summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2022-07-11 14:17:45 +0300
committerDmitry Gutov <dgutov@yandex.ru>2022-07-11 14:17:45 +0300
commitd4875e1235375feb8d67bad8b1a76e64445f3b1a (patch)
treef011f6df1cc03dfb724fdffae09886f6589c3adb
parent9c00d6c3f6f45755a20d093bbd821673fc7ac405 (diff)
parentb283e36cf1902eeb6d532077e1f46270aa1224e1 (diff)
downloademacs-scratch/etags-regen.tar.gz
Merge branch 'master' into scratch/etags-regenscratch/etags-regen
-rw-r--r--.dir-locals.el4
-rw-r--r--.gitignore1
-rw-r--r--CONTRIBUTE49
-rw-r--r--ChangeLog.32818
-rw-r--r--INSTALL50
-rw-r--r--Makefile.in6
-rw-r--r--admin/CPP-DEFINES31
-rw-r--r--admin/MAINTAINERS31
-rw-r--r--admin/admin.el156
-rw-r--r--admin/alloc-colors.c1
-rw-r--r--admin/authors.el214
-rw-r--r--admin/cus-test.el2
-rwxr-xr-xadmin/emake2
-rw-r--r--admin/gitmerge.el2
-rw-r--r--admin/grammars/Makefile.in5
-rw-r--r--admin/make-tarball.txt176
-rwxr-xr-xadmin/merge-gnulib14
-rw-r--r--admin/notes/emba13
-rw-r--r--admin/notes/multi-tty2
-rw-r--r--admin/notes/unicode26
-rw-r--r--admin/nt/dist-build/README-scripts2
-rwxr-xr-xadmin/nt/dist-build/build-zips.sh2
-rwxr-xr-xadmin/quick-install-emacs4
-rw-r--r--admin/unidata/IdnaMappingTable.txt8921
-rw-r--r--admin/unidata/Makefile.in24
-rw-r--r--admin/unidata/PropertyValueAliases.txt1615
-rw-r--r--admin/unidata/README16
-rw-r--r--admin/unidata/ScriptExtensions.txt628
-rw-r--r--admin/unidata/Scripts.txt2991
-rwxr-xr-xadmin/unidata/blocks.awk6
-rw-r--r--admin/unidata/confusables.txt9637
-rw-r--r--admin/unidata/unidata-gen.el232
-rwxr-xr-xadmin/upload-manuals5
-rwxr-xr-xautogen.sh2
-rwxr-xr-xbuild-aux/config.guess43
-rwxr-xr-xbuild-aux/config.sub8
-rwxr-xr-xbuild-aux/git-hooks/pre-commit4
-rwxr-xr-xbuild-aux/gitlog-to-changelog2
-rwxr-xr-xbuild-aux/update-copyright2
-rw-r--r--config.bat3
-rw-r--r--configure.ac1814
-rw-r--r--doc/emacs/ChangeLog.12
-rw-r--r--doc/emacs/abbrevs.texi5
-rw-r--r--doc/emacs/anti.texi4
-rw-r--r--doc/emacs/basic.texi24
-rw-r--r--doc/emacs/buffers.texi23
-rw-r--r--doc/emacs/building.texi29
-rw-r--r--doc/emacs/cmdargs.texi74
-rw-r--r--doc/emacs/custom.texi59
-rw-r--r--doc/emacs/dired.texi93
-rw-r--r--doc/emacs/display.texi99
-rw-r--r--doc/emacs/emacs.texi2
-rw-r--r--doc/emacs/files.texi86
-rw-r--r--doc/emacs/frames.texi69
-rw-r--r--doc/emacs/glossary.texi17
-rw-r--r--doc/emacs/haiku.texi22
-rw-r--r--doc/emacs/help.texi43
-rw-r--r--doc/emacs/killing.texi65
-rw-r--r--doc/emacs/kmacro.texi2
-rw-r--r--doc/emacs/macos.texi42
-rw-r--r--doc/emacs/maintaining.texi100
-rw-r--r--doc/emacs/mark.texi13
-rw-r--r--doc/emacs/mini.texi104
-rw-r--r--doc/emacs/misc.texi46
-rw-r--r--doc/emacs/mule.texi46
-rw-r--r--doc/emacs/package.texi27
-rw-r--r--doc/emacs/programs.texi18
-rw-r--r--doc/emacs/search.texi139
-rw-r--r--doc/emacs/sending.texi6
-rw-r--r--doc/emacs/text.texi23
-rw-r--r--doc/emacs/trouble.texi174
-rw-r--r--doc/emacs/vc1-xtra.texi2
-rw-r--r--doc/emacs/windows.texi12
-rw-r--r--doc/emacs/xresources.texi28
-rw-r--r--doc/lispintro/Makefile.in4
-rw-r--r--doc/lispintro/emacs-lisp-intro.texi7
-rw-r--r--doc/lispref/buffers.texi71
-rw-r--r--doc/lispref/commands.texi186
-rw-r--r--doc/lispref/compile.texi56
-rw-r--r--doc/lispref/control.texi21
-rw-r--r--doc/lispref/customize.texi16
-rw-r--r--doc/lispref/debugging.texi26
-rw-r--r--doc/lispref/display.texi325
-rw-r--r--doc/lispref/edebug.texi16
-rw-r--r--doc/lispref/elisp.texi6
-rw-r--r--doc/lispref/eval.texi2
-rw-r--r--doc/lispref/files.texi44
-rw-r--r--doc/lispref/frames.texi383
-rw-r--r--doc/lispref/functions.texi171
-rw-r--r--doc/lispref/hash.texi18
-rw-r--r--doc/lispref/help.texi21
-rw-r--r--doc/lispref/hooks.texi1
-rw-r--r--doc/lispref/internals.texi10
-rw-r--r--doc/lispref/intro.texi4
-rw-r--r--doc/lispref/keymaps.texi30
-rw-r--r--doc/lispref/lists.texi29
-rw-r--r--doc/lispref/loading.texi54
-rw-r--r--doc/lispref/minibuf.texi33
-rw-r--r--doc/lispref/modes.texi184
-rw-r--r--doc/lispref/nonascii.texi26
-rw-r--r--doc/lispref/objects.texi6
-rw-r--r--doc/lispref/os.texi349
-rw-r--r--doc/lispref/processes.texi134
-rw-r--r--doc/lispref/searching.texi37
-rw-r--r--doc/lispref/sequences.texi14
-rw-r--r--doc/lispref/streams.texi147
-rw-r--r--doc/lispref/strings.texi57
-rw-r--r--doc/lispref/symbols.texi83
-rw-r--r--doc/lispref/syntax.texi2
-rw-r--r--doc/lispref/text.texi200
-rw-r--r--doc/lispref/tips.texi30
-rw-r--r--doc/lispref/variables.texi107
-rw-r--r--doc/lispref/windows.texi156
-rw-r--r--doc/man/emacs.1.in6
-rw-r--r--doc/man/etags.16
-rw-r--r--doc/misc/Makefile.in9
-rw-r--r--doc/misc/auth.texi19
-rw-r--r--doc/misc/autotype.texi14
-rw-r--r--doc/misc/calc.texi6
-rw-r--r--doc/misc/cc-mode.texi26
-rw-r--r--doc/misc/cl.texi88
-rw-r--r--doc/misc/dbus.texi8
-rw-r--r--doc/misc/dired-x.texi64
-rw-r--r--doc/misc/ediff.texi3
-rw-r--r--doc/misc/efaq-w32.texi130
-rw-r--r--doc/misc/efaq.texi177
-rw-r--r--doc/misc/erc.texi211
-rw-r--r--doc/misc/ert.texi9
-rw-r--r--doc/misc/eshell.texi786
-rw-r--r--doc/misc/eudc.texi204
-rw-r--r--doc/misc/eww.texi12
-rw-r--r--doc/misc/flymake.texi3
-rw-r--r--doc/misc/gnus-faq.texi69
-rw-r--r--doc/misc/gnus.texi93
-rw-r--r--doc/misc/info.texi9
-rw-r--r--doc/misc/modus-themes.org1713
-rw-r--r--doc/misc/org.org10
-rw-r--r--doc/misc/rcirc.texi9
-rw-r--r--doc/misc/ses.texi38
-rw-r--r--doc/misc/texinfo.tex44
-rw-r--r--doc/misc/tramp.texi794
-rw-r--r--doc/misc/transient.texi2560
-rw-r--r--doc/misc/vtable.texi577
-rw-r--r--etc/AUTHORS276
-rw-r--r--etc/DEBUG13
-rw-r--r--etc/DEVEL.HUMOR16
-rw-r--r--etc/ERC-NEWS90
-rw-r--r--etc/HELLO43
-rw-r--r--etc/HISTORY2
-rw-r--r--etc/NEWS2134
-rw-r--r--etc/NEWS.28919
-rw-r--r--etc/ORG-NEWS6
-rw-r--r--etc/PROBLEMS241
-rw-r--r--etc/TODO45
-rw-r--r--etc/compilation.txt4
-rw-r--r--etc/e/eterm-colorbin1296 -> 1318 bytes
-rw-r--r--etc/e/eterm-color.ti5
-rw-r--r--etc/e/eterm-directbin1375 -> 1397 bytes
-rw-r--r--etc/enriched.txt12
-rw-r--r--etc/images/gnus/catchup.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/catchup.xpm33
-rw-r--r--etc/images/gnus/cu-exit.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/cu-exit.xpm31
-rw-r--r--etc/images/gnus/describe-group.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/describe-group.xpm32
-rw-r--r--etc/images/gnus/exit-gnus.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/exit-gnus.xpm33
-rw-r--r--etc/images/gnus/exit-summ.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/exit-summ.xpm30
-rw-r--r--etc/images/gnus/get-news.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/get-news.xpm31
-rw-r--r--etc/images/gnus/gnntg.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/gnntg.xpm31
-rw-r--r--etc/images/gnus/important.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/important.xpm32
-rw-r--r--etc/images/gnus/next-ur.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/next-ur.xpm35
-rw-r--r--etc/images/gnus/post.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/post.xpm35
-rw-r--r--etc/images/gnus/prev-ur.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/prev-ur.xpm35
-rw-r--r--etc/images/gnus/receipt.pbm3
-rw-r--r--etc/images/gnus/receipt.xpm32
-rw-r--r--etc/images/gnus/reply-wo.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/reply-wo.xpm31
-rw-r--r--etc/images/gnus/reply.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/reply.xpm31
-rw-r--r--etc/images/gnus/rot13.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/rot13.xpm128
-rw-r--r--etc/images/gnus/save-aif.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/save-aif.xpm33
-rw-r--r--etc/images/gnus/save-art.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/save-art.xpm32
-rw-r--r--etc/images/gnus/subscribe.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/subscribe.xpm32
-rw-r--r--etc/images/gnus/unimportant.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/unimportant.xpm32
-rw-r--r--etc/images/gnus/unsubscribe.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/unsubscribe.xpm32
-rw-r--r--etc/images/gnus/uu-decode.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/uu-decode.xpm36
-rw-r--r--etc/images/gnus/uu-post.pbmbin81 -> 0 bytes
-rw-r--r--etc/images/gnus/uu-post.xpm35
-rw-r--r--etc/images/tree-widget/default/nohandle-guide.pngbin0 -> 180 bytes
-rw-r--r--etc/images/tree-widget/default/nohandle-guide.xpm26
-rw-r--r--etc/images/tree-widget/folder/nohandle-guide.pngbin0 -> 178 bytes
-rw-r--r--etc/images/tree-widget/folder/nohandle-guide.xpm27
-rw-r--r--etc/publicsuffix.txt394
-rw-r--r--etc/refcards/Makefile7
-rw-r--r--etc/refcards/orgcard.tex2
-rw-r--r--etc/srecode/ede-autoconf.srt4
-rw-r--r--etc/themes/leuven-dark-theme.el1095
-rw-r--r--etc/themes/manoj-dark-theme.el4
-rw-r--r--etc/themes/modus-operandi-theme.el20
-rw-r--r--etc/themes/modus-themes.el2930
-rw-r--r--etc/themes/modus-vivendi-theme.el20
-rw-r--r--etc/tutorials/TUTORIAL.cn9
-rw-r--r--etc/tutorials/TUTORIAL.el_GR1267
-rw-r--r--etc/tutorials/TUTORIAL.it2
-rw-r--r--etc/tutorials/TUTORIAL.nl2
-rw-r--r--etc/tutorials/TUTORIAL.translators4
-rw-r--r--leim/Makefile.in19
-rw-r--r--lib-src/Makefile.in3
-rw-r--r--lib-src/be_resources.cc39
-rw-r--r--lib-src/ebrowse.c49
-rw-r--r--lib-src/emacsclient.c4
-rw-r--r--lib-src/etags.c62
-rw-r--r--lib-src/make-docfile.c3
-rw-r--r--lib-src/movemail.c1
-rw-r--r--lib-src/seccomp-filter.c7
-rw-r--r--lib/acl-errno-valid.c2
-rw-r--r--lib/acl-internal.c2
-rw-r--r--lib/acl-internal.h2
-rw-r--r--lib/acl.h2
-rw-r--r--lib/acl_entries.c2
-rw-r--r--lib/at-func.c2
-rw-r--r--lib/cdefs.h19
-rw-r--r--lib/close-stream.c2
-rw-r--r--lib/close-stream.h2
-rw-r--r--lib/copy-file-range.c34
-rw-r--r--lib/diffseq.h2
-rw-r--r--lib/dtoastr.c2
-rw-r--r--lib/dtotimespec.c2
-rw-r--r--lib/faccessat.c2
-rw-r--r--lib/fchmodat.c61
-rw-r--r--lib/fcntl.in.h4
-rw-r--r--lib/fdopendir.c2
-rw-r--r--lib/file-has-acl.c2
-rw-r--r--lib/filemode.c2
-rw-r--r--lib/filemode.h2
-rw-r--r--lib/filevercmp.c193
-rw-r--r--lib/filevercmp.h70
-rw-r--r--lib/fpending.c2
-rw-r--r--lib/fpending.h2
-rw-r--r--lib/fstatat.c2
-rw-r--r--lib/fsusage.c2
-rw-r--r--lib/fsusage.h2
-rw-r--r--lib/ftoastr.c2
-rw-r--r--lib/ftoastr.h2
-rw-r--r--lib/futimens.c2
-rw-r--r--lib/get-permissions.c2
-rw-r--r--lib/getloadavg.c2
-rw-r--r--lib/gettime.c2
-rw-r--r--lib/gnulib.mk.in435
-rw-r--r--lib/intprops.h8
-rw-r--r--lib/lchmod.c86
-rw-r--r--lib/libc-config.h11
-rw-r--r--lib/md5.h3
-rw-r--r--lib/memrchr.c2
-rw-r--r--lib/mini-gmp-gnulib.c5
-rw-r--r--lib/mini-gmp.c4
-rw-r--r--lib/mktime.c28
-rw-r--r--lib/nanosleep.c195
-rw-r--r--lib/nstrftime.c3
-rw-r--r--lib/openat-priv.h2
-rw-r--r--lib/openat-proc.c2
-rw-r--r--lib/openat.h4
-rw-r--r--lib/qcopy-acl.c2
-rw-r--r--lib/readlinkat.c2
-rw-r--r--lib/regcomp.c16
-rw-r--r--lib/regex_internal.c22
-rw-r--r--lib/regexec.c5
-rw-r--r--lib/save-cwd.h2
-rw-r--r--lib/set-permissions.c2
-rw-r--r--lib/sha1.h3
-rw-r--r--lib/sha256.h3
-rw-r--r--lib/sha512.h3
-rw-r--r--lib/sig2str.c2
-rw-r--r--lib/sig2str.h2
-rw-r--r--lib/stdlib.in.h4
-rw-r--r--lib/str-two-way.h4
-rw-r--r--lib/strftime.h2
-rw-r--r--lib/string.in.h106
-rw-r--r--lib/strtoimax.c2
-rw-r--r--lib/strtol.c2
-rw-r--r--lib/strtoll.c2
-rw-r--r--lib/symlink.c2
-rw-r--r--lib/sys_stat.in.h28
-rw-r--r--lib/time-internal.h2
-rw-r--r--lib/time_rz.c2
-rw-r--r--lib/timespec-add.c2
-rw-r--r--lib/timespec-sub.c2
-rw-r--r--lib/timespec.c2
-rw-r--r--lib/timespec.h2
-rw-r--r--lib/unistd.in.h16
-rw-r--r--lib/unlocked-io.h2
-rw-r--r--lib/utimens.c2
-rw-r--r--lib/utimens.h2
-rw-r--r--lib/utimensat.c2
-rw-r--r--lib/verify.h5
-rw-r--r--lib/vla.h2
-rw-r--r--lisp/Makefile.in139
-rw-r--r--lisp/abbrev.el306
-rw-r--r--lisp/align.el20
-rw-r--r--lisp/allout.el10
-rw-r--r--lisp/ansi-color.el35
-rw-r--r--lisp/apropos.el73
-rw-r--r--lisp/arc-mode.el8
-rw-r--r--lisp/array.el44
-rw-r--r--lisp/auth-source.el160
-rw-r--r--lisp/autoinsert.el21
-rw-r--r--lisp/autorevert.el2
-rw-r--r--lisp/avoid.el19
-rw-r--r--lisp/battery.el45
-rw-r--r--lisp/bindings.el37
-rw-r--r--lisp/bookmark.el245
-rw-r--r--lisp/bs.el108
-rw-r--r--lisp/buff-menu.el17
-rw-r--r--lisp/button.el80
-rw-r--r--lisp/calc/calc-embed.el3
-rw-r--r--lisp/calc/calc-misc.el62
-rw-r--r--lisp/calc/calc-prog.el4
-rw-r--r--lisp/calc/calc-yank.el20
-rw-r--r--lisp/calc/calc.el14
-rw-r--r--lisp/calendar/appt.el10
-rw-r--r--lisp/calendar/cal-hebrew.el11
-rw-r--r--lisp/calendar/calendar.el31
-rw-r--r--lisp/calendar/diary-lib.el23
-rw-r--r--lisp/calendar/holidays.el64
-rw-r--r--lisp/calendar/icalendar.el3
-rw-r--r--lisp/calendar/iso8601.el12
-rw-r--r--lisp/calendar/time-date.el81
-rw-r--r--lisp/calendar/timeclock.el2
-rw-r--r--lisp/cedet/data-debug.el16
-rw-r--r--lisp/cedet/ede/emacs.el2
-rw-r--r--lisp/cedet/ede/files.el2
-rw-r--r--lisp/cedet/ede/proj-elisp.el3
-rw-r--r--lisp/cedet/ede/project-am.el3
-rw-r--r--lisp/cedet/mode-local.el7
-rw-r--r--lisp/cedet/semantic.el4
-rw-r--r--lisp/cedet/semantic/bovine/grammar.el13
-rw-r--r--lisp/cedet/semantic/complete.el3
-rw-r--r--lisp/cedet/semantic/db-el.el4
-rw-r--r--lisp/cedet/semantic/db.el2
-rw-r--r--lisp/cedet/semantic/edit.el2
-rw-r--r--lisp/cedet/semantic/find.el2
-rw-r--r--lisp/cedet/semantic/fw.el35
-rw-r--r--lisp/cedet/semantic/grammar.el4
-rw-r--r--lisp/cedet/semantic/html.el12
-rw-r--r--lisp/cedet/semantic/imenu.el3
-rw-r--r--lisp/cedet/semantic/java.el39
-rw-r--r--lisp/cedet/semantic/lex-spp.el4
-rw-r--r--lisp/cedet/semantic/lex.el37
-rw-r--r--lisp/cedet/semantic/senator.el9
-rw-r--r--lisp/cedet/semantic/sort.el2
-rw-r--r--lisp/cedet/semantic/symref.el6
-rw-r--r--lisp/cedet/semantic/texi.el12
-rw-r--r--lisp/cedet/semantic/wisent/comp.el2
-rw-r--r--lisp/cedet/semantic/wisent/grammar.el11
-rw-r--r--lisp/cedet/srecode/texi.el2
-rw-r--r--lisp/chistory.el6
-rw-r--r--lisp/cmuscheme.el1
-rw-r--r--lisp/color.el6
-rw-r--r--lisp/comint.el108
-rw-r--r--lisp/composite.el19
-rw-r--r--lisp/cus-dep.el7
-rw-r--r--lisp/cus-edit.el144
-rw-r--r--lisp/cus-face.el150
-rw-r--r--lisp/cus-start.el14
-rw-r--r--lisp/custom.el66
-rw-r--r--lisp/dabbrev.el103
-rw-r--r--lisp/delsel.el24
-rw-r--r--lisp/descr-text.el5
-rw-r--r--lisp/desktop.el136
-rw-r--r--lisp/dframe.el4
-rw-r--r--lisp/dired-aux.el328
-rw-r--r--lisp/dired-x.el360
-rw-r--r--lisp/dired.el386
-rw-r--r--lisp/display-line-numbers.el78
-rw-r--r--lisp/dnd.el350
-rw-r--r--lisp/doc-view.el249
-rw-r--r--lisp/dos-fns.el16
-rw-r--r--lisp/ebuff-menu.el1
-rw-r--r--lisp/ecomplete.el40
-rw-r--r--lisp/edmacro.el91
-rw-r--r--lisp/ehelp.el5
-rw-r--r--lisp/elec-pair.el84
-rw-r--r--lisp/electric.el12
-rw-r--r--lisp/elide-head.el111
-rw-r--r--lisp/emacs-lisp/advice.el3
-rw-r--r--lisp/emacs-lisp/autoload.el379
-rw-r--r--lisp/emacs-lisp/backtrace.el117
-rw-r--r--lisp/emacs-lisp/benchmark.el6
-rw-r--r--lisp/emacs-lisp/bindat.el224
-rw-r--r--lisp/emacs-lisp/byte-opt.el396
-rw-r--r--lisp/emacs-lisp/byte-run.el294
-rw-r--r--lisp/emacs-lisp/bytecomp.el1108
-rw-r--r--lisp/emacs-lisp/cconv.el169
-rw-r--r--lisp/emacs-lisp/chart.el7
-rw-r--r--lisp/emacs-lisp/check-declare.el5
-rw-r--r--lisp/emacs-lisp/checkdoc.el113
-rw-r--r--lisp/emacs-lisp/cl-extra.el8
-rw-r--r--lisp/emacs-lisp/cl-generic.el345
-rw-r--r--lisp/emacs-lisp/cl-indent.el7
-rw-r--r--lisp/emacs-lisp/cl-lib.el10
-rw-r--r--lisp/emacs-lisp/cl-macs.el160
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el31
-rw-r--r--lisp/emacs-lisp/cl-print.el25
-rw-r--r--lisp/emacs-lisp/comp-cstr.el28
-rw-r--r--lisp/emacs-lisp/comp.el255
-rw-r--r--lisp/emacs-lisp/copyright.el8
-rw-r--r--lisp/emacs-lisp/crm.el56
-rw-r--r--lisp/emacs-lisp/debug-early.el97
-rw-r--r--lisp/emacs-lisp/debug.el131
-rw-r--r--lisp/emacs-lisp/derived.el2
-rw-r--r--lisp/emacs-lisp/easy-mmode.el91
-rw-r--r--lisp/emacs-lisp/edebug.el319
-rw-r--r--lisp/emacs-lisp/eieio-core.el132
-rw-r--r--lisp/emacs-lisp/eieio-custom.el8
-rw-r--r--lisp/emacs-lisp/eieio.el24
-rw-r--r--lisp/emacs-lisp/eldoc.el34
-rw-r--r--lisp/emacs-lisp/elp.el19
-rw-r--r--lisp/emacs-lisp/ert-x.el61
-rw-r--r--lisp/emacs-lisp/ert.el108
-rw-r--r--lisp/emacs-lisp/faceup.el2
-rw-r--r--lisp/emacs-lisp/find-func.el71
-rw-r--r--lisp/emacs-lisp/generate-lisp-file.el113
-rw-r--r--lisp/emacs-lisp/gv.el4
-rw-r--r--lisp/emacs-lisp/helper.el50
-rw-r--r--lisp/emacs-lisp/inline.el2
-rw-r--r--lisp/emacs-lisp/lisp-mnt.el6
-rw-r--r--lisp/emacs-lisp/lisp-mode.el294
-rw-r--r--lisp/emacs-lisp/lisp.el36
-rw-r--r--lisp/emacs-lisp/loaddefs-gen.el710
-rw-r--r--lisp/emacs-lisp/macroexp.el389
-rw-r--r--lisp/emacs-lisp/map-ynp.el10
-rw-r--r--lisp/emacs-lisp/map.el14
-rw-r--r--lisp/emacs-lisp/memory-report.el4
-rw-r--r--lisp/emacs-lisp/multisession.el21
-rw-r--r--lisp/emacs-lisp/nadvice.el228
-rw-r--r--lisp/emacs-lisp/oclosure.el562
-rw-r--r--lisp/emacs-lisp/package.el237
-rw-r--r--lisp/emacs-lisp/pcase.el6
-rw-r--r--lisp/emacs-lisp/pp.el13
-rw-r--r--lisp/emacs-lisp/range.el467
-rw-r--r--lisp/emacs-lisp/re-builder.el65
-rw-r--r--lisp/emacs-lisp/rmc.el48
-rw-r--r--lisp/emacs-lisp/rx.el9
-rw-r--r--lisp/emacs-lisp/seq.el40
-rw-r--r--lisp/emacs-lisp/shadow.el5
-rw-r--r--lisp/emacs-lisp/shortdoc.el132
-rw-r--r--lisp/emacs-lisp/shorthands.el3
-rw-r--r--lisp/emacs-lisp/smie.el12
-rw-r--r--lisp/emacs-lisp/subr-x.el344
-rw-r--r--lisp/emacs-lisp/syntax.el118
-rw-r--r--lisp/emacs-lisp/tabulated-list.el150
-rw-r--r--lisp/emacs-lisp/testcover.el3
-rw-r--r--lisp/emacs-lisp/text-property-search.el3
-rw-r--r--lisp/emacs-lisp/timer-list.el15
-rw-r--r--lisp/emacs-lisp/trace.el20
-rw-r--r--lisp/emacs-lisp/vtable.el976
-rw-r--r--lisp/emacs-lock.el11
-rw-r--r--lisp/emulation/cua-rect.el2
-rw-r--r--lisp/emulation/viper-cmd.el38
-rw-r--r--lisp/emulation/viper-macs.el8
-rw-r--r--lisp/emulation/viper-mous.el4
-rw-r--r--lisp/emulation/viper.el10
-rw-r--r--lisp/env.el2
-rw-r--r--lisp/epa-ks.el2
-rw-r--r--lisp/epa-mail.el28
-rw-r--r--lisp/erc/erc-autoaway.el2
-rw-r--r--lisp/erc/erc-backend.el257
-rw-r--r--lisp/erc/erc-button.el24
-rw-r--r--lisp/erc/erc-capab.el6
-rw-r--r--lisp/erc/erc-compat.el2
-rw-r--r--lisp/erc/erc-dcc.el143
-rw-r--r--lisp/erc/erc-desktop-notifications.el2
-rw-r--r--lisp/erc/erc-ezbounce.el2
-rw-r--r--lisp/erc/erc-fill.el2
-rw-r--r--lisp/erc/erc-goodies.el2
-rw-r--r--lisp/erc/erc-ibuffer.el2
-rw-r--r--lisp/erc/erc-identd.el2
-rw-r--r--lisp/erc/erc-imenu.el2
-rw-r--r--lisp/erc/erc-join.el123
-rw-r--r--lisp/erc/erc-lang.el14
-rw-r--r--lisp/erc/erc-list.el2
-rw-r--r--lisp/erc/erc-log.el2
-rw-r--r--lisp/erc/erc-match.el2
-rw-r--r--lisp/erc/erc-menu.el2
-rw-r--r--lisp/erc/erc-netsplit.el2
-rw-r--r--lisp/erc/erc-networks.el698
-rw-r--r--lisp/erc/erc-notify.el2
-rw-r--r--lisp/erc/erc-page.el2
-rw-r--r--lisp/erc/erc-pcomplete.el2
-rw-r--r--lisp/erc/erc-replace.el2
-rw-r--r--lisp/erc/erc-ring.el2
-rw-r--r--lisp/erc/erc-services.el58
-rw-r--r--lisp/erc/erc-sound.el2
-rw-r--r--lisp/erc/erc-speedbar.el2
-rw-r--r--lisp/erc/erc-spelling.el2
-rw-r--r--lisp/erc/erc-stamp.el2
-rw-r--r--lisp/erc/erc-status-sidebar.el2
-rw-r--r--lisp/erc/erc-track.el18
-rw-r--r--lisp/erc/erc-truncate.el2
-rw-r--r--lisp/erc/erc-xdcc.el2
-rw-r--r--lisp/erc/erc.el1029
-rw-r--r--lisp/eshell/em-basic.el93
-rw-r--r--lisp/eshell/em-cmpl.el36
-rw-r--r--lisp/eshell/em-dirs.el6
-rw-r--r--lisp/eshell/em-elecslash.el120
-rw-r--r--lisp/eshell/em-extpipe.el204
-rw-r--r--lisp/eshell/em-glob.el233
-rw-r--r--lisp/eshell/em-hist.el4
-rw-r--r--lisp/eshell/em-ls.el17
-rw-r--r--lisp/eshell/em-pred.el341
-rw-r--r--lisp/eshell/em-rebind.el2
-rw-r--r--lisp/eshell/em-script.el18
-rw-r--r--lisp/eshell/em-term.el12
-rw-r--r--lisp/eshell/em-tramp.el118
-rw-r--r--lisp/eshell/esh-arg.el90
-rw-r--r--lisp/eshell/esh-cmd.el246
-rw-r--r--lisp/eshell/esh-ext.el2
-rw-r--r--lisp/eshell/esh-io.el47
-rw-r--r--lisp/eshell/esh-mode.el38
-rw-r--r--lisp/eshell/esh-module.el1
-rw-r--r--lisp/eshell/esh-opt.el109
-rw-r--r--lisp/eshell/esh-proc.el58
-rw-r--r--lisp/eshell/esh-util.el146
-rw-r--r--lisp/eshell/esh-var.el208
-rw-r--r--lisp/eshell/eshell.el6
-rw-r--r--lisp/face-remap.el152
-rw-r--r--lisp/faces.el198
-rw-r--r--lisp/ffap.el92
-rw-r--r--lisp/files-x.el120
-rw-r--r--lisp/files.el622
-rw-r--r--lisp/filesets.el24
-rw-r--r--lisp/find-dired.el93
-rw-r--r--lisp/find-lisp.el4
-rw-r--r--lisp/finder.el43
-rw-r--r--lisp/foldout.el2
-rw-r--r--lisp/follow.el2
-rw-r--r--lisp/font-core.el3
-rw-r--r--lisp/font-lock.el202
-rw-r--r--lisp/forms.el2
-rw-r--r--lisp/frame.el207
-rw-r--r--lisp/frameset.el48
-rw-r--r--lisp/fringe.el10
-rw-r--r--lisp/generic-x.el4
-rw-r--r--lisp/gnus/deuglify.el1
-rw-r--r--lisp/gnus/gmm-utils.el43
-rw-r--r--lisp/gnus/gnus-agent.el45
-rw-r--r--lisp/gnus/gnus-art.el83
-rw-r--r--lisp/gnus/gnus-cloud.el3
-rw-r--r--lisp/gnus/gnus-cus.el2
-rw-r--r--lisp/gnus/gnus-draft.el2
-rw-r--r--lisp/gnus/gnus-eform.el2
-rw-r--r--lisp/gnus/gnus-group.el198
-rw-r--r--lisp/gnus/gnus-html.el11
-rw-r--r--lisp/gnus/gnus-icalendar.el7
-rw-r--r--lisp/gnus/gnus-int.el2
-rw-r--r--lisp/gnus/gnus-kill.el2
-rw-r--r--lisp/gnus/gnus-logic.el4
-rw-r--r--lisp/gnus/gnus-msg.el52
-rw-r--r--lisp/gnus/gnus-range.el459
-rw-r--r--lisp/gnus/gnus-registry.el113
-rw-r--r--lisp/gnus/gnus-salt.el4
-rw-r--r--lisp/gnus/gnus-search.el308
-rw-r--r--lisp/gnus/gnus-start.el49
-rw-r--r--lisp/gnus/gnus-sum.el241
-rw-r--r--lisp/gnus/gnus-topic.el13
-rw-r--r--lisp/gnus/gnus-util.el13
-rw-r--r--lisp/gnus/gnus.el39
-rw-r--r--lisp/gnus/mail-source.el40
-rw-r--r--lisp/gnus/message.el191
-rw-r--r--lisp/gnus/mm-bodies.el32
-rw-r--r--lisp/gnus/mm-encode.el2
-rw-r--r--lisp/gnus/mm-util.el3
-rw-r--r--lisp/gnus/mm-uu.el2
-rw-r--r--lisp/gnus/mm-view.el24
-rw-r--r--lisp/gnus/mml.el3
-rw-r--r--lisp/gnus/nnheader.el8
-rw-r--r--lisp/gnus/nnimap.el62
-rw-r--r--lisp/gnus/nnmail.el4
-rw-r--r--lisp/gnus/nnmaildir.el16
-rw-r--r--lisp/gnus/nnmairix.el4
-rw-r--r--lisp/gnus/nnmbox.el6
-rw-r--r--lisp/gnus/nnml.el19
-rw-r--r--lisp/gnus/nnnil.el2
-rw-r--r--lisp/gnus/nnregistry.el4
-rw-r--r--lisp/gnus/nnrss.el3
-rw-r--r--lisp/gnus/nnselect.el352
-rw-r--r--lisp/gnus/nntp.el15
-rw-r--r--lisp/gnus/nnvirtual.el13
-rw-r--r--lisp/gnus/smime.el11
-rw-r--r--lisp/gnus/spam-stat.el2
-rw-r--r--lisp/gnus/spam.el2
-rw-r--r--lisp/help-at-pt.el36
-rw-r--r--lisp/help-fns.el539
-rw-r--r--lisp/help-mode.el166
-rw-r--r--lisp/help.el297
-rw-r--r--lisp/hfy-cmap.el4
-rw-r--r--lisp/hi-lock.el94
-rw-r--r--lisp/hilit-chg.el2
-rw-r--r--lisp/hl-line.el18
-rw-r--r--lisp/htmlfontify.el18
-rw-r--r--lisp/ibuf-ext.el4
-rw-r--r--lisp/ibuf-macs.el13
-rw-r--r--lisp/ibuffer.el399
-rw-r--r--lisp/icomplete.el80
-rw-r--r--lisp/ido.el59
-rw-r--r--lisp/iimage.el11
-rw-r--r--lisp/image-dired.el29
-rw-r--r--lisp/image-mode.el92
-rw-r--r--lisp/image.el134
-rw-r--r--lisp/image/exif.el10
-rw-r--r--lisp/image/gravatar.el2
-rw-r--r--lisp/image/image-converter.el87
-rw-r--r--lisp/imenu.el15
-rw-r--r--lisp/indent.el62
-rw-r--r--lisp/info-look.el52
-rw-r--r--lisp/info.el259
-rw-r--r--lisp/informat.el2
-rw-r--r--lisp/international/ccl.el2
-rw-r--r--lisp/international/characters.el26
-rw-r--r--lisp/international/emoji.el143
-rw-r--r--lisp/international/fontset.el86
-rw-r--r--lisp/international/iso-transl.el81
-rw-r--r--lisp/international/ja-dic-cnv.el44
-rw-r--r--lisp/international/latin1-disp.el4860
-rw-r--r--lisp/international/mule-cmds.el4
-rw-r--r--lisp/international/mule.el29
-rw-r--r--lisp/international/quail.el4
-rw-r--r--lisp/international/textsec-check.el78
-rw-r--r--lisp/international/textsec.el467
-rw-r--r--lisp/international/titdic-cnv.el28
-rw-r--r--lisp/isearch.el443
-rw-r--r--lisp/jit-lock.el28
-rw-r--r--lisp/jsonrpc.el6
-rw-r--r--lisp/keymap.el115
-rw-r--r--lisp/kmacro.el294
-rw-r--r--lisp/language/greek.el4
-rw-r--r--lisp/language/ind-util.el37
-rw-r--r--lisp/language/indian.el436
-rw-r--r--lisp/language/indonesian.el197
-rw-r--r--lisp/language/misc-lang.el54
-rw-r--r--lisp/language/philippine.el96
-rw-r--r--lisp/language/thai-util.el16
-rw-r--r--lisp/language/thai.el37
-rw-r--r--lisp/ldefs-boot.el15417
-rw-r--r--lisp/leim/quail/compose.el6
-rw-r--r--lisp/leim/quail/emoji.el2003
-rw-r--r--lisp/leim/quail/indian.el1357
-rw-r--r--lisp/leim/quail/indonesian.el557
-rw-r--r--lisp/leim/quail/ipa.el2
-rw-r--r--lisp/leim/quail/latin-post.el75
-rw-r--r--lisp/leim/quail/latin-pre.el42
-rw-r--r--lisp/leim/quail/misc-lang.el1184
-rw-r--r--lisp/leim/quail/persian.el90
-rw-r--r--lisp/leim/quail/philippine.el152
-rw-r--r--lisp/leim/quail/symbol-ksc.el4
-rw-r--r--lisp/linum.el3
-rw-r--r--lisp/loadhist.el54
-rw-r--r--lisp/loadup.el16
-rw-r--r--lisp/locate.el6
-rw-r--r--lisp/longlines.el (renamed from lisp/obsolete/longlines.el)133
-rw-r--r--lisp/lpr.el2
-rw-r--r--lisp/ls-lisp.el24
-rw-r--r--lisp/macros.el96
-rw-r--r--lisp/mail/emacsbug.el65
-rw-r--r--lisp/mail/feedmail.el7
-rw-r--r--lisp/mail/footnote.el6
-rw-r--r--lisp/mail/hashcash.el4
-rw-r--r--lisp/mail/ietf-drums-date.el274
-rw-r--r--lisp/mail/ietf-drums.el52
-rw-r--r--lisp/mail/mail-extr.el115
-rw-r--r--lisp/mail/mail-hist.el2
-rw-r--r--lisp/mail/mail-parse.el3
-rw-r--r--lisp/mail/mail-utils.el11
-rw-r--r--lisp/mail/mailalias.el29
-rw-r--r--lisp/mail/rfc2047.el2
-rw-r--r--lisp/mail/rmail.el28
-rw-r--r--lisp/mail/rmailmm.el17
-rw-r--r--lisp/mail/rmailsum.el2
-rw-r--r--lisp/mail/sendmail.el48
-rw-r--r--lisp/mail/smtpmail.el12
-rw-r--r--lisp/mail/undigest.el50
-rw-r--r--lisp/mail/unrmail.el2
-rw-r--r--lisp/man.el28
-rw-r--r--lisp/menu-bar.el168
-rw-r--r--lisp/mh-e/mh-funcs.el6
-rw-r--r--lisp/mh-e/mh-limit.el6
-rw-r--r--lisp/mh-e/mh-mime.el12
-rw-r--r--lisp/midnight.el4
-rw-r--r--lisp/minibuffer.el488
-rw-r--r--lisp/misc.el37
-rw-r--r--lisp/mouse.el864
-rw-r--r--lisp/msb.el9
-rw-r--r--lisp/mwheel.el52
-rw-r--r--lisp/net/ange-ftp.el7
-rw-r--r--lisp/net/browse-url.el218
-rw-r--r--lisp/net/dbus.el8
-rw-r--r--lisp/net/dictionary-connection.el8
-rw-r--r--lisp/net/dictionary.el64
-rw-r--r--lisp/net/dig.el39
-rw-r--r--lisp/net/eudc-bob.el32
-rw-r--r--lisp/net/eudc-capf.el133
-rw-r--r--lisp/net/eudc-hotlist.el16
-rw-r--r--lisp/net/eudc-vars.el89
-rw-r--r--lisp/net/eudc.el308
-rw-r--r--lisp/net/eudcb-bbdb.el2
-rw-r--r--lisp/net/eudcb-ldap.el41
-rw-r--r--lisp/net/eww.el80
-rw-r--r--lisp/net/ldap.el12
-rw-r--r--lisp/net/mailcap.el90
-rw-r--r--lisp/net/mairix.el29
-rw-r--r--lisp/net/net-utils.el116
-rw-r--r--lisp/net/newst-backend.el43
-rw-r--r--lisp/net/newst-plainview.el17
-rw-r--r--lisp/net/newst-reader.el10
-rw-r--r--lisp/net/newst-treeview.el98
-rw-r--r--lisp/net/pop3.el4
-rw-r--r--lisp/net/quickurl.el24
-rw-r--r--lisp/net/rcirc.el171
-rw-r--r--lisp/net/rlogin.el25
-rw-r--r--lisp/net/secrets.el15
-rw-r--r--lisp/net/shr.el105
-rw-r--r--lisp/net/sieve-manage.el8
-rw-r--r--lisp/net/sieve-mode.el12
-rw-r--r--lisp/net/sieve.el52
-rw-r--r--lisp/net/snmp-mode.el14
-rw-r--r--lisp/net/soap-client.el9
-rw-r--r--lisp/net/socks.el9
-rw-r--r--lisp/net/telnet.el18
-rw-r--r--lisp/net/tramp-adb.el313
-rw-r--r--lisp/net/tramp-archive.el40
-rw-r--r--lisp/net/tramp-cache.el14
-rw-r--r--lisp/net/tramp-cmds.el6
-rw-r--r--lisp/net/tramp-compat.el21
-rw-r--r--lisp/net/tramp-crypt.el15
-rw-r--r--lisp/net/tramp-ftp.el17
-rw-r--r--lisp/net/tramp-fuse.el47
-rw-r--r--lisp/net/tramp-gvfs.el235
-rw-r--r--lisp/net/tramp-integration.el247
-rw-r--r--lisp/net/tramp-rclone.el9
-rw-r--r--lisp/net/tramp-sh.el1348
-rw-r--r--lisp/net/tramp-smb.el549
-rw-r--r--lisp/net/tramp-sshfs.el166
-rw-r--r--lisp/net/tramp-sudoedit.el87
-rw-r--r--lisp/net/tramp.el915
-rw-r--r--lisp/net/trampver.el10
-rw-r--r--lisp/newcomment.el30
-rw-r--r--lisp/notifications.el2
-rw-r--r--lisp/nxml/nxml-mode.el51
-rw-r--r--lisp/nxml/nxml-outln.el54
-rw-r--r--lisp/nxml/nxml-parse.el2
-rw-r--r--lisp/nxml/rng-valid.el4
-rw-r--r--lisp/obsolete/abbrevlist.el56
-rw-r--r--lisp/obsolete/assoc.el140
-rw-r--r--lisp/obsolete/autoarg.el (renamed from lisp/autoarg.el)1
-rw-r--r--lisp/obsolete/complete.el1122
-rw-r--r--lisp/obsolete/cust-print.el674
-rw-r--r--lisp/obsolete/eieio-compat.el16
-rw-r--r--lisp/obsolete/erc-hecomplete.el218
-rw-r--r--lisp/obsolete/gs.el2
-rw-r--r--lisp/obsolete/info-edit.el1
-rw-r--r--lisp/obsolete/iswitchb.el3
-rw-r--r--lisp/obsolete/mailpost.el101
-rw-r--r--lisp/obsolete/mouse-sel.el731
-rw-r--r--lisp/obsolete/old-emacs-lock.el102
-rw-r--r--lisp/obsolete/patcomp.el24
-rw-r--r--lisp/obsolete/pc-mode.el56
-rw-r--r--lisp/obsolete/pc-select.el410
-rw-r--r--lisp/obsolete/s-region.el123
-rw-r--r--lisp/obsolete/sregex.el605
-rw-r--r--lisp/obsolete/starttls.el3
-rw-r--r--lisp/obsolete/uce.el (renamed from lisp/mail/uce.el)1
-rw-r--r--lisp/obsolete/vc-mtn.el (renamed from lisp/vc/vc-mtn.el)1
-rw-r--r--lisp/obsolete/vt-control.el (renamed from lisp/vt-control.el)1
-rw-r--r--lisp/obsolete/vt100-led.el (renamed from lisp/vt100-led.el)1
-rw-r--r--lisp/org/ob-comint.el2
-rw-r--r--lisp/org/ob-core.el2
-rw-r--r--lisp/org/ob-gnuplot.el25
-rw-r--r--lisp/org/ob-julia.el8
-rw-r--r--lisp/org/ob-lua.el2
-rw-r--r--lisp/org/ob-table.el2
-rw-r--r--lisp/org/ob-tangle.el2
-rw-r--r--lisp/org/oc-basic.el71
-rw-r--r--lisp/org/oc-biblatex.el7
-rw-r--r--lisp/org/oc.el25
-rw-r--r--lisp/org/ol-bibtex.el8
-rw-r--r--lisp/org/ol-doi.el2
-rw-r--r--lisp/org/ol-eww.el2
-rw-r--r--lisp/org/ol-w3m.el2
-rw-r--r--lisp/org/ol.el12
-rw-r--r--lisp/org/org-agenda.el32
-rw-r--r--lisp/org/org-capture.el3
-rw-r--r--lisp/org/org-clock.el15
-rw-r--r--lisp/org/org-colview.el2
-rw-r--r--lisp/org/org-compat.el39
-rw-r--r--lisp/org/org-element.el27
-rw-r--r--lisp/org/org-faces.el20
-rw-r--r--lisp/org/org-feed.el2
-rw-r--r--lisp/org/org-lint.el8
-rw-r--r--lisp/org/org-list.el2
-rw-r--r--lisp/org/org-macro.el2
-rw-r--r--lisp/org/org-macs.el12
-rw-r--r--lisp/org/org-mouse.el4
-rw-r--r--lisp/org/org-plot.el2
-rw-r--r--lisp/org/org-refile.el10
-rw-r--r--lisp/org/org-table.el8
-rw-r--r--lisp/org/org-version.el4
-rw-r--r--lisp/org/org.el71
-rw-r--r--lisp/org/ox-ascii.el6
-rw-r--r--lisp/org/ox-html.el4
-rw-r--r--lisp/org/ox-publish.el2
-rw-r--r--lisp/org/ox.el159
-rw-r--r--lisp/outline.el302
-rw-r--r--lisp/paren.el198
-rw-r--r--lisp/pcmpl-gnu.el2
-rw-r--r--lisp/pcomplete.el61
-rw-r--r--lisp/pgtk-dnd.el396
-rw-r--r--lisp/pixel-scroll.el193
-rw-r--r--lisp/play/decipher.el13
-rw-r--r--lisp/play/dunnet.el2
-rw-r--r--lisp/play/gamegrid.el11
-rw-r--r--lisp/play/handwrite.el71
-rw-r--r--lisp/play/morse.el24
-rw-r--r--lisp/play/spook.el2
-rw-r--r--lisp/play/tetris.el35
-rw-r--r--lisp/plstore.el1
-rw-r--r--lisp/proced.el47
-rw-r--r--lisp/profiler.el2
-rw-r--r--lisp/progmodes/antlr-mode.el1
-rw-r--r--lisp/progmodes/asm-mode.el30
-rw-r--r--lisp/progmodes/bat-mode.el6
-rw-r--r--lisp/progmodes/bug-reference.el10
-rw-r--r--lisp/progmodes/cc-align.el120
-rw-r--r--lisp/progmodes/cc-awk.el118
-rw-r--r--lisp/progmodes/cc-cmds.el2214
-rw-r--r--lisp/progmodes/cc-defs.el22
-rw-r--r--lisp/progmodes/cc-engine.el26
-rw-r--r--lisp/progmodes/cc-fonts.el33
-rw-r--r--lisp/progmodes/cc-guess.el13
-rw-r--r--lisp/progmodes/cc-langs.el8
-rw-r--r--lisp/progmodes/cc-mode.el549
-rw-r--r--lisp/progmodes/cc-styles.el1
-rw-r--r--lisp/progmodes/cfengine.el17
-rw-r--r--lisp/progmodes/compile.el313
-rw-r--r--lisp/progmodes/cperl-mode.el46
-rw-r--r--lisp/progmodes/cwarn.el3
-rw-r--r--lisp/progmodes/ebrowse.el9
-rw-r--r--lisp/progmodes/elisp-mode.el177
-rw-r--r--lisp/progmodes/erts-mode.el16
-rw-r--r--lisp/progmodes/etags.el8
-rw-r--r--lisp/progmodes/executable.el13
-rw-r--r--lisp/progmodes/f90.el10
-rw-r--r--lisp/progmodes/flymake-proc.el2
-rw-r--r--lisp/progmodes/flymake.el26
-rw-r--r--lisp/progmodes/fortran.el1
-rw-r--r--lisp/progmodes/gdb-mi.el175
-rw-r--r--lisp/progmodes/grep.el161
-rw-r--r--lisp/progmodes/gud.el59
-rw-r--r--lisp/progmodes/hideif.el2
-rw-r--r--lisp/progmodes/icon.el21
-rw-r--r--lisp/progmodes/idlw-shell.el4
-rw-r--r--lisp/progmodes/idlwave.el10
-rw-r--r--lisp/progmodes/js.el10
-rw-r--r--lisp/progmodes/m4-mode.el12
-rw-r--r--lisp/progmodes/make-mode.el1
-rw-r--r--lisp/progmodes/meta-mode.el44
-rw-r--r--lisp/progmodes/mixal-mode.el17
-rw-r--r--lisp/progmodes/modula2.el5
-rw-r--r--lisp/progmodes/octave.el7
-rw-r--r--lisp/progmodes/opascal.el2
-rw-r--r--lisp/progmodes/pascal.el21
-rw-r--r--lisp/progmodes/project.el178
-rw-r--r--lisp/progmodes/prolog.el13
-rw-r--r--lisp/progmodes/python.el483
-rw-r--r--lisp/progmodes/ruby-mode.el45
-rw-r--r--lisp/progmodes/scheme.el104
-rw-r--r--lisp/progmodes/sh-script.el104
-rw-r--r--lisp/progmodes/sql.el187
-rw-r--r--lisp/progmodes/subword.el4
-rw-r--r--lisp/progmodes/tcl.el10
-rw-r--r--lisp/progmodes/verilog-mode.el8
-rw-r--r--lisp/progmodes/vhdl-mode.el60
-rw-r--r--lisp/progmodes/which-func.el7
-rw-r--r--lisp/progmodes/xref.el147
-rw-r--r--lisp/ps-print.el2
-rw-r--r--lisp/recentf.el148
-rw-r--r--lisp/rect.el27
-rw-r--r--lisp/repeat.el46
-rw-r--r--lisp/replace.el236
-rw-r--r--lisp/ruler-mode.el70
-rw-r--r--lisp/savehist.el43
-rw-r--r--lisp/saveplace.el14
-rw-r--r--lisp/scroll-bar.el7
-rw-r--r--lisp/scroll-lock.el18
-rw-r--r--lisp/select.el405
-rw-r--r--lisp/server.el8
-rw-r--r--lisp/ses.el115
-rw-r--r--lisp/shell.el289
-rw-r--r--lisp/simple.el1309
-rw-r--r--lisp/so-long.el56
-rw-r--r--lisp/sort.el48
-rw-r--r--lisp/speedbar.el31
-rw-r--r--lisp/sqlite-mode.el15
-rw-r--r--lisp/startup.el228
-rw-r--r--lisp/strokes.el8
-rw-r--r--lisp/subr.el659
-rw-r--r--lisp/tab-bar.el70
-rw-r--r--lisp/tab-line.el16
-rw-r--r--lisp/term.el151
-rw-r--r--lisp/term/common-win.el38
-rw-r--r--lisp/term/haiku-win.el406
-rw-r--r--lisp/term/linux.el4
-rw-r--r--lisp/term/ns-win.el127
-rw-r--r--lisp/term/pc-win.el8
-rw-r--r--lisp/term/pgtk-win.el222
-rw-r--r--lisp/term/w32-win.el2
-rw-r--r--lisp/term/x-win.el132
-rw-r--r--lisp/term/xterm.el2
-rw-r--r--lisp/textmodes/artist.el196
-rw-r--r--lisp/textmodes/bibtex.el58
-rw-r--r--lisp/textmodes/css-mode.el109
-rw-r--r--lisp/textmodes/dns-mode.el8
-rw-r--r--lisp/textmodes/emacs-news-mode.el269
-rw-r--r--lisp/textmodes/enriched.el24
-rw-r--r--lisp/textmodes/fill.el205
-rw-r--r--lisp/textmodes/flyspell.el7
-rw-r--r--lisp/textmodes/ispell.el64
-rw-r--r--lisp/textmodes/page-ext.el15
-rw-r--r--lisp/textmodes/page.el17
-rw-r--r--lisp/textmodes/paragraphs.el48
-rw-r--r--lisp/textmodes/pixel-fill.el4
-rw-r--r--lisp/textmodes/reftex-cite.el6
-rw-r--r--lisp/textmodes/reftex-global.el10
-rw-r--r--lisp/textmodes/reftex-index.el13
-rw-r--r--lisp/textmodes/reftex-parse.el17
-rw-r--r--lisp/textmodes/reftex-sel.el4
-rw-r--r--lisp/textmodes/reftex-toc.el43
-rw-r--r--lisp/textmodes/reftex-vars.el2
-rw-r--r--lisp/textmodes/reftex.el3
-rw-r--r--lisp/textmodes/remember.el5
-rw-r--r--lisp/textmodes/rst.el163
-rw-r--r--lisp/textmodes/sgml-mode.el52
-rw-r--r--lisp/textmodes/string-edit.el136
-rw-r--r--lisp/textmodes/table.el17
-rw-r--r--lisp/textmodes/tex-mode.el181
-rw-r--r--lisp/textmodes/texinfo.el78
-rw-r--r--lisp/textmodes/texnfo-upd.el2
-rw-r--r--lisp/textmodes/tildify.el5
-rw-r--r--lisp/textmodes/word-wrap-mode.el80
-rw-r--r--lisp/thingatpt.el11
-rw-r--r--lisp/thumbs.el42
-rw-r--r--lisp/time.el4
-rw-r--r--lisp/tool-bar.el27
-rw-r--r--lisp/tooltip.el71
-rw-r--r--lisp/transient.el14
-rw-r--r--lisp/tree-widget.el14
-rw-r--r--lisp/tutorial.el12
-rw-r--r--lisp/type-break.el8
-rw-r--r--lisp/uniquify.el1
-rw-r--r--lisp/url/url-auth.el30
-rw-r--r--lisp/url/url-cache.el2
-rw-r--r--lisp/url/url-cookie.el18
-rw-r--r--lisp/url/url-dired.el10
-rw-r--r--lisp/url/url-file.el30
-rw-r--r--lisp/url/url-history.el2
-rw-r--r--lisp/url/url-http.el208
-rw-r--r--lisp/url/url-queue.el19
-rw-r--r--lisp/url/url-tramp.el50
-rw-r--r--lisp/url/url-util.el7
-rw-r--r--lisp/url/url-vars.el26
-rw-r--r--lisp/url/url.el2
-rw-r--r--lisp/userlock.el2
-rw-r--r--lisp/vc/add-log.el18
-rw-r--r--lisp/vc/compare-w.el5
-rw-r--r--lisp/vc/diff-mode.el189
-rw-r--r--lisp/vc/diff.el16
-rw-r--r--lisp/vc/ediff-diff.el5
-rw-r--r--lisp/vc/ediff-init.el10
-rw-r--r--lisp/vc/ediff-merg.el2
-rw-r--r--lisp/vc/ediff-mult.el6
-rw-r--r--lisp/vc/ediff-util.el8
-rw-r--r--lisp/vc/ediff-wind.el29
-rw-r--r--lisp/vc/emerge.el6
-rw-r--r--lisp/vc/log-edit.el12
-rw-r--r--lisp/vc/log-view.el16
-rw-r--r--lisp/vc/pcvs-info.el8
-rw-r--r--lisp/vc/smerge-mode.el7
-rw-r--r--lisp/vc/vc-annotate.el2
-rw-r--r--lisp/vc/vc-bzr.el2
-rw-r--r--lisp/vc/vc-cvs.el11
-rw-r--r--lisp/vc/vc-dav.el4
-rw-r--r--lisp/vc/vc-dir.el35
-rw-r--r--lisp/vc/vc-git.el4
-rw-r--r--lisp/vc/vc-hooks.el23
-rw-r--r--lisp/vc/vc-rcs.el19
-rw-r--r--lisp/vc/vc-sccs.el11
-rw-r--r--lisp/vc/vc-src.el14
-rw-r--r--lisp/vc/vc-svn.el6
-rw-r--r--lisp/vc/vc.el87
-rw-r--r--lisp/vcursor.el67
-rw-r--r--lisp/version.el9
-rw-r--r--lisp/view.el70
-rw-r--r--lisp/w32-fns.el21
-rw-r--r--lisp/wdired.el51
-rw-r--r--lisp/whitespace.el341
-rw-r--r--lisp/wid-edit.el7
-rw-r--r--lisp/widget.el1
-rw-r--r--lisp/windmove.el2
-rw-r--r--lisp/window.el408
-rw-r--r--lisp/winner.el6
-rw-r--r--lisp/woman.el21
-rw-r--r--lisp/x-dnd.el1333
-rw-r--r--lisp/xdg.el13
-rw-r--r--lisp/xwidget.el5
-rw-r--r--lisp/yank-media.el44
-rw-r--r--lwlib/lwlib-Xm.c82
-rw-r--r--lwlib/lwlib.c12
-rw-r--r--lwlib/xlwmenu.c33
-rw-r--r--m4/copy-file-range.m425
-rw-r--r--m4/extern-inline.m419
-rw-r--r--m4/fchmodat.m44
-rw-r--r--m4/gnulib-common.m4103
-rw-r--r--m4/gnulib-comp.m4319
-rw-r--r--m4/lchmod.m46
-rw-r--r--m4/libgmp.m46
-rw-r--r--m4/manywarnings.m42
-rw-r--r--m4/mktime.m429
-rw-r--r--m4/nanosleep.m4139
-rw-r--r--m4/stdio_h.m429
-rw-r--r--m4/sys_stat_h.m46
-rw-r--r--m4/unistd_h.m41
-rwxr-xr-xmake-dist4
-rw-r--r--msdos/sed1v2.inp27
-rw-r--r--msdos/sedlibmk.inp37
-rw-r--r--nextstep/Makefile.in4
-rw-r--r--nt/gnulib-cfg.mk1
-rw-r--r--nt/inc/ms-w32.h1
-rw-r--r--nt/mingw-cfg.site3
-rw-r--r--oldXMenu/Activate.c26
-rw-r--r--oldXMenu/XMenu.h8
-rw-r--r--oldXMenu/XMenuInt.h2
-rw-r--r--src/.gdbinit12
-rw-r--r--src/Makefile.in31
-rw-r--r--src/alloc.c804
-rw-r--r--src/atimer.c37
-rw-r--r--src/bidi.c65
-rw-r--r--src/bignum.c93
-rw-r--r--src/bignum.h1
-rw-r--r--src/buffer.c172
-rw-r--r--src/bytecode.c657
-rw-r--r--src/callint.c49
-rw-r--r--src/callproc.c86
-rw-r--r--src/ccl.c6
-rw-r--r--src/character.c40
-rw-r--r--src/character.h2
-rw-r--r--src/charset.c29
-rw-r--r--src/coding.c65
-rw-r--r--src/comp.c431
-rw-r--r--src/comp.h4
-rw-r--r--src/composite.c95
-rw-r--r--src/conf_post.h54
-rw-r--r--src/cygw32.c8
-rw-r--r--src/data.c363
-rw-r--r--src/dbusbind.c41
-rw-r--r--src/decompress.c12
-rw-r--r--src/deps.mk2
-rw-r--r--src/dired.c71
-rw-r--r--src/dispextern.h49
-rw-r--r--src/dispnew.c126
-rw-r--r--src/doc.c73
-rw-r--r--src/dynlib.c4
-rw-r--r--src/dynlib.h1
-rw-r--r--src/editfns.c24
-rw-r--r--src/emacs-module.c14
-rw-r--r--src/emacs.c395
-rw-r--r--src/emacsgtkfixed.c36
-rw-r--r--src/eval.c1031
-rw-r--r--src/fileio.c132
-rw-r--r--src/filelock.c188
-rw-r--r--src/floatfns.c22
-rw-r--r--src/fns.c1173
-rw-r--r--src/font.c88
-rw-r--r--src/font.h5
-rw-r--r--src/fontset.c97
-rw-r--r--src/frame.c248
-rw-r--r--src/frame.h35
-rw-r--r--src/fringe.c23
-rw-r--r--src/ftcrfont.c72
-rw-r--r--src/ftfont.c51
-rw-r--r--src/gnutls.c38
-rw-r--r--src/gnutls.h1
-rw-r--r--src/gtkutil.c944
-rw-r--r--src/gtkutil.h11
-rw-r--r--src/haiku_draw_support.cc288
-rw-r--r--src/haiku_font_support.cc508
-rw-r--r--src/haiku_io.c68
-rw-r--r--src/haiku_select.cc489
-rw-r--r--src/haiku_support.cc3986
-rw-r--r--src/haiku_support.h1073
-rw-r--r--src/haikufns.c1769
-rw-r--r--src/haikufont.c478
-rw-r--r--src/haikugui.h113
-rw-r--r--src/haikuimage.c9
-rw-r--r--src/haikumenu.c362
-rw-r--r--src/haikuselect.c1127
-rw-r--r--src/haikuselect.h84
-rw-r--r--src/haikuterm.c2412
-rw-r--r--src/haikuterm.h218
-rw-r--r--src/image.c1090
-rw-r--r--src/indent.c78
-rw-r--r--src/inotify.c2
-rw-r--r--src/insdel.c6
-rw-r--r--src/intervals.c7
-rw-r--r--src/intervals.h2
-rw-r--r--src/json.c18
-rw-r--r--src/keyboard.c611
-rw-r--r--src/keyboard.h20
-rw-r--r--src/keymap.c65
-rw-r--r--src/kqueue.c4
-rw-r--r--src/lisp.h665
-rw-r--r--src/lread.c2397
-rw-r--r--src/macfont.m18
-rw-r--r--src/macros.c14
-rw-r--r--src/menu.c30
-rw-r--r--src/minibuf.c177
-rw-r--r--src/msdos.c3
-rw-r--r--src/msdos.h9
-rw-r--r--src/nsfns.m868
-rw-r--r--src/nsfont.m22
-rw-r--r--src/nsimage.m2
-rw-r--r--src/nsmenu.m429
-rw-r--r--src/nsselect.m239
-rw-r--r--src/nsterm.h147
-rw-r--r--src/nsterm.m1732
-rw-r--r--src/nsxwidget.m3
-rw-r--r--src/pdumper.c42
-rw-r--r--src/pgtkfns.c630
-rw-r--r--src/pgtkim.c16
-rw-r--r--src/pgtkmenu.c71
-rw-r--r--src/pgtkselect.c2090
-rw-r--r--src/pgtkselect.h33
-rw-r--r--src/pgtkterm.c2616
-rw-r--r--src/pgtkterm.h306
-rw-r--r--src/print.c1181
-rw-r--r--src/process.c354
-rw-r--r--src/profiler.c4
-rw-r--r--src/regex-emacs.c53
-rw-r--r--src/search.c63
-rw-r--r--src/sheap.h2
-rw-r--r--src/sort.c974
-rw-r--r--src/sound.c10
-rw-r--r--src/sqlite.c99
-rw-r--r--src/syntax.c16
-rw-r--r--src/syntax.h4
-rw-r--r--src/sysdep.c377
-rw-r--r--src/syssignal.h2
-rw-r--r--src/sysstdio.h7
-rw-r--r--src/systhread.h2
-rw-r--r--src/systime.h5
-rw-r--r--src/term.c12
-rw-r--r--src/termhooks.h62
-rw-r--r--src/terminal.c6
-rw-r--r--src/textprop.c41
-rw-r--r--src/thread.c39
-rw-r--r--src/thread.h23
-rw-r--r--src/timefns.c162
-rw-r--r--src/tparam.h7
-rw-r--r--src/undo.c4
-rw-r--r--src/verbose.mk.in31
-rw-r--r--src/w16select.c2
-rw-r--r--src/w32.c210
-rw-r--r--src/w32.h3
-rw-r--r--src/w32console.c12
-rw-r--r--src/w32fns.c182
-rw-r--r--src/w32font.c28
-rw-r--r--src/w32image.c5
-rw-r--r--src/w32menu.c21
-rw-r--r--src/w32notify.c32
-rw-r--r--src/w32proc.c17
-rw-r--r--src/w32select.c2
-rw-r--r--src/w32term.c312
-rw-r--r--src/w32term.h23
-rw-r--r--src/w32xfns.c78
-rw-r--r--src/widget.c71
-rw-r--r--src/widget.h2
-rw-r--r--src/window.c343
-rw-r--r--src/window.h14
-rw-r--r--src/xdisp.c726
-rw-r--r--src/xfaces.c402
-rw-r--r--src/xfns.c1878
-rw-r--r--src/xfont.c28
-rw-r--r--src/xftfont.c190
-rw-r--r--src/xgselect.c55
-rw-r--r--src/xgselect.h7
-rw-r--r--src/xmenu.c478
-rw-r--r--src/xrdb.c65
-rw-r--r--src/xselect.c744
-rw-r--r--src/xsettings.c202
-rw-r--r--src/xsettings.h10
-rw-r--r--src/xsmfns.c2
-rw-r--r--src/xterm.c15672
-rw-r--r--src/xterm.h476
-rw-r--r--src/xwidget.c828
-rw-r--r--src/xwidget.h8
-rw-r--r--test/Makefile.in66
-rw-r--r--test/README21
-rw-r--r--test/lisp/abbrev-tests.el4
-rw-r--r--test/lisp/ansi-color-tests.el20
-rw-r--r--test/lisp/auth-source-tests.el30
-rw-r--r--test/lisp/autorevert-tests.el36
-rw-r--r--test/lisp/bookmark-tests.el38
-rw-r--r--test/lisp/calc/calc-tests.el2
-rw-r--r--test/lisp/calendar/icalendar-tests.el14
-rw-r--r--test/lisp/calendar/iso8601-tests.el20
-rw-r--r--test/lisp/calendar/time-date-tests.el9
-rw-r--r--test/lisp/cedet/cedet-files-tests.el17
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp2
-rw-r--r--test/lisp/cedet/semantic/bovine/gcc-tests.el12
-rw-r--r--test/lisp/cedet/srecode-utest-template.el2
-rw-r--r--test/lisp/cedet/srecode/document-tests.el2
-rw-r--r--test/lisp/color-tests.el14
-rw-r--r--test/lisp/cus-edit-tests.el9
-rw-r--r--test/lisp/custom-tests.el1
-rw-r--r--test/lisp/desktop-tests.el50
-rw-r--r--test/lisp/dnd-tests.el441
-rw-r--r--test/lisp/edmacro-tests.el27
-rw-r--r--test/lisp/electric-tests.el2
-rw-r--r--test/lisp/elide-head-tests.el88
-rw-r--r--test/lisp/emacs-lisp/bindat-tests.el140
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el266
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el1
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el127
-rw-r--r--test/lisp/emacs-lisp/cconv-tests.el1
-rw-r--r--test/lisp/emacs-lisp/cl-generic-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-macs-tests.el33
-rw-r--r--test/lisp/emacs-lisp/copyright-tests.el42
-rw-r--r--test/lisp/emacs-lisp/derived-tests.el21
-rw-r--r--test/lisp/emacs-lisp/easy-mmode-tests.el2
-rw-r--r--test/lisp/emacs-lisp/edebug-tests.el19
-rw-r--r--test/lisp/emacs-lisp/ert-tests.el13
-rw-r--r--test/lisp/emacs-lisp/find-func-tests.el7
-rw-r--r--test/lisp/emacs-lisp/nadvice-tests.el17
-rw-r--r--test/lisp/emacs-lisp/oclosure-tests.el166
-rw-r--r--test/lisp/emacs-lisp/pp-resources/code-formats.erts12
-rw-r--r--test/lisp/emacs-lisp/range-tests.el65
-rw-r--r--test/lisp/emacs-lisp/rmc-tests.el23
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el21
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el62
-rw-r--r--test/lisp/emacs-lisp/tabulated-list-tests.el59
-rw-r--r--test/lisp/emacs-lisp/text-property-search-tests.el25
-rw-r--r--test/lisp/emacs-lisp/vtable-tests.el42
-rw-r--r--test/lisp/erc/erc-dcc-tests.el167
-rw-r--r--test/lisp/erc/erc-join-tests.el361
-rw-r--r--test/lisp/erc/erc-networks-tests.el1707
-rw-r--r--test/lisp/erc/erc-scenarios-auth-source.el178
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-nick.el163
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-samenet.el144
-rw-r--r--test/lisp/erc/erc-scenarios-base-association.el192
-rw-r--r--test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el171
-rw-r--r--test/lisp/erc/erc-scenarios-base-misc-regressions.el126
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el34
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el30
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el32
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el35
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer.el35
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-samenet.el147
-rw-r--r--test/lisp/erc/erc-scenarios-base-reconnect.el226
-rw-r--r--test/lisp/erc/erc-scenarios-base-renick.el305
-rw-r--r--test/lisp/erc/erc-scenarios-base-reuse-buffers.el238
-rw-r--r--test/lisp/erc/erc-scenarios-base-unstable.el134
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el43
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el43
-rw-r--r--test/lisp/erc/erc-scenarios-internal.el27
-rw-r--r--test/lisp/erc/erc-scenarios-join-auth-source.el67
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el50
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd.el37
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon-id.el46
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon.el36
-rw-r--r--test/lisp/erc/erc-scenarios-misc.el141
-rw-r--r--test/lisp/erc/erc-scenarios-services-misc.el86
-rw-r--r--test/lisp/erc/erc-services-tests.el574
-rw-r--r--test/lisp/erc/erc-tests.el620
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld44
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld48
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/again.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/foisted.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/refoisted.eld31
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/renicked.eld30
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/barnet.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/assoc/reconplay/again.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/reconplay/foonet.eld52
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/chester.eld40
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/tester.eld42
-rw-r--r--test/lisp/erc/resources/base/assoc/samenet/tester2.eld39
-rw-r--r--test/lisp/erc/resources/base/auth-source/foonet.eld23
-rw-r--r--test/lisp/erc/resources/base/auth-source/nopass.eld22
-rw-r--r--test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/flood/soju.eld87
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/barnet.eld40
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/foonet.eld41
-rw-r--r--test/lisp/erc/resources/base/gapless-connect/pass-stub.eld4
-rw-r--r--test/lisp/erc/resources/base/mask-target-routing/foonet.eld45
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld50
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld41
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet.eld41
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld50
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld46
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet.eld46
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/stub-again.eld4
-rw-r--r--test/lisp/erc/resources/base/netid/samenet/chester.eld48
-rw-r--r--test/lisp/erc/resources/base/netid/samenet/tester.eld52
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted-dupe.eld28
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted.eld45
-rw-r--r--test/lisp/erc/resources/base/reconnect/options-again.eld45
-rw-r--r--test/lisp/erc/resources/base/reconnect/options.eld35
-rw-r--r--test/lisp/erc/resources/base/reconnect/timer-last.eld6
-rw-r--r--test/lisp/erc/resources/base/reconnect/timer.eld6
-rw-r--r--test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld54
-rw-r--r--test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld52
-rw-r--r--test/lisp/erc/resources/base/renick/queries/solo.eld55
-rw-r--r--test/lisp/erc/resources/base/renick/self/auto.eld46
-rw-r--r--test/lisp/erc/resources/base/renick/self/manual.eld50
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-chester.eld40
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-tester.eld46
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld68
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld66
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld24
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld24
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld64
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld72
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld93
-rw-r--r--test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld86
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-i.el124
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-t.el170
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-tests.el1346
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-u.el213
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d.el997
-rw-r--r--test/lisp/erc/resources/erc-d/resources/basic.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/depleted.eld12
-rw-r--r--test/lisp/erc/resources/erc-d/resources/drop-a.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/drop-b.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic.eld30
-rw-r--r--test/lisp/erc/resources/erc-d/resources/eof.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/fuzzy.eld42
-rw-r--r--test/lisp/erc/resources/erc-d/resources/incremental.eld43
-rw-r--r--test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld380
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld3
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld3
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger.eld33
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-block.eld55
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-match.eld32
-rw-r--r--test/lisp/erc/resources/erc-d/resources/no-pong.eld27
-rw-r--r--test/lisp/erc/resources/erc-d/resources/nonstandard.eld6
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld24
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld24
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-solo.eld9
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el45
-rw-r--r--test/lisp/erc/resources/erc-d/resources/timeout.eld27
-rw-r--r--test/lisp/erc/resources/erc-d/resources/unexpected.eld28
-rw-r--r--test/lisp/erc/resources/erc-scenarios-common.el516
-rw-r--r--test/lisp/erc/resources/join/auth-source/foonet.eld33
-rw-r--r--test/lisp/erc/resources/join/legacy/foonet.eld38
-rw-r--r--test/lisp/erc/resources/join/network-id/barnet.eld43
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet-again.eld46
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet.eld39
-rw-r--r--test/lisp/erc/resources/join/reconnect/foonet-again.eld45
-rw-r--r--test/lisp/erc/resources/join/reconnect/foonet.eld45
-rw-r--r--test/lisp/erc/resources/networks/announced-missing/foonet.eld8
-rw-r--r--test/lisp/erc/resources/services/auth-source/libera.eld49
-rw-r--r--test/lisp/erc/resources/services/password/libera.eld49
-rw-r--r--test/lisp/eshell/em-basic-tests.el71
-rw-r--r--test/lisp/eshell/em-extpipe-tests.el205
-rw-r--r--test/lisp/eshell/em-glob-tests.el197
-rw-r--r--test/lisp/eshell/em-pred-tests.el566
-rw-r--r--test/lisp/eshell/em-tramp-tests.el88
-rw-r--r--test/lisp/eshell/esh-opt-tests.el289
-rw-r--r--test/lisp/eshell/esh-proc-tests.el96
-rw-r--r--test/lisp/eshell/esh-var-tests.el508
-rw-r--r--test/lisp/eshell/eshell-tests-helpers.el97
-rw-r--r--test/lisp/eshell/eshell-tests.el181
-rw-r--r--test/lisp/ffap-tests.el19
-rw-r--r--test/lisp/filenotify-tests.el42
-rw-r--r--test/lisp/files-resources/compile-utf8.el12
-rw-r--r--test/lisp/files-resources/file-mode3
-rw-r--r--test/lisp/files-resources/file-mode-multiple5
-rw-r--r--test/lisp/files-resources/file-mode-prop-line1
-rw-r--r--test/lisp/files-tests.el189
-rw-r--r--test/lisp/files-x-tests.el18
-rw-r--r--test/lisp/gnus/mml-sec-tests.el3
-rw-r--r--test/lisp/help-fns-tests.el10
-rw-r--r--test/lisp/help-mode-tests.el7
-rw-r--r--test/lisp/help-tests.el34
-rw-r--r--test/lisp/hi-lock-tests.el14
-rw-r--r--test/lisp/hl-line-tests.el114
-rw-r--r--test/lisp/htmlfontify-tests.el9
-rw-r--r--test/lisp/ibuffer-tests.el4
-rw-r--r--test/lisp/image-tests.el20
-rw-r--r--test/lisp/international/textsec-tests.el214
-rw-r--r--test/lisp/isearch-tests.el80
-rw-r--r--test/lisp/json-tests.el4
-rw-r--r--test/lisp/kmacro-tests.el17
-rw-r--r--test/lisp/loadhist-resources/loadhist--bar.el27
-rw-r--r--test/lisp/loadhist-resources/loadhist--foo.el29
-rw-r--r--test/lisp/loadhist-tests.el47
-rw-r--r--test/lisp/ls-lisp-tests.el39
-rw-r--r--test/lisp/mail/ietf-drums-date-tests.el172
-rw-r--r--test/lisp/mail/ietf-drums-tests.el178
-rw-r--r--test/lisp/mail/mail-extr-tests.el41
-rw-r--r--test/lisp/mail/undigest-tests.el359
-rw-r--r--test/lisp/mh-e/mh-thread-tests.el2
-rw-r--r--test/lisp/mh-e/mh-utils-tests.el4
-rw-r--r--test/lisp/minibuffer-tests.el136
-rw-r--r--test/lisp/misc-tests.el25
-rw-r--r--test/lisp/mouse-tests.el14
-rw-r--r--test/lisp/net/browse-url-tests.el15
-rw-r--r--test/lisp/net/mailcap-resources/mailcap9
-rw-r--r--test/lisp/net/mailcap-resources/test.test1
-rw-r--r--test/lisp/net/mailcap-tests.el70
-rw-r--r--test/lisp/net/ntlm-tests.el9
-rw-r--r--test/lisp/net/puny-resources/IdnaTestV2.txt6344
-rw-r--r--test/lisp/net/puny-tests.el6
-rw-r--r--test/lisp/net/tramp-archive-tests.el53
-rw-r--r--test/lisp/net/tramp-resources/foo.tar.gzbin0 -> 274 bytes
-rw-r--r--test/lisp/net/tramp-tests.el1166
-rw-r--r--test/lisp/obsolete/inversion-tests.el1
-rw-r--r--test/lisp/progmodes/autoconf-tests.el8
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl50
-rw-r--r--test/lisp/progmodes/cperl-mode-tests.el54
-rw-r--r--test/lisp/progmodes/flymake-tests.el9
-rw-r--r--test/lisp/progmodes/python-tests.el486
-rw-r--r--test/lisp/progmodes/ruby-mode-resources/ruby.rb17
-rw-r--r--test/lisp/progmodes/ruby-mode-tests.el7
-rw-r--r--test/lisp/progmodes/sh-script-resources/sh-indents.erts40
-rw-r--r--test/lisp/progmodes/sh-script-tests.el21
-rw-r--r--test/lisp/progmodes/sql-tests.el80
-rw-r--r--test/lisp/replace-tests.el96
-rw-r--r--test/lisp/ses-tests.el75
-rw-r--r--test/lisp/shadowfile-tests.el120
-rw-r--r--test/lisp/simple-tests.el59
-rw-r--r--test/lisp/so-long-tests/so-long-tests.el4
-rw-r--r--test/lisp/so-long-tests/spelling-tests.el16
-rw-r--r--test/lisp/subr-tests.el85
-rw-r--r--test/lisp/textmodes/css-mode-resources/css-selectors.txt56
-rw-r--r--test/lisp/textmodes/css-mode-resources/scss-selectors.txt10
-rw-r--r--test/lisp/textmodes/css-mode-tests.el69
-rw-r--r--test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts131
-rw-r--r--test/lisp/textmodes/emacs-news-mode-tests.el32
-rw-r--r--test/lisp/textmodes/fill-tests.el23
-rw-r--r--test/lisp/textmodes/page-tests.el12
-rw-r--r--test/lisp/time-stamp-tests.el17
-rw-r--r--test/lisp/url/url-tramp-tests.el16
-rw-r--r--test/lisp/vc/vc-bzr-tests.el2
-rw-r--r--test/lisp/vc/vc-tests.el31
-rw-r--r--test/lisp/x-dnd-tests.el203
-rw-r--r--test/lisp/xml-tests.el2
-rw-r--r--test/lisp/yank-media-tests.el38
-rw-r--r--test/manual/etags/ETAGS.good_1748
-rw-r--r--test/manual/etags/ETAGS.good_2776
-rw-r--r--test/manual/etags/ETAGS.good_3772
-rw-r--r--test/manual/etags/ETAGS.good_41028
-rw-r--r--test/manual/etags/ETAGS.good_51080
-rw-r--r--test/manual/etags/ETAGS.good_61080
-rw-r--r--test/manual/etags/c-src/emacs/src/keyboard.c2
-rw-r--r--test/manual/etags/el-src/emacs/lisp/progmodes/etags.el2
-rw-r--r--test/manual/image-circular-tests.el17
-rw-r--r--test/src/buffer-tests.el55
-rw-r--r--test/src/comp-resources/comp-test-45603.el5
-rw-r--r--test/src/comp-resources/comp-test-funcs.el12
-rw-r--r--test/src/comp-tests.el18
-rw-r--r--test/src/doc-tests.el4
-rw-r--r--test/src/emacs-module-resources/mod-test.c42
-rw-r--r--test/src/emacs-module-tests.el6
-rw-r--r--test/src/eval-tests.el27
-rw-r--r--test/src/fileio-tests.el26
-rw-r--r--test/src/filelock-tests.el217
-rw-r--r--test/src/fns-tests.el265
-rw-r--r--test/src/image-tests.el7
-rw-r--r--test/src/json-tests.el7
-rw-r--r--test/src/keymap-tests.el14
-rw-r--r--test/src/lread-tests.el63
-rw-r--r--test/src/print-tests.el124
-rw-r--r--test/src/process-tests.el2
-rw-r--r--test/src/regex-emacs-tests.el12
-rw-r--r--test/src/sqlite-tests.el25
-rw-r--r--test/src/syntax-tests.el15
-rw-r--r--test/src/thread-tests.el25
-rw-r--r--test/src/timefns-tests.el11
-rw-r--r--test/src/xdisp-tests.el9
-rw-r--r--test/src/xfaces-tests.el5
1509 files changed, 176141 insertions, 62490 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index 4cf221a7e1a..fac283eda6a 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -10,7 +10,9 @@
((("c" "objc") .
("/[ \t]*DEFVAR_[A-Z_ \t(]+\"\\([^\"]+\\)\"/\\1/"
"/[ \t]*DEFVAR_[A-Z_ \t(]+\"[^\"]+\",[ \t]\\([A-Za-z0-9_]+\\)/\\1/"))))
- (etags-regen-ignores . ("test/manual/etags/"))))
+ (etags-regen-ignores . ("test/manual/etags/"))
+ (emacs-lisp-docstring-fill-column . 65)
+ (bug-reference-url-format . "https://debbugs.gnu.org/%s")))
(c-mode . ((c-file-style . "GNU")
(c-noise-macro-names . ("INLINE" "ATTRIBUTE_NO_SANITIZE_UNDEFINED" "UNINIT" "CALLBACK" "ALIGN_STACK"))
(electric-quote-comment . nil)
diff --git a/.gitignore b/.gitignore
index 35ff949e93b..16f449a446e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -221,6 +221,7 @@ lisp/international/emoji-zwj.el
lisp/international/emoji-labels.el
lisp/international/eucjp-ms.el
lisp/international/uni-*.el
+lisp/international/idna-mapping.el
lisp/language/pinyin.el
# Documentation.
diff --git a/CONTRIBUTE b/CONTRIBUTE
index 7c3421ed75a..d624fe85245 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -314,11 +314,42 @@ them right the first time, so here are guidelines for formatting them:
with Emacs commands like 'C-x 4 a', and commit the change using the
shell command 'vc-dwim --commit'. Type 'vc-dwim --help' for more.
+** Committing your changes.
+
+When you commit changes, Git invokes several scripts that test the
+commit for validity, and may abort the commit of some of the tests
+fail. These scripts live in the '.git/hooks/' subdirectory of the
+top-level directory of the repository, and they perform the following
+tests:
+
+- commit log message must not be empty;
+- the first line of the commit log message doesn't start with
+ whitespace characters;
+- the second line of the commit log message must be empty;
+- commit log message should include only valid printable ASCII and
+ UTF-8 characters;
+- commit log message lines must be shorter than 79 characters, unless
+ a line consists of a single long word, in which case that word can
+ be up to 140 characters long;
+- there shouldn't be any "Signed-off-by:" tags in the commit log
+ message, and "git commit" should not be invoked with the '-s' option
+ (which automatically adds "Signed-off-by:");
+- if the commit adds new files, the file names must not begin with
+ '-' and must consist of ASCII letters, digits, and characters of the
+ set [-+./_];
+- the changes don't include unresolved merge conflict markers;
+- the changes don't introduce whitespace errors: trailing whitespace,
+ lines that include nothing but whitespace characters, and indented
+ lines where a SPC character is immediately followed by a TAB in the
+ line's initial indentation
+
** Committing changes by others
If committing changes written by someone else, commit in their name,
not yours. You can use 'git commit --author="AUTHOR"' to specify a
-change's author.
+change's author. Note that the validity checks described in the
+previous section are still applied, so you will have to correct any
+problems they uncover in the changes submitted by others.
** Branches
@@ -366,6 +397,22 @@ reasons. These should be marked by including something like "Do not
merge to master" or anything that matches gitmerge-skip-regexp (see
admin/gitmerge.el) in the commit message.
+** Some packages in Emacs are maintained externally
+
+Sometimes a package that ships as part of GNU Emacs is maintained as a
+separate project, with its own upstream repository, its own maintainer
+group, its own development conventions, etc. The upstream project's
+code is periodically merged into Emacs (exactly when and how such
+merges happen depends on the package).
+
+So when you are making a contribution -- such as fixing a bug or
+proposing an enhancement -- to one of these externally maintained
+packages, you sometimes need to deal with that package at its upstream
+source.
+
+In the section "Externally maintained packages" in "admin/MAINTAINERS"
+we maintain a list of such packages.
+
** GNU ELPA
This repository does not contain the Emacs Lisp package archive
diff --git a/ChangeLog.3 b/ChangeLog.3
index 177321dc45e..907eb2ce6ff 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -1,3 +1,2791 @@
+2022-06-29 Michael Albinus <michael.albinus@gmx.de>
+
+ Update Tramp version (don't merge with master)
+
+ * doc/misc/trampver.texi:
+ * lisp/net/trampver.el: Change version to "2.5.3".
+
+2022-06-28 Michael Albinus <michael.albinus@gmx.de>
+
+ Tramp shall not trap unrelated D-Bus errors
+
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-dbus-event-vector): Declare.
+ (tramp-gvfs-file-name-handler): Let-bind it.
+ (tramp-gvfs-dbus-event-vector): Fix docstring.
+ (tramp-gvfs-maybe-open-connection): Do not set it globally. (Bug#56162)
+
+2022-06-28 Basil L. Contovounesios <contovob@tcd.ie>
+
+ Fix hash table function return values in manual
+
+ * doc/lispref/hash.texi (Hash Access): Reconcile documented return
+ values of puthash and clrhash with their respective
+ docstrings (bug#55562).
+
+2022-06-27 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.4-3-g6dc785
+
+2022-06-27 Paul Eggert <eggert@cs.ucla.edu>
+
+ Mention Solaris 10 'make clean' and 'make check'
+
+ Mention further crashes on Solaris 10
+
+2022-06-26 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port distribution tarball to Solaris 10
+
+ * make-dist (taropt): Use 'tar -H ustar' to generate a portable
+ tar file format instead of a GNU-specific format. Needed now that
+ Emacs tarballs contain file names longer than 100 bytes, e.g.:
+ emacs-28.1/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key
+ emacs-28.1/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el
+ Without this patch, extracting a tarball on Solaris 10 fails with
+ many diagnostics like “tar: ././@LongLink: typeflag 'L' not
+ recognized, converting to regular file”.
+
+ (cherry picked from commit 4410f5d86997b6b238ff05c2ece338b28e1163b1)
+
+2022-06-24 Stefan Kangas <stefan@marxist.se>
+
+ Avoid treating number as an enum in the org manual
+
+ * doc/misc/org.org (The Agenda Dispatcher): Avoid treating number as
+ enum.
+
+2022-06-22 Eli Zaretskii <eliz@gnu.org>
+
+ Improve last change in autotype.texi
+
+ * doc/misc/autotype.texi (Autoinserting): Fix wording. Suggested
+ by Richard Stallman <rms@gnu.org>.
+
+2022-06-21 Stefan Kangas <stefan@marxist.se>
+
+ * lisp/repeat.el (repeat-mode): Fix message format.
+
+2022-06-21 Earl Hyatt <okamsn@protonmail.com>
+
+ Clarify autotype.texi text slightly
+
+ * doc/misc/autotype.texi (Autoinserting): Make text slightly
+ clearer (bug#56118).
+
+2022-06-20 Eli Zaretskii <eliz@gnu.org>
+
+ Support builds configured with a separate --bindir
+
+ * src/emacs.c (load_pdump): Don't overwrite the leading
+ directories of the Emacs executable just because the pdumper file
+ was not found in the expected directory relative to the binary.
+ This is needed to support builds with a separate --bindir
+ configure-time option and native-compilation. (Bug#55741)
+
+2022-06-20 Stefan Kangas <stefan@marxist.se>
+
+ * doc/misc/eww.texi (Overview, Basics): Fix typos.
+
+2022-06-18 Richard Hansen <rhansen@rhansen.org>
+
+ Fix invalid defcustom :group when :predicate is used
+
+ * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix
+ invalid `:group' argument for the `-modes' defcustom that is created
+ when `:predicate' is used (bug#56049).
+
+2022-06-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Prune the Gnus FAQ of some outdated data
+
+ * doc/misc/gnus-faq.texi (FAQ 9-2): Remove some outdated advice
+ (bug#56042).
+
+2022-06-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix efaq-w32.texi build warning
+
+ * doc/misc/efaq-w32.texi (Other useful ports): Fix ordering to
+ match nodes (or should the nodes be moved instead?).
+
+ Do not merge to master.
+
+2022-06-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Update cl-struct-sequence-type doc string
+
+ * lisp/emacs-lisp/cl-macs.el (cl-struct-sequence-type): Fix doc
+ string to reflect what it does (bug#46523).
+
+2022-06-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix a tagging problem in tramp.texi
+
+ * doc/misc/tramp.texi (Frequently Asked Questions): Restore an
+ @end lisp removed by accident.
+
+2022-06-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Mention face quirks after the final line in the lispref manual
+
+ * doc/lispref/display.texi (Face Attributes): Mention the quirks
+ about point after the final line (bug#56011).
+
+2022-06-17 Stefan Kangas <stefan@marxist.se>
+
+ Delete reference to obsolete library complete.el
+
+ * doc/misc/tramp.texi (Frequently Asked Questions): Delete reference
+ to obsolete library complete.el.
+
+2022-06-16 Stefan Kangas <stefan@marxist.se>
+
+ * lisp/textmodes/artist.el: Minor doc fixes.
+
+2022-06-16 Michael Albinus <michael.albinus@gmx.de>
+
+ * lisp/net/tramp.el (tramp-methods): Fix quoting in docstring.
+
+2022-06-16 Arash Esbati <arash@gnu.org>
+
+ Update MS Windows FAQ for MinGW64-w64/MSYS2
+
+ * doc/misc/efaq-w32.texi (Compiling, Debugging): Mention
+ MinGW64-w64/MSYS2 as the preferred way for building Emacs on
+ capable systems.
+ (Attachments with Gnus): Catch up with emacs-mime.texi in the
+ example given.
+ (Spell check): Add the availability of GNU Aspell and Hunspell
+ in MSYS2 distribution.
+ (Other useful ports): Add an entry for MinGW64-w64/MSYS2.
+ Fix link for MinGW homepage.
+ Remove entry for defunct UWIN project. (Bug#55930)
+
+2022-06-15 Robert Pluim <rpluim@gmail.com>
+
+ Describe 'set-file-modes' argument prompting
+
+ * src/fileio.c (Fset_file_modes): Document that FILENAME is prompted
+ for. (Bug#55984)
+
+2022-06-14 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert "Clarify what a Calc registeri in in calc-insert-register"
+
+ This reverts commit 73400e4002ce8fca060093548e6791b3a784eeaa.
+
+ This has been fixed in Emacs 29 by making it possible to use regular registers in calc.
+
+2022-06-13 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Clarify what a Calc registeri in in calc-insert-register
+
+ * lisp/calc/calc-yank.el (calc-insert-register): Note that these
+ aren't normal registers (bug#55943).
+
+2022-06-11 Eli Zaretskii <eliz@gnu.org>
+
+ Fix doc strings in whitespace.el
+
+ * lisp/whitespace.el (whitespace-style, whitespace-action):
+ Untabify the doc strings. (Bug#55904)
+
+2022-06-10 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of "etags -I"
+
+ * doc/man/etags.1:
+ * doc/emacs/maintaining.texi (Create Tags Table): Elaborate on the
+ importance of the '-I' option to 'etags'. (Bug#45246)
+
+2022-06-09 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Mention the #f syntax from cl-prin1
+
+ * doc/lispref/objects.texi (Special Read Syntax): Mention #f,
+ which is in cl-prin1 output (bug#55853).
+
+2022-06-09 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix file name quoting in tramp-smb.el (do not merge)
+
+ * lisp/net/tramp-smb.el (tramp-smb-handle-write-region): Quote tmpfile.
+ (tramp-smb-get-localname): Remove superfluous test. (Bug#55855)
+
+ * test/lisp/net/tramp-tests.el (tramp-test03-file-name-method-rules):
+ Remove superfluous checks.
+
+2022-06-09 Jeff Walsh <fejfighter@gmail.com>
+
+ Update error message to reflect variable rename
+
+ * src/comp.c (Fcomp_el_to_eln_filename): Update error message. (Bug#55861)
+
+2022-06-08 Ken Brown <kbrown@cornell.edu>
+
+ Fix error reporting in process-async-https-with-delay
+
+ * test/src/process-tests.el (process-async-https-with-delay): Use
+ 'plist-get' instead of 'assq' in testing for a connection error.
+ The 'status' variable is a plist, not an alist. (Bug#55849)
+
+2022-06-08 Stefan Kangas <stefan@marxist.se>
+
+ * doc/misc/org.org: Remove spurious markup.
+
+2022-06-08 Michael Albinus <michael.albinus@gmx.de>
+
+ Make Tramp version check more robust
+
+ * lisp/net/trampver.el (tramp-repository-branch)
+ (tramp-repository-version): Check for "git" executable.
+
+2022-06-07 Eli Zaretskii <eliz@gnu.org>
+
+ Fix debugging with GDB when a breakpoint has multiple locations
+
+ * lisp/progmodes/gdb-mi.el (gdb-breakpoints--add-breakpoint-row):
+ New function, extracted from 'gdb-breakpoints-list-handler-custom'.
+ Don't print "in <unknown>" for header-rows of breakpoints with
+ multiple locations that don't have a function name attached.
+ (gdb-breakpoints-list-handler-custom): Add to the breakpoint table
+ also any locations in multiple-location breakpoints, which are
+ supported since GDB 6.8.
+
+2022-06-05 Eli Zaretskii <eliz@gnu.org>
+
+ Update documentation of 'aset' and 'store-substring'
+
+ * doc/lispref/strings.texi (Modifying Strings): Adjust to
+ implementation changes: it is possible for the modified string to
+ have fewer or more bytes than the original. Add recommendations
+ regarding unibyte vs multibyte strings and characters. (Bug#55801)
+
+2022-06-04 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.4
+
+2022-06-04 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify documentation of 'string-to-unibyte'
+
+ * doc/lispref/nonascii.texi (Converting Representations): Clarify
+ what 'string-to-unibyte' does. Reported by Richard Hansen
+ <rhansen@rhansen.org>. (Bug#55777)
+
+2022-06-02 Ikumi Keita <ikumi@ikumi.que.jp> (tiny change)
+
+ Improve keystrokes in doc strings in some find-file functions
+
+ * lisp/files.el (find-file):
+ (find-file-other-window):
+ (find-file-other-frame): Include the correct keymap so that
+ keystrokes are displayed better (bug#55761).
+
+2022-06-02 Eli Zaretskii <eliz@gnu.org>
+
+ Fix segfaults when starting on 80x26 TTY frames
+
+ * src/dispnew.c (adjust_frame_glyphs_for_frame_redisplay): Make
+ sure we have valid frame glyph matrices for the interactive
+ session. (Bug#55760)
+ (adjust_frame_glyphs): Add assertions for when we fail to allocate
+ valid frame glyph matrices for a TTY frame.
+
+2022-06-01 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Make it explicit that a couple of _s in lispref are underscores
+
+ * doc/lispref/strings.texi (Custom Format Strings):
+ * doc/lispref/control.texi (pcase Macro): Make it explicit that
+ it's an underscore (bug#55742).
+
+2022-05-31 Eli Zaretskii <eliz@gnu.org>
+
+ Remove from FAQ the MS-Windows info about BDF fonts
+
+ * doc/misc/efaq.texi (How to add fonts): Remove the MS-Windows
+ specific steps, as BDF fonts are no longer supported on
+ MS-Windows. (Bug#55740)
+
+2022-05-31 Ikumi Keita <ikumi@ikumi.que.jp> (tiny change)
+
+ Fix Display Property manual example
+
+ * doc/lispref/display.texi (Display Property): Fix syntax of
+ example (bug#55736).
+
+2022-05-29 Michael Albinus <michael.albinus@gmx.de>
+
+ Some Tramp cleanup on MS Windows
+
+ * lisp/net/tramp.el (tramp-restricted-shell-hosts-alist): Do not add
+ localhost when `tramp-encoding-shell' is a POSIX shell.
+
+ * test/lisp/net/tramp-tests.el (tramp-test31-interrupt-process):
+ Skip on MS Windows.
+
+2022-05-28 Alan Mackenzie <acm@muc.de>
+
+ do_switch_frame: before leaving mini-window, check other (mru) window is live
+
+ This fixes bug#55684. There, with a minibuffer-only frame at start up,
+ Emacs tried to switch to this frame, whose selected window was the
+ mini-window. There is no other active window in this frame, so the
+ attempt to swith to another window failed.
+
+ * src/frame.c (do_switch_frame): On switching to a frame whose selected
+ window is as above, before selecting the most recently used window, check
+ this ostensible window is an actual live window. Otherwise leave the
+ mini-window selected.
+
+2022-05-28 Eli Zaretskii <eliz@gnu.org>
+
+ Fix commands used to produce on-line HTML docs
+
+ * admin/admin.el (manual-meta-string): Only include the first
+ line, and move the rest...
+ (manual-links-string): ...to this new string.
+ (manual-html-fix-headers): Don't remove the '<meta name=' elements
+ produced by makeinfo, especially not the 'name="viewport"' one,
+ which is essential for viewing the docs on mobile devices.
+ Reported by "Facundo Lander via RT" <webmasters-comment@gnu.org>,
+ see gnu.org ticket #1840138.
+
+2022-05-28 Eli Zaretskii <eliz@gnu.org>
+
+ Fix a bad cross-reference in elisp.pdf
+
+ * doc/lispref/control.texi (pcase Macro): Fix a conditional
+ cross-reference (bug#55689).
+
+2022-05-28 Eli Zaretskii <eliz@gnu.org>
+
+ Fix documentation of 'string-pad'
+
+ * doc/lispref/strings.texi (Creating Strings): Fix description of
+ 'string-pad'. (Bug#55688)
+
+2022-05-27 Juri Linkov <juri@linkov.net>
+
+ Fix more occurrences of renamed kmacro-keymap command
+
+ * doc/emacs/kmacro.texi (Basic Keyboard Macro): Fix documentation
+ after recent kmacro-redisplay command name change.
+
+2022-05-27 Eli Zaretskii <eliz@gnu.org>
+
+ Mention "unspecified-fg" and "unspecified-bg" in some doc strings
+
+ * lisp/faces.el (face-foreground, face-background)
+ (foreground-color-at-point, background-color-at-point):
+ * lisp/color.el (color-name-to-rgb): Mention "unspecified-fg" and
+ "unspecified-bg" pseudo-colors on TTY frames. (Bug#55623)
+
+2022-05-26 Hayden Shenk <hayden.shenk@zetier.com> (tiny change)
+
+ Fix format specifiers in tramp-adb.el
+
+ * lisp/net/tramp-adb.el (tramp-adb-get-device): Fix format
+ specifiers for port. (Bug#55651)
+
+2022-05-22 Damien Cassou <damien@cassou.me>
+
+ Improve documentation of mail-user-agent.
+
+ * doc/emacs/sending.texi (Mail Methods):
+ * lisp/simple.el (mail-user-agent): Mention additional options
+ of non-bundled MUA. (Bug#5569)
+
+2022-05-21 Eli Zaretskii <eliz@gnu.org>
+
+ More fixes in abbrev.el doc strings
+
+ * lisp/abbrev.el (inverse-add-global-abbrev, inverse-add-mode-abbrev):
+ Document the effect of negative ARG. (Bug#55527)
+
+2022-05-21 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Add note about Tramp completion to completion-styles doc string
+
+ * lisp/minibuffer.el (completion-styles): Add note about Tramp
+ completion (bug#37954).
+
+2022-05-21 Arash Esbati <arash@gnu.org>
+
+ Remove mention of removed nnimap-nov-is-evil variable
+
+ * doc/misc/gnus.texi (Slow/Expensive Connection): Remove mention
+ of removed nnimap-nov-is-evil variable (bug#55556).
+
+2022-05-21 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation strings and prompts in abbrev.el
+
+ * lisp/abbrev.el (abbrev-file-name, only-global-abbrevs)
+ (copy-abbrev-table, insert-abbrevs, list-abbrevs)
+ (abbrev-table-name, edit-abbrevs, define-abbrevs)
+ (read-abbrev-file, quietly-read-abbrev-file, write-abbrev-file)
+ (abbrev-edit-save-to-file, abbrev-edit-save-buffer)
+ (add-mode-abbrev, add-global-abbrev, inverse-add-mode-abbrev)
+ (inverse-add-global-abbrev, abbrev-prefix-mark)
+ (expand-region-abbrevs, abbrev-table-get, abbrev-table-put)
+ (abbrev-get, abbrev-minor-mode-table-alist, abbrevs-changed)
+ (abbrev-all-caps, last-abbrev-text, last-abbrev-location)
+ (clear-abbrev-table, define-abbrev, define-global-abbrev)
+ (define-mode-abbrev, abbrev--active-tables, abbrev--symbol)
+ (abbrev-symbol, abbrev-expansion, abbrev-insert)
+ (abbrev-expand-function, abbrev--suggest-above-threshold)
+ (abbrev--suggest-saved-recommendations)
+ (abbrev--suggest-shortest-abbrev, abbrev--suggest-get-totals)
+ (insert-abbrev-table-description, define-abbrev-table)
+ (abbrev-table-menu): Fix doc strings: wording, punctuation,
+ clarity.
+ (add-abbrev, inverse-add-abbrev): Improve the prompt text.
+ (Bug#55527)
+
+2022-05-20 Alan Mackenzie <acm@muc.de>
+
+ Restore the Fselect_window call in gui_consider_frame_title.
+
+ This fixes bug #55412. The call to Fselect_window was removed on 2021-03-21
+ in the commit "Prevent open minibuffers getting lost when their frame gets
+ deleted". This call is actually needed to determine current elements of the
+ pertinent window and frame when these are used in the frame title.
+
+ * src/frame.c (do_switch_frame): When the selected window in the target frame
+ is the mini-window, switch away from this window unless there is a valid
+ minibuffer there.
+
+ * src/frame.h (struct frame): Add an incidental comment about the element
+ selected_window.
+
+ * src/minibuf.c (move_minibuffers_onto_frame): No longer set the selected
+ window of the source frame. This action is now performed later, on returning
+ to that frame, in do_switch_frame when needed (see above).
+
+ * src/xdisp.c (gui_consider_frame_title): Replace the Fselect_window call and
+ associated ancillary settings.
+
+2022-05-20 Eli Zaretskii <eliz@gnu.org>
+
+ Advise against settings in the MS-Windows system registry
+
+ * doc/emacs/cmdargs.texi (MS-Windows Registry): Advise against
+ setting environment variables in the system registry. (Bug#16429)
+
+2022-05-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix kmacro-keymap binding after previous change
+
+ * lisp/kmacro.el (kmacro-keymap): Fix binding after
+ kmacro-redisplay command name change.
+
+2022-05-17 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Add glossary entries for "interactively"
+
+ * doc/emacs/glossary.texi (Glossary): Mention "interactively" and
+ how it relates to the "command" concept (bug#55461).
+
+2022-05-17 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the name of a kmacro command.
+
+ * lisp/kmacro.el (kmacro-redisplay): Rename from
+ 'kdb-macro-redisplay' (which was wrong and included a typo).
+
+ * etc/NEWS: Announce the change. (Bug#55471)
+
+2022-05-17 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix Tramp sshfs tests (don't merge)
+
+ * test/lisp/net/tramp-tests.el (tramp-fuse-remove-hidden-files): Declare.
+ (tramp-test16-directory-files)
+ (tramp-test16-file-expand-wildcards)
+ (tramp-test26-file-name-completion, tramp--test-check-files): Use it.
+ (tramp--test-check-files): Delete directory recursively.
+
+2022-05-17 Michael Albinus <michael.albinus@gmx.de>
+
+ Some minor Tramp fixes
+
+ * lisp/net/tramp-cmds.el (tramp-list-tramp-buffers)
+ (tramp-list-remote-buffers): Add ;;;###tramp-autoload cookie.
+
+ * lisp/net/tramp-fuse.el (tramp-fuse-remove-hidden-files): New defvar.
+ (tramp-fuse-remove-hidden-files): Use it.
+
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handler-askquestion):
+ Keep regression tests running.
+
+2022-05-15 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.3-6-gef41f3
+
+2022-05-15 Michael Albinus <michael.albinus@gmx.de>
+
+ Hide temporary FUSE files in Tramp
+
+ * lisp/net/tramp-fuse.el (tramp-fuse-remove-hidden-files): New defsubst.
+ (tramp-fuse-handle-directory-files)
+ (tramp-fuse-handle-file-name-all-completions): Use it.
+
+2022-05-15 Michael Albinus <michael.albinus@gmx.de>
+
+ * test/lisp/net/tramp-tests.el (tramp-test27-load): Adapt test. Don't merge
+
+2022-05-13 Po Lu <luangruo@yahoo.com>
+
+ Fix tooltip face overwriting dragged text strings during mouse DND
+
+ * lisp/mouse.el (mouse-drag-and-drop-region): Copy
+ `text-tooltip' before showing it. Do not merge to master.
+
+2022-05-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix lexical-binding fallout in vhdl-mode.el
+
+ * lisp/progmodes/vhdl-mode.el (arch-alist, pack-alist)
+ (file-alist, unit-alist, rule-alist): Defvar them, since vhdl-aput
+ expects them to be dynamically bound. (Bug#55389)
+ (vhdl-speedbar-insert-hierarchy): Rename the PACK-ALIST argument
+ to PACKAGE-ALIST, to avoid shadowing the global variable.
+
+2022-05-12 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix ControlPath quoting in Tramp
+
+ * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options):
+ Adapt docstring. Do not quote ControlPath. Reported by Daniel
+ Kessler <kesslerd@umich.edu>.
+
+2022-05-09 Eli Zaretskii <eliz@gnu.org>
+
+ Remove the AUCTeX subsection from MS-Windows FAQ
+
+ * doc/misc/efaq-w32.texi (AUCTeX): Remove the subsection, it is no
+ longer useful. (Bug#55330)
+
+2022-05-09 Arash Esbati <arash@gnu.org>
+
+ Update AUCTeX FAQ entry
+
+ * doc/misc/efaq-w32.texi (AUCTeX): AUCTeX project isn't providing
+ pre-compiled versions for Windows anymore (bug#55330).
+
+2022-05-09 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Update string-to-number documentation to bignum Emacs
+
+ * doc/lispref/strings.texi (String Conversion): string-to-number
+ no longer converts integers to floating point numbers (bug#55334).
+
+2022-05-09 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix doc string references to tags-loop-continue
+
+ * lisp/vc/vc-dir.el (vc-dir-search, vc-dir-query-replace-regexp):
+ Fix reference to obsolete tags-loop-continue (bug#55311).
+
+2022-05-08 Visuwesh M <visuweshm@gmail.com>
+
+ dired-do-query-replace-regexp doc string fix
+
+ * lisp/dired-aux.el (dired-do-query-replace-regexp): Refer
+ 'fileloop-continue' instead of the obsolete command
+ 'tags-loop-continue'. (Bug#55311)
+
+ (cherry picked from commit 4c505203f9171886f47638779326e257a95a1d79)
+
+2022-05-08 Alan Mackenzie <acm@muc.de>
+
+ Linux console: don't translate ESC TAB to `backtab' in input-decode-map.
+
+ This translation happened after the terminfo entry for <shift>TAB in the linux
+ section was changed to kcbt=\E^I in ncurses version 6.3.
+
+ * lisp/term/linux.el (terminal-init-linux): Add a define-key form to remove
+ the entry for "\e\t" from input-decode-map.
+
+ * etc/PROBLEMS: Add a new section under "character terminals" about S-TAB
+ wrongly doing the same thing as M-TAB, giving tips about amending the Linux
+ keyboard layout.
+
+2022-05-08 Michael Albinus <michael.albinus@gmx.de>
+
+ Handle changed scp protocol in Tramp, don't merge
+
+ * lisp/net/tramp-sh.el (tramp-scp-force-scp-protocol): New defvar.
+ (tramp-scp-force-scp-protocol): New defun.
+ (tramp-do-copy-or-rename-file-out-of-band): Use it.
+ (tramp-methods) <scp, scpx>: Use "%y".
+
+ * lisp/net/tramp.el (tramp-methods): Adapt docstring.
+
+2022-05-06 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix bug#55274
+
+ * lisp/dired-aux.el (dired-do-compress-to): Use `file-local-name'
+ for shell out-file. (Bug#55274)
+
+2022-05-06 Eli Zaretskii <eliz@gnu.org>
+
+ Provide reference for OTF tags in the ELisp manual
+
+ * doc/lispref/display.texi (Low-Level Font): Provide the canonical
+ reference URL for OTF tags.
+
+2022-05-05 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Be more resilient towards errors during error handling
+
+ * src/print.c (print_error_message): Avoid infinite recursion if
+ `substitute-command-keys' bugs out (bug#55269).
+
+ (cherry picked from commit 8364f058b821eba31f84dcded175cca403a965a5)
+
+2022-04-28 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of font- and face-related attribute functions
+
+ * lisp/faces.el (face-attribute):
+ * src/xfaces.c (Fx_family_fonts):
+ * src/font.c (Ffont_get, Ffont_put): Improve and clarify the doc
+ strings.
+
+ * doc/lispref/display.texi (Low-Level Font): Document the :type
+ attribute of a font. Improve documentation of 'font-get' and
+ 'font-put'.
+ (Attribute Functions): Add cross-reference to the description of
+ face attributes.
+
+2022-04-25 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.3-3-gd54104
+
+2022-04-24 Eli Zaretskii <eliz@gnu.org>
+
+ Improve indexing in "Programmed Completion"
+
+ * doc/lispref/minibuf.texi (Programmed Completion): Improve
+ indexing. (Bug#55095)
+
+2022-04-24 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of 'set-fontset-font'
+
+ * doc/lispref/display.texi (Fontsets):
+ * src/fontset.c (Fset_fontset_font): Improve and clarify the
+ documentation of 'set-fontset-font'. Rename the arguments to be
+ more self-explanatory. (Bug#55086)
+
+2022-04-23 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix problem with Solaris ls in Tramp
+
+ * lisp/net/tramp-sh.el (tramp-sunos-unames): Move up.
+ (tramp-sh--quoting-style-options): Handle erroneous Solaris ls.
+
+2022-04-22 Eli Zaretskii <eliz@gnu.org>
+
+ Another fix for non-ASCII 'overlay-arrow-string'
+
+ * src/xdisp.c (get_overlay_arrow_glyph_row): Fix yet another place
+ that assumed each character is a single byte.
+
+2022-04-21 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid a redisplay loop when 'overlay-arrow-string' is non-ASCII
+
+ * src/xdisp.c (get_overlay_arrow_glyph_row): Don't assume every
+ character in 'overlay-arrow-string' is one byte long. Reported by
+ Yuri D'Elia <wavexx@thregr.org>.
+
+2022-04-21 Eli Zaretskii <eliz@gnu.org>
+
+ Add minimum instructions to 'query-replace' commands
+
+ * lisp/vc/vc-dir.el (vc-dir-query-replace-regexp):
+ * lisp/textmodes/reftex-global.el (reftex-query-replace-document):
+ * lisp/progmodes/project.el (project-query-replace-regexp):
+ * lisp/progmodes/etags.el (tags-query-replace):
+ * lisp/progmodes/ebrowse.el (ebrowse-tags-query-replace):
+ * lisp/isearch.el (isearch-query-replace, isearch-occur):
+ * lisp/emulation/viper-cmd.el (viper-query-replace):
+ * lisp/dired-aux.el (dired-do-query-replace-regexp)
+ (dired-do-find-regexp-and-replace):
+ * lisp/progmodes/xref.el (xref-query-replace-in-results):
+ * lisp/replace.el (query-replace, query-replace-regexp)
+ (query-replace-regexp-eval, map-query-replace-regexp): Add minimal
+ instructions for dealing with matches, with a link to the command
+ that shows the full instructions. (Bug#55050)
+
+2022-04-21 Eli Zaretskii <eliz@gnu.org>
+
+ Fix customization-group of 'python-forward-sexp-function'
+
+ * lisp/progmodes/python.el (python-forward-sexp-function): Make it
+ be part of both 'python' and 'python-flymake' groups. (Bug#55027)
+ Do not merge to master.
+
+2022-04-20 Paul Eggert <eggert@cs.ucla.edu>
+
+ Update from gnulib
+
+ (cherry picked from commit 992cf3cb675e074079341cc54c3b16d37a8b9ca8)
+
+ This is a partial backport from master: it only includes the changes below.
+
+ * lib/mini-gmp.c (gmp_assert_nocarry): Avoid many Clang
+ unused-variable warnings when building with optimisation.
+ * lib/verify.h (_GL_HAVE__STATIC_ASSERT): Modify condition for using
+ _Static_assert to cope with older Apple builds of Clang exposing
+ misleading compiler version numbers. See discussion starting at
+ https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00779.html
+
+2022-04-20 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert prompting changes in viper-cmd
+
+ * lisp/emulation/viper-cmd.el (viper-quote-region)
+ (viper-read-string-with-history, viper-query-replace): Revert
+ prompting changes done in 50512e3 -- the way viper prompts in
+ command mode is special (bug#55007).
+
+ Do not merge to master.
+
+2022-04-19 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix regression with multiple mode: entries in the prop line
+
+ * lisp/files.el (hack-local-variables): Fix regression with multiple
+ mode: entries in the prop line.
+
+ Do not merge to master.
+
+2022-04-18 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Avoid hangs in python-mode with debug-on-error set
+
+ * lisp/progmodes/python.el (python-nav-end-of-statement): Avoid
+ using cl-assert here, because this is called from the font-lock
+ machinery, and if debug-on-error is set here, we'll hang Emacs
+ (bug#54996).
+
+ Do not merge to master.
+
+2022-04-18 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix major-mode setting regression when there's a mode: cookie
+
+ * lisp/files.el (hack-local-variables): Fix regression in setting
+ the major mode when there are mode: cookies in the file (bug#54993).
+
+ Do not merge to master.
+
+2022-04-17 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-38-g682ccd
+
+2022-04-17 Eli Zaretskii <eliz@gnu.org>
+
+ Revert "Don’t assume openat"
+
+ This reverts commit 3cccf0a9107d585173e527550bbc45253624ca2e.
+
+ This is a change with far-reaching effects on MS-Windows at the least,
+ where file-related APIs are shadowed to support transparent support
+ for UTF-8 encoded file names. Making such changes on a stable branch
+ for the benefit of a proprietary platform with a 13-year old OS is a
+ tail wagging the dog. Please don't do that without discussing first.
+
+2022-04-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Don’t assume openat
+
+ Use openat only on platforms with O_PATH.
+ This ports to OS X 10.9 and earlier.
+ Problem reported by Keith David Bershatsky in:
+ https://lists.gnu.org/r/emacs-devel/2022-04/msg00805.html
+ * lib-src/emacsclient.c (local_sockname): Use open, not openat.
+ * src/sysdep.c (sys_openat): New static function,
+ which uses openat only if O_PATH is defined.
+ (emacs_openat): Use it instead of openat.
+ (emacs_openat_noquit): Remove.
+ (emacs_open_noquit): Reimplement as per the old emacs_openat_noquit,
+ but use plain 'open'.
+
+2022-04-17 Paul Eggert <eggert@cs.ucla.edu>
+
+ Fix GC bug in filelock.c
+
+ Fix a bug where if GC occurred at the wrong moment when locking a
+ file, the lock file’s name was trashed so file locking did not work.
+ This bug was introduced in Emacs 28.1. The bug sometimes caused
+ filelock-tests-detect-external-change test failures on Fedora 35
+ x86-64 in an en_US.utf8 locale.
+ * src/filelock.c (lock_file_1, current_lock_owner, lock_if_free)
+ (lock_file, unlock_file, Ffile_locked_p):
+ Use Lisp_Object, not char *, for string, so that GC doesn’t trash
+ string contents.
+ (make_lock_file_name): Return the encoded name, not the original.
+ All callers changed.
+
+2022-04-16 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Clarify when mode tagging is used
+
+ * etc/NEWS: Clarify when mode tagging is used (bug#54964).
+
+2022-04-16 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Further vcs-cvs/rcs-responsible-p updates from master
+
+ * lisp/vc/vc-bzr.el (vc-bzr-responsible-p):
+ * lisp/vc/vc-sccs.el (vc-sccs-responsible-p):
+ * lisp/vc/vc-dav.el (vc-dav-responsible-p): Update doc string.
+
+ * lisp/vc/vc-rcs.el (vc-rcs-responsible-p):
+ * lisp/vc/vc-cvs.el (vc-cvs-responsible-p): Further fixes from
+ master.
+
+ * lisp/vc/vc-src.el (vc-src-responsible-p): Return the directory.
+
+ * lisp/vc/vc.el: Update comments.
+
+2022-04-16 Mattias Engdegård <mattiase@acm.org>
+
+ Fix builds on older versions of macOS
+
+ This adds back macOS-specific code replaced earlier (bug#48548),
+ specifically to fix build errors on macOS 10.7.5. See discussion at
+ https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00779.html .
+
+ * src/sysdep.c (HAVE_RUSAGE_INFO_CURRENT, HAVE_PROC_PIDINFO): New.
+ (system_process_attributes): Use alternative code or exclude features
+ when building on older macOS versions.
+
+2022-04-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix documentation of Outline minor mode options
+
+ * lisp/outline.el (outline-minor-mode-cycle-filter)
+ (outline-minor-mode-cycle, outline-minor-mode-highlight)
+ (outline-cycle, outline-cycle-buffer): Doc fixes. (Bug#54967)
+
+2022-04-15 Eli Zaretskii <eliz@gnu.org>
+
+ Improve discoverability of 'insert-directory-program'
+
+ * lisp/files.el (insert-directory-program): Mention 'dired' in the
+ doc string.
+ * lisp/dired.el (dired): Mention 'insert-directory-program' in the
+ doc string. (Bug#54962)
+
+2022-04-15 Eli Zaretskii <eliz@gnu.org>
+
+ Fix cursor motion under truncate-lines with Flymake fringe indicator
+
+ * src/indent.c (Fvertical_motion): Don't consider fringe bitmaps
+ as "images" for the purpose of vertical-motion logic dealing with
+ overshooting buffer positions. (Bug#54946)
+
+2022-04-14 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Make all vc-*-responsible-p functions return a string
+
+ * lisp/vc/vc-sccs.el (vc-sccs-responsible-p):
+ * lisp/vc/vc-rcs.el (vc-rcs-responsible-p):
+ * lisp/vc/vc-dav.el (vc-dav-responsible-p):
+ * lisp/vc/vc-cvs.el (vc-cvs-responsible-p): Return a file name
+ instead of t when we get a match (which is what
+ vc-backend-for-registration expects) (bug#51800).
+
+ This fixes the regression reported in bug#54935.
+
+ Do not merge to master.
+
+2022-04-14 Eli Zaretskii <eliz@gnu.org>
+
+ Describe problems with invoking Python on MS-Windows
+
+ * etc/PROBLEMS: Describe problems with running an inferior Python
+ interpreter due to the MS-Windows "App Execution Aliases" feature.
+ (Bug#54860)
+
+2022-04-13 Eli Zaretskii <eliz@gnu.org>
+
+ A better fix for bug#54800
+
+ * lisp/calc/calc.el (calc-align-stack-window): Improve scrolling
+ when windows have non-integral dimensions.
+
+2022-04-13 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Add a comment about cl-concatenate
+
+ * lisp/emacs-lisp/cl-extra.el (cl-concatenate): Add a comment.
+
+2022-04-13 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert "Make cl-concatenate an alias of seq-concatenate"
+
+ This reverts commit 78f76fe16e2737b40694f82af28d17a90a21ed7b.
+
+ The commit made calls to cl-concatenate bug out, since
+ autoloading defalises doesn't work very well (bug#54901).
+
+2022-04-12 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'window-text-pixel-width' when starting from display property
+
+ * src/xdisp.c (Fwindow_text_pixel_size): Handle the case where
+ there's a display property at START, and move_it_to overshoots.
+ Do not merge to master. (Bug#54862)
+
+2022-04-11 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp/gnus/mm-encode.el (mm-default-file-encoding): Fix "when" arg
+
+2022-04-11 Eli Zaretskii <eliz@gnu.org>
+
+ Fix default-directory of buffers visiting files in renamed directories
+
+ * lisp/dired-aux.el (dired-rename-file): Take note of whether FILE
+ is a directory before it is renamed, which makes it impossible to
+ determine if it was a directory.
+ (dired-rename-subdir, dired-rename-subdir-1): Revert to using
+ dired-in-this-tree-p instead of file-in-directory-p, for the
+ benefit of files that were renamed/removed, because
+ file-in-directory-p returns nil in those cases. (Bug#54838)
+
+2022-04-11 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix a kill-append regression
+
+ * lisp/simple.el (kill-append): Fix a regression when
+ kill-ring-max is zero (bug#54842).
+
+2022-04-10 Eli Zaretskii <eliz@gnu.org>
+
+ * doc/misc/eww.texi (Advanced): Correct outdated info (bug#54839).
+
+2022-04-10 Eli Zaretskii <eliz@gnu.org>
+
+ Clean up the MSDOS port
+
+ * src/msdos.h (tcdrain): Redirect to '_dos_commit'.
+ (openat, fchmodat, futimens, utimensat): Add prototypes.
+
+ * msdos/sed1v2.inp (MAKE_PDUMPER_FINGERPRINT): Fix indentation, so
+ that Make won't consider this line a command.
+ ($(etc)/DOC): Chdir back to ../src, since "make-docfile -d" leaves
+ us in a wrong directory.
+ * msdos/sedlibmk.inp (GL_GNULIB_GETRANDOM, GL_GNULIB_MEMMEM)
+ (GL_GNULIB_SIGDESCR_NP): Define to 1, to get the prototypes from
+ Gnulib headers.
+
+2022-04-10 Daniel Martín <mardani29@yahoo.es>
+
+ Fix typo in next-error-find-buffer-function
+
+ * lisp/simple.el (next-error-find-buffer-function): Fix typo
+ (bug#54830).
+
+2022-04-10 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert "Make shell-resync-dirs handle whitespace in directory names"
+
+ This reverts commit 90e65c826fab2092ad2099d7763538194c93e021.
+
+ This change led to hangs (bug#54776).
+
+ Do not merge to master; it has been fixed in a more encompassing way there.
+
+2022-04-09 Eli Zaretskii <eliz@gnu.org>
+
+ Fix scrolling of the stack window in Calc
+
+ * lisp/calc/calc.el (calc-align-stack-window): Fix off-by-one
+ error in computing the window-start point. (Bug#54800)
+
+2022-04-08 Eli Zaretskii <eliz@gnu.org>
+
+ Update and fix instructions and scripts for updating the Web pages
+
+ * admin/admin.el (manual-html-fix-index-2): Support Texinfo 6.8
+ and later by not converting TOC menus into tables. (Bug#49719)
+ * admin/upload-manuals (New directory): Invoke "cvs add" in
+ $webdir, to pick up the correct CVSROOT.
+ * admin/make-tarball.txt: Update the section about the Emacs Web
+ pages.
+
+ * etc/refcards/Makefile (pl-refcard.dvi): If mex.fmt cannot be
+ found, invoke 'mex' instead of 'tex'.
+
+2022-04-08 Michael Albinus <michael.albinus@gmx.de>
+
+ Extend tramp-archive-test45-auto-load
+
+ * test/lisp/net/tramp-archive-tests.el (tramp-archive-test45-auto-load):
+ Extend test.
+
+2022-04-08 Michael Albinus <michael.albinus@gmx.de>
+
+ Ensure local `default-directory' in Tramp when needed
+
+ * lisp/net/tramp.el (tramp-process-running-p): Ensure local
+ `default-directory' when calling `list-system-processes' and
+ `process-attributes'.
+
+2022-04-08 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify "idleness" in the ELisp manual
+
+ * doc/lispref/os.texi (Idle Timers): Clarify that waiting for
+ input with timeout doesn't make Emacs idle. Suggested by Ignacio
+ <ignaciocasso@hotmail.com>. (Bug#54371)
+
+2022-04-07 Jürgen Hötzel <juergen@archlinux.org>
+
+ Use correct signal oldset in posix_spawn implementation
+
+ posix_spawn was restoring the wrong signal set, which still had
+ SIGCHLD and SIGINT masked, causing problems with child processes that
+ spawned child processes. (Bug#54667)
+
+ See the thread ending at
+ https://lists.gnu.org/archive/html/emacs-devel/2022-03/msg00067.html
+ for more details.
+
+ * src/callproc.c (emacs_spawn): Pass oldset parameter.
+ (emacs_posix_spawn_init_attributes): Use correct oldset.
+ (emacs_posix_spawn_init): Remove intermediate function.
+
+ (cherry picked from commit 8103b060d89ac63a12c439087bd46c30da72cd97)
+
+2022-04-07 Felix Dietrich <felix.dietrich@sperrhaken.name> (tiny change)
+
+ Fix error in tramp-archive-autoload-file-name-handler
+
+ * lisp/net/tramp-archive.el (tramp-archive-autoload-file-name-handler):
+ Always call `tramp-autoload-file-name'. Otherwise, when
+ `tramp-archive-enabled’ is nil and
+ `tramp-archive-autoload-file-name-handler’ is in the
+ `file-name-handler-alist’ results in an error “Invalid handler in
+ `file-name-handler-alist” once Emacs calls
+ `tramp-archive-autoload-file-name-handler’ with a handler that
+ does not expect nil. Always returning nil is also false in
+ general.
+
+2022-04-07 Michael Albinus <michael.albinus@gmx.de>
+
+ Commit missing file from previous commit (Do not merge with master)
+
+ Commit missing file from previous commit
+
+2022-04-07 Michael Albinus <michael.albinus@gmx.de>
+
+ Merge with Tramp 2.5.2.3 (Do not merge with master)
+
+ * doc/misc/tramp.texi (Archive file names): Explicitly say how to
+ open an archive with Tramp (Bug#25076).
+
+ * doc/misc/trampver.texi:
+ * lisp/net/trampver.el: Change version to "2.5.3-pre".
+
+ * 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 implementation. (Bug#53854)
+
+ * lisp/net/tramp-adb.el (tramp-adb-tolerate-tilde):
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-tolerate-tilde):
+ New defuns. Advice `shell-mode' with them.
+
+ * lisp/net/tramp.el (tramp-register-autoload-file-name-handlers):
+ * lisp/net/tramp-archive.el (tramp-register-archive-file-name-handler):
+ Check, whether the real file name handler is already registered.
+ rules. (Bug#54542)
+
+ * lisp/net/tramp.el (tramp-autoload-file-name-handler)
+ (tramp-register-autoload-file-name-handlers)
+ (tramp-unload-file-name-handlers, tramp-unload-tramp):
+ * lisp/net/tramp-archive.el (tramp-archive-autoload-file-name-regexp)
+ (tramp-archive-autoload-file-name-handler)
+ (tramp-register-archive-file-name-handler):
+ Add `tramp-autoload' property.
+
+ * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist):
+ * lisp/net/tramp-rclone.el (tramp-rclone-file-name-handler-alist):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-file-name-handler-alist):
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-file-name-handler-alist):
+ Use `tramp-handle-file-notify-add-watch',
+ `tramp-handle-file-notify-rm-watch' and
+ `tramp-handle-file-notify-valid-p'.
+
+ * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist):
+ Use `tramp-handle-insert-file-contents'.
+
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection):
+ * lisp/net/tramp-rclone.el (tramp-rclone-maybe-open-connection):
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-maybe-open-connection):
+ * lisp/net/tramp-sudoedit.el
+ (tramp-sudoedit-maybe-open-connection): Do not set "lock-pid"
+ connection-property.
+ (tramp-sudoedit-handle-delete-file): Use "rm -f".
+
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-executable-p):
+ * lisp/net/tramp-sh.el (tramp-sh-handle-file-executable-p):
+ Check also for setuid/setgid bit.
+ (tramp-gvfs-handle-expand-file-name):
+ Respect `tramp-tolerate-tilde'.
+
+ * lisp/net/tramp-sh.el (tramp-sh-handle-insert-directory):
+ * lisp/net/tramp-smb.el (tramp-smb-handle-insert-directory):
+ Do not modify disk space information when
+ `dired--insert-disk-space' is available. (Bug#54512)
+
+ * lisp/net/tramp-sh.el (tramp-maybe-open-connection): Extend suppression
+ (tramp-get-remote-dev-tty): New defun.
+ (tramp-sh-handle-make-process): Use it.
+
+ * lisp/net/tramp-sshfs.el (tramp-methods) <sshfs>:
+ Add "-t -t" to `tramp-login-args'.
+ Add "-o dir_cache=no" to `tramp-mount-args'. (Bug#54126)
+ Add "-o transform_symlinks" to `tramp-mount-args'.
+ (tramp-sshfs-file-name-handler-alist):
+ Use `tramp-sshfs-handle-file-writable-p'.
+ (tramp-sshfs-handle-file-writable-p): New defun. (Bug#54130)
+ (tramp-sshfs-handle-write-region): Set file modification time.
+ (Bug#54016)
+ (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--test-expensive-test-p):
+ Rename from `tramp--test-expensive-test'. Make it a defun. Adapt
+ all callees.
+ (tramp-test07-file-exists-p, tramp-test14-delete-directory)
+ (tramp-test18-file-attributes, tramp-test20-file-modes)
+ (tramp-test28-process-file, tramp-test29-start-file-process)
+ (tramp-test30-make-process, tramp-test32-shell-command)
+ (tramp-test33-environment-variables, tramp--test-check-files)
+ (tramp--test-special-characters, tramp-test46-unload): Adapt tests.
+ (tramp-test39-detect-external-change): New test.
+ (tramp-test29-start-file-process)
+ (tramp--test--deftest-direct-async-process)
+ (tramp-test30-make-process, tramp-test31-interrupt-process)
+ (tramp-test34-explicit-shell-file-name)
+ (tramp-test44-asynchronous-requests):
+ Add :tramp-asynchronous-processes tag.
+ (tramp--test-asynchronous-processes-p): New defun.
+ (tramp--test-hpux-p, tramp--test-macos-p): Protect against errors.
+
+2022-04-06 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ cl-generic.el: Fix bug#46722
+
+ Fix longstanding bug due to unexpected interference via side-effect.
+
+ * lisp/emacs-lisp/cl-generic.el (cl--generic-get-dispatcher):
+ Copy the `dispatch` arg before storing it into the hash-table.
+
+ Backport from `master` (cherrypick from commit 61f8f7f68f).
+
+2022-04-05 Eli Zaretskii <eliz@gnu.org>
+
+ Fix fallout from lexical-binding in vhdl-mode.el
+
+ * lisp/progmodes/vhdl-mode.el (vhdl-update-sensitivity-list): Fix
+ production of a list with embedded function calls. (Bug#54730)
+
+2022-04-03 Eli Zaretskii <eliz@gnu.org>
+
+ Update logs and HISTORY for Emacs 28.1
+
+ * ChangeLog.3:
+ * etc/HISTORY:
+ * etc/AUTHORS: Update for Emacs 28.1 release.
+
+2022-04-03 Eli Zaretskii <eliz@gnu.org>
+
+ Bump Emacs version to 28.1
+
+ * README:
+ * configure.ac:
+ * nt/README.W32:
+ * msdos/sed2v2.inp: Bump Emacs version to 28.1
+
+2022-03-30 Tassilo Horn <tsdh@gnu.org>
+
+ dired: implement feature from 7b50ed553f differently
+
+ * lisp/dired.el (dired-buffers-for-dir): Restore to emacs-27 version.
+ (dired-buffers-for-dir-or-subdir): New function.
+ (dired-clean-up-after-deletion): Use dired-buffers-for-dir-or-subdir
+ instead dired-buffers-for-dir.
+
+2022-03-30 Eli Zaretskii <eliz@gnu.org>
+
+ Fix regression in 'dired-buffers-for-dir'
+
+ * lisp/dired.el (dired-buffers-for-dir): Fix inadvertently swapped
+ arguments. (Bug#54636)
+
+2022-03-27 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/desktop.el (desktop-read): Clarify warning text.
+
+2022-03-26 Po Lu <luangruo@yahoo.com>
+
+ * doc/emacs/anti.texi (Antinews): Unannounce removal of Motif.
+
+2022-03-25 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix eshell-explicit-command-char doc string typo
+
+ * lisp/eshell/esh-ext.el (eshell-explicit-command-char): Fix typo
+ in doc string (bug#54567).
+
+2022-03-24 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify the description of "selected tags table"
+
+ * doc/emacs/maintaining.texi (Select Tags Table): Clarify the
+ distinction between the "selected tags table" and the "current
+ list of tags tables". (Bug#54543)
+
+2022-03-21 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Add notes about command modes and nativecomp interaction
+
+ * doc/lispref/commands.texi (Command Modes): Note interaction with
+ native-compile (bug#54437).
+
+ * src/data.c: Add comment about not being supported.
+
+ Do not merge to master.
+
+2022-03-20 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-25-gaf6f12
+
+2022-03-20 Eli Zaretskii <eliz@gnu.org>
+
+ Improve doc strings of read-char-from-minibuffer-insert-* commands
+
+ * lisp/subr.el (read-char-from-minibuffer-insert-char)
+ (read-char-from-minibuffer-insert-other): Clarify the doc strings.
+ (Bug#54479)
+
+2022-03-19 Eli Zaretskii <eliz@gnu.org>
+
+ Fix region highlight in non-selected windows
+
+ * src/xdisp.c (prepare_menu_bars): Include in the windows passed
+ to pre-redisplay-functions windows whose point was moved from the
+ last recorded position. (Bug#54450)
+
+2022-03-18 Eli Zaretskii <eliz@gnu.org>
+
+ Fix a regression in 'decipher-digram-list'
+
+ * lisp/play/decipher.el (decipher-stats-buffer): Don't assume the
+ statistics buffer always exists. (Bug#54443)
+
+2022-03-17 Karl Fogel <kfogel@red-bean.com>
+
+ Improve documentation of bookmark default sorting
+
+ * lisp/bookmark.el (bookmark-alist, bookmark-store,
+ bookmark-maybe-sort-alist): Update doc strings and comments.
+
+2022-03-15 Juri Linkov <juri@linkov.net>
+
+ * doc/misc/transient.texi: Fix @dircategory to "Emacs misc features" for dir.
+
+2022-03-13 Jim Porter <jporterbugs@gmail.com>
+
+ Fix evaluation of negated argument predicates in Eshell
+
+ * lisp/eshell/em-pred.el (eshell-add-pred-func): Let-bind 'pred' so
+ the lambdas see the original value (bug#54369).
+
+ Committed on the wrong branch.
+
+ Do not merge to master.
+
+2022-03-12 Eli Zaretskii <eliz@gnu.org>
+
+ Emacs pretest 28.0.92
+
+ * README:
+ * configure.ac:
+ * nt/README.W32:
+ * msdos/sed2v2.inp: Bump Emacs version to 28.0.92.
+
+ * etc/AUTHORS:
+ * lisp/ldefs-boot.el: Update for pretest 28.0.92.
+
+ * ChangeLog.3: Regenerate.
+
+2022-03-10 Eli Zaretskii <eliz@gnu.org>
+
+ Fix regression in 'custom-prompt-customize-unsaved-options'
+
+ * lisp/cus-edit.el (custom-prompt-customize-unsaved-options):
+ Don't depend on the value returned by 'customize-unsaved'. Fix
+ the doc string. Patch by Sebastian Miele <iota@whxvd.name>.
+ (Bug#54329)
+
+2022-03-10 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of 'map-charset-chars'
+
+ * doc/lispref/nonascii.texi (Character Sets):
+ * src/charset.c (Fmap_charset_chars): Clarify the codepoint issue
+ in using 'map-charset-chars'.
+
+2022-03-08 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid assertion violations in 'bidi_resolve_brackets'
+
+ * src/bidi.c (bidi_resolve_brackets): Move assertion to where it
+ really matters. (Bug#54295)
+
+2022-03-07 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix which-func-update doc string
+
+ * lisp/progmodes/which-func.el (which-func-update): Make the doc
+ string match the code (bug#54288).
+
+2022-03-07 Eli Zaretskii <eliz@gnu.org>
+
+ Improve wording of 'dired-jump's description
+
+ * doc/emacs/dired.texi (Dired Enter): Clarify wording. Reported
+ by Natalie <batalie@riseup.net>.
+
+2022-03-06 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Add a comment for previous browse-url-of-dired-file change
+
+ * lisp/net/browse-url.el (browse-url-of-dired-file): Add a comment
+ for previous change.
+
+2022-03-06 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Restore documented Emacs 27.2 behaviour of browse-url-of-dired-file
+
+ * lisp/net/browse-url.el (browse-url-of-dired-file): Restore the
+ documented behaviour -- open a web browser instead of passing to
+ the various handlers.
+
+2022-03-06 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-24-g668205
+
+2022-03-05 Andreas Schwab <schwab@linux-m68k.org>
+
+ * lib-src/seccomp-filter.c (main): Use faccessat2 only if defined.
+
+2022-03-04 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix regression in derived-mode-init-mode-variables
+
+ * lisp/emacs-lisp/derived.el (derived-mode-init-mode-variables):
+ Fix regression caused by lexical-binding derived.el (bug#54240).
+
+2022-03-03 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid crashes when fringe bitmaps are defined in daemon mode
+
+ * src/dispextern.h (gui_define_fringe_bitmap): Add prototype.
+ (max_used_fringe_bitmap): Add declaration.
+ * src/fringe.c (gui_define_fringe_bitmap): New function.
+ * src/w32term.c (w32_draw_fringe_bitmap):
+ * src/xterm.c (x_draw_fringe_bitmap) [USE_CAIRO]: Call
+ 'gui_define_fringe_bitmap' if the terminal-specific bitmap data is
+ not available when a fringe bitmap is about to be drawn. Don't
+ try to draw a bitmap that is not known to fringe.c. (Bug#54183)
+
+2022-03-03 Eli Zaretskii <eliz@gnu.org>
+
+ One more fix of the BPA implementation
+
+ * src/bidi.c (bidi_find_bracket_pairs): Disable BPA optimization
+ when there are no strong directional characters inside the
+ bracketed pair. (Bug#54219)
+
+2022-03-03 Eli Zaretskii <eliz@gnu.org>
+
+ Fix handling of brackets in BPA
+
+ * src/bidi.c (bidi_resolve_brackets): Fix implementation of UBA's
+ N0 rule when there are no strong directional characters inside the
+ bracketed pair. (Bug#54219)
+
+2022-03-02 Po Lu <luangruo@yahoo.com>
+
+ Correct etc/NEWS entry about bitmapped fonts
+
+ * etc/NEWS: Don't say that bitmap font issues are due to Pango, that's
+ not accurate.
+
+2022-03-01 Jim Porter <jporterbugs@gmail.com>
+
+ Improve/correct documentation about Eshell variable expansion
+
+ * lisp/eshell/esh-var.el: Correct documentation comment.
+ (eshell-parse-variable-ref): Correct docstring.
+
+ * doc/misc/eshell.texi (Dollars Expansion): Add documentation for
+ $"var"/$'var' and $<command> syntaxes.
+
+2022-03-01 Jim Porter <jporterbugs@gmail.com>
+
+ Partially revert b03f74e0f2a578b1580e8b1c368665850ee7f808
+
+ That commit regressed '$<command>' forms in Eshell, due to a
+ limitation/bug in how 'eshell-do-eval' works. This fixes
+ bug#54190.
+
+ * lisp/eshell/esh-var.el (eshell-parse-variable-ref): Quote a lambda.
+
+ * test/lisp/eshell/eshell-tests.el (eshell-test/interp-temp-cmd):
+ New test.
+
+2022-03-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ Backport: Port pre-commit hook to Git 2.35.0
+
+ * build-aux/git-hooks/pre-commit: Use LC_ALL=C grep -E instead of
+ sane_egrep (removed in Git 2.35.0).
+
+ (cherry picked from commit b8a96f055624f86fe965a0d1b7b2495b2db80e63)
+
+2022-02-28 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix :tag for eol in tab-first-completion
+
+ * lisp/indent.el (tab-first-completion): Fix the :tag description
+ (bug#54179).
+
+2022-02-28 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-22-g33543d
+
+2022-02-27 Dmitry Gutov <dgutov@yandex.ru>
+
+ Add explicit '--no-heading' for ripgrep
+
+ * lisp/progmodes/xref.el (xref-search-program-alist):
+ Add explicit '--no-heading' for ripgrep (bug#54177).
+
+2022-02-26 Michael Albinus <michael.albinus@gmx.de>
+
+ Follow OpenSSH changes in Tramp
+
+ * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options):
+ Reimplement. OpenSSH has changed its diagnostics messages.
+
+2022-02-26 Eli Zaretskii <eliz@gnu.org>
+
+ Document better how to reset attributes of faces for new frames
+
+ * doc/lispref/display.texi (Attribute Functions):
+ * lisp/faces.el (set-face-attribute): Explain how to reset an
+ attribute's value for future frames. (Bug#54156)
+
+2022-02-25 Michael Albinus <michael.albinus@gmx.de>
+
+ * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options): Adapt test.
+
+2022-02-24 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Mention flyspell-prog-mode in flyspell-mode doc string
+
+ * lisp/textmodes/flyspell.el (flyspell-mode): Mention
+ flyspell-prog-mode (bug#54131).
+
+2022-02-23 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Reword face-remap-add-relative manual entry
+
+ * doc/lispref/display.texi (Face Remapping): Clarify the
+ face-remap-add-relative (bug#54114).
+
+2022-02-22 Philipp Stephani <phst@google.com>
+
+ Fix indexing of module functions that return enumeration types.
+
+ Return types that consist of more than one word need to be enclosed in
+ braces, see Info node `(texinfo) Typed Functions'. Otherwise they are
+ indexed incorrectly.
+
+ * doc/lispref/internals.texi (Module Misc, Module Nonlocal): Enclose
+ multi-word return types in braces.
+
+2022-02-22 Eli Zaretskii <eliz@gnu.org>
+
+ * doc/misc/transient.texi (Other Options): Fix a @ref. (Bug#54108)
+
+2022-02-22 Glenn Morris <rgm@gnu.org>
+
+ tramp.texi texinfo 4.13 compatibility
+
+ * doc/misc/tramp.texi (Frequently Asked Questions):
+ Restore compatibility with Texinfo < 5.
+
+2022-02-22 Michael Albinus <michael.albinus@gmx.de>
+
+ Explain "Tramp" spelling in its manual
+
+ * doc/misc/tramp.texi (Frequently Asked Questions):
+ Explain "Tramp" spelling.
+
+2022-02-21 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'display-line-numbers-mode' in hide-show buffers
+
+ * src/xdisp.c (redisplay_internal): Disable redisplay
+ optimizations that consider just the current line, when
+ 'display-line-numbers-mode' is turned on in the buffer.
+ (Bug#54091)
+
+2022-02-21 Martin Rudalics <rudalics@gmx.at>
+
+ Don't check whether a deleted window is deletable (Bug#54028)
+
+ * lisp/window.el (window-state-put): Make sure window is live
+ before calling 'window-deletable-p' on it (Bug#54028).
+
+2022-02-21 Eli Zaretskii <eliz@gnu.org>
+
+ A friendlier error message from image-mode in an empty buffer
+
+ * lisp/image-mode.el (image-mode): Handle the case where the empty
+ buffer doesn't visit a file (Bug#54084)
+
+2022-02-20 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-17-gea6b74
+
+2022-02-18 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of filling and justification commands
+
+ * doc/lispref/text.texi (Filling):
+ * lisp/textmodes/fill.el (fill-region-as-paragraph)
+ (default-justification, set-justification, justify-current-line):
+ Clarify "canonicalization" of spaces and the meaning of
+ justification styles. (Bug#54047)
+ (set-justification-left, set-justification-right)
+ (set-justification-full): Improve wording of doc strings.
+
+2022-02-18 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/progmodes/subword.el (superword-mode): Doc fix. (Bug#54045)
+
+2022-02-17 Philipp Stephani <phst@google.com>
+
+ Fix indexing of module functions that return complex types.
+
+ Return types that consist of more than one word need to be enclosed in
+ braces, see Info node `(texinfo) Typed Functions'. Otherwise they are
+ indexed incorrectly.
+
+ * doc/lispref/internals.texi (Module Values): Enclose multi-word
+ return types in braces.
+
+2022-02-17 Po Lu <luangruo@yahoo.com>
+
+ Prevent crashes caused by invalid locale coding systems
+
+ * src/xterm.c (handle_one_xevent): Prevent a signal inside
+ `setup_coding_system' which crashes recent versions of GLib if
+ the locale coding system is invalid.
+
+ Do not merge to master.
+
+2022-02-15 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix problem with popd for in remote shell buffers
+
+ * lisp/shell.el (shell-prefixed-directory-name):
+ Use `file-local-name' for DIR. (Bug#53927)
+
+2022-02-15 Jonas Bernoulli <jonas@bernoul.li>
+
+ Import texi source file for transient manual
+
+ * doc/misc/Makefile.in: Add transient to INFO_COMMON.
+ * doc/misc/transient.texi: New file.
+
+2022-02-13 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-15-gc5ceb6
+
+2022-02-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'exchange-point-and-mark' in 'transient-mark-mode'
+
+ * lisp/simple.el (exchange-point-and-mark): Don't deactivate mark
+ when 'transient-mark-mode' is ON. (Bug#53150)
+
+ (cherry picked from commit 415ed4b42515ff2e6dd9b94e964b479e50c6392e)
+
+2022-02-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix "C-SPC C-SPC" after "C-x C-x"
+
+ * lisp/simple.el (exchange-point-and-mark): Fix what the command
+ does when 'transient-mark-mode' is OFF. (Bug#52896)
+
+ (cherry picked from commit 19c6cad1821eb896b2ddd0f6eab030f0880ea254)
+
+2022-02-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix a typo in fontset.el
+
+ * lisp/international/fontset.el (xlfd-regexp-spacing-subnum): Fix
+ a typo. Reported by Greg A. Woods <woods@robohack.ca>.
+
+2022-02-12 Eli Zaretskii <eliz@gnu.org>
+
+ Note in ELisp manual that too-wide images are truncated
+
+ * doc/lispref/display.texi (Showing Images): Note that images are
+ truncated at the window's edge. (Bug#53952)
+
+2022-02-11 Andrea Corallo <akrl@sdf.org>
+
+ * lisp/mail/emacsbug.el (report-emacs-bug): Report libgccjit status.
+
+ * lisp/startup.el (normal-top-level): Small code move, improve 202d3be873.
+
+2022-02-10 Andrea Corallo <akrl@sdf.org>
+
+ * lisp/startup.el (normal-top-level): Disable native-comp if not available
+
+2022-02-09 Andrea Corallo <akrl@sdf.org>
+
+ Fix integer arithmetic miss-compilation (bug#53451)
+
+ * lisp/emacs-lisp/comp-cstr.el (comp-cstr-set-range-for-arithm):
+ When one of the two sources is negated revert to set dst as
+ number.
+ * test/src/comp-tests.el (comp-tests-type-spec-tests): Add test to
+ verify this is effective.
+
+2022-02-08 Robert Pluim <rpluim@gmail.com>
+
+ Mark flymake as compatible with emacs-26.1
+
+ * lisp/progmodes/flymake.el: Bump package version and set
+ emacs version in Package-Requires to 26.1 (Bug#53853).
+
+2022-02-08 Brian Leung <leungbk@posteo.net>
+
+ flymake: Ensure compatibility with older Emacsen
+
+ * lisp/progmodes/flymake.el (flymake--log-1): Use
+ replace-regexp-in-string instead of Emacs 28's
+ string-replace (bug#53853).
+
+2022-02-07 Eric Abrahamsen <eric@ericabrahamsen.net>
+
+ Don't remove dummy.group from gnus-newsrc-alist on Gnus save
+
+ bug#53352
+
+ * lisp/gnus/gnus-start.el (gnus-gnus-to-quick-newsrc-format): This
+ function was removing dummy.group from the global value of
+ `gnus-newsrc-alist' on save; we only wanted to remove it temporarily.
+
+2022-02-05 Bob Rogers <rogers@rgrjr.com>
+
+ Fix ietf-drums-get-comment doc string
+
+ * lisp/mail/ietf-drums.el (ietf-drums-get-comment): We really return
+ the last comment (bug#53810).
+
+2022-02-05 Daniel Martín <mardani29@yahoo.es>
+
+ Fix typo in display.texi
+
+ * doc/lispref/display.texi (Making Buttons): Fix typo. (Bug#53807)
+
+2022-02-03 Michael Albinus <michael.albinus@gmx.de>
+
+ Revert an erroneous change in tramp-cache.el
+
+ * lisp/net/tramp-cache.el (tramp-get-hash-table):
+ Use `string-match-p' instead of `string-search'. The latter one
+ was introduced by accident. Reported by Kai Tetzlaff <kai@tetzlaff.eu>.
+
+2022-02-02 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of 'emacs-version'
+
+ * doc/emacs/trouble.texi (Checklist): Mention the possibility of
+ invoking 'emacs-version' with a prefix argument.
+
+ * lisp/version.el (emacs-version): Improve doc string. (Bug#53720)
+
+2022-02-01 Michael Albinus <michael.albinus@gmx.de>
+
+ * etc/NEWS: Apply final fixes after proofreading.
+
+2022-01-31 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify documentation of a "face's font"
+
+ * doc/lispref/display.texi (Attribute Functions)
+ (Face Attributes): Clarify that the :font attribute of a face and
+ the font returned by 'face-font' are by default for ASCII
+ characters. (Bug#53664)
+
+2022-01-31 Alan Mackenzie <acm@muc.de>
+
+ Bind Qdebugger to Qdebug in signal_or_quit.
+
+ * src/eval.c (signal_or_quit): Bind the correct variable, Qdebugger (not
+ Vdebugger) to Qdebug in the section for errors in batch jobs.
+ (syms_of_eval): New DEFSYM for Qdebugger.
+
+2022-01-30 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-13-gdd6486
+
+2022-01-30 Eli Zaretskii <eliz@gnu.org>
+
+ Fix regression in Occur Edit mode
+
+ * lisp/replace.el (occur-after-change-function): Fix the algorithm
+ to find the smallest change in some corner cases. (Bug#53598)
+
+2022-01-29 Eli Zaretskii <eliz@gnu.org>
+
+ Fix last change of Malayalam composition rules
+
+ * lisp/language/indian.el (malayalam-composable-pattern):
+ Reinstate. Instead of removing it, add any sequence of
+ Malayalam characters to the existing patterns, so as not
+ to lose the patterns that use ZWJ and ZWNJ. (Bug#53625)
+
+2022-01-29 Eli Zaretskii <eliz@gnu.org>
+
+ Fix rendering of Malayalam script
+
+ * lisp/language/indian.el (malayalam-composable-pattern): Remove.
+ (script-regexp-alist): Remove 'malayalam-composable-pattern'.
+ Instead, pass any sequence of Malayalam codepoints to the shaping
+ engine. (Bug#53625)
+
+2022-01-29 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of Occur mode
+
+ * doc/emacs/search.texi (Other Repeating Search): Improve wording
+ and document Occur Edit mode better.
+
+2022-01-29 Alan Third <alan@idiocy.org>
+
+ Remove debug logging
+
+ * src/nsterm.m ([EmacsView copyRect:to:]): Remove logging as it's no
+ longer required.
+
+2022-01-29 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix error in filelock.c
+
+ * src/filelock.c (lock_file): Move call of file name handler to
+ `Flock_file'. Determine lock_filename only in case
+ create_lockfiles is non-nil. Adapt the rest of the function accordingly.
+ (Flock_file): Do not check for create_lockfiles. Call file name
+ handler if appropriate. (Bug#53207)
+
+2022-01-27 Juri Linkov <juri@linkov.net>
+
+ * lisp/frame.el (clone-frame): Filter out 'parent-id' (bug#51883).
+
+2022-01-26 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Partially revert a fill-region-as-paragraph regression
+
+ * lisp/textmodes/fill.el (fill-region-as-paragraph): Revert
+ e186af261 (bug#53537), because it leads to regressions. (But
+ leave tests in place.)
+
+2022-01-26 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'make_lispy_position' when there's an image at EOB
+
+ * src/xdisp.c (move_it_to): Don't compare IT_CHARPOS with an
+ invalid TO_CHARPOS. (Bug#53546)
+
+2022-01-26 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix copyright-find-copyright when searching from the end
+
+ * lisp/emacs-lisp/copyright.el (copyright-find-copyright): Make
+ the double check also work when searching from the end (bug#7179).
+
+ Do not merge to master.
+
+2022-01-26 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix copyright.el comment and add a test
+
+ * lisp/emacs-lisp/copyright.el (copyright-find-copyright): Fix
+ comment (bug#7179).
+
+ Do not merge to master.
+
+2022-01-24 Philipp Stephani <phst@google.com>
+
+ * configure.ac (LIBSECCOMP): Bump minimum version for faccessat2.
+
+2022-01-24 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Make the `f' command work in image-mode again
+
+ * lisp/image.el (image-show-frame): Protect against not having
+ computed the animation data yed (bug#53489).
+
+2022-01-22 Philipp Stephani <phst@google.com>
+
+ Seccomp: improve support for newer versions of glibc (Bug#51073)
+
+ * lib-src/seccomp-filter.c (main): Allow 'pread64' and 'faccessat2'
+ system calls. Newer versions of glibc use these system call (starting
+ with commits 95c1056962a3f2297c94ce47f0eaf0c5b6563231 and
+ 3d3ab573a5f3071992cbc4f57d50d1d29d55bde2, respectively).
+
+2022-01-21 Thomas Fitzsimmons <fitzsim@fitzsim.org>
+
+ EUDC: Fix a quoting bug in the BBDB backend
+
+ * lisp/net/eudcb-bbdb.el (eudc-bbdb-query-internal): Fix a quoting
+ bug introduced during lexical-binding conversion.
+
+2022-01-21 Sergey Vinokurov <serg.foo@gmail.com>
+
+ Fix memory-report-object-size to initialize memory-report--type-size
+
+ * lisp/emacs-lisp/memory-report.el (memory-report-object-size):
+ Allow using function directly (bug#53310).
+
+ Do not merge to master.
+
+2022-01-20 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ Fix menu-bar mouse clicks in "C-h c" and "C-h k" (bug#53322)
+
+ * lisp/subr.el (event-start, event-end): Handle '(menu-bar)'
+ events.
+ * lisp/net/browse-url.el (browse-url-interactive-arg): Simplify
+ accordingly.
+
+ (cherry picked from commit 9ceb3070e34ad8a54184fd0deda477bf5ff77000)
+
+2022-01-20 Eli Zaretskii <eliz@gnu.org> (tiny change)
+
+ Fix UB in ebrowse
+
+ * lib-src/ebrowse.c (matching_regexp): Avoid writing beyond the
+ limits of 'matching_regexp_buffer'. Patch by Jan Stranik
+ <jan@stranik.org>. (Bug#53333)
+
+2022-01-20 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Fix execute-extended-command-for-buffer in fundamental-mode
+
+ * lisp/simple.el (execute-extended-command-for-buffer): Protect
+ against the current local map being nil (bug#52907).
+
+2022-01-20 Martin Rudalics <rudalics@gmx.at>
+
+ Add workaround to handle a problem with Enlightenment WM (Bug#53298)
+
+ * src/xterm.c (handle_one_xevent): Handle setting of variable
+ 'x_set_frame_visibility_more_laxly' when receiving an Expose or
+ FocusIn event (Bug#53298).
+ (Qexpose): Define symbol.
+ (x_set_frame_visibility_more_laxly): New Lisp variable.
+ * etc/PROBLEMS: Mention frame redraw problem with the
+ Enlightenment WM and 'x-set-frame-visibility-more-laxly'
+ workaround.
+
+2022-01-17 Po Lu <luangruo@yahoo.com>
+
+ 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.
+
+2022-01-17 Andrea Corallo <akrl@sdf.org>
+
+ * 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
+
+2022-01-15 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-9-g7ba24c
+
+2022-01-15 Juri Linkov <juri@linkov.net>
+
+ * lisp/net/dictionary.el (dictionary-context-menu): Use package prefix.
+
+2022-01-15 Philipp Stephani <phst@google.com>
+
+ 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.
+
+2022-01-15 Philipp Stephani <phst@google.com>
+
+ * lisp/indent.el (tab-first-completion): Fix incorrect choices.
+
+2022-01-14 Philipp Stephani <phst@google.com>
+
+ * lisp/simple.el (undo-no-redo): Fix customization group
+
+ * lisp/progmodes/xref.el (xref-file-name-display): Fix docstring.
+
+2022-01-14 Eli Zaretskii <eliz@gnu.org>
+
+ 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)
+
+2022-01-14 Lars Ingebrigtsen <larsi@gnus.org>
+
+ 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.
+
+2022-01-13 Philipp Stephani <phst@google.com>
+
+ Fix Edebug specification for inline functions (Bug#53068).
+
+ * lisp/emacs-lisp/inline.el (inline-quote): Fix Edebug specification.
+
+ * test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-inline): New unit
+ test.
+
+2022-01-13 N. Jackson <nljlistbox2@gmail.com>
+
+ Remove mention of removed `gnus-treat-play-sounds' variable from manual
+
+ * info/gnus.info: Remove `gnus-treat-play-sounds' from
+ manual. According to lisp/gnus/ChangeLog.3 this variable was
+ removed in 2010 (bug#53192).
+
+2022-01-12 Mattias Engdegård <mattiase@acm.org>
+
+ Revert "Fix closure-conversion of shadowed captured lambda-lifted vars"
+
+ This reverts commit 3ec8c8b3ae2359ceb8135b672e86526969c16b7e.
+
+ It was committed to a stable branch without prior discussion;
+ see bug#53071.
+
+2022-01-12 Juri Linkov <juri@linkov.net>
+
+ * doc/lispref/windows.texi (Textual Scrolling): Remove obsolete text.
+
+ Remove text about scrolling the minibuffer from the buffer,
+ obsolete since Emacs 27 (bug#51210).
+
+2022-01-12 Glenn Morris <rgm@gnu.org>
+
+ * lisp/files.el (lock-file-name-transforms): Doc tweaks.
+
+2022-01-12 Mattias Engdegård <mattiase@acm.org>
+
+ Fix closure-conversion of shadowed captured lambda-lifted vars
+
+ Lambda-lifted variables (ones passed explicitly to lambda-lifted
+ functions) that are also captured in an outer closure and shadowed
+ were renamed incorrectly (bug#51982).
+
+ Reported by Paul Pogonyshev.
+
+ * lisp/emacs-lisp/cconv.el (cconv--lifted-arg): New.
+ (cconv-convert): Provide correct definiens for the closed-over
+ variable.
+ * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
+ * test/lisp/emacs-lisp/cconv-tests.el (cconv-tests--intern-all)
+ (cconv-closure-convert-remap-var): Add tests.
+
+ (cherry picked from commit 45252ad8f932c98a373ef0ab7f3363a3e27ccbe4)
+
+2022-01-12 Philipp Stephani <phst@google.com>
+
+ Fix test lisp/cedet/semantic/bovine/gcc-tests on macOS (Bug#52431)
+
+ * test/lisp/cedet/semantic/bovine/gcc-tests.el
+ (semantic-gcc-test-output-parser-this-machine): Also detect Apple
+ clang on macOS Monterey.
+
+ (cherry picked from commit 6e52becfbe2a33c025b8c4838b3c8f06ba5a6fb8)
+
+2022-01-12 Mattias Engdegård <mattiase@acm.org>
+
+ Don't fail flymake-tests if `gcc` actually is Clang
+
+ * test/lisp/progmodes/flymake-tests.el (flymake-tests--gcc-is-clang)
+ (different-diagnostic-types, included-c-header-files): Skip tests that
+ depend on the `gcc` command really being GCC and not Clang.
+
+ (cherry picked from commit b2167d98432a78442522b7564e22f47d75a98b6f)
+
+2022-01-10 Eli Zaretskii <eliz@gnu.org>
+
+ Revert "Remove the filename argument from the command line after an ELC+ELN build"
+
+ This reverts commit ffc047c896413b6e00032518fc934f08768671fa.
+
+ Please don't install anything non-trivial on the release branch
+ without asking first.
+
+2022-01-10 Alan Mackenzie <acm@muc.de>
+
+ Remove the filename argument from the command line after an ELC+ELN build
+
+ This fixes bug #53164. Without this fix, bootstrap-emacs loads the source
+ file uselessly into a buffer after completing the compilation.
+
+2022-01-09 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ (save-some-buffers): Simplify the fix for bug#46374
+
+ * lisp/files.el (save-some-buffers): Only check the
+ `save-some-buffers-function` property on functions from
+ `save-some-buffers-default-predicate` since callers which provide
+ a `pred` argument can arrange to compute `pred` themselves if needed.
+
+ * test/lisp/files-tests.el (files-tests-buffer-offer-save): Don't test
+ with `pred` set to `save-some-buffers-root` since it's not an
+ appropriate function for that any more.
+
+2022-01-09 Stefan Kangas <stefan@marxist.se>
+
+ Improve docstring of edit-abbrevs
+
+ * lisp/abbrev.el (edit-abbrevs): Doc fix; don't use obsolete name.
+ Improve docstring formatting.
+
+2022-01-09 Eli Zaretskii <eliz@gnu.org>
+
+ Revert "Fix alignment on font size change in tabulated-list-mode"
+
+ This reverts commit 2767c89db729a6106146d0aeff76678c64d4fc53.
+
+ That change caused a regression in a much more important use
+ case, see bug#53133.
+
+2022-01-08 Stefan Kangas <stefan@marxist.se>
+
+ Clarify docstring of package-native-compile
+
+ * lisp/emacs-lisp/package.el (package-native-compile): Clarify
+ docstring.
+
+2022-01-08 Eli Zaretskii <eliz@gnu.org>
+
+ Fix Subject "simplification" in Rmail
+
+ * lisp/mail/rmail.el (rmail-simplified-subject): Match against
+ "[external]" _after_ decoding the Subject by RFC-2047.
+
+2022-01-08 Stefan Kangas <stefan@marxist.se>
+
+ Bump Emacs version to 28.0.91
+
+ * README:
+ * configure.ac:
+ * msdos/sed2v2.inp:
+ * nt/README.W32: Bump Emacs version to 28.0.91.
+
+2022-01-05 Dmitry Gutov <dgutov@yandex.ru>
+
+ Fix vc-git with old Git over Tramp and cygwin-mount.el
+
+ * lisp/vc/vc-git.el (vc-git-use-literal-pathspecs): New variable.
+ (vc-git-command, vc-git--call): Use it to determine whether to set
+ GIT_LITERAL_PATHSPECS=1 (bug#51497).
+ (vc-git--literal-pathspec, vc-git--literal-pathspecs): Remove.
+ Update all callers. This reverts the previous solution for bug#39452.
+
+ * lisp/progmodes/project.el (project--vc-list-files):
+ Use the new variable.
+
+2022-01-05 Philipp Stephani <phst@google.com>
+
+ * lisp/emacs-lisp/checkdoc.el (bytecomp): Add missing require
+
+2022-01-02 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid inflooping when 'tab-bar-format' includes embedded newlines
+
+ * src/xdisp.c (tab_bar_height, redisplay_tab_bar): Support
+ 'tab-bar-format' with embedded newlines. (Bug#52947)
+
+2022-01-02 Juri Linkov <juri@linkov.net>
+
+ * lisp/tab-line.el: Revert part of the fix in a6adfe21e4 (bug#52881)
+
+ (tab-line--get-tab-property, tab-line-auto-hscroll): Use get-pos-property
+ instead of get-text-property that fails after previous-single-property-change.
+
+2022-01-02 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify %g and %G time format specs
+
+ * src/timefns.c (Fformat_time_string):
+ * doc/lispref/os.texi (Time Parsing): Clarify %g/%G. (Bug#52934)
+
+2022-01-02 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ (define-char-code-property): Workaround for bug#52945
+
+ * lisp/international/mule-cmds.el (define-char-code-property): Ignore
+ requests to re-setup lazy loading after the char-table is already loaded.
+
+2022-01-01 Eli Zaretskii <eliz@gnu.org>
+
+ Update more copyright years
+
+ * etc/tutorials/TUTORIAL.he (זכויות שימוש):
+ * config.bat: Update Copyright years.
+
+2022-01-01 Michael Albinus <michael.albinus@gmx.de>
+
+ * lisp/net/tramp-sh.el: Adapt copyright year
+
+2022-01-01 Zhehao Lin <zh_lin1@outlook.com> (tiny change)
+
+ * src/xfaces.c (face_for_font): Make 'hash' be uintptr_t.
+
+2021-12-31 Eli Zaretskii <eliz@gnu.org>
+
+ Improve doc strings of fringe indicator variables
+
+ * src/buffer.c (syms_of_buffer): Fix doc strings of
+ 'indicate-empty-lines' and 'indicate-buffer-boundaries'.
+
+2021-12-31 Juri Linkov <juri@linkov.net>
+
+ * lisp/tab-line.el (tab-line--get-tab-property): New function (bug#52881).
+
+ (tab-line-auto-hscroll): Use ‘tab-line--get-tab-property’ instead of
+ ‘get-pos-property 1’, and ‘get-text-property’ instead of
+ ‘get-pos-property’.
+ (tab-line-select-tab, tab-line-close-tab): Use tab-line--get-tab-property.
+
+2021-12-30 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid assertion violations with variable-weight fonts
+
+ * src/font.c (font_score, font_delete_unmatched): Don't assume
+ weight, slant, and width properties of the font must be fixnums:
+ some variable-weight fonts violate that assumption. Reported
+ by Sean Whitton <spwhitton@spwhitton.name>. Do not merge to
+ master. (Bug#52888)
+
+2021-12-30 Eli Zaretskii <eliz@gnu.org>
+
+ Minor improvement in user documentation of completion style
+
+ * doc/emacs/mini.texi (Completion Styles): Add reference to
+ "Completion Variables" in the ELisp manual. (Bug#52901)
+
+2021-12-30 Campbell Barton <ideasman42@gmail.com> (tiny change)
+
+ Fix bug where bookmark-jump used (point), not (point-at-bol)
+
+ This matches changes from e852822f3db469c985bf022651f184d6ff2c518a,
+ regression in 7fe88446c30279285e3171091189b3d1af697c05.
+ * lisp/bookmark.el (bookmark--jump-via): Look at overlays at BOL.
+ Otherwise the fringe bookmark indication is not deleted with the
+ bookmark.
+
+2021-12-29 Alan Mackenzie <acm@muc.de>
+
+ CC Mode: c-update-brace-stack: After struct foo *, do not expect a brace.
+
+ This fixes bug #52796.
+
+ * lisp/progmodes/cc-engine.el (c-update-brace-stack): Handle a "*" like a
+ semicolon, cancelling the expectation of a brace.
+
+ * lisp/progmodes/cc-langs.el (c-brace-stack-thing-key): Add a "*" into the
+ sets of significant characters.
+
+2021-12-29 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of 'M-X' and related features
+
+ * doc/emacs/m-x.texi (M-x): Index 'M-X'.
+ * doc/lispref/commands.texi (Interactive Call, Command Modes):
+ Mention 'M-X' and 'execute-extended-command-for-buffer'.
+
+ * etc/NEWS: Clarify that the '(declare (completion ...' and
+ '(declare (modes ...' forms have no effect by default. Likewise
+ for '(interactive "..." MODE)' specs. (Bug#52839)
+
+2021-12-28 Sean Whitton <spwhitton@spwhitton.name>
+
+ Improve rectangle-mark-mode documentation regarding mark activation
+
+ * doc/emacs/killing.texi: Describe how rectangle-mark-mode works when
+ Transient Mark mode is off. Qualify discussion of
+ rectangle-exchange-point-and-mark to say that it cycles the four
+ corners only when the region is active.
+ * lisp/rect.el (rectangle-mark-mode): State that rectangle-mark-mode
+ does not activate the mark when Transient Mark mode is off. Reword
+ sentence about how long the mode lasts to account for when Transient
+ Mark mode is off. (Bug#42663)
+
+2021-12-27 Eli Zaretskii <eliz@gnu.org>
+
+ Fix typos in 'reset-language-environment'
+
+ * lisp/international/mule-cmds.el (reset-language-environment):
+ Fix a typo in 'windows-nt'. (Bug#52816)
+
+2021-12-27 Óscar Fuentes <ofv@wanadoo.es>
+
+ eshell-complete-parse-arguments: don't use string-match on a list
+
+ When there is more than one candidate for completion, `val' is a list.
+
+ Fixes bug#52794.
+
+ * lisp/eshell/em-cmpl.el (eshell-complete-parse-arguments): protect
+ use of string-match with stringp.
+
+2021-12-26 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.2-3-geb9f34
+
+2021-12-26 Stefan Kangas <stefan@marxist.se>
+
+ Improve documentation of read-multiple-choice
+
+ * doc/lispref/commands.texi (Reading One Event): Document optional
+ third argument help-string of read-multiple-choice.
+
+2021-12-25 Eli Zaretskii <eliz@gnu.org>
+
+ Explain why we remove stuff from 'user-full-name'
+
+ * src/editfns.c (Fuser_full_name): Document why we chop everything
+ starting from the first comma. (Bug#52785)
+
+2021-12-24 Dmitry Gutov <dgutov@yandex.ru>
+
+ Fix the bug with duplicate entries in xref output
+
+ * lisp/progmodes/etags.el (xref-backend-definitions): Make sure to
+ save the changed intermediate value of the list (bug#52734).
+
+2021-12-24 Dmitry Gutov <dgutov@yandex.ru>
+
+ Improve Xref documentation
+
+ * lisp/progmodes/xref.el (xref-item): Add docstring for 'summary'.
+ Fix typo in the header Commentary.
+
+2021-12-23 Andreas Schwab <schwab@linux-m68k.org>
+
+ * lisp/net/shr.el (shr-expand-url): Also strip trailing
+ whitespace.
+
+2021-12-22 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert field-related thingatpt changes
+
+ This reverts 7db376e560448e61485ba054def8c82b21f33d6a, which led to
+ severe performance regressions when being run in large buffers with no
+ fields (bug#52593)
+
+2021-12-21 Juri Linkov <juri@linkov.net>
+
+ * lisp/window.el (quit-restore-window): Select previously selected window.
+
+ After deleting the dedicated window, such as a window with *Completions*
+ buffer, select the previously selected window, like most of other 'cond'
+ branches do in this function (bug#52491).
+
+2021-12-21 Robert Pluim <rpluim@gmail.com>
+
+ Revert "Remove Motif support"
+
+ This reverts commit db237850abc240e2c3e765e9cc7e15ee5681dcaf.
+
+2021-12-19 Martin Rudalics <rudalics@gmx.at>
+
+ Clarify description of two mouse dragging parameters (Bug#52537)
+
+ * doc/lispref/frames.texi (Child Frames): Clarify description of
+ 'top-visible' and 'bottom-visible' parameters (Bug#52537).
+
+2021-12-18 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.1-31-ga18849
+
+2021-12-15 Martin Rudalics <rudalics@gmx.at>
+
+ Fix control buffer window height in 'ediff-setup-control-buffer' (Bug#49277)
+
+ * lisp/vc/ediff-util.el (ediff-setup-control-buffer): Emulate
+ original 'shrink-window-if-larger-than-buffer' call by calling
+ 'fit-window-to-buffer' with an appropriate maximum height
+ argument (Bug#49277).
+
+2021-12-15 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+
+ Fix crash when dumping charset_table with portable dumper (Bug#52461)
+
+ * src/charset.h:
+ * src/charset.c (charset_table_used): Now extern.
+ * src/pdumper.c (dump_charset): Don't dump code_space_mask for unused
+ slots of charset_table.
+
+2021-12-14 Philipp Stephani <phst@google.com>
+
+ Remove maintainer comment from Emacs 28 module snippet.
+
+ This is the same as 44c13eefe8d30841000a96d82f467fb8d222e365 on
+ master. We should also remove this comment on the release branch,
+ otherwise it ends up in the emacs-module.h shipped to users.
+
+ * src/module-env-28.h: Remove maintainer comment.
+
+2021-12-14 Stefan Kangas <stefan@marxist.se>
+
+ Set calc-make-windows-dedicated to nil by default
+
+ * lisp/calc/calc.el (calc-make-windows-dedicated):
+ Default to nil. (Bug#52016)
+
+2021-12-14 Stefan Kangas <stefan@marxist.se>
+
+ * make-dist: Don't run "make --question info". (Bug#52322)
+
+2021-12-13 Eli Zaretskii <eliz@gnu.org>
+
+ Fix regression in help-mode prompt
+
+ * lisp/help-macro.el (make-help-screen): Restore SPC and DEL in
+ prompt. Reported by Colin Baxter <m43cap@yandex.com>.
+
+2021-12-13 Kévin Le Gouguec <kevin.legouguec@gmail.com>
+
+ Make `M-x run-python' select the window again
+
+ Interactively, we want M-x run-python to focus the interpreter buffer.
+ The previous code failed in two ways:
+
+ - the call to 'display-buffer' was not reached if an interpreter
+ was already running,
+
+ - set-buffer is ineffectual if the interpreter's window is not
+ selected: once Emacs returns to the command loop, the current buffer
+ will revert back to what the selected window contains.
+
+ * lisp/progmodes/python.el (python-shell-make-comint): Handle the SHOW
+ argument regardless of whether an interpreter buffer exists, and use
+ pop-to-buffer to select the window.
+ (run-python): Delegate buffer management to
+ 'python-shell-make-comint'.
+
+ * test/lisp/progmodes/python-tests.el
+ (python-tests--run-python-selects-window): Rename from
+ 'python-tests--bug31398', and adjust assertions (bug#52380).
+
+2021-12-12 Juri Linkov <juri@linkov.net>
+
+ * lisp/tab-bar.el (tab-bar-switch-to-last-tab): Add 'abs' for precautions.
+
+ https://lists.gnu.org/archive/html/emacs-devel/2021-11/msg01149.html
+
+2021-12-12 Eli Zaretskii <eliz@gnu.org>
+
+ * make-dist (manifest): Filter out msdos/autogen/* files.
+
+2021-12-12 Richard Stallman <rms@gnu.org>
+
+ Rewrite the "Quitting Windows" section of Emacs Lisp Reference
+
+ * doc/lispref/windows.texi (Quitting Windows): Rewrite for
+ clarity. (Bug#52328)
+
+2021-12-12 Po Lu <luangruo@yahoo.com>
+
+ Fix eshell for systems that do not have subprocesses
+
+ * lisp/eshell/esh-cmd.el (eshell-eval-command): Use
+ `eshell-processp' instead of `processp'.
+
+2021-12-11 Philipp Stephani <phst@google.com>
+
+ Avoid undefined behavior in 'send-process-region' (Bug#52369).
+
+ * src/process.c (send_process): Signal an error if the file descriptor
+ has already been closed.
+
+2021-12-11 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.1-25-g9ca3bc
+
+2021-12-11 Po Lu <luangruo@yahoo.com>
+
+ Fix the DJGPP port
+
+ * config.bat:
+ * msdos/sed1v2.inp:
+ * msdos/sed2v2.inp:
+ * msdos/sed3v2.inp:
+ * msdos/sedlibmk.inp: Update for Emacs 28.
+ * msdos/langinfo.h: New file.
+
+ * lisp/loadup.el: Use correct path to temacs when dumping on
+ MS-DOS.
+ * src/callproc.c (environ) [MSDOS]: New declaration.
+ (child_setup, emacs_spawn): Update MS-DOS parts for Emacs 28.
+ * src/fileio.c (Fcopy_file): Don't use copy_file_range on
+ MS-DOS.
+ * src/msdos.c (initialize_msdos_display): Add
+ `defined_color_hook'.
+ (openat, fchmodat, futimens, utimensat): New functions.
+
+ * src/msdos.h (FRAME_X_DISPLAY): New macro.
+ * src/process.c: Make some more things conditional on
+ subprocess support.
+ (PIPECONN_P, PIPECONN1_P) [!subprocesses]: New placeholder
+ macros.
+ (Fnum_processors): Return 1 on MSDOS.
+ (open_channel_for_module): Avoid subprocess specific code
+ on MSDOS.
+
+2021-12-10 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Revert "Make `M-x run-python' select the window again"
+
+ This reverts commit aa2872a12770282ede3548ed3fcab00c5a5b9f18.
+
+ This led to a test failure.
+
+2021-12-10 Kévin Le Gouguec <kevin.legouguec@gmail.com>
+
+ Make `M-x run-python' select the window again
+
+ * lisp/progmodes/python.el (python-shell-make-comint): Make `M-x
+ run-python' select the window again like in 27.2 (bug#52380).
+
+2021-12-10 Lars Ingebrigtsen <larsi@gnus.org>
+
+ Don't bug out on certain empty elements with ids
+
+ * lisp/net/shr.el (shr-descend): Fix empty-element #id targeting
+ (bug#52391).
+
+2021-12-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ emacsclient takes more care about XDG_RUNTIME_DIR
+
+ * lib-src/emacsclient.c (set_local_socket): Revert to the Emacs 27
+ behavior of not trying TMPDIR if XDG_RUNTIME_DIR is set.
+ This is one of the suggestions made by Jim Porter and
+ independently by Ulrich Mueller in Bug#51327.
+
+2021-12-09 Cameron Desautels <camdez@gmail.com>
+
+ Add missing K key documentation for Cangjie input methods
+
+ * lisp/international/titdic-cnv.el (tsang-quick-converter): Add the
+ missing K key in input method documentation. (Bug#52264)
+
+2021-12-09 Martin Rudalics <rudalics@gmx.at>
+
+ Fix manual entry of 'quit-restore-window' (Bug#52328)
+
+ * doc/lispref/windows.texi (Quitting Windows): Fix bug in
+ description of 'quit-restore-window' (Bug#52328).
+
+2021-12-09 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify a comment in xdisp.c
+
+ * src/xdisp.c (compute_window_start_on_continuation_line): Clarify
+ a comment. (Bug#52378)
+
+2021-12-08 Óscar Fuentes <ofv@wanadoo.es>
+
+ Revert "Grep alias `all' shall not match parent directory"
+
+ This reverts commit 856cd948d1a5a016ad36721246a049d33451902f.
+
+ Emacs got better at quoting shell arguments and the original value
+ works correctly for vc-git-grep. At the same time, the value
+ introduced on that commit caused a regression on lgrep.
+
+ * lisp/progmodes/grep.el (grep-files-aliases): Use previous value for
+ `all'. Fixes bug#52367
+
+2021-12-08 Eli Zaretskii <eliz@gnu.org>
+
+ Fix mode-line display in Calendar mode
+
+ * lisp/help.el (substitute-command-keys): New optional argument
+ NO-FACE, to avoid putting the 'help-key-binding' face on the key
+ bindings.
+ * lisp/calendar/calendar.el (calendar-mode-line-entry): Call
+ 'substitute-command-keys' with the new optional argument non-nil.
+ (Bug#52366)
+
+ * doc/lispref/help.texi (Keys in Documentation): Document the new
+ optional argument of 'substitute-command-keys'.
+
+ * etc/NEWS: Announce the addition of a new argument to
+ 'substitute-command-keys'.
+
+2021-12-08 Lele Gaifax <lele@metapensiero.it>
+
+ * etc/tutorials/TUTORIAL.it (CONCLUSIONI): Reword paragraph.
+
+ Don't merge to master.
+
+2021-12-08 Michael Albinus <michael.albinus@gmx.de>
+
+ Backport: Make a more robust check in Tramp using scripts
+
+ * lisp/net/tramp-sh.el (tramp-find-inline-encoding):
+ Check, whether scripts in `tramp-remote-coding-commands' are
+ expandable.
+
+ (cherry picked from commit 1d0a60113fd155c77ef5ea4ea44fcba3504adcbf)
+
+2021-12-07 Robert Pluim <rpluim@gmail.com>
+
+ Document native-comp-async-report-warning-errors more
+
+ The docstring has a description of how fix problems in lisp code
+ detected by native compilation, but not the Emacs Lisp manual, so
+ document it there as well.
+
+ * doc/lispref/compile.texi (Native-Compilation Functions): Refer to
+ 'native-comp-async-report-warning-errors'
+ (Native-Compilation Variables): Explain potential cause of warnings
+ from native compilation.
+
+2021-12-07 Stefan Kangas <stefan@marxist.se>
+
+ Doc fix; Epiphany has been renamed to GNOME Web
+
+ * lisp/net/browse-url.el: Doc fix; Epiphany is called GNOME Web
+ since GNOME 3.4, released in 2012.
+ Ref: https://help.gnome.org/misc/release-notes/3.4/
+
+2021-12-07 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/dired-aux.el (dired-check-process): Doc fix. (Bug#52337)
+
+2021-12-07 Stefan Kangas <stefan@marxist.se>
+
+ Remove dead link from newsticker
+
+ * lisp/net/newst-backend.el (newsticker--parse-rss-0.91):
+ * lisp/net/newsticker.el: Remove dead link.
+
+2021-12-06 Juri Linkov <juri@linkov.net>
+
+ Select the right buffer for event in context-menu functions (bug#9923)
+
+ * lisp/mouse.el (context-menu-region):
+ * lisp/progmodes/prog-mode.el (prog-context-menu):
+ Switch to the buffer displayed by the window of the event
+ before using syntax-ppss, char-after.
+
+2021-12-06 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ lisp/minibuffer.el: Fix for bug#52169 regression
+
+ * lisp/minibuffer.el (completion-table-subvert): Make sure we return
+ a boundary that's not outside of the limit of the string.
+
+2021-12-05 Christer Enfors <christer.enfors@gmail.com>
+
+ Fix typos and improve consistency in ERC manual
+
+ * doc/misc/erc.texi (Sample Session, Special Features, History): Fix
+ typos and improve consistency. (Bug52318)
+
+2021-12-05 Glenn Morris <rgm@gnu.org>
+
+ * test/Makefile.in (check-declare): Add missing --batch.
+
+2021-12-05 Eli Zaretskii <eliz@gnu.org>
+
+ Document the subtleties of the 'cursor' text property
+
+ * doc/lispref/text.texi (Special Properties): Update the
+ documentation of the 'cursor' property per bug#8627.
+
+2021-12-05 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.5.1-15-gdb4805
+
+2021-12-04 Stefan Kangas <stefan@marxist.se>
+
+ * lisp/emacs-lisp/edebug.el (edebug-eval-defun): Minor doc fix.
+
+2021-12-04 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the enumeration values returned by 'try_scrolling'
+
+ * src/xdisp.c (try_scrolling): Make the enum values match the
+ commentary. Reported by Po Lu <luangruo@yahoo.com>.
+
+2021-12-04 Stefan Kangas <stefan@marxist.se>
+
+ * src/dosfns.c (Fint86): Doc fix; don't use obsolete names.
+
+2021-12-03 Stefan Kangas <stefan@marxist.se>
+
+ * doc/misc/erc.texi (Keystroke Summary): Fix doc for TAB.
+
+2021-12-03 Stefan Kangas <stefan@marxist.se>
+
+ Remove reference to variable obsolete since 24.1
+
+ * doc/emacs/custom.texi (Minibuffer Maps, Minibuffer Maps): Remove
+ reference to variable 'minibuffer-local-filename-must-match-map',
+ obsolete since 24.1.
+
+2021-12-03 Stefan Kangas <stefan@marxist.se>
+
+ * doc/misc/efaq.texi (New in Emacs 28): New node.
+
+2021-12-03 Michael Albinus <michael.albinus@gmx.de>
+
+ Add Tramp version integrated in Emacs 28.1
+
+ * lisp/net/trampver.el (customize-package-emacs-version-alist):
+ Add Tramp version integrated in Emacs 28.1.
+
+2021-12-03 Michael Albinus <michael.albinus@gmx.de>
+
+ Update Tramp version (don't merge with master)
+
+ * doc/misc/trampver.texi:
+ * lisp/net/trampver.el: Change version to "2.5.2.28.1".
+
+2021-12-03 Philipp Stephani <phst@google.com>
+
+ Unbreak build after 9c222b9c1a7f91497a37567b4d7de3a511fff069.
+
+ * src/pdumper.c (dump_subr): Fix Lisp_Subr hash value.
+
+2021-12-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port to C compilers that lack size-0 arrays
+
+ The C standard does not allow size-zero arrays, so redo struct
+ Lisp_Subr to not use size-zero arrays when native compilation is
+ not being used. Formerly, the code was using size-zero arrays (a
+ GNU C extension) to avoid using memory unnecessarily when
+ HAVE_NATIVE_COMP is not defined. Replace this hack with the
+ more-traditional hack of putting the relevant members inside
+ ‘#ifdef HAVE_NATIVE_COMP’.
+ * src/alloc.c (cleanup_vector, mark_object):
+ * src/comp.c (make_subr):
+ * src/data.c (Fsubr_native_lambda_list, Fsubr_native_comp_unit):
+ * src/eval.c (init_eval_once, funcall_lambda):
+ * src/lisp.h (SUBR_NATIVE_COMPILEDP, SUBR_NATIVE_COMPILED_DYNP)
+ (SUBR_TYPE):
+ * src/lread.c (Fload):
+ Conditionally compile with ‘#ifdef HAVE_NATIVE_COMP’ instead of
+ with ‘if (NATIVE_COMP_FLAG)’. Redo members like native_comp_u[0]
+ to be plain native_comp_u. Put all uses of these members inside
+ ‘#ifdef HAVE_NATIVE_COMP’.
+ * src/lisp.h (struct Lisp_Subr): Members native_comp_u,
+ native_c_name, lambda_list, type are now all ifdeffed out if
+ HAVE_NATIVE_COMP is not defined, instead of being size-zero
+ arrays. All uses changed.
+ * src/pdumper.c (dump_subr, dump_cold_native_subr)
+ (dump_do_dump_relocation):
+ * src/comp.h (NATIVE_COMP_FLAG): Remove; no longer needed.
+
+2021-12-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port emacsclient to Solaris 10
+
+ Without this patch, the build fails on Solaris 10 with the diagnostic
+ “Undefined symbol acl_trivial first referenced in file
+ ../lib/libgnu.a(file-has-acl.o)”.
+ * lib-src/Makefile.in (LIB_HAS_ACL): New macro.
+ (emacsclient${EXEEXT}): Link with $(LIB_HAS_ACL).
+
+2021-12-03 Karl Fogel <kfogel@red-bean.com>
+
+ * CONTRIBUTE: Improve commit message instructions
+
+2021-12-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ Work around IBM XL C compiler bug
+
+ * src/fileio.c (Fcopy_file): Work around a compiler bug in IBM XL
+ C for AIX, V12.1 (5765-J02, 5725-C72). Without this patch, the
+ compiler incorrectly complains “Initialization between types "int"
+ and "struct timespec" is not allowed” and “Initialization between
+ types "long" and "struct timespec" is not allowed”.
+
+2021-12-03 Stefan Kangas <stefan@marxist.se>
+
+ * admin/make-tarball.txt: Various clarifications.
+
+2021-12-02 Stefan Kangas <stefan@marxist.se>
+
+ * admin/diff-tar-files: Don't assume .tar.gz.
+
+2021-12-02 Juri Linkov <juri@linkov.net>
+
+ * lisp/tab-bar.el (tab-bar-close-other-tabs): Fix regression.
+
+ * test/lisp/tab-bar-tests.el: New file.
+ (tab-bar-tests-close-other-tabs-with-arg): Test for regression
+ that closed the selected tab after selecting it.
+
2021-12-01 Juri Linkov <juri@linkov.net>
* lisp/repeat.el: Use same logic for repeat-check-key and repeat-exit-timeout.
@@ -12671,7 +15459,7 @@
Fix automatic hscrolling when line numbers are displayed
* src/xdisp.c (hscroll_window_tree): When line numbers are
- displayed, account for the the line-number space when calculating
+ displayed, account for the line-number space when calculating
the desired X coordinate on the left. (Bug#49891)
2021-08-06 Eli Zaretskii <eliz@gnu.org>
@@ -24381,7 +27169,7 @@
* lisp/minibuffer.el (minibuffer--sort-by-length-alpha): New function.
(minibuffer--sort-by-position): New function extracted from
`completion-all-sorted-completions`.
- (completion-all-sorted-completions): Use use them.
+ (completion-all-sorted-completions): Use them.
2021-04-19 Daniel Mendler <mail@daniel-mendler.de>
@@ -39430,7 +42218,7 @@
string in the byte-code (so the two branches return `eq` strings).
So, I think using `iso-2022-jp` is a bad idea here: it gives the
- illusion that the the `charset` info exists, even it will be lost.
+ illusion that the `charset` info exists, even it will be lost.
Eli discussed it with Handa-san a year ago, and they arrived at the
conclusion that the charset information is indeed no longer important.
@@ -64570,7 +67358,7 @@
wdired-do-renames: Speed up for long Emacs sessions
`dired-rename-file' calls unconditionally `dired-rename-subdir'.
- The second function performs performs a loop on all the Emacs
+ The second function performs a loop on all the Emacs
buffers; this step is only needed if FILE is a directory (bug#32899).
In a long lived Emacs session, this can make a difference
@@ -71518,7 +74306,7 @@
(Bug#42563)
- For some time, Eldoc has has some Elisp-specific code that shouldn't
+ For some time, Eldoc has some Elisp-specific code that shouldn't
live there, but in elisp-mode.el. This can be fixed in Emacs master,
but since ElDoc is distributed in GNU Elpa and is meant to work with
Emacs 26 and 27, this means that that elisp-specific code must still
@@ -71770,7 +74558,7 @@
Do this conservatively for now: if the ElDoc helper buffer (as
returned by eldoc--doc-buffer) is visible and showing documentation
- for the very same "situation" (as computed by the the new
+ for the very same "situation" (as computed by the new
eldoc--request-state helper), don't request that documentation from
sources again.
@@ -75188,7 +77976,7 @@
* lisp/emacs-lisp/comp.el (comp-symbol-values-optimizable): New
defconst.
- (comp-function-call-maybe-remove): New logic to to remove
+ (comp-function-call-maybe-remove): New logic to remove
unnecessary `symbol-value' calls.
2020-06-07 Juri Linkov <juri@linkov.net>
@@ -82580,7 +85368,7 @@
2020-03-10 AndreaCorallo <akrl@sdf.org>
- * Fix store_function_docstring for for native functions
+ * Fix store_function_docstring for native functions
Do not Nil native_doc fields. This will be naturally dumped by
pdumper. This was affecting dumped functions.
@@ -111638,7 +114426,7 @@
2019-08-21 Nicolas Petton <nicolas@petton.fr>
- * etc/HISTORY: Add Emacs 26.3 release release date.
+ * etc/HISTORY: Add Emacs 26.3 release date.
2019-08-21 Nicolas Petton <nicolas@petton.fr>
@@ -114620,7 +117408,7 @@
2019-07-30 Lars Ingebrigtsen <larsi@gnus.org>
- Use decoded time accessors in in em-ls
+ Use decoded time accessors in em-ls
* lisp/eshell/em-ls.el (eshell-ls-file): Use decoded time
accessors.
@@ -116195,7 +118983,7 @@
* doc/lispref/hash.texi (Creating Hash, Defining Hash):
* src/fns.c (Fsxhash_eq, Fsxhash_eql, Fsxhash_equal):
Say that hashes are fixnums.
- (Fmake_hash_table): Say that that an integer rehash-size
+ (Fmake_hash_table): Say that an integer rehash-size
should be a fixnum.
* doc/lispref/hash.texi (Defining Hash): Say that hash and
comparison functions should be consistent and pure, and should
@@ -125841,7 +128629,7 @@
* lisp/emacs-lisp/package.el (package-install-from-archive): Fix last change
- Don't place the unibyte content of of the downloaded file into
+ Don't place the unibyte content of the downloaded file into
a multibyte buffer.
2019-05-24 Michael Albinus <michael.albinus@gmx.de>
@@ -146883,7 +149671,7 @@
* lisp/textmodes/bibtex.el (bibtex-next-entry)
(bibtex-previous-entry): New commands.
- (bibtex-mode-map): Bind to to forward-paragraph and
+ (bibtex-mode-map): Bind to forward-paragraph and
backward-paragraph. Add to menu under "Moving inside an Entry".
2018-08-27 Noam Postavsky <npostavs@gmail.com>
@@ -183741,7 +186529,7 @@
Lay some groundwork for a more flexible approach that allows for
different classes of diagnostics, not necessarily line-based.
Importantly, one overlay per diagnostic is created, whereas the
- original implementation had one per line, and on it it concatenated
+ original implementation had one per line, and on it concatenated
the results of errors and warnings.
This means that currently, an error and warning on the same line are
@@ -233413,7 +236201,7 @@
This file records repository revisions from
commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to
-commit 334ff0232e07dad2ff5595b7f85c0f6f5efcb11c (inclusive).
+commit 7f749e44dbd50430e14f319b4c4d3f767740b10b (inclusive).
See ChangeLog.2 for earlier changes.
;; Local Variables:
diff --git a/INSTALL b/INSTALL
index 02d5a09d63c..95d2dbda80c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -4,11 +4,13 @@ Inc.
See the end of the file for license conditions.
-This file contains general information on building GNU Emacs.
-For more information specific to the MS-Windows, GNUstep/macOS, and
-MS-DOS ports, also read the files nt/INSTALL, nextstep/INSTALL, and
-msdos/INSTALL. For information about building from a repository checkout
-(rather than a release), also read the file INSTALL.REPO.
+This file contains general information on building GNU Emacs. For
+more information specific to the MS-Windows, GNUstep/macOS, and MS-DOS
+ports, also read the files nt/INSTALL, nextstep/INSTALL, and
+msdos/INSTALL.
+
+For information about building from a Git checkout (rather than an
+Emacs release), read the INSTALL.REPO file first.
BASIC INSTALLATION
@@ -226,6 +228,38 @@ e.g. 'emacs25'). On Red Hat-based systems, the corresponding command is
On FreeBSD, the command is 'pkg install -y `pkg rquery %dn emacs-devel`'.
+* Alternative window systems
+
+If you want to use Emacs on one of the alternative window systems
+available on GNU/Linux and some Unix systems, such as Wayland or
+Broadway, you can build the PGTK ("Pure GTK") port of Emacs, which
+utilizes the GTK+ toolkit to support those window systems. To this
+end, invoke the configure script with the '--with-pgtk' option, like
+this:
+
+ ./configure --with-pgtk
+
+This build is only supported with GTK+ version 3, and it is an error
+to specify any other X-specific configuration option when PGTK is
+enabled.
+
+If you use exclusively X, do not use the PGTK port. There are a
+number of respects in which the regular --with-x-toolkit=gtk build
+works better. The PGTK port should not be considered a simple upgrade
+from --with-x-toolkit=gtk.
+
+With the PGTK build, you will be able to switch between running Emacs
+on X, Wayland and Broadway using the 'GDK_BACKEND' environment
+variable. GTK+ should automatically detect and use the correct value
+for your system, but you can also specify it manually. For example,
+to force GTK+ to run under Broadway, start Emacs like this:
+
+ GDK_BACKEND=broadway emacs ...
+
+(where '...' denotes any further options you may want to pass to Emacs).
+
+The GNUstep build also supports the Wayland window system. If that is
+what you want, see nextstep/INSTALL.
DETAILED BUILDING AND INSTALLATION:
@@ -324,9 +358,9 @@ Use --without-toolkit-scroll-bars to disable Motif or Xaw3d scroll bars.
Use --without-xim to inhibit the default use of X Input Methods.
In this case, the X resource useXIM can be used to turn on use of XIM.
-Use --with-xinput2 to enable the use of version 2 of the X Input
-Extension. This enables support for touchscreens, pinch gestures, and
-scroll wheels that report scroll deltas at pixel-level precision.
+Use --without-xinput2 to disable the use of version 2 of the X Input
+Extension. This disables support for touchscreens, pinch gestures,
+and scroll wheels that report scroll deltas at pixel-level precision.
Use --disable-largefile to omit support for files larger than 2GB, and
--disable-year2038 to omit support for timestamps past the year 2038,
diff --git a/Makefile.in b/Makefile.in
index b72127dde67..4b749636656 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -319,6 +319,9 @@ GLIB_COMPILE_SCHEMAS = glib-compile-schemas
# Program name transformation.
TRANSFORM = @program_transform_name@
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
# What emacs should be called when installed.
EMACS_NAME = `echo emacs | sed '$(TRANSFORM)'`
EMACS = ${EMACS_NAME}${EXEEXT}
@@ -691,8 +694,6 @@ install-etcdoc: src install-arch-indep
printf 'Copying %s to %s ...\n' "etc/$$docfile" \
"$(DESTDIR)${etcdocdir}"; \
${INSTALL_DATA} etc/$${docfile} "$(DESTDIR)${etcdocdir}/$${docfile}"; \
- $(set_installuser); \
- chown $${installuser} "$(DESTDIR)${etcdocdir}/$${docfile}" || true ; \
else true; fi
## FIXME:
@@ -964,6 +965,7 @@ bootstrap-clean: $(distclean_dirs:=_bootstrap-clean)
[ ! -f config.log ] || mv -f config.log config.log~
rm -rf ${srcdir}/info
rm -f ${srcdir}/etc/refcards/emacsver.tex
+ rm -rf native-lisp/ lisp/leim/ja-dic/
${top_bootclean}
### 'maintainer-clean'
diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES
index 620ab0bed05..06986ec8f48 100644
--- a/admin/CPP-DEFINES
+++ b/admin/CPP-DEFINES
@@ -24,6 +24,7 @@ DARWIN_OS Compiling on macOS or pure Darwin (and using s/darwin.h).
SOLARIS2
USG
USG5_4
+HAIKU Compiling on Haiku.
** Distinguishing GUIs **
@@ -32,16 +33,38 @@ HAVE_NS Use the NeXT/OpenStep/Cocoa UI under macOS or GNUstep.
NS_IMPL_GNUSTEP Compile support for GNUstep implementation of NS GUI API.
NS_IMPL_COCOA Compile support for Cocoa (Apple) implementation of NS GUI API.
HAVE_X11 Compile support for the X11 GUI.
+HAVE_PGTK Compile support for using GTK itself without directly using X Windows APIs.
+HAVE_HAIKU Compile support for the Haiku window system.
HAVE_X_WINDOWS Compile support for X Window system
(It looks like, nowadays, if HAVE_X11 is set, HAVE_X_WINDOWS must
be, and vice versa. At least, this is true for configure, and
msdos; not sure about nt.)
-HAVE_X11R6
-HAVE_X11R6_XIM
-HAVE_X11XTR6
+
+** X Windows features **
+HAVE_X11R6 Whether or not the system has X11R6. (Always defined.)
+HAVE_X11R6_XIM Whether or not the system supports XIM features introduced in R6.
+HAVE_X11XTR6 Whether or not the Xt is from X11R6 or newer.
+
USE_LUCID Use the Lucid toolkit for menus&scrollbars. Requires HAVE_X11.
USE_MOTIF Use the Motif toolkit for menus&scrollbars. Requires HAVE_X11.
-USE_GTK Use the Gtk toolkit for menus&scrollbars. Requires HAVE_X11.
+USE_GTK Use the Gtk toolkit for menus&scrollbars. Requires HAVE_X11 or HAVE_PGTK.
+HAVE_GTK3 Use GTK version 3 or later. Requires HAVE_X11.
+
+HAVE_XCB_SHAPE Whether or not XCB supports the Nonrectangular Window Shape extension.
+HAVE_XCOMPOSITE Whether or not the XCOMPOSITE extension library is present.
+HAVE_XDBE Whether or not to use the Xdbe extension for double buffering.
+HAVE_XFIXES Whether or not the Xfixes extension library is present.
+HAVE_XINERAMA Whether or not the Xinerama extension library is present.
+HAVE_XINPUT2 Whether or not to use version 2 of the X Input Extension for input.
+HAVE_XINPUT2_1 Whether or not version 2.1 of the X Input Extension is supported.
+HAVE_XINPUT2_2 Whether or not version 2.2 of the X Input Extension is supported.
+HAVE_XINPUT2_3 Whether or not version 2.3 of the X Input Extension is supported.
+HAVE_XINPUT2_4 Whether or not version 2.4 of the X Input Extension is supported.
+HAVE_XKB Whether or not the XKB extension library is present.
+HAVE_XRANDR Whether or not the RandR extension library is present.
+HAVE_XSHAPE Whether or not the Nonrectangular Window Shape extension library is present.
+HAVE_XSYNC Whether or not the X Synchronization Extension library is present.
+USE_XCB Whether or not the XCB library is used to optimize some X requests.
** Frame types **
diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS
index e87c3e0204a..f0239db0089 100644
--- a/admin/MAINTAINERS
+++ b/admin/MAINTAINERS
@@ -275,14 +275,6 @@ Vibhav Pant
lisp/net/browse-url.el
lisp/erc/*
-Alan Third
- The NS port:
- nextstep/*
- src/ns*
- src/*.m
- lisp/term/ns-win.el
- doc/emacs/macos.texi
-
Amin Bandali
Eshell
lisp/eshell/*
@@ -304,6 +296,8 @@ Tramp
Repository: git://git.savannah.gnu.org/tramp.git
Mailing List: tramp-devel@gnu.org
Bug Reports: M-x tramp-bug
+ Notes: For backward compatibility requirements, see
+ lisp/net/trampver.el.
lisp/net/tramp*.el
doc/misc/tramp*.texi
@@ -311,11 +305,30 @@ Tramp
Modus themes
Maintainer: Protesilaos Stavrou
- Repository and issue tracker: https://gitlab.com/protesilaos/modus-themes
+ Repository: https://git.sr.ht/~protesilaos
+ Mailing list: https://lists.sr.ht/~protesilaos/modus-themes
+ Bug Reports: M-x modus-themes-report-bug
doc/misc/modus-themes.org
etc/themes/modus*.el
+Org Mode
+ Home Page: https://orgmode.org/
+ Maintainer: Org Mode developers
+ Repository: git://git.sv.gnu.org/emacs/org-mode.git
+ Mailing list: emacs-orgmode@gnu.org
+ Bug Reports: M-x org-submit-bug-report
+ Notes: Org Mode is maintained as a separate project that is
+ periodically merged into Emacs. To view or participate in
+ Org Mode development, please go to https://orgmode.org/ and
+ follow the instructions there.
+
+ lisp/org/*.el
+ etc/org/*
+ etc/refcards/orgcard.tex
+ doc/misc/org.org
+ doc/misc/org-setup.org
+
;;; Local Variables:
;;; coding: utf-8
diff --git a/admin/admin.el b/admin/admin.el
index 5f02ea8ce45..c84287a7024 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -351,11 +351,13 @@ Optional argument TYPE is type of output (nil means all)."
\"https://www.w3.org/TR/html4/loose.dtd\">\n\n")
(defconst manual-meta-string
- "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">
-<link rev=\"made\" href=\"mailto:bug-gnu-emacs@gnu.org\">
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n")
+
+(defconst manual-links-string
+ "<link rev=\"made\" href=\"mailto:bug-gnu-emacs@gnu.org\">
<link rel=\"icon\" type=\"image/png\" href=\"/graphics/gnu-head-mini.png\">
<meta name=\"ICBM\" content=\"42.256233,-71.006581\">
-<meta name=\"DC.title\" content=\"gnu.org\">\n\n")
+<meta name=\"DC.title\" content=\"gnu.org\">\n")
(defconst manual-style-string "<style type=\"text/css\">
@import url('/software/emacs/manual.css');\n</style>\n")
@@ -486,6 +488,13 @@ the @import directive."
(delete-region opoint (point))
(search-forward "<meta http-equiv=\"Content-Style")
(setq opoint (match-beginning 0)))
+ (search-forward "<title>")
+ (delete-region opoint (match-beginning 0))
+ (search-forward "</title>\n")
+ (when (search-forward "<link href=" nil t)
+ (goto-char (match-beginning 0)))
+ (insert manual-links-string)
+ (setq opoint (point))
(search-forward "</head>")
(goto-char (match-beginning 0))
(delete-region opoint (point))
@@ -602,76 +611,81 @@ style=\"text-align:left\">")
(forward-line 1)
(setq done t)))))
(let (done open-td tag desc)
- ;; Convert the list that Makeinfo made into a table.
- (or (search-forward "<ul class=\"menu\">" nil t)
- ;; FIXME? The following search seems dangerously lax.
- (search-forward "<ul>"))
- (replace-match "<table style=\"float:left\" width=\"100%\">")
- (forward-line 1)
- (while (not done)
- (cond
- ((or (looking-at "<li>\\(<a.+</a>\\):[ \t]+\\(.*\\)$")
- (looking-at "<li>\\(<a.+</a>\\)$"))
- (setq tag (match-string 1))
- (setq desc (match-string 2))
- (replace-match "" t t)
- (when open-td
- (save-excursion
- (forward-char -1)
- (skip-chars-backward " ")
- (delete-region (point) (line-end-position))
- (insert "</td>\n </tr>")))
- (insert " <tr>\n ")
- (if table-workaround
- ;; This works around a Firefox bug in the mono file.
- (insert "<td bgcolor=\"white\">")
- (insert "<td>"))
- (insert tag "</td>\n <td>" (or desc ""))
- (setq open-td t))
- ((eq (char-after) ?\n)
- (delete-char 1)
- ;; Negate the following `forward-line'.
- (forward-line -1))
- ((looking-at "<!-- ")
- (search-forward "-->"))
- ((looking-at "<p>[- ]*The Detailed Node Listing[- \n]*")
- (replace-match " </td></tr></table>\n
+ ;; Texinfo 6.8 and later doesn't produce <ul class="menu"> lists
+ ;; for the TOC menu, and the "description" part of each menu
+ ;; item is not there anymore. So for HTML manuals produced by
+ ;; those newer versions of Texinfo we punt and leave the menu in
+ ;; its original form.
+ (when (or (search-forward "<ul class=\"menu\">" nil t)
+ ;; FIXME? The following search seems dangerously lax.
+ (search-forward "<ul>" nil t))
+ ;; Convert the list that Makeinfo made into a table.
+ (replace-match "<table style=\"float:left\" width=\"100%\">")
+ (forward-line 1)
+ (while (not done)
+ (cond
+ ((or (looking-at "<li>\\(<a.+</a>\\):[ \t]+\\(.*\\)$")
+ (looking-at "<li>\\(<a.+</a>\\)$"))
+ (setq tag (match-string 1))
+ (setq desc (match-string 2))
+ (replace-match "" t t)
+ (when open-td
+ (save-excursion
+ (forward-char -1)
+ (skip-chars-backward " ")
+ (delete-region (point) (line-end-position))
+ (insert "</td>\n </tr>")))
+ (insert " <tr>\n ")
+ (if table-workaround
+ ;; This works around a Firefox bug in the mono file.
+ (insert "<td bgcolor=\"white\">")
+ (insert "<td>"))
+ (insert tag "</td>\n <td>" (or desc ""))
+ (setq open-td t))
+ ((eq (char-after) ?\n)
+ (delete-char 1)
+ ;; Negate the following `forward-line'.
+ (forward-line -1))
+ ((looking-at "<!-- ")
+ (search-forward "-->"))
+ ((looking-at "<p>[- ]*The Detailed Node Listing[- \n]*")
+ (replace-match " </td></tr></table>\n
<h3>Detailed Node Listing</h3>\n\n" t t)
- (search-forward "<p>")
- ;; FIXME Fragile!
- ;; The Emacs and Elisp manual have some text at the
- ;; start of the detailed menu that is not part of the menu.
- ;; Other manuals do not.
- (if (looking-at "Here are some other nodes")
- (search-forward "<p>"))
- (goto-char (match-beginning 0))
- (skip-chars-backward "\n ")
- (setq open-td nil)
- (insert "</p>\n\n<table style=\"float:left\" width=\"100%\">"))
- ((looking-at "</li></ul>")
- (replace-match "" t t))
- ((looking-at "<p>")
- (replace-match "" t t)
- (when open-td
- (insert " </td></tr>")
- (setq open-td nil))
- (insert " <tr>
+ (search-forward "<p>")
+ ;; FIXME Fragile!
+ ;; The Emacs and Elisp manual have some text at the
+ ;; start of the detailed menu that is not part of the menu.
+ ;; Other manuals do not.
+ (if (looking-at "Here are some other nodes")
+ (search-forward "<p>"))
+ (goto-char (match-beginning 0))
+ (skip-chars-backward "\n ")
+ (setq open-td nil)
+ (insert "</p>\n\n<table style=\"float:left\" width=\"100%\">"))
+ ((looking-at "</li></ul>")
+ (replace-match "" t t))
+ ((looking-at "<p>")
+ (replace-match "" t t)
+ (when open-td
+ (insert " </td></tr>")
+ (setq open-td nil))
+ (insert " <tr>
<th colspan=\"2\" align=\"left\" style=\"text-align:left\">")
- (if (re-search-forward "</p>[ \t\n]*<ul class=\"menu\">" nil t)
- (replace-match " </th></tr>")))
- ((looking-at "[ \t]*</ul>[ \t]*$")
- (replace-match
- (if open-td
- " </td></tr>\n</table>"
- "</table>") t t)
- (setq done t))
- (t
- (if (eobp)
- (error "Parse error in %s"
- (file-name-nondirectory buffer-file-name)))
- (unless open-td
- (setq done t))))
- (forward-line 1)))))
+ (if (re-search-forward "</p>[ \t\n]*<ul class=\"menu\">" nil t)
+ (replace-match " </th></tr>")))
+ ((looking-at "[ \t]*</ul>[ \t]*$")
+ (replace-match
+ (if open-td
+ " </td></tr>\n</table>"
+ "</table>") t t)
+ (setq done t))
+ (t
+ (if (eobp)
+ (error "Parse error in %s"
+ (file-name-nondirectory buffer-file-name)))
+ (unless open-td
+ (setq done t))))
+ (forward-line 1))))))
(defconst make-manuals-dist-output-variables
diff --git a/admin/alloc-colors.c b/admin/alloc-colors.c
index 4db447332ba..b78dd42b7e6 100644
--- a/admin/alloc-colors.c
+++ b/admin/alloc-colors.c
@@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
+#include <string.h>
void
fatal (const char *fmt, ...)
diff --git a/admin/authors.el b/admin/authors.el
index 342f2718c84..8a62520d6c5 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -68,6 +68,7 @@ files.")
(nil "castor@my-dejanews")
(nil "chengang31@gmail.com")
(nil "chuntaro")
+ ("Clément Pit-Claudel" "Clément Pit--Claudel")
("David Abrahams" "Dave Abrahams")
("David J. Biesack" "David Biesack")
("David De La Harpe Golden" "David Golden")
@@ -242,10 +243,14 @@ files.")
("Vinicius Jose Latorre" "viniciusjl")
("Gaby Launay" "galaunay")
("Dick R. Chiang" "dickmao")
+ ("Lin Zhou" "georgealbert@qq.com")
+ (nil "yan@metatem.net")
+ (nil "gnu_lists@halloleo.hailmail.net")
)
"Alist of author aliases.
-Each entry is of the form (REALNAME REGEXP...). If an author's name
+Each entry is of the form (REALNAME REGEXP...).
+If an author's full name, as in \"J.R.Hacker <foobar.com>\",
matches one of the REGEXPs, use REALNAME instead.
If REALNAME is nil, ignore that author.")
@@ -498,6 +503,7 @@ Changes to files matching one of the regexps in this list are not listed.")
"nextstep/WISHLIST"
;; Removed, replaced by gitmerge.el
"admin/bzrmerge.el"
+ "bzrmerge.el"
;; Removed in commit f5090b91299
"lib/fdatasync.c"
;; Removed as obsolete
@@ -512,8 +518,11 @@ Changes to files matching one of the regexps in this list are not listed.")
"MORE.STUFF"
"notes/font-backend"
"src/ftxfont.c"
+ "ftxfont.c"
"src/ptr-bounds.h"
"obsolete/options.el"
+ "obsolete/old-whitespace.el"
+ "obsolete/lucid.el"
;; ada-mode has been deleted, now in GNU ELPA
"ada-mode.texi"
"doc/misc/ada-mode.texi"
@@ -874,11 +883,9 @@ Changes to files in this list are not listed.")
"gnus-compat.el" "pgg-parse.el" "pgg-pgp.el" "pgg-pgp5.el" "pgg.el"
"dns-mode.el" "run-at-time.el" "gnus-encrypt.el" "sha1-el.el"
"gnus-gl.el" "gnus.sum.el" "proto-stream.el" "color.el" "color-lab.el"
- "eww.el" "shr-color.el" "shr.el" "earcon.el" "gnus-audio.el" "encrypt.el"
- "format-spec.el" "gnus-move.el" "gnus-sync.el"
- "auth-source.el" "ecomplete.el" "gravatar.el" "mailcap.el" "plstore.el"
- "pop3.el" "qp.el" "registry.el" "rfc2231.el" "rtree.el"
- "sieve.el" "sieve-mode.el" "gnus-ems.el"
+ "earcon.el" "gnus-audio.el" "encrypt.el"
+ "gnus-move.el" "gnus-sync.el"
+ "gnus-ems.el"
;; doc
"getopt.c" "texindex.c" "news.texi" "vc.texi" "vc2-xtra.texi"
"back.texi" "vol1.texi" "vol2.texi" "elisp-covers.texi" "two.el"
@@ -959,6 +966,43 @@ in the repository.")
;; NB So only add a directory if needed to disambiguate.
;; FIXME?
;; Although perhaps we could let authors-disambiguate-file-name do that?
+;;
+;; WARNING: The semantics of these entries is tricky to grasp without
+;; reading the code!
+;; The rule is: for every file that was renamed or moved to another
+;; directory, add an entry (OLD-NAME . NEW-BASENAME), where OLD-NAME
+;; is the old name of the file as it appears in the ChangeLog files,
+;; and NEW-BASENAME is the _basename_ of its new name. Yes, this
+;; means that a file which was moved to another directory but kept its
+;; basename will have a seemingly-silly entry ("foo" . "foo"). (Told
+;; you: this is tricky!) If the moved/renamed file was mentioned in
+;; several ChangeLog files with different leading directories, you
+;; need to provide an entry for each such instance. For example, if
+;; some ChangeLog mentioned a moved file as lisp/gnus/something.el and
+;; another ChangeLog mentioned it as gnus/something.el, you need to
+;; have two entries:
+;;
+;; ("gnus/something.el" . "something.el")
+;; ("lisp/gnus/something.el" . "something.el")
+;;
+;; The important part is that the car of the entry should be identical
+;; to how a file was mentioned in the respective ChangeLog. It is
+;; advisable to run a Grep command such as
+;;
+;; fgrep -R BASENAME . --include='ChangeLog*'
+;;
+;; where BASENAME is the old basename of the renamed file. This will
+;; show all the different reference forms of the file in the various
+;; ChangeLog* files, and you can then prepare a separate entry for
+;; each reference form.
+;;
+;; The cdr of the entry should generally be only the basename of the
+;; file's current name, because that's how AUTHORS references files.
+;; It _can_ have leading directories, but that is only
+;; needed/advisable if there are several files in the tree that have
+;; the same basename, and you want to disambiguate them, so that
+;; people who actually contributed to different files aren't mentioned
+;; as if they contributed to the same single file.
(defconst authors-renamed-files-alist
'(("nt.c" . "w32.c") ("nt.h" . "w32.h")
("ntheap.c" . "w32heap.c") ("ntheap.h" . "w32heap.h")
@@ -966,8 +1010,9 @@ in the repository.")
("ntproc.c" . "w32proc.c")
("w32console.c" . "w32term.c")
("unexnt.c" . "unexw32.c")
- ("s/windowsnt.h" . "s/ms-w32.h")
- ("s/ms-w32.h" . "inc/ms-w32.h")
+ ("m/windowsnt.h" . "ms-w32.h")
+ ("s/windowsnt.h" . "ms-w32.h")
+ ("s/ms-w32.h" . "ms-w32.h")
("src/config.h" . "config.h")
("winnt.el" . "w32-fns.el")
("linux.h" . "gnu-linux.h")
@@ -990,6 +1035,10 @@ in the repository.")
("INSTALL.MSYS" . "INSTALL")
("server.c" . "emacsserver.c")
("lib-src/etags.c" . "etags.c")
+ ;; gnulib
+ ("lib/strftime.c" . "nstrftime.c")
+ ("src/mini-gmp.c" . "mini-gmp.c")
+ ("src/mini-gmp.h" . "mini-gmp.h")
;; msdos/
("is-exec.c" . "is_exec.c")
("enriched.doc" . "enriched.txt")
@@ -1073,8 +1122,10 @@ in the repository.")
("nxml/test.invalid.xml" . "test-invalid.xml")
("nxml/test.valid.xml" . "test-valid.xml")
("automated/Makefile.in" . "test/Makefile.in")
- ("test/rmailmm.el" . "test/manual/rmailmm.el")
- ("rmailmm.el" . "test/manual/rmailmm.el")
+ ;; rmailmm tests wandered from test/ to test/manual to test/lisp/mail/
+ ("rmailmm.el" . "rmailmm-tests.el")
+ ("test/rmailmm.el" . "rmailmm-tests.el")
+ ("test/manual/rmailmm.el" . "rmailmm-tests.el")
;; The one in lisp is eshell/eshell.el.
("eshell.el" . "eshell-tests.el")
("automated/eshell.el" . "eshell-tests.el")
@@ -1106,22 +1157,79 @@ in the repository.")
("major.texi" . "modes.texi")
("msdog-xtra.texi" . "msdos-xtra.texi")
("msdog.texi" . "msdos.texi")
+ ;; Moved from lisp/gnus/ to lisp/
+ ("auth-source.el" . "auth-source.el")
+ ("lisp/gnus/auth-source.el" . "auth-source.el")
+ ("ecomplete.el" . "ecomplete.el")
+ ("format-spec.el" . "format-spec.el")
+ ("gnus/format-spec.el" . "format-spec.el")
+ ("lisp/gnus/ecomplete.el" . "ecomplete.el")
+ ("plstore.el" . "plstore.el")
+ ("lisp/gnus/plstore.el" . "plstore.el")
+ ("registry.el" . "registry.el")
+ ("lisp/gnus/registry.el" . "registry.el")
+ ("rtree.el" . "rtree.el")
;; Moved from lisp/gnus/ to lisp/calendar/
- ("time-date.el" . "calendar/time-date.el")
+ ("time-date.el" . "time-date.el")
;; Moved from lisp/gnus/ to lisp/mail/
- ("binhex.el" . "mail/binhex.el")
- ("uudecode.el" . "mail/uudecode.el")
- ("mail-parse.el" . "mail/mail-parse.el")
- ("yenc.el" . "mail/yenc.el")
- ("flow-fill.el" . "mail/flow-fill.el")
- ("ietf-drums.el" . "mail/ietf-drums.el")
- ("sieve-manage.el" . "mail/sieve-manage.el")
+ ("binhex.el" . "binhex.el")
+ ("gnus/binhex.el" . "binhex.el")
+ ("uudecode.el" . "uudecode.el")
+ ("gnus/uudecode.el" . "uudecode.el")
+ ("mail-parse.el" . "mail-parse.el")
+ ("gnus/mail-parse.el" . "mail-parse.el")
+ ("mail-prsvr.el" . "mail-prsvr.el")
+ ("gnus/mail-prsvr.el" . "mail-prsvr.el")
+ ("yenc.el" . "yenc.el")
+ ("flow-fill.el" . "flow-fill.el")
+ ("gnus/flow-fill.el" . "flow-fill.el")
+ ("ietf-drums.el" . "ietf-drums.el")
+ ("gnus/ietf-drums.el" . "ietf-drums.el")
+ ("pop3.el" . "pop3.el")
+ ("mail/pop3.el" . "pop3.el")
+ ("gnus/pop3.el" . "pop3.el")
+ ("lisp/gnus/pop3.el" . "pop3.el")
+ ("qp.el" . "qp.el")
+ ("gnus/qp.el" . "qp.el")
+ ("lisp/gnus/qp.el" . "qp.el")
+ ("rfc2045.el" . "rfc2045.el")
+ ("gnus/rfc2045.el" . "rfc2045.el")
+ ("rfc2047.el" . "rfc2047.el")
+ ("gnus/rfc2047.el" . "rfc2047.el")
+ ("rfc2231.el" . "rfc2231.el")
+ ("gnus/rfc2231.el" . "rfc2231.el")
+ ("lisp/gnus/rfc2231.el" . "rfc2231.el")
;; Moved from lisp/gnus/ to lisp/image/
- ("compface.el" . "image/compface.el")
+ ("compface.el" . "compface.el")
+ ("gravatar.el" . "gravatar.el")
+ ("lisp/gnus/gravatar.el" . "gravatar.el")
;; Moved from lisp/gnus/ to lisp/net/
+ ("eww.el" . "eww.el")
+ ("net/eww.el" . "eww.el")
+ ("lisp/new/eww.el" . "eww.el") ; an actual typo in ChangeLog.3
+ ("gssapi.el" . "gssapi.el")
+ ("lisp/gnus/gssapi.el" . "gssapi.el")
("imap.el" . "net/imap.el")
+ ("mailcap.el" . "mailcap.el")
+ ("gnus/mailcap.el" . "mailcap.el")
+ ("lisp/gnus/mailcap.el" . "mailcap.el")
("rfc2104.el" . "net/rfc2104.el")
- ("starttls.el" . "net/starttls.el")
+ ("starttls.el" . "starttls.el")
+ ("lisp/net/starttls.el" . "starttls.el") ; moved to obsolete/
+ ("shr.el" . "shr.el")
+ ("net/shr.el" . "shr.el")
+ ("shr-color.el" . "shr-color.el")
+ ("sieve-manage.el" . "sieve-manage.el")
+ ("sieve-mode.el" . "sieve-mode.el")
+ ("sieve.el" . "sieve.el")
+ ("lisp/gnus/sieve-manage.el" . "sieve-manage.el")
+ ("lisp/gnus/sieve-mode.el" . "sieve-mode.el")
+ ("lisp/gnus/sieve.el" . "sieve.el")
+ ;; Moved from lisp/gnus/ to lisp/international
+ ("rfc1843.el" . "rfc1843.el")
+ ("gnus/rfc1843.el" . "rfc1843.el")
+ ("utf7.el" . "utf7.el")
+ ("gnus/utf7.el" . "utf7.el")
;; And from emacs/ to misc/ and back again.
("ns-emacs.texi" . "macos.texi")
("overrides.texi" . "gnus-overrides.texi")
@@ -1136,7 +1244,7 @@ in the repository.")
("ED.WORSHIP" . "JOKES")
("GNU.JOKES" . "JOKES")
("CHARACTERS" . "TODO")
- ("lisp/character-fold.el" . "lisp/char-fold.el")
+ ("lisp/character-fold.el" . "char-fold.el")
("test/automated/character-fold-tests.el" . "char-fold-tests.el")
("test/automated/char-fold-tests.el" . "char-fold-tests.el")
("test/lisp/character-fold-tests.el" . "char-fold-tests.el")
@@ -1178,7 +1286,8 @@ in the repository.")
("grammars" . "grammars")
;; Moved from lisp/emacs-lisp/ to admin/.
("emacs-lisp/authors.el" . "authors.el")
- ("emacs-lisp/find-gc.el" . "admin/find-gc.el")
+ ("find-gc.el" . "find-gc.el")
+ ("emacs-lisp/find-gc.el" . "find-gc.el")
;; From etc to lisp/cedet/semantic/.
("grammars/bovine-grammar.el" . "bovine/grammar.el")
("grammars/wisent-grammar.el" . "wisent/grammar.el")
@@ -1186,28 +1295,41 @@ in the repository.")
("nt/README.W32" . "README.W32")
("notes/BRANCH" . "notes/repo")
("notes/bzr" . "notes/repo")
- ;; moved from lisp/ to lisp/net/
- ("lisp/pinentry.el" . "lisp/net/pinentry.el")
+ ;; moved from lisp/ to lisp/net/, then removed
+ ("pinentry.el" . "pinentry.el")
+ ("lisp/pinentry.el" . "pinentry.el")
+ ("lisp/net/pinentry.el" . "pinentry.el")
;; module.* moved to emacs-module.*
- ("src/module.h" . "src/emacs-module.h")
- ("src/module.c" . "src/emacs-module.c")
- ;; gnulib
- ("lib/strftime.c" . "lib/nstrftime.c")
- ("test/src/regex-tests.el" . "test/src/regex-emacs-tests.el")
- ("test/lisp/emacs-lisp/cl-tests.el" . "test/lisp/obsolete/cl-tests.el")
- ("lisp/net/starttls.el" . "lisp/obsolete/starttls.el")
- ("url-ns.el" . "lisp/obsolete/url-ns.el")
- ("gnus-news.texi" . "doc/misc/gnus.texi")
- ("lisp/multifile.el" . "lisp/fileloop.el")
- ("lisp/emacs-lisp/thread.el" . "lisp/thread.el")
- ("lisp/emacs-lisp/cl.el" . "lisp/emacs-lisp/cl-lib.el")
- ("lisp/progmodes/mantemp.el" . "lisp/obsolete/mantemp.el")
- ("src/mini-gmp.c" . "lib/mini-gmp.c")
- ("src/mini-gmp.h" . "lib/mini-gmp.h")
+ ("src/module.h" . "emacs-module.h")
+ ("src/module.c" . "emacs-module.c")
+ ("test/src/regex-tests.el" . "regex-emacs-tests.el")
+ ("test/lisp/emacs-lisp/cl-tests.el" . "cl-tests.el")
+ ("url-ns.el" . "url-ns.el")
+ ("gnus-news.texi" . "gnus.texi")
+ ("doc/misc/gnus-news.texi" . "gnus.texi")
+ ("lisp/multifile.el" . "fileloop.el")
+ ("lisp/emacs-lisp/thread.el" . "thread.el")
+ ;; cl.el was retired, replaced by cl-lib.el, and we want to
+ ;; pretend they are the same file...
+ ("emacs-lisp/cl.el" . "cl-lib.el")
+ ("lisp/emacs-lisp/cl.el" . "cl-lib.el")
+ ("lisp/obsolete/cl.el" . "cl-lib.el")
+ ("mantemp.el" . "mantemp.el")
+ ("lisp/progmodes/mantemp.el" . "mantemp.el")
+ ("progmodes/mantemp.el" . "mantemp.el")
("sysdep.c" . "src/sysdep.c")
+ ;; nnir.el started in lisp/gnus/ChangeLog.*, then was
+ ;; lisp/gnus/nnir.el in ChangeLog.[123], and is now
+ ;; lisp/obsolete/nnir.el.
+ ("nnir.el" . "nnir.el")
("lisp/gnus/nnir.el" . "nnir.el")
- ("src/regex.c" . "emacs-regex.c")
- ("src/regex.h" . "emacs-regex.h")
+ ;; regex.[ch] are mentioned as src/regex.[ch] in ChangeLog.[123],
+ ;; but as just regex.[ch] in src/ChangeLog.*, so we need 2 entries
+ ;; for each one of them.
+ ("regex.c" . "regex-emacs.c")
+ ("regex.h" . "regex-emacs.h")
+ ("src/regex.c" . "regex-emacs.c")
+ ("src/regex.h" . "regex-emacs.h")
("test/manual/rmailmm.el" . "rmailmm-tests.el")
("test/lisp/cedet/semantic-utest-fmt.el" . "format-tests.el")
("test/lisp/emacs-lisp/tabulated-list-test.el" . "tabulated-list-tests.el")
@@ -1368,10 +1490,14 @@ Additionally, for these logs we apply the `lax' elements of
(defun authors-canonical-file-name (file log-file pos author)
"Return canonical file name for FILE found in LOG-FILE.
+FILE is the file name as it appears in LOG-FILE, including any
+leading directories mentioned there.
+LOG-FILE is an absolute file name of the log file we are scanning.
Checks whether FILE is a valid (existing) file name, has been renamed,
or is on the list of removed files. Returns the non-directory part of
-the file name. Only uses the LOG-FILE position POS and associated AUTHOR
-to print a message if FILE is not found."
+the file name to use for FILE in the \"AUTHORS\" file.
+Only uses the LOG-FILE position POS and associated AUTHOR to print a
+message if FILE is not found."
;; FILE should be re-checked in every different directory associated
;; with a LOG-FILE. Eg configure.ac from src/ChangeLog is not the
;; same as that from top-level/ChangeLog.
@@ -1381,6 +1507,8 @@ to print a message if FILE is not found."
(if entry
(cdr entry)
(setq relname (file-name-nondirectory file))
+ ;; File names in `authors-valid-file-names' are OK by
+ ;; definition, so no need to check those.
(if (or (member file authors-valid-file-names)
(member relname authors-valid-file-names)
(file-exists-p file)
diff --git a/admin/cus-test.el b/admin/cus-test.el
index 8f0914ff691..5894abed3df 100644
--- a/admin/cus-test.el
+++ b/admin/cus-test.el
@@ -156,7 +156,7 @@ Names should be as they appear in loaddefs.el.")
"Set by `cus-test-apropos' to a list of options with :get property.")
(defvar cus-test-vars-with-changed-state nil
- "Set by `cus-test-apropos' to a list of options with state 'changed.")
+ "Set by `cus-test-apropos' to a list of options with state \\='changed.")
(defvar cus-test-deps-errors nil
"List of require/load problems found by `cus-test-deps'.")
diff --git a/admin/emake b/admin/emake
index 2ff553289da..6c778c85d41 100755
--- a/admin/emake
+++ b/admin/emake
@@ -79,6 +79,8 @@ The GNU allocators don't work|\
^git config |\
^'\.git/|\
^\^\(\(|\
+^ANCIENT=yes make|\
+^touch -t|\
^'build-aux/git-hooks\
" | \
while read
diff --git a/admin/gitmerge.el b/admin/gitmerge.el
index 5da70a40285..a214dcbcb74 100644
--- a/admin/gitmerge.el
+++ b/admin/gitmerge.el
@@ -124,7 +124,7 @@ If nil, the function `gitmerge-default-branch' guesses.")
(let ((coding-system-for-read vc-git-log-output-coding-system))
(call-process "git" nil t nil "show" (format "%s:configure.ac" branch)))
(goto-char (point-min)))
- (re-search-forward "^AC_INIT([^,]+, \\([0-9]+\\)\\.")
+ (re-search-forward "^AC_INIT([^,]+, \\[?\\([0-9]+\\)\\.")
(string-to-number (match-string 1))))
(defun gitmerge-default-branch ()
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index 83ac2ef46ef..4ca88982cde 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -31,10 +31,11 @@ top_builddir = @top_builddir@
-include ${top_builddir}/src/verbose.mk
# Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
EMACS = ${top_builddir}/src/emacs
-emacs = EMACSLOADPATH= "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefer-newer t)'
+emacs = "${EMACS}" -batch --no-site-file --no-site-lisp \
+ --eval '(setq max-specpdl-size 5000)' --eval '(setq load-prefer-newer t)'
make_bovine = ${emacs} -l semantic/bovine/grammar -f bovine-batch-make-parser
make_wisent = ${emacs} -l semantic/wisent/grammar -f wisent-batch-make-parser
diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt
index 872cb00ca28..6990f27bfa0 100644
--- a/admin/make-tarball.txt
+++ b/admin/make-tarball.txt
@@ -15,8 +15,8 @@ Steps to take before starting on the first pretest in any release sequence:
2. Consider increasing the value of the variable
'customize-changed-options-previous-release' in cus-edit.el to
refer to a newer version of Emacs. (This is now done when cutting
- the release branch, see admin/release-branch.txt.)
- Commit cus-edit.el if changed.
+ the release branch, see admin/release-branch.txt, but it can't
+ hurt to double check its value.) Commit cus-edit.el if changed.
3. Remove any old pretests from https://alpha.gnu.org/gnu/emacs/pretest.
You can use 'gnupload --delete' (see below for more gnupload details).
@@ -24,8 +24,8 @@ Steps to take before starting on the first pretest in any release sequence:
General steps (for each step, check for possible errors):
-1. git pull # fetch from the repository
- git status # check for locally modified files
+1. git pull # fetch from the repository
+ git status # check for locally modified files
Ensure that you have a clean, unmodified state.
If you switched in-place from another branch to the release branch,
@@ -43,18 +43,45 @@ General steps (for each step, check for possible errors):
because some of the commands below run Make, so they need
Makefiles to be present.
- For Emacs 28, and as long as --with-native-compilation is not the
- default, the tree needs to be configured with native-compilation
- enabled, to ensure all the pertinent *.elc files will end up in
- the tarball. Otherwise, the *.eln files might not build correctly
- on the user's system.
+ For Emacs 28 and later, as long as --with-native-compilation is
+ not the default, the tree needs to be configured with
+ native-compilation enabled, to ensure all the pertinent *.elc
+ files will end up in the tarball. Otherwise, the *.eln files
+ might not build correctly on the user's system.
+
+ ./autogen.sh
+ ./configure --with-native-compilation && make
+
+ For a release (as opposed to pretest), delete any left-over "---"
+ and "+++" markers from etc/NEWS, as well as the "Temporary note"
+ section at the beginning of that file, and commit etc/NEWS if it
+ was modified.
+
+2. Regenerate the versioned ChangeLog.N and etc/AUTHORS files.
+
+ The "M-x authors" command below will first update the current
+ versioned ChangeLog.N file. For this to work correctly, make sure
+ the top-level Makefile says
+
+ PREFERRED_BRANCH = emacs-NN
+
+ where NN is the version on the release branch from which you are
+ producing the tarball. If NN is incorrect, update Makefile.in and
+ re-run 'configure' to update Makefile.
+
+ If the versioned ChangeLog.N file is too large, start a new one
+ by bumping N, and also update the line in top-level Makefile.in
+ which says
+
+ CHANGELOG_HISTORY_INDEX_MAX = N
+
+ by incrementing the value of N by 1; then regenerate Makefile.
+
+ Now:
-2. Regenerate the etc/AUTHORS file:
M-: (require 'authors) RET
M-x authors RET
- (This first updates the current versioned ChangeLog.N)
-
If this says "Problem updating ChangeLog", find the reason for the
failure of the command it runs, viz.:
@@ -134,13 +161,15 @@ General steps (for each step, check for possible errors):
5. Copy lisp/loaddefs.el to lisp/ldefs-boot.el.
- Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the
- files changed by M-x set-version. The easiest way of doing that
- is "C-x v d ROOT-DIR RET", then go to the first modified file,
- press 'M' to mark all modified files, and finally 'v' to commit
- them. Make sure the commit log message mentions all the changes
- in all modified files, as by default 'v' doesn't necessarily do
- so.
+ Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the files
+ changed by M-x set-version. Note that the set-version changes
+ should be committed separately, as described in step 3 above.
+
+ The easiest way of doing that is "C-x v d ROOT-DIR RET", then go
+ to the first modified file, press 'M' to mark all modified files,
+ and finally 'v' to commit them. Make sure the commit log message
+ mentions all the changes in all modified files, as by default 'v'
+ doesn't necessarily do so.
If someone else made a commit between step 1 and now,
you need to repeat from step 4 onwards. (You can commit the files
@@ -232,7 +261,9 @@ General steps (for each step, check for possible errors):
FILE.gz FILE.xz ...
You only need the --user part if you have multiple GPG keys and do
- not want to use the default.
+ not want to use the default. Instead of "your@gpg.key.email" you
+ could also use the fingerprint of the key, a 40-digit hex number.
+ (Alternatively, define default-key in your ~/.gnupg/gpg.conf file.)
Obviously, if you do not have a fast uplink, be prepared for the
upload to take a while.
@@ -256,7 +287,8 @@ General steps (for each step, check for possible errors):
https://alpha.gnu.org/gnu/emacs/pretest/ for a pretest, or
https://ftp.gnu.org/gnu/emacs/ for a release.
- Download them and check the signatures. Check they build.
+ Download them and check the signatures and SHA1/SHA256 checksums.
+ Check they build.
11. Send an announcement to: emacs-devel, and bcc: info-gnu-emacs@gnu.org.
For a pretest, also bcc: platform-testers@gnu.org.
@@ -274,12 +306,20 @@ General steps (for each step, check for possible errors):
To create the included SHA1 and SHA256 checksums, run:
- sha1sum emacs-NEW.tar.xz
- sha256sum emacs-NEW.tar.xz
+ sha1sum emacs-NEW.tar.xz
+ sha256sum emacs-NEW.tar.xz
+
+ You can optionally sign the announcement email, probably using the
+ same PGP key that you used for signing the tarball.
+ (Use e.g. `M-x mml-secure-message-sign' in `message-mode' to sign
+ an email.)
12. After a release, update the Emacs pages as described below.
-13. Bump the Emacs version on the release branch.
+13. After a release, bump the Emacs version on the release branch.
+ There is no need to bump the version after a pretest; the version
+ is bumped before the next pretest or release instead.
+
If the released version was XX.Y, use 'set-version' from
admin/admin.el to bump the version on the release branch to
XX.Y.50. Commit the changes.
@@ -287,8 +327,8 @@ General steps (for each step, check for possible errors):
UPDATING THE EMACS WEB PAGES AFTER A RELEASE
As soon as possible after a release, the Emacs web pages at
-https://www.gnu.org/software/emacs/ should be updated. (See
-admin/notes/www for general information.)
+https://www.gnu.org/software/emacs/ should be updated.
+(See admin/notes/www for general information.)
The pages to update are:
@@ -304,21 +344,81 @@ looks like this:
<div class="release-banner">
<div class="container">
- <h2><em>Emacs 27.1 is out</em>, download it <a href="download.html">here</a>!</h2>
+ <h2><em>Emacs 28.1 is out</em>, download it <a href="download.html">here</a>!</h2>
</div>
</div>
-Regenerate the various manuals in manual/.
-The scripts admin/make-manuals and admin/upload-manuals summarize the process.
-
-If you have Texinfo installed locally, make-manuals might fail if it
-cannot find epsf.tex. In that case define in the environment
-
- TEXINPUTS=:/path/to/texinfo-tree/doc
-
-where /path/to/texinfo-tree is the absolute file name of the top-level
-directory where you have the Texinfo source tree. Then re-run
-make-manuals.
+Also, make sure the copyright years at the bottom of emacs.html are
+up-to-date.
+
+The file download.html may need to be updated, for example if the
+MS-Windows binaries will be signed by a different person/key than
+those mentioned there.
+
+Next, regenerate the various manuals in HTML, PDF, and PS formats:
+
+ Invoke ./admin/make-manuals from the top-level directory of the
+ Emacs source tree that contains the manuals for which you want to
+ produce HTML docs. This creates the 'manual' directory and
+ populates it with the necessary files.
+
+ If you have Texinfo installed locally, make-manuals might fail if it
+ cannot find epsf.tex. In that case define in the environment
+
+ TEXINPUTS=:/path/to/texinfo-tree/doc
+
+ where /path/to/texinfo-tree is the absolute file name of the
+ top-level directory where you have the Texinfo source tree. Then
+ re-run make-manuals.
+
+ make-manuals can also fail if the HTML manuals produced by Texinfo
+ violate some of the assumptions admin/admin.el makes about the
+ format of the produced HTML. Debug these problems and resolve them,
+ then re-run make-manuals. (Each time you run make-manuals, it
+ empties the manuals/ directory and regenerates the files there, but
+ if the files in manuals/ can be used without regeneration, i.e. if
+ the problem you solved doesn't affect the produced HTML, you can
+ invoke make-manuals with the -c switch, which will make the process
+ much faster.)
+
+Now change to the 'manual' directory and invoke upload-manuals:
+
+ ../admin/updload-manuals /path/to/webpages/cvs/checkout
+
+ where /path/to/webpages/cvs/checkout is the place where you have the
+ CVS checkout of the Emacs Web pages, with subdirectories 'manual'
+ and 'refcards'. This moves the produced manuals to directories in
+ the Web pages CVS checkout tree, and also invokes CVS commands to
+ commit changed files, add new files, and remove stale files that are
+ no longer part of the manuals.
+
+ If upload-manuals fails, resolve the problems and re-invoke it.
+ This requires running make-manuals again, since upload-manuals
+ destructively modifies the 'manual' directory where you invoke it.
+ Also, upload-manuals invokes "cvs commit -f", so if you run it
+ several times, some files will be committed more than once even
+ though they were not changed in-between. Suck it up.
+
+ All the added and removed files need to be committed, so next fire
+ up Emacs, type "C-x v d" to invoke vc-dir on the Web pages checkout,
+ and use "C-x v v" and other VC commands to commit all the files that
+ upload-manuals didn't automatically commit. (You can also do that
+ with manual CVS commands, of course, but this is not recommended.)
+
+ Next, make sure that manual/index.html file is consistent with the
+ info/dir file in the branch for which you are producing the manuals,
+ in that it mentions all the manuals. It could be outdated if
+ manuals were added or removed since the last release.
+
+ For each new manual, a file manual/MANUAL.html (where MANUAL is the
+ name of the manual) should be created from the template in
+ manual/eww.html, after editing the title and the Copyright years,
+ and the links in it changed to point to the appropriate files in the
+ manual/html_node/ and manual/html_mono/ subdirectories.
+
+ In addition, the file refcards/index.html should be audited to make
+ sure it includes the up-to-date list of refcards actually produced
+ and put under that subdirectory.
Browsing <https://web.cvs.savannah.gnu.org/viewvc/?root=emacs> is one
way to check for any files that still need updating.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 73b3d390499..4dd6a4d222f 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -40,7 +40,7 @@ GNULIB_MODULES='
getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
ieee754-h ignore-value intprops largefile libgmp lstat
manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime
- nproc nstrftime
+ nanosleep nproc nstrftime
pathmax pipe2 pselect pthread_sigmask
qcopy-acl readlink readlinkat regex
sig2str sigdescr_np socklen stat-time std-gnu11 stdalign stddef stdio
@@ -51,7 +51,7 @@ GNULIB_MODULES='
'
AVOIDED_MODULES='
- btowc close crypto/af_alg dup fchdir fstat langinfo lock
+ btowc chmod close crypto/af_alg dup fchdir fstat langinfo lock
mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo
openat-die opendir pthread-h raise
save-cwd select setenv sigprocmask stat stdarg stdbool
@@ -102,6 +102,12 @@ test -x "$gnulib_srcdir"/gnulib-tool || {
exit 1
}
+# gnulib-tool has problems with a bare checkout (Bug#32452#65).
+test -f configure || ./autogen.sh || exit
+
+# Old caches can confuse autoconf when some Gnulib-related changes take effect.
+rm -fr autom4te.cache || exit
+
avoided_flags=
for module in $AVOIDED_MODULES; do
avoided_flags="$avoided_flags --avoid=$module"
@@ -109,7 +115,9 @@ done
"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS \
$avoided_flags $GNULIB_MODULES &&
-rm -- "$src"lib/gl_openssl.h "$src"m4/fcntl-o.m4 \
+rm -- "$src"lib/gl_openssl.h \
+ "$src"lib/stdio-read.c "$src"lib/stdio-write.c \
+ "$src"m4/fcntl-o.m4 \
"$src"m4/gl-openssl.m4 \
"$src"m4/gnulib-cache.m4 "$src"m4/gnulib-tool.m4 \
"$src"m4/manywarnings-c++.m4 \
diff --git a/admin/notes/emba b/admin/notes/emba
index 99237ea5f63..4c8c27dfeaa 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -8,7 +8,8 @@ NOTES FOR EMACS CONTINUOUS BUILD ON EMBA
A continuous build for Emacs can be found at
<https://emba.gnu.org/emacs/emacs>, a Gitlab instance. It watches the
Emacs git repository and starts a pipeline (jobset) if there are new
-changes. This happens for all Emacs branches.
+changes. This happens for all Emacs branches which belong to the
+defined workflow (see below).
* Mail notifications
@@ -32,7 +33,11 @@ The Emacs jobset is defined in the Emacs source tree, file
'test/infra'. They could be adapted for every Emacs branch, see
<https://emba.gnu.org/help/ci/yaml/README.md>.
-A jobset on Gitlab is called pipeline. Emacs pipelines run through
+Only branches whose name starts with 'master', 'emacs', 'feature', or
+'fix' are considered. This is declared in the workflow rules of file
+'test/infra/gitlab-ci.yml'.
+
+A jobset on Gitlab is called a pipeline. Emacs pipelines run through
the stages 'build-images', 'platform-images' and 'native-comp-images'
(create an Emacs instance by 'make bootstrap' with different
configuration parameters) as well as 'normal', 'platforms' and
@@ -41,11 +46,11 @@ configuration parameters) as well as 'normal', 'platforms' and
The jobs for stage 'normal' are contained in the file
'test/infra/test-jobs.yml'. This file is generated by calling 'make
-C test generate-test-jobs' in the Emacs source tree, and the
-resulting file shall be pushed to the Emacs git repository afterwards.
+resulting file should be pushed to the Emacs git repository afterwards.
Every job runs in a Debian docker container. It uses the local clone
of the Emacs git repository to perform a bootstrap and test of Emacs.
-This could happen for several jobs with changed configuration, compile
+This could happen for several jobs with changed configuration, compile,
and test parameters.
The 'build-image-*' jobs of the different '*-images' stages run only
diff --git a/admin/notes/multi-tty b/admin/notes/multi-tty
index 9b3f1606a1b..84bc1b77d4e 100644
--- a/admin/notes/multi-tty
+++ b/admin/notes/multi-tty
@@ -474,7 +474,7 @@ THINGS TO DO
definition.
Exceptions found so far: x-select-text and
- x-selection-value (old name: x-cut-buffer-or-selection-value).
+ x-selection-value.
** Have a look at fatal_error_hook.
diff --git a/admin/notes/unicode b/admin/notes/unicode
index 2c4b5e0106a..f699f4fb1c0 100644
--- a/admin/notes/unicode
+++ b/admin/notes/unicode
@@ -15,20 +15,32 @@ Emacs uses the following files from the Unicode Character Database
. BidiMirroring.txt
. IVD_Sequences.txt
. NormalizationTest.txt
+ . PropertyValueAliases.txt
+ . ScriptExtensions.txt
+ . Scripts.txt
. SpecialCasing.txt
+ . confusables.txt
. emoji-data.txt
. emoji-zwj-sequences.txt
. emoji-sequences.txt
. BidiCharacterTest.txt
Emacs also uses the file emoji-test.txt which should be imported from
-the Unicode's Public/emoji/ directory.
-
-First, the first 10 files and emoji-test.txt need to be copied into
-admin/unidata/, and the file https://www.unicode.org/copyright.html
-should be copied over copyright.html in admin/unidata (some of them
-might need trailing whitespace removed before they can be committed to
-the Emacs repository).
+the Unicode's Public/emoji/ directory, and IdnaMappingTable.txt from
+the Public/idna/ directory.
+
+First, the first 14 files, emoji-test.txt and IdnaMappingTable.txt
+need to be copied into admin/unidata/, and the file
+https://www.unicode.org/copyright.html should be copied over
+copyright.html in admin/unidata (some of them might need trailing
+whitespace removed before they can be committed to the Emacs
+repository).
+
+Next, review the assignment of default values of the Bidi Class
+property to blocks in the file extracted/DerivedBidiClass.txt from the
+UCD (search for "unassigned" in that file). Any changes should be
+reflected in the unidata-gen.el file, where it sets up the default
+values around line 210.
Then Emacs should be rebuilt for them to take effect. Rebuilding
Emacs updates several derived files elsewhere in the Emacs source
diff --git a/admin/nt/dist-build/README-scripts b/admin/nt/dist-build/README-scripts
index 6b1adbe03e1..e99fbe07062 100644
--- a/admin/nt/dist-build/README-scripts
+++ b/admin/nt/dist-build/README-scripts
@@ -131,7 +131,7 @@ The process is the same as for building from the master branch, except
that the release branch should already exist as a worktree, and the
version number must be added to the command line with `build-zips.sh
-V 27 -s`. The final zips will be named after the branch rather than
-the version (e.g emacs-27-2019-12-26.zip) rather than than the Emacs
+the version (e.g emacs-27-2019-12-26.zip) rather than the Emacs
version (e.g emacs-27.0.50.zip).
diff --git a/admin/nt/dist-build/build-zips.sh b/admin/nt/dist-build/build-zips.sh
index 77d20a5a7b9..39ac1fde604 100755
--- a/admin/nt/dist-build/build-zips.sh
+++ b/admin/nt/dist-build/build-zips.sh
@@ -148,7 +148,7 @@ done
if [ -z $ACTUAL_VERSION ];
then
ACTUAL_VERSION=`
- sed -n 's/^AC_INIT(GNU Emacs,[ ]*\([^ ,)]*\).*/\1/p' < ../../../configure.ac
+ sed -n 's/^AC_INIT(\[*GNU Emacs]*,[ ]*\[*\([^] ,)]*\).*/\1/p' < ../../../configure.ac
`
fi
diff --git a/admin/quick-install-emacs b/admin/quick-install-emacs
index 9a73cf5a401..b0a1d342518 100755
--- a/admin/quick-install-emacs
+++ b/admin/quick-install-emacs
@@ -172,10 +172,10 @@ test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; }
test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; }
VERSION=`
- sed -n 's/^AC_INIT([ ]*emacs[ ]*,[ ]*\([^ ),]*\).*/\1/p' <$SRC/configure.ac
+ sed -n 's/^AC_INIT([ ]*\[*emacs]*[ ]*,[ ]*\[*\([^] ),]*\).*/\1/p' <$SRC/configure.ac
` || exit 4
test -n "$VERSION" || VERSION=`
- sed -n 's/^AC_INIT([ ]*GNU Emacs[ ]*,[ ]*\([^ ),]*\).*/\1/p' <$SRC/configure.ac
+ sed -n 's/^AC_INIT([ ]*\[*GNU Emacs]*[ ]*,[ ]*\[*\([^] ),]*\).*/\1/p' <$SRC/configure.ac
` || exit 4
test -n "$VERSION" || { printf '%s\n' >&2 "$me: no version in configure.ac"; exit 4; }
diff --git a/admin/unidata/IdnaMappingTable.txt b/admin/unidata/IdnaMappingTable.txt
new file mode 100644
index 00000000000..1b862827ef7
--- /dev/null
+++ b/admin/unidata/IdnaMappingTable.txt
@@ -0,0 +1,8921 @@
+# IdnaMappingTable.txt
+# Date: 2021-07-10, 00:49:51 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 IDNA Compatible Preprocessing for UTS #46
+# Version: 14.0.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr46
+#
+0000..002C ; disallowed_STD3_valid # 1.1 <control-0000>..COMMA
+002D..002E ; valid # 1.1 HYPHEN-MINUS..FULL STOP
+002F ; disallowed_STD3_valid # 1.1 SOLIDUS
+0030..0039 ; valid # 1.1 DIGIT ZERO..DIGIT NINE
+003A..0040 ; disallowed_STD3_valid # 1.1 COLON..COMMERCIAL AT
+0041 ; mapped ; 0061 # 1.1 LATIN CAPITAL LETTER A
+0042 ; mapped ; 0062 # 1.1 LATIN CAPITAL LETTER B
+0043 ; mapped ; 0063 # 1.1 LATIN CAPITAL LETTER C
+0044 ; mapped ; 0064 # 1.1 LATIN CAPITAL LETTER D
+0045 ; mapped ; 0065 # 1.1 LATIN CAPITAL LETTER E
+0046 ; mapped ; 0066 # 1.1 LATIN CAPITAL LETTER F
+0047 ; mapped ; 0067 # 1.1 LATIN CAPITAL LETTER G
+0048 ; mapped ; 0068 # 1.1 LATIN CAPITAL LETTER H
+0049 ; mapped ; 0069 # 1.1 LATIN CAPITAL LETTER I
+004A ; mapped ; 006A # 1.1 LATIN CAPITAL LETTER J
+004B ; mapped ; 006B # 1.1 LATIN CAPITAL LETTER K
+004C ; mapped ; 006C # 1.1 LATIN CAPITAL LETTER L
+004D ; mapped ; 006D # 1.1 LATIN CAPITAL LETTER M
+004E ; mapped ; 006E # 1.1 LATIN CAPITAL LETTER N
+004F ; mapped ; 006F # 1.1 LATIN CAPITAL LETTER O
+0050 ; mapped ; 0070 # 1.1 LATIN CAPITAL LETTER P
+0051 ; mapped ; 0071 # 1.1 LATIN CAPITAL LETTER Q
+0052 ; mapped ; 0072 # 1.1 LATIN CAPITAL LETTER R
+0053 ; mapped ; 0073 # 1.1 LATIN CAPITAL LETTER S
+0054 ; mapped ; 0074 # 1.1 LATIN CAPITAL LETTER T
+0055 ; mapped ; 0075 # 1.1 LATIN CAPITAL LETTER U
+0056 ; mapped ; 0076 # 1.1 LATIN CAPITAL LETTER V
+0057 ; mapped ; 0077 # 1.1 LATIN CAPITAL LETTER W
+0058 ; mapped ; 0078 # 1.1 LATIN CAPITAL LETTER X
+0059 ; mapped ; 0079 # 1.1 LATIN CAPITAL LETTER Y
+005A ; mapped ; 007A # 1.1 LATIN CAPITAL LETTER Z
+005B..0060 ; disallowed_STD3_valid # 1.1 LEFT SQUARE BRACKET..GRAVE ACCENT
+0061..007A ; valid # 1.1 LATIN SMALL LETTER A..LATIN SMALL LETTER Z
+007B..007F ; disallowed_STD3_valid # 1.1 LEFT CURLY BRACKET..<control-007F>
+0080..009F ; disallowed # 1.1 <control-0080>..<control-009F>
+00A0 ; disallowed_STD3_mapped ; 0020 # 1.1 NO-BREAK SPACE
+00A1..00A7 ; valid ; ; NV8 # 1.1 INVERTED EXCLAMATION MARK..SECTION SIGN
+00A8 ; disallowed_STD3_mapped ; 0020 0308 # 1.1 DIAERESIS
+00A9 ; valid ; ; NV8 # 1.1 COPYRIGHT SIGN
+00AA ; mapped ; 0061 # 1.1 FEMININE ORDINAL INDICATOR
+00AB..00AC ; valid ; ; NV8 # 1.1 LEFT-POINTING DOUBLE ANGLE QUOTATION MARK..NOT SIGN
+00AD ; ignored # 1.1 SOFT HYPHEN
+00AE ; valid ; ; NV8 # 1.1 REGISTERED SIGN
+00AF ; disallowed_STD3_mapped ; 0020 0304 # 1.1 MACRON
+00B0..00B1 ; valid ; ; NV8 # 1.1 DEGREE SIGN..PLUS-MINUS SIGN
+00B2 ; mapped ; 0032 # 1.1 SUPERSCRIPT TWO
+00B3 ; mapped ; 0033 # 1.1 SUPERSCRIPT THREE
+00B4 ; disallowed_STD3_mapped ; 0020 0301 # 1.1 ACUTE ACCENT
+00B5 ; mapped ; 03BC # 1.1 MICRO SIGN
+00B6 ; valid ; ; NV8 # 1.1 PILCROW SIGN
+00B7 ; valid # 1.1 MIDDLE DOT
+00B8 ; disallowed_STD3_mapped ; 0020 0327 # 1.1 CEDILLA
+00B9 ; mapped ; 0031 # 1.1 SUPERSCRIPT ONE
+00BA ; mapped ; 006F # 1.1 MASCULINE ORDINAL INDICATOR
+00BB ; valid ; ; NV8 # 1.1 RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BC ; mapped ; 0031 2044 0034 #1.1 VULGAR FRACTION ONE QUARTER
+00BD ; mapped ; 0031 2044 0032 #1.1 VULGAR FRACTION ONE HALF
+00BE ; mapped ; 0033 2044 0034 #1.1 VULGAR FRACTION THREE QUARTERS
+00BF ; valid ; ; NV8 # 1.1 INVERTED QUESTION MARK
+00C0 ; mapped ; 00E0 # 1.1 LATIN CAPITAL LETTER A WITH GRAVE
+00C1 ; mapped ; 00E1 # 1.1 LATIN CAPITAL LETTER A WITH ACUTE
+00C2 ; mapped ; 00E2 # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+00C3 ; mapped ; 00E3 # 1.1 LATIN CAPITAL LETTER A WITH TILDE
+00C4 ; mapped ; 00E4 # 1.1 LATIN CAPITAL LETTER A WITH DIAERESIS
+00C5 ; mapped ; 00E5 # 1.1 LATIN CAPITAL LETTER A WITH RING ABOVE
+00C6 ; mapped ; 00E6 # 1.1 LATIN CAPITAL LETTER AE
+00C7 ; mapped ; 00E7 # 1.1 LATIN CAPITAL LETTER C WITH CEDILLA
+00C8 ; mapped ; 00E8 # 1.1 LATIN CAPITAL LETTER E WITH GRAVE
+00C9 ; mapped ; 00E9 # 1.1 LATIN CAPITAL LETTER E WITH ACUTE
+00CA ; mapped ; 00EA # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+00CB ; mapped ; 00EB # 1.1 LATIN CAPITAL LETTER E WITH DIAERESIS
+00CC ; mapped ; 00EC # 1.1 LATIN CAPITAL LETTER I WITH GRAVE
+00CD ; mapped ; 00ED # 1.1 LATIN CAPITAL LETTER I WITH ACUTE
+00CE ; mapped ; 00EE # 1.1 LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+00CF ; mapped ; 00EF # 1.1 LATIN CAPITAL LETTER I WITH DIAERESIS
+00D0 ; mapped ; 00F0 # 1.1 LATIN CAPITAL LETTER ETH
+00D1 ; mapped ; 00F1 # 1.1 LATIN CAPITAL LETTER N WITH TILDE
+00D2 ; mapped ; 00F2 # 1.1 LATIN CAPITAL LETTER O WITH GRAVE
+00D3 ; mapped ; 00F3 # 1.1 LATIN CAPITAL LETTER O WITH ACUTE
+00D4 ; mapped ; 00F4 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+00D5 ; mapped ; 00F5 # 1.1 LATIN CAPITAL LETTER O WITH TILDE
+00D6 ; mapped ; 00F6 # 1.1 LATIN CAPITAL LETTER O WITH DIAERESIS
+00D7 ; valid ; ; NV8 # 1.1 MULTIPLICATION SIGN
+00D8 ; mapped ; 00F8 # 1.1 LATIN CAPITAL LETTER O WITH STROKE
+00D9 ; mapped ; 00F9 # 1.1 LATIN CAPITAL LETTER U WITH GRAVE
+00DA ; mapped ; 00FA # 1.1 LATIN CAPITAL LETTER U WITH ACUTE
+00DB ; mapped ; 00FB # 1.1 LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+00DC ; mapped ; 00FC # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS
+00DD ; mapped ; 00FD # 1.1 LATIN CAPITAL LETTER Y WITH ACUTE
+00DE ; mapped ; 00FE # 1.1 LATIN CAPITAL LETTER THORN
+00DF ; deviation ; 0073 0073 # 1.1 LATIN SMALL LETTER SHARP S
+00E0..00F6 ; valid # 1.1 LATIN SMALL LETTER A WITH GRAVE..LATIN SMALL LETTER O WITH DIAERESIS
+00F7 ; valid ; ; NV8 # 1.1 DIVISION SIGN
+00F8..00FF ; valid # 1.1 LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER Y WITH DIAERESIS
+0100 ; mapped ; 0101 # 1.1 LATIN CAPITAL LETTER A WITH MACRON
+0101 ; valid # 1.1 LATIN SMALL LETTER A WITH MACRON
+0102 ; mapped ; 0103 # 1.1 LATIN CAPITAL LETTER A WITH BREVE
+0103 ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE
+0104 ; mapped ; 0105 # 1.1 LATIN CAPITAL LETTER A WITH OGONEK
+0105 ; valid # 1.1 LATIN SMALL LETTER A WITH OGONEK
+0106 ; mapped ; 0107 # 1.1 LATIN CAPITAL LETTER C WITH ACUTE
+0107 ; valid # 1.1 LATIN SMALL LETTER C WITH ACUTE
+0108 ; mapped ; 0109 # 1.1 LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0109 ; valid # 1.1 LATIN SMALL LETTER C WITH CIRCUMFLEX
+010A ; mapped ; 010B # 1.1 LATIN CAPITAL LETTER C WITH DOT ABOVE
+010B ; valid # 1.1 LATIN SMALL LETTER C WITH DOT ABOVE
+010C ; mapped ; 010D # 1.1 LATIN CAPITAL LETTER C WITH CARON
+010D ; valid # 1.1 LATIN SMALL LETTER C WITH CARON
+010E ; mapped ; 010F # 1.1 LATIN CAPITAL LETTER D WITH CARON
+010F ; valid # 1.1 LATIN SMALL LETTER D WITH CARON
+0110 ; mapped ; 0111 # 1.1 LATIN CAPITAL LETTER D WITH STROKE
+0111 ; valid # 1.1 LATIN SMALL LETTER D WITH STROKE
+0112 ; mapped ; 0113 # 1.1 LATIN CAPITAL LETTER E WITH MACRON
+0113 ; valid # 1.1 LATIN SMALL LETTER E WITH MACRON
+0114 ; mapped ; 0115 # 1.1 LATIN CAPITAL LETTER E WITH BREVE
+0115 ; valid # 1.1 LATIN SMALL LETTER E WITH BREVE
+0116 ; mapped ; 0117 # 1.1 LATIN CAPITAL LETTER E WITH DOT ABOVE
+0117 ; valid # 1.1 LATIN SMALL LETTER E WITH DOT ABOVE
+0118 ; mapped ; 0119 # 1.1 LATIN CAPITAL LETTER E WITH OGONEK
+0119 ; valid # 1.1 LATIN SMALL LETTER E WITH OGONEK
+011A ; mapped ; 011B # 1.1 LATIN CAPITAL LETTER E WITH CARON
+011B ; valid # 1.1 LATIN SMALL LETTER E WITH CARON
+011C ; mapped ; 011D # 1.1 LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+011D ; valid # 1.1 LATIN SMALL LETTER G WITH CIRCUMFLEX
+011E ; mapped ; 011F # 1.1 LATIN CAPITAL LETTER G WITH BREVE
+011F ; valid # 1.1 LATIN SMALL LETTER G WITH BREVE
+0120 ; mapped ; 0121 # 1.1 LATIN CAPITAL LETTER G WITH DOT ABOVE
+0121 ; valid # 1.1 LATIN SMALL LETTER G WITH DOT ABOVE
+0122 ; mapped ; 0123 # 1.1 LATIN CAPITAL LETTER G WITH CEDILLA
+0123 ; valid # 1.1 LATIN SMALL LETTER G WITH CEDILLA
+0124 ; mapped ; 0125 # 1.1 LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0125 ; valid # 1.1 LATIN SMALL LETTER H WITH CIRCUMFLEX
+0126 ; mapped ; 0127 # 1.1 LATIN CAPITAL LETTER H WITH STROKE
+0127 ; valid # 1.1 LATIN SMALL LETTER H WITH STROKE
+0128 ; mapped ; 0129 # 1.1 LATIN CAPITAL LETTER I WITH TILDE
+0129 ; valid # 1.1 LATIN SMALL LETTER I WITH TILDE
+012A ; mapped ; 012B # 1.1 LATIN CAPITAL LETTER I WITH MACRON
+012B ; valid # 1.1 LATIN SMALL LETTER I WITH MACRON
+012C ; mapped ; 012D # 1.1 LATIN CAPITAL LETTER I WITH BREVE
+012D ; valid # 1.1 LATIN SMALL LETTER I WITH BREVE
+012E ; mapped ; 012F # 1.1 LATIN CAPITAL LETTER I WITH OGONEK
+012F ; valid # 1.1 LATIN SMALL LETTER I WITH OGONEK
+0130 ; mapped ; 0069 0307 # 1.1 LATIN CAPITAL LETTER I WITH DOT ABOVE
+0131 ; valid # 1.1 LATIN SMALL LETTER DOTLESS I
+0132..0133 ; mapped ; 0069 006A # 1.1 LATIN CAPITAL LIGATURE IJ..LATIN SMALL LIGATURE IJ
+0134 ; mapped ; 0135 # 1.1 LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0135 ; valid # 1.1 LATIN SMALL LETTER J WITH CIRCUMFLEX
+0136 ; mapped ; 0137 # 1.1 LATIN CAPITAL LETTER K WITH CEDILLA
+0137..0138 ; valid # 1.1 LATIN SMALL LETTER K WITH CEDILLA..LATIN SMALL LETTER KRA
+0139 ; mapped ; 013A # 1.1 LATIN CAPITAL LETTER L WITH ACUTE
+013A ; valid # 1.1 LATIN SMALL LETTER L WITH ACUTE
+013B ; mapped ; 013C # 1.1 LATIN CAPITAL LETTER L WITH CEDILLA
+013C ; valid # 1.1 LATIN SMALL LETTER L WITH CEDILLA
+013D ; mapped ; 013E # 1.1 LATIN CAPITAL LETTER L WITH CARON
+013E ; valid # 1.1 LATIN SMALL LETTER L WITH CARON
+013F..0140 ; mapped ; 006C 00B7 # 1.1 LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN SMALL LETTER L WITH MIDDLE DOT
+0141 ; mapped ; 0142 # 1.1 LATIN CAPITAL LETTER L WITH STROKE
+0142 ; valid # 1.1 LATIN SMALL LETTER L WITH STROKE
+0143 ; mapped ; 0144 # 1.1 LATIN CAPITAL LETTER N WITH ACUTE
+0144 ; valid # 1.1 LATIN SMALL LETTER N WITH ACUTE
+0145 ; mapped ; 0146 # 1.1 LATIN CAPITAL LETTER N WITH CEDILLA
+0146 ; valid # 1.1 LATIN SMALL LETTER N WITH CEDILLA
+0147 ; mapped ; 0148 # 1.1 LATIN CAPITAL LETTER N WITH CARON
+0148 ; valid # 1.1 LATIN SMALL LETTER N WITH CARON
+0149 ; mapped ; 02BC 006E # 1.1 LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+014A ; mapped ; 014B # 1.1 LATIN CAPITAL LETTER ENG
+014B ; valid # 1.1 LATIN SMALL LETTER ENG
+014C ; mapped ; 014D # 1.1 LATIN CAPITAL LETTER O WITH MACRON
+014D ; valid # 1.1 LATIN SMALL LETTER O WITH MACRON
+014E ; mapped ; 014F # 1.1 LATIN CAPITAL LETTER O WITH BREVE
+014F ; valid # 1.1 LATIN SMALL LETTER O WITH BREVE
+0150 ; mapped ; 0151 # 1.1 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0151 ; valid # 1.1 LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0152 ; mapped ; 0153 # 1.1 LATIN CAPITAL LIGATURE OE
+0153 ; valid # 1.1 LATIN SMALL LIGATURE OE
+0154 ; mapped ; 0155 # 1.1 LATIN CAPITAL LETTER R WITH ACUTE
+0155 ; valid # 1.1 LATIN SMALL LETTER R WITH ACUTE
+0156 ; mapped ; 0157 # 1.1 LATIN CAPITAL LETTER R WITH CEDILLA
+0157 ; valid # 1.1 LATIN SMALL LETTER R WITH CEDILLA
+0158 ; mapped ; 0159 # 1.1 LATIN CAPITAL LETTER R WITH CARON
+0159 ; valid # 1.1 LATIN SMALL LETTER R WITH CARON
+015A ; mapped ; 015B # 1.1 LATIN CAPITAL LETTER S WITH ACUTE
+015B ; valid # 1.1 LATIN SMALL LETTER S WITH ACUTE
+015C ; mapped ; 015D # 1.1 LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+015D ; valid # 1.1 LATIN SMALL LETTER S WITH CIRCUMFLEX
+015E ; mapped ; 015F # 1.1 LATIN CAPITAL LETTER S WITH CEDILLA
+015F ; valid # 1.1 LATIN SMALL LETTER S WITH CEDILLA
+0160 ; mapped ; 0161 # 1.1 LATIN CAPITAL LETTER S WITH CARON
+0161 ; valid # 1.1 LATIN SMALL LETTER S WITH CARON
+0162 ; mapped ; 0163 # 1.1 LATIN CAPITAL LETTER T WITH CEDILLA
+0163 ; valid # 1.1 LATIN SMALL LETTER T WITH CEDILLA
+0164 ; mapped ; 0165 # 1.1 LATIN CAPITAL LETTER T WITH CARON
+0165 ; valid # 1.1 LATIN SMALL LETTER T WITH CARON
+0166 ; mapped ; 0167 # 1.1 LATIN CAPITAL LETTER T WITH STROKE
+0167 ; valid # 1.1 LATIN SMALL LETTER T WITH STROKE
+0168 ; mapped ; 0169 # 1.1 LATIN CAPITAL LETTER U WITH TILDE
+0169 ; valid # 1.1 LATIN SMALL LETTER U WITH TILDE
+016A ; mapped ; 016B # 1.1 LATIN CAPITAL LETTER U WITH MACRON
+016B ; valid # 1.1 LATIN SMALL LETTER U WITH MACRON
+016C ; mapped ; 016D # 1.1 LATIN CAPITAL LETTER U WITH BREVE
+016D ; valid # 1.1 LATIN SMALL LETTER U WITH BREVE
+016E ; mapped ; 016F # 1.1 LATIN CAPITAL LETTER U WITH RING ABOVE
+016F ; valid # 1.1 LATIN SMALL LETTER U WITH RING ABOVE
+0170 ; mapped ; 0171 # 1.1 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0171 ; valid # 1.1 LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0172 ; mapped ; 0173 # 1.1 LATIN CAPITAL LETTER U WITH OGONEK
+0173 ; valid # 1.1 LATIN SMALL LETTER U WITH OGONEK
+0174 ; mapped ; 0175 # 1.1 LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0175 ; valid # 1.1 LATIN SMALL LETTER W WITH CIRCUMFLEX
+0176 ; mapped ; 0177 # 1.1 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0177 ; valid # 1.1 LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0178 ; mapped ; 00FF # 1.1 LATIN CAPITAL LETTER Y WITH DIAERESIS
+0179 ; mapped ; 017A # 1.1 LATIN CAPITAL LETTER Z WITH ACUTE
+017A ; valid # 1.1 LATIN SMALL LETTER Z WITH ACUTE
+017B ; mapped ; 017C # 1.1 LATIN CAPITAL LETTER Z WITH DOT ABOVE
+017C ; valid # 1.1 LATIN SMALL LETTER Z WITH DOT ABOVE
+017D ; mapped ; 017E # 1.1 LATIN CAPITAL LETTER Z WITH CARON
+017E ; valid # 1.1 LATIN SMALL LETTER Z WITH CARON
+017F ; mapped ; 0073 # 1.1 LATIN SMALL LETTER LONG S
+0180 ; valid # 1.1 LATIN SMALL LETTER B WITH STROKE
+0181 ; mapped ; 0253 # 1.1 LATIN CAPITAL LETTER B WITH HOOK
+0182 ; mapped ; 0183 # 1.1 LATIN CAPITAL LETTER B WITH TOPBAR
+0183 ; valid # 1.1 LATIN SMALL LETTER B WITH TOPBAR
+0184 ; mapped ; 0185 # 1.1 LATIN CAPITAL LETTER TONE SIX
+0185 ; valid # 1.1 LATIN SMALL LETTER TONE SIX
+0186 ; mapped ; 0254 # 1.1 LATIN CAPITAL LETTER OPEN O
+0187 ; mapped ; 0188 # 1.1 LATIN CAPITAL LETTER C WITH HOOK
+0188 ; valid # 1.1 LATIN SMALL LETTER C WITH HOOK
+0189 ; mapped ; 0256 # 1.1 LATIN CAPITAL LETTER AFRICAN D
+018A ; mapped ; 0257 # 1.1 LATIN CAPITAL LETTER D WITH HOOK
+018B ; mapped ; 018C # 1.1 LATIN CAPITAL LETTER D WITH TOPBAR
+018C..018D ; valid # 1.1 LATIN SMALL LETTER D WITH TOPBAR..LATIN SMALL LETTER TURNED DELTA
+018E ; mapped ; 01DD # 1.1 LATIN CAPITAL LETTER REVERSED E
+018F ; mapped ; 0259 # 1.1 LATIN CAPITAL LETTER SCHWA
+0190 ; mapped ; 025B # 1.1 LATIN CAPITAL LETTER OPEN E
+0191 ; mapped ; 0192 # 1.1 LATIN CAPITAL LETTER F WITH HOOK
+0192 ; valid # 1.1 LATIN SMALL LETTER F WITH HOOK
+0193 ; mapped ; 0260 # 1.1 LATIN CAPITAL LETTER G WITH HOOK
+0194 ; mapped ; 0263 # 1.1 LATIN CAPITAL LETTER GAMMA
+0195 ; valid # 1.1 LATIN SMALL LETTER HV
+0196 ; mapped ; 0269 # 1.1 LATIN CAPITAL LETTER IOTA
+0197 ; mapped ; 0268 # 1.1 LATIN CAPITAL LETTER I WITH STROKE
+0198 ; mapped ; 0199 # 1.1 LATIN CAPITAL LETTER K WITH HOOK
+0199..019B ; valid # 1.1 LATIN SMALL LETTER K WITH HOOK..LATIN SMALL LETTER LAMBDA WITH STROKE
+019C ; mapped ; 026F # 1.1 LATIN CAPITAL LETTER TURNED M
+019D ; mapped ; 0272 # 1.1 LATIN CAPITAL LETTER N WITH LEFT HOOK
+019E ; valid # 1.1 LATIN SMALL LETTER N WITH LONG RIGHT LEG
+019F ; mapped ; 0275 # 1.1 LATIN CAPITAL LETTER O WITH MIDDLE TILDE
+01A0 ; mapped ; 01A1 # 1.1 LATIN CAPITAL LETTER O WITH HORN
+01A1 ; valid # 1.1 LATIN SMALL LETTER O WITH HORN
+01A2 ; mapped ; 01A3 # 1.1 LATIN CAPITAL LETTER OI
+01A3 ; valid # 1.1 LATIN SMALL LETTER OI
+01A4 ; mapped ; 01A5 # 1.1 LATIN CAPITAL LETTER P WITH HOOK
+01A5 ; valid # 1.1 LATIN SMALL LETTER P WITH HOOK
+01A6 ; mapped ; 0280 # 1.1 LATIN LETTER YR
+01A7 ; mapped ; 01A8 # 1.1 LATIN CAPITAL LETTER TONE TWO
+01A8 ; valid # 1.1 LATIN SMALL LETTER TONE TWO
+01A9 ; mapped ; 0283 # 1.1 LATIN CAPITAL LETTER ESH
+01AA..01AB ; valid # 1.1 LATIN LETTER REVERSED ESH LOOP..LATIN SMALL LETTER T WITH PALATAL HOOK
+01AC ; mapped ; 01AD # 1.1 LATIN CAPITAL LETTER T WITH HOOK
+01AD ; valid # 1.1 LATIN SMALL LETTER T WITH HOOK
+01AE ; mapped ; 0288 # 1.1 LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
+01AF ; mapped ; 01B0 # 1.1 LATIN CAPITAL LETTER U WITH HORN
+01B0 ; valid # 1.1 LATIN SMALL LETTER U WITH HORN
+01B1 ; mapped ; 028A # 1.1 LATIN CAPITAL LETTER UPSILON
+01B2 ; mapped ; 028B # 1.1 LATIN CAPITAL LETTER V WITH HOOK
+01B3 ; mapped ; 01B4 # 1.1 LATIN CAPITAL LETTER Y WITH HOOK
+01B4 ; valid # 1.1 LATIN SMALL LETTER Y WITH HOOK
+01B5 ; mapped ; 01B6 # 1.1 LATIN CAPITAL LETTER Z WITH STROKE
+01B6 ; valid # 1.1 LATIN SMALL LETTER Z WITH STROKE
+01B7 ; mapped ; 0292 # 1.1 LATIN CAPITAL LETTER EZH
+01B8 ; mapped ; 01B9 # 1.1 LATIN CAPITAL LETTER EZH REVERSED
+01B9..01BB ; valid # 1.1 LATIN SMALL LETTER EZH REVERSED..LATIN LETTER TWO WITH STROKE
+01BC ; mapped ; 01BD # 1.1 LATIN CAPITAL LETTER TONE FIVE
+01BD..01C3 ; valid # 1.1 LATIN SMALL LETTER TONE FIVE..LATIN LETTER RETROFLEX CLICK
+01C4..01C6 ; mapped ; 0064 017E # 1.1 LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER DZ WITH CARON
+01C7..01C9 ; mapped ; 006C 006A # 1.1 LATIN CAPITAL LETTER LJ..LATIN SMALL LETTER LJ
+01CA..01CC ; mapped ; 006E 006A # 1.1 LATIN CAPITAL LETTER NJ..LATIN SMALL LETTER NJ
+01CD ; mapped ; 01CE # 1.1 LATIN CAPITAL LETTER A WITH CARON
+01CE ; valid # 1.1 LATIN SMALL LETTER A WITH CARON
+01CF ; mapped ; 01D0 # 1.1 LATIN CAPITAL LETTER I WITH CARON
+01D0 ; valid # 1.1 LATIN SMALL LETTER I WITH CARON
+01D1 ; mapped ; 01D2 # 1.1 LATIN CAPITAL LETTER O WITH CARON
+01D2 ; valid # 1.1 LATIN SMALL LETTER O WITH CARON
+01D3 ; mapped ; 01D4 # 1.1 LATIN CAPITAL LETTER U WITH CARON
+01D4 ; valid # 1.1 LATIN SMALL LETTER U WITH CARON
+01D5 ; mapped ; 01D6 # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+01D6 ; valid # 1.1 LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+01D7 ; mapped ; 01D8 # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+01D8 ; valid # 1.1 LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+01D9 ; mapped ; 01DA # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+01DA ; valid # 1.1 LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+01DB ; mapped ; 01DC # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+01DC..01DD ; valid # 1.1 LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE..LATIN SMALL LETTER TURNED E
+01DE ; mapped ; 01DF # 1.1 LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+01DF ; valid # 1.1 LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+01E0 ; mapped ; 01E1 # 1.1 LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+01E1 ; valid # 1.1 LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+01E2 ; mapped ; 01E3 # 1.1 LATIN CAPITAL LETTER AE WITH MACRON
+01E3 ; valid # 1.1 LATIN SMALL LETTER AE WITH MACRON
+01E4 ; mapped ; 01E5 # 1.1 LATIN CAPITAL LETTER G WITH STROKE
+01E5 ; valid # 1.1 LATIN SMALL LETTER G WITH STROKE
+01E6 ; mapped ; 01E7 # 1.1 LATIN CAPITAL LETTER G WITH CARON
+01E7 ; valid # 1.1 LATIN SMALL LETTER G WITH CARON
+01E8 ; mapped ; 01E9 # 1.1 LATIN CAPITAL LETTER K WITH CARON
+01E9 ; valid # 1.1 LATIN SMALL LETTER K WITH CARON
+01EA ; mapped ; 01EB # 1.1 LATIN CAPITAL LETTER O WITH OGONEK
+01EB ; valid # 1.1 LATIN SMALL LETTER O WITH OGONEK
+01EC ; mapped ; 01ED # 1.1 LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+01ED ; valid # 1.1 LATIN SMALL LETTER O WITH OGONEK AND MACRON
+01EE ; mapped ; 01EF # 1.1 LATIN CAPITAL LETTER EZH WITH CARON
+01EF..01F0 ; valid # 1.1 LATIN SMALL LETTER EZH WITH CARON..LATIN SMALL LETTER J WITH CARON
+01F1..01F3 ; mapped ; 0064 007A # 1.1 LATIN CAPITAL LETTER DZ..LATIN SMALL LETTER DZ
+01F4 ; mapped ; 01F5 # 1.1 LATIN CAPITAL LETTER G WITH ACUTE
+01F5 ; valid # 1.1 LATIN SMALL LETTER G WITH ACUTE
+01F6 ; mapped ; 0195 # 3.0 LATIN CAPITAL LETTER HWAIR
+01F7 ; mapped ; 01BF # 3.0 LATIN CAPITAL LETTER WYNN
+01F8 ; mapped ; 01F9 # 3.0 LATIN CAPITAL LETTER N WITH GRAVE
+01F9 ; valid # 3.0 LATIN SMALL LETTER N WITH GRAVE
+01FA ; mapped ; 01FB # 1.1 LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+01FB ; valid # 1.1 LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+01FC ; mapped ; 01FD # 1.1 LATIN CAPITAL LETTER AE WITH ACUTE
+01FD ; valid # 1.1 LATIN SMALL LETTER AE WITH ACUTE
+01FE ; mapped ; 01FF # 1.1 LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+01FF ; valid # 1.1 LATIN SMALL LETTER O WITH STROKE AND ACUTE
+0200 ; mapped ; 0201 # 1.1 LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+0201 ; valid # 1.1 LATIN SMALL LETTER A WITH DOUBLE GRAVE
+0202 ; mapped ; 0203 # 1.1 LATIN CAPITAL LETTER A WITH INVERTED BREVE
+0203 ; valid # 1.1 LATIN SMALL LETTER A WITH INVERTED BREVE
+0204 ; mapped ; 0205 # 1.1 LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+0205 ; valid # 1.1 LATIN SMALL LETTER E WITH DOUBLE GRAVE
+0206 ; mapped ; 0207 # 1.1 LATIN CAPITAL LETTER E WITH INVERTED BREVE
+0207 ; valid # 1.1 LATIN SMALL LETTER E WITH INVERTED BREVE
+0208 ; mapped ; 0209 # 1.1 LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+0209 ; valid # 1.1 LATIN SMALL LETTER I WITH DOUBLE GRAVE
+020A ; mapped ; 020B # 1.1 LATIN CAPITAL LETTER I WITH INVERTED BREVE
+020B ; valid # 1.1 LATIN SMALL LETTER I WITH INVERTED BREVE
+020C ; mapped ; 020D # 1.1 LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+020D ; valid # 1.1 LATIN SMALL LETTER O WITH DOUBLE GRAVE
+020E ; mapped ; 020F # 1.1 LATIN CAPITAL LETTER O WITH INVERTED BREVE
+020F ; valid # 1.1 LATIN SMALL LETTER O WITH INVERTED BREVE
+0210 ; mapped ; 0211 # 1.1 LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+0211 ; valid # 1.1 LATIN SMALL LETTER R WITH DOUBLE GRAVE
+0212 ; mapped ; 0213 # 1.1 LATIN CAPITAL LETTER R WITH INVERTED BREVE
+0213 ; valid # 1.1 LATIN SMALL LETTER R WITH INVERTED BREVE
+0214 ; mapped ; 0215 # 1.1 LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+0215 ; valid # 1.1 LATIN SMALL LETTER U WITH DOUBLE GRAVE
+0216 ; mapped ; 0217 # 1.1 LATIN CAPITAL LETTER U WITH INVERTED BREVE
+0217 ; valid # 1.1 LATIN SMALL LETTER U WITH INVERTED BREVE
+0218 ; mapped ; 0219 # 3.0 LATIN CAPITAL LETTER S WITH COMMA BELOW
+0219 ; valid # 3.0 LATIN SMALL LETTER S WITH COMMA BELOW
+021A ; mapped ; 021B # 3.0 LATIN CAPITAL LETTER T WITH COMMA BELOW
+021B ; valid # 3.0 LATIN SMALL LETTER T WITH COMMA BELOW
+021C ; mapped ; 021D # 3.0 LATIN CAPITAL LETTER YOGH
+021D ; valid # 3.0 LATIN SMALL LETTER YOGH
+021E ; mapped ; 021F # 3.0 LATIN CAPITAL LETTER H WITH CARON
+021F ; valid # 3.0 LATIN SMALL LETTER H WITH CARON
+0220 ; mapped ; 019E # 3.2 LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
+0221 ; valid # 4.0 LATIN SMALL LETTER D WITH CURL
+0222 ; mapped ; 0223 # 3.0 LATIN CAPITAL LETTER OU
+0223 ; valid # 3.0 LATIN SMALL LETTER OU
+0224 ; mapped ; 0225 # 3.0 LATIN CAPITAL LETTER Z WITH HOOK
+0225 ; valid # 3.0 LATIN SMALL LETTER Z WITH HOOK
+0226 ; mapped ; 0227 # 3.0 LATIN CAPITAL LETTER A WITH DOT ABOVE
+0227 ; valid # 3.0 LATIN SMALL LETTER A WITH DOT ABOVE
+0228 ; mapped ; 0229 # 3.0 LATIN CAPITAL LETTER E WITH CEDILLA
+0229 ; valid # 3.0 LATIN SMALL LETTER E WITH CEDILLA
+022A ; mapped ; 022B # 3.0 LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+022B ; valid # 3.0 LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
+022C ; mapped ; 022D # 3.0 LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+022D ; valid # 3.0 LATIN SMALL LETTER O WITH TILDE AND MACRON
+022E ; mapped ; 022F # 3.0 LATIN CAPITAL LETTER O WITH DOT ABOVE
+022F ; valid # 3.0 LATIN SMALL LETTER O WITH DOT ABOVE
+0230 ; mapped ; 0231 # 3.0 LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+0231 ; valid # 3.0 LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
+0232 ; mapped ; 0233 # 3.0 LATIN CAPITAL LETTER Y WITH MACRON
+0233 ; valid # 3.0 LATIN SMALL LETTER Y WITH MACRON
+0234..0236 ; valid # 4.0 LATIN SMALL LETTER L WITH CURL..LATIN SMALL LETTER T WITH CURL
+0237..0239 ; valid # 4.1 LATIN SMALL LETTER DOTLESS J..LATIN SMALL LETTER QP DIGRAPH
+023A ; mapped ; 2C65 # 4.1 LATIN CAPITAL LETTER A WITH STROKE
+023B ; mapped ; 023C # 4.1 LATIN CAPITAL LETTER C WITH STROKE
+023C ; valid # 4.1 LATIN SMALL LETTER C WITH STROKE
+023D ; mapped ; 019A # 4.1 LATIN CAPITAL LETTER L WITH BAR
+023E ; mapped ; 2C66 # 4.1 LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
+023F..0240 ; valid # 4.1 LATIN SMALL LETTER S WITH SWASH TAIL..LATIN SMALL LETTER Z WITH SWASH TAIL
+0241 ; mapped ; 0242 # 4.1 LATIN CAPITAL LETTER GLOTTAL STOP
+0242 ; valid # 5.0 LATIN SMALL LETTER GLOTTAL STOP
+0243 ; mapped ; 0180 # 5.0 LATIN CAPITAL LETTER B WITH STROKE
+0244 ; mapped ; 0289 # 5.0 LATIN CAPITAL LETTER U BAR
+0245 ; mapped ; 028C # 5.0 LATIN CAPITAL LETTER TURNED V
+0246 ; mapped ; 0247 # 5.0 LATIN CAPITAL LETTER E WITH STROKE
+0247 ; valid # 5.0 LATIN SMALL LETTER E WITH STROKE
+0248 ; mapped ; 0249 # 5.0 LATIN CAPITAL LETTER J WITH STROKE
+0249 ; valid # 5.0 LATIN SMALL LETTER J WITH STROKE
+024A ; mapped ; 024B # 5.0 LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
+024B ; valid # 5.0 LATIN SMALL LETTER Q WITH HOOK TAIL
+024C ; mapped ; 024D # 5.0 LATIN CAPITAL LETTER R WITH STROKE
+024D ; valid # 5.0 LATIN SMALL LETTER R WITH STROKE
+024E ; mapped ; 024F # 5.0 LATIN CAPITAL LETTER Y WITH STROKE
+024F ; valid # 5.0 LATIN SMALL LETTER Y WITH STROKE
+0250..02A8 ; valid # 1.1 LATIN SMALL LETTER TURNED A..LATIN SMALL LETTER TC DIGRAPH WITH CURL
+02A9..02AD ; valid # 3.0 LATIN SMALL LETTER FENG DIGRAPH..LATIN LETTER BIDENTAL PERCUSSIVE
+02AE..02AF ; valid # 4.0 LATIN SMALL LETTER TURNED H WITH FISHHOOK..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+02B0 ; mapped ; 0068 # 1.1 MODIFIER LETTER SMALL H
+02B1 ; mapped ; 0266 # 1.1 MODIFIER LETTER SMALL H WITH HOOK
+02B2 ; mapped ; 006A # 1.1 MODIFIER LETTER SMALL J
+02B3 ; mapped ; 0072 # 1.1 MODIFIER LETTER SMALL R
+02B4 ; mapped ; 0279 # 1.1 MODIFIER LETTER SMALL TURNED R
+02B5 ; mapped ; 027B # 1.1 MODIFIER LETTER SMALL TURNED R WITH HOOK
+02B6 ; mapped ; 0281 # 1.1 MODIFIER LETTER SMALL CAPITAL INVERTED R
+02B7 ; mapped ; 0077 # 1.1 MODIFIER LETTER SMALL W
+02B8 ; mapped ; 0079 # 1.1 MODIFIER LETTER SMALL Y
+02B9..02C1 ; valid # 1.1 MODIFIER LETTER PRIME..MODIFIER LETTER REVERSED GLOTTAL STOP
+02C2..02C5 ; valid ; ; NV8 # 1.1 MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD
+02C6..02D1 ; valid # 1.1 MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON
+02D2..02D7 ; valid ; ; NV8 # 1.1 MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN
+02D8 ; disallowed_STD3_mapped ; 0020 0306 # 1.1 BREVE
+02D9 ; disallowed_STD3_mapped ; 0020 0307 # 1.1 DOT ABOVE
+02DA ; disallowed_STD3_mapped ; 0020 030A # 1.1 RING ABOVE
+02DB ; disallowed_STD3_mapped ; 0020 0328 # 1.1 OGONEK
+02DC ; disallowed_STD3_mapped ; 0020 0303 # 1.1 SMALL TILDE
+02DD ; disallowed_STD3_mapped ; 0020 030B # 1.1 DOUBLE ACUTE ACCENT
+02DE ; valid ; ; NV8 # 1.1 MODIFIER LETTER RHOTIC HOOK
+02DF ; valid ; ; NV8 # 3.0 MODIFIER LETTER CROSS ACCENT
+02E0 ; mapped ; 0263 # 1.1 MODIFIER LETTER SMALL GAMMA
+02E1 ; mapped ; 006C # 1.1 MODIFIER LETTER SMALL L
+02E2 ; mapped ; 0073 # 1.1 MODIFIER LETTER SMALL S
+02E3 ; mapped ; 0078 # 1.1 MODIFIER LETTER SMALL X
+02E4 ; mapped ; 0295 # 1.1 MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+02E5..02E9 ; valid ; ; NV8 # 1.1 MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER EXTRA-LOW TONE BAR
+02EA..02EB ; valid ; ; NV8 # 3.0 MODIFIER LETTER YIN DEPARTING TONE MARK..MODIFIER LETTER YANG DEPARTING TONE MARK
+02EC ; valid # 3.0 MODIFIER LETTER VOICING
+02ED ; valid ; ; NV8 # 3.0 MODIFIER LETTER UNASPIRATED
+02EE ; valid # 3.0 MODIFIER LETTER DOUBLE APOSTROPHE
+02EF..02FF ; valid ; ; NV8 # 4.0 MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
+0300..033F ; valid # 1.1 COMBINING GRAVE ACCENT..COMBINING DOUBLE OVERLINE
+0340 ; mapped ; 0300 # 1.1 COMBINING GRAVE TONE MARK
+0341 ; mapped ; 0301 # 1.1 COMBINING ACUTE TONE MARK
+0342 ; valid # 1.1 COMBINING GREEK PERISPOMENI
+0343 ; mapped ; 0313 # 1.1 COMBINING GREEK KORONIS
+0344 ; mapped ; 0308 0301 # 1.1 COMBINING GREEK DIALYTIKA TONOS
+0345 ; mapped ; 03B9 # 1.1 COMBINING GREEK YPOGEGRAMMENI
+0346..034E ; valid # 3.0 COMBINING BRIDGE ABOVE..COMBINING UPWARDS ARROW BELOW
+034F ; ignored # 3.2 COMBINING GRAPHEME JOINER
+0350..0357 ; valid # 4.0 COMBINING RIGHT ARROWHEAD ABOVE..COMBINING RIGHT HALF RING ABOVE
+0358..035C ; valid # 4.1 COMBINING DOT ABOVE RIGHT..COMBINING DOUBLE BREVE BELOW
+035D..035F ; valid # 4.0 COMBINING DOUBLE BREVE..COMBINING DOUBLE MACRON BELOW
+0360..0361 ; valid # 1.1 COMBINING DOUBLE TILDE..COMBINING DOUBLE INVERTED BREVE
+0362 ; valid # 3.0 COMBINING DOUBLE RIGHTWARDS ARROW BELOW
+0363..036F ; valid # 3.2 COMBINING LATIN SMALL LETTER A..COMBINING LATIN SMALL LETTER X
+0370 ; mapped ; 0371 # 5.1 GREEK CAPITAL LETTER HETA
+0371 ; valid # 5.1 GREEK SMALL LETTER HETA
+0372 ; mapped ; 0373 # 5.1 GREEK CAPITAL LETTER ARCHAIC SAMPI
+0373 ; valid # 5.1 GREEK SMALL LETTER ARCHAIC SAMPI
+0374 ; mapped ; 02B9 # 1.1 GREEK NUMERAL SIGN
+0375 ; valid # 1.1 GREEK LOWER NUMERAL SIGN
+0376 ; mapped ; 0377 # 5.1 GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
+0377 ; valid # 5.1 GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+0378..0379 ; disallowed # NA <reserved-0378>..<reserved-0379>
+037A ; disallowed_STD3_mapped ; 0020 03B9 # 1.1 GREEK YPOGEGRAMMENI
+037B..037D ; valid # 5.0 GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+037E ; disallowed_STD3_mapped ; 003B # 1.1 GREEK QUESTION MARK
+037F ; mapped ; 03F3 # 7.0 GREEK CAPITAL LETTER YOT
+0380..0383 ; disallowed # NA <reserved-0380>..<reserved-0383>
+0384 ; disallowed_STD3_mapped ; 0020 0301 # 1.1 GREEK TONOS
+0385 ; disallowed_STD3_mapped ; 0020 0308 0301 #1.1 GREEK DIALYTIKA TONOS
+0386 ; mapped ; 03AC # 1.1 GREEK CAPITAL LETTER ALPHA WITH TONOS
+0387 ; mapped ; 00B7 # 1.1 GREEK ANO TELEIA
+0388 ; mapped ; 03AD # 1.1 GREEK CAPITAL LETTER EPSILON WITH TONOS
+0389 ; mapped ; 03AE # 1.1 GREEK CAPITAL LETTER ETA WITH TONOS
+038A ; mapped ; 03AF # 1.1 GREEK CAPITAL LETTER IOTA WITH TONOS
+038B ; disallowed # NA <reserved-038B>
+038C ; mapped ; 03CC # 1.1 GREEK CAPITAL LETTER OMICRON WITH TONOS
+038D ; disallowed # NA <reserved-038D>
+038E ; mapped ; 03CD # 1.1 GREEK CAPITAL LETTER UPSILON WITH TONOS
+038F ; mapped ; 03CE # 1.1 GREEK CAPITAL LETTER OMEGA WITH TONOS
+0390 ; valid # 1.1 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0391 ; mapped ; 03B1 # 1.1 GREEK CAPITAL LETTER ALPHA
+0392 ; mapped ; 03B2 # 1.1 GREEK CAPITAL LETTER BETA
+0393 ; mapped ; 03B3 # 1.1 GREEK CAPITAL LETTER GAMMA
+0394 ; mapped ; 03B4 # 1.1 GREEK CAPITAL LETTER DELTA
+0395 ; mapped ; 03B5 # 1.1 GREEK CAPITAL LETTER EPSILON
+0396 ; mapped ; 03B6 # 1.1 GREEK CAPITAL LETTER ZETA
+0397 ; mapped ; 03B7 # 1.1 GREEK CAPITAL LETTER ETA
+0398 ; mapped ; 03B8 # 1.1 GREEK CAPITAL LETTER THETA
+0399 ; mapped ; 03B9 # 1.1 GREEK CAPITAL LETTER IOTA
+039A ; mapped ; 03BA # 1.1 GREEK CAPITAL LETTER KAPPA
+039B ; mapped ; 03BB # 1.1 GREEK CAPITAL LETTER LAMDA
+039C ; mapped ; 03BC # 1.1 GREEK CAPITAL LETTER MU
+039D ; mapped ; 03BD # 1.1 GREEK CAPITAL LETTER NU
+039E ; mapped ; 03BE # 1.1 GREEK CAPITAL LETTER XI
+039F ; mapped ; 03BF # 1.1 GREEK CAPITAL LETTER OMICRON
+03A0 ; mapped ; 03C0 # 1.1 GREEK CAPITAL LETTER PI
+03A1 ; mapped ; 03C1 # 1.1 GREEK CAPITAL LETTER RHO
+03A2 ; disallowed # NA <reserved-03A2>
+03A3 ; mapped ; 03C3 # 1.1 GREEK CAPITAL LETTER SIGMA
+03A4 ; mapped ; 03C4 # 1.1 GREEK CAPITAL LETTER TAU
+03A5 ; mapped ; 03C5 # 1.1 GREEK CAPITAL LETTER UPSILON
+03A6 ; mapped ; 03C6 # 1.1 GREEK CAPITAL LETTER PHI
+03A7 ; mapped ; 03C7 # 1.1 GREEK CAPITAL LETTER CHI
+03A8 ; mapped ; 03C8 # 1.1 GREEK CAPITAL LETTER PSI
+03A9 ; mapped ; 03C9 # 1.1 GREEK CAPITAL LETTER OMEGA
+03AA ; mapped ; 03CA # 1.1 GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+03AB ; mapped ; 03CB # 1.1 GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+03AC..03C1 ; valid # 1.1 GREEK SMALL LETTER ALPHA WITH TONOS..GREEK SMALL LETTER RHO
+03C2 ; deviation ; 03C3 # 1.1 GREEK SMALL LETTER FINAL SIGMA
+03C3..03CE ; valid # 1.1 GREEK SMALL LETTER SIGMA..GREEK SMALL LETTER OMEGA WITH TONOS
+03CF ; mapped ; 03D7 # 5.1 GREEK CAPITAL KAI SYMBOL
+03D0 ; mapped ; 03B2 # 1.1 GREEK BETA SYMBOL
+03D1 ; mapped ; 03B8 # 1.1 GREEK THETA SYMBOL
+03D2 ; mapped ; 03C5 # 1.1 GREEK UPSILON WITH HOOK SYMBOL
+03D3 ; mapped ; 03CD # 1.1 GREEK UPSILON WITH ACUTE AND HOOK SYMBOL
+03D4 ; mapped ; 03CB # 1.1 GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL
+03D5 ; mapped ; 03C6 # 1.1 GREEK PHI SYMBOL
+03D6 ; mapped ; 03C0 # 1.1 GREEK PI SYMBOL
+03D7 ; valid # 3.0 GREEK KAI SYMBOL
+03D8 ; mapped ; 03D9 # 3.2 GREEK LETTER ARCHAIC KOPPA
+03D9 ; valid # 3.2 GREEK SMALL LETTER ARCHAIC KOPPA
+03DA ; mapped ; 03DB # 1.1 GREEK LETTER STIGMA
+03DB ; valid # 3.0 GREEK SMALL LETTER STIGMA
+03DC ; mapped ; 03DD # 1.1 GREEK LETTER DIGAMMA
+03DD ; valid # 3.0 GREEK SMALL LETTER DIGAMMA
+03DE ; mapped ; 03DF # 1.1 GREEK LETTER KOPPA
+03DF ; valid # 3.0 GREEK SMALL LETTER KOPPA
+03E0 ; mapped ; 03E1 # 1.1 GREEK LETTER SAMPI
+03E1 ; valid # 3.0 GREEK SMALL LETTER SAMPI
+03E2 ; mapped ; 03E3 # 1.1 COPTIC CAPITAL LETTER SHEI
+03E3 ; valid # 1.1 COPTIC SMALL LETTER SHEI
+03E4 ; mapped ; 03E5 # 1.1 COPTIC CAPITAL LETTER FEI
+03E5 ; valid # 1.1 COPTIC SMALL LETTER FEI
+03E6 ; mapped ; 03E7 # 1.1 COPTIC CAPITAL LETTER KHEI
+03E7 ; valid # 1.1 COPTIC SMALL LETTER KHEI
+03E8 ; mapped ; 03E9 # 1.1 COPTIC CAPITAL LETTER HORI
+03E9 ; valid # 1.1 COPTIC SMALL LETTER HORI
+03EA ; mapped ; 03EB # 1.1 COPTIC CAPITAL LETTER GANGIA
+03EB ; valid # 1.1 COPTIC SMALL LETTER GANGIA
+03EC ; mapped ; 03ED # 1.1 COPTIC CAPITAL LETTER SHIMA
+03ED ; valid # 1.1 COPTIC SMALL LETTER SHIMA
+03EE ; mapped ; 03EF # 1.1 COPTIC CAPITAL LETTER DEI
+03EF ; valid # 1.1 COPTIC SMALL LETTER DEI
+03F0 ; mapped ; 03BA # 1.1 GREEK KAPPA SYMBOL
+03F1 ; mapped ; 03C1 # 1.1 GREEK RHO SYMBOL
+03F2 ; mapped ; 03C3 # 1.1 GREEK LUNATE SIGMA SYMBOL
+03F3 ; valid # 1.1 GREEK LETTER YOT
+03F4 ; mapped ; 03B8 # 3.1 GREEK CAPITAL THETA SYMBOL
+03F5 ; mapped ; 03B5 # 3.1 GREEK LUNATE EPSILON SYMBOL
+03F6 ; valid ; ; NV8 # 3.2 GREEK REVERSED LUNATE EPSILON SYMBOL
+03F7 ; mapped ; 03F8 # 4.0 GREEK CAPITAL LETTER SHO
+03F8 ; valid # 4.0 GREEK SMALL LETTER SHO
+03F9 ; mapped ; 03C3 # 4.0 GREEK CAPITAL LUNATE SIGMA SYMBOL
+03FA ; mapped ; 03FB # 4.0 GREEK CAPITAL LETTER SAN
+03FB ; valid # 4.0 GREEK SMALL LETTER SAN
+03FC ; valid # 4.1 GREEK RHO WITH STROKE SYMBOL
+03FD ; mapped ; 037B # 4.1 GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL
+03FE ; mapped ; 037C # 4.1 GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL
+03FF ; mapped ; 037D # 4.1 GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
+0400 ; mapped ; 0450 # 3.0 CYRILLIC CAPITAL LETTER IE WITH GRAVE
+0401 ; mapped ; 0451 # 1.1 CYRILLIC CAPITAL LETTER IO
+0402 ; mapped ; 0452 # 1.1 CYRILLIC CAPITAL LETTER DJE
+0403 ; mapped ; 0453 # 1.1 CYRILLIC CAPITAL LETTER GJE
+0404 ; mapped ; 0454 # 1.1 CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0405 ; mapped ; 0455 # 1.1 CYRILLIC CAPITAL LETTER DZE
+0406 ; mapped ; 0456 # 1.1 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0407 ; mapped ; 0457 # 1.1 CYRILLIC CAPITAL LETTER YI
+0408 ; mapped ; 0458 # 1.1 CYRILLIC CAPITAL LETTER JE
+0409 ; mapped ; 0459 # 1.1 CYRILLIC CAPITAL LETTER LJE
+040A ; mapped ; 045A # 1.1 CYRILLIC CAPITAL LETTER NJE
+040B ; mapped ; 045B # 1.1 CYRILLIC CAPITAL LETTER TSHE
+040C ; mapped ; 045C # 1.1 CYRILLIC CAPITAL LETTER KJE
+040D ; mapped ; 045D # 3.0 CYRILLIC CAPITAL LETTER I WITH GRAVE
+040E ; mapped ; 045E # 1.1 CYRILLIC CAPITAL LETTER SHORT U
+040F ; mapped ; 045F # 1.1 CYRILLIC CAPITAL LETTER DZHE
+0410 ; mapped ; 0430 # 1.1 CYRILLIC CAPITAL LETTER A
+0411 ; mapped ; 0431 # 1.1 CYRILLIC CAPITAL LETTER BE
+0412 ; mapped ; 0432 # 1.1 CYRILLIC CAPITAL LETTER VE
+0413 ; mapped ; 0433 # 1.1 CYRILLIC CAPITAL LETTER GHE
+0414 ; mapped ; 0434 # 1.1 CYRILLIC CAPITAL LETTER DE
+0415 ; mapped ; 0435 # 1.1 CYRILLIC CAPITAL LETTER IE
+0416 ; mapped ; 0436 # 1.1 CYRILLIC CAPITAL LETTER ZHE
+0417 ; mapped ; 0437 # 1.1 CYRILLIC CAPITAL LETTER ZE
+0418 ; mapped ; 0438 # 1.1 CYRILLIC CAPITAL LETTER I
+0419 ; mapped ; 0439 # 1.1 CYRILLIC CAPITAL LETTER SHORT I
+041A ; mapped ; 043A # 1.1 CYRILLIC CAPITAL LETTER KA
+041B ; mapped ; 043B # 1.1 CYRILLIC CAPITAL LETTER EL
+041C ; mapped ; 043C # 1.1 CYRILLIC CAPITAL LETTER EM
+041D ; mapped ; 043D # 1.1 CYRILLIC CAPITAL LETTER EN
+041E ; mapped ; 043E # 1.1 CYRILLIC CAPITAL LETTER O
+041F ; mapped ; 043F # 1.1 CYRILLIC CAPITAL LETTER PE
+0420 ; mapped ; 0440 # 1.1 CYRILLIC CAPITAL LETTER ER
+0421 ; mapped ; 0441 # 1.1 CYRILLIC CAPITAL LETTER ES
+0422 ; mapped ; 0442 # 1.1 CYRILLIC CAPITAL LETTER TE
+0423 ; mapped ; 0443 # 1.1 CYRILLIC CAPITAL LETTER U
+0424 ; mapped ; 0444 # 1.1 CYRILLIC CAPITAL LETTER EF
+0425 ; mapped ; 0445 # 1.1 CYRILLIC CAPITAL LETTER HA
+0426 ; mapped ; 0446 # 1.1 CYRILLIC CAPITAL LETTER TSE
+0427 ; mapped ; 0447 # 1.1 CYRILLIC CAPITAL LETTER CHE
+0428 ; mapped ; 0448 # 1.1 CYRILLIC CAPITAL LETTER SHA
+0429 ; mapped ; 0449 # 1.1 CYRILLIC CAPITAL LETTER SHCHA
+042A ; mapped ; 044A # 1.1 CYRILLIC CAPITAL LETTER HARD SIGN
+042B ; mapped ; 044B # 1.1 CYRILLIC CAPITAL LETTER YERU
+042C ; mapped ; 044C # 1.1 CYRILLIC CAPITAL LETTER SOFT SIGN
+042D ; mapped ; 044D # 1.1 CYRILLIC CAPITAL LETTER E
+042E ; mapped ; 044E # 1.1 CYRILLIC CAPITAL LETTER YU
+042F ; mapped ; 044F # 1.1 CYRILLIC CAPITAL LETTER YA
+0430..044F ; valid # 1.1 CYRILLIC SMALL LETTER A..CYRILLIC SMALL LETTER YA
+0450 ; valid # 3.0 CYRILLIC SMALL LETTER IE WITH GRAVE
+0451..045C ; valid # 1.1 CYRILLIC SMALL LETTER IO..CYRILLIC SMALL LETTER KJE
+045D ; valid # 3.0 CYRILLIC SMALL LETTER I WITH GRAVE
+045E..045F ; valid # 1.1 CYRILLIC SMALL LETTER SHORT U..CYRILLIC SMALL LETTER DZHE
+0460 ; mapped ; 0461 # 1.1 CYRILLIC CAPITAL LETTER OMEGA
+0461 ; valid # 1.1 CYRILLIC SMALL LETTER OMEGA
+0462 ; mapped ; 0463 # 1.1 CYRILLIC CAPITAL LETTER YAT
+0463 ; valid # 1.1 CYRILLIC SMALL LETTER YAT
+0464 ; mapped ; 0465 # 1.1 CYRILLIC CAPITAL LETTER IOTIFIED E
+0465 ; valid # 1.1 CYRILLIC SMALL LETTER IOTIFIED E
+0466 ; mapped ; 0467 # 1.1 CYRILLIC CAPITAL LETTER LITTLE YUS
+0467 ; valid # 1.1 CYRILLIC SMALL LETTER LITTLE YUS
+0468 ; mapped ; 0469 # 1.1 CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+0469 ; valid # 1.1 CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
+046A ; mapped ; 046B # 1.1 CYRILLIC CAPITAL LETTER BIG YUS
+046B ; valid # 1.1 CYRILLIC SMALL LETTER BIG YUS
+046C ; mapped ; 046D # 1.1 CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+046D ; valid # 1.1 CYRILLIC SMALL LETTER IOTIFIED BIG YUS
+046E ; mapped ; 046F # 1.1 CYRILLIC CAPITAL LETTER KSI
+046F ; valid # 1.1 CYRILLIC SMALL LETTER KSI
+0470 ; mapped ; 0471 # 1.1 CYRILLIC CAPITAL LETTER PSI
+0471 ; valid # 1.1 CYRILLIC SMALL LETTER PSI
+0472 ; mapped ; 0473 # 1.1 CYRILLIC CAPITAL LETTER FITA
+0473 ; valid # 1.1 CYRILLIC SMALL LETTER FITA
+0474 ; mapped ; 0475 # 1.1 CYRILLIC CAPITAL LETTER IZHITSA
+0475 ; valid # 1.1 CYRILLIC SMALL LETTER IZHITSA
+0476 ; mapped ; 0477 # 1.1 CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0477 ; valid # 1.1 CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0478 ; mapped ; 0479 # 1.1 CYRILLIC CAPITAL LETTER UK
+0479 ; valid # 1.1 CYRILLIC SMALL LETTER UK
+047A ; mapped ; 047B # 1.1 CYRILLIC CAPITAL LETTER ROUND OMEGA
+047B ; valid # 1.1 CYRILLIC SMALL LETTER ROUND OMEGA
+047C ; mapped ; 047D # 1.1 CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+047D ; valid # 1.1 CYRILLIC SMALL LETTER OMEGA WITH TITLO
+047E ; mapped ; 047F # 1.1 CYRILLIC CAPITAL LETTER OT
+047F ; valid # 1.1 CYRILLIC SMALL LETTER OT
+0480 ; mapped ; 0481 # 1.1 CYRILLIC CAPITAL LETTER KOPPA
+0481 ; valid # 1.1 CYRILLIC SMALL LETTER KOPPA
+0482 ; valid ; ; NV8 # 1.1 CYRILLIC THOUSANDS SIGN
+0483..0486 ; valid # 1.1 COMBINING CYRILLIC TITLO..COMBINING CYRILLIC PSILI PNEUMATA
+0487 ; valid # 5.1 COMBINING CYRILLIC POKRYTIE
+0488..0489 ; valid ; ; NV8 # 3.0 COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
+048A ; mapped ; 048B # 3.2 CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
+048B ; valid # 3.2 CYRILLIC SMALL LETTER SHORT I WITH TAIL
+048C ; mapped ; 048D # 3.0 CYRILLIC CAPITAL LETTER SEMISOFT SIGN
+048D ; valid # 3.0 CYRILLIC SMALL LETTER SEMISOFT SIGN
+048E ; mapped ; 048F # 3.0 CYRILLIC CAPITAL LETTER ER WITH TICK
+048F ; valid # 3.0 CYRILLIC SMALL LETTER ER WITH TICK
+0490 ; mapped ; 0491 # 1.1 CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0491 ; valid # 1.1 CYRILLIC SMALL LETTER GHE WITH UPTURN
+0492 ; mapped ; 0493 # 1.1 CYRILLIC CAPITAL LETTER GHE WITH STROKE
+0493 ; valid # 1.1 CYRILLIC SMALL LETTER GHE WITH STROKE
+0494 ; mapped ; 0495 # 1.1 CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+0495 ; valid # 1.1 CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
+0496 ; mapped ; 0497 # 1.1 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+0497 ; valid # 1.1 CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+0498 ; mapped ; 0499 # 1.1 CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+0499 ; valid # 1.1 CYRILLIC SMALL LETTER ZE WITH DESCENDER
+049A ; mapped ; 049B # 1.1 CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+049B ; valid # 1.1 CYRILLIC SMALL LETTER KA WITH DESCENDER
+049C ; mapped ; 049D # 1.1 CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+049D ; valid # 1.1 CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+049E ; mapped ; 049F # 1.1 CYRILLIC CAPITAL LETTER KA WITH STROKE
+049F ; valid # 1.1 CYRILLIC SMALL LETTER KA WITH STROKE
+04A0 ; mapped ; 04A1 # 1.1 CYRILLIC CAPITAL LETTER BASHKIR KA
+04A1 ; valid # 1.1 CYRILLIC SMALL LETTER BASHKIR KA
+04A2 ; mapped ; 04A3 # 1.1 CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+04A3 ; valid # 1.1 CYRILLIC SMALL LETTER EN WITH DESCENDER
+04A4 ; mapped ; 04A5 # 1.1 CYRILLIC CAPITAL LIGATURE EN GHE
+04A5 ; valid # 1.1 CYRILLIC SMALL LIGATURE EN GHE
+04A6 ; mapped ; 04A7 # 1.1 CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+04A7 ; valid # 1.1 CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
+04A8 ; mapped ; 04A9 # 1.1 CYRILLIC CAPITAL LETTER ABKHASIAN HA
+04A9 ; valid # 1.1 CYRILLIC SMALL LETTER ABKHASIAN HA
+04AA ; mapped ; 04AB # 1.1 CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+04AB ; valid # 1.1 CYRILLIC SMALL LETTER ES WITH DESCENDER
+04AC ; mapped ; 04AD # 1.1 CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+04AD ; valid # 1.1 CYRILLIC SMALL LETTER TE WITH DESCENDER
+04AE ; mapped ; 04AF # 1.1 CYRILLIC CAPITAL LETTER STRAIGHT U
+04AF ; valid # 1.1 CYRILLIC SMALL LETTER STRAIGHT U
+04B0 ; mapped ; 04B1 # 1.1 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+04B1 ; valid # 1.1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+04B2 ; mapped ; 04B3 # 1.1 CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+04B3 ; valid # 1.1 CYRILLIC SMALL LETTER HA WITH DESCENDER
+04B4 ; mapped ; 04B5 # 1.1 CYRILLIC CAPITAL LIGATURE TE TSE
+04B5 ; valid # 1.1 CYRILLIC SMALL LIGATURE TE TSE
+04B6 ; mapped ; 04B7 # 1.1 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+04B7 ; valid # 1.1 CYRILLIC SMALL LETTER CHE WITH DESCENDER
+04B8 ; mapped ; 04B9 # 1.1 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+04B9 ; valid # 1.1 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+04BA ; mapped ; 04BB # 1.1 CYRILLIC CAPITAL LETTER SHHA
+04BB ; valid # 1.1 CYRILLIC SMALL LETTER SHHA
+04BC ; mapped ; 04BD # 1.1 CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+04BD ; valid # 1.1 CYRILLIC SMALL LETTER ABKHASIAN CHE
+04BE ; mapped ; 04BF # 1.1 CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+04BF ; valid # 1.1 CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
+04C0 ; disallowed # 1.1 CYRILLIC LETTER PALOCHKA
+04C1 ; mapped ; 04C2 # 1.1 CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+04C2 ; valid # 1.1 CYRILLIC SMALL LETTER ZHE WITH BREVE
+04C3 ; mapped ; 04C4 # 1.1 CYRILLIC CAPITAL LETTER KA WITH HOOK
+04C4 ; valid # 1.1 CYRILLIC SMALL LETTER KA WITH HOOK
+04C5 ; mapped ; 04C6 # 3.2 CYRILLIC CAPITAL LETTER EL WITH TAIL
+04C6 ; valid # 3.2 CYRILLIC SMALL LETTER EL WITH TAIL
+04C7 ; mapped ; 04C8 # 1.1 CYRILLIC CAPITAL LETTER EN WITH HOOK
+04C8 ; valid # 1.1 CYRILLIC SMALL LETTER EN WITH HOOK
+04C9 ; mapped ; 04CA # 3.2 CYRILLIC CAPITAL LETTER EN WITH TAIL
+04CA ; valid # 3.2 CYRILLIC SMALL LETTER EN WITH TAIL
+04CB ; mapped ; 04CC # 1.1 CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+04CC ; valid # 1.1 CYRILLIC SMALL LETTER KHAKASSIAN CHE
+04CD ; mapped ; 04CE # 3.2 CYRILLIC CAPITAL LETTER EM WITH TAIL
+04CE ; valid # 3.2 CYRILLIC SMALL LETTER EM WITH TAIL
+04CF ; valid # 5.0 CYRILLIC SMALL LETTER PALOCHKA
+04D0 ; mapped ; 04D1 # 1.1 CYRILLIC CAPITAL LETTER A WITH BREVE
+04D1 ; valid # 1.1 CYRILLIC SMALL LETTER A WITH BREVE
+04D2 ; mapped ; 04D3 # 1.1 CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+04D3 ; valid # 1.1 CYRILLIC SMALL LETTER A WITH DIAERESIS
+04D4 ; mapped ; 04D5 # 1.1 CYRILLIC CAPITAL LIGATURE A IE
+04D5 ; valid # 1.1 CYRILLIC SMALL LIGATURE A IE
+04D6 ; mapped ; 04D7 # 1.1 CYRILLIC CAPITAL LETTER IE WITH BREVE
+04D7 ; valid # 1.1 CYRILLIC SMALL LETTER IE WITH BREVE
+04D8 ; mapped ; 04D9 # 1.1 CYRILLIC CAPITAL LETTER SCHWA
+04D9 ; valid # 1.1 CYRILLIC SMALL LETTER SCHWA
+04DA ; mapped ; 04DB # 1.1 CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04DB ; valid # 1.1 CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+04DC ; mapped ; 04DD # 1.1 CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+04DD ; valid # 1.1 CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+04DE ; mapped ; 04DF # 1.1 CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+04DF ; valid # 1.1 CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+04E0 ; mapped ; 04E1 # 1.1 CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+04E1 ; valid # 1.1 CYRILLIC SMALL LETTER ABKHASIAN DZE
+04E2 ; mapped ; 04E3 # 1.1 CYRILLIC CAPITAL LETTER I WITH MACRON
+04E3 ; valid # 1.1 CYRILLIC SMALL LETTER I WITH MACRON
+04E4 ; mapped ; 04E5 # 1.1 CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+04E5 ; valid # 1.1 CYRILLIC SMALL LETTER I WITH DIAERESIS
+04E6 ; mapped ; 04E7 # 1.1 CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+04E7 ; valid # 1.1 CYRILLIC SMALL LETTER O WITH DIAERESIS
+04E8 ; mapped ; 04E9 # 1.1 CYRILLIC CAPITAL LETTER BARRED O
+04E9 ; valid # 1.1 CYRILLIC SMALL LETTER BARRED O
+04EA ; mapped ; 04EB # 1.1 CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+04EB ; valid # 1.1 CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+04EC ; mapped ; 04ED # 3.0 CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+04ED ; valid # 3.0 CYRILLIC SMALL LETTER E WITH DIAERESIS
+04EE ; mapped ; 04EF # 1.1 CYRILLIC CAPITAL LETTER U WITH MACRON
+04EF ; valid # 1.1 CYRILLIC SMALL LETTER U WITH MACRON
+04F0 ; mapped ; 04F1 # 1.1 CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+04F1 ; valid # 1.1 CYRILLIC SMALL LETTER U WITH DIAERESIS
+04F2 ; mapped ; 04F3 # 1.1 CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+04F3 ; valid # 1.1 CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+04F4 ; mapped ; 04F5 # 1.1 CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+04F5 ; valid # 1.1 CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+04F6 ; mapped ; 04F7 # 4.1 CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
+04F7 ; valid # 4.1 CYRILLIC SMALL LETTER GHE WITH DESCENDER
+04F8 ; mapped ; 04F9 # 1.1 CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+04F9 ; valid # 1.1 CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+04FA ; mapped ; 04FB # 5.0 CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
+04FB ; valid # 5.0 CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK
+04FC ; mapped ; 04FD # 5.0 CYRILLIC CAPITAL LETTER HA WITH HOOK
+04FD ; valid # 5.0 CYRILLIC SMALL LETTER HA WITH HOOK
+04FE ; mapped ; 04FF # 5.0 CYRILLIC CAPITAL LETTER HA WITH STROKE
+04FF ; valid # 5.0 CYRILLIC SMALL LETTER HA WITH STROKE
+0500 ; mapped ; 0501 # 3.2 CYRILLIC CAPITAL LETTER KOMI DE
+0501 ; valid # 3.2 CYRILLIC SMALL LETTER KOMI DE
+0502 ; mapped ; 0503 # 3.2 CYRILLIC CAPITAL LETTER KOMI DJE
+0503 ; valid # 3.2 CYRILLIC SMALL LETTER KOMI DJE
+0504 ; mapped ; 0505 # 3.2 CYRILLIC CAPITAL LETTER KOMI ZJE
+0505 ; valid # 3.2 CYRILLIC SMALL LETTER KOMI ZJE
+0506 ; mapped ; 0507 # 3.2 CYRILLIC CAPITAL LETTER KOMI DZJE
+0507 ; valid # 3.2 CYRILLIC SMALL LETTER KOMI DZJE
+0508 ; mapped ; 0509 # 3.2 CYRILLIC CAPITAL LETTER KOMI LJE
+0509 ; valid # 3.2 CYRILLIC SMALL LETTER KOMI LJE
+050A ; mapped ; 050B # 3.2 CYRILLIC CAPITAL LETTER KOMI NJE
+050B ; valid # 3.2 CYRILLIC SMALL LETTER KOMI NJE
+050C ; mapped ; 050D # 3.2 CYRILLIC CAPITAL LETTER KOMI SJE
+050D ; valid # 3.2 CYRILLIC SMALL LETTER KOMI SJE
+050E ; mapped ; 050F # 3.2 CYRILLIC CAPITAL LETTER KOMI TJE
+050F ; valid # 3.2 CYRILLIC SMALL LETTER KOMI TJE
+0510 ; mapped ; 0511 # 5.0 CYRILLIC CAPITAL LETTER REVERSED ZE
+0511 ; valid # 5.0 CYRILLIC SMALL LETTER REVERSED ZE
+0512 ; mapped ; 0513 # 5.0 CYRILLIC CAPITAL LETTER EL WITH HOOK
+0513 ; valid # 5.0 CYRILLIC SMALL LETTER EL WITH HOOK
+0514 ; mapped ; 0515 # 5.1 CYRILLIC CAPITAL LETTER LHA
+0515 ; valid # 5.1 CYRILLIC SMALL LETTER LHA
+0516 ; mapped ; 0517 # 5.1 CYRILLIC CAPITAL LETTER RHA
+0517 ; valid # 5.1 CYRILLIC SMALL LETTER RHA
+0518 ; mapped ; 0519 # 5.1 CYRILLIC CAPITAL LETTER YAE
+0519 ; valid # 5.1 CYRILLIC SMALL LETTER YAE
+051A ; mapped ; 051B # 5.1 CYRILLIC CAPITAL LETTER QA
+051B ; valid # 5.1 CYRILLIC SMALL LETTER QA
+051C ; mapped ; 051D # 5.1 CYRILLIC CAPITAL LETTER WE
+051D ; valid # 5.1 CYRILLIC SMALL LETTER WE
+051E ; mapped ; 051F # 5.1 CYRILLIC CAPITAL LETTER ALEUT KA
+051F ; valid # 5.1 CYRILLIC SMALL LETTER ALEUT KA
+0520 ; mapped ; 0521 # 5.1 CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
+0521 ; valid # 5.1 CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
+0522 ; mapped ; 0523 # 5.1 CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
+0523 ; valid # 5.1 CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
+0524 ; mapped ; 0525 # 5.2 CYRILLIC CAPITAL LETTER PE WITH DESCENDER
+0525 ; valid # 5.2 CYRILLIC SMALL LETTER PE WITH DESCENDER
+0526 ; mapped ; 0527 # 6.0 CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
+0527 ; valid # 6.0 CYRILLIC SMALL LETTER SHHA WITH DESCENDER
+0528 ; mapped ; 0529 # 7.0 CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK
+0529 ; valid # 7.0 CYRILLIC SMALL LETTER EN WITH LEFT HOOK
+052A ; mapped ; 052B # 7.0 CYRILLIC CAPITAL LETTER DZZHE
+052B ; valid # 7.0 CYRILLIC SMALL LETTER DZZHE
+052C ; mapped ; 052D # 7.0 CYRILLIC CAPITAL LETTER DCHE
+052D ; valid # 7.0 CYRILLIC SMALL LETTER DCHE
+052E ; mapped ; 052F # 7.0 CYRILLIC CAPITAL LETTER EL WITH DESCENDER
+052F ; valid # 7.0 CYRILLIC SMALL LETTER EL WITH DESCENDER
+0530 ; disallowed # NA <reserved-0530>
+0531 ; mapped ; 0561 # 1.1 ARMENIAN CAPITAL LETTER AYB
+0532 ; mapped ; 0562 # 1.1 ARMENIAN CAPITAL LETTER BEN
+0533 ; mapped ; 0563 # 1.1 ARMENIAN CAPITAL LETTER GIM
+0534 ; mapped ; 0564 # 1.1 ARMENIAN CAPITAL LETTER DA
+0535 ; mapped ; 0565 # 1.1 ARMENIAN CAPITAL LETTER ECH
+0536 ; mapped ; 0566 # 1.1 ARMENIAN CAPITAL LETTER ZA
+0537 ; mapped ; 0567 # 1.1 ARMENIAN CAPITAL LETTER EH
+0538 ; mapped ; 0568 # 1.1 ARMENIAN CAPITAL LETTER ET
+0539 ; mapped ; 0569 # 1.1 ARMENIAN CAPITAL LETTER TO
+053A ; mapped ; 056A # 1.1 ARMENIAN CAPITAL LETTER ZHE
+053B ; mapped ; 056B # 1.1 ARMENIAN CAPITAL LETTER INI
+053C ; mapped ; 056C # 1.1 ARMENIAN CAPITAL LETTER LIWN
+053D ; mapped ; 056D # 1.1 ARMENIAN CAPITAL LETTER XEH
+053E ; mapped ; 056E # 1.1 ARMENIAN CAPITAL LETTER CA
+053F ; mapped ; 056F # 1.1 ARMENIAN CAPITAL LETTER KEN
+0540 ; mapped ; 0570 # 1.1 ARMENIAN CAPITAL LETTER HO
+0541 ; mapped ; 0571 # 1.1 ARMENIAN CAPITAL LETTER JA
+0542 ; mapped ; 0572 # 1.1 ARMENIAN CAPITAL LETTER GHAD
+0543 ; mapped ; 0573 # 1.1 ARMENIAN CAPITAL LETTER CHEH
+0544 ; mapped ; 0574 # 1.1 ARMENIAN CAPITAL LETTER MEN
+0545 ; mapped ; 0575 # 1.1 ARMENIAN CAPITAL LETTER YI
+0546 ; mapped ; 0576 # 1.1 ARMENIAN CAPITAL LETTER NOW
+0547 ; mapped ; 0577 # 1.1 ARMENIAN CAPITAL LETTER SHA
+0548 ; mapped ; 0578 # 1.1 ARMENIAN CAPITAL LETTER VO
+0549 ; mapped ; 0579 # 1.1 ARMENIAN CAPITAL LETTER CHA
+054A ; mapped ; 057A # 1.1 ARMENIAN CAPITAL LETTER PEH
+054B ; mapped ; 057B # 1.1 ARMENIAN CAPITAL LETTER JHEH
+054C ; mapped ; 057C # 1.1 ARMENIAN CAPITAL LETTER RA
+054D ; mapped ; 057D # 1.1 ARMENIAN CAPITAL LETTER SEH
+054E ; mapped ; 057E # 1.1 ARMENIAN CAPITAL LETTER VEW
+054F ; mapped ; 057F # 1.1 ARMENIAN CAPITAL LETTER TIWN
+0550 ; mapped ; 0580 # 1.1 ARMENIAN CAPITAL LETTER REH
+0551 ; mapped ; 0581 # 1.1 ARMENIAN CAPITAL LETTER CO
+0552 ; mapped ; 0582 # 1.1 ARMENIAN CAPITAL LETTER YIWN
+0553 ; mapped ; 0583 # 1.1 ARMENIAN CAPITAL LETTER PIWR
+0554 ; mapped ; 0584 # 1.1 ARMENIAN CAPITAL LETTER KEH
+0555 ; mapped ; 0585 # 1.1 ARMENIAN CAPITAL LETTER OH
+0556 ; mapped ; 0586 # 1.1 ARMENIAN CAPITAL LETTER FEH
+0557..0558 ; disallowed # NA <reserved-0557>..<reserved-0558>
+0559 ; valid # 1.1 ARMENIAN MODIFIER LETTER LEFT HALF RING
+055A..055F ; valid ; ; NV8 # 1.1 ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
+0560 ; valid # 11.0 ARMENIAN SMALL LETTER TURNED AYB
+0561..0586 ; valid # 1.1 ARMENIAN SMALL LETTER AYB..ARMENIAN SMALL LETTER FEH
+0587 ; mapped ; 0565 0582 # 1.1 ARMENIAN SMALL LIGATURE ECH YIWN
+0588 ; valid # 11.0 ARMENIAN SMALL LETTER YI WITH STROKE
+0589 ; valid ; ; NV8 # 1.1 ARMENIAN FULL STOP
+058A ; valid ; ; NV8 # 3.0 ARMENIAN HYPHEN
+058B..058C ; disallowed # NA <reserved-058B>..<reserved-058C>
+058D..058E ; valid ; ; NV8 # 7.0 RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN
+058F ; valid ; ; NV8 # 6.1 ARMENIAN DRAM SIGN
+0590 ; disallowed # NA <reserved-0590>
+0591..05A1 ; valid # 2.0 HEBREW ACCENT ETNAHTA..HEBREW ACCENT PAZER
+05A2 ; valid # 4.1 HEBREW ACCENT ATNAH HAFUKH
+05A3..05AF ; valid # 2.0 HEBREW ACCENT MUNAH..HEBREW MARK MASORA CIRCLE
+05B0..05B9 ; valid # 1.1 HEBREW POINT SHEVA..HEBREW POINT HOLAM
+05BA ; valid # 5.0 HEBREW POINT HOLAM HASER FOR VAV
+05BB..05BD ; valid # 1.1 HEBREW POINT QUBUTS..HEBREW POINT METEG
+05BE ; valid ; ; NV8 # 1.1 HEBREW PUNCTUATION MAQAF
+05BF ; valid # 1.1 HEBREW POINT RAFE
+05C0 ; valid ; ; NV8 # 1.1 HEBREW PUNCTUATION PASEQ
+05C1..05C2 ; valid # 1.1 HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
+05C3 ; valid ; ; NV8 # 1.1 HEBREW PUNCTUATION SOF PASUQ
+05C4 ; valid # 2.0 HEBREW MARK UPPER DOT
+05C5 ; valid # 4.1 HEBREW MARK LOWER DOT
+05C6 ; valid ; ; NV8 # 4.1 HEBREW PUNCTUATION NUN HAFUKHA
+05C7 ; valid # 4.1 HEBREW POINT QAMATS QATAN
+05C8..05CF ; disallowed # NA <reserved-05C8>..<reserved-05CF>
+05D0..05EA ; valid # 1.1 HEBREW LETTER ALEF..HEBREW LETTER TAV
+05EB..05EE ; disallowed # NA <reserved-05EB>..<reserved-05EE>
+05EF ; valid # 11.0 HEBREW YOD TRIANGLE
+05F0..05F4 ; valid # 1.1 HEBREW LIGATURE YIDDISH DOUBLE VAV..HEBREW PUNCTUATION GERSHAYIM
+05F5..05FF ; disallowed # NA <reserved-05F5>..<reserved-05FF>
+0600..0603 ; disallowed # 4.0 ARABIC NUMBER SIGN..ARABIC SIGN SAFHA
+0604 ; disallowed # 6.1 ARABIC SIGN SAMVAT
+0605 ; disallowed # 7.0 ARABIC NUMBER MARK ABOVE
+0606..060A ; valid ; ; NV8 # 5.1 ARABIC-INDIC CUBE ROOT..ARABIC-INDIC PER TEN THOUSAND SIGN
+060B ; valid ; ; NV8 # 4.1 AFGHANI SIGN
+060C ; valid ; ; NV8 # 1.1 ARABIC COMMA
+060D..060F ; valid ; ; NV8 # 4.0 ARABIC DATE SEPARATOR..ARABIC SIGN MISRA
+0610..0615 ; valid # 4.0 ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL HIGH TAH
+0616..061A ; valid # 5.1 ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH..ARABIC SMALL KASRA
+061B ; valid ; ; NV8 # 1.1 ARABIC SEMICOLON
+061C ; disallowed # 6.3 ARABIC LETTER MARK
+061D ; valid ; ; NV8 # 14.0 ARABIC END OF TEXT MARK
+061E ; valid ; ; NV8 # 4.1 ARABIC TRIPLE DOT PUNCTUATION MARK
+061F ; valid ; ; NV8 # 1.1 ARABIC QUESTION MARK
+0620 ; valid # 6.0 ARABIC LETTER KASHMIRI YEH
+0621..063A ; valid # 1.1 ARABIC LETTER HAMZA..ARABIC LETTER GHAIN
+063B..063F ; valid # 5.1 ARABIC LETTER KEHEH WITH TWO DOTS ABOVE..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0640 ; valid ; ; NV8 # 1.1 ARABIC TATWEEL
+0641..0652 ; valid # 1.1 ARABIC LETTER FEH..ARABIC SUKUN
+0653..0655 ; valid # 3.0 ARABIC MADDAH ABOVE..ARABIC HAMZA BELOW
+0656..0658 ; valid # 4.0 ARABIC SUBSCRIPT ALEF..ARABIC MARK NOON GHUNNA
+0659..065E ; valid # 4.1 ARABIC ZWARAKAY..ARABIC FATHA WITH TWO DOTS
+065F ; valid # 6.0 ARABIC WAVY HAMZA BELOW
+0660..0669 ; valid # 1.1 ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
+066A..066D ; valid ; ; NV8 # 1.1 ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
+066E..066F ; valid # 3.2 ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
+0670..0674 ; valid # 1.1 ARABIC LETTER SUPERSCRIPT ALEF..ARABIC LETTER HIGH HAMZA
+0675 ; mapped ; 0627 0674 # 1.1 ARABIC LETTER HIGH HAMZA ALEF
+0676 ; mapped ; 0648 0674 # 1.1 ARABIC LETTER HIGH HAMZA WAW
+0677 ; mapped ; 06C7 0674 # 1.1 ARABIC LETTER U WITH HAMZA ABOVE
+0678 ; mapped ; 064A 0674 # 1.1 ARABIC LETTER HIGH HAMZA YEH
+0679..06B7 ; valid # 1.1 ARABIC LETTER TTEH..ARABIC LETTER LAM WITH THREE DOTS ABOVE
+06B8..06B9 ; valid # 3.0 ARABIC LETTER LAM WITH THREE DOTS BELOW..ARABIC LETTER NOON WITH DOT BELOW
+06BA..06BE ; valid # 1.1 ARABIC LETTER NOON GHUNNA..ARABIC LETTER HEH DOACHASHMEE
+06BF ; valid # 3.0 ARABIC LETTER TCHEH WITH DOT ABOVE
+06C0..06CE ; valid # 1.1 ARABIC LETTER HEH WITH YEH ABOVE..ARABIC LETTER YEH WITH SMALL V
+06CF ; valid # 3.0 ARABIC LETTER WAW WITH DOT ABOVE
+06D0..06D3 ; valid # 1.1 ARABIC LETTER E..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+06D4 ; valid ; ; NV8 # 1.1 ARABIC FULL STOP
+06D5..06DC ; valid # 1.1 ARABIC LETTER AE..ARABIC SMALL HIGH SEEN
+06DD ; disallowed # 1.1 ARABIC END OF AYAH
+06DE ; valid ; ; NV8 # 1.1 ARABIC START OF RUB EL HIZB
+06DF..06E8 ; valid # 1.1 ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH NOON
+06E9 ; valid ; ; NV8 # 1.1 ARABIC PLACE OF SAJDAH
+06EA..06ED ; valid # 1.1 ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
+06EE..06EF ; valid # 4.0 ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V
+06F0..06F9 ; valid # 1.1 EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
+06FA..06FE ; valid # 3.0 ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC SIGN SINDHI POSTPOSITION MEN
+06FF ; valid # 4.0 ARABIC LETTER HEH WITH INVERTED V
+0700..070D ; valid ; ; NV8 # 3.0 SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
+070E ; disallowed # NA <reserved-070E>
+070F ; disallowed # 3.0 SYRIAC ABBREVIATION MARK
+0710..072C ; valid # 3.0 SYRIAC LETTER ALAPH..SYRIAC LETTER TAW
+072D..072F ; valid # 4.0 SYRIAC LETTER PERSIAN BHETH..SYRIAC LETTER PERSIAN DHALATH
+0730..074A ; valid # 3.0 SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
+074B..074C ; disallowed # NA <reserved-074B>..<reserved-074C>
+074D..074F ; valid # 4.0 SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE
+0750..076D ; valid # 4.1 ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE
+076E..077F ; valid # 5.1 ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
+0780..07B0 ; valid # 3.0 THAANA LETTER HAA..THAANA SUKUN
+07B1 ; valid # 3.2 THAANA LETTER NAA
+07B2..07BF ; disallowed # NA <reserved-07B2>..<reserved-07BF>
+07C0..07F5 ; valid # 5.0 NKO DIGIT ZERO..NKO LOW TONE APOSTROPHE
+07F6..07FA ; valid ; ; NV8 # 5.0 NKO SYMBOL OO DENNEN..NKO LAJANYALAN
+07FB..07FC ; disallowed # NA <reserved-07FB>..<reserved-07FC>
+07FD ; valid # 11.0 NKO DANTAYALAN
+07FE..07FF ; valid ; ; NV8 # 11.0 NKO DOROME SIGN..NKO TAMAN SIGN
+0800..082D ; valid # 5.2 SAMARITAN LETTER ALAF..SAMARITAN MARK NEQUDAA
+082E..082F ; disallowed # NA <reserved-082E>..<reserved-082F>
+0830..083E ; valid ; ; NV8 # 5.2 SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
+083F ; disallowed # NA <reserved-083F>
+0840..085B ; valid # 6.0 MANDAIC LETTER HALQA..MANDAIC GEMINATION MARK
+085C..085D ; disallowed # NA <reserved-085C>..<reserved-085D>
+085E ; valid ; ; NV8 # 6.0 MANDAIC PUNCTUATION
+085F ; disallowed # NA <reserved-085F>
+0860..086A ; valid # 10.0 SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
+086B..086F ; disallowed # NA <reserved-086B>..<reserved-086F>
+0870..0887 ; valid # 14.0 ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT
+0888 ; valid ; ; NV8 # 14.0 ARABIC RAISED ROUND DOT
+0889..088E ; valid # 14.0 ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL
+088F ; disallowed # NA <reserved-088F>
+0890..0891 ; disallowed # 14.0 ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
+0892..0897 ; disallowed # NA <reserved-0892>..<reserved-0897>
+0898..089F ; valid # 14.0 ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
+08A0 ; valid # 6.1 ARABIC LETTER BEH WITH SMALL V BELOW
+08A1 ; valid # 7.0 ARABIC LETTER BEH WITH HAMZA ABOVE
+08A2..08AC ; valid # 6.1 ARABIC LETTER JEEM WITH TWO DOTS ABOVE..ARABIC LETTER ROHINGYA YEH
+08AD..08B2 ; valid # 7.0 ARABIC LETTER LOW ALEF..ARABIC LETTER ZAIN WITH INVERTED V ABOVE
+08B3..08B4 ; valid # 8.0 ARABIC LETTER AIN WITH THREE DOTS BELOW..ARABIC LETTER KAF WITH DOT BELOW
+08B5 ; valid # 14.0 ARABIC LETTER QAF WITH DOT BELOW AND NO DOTS ABOVE
+08B6..08BD ; valid # 9.0 ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON
+08BE..08C7 ; valid # 13.0 ARABIC LETTER PEH WITH SMALL V..ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE
+08C8..08D2 ; valid # 14.0 ARABIC LETTER GRAF..ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW
+08D3 ; valid # 11.0 ARABIC SMALL LOW WAW
+08D4..08E1 ; valid # 9.0 ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA
+08E2 ; disallowed # 9.0 ARABIC DISPUTED END OF AYAH
+08E3 ; valid # 8.0 ARABIC TURNED DAMMA BELOW
+08E4..08FE ; valid # 6.1 ARABIC CURLY FATHA..ARABIC DAMMA WITH DOT
+08FF ; valid # 7.0 ARABIC MARK SIDEWAYS NOON GHUNNA
+0900 ; valid # 5.2 DEVANAGARI SIGN INVERTED CANDRABINDU
+0901..0903 ; valid # 1.1 DEVANAGARI SIGN CANDRABINDU..DEVANAGARI SIGN VISARGA
+0904 ; valid # 4.0 DEVANAGARI LETTER SHORT A
+0905..0939 ; valid # 1.1 DEVANAGARI LETTER A..DEVANAGARI LETTER HA
+093A..093B ; valid # 6.0 DEVANAGARI VOWEL SIGN OE..DEVANAGARI VOWEL SIGN OOE
+093C..094D ; valid # 1.1 DEVANAGARI SIGN NUKTA..DEVANAGARI SIGN VIRAMA
+094E ; valid # 5.2 DEVANAGARI VOWEL SIGN PRISHTHAMATRA E
+094F ; valid # 6.0 DEVANAGARI VOWEL SIGN AW
+0950..0954 ; valid # 1.1 DEVANAGARI OM..DEVANAGARI ACUTE ACCENT
+0955 ; valid # 5.2 DEVANAGARI VOWEL SIGN CANDRA LONG E
+0956..0957 ; valid # 6.0 DEVANAGARI VOWEL SIGN UE..DEVANAGARI VOWEL SIGN UUE
+0958 ; mapped ; 0915 093C # 1.1 DEVANAGARI LETTER QA
+0959 ; mapped ; 0916 093C # 1.1 DEVANAGARI LETTER KHHA
+095A ; mapped ; 0917 093C # 1.1 DEVANAGARI LETTER GHHA
+095B ; mapped ; 091C 093C # 1.1 DEVANAGARI LETTER ZA
+095C ; mapped ; 0921 093C # 1.1 DEVANAGARI LETTER DDDHA
+095D ; mapped ; 0922 093C # 1.1 DEVANAGARI LETTER RHA
+095E ; mapped ; 092B 093C # 1.1 DEVANAGARI LETTER FA
+095F ; mapped ; 092F 093C # 1.1 DEVANAGARI LETTER YYA
+0960..0963 ; valid # 1.1 DEVANAGARI LETTER VOCALIC RR..DEVANAGARI VOWEL SIGN VOCALIC LL
+0964..0965 ; valid ; ; NV8 # 1.1 DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
+0966..096F ; valid # 1.1 DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
+0970 ; valid ; ; NV8 # 1.1 DEVANAGARI ABBREVIATION SIGN
+0971..0972 ; valid # 5.1 DEVANAGARI SIGN HIGH SPACING DOT..DEVANAGARI LETTER CANDRA A
+0973..0977 ; valid # 6.0 DEVANAGARI LETTER OE..DEVANAGARI LETTER UUE
+0978 ; valid # 7.0 DEVANAGARI LETTER MARWARI DDA
+0979..097A ; valid # 5.2 DEVANAGARI LETTER ZHA..DEVANAGARI LETTER HEAVY YA
+097B..097C ; valid # 5.0 DEVANAGARI LETTER GGA..DEVANAGARI LETTER JJA
+097D ; valid # 4.1 DEVANAGARI LETTER GLOTTAL STOP
+097E..097F ; valid # 5.0 DEVANAGARI LETTER DDDA..DEVANAGARI LETTER BBA
+0980 ; valid # 7.0 BENGALI ANJI
+0981..0983 ; valid # 1.1 BENGALI SIGN CANDRABINDU..BENGALI SIGN VISARGA
+0984 ; disallowed # NA <reserved-0984>
+0985..098C ; valid # 1.1 BENGALI LETTER A..BENGALI LETTER VOCALIC L
+098D..098E ; disallowed # NA <reserved-098D>..<reserved-098E>
+098F..0990 ; valid # 1.1 BENGALI LETTER E..BENGALI LETTER AI
+0991..0992 ; disallowed # NA <reserved-0991>..<reserved-0992>
+0993..09A8 ; valid # 1.1 BENGALI LETTER O..BENGALI LETTER NA
+09A9 ; disallowed # NA <reserved-09A9>
+09AA..09B0 ; valid # 1.1 BENGALI LETTER PA..BENGALI LETTER RA
+09B1 ; disallowed # NA <reserved-09B1>
+09B2 ; valid # 1.1 BENGALI LETTER LA
+09B3..09B5 ; disallowed # NA <reserved-09B3>..<reserved-09B5>
+09B6..09B9 ; valid # 1.1 BENGALI LETTER SHA..BENGALI LETTER HA
+09BA..09BB ; disallowed # NA <reserved-09BA>..<reserved-09BB>
+09BC ; valid # 1.1 BENGALI SIGN NUKTA
+09BD ; valid # 4.0 BENGALI SIGN AVAGRAHA
+09BE..09C4 ; valid # 1.1 BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN VOCALIC RR
+09C5..09C6 ; disallowed # NA <reserved-09C5>..<reserved-09C6>
+09C7..09C8 ; valid # 1.1 BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
+09C9..09CA ; disallowed # NA <reserved-09C9>..<reserved-09CA>
+09CB..09CD ; valid # 1.1 BENGALI VOWEL SIGN O..BENGALI SIGN VIRAMA
+09CE ; valid # 4.1 BENGALI LETTER KHANDA TA
+09CF..09D6 ; disallowed # NA <reserved-09CF>..<reserved-09D6>
+09D7 ; valid # 1.1 BENGALI AU LENGTH MARK
+09D8..09DB ; disallowed # NA <reserved-09D8>..<reserved-09DB>
+09DC ; mapped ; 09A1 09BC # 1.1 BENGALI LETTER RRA
+09DD ; mapped ; 09A2 09BC # 1.1 BENGALI LETTER RHA
+09DE ; disallowed # NA <reserved-09DE>
+09DF ; mapped ; 09AF 09BC # 1.1 BENGALI LETTER YYA
+09E0..09E3 ; valid # 1.1 BENGALI LETTER VOCALIC RR..BENGALI VOWEL SIGN VOCALIC LL
+09E4..09E5 ; disallowed # NA <reserved-09E4>..<reserved-09E5>
+09E6..09F1 ; valid # 1.1 BENGALI DIGIT ZERO..BENGALI LETTER RA WITH LOWER DIAGONAL
+09F2..09FA ; valid ; ; NV8 # 1.1 BENGALI RUPEE MARK..BENGALI ISSHAR
+09FB ; valid ; ; NV8 # 5.2 BENGALI GANDA MARK
+09FC ; valid # 10.0 BENGALI LETTER VEDIC ANUSVARA
+09FD ; valid ; ; NV8 # 10.0 BENGALI ABBREVIATION SIGN
+09FE ; valid # 11.0 BENGALI SANDHI MARK
+09FF..0A00 ; disallowed # NA <reserved-09FF>..<reserved-0A00>
+0A01 ; valid # 4.0 GURMUKHI SIGN ADAK BINDI
+0A02 ; valid # 1.1 GURMUKHI SIGN BINDI
+0A03 ; valid # 4.0 GURMUKHI SIGN VISARGA
+0A04 ; disallowed # NA <reserved-0A04>
+0A05..0A0A ; valid # 1.1 GURMUKHI LETTER A..GURMUKHI LETTER UU
+0A0B..0A0E ; disallowed # NA <reserved-0A0B>..<reserved-0A0E>
+0A0F..0A10 ; valid # 1.1 GURMUKHI LETTER EE..GURMUKHI LETTER AI
+0A11..0A12 ; disallowed # NA <reserved-0A11>..<reserved-0A12>
+0A13..0A28 ; valid # 1.1 GURMUKHI LETTER OO..GURMUKHI LETTER NA
+0A29 ; disallowed # NA <reserved-0A29>
+0A2A..0A30 ; valid # 1.1 GURMUKHI LETTER PA..GURMUKHI LETTER RA
+0A31 ; disallowed # NA <reserved-0A31>
+0A32 ; valid # 1.1 GURMUKHI LETTER LA
+0A33 ; mapped ; 0A32 0A3C # 1.1 GURMUKHI LETTER LLA
+0A34 ; disallowed # NA <reserved-0A34>
+0A35 ; valid # 1.1 GURMUKHI LETTER VA
+0A36 ; mapped ; 0A38 0A3C # 1.1 GURMUKHI LETTER SHA
+0A37 ; disallowed # NA <reserved-0A37>
+0A38..0A39 ; valid # 1.1 GURMUKHI LETTER SA..GURMUKHI LETTER HA
+0A3A..0A3B ; disallowed # NA <reserved-0A3A>..<reserved-0A3B>
+0A3C ; valid # 1.1 GURMUKHI SIGN NUKTA
+0A3D ; disallowed # NA <reserved-0A3D>
+0A3E..0A42 ; valid # 1.1 GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN UU
+0A43..0A46 ; disallowed # NA <reserved-0A43>..<reserved-0A46>
+0A47..0A48 ; valid # 1.1 GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
+0A49..0A4A ; disallowed # NA <reserved-0A49>..<reserved-0A4A>
+0A4B..0A4D ; valid # 1.1 GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
+0A4E..0A50 ; disallowed # NA <reserved-0A4E>..<reserved-0A50>
+0A51 ; valid # 5.1 GURMUKHI SIGN UDAAT
+0A52..0A58 ; disallowed # NA <reserved-0A52>..<reserved-0A58>
+0A59 ; mapped ; 0A16 0A3C # 1.1 GURMUKHI LETTER KHHA
+0A5A ; mapped ; 0A17 0A3C # 1.1 GURMUKHI LETTER GHHA
+0A5B ; mapped ; 0A1C 0A3C # 1.1 GURMUKHI LETTER ZA
+0A5C ; valid # 1.1 GURMUKHI LETTER RRA
+0A5D ; disallowed # NA <reserved-0A5D>
+0A5E ; mapped ; 0A2B 0A3C # 1.1 GURMUKHI LETTER FA
+0A5F..0A65 ; disallowed # NA <reserved-0A5F>..<reserved-0A65>
+0A66..0A74 ; valid # 1.1 GURMUKHI DIGIT ZERO..GURMUKHI EK ONKAR
+0A75 ; valid # 5.1 GURMUKHI SIGN YAKASH
+0A76 ; valid ; ; NV8 # 11.0 GURMUKHI ABBREVIATION SIGN
+0A77..0A80 ; disallowed # NA <reserved-0A77>..<reserved-0A80>
+0A81..0A83 ; valid # 1.1 GUJARATI SIGN CANDRABINDU..GUJARATI SIGN VISARGA
+0A84 ; disallowed # NA <reserved-0A84>
+0A85..0A8B ; valid # 1.1 GUJARATI LETTER A..GUJARATI LETTER VOCALIC R
+0A8C ; valid # 4.0 GUJARATI LETTER VOCALIC L
+0A8D ; valid # 1.1 GUJARATI VOWEL CANDRA E
+0A8E ; disallowed # NA <reserved-0A8E>
+0A8F..0A91 ; valid # 1.1 GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
+0A92 ; disallowed # NA <reserved-0A92>
+0A93..0AA8 ; valid # 1.1 GUJARATI LETTER O..GUJARATI LETTER NA
+0AA9 ; disallowed # NA <reserved-0AA9>
+0AAA..0AB0 ; valid # 1.1 GUJARATI LETTER PA..GUJARATI LETTER RA
+0AB1 ; disallowed # NA <reserved-0AB1>
+0AB2..0AB3 ; valid # 1.1 GUJARATI LETTER LA..GUJARATI LETTER LLA
+0AB4 ; disallowed # NA <reserved-0AB4>
+0AB5..0AB9 ; valid # 1.1 GUJARATI LETTER VA..GUJARATI LETTER HA
+0ABA..0ABB ; disallowed # NA <reserved-0ABA>..<reserved-0ABB>
+0ABC..0AC5 ; valid # 1.1 GUJARATI SIGN NUKTA..GUJARATI VOWEL SIGN CANDRA E
+0AC6 ; disallowed # NA <reserved-0AC6>
+0AC7..0AC9 ; valid # 1.1 GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN CANDRA O
+0ACA ; disallowed # NA <reserved-0ACA>
+0ACB..0ACD ; valid # 1.1 GUJARATI VOWEL SIGN O..GUJARATI SIGN VIRAMA
+0ACE..0ACF ; disallowed # NA <reserved-0ACE>..<reserved-0ACF>
+0AD0 ; valid # 1.1 GUJARATI OM
+0AD1..0ADF ; disallowed # NA <reserved-0AD1>..<reserved-0ADF>
+0AE0 ; valid # 1.1 GUJARATI LETTER VOCALIC RR
+0AE1..0AE3 ; valid # 4.0 GUJARATI LETTER VOCALIC LL..GUJARATI VOWEL SIGN VOCALIC LL
+0AE4..0AE5 ; disallowed # NA <reserved-0AE4>..<reserved-0AE5>
+0AE6..0AEF ; valid # 1.1 GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
+0AF0 ; valid ; ; NV8 # 6.1 GUJARATI ABBREVIATION SIGN
+0AF1 ; valid ; ; NV8 # 4.0 GUJARATI RUPEE SIGN
+0AF2..0AF8 ; disallowed # NA <reserved-0AF2>..<reserved-0AF8>
+0AF9 ; valid # 8.0 GUJARATI LETTER ZHA
+0AFA..0AFF ; valid # 10.0 GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
+0B00 ; disallowed # NA <reserved-0B00>
+0B01..0B03 ; valid # 1.1 ORIYA SIGN CANDRABINDU..ORIYA SIGN VISARGA
+0B04 ; disallowed # NA <reserved-0B04>
+0B05..0B0C ; valid # 1.1 ORIYA LETTER A..ORIYA LETTER VOCALIC L
+0B0D..0B0E ; disallowed # NA <reserved-0B0D>..<reserved-0B0E>
+0B0F..0B10 ; valid # 1.1 ORIYA LETTER E..ORIYA LETTER AI
+0B11..0B12 ; disallowed # NA <reserved-0B11>..<reserved-0B12>
+0B13..0B28 ; valid # 1.1 ORIYA LETTER O..ORIYA LETTER NA
+0B29 ; disallowed # NA <reserved-0B29>
+0B2A..0B30 ; valid # 1.1 ORIYA LETTER PA..ORIYA LETTER RA
+0B31 ; disallowed # NA <reserved-0B31>
+0B32..0B33 ; valid # 1.1 ORIYA LETTER LA..ORIYA LETTER LLA
+0B34 ; disallowed # NA <reserved-0B34>
+0B35 ; valid # 4.0 ORIYA LETTER VA
+0B36..0B39 ; valid # 1.1 ORIYA LETTER SHA..ORIYA LETTER HA
+0B3A..0B3B ; disallowed # NA <reserved-0B3A>..<reserved-0B3B>
+0B3C..0B43 ; valid # 1.1 ORIYA SIGN NUKTA..ORIYA VOWEL SIGN VOCALIC R
+0B44 ; valid # 5.1 ORIYA VOWEL SIGN VOCALIC RR
+0B45..0B46 ; disallowed # NA <reserved-0B45>..<reserved-0B46>
+0B47..0B48 ; valid # 1.1 ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
+0B49..0B4A ; disallowed # NA <reserved-0B49>..<reserved-0B4A>
+0B4B..0B4D ; valid # 1.1 ORIYA VOWEL SIGN O..ORIYA SIGN VIRAMA
+0B4E..0B54 ; disallowed # NA <reserved-0B4E>..<reserved-0B54>
+0B55 ; valid # 13.0 ORIYA SIGN OVERLINE
+0B56..0B57 ; valid # 1.1 ORIYA AI LENGTH MARK..ORIYA AU LENGTH MARK
+0B58..0B5B ; disallowed # NA <reserved-0B58>..<reserved-0B5B>
+0B5C ; mapped ; 0B21 0B3C # 1.1 ORIYA LETTER RRA
+0B5D ; mapped ; 0B22 0B3C # 1.1 ORIYA LETTER RHA
+0B5E ; disallowed # NA <reserved-0B5E>
+0B5F..0B61 ; valid # 1.1 ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL
+0B62..0B63 ; valid # 5.1 ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
+0B64..0B65 ; disallowed # NA <reserved-0B64>..<reserved-0B65>
+0B66..0B6F ; valid # 1.1 ORIYA DIGIT ZERO..ORIYA DIGIT NINE
+0B70 ; valid ; ; NV8 # 1.1 ORIYA ISSHAR
+0B71 ; valid # 4.0 ORIYA LETTER WA
+0B72..0B77 ; valid ; ; NV8 # 6.0 ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
+0B78..0B81 ; disallowed # NA <reserved-0B78>..<reserved-0B81>
+0B82..0B83 ; valid # 1.1 TAMIL SIGN ANUSVARA..TAMIL SIGN VISARGA
+0B84 ; disallowed # NA <reserved-0B84>
+0B85..0B8A ; valid # 1.1 TAMIL LETTER A..TAMIL LETTER UU
+0B8B..0B8D ; disallowed # NA <reserved-0B8B>..<reserved-0B8D>
+0B8E..0B90 ; valid # 1.1 TAMIL LETTER E..TAMIL LETTER AI
+0B91 ; disallowed # NA <reserved-0B91>
+0B92..0B95 ; valid # 1.1 TAMIL LETTER O..TAMIL LETTER KA
+0B96..0B98 ; disallowed # NA <reserved-0B96>..<reserved-0B98>
+0B99..0B9A ; valid # 1.1 TAMIL LETTER NGA..TAMIL LETTER CA
+0B9B ; disallowed # NA <reserved-0B9B>
+0B9C ; valid # 1.1 TAMIL LETTER JA
+0B9D ; disallowed # NA <reserved-0B9D>
+0B9E..0B9F ; valid # 1.1 TAMIL LETTER NYA..TAMIL LETTER TTA
+0BA0..0BA2 ; disallowed # NA <reserved-0BA0>..<reserved-0BA2>
+0BA3..0BA4 ; valid # 1.1 TAMIL LETTER NNA..TAMIL LETTER TA
+0BA5..0BA7 ; disallowed # NA <reserved-0BA5>..<reserved-0BA7>
+0BA8..0BAA ; valid # 1.1 TAMIL LETTER NA..TAMIL LETTER PA
+0BAB..0BAD ; disallowed # NA <reserved-0BAB>..<reserved-0BAD>
+0BAE..0BB5 ; valid # 1.1 TAMIL LETTER MA..TAMIL LETTER VA
+0BB6 ; valid # 4.1 TAMIL LETTER SHA
+0BB7..0BB9 ; valid # 1.1 TAMIL LETTER SSA..TAMIL LETTER HA
+0BBA..0BBD ; disallowed # NA <reserved-0BBA>..<reserved-0BBD>
+0BBE..0BC2 ; valid # 1.1 TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN UU
+0BC3..0BC5 ; disallowed # NA <reserved-0BC3>..<reserved-0BC5>
+0BC6..0BC8 ; valid # 1.1 TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
+0BC9 ; disallowed # NA <reserved-0BC9>
+0BCA..0BCD ; valid # 1.1 TAMIL VOWEL SIGN O..TAMIL SIGN VIRAMA
+0BCE..0BCF ; disallowed # NA <reserved-0BCE>..<reserved-0BCF>
+0BD0 ; valid # 5.1 TAMIL OM
+0BD1..0BD6 ; disallowed # NA <reserved-0BD1>..<reserved-0BD6>
+0BD7 ; valid # 1.1 TAMIL AU LENGTH MARK
+0BD8..0BE5 ; disallowed # NA <reserved-0BD8>..<reserved-0BE5>
+0BE6 ; valid # 4.1 TAMIL DIGIT ZERO
+0BE7..0BEF ; valid # 1.1 TAMIL DIGIT ONE..TAMIL DIGIT NINE
+0BF0..0BF2 ; valid ; ; NV8 # 1.1 TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
+0BF3..0BFA ; valid ; ; NV8 # 4.0 TAMIL DAY SIGN..TAMIL NUMBER SIGN
+0BFB..0BFF ; disallowed # NA <reserved-0BFB>..<reserved-0BFF>
+0C00 ; valid # 7.0 TELUGU SIGN COMBINING CANDRABINDU ABOVE
+0C01..0C03 ; valid # 1.1 TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
+0C04 ; valid # 11.0 TELUGU SIGN COMBINING ANUSVARA ABOVE
+0C05..0C0C ; valid # 1.1 TELUGU LETTER A..TELUGU LETTER VOCALIC L
+0C0D ; disallowed # NA <reserved-0C0D>
+0C0E..0C10 ; valid # 1.1 TELUGU LETTER E..TELUGU LETTER AI
+0C11 ; disallowed # NA <reserved-0C11>
+0C12..0C28 ; valid # 1.1 TELUGU LETTER O..TELUGU LETTER NA
+0C29 ; disallowed # NA <reserved-0C29>
+0C2A..0C33 ; valid # 1.1 TELUGU LETTER PA..TELUGU LETTER LLA
+0C34 ; valid # 7.0 TELUGU LETTER LLLA
+0C35..0C39 ; valid # 1.1 TELUGU LETTER VA..TELUGU LETTER HA
+0C3A..0C3B ; disallowed # NA <reserved-0C3A>..<reserved-0C3B>
+0C3C ; valid # 14.0 TELUGU SIGN NUKTA
+0C3D ; valid # 5.1 TELUGU SIGN AVAGRAHA
+0C3E..0C44 ; valid # 1.1 TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN VOCALIC RR
+0C45 ; disallowed # NA <reserved-0C45>
+0C46..0C48 ; valid # 1.1 TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
+0C49 ; disallowed # NA <reserved-0C49>
+0C4A..0C4D ; valid # 1.1 TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
+0C4E..0C54 ; disallowed # NA <reserved-0C4E>..<reserved-0C54>
+0C55..0C56 ; valid # 1.1 TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
+0C57 ; disallowed # NA <reserved-0C57>
+0C58..0C59 ; valid # 5.1 TELUGU LETTER TSA..TELUGU LETTER DZA
+0C5A ; valid # 8.0 TELUGU LETTER RRRA
+0C5B..0C5C ; disallowed # NA <reserved-0C5B>..<reserved-0C5C>
+0C5D ; valid # 14.0 TELUGU LETTER NAKAARA POLLU
+0C5E..0C5F ; disallowed # NA <reserved-0C5E>..<reserved-0C5F>
+0C60..0C61 ; valid # 1.1 TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
+0C62..0C63 ; valid # 5.1 TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
+0C64..0C65 ; disallowed # NA <reserved-0C64>..<reserved-0C65>
+0C66..0C6F ; valid # 1.1 TELUGU DIGIT ZERO..TELUGU DIGIT NINE
+0C70..0C76 ; disallowed # NA <reserved-0C70>..<reserved-0C76>
+0C77 ; valid ; ; NV8 # 12.0 TELUGU SIGN SIDDHAM
+0C78..0C7F ; valid ; ; NV8 # 5.1 TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU SIGN TUUMU
+0C80 ; valid # 9.0 KANNADA SIGN SPACING CANDRABINDU
+0C81 ; valid # 7.0 KANNADA SIGN CANDRABINDU
+0C82..0C83 ; valid # 1.1 KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
+0C84 ; valid ; ; NV8 # 11.0 KANNADA SIGN SIDDHAM
+0C85..0C8C ; valid # 1.1 KANNADA LETTER A..KANNADA LETTER VOCALIC L
+0C8D ; disallowed # NA <reserved-0C8D>
+0C8E..0C90 ; valid # 1.1 KANNADA LETTER E..KANNADA LETTER AI
+0C91 ; disallowed # NA <reserved-0C91>
+0C92..0CA8 ; valid # 1.1 KANNADA LETTER O..KANNADA LETTER NA
+0CA9 ; disallowed # NA <reserved-0CA9>
+0CAA..0CB3 ; valid # 1.1 KANNADA LETTER PA..KANNADA LETTER LLA
+0CB4 ; disallowed # NA <reserved-0CB4>
+0CB5..0CB9 ; valid # 1.1 KANNADA LETTER VA..KANNADA LETTER HA
+0CBA..0CBB ; disallowed # NA <reserved-0CBA>..<reserved-0CBB>
+0CBC..0CBD ; valid # 4.0 KANNADA SIGN NUKTA..KANNADA SIGN AVAGRAHA
+0CBE..0CC4 ; valid # 1.1 KANNADA VOWEL SIGN AA..KANNADA VOWEL SIGN VOCALIC RR
+0CC5 ; disallowed # NA <reserved-0CC5>
+0CC6..0CC8 ; valid # 1.1 KANNADA VOWEL SIGN E..KANNADA VOWEL SIGN AI
+0CC9 ; disallowed # NA <reserved-0CC9>
+0CCA..0CCD ; valid # 1.1 KANNADA VOWEL SIGN O..KANNADA SIGN VIRAMA
+0CCE..0CD4 ; disallowed # NA <reserved-0CCE>..<reserved-0CD4>
+0CD5..0CD6 ; valid # 1.1 KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
+0CD7..0CDC ; disallowed # NA <reserved-0CD7>..<reserved-0CDC>
+0CDD ; valid # 14.0 KANNADA LETTER NAKAARA POLLU
+0CDE ; valid # 1.1 KANNADA LETTER FA
+0CDF ; disallowed # NA <reserved-0CDF>
+0CE0..0CE1 ; valid # 1.1 KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
+0CE2..0CE3 ; valid # 5.0 KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
+0CE4..0CE5 ; disallowed # NA <reserved-0CE4>..<reserved-0CE5>
+0CE6..0CEF ; valid # 1.1 KANNADA DIGIT ZERO..KANNADA DIGIT NINE
+0CF0 ; disallowed # NA <reserved-0CF0>
+0CF1..0CF2 ; valid # 5.0 KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
+0CF3..0CFF ; disallowed # NA <reserved-0CF3>..<reserved-0CFF>
+0D00 ; valid # 10.0 MALAYALAM SIGN COMBINING ANUSVARA ABOVE
+0D01 ; valid # 7.0 MALAYALAM SIGN CANDRABINDU
+0D02..0D03 ; valid # 1.1 MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
+0D04 ; valid # 13.0 MALAYALAM LETTER VEDIC ANUSVARA
+0D05..0D0C ; valid # 1.1 MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L
+0D0D ; disallowed # NA <reserved-0D0D>
+0D0E..0D10 ; valid # 1.1 MALAYALAM LETTER E..MALAYALAM LETTER AI
+0D11 ; disallowed # NA <reserved-0D11>
+0D12..0D28 ; valid # 1.1 MALAYALAM LETTER O..MALAYALAM LETTER NA
+0D29 ; valid # 6.0 MALAYALAM LETTER NNNA
+0D2A..0D39 ; valid # 1.1 MALAYALAM LETTER PA..MALAYALAM LETTER HA
+0D3A ; valid # 6.0 MALAYALAM LETTER TTTA
+0D3B..0D3C ; valid # 10.0 MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
+0D3D ; valid # 5.1 MALAYALAM SIGN AVAGRAHA
+0D3E..0D43 ; valid # 1.1 MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN VOCALIC R
+0D44 ; valid # 5.1 MALAYALAM VOWEL SIGN VOCALIC RR
+0D45 ; disallowed # NA <reserved-0D45>
+0D46..0D48 ; valid # 1.1 MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
+0D49 ; disallowed # NA <reserved-0D49>
+0D4A..0D4D ; valid # 1.1 MALAYALAM VOWEL SIGN O..MALAYALAM SIGN VIRAMA
+0D4E ; valid # 6.0 MALAYALAM LETTER DOT REPH
+0D4F ; valid ; ; NV8 # 9.0 MALAYALAM SIGN PARA
+0D50..0D53 ; disallowed # NA <reserved-0D50>..<reserved-0D53>
+0D54..0D56 ; valid # 9.0 MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL
+0D57 ; valid # 1.1 MALAYALAM AU LENGTH MARK
+0D58..0D5E ; valid ; ; NV8 # 9.0 MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
+0D5F ; valid # 8.0 MALAYALAM LETTER ARCHAIC II
+0D60..0D61 ; valid # 1.1 MALAYALAM LETTER VOCALIC RR..MALAYALAM LETTER VOCALIC LL
+0D62..0D63 ; valid # 5.1 MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
+0D64..0D65 ; disallowed # NA <reserved-0D64>..<reserved-0D65>
+0D66..0D6F ; valid # 1.1 MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
+0D70..0D75 ; valid ; ; NV8 # 5.1 MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS
+0D76..0D78 ; valid ; ; NV8 # 9.0 MALAYALAM FRACTION ONE SIXTEENTH..MALAYALAM FRACTION THREE SIXTEENTHS
+0D79 ; valid ; ; NV8 # 5.1 MALAYALAM DATE MARK
+0D7A..0D7F ; valid # 5.1 MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
+0D80 ; disallowed # NA <reserved-0D80>
+0D81 ; valid # 13.0 SINHALA SIGN CANDRABINDU
+0D82..0D83 ; valid # 3.0 SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
+0D84 ; disallowed # NA <reserved-0D84>
+0D85..0D96 ; valid # 3.0 SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
+0D97..0D99 ; disallowed # NA <reserved-0D97>..<reserved-0D99>
+0D9A..0DB1 ; valid # 3.0 SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
+0DB2 ; disallowed # NA <reserved-0DB2>
+0DB3..0DBB ; valid # 3.0 SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
+0DBC ; disallowed # NA <reserved-0DBC>
+0DBD ; valid # 3.0 SINHALA LETTER DANTAJA LAYANNA
+0DBE..0DBF ; disallowed # NA <reserved-0DBE>..<reserved-0DBF>
+0DC0..0DC6 ; valid # 3.0 SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
+0DC7..0DC9 ; disallowed # NA <reserved-0DC7>..<reserved-0DC9>
+0DCA ; valid # 3.0 SINHALA SIGN AL-LAKUNA
+0DCB..0DCE ; disallowed # NA <reserved-0DCB>..<reserved-0DCE>
+0DCF..0DD4 ; valid # 3.0 SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
+0DD5 ; disallowed # NA <reserved-0DD5>
+0DD6 ; valid # 3.0 SINHALA VOWEL SIGN DIGA PAA-PILLA
+0DD7 ; disallowed # NA <reserved-0DD7>
+0DD8..0DDF ; valid # 3.0 SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
+0DE0..0DE5 ; disallowed # NA <reserved-0DE0>..<reserved-0DE5>
+0DE6..0DEF ; valid # 7.0 SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
+0DF0..0DF1 ; disallowed # NA <reserved-0DF0>..<reserved-0DF1>
+0DF2..0DF3 ; valid # 3.0 SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
+0DF4 ; valid ; ; NV8 # 3.0 SINHALA PUNCTUATION KUNDDALIYA
+0DF5..0E00 ; disallowed # NA <reserved-0DF5>..<reserved-0E00>
+0E01..0E32 ; valid # 1.1 THAI CHARACTER KO KAI..THAI CHARACTER SARA AA
+0E33 ; mapped ; 0E4D 0E32 # 1.1 THAI CHARACTER SARA AM
+0E34..0E3A ; valid # 1.1 THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
+0E3B..0E3E ; disallowed # NA <reserved-0E3B>..<reserved-0E3E>
+0E3F ; valid ; ; NV8 # 1.1 THAI CURRENCY SYMBOL BAHT
+0E40..0E4E ; valid # 1.1 THAI CHARACTER SARA E..THAI CHARACTER YAMAKKAN
+0E4F ; valid ; ; NV8 # 1.1 THAI CHARACTER FONGMAN
+0E50..0E59 ; valid # 1.1 THAI DIGIT ZERO..THAI DIGIT NINE
+0E5A..0E5B ; valid ; ; NV8 # 1.1 THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
+0E5C..0E80 ; disallowed # NA <reserved-0E5C>..<reserved-0E80>
+0E81..0E82 ; valid # 1.1 LAO LETTER KO..LAO LETTER KHO SUNG
+0E83 ; disallowed # NA <reserved-0E83>
+0E84 ; valid # 1.1 LAO LETTER KHO TAM
+0E85 ; disallowed # NA <reserved-0E85>
+0E86 ; valid # 12.0 LAO LETTER PALI GHA
+0E87..0E88 ; valid # 1.1 LAO LETTER NGO..LAO LETTER CO
+0E89 ; valid # 12.0 LAO LETTER PALI CHA
+0E8A ; valid # 1.1 LAO LETTER SO TAM
+0E8B ; disallowed # NA <reserved-0E8B>
+0E8C ; valid # 12.0 LAO LETTER PALI JHA
+0E8D ; valid # 1.1 LAO LETTER NYO
+0E8E..0E93 ; valid # 12.0 LAO LETTER PALI NYA..LAO LETTER PALI NNA
+0E94..0E97 ; valid # 1.1 LAO LETTER DO..LAO LETTER THO TAM
+0E98 ; valid # 12.0 LAO LETTER PALI DHA
+0E99..0E9F ; valid # 1.1 LAO LETTER NO..LAO LETTER FO SUNG
+0EA0 ; valid # 12.0 LAO LETTER PALI BHA
+0EA1..0EA3 ; valid # 1.1 LAO LETTER MO..LAO LETTER LO LING
+0EA4 ; disallowed # NA <reserved-0EA4>
+0EA5 ; valid # 1.1 LAO LETTER LO LOOT
+0EA6 ; disallowed # NA <reserved-0EA6>
+0EA7 ; valid # 1.1 LAO LETTER WO
+0EA8..0EA9 ; valid # 12.0 LAO LETTER SANSKRIT SHA..LAO LETTER SANSKRIT SSA
+0EAA..0EAB ; valid # 1.1 LAO LETTER SO SUNG..LAO LETTER HO SUNG
+0EAC ; valid # 12.0 LAO LETTER PALI LLA
+0EAD..0EB2 ; valid # 1.1 LAO LETTER O..LAO VOWEL SIGN AA
+0EB3 ; mapped ; 0ECD 0EB2 # 1.1 LAO VOWEL SIGN AM
+0EB4..0EB9 ; valid # 1.1 LAO VOWEL SIGN I..LAO VOWEL SIGN UU
+0EBA ; valid # 12.0 LAO SIGN PALI VIRAMA
+0EBB..0EBD ; valid # 1.1 LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN NYO
+0EBE..0EBF ; disallowed # NA <reserved-0EBE>..<reserved-0EBF>
+0EC0..0EC4 ; valid # 1.1 LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+0EC5 ; disallowed # NA <reserved-0EC5>
+0EC6 ; valid # 1.1 LAO KO LA
+0EC7 ; disallowed # NA <reserved-0EC7>
+0EC8..0ECD ; valid # 1.1 LAO TONE MAI EK..LAO NIGGAHITA
+0ECE..0ECF ; disallowed # NA <reserved-0ECE>..<reserved-0ECF>
+0ED0..0ED9 ; valid # 1.1 LAO DIGIT ZERO..LAO DIGIT NINE
+0EDA..0EDB ; disallowed # NA <reserved-0EDA>..<reserved-0EDB>
+0EDC ; mapped ; 0EAB 0E99 # 1.1 LAO HO NO
+0EDD ; mapped ; 0EAB 0EA1 # 1.1 LAO HO MO
+0EDE..0EDF ; valid # 6.1 LAO LETTER KHMU GO..LAO LETTER KHMU NYO
+0EE0..0EFF ; disallowed # NA <reserved-0EE0>..<reserved-0EFF>
+0F00 ; valid # 2.0 TIBETAN SYLLABLE OM
+0F01..0F0A ; valid ; ; NV8 # 2.0 TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK BKA- SHOG YIG MGO
+0F0B ; valid # 2.0 TIBETAN MARK INTERSYLLABIC TSHEG
+0F0C ; mapped ; 0F0B # 2.0 TIBETAN MARK DELIMITER TSHEG BSTAR
+0F0D..0F17 ; valid ; ; NV8 # 2.0 TIBETAN MARK SHAD..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18..0F19 ; valid # 2.0 TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A..0F1F ; valid ; ; NV8 # 2.0 TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
+0F20..0F29 ; valid # 2.0 TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
+0F2A..0F34 ; valid ; ; NV8 # 2.0 TIBETAN DIGIT HALF ONE..TIBETAN MARK BSDUS RTAGS
+0F35 ; valid # 2.0 TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36 ; valid ; ; NV8 # 2.0 TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37 ; valid # 2.0 TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38 ; valid ; ; NV8 # 2.0 TIBETAN MARK CHE MGO
+0F39 ; valid # 2.0 TIBETAN MARK TSA -PHRU
+0F3A..0F3D ; valid ; ; NV8 # 2.0 TIBETAN MARK GUG RTAGS GYON..TIBETAN MARK ANG KHANG GYAS
+0F3E..0F42 ; valid # 2.0 TIBETAN SIGN YAR TSHES..TIBETAN LETTER GA
+0F43 ; mapped ; 0F42 0FB7 # 2.0 TIBETAN LETTER GHA
+0F44..0F47 ; valid # 2.0 TIBETAN LETTER NGA..TIBETAN LETTER JA
+0F48 ; disallowed # NA <reserved-0F48>
+0F49..0F4C ; valid # 2.0 TIBETAN LETTER NYA..TIBETAN LETTER DDA
+0F4D ; mapped ; 0F4C 0FB7 # 2.0 TIBETAN LETTER DDHA
+0F4E..0F51 ; valid # 2.0 TIBETAN LETTER NNA..TIBETAN LETTER DA
+0F52 ; mapped ; 0F51 0FB7 # 2.0 TIBETAN LETTER DHA
+0F53..0F56 ; valid # 2.0 TIBETAN LETTER NA..TIBETAN LETTER BA
+0F57 ; mapped ; 0F56 0FB7 # 2.0 TIBETAN LETTER BHA
+0F58..0F5B ; valid # 2.0 TIBETAN LETTER MA..TIBETAN LETTER DZA
+0F5C ; mapped ; 0F5B 0FB7 # 2.0 TIBETAN LETTER DZHA
+0F5D..0F68 ; valid # 2.0 TIBETAN LETTER WA..TIBETAN LETTER A
+0F69 ; mapped ; 0F40 0FB5 # 2.0 TIBETAN LETTER KSSA
+0F6A ; valid # 3.0 TIBETAN LETTER FIXED-FORM RA
+0F6B..0F6C ; valid # 5.1 TIBETAN LETTER KKA..TIBETAN LETTER RRA
+0F6D..0F70 ; disallowed # NA <reserved-0F6D>..<reserved-0F70>
+0F71..0F72 ; valid # 2.0 TIBETAN VOWEL SIGN AA..TIBETAN VOWEL SIGN I
+0F73 ; mapped ; 0F71 0F72 # 2.0 TIBETAN VOWEL SIGN II
+0F74 ; valid # 2.0 TIBETAN VOWEL SIGN U
+0F75 ; mapped ; 0F71 0F74 # 2.0 TIBETAN VOWEL SIGN UU
+0F76 ; mapped ; 0FB2 0F80 # 2.0 TIBETAN VOWEL SIGN VOCALIC R
+0F77 ; mapped ; 0FB2 0F71 0F80 #2.0 TIBETAN VOWEL SIGN VOCALIC RR
+0F78 ; mapped ; 0FB3 0F80 # 2.0 TIBETAN VOWEL SIGN VOCALIC L
+0F79 ; mapped ; 0FB3 0F71 0F80 #2.0 TIBETAN VOWEL SIGN VOCALIC LL
+0F7A..0F80 ; valid # 2.0 TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN REVERSED I
+0F81 ; mapped ; 0F71 0F80 # 2.0 TIBETAN VOWEL SIGN REVERSED II
+0F82..0F84 ; valid # 2.0 TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HALANTA
+0F85 ; valid ; ; NV8 # 2.0 TIBETAN MARK PALUTA
+0F86..0F8B ; valid # 2.0 TIBETAN SIGN LCI RTAGS..TIBETAN SIGN GRU MED RGYINGS
+0F8C..0F8F ; valid # 6.0 TIBETAN SIGN INVERTED MCHU CAN..TIBETAN SUBJOINED SIGN INVERTED MCHU CAN
+0F90..0F92 ; valid # 2.0 TIBETAN SUBJOINED LETTER KA..TIBETAN SUBJOINED LETTER GA
+0F93 ; mapped ; 0F92 0FB7 # 2.0 TIBETAN SUBJOINED LETTER GHA
+0F94..0F95 ; valid # 2.0 TIBETAN SUBJOINED LETTER NGA..TIBETAN SUBJOINED LETTER CA
+0F96 ; valid # 3.0 TIBETAN SUBJOINED LETTER CHA
+0F97 ; valid # 2.0 TIBETAN SUBJOINED LETTER JA
+0F98 ; disallowed # NA <reserved-0F98>
+0F99..0F9C ; valid # 2.0 TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER DDA
+0F9D ; mapped ; 0F9C 0FB7 # 2.0 TIBETAN SUBJOINED LETTER DDHA
+0F9E..0FA1 ; valid # 2.0 TIBETAN SUBJOINED LETTER NNA..TIBETAN SUBJOINED LETTER DA
+0FA2 ; mapped ; 0FA1 0FB7 # 2.0 TIBETAN SUBJOINED LETTER DHA
+0FA3..0FA6 ; valid # 2.0 TIBETAN SUBJOINED LETTER NA..TIBETAN SUBJOINED LETTER BA
+0FA7 ; mapped ; 0FA6 0FB7 # 2.0 TIBETAN SUBJOINED LETTER BHA
+0FA8..0FAB ; valid # 2.0 TIBETAN SUBJOINED LETTER MA..TIBETAN SUBJOINED LETTER DZA
+0FAC ; mapped ; 0FAB 0FB7 # 2.0 TIBETAN SUBJOINED LETTER DZHA
+0FAD ; valid # 2.0 TIBETAN SUBJOINED LETTER WA
+0FAE..0FB0 ; valid # 3.0 TIBETAN SUBJOINED LETTER ZHA..TIBETAN SUBJOINED LETTER -A
+0FB1..0FB7 ; valid # 2.0 TIBETAN SUBJOINED LETTER YA..TIBETAN SUBJOINED LETTER HA
+0FB8 ; valid # 3.0 TIBETAN SUBJOINED LETTER A
+0FB9 ; mapped ; 0F90 0FB5 # 2.0 TIBETAN SUBJOINED LETTER KSSA
+0FBA..0FBC ; valid # 3.0 TIBETAN SUBJOINED LETTER FIXED-FORM WA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
+0FBD ; disallowed # NA <reserved-0FBD>
+0FBE..0FC5 ; valid ; ; NV8 # 3.0 TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
+0FC6 ; valid # 3.0 TIBETAN SYMBOL PADMA GDAN
+0FC7..0FCC ; valid ; ; NV8 # 3.0 TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
+0FCD ; disallowed # NA <reserved-0FCD>
+0FCE ; valid ; ; NV8 # 5.1 TIBETAN SIGN RDEL NAG RDEL DKAR
+0FCF ; valid ; ; NV8 # 3.0 TIBETAN SIGN RDEL NAG GSUM
+0FD0..0FD1 ; valid ; ; NV8 # 4.1 TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK MNYAM YIG GI MGO RGYAN
+0FD2..0FD4 ; valid ; ; NV8 # 5.1 TIBETAN MARK NYIS TSHEG..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA
+0FD5..0FD8 ; valid ; ; NV8 # 5.2 RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS
+0FD9..0FDA ; valid ; ; NV8 # 6.0 TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS
+0FDB..0FFF ; disallowed # NA <reserved-0FDB>..<reserved-0FFF>
+1000..1021 ; valid # 3.0 MYANMAR LETTER KA..MYANMAR LETTER A
+1022 ; valid # 5.1 MYANMAR LETTER SHAN A
+1023..1027 ; valid # 3.0 MYANMAR LETTER I..MYANMAR LETTER E
+1028 ; valid # 5.1 MYANMAR LETTER MON E
+1029..102A ; valid # 3.0 MYANMAR LETTER O..MYANMAR LETTER AU
+102B ; valid # 5.1 MYANMAR VOWEL SIGN TALL AA
+102C..1032 ; valid # 3.0 MYANMAR VOWEL SIGN AA..MYANMAR VOWEL SIGN AI
+1033..1035 ; valid # 5.1 MYANMAR VOWEL SIGN MON II..MYANMAR VOWEL SIGN E ABOVE
+1036..1039 ; valid # 3.0 MYANMAR SIGN ANUSVARA..MYANMAR SIGN VIRAMA
+103A..103F ; valid # 5.1 MYANMAR SIGN ASAT..MYANMAR LETTER GREAT SA
+1040..1049 ; valid # 3.0 MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
+104A..104F ; valid ; ; NV8 # 3.0 MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
+1050..1059 ; valid # 3.0 MYANMAR LETTER SHA..MYANMAR VOWEL SIGN VOCALIC LL
+105A..1099 ; valid # 5.1 MYANMAR LETTER MON NGA..MYANMAR SHAN DIGIT NINE
+109A..109D ; valid # 5.2 MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON AI
+109E..109F ; valid ; ; NV8 # 5.1 MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION
+10A0..10C5 ; disallowed # 1.1 GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE
+10C6 ; disallowed # NA <reserved-10C6>
+10C7 ; mapped ; 2D27 # 6.1 GEORGIAN CAPITAL LETTER YN
+10C8..10CC ; disallowed # NA <reserved-10C8>..<reserved-10CC>
+10CD ; mapped ; 2D2D # 6.1 GEORGIAN CAPITAL LETTER AEN
+10CE..10CF ; disallowed # NA <reserved-10CE>..<reserved-10CF>
+10D0..10F6 ; valid # 1.1 GEORGIAN LETTER AN..GEORGIAN LETTER FI
+10F7..10F8 ; valid # 3.2 GEORGIAN LETTER YN..GEORGIAN LETTER ELIFI
+10F9..10FA ; valid # 4.1 GEORGIAN LETTER TURNED GAN..GEORGIAN LETTER AIN
+10FB ; valid ; ; NV8 # 1.1 GEORGIAN PARAGRAPH SEPARATOR
+10FC ; mapped ; 10DC # 4.1 MODIFIER LETTER GEORGIAN NAR
+10FD..10FF ; valid # 6.1 GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
+1100..1159 ; valid ; ; NV8 # 1.1 HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG YEORINHIEUH
+115A..115E ; valid ; ; NV8 # 5.2 HANGUL CHOSEONG KIYEOK-TIKEUT..HANGUL CHOSEONG TIKEUT-RIEUL
+115F..1160 ; disallowed # 1.1 HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
+1161..11A2 ; valid ; ; NV8 # 1.1 HANGUL JUNGSEONG A..HANGUL JUNGSEONG SSANGARAEA
+11A3..11A7 ; valid ; ; NV8 # 5.2 HANGUL JUNGSEONG A-EU..HANGUL JUNGSEONG O-YAE
+11A8..11F9 ; valid ; ; NV8 # 1.1 HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG YEORINHIEUH
+11FA..11FF ; valid ; ; NV8 # 5.2 HANGUL JONGSEONG KIYEOK-NIEUN..HANGUL JONGSEONG SSANGNIEUN
+1200..1206 ; valid # 3.0 ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE HO
+1207 ; valid # 4.1 ETHIOPIC SYLLABLE HOA
+1208..1246 ; valid # 3.0 ETHIOPIC SYLLABLE LA..ETHIOPIC SYLLABLE QO
+1247 ; valid # 4.1 ETHIOPIC SYLLABLE QOA
+1248 ; valid # 3.0 ETHIOPIC SYLLABLE QWA
+1249 ; disallowed # NA <reserved-1249>
+124A..124D ; valid # 3.0 ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
+124E..124F ; disallowed # NA <reserved-124E>..<reserved-124F>
+1250..1256 ; valid # 3.0 ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
+1257 ; disallowed # NA <reserved-1257>
+1258 ; valid # 3.0 ETHIOPIC SYLLABLE QHWA
+1259 ; disallowed # NA <reserved-1259>
+125A..125D ; valid # 3.0 ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
+125E..125F ; disallowed # NA <reserved-125E>..<reserved-125F>
+1260..1286 ; valid # 3.0 ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XO
+1287 ; valid # 4.1 ETHIOPIC SYLLABLE XOA
+1288 ; valid # 3.0 ETHIOPIC SYLLABLE XWA
+1289 ; disallowed # NA <reserved-1289>
+128A..128D ; valid # 3.0 ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
+128E..128F ; disallowed # NA <reserved-128E>..<reserved-128F>
+1290..12AE ; valid # 3.0 ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KO
+12AF ; valid # 4.1 ETHIOPIC SYLLABLE KOA
+12B0 ; valid # 3.0 ETHIOPIC SYLLABLE KWA
+12B1 ; disallowed # NA <reserved-12B1>
+12B2..12B5 ; valid # 3.0 ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
+12B6..12B7 ; disallowed # NA <reserved-12B6>..<reserved-12B7>
+12B8..12BE ; valid # 3.0 ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
+12BF ; disallowed # NA <reserved-12BF>
+12C0 ; valid # 3.0 ETHIOPIC SYLLABLE KXWA
+12C1 ; disallowed # NA <reserved-12C1>
+12C2..12C5 ; valid # 3.0 ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
+12C6..12C7 ; disallowed # NA <reserved-12C6>..<reserved-12C7>
+12C8..12CE ; valid # 3.0 ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE WO
+12CF ; valid # 4.1 ETHIOPIC SYLLABLE WOA
+12D0..12D6 ; valid # 3.0 ETHIOPIC SYLLABLE PHARYNGEAL A..ETHIOPIC SYLLABLE PHARYNGEAL O
+12D7 ; disallowed # NA <reserved-12D7>
+12D8..12EE ; valid # 3.0 ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE YO
+12EF ; valid # 4.1 ETHIOPIC SYLLABLE YOA
+12F0..130E ; valid # 3.0 ETHIOPIC SYLLABLE DA..ETHIOPIC SYLLABLE GO
+130F ; valid # 4.1 ETHIOPIC SYLLABLE GOA
+1310 ; valid # 3.0 ETHIOPIC SYLLABLE GWA
+1311 ; disallowed # NA <reserved-1311>
+1312..1315 ; valid # 3.0 ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
+1316..1317 ; disallowed # NA <reserved-1316>..<reserved-1317>
+1318..131E ; valid # 3.0 ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE GGO
+131F ; valid # 4.1 ETHIOPIC SYLLABLE GGWAA
+1320..1346 ; valid # 3.0 ETHIOPIC SYLLABLE THA..ETHIOPIC SYLLABLE TZO
+1347 ; valid # 4.1 ETHIOPIC SYLLABLE TZOA
+1348..135A ; valid # 3.0 ETHIOPIC SYLLABLE FA..ETHIOPIC SYLLABLE FYA
+135B..135C ; disallowed # NA <reserved-135B>..<reserved-135C>
+135D..135E ; valid # 6.0 ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING VOWEL LENGTH MARK
+135F ; valid # 4.1 ETHIOPIC COMBINING GEMINATION MARK
+1360 ; valid ; ; NV8 # 4.1 ETHIOPIC SECTION MARK
+1361..137C ; valid ; ; NV8 # 3.0 ETHIOPIC WORDSPACE..ETHIOPIC NUMBER TEN THOUSAND
+137D..137F ; disallowed # NA <reserved-137D>..<reserved-137F>
+1380..138F ; valid # 4.1 ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
+1390..1399 ; valid ; ; NV8 # 4.1 ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
+139A..139F ; disallowed # NA <reserved-139A>..<reserved-139F>
+13A0..13F4 ; valid # 3.0 CHEROKEE LETTER A..CHEROKEE LETTER YV
+13F5 ; valid # 8.0 CHEROKEE LETTER MV
+13F6..13F7 ; disallowed # NA <reserved-13F6>..<reserved-13F7>
+13F8 ; mapped ; 13F0 # 8.0 CHEROKEE SMALL LETTER YE
+13F9 ; mapped ; 13F1 # 8.0 CHEROKEE SMALL LETTER YI
+13FA ; mapped ; 13F2 # 8.0 CHEROKEE SMALL LETTER YO
+13FB ; mapped ; 13F3 # 8.0 CHEROKEE SMALL LETTER YU
+13FC ; mapped ; 13F4 # 8.0 CHEROKEE SMALL LETTER YV
+13FD ; mapped ; 13F5 # 8.0 CHEROKEE SMALL LETTER MV
+13FE..13FF ; disallowed # NA <reserved-13FE>..<reserved-13FF>
+1400 ; valid ; ; NV8 # 5.2 CANADIAN SYLLABICS HYPHEN
+1401..166C ; valid # 3.0 CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
+166D..166E ; valid ; ; NV8 # 3.0 CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLABICS FULL STOP
+166F..1676 ; valid # 3.0 CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS NNGAA
+1677..167F ; valid # 5.2 CANADIAN SYLLABICS WOODS-CREE THWEE..CANADIAN SYLLABICS BLACKFOOT W
+1680 ; disallowed # 3.0 OGHAM SPACE MARK
+1681..169A ; valid # 3.0 OGHAM LETTER BEITH..OGHAM LETTER PEITH
+169B..169C ; valid ; ; NV8 # 3.0 OGHAM FEATHER MARK..OGHAM REVERSED FEATHER MARK
+169D..169F ; disallowed # NA <reserved-169D>..<reserved-169F>
+16A0..16EA ; valid # 3.0 RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
+16EB..16F0 ; valid ; ; NV8 # 3.0 RUNIC SINGLE PUNCTUATION..RUNIC BELGTHOR SYMBOL
+16F1..16F8 ; valid # 7.0 RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
+16F9..16FF ; disallowed # NA <reserved-16F9>..<reserved-16FF>
+1700..170C ; valid # 3.2 TAGALOG LETTER A..TAGALOG LETTER YA
+170D ; valid # 14.0 TAGALOG LETTER RA
+170E..1714 ; valid # 3.2 TAGALOG LETTER LA..TAGALOG SIGN VIRAMA
+1715 ; valid # 14.0 TAGALOG SIGN PAMUDPOD
+1716..171E ; disallowed # NA <reserved-1716>..<reserved-171E>
+171F ; valid # 14.0 TAGALOG LETTER ARCHAIC RA
+1720..1734 ; valid # 3.2 HANUNOO LETTER A..HANUNOO SIGN PAMUDPOD
+1735..1736 ; valid ; ; NV8 # 3.2 PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
+1737..173F ; disallowed # NA <reserved-1737>..<reserved-173F>
+1740..1753 ; valid # 3.2 BUHID LETTER A..BUHID VOWEL SIGN U
+1754..175F ; disallowed # NA <reserved-1754>..<reserved-175F>
+1760..176C ; valid # 3.2 TAGBANWA LETTER A..TAGBANWA LETTER YA
+176D ; disallowed # NA <reserved-176D>
+176E..1770 ; valid # 3.2 TAGBANWA LETTER LA..TAGBANWA LETTER SA
+1771 ; disallowed # NA <reserved-1771>
+1772..1773 ; valid # 3.2 TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
+1774..177F ; disallowed # NA <reserved-1774>..<reserved-177F>
+1780..17B3 ; valid # 3.0 KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
+17B4..17B5 ; disallowed # 3.0 KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+17B6..17D3 ; valid # 3.0 KHMER VOWEL SIGN AA..KHMER SIGN BATHAMASAT
+17D4..17D6 ; valid ; ; NV8 # 3.0 KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
+17D7 ; valid # 3.0 KHMER SIGN LEK TOO
+17D8..17DB ; valid ; ; NV8 # 3.0 KHMER SIGN BEYYAL..KHMER CURRENCY SYMBOL RIEL
+17DC ; valid # 3.0 KHMER SIGN AVAKRAHASANYA
+17DD ; valid # 4.0 KHMER SIGN ATTHACAN
+17DE..17DF ; disallowed # NA <reserved-17DE>..<reserved-17DF>
+17E0..17E9 ; valid # 3.0 KHMER DIGIT ZERO..KHMER DIGIT NINE
+17EA..17EF ; disallowed # NA <reserved-17EA>..<reserved-17EF>
+17F0..17F9 ; valid ; ; NV8 # 4.0 KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
+17FA..17FF ; disallowed # NA <reserved-17FA>..<reserved-17FF>
+1800..1805 ; valid ; ; NV8 # 3.0 MONGOLIAN BIRGA..MONGOLIAN FOUR DOTS
+1806 ; disallowed # 3.0 MONGOLIAN TODO SOFT HYPHEN
+1807..180A ; valid ; ; NV8 # 3.0 MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU
+180B..180D ; ignored # 3.0 MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180E ; disallowed # 3.0 MONGOLIAN VOWEL SEPARATOR
+180F ; ignored # 14.0 MONGOLIAN FREE VARIATION SELECTOR FOUR
+1810..1819 ; valid # 3.0 MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
+181A..181F ; disallowed # NA <reserved-181A>..<reserved-181F>
+1820..1877 ; valid # 3.0 MONGOLIAN LETTER A..MONGOLIAN LETTER MANCHU ZHA
+1878 ; valid # 11.0 MONGOLIAN LETTER CHA WITH TWO DOTS
+1879..187F ; disallowed # NA <reserved-1879>..<reserved-187F>
+1880..18A9 ; valid # 3.0 MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI DAGALGA
+18AA ; valid # 5.1 MONGOLIAN LETTER MANCHU ALI GALI LHA
+18AB..18AF ; disallowed # NA <reserved-18AB>..<reserved-18AF>
+18B0..18F5 ; valid # 5.2 CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
+18F6..18FF ; disallowed # NA <reserved-18F6>..<reserved-18FF>
+1900..191C ; valid # 4.0 LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER HA
+191D..191E ; valid # 7.0 LIMBU LETTER GYAN..LIMBU LETTER TRA
+191F ; disallowed # NA <reserved-191F>
+1920..192B ; valid # 4.0 LIMBU VOWEL SIGN A..LIMBU SUBJOINED LETTER WA
+192C..192F ; disallowed # NA <reserved-192C>..<reserved-192F>
+1930..193B ; valid # 4.0 LIMBU SMALL LETTER KA..LIMBU SIGN SA-I
+193C..193F ; disallowed # NA <reserved-193C>..<reserved-193F>
+1940 ; valid ; ; NV8 # 4.0 LIMBU SIGN LOO
+1941..1943 ; disallowed # NA <reserved-1941>..<reserved-1943>
+1944..1945 ; valid ; ; NV8 # 4.0 LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
+1946..196D ; valid # 4.0 LIMBU DIGIT ZERO..TAI LE LETTER AI
+196E..196F ; disallowed # NA <reserved-196E>..<reserved-196F>
+1970..1974 ; valid # 4.0 TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
+1975..197F ; disallowed # NA <reserved-1975>..<reserved-197F>
+1980..19A9 ; valid # 4.1 NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW XVA
+19AA..19AB ; valid # 5.2 NEW TAI LUE LETTER HIGH SUA..NEW TAI LUE LETTER LOW SUA
+19AC..19AF ; disallowed # NA <reserved-19AC>..<reserved-19AF>
+19B0..19C9 ; valid # 4.1 NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
+19CA..19CF ; disallowed # NA <reserved-19CA>..<reserved-19CF>
+19D0..19D9 ; valid # 4.1 NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
+19DA ; valid ; ; XV8 # 5.2 NEW TAI LUE THAM DIGIT ONE
+19DB..19DD ; disallowed # NA <reserved-19DB>..<reserved-19DD>
+19DE..19DF ; valid ; ; NV8 # 4.1 NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
+19E0..19FF ; valid ; ; NV8 # 4.0 KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC
+1A00..1A1B ; valid # 4.1 BUGINESE LETTER KA..BUGINESE VOWEL SIGN AE
+1A1C..1A1D ; disallowed # NA <reserved-1A1C>..<reserved-1A1D>
+1A1E..1A1F ; valid ; ; NV8 # 4.1 BUGINESE PALLAWA..BUGINESE END OF SECTION
+1A20..1A5E ; valid # 5.2 TAI THAM LETTER HIGH KA..TAI THAM CONSONANT SIGN SA
+1A5F ; disallowed # NA <reserved-1A5F>
+1A60..1A7C ; valid # 5.2 TAI THAM SIGN SAKOT..TAI THAM SIGN KHUEN-LUE KARAN
+1A7D..1A7E ; disallowed # NA <reserved-1A7D>..<reserved-1A7E>
+1A7F..1A89 ; valid # 5.2 TAI THAM COMBINING CRYPTOGRAMMIC DOT..TAI THAM HORA DIGIT NINE
+1A8A..1A8F ; disallowed # NA <reserved-1A8A>..<reserved-1A8F>
+1A90..1A99 ; valid # 5.2 TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
+1A9A..1A9F ; disallowed # NA <reserved-1A9A>..<reserved-1A9F>
+1AA0..1AA6 ; valid ; ; NV8 # 5.2 TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
+1AA7 ; valid # 5.2 TAI THAM SIGN MAI YAMOK
+1AA8..1AAD ; valid ; ; NV8 # 5.2 TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
+1AAE..1AAF ; disallowed # NA <reserved-1AAE>..<reserved-1AAF>
+1AB0..1ABD ; valid # 7.0 COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE ; valid ; ; NV8 # 7.0 COMBINING PARENTHESES OVERLAY
+1ABF..1AC0 ; valid # 13.0 COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW
+1AC1..1ACE ; valid # 14.0 COMBINING LEFT PARENTHESIS ABOVE LEFT..COMBINING LATIN SMALL LETTER INSULAR T
+1ACF..1AFF ; disallowed # NA <reserved-1ACF>..<reserved-1AFF>
+1B00..1B4B ; valid # 5.0 BALINESE SIGN ULU RICEM..BALINESE LETTER ASYURA SASAK
+1B4C ; valid # 14.0 BALINESE LETTER ARCHAIC JNYA
+1B4D..1B4F ; disallowed # NA <reserved-1B4D>..<reserved-1B4F>
+1B50..1B59 ; valid # 5.0 BALINESE DIGIT ZERO..BALINESE DIGIT NINE
+1B5A..1B6A ; valid ; ; NV8 # 5.0 BALINESE PANTI..BALINESE MUSICAL SYMBOL DANG GEDE
+1B6B..1B73 ; valid # 5.0 BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
+1B74..1B7C ; valid ; ; NV8 # 5.0 BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
+1B7D..1B7E ; valid ; ; NV8 # 14.0 BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
+1B7F ; disallowed # NA <reserved-1B7F>
+1B80..1BAA ; valid # 5.1 SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PAMAAEH
+1BAB..1BAD ; valid # 6.1 SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
+1BAE..1BB9 ; valid # 5.1 SUNDANESE LETTER KHA..SUNDANESE DIGIT NINE
+1BBA..1BBF ; valid # 6.1 SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M
+1BC0..1BF3 ; valid # 6.0 BATAK LETTER A..BATAK PANONGONAN
+1BF4..1BFB ; disallowed # NA <reserved-1BF4>..<reserved-1BFB>
+1BFC..1BFF ; valid ; ; NV8 # 6.0 BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
+1C00..1C37 ; valid # 5.1 LEPCHA LETTER KA..LEPCHA SIGN NUKTA
+1C38..1C3A ; disallowed # NA <reserved-1C38>..<reserved-1C3A>
+1C3B..1C3F ; valid ; ; NV8 # 5.1 LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
+1C40..1C49 ; valid # 5.1 LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
+1C4A..1C4C ; disallowed # NA <reserved-1C4A>..<reserved-1C4C>
+1C4D..1C7D ; valid # 5.1 LEPCHA LETTER TTA..OL CHIKI AHAD
+1C7E..1C7F ; valid ; ; NV8 # 5.1 OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
+1C80 ; mapped ; 0432 # 9.0 CYRILLIC SMALL LETTER ROUNDED VE
+1C81 ; mapped ; 0434 # 9.0 CYRILLIC SMALL LETTER LONG-LEGGED DE
+1C82 ; mapped ; 043E # 9.0 CYRILLIC SMALL LETTER NARROW O
+1C83 ; mapped ; 0441 # 9.0 CYRILLIC SMALL LETTER WIDE ES
+1C84..1C85 ; mapped ; 0442 # 9.0 CYRILLIC SMALL LETTER TALL TE..CYRILLIC SMALL LETTER THREE-LEGGED TE
+1C86 ; mapped ; 044A # 9.0 CYRILLIC SMALL LETTER TALL HARD SIGN
+1C87 ; mapped ; 0463 # 9.0 CYRILLIC SMALL LETTER TALL YAT
+1C88 ; mapped ; A64B # 9.0 CYRILLIC SMALL LETTER UNBLENDED UK
+1C89..1C8F ; disallowed # NA <reserved-1C89>..<reserved-1C8F>
+1C90 ; mapped ; 10D0 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER AN
+1C91 ; mapped ; 10D1 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER BAN
+1C92 ; mapped ; 10D2 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER GAN
+1C93 ; mapped ; 10D3 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER DON
+1C94 ; mapped ; 10D4 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER EN
+1C95 ; mapped ; 10D5 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER VIN
+1C96 ; mapped ; 10D6 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER ZEN
+1C97 ; mapped ; 10D7 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER TAN
+1C98 ; mapped ; 10D8 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER IN
+1C99 ; mapped ; 10D9 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER KAN
+1C9A ; mapped ; 10DA # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER LAS
+1C9B ; mapped ; 10DB # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER MAN
+1C9C ; mapped ; 10DC # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER NAR
+1C9D ; mapped ; 10DD # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER ON
+1C9E ; mapped ; 10DE # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER PAR
+1C9F ; mapped ; 10DF # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER ZHAR
+1CA0 ; mapped ; 10E0 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER RAE
+1CA1 ; mapped ; 10E1 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER SAN
+1CA2 ; mapped ; 10E2 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER TAR
+1CA3 ; mapped ; 10E3 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER UN
+1CA4 ; mapped ; 10E4 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER PHAR
+1CA5 ; mapped ; 10E5 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER KHAR
+1CA6 ; mapped ; 10E6 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER GHAN
+1CA7 ; mapped ; 10E7 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER QAR
+1CA8 ; mapped ; 10E8 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER SHIN
+1CA9 ; mapped ; 10E9 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER CHIN
+1CAA ; mapped ; 10EA # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER CAN
+1CAB ; mapped ; 10EB # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER JIL
+1CAC ; mapped ; 10EC # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER CIL
+1CAD ; mapped ; 10ED # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER CHAR
+1CAE ; mapped ; 10EE # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER XAN
+1CAF ; mapped ; 10EF # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER JHAN
+1CB0 ; mapped ; 10F0 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HAE
+1CB1 ; mapped ; 10F1 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HE
+1CB2 ; mapped ; 10F2 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HIE
+1CB3 ; mapped ; 10F3 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER WE
+1CB4 ; mapped ; 10F4 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HAR
+1CB5 ; mapped ; 10F5 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HOE
+1CB6 ; mapped ; 10F6 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER FI
+1CB7 ; mapped ; 10F7 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER YN
+1CB8 ; mapped ; 10F8 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER ELIFI
+1CB9 ; mapped ; 10F9 # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN
+1CBA ; mapped ; 10FA # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER AIN
+1CBB..1CBC ; disallowed # NA <reserved-1CBB>..<reserved-1CBC>
+1CBD ; mapped ; 10FD # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER AEN
+1CBE ; mapped ; 10FE # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN
+1CBF ; mapped ; 10FF # 11.0 GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
+1CC0..1CC7 ; valid ; ; NV8 # 6.1 SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA
+1CC8..1CCF ; disallowed # NA <reserved-1CC8>..<reserved-1CCF>
+1CD0..1CD2 ; valid # 5.2 VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
+1CD3 ; valid ; ; NV8 # 5.2 VEDIC SIGN NIHSHVASA
+1CD4..1CF2 ; valid # 5.2 VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC SIGN ARDHAVISARGA
+1CF3..1CF6 ; valid # 6.1 VEDIC SIGN ROTATED ARDHAVISARGA..VEDIC SIGN UPADHMANIYA
+1CF7 ; valid # 10.0 VEDIC SIGN ATIKRAMA
+1CF8..1CF9 ; valid # 7.0 VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
+1CFA ; valid # 12.0 VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA
+1CFB..1CFF ; disallowed # NA <reserved-1CFB>..<reserved-1CFF>
+1D00..1D2B ; valid # 4.0 LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
+1D2C ; mapped ; 0061 # 4.0 MODIFIER LETTER CAPITAL A
+1D2D ; mapped ; 00E6 # 4.0 MODIFIER LETTER CAPITAL AE
+1D2E ; mapped ; 0062 # 4.0 MODIFIER LETTER CAPITAL B
+1D2F ; valid # 4.0 MODIFIER LETTER CAPITAL BARRED B
+1D30 ; mapped ; 0064 # 4.0 MODIFIER LETTER CAPITAL D
+1D31 ; mapped ; 0065 # 4.0 MODIFIER LETTER CAPITAL E
+1D32 ; mapped ; 01DD # 4.0 MODIFIER LETTER CAPITAL REVERSED E
+1D33 ; mapped ; 0067 # 4.0 MODIFIER LETTER CAPITAL G
+1D34 ; mapped ; 0068 # 4.0 MODIFIER LETTER CAPITAL H
+1D35 ; mapped ; 0069 # 4.0 MODIFIER LETTER CAPITAL I
+1D36 ; mapped ; 006A # 4.0 MODIFIER LETTER CAPITAL J
+1D37 ; mapped ; 006B # 4.0 MODIFIER LETTER CAPITAL K
+1D38 ; mapped ; 006C # 4.0 MODIFIER LETTER CAPITAL L
+1D39 ; mapped ; 006D # 4.0 MODIFIER LETTER CAPITAL M
+1D3A ; mapped ; 006E # 4.0 MODIFIER LETTER CAPITAL N
+1D3B ; valid # 4.0 MODIFIER LETTER CAPITAL REVERSED N
+1D3C ; mapped ; 006F # 4.0 MODIFIER LETTER CAPITAL O
+1D3D ; mapped ; 0223 # 4.0 MODIFIER LETTER CAPITAL OU
+1D3E ; mapped ; 0070 # 4.0 MODIFIER LETTER CAPITAL P
+1D3F ; mapped ; 0072 # 4.0 MODIFIER LETTER CAPITAL R
+1D40 ; mapped ; 0074 # 4.0 MODIFIER LETTER CAPITAL T
+1D41 ; mapped ; 0075 # 4.0 MODIFIER LETTER CAPITAL U
+1D42 ; mapped ; 0077 # 4.0 MODIFIER LETTER CAPITAL W
+1D43 ; mapped ; 0061 # 4.0 MODIFIER LETTER SMALL A
+1D44 ; mapped ; 0250 # 4.0 MODIFIER LETTER SMALL TURNED A
+1D45 ; mapped ; 0251 # 4.0 MODIFIER LETTER SMALL ALPHA
+1D46 ; mapped ; 1D02 # 4.0 MODIFIER LETTER SMALL TURNED AE
+1D47 ; mapped ; 0062 # 4.0 MODIFIER LETTER SMALL B
+1D48 ; mapped ; 0064 # 4.0 MODIFIER LETTER SMALL D
+1D49 ; mapped ; 0065 # 4.0 MODIFIER LETTER SMALL E
+1D4A ; mapped ; 0259 # 4.0 MODIFIER LETTER SMALL SCHWA
+1D4B ; mapped ; 025B # 4.0 MODIFIER LETTER SMALL OPEN E
+1D4C ; mapped ; 025C # 4.0 MODIFIER LETTER SMALL TURNED OPEN E
+1D4D ; mapped ; 0067 # 4.0 MODIFIER LETTER SMALL G
+1D4E ; valid # 4.0 MODIFIER LETTER SMALL TURNED I
+1D4F ; mapped ; 006B # 4.0 MODIFIER LETTER SMALL K
+1D50 ; mapped ; 006D # 4.0 MODIFIER LETTER SMALL M
+1D51 ; mapped ; 014B # 4.0 MODIFIER LETTER SMALL ENG
+1D52 ; mapped ; 006F # 4.0 MODIFIER LETTER SMALL O
+1D53 ; mapped ; 0254 # 4.0 MODIFIER LETTER SMALL OPEN O
+1D54 ; mapped ; 1D16 # 4.0 MODIFIER LETTER SMALL TOP HALF O
+1D55 ; mapped ; 1D17 # 4.0 MODIFIER LETTER SMALL BOTTOM HALF O
+1D56 ; mapped ; 0070 # 4.0 MODIFIER LETTER SMALL P
+1D57 ; mapped ; 0074 # 4.0 MODIFIER LETTER SMALL T
+1D58 ; mapped ; 0075 # 4.0 MODIFIER LETTER SMALL U
+1D59 ; mapped ; 1D1D # 4.0 MODIFIER LETTER SMALL SIDEWAYS U
+1D5A ; mapped ; 026F # 4.0 MODIFIER LETTER SMALL TURNED M
+1D5B ; mapped ; 0076 # 4.0 MODIFIER LETTER SMALL V
+1D5C ; mapped ; 1D25 # 4.0 MODIFIER LETTER SMALL AIN
+1D5D ; mapped ; 03B2 # 4.0 MODIFIER LETTER SMALL BETA
+1D5E ; mapped ; 03B3 # 4.0 MODIFIER LETTER SMALL GREEK GAMMA
+1D5F ; mapped ; 03B4 # 4.0 MODIFIER LETTER SMALL DELTA
+1D60 ; mapped ; 03C6 # 4.0 MODIFIER LETTER SMALL GREEK PHI
+1D61 ; mapped ; 03C7 # 4.0 MODIFIER LETTER SMALL CHI
+1D62 ; mapped ; 0069 # 4.0 LATIN SUBSCRIPT SMALL LETTER I
+1D63 ; mapped ; 0072 # 4.0 LATIN SUBSCRIPT SMALL LETTER R
+1D64 ; mapped ; 0075 # 4.0 LATIN SUBSCRIPT SMALL LETTER U
+1D65 ; mapped ; 0076 # 4.0 LATIN SUBSCRIPT SMALL LETTER V
+1D66 ; mapped ; 03B2 # 4.0 GREEK SUBSCRIPT SMALL LETTER BETA
+1D67 ; mapped ; 03B3 # 4.0 GREEK SUBSCRIPT SMALL LETTER GAMMA
+1D68 ; mapped ; 03C1 # 4.0 GREEK SUBSCRIPT SMALL LETTER RHO
+1D69 ; mapped ; 03C6 # 4.0 GREEK SUBSCRIPT SMALL LETTER PHI
+1D6A ; mapped ; 03C7 # 4.0 GREEK SUBSCRIPT SMALL LETTER CHI
+1D6B ; valid # 4.0 LATIN SMALL LETTER UE
+1D6C..1D77 ; valid # 4.1 LATIN SMALL LETTER B WITH MIDDLE TILDE..LATIN SMALL LETTER TURNED G
+1D78 ; mapped ; 043D # 4.1 MODIFIER LETTER CYRILLIC EN
+1D79..1D9A ; valid # 4.1 LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
+1D9B ; mapped ; 0252 # 4.1 MODIFIER LETTER SMALL TURNED ALPHA
+1D9C ; mapped ; 0063 # 4.1 MODIFIER LETTER SMALL C
+1D9D ; mapped ; 0255 # 4.1 MODIFIER LETTER SMALL C WITH CURL
+1D9E ; mapped ; 00F0 # 4.1 MODIFIER LETTER SMALL ETH
+1D9F ; mapped ; 025C # 4.1 MODIFIER LETTER SMALL REVERSED OPEN E
+1DA0 ; mapped ; 0066 # 4.1 MODIFIER LETTER SMALL F
+1DA1 ; mapped ; 025F # 4.1 MODIFIER LETTER SMALL DOTLESS J WITH STROKE
+1DA2 ; mapped ; 0261 # 4.1 MODIFIER LETTER SMALL SCRIPT G
+1DA3 ; mapped ; 0265 # 4.1 MODIFIER LETTER SMALL TURNED H
+1DA4 ; mapped ; 0268 # 4.1 MODIFIER LETTER SMALL I WITH STROKE
+1DA5 ; mapped ; 0269 # 4.1 MODIFIER LETTER SMALL IOTA
+1DA6 ; mapped ; 026A # 4.1 MODIFIER LETTER SMALL CAPITAL I
+1DA7 ; mapped ; 1D7B # 4.1 MODIFIER LETTER SMALL CAPITAL I WITH STROKE
+1DA8 ; mapped ; 029D # 4.1 MODIFIER LETTER SMALL J WITH CROSSED-TAIL
+1DA9 ; mapped ; 026D # 4.1 MODIFIER LETTER SMALL L WITH RETROFLEX HOOK
+1DAA ; mapped ; 1D85 # 4.1 MODIFIER LETTER SMALL L WITH PALATAL HOOK
+1DAB ; mapped ; 029F # 4.1 MODIFIER LETTER SMALL CAPITAL L
+1DAC ; mapped ; 0271 # 4.1 MODIFIER LETTER SMALL M WITH HOOK
+1DAD ; mapped ; 0270 # 4.1 MODIFIER LETTER SMALL TURNED M WITH LONG LEG
+1DAE ; mapped ; 0272 # 4.1 MODIFIER LETTER SMALL N WITH LEFT HOOK
+1DAF ; mapped ; 0273 # 4.1 MODIFIER LETTER SMALL N WITH RETROFLEX HOOK
+1DB0 ; mapped ; 0274 # 4.1 MODIFIER LETTER SMALL CAPITAL N
+1DB1 ; mapped ; 0275 # 4.1 MODIFIER LETTER SMALL BARRED O
+1DB2 ; mapped ; 0278 # 4.1 MODIFIER LETTER SMALL PHI
+1DB3 ; mapped ; 0282 # 4.1 MODIFIER LETTER SMALL S WITH HOOK
+1DB4 ; mapped ; 0283 # 4.1 MODIFIER LETTER SMALL ESH
+1DB5 ; mapped ; 01AB # 4.1 MODIFIER LETTER SMALL T WITH PALATAL HOOK
+1DB6 ; mapped ; 0289 # 4.1 MODIFIER LETTER SMALL U BAR
+1DB7 ; mapped ; 028A # 4.1 MODIFIER LETTER SMALL UPSILON
+1DB8 ; mapped ; 1D1C # 4.1 MODIFIER LETTER SMALL CAPITAL U
+1DB9 ; mapped ; 028B # 4.1 MODIFIER LETTER SMALL V WITH HOOK
+1DBA ; mapped ; 028C # 4.1 MODIFIER LETTER SMALL TURNED V
+1DBB ; mapped ; 007A # 4.1 MODIFIER LETTER SMALL Z
+1DBC ; mapped ; 0290 # 4.1 MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK
+1DBD ; mapped ; 0291 # 4.1 MODIFIER LETTER SMALL Z WITH CURL
+1DBE ; mapped ; 0292 # 4.1 MODIFIER LETTER SMALL EZH
+1DBF ; mapped ; 03B8 # 4.1 MODIFIER LETTER SMALL THETA
+1DC0..1DC3 ; valid # 4.1 COMBINING DOTTED GRAVE ACCENT..COMBINING SUSPENSION MARK
+1DC4..1DCA ; valid # 5.0 COMBINING MACRON-ACUTE..COMBINING LATIN SMALL LETTER R BELOW
+1DCB..1DE6 ; valid # 5.1 COMBINING BREVE-MACRON..COMBINING LATIN SMALL LETTER Z
+1DE7..1DF5 ; valid # 7.0 COMBINING LATIN SMALL LETTER ALPHA..COMBINING UP TACK ABOVE
+1DF6..1DF9 ; valid # 10.0 COMBINING KAVYKA ABOVE RIGHT..COMBINING WIDE INVERTED BRIDGE BELOW
+1DFA ; valid # 14.0 COMBINING DOT BELOW LEFT
+1DFB ; valid # 9.0 COMBINING DELETION MARK
+1DFC ; valid # 6.0 COMBINING DOUBLE INVERTED BREVE BELOW
+1DFD ; valid # 5.2 COMBINING ALMOST EQUAL TO BELOW
+1DFE..1DFF ; valid # 5.0 COMBINING LEFT ARROWHEAD ABOVE..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1E00 ; mapped ; 1E01 # 1.1 LATIN CAPITAL LETTER A WITH RING BELOW
+1E01 ; valid # 1.1 LATIN SMALL LETTER A WITH RING BELOW
+1E02 ; mapped ; 1E03 # 1.1 LATIN CAPITAL LETTER B WITH DOT ABOVE
+1E03 ; valid # 1.1 LATIN SMALL LETTER B WITH DOT ABOVE
+1E04 ; mapped ; 1E05 # 1.1 LATIN CAPITAL LETTER B WITH DOT BELOW
+1E05 ; valid # 1.1 LATIN SMALL LETTER B WITH DOT BELOW
+1E06 ; mapped ; 1E07 # 1.1 LATIN CAPITAL LETTER B WITH LINE BELOW
+1E07 ; valid # 1.1 LATIN SMALL LETTER B WITH LINE BELOW
+1E08 ; mapped ; 1E09 # 1.1 LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
+1E09 ; valid # 1.1 LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
+1E0A ; mapped ; 1E0B # 1.1 LATIN CAPITAL LETTER D WITH DOT ABOVE
+1E0B ; valid # 1.1 LATIN SMALL LETTER D WITH DOT ABOVE
+1E0C ; mapped ; 1E0D # 1.1 LATIN CAPITAL LETTER D WITH DOT BELOW
+1E0D ; valid # 1.1 LATIN SMALL LETTER D WITH DOT BELOW
+1E0E ; mapped ; 1E0F # 1.1 LATIN CAPITAL LETTER D WITH LINE BELOW
+1E0F ; valid # 1.1 LATIN SMALL LETTER D WITH LINE BELOW
+1E10 ; mapped ; 1E11 # 1.1 LATIN CAPITAL LETTER D WITH CEDILLA
+1E11 ; valid # 1.1 LATIN SMALL LETTER D WITH CEDILLA
+1E12 ; mapped ; 1E13 # 1.1 LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
+1E13 ; valid # 1.1 LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
+1E14 ; mapped ; 1E15 # 1.1 LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
+1E15 ; valid # 1.1 LATIN SMALL LETTER E WITH MACRON AND GRAVE
+1E16 ; mapped ; 1E17 # 1.1 LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
+1E17 ; valid # 1.1 LATIN SMALL LETTER E WITH MACRON AND ACUTE
+1E18 ; mapped ; 1E19 # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
+1E19 ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
+1E1A ; mapped ; 1E1B # 1.1 LATIN CAPITAL LETTER E WITH TILDE BELOW
+1E1B ; valid # 1.1 LATIN SMALL LETTER E WITH TILDE BELOW
+1E1C ; mapped ; 1E1D # 1.1 LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
+1E1D ; valid # 1.1 LATIN SMALL LETTER E WITH CEDILLA AND BREVE
+1E1E ; mapped ; 1E1F # 1.1 LATIN CAPITAL LETTER F WITH DOT ABOVE
+1E1F ; valid # 1.1 LATIN SMALL LETTER F WITH DOT ABOVE
+1E20 ; mapped ; 1E21 # 1.1 LATIN CAPITAL LETTER G WITH MACRON
+1E21 ; valid # 1.1 LATIN SMALL LETTER G WITH MACRON
+1E22 ; mapped ; 1E23 # 1.1 LATIN CAPITAL LETTER H WITH DOT ABOVE
+1E23 ; valid # 1.1 LATIN SMALL LETTER H WITH DOT ABOVE
+1E24 ; mapped ; 1E25 # 1.1 LATIN CAPITAL LETTER H WITH DOT BELOW
+1E25 ; valid # 1.1 LATIN SMALL LETTER H WITH DOT BELOW
+1E26 ; mapped ; 1E27 # 1.1 LATIN CAPITAL LETTER H WITH DIAERESIS
+1E27 ; valid # 1.1 LATIN SMALL LETTER H WITH DIAERESIS
+1E28 ; mapped ; 1E29 # 1.1 LATIN CAPITAL LETTER H WITH CEDILLA
+1E29 ; valid # 1.1 LATIN SMALL LETTER H WITH CEDILLA
+1E2A ; mapped ; 1E2B # 1.1 LATIN CAPITAL LETTER H WITH BREVE BELOW
+1E2B ; valid # 1.1 LATIN SMALL LETTER H WITH BREVE BELOW
+1E2C ; mapped ; 1E2D # 1.1 LATIN CAPITAL LETTER I WITH TILDE BELOW
+1E2D ; valid # 1.1 LATIN SMALL LETTER I WITH TILDE BELOW
+1E2E ; mapped ; 1E2F # 1.1 LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
+1E2F ; valid # 1.1 LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE
+1E30 ; mapped ; 1E31 # 1.1 LATIN CAPITAL LETTER K WITH ACUTE
+1E31 ; valid # 1.1 LATIN SMALL LETTER K WITH ACUTE
+1E32 ; mapped ; 1E33 # 1.1 LATIN CAPITAL LETTER K WITH DOT BELOW
+1E33 ; valid # 1.1 LATIN SMALL LETTER K WITH DOT BELOW
+1E34 ; mapped ; 1E35 # 1.1 LATIN CAPITAL LETTER K WITH LINE BELOW
+1E35 ; valid # 1.1 LATIN SMALL LETTER K WITH LINE BELOW
+1E36 ; mapped ; 1E37 # 1.1 LATIN CAPITAL LETTER L WITH DOT BELOW
+1E37 ; valid # 1.1 LATIN SMALL LETTER L WITH DOT BELOW
+1E38 ; mapped ; 1E39 # 1.1 LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
+1E39 ; valid # 1.1 LATIN SMALL LETTER L WITH DOT BELOW AND MACRON
+1E3A ; mapped ; 1E3B # 1.1 LATIN CAPITAL LETTER L WITH LINE BELOW
+1E3B ; valid # 1.1 LATIN SMALL LETTER L WITH LINE BELOW
+1E3C ; mapped ; 1E3D # 1.1 LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
+1E3D ; valid # 1.1 LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
+1E3E ; mapped ; 1E3F # 1.1 LATIN CAPITAL LETTER M WITH ACUTE
+1E3F ; valid # 1.1 LATIN SMALL LETTER M WITH ACUTE
+1E40 ; mapped ; 1E41 # 1.1 LATIN CAPITAL LETTER M WITH DOT ABOVE
+1E41 ; valid # 1.1 LATIN SMALL LETTER M WITH DOT ABOVE
+1E42 ; mapped ; 1E43 # 1.1 LATIN CAPITAL LETTER M WITH DOT BELOW
+1E43 ; valid # 1.1 LATIN SMALL LETTER M WITH DOT BELOW
+1E44 ; mapped ; 1E45 # 1.1 LATIN CAPITAL LETTER N WITH DOT ABOVE
+1E45 ; valid # 1.1 LATIN SMALL LETTER N WITH DOT ABOVE
+1E46 ; mapped ; 1E47 # 1.1 LATIN CAPITAL LETTER N WITH DOT BELOW
+1E47 ; valid # 1.1 LATIN SMALL LETTER N WITH DOT BELOW
+1E48 ; mapped ; 1E49 # 1.1 LATIN CAPITAL LETTER N WITH LINE BELOW
+1E49 ; valid # 1.1 LATIN SMALL LETTER N WITH LINE BELOW
+1E4A ; mapped ; 1E4B # 1.1 LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
+1E4B ; valid # 1.1 LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
+1E4C ; mapped ; 1E4D # 1.1 LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
+1E4D ; valid # 1.1 LATIN SMALL LETTER O WITH TILDE AND ACUTE
+1E4E ; mapped ; 1E4F # 1.1 LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
+1E4F ; valid # 1.1 LATIN SMALL LETTER O WITH TILDE AND DIAERESIS
+1E50 ; mapped ; 1E51 # 1.1 LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
+1E51 ; valid # 1.1 LATIN SMALL LETTER O WITH MACRON AND GRAVE
+1E52 ; mapped ; 1E53 # 1.1 LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
+1E53 ; valid # 1.1 LATIN SMALL LETTER O WITH MACRON AND ACUTE
+1E54 ; mapped ; 1E55 # 1.1 LATIN CAPITAL LETTER P WITH ACUTE
+1E55 ; valid # 1.1 LATIN SMALL LETTER P WITH ACUTE
+1E56 ; mapped ; 1E57 # 1.1 LATIN CAPITAL LETTER P WITH DOT ABOVE
+1E57 ; valid # 1.1 LATIN SMALL LETTER P WITH DOT ABOVE
+1E58 ; mapped ; 1E59 # 1.1 LATIN CAPITAL LETTER R WITH DOT ABOVE
+1E59 ; valid # 1.1 LATIN SMALL LETTER R WITH DOT ABOVE
+1E5A ; mapped ; 1E5B # 1.1 LATIN CAPITAL LETTER R WITH DOT BELOW
+1E5B ; valid # 1.1 LATIN SMALL LETTER R WITH DOT BELOW
+1E5C ; mapped ; 1E5D # 1.1 LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
+1E5D ; valid # 1.1 LATIN SMALL LETTER R WITH DOT BELOW AND MACRON
+1E5E ; mapped ; 1E5F # 1.1 LATIN CAPITAL LETTER R WITH LINE BELOW
+1E5F ; valid # 1.1 LATIN SMALL LETTER R WITH LINE BELOW
+1E60 ; mapped ; 1E61 # 1.1 LATIN CAPITAL LETTER S WITH DOT ABOVE
+1E61 ; valid # 1.1 LATIN SMALL LETTER S WITH DOT ABOVE
+1E62 ; mapped ; 1E63 # 1.1 LATIN CAPITAL LETTER S WITH DOT BELOW
+1E63 ; valid # 1.1 LATIN SMALL LETTER S WITH DOT BELOW
+1E64 ; mapped ; 1E65 # 1.1 LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
+1E65 ; valid # 1.1 LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE
+1E66 ; mapped ; 1E67 # 1.1 LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
+1E67 ; valid # 1.1 LATIN SMALL LETTER S WITH CARON AND DOT ABOVE
+1E68 ; mapped ; 1E69 # 1.1 LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E69 ; valid # 1.1 LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E6A ; mapped ; 1E6B # 1.1 LATIN CAPITAL LETTER T WITH DOT ABOVE
+1E6B ; valid # 1.1 LATIN SMALL LETTER T WITH DOT ABOVE
+1E6C ; mapped ; 1E6D # 1.1 LATIN CAPITAL LETTER T WITH DOT BELOW
+1E6D ; valid # 1.1 LATIN SMALL LETTER T WITH DOT BELOW
+1E6E ; mapped ; 1E6F # 1.1 LATIN CAPITAL LETTER T WITH LINE BELOW
+1E6F ; valid # 1.1 LATIN SMALL LETTER T WITH LINE BELOW
+1E70 ; mapped ; 1E71 # 1.1 LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
+1E71 ; valid # 1.1 LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
+1E72 ; mapped ; 1E73 # 1.1 LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
+1E73 ; valid # 1.1 LATIN SMALL LETTER U WITH DIAERESIS BELOW
+1E74 ; mapped ; 1E75 # 1.1 LATIN CAPITAL LETTER U WITH TILDE BELOW
+1E75 ; valid # 1.1 LATIN SMALL LETTER U WITH TILDE BELOW
+1E76 ; mapped ; 1E77 # 1.1 LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
+1E77 ; valid # 1.1 LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
+1E78 ; mapped ; 1E79 # 1.1 LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
+1E79 ; valid # 1.1 LATIN SMALL LETTER U WITH TILDE AND ACUTE
+1E7A ; mapped ; 1E7B # 1.1 LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
+1E7B ; valid # 1.1 LATIN SMALL LETTER U WITH MACRON AND DIAERESIS
+1E7C ; mapped ; 1E7D # 1.1 LATIN CAPITAL LETTER V WITH TILDE
+1E7D ; valid # 1.1 LATIN SMALL LETTER V WITH TILDE
+1E7E ; mapped ; 1E7F # 1.1 LATIN CAPITAL LETTER V WITH DOT BELOW
+1E7F ; valid # 1.1 LATIN SMALL LETTER V WITH DOT BELOW
+1E80 ; mapped ; 1E81 # 1.1 LATIN CAPITAL LETTER W WITH GRAVE
+1E81 ; valid # 1.1 LATIN SMALL LETTER W WITH GRAVE
+1E82 ; mapped ; 1E83 # 1.1 LATIN CAPITAL LETTER W WITH ACUTE
+1E83 ; valid # 1.1 LATIN SMALL LETTER W WITH ACUTE
+1E84 ; mapped ; 1E85 # 1.1 LATIN CAPITAL LETTER W WITH DIAERESIS
+1E85 ; valid # 1.1 LATIN SMALL LETTER W WITH DIAERESIS
+1E86 ; mapped ; 1E87 # 1.1 LATIN CAPITAL LETTER W WITH DOT ABOVE
+1E87 ; valid # 1.1 LATIN SMALL LETTER W WITH DOT ABOVE
+1E88 ; mapped ; 1E89 # 1.1 LATIN CAPITAL LETTER W WITH DOT BELOW
+1E89 ; valid # 1.1 LATIN SMALL LETTER W WITH DOT BELOW
+1E8A ; mapped ; 1E8B # 1.1 LATIN CAPITAL LETTER X WITH DOT ABOVE
+1E8B ; valid # 1.1 LATIN SMALL LETTER X WITH DOT ABOVE
+1E8C ; mapped ; 1E8D # 1.1 LATIN CAPITAL LETTER X WITH DIAERESIS
+1E8D ; valid # 1.1 LATIN SMALL LETTER X WITH DIAERESIS
+1E8E ; mapped ; 1E8F # 1.1 LATIN CAPITAL LETTER Y WITH DOT ABOVE
+1E8F ; valid # 1.1 LATIN SMALL LETTER Y WITH DOT ABOVE
+1E90 ; mapped ; 1E91 # 1.1 LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
+1E91 ; valid # 1.1 LATIN SMALL LETTER Z WITH CIRCUMFLEX
+1E92 ; mapped ; 1E93 # 1.1 LATIN CAPITAL LETTER Z WITH DOT BELOW
+1E93 ; valid # 1.1 LATIN SMALL LETTER Z WITH DOT BELOW
+1E94 ; mapped ; 1E95 # 1.1 LATIN CAPITAL LETTER Z WITH LINE BELOW
+1E95..1E99 ; valid # 1.1 LATIN SMALL LETTER Z WITH LINE BELOW..LATIN SMALL LETTER Y WITH RING ABOVE
+1E9A ; mapped ; 0061 02BE # 1.1 LATIN SMALL LETTER A WITH RIGHT HALF RING
+1E9B ; mapped ; 1E61 # 2.0 LATIN SMALL LETTER LONG S WITH DOT ABOVE
+1E9C..1E9D ; valid # 5.1 LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE..LATIN SMALL LETTER LONG S WITH HIGH STROKE
+1E9E ; mapped ; 0073 0073 # 5.1 LATIN CAPITAL LETTER SHARP S
+1E9F ; valid # 5.1 LATIN SMALL LETTER DELTA
+1EA0 ; mapped ; 1EA1 # 1.1 LATIN CAPITAL LETTER A WITH DOT BELOW
+1EA1 ; valid # 1.1 LATIN SMALL LETTER A WITH DOT BELOW
+1EA2 ; mapped ; 1EA3 # 1.1 LATIN CAPITAL LETTER A WITH HOOK ABOVE
+1EA3 ; valid # 1.1 LATIN SMALL LETTER A WITH HOOK ABOVE
+1EA4 ; mapped ; 1EA5 # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA5 ; valid # 1.1 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA6 ; mapped ; 1EA7 # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA7 ; valid # 1.1 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA8 ; mapped ; 1EA9 # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EA9 ; valid # 1.1 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EAA ; mapped ; 1EAB # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAB ; valid # 1.1 LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAC ; mapped ; 1EAD # 1.1 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAD ; valid # 1.1 LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAE ; mapped ; 1EAF # 1.1 LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+1EAF ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE AND ACUTE
+1EB0 ; mapped ; 1EB1 # 1.1 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+1EB1 ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE AND GRAVE
+1EB2 ; mapped ; 1EB3 # 1.1 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+1EB3 ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+1EB4 ; mapped ; 1EB5 # 1.1 LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+1EB5 ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE AND TILDE
+1EB6 ; mapped ; 1EB7 # 1.1 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+1EB7 ; valid # 1.1 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+1EB8 ; mapped ; 1EB9 # 1.1 LATIN CAPITAL LETTER E WITH DOT BELOW
+1EB9 ; valid # 1.1 LATIN SMALL LETTER E WITH DOT BELOW
+1EBA ; mapped ; 1EBB # 1.1 LATIN CAPITAL LETTER E WITH HOOK ABOVE
+1EBB ; valid # 1.1 LATIN SMALL LETTER E WITH HOOK ABOVE
+1EBC ; mapped ; 1EBD # 1.1 LATIN CAPITAL LETTER E WITH TILDE
+1EBD ; valid # 1.1 LATIN SMALL LETTER E WITH TILDE
+1EBE ; mapped ; 1EBF # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EBF ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EC0 ; mapped ; 1EC1 # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC1 ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC2 ; mapped ; 1EC3 # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC3 ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC4 ; mapped ; 1EC5 # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC5 ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC6 ; mapped ; 1EC7 # 1.1 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC7 ; valid # 1.1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC8 ; mapped ; 1EC9 # 1.1 LATIN CAPITAL LETTER I WITH HOOK ABOVE
+1EC9 ; valid # 1.1 LATIN SMALL LETTER I WITH HOOK ABOVE
+1ECA ; mapped ; 1ECB # 1.1 LATIN CAPITAL LETTER I WITH DOT BELOW
+1ECB ; valid # 1.1 LATIN SMALL LETTER I WITH DOT BELOW
+1ECC ; mapped ; 1ECD # 1.1 LATIN CAPITAL LETTER O WITH DOT BELOW
+1ECD ; valid # 1.1 LATIN SMALL LETTER O WITH DOT BELOW
+1ECE ; mapped ; 1ECF # 1.1 LATIN CAPITAL LETTER O WITH HOOK ABOVE
+1ECF ; valid # 1.1 LATIN SMALL LETTER O WITH HOOK ABOVE
+1ED0 ; mapped ; 1ED1 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED1 ; valid # 1.1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED2 ; mapped ; 1ED3 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED3 ; valid # 1.1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED4 ; mapped ; 1ED5 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED5 ; valid # 1.1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED6 ; mapped ; 1ED7 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED7 ; valid # 1.1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED8 ; mapped ; 1ED9 # 1.1 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1ED9 ; valid # 1.1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1EDA ; mapped ; 1EDB # 1.1 LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+1EDB ; valid # 1.1 LATIN SMALL LETTER O WITH HORN AND ACUTE
+1EDC ; mapped ; 1EDD # 1.1 LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+1EDD ; valid # 1.1 LATIN SMALL LETTER O WITH HORN AND GRAVE
+1EDE ; mapped ; 1EDF # 1.1 LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+1EDF ; valid # 1.1 LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+1EE0 ; mapped ; 1EE1 # 1.1 LATIN CAPITAL LETTER O WITH HORN AND TILDE
+1EE1 ; valid # 1.1 LATIN SMALL LETTER O WITH HORN AND TILDE
+1EE2 ; mapped ; 1EE3 # 1.1 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+1EE3 ; valid # 1.1 LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+1EE4 ; mapped ; 1EE5 # 1.1 LATIN CAPITAL LETTER U WITH DOT BELOW
+1EE5 ; valid # 1.1 LATIN SMALL LETTER U WITH DOT BELOW
+1EE6 ; mapped ; 1EE7 # 1.1 LATIN CAPITAL LETTER U WITH HOOK ABOVE
+1EE7 ; valid # 1.1 LATIN SMALL LETTER U WITH HOOK ABOVE
+1EE8 ; mapped ; 1EE9 # 1.1 LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+1EE9 ; valid # 1.1 LATIN SMALL LETTER U WITH HORN AND ACUTE
+1EEA ; mapped ; 1EEB # 1.1 LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+1EEB ; valid # 1.1 LATIN SMALL LETTER U WITH HORN AND GRAVE
+1EEC ; mapped ; 1EED # 1.1 LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+1EED ; valid # 1.1 LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+1EEE ; mapped ; 1EEF # 1.1 LATIN CAPITAL LETTER U WITH HORN AND TILDE
+1EEF ; valid # 1.1 LATIN SMALL LETTER U WITH HORN AND TILDE
+1EF0 ; mapped ; 1EF1 # 1.1 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+1EF1 ; valid # 1.1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+1EF2 ; mapped ; 1EF3 # 1.1 LATIN CAPITAL LETTER Y WITH GRAVE
+1EF3 ; valid # 1.1 LATIN SMALL LETTER Y WITH GRAVE
+1EF4 ; mapped ; 1EF5 # 1.1 LATIN CAPITAL LETTER Y WITH DOT BELOW
+1EF5 ; valid # 1.1 LATIN SMALL LETTER Y WITH DOT BELOW
+1EF6 ; mapped ; 1EF7 # 1.1 LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+1EF7 ; valid # 1.1 LATIN SMALL LETTER Y WITH HOOK ABOVE
+1EF8 ; mapped ; 1EF9 # 1.1 LATIN CAPITAL LETTER Y WITH TILDE
+1EF9 ; valid # 1.1 LATIN SMALL LETTER Y WITH TILDE
+1EFA ; mapped ; 1EFB # 5.1 LATIN CAPITAL LETTER MIDDLE-WELSH LL
+1EFB ; valid # 5.1 LATIN SMALL LETTER MIDDLE-WELSH LL
+1EFC ; mapped ; 1EFD # 5.1 LATIN CAPITAL LETTER MIDDLE-WELSH V
+1EFD ; valid # 5.1 LATIN SMALL LETTER MIDDLE-WELSH V
+1EFE ; mapped ; 1EFF # 5.1 LATIN CAPITAL LETTER Y WITH LOOP
+1EFF ; valid # 5.1 LATIN SMALL LETTER Y WITH LOOP
+1F00..1F07 ; valid # 1.1 GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F08 ; mapped ; 1F00 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI
+1F09 ; mapped ; 1F01 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA
+1F0A ; mapped ; 1F02 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
+1F0B ; mapped ; 1F03 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA
+1F0C ; mapped ; 1F04 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA
+1F0D ; mapped ; 1F05 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA
+1F0E ; mapped ; 1F06 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI
+1F0F ; mapped ; 1F07 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F10..1F15 ; valid # 1.1 GREEK SMALL LETTER EPSILON WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+1F16..1F17 ; disallowed # NA <reserved-1F16>..<reserved-1F17>
+1F18 ; mapped ; 1F10 # 1.1 GREEK CAPITAL LETTER EPSILON WITH PSILI
+1F19 ; mapped ; 1F11 # 1.1 GREEK CAPITAL LETTER EPSILON WITH DASIA
+1F1A ; mapped ; 1F12 # 1.1 GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA
+1F1B ; mapped ; 1F13 # 1.1 GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA
+1F1C ; mapped ; 1F14 # 1.1 GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA
+1F1D ; mapped ; 1F15 # 1.1 GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F1E..1F1F ; disallowed # NA <reserved-1F1E>..<reserved-1F1F>
+1F20..1F27 ; valid # 1.1 GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
+1F28 ; mapped ; 1F20 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI
+1F29 ; mapped ; 1F21 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA
+1F2A ; mapped ; 1F22 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA
+1F2B ; mapped ; 1F23 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA
+1F2C ; mapped ; 1F24 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA
+1F2D ; mapped ; 1F25 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA
+1F2E ; mapped ; 1F26 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI
+1F2F ; mapped ; 1F27 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+1F30..1F37 ; valid # 1.1 GREEK SMALL LETTER IOTA WITH PSILI..GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F38 ; mapped ; 1F30 # 1.1 GREEK CAPITAL LETTER IOTA WITH PSILI
+1F39 ; mapped ; 1F31 # 1.1 GREEK CAPITAL LETTER IOTA WITH DASIA
+1F3A ; mapped ; 1F32 # 1.1 GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA
+1F3B ; mapped ; 1F33 # 1.1 GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA
+1F3C ; mapped ; 1F34 # 1.1 GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA
+1F3D ; mapped ; 1F35 # 1.1 GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA
+1F3E ; mapped ; 1F36 # 1.1 GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI
+1F3F ; mapped ; 1F37 # 1.1 GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F40..1F45 ; valid # 1.1 GREEK SMALL LETTER OMICRON WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+1F46..1F47 ; disallowed # NA <reserved-1F46>..<reserved-1F47>
+1F48 ; mapped ; 1F40 # 1.1 GREEK CAPITAL LETTER OMICRON WITH PSILI
+1F49 ; mapped ; 1F41 # 1.1 GREEK CAPITAL LETTER OMICRON WITH DASIA
+1F4A ; mapped ; 1F42 # 1.1 GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA
+1F4B ; mapped ; 1F43 # 1.1 GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA
+1F4C ; mapped ; 1F44 # 1.1 GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA
+1F4D ; mapped ; 1F45 # 1.1 GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F4E..1F4F ; disallowed # NA <reserved-1F4E>..<reserved-1F4F>
+1F50..1F57 ; valid # 1.1 GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F58 ; disallowed # NA <reserved-1F58>
+1F59 ; mapped ; 1F51 # 1.1 GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5A ; disallowed # NA <reserved-1F5A>
+1F5B ; mapped ; 1F53 # 1.1 GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5C ; disallowed # NA <reserved-1F5C>
+1F5D ; mapped ; 1F55 # 1.1 GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5E ; disallowed # NA <reserved-1F5E>
+1F5F ; mapped ; 1F57 # 1.1 GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F60..1F67 ; valid # 1.1 GREEK SMALL LETTER OMEGA WITH PSILI..GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F68 ; mapped ; 1F60 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI
+1F69 ; mapped ; 1F61 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA
+1F6A ; mapped ; 1F62 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA
+1F6B ; mapped ; 1F63 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA
+1F6C ; mapped ; 1F64 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA
+1F6D ; mapped ; 1F65 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA
+1F6E ; mapped ; 1F66 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI
+1F6F ; mapped ; 1F67 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F70 ; valid # 1.1 GREEK SMALL LETTER ALPHA WITH VARIA
+1F71 ; mapped ; 03AC # 1.1 GREEK SMALL LETTER ALPHA WITH OXIA
+1F72 ; valid # 1.1 GREEK SMALL LETTER EPSILON WITH VARIA
+1F73 ; mapped ; 03AD # 1.1 GREEK SMALL LETTER EPSILON WITH OXIA
+1F74 ; valid # 1.1 GREEK SMALL LETTER ETA WITH VARIA
+1F75 ; mapped ; 03AE # 1.1 GREEK SMALL LETTER ETA WITH OXIA
+1F76 ; valid # 1.1 GREEK SMALL LETTER IOTA WITH VARIA
+1F77 ; mapped ; 03AF # 1.1 GREEK SMALL LETTER IOTA WITH OXIA
+1F78 ; valid # 1.1 GREEK SMALL LETTER OMICRON WITH VARIA
+1F79 ; mapped ; 03CC # 1.1 GREEK SMALL LETTER OMICRON WITH OXIA
+1F7A ; valid # 1.1 GREEK SMALL LETTER UPSILON WITH VARIA
+1F7B ; mapped ; 03CD # 1.1 GREEK SMALL LETTER UPSILON WITH OXIA
+1F7C ; valid # 1.1 GREEK SMALL LETTER OMEGA WITH VARIA
+1F7D ; mapped ; 03CE # 1.1 GREEK SMALL LETTER OMEGA WITH OXIA
+1F7E..1F7F ; disallowed # NA <reserved-1F7E>..<reserved-1F7F>
+1F80 ; mapped ; 1F00 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI
+1F81 ; mapped ; 1F01 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI
+1F82 ; mapped ; 1F02 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F83 ; mapped ; 1F03 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F84 ; mapped ; 1F04 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F85 ; mapped ; 1F05 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F86 ; mapped ; 1F06 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F87 ; mapped ; 1F07 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F88 ; mapped ; 1F00 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI
+1F89 ; mapped ; 1F01 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI
+1F8A ; mapped ; 1F02 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F8B ; mapped ; 1F03 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F8C ; mapped ; 1F04 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F8D ; mapped ; 1F05 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F8E ; mapped ; 1F06 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F8F ; mapped ; 1F07 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1F90 ; mapped ; 1F20 03B9 # 1.1 GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI
+1F91 ; mapped ; 1F21 03B9 # 1.1 GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI
+1F92 ; mapped ; 1F22 03B9 # 1.1 GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1F93 ; mapped ; 1F23 03B9 # 1.1 GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1F94 ; mapped ; 1F24 03B9 # 1.1 GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1F95 ; mapped ; 1F25 03B9 # 1.1 GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1F96 ; mapped ; 1F26 03B9 # 1.1 GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1F97 ; mapped ; 1F27 03B9 # 1.1 GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1F98 ; mapped ; 1F20 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI
+1F99 ; mapped ; 1F21 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI
+1F9A ; mapped ; 1F22 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1F9B ; mapped ; 1F23 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1F9C ; mapped ; 1F24 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1F9D ; mapped ; 1F25 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1F9E ; mapped ; 1F26 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1F9F ; mapped ; 1F27 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FA0 ; mapped ; 1F60 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI
+1FA1 ; mapped ; 1F61 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI
+1FA2 ; mapped ; 1F62 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI
+1FA3 ; mapped ; 1F63 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI
+1FA4 ; mapped ; 1F64 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI
+1FA5 ; mapped ; 1F65 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI
+1FA6 ; mapped ; 1F66 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI
+1FA7 ; mapped ; 1F67 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI
+1FA8 ; mapped ; 1F60 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI
+1FA9 ; mapped ; 1F61 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI
+1FAA ; mapped ; 1F62 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI
+1FAB ; mapped ; 1F63 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI
+1FAC ; mapped ; 1F64 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI
+1FAD ; mapped ; 1F65 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI
+1FAE ; mapped ; 1F66 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI
+1FAF ; mapped ; 1F67 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FB0..1FB1 ; valid # 1.1 GREEK SMALL LETTER ALPHA WITH VRACHY..GREEK SMALL LETTER ALPHA WITH MACRON
+1FB2 ; mapped ; 1F70 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI
+1FB3 ; mapped ; 03B1 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI
+1FB4 ; mapped ; 03AC 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB5 ; disallowed # NA <reserved-1FB5>
+1FB6 ; valid # 1.1 GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+1FB7 ; mapped ; 1FB6 03B9 # 1.1 GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FB8 ; mapped ; 1FB0 # 1.1 GREEK CAPITAL LETTER ALPHA WITH VRACHY
+1FB9 ; mapped ; 1FB1 # 1.1 GREEK CAPITAL LETTER ALPHA WITH MACRON
+1FBA ; mapped ; 1F70 # 1.1 GREEK CAPITAL LETTER ALPHA WITH VARIA
+1FBB ; mapped ; 03AC # 1.1 GREEK CAPITAL LETTER ALPHA WITH OXIA
+1FBC ; mapped ; 03B1 03B9 # 1.1 GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBD ; disallowed_STD3_mapped ; 0020 0313 # 1.1 GREEK KORONIS
+1FBE ; mapped ; 03B9 # 1.1 GREEK PROSGEGRAMMENI
+1FBF ; disallowed_STD3_mapped ; 0020 0313 # 1.1 GREEK PSILI
+1FC0 ; disallowed_STD3_mapped ; 0020 0342 # 1.1 GREEK PERISPOMENI
+1FC1 ; disallowed_STD3_mapped ; 0020 0308 0342 #1.1 GREEK DIALYTIKA AND PERISPOMENI
+1FC2 ; mapped ; 1F74 03B9 # 1.1 GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI
+1FC3 ; mapped ; 03B7 03B9 # 1.1 GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI
+1FC4 ; mapped ; 03AE 03B9 # 1.1 GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC5 ; disallowed # NA <reserved-1FC5>
+1FC6 ; valid # 1.1 GREEK SMALL LETTER ETA WITH PERISPOMENI
+1FC7 ; mapped ; 1FC6 03B9 # 1.1 GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FC8 ; mapped ; 1F72 # 1.1 GREEK CAPITAL LETTER EPSILON WITH VARIA
+1FC9 ; mapped ; 03AD # 1.1 GREEK CAPITAL LETTER EPSILON WITH OXIA
+1FCA ; mapped ; 1F74 # 1.1 GREEK CAPITAL LETTER ETA WITH VARIA
+1FCB ; mapped ; 03AE # 1.1 GREEK CAPITAL LETTER ETA WITH OXIA
+1FCC ; mapped ; 03B7 03B9 # 1.1 GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FCD ; disallowed_STD3_mapped ; 0020 0313 0300 #1.1 GREEK PSILI AND VARIA
+1FCE ; disallowed_STD3_mapped ; 0020 0313 0301 #1.1 GREEK PSILI AND OXIA
+1FCF ; disallowed_STD3_mapped ; 0020 0313 0342 #1.1 GREEK PSILI AND PERISPOMENI
+1FD0..1FD2 ; valid # 1.1 GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+1FD3 ; mapped ; 0390 # 1.1 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD4..1FD5 ; disallowed # NA <reserved-1FD4>..<reserved-1FD5>
+1FD6..1FD7 ; valid # 1.1 GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+1FD8 ; mapped ; 1FD0 # 1.1 GREEK CAPITAL LETTER IOTA WITH VRACHY
+1FD9 ; mapped ; 1FD1 # 1.1 GREEK CAPITAL LETTER IOTA WITH MACRON
+1FDA ; mapped ; 1F76 # 1.1 GREEK CAPITAL LETTER IOTA WITH VARIA
+1FDB ; mapped ; 03AF # 1.1 GREEK CAPITAL LETTER IOTA WITH OXIA
+1FDC ; disallowed # NA <reserved-1FDC>
+1FDD ; disallowed_STD3_mapped ; 0020 0314 0300 #1.1 GREEK DASIA AND VARIA
+1FDE ; disallowed_STD3_mapped ; 0020 0314 0301 #1.1 GREEK DASIA AND OXIA
+1FDF ; disallowed_STD3_mapped ; 0020 0314 0342 #1.1 GREEK DASIA AND PERISPOMENI
+1FE0..1FE2 ; valid # 1.1 GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+1FE3 ; mapped ; 03B0 # 1.1 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+1FE4..1FE7 ; valid # 1.1 GREEK SMALL LETTER RHO WITH PSILI..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+1FE8 ; mapped ; 1FE0 # 1.1 GREEK CAPITAL LETTER UPSILON WITH VRACHY
+1FE9 ; mapped ; 1FE1 # 1.1 GREEK CAPITAL LETTER UPSILON WITH MACRON
+1FEA ; mapped ; 1F7A # 1.1 GREEK CAPITAL LETTER UPSILON WITH VARIA
+1FEB ; mapped ; 03CD # 1.1 GREEK CAPITAL LETTER UPSILON WITH OXIA
+1FEC ; mapped ; 1FE5 # 1.1 GREEK CAPITAL LETTER RHO WITH DASIA
+1FED ; disallowed_STD3_mapped ; 0020 0308 0300 #1.1 GREEK DIALYTIKA AND VARIA
+1FEE ; disallowed_STD3_mapped ; 0020 0308 0301 #1.1 GREEK DIALYTIKA AND OXIA
+1FEF ; disallowed_STD3_mapped ; 0060 # 1.1 GREEK VARIA
+1FF0..1FF1 ; disallowed # NA <reserved-1FF0>..<reserved-1FF1>
+1FF2 ; mapped ; 1F7C 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI
+1FF3 ; mapped ; 03C9 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI
+1FF4 ; mapped ; 03CE 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF5 ; disallowed # NA <reserved-1FF5>
+1FF6 ; valid # 1.1 GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+1FF7 ; mapped ; 1FF6 03B9 # 1.1 GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI
+1FF8 ; mapped ; 1F78 # 1.1 GREEK CAPITAL LETTER OMICRON WITH VARIA
+1FF9 ; mapped ; 03CC # 1.1 GREEK CAPITAL LETTER OMICRON WITH OXIA
+1FFA ; mapped ; 1F7C # 1.1 GREEK CAPITAL LETTER OMEGA WITH VARIA
+1FFB ; mapped ; 03CE # 1.1 GREEK CAPITAL LETTER OMEGA WITH OXIA
+1FFC ; mapped ; 03C9 03B9 # 1.1 GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+1FFD ; disallowed_STD3_mapped ; 0020 0301 # 1.1 GREEK OXIA
+1FFE ; disallowed_STD3_mapped ; 0020 0314 # 1.1 GREEK DASIA
+1FFF ; disallowed # NA <reserved-1FFF>
+2000..200A ; disallowed_STD3_mapped ; 0020 # 1.1 EN QUAD..HAIR SPACE
+200B ; ignored # 1.1 ZERO WIDTH SPACE
+200C..200D ; deviation ; # 1.1 ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
+200E..200F ; disallowed # 1.1 LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK
+2010 ; valid ; ; NV8 # 1.1 HYPHEN
+2011 ; mapped ; 2010 # 1.1 NON-BREAKING HYPHEN
+2012..2016 ; valid ; ; NV8 # 1.1 FIGURE DASH..DOUBLE VERTICAL LINE
+2017 ; disallowed_STD3_mapped ; 0020 0333 # 1.1 DOUBLE LOW LINE
+2018..2023 ; valid ; ; NV8 # 1.1 LEFT SINGLE QUOTATION MARK..TRIANGULAR BULLET
+2024..2026 ; disallowed # 1.1 ONE DOT LEADER..HORIZONTAL ELLIPSIS
+2027 ; valid ; ; NV8 # 1.1 HYPHENATION POINT
+2028..202E ; disallowed # 1.1 LINE SEPARATOR..RIGHT-TO-LEFT OVERRIDE
+202F ; disallowed_STD3_mapped ; 0020 # 3.0 NARROW NO-BREAK SPACE
+2030..2032 ; valid ; ; NV8 # 1.1 PER MILLE SIGN..PRIME
+2033 ; mapped ; 2032 2032 # 1.1 DOUBLE PRIME
+2034 ; mapped ; 2032 2032 2032 #1.1 TRIPLE PRIME
+2035 ; valid ; ; NV8 # 1.1 REVERSED PRIME
+2036 ; mapped ; 2035 2035 # 1.1 REVERSED DOUBLE PRIME
+2037 ; mapped ; 2035 2035 2035 #1.1 REVERSED TRIPLE PRIME
+2038..203B ; valid ; ; NV8 # 1.1 CARET..REFERENCE MARK
+203C ; disallowed_STD3_mapped ; 0021 0021 # 1.1 DOUBLE EXCLAMATION MARK
+203D ; valid ; ; NV8 # 1.1 INTERROBANG
+203E ; disallowed_STD3_mapped ; 0020 0305 # 1.1 OVERLINE
+203F..2046 ; valid ; ; NV8 # 1.1 UNDERTIE..RIGHT SQUARE BRACKET WITH QUILL
+2047 ; disallowed_STD3_mapped ; 003F 003F # 3.2 DOUBLE QUESTION MARK
+2048 ; disallowed_STD3_mapped ; 003F 0021 # 3.0 QUESTION EXCLAMATION MARK
+2049 ; disallowed_STD3_mapped ; 0021 003F # 3.0 EXCLAMATION QUESTION MARK
+204A..204D ; valid ; ; NV8 # 3.0 TIRONIAN SIGN ET..BLACK RIGHTWARDS BULLET
+204E..2052 ; valid ; ; NV8 # 3.2 LOW ASTERISK..COMMERCIAL MINUS SIGN
+2053..2054 ; valid ; ; NV8 # 4.0 SWUNG DASH..INVERTED UNDERTIE
+2055..2056 ; valid ; ; NV8 # 4.1 FLOWER PUNCTUATION MARK..THREE DOT PUNCTUATION
+2057 ; mapped ; 2032 2032 2032 2032 #3.2 QUADRUPLE PRIME
+2058..205E ; valid ; ; NV8 # 4.1 FOUR DOT PUNCTUATION..VERTICAL FOUR DOTS
+205F ; disallowed_STD3_mapped ; 0020 # 3.2 MEDIUM MATHEMATICAL SPACE
+2060 ; ignored # 3.2 WORD JOINER
+2061..2063 ; disallowed # 3.2 FUNCTION APPLICATION..INVISIBLE SEPARATOR
+2064 ; ignored # 5.1 INVISIBLE PLUS
+2065 ; disallowed # NA <reserved-2065>
+2066..2069 ; disallowed # 6.3 LEFT-TO-RIGHT ISOLATE..POP DIRECTIONAL ISOLATE
+206A..206F ; disallowed # 1.1 INHIBIT SYMMETRIC SWAPPING..NOMINAL DIGIT SHAPES
+2070 ; mapped ; 0030 # 1.1 SUPERSCRIPT ZERO
+2071 ; mapped ; 0069 # 3.2 SUPERSCRIPT LATIN SMALL LETTER I
+2072..2073 ; disallowed # NA <reserved-2072>..<reserved-2073>
+2074 ; mapped ; 0034 # 1.1 SUPERSCRIPT FOUR
+2075 ; mapped ; 0035 # 1.1 SUPERSCRIPT FIVE
+2076 ; mapped ; 0036 # 1.1 SUPERSCRIPT SIX
+2077 ; mapped ; 0037 # 1.1 SUPERSCRIPT SEVEN
+2078 ; mapped ; 0038 # 1.1 SUPERSCRIPT EIGHT
+2079 ; mapped ; 0039 # 1.1 SUPERSCRIPT NINE
+207A ; disallowed_STD3_mapped ; 002B # 1.1 SUPERSCRIPT PLUS SIGN
+207B ; mapped ; 2212 # 1.1 SUPERSCRIPT MINUS
+207C ; disallowed_STD3_mapped ; 003D # 1.1 SUPERSCRIPT EQUALS SIGN
+207D ; disallowed_STD3_mapped ; 0028 # 1.1 SUPERSCRIPT LEFT PARENTHESIS
+207E ; disallowed_STD3_mapped ; 0029 # 1.1 SUPERSCRIPT RIGHT PARENTHESIS
+207F ; mapped ; 006E # 1.1 SUPERSCRIPT LATIN SMALL LETTER N
+2080 ; mapped ; 0030 # 1.1 SUBSCRIPT ZERO
+2081 ; mapped ; 0031 # 1.1 SUBSCRIPT ONE
+2082 ; mapped ; 0032 # 1.1 SUBSCRIPT TWO
+2083 ; mapped ; 0033 # 1.1 SUBSCRIPT THREE
+2084 ; mapped ; 0034 # 1.1 SUBSCRIPT FOUR
+2085 ; mapped ; 0035 # 1.1 SUBSCRIPT FIVE
+2086 ; mapped ; 0036 # 1.1 SUBSCRIPT SIX
+2087 ; mapped ; 0037 # 1.1 SUBSCRIPT SEVEN
+2088 ; mapped ; 0038 # 1.1 SUBSCRIPT EIGHT
+2089 ; mapped ; 0039 # 1.1 SUBSCRIPT NINE
+208A ; disallowed_STD3_mapped ; 002B # 1.1 SUBSCRIPT PLUS SIGN
+208B ; mapped ; 2212 # 1.1 SUBSCRIPT MINUS
+208C ; disallowed_STD3_mapped ; 003D # 1.1 SUBSCRIPT EQUALS SIGN
+208D ; disallowed_STD3_mapped ; 0028 # 1.1 SUBSCRIPT LEFT PARENTHESIS
+208E ; disallowed_STD3_mapped ; 0029 # 1.1 SUBSCRIPT RIGHT PARENTHESIS
+208F ; disallowed # NA <reserved-208F>
+2090 ; mapped ; 0061 # 4.1 LATIN SUBSCRIPT SMALL LETTER A
+2091 ; mapped ; 0065 # 4.1 LATIN SUBSCRIPT SMALL LETTER E
+2092 ; mapped ; 006F # 4.1 LATIN SUBSCRIPT SMALL LETTER O
+2093 ; mapped ; 0078 # 4.1 LATIN SUBSCRIPT SMALL LETTER X
+2094 ; mapped ; 0259 # 4.1 LATIN SUBSCRIPT SMALL LETTER SCHWA
+2095 ; mapped ; 0068 # 6.0 LATIN SUBSCRIPT SMALL LETTER H
+2096 ; mapped ; 006B # 6.0 LATIN SUBSCRIPT SMALL LETTER K
+2097 ; mapped ; 006C # 6.0 LATIN SUBSCRIPT SMALL LETTER L
+2098 ; mapped ; 006D # 6.0 LATIN SUBSCRIPT SMALL LETTER M
+2099 ; mapped ; 006E # 6.0 LATIN SUBSCRIPT SMALL LETTER N
+209A ; mapped ; 0070 # 6.0 LATIN SUBSCRIPT SMALL LETTER P
+209B ; mapped ; 0073 # 6.0 LATIN SUBSCRIPT SMALL LETTER S
+209C ; mapped ; 0074 # 6.0 LATIN SUBSCRIPT SMALL LETTER T
+209D..209F ; disallowed # NA <reserved-209D>..<reserved-209F>
+20A0..20A7 ; valid ; ; NV8 # 1.1 EURO-CURRENCY SIGN..PESETA SIGN
+20A8 ; mapped ; 0072 0073 # 1.1 RUPEE SIGN
+20A9..20AA ; valid ; ; NV8 # 1.1 WON SIGN..NEW SHEQEL SIGN
+20AB ; valid ; ; NV8 # 2.0 DONG SIGN
+20AC ; valid ; ; NV8 # 2.1 EURO SIGN
+20AD..20AF ; valid ; ; NV8 # 3.0 KIP SIGN..DRACHMA SIGN
+20B0..20B1 ; valid ; ; NV8 # 3.2 GERMAN PENNY SIGN..PESO SIGN
+20B2..20B5 ; valid ; ; NV8 # 4.1 GUARANI SIGN..CEDI SIGN
+20B6..20B8 ; valid ; ; NV8 # 5.2 LIVRE TOURNOIS SIGN..TENGE SIGN
+20B9 ; valid ; ; NV8 # 6.0 INDIAN RUPEE SIGN
+20BA ; valid ; ; NV8 # 6.2 TURKISH LIRA SIGN
+20BB..20BD ; valid ; ; NV8 # 7.0 NORDIC MARK SIGN..RUBLE SIGN
+20BE ; valid ; ; NV8 # 8.0 LARI SIGN
+20BF ; valid ; ; NV8 # 10.0 BITCOIN SIGN
+20C0 ; valid ; ; NV8 # 14.0 SOM SIGN
+20C1..20CF ; disallowed # NA <reserved-20C1>..<reserved-20CF>
+20D0..20E1 ; valid ; ; NV8 # 1.1 COMBINING LEFT HARPOON ABOVE..COMBINING LEFT RIGHT ARROW ABOVE
+20E2..20E3 ; valid ; ; NV8 # 3.0 COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING KEYCAP
+20E4..20EA ; valid ; ; NV8 # 3.2 COMBINING ENCLOSING UPWARD POINTING TRIANGLE..COMBINING LEFTWARDS ARROW OVERLAY
+20EB ; valid ; ; NV8 # 4.1 COMBINING LONG DOUBLE SOLIDUS OVERLAY
+20EC..20EF ; valid ; ; NV8 # 5.0 COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS..COMBINING RIGHT ARROW BELOW
+20F0 ; valid ; ; NV8 # 5.1 COMBINING ASTERISK ABOVE
+20F1..20FF ; disallowed # NA <reserved-20F1>..<reserved-20FF>
+2100 ; disallowed_STD3_mapped ; 0061 002F 0063 #1.1 ACCOUNT OF
+2101 ; disallowed_STD3_mapped ; 0061 002F 0073 #1.1 ADDRESSED TO THE SUBJECT
+2102 ; mapped ; 0063 # 1.1 DOUBLE-STRUCK CAPITAL C
+2103 ; mapped ; 00B0 0063 # 1.1 DEGREE CELSIUS
+2104 ; valid ; ; NV8 # 1.1 CENTRE LINE SYMBOL
+2105 ; disallowed_STD3_mapped ; 0063 002F 006F #1.1 CARE OF
+2106 ; disallowed_STD3_mapped ; 0063 002F 0075 #1.1 CADA UNA
+2107 ; mapped ; 025B # 1.1 EULER CONSTANT
+2108 ; valid ; ; NV8 # 1.1 SCRUPLE
+2109 ; mapped ; 00B0 0066 # 1.1 DEGREE FAHRENHEIT
+210A ; mapped ; 0067 # 1.1 SCRIPT SMALL G
+210B..210E ; mapped ; 0068 # 1.1 SCRIPT CAPITAL H..PLANCK CONSTANT
+210F ; mapped ; 0127 # 1.1 PLANCK CONSTANT OVER TWO PI
+2110..2111 ; mapped ; 0069 # 1.1 SCRIPT CAPITAL I..BLACK-LETTER CAPITAL I
+2112..2113 ; mapped ; 006C # 1.1 SCRIPT CAPITAL L..SCRIPT SMALL L
+2114 ; valid ; ; NV8 # 1.1 L B BAR SYMBOL
+2115 ; mapped ; 006E # 1.1 DOUBLE-STRUCK CAPITAL N
+2116 ; mapped ; 006E 006F # 1.1 NUMERO SIGN
+2117..2118 ; valid ; ; NV8 # 1.1 SOUND RECORDING COPYRIGHT..SCRIPT CAPITAL P
+2119 ; mapped ; 0070 # 1.1 DOUBLE-STRUCK CAPITAL P
+211A ; mapped ; 0071 # 1.1 DOUBLE-STRUCK CAPITAL Q
+211B..211D ; mapped ; 0072 # 1.1 SCRIPT CAPITAL R..DOUBLE-STRUCK CAPITAL R
+211E..211F ; valid ; ; NV8 # 1.1 PRESCRIPTION TAKE..RESPONSE
+2120 ; mapped ; 0073 006D # 1.1 SERVICE MARK
+2121 ; mapped ; 0074 0065 006C #1.1 TELEPHONE SIGN
+2122 ; mapped ; 0074 006D # 1.1 TRADE MARK SIGN
+2123 ; valid ; ; NV8 # 1.1 VERSICLE
+2124 ; mapped ; 007A # 1.1 DOUBLE-STRUCK CAPITAL Z
+2125 ; valid ; ; NV8 # 1.1 OUNCE SIGN
+2126 ; mapped ; 03C9 # 1.1 OHM SIGN
+2127 ; valid ; ; NV8 # 1.1 INVERTED OHM SIGN
+2128 ; mapped ; 007A # 1.1 BLACK-LETTER CAPITAL Z
+2129 ; valid ; ; NV8 # 1.1 TURNED GREEK SMALL LETTER IOTA
+212A ; mapped ; 006B # 1.1 KELVIN SIGN
+212B ; mapped ; 00E5 # 1.1 ANGSTROM SIGN
+212C ; mapped ; 0062 # 1.1 SCRIPT CAPITAL B
+212D ; mapped ; 0063 # 1.1 BLACK-LETTER CAPITAL C
+212E ; valid ; ; NV8 # 1.1 ESTIMATED SYMBOL
+212F..2130 ; mapped ; 0065 # 1.1 SCRIPT SMALL E..SCRIPT CAPITAL E
+2131 ; mapped ; 0066 # 1.1 SCRIPT CAPITAL F
+2132 ; disallowed # 1.1 TURNED CAPITAL F
+2133 ; mapped ; 006D # 1.1 SCRIPT CAPITAL M
+2134 ; mapped ; 006F # 1.1 SCRIPT SMALL O
+2135 ; mapped ; 05D0 # 1.1 ALEF SYMBOL
+2136 ; mapped ; 05D1 # 1.1 BET SYMBOL
+2137 ; mapped ; 05D2 # 1.1 GIMEL SYMBOL
+2138 ; mapped ; 05D3 # 1.1 DALET SYMBOL
+2139 ; mapped ; 0069 # 3.0 INFORMATION SOURCE
+213A ; valid ; ; NV8 # 3.0 ROTATED CAPITAL Q
+213B ; mapped ; 0066 0061 0078 #4.0 FACSIMILE SIGN
+213C ; mapped ; 03C0 # 4.1 DOUBLE-STRUCK SMALL PI
+213D..213E ; mapped ; 03B3 # 3.2 DOUBLE-STRUCK SMALL GAMMA..DOUBLE-STRUCK CAPITAL GAMMA
+213F ; mapped ; 03C0 # 3.2 DOUBLE-STRUCK CAPITAL PI
+2140 ; mapped ; 2211 # 3.2 DOUBLE-STRUCK N-ARY SUMMATION
+2141..2144 ; valid ; ; NV8 # 3.2 TURNED SANS-SERIF CAPITAL G..TURNED SANS-SERIF CAPITAL Y
+2145..2146 ; mapped ; 0064 # 3.2 DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL D
+2147 ; mapped ; 0065 # 3.2 DOUBLE-STRUCK ITALIC SMALL E
+2148 ; mapped ; 0069 # 3.2 DOUBLE-STRUCK ITALIC SMALL I
+2149 ; mapped ; 006A # 3.2 DOUBLE-STRUCK ITALIC SMALL J
+214A..214B ; valid ; ; NV8 # 3.2 PROPERTY LINE..TURNED AMPERSAND
+214C ; valid ; ; NV8 # 4.1 PER SIGN
+214D ; valid ; ; NV8 # 5.0 AKTIESELSKAB
+214E ; valid # 5.0 TURNED SMALL F
+214F ; valid ; ; NV8 # 5.1 SYMBOL FOR SAMARITAN SOURCE
+2150 ; mapped ; 0031 2044 0037 #5.2 VULGAR FRACTION ONE SEVENTH
+2151 ; mapped ; 0031 2044 0039 #5.2 VULGAR FRACTION ONE NINTH
+2152 ; mapped ; 0031 2044 0031 0030 #5.2 VULGAR FRACTION ONE TENTH
+2153 ; mapped ; 0031 2044 0033 #1.1 VULGAR FRACTION ONE THIRD
+2154 ; mapped ; 0032 2044 0033 #1.1 VULGAR FRACTION TWO THIRDS
+2155 ; mapped ; 0031 2044 0035 #1.1 VULGAR FRACTION ONE FIFTH
+2156 ; mapped ; 0032 2044 0035 #1.1 VULGAR FRACTION TWO FIFTHS
+2157 ; mapped ; 0033 2044 0035 #1.1 VULGAR FRACTION THREE FIFTHS
+2158 ; mapped ; 0034 2044 0035 #1.1 VULGAR FRACTION FOUR FIFTHS
+2159 ; mapped ; 0031 2044 0036 #1.1 VULGAR FRACTION ONE SIXTH
+215A ; mapped ; 0035 2044 0036 #1.1 VULGAR FRACTION FIVE SIXTHS
+215B ; mapped ; 0031 2044 0038 #1.1 VULGAR FRACTION ONE EIGHTH
+215C ; mapped ; 0033 2044 0038 #1.1 VULGAR FRACTION THREE EIGHTHS
+215D ; mapped ; 0035 2044 0038 #1.1 VULGAR FRACTION FIVE EIGHTHS
+215E ; mapped ; 0037 2044 0038 #1.1 VULGAR FRACTION SEVEN EIGHTHS
+215F ; mapped ; 0031 2044 # 1.1 FRACTION NUMERATOR ONE
+2160 ; mapped ; 0069 # 1.1 ROMAN NUMERAL ONE
+2161 ; mapped ; 0069 0069 # 1.1 ROMAN NUMERAL TWO
+2162 ; mapped ; 0069 0069 0069 #1.1 ROMAN NUMERAL THREE
+2163 ; mapped ; 0069 0076 # 1.1 ROMAN NUMERAL FOUR
+2164 ; mapped ; 0076 # 1.1 ROMAN NUMERAL FIVE
+2165 ; mapped ; 0076 0069 # 1.1 ROMAN NUMERAL SIX
+2166 ; mapped ; 0076 0069 0069 #1.1 ROMAN NUMERAL SEVEN
+2167 ; mapped ; 0076 0069 0069 0069 #1.1 ROMAN NUMERAL EIGHT
+2168 ; mapped ; 0069 0078 # 1.1 ROMAN NUMERAL NINE
+2169 ; mapped ; 0078 # 1.1 ROMAN NUMERAL TEN
+216A ; mapped ; 0078 0069 # 1.1 ROMAN NUMERAL ELEVEN
+216B ; mapped ; 0078 0069 0069 #1.1 ROMAN NUMERAL TWELVE
+216C ; mapped ; 006C # 1.1 ROMAN NUMERAL FIFTY
+216D ; mapped ; 0063 # 1.1 ROMAN NUMERAL ONE HUNDRED
+216E ; mapped ; 0064 # 1.1 ROMAN NUMERAL FIVE HUNDRED
+216F ; mapped ; 006D # 1.1 ROMAN NUMERAL ONE THOUSAND
+2170 ; mapped ; 0069 # 1.1 SMALL ROMAN NUMERAL ONE
+2171 ; mapped ; 0069 0069 # 1.1 SMALL ROMAN NUMERAL TWO
+2172 ; mapped ; 0069 0069 0069 #1.1 SMALL ROMAN NUMERAL THREE
+2173 ; mapped ; 0069 0076 # 1.1 SMALL ROMAN NUMERAL FOUR
+2174 ; mapped ; 0076 # 1.1 SMALL ROMAN NUMERAL FIVE
+2175 ; mapped ; 0076 0069 # 1.1 SMALL ROMAN NUMERAL SIX
+2176 ; mapped ; 0076 0069 0069 #1.1 SMALL ROMAN NUMERAL SEVEN
+2177 ; mapped ; 0076 0069 0069 0069 #1.1 SMALL ROMAN NUMERAL EIGHT
+2178 ; mapped ; 0069 0078 # 1.1 SMALL ROMAN NUMERAL NINE
+2179 ; mapped ; 0078 # 1.1 SMALL ROMAN NUMERAL TEN
+217A ; mapped ; 0078 0069 # 1.1 SMALL ROMAN NUMERAL ELEVEN
+217B ; mapped ; 0078 0069 0069 #1.1 SMALL ROMAN NUMERAL TWELVE
+217C ; mapped ; 006C # 1.1 SMALL ROMAN NUMERAL FIFTY
+217D ; mapped ; 0063 # 1.1 SMALL ROMAN NUMERAL ONE HUNDRED
+217E ; mapped ; 0064 # 1.1 SMALL ROMAN NUMERAL FIVE HUNDRED
+217F ; mapped ; 006D # 1.1 SMALL ROMAN NUMERAL ONE THOUSAND
+2180..2182 ; valid ; ; NV8 # 1.1 ROMAN NUMERAL ONE THOUSAND C D..ROMAN NUMERAL TEN THOUSAND
+2183 ; disallowed # 3.0 ROMAN NUMERAL REVERSED ONE HUNDRED
+2184 ; valid # 5.0 LATIN SMALL LETTER REVERSED C
+2185..2188 ; valid ; ; NV8 # 5.1 ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND
+2189 ; mapped ; 0030 2044 0033 #5.2 VULGAR FRACTION ZERO THIRDS
+218A..218B ; valid ; ; NV8 # 8.0 TURNED DIGIT TWO..TURNED DIGIT THREE
+218C..218F ; disallowed # NA <reserved-218C>..<reserved-218F>
+2190..21EA ; valid ; ; NV8 # 1.1 LEFTWARDS ARROW..UPWARDS WHITE ARROW FROM BAR
+21EB..21F3 ; valid ; ; NV8 # 3.0 UPWARDS WHITE ARROW ON PEDESTAL..UP DOWN WHITE ARROW
+21F4..21FF ; valid ; ; NV8 # 3.2 RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW
+2200..222B ; valid ; ; NV8 # 1.1 FOR ALL..INTEGRAL
+222C ; mapped ; 222B 222B # 1.1 DOUBLE INTEGRAL
+222D ; mapped ; 222B 222B 222B #1.1 TRIPLE INTEGRAL
+222E ; valid ; ; NV8 # 1.1 CONTOUR INTEGRAL
+222F ; mapped ; 222E 222E # 1.1 SURFACE INTEGRAL
+2230 ; mapped ; 222E 222E 222E #1.1 VOLUME INTEGRAL
+2231..225F ; valid ; ; NV8 # 1.1 CLOCKWISE INTEGRAL..QUESTIONED EQUAL TO
+2260 ; disallowed_STD3_valid # 1.1 NOT EQUAL TO
+2261..226D ; valid ; ; NV8 # 1.1 IDENTICAL TO..NOT EQUIVALENT TO
+226E..226F ; disallowed_STD3_valid # 1.1 NOT LESS-THAN..NOT GREATER-THAN
+2270..22F1 ; valid ; ; NV8 # 1.1 NEITHER LESS-THAN NOR EQUAL TO..DOWN RIGHT DIAGONAL ELLIPSIS
+22F2..22FF ; valid ; ; NV8 # 3.2 ELEMENT OF WITH LONG HORIZONTAL STROKE..Z NOTATION BAG MEMBERSHIP
+2300 ; valid ; ; NV8 # 1.1 DIAMETER SIGN
+2301 ; valid ; ; NV8 # 3.0 ELECTRIC ARROW
+2302..2328 ; valid ; ; NV8 # 1.1 HOUSE..KEYBOARD
+2329 ; mapped ; 3008 # 1.1 LEFT-POINTING ANGLE BRACKET
+232A ; mapped ; 3009 # 1.1 RIGHT-POINTING ANGLE BRACKET
+232B..237A ; valid ; ; NV8 # 1.1 ERASE TO THE LEFT..APL FUNCTIONAL SYMBOL ALPHA
+237B ; valid ; ; NV8 # 3.0 NOT CHECK MARK
+237C ; valid ; ; NV8 # 3.2 RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+237D..239A ; valid ; ; NV8 # 3.0 SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL
+239B..23CE ; valid ; ; NV8 # 3.2 LEFT PARENTHESIS UPPER HOOK..RETURN SYMBOL
+23CF..23D0 ; valid ; ; NV8 # 4.0 EJECT SYMBOL..VERTICAL LINE EXTENSION
+23D1..23DB ; valid ; ; NV8 # 4.1 METRICAL BREVE..FUSE
+23DC..23E7 ; valid ; ; NV8 # 5.0 TOP PARENTHESIS..ELECTRICAL INTERSECTION
+23E8 ; valid ; ; NV8 # 5.2 DECIMAL EXPONENT SYMBOL
+23E9..23F3 ; valid ; ; NV8 # 6.0 BLACK RIGHT-POINTING DOUBLE TRIANGLE..HOURGLASS WITH FLOWING SAND
+23F4..23FA ; valid ; ; NV8 # 7.0 BLACK MEDIUM LEFT-POINTING TRIANGLE..BLACK CIRCLE FOR RECORD
+23FB..23FE ; valid ; ; NV8 # 9.0 POWER SYMBOL..POWER SLEEP SYMBOL
+23FF ; valid ; ; NV8 # 10.0 OBSERVER EYE SYMBOL
+2400..2424 ; valid ; ; NV8 # 1.1 SYMBOL FOR NULL..SYMBOL FOR NEWLINE
+2425..2426 ; valid ; ; NV8 # 3.0 SYMBOL FOR DELETE FORM TWO..SYMBOL FOR SUBSTITUTE FORM TWO
+2427..243F ; disallowed # NA <reserved-2427>..<reserved-243F>
+2440..244A ; valid ; ; NV8 # 1.1 OCR HOOK..OCR DOUBLE BACKSLASH
+244B..245F ; disallowed # NA <reserved-244B>..<reserved-245F>
+2460 ; mapped ; 0031 # 1.1 CIRCLED DIGIT ONE
+2461 ; mapped ; 0032 # 1.1 CIRCLED DIGIT TWO
+2462 ; mapped ; 0033 # 1.1 CIRCLED DIGIT THREE
+2463 ; mapped ; 0034 # 1.1 CIRCLED DIGIT FOUR
+2464 ; mapped ; 0035 # 1.1 CIRCLED DIGIT FIVE
+2465 ; mapped ; 0036 # 1.1 CIRCLED DIGIT SIX
+2466 ; mapped ; 0037 # 1.1 CIRCLED DIGIT SEVEN
+2467 ; mapped ; 0038 # 1.1 CIRCLED DIGIT EIGHT
+2468 ; mapped ; 0039 # 1.1 CIRCLED DIGIT NINE
+2469 ; mapped ; 0031 0030 # 1.1 CIRCLED NUMBER TEN
+246A ; mapped ; 0031 0031 # 1.1 CIRCLED NUMBER ELEVEN
+246B ; mapped ; 0031 0032 # 1.1 CIRCLED NUMBER TWELVE
+246C ; mapped ; 0031 0033 # 1.1 CIRCLED NUMBER THIRTEEN
+246D ; mapped ; 0031 0034 # 1.1 CIRCLED NUMBER FOURTEEN
+246E ; mapped ; 0031 0035 # 1.1 CIRCLED NUMBER FIFTEEN
+246F ; mapped ; 0031 0036 # 1.1 CIRCLED NUMBER SIXTEEN
+2470 ; mapped ; 0031 0037 # 1.1 CIRCLED NUMBER SEVENTEEN
+2471 ; mapped ; 0031 0038 # 1.1 CIRCLED NUMBER EIGHTEEN
+2472 ; mapped ; 0031 0039 # 1.1 CIRCLED NUMBER NINETEEN
+2473 ; mapped ; 0032 0030 # 1.1 CIRCLED NUMBER TWENTY
+2474 ; disallowed_STD3_mapped ; 0028 0031 0029 #1.1 PARENTHESIZED DIGIT ONE
+2475 ; disallowed_STD3_mapped ; 0028 0032 0029 #1.1 PARENTHESIZED DIGIT TWO
+2476 ; disallowed_STD3_mapped ; 0028 0033 0029 #1.1 PARENTHESIZED DIGIT THREE
+2477 ; disallowed_STD3_mapped ; 0028 0034 0029 #1.1 PARENTHESIZED DIGIT FOUR
+2478 ; disallowed_STD3_mapped ; 0028 0035 0029 #1.1 PARENTHESIZED DIGIT FIVE
+2479 ; disallowed_STD3_mapped ; 0028 0036 0029 #1.1 PARENTHESIZED DIGIT SIX
+247A ; disallowed_STD3_mapped ; 0028 0037 0029 #1.1 PARENTHESIZED DIGIT SEVEN
+247B ; disallowed_STD3_mapped ; 0028 0038 0029 #1.1 PARENTHESIZED DIGIT EIGHT
+247C ; disallowed_STD3_mapped ; 0028 0039 0029 #1.1 PARENTHESIZED DIGIT NINE
+247D ; disallowed_STD3_mapped ; 0028 0031 0030 0029 #1.1 PARENTHESIZED NUMBER TEN
+247E ; disallowed_STD3_mapped ; 0028 0031 0031 0029 #1.1 PARENTHESIZED NUMBER ELEVEN
+247F ; disallowed_STD3_mapped ; 0028 0031 0032 0029 #1.1 PARENTHESIZED NUMBER TWELVE
+2480 ; disallowed_STD3_mapped ; 0028 0031 0033 0029 #1.1 PARENTHESIZED NUMBER THIRTEEN
+2481 ; disallowed_STD3_mapped ; 0028 0031 0034 0029 #1.1 PARENTHESIZED NUMBER FOURTEEN
+2482 ; disallowed_STD3_mapped ; 0028 0031 0035 0029 #1.1 PARENTHESIZED NUMBER FIFTEEN
+2483 ; disallowed_STD3_mapped ; 0028 0031 0036 0029 #1.1 PARENTHESIZED NUMBER SIXTEEN
+2484 ; disallowed_STD3_mapped ; 0028 0031 0037 0029 #1.1 PARENTHESIZED NUMBER SEVENTEEN
+2485 ; disallowed_STD3_mapped ; 0028 0031 0038 0029 #1.1 PARENTHESIZED NUMBER EIGHTEEN
+2486 ; disallowed_STD3_mapped ; 0028 0031 0039 0029 #1.1 PARENTHESIZED NUMBER NINETEEN
+2487 ; disallowed_STD3_mapped ; 0028 0032 0030 0029 #1.1 PARENTHESIZED NUMBER TWENTY
+2488..249B ; disallowed # 1.1 DIGIT ONE FULL STOP..NUMBER TWENTY FULL STOP
+249C ; disallowed_STD3_mapped ; 0028 0061 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER A
+249D ; disallowed_STD3_mapped ; 0028 0062 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER B
+249E ; disallowed_STD3_mapped ; 0028 0063 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER C
+249F ; disallowed_STD3_mapped ; 0028 0064 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER D
+24A0 ; disallowed_STD3_mapped ; 0028 0065 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER E
+24A1 ; disallowed_STD3_mapped ; 0028 0066 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER F
+24A2 ; disallowed_STD3_mapped ; 0028 0067 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER G
+24A3 ; disallowed_STD3_mapped ; 0028 0068 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER H
+24A4 ; disallowed_STD3_mapped ; 0028 0069 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER I
+24A5 ; disallowed_STD3_mapped ; 0028 006A 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER J
+24A6 ; disallowed_STD3_mapped ; 0028 006B 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER K
+24A7 ; disallowed_STD3_mapped ; 0028 006C 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER L
+24A8 ; disallowed_STD3_mapped ; 0028 006D 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER M
+24A9 ; disallowed_STD3_mapped ; 0028 006E 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER N
+24AA ; disallowed_STD3_mapped ; 0028 006F 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER O
+24AB ; disallowed_STD3_mapped ; 0028 0070 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER P
+24AC ; disallowed_STD3_mapped ; 0028 0071 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER Q
+24AD ; disallowed_STD3_mapped ; 0028 0072 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER R
+24AE ; disallowed_STD3_mapped ; 0028 0073 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER S
+24AF ; disallowed_STD3_mapped ; 0028 0074 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER T
+24B0 ; disallowed_STD3_mapped ; 0028 0075 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER U
+24B1 ; disallowed_STD3_mapped ; 0028 0076 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER V
+24B2 ; disallowed_STD3_mapped ; 0028 0077 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER W
+24B3 ; disallowed_STD3_mapped ; 0028 0078 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER X
+24B4 ; disallowed_STD3_mapped ; 0028 0079 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER Y
+24B5 ; disallowed_STD3_mapped ; 0028 007A 0029 #1.1 PARENTHESIZED LATIN SMALL LETTER Z
+24B6 ; mapped ; 0061 # 1.1 CIRCLED LATIN CAPITAL LETTER A
+24B7 ; mapped ; 0062 # 1.1 CIRCLED LATIN CAPITAL LETTER B
+24B8 ; mapped ; 0063 # 1.1 CIRCLED LATIN CAPITAL LETTER C
+24B9 ; mapped ; 0064 # 1.1 CIRCLED LATIN CAPITAL LETTER D
+24BA ; mapped ; 0065 # 1.1 CIRCLED LATIN CAPITAL LETTER E
+24BB ; mapped ; 0066 # 1.1 CIRCLED LATIN CAPITAL LETTER F
+24BC ; mapped ; 0067 # 1.1 CIRCLED LATIN CAPITAL LETTER G
+24BD ; mapped ; 0068 # 1.1 CIRCLED LATIN CAPITAL LETTER H
+24BE ; mapped ; 0069 # 1.1 CIRCLED LATIN CAPITAL LETTER I
+24BF ; mapped ; 006A # 1.1 CIRCLED LATIN CAPITAL LETTER J
+24C0 ; mapped ; 006B # 1.1 CIRCLED LATIN CAPITAL LETTER K
+24C1 ; mapped ; 006C # 1.1 CIRCLED LATIN CAPITAL LETTER L
+24C2 ; mapped ; 006D # 1.1 CIRCLED LATIN CAPITAL LETTER M
+24C3 ; mapped ; 006E # 1.1 CIRCLED LATIN CAPITAL LETTER N
+24C4 ; mapped ; 006F # 1.1 CIRCLED LATIN CAPITAL LETTER O
+24C5 ; mapped ; 0070 # 1.1 CIRCLED LATIN CAPITAL LETTER P
+24C6 ; mapped ; 0071 # 1.1 CIRCLED LATIN CAPITAL LETTER Q
+24C7 ; mapped ; 0072 # 1.1 CIRCLED LATIN CAPITAL LETTER R
+24C8 ; mapped ; 0073 # 1.1 CIRCLED LATIN CAPITAL LETTER S
+24C9 ; mapped ; 0074 # 1.1 CIRCLED LATIN CAPITAL LETTER T
+24CA ; mapped ; 0075 # 1.1 CIRCLED LATIN CAPITAL LETTER U
+24CB ; mapped ; 0076 # 1.1 CIRCLED LATIN CAPITAL LETTER V
+24CC ; mapped ; 0077 # 1.1 CIRCLED LATIN CAPITAL LETTER W
+24CD ; mapped ; 0078 # 1.1 CIRCLED LATIN CAPITAL LETTER X
+24CE ; mapped ; 0079 # 1.1 CIRCLED LATIN CAPITAL LETTER Y
+24CF ; mapped ; 007A # 1.1 CIRCLED LATIN CAPITAL LETTER Z
+24D0 ; mapped ; 0061 # 1.1 CIRCLED LATIN SMALL LETTER A
+24D1 ; mapped ; 0062 # 1.1 CIRCLED LATIN SMALL LETTER B
+24D2 ; mapped ; 0063 # 1.1 CIRCLED LATIN SMALL LETTER C
+24D3 ; mapped ; 0064 # 1.1 CIRCLED LATIN SMALL LETTER D
+24D4 ; mapped ; 0065 # 1.1 CIRCLED LATIN SMALL LETTER E
+24D5 ; mapped ; 0066 # 1.1 CIRCLED LATIN SMALL LETTER F
+24D6 ; mapped ; 0067 # 1.1 CIRCLED LATIN SMALL LETTER G
+24D7 ; mapped ; 0068 # 1.1 CIRCLED LATIN SMALL LETTER H
+24D8 ; mapped ; 0069 # 1.1 CIRCLED LATIN SMALL LETTER I
+24D9 ; mapped ; 006A # 1.1 CIRCLED LATIN SMALL LETTER J
+24DA ; mapped ; 006B # 1.1 CIRCLED LATIN SMALL LETTER K
+24DB ; mapped ; 006C # 1.1 CIRCLED LATIN SMALL LETTER L
+24DC ; mapped ; 006D # 1.1 CIRCLED LATIN SMALL LETTER M
+24DD ; mapped ; 006E # 1.1 CIRCLED LATIN SMALL LETTER N
+24DE ; mapped ; 006F # 1.1 CIRCLED LATIN SMALL LETTER O
+24DF ; mapped ; 0070 # 1.1 CIRCLED LATIN SMALL LETTER P
+24E0 ; mapped ; 0071 # 1.1 CIRCLED LATIN SMALL LETTER Q
+24E1 ; mapped ; 0072 # 1.1 CIRCLED LATIN SMALL LETTER R
+24E2 ; mapped ; 0073 # 1.1 CIRCLED LATIN SMALL LETTER S
+24E3 ; mapped ; 0074 # 1.1 CIRCLED LATIN SMALL LETTER T
+24E4 ; mapped ; 0075 # 1.1 CIRCLED LATIN SMALL LETTER U
+24E5 ; mapped ; 0076 # 1.1 CIRCLED LATIN SMALL LETTER V
+24E6 ; mapped ; 0077 # 1.1 CIRCLED LATIN SMALL LETTER W
+24E7 ; mapped ; 0078 # 1.1 CIRCLED LATIN SMALL LETTER X
+24E8 ; mapped ; 0079 # 1.1 CIRCLED LATIN SMALL LETTER Y
+24E9 ; mapped ; 007A # 1.1 CIRCLED LATIN SMALL LETTER Z
+24EA ; mapped ; 0030 # 1.1 CIRCLED DIGIT ZERO
+24EB..24FE ; valid ; ; NV8 # 3.2 NEGATIVE CIRCLED NUMBER ELEVEN..DOUBLE CIRCLED NUMBER TEN
+24FF ; valid ; ; NV8 # 4.0 NEGATIVE CIRCLED DIGIT ZERO
+2500..2595 ; valid ; ; NV8 # 1.1 BOX DRAWINGS LIGHT HORIZONTAL..RIGHT ONE EIGHTH BLOCK
+2596..259F ; valid ; ; NV8 # 3.2 QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
+25A0..25EF ; valid ; ; NV8 # 1.1 BLACK SQUARE..LARGE CIRCLE
+25F0..25F7 ; valid ; ; NV8 # 3.0 WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT
+25F8..25FF ; valid ; ; NV8 # 3.2 UPPER LEFT TRIANGLE..LOWER RIGHT TRIANGLE
+2600..2613 ; valid ; ; NV8 # 1.1 BLACK SUN WITH RAYS..SALTIRE
+2614..2615 ; valid ; ; NV8 # 4.0 UMBRELLA WITH RAIN DROPS..HOT BEVERAGE
+2616..2617 ; valid ; ; NV8 # 3.2 WHITE SHOGI PIECE..BLACK SHOGI PIECE
+2618 ; valid ; ; NV8 # 4.1 SHAMROCK
+2619 ; valid ; ; NV8 # 3.0 REVERSED ROTATED FLORAL HEART BULLET
+261A..266F ; valid ; ; NV8 # 1.1 BLACK LEFT POINTING INDEX..MUSIC SHARP SIGN
+2670..2671 ; valid ; ; NV8 # 3.0 WEST SYRIAC CROSS..EAST SYRIAC CROSS
+2672..267D ; valid ; ; NV8 # 3.2 UNIVERSAL RECYCLING SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL
+267E..267F ; valid ; ; NV8 # 4.1 PERMANENT PAPER SIGN..WHEELCHAIR SYMBOL
+2680..2689 ; valid ; ; NV8 # 3.2 DIE FACE-1..BLACK CIRCLE WITH TWO WHITE DOTS
+268A..2691 ; valid ; ; NV8 # 4.0 MONOGRAM FOR YANG..BLACK FLAG
+2692..269C ; valid ; ; NV8 # 4.1 HAMMER AND PICK..FLEUR-DE-LIS
+269D ; valid ; ; NV8 # 5.1 OUTLINED WHITE STAR
+269E..269F ; valid ; ; NV8 # 5.2 THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
+26A0..26A1 ; valid ; ; NV8 # 4.0 WARNING SIGN..HIGH VOLTAGE SIGN
+26A2..26B1 ; valid ; ; NV8 # 4.1 DOUBLED FEMALE SIGN..FUNERAL URN
+26B2 ; valid ; ; NV8 # 5.0 NEUTER
+26B3..26BC ; valid ; ; NV8 # 5.1 CERES..SESQUIQUADRATE
+26BD..26BF ; valid ; ; NV8 # 5.2 SOCCER BALL..SQUARED KEY
+26C0..26C3 ; valid ; ; NV8 # 5.1 WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
+26C4..26CD ; valid ; ; NV8 # 5.2 SNOWMAN WITHOUT SNOW..DISABLED CAR
+26CE ; valid ; ; NV8 # 6.0 OPHIUCHUS
+26CF..26E1 ; valid ; ; NV8 # 5.2 PICK..RESTRICTED LEFT ENTRY-2
+26E2 ; valid ; ; NV8 # 6.0 ASTRONOMICAL SYMBOL FOR URANUS
+26E3 ; valid ; ; NV8 # 5.2 HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
+26E4..26E7 ; valid ; ; NV8 # 6.0 PENTAGRAM..INVERTED PENTAGRAM
+26E8..26FF ; valid ; ; NV8 # 5.2 BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
+2700 ; valid ; ; NV8 # 7.0 BLACK SAFETY SCISSORS
+2701..2704 ; valid ; ; NV8 # 1.1 UPPER BLADE SCISSORS..WHITE SCISSORS
+2705 ; valid ; ; NV8 # 6.0 WHITE HEAVY CHECK MARK
+2706..2709 ; valid ; ; NV8 # 1.1 TELEPHONE LOCATION SIGN..ENVELOPE
+270A..270B ; valid ; ; NV8 # 6.0 RAISED FIST..RAISED HAND
+270C..2727 ; valid ; ; NV8 # 1.1 VICTORY HAND..WHITE FOUR POINTED STAR
+2728 ; valid ; ; NV8 # 6.0 SPARKLES
+2729..274B ; valid ; ; NV8 # 1.1 STRESS OUTLINED WHITE STAR..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274C ; valid ; ; NV8 # 6.0 CROSS MARK
+274D ; valid ; ; NV8 # 1.1 SHADOWED WHITE CIRCLE
+274E ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED CROSS MARK
+274F..2752 ; valid ; ; NV8 # 1.1 LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE
+2753..2755 ; valid ; ; NV8 # 6.0 BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT
+2756 ; valid ; ; NV8 # 1.1 BLACK DIAMOND MINUS WHITE X
+2757 ; valid ; ; NV8 # 5.2 HEAVY EXCLAMATION MARK SYMBOL
+2758..275E ; valid ; ; NV8 # 1.1 LIGHT VERTICAL BAR..HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
+275F..2760 ; valid ; ; NV8 # 6.0 HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT..HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT
+2761..2767 ; valid ; ; NV8 # 1.1 CURVED STEM PARAGRAPH SIGN ORNAMENT..ROTATED FLORAL HEART BULLET
+2768..2775 ; valid ; ; NV8 # 3.2 MEDIUM LEFT PARENTHESIS ORNAMENT..MEDIUM RIGHT CURLY BRACKET ORNAMENT
+2776..2794 ; valid ; ; NV8 # 1.1 DINGBAT NEGATIVE CIRCLED DIGIT ONE..HEAVY WIDE-HEADED RIGHTWARDS ARROW
+2795..2797 ; valid ; ; NV8 # 6.0 HEAVY PLUS SIGN..HEAVY DIVISION SIGN
+2798..27AF ; valid ; ; NV8 # 1.1 HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B0 ; valid ; ; NV8 # 6.0 CURLY LOOP
+27B1..27BE ; valid ; ; NV8 # 1.1 NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW
+27BF ; valid ; ; NV8 # 6.0 DOUBLE CURLY LOOP
+27C0..27C6 ; valid ; ; NV8 # 4.1 THREE DIMENSIONAL ANGLE..RIGHT S-SHAPED BAG DELIMITER
+27C7..27CA ; valid ; ; NV8 # 5.0 OR WITH DOT INSIDE..VERTICAL BAR WITH HORIZONTAL STROKE
+27CB ; valid ; ; NV8 # 6.1 MATHEMATICAL RISING DIAGONAL
+27CC ; valid ; ; NV8 # 5.1 LONG DIVISION
+27CD ; valid ; ; NV8 # 6.1 MATHEMATICAL FALLING DIAGONAL
+27CE..27CF ; valid ; ; NV8 # 6.0 SQUARED LOGICAL AND..SQUARED LOGICAL OR
+27D0..27EB ; valid ; ; NV8 # 3.2 WHITE DIAMOND WITH CENTRED DOT..MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+27EC..27EF ; valid ; ; NV8 # 5.1 MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET..MATHEMATICAL RIGHT FLATTENED PARENTHESIS
+27F0..27FF ; valid ; ; NV8 # 3.2 UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW
+2800..28FF ; valid ; ; NV8 # 3.0 BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678
+2900..2A0B ; valid ; ; NV8 # 3.2 RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..SUMMATION WITH INTEGRAL
+2A0C ; mapped ; 222B 222B 222B 222B #3.2 QUADRUPLE INTEGRAL OPERATOR
+2A0D..2A73 ; valid ; ; NV8 # 3.2 FINITE PART INTEGRAL..EQUALS SIGN ABOVE TILDE OPERATOR
+2A74 ; disallowed_STD3_mapped ; 003A 003A 003D #3.2 DOUBLE COLON EQUAL
+2A75 ; disallowed_STD3_mapped ; 003D 003D # 3.2 TWO CONSECUTIVE EQUALS SIGNS
+2A76 ; disallowed_STD3_mapped ; 003D 003D 003D #3.2 THREE CONSECUTIVE EQUALS SIGNS
+2A77..2ADB ; valid ; ; NV8 # 3.2 EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW..TRANSVERSAL INTERSECTION
+2ADC ; mapped ; 2ADD 0338 # 3.2 FORKING
+2ADD..2AFF ; valid ; ; NV8 # 3.2 NONFORKING..N-ARY WHITE VERTICAL BAR
+2B00..2B0D ; valid ; ; NV8 # 4.0 NORTH EAST WHITE ARROW..UP DOWN BLACK ARROW
+2B0E..2B13 ; valid ; ; NV8 # 4.1 RIGHTWARDS ARROW WITH TIP DOWNWARDS..SQUARE WITH BOTTOM HALF BLACK
+2B14..2B1A ; valid ; ; NV8 # 5.0 SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK..DOTTED SQUARE
+2B1B..2B1F ; valid ; ; NV8 # 5.1 BLACK LARGE SQUARE..BLACK PENTAGON
+2B20..2B23 ; valid ; ; NV8 # 5.0 WHITE PENTAGON..HORIZONTAL BLACK HEXAGON
+2B24..2B4C ; valid ; ; NV8 # 5.1 BLACK LARGE CIRCLE..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
+2B4D..2B4F ; valid ; ; NV8 # 7.0 DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..SHORT BACKSLANTED SOUTH ARROW
+2B50..2B54 ; valid ; ; NV8 # 5.1 WHITE MEDIUM STAR..WHITE RIGHT-POINTING PENTAGON
+2B55..2B59 ; valid ; ; NV8 # 5.2 HEAVY LARGE CIRCLE..HEAVY CIRCLED SALTIRE
+2B5A..2B73 ; valid ; ; NV8 # 7.0 SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
+2B74..2B75 ; disallowed # NA <reserved-2B74>..<reserved-2B75>
+2B76..2B95 ; valid ; ; NV8 # 7.0 NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
+2B96 ; disallowed # NA <reserved-2B96>
+2B97 ; valid ; ; NV8 # 13.0 SYMBOL FOR TYPE A ELECTRONICS
+2B98..2BB9 ; valid ; ; NV8 # 7.0 THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX
+2BBA..2BBC ; valid ; ; NV8 # 11.0 OVERLAPPING WHITE SQUARES..OVERLAPPING BLACK SQUARES
+2BBD..2BC8 ; valid ; ; NV8 # 7.0 BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
+2BC9 ; valid ; ; NV8 # 12.0 NEPTUNE FORM TWO
+2BCA..2BD1 ; valid ; ; NV8 # 7.0 TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
+2BD2 ; valid ; ; NV8 # 10.0 GROUP MARK
+2BD3..2BEB ; valid ; ; NV8 # 11.0 PLUTO FORM TWO..STAR WITH RIGHT HALF BLACK
+2BEC..2BEF ; valid ; ; NV8 # 8.0 LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
+2BF0..2BFE ; valid ; ; NV8 # 11.0 ERIS FORM ONE..REVERSED RIGHT ANGLE
+2BFF ; valid ; ; NV8 # 12.0 HELLSCHREIBER PAUSE SYMBOL
+2C00 ; mapped ; 2C30 # 4.1 GLAGOLITIC CAPITAL LETTER AZU
+2C01 ; mapped ; 2C31 # 4.1 GLAGOLITIC CAPITAL LETTER BUKY
+2C02 ; mapped ; 2C32 # 4.1 GLAGOLITIC CAPITAL LETTER VEDE
+2C03 ; mapped ; 2C33 # 4.1 GLAGOLITIC CAPITAL LETTER GLAGOLI
+2C04 ; mapped ; 2C34 # 4.1 GLAGOLITIC CAPITAL LETTER DOBRO
+2C05 ; mapped ; 2C35 # 4.1 GLAGOLITIC CAPITAL LETTER YESTU
+2C06 ; mapped ; 2C36 # 4.1 GLAGOLITIC CAPITAL LETTER ZHIVETE
+2C07 ; mapped ; 2C37 # 4.1 GLAGOLITIC CAPITAL LETTER DZELO
+2C08 ; mapped ; 2C38 # 4.1 GLAGOLITIC CAPITAL LETTER ZEMLJA
+2C09 ; mapped ; 2C39 # 4.1 GLAGOLITIC CAPITAL LETTER IZHE
+2C0A ; mapped ; 2C3A # 4.1 GLAGOLITIC CAPITAL LETTER INITIAL IZHE
+2C0B ; mapped ; 2C3B # 4.1 GLAGOLITIC CAPITAL LETTER I
+2C0C ; mapped ; 2C3C # 4.1 GLAGOLITIC CAPITAL LETTER DJERVI
+2C0D ; mapped ; 2C3D # 4.1 GLAGOLITIC CAPITAL LETTER KAKO
+2C0E ; mapped ; 2C3E # 4.1 GLAGOLITIC CAPITAL LETTER LJUDIJE
+2C0F ; mapped ; 2C3F # 4.1 GLAGOLITIC CAPITAL LETTER MYSLITE
+2C10 ; mapped ; 2C40 # 4.1 GLAGOLITIC CAPITAL LETTER NASHI
+2C11 ; mapped ; 2C41 # 4.1 GLAGOLITIC CAPITAL LETTER ONU
+2C12 ; mapped ; 2C42 # 4.1 GLAGOLITIC CAPITAL LETTER POKOJI
+2C13 ; mapped ; 2C43 # 4.1 GLAGOLITIC CAPITAL LETTER RITSI
+2C14 ; mapped ; 2C44 # 4.1 GLAGOLITIC CAPITAL LETTER SLOVO
+2C15 ; mapped ; 2C45 # 4.1 GLAGOLITIC CAPITAL LETTER TVRIDO
+2C16 ; mapped ; 2C46 # 4.1 GLAGOLITIC CAPITAL LETTER UKU
+2C17 ; mapped ; 2C47 # 4.1 GLAGOLITIC CAPITAL LETTER FRITU
+2C18 ; mapped ; 2C48 # 4.1 GLAGOLITIC CAPITAL LETTER HERU
+2C19 ; mapped ; 2C49 # 4.1 GLAGOLITIC CAPITAL LETTER OTU
+2C1A ; mapped ; 2C4A # 4.1 GLAGOLITIC CAPITAL LETTER PE
+2C1B ; mapped ; 2C4B # 4.1 GLAGOLITIC CAPITAL LETTER SHTA
+2C1C ; mapped ; 2C4C # 4.1 GLAGOLITIC CAPITAL LETTER TSI
+2C1D ; mapped ; 2C4D # 4.1 GLAGOLITIC CAPITAL LETTER CHRIVI
+2C1E ; mapped ; 2C4E # 4.1 GLAGOLITIC CAPITAL LETTER SHA
+2C1F ; mapped ; 2C4F # 4.1 GLAGOLITIC CAPITAL LETTER YERU
+2C20 ; mapped ; 2C50 # 4.1 GLAGOLITIC CAPITAL LETTER YERI
+2C21 ; mapped ; 2C51 # 4.1 GLAGOLITIC CAPITAL LETTER YATI
+2C22 ; mapped ; 2C52 # 4.1 GLAGOLITIC CAPITAL LETTER SPIDERY HA
+2C23 ; mapped ; 2C53 # 4.1 GLAGOLITIC CAPITAL LETTER YU
+2C24 ; mapped ; 2C54 # 4.1 GLAGOLITIC CAPITAL LETTER SMALL YUS
+2C25 ; mapped ; 2C55 # 4.1 GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL
+2C26 ; mapped ; 2C56 # 4.1 GLAGOLITIC CAPITAL LETTER YO
+2C27 ; mapped ; 2C57 # 4.1 GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS
+2C28 ; mapped ; 2C58 # 4.1 GLAGOLITIC CAPITAL LETTER BIG YUS
+2C29 ; mapped ; 2C59 # 4.1 GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS
+2C2A ; mapped ; 2C5A # 4.1 GLAGOLITIC CAPITAL LETTER FITA
+2C2B ; mapped ; 2C5B # 4.1 GLAGOLITIC CAPITAL LETTER IZHITSA
+2C2C ; mapped ; 2C5C # 4.1 GLAGOLITIC CAPITAL LETTER SHTAPIC
+2C2D ; mapped ; 2C5D # 4.1 GLAGOLITIC CAPITAL LETTER TROKUTASTI A
+2C2E ; mapped ; 2C5E # 4.1 GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
+2C2F ; mapped ; 2C5F # 14.0 GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI
+2C30..2C5E ; valid # 4.1 GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE
+2C5F ; valid # 14.0 GLAGOLITIC SMALL LETTER CAUDATE CHRIVI
+2C60 ; mapped ; 2C61 # 5.0 LATIN CAPITAL LETTER L WITH DOUBLE BAR
+2C61 ; valid # 5.0 LATIN SMALL LETTER L WITH DOUBLE BAR
+2C62 ; mapped ; 026B # 5.0 LATIN CAPITAL LETTER L WITH MIDDLE TILDE
+2C63 ; mapped ; 1D7D # 5.0 LATIN CAPITAL LETTER P WITH STROKE
+2C64 ; mapped ; 027D # 5.0 LATIN CAPITAL LETTER R WITH TAIL
+2C65..2C66 ; valid # 5.0 LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE
+2C67 ; mapped ; 2C68 # 5.0 LATIN CAPITAL LETTER H WITH DESCENDER
+2C68 ; valid # 5.0 LATIN SMALL LETTER H WITH DESCENDER
+2C69 ; mapped ; 2C6A # 5.0 LATIN CAPITAL LETTER K WITH DESCENDER
+2C6A ; valid # 5.0 LATIN SMALL LETTER K WITH DESCENDER
+2C6B ; mapped ; 2C6C # 5.0 LATIN CAPITAL LETTER Z WITH DESCENDER
+2C6C ; valid # 5.0 LATIN SMALL LETTER Z WITH DESCENDER
+2C6D ; mapped ; 0251 # 5.1 LATIN CAPITAL LETTER ALPHA
+2C6E ; mapped ; 0271 # 5.1 LATIN CAPITAL LETTER M WITH HOOK
+2C6F ; mapped ; 0250 # 5.1 LATIN CAPITAL LETTER TURNED A
+2C70 ; mapped ; 0252 # 5.2 LATIN CAPITAL LETTER TURNED ALPHA
+2C71 ; valid # 5.1 LATIN SMALL LETTER V WITH RIGHT HOOK
+2C72 ; mapped ; 2C73 # 5.1 LATIN CAPITAL LETTER W WITH HOOK
+2C73 ; valid # 5.1 LATIN SMALL LETTER W WITH HOOK
+2C74 ; valid # 5.0 LATIN SMALL LETTER V WITH CURL
+2C75 ; mapped ; 2C76 # 5.0 LATIN CAPITAL LETTER HALF H
+2C76..2C77 ; valid # 5.0 LATIN SMALL LETTER HALF H..LATIN SMALL LETTER TAILLESS PHI
+2C78..2C7B ; valid # 5.1 LATIN SMALL LETTER E WITH NOTCH..LATIN LETTER SMALL CAPITAL TURNED E
+2C7C ; mapped ; 006A # 5.1 LATIN SUBSCRIPT SMALL LETTER J
+2C7D ; mapped ; 0076 # 5.1 MODIFIER LETTER CAPITAL V
+2C7E ; mapped ; 023F # 5.2 LATIN CAPITAL LETTER S WITH SWASH TAIL
+2C7F ; mapped ; 0240 # 5.2 LATIN CAPITAL LETTER Z WITH SWASH TAIL
+2C80 ; mapped ; 2C81 # 4.1 COPTIC CAPITAL LETTER ALFA
+2C81 ; valid # 4.1 COPTIC SMALL LETTER ALFA
+2C82 ; mapped ; 2C83 # 4.1 COPTIC CAPITAL LETTER VIDA
+2C83 ; valid # 4.1 COPTIC SMALL LETTER VIDA
+2C84 ; mapped ; 2C85 # 4.1 COPTIC CAPITAL LETTER GAMMA
+2C85 ; valid # 4.1 COPTIC SMALL LETTER GAMMA
+2C86 ; mapped ; 2C87 # 4.1 COPTIC CAPITAL LETTER DALDA
+2C87 ; valid # 4.1 COPTIC SMALL LETTER DALDA
+2C88 ; mapped ; 2C89 # 4.1 COPTIC CAPITAL LETTER EIE
+2C89 ; valid # 4.1 COPTIC SMALL LETTER EIE
+2C8A ; mapped ; 2C8B # 4.1 COPTIC CAPITAL LETTER SOU
+2C8B ; valid # 4.1 COPTIC SMALL LETTER SOU
+2C8C ; mapped ; 2C8D # 4.1 COPTIC CAPITAL LETTER ZATA
+2C8D ; valid # 4.1 COPTIC SMALL LETTER ZATA
+2C8E ; mapped ; 2C8F # 4.1 COPTIC CAPITAL LETTER HATE
+2C8F ; valid # 4.1 COPTIC SMALL LETTER HATE
+2C90 ; mapped ; 2C91 # 4.1 COPTIC CAPITAL LETTER THETHE
+2C91 ; valid # 4.1 COPTIC SMALL LETTER THETHE
+2C92 ; mapped ; 2C93 # 4.1 COPTIC CAPITAL LETTER IAUDA
+2C93 ; valid # 4.1 COPTIC SMALL LETTER IAUDA
+2C94 ; mapped ; 2C95 # 4.1 COPTIC CAPITAL LETTER KAPA
+2C95 ; valid # 4.1 COPTIC SMALL LETTER KAPA
+2C96 ; mapped ; 2C97 # 4.1 COPTIC CAPITAL LETTER LAULA
+2C97 ; valid # 4.1 COPTIC SMALL LETTER LAULA
+2C98 ; mapped ; 2C99 # 4.1 COPTIC CAPITAL LETTER MI
+2C99 ; valid # 4.1 COPTIC SMALL LETTER MI
+2C9A ; mapped ; 2C9B # 4.1 COPTIC CAPITAL LETTER NI
+2C9B ; valid # 4.1 COPTIC SMALL LETTER NI
+2C9C ; mapped ; 2C9D # 4.1 COPTIC CAPITAL LETTER KSI
+2C9D ; valid # 4.1 COPTIC SMALL LETTER KSI
+2C9E ; mapped ; 2C9F # 4.1 COPTIC CAPITAL LETTER O
+2C9F ; valid # 4.1 COPTIC SMALL LETTER O
+2CA0 ; mapped ; 2CA1 # 4.1 COPTIC CAPITAL LETTER PI
+2CA1 ; valid # 4.1 COPTIC SMALL LETTER PI
+2CA2 ; mapped ; 2CA3 # 4.1 COPTIC CAPITAL LETTER RO
+2CA3 ; valid # 4.1 COPTIC SMALL LETTER RO
+2CA4 ; mapped ; 2CA5 # 4.1 COPTIC CAPITAL LETTER SIMA
+2CA5 ; valid # 4.1 COPTIC SMALL LETTER SIMA
+2CA6 ; mapped ; 2CA7 # 4.1 COPTIC CAPITAL LETTER TAU
+2CA7 ; valid # 4.1 COPTIC SMALL LETTER TAU
+2CA8 ; mapped ; 2CA9 # 4.1 COPTIC CAPITAL LETTER UA
+2CA9 ; valid # 4.1 COPTIC SMALL LETTER UA
+2CAA ; mapped ; 2CAB # 4.1 COPTIC CAPITAL LETTER FI
+2CAB ; valid # 4.1 COPTIC SMALL LETTER FI
+2CAC ; mapped ; 2CAD # 4.1 COPTIC CAPITAL LETTER KHI
+2CAD ; valid # 4.1 COPTIC SMALL LETTER KHI
+2CAE ; mapped ; 2CAF # 4.1 COPTIC CAPITAL LETTER PSI
+2CAF ; valid # 4.1 COPTIC SMALL LETTER PSI
+2CB0 ; mapped ; 2CB1 # 4.1 COPTIC CAPITAL LETTER OOU
+2CB1 ; valid # 4.1 COPTIC SMALL LETTER OOU
+2CB2 ; mapped ; 2CB3 # 4.1 COPTIC CAPITAL LETTER DIALECT-P ALEF
+2CB3 ; valid # 4.1 COPTIC SMALL LETTER DIALECT-P ALEF
+2CB4 ; mapped ; 2CB5 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC AIN
+2CB5 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC AIN
+2CB6 ; mapped ; 2CB7 # 4.1 COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
+2CB7 ; valid # 4.1 COPTIC SMALL LETTER CRYPTOGRAMMIC EIE
+2CB8 ; mapped ; 2CB9 # 4.1 COPTIC CAPITAL LETTER DIALECT-P KAPA
+2CB9 ; valid # 4.1 COPTIC SMALL LETTER DIALECT-P KAPA
+2CBA ; mapped ; 2CBB # 4.1 COPTIC CAPITAL LETTER DIALECT-P NI
+2CBB ; valid # 4.1 COPTIC SMALL LETTER DIALECT-P NI
+2CBC ; mapped ; 2CBD # 4.1 COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
+2CBD ; valid # 4.1 COPTIC SMALL LETTER CRYPTOGRAMMIC NI
+2CBE ; mapped ; 2CBF # 4.1 COPTIC CAPITAL LETTER OLD COPTIC OOU
+2CBF ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC OOU
+2CC0 ; mapped ; 2CC1 # 4.1 COPTIC CAPITAL LETTER SAMPI
+2CC1 ; valid # 4.1 COPTIC SMALL LETTER SAMPI
+2CC2 ; mapped ; 2CC3 # 4.1 COPTIC CAPITAL LETTER CROSSED SHEI
+2CC3 ; valid # 4.1 COPTIC SMALL LETTER CROSSED SHEI
+2CC4 ; mapped ; 2CC5 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC SHEI
+2CC5 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC SHEI
+2CC6 ; mapped ; 2CC7 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC ESH
+2CC7 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC ESH
+2CC8 ; mapped ; 2CC9 # 4.1 COPTIC CAPITAL LETTER AKHMIMIC KHEI
+2CC9 ; valid # 4.1 COPTIC SMALL LETTER AKHMIMIC KHEI
+2CCA ; mapped ; 2CCB # 4.1 COPTIC CAPITAL LETTER DIALECT-P HORI
+2CCB ; valid # 4.1 COPTIC SMALL LETTER DIALECT-P HORI
+2CCC ; mapped ; 2CCD # 4.1 COPTIC CAPITAL LETTER OLD COPTIC HORI
+2CCD ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC HORI
+2CCE ; mapped ; 2CCF # 4.1 COPTIC CAPITAL LETTER OLD COPTIC HA
+2CCF ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC HA
+2CD0 ; mapped ; 2CD1 # 4.1 COPTIC CAPITAL LETTER L-SHAPED HA
+2CD1 ; valid # 4.1 COPTIC SMALL LETTER L-SHAPED HA
+2CD2 ; mapped ; 2CD3 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC HEI
+2CD3 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC HEI
+2CD4 ; mapped ; 2CD5 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC HAT
+2CD5 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC HAT
+2CD6 ; mapped ; 2CD7 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC GANGIA
+2CD7 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC GANGIA
+2CD8 ; mapped ; 2CD9 # 4.1 COPTIC CAPITAL LETTER OLD COPTIC DJA
+2CD9 ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC DJA
+2CDA ; mapped ; 2CDB # 4.1 COPTIC CAPITAL LETTER OLD COPTIC SHIMA
+2CDB ; valid # 4.1 COPTIC SMALL LETTER OLD COPTIC SHIMA
+2CDC ; mapped ; 2CDD # 4.1 COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
+2CDD ; valid # 4.1 COPTIC SMALL LETTER OLD NUBIAN SHIMA
+2CDE ; mapped ; 2CDF # 4.1 COPTIC CAPITAL LETTER OLD NUBIAN NGI
+2CDF ; valid # 4.1 COPTIC SMALL LETTER OLD NUBIAN NGI
+2CE0 ; mapped ; 2CE1 # 4.1 COPTIC CAPITAL LETTER OLD NUBIAN NYI
+2CE1 ; valid # 4.1 COPTIC SMALL LETTER OLD NUBIAN NYI
+2CE2 ; mapped ; 2CE3 # 4.1 COPTIC CAPITAL LETTER OLD NUBIAN WAU
+2CE3..2CE4 ; valid # 4.1 COPTIC SMALL LETTER OLD NUBIAN WAU..COPTIC SYMBOL KAI
+2CE5..2CEA ; valid ; ; NV8 # 4.1 COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA
+2CEB ; mapped ; 2CEC # 5.2 COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
+2CEC ; valid # 5.2 COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI
+2CED ; mapped ; 2CEE # 5.2 COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
+2CEE..2CF1 ; valid # 5.2 COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA..COPTIC COMBINING SPIRITUS LENIS
+2CF2 ; mapped ; 2CF3 # 6.1 COPTIC CAPITAL LETTER BOHAIRIC KHEI
+2CF3 ; valid # 6.1 COPTIC SMALL LETTER BOHAIRIC KHEI
+2CF4..2CF8 ; disallowed # NA <reserved-2CF4>..<reserved-2CF8>
+2CF9..2CFF ; valid ; ; NV8 # 4.1 COPTIC OLD NUBIAN FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
+2D00..2D25 ; valid # 4.1 GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
+2D26 ; disallowed # NA <reserved-2D26>
+2D27 ; valid # 6.1 GEORGIAN SMALL LETTER YN
+2D28..2D2C ; disallowed # NA <reserved-2D28>..<reserved-2D2C>
+2D2D ; valid # 6.1 GEORGIAN SMALL LETTER AEN
+2D2E..2D2F ; disallowed # NA <reserved-2D2E>..<reserved-2D2F>
+2D30..2D65 ; valid # 4.1 TIFINAGH LETTER YA..TIFINAGH LETTER YAZZ
+2D66..2D67 ; valid # 6.1 TIFINAGH LETTER YE..TIFINAGH LETTER YO
+2D68..2D6E ; disallowed # NA <reserved-2D68>..<reserved-2D6E>
+2D6F ; mapped ; 2D61 # 4.1 TIFINAGH MODIFIER LETTER LABIALIZATION MARK
+2D70 ; valid ; ; NV8 # 6.0 TIFINAGH SEPARATOR MARK
+2D71..2D7E ; disallowed # NA <reserved-2D71>..<reserved-2D7E>
+2D7F ; valid # 6.0 TIFINAGH CONSONANT JOINER
+2D80..2D96 ; valid # 4.1 ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
+2D97..2D9F ; disallowed # NA <reserved-2D97>..<reserved-2D9F>
+2DA0..2DA6 ; valid # 4.1 ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
+2DA7 ; disallowed # NA <reserved-2DA7>
+2DA8..2DAE ; valid # 4.1 ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
+2DAF ; disallowed # NA <reserved-2DAF>
+2DB0..2DB6 ; valid # 4.1 ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
+2DB7 ; disallowed # NA <reserved-2DB7>
+2DB8..2DBE ; valid # 4.1 ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
+2DBF ; disallowed # NA <reserved-2DBF>
+2DC0..2DC6 ; valid # 4.1 ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
+2DC7 ; disallowed # NA <reserved-2DC7>
+2DC8..2DCE ; valid # 4.1 ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
+2DCF ; disallowed # NA <reserved-2DCF>
+2DD0..2DD6 ; valid # 4.1 ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
+2DD7 ; disallowed # NA <reserved-2DD7>
+2DD8..2DDE ; valid # 4.1 ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
+2DDF ; disallowed # NA <reserved-2DDF>
+2DE0..2DFF ; valid # 5.1 COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
+2E00..2E17 ; valid ; ; NV8 # 4.1 RIGHT ANGLE SUBSTITUTION MARKER..DOUBLE OBLIQUE HYPHEN
+2E18..2E1B ; valid ; ; NV8 # 5.1 INVERTED INTERROBANG..TILDE WITH RING ABOVE
+2E1C..2E1D ; valid ; ; NV8 # 4.1 LEFT LOW PARAPHRASE BRACKET..RIGHT LOW PARAPHRASE BRACKET
+2E1E..2E2E ; valid ; ; NV8 # 5.1 TILDE WITH DOT ABOVE..REVERSED QUESTION MARK
+2E2F ; valid # 5.1 VERTICAL TILDE
+2E30 ; valid ; ; NV8 # 5.1 RING POINT
+2E31 ; valid ; ; NV8 # 5.2 WORD SEPARATOR MIDDLE DOT
+2E32..2E3B ; valid ; ; NV8 # 6.1 TURNED COMMA..THREE-EM DASH
+2E3C..2E42 ; valid ; ; NV8 # 7.0 STENOGRAPHIC FULL STOP..DOUBLE LOW-REVERSED-9 QUOTATION MARK
+2E43..2E44 ; valid ; ; NV8 # 9.0 DASH WITH LEFT UPTURN..DOUBLE SUSPENSION MARK
+2E45..2E49 ; valid ; ; NV8 # 10.0 INVERTED LOW KAVYKA..DOUBLE STACKED COMMA
+2E4A..2E4E ; valid ; ; NV8 # 11.0 DOTTED SOLIDUS..PUNCTUS ELEVATUS MARK
+2E4F ; valid ; ; NV8 # 12.0 CORNISH VERSE DIVIDER
+2E50..2E52 ; valid ; ; NV8 # 13.0 CROSS PATTY WITH RIGHT CROSSBAR..TIRONIAN SIGN CAPITAL ET
+2E53..2E5D ; valid ; ; NV8 # 14.0 MEDIEVAL EXCLAMATION MARK..OBLIQUE HYPHEN
+2E5E..2E7F ; disallowed # NA <reserved-2E5E>..<reserved-2E7F>
+2E80..2E99 ; valid ; ; NV8 # 3.0 CJK RADICAL REPEAT..CJK RADICAL RAP
+2E9A ; disallowed # NA <reserved-2E9A>
+2E9B..2E9E ; valid ; ; NV8 # 3.0 CJK RADICAL CHOKE..CJK RADICAL DEATH
+2E9F ; mapped ; 6BCD # 3.0 CJK RADICAL MOTHER
+2EA0..2EF2 ; valid ; ; NV8 # 3.0 CJK RADICAL CIVILIAN..CJK RADICAL J-SIMPLIFIED TURTLE
+2EF3 ; mapped ; 9F9F # 3.0 CJK RADICAL C-SIMPLIFIED TURTLE
+2EF4..2EFF ; disallowed # NA <reserved-2EF4>..<reserved-2EFF>
+2F00 ; mapped ; 4E00 # 3.0 KANGXI RADICAL ONE
+2F01 ; mapped ; 4E28 # 3.0 KANGXI RADICAL LINE
+2F02 ; mapped ; 4E36 # 3.0 KANGXI RADICAL DOT
+2F03 ; mapped ; 4E3F # 3.0 KANGXI RADICAL SLASH
+2F04 ; mapped ; 4E59 # 3.0 KANGXI RADICAL SECOND
+2F05 ; mapped ; 4E85 # 3.0 KANGXI RADICAL HOOK
+2F06 ; mapped ; 4E8C # 3.0 KANGXI RADICAL TWO
+2F07 ; mapped ; 4EA0 # 3.0 KANGXI RADICAL LID
+2F08 ; mapped ; 4EBA # 3.0 KANGXI RADICAL MAN
+2F09 ; mapped ; 513F # 3.0 KANGXI RADICAL LEGS
+2F0A ; mapped ; 5165 # 3.0 KANGXI RADICAL ENTER
+2F0B ; mapped ; 516B # 3.0 KANGXI RADICAL EIGHT
+2F0C ; mapped ; 5182 # 3.0 KANGXI RADICAL DOWN BOX
+2F0D ; mapped ; 5196 # 3.0 KANGXI RADICAL COVER
+2F0E ; mapped ; 51AB # 3.0 KANGXI RADICAL ICE
+2F0F ; mapped ; 51E0 # 3.0 KANGXI RADICAL TABLE
+2F10 ; mapped ; 51F5 # 3.0 KANGXI RADICAL OPEN BOX
+2F11 ; mapped ; 5200 # 3.0 KANGXI RADICAL KNIFE
+2F12 ; mapped ; 529B # 3.0 KANGXI RADICAL POWER
+2F13 ; mapped ; 52F9 # 3.0 KANGXI RADICAL WRAP
+2F14 ; mapped ; 5315 # 3.0 KANGXI RADICAL SPOON
+2F15 ; mapped ; 531A # 3.0 KANGXI RADICAL RIGHT OPEN BOX
+2F16 ; mapped ; 5338 # 3.0 KANGXI RADICAL HIDING ENCLOSURE
+2F17 ; mapped ; 5341 # 3.0 KANGXI RADICAL TEN
+2F18 ; mapped ; 535C # 3.0 KANGXI RADICAL DIVINATION
+2F19 ; mapped ; 5369 # 3.0 KANGXI RADICAL SEAL
+2F1A ; mapped ; 5382 # 3.0 KANGXI RADICAL CLIFF
+2F1B ; mapped ; 53B6 # 3.0 KANGXI RADICAL PRIVATE
+2F1C ; mapped ; 53C8 # 3.0 KANGXI RADICAL AGAIN
+2F1D ; mapped ; 53E3 # 3.0 KANGXI RADICAL MOUTH
+2F1E ; mapped ; 56D7 # 3.0 KANGXI RADICAL ENCLOSURE
+2F1F ; mapped ; 571F # 3.0 KANGXI RADICAL EARTH
+2F20 ; mapped ; 58EB # 3.0 KANGXI RADICAL SCHOLAR
+2F21 ; mapped ; 5902 # 3.0 KANGXI RADICAL GO
+2F22 ; mapped ; 590A # 3.0 KANGXI RADICAL GO SLOWLY
+2F23 ; mapped ; 5915 # 3.0 KANGXI RADICAL EVENING
+2F24 ; mapped ; 5927 # 3.0 KANGXI RADICAL BIG
+2F25 ; mapped ; 5973 # 3.0 KANGXI RADICAL WOMAN
+2F26 ; mapped ; 5B50 # 3.0 KANGXI RADICAL CHILD
+2F27 ; mapped ; 5B80 # 3.0 KANGXI RADICAL ROOF
+2F28 ; mapped ; 5BF8 # 3.0 KANGXI RADICAL INCH
+2F29 ; mapped ; 5C0F # 3.0 KANGXI RADICAL SMALL
+2F2A ; mapped ; 5C22 # 3.0 KANGXI RADICAL LAME
+2F2B ; mapped ; 5C38 # 3.0 KANGXI RADICAL CORPSE
+2F2C ; mapped ; 5C6E # 3.0 KANGXI RADICAL SPROUT
+2F2D ; mapped ; 5C71 # 3.0 KANGXI RADICAL MOUNTAIN
+2F2E ; mapped ; 5DDB # 3.0 KANGXI RADICAL RIVER
+2F2F ; mapped ; 5DE5 # 3.0 KANGXI RADICAL WORK
+2F30 ; mapped ; 5DF1 # 3.0 KANGXI RADICAL ONESELF
+2F31 ; mapped ; 5DFE # 3.0 KANGXI RADICAL TURBAN
+2F32 ; mapped ; 5E72 # 3.0 KANGXI RADICAL DRY
+2F33 ; mapped ; 5E7A # 3.0 KANGXI RADICAL SHORT THREAD
+2F34 ; mapped ; 5E7F # 3.0 KANGXI RADICAL DOTTED CLIFF
+2F35 ; mapped ; 5EF4 # 3.0 KANGXI RADICAL LONG STRIDE
+2F36 ; mapped ; 5EFE # 3.0 KANGXI RADICAL TWO HANDS
+2F37 ; mapped ; 5F0B # 3.0 KANGXI RADICAL SHOOT
+2F38 ; mapped ; 5F13 # 3.0 KANGXI RADICAL BOW
+2F39 ; mapped ; 5F50 # 3.0 KANGXI RADICAL SNOUT
+2F3A ; mapped ; 5F61 # 3.0 KANGXI RADICAL BRISTLE
+2F3B ; mapped ; 5F73 # 3.0 KANGXI RADICAL STEP
+2F3C ; mapped ; 5FC3 # 3.0 KANGXI RADICAL HEART
+2F3D ; mapped ; 6208 # 3.0 KANGXI RADICAL HALBERD
+2F3E ; mapped ; 6236 # 3.0 KANGXI RADICAL DOOR
+2F3F ; mapped ; 624B # 3.0 KANGXI RADICAL HAND
+2F40 ; mapped ; 652F # 3.0 KANGXI RADICAL BRANCH
+2F41 ; mapped ; 6534 # 3.0 KANGXI RADICAL RAP
+2F42 ; mapped ; 6587 # 3.0 KANGXI RADICAL SCRIPT
+2F43 ; mapped ; 6597 # 3.0 KANGXI RADICAL DIPPER
+2F44 ; mapped ; 65A4 # 3.0 KANGXI RADICAL AXE
+2F45 ; mapped ; 65B9 # 3.0 KANGXI RADICAL SQUARE
+2F46 ; mapped ; 65E0 # 3.0 KANGXI RADICAL NOT
+2F47 ; mapped ; 65E5 # 3.0 KANGXI RADICAL SUN
+2F48 ; mapped ; 66F0 # 3.0 KANGXI RADICAL SAY
+2F49 ; mapped ; 6708 # 3.0 KANGXI RADICAL MOON
+2F4A ; mapped ; 6728 # 3.0 KANGXI RADICAL TREE
+2F4B ; mapped ; 6B20 # 3.0 KANGXI RADICAL LACK
+2F4C ; mapped ; 6B62 # 3.0 KANGXI RADICAL STOP
+2F4D ; mapped ; 6B79 # 3.0 KANGXI RADICAL DEATH
+2F4E ; mapped ; 6BB3 # 3.0 KANGXI RADICAL WEAPON
+2F4F ; mapped ; 6BCB # 3.0 KANGXI RADICAL DO NOT
+2F50 ; mapped ; 6BD4 # 3.0 KANGXI RADICAL COMPARE
+2F51 ; mapped ; 6BDB # 3.0 KANGXI RADICAL FUR
+2F52 ; mapped ; 6C0F # 3.0 KANGXI RADICAL CLAN
+2F53 ; mapped ; 6C14 # 3.0 KANGXI RADICAL STEAM
+2F54 ; mapped ; 6C34 # 3.0 KANGXI RADICAL WATER
+2F55 ; mapped ; 706B # 3.0 KANGXI RADICAL FIRE
+2F56 ; mapped ; 722A # 3.0 KANGXI RADICAL CLAW
+2F57 ; mapped ; 7236 # 3.0 KANGXI RADICAL FATHER
+2F58 ; mapped ; 723B # 3.0 KANGXI RADICAL DOUBLE X
+2F59 ; mapped ; 723F # 3.0 KANGXI RADICAL HALF TREE TRUNK
+2F5A ; mapped ; 7247 # 3.0 KANGXI RADICAL SLICE
+2F5B ; mapped ; 7259 # 3.0 KANGXI RADICAL FANG
+2F5C ; mapped ; 725B # 3.0 KANGXI RADICAL COW
+2F5D ; mapped ; 72AC # 3.0 KANGXI RADICAL DOG
+2F5E ; mapped ; 7384 # 3.0 KANGXI RADICAL PROFOUND
+2F5F ; mapped ; 7389 # 3.0 KANGXI RADICAL JADE
+2F60 ; mapped ; 74DC # 3.0 KANGXI RADICAL MELON
+2F61 ; mapped ; 74E6 # 3.0 KANGXI RADICAL TILE
+2F62 ; mapped ; 7518 # 3.0 KANGXI RADICAL SWEET
+2F63 ; mapped ; 751F # 3.0 KANGXI RADICAL LIFE
+2F64 ; mapped ; 7528 # 3.0 KANGXI RADICAL USE
+2F65 ; mapped ; 7530 # 3.0 KANGXI RADICAL FIELD
+2F66 ; mapped ; 758B # 3.0 KANGXI RADICAL BOLT OF CLOTH
+2F67 ; mapped ; 7592 # 3.0 KANGXI RADICAL SICKNESS
+2F68 ; mapped ; 7676 # 3.0 KANGXI RADICAL DOTTED TENT
+2F69 ; mapped ; 767D # 3.0 KANGXI RADICAL WHITE
+2F6A ; mapped ; 76AE # 3.0 KANGXI RADICAL SKIN
+2F6B ; mapped ; 76BF # 3.0 KANGXI RADICAL DISH
+2F6C ; mapped ; 76EE # 3.0 KANGXI RADICAL EYE
+2F6D ; mapped ; 77DB # 3.0 KANGXI RADICAL SPEAR
+2F6E ; mapped ; 77E2 # 3.0 KANGXI RADICAL ARROW
+2F6F ; mapped ; 77F3 # 3.0 KANGXI RADICAL STONE
+2F70 ; mapped ; 793A # 3.0 KANGXI RADICAL SPIRIT
+2F71 ; mapped ; 79B8 # 3.0 KANGXI RADICAL TRACK
+2F72 ; mapped ; 79BE # 3.0 KANGXI RADICAL GRAIN
+2F73 ; mapped ; 7A74 # 3.0 KANGXI RADICAL CAVE
+2F74 ; mapped ; 7ACB # 3.0 KANGXI RADICAL STAND
+2F75 ; mapped ; 7AF9 # 3.0 KANGXI RADICAL BAMBOO
+2F76 ; mapped ; 7C73 # 3.0 KANGXI RADICAL RICE
+2F77 ; mapped ; 7CF8 # 3.0 KANGXI RADICAL SILK
+2F78 ; mapped ; 7F36 # 3.0 KANGXI RADICAL JAR
+2F79 ; mapped ; 7F51 # 3.0 KANGXI RADICAL NET
+2F7A ; mapped ; 7F8A # 3.0 KANGXI RADICAL SHEEP
+2F7B ; mapped ; 7FBD # 3.0 KANGXI RADICAL FEATHER
+2F7C ; mapped ; 8001 # 3.0 KANGXI RADICAL OLD
+2F7D ; mapped ; 800C # 3.0 KANGXI RADICAL AND
+2F7E ; mapped ; 8012 # 3.0 KANGXI RADICAL PLOW
+2F7F ; mapped ; 8033 # 3.0 KANGXI RADICAL EAR
+2F80 ; mapped ; 807F # 3.0 KANGXI RADICAL BRUSH
+2F81 ; mapped ; 8089 # 3.0 KANGXI RADICAL MEAT
+2F82 ; mapped ; 81E3 # 3.0 KANGXI RADICAL MINISTER
+2F83 ; mapped ; 81EA # 3.0 KANGXI RADICAL SELF
+2F84 ; mapped ; 81F3 # 3.0 KANGXI RADICAL ARRIVE
+2F85 ; mapped ; 81FC # 3.0 KANGXI RADICAL MORTAR
+2F86 ; mapped ; 820C # 3.0 KANGXI RADICAL TONGUE
+2F87 ; mapped ; 821B # 3.0 KANGXI RADICAL OPPOSE
+2F88 ; mapped ; 821F # 3.0 KANGXI RADICAL BOAT
+2F89 ; mapped ; 826E # 3.0 KANGXI RADICAL STOPPING
+2F8A ; mapped ; 8272 # 3.0 KANGXI RADICAL COLOR
+2F8B ; mapped ; 8278 # 3.0 KANGXI RADICAL GRASS
+2F8C ; mapped ; 864D # 3.0 KANGXI RADICAL TIGER
+2F8D ; mapped ; 866B # 3.0 KANGXI RADICAL INSECT
+2F8E ; mapped ; 8840 # 3.0 KANGXI RADICAL BLOOD
+2F8F ; mapped ; 884C # 3.0 KANGXI RADICAL WALK ENCLOSURE
+2F90 ; mapped ; 8863 # 3.0 KANGXI RADICAL CLOTHES
+2F91 ; mapped ; 897E # 3.0 KANGXI RADICAL WEST
+2F92 ; mapped ; 898B # 3.0 KANGXI RADICAL SEE
+2F93 ; mapped ; 89D2 # 3.0 KANGXI RADICAL HORN
+2F94 ; mapped ; 8A00 # 3.0 KANGXI RADICAL SPEECH
+2F95 ; mapped ; 8C37 # 3.0 KANGXI RADICAL VALLEY
+2F96 ; mapped ; 8C46 # 3.0 KANGXI RADICAL BEAN
+2F97 ; mapped ; 8C55 # 3.0 KANGXI RADICAL PIG
+2F98 ; mapped ; 8C78 # 3.0 KANGXI RADICAL BADGER
+2F99 ; mapped ; 8C9D # 3.0 KANGXI RADICAL SHELL
+2F9A ; mapped ; 8D64 # 3.0 KANGXI RADICAL RED
+2F9B ; mapped ; 8D70 # 3.0 KANGXI RADICAL RUN
+2F9C ; mapped ; 8DB3 # 3.0 KANGXI RADICAL FOOT
+2F9D ; mapped ; 8EAB # 3.0 KANGXI RADICAL BODY
+2F9E ; mapped ; 8ECA # 3.0 KANGXI RADICAL CART
+2F9F ; mapped ; 8F9B # 3.0 KANGXI RADICAL BITTER
+2FA0 ; mapped ; 8FB0 # 3.0 KANGXI RADICAL MORNING
+2FA1 ; mapped ; 8FB5 # 3.0 KANGXI RADICAL WALK
+2FA2 ; mapped ; 9091 # 3.0 KANGXI RADICAL CITY
+2FA3 ; mapped ; 9149 # 3.0 KANGXI RADICAL WINE
+2FA4 ; mapped ; 91C6 # 3.0 KANGXI RADICAL DISTINGUISH
+2FA5 ; mapped ; 91CC # 3.0 KANGXI RADICAL VILLAGE
+2FA6 ; mapped ; 91D1 # 3.0 KANGXI RADICAL GOLD
+2FA7 ; mapped ; 9577 # 3.0 KANGXI RADICAL LONG
+2FA8 ; mapped ; 9580 # 3.0 KANGXI RADICAL GATE
+2FA9 ; mapped ; 961C # 3.0 KANGXI RADICAL MOUND
+2FAA ; mapped ; 96B6 # 3.0 KANGXI RADICAL SLAVE
+2FAB ; mapped ; 96B9 # 3.0 KANGXI RADICAL SHORT TAILED BIRD
+2FAC ; mapped ; 96E8 # 3.0 KANGXI RADICAL RAIN
+2FAD ; mapped ; 9751 # 3.0 KANGXI RADICAL BLUE
+2FAE ; mapped ; 975E # 3.0 KANGXI RADICAL WRONG
+2FAF ; mapped ; 9762 # 3.0 KANGXI RADICAL FACE
+2FB0 ; mapped ; 9769 # 3.0 KANGXI RADICAL LEATHER
+2FB1 ; mapped ; 97CB # 3.0 KANGXI RADICAL TANNED LEATHER
+2FB2 ; mapped ; 97ED # 3.0 KANGXI RADICAL LEEK
+2FB3 ; mapped ; 97F3 # 3.0 KANGXI RADICAL SOUND
+2FB4 ; mapped ; 9801 # 3.0 KANGXI RADICAL LEAF
+2FB5 ; mapped ; 98A8 # 3.0 KANGXI RADICAL WIND
+2FB6 ; mapped ; 98DB # 3.0 KANGXI RADICAL FLY
+2FB7 ; mapped ; 98DF # 3.0 KANGXI RADICAL EAT
+2FB8 ; mapped ; 9996 # 3.0 KANGXI RADICAL HEAD
+2FB9 ; mapped ; 9999 # 3.0 KANGXI RADICAL FRAGRANT
+2FBA ; mapped ; 99AC # 3.0 KANGXI RADICAL HORSE
+2FBB ; mapped ; 9AA8 # 3.0 KANGXI RADICAL BONE
+2FBC ; mapped ; 9AD8 # 3.0 KANGXI RADICAL TALL
+2FBD ; mapped ; 9ADF # 3.0 KANGXI RADICAL HAIR
+2FBE ; mapped ; 9B25 # 3.0 KANGXI RADICAL FIGHT
+2FBF ; mapped ; 9B2F # 3.0 KANGXI RADICAL SACRIFICIAL WINE
+2FC0 ; mapped ; 9B32 # 3.0 KANGXI RADICAL CAULDRON
+2FC1 ; mapped ; 9B3C # 3.0 KANGXI RADICAL GHOST
+2FC2 ; mapped ; 9B5A # 3.0 KANGXI RADICAL FISH
+2FC3 ; mapped ; 9CE5 # 3.0 KANGXI RADICAL BIRD
+2FC4 ; mapped ; 9E75 # 3.0 KANGXI RADICAL SALT
+2FC5 ; mapped ; 9E7F # 3.0 KANGXI RADICAL DEER
+2FC6 ; mapped ; 9EA5 # 3.0 KANGXI RADICAL WHEAT
+2FC7 ; mapped ; 9EBB # 3.0 KANGXI RADICAL HEMP
+2FC8 ; mapped ; 9EC3 # 3.0 KANGXI RADICAL YELLOW
+2FC9 ; mapped ; 9ECD # 3.0 KANGXI RADICAL MILLET
+2FCA ; mapped ; 9ED1 # 3.0 KANGXI RADICAL BLACK
+2FCB ; mapped ; 9EF9 # 3.0 KANGXI RADICAL EMBROIDERY
+2FCC ; mapped ; 9EFD # 3.0 KANGXI RADICAL FROG
+2FCD ; mapped ; 9F0E # 3.0 KANGXI RADICAL TRIPOD
+2FCE ; mapped ; 9F13 # 3.0 KANGXI RADICAL DRUM
+2FCF ; mapped ; 9F20 # 3.0 KANGXI RADICAL RAT
+2FD0 ; mapped ; 9F3B # 3.0 KANGXI RADICAL NOSE
+2FD1 ; mapped ; 9F4A # 3.0 KANGXI RADICAL EVEN
+2FD2 ; mapped ; 9F52 # 3.0 KANGXI RADICAL TOOTH
+2FD3 ; mapped ; 9F8D # 3.0 KANGXI RADICAL DRAGON
+2FD4 ; mapped ; 9F9C # 3.0 KANGXI RADICAL TURTLE
+2FD5 ; mapped ; 9FA0 # 3.0 KANGXI RADICAL FLUTE
+2FD6..2FEF ; disallowed # NA <reserved-2FD6>..<reserved-2FEF>
+2FF0..2FFB ; disallowed # 3.0 IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
+2FFC..2FFF ; disallowed # NA <reserved-2FFC>..<reserved-2FFF>
+3000 ; disallowed_STD3_mapped ; 0020 # 1.1 IDEOGRAPHIC SPACE
+3001 ; valid ; ; NV8 # 1.1 IDEOGRAPHIC COMMA
+3002 ; mapped ; 002E # 1.1 IDEOGRAPHIC FULL STOP
+3003..3004 ; valid ; ; NV8 # 1.1 DITTO MARK..JAPANESE INDUSTRIAL STANDARD SYMBOL
+3005..3007 ; valid # 1.1 IDEOGRAPHIC ITERATION MARK..IDEOGRAPHIC NUMBER ZERO
+3008..3029 ; valid ; ; NV8 # 1.1 LEFT ANGLE BRACKET..HANGZHOU NUMERAL NINE
+302A..302D ; valid # 1.1 IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
+302E..3035 ; valid ; ; NV8 # 1.1 HANGUL SINGLE DOT TONE MARK..VERTICAL KANA REPEAT MARK LOWER HALF
+3036 ; mapped ; 3012 # 1.1 CIRCLED POSTAL MARK
+3037 ; valid ; ; NV8 # 1.1 IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+3038 ; mapped ; 5341 # 3.0 HANGZHOU NUMERAL TEN
+3039 ; mapped ; 5344 # 3.0 HANGZHOU NUMERAL TWENTY
+303A ; mapped ; 5345 # 3.0 HANGZHOU NUMERAL THIRTY
+303B ; valid ; ; NV8 # 3.2 VERTICAL IDEOGRAPHIC ITERATION MARK
+303C ; valid # 3.2 MASU MARK
+303D ; valid ; ; NV8 # 3.2 PART ALTERNATION MARK
+303E ; valid ; ; NV8 # 3.0 IDEOGRAPHIC VARIATION INDICATOR
+303F ; valid ; ; NV8 # 1.1 IDEOGRAPHIC HALF FILL SPACE
+3040 ; disallowed # NA <reserved-3040>
+3041..3094 ; valid # 1.1 HIRAGANA LETTER SMALL A..HIRAGANA LETTER VU
+3095..3096 ; valid # 3.2 HIRAGANA LETTER SMALL KA..HIRAGANA LETTER SMALL KE
+3097..3098 ; disallowed # NA <reserved-3097>..<reserved-3098>
+3099..309A ; valid # 1.1 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309B ; disallowed_STD3_mapped ; 0020 3099 # 1.1 KATAKANA-HIRAGANA VOICED SOUND MARK
+309C ; disallowed_STD3_mapped ; 0020 309A # 1.1 KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309D..309E ; valid # 1.1 HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
+309F ; mapped ; 3088 308A # 3.2 HIRAGANA DIGRAPH YORI
+30A0 ; valid ; ; NV8 # 3.2 KATAKANA-HIRAGANA DOUBLE HYPHEN
+30A1..30FE ; valid # 1.1 KATAKANA LETTER SMALL A..KATAKANA VOICED ITERATION MARK
+30FF ; mapped ; 30B3 30C8 # 3.2 KATAKANA DIGRAPH KOTO
+3100..3104 ; disallowed # NA <reserved-3100>..<reserved-3104>
+3105..312C ; valid # 1.1 BOPOMOFO LETTER B..BOPOMOFO LETTER GN
+312D ; valid # 5.1 BOPOMOFO LETTER IH
+312E ; valid # 10.0 BOPOMOFO LETTER O WITH DOT ABOVE
+312F ; valid # 11.0 BOPOMOFO LETTER NN
+3130 ; disallowed # NA <reserved-3130>
+3131 ; mapped ; 1100 # 1.1 HANGUL LETTER KIYEOK
+3132 ; mapped ; 1101 # 1.1 HANGUL LETTER SSANGKIYEOK
+3133 ; mapped ; 11AA # 1.1 HANGUL LETTER KIYEOK-SIOS
+3134 ; mapped ; 1102 # 1.1 HANGUL LETTER NIEUN
+3135 ; mapped ; 11AC # 1.1 HANGUL LETTER NIEUN-CIEUC
+3136 ; mapped ; 11AD # 1.1 HANGUL LETTER NIEUN-HIEUH
+3137 ; mapped ; 1103 # 1.1 HANGUL LETTER TIKEUT
+3138 ; mapped ; 1104 # 1.1 HANGUL LETTER SSANGTIKEUT
+3139 ; mapped ; 1105 # 1.1 HANGUL LETTER RIEUL
+313A ; mapped ; 11B0 # 1.1 HANGUL LETTER RIEUL-KIYEOK
+313B ; mapped ; 11B1 # 1.1 HANGUL LETTER RIEUL-MIEUM
+313C ; mapped ; 11B2 # 1.1 HANGUL LETTER RIEUL-PIEUP
+313D ; mapped ; 11B3 # 1.1 HANGUL LETTER RIEUL-SIOS
+313E ; mapped ; 11B4 # 1.1 HANGUL LETTER RIEUL-THIEUTH
+313F ; mapped ; 11B5 # 1.1 HANGUL LETTER RIEUL-PHIEUPH
+3140 ; mapped ; 111A # 1.1 HANGUL LETTER RIEUL-HIEUH
+3141 ; mapped ; 1106 # 1.1 HANGUL LETTER MIEUM
+3142 ; mapped ; 1107 # 1.1 HANGUL LETTER PIEUP
+3143 ; mapped ; 1108 # 1.1 HANGUL LETTER SSANGPIEUP
+3144 ; mapped ; 1121 # 1.1 HANGUL LETTER PIEUP-SIOS
+3145 ; mapped ; 1109 # 1.1 HANGUL LETTER SIOS
+3146 ; mapped ; 110A # 1.1 HANGUL LETTER SSANGSIOS
+3147 ; mapped ; 110B # 1.1 HANGUL LETTER IEUNG
+3148 ; mapped ; 110C # 1.1 HANGUL LETTER CIEUC
+3149 ; mapped ; 110D # 1.1 HANGUL LETTER SSANGCIEUC
+314A ; mapped ; 110E # 1.1 HANGUL LETTER CHIEUCH
+314B ; mapped ; 110F # 1.1 HANGUL LETTER KHIEUKH
+314C ; mapped ; 1110 # 1.1 HANGUL LETTER THIEUTH
+314D ; mapped ; 1111 # 1.1 HANGUL LETTER PHIEUPH
+314E ; mapped ; 1112 # 1.1 HANGUL LETTER HIEUH
+314F ; mapped ; 1161 # 1.1 HANGUL LETTER A
+3150 ; mapped ; 1162 # 1.1 HANGUL LETTER AE
+3151 ; mapped ; 1163 # 1.1 HANGUL LETTER YA
+3152 ; mapped ; 1164 # 1.1 HANGUL LETTER YAE
+3153 ; mapped ; 1165 # 1.1 HANGUL LETTER EO
+3154 ; mapped ; 1166 # 1.1 HANGUL LETTER E
+3155 ; mapped ; 1167 # 1.1 HANGUL LETTER YEO
+3156 ; mapped ; 1168 # 1.1 HANGUL LETTER YE
+3157 ; mapped ; 1169 # 1.1 HANGUL LETTER O
+3158 ; mapped ; 116A # 1.1 HANGUL LETTER WA
+3159 ; mapped ; 116B # 1.1 HANGUL LETTER WAE
+315A ; mapped ; 116C # 1.1 HANGUL LETTER OE
+315B ; mapped ; 116D # 1.1 HANGUL LETTER YO
+315C ; mapped ; 116E # 1.1 HANGUL LETTER U
+315D ; mapped ; 116F # 1.1 HANGUL LETTER WEO
+315E ; mapped ; 1170 # 1.1 HANGUL LETTER WE
+315F ; mapped ; 1171 # 1.1 HANGUL LETTER WI
+3160 ; mapped ; 1172 # 1.1 HANGUL LETTER YU
+3161 ; mapped ; 1173 # 1.1 HANGUL LETTER EU
+3162 ; mapped ; 1174 # 1.1 HANGUL LETTER YI
+3163 ; mapped ; 1175 # 1.1 HANGUL LETTER I
+3164 ; disallowed # 1.1 HANGUL FILLER
+3165 ; mapped ; 1114 # 1.1 HANGUL LETTER SSANGNIEUN
+3166 ; mapped ; 1115 # 1.1 HANGUL LETTER NIEUN-TIKEUT
+3167 ; mapped ; 11C7 # 1.1 HANGUL LETTER NIEUN-SIOS
+3168 ; mapped ; 11C8 # 1.1 HANGUL LETTER NIEUN-PANSIOS
+3169 ; mapped ; 11CC # 1.1 HANGUL LETTER RIEUL-KIYEOK-SIOS
+316A ; mapped ; 11CE # 1.1 HANGUL LETTER RIEUL-TIKEUT
+316B ; mapped ; 11D3 # 1.1 HANGUL LETTER RIEUL-PIEUP-SIOS
+316C ; mapped ; 11D7 # 1.1 HANGUL LETTER RIEUL-PANSIOS
+316D ; mapped ; 11D9 # 1.1 HANGUL LETTER RIEUL-YEORINHIEUH
+316E ; mapped ; 111C # 1.1 HANGUL LETTER MIEUM-PIEUP
+316F ; mapped ; 11DD # 1.1 HANGUL LETTER MIEUM-SIOS
+3170 ; mapped ; 11DF # 1.1 HANGUL LETTER MIEUM-PANSIOS
+3171 ; mapped ; 111D # 1.1 HANGUL LETTER KAPYEOUNMIEUM
+3172 ; mapped ; 111E # 1.1 HANGUL LETTER PIEUP-KIYEOK
+3173 ; mapped ; 1120 # 1.1 HANGUL LETTER PIEUP-TIKEUT
+3174 ; mapped ; 1122 # 1.1 HANGUL LETTER PIEUP-SIOS-KIYEOK
+3175 ; mapped ; 1123 # 1.1 HANGUL LETTER PIEUP-SIOS-TIKEUT
+3176 ; mapped ; 1127 # 1.1 HANGUL LETTER PIEUP-CIEUC
+3177 ; mapped ; 1129 # 1.1 HANGUL LETTER PIEUP-THIEUTH
+3178 ; mapped ; 112B # 1.1 HANGUL LETTER KAPYEOUNPIEUP
+3179 ; mapped ; 112C # 1.1 HANGUL LETTER KAPYEOUNSSANGPIEUP
+317A ; mapped ; 112D # 1.1 HANGUL LETTER SIOS-KIYEOK
+317B ; mapped ; 112E # 1.1 HANGUL LETTER SIOS-NIEUN
+317C ; mapped ; 112F # 1.1 HANGUL LETTER SIOS-TIKEUT
+317D ; mapped ; 1132 # 1.1 HANGUL LETTER SIOS-PIEUP
+317E ; mapped ; 1136 # 1.1 HANGUL LETTER SIOS-CIEUC
+317F ; mapped ; 1140 # 1.1 HANGUL LETTER PANSIOS
+3180 ; mapped ; 1147 # 1.1 HANGUL LETTER SSANGIEUNG
+3181 ; mapped ; 114C # 1.1 HANGUL LETTER YESIEUNG
+3182 ; mapped ; 11F1 # 1.1 HANGUL LETTER YESIEUNG-SIOS
+3183 ; mapped ; 11F2 # 1.1 HANGUL LETTER YESIEUNG-PANSIOS
+3184 ; mapped ; 1157 # 1.1 HANGUL LETTER KAPYEOUNPHIEUPH
+3185 ; mapped ; 1158 # 1.1 HANGUL LETTER SSANGHIEUH
+3186 ; mapped ; 1159 # 1.1 HANGUL LETTER YEORINHIEUH
+3187 ; mapped ; 1184 # 1.1 HANGUL LETTER YO-YA
+3188 ; mapped ; 1185 # 1.1 HANGUL LETTER YO-YAE
+3189 ; mapped ; 1188 # 1.1 HANGUL LETTER YO-I
+318A ; mapped ; 1191 # 1.1 HANGUL LETTER YU-YEO
+318B ; mapped ; 1192 # 1.1 HANGUL LETTER YU-YE
+318C ; mapped ; 1194 # 1.1 HANGUL LETTER YU-I
+318D ; mapped ; 119E # 1.1 HANGUL LETTER ARAEA
+318E ; mapped ; 11A1 # 1.1 HANGUL LETTER ARAEAE
+318F ; disallowed # NA <reserved-318F>
+3190..3191 ; valid ; ; NV8 # 1.1 IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
+3192 ; mapped ; 4E00 # 1.1 IDEOGRAPHIC ANNOTATION ONE MARK
+3193 ; mapped ; 4E8C # 1.1 IDEOGRAPHIC ANNOTATION TWO MARK
+3194 ; mapped ; 4E09 # 1.1 IDEOGRAPHIC ANNOTATION THREE MARK
+3195 ; mapped ; 56DB # 1.1 IDEOGRAPHIC ANNOTATION FOUR MARK
+3196 ; mapped ; 4E0A # 1.1 IDEOGRAPHIC ANNOTATION TOP MARK
+3197 ; mapped ; 4E2D # 1.1 IDEOGRAPHIC ANNOTATION MIDDLE MARK
+3198 ; mapped ; 4E0B # 1.1 IDEOGRAPHIC ANNOTATION BOTTOM MARK
+3199 ; mapped ; 7532 # 1.1 IDEOGRAPHIC ANNOTATION FIRST MARK
+319A ; mapped ; 4E59 # 1.1 IDEOGRAPHIC ANNOTATION SECOND MARK
+319B ; mapped ; 4E19 # 1.1 IDEOGRAPHIC ANNOTATION THIRD MARK
+319C ; mapped ; 4E01 # 1.1 IDEOGRAPHIC ANNOTATION FOURTH MARK
+319D ; mapped ; 5929 # 1.1 IDEOGRAPHIC ANNOTATION HEAVEN MARK
+319E ; mapped ; 5730 # 1.1 IDEOGRAPHIC ANNOTATION EARTH MARK
+319F ; mapped ; 4EBA # 1.1 IDEOGRAPHIC ANNOTATION MAN MARK
+31A0..31B7 ; valid # 3.0 BOPOMOFO LETTER BU..BOPOMOFO FINAL LETTER H
+31B8..31BA ; valid # 6.0 BOPOMOFO LETTER GH..BOPOMOFO LETTER ZY
+31BB..31BF ; valid # 13.0 BOPOMOFO FINAL LETTER G..BOPOMOFO LETTER AH
+31C0..31CF ; valid ; ; NV8 # 4.1 CJK STROKE T..CJK STROKE N
+31D0..31E3 ; valid ; ; NV8 # 5.1 CJK STROKE H..CJK STROKE Q
+31E4..31EF ; disallowed # NA <reserved-31E4>..<reserved-31EF>
+31F0..31FF ; valid # 3.2 KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
+3200 ; disallowed_STD3_mapped ; 0028 1100 0029 #1.1 PARENTHESIZED HANGUL KIYEOK
+3201 ; disallowed_STD3_mapped ; 0028 1102 0029 #1.1 PARENTHESIZED HANGUL NIEUN
+3202 ; disallowed_STD3_mapped ; 0028 1103 0029 #1.1 PARENTHESIZED HANGUL TIKEUT
+3203 ; disallowed_STD3_mapped ; 0028 1105 0029 #1.1 PARENTHESIZED HANGUL RIEUL
+3204 ; disallowed_STD3_mapped ; 0028 1106 0029 #1.1 PARENTHESIZED HANGUL MIEUM
+3205 ; disallowed_STD3_mapped ; 0028 1107 0029 #1.1 PARENTHESIZED HANGUL PIEUP
+3206 ; disallowed_STD3_mapped ; 0028 1109 0029 #1.1 PARENTHESIZED HANGUL SIOS
+3207 ; disallowed_STD3_mapped ; 0028 110B 0029 #1.1 PARENTHESIZED HANGUL IEUNG
+3208 ; disallowed_STD3_mapped ; 0028 110C 0029 #1.1 PARENTHESIZED HANGUL CIEUC
+3209 ; disallowed_STD3_mapped ; 0028 110E 0029 #1.1 PARENTHESIZED HANGUL CHIEUCH
+320A ; disallowed_STD3_mapped ; 0028 110F 0029 #1.1 PARENTHESIZED HANGUL KHIEUKH
+320B ; disallowed_STD3_mapped ; 0028 1110 0029 #1.1 PARENTHESIZED HANGUL THIEUTH
+320C ; disallowed_STD3_mapped ; 0028 1111 0029 #1.1 PARENTHESIZED HANGUL PHIEUPH
+320D ; disallowed_STD3_mapped ; 0028 1112 0029 #1.1 PARENTHESIZED HANGUL HIEUH
+320E ; disallowed_STD3_mapped ; 0028 AC00 0029 #1.1 PARENTHESIZED HANGUL KIYEOK A
+320F ; disallowed_STD3_mapped ; 0028 B098 0029 #1.1 PARENTHESIZED HANGUL NIEUN A
+3210 ; disallowed_STD3_mapped ; 0028 B2E4 0029 #1.1 PARENTHESIZED HANGUL TIKEUT A
+3211 ; disallowed_STD3_mapped ; 0028 B77C 0029 #1.1 PARENTHESIZED HANGUL RIEUL A
+3212 ; disallowed_STD3_mapped ; 0028 B9C8 0029 #1.1 PARENTHESIZED HANGUL MIEUM A
+3213 ; disallowed_STD3_mapped ; 0028 BC14 0029 #1.1 PARENTHESIZED HANGUL PIEUP A
+3214 ; disallowed_STD3_mapped ; 0028 C0AC 0029 #1.1 PARENTHESIZED HANGUL SIOS A
+3215 ; disallowed_STD3_mapped ; 0028 C544 0029 #1.1 PARENTHESIZED HANGUL IEUNG A
+3216 ; disallowed_STD3_mapped ; 0028 C790 0029 #1.1 PARENTHESIZED HANGUL CIEUC A
+3217 ; disallowed_STD3_mapped ; 0028 CC28 0029 #1.1 PARENTHESIZED HANGUL CHIEUCH A
+3218 ; disallowed_STD3_mapped ; 0028 CE74 0029 #1.1 PARENTHESIZED HANGUL KHIEUKH A
+3219 ; disallowed_STD3_mapped ; 0028 D0C0 0029 #1.1 PARENTHESIZED HANGUL THIEUTH A
+321A ; disallowed_STD3_mapped ; 0028 D30C 0029 #1.1 PARENTHESIZED HANGUL PHIEUPH A
+321B ; disallowed_STD3_mapped ; 0028 D558 0029 #1.1 PARENTHESIZED HANGUL HIEUH A
+321C ; disallowed_STD3_mapped ; 0028 C8FC 0029 #1.1 PARENTHESIZED HANGUL CIEUC U
+321D ; disallowed_STD3_mapped ; 0028 C624 C804 0029 #4.0 PARENTHESIZED KOREAN CHARACTER OJEON
+321E ; disallowed_STD3_mapped ; 0028 C624 D6C4 0029 #4.0 PARENTHESIZED KOREAN CHARACTER O HU
+321F ; disallowed # NA <reserved-321F>
+3220 ; disallowed_STD3_mapped ; 0028 4E00 0029 #1.1 PARENTHESIZED IDEOGRAPH ONE
+3221 ; disallowed_STD3_mapped ; 0028 4E8C 0029 #1.1 PARENTHESIZED IDEOGRAPH TWO
+3222 ; disallowed_STD3_mapped ; 0028 4E09 0029 #1.1 PARENTHESIZED IDEOGRAPH THREE
+3223 ; disallowed_STD3_mapped ; 0028 56DB 0029 #1.1 PARENTHESIZED IDEOGRAPH FOUR
+3224 ; disallowed_STD3_mapped ; 0028 4E94 0029 #1.1 PARENTHESIZED IDEOGRAPH FIVE
+3225 ; disallowed_STD3_mapped ; 0028 516D 0029 #1.1 PARENTHESIZED IDEOGRAPH SIX
+3226 ; disallowed_STD3_mapped ; 0028 4E03 0029 #1.1 PARENTHESIZED IDEOGRAPH SEVEN
+3227 ; disallowed_STD3_mapped ; 0028 516B 0029 #1.1 PARENTHESIZED IDEOGRAPH EIGHT
+3228 ; disallowed_STD3_mapped ; 0028 4E5D 0029 #1.1 PARENTHESIZED IDEOGRAPH NINE
+3229 ; disallowed_STD3_mapped ; 0028 5341 0029 #1.1 PARENTHESIZED IDEOGRAPH TEN
+322A ; disallowed_STD3_mapped ; 0028 6708 0029 #1.1 PARENTHESIZED IDEOGRAPH MOON
+322B ; disallowed_STD3_mapped ; 0028 706B 0029 #1.1 PARENTHESIZED IDEOGRAPH FIRE
+322C ; disallowed_STD3_mapped ; 0028 6C34 0029 #1.1 PARENTHESIZED IDEOGRAPH WATER
+322D ; disallowed_STD3_mapped ; 0028 6728 0029 #1.1 PARENTHESIZED IDEOGRAPH WOOD
+322E ; disallowed_STD3_mapped ; 0028 91D1 0029 #1.1 PARENTHESIZED IDEOGRAPH METAL
+322F ; disallowed_STD3_mapped ; 0028 571F 0029 #1.1 PARENTHESIZED IDEOGRAPH EARTH
+3230 ; disallowed_STD3_mapped ; 0028 65E5 0029 #1.1 PARENTHESIZED IDEOGRAPH SUN
+3231 ; disallowed_STD3_mapped ; 0028 682A 0029 #1.1 PARENTHESIZED IDEOGRAPH STOCK
+3232 ; disallowed_STD3_mapped ; 0028 6709 0029 #1.1 PARENTHESIZED IDEOGRAPH HAVE
+3233 ; disallowed_STD3_mapped ; 0028 793E 0029 #1.1 PARENTHESIZED IDEOGRAPH SOCIETY
+3234 ; disallowed_STD3_mapped ; 0028 540D 0029 #1.1 PARENTHESIZED IDEOGRAPH NAME
+3235 ; disallowed_STD3_mapped ; 0028 7279 0029 #1.1 PARENTHESIZED IDEOGRAPH SPECIAL
+3236 ; disallowed_STD3_mapped ; 0028 8CA1 0029 #1.1 PARENTHESIZED IDEOGRAPH FINANCIAL
+3237 ; disallowed_STD3_mapped ; 0028 795D 0029 #1.1 PARENTHESIZED IDEOGRAPH CONGRATULATION
+3238 ; disallowed_STD3_mapped ; 0028 52B4 0029 #1.1 PARENTHESIZED IDEOGRAPH LABOR
+3239 ; disallowed_STD3_mapped ; 0028 4EE3 0029 #1.1 PARENTHESIZED IDEOGRAPH REPRESENT
+323A ; disallowed_STD3_mapped ; 0028 547C 0029 #1.1 PARENTHESIZED IDEOGRAPH CALL
+323B ; disallowed_STD3_mapped ; 0028 5B66 0029 #1.1 PARENTHESIZED IDEOGRAPH STUDY
+323C ; disallowed_STD3_mapped ; 0028 76E3 0029 #1.1 PARENTHESIZED IDEOGRAPH SUPERVISE
+323D ; disallowed_STD3_mapped ; 0028 4F01 0029 #1.1 PARENTHESIZED IDEOGRAPH ENTERPRISE
+323E ; disallowed_STD3_mapped ; 0028 8CC7 0029 #1.1 PARENTHESIZED IDEOGRAPH RESOURCE
+323F ; disallowed_STD3_mapped ; 0028 5354 0029 #1.1 PARENTHESIZED IDEOGRAPH ALLIANCE
+3240 ; disallowed_STD3_mapped ; 0028 796D 0029 #1.1 PARENTHESIZED IDEOGRAPH FESTIVAL
+3241 ; disallowed_STD3_mapped ; 0028 4F11 0029 #1.1 PARENTHESIZED IDEOGRAPH REST
+3242 ; disallowed_STD3_mapped ; 0028 81EA 0029 #1.1 PARENTHESIZED IDEOGRAPH SELF
+3243 ; disallowed_STD3_mapped ; 0028 81F3 0029 #1.1 PARENTHESIZED IDEOGRAPH REACH
+3244 ; mapped ; 554F # 5.2 CIRCLED IDEOGRAPH QUESTION
+3245 ; mapped ; 5E7C # 5.2 CIRCLED IDEOGRAPH KINDERGARTEN
+3246 ; mapped ; 6587 # 5.2 CIRCLED IDEOGRAPH SCHOOL
+3247 ; mapped ; 7B8F # 5.2 CIRCLED IDEOGRAPH KOTO
+3248..324F ; valid ; ; NV8 # 5.2 CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
+3250 ; mapped ; 0070 0074 0065 #4.0 PARTNERSHIP SIGN
+3251 ; mapped ; 0032 0031 # 3.2 CIRCLED NUMBER TWENTY ONE
+3252 ; mapped ; 0032 0032 # 3.2 CIRCLED NUMBER TWENTY TWO
+3253 ; mapped ; 0032 0033 # 3.2 CIRCLED NUMBER TWENTY THREE
+3254 ; mapped ; 0032 0034 # 3.2 CIRCLED NUMBER TWENTY FOUR
+3255 ; mapped ; 0032 0035 # 3.2 CIRCLED NUMBER TWENTY FIVE
+3256 ; mapped ; 0032 0036 # 3.2 CIRCLED NUMBER TWENTY SIX
+3257 ; mapped ; 0032 0037 # 3.2 CIRCLED NUMBER TWENTY SEVEN
+3258 ; mapped ; 0032 0038 # 3.2 CIRCLED NUMBER TWENTY EIGHT
+3259 ; mapped ; 0032 0039 # 3.2 CIRCLED NUMBER TWENTY NINE
+325A ; mapped ; 0033 0030 # 3.2 CIRCLED NUMBER THIRTY
+325B ; mapped ; 0033 0031 # 3.2 CIRCLED NUMBER THIRTY ONE
+325C ; mapped ; 0033 0032 # 3.2 CIRCLED NUMBER THIRTY TWO
+325D ; mapped ; 0033 0033 # 3.2 CIRCLED NUMBER THIRTY THREE
+325E ; mapped ; 0033 0034 # 3.2 CIRCLED NUMBER THIRTY FOUR
+325F ; mapped ; 0033 0035 # 3.2 CIRCLED NUMBER THIRTY FIVE
+3260 ; mapped ; 1100 # 1.1 CIRCLED HANGUL KIYEOK
+3261 ; mapped ; 1102 # 1.1 CIRCLED HANGUL NIEUN
+3262 ; mapped ; 1103 # 1.1 CIRCLED HANGUL TIKEUT
+3263 ; mapped ; 1105 # 1.1 CIRCLED HANGUL RIEUL
+3264 ; mapped ; 1106 # 1.1 CIRCLED HANGUL MIEUM
+3265 ; mapped ; 1107 # 1.1 CIRCLED HANGUL PIEUP
+3266 ; mapped ; 1109 # 1.1 CIRCLED HANGUL SIOS
+3267 ; mapped ; 110B # 1.1 CIRCLED HANGUL IEUNG
+3268 ; mapped ; 110C # 1.1 CIRCLED HANGUL CIEUC
+3269 ; mapped ; 110E # 1.1 CIRCLED HANGUL CHIEUCH
+326A ; mapped ; 110F # 1.1 CIRCLED HANGUL KHIEUKH
+326B ; mapped ; 1110 # 1.1 CIRCLED HANGUL THIEUTH
+326C ; mapped ; 1111 # 1.1 CIRCLED HANGUL PHIEUPH
+326D ; mapped ; 1112 # 1.1 CIRCLED HANGUL HIEUH
+326E ; mapped ; AC00 # 1.1 CIRCLED HANGUL KIYEOK A
+326F ; mapped ; B098 # 1.1 CIRCLED HANGUL NIEUN A
+3270 ; mapped ; B2E4 # 1.1 CIRCLED HANGUL TIKEUT A
+3271 ; mapped ; B77C # 1.1 CIRCLED HANGUL RIEUL A
+3272 ; mapped ; B9C8 # 1.1 CIRCLED HANGUL MIEUM A
+3273 ; mapped ; BC14 # 1.1 CIRCLED HANGUL PIEUP A
+3274 ; mapped ; C0AC # 1.1 CIRCLED HANGUL SIOS A
+3275 ; mapped ; C544 # 1.1 CIRCLED HANGUL IEUNG A
+3276 ; mapped ; C790 # 1.1 CIRCLED HANGUL CIEUC A
+3277 ; mapped ; CC28 # 1.1 CIRCLED HANGUL CHIEUCH A
+3278 ; mapped ; CE74 # 1.1 CIRCLED HANGUL KHIEUKH A
+3279 ; mapped ; D0C0 # 1.1 CIRCLED HANGUL THIEUTH A
+327A ; mapped ; D30C # 1.1 CIRCLED HANGUL PHIEUPH A
+327B ; mapped ; D558 # 1.1 CIRCLED HANGUL HIEUH A
+327C ; mapped ; CC38 ACE0 # 4.0 CIRCLED KOREAN CHARACTER CHAMKO
+327D ; mapped ; C8FC C758 # 4.0 CIRCLED KOREAN CHARACTER JUEUI
+327E ; mapped ; C6B0 # 4.1 CIRCLED HANGUL IEUNG U
+327F ; valid ; ; NV8 # 1.1 KOREAN STANDARD SYMBOL
+3280 ; mapped ; 4E00 # 1.1 CIRCLED IDEOGRAPH ONE
+3281 ; mapped ; 4E8C # 1.1 CIRCLED IDEOGRAPH TWO
+3282 ; mapped ; 4E09 # 1.1 CIRCLED IDEOGRAPH THREE
+3283 ; mapped ; 56DB # 1.1 CIRCLED IDEOGRAPH FOUR
+3284 ; mapped ; 4E94 # 1.1 CIRCLED IDEOGRAPH FIVE
+3285 ; mapped ; 516D # 1.1 CIRCLED IDEOGRAPH SIX
+3286 ; mapped ; 4E03 # 1.1 CIRCLED IDEOGRAPH SEVEN
+3287 ; mapped ; 516B # 1.1 CIRCLED IDEOGRAPH EIGHT
+3288 ; mapped ; 4E5D # 1.1 CIRCLED IDEOGRAPH NINE
+3289 ; mapped ; 5341 # 1.1 CIRCLED IDEOGRAPH TEN
+328A ; mapped ; 6708 # 1.1 CIRCLED IDEOGRAPH MOON
+328B ; mapped ; 706B # 1.1 CIRCLED IDEOGRAPH FIRE
+328C ; mapped ; 6C34 # 1.1 CIRCLED IDEOGRAPH WATER
+328D ; mapped ; 6728 # 1.1 CIRCLED IDEOGRAPH WOOD
+328E ; mapped ; 91D1 # 1.1 CIRCLED IDEOGRAPH METAL
+328F ; mapped ; 571F # 1.1 CIRCLED IDEOGRAPH EARTH
+3290 ; mapped ; 65E5 # 1.1 CIRCLED IDEOGRAPH SUN
+3291 ; mapped ; 682A # 1.1 CIRCLED IDEOGRAPH STOCK
+3292 ; mapped ; 6709 # 1.1 CIRCLED IDEOGRAPH HAVE
+3293 ; mapped ; 793E # 1.1 CIRCLED IDEOGRAPH SOCIETY
+3294 ; mapped ; 540D # 1.1 CIRCLED IDEOGRAPH NAME
+3295 ; mapped ; 7279 # 1.1 CIRCLED IDEOGRAPH SPECIAL
+3296 ; mapped ; 8CA1 # 1.1 CIRCLED IDEOGRAPH FINANCIAL
+3297 ; mapped ; 795D # 1.1 CIRCLED IDEOGRAPH CONGRATULATION
+3298 ; mapped ; 52B4 # 1.1 CIRCLED IDEOGRAPH LABOR
+3299 ; mapped ; 79D8 # 1.1 CIRCLED IDEOGRAPH SECRET
+329A ; mapped ; 7537 # 1.1 CIRCLED IDEOGRAPH MALE
+329B ; mapped ; 5973 # 1.1 CIRCLED IDEOGRAPH FEMALE
+329C ; mapped ; 9069 # 1.1 CIRCLED IDEOGRAPH SUITABLE
+329D ; mapped ; 512A # 1.1 CIRCLED IDEOGRAPH EXCELLENT
+329E ; mapped ; 5370 # 1.1 CIRCLED IDEOGRAPH PRINT
+329F ; mapped ; 6CE8 # 1.1 CIRCLED IDEOGRAPH ATTENTION
+32A0 ; mapped ; 9805 # 1.1 CIRCLED IDEOGRAPH ITEM
+32A1 ; mapped ; 4F11 # 1.1 CIRCLED IDEOGRAPH REST
+32A2 ; mapped ; 5199 # 1.1 CIRCLED IDEOGRAPH COPY
+32A3 ; mapped ; 6B63 # 1.1 CIRCLED IDEOGRAPH CORRECT
+32A4 ; mapped ; 4E0A # 1.1 CIRCLED IDEOGRAPH HIGH
+32A5 ; mapped ; 4E2D # 1.1 CIRCLED IDEOGRAPH CENTRE
+32A6 ; mapped ; 4E0B # 1.1 CIRCLED IDEOGRAPH LOW
+32A7 ; mapped ; 5DE6 # 1.1 CIRCLED IDEOGRAPH LEFT
+32A8 ; mapped ; 53F3 # 1.1 CIRCLED IDEOGRAPH RIGHT
+32A9 ; mapped ; 533B # 1.1 CIRCLED IDEOGRAPH MEDICINE
+32AA ; mapped ; 5B97 # 1.1 CIRCLED IDEOGRAPH RELIGION
+32AB ; mapped ; 5B66 # 1.1 CIRCLED IDEOGRAPH STUDY
+32AC ; mapped ; 76E3 # 1.1 CIRCLED IDEOGRAPH SUPERVISE
+32AD ; mapped ; 4F01 # 1.1 CIRCLED IDEOGRAPH ENTERPRISE
+32AE ; mapped ; 8CC7 # 1.1 CIRCLED IDEOGRAPH RESOURCE
+32AF ; mapped ; 5354 # 1.1 CIRCLED IDEOGRAPH ALLIANCE
+32B0 ; mapped ; 591C # 1.1 CIRCLED IDEOGRAPH NIGHT
+32B1 ; mapped ; 0033 0036 # 3.2 CIRCLED NUMBER THIRTY SIX
+32B2 ; mapped ; 0033 0037 # 3.2 CIRCLED NUMBER THIRTY SEVEN
+32B3 ; mapped ; 0033 0038 # 3.2 CIRCLED NUMBER THIRTY EIGHT
+32B4 ; mapped ; 0033 0039 # 3.2 CIRCLED NUMBER THIRTY NINE
+32B5 ; mapped ; 0034 0030 # 3.2 CIRCLED NUMBER FORTY
+32B6 ; mapped ; 0034 0031 # 3.2 CIRCLED NUMBER FORTY ONE
+32B7 ; mapped ; 0034 0032 # 3.2 CIRCLED NUMBER FORTY TWO
+32B8 ; mapped ; 0034 0033 # 3.2 CIRCLED NUMBER FORTY THREE
+32B9 ; mapped ; 0034 0034 # 3.2 CIRCLED NUMBER FORTY FOUR
+32BA ; mapped ; 0034 0035 # 3.2 CIRCLED NUMBER FORTY FIVE
+32BB ; mapped ; 0034 0036 # 3.2 CIRCLED NUMBER FORTY SIX
+32BC ; mapped ; 0034 0037 # 3.2 CIRCLED NUMBER FORTY SEVEN
+32BD ; mapped ; 0034 0038 # 3.2 CIRCLED NUMBER FORTY EIGHT
+32BE ; mapped ; 0034 0039 # 3.2 CIRCLED NUMBER FORTY NINE
+32BF ; mapped ; 0035 0030 # 3.2 CIRCLED NUMBER FIFTY
+32C0 ; mapped ; 0031 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY
+32C1 ; mapped ; 0032 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY
+32C2 ; mapped ; 0033 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH
+32C3 ; mapped ; 0034 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL
+32C4 ; mapped ; 0035 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY
+32C5 ; mapped ; 0036 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE
+32C6 ; mapped ; 0037 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY
+32C7 ; mapped ; 0038 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST
+32C8 ; mapped ; 0039 6708 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER
+32C9 ; mapped ; 0031 0030 6708 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER
+32CA ; mapped ; 0031 0031 6708 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER
+32CB ; mapped ; 0031 0032 6708 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER
+32CC ; mapped ; 0068 0067 # 4.0 SQUARE HG
+32CD ; mapped ; 0065 0072 0067 #4.0 SQUARE ERG
+32CE ; mapped ; 0065 0076 # 4.0 SQUARE EV
+32CF ; mapped ; 006C 0074 0064 #4.0 LIMITED LIABILITY SIGN
+32D0 ; mapped ; 30A2 # 1.1 CIRCLED KATAKANA A
+32D1 ; mapped ; 30A4 # 1.1 CIRCLED KATAKANA I
+32D2 ; mapped ; 30A6 # 1.1 CIRCLED KATAKANA U
+32D3 ; mapped ; 30A8 # 1.1 CIRCLED KATAKANA E
+32D4 ; mapped ; 30AA # 1.1 CIRCLED KATAKANA O
+32D5 ; mapped ; 30AB # 1.1 CIRCLED KATAKANA KA
+32D6 ; mapped ; 30AD # 1.1 CIRCLED KATAKANA KI
+32D7 ; mapped ; 30AF # 1.1 CIRCLED KATAKANA KU
+32D8 ; mapped ; 30B1 # 1.1 CIRCLED KATAKANA KE
+32D9 ; mapped ; 30B3 # 1.1 CIRCLED KATAKANA KO
+32DA ; mapped ; 30B5 # 1.1 CIRCLED KATAKANA SA
+32DB ; mapped ; 30B7 # 1.1 CIRCLED KATAKANA SI
+32DC ; mapped ; 30B9 # 1.1 CIRCLED KATAKANA SU
+32DD ; mapped ; 30BB # 1.1 CIRCLED KATAKANA SE
+32DE ; mapped ; 30BD # 1.1 CIRCLED KATAKANA SO
+32DF ; mapped ; 30BF # 1.1 CIRCLED KATAKANA TA
+32E0 ; mapped ; 30C1 # 1.1 CIRCLED KATAKANA TI
+32E1 ; mapped ; 30C4 # 1.1 CIRCLED KATAKANA TU
+32E2 ; mapped ; 30C6 # 1.1 CIRCLED KATAKANA TE
+32E3 ; mapped ; 30C8 # 1.1 CIRCLED KATAKANA TO
+32E4 ; mapped ; 30CA # 1.1 CIRCLED KATAKANA NA
+32E5 ; mapped ; 30CB # 1.1 CIRCLED KATAKANA NI
+32E6 ; mapped ; 30CC # 1.1 CIRCLED KATAKANA NU
+32E7 ; mapped ; 30CD # 1.1 CIRCLED KATAKANA NE
+32E8 ; mapped ; 30CE # 1.1 CIRCLED KATAKANA NO
+32E9 ; mapped ; 30CF # 1.1 CIRCLED KATAKANA HA
+32EA ; mapped ; 30D2 # 1.1 CIRCLED KATAKANA HI
+32EB ; mapped ; 30D5 # 1.1 CIRCLED KATAKANA HU
+32EC ; mapped ; 30D8 # 1.1 CIRCLED KATAKANA HE
+32ED ; mapped ; 30DB # 1.1 CIRCLED KATAKANA HO
+32EE ; mapped ; 30DE # 1.1 CIRCLED KATAKANA MA
+32EF ; mapped ; 30DF # 1.1 CIRCLED KATAKANA MI
+32F0 ; mapped ; 30E0 # 1.1 CIRCLED KATAKANA MU
+32F1 ; mapped ; 30E1 # 1.1 CIRCLED KATAKANA ME
+32F2 ; mapped ; 30E2 # 1.1 CIRCLED KATAKANA MO
+32F3 ; mapped ; 30E4 # 1.1 CIRCLED KATAKANA YA
+32F4 ; mapped ; 30E6 # 1.1 CIRCLED KATAKANA YU
+32F5 ; mapped ; 30E8 # 1.1 CIRCLED KATAKANA YO
+32F6 ; mapped ; 30E9 # 1.1 CIRCLED KATAKANA RA
+32F7 ; mapped ; 30EA # 1.1 CIRCLED KATAKANA RI
+32F8 ; mapped ; 30EB # 1.1 CIRCLED KATAKANA RU
+32F9 ; mapped ; 30EC # 1.1 CIRCLED KATAKANA RE
+32FA ; mapped ; 30ED # 1.1 CIRCLED KATAKANA RO
+32FB ; mapped ; 30EF # 1.1 CIRCLED KATAKANA WA
+32FC ; mapped ; 30F0 # 1.1 CIRCLED KATAKANA WI
+32FD ; mapped ; 30F1 # 1.1 CIRCLED KATAKANA WE
+32FE ; mapped ; 30F2 # 1.1 CIRCLED KATAKANA WO
+32FF ; mapped ; 4EE4 548C # 12.1 SQUARE ERA NAME REIWA
+3300 ; mapped ; 30A2 30D1 30FC 30C8 #1.1 SQUARE APAATO
+3301 ; mapped ; 30A2 30EB 30D5 30A1 #1.1 SQUARE ARUHUA
+3302 ; mapped ; 30A2 30F3 30DA 30A2 #1.1 SQUARE ANPEA
+3303 ; mapped ; 30A2 30FC 30EB #1.1 SQUARE AARU
+3304 ; mapped ; 30A4 30CB 30F3 30B0 #1.1 SQUARE ININGU
+3305 ; mapped ; 30A4 30F3 30C1 #1.1 SQUARE INTI
+3306 ; mapped ; 30A6 30A9 30F3 #1.1 SQUARE UON
+3307 ; mapped ; 30A8 30B9 30AF 30FC 30C9 #1.1 SQUARE ESUKUUDO
+3308 ; mapped ; 30A8 30FC 30AB 30FC #1.1 SQUARE EEKAA
+3309 ; mapped ; 30AA 30F3 30B9 #1.1 SQUARE ONSU
+330A ; mapped ; 30AA 30FC 30E0 #1.1 SQUARE OOMU
+330B ; mapped ; 30AB 30A4 30EA #1.1 SQUARE KAIRI
+330C ; mapped ; 30AB 30E9 30C3 30C8 #1.1 SQUARE KARATTO
+330D ; mapped ; 30AB 30ED 30EA 30FC #1.1 SQUARE KARORII
+330E ; mapped ; 30AC 30ED 30F3 #1.1 SQUARE GARON
+330F ; mapped ; 30AC 30F3 30DE #1.1 SQUARE GANMA
+3310 ; mapped ; 30AE 30AC # 1.1 SQUARE GIGA
+3311 ; mapped ; 30AE 30CB 30FC #1.1 SQUARE GINII
+3312 ; mapped ; 30AD 30E5 30EA 30FC #1.1 SQUARE KYURII
+3313 ; mapped ; 30AE 30EB 30C0 30FC #1.1 SQUARE GIRUDAA
+3314 ; mapped ; 30AD 30ED # 1.1 SQUARE KIRO
+3315 ; mapped ; 30AD 30ED 30B0 30E9 30E0 #1.1 SQUARE KIROGURAMU
+3316 ; mapped ; 30AD 30ED 30E1 30FC 30C8 30EB #1.1 SQUARE KIROMEETORU
+3317 ; mapped ; 30AD 30ED 30EF 30C3 30C8 #1.1 SQUARE KIROWATTO
+3318 ; mapped ; 30B0 30E9 30E0 #1.1 SQUARE GURAMU
+3319 ; mapped ; 30B0 30E9 30E0 30C8 30F3 #1.1 SQUARE GURAMUTON
+331A ; mapped ; 30AF 30EB 30BC 30A4 30ED #1.1 SQUARE KURUZEIRO
+331B ; mapped ; 30AF 30ED 30FC 30CD #1.1 SQUARE KUROONE
+331C ; mapped ; 30B1 30FC 30B9 #1.1 SQUARE KEESU
+331D ; mapped ; 30B3 30EB 30CA #1.1 SQUARE KORUNA
+331E ; mapped ; 30B3 30FC 30DD #1.1 SQUARE KOOPO
+331F ; mapped ; 30B5 30A4 30AF 30EB #1.1 SQUARE SAIKURU
+3320 ; mapped ; 30B5 30F3 30C1 30FC 30E0 #1.1 SQUARE SANTIIMU
+3321 ; mapped ; 30B7 30EA 30F3 30B0 #1.1 SQUARE SIRINGU
+3322 ; mapped ; 30BB 30F3 30C1 #1.1 SQUARE SENTI
+3323 ; mapped ; 30BB 30F3 30C8 #1.1 SQUARE SENTO
+3324 ; mapped ; 30C0 30FC 30B9 #1.1 SQUARE DAASU
+3325 ; mapped ; 30C7 30B7 # 1.1 SQUARE DESI
+3326 ; mapped ; 30C9 30EB # 1.1 SQUARE DORU
+3327 ; mapped ; 30C8 30F3 # 1.1 SQUARE TON
+3328 ; mapped ; 30CA 30CE # 1.1 SQUARE NANO
+3329 ; mapped ; 30CE 30C3 30C8 #1.1 SQUARE NOTTO
+332A ; mapped ; 30CF 30A4 30C4 #1.1 SQUARE HAITU
+332B ; mapped ; 30D1 30FC 30BB 30F3 30C8 #1.1 SQUARE PAASENTO
+332C ; mapped ; 30D1 30FC 30C4 #1.1 SQUARE PAATU
+332D ; mapped ; 30D0 30FC 30EC 30EB #1.1 SQUARE BAARERU
+332E ; mapped ; 30D4 30A2 30B9 30C8 30EB #1.1 SQUARE PIASUTORU
+332F ; mapped ; 30D4 30AF 30EB #1.1 SQUARE PIKURU
+3330 ; mapped ; 30D4 30B3 # 1.1 SQUARE PIKO
+3331 ; mapped ; 30D3 30EB # 1.1 SQUARE BIRU
+3332 ; mapped ; 30D5 30A1 30E9 30C3 30C9 #1.1 SQUARE HUARADDO
+3333 ; mapped ; 30D5 30A3 30FC 30C8 #1.1 SQUARE HUIITO
+3334 ; mapped ; 30D6 30C3 30B7 30A7 30EB #1.1 SQUARE BUSSYERU
+3335 ; mapped ; 30D5 30E9 30F3 #1.1 SQUARE HURAN
+3336 ; mapped ; 30D8 30AF 30BF 30FC 30EB #1.1 SQUARE HEKUTAARU
+3337 ; mapped ; 30DA 30BD # 1.1 SQUARE PESO
+3338 ; mapped ; 30DA 30CB 30D2 #1.1 SQUARE PENIHI
+3339 ; mapped ; 30D8 30EB 30C4 #1.1 SQUARE HERUTU
+333A ; mapped ; 30DA 30F3 30B9 #1.1 SQUARE PENSU
+333B ; mapped ; 30DA 30FC 30B8 #1.1 SQUARE PEEZI
+333C ; mapped ; 30D9 30FC 30BF #1.1 SQUARE BEETA
+333D ; mapped ; 30DD 30A4 30F3 30C8 #1.1 SQUARE POINTO
+333E ; mapped ; 30DC 30EB 30C8 #1.1 SQUARE BORUTO
+333F ; mapped ; 30DB 30F3 # 1.1 SQUARE HON
+3340 ; mapped ; 30DD 30F3 30C9 #1.1 SQUARE PONDO
+3341 ; mapped ; 30DB 30FC 30EB #1.1 SQUARE HOORU
+3342 ; mapped ; 30DB 30FC 30F3 #1.1 SQUARE HOON
+3343 ; mapped ; 30DE 30A4 30AF 30ED #1.1 SQUARE MAIKURO
+3344 ; mapped ; 30DE 30A4 30EB #1.1 SQUARE MAIRU
+3345 ; mapped ; 30DE 30C3 30CF #1.1 SQUARE MAHHA
+3346 ; mapped ; 30DE 30EB 30AF #1.1 SQUARE MARUKU
+3347 ; mapped ; 30DE 30F3 30B7 30E7 30F3 #1.1 SQUARE MANSYON
+3348 ; mapped ; 30DF 30AF 30ED 30F3 #1.1 SQUARE MIKURON
+3349 ; mapped ; 30DF 30EA # 1.1 SQUARE MIRI
+334A ; mapped ; 30DF 30EA 30D0 30FC 30EB #1.1 SQUARE MIRIBAARU
+334B ; mapped ; 30E1 30AC # 1.1 SQUARE MEGA
+334C ; mapped ; 30E1 30AC 30C8 30F3 #1.1 SQUARE MEGATON
+334D ; mapped ; 30E1 30FC 30C8 30EB #1.1 SQUARE MEETORU
+334E ; mapped ; 30E4 30FC 30C9 #1.1 SQUARE YAADO
+334F ; mapped ; 30E4 30FC 30EB #1.1 SQUARE YAARU
+3350 ; mapped ; 30E6 30A2 30F3 #1.1 SQUARE YUAN
+3351 ; mapped ; 30EA 30C3 30C8 30EB #1.1 SQUARE RITTORU
+3352 ; mapped ; 30EA 30E9 # 1.1 SQUARE RIRA
+3353 ; mapped ; 30EB 30D4 30FC #1.1 SQUARE RUPII
+3354 ; mapped ; 30EB 30FC 30D6 30EB #1.1 SQUARE RUUBURU
+3355 ; mapped ; 30EC 30E0 # 1.1 SQUARE REMU
+3356 ; mapped ; 30EC 30F3 30C8 30B2 30F3 #1.1 SQUARE RENTOGEN
+3357 ; mapped ; 30EF 30C3 30C8 #1.1 SQUARE WATTO
+3358 ; mapped ; 0030 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO
+3359 ; mapped ; 0031 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE
+335A ; mapped ; 0032 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO
+335B ; mapped ; 0033 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE
+335C ; mapped ; 0034 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR
+335D ; mapped ; 0035 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE
+335E ; mapped ; 0036 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX
+335F ; mapped ; 0037 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN
+3360 ; mapped ; 0038 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT
+3361 ; mapped ; 0039 70B9 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE
+3362 ; mapped ; 0031 0030 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN
+3363 ; mapped ; 0031 0031 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN
+3364 ; mapped ; 0031 0032 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE
+3365 ; mapped ; 0031 0033 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN
+3366 ; mapped ; 0031 0034 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN
+3367 ; mapped ; 0031 0035 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN
+3368 ; mapped ; 0031 0036 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN
+3369 ; mapped ; 0031 0037 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN
+336A ; mapped ; 0031 0038 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN
+336B ; mapped ; 0031 0039 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN
+336C ; mapped ; 0032 0030 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY
+336D ; mapped ; 0032 0031 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE
+336E ; mapped ; 0032 0032 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO
+336F ; mapped ; 0032 0033 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE
+3370 ; mapped ; 0032 0034 70B9 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR
+3371 ; mapped ; 0068 0070 0061 #1.1 SQUARE HPA
+3372 ; mapped ; 0064 0061 # 1.1 SQUARE DA
+3373 ; mapped ; 0061 0075 # 1.1 SQUARE AU
+3374 ; mapped ; 0062 0061 0072 #1.1 SQUARE BAR
+3375 ; mapped ; 006F 0076 # 1.1 SQUARE OV
+3376 ; mapped ; 0070 0063 # 1.1 SQUARE PC
+3377 ; mapped ; 0064 006D # 4.0 SQUARE DM
+3378 ; mapped ; 0064 006D 0032 #4.0 SQUARE DM SQUARED
+3379 ; mapped ; 0064 006D 0033 #4.0 SQUARE DM CUBED
+337A ; mapped ; 0069 0075 # 4.0 SQUARE IU
+337B ; mapped ; 5E73 6210 # 1.1 SQUARE ERA NAME HEISEI
+337C ; mapped ; 662D 548C # 1.1 SQUARE ERA NAME SYOUWA
+337D ; mapped ; 5927 6B63 # 1.1 SQUARE ERA NAME TAISYOU
+337E ; mapped ; 660E 6CBB # 1.1 SQUARE ERA NAME MEIZI
+337F ; mapped ; 682A 5F0F 4F1A 793E #1.1 SQUARE CORPORATION
+3380 ; mapped ; 0070 0061 # 1.1 SQUARE PA AMPS
+3381 ; mapped ; 006E 0061 # 1.1 SQUARE NA
+3382 ; mapped ; 03BC 0061 # 1.1 SQUARE MU A
+3383 ; mapped ; 006D 0061 # 1.1 SQUARE MA
+3384 ; mapped ; 006B 0061 # 1.1 SQUARE KA
+3385 ; mapped ; 006B 0062 # 1.1 SQUARE KB
+3386 ; mapped ; 006D 0062 # 1.1 SQUARE MB
+3387 ; mapped ; 0067 0062 # 1.1 SQUARE GB
+3388 ; mapped ; 0063 0061 006C #1.1 SQUARE CAL
+3389 ; mapped ; 006B 0063 0061 006C #1.1 SQUARE KCAL
+338A ; mapped ; 0070 0066 # 1.1 SQUARE PF
+338B ; mapped ; 006E 0066 # 1.1 SQUARE NF
+338C ; mapped ; 03BC 0066 # 1.1 SQUARE MU F
+338D ; mapped ; 03BC 0067 # 1.1 SQUARE MU G
+338E ; mapped ; 006D 0067 # 1.1 SQUARE MG
+338F ; mapped ; 006B 0067 # 1.1 SQUARE KG
+3390 ; mapped ; 0068 007A # 1.1 SQUARE HZ
+3391 ; mapped ; 006B 0068 007A #1.1 SQUARE KHZ
+3392 ; mapped ; 006D 0068 007A #1.1 SQUARE MHZ
+3393 ; mapped ; 0067 0068 007A #1.1 SQUARE GHZ
+3394 ; mapped ; 0074 0068 007A #1.1 SQUARE THZ
+3395 ; mapped ; 03BC 006C # 1.1 SQUARE MU L
+3396 ; mapped ; 006D 006C # 1.1 SQUARE ML
+3397 ; mapped ; 0064 006C # 1.1 SQUARE DL
+3398 ; mapped ; 006B 006C # 1.1 SQUARE KL
+3399 ; mapped ; 0066 006D # 1.1 SQUARE FM
+339A ; mapped ; 006E 006D # 1.1 SQUARE NM
+339B ; mapped ; 03BC 006D # 1.1 SQUARE MU M
+339C ; mapped ; 006D 006D # 1.1 SQUARE MM
+339D ; mapped ; 0063 006D # 1.1 SQUARE CM
+339E ; mapped ; 006B 006D # 1.1 SQUARE KM
+339F ; mapped ; 006D 006D 0032 #1.1 SQUARE MM SQUARED
+33A0 ; mapped ; 0063 006D 0032 #1.1 SQUARE CM SQUARED
+33A1 ; mapped ; 006D 0032 # 1.1 SQUARE M SQUARED
+33A2 ; mapped ; 006B 006D 0032 #1.1 SQUARE KM SQUARED
+33A3 ; mapped ; 006D 006D 0033 #1.1 SQUARE MM CUBED
+33A4 ; mapped ; 0063 006D 0033 #1.1 SQUARE CM CUBED
+33A5 ; mapped ; 006D 0033 # 1.1 SQUARE M CUBED
+33A6 ; mapped ; 006B 006D 0033 #1.1 SQUARE KM CUBED
+33A7 ; mapped ; 006D 2215 0073 #1.1 SQUARE M OVER S
+33A8 ; mapped ; 006D 2215 0073 0032 #1.1 SQUARE M OVER S SQUARED
+33A9 ; mapped ; 0070 0061 # 1.1 SQUARE PA
+33AA ; mapped ; 006B 0070 0061 #1.1 SQUARE KPA
+33AB ; mapped ; 006D 0070 0061 #1.1 SQUARE MPA
+33AC ; mapped ; 0067 0070 0061 #1.1 SQUARE GPA
+33AD ; mapped ; 0072 0061 0064 #1.1 SQUARE RAD
+33AE ; mapped ; 0072 0061 0064 2215 0073 #1.1 SQUARE RAD OVER S
+33AF ; mapped ; 0072 0061 0064 2215 0073 0032 #1.1 SQUARE RAD OVER S SQUARED
+33B0 ; mapped ; 0070 0073 # 1.1 SQUARE PS
+33B1 ; mapped ; 006E 0073 # 1.1 SQUARE NS
+33B2 ; mapped ; 03BC 0073 # 1.1 SQUARE MU S
+33B3 ; mapped ; 006D 0073 # 1.1 SQUARE MS
+33B4 ; mapped ; 0070 0076 # 1.1 SQUARE PV
+33B5 ; mapped ; 006E 0076 # 1.1 SQUARE NV
+33B6 ; mapped ; 03BC 0076 # 1.1 SQUARE MU V
+33B7 ; mapped ; 006D 0076 # 1.1 SQUARE MV
+33B8 ; mapped ; 006B 0076 # 1.1 SQUARE KV
+33B9 ; mapped ; 006D 0076 # 1.1 SQUARE MV MEGA
+33BA ; mapped ; 0070 0077 # 1.1 SQUARE PW
+33BB ; mapped ; 006E 0077 # 1.1 SQUARE NW
+33BC ; mapped ; 03BC 0077 # 1.1 SQUARE MU W
+33BD ; mapped ; 006D 0077 # 1.1 SQUARE MW
+33BE ; mapped ; 006B 0077 # 1.1 SQUARE KW
+33BF ; mapped ; 006D 0077 # 1.1 SQUARE MW MEGA
+33C0 ; mapped ; 006B 03C9 # 1.1 SQUARE K OHM
+33C1 ; mapped ; 006D 03C9 # 1.1 SQUARE M OHM
+33C2 ; disallowed # 1.1 SQUARE AM
+33C3 ; mapped ; 0062 0071 # 1.1 SQUARE BQ
+33C4 ; mapped ; 0063 0063 # 1.1 SQUARE CC
+33C5 ; mapped ; 0063 0064 # 1.1 SQUARE CD
+33C6 ; mapped ; 0063 2215 006B 0067 #1.1 SQUARE C OVER KG
+33C7 ; disallowed # 1.1 SQUARE CO
+33C8 ; mapped ; 0064 0062 # 1.1 SQUARE DB
+33C9 ; mapped ; 0067 0079 # 1.1 SQUARE GY
+33CA ; mapped ; 0068 0061 # 1.1 SQUARE HA
+33CB ; mapped ; 0068 0070 # 1.1 SQUARE HP
+33CC ; mapped ; 0069 006E # 1.1 SQUARE IN
+33CD ; mapped ; 006B 006B # 1.1 SQUARE KK
+33CE ; mapped ; 006B 006D # 1.1 SQUARE KM CAPITAL
+33CF ; mapped ; 006B 0074 # 1.1 SQUARE KT
+33D0 ; mapped ; 006C 006D # 1.1 SQUARE LM
+33D1 ; mapped ; 006C 006E # 1.1 SQUARE LN
+33D2 ; mapped ; 006C 006F 0067 #1.1 SQUARE LOG
+33D3 ; mapped ; 006C 0078 # 1.1 SQUARE LX
+33D4 ; mapped ; 006D 0062 # 1.1 SQUARE MB SMALL
+33D5 ; mapped ; 006D 0069 006C #1.1 SQUARE MIL
+33D6 ; mapped ; 006D 006F 006C #1.1 SQUARE MOL
+33D7 ; mapped ; 0070 0068 # 1.1 SQUARE PH
+33D8 ; disallowed # 1.1 SQUARE PM
+33D9 ; mapped ; 0070 0070 006D #1.1 SQUARE PPM
+33DA ; mapped ; 0070 0072 # 1.1 SQUARE PR
+33DB ; mapped ; 0073 0072 # 1.1 SQUARE SR
+33DC ; mapped ; 0073 0076 # 1.1 SQUARE SV
+33DD ; mapped ; 0077 0062 # 1.1 SQUARE WB
+33DE ; mapped ; 0076 2215 006D #4.0 SQUARE V OVER M
+33DF ; mapped ; 0061 2215 006D #4.0 SQUARE A OVER M
+33E0 ; mapped ; 0031 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE
+33E1 ; mapped ; 0032 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO
+33E2 ; mapped ; 0033 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE
+33E3 ; mapped ; 0034 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR
+33E4 ; mapped ; 0035 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE
+33E5 ; mapped ; 0036 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX
+33E6 ; mapped ; 0037 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN
+33E7 ; mapped ; 0038 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT
+33E8 ; mapped ; 0039 65E5 # 1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE
+33E9 ; mapped ; 0031 0030 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN
+33EA ; mapped ; 0031 0031 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN
+33EB ; mapped ; 0031 0032 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE
+33EC ; mapped ; 0031 0033 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN
+33ED ; mapped ; 0031 0034 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN
+33EE ; mapped ; 0031 0035 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN
+33EF ; mapped ; 0031 0036 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN
+33F0 ; mapped ; 0031 0037 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN
+33F1 ; mapped ; 0031 0038 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN
+33F2 ; mapped ; 0031 0039 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN
+33F3 ; mapped ; 0032 0030 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY
+33F4 ; mapped ; 0032 0031 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE
+33F5 ; mapped ; 0032 0032 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO
+33F6 ; mapped ; 0032 0033 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE
+33F7 ; mapped ; 0032 0034 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR
+33F8 ; mapped ; 0032 0035 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE
+33F9 ; mapped ; 0032 0036 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX
+33FA ; mapped ; 0032 0037 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN
+33FB ; mapped ; 0032 0038 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT
+33FC ; mapped ; 0032 0039 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE
+33FD ; mapped ; 0033 0030 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY
+33FE ; mapped ; 0033 0031 65E5 #1.1 IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE
+33FF ; mapped ; 0067 0061 006C #4.0 SQUARE GAL
+3400..4DB5 ; valid # 3.0 CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
+4DB6..4DBF ; valid # 13.0 CJK UNIFIED IDEOGRAPH-4DB6..CJK UNIFIED IDEOGRAPH-4DBF
+4DC0..4DFF ; valid ; ; NV8 # 4.0 HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
+4E00..9FA5 ; valid # 1.1 CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FA5
+9FA6..9FBB ; valid # 4.1 CJK UNIFIED IDEOGRAPH-9FA6..CJK UNIFIED IDEOGRAPH-9FBB
+9FBC..9FC3 ; valid # 5.1 CJK UNIFIED IDEOGRAPH-9FBC..CJK UNIFIED IDEOGRAPH-9FC3
+9FC4..9FCB ; valid # 5.2 CJK UNIFIED IDEOGRAPH-9FC4..CJK UNIFIED IDEOGRAPH-9FCB
+9FCC ; valid # 6.1 CJK UNIFIED IDEOGRAPH-9FCC
+9FCD..9FD5 ; valid # 8.0 CJK UNIFIED IDEOGRAPH-9FCD..CJK UNIFIED IDEOGRAPH-9FD5
+9FD6..9FEA ; valid # 10.0 CJK UNIFIED IDEOGRAPH-9FD6..CJK UNIFIED IDEOGRAPH-9FEA
+9FEB..9FEF ; valid # 11.0 CJK UNIFIED IDEOGRAPH-9FEB..CJK UNIFIED IDEOGRAPH-9FEF
+9FF0..9FFC ; valid # 13.0 CJK UNIFIED IDEOGRAPH-9FF0..CJK UNIFIED IDEOGRAPH-9FFC
+9FFD..9FFF ; valid # 14.0 CJK UNIFIED IDEOGRAPH-9FFD..CJK UNIFIED IDEOGRAPH-9FFF
+A000..A48C ; valid # 3.0 YI SYLLABLE IT..YI SYLLABLE YYR
+A48D..A48F ; disallowed # NA <reserved-A48D>..<reserved-A48F>
+A490..A4A1 ; valid ; ; NV8 # 3.0 YI RADICAL QOT..YI RADICAL GA
+A4A2..A4A3 ; valid ; ; NV8 # 3.2 YI RADICAL ZUP..YI RADICAL CYT
+A4A4..A4B3 ; valid ; ; NV8 # 3.0 YI RADICAL DDUR..YI RADICAL JO
+A4B4 ; valid ; ; NV8 # 3.2 YI RADICAL NZUP
+A4B5..A4C0 ; valid ; ; NV8 # 3.0 YI RADICAL JJY..YI RADICAL SHAT
+A4C1 ; valid ; ; NV8 # 3.2 YI RADICAL ZUR
+A4C2..A4C4 ; valid ; ; NV8 # 3.0 YI RADICAL SHOP..YI RADICAL ZZIET
+A4C5 ; valid ; ; NV8 # 3.2 YI RADICAL NBIE
+A4C6 ; valid ; ; NV8 # 3.0 YI RADICAL KE
+A4C7..A4CF ; disallowed # NA <reserved-A4C7>..<reserved-A4CF>
+A4D0..A4FD ; valid # 5.2 LISU LETTER BA..LISU LETTER TONE MYA JEU
+A4FE..A4FF ; valid ; ; NV8 # 5.2 LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
+A500..A60C ; valid # 5.1 VAI SYLLABLE EE..VAI SYLLABLE LENGTHENER
+A60D..A60F ; valid ; ; NV8 # 5.1 VAI COMMA..VAI QUESTION MARK
+A610..A62B ; valid # 5.1 VAI SYLLABLE NDOLE FA..VAI SYLLABLE NDOLE DO
+A62C..A63F ; disallowed # NA <reserved-A62C>..<reserved-A63F>
+A640 ; mapped ; A641 # 5.1 CYRILLIC CAPITAL LETTER ZEMLYA
+A641 ; valid # 5.1 CYRILLIC SMALL LETTER ZEMLYA
+A642 ; mapped ; A643 # 5.1 CYRILLIC CAPITAL LETTER DZELO
+A643 ; valid # 5.1 CYRILLIC SMALL LETTER DZELO
+A644 ; mapped ; A645 # 5.1 CYRILLIC CAPITAL LETTER REVERSED DZE
+A645 ; valid # 5.1 CYRILLIC SMALL LETTER REVERSED DZE
+A646 ; mapped ; A647 # 5.1 CYRILLIC CAPITAL LETTER IOTA
+A647 ; valid # 5.1 CYRILLIC SMALL LETTER IOTA
+A648 ; mapped ; A649 # 5.1 CYRILLIC CAPITAL LETTER DJERV
+A649 ; valid # 5.1 CYRILLIC SMALL LETTER DJERV
+A64A ; mapped ; A64B # 5.1 CYRILLIC CAPITAL LETTER MONOGRAPH UK
+A64B ; valid # 5.1 CYRILLIC SMALL LETTER MONOGRAPH UK
+A64C ; mapped ; A64D # 5.1 CYRILLIC CAPITAL LETTER BROAD OMEGA
+A64D ; valid # 5.1 CYRILLIC SMALL LETTER BROAD OMEGA
+A64E ; mapped ; A64F # 5.1 CYRILLIC CAPITAL LETTER NEUTRAL YER
+A64F ; valid # 5.1 CYRILLIC SMALL LETTER NEUTRAL YER
+A650 ; mapped ; A651 # 5.1 CYRILLIC CAPITAL LETTER YERU WITH BACK YER
+A651 ; valid # 5.1 CYRILLIC SMALL LETTER YERU WITH BACK YER
+A652 ; mapped ; A653 # 5.1 CYRILLIC CAPITAL LETTER IOTIFIED YAT
+A653 ; valid # 5.1 CYRILLIC SMALL LETTER IOTIFIED YAT
+A654 ; mapped ; A655 # 5.1 CYRILLIC CAPITAL LETTER REVERSED YU
+A655 ; valid # 5.1 CYRILLIC SMALL LETTER REVERSED YU
+A656 ; mapped ; A657 # 5.1 CYRILLIC CAPITAL LETTER IOTIFIED A
+A657 ; valid # 5.1 CYRILLIC SMALL LETTER IOTIFIED A
+A658 ; mapped ; A659 # 5.1 CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
+A659 ; valid # 5.1 CYRILLIC SMALL LETTER CLOSED LITTLE YUS
+A65A ; mapped ; A65B # 5.1 CYRILLIC CAPITAL LETTER BLENDED YUS
+A65B ; valid # 5.1 CYRILLIC SMALL LETTER BLENDED YUS
+A65C ; mapped ; A65D # 5.1 CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
+A65D ; valid # 5.1 CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS
+A65E ; mapped ; A65F # 5.1 CYRILLIC CAPITAL LETTER YN
+A65F ; valid # 5.1 CYRILLIC SMALL LETTER YN
+A660 ; mapped ; A661 # 6.0 CYRILLIC CAPITAL LETTER REVERSED TSE
+A661 ; valid # 6.0 CYRILLIC SMALL LETTER REVERSED TSE
+A662 ; mapped ; A663 # 5.1 CYRILLIC CAPITAL LETTER SOFT DE
+A663 ; valid # 5.1 CYRILLIC SMALL LETTER SOFT DE
+A664 ; mapped ; A665 # 5.1 CYRILLIC CAPITAL LETTER SOFT EL
+A665 ; valid # 5.1 CYRILLIC SMALL LETTER SOFT EL
+A666 ; mapped ; A667 # 5.1 CYRILLIC CAPITAL LETTER SOFT EM
+A667 ; valid # 5.1 CYRILLIC SMALL LETTER SOFT EM
+A668 ; mapped ; A669 # 5.1 CYRILLIC CAPITAL LETTER MONOCULAR O
+A669 ; valid # 5.1 CYRILLIC SMALL LETTER MONOCULAR O
+A66A ; mapped ; A66B # 5.1 CYRILLIC CAPITAL LETTER BINOCULAR O
+A66B ; valid # 5.1 CYRILLIC SMALL LETTER BINOCULAR O
+A66C ; mapped ; A66D # 5.1 CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
+A66D..A66F ; valid # 5.1 CYRILLIC SMALL LETTER DOUBLE MONOCULAR O..COMBINING CYRILLIC VZMET
+A670..A673 ; valid ; ; NV8 # 5.1 COMBINING CYRILLIC TEN MILLIONS SIGN..SLAVONIC ASTERISK
+A674..A67B ; valid # 6.1 COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC LETTER OMEGA
+A67C..A67D ; valid # 5.1 COMBINING CYRILLIC KAVYKA..COMBINING CYRILLIC PAYEROK
+A67E ; valid ; ; NV8 # 5.1 CYRILLIC KAVYKA
+A67F ; valid # 5.1 CYRILLIC PAYEROK
+A680 ; mapped ; A681 # 5.1 CYRILLIC CAPITAL LETTER DWE
+A681 ; valid # 5.1 CYRILLIC SMALL LETTER DWE
+A682 ; mapped ; A683 # 5.1 CYRILLIC CAPITAL LETTER DZWE
+A683 ; valid # 5.1 CYRILLIC SMALL LETTER DZWE
+A684 ; mapped ; A685 # 5.1 CYRILLIC CAPITAL LETTER ZHWE
+A685 ; valid # 5.1 CYRILLIC SMALL LETTER ZHWE
+A686 ; mapped ; A687 # 5.1 CYRILLIC CAPITAL LETTER CCHE
+A687 ; valid # 5.1 CYRILLIC SMALL LETTER CCHE
+A688 ; mapped ; A689 # 5.1 CYRILLIC CAPITAL LETTER DZZE
+A689 ; valid # 5.1 CYRILLIC SMALL LETTER DZZE
+A68A ; mapped ; A68B # 5.1 CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
+A68B ; valid # 5.1 CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK
+A68C ; mapped ; A68D # 5.1 CYRILLIC CAPITAL LETTER TWE
+A68D ; valid # 5.1 CYRILLIC SMALL LETTER TWE
+A68E ; mapped ; A68F # 5.1 CYRILLIC CAPITAL LETTER TSWE
+A68F ; valid # 5.1 CYRILLIC SMALL LETTER TSWE
+A690 ; mapped ; A691 # 5.1 CYRILLIC CAPITAL LETTER TSSE
+A691 ; valid # 5.1 CYRILLIC SMALL LETTER TSSE
+A692 ; mapped ; A693 # 5.1 CYRILLIC CAPITAL LETTER TCHE
+A693 ; valid # 5.1 CYRILLIC SMALL LETTER TCHE
+A694 ; mapped ; A695 # 5.1 CYRILLIC CAPITAL LETTER HWE
+A695 ; valid # 5.1 CYRILLIC SMALL LETTER HWE
+A696 ; mapped ; A697 # 5.1 CYRILLIC CAPITAL LETTER SHWE
+A697 ; valid # 5.1 CYRILLIC SMALL LETTER SHWE
+A698 ; mapped ; A699 # 7.0 CYRILLIC CAPITAL LETTER DOUBLE O
+A699 ; valid # 7.0 CYRILLIC SMALL LETTER DOUBLE O
+A69A ; mapped ; A69B # 7.0 CYRILLIC CAPITAL LETTER CROSSED O
+A69B ; valid # 7.0 CYRILLIC SMALL LETTER CROSSED O
+A69C ; mapped ; 044A # 7.0 MODIFIER LETTER CYRILLIC HARD SIGN
+A69D ; mapped ; 044C # 7.0 MODIFIER LETTER CYRILLIC SOFT SIGN
+A69E ; valid # 8.0 COMBINING CYRILLIC LETTER EF
+A69F ; valid # 6.1 COMBINING CYRILLIC LETTER IOTIFIED E
+A6A0..A6E5 ; valid # 5.2 BAMUM LETTER A..BAMUM LETTER KI
+A6E6..A6EF ; valid ; ; NV8 # 5.2 BAMUM LETTER MO..BAMUM LETTER KOGHOM
+A6F0..A6F1 ; valid # 5.2 BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
+A6F2..A6F7 ; valid ; ; NV8 # 5.2 BAMUM NJAEMLI..BAMUM QUESTION MARK
+A6F8..A6FF ; disallowed # NA <reserved-A6F8>..<reserved-A6FF>
+A700..A716 ; valid ; ; NV8 # 4.1 MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
+A717..A71A ; valid # 5.0 MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOWER RIGHT CORNER ANGLE
+A71B..A71F ; valid # 5.1 MODIFIER LETTER RAISED UP ARROW..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
+A720..A721 ; valid ; ; NV8 # 5.0 MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE
+A722 ; mapped ; A723 # 5.1 LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
+A723 ; valid # 5.1 LATIN SMALL LETTER EGYPTOLOGICAL ALEF
+A724 ; mapped ; A725 # 5.1 LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
+A725 ; valid # 5.1 LATIN SMALL LETTER EGYPTOLOGICAL AIN
+A726 ; mapped ; A727 # 5.1 LATIN CAPITAL LETTER HENG
+A727 ; valid # 5.1 LATIN SMALL LETTER HENG
+A728 ; mapped ; A729 # 5.1 LATIN CAPITAL LETTER TZ
+A729 ; valid # 5.1 LATIN SMALL LETTER TZ
+A72A ; mapped ; A72B # 5.1 LATIN CAPITAL LETTER TRESILLO
+A72B ; valid # 5.1 LATIN SMALL LETTER TRESILLO
+A72C ; mapped ; A72D # 5.1 LATIN CAPITAL LETTER CUATRILLO
+A72D ; valid # 5.1 LATIN SMALL LETTER CUATRILLO
+A72E ; mapped ; A72F # 5.1 LATIN CAPITAL LETTER CUATRILLO WITH COMMA
+A72F..A731 ; valid # 5.1 LATIN SMALL LETTER CUATRILLO WITH COMMA..LATIN LETTER SMALL CAPITAL S
+A732 ; mapped ; A733 # 5.1 LATIN CAPITAL LETTER AA
+A733 ; valid # 5.1 LATIN SMALL LETTER AA
+A734 ; mapped ; A735 # 5.1 LATIN CAPITAL LETTER AO
+A735 ; valid # 5.1 LATIN SMALL LETTER AO
+A736 ; mapped ; A737 # 5.1 LATIN CAPITAL LETTER AU
+A737 ; valid # 5.1 LATIN SMALL LETTER AU
+A738 ; mapped ; A739 # 5.1 LATIN CAPITAL LETTER AV
+A739 ; valid # 5.1 LATIN SMALL LETTER AV
+A73A ; mapped ; A73B # 5.1 LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
+A73B ; valid # 5.1 LATIN SMALL LETTER AV WITH HORIZONTAL BAR
+A73C ; mapped ; A73D # 5.1 LATIN CAPITAL LETTER AY
+A73D ; valid # 5.1 LATIN SMALL LETTER AY
+A73E ; mapped ; A73F # 5.1 LATIN CAPITAL LETTER REVERSED C WITH DOT
+A73F ; valid # 5.1 LATIN SMALL LETTER REVERSED C WITH DOT
+A740 ; mapped ; A741 # 5.1 LATIN CAPITAL LETTER K WITH STROKE
+A741 ; valid # 5.1 LATIN SMALL LETTER K WITH STROKE
+A742 ; mapped ; A743 # 5.1 LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
+A743 ; valid # 5.1 LATIN SMALL LETTER K WITH DIAGONAL STROKE
+A744 ; mapped ; A745 # 5.1 LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
+A745 ; valid # 5.1 LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE
+A746 ; mapped ; A747 # 5.1 LATIN CAPITAL LETTER BROKEN L
+A747 ; valid # 5.1 LATIN SMALL LETTER BROKEN L
+A748 ; mapped ; A749 # 5.1 LATIN CAPITAL LETTER L WITH HIGH STROKE
+A749 ; valid # 5.1 LATIN SMALL LETTER L WITH HIGH STROKE
+A74A ; mapped ; A74B # 5.1 LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
+A74B ; valid # 5.1 LATIN SMALL LETTER O WITH LONG STROKE OVERLAY
+A74C ; mapped ; A74D # 5.1 LATIN CAPITAL LETTER O WITH LOOP
+A74D ; valid # 5.1 LATIN SMALL LETTER O WITH LOOP
+A74E ; mapped ; A74F # 5.1 LATIN CAPITAL LETTER OO
+A74F ; valid # 5.1 LATIN SMALL LETTER OO
+A750 ; mapped ; A751 # 5.1 LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
+A751 ; valid # 5.1 LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER
+A752 ; mapped ; A753 # 5.1 LATIN CAPITAL LETTER P WITH FLOURISH
+A753 ; valid # 5.1 LATIN SMALL LETTER P WITH FLOURISH
+A754 ; mapped ; A755 # 5.1 LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
+A755 ; valid # 5.1 LATIN SMALL LETTER P WITH SQUIRREL TAIL
+A756 ; mapped ; A757 # 5.1 LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
+A757 ; valid # 5.1 LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER
+A758 ; mapped ; A759 # 5.1 LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
+A759 ; valid # 5.1 LATIN SMALL LETTER Q WITH DIAGONAL STROKE
+A75A ; mapped ; A75B # 5.1 LATIN CAPITAL LETTER R ROTUNDA
+A75B ; valid # 5.1 LATIN SMALL LETTER R ROTUNDA
+A75C ; mapped ; A75D # 5.1 LATIN CAPITAL LETTER RUM ROTUNDA
+A75D ; valid # 5.1 LATIN SMALL LETTER RUM ROTUNDA
+A75E ; mapped ; A75F # 5.1 LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
+A75F ; valid # 5.1 LATIN SMALL LETTER V WITH DIAGONAL STROKE
+A760 ; mapped ; A761 # 5.1 LATIN CAPITAL LETTER VY
+A761 ; valid # 5.1 LATIN SMALL LETTER VY
+A762 ; mapped ; A763 # 5.1 LATIN CAPITAL LETTER VISIGOTHIC Z
+A763 ; valid # 5.1 LATIN SMALL LETTER VISIGOTHIC Z
+A764 ; mapped ; A765 # 5.1 LATIN CAPITAL LETTER THORN WITH STROKE
+A765 ; valid # 5.1 LATIN SMALL LETTER THORN WITH STROKE
+A766 ; mapped ; A767 # 5.1 LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
+A767 ; valid # 5.1 LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER
+A768 ; mapped ; A769 # 5.1 LATIN CAPITAL LETTER VEND
+A769 ; valid # 5.1 LATIN SMALL LETTER VEND
+A76A ; mapped ; A76B # 5.1 LATIN CAPITAL LETTER ET
+A76B ; valid # 5.1 LATIN SMALL LETTER ET
+A76C ; mapped ; A76D # 5.1 LATIN CAPITAL LETTER IS
+A76D ; valid # 5.1 LATIN SMALL LETTER IS
+A76E ; mapped ; A76F # 5.1 LATIN CAPITAL LETTER CON
+A76F ; valid # 5.1 LATIN SMALL LETTER CON
+A770 ; mapped ; A76F # 5.1 MODIFIER LETTER US
+A771..A778 ; valid # 5.1 LATIN SMALL LETTER DUM..LATIN SMALL LETTER UM
+A779 ; mapped ; A77A # 5.1 LATIN CAPITAL LETTER INSULAR D
+A77A ; valid # 5.1 LATIN SMALL LETTER INSULAR D
+A77B ; mapped ; A77C # 5.1 LATIN CAPITAL LETTER INSULAR F
+A77C ; valid # 5.1 LATIN SMALL LETTER INSULAR F
+A77D ; mapped ; 1D79 # 5.1 LATIN CAPITAL LETTER INSULAR G
+A77E ; mapped ; A77F # 5.1 LATIN CAPITAL LETTER TURNED INSULAR G
+A77F ; valid # 5.1 LATIN SMALL LETTER TURNED INSULAR G
+A780 ; mapped ; A781 # 5.1 LATIN CAPITAL LETTER TURNED L
+A781 ; valid # 5.1 LATIN SMALL LETTER TURNED L
+A782 ; mapped ; A783 # 5.1 LATIN CAPITAL LETTER INSULAR R
+A783 ; valid # 5.1 LATIN SMALL LETTER INSULAR R
+A784 ; mapped ; A785 # 5.1 LATIN CAPITAL LETTER INSULAR S
+A785 ; valid # 5.1 LATIN SMALL LETTER INSULAR S
+A786 ; mapped ; A787 # 5.1 LATIN CAPITAL LETTER INSULAR T
+A787..A788 ; valid # 5.1 LATIN SMALL LETTER INSULAR T..MODIFIER LETTER LOW CIRCUMFLEX ACCENT
+A789..A78A ; valid ; ; NV8 # 5.1 MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
+A78B ; mapped ; A78C # 5.1 LATIN CAPITAL LETTER SALTILLO
+A78C ; valid # 5.1 LATIN SMALL LETTER SALTILLO
+A78D ; mapped ; 0265 # 6.0 LATIN CAPITAL LETTER TURNED H
+A78E ; valid # 6.0 LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+A78F ; valid # 8.0 LATIN LETTER SINOLOGICAL DOT
+A790 ; mapped ; A791 # 6.0 LATIN CAPITAL LETTER N WITH DESCENDER
+A791 ; valid # 6.0 LATIN SMALL LETTER N WITH DESCENDER
+A792 ; mapped ; A793 # 6.1 LATIN CAPITAL LETTER C WITH BAR
+A793 ; valid # 6.1 LATIN SMALL LETTER C WITH BAR
+A794..A795 ; valid # 7.0 LATIN SMALL LETTER C WITH PALATAL HOOK..LATIN SMALL LETTER H WITH PALATAL HOOK
+A796 ; mapped ; A797 # 7.0 LATIN CAPITAL LETTER B WITH FLOURISH
+A797 ; valid # 7.0 LATIN SMALL LETTER B WITH FLOURISH
+A798 ; mapped ; A799 # 7.0 LATIN CAPITAL LETTER F WITH STROKE
+A799 ; valid # 7.0 LATIN SMALL LETTER F WITH STROKE
+A79A ; mapped ; A79B # 7.0 LATIN CAPITAL LETTER VOLAPUK AE
+A79B ; valid # 7.0 LATIN SMALL LETTER VOLAPUK AE
+A79C ; mapped ; A79D # 7.0 LATIN CAPITAL LETTER VOLAPUK OE
+A79D ; valid # 7.0 LATIN SMALL LETTER VOLAPUK OE
+A79E ; mapped ; A79F # 7.0 LATIN CAPITAL LETTER VOLAPUK UE
+A79F ; valid # 7.0 LATIN SMALL LETTER VOLAPUK UE
+A7A0 ; mapped ; A7A1 # 6.0 LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
+A7A1 ; valid # 6.0 LATIN SMALL LETTER G WITH OBLIQUE STROKE
+A7A2 ; mapped ; A7A3 # 6.0 LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
+A7A3 ; valid # 6.0 LATIN SMALL LETTER K WITH OBLIQUE STROKE
+A7A4 ; mapped ; A7A5 # 6.0 LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
+A7A5 ; valid # 6.0 LATIN SMALL LETTER N WITH OBLIQUE STROKE
+A7A6 ; mapped ; A7A7 # 6.0 LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
+A7A7 ; valid # 6.0 LATIN SMALL LETTER R WITH OBLIQUE STROKE
+A7A8 ; mapped ; A7A9 # 6.0 LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
+A7A9 ; valid # 6.0 LATIN SMALL LETTER S WITH OBLIQUE STROKE
+A7AA ; mapped ; 0266 # 6.1 LATIN CAPITAL LETTER H WITH HOOK
+A7AB ; mapped ; 025C # 7.0 LATIN CAPITAL LETTER REVERSED OPEN E
+A7AC ; mapped ; 0261 # 7.0 LATIN CAPITAL LETTER SCRIPT G
+A7AD ; mapped ; 026C # 7.0 LATIN CAPITAL LETTER L WITH BELT
+A7AE ; mapped ; 026A # 9.0 LATIN CAPITAL LETTER SMALL CAPITAL I
+A7AF ; valid # 11.0 LATIN LETTER SMALL CAPITAL Q
+A7B0 ; mapped ; 029E # 7.0 LATIN CAPITAL LETTER TURNED K
+A7B1 ; mapped ; 0287 # 7.0 LATIN CAPITAL LETTER TURNED T
+A7B2 ; mapped ; 029D # 8.0 LATIN CAPITAL LETTER J WITH CROSSED-TAIL
+A7B3 ; mapped ; AB53 # 8.0 LATIN CAPITAL LETTER CHI
+A7B4 ; mapped ; A7B5 # 8.0 LATIN CAPITAL LETTER BETA
+A7B5 ; valid # 8.0 LATIN SMALL LETTER BETA
+A7B6 ; mapped ; A7B7 # 8.0 LATIN CAPITAL LETTER OMEGA
+A7B7 ; valid # 8.0 LATIN SMALL LETTER OMEGA
+A7B8 ; mapped ; A7B9 # 11.0 LATIN CAPITAL LETTER U WITH STROKE
+A7B9 ; valid # 11.0 LATIN SMALL LETTER U WITH STROKE
+A7BA ; mapped ; A7BB # 12.0 LATIN CAPITAL LETTER GLOTTAL A
+A7BB ; valid # 12.0 LATIN SMALL LETTER GLOTTAL A
+A7BC ; mapped ; A7BD # 12.0 LATIN CAPITAL LETTER GLOTTAL I
+A7BD ; valid # 12.0 LATIN SMALL LETTER GLOTTAL I
+A7BE ; mapped ; A7BF # 12.0 LATIN CAPITAL LETTER GLOTTAL U
+A7BF ; valid # 12.0 LATIN SMALL LETTER GLOTTAL U
+A7C0 ; mapped ; A7C1 # 14.0 LATIN CAPITAL LETTER OLD POLISH O
+A7C1 ; valid # 14.0 LATIN SMALL LETTER OLD POLISH O
+A7C2 ; mapped ; A7C3 # 12.0 LATIN CAPITAL LETTER ANGLICANA W
+A7C3 ; valid # 12.0 LATIN SMALL LETTER ANGLICANA W
+A7C4 ; mapped ; A794 # 12.0 LATIN CAPITAL LETTER C WITH PALATAL HOOK
+A7C5 ; mapped ; 0282 # 12.0 LATIN CAPITAL LETTER S WITH HOOK
+A7C6 ; mapped ; 1D8E # 12.0 LATIN CAPITAL LETTER Z WITH PALATAL HOOK
+A7C7 ; mapped ; A7C8 # 13.0 LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY
+A7C8 ; valid # 13.0 LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY
+A7C9 ; mapped ; A7CA # 13.0 LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY
+A7CA ; valid # 13.0 LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY
+A7CB..A7CF ; disallowed # NA <reserved-A7CB>..<reserved-A7CF>
+A7D0 ; mapped ; A7D1 # 14.0 LATIN CAPITAL LETTER CLOSED INSULAR G
+A7D1 ; valid # 14.0 LATIN SMALL LETTER CLOSED INSULAR G
+A7D2 ; disallowed # NA <reserved-A7D2>
+A7D3 ; valid # 14.0 LATIN SMALL LETTER DOUBLE THORN
+A7D4 ; disallowed # NA <reserved-A7D4>
+A7D5 ; valid # 14.0 LATIN SMALL LETTER DOUBLE WYNN
+A7D6 ; mapped ; A7D7 # 14.0 LATIN CAPITAL LETTER MIDDLE SCOTS S
+A7D7 ; valid # 14.0 LATIN SMALL LETTER MIDDLE SCOTS S
+A7D8 ; mapped ; A7D9 # 14.0 LATIN CAPITAL LETTER SIGMOID S
+A7D9 ; valid # 14.0 LATIN SMALL LETTER SIGMOID S
+A7DA..A7F1 ; disallowed # NA <reserved-A7DA>..<reserved-A7F1>
+A7F2 ; mapped ; 0063 # 14.0 MODIFIER LETTER CAPITAL C
+A7F3 ; mapped ; 0066 # 14.0 MODIFIER LETTER CAPITAL F
+A7F4 ; mapped ; 0071 # 14.0 MODIFIER LETTER CAPITAL Q
+A7F5 ; mapped ; A7F6 # 13.0 LATIN CAPITAL LETTER REVERSED HALF H
+A7F6 ; valid # 13.0 LATIN SMALL LETTER REVERSED HALF H
+A7F7 ; valid # 7.0 LATIN EPIGRAPHIC LETTER SIDEWAYS I
+A7F8 ; mapped ; 0127 # 6.1 MODIFIER LETTER CAPITAL H WITH STROKE
+A7F9 ; mapped ; 0153 # 6.1 MODIFIER LETTER SMALL LIGATURE OE
+A7FA ; valid # 6.0 LATIN LETTER SMALL CAPITAL TURNED M
+A7FB..A7FF ; valid # 5.1 LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
+A800..A827 ; valid # 4.1 SYLOTI NAGRI LETTER A..SYLOTI NAGRI VOWEL SIGN OO
+A828..A82B ; valid ; ; NV8 # 4.1 SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
+A82C ; valid # 13.0 SYLOTI NAGRI SIGN ALTERNATE HASANTA
+A82D..A82F ; disallowed # NA <reserved-A82D>..<reserved-A82F>
+A830..A839 ; valid ; ; NV8 # 5.2 NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC QUANTITY MARK
+A83A..A83F ; disallowed # NA <reserved-A83A>..<reserved-A83F>
+A840..A873 ; valid # 5.0 PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
+A874..A877 ; valid ; ; NV8 # 5.0 PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
+A878..A87F ; disallowed # NA <reserved-A878>..<reserved-A87F>
+A880..A8C4 ; valid # 5.1 SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VIRAMA
+A8C5 ; valid # 9.0 SAURASHTRA SIGN CANDRABINDU
+A8C6..A8CD ; disallowed # NA <reserved-A8C6>..<reserved-A8CD>
+A8CE..A8CF ; valid ; ; NV8 # 5.1 SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
+A8D0..A8D9 ; valid # 5.1 SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
+A8DA..A8DF ; disallowed # NA <reserved-A8DA>..<reserved-A8DF>
+A8E0..A8F7 ; valid # 5.2 COMBINING DEVANAGARI DIGIT ZERO..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
+A8F8..A8FA ; valid ; ; NV8 # 5.2 DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
+A8FB ; valid # 5.2 DEVANAGARI HEADSTROKE
+A8FC ; valid ; ; NV8 # 8.0 DEVANAGARI SIGN SIDDHAM
+A8FD ; valid # 8.0 DEVANAGARI JAIN OM
+A8FE..A8FF ; valid # 11.0 DEVANAGARI LETTER AY..DEVANAGARI VOWEL SIGN AY
+A900..A92D ; valid # 5.1 KAYAH LI DIGIT ZERO..KAYAH LI TONE CALYA PLOPHU
+A92E..A92F ; valid ; ; NV8 # 5.1 KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
+A930..A953 ; valid # 5.1 REJANG LETTER KA..REJANG VIRAMA
+A954..A95E ; disallowed # NA <reserved-A954>..<reserved-A95E>
+A95F ; valid ; ; NV8 # 5.1 REJANG SECTION MARK
+A960..A97C ; valid ; ; NV8 # 5.2 HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
+A97D..A97F ; disallowed # NA <reserved-A97D>..<reserved-A97F>
+A980..A9C0 ; valid # 5.2 JAVANESE SIGN PANYANGGA..JAVANESE PANGKON
+A9C1..A9CD ; valid ; ; NV8 # 5.2 JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
+A9CE ; disallowed # NA <reserved-A9CE>
+A9CF..A9D9 ; valid # 5.2 JAVANESE PANGRANGKEP..JAVANESE DIGIT NINE
+A9DA..A9DD ; disallowed # NA <reserved-A9DA>..<reserved-A9DD>
+A9DE..A9DF ; valid ; ; NV8 # 5.2 JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
+A9E0..A9FE ; valid # 7.0 MYANMAR LETTER SHAN GHA..MYANMAR LETTER TAI LAING BHA
+A9FF ; disallowed # NA <reserved-A9FF>
+AA00..AA36 ; valid # 5.1 CHAM LETTER A..CHAM CONSONANT SIGN WA
+AA37..AA3F ; disallowed # NA <reserved-AA37>..<reserved-AA3F>
+AA40..AA4D ; valid # 5.1 CHAM LETTER FINAL K..CHAM CONSONANT SIGN FINAL H
+AA4E..AA4F ; disallowed # NA <reserved-AA4E>..<reserved-AA4F>
+AA50..AA59 ; valid # 5.1 CHAM DIGIT ZERO..CHAM DIGIT NINE
+AA5A..AA5B ; disallowed # NA <reserved-AA5A>..<reserved-AA5B>
+AA5C..AA5F ; valid ; ; NV8 # 5.1 CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
+AA60..AA76 ; valid # 5.2 MYANMAR LETTER KHAMTI GA..MYANMAR LOGOGRAM KHAMTI HM
+AA77..AA79 ; valid ; ; NV8 # 5.2 MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
+AA7A..AA7B ; valid # 5.2 MYANMAR LETTER AITON RA..MYANMAR SIGN PAO KAREN TONE
+AA7C..AA7F ; valid # 7.0 MYANMAR SIGN TAI LAING TONE-2..MYANMAR LETTER SHWE PALAUNG SHA
+AA80..AAC2 ; valid # 5.2 TAI VIET LETTER LOW KO..TAI VIET TONE MAI SONG
+AAC3..AADA ; disallowed # NA <reserved-AAC3>..<reserved-AADA>
+AADB..AADD ; valid # 5.2 TAI VIET SYMBOL KON..TAI VIET SYMBOL SAM
+AADE..AADF ; valid ; ; NV8 # 5.2 TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
+AAE0..AAEF ; valid # 6.1 MEETEI MAYEK LETTER E..MEETEI MAYEK VOWEL SIGN AAU
+AAF0..AAF1 ; valid ; ; NV8 # 6.1 MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
+AAF2..AAF6 ; valid # 6.1 MEETEI MAYEK ANJI..MEETEI MAYEK VIRAMA
+AAF7..AB00 ; disallowed # NA <reserved-AAF7>..<reserved-AB00>
+AB01..AB06 ; valid # 6.0 ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
+AB07..AB08 ; disallowed # NA <reserved-AB07>..<reserved-AB08>
+AB09..AB0E ; valid # 6.0 ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
+AB0F..AB10 ; disallowed # NA <reserved-AB0F>..<reserved-AB10>
+AB11..AB16 ; valid # 6.0 ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
+AB17..AB1F ; disallowed # NA <reserved-AB17>..<reserved-AB1F>
+AB20..AB26 ; valid # 6.0 ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
+AB27 ; disallowed # NA <reserved-AB27>
+AB28..AB2E ; valid # 6.0 ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
+AB2F ; disallowed # NA <reserved-AB2F>
+AB30..AB5A ; valid # 7.0 LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
+AB5B ; valid ; ; NV8 # 7.0 MODIFIER BREVE WITH INVERTED BREVE
+AB5C ; mapped ; A727 # 7.0 MODIFIER LETTER SMALL HENG
+AB5D ; mapped ; AB37 # 7.0 MODIFIER LETTER SMALL L WITH INVERTED LAZY S
+AB5E ; mapped ; 026B # 7.0 MODIFIER LETTER SMALL L WITH MIDDLE TILDE
+AB5F ; mapped ; AB52 # 7.0 MODIFIER LETTER SMALL U WITH LEFT HOOK
+AB60..AB63 ; valid # 8.0 LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER UO
+AB64..AB65 ; valid # 7.0 LATIN SMALL LETTER INVERTED ALPHA..GREEK LETTER SMALL CAPITAL OMEGA
+AB66..AB67 ; valid # 12.0 LATIN SMALL LETTER DZ DIGRAPH WITH RETROFLEX HOOK..LATIN SMALL LETTER TS DIGRAPH WITH RETROFLEX HOOK
+AB68 ; valid # 13.0 LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE
+AB69 ; mapped ; 028D # 13.0 MODIFIER LETTER SMALL TURNED W
+AB6A..AB6B ; valid ; ; NV8 # 13.0 MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK
+AB6C..AB6F ; disallowed # NA <reserved-AB6C>..<reserved-AB6F>
+AB70 ; mapped ; 13A0 # 8.0 CHEROKEE SMALL LETTER A
+AB71 ; mapped ; 13A1 # 8.0 CHEROKEE SMALL LETTER E
+AB72 ; mapped ; 13A2 # 8.0 CHEROKEE SMALL LETTER I
+AB73 ; mapped ; 13A3 # 8.0 CHEROKEE SMALL LETTER O
+AB74 ; mapped ; 13A4 # 8.0 CHEROKEE SMALL LETTER U
+AB75 ; mapped ; 13A5 # 8.0 CHEROKEE SMALL LETTER V
+AB76 ; mapped ; 13A6 # 8.0 CHEROKEE SMALL LETTER GA
+AB77 ; mapped ; 13A7 # 8.0 CHEROKEE SMALL LETTER KA
+AB78 ; mapped ; 13A8 # 8.0 CHEROKEE SMALL LETTER GE
+AB79 ; mapped ; 13A9 # 8.0 CHEROKEE SMALL LETTER GI
+AB7A ; mapped ; 13AA # 8.0 CHEROKEE SMALL LETTER GO
+AB7B ; mapped ; 13AB # 8.0 CHEROKEE SMALL LETTER GU
+AB7C ; mapped ; 13AC # 8.0 CHEROKEE SMALL LETTER GV
+AB7D ; mapped ; 13AD # 8.0 CHEROKEE SMALL LETTER HA
+AB7E ; mapped ; 13AE # 8.0 CHEROKEE SMALL LETTER HE
+AB7F ; mapped ; 13AF # 8.0 CHEROKEE SMALL LETTER HI
+AB80 ; mapped ; 13B0 # 8.0 CHEROKEE SMALL LETTER HO
+AB81 ; mapped ; 13B1 # 8.0 CHEROKEE SMALL LETTER HU
+AB82 ; mapped ; 13B2 # 8.0 CHEROKEE SMALL LETTER HV
+AB83 ; mapped ; 13B3 # 8.0 CHEROKEE SMALL LETTER LA
+AB84 ; mapped ; 13B4 # 8.0 CHEROKEE SMALL LETTER LE
+AB85 ; mapped ; 13B5 # 8.0 CHEROKEE SMALL LETTER LI
+AB86 ; mapped ; 13B6 # 8.0 CHEROKEE SMALL LETTER LO
+AB87 ; mapped ; 13B7 # 8.0 CHEROKEE SMALL LETTER LU
+AB88 ; mapped ; 13B8 # 8.0 CHEROKEE SMALL LETTER LV
+AB89 ; mapped ; 13B9 # 8.0 CHEROKEE SMALL LETTER MA
+AB8A ; mapped ; 13BA # 8.0 CHEROKEE SMALL LETTER ME
+AB8B ; mapped ; 13BB # 8.0 CHEROKEE SMALL LETTER MI
+AB8C ; mapped ; 13BC # 8.0 CHEROKEE SMALL LETTER MO
+AB8D ; mapped ; 13BD # 8.0 CHEROKEE SMALL LETTER MU
+AB8E ; mapped ; 13BE # 8.0 CHEROKEE SMALL LETTER NA
+AB8F ; mapped ; 13BF # 8.0 CHEROKEE SMALL LETTER HNA
+AB90 ; mapped ; 13C0 # 8.0 CHEROKEE SMALL LETTER NAH
+AB91 ; mapped ; 13C1 # 8.0 CHEROKEE SMALL LETTER NE
+AB92 ; mapped ; 13C2 # 8.0 CHEROKEE SMALL LETTER NI
+AB93 ; mapped ; 13C3 # 8.0 CHEROKEE SMALL LETTER NO
+AB94 ; mapped ; 13C4 # 8.0 CHEROKEE SMALL LETTER NU
+AB95 ; mapped ; 13C5 # 8.0 CHEROKEE SMALL LETTER NV
+AB96 ; mapped ; 13C6 # 8.0 CHEROKEE SMALL LETTER QUA
+AB97 ; mapped ; 13C7 # 8.0 CHEROKEE SMALL LETTER QUE
+AB98 ; mapped ; 13C8 # 8.0 CHEROKEE SMALL LETTER QUI
+AB99 ; mapped ; 13C9 # 8.0 CHEROKEE SMALL LETTER QUO
+AB9A ; mapped ; 13CA # 8.0 CHEROKEE SMALL LETTER QUU
+AB9B ; mapped ; 13CB # 8.0 CHEROKEE SMALL LETTER QUV
+AB9C ; mapped ; 13CC # 8.0 CHEROKEE SMALL LETTER SA
+AB9D ; mapped ; 13CD # 8.0 CHEROKEE SMALL LETTER S
+AB9E ; mapped ; 13CE # 8.0 CHEROKEE SMALL LETTER SE
+AB9F ; mapped ; 13CF # 8.0 CHEROKEE SMALL LETTER SI
+ABA0 ; mapped ; 13D0 # 8.0 CHEROKEE SMALL LETTER SO
+ABA1 ; mapped ; 13D1 # 8.0 CHEROKEE SMALL LETTER SU
+ABA2 ; mapped ; 13D2 # 8.0 CHEROKEE SMALL LETTER SV
+ABA3 ; mapped ; 13D3 # 8.0 CHEROKEE SMALL LETTER DA
+ABA4 ; mapped ; 13D4 # 8.0 CHEROKEE SMALL LETTER TA
+ABA5 ; mapped ; 13D5 # 8.0 CHEROKEE SMALL LETTER DE
+ABA6 ; mapped ; 13D6 # 8.0 CHEROKEE SMALL LETTER TE
+ABA7 ; mapped ; 13D7 # 8.0 CHEROKEE SMALL LETTER DI
+ABA8 ; mapped ; 13D8 # 8.0 CHEROKEE SMALL LETTER TI
+ABA9 ; mapped ; 13D9 # 8.0 CHEROKEE SMALL LETTER DO
+ABAA ; mapped ; 13DA # 8.0 CHEROKEE SMALL LETTER DU
+ABAB ; mapped ; 13DB # 8.0 CHEROKEE SMALL LETTER DV
+ABAC ; mapped ; 13DC # 8.0 CHEROKEE SMALL LETTER DLA
+ABAD ; mapped ; 13DD # 8.0 CHEROKEE SMALL LETTER TLA
+ABAE ; mapped ; 13DE # 8.0 CHEROKEE SMALL LETTER TLE
+ABAF ; mapped ; 13DF # 8.0 CHEROKEE SMALL LETTER TLI
+ABB0 ; mapped ; 13E0 # 8.0 CHEROKEE SMALL LETTER TLO
+ABB1 ; mapped ; 13E1 # 8.0 CHEROKEE SMALL LETTER TLU
+ABB2 ; mapped ; 13E2 # 8.0 CHEROKEE SMALL LETTER TLV
+ABB3 ; mapped ; 13E3 # 8.0 CHEROKEE SMALL LETTER TSA
+ABB4 ; mapped ; 13E4 # 8.0 CHEROKEE SMALL LETTER TSE
+ABB5 ; mapped ; 13E5 # 8.0 CHEROKEE SMALL LETTER TSI
+ABB6 ; mapped ; 13E6 # 8.0 CHEROKEE SMALL LETTER TSO
+ABB7 ; mapped ; 13E7 # 8.0 CHEROKEE SMALL LETTER TSU
+ABB8 ; mapped ; 13E8 # 8.0 CHEROKEE SMALL LETTER TSV
+ABB9 ; mapped ; 13E9 # 8.0 CHEROKEE SMALL LETTER WA
+ABBA ; mapped ; 13EA # 8.0 CHEROKEE SMALL LETTER WE
+ABBB ; mapped ; 13EB # 8.0 CHEROKEE SMALL LETTER WI
+ABBC ; mapped ; 13EC # 8.0 CHEROKEE SMALL LETTER WO
+ABBD ; mapped ; 13ED # 8.0 CHEROKEE SMALL LETTER WU
+ABBE ; mapped ; 13EE # 8.0 CHEROKEE SMALL LETTER WV
+ABBF ; mapped ; 13EF # 8.0 CHEROKEE SMALL LETTER YA
+ABC0..ABEA ; valid # 5.2 MEETEI MAYEK LETTER KOK..MEETEI MAYEK VOWEL SIGN NUNG
+ABEB ; valid ; ; NV8 # 5.2 MEETEI MAYEK CHEIKHEI
+ABEC..ABED ; valid # 5.2 MEETEI MAYEK LUM IYEK..MEETEI MAYEK APUN IYEK
+ABEE..ABEF ; disallowed # NA <reserved-ABEE>..<reserved-ABEF>
+ABF0..ABF9 ; valid # 5.2 MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
+ABFA..ABFF ; disallowed # NA <reserved-ABFA>..<reserved-ABFF>
+AC00..D7A3 ; valid # 2.0 HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH
+D7A4..D7AF ; disallowed # NA <reserved-D7A4>..<reserved-D7AF>
+D7B0..D7C6 ; valid ; ; NV8 # 5.2 HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
+D7C7..D7CA ; disallowed # NA <reserved-D7C7>..<reserved-D7CA>
+D7CB..D7FB ; valid ; ; NV8 # 5.2 HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
+D7FC..D7FF ; disallowed # NA <reserved-D7FC>..<reserved-D7FF>
+D800..DFFF ; disallowed # 2.0 <surrogate-D800>..<surrogate-DFFF>
+E000..F8FF ; disallowed # 1.1 <private-use-E000>..<private-use-F8FF>
+F900 ; mapped ; 8C48 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F900
+F901 ; mapped ; 66F4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F901
+F902 ; mapped ; 8ECA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F902
+F903 ; mapped ; 8CC8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F903
+F904 ; mapped ; 6ED1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F904
+F905 ; mapped ; 4E32 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F905
+F906 ; mapped ; 53E5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F906
+F907..F908 ; mapped ; 9F9C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F907..CJK COMPATIBILITY IDEOGRAPH-F908
+F909 ; mapped ; 5951 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F909
+F90A ; mapped ; 91D1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90A
+F90B ; mapped ; 5587 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90B
+F90C ; mapped ; 5948 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90C
+F90D ; mapped ; 61F6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90D
+F90E ; mapped ; 7669 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90E
+F90F ; mapped ; 7F85 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F90F
+F910 ; mapped ; 863F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F910
+F911 ; mapped ; 87BA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F911
+F912 ; mapped ; 88F8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F912
+F913 ; mapped ; 908F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F913
+F914 ; mapped ; 6A02 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F914
+F915 ; mapped ; 6D1B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F915
+F916 ; mapped ; 70D9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F916
+F917 ; mapped ; 73DE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F917
+F918 ; mapped ; 843D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F918
+F919 ; mapped ; 916A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F919
+F91A ; mapped ; 99F1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91A
+F91B ; mapped ; 4E82 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91B
+F91C ; mapped ; 5375 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91C
+F91D ; mapped ; 6B04 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91D
+F91E ; mapped ; 721B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91E
+F91F ; mapped ; 862D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F91F
+F920 ; mapped ; 9E1E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F920
+F921 ; mapped ; 5D50 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F921
+F922 ; mapped ; 6FEB # 1.1 CJK COMPATIBILITY IDEOGRAPH-F922
+F923 ; mapped ; 85CD # 1.1 CJK COMPATIBILITY IDEOGRAPH-F923
+F924 ; mapped ; 8964 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F924
+F925 ; mapped ; 62C9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F925
+F926 ; mapped ; 81D8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F926
+F927 ; mapped ; 881F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F927
+F928 ; mapped ; 5ECA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F928
+F929 ; mapped ; 6717 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F929
+F92A ; mapped ; 6D6A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92A
+F92B ; mapped ; 72FC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92B
+F92C ; mapped ; 90CE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92C
+F92D ; mapped ; 4F86 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92D
+F92E ; mapped ; 51B7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92E
+F92F ; mapped ; 52DE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F92F
+F930 ; mapped ; 64C4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F930
+F931 ; mapped ; 6AD3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F931
+F932 ; mapped ; 7210 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F932
+F933 ; mapped ; 76E7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F933
+F934 ; mapped ; 8001 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F934
+F935 ; mapped ; 8606 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F935
+F936 ; mapped ; 865C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F936
+F937 ; mapped ; 8DEF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F937
+F938 ; mapped ; 9732 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F938
+F939 ; mapped ; 9B6F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F939
+F93A ; mapped ; 9DFA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93A
+F93B ; mapped ; 788C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93B
+F93C ; mapped ; 797F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93C
+F93D ; mapped ; 7DA0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93D
+F93E ; mapped ; 83C9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93E
+F93F ; mapped ; 9304 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F93F
+F940 ; mapped ; 9E7F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F940
+F941 ; mapped ; 8AD6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F941
+F942 ; mapped ; 58DF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F942
+F943 ; mapped ; 5F04 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F943
+F944 ; mapped ; 7C60 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F944
+F945 ; mapped ; 807E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F945
+F946 ; mapped ; 7262 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F946
+F947 ; mapped ; 78CA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F947
+F948 ; mapped ; 8CC2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F948
+F949 ; mapped ; 96F7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F949
+F94A ; mapped ; 58D8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94A
+F94B ; mapped ; 5C62 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94B
+F94C ; mapped ; 6A13 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94C
+F94D ; mapped ; 6DDA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94D
+F94E ; mapped ; 6F0F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94E
+F94F ; mapped ; 7D2F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F94F
+F950 ; mapped ; 7E37 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F950
+F951 ; mapped ; 964B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F951
+F952 ; mapped ; 52D2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F952
+F953 ; mapped ; 808B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F953
+F954 ; mapped ; 51DC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F954
+F955 ; mapped ; 51CC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F955
+F956 ; mapped ; 7A1C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F956
+F957 ; mapped ; 7DBE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F957
+F958 ; mapped ; 83F1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F958
+F959 ; mapped ; 9675 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F959
+F95A ; mapped ; 8B80 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95A
+F95B ; mapped ; 62CF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95B
+F95C ; mapped ; 6A02 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95C
+F95D ; mapped ; 8AFE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95D
+F95E ; mapped ; 4E39 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95E
+F95F ; mapped ; 5BE7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F95F
+F960 ; mapped ; 6012 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F960
+F961 ; mapped ; 7387 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F961
+F962 ; mapped ; 7570 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F962
+F963 ; mapped ; 5317 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F963
+F964 ; mapped ; 78FB # 1.1 CJK COMPATIBILITY IDEOGRAPH-F964
+F965 ; mapped ; 4FBF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F965
+F966 ; mapped ; 5FA9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F966
+F967 ; mapped ; 4E0D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F967
+F968 ; mapped ; 6CCC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F968
+F969 ; mapped ; 6578 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F969
+F96A ; mapped ; 7D22 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96A
+F96B ; mapped ; 53C3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96B
+F96C ; mapped ; 585E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96C
+F96D ; mapped ; 7701 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96D
+F96E ; mapped ; 8449 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96E
+F96F ; mapped ; 8AAA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F96F
+F970 ; mapped ; 6BBA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F970
+F971 ; mapped ; 8FB0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F971
+F972 ; mapped ; 6C88 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F972
+F973 ; mapped ; 62FE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F973
+F974 ; mapped ; 82E5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F974
+F975 ; mapped ; 63A0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F975
+F976 ; mapped ; 7565 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F976
+F977 ; mapped ; 4EAE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F977
+F978 ; mapped ; 5169 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F978
+F979 ; mapped ; 51C9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F979
+F97A ; mapped ; 6881 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97A
+F97B ; mapped ; 7CE7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97B
+F97C ; mapped ; 826F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97C
+F97D ; mapped ; 8AD2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97D
+F97E ; mapped ; 91CF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97E
+F97F ; mapped ; 52F5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F97F
+F980 ; mapped ; 5442 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F980
+F981 ; mapped ; 5973 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F981
+F982 ; mapped ; 5EEC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F982
+F983 ; mapped ; 65C5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F983
+F984 ; mapped ; 6FFE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F984
+F985 ; mapped ; 792A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F985
+F986 ; mapped ; 95AD # 1.1 CJK COMPATIBILITY IDEOGRAPH-F986
+F987 ; mapped ; 9A6A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F987
+F988 ; mapped ; 9E97 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F988
+F989 ; mapped ; 9ECE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F989
+F98A ; mapped ; 529B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98A
+F98B ; mapped ; 66C6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98B
+F98C ; mapped ; 6B77 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98C
+F98D ; mapped ; 8F62 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98D
+F98E ; mapped ; 5E74 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98E
+F98F ; mapped ; 6190 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F98F
+F990 ; mapped ; 6200 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F990
+F991 ; mapped ; 649A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F991
+F992 ; mapped ; 6F23 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F992
+F993 ; mapped ; 7149 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F993
+F994 ; mapped ; 7489 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F994
+F995 ; mapped ; 79CA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F995
+F996 ; mapped ; 7DF4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F996
+F997 ; mapped ; 806F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F997
+F998 ; mapped ; 8F26 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F998
+F999 ; mapped ; 84EE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F999
+F99A ; mapped ; 9023 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99A
+F99B ; mapped ; 934A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99B
+F99C ; mapped ; 5217 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99C
+F99D ; mapped ; 52A3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99D
+F99E ; mapped ; 54BD # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99E
+F99F ; mapped ; 70C8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F99F
+F9A0 ; mapped ; 88C2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A0
+F9A1 ; mapped ; 8AAA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A1
+F9A2 ; mapped ; 5EC9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A2
+F9A3 ; mapped ; 5FF5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A3
+F9A4 ; mapped ; 637B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A4
+F9A5 ; mapped ; 6BAE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A5
+F9A6 ; mapped ; 7C3E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A6
+F9A7 ; mapped ; 7375 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A7
+F9A8 ; mapped ; 4EE4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A8
+F9A9 ; mapped ; 56F9 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9A9
+F9AA ; mapped ; 5BE7 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AA
+F9AB ; mapped ; 5DBA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AB
+F9AC ; mapped ; 601C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AC
+F9AD ; mapped ; 73B2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AD
+F9AE ; mapped ; 7469 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AE
+F9AF ; mapped ; 7F9A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9AF
+F9B0 ; mapped ; 8046 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B0
+F9B1 ; mapped ; 9234 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B1
+F9B2 ; mapped ; 96F6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B2
+F9B3 ; mapped ; 9748 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B3
+F9B4 ; mapped ; 9818 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B4
+F9B5 ; mapped ; 4F8B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B5
+F9B6 ; mapped ; 79AE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B6
+F9B7 ; mapped ; 91B4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B7
+F9B8 ; mapped ; 96B8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B8
+F9B9 ; mapped ; 60E1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9B9
+F9BA ; mapped ; 4E86 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BA
+F9BB ; mapped ; 50DA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BB
+F9BC ; mapped ; 5BEE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BC
+F9BD ; mapped ; 5C3F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BD
+F9BE ; mapped ; 6599 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BE
+F9BF ; mapped ; 6A02 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9BF
+F9C0 ; mapped ; 71CE # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C0
+F9C1 ; mapped ; 7642 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C1
+F9C2 ; mapped ; 84FC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C2
+F9C3 ; mapped ; 907C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C3
+F9C4 ; mapped ; 9F8D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C4
+F9C5 ; mapped ; 6688 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C5
+F9C6 ; mapped ; 962E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C6
+F9C7 ; mapped ; 5289 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C7
+F9C8 ; mapped ; 677B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C8
+F9C9 ; mapped ; 67F3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9C9
+F9CA ; mapped ; 6D41 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CA
+F9CB ; mapped ; 6E9C # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CB
+F9CC ; mapped ; 7409 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CC
+F9CD ; mapped ; 7559 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CD
+F9CE ; mapped ; 786B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CE
+F9CF ; mapped ; 7D10 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9CF
+F9D0 ; mapped ; 985E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D0
+F9D1 ; mapped ; 516D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D1
+F9D2 ; mapped ; 622E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D2
+F9D3 ; mapped ; 9678 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D3
+F9D4 ; mapped ; 502B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D4
+F9D5 ; mapped ; 5D19 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D5
+F9D6 ; mapped ; 6DEA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D6
+F9D7 ; mapped ; 8F2A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D7
+F9D8 ; mapped ; 5F8B # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D8
+F9D9 ; mapped ; 6144 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9D9
+F9DA ; mapped ; 6817 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DA
+F9DB ; mapped ; 7387 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DB
+F9DC ; mapped ; 9686 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DC
+F9DD ; mapped ; 5229 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DD
+F9DE ; mapped ; 540F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DE
+F9DF ; mapped ; 5C65 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9DF
+F9E0 ; mapped ; 6613 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E0
+F9E1 ; mapped ; 674E # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E1
+F9E2 ; mapped ; 68A8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E2
+F9E3 ; mapped ; 6CE5 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E3
+F9E4 ; mapped ; 7406 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E4
+F9E5 ; mapped ; 75E2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E5
+F9E6 ; mapped ; 7F79 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E6
+F9E7 ; mapped ; 88CF # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E7
+F9E8 ; mapped ; 88E1 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E8
+F9E9 ; mapped ; 91CC # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9E9
+F9EA ; mapped ; 96E2 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9EA
+F9EB ; mapped ; 533F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9EB
+F9EC ; mapped ; 6EBA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9EC
+F9ED ; mapped ; 541D # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9ED
+F9EE ; mapped ; 71D0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9EE
+F9EF ; mapped ; 7498 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9EF
+F9F0 ; mapped ; 85FA # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F0
+F9F1 ; mapped ; 96A3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F1
+F9F2 ; mapped ; 9C57 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F2
+F9F3 ; mapped ; 9E9F # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F3
+F9F4 ; mapped ; 6797 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F4
+F9F5 ; mapped ; 6DCB # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F5
+F9F6 ; mapped ; 81E8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F6
+F9F7 ; mapped ; 7ACB # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F7
+F9F8 ; mapped ; 7B20 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F8
+F9F9 ; mapped ; 7C92 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9F9
+F9FA ; mapped ; 72C0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FA
+F9FB ; mapped ; 7099 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FB
+F9FC ; mapped ; 8B58 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FC
+F9FD ; mapped ; 4EC0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FD
+F9FE ; mapped ; 8336 # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FE
+F9FF ; mapped ; 523A # 1.1 CJK COMPATIBILITY IDEOGRAPH-F9FF
+FA00 ; mapped ; 5207 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA00
+FA01 ; mapped ; 5EA6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA01
+FA02 ; mapped ; 62D3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA02
+FA03 ; mapped ; 7CD6 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA03
+FA04 ; mapped ; 5B85 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA04
+FA05 ; mapped ; 6D1E # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA05
+FA06 ; mapped ; 66B4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA06
+FA07 ; mapped ; 8F3B # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA07
+FA08 ; mapped ; 884C # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA08
+FA09 ; mapped ; 964D # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA09
+FA0A ; mapped ; 898B # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA0A
+FA0B ; mapped ; 5ED3 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA0B
+FA0C ; mapped ; 5140 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA0C
+FA0D ; mapped ; 55C0 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA0D
+FA0E..FA0F ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
+FA10 ; mapped ; 585A # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA10
+FA11 ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA11
+FA12 ; mapped ; 6674 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA12
+FA13..FA14 ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
+FA15 ; mapped ; 51DE # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA15
+FA16 ; mapped ; 732A # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA16
+FA17 ; mapped ; 76CA # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA17
+FA18 ; mapped ; 793C # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA18
+FA19 ; mapped ; 795E # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA19
+FA1A ; mapped ; 7965 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1A
+FA1B ; mapped ; 798F # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1B
+FA1C ; mapped ; 9756 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1C
+FA1D ; mapped ; 7CBE # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1D
+FA1E ; mapped ; 7FBD # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1E
+FA1F ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA1F
+FA20 ; mapped ; 8612 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA20
+FA21 ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA21
+FA22 ; mapped ; 8AF8 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA22
+FA23..FA24 ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24
+FA25 ; mapped ; 9038 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA25
+FA26 ; mapped ; 90FD # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA26
+FA27..FA29 ; valid # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29
+FA2A ; mapped ; 98EF # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA2A
+FA2B ; mapped ; 98FC # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA2B
+FA2C ; mapped ; 9928 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA2C
+FA2D ; mapped ; 9DB4 # 1.1 CJK COMPATIBILITY IDEOGRAPH-FA2D
+FA2E ; mapped ; 90DE # 6.1 CJK COMPATIBILITY IDEOGRAPH-FA2E
+FA2F ; mapped ; 96B7 # 6.1 CJK COMPATIBILITY IDEOGRAPH-FA2F
+FA30 ; mapped ; 4FAE # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA30
+FA31 ; mapped ; 50E7 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA31
+FA32 ; mapped ; 514D # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA32
+FA33 ; mapped ; 52C9 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA33
+FA34 ; mapped ; 52E4 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA34
+FA35 ; mapped ; 5351 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA35
+FA36 ; mapped ; 559D # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA36
+FA37 ; mapped ; 5606 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA37
+FA38 ; mapped ; 5668 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA38
+FA39 ; mapped ; 5840 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA39
+FA3A ; mapped ; 58A8 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3A
+FA3B ; mapped ; 5C64 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3B
+FA3C ; mapped ; 5C6E # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3C
+FA3D ; mapped ; 6094 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3D
+FA3E ; mapped ; 6168 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3E
+FA3F ; mapped ; 618E # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA3F
+FA40 ; mapped ; 61F2 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA40
+FA41 ; mapped ; 654F # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA41
+FA42 ; mapped ; 65E2 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA42
+FA43 ; mapped ; 6691 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA43
+FA44 ; mapped ; 6885 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA44
+FA45 ; mapped ; 6D77 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA45
+FA46 ; mapped ; 6E1A # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA46
+FA47 ; mapped ; 6F22 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA47
+FA48 ; mapped ; 716E # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA48
+FA49 ; mapped ; 722B # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA49
+FA4A ; mapped ; 7422 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4A
+FA4B ; mapped ; 7891 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4B
+FA4C ; mapped ; 793E # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4C
+FA4D ; mapped ; 7949 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4D
+FA4E ; mapped ; 7948 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4E
+FA4F ; mapped ; 7950 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA4F
+FA50 ; mapped ; 7956 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA50
+FA51 ; mapped ; 795D # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA51
+FA52 ; mapped ; 798D # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA52
+FA53 ; mapped ; 798E # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA53
+FA54 ; mapped ; 7A40 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA54
+FA55 ; mapped ; 7A81 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA55
+FA56 ; mapped ; 7BC0 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA56
+FA57 ; mapped ; 7DF4 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA57
+FA58 ; mapped ; 7E09 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA58
+FA59 ; mapped ; 7E41 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA59
+FA5A ; mapped ; 7F72 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA5A
+FA5B ; mapped ; 8005 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA5B
+FA5C ; mapped ; 81ED # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA5C
+FA5D..FA5E ; mapped ; 8279 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA5D..CJK COMPATIBILITY IDEOGRAPH-FA5E
+FA5F ; mapped ; 8457 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA5F
+FA60 ; mapped ; 8910 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA60
+FA61 ; mapped ; 8996 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA61
+FA62 ; mapped ; 8B01 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA62
+FA63 ; mapped ; 8B39 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA63
+FA64 ; mapped ; 8CD3 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA64
+FA65 ; mapped ; 8D08 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA65
+FA66 ; mapped ; 8FB6 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA66
+FA67 ; mapped ; 9038 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA67
+FA68 ; mapped ; 96E3 # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA68
+FA69 ; mapped ; 97FF # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA69
+FA6A ; mapped ; 983B # 3.2 CJK COMPATIBILITY IDEOGRAPH-FA6A
+FA6B ; mapped ; 6075 # 5.2 CJK COMPATIBILITY IDEOGRAPH-FA6B
+FA6C ; mapped ; 242EE # 5.2 CJK COMPATIBILITY IDEOGRAPH-FA6C
+FA6D ; mapped ; 8218 # 5.2 CJK COMPATIBILITY IDEOGRAPH-FA6D
+FA6E..FA6F ; disallowed # NA <reserved-FA6E>..<reserved-FA6F>
+FA70 ; mapped ; 4E26 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA70
+FA71 ; mapped ; 51B5 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA71
+FA72 ; mapped ; 5168 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA72
+FA73 ; mapped ; 4F80 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA73
+FA74 ; mapped ; 5145 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA74
+FA75 ; mapped ; 5180 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA75
+FA76 ; mapped ; 52C7 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA76
+FA77 ; mapped ; 52FA # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA77
+FA78 ; mapped ; 559D # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA78
+FA79 ; mapped ; 5555 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA79
+FA7A ; mapped ; 5599 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7A
+FA7B ; mapped ; 55E2 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7B
+FA7C ; mapped ; 585A # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7C
+FA7D ; mapped ; 58B3 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7D
+FA7E ; mapped ; 5944 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7E
+FA7F ; mapped ; 5954 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA7F
+FA80 ; mapped ; 5A62 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA80
+FA81 ; mapped ; 5B28 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA81
+FA82 ; mapped ; 5ED2 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA82
+FA83 ; mapped ; 5ED9 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA83
+FA84 ; mapped ; 5F69 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA84
+FA85 ; mapped ; 5FAD # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA85
+FA86 ; mapped ; 60D8 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA86
+FA87 ; mapped ; 614E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA87
+FA88 ; mapped ; 6108 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA88
+FA89 ; mapped ; 618E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA89
+FA8A ; mapped ; 6160 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8A
+FA8B ; mapped ; 61F2 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8B
+FA8C ; mapped ; 6234 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8C
+FA8D ; mapped ; 63C4 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8D
+FA8E ; mapped ; 641C # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8E
+FA8F ; mapped ; 6452 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA8F
+FA90 ; mapped ; 6556 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA90
+FA91 ; mapped ; 6674 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA91
+FA92 ; mapped ; 6717 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA92
+FA93 ; mapped ; 671B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA93
+FA94 ; mapped ; 6756 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA94
+FA95 ; mapped ; 6B79 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA95
+FA96 ; mapped ; 6BBA # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA96
+FA97 ; mapped ; 6D41 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA97
+FA98 ; mapped ; 6EDB # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA98
+FA99 ; mapped ; 6ECB # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA99
+FA9A ; mapped ; 6F22 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9A
+FA9B ; mapped ; 701E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9B
+FA9C ; mapped ; 716E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9C
+FA9D ; mapped ; 77A7 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9D
+FA9E ; mapped ; 7235 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9E
+FA9F ; mapped ; 72AF # 4.1 CJK COMPATIBILITY IDEOGRAPH-FA9F
+FAA0 ; mapped ; 732A # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA0
+FAA1 ; mapped ; 7471 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA1
+FAA2 ; mapped ; 7506 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA2
+FAA3 ; mapped ; 753B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA3
+FAA4 ; mapped ; 761D # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA4
+FAA5 ; mapped ; 761F # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA5
+FAA6 ; mapped ; 76CA # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA6
+FAA7 ; mapped ; 76DB # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA7
+FAA8 ; mapped ; 76F4 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA8
+FAA9 ; mapped ; 774A # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAA9
+FAAA ; mapped ; 7740 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAA
+FAAB ; mapped ; 78CC # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAB
+FAAC ; mapped ; 7AB1 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAC
+FAAD ; mapped ; 7BC0 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAD
+FAAE ; mapped ; 7C7B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAE
+FAAF ; mapped ; 7D5B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAAF
+FAB0 ; mapped ; 7DF4 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB0
+FAB1 ; mapped ; 7F3E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB1
+FAB2 ; mapped ; 8005 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB2
+FAB3 ; mapped ; 8352 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB3
+FAB4 ; mapped ; 83EF # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB4
+FAB5 ; mapped ; 8779 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB5
+FAB6 ; mapped ; 8941 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB6
+FAB7 ; mapped ; 8986 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB7
+FAB8 ; mapped ; 8996 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB8
+FAB9 ; mapped ; 8ABF # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAB9
+FABA ; mapped ; 8AF8 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABA
+FABB ; mapped ; 8ACB # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABB
+FABC ; mapped ; 8B01 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABC
+FABD ; mapped ; 8AFE # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABD
+FABE ; mapped ; 8AED # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABE
+FABF ; mapped ; 8B39 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FABF
+FAC0 ; mapped ; 8B8A # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC0
+FAC1 ; mapped ; 8D08 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC1
+FAC2 ; mapped ; 8F38 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC2
+FAC3 ; mapped ; 9072 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC3
+FAC4 ; mapped ; 9199 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC4
+FAC5 ; mapped ; 9276 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC5
+FAC6 ; mapped ; 967C # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC6
+FAC7 ; mapped ; 96E3 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC7
+FAC8 ; mapped ; 9756 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC8
+FAC9 ; mapped ; 97DB # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAC9
+FACA ; mapped ; 97FF # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACA
+FACB ; mapped ; 980B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACB
+FACC ; mapped ; 983B # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACC
+FACD ; mapped ; 9B12 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACD
+FACE ; mapped ; 9F9C # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACE
+FACF ; mapped ; 2284A # 4.1 CJK COMPATIBILITY IDEOGRAPH-FACF
+FAD0 ; mapped ; 22844 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD0
+FAD1 ; mapped ; 233D5 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD1
+FAD2 ; mapped ; 3B9D # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD2
+FAD3 ; mapped ; 4018 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD3
+FAD4 ; mapped ; 4039 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD4
+FAD5 ; mapped ; 25249 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD5
+FAD6 ; mapped ; 25CD0 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD6
+FAD7 ; mapped ; 27ED3 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD7
+FAD8 ; mapped ; 9F43 # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD8
+FAD9 ; mapped ; 9F8E # 4.1 CJK COMPATIBILITY IDEOGRAPH-FAD9
+FADA..FAFF ; disallowed # NA <reserved-FADA>..<reserved-FAFF>
+FB00 ; mapped ; 0066 0066 # 1.1 LATIN SMALL LIGATURE FF
+FB01 ; mapped ; 0066 0069 # 1.1 LATIN SMALL LIGATURE FI
+FB02 ; mapped ; 0066 006C # 1.1 LATIN SMALL LIGATURE FL
+FB03 ; mapped ; 0066 0066 0069 #1.1 LATIN SMALL LIGATURE FFI
+FB04 ; mapped ; 0066 0066 006C #1.1 LATIN SMALL LIGATURE FFL
+FB05..FB06 ; mapped ; 0073 0074 # 1.1 LATIN SMALL LIGATURE LONG S T..LATIN SMALL LIGATURE ST
+FB07..FB12 ; disallowed # NA <reserved-FB07>..<reserved-FB12>
+FB13 ; mapped ; 0574 0576 # 1.1 ARMENIAN SMALL LIGATURE MEN NOW
+FB14 ; mapped ; 0574 0565 # 1.1 ARMENIAN SMALL LIGATURE MEN ECH
+FB15 ; mapped ; 0574 056B # 1.1 ARMENIAN SMALL LIGATURE MEN INI
+FB16 ; mapped ; 057E 0576 # 1.1 ARMENIAN SMALL LIGATURE VEW NOW
+FB17 ; mapped ; 0574 056D # 1.1 ARMENIAN SMALL LIGATURE MEN XEH
+FB18..FB1C ; disallowed # NA <reserved-FB18>..<reserved-FB1C>
+FB1D ; mapped ; 05D9 05B4 # 3.0 HEBREW LETTER YOD WITH HIRIQ
+FB1E ; valid # 1.1 HEBREW POINT JUDEO-SPANISH VARIKA
+FB1F ; mapped ; 05F2 05B7 # 1.1 HEBREW LIGATURE YIDDISH YOD YOD PATAH
+FB20 ; mapped ; 05E2 # 1.1 HEBREW LETTER ALTERNATIVE AYIN
+FB21 ; mapped ; 05D0 # 1.1 HEBREW LETTER WIDE ALEF
+FB22 ; mapped ; 05D3 # 1.1 HEBREW LETTER WIDE DALET
+FB23 ; mapped ; 05D4 # 1.1 HEBREW LETTER WIDE HE
+FB24 ; mapped ; 05DB # 1.1 HEBREW LETTER WIDE KAF
+FB25 ; mapped ; 05DC # 1.1 HEBREW LETTER WIDE LAMED
+FB26 ; mapped ; 05DD # 1.1 HEBREW LETTER WIDE FINAL MEM
+FB27 ; mapped ; 05E8 # 1.1 HEBREW LETTER WIDE RESH
+FB28 ; mapped ; 05EA # 1.1 HEBREW LETTER WIDE TAV
+FB29 ; disallowed_STD3_mapped ; 002B # 1.1 HEBREW LETTER ALTERNATIVE PLUS SIGN
+FB2A ; mapped ; 05E9 05C1 # 1.1 HEBREW LETTER SHIN WITH SHIN DOT
+FB2B ; mapped ; 05E9 05C2 # 1.1 HEBREW LETTER SHIN WITH SIN DOT
+FB2C ; mapped ; 05E9 05BC 05C1 #1.1 HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT
+FB2D ; mapped ; 05E9 05BC 05C2 #1.1 HEBREW LETTER SHIN WITH DAGESH AND SIN DOT
+FB2E ; mapped ; 05D0 05B7 # 1.1 HEBREW LETTER ALEF WITH PATAH
+FB2F ; mapped ; 05D0 05B8 # 1.1 HEBREW LETTER ALEF WITH QAMATS
+FB30 ; mapped ; 05D0 05BC # 1.1 HEBREW LETTER ALEF WITH MAPIQ
+FB31 ; mapped ; 05D1 05BC # 1.1 HEBREW LETTER BET WITH DAGESH
+FB32 ; mapped ; 05D2 05BC # 1.1 HEBREW LETTER GIMEL WITH DAGESH
+FB33 ; mapped ; 05D3 05BC # 1.1 HEBREW LETTER DALET WITH DAGESH
+FB34 ; mapped ; 05D4 05BC # 1.1 HEBREW LETTER HE WITH MAPIQ
+FB35 ; mapped ; 05D5 05BC # 1.1 HEBREW LETTER VAV WITH DAGESH
+FB36 ; mapped ; 05D6 05BC # 1.1 HEBREW LETTER ZAYIN WITH DAGESH
+FB37 ; disallowed # NA <reserved-FB37>
+FB38 ; mapped ; 05D8 05BC # 1.1 HEBREW LETTER TET WITH DAGESH
+FB39 ; mapped ; 05D9 05BC # 1.1 HEBREW LETTER YOD WITH DAGESH
+FB3A ; mapped ; 05DA 05BC # 1.1 HEBREW LETTER FINAL KAF WITH DAGESH
+FB3B ; mapped ; 05DB 05BC # 1.1 HEBREW LETTER KAF WITH DAGESH
+FB3C ; mapped ; 05DC 05BC # 1.1 HEBREW LETTER LAMED WITH DAGESH
+FB3D ; disallowed # NA <reserved-FB3D>
+FB3E ; mapped ; 05DE 05BC # 1.1 HEBREW LETTER MEM WITH DAGESH
+FB3F ; disallowed # NA <reserved-FB3F>
+FB40 ; mapped ; 05E0 05BC # 1.1 HEBREW LETTER NUN WITH DAGESH
+FB41 ; mapped ; 05E1 05BC # 1.1 HEBREW LETTER SAMEKH WITH DAGESH
+FB42 ; disallowed # NA <reserved-FB42>
+FB43 ; mapped ; 05E3 05BC # 1.1 HEBREW LETTER FINAL PE WITH DAGESH
+FB44 ; mapped ; 05E4 05BC # 1.1 HEBREW LETTER PE WITH DAGESH
+FB45 ; disallowed # NA <reserved-FB45>
+FB46 ; mapped ; 05E6 05BC # 1.1 HEBREW LETTER TSADI WITH DAGESH
+FB47 ; mapped ; 05E7 05BC # 1.1 HEBREW LETTER QOF WITH DAGESH
+FB48 ; mapped ; 05E8 05BC # 1.1 HEBREW LETTER RESH WITH DAGESH
+FB49 ; mapped ; 05E9 05BC # 1.1 HEBREW LETTER SHIN WITH DAGESH
+FB4A ; mapped ; 05EA 05BC # 1.1 HEBREW LETTER TAV WITH DAGESH
+FB4B ; mapped ; 05D5 05B9 # 1.1 HEBREW LETTER VAV WITH HOLAM
+FB4C ; mapped ; 05D1 05BF # 1.1 HEBREW LETTER BET WITH RAFE
+FB4D ; mapped ; 05DB 05BF # 1.1 HEBREW LETTER KAF WITH RAFE
+FB4E ; mapped ; 05E4 05BF # 1.1 HEBREW LETTER PE WITH RAFE
+FB4F ; mapped ; 05D0 05DC # 1.1 HEBREW LIGATURE ALEF LAMED
+FB50..FB51 ; mapped ; 0671 # 1.1 ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER ALEF WASLA FINAL FORM
+FB52..FB55 ; mapped ; 067B # 1.1 ARABIC LETTER BEEH ISOLATED FORM..ARABIC LETTER BEEH MEDIAL FORM
+FB56..FB59 ; mapped ; 067E # 1.1 ARABIC LETTER PEH ISOLATED FORM..ARABIC LETTER PEH MEDIAL FORM
+FB5A..FB5D ; mapped ; 0680 # 1.1 ARABIC LETTER BEHEH ISOLATED FORM..ARABIC LETTER BEHEH MEDIAL FORM
+FB5E..FB61 ; mapped ; 067A # 1.1 ARABIC LETTER TTEHEH ISOLATED FORM..ARABIC LETTER TTEHEH MEDIAL FORM
+FB62..FB65 ; mapped ; 067F # 1.1 ARABIC LETTER TEHEH ISOLATED FORM..ARABIC LETTER TEHEH MEDIAL FORM
+FB66..FB69 ; mapped ; 0679 # 1.1 ARABIC LETTER TTEH ISOLATED FORM..ARABIC LETTER TTEH MEDIAL FORM
+FB6A..FB6D ; mapped ; 06A4 # 1.1 ARABIC LETTER VEH ISOLATED FORM..ARABIC LETTER VEH MEDIAL FORM
+FB6E..FB71 ; mapped ; 06A6 # 1.1 ARABIC LETTER PEHEH ISOLATED FORM..ARABIC LETTER PEHEH MEDIAL FORM
+FB72..FB75 ; mapped ; 0684 # 1.1 ARABIC LETTER DYEH ISOLATED FORM..ARABIC LETTER DYEH MEDIAL FORM
+FB76..FB79 ; mapped ; 0683 # 1.1 ARABIC LETTER NYEH ISOLATED FORM..ARABIC LETTER NYEH MEDIAL FORM
+FB7A..FB7D ; mapped ; 0686 # 1.1 ARABIC LETTER TCHEH ISOLATED FORM..ARABIC LETTER TCHEH MEDIAL FORM
+FB7E..FB81 ; mapped ; 0687 # 1.1 ARABIC LETTER TCHEHEH ISOLATED FORM..ARABIC LETTER TCHEHEH MEDIAL FORM
+FB82..FB83 ; mapped ; 068D # 1.1 ARABIC LETTER DDAHAL ISOLATED FORM..ARABIC LETTER DDAHAL FINAL FORM
+FB84..FB85 ; mapped ; 068C # 1.1 ARABIC LETTER DAHAL ISOLATED FORM..ARABIC LETTER DAHAL FINAL FORM
+FB86..FB87 ; mapped ; 068E # 1.1 ARABIC LETTER DUL ISOLATED FORM..ARABIC LETTER DUL FINAL FORM
+FB88..FB89 ; mapped ; 0688 # 1.1 ARABIC LETTER DDAL ISOLATED FORM..ARABIC LETTER DDAL FINAL FORM
+FB8A..FB8B ; mapped ; 0698 # 1.1 ARABIC LETTER JEH ISOLATED FORM..ARABIC LETTER JEH FINAL FORM
+FB8C..FB8D ; mapped ; 0691 # 1.1 ARABIC LETTER RREH ISOLATED FORM..ARABIC LETTER RREH FINAL FORM
+FB8E..FB91 ; mapped ; 06A9 # 1.1 ARABIC LETTER KEHEH ISOLATED FORM..ARABIC LETTER KEHEH MEDIAL FORM
+FB92..FB95 ; mapped ; 06AF # 1.1 ARABIC LETTER GAF ISOLATED FORM..ARABIC LETTER GAF MEDIAL FORM
+FB96..FB99 ; mapped ; 06B3 # 1.1 ARABIC LETTER GUEH ISOLATED FORM..ARABIC LETTER GUEH MEDIAL FORM
+FB9A..FB9D ; mapped ; 06B1 # 1.1 ARABIC LETTER NGOEH ISOLATED FORM..ARABIC LETTER NGOEH MEDIAL FORM
+FB9E..FB9F ; mapped ; 06BA # 1.1 ARABIC LETTER NOON GHUNNA ISOLATED FORM..ARABIC LETTER NOON GHUNNA FINAL FORM
+FBA0..FBA3 ; mapped ; 06BB # 1.1 ARABIC LETTER RNOON ISOLATED FORM..ARABIC LETTER RNOON MEDIAL FORM
+FBA4..FBA5 ; mapped ; 06C0 # 1.1 ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM..ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM
+FBA6..FBA9 ; mapped ; 06C1 # 1.1 ARABIC LETTER HEH GOAL ISOLATED FORM..ARABIC LETTER HEH GOAL MEDIAL FORM
+FBAA..FBAD ; mapped ; 06BE # 1.1 ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM..ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM
+FBAE..FBAF ; mapped ; 06D2 # 1.1 ARABIC LETTER YEH BARREE ISOLATED FORM..ARABIC LETTER YEH BARREE FINAL FORM
+FBB0..FBB1 ; mapped ; 06D3 # 1.1 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
+FBB2..FBC1 ; valid ; ; NV8 # 6.0 ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW
+FBC2 ; valid ; ; NV8 # 14.0 ARABIC SYMBOL WASLA ABOVE
+FBC3..FBD2 ; disallowed # NA <reserved-FBC3>..<reserved-FBD2>
+FBD3..FBD6 ; mapped ; 06AD # 1.1 ARABIC LETTER NG ISOLATED FORM..ARABIC LETTER NG MEDIAL FORM
+FBD7..FBD8 ; mapped ; 06C7 # 1.1 ARABIC LETTER U ISOLATED FORM..ARABIC LETTER U FINAL FORM
+FBD9..FBDA ; mapped ; 06C6 # 1.1 ARABIC LETTER OE ISOLATED FORM..ARABIC LETTER OE FINAL FORM
+FBDB..FBDC ; mapped ; 06C8 # 1.1 ARABIC LETTER YU ISOLATED FORM..ARABIC LETTER YU FINAL FORM
+FBDD ; mapped ; 06C7 0674 # 1.1 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM
+FBDE..FBDF ; mapped ; 06CB # 1.1 ARABIC LETTER VE ISOLATED FORM..ARABIC LETTER VE FINAL FORM
+FBE0..FBE1 ; mapped ; 06C5 # 1.1 ARABIC LETTER KIRGHIZ OE ISOLATED FORM..ARABIC LETTER KIRGHIZ OE FINAL FORM
+FBE2..FBE3 ; mapped ; 06C9 # 1.1 ARABIC LETTER KIRGHIZ YU ISOLATED FORM..ARABIC LETTER KIRGHIZ YU FINAL FORM
+FBE4..FBE7 ; mapped ; 06D0 # 1.1 ARABIC LETTER E ISOLATED FORM..ARABIC LETTER E MEDIAL FORM
+FBE8..FBE9 ; mapped ; 0649 # 1.1 ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM..ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM
+FBEA..FBEB ; mapped ; 0626 0627 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM
+FBEC..FBED ; mapped ; 0626 06D5 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM
+FBEE..FBEF ; mapped ; 0626 0648 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM
+FBF0..FBF1 ; mapped ; 0626 06C7 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM
+FBF2..FBF3 ; mapped ; 0626 06C6 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM
+FBF4..FBF5 ; mapped ; 0626 06C8 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM
+FBF6..FBF8 ; mapped ; 0626 06D0 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM..ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM
+FBF9..FBFB ; mapped ; 0626 0649 # 1.1 ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM..ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM
+FBFC..FBFF ; mapped ; 06CC # 1.1 ARABIC LETTER FARSI YEH ISOLATED FORM..ARABIC LETTER FARSI YEH MEDIAL FORM
+FC00 ; mapped ; 0626 062C # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM
+FC01 ; mapped ; 0626 062D # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM
+FC02 ; mapped ; 0626 0645 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM
+FC03 ; mapped ; 0626 0649 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM
+FC04 ; mapped ; 0626 064A # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM
+FC05 ; mapped ; 0628 062C # 1.1 ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM
+FC06 ; mapped ; 0628 062D # 1.1 ARABIC LIGATURE BEH WITH HAH ISOLATED FORM
+FC07 ; mapped ; 0628 062E # 1.1 ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM
+FC08 ; mapped ; 0628 0645 # 1.1 ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM
+FC09 ; mapped ; 0628 0649 # 1.1 ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM
+FC0A ; mapped ; 0628 064A # 1.1 ARABIC LIGATURE BEH WITH YEH ISOLATED FORM
+FC0B ; mapped ; 062A 062C # 1.1 ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM
+FC0C ; mapped ; 062A 062D # 1.1 ARABIC LIGATURE TEH WITH HAH ISOLATED FORM
+FC0D ; mapped ; 062A 062E # 1.1 ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM
+FC0E ; mapped ; 062A 0645 # 1.1 ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM
+FC0F ; mapped ; 062A 0649 # 1.1 ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM
+FC10 ; mapped ; 062A 064A # 1.1 ARABIC LIGATURE TEH WITH YEH ISOLATED FORM
+FC11 ; mapped ; 062B 062C # 1.1 ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM
+FC12 ; mapped ; 062B 0645 # 1.1 ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM
+FC13 ; mapped ; 062B 0649 # 1.1 ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM
+FC14 ; mapped ; 062B 064A # 1.1 ARABIC LIGATURE THEH WITH YEH ISOLATED FORM
+FC15 ; mapped ; 062C 062D # 1.1 ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM
+FC16 ; mapped ; 062C 0645 # 1.1 ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM
+FC17 ; mapped ; 062D 062C # 1.1 ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM
+FC18 ; mapped ; 062D 0645 # 1.1 ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM
+FC19 ; mapped ; 062E 062C # 1.1 ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM
+FC1A ; mapped ; 062E 062D # 1.1 ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM
+FC1B ; mapped ; 062E 0645 # 1.1 ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM
+FC1C ; mapped ; 0633 062C # 1.1 ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM
+FC1D ; mapped ; 0633 062D # 1.1 ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM
+FC1E ; mapped ; 0633 062E # 1.1 ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM
+FC1F ; mapped ; 0633 0645 # 1.1 ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM
+FC20 ; mapped ; 0635 062D # 1.1 ARABIC LIGATURE SAD WITH HAH ISOLATED FORM
+FC21 ; mapped ; 0635 0645 # 1.1 ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM
+FC22 ; mapped ; 0636 062C # 1.1 ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM
+FC23 ; mapped ; 0636 062D # 1.1 ARABIC LIGATURE DAD WITH HAH ISOLATED FORM
+FC24 ; mapped ; 0636 062E # 1.1 ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM
+FC25 ; mapped ; 0636 0645 # 1.1 ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM
+FC26 ; mapped ; 0637 062D # 1.1 ARABIC LIGATURE TAH WITH HAH ISOLATED FORM
+FC27 ; mapped ; 0637 0645 # 1.1 ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM
+FC28 ; mapped ; 0638 0645 # 1.1 ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM
+FC29 ; mapped ; 0639 062C # 1.1 ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM
+FC2A ; mapped ; 0639 0645 # 1.1 ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM
+FC2B ; mapped ; 063A 062C # 1.1 ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM
+FC2C ; mapped ; 063A 0645 # 1.1 ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM
+FC2D ; mapped ; 0641 062C # 1.1 ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM
+FC2E ; mapped ; 0641 062D # 1.1 ARABIC LIGATURE FEH WITH HAH ISOLATED FORM
+FC2F ; mapped ; 0641 062E # 1.1 ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM
+FC30 ; mapped ; 0641 0645 # 1.1 ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM
+FC31 ; mapped ; 0641 0649 # 1.1 ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM
+FC32 ; mapped ; 0641 064A # 1.1 ARABIC LIGATURE FEH WITH YEH ISOLATED FORM
+FC33 ; mapped ; 0642 062D # 1.1 ARABIC LIGATURE QAF WITH HAH ISOLATED FORM
+FC34 ; mapped ; 0642 0645 # 1.1 ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM
+FC35 ; mapped ; 0642 0649 # 1.1 ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM
+FC36 ; mapped ; 0642 064A # 1.1 ARABIC LIGATURE QAF WITH YEH ISOLATED FORM
+FC37 ; mapped ; 0643 0627 # 1.1 ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM
+FC38 ; mapped ; 0643 062C # 1.1 ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM
+FC39 ; mapped ; 0643 062D # 1.1 ARABIC LIGATURE KAF WITH HAH ISOLATED FORM
+FC3A ; mapped ; 0643 062E # 1.1 ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM
+FC3B ; mapped ; 0643 0644 # 1.1 ARABIC LIGATURE KAF WITH LAM ISOLATED FORM
+FC3C ; mapped ; 0643 0645 # 1.1 ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM
+FC3D ; mapped ; 0643 0649 # 1.1 ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM
+FC3E ; mapped ; 0643 064A # 1.1 ARABIC LIGATURE KAF WITH YEH ISOLATED FORM
+FC3F ; mapped ; 0644 062C # 1.1 ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM
+FC40 ; mapped ; 0644 062D # 1.1 ARABIC LIGATURE LAM WITH HAH ISOLATED FORM
+FC41 ; mapped ; 0644 062E # 1.1 ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM
+FC42 ; mapped ; 0644 0645 # 1.1 ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM
+FC43 ; mapped ; 0644 0649 # 1.1 ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM
+FC44 ; mapped ; 0644 064A # 1.1 ARABIC LIGATURE LAM WITH YEH ISOLATED FORM
+FC45 ; mapped ; 0645 062C # 1.1 ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM
+FC46 ; mapped ; 0645 062D # 1.1 ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM
+FC47 ; mapped ; 0645 062E # 1.1 ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM
+FC48 ; mapped ; 0645 0645 # 1.1 ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM
+FC49 ; mapped ; 0645 0649 # 1.1 ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM
+FC4A ; mapped ; 0645 064A # 1.1 ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM
+FC4B ; mapped ; 0646 062C # 1.1 ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM
+FC4C ; mapped ; 0646 062D # 1.1 ARABIC LIGATURE NOON WITH HAH ISOLATED FORM
+FC4D ; mapped ; 0646 062E # 1.1 ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM
+FC4E ; mapped ; 0646 0645 # 1.1 ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM
+FC4F ; mapped ; 0646 0649 # 1.1 ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM
+FC50 ; mapped ; 0646 064A # 1.1 ARABIC LIGATURE NOON WITH YEH ISOLATED FORM
+FC51 ; mapped ; 0647 062C # 1.1 ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM
+FC52 ; mapped ; 0647 0645 # 1.1 ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM
+FC53 ; mapped ; 0647 0649 # 1.1 ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM
+FC54 ; mapped ; 0647 064A # 1.1 ARABIC LIGATURE HEH WITH YEH ISOLATED FORM
+FC55 ; mapped ; 064A 062C # 1.1 ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM
+FC56 ; mapped ; 064A 062D # 1.1 ARABIC LIGATURE YEH WITH HAH ISOLATED FORM
+FC57 ; mapped ; 064A 062E # 1.1 ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM
+FC58 ; mapped ; 064A 0645 # 1.1 ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM
+FC59 ; mapped ; 064A 0649 # 1.1 ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM
+FC5A ; mapped ; 064A 064A # 1.1 ARABIC LIGATURE YEH WITH YEH ISOLATED FORM
+FC5B ; mapped ; 0630 0670 # 1.1 ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5C ; mapped ; 0631 0670 # 1.1 ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5D ; mapped ; 0649 0670 # 1.1 ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC5E ; disallowed_STD3_mapped ; 0020 064C 0651 #1.1 ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM
+FC5F ; disallowed_STD3_mapped ; 0020 064D 0651 #1.1 ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM
+FC60 ; disallowed_STD3_mapped ; 0020 064E 0651 #1.1 ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM
+FC61 ; disallowed_STD3_mapped ; 0020 064F 0651 #1.1 ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM
+FC62 ; disallowed_STD3_mapped ; 0020 0650 0651 #1.1 ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM
+FC63 ; disallowed_STD3_mapped ; 0020 0651 0670 #1.1 ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM
+FC64 ; mapped ; 0626 0631 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM
+FC65 ; mapped ; 0626 0632 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM
+FC66 ; mapped ; 0626 0645 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM
+FC67 ; mapped ; 0626 0646 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM
+FC68 ; mapped ; 0626 0649 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM
+FC69 ; mapped ; 0626 064A # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM
+FC6A ; mapped ; 0628 0631 # 1.1 ARABIC LIGATURE BEH WITH REH FINAL FORM
+FC6B ; mapped ; 0628 0632 # 1.1 ARABIC LIGATURE BEH WITH ZAIN FINAL FORM
+FC6C ; mapped ; 0628 0645 # 1.1 ARABIC LIGATURE BEH WITH MEEM FINAL FORM
+FC6D ; mapped ; 0628 0646 # 1.1 ARABIC LIGATURE BEH WITH NOON FINAL FORM
+FC6E ; mapped ; 0628 0649 # 1.1 ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM
+FC6F ; mapped ; 0628 064A # 1.1 ARABIC LIGATURE BEH WITH YEH FINAL FORM
+FC70 ; mapped ; 062A 0631 # 1.1 ARABIC LIGATURE TEH WITH REH FINAL FORM
+FC71 ; mapped ; 062A 0632 # 1.1 ARABIC LIGATURE TEH WITH ZAIN FINAL FORM
+FC72 ; mapped ; 062A 0645 # 1.1 ARABIC LIGATURE TEH WITH MEEM FINAL FORM
+FC73 ; mapped ; 062A 0646 # 1.1 ARABIC LIGATURE TEH WITH NOON FINAL FORM
+FC74 ; mapped ; 062A 0649 # 1.1 ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM
+FC75 ; mapped ; 062A 064A # 1.1 ARABIC LIGATURE TEH WITH YEH FINAL FORM
+FC76 ; mapped ; 062B 0631 # 1.1 ARABIC LIGATURE THEH WITH REH FINAL FORM
+FC77 ; mapped ; 062B 0632 # 1.1 ARABIC LIGATURE THEH WITH ZAIN FINAL FORM
+FC78 ; mapped ; 062B 0645 # 1.1 ARABIC LIGATURE THEH WITH MEEM FINAL FORM
+FC79 ; mapped ; 062B 0646 # 1.1 ARABIC LIGATURE THEH WITH NOON FINAL FORM
+FC7A ; mapped ; 062B 0649 # 1.1 ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM
+FC7B ; mapped ; 062B 064A # 1.1 ARABIC LIGATURE THEH WITH YEH FINAL FORM
+FC7C ; mapped ; 0641 0649 # 1.1 ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM
+FC7D ; mapped ; 0641 064A # 1.1 ARABIC LIGATURE FEH WITH YEH FINAL FORM
+FC7E ; mapped ; 0642 0649 # 1.1 ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM
+FC7F ; mapped ; 0642 064A # 1.1 ARABIC LIGATURE QAF WITH YEH FINAL FORM
+FC80 ; mapped ; 0643 0627 # 1.1 ARABIC LIGATURE KAF WITH ALEF FINAL FORM
+FC81 ; mapped ; 0643 0644 # 1.1 ARABIC LIGATURE KAF WITH LAM FINAL FORM
+FC82 ; mapped ; 0643 0645 # 1.1 ARABIC LIGATURE KAF WITH MEEM FINAL FORM
+FC83 ; mapped ; 0643 0649 # 1.1 ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM
+FC84 ; mapped ; 0643 064A # 1.1 ARABIC LIGATURE KAF WITH YEH FINAL FORM
+FC85 ; mapped ; 0644 0645 # 1.1 ARABIC LIGATURE LAM WITH MEEM FINAL FORM
+FC86 ; mapped ; 0644 0649 # 1.1 ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM
+FC87 ; mapped ; 0644 064A # 1.1 ARABIC LIGATURE LAM WITH YEH FINAL FORM
+FC88 ; mapped ; 0645 0627 # 1.1 ARABIC LIGATURE MEEM WITH ALEF FINAL FORM
+FC89 ; mapped ; 0645 0645 # 1.1 ARABIC LIGATURE MEEM WITH MEEM FINAL FORM
+FC8A ; mapped ; 0646 0631 # 1.1 ARABIC LIGATURE NOON WITH REH FINAL FORM
+FC8B ; mapped ; 0646 0632 # 1.1 ARABIC LIGATURE NOON WITH ZAIN FINAL FORM
+FC8C ; mapped ; 0646 0645 # 1.1 ARABIC LIGATURE NOON WITH MEEM FINAL FORM
+FC8D ; mapped ; 0646 0646 # 1.1 ARABIC LIGATURE NOON WITH NOON FINAL FORM
+FC8E ; mapped ; 0646 0649 # 1.1 ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM
+FC8F ; mapped ; 0646 064A # 1.1 ARABIC LIGATURE NOON WITH YEH FINAL FORM
+FC90 ; mapped ; 0649 0670 # 1.1 ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM
+FC91 ; mapped ; 064A 0631 # 1.1 ARABIC LIGATURE YEH WITH REH FINAL FORM
+FC92 ; mapped ; 064A 0632 # 1.1 ARABIC LIGATURE YEH WITH ZAIN FINAL FORM
+FC93 ; mapped ; 064A 0645 # 1.1 ARABIC LIGATURE YEH WITH MEEM FINAL FORM
+FC94 ; mapped ; 064A 0646 # 1.1 ARABIC LIGATURE YEH WITH NOON FINAL FORM
+FC95 ; mapped ; 064A 0649 # 1.1 ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM
+FC96 ; mapped ; 064A 064A # 1.1 ARABIC LIGATURE YEH WITH YEH FINAL FORM
+FC97 ; mapped ; 0626 062C # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM
+FC98 ; mapped ; 0626 062D # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM
+FC99 ; mapped ; 0626 062E # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM
+FC9A ; mapped ; 0626 0645 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM
+FC9B ; mapped ; 0626 0647 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM
+FC9C ; mapped ; 0628 062C # 1.1 ARABIC LIGATURE BEH WITH JEEM INITIAL FORM
+FC9D ; mapped ; 0628 062D # 1.1 ARABIC LIGATURE BEH WITH HAH INITIAL FORM
+FC9E ; mapped ; 0628 062E # 1.1 ARABIC LIGATURE BEH WITH KHAH INITIAL FORM
+FC9F ; mapped ; 0628 0645 # 1.1 ARABIC LIGATURE BEH WITH MEEM INITIAL FORM
+FCA0 ; mapped ; 0628 0647 # 1.1 ARABIC LIGATURE BEH WITH HEH INITIAL FORM
+FCA1 ; mapped ; 062A 062C # 1.1 ARABIC LIGATURE TEH WITH JEEM INITIAL FORM
+FCA2 ; mapped ; 062A 062D # 1.1 ARABIC LIGATURE TEH WITH HAH INITIAL FORM
+FCA3 ; mapped ; 062A 062E # 1.1 ARABIC LIGATURE TEH WITH KHAH INITIAL FORM
+FCA4 ; mapped ; 062A 0645 # 1.1 ARABIC LIGATURE TEH WITH MEEM INITIAL FORM
+FCA5 ; mapped ; 062A 0647 # 1.1 ARABIC LIGATURE TEH WITH HEH INITIAL FORM
+FCA6 ; mapped ; 062B 0645 # 1.1 ARABIC LIGATURE THEH WITH MEEM INITIAL FORM
+FCA7 ; mapped ; 062C 062D # 1.1 ARABIC LIGATURE JEEM WITH HAH INITIAL FORM
+FCA8 ; mapped ; 062C 0645 # 1.1 ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM
+FCA9 ; mapped ; 062D 062C # 1.1 ARABIC LIGATURE HAH WITH JEEM INITIAL FORM
+FCAA ; mapped ; 062D 0645 # 1.1 ARABIC LIGATURE HAH WITH MEEM INITIAL FORM
+FCAB ; mapped ; 062E 062C # 1.1 ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM
+FCAC ; mapped ; 062E 0645 # 1.1 ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM
+FCAD ; mapped ; 0633 062C # 1.1 ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM
+FCAE ; mapped ; 0633 062D # 1.1 ARABIC LIGATURE SEEN WITH HAH INITIAL FORM
+FCAF ; mapped ; 0633 062E # 1.1 ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM
+FCB0 ; mapped ; 0633 0645 # 1.1 ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM
+FCB1 ; mapped ; 0635 062D # 1.1 ARABIC LIGATURE SAD WITH HAH INITIAL FORM
+FCB2 ; mapped ; 0635 062E # 1.1 ARABIC LIGATURE SAD WITH KHAH INITIAL FORM
+FCB3 ; mapped ; 0635 0645 # 1.1 ARABIC LIGATURE SAD WITH MEEM INITIAL FORM
+FCB4 ; mapped ; 0636 062C # 1.1 ARABIC LIGATURE DAD WITH JEEM INITIAL FORM
+FCB5 ; mapped ; 0636 062D # 1.1 ARABIC LIGATURE DAD WITH HAH INITIAL FORM
+FCB6 ; mapped ; 0636 062E # 1.1 ARABIC LIGATURE DAD WITH KHAH INITIAL FORM
+FCB7 ; mapped ; 0636 0645 # 1.1 ARABIC LIGATURE DAD WITH MEEM INITIAL FORM
+FCB8 ; mapped ; 0637 062D # 1.1 ARABIC LIGATURE TAH WITH HAH INITIAL FORM
+FCB9 ; mapped ; 0638 0645 # 1.1 ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM
+FCBA ; mapped ; 0639 062C # 1.1 ARABIC LIGATURE AIN WITH JEEM INITIAL FORM
+FCBB ; mapped ; 0639 0645 # 1.1 ARABIC LIGATURE AIN WITH MEEM INITIAL FORM
+FCBC ; mapped ; 063A 062C # 1.1 ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM
+FCBD ; mapped ; 063A 0645 # 1.1 ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM
+FCBE ; mapped ; 0641 062C # 1.1 ARABIC LIGATURE FEH WITH JEEM INITIAL FORM
+FCBF ; mapped ; 0641 062D # 1.1 ARABIC LIGATURE FEH WITH HAH INITIAL FORM
+FCC0 ; mapped ; 0641 062E # 1.1 ARABIC LIGATURE FEH WITH KHAH INITIAL FORM
+FCC1 ; mapped ; 0641 0645 # 1.1 ARABIC LIGATURE FEH WITH MEEM INITIAL FORM
+FCC2 ; mapped ; 0642 062D # 1.1 ARABIC LIGATURE QAF WITH HAH INITIAL FORM
+FCC3 ; mapped ; 0642 0645 # 1.1 ARABIC LIGATURE QAF WITH MEEM INITIAL FORM
+FCC4 ; mapped ; 0643 062C # 1.1 ARABIC LIGATURE KAF WITH JEEM INITIAL FORM
+FCC5 ; mapped ; 0643 062D # 1.1 ARABIC LIGATURE KAF WITH HAH INITIAL FORM
+FCC6 ; mapped ; 0643 062E # 1.1 ARABIC LIGATURE KAF WITH KHAH INITIAL FORM
+FCC7 ; mapped ; 0643 0644 # 1.1 ARABIC LIGATURE KAF WITH LAM INITIAL FORM
+FCC8 ; mapped ; 0643 0645 # 1.1 ARABIC LIGATURE KAF WITH MEEM INITIAL FORM
+FCC9 ; mapped ; 0644 062C # 1.1 ARABIC LIGATURE LAM WITH JEEM INITIAL FORM
+FCCA ; mapped ; 0644 062D # 1.1 ARABIC LIGATURE LAM WITH HAH INITIAL FORM
+FCCB ; mapped ; 0644 062E # 1.1 ARABIC LIGATURE LAM WITH KHAH INITIAL FORM
+FCCC ; mapped ; 0644 0645 # 1.1 ARABIC LIGATURE LAM WITH MEEM INITIAL FORM
+FCCD ; mapped ; 0644 0647 # 1.1 ARABIC LIGATURE LAM WITH HEH INITIAL FORM
+FCCE ; mapped ; 0645 062C # 1.1 ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM
+FCCF ; mapped ; 0645 062D # 1.1 ARABIC LIGATURE MEEM WITH HAH INITIAL FORM
+FCD0 ; mapped ; 0645 062E # 1.1 ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM
+FCD1 ; mapped ; 0645 0645 # 1.1 ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM
+FCD2 ; mapped ; 0646 062C # 1.1 ARABIC LIGATURE NOON WITH JEEM INITIAL FORM
+FCD3 ; mapped ; 0646 062D # 1.1 ARABIC LIGATURE NOON WITH HAH INITIAL FORM
+FCD4 ; mapped ; 0646 062E # 1.1 ARABIC LIGATURE NOON WITH KHAH INITIAL FORM
+FCD5 ; mapped ; 0646 0645 # 1.1 ARABIC LIGATURE NOON WITH MEEM INITIAL FORM
+FCD6 ; mapped ; 0646 0647 # 1.1 ARABIC LIGATURE NOON WITH HEH INITIAL FORM
+FCD7 ; mapped ; 0647 062C # 1.1 ARABIC LIGATURE HEH WITH JEEM INITIAL FORM
+FCD8 ; mapped ; 0647 0645 # 1.1 ARABIC LIGATURE HEH WITH MEEM INITIAL FORM
+FCD9 ; mapped ; 0647 0670 # 1.1 ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM
+FCDA ; mapped ; 064A 062C # 1.1 ARABIC LIGATURE YEH WITH JEEM INITIAL FORM
+FCDB ; mapped ; 064A 062D # 1.1 ARABIC LIGATURE YEH WITH HAH INITIAL FORM
+FCDC ; mapped ; 064A 062E # 1.1 ARABIC LIGATURE YEH WITH KHAH INITIAL FORM
+FCDD ; mapped ; 064A 0645 # 1.1 ARABIC LIGATURE YEH WITH MEEM INITIAL FORM
+FCDE ; mapped ; 064A 0647 # 1.1 ARABIC LIGATURE YEH WITH HEH INITIAL FORM
+FCDF ; mapped ; 0626 0645 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM
+FCE0 ; mapped ; 0626 0647 # 1.1 ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM
+FCE1 ; mapped ; 0628 0645 # 1.1 ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM
+FCE2 ; mapped ; 0628 0647 # 1.1 ARABIC LIGATURE BEH WITH HEH MEDIAL FORM
+FCE3 ; mapped ; 062A 0645 # 1.1 ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM
+FCE4 ; mapped ; 062A 0647 # 1.1 ARABIC LIGATURE TEH WITH HEH MEDIAL FORM
+FCE5 ; mapped ; 062B 0645 # 1.1 ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM
+FCE6 ; mapped ; 062B 0647 # 1.1 ARABIC LIGATURE THEH WITH HEH MEDIAL FORM
+FCE7 ; mapped ; 0633 0645 # 1.1 ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM
+FCE8 ; mapped ; 0633 0647 # 1.1 ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM
+FCE9 ; mapped ; 0634 0645 # 1.1 ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM
+FCEA ; mapped ; 0634 0647 # 1.1 ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM
+FCEB ; mapped ; 0643 0644 # 1.1 ARABIC LIGATURE KAF WITH LAM MEDIAL FORM
+FCEC ; mapped ; 0643 0645 # 1.1 ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM
+FCED ; mapped ; 0644 0645 # 1.1 ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM
+FCEE ; mapped ; 0646 0645 # 1.1 ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM
+FCEF ; mapped ; 0646 0647 # 1.1 ARABIC LIGATURE NOON WITH HEH MEDIAL FORM
+FCF0 ; mapped ; 064A 0645 # 1.1 ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM
+FCF1 ; mapped ; 064A 0647 # 1.1 ARABIC LIGATURE YEH WITH HEH MEDIAL FORM
+FCF2 ; mapped ; 0640 064E 0651 #1.1 ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM
+FCF3 ; mapped ; 0640 064F 0651 #1.1 ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM
+FCF4 ; mapped ; 0640 0650 0651 #1.1 ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM
+FCF5 ; mapped ; 0637 0649 # 1.1 ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM
+FCF6 ; mapped ; 0637 064A # 1.1 ARABIC LIGATURE TAH WITH YEH ISOLATED FORM
+FCF7 ; mapped ; 0639 0649 # 1.1 ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM
+FCF8 ; mapped ; 0639 064A # 1.1 ARABIC LIGATURE AIN WITH YEH ISOLATED FORM
+FCF9 ; mapped ; 063A 0649 # 1.1 ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM
+FCFA ; mapped ; 063A 064A # 1.1 ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM
+FCFB ; mapped ; 0633 0649 # 1.1 ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM
+FCFC ; mapped ; 0633 064A # 1.1 ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM
+FCFD ; mapped ; 0634 0649 # 1.1 ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM
+FCFE ; mapped ; 0634 064A # 1.1 ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM
+FCFF ; mapped ; 062D 0649 # 1.1 ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM
+FD00 ; mapped ; 062D 064A # 1.1 ARABIC LIGATURE HAH WITH YEH ISOLATED FORM
+FD01 ; mapped ; 062C 0649 # 1.1 ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM
+FD02 ; mapped ; 062C 064A # 1.1 ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM
+FD03 ; mapped ; 062E 0649 # 1.1 ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM
+FD04 ; mapped ; 062E 064A # 1.1 ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM
+FD05 ; mapped ; 0635 0649 # 1.1 ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM
+FD06 ; mapped ; 0635 064A # 1.1 ARABIC LIGATURE SAD WITH YEH ISOLATED FORM
+FD07 ; mapped ; 0636 0649 # 1.1 ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM
+FD08 ; mapped ; 0636 064A # 1.1 ARABIC LIGATURE DAD WITH YEH ISOLATED FORM
+FD09 ; mapped ; 0634 062C # 1.1 ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM
+FD0A ; mapped ; 0634 062D # 1.1 ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM
+FD0B ; mapped ; 0634 062E # 1.1 ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM
+FD0C ; mapped ; 0634 0645 # 1.1 ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM
+FD0D ; mapped ; 0634 0631 # 1.1 ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM
+FD0E ; mapped ; 0633 0631 # 1.1 ARABIC LIGATURE SEEN WITH REH ISOLATED FORM
+FD0F ; mapped ; 0635 0631 # 1.1 ARABIC LIGATURE SAD WITH REH ISOLATED FORM
+FD10 ; mapped ; 0636 0631 # 1.1 ARABIC LIGATURE DAD WITH REH ISOLATED FORM
+FD11 ; mapped ; 0637 0649 # 1.1 ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM
+FD12 ; mapped ; 0637 064A # 1.1 ARABIC LIGATURE TAH WITH YEH FINAL FORM
+FD13 ; mapped ; 0639 0649 # 1.1 ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM
+FD14 ; mapped ; 0639 064A # 1.1 ARABIC LIGATURE AIN WITH YEH FINAL FORM
+FD15 ; mapped ; 063A 0649 # 1.1 ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM
+FD16 ; mapped ; 063A 064A # 1.1 ARABIC LIGATURE GHAIN WITH YEH FINAL FORM
+FD17 ; mapped ; 0633 0649 # 1.1 ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM
+FD18 ; mapped ; 0633 064A # 1.1 ARABIC LIGATURE SEEN WITH YEH FINAL FORM
+FD19 ; mapped ; 0634 0649 # 1.1 ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM
+FD1A ; mapped ; 0634 064A # 1.1 ARABIC LIGATURE SHEEN WITH YEH FINAL FORM
+FD1B ; mapped ; 062D 0649 # 1.1 ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM
+FD1C ; mapped ; 062D 064A # 1.1 ARABIC LIGATURE HAH WITH YEH FINAL FORM
+FD1D ; mapped ; 062C 0649 # 1.1 ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM
+FD1E ; mapped ; 062C 064A # 1.1 ARABIC LIGATURE JEEM WITH YEH FINAL FORM
+FD1F ; mapped ; 062E 0649 # 1.1 ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM
+FD20 ; mapped ; 062E 064A # 1.1 ARABIC LIGATURE KHAH WITH YEH FINAL FORM
+FD21 ; mapped ; 0635 0649 # 1.1 ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM
+FD22 ; mapped ; 0635 064A # 1.1 ARABIC LIGATURE SAD WITH YEH FINAL FORM
+FD23 ; mapped ; 0636 0649 # 1.1 ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM
+FD24 ; mapped ; 0636 064A # 1.1 ARABIC LIGATURE DAD WITH YEH FINAL FORM
+FD25 ; mapped ; 0634 062C # 1.1 ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM
+FD26 ; mapped ; 0634 062D # 1.1 ARABIC LIGATURE SHEEN WITH HAH FINAL FORM
+FD27 ; mapped ; 0634 062E # 1.1 ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM
+FD28 ; mapped ; 0634 0645 # 1.1 ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM
+FD29 ; mapped ; 0634 0631 # 1.1 ARABIC LIGATURE SHEEN WITH REH FINAL FORM
+FD2A ; mapped ; 0633 0631 # 1.1 ARABIC LIGATURE SEEN WITH REH FINAL FORM
+FD2B ; mapped ; 0635 0631 # 1.1 ARABIC LIGATURE SAD WITH REH FINAL FORM
+FD2C ; mapped ; 0636 0631 # 1.1 ARABIC LIGATURE DAD WITH REH FINAL FORM
+FD2D ; mapped ; 0634 062C # 1.1 ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM
+FD2E ; mapped ; 0634 062D # 1.1 ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM
+FD2F ; mapped ; 0634 062E # 1.1 ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM
+FD30 ; mapped ; 0634 0645 # 1.1 ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM
+FD31 ; mapped ; 0633 0647 # 1.1 ARABIC LIGATURE SEEN WITH HEH INITIAL FORM
+FD32 ; mapped ; 0634 0647 # 1.1 ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM
+FD33 ; mapped ; 0637 0645 # 1.1 ARABIC LIGATURE TAH WITH MEEM INITIAL FORM
+FD34 ; mapped ; 0633 062C # 1.1 ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM
+FD35 ; mapped ; 0633 062D # 1.1 ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM
+FD36 ; mapped ; 0633 062E # 1.1 ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM
+FD37 ; mapped ; 0634 062C # 1.1 ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM
+FD38 ; mapped ; 0634 062D # 1.1 ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM
+FD39 ; mapped ; 0634 062E # 1.1 ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM
+FD3A ; mapped ; 0637 0645 # 1.1 ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM
+FD3B ; mapped ; 0638 0645 # 1.1 ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM
+FD3C..FD3D ; mapped ; 0627 064B # 1.1 ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
+FD3E..FD3F ; valid ; ; NV8 # 1.1 ORNATE LEFT PARENTHESIS..ORNATE RIGHT PARENTHESIS
+FD40..FD4F ; valid ; ; NV8 # 14.0 ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH
+FD50 ; mapped ; 062A 062C 0645 #1.1 ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM
+FD51..FD52 ; mapped ; 062A 062D 062C #1.1 ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM..ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM
+FD53 ; mapped ; 062A 062D 0645 #1.1 ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM
+FD54 ; mapped ; 062A 062E 0645 #1.1 ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM
+FD55 ; mapped ; 062A 0645 062C #1.1 ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM
+FD56 ; mapped ; 062A 0645 062D #1.1 ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM
+FD57 ; mapped ; 062A 0645 062E #1.1 ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM
+FD58..FD59 ; mapped ; 062C 0645 062D #1.1 ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM..ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM
+FD5A ; mapped ; 062D 0645 064A #1.1 ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM
+FD5B ; mapped ; 062D 0645 0649 #1.1 ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD5C ; mapped ; 0633 062D 062C #1.1 ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM
+FD5D ; mapped ; 0633 062C 062D #1.1 ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM
+FD5E ; mapped ; 0633 062C 0649 #1.1 ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FD5F..FD60 ; mapped ; 0633 0645 062D #1.1 ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM..ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM
+FD61 ; mapped ; 0633 0645 062C #1.1 ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM
+FD62..FD63 ; mapped ; 0633 0645 0645 #1.1 ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM..ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM
+FD64..FD65 ; mapped ; 0635 062D 062D #1.1 ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM..ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM
+FD66 ; mapped ; 0635 0645 0645 #1.1 ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM
+FD67..FD68 ; mapped ; 0634 062D 0645 #1.1 ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM..ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM
+FD69 ; mapped ; 0634 062C 064A #1.1 ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM
+FD6A..FD6B ; mapped ; 0634 0645 062E #1.1 ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM..ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM
+FD6C..FD6D ; mapped ; 0634 0645 0645 #1.1 ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM..ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM
+FD6E ; mapped ; 0636 062D 0649 #1.1 ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD6F..FD70 ; mapped ; 0636 062E 0645 #1.1 ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM..ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM
+FD71..FD72 ; mapped ; 0637 0645 062D #1.1 ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM..ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM
+FD73 ; mapped ; 0637 0645 0645 #1.1 ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM
+FD74 ; mapped ; 0637 0645 064A #1.1 ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM
+FD75 ; mapped ; 0639 062C 0645 #1.1 ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM
+FD76..FD77 ; mapped ; 0639 0645 0645 #1.1 ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM..ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM
+FD78 ; mapped ; 0639 0645 0649 #1.1 ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD79 ; mapped ; 063A 0645 0645 #1.1 ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM
+FD7A ; mapped ; 063A 0645 064A #1.1 ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM
+FD7B ; mapped ; 063A 0645 0649 #1.1 ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD7C..FD7D ; mapped ; 0641 062E 0645 #1.1 ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM..ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM
+FD7E ; mapped ; 0642 0645 062D #1.1 ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM
+FD7F ; mapped ; 0642 0645 0645 #1.1 ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM
+FD80 ; mapped ; 0644 062D 0645 #1.1 ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM
+FD81 ; mapped ; 0644 062D 064A #1.1 ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM
+FD82 ; mapped ; 0644 062D 0649 #1.1 ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD83..FD84 ; mapped ; 0644 062C 062C #1.1 ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM..ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM
+FD85..FD86 ; mapped ; 0644 062E 0645 #1.1 ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM..ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM
+FD87..FD88 ; mapped ; 0644 0645 062D #1.1 ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM..ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM
+FD89 ; mapped ; 0645 062D 062C #1.1 ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM
+FD8A ; mapped ; 0645 062D 0645 #1.1 ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM
+FD8B ; mapped ; 0645 062D 064A #1.1 ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM
+FD8C ; mapped ; 0645 062C 062D #1.1 ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM
+FD8D ; mapped ; 0645 062C 0645 #1.1 ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM
+FD8E ; mapped ; 0645 062E 062C #1.1 ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM
+FD8F ; mapped ; 0645 062E 0645 #1.1 ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+FD90..FD91 ; disallowed # NA <reserved-FD90>..<reserved-FD91>
+FD92 ; mapped ; 0645 062C 062E #1.1 ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM
+FD93 ; mapped ; 0647 0645 062C #1.1 ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM
+FD94 ; mapped ; 0647 0645 0645 #1.1 ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM
+FD95 ; mapped ; 0646 062D 0645 #1.1 ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM
+FD96 ; mapped ; 0646 062D 0649 #1.1 ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM
+FD97..FD98 ; mapped ; 0646 062C 0645 #1.1 ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM
+FD99 ; mapped ; 0646 062C 0649 #1.1 ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FD9A ; mapped ; 0646 0645 064A #1.1 ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM
+FD9B ; mapped ; 0646 0645 0649 #1.1 ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FD9C..FD9D ; mapped ; 064A 0645 0645 #1.1 ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM..ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM
+FD9E ; mapped ; 0628 062E 064A #1.1 ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM
+FD9F ; mapped ; 062A 062C 064A #1.1 ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM
+FDA0 ; mapped ; 062A 062C 0649 #1.1 ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM
+FDA1 ; mapped ; 062A 062E 064A #1.1 ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM
+FDA2 ; mapped ; 062A 062E 0649 #1.1 ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM
+FDA3 ; mapped ; 062A 0645 064A #1.1 ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM
+FDA4 ; mapped ; 062A 0645 0649 #1.1 ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FDA5 ; mapped ; 062C 0645 064A #1.1 ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM
+FDA6 ; mapped ; 062C 062D 0649 #1.1 ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM
+FDA7 ; mapped ; 062C 0645 0649 #1.1 ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM
+FDA8 ; mapped ; 0633 062E 0649 #1.1 ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM
+FDA9 ; mapped ; 0635 062D 064A #1.1 ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM
+FDAA ; mapped ; 0634 062D 064A #1.1 ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM
+FDAB ; mapped ; 0636 062D 064A #1.1 ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM
+FDAC ; mapped ; 0644 062C 064A #1.1 ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM
+FDAD ; mapped ; 0644 0645 064A #1.1 ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM
+FDAE ; mapped ; 064A 062D 064A #1.1 ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM
+FDAF ; mapped ; 064A 062C 064A #1.1 ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM
+FDB0 ; mapped ; 064A 0645 064A #1.1 ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM
+FDB1 ; mapped ; 0645 0645 064A #1.1 ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM
+FDB2 ; mapped ; 0642 0645 064A #1.1 ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM
+FDB3 ; mapped ; 0646 062D 064A #1.1 ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM
+FDB4 ; mapped ; 0642 0645 062D #1.1 ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM
+FDB5 ; mapped ; 0644 062D 0645 #1.1 ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM
+FDB6 ; mapped ; 0639 0645 064A #1.1 ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM
+FDB7 ; mapped ; 0643 0645 064A #1.1 ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM
+FDB8 ; mapped ; 0646 062C 062D #1.1 ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM
+FDB9 ; mapped ; 0645 062E 064A #1.1 ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM
+FDBA ; mapped ; 0644 062C 0645 #1.1 ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM
+FDBB ; mapped ; 0643 0645 0645 #1.1 ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM
+FDBC ; mapped ; 0644 062C 0645 #1.1 ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM
+FDBD ; mapped ; 0646 062C 062D #1.1 ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM
+FDBE ; mapped ; 062C 062D 064A #1.1 ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM
+FDBF ; mapped ; 062D 062C 064A #1.1 ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM
+FDC0 ; mapped ; 0645 062C 064A #1.1 ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM
+FDC1 ; mapped ; 0641 0645 064A #1.1 ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM
+FDC2 ; mapped ; 0628 062D 064A #1.1 ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM
+FDC3 ; mapped ; 0643 0645 0645 #1.1 ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM
+FDC4 ; mapped ; 0639 062C 0645 #1.1 ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM
+FDC5 ; mapped ; 0635 0645 0645 #1.1 ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM
+FDC6 ; mapped ; 0633 062E 064A #1.1 ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM
+FDC7 ; mapped ; 0646 062C 064A #1.1 ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+FDC8..FDCE ; disallowed # NA <reserved-FDC8>..<reserved-FDCE>
+FDCF ; valid ; ; NV8 # 14.0 ARABIC LIGATURE SALAAMUHU ALAYNAA
+FDD0..FDEF ; disallowed # 3.1 <noncharacter-FDD0>..<noncharacter-FDEF>
+FDF0 ; mapped ; 0635 0644 06D2 #1.1 ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM
+FDF1 ; mapped ; 0642 0644 06D2 #1.1 ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM
+FDF2 ; mapped ; 0627 0644 0644 0647 #1.1 ARABIC LIGATURE ALLAH ISOLATED FORM
+FDF3 ; mapped ; 0627 0643 0628 0631 #1.1 ARABIC LIGATURE AKBAR ISOLATED FORM
+FDF4 ; mapped ; 0645 062D 0645 062F #1.1 ARABIC LIGATURE MOHAMMAD ISOLATED FORM
+FDF5 ; mapped ; 0635 0644 0639 0645 #1.1 ARABIC LIGATURE SALAM ISOLATED FORM
+FDF6 ; mapped ; 0631 0633 0648 0644 #1.1 ARABIC LIGATURE RASOUL ISOLATED FORM
+FDF7 ; mapped ; 0639 0644 064A 0647 #1.1 ARABIC LIGATURE ALAYHE ISOLATED FORM
+FDF8 ; mapped ; 0648 0633 0644 0645 #1.1 ARABIC LIGATURE WASALLAM ISOLATED FORM
+FDF9 ; mapped ; 0635 0644 0649 #1.1 ARABIC LIGATURE SALLA ISOLATED FORM
+FDFA ; disallowed_STD3_mapped ; 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645 #1.1 ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM
+FDFB ; disallowed_STD3_mapped ; 062C 0644 0020 062C 0644 0627 0644 0647 #1.1 ARABIC LIGATURE JALLAJALALOUHOU
+FDFC ; mapped ; 0631 06CC 0627 0644 #3.2 RIAL SIGN
+FDFD ; valid ; ; NV8 # 4.0 ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
+FDFE..FDFF ; valid ; ; NV8 # 14.0 ARABIC LIGATURE SUBHAANAHU WA TAAALAA..ARABIC LIGATURE AZZA WA JALL
+FE00..FE0F ; ignored # 3.2 VARIATION SELECTOR-1..VARIATION SELECTOR-16
+FE10 ; disallowed_STD3_mapped ; 002C # 4.1 PRESENTATION FORM FOR VERTICAL COMMA
+FE11 ; mapped ; 3001 # 4.1 PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA
+FE12 ; disallowed # 4.1 PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP
+FE13 ; disallowed_STD3_mapped ; 003A # 4.1 PRESENTATION FORM FOR VERTICAL COLON
+FE14 ; disallowed_STD3_mapped ; 003B # 4.1 PRESENTATION FORM FOR VERTICAL SEMICOLON
+FE15 ; disallowed_STD3_mapped ; 0021 # 4.1 PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK
+FE16 ; disallowed_STD3_mapped ; 003F # 4.1 PRESENTATION FORM FOR VERTICAL QUESTION MARK
+FE17 ; mapped ; 3016 # 4.1 PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET
+FE18 ; mapped ; 3017 # 4.1 PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET
+FE19 ; disallowed # 4.1 PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
+FE1A..FE1F ; disallowed # NA <reserved-FE1A>..<reserved-FE1F>
+FE20..FE23 ; valid # 1.1 COMBINING LIGATURE LEFT HALF..COMBINING DOUBLE TILDE RIGHT HALF
+FE24..FE26 ; valid # 5.1 COMBINING MACRON LEFT HALF..COMBINING CONJOINING MACRON
+FE27..FE2D ; valid # 7.0 COMBINING LIGATURE LEFT HALF BELOW..COMBINING CONJOINING MACRON BELOW
+FE2E..FE2F ; valid # 8.0 COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+FE30 ; disallowed # 1.1 PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
+FE31 ; mapped ; 2014 # 1.1 PRESENTATION FORM FOR VERTICAL EM DASH
+FE32 ; mapped ; 2013 # 1.1 PRESENTATION FORM FOR VERTICAL EN DASH
+FE33..FE34 ; disallowed_STD3_mapped ; 005F # 1.1 PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
+FE35 ; disallowed_STD3_mapped ; 0028 # 1.1 PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+FE36 ; disallowed_STD3_mapped ; 0029 # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+FE37 ; disallowed_STD3_mapped ; 007B # 1.1 PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+FE38 ; disallowed_STD3_mapped ; 007D # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+FE39 ; mapped ; 3014 # 1.1 PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
+FE3A ; mapped ; 3015 # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
+FE3B ; mapped ; 3010 # 1.1 PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
+FE3C ; mapped ; 3011 # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
+FE3D ; mapped ; 300A # 1.1 PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
+FE3E ; mapped ; 300B # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
+FE3F ; mapped ; 3008 # 1.1 PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
+FE40 ; mapped ; 3009 # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
+FE41 ; mapped ; 300C # 1.1 PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
+FE42 ; mapped ; 300D # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
+FE43 ; mapped ; 300E # 1.1 PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
+FE44 ; mapped ; 300F # 1.1 PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
+FE45..FE46 ; valid ; ; NV8 # 3.2 SESAME DOT..WHITE SESAME DOT
+FE47 ; disallowed_STD3_mapped ; 005B # 4.0 PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET
+FE48 ; disallowed_STD3_mapped ; 005D # 4.0 PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET
+FE49..FE4C ; disallowed_STD3_mapped ; 0020 0305 # 1.1 DASHED OVERLINE..DOUBLE WAVY OVERLINE
+FE4D..FE4F ; disallowed_STD3_mapped ; 005F # 1.1 DASHED LOW LINE..WAVY LOW LINE
+FE50 ; disallowed_STD3_mapped ; 002C # 1.1 SMALL COMMA
+FE51 ; mapped ; 3001 # 1.1 SMALL IDEOGRAPHIC COMMA
+FE52 ; disallowed # 1.1 SMALL FULL STOP
+FE53 ; disallowed # NA <reserved-FE53>
+FE54 ; disallowed_STD3_mapped ; 003B # 1.1 SMALL SEMICOLON
+FE55 ; disallowed_STD3_mapped ; 003A # 1.1 SMALL COLON
+FE56 ; disallowed_STD3_mapped ; 003F # 1.1 SMALL QUESTION MARK
+FE57 ; disallowed_STD3_mapped ; 0021 # 1.1 SMALL EXCLAMATION MARK
+FE58 ; mapped ; 2014 # 1.1 SMALL EM DASH
+FE59 ; disallowed_STD3_mapped ; 0028 # 1.1 SMALL LEFT PARENTHESIS
+FE5A ; disallowed_STD3_mapped ; 0029 # 1.1 SMALL RIGHT PARENTHESIS
+FE5B ; disallowed_STD3_mapped ; 007B # 1.1 SMALL LEFT CURLY BRACKET
+FE5C ; disallowed_STD3_mapped ; 007D # 1.1 SMALL RIGHT CURLY BRACKET
+FE5D ; mapped ; 3014 # 1.1 SMALL LEFT TORTOISE SHELL BRACKET
+FE5E ; mapped ; 3015 # 1.1 SMALL RIGHT TORTOISE SHELL BRACKET
+FE5F ; disallowed_STD3_mapped ; 0023 # 1.1 SMALL NUMBER SIGN
+FE60 ; disallowed_STD3_mapped ; 0026 # 1.1 SMALL AMPERSAND
+FE61 ; disallowed_STD3_mapped ; 002A # 1.1 SMALL ASTERISK
+FE62 ; disallowed_STD3_mapped ; 002B # 1.1 SMALL PLUS SIGN
+FE63 ; mapped ; 002D # 1.1 SMALL HYPHEN-MINUS
+FE64 ; disallowed_STD3_mapped ; 003C # 1.1 SMALL LESS-THAN SIGN
+FE65 ; disallowed_STD3_mapped ; 003E # 1.1 SMALL GREATER-THAN SIGN
+FE66 ; disallowed_STD3_mapped ; 003D # 1.1 SMALL EQUALS SIGN
+FE67 ; disallowed # NA <reserved-FE67>
+FE68 ; disallowed_STD3_mapped ; 005C # 1.1 SMALL REVERSE SOLIDUS
+FE69 ; disallowed_STD3_mapped ; 0024 # 1.1 SMALL DOLLAR SIGN
+FE6A ; disallowed_STD3_mapped ; 0025 # 1.1 SMALL PERCENT SIGN
+FE6B ; disallowed_STD3_mapped ; 0040 # 1.1 SMALL COMMERCIAL AT
+FE6C..FE6F ; disallowed # NA <reserved-FE6C>..<reserved-FE6F>
+FE70 ; disallowed_STD3_mapped ; 0020 064B # 1.1 ARABIC FATHATAN ISOLATED FORM
+FE71 ; mapped ; 0640 064B # 1.1 ARABIC TATWEEL WITH FATHATAN ABOVE
+FE72 ; disallowed_STD3_mapped ; 0020 064C # 1.1 ARABIC DAMMATAN ISOLATED FORM
+FE73 ; valid # 3.2 ARABIC TAIL FRAGMENT
+FE74 ; disallowed_STD3_mapped ; 0020 064D # 1.1 ARABIC KASRATAN ISOLATED FORM
+FE75 ; disallowed # NA <reserved-FE75>
+FE76 ; disallowed_STD3_mapped ; 0020 064E # 1.1 ARABIC FATHA ISOLATED FORM
+FE77 ; mapped ; 0640 064E # 1.1 ARABIC FATHA MEDIAL FORM
+FE78 ; disallowed_STD3_mapped ; 0020 064F # 1.1 ARABIC DAMMA ISOLATED FORM
+FE79 ; mapped ; 0640 064F # 1.1 ARABIC DAMMA MEDIAL FORM
+FE7A ; disallowed_STD3_mapped ; 0020 0650 # 1.1 ARABIC KASRA ISOLATED FORM
+FE7B ; mapped ; 0640 0650 # 1.1 ARABIC KASRA MEDIAL FORM
+FE7C ; disallowed_STD3_mapped ; 0020 0651 # 1.1 ARABIC SHADDA ISOLATED FORM
+FE7D ; mapped ; 0640 0651 # 1.1 ARABIC SHADDA MEDIAL FORM
+FE7E ; disallowed_STD3_mapped ; 0020 0652 # 1.1 ARABIC SUKUN ISOLATED FORM
+FE7F ; mapped ; 0640 0652 # 1.1 ARABIC SUKUN MEDIAL FORM
+FE80 ; mapped ; 0621 # 1.1 ARABIC LETTER HAMZA ISOLATED FORM
+FE81..FE82 ; mapped ; 0622 # 1.1 ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM..ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+FE83..FE84 ; mapped ; 0623 # 1.1 ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM..ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+FE85..FE86 ; mapped ; 0624 # 1.1 ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM..ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM
+FE87..FE88 ; mapped ; 0625 # 1.1 ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM..ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM
+FE89..FE8C ; mapped ; 0626 # 1.1 ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM..ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM
+FE8D..FE8E ; mapped ; 0627 # 1.1 ARABIC LETTER ALEF ISOLATED FORM..ARABIC LETTER ALEF FINAL FORM
+FE8F..FE92 ; mapped ; 0628 # 1.1 ARABIC LETTER BEH ISOLATED FORM..ARABIC LETTER BEH MEDIAL FORM
+FE93..FE94 ; mapped ; 0629 # 1.1 ARABIC LETTER TEH MARBUTA ISOLATED FORM..ARABIC LETTER TEH MARBUTA FINAL FORM
+FE95..FE98 ; mapped ; 062A # 1.1 ARABIC LETTER TEH ISOLATED FORM..ARABIC LETTER TEH MEDIAL FORM
+FE99..FE9C ; mapped ; 062B # 1.1 ARABIC LETTER THEH ISOLATED FORM..ARABIC LETTER THEH MEDIAL FORM
+FE9D..FEA0 ; mapped ; 062C # 1.1 ARABIC LETTER JEEM ISOLATED FORM..ARABIC LETTER JEEM MEDIAL FORM
+FEA1..FEA4 ; mapped ; 062D # 1.1 ARABIC LETTER HAH ISOLATED FORM..ARABIC LETTER HAH MEDIAL FORM
+FEA5..FEA8 ; mapped ; 062E # 1.1 ARABIC LETTER KHAH ISOLATED FORM..ARABIC LETTER KHAH MEDIAL FORM
+FEA9..FEAA ; mapped ; 062F # 1.1 ARABIC LETTER DAL ISOLATED FORM..ARABIC LETTER DAL FINAL FORM
+FEAB..FEAC ; mapped ; 0630 # 1.1 ARABIC LETTER THAL ISOLATED FORM..ARABIC LETTER THAL FINAL FORM
+FEAD..FEAE ; mapped ; 0631 # 1.1 ARABIC LETTER REH ISOLATED FORM..ARABIC LETTER REH FINAL FORM
+FEAF..FEB0 ; mapped ; 0632 # 1.1 ARABIC LETTER ZAIN ISOLATED FORM..ARABIC LETTER ZAIN FINAL FORM
+FEB1..FEB4 ; mapped ; 0633 # 1.1 ARABIC LETTER SEEN ISOLATED FORM..ARABIC LETTER SEEN MEDIAL FORM
+FEB5..FEB8 ; mapped ; 0634 # 1.1 ARABIC LETTER SHEEN ISOLATED FORM..ARABIC LETTER SHEEN MEDIAL FORM
+FEB9..FEBC ; mapped ; 0635 # 1.1 ARABIC LETTER SAD ISOLATED FORM..ARABIC LETTER SAD MEDIAL FORM
+FEBD..FEC0 ; mapped ; 0636 # 1.1 ARABIC LETTER DAD ISOLATED FORM..ARABIC LETTER DAD MEDIAL FORM
+FEC1..FEC4 ; mapped ; 0637 # 1.1 ARABIC LETTER TAH ISOLATED FORM..ARABIC LETTER TAH MEDIAL FORM
+FEC5..FEC8 ; mapped ; 0638 # 1.1 ARABIC LETTER ZAH ISOLATED FORM..ARABIC LETTER ZAH MEDIAL FORM
+FEC9..FECC ; mapped ; 0639 # 1.1 ARABIC LETTER AIN ISOLATED FORM..ARABIC LETTER AIN MEDIAL FORM
+FECD..FED0 ; mapped ; 063A # 1.1 ARABIC LETTER GHAIN ISOLATED FORM..ARABIC LETTER GHAIN MEDIAL FORM
+FED1..FED4 ; mapped ; 0641 # 1.1 ARABIC LETTER FEH ISOLATED FORM..ARABIC LETTER FEH MEDIAL FORM
+FED5..FED8 ; mapped ; 0642 # 1.1 ARABIC LETTER QAF ISOLATED FORM..ARABIC LETTER QAF MEDIAL FORM
+FED9..FEDC ; mapped ; 0643 # 1.1 ARABIC LETTER KAF ISOLATED FORM..ARABIC LETTER KAF MEDIAL FORM
+FEDD..FEE0 ; mapped ; 0644 # 1.1 ARABIC LETTER LAM ISOLATED FORM..ARABIC LETTER LAM MEDIAL FORM
+FEE1..FEE4 ; mapped ; 0645 # 1.1 ARABIC LETTER MEEM ISOLATED FORM..ARABIC LETTER MEEM MEDIAL FORM
+FEE5..FEE8 ; mapped ; 0646 # 1.1 ARABIC LETTER NOON ISOLATED FORM..ARABIC LETTER NOON MEDIAL FORM
+FEE9..FEEC ; mapped ; 0647 # 1.1 ARABIC LETTER HEH ISOLATED FORM..ARABIC LETTER HEH MEDIAL FORM
+FEED..FEEE ; mapped ; 0648 # 1.1 ARABIC LETTER WAW ISOLATED FORM..ARABIC LETTER WAW FINAL FORM
+FEEF..FEF0 ; mapped ; 0649 # 1.1 ARABIC LETTER ALEF MAKSURA ISOLATED FORM..ARABIC LETTER ALEF MAKSURA FINAL FORM
+FEF1..FEF4 ; mapped ; 064A # 1.1 ARABIC LETTER YEH ISOLATED FORM..ARABIC LETTER YEH MEDIAL FORM
+FEF5..FEF6 ; mapped ; 0644 0622 # 1.1 ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+FEF7..FEF8 ; mapped ; 0644 0623 # 1.1 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+FEF9..FEFA ; mapped ; 0644 0625 # 1.1 ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM
+FEFB..FEFC ; mapped ; 0644 0627 # 1.1 ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+FEFD..FEFE ; disallowed # NA <reserved-FEFD>..<reserved-FEFE>
+FEFF ; ignored # 1.1 ZERO WIDTH NO-BREAK SPACE
+FF00 ; disallowed # NA <reserved-FF00>
+FF01 ; disallowed_STD3_mapped ; 0021 # 1.1 FULLWIDTH EXCLAMATION MARK
+FF02 ; disallowed_STD3_mapped ; 0022 # 1.1 FULLWIDTH QUOTATION MARK
+FF03 ; disallowed_STD3_mapped ; 0023 # 1.1 FULLWIDTH NUMBER SIGN
+FF04 ; disallowed_STD3_mapped ; 0024 # 1.1 FULLWIDTH DOLLAR SIGN
+FF05 ; disallowed_STD3_mapped ; 0025 # 1.1 FULLWIDTH PERCENT SIGN
+FF06 ; disallowed_STD3_mapped ; 0026 # 1.1 FULLWIDTH AMPERSAND
+FF07 ; disallowed_STD3_mapped ; 0027 # 1.1 FULLWIDTH APOSTROPHE
+FF08 ; disallowed_STD3_mapped ; 0028 # 1.1 FULLWIDTH LEFT PARENTHESIS
+FF09 ; disallowed_STD3_mapped ; 0029 # 1.1 FULLWIDTH RIGHT PARENTHESIS
+FF0A ; disallowed_STD3_mapped ; 002A # 1.1 FULLWIDTH ASTERISK
+FF0B ; disallowed_STD3_mapped ; 002B # 1.1 FULLWIDTH PLUS SIGN
+FF0C ; disallowed_STD3_mapped ; 002C # 1.1 FULLWIDTH COMMA
+FF0D ; mapped ; 002D # 1.1 FULLWIDTH HYPHEN-MINUS
+FF0E ; mapped ; 002E # 1.1 FULLWIDTH FULL STOP
+FF0F ; disallowed_STD3_mapped ; 002F # 1.1 FULLWIDTH SOLIDUS
+FF10 ; mapped ; 0030 # 1.1 FULLWIDTH DIGIT ZERO
+FF11 ; mapped ; 0031 # 1.1 FULLWIDTH DIGIT ONE
+FF12 ; mapped ; 0032 # 1.1 FULLWIDTH DIGIT TWO
+FF13 ; mapped ; 0033 # 1.1 FULLWIDTH DIGIT THREE
+FF14 ; mapped ; 0034 # 1.1 FULLWIDTH DIGIT FOUR
+FF15 ; mapped ; 0035 # 1.1 FULLWIDTH DIGIT FIVE
+FF16 ; mapped ; 0036 # 1.1 FULLWIDTH DIGIT SIX
+FF17 ; mapped ; 0037 # 1.1 FULLWIDTH DIGIT SEVEN
+FF18 ; mapped ; 0038 # 1.1 FULLWIDTH DIGIT EIGHT
+FF19 ; mapped ; 0039 # 1.1 FULLWIDTH DIGIT NINE
+FF1A ; disallowed_STD3_mapped ; 003A # 1.1 FULLWIDTH COLON
+FF1B ; disallowed_STD3_mapped ; 003B # 1.1 FULLWIDTH SEMICOLON
+FF1C ; disallowed_STD3_mapped ; 003C # 1.1 FULLWIDTH LESS-THAN SIGN
+FF1D ; disallowed_STD3_mapped ; 003D # 1.1 FULLWIDTH EQUALS SIGN
+FF1E ; disallowed_STD3_mapped ; 003E # 1.1 FULLWIDTH GREATER-THAN SIGN
+FF1F ; disallowed_STD3_mapped ; 003F # 1.1 FULLWIDTH QUESTION MARK
+FF20 ; disallowed_STD3_mapped ; 0040 # 1.1 FULLWIDTH COMMERCIAL AT
+FF21 ; mapped ; 0061 # 1.1 FULLWIDTH LATIN CAPITAL LETTER A
+FF22 ; mapped ; 0062 # 1.1 FULLWIDTH LATIN CAPITAL LETTER B
+FF23 ; mapped ; 0063 # 1.1 FULLWIDTH LATIN CAPITAL LETTER C
+FF24 ; mapped ; 0064 # 1.1 FULLWIDTH LATIN CAPITAL LETTER D
+FF25 ; mapped ; 0065 # 1.1 FULLWIDTH LATIN CAPITAL LETTER E
+FF26 ; mapped ; 0066 # 1.1 FULLWIDTH LATIN CAPITAL LETTER F
+FF27 ; mapped ; 0067 # 1.1 FULLWIDTH LATIN CAPITAL LETTER G
+FF28 ; mapped ; 0068 # 1.1 FULLWIDTH LATIN CAPITAL LETTER H
+FF29 ; mapped ; 0069 # 1.1 FULLWIDTH LATIN CAPITAL LETTER I
+FF2A ; mapped ; 006A # 1.1 FULLWIDTH LATIN CAPITAL LETTER J
+FF2B ; mapped ; 006B # 1.1 FULLWIDTH LATIN CAPITAL LETTER K
+FF2C ; mapped ; 006C # 1.1 FULLWIDTH LATIN CAPITAL LETTER L
+FF2D ; mapped ; 006D # 1.1 FULLWIDTH LATIN CAPITAL LETTER M
+FF2E ; mapped ; 006E # 1.1 FULLWIDTH LATIN CAPITAL LETTER N
+FF2F ; mapped ; 006F # 1.1 FULLWIDTH LATIN CAPITAL LETTER O
+FF30 ; mapped ; 0070 # 1.1 FULLWIDTH LATIN CAPITAL LETTER P
+FF31 ; mapped ; 0071 # 1.1 FULLWIDTH LATIN CAPITAL LETTER Q
+FF32 ; mapped ; 0072 # 1.1 FULLWIDTH LATIN CAPITAL LETTER R
+FF33 ; mapped ; 0073 # 1.1 FULLWIDTH LATIN CAPITAL LETTER S
+FF34 ; mapped ; 0074 # 1.1 FULLWIDTH LATIN CAPITAL LETTER T
+FF35 ; mapped ; 0075 # 1.1 FULLWIDTH LATIN CAPITAL LETTER U
+FF36 ; mapped ; 0076 # 1.1 FULLWIDTH LATIN CAPITAL LETTER V
+FF37 ; mapped ; 0077 # 1.1 FULLWIDTH LATIN CAPITAL LETTER W
+FF38 ; mapped ; 0078 # 1.1 FULLWIDTH LATIN CAPITAL LETTER X
+FF39 ; mapped ; 0079 # 1.1 FULLWIDTH LATIN CAPITAL LETTER Y
+FF3A ; mapped ; 007A # 1.1 FULLWIDTH LATIN CAPITAL LETTER Z
+FF3B ; disallowed_STD3_mapped ; 005B # 1.1 FULLWIDTH LEFT SQUARE BRACKET
+FF3C ; disallowed_STD3_mapped ; 005C # 1.1 FULLWIDTH REVERSE SOLIDUS
+FF3D ; disallowed_STD3_mapped ; 005D # 1.1 FULLWIDTH RIGHT SQUARE BRACKET
+FF3E ; disallowed_STD3_mapped ; 005E # 1.1 FULLWIDTH CIRCUMFLEX ACCENT
+FF3F ; disallowed_STD3_mapped ; 005F # 1.1 FULLWIDTH LOW LINE
+FF40 ; disallowed_STD3_mapped ; 0060 # 1.1 FULLWIDTH GRAVE ACCENT
+FF41 ; mapped ; 0061 # 1.1 FULLWIDTH LATIN SMALL LETTER A
+FF42 ; mapped ; 0062 # 1.1 FULLWIDTH LATIN SMALL LETTER B
+FF43 ; mapped ; 0063 # 1.1 FULLWIDTH LATIN SMALL LETTER C
+FF44 ; mapped ; 0064 # 1.1 FULLWIDTH LATIN SMALL LETTER D
+FF45 ; mapped ; 0065 # 1.1 FULLWIDTH LATIN SMALL LETTER E
+FF46 ; mapped ; 0066 # 1.1 FULLWIDTH LATIN SMALL LETTER F
+FF47 ; mapped ; 0067 # 1.1 FULLWIDTH LATIN SMALL LETTER G
+FF48 ; mapped ; 0068 # 1.1 FULLWIDTH LATIN SMALL LETTER H
+FF49 ; mapped ; 0069 # 1.1 FULLWIDTH LATIN SMALL LETTER I
+FF4A ; mapped ; 006A # 1.1 FULLWIDTH LATIN SMALL LETTER J
+FF4B ; mapped ; 006B # 1.1 FULLWIDTH LATIN SMALL LETTER K
+FF4C ; mapped ; 006C # 1.1 FULLWIDTH LATIN SMALL LETTER L
+FF4D ; mapped ; 006D # 1.1 FULLWIDTH LATIN SMALL LETTER M
+FF4E ; mapped ; 006E # 1.1 FULLWIDTH LATIN SMALL LETTER N
+FF4F ; mapped ; 006F # 1.1 FULLWIDTH LATIN SMALL LETTER O
+FF50 ; mapped ; 0070 # 1.1 FULLWIDTH LATIN SMALL LETTER P
+FF51 ; mapped ; 0071 # 1.1 FULLWIDTH LATIN SMALL LETTER Q
+FF52 ; mapped ; 0072 # 1.1 FULLWIDTH LATIN SMALL LETTER R
+FF53 ; mapped ; 0073 # 1.1 FULLWIDTH LATIN SMALL LETTER S
+FF54 ; mapped ; 0074 # 1.1 FULLWIDTH LATIN SMALL LETTER T
+FF55 ; mapped ; 0075 # 1.1 FULLWIDTH LATIN SMALL LETTER U
+FF56 ; mapped ; 0076 # 1.1 FULLWIDTH LATIN SMALL LETTER V
+FF57 ; mapped ; 0077 # 1.1 FULLWIDTH LATIN SMALL LETTER W
+FF58 ; mapped ; 0078 # 1.1 FULLWIDTH LATIN SMALL LETTER X
+FF59 ; mapped ; 0079 # 1.1 FULLWIDTH LATIN SMALL LETTER Y
+FF5A ; mapped ; 007A # 1.1 FULLWIDTH LATIN SMALL LETTER Z
+FF5B ; disallowed_STD3_mapped ; 007B # 1.1 FULLWIDTH LEFT CURLY BRACKET
+FF5C ; disallowed_STD3_mapped ; 007C # 1.1 FULLWIDTH VERTICAL LINE
+FF5D ; disallowed_STD3_mapped ; 007D # 1.1 FULLWIDTH RIGHT CURLY BRACKET
+FF5E ; disallowed_STD3_mapped ; 007E # 1.1 FULLWIDTH TILDE
+FF5F ; mapped ; 2985 # 3.2 FULLWIDTH LEFT WHITE PARENTHESIS
+FF60 ; mapped ; 2986 # 3.2 FULLWIDTH RIGHT WHITE PARENTHESIS
+FF61 ; mapped ; 002E # 1.1 HALFWIDTH IDEOGRAPHIC FULL STOP
+FF62 ; mapped ; 300C # 1.1 HALFWIDTH LEFT CORNER BRACKET
+FF63 ; mapped ; 300D # 1.1 HALFWIDTH RIGHT CORNER BRACKET
+FF64 ; mapped ; 3001 # 1.1 HALFWIDTH IDEOGRAPHIC COMMA
+FF65 ; mapped ; 30FB # 1.1 HALFWIDTH KATAKANA MIDDLE DOT
+FF66 ; mapped ; 30F2 # 1.1 HALFWIDTH KATAKANA LETTER WO
+FF67 ; mapped ; 30A1 # 1.1 HALFWIDTH KATAKANA LETTER SMALL A
+FF68 ; mapped ; 30A3 # 1.1 HALFWIDTH KATAKANA LETTER SMALL I
+FF69 ; mapped ; 30A5 # 1.1 HALFWIDTH KATAKANA LETTER SMALL U
+FF6A ; mapped ; 30A7 # 1.1 HALFWIDTH KATAKANA LETTER SMALL E
+FF6B ; mapped ; 30A9 # 1.1 HALFWIDTH KATAKANA LETTER SMALL O
+FF6C ; mapped ; 30E3 # 1.1 HALFWIDTH KATAKANA LETTER SMALL YA
+FF6D ; mapped ; 30E5 # 1.1 HALFWIDTH KATAKANA LETTER SMALL YU
+FF6E ; mapped ; 30E7 # 1.1 HALFWIDTH KATAKANA LETTER SMALL YO
+FF6F ; mapped ; 30C3 # 1.1 HALFWIDTH KATAKANA LETTER SMALL TU
+FF70 ; mapped ; 30FC # 1.1 HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF71 ; mapped ; 30A2 # 1.1 HALFWIDTH KATAKANA LETTER A
+FF72 ; mapped ; 30A4 # 1.1 HALFWIDTH KATAKANA LETTER I
+FF73 ; mapped ; 30A6 # 1.1 HALFWIDTH KATAKANA LETTER U
+FF74 ; mapped ; 30A8 # 1.1 HALFWIDTH KATAKANA LETTER E
+FF75 ; mapped ; 30AA # 1.1 HALFWIDTH KATAKANA LETTER O
+FF76 ; mapped ; 30AB # 1.1 HALFWIDTH KATAKANA LETTER KA
+FF77 ; mapped ; 30AD # 1.1 HALFWIDTH KATAKANA LETTER KI
+FF78 ; mapped ; 30AF # 1.1 HALFWIDTH KATAKANA LETTER KU
+FF79 ; mapped ; 30B1 # 1.1 HALFWIDTH KATAKANA LETTER KE
+FF7A ; mapped ; 30B3 # 1.1 HALFWIDTH KATAKANA LETTER KO
+FF7B ; mapped ; 30B5 # 1.1 HALFWIDTH KATAKANA LETTER SA
+FF7C ; mapped ; 30B7 # 1.1 HALFWIDTH KATAKANA LETTER SI
+FF7D ; mapped ; 30B9 # 1.1 HALFWIDTH KATAKANA LETTER SU
+FF7E ; mapped ; 30BB # 1.1 HALFWIDTH KATAKANA LETTER SE
+FF7F ; mapped ; 30BD # 1.1 HALFWIDTH KATAKANA LETTER SO
+FF80 ; mapped ; 30BF # 1.1 HALFWIDTH KATAKANA LETTER TA
+FF81 ; mapped ; 30C1 # 1.1 HALFWIDTH KATAKANA LETTER TI
+FF82 ; mapped ; 30C4 # 1.1 HALFWIDTH KATAKANA LETTER TU
+FF83 ; mapped ; 30C6 # 1.1 HALFWIDTH KATAKANA LETTER TE
+FF84 ; mapped ; 30C8 # 1.1 HALFWIDTH KATAKANA LETTER TO
+FF85 ; mapped ; 30CA # 1.1 HALFWIDTH KATAKANA LETTER NA
+FF86 ; mapped ; 30CB # 1.1 HALFWIDTH KATAKANA LETTER NI
+FF87 ; mapped ; 30CC # 1.1 HALFWIDTH KATAKANA LETTER NU
+FF88 ; mapped ; 30CD # 1.1 HALFWIDTH KATAKANA LETTER NE
+FF89 ; mapped ; 30CE # 1.1 HALFWIDTH KATAKANA LETTER NO
+FF8A ; mapped ; 30CF # 1.1 HALFWIDTH KATAKANA LETTER HA
+FF8B ; mapped ; 30D2 # 1.1 HALFWIDTH KATAKANA LETTER HI
+FF8C ; mapped ; 30D5 # 1.1 HALFWIDTH KATAKANA LETTER HU
+FF8D ; mapped ; 30D8 # 1.1 HALFWIDTH KATAKANA LETTER HE
+FF8E ; mapped ; 30DB # 1.1 HALFWIDTH KATAKANA LETTER HO
+FF8F ; mapped ; 30DE # 1.1 HALFWIDTH KATAKANA LETTER MA
+FF90 ; mapped ; 30DF # 1.1 HALFWIDTH KATAKANA LETTER MI
+FF91 ; mapped ; 30E0 # 1.1 HALFWIDTH KATAKANA LETTER MU
+FF92 ; mapped ; 30E1 # 1.1 HALFWIDTH KATAKANA LETTER ME
+FF93 ; mapped ; 30E2 # 1.1 HALFWIDTH KATAKANA LETTER MO
+FF94 ; mapped ; 30E4 # 1.1 HALFWIDTH KATAKANA LETTER YA
+FF95 ; mapped ; 30E6 # 1.1 HALFWIDTH KATAKANA LETTER YU
+FF96 ; mapped ; 30E8 # 1.1 HALFWIDTH KATAKANA LETTER YO
+FF97 ; mapped ; 30E9 # 1.1 HALFWIDTH KATAKANA LETTER RA
+FF98 ; mapped ; 30EA # 1.1 HALFWIDTH KATAKANA LETTER RI
+FF99 ; mapped ; 30EB # 1.1 HALFWIDTH KATAKANA LETTER RU
+FF9A ; mapped ; 30EC # 1.1 HALFWIDTH KATAKANA LETTER RE
+FF9B ; mapped ; 30ED # 1.1 HALFWIDTH KATAKANA LETTER RO
+FF9C ; mapped ; 30EF # 1.1 HALFWIDTH KATAKANA LETTER WA
+FF9D ; mapped ; 30F3 # 1.1 HALFWIDTH KATAKANA LETTER N
+FF9E ; mapped ; 3099 # 1.1 HALFWIDTH KATAKANA VOICED SOUND MARK
+FF9F ; mapped ; 309A # 1.1 HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+FFA0 ; disallowed # 1.1 HALFWIDTH HANGUL FILLER
+FFA1 ; mapped ; 1100 # 1.1 HALFWIDTH HANGUL LETTER KIYEOK
+FFA2 ; mapped ; 1101 # 1.1 HALFWIDTH HANGUL LETTER SSANGKIYEOK
+FFA3 ; mapped ; 11AA # 1.1 HALFWIDTH HANGUL LETTER KIYEOK-SIOS
+FFA4 ; mapped ; 1102 # 1.1 HALFWIDTH HANGUL LETTER NIEUN
+FFA5 ; mapped ; 11AC # 1.1 HALFWIDTH HANGUL LETTER NIEUN-CIEUC
+FFA6 ; mapped ; 11AD # 1.1 HALFWIDTH HANGUL LETTER NIEUN-HIEUH
+FFA7 ; mapped ; 1103 # 1.1 HALFWIDTH HANGUL LETTER TIKEUT
+FFA8 ; mapped ; 1104 # 1.1 HALFWIDTH HANGUL LETTER SSANGTIKEUT
+FFA9 ; mapped ; 1105 # 1.1 HALFWIDTH HANGUL LETTER RIEUL
+FFAA ; mapped ; 11B0 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-KIYEOK
+FFAB ; mapped ; 11B1 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-MIEUM
+FFAC ; mapped ; 11B2 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-PIEUP
+FFAD ; mapped ; 11B3 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-SIOS
+FFAE ; mapped ; 11B4 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-THIEUTH
+FFAF ; mapped ; 11B5 # 1.1 HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH
+FFB0 ; mapped ; 111A # 1.1 HALFWIDTH HANGUL LETTER RIEUL-HIEUH
+FFB1 ; mapped ; 1106 # 1.1 HALFWIDTH HANGUL LETTER MIEUM
+FFB2 ; mapped ; 1107 # 1.1 HALFWIDTH HANGUL LETTER PIEUP
+FFB3 ; mapped ; 1108 # 1.1 HALFWIDTH HANGUL LETTER SSANGPIEUP
+FFB4 ; mapped ; 1121 # 1.1 HALFWIDTH HANGUL LETTER PIEUP-SIOS
+FFB5 ; mapped ; 1109 # 1.1 HALFWIDTH HANGUL LETTER SIOS
+FFB6 ; mapped ; 110A # 1.1 HALFWIDTH HANGUL LETTER SSANGSIOS
+FFB7 ; mapped ; 110B # 1.1 HALFWIDTH HANGUL LETTER IEUNG
+FFB8 ; mapped ; 110C # 1.1 HALFWIDTH HANGUL LETTER CIEUC
+FFB9 ; mapped ; 110D # 1.1 HALFWIDTH HANGUL LETTER SSANGCIEUC
+FFBA ; mapped ; 110E # 1.1 HALFWIDTH HANGUL LETTER CHIEUCH
+FFBB ; mapped ; 110F # 1.1 HALFWIDTH HANGUL LETTER KHIEUKH
+FFBC ; mapped ; 1110 # 1.1 HALFWIDTH HANGUL LETTER THIEUTH
+FFBD ; mapped ; 1111 # 1.1 HALFWIDTH HANGUL LETTER PHIEUPH
+FFBE ; mapped ; 1112 # 1.1 HALFWIDTH HANGUL LETTER HIEUH
+FFBF..FFC1 ; disallowed # NA <reserved-FFBF>..<reserved-FFC1>
+FFC2 ; mapped ; 1161 # 1.1 HALFWIDTH HANGUL LETTER A
+FFC3 ; mapped ; 1162 # 1.1 HALFWIDTH HANGUL LETTER AE
+FFC4 ; mapped ; 1163 # 1.1 HALFWIDTH HANGUL LETTER YA
+FFC5 ; mapped ; 1164 # 1.1 HALFWIDTH HANGUL LETTER YAE
+FFC6 ; mapped ; 1165 # 1.1 HALFWIDTH HANGUL LETTER EO
+FFC7 ; mapped ; 1166 # 1.1 HALFWIDTH HANGUL LETTER E
+FFC8..FFC9 ; disallowed # NA <reserved-FFC8>..<reserved-FFC9>
+FFCA ; mapped ; 1167 # 1.1 HALFWIDTH HANGUL LETTER YEO
+FFCB ; mapped ; 1168 # 1.1 HALFWIDTH HANGUL LETTER YE
+FFCC ; mapped ; 1169 # 1.1 HALFWIDTH HANGUL LETTER O
+FFCD ; mapped ; 116A # 1.1 HALFWIDTH HANGUL LETTER WA
+FFCE ; mapped ; 116B # 1.1 HALFWIDTH HANGUL LETTER WAE
+FFCF ; mapped ; 116C # 1.1 HALFWIDTH HANGUL LETTER OE
+FFD0..FFD1 ; disallowed # NA <reserved-FFD0>..<reserved-FFD1>
+FFD2 ; mapped ; 116D # 1.1 HALFWIDTH HANGUL LETTER YO
+FFD3 ; mapped ; 116E # 1.1 HALFWIDTH HANGUL LETTER U
+FFD4 ; mapped ; 116F # 1.1 HALFWIDTH HANGUL LETTER WEO
+FFD5 ; mapped ; 1170 # 1.1 HALFWIDTH HANGUL LETTER WE
+FFD6 ; mapped ; 1171 # 1.1 HALFWIDTH HANGUL LETTER WI
+FFD7 ; mapped ; 1172 # 1.1 HALFWIDTH HANGUL LETTER YU
+FFD8..FFD9 ; disallowed # NA <reserved-FFD8>..<reserved-FFD9>
+FFDA ; mapped ; 1173 # 1.1 HALFWIDTH HANGUL LETTER EU
+FFDB ; mapped ; 1174 # 1.1 HALFWIDTH HANGUL LETTER YI
+FFDC ; mapped ; 1175 # 1.1 HALFWIDTH HANGUL LETTER I
+FFDD..FFDF ; disallowed # NA <reserved-FFDD>..<reserved-FFDF>
+FFE0 ; mapped ; 00A2 # 1.1 FULLWIDTH CENT SIGN
+FFE1 ; mapped ; 00A3 # 1.1 FULLWIDTH POUND SIGN
+FFE2 ; mapped ; 00AC # 1.1 FULLWIDTH NOT SIGN
+FFE3 ; disallowed_STD3_mapped ; 0020 0304 # 1.1 FULLWIDTH MACRON
+FFE4 ; mapped ; 00A6 # 1.1 FULLWIDTH BROKEN BAR
+FFE5 ; mapped ; 00A5 # 1.1 FULLWIDTH YEN SIGN
+FFE6 ; mapped ; 20A9 # 1.1 FULLWIDTH WON SIGN
+FFE7 ; disallowed # NA <reserved-FFE7>
+FFE8 ; mapped ; 2502 # 1.1 HALFWIDTH FORMS LIGHT VERTICAL
+FFE9 ; mapped ; 2190 # 1.1 HALFWIDTH LEFTWARDS ARROW
+FFEA ; mapped ; 2191 # 1.1 HALFWIDTH UPWARDS ARROW
+FFEB ; mapped ; 2192 # 1.1 HALFWIDTH RIGHTWARDS ARROW
+FFEC ; mapped ; 2193 # 1.1 HALFWIDTH DOWNWARDS ARROW
+FFED ; mapped ; 25A0 # 1.1 HALFWIDTH BLACK SQUARE
+FFEE ; mapped ; 25CB # 1.1 HALFWIDTH WHITE CIRCLE
+FFEF..FFF8 ; disallowed # NA <reserved-FFEF>..<reserved-FFF8>
+FFF9..FFFB ; disallowed # 3.0 INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
+FFFC ; disallowed # 2.1 OBJECT REPLACEMENT CHARACTER
+FFFD ; disallowed # 1.1 REPLACEMENT CHARACTER
+FFFE..FFFF ; disallowed # 1.1 <noncharacter-FFFE>..<noncharacter-FFFF>
+10000..1000B ; valid # 4.0 LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
+1000C ; disallowed # NA <reserved-1000C>
+1000D..10026 ; valid # 4.0 LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
+10027 ; disallowed # NA <reserved-10027>
+10028..1003A ; valid # 4.0 LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
+1003B ; disallowed # NA <reserved-1003B>
+1003C..1003D ; valid # 4.0 LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
+1003E ; disallowed # NA <reserved-1003E>
+1003F..1004D ; valid # 4.0 LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
+1004E..1004F ; disallowed # NA <reserved-1004E>..<reserved-1004F>
+10050..1005D ; valid # 4.0 LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
+1005E..1007F ; disallowed # NA <reserved-1005E>..<reserved-1007F>
+10080..100FA ; valid # 4.0 LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
+100FB..100FF ; disallowed # NA <reserved-100FB>..<reserved-100FF>
+10100..10102 ; valid ; ; NV8 # 4.0 AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
+10103..10106 ; disallowed # NA <reserved-10103>..<reserved-10106>
+10107..10133 ; valid ; ; NV8 # 4.0 AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
+10134..10136 ; disallowed # NA <reserved-10134>..<reserved-10136>
+10137..1013F ; valid ; ; NV8 # 4.0 AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
+10140..1018A ; valid ; ; NV8 # 4.1 GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ZERO SIGN
+1018B..1018C ; valid ; ; NV8 # 7.0 GREEK ONE QUARTER SIGN..GREEK SINUSOID SIGN
+1018D..1018E ; valid ; ; NV8 # 9.0 GREEK INDICTION SIGN..NOMISMA SIGN
+1018F ; disallowed # NA <reserved-1018F>
+10190..1019B ; valid ; ; NV8 # 5.1 ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN
+1019C ; valid ; ; NV8 # 13.0 ASCIA SYMBOL
+1019D..1019F ; disallowed # NA <reserved-1019D>..<reserved-1019F>
+101A0 ; valid ; ; NV8 # 7.0 GREEK SYMBOL TAU RHO
+101A1..101CF ; disallowed # NA <reserved-101A1>..<reserved-101CF>
+101D0..101FC ; valid ; ; NV8 # 5.1 PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
+101FD ; valid # 5.1 PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
+101FE..1027F ; disallowed # NA <reserved-101FE>..<reserved-1027F>
+10280..1029C ; valid # 5.1 LYCIAN LETTER A..LYCIAN LETTER X
+1029D..1029F ; disallowed # NA <reserved-1029D>..<reserved-1029F>
+102A0..102D0 ; valid # 5.1 CARIAN LETTER A..CARIAN LETTER UUU3
+102D1..102DF ; disallowed # NA <reserved-102D1>..<reserved-102DF>
+102E0 ; valid # 7.0 COPTIC EPACT THOUSANDS MARK
+102E1..102FB ; valid ; ; NV8 # 7.0 COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
+102FC..102FF ; disallowed # NA <reserved-102FC>..<reserved-102FF>
+10300..1031E ; valid # 3.1 OLD ITALIC LETTER A..OLD ITALIC LETTER UU
+1031F ; valid # 7.0 OLD ITALIC LETTER ESS
+10320..10323 ; valid ; ; NV8 # 3.1 OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
+10324..1032C ; disallowed # NA <reserved-10324>..<reserved-1032C>
+1032D..1032F ; valid # 10.0 OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE
+10330..10340 ; valid # 3.1 GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
+10341 ; valid ; ; NV8 # 3.1 GOTHIC LETTER NINETY
+10342..10349 ; valid # 3.1 GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
+1034A ; valid ; ; NV8 # 3.1 GOTHIC LETTER NINE HUNDRED
+1034B..1034F ; disallowed # NA <reserved-1034B>..<reserved-1034F>
+10350..1037A ; valid # 7.0 OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
+1037B..1037F ; disallowed # NA <reserved-1037B>..<reserved-1037F>
+10380..1039D ; valid # 4.0 UGARITIC LETTER ALPA..UGARITIC LETTER SSU
+1039E ; disallowed # NA <reserved-1039E>
+1039F ; valid ; ; NV8 # 4.0 UGARITIC WORD DIVIDER
+103A0..103C3 ; valid # 4.1 OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
+103C4..103C7 ; disallowed # NA <reserved-103C4>..<reserved-103C7>
+103C8..103CF ; valid # 4.1 OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
+103D0..103D5 ; valid ; ; NV8 # 4.1 OLD PERSIAN WORD DIVIDER..OLD PERSIAN NUMBER HUNDRED
+103D6..103FF ; disallowed # NA <reserved-103D6>..<reserved-103FF>
+10400 ; mapped ; 10428 # 3.1 DESERET CAPITAL LETTER LONG I
+10401 ; mapped ; 10429 # 3.1 DESERET CAPITAL LETTER LONG E
+10402 ; mapped ; 1042A # 3.1 DESERET CAPITAL LETTER LONG A
+10403 ; mapped ; 1042B # 3.1 DESERET CAPITAL LETTER LONG AH
+10404 ; mapped ; 1042C # 3.1 DESERET CAPITAL LETTER LONG O
+10405 ; mapped ; 1042D # 3.1 DESERET CAPITAL LETTER LONG OO
+10406 ; mapped ; 1042E # 3.1 DESERET CAPITAL LETTER SHORT I
+10407 ; mapped ; 1042F # 3.1 DESERET CAPITAL LETTER SHORT E
+10408 ; mapped ; 10430 # 3.1 DESERET CAPITAL LETTER SHORT A
+10409 ; mapped ; 10431 # 3.1 DESERET CAPITAL LETTER SHORT AH
+1040A ; mapped ; 10432 # 3.1 DESERET CAPITAL LETTER SHORT O
+1040B ; mapped ; 10433 # 3.1 DESERET CAPITAL LETTER SHORT OO
+1040C ; mapped ; 10434 # 3.1 DESERET CAPITAL LETTER AY
+1040D ; mapped ; 10435 # 3.1 DESERET CAPITAL LETTER OW
+1040E ; mapped ; 10436 # 3.1 DESERET CAPITAL LETTER WU
+1040F ; mapped ; 10437 # 3.1 DESERET CAPITAL LETTER YEE
+10410 ; mapped ; 10438 # 3.1 DESERET CAPITAL LETTER H
+10411 ; mapped ; 10439 # 3.1 DESERET CAPITAL LETTER PEE
+10412 ; mapped ; 1043A # 3.1 DESERET CAPITAL LETTER BEE
+10413 ; mapped ; 1043B # 3.1 DESERET CAPITAL LETTER TEE
+10414 ; mapped ; 1043C # 3.1 DESERET CAPITAL LETTER DEE
+10415 ; mapped ; 1043D # 3.1 DESERET CAPITAL LETTER CHEE
+10416 ; mapped ; 1043E # 3.1 DESERET CAPITAL LETTER JEE
+10417 ; mapped ; 1043F # 3.1 DESERET CAPITAL LETTER KAY
+10418 ; mapped ; 10440 # 3.1 DESERET CAPITAL LETTER GAY
+10419 ; mapped ; 10441 # 3.1 DESERET CAPITAL LETTER EF
+1041A ; mapped ; 10442 # 3.1 DESERET CAPITAL LETTER VEE
+1041B ; mapped ; 10443 # 3.1 DESERET CAPITAL LETTER ETH
+1041C ; mapped ; 10444 # 3.1 DESERET CAPITAL LETTER THEE
+1041D ; mapped ; 10445 # 3.1 DESERET CAPITAL LETTER ES
+1041E ; mapped ; 10446 # 3.1 DESERET CAPITAL LETTER ZEE
+1041F ; mapped ; 10447 # 3.1 DESERET CAPITAL LETTER ESH
+10420 ; mapped ; 10448 # 3.1 DESERET CAPITAL LETTER ZHEE
+10421 ; mapped ; 10449 # 3.1 DESERET CAPITAL LETTER ER
+10422 ; mapped ; 1044A # 3.1 DESERET CAPITAL LETTER EL
+10423 ; mapped ; 1044B # 3.1 DESERET CAPITAL LETTER EM
+10424 ; mapped ; 1044C # 3.1 DESERET CAPITAL LETTER EN
+10425 ; mapped ; 1044D # 3.1 DESERET CAPITAL LETTER ENG
+10426 ; mapped ; 1044E # 4.0 DESERET CAPITAL LETTER OI
+10427 ; mapped ; 1044F # 4.0 DESERET CAPITAL LETTER EW
+10428..1044D ; valid # 3.1 DESERET SMALL LETTER LONG I..DESERET SMALL LETTER ENG
+1044E..1049D ; valid # 4.0 DESERET SMALL LETTER OI..OSMANYA LETTER OO
+1049E..1049F ; disallowed # NA <reserved-1049E>..<reserved-1049F>
+104A0..104A9 ; valid # 4.0 OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
+104AA..104AF ; disallowed # NA <reserved-104AA>..<reserved-104AF>
+104B0 ; mapped ; 104D8 # 9.0 OSAGE CAPITAL LETTER A
+104B1 ; mapped ; 104D9 # 9.0 OSAGE CAPITAL LETTER AI
+104B2 ; mapped ; 104DA # 9.0 OSAGE CAPITAL LETTER AIN
+104B3 ; mapped ; 104DB # 9.0 OSAGE CAPITAL LETTER AH
+104B4 ; mapped ; 104DC # 9.0 OSAGE CAPITAL LETTER BRA
+104B5 ; mapped ; 104DD # 9.0 OSAGE CAPITAL LETTER CHA
+104B6 ; mapped ; 104DE # 9.0 OSAGE CAPITAL LETTER EHCHA
+104B7 ; mapped ; 104DF # 9.0 OSAGE CAPITAL LETTER E
+104B8 ; mapped ; 104E0 # 9.0 OSAGE CAPITAL LETTER EIN
+104B9 ; mapped ; 104E1 # 9.0 OSAGE CAPITAL LETTER HA
+104BA ; mapped ; 104E2 # 9.0 OSAGE CAPITAL LETTER HYA
+104BB ; mapped ; 104E3 # 9.0 OSAGE CAPITAL LETTER I
+104BC ; mapped ; 104E4 # 9.0 OSAGE CAPITAL LETTER KA
+104BD ; mapped ; 104E5 # 9.0 OSAGE CAPITAL LETTER EHKA
+104BE ; mapped ; 104E6 # 9.0 OSAGE CAPITAL LETTER KYA
+104BF ; mapped ; 104E7 # 9.0 OSAGE CAPITAL LETTER LA
+104C0 ; mapped ; 104E8 # 9.0 OSAGE CAPITAL LETTER MA
+104C1 ; mapped ; 104E9 # 9.0 OSAGE CAPITAL LETTER NA
+104C2 ; mapped ; 104EA # 9.0 OSAGE CAPITAL LETTER O
+104C3 ; mapped ; 104EB # 9.0 OSAGE CAPITAL LETTER OIN
+104C4 ; mapped ; 104EC # 9.0 OSAGE CAPITAL LETTER PA
+104C5 ; mapped ; 104ED # 9.0 OSAGE CAPITAL LETTER EHPA
+104C6 ; mapped ; 104EE # 9.0 OSAGE CAPITAL LETTER SA
+104C7 ; mapped ; 104EF # 9.0 OSAGE CAPITAL LETTER SHA
+104C8 ; mapped ; 104F0 # 9.0 OSAGE CAPITAL LETTER TA
+104C9 ; mapped ; 104F1 # 9.0 OSAGE CAPITAL LETTER EHTA
+104CA ; mapped ; 104F2 # 9.0 OSAGE CAPITAL LETTER TSA
+104CB ; mapped ; 104F3 # 9.0 OSAGE CAPITAL LETTER EHTSA
+104CC ; mapped ; 104F4 # 9.0 OSAGE CAPITAL LETTER TSHA
+104CD ; mapped ; 104F5 # 9.0 OSAGE CAPITAL LETTER DHA
+104CE ; mapped ; 104F6 # 9.0 OSAGE CAPITAL LETTER U
+104CF ; mapped ; 104F7 # 9.0 OSAGE CAPITAL LETTER WA
+104D0 ; mapped ; 104F8 # 9.0 OSAGE CAPITAL LETTER KHA
+104D1 ; mapped ; 104F9 # 9.0 OSAGE CAPITAL LETTER GHA
+104D2 ; mapped ; 104FA # 9.0 OSAGE CAPITAL LETTER ZA
+104D3 ; mapped ; 104FB # 9.0 OSAGE CAPITAL LETTER ZHA
+104D4..104D7 ; disallowed # NA <reserved-104D4>..<reserved-104D7>
+104D8..104FB ; valid # 9.0 OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
+104FC..104FF ; disallowed # NA <reserved-104FC>..<reserved-104FF>
+10500..10527 ; valid # 7.0 ELBASAN LETTER A..ELBASAN LETTER KHE
+10528..1052F ; disallowed # NA <reserved-10528>..<reserved-1052F>
+10530..10563 ; valid # 7.0 CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
+10564..1056E ; disallowed # NA <reserved-10564>..<reserved-1056E>
+1056F ; valid ; ; NV8 # 7.0 CAUCASIAN ALBANIAN CITATION MARK
+10570 ; mapped ; 10597 # 14.0 VITHKUQI CAPITAL LETTER A
+10571 ; mapped ; 10598 # 14.0 VITHKUQI CAPITAL LETTER BBE
+10572 ; mapped ; 10599 # 14.0 VITHKUQI CAPITAL LETTER BE
+10573 ; mapped ; 1059A # 14.0 VITHKUQI CAPITAL LETTER CE
+10574 ; mapped ; 1059B # 14.0 VITHKUQI CAPITAL LETTER CHE
+10575 ; mapped ; 1059C # 14.0 VITHKUQI CAPITAL LETTER DE
+10576 ; mapped ; 1059D # 14.0 VITHKUQI CAPITAL LETTER DHE
+10577 ; mapped ; 1059E # 14.0 VITHKUQI CAPITAL LETTER EI
+10578 ; mapped ; 1059F # 14.0 VITHKUQI CAPITAL LETTER E
+10579 ; mapped ; 105A0 # 14.0 VITHKUQI CAPITAL LETTER FE
+1057A ; mapped ; 105A1 # 14.0 VITHKUQI CAPITAL LETTER GA
+1057B ; disallowed # NA <reserved-1057B>
+1057C ; mapped ; 105A3 # 14.0 VITHKUQI CAPITAL LETTER HA
+1057D ; mapped ; 105A4 # 14.0 VITHKUQI CAPITAL LETTER HHA
+1057E ; mapped ; 105A5 # 14.0 VITHKUQI CAPITAL LETTER I
+1057F ; mapped ; 105A6 # 14.0 VITHKUQI CAPITAL LETTER IJE
+10580 ; mapped ; 105A7 # 14.0 VITHKUQI CAPITAL LETTER JE
+10581 ; mapped ; 105A8 # 14.0 VITHKUQI CAPITAL LETTER KA
+10582 ; mapped ; 105A9 # 14.0 VITHKUQI CAPITAL LETTER LA
+10583 ; mapped ; 105AA # 14.0 VITHKUQI CAPITAL LETTER LLA
+10584 ; mapped ; 105AB # 14.0 VITHKUQI CAPITAL LETTER ME
+10585 ; mapped ; 105AC # 14.0 VITHKUQI CAPITAL LETTER NE
+10586 ; mapped ; 105AD # 14.0 VITHKUQI CAPITAL LETTER NJE
+10587 ; mapped ; 105AE # 14.0 VITHKUQI CAPITAL LETTER O
+10588 ; mapped ; 105AF # 14.0 VITHKUQI CAPITAL LETTER PE
+10589 ; mapped ; 105B0 # 14.0 VITHKUQI CAPITAL LETTER QA
+1058A ; mapped ; 105B1 # 14.0 VITHKUQI CAPITAL LETTER RE
+1058B ; disallowed # NA <reserved-1058B>
+1058C ; mapped ; 105B3 # 14.0 VITHKUQI CAPITAL LETTER SE
+1058D ; mapped ; 105B4 # 14.0 VITHKUQI CAPITAL LETTER SHE
+1058E ; mapped ; 105B5 # 14.0 VITHKUQI CAPITAL LETTER TE
+1058F ; mapped ; 105B6 # 14.0 VITHKUQI CAPITAL LETTER THE
+10590 ; mapped ; 105B7 # 14.0 VITHKUQI CAPITAL LETTER U
+10591 ; mapped ; 105B8 # 14.0 VITHKUQI CAPITAL LETTER VE
+10592 ; mapped ; 105B9 # 14.0 VITHKUQI CAPITAL LETTER XE
+10593 ; disallowed # NA <reserved-10593>
+10594 ; mapped ; 105BB # 14.0 VITHKUQI CAPITAL LETTER Y
+10595 ; mapped ; 105BC # 14.0 VITHKUQI CAPITAL LETTER ZE
+10596 ; disallowed # NA <reserved-10596>
+10597..105A1 ; valid # 14.0 VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA
+105A2 ; disallowed # NA <reserved-105A2>
+105A3..105B1 ; valid # 14.0 VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE
+105B2 ; disallowed # NA <reserved-105B2>
+105B3..105B9 ; valid # 14.0 VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE
+105BA ; disallowed # NA <reserved-105BA>
+105BB..105BC ; valid # 14.0 VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE
+105BD..105FF ; disallowed # NA <reserved-105BD>..<reserved-105FF>
+10600..10736 ; valid # 7.0 LINEAR A SIGN AB001..LINEAR A SIGN A664
+10737..1073F ; disallowed # NA <reserved-10737>..<reserved-1073F>
+10740..10755 ; valid # 7.0 LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
+10756..1075F ; disallowed # NA <reserved-10756>..<reserved-1075F>
+10760..10767 ; valid # 7.0 LINEAR A SIGN A800..LINEAR A SIGN A807
+10768..1077F ; disallowed # NA <reserved-10768>..<reserved-1077F>
+10780 ; valid # 14.0 MODIFIER LETTER SMALL CAPITAL AA
+10781 ; mapped ; 02D0 # 14.0 MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON
+10782 ; mapped ; 02D1 # 14.0 MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON
+10783 ; mapped ; 00E6 # 14.0 MODIFIER LETTER SMALL AE
+10784 ; mapped ; 0299 # 14.0 MODIFIER LETTER SMALL CAPITAL B
+10785 ; mapped ; 0253 # 14.0 MODIFIER LETTER SMALL B WITH HOOK
+10786 ; disallowed # NA <reserved-10786>
+10787 ; mapped ; 02A3 # 14.0 MODIFIER LETTER SMALL DZ DIGRAPH
+10788 ; mapped ; AB66 # 14.0 MODIFIER LETTER SMALL DZ DIGRAPH WITH RETROFLEX HOOK
+10789 ; mapped ; 02A5 # 14.0 MODIFIER LETTER SMALL DZ DIGRAPH WITH CURL
+1078A ; mapped ; 02A4 # 14.0 MODIFIER LETTER SMALL DEZH DIGRAPH
+1078B ; mapped ; 0256 # 14.0 MODIFIER LETTER SMALL D WITH TAIL
+1078C ; mapped ; 0257 # 14.0 MODIFIER LETTER SMALL D WITH HOOK
+1078D ; mapped ; 1D91 # 14.0 MODIFIER LETTER SMALL D WITH HOOK AND TAIL
+1078E ; mapped ; 0258 # 14.0 MODIFIER LETTER SMALL REVERSED E
+1078F ; mapped ; 025E # 14.0 MODIFIER LETTER SMALL CLOSED REVERSED OPEN E
+10790 ; mapped ; 02A9 # 14.0 MODIFIER LETTER SMALL FENG DIGRAPH
+10791 ; mapped ; 0264 # 14.0 MODIFIER LETTER SMALL RAMS HORN
+10792 ; mapped ; 0262 # 14.0 MODIFIER LETTER SMALL CAPITAL G
+10793 ; mapped ; 0260 # 14.0 MODIFIER LETTER SMALL G WITH HOOK
+10794 ; mapped ; 029B # 14.0 MODIFIER LETTER SMALL CAPITAL G WITH HOOK
+10795 ; mapped ; 0127 # 14.0 MODIFIER LETTER SMALL H WITH STROKE
+10796 ; mapped ; 029C # 14.0 MODIFIER LETTER SMALL CAPITAL H
+10797 ; mapped ; 0267 # 14.0 MODIFIER LETTER SMALL HENG WITH HOOK
+10798 ; mapped ; 0284 # 14.0 MODIFIER LETTER SMALL DOTLESS J WITH STROKE AND HOOK
+10799 ; mapped ; 02AA # 14.0 MODIFIER LETTER SMALL LS DIGRAPH
+1079A ; mapped ; 02AB # 14.0 MODIFIER LETTER SMALL LZ DIGRAPH
+1079B ; mapped ; 026C # 14.0 MODIFIER LETTER SMALL L WITH BELT
+1079C ; mapped ; 1DF04 # 14.0 MODIFIER LETTER SMALL CAPITAL L WITH BELT
+1079D ; mapped ; A78E # 14.0 MODIFIER LETTER SMALL L WITH RETROFLEX HOOK AND BELT
+1079E ; mapped ; 026E # 14.0 MODIFIER LETTER SMALL LEZH
+1079F ; mapped ; 1DF05 # 14.0 MODIFIER LETTER SMALL LEZH WITH RETROFLEX HOOK
+107A0 ; mapped ; 028E # 14.0 MODIFIER LETTER SMALL TURNED Y
+107A1 ; mapped ; 1DF06 # 14.0 MODIFIER LETTER SMALL TURNED Y WITH BELT
+107A2 ; mapped ; 00F8 # 14.0 MODIFIER LETTER SMALL O WITH STROKE
+107A3 ; mapped ; 0276 # 14.0 MODIFIER LETTER SMALL CAPITAL OE
+107A4 ; mapped ; 0277 # 14.0 MODIFIER LETTER SMALL CLOSED OMEGA
+107A5 ; mapped ; 0071 # 14.0 MODIFIER LETTER SMALL Q
+107A6 ; mapped ; 027A # 14.0 MODIFIER LETTER SMALL TURNED R WITH LONG LEG
+107A7 ; mapped ; 1DF08 # 14.0 MODIFIER LETTER SMALL TURNED R WITH LONG LEG AND RETROFLEX HOOK
+107A8 ; mapped ; 027D # 14.0 MODIFIER LETTER SMALL R WITH TAIL
+107A9 ; mapped ; 027E # 14.0 MODIFIER LETTER SMALL R WITH FISHHOOK
+107AA ; mapped ; 0280 # 14.0 MODIFIER LETTER SMALL CAPITAL R
+107AB ; mapped ; 02A8 # 14.0 MODIFIER LETTER SMALL TC DIGRAPH WITH CURL
+107AC ; mapped ; 02A6 # 14.0 MODIFIER LETTER SMALL TS DIGRAPH
+107AD ; mapped ; AB67 # 14.0 MODIFIER LETTER SMALL TS DIGRAPH WITH RETROFLEX HOOK
+107AE ; mapped ; 02A7 # 14.0 MODIFIER LETTER SMALL TESH DIGRAPH
+107AF ; mapped ; 0288 # 14.0 MODIFIER LETTER SMALL T WITH RETROFLEX HOOK
+107B0 ; mapped ; 2C71 # 14.0 MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B1 ; disallowed # NA <reserved-107B1>
+107B2 ; mapped ; 028F # 14.0 MODIFIER LETTER SMALL CAPITAL Y
+107B3 ; mapped ; 02A1 # 14.0 MODIFIER LETTER GLOTTAL STOP WITH STROKE
+107B4 ; mapped ; 02A2 # 14.0 MODIFIER LETTER REVERSED GLOTTAL STOP WITH STROKE
+107B5 ; mapped ; 0298 # 14.0 MODIFIER LETTER BILABIAL CLICK
+107B6 ; mapped ; 01C0 # 14.0 MODIFIER LETTER DENTAL CLICK
+107B7 ; mapped ; 01C1 # 14.0 MODIFIER LETTER LATERAL CLICK
+107B8 ; mapped ; 01C2 # 14.0 MODIFIER LETTER ALVEOLAR CLICK
+107B9 ; mapped ; 1DF0A # 14.0 MODIFIER LETTER RETROFLEX CLICK WITH RETROFLEX HOOK
+107BA ; mapped ; 1DF1E # 14.0 MODIFIER LETTER SMALL S WITH CURL
+107BB..107FF ; disallowed # NA <reserved-107BB>..<reserved-107FF>
+10800..10805 ; valid # 4.0 CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
+10806..10807 ; disallowed # NA <reserved-10806>..<reserved-10807>
+10808 ; valid # 4.0 CYPRIOT SYLLABLE JO
+10809 ; disallowed # NA <reserved-10809>
+1080A..10835 ; valid # 4.0 CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
+10836 ; disallowed # NA <reserved-10836>
+10837..10838 ; valid # 4.0 CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
+10839..1083B ; disallowed # NA <reserved-10839>..<reserved-1083B>
+1083C ; valid # 4.0 CYPRIOT SYLLABLE ZA
+1083D..1083E ; disallowed # NA <reserved-1083D>..<reserved-1083E>
+1083F ; valid # 4.0 CYPRIOT SYLLABLE ZO
+10840..10855 ; valid # 5.2 IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW
+10856 ; disallowed # NA <reserved-10856>
+10857..1085F ; valid ; ; NV8 # 5.2 IMPERIAL ARAMAIC SECTION SIGN..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
+10860..10876 ; valid # 7.0 PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
+10877..1087F ; valid ; ; NV8 # 7.0 PALMYRENE LEFT-POINTING FLEURON..PALMYRENE NUMBER TWENTY
+10880..1089E ; valid # 7.0 NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
+1089F..108A6 ; disallowed # NA <reserved-1089F>..<reserved-108A6>
+108A7..108AF ; valid ; ; NV8 # 7.0 NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
+108B0..108DF ; disallowed # NA <reserved-108B0>..<reserved-108DF>
+108E0..108F2 ; valid # 8.0 HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F3 ; disallowed # NA <reserved-108F3>
+108F4..108F5 ; valid # 8.0 HATRAN LETTER SHIN..HATRAN LETTER TAW
+108F6..108FA ; disallowed # NA <reserved-108F6>..<reserved-108FA>
+108FB..108FF ; valid ; ; NV8 # 8.0 HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+10900..10915 ; valid # 5.0 PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
+10916..10919 ; valid ; ; NV8 # 5.0 PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER ONE HUNDRED
+1091A..1091B ; valid ; ; NV8 # 5.2 PHOENICIAN NUMBER TWO..PHOENICIAN NUMBER THREE
+1091C..1091E ; disallowed # NA <reserved-1091C>..<reserved-1091E>
+1091F ; valid ; ; NV8 # 5.0 PHOENICIAN WORD SEPARATOR
+10920..10939 ; valid # 5.1 LYDIAN LETTER A..LYDIAN LETTER C
+1093A..1093E ; disallowed # NA <reserved-1093A>..<reserved-1093E>
+1093F ; valid ; ; NV8 # 5.1 LYDIAN TRIANGULAR MARK
+10940..1097F ; disallowed # NA <reserved-10940>..<reserved-1097F>
+10980..109B7 ; valid # 6.1 MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA
+109B8..109BB ; disallowed # NA <reserved-109B8>..<reserved-109BB>
+109BC..109BD ; valid ; ; NV8 # 8.0 MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
+109BE..109BF ; valid # 6.1 MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
+109C0..109CF ; valid ; ; NV8 # 8.0 MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D0..109D1 ; disallowed # NA <reserved-109D0>..<reserved-109D1>
+109D2..109FF ; valid ; ; NV8 # 8.0 MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+10A00..10A03 ; valid # 4.1 KHAROSHTHI LETTER A..KHAROSHTHI VOWEL SIGN VOCALIC R
+10A04 ; disallowed # NA <reserved-10A04>
+10A05..10A06 ; valid # 4.1 KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
+10A07..10A0B ; disallowed # NA <reserved-10A07>..<reserved-10A0B>
+10A0C..10A13 ; valid # 4.1 KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI LETTER GHA
+10A14 ; disallowed # NA <reserved-10A14>
+10A15..10A17 ; valid # 4.1 KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
+10A18 ; disallowed # NA <reserved-10A18>
+10A19..10A33 ; valid # 4.1 KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER TTTHA
+10A34..10A35 ; valid # 11.0 KHAROSHTHI LETTER TTTA..KHAROSHTHI LETTER VHA
+10A36..10A37 ; disallowed # NA <reserved-10A36>..<reserved-10A37>
+10A38..10A3A ; valid # 4.1 KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
+10A3B..10A3E ; disallowed # NA <reserved-10A3B>..<reserved-10A3E>
+10A3F ; valid # 4.1 KHAROSHTHI VIRAMA
+10A40..10A47 ; valid ; ; NV8 # 4.1 KHAROSHTHI DIGIT ONE..KHAROSHTHI NUMBER ONE THOUSAND
+10A48 ; valid ; ; NV8 # 11.0 KHAROSHTHI FRACTION ONE HALF
+10A49..10A4F ; disallowed # NA <reserved-10A49>..<reserved-10A4F>
+10A50..10A58 ; valid ; ; NV8 # 4.1 KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
+10A59..10A5F ; disallowed # NA <reserved-10A59>..<reserved-10A5F>
+10A60..10A7C ; valid # 5.2 OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
+10A7D..10A7F ; valid ; ; NV8 # 5.2 OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMERIC INDICATOR
+10A80..10A9C ; valid # 7.0 OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
+10A9D..10A9F ; valid ; ; NV8 # 7.0 OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
+10AA0..10ABF ; disallowed # NA <reserved-10AA0>..<reserved-10ABF>
+10AC0..10AC7 ; valid # 7.0 MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
+10AC8 ; valid ; ; NV8 # 7.0 MANICHAEAN SIGN UD
+10AC9..10AE6 ; valid # 7.0 MANICHAEAN LETTER ZAYIN..MANICHAEAN ABBREVIATION MARK BELOW
+10AE7..10AEA ; disallowed # NA <reserved-10AE7>..<reserved-10AEA>
+10AEB..10AF6 ; valid ; ; NV8 # 7.0 MANICHAEAN NUMBER ONE..MANICHAEAN PUNCTUATION LINE FILLER
+10AF7..10AFF ; disallowed # NA <reserved-10AF7>..<reserved-10AFF>
+10B00..10B35 ; valid # 5.2 AVESTAN LETTER A..AVESTAN LETTER HE
+10B36..10B38 ; disallowed # NA <reserved-10B36>..<reserved-10B38>
+10B39..10B3F ; valid ; ; NV8 # 5.2 AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
+10B40..10B55 ; valid # 5.2 INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
+10B56..10B57 ; disallowed # NA <reserved-10B56>..<reserved-10B57>
+10B58..10B5F ; valid ; ; NV8 # 5.2 INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
+10B60..10B72 ; valid # 5.2 INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
+10B73..10B77 ; disallowed # NA <reserved-10B73>..<reserved-10B77>
+10B78..10B7F ; valid ; ; NV8 # 5.2 INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
+10B80..10B91 ; valid # 7.0 PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
+10B92..10B98 ; disallowed # NA <reserved-10B92>..<reserved-10B98>
+10B99..10B9C ; valid ; ; NV8 # 7.0 PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
+10B9D..10BA8 ; disallowed # NA <reserved-10B9D>..<reserved-10BA8>
+10BA9..10BAF ; valid ; ; NV8 # 7.0 PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
+10BB0..10BFF ; disallowed # NA <reserved-10BB0>..<reserved-10BFF>
+10C00..10C48 ; valid # 5.2 OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
+10C49..10C7F ; disallowed # NA <reserved-10C49>..<reserved-10C7F>
+10C80 ; mapped ; 10CC0 # 8.0 OLD HUNGARIAN CAPITAL LETTER A
+10C81 ; mapped ; 10CC1 # 8.0 OLD HUNGARIAN CAPITAL LETTER AA
+10C82 ; mapped ; 10CC2 # 8.0 OLD HUNGARIAN CAPITAL LETTER EB
+10C83 ; mapped ; 10CC3 # 8.0 OLD HUNGARIAN CAPITAL LETTER AMB
+10C84 ; mapped ; 10CC4 # 8.0 OLD HUNGARIAN CAPITAL LETTER EC
+10C85 ; mapped ; 10CC5 # 8.0 OLD HUNGARIAN CAPITAL LETTER ENC
+10C86 ; mapped ; 10CC6 # 8.0 OLD HUNGARIAN CAPITAL LETTER ECS
+10C87 ; mapped ; 10CC7 # 8.0 OLD HUNGARIAN CAPITAL LETTER ED
+10C88 ; mapped ; 10CC8 # 8.0 OLD HUNGARIAN CAPITAL LETTER AND
+10C89 ; mapped ; 10CC9 # 8.0 OLD HUNGARIAN CAPITAL LETTER E
+10C8A ; mapped ; 10CCA # 8.0 OLD HUNGARIAN CAPITAL LETTER CLOSE E
+10C8B ; mapped ; 10CCB # 8.0 OLD HUNGARIAN CAPITAL LETTER EE
+10C8C ; mapped ; 10CCC # 8.0 OLD HUNGARIAN CAPITAL LETTER EF
+10C8D ; mapped ; 10CCD # 8.0 OLD HUNGARIAN CAPITAL LETTER EG
+10C8E ; mapped ; 10CCE # 8.0 OLD HUNGARIAN CAPITAL LETTER EGY
+10C8F ; mapped ; 10CCF # 8.0 OLD HUNGARIAN CAPITAL LETTER EH
+10C90 ; mapped ; 10CD0 # 8.0 OLD HUNGARIAN CAPITAL LETTER I
+10C91 ; mapped ; 10CD1 # 8.0 OLD HUNGARIAN CAPITAL LETTER II
+10C92 ; mapped ; 10CD2 # 8.0 OLD HUNGARIAN CAPITAL LETTER EJ
+10C93 ; mapped ; 10CD3 # 8.0 OLD HUNGARIAN CAPITAL LETTER EK
+10C94 ; mapped ; 10CD4 # 8.0 OLD HUNGARIAN CAPITAL LETTER AK
+10C95 ; mapped ; 10CD5 # 8.0 OLD HUNGARIAN CAPITAL LETTER UNK
+10C96 ; mapped ; 10CD6 # 8.0 OLD HUNGARIAN CAPITAL LETTER EL
+10C97 ; mapped ; 10CD7 # 8.0 OLD HUNGARIAN CAPITAL LETTER ELY
+10C98 ; mapped ; 10CD8 # 8.0 OLD HUNGARIAN CAPITAL LETTER EM
+10C99 ; mapped ; 10CD9 # 8.0 OLD HUNGARIAN CAPITAL LETTER EN
+10C9A ; mapped ; 10CDA # 8.0 OLD HUNGARIAN CAPITAL LETTER ENY
+10C9B ; mapped ; 10CDB # 8.0 OLD HUNGARIAN CAPITAL LETTER O
+10C9C ; mapped ; 10CDC # 8.0 OLD HUNGARIAN CAPITAL LETTER OO
+10C9D ; mapped ; 10CDD # 8.0 OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE
+10C9E ; mapped ; 10CDE # 8.0 OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE
+10C9F ; mapped ; 10CDF # 8.0 OLD HUNGARIAN CAPITAL LETTER OEE
+10CA0 ; mapped ; 10CE0 # 8.0 OLD HUNGARIAN CAPITAL LETTER EP
+10CA1 ; mapped ; 10CE1 # 8.0 OLD HUNGARIAN CAPITAL LETTER EMP
+10CA2 ; mapped ; 10CE2 # 8.0 OLD HUNGARIAN CAPITAL LETTER ER
+10CA3 ; mapped ; 10CE3 # 8.0 OLD HUNGARIAN CAPITAL LETTER SHORT ER
+10CA4 ; mapped ; 10CE4 # 8.0 OLD HUNGARIAN CAPITAL LETTER ES
+10CA5 ; mapped ; 10CE5 # 8.0 OLD HUNGARIAN CAPITAL LETTER ESZ
+10CA6 ; mapped ; 10CE6 # 8.0 OLD HUNGARIAN CAPITAL LETTER ET
+10CA7 ; mapped ; 10CE7 # 8.0 OLD HUNGARIAN CAPITAL LETTER ENT
+10CA8 ; mapped ; 10CE8 # 8.0 OLD HUNGARIAN CAPITAL LETTER ETY
+10CA9 ; mapped ; 10CE9 # 8.0 OLD HUNGARIAN CAPITAL LETTER ECH
+10CAA ; mapped ; 10CEA # 8.0 OLD HUNGARIAN CAPITAL LETTER U
+10CAB ; mapped ; 10CEB # 8.0 OLD HUNGARIAN CAPITAL LETTER UU
+10CAC ; mapped ; 10CEC # 8.0 OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE
+10CAD ; mapped ; 10CED # 8.0 OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE
+10CAE ; mapped ; 10CEE # 8.0 OLD HUNGARIAN CAPITAL LETTER EV
+10CAF ; mapped ; 10CEF # 8.0 OLD HUNGARIAN CAPITAL LETTER EZ
+10CB0 ; mapped ; 10CF0 # 8.0 OLD HUNGARIAN CAPITAL LETTER EZS
+10CB1 ; mapped ; 10CF1 # 8.0 OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN
+10CB2 ; mapped ; 10CF2 # 8.0 OLD HUNGARIAN CAPITAL LETTER US
+10CB3..10CBF ; disallowed # NA <reserved-10CB3>..<reserved-10CBF>
+10CC0..10CF2 ; valid # 8.0 OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CF3..10CF9 ; disallowed # NA <reserved-10CF3>..<reserved-10CF9>
+10CFA..10CFF ; valid ; ; NV8 # 8.0 OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+10D00..10D27 ; valid # 11.0 HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA SIGN TASSI
+10D28..10D2F ; disallowed # NA <reserved-10D28>..<reserved-10D2F>
+10D30..10D39 ; valid # 11.0 HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
+10D3A..10E5F ; disallowed # NA <reserved-10D3A>..<reserved-10E5F>
+10E60..10E7E ; valid ; ; NV8 # 5.2 RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
+10E7F ; disallowed # NA <reserved-10E7F>
+10E80..10EA9 ; valid # 13.0 YEZIDI LETTER ELIF..YEZIDI LETTER ET
+10EAA ; disallowed # NA <reserved-10EAA>
+10EAB..10EAC ; valid # 13.0 YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
+10EAD ; valid ; ; NV8 # 13.0 YEZIDI HYPHENATION MARK
+10EAE..10EAF ; disallowed # NA <reserved-10EAE>..<reserved-10EAF>
+10EB0..10EB1 ; valid # 13.0 YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
+10EB2..10EFF ; disallowed # NA <reserved-10EB2>..<reserved-10EFF>
+10F00..10F1C ; valid # 11.0 OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
+10F1D..10F26 ; valid ; ; NV8 # 11.0 OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
+10F27 ; valid # 11.0 OLD SOGDIAN LIGATURE AYIN-DALETH
+10F28..10F2F ; disallowed # NA <reserved-10F28>..<reserved-10F2F>
+10F30..10F50 ; valid # 11.0 SOGDIAN LETTER ALEPH..SOGDIAN COMBINING STROKE BELOW
+10F51..10F59 ; valid ; ; NV8 # 11.0 SOGDIAN NUMBER ONE..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+10F5A..10F6F ; disallowed # NA <reserved-10F5A>..<reserved-10F6F>
+10F70..10F85 ; valid # 14.0 OLD UYGHUR LETTER ALEPH..OLD UYGHUR COMBINING TWO DOTS BELOW
+10F86..10F89 ; valid ; ; NV8 # 14.0 OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
+10F8A..10FAF ; disallowed # NA <reserved-10F8A>..<reserved-10FAF>
+10FB0..10FC4 ; valid # 13.0 CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW
+10FC5..10FCB ; valid ; ; NV8 # 13.0 CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED
+10FCC..10FDF ; disallowed # NA <reserved-10FCC>..<reserved-10FDF>
+10FE0..10FF6 ; valid # 12.0 ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH
+10FF7..10FFF ; disallowed # NA <reserved-10FF7>..<reserved-10FFF>
+11000..11046 ; valid # 6.0 BRAHMI SIGN CANDRABINDU..BRAHMI VIRAMA
+11047..1104D ; valid ; ; NV8 # 6.0 BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
+1104E..11051 ; disallowed # NA <reserved-1104E>..<reserved-11051>
+11052..11065 ; valid ; ; NV8 # 6.0 BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
+11066..1106F ; valid # 6.0 BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
+11070..11075 ; valid # 14.0 BRAHMI SIGN OLD TAMIL VIRAMA..BRAHMI LETTER OLD TAMIL LLA
+11076..1107E ; disallowed # NA <reserved-11076>..<reserved-1107E>
+1107F ; valid # 7.0 BRAHMI NUMBER JOINER
+11080..110BA ; valid # 5.2 KAITHI SIGN CANDRABINDU..KAITHI SIGN NUKTA
+110BB..110BC ; valid ; ; NV8 # 5.2 KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN
+110BD ; disallowed # 5.2 KAITHI NUMBER SIGN
+110BE..110C1 ; valid ; ; NV8 # 5.2 KAITHI SECTION MARK..KAITHI DOUBLE DANDA
+110C2 ; valid # 14.0 KAITHI VOWEL SIGN VOCALIC R
+110C3..110CC ; disallowed # NA <reserved-110C3>..<reserved-110CC>
+110CD ; disallowed # 11.0 KAITHI NUMBER SIGN ABOVE
+110CE..110CF ; disallowed # NA <reserved-110CE>..<reserved-110CF>
+110D0..110E8 ; valid # 6.1 SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
+110E9..110EF ; disallowed # NA <reserved-110E9>..<reserved-110EF>
+110F0..110F9 ; valid # 6.1 SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
+110FA..110FF ; disallowed # NA <reserved-110FA>..<reserved-110FF>
+11100..11134 ; valid # 6.1 CHAKMA SIGN CANDRABINDU..CHAKMA MAAYYAA
+11135 ; disallowed # NA <reserved-11135>
+11136..1113F ; valid # 6.1 CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
+11140..11143 ; valid ; ; NV8 # 6.1 CHAKMA SECTION MARK..CHAKMA QUESTION MARK
+11144..11146 ; valid # 11.0 CHAKMA LETTER LHAA..CHAKMA VOWEL SIGN EI
+11147 ; valid # 13.0 CHAKMA LETTER VAA
+11148..1114F ; disallowed # NA <reserved-11148>..<reserved-1114F>
+11150..11173 ; valid # 7.0 MAHAJANI LETTER A..MAHAJANI SIGN NUKTA
+11174..11175 ; valid ; ; NV8 # 7.0 MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
+11176 ; valid # 7.0 MAHAJANI LIGATURE SHRI
+11177..1117F ; disallowed # NA <reserved-11177>..<reserved-1117F>
+11180..111C4 ; valid # 6.1 SHARADA SIGN CANDRABINDU..SHARADA OM
+111C5..111C8 ; valid ; ; NV8 # 6.1 SHARADA DANDA..SHARADA SEPARATOR
+111C9..111CC ; valid # 8.0 SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
+111CD ; valid ; ; NV8 # 7.0 SHARADA SUTRA MARK
+111CE..111CF ; valid # 13.0 SHARADA VOWEL SIGN PRISHTHAMATRA E..SHARADA SIGN INVERTED CANDRABINDU
+111D0..111D9 ; valid # 6.1 SHARADA DIGIT ZERO..SHARADA DIGIT NINE
+111DA ; valid # 7.0 SHARADA EKAM
+111DB ; valid ; ; NV8 # 8.0 SHARADA SIGN SIDDHAM
+111DC ; valid # 8.0 SHARADA HEADSTROKE
+111DD..111DF ; valid ; ; NV8 # 8.0 SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+111E0 ; disallowed # NA <reserved-111E0>
+111E1..111F4 ; valid ; ; NV8 # 7.0 SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
+111F5..111FF ; disallowed # NA <reserved-111F5>..<reserved-111FF>
+11200..11211 ; valid # 7.0 KHOJKI LETTER A..KHOJKI LETTER JJA
+11212 ; disallowed # NA <reserved-11212>
+11213..11237 ; valid # 7.0 KHOJKI LETTER NYA..KHOJKI SIGN SHADDA
+11238..1123D ; valid ; ; NV8 # 7.0 KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
+1123E ; valid # 9.0 KHOJKI SIGN SUKUN
+1123F..1127F ; disallowed # NA <reserved-1123F>..<reserved-1127F>
+11280..11286 ; valid # 8.0 MULTANI LETTER A..MULTANI LETTER GA
+11287 ; disallowed # NA <reserved-11287>
+11288 ; valid # 8.0 MULTANI LETTER GHA
+11289 ; disallowed # NA <reserved-11289>
+1128A..1128D ; valid # 8.0 MULTANI LETTER CA..MULTANI LETTER JJA
+1128E ; disallowed # NA <reserved-1128E>
+1128F..1129D ; valid # 8.0 MULTANI LETTER NYA..MULTANI LETTER BA
+1129E ; disallowed # NA <reserved-1129E>
+1129F..112A8 ; valid # 8.0 MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9 ; valid ; ; NV8 # 8.0 MULTANI SECTION MARK
+112AA..112AF ; disallowed # NA <reserved-112AA>..<reserved-112AF>
+112B0..112EA ; valid # 7.0 KHUDAWADI LETTER A..KHUDAWADI SIGN VIRAMA
+112EB..112EF ; disallowed # NA <reserved-112EB>..<reserved-112EF>
+112F0..112F9 ; valid # 7.0 KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
+112FA..112FF ; disallowed # NA <reserved-112FA>..<reserved-112FF>
+11300 ; valid # 8.0 GRANTHA SIGN COMBINING ANUSVARA ABOVE
+11301..11303 ; valid # 7.0 GRANTHA SIGN CANDRABINDU..GRANTHA SIGN VISARGA
+11304 ; disallowed # NA <reserved-11304>
+11305..1130C ; valid # 7.0 GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
+1130D..1130E ; disallowed # NA <reserved-1130D>..<reserved-1130E>
+1130F..11310 ; valid # 7.0 GRANTHA LETTER EE..GRANTHA LETTER AI
+11311..11312 ; disallowed # NA <reserved-11311>..<reserved-11312>
+11313..11328 ; valid # 7.0 GRANTHA LETTER OO..GRANTHA LETTER NA
+11329 ; disallowed # NA <reserved-11329>
+1132A..11330 ; valid # 7.0 GRANTHA LETTER PA..GRANTHA LETTER RA
+11331 ; disallowed # NA <reserved-11331>
+11332..11333 ; valid # 7.0 GRANTHA LETTER LA..GRANTHA LETTER LLA
+11334 ; disallowed # NA <reserved-11334>
+11335..11339 ; valid # 7.0 GRANTHA LETTER VA..GRANTHA LETTER HA
+1133A ; disallowed # NA <reserved-1133A>
+1133B ; valid # 11.0 COMBINING BINDU BELOW
+1133C..11344 ; valid # 7.0 GRANTHA SIGN NUKTA..GRANTHA VOWEL SIGN VOCALIC RR
+11345..11346 ; disallowed # NA <reserved-11345>..<reserved-11346>
+11347..11348 ; valid # 7.0 GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
+11349..1134A ; disallowed # NA <reserved-11349>..<reserved-1134A>
+1134B..1134D ; valid # 7.0 GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+1134E..1134F ; disallowed # NA <reserved-1134E>..<reserved-1134F>
+11350 ; valid # 8.0 GRANTHA OM
+11351..11356 ; disallowed # NA <reserved-11351>..<reserved-11356>
+11357 ; valid # 7.0 GRANTHA AU LENGTH MARK
+11358..1135C ; disallowed # NA <reserved-11358>..<reserved-1135C>
+1135D..11363 ; valid # 7.0 GRANTHA SIGN PLUTA..GRANTHA VOWEL SIGN VOCALIC LL
+11364..11365 ; disallowed # NA <reserved-11364>..<reserved-11365>
+11366..1136C ; valid # 7.0 COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
+1136D..1136F ; disallowed # NA <reserved-1136D>..<reserved-1136F>
+11370..11374 ; valid # 7.0 COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
+11375..113FF ; disallowed # NA <reserved-11375>..<reserved-113FF>
+11400..1144A ; valid # 9.0 NEWA LETTER A..NEWA SIDDHI
+1144B..1144F ; valid ; ; NV8 # 9.0 NEWA DANDA..NEWA ABBREVIATION SIGN
+11450..11459 ; valid # 9.0 NEWA DIGIT ZERO..NEWA DIGIT NINE
+1145A ; valid ; ; NV8 # 13.0 NEWA DOUBLE COMMA
+1145B ; valid ; ; NV8 # 9.0 NEWA PLACEHOLDER MARK
+1145C ; disallowed # NA <reserved-1145C>
+1145D ; valid ; ; NV8 # 9.0 NEWA INSERTION SIGN
+1145E ; valid # 11.0 NEWA SANDHI MARK
+1145F ; valid # 12.0 NEWA LETTER VEDIC ANUSVARA
+11460..11461 ; valid # 13.0 NEWA SIGN JIHVAMULIYA..NEWA SIGN UPADHMANIYA
+11462..1147F ; disallowed # NA <reserved-11462>..<reserved-1147F>
+11480..114C5 ; valid # 7.0 TIRHUTA ANJI..TIRHUTA GVANG
+114C6 ; valid ; ; NV8 # 7.0 TIRHUTA ABBREVIATION SIGN
+114C7 ; valid # 7.0 TIRHUTA OM
+114C8..114CF ; disallowed # NA <reserved-114C8>..<reserved-114CF>
+114D0..114D9 ; valid # 7.0 TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
+114DA..1157F ; disallowed # NA <reserved-114DA>..<reserved-1157F>
+11580..115B5 ; valid # 7.0 SIDDHAM LETTER A..SIDDHAM VOWEL SIGN VOCALIC RR
+115B6..115B7 ; disallowed # NA <reserved-115B6>..<reserved-115B7>
+115B8..115C0 ; valid # 7.0 SIDDHAM VOWEL SIGN E..SIDDHAM SIGN NUKTA
+115C1..115C9 ; valid ; ; NV8 # 7.0 SIDDHAM SIGN SIDDHAM..SIDDHAM END OF TEXT MARK
+115CA..115D7 ; valid ; ; NV8 # 8.0 SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8..115DD ; valid # 8.0 SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM VOWEL SIGN ALTERNATE UU
+115DE..115FF ; disallowed # NA <reserved-115DE>..<reserved-115FF>
+11600..11640 ; valid # 7.0 MODI LETTER A..MODI SIGN ARDHACANDRA
+11641..11643 ; valid ; ; NV8 # 7.0 MODI DANDA..MODI ABBREVIATION SIGN
+11644 ; valid # 7.0 MODI SIGN HUVA
+11645..1164F ; disallowed # NA <reserved-11645>..<reserved-1164F>
+11650..11659 ; valid # 7.0 MODI DIGIT ZERO..MODI DIGIT NINE
+1165A..1165F ; disallowed # NA <reserved-1165A>..<reserved-1165F>
+11660..1166C ; valid ; ; NV8 # 9.0 MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
+1166D..1167F ; disallowed # NA <reserved-1166D>..<reserved-1167F>
+11680..116B7 ; valid # 6.1 TAKRI LETTER A..TAKRI SIGN NUKTA
+116B8 ; valid # 12.0 TAKRI LETTER ARCHAIC KHA
+116B9 ; valid ; ; NV8 # 14.0 TAKRI ABBREVIATION SIGN
+116BA..116BF ; disallowed # NA <reserved-116BA>..<reserved-116BF>
+116C0..116C9 ; valid # 6.1 TAKRI DIGIT ZERO..TAKRI DIGIT NINE
+116CA..116FF ; disallowed # NA <reserved-116CA>..<reserved-116FF>
+11700..11719 ; valid # 8.0 AHOM LETTER KA..AHOM LETTER JHA
+1171A ; valid # 11.0 AHOM LETTER ALTERNATE BA
+1171B..1171C ; disallowed # NA <reserved-1171B>..<reserved-1171C>
+1171D..1172B ; valid # 8.0 AHOM CONSONANT SIGN MEDIAL LA..AHOM SIGN KILLER
+1172C..1172F ; disallowed # NA <reserved-1172C>..<reserved-1172F>
+11730..11739 ; valid # 8.0 AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A..1173F ; valid ; ; NV8 # 8.0 AHOM NUMBER TEN..AHOM SYMBOL VI
+11740..11746 ; valid # 14.0 AHOM LETTER CA..AHOM LETTER LLA
+11747..117FF ; disallowed # NA <reserved-11747>..<reserved-117FF>
+11800..1183A ; valid # 11.0 DOGRA LETTER A..DOGRA SIGN NUKTA
+1183B ; valid ; ; NV8 # 11.0 DOGRA ABBREVIATION SIGN
+1183C..1189F ; disallowed # NA <reserved-1183C>..<reserved-1189F>
+118A0 ; mapped ; 118C0 # 7.0 WARANG CITI CAPITAL LETTER NGAA
+118A1 ; mapped ; 118C1 # 7.0 WARANG CITI CAPITAL LETTER A
+118A2 ; mapped ; 118C2 # 7.0 WARANG CITI CAPITAL LETTER WI
+118A3 ; mapped ; 118C3 # 7.0 WARANG CITI CAPITAL LETTER YU
+118A4 ; mapped ; 118C4 # 7.0 WARANG CITI CAPITAL LETTER YA
+118A5 ; mapped ; 118C5 # 7.0 WARANG CITI CAPITAL LETTER YO
+118A6 ; mapped ; 118C6 # 7.0 WARANG CITI CAPITAL LETTER II
+118A7 ; mapped ; 118C7 # 7.0 WARANG CITI CAPITAL LETTER UU
+118A8 ; mapped ; 118C8 # 7.0 WARANG CITI CAPITAL LETTER E
+118A9 ; mapped ; 118C9 # 7.0 WARANG CITI CAPITAL LETTER O
+118AA ; mapped ; 118CA # 7.0 WARANG CITI CAPITAL LETTER ANG
+118AB ; mapped ; 118CB # 7.0 WARANG CITI CAPITAL LETTER GA
+118AC ; mapped ; 118CC # 7.0 WARANG CITI CAPITAL LETTER KO
+118AD ; mapped ; 118CD # 7.0 WARANG CITI CAPITAL LETTER ENY
+118AE ; mapped ; 118CE # 7.0 WARANG CITI CAPITAL LETTER YUJ
+118AF ; mapped ; 118CF # 7.0 WARANG CITI CAPITAL LETTER UC
+118B0 ; mapped ; 118D0 # 7.0 WARANG CITI CAPITAL LETTER ENN
+118B1 ; mapped ; 118D1 # 7.0 WARANG CITI CAPITAL LETTER ODD
+118B2 ; mapped ; 118D2 # 7.0 WARANG CITI CAPITAL LETTER TTE
+118B3 ; mapped ; 118D3 # 7.0 WARANG CITI CAPITAL LETTER NUNG
+118B4 ; mapped ; 118D4 # 7.0 WARANG CITI CAPITAL LETTER DA
+118B5 ; mapped ; 118D5 # 7.0 WARANG CITI CAPITAL LETTER AT
+118B6 ; mapped ; 118D6 # 7.0 WARANG CITI CAPITAL LETTER AM
+118B7 ; mapped ; 118D7 # 7.0 WARANG CITI CAPITAL LETTER BU
+118B8 ; mapped ; 118D8 # 7.0 WARANG CITI CAPITAL LETTER PU
+118B9 ; mapped ; 118D9 # 7.0 WARANG CITI CAPITAL LETTER HIYO
+118BA ; mapped ; 118DA # 7.0 WARANG CITI CAPITAL LETTER HOLO
+118BB ; mapped ; 118DB # 7.0 WARANG CITI CAPITAL LETTER HORR
+118BC ; mapped ; 118DC # 7.0 WARANG CITI CAPITAL LETTER HAR
+118BD ; mapped ; 118DD # 7.0 WARANG CITI CAPITAL LETTER SSUU
+118BE ; mapped ; 118DE # 7.0 WARANG CITI CAPITAL LETTER SII
+118BF ; mapped ; 118DF # 7.0 WARANG CITI CAPITAL LETTER VIYO
+118C0..118E9 ; valid # 7.0 WARANG CITI SMALL LETTER NGAA..WARANG CITI DIGIT NINE
+118EA..118F2 ; valid ; ; NV8 # 7.0 WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
+118F3..118FE ; disallowed # NA <reserved-118F3>..<reserved-118FE>
+118FF ; valid # 7.0 WARANG CITI OM
+11900..11906 ; valid # 13.0 DIVES AKURU LETTER A..DIVES AKURU LETTER E
+11907..11908 ; disallowed # NA <reserved-11907>..<reserved-11908>
+11909 ; valid # 13.0 DIVES AKURU LETTER O
+1190A..1190B ; disallowed # NA <reserved-1190A>..<reserved-1190B>
+1190C..11913 ; valid # 13.0 DIVES AKURU LETTER KA..DIVES AKURU LETTER JA
+11914 ; disallowed # NA <reserved-11914>
+11915..11916 ; valid # 13.0 DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA
+11917 ; disallowed # NA <reserved-11917>
+11918..11935 ; valid # 13.0 DIVES AKURU LETTER DDA..DIVES AKURU VOWEL SIGN E
+11936 ; disallowed # NA <reserved-11936>
+11937..11938 ; valid # 13.0 DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
+11939..1193A ; disallowed # NA <reserved-11939>..<reserved-1193A>
+1193B..11943 ; valid # 13.0 DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN NUKTA
+11944..11946 ; valid ; ; NV8 # 13.0 DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK
+11947..1194F ; disallowed # NA <reserved-11947>..<reserved-1194F>
+11950..11959 ; valid # 13.0 DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE
+1195A..1199F ; disallowed # NA <reserved-1195A>..<reserved-1199F>
+119A0..119A7 ; valid # 12.0 NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR
+119A8..119A9 ; disallowed # NA <reserved-119A8>..<reserved-119A9>
+119AA..119D7 ; valid # 12.0 NANDINAGARI LETTER E..NANDINAGARI VOWEL SIGN VOCALIC RR
+119D8..119D9 ; disallowed # NA <reserved-119D8>..<reserved-119D9>
+119DA..119E1 ; valid # 12.0 NANDINAGARI VOWEL SIGN E..NANDINAGARI SIGN AVAGRAHA
+119E2 ; valid ; ; NV8 # 12.0 NANDINAGARI SIGN SIDDHAM
+119E3..119E4 ; valid # 12.0 NANDINAGARI HEADSTROKE..NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
+119E5..119FF ; disallowed # NA <reserved-119E5>..<reserved-119FF>
+11A00..11A3E ; valid # 10.0 ZANABAZAR SQUARE LETTER A..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A3F..11A46 ; valid ; ; NV8 # 10.0 ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
+11A47 ; valid # 10.0 ZANABAZAR SQUARE SUBJOINER
+11A48..11A4F ; disallowed # NA <reserved-11A48>..<reserved-11A4F>
+11A50..11A83 ; valid # 10.0 SOYOMBO LETTER A..SOYOMBO LETTER KSSA
+11A84..11A85 ; valid # 12.0 SOYOMBO SIGN JIHVAMULIYA..SOYOMBO SIGN UPADHMANIYA
+11A86..11A99 ; valid # 10.0 SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO SUBJOINER
+11A9A..11A9C ; valid ; ; NV8 # 10.0 SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
+11A9D ; valid # 11.0 SOYOMBO MARK PLUTA
+11A9E..11AA2 ; valid ; ; NV8 # 10.0 SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
+11AA3..11AAF ; disallowed # NA <reserved-11AA3>..<reserved-11AAF>
+11AB0..11ABF ; valid # 14.0 CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA
+11AC0..11AF8 ; valid # 7.0 PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
+11AF9..11BFF ; disallowed # NA <reserved-11AF9>..<reserved-11BFF>
+11C00..11C08 ; valid # 9.0 BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
+11C09 ; disallowed # NA <reserved-11C09>
+11C0A..11C36 ; valid # 9.0 BHAIKSUKI LETTER E..BHAIKSUKI VOWEL SIGN VOCALIC L
+11C37 ; disallowed # NA <reserved-11C37>
+11C38..11C40 ; valid # 9.0 BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN AVAGRAHA
+11C41..11C45 ; valid ; ; NV8 # 9.0 BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
+11C46..11C4F ; disallowed # NA <reserved-11C46>..<reserved-11C4F>
+11C50..11C59 ; valid # 9.0 BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
+11C5A..11C6C ; valid ; ; NV8 # 9.0 BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
+11C6D..11C6F ; disallowed # NA <reserved-11C6D>..<reserved-11C6F>
+11C70..11C71 ; valid ; ; NV8 # 9.0 MARCHEN HEAD MARK..MARCHEN MARK SHAD
+11C72..11C8F ; valid # 9.0 MARCHEN LETTER KA..MARCHEN LETTER A
+11C90..11C91 ; disallowed # NA <reserved-11C90>..<reserved-11C91>
+11C92..11CA7 ; valid # 9.0 MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
+11CA8 ; disallowed # NA <reserved-11CA8>
+11CA9..11CB6 ; valid # 9.0 MARCHEN SUBJOINED LETTER YA..MARCHEN SIGN CANDRABINDU
+11CB7..11CFF ; disallowed # NA <reserved-11CB7>..<reserved-11CFF>
+11D00..11D06 ; valid # 10.0 MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
+11D07 ; disallowed # NA <reserved-11D07>
+11D08..11D09 ; valid # 10.0 MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
+11D0A ; disallowed # NA <reserved-11D0A>
+11D0B..11D36 ; valid # 10.0 MASARAM GONDI LETTER AU..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D37..11D39 ; disallowed # NA <reserved-11D37>..<reserved-11D39>
+11D3A ; valid # 10.0 MASARAM GONDI VOWEL SIGN E
+11D3B ; disallowed # NA <reserved-11D3B>
+11D3C..11D3D ; valid # 10.0 MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3E ; disallowed # NA <reserved-11D3E>
+11D3F..11D47 ; valid # 10.0 MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI RA-KARA
+11D48..11D4F ; disallowed # NA <reserved-11D48>..<reserved-11D4F>
+11D50..11D59 ; valid # 10.0 MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
+11D5A..11D5F ; disallowed # NA <reserved-11D5A>..<reserved-11D5F>
+11D60..11D65 ; valid # 11.0 GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
+11D66 ; disallowed # NA <reserved-11D66>
+11D67..11D68 ; valid # 11.0 GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
+11D69 ; disallowed # NA <reserved-11D69>
+11D6A..11D8E ; valid # 11.0 GUNJALA GONDI LETTER OO..GUNJALA GONDI VOWEL SIGN UU
+11D8F ; disallowed # NA <reserved-11D8F>
+11D90..11D91 ; valid # 11.0 GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
+11D92 ; disallowed # NA <reserved-11D92>
+11D93..11D98 ; valid # 11.0 GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI OM
+11D99..11D9F ; disallowed # NA <reserved-11D99>..<reserved-11D9F>
+11DA0..11DA9 ; valid # 11.0 GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
+11DAA..11EDF ; disallowed # NA <reserved-11DAA>..<reserved-11EDF>
+11EE0..11EF6 ; valid # 11.0 MAKASAR LETTER KA..MAKASAR VOWEL SIGN O
+11EF7..11EF8 ; valid ; ; NV8 # 11.0 MAKASAR PASSIMBANG..MAKASAR END OF SECTION
+11EF9..11FAF ; disallowed # NA <reserved-11EF9>..<reserved-11FAF>
+11FB0 ; valid # 13.0 LISU LETTER YHA
+11FB1..11FBF ; disallowed # NA <reserved-11FB1>..<reserved-11FBF>
+11FC0..11FF1 ; valid ; ; NV8 # 12.0 TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL SIGN VAKAIYARAA
+11FF2..11FFE ; disallowed # NA <reserved-11FF2>..<reserved-11FFE>
+11FFF ; valid ; ; NV8 # 12.0 TAMIL PUNCTUATION END OF TEXT
+12000..1236E ; valid # 5.0 CUNEIFORM SIGN A..CUNEIFORM SIGN ZUM
+1236F..12398 ; valid # 7.0 CUNEIFORM SIGN KAP ELAMITE..CUNEIFORM SIGN UM TIMES ME
+12399 ; valid # 8.0 CUNEIFORM SIGN U U
+1239A..123FF ; disallowed # NA <reserved-1239A>..<reserved-123FF>
+12400..12462 ; valid ; ; NV8 # 5.0 CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER
+12463..1246E ; valid ; ; NV8 # 7.0 CUNEIFORM NUMERIC SIGN ONE QUARTER GUR..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
+1246F ; disallowed # NA <reserved-1246F>
+12470..12473 ; valid ; ; NV8 # 5.0 CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON
+12474 ; valid ; ; NV8 # 7.0 CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
+12475..1247F ; disallowed # NA <reserved-12475>..<reserved-1247F>
+12480..12543 ; valid # 8.0 CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+12544..12F8F ; disallowed # NA <reserved-12544>..<reserved-12F8F>
+12F90..12FF0 ; valid # 14.0 CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114
+12FF1..12FF2 ; valid ; ; NV8 # 14.0 CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302
+12FF3..12FFF ; disallowed # NA <reserved-12FF3>..<reserved-12FFF>
+13000..1342E ; valid # 5.2 EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
+1342F ; disallowed # NA <reserved-1342F>
+13430..13438 ; disallowed # 12.0 EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT
+13439..143FF ; disallowed # NA <reserved-13439>..<reserved-143FF>
+14400..14646 ; valid # 8.0 ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+14647..167FF ; disallowed # NA <reserved-14647>..<reserved-167FF>
+16800..16A38 ; valid # 6.0 BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
+16A39..16A3F ; disallowed # NA <reserved-16A39>..<reserved-16A3F>
+16A40..16A5E ; valid # 7.0 MRO LETTER TA..MRO LETTER TEK
+16A5F ; disallowed # NA <reserved-16A5F>
+16A60..16A69 ; valid # 7.0 MRO DIGIT ZERO..MRO DIGIT NINE
+16A6A..16A6D ; disallowed # NA <reserved-16A6A>..<reserved-16A6D>
+16A6E..16A6F ; valid ; ; NV8 # 7.0 MRO DANDA..MRO DOUBLE DANDA
+16A70..16ABE ; valid # 14.0 TANGSA LETTER OZ..TANGSA LETTER ZA
+16ABF ; disallowed # NA <reserved-16ABF>
+16AC0..16AC9 ; valid # 14.0 TANGSA DIGIT ZERO..TANGSA DIGIT NINE
+16ACA..16ACF ; disallowed # NA <reserved-16ACA>..<reserved-16ACF>
+16AD0..16AED ; valid # 7.0 BASSA VAH LETTER ENNI..BASSA VAH LETTER I
+16AEE..16AEF ; disallowed # NA <reserved-16AEE>..<reserved-16AEF>
+16AF0..16AF4 ; valid # 7.0 BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
+16AF5 ; valid ; ; NV8 # 7.0 BASSA VAH FULL STOP
+16AF6..16AFF ; disallowed # NA <reserved-16AF6>..<reserved-16AFF>
+16B00..16B36 ; valid # 7.0 PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG MARK CIM TAUM
+16B37..16B3F ; valid ; ; NV8 # 7.0 PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN XYEEM FAIB
+16B40..16B43 ; valid # 7.0 PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
+16B44..16B45 ; valid ; ; NV8 # 7.0 PAHAWH HMONG SIGN XAUS..PAHAWH HMONG SIGN CIM TSOV ROG
+16B46..16B4F ; disallowed # NA <reserved-16B46>..<reserved-16B4F>
+16B50..16B59 ; valid # 7.0 PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
+16B5A ; disallowed # NA <reserved-16B5A>
+16B5B..16B61 ; valid ; ; NV8 # 7.0 PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
+16B62 ; disallowed # NA <reserved-16B62>
+16B63..16B77 ; valid # 7.0 PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
+16B78..16B7C ; disallowed # NA <reserved-16B78>..<reserved-16B7C>
+16B7D..16B8F ; valid # 7.0 PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
+16B90..16E3F ; disallowed # NA <reserved-16B90>..<reserved-16E3F>
+16E40 ; mapped ; 16E60 # 11.0 MEDEFAIDRIN CAPITAL LETTER M
+16E41 ; mapped ; 16E61 # 11.0 MEDEFAIDRIN CAPITAL LETTER S
+16E42 ; mapped ; 16E62 # 11.0 MEDEFAIDRIN CAPITAL LETTER V
+16E43 ; mapped ; 16E63 # 11.0 MEDEFAIDRIN CAPITAL LETTER W
+16E44 ; mapped ; 16E64 # 11.0 MEDEFAIDRIN CAPITAL LETTER ATIU
+16E45 ; mapped ; 16E65 # 11.0 MEDEFAIDRIN CAPITAL LETTER Z
+16E46 ; mapped ; 16E66 # 11.0 MEDEFAIDRIN CAPITAL LETTER KP
+16E47 ; mapped ; 16E67 # 11.0 MEDEFAIDRIN CAPITAL LETTER P
+16E48 ; mapped ; 16E68 # 11.0 MEDEFAIDRIN CAPITAL LETTER T
+16E49 ; mapped ; 16E69 # 11.0 MEDEFAIDRIN CAPITAL LETTER G
+16E4A ; mapped ; 16E6A # 11.0 MEDEFAIDRIN CAPITAL LETTER F
+16E4B ; mapped ; 16E6B # 11.0 MEDEFAIDRIN CAPITAL LETTER I
+16E4C ; mapped ; 16E6C # 11.0 MEDEFAIDRIN CAPITAL LETTER K
+16E4D ; mapped ; 16E6D # 11.0 MEDEFAIDRIN CAPITAL LETTER A
+16E4E ; mapped ; 16E6E # 11.0 MEDEFAIDRIN CAPITAL LETTER J
+16E4F ; mapped ; 16E6F # 11.0 MEDEFAIDRIN CAPITAL LETTER E
+16E50 ; mapped ; 16E70 # 11.0 MEDEFAIDRIN CAPITAL LETTER B
+16E51 ; mapped ; 16E71 # 11.0 MEDEFAIDRIN CAPITAL LETTER C
+16E52 ; mapped ; 16E72 # 11.0 MEDEFAIDRIN CAPITAL LETTER U
+16E53 ; mapped ; 16E73 # 11.0 MEDEFAIDRIN CAPITAL LETTER YU
+16E54 ; mapped ; 16E74 # 11.0 MEDEFAIDRIN CAPITAL LETTER L
+16E55 ; mapped ; 16E75 # 11.0 MEDEFAIDRIN CAPITAL LETTER Q
+16E56 ; mapped ; 16E76 # 11.0 MEDEFAIDRIN CAPITAL LETTER HP
+16E57 ; mapped ; 16E77 # 11.0 MEDEFAIDRIN CAPITAL LETTER NY
+16E58 ; mapped ; 16E78 # 11.0 MEDEFAIDRIN CAPITAL LETTER X
+16E59 ; mapped ; 16E79 # 11.0 MEDEFAIDRIN CAPITAL LETTER D
+16E5A ; mapped ; 16E7A # 11.0 MEDEFAIDRIN CAPITAL LETTER OE
+16E5B ; mapped ; 16E7B # 11.0 MEDEFAIDRIN CAPITAL LETTER N
+16E5C ; mapped ; 16E7C # 11.0 MEDEFAIDRIN CAPITAL LETTER R
+16E5D ; mapped ; 16E7D # 11.0 MEDEFAIDRIN CAPITAL LETTER O
+16E5E ; mapped ; 16E7E # 11.0 MEDEFAIDRIN CAPITAL LETTER AI
+16E5F ; mapped ; 16E7F # 11.0 MEDEFAIDRIN CAPITAL LETTER Y
+16E60..16E7F ; valid # 11.0 MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y
+16E80..16E9A ; valid ; ; NV8 # 11.0 MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN EXCLAMATION OH
+16E9B..16EFF ; disallowed # NA <reserved-16E9B>..<reserved-16EFF>
+16F00..16F44 ; valid # 6.1 MIAO LETTER PA..MIAO LETTER HHA
+16F45..16F4A ; valid # 12.0 MIAO LETTER BRI..MIAO LETTER RTE
+16F4B..16F4E ; disallowed # NA <reserved-16F4B>..<reserved-16F4E>
+16F4F ; valid # 12.0 MIAO SIGN CONSONANT MODIFIER BAR
+16F50..16F7E ; valid # 6.1 MIAO LETTER NASALIZATION..MIAO VOWEL SIGN NG
+16F7F..16F87 ; valid # 12.0 MIAO VOWEL SIGN UOG..MIAO VOWEL SIGN UI
+16F88..16F8E ; disallowed # NA <reserved-16F88>..<reserved-16F8E>
+16F8F..16F9F ; valid # 6.1 MIAO TONE RIGHT..MIAO LETTER REFORMED TONE-8
+16FA0..16FDF ; disallowed # NA <reserved-16FA0>..<reserved-16FDF>
+16FE0 ; valid # 9.0 TANGUT ITERATION MARK
+16FE1 ; valid # 10.0 NUSHU ITERATION MARK
+16FE2 ; valid ; ; NV8 # 12.0 OLD CHINESE HOOK MARK
+16FE3 ; valid # 12.0 OLD CHINESE ITERATION MARK
+16FE4 ; valid # 13.0 KHITAN SMALL SCRIPT FILLER
+16FE5..16FEF ; disallowed # NA <reserved-16FE5>..<reserved-16FEF>
+16FF0..16FF1 ; valid # 13.0 VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
+16FF2..16FFF ; disallowed # NA <reserved-16FF2>..<reserved-16FFF>
+17000..187EC ; valid # 9.0 TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC
+187ED..187F1 ; valid # 11.0 TANGUT IDEOGRAPH-187ED..TANGUT IDEOGRAPH-187F1
+187F2..187F7 ; valid # 12.0 TANGUT IDEOGRAPH-187F2..TANGUT IDEOGRAPH-187F7
+187F8..187FF ; disallowed # NA <reserved-187F8>..<reserved-187FF>
+18800..18AF2 ; valid # 9.0 TANGUT COMPONENT-001..TANGUT COMPONENT-755
+18AF3..18CD5 ; valid # 13.0 TANGUT COMPONENT-756..KHITAN SMALL SCRIPT CHARACTER-18CD5
+18CD6..18CFF ; disallowed # NA <reserved-18CD6>..<reserved-18CFF>
+18D00..18D08 ; valid # 13.0 TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
+18D09..1AFEF ; disallowed # NA <reserved-18D09>..<reserved-1AFEF>
+1AFF0..1AFF3 ; valid # 14.0 KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5
+1AFF4 ; disallowed # NA <reserved-1AFF4>
+1AFF5..1AFFB ; valid # 14.0 KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5
+1AFFC ; disallowed # NA <reserved-1AFFC>
+1AFFD..1AFFE ; valid # 14.0 KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8
+1AFFF ; disallowed # NA <reserved-1AFFF>
+1B000..1B001 ; valid # 6.0 KATAKANA LETTER ARCHAIC E..HIRAGANA LETTER ARCHAIC YE
+1B002..1B11E ; valid # 10.0 HENTAIGANA LETTER A-1..HENTAIGANA LETTER N-MU-MO-2
+1B11F..1B122 ; valid # 14.0 HIRAGANA LETTER ARCHAIC WU..KATAKANA LETTER ARCHAIC WU
+1B123..1B14F ; disallowed # NA <reserved-1B123>..<reserved-1B14F>
+1B150..1B152 ; valid # 12.0 HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO
+1B153..1B163 ; disallowed # NA <reserved-1B153>..<reserved-1B163>
+1B164..1B167 ; valid # 12.0 KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N
+1B168..1B16F ; disallowed # NA <reserved-1B168>..<reserved-1B16F>
+1B170..1B2FB ; valid # 10.0 NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
+1B2FC..1BBFF ; disallowed # NA <reserved-1B2FC>..<reserved-1BBFF>
+1BC00..1BC6A ; valid # 7.0 DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
+1BC6B..1BC6F ; disallowed # NA <reserved-1BC6B>..<reserved-1BC6F>
+1BC70..1BC7C ; valid # 7.0 DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
+1BC7D..1BC7F ; disallowed # NA <reserved-1BC7D>..<reserved-1BC7F>
+1BC80..1BC88 ; valid # 7.0 DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
+1BC89..1BC8F ; disallowed # NA <reserved-1BC89>..<reserved-1BC8F>
+1BC90..1BC99 ; valid # 7.0 DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
+1BC9A..1BC9B ; disallowed # NA <reserved-1BC9A>..<reserved-1BC9B>
+1BC9C ; valid ; ; NV8 # 7.0 DUPLOYAN SIGN O WITH CROSS
+1BC9D..1BC9E ; valid # 7.0 DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BC9F ; valid ; ; NV8 # 7.0 DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1BCA0..1BCA3 ; ignored # 7.0 SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+1BCA4..1CEFF ; disallowed # NA <reserved-1BCA4>..<reserved-1CEFF>
+1CF00..1CF2D ; valid # 14.0 ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
+1CF2E..1CF2F ; disallowed # NA <reserved-1CF2E>..<reserved-1CF2F>
+1CF30..1CF46 ; valid # 14.0 ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
+1CF47..1CF4F ; disallowed # NA <reserved-1CF47>..<reserved-1CF4F>
+1CF50..1CFC3 ; valid ; ; NV8 # 14.0 ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK
+1CFC4..1CFFF ; disallowed # NA <reserved-1CFC4>..<reserved-1CFFF>
+1D000..1D0F5 ; valid ; ; NV8 # 3.1 BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
+1D0F6..1D0FF ; disallowed # NA <reserved-1D0F6>..<reserved-1D0FF>
+1D100..1D126 ; valid ; ; NV8 # 3.1 MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
+1D127..1D128 ; disallowed # NA <reserved-1D127>..<reserved-1D128>
+1D129 ; valid ; ; NV8 # 5.1 MUSICAL SYMBOL MULTIPLE MEASURE REST
+1D12A..1D15D ; valid ; ; NV8 # 3.1 MUSICAL SYMBOL DOUBLE SHARP..MUSICAL SYMBOL WHOLE NOTE
+1D15E ; mapped ; 1D157 1D165 # 3.1 MUSICAL SYMBOL HALF NOTE
+1D15F ; mapped ; 1D158 1D165 # 3.1 MUSICAL SYMBOL QUARTER NOTE
+1D160 ; mapped ; 1D158 1D165 1D16E #3.1 MUSICAL SYMBOL EIGHTH NOTE
+1D161 ; mapped ; 1D158 1D165 1D16F #3.1 MUSICAL SYMBOL SIXTEENTH NOTE
+1D162 ; mapped ; 1D158 1D165 1D170 #3.1 MUSICAL SYMBOL THIRTY-SECOND NOTE
+1D163 ; mapped ; 1D158 1D165 1D171 #3.1 MUSICAL SYMBOL SIXTY-FOURTH NOTE
+1D164 ; mapped ; 1D158 1D165 1D172 #3.1 MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
+1D165..1D172 ; valid ; ; NV8 # 3.1 MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING FLAG-5
+1D173..1D17A ; disallowed # 3.1 MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+1D17B..1D1BA ; valid ; ; NV8 # 3.1 MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL SEMIBREVIS BLACK
+1D1BB ; mapped ; 1D1B9 1D165 # 3.1 MUSICAL SYMBOL MINIMA
+1D1BC ; mapped ; 1D1BA 1D165 # 3.1 MUSICAL SYMBOL MINIMA BLACK
+1D1BD ; mapped ; 1D1B9 1D165 1D16E #3.1 MUSICAL SYMBOL SEMIMINIMA WHITE
+1D1BE ; mapped ; 1D1BA 1D165 1D16E #3.1 MUSICAL SYMBOL SEMIMINIMA BLACK
+1D1BF ; mapped ; 1D1B9 1D165 1D16F #3.1 MUSICAL SYMBOL FUSA WHITE
+1D1C0 ; mapped ; 1D1BA 1D165 1D16F #3.1 MUSICAL SYMBOL FUSA BLACK
+1D1C1..1D1DD ; valid ; ; NV8 # 3.1 MUSICAL SYMBOL LONGA PERFECTA REST..MUSICAL SYMBOL PES SUBPUNCTIS
+1D1DE..1D1E8 ; valid ; ; NV8 # 8.0 MUSICAL SYMBOL KIEVAN C CLEF..MUSICAL SYMBOL KIEVAN FLAT SIGN
+1D1E9..1D1EA ; valid ; ; NV8 # 14.0 MUSICAL SYMBOL SORI..MUSICAL SYMBOL KORON
+1D1EB..1D1FF ; disallowed # NA <reserved-1D1EB>..<reserved-1D1FF>
+1D200..1D245 ; valid ; ; NV8 # 4.1 GREEK VOCAL NOTATION SYMBOL-1..GREEK MUSICAL LEIMMA
+1D246..1D2DF ; disallowed # NA <reserved-1D246>..<reserved-1D2DF>
+1D2E0..1D2F3 ; valid ; ; NV8 # 11.0 MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
+1D2F4..1D2FF ; disallowed # NA <reserved-1D2F4>..<reserved-1D2FF>
+1D300..1D356 ; valid ; ; NV8 # 4.0 MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
+1D357..1D35F ; disallowed # NA <reserved-1D357>..<reserved-1D35F>
+1D360..1D371 ; valid ; ; NV8 # 5.0 COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE
+1D372..1D378 ; valid ; ; NV8 # 11.0 IDEOGRAPHIC TALLY MARK ONE..TALLY MARK FIVE
+1D379..1D3FF ; disallowed # NA <reserved-1D379>..<reserved-1D3FF>
+1D400 ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD CAPITAL A
+1D401 ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD CAPITAL B
+1D402 ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD CAPITAL C
+1D403 ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD CAPITAL D
+1D404 ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD CAPITAL E
+1D405 ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD CAPITAL F
+1D406 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD CAPITAL G
+1D407 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD CAPITAL H
+1D408 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD CAPITAL I
+1D409 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD CAPITAL J
+1D40A ; mapped ; 006B # 3.1 MATHEMATICAL BOLD CAPITAL K
+1D40B ; mapped ; 006C # 3.1 MATHEMATICAL BOLD CAPITAL L
+1D40C ; mapped ; 006D # 3.1 MATHEMATICAL BOLD CAPITAL M
+1D40D ; mapped ; 006E # 3.1 MATHEMATICAL BOLD CAPITAL N
+1D40E ; mapped ; 006F # 3.1 MATHEMATICAL BOLD CAPITAL O
+1D40F ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD CAPITAL P
+1D410 ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD CAPITAL Q
+1D411 ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD CAPITAL R
+1D412 ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD CAPITAL S
+1D413 ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD CAPITAL T
+1D414 ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD CAPITAL U
+1D415 ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD CAPITAL V
+1D416 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD CAPITAL W
+1D417 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD CAPITAL X
+1D418 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD CAPITAL Y
+1D419 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD CAPITAL Z
+1D41A ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD SMALL A
+1D41B ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD SMALL B
+1D41C ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD SMALL C
+1D41D ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD SMALL D
+1D41E ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD SMALL E
+1D41F ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD SMALL F
+1D420 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD SMALL G
+1D421 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD SMALL H
+1D422 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD SMALL I
+1D423 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD SMALL J
+1D424 ; mapped ; 006B # 3.1 MATHEMATICAL BOLD SMALL K
+1D425 ; mapped ; 006C # 3.1 MATHEMATICAL BOLD SMALL L
+1D426 ; mapped ; 006D # 3.1 MATHEMATICAL BOLD SMALL M
+1D427 ; mapped ; 006E # 3.1 MATHEMATICAL BOLD SMALL N
+1D428 ; mapped ; 006F # 3.1 MATHEMATICAL BOLD SMALL O
+1D429 ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD SMALL P
+1D42A ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD SMALL Q
+1D42B ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD SMALL R
+1D42C ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD SMALL S
+1D42D ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD SMALL T
+1D42E ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD SMALL U
+1D42F ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD SMALL V
+1D430 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD SMALL W
+1D431 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD SMALL X
+1D432 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD SMALL Y
+1D433 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD SMALL Z
+1D434 ; mapped ; 0061 # 3.1 MATHEMATICAL ITALIC CAPITAL A
+1D435 ; mapped ; 0062 # 3.1 MATHEMATICAL ITALIC CAPITAL B
+1D436 ; mapped ; 0063 # 3.1 MATHEMATICAL ITALIC CAPITAL C
+1D437 ; mapped ; 0064 # 3.1 MATHEMATICAL ITALIC CAPITAL D
+1D438 ; mapped ; 0065 # 3.1 MATHEMATICAL ITALIC CAPITAL E
+1D439 ; mapped ; 0066 # 3.1 MATHEMATICAL ITALIC CAPITAL F
+1D43A ; mapped ; 0067 # 3.1 MATHEMATICAL ITALIC CAPITAL G
+1D43B ; mapped ; 0068 # 3.1 MATHEMATICAL ITALIC CAPITAL H
+1D43C ; mapped ; 0069 # 3.1 MATHEMATICAL ITALIC CAPITAL I
+1D43D ; mapped ; 006A # 3.1 MATHEMATICAL ITALIC CAPITAL J
+1D43E ; mapped ; 006B # 3.1 MATHEMATICAL ITALIC CAPITAL K
+1D43F ; mapped ; 006C # 3.1 MATHEMATICAL ITALIC CAPITAL L
+1D440 ; mapped ; 006D # 3.1 MATHEMATICAL ITALIC CAPITAL M
+1D441 ; mapped ; 006E # 3.1 MATHEMATICAL ITALIC CAPITAL N
+1D442 ; mapped ; 006F # 3.1 MATHEMATICAL ITALIC CAPITAL O
+1D443 ; mapped ; 0070 # 3.1 MATHEMATICAL ITALIC CAPITAL P
+1D444 ; mapped ; 0071 # 3.1 MATHEMATICAL ITALIC CAPITAL Q
+1D445 ; mapped ; 0072 # 3.1 MATHEMATICAL ITALIC CAPITAL R
+1D446 ; mapped ; 0073 # 3.1 MATHEMATICAL ITALIC CAPITAL S
+1D447 ; mapped ; 0074 # 3.1 MATHEMATICAL ITALIC CAPITAL T
+1D448 ; mapped ; 0075 # 3.1 MATHEMATICAL ITALIC CAPITAL U
+1D449 ; mapped ; 0076 # 3.1 MATHEMATICAL ITALIC CAPITAL V
+1D44A ; mapped ; 0077 # 3.1 MATHEMATICAL ITALIC CAPITAL W
+1D44B ; mapped ; 0078 # 3.1 MATHEMATICAL ITALIC CAPITAL X
+1D44C ; mapped ; 0079 # 3.1 MATHEMATICAL ITALIC CAPITAL Y
+1D44D ; mapped ; 007A # 3.1 MATHEMATICAL ITALIC CAPITAL Z
+1D44E ; mapped ; 0061 # 3.1 MATHEMATICAL ITALIC SMALL A
+1D44F ; mapped ; 0062 # 3.1 MATHEMATICAL ITALIC SMALL B
+1D450 ; mapped ; 0063 # 3.1 MATHEMATICAL ITALIC SMALL C
+1D451 ; mapped ; 0064 # 3.1 MATHEMATICAL ITALIC SMALL D
+1D452 ; mapped ; 0065 # 3.1 MATHEMATICAL ITALIC SMALL E
+1D453 ; mapped ; 0066 # 3.1 MATHEMATICAL ITALIC SMALL F
+1D454 ; mapped ; 0067 # 3.1 MATHEMATICAL ITALIC SMALL G
+1D455 ; disallowed # NA <reserved-1D455>
+1D456 ; mapped ; 0069 # 3.1 MATHEMATICAL ITALIC SMALL I
+1D457 ; mapped ; 006A # 3.1 MATHEMATICAL ITALIC SMALL J
+1D458 ; mapped ; 006B # 3.1 MATHEMATICAL ITALIC SMALL K
+1D459 ; mapped ; 006C # 3.1 MATHEMATICAL ITALIC SMALL L
+1D45A ; mapped ; 006D # 3.1 MATHEMATICAL ITALIC SMALL M
+1D45B ; mapped ; 006E # 3.1 MATHEMATICAL ITALIC SMALL N
+1D45C ; mapped ; 006F # 3.1 MATHEMATICAL ITALIC SMALL O
+1D45D ; mapped ; 0070 # 3.1 MATHEMATICAL ITALIC SMALL P
+1D45E ; mapped ; 0071 # 3.1 MATHEMATICAL ITALIC SMALL Q
+1D45F ; mapped ; 0072 # 3.1 MATHEMATICAL ITALIC SMALL R
+1D460 ; mapped ; 0073 # 3.1 MATHEMATICAL ITALIC SMALL S
+1D461 ; mapped ; 0074 # 3.1 MATHEMATICAL ITALIC SMALL T
+1D462 ; mapped ; 0075 # 3.1 MATHEMATICAL ITALIC SMALL U
+1D463 ; mapped ; 0076 # 3.1 MATHEMATICAL ITALIC SMALL V
+1D464 ; mapped ; 0077 # 3.1 MATHEMATICAL ITALIC SMALL W
+1D465 ; mapped ; 0078 # 3.1 MATHEMATICAL ITALIC SMALL X
+1D466 ; mapped ; 0079 # 3.1 MATHEMATICAL ITALIC SMALL Y
+1D467 ; mapped ; 007A # 3.1 MATHEMATICAL ITALIC SMALL Z
+1D468 ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL A
+1D469 ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL B
+1D46A ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL C
+1D46B ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL D
+1D46C ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL E
+1D46D ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL F
+1D46E ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL G
+1D46F ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL H
+1D470 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL I
+1D471 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL J
+1D472 ; mapped ; 006B # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL K
+1D473 ; mapped ; 006C # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL L
+1D474 ; mapped ; 006D # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL M
+1D475 ; mapped ; 006E # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL N
+1D476 ; mapped ; 006F # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL O
+1D477 ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL P
+1D478 ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL Q
+1D479 ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL R
+1D47A ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL S
+1D47B ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL T
+1D47C ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL U
+1D47D ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL V
+1D47E ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL W
+1D47F ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL X
+1D480 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL Y
+1D481 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL Z
+1D482 ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD ITALIC SMALL A
+1D483 ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD ITALIC SMALL B
+1D484 ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD ITALIC SMALL C
+1D485 ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD ITALIC SMALL D
+1D486 ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD ITALIC SMALL E
+1D487 ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD ITALIC SMALL F
+1D488 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD ITALIC SMALL G
+1D489 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD ITALIC SMALL H
+1D48A ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD ITALIC SMALL I
+1D48B ; mapped ; 006A # 3.1 MATHEMATICAL BOLD ITALIC SMALL J
+1D48C ; mapped ; 006B # 3.1 MATHEMATICAL BOLD ITALIC SMALL K
+1D48D ; mapped ; 006C # 3.1 MATHEMATICAL BOLD ITALIC SMALL L
+1D48E ; mapped ; 006D # 3.1 MATHEMATICAL BOLD ITALIC SMALL M
+1D48F ; mapped ; 006E # 3.1 MATHEMATICAL BOLD ITALIC SMALL N
+1D490 ; mapped ; 006F # 3.1 MATHEMATICAL BOLD ITALIC SMALL O
+1D491 ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD ITALIC SMALL P
+1D492 ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD ITALIC SMALL Q
+1D493 ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD ITALIC SMALL R
+1D494 ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD ITALIC SMALL S
+1D495 ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD ITALIC SMALL T
+1D496 ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD ITALIC SMALL U
+1D497 ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD ITALIC SMALL V
+1D498 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD ITALIC SMALL W
+1D499 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD ITALIC SMALL X
+1D49A ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD ITALIC SMALL Y
+1D49B ; mapped ; 007A # 3.1 MATHEMATICAL BOLD ITALIC SMALL Z
+1D49C ; mapped ; 0061 # 3.1 MATHEMATICAL SCRIPT CAPITAL A
+1D49D ; disallowed # NA <reserved-1D49D>
+1D49E ; mapped ; 0063 # 3.1 MATHEMATICAL SCRIPT CAPITAL C
+1D49F ; mapped ; 0064 # 3.1 MATHEMATICAL SCRIPT CAPITAL D
+1D4A0..1D4A1 ; disallowed # NA <reserved-1D4A0>..<reserved-1D4A1>
+1D4A2 ; mapped ; 0067 # 3.1 MATHEMATICAL SCRIPT CAPITAL G
+1D4A3..1D4A4 ; disallowed # NA <reserved-1D4A3>..<reserved-1D4A4>
+1D4A5 ; mapped ; 006A # 3.1 MATHEMATICAL SCRIPT CAPITAL J
+1D4A6 ; mapped ; 006B # 3.1 MATHEMATICAL SCRIPT CAPITAL K
+1D4A7..1D4A8 ; disallowed # NA <reserved-1D4A7>..<reserved-1D4A8>
+1D4A9 ; mapped ; 006E # 3.1 MATHEMATICAL SCRIPT CAPITAL N
+1D4AA ; mapped ; 006F # 3.1 MATHEMATICAL SCRIPT CAPITAL O
+1D4AB ; mapped ; 0070 # 3.1 MATHEMATICAL SCRIPT CAPITAL P
+1D4AC ; mapped ; 0071 # 3.1 MATHEMATICAL SCRIPT CAPITAL Q
+1D4AD ; disallowed # NA <reserved-1D4AD>
+1D4AE ; mapped ; 0073 # 3.1 MATHEMATICAL SCRIPT CAPITAL S
+1D4AF ; mapped ; 0074 # 3.1 MATHEMATICAL SCRIPT CAPITAL T
+1D4B0 ; mapped ; 0075 # 3.1 MATHEMATICAL SCRIPT CAPITAL U
+1D4B1 ; mapped ; 0076 # 3.1 MATHEMATICAL SCRIPT CAPITAL V
+1D4B2 ; mapped ; 0077 # 3.1 MATHEMATICAL SCRIPT CAPITAL W
+1D4B3 ; mapped ; 0078 # 3.1 MATHEMATICAL SCRIPT CAPITAL X
+1D4B4 ; mapped ; 0079 # 3.1 MATHEMATICAL SCRIPT CAPITAL Y
+1D4B5 ; mapped ; 007A # 3.1 MATHEMATICAL SCRIPT CAPITAL Z
+1D4B6 ; mapped ; 0061 # 3.1 MATHEMATICAL SCRIPT SMALL A
+1D4B7 ; mapped ; 0062 # 3.1 MATHEMATICAL SCRIPT SMALL B
+1D4B8 ; mapped ; 0063 # 3.1 MATHEMATICAL SCRIPT SMALL C
+1D4B9 ; mapped ; 0064 # 3.1 MATHEMATICAL SCRIPT SMALL D
+1D4BA ; disallowed # NA <reserved-1D4BA>
+1D4BB ; mapped ; 0066 # 3.1 MATHEMATICAL SCRIPT SMALL F
+1D4BC ; disallowed # NA <reserved-1D4BC>
+1D4BD ; mapped ; 0068 # 3.1 MATHEMATICAL SCRIPT SMALL H
+1D4BE ; mapped ; 0069 # 3.1 MATHEMATICAL SCRIPT SMALL I
+1D4BF ; mapped ; 006A # 3.1 MATHEMATICAL SCRIPT SMALL J
+1D4C0 ; mapped ; 006B # 3.1 MATHEMATICAL SCRIPT SMALL K
+1D4C1 ; mapped ; 006C # 4.0 MATHEMATICAL SCRIPT SMALL L
+1D4C2 ; mapped ; 006D # 3.1 MATHEMATICAL SCRIPT SMALL M
+1D4C3 ; mapped ; 006E # 3.1 MATHEMATICAL SCRIPT SMALL N
+1D4C4 ; disallowed # NA <reserved-1D4C4>
+1D4C5 ; mapped ; 0070 # 3.1 MATHEMATICAL SCRIPT SMALL P
+1D4C6 ; mapped ; 0071 # 3.1 MATHEMATICAL SCRIPT SMALL Q
+1D4C7 ; mapped ; 0072 # 3.1 MATHEMATICAL SCRIPT SMALL R
+1D4C8 ; mapped ; 0073 # 3.1 MATHEMATICAL SCRIPT SMALL S
+1D4C9 ; mapped ; 0074 # 3.1 MATHEMATICAL SCRIPT SMALL T
+1D4CA ; mapped ; 0075 # 3.1 MATHEMATICAL SCRIPT SMALL U
+1D4CB ; mapped ; 0076 # 3.1 MATHEMATICAL SCRIPT SMALL V
+1D4CC ; mapped ; 0077 # 3.1 MATHEMATICAL SCRIPT SMALL W
+1D4CD ; mapped ; 0078 # 3.1 MATHEMATICAL SCRIPT SMALL X
+1D4CE ; mapped ; 0079 # 3.1 MATHEMATICAL SCRIPT SMALL Y
+1D4CF ; mapped ; 007A # 3.1 MATHEMATICAL SCRIPT SMALL Z
+1D4D0 ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL A
+1D4D1 ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL B
+1D4D2 ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL C
+1D4D3 ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL D
+1D4D4 ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL E
+1D4D5 ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL F
+1D4D6 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL G
+1D4D7 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL H
+1D4D8 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL I
+1D4D9 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL J
+1D4DA ; mapped ; 006B # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL K
+1D4DB ; mapped ; 006C # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL L
+1D4DC ; mapped ; 006D # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL M
+1D4DD ; mapped ; 006E # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL N
+1D4DE ; mapped ; 006F # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL O
+1D4DF ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL P
+1D4E0 ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL Q
+1D4E1 ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL R
+1D4E2 ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL S
+1D4E3 ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL T
+1D4E4 ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL U
+1D4E5 ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL V
+1D4E6 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL W
+1D4E7 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL X
+1D4E8 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL Y
+1D4E9 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD SCRIPT CAPITAL Z
+1D4EA ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL A
+1D4EB ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL B
+1D4EC ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL C
+1D4ED ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL D
+1D4EE ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL E
+1D4EF ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL F
+1D4F0 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL G
+1D4F1 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL H
+1D4F2 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL I
+1D4F3 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD SCRIPT SMALL J
+1D4F4 ; mapped ; 006B # 3.1 MATHEMATICAL BOLD SCRIPT SMALL K
+1D4F5 ; mapped ; 006C # 3.1 MATHEMATICAL BOLD SCRIPT SMALL L
+1D4F6 ; mapped ; 006D # 3.1 MATHEMATICAL BOLD SCRIPT SMALL M
+1D4F7 ; mapped ; 006E # 3.1 MATHEMATICAL BOLD SCRIPT SMALL N
+1D4F8 ; mapped ; 006F # 3.1 MATHEMATICAL BOLD SCRIPT SMALL O
+1D4F9 ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL P
+1D4FA ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL Q
+1D4FB ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL R
+1D4FC ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL S
+1D4FD ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL T
+1D4FE ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL U
+1D4FF ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL V
+1D500 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL W
+1D501 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL X
+1D502 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD SCRIPT SMALL Y
+1D503 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD SCRIPT SMALL Z
+1D504 ; mapped ; 0061 # 3.1 MATHEMATICAL FRAKTUR CAPITAL A
+1D505 ; mapped ; 0062 # 3.1 MATHEMATICAL FRAKTUR CAPITAL B
+1D506 ; disallowed # NA <reserved-1D506>
+1D507 ; mapped ; 0064 # 3.1 MATHEMATICAL FRAKTUR CAPITAL D
+1D508 ; mapped ; 0065 # 3.1 MATHEMATICAL FRAKTUR CAPITAL E
+1D509 ; mapped ; 0066 # 3.1 MATHEMATICAL FRAKTUR CAPITAL F
+1D50A ; mapped ; 0067 # 3.1 MATHEMATICAL FRAKTUR CAPITAL G
+1D50B..1D50C ; disallowed # NA <reserved-1D50B>..<reserved-1D50C>
+1D50D ; mapped ; 006A # 3.1 MATHEMATICAL FRAKTUR CAPITAL J
+1D50E ; mapped ; 006B # 3.1 MATHEMATICAL FRAKTUR CAPITAL K
+1D50F ; mapped ; 006C # 3.1 MATHEMATICAL FRAKTUR CAPITAL L
+1D510 ; mapped ; 006D # 3.1 MATHEMATICAL FRAKTUR CAPITAL M
+1D511 ; mapped ; 006E # 3.1 MATHEMATICAL FRAKTUR CAPITAL N
+1D512 ; mapped ; 006F # 3.1 MATHEMATICAL FRAKTUR CAPITAL O
+1D513 ; mapped ; 0070 # 3.1 MATHEMATICAL FRAKTUR CAPITAL P
+1D514 ; mapped ; 0071 # 3.1 MATHEMATICAL FRAKTUR CAPITAL Q
+1D515 ; disallowed # NA <reserved-1D515>
+1D516 ; mapped ; 0073 # 3.1 MATHEMATICAL FRAKTUR CAPITAL S
+1D517 ; mapped ; 0074 # 3.1 MATHEMATICAL FRAKTUR CAPITAL T
+1D518 ; mapped ; 0075 # 3.1 MATHEMATICAL FRAKTUR CAPITAL U
+1D519 ; mapped ; 0076 # 3.1 MATHEMATICAL FRAKTUR CAPITAL V
+1D51A ; mapped ; 0077 # 3.1 MATHEMATICAL FRAKTUR CAPITAL W
+1D51B ; mapped ; 0078 # 3.1 MATHEMATICAL FRAKTUR CAPITAL X
+1D51C ; mapped ; 0079 # 3.1 MATHEMATICAL FRAKTUR CAPITAL Y
+1D51D ; disallowed # NA <reserved-1D51D>
+1D51E ; mapped ; 0061 # 3.1 MATHEMATICAL FRAKTUR SMALL A
+1D51F ; mapped ; 0062 # 3.1 MATHEMATICAL FRAKTUR SMALL B
+1D520 ; mapped ; 0063 # 3.1 MATHEMATICAL FRAKTUR SMALL C
+1D521 ; mapped ; 0064 # 3.1 MATHEMATICAL FRAKTUR SMALL D
+1D522 ; mapped ; 0065 # 3.1 MATHEMATICAL FRAKTUR SMALL E
+1D523 ; mapped ; 0066 # 3.1 MATHEMATICAL FRAKTUR SMALL F
+1D524 ; mapped ; 0067 # 3.1 MATHEMATICAL FRAKTUR SMALL G
+1D525 ; mapped ; 0068 # 3.1 MATHEMATICAL FRAKTUR SMALL H
+1D526 ; mapped ; 0069 # 3.1 MATHEMATICAL FRAKTUR SMALL I
+1D527 ; mapped ; 006A # 3.1 MATHEMATICAL FRAKTUR SMALL J
+1D528 ; mapped ; 006B # 3.1 MATHEMATICAL FRAKTUR SMALL K
+1D529 ; mapped ; 006C # 3.1 MATHEMATICAL FRAKTUR SMALL L
+1D52A ; mapped ; 006D # 3.1 MATHEMATICAL FRAKTUR SMALL M
+1D52B ; mapped ; 006E # 3.1 MATHEMATICAL FRAKTUR SMALL N
+1D52C ; mapped ; 006F # 3.1 MATHEMATICAL FRAKTUR SMALL O
+1D52D ; mapped ; 0070 # 3.1 MATHEMATICAL FRAKTUR SMALL P
+1D52E ; mapped ; 0071 # 3.1 MATHEMATICAL FRAKTUR SMALL Q
+1D52F ; mapped ; 0072 # 3.1 MATHEMATICAL FRAKTUR SMALL R
+1D530 ; mapped ; 0073 # 3.1 MATHEMATICAL FRAKTUR SMALL S
+1D531 ; mapped ; 0074 # 3.1 MATHEMATICAL FRAKTUR SMALL T
+1D532 ; mapped ; 0075 # 3.1 MATHEMATICAL FRAKTUR SMALL U
+1D533 ; mapped ; 0076 # 3.1 MATHEMATICAL FRAKTUR SMALL V
+1D534 ; mapped ; 0077 # 3.1 MATHEMATICAL FRAKTUR SMALL W
+1D535 ; mapped ; 0078 # 3.1 MATHEMATICAL FRAKTUR SMALL X
+1D536 ; mapped ; 0079 # 3.1 MATHEMATICAL FRAKTUR SMALL Y
+1D537 ; mapped ; 007A # 3.1 MATHEMATICAL FRAKTUR SMALL Z
+1D538 ; mapped ; 0061 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL A
+1D539 ; mapped ; 0062 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+1D53A ; disallowed # NA <reserved-1D53A>
+1D53B ; mapped ; 0064 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL D
+1D53C ; mapped ; 0065 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL E
+1D53D ; mapped ; 0066 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL F
+1D53E ; mapped ; 0067 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+1D53F ; disallowed # NA <reserved-1D53F>
+1D540 ; mapped ; 0069 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL I
+1D541 ; mapped ; 006A # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL J
+1D542 ; mapped ; 006B # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL K
+1D543 ; mapped ; 006C # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL L
+1D544 ; mapped ; 006D # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+1D545 ; disallowed # NA <reserved-1D545>
+1D546 ; mapped ; 006F # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+1D547..1D549 ; disallowed # NA <reserved-1D547>..<reserved-1D549>
+1D54A ; mapped ; 0073 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL S
+1D54B ; mapped ; 0074 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL T
+1D54C ; mapped ; 0075 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL U
+1D54D ; mapped ; 0076 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL V
+1D54E ; mapped ; 0077 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL W
+1D54F ; mapped ; 0078 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL X
+1D550 ; mapped ; 0079 # 3.1 MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+1D551 ; disallowed # NA <reserved-1D551>
+1D552 ; mapped ; 0061 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL A
+1D553 ; mapped ; 0062 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL B
+1D554 ; mapped ; 0063 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL C
+1D555 ; mapped ; 0064 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL D
+1D556 ; mapped ; 0065 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL E
+1D557 ; mapped ; 0066 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL F
+1D558 ; mapped ; 0067 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL G
+1D559 ; mapped ; 0068 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL H
+1D55A ; mapped ; 0069 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL I
+1D55B ; mapped ; 006A # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL J
+1D55C ; mapped ; 006B # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL K
+1D55D ; mapped ; 006C # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL L
+1D55E ; mapped ; 006D # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL M
+1D55F ; mapped ; 006E # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL N
+1D560 ; mapped ; 006F # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL O
+1D561 ; mapped ; 0070 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL P
+1D562 ; mapped ; 0071 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL Q
+1D563 ; mapped ; 0072 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL R
+1D564 ; mapped ; 0073 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL S
+1D565 ; mapped ; 0074 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL T
+1D566 ; mapped ; 0075 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL U
+1D567 ; mapped ; 0076 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL V
+1D568 ; mapped ; 0077 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL W
+1D569 ; mapped ; 0078 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL X
+1D56A ; mapped ; 0079 # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL Y
+1D56B ; mapped ; 007A # 3.1 MATHEMATICAL DOUBLE-STRUCK SMALL Z
+1D56C ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL A
+1D56D ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL B
+1D56E ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL C
+1D56F ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL D
+1D570 ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL E
+1D571 ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL F
+1D572 ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL G
+1D573 ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL H
+1D574 ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL I
+1D575 ; mapped ; 006A # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL J
+1D576 ; mapped ; 006B # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL K
+1D577 ; mapped ; 006C # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL L
+1D578 ; mapped ; 006D # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL M
+1D579 ; mapped ; 006E # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL N
+1D57A ; mapped ; 006F # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL O
+1D57B ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL P
+1D57C ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL Q
+1D57D ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL R
+1D57E ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL S
+1D57F ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL T
+1D580 ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL U
+1D581 ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL V
+1D582 ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL W
+1D583 ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL X
+1D584 ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL Y
+1D585 ; mapped ; 007A # 3.1 MATHEMATICAL BOLD FRAKTUR CAPITAL Z
+1D586 ; mapped ; 0061 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL A
+1D587 ; mapped ; 0062 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL B
+1D588 ; mapped ; 0063 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL C
+1D589 ; mapped ; 0064 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL D
+1D58A ; mapped ; 0065 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL E
+1D58B ; mapped ; 0066 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL F
+1D58C ; mapped ; 0067 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL G
+1D58D ; mapped ; 0068 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL H
+1D58E ; mapped ; 0069 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL I
+1D58F ; mapped ; 006A # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL J
+1D590 ; mapped ; 006B # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL K
+1D591 ; mapped ; 006C # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL L
+1D592 ; mapped ; 006D # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL M
+1D593 ; mapped ; 006E # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL N
+1D594 ; mapped ; 006F # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL O
+1D595 ; mapped ; 0070 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL P
+1D596 ; mapped ; 0071 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL Q
+1D597 ; mapped ; 0072 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL R
+1D598 ; mapped ; 0073 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL S
+1D599 ; mapped ; 0074 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL T
+1D59A ; mapped ; 0075 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL U
+1D59B ; mapped ; 0076 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL V
+1D59C ; mapped ; 0077 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL W
+1D59D ; mapped ; 0078 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL X
+1D59E ; mapped ; 0079 # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL Y
+1D59F ; mapped ; 007A # 3.1 MATHEMATICAL BOLD FRAKTUR SMALL Z
+1D5A0 ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL A
+1D5A1 ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL B
+1D5A2 ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL C
+1D5A3 ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL D
+1D5A4 ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL E
+1D5A5 ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL F
+1D5A6 ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL G
+1D5A7 ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL H
+1D5A8 ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL I
+1D5A9 ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF CAPITAL J
+1D5AA ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF CAPITAL K
+1D5AB ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF CAPITAL L
+1D5AC ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF CAPITAL M
+1D5AD ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF CAPITAL N
+1D5AE ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF CAPITAL O
+1D5AF ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL P
+1D5B0 ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL Q
+1D5B1 ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL R
+1D5B2 ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL S
+1D5B3 ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL T
+1D5B4 ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL U
+1D5B5 ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL V
+1D5B6 ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL W
+1D5B7 ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL X
+1D5B8 ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF CAPITAL Y
+1D5B9 ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF CAPITAL Z
+1D5BA ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF SMALL A
+1D5BB ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF SMALL B
+1D5BC ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF SMALL C
+1D5BD ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF SMALL D
+1D5BE ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF SMALL E
+1D5BF ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF SMALL F
+1D5C0 ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF SMALL G
+1D5C1 ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF SMALL H
+1D5C2 ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF SMALL I
+1D5C3 ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF SMALL J
+1D5C4 ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF SMALL K
+1D5C5 ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF SMALL L
+1D5C6 ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF SMALL M
+1D5C7 ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF SMALL N
+1D5C8 ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF SMALL O
+1D5C9 ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF SMALL P
+1D5CA ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF SMALL Q
+1D5CB ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF SMALL R
+1D5CC ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF SMALL S
+1D5CD ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF SMALL T
+1D5CE ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF SMALL U
+1D5CF ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF SMALL V
+1D5D0 ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF SMALL W
+1D5D1 ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF SMALL X
+1D5D2 ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF SMALL Y
+1D5D3 ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF SMALL Z
+1D5D4 ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL A
+1D5D5 ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL B
+1D5D6 ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL C
+1D5D7 ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL D
+1D5D8 ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL E
+1D5D9 ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL F
+1D5DA ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL G
+1D5DB ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL H
+1D5DC ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL I
+1D5DD ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL J
+1D5DE ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL K
+1D5DF ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL L
+1D5E0 ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL M
+1D5E1 ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL N
+1D5E2 ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL O
+1D5E3 ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL P
+1D5E4 ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL Q
+1D5E5 ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL R
+1D5E6 ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL S
+1D5E7 ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL T
+1D5E8 ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL U
+1D5E9 ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL V
+1D5EA ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL W
+1D5EB ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL X
+1D5EC ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL Y
+1D5ED ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL Z
+1D5EE ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL A
+1D5EF ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL B
+1D5F0 ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL C
+1D5F1 ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL D
+1D5F2 ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL E
+1D5F3 ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL F
+1D5F4 ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL G
+1D5F5 ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL H
+1D5F6 ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL I
+1D5F7 ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL J
+1D5F8 ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL K
+1D5F9 ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL L
+1D5FA ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL M
+1D5FB ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL N
+1D5FC ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL O
+1D5FD ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL P
+1D5FE ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL Q
+1D5FF ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL R
+1D600 ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL S
+1D601 ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL T
+1D602 ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL U
+1D603 ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL V
+1D604 ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL W
+1D605 ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL X
+1D606 ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL Y
+1D607 ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL Z
+1D608 ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL A
+1D609 ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL B
+1D60A ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL C
+1D60B ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL D
+1D60C ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL E
+1D60D ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL F
+1D60E ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL G
+1D60F ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL H
+1D610 ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL I
+1D611 ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL J
+1D612 ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL K
+1D613 ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL L
+1D614 ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL M
+1D615 ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL N
+1D616 ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL O
+1D617 ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL P
+1D618 ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q
+1D619 ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL R
+1D61A ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL S
+1D61B ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL T
+1D61C ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL U
+1D61D ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL V
+1D61E ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL W
+1D61F ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL X
+1D620 ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y
+1D621 ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z
+1D622 ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL A
+1D623 ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL B
+1D624 ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL C
+1D625 ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL D
+1D626 ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL E
+1D627 ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL F
+1D628 ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL G
+1D629 ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL H
+1D62A ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL I
+1D62B ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL J
+1D62C ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL K
+1D62D ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL L
+1D62E ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL M
+1D62F ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL N
+1D630 ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL O
+1D631 ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL P
+1D632 ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL Q
+1D633 ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL R
+1D634 ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL S
+1D635 ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL T
+1D636 ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL U
+1D637 ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL V
+1D638 ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL W
+1D639 ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL X
+1D63A ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL Y
+1D63B ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF ITALIC SMALL Z
+1D63C ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A
+1D63D ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B
+1D63E ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C
+1D63F ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D
+1D640 ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E
+1D641 ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F
+1D642 ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G
+1D643 ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H
+1D644 ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I
+1D645 ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J
+1D646 ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K
+1D647 ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L
+1D648 ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M
+1D649 ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N
+1D64A ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O
+1D64B ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P
+1D64C ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q
+1D64D ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R
+1D64E ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S
+1D64F ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T
+1D650 ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U
+1D651 ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V
+1D652 ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W
+1D653 ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X
+1D654 ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y
+1D655 ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z
+1D656 ; mapped ; 0061 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A
+1D657 ; mapped ; 0062 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B
+1D658 ; mapped ; 0063 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C
+1D659 ; mapped ; 0064 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D
+1D65A ; mapped ; 0065 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E
+1D65B ; mapped ; 0066 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F
+1D65C ; mapped ; 0067 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G
+1D65D ; mapped ; 0068 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H
+1D65E ; mapped ; 0069 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I
+1D65F ; mapped ; 006A # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
+1D660 ; mapped ; 006B # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K
+1D661 ; mapped ; 006C # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L
+1D662 ; mapped ; 006D # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M
+1D663 ; mapped ; 006E # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N
+1D664 ; mapped ; 006F # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O
+1D665 ; mapped ; 0070 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P
+1D666 ; mapped ; 0071 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q
+1D667 ; mapped ; 0072 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R
+1D668 ; mapped ; 0073 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S
+1D669 ; mapped ; 0074 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T
+1D66A ; mapped ; 0075 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U
+1D66B ; mapped ; 0076 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V
+1D66C ; mapped ; 0077 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W
+1D66D ; mapped ; 0078 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X
+1D66E ; mapped ; 0079 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y
+1D66F ; mapped ; 007A # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z
+1D670 ; mapped ; 0061 # 3.1 MATHEMATICAL MONOSPACE CAPITAL A
+1D671 ; mapped ; 0062 # 3.1 MATHEMATICAL MONOSPACE CAPITAL B
+1D672 ; mapped ; 0063 # 3.1 MATHEMATICAL MONOSPACE CAPITAL C
+1D673 ; mapped ; 0064 # 3.1 MATHEMATICAL MONOSPACE CAPITAL D
+1D674 ; mapped ; 0065 # 3.1 MATHEMATICAL MONOSPACE CAPITAL E
+1D675 ; mapped ; 0066 # 3.1 MATHEMATICAL MONOSPACE CAPITAL F
+1D676 ; mapped ; 0067 # 3.1 MATHEMATICAL MONOSPACE CAPITAL G
+1D677 ; mapped ; 0068 # 3.1 MATHEMATICAL MONOSPACE CAPITAL H
+1D678 ; mapped ; 0069 # 3.1 MATHEMATICAL MONOSPACE CAPITAL I
+1D679 ; mapped ; 006A # 3.1 MATHEMATICAL MONOSPACE CAPITAL J
+1D67A ; mapped ; 006B # 3.1 MATHEMATICAL MONOSPACE CAPITAL K
+1D67B ; mapped ; 006C # 3.1 MATHEMATICAL MONOSPACE CAPITAL L
+1D67C ; mapped ; 006D # 3.1 MATHEMATICAL MONOSPACE CAPITAL M
+1D67D ; mapped ; 006E # 3.1 MATHEMATICAL MONOSPACE CAPITAL N
+1D67E ; mapped ; 006F # 3.1 MATHEMATICAL MONOSPACE CAPITAL O
+1D67F ; mapped ; 0070 # 3.1 MATHEMATICAL MONOSPACE CAPITAL P
+1D680 ; mapped ; 0071 # 3.1 MATHEMATICAL MONOSPACE CAPITAL Q
+1D681 ; mapped ; 0072 # 3.1 MATHEMATICAL MONOSPACE CAPITAL R
+1D682 ; mapped ; 0073 # 3.1 MATHEMATICAL MONOSPACE CAPITAL S
+1D683 ; mapped ; 0074 # 3.1 MATHEMATICAL MONOSPACE CAPITAL T
+1D684 ; mapped ; 0075 # 3.1 MATHEMATICAL MONOSPACE CAPITAL U
+1D685 ; mapped ; 0076 # 3.1 MATHEMATICAL MONOSPACE CAPITAL V
+1D686 ; mapped ; 0077 # 3.1 MATHEMATICAL MONOSPACE CAPITAL W
+1D687 ; mapped ; 0078 # 3.1 MATHEMATICAL MONOSPACE CAPITAL X
+1D688 ; mapped ; 0079 # 3.1 MATHEMATICAL MONOSPACE CAPITAL Y
+1D689 ; mapped ; 007A # 3.1 MATHEMATICAL MONOSPACE CAPITAL Z
+1D68A ; mapped ; 0061 # 3.1 MATHEMATICAL MONOSPACE SMALL A
+1D68B ; mapped ; 0062 # 3.1 MATHEMATICAL MONOSPACE SMALL B
+1D68C ; mapped ; 0063 # 3.1 MATHEMATICAL MONOSPACE SMALL C
+1D68D ; mapped ; 0064 # 3.1 MATHEMATICAL MONOSPACE SMALL D
+1D68E ; mapped ; 0065 # 3.1 MATHEMATICAL MONOSPACE SMALL E
+1D68F ; mapped ; 0066 # 3.1 MATHEMATICAL MONOSPACE SMALL F
+1D690 ; mapped ; 0067 # 3.1 MATHEMATICAL MONOSPACE SMALL G
+1D691 ; mapped ; 0068 # 3.1 MATHEMATICAL MONOSPACE SMALL H
+1D692 ; mapped ; 0069 # 3.1 MATHEMATICAL MONOSPACE SMALL I
+1D693 ; mapped ; 006A # 3.1 MATHEMATICAL MONOSPACE SMALL J
+1D694 ; mapped ; 006B # 3.1 MATHEMATICAL MONOSPACE SMALL K
+1D695 ; mapped ; 006C # 3.1 MATHEMATICAL MONOSPACE SMALL L
+1D696 ; mapped ; 006D # 3.1 MATHEMATICAL MONOSPACE SMALL M
+1D697 ; mapped ; 006E # 3.1 MATHEMATICAL MONOSPACE SMALL N
+1D698 ; mapped ; 006F # 3.1 MATHEMATICAL MONOSPACE SMALL O
+1D699 ; mapped ; 0070 # 3.1 MATHEMATICAL MONOSPACE SMALL P
+1D69A ; mapped ; 0071 # 3.1 MATHEMATICAL MONOSPACE SMALL Q
+1D69B ; mapped ; 0072 # 3.1 MATHEMATICAL MONOSPACE SMALL R
+1D69C ; mapped ; 0073 # 3.1 MATHEMATICAL MONOSPACE SMALL S
+1D69D ; mapped ; 0074 # 3.1 MATHEMATICAL MONOSPACE SMALL T
+1D69E ; mapped ; 0075 # 3.1 MATHEMATICAL MONOSPACE SMALL U
+1D69F ; mapped ; 0076 # 3.1 MATHEMATICAL MONOSPACE SMALL V
+1D6A0 ; mapped ; 0077 # 3.1 MATHEMATICAL MONOSPACE SMALL W
+1D6A1 ; mapped ; 0078 # 3.1 MATHEMATICAL MONOSPACE SMALL X
+1D6A2 ; mapped ; 0079 # 3.1 MATHEMATICAL MONOSPACE SMALL Y
+1D6A3 ; mapped ; 007A # 3.1 MATHEMATICAL MONOSPACE SMALL Z
+1D6A4 ; mapped ; 0131 # 4.1 MATHEMATICAL ITALIC SMALL DOTLESS I
+1D6A5 ; mapped ; 0237 # 4.1 MATHEMATICAL ITALIC SMALL DOTLESS J
+1D6A6..1D6A7 ; disallowed # NA <reserved-1D6A6>..<reserved-1D6A7>
+1D6A8 ; mapped ; 03B1 # 3.1 MATHEMATICAL BOLD CAPITAL ALPHA
+1D6A9 ; mapped ; 03B2 # 3.1 MATHEMATICAL BOLD CAPITAL BETA
+1D6AA ; mapped ; 03B3 # 3.1 MATHEMATICAL BOLD CAPITAL GAMMA
+1D6AB ; mapped ; 03B4 # 3.1 MATHEMATICAL BOLD CAPITAL DELTA
+1D6AC ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD CAPITAL EPSILON
+1D6AD ; mapped ; 03B6 # 3.1 MATHEMATICAL BOLD CAPITAL ZETA
+1D6AE ; mapped ; 03B7 # 3.1 MATHEMATICAL BOLD CAPITAL ETA
+1D6AF ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD CAPITAL THETA
+1D6B0 ; mapped ; 03B9 # 3.1 MATHEMATICAL BOLD CAPITAL IOTA
+1D6B1 ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD CAPITAL KAPPA
+1D6B2 ; mapped ; 03BB # 3.1 MATHEMATICAL BOLD CAPITAL LAMDA
+1D6B3 ; mapped ; 03BC # 3.1 MATHEMATICAL BOLD CAPITAL MU
+1D6B4 ; mapped ; 03BD # 3.1 MATHEMATICAL BOLD CAPITAL NU
+1D6B5 ; mapped ; 03BE # 3.1 MATHEMATICAL BOLD CAPITAL XI
+1D6B6 ; mapped ; 03BF # 3.1 MATHEMATICAL BOLD CAPITAL OMICRON
+1D6B7 ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD CAPITAL PI
+1D6B8 ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD CAPITAL RHO
+1D6B9 ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD CAPITAL THETA SYMBOL
+1D6BA ; mapped ; 03C3 # 3.1 MATHEMATICAL BOLD CAPITAL SIGMA
+1D6BB ; mapped ; 03C4 # 3.1 MATHEMATICAL BOLD CAPITAL TAU
+1D6BC ; mapped ; 03C5 # 3.1 MATHEMATICAL BOLD CAPITAL UPSILON
+1D6BD ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD CAPITAL PHI
+1D6BE ; mapped ; 03C7 # 3.1 MATHEMATICAL BOLD CAPITAL CHI
+1D6BF ; mapped ; 03C8 # 3.1 MATHEMATICAL BOLD CAPITAL PSI
+1D6C0 ; mapped ; 03C9 # 3.1 MATHEMATICAL BOLD CAPITAL OMEGA
+1D6C1 ; mapped ; 2207 # 3.1 MATHEMATICAL BOLD NABLA
+1D6C2 ; mapped ; 03B1 # 3.1 MATHEMATICAL BOLD SMALL ALPHA
+1D6C3 ; mapped ; 03B2 # 3.1 MATHEMATICAL BOLD SMALL BETA
+1D6C4 ; mapped ; 03B3 # 3.1 MATHEMATICAL BOLD SMALL GAMMA
+1D6C5 ; mapped ; 03B4 # 3.1 MATHEMATICAL BOLD SMALL DELTA
+1D6C6 ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD SMALL EPSILON
+1D6C7 ; mapped ; 03B6 # 3.1 MATHEMATICAL BOLD SMALL ZETA
+1D6C8 ; mapped ; 03B7 # 3.1 MATHEMATICAL BOLD SMALL ETA
+1D6C9 ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD SMALL THETA
+1D6CA ; mapped ; 03B9 # 3.1 MATHEMATICAL BOLD SMALL IOTA
+1D6CB ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD SMALL KAPPA
+1D6CC ; mapped ; 03BB # 3.1 MATHEMATICAL BOLD SMALL LAMDA
+1D6CD ; mapped ; 03BC # 3.1 MATHEMATICAL BOLD SMALL MU
+1D6CE ; mapped ; 03BD # 3.1 MATHEMATICAL BOLD SMALL NU
+1D6CF ; mapped ; 03BE # 3.1 MATHEMATICAL BOLD SMALL XI
+1D6D0 ; mapped ; 03BF # 3.1 MATHEMATICAL BOLD SMALL OMICRON
+1D6D1 ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD SMALL PI
+1D6D2 ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD SMALL RHO
+1D6D3..1D6D4 ; mapped ; 03C3 # 3.1 MATHEMATICAL BOLD SMALL FINAL SIGMA..MATHEMATICAL BOLD SMALL SIGMA
+1D6D5 ; mapped ; 03C4 # 3.1 MATHEMATICAL BOLD SMALL TAU
+1D6D6 ; mapped ; 03C5 # 3.1 MATHEMATICAL BOLD SMALL UPSILON
+1D6D7 ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD SMALL PHI
+1D6D8 ; mapped ; 03C7 # 3.1 MATHEMATICAL BOLD SMALL CHI
+1D6D9 ; mapped ; 03C8 # 3.1 MATHEMATICAL BOLD SMALL PSI
+1D6DA ; mapped ; 03C9 # 3.1 MATHEMATICAL BOLD SMALL OMEGA
+1D6DB ; mapped ; 2202 # 3.1 MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
+1D6DC ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD EPSILON SYMBOL
+1D6DD ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD THETA SYMBOL
+1D6DE ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD KAPPA SYMBOL
+1D6DF ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD PHI SYMBOL
+1D6E0 ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD RHO SYMBOL
+1D6E1 ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD PI SYMBOL
+1D6E2 ; mapped ; 03B1 # 3.1 MATHEMATICAL ITALIC CAPITAL ALPHA
+1D6E3 ; mapped ; 03B2 # 3.1 MATHEMATICAL ITALIC CAPITAL BETA
+1D6E4 ; mapped ; 03B3 # 3.1 MATHEMATICAL ITALIC CAPITAL GAMMA
+1D6E5 ; mapped ; 03B4 # 3.1 MATHEMATICAL ITALIC CAPITAL DELTA
+1D6E6 ; mapped ; 03B5 # 3.1 MATHEMATICAL ITALIC CAPITAL EPSILON
+1D6E7 ; mapped ; 03B6 # 3.1 MATHEMATICAL ITALIC CAPITAL ZETA
+1D6E8 ; mapped ; 03B7 # 3.1 MATHEMATICAL ITALIC CAPITAL ETA
+1D6E9 ; mapped ; 03B8 # 3.1 MATHEMATICAL ITALIC CAPITAL THETA
+1D6EA ; mapped ; 03B9 # 3.1 MATHEMATICAL ITALIC CAPITAL IOTA
+1D6EB ; mapped ; 03BA # 3.1 MATHEMATICAL ITALIC CAPITAL KAPPA
+1D6EC ; mapped ; 03BB # 3.1 MATHEMATICAL ITALIC CAPITAL LAMDA
+1D6ED ; mapped ; 03BC # 3.1 MATHEMATICAL ITALIC CAPITAL MU
+1D6EE ; mapped ; 03BD # 3.1 MATHEMATICAL ITALIC CAPITAL NU
+1D6EF ; mapped ; 03BE # 3.1 MATHEMATICAL ITALIC CAPITAL XI
+1D6F0 ; mapped ; 03BF # 3.1 MATHEMATICAL ITALIC CAPITAL OMICRON
+1D6F1 ; mapped ; 03C0 # 3.1 MATHEMATICAL ITALIC CAPITAL PI
+1D6F2 ; mapped ; 03C1 # 3.1 MATHEMATICAL ITALIC CAPITAL RHO
+1D6F3 ; mapped ; 03B8 # 3.1 MATHEMATICAL ITALIC CAPITAL THETA SYMBOL
+1D6F4 ; mapped ; 03C3 # 3.1 MATHEMATICAL ITALIC CAPITAL SIGMA
+1D6F5 ; mapped ; 03C4 # 3.1 MATHEMATICAL ITALIC CAPITAL TAU
+1D6F6 ; mapped ; 03C5 # 3.1 MATHEMATICAL ITALIC CAPITAL UPSILON
+1D6F7 ; mapped ; 03C6 # 3.1 MATHEMATICAL ITALIC CAPITAL PHI
+1D6F8 ; mapped ; 03C7 # 3.1 MATHEMATICAL ITALIC CAPITAL CHI
+1D6F9 ; mapped ; 03C8 # 3.1 MATHEMATICAL ITALIC CAPITAL PSI
+1D6FA ; mapped ; 03C9 # 3.1 MATHEMATICAL ITALIC CAPITAL OMEGA
+1D6FB ; mapped ; 2207 # 3.1 MATHEMATICAL ITALIC NABLA
+1D6FC ; mapped ; 03B1 # 3.1 MATHEMATICAL ITALIC SMALL ALPHA
+1D6FD ; mapped ; 03B2 # 3.1 MATHEMATICAL ITALIC SMALL BETA
+1D6FE ; mapped ; 03B3 # 3.1 MATHEMATICAL ITALIC SMALL GAMMA
+1D6FF ; mapped ; 03B4 # 3.1 MATHEMATICAL ITALIC SMALL DELTA
+1D700 ; mapped ; 03B5 # 3.1 MATHEMATICAL ITALIC SMALL EPSILON
+1D701 ; mapped ; 03B6 # 3.1 MATHEMATICAL ITALIC SMALL ZETA
+1D702 ; mapped ; 03B7 # 3.1 MATHEMATICAL ITALIC SMALL ETA
+1D703 ; mapped ; 03B8 # 3.1 MATHEMATICAL ITALIC SMALL THETA
+1D704 ; mapped ; 03B9 # 3.1 MATHEMATICAL ITALIC SMALL IOTA
+1D705 ; mapped ; 03BA # 3.1 MATHEMATICAL ITALIC SMALL KAPPA
+1D706 ; mapped ; 03BB # 3.1 MATHEMATICAL ITALIC SMALL LAMDA
+1D707 ; mapped ; 03BC # 3.1 MATHEMATICAL ITALIC SMALL MU
+1D708 ; mapped ; 03BD # 3.1 MATHEMATICAL ITALIC SMALL NU
+1D709 ; mapped ; 03BE # 3.1 MATHEMATICAL ITALIC SMALL XI
+1D70A ; mapped ; 03BF # 3.1 MATHEMATICAL ITALIC SMALL OMICRON
+1D70B ; mapped ; 03C0 # 3.1 MATHEMATICAL ITALIC SMALL PI
+1D70C ; mapped ; 03C1 # 3.1 MATHEMATICAL ITALIC SMALL RHO
+1D70D..1D70E ; mapped ; 03C3 # 3.1 MATHEMATICAL ITALIC SMALL FINAL SIGMA..MATHEMATICAL ITALIC SMALL SIGMA
+1D70F ; mapped ; 03C4 # 3.1 MATHEMATICAL ITALIC SMALL TAU
+1D710 ; mapped ; 03C5 # 3.1 MATHEMATICAL ITALIC SMALL UPSILON
+1D711 ; mapped ; 03C6 # 3.1 MATHEMATICAL ITALIC SMALL PHI
+1D712 ; mapped ; 03C7 # 3.1 MATHEMATICAL ITALIC SMALL CHI
+1D713 ; mapped ; 03C8 # 3.1 MATHEMATICAL ITALIC SMALL PSI
+1D714 ; mapped ; 03C9 # 3.1 MATHEMATICAL ITALIC SMALL OMEGA
+1D715 ; mapped ; 2202 # 3.1 MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
+1D716 ; mapped ; 03B5 # 3.1 MATHEMATICAL ITALIC EPSILON SYMBOL
+1D717 ; mapped ; 03B8 # 3.1 MATHEMATICAL ITALIC THETA SYMBOL
+1D718 ; mapped ; 03BA # 3.1 MATHEMATICAL ITALIC KAPPA SYMBOL
+1D719 ; mapped ; 03C6 # 3.1 MATHEMATICAL ITALIC PHI SYMBOL
+1D71A ; mapped ; 03C1 # 3.1 MATHEMATICAL ITALIC RHO SYMBOL
+1D71B ; mapped ; 03C0 # 3.1 MATHEMATICAL ITALIC PI SYMBOL
+1D71C ; mapped ; 03B1 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL ALPHA
+1D71D ; mapped ; 03B2 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL BETA
+1D71E ; mapped ; 03B3 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL GAMMA
+1D71F ; mapped ; 03B4 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL DELTA
+1D720 ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL EPSILON
+1D721 ; mapped ; 03B6 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL ZETA
+1D722 ; mapped ; 03B7 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL ETA
+1D723 ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL THETA
+1D724 ; mapped ; 03B9 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL IOTA
+1D725 ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL KAPPA
+1D726 ; mapped ; 03BB # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL LAMDA
+1D727 ; mapped ; 03BC # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL MU
+1D728 ; mapped ; 03BD # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL NU
+1D729 ; mapped ; 03BE # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL XI
+1D72A ; mapped ; 03BF # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL OMICRON
+1D72B ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL PI
+1D72C ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL RHO
+1D72D ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL
+1D72E ; mapped ; 03C3 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL SIGMA
+1D72F ; mapped ; 03C4 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL TAU
+1D730 ; mapped ; 03C5 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL UPSILON
+1D731 ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL PHI
+1D732 ; mapped ; 03C7 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL CHI
+1D733 ; mapped ; 03C8 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL PSI
+1D734 ; mapped ; 03C9 # 3.1 MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
+1D735 ; mapped ; 2207 # 3.1 MATHEMATICAL BOLD ITALIC NABLA
+1D736 ; mapped ; 03B1 # 3.1 MATHEMATICAL BOLD ITALIC SMALL ALPHA
+1D737 ; mapped ; 03B2 # 3.1 MATHEMATICAL BOLD ITALIC SMALL BETA
+1D738 ; mapped ; 03B3 # 3.1 MATHEMATICAL BOLD ITALIC SMALL GAMMA
+1D739 ; mapped ; 03B4 # 3.1 MATHEMATICAL BOLD ITALIC SMALL DELTA
+1D73A ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD ITALIC SMALL EPSILON
+1D73B ; mapped ; 03B6 # 3.1 MATHEMATICAL BOLD ITALIC SMALL ZETA
+1D73C ; mapped ; 03B7 # 3.1 MATHEMATICAL BOLD ITALIC SMALL ETA
+1D73D ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD ITALIC SMALL THETA
+1D73E ; mapped ; 03B9 # 3.1 MATHEMATICAL BOLD ITALIC SMALL IOTA
+1D73F ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD ITALIC SMALL KAPPA
+1D740 ; mapped ; 03BB # 3.1 MATHEMATICAL BOLD ITALIC SMALL LAMDA
+1D741 ; mapped ; 03BC # 3.1 MATHEMATICAL BOLD ITALIC SMALL MU
+1D742 ; mapped ; 03BD # 3.1 MATHEMATICAL BOLD ITALIC SMALL NU
+1D743 ; mapped ; 03BE # 3.1 MATHEMATICAL BOLD ITALIC SMALL XI
+1D744 ; mapped ; 03BF # 3.1 MATHEMATICAL BOLD ITALIC SMALL OMICRON
+1D745 ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD ITALIC SMALL PI
+1D746 ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD ITALIC SMALL RHO
+1D747..1D748 ; mapped ; 03C3 # 3.1 MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA..MATHEMATICAL BOLD ITALIC SMALL SIGMA
+1D749 ; mapped ; 03C4 # 3.1 MATHEMATICAL BOLD ITALIC SMALL TAU
+1D74A ; mapped ; 03C5 # 3.1 MATHEMATICAL BOLD ITALIC SMALL UPSILON
+1D74B ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD ITALIC SMALL PHI
+1D74C ; mapped ; 03C7 # 3.1 MATHEMATICAL BOLD ITALIC SMALL CHI
+1D74D ; mapped ; 03C8 # 3.1 MATHEMATICAL BOLD ITALIC SMALL PSI
+1D74E ; mapped ; 03C9 # 3.1 MATHEMATICAL BOLD ITALIC SMALL OMEGA
+1D74F ; mapped ; 2202 # 3.1 MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
+1D750 ; mapped ; 03B5 # 3.1 MATHEMATICAL BOLD ITALIC EPSILON SYMBOL
+1D751 ; mapped ; 03B8 # 3.1 MATHEMATICAL BOLD ITALIC THETA SYMBOL
+1D752 ; mapped ; 03BA # 3.1 MATHEMATICAL BOLD ITALIC KAPPA SYMBOL
+1D753 ; mapped ; 03C6 # 3.1 MATHEMATICAL BOLD ITALIC PHI SYMBOL
+1D754 ; mapped ; 03C1 # 3.1 MATHEMATICAL BOLD ITALIC RHO SYMBOL
+1D755 ; mapped ; 03C0 # 3.1 MATHEMATICAL BOLD ITALIC PI SYMBOL
+1D756 ; mapped ; 03B1 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA
+1D757 ; mapped ; 03B2 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA
+1D758 ; mapped ; 03B3 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA
+1D759 ; mapped ; 03B4 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA
+1D75A ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON
+1D75B ; mapped ; 03B6 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA
+1D75C ; mapped ; 03B7 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA
+1D75D ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA
+1D75E ; mapped ; 03B9 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA
+1D75F ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA
+1D760 ; mapped ; 03BB # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA
+1D761 ; mapped ; 03BC # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL MU
+1D762 ; mapped ; 03BD # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL NU
+1D763 ; mapped ; 03BE # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL XI
+1D764 ; mapped ; 03BF # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON
+1D765 ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL PI
+1D766 ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO
+1D767 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL
+1D768 ; mapped ; 03C3 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA
+1D769 ; mapped ; 03C4 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU
+1D76A ; mapped ; 03C5 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON
+1D76B ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI
+1D76C ; mapped ; 03C7 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI
+1D76D ; mapped ; 03C8 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI
+1D76E ; mapped ; 03C9 # 3.1 MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
+1D76F ; mapped ; 2207 # 3.1 MATHEMATICAL SANS-SERIF BOLD NABLA
+1D770 ; mapped ; 03B1 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA
+1D771 ; mapped ; 03B2 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL BETA
+1D772 ; mapped ; 03B3 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA
+1D773 ; mapped ; 03B4 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL DELTA
+1D774 ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON
+1D775 ; mapped ; 03B6 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL ZETA
+1D776 ; mapped ; 03B7 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL ETA
+1D777 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL THETA
+1D778 ; mapped ; 03B9 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL IOTA
+1D779 ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA
+1D77A ; mapped ; 03BB # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA
+1D77B ; mapped ; 03BC # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL MU
+1D77C ; mapped ; 03BD # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL NU
+1D77D ; mapped ; 03BE # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL XI
+1D77E ; mapped ; 03BF # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON
+1D77F ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL PI
+1D780 ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL RHO
+1D781..1D782 ; mapped ; 03C3 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA..MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA
+1D783 ; mapped ; 03C4 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL TAU
+1D784 ; mapped ; 03C5 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON
+1D785 ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL PHI
+1D786 ; mapped ; 03C7 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL CHI
+1D787 ; mapped ; 03C8 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL PSI
+1D788 ; mapped ; 03C9 # 3.1 MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
+1D789 ; mapped ; 2202 # 3.1 MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
+1D78A ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL
+1D78B ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL
+1D78C ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL
+1D78D ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL
+1D78E ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL
+1D78F ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD PI SYMBOL
+1D790 ; mapped ; 03B1 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA
+1D791 ; mapped ; 03B2 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA
+1D792 ; mapped ; 03B3 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA
+1D793 ; mapped ; 03B4 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA
+1D794 ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON
+1D795 ; mapped ; 03B6 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA
+1D796 ; mapped ; 03B7 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA
+1D797 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA
+1D798 ; mapped ; 03B9 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA
+1D799 ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA
+1D79A ; mapped ; 03BB # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA
+1D79B ; mapped ; 03BC # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU
+1D79C ; mapped ; 03BD # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU
+1D79D ; mapped ; 03BE # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI
+1D79E ; mapped ; 03BF # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON
+1D79F ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI
+1D7A0 ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO
+1D7A1 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL
+1D7A2 ; mapped ; 03C3 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA
+1D7A3 ; mapped ; 03C4 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU
+1D7A4 ; mapped ; 03C5 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON
+1D7A5 ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI
+1D7A6 ; mapped ; 03C7 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI
+1D7A7 ; mapped ; 03C8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI
+1D7A8 ; mapped ; 03C9 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
+1D7A9 ; mapped ; 2207 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
+1D7AA ; mapped ; 03B1 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA
+1D7AB ; mapped ; 03B2 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA
+1D7AC ; mapped ; 03B3 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA
+1D7AD ; mapped ; 03B4 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA
+1D7AE ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON
+1D7AF ; mapped ; 03B6 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA
+1D7B0 ; mapped ; 03B7 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA
+1D7B1 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA
+1D7B2 ; mapped ; 03B9 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA
+1D7B3 ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA
+1D7B4 ; mapped ; 03BB # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA
+1D7B5 ; mapped ; 03BC # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU
+1D7B6 ; mapped ; 03BD # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU
+1D7B7 ; mapped ; 03BE # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI
+1D7B8 ; mapped ; 03BF # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON
+1D7B9 ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI
+1D7BA ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO
+1D7BB..1D7BC ; mapped ; 03C3 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA
+1D7BD ; mapped ; 03C4 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU
+1D7BE ; mapped ; 03C5 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON
+1D7BF ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI
+1D7C0 ; mapped ; 03C7 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI
+1D7C1 ; mapped ; 03C8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI
+1D7C2 ; mapped ; 03C9 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
+1D7C3 ; mapped ; 2202 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
+1D7C4 ; mapped ; 03B5 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL
+1D7C5 ; mapped ; 03B8 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL
+1D7C6 ; mapped ; 03BA # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL
+1D7C7 ; mapped ; 03C6 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL
+1D7C8 ; mapped ; 03C1 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL
+1D7C9 ; mapped ; 03C0 # 3.1 MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL
+1D7CA..1D7CB ; mapped ; 03DD # 5.0 MATHEMATICAL BOLD CAPITAL DIGAMMA..MATHEMATICAL BOLD SMALL DIGAMMA
+1D7CC..1D7CD ; disallowed # NA <reserved-1D7CC>..<reserved-1D7CD>
+1D7CE ; mapped ; 0030 # 3.1 MATHEMATICAL BOLD DIGIT ZERO
+1D7CF ; mapped ; 0031 # 3.1 MATHEMATICAL BOLD DIGIT ONE
+1D7D0 ; mapped ; 0032 # 3.1 MATHEMATICAL BOLD DIGIT TWO
+1D7D1 ; mapped ; 0033 # 3.1 MATHEMATICAL BOLD DIGIT THREE
+1D7D2 ; mapped ; 0034 # 3.1 MATHEMATICAL BOLD DIGIT FOUR
+1D7D3 ; mapped ; 0035 # 3.1 MATHEMATICAL BOLD DIGIT FIVE
+1D7D4 ; mapped ; 0036 # 3.1 MATHEMATICAL BOLD DIGIT SIX
+1D7D5 ; mapped ; 0037 # 3.1 MATHEMATICAL BOLD DIGIT SEVEN
+1D7D6 ; mapped ; 0038 # 3.1 MATHEMATICAL BOLD DIGIT EIGHT
+1D7D7 ; mapped ; 0039 # 3.1 MATHEMATICAL BOLD DIGIT NINE
+1D7D8 ; mapped ; 0030 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO
+1D7D9 ; mapped ; 0031 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT ONE
+1D7DA ; mapped ; 0032 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT TWO
+1D7DB ; mapped ; 0033 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT THREE
+1D7DC ; mapped ; 0034 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR
+1D7DD ; mapped ; 0035 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE
+1D7DE ; mapped ; 0036 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT SIX
+1D7DF ; mapped ; 0037 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN
+1D7E0 ; mapped ; 0038 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT
+1D7E1 ; mapped ; 0039 # 3.1 MATHEMATICAL DOUBLE-STRUCK DIGIT NINE
+1D7E2 ; mapped ; 0030 # 3.1 MATHEMATICAL SANS-SERIF DIGIT ZERO
+1D7E3 ; mapped ; 0031 # 3.1 MATHEMATICAL SANS-SERIF DIGIT ONE
+1D7E4 ; mapped ; 0032 # 3.1 MATHEMATICAL SANS-SERIF DIGIT TWO
+1D7E5 ; mapped ; 0033 # 3.1 MATHEMATICAL SANS-SERIF DIGIT THREE
+1D7E6 ; mapped ; 0034 # 3.1 MATHEMATICAL SANS-SERIF DIGIT FOUR
+1D7E7 ; mapped ; 0035 # 3.1 MATHEMATICAL SANS-SERIF DIGIT FIVE
+1D7E8 ; mapped ; 0036 # 3.1 MATHEMATICAL SANS-SERIF DIGIT SIX
+1D7E9 ; mapped ; 0037 # 3.1 MATHEMATICAL SANS-SERIF DIGIT SEVEN
+1D7EA ; mapped ; 0038 # 3.1 MATHEMATICAL SANS-SERIF DIGIT EIGHT
+1D7EB ; mapped ; 0039 # 3.1 MATHEMATICAL SANS-SERIF DIGIT NINE
+1D7EC ; mapped ; 0030 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO
+1D7ED ; mapped ; 0031 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT ONE
+1D7EE ; mapped ; 0032 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT TWO
+1D7EF ; mapped ; 0033 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT THREE
+1D7F0 ; mapped ; 0034 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR
+1D7F1 ; mapped ; 0035 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE
+1D7F2 ; mapped ; 0036 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT SIX
+1D7F3 ; mapped ; 0037 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN
+1D7F4 ; mapped ; 0038 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT
+1D7F5 ; mapped ; 0039 # 3.1 MATHEMATICAL SANS-SERIF BOLD DIGIT NINE
+1D7F6 ; mapped ; 0030 # 3.1 MATHEMATICAL MONOSPACE DIGIT ZERO
+1D7F7 ; mapped ; 0031 # 3.1 MATHEMATICAL MONOSPACE DIGIT ONE
+1D7F8 ; mapped ; 0032 # 3.1 MATHEMATICAL MONOSPACE DIGIT TWO
+1D7F9 ; mapped ; 0033 # 3.1 MATHEMATICAL MONOSPACE DIGIT THREE
+1D7FA ; mapped ; 0034 # 3.1 MATHEMATICAL MONOSPACE DIGIT FOUR
+1D7FB ; mapped ; 0035 # 3.1 MATHEMATICAL MONOSPACE DIGIT FIVE
+1D7FC ; mapped ; 0036 # 3.1 MATHEMATICAL MONOSPACE DIGIT SIX
+1D7FD ; mapped ; 0037 # 3.1 MATHEMATICAL MONOSPACE DIGIT SEVEN
+1D7FE ; mapped ; 0038 # 3.1 MATHEMATICAL MONOSPACE DIGIT EIGHT
+1D7FF ; mapped ; 0039 # 3.1 MATHEMATICAL MONOSPACE DIGIT NINE
+1D800..1D9FF ; valid ; ; NV8 # 8.0 SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
+1DA00..1DA36 ; valid # 8.0 SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37..1DA3A ; valid ; ; NV8 # 8.0 SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B..1DA6C ; valid # 8.0 SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D..1DA74 ; valid ; ; NV8 # 8.0 SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75 ; valid # 8.0 SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76..1DA83 ; valid ; ; NV8 # 8.0 SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84 ; valid # 8.0 SIGNWRITING LOCATION HEAD NECK
+1DA85..1DA8B ; valid ; ; NV8 # 8.0 SIGNWRITING LOCATION TORSO..SIGNWRITING PARENTHESIS
+1DA8C..1DA9A ; disallowed # NA <reserved-1DA8C>..<reserved-1DA9A>
+1DA9B..1DA9F ; valid # 8.0 SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA0 ; disallowed # NA <reserved-1DAA0>
+1DAA1..1DAAF ; valid # 8.0 SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+1DAB0..1DEFF ; disallowed # NA <reserved-1DAB0>..<reserved-1DEFF>
+1DF00..1DF1E ; valid # 14.0 LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER S WITH CURL
+1DF1F..1DFFF ; disallowed # NA <reserved-1DF1F>..<reserved-1DFFF>
+1E000..1E006 ; valid # 9.0 COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
+1E007 ; disallowed # NA <reserved-1E007>
+1E008..1E018 ; valid # 9.0 COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
+1E019..1E01A ; disallowed # NA <reserved-1E019>..<reserved-1E01A>
+1E01B..1E021 ; valid # 9.0 COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
+1E022 ; disallowed # NA <reserved-1E022>
+1E023..1E024 ; valid # 9.0 COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
+1E025 ; disallowed # NA <reserved-1E025>
+1E026..1E02A ; valid # 9.0 COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
+1E02B..1E0FF ; disallowed # NA <reserved-1E02B>..<reserved-1E0FF>
+1E100..1E12C ; valid # 12.0 NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
+1E12D..1E12F ; disallowed # NA <reserved-1E12D>..<reserved-1E12F>
+1E130..1E13D ; valid # 12.0 NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
+1E13E..1E13F ; disallowed # NA <reserved-1E13E>..<reserved-1E13F>
+1E140..1E149 ; valid # 12.0 NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
+1E14A..1E14D ; disallowed # NA <reserved-1E14A>..<reserved-1E14D>
+1E14E ; valid # 12.0 NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
+1E14F ; valid ; ; NV8 # 12.0 NYIAKENG PUACHUE HMONG CIRCLED CA
+1E150..1E28F ; disallowed # NA <reserved-1E150>..<reserved-1E28F>
+1E290..1E2AE ; valid # 14.0 TOTO LETTER PA..TOTO SIGN RISING TONE
+1E2AF..1E2BF ; disallowed # NA <reserved-1E2AF>..<reserved-1E2BF>
+1E2C0..1E2F9 ; valid # 12.0 WANCHO LETTER AA..WANCHO DIGIT NINE
+1E2FA..1E2FE ; disallowed # NA <reserved-1E2FA>..<reserved-1E2FE>
+1E2FF ; valid ; ; NV8 # 12.0 WANCHO NGUN SIGN
+1E300..1E7DF ; disallowed # NA <reserved-1E300>..<reserved-1E7DF>
+1E7E0..1E7E6 ; valid # 14.0 ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO
+1E7E7 ; disallowed # NA <reserved-1E7E7>
+1E7E8..1E7EB ; valid # 14.0 ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE
+1E7EC ; disallowed # NA <reserved-1E7EC>
+1E7ED..1E7EE ; valid # 14.0 ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE
+1E7EF ; disallowed # NA <reserved-1E7EF>
+1E7F0..1E7FE ; valid # 14.0 ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE
+1E7FF ; disallowed # NA <reserved-1E7FF>
+1E800..1E8C4 ; valid # 7.0 MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
+1E8C5..1E8C6 ; disallowed # NA <reserved-1E8C5>..<reserved-1E8C6>
+1E8C7..1E8CF ; valid ; ; NV8 # 7.0 MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
+1E8D0..1E8D6 ; valid # 7.0 MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
+1E8D7..1E8FF ; disallowed # NA <reserved-1E8D7>..<reserved-1E8FF>
+1E900 ; mapped ; 1E922 # 9.0 ADLAM CAPITAL LETTER ALIF
+1E901 ; mapped ; 1E923 # 9.0 ADLAM CAPITAL LETTER DAALI
+1E902 ; mapped ; 1E924 # 9.0 ADLAM CAPITAL LETTER LAAM
+1E903 ; mapped ; 1E925 # 9.0 ADLAM CAPITAL LETTER MIIM
+1E904 ; mapped ; 1E926 # 9.0 ADLAM CAPITAL LETTER BA
+1E905 ; mapped ; 1E927 # 9.0 ADLAM CAPITAL LETTER SINNYIIYHE
+1E906 ; mapped ; 1E928 # 9.0 ADLAM CAPITAL LETTER PE
+1E907 ; mapped ; 1E929 # 9.0 ADLAM CAPITAL LETTER BHE
+1E908 ; mapped ; 1E92A # 9.0 ADLAM CAPITAL LETTER RA
+1E909 ; mapped ; 1E92B # 9.0 ADLAM CAPITAL LETTER E
+1E90A ; mapped ; 1E92C # 9.0 ADLAM CAPITAL LETTER FA
+1E90B ; mapped ; 1E92D # 9.0 ADLAM CAPITAL LETTER I
+1E90C ; mapped ; 1E92E # 9.0 ADLAM CAPITAL LETTER O
+1E90D ; mapped ; 1E92F # 9.0 ADLAM CAPITAL LETTER DHA
+1E90E ; mapped ; 1E930 # 9.0 ADLAM CAPITAL LETTER YHE
+1E90F ; mapped ; 1E931 # 9.0 ADLAM CAPITAL LETTER WAW
+1E910 ; mapped ; 1E932 # 9.0 ADLAM CAPITAL LETTER NUN
+1E911 ; mapped ; 1E933 # 9.0 ADLAM CAPITAL LETTER KAF
+1E912 ; mapped ; 1E934 # 9.0 ADLAM CAPITAL LETTER YA
+1E913 ; mapped ; 1E935 # 9.0 ADLAM CAPITAL LETTER U
+1E914 ; mapped ; 1E936 # 9.0 ADLAM CAPITAL LETTER JIIM
+1E915 ; mapped ; 1E937 # 9.0 ADLAM CAPITAL LETTER CHI
+1E916 ; mapped ; 1E938 # 9.0 ADLAM CAPITAL LETTER HA
+1E917 ; mapped ; 1E939 # 9.0 ADLAM CAPITAL LETTER QAAF
+1E918 ; mapped ; 1E93A # 9.0 ADLAM CAPITAL LETTER GA
+1E919 ; mapped ; 1E93B # 9.0 ADLAM CAPITAL LETTER NYA
+1E91A ; mapped ; 1E93C # 9.0 ADLAM CAPITAL LETTER TU
+1E91B ; mapped ; 1E93D # 9.0 ADLAM CAPITAL LETTER NHA
+1E91C ; mapped ; 1E93E # 9.0 ADLAM CAPITAL LETTER VA
+1E91D ; mapped ; 1E93F # 9.0 ADLAM CAPITAL LETTER KHA
+1E91E ; mapped ; 1E940 # 9.0 ADLAM CAPITAL LETTER GBE
+1E91F ; mapped ; 1E941 # 9.0 ADLAM CAPITAL LETTER ZAL
+1E920 ; mapped ; 1E942 # 9.0 ADLAM CAPITAL LETTER KPO
+1E921 ; mapped ; 1E943 # 9.0 ADLAM CAPITAL LETTER SHA
+1E922..1E94A ; valid # 9.0 ADLAM SMALL LETTER ALIF..ADLAM NUKTA
+1E94B ; valid # 12.0 ADLAM NASALIZATION MARK
+1E94C..1E94F ; disallowed # NA <reserved-1E94C>..<reserved-1E94F>
+1E950..1E959 ; valid # 9.0 ADLAM DIGIT ZERO..ADLAM DIGIT NINE
+1E95A..1E95D ; disallowed # NA <reserved-1E95A>..<reserved-1E95D>
+1E95E..1E95F ; valid ; ; NV8 # 9.0 ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
+1E960..1EC70 ; disallowed # NA <reserved-1E960>..<reserved-1EC70>
+1EC71..1ECB4 ; valid ; ; NV8 # 11.0 INDIC SIYAQ NUMBER ONE..INDIC SIYAQ ALTERNATE LAKH MARK
+1ECB5..1ED00 ; disallowed # NA <reserved-1ECB5>..<reserved-1ED00>
+1ED01..1ED3D ; valid ; ; NV8 # 12.0 OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ FRACTION ONE SIXTH
+1ED3E..1EDFF ; disallowed # NA <reserved-1ED3E>..<reserved-1EDFF>
+1EE00 ; mapped ; 0627 # 6.1 ARABIC MATHEMATICAL ALEF
+1EE01 ; mapped ; 0628 # 6.1 ARABIC MATHEMATICAL BEH
+1EE02 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL JEEM
+1EE03 ; mapped ; 062F # 6.1 ARABIC MATHEMATICAL DAL
+1EE04 ; disallowed # NA <reserved-1EE04>
+1EE05 ; mapped ; 0648 # 6.1 ARABIC MATHEMATICAL WAW
+1EE06 ; mapped ; 0632 # 6.1 ARABIC MATHEMATICAL ZAIN
+1EE07 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL HAH
+1EE08 ; mapped ; 0637 # 6.1 ARABIC MATHEMATICAL TAH
+1EE09 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL YEH
+1EE0A ; mapped ; 0643 # 6.1 ARABIC MATHEMATICAL KAF
+1EE0B ; mapped ; 0644 # 6.1 ARABIC MATHEMATICAL LAM
+1EE0C ; mapped ; 0645 # 6.1 ARABIC MATHEMATICAL MEEM
+1EE0D ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL NOON
+1EE0E ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL SEEN
+1EE0F ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL AIN
+1EE10 ; mapped ; 0641 # 6.1 ARABIC MATHEMATICAL FEH
+1EE11 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL SAD
+1EE12 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL QAF
+1EE13 ; mapped ; 0631 # 6.1 ARABIC MATHEMATICAL REH
+1EE14 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL SHEEN
+1EE15 ; mapped ; 062A # 6.1 ARABIC MATHEMATICAL TEH
+1EE16 ; mapped ; 062B # 6.1 ARABIC MATHEMATICAL THEH
+1EE17 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL KHAH
+1EE18 ; mapped ; 0630 # 6.1 ARABIC MATHEMATICAL THAL
+1EE19 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL DAD
+1EE1A ; mapped ; 0638 # 6.1 ARABIC MATHEMATICAL ZAH
+1EE1B ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL GHAIN
+1EE1C ; mapped ; 066E # 6.1 ARABIC MATHEMATICAL DOTLESS BEH
+1EE1D ; mapped ; 06BA # 6.1 ARABIC MATHEMATICAL DOTLESS NOON
+1EE1E ; mapped ; 06A1 # 6.1 ARABIC MATHEMATICAL DOTLESS FEH
+1EE1F ; mapped ; 066F # 6.1 ARABIC MATHEMATICAL DOTLESS QAF
+1EE20 ; disallowed # NA <reserved-1EE20>
+1EE21 ; mapped ; 0628 # 6.1 ARABIC MATHEMATICAL INITIAL BEH
+1EE22 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL INITIAL JEEM
+1EE23 ; disallowed # NA <reserved-1EE23>
+1EE24 ; mapped ; 0647 # 6.1 ARABIC MATHEMATICAL INITIAL HEH
+1EE25..1EE26 ; disallowed # NA <reserved-1EE25>..<reserved-1EE26>
+1EE27 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL INITIAL HAH
+1EE28 ; disallowed # NA <reserved-1EE28>
+1EE29 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL INITIAL YEH
+1EE2A ; mapped ; 0643 # 6.1 ARABIC MATHEMATICAL INITIAL KAF
+1EE2B ; mapped ; 0644 # 6.1 ARABIC MATHEMATICAL INITIAL LAM
+1EE2C ; mapped ; 0645 # 6.1 ARABIC MATHEMATICAL INITIAL MEEM
+1EE2D ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL INITIAL NOON
+1EE2E ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL INITIAL SEEN
+1EE2F ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL INITIAL AIN
+1EE30 ; mapped ; 0641 # 6.1 ARABIC MATHEMATICAL INITIAL FEH
+1EE31 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL INITIAL SAD
+1EE32 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL INITIAL QAF
+1EE33 ; disallowed # NA <reserved-1EE33>
+1EE34 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL INITIAL SHEEN
+1EE35 ; mapped ; 062A # 6.1 ARABIC MATHEMATICAL INITIAL TEH
+1EE36 ; mapped ; 062B # 6.1 ARABIC MATHEMATICAL INITIAL THEH
+1EE37 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL INITIAL KHAH
+1EE38 ; disallowed # NA <reserved-1EE38>
+1EE39 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL INITIAL DAD
+1EE3A ; disallowed # NA <reserved-1EE3A>
+1EE3B ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL INITIAL GHAIN
+1EE3C..1EE41 ; disallowed # NA <reserved-1EE3C>..<reserved-1EE41>
+1EE42 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL TAILED JEEM
+1EE43..1EE46 ; disallowed # NA <reserved-1EE43>..<reserved-1EE46>
+1EE47 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL TAILED HAH
+1EE48 ; disallowed # NA <reserved-1EE48>
+1EE49 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL TAILED YEH
+1EE4A ; disallowed # NA <reserved-1EE4A>
+1EE4B ; mapped ; 0644 # 6.1 ARABIC MATHEMATICAL TAILED LAM
+1EE4C ; disallowed # NA <reserved-1EE4C>
+1EE4D ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL TAILED NOON
+1EE4E ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL TAILED SEEN
+1EE4F ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL TAILED AIN
+1EE50 ; disallowed # NA <reserved-1EE50>
+1EE51 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL TAILED SAD
+1EE52 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL TAILED QAF
+1EE53 ; disallowed # NA <reserved-1EE53>
+1EE54 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL TAILED SHEEN
+1EE55..1EE56 ; disallowed # NA <reserved-1EE55>..<reserved-1EE56>
+1EE57 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL TAILED KHAH
+1EE58 ; disallowed # NA <reserved-1EE58>
+1EE59 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL TAILED DAD
+1EE5A ; disallowed # NA <reserved-1EE5A>
+1EE5B ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL TAILED GHAIN
+1EE5C ; disallowed # NA <reserved-1EE5C>
+1EE5D ; mapped ; 06BA # 6.1 ARABIC MATHEMATICAL TAILED DOTLESS NOON
+1EE5E ; disallowed # NA <reserved-1EE5E>
+1EE5F ; mapped ; 066F # 6.1 ARABIC MATHEMATICAL TAILED DOTLESS QAF
+1EE60 ; disallowed # NA <reserved-1EE60>
+1EE61 ; mapped ; 0628 # 6.1 ARABIC MATHEMATICAL STRETCHED BEH
+1EE62 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL STRETCHED JEEM
+1EE63 ; disallowed # NA <reserved-1EE63>
+1EE64 ; mapped ; 0647 # 6.1 ARABIC MATHEMATICAL STRETCHED HEH
+1EE65..1EE66 ; disallowed # NA <reserved-1EE65>..<reserved-1EE66>
+1EE67 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL STRETCHED HAH
+1EE68 ; mapped ; 0637 # 6.1 ARABIC MATHEMATICAL STRETCHED TAH
+1EE69 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL STRETCHED YEH
+1EE6A ; mapped ; 0643 # 6.1 ARABIC MATHEMATICAL STRETCHED KAF
+1EE6B ; disallowed # NA <reserved-1EE6B>
+1EE6C ; mapped ; 0645 # 6.1 ARABIC MATHEMATICAL STRETCHED MEEM
+1EE6D ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL STRETCHED NOON
+1EE6E ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL STRETCHED SEEN
+1EE6F ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL STRETCHED AIN
+1EE70 ; mapped ; 0641 # 6.1 ARABIC MATHEMATICAL STRETCHED FEH
+1EE71 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL STRETCHED SAD
+1EE72 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL STRETCHED QAF
+1EE73 ; disallowed # NA <reserved-1EE73>
+1EE74 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL STRETCHED SHEEN
+1EE75 ; mapped ; 062A # 6.1 ARABIC MATHEMATICAL STRETCHED TEH
+1EE76 ; mapped ; 062B # 6.1 ARABIC MATHEMATICAL STRETCHED THEH
+1EE77 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL STRETCHED KHAH
+1EE78 ; disallowed # NA <reserved-1EE78>
+1EE79 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL STRETCHED DAD
+1EE7A ; mapped ; 0638 # 6.1 ARABIC MATHEMATICAL STRETCHED ZAH
+1EE7B ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL STRETCHED GHAIN
+1EE7C ; mapped ; 066E # 6.1 ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
+1EE7D ; disallowed # NA <reserved-1EE7D>
+1EE7E ; mapped ; 06A1 # 6.1 ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
+1EE7F ; disallowed # NA <reserved-1EE7F>
+1EE80 ; mapped ; 0627 # 6.1 ARABIC MATHEMATICAL LOOPED ALEF
+1EE81 ; mapped ; 0628 # 6.1 ARABIC MATHEMATICAL LOOPED BEH
+1EE82 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL LOOPED JEEM
+1EE83 ; mapped ; 062F # 6.1 ARABIC MATHEMATICAL LOOPED DAL
+1EE84 ; mapped ; 0647 # 6.1 ARABIC MATHEMATICAL LOOPED HEH
+1EE85 ; mapped ; 0648 # 6.1 ARABIC MATHEMATICAL LOOPED WAW
+1EE86 ; mapped ; 0632 # 6.1 ARABIC MATHEMATICAL LOOPED ZAIN
+1EE87 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL LOOPED HAH
+1EE88 ; mapped ; 0637 # 6.1 ARABIC MATHEMATICAL LOOPED TAH
+1EE89 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL LOOPED YEH
+1EE8A ; disallowed # NA <reserved-1EE8A>
+1EE8B ; mapped ; 0644 # 6.1 ARABIC MATHEMATICAL LOOPED LAM
+1EE8C ; mapped ; 0645 # 6.1 ARABIC MATHEMATICAL LOOPED MEEM
+1EE8D ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL LOOPED NOON
+1EE8E ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL LOOPED SEEN
+1EE8F ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL LOOPED AIN
+1EE90 ; mapped ; 0641 # 6.1 ARABIC MATHEMATICAL LOOPED FEH
+1EE91 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL LOOPED SAD
+1EE92 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL LOOPED QAF
+1EE93 ; mapped ; 0631 # 6.1 ARABIC MATHEMATICAL LOOPED REH
+1EE94 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL LOOPED SHEEN
+1EE95 ; mapped ; 062A # 6.1 ARABIC MATHEMATICAL LOOPED TEH
+1EE96 ; mapped ; 062B # 6.1 ARABIC MATHEMATICAL LOOPED THEH
+1EE97 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL LOOPED KHAH
+1EE98 ; mapped ; 0630 # 6.1 ARABIC MATHEMATICAL LOOPED THAL
+1EE99 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL LOOPED DAD
+1EE9A ; mapped ; 0638 # 6.1 ARABIC MATHEMATICAL LOOPED ZAH
+1EE9B ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL LOOPED GHAIN
+1EE9C..1EEA0 ; disallowed # NA <reserved-1EE9C>..<reserved-1EEA0>
+1EEA1 ; mapped ; 0628 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK BEH
+1EEA2 ; mapped ; 062C # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM
+1EEA3 ; mapped ; 062F # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
+1EEA4 ; disallowed # NA <reserved-1EEA4>
+1EEA5 ; mapped ; 0648 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK WAW
+1EEA6 ; mapped ; 0632 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN
+1EEA7 ; mapped ; 062D # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK HAH
+1EEA8 ; mapped ; 0637 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK TAH
+1EEA9 ; mapped ; 064A # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
+1EEAA ; disallowed # NA <reserved-1EEAA>
+1EEAB ; mapped ; 0644 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK LAM
+1EEAC ; mapped ; 0645 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM
+1EEAD ; mapped ; 0646 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK NOON
+1EEAE ; mapped ; 0633 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN
+1EEAF ; mapped ; 0639 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK AIN
+1EEB0 ; mapped ; 0641 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK FEH
+1EEB1 ; mapped ; 0635 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK SAD
+1EEB2 ; mapped ; 0642 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK QAF
+1EEB3 ; mapped ; 0631 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK REH
+1EEB4 ; mapped ; 0634 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN
+1EEB5 ; mapped ; 062A # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK TEH
+1EEB6 ; mapped ; 062B # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK THEH
+1EEB7 ; mapped ; 062E # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH
+1EEB8 ; mapped ; 0630 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK THAL
+1EEB9 ; mapped ; 0636 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK DAD
+1EEBA ; mapped ; 0638 # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH
+1EEBB ; mapped ; 063A # 6.1 ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
+1EEBC..1EEEF ; disallowed # NA <reserved-1EEBC>..<reserved-1EEEF>
+1EEF0..1EEF1 ; valid ; ; NV8 # 6.1 ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
+1EEF2..1EFFF ; disallowed # NA <reserved-1EEF2>..<reserved-1EFFF>
+1F000..1F02B ; valid ; ; NV8 # 5.1 MAHJONG TILE EAST WIND..MAHJONG TILE BACK
+1F02C..1F02F ; disallowed # NA <reserved-1F02C>..<reserved-1F02F>
+1F030..1F093 ; valid ; ; NV8 # 5.1 DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
+1F094..1F09F ; disallowed # NA <reserved-1F094>..<reserved-1F09F>
+1F0A0..1F0AE ; valid ; ; NV8 # 6.0 PLAYING CARD BACK..PLAYING CARD KING OF SPADES
+1F0AF..1F0B0 ; disallowed # NA <reserved-1F0AF>..<reserved-1F0B0>
+1F0B1..1F0BE ; valid ; ; NV8 # 6.0 PLAYING CARD ACE OF HEARTS..PLAYING CARD KING OF HEARTS
+1F0BF ; valid ; ; NV8 # 7.0 PLAYING CARD RED JOKER
+1F0C0 ; disallowed # NA <reserved-1F0C0>
+1F0C1..1F0CF ; valid ; ; NV8 # 6.0 PLAYING CARD ACE OF DIAMONDS..PLAYING CARD BLACK JOKER
+1F0D0 ; disallowed # NA <reserved-1F0D0>
+1F0D1..1F0DF ; valid ; ; NV8 # 6.0 PLAYING CARD ACE OF CLUBS..PLAYING CARD WHITE JOKER
+1F0E0..1F0F5 ; valid ; ; NV8 # 7.0 PLAYING CARD FOOL..PLAYING CARD TRUMP-21
+1F0F6..1F0FF ; disallowed # NA <reserved-1F0F6>..<reserved-1F0FF>
+1F100 ; disallowed # 5.2 DIGIT ZERO FULL STOP
+1F101 ; disallowed_STD3_mapped ; 0030 002C # 5.2 DIGIT ZERO COMMA
+1F102 ; disallowed_STD3_mapped ; 0031 002C # 5.2 DIGIT ONE COMMA
+1F103 ; disallowed_STD3_mapped ; 0032 002C # 5.2 DIGIT TWO COMMA
+1F104 ; disallowed_STD3_mapped ; 0033 002C # 5.2 DIGIT THREE COMMA
+1F105 ; disallowed_STD3_mapped ; 0034 002C # 5.2 DIGIT FOUR COMMA
+1F106 ; disallowed_STD3_mapped ; 0035 002C # 5.2 DIGIT FIVE COMMA
+1F107 ; disallowed_STD3_mapped ; 0036 002C # 5.2 DIGIT SIX COMMA
+1F108 ; disallowed_STD3_mapped ; 0037 002C # 5.2 DIGIT SEVEN COMMA
+1F109 ; disallowed_STD3_mapped ; 0038 002C # 5.2 DIGIT EIGHT COMMA
+1F10A ; disallowed_STD3_mapped ; 0039 002C # 5.2 DIGIT NINE COMMA
+1F10B..1F10C ; valid ; ; NV8 # 7.0 DINGBAT CIRCLED SANS-SERIF DIGIT ZERO..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
+1F10D..1F10F ; valid ; ; NV8 # 13.0 CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH
+1F110 ; disallowed_STD3_mapped ; 0028 0061 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER A
+1F111 ; disallowed_STD3_mapped ; 0028 0062 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER B
+1F112 ; disallowed_STD3_mapped ; 0028 0063 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER C
+1F113 ; disallowed_STD3_mapped ; 0028 0064 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER D
+1F114 ; disallowed_STD3_mapped ; 0028 0065 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER E
+1F115 ; disallowed_STD3_mapped ; 0028 0066 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER F
+1F116 ; disallowed_STD3_mapped ; 0028 0067 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER G
+1F117 ; disallowed_STD3_mapped ; 0028 0068 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER H
+1F118 ; disallowed_STD3_mapped ; 0028 0069 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER I
+1F119 ; disallowed_STD3_mapped ; 0028 006A 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER J
+1F11A ; disallowed_STD3_mapped ; 0028 006B 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER K
+1F11B ; disallowed_STD3_mapped ; 0028 006C 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER L
+1F11C ; disallowed_STD3_mapped ; 0028 006D 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER M
+1F11D ; disallowed_STD3_mapped ; 0028 006E 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER N
+1F11E ; disallowed_STD3_mapped ; 0028 006F 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER O
+1F11F ; disallowed_STD3_mapped ; 0028 0070 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER P
+1F120 ; disallowed_STD3_mapped ; 0028 0071 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER Q
+1F121 ; disallowed_STD3_mapped ; 0028 0072 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER R
+1F122 ; disallowed_STD3_mapped ; 0028 0073 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER S
+1F123 ; disallowed_STD3_mapped ; 0028 0074 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER T
+1F124 ; disallowed_STD3_mapped ; 0028 0075 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER U
+1F125 ; disallowed_STD3_mapped ; 0028 0076 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER V
+1F126 ; disallowed_STD3_mapped ; 0028 0077 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER W
+1F127 ; disallowed_STD3_mapped ; 0028 0078 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER X
+1F128 ; disallowed_STD3_mapped ; 0028 0079 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER Y
+1F129 ; disallowed_STD3_mapped ; 0028 007A 0029 #5.2 PARENTHESIZED LATIN CAPITAL LETTER Z
+1F12A ; mapped ; 3014 0073 3015 #5.2 TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S
+1F12B ; mapped ; 0063 # 5.2 CIRCLED ITALIC LATIN CAPITAL LETTER C
+1F12C ; mapped ; 0072 # 5.2 CIRCLED ITALIC LATIN CAPITAL LETTER R
+1F12D ; mapped ; 0063 0064 # 5.2 CIRCLED CD
+1F12E ; mapped ; 0077 007A # 5.2 CIRCLED WZ
+1F12F ; valid ; ; NV8 # 11.0 COPYLEFT SYMBOL
+1F130 ; mapped ; 0061 # 6.0 SQUARED LATIN CAPITAL LETTER A
+1F131 ; mapped ; 0062 # 5.2 SQUARED LATIN CAPITAL LETTER B
+1F132 ; mapped ; 0063 # 6.0 SQUARED LATIN CAPITAL LETTER C
+1F133 ; mapped ; 0064 # 6.0 SQUARED LATIN CAPITAL LETTER D
+1F134 ; mapped ; 0065 # 6.0 SQUARED LATIN CAPITAL LETTER E
+1F135 ; mapped ; 0066 # 6.0 SQUARED LATIN CAPITAL LETTER F
+1F136 ; mapped ; 0067 # 6.0 SQUARED LATIN CAPITAL LETTER G
+1F137 ; mapped ; 0068 # 6.0 SQUARED LATIN CAPITAL LETTER H
+1F138 ; mapped ; 0069 # 6.0 SQUARED LATIN CAPITAL LETTER I
+1F139 ; mapped ; 006A # 6.0 SQUARED LATIN CAPITAL LETTER J
+1F13A ; mapped ; 006B # 6.0 SQUARED LATIN CAPITAL LETTER K
+1F13B ; mapped ; 006C # 6.0 SQUARED LATIN CAPITAL LETTER L
+1F13C ; mapped ; 006D # 6.0 SQUARED LATIN CAPITAL LETTER M
+1F13D ; mapped ; 006E # 5.2 SQUARED LATIN CAPITAL LETTER N
+1F13E ; mapped ; 006F # 6.0 SQUARED LATIN CAPITAL LETTER O
+1F13F ; mapped ; 0070 # 5.2 SQUARED LATIN CAPITAL LETTER P
+1F140 ; mapped ; 0071 # 6.0 SQUARED LATIN CAPITAL LETTER Q
+1F141 ; mapped ; 0072 # 6.0 SQUARED LATIN CAPITAL LETTER R
+1F142 ; mapped ; 0073 # 5.2 SQUARED LATIN CAPITAL LETTER S
+1F143 ; mapped ; 0074 # 6.0 SQUARED LATIN CAPITAL LETTER T
+1F144 ; mapped ; 0075 # 6.0 SQUARED LATIN CAPITAL LETTER U
+1F145 ; mapped ; 0076 # 6.0 SQUARED LATIN CAPITAL LETTER V
+1F146 ; mapped ; 0077 # 5.2 SQUARED LATIN CAPITAL LETTER W
+1F147 ; mapped ; 0078 # 6.0 SQUARED LATIN CAPITAL LETTER X
+1F148 ; mapped ; 0079 # 6.0 SQUARED LATIN CAPITAL LETTER Y
+1F149 ; mapped ; 007A # 6.0 SQUARED LATIN CAPITAL LETTER Z
+1F14A ; mapped ; 0068 0076 # 5.2 SQUARED HV
+1F14B ; mapped ; 006D 0076 # 5.2 SQUARED MV
+1F14C ; mapped ; 0073 0064 # 5.2 SQUARED SD
+1F14D ; mapped ; 0073 0073 # 5.2 SQUARED SS
+1F14E ; mapped ; 0070 0070 0076 #5.2 SQUARED PPV
+1F14F ; mapped ; 0077 0063 # 6.0 SQUARED WC
+1F150..1F156 ; valid ; ; NV8 # 6.0 NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER G
+1F157 ; valid ; ; NV8 # 5.2 NEGATIVE CIRCLED LATIN CAPITAL LETTER H
+1F158..1F15E ; valid ; ; NV8 # 6.0 NEGATIVE CIRCLED LATIN CAPITAL LETTER I..NEGATIVE CIRCLED LATIN CAPITAL LETTER O
+1F15F ; valid ; ; NV8 # 5.2 NEGATIVE CIRCLED LATIN CAPITAL LETTER P
+1F160..1F169 ; valid ; ; NV8 # 6.0 NEGATIVE CIRCLED LATIN CAPITAL LETTER Q..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
+1F16A ; mapped ; 006D 0063 # 6.1 RAISED MC SIGN
+1F16B ; mapped ; 006D 0064 # 6.1 RAISED MD SIGN
+1F16C ; mapped ; 006D 0072 # 12.0 RAISED MR SIGN
+1F16D..1F16F ; valid ; ; NV8 # 13.0 CIRCLED CC..CIRCLED HUMAN FIGURE
+1F170..1F178 ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER I
+1F179 ; valid ; ; NV8 # 5.2 NEGATIVE SQUARED LATIN CAPITAL LETTER J
+1F17A ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED LATIN CAPITAL LETTER K
+1F17B..1F17C ; valid ; ; NV8 # 5.2 NEGATIVE SQUARED LATIN CAPITAL LETTER L..NEGATIVE SQUARED LATIN CAPITAL LETTER M
+1F17D..1F17E ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED LATIN CAPITAL LETTER N..NEGATIVE SQUARED LATIN CAPITAL LETTER O
+1F17F ; valid ; ; NV8 # 5.2 NEGATIVE SQUARED LATIN CAPITAL LETTER P
+1F180..1F189 ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED LATIN CAPITAL LETTER Q..NEGATIVE SQUARED LATIN CAPITAL LETTER Z
+1F18A..1F18D ; valid ; ; NV8 # 5.2 CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P..NEGATIVE SQUARED SA
+1F18E..1F18F ; valid ; ; NV8 # 6.0 NEGATIVE SQUARED AB..NEGATIVE SQUARED WC
+1F190 ; mapped ; 0064 006A # 5.2 SQUARE DJ
+1F191..1F19A ; valid ; ; NV8 # 6.0 SQUARED CL..SQUARED VS
+1F19B..1F1AC ; valid ; ; NV8 # 9.0 SQUARED THREE D..SQUARED VOD
+1F1AD ; valid ; ; NV8 # 13.0 MASK WORK SYMBOL
+1F1AE..1F1E5 ; disallowed # NA <reserved-1F1AE>..<reserved-1F1E5>
+1F1E6..1F1FF ; valid ; ; NV8 # 6.0 REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
+1F200 ; mapped ; 307B 304B # 5.2 SQUARE HIRAGANA HOKA
+1F201 ; mapped ; 30B3 30B3 # 6.0 SQUARED KATAKANA KOKO
+1F202 ; mapped ; 30B5 # 6.0 SQUARED KATAKANA SA
+1F203..1F20F ; disallowed # NA <reserved-1F203>..<reserved-1F20F>
+1F210 ; mapped ; 624B # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-624B
+1F211 ; mapped ; 5B57 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-5B57
+1F212 ; mapped ; 53CC # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-53CC
+1F213 ; mapped ; 30C7 # 5.2 SQUARED KATAKANA DE
+1F214 ; mapped ; 4E8C # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-4E8C
+1F215 ; mapped ; 591A # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-591A
+1F216 ; mapped ; 89E3 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-89E3
+1F217 ; mapped ; 5929 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-5929
+1F218 ; mapped ; 4EA4 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-4EA4
+1F219 ; mapped ; 6620 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6620
+1F21A ; mapped ; 7121 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-7121
+1F21B ; mapped ; 6599 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6599
+1F21C ; mapped ; 524D # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-524D
+1F21D ; mapped ; 5F8C # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-5F8C
+1F21E ; mapped ; 518D # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-518D
+1F21F ; mapped ; 65B0 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-65B0
+1F220 ; mapped ; 521D # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-521D
+1F221 ; mapped ; 7D42 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-7D42
+1F222 ; mapped ; 751F # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-751F
+1F223 ; mapped ; 8CA9 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-8CA9
+1F224 ; mapped ; 58F0 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-58F0
+1F225 ; mapped ; 5439 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-5439
+1F226 ; mapped ; 6F14 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6F14
+1F227 ; mapped ; 6295 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6295
+1F228 ; mapped ; 6355 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6355
+1F229 ; mapped ; 4E00 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-4E00
+1F22A ; mapped ; 4E09 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-4E09
+1F22B ; mapped ; 904A # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-904A
+1F22C ; mapped ; 5DE6 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-5DE6
+1F22D ; mapped ; 4E2D # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-4E2D
+1F22E ; mapped ; 53F3 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-53F3
+1F22F ; mapped ; 6307 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6307
+1F230 ; mapped ; 8D70 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-8D70
+1F231 ; mapped ; 6253 # 5.2 SQUARED CJK UNIFIED IDEOGRAPH-6253
+1F232 ; mapped ; 7981 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-7981
+1F233 ; mapped ; 7A7A # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-7A7A
+1F234 ; mapped ; 5408 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-5408
+1F235 ; mapped ; 6E80 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-6E80
+1F236 ; mapped ; 6709 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-6709
+1F237 ; mapped ; 6708 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-6708
+1F238 ; mapped ; 7533 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-7533
+1F239 ; mapped ; 5272 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-5272
+1F23A ; mapped ; 55B6 # 6.0 SQUARED CJK UNIFIED IDEOGRAPH-55B6
+1F23B ; mapped ; 914D # 9.0 SQUARED CJK UNIFIED IDEOGRAPH-914D
+1F23C..1F23F ; disallowed # NA <reserved-1F23C>..<reserved-1F23F>
+1F240 ; mapped ; 3014 672C 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C
+1F241 ; mapped ; 3014 4E09 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09
+1F242 ; mapped ; 3014 4E8C 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C
+1F243 ; mapped ; 3014 5B89 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89
+1F244 ; mapped ; 3014 70B9 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9
+1F245 ; mapped ; 3014 6253 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253
+1F246 ; mapped ; 3014 76D7 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7
+1F247 ; mapped ; 3014 52DD 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD
+1F248 ; mapped ; 3014 6557 3015 #5.2 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
+1F249..1F24F ; disallowed # NA <reserved-1F249>..<reserved-1F24F>
+1F250 ; mapped ; 5F97 # 6.0 CIRCLED IDEOGRAPH ADVANTAGE
+1F251 ; mapped ; 53EF # 6.0 CIRCLED IDEOGRAPH ACCEPT
+1F252..1F25F ; disallowed # NA <reserved-1F252>..<reserved-1F25F>
+1F260..1F265 ; valid ; ; NV8 # 10.0 ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
+1F266..1F2FF ; disallowed # NA <reserved-1F266>..<reserved-1F2FF>
+1F300..1F320 ; valid ; ; NV8 # 6.0 CYCLONE..SHOOTING STAR
+1F321..1F32C ; valid ; ; NV8 # 7.0 THERMOMETER..WIND BLOWING FACE
+1F32D..1F32F ; valid ; ; NV8 # 8.0 HOT DOG..BURRITO
+1F330..1F335 ; valid ; ; NV8 # 6.0 CHESTNUT..CACTUS
+1F336 ; valid ; ; NV8 # 7.0 HOT PEPPER
+1F337..1F37C ; valid ; ; NV8 # 6.0 TULIP..BABY BOTTLE
+1F37D ; valid ; ; NV8 # 7.0 FORK AND KNIFE WITH PLATE
+1F37E..1F37F ; valid ; ; NV8 # 8.0 BOTTLE WITH POPPING CORK..POPCORN
+1F380..1F393 ; valid ; ; NV8 # 6.0 RIBBON..GRADUATION CAP
+1F394..1F39F ; valid ; ; NV8 # 7.0 HEART WITH TIP ON THE LEFT..ADMISSION TICKETS
+1F3A0..1F3C4 ; valid ; ; NV8 # 6.0 CAROUSEL HORSE..SURFER
+1F3C5 ; valid ; ; NV8 # 7.0 SPORTS MEDAL
+1F3C6..1F3CA ; valid ; ; NV8 # 6.0 TROPHY..SWIMMER
+1F3CB..1F3CE ; valid ; ; NV8 # 7.0 WEIGHT LIFTER..RACING CAR
+1F3CF..1F3D3 ; valid ; ; NV8 # 8.0 CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL
+1F3D4..1F3DF ; valid ; ; NV8 # 7.0 SNOW CAPPED MOUNTAIN..STADIUM
+1F3E0..1F3F0 ; valid ; ; NV8 # 6.0 HOUSE BUILDING..EUROPEAN CASTLE
+1F3F1..1F3F7 ; valid ; ; NV8 # 7.0 WHITE PENNANT..LABEL
+1F3F8..1F3FF ; valid ; ; NV8 # 8.0 BADMINTON RACQUET AND SHUTTLECOCK..EMOJI MODIFIER FITZPATRICK TYPE-6
+1F400..1F43E ; valid ; ; NV8 # 6.0 RAT..PAW PRINTS
+1F43F ; valid ; ; NV8 # 7.0 CHIPMUNK
+1F440 ; valid ; ; NV8 # 6.0 EYES
+1F441 ; valid ; ; NV8 # 7.0 EYE
+1F442..1F4F7 ; valid ; ; NV8 # 6.0 EAR..CAMERA
+1F4F8 ; valid ; ; NV8 # 7.0 CAMERA WITH FLASH
+1F4F9..1F4FC ; valid ; ; NV8 # 6.0 VIDEO CAMERA..VIDEOCASSETTE
+1F4FD..1F4FE ; valid ; ; NV8 # 7.0 FILM PROJECTOR..PORTABLE STEREO
+1F4FF ; valid ; ; NV8 # 8.0 PRAYER BEADS
+1F500..1F53D ; valid ; ; NV8 # 6.0 TWISTED RIGHTWARDS ARROWS..DOWN-POINTING SMALL RED TRIANGLE
+1F53E..1F53F ; valid ; ; NV8 # 7.0 LOWER RIGHT SHADOWED WHITE CIRCLE..UPPER RIGHT SHADOWED WHITE CIRCLE
+1F540..1F543 ; valid ; ; NV8 # 6.1 CIRCLED CROSS POMMEE..NOTCHED LEFT SEMICIRCLE WITH THREE DOTS
+1F544..1F54A ; valid ; ; NV8 # 7.0 NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS..DOVE OF PEACE
+1F54B..1F54F ; valid ; ; NV8 # 8.0 KAABA..BOWL OF HYGIEIA
+1F550..1F567 ; valid ; ; NV8 # 6.0 CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY
+1F568..1F579 ; valid ; ; NV8 # 7.0 RIGHT SPEAKER..JOYSTICK
+1F57A ; valid ; ; NV8 # 9.0 MAN DANCING
+1F57B..1F5A3 ; valid ; ; NV8 # 7.0 LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX
+1F5A4 ; valid ; ; NV8 # 9.0 BLACK HEART
+1F5A5..1F5FA ; valid ; ; NV8 # 7.0 DESKTOP COMPUTER..WORLD MAP
+1F5FB..1F5FF ; valid ; ; NV8 # 6.0 MOUNT FUJI..MOYAI
+1F600 ; valid ; ; NV8 # 6.1 GRINNING FACE
+1F601..1F610 ; valid ; ; NV8 # 6.0 GRINNING FACE WITH SMILING EYES..NEUTRAL FACE
+1F611 ; valid ; ; NV8 # 6.1 EXPRESSIONLESS FACE
+1F612..1F614 ; valid ; ; NV8 # 6.0 UNAMUSED FACE..PENSIVE FACE
+1F615 ; valid ; ; NV8 # 6.1 CONFUSED FACE
+1F616 ; valid ; ; NV8 # 6.0 CONFOUNDED FACE
+1F617 ; valid ; ; NV8 # 6.1 KISSING FACE
+1F618 ; valid ; ; NV8 # 6.0 FACE THROWING A KISS
+1F619 ; valid ; ; NV8 # 6.1 KISSING FACE WITH SMILING EYES
+1F61A ; valid ; ; NV8 # 6.0 KISSING FACE WITH CLOSED EYES
+1F61B ; valid ; ; NV8 # 6.1 FACE WITH STUCK-OUT TONGUE
+1F61C..1F61E ; valid ; ; NV8 # 6.0 FACE WITH STUCK-OUT TONGUE AND WINKING EYE..DISAPPOINTED FACE
+1F61F ; valid ; ; NV8 # 6.1 WORRIED FACE
+1F620..1F625 ; valid ; ; NV8 # 6.0 ANGRY FACE..DISAPPOINTED BUT RELIEVED FACE
+1F626..1F627 ; valid ; ; NV8 # 6.1 FROWNING FACE WITH OPEN MOUTH..ANGUISHED FACE
+1F628..1F62B ; valid ; ; NV8 # 6.0 FEARFUL FACE..TIRED FACE
+1F62C ; valid ; ; NV8 # 6.1 GRIMACING FACE
+1F62D ; valid ; ; NV8 # 6.0 LOUDLY CRYING FACE
+1F62E..1F62F ; valid ; ; NV8 # 6.1 FACE WITH OPEN MOUTH..HUSHED FACE
+1F630..1F633 ; valid ; ; NV8 # 6.0 FACE WITH OPEN MOUTH AND COLD SWEAT..FLUSHED FACE
+1F634 ; valid ; ; NV8 # 6.1 SLEEPING FACE
+1F635..1F640 ; valid ; ; NV8 # 6.0 DIZZY FACE..WEARY CAT FACE
+1F641..1F642 ; valid ; ; NV8 # 7.0 SLIGHTLY FROWNING FACE..SLIGHTLY SMILING FACE
+1F643..1F644 ; valid ; ; NV8 # 8.0 UPSIDE-DOWN FACE..FACE WITH ROLLING EYES
+1F645..1F64F ; valid ; ; NV8 # 6.0 FACE WITH NO GOOD GESTURE..PERSON WITH FOLDED HANDS
+1F650..1F67F ; valid ; ; NV8 # 7.0 NORTH WEST POINTING LEAF..REVERSE CHECKER BOARD
+1F680..1F6C5 ; valid ; ; NV8 # 6.0 ROCKET..LEFT LUGGAGE
+1F6C6..1F6CF ; valid ; ; NV8 # 7.0 TRIANGLE WITH ROUNDED CORNERS..BED
+1F6D0 ; valid ; ; NV8 # 8.0 PLACE OF WORSHIP
+1F6D1..1F6D2 ; valid ; ; NV8 # 9.0 OCTAGONAL SIGN..SHOPPING TROLLEY
+1F6D3..1F6D4 ; valid ; ; NV8 # 10.0 STUPA..PAGODA
+1F6D5 ; valid ; ; NV8 # 12.0 HINDU TEMPLE
+1F6D6..1F6D7 ; valid ; ; NV8 # 13.0 HUT..ELEVATOR
+1F6D8..1F6DC ; disallowed # NA <reserved-1F6D8>..<reserved-1F6DC>
+1F6DD..1F6DF ; valid ; ; NV8 # 14.0 PLAYGROUND SLIDE..RING BUOY
+1F6E0..1F6EC ; valid ; ; NV8 # 7.0 HAMMER AND WRENCH..AIRPLANE ARRIVING
+1F6ED..1F6EF ; disallowed # NA <reserved-1F6ED>..<reserved-1F6EF>
+1F6F0..1F6F3 ; valid ; ; NV8 # 7.0 SATELLITE..PASSENGER SHIP
+1F6F4..1F6F6 ; valid ; ; NV8 # 9.0 SCOOTER..CANOE
+1F6F7..1F6F8 ; valid ; ; NV8 # 10.0 SLED..FLYING SAUCER
+1F6F9 ; valid ; ; NV8 # 11.0 SKATEBOARD
+1F6FA ; valid ; ; NV8 # 12.0 AUTO RICKSHAW
+1F6FB..1F6FC ; valid ; ; NV8 # 13.0 PICKUP TRUCK..ROLLER SKATE
+1F6FD..1F6FF ; disallowed # NA <reserved-1F6FD>..<reserved-1F6FF>
+1F700..1F773 ; valid ; ; NV8 # 6.0 ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
+1F774..1F77F ; disallowed # NA <reserved-1F774>..<reserved-1F77F>
+1F780..1F7D4 ; valid ; ; NV8 # 7.0 BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR
+1F7D5..1F7D8 ; valid ; ; NV8 # 11.0 CIRCLED TRIANGLE..NEGATIVE CIRCLED SQUARE
+1F7D9..1F7DF ; disallowed # NA <reserved-1F7D9>..<reserved-1F7DF>
+1F7E0..1F7EB ; valid ; ; NV8 # 12.0 LARGE ORANGE CIRCLE..LARGE BROWN SQUARE
+1F7EC..1F7EF ; disallowed # NA <reserved-1F7EC>..<reserved-1F7EF>
+1F7F0 ; valid ; ; NV8 # 14.0 HEAVY EQUALS SIGN
+1F7F1..1F7FF ; disallowed # NA <reserved-1F7F1>..<reserved-1F7FF>
+1F800..1F80B ; valid ; ; NV8 # 7.0 LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
+1F80C..1F80F ; disallowed # NA <reserved-1F80C>..<reserved-1F80F>
+1F810..1F847 ; valid ; ; NV8 # 7.0 LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
+1F848..1F84F ; disallowed # NA <reserved-1F848>..<reserved-1F84F>
+1F850..1F859 ; valid ; ; NV8 # 7.0 LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
+1F85A..1F85F ; disallowed # NA <reserved-1F85A>..<reserved-1F85F>
+1F860..1F887 ; valid ; ; NV8 # 7.0 WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
+1F888..1F88F ; disallowed # NA <reserved-1F888>..<reserved-1F88F>
+1F890..1F8AD ; valid ; ; NV8 # 7.0 LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F8AE..1F8AF ; disallowed # NA <reserved-1F8AE>..<reserved-1F8AF>
+1F8B0..1F8B1 ; valid ; ; NV8 # 13.0 ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST
+1F8B2..1F8FF ; disallowed # NA <reserved-1F8B2>..<reserved-1F8FF>
+1F900..1F90B ; valid ; ; NV8 # 10.0 CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT
+1F90C ; valid ; ; NV8 # 13.0 PINCHED FINGERS
+1F90D..1F90F ; valid ; ; NV8 # 12.0 WHITE HEART..PINCHING HAND
+1F910..1F918 ; valid ; ; NV8 # 8.0 ZIPPER-MOUTH FACE..SIGN OF THE HORNS
+1F919..1F91E ; valid ; ; NV8 # 9.0 CALL ME HAND..HAND WITH INDEX AND MIDDLE FINGERS CROSSED
+1F91F ; valid ; ; NV8 # 10.0 I LOVE YOU HAND SIGN
+1F920..1F927 ; valid ; ; NV8 # 9.0 FACE WITH COWBOY HAT..SNEEZING FACE
+1F928..1F92F ; valid ; ; NV8 # 10.0 FACE WITH ONE EYEBROW RAISED..SHOCKED FACE WITH EXPLODING HEAD
+1F930 ; valid ; ; NV8 # 9.0 PREGNANT WOMAN
+1F931..1F932 ; valid ; ; NV8 # 10.0 BREAST-FEEDING..PALMS UP TOGETHER
+1F933..1F93E ; valid ; ; NV8 # 9.0 SELFIE..HANDBALL
+1F93F ; valid ; ; NV8 # 12.0 DIVING MASK
+1F940..1F94B ; valid ; ; NV8 # 9.0 WILTED FLOWER..MARTIAL ARTS UNIFORM
+1F94C ; valid ; ; NV8 # 10.0 CURLING STONE
+1F94D..1F94F ; valid ; ; NV8 # 11.0 LACROSSE STICK AND BALL..FLYING DISC
+1F950..1F95E ; valid ; ; NV8 # 9.0 CROISSANT..PANCAKES
+1F95F..1F96B ; valid ; ; NV8 # 10.0 DUMPLING..CANNED FOOD
+1F96C..1F970 ; valid ; ; NV8 # 11.0 LEAFY GREEN..SMILING FACE WITH SMILING EYES AND THREE HEARTS
+1F971 ; valid ; ; NV8 # 12.0 YAWNING FACE
+1F972 ; valid ; ; NV8 # 13.0 SMILING FACE WITH TEAR
+1F973..1F976 ; valid ; ; NV8 # 11.0 FACE WITH PARTY HORN AND PARTY HAT..FREEZING FACE
+1F977..1F978 ; valid ; ; NV8 # 13.0 NINJA..DISGUISED FACE
+1F979 ; valid ; ; NV8 # 14.0 FACE HOLDING BACK TEARS
+1F97A ; valid ; ; NV8 # 11.0 FACE WITH PLEADING EYES
+1F97B ; valid ; ; NV8 # 12.0 SARI
+1F97C..1F97F ; valid ; ; NV8 # 11.0 LAB COAT..FLAT SHOE
+1F980..1F984 ; valid ; ; NV8 # 8.0 CRAB..UNICORN FACE
+1F985..1F991 ; valid ; ; NV8 # 9.0 EAGLE..SQUID
+1F992..1F997 ; valid ; ; NV8 # 10.0 GIRAFFE FACE..CRICKET
+1F998..1F9A2 ; valid ; ; NV8 # 11.0 KANGAROO..SWAN
+1F9A3..1F9A4 ; valid ; ; NV8 # 13.0 MAMMOTH..DODO
+1F9A5..1F9AA ; valid ; ; NV8 # 12.0 SLOTH..OYSTER
+1F9AB..1F9AD ; valid ; ; NV8 # 13.0 BEAVER..SEAL
+1F9AE..1F9AF ; valid ; ; NV8 # 12.0 GUIDE DOG..PROBING CANE
+1F9B0..1F9B9 ; valid ; ; NV8 # 11.0 EMOJI COMPONENT RED HAIR..SUPERVILLAIN
+1F9BA..1F9BF ; valid ; ; NV8 # 12.0 SAFETY VEST..MECHANICAL LEG
+1F9C0 ; valid ; ; NV8 # 8.0 CHEESE WEDGE
+1F9C1..1F9C2 ; valid ; ; NV8 # 11.0 CUPCAKE..SALT SHAKER
+1F9C3..1F9CA ; valid ; ; NV8 # 12.0 BEVERAGE BOX..ICE CUBE
+1F9CB ; valid ; ; NV8 # 13.0 BUBBLE TEA
+1F9CC ; valid ; ; NV8 # 14.0 TROLL
+1F9CD..1F9CF ; valid ; ; NV8 # 12.0 STANDING PERSON..DEAF PERSON
+1F9D0..1F9E6 ; valid ; ; NV8 # 10.0 FACE WITH MONOCLE..SOCKS
+1F9E7..1F9FF ; valid ; ; NV8 # 11.0 RED GIFT ENVELOPE..NAZAR AMULET
+1FA00..1FA53 ; valid ; ; NV8 # 12.0 NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP
+1FA54..1FA5F ; disallowed # NA <reserved-1FA54>..<reserved-1FA5F>
+1FA60..1FA6D ; valid ; ; NV8 # 11.0 XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
+1FA6E..1FA6F ; disallowed # NA <reserved-1FA6E>..<reserved-1FA6F>
+1FA70..1FA73 ; valid ; ; NV8 # 12.0 BALLET SHOES..SHORTS
+1FA74 ; valid ; ; NV8 # 13.0 THONG SANDAL
+1FA75..1FA77 ; disallowed # NA <reserved-1FA75>..<reserved-1FA77>
+1FA78..1FA7A ; valid ; ; NV8 # 12.0 DROP OF BLOOD..STETHOSCOPE
+1FA7B..1FA7C ; valid ; ; NV8 # 14.0 X-RAY..CRUTCH
+1FA7D..1FA7F ; disallowed # NA <reserved-1FA7D>..<reserved-1FA7F>
+1FA80..1FA82 ; valid ; ; NV8 # 12.0 YO-YO..PARACHUTE
+1FA83..1FA86 ; valid ; ; NV8 # 13.0 BOOMERANG..NESTING DOLLS
+1FA87..1FA8F ; disallowed # NA <reserved-1FA87>..<reserved-1FA8F>
+1FA90..1FA95 ; valid ; ; NV8 # 12.0 RINGED PLANET..BANJO
+1FA96..1FAA8 ; valid ; ; NV8 # 13.0 MILITARY HELMET..ROCK
+1FAA9..1FAAC ; valid ; ; NV8 # 14.0 MIRROR BALL..HAMSA
+1FAAD..1FAAF ; disallowed # NA <reserved-1FAAD>..<reserved-1FAAF>
+1FAB0..1FAB6 ; valid ; ; NV8 # 13.0 FLY..FEATHER
+1FAB7..1FABA ; valid ; ; NV8 # 14.0 LOTUS..NEST WITH EGGS
+1FABB..1FABF ; disallowed # NA <reserved-1FABB>..<reserved-1FABF>
+1FAC0..1FAC2 ; valid ; ; NV8 # 13.0 ANATOMICAL HEART..PEOPLE HUGGING
+1FAC3..1FAC5 ; valid ; ; NV8 # 14.0 PREGNANT MAN..PERSON WITH CROWN
+1FAC6..1FACF ; disallowed # NA <reserved-1FAC6>..<reserved-1FACF>
+1FAD0..1FAD6 ; valid ; ; NV8 # 13.0 BLUEBERRIES..TEAPOT
+1FAD7..1FAD9 ; valid ; ; NV8 # 14.0 POURING LIQUID..JAR
+1FADA..1FADF ; disallowed # NA <reserved-1FADA>..<reserved-1FADF>
+1FAE0..1FAE7 ; valid ; ; NV8 # 14.0 MELTING FACE..BUBBLES
+1FAE8..1FAEF ; disallowed # NA <reserved-1FAE8>..<reserved-1FAEF>
+1FAF0..1FAF6 ; valid ; ; NV8 # 14.0 HAND WITH INDEX FINGER AND THUMB CROSSED..HEART HANDS
+1FAF7..1FAFF ; disallowed # NA <reserved-1FAF7>..<reserved-1FAFF>
+1FB00..1FB92 ; valid ; ; NV8 # 13.0 BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
+1FB93 ; disallowed # NA <reserved-1FB93>
+1FB94..1FBCA ; valid ; ; NV8 # 13.0 LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON
+1FBCB..1FBEF ; disallowed # NA <reserved-1FBCB>..<reserved-1FBEF>
+1FBF0 ; mapped ; 0030 # 13.0 SEGMENTED DIGIT ZERO
+1FBF1 ; mapped ; 0031 # 13.0 SEGMENTED DIGIT ONE
+1FBF2 ; mapped ; 0032 # 13.0 SEGMENTED DIGIT TWO
+1FBF3 ; mapped ; 0033 # 13.0 SEGMENTED DIGIT THREE
+1FBF4 ; mapped ; 0034 # 13.0 SEGMENTED DIGIT FOUR
+1FBF5 ; mapped ; 0035 # 13.0 SEGMENTED DIGIT FIVE
+1FBF6 ; mapped ; 0036 # 13.0 SEGMENTED DIGIT SIX
+1FBF7 ; mapped ; 0037 # 13.0 SEGMENTED DIGIT SEVEN
+1FBF8 ; mapped ; 0038 # 13.0 SEGMENTED DIGIT EIGHT
+1FBF9 ; mapped ; 0039 # 13.0 SEGMENTED DIGIT NINE
+1FBFA..1FFFD ; disallowed # NA <reserved-1FBFA>..<reserved-1FFFD>
+1FFFE..1FFFF ; disallowed # 2.0 <noncharacter-1FFFE>..<noncharacter-1FFFF>
+20000..2A6D6 ; valid # 3.1 CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
+2A6D7..2A6DD ; valid # 13.0 CJK UNIFIED IDEOGRAPH-2A6D7..CJK UNIFIED IDEOGRAPH-2A6DD
+2A6DE..2A6DF ; valid # 14.0 CJK UNIFIED IDEOGRAPH-2A6DE..CJK UNIFIED IDEOGRAPH-2A6DF
+2A6E0..2A6FF ; disallowed # NA <reserved-2A6E0>..<reserved-2A6FF>
+2A700..2B734 ; valid # 5.2 CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
+2B735..2B738 ; valid # 14.0 CJK UNIFIED IDEOGRAPH-2B735..CJK UNIFIED IDEOGRAPH-2B738
+2B739..2B73F ; disallowed # NA <reserved-2B739>..<reserved-2B73F>
+2B740..2B81D ; valid # 6.0 CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B81E..2B81F ; disallowed # NA <reserved-2B81E>..<reserved-2B81F>
+2B820..2CEA1 ; valid # 8.0 CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
+2CEA2..2CEAF ; disallowed # NA <reserved-2CEA2>..<reserved-2CEAF>
+2CEB0..2EBE0 ; valid # 10.0 CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
+2EBE1..2F7FF ; disallowed # NA <reserved-2EBE1>..<reserved-2F7FF>
+2F800 ; mapped ; 4E3D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F800
+2F801 ; mapped ; 4E38 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F801
+2F802 ; mapped ; 4E41 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F802
+2F803 ; mapped ; 20122 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F803
+2F804 ; mapped ; 4F60 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F804
+2F805 ; mapped ; 4FAE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F805
+2F806 ; mapped ; 4FBB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F806
+2F807 ; mapped ; 5002 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F807
+2F808 ; mapped ; 507A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F808
+2F809 ; mapped ; 5099 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F809
+2F80A ; mapped ; 50E7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80A
+2F80B ; mapped ; 50CF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80B
+2F80C ; mapped ; 349E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80C
+2F80D ; mapped ; 2063A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80D
+2F80E ; mapped ; 514D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80E
+2F80F ; mapped ; 5154 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F80F
+2F810 ; mapped ; 5164 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F810
+2F811 ; mapped ; 5177 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F811
+2F812 ; mapped ; 2051C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F812
+2F813 ; mapped ; 34B9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F813
+2F814 ; mapped ; 5167 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F814
+2F815 ; mapped ; 518D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F815
+2F816 ; mapped ; 2054B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F816
+2F817 ; mapped ; 5197 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F817
+2F818 ; mapped ; 51A4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F818
+2F819 ; mapped ; 4ECC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F819
+2F81A ; mapped ; 51AC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81A
+2F81B ; mapped ; 51B5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81B
+2F81C ; mapped ; 291DF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81C
+2F81D ; mapped ; 51F5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81D
+2F81E ; mapped ; 5203 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81E
+2F81F ; mapped ; 34DF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F81F
+2F820 ; mapped ; 523B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F820
+2F821 ; mapped ; 5246 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F821
+2F822 ; mapped ; 5272 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F822
+2F823 ; mapped ; 5277 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F823
+2F824 ; mapped ; 3515 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F824
+2F825 ; mapped ; 52C7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F825
+2F826 ; mapped ; 52C9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F826
+2F827 ; mapped ; 52E4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F827
+2F828 ; mapped ; 52FA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F828
+2F829 ; mapped ; 5305 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F829
+2F82A ; mapped ; 5306 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82A
+2F82B ; mapped ; 5317 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82B
+2F82C ; mapped ; 5349 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82C
+2F82D ; mapped ; 5351 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82D
+2F82E ; mapped ; 535A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82E
+2F82F ; mapped ; 5373 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F82F
+2F830 ; mapped ; 537D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F830
+2F831..2F833 ; mapped ; 537F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F831..CJK COMPATIBILITY IDEOGRAPH-2F833
+2F834 ; mapped ; 20A2C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F834
+2F835 ; mapped ; 7070 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F835
+2F836 ; mapped ; 53CA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F836
+2F837 ; mapped ; 53DF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F837
+2F838 ; mapped ; 20B63 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F838
+2F839 ; mapped ; 53EB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F839
+2F83A ; mapped ; 53F1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83A
+2F83B ; mapped ; 5406 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83B
+2F83C ; mapped ; 549E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83C
+2F83D ; mapped ; 5438 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83D
+2F83E ; mapped ; 5448 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83E
+2F83F ; mapped ; 5468 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F83F
+2F840 ; mapped ; 54A2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F840
+2F841 ; mapped ; 54F6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F841
+2F842 ; mapped ; 5510 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F842
+2F843 ; mapped ; 5553 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F843
+2F844 ; mapped ; 5563 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F844
+2F845..2F846 ; mapped ; 5584 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F845..CJK COMPATIBILITY IDEOGRAPH-2F846
+2F847 ; mapped ; 5599 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F847
+2F848 ; mapped ; 55AB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F848
+2F849 ; mapped ; 55B3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F849
+2F84A ; mapped ; 55C2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84A
+2F84B ; mapped ; 5716 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84B
+2F84C ; mapped ; 5606 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84C
+2F84D ; mapped ; 5717 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84D
+2F84E ; mapped ; 5651 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84E
+2F84F ; mapped ; 5674 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F84F
+2F850 ; mapped ; 5207 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F850
+2F851 ; mapped ; 58EE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F851
+2F852 ; mapped ; 57CE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F852
+2F853 ; mapped ; 57F4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F853
+2F854 ; mapped ; 580D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F854
+2F855 ; mapped ; 578B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F855
+2F856 ; mapped ; 5832 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F856
+2F857 ; mapped ; 5831 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F857
+2F858 ; mapped ; 58AC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F858
+2F859 ; mapped ; 214E4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F859
+2F85A ; mapped ; 58F2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85A
+2F85B ; mapped ; 58F7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85B
+2F85C ; mapped ; 5906 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85C
+2F85D ; mapped ; 591A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85D
+2F85E ; mapped ; 5922 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85E
+2F85F ; mapped ; 5962 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F85F
+2F860 ; mapped ; 216A8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F860
+2F861 ; mapped ; 216EA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F861
+2F862 ; mapped ; 59EC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F862
+2F863 ; mapped ; 5A1B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F863
+2F864 ; mapped ; 5A27 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F864
+2F865 ; mapped ; 59D8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F865
+2F866 ; mapped ; 5A66 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F866
+2F867 ; mapped ; 36EE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F867
+2F868 ; disallowed # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F868
+2F869 ; mapped ; 5B08 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F869
+2F86A..2F86B ; mapped ; 5B3E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F86A..CJK COMPATIBILITY IDEOGRAPH-2F86B
+2F86C ; mapped ; 219C8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F86C
+2F86D ; mapped ; 5BC3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F86D
+2F86E ; mapped ; 5BD8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F86E
+2F86F ; mapped ; 5BE7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F86F
+2F870 ; mapped ; 5BF3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F870
+2F871 ; mapped ; 21B18 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F871
+2F872 ; mapped ; 5BFF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F872
+2F873 ; mapped ; 5C06 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F873
+2F874 ; disallowed # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F874
+2F875 ; mapped ; 5C22 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F875
+2F876 ; mapped ; 3781 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F876
+2F877 ; mapped ; 5C60 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F877
+2F878 ; mapped ; 5C6E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F878
+2F879 ; mapped ; 5CC0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F879
+2F87A ; mapped ; 5C8D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87A
+2F87B ; mapped ; 21DE4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87B
+2F87C ; mapped ; 5D43 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87C
+2F87D ; mapped ; 21DE6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87D
+2F87E ; mapped ; 5D6E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87E
+2F87F ; mapped ; 5D6B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F87F
+2F880 ; mapped ; 5D7C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F880
+2F881 ; mapped ; 5DE1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F881
+2F882 ; mapped ; 5DE2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F882
+2F883 ; mapped ; 382F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F883
+2F884 ; mapped ; 5DFD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F884
+2F885 ; mapped ; 5E28 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F885
+2F886 ; mapped ; 5E3D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F886
+2F887 ; mapped ; 5E69 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F887
+2F888 ; mapped ; 3862 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F888
+2F889 ; mapped ; 22183 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F889
+2F88A ; mapped ; 387C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88A
+2F88B ; mapped ; 5EB0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88B
+2F88C ; mapped ; 5EB3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88C
+2F88D ; mapped ; 5EB6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88D
+2F88E ; mapped ; 5ECA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88E
+2F88F ; mapped ; 2A392 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F88F
+2F890 ; mapped ; 5EFE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F890
+2F891..2F892 ; mapped ; 22331 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F891..CJK COMPATIBILITY IDEOGRAPH-2F892
+2F893 ; mapped ; 8201 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F893
+2F894..2F895 ; mapped ; 5F22 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F894..CJK COMPATIBILITY IDEOGRAPH-2F895
+2F896 ; mapped ; 38C7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F896
+2F897 ; mapped ; 232B8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F897
+2F898 ; mapped ; 261DA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F898
+2F899 ; mapped ; 5F62 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F899
+2F89A ; mapped ; 5F6B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89A
+2F89B ; mapped ; 38E3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89B
+2F89C ; mapped ; 5F9A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89C
+2F89D ; mapped ; 5FCD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89D
+2F89E ; mapped ; 5FD7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89E
+2F89F ; mapped ; 5FF9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F89F
+2F8A0 ; mapped ; 6081 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A0
+2F8A1 ; mapped ; 393A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A1
+2F8A2 ; mapped ; 391C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A2
+2F8A3 ; mapped ; 6094 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A3
+2F8A4 ; mapped ; 226D4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A4
+2F8A5 ; mapped ; 60C7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A5
+2F8A6 ; mapped ; 6148 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A6
+2F8A7 ; mapped ; 614C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A7
+2F8A8 ; mapped ; 614E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A8
+2F8A9 ; mapped ; 614C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8A9
+2F8AA ; mapped ; 617A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AA
+2F8AB ; mapped ; 618E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AB
+2F8AC ; mapped ; 61B2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AC
+2F8AD ; mapped ; 61A4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AD
+2F8AE ; mapped ; 61AF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AE
+2F8AF ; mapped ; 61DE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8AF
+2F8B0 ; mapped ; 61F2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B0
+2F8B1 ; mapped ; 61F6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B1
+2F8B2 ; mapped ; 6210 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B2
+2F8B3 ; mapped ; 621B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B3
+2F8B4 ; mapped ; 625D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B4
+2F8B5 ; mapped ; 62B1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B5
+2F8B6 ; mapped ; 62D4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B6
+2F8B7 ; mapped ; 6350 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B7
+2F8B8 ; mapped ; 22B0C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B8
+2F8B9 ; mapped ; 633D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8B9
+2F8BA ; mapped ; 62FC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BA
+2F8BB ; mapped ; 6368 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BB
+2F8BC ; mapped ; 6383 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BC
+2F8BD ; mapped ; 63E4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BD
+2F8BE ; mapped ; 22BF1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BE
+2F8BF ; mapped ; 6422 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8BF
+2F8C0 ; mapped ; 63C5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C0
+2F8C1 ; mapped ; 63A9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C1
+2F8C2 ; mapped ; 3A2E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C2
+2F8C3 ; mapped ; 6469 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C3
+2F8C4 ; mapped ; 647E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C4
+2F8C5 ; mapped ; 649D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C5
+2F8C6 ; mapped ; 6477 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C6
+2F8C7 ; mapped ; 3A6C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C7
+2F8C8 ; mapped ; 654F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C8
+2F8C9 ; mapped ; 656C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8C9
+2F8CA ; mapped ; 2300A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CA
+2F8CB ; mapped ; 65E3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CB
+2F8CC ; mapped ; 66F8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CC
+2F8CD ; mapped ; 6649 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CD
+2F8CE ; mapped ; 3B19 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CE
+2F8CF ; mapped ; 6691 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8CF
+2F8D0 ; mapped ; 3B08 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D0
+2F8D1 ; mapped ; 3AE4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D1
+2F8D2 ; mapped ; 5192 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D2
+2F8D3 ; mapped ; 5195 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D3
+2F8D4 ; mapped ; 6700 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D4
+2F8D5 ; mapped ; 669C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D5
+2F8D6 ; mapped ; 80AD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D6
+2F8D7 ; mapped ; 43D9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D7
+2F8D8 ; mapped ; 6717 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D8
+2F8D9 ; mapped ; 671B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8D9
+2F8DA ; mapped ; 6721 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DA
+2F8DB ; mapped ; 675E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DB
+2F8DC ; mapped ; 6753 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DC
+2F8DD ; mapped ; 233C3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DD
+2F8DE ; mapped ; 3B49 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DE
+2F8DF ; mapped ; 67FA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8DF
+2F8E0 ; mapped ; 6785 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E0
+2F8E1 ; mapped ; 6852 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E1
+2F8E2 ; mapped ; 6885 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E2
+2F8E3 ; mapped ; 2346D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E3
+2F8E4 ; mapped ; 688E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E4
+2F8E5 ; mapped ; 681F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E5
+2F8E6 ; mapped ; 6914 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E6
+2F8E7 ; mapped ; 3B9D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E7
+2F8E8 ; mapped ; 6942 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E8
+2F8E9 ; mapped ; 69A3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8E9
+2F8EA ; mapped ; 69EA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8EA
+2F8EB ; mapped ; 6AA8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8EB
+2F8EC ; mapped ; 236A3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8EC
+2F8ED ; mapped ; 6ADB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8ED
+2F8EE ; mapped ; 3C18 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8EE
+2F8EF ; mapped ; 6B21 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8EF
+2F8F0 ; mapped ; 238A7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F0
+2F8F1 ; mapped ; 6B54 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F1
+2F8F2 ; mapped ; 3C4E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F2
+2F8F3 ; mapped ; 6B72 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F3
+2F8F4 ; mapped ; 6B9F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F4
+2F8F5 ; mapped ; 6BBA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F5
+2F8F6 ; mapped ; 6BBB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F6
+2F8F7 ; mapped ; 23A8D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F7
+2F8F8 ; mapped ; 21D0B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F8
+2F8F9 ; mapped ; 23AFA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8F9
+2F8FA ; mapped ; 6C4E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FA
+2F8FB ; mapped ; 23CBC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FB
+2F8FC ; mapped ; 6CBF # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FC
+2F8FD ; mapped ; 6CCD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FD
+2F8FE ; mapped ; 6C67 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FE
+2F8FF ; mapped ; 6D16 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F8FF
+2F900 ; mapped ; 6D3E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F900
+2F901 ; mapped ; 6D77 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F901
+2F902 ; mapped ; 6D41 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F902
+2F903 ; mapped ; 6D69 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F903
+2F904 ; mapped ; 6D78 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F904
+2F905 ; mapped ; 6D85 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F905
+2F906 ; mapped ; 23D1E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F906
+2F907 ; mapped ; 6D34 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F907
+2F908 ; mapped ; 6E2F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F908
+2F909 ; mapped ; 6E6E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F909
+2F90A ; mapped ; 3D33 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90A
+2F90B ; mapped ; 6ECB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90B
+2F90C ; mapped ; 6EC7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90C
+2F90D ; mapped ; 23ED1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90D
+2F90E ; mapped ; 6DF9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90E
+2F90F ; mapped ; 6F6E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F90F
+2F910 ; mapped ; 23F5E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F910
+2F911 ; mapped ; 23F8E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F911
+2F912 ; mapped ; 6FC6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F912
+2F913 ; mapped ; 7039 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F913
+2F914 ; mapped ; 701E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F914
+2F915 ; mapped ; 701B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F915
+2F916 ; mapped ; 3D96 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F916
+2F917 ; mapped ; 704A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F917
+2F918 ; mapped ; 707D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F918
+2F919 ; mapped ; 7077 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F919
+2F91A ; mapped ; 70AD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91A
+2F91B ; mapped ; 20525 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91B
+2F91C ; mapped ; 7145 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91C
+2F91D ; mapped ; 24263 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91D
+2F91E ; mapped ; 719C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91E
+2F91F ; disallowed # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F91F
+2F920 ; mapped ; 7228 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F920
+2F921 ; mapped ; 7235 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F921
+2F922 ; mapped ; 7250 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F922
+2F923 ; mapped ; 24608 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F923
+2F924 ; mapped ; 7280 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F924
+2F925 ; mapped ; 7295 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F925
+2F926 ; mapped ; 24735 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F926
+2F927 ; mapped ; 24814 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F927
+2F928 ; mapped ; 737A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F928
+2F929 ; mapped ; 738B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F929
+2F92A ; mapped ; 3EAC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F92A
+2F92B ; mapped ; 73A5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F92B
+2F92C..2F92D ; mapped ; 3EB8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F92C..CJK COMPATIBILITY IDEOGRAPH-2F92D
+2F92E ; mapped ; 7447 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F92E
+2F92F ; mapped ; 745C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F92F
+2F930 ; mapped ; 7471 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F930
+2F931 ; mapped ; 7485 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F931
+2F932 ; mapped ; 74CA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F932
+2F933 ; mapped ; 3F1B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F933
+2F934 ; mapped ; 7524 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F934
+2F935 ; mapped ; 24C36 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F935
+2F936 ; mapped ; 753E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F936
+2F937 ; mapped ; 24C92 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F937
+2F938 ; mapped ; 7570 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F938
+2F939 ; mapped ; 2219F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F939
+2F93A ; mapped ; 7610 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93A
+2F93B ; mapped ; 24FA1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93B
+2F93C ; mapped ; 24FB8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93C
+2F93D ; mapped ; 25044 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93D
+2F93E ; mapped ; 3FFC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93E
+2F93F ; mapped ; 4008 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F93F
+2F940 ; mapped ; 76F4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F940
+2F941 ; mapped ; 250F3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F941
+2F942 ; mapped ; 250F2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F942
+2F943 ; mapped ; 25119 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F943
+2F944 ; mapped ; 25133 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F944
+2F945 ; mapped ; 771E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F945
+2F946..2F947 ; mapped ; 771F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F946..CJK COMPATIBILITY IDEOGRAPH-2F947
+2F948 ; mapped ; 774A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F948
+2F949 ; mapped ; 4039 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F949
+2F94A ; mapped ; 778B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94A
+2F94B ; mapped ; 4046 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94B
+2F94C ; mapped ; 4096 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94C
+2F94D ; mapped ; 2541D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94D
+2F94E ; mapped ; 784E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94E
+2F94F ; mapped ; 788C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F94F
+2F950 ; mapped ; 78CC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F950
+2F951 ; mapped ; 40E3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F951
+2F952 ; mapped ; 25626 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F952
+2F953 ; mapped ; 7956 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F953
+2F954 ; mapped ; 2569A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F954
+2F955 ; mapped ; 256C5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F955
+2F956 ; mapped ; 798F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F956
+2F957 ; mapped ; 79EB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F957
+2F958 ; mapped ; 412F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F958
+2F959 ; mapped ; 7A40 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F959
+2F95A ; mapped ; 7A4A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F95A
+2F95B ; mapped ; 7A4F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F95B
+2F95C ; mapped ; 2597C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F95C
+2F95D..2F95E ; mapped ; 25AA7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F95D..CJK COMPATIBILITY IDEOGRAPH-2F95E
+2F95F ; disallowed # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F95F
+2F960 ; mapped ; 4202 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F960
+2F961 ; mapped ; 25BAB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F961
+2F962 ; mapped ; 7BC6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F962
+2F963 ; mapped ; 7BC9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F963
+2F964 ; mapped ; 4227 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F964
+2F965 ; mapped ; 25C80 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F965
+2F966 ; mapped ; 7CD2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F966
+2F967 ; mapped ; 42A0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F967
+2F968 ; mapped ; 7CE8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F968
+2F969 ; mapped ; 7CE3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F969
+2F96A ; mapped ; 7D00 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96A
+2F96B ; mapped ; 25F86 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96B
+2F96C ; mapped ; 7D63 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96C
+2F96D ; mapped ; 4301 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96D
+2F96E ; mapped ; 7DC7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96E
+2F96F ; mapped ; 7E02 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F96F
+2F970 ; mapped ; 7E45 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F970
+2F971 ; mapped ; 4334 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F971
+2F972 ; mapped ; 26228 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F972
+2F973 ; mapped ; 26247 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F973
+2F974 ; mapped ; 4359 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F974
+2F975 ; mapped ; 262D9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F975
+2F976 ; mapped ; 7F7A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F976
+2F977 ; mapped ; 2633E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F977
+2F978 ; mapped ; 7F95 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F978
+2F979 ; mapped ; 7FFA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F979
+2F97A ; mapped ; 8005 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97A
+2F97B ; mapped ; 264DA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97B
+2F97C ; mapped ; 26523 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97C
+2F97D ; mapped ; 8060 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97D
+2F97E ; mapped ; 265A8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97E
+2F97F ; mapped ; 8070 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F97F
+2F980 ; mapped ; 2335F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F980
+2F981 ; mapped ; 43D5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F981
+2F982 ; mapped ; 80B2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F982
+2F983 ; mapped ; 8103 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F983
+2F984 ; mapped ; 440B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F984
+2F985 ; mapped ; 813E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F985
+2F986 ; mapped ; 5AB5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F986
+2F987 ; mapped ; 267A7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F987
+2F988 ; mapped ; 267B5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F988
+2F989 ; mapped ; 23393 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F989
+2F98A ; mapped ; 2339C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98A
+2F98B ; mapped ; 8201 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98B
+2F98C ; mapped ; 8204 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98C
+2F98D ; mapped ; 8F9E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98D
+2F98E ; mapped ; 446B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98E
+2F98F ; mapped ; 8291 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F98F
+2F990 ; mapped ; 828B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F990
+2F991 ; mapped ; 829D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F991
+2F992 ; mapped ; 52B3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F992
+2F993 ; mapped ; 82B1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F993
+2F994 ; mapped ; 82B3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F994
+2F995 ; mapped ; 82BD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F995
+2F996 ; mapped ; 82E6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F996
+2F997 ; mapped ; 26B3C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F997
+2F998 ; mapped ; 82E5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F998
+2F999 ; mapped ; 831D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F999
+2F99A ; mapped ; 8363 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99A
+2F99B ; mapped ; 83AD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99B
+2F99C ; mapped ; 8323 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99C
+2F99D ; mapped ; 83BD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99D
+2F99E ; mapped ; 83E7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99E
+2F99F ; mapped ; 8457 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F99F
+2F9A0 ; mapped ; 8353 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A0
+2F9A1 ; mapped ; 83CA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A1
+2F9A2 ; mapped ; 83CC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A2
+2F9A3 ; mapped ; 83DC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A3
+2F9A4 ; mapped ; 26C36 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A4
+2F9A5 ; mapped ; 26D6B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A5
+2F9A6 ; mapped ; 26CD5 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A6
+2F9A7 ; mapped ; 452B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A7
+2F9A8 ; mapped ; 84F1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A8
+2F9A9 ; mapped ; 84F3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9A9
+2F9AA ; mapped ; 8516 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AA
+2F9AB ; mapped ; 273CA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AB
+2F9AC ; mapped ; 8564 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AC
+2F9AD ; mapped ; 26F2C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AD
+2F9AE ; mapped ; 455D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AE
+2F9AF ; mapped ; 4561 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9AF
+2F9B0 ; mapped ; 26FB1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B0
+2F9B1 ; mapped ; 270D2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B1
+2F9B2 ; mapped ; 456B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B2
+2F9B3 ; mapped ; 8650 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B3
+2F9B4 ; mapped ; 865C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B4
+2F9B5 ; mapped ; 8667 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B5
+2F9B6 ; mapped ; 8669 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B6
+2F9B7 ; mapped ; 86A9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B7
+2F9B8 ; mapped ; 8688 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B8
+2F9B9 ; mapped ; 870E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9B9
+2F9BA ; mapped ; 86E2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BA
+2F9BB ; mapped ; 8779 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BB
+2F9BC ; mapped ; 8728 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BC
+2F9BD ; mapped ; 876B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BD
+2F9BE ; mapped ; 8786 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BE
+2F9BF ; disallowed # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9BF
+2F9C0 ; mapped ; 87E1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C0
+2F9C1 ; mapped ; 8801 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C1
+2F9C2 ; mapped ; 45F9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C2
+2F9C3 ; mapped ; 8860 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C3
+2F9C4 ; mapped ; 8863 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C4
+2F9C5 ; mapped ; 27667 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C5
+2F9C6 ; mapped ; 88D7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C6
+2F9C7 ; mapped ; 88DE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C7
+2F9C8 ; mapped ; 4635 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C8
+2F9C9 ; mapped ; 88FA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9C9
+2F9CA ; mapped ; 34BB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CA
+2F9CB ; mapped ; 278AE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CB
+2F9CC ; mapped ; 27966 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CC
+2F9CD ; mapped ; 46BE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CD
+2F9CE ; mapped ; 46C7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CE
+2F9CF ; mapped ; 8AA0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9CF
+2F9D0 ; mapped ; 8AED # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D0
+2F9D1 ; mapped ; 8B8A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D1
+2F9D2 ; mapped ; 8C55 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D2
+2F9D3 ; mapped ; 27CA8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D3
+2F9D4 ; mapped ; 8CAB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D4
+2F9D5 ; mapped ; 8CC1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D5
+2F9D6 ; mapped ; 8D1B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D6
+2F9D7 ; mapped ; 8D77 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D7
+2F9D8 ; mapped ; 27F2F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D8
+2F9D9 ; mapped ; 20804 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9D9
+2F9DA ; mapped ; 8DCB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DA
+2F9DB ; mapped ; 8DBC # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DB
+2F9DC ; mapped ; 8DF0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DC
+2F9DD ; mapped ; 208DE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DD
+2F9DE ; mapped ; 8ED4 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DE
+2F9DF ; mapped ; 8F38 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9DF
+2F9E0 ; mapped ; 285D2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E0
+2F9E1 ; mapped ; 285ED # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E1
+2F9E2 ; mapped ; 9094 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E2
+2F9E3 ; mapped ; 90F1 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E3
+2F9E4 ; mapped ; 9111 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E4
+2F9E5 ; mapped ; 2872E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E5
+2F9E6 ; mapped ; 911B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E6
+2F9E7 ; mapped ; 9238 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E7
+2F9E8 ; mapped ; 92D7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E8
+2F9E9 ; mapped ; 92D8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9E9
+2F9EA ; mapped ; 927C # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9EA
+2F9EB ; mapped ; 93F9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9EB
+2F9EC ; mapped ; 9415 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9EC
+2F9ED ; mapped ; 28BFA # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9ED
+2F9EE ; mapped ; 958B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9EE
+2F9EF ; mapped ; 4995 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9EF
+2F9F0 ; mapped ; 95B7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F0
+2F9F1 ; mapped ; 28D77 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F1
+2F9F2 ; mapped ; 49E6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F2
+2F9F3 ; mapped ; 96C3 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F3
+2F9F4 ; mapped ; 5DB2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F4
+2F9F5 ; mapped ; 9723 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F5
+2F9F6 ; mapped ; 29145 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F6
+2F9F7 ; mapped ; 2921A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F7
+2F9F8 ; mapped ; 4A6E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F8
+2F9F9 ; mapped ; 4A76 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9F9
+2F9FA ; mapped ; 97E0 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9FA
+2F9FB ; mapped ; 2940A # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9FB
+2F9FC ; mapped ; 4AB2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9FC
+2F9FD ; mapped ; 29496 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9FD
+2F9FE..2F9FF ; mapped ; 980B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F9FE..CJK COMPATIBILITY IDEOGRAPH-2F9FF
+2FA00 ; mapped ; 9829 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA00
+2FA01 ; mapped ; 295B6 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA01
+2FA02 ; mapped ; 98E2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA02
+2FA03 ; mapped ; 4B33 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA03
+2FA04 ; mapped ; 9929 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA04
+2FA05 ; mapped ; 99A7 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA05
+2FA06 ; mapped ; 99C2 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA06
+2FA07 ; mapped ; 99FE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA07
+2FA08 ; mapped ; 4BCE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA08
+2FA09 ; mapped ; 29B30 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA09
+2FA0A ; mapped ; 9B12 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0A
+2FA0B ; mapped ; 9C40 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0B
+2FA0C ; mapped ; 9CFD # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0C
+2FA0D ; mapped ; 4CCE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0D
+2FA0E ; mapped ; 4CED # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0E
+2FA0F ; mapped ; 9D67 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA0F
+2FA10 ; mapped ; 2A0CE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA10
+2FA11 ; mapped ; 4CF8 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA11
+2FA12 ; mapped ; 2A105 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA12
+2FA13 ; mapped ; 2A20E # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA13
+2FA14 ; mapped ; 2A291 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA14
+2FA15 ; mapped ; 9EBB # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA15
+2FA16 ; mapped ; 4D56 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA16
+2FA17 ; mapped ; 9EF9 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA17
+2FA18 ; mapped ; 9EFE # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA18
+2FA19 ; mapped ; 9F05 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA19
+2FA1A ; mapped ; 9F0F # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA1A
+2FA1B ; mapped ; 9F16 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA1B
+2FA1C ; mapped ; 9F3B # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA1C
+2FA1D ; mapped ; 2A600 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2FA1D
+2FA1E..2FFFD ; disallowed # NA <reserved-2FA1E>..<reserved-2FFFD>
+2FFFE..2FFFF ; disallowed # 2.0 <noncharacter-2FFFE>..<noncharacter-2FFFF>
+30000..3134A ; valid # 13.0 CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
+3134B..3FFFD ; disallowed # NA <reserved-3134B>..<reserved-3FFFD>
+3FFFE..3FFFF ; disallowed # 2.0 <noncharacter-3FFFE>..<noncharacter-3FFFF>
+40000..4FFFD ; disallowed # NA <reserved-40000>..<reserved-4FFFD>
+4FFFE..4FFFF ; disallowed # 2.0 <noncharacter-4FFFE>..<noncharacter-4FFFF>
+50000..5FFFD ; disallowed # NA <reserved-50000>..<reserved-5FFFD>
+5FFFE..5FFFF ; disallowed # 2.0 <noncharacter-5FFFE>..<noncharacter-5FFFF>
+60000..6FFFD ; disallowed # NA <reserved-60000>..<reserved-6FFFD>
+6FFFE..6FFFF ; disallowed # 2.0 <noncharacter-6FFFE>..<noncharacter-6FFFF>
+70000..7FFFD ; disallowed # NA <reserved-70000>..<reserved-7FFFD>
+7FFFE..7FFFF ; disallowed # 2.0 <noncharacter-7FFFE>..<noncharacter-7FFFF>
+80000..8FFFD ; disallowed # NA <reserved-80000>..<reserved-8FFFD>
+8FFFE..8FFFF ; disallowed # 2.0 <noncharacter-8FFFE>..<noncharacter-8FFFF>
+90000..9FFFD ; disallowed # NA <reserved-90000>..<reserved-9FFFD>
+9FFFE..9FFFF ; disallowed # 2.0 <noncharacter-9FFFE>..<noncharacter-9FFFF>
+A0000..AFFFD ; disallowed # NA <reserved-A0000>..<reserved-AFFFD>
+AFFFE..AFFFF ; disallowed # 2.0 <noncharacter-AFFFE>..<noncharacter-AFFFF>
+B0000..BFFFD ; disallowed # NA <reserved-B0000>..<reserved-BFFFD>
+BFFFE..BFFFF ; disallowed # 2.0 <noncharacter-BFFFE>..<noncharacter-BFFFF>
+C0000..CFFFD ; disallowed # NA <reserved-C0000>..<reserved-CFFFD>
+CFFFE..CFFFF ; disallowed # 2.0 <noncharacter-CFFFE>..<noncharacter-CFFFF>
+D0000..DFFFD ; disallowed # NA <reserved-D0000>..<reserved-DFFFD>
+DFFFE..DFFFF ; disallowed # 2.0 <noncharacter-DFFFE>..<noncharacter-DFFFF>
+E0000 ; disallowed # NA <reserved-E0000>
+E0001 ; disallowed # 3.1 LANGUAGE TAG
+E0002..E001F ; disallowed # NA <reserved-E0002>..<reserved-E001F>
+E0020..E007F ; disallowed # 3.1 TAG SPACE..CANCEL TAG
+E0080..E00FF ; disallowed # NA <reserved-E0080>..<reserved-E00FF>
+E0100..E01EF ; ignored # 4.0 VARIATION SELECTOR-17..VARIATION SELECTOR-256
+E01F0..EFFFD ; disallowed # NA <reserved-E01F0>..<reserved-EFFFD>
+EFFFE..EFFFF ; disallowed # 2.0 <noncharacter-EFFFE>..<noncharacter-EFFFF>
+F0000..FFFFD ; disallowed # 2.0 <private-use-F0000>..<private-use-FFFFD>
+FFFFE..FFFFF ; disallowed # 2.0 <noncharacter-FFFFE>..<noncharacter-FFFFF>
+100000..10FFFD; disallowed # 2.0 <private-use-100000>..<private-use-10FFFD>
+10FFFE..10FFFF; disallowed # 2.0 <noncharacter-10FFFE>..<noncharacter-10FFFF>
+
+# Total code points: 1114112
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index 45bba85213b..4b3e72f0131 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -29,6 +29,9 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
EMACS = ${top_builddir}/src/emacs
unidir = ${top_srcdir}/lisp/international
emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
@@ -41,7 +44,9 @@ 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 ${unidir}/uni-confusable.el \
+ ${unidir}/idna-mapping.el
## Specify .elc as an order-only prereq so as to not needlessly rebuild
## target just because the .elc is missing.
@@ -79,6 +84,23 @@ ${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.el -f unidata-gen-scripts $@
+
+${unidir}/uni-confusable.el: ${srcdir}/unidata-gen.el \
+ ${srcdir}/confusables.txt
+ $(AM_V_GEN)${emacs} -L ${srcdir} \
+ -l unidata-gen.el -f unidata-gen-confusable $@
+
+${unidir}/idna-mapping.el: ${srcdir}/unidata-gen.el \
+ ${srcdir}/IdnaMappingTable.txt
+ $(AM_V_GEN)${emacs} -L ${srcdir} \
+ -l unidata-gen.el -f unidata-gen-idna-mapping $@
+
.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; <none>
+
+# Bidi_Paired_Bracket (bpb)
+
+# @missing: 0000..10FFFF; Bidi_Paired_Bracket; <none>
+
+# 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; <code point>
+
+# 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; <code point>
+
+# 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; <none>
+
+# 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; <code point>
+
+# 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; <none>
+
+# 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; <none>
+
+# 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; <code point>
+
+# 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; <code point>
+
+# 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; <none>
+
+# Name_Alias (Name_Alias)
+
+# @missing: 0000..10FFFF; Name_Alias; <none>
+
+# 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; <script>
+
+# Sentence_Break (SB)
+
+SB ; AT ; ATerm
+SB ; CL ; Close
+SB ; CR ; CR
+SB ; EX ; Extend
+SB ; FO ; Format
+SB ; LE ; OLetter
+SB ; LF ; LF
+SB ; LO ; Lower
+SB ; NU ; Numeric
+SB ; SC ; SContinue
+SB ; SE ; Sep
+SB ; SP ; Sp
+SB ; ST ; STerm
+SB ; UP ; Upper
+SB ; XX ; Other
+
+# Sentence_Terminal (STerm)
+
+STerm; N ; No ; F ; False
+STerm; Y ; Yes ; T ; True
+
+# Simple_Case_Folding (scf)
+
+# @missing: 0000..10FFFF; Simple_Case_Folding; <code point>
+
+# Simple_Lowercase_Mapping (slc)
+
+# @missing: 0000..10FFFF; Simple_Lowercase_Mapping; <code point>
+
+# Simple_Titlecase_Mapping (stc)
+
+# @missing: 0000..10FFFF; Simple_Titlecase_Mapping; <code point>
+
+# Simple_Uppercase_Mapping (suc)
+
+# @missing: 0000..10FFFF; Simple_Uppercase_Mapping; <code point>
+
+# Soft_Dotted (SD)
+
+SD ; N ; No ; F ; False
+SD ; Y ; Yes ; T ; True
+
+# Terminal_Punctuation (Term)
+
+Term; N ; No ; F ; False
+Term; Y ; Yes ; T ; True
+
+# Titlecase_Mapping (tc)
+
+# @missing: 0000..10FFFF; Titlecase_Mapping; <code point>
+
+# Unicode_1_Name (na1)
+
+# @missing: 0000..10FFFF; Unicode_1_Name; <none>
+
+# Unified_Ideograph (UIdeo)
+
+UIdeo; N ; No ; F ; False
+UIdeo; Y ; Yes ; T ; True
+
+# Uppercase (Upper)
+
+Upper; N ; No ; F ; False
+Upper; Y ; Yes ; T ; True
+
+# Uppercase_Mapping (uc)
+
+# @missing: 0000..10FFFF; Uppercase_Mapping; <code point>
+
+# Variation_Selector (VS)
+
+VS ; N ; No ; F ; False
+VS ; Y ; Yes ; T ; True
+
+# Vertical_Orientation (vo)
+
+vo ; R ; Rotated
+vo ; Tr ; Transformed_Rotated
+vo ; Tu ; Transformed_Upright
+vo ; U ; Upright
+
+# White_Space (WSpace)
+
+WSpace; N ; No ; F ; False
+WSpace; Y ; Yes ; T ; True
+
+# Word_Break (WB)
+
+WB ; CR ; CR
+WB ; DQ ; Double_Quote
+WB ; EB ; E_Base
+WB ; EBG ; E_Base_GAZ
+WB ; EM ; E_Modifier
+WB ; EX ; ExtendNumLet
+WB ; Extend ; Extend
+WB ; FO ; Format
+WB ; GAZ ; Glue_After_Zwj
+WB ; HL ; Hebrew_Letter
+WB ; KA ; Katakana
+WB ; LE ; ALetter
+WB ; LF ; LF
+WB ; MB ; MidNumLet
+WB ; ML ; MidLetter
+WB ; MN ; MidNum
+WB ; NL ; Newline
+WB ; NU ; Numeric
+WB ; RI ; Regional_Indicator
+WB ; SQ ; Single_Quote
+WB ; WSegSpace ; WSegSpace
+WB ; XX ; Other
+WB ; ZWJ ; ZWJ
+
+# XID_Continue (XIDC)
+
+XIDC; N ; No ; F ; False
+XIDC; Y ; Yes ; T ; True
+
+# XID_Start (XIDS)
+
+XIDS; N ; No ; F ; False
+XIDS; Y ; Yes ; T ; True
+
+# cjkAccountingNumeric (cjkAccountingNumeric)
+
+# @missing: 0000..10FFFF; cjkAccountingNumeric; NaN
+
+# cjkCompatibilityVariant (cjkCompatibilityVariant)
+
+# @missing: 0000..10FFFF; cjkCompatibilityVariant; <code point>
+
+# cjkIICore (cjkIICore)
+
+# @missing: 0000..10FFFF; cjkIICore; <none>
+
+# cjkIRG_GSource (cjkIRG_GSource)
+
+# @missing: 0000..10FFFF; cjkIRG_GSource; <none>
+
+# cjkIRG_HSource (cjkIRG_HSource)
+
+# @missing: 0000..10FFFF; cjkIRG_HSource; <none>
+
+# cjkIRG_JSource (cjkIRG_JSource)
+
+# @missing: 0000..10FFFF; cjkIRG_JSource; <none>
+
+# cjkIRG_KPSource (cjkIRG_KPSource)
+
+# @missing: 0000..10FFFF; cjkIRG_KPSource; <none>
+
+# cjkIRG_KSource (cjkIRG_KSource)
+
+# @missing: 0000..10FFFF; cjkIRG_KSource; <none>
+
+# cjkIRG_MSource (cjkIRG_MSource)
+
+# @missing: 0000..10FFFF; cjkIRG_MSource; <none>
+
+# cjkIRG_SSource (cjkIRG_SSource)
+
+# @missing: 0000..10FFFF; cjkIRG_SSource; <none>
+
+# cjkIRG_TSource (cjkIRG_TSource)
+
+# @missing: 0000..10FFFF; cjkIRG_TSource; <none>
+
+# cjkIRG_UKSource (cjkIRG_UKSource)
+
+# @missing: 0000..10FFFF; cjkIRG_UKSource; <none>
+
+# cjkIRG_USource (cjkIRG_USource)
+
+# @missing: 0000..10FFFF; cjkIRG_USource; <none>
+
+# cjkIRG_VSource (cjkIRG_VSource)
+
+# @missing: 0000..10FFFF; cjkIRG_VSource; <none>
+
+# cjkOtherNumeric (cjkOtherNumeric)
+
+# @missing: 0000..10FFFF; cjkOtherNumeric; NaN
+
+# cjkPrimaryNumeric (cjkPrimaryNumeric)
+
+# @missing: 0000..10FFFF; cjkPrimaryNumeric; NaN
+
+# cjkRSUnicode (cjkRSUnicode)
+
+# @missing: 0000..10FFFF; cjkRSUnicode; <none>
+
+# EOF
diff --git a/admin/unidata/README b/admin/unidata/README
index 4b8444b0fec..2da01402b70 100644
--- a/admin/unidata/README
+++ b/admin/unidata/README
@@ -48,3 +48,19 @@ https://www.unicode.org/Public/emoji/14.0/emoji-sequences.txt
emoji-test.txt
https://unicode.org/Public/emoji/14.0/emoji-test.txt
2021-10-28
+
+ScriptExtensions.txt
+https://www.unicode.org/Public/UCD/latest/ucd/ScriptExtensions.txt
+2022-01-17
+
+Scripts.txt
+https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt
+2022-01-17
+
+PropertyValueAliases.txt
+https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt
+2022-01-17
+
+IdnaMappingTable.txt
+https://www.unicode.org/Public/idna/latest/IdnaMappingTable.txt
+2022-01-18
diff --git a/admin/unidata/ScriptExtensions.txt b/admin/unidata/ScriptExtensions.txt
new file mode 100644
index 00000000000..3f5cd1c0dbb
--- /dev/null
+++ b/admin/unidata/ScriptExtensions.txt
@@ -0,0 +1,628 @@
+# ScriptExtensions-14.0.0.txt
+# Date: 2021-06-04, 02:19:38 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/
+#
+# The Script_Extensions property indicates which characters are commonly used
+# with more than one script, but with a limited number of scripts.
+# For each code point, there is one or more property values. Each such value is a Script property value.
+# For more information, see:
+# UAX #24, Unicode Script Property: https://www.unicode.org/reports/tr24/
+# Especially the sections:
+# https://www.unicode.org/reports/tr24/#Assignment_Script_Values
+# https://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values
+#
+# Each Script_Extensions value in this file consists of a set
+# of one or more abbreviated Script property values. The ordering of the
+# values in that set is not material, but for stability in presentation
+# it is given here as alphabetical.
+#
+# The Script_Extensions values are presented in sorted order in the file.
+# They are sorted first by the number of Script property values in their sets,
+# and then alphabetically by first differing Script property value.
+#
+# Following each distinct Script_Extensions value is the list of code
+# points associated with that value, listed in code point order.
+#
+# All code points not explicitly listed for Script_Extensions
+# have as their value the corresponding Script property value
+#
+# @missing: 0000..10FFFF; <script>
+
+# ================================================
+
+# Property: Script_Extensions
+
+# ================================================
+
+# Script_Extensions=Beng
+
+1CF7 ; Beng # Mc VEDIC SIGN ATIKRAMA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva
+
+1CD1 ; Deva # Mn VEDIC TONE SHARA
+1CD4 ; Deva # Mn VEDIC SIGN YAJURVEDIC MIDLINE SVARITA
+1CDB ; Deva # Mn VEDIC TONE TRIPLE SVARITA
+1CDE..1CDF ; Deva # Mn [2] VEDIC TONE TWO DOTS BELOW..VEDIC TONE THREE DOTS BELOW
+1CE2..1CE8 ; Deva # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
+1CEB..1CEC ; Deva # Lo [2] VEDIC SIGN ANUSVARA VAMAGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL
+1CEE..1CF1 ; Deva # Lo [4] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ANUSVARA UBHAYATO MUKHA
+
+# Total code points: 18
+
+# ================================================
+
+# Script_Extensions=Dupl
+
+1BCA0..1BCA3 ; Dupl # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Grek
+
+0342 ; Grek # Mn COMBINING GREEK PERISPOMENI
+0345 ; Grek # Mn COMBINING GREEK YPOGEGRAMMENI
+1DC0..1DC1 ; Grek # Mn [2] COMBINING DOTTED GRAVE ACCENT..COMBINING DOTTED ACUTE ACCENT
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Hani
+
+3006 ; Hani # Lo IDEOGRAPHIC CLOSING MARK
+303E..303F ; Hani # So [2] IDEOGRAPHIC VARIATION INDICATOR..IDEOGRAPHIC HALF FILL SPACE
+3190..3191 ; Hani # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
+3192..3195 ; Hani # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
+3196..319F ; Hani # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
+31C0..31E3 ; Hani # So [36] CJK STROKE T..CJK STROKE Q
+3220..3229 ; Hani # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
+322A..3247 ; Hani # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
+3280..3289 ; Hani # No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN
+328A..32B0 ; Hani # So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT
+32C0..32CB ; Hani # So [12] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER
+32FF ; Hani # So SQUARE ERA NAME REIWA
+3358..3370 ; Hani # So [25] IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO..IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR
+337B..337F ; Hani # So [5] SQUARE ERA NAME HEISEI..SQUARE CORPORATION
+33E0..33FE ; Hani # So [31] IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE..IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE
+1D360..1D371 ; Hani # No [18] COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE
+1F250..1F251 ; Hani # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
+
+# Total code points: 238
+
+# ================================================
+
+# Script_Extensions=Latn
+
+0363..036F ; Latn # Mn [13] COMBINING LATIN SMALL LETTER A..COMBINING LATIN SMALL LETTER X
+
+# Total code points: 13
+
+# ================================================
+
+# Script_Extensions=Nand
+
+1CFA ; Nand # Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Syrc
+
+1DFA ; Syrc # Mn COMBINING DOT BELOW LEFT
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Arab Copt
+
+102E0 ; Arab Copt # Mn COPTIC EPACT THOUSANDS MARK
+102E1..102FB ; Arab Copt # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
+
+# Total code points: 28
+
+# ================================================
+
+# Script_Extensions=Arab Rohg
+
+06D4 ; Arab Rohg # Po ARABIC FULL STOP
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Arab Nkoo
+
+FD3E ; Arab Nkoo # Pe ORNATE LEFT PARENTHESIS
+FD3F ; Arab Nkoo # Ps ORNATE RIGHT PARENTHESIS
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Arab Syrc
+
+064B..0655 ; Arab Syrc # Mn [11] ARABIC FATHATAN..ARABIC HAMZA BELOW
+0670 ; Arab Syrc # Mn ARABIC LETTER SUPERSCRIPT ALEF
+
+# Total code points: 12
+
+# ================================================
+
+# Script_Extensions=Arab Thaa
+
+FDF2 ; Arab Thaa # Lo ARABIC LIGATURE ALLAH ISOLATED FORM
+FDFD ; Arab Thaa # So ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Beng Deva
+
+1CD5..1CD6 ; Beng Deva # Mn [2] VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA..VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA
+1CD8 ; Beng Deva # Mn VEDIC TONE CANDRA BELOW
+1CE1 ; Beng Deva # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
+1CEA ; Beng Deva # Lo VEDIC SIGN ANUSVARA BAHIRGOMUKHA
+1CED ; Beng Deva # Mn VEDIC SIGN TIRYAK
+1CF5..1CF6 ; Beng Deva # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA
+A8F1 ; Beng Deva # Mn COMBINING DEVANAGARI SIGN AVAGRAHA
+
+# Total code points: 9
+
+# ================================================
+
+# Script_Extensions=Bopo Hani
+
+302A..302D ; Bopo Hani # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Bugi Java
+
+A9CF ; Bugi Java # Lm JAVANESE PANGRANGKEP
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Cprt Linb
+
+10102 ; Cprt Linb # Po AEGEAN CHECK MARK
+10137..1013F ; Cprt Linb # So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Cyrl Glag
+
+0484 ; Cyrl Glag # Mn COMBINING CYRILLIC PALATALIZATION
+0487 ; Cyrl Glag # Mn COMBINING CYRILLIC POKRYTIE
+2E43 ; Cyrl Glag # Po DASH WITH LEFT UPTURN
+A66F ; Cyrl Glag # Mn COMBINING CYRILLIC VZMET
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Cyrl Latn
+
+0485..0486 ; Cyrl Latn # Mn [2] COMBINING CYRILLIC DASIA PNEUMATA..COMBINING CYRILLIC PSILI PNEUMATA
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Cyrl Perm
+
+0483 ; Cyrl Perm # Mn COMBINING CYRILLIC TITLO
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Cyrl Syrc
+
+1DF8 ; Cyrl Syrc # Mn COMBINING DOT ABOVE LEFT
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva Gran
+
+1CD3 ; Deva Gran # Po VEDIC SIGN NIHSHVASA
+1CF3 ; Deva Gran # Lo VEDIC SIGN ROTATED ARDHAVISARGA
+1CF8..1CF9 ; Deva Gran # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Deva Nand
+
+1CE9 ; Deva Nand # Lo VEDIC SIGN ANUSVARA ANTARGOMUKHA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva Shrd
+
+1CD7 ; Deva Shrd # Mn VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA
+1CD9 ; Deva Shrd # Mn VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER
+1CDC..1CDD ; Deva Shrd # Mn [2] VEDIC TONE KATHAKA ANUDATTA..VEDIC TONE DOT BELOW
+1CE0 ; Deva Shrd # Mn VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
+
+# Total code points: 5
+
+# ================================================
+
+# Script_Extensions=Deva Taml
+
+A8F3 ; Deva Taml # Lo DEVANAGARI SIGN CANDRABINDU VIRAMA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Geor Latn
+
+10FB ; Geor Latn # Po GEORGIAN PARAGRAPH SEPARATOR
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Gran Taml
+
+0BE6..0BEF ; Gran Taml # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
+0BF0..0BF2 ; Gran Taml # No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
+0BF3 ; Gran Taml # So TAMIL DAY SIGN
+11301 ; Gran Taml # Mn GRANTHA SIGN CANDRABINDU
+11303 ; Gran Taml # Mc GRANTHA SIGN VISARGA
+1133B..1133C ; Gran Taml # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
+11FD0..11FD1 ; Gran Taml # No [2] TAMIL FRACTION ONE QUARTER..TAMIL FRACTION ONE HALF-1
+11FD3 ; Gran Taml # No TAMIL FRACTION THREE QUARTERS
+
+# Total code points: 21
+
+# ================================================
+
+# Script_Extensions=Gujr Khoj
+
+0AE6..0AEF ; Gujr Khoj # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Guru Mult
+
+0A66..0A6F ; Guru Mult # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Hani Latn
+
+A700..A707 ; Hani Latn # Sk [8] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER CHINESE TONE YANG RU
+
+# Total code points: 8
+
+# ================================================
+
+# Script_Extensions=Hira Kana
+
+3031..3035 ; Hira Kana # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF
+3099..309A ; Hira Kana # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309B..309C ; Hira Kana # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+30A0 ; Hira Kana # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN
+30FC ; Hira Kana # Lm KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF70 ; Hira Kana # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF9E..FF9F ; Hira Kana # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+
+# Total code points: 14
+
+# ================================================
+
+# Script_Extensions=Knda Nand
+
+0CE6..0CEF ; Knda Nand # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Latn Mong
+
+202F ; Latn Mong # Zs NARROW NO-BREAK SPACE
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Mani Ougr
+
+10AF2 ; Mani Ougr # Po MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Mong Phag
+
+1802..1803 ; Mong Phag # Po [2] MONGOLIAN COMMA..MONGOLIAN FULL STOP
+1805 ; Mong Phag # Po MONGOLIAN FOUR DOTS
+
+# Total code points: 3
+
+# ================================================
+
+# Script_Extensions=Arab Syrc Thaa
+
+061C ; Arab Syrc Thaa # Cf ARABIC LETTER MARK
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Arab Thaa Yezi
+
+0660..0669 ; Arab Thaa Yezi # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Beng Cakm Sylo
+
+09E6..09EF ; Beng Cakm Sylo # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Cakm Mymr Tale
+
+1040..1049 ; Cakm Mymr Tale # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Cpmn Cprt Linb
+
+10100..10101 ; Cpmn Cprt Linb # Po [2] AEGEAN WORD SEPARATOR LINE..AEGEAN WORD SEPARATOR DOT
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Cprt Lina Linb
+
+10107..10133 ; Cprt Lina Linb # No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
+
+# Total code points: 45
+
+# ================================================
+
+# Script_Extensions=Deva Gran Knda
+
+1CF4 ; Deva Gran Knda # Mn VEDIC TONE CANDRA ABOVE
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva Gran Latn
+
+20F0 ; Deva Gran Latn # Mn COMBINING ASTERISK ABOVE
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Hani Hira Kana
+
+303C ; Hani Hira Kana # Lo MASU MARK
+303D ; Hani Hira Kana # Po PART ALTERNATION MARK
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Kali Latn Mymr
+
+A92E ; Kali Latn Mymr # Po KAYAH LI SIGN CWI
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Beng Deva Gran Knda
+
+1CD0 ; Beng Deva Gran Knda # Mn VEDIC TONE KARSHANA
+1CD2 ; Beng Deva Gran Knda # Mn VEDIC TONE PRENKHA
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Buhd Hano Tagb Tglg
+
+1735..1736 ; Buhd Hano Tagb Tglg # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Deva Dogr Kthi Mahj
+
+0966..096F ; Deva Dogr Kthi Mahj # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Bopo Hang Hani Hira Kana
+
+3003 ; Bopo Hang Hani Hira Kana # Po DITTO MARK
+3013 ; Bopo Hang Hani Hira Kana # So GETA MARK
+301C ; Bopo Hang Hani Hira Kana # Pd WAVE DASH
+301D ; Bopo Hang Hani Hira Kana # Ps REVERSED DOUBLE PRIME QUOTATION MARK
+301E..301F ; Bopo Hang Hani Hira Kana # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK
+3030 ; Bopo Hang Hani Hira Kana # Pd WAVY DASH
+3037 ; Bopo Hang Hani Hira Kana # So IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+FE45..FE46 ; Bopo Hang Hani Hira Kana # Po [2] SESAME DOT..WHITE SESAME DOT
+
+# Total code points: 10
+
+# ================================================
+
+# Script_Extensions=Arab Nkoo Rohg Syrc Thaa Yezi
+
+060C ; Arab Nkoo Rohg Syrc Thaa Yezi # Po ARABIC COMMA
+061B ; Arab Nkoo Rohg Syrc Thaa Yezi # Po ARABIC SEMICOLON
+
+# Total code points: 2
+
+# ================================================
+
+# Script_Extensions=Bopo Hang Hani Hira Kana Yiii
+
+3001..3002 ; Bopo Hang Hani Hira Kana Yiii # Po [2] IDEOGRAPHIC COMMA..IDEOGRAPHIC FULL STOP
+3008 ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT ANGLE BRACKET
+3009 ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT ANGLE BRACKET
+300A ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT DOUBLE ANGLE BRACKET
+300B ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT DOUBLE ANGLE BRACKET
+300C ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT CORNER BRACKET
+300D ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT CORNER BRACKET
+300E ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT WHITE CORNER BRACKET
+300F ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT WHITE CORNER BRACKET
+3010 ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT BLACK LENTICULAR BRACKET
+3011 ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT BLACK LENTICULAR BRACKET
+3014 ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT TORTOISE SHELL BRACKET
+3015 ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT TORTOISE SHELL BRACKET
+3016 ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT WHITE LENTICULAR BRACKET
+3017 ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT WHITE LENTICULAR BRACKET
+3018 ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT WHITE TORTOISE SHELL BRACKET
+3019 ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT WHITE TORTOISE SHELL BRACKET
+301A ; Bopo Hang Hani Hira Kana Yiii # Ps LEFT WHITE SQUARE BRACKET
+301B ; Bopo Hang Hani Hira Kana Yiii # Pe RIGHT WHITE SQUARE BRACKET
+30FB ; Bopo Hang Hani Hira Kana Yiii # Po KATAKANA MIDDLE DOT
+FF61 ; Bopo Hang Hani Hira Kana Yiii # Po HALFWIDTH IDEOGRAPHIC FULL STOP
+FF62 ; Bopo Hang Hani Hira Kana Yiii # Ps HALFWIDTH LEFT CORNER BRACKET
+FF63 ; Bopo Hang Hani Hira Kana Yiii # Pe HALFWIDTH RIGHT CORNER BRACKET
+FF64..FF65 ; Bopo Hang Hani Hira Kana Yiii # Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT
+
+# Total code points: 26
+
+# ================================================
+
+# Script_Extensions=Deva Knda Mlym Orya Taml Telu
+
+1CDA ; Deva Knda Mlym Orya Taml Telu # Mn VEDIC TONE DOUBLE SVARITA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Adlm Arab Nkoo Rohg Syrc Thaa Yezi
+
+061F ; Adlm Arab Nkoo Rohg Syrc Thaa Yezi # Po ARABIC QUESTION MARK
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Beng Deva Gran Knda Nand Orya Telu Tirh
+
+1CF2 ; Beng Deva Gran Knda Nand Orya Telu Tirh # Lo VEDIC SIGN ARDHAVISARGA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc
+
+0640 ; Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc # Lm ARABIC TATWEEL
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh
+
+A836..A837 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
+A838 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # Sc NORTH INDIC RUPEE MARK
+A839 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So NORTH INDIC QUANTITY MARK
+
+# Total code points: 4
+
+# ================================================
+
+# Script_Extensions=Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Taml Telu Tirh
+
+0952 ; Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Taml Telu Tirh # Mn DEVANAGARI STRESS SIGN ANUDATTA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Shrd Taml Telu Tirh
+
+0951 ; Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Shrd Taml Telu Tirh # Mn DEVANAGARI STRESS SIGN UDATTA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Sind Takr Tirh
+
+A833..A835 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE SIXTEENTH..NORTH INDIC FRACTION THREE SIXTEENTHS
+
+# Total code points: 3
+
+# ================================================
+
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Sind Takr Tirh
+
+A830..A832 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE QUARTERS
+
+# Total code points: 3
+
+# ================================================
+
+# Script_Extensions=Beng Deva Dogr Gong Gonm Gran Gujr Guru Knda Mahj Mlym Nand Orya Sind Sinh Sylo Takr Taml Telu Tirh
+
+0964 ; Beng Deva Dogr Gong Gonm Gran Gujr Guru Knda Mahj Mlym Nand Orya Sind Sinh Sylo Takr Taml Telu Tirh # Po DEVANAGARI DANDA
+
+# Total code points: 1
+
+# ================================================
+
+# Script_Extensions=Beng Deva Dogr Gong Gonm Gran Gujr Guru Knda Limb Mahj Mlym Nand Orya Sind Sinh Sylo Takr Taml Telu Tirh
+
+0965 ; Beng Deva Dogr Gong Gonm Gran Gujr Guru Knda Limb Mahj Mlym Nand Orya Sind Sinh Sylo Takr Taml Telu Tirh # Po DEVANAGARI DOUBLE DANDA
+
+# Total code points: 1
+
+# EOF
diff --git a/admin/unidata/Scripts.txt b/admin/unidata/Scripts.txt
new file mode 100644
index 00000000000..a1383730119
--- /dev/null
+++ b/admin/unidata/Scripts.txt
@@ -0,0 +1,2991 @@
+# Scripts-14.0.0.txt
+# Date: 2021-07-10, 00:35:31 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/
+# For more information, see:
+# UAX #24, Unicode Script Property: https://www.unicode.org/reports/tr24/
+# Especially the sections:
+# https://www.unicode.org/reports/tr24/#Assignment_Script_Values
+# https://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values
+#
+
+# ================================================
+
+# Property: Script
+
+# All code points not explicitly listed for Script
+# have the value Unknown (Zzzz).
+
+# @missing: 0000..10FFFF; Unknown
+
+# ================================================
+
+0000..001F ; Common # Cc [32] <control-0000>..<control-001F>
+0020 ; Common # Zs SPACE
+0021..0023 ; Common # Po [3] EXCLAMATION MARK..NUMBER SIGN
+0024 ; Common # Sc DOLLAR SIGN
+0025..0027 ; Common # Po [3] PERCENT SIGN..APOSTROPHE
+0028 ; Common # Ps LEFT PARENTHESIS
+0029 ; Common # Pe RIGHT PARENTHESIS
+002A ; Common # Po ASTERISK
+002B ; Common # Sm PLUS SIGN
+002C ; Common # Po COMMA
+002D ; Common # Pd HYPHEN-MINUS
+002E..002F ; Common # Po [2] FULL STOP..SOLIDUS
+0030..0039 ; Common # Nd [10] DIGIT ZERO..DIGIT NINE
+003A..003B ; Common # Po [2] COLON..SEMICOLON
+003C..003E ; Common # Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN
+003F..0040 ; Common # Po [2] QUESTION MARK..COMMERCIAL AT
+005B ; Common # Ps LEFT SQUARE BRACKET
+005C ; Common # Po REVERSE SOLIDUS
+005D ; Common # Pe RIGHT SQUARE BRACKET
+005E ; Common # Sk CIRCUMFLEX ACCENT
+005F ; Common # Pc LOW LINE
+0060 ; Common # Sk GRAVE ACCENT
+007B ; Common # Ps LEFT CURLY BRACKET
+007C ; Common # Sm VERTICAL LINE
+007D ; Common # Pe RIGHT CURLY BRACKET
+007E ; Common # Sm TILDE
+007F..009F ; Common # Cc [33] <control-007F>..<control-009F>
+00A0 ; Common # Zs NO-BREAK SPACE
+00A1 ; Common # Po INVERTED EXCLAMATION MARK
+00A2..00A5 ; Common # Sc [4] CENT SIGN..YEN SIGN
+00A6 ; Common # So BROKEN BAR
+00A7 ; Common # Po SECTION SIGN
+00A8 ; Common # Sk DIAERESIS
+00A9 ; Common # So COPYRIGHT SIGN
+00AB ; Common # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00AC ; Common # Sm NOT SIGN
+00AD ; Common # Cf SOFT HYPHEN
+00AE ; Common # So REGISTERED SIGN
+00AF ; Common # Sk MACRON
+00B0 ; Common # So DEGREE SIGN
+00B1 ; Common # Sm PLUS-MINUS SIGN
+00B2..00B3 ; Common # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE
+00B4 ; Common # Sk ACUTE ACCENT
+00B5 ; Common # L& MICRO SIGN
+00B6..00B7 ; Common # Po [2] PILCROW SIGN..MIDDLE DOT
+00B8 ; Common # Sk CEDILLA
+00B9 ; Common # No SUPERSCRIPT ONE
+00BB ; Common # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BC..00BE ; Common # No [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS
+00BF ; Common # Po INVERTED QUESTION MARK
+00D7 ; Common # Sm MULTIPLICATION SIGN
+00F7 ; Common # Sm DIVISION SIGN
+02B9..02C1 ; Common # Lm [9] MODIFIER LETTER PRIME..MODIFIER LETTER REVERSED GLOTTAL STOP
+02C2..02C5 ; Common # Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD
+02C6..02D1 ; Common # Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON
+02D2..02DF ; Common # Sk [14] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER CROSS ACCENT
+02E5..02E9 ; Common # Sk [5] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER EXTRA-LOW TONE BAR
+02EC ; Common # Lm MODIFIER LETTER VOICING
+02ED ; Common # Sk MODIFIER LETTER UNASPIRATED
+02EE ; Common # Lm MODIFIER LETTER DOUBLE APOSTROPHE
+02EF..02FF ; Common # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
+0374 ; Common # Lm GREEK NUMERAL SIGN
+037E ; Common # Po GREEK QUESTION MARK
+0385 ; Common # Sk GREEK DIALYTIKA TONOS
+0387 ; Common # Po GREEK ANO TELEIA
+0605 ; Common # Cf ARABIC NUMBER MARK ABOVE
+060C ; Common # Po ARABIC COMMA
+061B ; Common # Po ARABIC SEMICOLON
+061F ; Common # Po ARABIC QUESTION MARK
+0640 ; Common # Lm ARABIC TATWEEL
+06DD ; Common # Cf ARABIC END OF AYAH
+08E2 ; Common # Cf ARABIC DISPUTED END OF AYAH
+0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
+0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT
+0FD5..0FD8 ; Common # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS
+10FB ; Common # Po GEORGIAN PARAGRAPH SEPARATOR
+16EB..16ED ; Common # Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION
+1735..1736 ; Common # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
+1802..1803 ; Common # Po [2] MONGOLIAN COMMA..MONGOLIAN FULL STOP
+1805 ; Common # Po MONGOLIAN FOUR DOTS
+1CD3 ; Common # Po VEDIC SIGN NIHSHVASA
+1CE1 ; Common # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
+1CE9..1CEC ; Common # Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL
+1CEE..1CF3 ; Common # Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA
+1CF5..1CF6 ; Common # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA
+1CF7 ; Common # Mc VEDIC SIGN ATIKRAMA
+1CFA ; Common # Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA
+2000..200A ; Common # Zs [11] EN QUAD..HAIR SPACE
+200B ; Common # Cf ZERO WIDTH SPACE
+200E..200F ; Common # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK
+2010..2015 ; Common # Pd [6] HYPHEN..HORIZONTAL BAR
+2016..2017 ; Common # Po [2] DOUBLE VERTICAL LINE..DOUBLE LOW LINE
+2018 ; Common # Pi LEFT SINGLE QUOTATION MARK
+2019 ; Common # Pf RIGHT SINGLE QUOTATION MARK
+201A ; Common # Ps SINGLE LOW-9 QUOTATION MARK
+201B..201C ; Common # Pi [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK
+201D ; Common # Pf RIGHT DOUBLE QUOTATION MARK
+201E ; Common # Ps DOUBLE LOW-9 QUOTATION MARK
+201F ; Common # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+2020..2027 ; Common # Po [8] DAGGER..HYPHENATION POINT
+2028 ; Common # Zl LINE SEPARATOR
+2029 ; Common # Zp PARAGRAPH SEPARATOR
+202A..202E ; Common # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+202F ; Common # Zs NARROW NO-BREAK SPACE
+2030..2038 ; Common # Po [9] PER MILLE SIGN..CARET
+2039 ; Common # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A ; Common # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+203B..203E ; Common # Po [4] REFERENCE MARK..OVERLINE
+203F..2040 ; Common # Pc [2] UNDERTIE..CHARACTER TIE
+2041..2043 ; Common # Po [3] CARET INSERTION POINT..HYPHEN BULLET
+2044 ; Common # Sm FRACTION SLASH
+2045 ; Common # Ps LEFT SQUARE BRACKET WITH QUILL
+2046 ; Common # Pe RIGHT SQUARE BRACKET WITH QUILL
+2047..2051 ; Common # Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY
+2052 ; Common # Sm COMMERCIAL MINUS SIGN
+2053 ; Common # Po SWUNG DASH
+2054 ; Common # Pc INVERTED UNDERTIE
+2055..205E ; Common # Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS
+205F ; Common # Zs MEDIUM MATHEMATICAL SPACE
+2060..2064 ; Common # Cf [5] WORD JOINER..INVISIBLE PLUS
+2066..206F ; Common # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+2070 ; Common # No SUPERSCRIPT ZERO
+2074..2079 ; Common # No [6] SUPERSCRIPT FOUR..SUPERSCRIPT NINE
+207A..207C ; Common # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN
+207D ; Common # Ps SUPERSCRIPT LEFT PARENTHESIS
+207E ; Common # Pe SUPERSCRIPT RIGHT PARENTHESIS
+2080..2089 ; Common # No [10] SUBSCRIPT ZERO..SUBSCRIPT NINE
+208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
+208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS
+208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS
+20A0..20C0 ; Common # Sc [33] EURO-CURRENCY SIGN..SOM SIGN
+2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
+2102 ; Common # L& DOUBLE-STRUCK CAPITAL C
+2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA
+2107 ; Common # L& EULER CONSTANT
+2108..2109 ; Common # So [2] SCRUPLE..DEGREE FAHRENHEIT
+210A..2113 ; Common # L& [10] SCRIPT SMALL G..SCRIPT SMALL L
+2114 ; Common # So L B BAR SYMBOL
+2115 ; Common # L& DOUBLE-STRUCK CAPITAL N
+2116..2117 ; Common # So [2] NUMERO SIGN..SOUND RECORDING COPYRIGHT
+2118 ; Common # Sm SCRIPT CAPITAL P
+2119..211D ; Common # L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R
+211E..2123 ; Common # So [6] PRESCRIPTION TAKE..VERSICLE
+2124 ; Common # L& DOUBLE-STRUCK CAPITAL Z
+2125 ; Common # So OUNCE SIGN
+2127 ; Common # So INVERTED OHM SIGN
+2128 ; Common # L& BLACK-LETTER CAPITAL Z
+2129 ; Common # So TURNED GREEK SMALL LETTER IOTA
+212C..212D ; Common # L& [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C
+212E ; Common # So ESTIMATED SYMBOL
+212F..2131 ; Common # L& [3] SCRIPT SMALL E..SCRIPT CAPITAL F
+2133..2134 ; Common # L& [2] SCRIPT CAPITAL M..SCRIPT SMALL O
+2135..2138 ; Common # Lo [4] ALEF SYMBOL..DALET SYMBOL
+2139 ; Common # L& INFORMATION SOURCE
+213A..213B ; Common # So [2] ROTATED CAPITAL Q..FACSIMILE SIGN
+213C..213F ; Common # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI
+2140..2144 ; Common # Sm [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y
+2145..2149 ; Common # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J
+214A ; Common # So PROPERTY LINE
+214B ; Common # Sm TURNED AMPERSAND
+214C..214D ; Common # So [2] PER SIGN..AKTIESELSKAB
+214F ; Common # So SYMBOL FOR SAMARITAN SOURCE
+2150..215F ; Common # No [16] VULGAR FRACTION ONE SEVENTH..FRACTION NUMERATOR ONE
+2189 ; Common # No VULGAR FRACTION ZERO THIRDS
+218A..218B ; Common # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE
+2190..2194 ; Common # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
+2195..2199 ; Common # So [5] UP DOWN ARROW..SOUTH WEST ARROW
+219A..219B ; Common # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
+219C..219F ; Common # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW
+21A0 ; Common # Sm RIGHTWARDS TWO HEADED ARROW
+21A1..21A2 ; Common # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL
+21A3 ; Common # Sm RIGHTWARDS ARROW WITH TAIL
+21A4..21A5 ; Common # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR
+21A6 ; Common # Sm RIGHTWARDS ARROW FROM BAR
+21A7..21AD ; Common # So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW
+21AE ; Common # Sm LEFT RIGHT ARROW WITH STROKE
+21AF..21CD ; Common # So [31] DOWNWARDS ZIGZAG ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE
+21CE..21CF ; Common # Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE
+21D0..21D1 ; Common # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW
+21D2 ; Common # Sm RIGHTWARDS DOUBLE ARROW
+21D3 ; Common # So DOWNWARDS DOUBLE ARROW
+21D4 ; Common # Sm LEFT RIGHT DOUBLE ARROW
+21D5..21F3 ; Common # So [31] UP DOWN DOUBLE ARROW..UP DOWN WHITE ARROW
+21F4..22FF ; Common # Sm [268] RIGHT ARROW WITH SMALL CIRCLE..Z NOTATION BAG MEMBERSHIP
+2300..2307 ; Common # So [8] DIAMETER SIGN..WAVY LINE
+2308 ; Common # Ps LEFT CEILING
+2309 ; Common # Pe RIGHT CEILING
+230A ; Common # Ps LEFT FLOOR
+230B ; Common # Pe RIGHT FLOOR
+230C..231F ; Common # So [20] BOTTOM RIGHT CROP..BOTTOM RIGHT CORNER
+2320..2321 ; Common # Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL
+2322..2328 ; Common # So [7] FROWN..KEYBOARD
+2329 ; Common # Ps LEFT-POINTING ANGLE BRACKET
+232A ; Common # Pe RIGHT-POINTING ANGLE BRACKET
+232B..237B ; Common # So [81] ERASE TO THE LEFT..NOT CHECK MARK
+237C ; Common # Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+237D..239A ; Common # So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL
+239B..23B3 ; Common # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM
+23B4..23DB ; Common # So [40] TOP SQUARE BRACKET..FUSE
+23DC..23E1 ; Common # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET
+23E2..2426 ; Common # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO
+2440..244A ; Common # So [11] OCR HOOK..OCR DOUBLE BACKSLASH
+2460..249B ; Common # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP
+249C..24E9 ; Common # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z
+24EA..24FF ; Common # No [22] CIRCLED DIGIT ZERO..NEGATIVE CIRCLED DIGIT ZERO
+2500..25B6 ; Common # So [183] BOX DRAWINGS LIGHT HORIZONTAL..BLACK RIGHT-POINTING TRIANGLE
+25B7 ; Common # Sm WHITE RIGHT-POINTING TRIANGLE
+25B8..25C0 ; Common # So [9] BLACK RIGHT-POINTING SMALL TRIANGLE..BLACK LEFT-POINTING TRIANGLE
+25C1 ; Common # Sm WHITE LEFT-POINTING TRIANGLE
+25C2..25F7 ; Common # So [54] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE CIRCLE WITH UPPER RIGHT QUADRANT
+25F8..25FF ; Common # Sm [8] UPPER LEFT TRIANGLE..LOWER RIGHT TRIANGLE
+2600..266E ; Common # So [111] BLACK SUN WITH RAYS..MUSIC NATURAL SIGN
+266F ; Common # Sm MUSIC SHARP SIGN
+2670..2767 ; Common # So [248] WEST SYRIAC CROSS..ROTATED FLORAL HEART BULLET
+2768 ; Common # Ps MEDIUM LEFT PARENTHESIS ORNAMENT
+2769 ; Common # Pe MEDIUM RIGHT PARENTHESIS ORNAMENT
+276A ; Common # Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+276B ; Common # Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+276C ; Common # Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+276D ; Common # Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+276E ; Common # Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+276F ; Common # Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+2770 ; Common # Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+2771 ; Common # Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+2772 ; Common # Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
+2773 ; Common # Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
+2774 ; Common # Ps MEDIUM LEFT CURLY BRACKET ORNAMENT
+2775 ; Common # Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT
+2776..2793 ; Common # No [30] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
+2794..27BF ; Common # So [44] HEAVY WIDE-HEADED RIGHTWARDS ARROW..DOUBLE CURLY LOOP
+27C0..27C4 ; Common # Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET
+27C5 ; Common # Ps LEFT S-SHAPED BAG DELIMITER
+27C6 ; Common # Pe RIGHT S-SHAPED BAG DELIMITER
+27C7..27E5 ; Common # Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK
+27E6 ; Common # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET
+27E7 ; Common # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+27E8 ; Common # Ps MATHEMATICAL LEFT ANGLE BRACKET
+27E9 ; Common # Pe MATHEMATICAL RIGHT ANGLE BRACKET
+27EA ; Common # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+27EB ; Common # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+27EC ; Common # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
+27ED ; Common # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
+27EE ; Common # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS
+27EF ; Common # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS
+27F0..27FF ; Common # Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW
+2900..2982 ; Common # Sm [131] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..Z NOTATION TYPE COLON
+2983 ; Common # Ps LEFT WHITE CURLY BRACKET
+2984 ; Common # Pe RIGHT WHITE CURLY BRACKET
+2985 ; Common # Ps LEFT WHITE PARENTHESIS
+2986 ; Common # Pe RIGHT WHITE PARENTHESIS
+2987 ; Common # Ps Z NOTATION LEFT IMAGE BRACKET
+2988 ; Common # Pe Z NOTATION RIGHT IMAGE BRACKET
+2989 ; Common # Ps Z NOTATION LEFT BINDING BRACKET
+298A ; Common # Pe Z NOTATION RIGHT BINDING BRACKET
+298B ; Common # Ps LEFT SQUARE BRACKET WITH UNDERBAR
+298C ; Common # Pe RIGHT SQUARE BRACKET WITH UNDERBAR
+298D ; Common # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+298E ; Common # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+298F ; Common # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+2990 ; Common # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+2991 ; Common # Ps LEFT ANGLE BRACKET WITH DOT
+2992 ; Common # Pe RIGHT ANGLE BRACKET WITH DOT
+2993 ; Common # Ps LEFT ARC LESS-THAN BRACKET
+2994 ; Common # Pe RIGHT ARC GREATER-THAN BRACKET
+2995 ; Common # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET
+2996 ; Common # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET
+2997 ; Common # Ps LEFT BLACK TORTOISE SHELL BRACKET
+2998 ; Common # Pe RIGHT BLACK TORTOISE SHELL BRACKET
+2999..29D7 ; Common # Sm [63] DOTTED FENCE..BLACK HOURGLASS
+29D8 ; Common # Ps LEFT WIGGLY FENCE
+29D9 ; Common # Pe RIGHT WIGGLY FENCE
+29DA ; Common # Ps LEFT DOUBLE WIGGLY FENCE
+29DB ; Common # Pe RIGHT DOUBLE WIGGLY FENCE
+29DC..29FB ; Common # Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS
+29FC ; Common # Ps LEFT-POINTING CURVED ANGLE BRACKET
+29FD ; Common # Pe RIGHT-POINTING CURVED ANGLE BRACKET
+29FE..2AFF ; Common # Sm [258] TINY..N-ARY WHITE VERTICAL BAR
+2B00..2B2F ; Common # So [48] NORTH EAST WHITE ARROW..WHITE VERTICAL ELLIPSE
+2B30..2B44 ; Common # Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET
+2B45..2B46 ; Common # So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW
+2B47..2B4C ; Common # Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
+2B4D..2B73 ; Common # So [39] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
+2B76..2B95 ; Common # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
+2B97..2BFF ; Common # So [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL
+2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
+2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET
+2E03 ; Common # Pf RIGHT SUBSTITUTION BRACKET
+2E04 ; Common # Pi LEFT DOTTED SUBSTITUTION BRACKET
+2E05 ; Common # Pf RIGHT DOTTED SUBSTITUTION BRACKET
+2E06..2E08 ; Common # Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER
+2E09 ; Common # Pi LEFT TRANSPOSITION BRACKET
+2E0A ; Common # Pf RIGHT TRANSPOSITION BRACKET
+2E0B ; Common # Po RAISED SQUARE
+2E0C ; Common # Pi LEFT RAISED OMISSION BRACKET
+2E0D ; Common # Pf RIGHT RAISED OMISSION BRACKET
+2E0E..2E16 ; Common # Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE
+2E17 ; Common # Pd DOUBLE OBLIQUE HYPHEN
+2E18..2E19 ; Common # Po [2] INVERTED INTERROBANG..PALM BRANCH
+2E1A ; Common # Pd HYPHEN WITH DIAERESIS
+2E1B ; Common # Po TILDE WITH RING ABOVE
+2E1C ; Common # Pi LEFT LOW PARAPHRASE BRACKET
+2E1D ; Common # Pf RIGHT LOW PARAPHRASE BRACKET
+2E1E..2E1F ; Common # Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW
+2E20 ; Common # Pi LEFT VERTICAL BAR WITH QUILL
+2E21 ; Common # Pf RIGHT VERTICAL BAR WITH QUILL
+2E22 ; Common # Ps TOP LEFT HALF BRACKET
+2E23 ; Common # Pe TOP RIGHT HALF BRACKET
+2E24 ; Common # Ps BOTTOM LEFT HALF BRACKET
+2E25 ; Common # Pe BOTTOM RIGHT HALF BRACKET
+2E26 ; Common # Ps LEFT SIDEWAYS U BRACKET
+2E27 ; Common # Pe RIGHT SIDEWAYS U BRACKET
+2E28 ; Common # Ps LEFT DOUBLE PARENTHESIS
+2E29 ; Common # Pe RIGHT DOUBLE PARENTHESIS
+2E2A..2E2E ; Common # Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK
+2E2F ; Common # Lm VERTICAL TILDE
+2E30..2E39 ; Common # Po [10] RING POINT..TOP HALF SECTION SIGN
+2E3A..2E3B ; Common # Pd [2] TWO-EM DASH..THREE-EM DASH
+2E3C..2E3F ; Common # Po [4] STENOGRAPHIC FULL STOP..CAPITULUM
+2E40 ; Common # Pd DOUBLE HYPHEN
+2E41 ; Common # Po REVERSED COMMA
+2E42 ; Common # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
+2E43..2E4F ; Common # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER
+2E50..2E51 ; Common # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR
+2E52..2E54 ; Common # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK
+2E55 ; Common # Ps LEFT SQUARE BRACKET WITH STROKE
+2E56 ; Common # Pe RIGHT SQUARE BRACKET WITH STROKE
+2E57 ; Common # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE
+2E58 ; Common # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE
+2E59 ; Common # Ps TOP HALF LEFT PARENTHESIS
+2E5A ; Common # Pe TOP HALF RIGHT PARENTHESIS
+2E5B ; Common # Ps BOTTOM HALF LEFT PARENTHESIS
+2E5C ; Common # Pe BOTTOM HALF RIGHT PARENTHESIS
+2E5D ; Common # Pd OBLIQUE HYPHEN
+2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
+3000 ; Common # Zs IDEOGRAPHIC SPACE
+3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
+3004 ; Common # So JAPANESE INDUSTRIAL STANDARD SYMBOL
+3006 ; Common # Lo IDEOGRAPHIC CLOSING MARK
+3008 ; Common # Ps LEFT ANGLE BRACKET
+3009 ; Common # Pe RIGHT ANGLE BRACKET
+300A ; Common # Ps LEFT DOUBLE ANGLE BRACKET
+300B ; Common # Pe RIGHT DOUBLE ANGLE BRACKET
+300C ; Common # Ps LEFT CORNER BRACKET
+300D ; Common # Pe RIGHT CORNER BRACKET
+300E ; Common # Ps LEFT WHITE CORNER BRACKET
+300F ; Common # Pe RIGHT WHITE CORNER BRACKET
+3010 ; Common # Ps LEFT BLACK LENTICULAR BRACKET
+3011 ; Common # Pe RIGHT BLACK LENTICULAR BRACKET
+3012..3013 ; Common # So [2] POSTAL MARK..GETA MARK
+3014 ; Common # Ps LEFT TORTOISE SHELL BRACKET
+3015 ; Common # Pe RIGHT TORTOISE SHELL BRACKET
+3016 ; Common # Ps LEFT WHITE LENTICULAR BRACKET
+3017 ; Common # Pe RIGHT WHITE LENTICULAR BRACKET
+3018 ; Common # Ps LEFT WHITE TORTOISE SHELL BRACKET
+3019 ; Common # Pe RIGHT WHITE TORTOISE SHELL BRACKET
+301A ; Common # Ps LEFT WHITE SQUARE BRACKET
+301B ; Common # Pe RIGHT WHITE SQUARE BRACKET
+301C ; Common # Pd WAVE DASH
+301D ; Common # Ps REVERSED DOUBLE PRIME QUOTATION MARK
+301E..301F ; Common # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK
+3020 ; Common # So POSTAL MARK FACE
+3030 ; Common # Pd WAVY DASH
+3031..3035 ; Common # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF
+3036..3037 ; Common # So [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+303C ; Common # Lo MASU MARK
+303D ; Common # Po PART ALTERNATION MARK
+303E..303F ; Common # So [2] IDEOGRAPHIC VARIATION INDICATOR..IDEOGRAPHIC HALF FILL SPACE
+309B..309C ; Common # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+30A0 ; Common # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN
+30FB ; Common # Po KATAKANA MIDDLE DOT
+30FC ; Common # Lm KATAKANA-HIRAGANA PROLONGED SOUND MARK
+3190..3191 ; Common # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
+3192..3195 ; Common # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
+3196..319F ; Common # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
+31C0..31E3 ; Common # So [36] CJK STROKE T..CJK STROKE Q
+3220..3229 ; Common # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
+322A..3247 ; Common # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
+3248..324F ; Common # No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
+3250 ; Common # So PARTNERSHIP SIGN
+3251..325F ; Common # No [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE
+327F ; Common # So KOREAN STANDARD SYMBOL
+3280..3289 ; Common # No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN
+328A..32B0 ; Common # So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT
+32B1..32BF ; Common # No [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY
+32C0..32CF ; Common # So [16] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..LIMITED LIABILITY SIGN
+32FF ; Common # So SQUARE ERA NAME REIWA
+3358..33FF ; Common # So [168] IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO..SQUARE GAL
+4DC0..4DFF ; Common # So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
+A700..A716 ; Common # Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
+A717..A71F ; Common # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
+A720..A721 ; Common # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE
+A788 ; Common # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT
+A789..A78A ; Common # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
+A830..A835 ; Common # No [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS
+A836..A837 ; Common # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
+A838 ; Common # Sc NORTH INDIC RUPEE MARK
+A839 ; Common # So NORTH INDIC QUANTITY MARK
+A92E ; Common # Po KAYAH LI SIGN CWI
+A9CF ; Common # Lm JAVANESE PANGRANGKEP
+AB5B ; Common # Sk MODIFIER BREVE WITH INVERTED BREVE
+AB6A..AB6B ; Common # Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK
+FD3E ; Common # Pe ORNATE LEFT PARENTHESIS
+FD3F ; Common # Ps ORNATE RIGHT PARENTHESIS
+FE10..FE16 ; Common # Po [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK
+FE17 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET
+FE18 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET
+FE19 ; Common # Po PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
+FE30 ; Common # Po PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
+FE31..FE32 ; Common # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH
+FE33..FE34 ; Common # Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
+FE35 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+FE36 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+FE37 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+FE38 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+FE39 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
+FE3A ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
+FE3B ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
+FE3C ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
+FE3D ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
+FE3E ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
+FE3F ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
+FE40 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
+FE41 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
+FE42 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
+FE43 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
+FE44 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
+FE45..FE46 ; Common # Po [2] SESAME DOT..WHITE SESAME DOT
+FE47 ; Common # Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET
+FE48 ; Common # Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET
+FE49..FE4C ; Common # Po [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE
+FE4D..FE4F ; Common # Pc [3] DASHED LOW LINE..WAVY LOW LINE
+FE50..FE52 ; Common # Po [3] SMALL COMMA..SMALL FULL STOP
+FE54..FE57 ; Common # Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK
+FE58 ; Common # Pd SMALL EM DASH
+FE59 ; Common # Ps SMALL LEFT PARENTHESIS
+FE5A ; Common # Pe SMALL RIGHT PARENTHESIS
+FE5B ; Common # Ps SMALL LEFT CURLY BRACKET
+FE5C ; Common # Pe SMALL RIGHT CURLY BRACKET
+FE5D ; Common # Ps SMALL LEFT TORTOISE SHELL BRACKET
+FE5E ; Common # Pe SMALL RIGHT TORTOISE SHELL BRACKET
+FE5F..FE61 ; Common # Po [3] SMALL NUMBER SIGN..SMALL ASTERISK
+FE62 ; Common # Sm SMALL PLUS SIGN
+FE63 ; Common # Pd SMALL HYPHEN-MINUS
+FE64..FE66 ; Common # Sm [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN
+FE68 ; Common # Po SMALL REVERSE SOLIDUS
+FE69 ; Common # Sc SMALL DOLLAR SIGN
+FE6A..FE6B ; Common # Po [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT
+FEFF ; Common # Cf ZERO WIDTH NO-BREAK SPACE
+FF01..FF03 ; Common # Po [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN
+FF04 ; Common # Sc FULLWIDTH DOLLAR SIGN
+FF05..FF07 ; Common # Po [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE
+FF08 ; Common # Ps FULLWIDTH LEFT PARENTHESIS
+FF09 ; Common # Pe FULLWIDTH RIGHT PARENTHESIS
+FF0A ; Common # Po FULLWIDTH ASTERISK
+FF0B ; Common # Sm FULLWIDTH PLUS SIGN
+FF0C ; Common # Po FULLWIDTH COMMA
+FF0D ; Common # Pd FULLWIDTH HYPHEN-MINUS
+FF0E..FF0F ; Common # Po [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS
+FF10..FF19 ; Common # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
+FF1A..FF1B ; Common # Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON
+FF1C..FF1E ; Common # Sm [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN
+FF1F..FF20 ; Common # Po [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT
+FF3B ; Common # Ps FULLWIDTH LEFT SQUARE BRACKET
+FF3C ; Common # Po FULLWIDTH REVERSE SOLIDUS
+FF3D ; Common # Pe FULLWIDTH RIGHT SQUARE BRACKET
+FF3E ; Common # Sk FULLWIDTH CIRCUMFLEX ACCENT
+FF3F ; Common # Pc FULLWIDTH LOW LINE
+FF40 ; Common # Sk FULLWIDTH GRAVE ACCENT
+FF5B ; Common # Ps FULLWIDTH LEFT CURLY BRACKET
+FF5C ; Common # Sm FULLWIDTH VERTICAL LINE
+FF5D ; Common # Pe FULLWIDTH RIGHT CURLY BRACKET
+FF5E ; Common # Sm FULLWIDTH TILDE
+FF5F ; Common # Ps FULLWIDTH LEFT WHITE PARENTHESIS
+FF60 ; Common # Pe FULLWIDTH RIGHT WHITE PARENTHESIS
+FF61 ; Common # Po HALFWIDTH IDEOGRAPHIC FULL STOP
+FF62 ; Common # Ps HALFWIDTH LEFT CORNER BRACKET
+FF63 ; Common # Pe HALFWIDTH RIGHT CORNER BRACKET
+FF64..FF65 ; Common # Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT
+FF70 ; Common # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF9E..FF9F ; Common # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+FFE0..FFE1 ; Common # Sc [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN
+FFE2 ; Common # Sm FULLWIDTH NOT SIGN
+FFE3 ; Common # Sk FULLWIDTH MACRON
+FFE4 ; Common # So FULLWIDTH BROKEN BAR
+FFE5..FFE6 ; Common # Sc [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN
+FFE8 ; Common # So HALFWIDTH FORMS LIGHT VERTICAL
+FFE9..FFEC ; Common # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW
+FFED..FFEE ; Common # So [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE
+FFF9..FFFB ; Common # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
+FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHARACTER
+10100..10102 ; Common # Po [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
+10107..10133 ; Common # No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
+10137..1013F ; Common # So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
+10190..1019C ; Common # So [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL
+101D0..101FC ; Common # So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
+102E1..102FB ; Common # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
+1BCA0..1BCA3 ; Common # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+1CF50..1CFC3 ; Common # So [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK
+1D000..1D0F5 ; Common # So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
+1D100..1D126 ; Common # So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
+1D129..1D164 ; Common # So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
+1D165..1D166 ; Common # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
+1D16A..1D16C ; Common # So [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3
+1D16D..1D172 ; Common # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
+1D173..1D17A ; Common # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+1D183..1D184 ; Common # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
+1D18C..1D1A9 ; Common # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
+1D1AE..1D1EA ; Common # So [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON
+1D2E0..1D2F3 ; Common # No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
+1D300..1D356 ; Common # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
+1D360..1D378 ; Common # No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE
+1D400..1D454 ; Common # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
+1D456..1D49C ; Common # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
+1D49E..1D49F ; Common # L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
+1D4A2 ; Common # L& MATHEMATICAL SCRIPT CAPITAL G
+1D4A5..1D4A6 ; Common # L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
+1D4A9..1D4AC ; Common # L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
+1D4AE..1D4B9 ; Common # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
+1D4BB ; Common # L& MATHEMATICAL SCRIPT SMALL F
+1D4BD..1D4C3 ; Common # L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
+1D4C5..1D505 ; Common # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
+1D507..1D50A ; Common # L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
+1D50D..1D514 ; Common # L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
+1D516..1D51C ; Common # L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
+1D51E..1D539 ; Common # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+1D53B..1D53E ; Common # L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+1D540..1D544 ; Common # L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+1D546 ; Common # L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+1D54A..1D550 ; Common # L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+1D552..1D6A5 ; Common # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
+1D6A8..1D6C0 ; Common # L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA
+1D6C1 ; Common # Sm MATHEMATICAL BOLD NABLA
+1D6C2..1D6DA ; Common # L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA
+1D6DB ; Common # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
+1D6DC..1D6FA ; Common # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA
+1D6FB ; Common # Sm MATHEMATICAL ITALIC NABLA
+1D6FC..1D714 ; Common # L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA
+1D715 ; Common # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
+1D716..1D734 ; Common # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
+1D735 ; Common # Sm MATHEMATICAL BOLD ITALIC NABLA
+1D736..1D74E ; Common # L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA
+1D74F ; Common # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
+1D750..1D76E ; Common # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
+1D76F ; Common # Sm MATHEMATICAL SANS-SERIF BOLD NABLA
+1D770..1D788 ; Common # L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
+1D789 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
+1D78A..1D7A8 ; Common # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
+1D7A9 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
+1D7AA..1D7C2 ; Common # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
+1D7C3 ; Common # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
+1D7C4..1D7CB ; Common # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA
+1D7CE..1D7FF ; Common # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
+1EC71..1ECAB ; Common # No [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE
+1ECAC ; Common # So INDIC SIYAQ PLACEHOLDER
+1ECAD..1ECAF ; Common # No [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS
+1ECB0 ; Common # Sc INDIC SIYAQ RUPEE MARK
+1ECB1..1ECB4 ; Common # No [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK
+1ED01..1ED2D ; Common # No [45] OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ NUMBER NINETY THOUSAND
+1ED2E ; Common # So OTTOMAN SIYAQ MARRATAN
+1ED2F..1ED3D ; Common # No [15] OTTOMAN SIYAQ ALTERNATE NUMBER TWO..OTTOMAN SIYAQ FRACTION ONE SIXTH
+1F000..1F02B ; Common # So [44] MAHJONG TILE EAST WIND..MAHJONG TILE BACK
+1F030..1F093 ; Common # So [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
+1F0A0..1F0AE ; Common # So [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES
+1F0B1..1F0BF ; Common # So [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER
+1F0C1..1F0CF ; Common # So [15] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD BLACK JOKER
+1F0D1..1F0F5 ; Common # So [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21
+1F100..1F10C ; Common # No [13] DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
+1F10D..1F1AD ; Common # So [161] CIRCLED ZERO WITH SLASH..MASK WORK SYMBOL
+1F1E6..1F1FF ; Common # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
+1F201..1F202 ; Common # So [2] SQUARED KATAKANA KOKO..SQUARED KATAKANA SA
+1F210..1F23B ; Common # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D
+1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
+1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
+1F260..1F265 ; Common # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
+1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA
+1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
+1F400..1F6D7 ; Common # So [728] RAT..ELEVATOR
+1F6DD..1F6EC ; Common # So [16] PLAYGROUND SLIDE..AIRPLANE ARRIVING
+1F6F0..1F6FC ; Common # So [13] SATELLITE..ROLLER SKATE
+1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
+1F780..1F7D8 ; Common # So [89] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NEGATIVE CIRCLED SQUARE
+1F7E0..1F7EB ; Common # So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE
+1F7F0 ; Common # So HEAVY EQUALS SIGN
+1F800..1F80B ; Common # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
+1F810..1F847 ; Common # So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
+1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
+1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
+1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F8B0..1F8B1 ; Common # So [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST
+1F900..1FA53 ; Common # So [340] CIRCLED CROSS FORMEE WITH FOUR DOTS..BLACK CHESS KNIGHT-BISHOP
+1FA60..1FA6D ; Common # So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
+1FA70..1FA74 ; Common # So [5] BALLET SHOES..THONG SANDAL
+1FA78..1FA7C ; Common # So [5] DROP OF BLOOD..CRUTCH
+1FA80..1FA86 ; Common # So [7] YO-YO..NESTING DOLLS
+1FA90..1FAAC ; Common # So [29] RINGED PLANET..HAMSA
+1FAB0..1FABA ; Common # So [11] FLY..NEST WITH EGGS
+1FAC0..1FAC5 ; Common # So [6] ANATOMICAL HEART..PERSON WITH CROWN
+1FAD0..1FAD9 ; Common # So [10] BLUEBERRIES..JAR
+1FAE0..1FAE7 ; Common # So [8] MELTING FACE..BUBBLES
+1FAF0..1FAF6 ; Common # So [7] HAND WITH INDEX FINGER AND THUMB CROSSED..HEART HANDS
+1FB00..1FB92 ; Common # So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
+1FB94..1FBCA ; Common # So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON
+1FBF0..1FBF9 ; Common # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE
+E0001 ; Common # Cf LANGUAGE TAG
+E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
+
+# Total code points: 8252
+
+# ================================================
+
+0041..005A ; Latin # L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
+0061..007A ; Latin # L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z
+00AA ; Latin # Lo FEMININE ORDINAL INDICATOR
+00BA ; Latin # Lo MASCULINE ORDINAL INDICATOR
+00C0..00D6 ; Latin # L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS
+00D8..00F6 ; Latin # L& [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS
+00F8..01BA ; Latin # L& [195] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL
+01BB ; Latin # Lo LATIN LETTER TWO WITH STROKE
+01BC..01BF ; Latin # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN
+01C0..01C3 ; Latin # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK
+01C4..0293 ; Latin # L& [208] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER EZH WITH CURL
+0294 ; Latin # Lo LATIN LETTER GLOTTAL STOP
+0295..02AF ; Latin # L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+02B0..02B8 ; Latin # Lm [9] MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y
+02E0..02E4 ; Latin # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+1D00..1D25 ; Latin # L& [38] LATIN LETTER SMALL CAPITAL A..LATIN LETTER AIN
+1D2C..1D5C ; Latin # Lm [49] MODIFIER LETTER CAPITAL A..MODIFIER LETTER SMALL AIN
+1D62..1D65 ; Latin # Lm [4] LATIN SUBSCRIPT SMALL LETTER I..LATIN SUBSCRIPT SMALL LETTER V
+1D6B..1D77 ; Latin # L& [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
+1D79..1D9A ; Latin # L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
+1D9B..1DBE ; Latin # Lm [36] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL EZH
+1E00..1EFF ; Latin # L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP
+2071 ; Latin # Lm SUPERSCRIPT LATIN SMALL LETTER I
+207F ; Latin # Lm SUPERSCRIPT LATIN SMALL LETTER N
+2090..209C ; Latin # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T
+212A..212B ; Latin # L& [2] KELVIN SIGN..ANGSTROM SIGN
+2132 ; Latin # L& TURNED CAPITAL F
+214E ; Latin # L& TURNED SMALL F
+2160..2182 ; Latin # Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND
+2183..2184 ; Latin # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C
+2185..2188 ; Latin # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND
+2C60..2C7B ; Latin # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E
+2C7C..2C7D ; Latin # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V
+2C7E..2C7F ; Latin # L& [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL
+A722..A76F ; Latin # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON
+A770 ; Latin # Lm MODIFIER LETTER US
+A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
+A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT
+A790..A7CA ; Latin # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY
+A7D0..A7D1 ; Latin # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G
+A7D3 ; Latin # L& LATIN SMALL LETTER DOUBLE THORN
+A7D5..A7D9 ; Latin # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S
+A7F2..A7F4 ; Latin # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q
+A7F5..A7F6 ; Latin # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H
+A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
+A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
+A7FA ; Latin # L& LATIN LETTER SMALL CAPITAL TURNED M
+A7FB..A7FF ; Latin # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
+AB30..AB5A ; Latin # L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
+AB5C..AB5F ; Latin # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
+AB60..AB64 ; Latin # L& [5] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER INVERTED ALPHA
+AB66..AB68 ; Latin # L& [3] LATIN SMALL LETTER DZ DIGRAPH WITH RETROFLEX HOOK..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE
+AB69 ; Latin # Lm MODIFIER LETTER SMALL TURNED W
+FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
+FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
+FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
+10780..10785 ; Latin # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK
+10787..107B0 ; Latin # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B2..107BA ; Latin # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL
+1DF00..1DF09 ; Latin # L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK
+1DF0A ; Latin # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK
+1DF0B..1DF1E ; Latin # L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL
+
+# Total code points: 1475
+
+# ================================================
+
+0370..0373 ; Greek # L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI
+0375 ; Greek # Sk GREEK LOWER NUMERAL SIGN
+0376..0377 ; Greek # L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+037A ; Greek # Lm GREEK YPOGEGRAMMENI
+037B..037D ; Greek # L& [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+037F ; Greek # L& GREEK CAPITAL LETTER YOT
+0384 ; Greek # Sk GREEK TONOS
+0386 ; Greek # L& GREEK CAPITAL LETTER ALPHA WITH TONOS
+0388..038A ; Greek # L& [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
+038C ; Greek # L& GREEK CAPITAL LETTER OMICRON WITH TONOS
+038E..03A1 ; Greek # L& [20] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER RHO
+03A3..03E1 ; Greek # L& [63] GREEK CAPITAL LETTER SIGMA..GREEK SMALL LETTER SAMPI
+03F0..03F5 ; Greek # L& [6] GREEK KAPPA SYMBOL..GREEK LUNATE EPSILON SYMBOL
+03F6 ; Greek # Sm GREEK REVERSED LUNATE EPSILON SYMBOL
+03F7..03FF ; Greek # L& [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
+1D26..1D2A ; Greek # L& [5] GREEK LETTER SMALL CAPITAL GAMMA..GREEK LETTER SMALL CAPITAL PSI
+1D5D..1D61 ; Greek # Lm [5] MODIFIER LETTER SMALL BETA..MODIFIER LETTER SMALL CHI
+1D66..1D6A ; Greek # Lm [5] GREEK SUBSCRIPT SMALL LETTER BETA..GREEK SUBSCRIPT SMALL LETTER CHI
+1DBF ; Greek # Lm MODIFIER LETTER SMALL THETA
+1F00..1F15 ; Greek # L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+1F18..1F1D ; Greek # L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F20..1F45 ; Greek # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+1F48..1F4D ; Greek # L& [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F50..1F57 ; Greek # L& [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F59 ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5B ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5D ; Greek # L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5F..1F7D ; Greek # L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA
+1F80..1FB4 ; Greek # L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB6..1FBC ; Greek # L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBD ; Greek # Sk GREEK KORONIS
+1FBE ; Greek # L& GREEK PROSGEGRAMMENI
+1FBF..1FC1 ; Greek # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
+1FC2..1FC4 ; Greek # L& [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC6..1FCC ; Greek # L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FCD..1FCF ; Greek # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI
+1FD0..1FD3 ; Greek # L& [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD6..1FDB ; Greek # L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA
+1FDD..1FDF ; Greek # Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
+1FE0..1FEC ; Greek # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
+1FED..1FEF ; Greek # Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA
+1FF2..1FF4 ; Greek # L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF6..1FFC ; Greek # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+1FFD..1FFE ; Greek # Sk [2] GREEK OXIA..GREEK DASIA
+2126 ; Greek # L& OHM SIGN
+AB65 ; Greek # L& GREEK LETTER SMALL CAPITAL OMEGA
+10140..10174 ; Greek # Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS
+10175..10178 ; Greek # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN
+10179..10189 ; Greek # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN
+1018A..1018B ; Greek # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN
+1018C..1018E ; Greek # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN
+101A0 ; Greek # So GREEK SYMBOL TAU RHO
+1D200..1D241 ; Greek # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54
+1D242..1D244 ; Greek # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
+1D245 ; Greek # So GREEK MUSICAL LEIMMA
+
+# Total code points: 518
+
+# ================================================
+
+0400..0481 ; Cyrillic # L& [130] CYRILLIC CAPITAL LETTER IE WITH GRAVE..CYRILLIC SMALL LETTER KOPPA
+0482 ; Cyrillic # So CYRILLIC THOUSANDS SIGN
+0483..0484 ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC PALATALIZATION
+0487 ; Cyrillic # Mn COMBINING CYRILLIC POKRYTIE
+0488..0489 ; Cyrillic # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
+048A..052F ; Cyrillic # L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER
+1C80..1C88 ; Cyrillic # L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK
+1D2B ; Cyrillic # L& CYRILLIC LETTER SMALL CAPITAL EL
+1D78 ; Cyrillic # Lm MODIFIER LETTER CYRILLIC EN
+2DE0..2DFF ; Cyrillic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
+A640..A66D ; Cyrillic # L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O
+A66E ; Cyrillic # Lo CYRILLIC LETTER MULTIOCULAR O
+A66F ; Cyrillic # Mn COMBINING CYRILLIC VZMET
+A670..A672 ; Cyrillic # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
+A673 ; Cyrillic # Po SLAVONIC ASTERISK
+A674..A67D ; Cyrillic # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
+A67E ; Cyrillic # Po CYRILLIC KAVYKA
+A67F ; Cyrillic # Lm CYRILLIC PAYEROK
+A680..A69B ; Cyrillic # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
+A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
+A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
+FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+
+# Total code points: 443
+
+# ================================================
+
+0531..0556 ; Armenian # L& [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
+0559 ; Armenian # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING
+055A..055F ; Armenian # Po [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
+0560..0588 ; Armenian # L& [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE
+0589 ; Armenian # Po ARMENIAN FULL STOP
+058A ; Armenian # Pd ARMENIAN HYPHEN
+058D..058E ; Armenian # So [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN
+058F ; Armenian # Sc ARMENIAN DRAM SIGN
+FB13..FB17 ; Armenian # L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
+
+# Total code points: 96
+
+# ================================================
+
+0591..05BD ; Hebrew # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
+05BE ; Hebrew # Pd HEBREW PUNCTUATION MAQAF
+05BF ; Hebrew # Mn HEBREW POINT RAFE
+05C0 ; Hebrew # Po HEBREW PUNCTUATION PASEQ
+05C1..05C2 ; Hebrew # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
+05C3 ; Hebrew # Po HEBREW PUNCTUATION SOF PASUQ
+05C4..05C5 ; Hebrew # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
+05C6 ; Hebrew # Po HEBREW PUNCTUATION NUN HAFUKHA
+05C7 ; Hebrew # Mn HEBREW POINT QAMATS QATAN
+05D0..05EA ; Hebrew # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV
+05EF..05F2 ; Hebrew # Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD
+05F3..05F4 ; Hebrew # Po [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
+FB1D ; Hebrew # Lo HEBREW LETTER YOD WITH HIRIQ
+FB1E ; Hebrew # Mn HEBREW POINT JUDEO-SPANISH VARIKA
+FB1F..FB28 ; Hebrew # Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV
+FB29 ; Hebrew # Sm HEBREW LETTER ALTERNATIVE PLUS SIGN
+FB2A..FB36 ; Hebrew # Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH
+FB38..FB3C ; Hebrew # Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
+FB3E ; Hebrew # Lo HEBREW LETTER MEM WITH DAGESH
+FB40..FB41 ; Hebrew # Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
+FB43..FB44 ; Hebrew # Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
+FB46..FB4F ; Hebrew # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED
+
+# Total code points: 134
+
+# ================================================
+
+0600..0604 ; Arabic # Cf [5] ARABIC NUMBER SIGN..ARABIC SIGN SAMVAT
+0606..0608 ; Arabic # Sm [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY
+0609..060A ; Arabic # Po [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN
+060B ; Arabic # Sc AFGHANI SIGN
+060D ; Arabic # Po ARABIC DATE SEPARATOR
+060E..060F ; Arabic # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA
+0610..061A ; Arabic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
+061C ; Arabic # Cf ARABIC LETTER MARK
+061D..061E ; Arabic # Po [2] ARABIC END OF TEXT MARK..ARABIC TRIPLE DOT PUNCTUATION MARK
+0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
+0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW
+0660..0669 ; Arabic # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
+066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
+066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
+0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+06D4 ; Arabic # Po ARABIC FULL STOP
+06D5 ; Arabic # Lo ARABIC LETTER AE
+06D6..06DC ; Arabic # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
+06DE ; Arabic # So ARABIC START OF RUB EL HIZB
+06DF..06E4 ; Arabic # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
+06E5..06E6 ; Arabic # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH
+06E7..06E8 ; Arabic # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
+06E9 ; Arabic # So ARABIC PLACE OF SAJDAH
+06EA..06ED ; Arabic # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
+06EE..06EF ; Arabic # Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V
+06F0..06F9 ; Arabic # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
+06FA..06FC ; Arabic # Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW
+06FD..06FE ; Arabic # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
+06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V
+0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
+0870..0887 ; Arabic # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT
+0888 ; Arabic # Sk ARABIC RAISED ROUND DOT
+0889..088E ; Arabic # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL
+0890..0891 ; Arabic # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
+0898..089F ; Arabic # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
+08A0..08C8 ; Arabic # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF
+08C9 ; Arabic # Lm ARABIC SMALL FARSI YEH
+08CA..08E1 ; Arabic # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
+08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
+FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
+FBB2..FBC2 ; Arabic # Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE
+FBD3..FD3D ; Arabic # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
+FD40..FD4F ; Arabic # So [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH
+FD50..FD8F ; Arabic # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+FD92..FDC7 ; Arabic # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+FDCF ; Arabic # So ARABIC LIGATURE SALAAMUHU ALAYNAA
+FDF0..FDFB ; Arabic # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU
+FDFC ; Arabic # Sc RIAL SIGN
+FDFD..FDFF ; Arabic # So [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL
+FE70..FE74 ; Arabic # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM
+FE76..FEFC ; Arabic # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+10E60..10E7E ; Arabic # No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
+1EE00..1EE03 ; Arabic # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL
+1EE05..1EE1F ; Arabic # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF
+1EE21..1EE22 ; Arabic # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM
+1EE24 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL HEH
+1EE27 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL HAH
+1EE29..1EE32 ; Arabic # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF
+1EE34..1EE37 ; Arabic # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH
+1EE39 ; Arabic # Lo ARABIC MATHEMATICAL INITIAL DAD
+1EE3B ; Arabic # Lo ARABIC MATHEMATICAL INITIAL GHAIN
+1EE42 ; Arabic # Lo ARABIC MATHEMATICAL TAILED JEEM
+1EE47 ; Arabic # Lo ARABIC MATHEMATICAL TAILED HAH
+1EE49 ; Arabic # Lo ARABIC MATHEMATICAL TAILED YEH
+1EE4B ; Arabic # Lo ARABIC MATHEMATICAL TAILED LAM
+1EE4D..1EE4F ; Arabic # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN
+1EE51..1EE52 ; Arabic # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF
+1EE54 ; Arabic # Lo ARABIC MATHEMATICAL TAILED SHEEN
+1EE57 ; Arabic # Lo ARABIC MATHEMATICAL TAILED KHAH
+1EE59 ; Arabic # Lo ARABIC MATHEMATICAL TAILED DAD
+1EE5B ; Arabic # Lo ARABIC MATHEMATICAL TAILED GHAIN
+1EE5D ; Arabic # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON
+1EE5F ; Arabic # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF
+1EE61..1EE62 ; Arabic # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM
+1EE64 ; Arabic # Lo ARABIC MATHEMATICAL STRETCHED HEH
+1EE67..1EE6A ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF
+1EE6C..1EE72 ; Arabic # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF
+1EE74..1EE77 ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH
+1EE79..1EE7C ; Arabic # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
+1EE7E ; Arabic # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
+1EE80..1EE89 ; Arabic # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH
+1EE8B..1EE9B ; Arabic # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN
+1EEA1..1EEA3 ; Arabic # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
+1EEA5..1EEA9 ; Arabic # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
+1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
+1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
+
+# Total code points: 1365
+
+# ================================================
+
+0700..070D ; Syriac # Po [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
+070F ; Syriac # Cf SYRIAC ABBREVIATION MARK
+0710 ; Syriac # Lo SYRIAC LETTER ALAPH
+0711 ; Syriac # Mn SYRIAC LETTER SUPERSCRIPT ALAPH
+0712..072F ; Syriac # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH
+0730..074A ; Syriac # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
+074D..074F ; Syriac # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE
+0860..086A ; Syriac # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
+
+# Total code points: 88
+
+# ================================================
+
+0780..07A5 ; Thaana # Lo [38] THAANA LETTER HAA..THAANA LETTER WAAVU
+07A6..07B0 ; Thaana # Mn [11] THAANA ABAFILI..THAANA SUKUN
+07B1 ; Thaana # Lo THAANA LETTER NAA
+
+# Total code points: 50
+
+# ================================================
+
+0900..0902 ; Devanagari # Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA
+0903 ; Devanagari # Mc DEVANAGARI SIGN VISARGA
+0904..0939 ; Devanagari # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA
+093A ; Devanagari # Mn DEVANAGARI VOWEL SIGN OE
+093B ; Devanagari # Mc DEVANAGARI VOWEL SIGN OOE
+093C ; Devanagari # Mn DEVANAGARI SIGN NUKTA
+093D ; Devanagari # Lo DEVANAGARI SIGN AVAGRAHA
+093E..0940 ; Devanagari # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II
+0941..0948 ; Devanagari # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
+0949..094C ; Devanagari # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU
+094D ; Devanagari # Mn DEVANAGARI SIGN VIRAMA
+094E..094F ; Devanagari # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW
+0950 ; Devanagari # Lo DEVANAGARI OM
+0955..0957 ; Devanagari # Mn [3] DEVANAGARI VOWEL SIGN CANDRA LONG E..DEVANAGARI VOWEL SIGN UUE
+0958..0961 ; Devanagari # Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL
+0962..0963 ; Devanagari # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
+0966..096F ; Devanagari # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
+0970 ; Devanagari # Po DEVANAGARI ABBREVIATION SIGN
+0971 ; Devanagari # Lm DEVANAGARI SIGN HIGH SPACING DOT
+0972..097F ; Devanagari # Lo [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA
+A8E0..A8F1 ; Devanagari # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
+A8F2..A8F7 ; Devanagari # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
+A8F8..A8FA ; Devanagari # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
+A8FB ; Devanagari # Lo DEVANAGARI HEADSTROKE
+A8FC ; Devanagari # Po DEVANAGARI SIGN SIDDHAM
+A8FD..A8FE ; Devanagari # Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY
+A8FF ; Devanagari # Mn DEVANAGARI VOWEL SIGN AY
+
+# Total code points: 154
+
+# ================================================
+
+0980 ; Bengali # Lo BENGALI ANJI
+0981 ; Bengali # Mn BENGALI SIGN CANDRABINDU
+0982..0983 ; Bengali # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA
+0985..098C ; Bengali # Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L
+098F..0990 ; Bengali # Lo [2] BENGALI LETTER E..BENGALI LETTER AI
+0993..09A8 ; Bengali # Lo [22] BENGALI LETTER O..BENGALI LETTER NA
+09AA..09B0 ; Bengali # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA
+09B2 ; Bengali # Lo BENGALI LETTER LA
+09B6..09B9 ; Bengali # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA
+09BC ; Bengali # Mn BENGALI SIGN NUKTA
+09BD ; Bengali # Lo BENGALI SIGN AVAGRAHA
+09BE..09C0 ; Bengali # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II
+09C1..09C4 ; Bengali # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
+09C7..09C8 ; Bengali # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
+09CB..09CC ; Bengali # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU
+09CD ; Bengali # Mn BENGALI SIGN VIRAMA
+09CE ; Bengali # Lo BENGALI LETTER KHANDA TA
+09D7 ; Bengali # Mc BENGALI AU LENGTH MARK
+09DC..09DD ; Bengali # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA
+09DF..09E1 ; Bengali # Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL
+09E2..09E3 ; Bengali # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
+09E6..09EF ; Bengali # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
+09F0..09F1 ; Bengali # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL
+09F2..09F3 ; Bengali # Sc [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN
+09F4..09F9 ; Bengali # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN
+09FA ; Bengali # So BENGALI ISSHAR
+09FB ; Bengali # Sc BENGALI GANDA MARK
+09FC ; Bengali # Lo BENGALI LETTER VEDIC ANUSVARA
+09FD ; Bengali # Po BENGALI ABBREVIATION SIGN
+09FE ; Bengali # Mn BENGALI SANDHI MARK
+
+# Total code points: 96
+
+# ================================================
+
+0A01..0A02 ; Gurmukhi # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
+0A03 ; Gurmukhi # Mc GURMUKHI SIGN VISARGA
+0A05..0A0A ; Gurmukhi # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU
+0A0F..0A10 ; Gurmukhi # Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI
+0A13..0A28 ; Gurmukhi # Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA
+0A2A..0A30 ; Gurmukhi # Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA
+0A32..0A33 ; Gurmukhi # Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA
+0A35..0A36 ; Gurmukhi # Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA
+0A38..0A39 ; Gurmukhi # Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA
+0A3C ; Gurmukhi # Mn GURMUKHI SIGN NUKTA
+0A3E..0A40 ; Gurmukhi # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II
+0A41..0A42 ; Gurmukhi # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
+0A47..0A48 ; Gurmukhi # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
+0A4B..0A4D ; Gurmukhi # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
+0A51 ; Gurmukhi # Mn GURMUKHI SIGN UDAAT
+0A59..0A5C ; Gurmukhi # Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA
+0A5E ; Gurmukhi # Lo GURMUKHI LETTER FA
+0A66..0A6F ; Gurmukhi # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
+0A70..0A71 ; Gurmukhi # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK
+0A72..0A74 ; Gurmukhi # Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR
+0A75 ; Gurmukhi # Mn GURMUKHI SIGN YAKASH
+0A76 ; Gurmukhi # Po GURMUKHI ABBREVIATION SIGN
+
+# Total code points: 80
+
+# ================================================
+
+0A81..0A82 ; Gujarati # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA
+0A83 ; Gujarati # Mc GUJARATI SIGN VISARGA
+0A85..0A8D ; Gujarati # Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
+0A8F..0A91 ; Gujarati # Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
+0A93..0AA8 ; Gujarati # Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA
+0AAA..0AB0 ; Gujarati # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA
+0AB2..0AB3 ; Gujarati # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA
+0AB5..0AB9 ; Gujarati # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA
+0ABC ; Gujarati # Mn GUJARATI SIGN NUKTA
+0ABD ; Gujarati # Lo GUJARATI SIGN AVAGRAHA
+0ABE..0AC0 ; Gujarati # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II
+0AC1..0AC5 ; Gujarati # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E
+0AC7..0AC8 ; Gujarati # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
+0AC9 ; Gujarati # Mc GUJARATI VOWEL SIGN CANDRA O
+0ACB..0ACC ; Gujarati # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
+0ACD ; Gujarati # Mn GUJARATI SIGN VIRAMA
+0AD0 ; Gujarati # Lo GUJARATI OM
+0AE0..0AE1 ; Gujarati # Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL
+0AE2..0AE3 ; Gujarati # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
+0AE6..0AEF ; Gujarati # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
+0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN
+0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN
+0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA
+0AFA..0AFF ; Gujarati # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
+
+# Total code points: 91
+
+# ================================================
+
+0B01 ; Oriya # Mn ORIYA SIGN CANDRABINDU
+0B02..0B03 ; Oriya # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
+0B05..0B0C ; Oriya # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L
+0B0F..0B10 ; Oriya # Lo [2] ORIYA LETTER E..ORIYA LETTER AI
+0B13..0B28 ; Oriya # Lo [22] ORIYA LETTER O..ORIYA LETTER NA
+0B2A..0B30 ; Oriya # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA
+0B32..0B33 ; Oriya # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA
+0B35..0B39 ; Oriya # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA
+0B3C ; Oriya # Mn ORIYA SIGN NUKTA
+0B3D ; Oriya # Lo ORIYA SIGN AVAGRAHA
+0B3E ; Oriya # Mc ORIYA VOWEL SIGN AA
+0B3F ; Oriya # Mn ORIYA VOWEL SIGN I
+0B40 ; Oriya # Mc ORIYA VOWEL SIGN II
+0B41..0B44 ; Oriya # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
+0B47..0B48 ; Oriya # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
+0B4B..0B4C ; Oriya # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU
+0B4D ; Oriya # Mn ORIYA SIGN VIRAMA
+0B55..0B56 ; Oriya # Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK
+0B57 ; Oriya # Mc ORIYA AU LENGTH MARK
+0B5C..0B5D ; Oriya # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA
+0B5F..0B61 ; Oriya # Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL
+0B62..0B63 ; Oriya # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
+0B66..0B6F ; Oriya # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE
+0B70 ; Oriya # So ORIYA ISSHAR
+0B71 ; Oriya # Lo ORIYA LETTER WA
+0B72..0B77 ; Oriya # No [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
+
+# Total code points: 91
+
+# ================================================
+
+0B82 ; Tamil # Mn TAMIL SIGN ANUSVARA
+0B83 ; Tamil # Lo TAMIL SIGN VISARGA
+0B85..0B8A ; Tamil # Lo [6] TAMIL LETTER A..TAMIL LETTER UU
+0B8E..0B90 ; Tamil # Lo [3] TAMIL LETTER E..TAMIL LETTER AI
+0B92..0B95 ; Tamil # Lo [4] TAMIL LETTER O..TAMIL LETTER KA
+0B99..0B9A ; Tamil # Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA
+0B9C ; Tamil # Lo TAMIL LETTER JA
+0B9E..0B9F ; Tamil # Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA
+0BA3..0BA4 ; Tamil # Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA
+0BA8..0BAA ; Tamil # Lo [3] TAMIL LETTER NA..TAMIL LETTER PA
+0BAE..0BB9 ; Tamil # Lo [12] TAMIL LETTER MA..TAMIL LETTER HA
+0BBE..0BBF ; Tamil # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I
+0BC0 ; Tamil # Mn TAMIL VOWEL SIGN II
+0BC1..0BC2 ; Tamil # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU
+0BC6..0BC8 ; Tamil # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
+0BCA..0BCC ; Tamil # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU
+0BCD ; Tamil # Mn TAMIL SIGN VIRAMA
+0BD0 ; Tamil # Lo TAMIL OM
+0BD7 ; Tamil # Mc TAMIL AU LENGTH MARK
+0BE6..0BEF ; Tamil # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
+0BF0..0BF2 ; Tamil # No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
+0BF3..0BF8 ; Tamil # So [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN
+0BF9 ; Tamil # Sc TAMIL RUPEE SIGN
+0BFA ; Tamil # So TAMIL NUMBER SIGN
+11FC0..11FD4 ; Tamil # No [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH
+11FD5..11FDC ; Tamil # So [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI
+11FDD..11FE0 ; Tamil # Sc [4] TAMIL SIGN KAACU..TAMIL SIGN VARAAKAN
+11FE1..11FF1 ; Tamil # So [17] TAMIL SIGN PAARAM..TAMIL SIGN VAKAIYARAA
+11FFF ; Tamil # Po TAMIL PUNCTUATION END OF TEXT
+
+# Total code points: 123
+
+# ================================================
+
+0C00 ; Telugu # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE
+0C01..0C03 ; Telugu # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
+0C04 ; Telugu # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE
+0C05..0C0C ; Telugu # Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L
+0C0E..0C10 ; Telugu # Lo [3] TELUGU LETTER E..TELUGU LETTER AI
+0C12..0C28 ; Telugu # Lo [23] TELUGU LETTER O..TELUGU LETTER NA
+0C2A..0C39 ; Telugu # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA
+0C3C ; Telugu # Mn TELUGU SIGN NUKTA
+0C3D ; Telugu # Lo TELUGU SIGN AVAGRAHA
+0C3E..0C40 ; Telugu # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
+0C41..0C44 ; Telugu # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR
+0C46..0C48 ; Telugu # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
+0C4A..0C4D ; Telugu # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
+0C55..0C56 ; Telugu # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
+0C58..0C5A ; Telugu # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
+0C5D ; Telugu # Lo TELUGU LETTER NAKAARA POLLU
+0C60..0C61 ; Telugu # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
+0C62..0C63 ; Telugu # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
+0C66..0C6F ; Telugu # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
+0C77 ; Telugu # Po TELUGU SIGN SIDDHAM
+0C78..0C7E ; Telugu # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
+0C7F ; Telugu # So TELUGU SIGN TUUMU
+
+# Total code points: 100
+
+# ================================================
+
+0C80 ; Kannada # Lo KANNADA SIGN SPACING CANDRABINDU
+0C81 ; Kannada # Mn KANNADA SIGN CANDRABINDU
+0C82..0C83 ; Kannada # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
+0C84 ; Kannada # Po KANNADA SIGN SIDDHAM
+0C85..0C8C ; Kannada # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L
+0C8E..0C90 ; Kannada # Lo [3] KANNADA LETTER E..KANNADA LETTER AI
+0C92..0CA8 ; Kannada # Lo [23] KANNADA LETTER O..KANNADA LETTER NA
+0CAA..0CB3 ; Kannada # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA
+0CB5..0CB9 ; Kannada # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA
+0CBC ; Kannada # Mn KANNADA SIGN NUKTA
+0CBD ; Kannada # Lo KANNADA SIGN AVAGRAHA
+0CBE ; Kannada # Mc KANNADA VOWEL SIGN AA
+0CBF ; Kannada # Mn KANNADA VOWEL SIGN I
+0CC0..0CC4 ; Kannada # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR
+0CC6 ; Kannada # Mn KANNADA VOWEL SIGN E
+0CC7..0CC8 ; Kannada # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI
+0CCA..0CCB ; Kannada # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO
+0CCC..0CCD ; Kannada # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
+0CD5..0CD6 ; Kannada # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
+0CDD..0CDE ; Kannada # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA
+0CE0..0CE1 ; Kannada # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
+0CE2..0CE3 ; Kannada # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
+0CE6..0CEF ; Kannada # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
+0CF1..0CF2 ; Kannada # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
+
+# Total code points: 90
+
+# ================================================
+
+0D00..0D01 ; Malayalam # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
+0D02..0D03 ; Malayalam # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
+0D04..0D0C ; Malayalam # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L
+0D0E..0D10 ; Malayalam # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI
+0D12..0D3A ; Malayalam # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA
+0D3B..0D3C ; Malayalam # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
+0D3D ; Malayalam # Lo MALAYALAM SIGN AVAGRAHA
+0D3E..0D40 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II
+0D41..0D44 ; Malayalam # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
+0D46..0D48 ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
+0D4A..0D4C ; Malayalam # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
+0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA
+0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH
+0D4F ; Malayalam # So MALAYALAM SIGN PARA
+0D54..0D56 ; Malayalam # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL
+0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK
+0D58..0D5E ; Malayalam # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
+0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
+0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
+0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
+0D70..0D78 ; Malayalam # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS
+0D79 ; Malayalam # So MALAYALAM DATE MARK
+0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
+
+# Total code points: 118
+
+# ================================================
+
+0D81 ; Sinhala # Mn SINHALA SIGN CANDRABINDU
+0D82..0D83 ; Sinhala # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
+0D85..0D96 ; Sinhala # Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
+0D9A..0DB1 ; Sinhala # Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
+0DB3..0DBB ; Sinhala # Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
+0DBD ; Sinhala # Lo SINHALA LETTER DANTAJA LAYANNA
+0DC0..0DC6 ; Sinhala # Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
+0DCA ; Sinhala # Mn SINHALA SIGN AL-LAKUNA
+0DCF..0DD1 ; Sinhala # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
+0DD2..0DD4 ; Sinhala # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
+0DD6 ; Sinhala # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA
+0DD8..0DDF ; Sinhala # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
+0DE6..0DEF ; Sinhala # Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
+0DF2..0DF3 ; Sinhala # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
+0DF4 ; Sinhala # Po SINHALA PUNCTUATION KUNDDALIYA
+111E1..111F4 ; Sinhala # No [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
+
+# Total code points: 111
+
+# ================================================
+
+0E01..0E30 ; Thai # Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A
+0E31 ; Thai # Mn THAI CHARACTER MAI HAN-AKAT
+0E32..0E33 ; Thai # Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM
+0E34..0E3A ; Thai # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
+0E40..0E45 ; Thai # Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO
+0E46 ; Thai # Lm THAI CHARACTER MAIYAMOK
+0E47..0E4E ; Thai # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN
+0E4F ; Thai # Po THAI CHARACTER FONGMAN
+0E50..0E59 ; Thai # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE
+0E5A..0E5B ; Thai # Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
+
+# Total code points: 86
+
+# ================================================
+
+0E81..0E82 ; Lao # Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG
+0E84 ; Lao # Lo LAO LETTER KHO TAM
+0E86..0E8A ; Lao # Lo [5] LAO LETTER PALI GHA..LAO LETTER SO TAM
+0E8C..0EA3 ; Lao # Lo [24] LAO LETTER PALI JHA..LAO LETTER LO LING
+0EA5 ; Lao # Lo LAO LETTER LO LOOT
+0EA7..0EB0 ; Lao # Lo [10] LAO LETTER WO..LAO VOWEL SIGN A
+0EB1 ; Lao # Mn LAO VOWEL SIGN MAI KAN
+0EB2..0EB3 ; Lao # Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM
+0EB4..0EBC ; Lao # Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO
+0EBD ; Lao # Lo LAO SEMIVOWEL SIGN NYO
+0EC0..0EC4 ; Lao # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+0EC6 ; Lao # Lm LAO KO LA
+0EC8..0ECD ; Lao # Mn [6] LAO TONE MAI EK..LAO NIGGAHITA
+0ED0..0ED9 ; Lao # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE
+0EDC..0EDF ; Lao # Lo [4] LAO HO NO..LAO LETTER KHMU NYO
+
+# Total code points: 82
+
+# ================================================
+
+0F00 ; Tibetan # Lo TIBETAN SYLLABLE OM
+0F01..0F03 ; Tibetan # So [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
+0F04..0F12 ; Tibetan # Po [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD
+0F13 ; Tibetan # So TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
+0F14 ; Tibetan # Po TIBETAN MARK GTER TSHEG
+0F15..0F17 ; Tibetan # So [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18..0F19 ; Tibetan # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A..0F1F ; Tibetan # So [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
+0F20..0F29 ; Tibetan # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
+0F2A..0F33 ; Tibetan # No [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO
+0F34 ; Tibetan # So TIBETAN MARK BSDUS RTAGS
+0F35 ; Tibetan # Mn TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36 ; Tibetan # So TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37 ; Tibetan # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38 ; Tibetan # So TIBETAN MARK CHE MGO
+0F39 ; Tibetan # Mn TIBETAN MARK TSA -PHRU
+0F3A ; Tibetan # Ps TIBETAN MARK GUG RTAGS GYON
+0F3B ; Tibetan # Pe TIBETAN MARK GUG RTAGS GYAS
+0F3C ; Tibetan # Ps TIBETAN MARK ANG KHANG GYON
+0F3D ; Tibetan # Pe TIBETAN MARK ANG KHANG GYAS
+0F3E..0F3F ; Tibetan # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES
+0F40..0F47 ; Tibetan # Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA
+0F49..0F6C ; Tibetan # Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA
+0F71..0F7E ; Tibetan # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
+0F7F ; Tibetan # Mc TIBETAN SIGN RNAM BCAD
+0F80..0F84 ; Tibetan # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
+0F85 ; Tibetan # Po TIBETAN MARK PALUTA
+0F86..0F87 ; Tibetan # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
+0F88..0F8C ; Tibetan # Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN
+0F8D..0F97 ; Tibetan # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
+0F99..0FBC ; Tibetan # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
+0FBE..0FC5 ; Tibetan # So [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
+0FC6 ; Tibetan # Mn TIBETAN SYMBOL PADMA GDAN
+0FC7..0FCC ; Tibetan # So [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
+0FCE..0FCF ; Tibetan # So [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM
+0FD0..0FD4 ; Tibetan # Po [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA
+0FD9..0FDA ; Tibetan # Po [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS
+
+# Total code points: 207
+
+# ================================================
+
+1000..102A ; Myanmar # Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU
+102B..102C ; Myanmar # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA
+102D..1030 ; Myanmar # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
+1031 ; Myanmar # Mc MYANMAR VOWEL SIGN E
+1032..1037 ; Myanmar # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW
+1038 ; Myanmar # Mc MYANMAR SIGN VISARGA
+1039..103A ; Myanmar # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
+103B..103C ; Myanmar # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
+103D..103E ; Myanmar # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA
+103F ; Myanmar # Lo MYANMAR LETTER GREAT SA
+1040..1049 ; Myanmar # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
+104A..104F ; Myanmar # Po [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
+1050..1055 ; Myanmar # Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL
+1056..1057 ; Myanmar # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
+1058..1059 ; Myanmar # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL
+105A..105D ; Myanmar # Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE
+105E..1060 ; Myanmar # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA
+1061 ; Myanmar # Lo MYANMAR LETTER SGAW KAREN SHA
+1062..1064 ; Myanmar # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO
+1065..1066 ; Myanmar # Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA
+1067..106D ; Myanmar # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5
+106E..1070 ; Myanmar # Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA
+1071..1074 ; Myanmar # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE
+1075..1081 ; Myanmar # Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA
+1082 ; Myanmar # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA
+1083..1084 ; Myanmar # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E
+1085..1086 ; Myanmar # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
+1087..108C ; Myanmar # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3
+108D ; Myanmar # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
+108E ; Myanmar # Lo MYANMAR LETTER RUMAI PALAUNG FA
+108F ; Myanmar # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5
+1090..1099 ; Myanmar # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
+109A..109C ; Myanmar # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A
+109D ; Myanmar # Mn MYANMAR VOWEL SIGN AITON AI
+109E..109F ; Myanmar # So [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION
+A9E0..A9E4 ; Myanmar # Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA
+A9E5 ; Myanmar # Mn MYANMAR SIGN SHAN SAW
+A9E6 ; Myanmar # Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION
+A9E7..A9EF ; Myanmar # Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA
+A9F0..A9F9 ; Myanmar # Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE
+A9FA..A9FE ; Myanmar # Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA
+AA60..AA6F ; Myanmar # Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA
+AA70 ; Myanmar # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION
+AA71..AA76 ; Myanmar # Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM
+AA77..AA79 ; Myanmar # So [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
+AA7A ; Myanmar # Lo MYANMAR LETTER AITON RA
+AA7B ; Myanmar # Mc MYANMAR SIGN PAO KAREN TONE
+AA7C ; Myanmar # Mn MYANMAR SIGN TAI LAING TONE-2
+AA7D ; Myanmar # Mc MYANMAR SIGN TAI LAING TONE-5
+AA7E..AA7F ; Myanmar # Lo [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA
+
+# Total code points: 223
+
+# ================================================
+
+10A0..10C5 ; Georgian # L& [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE
+10C7 ; Georgian # L& GEORGIAN CAPITAL LETTER YN
+10CD ; Georgian # L& GEORGIAN CAPITAL LETTER AEN
+10D0..10FA ; Georgian # L& [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN
+10FC ; Georgian # Lm MODIFIER LETTER GEORGIAN NAR
+10FD..10FF ; Georgian # L& [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
+1C90..1CBA ; Georgian # L& [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN
+1CBD..1CBF ; Georgian # L& [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
+2D00..2D25 ; Georgian # L& [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
+2D27 ; Georgian # L& GEORGIAN SMALL LETTER YN
+2D2D ; Georgian # L& GEORGIAN SMALL LETTER AEN
+
+# Total code points: 173
+
+# ================================================
+
+1100..11FF ; Hangul # Lo [256] HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN
+302E..302F ; Hangul # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
+3131..318E ; Hangul # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
+3200..321E ; Hangul # So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
+3260..327E ; Hangul # So [31] CIRCLED HANGUL KIYEOK..CIRCLED HANGUL IEUNG U
+A960..A97C ; Hangul # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
+AC00..D7A3 ; Hangul # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH
+D7B0..D7C6 ; Hangul # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
+D7CB..D7FB ; Hangul # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
+FFA0..FFBE ; Hangul # Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH
+FFC2..FFC7 ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
+FFCA..FFCF ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
+FFD2..FFD7 ; Hangul # Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
+FFDA..FFDC ; Hangul # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
+
+# Total code points: 11739
+
+# ================================================
+
+1200..1248 ; Ethiopic # Lo [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
+124A..124D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
+1250..1256 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
+1258 ; Ethiopic # Lo ETHIOPIC SYLLABLE QHWA
+125A..125D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
+1260..1288 ; Ethiopic # Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
+128A..128D ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
+1290..12B0 ; Ethiopic # Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
+12B2..12B5 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
+12B8..12BE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
+12C0 ; Ethiopic # Lo ETHIOPIC SYLLABLE KXWA
+12C2..12C5 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
+12C8..12D6 ; Ethiopic # Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
+12D8..1310 ; Ethiopic # Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
+1312..1315 ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
+1318..135A ; Ethiopic # Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
+135D..135F ; Ethiopic # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
+1360..1368 ; Ethiopic # Po [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR
+1369..137C ; Ethiopic # No [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND
+1380..138F ; Ethiopic # Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
+1390..1399 ; Ethiopic # So [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
+2D80..2D96 ; Ethiopic # Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
+2DA0..2DA6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
+2DA8..2DAE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
+2DB0..2DB6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
+2DB8..2DBE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
+2DC0..2DC6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
+2DC8..2DCE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
+2DD0..2DD6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
+2DD8..2DDE ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
+AB01..AB06 ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
+AB09..AB0E ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
+AB11..AB16 ; Ethiopic # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
+AB20..AB26 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
+AB28..AB2E ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
+1E7E0..1E7E6 ; Ethiopic # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO
+1E7E8..1E7EB ; Ethiopic # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE
+1E7ED..1E7EE ; Ethiopic # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE
+1E7F0..1E7FE ; Ethiopic # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE
+
+# Total code points: 523
+
+# ================================================
+
+13A0..13F5 ; Cherokee # L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
+13F8..13FD ; Cherokee # L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
+AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
+
+# Total code points: 172
+
+# ================================================
+
+1400 ; Canadian_Aboriginal # Pd CANADIAN SYLLABICS HYPHEN
+1401..166C ; Canadian_Aboriginal # Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
+166D ; Canadian_Aboriginal # So CANADIAN SYLLABICS CHI SIGN
+166E ; Canadian_Aboriginal # Po CANADIAN SYLLABICS FULL STOP
+166F..167F ; Canadian_Aboriginal # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
+18B0..18F5 ; Canadian_Aboriginal # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
+11AB0..11ABF ; Canadian_Aboriginal # Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA
+
+# Total code points: 726
+
+# ================================================
+
+1680 ; Ogham # Zs OGHAM SPACE MARK
+1681..169A ; Ogham # Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH
+169B ; Ogham # Ps OGHAM FEATHER MARK
+169C ; Ogham # Pe OGHAM REVERSED FEATHER MARK
+
+# Total code points: 29
+
+# ================================================
+
+16A0..16EA ; Runic # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
+16EE..16F0 ; Runic # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL
+16F1..16F8 ; Runic # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
+
+# Total code points: 86
+
+# ================================================
+
+1780..17B3 ; Khmer # Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
+17B4..17B5 ; Khmer # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+17B6 ; Khmer # Mc KHMER VOWEL SIGN AA
+17B7..17BD ; Khmer # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
+17BE..17C5 ; Khmer # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
+17C6 ; Khmer # Mn KHMER SIGN NIKAHIT
+17C7..17C8 ; Khmer # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
+17C9..17D3 ; Khmer # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
+17D4..17D6 ; Khmer # Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
+17D7 ; Khmer # Lm KHMER SIGN LEK TOO
+17D8..17DA ; Khmer # Po [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT
+17DB ; Khmer # Sc KHMER CURRENCY SYMBOL RIEL
+17DC ; Khmer # Lo KHMER SIGN AVAKRAHASANYA
+17DD ; Khmer # Mn KHMER SIGN ATTHACAN
+17E0..17E9 ; Khmer # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
+17F0..17F9 ; Khmer # No [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
+19E0..19FF ; Khmer # So [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC
+
+# Total code points: 146
+
+# ================================================
+
+1800..1801 ; Mongolian # Po [2] MONGOLIAN BIRGA..MONGOLIAN ELLIPSIS
+1804 ; Mongolian # Po MONGOLIAN COLON
+1806 ; Mongolian # Pd MONGOLIAN TODO SOFT HYPHEN
+1807..180A ; Mongolian # Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU
+180B..180D ; Mongolian # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180E ; Mongolian # Cf MONGOLIAN VOWEL SEPARATOR
+180F ; Mongolian # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
+1810..1819 ; Mongolian # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
+1820..1842 ; Mongolian # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI
+1843 ; Mongolian # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN
+1844..1878 ; Mongolian # Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS
+1880..1884 ; Mongolian # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA
+1885..1886 ; Mongolian # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
+1887..18A8 ; Mongolian # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA
+18A9 ; Mongolian # Mn MONGOLIAN LETTER ALI GALI DAGALGA
+18AA ; Mongolian # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA
+11660..1166C ; Mongolian # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
+
+# Total code points: 168
+
+# ================================================
+
+3041..3096 ; Hiragana # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
+309D..309E ; Hiragana # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
+309F ; Hiragana # Lo HIRAGANA DIGRAPH YORI
+1B001..1B11F ; Hiragana # Lo [287] HIRAGANA LETTER ARCHAIC YE..HIRAGANA LETTER ARCHAIC WU
+1B150..1B152 ; Hiragana # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO
+1F200 ; Hiragana # So SQUARE HIRAGANA HOKA
+
+# Total code points: 380
+
+# ================================================
+
+30A1..30FA ; Katakana # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
+30FD..30FE ; Katakana # Lm [2] KATAKANA ITERATION MARK..KATAKANA VOICED ITERATION MARK
+30FF ; Katakana # Lo KATAKANA DIGRAPH KOTO
+31F0..31FF ; Katakana # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
+32D0..32FE ; Katakana # So [47] CIRCLED KATAKANA A..CIRCLED KATAKANA WO
+3300..3357 ; Katakana # So [88] SQUARE APAATO..SQUARE WATTO
+FF66..FF6F ; Katakana # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
+FF71..FF9D ; Katakana # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
+1AFF0..1AFF3 ; Katakana # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5
+1AFF5..1AFFB ; Katakana # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5
+1AFFD..1AFFE ; Katakana # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8
+1B000 ; Katakana # Lo KATAKANA LETTER ARCHAIC E
+1B120..1B122 ; Katakana # Lo [3] KATAKANA LETTER ARCHAIC YI..KATAKANA LETTER ARCHAIC WU
+1B164..1B167 ; Katakana # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N
+
+# Total code points: 320
+
+# ================================================
+
+02EA..02EB ; Bopomofo # Sk [2] MODIFIER LETTER YIN DEPARTING TONE MARK..MODIFIER LETTER YANG DEPARTING TONE MARK
+3105..312F ; Bopomofo # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
+31A0..31BF ; Bopomofo # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH
+
+# Total code points: 77
+
+# ================================================
+
+2E80..2E99 ; Han # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP
+2E9B..2EF3 ; Han # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
+2F00..2FD5 ; Han # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
+3005 ; Han # Lm IDEOGRAPHIC ITERATION MARK
+3007 ; Han # Nl IDEOGRAPHIC NUMBER ZERO
+3021..3029 ; Han # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
+3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
+303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK
+3400..4DBF ; Han # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
+4E00..9FFF ; Han # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF
+F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
+FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
+16FE2 ; Han # Po OLD CHINESE HOOK MARK
+16FE3 ; Han # Lm OLD CHINESE ITERATION MARK
+16FF0..16FF1 ; Han # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
+20000..2A6DF ; Han # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF
+2A700..2B738 ; Han # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738
+2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
+2CEB0..2EBE0 ; Han # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
+2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
+30000..3134A ; Han # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
+
+# Total code points: 94215
+
+# ================================================
+
+A000..A014 ; Yi # Lo [21] YI SYLLABLE IT..YI SYLLABLE E
+A015 ; Yi # Lm YI SYLLABLE WU
+A016..A48C ; Yi # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR
+A490..A4C6 ; Yi # So [55] YI RADICAL QOT..YI RADICAL KE
+
+# Total code points: 1220
+
+# ================================================
+
+10300..1031F ; Old_Italic # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS
+10320..10323 ; Old_Italic # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
+1032D..1032F ; Old_Italic # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE
+
+# Total code points: 39
+
+# ================================================
+
+10330..10340 ; Gothic # Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
+10341 ; Gothic # Nl GOTHIC LETTER NINETY
+10342..10349 ; Gothic # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
+1034A ; Gothic # Nl GOTHIC LETTER NINE HUNDRED
+
+# Total code points: 27
+
+# ================================================
+
+10400..1044F ; Deseret # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW
+
+# Total code points: 80
+
+# ================================================
+
+0300..036F ; Inherited # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
+0485..0486 ; Inherited # Mn [2] COMBINING CYRILLIC DASIA PNEUMATA..COMBINING CYRILLIC PSILI PNEUMATA
+064B..0655 ; Inherited # Mn [11] ARABIC FATHATAN..ARABIC HAMZA BELOW
+0670 ; Inherited # Mn ARABIC LETTER SUPERSCRIPT ALEF
+0951..0954 ; Inherited # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT
+1AB0..1ABD ; Inherited # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE ; Inherited # Me COMBINING PARENTHESES OVERLAY
+1ABF..1ACE ; Inherited # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
+1CD0..1CD2 ; Inherited # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
+1CD4..1CE0 ; Inherited # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
+1CE2..1CE8 ; Inherited # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
+1CED ; Inherited # Mn VEDIC SIGN TIRYAK
+1CF4 ; Inherited # Mn VEDIC TONE CANDRA ABOVE
+1CF8..1CF9 ; Inherited # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
+1DC0..1DFF ; Inherited # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+200C..200D ; Inherited # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
+20D0..20DC ; Inherited # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
+20DD..20E0 ; Inherited # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
+20E1 ; Inherited # Mn COMBINING LEFT RIGHT ARROW ABOVE
+20E2..20E4 ; Inherited # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
+20E5..20F0 ; Inherited # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
+302A..302D ; Inherited # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
+3099..309A ; Inherited # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+FE00..FE0F ; Inherited # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+FE20..FE2D ; Inherited # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON BELOW
+101FD ; Inherited # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
+102E0 ; Inherited # Mn COPTIC EPACT THOUSANDS MARK
+1133B ; Inherited # Mn COMBINING BINDU BELOW
+1CF00..1CF2D ; Inherited # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
+1CF30..1CF46 ; Inherited # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
+1D167..1D169 ; Inherited # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
+1D17B..1D182 ; Inherited # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
+1D185..1D18B ; Inherited # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
+1D1AA..1D1AD ; Inherited # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
+E0100..E01EF ; Inherited # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+
+# Total code points: 657
+
+# ================================================
+
+1700..1711 ; Tagalog # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA
+1712..1714 ; Tagalog # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
+1715 ; Tagalog # Mc TAGALOG SIGN PAMUDPOD
+171F ; Tagalog # Lo TAGALOG LETTER ARCHAIC RA
+
+# Total code points: 23
+
+# ================================================
+
+1720..1731 ; Hanunoo # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA
+1732..1733 ; Hanunoo # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U
+1734 ; Hanunoo # Mc HANUNOO SIGN PAMUDPOD
+
+# Total code points: 21
+
+# ================================================
+
+1740..1751 ; Buhid # Lo [18] BUHID LETTER A..BUHID LETTER HA
+1752..1753 ; Buhid # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
+
+# Total code points: 20
+
+# ================================================
+
+1760..176C ; Tagbanwa # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA
+176E..1770 ; Tagbanwa # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA
+1772..1773 ; Tagbanwa # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
+
+# Total code points: 18
+
+# ================================================
+
+1900..191E ; Limbu # Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA
+1920..1922 ; Limbu # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
+1923..1926 ; Limbu # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU
+1927..1928 ; Limbu # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
+1929..192B ; Limbu # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA
+1930..1931 ; Limbu # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
+1932 ; Limbu # Mn LIMBU SMALL LETTER ANUSVARA
+1933..1938 ; Limbu # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
+1939..193B ; Limbu # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
+1940 ; Limbu # So LIMBU SIGN LOO
+1944..1945 ; Limbu # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
+1946..194F ; Limbu # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
+
+# Total code points: 68
+
+# ================================================
+
+1950..196D ; Tai_Le # Lo [30] TAI LE LETTER KA..TAI LE LETTER AI
+1970..1974 ; Tai_Le # Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
+
+# Total code points: 35
+
+# ================================================
+
+10000..1000B ; Linear_B # Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
+1000D..10026 ; Linear_B # Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
+10028..1003A ; Linear_B # Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
+1003C..1003D ; Linear_B # Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
+1003F..1004D ; Linear_B # Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
+10050..1005D ; Linear_B # Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
+10080..100FA ; Linear_B # Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
+
+# Total code points: 211
+
+# ================================================
+
+10380..1039D ; Ugaritic # Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU
+1039F ; Ugaritic # Po UGARITIC WORD DIVIDER
+
+# Total code points: 31
+
+# ================================================
+
+10450..1047F ; Shavian # Lo [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW
+
+# Total code points: 48
+
+# ================================================
+
+10480..1049D ; Osmanya # Lo [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO
+104A0..104A9 ; Osmanya # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
+
+# Total code points: 40
+
+# ================================================
+
+10800..10805 ; Cypriot # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
+10808 ; Cypriot # Lo CYPRIOT SYLLABLE JO
+1080A..10835 ; Cypriot # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
+10837..10838 ; Cypriot # Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
+1083C ; Cypriot # Lo CYPRIOT SYLLABLE ZA
+1083F ; Cypriot # Lo CYPRIOT SYLLABLE ZO
+
+# Total code points: 55
+
+# ================================================
+
+2800..28FF ; Braille # So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678
+
+# Total code points: 256
+
+# ================================================
+
+1A00..1A16 ; Buginese # Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA
+1A17..1A18 ; Buginese # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
+1A19..1A1A ; Buginese # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
+1A1B ; Buginese # Mn BUGINESE VOWEL SIGN AE
+1A1E..1A1F ; Buginese # Po [2] BUGINESE PALLAWA..BUGINESE END OF SECTION
+
+# Total code points: 30
+
+# ================================================
+
+03E2..03EF ; Coptic # L& [14] COPTIC CAPITAL LETTER SHEI..COPTIC SMALL LETTER DEI
+2C80..2CE4 ; Coptic # L& [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI
+2CE5..2CEA ; Coptic # So [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA
+2CEB..2CEE ; Coptic # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA
+2CEF..2CF1 ; Coptic # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
+2CF2..2CF3 ; Coptic # L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI
+2CF9..2CFC ; Coptic # Po [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER
+2CFD ; Coptic # No COPTIC FRACTION ONE HALF
+2CFE..2CFF ; Coptic # Po [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
+
+# Total code points: 137
+
+# ================================================
+
+1980..19AB ; New_Tai_Lue # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
+19B0..19C9 ; New_Tai_Lue # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
+19D0..19D9 ; New_Tai_Lue # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
+19DA ; New_Tai_Lue # No NEW TAI LUE THAM DIGIT ONE
+19DE..19DF ; New_Tai_Lue # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
+
+# Total code points: 83
+
+# ================================================
+
+2C00..2C5F ; Glagolitic # L& [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI
+1E000..1E006 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
+1E008..1E018 ; Glagolitic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
+1E01B..1E021 ; Glagolitic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
+1E023..1E024 ; Glagolitic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
+1E026..1E02A ; Glagolitic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
+
+# Total code points: 134
+
+# ================================================
+
+2D30..2D67 ; Tifinagh # Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
+2D6F ; Tifinagh # Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK
+2D70 ; Tifinagh # Po TIFINAGH SEPARATOR MARK
+2D7F ; Tifinagh # Mn TIFINAGH CONSONANT JOINER
+
+# Total code points: 59
+
+# ================================================
+
+A800..A801 ; Syloti_Nagri # Lo [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I
+A802 ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN DVISVARA
+A803..A805 ; Syloti_Nagri # Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O
+A806 ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN HASANTA
+A807..A80A ; Syloti_Nagri # Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO
+A80B ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN ANUSVARA
+A80C..A822 ; Syloti_Nagri # Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO
+A823..A824 ; Syloti_Nagri # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
+A825..A826 ; Syloti_Nagri # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
+A827 ; Syloti_Nagri # Mc SYLOTI NAGRI VOWEL SIGN OO
+A828..A82B ; Syloti_Nagri # So [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
+A82C ; Syloti_Nagri # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA
+
+# Total code points: 45
+
+# ================================================
+
+103A0..103C3 ; Old_Persian # Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
+103C8..103CF ; Old_Persian # Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
+103D0 ; Old_Persian # Po OLD PERSIAN WORD DIVIDER
+103D1..103D5 ; Old_Persian # Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED
+
+# Total code points: 50
+
+# ================================================
+
+10A00 ; Kharoshthi # Lo KHAROSHTHI LETTER A
+10A01..10A03 ; Kharoshthi # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
+10A05..10A06 ; Kharoshthi # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
+10A0C..10A0F ; Kharoshthi # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
+10A10..10A13 ; Kharoshthi # Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA
+10A15..10A17 ; Kharoshthi # Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
+10A19..10A35 ; Kharoshthi # Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA
+10A38..10A3A ; Kharoshthi # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
+10A3F ; Kharoshthi # Mn KHAROSHTHI VIRAMA
+10A40..10A48 ; Kharoshthi # No [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF
+10A50..10A58 ; Kharoshthi # Po [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
+
+# Total code points: 68
+
+# ================================================
+
+1B00..1B03 ; Balinese # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
+1B04 ; Balinese # Mc BALINESE SIGN BISAH
+1B05..1B33 ; Balinese # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA
+1B34 ; Balinese # Mn BALINESE SIGN REREKAN
+1B35 ; Balinese # Mc BALINESE VOWEL SIGN TEDUNG
+1B36..1B3A ; Balinese # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
+1B3B ; Balinese # Mc BALINESE VOWEL SIGN RA REPA TEDUNG
+1B3C ; Balinese # Mn BALINESE VOWEL SIGN LA LENGA
+1B3D..1B41 ; Balinese # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG
+1B42 ; Balinese # Mn BALINESE VOWEL SIGN PEPET
+1B43..1B44 ; Balinese # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG
+1B45..1B4C ; Balinese # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA
+1B50..1B59 ; Balinese # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
+1B5A..1B60 ; Balinese # Po [7] BALINESE PANTI..BALINESE PAMENENG
+1B61..1B6A ; Balinese # So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE
+1B6B..1B73 ; Balinese # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
+1B74..1B7C ; Balinese # So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
+1B7D..1B7E ; Balinese # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
+
+# Total code points: 124
+
+# ================================================
+
+12000..12399 ; Cuneiform # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
+12400..1246E ; Cuneiform # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
+12470..12474 ; Cuneiform # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
+12480..12543 ; Cuneiform # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+
+# Total code points: 1234
+
+# ================================================
+
+10900..10915 ; Phoenician # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
+10916..1091B ; Phoenician # No [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
+1091F ; Phoenician # Po PHOENICIAN WORD SEPARATOR
+
+# Total code points: 29
+
+# ================================================
+
+A840..A873 ; Phags_Pa # Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
+A874..A877 ; Phags_Pa # Po [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
+
+# Total code points: 56
+
+# ================================================
+
+07C0..07C9 ; Nko # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE
+07CA..07EA ; Nko # Lo [33] NKO LETTER A..NKO LETTER JONA RA
+07EB..07F3 ; Nko # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
+07F4..07F5 ; Nko # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
+07F6 ; Nko # So NKO SYMBOL OO DENNEN
+07F7..07F9 ; Nko # Po [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK
+07FA ; Nko # Lm NKO LAJANYALAN
+07FD ; Nko # Mn NKO DANTAYALAN
+07FE..07FF ; Nko # Sc [2] NKO DOROME SIGN..NKO TAMAN SIGN
+
+# Total code points: 62
+
+# ================================================
+
+1B80..1B81 ; Sundanese # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
+1B82 ; Sundanese # Mc SUNDANESE SIGN PANGWISAD
+1B83..1BA0 ; Sundanese # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA
+1BA1 ; Sundanese # Mc SUNDANESE CONSONANT SIGN PAMINGKAL
+1BA2..1BA5 ; Sundanese # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
+1BA6..1BA7 ; Sundanese # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG
+1BA8..1BA9 ; Sundanese # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
+1BAA ; Sundanese # Mc SUNDANESE SIGN PAMAAEH
+1BAB..1BAD ; Sundanese # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
+1BAE..1BAF ; Sundanese # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA
+1BB0..1BB9 ; Sundanese # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
+1BBA..1BBF ; Sundanese # Lo [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M
+1CC0..1CC7 ; Sundanese # Po [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA
+
+# Total code points: 72
+
+# ================================================
+
+1C00..1C23 ; Lepcha # Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A
+1C24..1C2B ; Lepcha # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU
+1C2C..1C33 ; Lepcha # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
+1C34..1C35 ; Lepcha # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
+1C36..1C37 ; Lepcha # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
+1C3B..1C3F ; Lepcha # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
+1C40..1C49 ; Lepcha # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
+1C4D..1C4F ; Lepcha # Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA
+
+# Total code points: 74
+
+# ================================================
+
+1C50..1C59 ; Ol_Chiki # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
+1C5A..1C77 ; Ol_Chiki # Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH
+1C78..1C7D ; Ol_Chiki # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD
+1C7E..1C7F ; Ol_Chiki # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
+
+# Total code points: 48
+
+# ================================================
+
+A500..A60B ; Vai # Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG
+A60C ; Vai # Lm VAI SYLLABLE LENGTHENER
+A60D..A60F ; Vai # Po [3] VAI COMMA..VAI QUESTION MARK
+A610..A61F ; Vai # Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG
+A620..A629 ; Vai # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE
+A62A..A62B ; Vai # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO
+
+# Total code points: 300
+
+# ================================================
+
+A880..A881 ; Saurashtra # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
+A882..A8B3 ; Saurashtra # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA
+A8B4..A8C3 ; Saurashtra # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU
+A8C4..A8C5 ; Saurashtra # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
+A8CE..A8CF ; Saurashtra # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
+A8D0..A8D9 ; Saurashtra # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
+
+# Total code points: 82
+
+# ================================================
+
+A900..A909 ; Kayah_Li # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
+A90A..A925 ; Kayah_Li # Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO
+A926..A92D ; Kayah_Li # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
+A92F ; Kayah_Li # Po KAYAH LI SIGN SHYA
+
+# Total code points: 47
+
+# ================================================
+
+A930..A946 ; Rejang # Lo [23] REJANG LETTER KA..REJANG LETTER A
+A947..A951 ; Rejang # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
+A952..A953 ; Rejang # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA
+A95F ; Rejang # Po REJANG SECTION MARK
+
+# Total code points: 37
+
+# ================================================
+
+10280..1029C ; Lycian # Lo [29] LYCIAN LETTER A..LYCIAN LETTER X
+
+# Total code points: 29
+
+# ================================================
+
+102A0..102D0 ; Carian # Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3
+
+# Total code points: 49
+
+# ================================================
+
+10920..10939 ; Lydian # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C
+1093F ; Lydian # Po LYDIAN TRIANGULAR MARK
+
+# Total code points: 27
+
+# ================================================
+
+AA00..AA28 ; Cham # Lo [41] CHAM LETTER A..CHAM LETTER HA
+AA29..AA2E ; Cham # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
+AA2F..AA30 ; Cham # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI
+AA31..AA32 ; Cham # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
+AA33..AA34 ; Cham # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA
+AA35..AA36 ; Cham # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
+AA40..AA42 ; Cham # Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG
+AA43 ; Cham # Mn CHAM CONSONANT SIGN FINAL NG
+AA44..AA4B ; Cham # Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS
+AA4C ; Cham # Mn CHAM CONSONANT SIGN FINAL M
+AA4D ; Cham # Mc CHAM CONSONANT SIGN FINAL H
+AA50..AA59 ; Cham # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
+AA5C..AA5F ; Cham # Po [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
+
+# Total code points: 83
+
+# ================================================
+
+1A20..1A54 ; Tai_Tham # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA
+1A55 ; Tai_Tham # Mc TAI THAM CONSONANT SIGN MEDIAL RA
+1A56 ; Tai_Tham # Mn TAI THAM CONSONANT SIGN MEDIAL LA
+1A57 ; Tai_Tham # Mc TAI THAM CONSONANT SIGN LA TANG LAI
+1A58..1A5E ; Tai_Tham # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
+1A60 ; Tai_Tham # Mn TAI THAM SIGN SAKOT
+1A61 ; Tai_Tham # Mc TAI THAM VOWEL SIGN A
+1A62 ; Tai_Tham # Mn TAI THAM VOWEL SIGN MAI SAT
+1A63..1A64 ; Tai_Tham # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA
+1A65..1A6C ; Tai_Tham # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
+1A6D..1A72 ; Tai_Tham # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
+1A73..1A7C ; Tai_Tham # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
+1A7F ; Tai_Tham # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
+1A80..1A89 ; Tai_Tham # Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE
+1A90..1A99 ; Tai_Tham # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
+1AA0..1AA6 ; Tai_Tham # Po [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
+1AA7 ; Tai_Tham # Lm TAI THAM SIGN MAI YAMOK
+1AA8..1AAD ; Tai_Tham # Po [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
+
+# Total code points: 127
+
+# ================================================
+
+AA80..AAAF ; Tai_Viet # Lo [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O
+AAB0 ; Tai_Viet # Mn TAI VIET MAI KANG
+AAB1 ; Tai_Viet # Lo TAI VIET VOWEL AA
+AAB2..AAB4 ; Tai_Viet # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U
+AAB5..AAB6 ; Tai_Viet # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O
+AAB7..AAB8 ; Tai_Viet # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
+AAB9..AABD ; Tai_Viet # Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN
+AABE..AABF ; Tai_Viet # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
+AAC0 ; Tai_Viet # Lo TAI VIET TONE MAI NUENG
+AAC1 ; Tai_Viet # Mn TAI VIET TONE MAI THO
+AAC2 ; Tai_Viet # Lo TAI VIET TONE MAI SONG
+AADB..AADC ; Tai_Viet # Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG
+AADD ; Tai_Viet # Lm TAI VIET SYMBOL SAM
+AADE..AADF ; Tai_Viet # Po [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
+
+# Total code points: 72
+
+# ================================================
+
+10B00..10B35 ; Avestan # Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE
+10B39..10B3F ; Avestan # Po [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
+
+# Total code points: 61
+
+# ================================================
+
+13000..1342E ; Egyptian_Hieroglyphs # Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
+13430..13438 ; Egyptian_Hieroglyphs # Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT
+
+# Total code points: 1080
+
+# ================================================
+
+0800..0815 ; Samaritan # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
+0816..0819 ; Samaritan # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
+081A ; Samaritan # Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT
+081B..0823 ; Samaritan # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
+0824 ; Samaritan # Lm SAMARITAN MODIFIER LETTER SHORT A
+0825..0827 ; Samaritan # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
+0828 ; Samaritan # Lm SAMARITAN MODIFIER LETTER I
+0829..082D ; Samaritan # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
+0830..083E ; Samaritan # Po [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
+
+# Total code points: 61
+
+# ================================================
+
+A4D0..A4F7 ; Lisu # Lo [40] LISU LETTER BA..LISU LETTER OE
+A4F8..A4FD ; Lisu # Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU
+A4FE..A4FF ; Lisu # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
+11FB0 ; Lisu # Lo LISU LETTER YHA
+
+# Total code points: 49
+
+# ================================================
+
+A6A0..A6E5 ; Bamum # Lo [70] BAMUM LETTER A..BAMUM LETTER KI
+A6E6..A6EF ; Bamum # Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM
+A6F0..A6F1 ; Bamum # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
+A6F2..A6F7 ; Bamum # Po [6] BAMUM NJAEMLI..BAMUM QUESTION MARK
+16800..16A38 ; Bamum # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
+
+# Total code points: 657
+
+# ================================================
+
+A980..A982 ; Javanese # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
+A983 ; Javanese # Mc JAVANESE SIGN WIGNYAN
+A984..A9B2 ; Javanese # Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA
+A9B3 ; Javanese # Mn JAVANESE SIGN CECAK TELU
+A9B4..A9B5 ; Javanese # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG
+A9B6..A9B9 ; Javanese # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
+A9BA..A9BB ; Javanese # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE
+A9BC..A9BD ; Javanese # Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET
+A9BE..A9C0 ; Javanese # Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON
+A9C1..A9CD ; Javanese # Po [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
+A9D0..A9D9 ; Javanese # Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE
+A9DE..A9DF ; Javanese # Po [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
+
+# Total code points: 90
+
+# ================================================
+
+AAE0..AAEA ; Meetei_Mayek # Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA
+AAEB ; Meetei_Mayek # Mc MEETEI MAYEK VOWEL SIGN II
+AAEC..AAED ; Meetei_Mayek # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
+AAEE..AAEF ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU
+AAF0..AAF1 ; Meetei_Mayek # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
+AAF2 ; Meetei_Mayek # Lo MEETEI MAYEK ANJI
+AAF3..AAF4 ; Meetei_Mayek # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK
+AAF5 ; Meetei_Mayek # Mc MEETEI MAYEK VOWEL SIGN VISARGA
+AAF6 ; Meetei_Mayek # Mn MEETEI MAYEK VIRAMA
+ABC0..ABE2 ; Meetei_Mayek # Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM
+ABE3..ABE4 ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP
+ABE5 ; Meetei_Mayek # Mn MEETEI MAYEK VOWEL SIGN ANAP
+ABE6..ABE7 ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP
+ABE8 ; Meetei_Mayek # Mn MEETEI MAYEK VOWEL SIGN UNAP
+ABE9..ABEA ; Meetei_Mayek # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG
+ABEB ; Meetei_Mayek # Po MEETEI MAYEK CHEIKHEI
+ABEC ; Meetei_Mayek # Mc MEETEI MAYEK LUM IYEK
+ABED ; Meetei_Mayek # Mn MEETEI MAYEK APUN IYEK
+ABF0..ABF9 ; Meetei_Mayek # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
+
+# Total code points: 79
+
+# ================================================
+
+10840..10855 ; Imperial_Aramaic # Lo [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW
+10857 ; Imperial_Aramaic # Po IMPERIAL ARAMAIC SECTION SIGN
+10858..1085F ; Imperial_Aramaic # No [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
+
+# Total code points: 31
+
+# ================================================
+
+10A60..10A7C ; Old_South_Arabian # Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
+10A7D..10A7E ; Old_South_Arabian # No [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY
+10A7F ; Old_South_Arabian # Po OLD SOUTH ARABIAN NUMERIC INDICATOR
+
+# Total code points: 32
+
+# ================================================
+
+10B40..10B55 ; Inscriptional_Parthian # Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
+10B58..10B5F ; Inscriptional_Parthian # No [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
+
+# Total code points: 30
+
+# ================================================
+
+10B60..10B72 ; Inscriptional_Pahlavi # Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
+10B78..10B7F ; Inscriptional_Pahlavi # No [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
+
+# Total code points: 27
+
+# ================================================
+
+10C00..10C48 ; Old_Turkic # Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
+
+# Total code points: 73
+
+# ================================================
+
+11080..11081 ; Kaithi # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA
+11082 ; Kaithi # Mc KAITHI SIGN VISARGA
+11083..110AF ; Kaithi # Lo [45] KAITHI LETTER A..KAITHI LETTER HA
+110B0..110B2 ; Kaithi # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
+110B3..110B6 ; Kaithi # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
+110B7..110B8 ; Kaithi # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
+110B9..110BA ; Kaithi # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
+110BB..110BC ; Kaithi # Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN
+110BD ; Kaithi # Cf KAITHI NUMBER SIGN
+110BE..110C1 ; Kaithi # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
+110C2 ; Kaithi # Mn KAITHI VOWEL SIGN VOCALIC R
+110CD ; Kaithi # Cf KAITHI NUMBER SIGN ABOVE
+
+# Total code points: 68
+
+# ================================================
+
+1BC0..1BE5 ; Batak # Lo [38] BATAK LETTER A..BATAK LETTER U
+1BE6 ; Batak # Mn BATAK SIGN TOMPI
+1BE7 ; Batak # Mc BATAK VOWEL SIGN E
+1BE8..1BE9 ; Batak # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
+1BEA..1BEC ; Batak # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O
+1BED ; Batak # Mn BATAK VOWEL SIGN KARO O
+1BEE ; Batak # Mc BATAK VOWEL SIGN U
+1BEF..1BF1 ; Batak # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
+1BF2..1BF3 ; Batak # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN
+1BFC..1BFF ; Batak # Po [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
+
+# Total code points: 56
+
+# ================================================
+
+11000 ; Brahmi # Mc BRAHMI SIGN CANDRABINDU
+11001 ; Brahmi # Mn BRAHMI SIGN ANUSVARA
+11002 ; Brahmi # Mc BRAHMI SIGN VISARGA
+11003..11037 ; Brahmi # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA
+11038..11046 ; Brahmi # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
+11047..1104D ; Brahmi # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
+11052..11065 ; Brahmi # No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
+11066..1106F ; Brahmi # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
+11070 ; Brahmi # Mn BRAHMI SIGN OLD TAMIL VIRAMA
+11071..11072 ; Brahmi # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O
+11073..11074 ; Brahmi # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
+11075 ; Brahmi # Lo BRAHMI LETTER OLD TAMIL LLA
+1107F ; Brahmi # Mn BRAHMI NUMBER JOINER
+
+# Total code points: 115
+
+# ================================================
+
+0840..0858 ; Mandaic # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
+0859..085B ; Mandaic # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
+085E ; Mandaic # Po MANDAIC PUNCTUATION
+
+# Total code points: 29
+
+# ================================================
+
+11100..11102 ; Chakma # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
+11103..11126 ; Chakma # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA
+11127..1112B ; Chakma # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
+1112C ; Chakma # Mc CHAKMA VOWEL SIGN E
+1112D..11134 ; Chakma # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
+11136..1113F ; Chakma # Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
+11140..11143 ; Chakma # Po [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK
+11144 ; Chakma # Lo CHAKMA LETTER LHAA
+11145..11146 ; Chakma # Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI
+11147 ; Chakma # Lo CHAKMA LETTER VAA
+
+# Total code points: 71
+
+# ================================================
+
+109A0..109B7 ; Meroitic_Cursive # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
+109BC..109BD ; Meroitic_Cursive # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
+109BE..109BF ; Meroitic_Cursive # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
+109C0..109CF ; Meroitic_Cursive # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D2..109FF ; Meroitic_Cursive # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+
+# Total code points: 90
+
+# ================================================
+
+10980..1099F ; Meroitic_Hieroglyphs # Lo [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2
+
+# Total code points: 32
+
+# ================================================
+
+16F00..16F4A ; Miao # Lo [75] MIAO LETTER PA..MIAO LETTER RTE
+16F4F ; Miao # Mn MIAO SIGN CONSONANT MODIFIER BAR
+16F50 ; Miao # Lo MIAO LETTER NASALIZATION
+16F51..16F87 ; Miao # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
+16F8F..16F92 ; Miao # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
+16F93..16F9F ; Miao # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
+
+# Total code points: 149
+
+# ================================================
+
+11180..11181 ; Sharada # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
+11182 ; Sharada # Mc SHARADA SIGN VISARGA
+11183..111B2 ; Sharada # Lo [48] SHARADA LETTER A..SHARADA LETTER HA
+111B3..111B5 ; Sharada # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
+111B6..111BE ; Sharada # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
+111BF..111C0 ; Sharada # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
+111C1..111C4 ; Sharada # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM
+111C5..111C8 ; Sharada # Po [4] SHARADA DANDA..SHARADA SEPARATOR
+111C9..111CC ; Sharada # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
+111CD ; Sharada # Po SHARADA SUTRA MARK
+111CE ; Sharada # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E
+111CF ; Sharada # Mn SHARADA SIGN INVERTED CANDRABINDU
+111D0..111D9 ; Sharada # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
+111DA ; Sharada # Lo SHARADA EKAM
+111DB ; Sharada # Po SHARADA SIGN SIDDHAM
+111DC ; Sharada # Lo SHARADA HEADSTROKE
+111DD..111DF ; Sharada # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+
+# Total code points: 96
+
+# ================================================
+
+110D0..110E8 ; Sora_Sompeng # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
+110F0..110F9 ; Sora_Sompeng # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
+
+# Total code points: 35
+
+# ================================================
+
+11680..116AA ; Takri # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA
+116AB ; Takri # Mn TAKRI SIGN ANUSVARA
+116AC ; Takri # Mc TAKRI SIGN VISARGA
+116AD ; Takri # Mn TAKRI VOWEL SIGN AA
+116AE..116AF ; Takri # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
+116B0..116B5 ; Takri # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
+116B6 ; Takri # Mc TAKRI SIGN VIRAMA
+116B7 ; Takri # Mn TAKRI SIGN NUKTA
+116B8 ; Takri # Lo TAKRI LETTER ARCHAIC KHA
+116B9 ; Takri # Po TAKRI ABBREVIATION SIGN
+116C0..116C9 ; Takri # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE
+
+# Total code points: 68
+
+# ================================================
+
+10530..10563 ; Caucasian_Albanian # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
+1056F ; Caucasian_Albanian # Po CAUCASIAN ALBANIAN CITATION MARK
+
+# Total code points: 53
+
+# ================================================
+
+16AD0..16AED ; Bassa_Vah # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I
+16AF0..16AF4 ; Bassa_Vah # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
+16AF5 ; Bassa_Vah # Po BASSA VAH FULL STOP
+
+# Total code points: 36
+
+# ================================================
+
+1BC00..1BC6A ; Duployan # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
+1BC70..1BC7C ; Duployan # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
+1BC80..1BC88 ; Duployan # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
+1BC90..1BC99 ; Duployan # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
+1BC9C ; Duployan # So DUPLOYAN SIGN O WITH CROSS
+1BC9D..1BC9E ; Duployan # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BC9F ; Duployan # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+
+# Total code points: 143
+
+# ================================================
+
+10500..10527 ; Elbasan # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE
+
+# Total code points: 40
+
+# ================================================
+
+11300..11301 ; Grantha # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
+11302..11303 ; Grantha # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
+11305..1130C ; Grantha # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
+1130F..11310 ; Grantha # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI
+11313..11328 ; Grantha # Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA
+1132A..11330 ; Grantha # Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA
+11332..11333 ; Grantha # Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA
+11335..11339 ; Grantha # Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA
+1133C ; Grantha # Mn GRANTHA SIGN NUKTA
+1133D ; Grantha # Lo GRANTHA SIGN AVAGRAHA
+1133E..1133F ; Grantha # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
+11340 ; Grantha # Mn GRANTHA VOWEL SIGN II
+11341..11344 ; Grantha # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
+11347..11348 ; Grantha # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
+1134B..1134D ; Grantha # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+11350 ; Grantha # Lo GRANTHA OM
+11357 ; Grantha # Mc GRANTHA AU LENGTH MARK
+1135D..11361 ; Grantha # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
+11362..11363 ; Grantha # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
+11366..1136C ; Grantha # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
+11370..11374 ; Grantha # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
+
+# Total code points: 85
+
+# ================================================
+
+16B00..16B2F ; Pahawh_Hmong # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
+16B30..16B36 ; Pahawh_Hmong # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
+16B37..16B3B ; Pahawh_Hmong # Po [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM
+16B3C..16B3F ; Pahawh_Hmong # So [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB
+16B40..16B43 ; Pahawh_Hmong # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
+16B44 ; Pahawh_Hmong # Po PAHAWH HMONG SIGN XAUS
+16B45 ; Pahawh_Hmong # So PAHAWH HMONG SIGN CIM TSOV ROG
+16B50..16B59 ; Pahawh_Hmong # Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
+16B5B..16B61 ; Pahawh_Hmong # No [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
+16B63..16B77 ; Pahawh_Hmong # Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
+16B7D..16B8F ; Pahawh_Hmong # Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
+
+# Total code points: 127
+
+# ================================================
+
+11200..11211 ; Khojki # Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA
+11213..1122B ; Khojki # Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA
+1122C..1122E ; Khojki # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
+1122F..11231 ; Khojki # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
+11232..11233 ; Khojki # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
+11234 ; Khojki # Mn KHOJKI SIGN ANUSVARA
+11235 ; Khojki # Mc KHOJKI SIGN VIRAMA
+11236..11237 ; Khojki # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
+11238..1123D ; Khojki # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
+1123E ; Khojki # Mn KHOJKI SIGN SUKUN
+
+# Total code points: 62
+
+# ================================================
+
+10600..10736 ; Linear_A # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664
+10740..10755 ; Linear_A # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
+10760..10767 ; Linear_A # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807
+
+# Total code points: 341
+
+# ================================================
+
+11150..11172 ; Mahajani # Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA
+11173 ; Mahajani # Mn MAHAJANI SIGN NUKTA
+11174..11175 ; Mahajani # Po [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
+11176 ; Mahajani # Lo MAHAJANI LIGATURE SHRI
+
+# Total code points: 39
+
+# ================================================
+
+10AC0..10AC7 ; Manichaean # Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
+10AC8 ; Manichaean # So MANICHAEAN SIGN UD
+10AC9..10AE4 ; Manichaean # Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
+10AE5..10AE6 ; Manichaean # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
+10AEB..10AEF ; Manichaean # No [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED
+10AF0..10AF6 ; Manichaean # Po [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER
+
+# Total code points: 51
+
+# ================================================
+
+1E800..1E8C4 ; Mende_Kikakui # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
+1E8C7..1E8CF ; Mende_Kikakui # No [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
+1E8D0..1E8D6 ; Mende_Kikakui # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
+
+# Total code points: 213
+
+# ================================================
+
+11600..1162F ; Modi # Lo [48] MODI LETTER A..MODI LETTER LLA
+11630..11632 ; Modi # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
+11633..1163A ; Modi # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
+1163B..1163C ; Modi # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
+1163D ; Modi # Mn MODI SIGN ANUSVARA
+1163E ; Modi # Mc MODI SIGN VISARGA
+1163F..11640 ; Modi # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
+11641..11643 ; Modi # Po [3] MODI DANDA..MODI ABBREVIATION SIGN
+11644 ; Modi # Lo MODI SIGN HUVA
+11650..11659 ; Modi # Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE
+
+# Total code points: 79
+
+# ================================================
+
+16A40..16A5E ; Mro # Lo [31] MRO LETTER TA..MRO LETTER TEK
+16A60..16A69 ; Mro # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE
+16A6E..16A6F ; Mro # Po [2] MRO DANDA..MRO DOUBLE DANDA
+
+# Total code points: 43
+
+# ================================================
+
+10A80..10A9C ; Old_North_Arabian # Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
+10A9D..10A9F ; Old_North_Arabian # No [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
+
+# Total code points: 32
+
+# ================================================
+
+10880..1089E ; Nabataean # Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
+108A7..108AF ; Nabataean # No [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
+
+# Total code points: 40
+
+# ================================================
+
+10860..10876 ; Palmyrene # Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
+10877..10878 ; Palmyrene # So [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON
+10879..1087F ; Palmyrene # No [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY
+
+# Total code points: 32
+
+# ================================================
+
+11AC0..11AF8 ; Pau_Cin_Hau # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
+
+# Total code points: 57
+
+# ================================================
+
+10350..10375 ; Old_Permic # Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA
+10376..1037A ; Old_Permic # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
+
+# Total code points: 43
+
+# ================================================
+
+10B80..10B91 ; Psalter_Pahlavi # Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
+10B99..10B9C ; Psalter_Pahlavi # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
+10BA9..10BAF ; Psalter_Pahlavi # No [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
+
+# Total code points: 29
+
+# ================================================
+
+11580..115AE ; Siddham # Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA
+115AF..115B1 ; Siddham # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II
+115B2..115B5 ; Siddham # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
+115B8..115BB ; Siddham # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
+115BC..115BD ; Siddham # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
+115BE ; Siddham # Mc SIDDHAM SIGN VISARGA
+115BF..115C0 ; Siddham # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
+115C1..115D7 ; Siddham # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8..115DB ; Siddham # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
+115DC..115DD ; Siddham # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
+
+# Total code points: 92
+
+# ================================================
+
+112B0..112DE ; Khudawadi # Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA
+112DF ; Khudawadi # Mn KHUDAWADI SIGN ANUSVARA
+112E0..112E2 ; Khudawadi # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
+112E3..112EA ; Khudawadi # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
+112F0..112F9 ; Khudawadi # Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
+
+# Total code points: 69
+
+# ================================================
+
+11480..114AF ; Tirhuta # Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA
+114B0..114B2 ; Tirhuta # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II
+114B3..114B8 ; Tirhuta # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
+114B9 ; Tirhuta # Mc TIRHUTA VOWEL SIGN E
+114BA ; Tirhuta # Mn TIRHUTA VOWEL SIGN SHORT E
+114BB..114BE ; Tirhuta # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU
+114BF..114C0 ; Tirhuta # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
+114C1 ; Tirhuta # Mc TIRHUTA SIGN VISARGA
+114C2..114C3 ; Tirhuta # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
+114C4..114C5 ; Tirhuta # Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG
+114C6 ; Tirhuta # Po TIRHUTA ABBREVIATION SIGN
+114C7 ; Tirhuta # Lo TIRHUTA OM
+114D0..114D9 ; Tirhuta # Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
+
+# Total code points: 82
+
+# ================================================
+
+118A0..118DF ; Warang_Citi # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO
+118E0..118E9 ; Warang_Citi # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE
+118EA..118F2 ; Warang_Citi # No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
+118FF ; Warang_Citi # Lo WARANG CITI OM
+
+# Total code points: 84
+
+# ================================================
+
+11700..1171A ; Ahom # Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA
+1171D..1171F ; Ahom # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; Ahom # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; Ahom # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; Ahom # Mc AHOM VOWEL SIGN E
+11727..1172B ; Ahom # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+11730..11739 ; Ahom # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A..1173B ; Ahom # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
+1173C..1173E ; Ahom # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+1173F ; Ahom # So AHOM SYMBOL VI
+11740..11746 ; Ahom # Lo [7] AHOM LETTER CA..AHOM LETTER LLA
+
+# Total code points: 65
+
+# ================================================
+
+14400..14646 ; Anatolian_Hieroglyphs # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+
+# Total code points: 583
+
+# ================================================
+
+108E0..108F2 ; Hatran # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F4..108F5 ; Hatran # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
+108FB..108FF ; Hatran # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+
+# Total code points: 26
+
+# ================================================
+
+11280..11286 ; Multani # Lo [7] MULTANI LETTER A..MULTANI LETTER GA
+11288 ; Multani # Lo MULTANI LETTER GHA
+1128A..1128D ; Multani # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA
+1128F..1129D ; Multani # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA
+1129F..112A8 ; Multani # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9 ; Multani # Po MULTANI SECTION MARK
+
+# Total code points: 38
+
+# ================================================
+
+10C80..10CB2 ; Old_Hungarian # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
+10CC0..10CF2 ; Old_Hungarian # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CFA..10CFF ; Old_Hungarian # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+
+# Total code points: 108
+
+# ================================================
+
+1D800..1D9FF ; SignWriting # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
+1DA00..1DA36 ; SignWriting # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37..1DA3A ; SignWriting # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B..1DA6C ; SignWriting # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D..1DA74 ; SignWriting # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75 ; SignWriting # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76..1DA83 ; SignWriting # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84 ; SignWriting # Mn SIGNWRITING LOCATION HEAD NECK
+1DA85..1DA86 ; SignWriting # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
+1DA87..1DA8B ; SignWriting # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
+1DA9B..1DA9F ; SignWriting # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA1..1DAAF ; SignWriting # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+
+# Total code points: 672
+
+# ================================================
+
+1E900..1E943 ; Adlam # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA
+1E944..1E94A ; Adlam # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
+1E94B ; Adlam # Lm ADLAM NASALIZATION MARK
+1E950..1E959 ; Adlam # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
+1E95E..1E95F ; Adlam # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
+
+# Total code points: 88
+
+# ================================================
+
+11C00..11C08 ; Bhaiksuki # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
+11C0A..11C2E ; Bhaiksuki # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA
+11C2F ; Bhaiksuki # Mc BHAIKSUKI VOWEL SIGN AA
+11C30..11C36 ; Bhaiksuki # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
+11C38..11C3D ; Bhaiksuki # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
+11C3E ; Bhaiksuki # Mc BHAIKSUKI SIGN VISARGA
+11C3F ; Bhaiksuki # Mn BHAIKSUKI SIGN VIRAMA
+11C40 ; Bhaiksuki # Lo BHAIKSUKI SIGN AVAGRAHA
+11C41..11C45 ; Bhaiksuki # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
+11C50..11C59 ; Bhaiksuki # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
+11C5A..11C6C ; Bhaiksuki # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
+
+# Total code points: 97
+
+# ================================================
+
+11C70..11C71 ; Marchen # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD
+11C72..11C8F ; Marchen # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A
+11C92..11CA7 ; Marchen # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
+11CA9 ; Marchen # Mc MARCHEN SUBJOINED LETTER YA
+11CAA..11CB0 ; Marchen # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
+11CB1 ; Marchen # Mc MARCHEN VOWEL SIGN I
+11CB2..11CB3 ; Marchen # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
+11CB4 ; Marchen # Mc MARCHEN VOWEL SIGN O
+11CB5..11CB6 ; Marchen # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
+
+# Total code points: 68
+
+# ================================================
+
+11400..11434 ; Newa # Lo [53] NEWA LETTER A..NEWA LETTER HA
+11435..11437 ; Newa # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II
+11438..1143F ; Newa # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
+11440..11441 ; Newa # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU
+11442..11444 ; Newa # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
+11445 ; Newa # Mc NEWA SIGN VISARGA
+11446 ; Newa # Mn NEWA SIGN NUKTA
+11447..1144A ; Newa # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI
+1144B..1144F ; Newa # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN
+11450..11459 ; Newa # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE
+1145A..1145B ; Newa # Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK
+1145D ; Newa # Po NEWA INSERTION SIGN
+1145E ; Newa # Mn NEWA SANDHI MARK
+1145F..11461 ; Newa # Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA
+
+# Total code points: 97
+
+# ================================================
+
+104B0..104D3 ; Osage # L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA
+104D8..104FB ; Osage # L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
+
+# Total code points: 72
+
+# ================================================
+
+16FE0 ; Tangut # Lm TANGUT ITERATION MARK
+17000..187F7 ; Tangut # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7
+18800..18AFF ; Tangut # Lo [768] TANGUT COMPONENT-001..TANGUT COMPONENT-768
+18D00..18D08 ; Tangut # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
+
+# Total code points: 6914
+
+# ================================================
+
+11D00..11D06 ; Masaram_Gondi # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
+11D08..11D09 ; Masaram_Gondi # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
+11D0B..11D30 ; Masaram_Gondi # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA
+11D31..11D36 ; Masaram_Gondi # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D3A ; Masaram_Gondi # Mn MASARAM GONDI VOWEL SIGN E
+11D3C..11D3D ; Masaram_Gondi # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3F..11D45 ; Masaram_Gondi # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
+11D46 ; Masaram_Gondi # Lo MASARAM GONDI REPHA
+11D47 ; Masaram_Gondi # Mn MASARAM GONDI RA-KARA
+11D50..11D59 ; Masaram_Gondi # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
+
+# Total code points: 75
+
+# ================================================
+
+16FE1 ; Nushu # Lm NUSHU ITERATION MARK
+1B170..1B2FB ; Nushu # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
+
+# Total code points: 397
+
+# ================================================
+
+11A50 ; Soyombo # Lo SOYOMBO LETTER A
+11A51..11A56 ; Soyombo # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
+11A57..11A58 ; Soyombo # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
+11A59..11A5B ; Soyombo # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
+11A5C..11A89 ; Soyombo # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA
+11A8A..11A96 ; Soyombo # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
+11A97 ; Soyombo # Mc SOYOMBO SIGN VISARGA
+11A98..11A99 ; Soyombo # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
+11A9A..11A9C ; Soyombo # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
+11A9D ; Soyombo # Lo SOYOMBO MARK PLUTA
+11A9E..11AA2 ; Soyombo # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
+
+# Total code points: 83
+
+# ================================================
+
+11A00 ; Zanabazar_Square # Lo ZANABAZAR SQUARE LETTER A
+11A01..11A0A ; Zanabazar_Square # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
+11A0B..11A32 ; Zanabazar_Square # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA
+11A33..11A38 ; Zanabazar_Square # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
+11A39 ; Zanabazar_Square # Mc ZANABAZAR SQUARE SIGN VISARGA
+11A3A ; Zanabazar_Square # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
+11A3B..11A3E ; Zanabazar_Square # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A3F..11A46 ; Zanabazar_Square # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
+11A47 ; Zanabazar_Square # Mn ZANABAZAR SQUARE SUBJOINER
+
+# Total code points: 72
+
+# ================================================
+
+11800..1182B ; Dogra # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA
+1182C..1182E ; Dogra # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
+1182F..11837 ; Dogra # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
+11838 ; Dogra # Mc DOGRA SIGN VISARGA
+11839..1183A ; Dogra # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
+1183B ; Dogra # Po DOGRA ABBREVIATION SIGN
+
+# Total code points: 60
+
+# ================================================
+
+11D60..11D65 ; Gunjala_Gondi # Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
+11D67..11D68 ; Gunjala_Gondi # Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
+11D6A..11D89 ; Gunjala_Gondi # Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA
+11D8A..11D8E ; Gunjala_Gondi # Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU
+11D90..11D91 ; Gunjala_Gondi # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
+11D93..11D94 ; Gunjala_Gondi # Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU
+11D95 ; Gunjala_Gondi # Mn GUNJALA GONDI SIGN ANUSVARA
+11D96 ; Gunjala_Gondi # Mc GUNJALA GONDI SIGN VISARGA
+11D97 ; Gunjala_Gondi # Mn GUNJALA GONDI VIRAMA
+11D98 ; Gunjala_Gondi # Lo GUNJALA GONDI OM
+11DA0..11DA9 ; Gunjala_Gondi # Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
+
+# Total code points: 63
+
+# ================================================
+
+11EE0..11EF2 ; Makasar # Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA
+11EF3..11EF4 ; Makasar # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
+11EF5..11EF6 ; Makasar # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
+11EF7..11EF8 ; Makasar # Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION
+
+# Total code points: 25
+
+# ================================================
+
+16E40..16E7F ; Medefaidrin # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y
+16E80..16E96 ; Medefaidrin # No [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM
+16E97..16E9A ; Medefaidrin # Po [4] MEDEFAIDRIN COMMA..MEDEFAIDRIN EXCLAMATION OH
+
+# Total code points: 91
+
+# ================================================
+
+10D00..10D23 ; Hanifi_Rohingya # Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
+10D24..10D27 ; Hanifi_Rohingya # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
+10D30..10D39 ; Hanifi_Rohingya # Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
+
+# Total code points: 50
+
+# ================================================
+
+10F30..10F45 ; Sogdian # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
+10F46..10F50 ; Sogdian # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+10F51..10F54 ; Sogdian # No [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
+10F55..10F59 ; Sogdian # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+
+# Total code points: 42
+
+# ================================================
+
+10F00..10F1C ; Old_Sogdian # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
+10F1D..10F26 ; Old_Sogdian # No [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
+10F27 ; Old_Sogdian # Lo OLD SOGDIAN LIGATURE AYIN-DALETH
+
+# Total code points: 40
+
+# ================================================
+
+10FE0..10FF6 ; Elymaic # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH
+
+# Total code points: 23
+
+# ================================================
+
+119A0..119A7 ; Nandinagari # Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR
+119AA..119D0 ; Nandinagari # Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA
+119D1..119D3 ; Nandinagari # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
+119D4..119D7 ; Nandinagari # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
+119DA..119DB ; Nandinagari # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
+119DC..119DF ; Nandinagari # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA
+119E0 ; Nandinagari # Mn NANDINAGARI SIGN VIRAMA
+119E1 ; Nandinagari # Lo NANDINAGARI SIGN AVAGRAHA
+119E2 ; Nandinagari # Po NANDINAGARI SIGN SIDDHAM
+119E3 ; Nandinagari # Lo NANDINAGARI HEADSTROKE
+119E4 ; Nandinagari # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
+
+# Total code points: 65
+
+# ================================================
+
+1E100..1E12C ; Nyiakeng_Puachue_Hmong # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
+1E130..1E136 ; Nyiakeng_Puachue_Hmong # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E137..1E13D ; Nyiakeng_Puachue_Hmong # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
+1E140..1E149 ; Nyiakeng_Puachue_Hmong # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
+1E14E ; Nyiakeng_Puachue_Hmong # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
+1E14F ; Nyiakeng_Puachue_Hmong # So NYIAKENG PUACHUE HMONG CIRCLED CA
+
+# Total code points: 71
+
+# ================================================
+
+1E2C0..1E2EB ; Wancho # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH
+1E2EC..1E2EF ; Wancho # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
+1E2F0..1E2F9 ; Wancho # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
+1E2FF ; Wancho # Sc WANCHO NGUN SIGN
+
+# Total code points: 59
+
+# ================================================
+
+10FB0..10FC4 ; Chorasmian # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW
+10FC5..10FCB ; Chorasmian # No [7] CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED
+
+# Total code points: 28
+
+# ================================================
+
+11900..11906 ; Dives_Akuru # Lo [7] DIVES AKURU LETTER A..DIVES AKURU LETTER E
+11909 ; Dives_Akuru # Lo DIVES AKURU LETTER O
+1190C..11913 ; Dives_Akuru # Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA
+11915..11916 ; Dives_Akuru # Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA
+11918..1192F ; Dives_Akuru # Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA
+11930..11935 ; Dives_Akuru # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E
+11937..11938 ; Dives_Akuru # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
+1193B..1193C ; Dives_Akuru # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
+1193D ; Dives_Akuru # Mc DIVES AKURU SIGN HALANTA
+1193E ; Dives_Akuru # Mn DIVES AKURU VIRAMA
+1193F ; Dives_Akuru # Lo DIVES AKURU PREFIXED NASAL SIGN
+11940 ; Dives_Akuru # Mc DIVES AKURU MEDIAL YA
+11941 ; Dives_Akuru # Lo DIVES AKURU INITIAL RA
+11942 ; Dives_Akuru # Mc DIVES AKURU MEDIAL RA
+11943 ; Dives_Akuru # Mn DIVES AKURU SIGN NUKTA
+11944..11946 ; Dives_Akuru # Po [3] DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK
+11950..11959 ; Dives_Akuru # Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE
+
+# Total code points: 72
+
+# ================================================
+
+16FE4 ; Khitan_Small_Script # Mn KHITAN SMALL SCRIPT FILLER
+18B00..18CD5 ; Khitan_Small_Script # Lo [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5
+
+# Total code points: 471
+
+# ================================================
+
+10E80..10EA9 ; Yezidi # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
+10EAB..10EAC ; Yezidi # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
+10EAD ; Yezidi # Pd YEZIDI HYPHENATION MARK
+10EB0..10EB1 ; Yezidi # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
+
+# Total code points: 47
+
+# ================================================
+
+12F90..12FF0 ; Cypro_Minoan # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114
+12FF1..12FF2 ; Cypro_Minoan # Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302
+
+# Total code points: 99
+
+# ================================================
+
+10F70..10F81 ; Old_Uyghur # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH
+10F82..10F85 ; Old_Uyghur # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
+10F86..10F89 ; Old_Uyghur # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
+
+# Total code points: 26
+
+# ================================================
+
+16A70..16ABE ; Tangsa # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA
+16AC0..16AC9 ; Tangsa # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE
+
+# Total code points: 89
+
+# ================================================
+
+1E290..1E2AD ; Toto # Lo [30] TOTO LETTER PA..TOTO LETTER A
+1E2AE ; Toto # Mn TOTO SIGN RISING TONE
+
+# Total code points: 31
+
+# ================================================
+
+10570..1057A ; Vithkuqi # L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA
+1057C..1058A ; Vithkuqi # L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE
+1058C..10592 ; Vithkuqi # L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE
+10594..10595 ; Vithkuqi # L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE
+10597..105A1 ; Vithkuqi # L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA
+105A3..105B1 ; Vithkuqi # L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE
+105B3..105B9 ; Vithkuqi # L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE
+105BB..105BC ; Vithkuqi # L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE
+
+# Total code points: 70
+
+# EOF
diff --git a/admin/unidata/blocks.awk b/admin/unidata/blocks.awk
index 48d8c873c7a..5f392b5ad35 100755
--- a/admin/unidata/blocks.awk
+++ b/admin/unidata/blocks.awk
@@ -98,7 +98,7 @@ function name2alias(name , w, w2) {
else if (name ~ /arabic/) return "arabic"
else if (name ~ /^greek/) return "greek"
else if (name ~ /^coptic/) return "coptic"
- else if (name ~ /cuneiform number/) return "cuneiform-numbers-and-punctuation"
+ else if (name ~ /cuneiform number/) return "cuneiform"
else if (name ~ /cuneiform/) return "cuneiform"
else if (name ~ /mathematical alphanumeric symbol/) return "mathematical"
else if (name ~ /punctuation|mathematical|arrows|currency|superscript|small form variants|geometric|dingbats|enclosed|alchemical|pictograph|emoticon|transport/) return "symbol"
@@ -113,9 +113,11 @@ function name2alias(name , w, w2) {
else if (name ~/^(specials|tags)$/) return 0
else if (name ~ /linear b/) return "linear-b"
else if (name ~ /aramaic/) return "aramaic"
- else if (name ~ /rumi num/) return "rumi-number"
+ else if (name ~ /rumi num/) return "arabic"
else if (name ~ /duployan|shorthand/) return "duployan-shorthand"
else if (name ~ /sutton signwriting/) return "sutton-sign-writing"
+ else if (name ~ /sinhala archaic number/) return "sinhala"
+ else if (name ~ /tangut components/) return "tangut"
sub(/^small /, "", name)
sub(/ (extended|extensions*|supplement).*/, "", name)
diff --git a/admin/unidata/confusables.txt b/admin/unidata/confusables.txt
new file mode 100644
index 00000000000..c75f78ec3e9
--- /dev/null
+++ b/admin/unidata/confusables.txt
@@ -0,0 +1,9637 @@
+# confusables.txt
+# Date: 2021-05-29, 22:09:29 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 Security Mechanisms for UTS #39
+# Version: 14.0.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr39
+#
+05AD ; 0596 ; MA # ( ֭ → ֖ ) HEBREW ACCENT DEHI → HEBREW ACCENT TIPEHA #
+
+05AE ; 0598 ; MA # ( ֮ → ֘ ) HEBREW ACCENT ZINOR → HEBREW ACCENT ZARQA #
+
+05A8 ; 0599 ; MA # ( ֨ → ֙ ) HEBREW ACCENT QADMA → HEBREW ACCENT PASHTA #
+
+05A4 ; 059A ; MA # ( ֤ → ֚ ) HEBREW ACCENT MAHAPAKH → HEBREW ACCENT YETIV #
+
+1AB4 ; 06DB ; MA # ( ᪴ → ۛ ) COMBINING TRIPLE DOT → ARABIC SMALL HIGH THREE DOTS #
+20DB ; 06DB ; MA # ( ⃛ → ۛ ) COMBINING THREE DOTS ABOVE → ARABIC SMALL HIGH THREE DOTS # →᪴→
+
+0619 ; 0313 ; MA # ( ؙ → ̓ ) ARABIC SMALL DAMMA → COMBINING COMMA ABOVE # →ُ→
+08F3 ; 0313 ; MA # ( ࣳ → ̓ ) ARABIC SMALL HIGH WAW → COMBINING COMMA ABOVE # →ُ→
+0343 ; 0313 ; MA # ( ̓ → ̓ ) COMBINING GREEK KORONIS → COMBINING COMMA ABOVE #
+0315 ; 0313 ; MA # ( ̕ → ̓ ) COMBINING COMMA ABOVE RIGHT → COMBINING COMMA ABOVE #
+064F ; 0313 ; MA # ( ُ → ̓ ) ARABIC DAMMA → COMBINING COMMA ABOVE #
+
+065D ; 0314 ; MA # ( ٝ → ̔ ) ARABIC REVERSED DAMMA → COMBINING REVERSED COMMA ABOVE #
+
+059C ; 0301 ; MA # ( ֜ → ́ ) HEBREW ACCENT GERESH → COMBINING ACUTE ACCENT #
+059D ; 0301 ; MA # ( ֝ → ́ ) HEBREW ACCENT GERESH MUQDAM → COMBINING ACUTE ACCENT # →֜→
+0618 ; 0301 ; MA # ( ؘ → ́ ) ARABIC SMALL FATHA → COMBINING ACUTE ACCENT # →َ→
+0747 ; 0301 ; MA # ( ݇ → ́ ) SYRIAC OBLIQUE LINE ABOVE → COMBINING ACUTE ACCENT #
+0341 ; 0301 ; MA # ( ́ → ́ ) COMBINING ACUTE TONE MARK → COMBINING ACUTE ACCENT #
+0954 ; 0301 ; MA # ( ॔ → ́ ) DEVANAGARI ACUTE ACCENT → COMBINING ACUTE ACCENT #
+064E ; 0301 ; MA # ( َ → ́ ) ARABIC FATHA → COMBINING ACUTE ACCENT #
+
+0340 ; 0300 ; MA # ( ̀ → ̀ ) COMBINING GRAVE TONE MARK → COMBINING GRAVE ACCENT #
+0953 ; 0300 ; MA # ( ॓ → ̀ ) DEVANAGARI GRAVE ACCENT → COMBINING GRAVE ACCENT #
+
+030C ; 0306 ; MA # ( ̌ → ̆ ) COMBINING CARON → COMBINING BREVE #
+A67C ; 0306 ; MA # ( ꙼ → ̆ ) COMBINING CYRILLIC KAVYKA → COMBINING BREVE #
+0658 ; 0306 ; MA # ( ٘ → ̆ ) ARABIC MARK NOON GHUNNA → COMBINING BREVE #
+065A ; 0306 ; MA # ( ٚ → ̆ ) ARABIC VOWEL SIGN SMALL V ABOVE → COMBINING BREVE # →̌→
+036E ; 0306 ; MA # ( ͮ → ̆ ) COMBINING LATIN SMALL LETTER V → COMBINING BREVE # →̌→
+
+06E8 ; 0306 0307 ; MA # ( ۨ → ̆̇ ) ARABIC SMALL HIGH NOON → COMBINING BREVE, COMBINING DOT ABOVE # →̐→
+0310 ; 0306 0307 ; MA # ( ̐ → ̆̇ ) COMBINING CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE #
+0901 ; 0306 0307 ; MA # ( ँ → ̆̇ ) DEVANAGARI SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →̐→
+0981 ; 0306 0307 ; MA # ( ঁ → ̆̇ ) BENGALI SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →̐→
+0A81 ; 0306 0307 ; MA # ( ઁ → ̆̇ ) GUJARATI SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →̐→
+0B01 ; 0306 0307 ; MA # ( ଁ → ̆̇ ) ORIYA SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →̐→
+0C00 ; 0306 0307 ; MA # ( ఀ → ̆̇ ) TELUGU SIGN COMBINING CANDRABINDU ABOVE → COMBINING BREVE, COMBINING DOT ABOVE # →ँ→→̐→
+0C81 ; 0306 0307 ; MA # ( ಁ → ̆̇ ) KANNADA SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →ँ→→̐→
+0D01 ; 0306 0307 ; MA # ( ഁ → ̆̇ ) MALAYALAM SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →ँ→→̐→
+114BF ; 0306 0307 ; MA # ( 𑒿 → ̆̇ ) TIRHUTA SIGN CANDRABINDU → COMBINING BREVE, COMBINING DOT ABOVE # →ঁ→→̐→
+
+1CD0 ; 0302 ; MA # ( ᳐ → ̂ ) VEDIC TONE KARSHANA → COMBINING CIRCUMFLEX ACCENT #
+0311 ; 0302 ; MA # ( ̑ → ̂ ) COMBINING INVERTED BREVE → COMBINING CIRCUMFLEX ACCENT #
+065B ; 0302 ; MA # ( ٛ → ̂ ) ARABIC VOWEL SIGN INVERTED SMALL V ABOVE → COMBINING CIRCUMFLEX ACCENT #
+07EE ; 0302 ; MA # ( ߮ → ̂ ) NKO COMBINING LONG DESCENDING TONE → COMBINING CIRCUMFLEX ACCENT #
+A6F0 ; 0302 ; MA # ( ꛰ → ̂ ) BAMUM COMBINING MARK KOQNDON → COMBINING CIRCUMFLEX ACCENT #
+
+05AF ; 030A ; MA # ( ֯ → ̊ ) HEBREW MARK MASORA CIRCLE → COMBINING RING ABOVE #
+06DF ; 030A ; MA # ( ۟ → ̊ ) ARABIC SMALL HIGH ROUNDED ZERO → COMBINING RING ABOVE # →ْ→
+17D3 ; 030A ; MA # ( ៓ → ̊ ) KHMER SIGN BATHAMASAT → COMBINING RING ABOVE #
+309A ; 030A ; MA # ( ゚ → ̊ ) COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK → COMBINING RING ABOVE #
+0652 ; 030A ; MA # ( ْ → ̊ ) ARABIC SUKUN → COMBINING RING ABOVE #
+0B82 ; 030A ; MA # ( ஂ → ̊ ) TAMIL SIGN ANUSVARA → COMBINING RING ABOVE #
+1036 ; 030A ; MA # ( ံ → ̊ ) MYANMAR SIGN ANUSVARA → COMBINING RING ABOVE #
+17C6 ; 030A ; MA # ( ំ → ̊ ) KHMER SIGN NIKAHIT → COMBINING RING ABOVE #
+11300 ; 030A ; MA # ( 𑌀 → ̊ ) GRANTHA SIGN COMBINING ANUSVARA ABOVE → COMBINING RING ABOVE # →ஂ→
+0E4D ; 030A ; MA # ( ํ → ̊ ) THAI CHARACTER NIKHAHIT → COMBINING RING ABOVE #
+0ECD ; 030A ; MA # ( ໍ → ̊ ) LAO NIGGAHITA → COMBINING RING ABOVE #
+0366 ; 030A ; MA # ( ͦ → ̊ ) COMBINING LATIN SMALL LETTER O → COMBINING RING ABOVE #
+2DEA ; 030A ; MA # ( ⷪ → ̊ ) COMBINING CYRILLIC LETTER O → COMBINING RING ABOVE # →ͦ→
+
+08EB ; 0308 ; MA # ( ࣫ → ̈ ) ARABIC TONE TWO DOTS ABOVE → COMBINING DIAERESIS #
+07F3 ; 0308 ; MA # ( ߳ → ̈ ) NKO COMBINING DOUBLE DOT ABOVE → COMBINING DIAERESIS #
+
+064B ; 030B ; MA # ( ً → ̋ ) ARABIC FATHATAN → COMBINING DOUBLE ACUTE ACCENT #
+08F0 ; 030B ; MA # ( ࣰ → ̋ ) ARABIC OPEN FATHATAN → COMBINING DOUBLE ACUTE ACCENT # →ً→
+
+0342 ; 0303 ; MA # ( ͂ → ̃ ) COMBINING GREEK PERISPOMENI → COMBINING TILDE #
+0653 ; 0303 ; MA # ( ٓ → ̃ ) ARABIC MADDAH ABOVE → COMBINING TILDE #
+
+05C4 ; 0307 ; MA # ( ׄ → ̇ ) HEBREW MARK UPPER DOT → COMBINING DOT ABOVE #
+06EC ; 0307 ; MA # ( ۬ → ̇ ) ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE → COMBINING DOT ABOVE #
+0740 ; 0307 ; MA # ( ݀ → ̇ ) SYRIAC FEMININE DOT → COMBINING DOT ABOVE # →݁→
+08EA ; 0307 ; MA # ( ࣪ → ̇ ) ARABIC TONE ONE DOT ABOVE → COMBINING DOT ABOVE #
+0741 ; 0307 ; MA # ( ݁ → ̇ ) SYRIAC QUSHSHAYA → COMBINING DOT ABOVE #
+0358 ; 0307 ; MA # ( ͘ → ̇ ) COMBINING DOT ABOVE RIGHT → COMBINING DOT ABOVE #
+05B9 ; 0307 ; MA # ( ֹ → ̇ ) HEBREW POINT HOLAM → COMBINING DOT ABOVE #
+05BA ; 0307 ; MA # ( ֺ → ̇ ) HEBREW POINT HOLAM HASER FOR VAV → COMBINING DOT ABOVE # →ׁ→
+05C2 ; 0307 ; MA # ( ׂ → ̇ ) HEBREW POINT SIN DOT → COMBINING DOT ABOVE #
+05C1 ; 0307 ; MA # ( ׁ → ̇ ) HEBREW POINT SHIN DOT → COMBINING DOT ABOVE #
+07ED ; 0307 ; MA # ( ߭ → ̇ ) NKO COMBINING SHORT RISING TONE → COMBINING DOT ABOVE #
+0902 ; 0307 ; MA # ( ं → ̇ ) DEVANAGARI SIGN ANUSVARA → COMBINING DOT ABOVE #
+0A02 ; 0307 ; MA # ( ਂ → ̇ ) GURMUKHI SIGN BINDI → COMBINING DOT ABOVE #
+0A82 ; 0307 ; MA # ( ં → ̇ ) GUJARATI SIGN ANUSVARA → COMBINING DOT ABOVE #
+0BCD ; 0307 ; MA # ( ் → ̇ ) TAMIL SIGN VIRAMA → COMBINING DOT ABOVE #
+
+0337 ; 0338 ; MA # ( ̷ → ̸ ) COMBINING SHORT SOLIDUS OVERLAY → COMBINING LONG SOLIDUS OVERLAY #
+
+1AB7 ; 0328 ; MA # ( ᪷ → ̨ ) COMBINING OPEN MARK BELOW → COMBINING OGONEK #
+0322 ; 0328 ; MA # ( ̢ → ̨ ) COMBINING RETROFLEX HOOK BELOW → COMBINING OGONEK #
+0345 ; 0328 ; MA # ( ͅ → ̨ ) COMBINING GREEK YPOGEGRAMMENI → COMBINING OGONEK #
+
+1CD2 ; 0304 ; MA # ( ᳒ → ̄ ) VEDIC TONE PRENKHA → COMBINING MACRON #
+0305 ; 0304 ; MA # ( ̅ → ̄ ) COMBINING OVERLINE → COMBINING MACRON #
+0659 ; 0304 ; MA # ( ٙ → ̄ ) ARABIC ZWARAKAY → COMBINING MACRON #
+07EB ; 0304 ; MA # ( ߫ → ̄ ) NKO COMBINING SHORT HIGH TONE → COMBINING MACRON #
+A6F1 ; 0304 ; MA # ( ꛱ → ̄ ) BAMUM COMBINING MARK TUKWENTIS → COMBINING MACRON #
+
+1CDA ; 030E ; MA # ( ᳚ → ̎ ) VEDIC TONE DOUBLE SVARITA → COMBINING DOUBLE VERTICAL LINE ABOVE #
+
+0657 ; 0312 ; MA # ( ٗ → ̒ ) ARABIC INVERTED DAMMA → COMBINING TURNED COMMA ABOVE #
+
+0357 ; 0350 ; MA # ( ͗ → ͐ ) COMBINING RIGHT HALF RING ABOVE → COMBINING RIGHT ARROWHEAD ABOVE # →ࣿ→→ࣸ→
+08FF ; 0350 ; MA # ( ࣿ → ͐ ) ARABIC MARK SIDEWAYS NOON GHUNNA → COMBINING RIGHT ARROWHEAD ABOVE # →ࣸ→
+08F8 ; 0350 ; MA # ( ࣸ → ͐ ) ARABIC RIGHT ARROWHEAD ABOVE → COMBINING RIGHT ARROWHEAD ABOVE #
+
+0900 ; 0352 ; MA # ( ऀ → ͒ ) DEVANAGARI SIGN INVERTED CANDRABINDU → COMBINING FERMATA #
+
+1CED ; 0316 ; MA # ( ᳭ → ̖ ) VEDIC SIGN TIRYAK → COMBINING GRAVE ACCENT BELOW #
+
+1CDC ; 0329 ; MA # ( ᳜ → ̩ ) VEDIC TONE KATHAKA ANUDATTA → COMBINING VERTICAL LINE BELOW #
+0656 ; 0329 ; MA # ( ٖ → ̩ ) ARABIC SUBSCRIPT ALEF → COMBINING VERTICAL LINE BELOW #
+
+1CD5 ; 032B ; MA # ( ᳕ → ̫ ) VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA → COMBINING INVERTED DOUBLE ARCH BELOW #
+
+0347 ; 0333 ; MA # ( ͇ → ̳ ) COMBINING EQUALS SIGN BELOW → COMBINING DOUBLE LOW LINE #
+
+08F9 ; 0354 ; MA # ( ࣹ → ͔ ) ARABIC LEFT ARROWHEAD BELOW → COMBINING LEFT ARROWHEAD BELOW #
+
+08FA ; 0355 ; MA # ( ࣺ → ͕ ) ARABIC RIGHT ARROWHEAD BELOW → COMBINING RIGHT ARROWHEAD BELOW #
+
+309B ; FF9E ; MA #* ( ゛ → ゙ ) KATAKANA-HIRAGANA VOICED SOUND MARK → HALFWIDTH KATAKANA VOICED SOUND MARK #
+
+309C ; FF9F ; MA #* ( ゜ → ゚ ) KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK → HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK #
+
+0336 ; 0335 ; MA # ( ̶ → ̵ ) COMBINING LONG STROKE OVERLAY → COMBINING SHORT STROKE OVERLAY #
+
+302C ; 0309 ; MA # ( 〬 → ̉ ) IDEOGRAPHIC DEPARTING TONE MARK → COMBINING HOOK ABOVE #
+
+05C5 ; 0323 ; MA # ( ׅ → ̣ ) HEBREW MARK LOWER DOT → COMBINING DOT BELOW #
+08ED ; 0323 ; MA # ( ࣭ → ̣ ) ARABIC TONE ONE DOT BELOW → COMBINING DOT BELOW #
+1CDD ; 0323 ; MA # ( ᳝ → ̣ ) VEDIC TONE DOT BELOW → COMBINING DOT BELOW #
+05B4 ; 0323 ; MA # ( ִ → ̣ ) HEBREW POINT HIRIQ → COMBINING DOT BELOW #
+065C ; 0323 ; MA # ( ٜ → ̣ ) ARABIC VOWEL SIGN DOT BELOW → COMBINING DOT BELOW #
+093C ; 0323 ; MA # ( ़ → ̣ ) DEVANAGARI SIGN NUKTA → COMBINING DOT BELOW #
+09BC ; 0323 ; MA # ( ় → ̣ ) BENGALI SIGN NUKTA → COMBINING DOT BELOW #
+0A3C ; 0323 ; MA # ( ਼ → ̣ ) GURMUKHI SIGN NUKTA → COMBINING DOT BELOW #
+0ABC ; 0323 ; MA # ( ઼ → ̣ ) GUJARATI SIGN NUKTA → COMBINING DOT BELOW #
+0B3C ; 0323 ; MA # ( ଼ → ̣ ) ORIYA SIGN NUKTA → COMBINING DOT BELOW #
+111CA ; 0323 ; MA # ( 𑇊 → ̣ ) SHARADA SIGN NUKTA → COMBINING DOT BELOW # →़→
+114C3 ; 0323 ; MA # ( 𑓃 → ̣ ) TIRHUTA SIGN NUKTA → COMBINING DOT BELOW # →়→
+10A3A ; 0323 ; MA # ( 𐨺 → ̣ ) KHAROSHTHI SIGN DOT BELOW → COMBINING DOT BELOW #
+
+08EE ; 0324 ; MA # ( ࣮ → ̤ ) ARABIC TONE TWO DOTS BELOW → COMBINING DIAERESIS BELOW #
+1CDE ; 0324 ; MA # ( ᳞ → ̤ ) VEDIC TONE TWO DOTS BELOW → COMBINING DIAERESIS BELOW #
+
+0F37 ; 0325 ; MA # ( ༷ → ̥ ) TIBETAN MARK NGAS BZUNG SGOR RTAGS → COMBINING RING BELOW #
+302D ; 0325 ; MA # ( 〭 → ̥ ) IDEOGRAPHIC ENTERING TONE MARK → COMBINING RING BELOW #
+
+0327 ; 0326 ; MA # ( ̧ → ̦ ) COMBINING CEDILLA → COMBINING COMMA BELOW # →̡→
+0321 ; 0326 ; MA # ( ̡ → ̦ ) COMBINING PALATALIZED HOOK BELOW → COMBINING COMMA BELOW #
+0339 ; 0326 ; MA # ( ̹ → ̦ ) COMBINING RIGHT HALF RING BELOW → COMBINING COMMA BELOW # →̧→→̡→
+
+1CD9 ; 032D ; MA # ( ᳙ → ̭ ) VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER → COMBINING CIRCUMFLEX ACCENT BELOW #
+
+1CD8 ; 032E ; MA # ( ᳘ → ̮ ) VEDIC TONE CANDRA BELOW → COMBINING BREVE BELOW #
+
+0952 ; 0331 ; MA # ( ॒ → ̱ ) DEVANAGARI STRESS SIGN ANUDATTA → COMBINING MACRON BELOW #
+0320 ; 0331 ; MA # ( ̠ → ̱ ) COMBINING MINUS SIGN BELOW → COMBINING MACRON BELOW #
+
+08F1 ; 064C ; MA # ( ࣱ → ٌ ) ARABIC OPEN DAMMATAN → ARABIC DAMMATAN #
+08E8 ; 064C ; MA # ( ࣨ → ٌ ) ARABIC CURLY DAMMATAN → ARABIC DAMMATAN #
+08E5 ; 064C ; MA # ( ࣥ → ٌ ) ARABIC CURLY DAMMA → ARABIC DAMMATAN #
+
+FC5E ; FE72 0651 ; MA #* ( ‎ﱞ‎ → ‎ﹲّ‎ ) ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM → ARABIC DAMMATAN ISOLATED FORM, ARABIC SHADDA #
+
+08F2 ; 064D ; MA # ( ࣲ → ٍ ) ARABIC OPEN KASRATAN → ARABIC KASRATAN #
+
+FC5F ; FE74 0651 ; MA #* ( ‎ﱟ‎ → ‎ﹴّ‎ ) ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM → ARABIC KASRATAN ISOLATED FORM, ARABIC SHADDA #
+
+FCF2 ; FE77 0651 ; MA # ( ‎ﳲ‎ → ‎ﹷّ‎ ) ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM → ARABIC FATHA MEDIAL FORM, ARABIC SHADDA #
+
+FC60 ; FE76 0651 ; MA #* ( ‎ﱠ‎ → ‎ﹶّ‎ ) ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM → ARABIC FATHA ISOLATED FORM, ARABIC SHADDA #
+
+FCF3 ; FE79 0651 ; MA # ( ‎ﳳ‎ → ‎ﹹّ‎ ) ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM → ARABIC DAMMA MEDIAL FORM, ARABIC SHADDA #
+
+FC61 ; FE78 0651 ; MA #* ( ‎ﱡ‎ → ‎ﹸّ‎ ) ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM → ARABIC DAMMA ISOLATED FORM, ARABIC SHADDA #
+
+061A ; 0650 ; MA # ( ؚ → ِ ) ARABIC SMALL KASRA → ARABIC KASRA #
+0317 ; 0650 ; MA # ( ̗ → ِ ) COMBINING ACUTE ACCENT BELOW → ARABIC KASRA #
+
+FCF4 ; FE7B 0651 ; MA # ( ‎ﳴ‎ → ‎ﹻّ‎ ) ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM → ARABIC KASRA MEDIAL FORM, ARABIC SHADDA #
+
+FC62 ; FE7A 0651 ; MA #* ( ‎ﱢ‎ → ‎ﹺّ‎ ) ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM → ARABIC KASRA ISOLATED FORM, ARABIC SHADDA #
+
+FC63 ; FE7C 0670 ; MA #* ( ‎ﱣ‎ → ‎ﹼٰ‎ ) ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM → ARABIC SHADDA ISOLATED FORM, ARABIC LETTER SUPERSCRIPT ALEF #
+
+065F ; 0655 ; MA # ( ٟ → ٕ ) ARABIC WAVY HAMZA BELOW → ARABIC HAMZA BELOW #
+
+030D ; 0670 ; MA # ( ̍ → ٰ ) COMBINING VERTICAL LINE ABOVE → ARABIC LETTER SUPERSCRIPT ALEF #
+
+0742 ; 073C ; MA # ( ݂ → ܼ ) SYRIAC RUKKAKHA → SYRIAC HBASA-ESASA DOTTED #
+
+0A03 ; 0983 ; MA # ( ਃ → ঃ ) GURMUKHI SIGN VISARGA → BENGALI SIGN VISARGA #
+0C03 ; 0983 ; MA # ( ః → ঃ ) TELUGU SIGN VISARGA → BENGALI SIGN VISARGA # →ਃ→
+0C83 ; 0983 ; MA # ( ಃ → ঃ ) KANNADA SIGN VISARGA → BENGALI SIGN VISARGA # →ః→→ਃ→
+0D03 ; 0983 ; MA # ( ഃ → ঃ ) MALAYALAM SIGN VISARGA → BENGALI SIGN VISARGA # →ಃ→→ః→→ਃ→
+0D83 ; 0983 ; MA # ( ඃ → ঃ ) SINHALA SIGN VISARGAYA → BENGALI SIGN VISARGA # →ഃ→→ಃ→→ః→→ਃ→
+1038 ; 0983 ; MA # ( း → ঃ ) MYANMAR SIGN VISARGA → BENGALI SIGN VISARGA # →ඃ→→ഃ→→ಃ→→ః→→ਃ→
+114C1 ; 0983 ; MA # ( 𑓁 → ঃ ) TIRHUTA SIGN VISARGA → BENGALI SIGN VISARGA #
+
+17CB ; 0E48 ; MA # ( ់ → ่ ) KHMER SIGN BANTOC → THAI CHARACTER MAI EK #
+0EC8 ; 0E48 ; MA # ( ່ → ่ ) LAO TONE MAI EK → THAI CHARACTER MAI EK #
+
+0EC9 ; 0E49 ; MA # ( ້ → ้ ) LAO TONE MAI THO → THAI CHARACTER MAI THO #
+
+0ECA ; 0E4A ; MA # ( ໊ → ๊ ) LAO TONE MAI TI → THAI CHARACTER MAI TRI #
+
+0ECB ; 0E4B ; MA # ( ໋ → ๋ ) LAO TONE MAI CATAWA → THAI CHARACTER MAI CHATTAWA #
+
+A66F ; 20E9 ; MA # ( ꙯ → ⃩ ) COMBINING CYRILLIC VZMET → COMBINING WIDE BRIDGE ABOVE #
+
+2028 ; 0020 ; MA #* ( → ) LINE SEPARATOR → SPACE #
+2029 ; 0020 ; MA #* ( → ) PARAGRAPH SEPARATOR → SPACE #
+1680 ; 0020 ; MA #* (   → ) OGHAM SPACE MARK → SPACE #
+2000 ; 0020 ; MA #* (   → ) EN QUAD → SPACE #
+2001 ; 0020 ; MA #* (   → ) EM QUAD → SPACE #
+2002 ; 0020 ; MA #* (   → ) EN SPACE → SPACE #
+2003 ; 0020 ; MA #* (   → ) EM SPACE → SPACE #
+2004 ; 0020 ; MA #* (   → ) THREE-PER-EM SPACE → SPACE #
+2005 ; 0020 ; MA #* (   → ) FOUR-PER-EM SPACE → SPACE #
+2006 ; 0020 ; MA #* (   → ) SIX-PER-EM SPACE → SPACE #
+2008 ; 0020 ; MA #* (   → ) PUNCTUATION SPACE → SPACE #
+2009 ; 0020 ; MA #* (   → ) THIN SPACE → SPACE #
+200A ; 0020 ; MA #* (   → ) HAIR SPACE → SPACE #
+205F ; 0020 ; MA #* (   → ) MEDIUM MATHEMATICAL SPACE → SPACE #
+00A0 ; 0020 ; MA #* (   → ) NO-BREAK SPACE → SPACE #
+2007 ; 0020 ; MA #* (   → ) FIGURE SPACE → SPACE #
+202F ; 0020 ; MA #* (   → ) NARROW NO-BREAK SPACE → SPACE #
+
+07FA ; 005F ; MA # ( ‎ߺ‎ → _ ) NKO LAJANYALAN → LOW LINE #
+FE4D ; 005F ; MA # ( ﹍ → _ ) DASHED LOW LINE → LOW LINE #
+FE4E ; 005F ; MA # ( ﹎ → _ ) CENTRELINE LOW LINE → LOW LINE #
+FE4F ; 005F ; MA # ( ﹏ → _ ) WAVY LOW LINE → LOW LINE #
+
+2010 ; 002D ; MA #* ( ‐ → - ) HYPHEN → HYPHEN-MINUS #
+2011 ; 002D ; MA #* ( ‑ → - ) NON-BREAKING HYPHEN → HYPHEN-MINUS #
+2012 ; 002D ; MA #* ( ‒ → - ) FIGURE DASH → HYPHEN-MINUS #
+2013 ; 002D ; MA #* ( – → - ) EN DASH → HYPHEN-MINUS #
+FE58 ; 002D ; MA #* ( ﹘ → - ) SMALL EM DASH → HYPHEN-MINUS #
+06D4 ; 002D ; MA #* ( ‎۔‎ → - ) ARABIC FULL STOP → HYPHEN-MINUS # →‐→
+2043 ; 002D ; MA #* ( ⁃ → - ) HYPHEN BULLET → HYPHEN-MINUS # →‐→
+02D7 ; 002D ; MA #* ( ˗ → - ) MODIFIER LETTER MINUS SIGN → HYPHEN-MINUS #
+2212 ; 002D ; MA #* ( − → - ) MINUS SIGN → HYPHEN-MINUS #
+2796 ; 002D ; MA #* ( ➖ → - ) HEAVY MINUS SIGN → HYPHEN-MINUS # →−→
+2CBA ; 002D ; MA # ( Ⲻ → - ) COPTIC CAPITAL LETTER DIALECT-P NI → HYPHEN-MINUS # →‒→
+
+2A29 ; 002D 0313 ; MA #* ( ⨩ → -̓ ) MINUS SIGN WITH COMMA ABOVE → HYPHEN-MINUS, COMBINING COMMA ABOVE # →−̓→
+
+2E1A ; 002D 0308 ; MA #* ( ⸚ → -̈ ) HYPHEN WITH DIAERESIS → HYPHEN-MINUS, COMBINING DIAERESIS #
+
+FB29 ; 002D 0307 ; MA #* ( ﬩ → -̇ ) HEBREW LETTER ALTERNATIVE PLUS SIGN → HYPHEN-MINUS, COMBINING DOT ABOVE # →∸→→−̇→
+2238 ; 002D 0307 ; MA #* ( ∸ → -̇ ) DOT MINUS → HYPHEN-MINUS, COMBINING DOT ABOVE # →−̇→
+
+2A2A ; 002D 0323 ; MA #* ( ⨪ → -̣ ) MINUS SIGN WITH DOT BELOW → HYPHEN-MINUS, COMBINING DOT BELOW # →−̣→
+
+A4FE ; 002D 002E ; MA #* ( ꓾ → -. ) LISU PUNCTUATION COMMA → HYPHEN-MINUS, FULL STOP #
+
+FF5E ; 301C ; MA #* ( ~ → 〜 ) FULLWIDTH TILDE → WAVE DASH #
+
+060D ; 002C ; MA #* ( ‎؍‎ → , ) ARABIC DATE SEPARATOR → COMMA # →‎٫‎→
+066B ; 002C ; MA #* ( ‎٫‎ → , ) ARABIC DECIMAL SEPARATOR → COMMA #
+201A ; 002C ; MA #* ( ‚ → , ) SINGLE LOW-9 QUOTATION MARK → COMMA #
+00B8 ; 002C ; MA #* ( ¸ → , ) CEDILLA → COMMA #
+A4F9 ; 002C ; MA # ( ꓹ → , ) LISU LETTER TONE NA PO → COMMA #
+
+2E32 ; 060C ; MA #* ( ⸲ → ، ) TURNED COMMA → ARABIC COMMA #
+066C ; 060C ; MA #* ( ‎٬‎ → ، ) ARABIC THOUSANDS SEPARATOR → ARABIC COMMA #
+
+037E ; 003B ; MA #* ( ; → ; ) GREEK QUESTION MARK → SEMICOLON #
+
+2E35 ; 061B ; MA #* ( ⸵ → ‎؛‎ ) TURNED SEMICOLON → ARABIC SEMICOLON #
+
+0903 ; 003A ; MA # ( ः → : ) DEVANAGARI SIGN VISARGA → COLON #
+0A83 ; 003A ; MA # ( ઃ → : ) GUJARATI SIGN VISARGA → COLON #
+FF1A ; 003A ; MA #* ( : → : ) FULLWIDTH COLON → COLON # →︰→
+0589 ; 003A ; MA #* ( ։ → : ) ARMENIAN FULL STOP → COLON #
+0703 ; 003A ; MA #* ( ‎܃‎ → : ) SYRIAC SUPRALINEAR COLON → COLON #
+0704 ; 003A ; MA #* ( ‎܄‎ → : ) SYRIAC SUBLINEAR COLON → COLON #
+16EC ; 003A ; MA #* ( ᛬ → : ) RUNIC MULTIPLE PUNCTUATION → COLON #
+FE30 ; 003A ; MA #* ( ︰ → : ) PRESENTATION FORM FOR VERTICAL TWO DOT LEADER → COLON #
+1803 ; 003A ; MA #* ( ᠃ → : ) MONGOLIAN FULL STOP → COLON #
+1809 ; 003A ; MA #* ( ᠉ → : ) MONGOLIAN MANCHU FULL STOP → COLON #
+205A ; 003A ; MA #* ( ⁚ → : ) TWO DOT PUNCTUATION → COLON #
+05C3 ; 003A ; MA #* ( ‎׃‎ → : ) HEBREW PUNCTUATION SOF PASUQ → COLON #
+02F8 ; 003A ; MA #* ( ˸ → : ) MODIFIER LETTER RAISED COLON → COLON #
+A789 ; 003A ; MA #* ( ꞉ → : ) MODIFIER LETTER COLON → COLON #
+2236 ; 003A ; MA #* ( ∶ → : ) RATIO → COLON #
+02D0 ; 003A ; MA # ( ː → : ) MODIFIER LETTER TRIANGULAR COLON → COLON #
+A4FD ; 003A ; MA # ( ꓽ → : ) LISU LETTER TONE MYA JEU → COLON #
+
+2A74 ; 003A 003A 003D ; MA #* ( ⩴ → ::= ) DOUBLE COLON EQUAL → COLON, COLON, EQUALS SIGN #
+
+29F4 ; 003A 2192 ; MA #* ( ⧴ → :→ ) RULE-DELAYED → COLON, RIGHTWARDS ARROW #
+
+FF01 ; 0021 ; MA #* ( ! → ! ) FULLWIDTH EXCLAMATION MARK → EXCLAMATION MARK # →ǃ→
+01C3 ; 0021 ; MA # ( ǃ → ! ) LATIN LETTER RETROFLEX CLICK → EXCLAMATION MARK #
+2D51 ; 0021 ; MA # ( ⵑ → ! ) TIFINAGH LETTER TUAREG YANG → EXCLAMATION MARK #
+
+203C ; 0021 0021 ; MA #* ( ‼ → !! ) DOUBLE EXCLAMATION MARK → EXCLAMATION MARK, EXCLAMATION MARK #
+
+2049 ; 0021 003F ; MA #* ( ⁉ → !? ) EXCLAMATION QUESTION MARK → EXCLAMATION MARK, QUESTION MARK #
+
+0294 ; 003F ; MA # ( ʔ → ? ) LATIN LETTER GLOTTAL STOP → QUESTION MARK #
+0241 ; 003F ; MA # ( Ɂ → ? ) LATIN CAPITAL LETTER GLOTTAL STOP → QUESTION MARK # →ʔ→
+097D ; 003F ; MA # ( ॽ → ? ) DEVANAGARI LETTER GLOTTAL STOP → QUESTION MARK #
+13AE ; 003F ; MA # ( Ꭾ → ? ) CHEROKEE LETTER HE → QUESTION MARK # →Ɂ→→ʔ→
+A6EB ; 003F ; MA # ( ꛫ → ? ) BAMUM LETTER NTUU → QUESTION MARK # →ʔ→
+
+2048 ; 003F 0021 ; MA #* ( ⁈ → ?! ) QUESTION EXCLAMATION MARK → QUESTION MARK, EXCLAMATION MARK #
+
+2047 ; 003F 003F ; MA #* ( ⁇ → ?? ) DOUBLE QUESTION MARK → QUESTION MARK, QUESTION MARK #
+
+2E2E ; 061F ; MA #* ( ⸮ → ‎؟‎ ) REVERSED QUESTION MARK → ARABIC QUESTION MARK #
+
+1D16D ; 002E ; MA # ( 𝅭 → . ) MUSICAL SYMBOL COMBINING AUGMENTATION DOT → FULL STOP #
+2024 ; 002E ; MA #* ( ․ → . ) ONE DOT LEADER → FULL STOP #
+0701 ; 002E ; MA #* ( ‎܁‎ → . ) SYRIAC SUPRALINEAR FULL STOP → FULL STOP #
+0702 ; 002E ; MA #* ( ‎܂‎ → . ) SYRIAC SUBLINEAR FULL STOP → FULL STOP #
+A60E ; 002E ; MA #* ( ꘎ → . ) VAI FULL STOP → FULL STOP #
+10A50 ; 002E ; MA #* ( ‎𐩐‎ → . ) KHAROSHTHI PUNCTUATION DOT → FULL STOP #
+0660 ; 002E ; MA # ( ‎٠‎ → . ) ARABIC-INDIC DIGIT ZERO → FULL STOP #
+06F0 ; 002E ; MA # ( ۰ → . ) EXTENDED ARABIC-INDIC DIGIT ZERO → FULL STOP # →‎٠‎→
+A4F8 ; 002E ; MA # ( ꓸ → . ) LISU LETTER TONE MYA TI → FULL STOP #
+
+A4FB ; 002E 002C ; MA # ( ꓻ → ., ) LISU LETTER TONE MYA BO → FULL STOP, COMMA #
+
+2025 ; 002E 002E ; MA #* ( ‥ → .. ) TWO DOT LEADER → FULL STOP, FULL STOP #
+A4FA ; 002E 002E ; MA # ( ꓺ → .. ) LISU LETTER TONE MYA CYA → FULL STOP, FULL STOP #
+
+2026 ; 002E 002E 002E ; MA #* ( … → ... ) HORIZONTAL ELLIPSIS → FULL STOP, FULL STOP, FULL STOP #
+
+A6F4 ; A6F3 A6F3 ; MA #* ( ꛴ → ꛳꛳ ) BAMUM COLON → BAMUM FULL STOP, BAMUM FULL STOP #
+
+30FB ; 00B7 ; MA #* ( ・ → · ) KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
+FF65 ; 00B7 ; MA #* ( ・ → · ) HALFWIDTH KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
+16EB ; 00B7 ; MA #* ( ᛫ → · ) RUNIC SINGLE PUNCTUATION → MIDDLE DOT #
+0387 ; 00B7 ; MA # ( · → · ) GREEK ANO TELEIA → MIDDLE DOT #
+2E31 ; 00B7 ; MA #* ( ⸱ → · ) WORD SEPARATOR MIDDLE DOT → MIDDLE DOT #
+10101 ; 00B7 ; MA #* ( 𐄁 → · ) AEGEAN WORD SEPARATOR DOT → MIDDLE DOT #
+2022 ; 00B7 ; MA #* ( • → · ) BULLET → MIDDLE DOT #
+2027 ; 00B7 ; MA #* ( ‧ → · ) HYPHENATION POINT → MIDDLE DOT #
+2219 ; 00B7 ; MA #* ( ∙ → · ) BULLET OPERATOR → MIDDLE DOT #
+22C5 ; 00B7 ; MA #* ( ⋅ → · ) DOT OPERATOR → MIDDLE DOT #
+A78F ; 00B7 ; MA # ( ꞏ → · ) LATIN LETTER SINOLOGICAL DOT → MIDDLE DOT #
+1427 ; 00B7 ; MA # ( ᐧ → · ) CANADIAN SYLLABICS FINAL MIDDLE DOT → MIDDLE DOT #
+
+22EF ; 00B7 00B7 00B7 ; MA #* ( ⋯ → ··· ) MIDLINE HORIZONTAL ELLIPSIS → MIDDLE DOT, MIDDLE DOT, MIDDLE DOT #
+2D48 ; 00B7 00B7 00B7 ; MA # ( ⵈ → ··· ) TIFINAGH LETTER TUAREG YAQ → MIDDLE DOT, MIDDLE DOT, MIDDLE DOT # →⋯→
+
+1444 ; 00B7 003C ; MA # ( ᑄ → ·< ) CANADIAN SYLLABICS PWA → MIDDLE DOT, LESS-THAN SIGN # →ᐧᐸ→
+
+22D7 ; 00B7 003E ; MA #* ( ⋗ → ·> ) GREATER-THAN WITH DOT → MIDDLE DOT, GREATER-THAN SIGN # →ᑀ→→ᐧᐳ→
+1437 ; 00B7 003E ; MA # ( ᐷ → ·> ) CANADIAN SYLLABICS CARRIER HI → MIDDLE DOT, GREATER-THAN SIGN # →ᑀ→→ᐧᐳ→
+1440 ; 00B7 003E ; MA # ( ᑀ → ·> ) CANADIAN SYLLABICS PWO → MIDDLE DOT, GREATER-THAN SIGN # →ᐧᐳ→
+
+152F ; 00B7 0034 ; MA # ( ᔯ → ·4 ) CANADIAN SYLLABICS YWE → MIDDLE DOT, DIGIT FOUR # →ᐧ4→
+
+147E ; 00B7 0062 ; MA # ( ᑾ → ·b ) CANADIAN SYLLABICS KWA → MIDDLE DOT, LATIN SMALL LETTER B # →ᐧᑲ→
+
+1480 ; 00B7 0062 0307 ; MA # ( ᒀ → ·ḃ ) CANADIAN SYLLABICS KWAA → MIDDLE DOT, LATIN SMALL LETTER B, COMBINING DOT ABOVE # →ᐧᑳ→
+
+147A ; 00B7 0064 ; MA # ( ᑺ → ·d ) CANADIAN SYLLABICS KWO → MIDDLE DOT, LATIN SMALL LETTER D # →ᐧᑯ→
+
+1498 ; 00B7 004A ; MA # ( ᒘ → ·J ) CANADIAN SYLLABICS CWO → MIDDLE DOT, LATIN CAPITAL LETTER J # →ᐧᒍ→
+
+14B6 ; 00B7 004C ; MA # ( ᒶ → ·L ) CANADIAN SYLLABICS MWA → MIDDLE DOT, LATIN CAPITAL LETTER L # →ᐧL→
+
+1476 ; 00B7 0050 ; MA # ( ᑶ → ·P ) CANADIAN SYLLABICS KWI → MIDDLE DOT, LATIN CAPITAL LETTER P # →ᐧᑭ→
+
+1457 ; 00B7 0055 ; MA # ( ᑗ → ·U ) CANADIAN SYLLABICS TWE → MIDDLE DOT, LATIN CAPITAL LETTER U # →ᐧᑌ→→·ᑌ→
+
+143A ; 00B7 0056 ; MA # ( ᐺ → ·V ) CANADIAN SYLLABICS PWE → MIDDLE DOT, LATIN CAPITAL LETTER V # →ᐧᐯ→
+
+143C ; 00B7 0245 ; MA # ( ᐼ → ·Ʌ ) CANADIAN SYLLABICS PWI → MIDDLE DOT, LATIN CAPITAL LETTER TURNED V # →ᐧᐱ→→·ᐱ→
+
+14AE ; 00B7 0393 ; MA # ( ᒮ → ·Γ ) CANADIAN SYLLABICS MWI → MIDDLE DOT, GREEK CAPITAL LETTER GAMMA # →ᐧᒥ→→·ᒥ→
+
+140E ; 00B7 0394 ; MA # ( ᐎ → ·Δ ) CANADIAN SYLLABICS WI → MIDDLE DOT, GREEK CAPITAL LETTER DELTA # →ᐧᐃ→
+
+1459 ; 00B7 0548 ; MA # ( ᑙ → ·Ո ) CANADIAN SYLLABICS TWI → MIDDLE DOT, ARMENIAN CAPITAL LETTER VO # →ᐧᑎ→→·ᑎ→
+
+140C ; 00B7 1401 ; MA # ( ᐌ → ·ᐁ ) CANADIAN SYLLABICS WE → MIDDLE DOT, CANADIAN SYLLABICS E # →ᐧᐁ→
+
+1410 ; 00B7 1404 ; MA # ( ᐐ → ·ᐄ ) CANADIAN SYLLABICS WII → MIDDLE DOT, CANADIAN SYLLABICS II # →ᐧᐄ→
+
+1412 ; 00B7 1405 ; MA # ( ᐒ → ·ᐅ ) CANADIAN SYLLABICS WO → MIDDLE DOT, CANADIAN SYLLABICS O # →ᐧᐅ→
+
+1414 ; 00B7 1406 ; MA # ( ᐔ → ·ᐆ ) CANADIAN SYLLABICS WOO → MIDDLE DOT, CANADIAN SYLLABICS OO # →ᐧᐆ→
+
+1417 ; 00B7 140A ; MA # ( ᐗ → ·ᐊ ) CANADIAN SYLLABICS WA → MIDDLE DOT, CANADIAN SYLLABICS A # →ᐧᐊ→
+
+1419 ; 00B7 140B ; MA # ( ᐙ → ·ᐋ ) CANADIAN SYLLABICS WAA → MIDDLE DOT, CANADIAN SYLLABICS AA # →ᐧᐋ→
+
+143E ; 00B7 1432 ; MA # ( ᐾ → ·ᐲ ) CANADIAN SYLLABICS PWII → MIDDLE DOT, CANADIAN SYLLABICS PII # →ᐧᐲ→
+
+1442 ; 00B7 1434 ; MA # ( ᑂ → ·ᐴ ) CANADIAN SYLLABICS PWOO → MIDDLE DOT, CANADIAN SYLLABICS POO # →ᐧᐴ→
+
+1446 ; 00B7 1439 ; MA # ( ᑆ → ·ᐹ ) CANADIAN SYLLABICS PWAA → MIDDLE DOT, CANADIAN SYLLABICS PAA # →ᐧᐹ→
+
+145B ; 00B7 144F ; MA # ( ᑛ → ·ᑏ ) CANADIAN SYLLABICS TWII → MIDDLE DOT, CANADIAN SYLLABICS TII # →ᐧᑏ→
+
+1454 ; 00B7 1450 ; MA # ( ᑔ → ·ᑐ ) CANADIAN SYLLABICS CARRIER DI → MIDDLE DOT, CANADIAN SYLLABICS TO # →ᑝ→→ᐧᑐ→
+145D ; 00B7 1450 ; MA # ( ᑝ → ·ᑐ ) CANADIAN SYLLABICS TWO → MIDDLE DOT, CANADIAN SYLLABICS TO # →ᐧᑐ→
+
+145F ; 00B7 1451 ; MA # ( ᑟ → ·ᑑ ) CANADIAN SYLLABICS TWOO → MIDDLE DOT, CANADIAN SYLLABICS TOO # →ᐧᑑ→
+
+1461 ; 00B7 1455 ; MA # ( ᑡ → ·ᑕ ) CANADIAN SYLLABICS TWA → MIDDLE DOT, CANADIAN SYLLABICS TA # →ᐧᑕ→
+
+1463 ; 00B7 1456 ; MA # ( ᑣ → ·ᑖ ) CANADIAN SYLLABICS TWAA → MIDDLE DOT, CANADIAN SYLLABICS TAA # →ᐧᑖ→
+
+1474 ; 00B7 146B ; MA # ( ᑴ → ·ᑫ ) CANADIAN SYLLABICS KWE → MIDDLE DOT, CANADIAN SYLLABICS KE # →ᐧᑫ→
+
+1478 ; 00B7 146E ; MA # ( ᑸ → ·ᑮ ) CANADIAN SYLLABICS KWII → MIDDLE DOT, CANADIAN SYLLABICS KII # →ᐧᑮ→
+
+147C ; 00B7 1470 ; MA # ( ᑼ → ·ᑰ ) CANADIAN SYLLABICS KWOO → MIDDLE DOT, CANADIAN SYLLABICS KOO # →ᐧᑰ→
+
+1492 ; 00B7 1489 ; MA # ( ᒒ → ·ᒉ ) CANADIAN SYLLABICS CWE → MIDDLE DOT, CANADIAN SYLLABICS CE # →ᐧᒉ→
+
+1494 ; 00B7 148B ; MA # ( ᒔ → ·ᒋ ) CANADIAN SYLLABICS CWI → MIDDLE DOT, CANADIAN SYLLABICS CI # →ᐧᒋ→
+
+1496 ; 00B7 148C ; MA # ( ᒖ → ·ᒌ ) CANADIAN SYLLABICS CWII → MIDDLE DOT, CANADIAN SYLLABICS CII # →ᐧᒌ→
+
+149A ; 00B7 148E ; MA # ( ᒚ → ·ᒎ ) CANADIAN SYLLABICS CWOO → MIDDLE DOT, CANADIAN SYLLABICS COO # →ᐧᒎ→
+
+149C ; 00B7 1490 ; MA # ( ᒜ → ·ᒐ ) CANADIAN SYLLABICS CWA → MIDDLE DOT, CANADIAN SYLLABICS CA # →ᐧᒐ→
+
+149E ; 00B7 1491 ; MA # ( ᒞ → ·ᒑ ) CANADIAN SYLLABICS CWAA → MIDDLE DOT, CANADIAN SYLLABICS CAA # →ᐧᒑ→
+
+14AC ; 00B7 14A3 ; MA # ( ᒬ → ·ᒣ ) CANADIAN SYLLABICS MWE → MIDDLE DOT, CANADIAN SYLLABICS ME # →ᐧᒣ→
+
+14B0 ; 00B7 14A6 ; MA # ( ᒰ → ·ᒦ ) CANADIAN SYLLABICS MWII → MIDDLE DOT, CANADIAN SYLLABICS MII # →ᐧᒦ→
+
+14B2 ; 00B7 14A7 ; MA # ( ᒲ → ·ᒧ ) CANADIAN SYLLABICS MWO → MIDDLE DOT, CANADIAN SYLLABICS MO # →ᐧᒧ→
+
+14B4 ; 00B7 14A8 ; MA # ( ᒴ → ·ᒨ ) CANADIAN SYLLABICS MWOO → MIDDLE DOT, CANADIAN SYLLABICS MOO # →ᐧᒨ→
+
+14B8 ; 00B7 14AB ; MA # ( ᒸ → ·ᒫ ) CANADIAN SYLLABICS MWAA → MIDDLE DOT, CANADIAN SYLLABICS MAA # →ᐧᒫ→
+
+14C9 ; 00B7 14C0 ; MA # ( ᓉ → ·ᓀ ) CANADIAN SYLLABICS NWE → MIDDLE DOT, CANADIAN SYLLABICS NE # →ᐧᓀ→
+
+18C6 ; 00B7 14C2 ; MA # ( ᣆ → ·ᓂ ) CANADIAN SYLLABICS NWI → MIDDLE DOT, CANADIAN SYLLABICS NI # →ᐧᓂ→
+
+18C8 ; 00B7 14C3 ; MA # ( ᣈ → ·ᓃ ) CANADIAN SYLLABICS NWII → MIDDLE DOT, CANADIAN SYLLABICS NII # →ᐧᓃ→
+
+18CA ; 00B7 14C4 ; MA # ( ᣊ → ·ᓄ ) CANADIAN SYLLABICS NWO → MIDDLE DOT, CANADIAN SYLLABICS NO # →ᐧᓄ→
+
+18CC ; 00B7 14C5 ; MA # ( ᣌ → ·ᓅ ) CANADIAN SYLLABICS NWOO → MIDDLE DOT, CANADIAN SYLLABICS NOO # →ᐧᓅ→
+
+14CB ; 00B7 14C7 ; MA # ( ᓋ → ·ᓇ ) CANADIAN SYLLABICS NWA → MIDDLE DOT, CANADIAN SYLLABICS NA # →ᐧᓇ→
+
+14CD ; 00B7 14C8 ; MA # ( ᓍ → ·ᓈ ) CANADIAN SYLLABICS NWAA → MIDDLE DOT, CANADIAN SYLLABICS NAA # →ᐧᓈ→
+
+14DC ; 00B7 14D3 ; MA # ( ᓜ → ·ᓓ ) CANADIAN SYLLABICS LWE → MIDDLE DOT, CANADIAN SYLLABICS LE # →ᐧᓓ→
+
+14DE ; 00B7 14D5 ; MA # ( ᓞ → ·ᓕ ) CANADIAN SYLLABICS LWI → MIDDLE DOT, CANADIAN SYLLABICS LI # →ᐧᓕ→
+
+14E0 ; 00B7 14D6 ; MA # ( ᓠ → ·ᓖ ) CANADIAN SYLLABICS LWII → MIDDLE DOT, CANADIAN SYLLABICS LII # →ᐧᓖ→
+
+14E2 ; 00B7 14D7 ; MA # ( ᓢ → ·ᓗ ) CANADIAN SYLLABICS LWO → MIDDLE DOT, CANADIAN SYLLABICS LO # →ᐧᓗ→
+
+14E4 ; 00B7 14D8 ; MA # ( ᓤ → ·ᓘ ) CANADIAN SYLLABICS LWOO → MIDDLE DOT, CANADIAN SYLLABICS LOO # →ᐧᓘ→
+
+14E6 ; 00B7 14DA ; MA # ( ᓦ → ·ᓚ ) CANADIAN SYLLABICS LWA → MIDDLE DOT, CANADIAN SYLLABICS LA # →ᐧᓚ→
+
+14E8 ; 00B7 14DB ; MA # ( ᓨ → ·ᓛ ) CANADIAN SYLLABICS LWAA → MIDDLE DOT, CANADIAN SYLLABICS LAA # →ᐧᓛ→
+
+14F6 ; 00B7 14ED ; MA # ( ᓶ → ·ᓭ ) CANADIAN SYLLABICS SWE → MIDDLE DOT, CANADIAN SYLLABICS SE # →ᐧᓭ→
+
+14F8 ; 00B7 14EF ; MA # ( ᓸ → ·ᓯ ) CANADIAN SYLLABICS SWI → MIDDLE DOT, CANADIAN SYLLABICS SI # →ᐧᓯ→
+
+14FA ; 00B7 14F0 ; MA # ( ᓺ → ·ᓰ ) CANADIAN SYLLABICS SWII → MIDDLE DOT, CANADIAN SYLLABICS SII # →ᐧᓰ→
+
+14FC ; 00B7 14F1 ; MA # ( ᓼ → ·ᓱ ) CANADIAN SYLLABICS SWO → MIDDLE DOT, CANADIAN SYLLABICS SO # →ᐧᓱ→
+
+14FE ; 00B7 14F2 ; MA # ( ᓾ → ·ᓲ ) CANADIAN SYLLABICS SWOO → MIDDLE DOT, CANADIAN SYLLABICS SOO # →ᐧᓲ→
+
+1500 ; 00B7 14F4 ; MA # ( ᔀ → ·ᓴ ) CANADIAN SYLLABICS SWA → MIDDLE DOT, CANADIAN SYLLABICS SA # →ᐧᓴ→
+
+1502 ; 00B7 14F5 ; MA # ( ᔂ → ·ᓵ ) CANADIAN SYLLABICS SWAA → MIDDLE DOT, CANADIAN SYLLABICS SAA # →ᐧᓵ→
+
+1517 ; 00B7 1510 ; MA # ( ᔗ → ·ᔐ ) CANADIAN SYLLABICS SHWE → MIDDLE DOT, CANADIAN SYLLABICS SHE # →ᐧᔐ→
+
+1519 ; 00B7 1511 ; MA # ( ᔙ → ·ᔑ ) CANADIAN SYLLABICS SHWI → MIDDLE DOT, CANADIAN SYLLABICS SHI # →ᐧᔑ→
+
+151B ; 00B7 1512 ; MA # ( ᔛ → ·ᔒ ) CANADIAN SYLLABICS SHWII → MIDDLE DOT, CANADIAN SYLLABICS SHII # →ᐧᔒ→
+
+151D ; 00B7 1513 ; MA # ( ᔝ → ·ᔓ ) CANADIAN SYLLABICS SHWO → MIDDLE DOT, CANADIAN SYLLABICS SHO # →ᐧᔓ→
+
+151F ; 00B7 1514 ; MA # ( ᔟ → ·ᔔ ) CANADIAN SYLLABICS SHWOO → MIDDLE DOT, CANADIAN SYLLABICS SHOO # →ᐧᔔ→
+
+1521 ; 00B7 1515 ; MA # ( ᔡ → ·ᔕ ) CANADIAN SYLLABICS SHWA → MIDDLE DOT, CANADIAN SYLLABICS SHA # →ᐧᔕ→
+
+1523 ; 00B7 1516 ; MA # ( ᔣ → ·ᔖ ) CANADIAN SYLLABICS SHWAA → MIDDLE DOT, CANADIAN SYLLABICS SHAA # →ᐧᔖ→
+
+1531 ; 00B7 1528 ; MA # ( ᔱ → ·ᔨ ) CANADIAN SYLLABICS YWI → MIDDLE DOT, CANADIAN SYLLABICS YI # →ᐧᔨ→
+
+1533 ; 00B7 1529 ; MA # ( ᔳ → ·ᔩ ) CANADIAN SYLLABICS YWII → MIDDLE DOT, CANADIAN SYLLABICS YII # →ᐧᔩ→
+
+1535 ; 00B7 152A ; MA # ( ᔵ → ·ᔪ ) CANADIAN SYLLABICS YWO → MIDDLE DOT, CANADIAN SYLLABICS YO # →ᐧᔪ→
+
+1537 ; 00B7 152B ; MA # ( ᔷ → ·ᔫ ) CANADIAN SYLLABICS YWOO → MIDDLE DOT, CANADIAN SYLLABICS YOO # →ᐧᔫ→
+
+1539 ; 00B7 152D ; MA # ( ᔹ → ·ᔭ ) CANADIAN SYLLABICS YWA → MIDDLE DOT, CANADIAN SYLLABICS YA # →ᐧᔭ→
+
+153B ; 00B7 152E ; MA # ( ᔻ → ·ᔮ ) CANADIAN SYLLABICS YWAA → MIDDLE DOT, CANADIAN SYLLABICS YAA # →ᐧᔮ→
+
+18CE ; 00B7 1543 ; MA # ( ᣎ → ·ᕃ ) CANADIAN SYLLABICS RWEE → MIDDLE DOT, CANADIAN SYLLABICS R-CREE RE # →ᐧᕃ→
+
+18CF ; 00B7 1546 ; MA # ( ᣏ → ·ᕆ ) CANADIAN SYLLABICS RWI → MIDDLE DOT, CANADIAN SYLLABICS RI # →ᐧᕆ→
+
+18D0 ; 00B7 1547 ; MA # ( ᣐ → ·ᕇ ) CANADIAN SYLLABICS RWII → MIDDLE DOT, CANADIAN SYLLABICS RII # →ᐧᕇ→
+
+18D1 ; 00B7 1548 ; MA # ( ᣑ → ·ᕈ ) CANADIAN SYLLABICS RWO → MIDDLE DOT, CANADIAN SYLLABICS RO # →ᐧᕈ→
+
+18D2 ; 00B7 1549 ; MA # ( ᣒ → ·ᕉ ) CANADIAN SYLLABICS RWOO → MIDDLE DOT, CANADIAN SYLLABICS ROO # →ᐧᕉ→
+
+18D3 ; 00B7 154B ; MA # ( ᣓ → ·ᕋ ) CANADIAN SYLLABICS RWA → MIDDLE DOT, CANADIAN SYLLABICS RA # →ᐧᕋ→
+
+154E ; 00B7 154C ; MA # ( ᕎ → ·ᕌ ) CANADIAN SYLLABICS RWAA → MIDDLE DOT, CANADIAN SYLLABICS RAA # →ᐧᕌ→
+
+155B ; 00B7 155A ; MA # ( ᕛ → ·ᕚ ) CANADIAN SYLLABICS FWAA → MIDDLE DOT, CANADIAN SYLLABICS FAA # →ᐧᕚ→
+
+1568 ; 00B7 1567 ; MA # ( ᕨ → ·ᕧ ) CANADIAN SYLLABICS THWAA → MIDDLE DOT, CANADIAN SYLLABICS THAA # →ᐧᕧ→
+
+18B3 ; 00B7 18B1 ; MA # ( ᢳ → ·ᢱ ) CANADIAN SYLLABICS WAY → MIDDLE DOT, CANADIAN SYLLABICS AY # →ᐧᢱ→
+
+18B6 ; 00B7 18B4 ; MA # ( ᢶ → ·ᢴ ) CANADIAN SYLLABICS PWOY → MIDDLE DOT, CANADIAN SYLLABICS POY # →ᐧᢴ→
+
+18B9 ; 00B7 18B8 ; MA # ( ᢹ → ·ᢸ ) CANADIAN SYLLABICS KWAY → MIDDLE DOT, CANADIAN SYLLABICS KAY # →ᐧᢸ→
+
+18C2 ; 00B7 18C0 ; MA # ( ᣂ → ·ᣀ ) CANADIAN SYLLABICS SHWOY → MIDDLE DOT, CANADIAN SYLLABICS SHOY # →ᐧᣀ→
+
+A830 ; 0964 ; MA #* ( ꠰ → । ) NORTH INDIC FRACTION ONE QUARTER → DEVANAGARI DANDA #
+
+0965 ; 0964 0964 ; MA #* ( ॥ → ।। ) DEVANAGARI DOUBLE DANDA → DEVANAGARI DANDA, DEVANAGARI DANDA #
+
+1C3C ; 1C3B 1C3B ; MA #* ( ᰼ → ᰻᰻ ) LEPCHA PUNCTUATION NYET THYOOM TA-ROL → LEPCHA PUNCTUATION TA-ROL, LEPCHA PUNCTUATION TA-ROL #
+
+104B ; 104A 104A ; MA #* ( ။ → ၊၊ ) MYANMAR SIGN SECTION → MYANMAR SIGN LITTLE SECTION, MYANMAR SIGN LITTLE SECTION #
+
+1AA9 ; 1AA8 1AA8 ; MA #* ( ᪩ → ᪨᪨ ) TAI THAM SIGN KAANKUU → TAI THAM SIGN KAAN, TAI THAM SIGN KAAN #
+
+1AAB ; 1AAA 1AA8 ; MA #* ( ᪫ → ᪪᪨ ) TAI THAM SIGN SATKAANKUU → TAI THAM SIGN SATKAAN, TAI THAM SIGN KAAN #
+
+1B5F ; 1B5E 1B5E ; MA #* ( ᭟ → ᭞᭞ ) BALINESE CARIK PAREREN → BALINESE CARIK SIKI, BALINESE CARIK SIKI #
+
+10A57 ; 10A56 10A56 ; MA #* ( ‎𐩗‎ → ‎𐩖𐩖‎ ) KHAROSHTHI PUNCTUATION DOUBLE DANDA → KHAROSHTHI PUNCTUATION DANDA, KHAROSHTHI PUNCTUATION DANDA #
+
+1144C ; 1144B 1144B ; MA #* ( 𑑌 → 𑑋𑑋 ) NEWA DOUBLE DANDA → NEWA DANDA, NEWA DANDA #
+
+11642 ; 11641 11641 ; MA #* ( 𑙂 → 𑙁𑙁 ) MODI DOUBLE DANDA → MODI DANDA, MODI DANDA #
+
+11C42 ; 11C41 11C41 ; MA #* ( 𑱂 → 𑱁𑱁 ) BHAIKSUKI DOUBLE DANDA → BHAIKSUKI DANDA, BHAIKSUKI DANDA #
+
+1C7F ; 1C7E 1C7E ; MA #* ( ᱿ → ᱾᱾ ) OL CHIKI PUNCTUATION DOUBLE MUCAAD → OL CHIKI PUNCTUATION MUCAAD, OL CHIKI PUNCTUATION MUCAAD #
+
+055D ; 0027 ; MA #* ( ՝ → ' ) ARMENIAN COMMA → APOSTROPHE # →ˋ→→`→→‘→
+FF07 ; 0027 ; MA #* ( ' → ' ) FULLWIDTH APOSTROPHE → APOSTROPHE # →’→
+2018 ; 0027 ; MA #* ( ‘ → ' ) LEFT SINGLE QUOTATION MARK → APOSTROPHE #
+2019 ; 0027 ; MA #* ( ’ → ' ) RIGHT SINGLE QUOTATION MARK → APOSTROPHE #
+201B ; 0027 ; MA #* ( ‛ → ' ) SINGLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE # →′→
+2032 ; 0027 ; MA #* ( ′ → ' ) PRIME → APOSTROPHE #
+2035 ; 0027 ; MA #* ( ‵ → ' ) REVERSED PRIME → APOSTROPHE # →ʽ→→‘→
+055A ; 0027 ; MA #* ( ՚ → ' ) ARMENIAN APOSTROPHE → APOSTROPHE # →’→
+05F3 ; 0027 ; MA #* ( ‎׳‎ → ' ) HEBREW PUNCTUATION GERESH → APOSTROPHE #
+0060 ; 0027 ; MA #* ( ` → ' ) GRAVE ACCENT → APOSTROPHE # →ˋ→→`→→‘→
+1FEF ; 0027 ; MA #* ( ` → ' ) GREEK VARIA → APOSTROPHE # →ˋ→→`→→‘→
+FF40 ; 0027 ; MA #* ( ` → ' ) FULLWIDTH GRAVE ACCENT → APOSTROPHE # →‘→
+00B4 ; 0027 ; MA #* ( ´ → ' ) ACUTE ACCENT → APOSTROPHE # →΄→→ʹ→
+0384 ; 0027 ; MA #* ( ΄ → ' ) GREEK TONOS → APOSTROPHE # →ʹ→
+1FFD ; 0027 ; MA #* ( ´ → ' ) GREEK OXIA → APOSTROPHE # →´→→΄→→ʹ→
+1FBD ; 0027 ; MA #* ( ᾽ → ' ) GREEK KORONIS → APOSTROPHE # →’→
+1FBF ; 0027 ; MA #* ( ᾿ → ' ) GREEK PSILI → APOSTROPHE # →’→
+1FFE ; 0027 ; MA #* ( ῾ → ' ) GREEK DASIA → APOSTROPHE # →‛→→′→
+02B9 ; 0027 ; MA # ( ʹ → ' ) MODIFIER LETTER PRIME → APOSTROPHE #
+0374 ; 0027 ; MA # ( ʹ → ' ) GREEK NUMERAL SIGN → APOSTROPHE # →′→
+02C8 ; 0027 ; MA # ( ˈ → ' ) MODIFIER LETTER VERTICAL LINE → APOSTROPHE #
+02CA ; 0027 ; MA # ( ˊ → ' ) MODIFIER LETTER ACUTE ACCENT → APOSTROPHE # →ʹ→→′→
+02CB ; 0027 ; MA # ( ˋ → ' ) MODIFIER LETTER GRAVE ACCENT → APOSTROPHE # →`→→‘→
+02F4 ; 0027 ; MA #* ( ˴ → ' ) MODIFIER LETTER MIDDLE GRAVE ACCENT → APOSTROPHE # →ˋ→→`→→‘→
+02BB ; 0027 ; MA # ( ʻ → ' ) MODIFIER LETTER TURNED COMMA → APOSTROPHE # →‘→
+02BD ; 0027 ; MA # ( ʽ → ' ) MODIFIER LETTER REVERSED COMMA → APOSTROPHE # →‘→
+02BC ; 0027 ; MA # ( ʼ → ' ) MODIFIER LETTER APOSTROPHE → APOSTROPHE # →′→
+02BE ; 0027 ; MA # ( ʾ → ' ) MODIFIER LETTER RIGHT HALF RING → APOSTROPHE # →ʼ→→′→
+A78C ; 0027 ; MA # ( ꞌ → ' ) LATIN SMALL LETTER SALTILLO → APOSTROPHE #
+05D9 ; 0027 ; MA # ( ‎י‎ → ' ) HEBREW LETTER YOD → APOSTROPHE #
+07F4 ; 0027 ; MA # ( ‎ߴ‎ → ' ) NKO HIGH TONE APOSTROPHE → APOSTROPHE # →’→
+07F5 ; 0027 ; MA # ( ‎ߵ‎ → ' ) NKO LOW TONE APOSTROPHE → APOSTROPHE # →‘→
+144A ; 0027 ; MA # ( ᑊ → ' ) CANADIAN SYLLABICS WEST-CREE P → APOSTROPHE # →ˈ→
+16CC ; 0027 ; MA # ( ᛌ → ' ) RUNIC LETTER SHORT-TWIG-SOL S → APOSTROPHE #
+16F51 ; 0027 ; MA # ( 𖽑 → ' ) MIAO SIGN ASPIRATION → APOSTROPHE # →ʼ→→′→
+16F52 ; 0027 ; MA # ( 𖽒 → ' ) MIAO SIGN REFORMED VOICING → APOSTROPHE # →ʻ→→‘→
+
+1CD3 ; 0027 0027 ; MA #* ( ᳓ → '' ) VEDIC SIGN NIHSHVASA → APOSTROPHE, APOSTROPHE # →″→→"→
+0022 ; 0027 0027 ; MA #* ( " → '' ) QUOTATION MARK → APOSTROPHE, APOSTROPHE #
+FF02 ; 0027 0027 ; MA #* ( " → '' ) FULLWIDTH QUOTATION MARK → APOSTROPHE, APOSTROPHE # →”→→"→
+201C ; 0027 0027 ; MA #* ( “ → '' ) LEFT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE # →"→
+201D ; 0027 0027 ; MA #* ( ” → '' ) RIGHT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE # →"→
+201F ; 0027 0027 ; MA #* ( ‟ → '' ) DOUBLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE, APOSTROPHE # →“→→"→
+2033 ; 0027 0027 ; MA #* ( ″ → '' ) DOUBLE PRIME → APOSTROPHE, APOSTROPHE # →"→
+2036 ; 0027 0027 ; MA #* ( ‶ → '' ) REVERSED DOUBLE PRIME → APOSTROPHE, APOSTROPHE # →‵‵→
+3003 ; 0027 0027 ; MA #* ( 〃 → '' ) DITTO MARK → APOSTROPHE, APOSTROPHE # →″→→"→
+05F4 ; 0027 0027 ; MA #* ( ‎״‎ → '' ) HEBREW PUNCTUATION GERSHAYIM → APOSTROPHE, APOSTROPHE # →"→
+02DD ; 0027 0027 ; MA #* ( ˝ → '' ) DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE # →"→
+02BA ; 0027 0027 ; MA # ( ʺ → '' ) MODIFIER LETTER DOUBLE PRIME → APOSTROPHE, APOSTROPHE # →"→
+02F6 ; 0027 0027 ; MA #* ( ˶ → '' ) MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE # →˝→→"→
+02EE ; 0027 0027 ; MA # ( ˮ → '' ) MODIFIER LETTER DOUBLE APOSTROPHE → APOSTROPHE, APOSTROPHE # →″→→"→
+05F2 ; 0027 0027 ; MA # ( ‎ײ‎ → '' ) HEBREW LIGATURE YIDDISH DOUBLE YOD → APOSTROPHE, APOSTROPHE # →‎יי‎→
+
+2034 ; 0027 0027 0027 ; MA #* ( ‴ → ''' ) TRIPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE # →′′′→
+2037 ; 0027 0027 0027 ; MA #* ( ‷ → ''' ) REVERSED TRIPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE # →‵‵‵→
+
+2057 ; 0027 0027 0027 0027 ; MA #* ( ⁗ → '''' ) QUADRUPLE PRIME → APOSTROPHE, APOSTROPHE, APOSTROPHE, APOSTROPHE # →′′′′→
+
+0181 ; 0027 0042 ; MA # ( Ɓ → 'B ) LATIN CAPITAL LETTER B WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER B # →ʽB→
+
+018A ; 0027 0044 ; MA # ( Ɗ → 'D ) LATIN CAPITAL LETTER D WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER D # →ʽD→
+
+0149 ; 0027 006E ; MA # ( ʼn → 'n ) LATIN SMALL LETTER N PRECEDED BY APOSTROPHE → APOSTROPHE, LATIN SMALL LETTER N # →ʼn→
+
+01A4 ; 0027 0050 ; MA # ( Ƥ → 'P ) LATIN CAPITAL LETTER P WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER P # →ʽP→
+
+01AC ; 0027 0054 ; MA # ( Ƭ → 'T ) LATIN CAPITAL LETTER T WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER T # →ʽT→
+
+01B3 ; 0027 0059 ; MA # ( Ƴ → 'Y ) LATIN CAPITAL LETTER Y WITH HOOK → APOSTROPHE, LATIN CAPITAL LETTER Y # →ʽY→
+
+FF3B ; 0028 ; MA #* ( [ → ( ) FULLWIDTH LEFT SQUARE BRACKET → LEFT PARENTHESIS # →〔→
+2768 ; 0028 ; MA #* ( ❨ → ( ) MEDIUM LEFT PARENTHESIS ORNAMENT → LEFT PARENTHESIS #
+2772 ; 0028 ; MA #* ( ❲ → ( ) LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT → LEFT PARENTHESIS # →〔→
+3014 ; 0028 ; MA #* ( 〔 → ( ) LEFT TORTOISE SHELL BRACKET → LEFT PARENTHESIS #
+FD3E ; 0028 ; MA #* ( ﴾ → ( ) ORNATE LEFT PARENTHESIS → LEFT PARENTHESIS #
+
+2E28 ; 0028 0028 ; MA #* ( ⸨ → (( ) LEFT DOUBLE PARENTHESIS → LEFT PARENTHESIS, LEFT PARENTHESIS #
+
+3220 ; 0028 30FC 0029 ; MA #* ( ㈠ → (ー) ) PARENTHESIZED IDEOGRAPH ONE → LEFT PARENTHESIS, KATAKANA-HIRAGANA PROLONGED SOUND MARK, RIGHT PARENTHESIS # →(一)→
+
+2475 ; 0028 0032 0029 ; MA #* ( ⑵ → (2) ) PARENTHESIZED DIGIT TWO → LEFT PARENTHESIS, DIGIT TWO, RIGHT PARENTHESIS #
+
+2487 ; 0028 0032 004F 0029 ; MA #* ( ⒇ → (2O) ) PARENTHESIZED NUMBER TWENTY → LEFT PARENTHESIS, DIGIT TWO, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS # →(20)→
+
+2476 ; 0028 0033 0029 ; MA #* ( ⑶ → (3) ) PARENTHESIZED DIGIT THREE → LEFT PARENTHESIS, DIGIT THREE, RIGHT PARENTHESIS #
+
+2477 ; 0028 0034 0029 ; MA #* ( ⑷ → (4) ) PARENTHESIZED DIGIT FOUR → LEFT PARENTHESIS, DIGIT FOUR, RIGHT PARENTHESIS #
+
+2478 ; 0028 0035 0029 ; MA #* ( ⑸ → (5) ) PARENTHESIZED DIGIT FIVE → LEFT PARENTHESIS, DIGIT FIVE, RIGHT PARENTHESIS #
+
+2479 ; 0028 0036 0029 ; MA #* ( ⑹ → (6) ) PARENTHESIZED DIGIT SIX → LEFT PARENTHESIS, DIGIT SIX, RIGHT PARENTHESIS #
+
+247A ; 0028 0037 0029 ; MA #* ( ⑺ → (7) ) PARENTHESIZED DIGIT SEVEN → LEFT PARENTHESIS, DIGIT SEVEN, RIGHT PARENTHESIS #
+
+247B ; 0028 0038 0029 ; MA #* ( ⑻ → (8) ) PARENTHESIZED DIGIT EIGHT → LEFT PARENTHESIS, DIGIT EIGHT, RIGHT PARENTHESIS #
+
+247C ; 0028 0039 0029 ; MA #* ( ⑼ → (9) ) PARENTHESIZED DIGIT NINE → LEFT PARENTHESIS, DIGIT NINE, RIGHT PARENTHESIS #
+
+249C ; 0028 0061 0029 ; MA #* ( ⒜ → (a) ) PARENTHESIZED LATIN SMALL LETTER A → LEFT PARENTHESIS, LATIN SMALL LETTER A, RIGHT PARENTHESIS #
+
+1F110 ; 0028 0041 0029 ; MA #* ( 🄐 → (A) ) PARENTHESIZED LATIN CAPITAL LETTER A → LEFT PARENTHESIS, LATIN CAPITAL LETTER A, RIGHT PARENTHESIS #
+
+249D ; 0028 0062 0029 ; MA #* ( ⒝ → (b) ) PARENTHESIZED LATIN SMALL LETTER B → LEFT PARENTHESIS, LATIN SMALL LETTER B, RIGHT PARENTHESIS #
+
+1F111 ; 0028 0042 0029 ; MA #* ( 🄑 → (B) ) PARENTHESIZED LATIN CAPITAL LETTER B → LEFT PARENTHESIS, LATIN CAPITAL LETTER B, RIGHT PARENTHESIS #
+
+249E ; 0028 0063 0029 ; MA #* ( ⒞ → (c) ) PARENTHESIZED LATIN SMALL LETTER C → LEFT PARENTHESIS, LATIN SMALL LETTER C, RIGHT PARENTHESIS #
+
+1F112 ; 0028 0043 0029 ; MA #* ( 🄒 → (C) ) PARENTHESIZED LATIN CAPITAL LETTER C → LEFT PARENTHESIS, LATIN CAPITAL LETTER C, RIGHT PARENTHESIS #
+
+249F ; 0028 0064 0029 ; MA #* ( ⒟ → (d) ) PARENTHESIZED LATIN SMALL LETTER D → LEFT PARENTHESIS, LATIN SMALL LETTER D, RIGHT PARENTHESIS #
+
+1F113 ; 0028 0044 0029 ; MA #* ( 🄓 → (D) ) PARENTHESIZED LATIN CAPITAL LETTER D → LEFT PARENTHESIS, LATIN CAPITAL LETTER D, RIGHT PARENTHESIS #
+
+24A0 ; 0028 0065 0029 ; MA #* ( ⒠ → (e) ) PARENTHESIZED LATIN SMALL LETTER E → LEFT PARENTHESIS, LATIN SMALL LETTER E, RIGHT PARENTHESIS #
+
+1F114 ; 0028 0045 0029 ; MA #* ( 🄔 → (E) ) PARENTHESIZED LATIN CAPITAL LETTER E → LEFT PARENTHESIS, LATIN CAPITAL LETTER E, RIGHT PARENTHESIS #
+
+24A1 ; 0028 0066 0029 ; MA #* ( ⒡ → (f) ) PARENTHESIZED LATIN SMALL LETTER F → LEFT PARENTHESIS, LATIN SMALL LETTER F, RIGHT PARENTHESIS #
+
+1F115 ; 0028 0046 0029 ; MA #* ( 🄕 → (F) ) PARENTHESIZED LATIN CAPITAL LETTER F → LEFT PARENTHESIS, LATIN CAPITAL LETTER F, RIGHT PARENTHESIS #
+
+24A2 ; 0028 0067 0029 ; MA #* ( ⒢ → (g) ) PARENTHESIZED LATIN SMALL LETTER G → LEFT PARENTHESIS, LATIN SMALL LETTER G, RIGHT PARENTHESIS #
+
+1F116 ; 0028 0047 0029 ; MA #* ( 🄖 → (G) ) PARENTHESIZED LATIN CAPITAL LETTER G → LEFT PARENTHESIS, LATIN CAPITAL LETTER G, RIGHT PARENTHESIS #
+
+24A3 ; 0028 0068 0029 ; MA #* ( ⒣ → (h) ) PARENTHESIZED LATIN SMALL LETTER H → LEFT PARENTHESIS, LATIN SMALL LETTER H, RIGHT PARENTHESIS #
+
+1F117 ; 0028 0048 0029 ; MA #* ( 🄗 → (H) ) PARENTHESIZED LATIN CAPITAL LETTER H → LEFT PARENTHESIS, LATIN CAPITAL LETTER H, RIGHT PARENTHESIS #
+
+24A4 ; 0028 0069 0029 ; MA #* ( ⒤ → (i) ) PARENTHESIZED LATIN SMALL LETTER I → LEFT PARENTHESIS, LATIN SMALL LETTER I, RIGHT PARENTHESIS #
+
+24A5 ; 0028 006A 0029 ; MA #* ( ⒥ → (j) ) PARENTHESIZED LATIN SMALL LETTER J → LEFT PARENTHESIS, LATIN SMALL LETTER J, RIGHT PARENTHESIS #
+
+1F119 ; 0028 004A 0029 ; MA #* ( 🄙 → (J) ) PARENTHESIZED LATIN CAPITAL LETTER J → LEFT PARENTHESIS, LATIN CAPITAL LETTER J, RIGHT PARENTHESIS #
+
+24A6 ; 0028 006B 0029 ; MA #* ( ⒦ → (k) ) PARENTHESIZED LATIN SMALL LETTER K → LEFT PARENTHESIS, LATIN SMALL LETTER K, RIGHT PARENTHESIS #
+
+1F11A ; 0028 004B 0029 ; MA #* ( 🄚 → (K) ) PARENTHESIZED LATIN CAPITAL LETTER K → LEFT PARENTHESIS, LATIN CAPITAL LETTER K, RIGHT PARENTHESIS #
+
+2474 ; 0028 006C 0029 ; MA #* ( ⑴ → (l) ) PARENTHESIZED DIGIT ONE → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS # →(1)→
+1F118 ; 0028 006C 0029 ; MA #* ( 🄘 → (l) ) PARENTHESIZED LATIN CAPITAL LETTER I → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS # →(I)→
+24A7 ; 0028 006C 0029 ; MA #* ( ⒧ → (l) ) PARENTHESIZED LATIN SMALL LETTER L → LEFT PARENTHESIS, LATIN SMALL LETTER L, RIGHT PARENTHESIS #
+
+1F11B ; 0028 004C 0029 ; MA #* ( 🄛 → (L) ) PARENTHESIZED LATIN CAPITAL LETTER L → LEFT PARENTHESIS, LATIN CAPITAL LETTER L, RIGHT PARENTHESIS #
+
+247F ; 0028 006C 0032 0029 ; MA #* ( ⑿ → (l2) ) PARENTHESIZED NUMBER TWELVE → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT TWO, RIGHT PARENTHESIS # →(12)→
+
+2480 ; 0028 006C 0033 0029 ; MA #* ( ⒀ → (l3) ) PARENTHESIZED NUMBER THIRTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT THREE, RIGHT PARENTHESIS # →(13)→
+
+2481 ; 0028 006C 0034 0029 ; MA #* ( ⒁ → (l4) ) PARENTHESIZED NUMBER FOURTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT FOUR, RIGHT PARENTHESIS # →(14)→
+
+2482 ; 0028 006C 0035 0029 ; MA #* ( ⒂ → (l5) ) PARENTHESIZED NUMBER FIFTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT FIVE, RIGHT PARENTHESIS # →(15)→
+
+2483 ; 0028 006C 0036 0029 ; MA #* ( ⒃ → (l6) ) PARENTHESIZED NUMBER SIXTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT SIX, RIGHT PARENTHESIS # →(16)→
+
+2484 ; 0028 006C 0037 0029 ; MA #* ( ⒄ → (l7) ) PARENTHESIZED NUMBER SEVENTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT SEVEN, RIGHT PARENTHESIS # →(17)→
+
+2485 ; 0028 006C 0038 0029 ; MA #* ( ⒅ → (l8) ) PARENTHESIZED NUMBER EIGHTEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT EIGHT, RIGHT PARENTHESIS # →(18)→
+
+2486 ; 0028 006C 0039 0029 ; MA #* ( ⒆ → (l9) ) PARENTHESIZED NUMBER NINETEEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, DIGIT NINE, RIGHT PARENTHESIS # →(19)→
+
+247E ; 0028 006C 006C 0029 ; MA #* ( ⑾ → (ll) ) PARENTHESIZED NUMBER ELEVEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, LATIN SMALL LETTER L, RIGHT PARENTHESIS # →(11)→
+
+247D ; 0028 006C 004F 0029 ; MA #* ( ⑽ → (lO) ) PARENTHESIZED NUMBER TEN → LEFT PARENTHESIS, LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS # →(10)→
+
+1F11C ; 0028 004D 0029 ; MA #* ( 🄜 → (M) ) PARENTHESIZED LATIN CAPITAL LETTER M → LEFT PARENTHESIS, LATIN CAPITAL LETTER M, RIGHT PARENTHESIS #
+
+24A9 ; 0028 006E 0029 ; MA #* ( ⒩ → (n) ) PARENTHESIZED LATIN SMALL LETTER N → LEFT PARENTHESIS, LATIN SMALL LETTER N, RIGHT PARENTHESIS #
+
+1F11D ; 0028 004E 0029 ; MA #* ( 🄝 → (N) ) PARENTHESIZED LATIN CAPITAL LETTER N → LEFT PARENTHESIS, LATIN CAPITAL LETTER N, RIGHT PARENTHESIS #
+
+24AA ; 0028 006F 0029 ; MA #* ( ⒪ → (o) ) PARENTHESIZED LATIN SMALL LETTER O → LEFT PARENTHESIS, LATIN SMALL LETTER O, RIGHT PARENTHESIS #
+
+1F11E ; 0028 004F 0029 ; MA #* ( 🄞 → (O) ) PARENTHESIZED LATIN CAPITAL LETTER O → LEFT PARENTHESIS, LATIN CAPITAL LETTER O, RIGHT PARENTHESIS #
+
+24AB ; 0028 0070 0029 ; MA #* ( ⒫ → (p) ) PARENTHESIZED LATIN SMALL LETTER P → LEFT PARENTHESIS, LATIN SMALL LETTER P, RIGHT PARENTHESIS #
+
+1F11F ; 0028 0050 0029 ; MA #* ( 🄟 → (P) ) PARENTHESIZED LATIN CAPITAL LETTER P → LEFT PARENTHESIS, LATIN CAPITAL LETTER P, RIGHT PARENTHESIS #
+
+24AC ; 0028 0071 0029 ; MA #* ( ⒬ → (q) ) PARENTHESIZED LATIN SMALL LETTER Q → LEFT PARENTHESIS, LATIN SMALL LETTER Q, RIGHT PARENTHESIS #
+
+1F120 ; 0028 0051 0029 ; MA #* ( 🄠 → (Q) ) PARENTHESIZED LATIN CAPITAL LETTER Q → LEFT PARENTHESIS, LATIN CAPITAL LETTER Q, RIGHT PARENTHESIS #
+
+24AD ; 0028 0072 0029 ; MA #* ( ⒭ → (r) ) PARENTHESIZED LATIN SMALL LETTER R → LEFT PARENTHESIS, LATIN SMALL LETTER R, RIGHT PARENTHESIS #
+
+1F121 ; 0028 0052 0029 ; MA #* ( 🄡 → (R) ) PARENTHESIZED LATIN CAPITAL LETTER R → LEFT PARENTHESIS, LATIN CAPITAL LETTER R, RIGHT PARENTHESIS #
+
+24A8 ; 0028 0072 006E 0029 ; MA #* ( ⒨ → (rn) ) PARENTHESIZED LATIN SMALL LETTER M → LEFT PARENTHESIS, LATIN SMALL LETTER R, LATIN SMALL LETTER N, RIGHT PARENTHESIS # →(m)→
+
+24AE ; 0028 0073 0029 ; MA #* ( ⒮ → (s) ) PARENTHESIZED LATIN SMALL LETTER S → LEFT PARENTHESIS, LATIN SMALL LETTER S, RIGHT PARENTHESIS #
+
+1F122 ; 0028 0053 0029 ; MA #* ( 🄢 → (S) ) PARENTHESIZED LATIN CAPITAL LETTER S → LEFT PARENTHESIS, LATIN CAPITAL LETTER S, RIGHT PARENTHESIS #
+1F12A ; 0028 0053 0029 ; MA #* ( 🄪 → (S) ) TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S → LEFT PARENTHESIS, LATIN CAPITAL LETTER S, RIGHT PARENTHESIS # →〔S〕→
+
+24AF ; 0028 0074 0029 ; MA #* ( ⒯ → (t) ) PARENTHESIZED LATIN SMALL LETTER T → LEFT PARENTHESIS, LATIN SMALL LETTER T, RIGHT PARENTHESIS #
+
+1F123 ; 0028 0054 0029 ; MA #* ( 🄣 → (T) ) PARENTHESIZED LATIN CAPITAL LETTER T → LEFT PARENTHESIS, LATIN CAPITAL LETTER T, RIGHT PARENTHESIS #
+
+24B0 ; 0028 0075 0029 ; MA #* ( ⒰ → (u) ) PARENTHESIZED LATIN SMALL LETTER U → LEFT PARENTHESIS, LATIN SMALL LETTER U, RIGHT PARENTHESIS #
+
+1F124 ; 0028 0055 0029 ; MA #* ( 🄤 → (U) ) PARENTHESIZED LATIN CAPITAL LETTER U → LEFT PARENTHESIS, LATIN CAPITAL LETTER U, RIGHT PARENTHESIS #
+
+24B1 ; 0028 0076 0029 ; MA #* ( ⒱ → (v) ) PARENTHESIZED LATIN SMALL LETTER V → LEFT PARENTHESIS, LATIN SMALL LETTER V, RIGHT PARENTHESIS #
+
+1F125 ; 0028 0056 0029 ; MA #* ( 🄥 → (V) ) PARENTHESIZED LATIN CAPITAL LETTER V → LEFT PARENTHESIS, LATIN CAPITAL LETTER V, RIGHT PARENTHESIS #
+
+24B2 ; 0028 0077 0029 ; MA #* ( ⒲ → (w) ) PARENTHESIZED LATIN SMALL LETTER W → LEFT PARENTHESIS, LATIN SMALL LETTER W, RIGHT PARENTHESIS #
+
+1F126 ; 0028 0057 0029 ; MA #* ( 🄦 → (W) ) PARENTHESIZED LATIN CAPITAL LETTER W → LEFT PARENTHESIS, LATIN CAPITAL LETTER W, RIGHT PARENTHESIS #
+
+24B3 ; 0028 0078 0029 ; MA #* ( ⒳ → (x) ) PARENTHESIZED LATIN SMALL LETTER X → LEFT PARENTHESIS, LATIN SMALL LETTER X, RIGHT PARENTHESIS #
+
+1F127 ; 0028 0058 0029 ; MA #* ( 🄧 → (X) ) PARENTHESIZED LATIN CAPITAL LETTER X → LEFT PARENTHESIS, LATIN CAPITAL LETTER X, RIGHT PARENTHESIS #
+
+24B4 ; 0028 0079 0029 ; MA #* ( ⒴ → (y) ) PARENTHESIZED LATIN SMALL LETTER Y → LEFT PARENTHESIS, LATIN SMALL LETTER Y, RIGHT PARENTHESIS #
+
+1F128 ; 0028 0059 0029 ; MA #* ( 🄨 → (Y) ) PARENTHESIZED LATIN CAPITAL LETTER Y → LEFT PARENTHESIS, LATIN CAPITAL LETTER Y, RIGHT PARENTHESIS #
+
+24B5 ; 0028 007A 0029 ; MA #* ( ⒵ → (z) ) PARENTHESIZED LATIN SMALL LETTER Z → LEFT PARENTHESIS, LATIN SMALL LETTER Z, RIGHT PARENTHESIS #
+
+1F129 ; 0028 005A 0029 ; MA #* ( 🄩 → (Z) ) PARENTHESIZED LATIN CAPITAL LETTER Z → LEFT PARENTHESIS, LATIN CAPITAL LETTER Z, RIGHT PARENTHESIS #
+
+3200 ; 0028 1100 0029 ; MA #* ( ㈀ → (ᄀ) ) PARENTHESIZED HANGUL KIYEOK → LEFT PARENTHESIS, HANGUL CHOSEONG KIYEOK, RIGHT PARENTHESIS #
+
+320E ; 0028 AC00 0029 ; MA #* ( ㈎ → (가) ) PARENTHESIZED HANGUL KIYEOK A → LEFT PARENTHESIS, HANGUL SYLLABLE GA, RIGHT PARENTHESIS #
+
+3201 ; 0028 1102 0029 ; MA #* ( ㈁ → (ᄂ) ) PARENTHESIZED HANGUL NIEUN → LEFT PARENTHESIS, HANGUL CHOSEONG NIEUN, RIGHT PARENTHESIS #
+
+320F ; 0028 B098 0029 ; MA #* ( ㈏ → (나) ) PARENTHESIZED HANGUL NIEUN A → LEFT PARENTHESIS, HANGUL SYLLABLE NA, RIGHT PARENTHESIS #
+
+3202 ; 0028 1103 0029 ; MA #* ( ㈂ → (ᄃ) ) PARENTHESIZED HANGUL TIKEUT → LEFT PARENTHESIS, HANGUL CHOSEONG TIKEUT, RIGHT PARENTHESIS #
+
+3210 ; 0028 B2E4 0029 ; MA #* ( ㈐ → (다) ) PARENTHESIZED HANGUL TIKEUT A → LEFT PARENTHESIS, HANGUL SYLLABLE DA, RIGHT PARENTHESIS #
+
+3203 ; 0028 1105 0029 ; MA #* ( ㈃ → (ᄅ) ) PARENTHESIZED HANGUL RIEUL → LEFT PARENTHESIS, HANGUL CHOSEONG RIEUL, RIGHT PARENTHESIS #
+
+3211 ; 0028 B77C 0029 ; MA #* ( ㈑ → (라) ) PARENTHESIZED HANGUL RIEUL A → LEFT PARENTHESIS, HANGUL SYLLABLE RA, RIGHT PARENTHESIS #
+
+3204 ; 0028 1106 0029 ; MA #* ( ㈄ → (ᄆ) ) PARENTHESIZED HANGUL MIEUM → LEFT PARENTHESIS, HANGUL CHOSEONG MIEUM, RIGHT PARENTHESIS #
+
+3212 ; 0028 B9C8 0029 ; MA #* ( ㈒ → (마) ) PARENTHESIZED HANGUL MIEUM A → LEFT PARENTHESIS, HANGUL SYLLABLE MA, RIGHT PARENTHESIS #
+
+3205 ; 0028 1107 0029 ; MA #* ( ㈅ → (ᄇ) ) PARENTHESIZED HANGUL PIEUP → LEFT PARENTHESIS, HANGUL CHOSEONG PIEUP, RIGHT PARENTHESIS #
+
+3213 ; 0028 BC14 0029 ; MA #* ( ㈓ → (바) ) PARENTHESIZED HANGUL PIEUP A → LEFT PARENTHESIS, HANGUL SYLLABLE BA, RIGHT PARENTHESIS #
+
+3206 ; 0028 1109 0029 ; MA #* ( ㈆ → (ᄉ) ) PARENTHESIZED HANGUL SIOS → LEFT PARENTHESIS, HANGUL CHOSEONG SIOS, RIGHT PARENTHESIS #
+
+3214 ; 0028 C0AC 0029 ; MA #* ( ㈔ → (사) ) PARENTHESIZED HANGUL SIOS A → LEFT PARENTHESIS, HANGUL SYLLABLE SA, RIGHT PARENTHESIS #
+
+3207 ; 0028 110B 0029 ; MA #* ( ㈇ → (ᄋ) ) PARENTHESIZED HANGUL IEUNG → LEFT PARENTHESIS, HANGUL CHOSEONG IEUNG, RIGHT PARENTHESIS #
+
+3215 ; 0028 C544 0029 ; MA #* ( ㈕ → (아) ) PARENTHESIZED HANGUL IEUNG A → LEFT PARENTHESIS, HANGUL SYLLABLE A, RIGHT PARENTHESIS #
+
+321D ; 0028 C624 C804 0029 ; MA #* ( ㈝ → (오전) ) PARENTHESIZED KOREAN CHARACTER OJEON → LEFT PARENTHESIS, HANGUL SYLLABLE O, HANGUL SYLLABLE JEON, RIGHT PARENTHESIS #
+
+321E ; 0028 C624 D6C4 0029 ; MA #* ( ㈞ → (오후) ) PARENTHESIZED KOREAN CHARACTER O HU → LEFT PARENTHESIS, HANGUL SYLLABLE O, HANGUL SYLLABLE HU, RIGHT PARENTHESIS #
+
+3208 ; 0028 110C 0029 ; MA #* ( ㈈ → (ᄌ) ) PARENTHESIZED HANGUL CIEUC → LEFT PARENTHESIS, HANGUL CHOSEONG CIEUC, RIGHT PARENTHESIS #
+
+3216 ; 0028 C790 0029 ; MA #* ( ㈖ → (자) ) PARENTHESIZED HANGUL CIEUC A → LEFT PARENTHESIS, HANGUL SYLLABLE JA, RIGHT PARENTHESIS #
+
+321C ; 0028 C8FC 0029 ; MA #* ( ㈜ → (주) ) PARENTHESIZED HANGUL CIEUC U → LEFT PARENTHESIS, HANGUL SYLLABLE JU, RIGHT PARENTHESIS #
+
+3209 ; 0028 110E 0029 ; MA #* ( ㈉ → (ᄎ) ) PARENTHESIZED HANGUL CHIEUCH → LEFT PARENTHESIS, HANGUL CHOSEONG CHIEUCH, RIGHT PARENTHESIS #
+
+3217 ; 0028 CC28 0029 ; MA #* ( ㈗ → (차) ) PARENTHESIZED HANGUL CHIEUCH A → LEFT PARENTHESIS, HANGUL SYLLABLE CA, RIGHT PARENTHESIS #
+
+320A ; 0028 110F 0029 ; MA #* ( ㈊ → (ᄏ) ) PARENTHESIZED HANGUL KHIEUKH → LEFT PARENTHESIS, HANGUL CHOSEONG KHIEUKH, RIGHT PARENTHESIS #
+
+3218 ; 0028 CE74 0029 ; MA #* ( ㈘ → (카) ) PARENTHESIZED HANGUL KHIEUKH A → LEFT PARENTHESIS, HANGUL SYLLABLE KA, RIGHT PARENTHESIS #
+
+320B ; 0028 1110 0029 ; MA #* ( ㈋ → (ᄐ) ) PARENTHESIZED HANGUL THIEUTH → LEFT PARENTHESIS, HANGUL CHOSEONG THIEUTH, RIGHT PARENTHESIS #
+
+3219 ; 0028 D0C0 0029 ; MA #* ( ㈙ → (타) ) PARENTHESIZED HANGUL THIEUTH A → LEFT PARENTHESIS, HANGUL SYLLABLE TA, RIGHT PARENTHESIS #
+
+320C ; 0028 1111 0029 ; MA #* ( ㈌ → (ᄑ) ) PARENTHESIZED HANGUL PHIEUPH → LEFT PARENTHESIS, HANGUL CHOSEONG PHIEUPH, RIGHT PARENTHESIS #
+
+321A ; 0028 D30C 0029 ; MA #* ( ㈚ → (파) ) PARENTHESIZED HANGUL PHIEUPH A → LEFT PARENTHESIS, HANGUL SYLLABLE PA, RIGHT PARENTHESIS #
+
+320D ; 0028 1112 0029 ; MA #* ( ㈍ → (ᄒ) ) PARENTHESIZED HANGUL HIEUH → LEFT PARENTHESIS, HANGUL CHOSEONG HIEUH, RIGHT PARENTHESIS #
+
+321B ; 0028 D558 0029 ; MA #* ( ㈛ → (하) ) PARENTHESIZED HANGUL HIEUH A → LEFT PARENTHESIS, HANGUL SYLLABLE HA, RIGHT PARENTHESIS #
+
+3226 ; 0028 4E03 0029 ; MA #* ( ㈦ → (七) ) PARENTHESIZED IDEOGRAPH SEVEN → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E03, RIGHT PARENTHESIS #
+
+3222 ; 0028 4E09 0029 ; MA #* ( ㈢ → (三) ) PARENTHESIZED IDEOGRAPH THREE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E09, RIGHT PARENTHESIS #
+1F241 ; 0028 4E09 0029 ; MA #* ( 🉁 → (三) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E09, RIGHT PARENTHESIS # →〔三〕→
+
+3228 ; 0028 4E5D 0029 ; MA #* ( ㈨ → (九) ) PARENTHESIZED IDEOGRAPH NINE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E5D, RIGHT PARENTHESIS #
+
+3221 ; 0028 4E8C 0029 ; MA #* ( ㈡ → (二) ) PARENTHESIZED IDEOGRAPH TWO → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E8C, RIGHT PARENTHESIS #
+1F242 ; 0028 4E8C 0029 ; MA #* ( 🉂 → (二) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E8C, RIGHT PARENTHESIS # →〔二〕→
+
+3224 ; 0028 4E94 0029 ; MA #* ( ㈤ → (五) ) PARENTHESIZED IDEOGRAPH FIVE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4E94, RIGHT PARENTHESIS #
+
+3239 ; 0028 4EE3 0029 ; MA #* ( ㈹ → (代) ) PARENTHESIZED IDEOGRAPH REPRESENT → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4EE3, RIGHT PARENTHESIS #
+
+323D ; 0028 4F01 0029 ; MA #* ( ㈽ → (企) ) PARENTHESIZED IDEOGRAPH ENTERPRISE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4F01, RIGHT PARENTHESIS #
+
+3241 ; 0028 4F11 0029 ; MA #* ( ㉁ → (休) ) PARENTHESIZED IDEOGRAPH REST → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-4F11, RIGHT PARENTHESIS #
+
+3227 ; 0028 516B 0029 ; MA #* ( ㈧ → (八) ) PARENTHESIZED IDEOGRAPH EIGHT → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-516B, RIGHT PARENTHESIS #
+
+3225 ; 0028 516D 0029 ; MA #* ( ㈥ → (六) ) PARENTHESIZED IDEOGRAPH SIX → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-516D, RIGHT PARENTHESIS #
+
+3238 ; 0028 52B4 0029 ; MA #* ( ㈸ → (労) ) PARENTHESIZED IDEOGRAPH LABOR → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-52B4, RIGHT PARENTHESIS #
+
+1F247 ; 0028 52DD 0029 ; MA #* ( 🉇 → (勝) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-52DD, RIGHT PARENTHESIS # →〔勝〕→
+
+3229 ; 0028 5341 0029 ; MA #* ( ㈩ → (十) ) PARENTHESIZED IDEOGRAPH TEN → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-5341, RIGHT PARENTHESIS #
+
+323F ; 0028 5354 0029 ; MA #* ( ㈿ → (協) ) PARENTHESIZED IDEOGRAPH ALLIANCE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-5354, RIGHT PARENTHESIS #
+
+3234 ; 0028 540D 0029 ; MA #* ( ㈴ → (名) ) PARENTHESIZED IDEOGRAPH NAME → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-540D, RIGHT PARENTHESIS #
+
+323A ; 0028 547C 0029 ; MA #* ( ㈺ → (呼) ) PARENTHESIZED IDEOGRAPH CALL → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-547C, RIGHT PARENTHESIS #
+
+3223 ; 0028 56DB 0029 ; MA #* ( ㈣ → (四) ) PARENTHESIZED IDEOGRAPH FOUR → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-56DB, RIGHT PARENTHESIS #
+
+322F ; 0028 571F 0029 ; MA #* ( ㈯ → (土) ) PARENTHESIZED IDEOGRAPH EARTH → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-571F, RIGHT PARENTHESIS #
+
+323B ; 0028 5B66 0029 ; MA #* ( ㈻ → (学) ) PARENTHESIZED IDEOGRAPH STUDY → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-5B66, RIGHT PARENTHESIS #
+
+1F243 ; 0028 5B89 0029 ; MA #* ( 🉃 → (安) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-5B89, RIGHT PARENTHESIS # →〔安〕→
+
+1F245 ; 0028 6253 0029 ; MA #* ( 🉅 → (打) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6253, RIGHT PARENTHESIS # →〔打〕→
+
+1F248 ; 0028 6557 0029 ; MA #* ( 🉈 → (敗) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6557, RIGHT PARENTHESIS # →〔敗〕→
+
+3230 ; 0028 65E5 0029 ; MA #* ( ㈰ → (日) ) PARENTHESIZED IDEOGRAPH SUN → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-65E5, RIGHT PARENTHESIS #
+
+322A ; 0028 6708 0029 ; MA #* ( ㈪ → (月) ) PARENTHESIZED IDEOGRAPH MOON → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6708, RIGHT PARENTHESIS #
+
+3232 ; 0028 6709 0029 ; MA #* ( ㈲ → (有) ) PARENTHESIZED IDEOGRAPH HAVE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6709, RIGHT PARENTHESIS #
+
+322D ; 0028 6728 0029 ; MA #* ( ㈭ → (木) ) PARENTHESIZED IDEOGRAPH WOOD → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6728, RIGHT PARENTHESIS #
+
+1F240 ; 0028 672C 0029 ; MA #* ( 🉀 → (本) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-672C, RIGHT PARENTHESIS # →〔本〕→
+
+3231 ; 0028 682A 0029 ; MA #* ( ㈱ → (株) ) PARENTHESIZED IDEOGRAPH STOCK → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-682A, RIGHT PARENTHESIS #
+
+322C ; 0028 6C34 0029 ; MA #* ( ㈬ → (水) ) PARENTHESIZED IDEOGRAPH WATER → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-6C34, RIGHT PARENTHESIS #
+
+322B ; 0028 706B 0029 ; MA #* ( ㈫ → (火) ) PARENTHESIZED IDEOGRAPH FIRE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-706B, RIGHT PARENTHESIS #
+
+1F244 ; 0028 70B9 0029 ; MA #* ( 🉄 → (点) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-70B9, RIGHT PARENTHESIS # →〔点〕→
+
+3235 ; 0028 7279 0029 ; MA #* ( ㈵ → (特) ) PARENTHESIZED IDEOGRAPH SPECIAL → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-7279, RIGHT PARENTHESIS #
+
+1F246 ; 0028 76D7 0029 ; MA #* ( 🉆 → (盗) ) TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7 → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-76D7, RIGHT PARENTHESIS # →〔盗〕→
+
+323C ; 0028 76E3 0029 ; MA #* ( ㈼ → (監) ) PARENTHESIZED IDEOGRAPH SUPERVISE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-76E3, RIGHT PARENTHESIS #
+
+3233 ; 0028 793E 0029 ; MA #* ( ㈳ → (社) ) PARENTHESIZED IDEOGRAPH SOCIETY → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-793E, RIGHT PARENTHESIS #
+
+3237 ; 0028 795D 0029 ; MA #* ( ㈷ → (祝) ) PARENTHESIZED IDEOGRAPH CONGRATULATION → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-795D, RIGHT PARENTHESIS #
+
+3240 ; 0028 796D 0029 ; MA #* ( ㉀ → (祭) ) PARENTHESIZED IDEOGRAPH FESTIVAL → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-796D, RIGHT PARENTHESIS #
+
+3242 ; 0028 81EA 0029 ; MA #* ( ㉂ → (自) ) PARENTHESIZED IDEOGRAPH SELF → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-81EA, RIGHT PARENTHESIS #
+
+3243 ; 0028 81F3 0029 ; MA #* ( ㉃ → (至) ) PARENTHESIZED IDEOGRAPH REACH → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-81F3, RIGHT PARENTHESIS #
+
+3236 ; 0028 8CA1 0029 ; MA #* ( ㈶ → (財) ) PARENTHESIZED IDEOGRAPH FINANCIAL → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-8CA1, RIGHT PARENTHESIS #
+
+323E ; 0028 8CC7 0029 ; MA #* ( ㈾ → (資) ) PARENTHESIZED IDEOGRAPH RESOURCE → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-8CC7, RIGHT PARENTHESIS #
+
+322E ; 0028 91D1 0029 ; MA #* ( ㈮ → (金) ) PARENTHESIZED IDEOGRAPH METAL → LEFT PARENTHESIS, CJK UNIFIED IDEOGRAPH-91D1, RIGHT PARENTHESIS #
+
+FF3D ; 0029 ; MA #* ( ] → ) ) FULLWIDTH RIGHT SQUARE BRACKET → RIGHT PARENTHESIS # →〕→
+2769 ; 0029 ; MA #* ( ❩ → ) ) MEDIUM RIGHT PARENTHESIS ORNAMENT → RIGHT PARENTHESIS #
+2773 ; 0029 ; MA #* ( ❳ → ) ) LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT → RIGHT PARENTHESIS # →〕→
+3015 ; 0029 ; MA #* ( 〕 → ) ) RIGHT TORTOISE SHELL BRACKET → RIGHT PARENTHESIS #
+FD3F ; 0029 ; MA #* ( ﴿ → ) ) ORNATE RIGHT PARENTHESIS → RIGHT PARENTHESIS #
+
+2E29 ; 0029 0029 ; MA #* ( ⸩ → )) ) RIGHT DOUBLE PARENTHESIS → RIGHT PARENTHESIS, RIGHT PARENTHESIS #
+
+2774 ; 007B ; MA #* ( ❴ → { ) MEDIUM LEFT CURLY BRACKET ORNAMENT → LEFT CURLY BRACKET #
+1D114 ; 007B ; MA #* ( 𝄔 → { ) MUSICAL SYMBOL BRACE → LEFT CURLY BRACKET #
+
+2775 ; 007D ; MA #* ( ❵ → } ) MEDIUM RIGHT CURLY BRACKET ORNAMENT → RIGHT CURLY BRACKET #
+
+301A ; 27E6 ; MA #* ( 〚 → ⟦ ) LEFT WHITE SQUARE BRACKET → MATHEMATICAL LEFT WHITE SQUARE BRACKET #
+
+301B ; 27E7 ; MA #* ( 〛 → ⟧ ) RIGHT WHITE SQUARE BRACKET → MATHEMATICAL RIGHT WHITE SQUARE BRACKET #
+
+27E8 ; 276C ; MA #* ( ⟨ → ❬ ) MATHEMATICAL LEFT ANGLE BRACKET → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →〈→
+2329 ; 276C ; MA #* ( 〈 → ❬ ) LEFT-POINTING ANGLE BRACKET → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →〈→
+3008 ; 276C ; MA #* ( 〈 → ❬ ) LEFT ANGLE BRACKET → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT #
+31DB ; 276C ; MA #* ( ㇛ → ❬ ) CJK STROKE PD → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →⟨→→〈→
+304F ; 276C ; MA # ( く → ❬ ) HIRAGANA LETTER KU → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →㇛→→⟨→→〈→
+21FE8 ; 276C ; MA # ( 𡿨 → ❬ ) CJK UNIFIED IDEOGRAPH-21FE8 → MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # →㇛→→⟨→→〈→
+
+27E9 ; 276D ; MA #* ( ⟩ → ❭ ) MATHEMATICAL RIGHT ANGLE BRACKET → MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT # →〉→
+232A ; 276D ; MA #* ( 〉 → ❭ ) RIGHT-POINTING ANGLE BRACKET → MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT # →〉→
+3009 ; 276D ; MA #* ( 〉 → ❭ ) RIGHT ANGLE BRACKET → MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT #
+
+FF3E ; FE3F ; MA #* ( ^ → ︿ ) FULLWIDTH CIRCUMFLEX ACCENT → PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET #
+
+2E3F ; 00B6 ; MA #* ( ⸿ → ¶ ) CAPITULUM → PILCROW SIGN #
+
+204E ; 002A ; MA #* ( ⁎ → * ) LOW ASTERISK → ASTERISK #
+066D ; 002A ; MA #* ( ‎٭‎ → * ) ARABIC FIVE POINTED STAR → ASTERISK #
+2217 ; 002A ; MA #* ( ∗ → * ) ASTERISK OPERATOR → ASTERISK #
+1031F ; 002A ; MA # ( 𐌟 → * ) OLD ITALIC LETTER ESS → ASTERISK #
+
+1735 ; 002F ; MA #* ( ᜵ → / ) PHILIPPINE SINGLE PUNCTUATION → SOLIDUS #
+2041 ; 002F ; MA #* ( ⁁ → / ) CARET INSERTION POINT → SOLIDUS #
+2215 ; 002F ; MA #* ( ∕ → / ) DIVISION SLASH → SOLIDUS #
+2044 ; 002F ; MA #* ( ⁄ → / ) FRACTION SLASH → SOLIDUS #
+2571 ; 002F ; MA #* ( ╱ → / ) BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT → SOLIDUS #
+27CB ; 002F ; MA #* ( ⟋ → / ) MATHEMATICAL RISING DIAGONAL → SOLIDUS #
+29F8 ; 002F ; MA #* ( ⧸ → / ) BIG SOLIDUS → SOLIDUS #
+1D23A ; 002F ; MA #* ( 𝈺 → / ) GREEK INSTRUMENTAL NOTATION SYMBOL-47 → SOLIDUS #
+31D3 ; 002F ; MA #* ( ㇓ → / ) CJK STROKE SP → SOLIDUS # →⼃→
+3033 ; 002F ; MA # ( 〳 → / ) VERTICAL KANA REPEAT MARK UPPER HALF → SOLIDUS #
+2CC6 ; 002F ; MA # ( Ⳇ → / ) COPTIC CAPITAL LETTER OLD COPTIC ESH → SOLIDUS #
+30CE ; 002F ; MA # ( ノ → / ) KATAKANA LETTER NO → SOLIDUS # →⼃→
+4E3F ; 002F ; MA # ( 丿 → / ) CJK UNIFIED IDEOGRAPH-4E3F → SOLIDUS # →⼃→
+2F03 ; 002F ; MA #* ( ⼃ → / ) KANGXI RADICAL SLASH → SOLIDUS #
+
+29F6 ; 002F 0304 ; MA #* ( ⧶ → /̄ ) SOLIDUS WITH OVERBAR → SOLIDUS, COMBINING MACRON #
+
+2AFD ; 002F 002F ; MA #* ( ⫽ → // ) DOUBLE SOLIDUS OPERATOR → SOLIDUS, SOLIDUS #
+
+2AFB ; 002F 002F 002F ; MA #* ( ⫻ → /// ) TRIPLE SOLIDUS BINARY RELATION → SOLIDUS, SOLIDUS, SOLIDUS #
+
+FF3C ; 005C ; MA #* ( \ → \ ) FULLWIDTH REVERSE SOLIDUS → REVERSE SOLIDUS # →∖→
+FE68 ; 005C ; MA #* ( ﹨ → \ ) SMALL REVERSE SOLIDUS → REVERSE SOLIDUS # →∖→
+2216 ; 005C ; MA #* ( ∖ → \ ) SET MINUS → REVERSE SOLIDUS #
+27CD ; 005C ; MA #* ( ⟍ → \ ) MATHEMATICAL FALLING DIAGONAL → REVERSE SOLIDUS #
+29F5 ; 005C ; MA #* ( ⧵ → \ ) REVERSE SOLIDUS OPERATOR → REVERSE SOLIDUS #
+29F9 ; 005C ; MA #* ( ⧹ → \ ) BIG REVERSE SOLIDUS → REVERSE SOLIDUS #
+1D20F ; 005C ; MA #* ( 𝈏 → \ ) GREEK VOCAL NOTATION SYMBOL-16 → REVERSE SOLIDUS #
+1D23B ; 005C ; MA #* ( 𝈻 → \ ) GREEK INSTRUMENTAL NOTATION SYMBOL-48 → REVERSE SOLIDUS # →𝈏→
+31D4 ; 005C ; MA #* ( ㇔ → \ ) CJK STROKE D → REVERSE SOLIDUS # →⼂→
+4E36 ; 005C ; MA # ( 丶 → \ ) CJK UNIFIED IDEOGRAPH-4E36 → REVERSE SOLIDUS # →⼂→
+2F02 ; 005C ; MA #* ( ⼂ → \ ) KANGXI RADICAL DOT → REVERSE SOLIDUS #
+
+2CF9 ; 005C 005C ; MA #* ( ⳹ → \\ ) COPTIC OLD NUBIAN FULL STOP → REVERSE SOLIDUS, REVERSE SOLIDUS #
+244A ; 005C 005C ; MA #* ( ⑊ → \\ ) OCR DOUBLE BACKSLASH → REVERSE SOLIDUS, REVERSE SOLIDUS #
+
+27C8 ; 005C 1455 ; MA #* ( ⟈ → \ᑕ ) REVERSE SOLIDUS PRECEDING SUBSET → REVERSE SOLIDUS, CANADIAN SYLLABICS TA # →\⊂→
+
+A778 ; 0026 ; MA # ( ꝸ → & ) LATIN SMALL LETTER UM → AMPERSAND #
+
+0AF0 ; 0970 ; MA #* ( ૰ → ॰ ) GUJARATI ABBREVIATION SIGN → DEVANAGARI ABBREVIATION SIGN #
+110BB ; 0970 ; MA #* ( 𑂻 → ॰ ) KAITHI ABBREVIATION SIGN → DEVANAGARI ABBREVIATION SIGN #
+111C7 ; 0970 ; MA #* ( 𑇇 → ॰ ) SHARADA ABBREVIATION SIGN → DEVANAGARI ABBREVIATION SIGN #
+26AC ; 0970 ; MA #* ( ⚬ → ॰ ) MEDIUM SMALL WHITE CIRCLE → DEVANAGARI ABBREVIATION SIGN #
+
+111DB ; A8FC ; MA #* ( 𑇛 → ꣼ ) SHARADA SIGN SIDDHAM → DEVANAGARI SIGN SIDDHAM #
+
+17D9 ; 0E4F ; MA #* ( ៙ → ๏ ) KHMER SIGN PHNAEK MUAN → THAI CHARACTER FONGMAN #
+
+17D5 ; 0E5A ; MA #* ( ៕ → ๚ ) KHMER SIGN BARIYOOSAN → THAI CHARACTER ANGKHANKHU #
+
+17DA ; 0E5B ; MA #* ( ៚ → ๛ ) KHMER SIGN KOOMUUT → THAI CHARACTER KHOMUT #
+
+0F0C ; 0F0B ; MA #* ( ༌ → ་ ) TIBETAN MARK DELIMITER TSHEG BSTAR → TIBETAN MARK INTERSYLLABIC TSHEG #
+
+0F0E ; 0F0D 0F0D ; MA #* ( ༎ → །། ) TIBETAN MARK NYIS SHAD → TIBETAN MARK SHAD, TIBETAN MARK SHAD #
+
+02C4 ; 005E ; MA #* ( ˄ → ^ ) MODIFIER LETTER UP ARROWHEAD → CIRCUMFLEX ACCENT #
+02C6 ; 005E ; MA # ( ˆ → ^ ) MODIFIER LETTER CIRCUMFLEX ACCENT → CIRCUMFLEX ACCENT #
+
+A67E ; 02C7 ; MA #* ( ꙾ → ˇ ) CYRILLIC KAVYKA → CARON # →˘→
+02D8 ; 02C7 ; MA #* ( ˘ → ˇ ) BREVE → CARON #
+
+203E ; 02C9 ; MA #* ( ‾ → ˉ ) OVERLINE → MODIFIER LETTER MACRON #
+FE49 ; 02C9 ; MA #* ( ﹉ → ˉ ) DASHED OVERLINE → MODIFIER LETTER MACRON # →‾→
+FE4A ; 02C9 ; MA #* ( ﹊ → ˉ ) CENTRELINE OVERLINE → MODIFIER LETTER MACRON # →‾→
+FE4B ; 02C9 ; MA #* ( ﹋ → ˉ ) WAVY OVERLINE → MODIFIER LETTER MACRON # →‾→
+FE4C ; 02C9 ; MA #* ( ﹌ → ˉ ) DOUBLE WAVY OVERLINE → MODIFIER LETTER MACRON # →‾→
+00AF ; 02C9 ; MA #* ( ¯ → ˉ ) MACRON → MODIFIER LETTER MACRON #
+FFE3 ; 02C9 ; MA #* (  ̄ → ˉ ) FULLWIDTH MACRON → MODIFIER LETTER MACRON # →‾→
+2594 ; 02C9 ; MA #* ( ▔ → ˉ ) UPPER ONE EIGHTH BLOCK → MODIFIER LETTER MACRON # →¯→
+
+044A ; 02C9 0062 ; MA # ( ъ → ˉb ) CYRILLIC SMALL LETTER HARD SIGN → MODIFIER LETTER MACRON, LATIN SMALL LETTER B # →¯b→
+
+A651 ; 02C9 0062 0069 ; MA # ( ꙑ → ˉbi ) CYRILLIC SMALL LETTER YERU WITH BACK YER → MODIFIER LETTER MACRON, LATIN SMALL LETTER B, LATIN SMALL LETTER I # →ъı→
+
+0375 ; 02CF ; MA #* ( ͵ → ˏ ) GREEK LOWER NUMERAL SIGN → MODIFIER LETTER LOW ACUTE ACCENT #
+
+02FB ; 02EA ; MA #* ( ˻ → ˪ ) MODIFIER LETTER BEGIN LOW TONE → MODIFIER LETTER YIN DEPARTING TONE MARK #
+A716 ; 02EA ; MA #* ( ꜖ → ˪ ) MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR → MODIFIER LETTER YIN DEPARTING TONE MARK #
+
+A714 ; 02EB ; MA #* ( ꜔ → ˫ ) MODIFIER LETTER MID LEFT-STEM TONE BAR → MODIFIER LETTER YANG DEPARTING TONE MARK #
+
+3002 ; 02F3 ; MA #* ( 。 → ˳ ) IDEOGRAPHIC FULL STOP → MODIFIER LETTER LOW RING #
+
+2E30 ; 00B0 ; MA #* ( ⸰ → ° ) RING POINT → DEGREE SIGN # →∘→
+02DA ; 00B0 ; MA #* ( ˚ → ° ) RING ABOVE → DEGREE SIGN #
+2218 ; 00B0 ; MA #* ( ∘ → ° ) RING OPERATOR → DEGREE SIGN #
+25CB ; 00B0 ; MA #* ( ○ → ° ) WHITE CIRCLE → DEGREE SIGN # →◦→→∘→
+25E6 ; 00B0 ; MA #* ( ◦ → ° ) WHITE BULLET → DEGREE SIGN # →∘→
+
+235C ; 00B0 0332 ; MA #* ( ⍜ → °̲ ) APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR → DEGREE SIGN, COMBINING LOW LINE # →○̲→→∘̲→
+
+2364 ; 00B0 0308 ; MA #* ( ⍤ → °̈ ) APL FUNCTIONAL SYMBOL JOT DIAERESIS → DEGREE SIGN, COMBINING DIAERESIS # →◦̈→→∘̈→
+
+2103 ; 00B0 0043 ; MA #* ( ℃ → °C ) DEGREE CELSIUS → DEGREE SIGN, LATIN CAPITAL LETTER C #
+
+2109 ; 00B0 0046 ; MA #* ( ℉ → °F ) DEGREE FAHRENHEIT → DEGREE SIGN, LATIN CAPITAL LETTER F #
+
+0BF5 ; 0BF3 ; MA #* ( ௵ → ௳ ) TAMIL YEAR SIGN → TAMIL DAY SIGN #
+
+0F1B ; 0F1A 0F1A ; MA #* ( ༛ → ༚༚ ) TIBETAN SIGN RDEL DKAR GNYIS → TIBETAN SIGN RDEL DKAR GCIG, TIBETAN SIGN RDEL DKAR GCIG #
+
+0F1F ; 0F1A 0F1D ; MA #* ( ༟ → ༚༝ ) TIBETAN SIGN RDEL DKAR RDEL NAG → TIBETAN SIGN RDEL DKAR GCIG, TIBETAN SIGN RDEL NAG GCIG #
+
+0FCE ; 0F1D 0F1A ; MA #* ( ࿎ → ༝༚ ) TIBETAN SIGN RDEL NAG RDEL DKAR → TIBETAN SIGN RDEL NAG GCIG, TIBETAN SIGN RDEL DKAR GCIG #
+
+0F1E ; 0F1D 0F1D ; MA #* ( ༞ → ༝༝ ) TIBETAN SIGN RDEL NAG GNYIS → TIBETAN SIGN RDEL NAG GCIG, TIBETAN SIGN RDEL NAG GCIG #
+
+24B8 ; 00A9 ; MA #* ( Ⓒ → © ) CIRCLED LATIN CAPITAL LETTER C → COPYRIGHT SIGN #
+
+24C7 ; 00AE ; MA #* ( Ⓡ → ® ) CIRCLED LATIN CAPITAL LETTER R → REGISTERED SIGN #
+
+24C5 ; 2117 ; MA #* ( Ⓟ → ℗ ) CIRCLED LATIN CAPITAL LETTER P → SOUND RECORDING COPYRIGHT #
+
+1D21B ; 2144 ; MA #* ( 𝈛 → ⅄ ) GREEK VOCAL NOTATION SYMBOL-53 → TURNED SANS-SERIF CAPITAL Y #
+
+2BEC ; 219E ; MA #* ( ⯬ → ↞ ) LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS → LEFTWARDS TWO HEADED ARROW #
+
+2BED ; 219F ; MA #* ( ⯭ → ↟ ) UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS → UPWARDS TWO HEADED ARROW #
+
+2BEE ; 21A0 ; MA #* ( ⯮ → ↠ ) RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS → RIGHTWARDS TWO HEADED ARROW #
+
+2BEF ; 21A1 ; MA #* ( ⯯ → ↡ ) DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS → DOWNWARDS TWO HEADED ARROW #
+
+21B5 ; 21B2 ; MA #* ( ↵ → ↲ ) DOWNWARDS ARROW WITH CORNER LEFTWARDS → DOWNWARDS ARROW WITH TIP LEFTWARDS #
+
+2965 ; 21C3 21C2 ; MA #* ( ⥥ → ⇃⇂ ) DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT → DOWNWARDS HARPOON WITH BARB LEFTWARDS, DOWNWARDS HARPOON WITH BARB RIGHTWARDS #
+
+296F ; 21C3 16DA ; MA #* ( ⥯ → ⇃ᛚ ) DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT → DOWNWARDS HARPOON WITH BARB LEFTWARDS, RUNIC LETTER LAUKAZ LAGU LOGR L # →⇃↾→
+
+1D6DB ; 2202 ; MA #* ( 𝛛 → ∂ ) MATHEMATICAL BOLD PARTIAL DIFFERENTIAL → PARTIAL DIFFERENTIAL #
+1D715 ; 2202 ; MA #* ( 𝜕 → ∂ ) MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL → PARTIAL DIFFERENTIAL #
+1D74F ; 2202 ; MA #* ( 𝝏 → ∂ ) MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL → PARTIAL DIFFERENTIAL #
+1D789 ; 2202 ; MA #* ( 𝞉 → ∂ ) MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL → PARTIAL DIFFERENTIAL #
+1D7C3 ; 2202 ; MA #* ( 𝟃 → ∂ ) MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL → PARTIAL DIFFERENTIAL #
+1E8CC ; 2202 ; MA #* ( ‎𞣌‎ → ∂ ) MENDE KIKAKUI DIGIT SIX → PARTIAL DIFFERENTIAL #
+
+1E8CD ; 2202 0335 ; MA #* ( ‎𞣍‎ → ∂̵ ) MENDE KIKAKUI DIGIT SEVEN → PARTIAL DIFFERENTIAL, COMBINING SHORT STROKE OVERLAY # →ð→
+00F0 ; 2202 0335 ; MA # ( ð → ∂̵ ) LATIN SMALL LETTER ETH → PARTIAL DIFFERENTIAL, COMBINING SHORT STROKE OVERLAY #
+
+2300 ; 2205 ; MA #* ( ⌀ → ∅ ) DIAMETER SIGN → EMPTY SET #
+
+1D6C1 ; 2207 ; MA #* ( 𝛁 → ∇ ) MATHEMATICAL BOLD NABLA → NABLA #
+1D6FB ; 2207 ; MA #* ( 𝛻 → ∇ ) MATHEMATICAL ITALIC NABLA → NABLA #
+1D735 ; 2207 ; MA #* ( 𝜵 → ∇ ) MATHEMATICAL BOLD ITALIC NABLA → NABLA #
+1D76F ; 2207 ; MA #* ( 𝝯 → ∇ ) MATHEMATICAL SANS-SERIF BOLD NABLA → NABLA #
+1D7A9 ; 2207 ; MA #* ( 𝞩 → ∇ ) MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA → NABLA #
+118A8 ; 2207 ; MA # ( 𑢨 → ∇ ) WARANG CITI CAPITAL LETTER E → NABLA #
+
+2362 ; 2207 0308 ; MA #* ( ⍢ → ∇̈ ) APL FUNCTIONAL SYMBOL DEL DIAERESIS → NABLA, COMBINING DIAERESIS #
+
+236B ; 2207 0334 ; MA #* ( ⍫ → ∇̴ ) APL FUNCTIONAL SYMBOL DEL TILDE → NABLA, COMBINING TILDE OVERLAY #
+
+2588 ; 220E ; MA #* ( █ → ∎ ) FULL BLOCK → END OF PROOF # →■→
+25A0 ; 220E ; MA #* ( ■ → ∎ ) BLACK SQUARE → END OF PROOF #
+
+2A3F ; 2210 ; MA #* ( ⨿ → ∐ ) AMALGAMATION OR COPRODUCT → N-ARY COPRODUCT #
+
+16ED ; 002B ; MA #* ( ᛭ → + ) RUNIC CROSS PUNCTUATION → PLUS SIGN #
+2795 ; 002B ; MA #* ( ➕ → + ) HEAVY PLUS SIGN → PLUS SIGN #
+1029B ; 002B ; MA # ( 𐊛 → + ) LYCIAN LETTER H → PLUS SIGN #
+
+2A23 ; 002B 0302 ; MA #* ( ⨣ → +̂ ) PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE → PLUS SIGN, COMBINING CIRCUMFLEX ACCENT #
+
+2A22 ; 002B 030A ; MA #* ( ⨢ → +̊ ) PLUS SIGN WITH SMALL CIRCLE ABOVE → PLUS SIGN, COMBINING RING ABOVE #
+
+2A24 ; 002B 0303 ; MA #* ( ⨤ → +̃ ) PLUS SIGN WITH TILDE ABOVE → PLUS SIGN, COMBINING TILDE #
+
+2214 ; 002B 0307 ; MA #* ( ∔ → +̇ ) DOT PLUS → PLUS SIGN, COMBINING DOT ABOVE #
+
+2A25 ; 002B 0323 ; MA #* ( ⨥ → +̣ ) PLUS SIGN WITH DOT BELOW → PLUS SIGN, COMBINING DOT BELOW #
+
+2A26 ; 002B 0330 ; MA #* ( ⨦ → +̰ ) PLUS SIGN WITH TILDE BELOW → PLUS SIGN, COMBINING TILDE BELOW #
+
+2A27 ; 002B 2082 ; MA #* ( ⨧ → +₂ ) PLUS SIGN WITH SUBSCRIPT TWO → PLUS SIGN, SUBSCRIPT TWO #
+
+2797 ; 00F7 ; MA #* ( ➗ → ÷ ) HEAVY DIVISION SIGN → DIVISION SIGN #
+
+2039 ; 003C ; MA #* ( ‹ → < ) SINGLE LEFT-POINTING ANGLE QUOTATION MARK → LESS-THAN SIGN #
+276E ; 003C ; MA #* ( ❮ → < ) HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT → LESS-THAN SIGN # →‹→
+02C2 ; 003C ; MA #* ( ˂ → < ) MODIFIER LETTER LEFT ARROWHEAD → LESS-THAN SIGN #
+1D236 ; 003C ; MA #* ( 𝈶 → < ) GREEK INSTRUMENTAL NOTATION SYMBOL-40 → LESS-THAN SIGN #
+1438 ; 003C ; MA # ( ᐸ → < ) CANADIAN SYLLABICS PA → LESS-THAN SIGN #
+16B2 ; 003C ; MA # ( ᚲ → < ) RUNIC LETTER KAUNA → LESS-THAN SIGN #
+
+22D6 ; 003C 00B7 ; MA #* ( ⋖ → <· ) LESS-THAN WITH DOT → LESS-THAN SIGN, MIDDLE DOT # →ᑅ→→ᐸᐧ→
+2CB4 ; 003C 00B7 ; MA # ( Ⲵ → <· ) COPTIC CAPITAL LETTER OLD COPTIC AIN → LESS-THAN SIGN, MIDDLE DOT # →ᑅ→→ᐸᐧ→
+1445 ; 003C 00B7 ; MA # ( ᑅ → <· ) CANADIAN SYLLABICS WEST-CREE PWA → LESS-THAN SIGN, MIDDLE DOT # →ᐸᐧ→
+
+226A ; 003C 003C ; MA #* ( ≪ → << ) MUCH LESS-THAN → LESS-THAN SIGN, LESS-THAN SIGN #
+
+22D8 ; 003C 003C 003C ; MA #* ( ⋘ → <<< ) VERY MUCH LESS-THAN → LESS-THAN SIGN, LESS-THAN SIGN, LESS-THAN SIGN #
+
+1400 ; 003D ; MA #* ( ᐀ → = ) CANADIAN SYLLABICS HYPHEN → EQUALS SIGN #
+2E40 ; 003D ; MA #* ( ⹀ → = ) DOUBLE HYPHEN → EQUALS SIGN #
+30A0 ; 003D ; MA #* ( ゠ → = ) KATAKANA-HIRAGANA DOUBLE HYPHEN → EQUALS SIGN #
+A4FF ; 003D ; MA #* ( ꓿ → = ) LISU PUNCTUATION FULL STOP → EQUALS SIGN #
+
+225A ; 003D 0306 ; MA #* ( ≚ → =̆ ) EQUIANGULAR TO → EQUALS SIGN, COMBINING BREVE # →=̌→
+
+2259 ; 003D 0302 ; MA #* ( ≙ → =̂ ) ESTIMATES → EQUALS SIGN, COMBINING CIRCUMFLEX ACCENT #
+
+2257 ; 003D 030A ; MA #* ( ≗ → =̊ ) RING EQUAL TO → EQUALS SIGN, COMBINING RING ABOVE #
+
+2250 ; 003D 0307 ; MA #* ( ≐ → =̇ ) APPROACHES THE LIMIT → EQUALS SIGN, COMBINING DOT ABOVE #
+
+2251 ; 003D 0307 0323 ; MA #* ( ≑ → =̣̇ ) GEOMETRICALLY EQUAL TO → EQUALS SIGN, COMBINING DOT ABOVE, COMBINING DOT BELOW # →≐̣→
+
+2A6E ; 003D 20F0 ; MA #* ( ⩮ → =⃰ ) EQUALS WITH ASTERISK → EQUALS SIGN, COMBINING ASTERISK ABOVE #
+
+2A75 ; 003D 003D ; MA #* ( ⩵ → == ) TWO CONSECUTIVE EQUALS SIGNS → EQUALS SIGN, EQUALS SIGN #
+
+2A76 ; 003D 003D 003D ; MA #* ( ⩶ → === ) THREE CONSECUTIVE EQUALS SIGNS → EQUALS SIGN, EQUALS SIGN, EQUALS SIGN #
+
+225E ; 003D 036B ; MA #* ( ≞ → =ͫ ) MEASURED BY → EQUALS SIGN, COMBINING LATIN SMALL LETTER M #
+
+203A ; 003E ; MA #* ( › → > ) SINGLE RIGHT-POINTING ANGLE QUOTATION MARK → GREATER-THAN SIGN #
+276F ; 003E ; MA #* ( ❯ → > ) HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT → GREATER-THAN SIGN # →›→
+02C3 ; 003E ; MA #* ( ˃ → > ) MODIFIER LETTER RIGHT ARROWHEAD → GREATER-THAN SIGN #
+1D237 ; 003E ; MA #* ( 𝈷 → > ) GREEK INSTRUMENTAL NOTATION SYMBOL-42 → GREATER-THAN SIGN #
+1433 ; 003E ; MA # ( ᐳ → > ) CANADIAN SYLLABICS PO → GREATER-THAN SIGN #
+16F3F ; 003E ; MA # ( 𖼿 → > ) MIAO LETTER ARCHAIC ZZA → GREATER-THAN SIGN #
+
+1441 ; 003E 00B7 ; MA # ( ᑁ → >· ) CANADIAN SYLLABICS WEST-CREE PWO → GREATER-THAN SIGN, MIDDLE DOT # →ᐳᐧ→
+
+2AA5 ; 003E 003C ; MA #* ( ⪥ → >< ) GREATER-THAN BESIDE LESS-THAN → GREATER-THAN SIGN, LESS-THAN SIGN #
+
+226B ; 003E 003E ; MA #* ( ≫ → >> ) MUCH GREATER-THAN → GREATER-THAN SIGN, GREATER-THAN SIGN #
+2A20 ; 003E 003E ; MA #* ( ⨠ → >> ) Z NOTATION SCHEMA PIPING → GREATER-THAN SIGN, GREATER-THAN SIGN # →≫→
+
+22D9 ; 003E 003E 003E ; MA #* ( ⋙ → >>> ) VERY MUCH GREATER-THAN → GREATER-THAN SIGN, GREATER-THAN SIGN, GREATER-THAN SIGN #
+
+2053 ; 007E ; MA #* ( ⁓ → ~ ) SWUNG DASH → TILDE #
+02DC ; 007E ; MA #* ( ˜ → ~ ) SMALL TILDE → TILDE #
+1FC0 ; 007E ; MA #* ( ῀ → ~ ) GREEK PERISPOMENI → TILDE # →˜→
+223C ; 007E ; MA #* ( ∼ → ~ ) TILDE OPERATOR → TILDE #
+
+2368 ; 007E 0308 ; MA #* ( ⍨ → ~̈ ) APL FUNCTIONAL SYMBOL TILDE DIAERESIS → TILDE, COMBINING DIAERESIS #
+
+2E1E ; 007E 0307 ; MA #* ( ⸞ → ~̇ ) TILDE WITH DOT ABOVE → TILDE, COMBINING DOT ABOVE # →⩪→→∼̇→→⁓̇→
+2A6A ; 007E 0307 ; MA #* ( ⩪ → ~̇ ) TILDE OPERATOR WITH DOT ABOVE → TILDE, COMBINING DOT ABOVE # →∼̇→→⁓̇→
+
+2E1F ; 007E 0323 ; MA #* ( ⸟ → ~̣ ) TILDE WITH DOT BELOW → TILDE, COMBINING DOT BELOW #
+
+1E8C8 ; 2220 ; MA #* ( ‎𞣈‎ → ∠ ) MENDE KIKAKUI DIGIT TWO → ANGLE #
+
+22C0 ; 2227 ; MA #* ( ⋀ → ∧ ) N-ARY LOGICAL AND → LOGICAL AND #
+
+222F ; 222E 222E ; MA #* ( ∯ → ∮∮ ) SURFACE INTEGRAL → CONTOUR INTEGRAL, CONTOUR INTEGRAL #
+
+2230 ; 222E 222E 222E ; MA #* ( ∰ → ∮∮∮ ) VOLUME INTEGRAL → CONTOUR INTEGRAL, CONTOUR INTEGRAL, CONTOUR INTEGRAL #
+
+2E2B ; 2234 ; MA #* ( ⸫ → ∴ ) ONE DOT OVER TWO DOTS PUNCTUATION → THEREFORE #
+
+2E2A ; 2235 ; MA #* ( ⸪ → ∵ ) TWO DOTS OVER ONE DOT PUNCTUATION → BECAUSE #
+
+2E2C ; 2237 ; MA #* ( ⸬ → ∷ ) SQUARED FOUR DOT PUNCTUATION → PROPORTION #
+
+111DE ; 2248 ; MA #* ( 𑇞 → ≈ ) SHARADA SECTION MARK-1 → ALMOST EQUAL TO #
+
+264E ; 224F ; MA #* ( ♎ → ≏ ) LIBRA → DIFFERENCE BETWEEN #
+1F75E ; 224F ; MA #* ( 🝞 → ≏ ) ALCHEMICAL SYMBOL FOR SUBLIMATION → DIFFERENCE BETWEEN # →♎→
+
+2263 ; 2261 ; MA #* ( ≣ → ≡ ) STRICTLY EQUIVALENT TO → IDENTICAL TO #
+
+2A03 ; 228D ; MA #* ( ⨃ → ⊍ ) N-ARY UNION OPERATOR WITH DOT → MULTISET MULTIPLICATION #
+
+2A04 ; 228E ; MA #* ( ⨄ → ⊎ ) N-ARY UNION OPERATOR WITH PLUS → MULTISET UNION #
+
+1D238 ; 228F ; MA #* ( 𝈸 → ⊏ ) GREEK INSTRUMENTAL NOTATION SYMBOL-43 → SQUARE IMAGE OF #
+
+1D239 ; 2290 ; MA #* ( 𝈹 → ⊐ ) GREEK INSTRUMENTAL NOTATION SYMBOL-45 → SQUARE ORIGINAL OF #
+
+2A05 ; 2293 ; MA #* ( ⨅ → ⊓ ) N-ARY SQUARE INTERSECTION OPERATOR → SQUARE CAP #
+
+2A06 ; 2294 ; MA #* ( ⨆ → ⊔ ) N-ARY SQUARE UNION OPERATOR → SQUARE CUP #
+
+2A02 ; 2297 ; MA #* ( ⨂ → ⊗ ) N-ARY CIRCLED TIMES OPERATOR → CIRCLED TIMES #
+
+235F ; 229B ; MA #* ( ⍟ → ⊛ ) APL FUNCTIONAL SYMBOL CIRCLE STAR → CIRCLED ASTERISK OPERATOR #
+
+1F771 ; 22A0 ; MA #* ( 🝱 → ⊠ ) ALCHEMICAL SYMBOL FOR MONTH → SQUARED TIMES #
+
+1F755 ; 22A1 ; MA #* ( 🝕 → ⊡ ) ALCHEMICAL SYMBOL FOR URINE → SQUARED DOT OPERATOR #
+
+25C1 ; 22B2 ; MA #* ( ◁ → ⊲ ) WHITE LEFT-POINTING TRIANGLE → NORMAL SUBGROUP OF #
+
+25B7 ; 22B3 ; MA #* ( ▷ → ⊳ ) WHITE RIGHT-POINTING TRIANGLE → CONTAINS AS NORMAL SUBGROUP #
+
+2363 ; 22C6 0308 ; MA #* ( ⍣ → ⋆̈ ) APL FUNCTIONAL SYMBOL STAR DIAERESIS → STAR OPERATOR, COMBINING DIAERESIS #
+
+FE34 ; 2307 ; MA # ( ︴ → ⌇ ) PRESENTATION FORM FOR VERTICAL WAVY LOW LINE → WAVY LINE #
+
+25E0 ; 2312 ; MA #* ( ◠ → ⌒ ) UPPER HALF CIRCLE → ARC #
+
+2A3D ; 2319 ; MA #* ( ⨽ → ⌙ ) RIGHTHAND INTERIOR PRODUCT → TURNED NOT SIGN #
+
+2325 ; 2324 ; MA #* ( ⌥ → ⌤ ) OPTION KEY → UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS #
+
+29C7 ; 233B ; MA #* ( ⧇ → ⌻ ) SQUARED SMALL CIRCLE → APL FUNCTIONAL SYMBOL QUAD JOT #
+
+25CE ; 233E ; MA #* ( ◎ → ⌾ ) BULLSEYE → APL FUNCTIONAL SYMBOL CIRCLE JOT # →⦾→
+29BE ; 233E ; MA #* ( ⦾ → ⌾ ) CIRCLED WHITE BULLET → APL FUNCTIONAL SYMBOL CIRCLE JOT #
+
+29C5 ; 2342 ; MA #* ( ⧅ → ⍂ ) SQUARED FALLING DIAGONAL SLASH → APL FUNCTIONAL SYMBOL QUAD BACKSLASH #
+
+29B0 ; 2349 ; MA #* ( ⦰ → ⍉ ) REVERSED EMPTY SET → APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH #
+
+23C3 ; 234B ; MA #* ( ⏃ → ⍋ ) DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE → APL FUNCTIONAL SYMBOL DELTA STILE #
+
+23C2 ; 234E ; MA #* ( ⏂ → ⍎ ) DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE → APL FUNCTIONAL SYMBOL DOWN TACK JOT #
+
+23C1 ; 2355 ; MA #* ( ⏁ → ⍕ ) DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE → APL FUNCTIONAL SYMBOL UP TACK JOT #
+
+23C6 ; 236D ; MA #* ( ⏆ → ⍭ ) DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE → APL FUNCTIONAL SYMBOL STILE TILDE #
+
+2638 ; 2388 ; MA #* ( ☸ → ⎈ ) WHEEL OF DHARMA → HELM SYMBOL #
+
+FE35 ; 23DC ; MA #* ( ︵ → ⏜ ) PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS → TOP PARENTHESIS #
+
+FE36 ; 23DD ; MA #* ( ︶ → ⏝ ) PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS → BOTTOM PARENTHESIS #
+
+FE37 ; 23DE ; MA #* ( ︷ → ⏞ ) PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET → TOP CURLY BRACKET #
+
+FE38 ; 23DF ; MA #* ( ︸ → ⏟ ) PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET → BOTTOM CURLY BRACKET #
+
+FE39 ; 23E0 ; MA #* ( ︹ → ⏠ ) PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET → TOP TORTOISE SHELL BRACKET #
+
+FE3A ; 23E1 ; MA #* ( ︺ → ⏡ ) PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET → BOTTOM TORTOISE SHELL BRACKET #
+
+25B1 ; 23E5 ; MA #* ( ▱ → ⏥ ) WHITE PARALLELOGRAM → FLATNESS #
+
+23FC ; 23FB ; MA #* ( ⏼ → ⏻ ) POWER ON-OFF SYMBOL → POWER SYMBOL #
+
+FE31 ; 2502 ; MA #* ( ︱ → │ ) PRESENTATION FORM FOR VERTICAL EM DASH → BOX DRAWINGS LIGHT VERTICAL # →|→
+FF5C ; 2502 ; MA #* ( | → │ ) FULLWIDTH VERTICAL LINE → BOX DRAWINGS LIGHT VERTICAL #
+2503 ; 2502 ; MA #* ( ┃ → │ ) BOX DRAWINGS HEAVY VERTICAL → BOX DRAWINGS LIGHT VERTICAL #
+
+250F ; 250C ; MA #* ( ┏ → ┌ ) BOX DRAWINGS HEAVY DOWN AND RIGHT → BOX DRAWINGS LIGHT DOWN AND RIGHT #
+
+2523 ; 251C ; MA #* ( ┣ → ├ ) BOX DRAWINGS HEAVY VERTICAL AND RIGHT → BOX DRAWINGS LIGHT VERTICAL AND RIGHT #
+
+2590 ; 258C ; MA #* ( ▐ → ▌ ) RIGHT HALF BLOCK → LEFT HALF BLOCK #
+
+2597 ; 2596 ; MA #* ( ▗ → ▖ ) QUADRANT LOWER RIGHT → QUADRANT LOWER LEFT #
+
+259D ; 2598 ; MA #* ( ▝ → ▘ ) QUADRANT UPPER RIGHT → QUADRANT UPPER LEFT #
+
+2610 ; 25A1 ; MA #* ( ☐ → □ ) BALLOT BOX → WHITE SQUARE #
+
+FFED ; 25AA ; MA #* ( ■ → ▪ ) HALFWIDTH BLACK SQUARE → BLACK SMALL SQUARE #
+
+25B8 ; 25B6 ; MA #* ( ▸ → ▶ ) BLACK RIGHT-POINTING SMALL TRIANGLE → BLACK RIGHT-POINTING TRIANGLE # →►→
+25BA ; 25B6 ; MA #* ( ► → ▶ ) BLACK RIGHT-POINTING POINTER → BLACK RIGHT-POINTING TRIANGLE #
+
+2CE9 ; 2627 ; MA #* ( ⳩ → ☧ ) COPTIC SYMBOL KHI RO → CHI RHO #
+
+1F70A ; 2629 ; MA #* ( 🜊 → ☩ ) ALCHEMICAL SYMBOL FOR VINEGAR → CROSS OF JERUSALEM #
+
+1F312 ; 263D ; MA #* ( 🌒 → ☽ ) WAXING CRESCENT MOON SYMBOL → FIRST QUARTER MOON #
+1F319 ; 263D ; MA #* ( 🌙 → ☽ ) CRESCENT MOON → FIRST QUARTER MOON #
+
+23FE ; 263E ; MA #* ( ⏾ → ☾ ) POWER SLEEP SYMBOL → LAST QUARTER MOON #
+1F318 ; 263E ; MA #* ( 🌘 → ☾ ) WANING CRESCENT MOON SYMBOL → LAST QUARTER MOON #
+
+29D9 ; 299A ; MA #* ( ⧙ → ⦚ ) RIGHT WIGGLY FENCE → VERTICAL ZIGZAG LINE #
+
+1F73A ; 29DF ; MA #* ( 🜺 → ⧟ ) ALCHEMICAL SYMBOL FOR ARSENIC → DOUBLE-ENDED MULTIMAP #
+
+2A3E ; 2A1F ; MA #* ( ⨾ → ⨟ ) Z NOTATION RELATIONAL COMPOSITION → Z NOTATION SCHEMA COMPOSITION #
+
+101A0 ; 2CE8 ; MA #* ( 𐆠 → ⳨ ) GREEK SYMBOL TAU RHO → COPTIC SYMBOL TAU RO #
+
+2669 ; 1D158 1D165 ; MA #* ( ♩ → 𝅘𝅥 ) QUARTER NOTE → MUSICAL SYMBOL NOTEHEAD BLACK, MUSICAL SYMBOL COMBINING STEM #
+
+266A ; 1D158 1D165 1D16E ; MA #* ( ♪ → 𝅘𝅥𝅮 ) EIGHTH NOTE → MUSICAL SYMBOL NOTEHEAD BLACK, MUSICAL SYMBOL COMBINING STEM, MUSICAL SYMBOL COMBINING FLAG-1 #
+
+24EA ; 1F10D ; MA #* ( ⓪ → 🄍 ) CIRCLED DIGIT ZERO → CIRCLED ZERO WITH SLASH #
+
+21BA ; 1F10E ; MA #* ( ↺ → 🄎 ) ANTICLOCKWISE OPEN CIRCLE ARROW → CIRCLED ANTICLOCKWISE ARROW #
+
+02D9 ; 0971 ; MA #* ( ˙ → ॱ ) DOT ABOVE → DEVANAGARI SIGN HIGH SPACING DOT #
+0D4E ; 0971 ; MA # ( ൎ → ॱ ) MALAYALAM LETTER DOT REPH → DEVANAGARI SIGN HIGH SPACING DOT # →˙→
+
+FF0D ; 30FC ; MA #* ( - → ー ) FULLWIDTH HYPHEN-MINUS → KATAKANA-HIRAGANA PROLONGED SOUND MARK #
+2014 ; 30FC ; MA #* ( — → ー ) EM DASH → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →一→
+2015 ; 30FC ; MA #* ( ― → ー ) HORIZONTAL BAR → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →—→→一→
+2500 ; 30FC ; MA #* ( ─ → ー ) BOX DRAWINGS LIGHT HORIZONTAL → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →━→→—→→一→
+2501 ; 30FC ; MA #* ( ━ → ー ) BOX DRAWINGS HEAVY HORIZONTAL → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →—→→一→
+31D0 ; 30FC ; MA #* ( ㇐ → ー ) CJK STROKE H → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →一→
+A7F7 ; 30FC ; MA # ( ꟷ → ー ) LATIN EPIGRAPHIC LETTER SIDEWAYS I → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →—→→一→
+1173 ; 30FC ; MA # ( ᅳ → ー ) HANGUL JUNGSEONG EU → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ㅡ→→—→→一→
+3161 ; 30FC ; MA # ( ㅡ → ー ) HANGUL LETTER EU → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →—→→一→
+4E00 ; 30FC ; MA # ( 一 → ー ) CJK UNIFIED IDEOGRAPH-4E00 → KATAKANA-HIRAGANA PROLONGED SOUND MARK #
+2F00 ; 30FC ; MA #* ( ⼀ → ー ) KANGXI RADICAL ONE → KATAKANA-HIRAGANA PROLONGED SOUND MARK # →一→
+
+1196 ; 30FC 30FC ; MA # ( ᆖ → ーー ) HANGUL JUNGSEONG EU-EU → KATAKANA-HIRAGANA PROLONGED SOUND MARK, KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ᅳᅳ→
+
+D7B9 ; 30FC 1161 ; MA # ( ힹ → ーᅡ ) HANGUL JUNGSEONG EU-A → KATAKANA-HIRAGANA PROLONGED SOUND MARK, HANGUL JUNGSEONG A # →ᅳᅡ→
+
+D7BA ; 30FC 1165 ; MA # ( ힺ → ーᅥ ) HANGUL JUNGSEONG EU-EO → KATAKANA-HIRAGANA PROLONGED SOUND MARK, HANGUL JUNGSEONG EO # →ᅳᅥ→
+
+D7BB ; 30FC 1165 4E28 ; MA # ( ힻ → ーᅥ丨 ) HANGUL JUNGSEONG EU-E → KATAKANA-HIRAGANA PROLONGED SOUND MARK, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅳᅥᅵ→
+
+D7BC ; 30FC 1169 ; MA # ( ힼ → ーᅩ ) HANGUL JUNGSEONG EU-O → KATAKANA-HIRAGANA PROLONGED SOUND MARK, HANGUL JUNGSEONG O # →ᅳᅩ→
+
+1195 ; 30FC 116E ; MA # ( ᆕ → ーᅮ ) HANGUL JUNGSEONG EU-U → KATAKANA-HIRAGANA PROLONGED SOUND MARK, HANGUL JUNGSEONG U # →ᅳᅮ→
+
+1174 ; 30FC 4E28 ; MA # ( ᅴ → ー丨 ) HANGUL JUNGSEONG YI → KATAKANA-HIRAGANA PROLONGED SOUND MARK, CJK UNIFIED IDEOGRAPH-4E28 # →ᅳᅵ→
+3162 ; 30FC 4E28 ; MA # ( ㅢ → ー丨 ) HANGUL LETTER YI → KATAKANA-HIRAGANA PROLONGED SOUND MARK, CJK UNIFIED IDEOGRAPH-4E28 # →ᅴ→→ᅳᅵ→
+
+1197 ; 30FC 4E28 116E ; MA # ( ᆗ → ー丨ᅮ ) HANGUL JUNGSEONG YI-U → KATAKANA-HIRAGANA PROLONGED SOUND MARK, CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG U # →ᅳᅵᅮ→
+
+1F10F ; 0024 20E0 ; MA #* ( 🄏 → $⃠ ) CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH → DOLLAR SIGN, COMBINING ENCLOSING CIRCLE BACKSLASH #
+
+20A4 ; 00A3 ; MA #* ( ₤ → £ ) LIRA SIGN → POUND SIGN #
+
+3012 ; 20B8 ; MA #* ( 〒 → ₸ ) POSTAL MARK → TENGE SIGN #
+3036 ; 20B8 ; MA #* ( 〶 → ₸ ) CIRCLED POSTAL MARK → TENGE SIGN # →〒→
+
+1B5C ; 1B50 ; MA #* ( ᭜ → ᭐ ) BALINESE WINDU → BALINESE DIGIT ZERO #
+
+A9C6 ; A9D0 ; MA #* ( ꧆ → ꧐ ) JAVANESE PADA WINDU → JAVANESE DIGIT ZERO #
+
+114D1 ; 09E7 ; MA # ( 𑓑 → ১ ) TIRHUTA DIGIT ONE → BENGALI DIGIT ONE #
+
+0CE7 ; 0C67 ; MA # ( ೧ → ౧ ) KANNADA DIGIT ONE → TELUGU DIGIT ONE #
+
+1065 ; 1041 ; MA # ( ၥ → ၁ ) MYANMAR LETTER WESTERN PWO KAREN THA → MYANMAR DIGIT ONE #
+
+2460 ; 2780 ; MA #* ( ① → ➀ ) CIRCLED DIGIT ONE → DINGBAT CIRCLED SANS-SERIF DIGIT ONE #
+
+2469 ; 2789 ; MA #* ( ⑩ → ➉ ) CIRCLED NUMBER TEN → DINGBAT CIRCLED SANS-SERIF NUMBER TEN #
+
+23E8 ; 2081 2080 ; MA #* ( ⏨ → ₁₀ ) DECIMAL EXPONENT SYMBOL → SUBSCRIPT ONE, SUBSCRIPT ZERO #
+
+1D7D0 ; 0032 ; MA # ( 𝟐 → 2 ) MATHEMATICAL BOLD DIGIT TWO → DIGIT TWO #
+1D7DA ; 0032 ; MA # ( 𝟚 → 2 ) MATHEMATICAL DOUBLE-STRUCK DIGIT TWO → DIGIT TWO #
+1D7E4 ; 0032 ; MA # ( 𝟤 → 2 ) MATHEMATICAL SANS-SERIF DIGIT TWO → DIGIT TWO #
+1D7EE ; 0032 ; MA # ( 𝟮 → 2 ) MATHEMATICAL SANS-SERIF BOLD DIGIT TWO → DIGIT TWO #
+1D7F8 ; 0032 ; MA # ( 𝟸 → 2 ) MATHEMATICAL MONOSPACE DIGIT TWO → DIGIT TWO #
+1FBF2 ; 0032 ; MA # ( 🯲 → 2 ) SEGMENTED DIGIT TWO → DIGIT TWO #
+A75A ; 0032 ; MA # ( Ꝛ → 2 ) LATIN CAPITAL LETTER R ROTUNDA → DIGIT TWO #
+01A7 ; 0032 ; MA # ( Ƨ → 2 ) LATIN CAPITAL LETTER TONE TWO → DIGIT TWO #
+03E8 ; 0032 ; MA # ( Ϩ → 2 ) COPTIC CAPITAL LETTER HORI → DIGIT TWO # →Ƨ→
+A644 ; 0032 ; MA # ( Ꙅ → 2 ) CYRILLIC CAPITAL LETTER REVERSED DZE → DIGIT TWO # →Ƨ→
+14BF ; 0032 ; MA # ( ᒿ → 2 ) CANADIAN SYLLABICS SAYISI M → DIGIT TWO #
+A6EF ; 0032 ; MA # ( ꛯ → 2 ) BAMUM LETTER KOGHOM → DIGIT TWO # →Ƨ→
+
+A9CF ; 0662 ; MA # ( ꧏ → ‎٢‎ ) JAVANESE PANGRANGKEP → ARABIC-INDIC DIGIT TWO #
+06F2 ; 0662 ; MA # ( ۲ → ‎٢‎ ) EXTENDED ARABIC-INDIC DIGIT TWO → ARABIC-INDIC DIGIT TWO #
+
+0AE8 ; 0968 ; MA # ( ૨ → २ ) GUJARATI DIGIT TWO → DEVANAGARI DIGIT TWO #
+
+114D2 ; 09E8 ; MA # ( 𑓒 → ২ ) TIRHUTA DIGIT TWO → BENGALI DIGIT TWO #
+
+0CE8 ; 0C68 ; MA # ( ೨ → ౨ ) KANNADA DIGIT TWO → TELUGU DIGIT TWO #
+
+2461 ; 2781 ; MA #* ( ② → ➁ ) CIRCLED DIGIT TWO → DINGBAT CIRCLED SANS-SERIF DIGIT TWO #
+
+01BB ; 0032 0335 ; MA # ( ƻ → 2̵ ) LATIN LETTER TWO WITH STROKE → DIGIT TWO, COMBINING SHORT STROKE OVERLAY #
+
+1F103 ; 0032 002C ; MA #* ( 🄃 → 2, ) DIGIT TWO COMMA → DIGIT TWO, COMMA #
+
+2489 ; 0032 002E ; MA #* ( ⒉ → 2. ) DIGIT TWO FULL STOP → DIGIT TWO, FULL STOP #
+
+33F5 ; 0032 0032 65E5 ; MA #* ( ㏵ → 22日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO → DIGIT TWO, DIGIT TWO, CJK UNIFIED IDEOGRAPH-65E5 #
+
+336E ; 0032 0032 70B9 ; MA #* ( ㍮ → 22点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO → DIGIT TWO, DIGIT TWO, CJK UNIFIED IDEOGRAPH-70B9 #
+
+33F6 ; 0032 0033 65E5 ; MA #* ( ㏶ → 23日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE → DIGIT TWO, DIGIT THREE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+336F ; 0032 0033 70B9 ; MA #* ( ㍯ → 23点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE → DIGIT TWO, DIGIT THREE, CJK UNIFIED IDEOGRAPH-70B9 #
+
+33F7 ; 0032 0034 65E5 ; MA #* ( ㏷ → 24日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR → DIGIT TWO, DIGIT FOUR, CJK UNIFIED IDEOGRAPH-65E5 #
+
+3370 ; 0032 0034 70B9 ; MA #* ( ㍰ → 24点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR → DIGIT TWO, DIGIT FOUR, CJK UNIFIED IDEOGRAPH-70B9 #
+
+33F8 ; 0032 0035 65E5 ; MA #* ( ㏸ → 25日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE → DIGIT TWO, DIGIT FIVE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+33F9 ; 0032 0036 65E5 ; MA #* ( ㏹ → 26日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX → DIGIT TWO, DIGIT SIX, CJK UNIFIED IDEOGRAPH-65E5 #
+
+33FA ; 0032 0037 65E5 ; MA #* ( ㏺ → 27日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN → DIGIT TWO, DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-65E5 #
+
+33FB ; 0032 0038 65E5 ; MA #* ( ㏻ → 28日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT → DIGIT TWO, DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-65E5 #
+
+33FC ; 0032 0039 65E5 ; MA #* ( ㏼ → 29日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE → DIGIT TWO, DIGIT NINE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+33F4 ; 0032 006C 65E5 ; MA #* ( ㏴ → 2l日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE → DIGIT TWO, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-65E5 # →21日→
+
+336D ; 0032 006C 70B9 ; MA #* ( ㍭ → 2l点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE → DIGIT TWO, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-70B9 # →21点→
+
+249B ; 0032 004F 002E ; MA #* ( ⒛ → 2O. ) NUMBER TWENTY FULL STOP → DIGIT TWO, LATIN CAPITAL LETTER O, FULL STOP # →20.→
+
+33F3 ; 0032 004F 65E5 ; MA #* ( ㏳ → 2O日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY → DIGIT TWO, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-65E5 # →20日→
+
+336C ; 0032 004F 70B9 ; MA #* ( ㍬ → 2O点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY → DIGIT TWO, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-70B9 # →20点→
+
+0DE9 ; 0DE8 0DCF ; MA # ( ෩ → ෨ා ) SINHALA LITH DIGIT THREE → SINHALA LITH DIGIT TWO, SINHALA VOWEL SIGN AELA-PILLA #
+
+0DEF ; 0DE8 0DD3 ; MA # ( ෯ → ෨ී ) SINHALA LITH DIGIT NINE → SINHALA LITH DIGIT TWO, SINHALA VOWEL SIGN DIGA IS-PILLA #
+
+33E1 ; 0032 65E5 ; MA #* ( ㏡ → 2日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO → DIGIT TWO, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C1 ; 0032 6708 ; MA #* ( ㋁ → 2月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY → DIGIT TWO, CJK UNIFIED IDEOGRAPH-6708 #
+
+335A ; 0032 70B9 ; MA #* ( ㍚ → 2点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO → DIGIT TWO, CJK UNIFIED IDEOGRAPH-70B9 #
+
+1D206 ; 0033 ; MA #* ( 𝈆 → 3 ) GREEK VOCAL NOTATION SYMBOL-7 → DIGIT THREE #
+1D7D1 ; 0033 ; MA # ( 𝟑 → 3 ) MATHEMATICAL BOLD DIGIT THREE → DIGIT THREE #
+1D7DB ; 0033 ; MA # ( 𝟛 → 3 ) MATHEMATICAL DOUBLE-STRUCK DIGIT THREE → DIGIT THREE #
+1D7E5 ; 0033 ; MA # ( 𝟥 → 3 ) MATHEMATICAL SANS-SERIF DIGIT THREE → DIGIT THREE #
+1D7EF ; 0033 ; MA # ( 𝟯 → 3 ) MATHEMATICAL SANS-SERIF BOLD DIGIT THREE → DIGIT THREE #
+1D7F9 ; 0033 ; MA # ( 𝟹 → 3 ) MATHEMATICAL MONOSPACE DIGIT THREE → DIGIT THREE #
+1FBF3 ; 0033 ; MA # ( 🯳 → 3 ) SEGMENTED DIGIT THREE → DIGIT THREE #
+A7AB ; 0033 ; MA # ( Ɜ → 3 ) LATIN CAPITAL LETTER REVERSED OPEN E → DIGIT THREE #
+021C ; 0033 ; MA # ( Ȝ → 3 ) LATIN CAPITAL LETTER YOGH → DIGIT THREE # →Ʒ→
+01B7 ; 0033 ; MA # ( Ʒ → 3 ) LATIN CAPITAL LETTER EZH → DIGIT THREE #
+A76A ; 0033 ; MA # ( Ꝫ → 3 ) LATIN CAPITAL LETTER ET → DIGIT THREE #
+2CCC ; 0033 ; MA # ( Ⳍ → 3 ) COPTIC CAPITAL LETTER OLD COPTIC HORI → DIGIT THREE # →Ȝ→→Ʒ→
+0417 ; 0033 ; MA # ( З → 3 ) CYRILLIC CAPITAL LETTER ZE → DIGIT THREE #
+04E0 ; 0033 ; MA # ( Ӡ → 3 ) CYRILLIC CAPITAL LETTER ABKHASIAN DZE → DIGIT THREE # →Ʒ→
+16F3B ; 0033 ; MA # ( 𖼻 → 3 ) MIAO LETTER ZA → DIGIT THREE # →Ʒ→
+118CA ; 0033 ; MA # ( 𑣊 → 3 ) WARANG CITI SMALL LETTER ANG → DIGIT THREE #
+
+06F3 ; 0663 ; MA # ( ۳ → ‎٣‎ ) EXTENDED ARABIC-INDIC DIGIT THREE → ARABIC-INDIC DIGIT THREE #
+1E8C9 ; 0663 ; MA #* ( ‎𞣉‎ → ‎٣‎ ) MENDE KIKAKUI DIGIT THREE → ARABIC-INDIC DIGIT THREE #
+
+0AE9 ; 0969 ; MA # ( ૩ → ३ ) GUJARATI DIGIT THREE → DEVANAGARI DIGIT THREE #
+
+2462 ; 2782 ; MA #* ( ③ → ➂ ) CIRCLED DIGIT THREE → DINGBAT CIRCLED SANS-SERIF DIGIT THREE #
+
+0498 ; 0033 0326 ; MA # ( Ҙ → 3̦ ) CYRILLIC CAPITAL LETTER ZE WITH DESCENDER → DIGIT THREE, COMBINING COMMA BELOW # →З̧→
+
+1F104 ; 0033 002C ; MA #* ( 🄄 → 3, ) DIGIT THREE COMMA → DIGIT THREE, COMMA #
+
+248A ; 0033 002E ; MA #* ( ⒊ → 3. ) DIGIT THREE FULL STOP → DIGIT THREE, FULL STOP #
+
+33FE ; 0033 006C 65E5 ; MA #* ( ㏾ → 3l日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE → DIGIT THREE, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-65E5 # →31日→
+
+33FD ; 0033 004F 65E5 ; MA #* ( ㏽ → 3O日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY → DIGIT THREE, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-65E5 # →30日→
+
+33E2 ; 0033 65E5 ; MA #* ( ㏢ → 3日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE → DIGIT THREE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C2 ; 0033 6708 ; MA #* ( ㋂ → 3月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH → DIGIT THREE, CJK UNIFIED IDEOGRAPH-6708 #
+
+335B ; 0033 70B9 ; MA #* ( ㍛ → 3点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE → DIGIT THREE, CJK UNIFIED IDEOGRAPH-70B9 #
+
+1D7D2 ; 0034 ; MA # ( 𝟒 → 4 ) MATHEMATICAL BOLD DIGIT FOUR → DIGIT FOUR #
+1D7DC ; 0034 ; MA # ( 𝟜 → 4 ) MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR → DIGIT FOUR #
+1D7E6 ; 0034 ; MA # ( 𝟦 → 4 ) MATHEMATICAL SANS-SERIF DIGIT FOUR → DIGIT FOUR #
+1D7F0 ; 0034 ; MA # ( 𝟰 → 4 ) MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR → DIGIT FOUR #
+1D7FA ; 0034 ; MA # ( 𝟺 → 4 ) MATHEMATICAL MONOSPACE DIGIT FOUR → DIGIT FOUR #
+1FBF4 ; 0034 ; MA # ( 🯴 → 4 ) SEGMENTED DIGIT FOUR → DIGIT FOUR #
+13CE ; 0034 ; MA # ( Ꮞ → 4 ) CHEROKEE LETTER SE → DIGIT FOUR #
+118AF ; 0034 ; MA # ( 𑢯 → 4 ) WARANG CITI CAPITAL LETTER UC → DIGIT FOUR #
+
+06F4 ; 0664 ; MA # ( ۴ → ‎٤‎ ) EXTENDED ARABIC-INDIC DIGIT FOUR → ARABIC-INDIC DIGIT FOUR #
+
+0AEA ; 096A ; MA # ( ૪ → ४ ) GUJARATI DIGIT FOUR → DEVANAGARI DIGIT FOUR #
+
+2463 ; 2783 ; MA #* ( ④ → ➃ ) CIRCLED DIGIT FOUR → DINGBAT CIRCLED SANS-SERIF DIGIT FOUR #
+
+1F105 ; 0034 002C ; MA #* ( 🄅 → 4, ) DIGIT FOUR COMMA → DIGIT FOUR, COMMA #
+
+248B ; 0034 002E ; MA #* ( ⒋ → 4. ) DIGIT FOUR FULL STOP → DIGIT FOUR, FULL STOP #
+
+1530 ; 0034 00B7 ; MA # ( ᔰ → 4· ) CANADIAN SYLLABICS WEST-CREE YWE → DIGIT FOUR, MIDDLE DOT # →4ᐧ→
+
+33E3 ; 0034 65E5 ; MA #* ( ㏣ → 4日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR → DIGIT FOUR, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C3 ; 0034 6708 ; MA #* ( ㋃ → 4月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL → DIGIT FOUR, CJK UNIFIED IDEOGRAPH-6708 #
+
+335C ; 0034 70B9 ; MA #* ( ㍜ → 4点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR → DIGIT FOUR, CJK UNIFIED IDEOGRAPH-70B9 #
+
+1D7D3 ; 0035 ; MA # ( 𝟓 → 5 ) MATHEMATICAL BOLD DIGIT FIVE → DIGIT FIVE #
+1D7DD ; 0035 ; MA # ( 𝟝 → 5 ) MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE → DIGIT FIVE #
+1D7E7 ; 0035 ; MA # ( 𝟧 → 5 ) MATHEMATICAL SANS-SERIF DIGIT FIVE → DIGIT FIVE #
+1D7F1 ; 0035 ; MA # ( 𝟱 → 5 ) MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE → DIGIT FIVE #
+1D7FB ; 0035 ; MA # ( 𝟻 → 5 ) MATHEMATICAL MONOSPACE DIGIT FIVE → DIGIT FIVE #
+1FBF5 ; 0035 ; MA # ( 🯵 → 5 ) SEGMENTED DIGIT FIVE → DIGIT FIVE #
+01BC ; 0035 ; MA # ( Ƽ → 5 ) LATIN CAPITAL LETTER TONE FIVE → DIGIT FIVE #
+118BB ; 0035 ; MA # ( 𑢻 → 5 ) WARANG CITI CAPITAL LETTER HORR → DIGIT FIVE #
+
+2464 ; 2784 ; MA #* ( ⑤ → ➄ ) CIRCLED DIGIT FIVE → DINGBAT CIRCLED SANS-SERIF DIGIT FIVE #
+
+1F106 ; 0035 002C ; MA #* ( 🄆 → 5, ) DIGIT FIVE COMMA → DIGIT FIVE, COMMA #
+
+248C ; 0035 002E ; MA #* ( ⒌ → 5. ) DIGIT FIVE FULL STOP → DIGIT FIVE, FULL STOP #
+
+33E4 ; 0035 65E5 ; MA #* ( ㏤ → 5日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE → DIGIT FIVE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C4 ; 0035 6708 ; MA #* ( ㋄ → 5月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY → DIGIT FIVE, CJK UNIFIED IDEOGRAPH-6708 #
+
+335D ; 0035 70B9 ; MA #* ( ㍝ → 5点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE → DIGIT FIVE, CJK UNIFIED IDEOGRAPH-70B9 #
+
+1D7D4 ; 0036 ; MA # ( 𝟔 → 6 ) MATHEMATICAL BOLD DIGIT SIX → DIGIT SIX #
+1D7DE ; 0036 ; MA # ( 𝟞 → 6 ) MATHEMATICAL DOUBLE-STRUCK DIGIT SIX → DIGIT SIX #
+1D7E8 ; 0036 ; MA # ( 𝟨 → 6 ) MATHEMATICAL SANS-SERIF DIGIT SIX → DIGIT SIX #
+1D7F2 ; 0036 ; MA # ( 𝟲 → 6 ) MATHEMATICAL SANS-SERIF BOLD DIGIT SIX → DIGIT SIX #
+1D7FC ; 0036 ; MA # ( 𝟼 → 6 ) MATHEMATICAL MONOSPACE DIGIT SIX → DIGIT SIX #
+1FBF6 ; 0036 ; MA # ( 🯶 → 6 ) SEGMENTED DIGIT SIX → DIGIT SIX #
+2CD2 ; 0036 ; MA # ( Ⳓ → 6 ) COPTIC CAPITAL LETTER OLD COPTIC HEI → DIGIT SIX #
+0431 ; 0036 ; MA # ( б → 6 ) CYRILLIC SMALL LETTER BE → DIGIT SIX #
+13EE ; 0036 ; MA # ( Ꮾ → 6 ) CHEROKEE LETTER WV → DIGIT SIX #
+118D5 ; 0036 ; MA # ( 𑣕 → 6 ) WARANG CITI SMALL LETTER AT → DIGIT SIX #
+
+06F6 ; 0666 ; MA # ( ۶ → ‎٦‎ ) EXTENDED ARABIC-INDIC DIGIT SIX → ARABIC-INDIC DIGIT SIX #
+
+114D6 ; 09EC ; MA # ( 𑓖 → ৬ ) TIRHUTA DIGIT SIX → BENGALI DIGIT SIX #
+
+2465 ; 2785 ; MA #* ( ⑥ → ➅ ) CIRCLED DIGIT SIX → DINGBAT CIRCLED SANS-SERIF DIGIT SIX #
+
+1F107 ; 0036 002C ; MA #* ( 🄇 → 6, ) DIGIT SIX COMMA → DIGIT SIX, COMMA #
+
+248D ; 0036 002E ; MA #* ( ⒍ → 6. ) DIGIT SIX FULL STOP → DIGIT SIX, FULL STOP #
+
+33E5 ; 0036 65E5 ; MA #* ( ㏥ → 6日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX → DIGIT SIX, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C5 ; 0036 6708 ; MA #* ( ㋅ → 6月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE → DIGIT SIX, CJK UNIFIED IDEOGRAPH-6708 #
+
+335E ; 0036 70B9 ; MA #* ( ㍞ → 6点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX → DIGIT SIX, CJK UNIFIED IDEOGRAPH-70B9 #
+
+1D212 ; 0037 ; MA #* ( 𝈒 → 7 ) GREEK VOCAL NOTATION SYMBOL-19 → DIGIT SEVEN #
+1D7D5 ; 0037 ; MA # ( 𝟕 → 7 ) MATHEMATICAL BOLD DIGIT SEVEN → DIGIT SEVEN #
+1D7DF ; 0037 ; MA # ( 𝟟 → 7 ) MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN → DIGIT SEVEN #
+1D7E9 ; 0037 ; MA # ( 𝟩 → 7 ) MATHEMATICAL SANS-SERIF DIGIT SEVEN → DIGIT SEVEN #
+1D7F3 ; 0037 ; MA # ( 𝟳 → 7 ) MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN → DIGIT SEVEN #
+1D7FD ; 0037 ; MA # ( 𝟽 → 7 ) MATHEMATICAL MONOSPACE DIGIT SEVEN → DIGIT SEVEN #
+1FBF7 ; 0037 ; MA # ( 🯷 → 7 ) SEGMENTED DIGIT SEVEN → DIGIT SEVEN #
+104D2 ; 0037 ; MA # ( 𐓒 → 7 ) OSAGE CAPITAL LETTER ZA → DIGIT SEVEN #
+118C6 ; 0037 ; MA # ( 𑣆 → 7 ) WARANG CITI SMALL LETTER II → DIGIT SEVEN #
+
+2466 ; 2786 ; MA #* ( ⑦ → ➆ ) CIRCLED DIGIT SEVEN → DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN #
+
+1F108 ; 0037 002C ; MA #* ( 🄈 → 7, ) DIGIT SEVEN COMMA → DIGIT SEVEN, COMMA #
+
+248E ; 0037 002E ; MA #* ( ⒎ → 7. ) DIGIT SEVEN FULL STOP → DIGIT SEVEN, FULL STOP #
+
+33E6 ; 0037 65E5 ; MA #* ( ㏦ → 7日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN → DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C6 ; 0037 6708 ; MA #* ( ㋆ → 7月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY → DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-6708 #
+
+335F ; 0037 70B9 ; MA #* ( ㍟ → 7点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN → DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-70B9 #
+
+0B03 ; 0038 ; MA # ( ଃ → 8 ) ORIYA SIGN VISARGA → DIGIT EIGHT #
+09EA ; 0038 ; MA # ( ৪ → 8 ) BENGALI DIGIT FOUR → DIGIT EIGHT #
+0A6A ; 0038 ; MA # ( ੪ → 8 ) GURMUKHI DIGIT FOUR → DIGIT EIGHT #
+1E8CB ; 0038 ; MA #* ( ‎𞣋‎ → 8 ) MENDE KIKAKUI DIGIT FIVE → DIGIT EIGHT #
+1D7D6 ; 0038 ; MA # ( 𝟖 → 8 ) MATHEMATICAL BOLD DIGIT EIGHT → DIGIT EIGHT #
+1D7E0 ; 0038 ; MA # ( 𝟠 → 8 ) MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT → DIGIT EIGHT #
+1D7EA ; 0038 ; MA # ( 𝟪 → 8 ) MATHEMATICAL SANS-SERIF DIGIT EIGHT → DIGIT EIGHT #
+1D7F4 ; 0038 ; MA # ( 𝟴 → 8 ) MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT → DIGIT EIGHT #
+1D7FE ; 0038 ; MA # ( 𝟾 → 8 ) MATHEMATICAL MONOSPACE DIGIT EIGHT → DIGIT EIGHT #
+1FBF8 ; 0038 ; MA # ( 🯸 → 8 ) SEGMENTED DIGIT EIGHT → DIGIT EIGHT #
+0223 ; 0038 ; MA # ( ȣ → 8 ) LATIN SMALL LETTER OU → DIGIT EIGHT #
+0222 ; 0038 ; MA # ( Ȣ → 8 ) LATIN CAPITAL LETTER OU → DIGIT EIGHT #
+1031A ; 0038 ; MA # ( 𐌚 → 8 ) OLD ITALIC LETTER EF → DIGIT EIGHT #
+
+0AEE ; 096E ; MA # ( ૮ → ८ ) GUJARATI DIGIT EIGHT → DEVANAGARI DIGIT EIGHT #
+
+2467 ; 2787 ; MA #* ( ⑧ → ➇ ) CIRCLED DIGIT EIGHT → DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT #
+
+1F109 ; 0038 002C ; MA #* ( 🄉 → 8, ) DIGIT EIGHT COMMA → DIGIT EIGHT, COMMA #
+
+248F ; 0038 002E ; MA #* ( ⒏ → 8. ) DIGIT EIGHT FULL STOP → DIGIT EIGHT, FULL STOP #
+
+33E7 ; 0038 65E5 ; MA #* ( ㏧ → 8日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT → DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C7 ; 0038 6708 ; MA #* ( ㋇ → 8月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST → DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-6708 #
+
+3360 ; 0038 70B9 ; MA #* ( ㍠ → 8点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT → DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-70B9 #
+
+0A67 ; 0039 ; MA # ( ੧ → 9 ) GURMUKHI DIGIT ONE → DIGIT NINE #
+0B68 ; 0039 ; MA # ( ୨ → 9 ) ORIYA DIGIT TWO → DIGIT NINE #
+09ED ; 0039 ; MA # ( ৭ → 9 ) BENGALI DIGIT SEVEN → DIGIT NINE #
+0D6D ; 0039 ; MA # ( ൭ → 9 ) MALAYALAM DIGIT SEVEN → DIGIT NINE #
+1D7D7 ; 0039 ; MA # ( 𝟗 → 9 ) MATHEMATICAL BOLD DIGIT NINE → DIGIT NINE #
+1D7E1 ; 0039 ; MA # ( 𝟡 → 9 ) MATHEMATICAL DOUBLE-STRUCK DIGIT NINE → DIGIT NINE #
+1D7EB ; 0039 ; MA # ( 𝟫 → 9 ) MATHEMATICAL SANS-SERIF DIGIT NINE → DIGIT NINE #
+1D7F5 ; 0039 ; MA # ( 𝟵 → 9 ) MATHEMATICAL SANS-SERIF BOLD DIGIT NINE → DIGIT NINE #
+1D7FF ; 0039 ; MA # ( 𝟿 → 9 ) MATHEMATICAL MONOSPACE DIGIT NINE → DIGIT NINE #
+1FBF9 ; 0039 ; MA # ( 🯹 → 9 ) SEGMENTED DIGIT NINE → DIGIT NINE #
+A76E ; 0039 ; MA # ( Ꝯ → 9 ) LATIN CAPITAL LETTER CON → DIGIT NINE #
+2CCA ; 0039 ; MA # ( Ⳋ → 9 ) COPTIC CAPITAL LETTER DIALECT-P HORI → DIGIT NINE #
+118CC ; 0039 ; MA # ( 𑣌 → 9 ) WARANG CITI SMALL LETTER KO → DIGIT NINE #
+118AC ; 0039 ; MA # ( 𑢬 → 9 ) WARANG CITI CAPITAL LETTER KO → DIGIT NINE #
+118D6 ; 0039 ; MA # ( 𑣖 → 9 ) WARANG CITI SMALL LETTER AM → DIGIT NINE #
+
+0967 ; 0669 ; MA # ( १ → ‎٩‎ ) DEVANAGARI DIGIT ONE → ARABIC-INDIC DIGIT NINE #
+118E4 ; 0669 ; MA # ( 𑣤 → ‎٩‎ ) WARANG CITI DIGIT FOUR → ARABIC-INDIC DIGIT NINE #
+06F9 ; 0669 ; MA # ( ۹ → ‎٩‎ ) EXTENDED ARABIC-INDIC DIGIT NINE → ARABIC-INDIC DIGIT NINE #
+
+0CEF ; 0C6F ; MA # ( ೯ → ౯ ) KANNADA DIGIT NINE → TELUGU DIGIT NINE #
+
+2468 ; 2788 ; MA #* ( ⑨ → ➈ ) CIRCLED DIGIT NINE → DINGBAT CIRCLED SANS-SERIF DIGIT NINE #
+
+1F10A ; 0039 002C ; MA #* ( 🄊 → 9, ) DIGIT NINE COMMA → DIGIT NINE, COMMA #
+
+2490 ; 0039 002E ; MA #* ( ⒐ → 9. ) DIGIT NINE FULL STOP → DIGIT NINE, FULL STOP #
+
+33E8 ; 0039 65E5 ; MA #* ( ㏨ → 9日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE → DIGIT NINE, CJK UNIFIED IDEOGRAPH-65E5 #
+
+32C8 ; 0039 6708 ; MA #* ( ㋈ → 9月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER → DIGIT NINE, CJK UNIFIED IDEOGRAPH-6708 #
+
+3361 ; 0039 70B9 ; MA #* ( ㍡ → 9点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE → DIGIT NINE, CJK UNIFIED IDEOGRAPH-70B9 #
+
+237A ; 0061 ; MA #* ( ⍺ → a ) APL FUNCTIONAL SYMBOL ALPHA → LATIN SMALL LETTER A # →α→
+FF41 ; 0061 ; MA # ( a → a ) FULLWIDTH LATIN SMALL LETTER A → LATIN SMALL LETTER A # →а→
+1D41A ; 0061 ; MA # ( 𝐚 → a ) MATHEMATICAL BOLD SMALL A → LATIN SMALL LETTER A #
+1D44E ; 0061 ; MA # ( 𝑎 → a ) MATHEMATICAL ITALIC SMALL A → LATIN SMALL LETTER A #
+1D482 ; 0061 ; MA # ( 𝒂 → a ) MATHEMATICAL BOLD ITALIC SMALL A → LATIN SMALL LETTER A #
+1D4B6 ; 0061 ; MA # ( 𝒶 → a ) MATHEMATICAL SCRIPT SMALL A → LATIN SMALL LETTER A #
+1D4EA ; 0061 ; MA # ( 𝓪 → a ) MATHEMATICAL BOLD SCRIPT SMALL A → LATIN SMALL LETTER A #
+1D51E ; 0061 ; MA # ( 𝔞 → a ) MATHEMATICAL FRAKTUR SMALL A → LATIN SMALL LETTER A #
+1D552 ; 0061 ; MA # ( 𝕒 → a ) MATHEMATICAL DOUBLE-STRUCK SMALL A → LATIN SMALL LETTER A #
+1D586 ; 0061 ; MA # ( 𝖆 → a ) MATHEMATICAL BOLD FRAKTUR SMALL A → LATIN SMALL LETTER A #
+1D5BA ; 0061 ; MA # ( 𝖺 → a ) MATHEMATICAL SANS-SERIF SMALL A → LATIN SMALL LETTER A #
+1D5EE ; 0061 ; MA # ( 𝗮 → a ) MATHEMATICAL SANS-SERIF BOLD SMALL A → LATIN SMALL LETTER A #
+1D622 ; 0061 ; MA # ( 𝘢 → a ) MATHEMATICAL SANS-SERIF ITALIC SMALL A → LATIN SMALL LETTER A #
+1D656 ; 0061 ; MA # ( 𝙖 → a ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A → LATIN SMALL LETTER A #
+1D68A ; 0061 ; MA # ( 𝚊 → a ) MATHEMATICAL MONOSPACE SMALL A → LATIN SMALL LETTER A #
+0251 ; 0061 ; MA # ( ɑ → a ) LATIN SMALL LETTER ALPHA → LATIN SMALL LETTER A #
+03B1 ; 0061 ; MA # ( α → a ) GREEK SMALL LETTER ALPHA → LATIN SMALL LETTER A #
+1D6C2 ; 0061 ; MA # ( 𝛂 → a ) MATHEMATICAL BOLD SMALL ALPHA → LATIN SMALL LETTER A # →α→
+1D6FC ; 0061 ; MA # ( 𝛼 → a ) MATHEMATICAL ITALIC SMALL ALPHA → LATIN SMALL LETTER A # →α→
+1D736 ; 0061 ; MA # ( 𝜶 → a ) MATHEMATICAL BOLD ITALIC SMALL ALPHA → LATIN SMALL LETTER A # →α→
+1D770 ; 0061 ; MA # ( 𝝰 → a ) MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA → LATIN SMALL LETTER A # →α→
+1D7AA ; 0061 ; MA # ( 𝞪 → a ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA → LATIN SMALL LETTER A # →α→
+0430 ; 0061 ; MA # ( а → a ) CYRILLIC SMALL LETTER A → LATIN SMALL LETTER A #
+
+2DF6 ; 0363 ; MA # ( ⷶ → ͣ ) COMBINING CYRILLIC LETTER A → COMBINING LATIN SMALL LETTER A #
+
+FF21 ; 0041 ; MA # ( A → A ) FULLWIDTH LATIN CAPITAL LETTER A → LATIN CAPITAL LETTER A # →А→
+1D400 ; 0041 ; MA # ( 𝐀 → A ) MATHEMATICAL BOLD CAPITAL A → LATIN CAPITAL LETTER A #
+1D434 ; 0041 ; MA # ( 𝐴 → A ) MATHEMATICAL ITALIC CAPITAL A → LATIN CAPITAL LETTER A #
+1D468 ; 0041 ; MA # ( 𝑨 → A ) MATHEMATICAL BOLD ITALIC CAPITAL A → LATIN CAPITAL LETTER A #
+1D49C ; 0041 ; MA # ( 𝒜 → A ) MATHEMATICAL SCRIPT CAPITAL A → LATIN CAPITAL LETTER A #
+1D4D0 ; 0041 ; MA # ( 𝓐 → A ) MATHEMATICAL BOLD SCRIPT CAPITAL A → LATIN CAPITAL LETTER A #
+1D504 ; 0041 ; MA # ( 𝔄 → A ) MATHEMATICAL FRAKTUR CAPITAL A → LATIN CAPITAL LETTER A #
+1D538 ; 0041 ; MA # ( 𝔸 → A ) MATHEMATICAL DOUBLE-STRUCK CAPITAL A → LATIN CAPITAL LETTER A #
+1D56C ; 0041 ; MA # ( 𝕬 → A ) MATHEMATICAL BOLD FRAKTUR CAPITAL A → LATIN CAPITAL LETTER A #
+1D5A0 ; 0041 ; MA # ( 𝖠 → A ) MATHEMATICAL SANS-SERIF CAPITAL A → LATIN CAPITAL LETTER A #
+1D5D4 ; 0041 ; MA # ( 𝗔 → A ) MATHEMATICAL SANS-SERIF BOLD CAPITAL A → LATIN CAPITAL LETTER A #
+1D608 ; 0041 ; MA # ( 𝘈 → A ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL A → LATIN CAPITAL LETTER A #
+1D63C ; 0041 ; MA # ( 𝘼 → A ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A → LATIN CAPITAL LETTER A #
+1D670 ; 0041 ; MA # ( 𝙰 → A ) MATHEMATICAL MONOSPACE CAPITAL A → LATIN CAPITAL LETTER A #
+0391 ; 0041 ; MA # ( Α → A ) GREEK CAPITAL LETTER ALPHA → LATIN CAPITAL LETTER A #
+1D6A8 ; 0041 ; MA # ( 𝚨 → A ) MATHEMATICAL BOLD CAPITAL ALPHA → LATIN CAPITAL LETTER A # →𝐀→
+1D6E2 ; 0041 ; MA # ( 𝛢 → A ) MATHEMATICAL ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A # →Α→
+1D71C ; 0041 ; MA # ( 𝜜 → A ) MATHEMATICAL BOLD ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A # →Α→
+1D756 ; 0041 ; MA # ( 𝝖 → A ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA → LATIN CAPITAL LETTER A # →Α→
+1D790 ; 0041 ; MA # ( 𝞐 → A ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA → LATIN CAPITAL LETTER A # →Α→
+0410 ; 0041 ; MA # ( А → A ) CYRILLIC CAPITAL LETTER A → LATIN CAPITAL LETTER A #
+13AA ; 0041 ; MA # ( Ꭺ → A ) CHEROKEE LETTER GO → LATIN CAPITAL LETTER A #
+15C5 ; 0041 ; MA # ( ᗅ → A ) CANADIAN SYLLABICS CARRIER GHO → LATIN CAPITAL LETTER A #
+A4EE ; 0041 ; MA # ( ꓮ → A ) LISU LETTER A → LATIN CAPITAL LETTER A #
+16F40 ; 0041 ; MA # ( 𖽀 → A ) MIAO LETTER ZZYA → LATIN CAPITAL LETTER A #
+102A0 ; 0041 ; MA # ( 𐊠 → A ) CARIAN LETTER A → LATIN CAPITAL LETTER A #
+
+2376 ; 0061 0332 ; MA #* ( ⍶ → a̲ ) APL FUNCTIONAL SYMBOL ALPHA UNDERBAR → LATIN SMALL LETTER A, COMBINING LOW LINE # →α̲→→ɑ̲→
+
+01CE ; 0103 ; MA # ( ǎ → ă ) LATIN SMALL LETTER A WITH CARON → LATIN SMALL LETTER A WITH BREVE #
+
+01CD ; 0102 ; MA # ( Ǎ → Ă ) LATIN CAPITAL LETTER A WITH CARON → LATIN CAPITAL LETTER A WITH BREVE #
+
+0227 ; 00E5 ; MA # ( ȧ → å ) LATIN SMALL LETTER A WITH DOT ABOVE → LATIN SMALL LETTER A WITH RING ABOVE #
+
+0226 ; 00C5 ; MA # ( Ȧ → Å ) LATIN CAPITAL LETTER A WITH DOT ABOVE → LATIN CAPITAL LETTER A WITH RING ABOVE #
+
+1E9A ; 1EA3 ; MA # ( ẚ → ả ) LATIN SMALL LETTER A WITH RIGHT HALF RING → LATIN SMALL LETTER A WITH HOOK ABOVE #
+
+2100 ; 0061 002F 0063 ; MA #* ( ℀ → a/c ) ACCOUNT OF → LATIN SMALL LETTER A, SOLIDUS, LATIN SMALL LETTER C #
+
+2101 ; 0061 002F 0073 ; MA #* ( ℁ → a/s ) ADDRESSED TO THE SUBJECT → LATIN SMALL LETTER A, SOLIDUS, LATIN SMALL LETTER S #
+
+A733 ; 0061 0061 ; MA # ( ꜳ → aa ) LATIN SMALL LETTER AA → LATIN SMALL LETTER A, LATIN SMALL LETTER A #
+
+A732 ; 0041 0041 ; MA # ( Ꜳ → AA ) LATIN CAPITAL LETTER AA → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER A #
+
+00E6 ; 0061 0065 ; MA # ( æ → ae ) LATIN SMALL LETTER AE → LATIN SMALL LETTER A, LATIN SMALL LETTER E #
+04D5 ; 0061 0065 ; MA # ( ӕ → ae ) CYRILLIC SMALL LIGATURE A IE → LATIN SMALL LETTER A, LATIN SMALL LETTER E # →ае→
+
+00C6 ; 0041 0045 ; MA # ( Æ → AE ) LATIN CAPITAL LETTER AE → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER E #
+04D4 ; 0041 0045 ; MA # ( Ӕ → AE ) CYRILLIC CAPITAL LIGATURE A IE → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER E # →Æ→
+
+A735 ; 0061 006F ; MA # ( ꜵ → ao ) LATIN SMALL LETTER AO → LATIN SMALL LETTER A, LATIN SMALL LETTER O #
+
+A734 ; 0041 004F ; MA # ( Ꜵ → AO ) LATIN CAPITAL LETTER AO → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER O #
+
+1F707 ; 0041 0052 ; MA #* ( 🜇 → AR ) ALCHEMICAL SYMBOL FOR AQUA REGIA-2 → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER R #
+
+A737 ; 0061 0075 ; MA # ( ꜷ → au ) LATIN SMALL LETTER AU → LATIN SMALL LETTER A, LATIN SMALL LETTER U #
+
+A736 ; 0041 0055 ; MA # ( Ꜷ → AU ) LATIN CAPITAL LETTER AU → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER U #
+
+A739 ; 0061 0076 ; MA # ( ꜹ → av ) LATIN SMALL LETTER AV → LATIN SMALL LETTER A, LATIN SMALL LETTER V #
+A73B ; 0061 0076 ; MA # ( ꜻ → av ) LATIN SMALL LETTER AV WITH HORIZONTAL BAR → LATIN SMALL LETTER A, LATIN SMALL LETTER V #
+
+A738 ; 0041 0056 ; MA # ( Ꜹ → AV ) LATIN CAPITAL LETTER AV → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER V #
+A73A ; 0041 0056 ; MA # ( Ꜻ → AV ) LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER V #
+
+A73D ; 0061 0079 ; MA # ( ꜽ → ay ) LATIN SMALL LETTER AY → LATIN SMALL LETTER A, LATIN SMALL LETTER Y #
+
+A73C ; 0041 0059 ; MA # ( Ꜽ → AY ) LATIN CAPITAL LETTER AY → LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER Y #
+
+AB7A ; 1D00 ; MA # ( ꭺ → ᴀ ) CHEROKEE SMALL LETTER GO → LATIN LETTER SMALL CAPITAL A #
+
+2200 ; 2C6F ; MA #* ( ∀ → Ɐ ) FOR ALL → LATIN CAPITAL LETTER TURNED A #
+1D217 ; 2C6F ; MA #* ( 𝈗 → Ɐ ) GREEK VOCAL NOTATION SYMBOL-24 → LATIN CAPITAL LETTER TURNED A #
+15C4 ; 2C6F ; MA # ( ᗄ → Ɐ ) CANADIAN SYLLABICS CARRIER GHU → LATIN CAPITAL LETTER TURNED A # →∀→
+A4EF ; 2C6F ; MA # ( ꓯ → Ɐ ) LISU LETTER AE → LATIN CAPITAL LETTER TURNED A #
+
+1041F ; 2C70 ; MA # ( 𐐟 → Ɒ ) DESERET CAPITAL LETTER ESH → LATIN CAPITAL LETTER TURNED ALPHA #
+
+1D41B ; 0062 ; MA # ( 𝐛 → b ) MATHEMATICAL BOLD SMALL B → LATIN SMALL LETTER B #
+1D44F ; 0062 ; MA # ( 𝑏 → b ) MATHEMATICAL ITALIC SMALL B → LATIN SMALL LETTER B #
+1D483 ; 0062 ; MA # ( 𝒃 → b ) MATHEMATICAL BOLD ITALIC SMALL B → LATIN SMALL LETTER B #
+1D4B7 ; 0062 ; MA # ( 𝒷 → b ) MATHEMATICAL SCRIPT SMALL B → LATIN SMALL LETTER B #
+1D4EB ; 0062 ; MA # ( 𝓫 → b ) MATHEMATICAL BOLD SCRIPT SMALL B → LATIN SMALL LETTER B #
+1D51F ; 0062 ; MA # ( 𝔟 → b ) MATHEMATICAL FRAKTUR SMALL B → LATIN SMALL LETTER B #
+1D553 ; 0062 ; MA # ( 𝕓 → b ) MATHEMATICAL DOUBLE-STRUCK SMALL B → LATIN SMALL LETTER B #
+1D587 ; 0062 ; MA # ( 𝖇 → b ) MATHEMATICAL BOLD FRAKTUR SMALL B → LATIN SMALL LETTER B #
+1D5BB ; 0062 ; MA # ( 𝖻 → b ) MATHEMATICAL SANS-SERIF SMALL B → LATIN SMALL LETTER B #
+1D5EF ; 0062 ; MA # ( 𝗯 → b ) MATHEMATICAL SANS-SERIF BOLD SMALL B → LATIN SMALL LETTER B #
+1D623 ; 0062 ; MA # ( 𝘣 → b ) MATHEMATICAL SANS-SERIF ITALIC SMALL B → LATIN SMALL LETTER B #
+1D657 ; 0062 ; MA # ( 𝙗 → b ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B → LATIN SMALL LETTER B #
+1D68B ; 0062 ; MA # ( 𝚋 → b ) MATHEMATICAL MONOSPACE SMALL B → LATIN SMALL LETTER B #
+0184 ; 0062 ; MA # ( Ƅ → b ) LATIN CAPITAL LETTER TONE SIX → LATIN SMALL LETTER B #
+042C ; 0062 ; MA # ( Ь → b ) CYRILLIC CAPITAL LETTER SOFT SIGN → LATIN SMALL LETTER B # →Ƅ→
+13CF ; 0062 ; MA # ( Ꮟ → b ) CHEROKEE LETTER SI → LATIN SMALL LETTER B #
+1472 ; 0062 ; MA # ( ᑲ → b ) CANADIAN SYLLABICS KA → LATIN SMALL LETTER B #
+15AF ; 0062 ; MA # ( ᖯ → b ) CANADIAN SYLLABICS AIVILIK B → LATIN SMALL LETTER B #
+
+FF22 ; 0042 ; MA # ( B → B ) FULLWIDTH LATIN CAPITAL LETTER B → LATIN CAPITAL LETTER B # →Β→
+212C ; 0042 ; MA # ( ℬ → B ) SCRIPT CAPITAL B → LATIN CAPITAL LETTER B #
+1D401 ; 0042 ; MA # ( 𝐁 → B ) MATHEMATICAL BOLD CAPITAL B → LATIN CAPITAL LETTER B #
+1D435 ; 0042 ; MA # ( 𝐵 → B ) MATHEMATICAL ITALIC CAPITAL B → LATIN CAPITAL LETTER B #
+1D469 ; 0042 ; MA # ( 𝑩 → B ) MATHEMATICAL BOLD ITALIC CAPITAL B → LATIN CAPITAL LETTER B #
+1D4D1 ; 0042 ; MA # ( 𝓑 → B ) MATHEMATICAL BOLD SCRIPT CAPITAL B → LATIN CAPITAL LETTER B #
+1D505 ; 0042 ; MA # ( 𝔅 → B ) MATHEMATICAL FRAKTUR CAPITAL B → LATIN CAPITAL LETTER B #
+1D539 ; 0042 ; MA # ( 𝔹 → B ) MATHEMATICAL DOUBLE-STRUCK CAPITAL B → LATIN CAPITAL LETTER B #
+1D56D ; 0042 ; MA # ( 𝕭 → B ) MATHEMATICAL BOLD FRAKTUR CAPITAL B → LATIN CAPITAL LETTER B #
+1D5A1 ; 0042 ; MA # ( 𝖡 → B ) MATHEMATICAL SANS-SERIF CAPITAL B → LATIN CAPITAL LETTER B #
+1D5D5 ; 0042 ; MA # ( 𝗕 → B ) MATHEMATICAL SANS-SERIF BOLD CAPITAL B → LATIN CAPITAL LETTER B #
+1D609 ; 0042 ; MA # ( 𝘉 → B ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL B → LATIN CAPITAL LETTER B #
+1D63D ; 0042 ; MA # ( 𝘽 → B ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B → LATIN CAPITAL LETTER B #
+1D671 ; 0042 ; MA # ( 𝙱 → B ) MATHEMATICAL MONOSPACE CAPITAL B → LATIN CAPITAL LETTER B #
+A7B4 ; 0042 ; MA # ( Ꞵ → B ) LATIN CAPITAL LETTER BETA → LATIN CAPITAL LETTER B #
+0392 ; 0042 ; MA # ( Β → B ) GREEK CAPITAL LETTER BETA → LATIN CAPITAL LETTER B #
+1D6A9 ; 0042 ; MA # ( 𝚩 → B ) MATHEMATICAL BOLD CAPITAL BETA → LATIN CAPITAL LETTER B # →Β→
+1D6E3 ; 0042 ; MA # ( 𝛣 → B ) MATHEMATICAL ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B # →Β→
+1D71D ; 0042 ; MA # ( 𝜝 → B ) MATHEMATICAL BOLD ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B # →Β→
+1D757 ; 0042 ; MA # ( 𝝗 → B ) MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA → LATIN CAPITAL LETTER B # →Β→
+1D791 ; 0042 ; MA # ( 𝞑 → B ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA → LATIN CAPITAL LETTER B # →Β→
+0412 ; 0042 ; MA # ( В → B ) CYRILLIC CAPITAL LETTER VE → LATIN CAPITAL LETTER B #
+13F4 ; 0042 ; MA # ( Ᏼ → B ) CHEROKEE LETTER YV → LATIN CAPITAL LETTER B #
+15F7 ; 0042 ; MA # ( ᗷ → B ) CANADIAN SYLLABICS CARRIER KHE → LATIN CAPITAL LETTER B #
+A4D0 ; 0042 ; MA # ( ꓐ → B ) LISU LETTER BA → LATIN CAPITAL LETTER B #
+10282 ; 0042 ; MA # ( 𐊂 → B ) LYCIAN LETTER B → LATIN CAPITAL LETTER B #
+102A1 ; 0042 ; MA # ( 𐊡 → B ) CARIAN LETTER P2 → LATIN CAPITAL LETTER B #
+10301 ; 0042 ; MA # ( 𐌁 → B ) OLD ITALIC LETTER BE → LATIN CAPITAL LETTER B #
+
+0253 ; 0062 0314 ; MA # ( ɓ → b̔ ) LATIN SMALL LETTER B WITH HOOK → LATIN SMALL LETTER B, COMBINING REVERSED COMMA ABOVE #
+
+1473 ; 0062 0307 ; MA # ( ᑳ → ḃ ) CANADIAN SYLLABICS KAA → LATIN SMALL LETTER B, COMBINING DOT ABOVE #
+
+0183 ; 0062 0304 ; MA # ( ƃ → b̄ ) LATIN SMALL LETTER B WITH TOPBAR → LATIN SMALL LETTER B, COMBINING MACRON #
+0182 ; 0062 0304 ; MA # ( Ƃ → b̄ ) LATIN CAPITAL LETTER B WITH TOPBAR → LATIN SMALL LETTER B, COMBINING MACRON #
+0411 ; 0062 0304 ; MA # ( Б → b̄ ) CYRILLIC CAPITAL LETTER BE → LATIN SMALL LETTER B, COMBINING MACRON # →Ƃ→
+
+0180 ; 0062 0335 ; MA # ( ƀ → b̵ ) LATIN SMALL LETTER B WITH STROKE → LATIN SMALL LETTER B, COMBINING SHORT STROKE OVERLAY #
+048D ; 0062 0335 ; MA # ( ҍ → b̵ ) CYRILLIC SMALL LETTER SEMISOFT SIGN → LATIN SMALL LETTER B, COMBINING SHORT STROKE OVERLAY # →ѣ→→Ь̵→
+048C ; 0062 0335 ; MA # ( Ҍ → b̵ ) CYRILLIC CAPITAL LETTER SEMISOFT SIGN → LATIN SMALL LETTER B, COMBINING SHORT STROKE OVERLAY # →Ѣ→→Ь̵→
+0463 ; 0062 0335 ; MA # ( ѣ → b̵ ) CYRILLIC SMALL LETTER YAT → LATIN SMALL LETTER B, COMBINING SHORT STROKE OVERLAY # →Ь̵→
+0462 ; 0062 0335 ; MA # ( Ѣ → b̵ ) CYRILLIC CAPITAL LETTER YAT → LATIN SMALL LETTER B, COMBINING SHORT STROKE OVERLAY # →Ь̵→
+
+147F ; 0062 00B7 ; MA # ( ᑿ → b· ) CANADIAN SYLLABICS WEST-CREE KWA → LATIN SMALL LETTER B, MIDDLE DOT # →ᑲᐧ→
+
+1481 ; 0062 0307 00B7 ; MA # ( ᒁ → ḃ· ) CANADIAN SYLLABICS WEST-CREE KWAA → LATIN SMALL LETTER B, COMBINING DOT ABOVE, MIDDLE DOT # →ᑳᐧ→
+
+1488 ; 0062 0027 ; MA # ( ᒈ → b' ) CANADIAN SYLLABICS SOUTH-SLAVEY KAH → LATIN SMALL LETTER B, APOSTROPHE # →ᑲᑊ→
+
+042B ; 0062 006C ; MA # ( Ы → bl ) CYRILLIC CAPITAL LETTER YERU → LATIN SMALL LETTER B, LATIN SMALL LETTER L # →ЬІ→→Ь1→
+
+0432 ; 0299 ; MA # ( в → ʙ ) CYRILLIC SMALL LETTER VE → LATIN LETTER SMALL CAPITAL B #
+13FC ; 0299 ; MA # ( ᏼ → ʙ ) CHEROKEE SMALL LETTER YV → LATIN LETTER SMALL CAPITAL B #
+
+FF43 ; 0063 ; MA # ( c → c ) FULLWIDTH LATIN SMALL LETTER C → LATIN SMALL LETTER C # →с→
+217D ; 0063 ; MA # ( ⅽ → c ) SMALL ROMAN NUMERAL ONE HUNDRED → LATIN SMALL LETTER C #
+1D41C ; 0063 ; MA # ( 𝐜 → c ) MATHEMATICAL BOLD SMALL C → LATIN SMALL LETTER C #
+1D450 ; 0063 ; MA # ( 𝑐 → c ) MATHEMATICAL ITALIC SMALL C → LATIN SMALL LETTER C #
+1D484 ; 0063 ; MA # ( 𝒄 → c ) MATHEMATICAL BOLD ITALIC SMALL C → LATIN SMALL LETTER C #
+1D4B8 ; 0063 ; MA # ( 𝒸 → c ) MATHEMATICAL SCRIPT SMALL C → LATIN SMALL LETTER C #
+1D4EC ; 0063 ; MA # ( 𝓬 → c ) MATHEMATICAL BOLD SCRIPT SMALL C → LATIN SMALL LETTER C #
+1D520 ; 0063 ; MA # ( 𝔠 → c ) MATHEMATICAL FRAKTUR SMALL C → LATIN SMALL LETTER C #
+1D554 ; 0063 ; MA # ( 𝕔 → c ) MATHEMATICAL DOUBLE-STRUCK SMALL C → LATIN SMALL LETTER C #
+1D588 ; 0063 ; MA # ( 𝖈 → c ) MATHEMATICAL BOLD FRAKTUR SMALL C → LATIN SMALL LETTER C #
+1D5BC ; 0063 ; MA # ( 𝖼 → c ) MATHEMATICAL SANS-SERIF SMALL C → LATIN SMALL LETTER C #
+1D5F0 ; 0063 ; MA # ( 𝗰 → c ) MATHEMATICAL SANS-SERIF BOLD SMALL C → LATIN SMALL LETTER C #
+1D624 ; 0063 ; MA # ( 𝘤 → c ) MATHEMATICAL SANS-SERIF ITALIC SMALL C → LATIN SMALL LETTER C #
+1D658 ; 0063 ; MA # ( 𝙘 → c ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C → LATIN SMALL LETTER C #
+1D68C ; 0063 ; MA # ( 𝚌 → c ) MATHEMATICAL MONOSPACE SMALL C → LATIN SMALL LETTER C #
+1D04 ; 0063 ; MA # ( ᴄ → c ) LATIN LETTER SMALL CAPITAL C → LATIN SMALL LETTER C #
+03F2 ; 0063 ; MA # ( ϲ → c ) GREEK LUNATE SIGMA SYMBOL → LATIN SMALL LETTER C #
+2CA5 ; 0063 ; MA # ( ⲥ → c ) COPTIC SMALL LETTER SIMA → LATIN SMALL LETTER C # →ϲ→
+0441 ; 0063 ; MA # ( с → c ) CYRILLIC SMALL LETTER ES → LATIN SMALL LETTER C #
+ABAF ; 0063 ; MA # ( ꮯ → c ) CHEROKEE SMALL LETTER TLI → LATIN SMALL LETTER C # →ᴄ→
+1043D ; 0063 ; MA # ( 𐐽 → c ) DESERET SMALL LETTER CHEE → LATIN SMALL LETTER C #
+
+2DED ; 0368 ; MA # ( ⷭ → ͨ ) COMBINING CYRILLIC LETTER ES → COMBINING LATIN SMALL LETTER C #
+
+1F74C ; 0043 ; MA #* ( 🝌 → C ) ALCHEMICAL SYMBOL FOR CALX → LATIN CAPITAL LETTER C #
+118F2 ; 0043 ; MA #* ( 𑣲 → C ) WARANG CITI NUMBER NINETY → LATIN CAPITAL LETTER C #
+118E9 ; 0043 ; MA # ( 𑣩 → C ) WARANG CITI DIGIT NINE → LATIN CAPITAL LETTER C #
+FF23 ; 0043 ; MA # ( C → C ) FULLWIDTH LATIN CAPITAL LETTER C → LATIN CAPITAL LETTER C # →С→
+216D ; 0043 ; MA # ( Ⅽ → C ) ROMAN NUMERAL ONE HUNDRED → LATIN CAPITAL LETTER C #
+2102 ; 0043 ; MA # ( ℂ → C ) DOUBLE-STRUCK CAPITAL C → LATIN CAPITAL LETTER C #
+212D ; 0043 ; MA # ( ℭ → C ) BLACK-LETTER CAPITAL C → LATIN CAPITAL LETTER C #
+1D402 ; 0043 ; MA # ( 𝐂 → C ) MATHEMATICAL BOLD CAPITAL C → LATIN CAPITAL LETTER C #
+1D436 ; 0043 ; MA # ( 𝐶 → C ) MATHEMATICAL ITALIC CAPITAL C → LATIN CAPITAL LETTER C #
+1D46A ; 0043 ; MA # ( 𝑪 → C ) MATHEMATICAL BOLD ITALIC CAPITAL C → LATIN CAPITAL LETTER C #
+1D49E ; 0043 ; MA # ( 𝒞 → C ) MATHEMATICAL SCRIPT CAPITAL C → LATIN CAPITAL LETTER C #
+1D4D2 ; 0043 ; MA # ( 𝓒 → C ) MATHEMATICAL BOLD SCRIPT CAPITAL C → LATIN CAPITAL LETTER C #
+1D56E ; 0043 ; MA # ( 𝕮 → C ) MATHEMATICAL BOLD FRAKTUR CAPITAL C → LATIN CAPITAL LETTER C #
+1D5A2 ; 0043 ; MA # ( 𝖢 → C ) MATHEMATICAL SANS-SERIF CAPITAL C → LATIN CAPITAL LETTER C #
+1D5D6 ; 0043 ; MA # ( 𝗖 → C ) MATHEMATICAL SANS-SERIF BOLD CAPITAL C → LATIN CAPITAL LETTER C #
+1D60A ; 0043 ; MA # ( 𝘊 → C ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL C → LATIN CAPITAL LETTER C #
+1D63E ; 0043 ; MA # ( 𝘾 → C ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C → LATIN CAPITAL LETTER C #
+1D672 ; 0043 ; MA # ( 𝙲 → C ) MATHEMATICAL MONOSPACE CAPITAL C → LATIN CAPITAL LETTER C #
+03F9 ; 0043 ; MA # ( Ϲ → C ) GREEK CAPITAL LUNATE SIGMA SYMBOL → LATIN CAPITAL LETTER C #
+2CA4 ; 0043 ; MA # ( Ⲥ → C ) COPTIC CAPITAL LETTER SIMA → LATIN CAPITAL LETTER C # →Ϲ→
+0421 ; 0043 ; MA # ( С → C ) CYRILLIC CAPITAL LETTER ES → LATIN CAPITAL LETTER C #
+13DF ; 0043 ; MA # ( Ꮯ → C ) CHEROKEE LETTER TLI → LATIN CAPITAL LETTER C #
+A4DA ; 0043 ; MA # ( ꓚ → C ) LISU LETTER CA → LATIN CAPITAL LETTER C #
+102A2 ; 0043 ; MA # ( 𐊢 → C ) CARIAN LETTER D → LATIN CAPITAL LETTER C #
+10302 ; 0043 ; MA # ( 𐌂 → C ) OLD ITALIC LETTER KE → LATIN CAPITAL LETTER C #
+10415 ; 0043 ; MA # ( 𐐕 → C ) DESERET CAPITAL LETTER CHEE → LATIN CAPITAL LETTER C #
+1051C ; 0043 ; MA # ( 𐔜 → C ) ELBASAN LETTER SHE → LATIN CAPITAL LETTER C #
+
+00A2 ; 0063 0338 ; MA #* ( ¢ → c̸ ) CENT SIGN → LATIN SMALL LETTER C, COMBINING LONG SOLIDUS OVERLAY #
+023C ; 0063 0338 ; MA # ( ȼ → c̸ ) LATIN SMALL LETTER C WITH STROKE → LATIN SMALL LETTER C, COMBINING LONG SOLIDUS OVERLAY # →¢→
+
+20A1 ; 0043 20EB ; MA #* ( ₡ → C⃫ ) COLON SIGN → LATIN CAPITAL LETTER C, COMBINING LONG DOUBLE SOLIDUS OVERLAY #
+
+1F16E ; 0043 20E0 ; MA #* ( 🅮 → C⃠ ) CIRCLED C WITH OVERLAID BACKSLASH → LATIN CAPITAL LETTER C, COMBINING ENCLOSING CIRCLE BACKSLASH #
+
+00E7 ; 0063 0326 ; MA # ( ç → c̦ ) LATIN SMALL LETTER C WITH CEDILLA → LATIN SMALL LETTER C, COMBINING COMMA BELOW # →ҫ→→с̡→
+04AB ; 0063 0326 ; MA # ( ҫ → c̦ ) CYRILLIC SMALL LETTER ES WITH DESCENDER → LATIN SMALL LETTER C, COMBINING COMMA BELOW # →с̡→
+
+00C7 ; 0043 0326 ; MA # ( Ç → C̦ ) LATIN CAPITAL LETTER C WITH CEDILLA → LATIN CAPITAL LETTER C, COMBINING COMMA BELOW # →Ҫ→→С̡→
+04AA ; 0043 0326 ; MA # ( Ҫ → C̦ ) CYRILLIC CAPITAL LETTER ES WITH DESCENDER → LATIN CAPITAL LETTER C, COMBINING COMMA BELOW # →С̡→
+
+0187 ; 0043 0027 ; MA # ( Ƈ → C' ) LATIN CAPITAL LETTER C WITH HOOK → LATIN CAPITAL LETTER C, APOSTROPHE # →Cʽ→
+
+2105 ; 0063 002F 006F ; MA #* ( ℅ → c/o ) CARE OF → LATIN SMALL LETTER C, SOLIDUS, LATIN SMALL LETTER O #
+
+2106 ; 0063 002F 0075 ; MA #* ( ℆ → c/u ) CADA UNA → LATIN SMALL LETTER C, SOLIDUS, LATIN SMALL LETTER U #
+
+1F16D ; 33C4 0009 20DD ; MA #* ( 🅭 → ) CIRCLED CC → SQUARE CC, <CHARACTER TABULATION>, COMBINING ENCLOSING CIRCLE #
+
+22F4 ; A793 ; MA #* ( ⋴ → ꞓ ) SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE → LATIN SMALL LETTER C WITH BAR # →ɛ→→є→
+025B ; A793 ; MA # ( ɛ → ꞓ ) LATIN SMALL LETTER OPEN E → LATIN SMALL LETTER C WITH BAR # →є→
+03B5 ; A793 ; MA # ( ε → ꞓ ) GREEK SMALL LETTER EPSILON → LATIN SMALL LETTER C WITH BAR # →є→
+03F5 ; A793 ; MA # ( ϵ → ꞓ ) GREEK LUNATE EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D6C6 ; A793 ; MA # ( 𝛆 → ꞓ ) MATHEMATICAL BOLD SMALL EPSILON → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D6DC ; A793 ; MA # ( 𝛜 → ꞓ ) MATHEMATICAL BOLD EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D700 ; A793 ; MA # ( 𝜀 → ꞓ ) MATHEMATICAL ITALIC SMALL EPSILON → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D716 ; A793 ; MA # ( 𝜖 → ꞓ ) MATHEMATICAL ITALIC EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D73A ; A793 ; MA # ( 𝜺 → ꞓ ) MATHEMATICAL BOLD ITALIC SMALL EPSILON → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D750 ; A793 ; MA # ( 𝝐 → ꞓ ) MATHEMATICAL BOLD ITALIC EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D774 ; A793 ; MA # ( 𝝴 → ꞓ ) MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D78A ; A793 ; MA # ( 𝞊 → ꞓ ) MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D7AE ; A793 ; MA # ( 𝞮 → ꞓ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+1D7C4 ; A793 ; MA # ( 𝟄 → ꞓ ) MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+2C89 ; A793 ; MA # ( ⲉ → ꞓ ) COPTIC SMALL LETTER EIE → LATIN SMALL LETTER C WITH BAR # →є→
+0454 ; A793 ; MA # ( є → ꞓ ) CYRILLIC SMALL LETTER UKRAINIAN IE → LATIN SMALL LETTER C WITH BAR #
+0511 ; A793 ; MA # ( ԑ → ꞓ ) CYRILLIC SMALL LETTER REVERSED ZE → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+AB9B ; A793 ; MA # ( ꮛ → ꞓ ) CHEROKEE SMALL LETTER QUV → LATIN SMALL LETTER C WITH BAR # →ɛ→→є→
+118CE ; A793 ; MA # ( 𑣎 → ꞓ ) WARANG CITI SMALL LETTER YUJ → LATIN SMALL LETTER C WITH BAR # →ε→→є→
+10429 ; A793 ; MA # ( 𐐩 → ꞓ ) DESERET SMALL LETTER LONG E → LATIN SMALL LETTER C WITH BAR # →ɛ→→є→
+
+20AC ; A792 ; MA #* ( € → Ꞓ ) EURO SIGN → LATIN CAPITAL LETTER C WITH BAR # →Є→
+2C88 ; A792 ; MA # ( Ⲉ → Ꞓ ) COPTIC CAPITAL LETTER EIE → LATIN CAPITAL LETTER C WITH BAR # →Є→
+0404 ; A792 ; MA # ( Є → Ꞓ ) CYRILLIC CAPITAL LETTER UKRAINIAN IE → LATIN CAPITAL LETTER C WITH BAR #
+
+2377 ; A793 0332 ; MA #* ( ⍷ → ꞓ̲ ) APL FUNCTIONAL SYMBOL EPSILON UNDERBAR → LATIN SMALL LETTER C WITH BAR, COMBINING LOW LINE # →ε̲→
+
+037D ; A73F ; MA # ( ͽ → ꜿ ) GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL → LATIN SMALL LETTER REVERSED C WITH DOT #
+
+03FF ; A73E ; MA # ( Ͽ → Ꜿ ) GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL → LATIN CAPITAL LETTER REVERSED C WITH DOT #
+
+217E ; 0064 ; MA # ( ⅾ → d ) SMALL ROMAN NUMERAL FIVE HUNDRED → LATIN SMALL LETTER D #
+2146 ; 0064 ; MA # ( ⅆ → d ) DOUBLE-STRUCK ITALIC SMALL D → LATIN SMALL LETTER D #
+1D41D ; 0064 ; MA # ( 𝐝 → d ) MATHEMATICAL BOLD SMALL D → LATIN SMALL LETTER D #
+1D451 ; 0064 ; MA # ( 𝑑 → d ) MATHEMATICAL ITALIC SMALL D → LATIN SMALL LETTER D #
+1D485 ; 0064 ; MA # ( 𝒅 → d ) MATHEMATICAL BOLD ITALIC SMALL D → LATIN SMALL LETTER D #
+1D4B9 ; 0064 ; MA # ( 𝒹 → d ) MATHEMATICAL SCRIPT SMALL D → LATIN SMALL LETTER D #
+1D4ED ; 0064 ; MA # ( 𝓭 → d ) MATHEMATICAL BOLD SCRIPT SMALL D → LATIN SMALL LETTER D #
+1D521 ; 0064 ; MA # ( 𝔡 → d ) MATHEMATICAL FRAKTUR SMALL D → LATIN SMALL LETTER D #
+1D555 ; 0064 ; MA # ( 𝕕 → d ) MATHEMATICAL DOUBLE-STRUCK SMALL D → LATIN SMALL LETTER D #
+1D589 ; 0064 ; MA # ( 𝖉 → d ) MATHEMATICAL BOLD FRAKTUR SMALL D → LATIN SMALL LETTER D #
+1D5BD ; 0064 ; MA # ( 𝖽 → d ) MATHEMATICAL SANS-SERIF SMALL D → LATIN SMALL LETTER D #
+1D5F1 ; 0064 ; MA # ( 𝗱 → d ) MATHEMATICAL SANS-SERIF BOLD SMALL D → LATIN SMALL LETTER D #
+1D625 ; 0064 ; MA # ( 𝘥 → d ) MATHEMATICAL SANS-SERIF ITALIC SMALL D → LATIN SMALL LETTER D #
+1D659 ; 0064 ; MA # ( 𝙙 → d ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D → LATIN SMALL LETTER D #
+1D68D ; 0064 ; MA # ( 𝚍 → d ) MATHEMATICAL MONOSPACE SMALL D → LATIN SMALL LETTER D #
+0501 ; 0064 ; MA # ( ԁ → d ) CYRILLIC SMALL LETTER KOMI DE → LATIN SMALL LETTER D #
+13E7 ; 0064 ; MA # ( Ꮷ → d ) CHEROKEE LETTER TSU → LATIN SMALL LETTER D #
+146F ; 0064 ; MA # ( ᑯ → d ) CANADIAN SYLLABICS KO → LATIN SMALL LETTER D #
+A4D2 ; 0064 ; MA # ( ꓒ → d ) LISU LETTER PHA → LATIN SMALL LETTER D #
+
+216E ; 0044 ; MA # ( Ⅾ → D ) ROMAN NUMERAL FIVE HUNDRED → LATIN CAPITAL LETTER D #
+2145 ; 0044 ; MA # ( ⅅ → D ) DOUBLE-STRUCK ITALIC CAPITAL D → LATIN CAPITAL LETTER D #
+1D403 ; 0044 ; MA # ( 𝐃 → D ) MATHEMATICAL BOLD CAPITAL D → LATIN CAPITAL LETTER D #
+1D437 ; 0044 ; MA # ( 𝐷 → D ) MATHEMATICAL ITALIC CAPITAL D → LATIN CAPITAL LETTER D #
+1D46B ; 0044 ; MA # ( 𝑫 → D ) MATHEMATICAL BOLD ITALIC CAPITAL D → LATIN CAPITAL LETTER D #
+1D49F ; 0044 ; MA # ( 𝒟 → D ) MATHEMATICAL SCRIPT CAPITAL D → LATIN CAPITAL LETTER D #
+1D4D3 ; 0044 ; MA # ( 𝓓 → D ) MATHEMATICAL BOLD SCRIPT CAPITAL D → LATIN CAPITAL LETTER D #
+1D507 ; 0044 ; MA # ( 𝔇 → D ) MATHEMATICAL FRAKTUR CAPITAL D → LATIN CAPITAL LETTER D #
+1D53B ; 0044 ; MA # ( 𝔻 → D ) MATHEMATICAL DOUBLE-STRUCK CAPITAL D → LATIN CAPITAL LETTER D #
+1D56F ; 0044 ; MA # ( 𝕯 → D ) MATHEMATICAL BOLD FRAKTUR CAPITAL D → LATIN CAPITAL LETTER D #
+1D5A3 ; 0044 ; MA # ( 𝖣 → D ) MATHEMATICAL SANS-SERIF CAPITAL D → LATIN CAPITAL LETTER D #
+1D5D7 ; 0044 ; MA # ( 𝗗 → D ) MATHEMATICAL SANS-SERIF BOLD CAPITAL D → LATIN CAPITAL LETTER D #
+1D60B ; 0044 ; MA # ( 𝘋 → D ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL D → LATIN CAPITAL LETTER D #
+1D63F ; 0044 ; MA # ( 𝘿 → D ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D → LATIN CAPITAL LETTER D #
+1D673 ; 0044 ; MA # ( 𝙳 → D ) MATHEMATICAL MONOSPACE CAPITAL D → LATIN CAPITAL LETTER D #
+13A0 ; 0044 ; MA # ( Ꭰ → D ) CHEROKEE LETTER A → LATIN CAPITAL LETTER D #
+15DE ; 0044 ; MA # ( ᗞ → D ) CANADIAN SYLLABICS CARRIER THE → LATIN CAPITAL LETTER D #
+15EA ; 0044 ; MA # ( ᗪ → D ) CANADIAN SYLLABICS CARRIER PE → LATIN CAPITAL LETTER D # →ᗞ→
+A4D3 ; 0044 ; MA # ( ꓓ → D ) LISU LETTER DA → LATIN CAPITAL LETTER D #
+
+0257 ; 0064 0314 ; MA # ( ɗ → d̔ ) LATIN SMALL LETTER D WITH HOOK → LATIN SMALL LETTER D, COMBINING REVERSED COMMA ABOVE #
+
+0256 ; 0064 0328 ; MA # ( ɖ → d̨ ) LATIN SMALL LETTER D WITH TAIL → LATIN SMALL LETTER D, COMBINING OGONEK # →d̢→
+
+018C ; 0064 0304 ; MA # ( ƌ → d̄ ) LATIN SMALL LETTER D WITH TOPBAR → LATIN SMALL LETTER D, COMBINING MACRON #
+
+0111 ; 0064 0335 ; MA # ( đ → d̵ ) LATIN SMALL LETTER D WITH STROKE → LATIN SMALL LETTER D, COMBINING SHORT STROKE OVERLAY #
+
+0110 ; 0044 0335 ; MA # ( Đ → D̵ ) LATIN CAPITAL LETTER D WITH STROKE → LATIN CAPITAL LETTER D, COMBINING SHORT STROKE OVERLAY #
+00D0 ; 0044 0335 ; MA # ( Ð → D̵ ) LATIN CAPITAL LETTER ETH → LATIN CAPITAL LETTER D, COMBINING SHORT STROKE OVERLAY # →Đ→
+0189 ; 0044 0335 ; MA # ( Ɖ → D̵ ) LATIN CAPITAL LETTER AFRICAN D → LATIN CAPITAL LETTER D, COMBINING SHORT STROKE OVERLAY # →Đ→
+
+20AB ; 0064 0335 0331 ; MA #* ( ₫ → ḏ̵ ) DONG SIGN → LATIN SMALL LETTER D, COMBINING SHORT STROKE OVERLAY, COMBINING MACRON BELOW # →đ̱→
+
+A77A ; A779 ; MA # ( ꝺ → Ꝺ ) LATIN SMALL LETTER INSULAR D → LATIN CAPITAL LETTER INSULAR D #
+
+147B ; 0064 00B7 ; MA # ( ᑻ → d· ) CANADIAN SYLLABICS WEST-CREE KWO → LATIN SMALL LETTER D, MIDDLE DOT # →ᑯᐧ→
+
+1487 ; 0064 0027 ; MA # ( ᒇ → d' ) CANADIAN SYLLABICS SOUTH-SLAVEY KOH → LATIN SMALL LETTER D, APOSTROPHE # →ᑯᑊ→
+
+02A4 ; 0064 021D ; MA # ( ʤ → dȝ ) LATIN SMALL LETTER DEZH DIGRAPH → LATIN SMALL LETTER D, LATIN SMALL LETTER YOGH # →dʒ→
+
+01F3 ; 0064 007A ; MA # ( dz → dz ) LATIN SMALL LETTER DZ → LATIN SMALL LETTER D, LATIN SMALL LETTER Z #
+02A3 ; 0064 007A ; MA # ( ʣ → dz ) LATIN SMALL LETTER DZ DIGRAPH → LATIN SMALL LETTER D, LATIN SMALL LETTER Z #
+
+01F2 ; 0044 007A ; MA # ( Dz → Dz ) LATIN CAPITAL LETTER D WITH SMALL LETTER Z → LATIN CAPITAL LETTER D, LATIN SMALL LETTER Z #
+
+01F1 ; 0044 005A ; MA # ( DZ → DZ ) LATIN CAPITAL LETTER DZ → LATIN CAPITAL LETTER D, LATIN CAPITAL LETTER Z #
+
+01C6 ; 0064 017E ; MA # ( dž → dž ) LATIN SMALL LETTER DZ WITH CARON → LATIN SMALL LETTER D, LATIN SMALL LETTER Z WITH CARON #
+
+01C5 ; 0044 017E ; MA # ( Dž → Dž ) LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON → LATIN CAPITAL LETTER D, LATIN SMALL LETTER Z WITH CARON #
+
+01C4 ; 0044 017D ; MA # ( DŽ → DŽ ) LATIN CAPITAL LETTER DZ WITH CARON → LATIN CAPITAL LETTER D, LATIN CAPITAL LETTER Z WITH CARON #
+
+02A5 ; 0064 0291 ; MA # ( ʥ → dʑ ) LATIN SMALL LETTER DZ DIGRAPH WITH CURL → LATIN SMALL LETTER D, LATIN SMALL LETTER Z WITH CURL #
+
+AB70 ; 1D05 ; MA # ( ꭰ → ᴅ ) CHEROKEE SMALL LETTER A → LATIN LETTER SMALL CAPITAL D #
+
+2E39 ; 1E9F ; MA #* ( ⸹ → ẟ ) TOP HALF SECTION SIGN → LATIN SMALL LETTER DELTA # →δ→
+03B4 ; 1E9F ; MA # ( δ → ẟ ) GREEK SMALL LETTER DELTA → LATIN SMALL LETTER DELTA #
+1D6C5 ; 1E9F ; MA # ( 𝛅 → ẟ ) MATHEMATICAL BOLD SMALL DELTA → LATIN SMALL LETTER DELTA # →δ→
+1D6FF ; 1E9F ; MA # ( 𝛿 → ẟ ) MATHEMATICAL ITALIC SMALL DELTA → LATIN SMALL LETTER DELTA # →δ→
+1D739 ; 1E9F ; MA # ( 𝜹 → ẟ ) MATHEMATICAL BOLD ITALIC SMALL DELTA → LATIN SMALL LETTER DELTA # →δ→
+1D773 ; 1E9F ; MA # ( 𝝳 → ẟ ) MATHEMATICAL SANS-SERIF BOLD SMALL DELTA → LATIN SMALL LETTER DELTA # →δ→
+1D7AD ; 1E9F ; MA # ( 𝞭 → ẟ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA → LATIN SMALL LETTER DELTA # →δ→
+056E ; 1E9F ; MA # ( ծ → ẟ ) ARMENIAN SMALL LETTER CA → LATIN SMALL LETTER DELTA # →δ→
+1577 ; 1E9F ; MA # ( ᕷ → ẟ ) CANADIAN SYLLABICS NUNAVIK HO → LATIN SMALL LETTER DELTA # →δ→
+
+212E ; 0065 ; MA # ( ℮ → e ) ESTIMATED SYMBOL → LATIN SMALL LETTER E #
+FF45 ; 0065 ; MA # ( e → e ) FULLWIDTH LATIN SMALL LETTER E → LATIN SMALL LETTER E # →е→
+212F ; 0065 ; MA # ( ℯ → e ) SCRIPT SMALL E → LATIN SMALL LETTER E #
+2147 ; 0065 ; MA # ( ⅇ → e ) DOUBLE-STRUCK ITALIC SMALL E → LATIN SMALL LETTER E #
+1D41E ; 0065 ; MA # ( 𝐞 → e ) MATHEMATICAL BOLD SMALL E → LATIN SMALL LETTER E #
+1D452 ; 0065 ; MA # ( 𝑒 → e ) MATHEMATICAL ITALIC SMALL E → LATIN SMALL LETTER E #
+1D486 ; 0065 ; MA # ( 𝒆 → e ) MATHEMATICAL BOLD ITALIC SMALL E → LATIN SMALL LETTER E #
+1D4EE ; 0065 ; MA # ( 𝓮 → e ) MATHEMATICAL BOLD SCRIPT SMALL E → LATIN SMALL LETTER E #
+1D522 ; 0065 ; MA # ( 𝔢 → e ) MATHEMATICAL FRAKTUR SMALL E → LATIN SMALL LETTER E #
+1D556 ; 0065 ; MA # ( 𝕖 → e ) MATHEMATICAL DOUBLE-STRUCK SMALL E → LATIN SMALL LETTER E #
+1D58A ; 0065 ; MA # ( 𝖊 → e ) MATHEMATICAL BOLD FRAKTUR SMALL E → LATIN SMALL LETTER E #
+1D5BE ; 0065 ; MA # ( 𝖾 → e ) MATHEMATICAL SANS-SERIF SMALL E → LATIN SMALL LETTER E #
+1D5F2 ; 0065 ; MA # ( 𝗲 → e ) MATHEMATICAL SANS-SERIF BOLD SMALL E → LATIN SMALL LETTER E #
+1D626 ; 0065 ; MA # ( 𝘦 → e ) MATHEMATICAL SANS-SERIF ITALIC SMALL E → LATIN SMALL LETTER E #
+1D65A ; 0065 ; MA # ( 𝙚 → e ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E → LATIN SMALL LETTER E #
+1D68E ; 0065 ; MA # ( 𝚎 → e ) MATHEMATICAL MONOSPACE SMALL E → LATIN SMALL LETTER E #
+AB32 ; 0065 ; MA # ( ꬲ → e ) LATIN SMALL LETTER BLACKLETTER E → LATIN SMALL LETTER E #
+0435 ; 0065 ; MA # ( е → e ) CYRILLIC SMALL LETTER IE → LATIN SMALL LETTER E #
+04BD ; 0065 ; MA # ( ҽ → e ) CYRILLIC SMALL LETTER ABKHASIAN CHE → LATIN SMALL LETTER E #
+
+2DF7 ; 0364 ; MA # ( ⷷ → ͤ ) COMBINING CYRILLIC LETTER IE → COMBINING LATIN SMALL LETTER E #
+
+22FF ; 0045 ; MA #* ( ⋿ → E ) Z NOTATION BAG MEMBERSHIP → LATIN CAPITAL LETTER E #
+FF25 ; 0045 ; MA # ( E → E ) FULLWIDTH LATIN CAPITAL LETTER E → LATIN CAPITAL LETTER E # →Ε→
+2130 ; 0045 ; MA # ( ℰ → E ) SCRIPT CAPITAL E → LATIN CAPITAL LETTER E #
+1D404 ; 0045 ; MA # ( 𝐄 → E ) MATHEMATICAL BOLD CAPITAL E → LATIN CAPITAL LETTER E #
+1D438 ; 0045 ; MA # ( 𝐸 → E ) MATHEMATICAL ITALIC CAPITAL E → LATIN CAPITAL LETTER E #
+1D46C ; 0045 ; MA # ( 𝑬 → E ) MATHEMATICAL BOLD ITALIC CAPITAL E → LATIN CAPITAL LETTER E #
+1D4D4 ; 0045 ; MA # ( 𝓔 → E ) MATHEMATICAL BOLD SCRIPT CAPITAL E → LATIN CAPITAL LETTER E #
+1D508 ; 0045 ; MA # ( 𝔈 → E ) MATHEMATICAL FRAKTUR CAPITAL E → LATIN CAPITAL LETTER E #
+1D53C ; 0045 ; MA # ( 𝔼 → E ) MATHEMATICAL DOUBLE-STRUCK CAPITAL E → LATIN CAPITAL LETTER E #
+1D570 ; 0045 ; MA # ( 𝕰 → E ) MATHEMATICAL BOLD FRAKTUR CAPITAL E → LATIN CAPITAL LETTER E #
+1D5A4 ; 0045 ; MA # ( 𝖤 → E ) MATHEMATICAL SANS-SERIF CAPITAL E → LATIN CAPITAL LETTER E #
+1D5D8 ; 0045 ; MA # ( 𝗘 → E ) MATHEMATICAL SANS-SERIF BOLD CAPITAL E → LATIN CAPITAL LETTER E #
+1D60C ; 0045 ; MA # ( 𝘌 → E ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL E → LATIN CAPITAL LETTER E #
+1D640 ; 0045 ; MA # ( 𝙀 → E ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E → LATIN CAPITAL LETTER E #
+1D674 ; 0045 ; MA # ( 𝙴 → E ) MATHEMATICAL MONOSPACE CAPITAL E → LATIN CAPITAL LETTER E #
+0395 ; 0045 ; MA # ( Ε → E ) GREEK CAPITAL LETTER EPSILON → LATIN CAPITAL LETTER E #
+1D6AC ; 0045 ; MA # ( 𝚬 → E ) MATHEMATICAL BOLD CAPITAL EPSILON → LATIN CAPITAL LETTER E # →𝐄→
+1D6E6 ; 0045 ; MA # ( 𝛦 → E ) MATHEMATICAL ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E # →Ε→
+1D720 ; 0045 ; MA # ( 𝜠 → E ) MATHEMATICAL BOLD ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E # →Ε→
+1D75A ; 0045 ; MA # ( 𝝚 → E ) MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON → LATIN CAPITAL LETTER E # →Ε→
+1D794 ; 0045 ; MA # ( 𝞔 → E ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON → LATIN CAPITAL LETTER E # →Ε→
+0415 ; 0045 ; MA # ( Е → E ) CYRILLIC CAPITAL LETTER IE → LATIN CAPITAL LETTER E #
+2D39 ; 0045 ; MA # ( ⴹ → E ) TIFINAGH LETTER YADD → LATIN CAPITAL LETTER E #
+13AC ; 0045 ; MA # ( Ꭼ → E ) CHEROKEE LETTER GV → LATIN CAPITAL LETTER E #
+A4F0 ; 0045 ; MA # ( ꓰ → E ) LISU LETTER E → LATIN CAPITAL LETTER E #
+118A6 ; 0045 ; MA # ( 𑢦 → E ) WARANG CITI CAPITAL LETTER II → LATIN CAPITAL LETTER E #
+118AE ; 0045 ; MA # ( 𑢮 → E ) WARANG CITI CAPITAL LETTER YUJ → LATIN CAPITAL LETTER E #
+10286 ; 0045 ; MA # ( 𐊆 → E ) LYCIAN LETTER I → LATIN CAPITAL LETTER E #
+
+011B ; 0115 ; MA # ( ě → ĕ ) LATIN SMALL LETTER E WITH CARON → LATIN SMALL LETTER E WITH BREVE #
+
+011A ; 0114 ; MA # ( Ě → Ĕ ) LATIN CAPITAL LETTER E WITH CARON → LATIN CAPITAL LETTER E WITH BREVE #
+
+0247 ; 0065 0338 ; MA # ( ɇ → e̸ ) LATIN SMALL LETTER E WITH STROKE → LATIN SMALL LETTER E, COMBINING LONG SOLIDUS OVERLAY # →e̷→
+
+0246 ; 0045 0338 ; MA # ( Ɇ → E̸ ) LATIN CAPITAL LETTER E WITH STROKE → LATIN CAPITAL LETTER E, COMBINING LONG SOLIDUS OVERLAY #
+
+04BF ; 0065 0328 ; MA # ( ҿ → ę ) CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER → LATIN SMALL LETTER E, COMBINING OGONEK # →ҽ̢→
+
+AB7C ; 1D07 ; MA # ( ꭼ → ᴇ ) CHEROKEE SMALL LETTER GV → LATIN LETTER SMALL CAPITAL E #
+
+0259 ; 01DD ; MA # ( ə → ǝ ) LATIN SMALL LETTER SCHWA → LATIN SMALL LETTER TURNED E #
+04D9 ; 01DD ; MA # ( ә → ǝ ) CYRILLIC SMALL LETTER SCHWA → LATIN SMALL LETTER TURNED E #
+
+2203 ; 018E ; MA #* ( ∃ → Ǝ ) THERE EXISTS → LATIN CAPITAL LETTER REVERSED E #
+2D3A ; 018E ; MA # ( ⴺ → Ǝ ) TIFINAGH LETTER YADDH → LATIN CAPITAL LETTER REVERSED E #
+A4F1 ; 018E ; MA # ( ꓱ → Ǝ ) LISU LETTER EU → LATIN CAPITAL LETTER REVERSED E #
+
+025A ; 01DD 02DE ; MA # ( ɚ → ǝ˞ ) LATIN SMALL LETTER SCHWA WITH HOOK → LATIN SMALL LETTER TURNED E, MODIFIER LETTER RHOTIC HOOK # →ə˞→
+
+1D14 ; 01DD 006F ; MA # ( ᴔ → ǝo ) LATIN SMALL LETTER TURNED OE → LATIN SMALL LETTER TURNED E, LATIN SMALL LETTER O # →əo→
+
+AB41 ; 01DD 006F 0338 ; MA # ( ꭁ → ǝo̸ ) LATIN SMALL LETTER TURNED OE WITH STROKE → LATIN SMALL LETTER TURNED E, LATIN SMALL LETTER O, COMBINING LONG SOLIDUS OVERLAY # →ǝø→
+
+AB42 ; 01DD 006F 0335 ; MA # ( ꭂ → ǝo̵ ) LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE → LATIN SMALL LETTER TURNED E, LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY # →ǝɵ→
+
+04D8 ; 018F ; MA # ( Ә → Ə ) CYRILLIC CAPITAL LETTER SCHWA → LATIN CAPITAL LETTER SCHWA #
+
+1D221 ; 0190 ; MA #* ( 𝈡 → Ɛ ) GREEK INSTRUMENTAL NOTATION SYMBOL-7 → LATIN CAPITAL LETTER OPEN E #
+2107 ; 0190 ; MA # ( ℇ → Ɛ ) EULER CONSTANT → LATIN CAPITAL LETTER OPEN E #
+0510 ; 0190 ; MA # ( Ԑ → Ɛ ) CYRILLIC CAPITAL LETTER REVERSED ZE → LATIN CAPITAL LETTER OPEN E #
+13CB ; 0190 ; MA # ( Ꮛ → Ɛ ) CHEROKEE LETTER QUV → LATIN CAPITAL LETTER OPEN E #
+16F2D ; 0190 ; MA # ( 𖼭 → Ɛ ) MIAO LETTER NYHA → LATIN CAPITAL LETTER OPEN E #
+10401 ; 0190 ; MA # ( 𐐁 → Ɛ ) DESERET CAPITAL LETTER LONG E → LATIN CAPITAL LETTER OPEN E #
+
+1D9F ; 1D4B ; MA # ( ᶟ → ᵋ ) MODIFIER LETTER SMALL REVERSED OPEN E → MODIFIER LETTER SMALL OPEN E #
+
+1D08 ; 025C ; MA # ( ᴈ → ɜ ) LATIN SMALL LETTER TURNED OPEN E → LATIN SMALL LETTER REVERSED OPEN E #
+0437 ; 025C ; MA # ( з → ɜ ) CYRILLIC SMALL LETTER ZE → LATIN SMALL LETTER REVERSED OPEN E #
+
+0499 ; 025C 0326 ; MA # ( ҙ → ɜ̦ ) CYRILLIC SMALL LETTER ZE WITH DESCENDER → LATIN SMALL LETTER REVERSED OPEN E, COMBINING COMMA BELOW # →з̡→
+
+10442 ; 025E ; MA # ( 𐑂 → ɞ ) DESERET SMALL LETTER VEE → LATIN SMALL LETTER CLOSED REVERSED OPEN E #
+
+A79D ; 029A ; MA # ( ꞝ → ʚ ) LATIN SMALL LETTER VOLAPUK OE → LATIN SMALL LETTER CLOSED OPEN E #
+1042A ; 029A ; MA # ( 𐐪 → ʚ ) DESERET SMALL LETTER LONG A → LATIN SMALL LETTER CLOSED OPEN E #
+
+1D41F ; 0066 ; MA # ( 𝐟 → f ) MATHEMATICAL BOLD SMALL F → LATIN SMALL LETTER F #
+1D453 ; 0066 ; MA # ( 𝑓 → f ) MATHEMATICAL ITALIC SMALL F → LATIN SMALL LETTER F #
+1D487 ; 0066 ; MA # ( 𝒇 → f ) MATHEMATICAL BOLD ITALIC SMALL F → LATIN SMALL LETTER F #
+1D4BB ; 0066 ; MA # ( 𝒻 → f ) MATHEMATICAL SCRIPT SMALL F → LATIN SMALL LETTER F #
+1D4EF ; 0066 ; MA # ( 𝓯 → f ) MATHEMATICAL BOLD SCRIPT SMALL F → LATIN SMALL LETTER F #
+1D523 ; 0066 ; MA # ( 𝔣 → f ) MATHEMATICAL FRAKTUR SMALL F → LATIN SMALL LETTER F #
+1D557 ; 0066 ; MA # ( 𝕗 → f ) MATHEMATICAL DOUBLE-STRUCK SMALL F → LATIN SMALL LETTER F #
+1D58B ; 0066 ; MA # ( 𝖋 → f ) MATHEMATICAL BOLD FRAKTUR SMALL F → LATIN SMALL LETTER F #
+1D5BF ; 0066 ; MA # ( 𝖿 → f ) MATHEMATICAL SANS-SERIF SMALL F → LATIN SMALL LETTER F #
+1D5F3 ; 0066 ; MA # ( 𝗳 → f ) MATHEMATICAL SANS-SERIF BOLD SMALL F → LATIN SMALL LETTER F #
+1D627 ; 0066 ; MA # ( 𝘧 → f ) MATHEMATICAL SANS-SERIF ITALIC SMALL F → LATIN SMALL LETTER F #
+1D65B ; 0066 ; MA # ( 𝙛 → f ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F → LATIN SMALL LETTER F #
+1D68F ; 0066 ; MA # ( 𝚏 → f ) MATHEMATICAL MONOSPACE SMALL F → LATIN SMALL LETTER F #
+AB35 ; 0066 ; MA # ( ꬵ → f ) LATIN SMALL LETTER LENIS F → LATIN SMALL LETTER F #
+A799 ; 0066 ; MA # ( ꞙ → f ) LATIN SMALL LETTER F WITH STROKE → LATIN SMALL LETTER F #
+017F ; 0066 ; MA # ( ſ → f ) LATIN SMALL LETTER LONG S → LATIN SMALL LETTER F #
+1E9D ; 0066 ; MA # ( ẝ → f ) LATIN SMALL LETTER LONG S WITH HIGH STROKE → LATIN SMALL LETTER F #
+0584 ; 0066 ; MA # ( ք → f ) ARMENIAN SMALL LETTER KEH → LATIN SMALL LETTER F #
+
+1D213 ; 0046 ; MA #* ( 𝈓 → F ) GREEK VOCAL NOTATION SYMBOL-20 → LATIN CAPITAL LETTER F # →Ϝ→
+2131 ; 0046 ; MA # ( ℱ → F ) SCRIPT CAPITAL F → LATIN CAPITAL LETTER F #
+1D405 ; 0046 ; MA # ( 𝐅 → F ) MATHEMATICAL BOLD CAPITAL F → LATIN CAPITAL LETTER F #
+1D439 ; 0046 ; MA # ( 𝐹 → F ) MATHEMATICAL ITALIC CAPITAL F → LATIN CAPITAL LETTER F #
+1D46D ; 0046 ; MA # ( 𝑭 → F ) MATHEMATICAL BOLD ITALIC CAPITAL F → LATIN CAPITAL LETTER F #
+1D4D5 ; 0046 ; MA # ( 𝓕 → F ) MATHEMATICAL BOLD SCRIPT CAPITAL F → LATIN CAPITAL LETTER F #
+1D509 ; 0046 ; MA # ( 𝔉 → F ) MATHEMATICAL FRAKTUR CAPITAL F → LATIN CAPITAL LETTER F #
+1D53D ; 0046 ; MA # ( 𝔽 → F ) MATHEMATICAL DOUBLE-STRUCK CAPITAL F → LATIN CAPITAL LETTER F #
+1D571 ; 0046 ; MA # ( 𝕱 → F ) MATHEMATICAL BOLD FRAKTUR CAPITAL F → LATIN CAPITAL LETTER F #
+1D5A5 ; 0046 ; MA # ( 𝖥 → F ) MATHEMATICAL SANS-SERIF CAPITAL F → LATIN CAPITAL LETTER F #
+1D5D9 ; 0046 ; MA # ( 𝗙 → F ) MATHEMATICAL SANS-SERIF BOLD CAPITAL F → LATIN CAPITAL LETTER F #
+1D60D ; 0046 ; MA # ( 𝘍 → F ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL F → LATIN CAPITAL LETTER F #
+1D641 ; 0046 ; MA # ( 𝙁 → F ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F → LATIN CAPITAL LETTER F #
+1D675 ; 0046 ; MA # ( 𝙵 → F ) MATHEMATICAL MONOSPACE CAPITAL F → LATIN CAPITAL LETTER F #
+A798 ; 0046 ; MA # ( Ꞙ → F ) LATIN CAPITAL LETTER F WITH STROKE → LATIN CAPITAL LETTER F #
+03DC ; 0046 ; MA # ( Ϝ → F ) GREEK LETTER DIGAMMA → LATIN CAPITAL LETTER F #
+1D7CA ; 0046 ; MA # ( 𝟊 → F ) MATHEMATICAL BOLD CAPITAL DIGAMMA → LATIN CAPITAL LETTER F # →Ϝ→
+15B4 ; 0046 ; MA # ( ᖴ → F ) CANADIAN SYLLABICS BLACKFOOT WE → LATIN CAPITAL LETTER F #
+A4DD ; 0046 ; MA # ( ꓝ → F ) LISU LETTER TSA → LATIN CAPITAL LETTER F #
+118C2 ; 0046 ; MA # ( 𑣂 → F ) WARANG CITI SMALL LETTER WI → LATIN CAPITAL LETTER F #
+118A2 ; 0046 ; MA # ( 𑢢 → F ) WARANG CITI CAPITAL LETTER WI → LATIN CAPITAL LETTER F #
+10287 ; 0046 ; MA # ( 𐊇 → F ) LYCIAN LETTER W → LATIN CAPITAL LETTER F #
+102A5 ; 0046 ; MA # ( 𐊥 → F ) CARIAN LETTER R → LATIN CAPITAL LETTER F #
+10525 ; 0046 ; MA # ( 𐔥 → F ) ELBASAN LETTER GHE → LATIN CAPITAL LETTER F #
+
+0192 ; 0066 0326 ; MA # ( ƒ → f̦ ) LATIN SMALL LETTER F WITH HOOK → LATIN SMALL LETTER F, COMBINING COMMA BELOW # →f̡→
+
+0191 ; 0046 0326 ; MA # ( Ƒ → F̦ ) LATIN CAPITAL LETTER F WITH HOOK → LATIN CAPITAL LETTER F, COMBINING COMMA BELOW # →F̡→
+
+1D6E ; 0066 0334 ; MA # ( ᵮ → f̴ ) LATIN SMALL LETTER F WITH MIDDLE TILDE → LATIN SMALL LETTER F, COMBINING TILDE OVERLAY #
+
+213B ; 0046 0041 0058 ; MA #* ( ℻ → FAX ) FACSIMILE SIGN → LATIN CAPITAL LETTER F, LATIN CAPITAL LETTER A, LATIN CAPITAL LETTER X #
+
+FB00 ; 0066 0066 ; MA # ( ff → ff ) LATIN SMALL LIGATURE FF → LATIN SMALL LETTER F, LATIN SMALL LETTER F #
+
+FB03 ; 0066 0066 0069 ; MA # ( ffi → ffi ) LATIN SMALL LIGATURE FFI → LATIN SMALL LETTER F, LATIN SMALL LETTER F, LATIN SMALL LETTER I #
+
+FB04 ; 0066 0066 006C ; MA # ( ffl → ffl ) LATIN SMALL LIGATURE FFL → LATIN SMALL LETTER F, LATIN SMALL LETTER F, LATIN SMALL LETTER L #
+
+FB01 ; 0066 0069 ; MA # ( fi → fi ) LATIN SMALL LIGATURE FI → LATIN SMALL LETTER F, LATIN SMALL LETTER I #
+
+FB02 ; 0066 006C ; MA # ( fl → fl ) LATIN SMALL LIGATURE FL → LATIN SMALL LETTER F, LATIN SMALL LETTER L #
+
+02A9 ; 0066 014B ; MA # ( ʩ → fŋ ) LATIN SMALL LETTER FENG DIGRAPH → LATIN SMALL LETTER F, LATIN SMALL LETTER ENG #
+
+15B5 ; 2132 ; MA # ( ᖵ → Ⅎ ) CANADIAN SYLLABICS BLACKFOOT WI → TURNED CAPITAL F #
+A4DE ; 2132 ; MA # ( ꓞ → Ⅎ ) LISU LETTER TSHA → TURNED CAPITAL F #
+
+1D230 ; A7FB ; MA #* ( 𝈰 → ꟻ ) GREEK INSTRUMENTAL NOTATION SYMBOL-30 → LATIN EPIGRAPHIC LETTER REVERSED F #
+15B7 ; A7FB ; MA # ( ᖷ → ꟻ ) CANADIAN SYLLABICS BLACKFOOT WA → LATIN EPIGRAPHIC LETTER REVERSED F #
+
+FF47 ; 0067 ; MA # ( g → g ) FULLWIDTH LATIN SMALL LETTER G → LATIN SMALL LETTER G # →ɡ→
+210A ; 0067 ; MA # ( ℊ → g ) SCRIPT SMALL G → LATIN SMALL LETTER G #
+1D420 ; 0067 ; MA # ( 𝐠 → g ) MATHEMATICAL BOLD SMALL G → LATIN SMALL LETTER G #
+1D454 ; 0067 ; MA # ( 𝑔 → g ) MATHEMATICAL ITALIC SMALL G → LATIN SMALL LETTER G #
+1D488 ; 0067 ; MA # ( 𝒈 → g ) MATHEMATICAL BOLD ITALIC SMALL G → LATIN SMALL LETTER G #
+1D4F0 ; 0067 ; MA # ( 𝓰 → g ) MATHEMATICAL BOLD SCRIPT SMALL G → LATIN SMALL LETTER G #
+1D524 ; 0067 ; MA # ( 𝔤 → g ) MATHEMATICAL FRAKTUR SMALL G → LATIN SMALL LETTER G #
+1D558 ; 0067 ; MA # ( 𝕘 → g ) MATHEMATICAL DOUBLE-STRUCK SMALL G → LATIN SMALL LETTER G #
+1D58C ; 0067 ; MA # ( 𝖌 → g ) MATHEMATICAL BOLD FRAKTUR SMALL G → LATIN SMALL LETTER G #
+1D5C0 ; 0067 ; MA # ( 𝗀 → g ) MATHEMATICAL SANS-SERIF SMALL G → LATIN SMALL LETTER G #
+1D5F4 ; 0067 ; MA # ( 𝗴 → g ) MATHEMATICAL SANS-SERIF BOLD SMALL G → LATIN SMALL LETTER G #
+1D628 ; 0067 ; MA # ( 𝘨 → g ) MATHEMATICAL SANS-SERIF ITALIC SMALL G → LATIN SMALL LETTER G #
+1D65C ; 0067 ; MA # ( 𝙜 → g ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G → LATIN SMALL LETTER G #
+1D690 ; 0067 ; MA # ( 𝚐 → g ) MATHEMATICAL MONOSPACE SMALL G → LATIN SMALL LETTER G #
+0261 ; 0067 ; MA # ( ɡ → g ) LATIN SMALL LETTER SCRIPT G → LATIN SMALL LETTER G #
+1D83 ; 0067 ; MA # ( ᶃ → g ) LATIN SMALL LETTER G WITH PALATAL HOOK → LATIN SMALL LETTER G #
+018D ; 0067 ; MA # ( ƍ → g ) LATIN SMALL LETTER TURNED DELTA → LATIN SMALL LETTER G #
+0581 ; 0067 ; MA # ( ց → g ) ARMENIAN SMALL LETTER CO → LATIN SMALL LETTER G #
+
+1D406 ; 0047 ; MA # ( 𝐆 → G ) MATHEMATICAL BOLD CAPITAL G → LATIN CAPITAL LETTER G #
+1D43A ; 0047 ; MA # ( 𝐺 → G ) MATHEMATICAL ITALIC CAPITAL G → LATIN CAPITAL LETTER G #
+1D46E ; 0047 ; MA # ( 𝑮 → G ) MATHEMATICAL BOLD ITALIC CAPITAL G → LATIN CAPITAL LETTER G #
+1D4A2 ; 0047 ; MA # ( 𝒢 → G ) MATHEMATICAL SCRIPT CAPITAL G → LATIN CAPITAL LETTER G #
+1D4D6 ; 0047 ; MA # ( 𝓖 → G ) MATHEMATICAL BOLD SCRIPT CAPITAL G → LATIN CAPITAL LETTER G #
+1D50A ; 0047 ; MA # ( 𝔊 → G ) MATHEMATICAL FRAKTUR CAPITAL G → LATIN CAPITAL LETTER G #
+1D53E ; 0047 ; MA # ( 𝔾 → G ) MATHEMATICAL DOUBLE-STRUCK CAPITAL G → LATIN CAPITAL LETTER G #
+1D572 ; 0047 ; MA # ( 𝕲 → G ) MATHEMATICAL BOLD FRAKTUR CAPITAL G → LATIN CAPITAL LETTER G #
+1D5A6 ; 0047 ; MA # ( 𝖦 → G ) MATHEMATICAL SANS-SERIF CAPITAL G → LATIN CAPITAL LETTER G #
+1D5DA ; 0047 ; MA # ( 𝗚 → G ) MATHEMATICAL SANS-SERIF BOLD CAPITAL G → LATIN CAPITAL LETTER G #
+1D60E ; 0047 ; MA # ( 𝘎 → G ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL G → LATIN CAPITAL LETTER G #
+1D642 ; 0047 ; MA # ( 𝙂 → G ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G → LATIN CAPITAL LETTER G #
+1D676 ; 0047 ; MA # ( 𝙶 → G ) MATHEMATICAL MONOSPACE CAPITAL G → LATIN CAPITAL LETTER G #
+050C ; 0047 ; MA # ( Ԍ → G ) CYRILLIC CAPITAL LETTER KOMI SJE → LATIN CAPITAL LETTER G #
+13C0 ; 0047 ; MA # ( Ꮐ → G ) CHEROKEE LETTER NAH → LATIN CAPITAL LETTER G #
+13F3 ; 0047 ; MA # ( Ᏻ → G ) CHEROKEE LETTER YU → LATIN CAPITAL LETTER G #
+A4D6 ; 0047 ; MA # ( ꓖ → G ) LISU LETTER GA → LATIN CAPITAL LETTER G #
+
+1DA2 ; 1D4D ; MA # ( ᶢ → ᵍ ) MODIFIER LETTER SMALL SCRIPT G → MODIFIER LETTER SMALL G #
+
+0260 ; 0067 0314 ; MA # ( ɠ → g̔ ) LATIN SMALL LETTER G WITH HOOK → LATIN SMALL LETTER G, COMBINING REVERSED COMMA ABOVE #
+
+01E7 ; 011F ; MA # ( ǧ → ğ ) LATIN SMALL LETTER G WITH CARON → LATIN SMALL LETTER G WITH BREVE #
+
+01E6 ; 011E ; MA # ( Ǧ → Ğ ) LATIN CAPITAL LETTER G WITH CARON → LATIN CAPITAL LETTER G WITH BREVE #
+
+01F5 ; 0123 ; MA # ( ǵ → ģ ) LATIN SMALL LETTER G WITH ACUTE → LATIN SMALL LETTER G WITH CEDILLA #
+
+01E5 ; 0067 0335 ; MA # ( ǥ → g̵ ) LATIN SMALL LETTER G WITH STROKE → LATIN SMALL LETTER G, COMBINING SHORT STROKE OVERLAY #
+
+01E4 ; 0047 0335 ; MA # ( Ǥ → G̵ ) LATIN CAPITAL LETTER G WITH STROKE → LATIN CAPITAL LETTER G, COMBINING SHORT STROKE OVERLAY #
+
+0193 ; 0047 0027 ; MA # ( Ɠ → G' ) LATIN CAPITAL LETTER G WITH HOOK → LATIN CAPITAL LETTER G, APOSTROPHE # →Gʽ→
+
+050D ; 0262 ; MA # ( ԍ → ɢ ) CYRILLIC SMALL LETTER KOMI SJE → LATIN LETTER SMALL CAPITAL G #
+AB90 ; 0262 ; MA # ( ꮐ → ɢ ) CHEROKEE SMALL LETTER NAH → LATIN LETTER SMALL CAPITAL G #
+13FB ; 0262 ; MA # ( ᏻ → ɢ ) CHEROKEE SMALL LETTER YU → LATIN LETTER SMALL CAPITAL G #
+
+FF48 ; 0068 ; MA # ( h → h ) FULLWIDTH LATIN SMALL LETTER H → LATIN SMALL LETTER H # →һ→
+210E ; 0068 ; MA # ( ℎ → h ) PLANCK CONSTANT → LATIN SMALL LETTER H #
+1D421 ; 0068 ; MA # ( 𝐡 → h ) MATHEMATICAL BOLD SMALL H → LATIN SMALL LETTER H #
+1D489 ; 0068 ; MA # ( 𝒉 → h ) MATHEMATICAL BOLD ITALIC SMALL H → LATIN SMALL LETTER H #
+1D4BD ; 0068 ; MA # ( 𝒽 → h ) MATHEMATICAL SCRIPT SMALL H → LATIN SMALL LETTER H #
+1D4F1 ; 0068 ; MA # ( 𝓱 → h ) MATHEMATICAL BOLD SCRIPT SMALL H → LATIN SMALL LETTER H #
+1D525 ; 0068 ; MA # ( 𝔥 → h ) MATHEMATICAL FRAKTUR SMALL H → LATIN SMALL LETTER H #
+1D559 ; 0068 ; MA # ( 𝕙 → h ) MATHEMATICAL DOUBLE-STRUCK SMALL H → LATIN SMALL LETTER H #
+1D58D ; 0068 ; MA # ( 𝖍 → h ) MATHEMATICAL BOLD FRAKTUR SMALL H → LATIN SMALL LETTER H #
+1D5C1 ; 0068 ; MA # ( 𝗁 → h ) MATHEMATICAL SANS-SERIF SMALL H → LATIN SMALL LETTER H #
+1D5F5 ; 0068 ; MA # ( 𝗵 → h ) MATHEMATICAL SANS-SERIF BOLD SMALL H → LATIN SMALL LETTER H #
+1D629 ; 0068 ; MA # ( 𝘩 → h ) MATHEMATICAL SANS-SERIF ITALIC SMALL H → LATIN SMALL LETTER H #
+1D65D ; 0068 ; MA # ( 𝙝 → h ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H → LATIN SMALL LETTER H #
+1D691 ; 0068 ; MA # ( 𝚑 → h ) MATHEMATICAL MONOSPACE SMALL H → LATIN SMALL LETTER H #
+04BB ; 0068 ; MA # ( һ → h ) CYRILLIC SMALL LETTER SHHA → LATIN SMALL LETTER H #
+0570 ; 0068 ; MA # ( հ → h ) ARMENIAN SMALL LETTER HO → LATIN SMALL LETTER H #
+13C2 ; 0068 ; MA # ( Ꮒ → h ) CHEROKEE LETTER NI → LATIN SMALL LETTER H #
+
+FF28 ; 0048 ; MA # ( H → H ) FULLWIDTH LATIN CAPITAL LETTER H → LATIN CAPITAL LETTER H # →Η→
+210B ; 0048 ; MA # ( ℋ → H ) SCRIPT CAPITAL H → LATIN CAPITAL LETTER H #
+210C ; 0048 ; MA # ( ℌ → H ) BLACK-LETTER CAPITAL H → LATIN CAPITAL LETTER H #
+210D ; 0048 ; MA # ( ℍ → H ) DOUBLE-STRUCK CAPITAL H → LATIN CAPITAL LETTER H #
+1D407 ; 0048 ; MA # ( 𝐇 → H ) MATHEMATICAL BOLD CAPITAL H → LATIN CAPITAL LETTER H #
+1D43B ; 0048 ; MA # ( 𝐻 → H ) MATHEMATICAL ITALIC CAPITAL H → LATIN CAPITAL LETTER H #
+1D46F ; 0048 ; MA # ( 𝑯 → H ) MATHEMATICAL BOLD ITALIC CAPITAL H → LATIN CAPITAL LETTER H #
+1D4D7 ; 0048 ; MA # ( 𝓗 → H ) MATHEMATICAL BOLD SCRIPT CAPITAL H → LATIN CAPITAL LETTER H #
+1D573 ; 0048 ; MA # ( 𝕳 → H ) MATHEMATICAL BOLD FRAKTUR CAPITAL H → LATIN CAPITAL LETTER H #
+1D5A7 ; 0048 ; MA # ( 𝖧 → H ) MATHEMATICAL SANS-SERIF CAPITAL H → LATIN CAPITAL LETTER H #
+1D5DB ; 0048 ; MA # ( 𝗛 → H ) MATHEMATICAL SANS-SERIF BOLD CAPITAL H → LATIN CAPITAL LETTER H #
+1D60F ; 0048 ; MA # ( 𝘏 → H ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL H → LATIN CAPITAL LETTER H #
+1D643 ; 0048 ; MA # ( 𝙃 → H ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H → LATIN CAPITAL LETTER H #
+1D677 ; 0048 ; MA # ( 𝙷 → H ) MATHEMATICAL MONOSPACE CAPITAL H → LATIN CAPITAL LETTER H #
+0397 ; 0048 ; MA # ( Η → H ) GREEK CAPITAL LETTER ETA → LATIN CAPITAL LETTER H #
+1D6AE ; 0048 ; MA # ( 𝚮 → H ) MATHEMATICAL BOLD CAPITAL ETA → LATIN CAPITAL LETTER H # →Η→
+1D6E8 ; 0048 ; MA # ( 𝛨 → H ) MATHEMATICAL ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H # →Η→
+1D722 ; 0048 ; MA # ( 𝜢 → H ) MATHEMATICAL BOLD ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H # →𝑯→
+1D75C ; 0048 ; MA # ( 𝝜 → H ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA → LATIN CAPITAL LETTER H # →Η→
+1D796 ; 0048 ; MA # ( 𝞖 → H ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA → LATIN CAPITAL LETTER H # →Η→
+2C8E ; 0048 ; MA # ( Ⲏ → H ) COPTIC CAPITAL LETTER HATE → LATIN CAPITAL LETTER H # →Η→
+041D ; 0048 ; MA # ( Н → H ) CYRILLIC CAPITAL LETTER EN → LATIN CAPITAL LETTER H #
+13BB ; 0048 ; MA # ( Ꮋ → H ) CHEROKEE LETTER MI → LATIN CAPITAL LETTER H #
+157C ; 0048 ; MA # ( ᕼ → H ) CANADIAN SYLLABICS NUNAVUT H → LATIN CAPITAL LETTER H #
+A4E7 ; 0048 ; MA # ( ꓧ → H ) LISU LETTER XA → LATIN CAPITAL LETTER H #
+102CF ; 0048 ; MA # ( 𐋏 → H ) CARIAN LETTER E2 → LATIN CAPITAL LETTER H #
+
+1D78 ; 1D34 ; MA # ( ᵸ → ᴴ ) MODIFIER LETTER CYRILLIC EN → MODIFIER LETTER CAPITAL H #
+
+0266 ; 0068 0314 ; MA # ( ɦ → h̔ ) LATIN SMALL LETTER H WITH HOOK → LATIN SMALL LETTER H, COMBINING REVERSED COMMA ABOVE #
+A695 ; 0068 0314 ; MA # ( ꚕ → h̔ ) CYRILLIC SMALL LETTER HWE → LATIN SMALL LETTER H, COMBINING REVERSED COMMA ABOVE # →ɦ→
+13F2 ; 0068 0314 ; MA # ( Ᏺ → h̔ ) CHEROKEE LETTER YO → LATIN SMALL LETTER H, COMBINING REVERSED COMMA ABOVE #
+
+2C67 ; 0048 0329 ; MA # ( Ⱨ → H̩ ) LATIN CAPITAL LETTER H WITH DESCENDER → LATIN CAPITAL LETTER H, COMBINING VERTICAL LINE BELOW # →Ң→→Н̩→
+04A2 ; 0048 0329 ; MA # ( Ң → H̩ ) CYRILLIC CAPITAL LETTER EN WITH DESCENDER → LATIN CAPITAL LETTER H, COMBINING VERTICAL LINE BELOW # →Н̩→
+
+0127 ; 0068 0335 ; MA # ( ħ → h̵ ) LATIN SMALL LETTER H WITH STROKE → LATIN SMALL LETTER H, COMBINING SHORT STROKE OVERLAY #
+210F ; 0068 0335 ; MA # ( ℏ → h̵ ) PLANCK CONSTANT OVER TWO PI → LATIN SMALL LETTER H, COMBINING SHORT STROKE OVERLAY # →ħ→
+045B ; 0068 0335 ; MA # ( ћ → h̵ ) CYRILLIC SMALL LETTER TSHE → LATIN SMALL LETTER H, COMBINING SHORT STROKE OVERLAY # →ħ→
+
+0126 ; 0048 0335 ; MA # ( Ħ → H̵ ) LATIN CAPITAL LETTER H WITH STROKE → LATIN CAPITAL LETTER H, COMBINING SHORT STROKE OVERLAY #
+
+04C9 ; 0048 0326 ; MA # ( Ӊ → H̦ ) CYRILLIC CAPITAL LETTER EN WITH TAIL → LATIN CAPITAL LETTER H, COMBINING COMMA BELOW # →Н̡→
+04C7 ; 0048 0326 ; MA # ( Ӈ → H̦ ) CYRILLIC CAPITAL LETTER EN WITH HOOK → LATIN CAPITAL LETTER H, COMBINING COMMA BELOW # →Н̡→
+
+043D ; 029C ; MA # ( н → ʜ ) CYRILLIC SMALL LETTER EN → LATIN LETTER SMALL CAPITAL H #
+AB8B ; 029C ; MA # ( ꮋ → ʜ ) CHEROKEE SMALL LETTER MI → LATIN LETTER SMALL CAPITAL H #
+
+04A3 ; 029C 0329 ; MA # ( ң → ʜ̩ ) CYRILLIC SMALL LETTER EN WITH DESCENDER → LATIN LETTER SMALL CAPITAL H, COMBINING VERTICAL LINE BELOW # →н̩→
+
+04CA ; 029C 0326 ; MA # ( ӊ → ʜ̦ ) CYRILLIC SMALL LETTER EN WITH TAIL → LATIN LETTER SMALL CAPITAL H, COMBINING COMMA BELOW # →н̡→
+04C8 ; 029C 0326 ; MA # ( ӈ → ʜ̦ ) CYRILLIC SMALL LETTER EN WITH HOOK → LATIN LETTER SMALL CAPITAL H, COMBINING COMMA BELOW # →н̡→
+
+050A ; 01F6 ; MA # ( Ԋ → Ƕ ) CYRILLIC CAPITAL LETTER KOMI NJE → LATIN CAPITAL LETTER HWAIR #
+
+AB80 ; 2C76 ; MA # ( ꮀ → ⱶ ) CHEROKEE SMALL LETTER HO → LATIN SMALL LETTER HALF H #
+
+0370 ; 2C75 ; MA # ( Ͱ → Ⱶ ) GREEK CAPITAL LETTER HETA → LATIN CAPITAL LETTER HALF H # →Ꮀ→
+13A8 ; 2C75 ; MA # ( Ꭸ → Ⱶ ) CHEROKEE LETTER GE → LATIN CAPITAL LETTER HALF H # →Ͱ→→Ꮀ→
+13B0 ; 2C75 ; MA # ( Ꮀ → Ⱶ ) CHEROKEE LETTER HO → LATIN CAPITAL LETTER HALF H #
+A6B1 ; 2C75 ; MA # ( ꚱ → Ⱶ ) BAMUM LETTER NDAA → LATIN CAPITAL LETTER HALF H # →Ͱ→→Ꮀ→
+
+A795 ; A727 ; MA # ( ꞕ → ꜧ ) LATIN SMALL LETTER H WITH PALATAL HOOK → LATIN SMALL LETTER HENG #
+
+02DB ; 0069 ; MA #* ( ˛ → i ) OGONEK → LATIN SMALL LETTER I # →ͺ→→ι→→ι→
+2373 ; 0069 ; MA #* ( ⍳ → i ) APL FUNCTIONAL SYMBOL IOTA → LATIN SMALL LETTER I # →ι→
+FF49 ; 0069 ; MA # ( i → i ) FULLWIDTH LATIN SMALL LETTER I → LATIN SMALL LETTER I # →і→
+2170 ; 0069 ; MA # ( ⅰ → i ) SMALL ROMAN NUMERAL ONE → LATIN SMALL LETTER I #
+2139 ; 0069 ; MA # ( ℹ → i ) INFORMATION SOURCE → LATIN SMALL LETTER I #
+2148 ; 0069 ; MA # ( ⅈ → i ) DOUBLE-STRUCK ITALIC SMALL I → LATIN SMALL LETTER I #
+1D422 ; 0069 ; MA # ( 𝐢 → i ) MATHEMATICAL BOLD SMALL I → LATIN SMALL LETTER I #
+1D456 ; 0069 ; MA # ( 𝑖 → i ) MATHEMATICAL ITALIC SMALL I → LATIN SMALL LETTER I #
+1D48A ; 0069 ; MA # ( 𝒊 → i ) MATHEMATICAL BOLD ITALIC SMALL I → LATIN SMALL LETTER I #
+1D4BE ; 0069 ; MA # ( 𝒾 → i ) MATHEMATICAL SCRIPT SMALL I → LATIN SMALL LETTER I #
+1D4F2 ; 0069 ; MA # ( 𝓲 → i ) MATHEMATICAL BOLD SCRIPT SMALL I → LATIN SMALL LETTER I #
+1D526 ; 0069 ; MA # ( 𝔦 → i ) MATHEMATICAL FRAKTUR SMALL I → LATIN SMALL LETTER I #
+1D55A ; 0069 ; MA # ( 𝕚 → i ) MATHEMATICAL DOUBLE-STRUCK SMALL I → LATIN SMALL LETTER I #
+1D58E ; 0069 ; MA # ( 𝖎 → i ) MATHEMATICAL BOLD FRAKTUR SMALL I → LATIN SMALL LETTER I #
+1D5C2 ; 0069 ; MA # ( 𝗂 → i ) MATHEMATICAL SANS-SERIF SMALL I → LATIN SMALL LETTER I #
+1D5F6 ; 0069 ; MA # ( 𝗶 → i ) MATHEMATICAL SANS-SERIF BOLD SMALL I → LATIN SMALL LETTER I #
+1D62A ; 0069 ; MA # ( 𝘪 → i ) MATHEMATICAL SANS-SERIF ITALIC SMALL I → LATIN SMALL LETTER I #
+1D65E ; 0069 ; MA # ( 𝙞 → i ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I → LATIN SMALL LETTER I #
+1D692 ; 0069 ; MA # ( 𝚒 → i ) MATHEMATICAL MONOSPACE SMALL I → LATIN SMALL LETTER I #
+0131 ; 0069 ; MA # ( ı → i ) LATIN SMALL LETTER DOTLESS I → LATIN SMALL LETTER I #
+1D6A4 ; 0069 ; MA # ( 𝚤 → i ) MATHEMATICAL ITALIC SMALL DOTLESS I → LATIN SMALL LETTER I # →ı→
+026A ; 0069 ; MA # ( ɪ → i ) LATIN LETTER SMALL CAPITAL I → LATIN SMALL LETTER I # →ı→
+0269 ; 0069 ; MA # ( ɩ → i ) LATIN SMALL LETTER IOTA → LATIN SMALL LETTER I #
+03B9 ; 0069 ; MA # ( ι → i ) GREEK SMALL LETTER IOTA → LATIN SMALL LETTER I #
+1FBE ; 0069 ; MA # ( ι → i ) GREEK PROSGEGRAMMENI → LATIN SMALL LETTER I # →ι→
+037A ; 0069 ; MA #* ( ͺ → i ) GREEK YPOGEGRAMMENI → LATIN SMALL LETTER I # →ι→→ι→
+1D6CA ; 0069 ; MA # ( 𝛊 → i ) MATHEMATICAL BOLD SMALL IOTA → LATIN SMALL LETTER I # →ι→
+1D704 ; 0069 ; MA # ( 𝜄 → i ) MATHEMATICAL ITALIC SMALL IOTA → LATIN SMALL LETTER I # →ι→
+1D73E ; 0069 ; MA # ( 𝜾 → i ) MATHEMATICAL BOLD ITALIC SMALL IOTA → LATIN SMALL LETTER I # →ι→
+1D778 ; 0069 ; MA # ( 𝝸 → i ) MATHEMATICAL SANS-SERIF BOLD SMALL IOTA → LATIN SMALL LETTER I # →ι→
+1D7B2 ; 0069 ; MA # ( 𝞲 → i ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA → LATIN SMALL LETTER I # →ι→
+0456 ; 0069 ; MA # ( і → i ) CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I → LATIN SMALL LETTER I #
+A647 ; 0069 ; MA # ( ꙇ → i ) CYRILLIC SMALL LETTER IOTA → LATIN SMALL LETTER I # →ι→
+04CF ; 0069 ; MA # ( ӏ → i ) CYRILLIC SMALL LETTER PALOCHKA → LATIN SMALL LETTER I # →ı→
+AB75 ; 0069 ; MA # ( ꭵ → i ) CHEROKEE SMALL LETTER V → LATIN SMALL LETTER I #
+13A5 ; 0069 ; MA # ( Ꭵ → i ) CHEROKEE LETTER V → LATIN SMALL LETTER I #
+118C3 ; 0069 ; MA # ( 𑣃 → i ) WARANG CITI SMALL LETTER YU → LATIN SMALL LETTER I # →ι→
+
+24DB ; 24BE ; MA #* ( ⓛ → Ⓘ ) CIRCLED LATIN SMALL LETTER L → CIRCLED LATIN CAPITAL LETTER I #
+
+2378 ; 0069 0332 ; MA #* ( ⍸ → i̲ ) APL FUNCTIONAL SYMBOL IOTA UNDERBAR → LATIN SMALL LETTER I, COMBINING LOW LINE # →ι̲→
+
+01D0 ; 012D ; MA # ( ǐ → ĭ ) LATIN SMALL LETTER I WITH CARON → LATIN SMALL LETTER I WITH BREVE #
+
+01CF ; 012C ; MA # ( Ǐ → Ĭ ) LATIN CAPITAL LETTER I WITH CARON → LATIN CAPITAL LETTER I WITH BREVE #
+
+0268 ; 0069 0335 ; MA # ( ɨ → i̵ ) LATIN SMALL LETTER I WITH STROKE → LATIN SMALL LETTER I, COMBINING SHORT STROKE OVERLAY #
+1D7B ; 0069 0335 ; MA # ( ᵻ → i̵ ) LATIN SMALL CAPITAL LETTER I WITH STROKE → LATIN SMALL LETTER I, COMBINING SHORT STROKE OVERLAY # →ɪ̵→
+1D7C ; 0069 0335 ; MA # ( ᵼ → i̵ ) LATIN SMALL LETTER IOTA WITH STROKE → LATIN SMALL LETTER I, COMBINING SHORT STROKE OVERLAY # →ɩ̵→
+
+2171 ; 0069 0069 ; MA # ( ⅱ → ii ) SMALL ROMAN NUMERAL TWO → LATIN SMALL LETTER I, LATIN SMALL LETTER I #
+
+2172 ; 0069 0069 0069 ; MA # ( ⅲ → iii ) SMALL ROMAN NUMERAL THREE → LATIN SMALL LETTER I, LATIN SMALL LETTER I, LATIN SMALL LETTER I #
+
+0133 ; 0069 006A ; MA # ( ij → ij ) LATIN SMALL LIGATURE IJ → LATIN SMALL LETTER I, LATIN SMALL LETTER J #
+
+2173 ; 0069 0076 ; MA # ( ⅳ → iv ) SMALL ROMAN NUMERAL FOUR → LATIN SMALL LETTER I, LATIN SMALL LETTER V #
+
+2178 ; 0069 0078 ; MA # ( ⅸ → ix ) SMALL ROMAN NUMERAL NINE → LATIN SMALL LETTER I, LATIN SMALL LETTER X #
+
+FF4A ; 006A ; MA # ( j → j ) FULLWIDTH LATIN SMALL LETTER J → LATIN SMALL LETTER J # →ϳ→
+2149 ; 006A ; MA # ( ⅉ → j ) DOUBLE-STRUCK ITALIC SMALL J → LATIN SMALL LETTER J #
+1D423 ; 006A ; MA # ( 𝐣 → j ) MATHEMATICAL BOLD SMALL J → LATIN SMALL LETTER J #
+1D457 ; 006A ; MA # ( 𝑗 → j ) MATHEMATICAL ITALIC SMALL J → LATIN SMALL LETTER J #
+1D48B ; 006A ; MA # ( 𝒋 → j ) MATHEMATICAL BOLD ITALIC SMALL J → LATIN SMALL LETTER J #
+1D4BF ; 006A ; MA # ( 𝒿 → j ) MATHEMATICAL SCRIPT SMALL J → LATIN SMALL LETTER J #
+1D4F3 ; 006A ; MA # ( 𝓳 → j ) MATHEMATICAL BOLD SCRIPT SMALL J → LATIN SMALL LETTER J #
+1D527 ; 006A ; MA # ( 𝔧 → j ) MATHEMATICAL FRAKTUR SMALL J → LATIN SMALL LETTER J #
+1D55B ; 006A ; MA # ( 𝕛 → j ) MATHEMATICAL DOUBLE-STRUCK SMALL J → LATIN SMALL LETTER J #
+1D58F ; 006A ; MA # ( 𝖏 → j ) MATHEMATICAL BOLD FRAKTUR SMALL J → LATIN SMALL LETTER J #
+1D5C3 ; 006A ; MA # ( 𝗃 → j ) MATHEMATICAL SANS-SERIF SMALL J → LATIN SMALL LETTER J #
+1D5F7 ; 006A ; MA # ( 𝗷 → j ) MATHEMATICAL SANS-SERIF BOLD SMALL J → LATIN SMALL LETTER J #
+1D62B ; 006A ; MA # ( 𝘫 → j ) MATHEMATICAL SANS-SERIF ITALIC SMALL J → LATIN SMALL LETTER J #
+1D65F ; 006A ; MA # ( 𝙟 → j ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J → LATIN SMALL LETTER J #
+1D693 ; 006A ; MA # ( 𝚓 → j ) MATHEMATICAL MONOSPACE SMALL J → LATIN SMALL LETTER J #
+03F3 ; 006A ; MA # ( ϳ → j ) GREEK LETTER YOT → LATIN SMALL LETTER J #
+0458 ; 006A ; MA # ( ј → j ) CYRILLIC SMALL LETTER JE → LATIN SMALL LETTER J #
+
+FF2A ; 004A ; MA # ( J → J ) FULLWIDTH LATIN CAPITAL LETTER J → LATIN CAPITAL LETTER J # →Ј→
+1D409 ; 004A ; MA # ( 𝐉 → J ) MATHEMATICAL BOLD CAPITAL J → LATIN CAPITAL LETTER J #
+1D43D ; 004A ; MA # ( 𝐽 → J ) MATHEMATICAL ITALIC CAPITAL J → LATIN CAPITAL LETTER J #
+1D471 ; 004A ; MA # ( 𝑱 → J ) MATHEMATICAL BOLD ITALIC CAPITAL J → LATIN CAPITAL LETTER J #
+1D4A5 ; 004A ; MA # ( 𝒥 → J ) MATHEMATICAL SCRIPT CAPITAL J → LATIN CAPITAL LETTER J #
+1D4D9 ; 004A ; MA # ( 𝓙 → J ) MATHEMATICAL BOLD SCRIPT CAPITAL J → LATIN CAPITAL LETTER J #
+1D50D ; 004A ; MA # ( 𝔍 → J ) MATHEMATICAL FRAKTUR CAPITAL J → LATIN CAPITAL LETTER J #
+1D541 ; 004A ; MA # ( 𝕁 → J ) MATHEMATICAL DOUBLE-STRUCK CAPITAL J → LATIN CAPITAL LETTER J #
+1D575 ; 004A ; MA # ( 𝕵 → J ) MATHEMATICAL BOLD FRAKTUR CAPITAL J → LATIN CAPITAL LETTER J #
+1D5A9 ; 004A ; MA # ( 𝖩 → J ) MATHEMATICAL SANS-SERIF CAPITAL J → LATIN CAPITAL LETTER J #
+1D5DD ; 004A ; MA # ( 𝗝 → J ) MATHEMATICAL SANS-SERIF BOLD CAPITAL J → LATIN CAPITAL LETTER J #
+1D611 ; 004A ; MA # ( 𝘑 → J ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL J → LATIN CAPITAL LETTER J #
+1D645 ; 004A ; MA # ( 𝙅 → J ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J → LATIN CAPITAL LETTER J #
+1D679 ; 004A ; MA # ( 𝙹 → J ) MATHEMATICAL MONOSPACE CAPITAL J → LATIN CAPITAL LETTER J #
+A7B2 ; 004A ; MA # ( Ʝ → J ) LATIN CAPITAL LETTER J WITH CROSSED-TAIL → LATIN CAPITAL LETTER J #
+037F ; 004A ; MA # ( Ϳ → J ) GREEK CAPITAL LETTER YOT → LATIN CAPITAL LETTER J #
+0408 ; 004A ; MA # ( Ј → J ) CYRILLIC CAPITAL LETTER JE → LATIN CAPITAL LETTER J #
+13AB ; 004A ; MA # ( Ꭻ → J ) CHEROKEE LETTER GU → LATIN CAPITAL LETTER J #
+148D ; 004A ; MA # ( ᒍ → J ) CANADIAN SYLLABICS CO → LATIN CAPITAL LETTER J #
+A4D9 ; 004A ; MA # ( ꓙ → J ) LISU LETTER JA → LATIN CAPITAL LETTER J #
+
+0249 ; 006A 0335 ; MA # ( ɉ → j̵ ) LATIN SMALL LETTER J WITH STROKE → LATIN SMALL LETTER J, COMBINING SHORT STROKE OVERLAY #
+
+0248 ; 004A 0335 ; MA # ( Ɉ → J̵ ) LATIN CAPITAL LETTER J WITH STROKE → LATIN CAPITAL LETTER J, COMBINING SHORT STROKE OVERLAY #
+
+1499 ; 004A 00B7 ; MA # ( ᒙ → J· ) CANADIAN SYLLABICS WEST-CREE CWO → LATIN CAPITAL LETTER J, MIDDLE DOT # →ᒍᐧ→
+
+1D6A5 ; 0237 ; MA # ( 𝚥 → ȷ ) MATHEMATICAL ITALIC SMALL DOTLESS J → LATIN SMALL LETTER DOTLESS J #
+0575 ; 0237 ; MA # ( յ → ȷ ) ARMENIAN SMALL LETTER YI → LATIN SMALL LETTER DOTLESS J #
+
+AB7B ; 1D0A ; MA # ( ꭻ → ᴊ ) CHEROKEE SMALL LETTER GU → LATIN LETTER SMALL CAPITAL J #
+
+1D424 ; 006B ; MA # ( 𝐤 → k ) MATHEMATICAL BOLD SMALL K → LATIN SMALL LETTER K #
+1D458 ; 006B ; MA # ( 𝑘 → k ) MATHEMATICAL ITALIC SMALL K → LATIN SMALL LETTER K #
+1D48C ; 006B ; MA # ( 𝒌 → k ) MATHEMATICAL BOLD ITALIC SMALL K → LATIN SMALL LETTER K #
+1D4C0 ; 006B ; MA # ( 𝓀 → k ) MATHEMATICAL SCRIPT SMALL K → LATIN SMALL LETTER K #
+1D4F4 ; 006B ; MA # ( 𝓴 → k ) MATHEMATICAL BOLD SCRIPT SMALL K → LATIN SMALL LETTER K #
+1D528 ; 006B ; MA # ( 𝔨 → k ) MATHEMATICAL FRAKTUR SMALL K → LATIN SMALL LETTER K #
+1D55C ; 006B ; MA # ( 𝕜 → k ) MATHEMATICAL DOUBLE-STRUCK SMALL K → LATIN SMALL LETTER K #
+1D590 ; 006B ; MA # ( 𝖐 → k ) MATHEMATICAL BOLD FRAKTUR SMALL K → LATIN SMALL LETTER K #
+1D5C4 ; 006B ; MA # ( 𝗄 → k ) MATHEMATICAL SANS-SERIF SMALL K → LATIN SMALL LETTER K #
+1D5F8 ; 006B ; MA # ( 𝗸 → k ) MATHEMATICAL SANS-SERIF BOLD SMALL K → LATIN SMALL LETTER K #
+1D62C ; 006B ; MA # ( 𝘬 → k ) MATHEMATICAL SANS-SERIF ITALIC SMALL K → LATIN SMALL LETTER K #
+1D660 ; 006B ; MA # ( 𝙠 → k ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K → LATIN SMALL LETTER K #
+1D694 ; 006B ; MA # ( 𝚔 → k ) MATHEMATICAL MONOSPACE SMALL K → LATIN SMALL LETTER K #
+
+212A ; 004B ; MA # ( K → K ) KELVIN SIGN → LATIN CAPITAL LETTER K #
+FF2B ; 004B ; MA # ( K → K ) FULLWIDTH LATIN CAPITAL LETTER K → LATIN CAPITAL LETTER K # →Κ→
+1D40A ; 004B ; MA # ( 𝐊 → K ) MATHEMATICAL BOLD CAPITAL K → LATIN CAPITAL LETTER K #
+1D43E ; 004B ; MA # ( 𝐾 → K ) MATHEMATICAL ITALIC CAPITAL K → LATIN CAPITAL LETTER K #
+1D472 ; 004B ; MA # ( 𝑲 → K ) MATHEMATICAL BOLD ITALIC CAPITAL K → LATIN CAPITAL LETTER K #
+1D4A6 ; 004B ; MA # ( 𝒦 → K ) MATHEMATICAL SCRIPT CAPITAL K → LATIN CAPITAL LETTER K #
+1D4DA ; 004B ; MA # ( 𝓚 → K ) MATHEMATICAL BOLD SCRIPT CAPITAL K → LATIN CAPITAL LETTER K #
+1D50E ; 004B ; MA # ( 𝔎 → K ) MATHEMATICAL FRAKTUR CAPITAL K → LATIN CAPITAL LETTER K #
+1D542 ; 004B ; MA # ( 𝕂 → K ) MATHEMATICAL DOUBLE-STRUCK CAPITAL K → LATIN CAPITAL LETTER K #
+1D576 ; 004B ; MA # ( 𝕶 → K ) MATHEMATICAL BOLD FRAKTUR CAPITAL K → LATIN CAPITAL LETTER K #
+1D5AA ; 004B ; MA # ( 𝖪 → K ) MATHEMATICAL SANS-SERIF CAPITAL K → LATIN CAPITAL LETTER K #
+1D5DE ; 004B ; MA # ( 𝗞 → K ) MATHEMATICAL SANS-SERIF BOLD CAPITAL K → LATIN CAPITAL LETTER K #
+1D612 ; 004B ; MA # ( 𝘒 → K ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL K → LATIN CAPITAL LETTER K #
+1D646 ; 004B ; MA # ( 𝙆 → K ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K → LATIN CAPITAL LETTER K #
+1D67A ; 004B ; MA # ( 𝙺 → K ) MATHEMATICAL MONOSPACE CAPITAL K → LATIN CAPITAL LETTER K #
+039A ; 004B ; MA # ( Κ → K ) GREEK CAPITAL LETTER KAPPA → LATIN CAPITAL LETTER K #
+1D6B1 ; 004B ; MA # ( 𝚱 → K ) MATHEMATICAL BOLD CAPITAL KAPPA → LATIN CAPITAL LETTER K # →Κ→
+1D6EB ; 004B ; MA # ( 𝛫 → K ) MATHEMATICAL ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K # →𝐾→
+1D725 ; 004B ; MA # ( 𝜥 → K ) MATHEMATICAL BOLD ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K # →𝑲→
+1D75F ; 004B ; MA # ( 𝝟 → K ) MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA → LATIN CAPITAL LETTER K # →Κ→
+1D799 ; 004B ; MA # ( 𝞙 → K ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA → LATIN CAPITAL LETTER K # →Κ→
+2C94 ; 004B ; MA # ( Ⲕ → K ) COPTIC CAPITAL LETTER KAPA → LATIN CAPITAL LETTER K # →Κ→
+041A ; 004B ; MA # ( К → K ) CYRILLIC CAPITAL LETTER KA → LATIN CAPITAL LETTER K #
+13E6 ; 004B ; MA # ( Ꮶ → K ) CHEROKEE LETTER TSO → LATIN CAPITAL LETTER K #
+16D5 ; 004B ; MA # ( ᛕ → K ) RUNIC LETTER OPEN-P → LATIN CAPITAL LETTER K #
+A4D7 ; 004B ; MA # ( ꓗ → K ) LISU LETTER KA → LATIN CAPITAL LETTER K #
+10518 ; 004B ; MA # ( 𐔘 → K ) ELBASAN LETTER QE → LATIN CAPITAL LETTER K #
+
+0199 ; 006B 0314 ; MA # ( ƙ → k̔ ) LATIN SMALL LETTER K WITH HOOK → LATIN SMALL LETTER K, COMBINING REVERSED COMMA ABOVE #
+
+2C69 ; 004B 0329 ; MA # ( Ⱪ → K̩ ) LATIN CAPITAL LETTER K WITH DESCENDER → LATIN CAPITAL LETTER K, COMBINING VERTICAL LINE BELOW # →Қ→→К̩→
+049A ; 004B 0329 ; MA # ( Қ → K̩ ) CYRILLIC CAPITAL LETTER KA WITH DESCENDER → LATIN CAPITAL LETTER K, COMBINING VERTICAL LINE BELOW # →К̩→
+
+20AD ; 004B 0335 ; MA #* ( ₭ → K̵ ) KIP SIGN → LATIN CAPITAL LETTER K, COMBINING SHORT STROKE OVERLAY # →K̶→
+A740 ; 004B 0335 ; MA # ( Ꝁ → K̵ ) LATIN CAPITAL LETTER K WITH STROKE → LATIN CAPITAL LETTER K, COMBINING SHORT STROKE OVERLAY # →Ҟ→→К̵→
+049E ; 004B 0335 ; MA # ( Ҟ → K̵ ) CYRILLIC CAPITAL LETTER KA WITH STROKE → LATIN CAPITAL LETTER K, COMBINING SHORT STROKE OVERLAY # →К̵→
+
+0198 ; 004B 0027 ; MA # ( Ƙ → K' ) LATIN CAPITAL LETTER K WITH HOOK → LATIN CAPITAL LETTER K, APOSTROPHE # →Kʽ→
+
+05C0 ; 006C ; MA #* ( ‎׀‎ → l ) HEBREW PUNCTUATION PASEQ → LATIN SMALL LETTER L # →|→
+007C ; 006C ; MA #* ( | → l ) VERTICAL LINE → LATIN SMALL LETTER L #
+2223 ; 006C ; MA #* ( ∣ → l ) DIVIDES → LATIN SMALL LETTER L # →ǀ→
+23FD ; 006C ; MA #* ( ⏽ → l ) POWER ON SYMBOL → LATIN SMALL LETTER L # →I→
+FFE8 ; 006C ; MA #* ( │ → l ) HALFWIDTH FORMS LIGHT VERTICAL → LATIN SMALL LETTER L # →|→
+0031 ; 006C ; MA # ( 1 → l ) DIGIT ONE → LATIN SMALL LETTER L #
+0661 ; 006C ; MA # ( ‎١‎ → l ) ARABIC-INDIC DIGIT ONE → LATIN SMALL LETTER L # →1→
+06F1 ; 006C ; MA # ( ۱ → l ) EXTENDED ARABIC-INDIC DIGIT ONE → LATIN SMALL LETTER L # →1→
+10320 ; 006C ; MA #* ( 𐌠 → l ) OLD ITALIC NUMERAL ONE → LATIN SMALL LETTER L # →𐌉→→I→
+1E8C7 ; 006C ; MA #* ( ‎𞣇‎ → l ) MENDE KIKAKUI DIGIT ONE → LATIN SMALL LETTER L #
+1D7CF ; 006C ; MA # ( 𝟏 → l ) MATHEMATICAL BOLD DIGIT ONE → LATIN SMALL LETTER L # →1→
+1D7D9 ; 006C ; MA # ( 𝟙 → l ) MATHEMATICAL DOUBLE-STRUCK DIGIT ONE → LATIN SMALL LETTER L # →1→
+1D7E3 ; 006C ; MA # ( 𝟣 → l ) MATHEMATICAL SANS-SERIF DIGIT ONE → LATIN SMALL LETTER L # →1→
+1D7ED ; 006C ; MA # ( 𝟭 → l ) MATHEMATICAL SANS-SERIF BOLD DIGIT ONE → LATIN SMALL LETTER L # →1→
+1D7F7 ; 006C ; MA # ( 𝟷 → l ) MATHEMATICAL MONOSPACE DIGIT ONE → LATIN SMALL LETTER L # →1→
+1FBF1 ; 006C ; MA # ( 🯱 → l ) SEGMENTED DIGIT ONE → LATIN SMALL LETTER L # →1→
+0049 ; 006C ; MA # ( I → l ) LATIN CAPITAL LETTER I → LATIN SMALL LETTER L #
+FF29 ; 006C ; MA # ( I → l ) FULLWIDTH LATIN CAPITAL LETTER I → LATIN SMALL LETTER L # →Ӏ→
+2160 ; 006C ; MA # ( Ⅰ → l ) ROMAN NUMERAL ONE → LATIN SMALL LETTER L # →Ӏ→
+2110 ; 006C ; MA # ( ℐ → l ) SCRIPT CAPITAL I → LATIN SMALL LETTER L # →I→
+2111 ; 006C ; MA # ( ℑ → l ) BLACK-LETTER CAPITAL I → LATIN SMALL LETTER L # →I→
+1D408 ; 006C ; MA # ( 𝐈 → l ) MATHEMATICAL BOLD CAPITAL I → LATIN SMALL LETTER L # →I→
+1D43C ; 006C ; MA # ( 𝐼 → l ) MATHEMATICAL ITALIC CAPITAL I → LATIN SMALL LETTER L # →I→
+1D470 ; 006C ; MA # ( 𝑰 → l ) MATHEMATICAL BOLD ITALIC CAPITAL I → LATIN SMALL LETTER L # →I→
+1D4D8 ; 006C ; MA # ( 𝓘 → l ) MATHEMATICAL BOLD SCRIPT CAPITAL I → LATIN SMALL LETTER L # →I→
+1D540 ; 006C ; MA # ( 𝕀 → l ) MATHEMATICAL DOUBLE-STRUCK CAPITAL I → LATIN SMALL LETTER L # →I→
+1D574 ; 006C ; MA # ( 𝕴 → l ) MATHEMATICAL BOLD FRAKTUR CAPITAL I → LATIN SMALL LETTER L # →I→
+1D5A8 ; 006C ; MA # ( 𝖨 → l ) MATHEMATICAL SANS-SERIF CAPITAL I → LATIN SMALL LETTER L # →I→
+1D5DC ; 006C ; MA # ( 𝗜 → l ) MATHEMATICAL SANS-SERIF BOLD CAPITAL I → LATIN SMALL LETTER L # →I→
+1D610 ; 006C ; MA # ( 𝘐 → l ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL I → LATIN SMALL LETTER L # →I→
+1D644 ; 006C ; MA # ( 𝙄 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I → LATIN SMALL LETTER L # →I→
+1D678 ; 006C ; MA # ( 𝙸 → l ) MATHEMATICAL MONOSPACE CAPITAL I → LATIN SMALL LETTER L # →I→
+0196 ; 006C ; MA # ( Ɩ → l ) LATIN CAPITAL LETTER IOTA → LATIN SMALL LETTER L #
+FF4C ; 006C ; MA # ( l → l ) FULLWIDTH LATIN SMALL LETTER L → LATIN SMALL LETTER L # →Ⅰ→→Ӏ→
+217C ; 006C ; MA # ( ⅼ → l ) SMALL ROMAN NUMERAL FIFTY → LATIN SMALL LETTER L #
+2113 ; 006C ; MA # ( ℓ → l ) SCRIPT SMALL L → LATIN SMALL LETTER L #
+1D425 ; 006C ; MA # ( 𝐥 → l ) MATHEMATICAL BOLD SMALL L → LATIN SMALL LETTER L #
+1D459 ; 006C ; MA # ( 𝑙 → l ) MATHEMATICAL ITALIC SMALL L → LATIN SMALL LETTER L #
+1D48D ; 006C ; MA # ( 𝒍 → l ) MATHEMATICAL BOLD ITALIC SMALL L → LATIN SMALL LETTER L #
+1D4C1 ; 006C ; MA # ( 𝓁 → l ) MATHEMATICAL SCRIPT SMALL L → LATIN SMALL LETTER L #
+1D4F5 ; 006C ; MA # ( 𝓵 → l ) MATHEMATICAL BOLD SCRIPT SMALL L → LATIN SMALL LETTER L #
+1D529 ; 006C ; MA # ( 𝔩 → l ) MATHEMATICAL FRAKTUR SMALL L → LATIN SMALL LETTER L #
+1D55D ; 006C ; MA # ( 𝕝 → l ) MATHEMATICAL DOUBLE-STRUCK SMALL L → LATIN SMALL LETTER L #
+1D591 ; 006C ; MA # ( 𝖑 → l ) MATHEMATICAL BOLD FRAKTUR SMALL L → LATIN SMALL LETTER L #
+1D5C5 ; 006C ; MA # ( 𝗅 → l ) MATHEMATICAL SANS-SERIF SMALL L → LATIN SMALL LETTER L #
+1D5F9 ; 006C ; MA # ( 𝗹 → l ) MATHEMATICAL SANS-SERIF BOLD SMALL L → LATIN SMALL LETTER L #
+1D62D ; 006C ; MA # ( 𝘭 → l ) MATHEMATICAL SANS-SERIF ITALIC SMALL L → LATIN SMALL LETTER L #
+1D661 ; 006C ; MA # ( 𝙡 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L → LATIN SMALL LETTER L #
+1D695 ; 006C ; MA # ( 𝚕 → l ) MATHEMATICAL MONOSPACE SMALL L → LATIN SMALL LETTER L #
+01C0 ; 006C ; MA # ( ǀ → l ) LATIN LETTER DENTAL CLICK → LATIN SMALL LETTER L #
+0399 ; 006C ; MA # ( Ι → l ) GREEK CAPITAL LETTER IOTA → LATIN SMALL LETTER L #
+1D6B0 ; 006C ; MA # ( 𝚰 → l ) MATHEMATICAL BOLD CAPITAL IOTA → LATIN SMALL LETTER L # →Ι→
+1D6EA ; 006C ; MA # ( 𝛪 → l ) MATHEMATICAL ITALIC CAPITAL IOTA → LATIN SMALL LETTER L # →Ι→
+1D724 ; 006C ; MA # ( 𝜤 → l ) MATHEMATICAL BOLD ITALIC CAPITAL IOTA → LATIN SMALL LETTER L # →Ι→
+1D75E ; 006C ; MA # ( 𝝞 → l ) MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA → LATIN SMALL LETTER L # →Ι→
+1D798 ; 006C ; MA # ( 𝞘 → l ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA → LATIN SMALL LETTER L # →Ι→
+2C92 ; 006C ; MA # ( Ⲓ → l ) COPTIC CAPITAL LETTER IAUDA → LATIN SMALL LETTER L # →Ӏ→
+0406 ; 006C ; MA # ( І → l ) CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I → LATIN SMALL LETTER L #
+04C0 ; 006C ; MA # ( Ӏ → l ) CYRILLIC LETTER PALOCHKA → LATIN SMALL LETTER L #
+05D5 ; 006C ; MA # ( ‎ו‎ → l ) HEBREW LETTER VAV → LATIN SMALL LETTER L #
+05DF ; 006C ; MA # ( ‎ן‎ → l ) HEBREW LETTER FINAL NUN → LATIN SMALL LETTER L #
+0627 ; 006C ; MA # ( ‎ا‎ → l ) ARABIC LETTER ALEF → LATIN SMALL LETTER L # →1→
+1EE00 ; 006C ; MA # ( ‎𞸀‎ → l ) ARABIC MATHEMATICAL ALEF → LATIN SMALL LETTER L # →‎ا‎→→1→
+1EE80 ; 006C ; MA # ( ‎𞺀‎ → l ) ARABIC MATHEMATICAL LOOPED ALEF → LATIN SMALL LETTER L # →‎ا‎→→1→
+FE8E ; 006C ; MA # ( ‎ﺎ‎ → l ) ARABIC LETTER ALEF FINAL FORM → LATIN SMALL LETTER L # →‎ا‎→→1→
+FE8D ; 006C ; MA # ( ‎ﺍ‎ → l ) ARABIC LETTER ALEF ISOLATED FORM → LATIN SMALL LETTER L # →‎ا‎→→1→
+07CA ; 006C ; MA # ( ‎ߊ‎ → l ) NKO LETTER A → LATIN SMALL LETTER L # →∣→→ǀ→
+2D4F ; 006C ; MA # ( ⵏ → l ) TIFINAGH LETTER YAN → LATIN SMALL LETTER L # →Ӏ→
+16C1 ; 006C ; MA # ( ᛁ → l ) RUNIC LETTER ISAZ IS ISS I → LATIN SMALL LETTER L # →I→
+A4F2 ; 006C ; MA # ( ꓲ → l ) LISU LETTER I → LATIN SMALL LETTER L # →I→
+16F28 ; 006C ; MA # ( 𖼨 → l ) MIAO LETTER GHA → LATIN SMALL LETTER L # →I→
+1028A ; 006C ; MA # ( 𐊊 → l ) LYCIAN LETTER J → LATIN SMALL LETTER L # →I→
+10309 ; 006C ; MA # ( 𐌉 → l ) OLD ITALIC LETTER I → LATIN SMALL LETTER L # →I→
+
+1D22A ; 004C ; MA #* ( 𝈪 → L ) GREEK INSTRUMENTAL NOTATION SYMBOL-23 → LATIN CAPITAL LETTER L #
+216C ; 004C ; MA # ( Ⅼ → L ) ROMAN NUMERAL FIFTY → LATIN CAPITAL LETTER L #
+2112 ; 004C ; MA # ( ℒ → L ) SCRIPT CAPITAL L → LATIN CAPITAL LETTER L #
+1D40B ; 004C ; MA # ( 𝐋 → L ) MATHEMATICAL BOLD CAPITAL L → LATIN CAPITAL LETTER L #
+1D43F ; 004C ; MA # ( 𝐿 → L ) MATHEMATICAL ITALIC CAPITAL L → LATIN CAPITAL LETTER L #
+1D473 ; 004C ; MA # ( 𝑳 → L ) MATHEMATICAL BOLD ITALIC CAPITAL L → LATIN CAPITAL LETTER L #
+1D4DB ; 004C ; MA # ( 𝓛 → L ) MATHEMATICAL BOLD SCRIPT CAPITAL L → LATIN CAPITAL LETTER L #
+1D50F ; 004C ; MA # ( 𝔏 → L ) MATHEMATICAL FRAKTUR CAPITAL L → LATIN CAPITAL LETTER L #
+1D543 ; 004C ; MA # ( 𝕃 → L ) MATHEMATICAL DOUBLE-STRUCK CAPITAL L → LATIN CAPITAL LETTER L #
+1D577 ; 004C ; MA # ( 𝕷 → L ) MATHEMATICAL BOLD FRAKTUR CAPITAL L → LATIN CAPITAL LETTER L #
+1D5AB ; 004C ; MA # ( 𝖫 → L ) MATHEMATICAL SANS-SERIF CAPITAL L → LATIN CAPITAL LETTER L #
+1D5DF ; 004C ; MA # ( 𝗟 → L ) MATHEMATICAL SANS-SERIF BOLD CAPITAL L → LATIN CAPITAL LETTER L #
+1D613 ; 004C ; MA # ( 𝘓 → L ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL L → LATIN CAPITAL LETTER L #
+1D647 ; 004C ; MA # ( 𝙇 → L ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L → LATIN CAPITAL LETTER L #
+1D67B ; 004C ; MA # ( 𝙻 → L ) MATHEMATICAL MONOSPACE CAPITAL L → LATIN CAPITAL LETTER L #
+2CD0 ; 004C ; MA # ( Ⳑ → L ) COPTIC CAPITAL LETTER L-SHAPED HA → LATIN CAPITAL LETTER L #
+13DE ; 004C ; MA # ( Ꮮ → L ) CHEROKEE LETTER TLE → LATIN CAPITAL LETTER L #
+14AA ; 004C ; MA # ( ᒪ → L ) CANADIAN SYLLABICS MA → LATIN CAPITAL LETTER L #
+A4E1 ; 004C ; MA # ( ꓡ → L ) LISU LETTER LA → LATIN CAPITAL LETTER L #
+16F16 ; 004C ; MA # ( 𖼖 → L ) MIAO LETTER LA → LATIN CAPITAL LETTER L #
+118A3 ; 004C ; MA # ( 𑢣 → L ) WARANG CITI CAPITAL LETTER YU → LATIN CAPITAL LETTER L #
+118B2 ; 004C ; MA # ( 𑢲 → L ) WARANG CITI CAPITAL LETTER TTE → LATIN CAPITAL LETTER L #
+1041B ; 004C ; MA # ( 𐐛 → L ) DESERET CAPITAL LETTER ETH → LATIN CAPITAL LETTER L #
+10526 ; 004C ; MA # ( 𐔦 → L ) ELBASAN LETTER GHAMMA → LATIN CAPITAL LETTER L #
+
+FD3C ; 006C 030B ; MA # ( ‎ﴼ‎ → l̋ ) ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM → LATIN SMALL LETTER L, COMBINING DOUBLE ACUTE ACCENT # →‎اً‎→
+FD3D ; 006C 030B ; MA # ( ‎ﴽ‎ → l̋ ) ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM → LATIN SMALL LETTER L, COMBINING DOUBLE ACUTE ACCENT # →‎اً‎→
+
+0142 ; 006C 0338 ; MA # ( ł → l̸ ) LATIN SMALL LETTER L WITH STROKE → LATIN SMALL LETTER L, COMBINING LONG SOLIDUS OVERLAY # →l̷→
+
+0141 ; 004C 0338 ; MA # ( Ł → L̸ ) LATIN CAPITAL LETTER L WITH STROKE → LATIN CAPITAL LETTER L, COMBINING LONG SOLIDUS OVERLAY # →L̷→
+
+026D ; 006C 0328 ; MA # ( ɭ → l̨ ) LATIN SMALL LETTER L WITH RETROFLEX HOOK → LATIN SMALL LETTER L, COMBINING OGONEK # →l̢→
+
+0197 ; 006C 0335 ; MA # ( Ɨ → l̵ ) LATIN CAPITAL LETTER I WITH STROKE → LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY # →ƚ→
+019A ; 006C 0335 ; MA # ( ƚ → l̵ ) LATIN SMALL LETTER L WITH BAR → LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY #
+
+026B ; 006C 0334 ; MA # ( ɫ → l̴ ) LATIN SMALL LETTER L WITH MIDDLE TILDE → LATIN SMALL LETTER L, COMBINING TILDE OVERLAY #
+
+0625 ; 006C 0655 ; MA # ( ‎إ‎ → lٕ ) ARABIC LETTER ALEF WITH HAMZA BELOW → LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎ٳ‎→→‎اٟ‎→
+FE88 ; 006C 0655 ; MA # ( ‎ﺈ‎ → lٕ ) ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM → LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎إ‎→→‎ٳ‎→→‎اٟ‎→
+FE87 ; 006C 0655 ; MA # ( ‎ﺇ‎ → lٕ ) ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM → LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎إ‎→→‎ٳ‎→→‎اٟ‎→
+0673 ; 006C 0655 ; MA # ( ‎ٳ‎ → lٕ ) ARABIC LETTER ALEF WITH WAVY HAMZA BELOW → LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎اٟ‎→
+
+0140 ; 006C 00B7 ; MA # ( ŀ → l· ) LATIN SMALL LETTER L WITH MIDDLE DOT → LATIN SMALL LETTER L, MIDDLE DOT #
+013F ; 006C 00B7 ; MA # ( Ŀ → l· ) LATIN CAPITAL LETTER L WITH MIDDLE DOT → LATIN SMALL LETTER L, MIDDLE DOT # →L·→→ᒪ·→→ᒪᐧ→→ᒷ→→1ᐧ→
+14B7 ; 006C 00B7 ; MA # ( ᒷ → l· ) CANADIAN SYLLABICS WEST-CREE MWA → LATIN SMALL LETTER L, MIDDLE DOT # →1ᐧ→
+
+1F102 ; 006C 002C ; MA #* ( 🄂 → l, ) DIGIT ONE COMMA → LATIN SMALL LETTER L, COMMA # →1,→
+
+2488 ; 006C 002E ; MA #* ( ⒈ → l. ) DIGIT ONE FULL STOP → LATIN SMALL LETTER L, FULL STOP # →1.→
+
+05F1 ; 006C 0027 ; MA # ( ‎ױ‎ → l' ) HEBREW LIGATURE YIDDISH VAV YOD → LATIN SMALL LETTER L, APOSTROPHE # →‎וי‎→
+
+2493 ; 006C 0032 002E ; MA #* ( ⒓ → l2. ) NUMBER TWELVE FULL STOP → LATIN SMALL LETTER L, DIGIT TWO, FULL STOP # →12.→
+
+33EB ; 006C 0032 65E5 ; MA #* ( ㏫ → l2日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE → LATIN SMALL LETTER L, DIGIT TWO, CJK UNIFIED IDEOGRAPH-65E5 # →12日→
+
+32CB ; 006C 0032 6708 ; MA #* ( ㋋ → l2月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER → LATIN SMALL LETTER L, DIGIT TWO, CJK UNIFIED IDEOGRAPH-6708 # →12月→
+
+3364 ; 006C 0032 70B9 ; MA #* ( ㍤ → l2点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE → LATIN SMALL LETTER L, DIGIT TWO, CJK UNIFIED IDEOGRAPH-70B9 # →12点→
+
+2494 ; 006C 0033 002E ; MA #* ( ⒔ → l3. ) NUMBER THIRTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT THREE, FULL STOP # →13.→
+
+33EC ; 006C 0033 65E5 ; MA #* ( ㏬ → l3日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN → LATIN SMALL LETTER L, DIGIT THREE, CJK UNIFIED IDEOGRAPH-65E5 # →13日→
+
+3365 ; 006C 0033 70B9 ; MA #* ( ㍥ → l3点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN → LATIN SMALL LETTER L, DIGIT THREE, CJK UNIFIED IDEOGRAPH-70B9 # →13点→
+
+2495 ; 006C 0034 002E ; MA #* ( ⒕ → l4. ) NUMBER FOURTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT FOUR, FULL STOP # →14.→
+
+33ED ; 006C 0034 65E5 ; MA #* ( ㏭ → l4日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN → LATIN SMALL LETTER L, DIGIT FOUR, CJK UNIFIED IDEOGRAPH-65E5 # →14日→
+
+3366 ; 006C 0034 70B9 ; MA #* ( ㍦ → l4点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN → LATIN SMALL LETTER L, DIGIT FOUR, CJK UNIFIED IDEOGRAPH-70B9 # →14点→
+
+2496 ; 006C 0035 002E ; MA #* ( ⒖ → l5. ) NUMBER FIFTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT FIVE, FULL STOP # →15.→
+
+33EE ; 006C 0035 65E5 ; MA #* ( ㏮ → l5日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN → LATIN SMALL LETTER L, DIGIT FIVE, CJK UNIFIED IDEOGRAPH-65E5 # →15日→
+
+3367 ; 006C 0035 70B9 ; MA #* ( ㍧ → l5点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN → LATIN SMALL LETTER L, DIGIT FIVE, CJK UNIFIED IDEOGRAPH-70B9 # →15点→
+
+2497 ; 006C 0036 002E ; MA #* ( ⒗ → l6. ) NUMBER SIXTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT SIX, FULL STOP # →16.→
+
+33EF ; 006C 0036 65E5 ; MA #* ( ㏯ → l6日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN → LATIN SMALL LETTER L, DIGIT SIX, CJK UNIFIED IDEOGRAPH-65E5 # →16日→
+
+3368 ; 006C 0036 70B9 ; MA #* ( ㍨ → l6点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN → LATIN SMALL LETTER L, DIGIT SIX, CJK UNIFIED IDEOGRAPH-70B9 # →16点→
+
+2498 ; 006C 0037 002E ; MA #* ( ⒘ → l7. ) NUMBER SEVENTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT SEVEN, FULL STOP # →17.→
+
+33F0 ; 006C 0037 65E5 ; MA #* ( ㏰ → l7日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN → LATIN SMALL LETTER L, DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-65E5 # →17日→
+
+3369 ; 006C 0037 70B9 ; MA #* ( ㍩ → l7点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN → LATIN SMALL LETTER L, DIGIT SEVEN, CJK UNIFIED IDEOGRAPH-70B9 # →17点→
+
+2499 ; 006C 0038 002E ; MA #* ( ⒙ → l8. ) NUMBER EIGHTEEN FULL STOP → LATIN SMALL LETTER L, DIGIT EIGHT, FULL STOP # →18.→
+
+33F1 ; 006C 0038 65E5 ; MA #* ( ㏱ → l8日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN → LATIN SMALL LETTER L, DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-65E5 # →18日→
+
+336A ; 006C 0038 70B9 ; MA #* ( ㍪ → l8点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN → LATIN SMALL LETTER L, DIGIT EIGHT, CJK UNIFIED IDEOGRAPH-70B9 # →18点→
+
+249A ; 006C 0039 002E ; MA #* ( ⒚ → l9. ) NUMBER NINETEEN FULL STOP → LATIN SMALL LETTER L, DIGIT NINE, FULL STOP # →19.→
+
+33F2 ; 006C 0039 65E5 ; MA #* ( ㏲ → l9日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN → LATIN SMALL LETTER L, DIGIT NINE, CJK UNIFIED IDEOGRAPH-65E5 # →19日→
+
+336B ; 006C 0039 70B9 ; MA #* ( ㍫ → l9点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN → LATIN SMALL LETTER L, DIGIT NINE, CJK UNIFIED IDEOGRAPH-70B9 # →19点→
+
+01C9 ; 006C 006A ; MA # ( lj → lj ) LATIN SMALL LETTER LJ → LATIN SMALL LETTER L, LATIN SMALL LETTER J #
+
+0132 ; 006C 004A ; MA # ( IJ → lJ ) LATIN CAPITAL LIGATURE IJ → LATIN SMALL LETTER L, LATIN CAPITAL LETTER J # →IJ→
+
+01C8 ; 004C 006A ; MA # ( Lj → Lj ) LATIN CAPITAL LETTER L WITH SMALL LETTER J → LATIN CAPITAL LETTER L, LATIN SMALL LETTER J #
+
+01C7 ; 004C 004A ; MA # ( LJ → LJ ) LATIN CAPITAL LETTER LJ → LATIN CAPITAL LETTER L, LATIN CAPITAL LETTER J #
+
+2016 ; 006C 006C ; MA #* ( ‖ → ll ) DOUBLE VERTICAL LINE → LATIN SMALL LETTER L, LATIN SMALL LETTER L # →∥→→||→
+2225 ; 006C 006C ; MA #* ( ∥ → ll ) PARALLEL TO → LATIN SMALL LETTER L, LATIN SMALL LETTER L # →||→
+2161 ; 006C 006C ; MA # ( Ⅱ → ll ) ROMAN NUMERAL TWO → LATIN SMALL LETTER L, LATIN SMALL LETTER L # →II→
+01C1 ; 006C 006C ; MA # ( ǁ → ll ) LATIN LETTER LATERAL CLICK → LATIN SMALL LETTER L, LATIN SMALL LETTER L # →‖→→∥→→||→
+05F0 ; 006C 006C ; MA # ( ‎װ‎ → ll ) HEBREW LIGATURE YIDDISH DOUBLE VAV → LATIN SMALL LETTER L, LATIN SMALL LETTER L # →‎וו‎→
+
+10199 ; 006C 0335 006C 0335 ; MA #* ( 𐆙 → l̵l̵ ) ROMAN DUPONDIUS SIGN → LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY, LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY # →I̶I̶→
+
+2492 ; 006C 006C 002E ; MA #* ( ⒒ → ll. ) NUMBER ELEVEN FULL STOP → LATIN SMALL LETTER L, LATIN SMALL LETTER L, FULL STOP # →11.→
+
+2162 ; 006C 006C 006C ; MA # ( Ⅲ → lll ) ROMAN NUMERAL THREE → LATIN SMALL LETTER L, LATIN SMALL LETTER L, LATIN SMALL LETTER L # →III→
+
+10198 ; 006C 0335 006C 0335 0053 0335 ; MA #* ( 𐆘 → l̵l̵S̵ ) ROMAN SESTERTIUS SIGN → LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY, LATIN SMALL LETTER L, COMBINING SHORT STROKE OVERLAY, LATIN CAPITAL LETTER S, COMBINING SHORT STROKE OVERLAY # →I̶I̶S̶→
+
+33EA ; 006C 006C 65E5 ; MA #* ( ㏪ → ll日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN → LATIN SMALL LETTER L, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-65E5 # →11日→
+
+32CA ; 006C 006C 6708 ; MA #* ( ㋊ → ll月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER → LATIN SMALL LETTER L, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-6708 # →11月→
+
+3363 ; 006C 006C 70B9 ; MA #* ( ㍣ → ll点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN → LATIN SMALL LETTER L, LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-70B9 # →11点→
+
+042E ; 006C 004F ; MA # ( Ю → lO ) CYRILLIC CAPITAL LETTER YU → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O # →IO→
+
+2491 ; 006C 004F 002E ; MA #* ( ⒑ → lO. ) NUMBER TEN FULL STOP → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, FULL STOP # →10.→
+
+33E9 ; 006C 004F 65E5 ; MA #* ( ㏩ → lO日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-65E5 # →10日→
+
+32C9 ; 006C 004F 6708 ; MA #* ( ㋉ → lO月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-6708 # →10月→
+
+3362 ; 006C 004F 70B9 ; MA #* ( ㍢ → lO点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN → LATIN SMALL LETTER L, LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-70B9 # →10点→
+
+02AA ; 006C 0073 ; MA # ( ʪ → ls ) LATIN SMALL LETTER LS DIGRAPH → LATIN SMALL LETTER L, LATIN SMALL LETTER S #
+
+20B6 ; 006C 0074 ; MA #* ( ₶ → lt ) LIVRE TOURNOIS SIGN → LATIN SMALL LETTER L, LATIN SMALL LETTER T #
+
+2163 ; 006C 0056 ; MA # ( Ⅳ → lV ) ROMAN NUMERAL FOUR → LATIN SMALL LETTER L, LATIN CAPITAL LETTER V # →IV→
+
+2168 ; 006C 0058 ; MA # ( Ⅸ → lX ) ROMAN NUMERAL NINE → LATIN SMALL LETTER L, LATIN CAPITAL LETTER X # →IX→
+
+026E ; 006C 021D ; MA # ( ɮ → lȝ ) LATIN SMALL LETTER LEZH → LATIN SMALL LETTER L, LATIN SMALL LETTER YOGH # →lʒ→
+
+02AB ; 006C 007A ; MA # ( ʫ → lz ) LATIN SMALL LETTER LZ DIGRAPH → LATIN SMALL LETTER L, LATIN SMALL LETTER Z #
+
+0623 ; 006C 0674 ; MA # ( ‎أ‎ → ‎lٴ‎ ) ARABIC LETTER ALEF WITH HAMZA ABOVE → LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎ٵ‎→→‎اٴ‎→
+FE84 ; 006C 0674 ; MA # ( ‎ﺄ‎ → ‎lٴ‎ ) ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM → LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎أ‎→→‎ٵ‎→→‎اٴ‎→
+FE83 ; 006C 0674 ; MA # ( ‎ﺃ‎ → ‎lٴ‎ ) ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM → LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎ٵ‎→→‎اٴ‎→
+0672 ; 006C 0674 ; MA # ( ‎ٲ‎ → ‎lٴ‎ ) ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE → LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎أ‎→→‎ٵ‎→→‎اٴ‎→
+0675 ; 006C 0674 ; MA # ( ‎ٵ‎ → ‎lٴ‎ ) ARABIC LETTER HIGH HAMZA ALEF → LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎اٴ‎→
+
+FDF3 ; 006C 0643 0628 0631 ; MA # ( ‎ﷳ‎ → ‎lكبر‎ ) ARABIC LIGATURE AKBAR ISOLATED FORM → LATIN SMALL LETTER L, ARABIC LETTER KAF, ARABIC LETTER BEH, ARABIC LETTER REH # →‎اكبر‎→
+
+FDF2 ; 006C 0644 0644 0651 0670 006F ; MA # ( ‎ﷲ‎ → ‎lللّٰo‎ ) ARABIC LIGATURE ALLAH ISOLATED FORM → LATIN SMALL LETTER L, ARABIC LETTER LAM, ARABIC LETTER LAM, ARABIC SHADDA, ARABIC LETTER SUPERSCRIPT ALEF, LATIN SMALL LETTER O # →‎اللّٰه‎→
+
+33E0 ; 006C 65E5 ; MA #* ( ㏠ → l日 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE → LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-65E5 # →1日→
+
+32C0 ; 006C 6708 ; MA #* ( ㋀ → l月 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY → LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-6708 # →1月→
+
+3359 ; 006C 70B9 ; MA #* ( ㍙ → l点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE → LATIN SMALL LETTER L, CJK UNIFIED IDEOGRAPH-70B9 # →1点→
+
+2CD1 ; 029F ; MA # ( ⳑ → ʟ ) COPTIC SMALL LETTER L-SHAPED HA → LATIN LETTER SMALL CAPITAL L #
+ABAE ; 029F ; MA # ( ꮮ → ʟ ) CHEROKEE SMALL LETTER TLE → LATIN LETTER SMALL CAPITAL L #
+10443 ; 029F ; MA # ( 𐑃 → ʟ ) DESERET SMALL LETTER ETH → LATIN LETTER SMALL CAPITAL L #
+
+FF2D ; 004D ; MA # ( M → M ) FULLWIDTH LATIN CAPITAL LETTER M → LATIN CAPITAL LETTER M # →Μ→
+216F ; 004D ; MA # ( Ⅿ → M ) ROMAN NUMERAL ONE THOUSAND → LATIN CAPITAL LETTER M #
+2133 ; 004D ; MA # ( ℳ → M ) SCRIPT CAPITAL M → LATIN CAPITAL LETTER M #
+1D40C ; 004D ; MA # ( 𝐌 → M ) MATHEMATICAL BOLD CAPITAL M → LATIN CAPITAL LETTER M #
+1D440 ; 004D ; MA # ( 𝑀 → M ) MATHEMATICAL ITALIC CAPITAL M → LATIN CAPITAL LETTER M #
+1D474 ; 004D ; MA # ( 𝑴 → M ) MATHEMATICAL BOLD ITALIC CAPITAL M → LATIN CAPITAL LETTER M #
+1D4DC ; 004D ; MA # ( 𝓜 → M ) MATHEMATICAL BOLD SCRIPT CAPITAL M → LATIN CAPITAL LETTER M #
+1D510 ; 004D ; MA # ( 𝔐 → M ) MATHEMATICAL FRAKTUR CAPITAL M → LATIN CAPITAL LETTER M #
+1D544 ; 004D ; MA # ( 𝕄 → M ) MATHEMATICAL DOUBLE-STRUCK CAPITAL M → LATIN CAPITAL LETTER M #
+1D578 ; 004D ; MA # ( 𝕸 → M ) MATHEMATICAL BOLD FRAKTUR CAPITAL M → LATIN CAPITAL LETTER M #
+1D5AC ; 004D ; MA # ( 𝖬 → M ) MATHEMATICAL SANS-SERIF CAPITAL M → LATIN CAPITAL LETTER M #
+1D5E0 ; 004D ; MA # ( 𝗠 → M ) MATHEMATICAL SANS-SERIF BOLD CAPITAL M → LATIN CAPITAL LETTER M #
+1D614 ; 004D ; MA # ( 𝘔 → M ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL M → LATIN CAPITAL LETTER M #
+1D648 ; 004D ; MA # ( 𝙈 → M ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M → LATIN CAPITAL LETTER M #
+1D67C ; 004D ; MA # ( 𝙼 → M ) MATHEMATICAL MONOSPACE CAPITAL M → LATIN CAPITAL LETTER M #
+039C ; 004D ; MA # ( Μ → M ) GREEK CAPITAL LETTER MU → LATIN CAPITAL LETTER M #
+1D6B3 ; 004D ; MA # ( 𝚳 → M ) MATHEMATICAL BOLD CAPITAL MU → LATIN CAPITAL LETTER M # →𝐌→
+1D6ED ; 004D ; MA # ( 𝛭 → M ) MATHEMATICAL ITALIC CAPITAL MU → LATIN CAPITAL LETTER M # →𝑀→
+1D727 ; 004D ; MA # ( 𝜧 → M ) MATHEMATICAL BOLD ITALIC CAPITAL MU → LATIN CAPITAL LETTER M # →𝑴→
+1D761 ; 004D ; MA # ( 𝝡 → M ) MATHEMATICAL SANS-SERIF BOLD CAPITAL MU → LATIN CAPITAL LETTER M # →Μ→
+1D79B ; 004D ; MA # ( 𝞛 → M ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU → LATIN CAPITAL LETTER M # →Μ→
+03FA ; 004D ; MA # ( Ϻ → M ) GREEK CAPITAL LETTER SAN → LATIN CAPITAL LETTER M #
+2C98 ; 004D ; MA # ( Ⲙ → M ) COPTIC CAPITAL LETTER MI → LATIN CAPITAL LETTER M #
+041C ; 004D ; MA # ( М → M ) CYRILLIC CAPITAL LETTER EM → LATIN CAPITAL LETTER M #
+13B7 ; 004D ; MA # ( Ꮇ → M ) CHEROKEE LETTER LU → LATIN CAPITAL LETTER M #
+15F0 ; 004D ; MA # ( ᗰ → M ) CANADIAN SYLLABICS CARRIER GO → LATIN CAPITAL LETTER M #
+16D6 ; 004D ; MA # ( ᛖ → M ) RUNIC LETTER EHWAZ EH E → LATIN CAPITAL LETTER M #
+A4DF ; 004D ; MA # ( ꓟ → M ) LISU LETTER MA → LATIN CAPITAL LETTER M #
+102B0 ; 004D ; MA # ( 𐊰 → M ) CARIAN LETTER S → LATIN CAPITAL LETTER M #
+10311 ; 004D ; MA # ( 𐌑 → M ) OLD ITALIC LETTER SHE → LATIN CAPITAL LETTER M #
+
+04CD ; 004D 0326 ; MA # ( Ӎ → M̦ ) CYRILLIC CAPITAL LETTER EM WITH TAIL → LATIN CAPITAL LETTER M, COMBINING COMMA BELOW # →М̡→
+
+1F76B ; 004D 0042 ; MA #* ( 🝫 → MB ) ALCHEMICAL SYMBOL FOR BATH OF MARY → LATIN CAPITAL LETTER M, LATIN CAPITAL LETTER B #
+
+2DE8 ; 1DDF ; MA # ( ⷨ → ᷟ ) COMBINING CYRILLIC LETTER EM → COMBINING LATIN LETTER SMALL CAPITAL M #
+
+1D427 ; 006E ; MA # ( 𝐧 → n ) MATHEMATICAL BOLD SMALL N → LATIN SMALL LETTER N #
+1D45B ; 006E ; MA # ( 𝑛 → n ) MATHEMATICAL ITALIC SMALL N → LATIN SMALL LETTER N #
+1D48F ; 006E ; MA # ( 𝒏 → n ) MATHEMATICAL BOLD ITALIC SMALL N → LATIN SMALL LETTER N #
+1D4C3 ; 006E ; MA # ( 𝓃 → n ) MATHEMATICAL SCRIPT SMALL N → LATIN SMALL LETTER N #
+1D4F7 ; 006E ; MA # ( 𝓷 → n ) MATHEMATICAL BOLD SCRIPT SMALL N → LATIN SMALL LETTER N #
+1D52B ; 006E ; MA # ( 𝔫 → n ) MATHEMATICAL FRAKTUR SMALL N → LATIN SMALL LETTER N #
+1D55F ; 006E ; MA # ( 𝕟 → n ) MATHEMATICAL DOUBLE-STRUCK SMALL N → LATIN SMALL LETTER N #
+1D593 ; 006E ; MA # ( 𝖓 → n ) MATHEMATICAL BOLD FRAKTUR SMALL N → LATIN SMALL LETTER N #
+1D5C7 ; 006E ; MA # ( 𝗇 → n ) MATHEMATICAL SANS-SERIF SMALL N → LATIN SMALL LETTER N #
+1D5FB ; 006E ; MA # ( 𝗻 → n ) MATHEMATICAL SANS-SERIF BOLD SMALL N → LATIN SMALL LETTER N #
+1D62F ; 006E ; MA # ( 𝘯 → n ) MATHEMATICAL SANS-SERIF ITALIC SMALL N → LATIN SMALL LETTER N #
+1D663 ; 006E ; MA # ( 𝙣 → n ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N → LATIN SMALL LETTER N #
+1D697 ; 006E ; MA # ( 𝚗 → n ) MATHEMATICAL MONOSPACE SMALL N → LATIN SMALL LETTER N #
+0578 ; 006E ; MA # ( ո → n ) ARMENIAN SMALL LETTER VO → LATIN SMALL LETTER N #
+057C ; 006E ; MA # ( ռ → n ) ARMENIAN SMALL LETTER RA → LATIN SMALL LETTER N #
+
+FF2E ; 004E ; MA # ( N → N ) FULLWIDTH LATIN CAPITAL LETTER N → LATIN CAPITAL LETTER N # →Ν→
+2115 ; 004E ; MA # ( ℕ → N ) DOUBLE-STRUCK CAPITAL N → LATIN CAPITAL LETTER N #
+1D40D ; 004E ; MA # ( 𝐍 → N ) MATHEMATICAL BOLD CAPITAL N → LATIN CAPITAL LETTER N #
+1D441 ; 004E ; MA # ( 𝑁 → N ) MATHEMATICAL ITALIC CAPITAL N → LATIN CAPITAL LETTER N #
+1D475 ; 004E ; MA # ( 𝑵 → N ) MATHEMATICAL BOLD ITALIC CAPITAL N → LATIN CAPITAL LETTER N #
+1D4A9 ; 004E ; MA # ( 𝒩 → N ) MATHEMATICAL SCRIPT CAPITAL N → LATIN CAPITAL LETTER N #
+1D4DD ; 004E ; MA # ( 𝓝 → N ) MATHEMATICAL BOLD SCRIPT CAPITAL N → LATIN CAPITAL LETTER N #
+1D511 ; 004E ; MA # ( 𝔑 → N ) MATHEMATICAL FRAKTUR CAPITAL N → LATIN CAPITAL LETTER N #
+1D579 ; 004E ; MA # ( 𝕹 → N ) MATHEMATICAL BOLD FRAKTUR CAPITAL N → LATIN CAPITAL LETTER N #
+1D5AD ; 004E ; MA # ( 𝖭 → N ) MATHEMATICAL SANS-SERIF CAPITAL N → LATIN CAPITAL LETTER N #
+1D5E1 ; 004E ; MA # ( 𝗡 → N ) MATHEMATICAL SANS-SERIF BOLD CAPITAL N → LATIN CAPITAL LETTER N #
+1D615 ; 004E ; MA # ( 𝘕 → N ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL N → LATIN CAPITAL LETTER N #
+1D649 ; 004E ; MA # ( 𝙉 → N ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N → LATIN CAPITAL LETTER N #
+1D67D ; 004E ; MA # ( 𝙽 → N ) MATHEMATICAL MONOSPACE CAPITAL N → LATIN CAPITAL LETTER N #
+039D ; 004E ; MA # ( Ν → N ) GREEK CAPITAL LETTER NU → LATIN CAPITAL LETTER N #
+1D6B4 ; 004E ; MA # ( 𝚴 → N ) MATHEMATICAL BOLD CAPITAL NU → LATIN CAPITAL LETTER N # →𝐍→
+1D6EE ; 004E ; MA # ( 𝛮 → N ) MATHEMATICAL ITALIC CAPITAL NU → LATIN CAPITAL LETTER N # →𝑁→
+1D728 ; 004E ; MA # ( 𝜨 → N ) MATHEMATICAL BOLD ITALIC CAPITAL NU → LATIN CAPITAL LETTER N # →𝑵→
+1D762 ; 004E ; MA # ( 𝝢 → N ) MATHEMATICAL SANS-SERIF BOLD CAPITAL NU → LATIN CAPITAL LETTER N # →Ν→
+1D79C ; 004E ; MA # ( 𝞜 → N ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU → LATIN CAPITAL LETTER N # →Ν→
+2C9A ; 004E ; MA # ( Ⲛ → N ) COPTIC CAPITAL LETTER NI → LATIN CAPITAL LETTER N #
+A4E0 ; 004E ; MA # ( ꓠ → N ) LISU LETTER NA → LATIN CAPITAL LETTER N #
+10513 ; 004E ; MA # ( 𐔓 → N ) ELBASAN LETTER NE → LATIN CAPITAL LETTER N #
+
+1018E ; 004E 030A ; MA #* ( 𐆎 → N̊ ) NOMISMA SIGN → LATIN CAPITAL LETTER N, COMBINING RING ABOVE # →Νͦ→
+
+0273 ; 006E 0328 ; MA # ( ɳ → n̨ ) LATIN SMALL LETTER N WITH RETROFLEX HOOK → LATIN SMALL LETTER N, COMBINING OGONEK # →n̢→
+
+019E ; 006E 0329 ; MA # ( ƞ → n̩ ) LATIN SMALL LETTER N WITH LONG RIGHT LEG → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW #
+03B7 ; 006E 0329 ; MA # ( η → n̩ ) GREEK SMALL LETTER ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →ƞ→
+1D6C8 ; 006E 0329 ; MA # ( 𝛈 → n̩ ) MATHEMATICAL BOLD SMALL ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →η→→ƞ→
+1D702 ; 006E 0329 ; MA # ( 𝜂 → n̩ ) MATHEMATICAL ITALIC SMALL ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →η→→ƞ→
+1D73C ; 006E 0329 ; MA # ( 𝜼 → n̩ ) MATHEMATICAL BOLD ITALIC SMALL ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →η→→ƞ→
+1D776 ; 006E 0329 ; MA # ( 𝝶 → n̩ ) MATHEMATICAL SANS-SERIF BOLD SMALL ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →η→→ƞ→
+1D7B0 ; 006E 0329 ; MA # ( 𝞰 → n̩ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA → LATIN SMALL LETTER N, COMBINING VERTICAL LINE BELOW # →η→→ƞ→
+
+019D ; 004E 0326 ; MA # ( Ɲ → N̦ ) LATIN CAPITAL LETTER N WITH LEFT HOOK → LATIN CAPITAL LETTER N, COMBINING COMMA BELOW # →N̡→
+
+1D70 ; 006E 0334 ; MA # ( ᵰ → n̴ ) LATIN SMALL LETTER N WITH MIDDLE TILDE → LATIN SMALL LETTER N, COMBINING TILDE OVERLAY #
+
+01CC ; 006E 006A ; MA # ( nj → nj ) LATIN SMALL LETTER NJ → LATIN SMALL LETTER N, LATIN SMALL LETTER J #
+
+01CB ; 004E 006A ; MA # ( Nj → Nj ) LATIN CAPITAL LETTER N WITH SMALL LETTER J → LATIN CAPITAL LETTER N, LATIN SMALL LETTER J #
+
+01CA ; 004E 004A ; MA # ( NJ → NJ ) LATIN CAPITAL LETTER NJ → LATIN CAPITAL LETTER N, LATIN CAPITAL LETTER J #
+
+2116 ; 004E 006F ; MA #* ( № → No ) NUMERO SIGN → LATIN CAPITAL LETTER N, LATIN SMALL LETTER O #
+
+0377 ; 1D0E ; MA # ( ͷ → ᴎ ) GREEK SMALL LETTER PAMPHYLIAN DIGAMMA → LATIN LETTER SMALL CAPITAL REVERSED N # →и→
+0438 ; 1D0E ; MA # ( и → ᴎ ) CYRILLIC SMALL LETTER I → LATIN LETTER SMALL CAPITAL REVERSED N #
+1044D ; 1D0E ; MA # ( 𐑍 → ᴎ ) DESERET SMALL LETTER ENG → LATIN LETTER SMALL CAPITAL REVERSED N # →и→
+
+0146 ; 0272 ; MA # ( ņ → ɲ ) LATIN SMALL LETTER N WITH CEDILLA → LATIN SMALL LETTER N WITH LEFT HOOK #
+
+0C02 ; 006F ; MA # ( ం → o ) TELUGU SIGN ANUSVARA → LATIN SMALL LETTER O #
+0C82 ; 006F ; MA # ( ಂ → o ) KANNADA SIGN ANUSVARA → LATIN SMALL LETTER O #
+0D02 ; 006F ; MA # ( ം → o ) MALAYALAM SIGN ANUSVARA → LATIN SMALL LETTER O #
+0D82 ; 006F ; MA # ( ං → o ) SINHALA SIGN ANUSVARAYA → LATIN SMALL LETTER O #
+0966 ; 006F ; MA # ( ० → o ) DEVANAGARI DIGIT ZERO → LATIN SMALL LETTER O #
+0A66 ; 006F ; MA # ( ੦ → o ) GURMUKHI DIGIT ZERO → LATIN SMALL LETTER O #
+0AE6 ; 006F ; MA # ( ૦ → o ) GUJARATI DIGIT ZERO → LATIN SMALL LETTER O #
+0BE6 ; 006F ; MA # ( ௦ → o ) TAMIL DIGIT ZERO → LATIN SMALL LETTER O #
+0C66 ; 006F ; MA # ( ౦ → o ) TELUGU DIGIT ZERO → LATIN SMALL LETTER O #
+0CE6 ; 006F ; MA # ( ೦ → o ) KANNADA DIGIT ZERO → LATIN SMALL LETTER O # →౦→
+0D66 ; 006F ; MA # ( ൦ → o ) MALAYALAM DIGIT ZERO → LATIN SMALL LETTER O #
+0E50 ; 006F ; MA # ( ๐ → o ) THAI DIGIT ZERO → LATIN SMALL LETTER O #
+0ED0 ; 006F ; MA # ( ໐ → o ) LAO DIGIT ZERO → LATIN SMALL LETTER O #
+1040 ; 006F ; MA # ( ၀ → o ) MYANMAR DIGIT ZERO → LATIN SMALL LETTER O #
+0665 ; 006F ; MA # ( ‎٥‎ → o ) ARABIC-INDIC DIGIT FIVE → LATIN SMALL LETTER O #
+06F5 ; 006F ; MA # ( ۵ → o ) EXTENDED ARABIC-INDIC DIGIT FIVE → LATIN SMALL LETTER O # →‎٥‎→
+FF4F ; 006F ; MA # ( o → o ) FULLWIDTH LATIN SMALL LETTER O → LATIN SMALL LETTER O # →о→
+2134 ; 006F ; MA # ( ℴ → o ) SCRIPT SMALL O → LATIN SMALL LETTER O #
+1D428 ; 006F ; MA # ( 𝐨 → o ) MATHEMATICAL BOLD SMALL O → LATIN SMALL LETTER O #
+1D45C ; 006F ; MA # ( 𝑜 → o ) MATHEMATICAL ITALIC SMALL O → LATIN SMALL LETTER O #
+1D490 ; 006F ; MA # ( 𝒐 → o ) MATHEMATICAL BOLD ITALIC SMALL O → LATIN SMALL LETTER O #
+1D4F8 ; 006F ; MA # ( 𝓸 → o ) MATHEMATICAL BOLD SCRIPT SMALL O → LATIN SMALL LETTER O #
+1D52C ; 006F ; MA # ( 𝔬 → o ) MATHEMATICAL FRAKTUR SMALL O → LATIN SMALL LETTER O #
+1D560 ; 006F ; MA # ( 𝕠 → o ) MATHEMATICAL DOUBLE-STRUCK SMALL O → LATIN SMALL LETTER O #
+1D594 ; 006F ; MA # ( 𝖔 → o ) MATHEMATICAL BOLD FRAKTUR SMALL O → LATIN SMALL LETTER O #
+1D5C8 ; 006F ; MA # ( 𝗈 → o ) MATHEMATICAL SANS-SERIF SMALL O → LATIN SMALL LETTER O #
+1D5FC ; 006F ; MA # ( 𝗼 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL O → LATIN SMALL LETTER O #
+1D630 ; 006F ; MA # ( 𝘰 → o ) MATHEMATICAL SANS-SERIF ITALIC SMALL O → LATIN SMALL LETTER O #
+1D664 ; 006F ; MA # ( 𝙤 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O → LATIN SMALL LETTER O #
+1D698 ; 006F ; MA # ( 𝚘 → o ) MATHEMATICAL MONOSPACE SMALL O → LATIN SMALL LETTER O #
+1D0F ; 006F ; MA # ( ᴏ → o ) LATIN LETTER SMALL CAPITAL O → LATIN SMALL LETTER O #
+1D11 ; 006F ; MA # ( ᴑ → o ) LATIN SMALL LETTER SIDEWAYS O → LATIN SMALL LETTER O #
+AB3D ; 006F ; MA # ( ꬽ → o ) LATIN SMALL LETTER BLACKLETTER O → LATIN SMALL LETTER O #
+03BF ; 006F ; MA # ( ο → o ) GREEK SMALL LETTER OMICRON → LATIN SMALL LETTER O #
+1D6D0 ; 006F ; MA # ( 𝛐 → o ) MATHEMATICAL BOLD SMALL OMICRON → LATIN SMALL LETTER O # →𝐨→
+1D70A ; 006F ; MA # ( 𝜊 → o ) MATHEMATICAL ITALIC SMALL OMICRON → LATIN SMALL LETTER O # →𝑜→
+1D744 ; 006F ; MA # ( 𝝄 → o ) MATHEMATICAL BOLD ITALIC SMALL OMICRON → LATIN SMALL LETTER O # →𝒐→
+1D77E ; 006F ; MA # ( 𝝾 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON → LATIN SMALL LETTER O # →ο→
+1D7B8 ; 006F ; MA # ( 𝞸 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON → LATIN SMALL LETTER O # →ο→
+03C3 ; 006F ; MA # ( σ → o ) GREEK SMALL LETTER SIGMA → LATIN SMALL LETTER O #
+1D6D4 ; 006F ; MA # ( 𝛔 → o ) MATHEMATICAL BOLD SMALL SIGMA → LATIN SMALL LETTER O # →σ→
+1D70E ; 006F ; MA # ( 𝜎 → o ) MATHEMATICAL ITALIC SMALL SIGMA → LATIN SMALL LETTER O # →σ→
+1D748 ; 006F ; MA # ( 𝝈 → o ) MATHEMATICAL BOLD ITALIC SMALL SIGMA → LATIN SMALL LETTER O # →σ→
+1D782 ; 006F ; MA # ( 𝞂 → o ) MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA → LATIN SMALL LETTER O # →σ→
+1D7BC ; 006F ; MA # ( 𝞼 → o ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA → LATIN SMALL LETTER O # →σ→
+2C9F ; 006F ; MA # ( ⲟ → o ) COPTIC SMALL LETTER O → LATIN SMALL LETTER O #
+043E ; 006F ; MA # ( о → o ) CYRILLIC SMALL LETTER O → LATIN SMALL LETTER O #
+10FF ; 006F ; MA # ( ჿ → o ) GEORGIAN LETTER LABIAL SIGN → LATIN SMALL LETTER O #
+0585 ; 006F ; MA # ( օ → o ) ARMENIAN SMALL LETTER OH → LATIN SMALL LETTER O #
+05E1 ; 006F ; MA # ( ‎ס‎ → o ) HEBREW LETTER SAMEKH → LATIN SMALL LETTER O #
+0647 ; 006F ; MA # ( ‎ه‎ → o ) ARABIC LETTER HEH → LATIN SMALL LETTER O #
+1EE24 ; 006F ; MA # ( ‎𞸤‎ → o ) ARABIC MATHEMATICAL INITIAL HEH → LATIN SMALL LETTER O # →‎ه‎→
+1EE64 ; 006F ; MA # ( ‎𞹤‎ → o ) ARABIC MATHEMATICAL STRETCHED HEH → LATIN SMALL LETTER O # →‎ه‎→
+1EE84 ; 006F ; MA # ( ‎𞺄‎ → o ) ARABIC MATHEMATICAL LOOPED HEH → LATIN SMALL LETTER O # →‎ه‎→
+FEEB ; 006F ; MA # ( ‎ﻫ‎ → o ) ARABIC LETTER HEH INITIAL FORM → LATIN SMALL LETTER O # →‎ه‎→
+FEEC ; 006F ; MA # ( ‎ﻬ‎ → o ) ARABIC LETTER HEH MEDIAL FORM → LATIN SMALL LETTER O # →‎ه‎→
+FEEA ; 006F ; MA # ( ‎ﻪ‎ → o ) ARABIC LETTER HEH FINAL FORM → LATIN SMALL LETTER O # →‎ه‎→
+FEE9 ; 006F ; MA # ( ‎ﻩ‎ → o ) ARABIC LETTER HEH ISOLATED FORM → LATIN SMALL LETTER O # →‎ه‎→
+06BE ; 006F ; MA # ( ‎ھ‎ → o ) ARABIC LETTER HEH DOACHASHMEE → LATIN SMALL LETTER O # →‎ه‎→
+FBAC ; 006F ; MA # ( ‎ﮬ‎ → o ) ARABIC LETTER HEH DOACHASHMEE INITIAL FORM → LATIN SMALL LETTER O # →‎ﻫ‎→→‎ه‎→
+FBAD ; 006F ; MA # ( ‎ﮭ‎ → o ) ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM → LATIN SMALL LETTER O # →‎ﻬ‎→→‎ه‎→
+FBAB ; 006F ; MA # ( ‎ﮫ‎ → o ) ARABIC LETTER HEH DOACHASHMEE FINAL FORM → LATIN SMALL LETTER O # →‎ﻪ‎→→‎ه‎→
+FBAA ; 006F ; MA # ( ‎ﮪ‎ → o ) ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM → LATIN SMALL LETTER O # →‎ه‎→
+06C1 ; 006F ; MA # ( ‎ہ‎ → o ) ARABIC LETTER HEH GOAL → LATIN SMALL LETTER O # →‎ه‎→
+FBA8 ; 006F ; MA # ( ‎ﮨ‎ → o ) ARABIC LETTER HEH GOAL INITIAL FORM → LATIN SMALL LETTER O # →‎ہ‎→→‎ه‎→
+FBA9 ; 006F ; MA # ( ‎ﮩ‎ → o ) ARABIC LETTER HEH GOAL MEDIAL FORM → LATIN SMALL LETTER O # →‎ہ‎→→‎ه‎→
+FBA7 ; 006F ; MA # ( ‎ﮧ‎ → o ) ARABIC LETTER HEH GOAL FINAL FORM → LATIN SMALL LETTER O # →‎ہ‎→→‎ه‎→
+FBA6 ; 006F ; MA # ( ‎ﮦ‎ → o ) ARABIC LETTER HEH GOAL ISOLATED FORM → LATIN SMALL LETTER O # →‎ه‎→
+06D5 ; 006F ; MA # ( ‎ە‎ → o ) ARABIC LETTER AE → LATIN SMALL LETTER O # →‎ه‎→
+0D20 ; 006F ; MA # ( ഠ → o ) MALAYALAM LETTER TTHA → LATIN SMALL LETTER O #
+101D ; 006F ; MA # ( ဝ → o ) MYANMAR LETTER WA → LATIN SMALL LETTER O #
+104EA ; 006F ; MA # ( 𐓪 → o ) OSAGE SMALL LETTER O → LATIN SMALL LETTER O #
+118C8 ; 006F ; MA # ( 𑣈 → o ) WARANG CITI SMALL LETTER E → LATIN SMALL LETTER O #
+118D7 ; 006F ; MA # ( 𑣗 → o ) WARANG CITI SMALL LETTER BU → LATIN SMALL LETTER O #
+1042C ; 006F ; MA # ( 𐐬 → o ) DESERET SMALL LETTER LONG O → LATIN SMALL LETTER O #
+
+0030 ; 004F ; MA # ( 0 → O ) DIGIT ZERO → LATIN CAPITAL LETTER O #
+07C0 ; 004F ; MA # ( ‎߀‎ → O ) NKO DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+09E6 ; 004F ; MA # ( ০ → O ) BENGALI DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+0B66 ; 004F ; MA # ( ୦ → O ) ORIYA DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+3007 ; 004F ; MA # ( 〇 → O ) IDEOGRAPHIC NUMBER ZERO → LATIN CAPITAL LETTER O #
+114D0 ; 004F ; MA # ( 𑓐 → O ) TIRHUTA DIGIT ZERO → LATIN CAPITAL LETTER O # →০→→0→
+118E0 ; 004F ; MA # ( 𑣠 → O ) WARANG CITI DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1D7CE ; 004F ; MA # ( 𝟎 → O ) MATHEMATICAL BOLD DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1D7D8 ; 004F ; MA # ( 𝟘 → O ) MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1D7E2 ; 004F ; MA # ( 𝟢 → O ) MATHEMATICAL SANS-SERIF DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1D7EC ; 004F ; MA # ( 𝟬 → O ) MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1D7F6 ; 004F ; MA # ( 𝟶 → O ) MATHEMATICAL MONOSPACE DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+1FBF0 ; 004F ; MA # ( 🯰 → O ) SEGMENTED DIGIT ZERO → LATIN CAPITAL LETTER O # →0→
+FF2F ; 004F ; MA # ( O → O ) FULLWIDTH LATIN CAPITAL LETTER O → LATIN CAPITAL LETTER O # →О→
+1D40E ; 004F ; MA # ( 𝐎 → O ) MATHEMATICAL BOLD CAPITAL O → LATIN CAPITAL LETTER O #
+1D442 ; 004F ; MA # ( 𝑂 → O ) MATHEMATICAL ITALIC CAPITAL O → LATIN CAPITAL LETTER O #
+1D476 ; 004F ; MA # ( 𝑶 → O ) MATHEMATICAL BOLD ITALIC CAPITAL O → LATIN CAPITAL LETTER O #
+1D4AA ; 004F ; MA # ( 𝒪 → O ) MATHEMATICAL SCRIPT CAPITAL O → LATIN CAPITAL LETTER O #
+1D4DE ; 004F ; MA # ( 𝓞 → O ) MATHEMATICAL BOLD SCRIPT CAPITAL O → LATIN CAPITAL LETTER O #
+1D512 ; 004F ; MA # ( 𝔒 → O ) MATHEMATICAL FRAKTUR CAPITAL O → LATIN CAPITAL LETTER O #
+1D546 ; 004F ; MA # ( 𝕆 → O ) MATHEMATICAL DOUBLE-STRUCK CAPITAL O → LATIN CAPITAL LETTER O #
+1D57A ; 004F ; MA # ( 𝕺 → O ) MATHEMATICAL BOLD FRAKTUR CAPITAL O → LATIN CAPITAL LETTER O #
+1D5AE ; 004F ; MA # ( 𝖮 → O ) MATHEMATICAL SANS-SERIF CAPITAL O → LATIN CAPITAL LETTER O #
+1D5E2 ; 004F ; MA # ( 𝗢 → O ) MATHEMATICAL SANS-SERIF BOLD CAPITAL O → LATIN CAPITAL LETTER O #
+1D616 ; 004F ; MA # ( 𝘖 → O ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL O → LATIN CAPITAL LETTER O #
+1D64A ; 004F ; MA # ( 𝙊 → O ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O → LATIN CAPITAL LETTER O #
+1D67E ; 004F ; MA # ( 𝙾 → O ) MATHEMATICAL MONOSPACE CAPITAL O → LATIN CAPITAL LETTER O #
+039F ; 004F ; MA # ( Ο → O ) GREEK CAPITAL LETTER OMICRON → LATIN CAPITAL LETTER O #
+1D6B6 ; 004F ; MA # ( 𝚶 → O ) MATHEMATICAL BOLD CAPITAL OMICRON → LATIN CAPITAL LETTER O # →𝐎→
+1D6F0 ; 004F ; MA # ( 𝛰 → O ) MATHEMATICAL ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O # →𝑂→
+1D72A ; 004F ; MA # ( 𝜪 → O ) MATHEMATICAL BOLD ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O # →𝑶→
+1D764 ; 004F ; MA # ( 𝝤 → O ) MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON → LATIN CAPITAL LETTER O # →Ο→
+1D79E ; 004F ; MA # ( 𝞞 → O ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON → LATIN CAPITAL LETTER O # →Ο→
+2C9E ; 004F ; MA # ( Ⲟ → O ) COPTIC CAPITAL LETTER O → LATIN CAPITAL LETTER O #
+041E ; 004F ; MA # ( О → O ) CYRILLIC CAPITAL LETTER O → LATIN CAPITAL LETTER O #
+0555 ; 004F ; MA # ( Օ → O ) ARMENIAN CAPITAL LETTER OH → LATIN CAPITAL LETTER O #
+2D54 ; 004F ; MA # ( ⵔ → O ) TIFINAGH LETTER YAR → LATIN CAPITAL LETTER O #
+12D0 ; 004F ; MA # ( ዐ → O ) ETHIOPIC SYLLABLE PHARYNGEAL A → LATIN CAPITAL LETTER O # →Օ→
+0B20 ; 004F ; MA # ( ଠ → O ) ORIYA LETTER TTHA → LATIN CAPITAL LETTER O # →୦→→0→
+104C2 ; 004F ; MA # ( 𐓂 → O ) OSAGE CAPITAL LETTER O → LATIN CAPITAL LETTER O #
+A4F3 ; 004F ; MA # ( ꓳ → O ) LISU LETTER O → LATIN CAPITAL LETTER O #
+118B5 ; 004F ; MA # ( 𑢵 → O ) WARANG CITI CAPITAL LETTER AT → LATIN CAPITAL LETTER O #
+10292 ; 004F ; MA # ( 𐊒 → O ) LYCIAN LETTER U → LATIN CAPITAL LETTER O #
+102AB ; 004F ; MA # ( 𐊫 → O ) CARIAN LETTER O → LATIN CAPITAL LETTER O #
+10404 ; 004F ; MA # ( 𐐄 → O ) DESERET CAPITAL LETTER LONG O → LATIN CAPITAL LETTER O #
+10516 ; 004F ; MA # ( 𐔖 → O ) ELBASAN LETTER O → LATIN CAPITAL LETTER O #
+
+2070 ; 00BA ; MA #* ( ⁰ → º ) SUPERSCRIPT ZERO → MASCULINE ORDINAL INDICATOR #
+1D52 ; 00BA ; MA # ( ᵒ → º ) MODIFIER LETTER SMALL O → MASCULINE ORDINAL INDICATOR # →⁰→
+
+01D2 ; 014F ; MA # ( ǒ → ŏ ) LATIN SMALL LETTER O WITH CARON → LATIN SMALL LETTER O WITH BREVE #
+
+01D1 ; 014E ; MA # ( Ǒ → Ŏ ) LATIN CAPITAL LETTER O WITH CARON → LATIN CAPITAL LETTER O WITH BREVE #
+
+06FF ; 006F 0302 ; MA # ( ‎ۿ‎ → ô ) ARABIC LETTER HEH WITH INVERTED V → LATIN SMALL LETTER O, COMBINING CIRCUMFLEX ACCENT # →‎ھٛ‎→
+
+0150 ; 00D6 ; MA # ( Ő → Ö ) LATIN CAPITAL LETTER O WITH DOUBLE ACUTE → LATIN CAPITAL LETTER O WITH DIAERESIS #
+
+00F8 ; 006F 0338 ; MA # ( ø → o̸ ) LATIN SMALL LETTER O WITH STROKE → LATIN SMALL LETTER O, COMBINING LONG SOLIDUS OVERLAY # →o̷→
+AB3E ; 006F 0338 ; MA # ( ꬾ → o̸ ) LATIN SMALL LETTER BLACKLETTER O WITH STROKE → LATIN SMALL LETTER O, COMBINING LONG SOLIDUS OVERLAY # →ø→→o̷→
+
+00D8 ; 004F 0338 ; MA # ( Ø → O̸ ) LATIN CAPITAL LETTER O WITH STROKE → LATIN CAPITAL LETTER O, COMBINING LONG SOLIDUS OVERLAY #
+2D41 ; 004F 0338 ; MA # ( ⵁ → O̸ ) TIFINAGH LETTER BERBER ACADEMY YAH → LATIN CAPITAL LETTER O, COMBINING LONG SOLIDUS OVERLAY # →Ø→
+
+01FE ; 004F 0338 0301 ; MA # ( Ǿ → Ó̸ ) LATIN CAPITAL LETTER O WITH STROKE AND ACUTE → LATIN CAPITAL LETTER O, COMBINING LONG SOLIDUS OVERLAY, COMBINING ACUTE ACCENT #
+
+0275 ; 006F 0335 ; MA # ( ɵ → o̵ ) LATIN SMALL LETTER BARRED O → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY #
+A74B ; 006F 0335 ; MA # ( ꝋ → o̵ ) LATIN SMALL LETTER O WITH LONG STROKE OVERLAY → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY # →o̶→
+04E9 ; 006F 0335 ; MA # ( ө → o̵ ) CYRILLIC SMALL LETTER BARRED O → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY # →ѳ→
+0473 ; 006F 0335 ; MA # ( ѳ → o̵ ) CYRILLIC SMALL LETTER FITA → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY #
+AB8E ; 006F 0335 ; MA # ( ꮎ → o̵ ) CHEROKEE SMALL LETTER NA → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY # →ɵ→
+ABBB ; 006F 0335 ; MA # ( ꮻ → o̵ ) CHEROKEE SMALL LETTER WI → LATIN SMALL LETTER O, COMBINING SHORT STROKE OVERLAY # →ѳ→
+
+2296 ; 004F 0335 ; MA #* ( ⊖ → O̵ ) CIRCLED MINUS → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+229D ; 004F 0335 ; MA #* ( ⊝ → O̵ ) CIRCLED DASH → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →⊖→→θ→→Ꮎ→
+236C ; 004F 0335 ; MA #* ( ⍬ → O̵ ) APL FUNCTIONAL SYMBOL ZILDE → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D21A ; 004F 0335 ; MA #* ( 𝈚 → O̵ ) GREEK VOCAL NOTATION SYMBOL-52 → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ꝋ→→O̶→
+1F714 ; 004F 0335 ; MA #* ( 🜔 → O̵ ) ALCHEMICAL SYMBOL FOR SALT → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ɵ→→O̶→
+019F ; 004F 0335 ; MA # ( Ɵ → O̵ ) LATIN CAPITAL LETTER O WITH MIDDLE TILDE → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →O̶→
+A74A ; 004F 0335 ; MA # ( Ꝋ → O̵ ) LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →O̶→
+03B8 ; 004F 0335 ; MA # ( θ → O̵ ) GREEK SMALL LETTER THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ꮎ→
+03D1 ; 004F 0335 ; MA # ( ϑ → O̵ ) GREEK THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D6C9 ; 004F 0335 ; MA # ( 𝛉 → O̵ ) MATHEMATICAL BOLD SMALL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D6DD ; 004F 0335 ; MA # ( 𝛝 → O̵ ) MATHEMATICAL BOLD THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D703 ; 004F 0335 ; MA # ( 𝜃 → O̵ ) MATHEMATICAL ITALIC SMALL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D717 ; 004F 0335 ; MA # ( 𝜗 → O̵ ) MATHEMATICAL ITALIC THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D73D ; 004F 0335 ; MA # ( 𝜽 → O̵ ) MATHEMATICAL BOLD ITALIC SMALL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D751 ; 004F 0335 ; MA # ( 𝝑 → O̵ ) MATHEMATICAL BOLD ITALIC THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D777 ; 004F 0335 ; MA # ( 𝝷 → O̵ ) MATHEMATICAL SANS-SERIF BOLD SMALL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D78B ; 004F 0335 ; MA # ( 𝞋 → O̵ ) MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D7B1 ; 004F 0335 ; MA # ( 𝞱 → O̵ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+1D7C5 ; 004F 0335 ; MA # ( 𝟅 → O̵ ) MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →θ→→Ꮎ→
+0398 ; 004F 0335 ; MA # ( Θ → O̵ ) GREEK CAPITAL LETTER THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ꮎ→
+03F4 ; 004F 0335 ; MA # ( ϴ → O̵ ) GREEK CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ѳ→→О̵→
+1D6AF ; 004F 0335 ; MA # ( 𝚯 → O̵ ) MATHEMATICAL BOLD CAPITAL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D6B9 ; 004F 0335 ; MA # ( 𝚹 → O̵ ) MATHEMATICAL BOLD CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D6E9 ; 004F 0335 ; MA # ( 𝛩 → O̵ ) MATHEMATICAL ITALIC CAPITAL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D6F3 ; 004F 0335 ; MA # ( 𝛳 → O̵ ) MATHEMATICAL ITALIC CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D723 ; 004F 0335 ; MA # ( 𝜣 → O̵ ) MATHEMATICAL BOLD ITALIC CAPITAL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D72D ; 004F 0335 ; MA # ( 𝜭 → O̵ ) MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D75D ; 004F 0335 ; MA # ( 𝝝 → O̵ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D767 ; 004F 0335 ; MA # ( 𝝧 → O̵ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D797 ; 004F 0335 ; MA # ( 𝞗 → O̵ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+1D7A1 ; 004F 0335 ; MA # ( 𝞡 → O̵ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Θ→→Ꮎ→
+04E8 ; 004F 0335 ; MA # ( Ө → O̵ ) CYRILLIC CAPITAL LETTER BARRED O → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ѳ→→О̵→
+0472 ; 004F 0335 ; MA # ( Ѳ → O̵ ) CYRILLIC CAPITAL LETTER FITA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →О̵→
+2D31 ; 004F 0335 ; MA # ( ⴱ → O̵ ) TIFINAGH LETTER YAB → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ɵ→→O̶→
+13BE ; 004F 0335 ; MA # ( Ꮎ → O̵ ) CHEROKEE LETTER NA → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY #
+13EB ; 004F 0335 ; MA # ( Ꮻ → O̵ ) CHEROKEE LETTER WI → LATIN CAPITAL LETTER O, COMBINING SHORT STROKE OVERLAY # →Ѳ→→О̵→
+
+AB74 ; 006F 031B ; MA # ( ꭴ → ơ ) CHEROKEE SMALL LETTER U → LATIN SMALL LETTER O, COMBINING HORN #
+
+FCD9 ; 006F 0670 ; MA # ( ‎ﳙ‎ → oٰ ) ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM → LATIN SMALL LETTER O, ARABIC LETTER SUPERSCRIPT ALEF # →‎هٰ‎→
+
+1F101 ; 004F 002C ; MA #* ( 🄁 → O, ) DIGIT ZERO COMMA → LATIN CAPITAL LETTER O, COMMA # →0,→
+
+1F100 ; 004F 002E ; MA #* ( 🄀 → O. ) DIGIT ZERO FULL STOP → LATIN CAPITAL LETTER O, FULL STOP # →0.→
+
+01A1 ; 006F 0027 ; MA # ( ơ → o' ) LATIN SMALL LETTER O WITH HORN → LATIN SMALL LETTER O, APOSTROPHE # →oʼ→
+
+01A0 ; 004F 0027 ; MA # ( Ơ → O' ) LATIN CAPITAL LETTER O WITH HORN → LATIN CAPITAL LETTER O, APOSTROPHE # →Oʼ→
+13A4 ; 004F 0027 ; MA # ( Ꭴ → O' ) CHEROKEE LETTER U → LATIN CAPITAL LETTER O, APOSTROPHE # →Ơ→→Oʼ→
+
+0025 ; 00BA 002F 2080 ; MA #* ( % → º/₀ ) PERCENT SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO # →⁰/₀→
+066A ; 00BA 002F 2080 ; MA #* ( ٪ → º/₀ ) ARABIC PERCENT SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO # →%→→⁰/₀→
+2052 ; 00BA 002F 2080 ; MA #* ( ⁒ → º/₀ ) COMMERCIAL MINUS SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO # →%→→⁰/₀→
+
+2030 ; 00BA 002F 2080 2080 ; MA #* ( ‰ → º/₀₀ ) PER MILLE SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO, SUBSCRIPT ZERO # →⁰/₀₀→
+0609 ; 00BA 002F 2080 2080 ; MA #* ( ؉ → º/₀₀ ) ARABIC-INDIC PER MILLE SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO, SUBSCRIPT ZERO # →‰→→⁰/₀₀→
+
+2031 ; 00BA 002F 2080 2080 2080 ; MA #* ( ‱ → º/₀₀₀ ) PER TEN THOUSAND SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO, SUBSCRIPT ZERO, SUBSCRIPT ZERO # →⁰/₀₀₀→
+060A ; 00BA 002F 2080 2080 2080 ; MA #* ( ؊ → º/₀₀₀ ) ARABIC-INDIC PER TEN THOUSAND SIGN → MASCULINE ORDINAL INDICATOR, SOLIDUS, SUBSCRIPT ZERO, SUBSCRIPT ZERO, SUBSCRIPT ZERO # →‱→→⁰/₀₀₀→
+
+0153 ; 006F 0065 ; MA # ( œ → oe ) LATIN SMALL LIGATURE OE → LATIN SMALL LETTER O, LATIN SMALL LETTER E #
+
+0152 ; 004F 0045 ; MA # ( Œ → OE ) LATIN CAPITAL LIGATURE OE → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER E #
+
+0276 ; 006F 1D07 ; MA # ( ɶ → oᴇ ) LATIN LETTER SMALL CAPITAL OE → LATIN SMALL LETTER O, LATIN LETTER SMALL CAPITAL E #
+
+221E ; 006F 006F ; MA #* ( ∞ → oo ) INFINITY → LATIN SMALL LETTER O, LATIN SMALL LETTER O # →ꝏ→
+A74F ; 006F 006F ; MA # ( ꝏ → oo ) LATIN SMALL LETTER OO → LATIN SMALL LETTER O, LATIN SMALL LETTER O #
+A699 ; 006F 006F ; MA # ( ꚙ → oo ) CYRILLIC SMALL LETTER DOUBLE O → LATIN SMALL LETTER O, LATIN SMALL LETTER O #
+
+A74E ; 004F 004F ; MA # ( Ꝏ → OO ) LATIN CAPITAL LETTER OO → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER O #
+A698 ; 004F 004F ; MA # ( Ꚙ → OO ) CYRILLIC CAPITAL LETTER DOUBLE O → LATIN CAPITAL LETTER O, LATIN CAPITAL LETTER O #
+
+FCD7 ; 006F 062C ; MA # ( ‎ﳗ‎ → ‎oج‎ ) ARABIC LIGATURE HEH WITH JEEM INITIAL FORM → LATIN SMALL LETTER O, ARABIC LETTER JEEM # →‎هج‎→
+FC51 ; 006F 062C ; MA # ( ‎ﱑ‎ → ‎oج‎ ) ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM → LATIN SMALL LETTER O, ARABIC LETTER JEEM # →‎هج‎→
+
+FCD8 ; 006F 0645 ; MA # ( ‎ﳘ‎ → ‎oم‎ ) ARABIC LIGATURE HEH WITH MEEM INITIAL FORM → LATIN SMALL LETTER O, ARABIC LETTER MEEM # →‎هم‎→
+FC52 ; 006F 0645 ; MA # ( ‎ﱒ‎ → ‎oم‎ ) ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM → LATIN SMALL LETTER O, ARABIC LETTER MEEM # →‎هم‎→
+
+FD93 ; 006F 0645 062C ; MA # ( ‎ﶓ‎ → ‎oمج‎ ) ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM → LATIN SMALL LETTER O, ARABIC LETTER MEEM, ARABIC LETTER JEEM # →‎همج‎→
+
+FD94 ; 006F 0645 0645 ; MA # ( ‎ﶔ‎ → ‎oمم‎ ) ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM → LATIN SMALL LETTER O, ARABIC LETTER MEEM, ARABIC LETTER MEEM # →‎همم‎→
+
+FC53 ; 006F 0649 ; MA # ( ‎ﱓ‎ → ‎oى‎ ) ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM → LATIN SMALL LETTER O, ARABIC LETTER ALEF MAKSURA # →‎هى‎→
+FC54 ; 006F 0649 ; MA # ( ‎ﱔ‎ → ‎oى‎ ) ARABIC LIGATURE HEH WITH YEH ISOLATED FORM → LATIN SMALL LETTER O, ARABIC LETTER ALEF MAKSURA # →‎هي‎→
+
+0D5F ; 006F 0D30 006F ; MA # ( ൟ → oരo ) MALAYALAM LETTER ARCHAIC II → LATIN SMALL LETTER O, MALAYALAM LETTER RA, LATIN SMALL LETTER O # →ംരം→
+
+1010 ; 006F 102C ; MA # ( တ → oာ ) MYANMAR LETTER TA → LATIN SMALL LETTER O, MYANMAR VOWEL SIGN AA # →ဝာ→
+
+3358 ; 004F 70B9 ; MA #* ( ㍘ → O点 ) IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO → LATIN CAPITAL LETTER O, CJK UNIFIED IDEOGRAPH-70B9 # →0点→
+
+2184 ; 0254 ; MA # ( ↄ → ɔ ) LATIN SMALL LETTER REVERSED C → LATIN SMALL LETTER OPEN O #
+1D10 ; 0254 ; MA # ( ᴐ → ɔ ) LATIN LETTER SMALL CAPITAL OPEN O → LATIN SMALL LETTER OPEN O #
+037B ; 0254 ; MA # ( ͻ → ɔ ) GREEK SMALL REVERSED LUNATE SIGMA SYMBOL → LATIN SMALL LETTER OPEN O #
+1044B ; 0254 ; MA # ( 𐑋 → ɔ ) DESERET SMALL LETTER EM → LATIN SMALL LETTER OPEN O #
+
+2183 ; 0186 ; MA # ( Ↄ → Ɔ ) ROMAN NUMERAL REVERSED ONE HUNDRED → LATIN CAPITAL LETTER OPEN O #
+03FD ; 0186 ; MA # ( Ͻ → Ɔ ) GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL → LATIN CAPITAL LETTER OPEN O #
+A4DB ; 0186 ; MA # ( ꓛ → Ɔ ) LISU LETTER CHA → LATIN CAPITAL LETTER OPEN O #
+10423 ; 0186 ; MA # ( 𐐣 → Ɔ ) DESERET CAPITAL LETTER EM → LATIN CAPITAL LETTER OPEN O #
+
+AB3F ; 0254 0338 ; MA # ( ꬿ → ɔ̸ ) LATIN SMALL LETTER OPEN O WITH STROKE → LATIN SMALL LETTER OPEN O, COMBINING LONG SOLIDUS OVERLAY #
+
+AB62 ; 0254 0065 ; MA # ( ꭢ → ɔe ) LATIN SMALL LETTER OPEN OE → LATIN SMALL LETTER OPEN O, LATIN SMALL LETTER E #
+
+1043F ; 0277 ; MA # ( 𐐿 → ɷ ) DESERET SMALL LETTER KAY → LATIN SMALL LETTER CLOSED OMEGA #
+
+2374 ; 0070 ; MA #* ( ⍴ → p ) APL FUNCTIONAL SYMBOL RHO → LATIN SMALL LETTER P # →ρ→
+FF50 ; 0070 ; MA # ( p → p ) FULLWIDTH LATIN SMALL LETTER P → LATIN SMALL LETTER P # →р→
+1D429 ; 0070 ; MA # ( 𝐩 → p ) MATHEMATICAL BOLD SMALL P → LATIN SMALL LETTER P #
+1D45D ; 0070 ; MA # ( 𝑝 → p ) MATHEMATICAL ITALIC SMALL P → LATIN SMALL LETTER P #
+1D491 ; 0070 ; MA # ( 𝒑 → p ) MATHEMATICAL BOLD ITALIC SMALL P → LATIN SMALL LETTER P #
+1D4C5 ; 0070 ; MA # ( 𝓅 → p ) MATHEMATICAL SCRIPT SMALL P → LATIN SMALL LETTER P #
+1D4F9 ; 0070 ; MA # ( 𝓹 → p ) MATHEMATICAL BOLD SCRIPT SMALL P → LATIN SMALL LETTER P #
+1D52D ; 0070 ; MA # ( 𝔭 → p ) MATHEMATICAL FRAKTUR SMALL P → LATIN SMALL LETTER P #
+1D561 ; 0070 ; MA # ( 𝕡 → p ) MATHEMATICAL DOUBLE-STRUCK SMALL P → LATIN SMALL LETTER P #
+1D595 ; 0070 ; MA # ( 𝖕 → p ) MATHEMATICAL BOLD FRAKTUR SMALL P → LATIN SMALL LETTER P #
+1D5C9 ; 0070 ; MA # ( 𝗉 → p ) MATHEMATICAL SANS-SERIF SMALL P → LATIN SMALL LETTER P #
+1D5FD ; 0070 ; MA # ( 𝗽 → p ) MATHEMATICAL SANS-SERIF BOLD SMALL P → LATIN SMALL LETTER P #
+1D631 ; 0070 ; MA # ( 𝘱 → p ) MATHEMATICAL SANS-SERIF ITALIC SMALL P → LATIN SMALL LETTER P #
+1D665 ; 0070 ; MA # ( 𝙥 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P → LATIN SMALL LETTER P #
+1D699 ; 0070 ; MA # ( 𝚙 → p ) MATHEMATICAL MONOSPACE SMALL P → LATIN SMALL LETTER P #
+03C1 ; 0070 ; MA # ( ρ → p ) GREEK SMALL LETTER RHO → LATIN SMALL LETTER P #
+03F1 ; 0070 ; MA # ( ϱ → p ) GREEK RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+1D6D2 ; 0070 ; MA # ( 𝛒 → p ) MATHEMATICAL BOLD SMALL RHO → LATIN SMALL LETTER P # →ρ→
+1D6E0 ; 0070 ; MA # ( 𝛠 → p ) MATHEMATICAL BOLD RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+1D70C ; 0070 ; MA # ( 𝜌 → p ) MATHEMATICAL ITALIC SMALL RHO → LATIN SMALL LETTER P # →ρ→
+1D71A ; 0070 ; MA # ( 𝜚 → p ) MATHEMATICAL ITALIC RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+1D746 ; 0070 ; MA # ( 𝝆 → p ) MATHEMATICAL BOLD ITALIC SMALL RHO → LATIN SMALL LETTER P # →ρ→
+1D754 ; 0070 ; MA # ( 𝝔 → p ) MATHEMATICAL BOLD ITALIC RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+1D780 ; 0070 ; MA # ( 𝞀 → p ) MATHEMATICAL SANS-SERIF BOLD SMALL RHO → LATIN SMALL LETTER P # →ρ→
+1D78E ; 0070 ; MA # ( 𝞎 → p ) MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+1D7BA ; 0070 ; MA # ( 𝞺 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO → LATIN SMALL LETTER P # →ρ→
+1D7C8 ; 0070 ; MA # ( 𝟈 → p ) MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL → LATIN SMALL LETTER P # →ρ→
+2CA3 ; 0070 ; MA # ( ⲣ → p ) COPTIC SMALL LETTER RO → LATIN SMALL LETTER P # →ρ→
+0440 ; 0070 ; MA # ( р → p ) CYRILLIC SMALL LETTER ER → LATIN SMALL LETTER P #
+
+FF30 ; 0050 ; MA # ( P → P ) FULLWIDTH LATIN CAPITAL LETTER P → LATIN CAPITAL LETTER P # →Р→
+2119 ; 0050 ; MA # ( ℙ → P ) DOUBLE-STRUCK CAPITAL P → LATIN CAPITAL LETTER P #
+1D40F ; 0050 ; MA # ( 𝐏 → P ) MATHEMATICAL BOLD CAPITAL P → LATIN CAPITAL LETTER P #
+1D443 ; 0050 ; MA # ( 𝑃 → P ) MATHEMATICAL ITALIC CAPITAL P → LATIN CAPITAL LETTER P #
+1D477 ; 0050 ; MA # ( 𝑷 → P ) MATHEMATICAL BOLD ITALIC CAPITAL P → LATIN CAPITAL LETTER P #
+1D4AB ; 0050 ; MA # ( 𝒫 → P ) MATHEMATICAL SCRIPT CAPITAL P → LATIN CAPITAL LETTER P #
+1D4DF ; 0050 ; MA # ( 𝓟 → P ) MATHEMATICAL BOLD SCRIPT CAPITAL P → LATIN CAPITAL LETTER P #
+1D513 ; 0050 ; MA # ( 𝔓 → P ) MATHEMATICAL FRAKTUR CAPITAL P → LATIN CAPITAL LETTER P #
+1D57B ; 0050 ; MA # ( 𝕻 → P ) MATHEMATICAL BOLD FRAKTUR CAPITAL P → LATIN CAPITAL LETTER P #
+1D5AF ; 0050 ; MA # ( 𝖯 → P ) MATHEMATICAL SANS-SERIF CAPITAL P → LATIN CAPITAL LETTER P #
+1D5E3 ; 0050 ; MA # ( 𝗣 → P ) MATHEMATICAL SANS-SERIF BOLD CAPITAL P → LATIN CAPITAL LETTER P #
+1D617 ; 0050 ; MA # ( 𝘗 → P ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL P → LATIN CAPITAL LETTER P #
+1D64B ; 0050 ; MA # ( 𝙋 → P ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P → LATIN CAPITAL LETTER P #
+1D67F ; 0050 ; MA # ( 𝙿 → P ) MATHEMATICAL MONOSPACE CAPITAL P → LATIN CAPITAL LETTER P #
+03A1 ; 0050 ; MA # ( Ρ → P ) GREEK CAPITAL LETTER RHO → LATIN CAPITAL LETTER P #
+1D6B8 ; 0050 ; MA # ( 𝚸 → P ) MATHEMATICAL BOLD CAPITAL RHO → LATIN CAPITAL LETTER P # →𝐏→
+1D6F2 ; 0050 ; MA # ( 𝛲 → P ) MATHEMATICAL ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P # →Ρ→
+1D72C ; 0050 ; MA # ( 𝜬 → P ) MATHEMATICAL BOLD ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P # →Ρ→
+1D766 ; 0050 ; MA # ( 𝝦 → P ) MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO → LATIN CAPITAL LETTER P # →Ρ→
+1D7A0 ; 0050 ; MA # ( 𝞠 → P ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO → LATIN CAPITAL LETTER P # →Ρ→
+2CA2 ; 0050 ; MA # ( Ⲣ → P ) COPTIC CAPITAL LETTER RO → LATIN CAPITAL LETTER P #
+0420 ; 0050 ; MA # ( Р → P ) CYRILLIC CAPITAL LETTER ER → LATIN CAPITAL LETTER P #
+13E2 ; 0050 ; MA # ( Ꮲ → P ) CHEROKEE LETTER TLV → LATIN CAPITAL LETTER P #
+146D ; 0050 ; MA # ( ᑭ → P ) CANADIAN SYLLABICS KI → LATIN CAPITAL LETTER P #
+A4D1 ; 0050 ; MA # ( ꓑ → P ) LISU LETTER PA → LATIN CAPITAL LETTER P #
+10295 ; 0050 ; MA # ( 𐊕 → P ) LYCIAN LETTER R → LATIN CAPITAL LETTER P #
+
+01A5 ; 0070 0314 ; MA # ( ƥ → p̔ ) LATIN SMALL LETTER P WITH HOOK → LATIN SMALL LETTER P, COMBINING REVERSED COMMA ABOVE #
+
+1D7D ; 0070 0335 ; MA # ( ᵽ → p̵ ) LATIN SMALL LETTER P WITH STROKE → LATIN SMALL LETTER P, COMBINING SHORT STROKE OVERLAY #
+
+1477 ; 0070 00B7 ; MA # ( ᑷ → p· ) CANADIAN SYLLABICS WEST-CREE KWI → LATIN SMALL LETTER P, MIDDLE DOT # →pᐧ→
+
+1486 ; 0050 0027 ; MA # ( ᒆ → P' ) CANADIAN SYLLABICS SOUTH-SLAVEY KIH → LATIN CAPITAL LETTER P, APOSTROPHE # →ᑭᑊ→
+
+1D29 ; 1D18 ; MA # ( ᴩ → ᴘ ) GREEK LETTER SMALL CAPITAL RHO → LATIN LETTER SMALL CAPITAL P #
+ABB2 ; 1D18 ; MA # ( ꮲ → ᴘ ) CHEROKEE SMALL LETTER TLV → LATIN LETTER SMALL CAPITAL P #
+
+03C6 ; 0278 ; MA # ( φ → ɸ ) GREEK SMALL LETTER PHI → LATIN SMALL LETTER PHI #
+03D5 ; 0278 ; MA # ( ϕ → ɸ ) GREEK PHI SYMBOL → LATIN SMALL LETTER PHI #
+1D6D7 ; 0278 ; MA # ( 𝛗 → ɸ ) MATHEMATICAL BOLD SMALL PHI → LATIN SMALL LETTER PHI # →φ→
+1D6DF ; 0278 ; MA # ( 𝛟 → ɸ ) MATHEMATICAL BOLD PHI SYMBOL → LATIN SMALL LETTER PHI # →φ→
+1D711 ; 0278 ; MA # ( 𝜑 → ɸ ) MATHEMATICAL ITALIC SMALL PHI → LATIN SMALL LETTER PHI # →φ→
+1D719 ; 0278 ; MA # ( 𝜙 → ɸ ) MATHEMATICAL ITALIC PHI SYMBOL → LATIN SMALL LETTER PHI # →φ→
+1D74B ; 0278 ; MA # ( 𝝋 → ɸ ) MATHEMATICAL BOLD ITALIC SMALL PHI → LATIN SMALL LETTER PHI # →φ→
+1D753 ; 0278 ; MA # ( 𝝓 → ɸ ) MATHEMATICAL BOLD ITALIC PHI SYMBOL → LATIN SMALL LETTER PHI # →φ→
+1D785 ; 0278 ; MA # ( 𝞅 → ɸ ) MATHEMATICAL SANS-SERIF BOLD SMALL PHI → LATIN SMALL LETTER PHI # →φ→
+1D78D ; 0278 ; MA # ( 𝞍 → ɸ ) MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL → LATIN SMALL LETTER PHI # →φ→
+1D7BF ; 0278 ; MA # ( 𝞿 → ɸ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI → LATIN SMALL LETTER PHI # →φ→
+1D7C7 ; 0278 ; MA # ( 𝟇 → ɸ ) MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL → LATIN SMALL LETTER PHI # →φ→
+2CAB ; 0278 ; MA # ( ⲫ → ɸ ) COPTIC SMALL LETTER FI → LATIN SMALL LETTER PHI # →ϕ→
+0444 ; 0278 ; MA # ( ф → ɸ ) CYRILLIC SMALL LETTER EF → LATIN SMALL LETTER PHI #
+
+1D42A ; 0071 ; MA # ( 𝐪 → q ) MATHEMATICAL BOLD SMALL Q → LATIN SMALL LETTER Q #
+1D45E ; 0071 ; MA # ( 𝑞 → q ) MATHEMATICAL ITALIC SMALL Q → LATIN SMALL LETTER Q #
+1D492 ; 0071 ; MA # ( 𝒒 → q ) MATHEMATICAL BOLD ITALIC SMALL Q → LATIN SMALL LETTER Q #
+1D4C6 ; 0071 ; MA # ( 𝓆 → q ) MATHEMATICAL SCRIPT SMALL Q → LATIN SMALL LETTER Q #
+1D4FA ; 0071 ; MA # ( 𝓺 → q ) MATHEMATICAL BOLD SCRIPT SMALL Q → LATIN SMALL LETTER Q #
+1D52E ; 0071 ; MA # ( 𝔮 → q ) MATHEMATICAL FRAKTUR SMALL Q → LATIN SMALL LETTER Q #
+1D562 ; 0071 ; MA # ( 𝕢 → q ) MATHEMATICAL DOUBLE-STRUCK SMALL Q → LATIN SMALL LETTER Q #
+1D596 ; 0071 ; MA # ( 𝖖 → q ) MATHEMATICAL BOLD FRAKTUR SMALL Q → LATIN SMALL LETTER Q #
+1D5CA ; 0071 ; MA # ( 𝗊 → q ) MATHEMATICAL SANS-SERIF SMALL Q → LATIN SMALL LETTER Q #
+1D5FE ; 0071 ; MA # ( 𝗾 → q ) MATHEMATICAL SANS-SERIF BOLD SMALL Q → LATIN SMALL LETTER Q #
+1D632 ; 0071 ; MA # ( 𝘲 → q ) MATHEMATICAL SANS-SERIF ITALIC SMALL Q → LATIN SMALL LETTER Q #
+1D666 ; 0071 ; MA # ( 𝙦 → q ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q → LATIN SMALL LETTER Q #
+1D69A ; 0071 ; MA # ( 𝚚 → q ) MATHEMATICAL MONOSPACE SMALL Q → LATIN SMALL LETTER Q #
+051B ; 0071 ; MA # ( ԛ → q ) CYRILLIC SMALL LETTER QA → LATIN SMALL LETTER Q #
+0563 ; 0071 ; MA # ( գ → q ) ARMENIAN SMALL LETTER GIM → LATIN SMALL LETTER Q #
+0566 ; 0071 ; MA # ( զ → q ) ARMENIAN SMALL LETTER ZA → LATIN SMALL LETTER Q #
+
+211A ; 0051 ; MA # ( ℚ → Q ) DOUBLE-STRUCK CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D410 ; 0051 ; MA # ( 𝐐 → Q ) MATHEMATICAL BOLD CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D444 ; 0051 ; MA # ( 𝑄 → Q ) MATHEMATICAL ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D478 ; 0051 ; MA # ( 𝑸 → Q ) MATHEMATICAL BOLD ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D4AC ; 0051 ; MA # ( 𝒬 → Q ) MATHEMATICAL SCRIPT CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D4E0 ; 0051 ; MA # ( 𝓠 → Q ) MATHEMATICAL BOLD SCRIPT CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D514 ; 0051 ; MA # ( 𝔔 → Q ) MATHEMATICAL FRAKTUR CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D57C ; 0051 ; MA # ( 𝕼 → Q ) MATHEMATICAL BOLD FRAKTUR CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D5B0 ; 0051 ; MA # ( 𝖰 → Q ) MATHEMATICAL SANS-SERIF CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D5E4 ; 0051 ; MA # ( 𝗤 → Q ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D618 ; 0051 ; MA # ( 𝘘 → Q ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D64C ; 0051 ; MA # ( 𝙌 → Q ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q → LATIN CAPITAL LETTER Q #
+1D680 ; 0051 ; MA # ( 𝚀 → Q ) MATHEMATICAL MONOSPACE CAPITAL Q → LATIN CAPITAL LETTER Q #
+2D55 ; 0051 ; MA # ( ⵕ → Q ) TIFINAGH LETTER YARR → LATIN CAPITAL LETTER Q #
+
+02A0 ; 0071 0314 ; MA # ( ʠ → q̔ ) LATIN SMALL LETTER Q WITH HOOK → LATIN SMALL LETTER Q, COMBINING REVERSED COMMA ABOVE #
+
+1F700 ; 0051 0045 ; MA #* ( 🜀 → QE ) ALCHEMICAL SYMBOL FOR QUINTESSENCE → LATIN CAPITAL LETTER Q, LATIN CAPITAL LETTER E #
+
+1D90 ; 024B ; MA # ( ᶐ → ɋ ) LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK → LATIN SMALL LETTER Q WITH HOOK TAIL #
+
+1D0B ; 0138 ; MA # ( ᴋ → ĸ ) LATIN LETTER SMALL CAPITAL K → LATIN SMALL LETTER KRA #
+03BA ; 0138 ; MA # ( κ → ĸ ) GREEK SMALL LETTER KAPPA → LATIN SMALL LETTER KRA #
+03F0 ; 0138 ; MA # ( ϰ → ĸ ) GREEK KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+1D6CB ; 0138 ; MA # ( 𝛋 → ĸ ) MATHEMATICAL BOLD SMALL KAPPA → LATIN SMALL LETTER KRA # →κ→
+1D6DE ; 0138 ; MA # ( 𝛞 → ĸ ) MATHEMATICAL BOLD KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+1D705 ; 0138 ; MA # ( 𝜅 → ĸ ) MATHEMATICAL ITALIC SMALL KAPPA → LATIN SMALL LETTER KRA # →κ→
+1D718 ; 0138 ; MA # ( 𝜘 → ĸ ) MATHEMATICAL ITALIC KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+1D73F ; 0138 ; MA # ( 𝜿 → ĸ ) MATHEMATICAL BOLD ITALIC SMALL KAPPA → LATIN SMALL LETTER KRA # →κ→
+1D752 ; 0138 ; MA # ( 𝝒 → ĸ ) MATHEMATICAL BOLD ITALIC KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+1D779 ; 0138 ; MA # ( 𝝹 → ĸ ) MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA → LATIN SMALL LETTER KRA # →κ→
+1D78C ; 0138 ; MA # ( 𝞌 → ĸ ) MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+1D7B3 ; 0138 ; MA # ( 𝞳 → ĸ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA → LATIN SMALL LETTER KRA # →κ→
+1D7C6 ; 0138 ; MA # ( 𝟆 → ĸ ) MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL → LATIN SMALL LETTER KRA # →κ→
+2C95 ; 0138 ; MA # ( ⲕ → ĸ ) COPTIC SMALL LETTER KAPA → LATIN SMALL LETTER KRA # →κ→
+043A ; 0138 ; MA # ( к → ĸ ) CYRILLIC SMALL LETTER KA → LATIN SMALL LETTER KRA #
+ABB6 ; 0138 ; MA # ( ꮶ → ĸ ) CHEROKEE SMALL LETTER TSO → LATIN SMALL LETTER KRA # →ᴋ→
+
+049B ; 0138 0329 ; MA # ( қ → ĸ̩ ) CYRILLIC SMALL LETTER KA WITH DESCENDER → LATIN SMALL LETTER KRA, COMBINING VERTICAL LINE BELOW # →к̩→
+
+049F ; 0138 0335 ; MA # ( ҟ → ĸ̵ ) CYRILLIC SMALL LETTER KA WITH STROKE → LATIN SMALL LETTER KRA, COMBINING SHORT STROKE OVERLAY # →к̵→
+
+1D42B ; 0072 ; MA # ( 𝐫 → r ) MATHEMATICAL BOLD SMALL R → LATIN SMALL LETTER R #
+1D45F ; 0072 ; MA # ( 𝑟 → r ) MATHEMATICAL ITALIC SMALL R → LATIN SMALL LETTER R #
+1D493 ; 0072 ; MA # ( 𝒓 → r ) MATHEMATICAL BOLD ITALIC SMALL R → LATIN SMALL LETTER R #
+1D4C7 ; 0072 ; MA # ( 𝓇 → r ) MATHEMATICAL SCRIPT SMALL R → LATIN SMALL LETTER R #
+1D4FB ; 0072 ; MA # ( 𝓻 → r ) MATHEMATICAL BOLD SCRIPT SMALL R → LATIN SMALL LETTER R #
+1D52F ; 0072 ; MA # ( 𝔯 → r ) MATHEMATICAL FRAKTUR SMALL R → LATIN SMALL LETTER R #
+1D563 ; 0072 ; MA # ( 𝕣 → r ) MATHEMATICAL DOUBLE-STRUCK SMALL R → LATIN SMALL LETTER R #
+1D597 ; 0072 ; MA # ( 𝖗 → r ) MATHEMATICAL BOLD FRAKTUR SMALL R → LATIN SMALL LETTER R #
+1D5CB ; 0072 ; MA # ( 𝗋 → r ) MATHEMATICAL SANS-SERIF SMALL R → LATIN SMALL LETTER R #
+1D5FF ; 0072 ; MA # ( 𝗿 → r ) MATHEMATICAL SANS-SERIF BOLD SMALL R → LATIN SMALL LETTER R #
+1D633 ; 0072 ; MA # ( 𝘳 → r ) MATHEMATICAL SANS-SERIF ITALIC SMALL R → LATIN SMALL LETTER R #
+1D667 ; 0072 ; MA # ( 𝙧 → r ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R → LATIN SMALL LETTER R #
+1D69B ; 0072 ; MA # ( 𝚛 → r ) MATHEMATICAL MONOSPACE SMALL R → LATIN SMALL LETTER R #
+AB47 ; 0072 ; MA # ( ꭇ → r ) LATIN SMALL LETTER R WITHOUT HANDLE → LATIN SMALL LETTER R #
+AB48 ; 0072 ; MA # ( ꭈ → r ) LATIN SMALL LETTER DOUBLE R → LATIN SMALL LETTER R #
+1D26 ; 0072 ; MA # ( ᴦ → r ) GREEK LETTER SMALL CAPITAL GAMMA → LATIN SMALL LETTER R # →г→
+2C85 ; 0072 ; MA # ( ⲅ → r ) COPTIC SMALL LETTER GAMMA → LATIN SMALL LETTER R # →г→
+0433 ; 0072 ; MA # ( г → r ) CYRILLIC SMALL LETTER GHE → LATIN SMALL LETTER R #
+AB81 ; 0072 ; MA # ( ꮁ → r ) CHEROKEE SMALL LETTER HU → LATIN SMALL LETTER R # →ᴦ→→г→
+
+1D216 ; 0052 ; MA #* ( 𝈖 → R ) GREEK VOCAL NOTATION SYMBOL-23 → LATIN CAPITAL LETTER R #
+211B ; 0052 ; MA # ( ℛ → R ) SCRIPT CAPITAL R → LATIN CAPITAL LETTER R #
+211C ; 0052 ; MA # ( ℜ → R ) BLACK-LETTER CAPITAL R → LATIN CAPITAL LETTER R #
+211D ; 0052 ; MA # ( ℝ → R ) DOUBLE-STRUCK CAPITAL R → LATIN CAPITAL LETTER R #
+1D411 ; 0052 ; MA # ( 𝐑 → R ) MATHEMATICAL BOLD CAPITAL R → LATIN CAPITAL LETTER R #
+1D445 ; 0052 ; MA # ( 𝑅 → R ) MATHEMATICAL ITALIC CAPITAL R → LATIN CAPITAL LETTER R #
+1D479 ; 0052 ; MA # ( 𝑹 → R ) MATHEMATICAL BOLD ITALIC CAPITAL R → LATIN CAPITAL LETTER R #
+1D4E1 ; 0052 ; MA # ( 𝓡 → R ) MATHEMATICAL BOLD SCRIPT CAPITAL R → LATIN CAPITAL LETTER R #
+1D57D ; 0052 ; MA # ( 𝕽 → R ) MATHEMATICAL BOLD FRAKTUR CAPITAL R → LATIN CAPITAL LETTER R #
+1D5B1 ; 0052 ; MA # ( 𝖱 → R ) MATHEMATICAL SANS-SERIF CAPITAL R → LATIN CAPITAL LETTER R #
+1D5E5 ; 0052 ; MA # ( 𝗥 → R ) MATHEMATICAL SANS-SERIF BOLD CAPITAL R → LATIN CAPITAL LETTER R #
+1D619 ; 0052 ; MA # ( 𝘙 → R ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL R → LATIN CAPITAL LETTER R #
+1D64D ; 0052 ; MA # ( 𝙍 → R ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R → LATIN CAPITAL LETTER R #
+1D681 ; 0052 ; MA # ( 𝚁 → R ) MATHEMATICAL MONOSPACE CAPITAL R → LATIN CAPITAL LETTER R #
+01A6 ; 0052 ; MA # ( Ʀ → R ) LATIN LETTER YR → LATIN CAPITAL LETTER R #
+13A1 ; 0052 ; MA # ( Ꭱ → R ) CHEROKEE LETTER E → LATIN CAPITAL LETTER R #
+13D2 ; 0052 ; MA # ( Ꮢ → R ) CHEROKEE LETTER SV → LATIN CAPITAL LETTER R #
+104B4 ; 0052 ; MA # ( 𐒴 → R ) OSAGE CAPITAL LETTER BRA → LATIN CAPITAL LETTER R # →Ʀ→
+1587 ; 0052 ; MA # ( ᖇ → R ) CANADIAN SYLLABICS TLHI → LATIN CAPITAL LETTER R #
+A4E3 ; 0052 ; MA # ( ꓣ → R ) LISU LETTER ZHA → LATIN CAPITAL LETTER R #
+16F35 ; 0052 ; MA # ( 𖼵 → R ) MIAO LETTER ZHA → LATIN CAPITAL LETTER R #
+
+027D ; 0072 0328 ; MA # ( ɽ → r̨ ) LATIN SMALL LETTER R WITH TAIL → LATIN SMALL LETTER R, COMBINING OGONEK #
+
+027C ; 0072 0329 ; MA # ( ɼ → r̩ ) LATIN SMALL LETTER R WITH LONG LEG → LATIN SMALL LETTER R, COMBINING VERTICAL LINE BELOW #
+
+024D ; 0072 0335 ; MA # ( ɍ → r̵ ) LATIN SMALL LETTER R WITH STROKE → LATIN SMALL LETTER R, COMBINING SHORT STROKE OVERLAY #
+0493 ; 0072 0335 ; MA # ( ғ → r̵ ) CYRILLIC SMALL LETTER GHE WITH STROKE → LATIN SMALL LETTER R, COMBINING SHORT STROKE OVERLAY # →г̵→
+
+1D72 ; 0072 0334 ; MA # ( ᵲ → r̴ ) LATIN SMALL LETTER R WITH MIDDLE TILDE → LATIN SMALL LETTER R, COMBINING TILDE OVERLAY #
+
+0491 ; 0072 0027 ; MA # ( ґ → r' ) CYRILLIC SMALL LETTER GHE WITH UPTURN → LATIN SMALL LETTER R, APOSTROPHE # →гˈ→
+
+118E3 ; 0072 006E ; MA # ( 𑣣 → rn ) WARANG CITI DIGIT THREE → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+006D ; 0072 006E ; MA # ( m → rn ) LATIN SMALL LETTER M → LATIN SMALL LETTER R, LATIN SMALL LETTER N #
+217F ; 0072 006E ; MA # ( ⅿ → rn ) SMALL ROMAN NUMERAL ONE THOUSAND → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D426 ; 0072 006E ; MA # ( 𝐦 → rn ) MATHEMATICAL BOLD SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D45A ; 0072 006E ; MA # ( 𝑚 → rn ) MATHEMATICAL ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D48E ; 0072 006E ; MA # ( 𝒎 → rn ) MATHEMATICAL BOLD ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D4C2 ; 0072 006E ; MA # ( 𝓂 → rn ) MATHEMATICAL SCRIPT SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D4F6 ; 0072 006E ; MA # ( 𝓶 → rn ) MATHEMATICAL BOLD SCRIPT SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D52A ; 0072 006E ; MA # ( 𝔪 → rn ) MATHEMATICAL FRAKTUR SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D55E ; 0072 006E ; MA # ( 𝕞 → rn ) MATHEMATICAL DOUBLE-STRUCK SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D592 ; 0072 006E ; MA # ( 𝖒 → rn ) MATHEMATICAL BOLD FRAKTUR SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D5C6 ; 0072 006E ; MA # ( 𝗆 → rn ) MATHEMATICAL SANS-SERIF SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D5FA ; 0072 006E ; MA # ( 𝗺 → rn ) MATHEMATICAL SANS-SERIF BOLD SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D62E ; 0072 006E ; MA # ( 𝘮 → rn ) MATHEMATICAL SANS-SERIF ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D662 ; 0072 006E ; MA # ( 𝙢 → rn ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+1D696 ; 0072 006E ; MA # ( 𝚖 → rn ) MATHEMATICAL MONOSPACE SMALL M → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+11700 ; 0072 006E ; MA # ( 𑜀 → rn ) AHOM LETTER KA → LATIN SMALL LETTER R, LATIN SMALL LETTER N # →m→
+
+20A5 ; 0072 006E 0338 ; MA #* ( ₥ → rn̸ ) MILL SIGN → LATIN SMALL LETTER R, LATIN SMALL LETTER N, COMBINING LONG SOLIDUS OVERLAY # →m̷→
+
+0271 ; 0072 006E 0326 ; MA # ( ɱ → rn̦ ) LATIN SMALL LETTER M WITH HOOK → LATIN SMALL LETTER R, LATIN SMALL LETTER N, COMBINING COMMA BELOW # →m̡→
+
+1D6F ; 0072 006E 0334 ; MA # ( ᵯ → rn̴ ) LATIN SMALL LETTER M WITH MIDDLE TILDE → LATIN SMALL LETTER R, LATIN SMALL LETTER N, COMBINING TILDE OVERLAY # →m̴→
+
+20A8 ; 0052 0073 ; MA #* ( ₨ → Rs ) RUPEE SIGN → LATIN CAPITAL LETTER R, LATIN SMALL LETTER S #
+
+AB71 ; 0280 ; MA # ( ꭱ → ʀ ) CHEROKEE SMALL LETTER E → LATIN LETTER SMALL CAPITAL R #
+ABA2 ; 0280 ; MA # ( ꮢ → ʀ ) CHEROKEE SMALL LETTER SV → LATIN LETTER SMALL CAPITAL R #
+
+044F ; 1D19 ; MA # ( я → ᴙ ) CYRILLIC SMALL LETTER YA → LATIN LETTER SMALL CAPITAL REVERSED R #
+
+1D73 ; 027E 0334 ; MA # ( ᵳ → ɾ̴ ) LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE → LATIN SMALL LETTER R WITH FISHHOOK, COMBINING TILDE OVERLAY #
+
+2129 ; 027F ; MA #* ( ℩ → ɿ ) TURNED GREEK SMALL LETTER IOTA → LATIN SMALL LETTER REVERSED R WITH FISHHOOK #
+
+FF53 ; 0073 ; MA # ( s → s ) FULLWIDTH LATIN SMALL LETTER S → LATIN SMALL LETTER S # →ѕ→
+1D42C ; 0073 ; MA # ( 𝐬 → s ) MATHEMATICAL BOLD SMALL S → LATIN SMALL LETTER S #
+1D460 ; 0073 ; MA # ( 𝑠 → s ) MATHEMATICAL ITALIC SMALL S → LATIN SMALL LETTER S #
+1D494 ; 0073 ; MA # ( 𝒔 → s ) MATHEMATICAL BOLD ITALIC SMALL S → LATIN SMALL LETTER S #
+1D4C8 ; 0073 ; MA # ( 𝓈 → s ) MATHEMATICAL SCRIPT SMALL S → LATIN SMALL LETTER S #
+1D4FC ; 0073 ; MA # ( 𝓼 → s ) MATHEMATICAL BOLD SCRIPT SMALL S → LATIN SMALL LETTER S #
+1D530 ; 0073 ; MA # ( 𝔰 → s ) MATHEMATICAL FRAKTUR SMALL S → LATIN SMALL LETTER S #
+1D564 ; 0073 ; MA # ( 𝕤 → s ) MATHEMATICAL DOUBLE-STRUCK SMALL S → LATIN SMALL LETTER S #
+1D598 ; 0073 ; MA # ( 𝖘 → s ) MATHEMATICAL BOLD FRAKTUR SMALL S → LATIN SMALL LETTER S #
+1D5CC ; 0073 ; MA # ( 𝗌 → s ) MATHEMATICAL SANS-SERIF SMALL S → LATIN SMALL LETTER S #
+1D600 ; 0073 ; MA # ( 𝘀 → s ) MATHEMATICAL SANS-SERIF BOLD SMALL S → LATIN SMALL LETTER S #
+1D634 ; 0073 ; MA # ( 𝘴 → s ) MATHEMATICAL SANS-SERIF ITALIC SMALL S → LATIN SMALL LETTER S #
+1D668 ; 0073 ; MA # ( 𝙨 → s ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S → LATIN SMALL LETTER S #
+1D69C ; 0073 ; MA # ( 𝚜 → s ) MATHEMATICAL MONOSPACE SMALL S → LATIN SMALL LETTER S #
+A731 ; 0073 ; MA # ( ꜱ → s ) LATIN LETTER SMALL CAPITAL S → LATIN SMALL LETTER S #
+01BD ; 0073 ; MA # ( ƽ → s ) LATIN SMALL LETTER TONE FIVE → LATIN SMALL LETTER S #
+0455 ; 0073 ; MA # ( ѕ → s ) CYRILLIC SMALL LETTER DZE → LATIN SMALL LETTER S #
+ABAA ; 0073 ; MA # ( ꮪ → s ) CHEROKEE SMALL LETTER DU → LATIN SMALL LETTER S # →ꜱ→
+118C1 ; 0073 ; MA # ( 𑣁 → s ) WARANG CITI SMALL LETTER A → LATIN SMALL LETTER S #
+10448 ; 0073 ; MA # ( 𐑈 → s ) DESERET SMALL LETTER ZHEE → LATIN SMALL LETTER S #
+
+FF33 ; 0053 ; MA # ( S → S ) FULLWIDTH LATIN CAPITAL LETTER S → LATIN CAPITAL LETTER S # →Ѕ→
+1D412 ; 0053 ; MA # ( 𝐒 → S ) MATHEMATICAL BOLD CAPITAL S → LATIN CAPITAL LETTER S #
+1D446 ; 0053 ; MA # ( 𝑆 → S ) MATHEMATICAL ITALIC CAPITAL S → LATIN CAPITAL LETTER S #
+1D47A ; 0053 ; MA # ( 𝑺 → S ) MATHEMATICAL BOLD ITALIC CAPITAL S → LATIN CAPITAL LETTER S #
+1D4AE ; 0053 ; MA # ( 𝒮 → S ) MATHEMATICAL SCRIPT CAPITAL S → LATIN CAPITAL LETTER S #
+1D4E2 ; 0053 ; MA # ( 𝓢 → S ) MATHEMATICAL BOLD SCRIPT CAPITAL S → LATIN CAPITAL LETTER S #
+1D516 ; 0053 ; MA # ( 𝔖 → S ) MATHEMATICAL FRAKTUR CAPITAL S → LATIN CAPITAL LETTER S #
+1D54A ; 0053 ; MA # ( 𝕊 → S ) MATHEMATICAL DOUBLE-STRUCK CAPITAL S → LATIN CAPITAL LETTER S #
+1D57E ; 0053 ; MA # ( 𝕾 → S ) MATHEMATICAL BOLD FRAKTUR CAPITAL S → LATIN CAPITAL LETTER S #
+1D5B2 ; 0053 ; MA # ( 𝖲 → S ) MATHEMATICAL SANS-SERIF CAPITAL S → LATIN CAPITAL LETTER S #
+1D5E6 ; 0053 ; MA # ( 𝗦 → S ) MATHEMATICAL SANS-SERIF BOLD CAPITAL S → LATIN CAPITAL LETTER S #
+1D61A ; 0053 ; MA # ( 𝘚 → S ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL S → LATIN CAPITAL LETTER S #
+1D64E ; 0053 ; MA # ( 𝙎 → S ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S → LATIN CAPITAL LETTER S #
+1D682 ; 0053 ; MA # ( 𝚂 → S ) MATHEMATICAL MONOSPACE CAPITAL S → LATIN CAPITAL LETTER S #
+0405 ; 0053 ; MA # ( Ѕ → S ) CYRILLIC CAPITAL LETTER DZE → LATIN CAPITAL LETTER S #
+054F ; 0053 ; MA # ( Տ → S ) ARMENIAN CAPITAL LETTER TIWN → LATIN CAPITAL LETTER S #
+13D5 ; 0053 ; MA # ( Ꮥ → S ) CHEROKEE LETTER DE → LATIN CAPITAL LETTER S #
+13DA ; 0053 ; MA # ( Ꮪ → S ) CHEROKEE LETTER DU → LATIN CAPITAL LETTER S #
+A4E2 ; 0053 ; MA # ( ꓢ → S ) LISU LETTER SA → LATIN CAPITAL LETTER S #
+16F3A ; 0053 ; MA # ( 𖼺 → S ) MIAO LETTER SA → LATIN CAPITAL LETTER S #
+10296 ; 0053 ; MA # ( 𐊖 → S ) LYCIAN LETTER S → LATIN CAPITAL LETTER S #
+10420 ; 0053 ; MA # ( 𐐠 → S ) DESERET CAPITAL LETTER ZHEE → LATIN CAPITAL LETTER S #
+
+0282 ; 0073 0328 ; MA # ( ʂ → s̨ ) LATIN SMALL LETTER S WITH HOOK → LATIN SMALL LETTER S, COMBINING OGONEK #
+
+1D74 ; 0073 0334 ; MA # ( ᵴ → s̴ ) LATIN SMALL LETTER S WITH MIDDLE TILDE → LATIN SMALL LETTER S, COMBINING TILDE OVERLAY #
+
+A7B5 ; 00DF ; MA # ( ꞵ → ß ) LATIN SMALL LETTER BETA → LATIN SMALL LETTER SHARP S # →β→
+03B2 ; 00DF ; MA # ( β → ß ) GREEK SMALL LETTER BETA → LATIN SMALL LETTER SHARP S #
+03D0 ; 00DF ; MA # ( ϐ → ß ) GREEK BETA SYMBOL → LATIN SMALL LETTER SHARP S # →β→
+1D6C3 ; 00DF ; MA # ( 𝛃 → ß ) MATHEMATICAL BOLD SMALL BETA → LATIN SMALL LETTER SHARP S # →β→
+1D6FD ; 00DF ; MA # ( 𝛽 → ß ) MATHEMATICAL ITALIC SMALL BETA → LATIN SMALL LETTER SHARP S # →β→
+1D737 ; 00DF ; MA # ( 𝜷 → ß ) MATHEMATICAL BOLD ITALIC SMALL BETA → LATIN SMALL LETTER SHARP S # →β→
+1D771 ; 00DF ; MA # ( 𝝱 → ß ) MATHEMATICAL SANS-SERIF BOLD SMALL BETA → LATIN SMALL LETTER SHARP S # →β→
+1D7AB ; 00DF ; MA # ( 𝞫 → ß ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA → LATIN SMALL LETTER SHARP S # →β→
+13F0 ; 00DF ; MA # ( Ᏸ → ß ) CHEROKEE LETTER YE → LATIN SMALL LETTER SHARP S # →β→
+
+1F75C ; 0073 0073 0073 ; MA #* ( 🝜 → sss ) ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM → LATIN SMALL LETTER S, LATIN SMALL LETTER S, LATIN SMALL LETTER S #
+
+FB06 ; 0073 0074 ; MA # ( st → st ) LATIN SMALL LIGATURE ST → LATIN SMALL LETTER S, LATIN SMALL LETTER T #
+
+222B ; 0283 ; MA #* ( ∫ → ʃ ) INTEGRAL → LATIN SMALL LETTER ESH #
+AB4D ; 0283 ; MA # ( ꭍ → ʃ ) LATIN SMALL LETTER BASELINE ESH → LATIN SMALL LETTER ESH #
+
+2211 ; 01A9 ; MA #* ( ∑ → Ʃ ) N-ARY SUMMATION → LATIN CAPITAL LETTER ESH #
+2140 ; 01A9 ; MA #* ( ⅀ → Ʃ ) DOUBLE-STRUCK N-ARY SUMMATION → LATIN CAPITAL LETTER ESH # →∑→
+03A3 ; 01A9 ; MA # ( Σ → Ʃ ) GREEK CAPITAL LETTER SIGMA → LATIN CAPITAL LETTER ESH #
+1D6BA ; 01A9 ; MA # ( 𝚺 → Ʃ ) MATHEMATICAL BOLD CAPITAL SIGMA → LATIN CAPITAL LETTER ESH # →Σ→
+1D6F4 ; 01A9 ; MA # ( 𝛴 → Ʃ ) MATHEMATICAL ITALIC CAPITAL SIGMA → LATIN CAPITAL LETTER ESH # →Σ→
+1D72E ; 01A9 ; MA # ( 𝜮 → Ʃ ) MATHEMATICAL BOLD ITALIC CAPITAL SIGMA → LATIN CAPITAL LETTER ESH # →Σ→
+1D768 ; 01A9 ; MA # ( 𝝨 → Ʃ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA → LATIN CAPITAL LETTER ESH # →Σ→
+1D7A2 ; 01A9 ; MA # ( 𝞢 → Ʃ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA → LATIN CAPITAL LETTER ESH # →Σ→
+2D49 ; 01A9 ; MA # ( ⵉ → Ʃ ) TIFINAGH LETTER YI → LATIN CAPITAL LETTER ESH #
+
+222C ; 0283 0283 ; MA #* ( ∬ → ʃʃ ) DOUBLE INTEGRAL → LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH # →∫∫→
+
+222D ; 0283 0283 0283 ; MA #* ( ∭ → ʃʃʃ ) TRIPLE INTEGRAL → LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH # →∫∫∫→
+
+2A0C ; 0283 0283 0283 0283 ; MA #* ( ⨌ → ʃʃʃʃ ) QUADRUPLE INTEGRAL OPERATOR → LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH, LATIN SMALL LETTER ESH # →∫∫∫∫→
+
+1D42D ; 0074 ; MA # ( 𝐭 → t ) MATHEMATICAL BOLD SMALL T → LATIN SMALL LETTER T #
+1D461 ; 0074 ; MA # ( 𝑡 → t ) MATHEMATICAL ITALIC SMALL T → LATIN SMALL LETTER T #
+1D495 ; 0074 ; MA # ( 𝒕 → t ) MATHEMATICAL BOLD ITALIC SMALL T → LATIN SMALL LETTER T #
+1D4C9 ; 0074 ; MA # ( 𝓉 → t ) MATHEMATICAL SCRIPT SMALL T → LATIN SMALL LETTER T #
+1D4FD ; 0074 ; MA # ( 𝓽 → t ) MATHEMATICAL BOLD SCRIPT SMALL T → LATIN SMALL LETTER T #
+1D531 ; 0074 ; MA # ( 𝔱 → t ) MATHEMATICAL FRAKTUR SMALL T → LATIN SMALL LETTER T #
+1D565 ; 0074 ; MA # ( 𝕥 → t ) MATHEMATICAL DOUBLE-STRUCK SMALL T → LATIN SMALL LETTER T #
+1D599 ; 0074 ; MA # ( 𝖙 → t ) MATHEMATICAL BOLD FRAKTUR SMALL T → LATIN SMALL LETTER T #
+1D5CD ; 0074 ; MA # ( 𝗍 → t ) MATHEMATICAL SANS-SERIF SMALL T → LATIN SMALL LETTER T #
+1D601 ; 0074 ; MA # ( 𝘁 → t ) MATHEMATICAL SANS-SERIF BOLD SMALL T → LATIN SMALL LETTER T #
+1D635 ; 0074 ; MA # ( 𝘵 → t ) MATHEMATICAL SANS-SERIF ITALIC SMALL T → LATIN SMALL LETTER T #
+1D669 ; 0074 ; MA # ( 𝙩 → t ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T → LATIN SMALL LETTER T #
+1D69D ; 0074 ; MA # ( 𝚝 → t ) MATHEMATICAL MONOSPACE SMALL T → LATIN SMALL LETTER T #
+
+22A4 ; 0054 ; MA #* ( ⊤ → T ) DOWN TACK → LATIN CAPITAL LETTER T #
+27D9 ; 0054 ; MA #* ( ⟙ → T ) LARGE DOWN TACK → LATIN CAPITAL LETTER T #
+1F768 ; 0054 ; MA #* ( 🝨 → T ) ALCHEMICAL SYMBOL FOR CRUCIBLE-4 → LATIN CAPITAL LETTER T #
+FF34 ; 0054 ; MA # ( T → T ) FULLWIDTH LATIN CAPITAL LETTER T → LATIN CAPITAL LETTER T # →Т→
+1D413 ; 0054 ; MA # ( 𝐓 → T ) MATHEMATICAL BOLD CAPITAL T → LATIN CAPITAL LETTER T #
+1D447 ; 0054 ; MA # ( 𝑇 → T ) MATHEMATICAL ITALIC CAPITAL T → LATIN CAPITAL LETTER T #
+1D47B ; 0054 ; MA # ( 𝑻 → T ) MATHEMATICAL BOLD ITALIC CAPITAL T → LATIN CAPITAL LETTER T #
+1D4AF ; 0054 ; MA # ( 𝒯 → T ) MATHEMATICAL SCRIPT CAPITAL T → LATIN CAPITAL LETTER T #
+1D4E3 ; 0054 ; MA # ( 𝓣 → T ) MATHEMATICAL BOLD SCRIPT CAPITAL T → LATIN CAPITAL LETTER T #
+1D517 ; 0054 ; MA # ( 𝔗 → T ) MATHEMATICAL FRAKTUR CAPITAL T → LATIN CAPITAL LETTER T #
+1D54B ; 0054 ; MA # ( 𝕋 → T ) MATHEMATICAL DOUBLE-STRUCK CAPITAL T → LATIN CAPITAL LETTER T #
+1D57F ; 0054 ; MA # ( 𝕿 → T ) MATHEMATICAL BOLD FRAKTUR CAPITAL T → LATIN CAPITAL LETTER T #
+1D5B3 ; 0054 ; MA # ( 𝖳 → T ) MATHEMATICAL SANS-SERIF CAPITAL T → LATIN CAPITAL LETTER T #
+1D5E7 ; 0054 ; MA # ( 𝗧 → T ) MATHEMATICAL SANS-SERIF BOLD CAPITAL T → LATIN CAPITAL LETTER T #
+1D61B ; 0054 ; MA # ( 𝘛 → T ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL T → LATIN CAPITAL LETTER T #
+1D64F ; 0054 ; MA # ( 𝙏 → T ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T → LATIN CAPITAL LETTER T #
+1D683 ; 0054 ; MA # ( 𝚃 → T ) MATHEMATICAL MONOSPACE CAPITAL T → LATIN CAPITAL LETTER T #
+03A4 ; 0054 ; MA # ( Τ → T ) GREEK CAPITAL LETTER TAU → LATIN CAPITAL LETTER T #
+1D6BB ; 0054 ; MA # ( 𝚻 → T ) MATHEMATICAL BOLD CAPITAL TAU → LATIN CAPITAL LETTER T # →Τ→
+1D6F5 ; 0054 ; MA # ( 𝛵 → T ) MATHEMATICAL ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T # →Τ→
+1D72F ; 0054 ; MA # ( 𝜯 → T ) MATHEMATICAL BOLD ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T # →Τ→
+1D769 ; 0054 ; MA # ( 𝝩 → T ) MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU → LATIN CAPITAL LETTER T # →Τ→
+1D7A3 ; 0054 ; MA # ( 𝞣 → T ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU → LATIN CAPITAL LETTER T # →Τ→
+2CA6 ; 0054 ; MA # ( Ⲧ → T ) COPTIC CAPITAL LETTER TAU → LATIN CAPITAL LETTER T #
+0422 ; 0054 ; MA # ( Т → T ) CYRILLIC CAPITAL LETTER TE → LATIN CAPITAL LETTER T #
+13A2 ; 0054 ; MA # ( Ꭲ → T ) CHEROKEE LETTER I → LATIN CAPITAL LETTER T #
+A4D4 ; 0054 ; MA # ( ꓔ → T ) LISU LETTER TA → LATIN CAPITAL LETTER T #
+16F0A ; 0054 ; MA # ( 𖼊 → T ) MIAO LETTER TA → LATIN CAPITAL LETTER T #
+118BC ; 0054 ; MA # ( 𑢼 → T ) WARANG CITI CAPITAL LETTER HAR → LATIN CAPITAL LETTER T #
+10297 ; 0054 ; MA # ( 𐊗 → T ) LYCIAN LETTER T → LATIN CAPITAL LETTER T #
+102B1 ; 0054 ; MA # ( 𐊱 → T ) CARIAN LETTER C-18 → LATIN CAPITAL LETTER T #
+10315 ; 0054 ; MA # ( 𐌕 → T ) OLD ITALIC LETTER TE → LATIN CAPITAL LETTER T #
+
+01AD ; 0074 0314 ; MA # ( ƭ → t̔ ) LATIN SMALL LETTER T WITH HOOK → LATIN SMALL LETTER T, COMBINING REVERSED COMMA ABOVE #
+
+2361 ; 0054 0308 ; MA #* ( ⍡ → T̈ ) APL FUNCTIONAL SYMBOL UP TACK DIAERESIS → LATIN CAPITAL LETTER T, COMBINING DIAERESIS # →⊤̈→
+
+023E ; 0054 0338 ; MA # ( Ⱦ → T̸ ) LATIN CAPITAL LETTER T WITH DIAGONAL STROKE → LATIN CAPITAL LETTER T, COMBINING LONG SOLIDUS OVERLAY #
+
+021A ; 0162 ; MA # ( Ț → Ţ ) LATIN CAPITAL LETTER T WITH COMMA BELOW → LATIN CAPITAL LETTER T WITH CEDILLA #
+
+01AE ; 0054 0328 ; MA # ( Ʈ → T̨ ) LATIN CAPITAL LETTER T WITH RETROFLEX HOOK → LATIN CAPITAL LETTER T, COMBINING OGONEK #
+
+04AC ; 0054 0329 ; MA # ( Ҭ → T̩ ) CYRILLIC CAPITAL LETTER TE WITH DESCENDER → LATIN CAPITAL LETTER T, COMBINING VERTICAL LINE BELOW # →Т̩→
+
+20AE ; 0054 20EB ; MA #* ( ₮ → T⃫ ) TUGRIK SIGN → LATIN CAPITAL LETTER T, COMBINING LONG DOUBLE SOLIDUS OVERLAY # →Т⃫→
+
+0167 ; 0074 0335 ; MA # ( ŧ → t̵ ) LATIN SMALL LETTER T WITH STROKE → LATIN SMALL LETTER T, COMBINING SHORT STROKE OVERLAY #
+
+0166 ; 0054 0335 ; MA # ( Ŧ → T̵ ) LATIN CAPITAL LETTER T WITH STROKE → LATIN CAPITAL LETTER T, COMBINING SHORT STROKE OVERLAY #
+
+1D75 ; 0074 0334 ; MA # ( ᵵ → t̴ ) LATIN SMALL LETTER T WITH MIDDLE TILDE → LATIN SMALL LETTER T, COMBINING TILDE OVERLAY #
+
+10A0 ; A786 ; MA # ( Ⴀ → Ꞇ ) GEORGIAN CAPITAL LETTER AN → LATIN CAPITAL LETTER INSULAR T #
+
+A728 ; 0054 0033 ; MA # ( Ꜩ → T3 ) LATIN CAPITAL LETTER TZ → LATIN CAPITAL LETTER T, DIGIT THREE # →TƷ→
+
+02A8 ; 0074 0255 ; MA # ( ʨ → tɕ ) LATIN SMALL LETTER TC DIGRAPH WITH CURL → LATIN SMALL LETTER T, LATIN SMALL LETTER C WITH CURL #
+
+2121 ; 0054 0045 004C ; MA #* ( ℡ → TEL ) TELEPHONE SIGN → LATIN CAPITAL LETTER T, LATIN CAPITAL LETTER E, LATIN CAPITAL LETTER L #
+
+A777 ; 0074 0066 ; MA # ( ꝷ → tf ) LATIN SMALL LETTER TUM → LATIN SMALL LETTER T, LATIN SMALL LETTER F #
+
+02A6 ; 0074 0073 ; MA # ( ʦ → ts ) LATIN SMALL LETTER TS DIGRAPH → LATIN SMALL LETTER T, LATIN SMALL LETTER S #
+
+02A7 ; 0074 0283 ; MA # ( ʧ → tʃ ) LATIN SMALL LETTER TESH DIGRAPH → LATIN SMALL LETTER T, LATIN SMALL LETTER ESH #
+
+A729 ; 0074 021D ; MA # ( ꜩ → tȝ ) LATIN SMALL LETTER TZ → LATIN SMALL LETTER T, LATIN SMALL LETTER YOGH #
+
+03C4 ; 1D1B ; MA # ( τ → ᴛ ) GREEK SMALL LETTER TAU → LATIN LETTER SMALL CAPITAL T #
+1D6D5 ; 1D1B ; MA # ( 𝛕 → ᴛ ) MATHEMATICAL BOLD SMALL TAU → LATIN LETTER SMALL CAPITAL T #
+1D70F ; 1D1B ; MA # ( 𝜏 → ᴛ ) MATHEMATICAL ITALIC SMALL TAU → LATIN LETTER SMALL CAPITAL T #
+1D749 ; 1D1B ; MA # ( 𝝉 → ᴛ ) MATHEMATICAL BOLD ITALIC SMALL TAU → LATIN LETTER SMALL CAPITAL T #
+1D783 ; 1D1B ; MA # ( 𝞃 → ᴛ ) MATHEMATICAL SANS-SERIF BOLD SMALL TAU → LATIN LETTER SMALL CAPITAL T #
+1D7BD ; 1D1B ; MA # ( 𝞽 → ᴛ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU → LATIN LETTER SMALL CAPITAL T #
+0442 ; 1D1B ; MA # ( т → ᴛ ) CYRILLIC SMALL LETTER TE → LATIN LETTER SMALL CAPITAL T #
+AB72 ; 1D1B ; MA # ( ꭲ → ᴛ ) CHEROKEE SMALL LETTER I → LATIN LETTER SMALL CAPITAL T #
+
+04AD ; 1D1B 0329 ; MA # ( ҭ → ᴛ̩ ) CYRILLIC SMALL LETTER TE WITH DESCENDER → LATIN LETTER SMALL CAPITAL T, COMBINING VERTICAL LINE BELOW # →т̩→
+
+0163 ; 01AB ; MA # ( ţ → ƫ ) LATIN SMALL LETTER T WITH CEDILLA → LATIN SMALL LETTER T WITH PALATAL HOOK #
+021B ; 01AB ; MA # ( ț → ƫ ) LATIN SMALL LETTER T WITH COMMA BELOW → LATIN SMALL LETTER T WITH PALATAL HOOK # →ţ→
+13BF ; 01AB ; MA # ( Ꮏ → ƫ ) CHEROKEE LETTER HNA → LATIN SMALL LETTER T WITH PALATAL HOOK #
+
+1D42E ; 0075 ; MA # ( 𝐮 → u ) MATHEMATICAL BOLD SMALL U → LATIN SMALL LETTER U #
+1D462 ; 0075 ; MA # ( 𝑢 → u ) MATHEMATICAL ITALIC SMALL U → LATIN SMALL LETTER U #
+1D496 ; 0075 ; MA # ( 𝒖 → u ) MATHEMATICAL BOLD ITALIC SMALL U → LATIN SMALL LETTER U #
+1D4CA ; 0075 ; MA # ( 𝓊 → u ) MATHEMATICAL SCRIPT SMALL U → LATIN SMALL LETTER U #
+1D4FE ; 0075 ; MA # ( 𝓾 → u ) MATHEMATICAL BOLD SCRIPT SMALL U → LATIN SMALL LETTER U #
+1D532 ; 0075 ; MA # ( 𝔲 → u ) MATHEMATICAL FRAKTUR SMALL U → LATIN SMALL LETTER U #
+1D566 ; 0075 ; MA # ( 𝕦 → u ) MATHEMATICAL DOUBLE-STRUCK SMALL U → LATIN SMALL LETTER U #
+1D59A ; 0075 ; MA # ( 𝖚 → u ) MATHEMATICAL BOLD FRAKTUR SMALL U → LATIN SMALL LETTER U #
+1D5CE ; 0075 ; MA # ( 𝗎 → u ) MATHEMATICAL SANS-SERIF SMALL U → LATIN SMALL LETTER U #
+1D602 ; 0075 ; MA # ( 𝘂 → u ) MATHEMATICAL SANS-SERIF BOLD SMALL U → LATIN SMALL LETTER U #
+1D636 ; 0075 ; MA # ( 𝘶 → u ) MATHEMATICAL SANS-SERIF ITALIC SMALL U → LATIN SMALL LETTER U #
+1D66A ; 0075 ; MA # ( 𝙪 → u ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U → LATIN SMALL LETTER U #
+1D69E ; 0075 ; MA # ( 𝚞 → u ) MATHEMATICAL MONOSPACE SMALL U → LATIN SMALL LETTER U #
+A79F ; 0075 ; MA # ( ꞟ → u ) LATIN SMALL LETTER VOLAPUK UE → LATIN SMALL LETTER U #
+1D1C ; 0075 ; MA # ( ᴜ → u ) LATIN LETTER SMALL CAPITAL U → LATIN SMALL LETTER U #
+AB4E ; 0075 ; MA # ( ꭎ → u ) LATIN SMALL LETTER U WITH SHORT RIGHT LEG → LATIN SMALL LETTER U #
+AB52 ; 0075 ; MA # ( ꭒ → u ) LATIN SMALL LETTER U WITH LEFT HOOK → LATIN SMALL LETTER U #
+028B ; 0075 ; MA # ( ʋ → u ) LATIN SMALL LETTER V WITH HOOK → LATIN SMALL LETTER U #
+03C5 ; 0075 ; MA # ( υ → u ) GREEK SMALL LETTER UPSILON → LATIN SMALL LETTER U # →ʋ→
+1D6D6 ; 0075 ; MA # ( 𝛖 → u ) MATHEMATICAL BOLD SMALL UPSILON → LATIN SMALL LETTER U # →υ→→ʋ→
+1D710 ; 0075 ; MA # ( 𝜐 → u ) MATHEMATICAL ITALIC SMALL UPSILON → LATIN SMALL LETTER U # →υ→→ʋ→
+1D74A ; 0075 ; MA # ( 𝝊 → u ) MATHEMATICAL BOLD ITALIC SMALL UPSILON → LATIN SMALL LETTER U # →υ→→ʋ→
+1D784 ; 0075 ; MA # ( 𝞄 → u ) MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON → LATIN SMALL LETTER U # →υ→→ʋ→
+1D7BE ; 0075 ; MA # ( 𝞾 → u ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON → LATIN SMALL LETTER U # →υ→→ʋ→
+057D ; 0075 ; MA # ( ս → u ) ARMENIAN SMALL LETTER SEH → LATIN SMALL LETTER U #
+104F6 ; 0075 ; MA # ( 𐓶 → u ) OSAGE SMALL LETTER U → LATIN SMALL LETTER U # →ᴜ→
+118D8 ; 0075 ; MA # ( 𑣘 → u ) WARANG CITI SMALL LETTER PU → LATIN SMALL LETTER U # →υ→→ʋ→
+
+222A ; 0055 ; MA #* ( ∪ → U ) UNION → LATIN CAPITAL LETTER U # →ᑌ→
+22C3 ; 0055 ; MA #* ( ⋃ → U ) N-ARY UNION → LATIN CAPITAL LETTER U # →∪→→ᑌ→
+1D414 ; 0055 ; MA # ( 𝐔 → U ) MATHEMATICAL BOLD CAPITAL U → LATIN CAPITAL LETTER U #
+1D448 ; 0055 ; MA # ( 𝑈 → U ) MATHEMATICAL ITALIC CAPITAL U → LATIN CAPITAL LETTER U #
+1D47C ; 0055 ; MA # ( 𝑼 → U ) MATHEMATICAL BOLD ITALIC CAPITAL U → LATIN CAPITAL LETTER U #
+1D4B0 ; 0055 ; MA # ( 𝒰 → U ) MATHEMATICAL SCRIPT CAPITAL U → LATIN CAPITAL LETTER U #
+1D4E4 ; 0055 ; MA # ( 𝓤 → U ) MATHEMATICAL BOLD SCRIPT CAPITAL U → LATIN CAPITAL LETTER U #
+1D518 ; 0055 ; MA # ( 𝔘 → U ) MATHEMATICAL FRAKTUR CAPITAL U → LATIN CAPITAL LETTER U #
+1D54C ; 0055 ; MA # ( 𝕌 → U ) MATHEMATICAL DOUBLE-STRUCK CAPITAL U → LATIN CAPITAL LETTER U #
+1D580 ; 0055 ; MA # ( 𝖀 → U ) MATHEMATICAL BOLD FRAKTUR CAPITAL U → LATIN CAPITAL LETTER U #
+1D5B4 ; 0055 ; MA # ( 𝖴 → U ) MATHEMATICAL SANS-SERIF CAPITAL U → LATIN CAPITAL LETTER U #
+1D5E8 ; 0055 ; MA # ( 𝗨 → U ) MATHEMATICAL SANS-SERIF BOLD CAPITAL U → LATIN CAPITAL LETTER U #
+1D61C ; 0055 ; MA # ( 𝘜 → U ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL U → LATIN CAPITAL LETTER U #
+1D650 ; 0055 ; MA # ( 𝙐 → U ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U → LATIN CAPITAL LETTER U #
+1D684 ; 0055 ; MA # ( 𝚄 → U ) MATHEMATICAL MONOSPACE CAPITAL U → LATIN CAPITAL LETTER U #
+054D ; 0055 ; MA # ( Ս → U ) ARMENIAN CAPITAL LETTER SEH → LATIN CAPITAL LETTER U #
+1200 ; 0055 ; MA # ( ሀ → U ) ETHIOPIC SYLLABLE HA → LATIN CAPITAL LETTER U # →Ս→
+104CE ; 0055 ; MA # ( 𐓎 → U ) OSAGE CAPITAL LETTER U → LATIN CAPITAL LETTER U #
+144C ; 0055 ; MA # ( ᑌ → U ) CANADIAN SYLLABICS TE → LATIN CAPITAL LETTER U #
+A4F4 ; 0055 ; MA # ( ꓴ → U ) LISU LETTER U → LATIN CAPITAL LETTER U #
+16F42 ; 0055 ; MA # ( 𖽂 → U ) MIAO LETTER WA → LATIN CAPITAL LETTER U #
+118B8 ; 0055 ; MA # ( 𑢸 → U ) WARANG CITI CAPITAL LETTER PU → LATIN CAPITAL LETTER U #
+
+01D4 ; 016D ; MA # ( ǔ → ŭ ) LATIN SMALL LETTER U WITH CARON → LATIN SMALL LETTER U WITH BREVE #
+
+01D3 ; 016C ; MA # ( Ǔ → Ŭ ) LATIN CAPITAL LETTER U WITH CARON → LATIN CAPITAL LETTER U WITH BREVE #
+
+1D7E ; 0075 0335 ; MA # ( ᵾ → u̵ ) LATIN SMALL CAPITAL LETTER U WITH STROKE → LATIN SMALL LETTER U, COMBINING SHORT STROKE OVERLAY # →ᴜ̵→
+AB9C ; 0075 0335 ; MA # ( ꮜ → u̵ ) CHEROKEE SMALL LETTER SA → LATIN SMALL LETTER U, COMBINING SHORT STROKE OVERLAY # →ᴜ̵→
+
+0244 ; 0055 0335 ; MA # ( Ʉ → U̵ ) LATIN CAPITAL LETTER U BAR → LATIN CAPITAL LETTER U, COMBINING SHORT STROKE OVERLAY # →U̶→
+13CC ; 0055 0335 ; MA # ( Ꮜ → U̵ ) CHEROKEE LETTER SA → LATIN CAPITAL LETTER U, COMBINING SHORT STROKE OVERLAY # →Ʉ→→U̶→
+
+1458 ; 0055 00B7 ; MA # ( ᑘ → U· ) CANADIAN SYLLABICS WEST-CREE TWE → LATIN CAPITAL LETTER U, MIDDLE DOT # →ᑌᐧ→→ᑌ·→
+
+1467 ; 0055 0027 ; MA # ( ᑧ → U' ) CANADIAN SYLLABICS TTE → LATIN CAPITAL LETTER U, APOSTROPHE # →ᑌᑊ→→ᑌ'→
+
+1D6B ; 0075 0065 ; MA # ( ᵫ → ue ) LATIN SMALL LETTER UE → LATIN SMALL LETTER U, LATIN SMALL LETTER E #
+
+AB63 ; 0075 006F ; MA # ( ꭣ → uo ) LATIN SMALL LETTER UO → LATIN SMALL LETTER U, LATIN SMALL LETTER O #
+
+1E43 ; AB51 ; MA # ( ṃ → ꭑ ) LATIN SMALL LETTER M WITH DOT BELOW → LATIN SMALL LETTER TURNED UI #
+
+057A ; 0270 ; MA # ( պ → ɰ ) ARMENIAN SMALL LETTER PEH → LATIN SMALL LETTER TURNED M WITH LONG LEG #
+1223 ; 0270 ; MA # ( ሣ → ɰ ) ETHIOPIC SYLLABLE SZAA → LATIN SMALL LETTER TURNED M WITH LONG LEG # →պ→
+
+2127 ; 01B1 ; MA #* ( ℧ → Ʊ ) INVERTED OHM SIGN → LATIN CAPITAL LETTER UPSILON #
+162E ; 01B1 ; MA # ( ᘮ → Ʊ ) CANADIAN SYLLABICS CARRIER LHU → LATIN CAPITAL LETTER UPSILON # →℧→
+1634 ; 01B1 ; MA # ( ᘴ → Ʊ ) CANADIAN SYLLABICS CARRIER TLHU → LATIN CAPITAL LETTER UPSILON # →ᘮ→→℧→
+
+1D7F ; 028A 0335 ; MA # ( ᵿ → ʊ̵ ) LATIN SMALL LETTER UPSILON WITH STROKE → LATIN SMALL LETTER UPSILON, COMBINING SHORT STROKE OVERLAY #
+
+2228 ; 0076 ; MA #* ( ∨ → v ) LOGICAL OR → LATIN SMALL LETTER V #
+22C1 ; 0076 ; MA #* ( ⋁ → v ) N-ARY LOGICAL OR → LATIN SMALL LETTER V # →∨→
+FF56 ; 0076 ; MA # ( v → v ) FULLWIDTH LATIN SMALL LETTER V → LATIN SMALL LETTER V # →ν→
+2174 ; 0076 ; MA # ( ⅴ → v ) SMALL ROMAN NUMERAL FIVE → LATIN SMALL LETTER V #
+1D42F ; 0076 ; MA # ( 𝐯 → v ) MATHEMATICAL BOLD SMALL V → LATIN SMALL LETTER V #
+1D463 ; 0076 ; MA # ( 𝑣 → v ) MATHEMATICAL ITALIC SMALL V → LATIN SMALL LETTER V #
+1D497 ; 0076 ; MA # ( 𝒗 → v ) MATHEMATICAL BOLD ITALIC SMALL V → LATIN SMALL LETTER V #
+1D4CB ; 0076 ; MA # ( 𝓋 → v ) MATHEMATICAL SCRIPT SMALL V → LATIN SMALL LETTER V #
+1D4FF ; 0076 ; MA # ( 𝓿 → v ) MATHEMATICAL BOLD SCRIPT SMALL V → LATIN SMALL LETTER V #
+1D533 ; 0076 ; MA # ( 𝔳 → v ) MATHEMATICAL FRAKTUR SMALL V → LATIN SMALL LETTER V #
+1D567 ; 0076 ; MA # ( 𝕧 → v ) MATHEMATICAL DOUBLE-STRUCK SMALL V → LATIN SMALL LETTER V #
+1D59B ; 0076 ; MA # ( 𝖛 → v ) MATHEMATICAL BOLD FRAKTUR SMALL V → LATIN SMALL LETTER V #
+1D5CF ; 0076 ; MA # ( 𝗏 → v ) MATHEMATICAL SANS-SERIF SMALL V → LATIN SMALL LETTER V #
+1D603 ; 0076 ; MA # ( 𝘃 → v ) MATHEMATICAL SANS-SERIF BOLD SMALL V → LATIN SMALL LETTER V #
+1D637 ; 0076 ; MA # ( 𝘷 → v ) MATHEMATICAL SANS-SERIF ITALIC SMALL V → LATIN SMALL LETTER V #
+1D66B ; 0076 ; MA # ( 𝙫 → v ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V → LATIN SMALL LETTER V #
+1D69F ; 0076 ; MA # ( 𝚟 → v ) MATHEMATICAL MONOSPACE SMALL V → LATIN SMALL LETTER V #
+1D20 ; 0076 ; MA # ( ᴠ → v ) LATIN LETTER SMALL CAPITAL V → LATIN SMALL LETTER V #
+03BD ; 0076 ; MA # ( ν → v ) GREEK SMALL LETTER NU → LATIN SMALL LETTER V #
+1D6CE ; 0076 ; MA # ( 𝛎 → v ) MATHEMATICAL BOLD SMALL NU → LATIN SMALL LETTER V # →ν→
+1D708 ; 0076 ; MA # ( 𝜈 → v ) MATHEMATICAL ITALIC SMALL NU → LATIN SMALL LETTER V # →ν→
+1D742 ; 0076 ; MA # ( 𝝂 → v ) MATHEMATICAL BOLD ITALIC SMALL NU → LATIN SMALL LETTER V # →ν→
+1D77C ; 0076 ; MA # ( 𝝼 → v ) MATHEMATICAL SANS-SERIF BOLD SMALL NU → LATIN SMALL LETTER V # →ν→
+1D7B6 ; 0076 ; MA # ( 𝞶 → v ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU → LATIN SMALL LETTER V # →ν→
+0475 ; 0076 ; MA # ( ѵ → v ) CYRILLIC SMALL LETTER IZHITSA → LATIN SMALL LETTER V #
+05D8 ; 0076 ; MA # ( ‎ט‎ → v ) HEBREW LETTER TET → LATIN SMALL LETTER V #
+11706 ; 0076 ; MA # ( 𑜆 → v ) AHOM LETTER PA → LATIN SMALL LETTER V #
+ABA9 ; 0076 ; MA # ( ꮩ → v ) CHEROKEE SMALL LETTER DO → LATIN SMALL LETTER V # →ᴠ→
+118C0 ; 0076 ; MA # ( 𑣀 → v ) WARANG CITI SMALL LETTER NGAA → LATIN SMALL LETTER V #
+
+1D20D ; 0056 ; MA #* ( 𝈍 → V ) GREEK VOCAL NOTATION SYMBOL-14 → LATIN CAPITAL LETTER V #
+0667 ; 0056 ; MA # ( ‎٧‎ → V ) ARABIC-INDIC DIGIT SEVEN → LATIN CAPITAL LETTER V #
+06F7 ; 0056 ; MA # ( ۷ → V ) EXTENDED ARABIC-INDIC DIGIT SEVEN → LATIN CAPITAL LETTER V # →‎٧‎→
+2164 ; 0056 ; MA # ( Ⅴ → V ) ROMAN NUMERAL FIVE → LATIN CAPITAL LETTER V #
+1D415 ; 0056 ; MA # ( 𝐕 → V ) MATHEMATICAL BOLD CAPITAL V → LATIN CAPITAL LETTER V #
+1D449 ; 0056 ; MA # ( 𝑉 → V ) MATHEMATICAL ITALIC CAPITAL V → LATIN CAPITAL LETTER V #
+1D47D ; 0056 ; MA # ( 𝑽 → V ) MATHEMATICAL BOLD ITALIC CAPITAL V → LATIN CAPITAL LETTER V #
+1D4B1 ; 0056 ; MA # ( 𝒱 → V ) MATHEMATICAL SCRIPT CAPITAL V → LATIN CAPITAL LETTER V #
+1D4E5 ; 0056 ; MA # ( 𝓥 → V ) MATHEMATICAL BOLD SCRIPT CAPITAL V → LATIN CAPITAL LETTER V #
+1D519 ; 0056 ; MA # ( 𝔙 → V ) MATHEMATICAL FRAKTUR CAPITAL V → LATIN CAPITAL LETTER V #
+1D54D ; 0056 ; MA # ( 𝕍 → V ) MATHEMATICAL DOUBLE-STRUCK CAPITAL V → LATIN CAPITAL LETTER V #
+1D581 ; 0056 ; MA # ( 𝖁 → V ) MATHEMATICAL BOLD FRAKTUR CAPITAL V → LATIN CAPITAL LETTER V #
+1D5B5 ; 0056 ; MA # ( 𝖵 → V ) MATHEMATICAL SANS-SERIF CAPITAL V → LATIN CAPITAL LETTER V #
+1D5E9 ; 0056 ; MA # ( 𝗩 → V ) MATHEMATICAL SANS-SERIF BOLD CAPITAL V → LATIN CAPITAL LETTER V #
+1D61D ; 0056 ; MA # ( 𝘝 → V ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL V → LATIN CAPITAL LETTER V #
+1D651 ; 0056 ; MA # ( 𝙑 → V ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V → LATIN CAPITAL LETTER V #
+1D685 ; 0056 ; MA # ( 𝚅 → V ) MATHEMATICAL MONOSPACE CAPITAL V → LATIN CAPITAL LETTER V #
+0474 ; 0056 ; MA # ( Ѵ → V ) CYRILLIC CAPITAL LETTER IZHITSA → LATIN CAPITAL LETTER V #
+2D38 ; 0056 ; MA # ( ⴸ → V ) TIFINAGH LETTER YADH → LATIN CAPITAL LETTER V #
+13D9 ; 0056 ; MA # ( Ꮩ → V ) CHEROKEE LETTER DO → LATIN CAPITAL LETTER V #
+142F ; 0056 ; MA # ( ᐯ → V ) CANADIAN SYLLABICS PE → LATIN CAPITAL LETTER V #
+A6DF ; 0056 ; MA # ( ꛟ → V ) BAMUM LETTER KO → LATIN CAPITAL LETTER V #
+A4E6 ; 0056 ; MA # ( ꓦ → V ) LISU LETTER HA → LATIN CAPITAL LETTER V #
+16F08 ; 0056 ; MA # ( 𖼈 → V ) MIAO LETTER VA → LATIN CAPITAL LETTER V #
+118A0 ; 0056 ; MA # ( 𑢠 → V ) WARANG CITI CAPITAL LETTER NGAA → LATIN CAPITAL LETTER V #
+1051D ; 0056 ; MA # ( 𐔝 → V ) ELBASAN LETTER TE → LATIN CAPITAL LETTER V #
+
+10197 ; 0056 0335 ; MA #* ( 𐆗 → V̵ ) ROMAN QUINARIUS SIGN → LATIN CAPITAL LETTER V, COMBINING SHORT STROKE OVERLAY # →V̶→
+
+143B ; 0056 00B7 ; MA # ( ᐻ → V· ) CANADIAN SYLLABICS WEST-CREE PWE → LATIN CAPITAL LETTER V, MIDDLE DOT # →ᐯᐧ→
+
+1F76C ; 0056 0042 ; MA #* ( 🝬 → VB ) ALCHEMICAL SYMBOL FOR BATH OF VAPOURS → LATIN CAPITAL LETTER V, LATIN CAPITAL LETTER B #
+
+2175 ; 0076 0069 ; MA # ( ⅵ → vi ) SMALL ROMAN NUMERAL SIX → LATIN SMALL LETTER V, LATIN SMALL LETTER I #
+
+2176 ; 0076 0069 0069 ; MA # ( ⅶ → vii ) SMALL ROMAN NUMERAL SEVEN → LATIN SMALL LETTER V, LATIN SMALL LETTER I, LATIN SMALL LETTER I #
+
+2177 ; 0076 0069 0069 0069 ; MA # ( ⅷ → viii ) SMALL ROMAN NUMERAL EIGHT → LATIN SMALL LETTER V, LATIN SMALL LETTER I, LATIN SMALL LETTER I, LATIN SMALL LETTER I #
+
+2165 ; 0056 006C ; MA # ( Ⅵ → Vl ) ROMAN NUMERAL SIX → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L # →VI→
+
+2166 ; 0056 006C 006C ; MA # ( Ⅶ → Vll ) ROMAN NUMERAL SEVEN → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L, LATIN SMALL LETTER L # →VII→
+
+2167 ; 0056 006C 006C 006C ; MA # ( Ⅷ → Vlll ) ROMAN NUMERAL EIGHT → LATIN CAPITAL LETTER V, LATIN SMALL LETTER L, LATIN SMALL LETTER L, LATIN SMALL LETTER L # →VIII→
+
+1F708 ; 0056 1DE4 ; MA #* ( 🜈 → Vᷤ ) ALCHEMICAL SYMBOL FOR AQUA VITAE → LATIN CAPITAL LETTER V, COMBINING LATIN SMALL LETTER S #
+
+1D27 ; 028C ; MA # ( ᴧ → ʌ ) GREEK LETTER SMALL CAPITAL LAMDA → LATIN SMALL LETTER TURNED V #
+104D8 ; 028C ; MA # ( 𐓘 → ʌ ) OSAGE SMALL LETTER A → LATIN SMALL LETTER TURNED V #
+
+0668 ; 0245 ; MA # ( ‎٨‎ → Ʌ ) ARABIC-INDIC DIGIT EIGHT → LATIN CAPITAL LETTER TURNED V # →Λ→
+06F8 ; 0245 ; MA # ( ۸ → Ʌ ) EXTENDED ARABIC-INDIC DIGIT EIGHT → LATIN CAPITAL LETTER TURNED V # →‎٨‎→→Λ→
+039B ; 0245 ; MA # ( Λ → Ʌ ) GREEK CAPITAL LETTER LAMDA → LATIN CAPITAL LETTER TURNED V #
+1D6B2 ; 0245 ; MA # ( 𝚲 → Ʌ ) MATHEMATICAL BOLD CAPITAL LAMDA → LATIN CAPITAL LETTER TURNED V # →Λ→
+1D6EC ; 0245 ; MA # ( 𝛬 → Ʌ ) MATHEMATICAL ITALIC CAPITAL LAMDA → LATIN CAPITAL LETTER TURNED V # →Λ→
+1D726 ; 0245 ; MA # ( 𝜦 → Ʌ ) MATHEMATICAL BOLD ITALIC CAPITAL LAMDA → LATIN CAPITAL LETTER TURNED V # →Λ→
+1D760 ; 0245 ; MA # ( 𝝠 → Ʌ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA → LATIN CAPITAL LETTER TURNED V # →Λ→
+1D79A ; 0245 ; MA # ( 𝞚 → Ʌ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA → LATIN CAPITAL LETTER TURNED V # →Λ→
+041B ; 0245 ; MA # ( Л → Ʌ ) CYRILLIC CAPITAL LETTER EL → LATIN CAPITAL LETTER TURNED V # →Λ→
+2D37 ; 0245 ; MA # ( ⴷ → Ʌ ) TIFINAGH LETTER YAD → LATIN CAPITAL LETTER TURNED V #
+104B0 ; 0245 ; MA # ( 𐒰 → Ʌ ) OSAGE CAPITAL LETTER A → LATIN CAPITAL LETTER TURNED V #
+1431 ; 0245 ; MA # ( ᐱ → Ʌ ) CANADIAN SYLLABICS PI → LATIN CAPITAL LETTER TURNED V #
+A6CE ; 0245 ; MA # ( ꛎ → Ʌ ) BAMUM LETTER MI → LATIN CAPITAL LETTER TURNED V # →Λ→
+A4E5 ; 0245 ; MA # ( ꓥ → Ʌ ) LISU LETTER NGA → LATIN CAPITAL LETTER TURNED V #
+16F3D ; 0245 ; MA # ( 𖼽 → Ʌ ) MIAO LETTER ZZA → LATIN CAPITAL LETTER TURNED V #
+1028D ; 0245 ; MA # ( 𐊍 → Ʌ ) LYCIAN LETTER L → LATIN CAPITAL LETTER TURNED V # →Λ→
+
+04C5 ; 0245 0326 ; MA # ( Ӆ → Ʌ̦ ) CYRILLIC CAPITAL LETTER EL WITH TAIL → LATIN CAPITAL LETTER TURNED V, COMBINING COMMA BELOW # →Л̡→
+
+143D ; 0245 00B7 ; MA # ( ᐽ → Ʌ· ) CANADIAN SYLLABICS WEST-CREE PWI → LATIN CAPITAL LETTER TURNED V, MIDDLE DOT # →ᐱᐧ→→ᐱ·→
+
+026F ; 0077 ; MA # ( ɯ → w ) LATIN SMALL LETTER TURNED M → LATIN SMALL LETTER W #
+1D430 ; 0077 ; MA # ( 𝐰 → w ) MATHEMATICAL BOLD SMALL W → LATIN SMALL LETTER W #
+1D464 ; 0077 ; MA # ( 𝑤 → w ) MATHEMATICAL ITALIC SMALL W → LATIN SMALL LETTER W #
+1D498 ; 0077 ; MA # ( 𝒘 → w ) MATHEMATICAL BOLD ITALIC SMALL W → LATIN SMALL LETTER W #
+1D4CC ; 0077 ; MA # ( 𝓌 → w ) MATHEMATICAL SCRIPT SMALL W → LATIN SMALL LETTER W #
+1D500 ; 0077 ; MA # ( 𝔀 → w ) MATHEMATICAL BOLD SCRIPT SMALL W → LATIN SMALL LETTER W #
+1D534 ; 0077 ; MA # ( 𝔴 → w ) MATHEMATICAL FRAKTUR SMALL W → LATIN SMALL LETTER W #
+1D568 ; 0077 ; MA # ( 𝕨 → w ) MATHEMATICAL DOUBLE-STRUCK SMALL W → LATIN SMALL LETTER W #
+1D59C ; 0077 ; MA # ( 𝖜 → w ) MATHEMATICAL BOLD FRAKTUR SMALL W → LATIN SMALL LETTER W #
+1D5D0 ; 0077 ; MA # ( 𝗐 → w ) MATHEMATICAL SANS-SERIF SMALL W → LATIN SMALL LETTER W #
+1D604 ; 0077 ; MA # ( 𝘄 → w ) MATHEMATICAL SANS-SERIF BOLD SMALL W → LATIN SMALL LETTER W #
+1D638 ; 0077 ; MA # ( 𝘸 → w ) MATHEMATICAL SANS-SERIF ITALIC SMALL W → LATIN SMALL LETTER W #
+1D66C ; 0077 ; MA # ( 𝙬 → w ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W → LATIN SMALL LETTER W #
+1D6A0 ; 0077 ; MA # ( 𝚠 → w ) MATHEMATICAL MONOSPACE SMALL W → LATIN SMALL LETTER W #
+1D21 ; 0077 ; MA # ( ᴡ → w ) LATIN LETTER SMALL CAPITAL W → LATIN SMALL LETTER W #
+0461 ; 0077 ; MA # ( ѡ → w ) CYRILLIC SMALL LETTER OMEGA → LATIN SMALL LETTER W #
+051D ; 0077 ; MA # ( ԝ → w ) CYRILLIC SMALL LETTER WE → LATIN SMALL LETTER W #
+0561 ; 0077 ; MA # ( ա → w ) ARMENIAN SMALL LETTER AYB → LATIN SMALL LETTER W # →ɯ→
+1170A ; 0077 ; MA # ( 𑜊 → w ) AHOM LETTER JA → LATIN SMALL LETTER W #
+1170E ; 0077 ; MA # ( 𑜎 → w ) AHOM LETTER LA → LATIN SMALL LETTER W #
+1170F ; 0077 ; MA # ( 𑜏 → w ) AHOM LETTER SA → LATIN SMALL LETTER W #
+AB83 ; 0077 ; MA # ( ꮃ → w ) CHEROKEE SMALL LETTER LA → LATIN SMALL LETTER W # →ᴡ→
+
+118EF ; 0057 ; MA #* ( 𑣯 → W ) WARANG CITI NUMBER SIXTY → LATIN CAPITAL LETTER W #
+118E6 ; 0057 ; MA # ( 𑣦 → W ) WARANG CITI DIGIT SIX → LATIN CAPITAL LETTER W #
+1D416 ; 0057 ; MA # ( 𝐖 → W ) MATHEMATICAL BOLD CAPITAL W → LATIN CAPITAL LETTER W #
+1D44A ; 0057 ; MA # ( 𝑊 → W ) MATHEMATICAL ITALIC CAPITAL W → LATIN CAPITAL LETTER W #
+1D47E ; 0057 ; MA # ( 𝑾 → W ) MATHEMATICAL BOLD ITALIC CAPITAL W → LATIN CAPITAL LETTER W #
+1D4B2 ; 0057 ; MA # ( 𝒲 → W ) MATHEMATICAL SCRIPT CAPITAL W → LATIN CAPITAL LETTER W #
+1D4E6 ; 0057 ; MA # ( 𝓦 → W ) MATHEMATICAL BOLD SCRIPT CAPITAL W → LATIN CAPITAL LETTER W #
+1D51A ; 0057 ; MA # ( 𝔚 → W ) MATHEMATICAL FRAKTUR CAPITAL W → LATIN CAPITAL LETTER W #
+1D54E ; 0057 ; MA # ( 𝕎 → W ) MATHEMATICAL DOUBLE-STRUCK CAPITAL W → LATIN CAPITAL LETTER W #
+1D582 ; 0057 ; MA # ( 𝖂 → W ) MATHEMATICAL BOLD FRAKTUR CAPITAL W → LATIN CAPITAL LETTER W #
+1D5B6 ; 0057 ; MA # ( 𝖶 → W ) MATHEMATICAL SANS-SERIF CAPITAL W → LATIN CAPITAL LETTER W #
+1D5EA ; 0057 ; MA # ( 𝗪 → W ) MATHEMATICAL SANS-SERIF BOLD CAPITAL W → LATIN CAPITAL LETTER W #
+1D61E ; 0057 ; MA # ( 𝘞 → W ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL W → LATIN CAPITAL LETTER W #
+1D652 ; 0057 ; MA # ( 𝙒 → W ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W → LATIN CAPITAL LETTER W #
+1D686 ; 0057 ; MA # ( 𝚆 → W ) MATHEMATICAL MONOSPACE CAPITAL W → LATIN CAPITAL LETTER W #
+051C ; 0057 ; MA # ( Ԝ → W ) CYRILLIC CAPITAL LETTER WE → LATIN CAPITAL LETTER W #
+13B3 ; 0057 ; MA # ( Ꮃ → W ) CHEROKEE LETTER LA → LATIN CAPITAL LETTER W #
+13D4 ; 0057 ; MA # ( Ꮤ → W ) CHEROKEE LETTER TA → LATIN CAPITAL LETTER W #
+A4EA ; 0057 ; MA # ( ꓪ → W ) LISU LETTER WA → LATIN CAPITAL LETTER W #
+
+047D ; 0077 0486 0487 ; MA # ( ѽ → w҆҇ ) CYRILLIC SMALL LETTER OMEGA WITH TITLO → LATIN SMALL LETTER W, COMBINING CYRILLIC PSILI PNEUMATA, COMBINING CYRILLIC POKRYTIE # →ѡ҆҇→
+
+114C5 ; 0077 0307 ; MA # ( 𑓅 → ẇ ) TIRHUTA GVANG → LATIN SMALL LETTER W, COMBINING DOT ABOVE #
+
+20A9 ; 0057 0335 ; MA #* ( ₩ → W̵ ) WON SIGN → LATIN CAPITAL LETTER W, COMBINING SHORT STROKE OVERLAY #
+
+A761 ; 0077 0326 ; MA # ( ꝡ → w̦ ) LATIN SMALL LETTER VY → LATIN SMALL LETTER W, COMBINING COMMA BELOW # →w̡→
+
+1D0D ; 028D ; MA # ( ᴍ → ʍ ) LATIN LETTER SMALL CAPITAL M → LATIN SMALL LETTER TURNED W # →м→
+043C ; 028D ; MA # ( м → ʍ ) CYRILLIC SMALL LETTER EM → LATIN SMALL LETTER TURNED W #
+AB87 ; 028D ; MA # ( ꮇ → ʍ ) CHEROKEE SMALL LETTER LU → LATIN SMALL LETTER TURNED W # →ᴍ→→м→
+
+04CE ; 028D 0326 ; MA # ( ӎ → ʍ̦ ) CYRILLIC SMALL LETTER EM WITH TAIL → LATIN SMALL LETTER TURNED W, COMBINING COMMA BELOW # →м̡→
+
+166E ; 0078 ; MA #* ( ᙮ → x ) CANADIAN SYLLABICS FULL STOP → LATIN SMALL LETTER X #
+00D7 ; 0078 ; MA #* ( × → x ) MULTIPLICATION SIGN → LATIN SMALL LETTER X #
+292B ; 0078 ; MA #* ( ⤫ → x ) RISING DIAGONAL CROSSING FALLING DIAGONAL → LATIN SMALL LETTER X #
+292C ; 0078 ; MA #* ( ⤬ → x ) FALLING DIAGONAL CROSSING RISING DIAGONAL → LATIN SMALL LETTER X #
+2A2F ; 0078 ; MA #* ( ⨯ → x ) VECTOR OR CROSS PRODUCT → LATIN SMALL LETTER X # →×→
+FF58 ; 0078 ; MA # ( x → x ) FULLWIDTH LATIN SMALL LETTER X → LATIN SMALL LETTER X # →х→
+2179 ; 0078 ; MA # ( ⅹ → x ) SMALL ROMAN NUMERAL TEN → LATIN SMALL LETTER X #
+1D431 ; 0078 ; MA # ( 𝐱 → x ) MATHEMATICAL BOLD SMALL X → LATIN SMALL LETTER X #
+1D465 ; 0078 ; MA # ( 𝑥 → x ) MATHEMATICAL ITALIC SMALL X → LATIN SMALL LETTER X #
+1D499 ; 0078 ; MA # ( 𝒙 → x ) MATHEMATICAL BOLD ITALIC SMALL X → LATIN SMALL LETTER X #
+1D4CD ; 0078 ; MA # ( 𝓍 → x ) MATHEMATICAL SCRIPT SMALL X → LATIN SMALL LETTER X #
+1D501 ; 0078 ; MA # ( 𝔁 → x ) MATHEMATICAL BOLD SCRIPT SMALL X → LATIN SMALL LETTER X #
+1D535 ; 0078 ; MA # ( 𝔵 → x ) MATHEMATICAL FRAKTUR SMALL X → LATIN SMALL LETTER X #
+1D569 ; 0078 ; MA # ( 𝕩 → x ) MATHEMATICAL DOUBLE-STRUCK SMALL X → LATIN SMALL LETTER X #
+1D59D ; 0078 ; MA # ( 𝖝 → x ) MATHEMATICAL BOLD FRAKTUR SMALL X → LATIN SMALL LETTER X #
+1D5D1 ; 0078 ; MA # ( 𝗑 → x ) MATHEMATICAL SANS-SERIF SMALL X → LATIN SMALL LETTER X #
+1D605 ; 0078 ; MA # ( 𝘅 → x ) MATHEMATICAL SANS-SERIF BOLD SMALL X → LATIN SMALL LETTER X #
+1D639 ; 0078 ; MA # ( 𝘹 → x ) MATHEMATICAL SANS-SERIF ITALIC SMALL X → LATIN SMALL LETTER X #
+1D66D ; 0078 ; MA # ( 𝙭 → x ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X → LATIN SMALL LETTER X #
+1D6A1 ; 0078 ; MA # ( 𝚡 → x ) MATHEMATICAL MONOSPACE SMALL X → LATIN SMALL LETTER X #
+0445 ; 0078 ; MA # ( х → x ) CYRILLIC SMALL LETTER HA → LATIN SMALL LETTER X #
+1541 ; 0078 ; MA # ( ᕁ → x ) CANADIAN SYLLABICS SAYISI YI → LATIN SMALL LETTER X # →᙮→
+157D ; 0078 ; MA # ( ᕽ → x ) CANADIAN SYLLABICS HK → LATIN SMALL LETTER X # →ᕁ→→᙮→
+
+2DEF ; 036F ; MA # ( ⷯ → ͯ ) COMBINING CYRILLIC LETTER HA → COMBINING LATIN SMALL LETTER X #
+
+166D ; 0058 ; MA #* ( ᙭ → X ) CANADIAN SYLLABICS CHI SIGN → LATIN CAPITAL LETTER X #
+2573 ; 0058 ; MA #* ( ╳ → X ) BOX DRAWINGS LIGHT DIAGONAL CROSS → LATIN CAPITAL LETTER X #
+10322 ; 0058 ; MA #* ( 𐌢 → X ) OLD ITALIC NUMERAL TEN → LATIN CAPITAL LETTER X # →𐌗→
+118EC ; 0058 ; MA #* ( 𑣬 → X ) WARANG CITI NUMBER THIRTY → LATIN CAPITAL LETTER X #
+FF38 ; 0058 ; MA # ( X → X ) FULLWIDTH LATIN CAPITAL LETTER X → LATIN CAPITAL LETTER X # →Х→
+2169 ; 0058 ; MA # ( Ⅹ → X ) ROMAN NUMERAL TEN → LATIN CAPITAL LETTER X #
+1D417 ; 0058 ; MA # ( 𝐗 → X ) MATHEMATICAL BOLD CAPITAL X → LATIN CAPITAL LETTER X #
+1D44B ; 0058 ; MA # ( 𝑋 → X ) MATHEMATICAL ITALIC CAPITAL X → LATIN CAPITAL LETTER X #
+1D47F ; 0058 ; MA # ( 𝑿 → X ) MATHEMATICAL BOLD ITALIC CAPITAL X → LATIN CAPITAL LETTER X #
+1D4B3 ; 0058 ; MA # ( 𝒳 → X ) MATHEMATICAL SCRIPT CAPITAL X → LATIN CAPITAL LETTER X #
+1D4E7 ; 0058 ; MA # ( 𝓧 → X ) MATHEMATICAL BOLD SCRIPT CAPITAL X → LATIN CAPITAL LETTER X #
+1D51B ; 0058 ; MA # ( 𝔛 → X ) MATHEMATICAL FRAKTUR CAPITAL X → LATIN CAPITAL LETTER X #
+1D54F ; 0058 ; MA # ( 𝕏 → X ) MATHEMATICAL DOUBLE-STRUCK CAPITAL X → LATIN CAPITAL LETTER X #
+1D583 ; 0058 ; MA # ( 𝖃 → X ) MATHEMATICAL BOLD FRAKTUR CAPITAL X → LATIN CAPITAL LETTER X #
+1D5B7 ; 0058 ; MA # ( 𝖷 → X ) MATHEMATICAL SANS-SERIF CAPITAL X → LATIN CAPITAL LETTER X #
+1D5EB ; 0058 ; MA # ( 𝗫 → X ) MATHEMATICAL SANS-SERIF BOLD CAPITAL X → LATIN CAPITAL LETTER X #
+1D61F ; 0058 ; MA # ( 𝘟 → X ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL X → LATIN CAPITAL LETTER X #
+1D653 ; 0058 ; MA # ( 𝙓 → X ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X → LATIN CAPITAL LETTER X #
+1D687 ; 0058 ; MA # ( 𝚇 → X ) MATHEMATICAL MONOSPACE CAPITAL X → LATIN CAPITAL LETTER X #
+A7B3 ; 0058 ; MA # ( Ꭓ → X ) LATIN CAPITAL LETTER CHI → LATIN CAPITAL LETTER X #
+03A7 ; 0058 ; MA # ( Χ → X ) GREEK CAPITAL LETTER CHI → LATIN CAPITAL LETTER X #
+1D6BE ; 0058 ; MA # ( 𝚾 → X ) MATHEMATICAL BOLD CAPITAL CHI → LATIN CAPITAL LETTER X # →Χ→
+1D6F8 ; 0058 ; MA # ( 𝛸 → X ) MATHEMATICAL ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X # →Χ→
+1D732 ; 0058 ; MA # ( 𝜲 → X ) MATHEMATICAL BOLD ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X # →𝑿→
+1D76C ; 0058 ; MA # ( 𝝬 → X ) MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI → LATIN CAPITAL LETTER X # →Χ→
+1D7A6 ; 0058 ; MA # ( 𝞦 → X ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI → LATIN CAPITAL LETTER X # →Χ→
+2CAC ; 0058 ; MA # ( Ⲭ → X ) COPTIC CAPITAL LETTER KHI → LATIN CAPITAL LETTER X # →Х→
+0425 ; 0058 ; MA # ( Х → X ) CYRILLIC CAPITAL LETTER HA → LATIN CAPITAL LETTER X #
+2D5D ; 0058 ; MA # ( ⵝ → X ) TIFINAGH LETTER YATH → LATIN CAPITAL LETTER X #
+16B7 ; 0058 ; MA # ( ᚷ → X ) RUNIC LETTER GEBO GYFU G → LATIN CAPITAL LETTER X #
+A4EB ; 0058 ; MA # ( ꓫ → X ) LISU LETTER SHA → LATIN CAPITAL LETTER X #
+10290 ; 0058 ; MA # ( 𐊐 → X ) LYCIAN LETTER MM → LATIN CAPITAL LETTER X #
+102B4 ; 0058 ; MA # ( 𐊴 → X ) CARIAN LETTER X → LATIN CAPITAL LETTER X #
+10317 ; 0058 ; MA # ( 𐌗 → X ) OLD ITALIC LETTER EKS → LATIN CAPITAL LETTER X #
+10527 ; 0058 ; MA # ( 𐔧 → X ) ELBASAN LETTER KHE → LATIN CAPITAL LETTER X #
+
+2A30 ; 0078 0307 ; MA #* ( ⨰ → ẋ ) MULTIPLICATION SIGN WITH DOT ABOVE → LATIN SMALL LETTER X, COMBINING DOT ABOVE # →×̇→
+
+04B2 ; 0058 0329 ; MA # ( Ҳ → X̩ ) CYRILLIC CAPITAL LETTER HA WITH DESCENDER → LATIN CAPITAL LETTER X, COMBINING VERTICAL LINE BELOW # →Х̩→
+
+10196 ; 0058 0335 ; MA #* ( 𐆖 → X̵ ) ROMAN DENARIUS SIGN → LATIN CAPITAL LETTER X, COMBINING SHORT STROKE OVERLAY # →X̶→
+
+217A ; 0078 0069 ; MA # ( ⅺ → xi ) SMALL ROMAN NUMERAL ELEVEN → LATIN SMALL LETTER X, LATIN SMALL LETTER I #
+
+217B ; 0078 0069 0069 ; MA # ( ⅻ → xii ) SMALL ROMAN NUMERAL TWELVE → LATIN SMALL LETTER X, LATIN SMALL LETTER I, LATIN SMALL LETTER I #
+
+216A ; 0058 006C ; MA # ( Ⅺ → Xl ) ROMAN NUMERAL ELEVEN → LATIN CAPITAL LETTER X, LATIN SMALL LETTER L # →XI→
+
+216B ; 0058 006C 006C ; MA # ( Ⅻ → Xll ) ROMAN NUMERAL TWELVE → LATIN CAPITAL LETTER X, LATIN SMALL LETTER L, LATIN SMALL LETTER L # →XII→
+
+0263 ; 0079 ; MA # ( ɣ → y ) LATIN SMALL LETTER GAMMA → LATIN SMALL LETTER Y # →γ→
+1D8C ; 0079 ; MA # ( ᶌ → y ) LATIN SMALL LETTER V WITH PALATAL HOOK → LATIN SMALL LETTER Y #
+FF59 ; 0079 ; MA # ( y → y ) FULLWIDTH LATIN SMALL LETTER Y → LATIN SMALL LETTER Y # →у→
+1D432 ; 0079 ; MA # ( 𝐲 → y ) MATHEMATICAL BOLD SMALL Y → LATIN SMALL LETTER Y #
+1D466 ; 0079 ; MA # ( 𝑦 → y ) MATHEMATICAL ITALIC SMALL Y → LATIN SMALL LETTER Y #
+1D49A ; 0079 ; MA # ( 𝒚 → y ) MATHEMATICAL BOLD ITALIC SMALL Y → LATIN SMALL LETTER Y #
+1D4CE ; 0079 ; MA # ( 𝓎 → y ) MATHEMATICAL SCRIPT SMALL Y → LATIN SMALL LETTER Y #
+1D502 ; 0079 ; MA # ( 𝔂 → y ) MATHEMATICAL BOLD SCRIPT SMALL Y → LATIN SMALL LETTER Y #
+1D536 ; 0079 ; MA # ( 𝔶 → y ) MATHEMATICAL FRAKTUR SMALL Y → LATIN SMALL LETTER Y #
+1D56A ; 0079 ; MA # ( 𝕪 → y ) MATHEMATICAL DOUBLE-STRUCK SMALL Y → LATIN SMALL LETTER Y #
+1D59E ; 0079 ; MA # ( 𝖞 → y ) MATHEMATICAL BOLD FRAKTUR SMALL Y → LATIN SMALL LETTER Y #
+1D5D2 ; 0079 ; MA # ( 𝗒 → y ) MATHEMATICAL SANS-SERIF SMALL Y → LATIN SMALL LETTER Y #
+1D606 ; 0079 ; MA # ( 𝘆 → y ) MATHEMATICAL SANS-SERIF BOLD SMALL Y → LATIN SMALL LETTER Y #
+1D63A ; 0079 ; MA # ( 𝘺 → y ) MATHEMATICAL SANS-SERIF ITALIC SMALL Y → LATIN SMALL LETTER Y #
+1D66E ; 0079 ; MA # ( 𝙮 → y ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y → LATIN SMALL LETTER Y #
+1D6A2 ; 0079 ; MA # ( 𝚢 → y ) MATHEMATICAL MONOSPACE SMALL Y → LATIN SMALL LETTER Y #
+028F ; 0079 ; MA # ( ʏ → y ) LATIN LETTER SMALL CAPITAL Y → LATIN SMALL LETTER Y # →ү→→γ→
+1EFF ; 0079 ; MA # ( ỿ → y ) LATIN SMALL LETTER Y WITH LOOP → LATIN SMALL LETTER Y #
+AB5A ; 0079 ; MA # ( ꭚ → y ) LATIN SMALL LETTER Y WITH SHORT RIGHT LEG → LATIN SMALL LETTER Y #
+03B3 ; 0079 ; MA # ( γ → y ) GREEK SMALL LETTER GAMMA → LATIN SMALL LETTER Y #
+213D ; 0079 ; MA # ( ℽ → y ) DOUBLE-STRUCK SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+1D6C4 ; 0079 ; MA # ( 𝛄 → y ) MATHEMATICAL BOLD SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+1D6FE ; 0079 ; MA # ( 𝛾 → y ) MATHEMATICAL ITALIC SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+1D738 ; 0079 ; MA # ( 𝜸 → y ) MATHEMATICAL BOLD ITALIC SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+1D772 ; 0079 ; MA # ( 𝝲 → y ) MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+1D7AC ; 0079 ; MA # ( 𝞬 → y ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA → LATIN SMALL LETTER Y # →γ→
+0443 ; 0079 ; MA # ( у → y ) CYRILLIC SMALL LETTER U → LATIN SMALL LETTER Y #
+04AF ; 0079 ; MA # ( ү → y ) CYRILLIC SMALL LETTER STRAIGHT U → LATIN SMALL LETTER Y # →γ→
+10E7 ; 0079 ; MA # ( ყ → y ) GEORGIAN LETTER QAR → LATIN SMALL LETTER Y #
+118DC ; 0079 ; MA # ( 𑣜 → y ) WARANG CITI SMALL LETTER HAR → LATIN SMALL LETTER Y # →ɣ→→γ→
+
+FF39 ; 0059 ; MA # ( Y → Y ) FULLWIDTH LATIN CAPITAL LETTER Y → LATIN CAPITAL LETTER Y # →Υ→
+1D418 ; 0059 ; MA # ( 𝐘 → Y ) MATHEMATICAL BOLD CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D44C ; 0059 ; MA # ( 𝑌 → Y ) MATHEMATICAL ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D480 ; 0059 ; MA # ( 𝒀 → Y ) MATHEMATICAL BOLD ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D4B4 ; 0059 ; MA # ( 𝒴 → Y ) MATHEMATICAL SCRIPT CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D4E8 ; 0059 ; MA # ( 𝓨 → Y ) MATHEMATICAL BOLD SCRIPT CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D51C ; 0059 ; MA # ( 𝔜 → Y ) MATHEMATICAL FRAKTUR CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D550 ; 0059 ; MA # ( 𝕐 → Y ) MATHEMATICAL DOUBLE-STRUCK CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D584 ; 0059 ; MA # ( 𝖄 → Y ) MATHEMATICAL BOLD FRAKTUR CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D5B8 ; 0059 ; MA # ( 𝖸 → Y ) MATHEMATICAL SANS-SERIF CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D5EC ; 0059 ; MA # ( 𝗬 → Y ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D620 ; 0059 ; MA # ( 𝘠 → Y ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D654 ; 0059 ; MA # ( 𝙔 → Y ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y → LATIN CAPITAL LETTER Y #
+1D688 ; 0059 ; MA # ( 𝚈 → Y ) MATHEMATICAL MONOSPACE CAPITAL Y → LATIN CAPITAL LETTER Y #
+03A5 ; 0059 ; MA # ( Υ → Y ) GREEK CAPITAL LETTER UPSILON → LATIN CAPITAL LETTER Y #
+03D2 ; 0059 ; MA # ( ϒ → Y ) GREEK UPSILON WITH HOOK SYMBOL → LATIN CAPITAL LETTER Y #
+1D6BC ; 0059 ; MA # ( 𝚼 → Y ) MATHEMATICAL BOLD CAPITAL UPSILON → LATIN CAPITAL LETTER Y # →Υ→
+1D6F6 ; 0059 ; MA # ( 𝛶 → Y ) MATHEMATICAL ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y # →Υ→
+1D730 ; 0059 ; MA # ( 𝜰 → Y ) MATHEMATICAL BOLD ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y # →Υ→
+1D76A ; 0059 ; MA # ( 𝝪 → Y ) MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON → LATIN CAPITAL LETTER Y # →Υ→
+1D7A4 ; 0059 ; MA # ( 𝞤 → Y ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON → LATIN CAPITAL LETTER Y # →Υ→
+2CA8 ; 0059 ; MA # ( Ⲩ → Y ) COPTIC CAPITAL LETTER UA → LATIN CAPITAL LETTER Y #
+0423 ; 0059 ; MA # ( У → Y ) CYRILLIC CAPITAL LETTER U → LATIN CAPITAL LETTER Y #
+04AE ; 0059 ; MA # ( Ү → Y ) CYRILLIC CAPITAL LETTER STRAIGHT U → LATIN CAPITAL LETTER Y #
+13A9 ; 0059 ; MA # ( Ꭹ → Y ) CHEROKEE LETTER GI → LATIN CAPITAL LETTER Y #
+13BD ; 0059 ; MA # ( Ꮍ → Y ) CHEROKEE LETTER MU → LATIN CAPITAL LETTER Y # →Ꭹ→
+A4EC ; 0059 ; MA # ( ꓬ → Y ) LISU LETTER YA → LATIN CAPITAL LETTER Y #
+16F43 ; 0059 ; MA # ( 𖽃 → Y ) MIAO LETTER AH → LATIN CAPITAL LETTER Y #
+118A4 ; 0059 ; MA # ( 𑢤 → Y ) WARANG CITI CAPITAL LETTER YA → LATIN CAPITAL LETTER Y #
+102B2 ; 0059 ; MA # ( 𐊲 → Y ) CARIAN LETTER U → LATIN CAPITAL LETTER Y #
+
+01B4 ; 0079 0314 ; MA # ( ƴ → y̔ ) LATIN SMALL LETTER Y WITH HOOK → LATIN SMALL LETTER Y, COMBINING REVERSED COMMA ABOVE #
+
+024F ; 0079 0335 ; MA # ( ɏ → y̵ ) LATIN SMALL LETTER Y WITH STROKE → LATIN SMALL LETTER Y, COMBINING SHORT STROKE OVERLAY #
+04B1 ; 0079 0335 ; MA # ( ұ → y̵ ) CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE → LATIN SMALL LETTER Y, COMBINING SHORT STROKE OVERLAY # →ү̵→
+
+00A5 ; 0059 0335 ; MA #* ( ¥ → Y̵ ) YEN SIGN → LATIN CAPITAL LETTER Y, COMBINING SHORT STROKE OVERLAY #
+024E ; 0059 0335 ; MA # ( Ɏ → Y̵ ) LATIN CAPITAL LETTER Y WITH STROKE → LATIN CAPITAL LETTER Y, COMBINING SHORT STROKE OVERLAY #
+04B0 ; 0059 0335 ; MA # ( Ұ → Y̵ ) CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE → LATIN CAPITAL LETTER Y, COMBINING SHORT STROKE OVERLAY # →Ү̵→
+
+0292 ; 021D ; MA # ( ʒ → ȝ ) LATIN SMALL LETTER EZH → LATIN SMALL LETTER YOGH #
+A76B ; 021D ; MA # ( ꝫ → ȝ ) LATIN SMALL LETTER ET → LATIN SMALL LETTER YOGH #
+2CCD ; 021D ; MA # ( ⳍ → ȝ ) COPTIC SMALL LETTER OLD COPTIC HORI → LATIN SMALL LETTER YOGH #
+04E1 ; 021D ; MA # ( ӡ → ȝ ) CYRILLIC SMALL LETTER ABKHASIAN DZE → LATIN SMALL LETTER YOGH # →ʒ→
+10F3 ; 021D ; MA # ( ჳ → ȝ ) GEORGIAN LETTER WE → LATIN SMALL LETTER YOGH # →ʒ→
+
+1D433 ; 007A ; MA # ( 𝐳 → z ) MATHEMATICAL BOLD SMALL Z → LATIN SMALL LETTER Z #
+1D467 ; 007A ; MA # ( 𝑧 → z ) MATHEMATICAL ITALIC SMALL Z → LATIN SMALL LETTER Z #
+1D49B ; 007A ; MA # ( 𝒛 → z ) MATHEMATICAL BOLD ITALIC SMALL Z → LATIN SMALL LETTER Z #
+1D4CF ; 007A ; MA # ( 𝓏 → z ) MATHEMATICAL SCRIPT SMALL Z → LATIN SMALL LETTER Z #
+1D503 ; 007A ; MA # ( 𝔃 → z ) MATHEMATICAL BOLD SCRIPT SMALL Z → LATIN SMALL LETTER Z #
+1D537 ; 007A ; MA # ( 𝔷 → z ) MATHEMATICAL FRAKTUR SMALL Z → LATIN SMALL LETTER Z #
+1D56B ; 007A ; MA # ( 𝕫 → z ) MATHEMATICAL DOUBLE-STRUCK SMALL Z → LATIN SMALL LETTER Z #
+1D59F ; 007A ; MA # ( 𝖟 → z ) MATHEMATICAL BOLD FRAKTUR SMALL Z → LATIN SMALL LETTER Z #
+1D5D3 ; 007A ; MA # ( 𝗓 → z ) MATHEMATICAL SANS-SERIF SMALL Z → LATIN SMALL LETTER Z #
+1D607 ; 007A ; MA # ( 𝘇 → z ) MATHEMATICAL SANS-SERIF BOLD SMALL Z → LATIN SMALL LETTER Z #
+1D63B ; 007A ; MA # ( 𝘻 → z ) MATHEMATICAL SANS-SERIF ITALIC SMALL Z → LATIN SMALL LETTER Z #
+1D66F ; 007A ; MA # ( 𝙯 → z ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z → LATIN SMALL LETTER Z #
+1D6A3 ; 007A ; MA # ( 𝚣 → z ) MATHEMATICAL MONOSPACE SMALL Z → LATIN SMALL LETTER Z #
+1D22 ; 007A ; MA # ( ᴢ → z ) LATIN LETTER SMALL CAPITAL Z → LATIN SMALL LETTER Z #
+AB93 ; 007A ; MA # ( ꮓ → z ) CHEROKEE SMALL LETTER NO → LATIN SMALL LETTER Z # →ᴢ→
+118C4 ; 007A ; MA # ( 𑣄 → z ) WARANG CITI SMALL LETTER YA → LATIN SMALL LETTER Z #
+
+102F5 ; 005A ; MA #* ( 𐋵 → Z ) COPTIC EPACT NUMBER THREE HUNDRED → LATIN CAPITAL LETTER Z #
+118E5 ; 005A ; MA # ( 𑣥 → Z ) WARANG CITI DIGIT FIVE → LATIN CAPITAL LETTER Z #
+FF3A ; 005A ; MA # ( Z → Z ) FULLWIDTH LATIN CAPITAL LETTER Z → LATIN CAPITAL LETTER Z # →Ζ→
+2124 ; 005A ; MA # ( ℤ → Z ) DOUBLE-STRUCK CAPITAL Z → LATIN CAPITAL LETTER Z #
+2128 ; 005A ; MA # ( ℨ → Z ) BLACK-LETTER CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D419 ; 005A ; MA # ( 𝐙 → Z ) MATHEMATICAL BOLD CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D44D ; 005A ; MA # ( 𝑍 → Z ) MATHEMATICAL ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D481 ; 005A ; MA # ( 𝒁 → Z ) MATHEMATICAL BOLD ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D4B5 ; 005A ; MA # ( 𝒵 → Z ) MATHEMATICAL SCRIPT CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D4E9 ; 005A ; MA # ( 𝓩 → Z ) MATHEMATICAL BOLD SCRIPT CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D585 ; 005A ; MA # ( 𝖅 → Z ) MATHEMATICAL BOLD FRAKTUR CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D5B9 ; 005A ; MA # ( 𝖹 → Z ) MATHEMATICAL SANS-SERIF CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D5ED ; 005A ; MA # ( 𝗭 → Z ) MATHEMATICAL SANS-SERIF BOLD CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D621 ; 005A ; MA # ( 𝘡 → Z ) MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D655 ; 005A ; MA # ( 𝙕 → Z ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z → LATIN CAPITAL LETTER Z #
+1D689 ; 005A ; MA # ( 𝚉 → Z ) MATHEMATICAL MONOSPACE CAPITAL Z → LATIN CAPITAL LETTER Z #
+0396 ; 005A ; MA # ( Ζ → Z ) GREEK CAPITAL LETTER ZETA → LATIN CAPITAL LETTER Z #
+1D6AD ; 005A ; MA # ( 𝚭 → Z ) MATHEMATICAL BOLD CAPITAL ZETA → LATIN CAPITAL LETTER Z # →Ζ→
+1D6E7 ; 005A ; MA # ( 𝛧 → Z ) MATHEMATICAL ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z # →𝑍→
+1D721 ; 005A ; MA # ( 𝜡 → Z ) MATHEMATICAL BOLD ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z # →Ζ→
+1D75B ; 005A ; MA # ( 𝝛 → Z ) MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA → LATIN CAPITAL LETTER Z # →Ζ→
+1D795 ; 005A ; MA # ( 𝞕 → Z ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA → LATIN CAPITAL LETTER Z # →Ζ→
+13C3 ; 005A ; MA # ( Ꮓ → Z ) CHEROKEE LETTER NO → LATIN CAPITAL LETTER Z #
+A4DC ; 005A ; MA # ( ꓜ → Z ) LISU LETTER DZA → LATIN CAPITAL LETTER Z #
+118A9 ; 005A ; MA # ( 𑢩 → Z ) WARANG CITI CAPITAL LETTER O → LATIN CAPITAL LETTER Z #
+
+0290 ; 007A 0328 ; MA # ( ʐ → z̨ ) LATIN SMALL LETTER Z WITH RETROFLEX HOOK → LATIN SMALL LETTER Z, COMBINING OGONEK # →z̢→
+
+01B6 ; 007A 0335 ; MA # ( ƶ → z̵ ) LATIN SMALL LETTER Z WITH STROKE → LATIN SMALL LETTER Z, COMBINING SHORT STROKE OVERLAY #
+
+01B5 ; 005A 0335 ; MA # ( Ƶ → Z̵ ) LATIN CAPITAL LETTER Z WITH STROKE → LATIN CAPITAL LETTER Z, COMBINING SHORT STROKE OVERLAY #
+
+0225 ; 007A 0326 ; MA # ( ȥ → z̦ ) LATIN SMALL LETTER Z WITH HOOK → LATIN SMALL LETTER Z, COMBINING COMMA BELOW # →z̡→
+
+0224 ; 005A 0326 ; MA # ( Ȥ → Z̦ ) LATIN CAPITAL LETTER Z WITH HOOK → LATIN CAPITAL LETTER Z, COMBINING COMMA BELOW # →Z̧→
+
+1D76 ; 007A 0334 ; MA # ( ᵶ → z̴ ) LATIN SMALL LETTER Z WITH MIDDLE TILDE → LATIN SMALL LETTER Z, COMBINING TILDE OVERLAY #
+
+01BF ; 00FE ; MA # ( ƿ → þ ) LATIN LETTER WYNN → LATIN SMALL LETTER THORN #
+03F8 ; 00FE ; MA # ( ϸ → þ ) GREEK SMALL LETTER SHO → LATIN SMALL LETTER THORN #
+
+03F7 ; 00DE ; MA # ( Ϸ → Þ ) GREEK CAPITAL LETTER SHO → LATIN CAPITAL LETTER THORN #
+104C4 ; 00DE ; MA # ( 𐓄 → Þ ) OSAGE CAPITAL LETTER PA → LATIN CAPITAL LETTER THORN #
+
+2079 ; A770 ; MA #* ( ⁹ → ꝰ ) SUPERSCRIPT NINE → MODIFIER LETTER US #
+
+1D24 ; 01A8 ; MA # ( ᴤ → ƨ ) LATIN LETTER VOICED LARYNGEAL SPIRANT → LATIN SMALL LETTER TONE TWO #
+03E9 ; 01A8 ; MA # ( ϩ → ƨ ) COPTIC SMALL LETTER HORI → LATIN SMALL LETTER TONE TWO #
+A645 ; 01A8 ; MA # ( ꙅ → ƨ ) CYRILLIC SMALL LETTER REVERSED DZE → LATIN SMALL LETTER TONE TWO #
+
+044C ; 0185 ; MA # ( ь → ƅ ) CYRILLIC SMALL LETTER SOFT SIGN → LATIN SMALL LETTER TONE SIX #
+AB9F ; 0185 ; MA # ( ꮟ → ƅ ) CHEROKEE SMALL LETTER SI → LATIN SMALL LETTER TONE SIX # →ь→
+
+044B ; 0185 0069 ; MA # ( ы → ƅi ) CYRILLIC SMALL LETTER YERU → LATIN SMALL LETTER TONE SIX, LATIN SMALL LETTER I # →ьı→
+
+AB7E ; 0242 ; MA # ( ꭾ → ɂ ) CHEROKEE SMALL LETTER HE → LATIN SMALL LETTER GLOTTAL STOP #
+
+02E4 ; 02C1 ; MA # ( ˤ → ˁ ) MODIFIER LETTER SMALL REVERSED GLOTTAL STOP → MODIFIER LETTER REVERSED GLOTTAL STOP #
+
+A6CD ; 02A1 ; MA # ( ꛍ → ʡ ) BAMUM LETTER LU → LATIN LETTER GLOTTAL STOP WITH STROKE #
+
+2299 ; 0298 ; MA #* ( ⊙ → ʘ ) CIRCLED DOT OPERATOR → LATIN LETTER BILABIAL CLICK #
+2609 ; 0298 ; MA #* ( ☉ → ʘ ) SUN → LATIN LETTER BILABIAL CLICK # →⊙→
+2A00 ; 0298 ; MA #* ( ⨀ → ʘ ) N-ARY CIRCLED DOT OPERATOR → LATIN LETTER BILABIAL CLICK # →⊙→
+A668 ; 0298 ; MA # ( Ꙩ → ʘ ) CYRILLIC CAPITAL LETTER MONOCULAR O → LATIN LETTER BILABIAL CLICK #
+2D59 ; 0298 ; MA # ( ⵙ → ʘ ) TIFINAGH LETTER YAS → LATIN LETTER BILABIAL CLICK # →⊙→
+104C3 ; 0298 ; MA # ( 𐓃 → ʘ ) OSAGE CAPITAL LETTER OIN → LATIN LETTER BILABIAL CLICK # →Ꙩ→
+
+213E ; 0393 ; MA # ( ℾ → Γ ) DOUBLE-STRUCK CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+1D6AA ; 0393 ; MA # ( 𝚪 → Γ ) MATHEMATICAL BOLD CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+1D6E4 ; 0393 ; MA # ( 𝛤 → Γ ) MATHEMATICAL ITALIC CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+1D71E ; 0393 ; MA # ( 𝜞 → Γ ) MATHEMATICAL BOLD ITALIC CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+1D758 ; 0393 ; MA # ( 𝝘 → Γ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+1D792 ; 0393 ; MA # ( 𝞒 → Γ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA → GREEK CAPITAL LETTER GAMMA #
+2C84 ; 0393 ; MA # ( Ⲅ → Γ ) COPTIC CAPITAL LETTER GAMMA → GREEK CAPITAL LETTER GAMMA #
+0413 ; 0393 ; MA # ( Г → Γ ) CYRILLIC CAPITAL LETTER GHE → GREEK CAPITAL LETTER GAMMA #
+13B1 ; 0393 ; MA # ( Ꮁ → Γ ) CHEROKEE LETTER HU → GREEK CAPITAL LETTER GAMMA #
+14A5 ; 0393 ; MA # ( ᒥ → Γ ) CANADIAN SYLLABICS MI → GREEK CAPITAL LETTER GAMMA #
+16F07 ; 0393 ; MA # ( 𖼇 → Γ ) MIAO LETTER FA → GREEK CAPITAL LETTER GAMMA #
+
+0492 ; 0393 0335 ; MA # ( Ғ → Γ̵ ) CYRILLIC CAPITAL LETTER GHE WITH STROKE → GREEK CAPITAL LETTER GAMMA, COMBINING SHORT STROKE OVERLAY # →Г̵→
+
+14AF ; 0393 00B7 ; MA # ( ᒯ → Γ· ) CANADIAN SYLLABICS WEST-CREE MWI → GREEK CAPITAL LETTER GAMMA, MIDDLE DOT # →ᒥᐧ→→ᒥ·→
+
+0490 ; 0393 0027 ; MA # ( Ґ → Γ' ) CYRILLIC CAPITAL LETTER GHE WITH UPTURN → GREEK CAPITAL LETTER GAMMA, APOSTROPHE # →Гˈ→
+
+2206 ; 0394 ; MA #* ( ∆ → Δ ) INCREMENT → GREEK CAPITAL LETTER DELTA #
+25B3 ; 0394 ; MA #* ( △ → Δ ) WHITE UP-POINTING TRIANGLE → GREEK CAPITAL LETTER DELTA #
+1F702 ; 0394 ; MA #* ( 🜂 → Δ ) ALCHEMICAL SYMBOL FOR FIRE → GREEK CAPITAL LETTER DELTA # →△→
+1D6AB ; 0394 ; MA # ( 𝚫 → Δ ) MATHEMATICAL BOLD CAPITAL DELTA → GREEK CAPITAL LETTER DELTA #
+1D6E5 ; 0394 ; MA # ( 𝛥 → Δ ) MATHEMATICAL ITALIC CAPITAL DELTA → GREEK CAPITAL LETTER DELTA #
+1D71F ; 0394 ; MA # ( 𝜟 → Δ ) MATHEMATICAL BOLD ITALIC CAPITAL DELTA → GREEK CAPITAL LETTER DELTA #
+1D759 ; 0394 ; MA # ( 𝝙 → Δ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA → GREEK CAPITAL LETTER DELTA #
+1D793 ; 0394 ; MA # ( 𝞓 → Δ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA → GREEK CAPITAL LETTER DELTA #
+2C86 ; 0394 ; MA # ( Ⲇ → Δ ) COPTIC CAPITAL LETTER DALDA → GREEK CAPITAL LETTER DELTA #
+2D60 ; 0394 ; MA # ( ⵠ → Δ ) TIFINAGH LETTER YAV → GREEK CAPITAL LETTER DELTA #
+1403 ; 0394 ; MA # ( ᐃ → Δ ) CANADIAN SYLLABICS I → GREEK CAPITAL LETTER DELTA #
+16F1A ; 0394 ; MA # ( 𖼚 → Δ ) MIAO LETTER TLHA → GREEK CAPITAL LETTER DELTA #
+10285 ; 0394 ; MA # ( 𐊅 → Δ ) LYCIAN LETTER D → GREEK CAPITAL LETTER DELTA #
+102A3 ; 0394 ; MA # ( 𐊣 → Δ ) CARIAN LETTER L → GREEK CAPITAL LETTER DELTA #
+
+2359 ; 0394 0332 ; MA #* ( ⍙ → Δ̲ ) APL FUNCTIONAL SYMBOL DELTA UNDERBAR → GREEK CAPITAL LETTER DELTA, COMBINING LOW LINE #
+
+140F ; 0394 00B7 ; MA # ( ᐏ → Δ· ) CANADIAN SYLLABICS WEST-CREE WI → GREEK CAPITAL LETTER DELTA, MIDDLE DOT # →ᐃᐧ→
+
+142C ; 0394 1420 ; MA # ( ᐬ → Δᐠ ) CANADIAN SYLLABICS IN → GREEK CAPITAL LETTER DELTA, CANADIAN SYLLABICS FINAL GRAVE # →ᐃᐠ→
+
+1D7CB ; 03DD ; MA # ( 𝟋 → ϝ ) MATHEMATICAL BOLD SMALL DIGAMMA → GREEK SMALL LETTER DIGAMMA #
+
+1D6C7 ; 03B6 ; MA # ( 𝛇 → ζ ) MATHEMATICAL BOLD SMALL ZETA → GREEK SMALL LETTER ZETA #
+1D701 ; 03B6 ; MA # ( 𝜁 → ζ ) MATHEMATICAL ITALIC SMALL ZETA → GREEK SMALL LETTER ZETA #
+1D73B ; 03B6 ; MA # ( 𝜻 → ζ ) MATHEMATICAL BOLD ITALIC SMALL ZETA → GREEK SMALL LETTER ZETA #
+1D775 ; 03B6 ; MA # ( 𝝵 → ζ ) MATHEMATICAL SANS-SERIF BOLD SMALL ZETA → GREEK SMALL LETTER ZETA #
+1D7AF ; 03B6 ; MA # ( 𝞯 → ζ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA → GREEK SMALL LETTER ZETA #
+
+2CE4 ; 03D7 ; MA # ( ⳤ → ϗ ) COPTIC SYMBOL KAI → GREEK KAI SYMBOL #
+
+1D6CC ; 03BB ; MA # ( 𝛌 → λ ) MATHEMATICAL BOLD SMALL LAMDA → GREEK SMALL LETTER LAMDA #
+1D706 ; 03BB ; MA # ( 𝜆 → λ ) MATHEMATICAL ITALIC SMALL LAMDA → GREEK SMALL LETTER LAMDA #
+1D740 ; 03BB ; MA # ( 𝝀 → λ ) MATHEMATICAL BOLD ITALIC SMALL LAMDA → GREEK SMALL LETTER LAMDA #
+1D77A ; 03BB ; MA # ( 𝝺 → λ ) MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA → GREEK SMALL LETTER LAMDA #
+1D7B4 ; 03BB ; MA # ( 𝞴 → λ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA → GREEK SMALL LETTER LAMDA #
+2C96 ; 03BB ; MA # ( Ⲗ → λ ) COPTIC CAPITAL LETTER LAULA → GREEK SMALL LETTER LAMDA #
+104DB ; 03BB ; MA # ( 𐓛 → λ ) OSAGE SMALL LETTER AH → GREEK SMALL LETTER LAMDA #
+
+00B5 ; 03BC ; MA # ( µ → μ ) MICRO SIGN → GREEK SMALL LETTER MU #
+1D6CD ; 03BC ; MA # ( 𝛍 → μ ) MATHEMATICAL BOLD SMALL MU → GREEK SMALL LETTER MU #
+1D707 ; 03BC ; MA # ( 𝜇 → μ ) MATHEMATICAL ITALIC SMALL MU → GREEK SMALL LETTER MU #
+1D741 ; 03BC ; MA # ( 𝝁 → μ ) MATHEMATICAL BOLD ITALIC SMALL MU → GREEK SMALL LETTER MU #
+1D77B ; 03BC ; MA # ( 𝝻 → μ ) MATHEMATICAL SANS-SERIF BOLD SMALL MU → GREEK SMALL LETTER MU #
+1D7B5 ; 03BC ; MA # ( 𝞵 → μ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU → GREEK SMALL LETTER MU #
+
+1D6CF ; 03BE ; MA # ( 𝛏 → ξ ) MATHEMATICAL BOLD SMALL XI → GREEK SMALL LETTER XI #
+1D709 ; 03BE ; MA # ( 𝜉 → ξ ) MATHEMATICAL ITALIC SMALL XI → GREEK SMALL LETTER XI #
+1D743 ; 03BE ; MA # ( 𝝃 → ξ ) MATHEMATICAL BOLD ITALIC SMALL XI → GREEK SMALL LETTER XI #
+1D77D ; 03BE ; MA # ( 𝝽 → ξ ) MATHEMATICAL SANS-SERIF BOLD SMALL XI → GREEK SMALL LETTER XI #
+1D7B7 ; 03BE ; MA # ( 𝞷 → ξ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI → GREEK SMALL LETTER XI #
+
+1D6B5 ; 039E ; MA # ( 𝚵 → Ξ ) MATHEMATICAL BOLD CAPITAL XI → GREEK CAPITAL LETTER XI #
+1D6EF ; 039E ; MA # ( 𝛯 → Ξ ) MATHEMATICAL ITALIC CAPITAL XI → GREEK CAPITAL LETTER XI #
+1D729 ; 039E ; MA # ( 𝜩 → Ξ ) MATHEMATICAL BOLD ITALIC CAPITAL XI → GREEK CAPITAL LETTER XI #
+1D763 ; 039E ; MA # ( 𝝣 → Ξ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL XI → GREEK CAPITAL LETTER XI #
+1D79D ; 039E ; MA # ( 𝞝 → Ξ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI → GREEK CAPITAL LETTER XI #
+
+03D6 ; 03C0 ; MA # ( ϖ → π ) GREEK PI SYMBOL → GREEK SMALL LETTER PI #
+213C ; 03C0 ; MA # ( ℼ → π ) DOUBLE-STRUCK SMALL PI → GREEK SMALL LETTER PI #
+1D6D1 ; 03C0 ; MA # ( 𝛑 → π ) MATHEMATICAL BOLD SMALL PI → GREEK SMALL LETTER PI #
+1D6E1 ; 03C0 ; MA # ( 𝛡 → π ) MATHEMATICAL BOLD PI SYMBOL → GREEK SMALL LETTER PI #
+1D70B ; 03C0 ; MA # ( 𝜋 → π ) MATHEMATICAL ITALIC SMALL PI → GREEK SMALL LETTER PI #
+1D71B ; 03C0 ; MA # ( 𝜛 → π ) MATHEMATICAL ITALIC PI SYMBOL → GREEK SMALL LETTER PI #
+1D745 ; 03C0 ; MA # ( 𝝅 → π ) MATHEMATICAL BOLD ITALIC SMALL PI → GREEK SMALL LETTER PI #
+1D755 ; 03C0 ; MA # ( 𝝕 → π ) MATHEMATICAL BOLD ITALIC PI SYMBOL → GREEK SMALL LETTER PI #
+1D77F ; 03C0 ; MA # ( 𝝿 → π ) MATHEMATICAL SANS-SERIF BOLD SMALL PI → GREEK SMALL LETTER PI #
+1D78F ; 03C0 ; MA # ( 𝞏 → π ) MATHEMATICAL SANS-SERIF BOLD PI SYMBOL → GREEK SMALL LETTER PI #
+1D7B9 ; 03C0 ; MA # ( 𝞹 → π ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI → GREEK SMALL LETTER PI #
+1D7C9 ; 03C0 ; MA # ( 𝟉 → π ) MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL → GREEK SMALL LETTER PI #
+1D28 ; 03C0 ; MA # ( ᴨ → π ) GREEK LETTER SMALL CAPITAL PI → GREEK SMALL LETTER PI # →п→
+043F ; 03C0 ; MA # ( п → π ) CYRILLIC SMALL LETTER PE → GREEK SMALL LETTER PI #
+
+220F ; 03A0 ; MA #* ( ∏ → Π ) N-ARY PRODUCT → GREEK CAPITAL LETTER PI #
+213F ; 03A0 ; MA # ( ℿ → Π ) DOUBLE-STRUCK CAPITAL PI → GREEK CAPITAL LETTER PI #
+1D6B7 ; 03A0 ; MA # ( 𝚷 → Π ) MATHEMATICAL BOLD CAPITAL PI → GREEK CAPITAL LETTER PI #
+1D6F1 ; 03A0 ; MA # ( 𝛱 → Π ) MATHEMATICAL ITALIC CAPITAL PI → GREEK CAPITAL LETTER PI #
+1D72B ; 03A0 ; MA # ( 𝜫 → Π ) MATHEMATICAL BOLD ITALIC CAPITAL PI → GREEK CAPITAL LETTER PI #
+1D765 ; 03A0 ; MA # ( 𝝥 → Π ) MATHEMATICAL SANS-SERIF BOLD CAPITAL PI → GREEK CAPITAL LETTER PI #
+1D79F ; 03A0 ; MA # ( 𝞟 → Π ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI → GREEK CAPITAL LETTER PI #
+2CA0 ; 03A0 ; MA # ( Ⲡ → Π ) COPTIC CAPITAL LETTER PI → GREEK CAPITAL LETTER PI #
+041F ; 03A0 ; MA # ( П → Π ) CYRILLIC CAPITAL LETTER PE → GREEK CAPITAL LETTER PI #
+A6DB ; 03A0 ; MA # ( ꛛ → Π ) BAMUM LETTER NA → GREEK CAPITAL LETTER PI #
+
+102AD ; 03D8 ; MA # ( 𐊭 → Ϙ ) CARIAN LETTER T → GREEK LETTER ARCHAIC KOPPA #
+10312 ; 03D8 ; MA # ( 𐌒 → Ϙ ) OLD ITALIC LETTER KU → GREEK LETTER ARCHAIC KOPPA #
+
+03DB ; 03C2 ; MA # ( ϛ → ς ) GREEK SMALL LETTER STIGMA → GREEK SMALL LETTER FINAL SIGMA #
+1D6D3 ; 03C2 ; MA # ( 𝛓 → ς ) MATHEMATICAL BOLD SMALL FINAL SIGMA → GREEK SMALL LETTER FINAL SIGMA #
+1D70D ; 03C2 ; MA # ( 𝜍 → ς ) MATHEMATICAL ITALIC SMALL FINAL SIGMA → GREEK SMALL LETTER FINAL SIGMA #
+1D747 ; 03C2 ; MA # ( 𝝇 → ς ) MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA → GREEK SMALL LETTER FINAL SIGMA #
+1D781 ; 03C2 ; MA # ( 𝞁 → ς ) MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA → GREEK SMALL LETTER FINAL SIGMA #
+1D7BB ; 03C2 ; MA # ( 𝞻 → ς ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA → GREEK SMALL LETTER FINAL SIGMA #
+
+1D6BD ; 03A6 ; MA # ( 𝚽 → Φ ) MATHEMATICAL BOLD CAPITAL PHI → GREEK CAPITAL LETTER PHI #
+1D6F7 ; 03A6 ; MA # ( 𝛷 → Φ ) MATHEMATICAL ITALIC CAPITAL PHI → GREEK CAPITAL LETTER PHI #
+1D731 ; 03A6 ; MA # ( 𝜱 → Φ ) MATHEMATICAL BOLD ITALIC CAPITAL PHI → GREEK CAPITAL LETTER PHI #
+1D76B ; 03A6 ; MA # ( 𝝫 → Φ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI → GREEK CAPITAL LETTER PHI #
+1D7A5 ; 03A6 ; MA # ( 𝞥 → Φ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI → GREEK CAPITAL LETTER PHI #
+2CAA ; 03A6 ; MA # ( Ⲫ → Φ ) COPTIC CAPITAL LETTER FI → GREEK CAPITAL LETTER PHI #
+0424 ; 03A6 ; MA # ( Ф → Φ ) CYRILLIC CAPITAL LETTER EF → GREEK CAPITAL LETTER PHI #
+0553 ; 03A6 ; MA # ( Փ → Φ ) ARMENIAN CAPITAL LETTER PIWR → GREEK CAPITAL LETTER PHI #
+1240 ; 03A6 ; MA # ( ቀ → Φ ) ETHIOPIC SYLLABLE QA → GREEK CAPITAL LETTER PHI # →Փ→
+16F0 ; 03A6 ; MA # ( ᛰ → Φ ) RUNIC BELGTHOR SYMBOL → GREEK CAPITAL LETTER PHI #
+102B3 ; 03A6 ; MA # ( 𐊳 → Φ ) CARIAN LETTER NN → GREEK CAPITAL LETTER PHI #
+
+AB53 ; 03C7 ; MA # ( ꭓ → χ ) LATIN SMALL LETTER CHI → GREEK SMALL LETTER CHI #
+AB55 ; 03C7 ; MA # ( ꭕ → χ ) LATIN SMALL LETTER CHI WITH LOW LEFT SERIF → GREEK SMALL LETTER CHI #
+1D6D8 ; 03C7 ; MA # ( 𝛘 → χ ) MATHEMATICAL BOLD SMALL CHI → GREEK SMALL LETTER CHI #
+1D712 ; 03C7 ; MA # ( 𝜒 → χ ) MATHEMATICAL ITALIC SMALL CHI → GREEK SMALL LETTER CHI #
+1D74C ; 03C7 ; MA # ( 𝝌 → χ ) MATHEMATICAL BOLD ITALIC SMALL CHI → GREEK SMALL LETTER CHI #
+1D786 ; 03C7 ; MA # ( 𝞆 → χ ) MATHEMATICAL SANS-SERIF BOLD SMALL CHI → GREEK SMALL LETTER CHI #
+1D7C0 ; 03C7 ; MA # ( 𝟀 → χ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI → GREEK SMALL LETTER CHI #
+2CAD ; 03C7 ; MA # ( ⲭ → χ ) COPTIC SMALL LETTER KHI → GREEK SMALL LETTER CHI #
+
+1D6D9 ; 03C8 ; MA # ( 𝛙 → ψ ) MATHEMATICAL BOLD SMALL PSI → GREEK SMALL LETTER PSI #
+1D713 ; 03C8 ; MA # ( 𝜓 → ψ ) MATHEMATICAL ITALIC SMALL PSI → GREEK SMALL LETTER PSI #
+1D74D ; 03C8 ; MA # ( 𝝍 → ψ ) MATHEMATICAL BOLD ITALIC SMALL PSI → GREEK SMALL LETTER PSI #
+1D787 ; 03C8 ; MA # ( 𝞇 → ψ ) MATHEMATICAL SANS-SERIF BOLD SMALL PSI → GREEK SMALL LETTER PSI #
+1D7C1 ; 03C8 ; MA # ( 𝟁 → ψ ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI → GREEK SMALL LETTER PSI #
+0471 ; 03C8 ; MA # ( ѱ → ψ ) CYRILLIC SMALL LETTER PSI → GREEK SMALL LETTER PSI #
+104F9 ; 03C8 ; MA # ( 𐓹 → ψ ) OSAGE SMALL LETTER GHA → GREEK SMALL LETTER PSI #
+
+1D6BF ; 03A8 ; MA # ( 𝚿 → Ψ ) MATHEMATICAL BOLD CAPITAL PSI → GREEK CAPITAL LETTER PSI #
+1D6F9 ; 03A8 ; MA # ( 𝛹 → Ψ ) MATHEMATICAL ITALIC CAPITAL PSI → GREEK CAPITAL LETTER PSI #
+1D733 ; 03A8 ; MA # ( 𝜳 → Ψ ) MATHEMATICAL BOLD ITALIC CAPITAL PSI → GREEK CAPITAL LETTER PSI #
+1D76D ; 03A8 ; MA # ( 𝝭 → Ψ ) MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI → GREEK CAPITAL LETTER PSI #
+1D7A7 ; 03A8 ; MA # ( 𝞧 → Ψ ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI → GREEK CAPITAL LETTER PSI #
+2CAE ; 03A8 ; MA # ( Ⲯ → Ψ ) COPTIC CAPITAL LETTER PSI → GREEK CAPITAL LETTER PSI #
+0470 ; 03A8 ; MA # ( Ѱ → Ψ ) CYRILLIC CAPITAL LETTER PSI → GREEK CAPITAL LETTER PSI #
+104D1 ; 03A8 ; MA # ( 𐓑 → Ψ ) OSAGE CAPITAL LETTER GHA → GREEK CAPITAL LETTER PSI #
+16D8 ; 03A8 ; MA # ( ᛘ → Ψ ) RUNIC LETTER LONG-BRANCH-MADR M → GREEK CAPITAL LETTER PSI #
+102B5 ; 03A8 ; MA # ( 𐊵 → Ψ ) CARIAN LETTER N → GREEK CAPITAL LETTER PSI #
+
+2375 ; 03C9 ; MA #* ( ⍵ → ω ) APL FUNCTIONAL SYMBOL OMEGA → GREEK SMALL LETTER OMEGA #
+A7B7 ; 03C9 ; MA # ( ꞷ → ω ) LATIN SMALL LETTER OMEGA → GREEK SMALL LETTER OMEGA #
+1D6DA ; 03C9 ; MA # ( 𝛚 → ω ) MATHEMATICAL BOLD SMALL OMEGA → GREEK SMALL LETTER OMEGA #
+1D714 ; 03C9 ; MA # ( 𝜔 → ω ) MATHEMATICAL ITALIC SMALL OMEGA → GREEK SMALL LETTER OMEGA #
+1D74E ; 03C9 ; MA # ( 𝝎 → ω ) MATHEMATICAL BOLD ITALIC SMALL OMEGA → GREEK SMALL LETTER OMEGA #
+1D788 ; 03C9 ; MA # ( 𝞈 → ω ) MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA → GREEK SMALL LETTER OMEGA #
+1D7C2 ; 03C9 ; MA # ( 𝟂 → ω ) MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA → GREEK SMALL LETTER OMEGA #
+2CB1 ; 03C9 ; MA # ( ⲱ → ω ) COPTIC SMALL LETTER OOU → GREEK SMALL LETTER OMEGA #
+A64D ; 03C9 ; MA # ( ꙍ → ω ) CYRILLIC SMALL LETTER BROAD OMEGA → GREEK SMALL LETTER OMEGA # →ꞷ→
+
+2126 ; 03A9 ; MA # ( Ω → Ω ) OHM SIGN → GREEK CAPITAL LETTER OMEGA #
+1D6C0 ; 03A9 ; MA # ( 𝛀 → Ω ) MATHEMATICAL BOLD CAPITAL OMEGA → GREEK CAPITAL LETTER OMEGA #
+1D6FA ; 03A9 ; MA # ( 𝛺 → Ω ) MATHEMATICAL ITALIC CAPITAL OMEGA → GREEK CAPITAL LETTER OMEGA #
+1D734 ; 03A9 ; MA # ( 𝜴 → Ω ) MATHEMATICAL BOLD ITALIC CAPITAL OMEGA → GREEK CAPITAL LETTER OMEGA #
+1D76E ; 03A9 ; MA # ( 𝝮 → Ω ) MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA → GREEK CAPITAL LETTER OMEGA #
+1D7A8 ; 03A9 ; MA # ( 𝞨 → Ω ) MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA → GREEK CAPITAL LETTER OMEGA #
+162F ; 03A9 ; MA # ( ᘯ → Ω ) CANADIAN SYLLABICS CARRIER LHO → GREEK CAPITAL LETTER OMEGA #
+1635 ; 03A9 ; MA # ( ᘵ → Ω ) CANADIAN SYLLABICS CARRIER TLHO → GREEK CAPITAL LETTER OMEGA # →ᘯ→
+102B6 ; 03A9 ; MA # ( 𐊶 → Ω ) CARIAN LETTER TT2 → GREEK CAPITAL LETTER OMEGA #
+
+2379 ; 03C9 0332 ; MA #* ( ⍹ → ω̲ ) APL FUNCTIONAL SYMBOL OMEGA UNDERBAR → GREEK SMALL LETTER OMEGA, COMBINING LOW LINE #
+
+1F7D ; 1FF4 ; MA # ( ώ → ῴ ) GREEK SMALL LETTER OMEGA WITH OXIA → GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI #
+
+2630 ; 2CB6 ; MA #* ( ☰ → Ⲷ ) TRIGRAM FOR HEAVEN → COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE #
+
+2CDC ; 03EC ; MA # ( Ⳝ → Ϭ ) COPTIC CAPITAL LETTER OLD NUBIAN SHIMA → COPTIC CAPITAL LETTER SHIMA #
+
+0497 ; 0436 0329 ; MA # ( җ → ж̩ ) CYRILLIC SMALL LETTER ZHE WITH DESCENDER → CYRILLIC SMALL LETTER ZHE, COMBINING VERTICAL LINE BELOW #
+
+0496 ; 0416 0329 ; MA # ( Җ → Ж̩ ) CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER → CYRILLIC CAPITAL LETTER ZHE, COMBINING VERTICAL LINE BELOW #
+
+1D20B ; 0418 ; MA #* ( 𝈋 → И ) GREEK VOCAL NOTATION SYMBOL-12 → CYRILLIC CAPITAL LETTER I # →Ͷ→
+0376 ; 0418 ; MA # ( Ͷ → И ) GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA → CYRILLIC CAPITAL LETTER I #
+A6A1 ; 0418 ; MA # ( ꚡ → И ) BAMUM LETTER KA → CYRILLIC CAPITAL LETTER I # →Ͷ→
+10425 ; 0418 ; MA # ( 𐐥 → И ) DESERET CAPITAL LETTER ENG → CYRILLIC CAPITAL LETTER I #
+
+0419 ; 040D ; MA # ( Й → Ѝ ) CYRILLIC CAPITAL LETTER SHORT I → CYRILLIC CAPITAL LETTER I WITH GRAVE #
+
+048A ; 040D 0326 ; MA # ( Ҋ → Ѝ̦ ) CYRILLIC CAPITAL LETTER SHORT I WITH TAIL → CYRILLIC CAPITAL LETTER I WITH GRAVE, COMBINING COMMA BELOW # →Й̡→
+
+045D ; 0439 ; MA # ( ѝ → й ) CYRILLIC SMALL LETTER I WITH GRAVE → CYRILLIC SMALL LETTER SHORT I #
+
+048B ; 0439 0326 ; MA # ( ҋ → й̦ ) CYRILLIC SMALL LETTER SHORT I WITH TAIL → CYRILLIC SMALL LETTER SHORT I, COMBINING COMMA BELOW # →й̡→
+
+104BC ; 04C3 ; MA # ( 𐒼 → Ӄ ) OSAGE CAPITAL LETTER KA → CYRILLIC CAPITAL LETTER KA WITH HOOK #
+
+1D2B ; 043B ; MA # ( ᴫ → л ) CYRILLIC LETTER SMALL CAPITAL EL → CYRILLIC SMALL LETTER EL #
+
+04C6 ; 043B 0326 ; MA # ( ӆ → л̦ ) CYRILLIC SMALL LETTER EL WITH TAIL → CYRILLIC SMALL LETTER EL, COMBINING COMMA BELOW # →л̡→
+
+AB60 ; 0459 ; MA # ( ꭠ → љ ) LATIN SMALL LETTER SAKHA YAT → CYRILLIC SMALL LETTER LJE #
+
+104EB ; A669 ; MA # ( 𐓫 → ꙩ ) OSAGE SMALL LETTER OIN → CYRILLIC SMALL LETTER MONOCULAR O #
+
+1DEE ; 2DEC ; MA # ( ᷮ → ⷬ ) COMBINING LATIN SMALL LETTER P → COMBINING CYRILLIC LETTER ER #
+
+104CD ; 040B ; MA # ( 𐓍 → Ћ ) OSAGE CAPITAL LETTER DHA → CYRILLIC CAPITAL LETTER TSHE #
+
+1D202 ; 04FE ; MA #* ( 𝈂 → Ӿ ) GREEK VOCAL NOTATION SYMBOL-3 → CYRILLIC CAPITAL LETTER HA WITH STROKE #
+
+1D222 ; 0460 ; MA #* ( 𝈢 → Ѡ ) GREEK INSTRUMENTAL NOTATION SYMBOL-8 → CYRILLIC CAPITAL LETTER OMEGA #
+13C7 ; 0460 ; MA # ( Ꮗ → Ѡ ) CHEROKEE LETTER QUE → CYRILLIC CAPITAL LETTER OMEGA #
+15EF ; 0460 ; MA # ( ᗯ → Ѡ ) CANADIAN SYLLABICS CARRIER GU → CYRILLIC CAPITAL LETTER OMEGA #
+
+047C ; 0460 0486 0487 ; MA # ( Ѽ → Ѡ҆҇ ) CYRILLIC CAPITAL LETTER OMEGA WITH TITLO → CYRILLIC CAPITAL LETTER OMEGA, COMBINING CYRILLIC PSILI PNEUMATA, COMBINING CYRILLIC POKRYTIE #
+
+18ED ; 0460 00B7 ; MA # ( ᣭ → Ѡ· ) CANADIAN SYLLABICS CARRIER GWU → CYRILLIC CAPITAL LETTER OMEGA, MIDDLE DOT # →ᗯᐧ→
+
+A7B6 ; A64C ; MA # ( Ꞷ → Ꙍ ) LATIN CAPITAL LETTER OMEGA → CYRILLIC CAPITAL LETTER BROAD OMEGA #
+
+04CC ; 04B7 ; MA # ( ӌ → ҷ ) CYRILLIC SMALL LETTER KHAKASSIAN CHE → CYRILLIC SMALL LETTER CHE WITH DESCENDER #
+
+04CB ; 04B6 ; MA # ( Ӌ → Ҷ ) CYRILLIC CAPITAL LETTER KHAKASSIAN CHE → CYRILLIC CAPITAL LETTER CHE WITH DESCENDER #
+
+04BE ; 04BC 0328 ; MA # ( Ҿ → Ҽ̨ ) CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER → CYRILLIC CAPITAL LETTER ABKHASIAN CHE, COMBINING OGONEK #
+
+2CBD ; 0448 ; MA # ( ⲽ → ш ) COPTIC SMALL LETTER CRYPTOGRAMMIC NI → CYRILLIC SMALL LETTER SHA #
+
+2CBC ; 0428 ; MA # ( Ⲽ → Ш ) COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI → CYRILLIC CAPITAL LETTER SHA #
+
+A650 ; 042A 006C ; MA # ( Ꙑ → Ъl ) CYRILLIC CAPITAL LETTER YERU WITH BACK YER → CYRILLIC CAPITAL LETTER HARD SIGN, LATIN SMALL LETTER L # →ЪІ→
+
+2108 ; 042D ; MA #* ( ℈ → Э ) SCRUPLE → CYRILLIC CAPITAL LETTER E #
+
+1F701 ; A658 ; MA #* ( 🜁 → Ꙙ ) ALCHEMICAL SYMBOL FOR AIR → CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS #
+16F1C ; A658 ; MA # ( 𖼜 → Ꙙ ) MIAO LETTER TLHYA → CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS #
+
+A992 ; 2C3F ; MA # ( ꦒ → ⰿ ) JAVANESE LETTER GA → GLAGOLITIC SMALL LETTER MYSLITE #
+
+0587 ; 0565 0582 ; MA # ( և → եւ ) ARMENIAN SMALL LIGATURE ECH YIWN → ARMENIAN SMALL LETTER ECH, ARMENIAN SMALL LETTER YIWN #
+
+1294 ; 0571 ; MA # ( ኔ → ձ ) ETHIOPIC SYLLABLE NEE → ARMENIAN SMALL LETTER JA #
+
+FB14 ; 0574 0565 ; MA # ( ﬔ → մե ) ARMENIAN SMALL LIGATURE MEN ECH → ARMENIAN SMALL LETTER MEN, ARMENIAN SMALL LETTER ECH #
+
+FB15 ; 0574 056B ; MA # ( ﬕ → մի ) ARMENIAN SMALL LIGATURE MEN INI → ARMENIAN SMALL LETTER MEN, ARMENIAN SMALL LETTER INI #
+
+FB17 ; 0574 056D ; MA # ( ﬗ → մխ ) ARMENIAN SMALL LIGATURE MEN XEH → ARMENIAN SMALL LETTER MEN, ARMENIAN SMALL LETTER XEH #
+
+FB13 ; 0574 0576 ; MA # ( ﬓ → մն ) ARMENIAN SMALL LIGATURE MEN NOW → ARMENIAN SMALL LETTER MEN, ARMENIAN SMALL LETTER NOW #
+
+2229 ; 0548 ; MA #* ( ∩ → Ո ) INTERSECTION → ARMENIAN CAPITAL LETTER VO # →ᑎ→
+22C2 ; 0548 ; MA #* ( ⋂ → Ո ) N-ARY INTERSECTION → ARMENIAN CAPITAL LETTER VO # →∩→→ᑎ→
+1D245 ; 0548 ; MA #* ( 𝉅 → Ո ) GREEK MUSICAL LEIMMA → ARMENIAN CAPITAL LETTER VO # →∩→→ᑎ→
+1260 ; 0548 ; MA # ( በ → Ո ) ETHIOPIC SYLLABLE BA → ARMENIAN CAPITAL LETTER VO #
+144E ; 0548 ; MA # ( ᑎ → Ո ) CANADIAN SYLLABICS TI → ARMENIAN CAPITAL LETTER VO #
+A4F5 ; 0548 ; MA # ( ꓵ → Ո ) LISU LETTER UE → ARMENIAN CAPITAL LETTER VO # →∩→→ᑎ→
+
+145A ; 0548 00B7 ; MA # ( ᑚ → Ո· ) CANADIAN SYLLABICS WEST-CREE TWI → ARMENIAN CAPITAL LETTER VO, MIDDLE DOT # →ᑎᐧ→→ᑎ·→
+
+1468 ; 0548 0027 ; MA # ( ᑨ → Ո' ) CANADIAN SYLLABICS TTI → ARMENIAN CAPITAL LETTER VO, APOSTROPHE # →ᑎᑊ→→ᑎ'→
+
+FB16 ; 057E 0576 ; MA # ( ﬖ → վն ) ARMENIAN SMALL LIGATURE VEW NOW → ARMENIAN SMALL LETTER VEW, ARMENIAN SMALL LETTER NOW #
+
+20BD ; 0554 ; MA #* ( ₽ → Ք ) RUBLE SIGN → ARMENIAN CAPITAL LETTER KEH #
+
+02D3 ; 0559 ; MA #* ( ˓ → ՙ ) MODIFIER LETTER CENTRED LEFT HALF RING → ARMENIAN MODIFIER LETTER LEFT HALF RING #
+02BF ; 0559 ; MA # ( ʿ → ՙ ) MODIFIER LETTER LEFT HALF RING → ARMENIAN MODIFIER LETTER LEFT HALF RING #
+
+2135 ; 05D0 ; MA # ( ℵ → ‎א‎ ) ALEF SYMBOL → HEBREW LETTER ALEF #
+FB21 ; 05D0 ; MA # ( ‎ﬡ‎ → ‎א‎ ) HEBREW LETTER WIDE ALEF → HEBREW LETTER ALEF #
+
+FB2F ; FB2E ; MA # ( ‎אָ‎ → ‎אַ‎ ) HEBREW LETTER ALEF WITH QAMATS → HEBREW LETTER ALEF WITH PATAH #
+FB30 ; FB2E ; MA # ( ‎אּ‎ → ‎אַ‎ ) HEBREW LETTER ALEF WITH MAPIQ → HEBREW LETTER ALEF WITH PATAH #
+
+FB4F ; 05D0 05DC ; MA # ( ‎ﭏ‎ → ‎אל‎ ) HEBREW LIGATURE ALEF LAMED → HEBREW LETTER ALEF, HEBREW LETTER LAMED #
+
+2136 ; 05D1 ; MA # ( ℶ → ‎ב‎ ) BET SYMBOL → HEBREW LETTER BET #
+
+2137 ; 05D2 ; MA # ( ℷ → ‎ג‎ ) GIMEL SYMBOL → HEBREW LETTER GIMEL #
+
+2138 ; 05D3 ; MA # ( ℸ → ‎ד‎ ) DALET SYMBOL → HEBREW LETTER DALET #
+FB22 ; 05D3 ; MA # ( ‎ﬢ‎ → ‎ד‎ ) HEBREW LETTER WIDE DALET → HEBREW LETTER DALET #
+
+FB23 ; 05D4 ; MA # ( ‎ﬣ‎ → ‎ה‎ ) HEBREW LETTER WIDE HE → HEBREW LETTER HE #
+
+FB39 ; FB1D ; MA # ( ‎יּ‎ → ‎יִ‎ ) HEBREW LETTER YOD WITH DAGESH → HEBREW LETTER YOD WITH HIRIQ #
+
+FB24 ; 05DB ; MA # ( ‎ﬤ‎ → ‎כ‎ ) HEBREW LETTER WIDE KAF → HEBREW LETTER KAF #
+
+FB25 ; 05DC ; MA # ( ‎ﬥ‎ → ‎ל‎ ) HEBREW LETTER WIDE LAMED → HEBREW LETTER LAMED #
+
+FB26 ; 05DD ; MA # ( ‎ﬦ‎ → ‎ם‎ ) HEBREW LETTER WIDE FINAL MEM → HEBREW LETTER FINAL MEM #
+
+FB20 ; 05E2 ; MA # ( ‎ﬠ‎ → ‎ע‎ ) HEBREW LETTER ALTERNATIVE AYIN → HEBREW LETTER AYIN #
+
+FB27 ; 05E8 ; MA # ( ‎ﬧ‎ → ‎ר‎ ) HEBREW LETTER WIDE RESH → HEBREW LETTER RESH #
+
+FB2B ; FB2A ; MA # ( ‎שׂ‎ → ‎שׁ‎ ) HEBREW LETTER SHIN WITH SIN DOT → HEBREW LETTER SHIN WITH SHIN DOT #
+FB49 ; FB2A ; MA # ( ‎שּ‎ → ‎שׁ‎ ) HEBREW LETTER SHIN WITH DAGESH → HEBREW LETTER SHIN WITH SHIN DOT #
+
+FB2D ; FB2C ; MA # ( ‎שּׂ‎ → ‎שּׁ‎ ) HEBREW LETTER SHIN WITH DAGESH AND SIN DOT → HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT #
+
+FB28 ; 05EA ; MA # ( ‎ﬨ‎ → ‎ת‎ ) HEBREW LETTER WIDE TAV → HEBREW LETTER TAV #
+
+FE80 ; 0621 ; MA # ( ‎ﺀ‎ → ‎ء‎ ) ARABIC LETTER HAMZA ISOLATED FORM → ARABIC LETTER HAMZA #
+
+06FD ; 0621 0348 ; MA #* ( ‎۽‎ → ‎ء͈‎ ) ARABIC SIGN SINDHI AMPERSAND → ARABIC LETTER HAMZA, COMBINING DOUBLE VERTICAL LINE BELOW #
+
+FE82 ; 0622 ; MA # ( ‎ﺂ‎ → ‎آ‎ ) ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM → ARABIC LETTER ALEF WITH MADDA ABOVE #
+FE81 ; 0622 ; MA # ( ‎ﺁ‎ → ‎آ‎ ) ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM → ARABIC LETTER ALEF WITH MADDA ABOVE #
+
+FB51 ; 0671 ; MA # ( ‎ﭑ‎ → ‎ٱ‎ ) ARABIC LETTER ALEF WASLA FINAL FORM → ARABIC LETTER ALEF WASLA #
+FB50 ; 0671 ; MA # ( ‎ﭐ‎ → ‎ٱ‎ ) ARABIC LETTER ALEF WASLA ISOLATED FORM → ARABIC LETTER ALEF WASLA #
+
+1EE01 ; 0628 ; MA # ( ‎𞸁‎ → ‎ب‎ ) ARABIC MATHEMATICAL BEH → ARABIC LETTER BEH #
+1EE21 ; 0628 ; MA # ( ‎𞸡‎ → ‎ب‎ ) ARABIC MATHEMATICAL INITIAL BEH → ARABIC LETTER BEH #
+1EE61 ; 0628 ; MA # ( ‎𞹡‎ → ‎ب‎ ) ARABIC MATHEMATICAL STRETCHED BEH → ARABIC LETTER BEH #
+1EE81 ; 0628 ; MA # ( ‎𞺁‎ → ‎ب‎ ) ARABIC MATHEMATICAL LOOPED BEH → ARABIC LETTER BEH #
+1EEA1 ; 0628 ; MA # ( ‎𞺡‎ → ‎ب‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK BEH → ARABIC LETTER BEH #
+FE91 ; 0628 ; MA # ( ‎ﺑ‎ → ‎ب‎ ) ARABIC LETTER BEH INITIAL FORM → ARABIC LETTER BEH #
+FE92 ; 0628 ; MA # ( ‎ﺒ‎ → ‎ب‎ ) ARABIC LETTER BEH MEDIAL FORM → ARABIC LETTER BEH #
+FE90 ; 0628 ; MA # ( ‎ﺐ‎ → ‎ب‎ ) ARABIC LETTER BEH FINAL FORM → ARABIC LETTER BEH #
+FE8F ; 0628 ; MA # ( ‎ﺏ‎ → ‎ب‎ ) ARABIC LETTER BEH ISOLATED FORM → ARABIC LETTER BEH #
+
+0751 ; 0628 06DB ; MA # ( ‎ݑ‎ → ‎بۛ‎ ) ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE → ARABIC LETTER BEH, ARABIC SMALL HIGH THREE DOTS #
+
+08B6 ; 0628 06E2 ; MA # ( ‎ࢶ‎ → ‎بۢ‎ ) ARABIC LETTER BEH WITH SMALL MEEM ABOVE → ARABIC LETTER BEH, ARABIC SMALL HIGH MEEM ISOLATED FORM #
+
+08A1 ; 0628 0654 ; MA # ( ‎ࢡ‎ → ‎بٔ‎ ) ARABIC LETTER BEH WITH HAMZA ABOVE → ARABIC LETTER BEH, ARABIC HAMZA ABOVE #
+
+FCA0 ; 0628 006F ; MA # ( ‎ﲠ‎ → ‎بo‎ ) ARABIC LIGATURE BEH WITH HEH INITIAL FORM → ARABIC LETTER BEH, LATIN SMALL LETTER O # →‎به‎→
+FCE2 ; 0628 006F ; MA # ( ‎ﳢ‎ → ‎بo‎ ) ARABIC LIGATURE BEH WITH HEH MEDIAL FORM → ARABIC LETTER BEH, LATIN SMALL LETTER O # →‎به‎→
+
+FC9C ; 0628 062C ; MA # ( ‎ﲜ‎ → ‎بج‎ ) ARABIC LIGATURE BEH WITH JEEM INITIAL FORM → ARABIC LETTER BEH, ARABIC LETTER JEEM #
+FC05 ; 0628 062C ; MA # ( ‎ﰅ‎ → ‎بج‎ ) ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER JEEM #
+
+FC9D ; 0628 062D ; MA # ( ‎ﲝ‎ → ‎بح‎ ) ARABIC LIGATURE BEH WITH HAH INITIAL FORM → ARABIC LETTER BEH, ARABIC LETTER HAH #
+FC06 ; 0628 062D ; MA # ( ‎ﰆ‎ → ‎بح‎ ) ARABIC LIGATURE BEH WITH HAH ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER HAH #
+
+FDC2 ; 0628 062D 0649 ; MA # ( ‎ﷂ‎ → ‎بحى‎ ) ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎بحي‎→
+
+FC9E ; 0628 062E ; MA # ( ‎ﲞ‎ → ‎بخ‎ ) ARABIC LIGATURE BEH WITH KHAH INITIAL FORM → ARABIC LETTER BEH, ARABIC LETTER KHAH #
+FC07 ; 0628 062E ; MA # ( ‎ﰇ‎ → ‎بخ‎ ) ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER KHAH #
+FCD2 ; 0628 062E ; MA # ( ‎ﳒ‎ → ‎بخ‎ ) ARABIC LIGATURE NOON WITH JEEM INITIAL FORM → ARABIC LETTER BEH, ARABIC LETTER KHAH # →‎ﲞ‎→
+FC4B ; 0628 062E ; MA # ( ‎ﱋ‎ → ‎بخ‎ ) ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER KHAH # →‎نج‎→→‎ﳒ‎→→‎ﲞ‎→
+
+FD9E ; 0628 062E 0649 ; MA # ( ‎ﶞ‎ → ‎بخى‎ ) ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎بخي‎→
+
+FC6A ; 0628 0631 ; MA # ( ‎ﱪ‎ → ‎بر‎ ) ARABIC LIGATURE BEH WITH REH FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER REH #
+
+FC6B ; 0628 0632 ; MA # ( ‎ﱫ‎ → ‎بز‎ ) ARABIC LIGATURE BEH WITH ZAIN FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER ZAIN #
+
+FC9F ; 0628 0645 ; MA # ( ‎ﲟ‎ → ‎بم‎ ) ARABIC LIGATURE BEH WITH MEEM INITIAL FORM → ARABIC LETTER BEH, ARABIC LETTER MEEM #
+FCE1 ; 0628 0645 ; MA # ( ‎ﳡ‎ → ‎بم‎ ) ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM → ARABIC LETTER BEH, ARABIC LETTER MEEM #
+FC6C ; 0628 0645 ; MA # ( ‎ﱬ‎ → ‎بم‎ ) ARABIC LIGATURE BEH WITH MEEM FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER MEEM #
+FC08 ; 0628 0645 ; MA # ( ‎ﰈ‎ → ‎بم‎ ) ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER MEEM #
+
+FC6D ; 0628 0646 ; MA # ( ‎ﱭ‎ → ‎بن‎ ) ARABIC LIGATURE BEH WITH NOON FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER NOON #
+
+FC6E ; 0628 0649 ; MA # ( ‎ﱮ‎ → ‎بى‎ ) ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER ALEF MAKSURA #
+FC09 ; 0628 0649 ; MA # ( ‎ﰉ‎ → ‎بى‎ ) ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER ALEF MAKSURA #
+FC6F ; 0628 0649 ; MA # ( ‎ﱯ‎ → ‎بى‎ ) ARABIC LIGATURE BEH WITH YEH FINAL FORM → ARABIC LETTER BEH, ARABIC LETTER ALEF MAKSURA # →‎بي‎→
+FC0A ; 0628 0649 ; MA # ( ‎ﰊ‎ → ‎بى‎ ) ARABIC LIGATURE BEH WITH YEH ISOLATED FORM → ARABIC LETTER BEH, ARABIC LETTER ALEF MAKSURA # →‎بي‎→
+
+FB54 ; 067B ; MA # ( ‎ﭔ‎ → ‎ٻ‎ ) ARABIC LETTER BEEH INITIAL FORM → ARABIC LETTER BEEH #
+FB55 ; 067B ; MA # ( ‎ﭕ‎ → ‎ٻ‎ ) ARABIC LETTER BEEH MEDIAL FORM → ARABIC LETTER BEEH #
+FB53 ; 067B ; MA # ( ‎ﭓ‎ → ‎ٻ‎ ) ARABIC LETTER BEEH FINAL FORM → ARABIC LETTER BEEH #
+FB52 ; 067B ; MA # ( ‎ﭒ‎ → ‎ٻ‎ ) ARABIC LETTER BEEH ISOLATED FORM → ARABIC LETTER BEEH #
+06D0 ; 067B ; MA # ( ‎ې‎ → ‎ٻ‎ ) ARABIC LETTER E → ARABIC LETTER BEEH #
+FBE6 ; 067B ; MA # ( ‎ﯦ‎ → ‎ٻ‎ ) ARABIC LETTER E INITIAL FORM → ARABIC LETTER BEEH # →‎ې‎→
+FBE7 ; 067B ; MA # ( ‎ﯧ‎ → ‎ٻ‎ ) ARABIC LETTER E MEDIAL FORM → ARABIC LETTER BEEH # →‎ې‎→
+FBE5 ; 067B ; MA # ( ‎ﯥ‎ → ‎ٻ‎ ) ARABIC LETTER E FINAL FORM → ARABIC LETTER BEEH # →‎ې‎→
+FBE4 ; 067B ; MA # ( ‎ﯤ‎ → ‎ٻ‎ ) ARABIC LETTER E ISOLATED FORM → ARABIC LETTER BEEH # →‎ې‎→
+
+FB5C ; 0680 ; MA # ( ‎ﭜ‎ → ‎ڀ‎ ) ARABIC LETTER BEHEH INITIAL FORM → ARABIC LETTER BEHEH #
+FB5D ; 0680 ; MA # ( ‎ﭝ‎ → ‎ڀ‎ ) ARABIC LETTER BEHEH MEDIAL FORM → ARABIC LETTER BEHEH #
+FB5B ; 0680 ; MA # ( ‎ﭛ‎ → ‎ڀ‎ ) ARABIC LETTER BEHEH FINAL FORM → ARABIC LETTER BEHEH #
+FB5A ; 0680 ; MA # ( ‎ﭚ‎ → ‎ڀ‎ ) ARABIC LETTER BEHEH ISOLATED FORM → ARABIC LETTER BEHEH #
+
+08A9 ; 0754 ; MA # ( ‎ࢩ‎ → ‎ݔ‎ ) ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE → ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE #
+0767 ; 0754 ; MA # ( ‎ݧ‎ → ‎ݔ‎ ) ARABIC LETTER NOON WITH TWO DOTS BELOW → ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE #
+
+2365 ; 0629 ; MA #* ( ⍥ → ‎ة‎ ) APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS → ARABIC LETTER TEH MARBUTA # →ö→
+00F6 ; 0629 ; MA # ( ö → ‎ة‎ ) LATIN SMALL LETTER O WITH DIAERESIS → ARABIC LETTER TEH MARBUTA #
+FE94 ; 0629 ; MA # ( ‎ﺔ‎ → ‎ة‎ ) ARABIC LETTER TEH MARBUTA FINAL FORM → ARABIC LETTER TEH MARBUTA #
+FE93 ; 0629 ; MA # ( ‎ﺓ‎ → ‎ة‎ ) ARABIC LETTER TEH MARBUTA ISOLATED FORM → ARABIC LETTER TEH MARBUTA #
+06C3 ; 0629 ; MA # ( ‎ۃ‎ → ‎ة‎ ) ARABIC LETTER TEH MARBUTA GOAL → ARABIC LETTER TEH MARBUTA #
+
+1EE15 ; 062A ; MA # ( ‎𞸕‎ → ‎ت‎ ) ARABIC MATHEMATICAL TEH → ARABIC LETTER TEH #
+1EE35 ; 062A ; MA # ( ‎𞸵‎ → ‎ت‎ ) ARABIC MATHEMATICAL INITIAL TEH → ARABIC LETTER TEH #
+1EE75 ; 062A ; MA # ( ‎𞹵‎ → ‎ت‎ ) ARABIC MATHEMATICAL STRETCHED TEH → ARABIC LETTER TEH #
+1EE95 ; 062A ; MA # ( ‎𞺕‎ → ‎ت‎ ) ARABIC MATHEMATICAL LOOPED TEH → ARABIC LETTER TEH #
+1EEB5 ; 062A ; MA # ( ‎𞺵‎ → ‎ت‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK TEH → ARABIC LETTER TEH #
+FE97 ; 062A ; MA # ( ‎ﺗ‎ → ‎ت‎ ) ARABIC LETTER TEH INITIAL FORM → ARABIC LETTER TEH #
+FE98 ; 062A ; MA # ( ‎ﺘ‎ → ‎ت‎ ) ARABIC LETTER TEH MEDIAL FORM → ARABIC LETTER TEH #
+FE96 ; 062A ; MA # ( ‎ﺖ‎ → ‎ت‎ ) ARABIC LETTER TEH FINAL FORM → ARABIC LETTER TEH #
+FE95 ; 062A ; MA # ( ‎ﺕ‎ → ‎ت‎ ) ARABIC LETTER TEH ISOLATED FORM → ARABIC LETTER TEH #
+
+FCA5 ; 062A 006F ; MA # ( ‎ﲥ‎ → ‎تo‎ ) ARABIC LIGATURE TEH WITH HEH INITIAL FORM → ARABIC LETTER TEH, LATIN SMALL LETTER O # →‎ته‎→
+FCE4 ; 062A 006F ; MA # ( ‎ﳤ‎ → ‎تo‎ ) ARABIC LIGATURE TEH WITH HEH MEDIAL FORM → ARABIC LETTER TEH, LATIN SMALL LETTER O # →‎ته‎→
+
+FCA1 ; 062A 062C ; MA # ( ‎ﲡ‎ → ‎تج‎ ) ARABIC LIGATURE TEH WITH JEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER JEEM #
+FC0B ; 062A 062C ; MA # ( ‎ﰋ‎ → ‎تج‎ ) ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER JEEM #
+
+FD50 ; 062A 062C 0645 ; MA # ( ‎ﵐ‎ → ‎تجم‎ ) ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FDA0 ; 062A 062C 0649 ; MA # ( ‎ﶠ‎ → ‎تجى‎ ) ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA #
+FD9F ; 062A 062C 0649 ; MA # ( ‎ﶟ‎ → ‎تجى‎ ) ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎تجي‎→
+
+FCA2 ; 062A 062D ; MA # ( ‎ﲢ‎ → ‎تح‎ ) ARABIC LIGATURE TEH WITH HAH INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER HAH #
+FC0C ; 062A 062D ; MA # ( ‎ﰌ‎ → ‎تح‎ ) ARABIC LIGATURE TEH WITH HAH ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER HAH #
+
+FD52 ; 062A 062D 062C ; MA # ( ‎ﵒ‎ → ‎تحج‎ ) ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER HAH, ARABIC LETTER JEEM #
+FD51 ; 062A 062D 062C ; MA # ( ‎ﵑ‎ → ‎تحج‎ ) ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER HAH, ARABIC LETTER JEEM #
+
+FD53 ; 062A 062D 0645 ; MA # ( ‎ﵓ‎ → ‎تحم‎ ) ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER HAH, ARABIC LETTER MEEM #
+
+FCA3 ; 062A 062E ; MA # ( ‎ﲣ‎ → ‎تخ‎ ) ARABIC LIGATURE TEH WITH KHAH INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER KHAH #
+FC0D ; 062A 062E ; MA # ( ‎ﰍ‎ → ‎تخ‎ ) ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER KHAH #
+
+FD54 ; 062A 062E 0645 ; MA # ( ‎ﵔ‎ → ‎تخم‎ ) ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FDA2 ; 062A 062E 0649 ; MA # ( ‎ﶢ‎ → ‎تخى‎ ) ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA #
+FDA1 ; 062A 062E 0649 ; MA # ( ‎ﶡ‎ → ‎تخى‎ ) ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎تخي‎→
+
+FC70 ; 062A 0631 ; MA # ( ‎ﱰ‎ → ‎تر‎ ) ARABIC LIGATURE TEH WITH REH FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER REH #
+
+FC71 ; 062A 0632 ; MA # ( ‎ﱱ‎ → ‎تز‎ ) ARABIC LIGATURE TEH WITH ZAIN FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER ZAIN #
+
+FCA4 ; 062A 0645 ; MA # ( ‎ﲤ‎ → ‎تم‎ ) ARABIC LIGATURE TEH WITH MEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM #
+FCE3 ; 062A 0645 ; MA # ( ‎ﳣ‎ → ‎تم‎ ) ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM #
+FC72 ; 062A 0645 ; MA # ( ‎ﱲ‎ → ‎تم‎ ) ARABIC LIGATURE TEH WITH MEEM FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM #
+FC0E ; 062A 0645 ; MA # ( ‎ﰎ‎ → ‎تم‎ ) ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM #
+
+FD55 ; 062A 0645 062C ; MA # ( ‎ﵕ‎ → ‎تمج‎ ) ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM, ARABIC LETTER JEEM #
+
+FD56 ; 062A 0645 062D ; MA # ( ‎ﵖ‎ → ‎تمح‎ ) ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FD57 ; 062A 0645 062E ; MA # ( ‎ﵗ‎ → ‎تمخ‎ ) ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM, ARABIC LETTER KHAH #
+
+FDA4 ; 062A 0645 0649 ; MA # ( ‎ﶤ‎ → ‎تمى‎ ) ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FDA3 ; 062A 0645 0649 ; MA # ( ‎ﶣ‎ → ‎تمى‎ ) ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎تمي‎→
+
+FC73 ; 062A 0646 ; MA # ( ‎ﱳ‎ → ‎تن‎ ) ARABIC LIGATURE TEH WITH NOON FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER NOON #
+
+FC74 ; 062A 0649 ; MA # ( ‎ﱴ‎ → ‎تى‎ ) ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER ALEF MAKSURA #
+FC0F ; 062A 0649 ; MA # ( ‎ﰏ‎ → ‎تى‎ ) ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER ALEF MAKSURA #
+FC75 ; 062A 0649 ; MA # ( ‎ﱵ‎ → ‎تى‎ ) ARABIC LIGATURE TEH WITH YEH FINAL FORM → ARABIC LETTER TEH, ARABIC LETTER ALEF MAKSURA # →‎تي‎→
+FC10 ; 062A 0649 ; MA # ( ‎ﰐ‎ → ‎تى‎ ) ARABIC LIGATURE TEH WITH YEH ISOLATED FORM → ARABIC LETTER TEH, ARABIC LETTER ALEF MAKSURA # →‎تي‎→
+
+FB60 ; 067A ; MA # ( ‎ﭠ‎ → ‎ٺ‎ ) ARABIC LETTER TTEHEH INITIAL FORM → ARABIC LETTER TTEHEH #
+FB61 ; 067A ; MA # ( ‎ﭡ‎ → ‎ٺ‎ ) ARABIC LETTER TTEHEH MEDIAL FORM → ARABIC LETTER TTEHEH #
+FB5F ; 067A ; MA # ( ‎ﭟ‎ → ‎ٺ‎ ) ARABIC LETTER TTEHEH FINAL FORM → ARABIC LETTER TTEHEH #
+FB5E ; 067A ; MA # ( ‎ﭞ‎ → ‎ٺ‎ ) ARABIC LETTER TTEHEH ISOLATED FORM → ARABIC LETTER TTEHEH #
+
+FB64 ; 067F ; MA # ( ‎ﭤ‎ → ‎ٿ‎ ) ARABIC LETTER TEHEH INITIAL FORM → ARABIC LETTER TEHEH #
+FB65 ; 067F ; MA # ( ‎ﭥ‎ → ‎ٿ‎ ) ARABIC LETTER TEHEH MEDIAL FORM → ARABIC LETTER TEHEH #
+FB63 ; 067F ; MA # ( ‎ﭣ‎ → ‎ٿ‎ ) ARABIC LETTER TEHEH FINAL FORM → ARABIC LETTER TEHEH #
+FB62 ; 067F ; MA # ( ‎ﭢ‎ → ‎ٿ‎ ) ARABIC LETTER TEHEH ISOLATED FORM → ARABIC LETTER TEHEH #
+
+1EE02 ; 062C ; MA # ( ‎𞸂‎ → ‎ج‎ ) ARABIC MATHEMATICAL JEEM → ARABIC LETTER JEEM #
+1EE22 ; 062C ; MA # ( ‎𞸢‎ → ‎ج‎ ) ARABIC MATHEMATICAL INITIAL JEEM → ARABIC LETTER JEEM #
+1EE42 ; 062C ; MA # ( ‎𞹂‎ → ‎ج‎ ) ARABIC MATHEMATICAL TAILED JEEM → ARABIC LETTER JEEM #
+1EE62 ; 062C ; MA # ( ‎𞹢‎ → ‎ج‎ ) ARABIC MATHEMATICAL STRETCHED JEEM → ARABIC LETTER JEEM #
+1EE82 ; 062C ; MA # ( ‎𞺂‎ → ‎ج‎ ) ARABIC MATHEMATICAL LOOPED JEEM → ARABIC LETTER JEEM #
+1EEA2 ; 062C ; MA # ( ‎𞺢‎ → ‎ج‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM → ARABIC LETTER JEEM #
+FE9F ; 062C ; MA # ( ‎ﺟ‎ → ‎ج‎ ) ARABIC LETTER JEEM INITIAL FORM → ARABIC LETTER JEEM #
+FEA0 ; 062C ; MA # ( ‎ﺠ‎ → ‎ج‎ ) ARABIC LETTER JEEM MEDIAL FORM → ARABIC LETTER JEEM #
+FE9E ; 062C ; MA # ( ‎ﺞ‎ → ‎ج‎ ) ARABIC LETTER JEEM FINAL FORM → ARABIC LETTER JEEM #
+FE9D ; 062C ; MA # ( ‎ﺝ‎ → ‎ج‎ ) ARABIC LETTER JEEM ISOLATED FORM → ARABIC LETTER JEEM #
+
+FCA7 ; 062C 062D ; MA # ( ‎ﲧ‎ → ‎جح‎ ) ARABIC LIGATURE JEEM WITH HAH INITIAL FORM → ARABIC LETTER JEEM, ARABIC LETTER HAH #
+FC15 ; 062C 062D ; MA # ( ‎ﰕ‎ → ‎جح‎ ) ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM → ARABIC LETTER JEEM, ARABIC LETTER HAH #
+
+FDA6 ; 062C 062D 0649 ; MA # ( ‎ﶦ‎ → ‎جحى‎ ) ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FDBE ; 062C 062D 0649 ; MA # ( ‎ﶾ‎ → ‎جحى‎ ) ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎جحي‎→
+
+FDFB ; 062C 0644 0020 062C 0644 006C 0644 006F ; MA #* ( ‎ﷻ‎ → ‎جل جلlلo‎ ) ARABIC LIGATURE JALLAJALALOUHOU → ARABIC LETTER JEEM, ARABIC LETTER LAM, SPACE, ARABIC LETTER JEEM, ARABIC LETTER LAM, LATIN SMALL LETTER L, ARABIC LETTER LAM, LATIN SMALL LETTER O # →‎جل جلاله‎→
+
+FCA8 ; 062C 0645 ; MA # ( ‎ﲨ‎ → ‎جم‎ ) ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+FC16 ; 062C 0645 ; MA # ( ‎ﰖ‎ → ‎جم‎ ) ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FD59 ; 062C 0645 062D ; MA # ( ‎ﵙ‎ → ‎جمح‎ ) ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FD58 ; 062C 0645 062D ; MA # ( ‎ﵘ‎ → ‎جمح‎ ) ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FDA7 ; 062C 0645 0649 ; MA # ( ‎ﶧ‎ → ‎جمى‎ ) ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FDA5 ; 062C 0645 0649 ; MA # ( ‎ﶥ‎ → ‎جمى‎ ) ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎جمي‎→
+
+FD1D ; 062C 0649 ; MA # ( ‎ﴝ‎ → ‎جى‎ ) ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA #
+FD01 ; 062C 0649 ; MA # ( ‎ﴁ‎ → ‎جى‎ ) ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA #
+FD1E ; 062C 0649 ; MA # ( ‎ﴞ‎ → ‎جى‎ ) ARABIC LIGATURE JEEM WITH YEH FINAL FORM → ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎جي‎→
+FD02 ; 062C 0649 ; MA # ( ‎ﴂ‎ → ‎جى‎ ) ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM → ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎جي‎→
+
+FB78 ; 0683 ; MA # ( ‎ﭸ‎ → ‎ڃ‎ ) ARABIC LETTER NYEH INITIAL FORM → ARABIC LETTER NYEH #
+FB79 ; 0683 ; MA # ( ‎ﭹ‎ → ‎ڃ‎ ) ARABIC LETTER NYEH MEDIAL FORM → ARABIC LETTER NYEH #
+FB77 ; 0683 ; MA # ( ‎ﭷ‎ → ‎ڃ‎ ) ARABIC LETTER NYEH FINAL FORM → ARABIC LETTER NYEH #
+FB76 ; 0683 ; MA # ( ‎ﭶ‎ → ‎ڃ‎ ) ARABIC LETTER NYEH ISOLATED FORM → ARABIC LETTER NYEH #
+
+FB74 ; 0684 ; MA # ( ‎ﭴ‎ → ‎ڄ‎ ) ARABIC LETTER DYEH INITIAL FORM → ARABIC LETTER DYEH #
+FB75 ; 0684 ; MA # ( ‎ﭵ‎ → ‎ڄ‎ ) ARABIC LETTER DYEH MEDIAL FORM → ARABIC LETTER DYEH #
+FB73 ; 0684 ; MA # ( ‎ﭳ‎ → ‎ڄ‎ ) ARABIC LETTER DYEH FINAL FORM → ARABIC LETTER DYEH #
+FB72 ; 0684 ; MA # ( ‎ﭲ‎ → ‎ڄ‎ ) ARABIC LETTER DYEH ISOLATED FORM → ARABIC LETTER DYEH #
+
+FB7C ; 0686 ; MA # ( ‎ﭼ‎ → ‎چ‎ ) ARABIC LETTER TCHEH INITIAL FORM → ARABIC LETTER TCHEH #
+FB7D ; 0686 ; MA # ( ‎ﭽ‎ → ‎چ‎ ) ARABIC LETTER TCHEH MEDIAL FORM → ARABIC LETTER TCHEH #
+FB7B ; 0686 ; MA # ( ‎ﭻ‎ → ‎چ‎ ) ARABIC LETTER TCHEH FINAL FORM → ARABIC LETTER TCHEH #
+FB7A ; 0686 ; MA # ( ‎ﭺ‎ → ‎چ‎ ) ARABIC LETTER TCHEH ISOLATED FORM → ARABIC LETTER TCHEH #
+
+FB80 ; 0687 ; MA # ( ‎ﮀ‎ → ‎ڇ‎ ) ARABIC LETTER TCHEHEH INITIAL FORM → ARABIC LETTER TCHEHEH #
+FB81 ; 0687 ; MA # ( ‎ﮁ‎ → ‎ڇ‎ ) ARABIC LETTER TCHEHEH MEDIAL FORM → ARABIC LETTER TCHEHEH #
+FB7F ; 0687 ; MA # ( ‎ﭿ‎ → ‎ڇ‎ ) ARABIC LETTER TCHEHEH FINAL FORM → ARABIC LETTER TCHEHEH #
+FB7E ; 0687 ; MA # ( ‎ﭾ‎ → ‎ڇ‎ ) ARABIC LETTER TCHEHEH ISOLATED FORM → ARABIC LETTER TCHEHEH #
+
+1EE07 ; 062D ; MA # ( ‎𞸇‎ → ‎ح‎ ) ARABIC MATHEMATICAL HAH → ARABIC LETTER HAH #
+1EE27 ; 062D ; MA # ( ‎𞸧‎ → ‎ح‎ ) ARABIC MATHEMATICAL INITIAL HAH → ARABIC LETTER HAH #
+1EE47 ; 062D ; MA # ( ‎𞹇‎ → ‎ح‎ ) ARABIC MATHEMATICAL TAILED HAH → ARABIC LETTER HAH #
+1EE67 ; 062D ; MA # ( ‎𞹧‎ → ‎ح‎ ) ARABIC MATHEMATICAL STRETCHED HAH → ARABIC LETTER HAH #
+1EE87 ; 062D ; MA # ( ‎𞺇‎ → ‎ح‎ ) ARABIC MATHEMATICAL LOOPED HAH → ARABIC LETTER HAH #
+1EEA7 ; 062D ; MA # ( ‎𞺧‎ → ‎ح‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK HAH → ARABIC LETTER HAH #
+FEA3 ; 062D ; MA # ( ‎ﺣ‎ → ‎ح‎ ) ARABIC LETTER HAH INITIAL FORM → ARABIC LETTER HAH #
+FEA4 ; 062D ; MA # ( ‎ﺤ‎ → ‎ح‎ ) ARABIC LETTER HAH MEDIAL FORM → ARABIC LETTER HAH #
+FEA2 ; 062D ; MA # ( ‎ﺢ‎ → ‎ح‎ ) ARABIC LETTER HAH FINAL FORM → ARABIC LETTER HAH #
+FEA1 ; 062D ; MA # ( ‎ﺡ‎ → ‎ح‎ ) ARABIC LETTER HAH ISOLATED FORM → ARABIC LETTER HAH #
+
+0685 ; 062D 06DB ; MA # ( ‎څ‎ → ‎حۛ‎ ) ARABIC LETTER HAH WITH THREE DOTS ABOVE → ARABIC LETTER HAH, ARABIC SMALL HIGH THREE DOTS #
+
+0681 ; 062D 0654 ; MA # ( ‎ځ‎ → ‎حٔ‎ ) ARABIC LETTER HAH WITH HAMZA ABOVE → ARABIC LETTER HAH, ARABIC HAMZA ABOVE #
+0772 ; 062D 0654 ; MA # ( ‎ݲ‎ → ‎حٔ‎ ) ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE → ARABIC LETTER HAH, ARABIC HAMZA ABOVE #
+
+FCA9 ; 062D 062C ; MA # ( ‎ﲩ‎ → ‎حج‎ ) ARABIC LIGATURE HAH WITH JEEM INITIAL FORM → ARABIC LETTER HAH, ARABIC LETTER JEEM #
+FC17 ; 062D 062C ; MA # ( ‎ﰗ‎ → ‎حج‎ ) ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM → ARABIC LETTER HAH, ARABIC LETTER JEEM #
+
+FDBF ; 062D 062C 0649 ; MA # ( ‎ﶿ‎ → ‎حجى‎ ) ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER HAH, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎حجي‎→
+
+FCAA ; 062D 0645 ; MA # ( ‎ﲪ‎ → ‎حم‎ ) ARABIC LIGATURE HAH WITH MEEM INITIAL FORM → ARABIC LETTER HAH, ARABIC LETTER MEEM #
+FC18 ; 062D 0645 ; MA # ( ‎ﰘ‎ → ‎حم‎ ) ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM → ARABIC LETTER HAH, ARABIC LETTER MEEM #
+
+FD5B ; 062D 0645 0649 ; MA # ( ‎ﵛ‎ → ‎حمى‎ ) ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER HAH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FD5A ; 062D 0645 0649 ; MA # ( ‎ﵚ‎ → ‎حمى‎ ) ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER HAH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎حمي‎→
+
+FD1B ; 062D 0649 ; MA # ( ‎ﴛ‎ → ‎حى‎ ) ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FCFF ; 062D 0649 ; MA # ( ‎ﳿ‎ → ‎حى‎ ) ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FD1C ; 062D 0649 ; MA # ( ‎ﴜ‎ → ‎حى‎ ) ARABIC LIGATURE HAH WITH YEH FINAL FORM → ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎حي‎→
+FD00 ; 062D 0649 ; MA # ( ‎ﴀ‎ → ‎حى‎ ) ARABIC LIGATURE HAH WITH YEH ISOLATED FORM → ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎حي‎→
+
+1EE17 ; 062E ; MA # ( ‎𞸗‎ → ‎خ‎ ) ARABIC MATHEMATICAL KHAH → ARABIC LETTER KHAH #
+1EE37 ; 062E ; MA # ( ‎𞸷‎ → ‎خ‎ ) ARABIC MATHEMATICAL INITIAL KHAH → ARABIC LETTER KHAH #
+1EE57 ; 062E ; MA # ( ‎𞹗‎ → ‎خ‎ ) ARABIC MATHEMATICAL TAILED KHAH → ARABIC LETTER KHAH #
+1EE77 ; 062E ; MA # ( ‎𞹷‎ → ‎خ‎ ) ARABIC MATHEMATICAL STRETCHED KHAH → ARABIC LETTER KHAH #
+1EE97 ; 062E ; MA # ( ‎𞺗‎ → ‎خ‎ ) ARABIC MATHEMATICAL LOOPED KHAH → ARABIC LETTER KHAH #
+1EEB7 ; 062E ; MA # ( ‎𞺷‎ → ‎خ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH → ARABIC LETTER KHAH #
+FEA7 ; 062E ; MA # ( ‎ﺧ‎ → ‎خ‎ ) ARABIC LETTER KHAH INITIAL FORM → ARABIC LETTER KHAH #
+FEA8 ; 062E ; MA # ( ‎ﺨ‎ → ‎خ‎ ) ARABIC LETTER KHAH MEDIAL FORM → ARABIC LETTER KHAH #
+FEA6 ; 062E ; MA # ( ‎ﺦ‎ → ‎خ‎ ) ARABIC LETTER KHAH FINAL FORM → ARABIC LETTER KHAH #
+FEA5 ; 062E ; MA # ( ‎ﺥ‎ → ‎خ‎ ) ARABIC LETTER KHAH ISOLATED FORM → ARABIC LETTER KHAH #
+
+FCAB ; 062E 062C ; MA # ( ‎ﲫ‎ → ‎خج‎ ) ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM → ARABIC LETTER KHAH, ARABIC LETTER JEEM #
+FC19 ; 062E 062C ; MA # ( ‎ﰙ‎ → ‎خج‎ ) ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM → ARABIC LETTER KHAH, ARABIC LETTER JEEM #
+
+FC1A ; 062E 062D ; MA # ( ‎ﰚ‎ → ‎خح‎ ) ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM → ARABIC LETTER KHAH, ARABIC LETTER HAH #
+
+FCAC ; 062E 0645 ; MA # ( ‎ﲬ‎ → ‎خم‎ ) ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM → ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+FC1B ; 062E 0645 ; MA # ( ‎ﰛ‎ → ‎خم‎ ) ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM → ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FD1F ; 062E 0649 ; MA # ( ‎ﴟ‎ → ‎خى‎ ) ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA #
+FD03 ; 062E 0649 ; MA # ( ‎ﴃ‎ → ‎خى‎ ) ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA #
+FD20 ; 062E 0649 ; MA # ( ‎ﴠ‎ → ‎خى‎ ) ARABIC LIGATURE KHAH WITH YEH FINAL FORM → ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎خي‎→
+FD04 ; 062E 0649 ; MA # ( ‎ﴄ‎ → ‎خى‎ ) ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM → ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎خي‎→
+
+102E1 ; 062F ; MA #* ( 𐋡 → ‎د‎ ) COPTIC EPACT DIGIT ONE → ARABIC LETTER DAL #
+1EE03 ; 062F ; MA # ( ‎𞸃‎ → ‎د‎ ) ARABIC MATHEMATICAL DAL → ARABIC LETTER DAL #
+1EE83 ; 062F ; MA # ( ‎𞺃‎ → ‎د‎ ) ARABIC MATHEMATICAL LOOPED DAL → ARABIC LETTER DAL #
+1EEA3 ; 062F ; MA # ( ‎𞺣‎ → ‎د‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK DAL → ARABIC LETTER DAL #
+FEAA ; 062F ; MA # ( ‎ﺪ‎ → ‎د‎ ) ARABIC LETTER DAL FINAL FORM → ARABIC LETTER DAL #
+FEA9 ; 062F ; MA # ( ‎ﺩ‎ → ‎د‎ ) ARABIC LETTER DAL ISOLATED FORM → ARABIC LETTER DAL #
+
+0688 ; 062F 0615 ; MA # ( ‎ڈ‎ → ‎دؕ‎ ) ARABIC LETTER DDAL → ARABIC LETTER DAL, ARABIC SMALL HIGH TAH #
+FB89 ; 062F 0615 ; MA # ( ‎ﮉ‎ → ‎دؕ‎ ) ARABIC LETTER DDAL FINAL FORM → ARABIC LETTER DAL, ARABIC SMALL HIGH TAH # →‎ڈ‎→
+FB88 ; 062F 0615 ; MA # ( ‎ﮈ‎ → ‎دؕ‎ ) ARABIC LETTER DDAL ISOLATED FORM → ARABIC LETTER DAL, ARABIC SMALL HIGH TAH # →‎ڈ‎→
+
+068E ; 062F 06DB ; MA # ( ‎ڎ‎ → ‎دۛ‎ ) ARABIC LETTER DUL → ARABIC LETTER DAL, ARABIC SMALL HIGH THREE DOTS #
+FB87 ; 062F 06DB ; MA # ( ‎ﮇ‎ → ‎دۛ‎ ) ARABIC LETTER DUL FINAL FORM → ARABIC LETTER DAL, ARABIC SMALL HIGH THREE DOTS # →‎ڎ‎→
+FB86 ; 062F 06DB ; MA # ( ‎ﮆ‎ → ‎دۛ‎ ) ARABIC LETTER DUL ISOLATED FORM → ARABIC LETTER DAL, ARABIC SMALL HIGH THREE DOTS # →‎ڎ‎→
+
+06EE ; 062F 0302 ; MA # ( ‎ۮ‎ → ‎د̂‎ ) ARABIC LETTER DAL WITH INVERTED V → ARABIC LETTER DAL, COMBINING CIRCUMFLEX ACCENT # →‎دٛ‎→
+
+08AE ; 062F 0324 0323 ; MA # ( ‎ࢮ‎ → ‎د̤̣‎ ) ARABIC LETTER DAL WITH THREE DOTS BELOW → ARABIC LETTER DAL, COMBINING DIAERESIS BELOW, COMBINING DOT BELOW # →‎د࣮࣭‎→
+
+1EE18 ; 0630 ; MA # ( ‎𞸘‎ → ‎ذ‎ ) ARABIC MATHEMATICAL THAL → ARABIC LETTER THAL #
+1EE98 ; 0630 ; MA # ( ‎𞺘‎ → ‎ذ‎ ) ARABIC MATHEMATICAL LOOPED THAL → ARABIC LETTER THAL #
+1EEB8 ; 0630 ; MA # ( ‎𞺸‎ → ‎ذ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK THAL → ARABIC LETTER THAL #
+FEAC ; 0630 ; MA # ( ‎ﺬ‎ → ‎ذ‎ ) ARABIC LETTER THAL FINAL FORM → ARABIC LETTER THAL #
+FEAB ; 0630 ; MA # ( ‎ﺫ‎ → ‎ذ‎ ) ARABIC LETTER THAL ISOLATED FORM → ARABIC LETTER THAL #
+
+FC5B ; 0630 0670 ; MA # ( ‎ﱛ‎ → ‎ذٰ‎ ) ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM → ARABIC LETTER THAL, ARABIC LETTER SUPERSCRIPT ALEF #
+
+068B ; 068A 0615 ; MA # ( ‎ڋ‎ → ‎ڊؕ‎ ) ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH → ARABIC LETTER DAL WITH DOT BELOW, ARABIC SMALL HIGH TAH #
+
+FB85 ; 068C ; MA # ( ‎ﮅ‎ → ‎ڌ‎ ) ARABIC LETTER DAHAL FINAL FORM → ARABIC LETTER DAHAL #
+FB84 ; 068C ; MA # ( ‎ﮄ‎ → ‎ڌ‎ ) ARABIC LETTER DAHAL ISOLATED FORM → ARABIC LETTER DAHAL #
+
+FB83 ; 068D ; MA # ( ‎ﮃ‎ → ‎ڍ‎ ) ARABIC LETTER DDAHAL FINAL FORM → ARABIC LETTER DDAHAL #
+FB82 ; 068D ; MA # ( ‎ﮂ‎ → ‎ڍ‎ ) ARABIC LETTER DDAHAL ISOLATED FORM → ARABIC LETTER DDAHAL #
+
+1EE13 ; 0631 ; MA # ( ‎𞸓‎ → ‎ر‎ ) ARABIC MATHEMATICAL REH → ARABIC LETTER REH #
+1EE93 ; 0631 ; MA # ( ‎𞺓‎ → ‎ر‎ ) ARABIC MATHEMATICAL LOOPED REH → ARABIC LETTER REH #
+1EEB3 ; 0631 ; MA # ( ‎𞺳‎ → ‎ر‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK REH → ARABIC LETTER REH #
+FEAE ; 0631 ; MA # ( ‎ﺮ‎ → ‎ر‎ ) ARABIC LETTER REH FINAL FORM → ARABIC LETTER REH #
+FEAD ; 0631 ; MA # ( ‎ﺭ‎ → ‎ر‎ ) ARABIC LETTER REH ISOLATED FORM → ARABIC LETTER REH #
+
+0691 ; 0631 0615 ; MA # ( ‎ڑ‎ → ‎رؕ‎ ) ARABIC LETTER RREH → ARABIC LETTER REH, ARABIC SMALL HIGH TAH #
+FB8D ; 0631 0615 ; MA # ( ‎ﮍ‎ → ‎رؕ‎ ) ARABIC LETTER RREH FINAL FORM → ARABIC LETTER REH, ARABIC SMALL HIGH TAH # →‎ڑ‎→
+FB8C ; 0631 0615 ; MA # ( ‎ﮌ‎ → ‎رؕ‎ ) ARABIC LETTER RREH ISOLATED FORM → ARABIC LETTER REH, ARABIC SMALL HIGH TAH # →‎ڑ‎→
+
+0698 ; 0631 06DB ; MA # ( ‎ژ‎ → ‎رۛ‎ ) ARABIC LETTER JEH → ARABIC LETTER REH, ARABIC SMALL HIGH THREE DOTS #
+FB8B ; 0631 06DB ; MA # ( ‎ﮋ‎ → ‎رۛ‎ ) ARABIC LETTER JEH FINAL FORM → ARABIC LETTER REH, ARABIC SMALL HIGH THREE DOTS # →‎ژ‎→
+FB8A ; 0631 06DB ; MA # ( ‎ﮊ‎ → ‎رۛ‎ ) ARABIC LETTER JEH ISOLATED FORM → ARABIC LETTER REH, ARABIC SMALL HIGH THREE DOTS # →‎ژ‎→
+
+0692 ; 0631 0306 ; MA # ( ‎ڒ‎ → ‎ر̆‎ ) ARABIC LETTER REH WITH SMALL V → ARABIC LETTER REH, COMBINING BREVE # →‎رٚ‎→
+
+08B9 ; 0631 0306 0307 ; MA # ( ‎ࢹ‎ → ‎ر̆̇‎ ) ARABIC LETTER REH WITH SMALL NOON ABOVE → ARABIC LETTER REH, COMBINING BREVE, COMBINING DOT ABOVE # →‎رۨ‎→
+
+06EF ; 0631 0302 ; MA # ( ‎ۯ‎ → ‎ر̂‎ ) ARABIC LETTER REH WITH INVERTED V → ARABIC LETTER REH, COMBINING CIRCUMFLEX ACCENT # →‎رٛ‎→
+
+076C ; 0631 0654 ; MA # ( ‎ݬ‎ → ‎رٔ‎ ) ARABIC LETTER REH WITH HAMZA ABOVE → ARABIC LETTER REH, ARABIC HAMZA ABOVE #
+
+FC5C ; 0631 0670 ; MA # ( ‎ﱜ‎ → ‎رٰ‎ ) ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM → ARABIC LETTER REH, ARABIC LETTER SUPERSCRIPT ALEF #
+
+FDF6 ; 0631 0633 0648 0644 ; MA # ( ‎ﷶ‎ → ‎رسول‎ ) ARABIC LIGATURE RASOUL ISOLATED FORM → ARABIC LETTER REH, ARABIC LETTER SEEN, ARABIC LETTER WAW, ARABIC LETTER LAM #
+
+FDFC ; 0631 0649 006C 0644 ; MA #* ( ‎﷼‎ → ‎رىlل‎ ) RIAL SIGN → ARABIC LETTER REH, ARABIC LETTER ALEF MAKSURA, LATIN SMALL LETTER L, ARABIC LETTER LAM # →‎ریال‎→
+
+1EE06 ; 0632 ; MA # ( ‎𞸆‎ → ‎ز‎ ) ARABIC MATHEMATICAL ZAIN → ARABIC LETTER ZAIN #
+1EE86 ; 0632 ; MA # ( ‎𞺆‎ → ‎ز‎ ) ARABIC MATHEMATICAL LOOPED ZAIN → ARABIC LETTER ZAIN #
+1EEA6 ; 0632 ; MA # ( ‎𞺦‎ → ‎ز‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN → ARABIC LETTER ZAIN #
+FEB0 ; 0632 ; MA # ( ‎ﺰ‎ → ‎ز‎ ) ARABIC LETTER ZAIN FINAL FORM → ARABIC LETTER ZAIN #
+FEAF ; 0632 ; MA # ( ‎ﺯ‎ → ‎ز‎ ) ARABIC LETTER ZAIN ISOLATED FORM → ARABIC LETTER ZAIN #
+
+08B2 ; 0632 0302 ; MA # ( ‎ࢲ‎ → ‎ز̂‎ ) ARABIC LETTER ZAIN WITH INVERTED V ABOVE → ARABIC LETTER ZAIN, COMBINING CIRCUMFLEX ACCENT # →‎زٛ‎→
+
+0771 ; 0697 0615 ; MA # ( ‎ݱ‎ → ‎ڗؕ‎ ) ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS → ARABIC LETTER REH WITH TWO DOTS ABOVE, ARABIC SMALL HIGH TAH #
+
+1EE0E ; 0633 ; MA # ( ‎𞸎‎ → ‎س‎ ) ARABIC MATHEMATICAL SEEN → ARABIC LETTER SEEN #
+1EE2E ; 0633 ; MA # ( ‎𞸮‎ → ‎س‎ ) ARABIC MATHEMATICAL INITIAL SEEN → ARABIC LETTER SEEN #
+1EE4E ; 0633 ; MA # ( ‎𞹎‎ → ‎س‎ ) ARABIC MATHEMATICAL TAILED SEEN → ARABIC LETTER SEEN #
+1EE6E ; 0633 ; MA # ( ‎𞹮‎ → ‎س‎ ) ARABIC MATHEMATICAL STRETCHED SEEN → ARABIC LETTER SEEN #
+1EE8E ; 0633 ; MA # ( ‎𞺎‎ → ‎س‎ ) ARABIC MATHEMATICAL LOOPED SEEN → ARABIC LETTER SEEN #
+1EEAE ; 0633 ; MA # ( ‎𞺮‎ → ‎س‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN → ARABIC LETTER SEEN #
+FEB3 ; 0633 ; MA # ( ‎ﺳ‎ → ‎س‎ ) ARABIC LETTER SEEN INITIAL FORM → ARABIC LETTER SEEN #
+FEB4 ; 0633 ; MA # ( ‎ﺴ‎ → ‎س‎ ) ARABIC LETTER SEEN MEDIAL FORM → ARABIC LETTER SEEN #
+FEB2 ; 0633 ; MA # ( ‎ﺲ‎ → ‎س‎ ) ARABIC LETTER SEEN FINAL FORM → ARABIC LETTER SEEN #
+FEB1 ; 0633 ; MA # ( ‎ﺱ‎ → ‎س‎ ) ARABIC LETTER SEEN ISOLATED FORM → ARABIC LETTER SEEN #
+
+0634 ; 0633 06DB ; MA # ( ‎ش‎ → ‎سۛ‎ ) ARABIC LETTER SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS #
+1EE14 ; 0633 06DB ; MA # ( ‎𞸔‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+1EE34 ; 0633 06DB ; MA # ( ‎𞸴‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL INITIAL SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+1EE54 ; 0633 06DB ; MA # ( ‎𞹔‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL TAILED SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+1EE74 ; 0633 06DB ; MA # ( ‎𞹴‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL STRETCHED SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+1EE94 ; 0633 06DB ; MA # ( ‎𞺔‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL LOOPED SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+1EEB4 ; 0633 06DB ; MA # ( ‎𞺴‎ → ‎سۛ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+FEB7 ; 0633 06DB ; MA # ( ‎ﺷ‎ → ‎سۛ‎ ) ARABIC LETTER SHEEN INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+FEB8 ; 0633 06DB ; MA # ( ‎ﺸ‎ → ‎سۛ‎ ) ARABIC LETTER SHEEN MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+FEB6 ; 0633 06DB ; MA # ( ‎ﺶ‎ → ‎سۛ‎ ) ARABIC LETTER SHEEN FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+FEB5 ; 0633 06DB ; MA # ( ‎ﺵ‎ → ‎سۛ‎ ) ARABIC LETTER SHEEN ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS # →‎ش‎→
+
+077E ; 0633 0302 ; MA # ( ‎ݾ‎ → ‎س̂‎ ) ARABIC LETTER SEEN WITH INVERTED V → ARABIC LETTER SEEN, COMBINING CIRCUMFLEX ACCENT # →‎سٛ‎→
+
+FD31 ; 0633 006F ; MA # ( ‎ﴱ‎ → ‎سo‎ ) ARABIC LIGATURE SEEN WITH HEH INITIAL FORM → ARABIC LETTER SEEN, LATIN SMALL LETTER O # →‎سه‎→
+FCE8 ; 0633 006F ; MA # ( ‎ﳨ‎ → ‎سo‎ ) ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM → ARABIC LETTER SEEN, LATIN SMALL LETTER O # →‎سه‎→
+
+FD32 ; 0633 06DB 006F ; MA # ( ‎ﴲ‎ → ‎سۛo‎ ) ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, LATIN SMALL LETTER O # →‎شه‎→
+FCEA ; 0633 06DB 006F ; MA # ( ‎ﳪ‎ → ‎سۛo‎ ) ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, LATIN SMALL LETTER O # →‎شه‎→
+
+FCAD ; 0633 062C ; MA # ( ‎ﲭ‎ → ‎سج‎ ) ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER JEEM #
+FD34 ; 0633 062C ; MA # ( ‎ﴴ‎ → ‎سج‎ ) ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER JEEM #
+FC1C ; 0633 062C ; MA # ( ‎ﰜ‎ → ‎سج‎ ) ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER JEEM #
+
+FD2D ; 0633 06DB 062C ; MA # ( ‎ﴭ‎ → ‎سۛج‎ ) ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM # →‎شج‎→
+FD37 ; 0633 06DB 062C ; MA # ( ‎ﴷ‎ → ‎سۛج‎ ) ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM # →‎شج‎→
+FD25 ; 0633 06DB 062C ; MA # ( ‎ﴥ‎ → ‎سۛج‎ ) ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM # →‎شج‎→
+FD09 ; 0633 06DB 062C ; MA # ( ‎ﴉ‎ → ‎سۛج‎ ) ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM # →‎شج‎→
+
+FD5D ; 0633 062C 062D ; MA # ( ‎ﵝ‎ → ‎سجح‎ ) ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER JEEM, ARABIC LETTER HAH #
+
+FD5E ; 0633 062C 0649 ; MA # ( ‎ﵞ‎ → ‎سجى‎ ) ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA #
+
+FD69 ; 0633 06DB 062C 0649 ; MA # ( ‎ﵩ‎ → ‎سۛجى‎ ) ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎شجي‎→
+
+FCAE ; 0633 062D ; MA # ( ‎ﲮ‎ → ‎سح‎ ) ARABIC LIGATURE SEEN WITH HAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER HAH #
+FD35 ; 0633 062D ; MA # ( ‎ﴵ‎ → ‎سح‎ ) ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER HAH #
+FC1D ; 0633 062D ; MA # ( ‎ﰝ‎ → ‎سح‎ ) ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER HAH #
+
+FD2E ; 0633 06DB 062D ; MA # ( ‎ﴮ‎ → ‎سۛح‎ ) ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH # →‎شح‎→
+FD38 ; 0633 06DB 062D ; MA # ( ‎ﴸ‎ → ‎سۛح‎ ) ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH # →‎شح‎→
+FD26 ; 0633 06DB 062D ; MA # ( ‎ﴦ‎ → ‎سۛح‎ ) ARABIC LIGATURE SHEEN WITH HAH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH # →‎شح‎→
+FD0A ; 0633 06DB 062D ; MA # ( ‎ﴊ‎ → ‎سۛح‎ ) ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH # →‎شح‎→
+
+FD5C ; 0633 062D 062C ; MA # ( ‎ﵜ‎ → ‎سحج‎ ) ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER HAH, ARABIC LETTER JEEM #
+
+FD68 ; 0633 06DB 062D 0645 ; MA # ( ‎ﵨ‎ → ‎سۛحم‎ ) ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH, ARABIC LETTER MEEM # →‎شحم‎→
+FD67 ; 0633 06DB 062D 0645 ; MA # ( ‎ﵧ‎ → ‎سۛحم‎ ) ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH, ARABIC LETTER MEEM # →‎شحم‎→
+
+FDAA ; 0633 06DB 062D 0649 ; MA # ( ‎ﶪ‎ → ‎سۛحى‎ ) ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎شحي‎→
+
+FCAF ; 0633 062E ; MA # ( ‎ﲯ‎ → ‎سخ‎ ) ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER KHAH #
+FD36 ; 0633 062E ; MA # ( ‎ﴶ‎ → ‎سخ‎ ) ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER KHAH #
+FC1E ; 0633 062E ; MA # ( ‎ﰞ‎ → ‎سخ‎ ) ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER KHAH #
+
+FD2F ; 0633 06DB 062E ; MA # ( ‎ﴯ‎ → ‎سۛخ‎ ) ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER KHAH # →‎شخ‎→
+FD39 ; 0633 06DB 062E ; MA # ( ‎ﴹ‎ → ‎سۛخ‎ ) ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER KHAH # →‎شخ‎→
+FD27 ; 0633 06DB 062E ; MA # ( ‎ﴧ‎ → ‎سۛخ‎ ) ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER KHAH # →‎شخ‎→
+FD0B ; 0633 06DB 062E ; MA # ( ‎ﴋ‎ → ‎سۛخ‎ ) ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER KHAH # →‎شخ‎→
+
+FDA8 ; 0633 062E 0649 ; MA # ( ‎ﶨ‎ → ‎سخى‎ ) ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA #
+FDC6 ; 0633 062E 0649 ; MA # ( ‎ﷆ‎ → ‎سخى‎ ) ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎سخي‎→
+
+FD2A ; 0633 0631 ; MA # ( ‎ﴪ‎ → ‎سر‎ ) ARABIC LIGATURE SEEN WITH REH FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER REH #
+FD0E ; 0633 0631 ; MA # ( ‎ﴎ‎ → ‎سر‎ ) ARABIC LIGATURE SEEN WITH REH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER REH #
+
+FD29 ; 0633 06DB 0631 ; MA # ( ‎ﴩ‎ → ‎سۛر‎ ) ARABIC LIGATURE SHEEN WITH REH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER REH # →‎شر‎→
+FD0D ; 0633 06DB 0631 ; MA # ( ‎ﴍ‎ → ‎سۛر‎ ) ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER REH # →‎شر‎→
+
+FCB0 ; 0633 0645 ; MA # ( ‎ﲰ‎ → ‎سم‎ ) ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM #
+FCE7 ; 0633 0645 ; MA # ( ‎ﳧ‎ → ‎سم‎ ) ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM #
+FC1F ; 0633 0645 ; MA # ( ‎ﰟ‎ → ‎سم‎ ) ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM #
+
+FD30 ; 0633 06DB 0645 ; MA # ( ‎ﴰ‎ → ‎سۛم‎ ) ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎شم‎→
+FCE9 ; 0633 06DB 0645 ; MA # ( ‎ﳩ‎ → ‎سۛم‎ ) ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎شم‎→
+FD28 ; 0633 06DB 0645 ; MA # ( ‎ﴨ‎ → ‎سۛم‎ ) ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎شم‎→
+FD0C ; 0633 06DB 0645 ; MA # ( ‎ﴌ‎ → ‎سۛم‎ ) ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎شم‎→
+
+FD61 ; 0633 0645 062C ; MA # ( ‎ﵡ‎ → ‎سمج‎ ) ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM, ARABIC LETTER JEEM #
+
+FD60 ; 0633 0645 062D ; MA # ( ‎ﵠ‎ → ‎سمح‎ ) ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FD5F ; 0633 0645 062D ; MA # ( ‎ﵟ‎ → ‎سمح‎ ) ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FD6B ; 0633 06DB 0645 062E ; MA # ( ‎ﵫ‎ → ‎سۛمخ‎ ) ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM, ARABIC LETTER KHAH # →‎شمخ‎→
+FD6A ; 0633 06DB 0645 062E ; MA # ( ‎ﵪ‎ → ‎سۛمخ‎ ) ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM, ARABIC LETTER KHAH # →‎شمخ‎→
+
+FD63 ; 0633 0645 0645 ; MA # ( ‎ﵣ‎ → ‎سمم‎ ) ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FD62 ; 0633 0645 0645 ; MA # ( ‎ﵢ‎ → ‎سمم‎ ) ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FD6D ; 0633 06DB 0645 0645 ; MA # ( ‎ﵭ‎ → ‎سۛمم‎ ) ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM, ARABIC LETTER MEEM # →‎شمم‎→
+FD6C ; 0633 06DB 0645 0645 ; MA # ( ‎ﵬ‎ → ‎سۛمم‎ ) ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM, ARABIC LETTER MEEM # →‎شمم‎→
+
+FD17 ; 0633 0649 ; MA # ( ‎ﴗ‎ → ‎سى‎ ) ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER ALEF MAKSURA #
+FCFB ; 0633 0649 ; MA # ( ‎ﳻ‎ → ‎سى‎ ) ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER ALEF MAKSURA #
+FD18 ; 0633 0649 ; MA # ( ‎ﴘ‎ → ‎سى‎ ) ARABIC LIGATURE SEEN WITH YEH FINAL FORM → ARABIC LETTER SEEN, ARABIC LETTER ALEF MAKSURA # →‎سي‎→
+FCFC ; 0633 0649 ; MA # ( ‎ﳼ‎ → ‎سى‎ ) ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC LETTER ALEF MAKSURA # →‎سي‎→
+
+FD19 ; 0633 06DB 0649 ; MA # ( ‎ﴙ‎ → ‎سۛى‎ ) ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎شى‎→
+FCFD ; 0633 06DB 0649 ; MA # ( ‎ﳽ‎ → ‎سۛى‎ ) ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎شى‎→
+FD1A ; 0633 06DB 0649 ; MA # ( ‎ﴚ‎ → ‎سۛى‎ ) ARABIC LIGATURE SHEEN WITH YEH FINAL FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎شي‎→
+FCFE ; 0633 06DB 0649 ; MA # ( ‎ﳾ‎ → ‎سۛى‎ ) ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM → ARABIC LETTER SEEN, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎شي‎→
+
+102F2 ; 0635 ; MA #* ( 𐋲 → ‎ص‎ ) COPTIC EPACT NUMBER NINETY → ARABIC LETTER SAD #
+1EE11 ; 0635 ; MA # ( ‎𞸑‎ → ‎ص‎ ) ARABIC MATHEMATICAL SAD → ARABIC LETTER SAD #
+1EE31 ; 0635 ; MA # ( ‎𞸱‎ → ‎ص‎ ) ARABIC MATHEMATICAL INITIAL SAD → ARABIC LETTER SAD #
+1EE51 ; 0635 ; MA # ( ‎𞹑‎ → ‎ص‎ ) ARABIC MATHEMATICAL TAILED SAD → ARABIC LETTER SAD #
+1EE71 ; 0635 ; MA # ( ‎𞹱‎ → ‎ص‎ ) ARABIC MATHEMATICAL STRETCHED SAD → ARABIC LETTER SAD #
+1EE91 ; 0635 ; MA # ( ‎𞺑‎ → ‎ص‎ ) ARABIC MATHEMATICAL LOOPED SAD → ARABIC LETTER SAD #
+1EEB1 ; 0635 ; MA # ( ‎𞺱‎ → ‎ص‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK SAD → ARABIC LETTER SAD #
+FEBB ; 0635 ; MA # ( ‎ﺻ‎ → ‎ص‎ ) ARABIC LETTER SAD INITIAL FORM → ARABIC LETTER SAD #
+FEBC ; 0635 ; MA # ( ‎ﺼ‎ → ‎ص‎ ) ARABIC LETTER SAD MEDIAL FORM → ARABIC LETTER SAD #
+FEBA ; 0635 ; MA # ( ‎ﺺ‎ → ‎ص‎ ) ARABIC LETTER SAD FINAL FORM → ARABIC LETTER SAD #
+FEB9 ; 0635 ; MA # ( ‎ﺹ‎ → ‎ص‎ ) ARABIC LETTER SAD ISOLATED FORM → ARABIC LETTER SAD #
+
+069E ; 0635 06DB ; MA # ( ‎ڞ‎ → ‎صۛ‎ ) ARABIC LETTER SAD WITH THREE DOTS ABOVE → ARABIC LETTER SAD, ARABIC SMALL HIGH THREE DOTS #
+
+08AF ; 0635 0324 0323 ; MA # ( ‎ࢯ‎ → ‎ص̤̣‎ ) ARABIC LETTER SAD WITH THREE DOTS BELOW → ARABIC LETTER SAD, COMBINING DIAERESIS BELOW, COMBINING DOT BELOW # →‎ص࣮࣭‎→
+
+FCB1 ; 0635 062D ; MA # ( ‎ﲱ‎ → ‎صح‎ ) ARABIC LIGATURE SAD WITH HAH INITIAL FORM → ARABIC LETTER SAD, ARABIC LETTER HAH #
+FC20 ; 0635 062D ; MA # ( ‎ﰠ‎ → ‎صح‎ ) ARABIC LIGATURE SAD WITH HAH ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER HAH #
+
+FD65 ; 0635 062D 062D ; MA # ( ‎ﵥ‎ → ‎صحح‎ ) ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM → ARABIC LETTER SAD, ARABIC LETTER HAH, ARABIC LETTER HAH #
+FD64 ; 0635 062D 062D ; MA # ( ‎ﵤ‎ → ‎صحح‎ ) ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER HAH, ARABIC LETTER HAH #
+
+FDA9 ; 0635 062D 0649 ; MA # ( ‎ﶩ‎ → ‎صحى‎ ) ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎صحي‎→
+
+FCB2 ; 0635 062E ; MA # ( ‎ﲲ‎ → ‎صخ‎ ) ARABIC LIGATURE SAD WITH KHAH INITIAL FORM → ARABIC LETTER SAD, ARABIC LETTER KHAH #
+
+FD2B ; 0635 0631 ; MA # ( ‎ﴫ‎ → ‎صر‎ ) ARABIC LIGATURE SAD WITH REH FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER REH #
+FD0F ; 0635 0631 ; MA # ( ‎ﴏ‎ → ‎صر‎ ) ARABIC LIGATURE SAD WITH REH ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER REH #
+
+FDF5 ; 0635 0644 0639 0645 ; MA # ( ‎ﷵ‎ → ‎صلعم‎ ) ARABIC LIGATURE SALAM ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER LAM, ARABIC LETTER AIN, ARABIC LETTER MEEM #
+
+FDF9 ; 0635 0644 0649 ; MA # ( ‎ﷹ‎ → ‎صلى‎ ) ARABIC LIGATURE SALLA ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA #
+FDF0 ; 0635 0644 0649 ; MA # ( ‎ﷰ‎ → ‎صلى‎ ) ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA # →‎صلے‎→
+
+FDFA ; 0635 0644 0649 0020 006C 0644 0644 006F 0020 0639 0644 0649 006F 0020 0648 0633 0644 0645 ; MA #* ( ‎ﷺ‎ → ‎صلى lللo علىo وسلم‎ ) ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM → ARABIC LETTER SAD, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA, SPACE, LATIN SMALL LETTER L, ARABIC LETTER LAM, ARABIC LETTER LAM, LATIN SMALL LETTER O, SPACE, ARABIC LETTER AIN, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA, LATIN SMALL LETTER O, SPACE, ARABIC LETTER WAW, ARABIC LETTER SEEN, ARABIC LETTER LAM, ARABIC LETTER MEEM # →‎صلى الله عليه وسلم‎→
+
+FCB3 ; 0635 0645 ; MA # ( ‎ﲳ‎ → ‎صم‎ ) ARABIC LIGATURE SAD WITH MEEM INITIAL FORM → ARABIC LETTER SAD, ARABIC LETTER MEEM #
+FC21 ; 0635 0645 ; MA # ( ‎ﰡ‎ → ‎صم‎ ) ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER MEEM #
+
+FDC5 ; 0635 0645 0645 ; MA # ( ‎ﷅ‎ → ‎صمم‎ ) ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER SAD, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FD66 ; 0635 0645 0645 ; MA # ( ‎ﵦ‎ → ‎صمم‎ ) ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FD21 ; 0635 0649 ; MA # ( ‎ﴡ‎ → ‎صى‎ ) ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER ALEF MAKSURA #
+FD05 ; 0635 0649 ; MA # ( ‎ﴅ‎ → ‎صى‎ ) ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER ALEF MAKSURA #
+FD22 ; 0635 0649 ; MA # ( ‎ﴢ‎ → ‎صى‎ ) ARABIC LIGATURE SAD WITH YEH FINAL FORM → ARABIC LETTER SAD, ARABIC LETTER ALEF MAKSURA # →‎صي‎→
+FD06 ; 0635 0649 ; MA # ( ‎ﴆ‎ → ‎صى‎ ) ARABIC LIGATURE SAD WITH YEH ISOLATED FORM → ARABIC LETTER SAD, ARABIC LETTER ALEF MAKSURA # →‎صي‎→
+
+1EE19 ; 0636 ; MA # ( ‎𞸙‎ → ‎ض‎ ) ARABIC MATHEMATICAL DAD → ARABIC LETTER DAD #
+1EE39 ; 0636 ; MA # ( ‎𞸹‎ → ‎ض‎ ) ARABIC MATHEMATICAL INITIAL DAD → ARABIC LETTER DAD #
+1EE59 ; 0636 ; MA # ( ‎𞹙‎ → ‎ض‎ ) ARABIC MATHEMATICAL TAILED DAD → ARABIC LETTER DAD #
+1EE79 ; 0636 ; MA # ( ‎𞹹‎ → ‎ض‎ ) ARABIC MATHEMATICAL STRETCHED DAD → ARABIC LETTER DAD #
+1EE99 ; 0636 ; MA # ( ‎𞺙‎ → ‎ض‎ ) ARABIC MATHEMATICAL LOOPED DAD → ARABIC LETTER DAD #
+1EEB9 ; 0636 ; MA # ( ‎𞺹‎ → ‎ض‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK DAD → ARABIC LETTER DAD #
+FEBF ; 0636 ; MA # ( ‎ﺿ‎ → ‎ض‎ ) ARABIC LETTER DAD INITIAL FORM → ARABIC LETTER DAD #
+FEC0 ; 0636 ; MA # ( ‎ﻀ‎ → ‎ض‎ ) ARABIC LETTER DAD MEDIAL FORM → ARABIC LETTER DAD #
+FEBE ; 0636 ; MA # ( ‎ﺾ‎ → ‎ض‎ ) ARABIC LETTER DAD FINAL FORM → ARABIC LETTER DAD #
+FEBD ; 0636 ; MA # ( ‎ﺽ‎ → ‎ض‎ ) ARABIC LETTER DAD ISOLATED FORM → ARABIC LETTER DAD #
+
+FCB4 ; 0636 062C ; MA # ( ‎ﲴ‎ → ‎ضج‎ ) ARABIC LIGATURE DAD WITH JEEM INITIAL FORM → ARABIC LETTER DAD, ARABIC LETTER JEEM #
+FC22 ; 0636 062C ; MA # ( ‎ﰢ‎ → ‎ضج‎ ) ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER JEEM #
+
+FCB5 ; 0636 062D ; MA # ( ‎ﲵ‎ → ‎ضح‎ ) ARABIC LIGATURE DAD WITH HAH INITIAL FORM → ARABIC LETTER DAD, ARABIC LETTER HAH #
+FC23 ; 0636 062D ; MA # ( ‎ﰣ‎ → ‎ضح‎ ) ARABIC LIGATURE DAD WITH HAH ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER HAH #
+
+FD6E ; 0636 062D 0649 ; MA # ( ‎ﵮ‎ → ‎ضحى‎ ) ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FDAB ; 0636 062D 0649 ; MA # ( ‎ﶫ‎ → ‎ضحى‎ ) ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎ضحي‎→
+
+FCB6 ; 0636 062E ; MA # ( ‎ﲶ‎ → ‎ضخ‎ ) ARABIC LIGATURE DAD WITH KHAH INITIAL FORM → ARABIC LETTER DAD, ARABIC LETTER KHAH #
+FC24 ; 0636 062E ; MA # ( ‎ﰤ‎ → ‎ضخ‎ ) ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER KHAH #
+
+FD70 ; 0636 062E 0645 ; MA # ( ‎ﵰ‎ → ‎ضخم‎ ) ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM → ARABIC LETTER DAD, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+FD6F ; 0636 062E 0645 ; MA # ( ‎ﵯ‎ → ‎ضخم‎ ) ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FD2C ; 0636 0631 ; MA # ( ‎ﴬ‎ → ‎ضر‎ ) ARABIC LIGATURE DAD WITH REH FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER REH #
+FD10 ; 0636 0631 ; MA # ( ‎ﴐ‎ → ‎ضر‎ ) ARABIC LIGATURE DAD WITH REH ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER REH #
+
+FCB7 ; 0636 0645 ; MA # ( ‎ﲷ‎ → ‎ضم‎ ) ARABIC LIGATURE DAD WITH MEEM INITIAL FORM → ARABIC LETTER DAD, ARABIC LETTER MEEM #
+FC25 ; 0636 0645 ; MA # ( ‎ﰥ‎ → ‎ضم‎ ) ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER MEEM #
+
+FD23 ; 0636 0649 ; MA # ( ‎ﴣ‎ → ‎ضى‎ ) ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER ALEF MAKSURA #
+FD07 ; 0636 0649 ; MA # ( ‎ﴇ‎ → ‎ضى‎ ) ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER ALEF MAKSURA #
+FD24 ; 0636 0649 ; MA # ( ‎ﴤ‎ → ‎ضى‎ ) ARABIC LIGATURE DAD WITH YEH FINAL FORM → ARABIC LETTER DAD, ARABIC LETTER ALEF MAKSURA # →‎ضي‎→
+FD08 ; 0636 0649 ; MA # ( ‎ﴈ‎ → ‎ضى‎ ) ARABIC LIGATURE DAD WITH YEH ISOLATED FORM → ARABIC LETTER DAD, ARABIC LETTER ALEF MAKSURA # →‎ضي‎→
+
+102E8 ; 0637 ; MA #* ( 𐋨 → ‎ط‎ ) COPTIC EPACT DIGIT EIGHT → ARABIC LETTER TAH #
+1EE08 ; 0637 ; MA # ( ‎𞸈‎ → ‎ط‎ ) ARABIC MATHEMATICAL TAH → ARABIC LETTER TAH #
+1EE68 ; 0637 ; MA # ( ‎𞹨‎ → ‎ط‎ ) ARABIC MATHEMATICAL STRETCHED TAH → ARABIC LETTER TAH #
+1EE88 ; 0637 ; MA # ( ‎𞺈‎ → ‎ط‎ ) ARABIC MATHEMATICAL LOOPED TAH → ARABIC LETTER TAH #
+1EEA8 ; 0637 ; MA # ( ‎𞺨‎ → ‎ط‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK TAH → ARABIC LETTER TAH #
+FEC3 ; 0637 ; MA # ( ‎ﻃ‎ → ‎ط‎ ) ARABIC LETTER TAH INITIAL FORM → ARABIC LETTER TAH #
+FEC4 ; 0637 ; MA # ( ‎ﻄ‎ → ‎ط‎ ) ARABIC LETTER TAH MEDIAL FORM → ARABIC LETTER TAH #
+FEC2 ; 0637 ; MA # ( ‎ﻂ‎ → ‎ط‎ ) ARABIC LETTER TAH FINAL FORM → ARABIC LETTER TAH #
+FEC1 ; 0637 ; MA # ( ‎ﻁ‎ → ‎ط‎ ) ARABIC LETTER TAH ISOLATED FORM → ARABIC LETTER TAH #
+
+069F ; 0637 06DB ; MA # ( ‎ڟ‎ → ‎طۛ‎ ) ARABIC LETTER TAH WITH THREE DOTS ABOVE → ARABIC LETTER TAH, ARABIC SMALL HIGH THREE DOTS #
+
+FCB8 ; 0637 062D ; MA # ( ‎ﲸ‎ → ‎طح‎ ) ARABIC LIGATURE TAH WITH HAH INITIAL FORM → ARABIC LETTER TAH, ARABIC LETTER HAH #
+FC26 ; 0637 062D ; MA # ( ‎ﰦ‎ → ‎طح‎ ) ARABIC LIGATURE TAH WITH HAH ISOLATED FORM → ARABIC LETTER TAH, ARABIC LETTER HAH #
+
+FD33 ; 0637 0645 ; MA # ( ‎ﴳ‎ → ‎طم‎ ) ARABIC LIGATURE TAH WITH MEEM INITIAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM #
+FD3A ; 0637 0645 ; MA # ( ‎ﴺ‎ → ‎طم‎ ) ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM #
+FC27 ; 0637 0645 ; MA # ( ‎ﰧ‎ → ‎طم‎ ) ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM #
+
+FD72 ; 0637 0645 062D ; MA # ( ‎ﵲ‎ → ‎طمح‎ ) ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FD71 ; 0637 0645 062D ; MA # ( ‎ﵱ‎ → ‎طمح‎ ) ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FD73 ; 0637 0645 0645 ; MA # ( ‎ﵳ‎ → ‎طمم‎ ) ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FD74 ; 0637 0645 0649 ; MA # ( ‎ﵴ‎ → ‎طمى‎ ) ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER TAH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎طمي‎→
+
+FD11 ; 0637 0649 ; MA # ( ‎ﴑ‎ → ‎طى‎ ) ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER TAH, ARABIC LETTER ALEF MAKSURA #
+FCF5 ; 0637 0649 ; MA # ( ‎ﳵ‎ → ‎طى‎ ) ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER TAH, ARABIC LETTER ALEF MAKSURA #
+FD12 ; 0637 0649 ; MA # ( ‎ﴒ‎ → ‎طى‎ ) ARABIC LIGATURE TAH WITH YEH FINAL FORM → ARABIC LETTER TAH, ARABIC LETTER ALEF MAKSURA # →‎طي‎→
+FCF6 ; 0637 0649 ; MA # ( ‎ﳶ‎ → ‎طى‎ ) ARABIC LIGATURE TAH WITH YEH ISOLATED FORM → ARABIC LETTER TAH, ARABIC LETTER ALEF MAKSURA # →‎طي‎→
+
+1EE1A ; 0638 ; MA # ( ‎𞸚‎ → ‎ظ‎ ) ARABIC MATHEMATICAL ZAH → ARABIC LETTER ZAH #
+1EE7A ; 0638 ; MA # ( ‎𞹺‎ → ‎ظ‎ ) ARABIC MATHEMATICAL STRETCHED ZAH → ARABIC LETTER ZAH #
+1EE9A ; 0638 ; MA # ( ‎𞺚‎ → ‎ظ‎ ) ARABIC MATHEMATICAL LOOPED ZAH → ARABIC LETTER ZAH #
+1EEBA ; 0638 ; MA # ( ‎𞺺‎ → ‎ظ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH → ARABIC LETTER ZAH #
+FEC7 ; 0638 ; MA # ( ‎ﻇ‎ → ‎ظ‎ ) ARABIC LETTER ZAH INITIAL FORM → ARABIC LETTER ZAH #
+FEC8 ; 0638 ; MA # ( ‎ﻈ‎ → ‎ظ‎ ) ARABIC LETTER ZAH MEDIAL FORM → ARABIC LETTER ZAH #
+FEC6 ; 0638 ; MA # ( ‎ﻆ‎ → ‎ظ‎ ) ARABIC LETTER ZAH FINAL FORM → ARABIC LETTER ZAH #
+FEC5 ; 0638 ; MA # ( ‎ﻅ‎ → ‎ظ‎ ) ARABIC LETTER ZAH ISOLATED FORM → ARABIC LETTER ZAH #
+
+FCB9 ; 0638 0645 ; MA # ( ‎ﲹ‎ → ‎ظم‎ ) ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM → ARABIC LETTER ZAH, ARABIC LETTER MEEM #
+FD3B ; 0638 0645 ; MA # ( ‎ﴻ‎ → ‎ظم‎ ) ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM → ARABIC LETTER ZAH, ARABIC LETTER MEEM #
+FC28 ; 0638 0645 ; MA # ( ‎ﰨ‎ → ‎ظم‎ ) ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM → ARABIC LETTER ZAH, ARABIC LETTER MEEM #
+
+060F ; 0639 ; MA #* ( ؏ → ‎ع‎ ) ARABIC SIGN MISRA → ARABIC LETTER AIN #
+1EE0F ; 0639 ; MA # ( ‎𞸏‎ → ‎ع‎ ) ARABIC MATHEMATICAL AIN → ARABIC LETTER AIN #
+1EE2F ; 0639 ; MA # ( ‎𞸯‎ → ‎ع‎ ) ARABIC MATHEMATICAL INITIAL AIN → ARABIC LETTER AIN #
+1EE4F ; 0639 ; MA # ( ‎𞹏‎ → ‎ع‎ ) ARABIC MATHEMATICAL TAILED AIN → ARABIC LETTER AIN #
+1EE6F ; 0639 ; MA # ( ‎𞹯‎ → ‎ع‎ ) ARABIC MATHEMATICAL STRETCHED AIN → ARABIC LETTER AIN #
+1EE8F ; 0639 ; MA # ( ‎𞺏‎ → ‎ع‎ ) ARABIC MATHEMATICAL LOOPED AIN → ARABIC LETTER AIN #
+1EEAF ; 0639 ; MA # ( ‎𞺯‎ → ‎ع‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK AIN → ARABIC LETTER AIN #
+FECB ; 0639 ; MA # ( ‎ﻋ‎ → ‎ع‎ ) ARABIC LETTER AIN INITIAL FORM → ARABIC LETTER AIN #
+FECC ; 0639 ; MA # ( ‎ﻌ‎ → ‎ع‎ ) ARABIC LETTER AIN MEDIAL FORM → ARABIC LETTER AIN #
+FECA ; 0639 ; MA # ( ‎ﻊ‎ → ‎ع‎ ) ARABIC LETTER AIN FINAL FORM → ARABIC LETTER AIN #
+FEC9 ; 0639 ; MA # ( ‎ﻉ‎ → ‎ع‎ ) ARABIC LETTER AIN ISOLATED FORM → ARABIC LETTER AIN #
+
+FCBA ; 0639 062C ; MA # ( ‎ﲺ‎ → ‎عج‎ ) ARABIC LIGATURE AIN WITH JEEM INITIAL FORM → ARABIC LETTER AIN, ARABIC LETTER JEEM #
+FC29 ; 0639 062C ; MA # ( ‎ﰩ‎ → ‎عج‎ ) ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM → ARABIC LETTER AIN, ARABIC LETTER JEEM #
+
+FDC4 ; 0639 062C 0645 ; MA # ( ‎ﷄ‎ → ‎عجم‎ ) ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM → ARABIC LETTER AIN, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+FD75 ; 0639 062C 0645 ; MA # ( ‎ﵵ‎ → ‎عجم‎ ) ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FDF7 ; 0639 0644 0649 006F ; MA # ( ‎ﷷ‎ → ‎علىo‎ ) ARABIC LIGATURE ALAYHE ISOLATED FORM → ARABIC LETTER AIN, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA, LATIN SMALL LETTER O # →‎عليه‎→
+
+FCBB ; 0639 0645 ; MA # ( ‎ﲻ‎ → ‎عم‎ ) ARABIC LIGATURE AIN WITH MEEM INITIAL FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM #
+FC2A ; 0639 0645 ; MA # ( ‎ﰪ‎ → ‎عم‎ ) ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM #
+
+FD77 ; 0639 0645 0645 ; MA # ( ‎ﵷ‎ → ‎عمم‎ ) ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FD76 ; 0639 0645 0645 ; MA # ( ‎ﵶ‎ → ‎عمم‎ ) ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FD78 ; 0639 0645 0649 ; MA # ( ‎ﵸ‎ → ‎عمى‎ ) ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FDB6 ; 0639 0645 0649 ; MA # ( ‎ﶶ‎ → ‎عمى‎ ) ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎عمي‎→
+
+FD13 ; 0639 0649 ; MA # ( ‎ﴓ‎ → ‎عى‎ ) ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER ALEF MAKSURA #
+FCF7 ; 0639 0649 ; MA # ( ‎ﳷ‎ → ‎عى‎ ) ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER AIN, ARABIC LETTER ALEF MAKSURA #
+FD14 ; 0639 0649 ; MA # ( ‎ﴔ‎ → ‎عى‎ ) ARABIC LIGATURE AIN WITH YEH FINAL FORM → ARABIC LETTER AIN, ARABIC LETTER ALEF MAKSURA # →‎عي‎→
+FCF8 ; 0639 0649 ; MA # ( ‎ﳸ‎ → ‎عى‎ ) ARABIC LIGATURE AIN WITH YEH ISOLATED FORM → ARABIC LETTER AIN, ARABIC LETTER ALEF MAKSURA # →‎عي‎→
+
+1EE1B ; 063A ; MA # ( ‎𞸛‎ → ‎غ‎ ) ARABIC MATHEMATICAL GHAIN → ARABIC LETTER GHAIN #
+1EE3B ; 063A ; MA # ( ‎𞸻‎ → ‎غ‎ ) ARABIC MATHEMATICAL INITIAL GHAIN → ARABIC LETTER GHAIN #
+1EE5B ; 063A ; MA # ( ‎𞹛‎ → ‎غ‎ ) ARABIC MATHEMATICAL TAILED GHAIN → ARABIC LETTER GHAIN #
+1EE7B ; 063A ; MA # ( ‎𞹻‎ → ‎غ‎ ) ARABIC MATHEMATICAL STRETCHED GHAIN → ARABIC LETTER GHAIN #
+1EE9B ; 063A ; MA # ( ‎𞺛‎ → ‎غ‎ ) ARABIC MATHEMATICAL LOOPED GHAIN → ARABIC LETTER GHAIN #
+1EEBB ; 063A ; MA # ( ‎𞺻‎ → ‎غ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN → ARABIC LETTER GHAIN #
+FECF ; 063A ; MA # ( ‎ﻏ‎ → ‎غ‎ ) ARABIC LETTER GHAIN INITIAL FORM → ARABIC LETTER GHAIN #
+FED0 ; 063A ; MA # ( ‎ﻐ‎ → ‎غ‎ ) ARABIC LETTER GHAIN MEDIAL FORM → ARABIC LETTER GHAIN #
+FECE ; 063A ; MA # ( ‎ﻎ‎ → ‎غ‎ ) ARABIC LETTER GHAIN FINAL FORM → ARABIC LETTER GHAIN #
+FECD ; 063A ; MA # ( ‎ﻍ‎ → ‎غ‎ ) ARABIC LETTER GHAIN ISOLATED FORM → ARABIC LETTER GHAIN #
+
+FCBC ; 063A 062C ; MA # ( ‎ﲼ‎ → ‎غج‎ ) ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER JEEM #
+FC2B ; 063A 062C ; MA # ( ‎ﰫ‎ → ‎غج‎ ) ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM → ARABIC LETTER GHAIN, ARABIC LETTER JEEM #
+
+FCBD ; 063A 0645 ; MA # ( ‎ﲽ‎ → ‎غم‎ ) ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER MEEM #
+FC2C ; 063A 0645 ; MA # ( ‎ﰬ‎ → ‎غم‎ ) ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM → ARABIC LETTER GHAIN, ARABIC LETTER MEEM #
+
+FD79 ; 063A 0645 0645 ; MA # ( ‎ﵹ‎ → ‎غمم‎ ) ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FD7B ; 063A 0645 0649 ; MA # ( ‎ﵻ‎ → ‎غمى‎ ) ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FD7A ; 063A 0645 0649 ; MA # ( ‎ﵺ‎ → ‎غمى‎ ) ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎غمي‎→
+
+FD15 ; 063A 0649 ; MA # ( ‎ﴕ‎ → ‎غى‎ ) ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER ALEF MAKSURA #
+FCF9 ; 063A 0649 ; MA # ( ‎ﳹ‎ → ‎غى‎ ) ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER GHAIN, ARABIC LETTER ALEF MAKSURA #
+FD16 ; 063A 0649 ; MA # ( ‎ﴖ‎ → ‎غى‎ ) ARABIC LIGATURE GHAIN WITH YEH FINAL FORM → ARABIC LETTER GHAIN, ARABIC LETTER ALEF MAKSURA # →‎غي‎→
+FCFA ; 063A 0649 ; MA # ( ‎ﳺ‎ → ‎غى‎ ) ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM → ARABIC LETTER GHAIN, ARABIC LETTER ALEF MAKSURA # →‎غي‎→
+
+1EE10 ; 0641 ; MA # ( ‎𞸐‎ → ‎ف‎ ) ARABIC MATHEMATICAL FEH → ARABIC LETTER FEH #
+1EE30 ; 0641 ; MA # ( ‎𞸰‎ → ‎ف‎ ) ARABIC MATHEMATICAL INITIAL FEH → ARABIC LETTER FEH #
+1EE70 ; 0641 ; MA # ( ‎𞹰‎ → ‎ف‎ ) ARABIC MATHEMATICAL STRETCHED FEH → ARABIC LETTER FEH #
+1EE90 ; 0641 ; MA # ( ‎𞺐‎ → ‎ف‎ ) ARABIC MATHEMATICAL LOOPED FEH → ARABIC LETTER FEH #
+1EEB0 ; 0641 ; MA # ( ‎𞺰‎ → ‎ف‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK FEH → ARABIC LETTER FEH #
+FED3 ; 0641 ; MA # ( ‎ﻓ‎ → ‎ف‎ ) ARABIC LETTER FEH INITIAL FORM → ARABIC LETTER FEH #
+FED4 ; 0641 ; MA # ( ‎ﻔ‎ → ‎ف‎ ) ARABIC LETTER FEH MEDIAL FORM → ARABIC LETTER FEH #
+FED2 ; 0641 ; MA # ( ‎ﻒ‎ → ‎ف‎ ) ARABIC LETTER FEH FINAL FORM → ARABIC LETTER FEH #
+FED1 ; 0641 ; MA # ( ‎ﻑ‎ → ‎ف‎ ) ARABIC LETTER FEH ISOLATED FORM → ARABIC LETTER FEH #
+06A7 ; 0641 ; MA # ( ‎ڧ‎ → ‎ف‎ ) ARABIC LETTER QAF WITH DOT ABOVE → ARABIC LETTER FEH #
+
+FCBE ; 0641 062C ; MA # ( ‎ﲾ‎ → ‎فج‎ ) ARABIC LIGATURE FEH WITH JEEM INITIAL FORM → ARABIC LETTER FEH, ARABIC LETTER JEEM #
+FC2D ; 0641 062C ; MA # ( ‎ﰭ‎ → ‎فج‎ ) ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER JEEM #
+
+FCBF ; 0641 062D ; MA # ( ‎ﲿ‎ → ‎فح‎ ) ARABIC LIGATURE FEH WITH HAH INITIAL FORM → ARABIC LETTER FEH, ARABIC LETTER HAH #
+FC2E ; 0641 062D ; MA # ( ‎ﰮ‎ → ‎فح‎ ) ARABIC LIGATURE FEH WITH HAH ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER HAH #
+
+FCC0 ; 0641 062E ; MA # ( ‎ﳀ‎ → ‎فخ‎ ) ARABIC LIGATURE FEH WITH KHAH INITIAL FORM → ARABIC LETTER FEH, ARABIC LETTER KHAH #
+FC2F ; 0641 062E ; MA # ( ‎ﰯ‎ → ‎فخ‎ ) ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER KHAH #
+
+FD7D ; 0641 062E 0645 ; MA # ( ‎ﵽ‎ → ‎فخم‎ ) ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM → ARABIC LETTER FEH, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+FD7C ; 0641 062E 0645 ; MA # ( ‎ﵼ‎ → ‎فخم‎ ) ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM → ARABIC LETTER FEH, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FCC1 ; 0641 0645 ; MA # ( ‎ﳁ‎ → ‎فم‎ ) ARABIC LIGATURE FEH WITH MEEM INITIAL FORM → ARABIC LETTER FEH, ARABIC LETTER MEEM #
+FC30 ; 0641 0645 ; MA # ( ‎ﰰ‎ → ‎فم‎ ) ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER MEEM #
+
+FDC1 ; 0641 0645 0649 ; MA # ( ‎ﷁ‎ → ‎فمى‎ ) ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER FEH, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎فمي‎→
+
+FC7C ; 0641 0649 ; MA # ( ‎ﱼ‎ → ‎فى‎ ) ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER FEH, ARABIC LETTER ALEF MAKSURA #
+FC31 ; 0641 0649 ; MA # ( ‎ﰱ‎ → ‎فى‎ ) ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER ALEF MAKSURA #
+FC7D ; 0641 0649 ; MA # ( ‎ﱽ‎ → ‎فى‎ ) ARABIC LIGATURE FEH WITH YEH FINAL FORM → ARABIC LETTER FEH, ARABIC LETTER ALEF MAKSURA # →‎في‎→
+FC32 ; 0641 0649 ; MA # ( ‎ﰲ‎ → ‎فى‎ ) ARABIC LIGATURE FEH WITH YEH ISOLATED FORM → ARABIC LETTER FEH, ARABIC LETTER ALEF MAKSURA # →‎في‎→
+
+1EE1E ; 06A1 ; MA # ( ‎𞸞‎ → ‎ڡ‎ ) ARABIC MATHEMATICAL DOTLESS FEH → ARABIC LETTER DOTLESS FEH #
+1EE7E ; 06A1 ; MA # ( ‎𞹾‎ → ‎ڡ‎ ) ARABIC MATHEMATICAL STRETCHED DOTLESS FEH → ARABIC LETTER DOTLESS FEH #
+08BB ; 06A1 ; MA # ( ‎ࢻ‎ → ‎ڡ‎ ) ARABIC LETTER AFRICAN FEH → ARABIC LETTER DOTLESS FEH #
+066F ; 06A1 ; MA # ( ‎ٯ‎ → ‎ڡ‎ ) ARABIC LETTER DOTLESS QAF → ARABIC LETTER DOTLESS FEH #
+1EE1F ; 06A1 ; MA # ( ‎𞸟‎ → ‎ڡ‎ ) ARABIC MATHEMATICAL DOTLESS QAF → ARABIC LETTER DOTLESS FEH # →‎ٯ‎→
+1EE5F ; 06A1 ; MA # ( ‎𞹟‎ → ‎ڡ‎ ) ARABIC MATHEMATICAL TAILED DOTLESS QAF → ARABIC LETTER DOTLESS FEH # →‎ٯ‎→
+08BC ; 06A1 ; MA # ( ‎ࢼ‎ → ‎ڡ‎ ) ARABIC LETTER AFRICAN QAF → ARABIC LETTER DOTLESS FEH # →‎ٯ‎→
+
+06A4 ; 06A1 06DB ; MA # ( ‎ڤ‎ → ‎ڡۛ‎ ) ARABIC LETTER VEH → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS #
+FB6C ; 06A1 06DB ; MA # ( ‎ﭬ‎ → ‎ڡۛ‎ ) ARABIC LETTER VEH INITIAL FORM → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS # →‎ڤ‎→
+FB6D ; 06A1 06DB ; MA # ( ‎ﭭ‎ → ‎ڡۛ‎ ) ARABIC LETTER VEH MEDIAL FORM → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS # →‎ڤ‎→
+FB6B ; 06A1 06DB ; MA # ( ‎ﭫ‎ → ‎ڡۛ‎ ) ARABIC LETTER VEH FINAL FORM → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS # →‎ڤ‎→
+FB6A ; 06A1 06DB ; MA # ( ‎ﭪ‎ → ‎ڡۛ‎ ) ARABIC LETTER VEH ISOLATED FORM → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS # →‎ڤ‎→
+06A8 ; 06A1 06DB ; MA # ( ‎ڨ‎ → ‎ڡۛ‎ ) ARABIC LETTER QAF WITH THREE DOTS ABOVE → ARABIC LETTER DOTLESS FEH, ARABIC SMALL HIGH THREE DOTS # →‎ڤ‎→
+
+08A4 ; 06A2 06DB ; MA # ( ‎ࢤ‎ → ‎ڢۛ‎ ) ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE → ARABIC LETTER FEH WITH DOT MOVED BELOW, ARABIC SMALL HIGH THREE DOTS #
+
+FB70 ; 06A6 ; MA # ( ‎ﭰ‎ → ‎ڦ‎ ) ARABIC LETTER PEHEH INITIAL FORM → ARABIC LETTER PEHEH #
+FB71 ; 06A6 ; MA # ( ‎ﭱ‎ → ‎ڦ‎ ) ARABIC LETTER PEHEH MEDIAL FORM → ARABIC LETTER PEHEH #
+FB6F ; 06A6 ; MA # ( ‎ﭯ‎ → ‎ڦ‎ ) ARABIC LETTER PEHEH FINAL FORM → ARABIC LETTER PEHEH #
+FB6E ; 06A6 ; MA # ( ‎ﭮ‎ → ‎ڦ‎ ) ARABIC LETTER PEHEH ISOLATED FORM → ARABIC LETTER PEHEH #
+
+1EE12 ; 0642 ; MA # ( ‎𞸒‎ → ‎ق‎ ) ARABIC MATHEMATICAL QAF → ARABIC LETTER QAF #
+1EE32 ; 0642 ; MA # ( ‎𞸲‎ → ‎ق‎ ) ARABIC MATHEMATICAL INITIAL QAF → ARABIC LETTER QAF #
+1EE52 ; 0642 ; MA # ( ‎𞹒‎ → ‎ق‎ ) ARABIC MATHEMATICAL TAILED QAF → ARABIC LETTER QAF #
+1EE72 ; 0642 ; MA # ( ‎𞹲‎ → ‎ق‎ ) ARABIC MATHEMATICAL STRETCHED QAF → ARABIC LETTER QAF #
+1EE92 ; 0642 ; MA # ( ‎𞺒‎ → ‎ق‎ ) ARABIC MATHEMATICAL LOOPED QAF → ARABIC LETTER QAF #
+1EEB2 ; 0642 ; MA # ( ‎𞺲‎ → ‎ق‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK QAF → ARABIC LETTER QAF #
+FED7 ; 0642 ; MA # ( ‎ﻗ‎ → ‎ق‎ ) ARABIC LETTER QAF INITIAL FORM → ARABIC LETTER QAF #
+FED8 ; 0642 ; MA # ( ‎ﻘ‎ → ‎ق‎ ) ARABIC LETTER QAF MEDIAL FORM → ARABIC LETTER QAF #
+FED6 ; 0642 ; MA # ( ‎ﻖ‎ → ‎ق‎ ) ARABIC LETTER QAF FINAL FORM → ARABIC LETTER QAF #
+FED5 ; 0642 ; MA # ( ‎ﻕ‎ → ‎ق‎ ) ARABIC LETTER QAF ISOLATED FORM → ARABIC LETTER QAF #
+
+FCC2 ; 0642 062D ; MA # ( ‎ﳂ‎ → ‎قح‎ ) ARABIC LIGATURE QAF WITH HAH INITIAL FORM → ARABIC LETTER QAF, ARABIC LETTER HAH #
+FC33 ; 0642 062D ; MA # ( ‎ﰳ‎ → ‎قح‎ ) ARABIC LIGATURE QAF WITH HAH ISOLATED FORM → ARABIC LETTER QAF, ARABIC LETTER HAH #
+
+FDF1 ; 0642 0644 0649 ; MA # ( ‎ﷱ‎ → ‎قلى‎ ) ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM → ARABIC LETTER QAF, ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA # →‎قلے‎→
+
+FCC3 ; 0642 0645 ; MA # ( ‎ﳃ‎ → ‎قم‎ ) ARABIC LIGATURE QAF WITH MEEM INITIAL FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM #
+FC34 ; 0642 0645 ; MA # ( ‎ﰴ‎ → ‎قم‎ ) ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM #
+
+FDB4 ; 0642 0645 062D ; MA # ( ‎ﶴ‎ → ‎قمح‎ ) ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FD7E ; 0642 0645 062D ; MA # ( ‎ﵾ‎ → ‎قمح‎ ) ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FD7F ; 0642 0645 0645 ; MA # ( ‎ﵿ‎ → ‎قمم‎ ) ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FDB2 ; 0642 0645 0649 ; MA # ( ‎ﶲ‎ → ‎قمى‎ ) ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER QAF, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎قمي‎→
+
+FC7E ; 0642 0649 ; MA # ( ‎ﱾ‎ → ‎قى‎ ) ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER QAF, ARABIC LETTER ALEF MAKSURA #
+FC35 ; 0642 0649 ; MA # ( ‎ﰵ‎ → ‎قى‎ ) ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER QAF, ARABIC LETTER ALEF MAKSURA #
+FC7F ; 0642 0649 ; MA # ( ‎ﱿ‎ → ‎قى‎ ) ARABIC LIGATURE QAF WITH YEH FINAL FORM → ARABIC LETTER QAF, ARABIC LETTER ALEF MAKSURA # →‎قي‎→
+FC36 ; 0642 0649 ; MA # ( ‎ﰶ‎ → ‎قى‎ ) ARABIC LIGATURE QAF WITH YEH ISOLATED FORM → ARABIC LETTER QAF, ARABIC LETTER ALEF MAKSURA # →‎قي‎→
+
+1EE0A ; 0643 ; MA # ( ‎𞸊‎ → ‎ك‎ ) ARABIC MATHEMATICAL KAF → ARABIC LETTER KAF #
+1EE2A ; 0643 ; MA # ( ‎𞸪‎ → ‎ك‎ ) ARABIC MATHEMATICAL INITIAL KAF → ARABIC LETTER KAF #
+1EE6A ; 0643 ; MA # ( ‎𞹪‎ → ‎ك‎ ) ARABIC MATHEMATICAL STRETCHED KAF → ARABIC LETTER KAF #
+FEDB ; 0643 ; MA # ( ‎ﻛ‎ → ‎ك‎ ) ARABIC LETTER KAF INITIAL FORM → ARABIC LETTER KAF #
+FEDC ; 0643 ; MA # ( ‎ﻜ‎ → ‎ك‎ ) ARABIC LETTER KAF MEDIAL FORM → ARABIC LETTER KAF #
+FEDA ; 0643 ; MA # ( ‎ﻚ‎ → ‎ك‎ ) ARABIC LETTER KAF FINAL FORM → ARABIC LETTER KAF #
+FED9 ; 0643 ; MA # ( ‎ﻙ‎ → ‎ك‎ ) ARABIC LETTER KAF ISOLATED FORM → ARABIC LETTER KAF #
+06A9 ; 0643 ; MA # ( ‎ک‎ → ‎ك‎ ) ARABIC LETTER KEHEH → ARABIC LETTER KAF #
+FB90 ; 0643 ; MA # ( ‎ﮐ‎ → ‎ك‎ ) ARABIC LETTER KEHEH INITIAL FORM → ARABIC LETTER KAF # →‎ک‎→
+FB91 ; 0643 ; MA # ( ‎ﮑ‎ → ‎ك‎ ) ARABIC LETTER KEHEH MEDIAL FORM → ARABIC LETTER KAF # →‎ک‎→
+FB8F ; 0643 ; MA # ( ‎ﮏ‎ → ‎ك‎ ) ARABIC LETTER KEHEH FINAL FORM → ARABIC LETTER KAF # →‎ک‎→
+FB8E ; 0643 ; MA # ( ‎ﮎ‎ → ‎ك‎ ) ARABIC LETTER KEHEH ISOLATED FORM → ARABIC LETTER KAF # →‎ک‎→
+06AA ; 0643 ; MA # ( ‎ڪ‎ → ‎ك‎ ) ARABIC LETTER SWASH KAF → ARABIC LETTER KAF #
+
+06AD ; 0643 06DB ; MA # ( ‎ڭ‎ → ‎كۛ‎ ) ARABIC LETTER NG → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS #
+FBD5 ; 0643 06DB ; MA # ( ‎ﯕ‎ → ‎كۛ‎ ) ARABIC LETTER NG INITIAL FORM → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS # →‎ڭ‎→
+FBD6 ; 0643 06DB ; MA # ( ‎ﯖ‎ → ‎كۛ‎ ) ARABIC LETTER NG MEDIAL FORM → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS # →‎ڭ‎→
+FBD4 ; 0643 06DB ; MA # ( ‎ﯔ‎ → ‎كۛ‎ ) ARABIC LETTER NG FINAL FORM → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS # →‎ڭ‎→
+FBD3 ; 0643 06DB ; MA # ( ‎ﯓ‎ → ‎كۛ‎ ) ARABIC LETTER NG ISOLATED FORM → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS # →‎ڭ‎→
+0763 ; 0643 06DB ; MA # ( ‎ݣ‎ → ‎كۛ‎ ) ARABIC LETTER KEHEH WITH THREE DOTS ABOVE → ARABIC LETTER KAF, ARABIC SMALL HIGH THREE DOTS # →‎ڭ‎→
+
+FC80 ; 0643 006C ; MA # ( ‎ﲀ‎ → ‎كl‎ ) ARABIC LIGATURE KAF WITH ALEF FINAL FORM → ARABIC LETTER KAF, LATIN SMALL LETTER L # →‎كا‎→
+FC37 ; 0643 006C ; MA # ( ‎ﰷ‎ → ‎كl‎ ) ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM → ARABIC LETTER KAF, LATIN SMALL LETTER L # →‎كا‎→
+
+FCC4 ; 0643 062C ; MA # ( ‎ﳄ‎ → ‎كج‎ ) ARABIC LIGATURE KAF WITH JEEM INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER JEEM #
+FC38 ; 0643 062C ; MA # ( ‎ﰸ‎ → ‎كج‎ ) ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER JEEM #
+
+FCC5 ; 0643 062D ; MA # ( ‎ﳅ‎ → ‎كح‎ ) ARABIC LIGATURE KAF WITH HAH INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER HAH #
+FC39 ; 0643 062D ; MA # ( ‎ﰹ‎ → ‎كح‎ ) ARABIC LIGATURE KAF WITH HAH ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER HAH #
+
+FCC6 ; 0643 062E ; MA # ( ‎ﳆ‎ → ‎كخ‎ ) ARABIC LIGATURE KAF WITH KHAH INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER KHAH #
+FC3A ; 0643 062E ; MA # ( ‎ﰺ‎ → ‎كخ‎ ) ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER KHAH #
+
+FCC7 ; 0643 0644 ; MA # ( ‎ﳇ‎ → ‎كل‎ ) ARABIC LIGATURE KAF WITH LAM INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER LAM #
+FCEB ; 0643 0644 ; MA # ( ‎ﳫ‎ → ‎كل‎ ) ARABIC LIGATURE KAF WITH LAM MEDIAL FORM → ARABIC LETTER KAF, ARABIC LETTER LAM #
+FC81 ; 0643 0644 ; MA # ( ‎ﲁ‎ → ‎كل‎ ) ARABIC LIGATURE KAF WITH LAM FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER LAM #
+FC3B ; 0643 0644 ; MA # ( ‎ﰻ‎ → ‎كل‎ ) ARABIC LIGATURE KAF WITH LAM ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER LAM #
+
+FCC8 ; 0643 0645 ; MA # ( ‎ﳈ‎ → ‎كم‎ ) ARABIC LIGATURE KAF WITH MEEM INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM #
+FCEC ; 0643 0645 ; MA # ( ‎ﳬ‎ → ‎كم‎ ) ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM #
+FC82 ; 0643 0645 ; MA # ( ‎ﲂ‎ → ‎كم‎ ) ARABIC LIGATURE KAF WITH MEEM FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM #
+FC3C ; 0643 0645 ; MA # ( ‎ﰼ‎ → ‎كم‎ ) ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM #
+
+FDC3 ; 0643 0645 0645 ; MA # ( ‎ﷃ‎ → ‎كمم‎ ) ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FDBB ; 0643 0645 0645 ; MA # ( ‎ﶻ‎ → ‎كمم‎ ) ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FDB7 ; 0643 0645 0649 ; MA # ( ‎ﶷ‎ → ‎كمى‎ ) ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎كمي‎→
+
+FC83 ; 0643 0649 ; MA # ( ‎ﲃ‎ → ‎كى‎ ) ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER ALEF MAKSURA #
+FC3D ; 0643 0649 ; MA # ( ‎ﰽ‎ → ‎كى‎ ) ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER ALEF MAKSURA #
+FC84 ; 0643 0649 ; MA # ( ‎ﲄ‎ → ‎كى‎ ) ARABIC LIGATURE KAF WITH YEH FINAL FORM → ARABIC LETTER KAF, ARABIC LETTER ALEF MAKSURA # →‎كي‎→
+FC3E ; 0643 0649 ; MA # ( ‎ﰾ‎ → ‎كى‎ ) ARABIC LIGATURE KAF WITH YEH ISOLATED FORM → ARABIC LETTER KAF, ARABIC LETTER ALEF MAKSURA # →‎كي‎→
+
+0762 ; 06AC ; MA # ( ‎ݢ‎ → ‎ڬ‎ ) ARABIC LETTER KEHEH WITH DOT ABOVE → ARABIC LETTER KAF WITH DOT ABOVE #
+
+FB94 ; 06AF ; MA # ( ‎ﮔ‎ → ‎گ‎ ) ARABIC LETTER GAF INITIAL FORM → ARABIC LETTER GAF #
+FB95 ; 06AF ; MA # ( ‎ﮕ‎ → ‎گ‎ ) ARABIC LETTER GAF MEDIAL FORM → ARABIC LETTER GAF #
+FB93 ; 06AF ; MA # ( ‎ﮓ‎ → ‎گ‎ ) ARABIC LETTER GAF FINAL FORM → ARABIC LETTER GAF #
+FB92 ; 06AF ; MA # ( ‎ﮒ‎ → ‎گ‎ ) ARABIC LETTER GAF ISOLATED FORM → ARABIC LETTER GAF #
+08B0 ; 06AF ; MA # ( ‎ࢰ‎ → ‎گ‎ ) ARABIC LETTER GAF WITH INVERTED STROKE → ARABIC LETTER GAF #
+
+06B4 ; 06AF 06DB ; MA # ( ‎ڴ‎ → ‎گۛ‎ ) ARABIC LETTER GAF WITH THREE DOTS ABOVE → ARABIC LETTER GAF, ARABIC SMALL HIGH THREE DOTS #
+
+FB9C ; 06B1 ; MA # ( ‎ﮜ‎ → ‎ڱ‎ ) ARABIC LETTER NGOEH INITIAL FORM → ARABIC LETTER NGOEH #
+FB9D ; 06B1 ; MA # ( ‎ﮝ‎ → ‎ڱ‎ ) ARABIC LETTER NGOEH MEDIAL FORM → ARABIC LETTER NGOEH #
+FB9B ; 06B1 ; MA # ( ‎ﮛ‎ → ‎ڱ‎ ) ARABIC LETTER NGOEH FINAL FORM → ARABIC LETTER NGOEH #
+FB9A ; 06B1 ; MA # ( ‎ﮚ‎ → ‎ڱ‎ ) ARABIC LETTER NGOEH ISOLATED FORM → ARABIC LETTER NGOEH #
+
+FB98 ; 06B3 ; MA # ( ‎ﮘ‎ → ‎ڳ‎ ) ARABIC LETTER GUEH INITIAL FORM → ARABIC LETTER GUEH #
+FB99 ; 06B3 ; MA # ( ‎ﮙ‎ → ‎ڳ‎ ) ARABIC LETTER GUEH MEDIAL FORM → ARABIC LETTER GUEH #
+FB97 ; 06B3 ; MA # ( ‎ﮗ‎ → ‎ڳ‎ ) ARABIC LETTER GUEH FINAL FORM → ARABIC LETTER GUEH #
+FB96 ; 06B3 ; MA # ( ‎ﮖ‎ → ‎ڳ‎ ) ARABIC LETTER GUEH ISOLATED FORM → ARABIC LETTER GUEH #
+
+1EE0B ; 0644 ; MA # ( ‎𞸋‎ → ‎ل‎ ) ARABIC MATHEMATICAL LAM → ARABIC LETTER LAM #
+1EE2B ; 0644 ; MA # ( ‎𞸫‎ → ‎ل‎ ) ARABIC MATHEMATICAL INITIAL LAM → ARABIC LETTER LAM #
+1EE4B ; 0644 ; MA # ( ‎𞹋‎ → ‎ل‎ ) ARABIC MATHEMATICAL TAILED LAM → ARABIC LETTER LAM #
+1EE8B ; 0644 ; MA # ( ‎𞺋‎ → ‎ل‎ ) ARABIC MATHEMATICAL LOOPED LAM → ARABIC LETTER LAM #
+1EEAB ; 0644 ; MA # ( ‎𞺫‎ → ‎ل‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK LAM → ARABIC LETTER LAM #
+FEDF ; 0644 ; MA # ( ‎ﻟ‎ → ‎ل‎ ) ARABIC LETTER LAM INITIAL FORM → ARABIC LETTER LAM #
+FEE0 ; 0644 ; MA # ( ‎ﻠ‎ → ‎ل‎ ) ARABIC LETTER LAM MEDIAL FORM → ARABIC LETTER LAM #
+FEDE ; 0644 ; MA # ( ‎ﻞ‎ → ‎ل‎ ) ARABIC LETTER LAM FINAL FORM → ARABIC LETTER LAM #
+FEDD ; 0644 ; MA # ( ‎ﻝ‎ → ‎ل‎ ) ARABIC LETTER LAM ISOLATED FORM → ARABIC LETTER LAM #
+
+06B7 ; 0644 06DB ; MA # ( ‎ڷ‎ → ‎لۛ‎ ) ARABIC LETTER LAM WITH THREE DOTS ABOVE → ARABIC LETTER LAM, ARABIC SMALL HIGH THREE DOTS #
+
+06B5 ; 0644 0306 ; MA # ( ‎ڵ‎ → ‎ل̆‎ ) ARABIC LETTER LAM WITH SMALL V → ARABIC LETTER LAM, COMBINING BREVE # →‎لٚ‎→
+
+FEFC ; 0644 006C ; MA # ( ‎ﻼ‎ → ‎لl‎ ) ARABIC LIGATURE LAM WITH ALEF FINAL FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L # →‎لا‎→
+FEFB ; 0644 006C ; MA # ( ‎ﻻ‎ → ‎لl‎ ) ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L # →‎لا‎→
+
+FEFA ; 0644 006C 0655 ; MA # ( ‎ﻺ‎ → ‎لlٕ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎لإ‎→
+FEF9 ; 0644 006C 0655 ; MA # ( ‎ﻹ‎ → ‎لlٕ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L, ARABIC HAMZA BELOW # →‎لإ‎→
+
+FEF8 ; 0644 006C 0674 ; MA # ( ‎ﻸ‎ → ‎لlٴ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎لأ‎→
+FEF7 ; 0644 006C 0674 ; MA # ( ‎ﻷ‎ → ‎لlٴ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM → ARABIC LETTER LAM, LATIN SMALL LETTER L, ARABIC LETTER HIGH HAMZA # →‎لأ‎→
+
+FCCD ; 0644 006F ; MA # ( ‎ﳍ‎ → ‎لo‎ ) ARABIC LIGATURE LAM WITH HEH INITIAL FORM → ARABIC LETTER LAM, LATIN SMALL LETTER O # →‎له‎→
+
+FEF6 ; 0644 0622 ; MA # ( ‎ﻶ‎ → ‎لآ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF WITH MADDA ABOVE #
+FEF5 ; 0644 0622 ; MA # ( ‎ﻵ‎ → ‎لآ‎ ) ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF WITH MADDA ABOVE #
+
+FCC9 ; 0644 062C ; MA # ( ‎ﳉ‎ → ‎لج‎ ) ARABIC LIGATURE LAM WITH JEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM #
+FC3F ; 0644 062C ; MA # ( ‎ﰿ‎ → ‎لج‎ ) ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM #
+
+FD83 ; 0644 062C 062C ; MA # ( ‎ﶃ‎ → ‎لجج‎ ) ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM, ARABIC LETTER JEEM #
+FD84 ; 0644 062C 062C ; MA # ( ‎ﶄ‎ → ‎لجج‎ ) ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM, ARABIC LETTER JEEM #
+
+FDBA ; 0644 062C 0645 ; MA # ( ‎ﶺ‎ → ‎لجم‎ ) ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+FDBC ; 0644 062C 0645 ; MA # ( ‎ﶼ‎ → ‎لجم‎ ) ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FDAC ; 0644 062C 0649 ; MA # ( ‎ﶬ‎ → ‎لجى‎ ) ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎لجي‎→
+
+FCCA ; 0644 062D ; MA # ( ‎ﳊ‎ → ‎لح‎ ) ARABIC LIGATURE LAM WITH HAH INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER HAH #
+FC40 ; 0644 062D ; MA # ( ‎ﱀ‎ → ‎لح‎ ) ARABIC LIGATURE LAM WITH HAH ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER HAH #
+
+FDB5 ; 0644 062D 0645 ; MA # ( ‎ﶵ‎ → ‎لحم‎ ) ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER HAH, ARABIC LETTER MEEM #
+FD80 ; 0644 062D 0645 ; MA # ( ‎ﶀ‎ → ‎لحم‎ ) ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER HAH, ARABIC LETTER MEEM #
+
+FD82 ; 0644 062D 0649 ; MA # ( ‎ﶂ‎ → ‎لحى‎ ) ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FD81 ; 0644 062D 0649 ; MA # ( ‎ﶁ‎ → ‎لحى‎ ) ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎لحي‎→
+
+FCCB ; 0644 062E ; MA # ( ‎ﳋ‎ → ‎لخ‎ ) ARABIC LIGATURE LAM WITH KHAH INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER KHAH #
+FC41 ; 0644 062E ; MA # ( ‎ﱁ‎ → ‎لخ‎ ) ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER KHAH #
+
+FD86 ; 0644 062E 0645 ; MA # ( ‎ﶆ‎ → ‎لخم‎ ) ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+FD85 ; 0644 062E 0645 ; MA # ( ‎ﶅ‎ → ‎لخم‎ ) ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FCCC ; 0644 0645 ; MA # ( ‎ﳌ‎ → ‎لم‎ ) ARABIC LIGATURE LAM WITH MEEM INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM #
+FCED ; 0644 0645 ; MA # ( ‎ﳭ‎ → ‎لم‎ ) ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM #
+FC85 ; 0644 0645 ; MA # ( ‎ﲅ‎ → ‎لم‎ ) ARABIC LIGATURE LAM WITH MEEM FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM #
+FC42 ; 0644 0645 ; MA # ( ‎ﱂ‎ → ‎لم‎ ) ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM #
+
+FD88 ; 0644 0645 062D ; MA # ( ‎ﶈ‎ → ‎لمح‎ ) ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FD87 ; 0644 0645 062D ; MA # ( ‎ﶇ‎ → ‎لمح‎ ) ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FDAD ; 0644 0645 0649 ; MA # ( ‎ﶭ‎ → ‎لمى‎ ) ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎لمي‎→
+
+FC86 ; 0644 0649 ; MA # ( ‎ﲆ‎ → ‎لى‎ ) ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA #
+FC43 ; 0644 0649 ; MA # ( ‎ﱃ‎ → ‎لى‎ ) ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA #
+FC87 ; 0644 0649 ; MA # ( ‎ﲇ‎ → ‎لى‎ ) ARABIC LIGATURE LAM WITH YEH FINAL FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA # →‎لي‎→
+FC44 ; 0644 0649 ; MA # ( ‎ﱄ‎ → ‎لى‎ ) ARABIC LIGATURE LAM WITH YEH ISOLATED FORM → ARABIC LETTER LAM, ARABIC LETTER ALEF MAKSURA # →‎لي‎→
+
+1EE0C ; 0645 ; MA # ( ‎𞸌‎ → ‎م‎ ) ARABIC MATHEMATICAL MEEM → ARABIC LETTER MEEM #
+1EE2C ; 0645 ; MA # ( ‎𞸬‎ → ‎م‎ ) ARABIC MATHEMATICAL INITIAL MEEM → ARABIC LETTER MEEM #
+1EE6C ; 0645 ; MA # ( ‎𞹬‎ → ‎م‎ ) ARABIC MATHEMATICAL STRETCHED MEEM → ARABIC LETTER MEEM #
+1EE8C ; 0645 ; MA # ( ‎𞺌‎ → ‎م‎ ) ARABIC MATHEMATICAL LOOPED MEEM → ARABIC LETTER MEEM #
+1EEAC ; 0645 ; MA # ( ‎𞺬‎ → ‎م‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM → ARABIC LETTER MEEM #
+FEE3 ; 0645 ; MA # ( ‎ﻣ‎ → ‎م‎ ) ARABIC LETTER MEEM INITIAL FORM → ARABIC LETTER MEEM #
+FEE4 ; 0645 ; MA # ( ‎ﻤ‎ → ‎م‎ ) ARABIC LETTER MEEM MEDIAL FORM → ARABIC LETTER MEEM #
+FEE2 ; 0645 ; MA # ( ‎ﻢ‎ → ‎م‎ ) ARABIC LETTER MEEM FINAL FORM → ARABIC LETTER MEEM #
+FEE1 ; 0645 ; MA # ( ‎ﻡ‎ → ‎م‎ ) ARABIC LETTER MEEM ISOLATED FORM → ARABIC LETTER MEEM #
+
+08A7 ; 0645 06DB ; MA # ( ‎ࢧ‎ → ‎مۛ‎ ) ARABIC LETTER MEEM WITH THREE DOTS ABOVE → ARABIC LETTER MEEM, ARABIC SMALL HIGH THREE DOTS #
+
+06FE ; 0645 0348 ; MA #* ( ‎۾‎ → ‎م͈‎ ) ARABIC SIGN SINDHI POSTPOSITION MEN → ARABIC LETTER MEEM, COMBINING DOUBLE VERTICAL LINE BELOW #
+
+FC88 ; 0645 006C ; MA # ( ‎ﲈ‎ → ‎مl‎ ) ARABIC LIGATURE MEEM WITH ALEF FINAL FORM → ARABIC LETTER MEEM, LATIN SMALL LETTER L # →‎ما‎→
+
+FCCE ; 0645 062C ; MA # ( ‎ﳎ‎ → ‎مج‎ ) ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM #
+FC45 ; 0645 062C ; MA # ( ‎ﱅ‎ → ‎مج‎ ) ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM #
+
+FD8C ; 0645 062C 062D ; MA # ( ‎ﶌ‎ → ‎مجح‎ ) ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM, ARABIC LETTER HAH #
+
+FD92 ; 0645 062C 062E ; MA # ( ‎ﶒ‎ → ‎مجخ‎ ) ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM, ARABIC LETTER KHAH #
+
+FD8D ; 0645 062C 0645 ; MA # ( ‎ﶍ‎ → ‎مجم‎ ) ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FDC0 ; 0645 062C 0649 ; MA # ( ‎ﷀ‎ → ‎مجى‎ ) ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER MEEM, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎مجي‎→
+
+FCCF ; 0645 062D ; MA # ( ‎ﳏ‎ → ‎مح‎ ) ARABIC LIGATURE MEEM WITH HAH INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH #
+FC46 ; 0645 062D ; MA # ( ‎ﱆ‎ → ‎مح‎ ) ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH #
+
+FD89 ; 0645 062D 062C ; MA # ( ‎ﶉ‎ → ‎محج‎ ) ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH, ARABIC LETTER JEEM #
+
+FD8A ; 0645 062D 0645 ; MA # ( ‎ﶊ‎ → ‎محم‎ ) ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH, ARABIC LETTER MEEM #
+
+FDF4 ; 0645 062D 0645 062F ; MA # ( ‎ﷴ‎ → ‎محمد‎ ) ARABIC LIGATURE MOHAMMAD ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH, ARABIC LETTER MEEM, ARABIC LETTER DAL #
+
+FD8B ; 0645 062D 0649 ; MA # ( ‎ﶋ‎ → ‎محى‎ ) ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM → ARABIC LETTER MEEM, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎محي‎→
+
+FCD0 ; 0645 062E ; MA # ( ‎ﳐ‎ → ‎مخ‎ ) ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER KHAH #
+FC47 ; 0645 062E ; MA # ( ‎ﱇ‎ → ‎مخ‎ ) ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER KHAH #
+
+FD8E ; 0645 062E 062C ; MA # ( ‎ﶎ‎ → ‎مخج‎ ) ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER KHAH, ARABIC LETTER JEEM #
+
+FD8F ; 0645 062E 0645 ; MA # ( ‎ﶏ‎ → ‎مخم‎ ) ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER KHAH, ARABIC LETTER MEEM #
+
+FDB9 ; 0645 062E 0649 ; MA # ( ‎ﶹ‎ → ‎مخى‎ ) ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM → ARABIC LETTER MEEM, ARABIC LETTER KHAH, ARABIC LETTER ALEF MAKSURA # →‎مخي‎→
+
+FCD1 ; 0645 0645 ; MA # ( ‎ﳑ‎ → ‎مم‎ ) ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM → ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FC89 ; 0645 0645 ; MA # ( ‎ﲉ‎ → ‎مم‎ ) ARABIC LIGATURE MEEM WITH MEEM FINAL FORM → ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+FC48 ; 0645 0645 ; MA # ( ‎ﱈ‎ → ‎مم‎ ) ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER MEEM #
+
+FDB1 ; 0645 0645 0649 ; MA # ( ‎ﶱ‎ → ‎ممى‎ ) ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER MEEM, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎ممي‎→
+
+FC49 ; 0645 0649 ; MA # ( ‎ﱉ‎ → ‎مى‎ ) ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FC4A ; 0645 0649 ; MA # ( ‎ﱊ‎ → ‎مى‎ ) ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM → ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎مي‎→
+
+1EE0D ; 0646 ; MA # ( ‎𞸍‎ → ‎ن‎ ) ARABIC MATHEMATICAL NOON → ARABIC LETTER NOON #
+1EE2D ; 0646 ; MA # ( ‎𞸭‎ → ‎ن‎ ) ARABIC MATHEMATICAL INITIAL NOON → ARABIC LETTER NOON #
+1EE4D ; 0646 ; MA # ( ‎𞹍‎ → ‎ن‎ ) ARABIC MATHEMATICAL TAILED NOON → ARABIC LETTER NOON #
+1EE6D ; 0646 ; MA # ( ‎𞹭‎ → ‎ن‎ ) ARABIC MATHEMATICAL STRETCHED NOON → ARABIC LETTER NOON #
+1EE8D ; 0646 ; MA # ( ‎𞺍‎ → ‎ن‎ ) ARABIC MATHEMATICAL LOOPED NOON → ARABIC LETTER NOON #
+1EEAD ; 0646 ; MA # ( ‎𞺭‎ → ‎ن‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK NOON → ARABIC LETTER NOON #
+FEE7 ; 0646 ; MA # ( ‎ﻧ‎ → ‎ن‎ ) ARABIC LETTER NOON INITIAL FORM → ARABIC LETTER NOON #
+FEE8 ; 0646 ; MA # ( ‎ﻨ‎ → ‎ن‎ ) ARABIC LETTER NOON MEDIAL FORM → ARABIC LETTER NOON #
+FEE6 ; 0646 ; MA # ( ‎ﻦ‎ → ‎ن‎ ) ARABIC LETTER NOON FINAL FORM → ARABIC LETTER NOON #
+FEE5 ; 0646 ; MA # ( ‎ﻥ‎ → ‎ن‎ ) ARABIC LETTER NOON ISOLATED FORM → ARABIC LETTER NOON #
+
+0768 ; 0646 0615 ; MA # ( ‎ݨ‎ → ‎نؕ‎ ) ARABIC LETTER NOON WITH SMALL TAH → ARABIC LETTER NOON, ARABIC SMALL HIGH TAH #
+
+0769 ; 0646 0306 ; MA # ( ‎ݩ‎ → ‎ن̆‎ ) ARABIC LETTER NOON WITH SMALL V → ARABIC LETTER NOON, COMBINING BREVE # →‎نٚ‎→
+
+FCD6 ; 0646 006F ; MA # ( ‎ﳖ‎ → ‎نo‎ ) ARABIC LIGATURE NOON WITH HEH INITIAL FORM → ARABIC LETTER NOON, LATIN SMALL LETTER O # →‎نه‎→
+FCEF ; 0646 006F ; MA # ( ‎ﳯ‎ → ‎نo‎ ) ARABIC LIGATURE NOON WITH HEH MEDIAL FORM → ARABIC LETTER NOON, LATIN SMALL LETTER O # →‎نه‎→
+
+FDB8 ; 0646 062C 062D ; MA # ( ‎ﶸ‎ → ‎نجح‎ ) ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER HAH #
+FDBD ; 0646 062C 062D ; MA # ( ‎ﶽ‎ → ‎نجح‎ ) ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER HAH #
+
+FD98 ; 0646 062C 0645 ; MA # ( ‎ﶘ‎ → ‎نجم‎ ) ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+FD97 ; 0646 062C 0645 ; MA # ( ‎ﶗ‎ → ‎نجم‎ ) ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER MEEM #
+
+FD99 ; 0646 062C 0649 ; MA # ( ‎ﶙ‎ → ‎نجى‎ ) ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA #
+FDC7 ; 0646 062C 0649 ; MA # ( ‎ﷇ‎ → ‎نجى‎ ) ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎نجي‎→
+
+FCD3 ; 0646 062D ; MA # ( ‎ﳓ‎ → ‎نح‎ ) ARABIC LIGATURE NOON WITH HAH INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER HAH #
+FC4C ; 0646 062D ; MA # ( ‎ﱌ‎ → ‎نح‎ ) ARABIC LIGATURE NOON WITH HAH ISOLATED FORM → ARABIC LETTER NOON, ARABIC LETTER HAH #
+
+FD95 ; 0646 062D 0645 ; MA # ( ‎ﶕ‎ → ‎نحم‎ ) ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER HAH, ARABIC LETTER MEEM #
+
+FD96 ; 0646 062D 0649 ; MA # ( ‎ﶖ‎ → ‎نحى‎ ) ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA #
+FDB3 ; 0646 062D 0649 ; MA # ( ‎ﶳ‎ → ‎نحى‎ ) ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎نحي‎→
+
+FCD4 ; 0646 062E ; MA # ( ‎ﳔ‎ → ‎نخ‎ ) ARABIC LIGATURE NOON WITH KHAH INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER KHAH #
+FC4D ; 0646 062E ; MA # ( ‎ﱍ‎ → ‎نخ‎ ) ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM → ARABIC LETTER NOON, ARABIC LETTER KHAH #
+
+FC8A ; 0646 0631 ; MA # ( ‎ﲊ‎ → ‎نر‎ ) ARABIC LIGATURE NOON WITH REH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER REH #
+
+FC8B ; 0646 0632 ; MA # ( ‎ﲋ‎ → ‎نز‎ ) ARABIC LIGATURE NOON WITH ZAIN FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER ZAIN #
+
+FCD5 ; 0646 0645 ; MA # ( ‎ﳕ‎ → ‎نم‎ ) ARABIC LIGATURE NOON WITH MEEM INITIAL FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM #
+FCEE ; 0646 0645 ; MA # ( ‎ﳮ‎ → ‎نم‎ ) ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM #
+FC8C ; 0646 0645 ; MA # ( ‎ﲌ‎ → ‎نم‎ ) ARABIC LIGATURE NOON WITH MEEM FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM #
+FC4E ; 0646 0645 ; MA # ( ‎ﱎ‎ → ‎نم‎ ) ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM #
+
+FD9B ; 0646 0645 0649 ; MA # ( ‎ﶛ‎ → ‎نمى‎ ) ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA #
+FD9A ; 0646 0645 0649 ; MA # ( ‎ﶚ‎ → ‎نمى‎ ) ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎نمي‎→
+
+FC8D ; 0646 0646 ; MA # ( ‎ﲍ‎ → ‎نن‎ ) ARABIC LIGATURE NOON WITH NOON FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER NOON #
+
+FC8E ; 0646 0649 ; MA # ( ‎ﲎ‎ → ‎نى‎ ) ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER ALEF MAKSURA #
+FC4F ; 0646 0649 ; MA # ( ‎ﱏ‎ → ‎نى‎ ) ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER NOON, ARABIC LETTER ALEF MAKSURA #
+FC8F ; 0646 0649 ; MA # ( ‎ﲏ‎ → ‎نى‎ ) ARABIC LIGATURE NOON WITH YEH FINAL FORM → ARABIC LETTER NOON, ARABIC LETTER ALEF MAKSURA # →‎ني‎→
+FC50 ; 0646 0649 ; MA # ( ‎ﱐ‎ → ‎نى‎ ) ARABIC LIGATURE NOON WITH YEH ISOLATED FORM → ARABIC LETTER NOON, ARABIC LETTER ALEF MAKSURA # →‎ني‎→
+
+06C2 ; 06C0 ; MA # ( ‎ۂ‎ → ‎ۀ‎ ) ARABIC LETTER HEH GOAL WITH HAMZA ABOVE → ARABIC LETTER HEH WITH YEH ABOVE # →‎ﮤ‎→
+FBA5 ; 06C0 ; MA # ( ‎ﮥ‎ → ‎ۀ‎ ) ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM → ARABIC LETTER HEH WITH YEH ABOVE #
+FBA4 ; 06C0 ; MA # ( ‎ﮤ‎ → ‎ۀ‎ ) ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM → ARABIC LETTER HEH WITH YEH ABOVE #
+
+102E4 ; 0648 ; MA #* ( 𐋤 → ‎و‎ ) COPTIC EPACT DIGIT FOUR → ARABIC LETTER WAW #
+1EE05 ; 0648 ; MA # ( ‎𞸅‎ → ‎و‎ ) ARABIC MATHEMATICAL WAW → ARABIC LETTER WAW #
+1EE85 ; 0648 ; MA # ( ‎𞺅‎ → ‎و‎ ) ARABIC MATHEMATICAL LOOPED WAW → ARABIC LETTER WAW #
+1EEA5 ; 0648 ; MA # ( ‎𞺥‎ → ‎و‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK WAW → ARABIC LETTER WAW #
+FEEE ; 0648 ; MA # ( ‎ﻮ‎ → ‎و‎ ) ARABIC LETTER WAW FINAL FORM → ARABIC LETTER WAW #
+FEED ; 0648 ; MA # ( ‎ﻭ‎ → ‎و‎ ) ARABIC LETTER WAW ISOLATED FORM → ARABIC LETTER WAW #
+08B1 ; 0648 ; MA # ( ‎ࢱ‎ → ‎و‎ ) ARABIC LETTER STRAIGHT WAW → ARABIC LETTER WAW #
+
+06CB ; 0648 06DB ; MA # ( ‎ۋ‎ → ‎وۛ‎ ) ARABIC LETTER VE → ARABIC LETTER WAW, ARABIC SMALL HIGH THREE DOTS #
+FBDF ; 0648 06DB ; MA # ( ‎ﯟ‎ → ‎وۛ‎ ) ARABIC LETTER VE FINAL FORM → ARABIC LETTER WAW, ARABIC SMALL HIGH THREE DOTS # →‎ۋ‎→
+FBDE ; 0648 06DB ; MA # ( ‎ﯞ‎ → ‎وۛ‎ ) ARABIC LETTER VE ISOLATED FORM → ARABIC LETTER WAW, ARABIC SMALL HIGH THREE DOTS # →‎ۋ‎→
+
+06C7 ; 0648 0313 ; MA # ( ‎ۇ‎ → ‎و̓‎ ) ARABIC LETTER U → ARABIC LETTER WAW, COMBINING COMMA ABOVE # →‎وُ‎→
+FBD8 ; 0648 0313 ; MA # ( ‎ﯘ‎ → ‎و̓‎ ) ARABIC LETTER U FINAL FORM → ARABIC LETTER WAW, COMBINING COMMA ABOVE # →‎ۇ‎→→‎وُ‎→
+FBD7 ; 0648 0313 ; MA # ( ‎ﯗ‎ → ‎و̓‎ ) ARABIC LETTER U ISOLATED FORM → ARABIC LETTER WAW, COMBINING COMMA ABOVE # →‎ۇ‎→→‎وُ‎→
+
+06C6 ; 0648 0306 ; MA # ( ‎ۆ‎ → ‎و̆‎ ) ARABIC LETTER OE → ARABIC LETTER WAW, COMBINING BREVE # →‎وٚ‎→
+FBDA ; 0648 0306 ; MA # ( ‎ﯚ‎ → ‎و̆‎ ) ARABIC LETTER OE FINAL FORM → ARABIC LETTER WAW, COMBINING BREVE # →‎ۆ‎→→‎وٚ‎→
+FBD9 ; 0648 0306 ; MA # ( ‎ﯙ‎ → ‎و̆‎ ) ARABIC LETTER OE ISOLATED FORM → ARABIC LETTER WAW, COMBINING BREVE # →‎ۆ‎→→‎وٚ‎→
+
+06C9 ; 0648 0302 ; MA # ( ‎ۉ‎ → ‎و̂‎ ) ARABIC LETTER KIRGHIZ YU → ARABIC LETTER WAW, COMBINING CIRCUMFLEX ACCENT # →‎وٛ‎→
+FBE3 ; 0648 0302 ; MA # ( ‎ﯣ‎ → ‎و̂‎ ) ARABIC LETTER KIRGHIZ YU FINAL FORM → ARABIC LETTER WAW, COMBINING CIRCUMFLEX ACCENT # →‎ۉ‎→→‎وٛ‎→
+FBE2 ; 0648 0302 ; MA # ( ‎ﯢ‎ → ‎و̂‎ ) ARABIC LETTER KIRGHIZ YU ISOLATED FORM → ARABIC LETTER WAW, COMBINING CIRCUMFLEX ACCENT # →‎ۉ‎→→‎وٛ‎→
+
+06C8 ; 0648 0670 ; MA # ( ‎ۈ‎ → ‎وٰ‎ ) ARABIC LETTER YU → ARABIC LETTER WAW, ARABIC LETTER SUPERSCRIPT ALEF #
+FBDC ; 0648 0670 ; MA # ( ‎ﯜ‎ → ‎وٰ‎ ) ARABIC LETTER YU FINAL FORM → ARABIC LETTER WAW, ARABIC LETTER SUPERSCRIPT ALEF # →‎ۈ‎→
+FBDB ; 0648 0670 ; MA # ( ‎ﯛ‎ → ‎وٰ‎ ) ARABIC LETTER YU ISOLATED FORM → ARABIC LETTER WAW, ARABIC LETTER SUPERSCRIPT ALEF # →‎ۈ‎→
+
+0624 ; 0648 0674 ; MA # ( ‎ؤ‎ → ‎وٴ‎ ) ARABIC LETTER WAW WITH HAMZA ABOVE → ARABIC LETTER WAW, ARABIC LETTER HIGH HAMZA # →‎ٶ‎→
+FE86 ; 0648 0674 ; MA # ( ‎ﺆ‎ → ‎وٴ‎ ) ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM → ARABIC LETTER WAW, ARABIC LETTER HIGH HAMZA # →‎ٶ‎→
+FE85 ; 0648 0674 ; MA # ( ‎ﺅ‎ → ‎وٴ‎ ) ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM → ARABIC LETTER WAW, ARABIC LETTER HIGH HAMZA # →‎ٶ‎→
+0676 ; 0648 0674 ; MA # ( ‎ٶ‎ → ‎وٴ‎ ) ARABIC LETTER HIGH HAMZA WAW → ARABIC LETTER WAW, ARABIC LETTER HIGH HAMZA #
+
+0677 ; 0648 0313 0674 ; MA # ( ‎ٷ‎ → ‎و̓ٴ‎ ) ARABIC LETTER U WITH HAMZA ABOVE → ARABIC LETTER WAW, COMBINING COMMA ABOVE, ARABIC LETTER HIGH HAMZA # →‎ۇٴ‎→
+FBDD ; 0648 0313 0674 ; MA # ( ‎ﯝ‎ → ‎و̓ٴ‎ ) ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM → ARABIC LETTER WAW, COMBINING COMMA ABOVE, ARABIC LETTER HIGH HAMZA # →‎ۇٴ‎→
+
+FDF8 ; 0648 0633 0644 0645 ; MA # ( ‎ﷸ‎ → ‎وسلم‎ ) ARABIC LIGATURE WASALLAM ISOLATED FORM → ARABIC LETTER WAW, ARABIC LETTER SEEN, ARABIC LETTER LAM, ARABIC LETTER MEEM #
+
+FBE1 ; 06C5 ; MA # ( ‎ﯡ‎ → ‎ۅ‎ ) ARABIC LETTER KIRGHIZ OE FINAL FORM → ARABIC LETTER KIRGHIZ OE #
+FBE0 ; 06C5 ; MA # ( ‎ﯠ‎ → ‎ۅ‎ ) ARABIC LETTER KIRGHIZ OE ISOLATED FORM → ARABIC LETTER KIRGHIZ OE #
+
+066E ; 0649 ; MA # ( ‎ٮ‎ → ‎ى‎ ) ARABIC LETTER DOTLESS BEH → ARABIC LETTER ALEF MAKSURA #
+1EE1C ; 0649 ; MA # ( ‎𞸜‎ → ‎ى‎ ) ARABIC MATHEMATICAL DOTLESS BEH → ARABIC LETTER ALEF MAKSURA # →‎ٮ‎→
+1EE7C ; 0649 ; MA # ( ‎𞹼‎ → ‎ى‎ ) ARABIC MATHEMATICAL STRETCHED DOTLESS BEH → ARABIC LETTER ALEF MAKSURA # →‎ٮ‎→
+06BA ; 0649 ; MA # ( ‎ں‎ → ‎ى‎ ) ARABIC LETTER NOON GHUNNA → ARABIC LETTER ALEF MAKSURA #
+1EE1D ; 0649 ; MA # ( ‎𞸝‎ → ‎ى‎ ) ARABIC MATHEMATICAL DOTLESS NOON → ARABIC LETTER ALEF MAKSURA # →‎ں‎→
+1EE5D ; 0649 ; MA # ( ‎𞹝‎ → ‎ى‎ ) ARABIC MATHEMATICAL TAILED DOTLESS NOON → ARABIC LETTER ALEF MAKSURA # →‎ں‎→
+FB9F ; 0649 ; MA # ( ‎ﮟ‎ → ‎ى‎ ) ARABIC LETTER NOON GHUNNA FINAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ں‎→
+FB9E ; 0649 ; MA # ( ‎ﮞ‎ → ‎ى‎ ) ARABIC LETTER NOON GHUNNA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA # →‎ں‎→
+08BD ; 0649 ; MA # ( ‎ࢽ‎ → ‎ى‎ ) ARABIC LETTER AFRICAN NOON → ARABIC LETTER ALEF MAKSURA # →‎ں‎→
+FBE8 ; 0649 ; MA # ( ‎ﯨ‎ → ‎ى‎ ) ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM → ARABIC LETTER ALEF MAKSURA #
+FBE9 ; 0649 ; MA # ( ‎ﯩ‎ → ‎ى‎ ) ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM → ARABIC LETTER ALEF MAKSURA #
+FEF0 ; 0649 ; MA # ( ‎ﻰ‎ → ‎ى‎ ) ARABIC LETTER ALEF MAKSURA FINAL FORM → ARABIC LETTER ALEF MAKSURA #
+FEEF ; 0649 ; MA # ( ‎ﻯ‎ → ‎ى‎ ) ARABIC LETTER ALEF MAKSURA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA #
+064A ; 0649 ; MA # ( ‎ي‎ → ‎ى‎ ) ARABIC LETTER YEH → ARABIC LETTER ALEF MAKSURA #
+1EE09 ; 0649 ; MA # ( ‎𞸉‎ → ‎ى‎ ) ARABIC MATHEMATICAL YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+1EE29 ; 0649 ; MA # ( ‎𞸩‎ → ‎ى‎ ) ARABIC MATHEMATICAL INITIAL YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+1EE49 ; 0649 ; MA # ( ‎𞹉‎ → ‎ى‎ ) ARABIC MATHEMATICAL TAILED YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+1EE69 ; 0649 ; MA # ( ‎𞹩‎ → ‎ى‎ ) ARABIC MATHEMATICAL STRETCHED YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+1EE89 ; 0649 ; MA # ( ‎𞺉‎ → ‎ى‎ ) ARABIC MATHEMATICAL LOOPED YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+1EEA9 ; 0649 ; MA # ( ‎𞺩‎ → ‎ى‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK YEH → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+FEF3 ; 0649 ; MA # ( ‎ﻳ‎ → ‎ى‎ ) ARABIC LETTER YEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+FEF4 ; 0649 ; MA # ( ‎ﻴ‎ → ‎ى‎ ) ARABIC LETTER YEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+FEF2 ; 0649 ; MA # ( ‎ﻲ‎ → ‎ى‎ ) ARABIC LETTER YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+FEF1 ; 0649 ; MA # ( ‎ﻱ‎ → ‎ى‎ ) ARABIC LETTER YEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+06CC ; 0649 ; MA # ( ‎ی‎ → ‎ى‎ ) ARABIC LETTER FARSI YEH → ARABIC LETTER ALEF MAKSURA #
+FBFE ; 0649 ; MA # ( ‎ﯾ‎ → ‎ى‎ ) ARABIC LETTER FARSI YEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ی‎→
+FBFF ; 0649 ; MA # ( ‎ﯿ‎ → ‎ى‎ ) ARABIC LETTER FARSI YEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ی‎→
+FBFD ; 0649 ; MA # ( ‎ﯽ‎ → ‎ى‎ ) ARABIC LETTER FARSI YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ﻰ‎→
+FBFC ; 0649 ; MA # ( ‎ﯼ‎ → ‎ى‎ ) ARABIC LETTER FARSI YEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA #
+06D2 ; 0649 ; MA # ( ‎ے‎ → ‎ى‎ ) ARABIC LETTER YEH BARREE → ARABIC LETTER ALEF MAKSURA # →‎ي‎→
+FBAF ; 0649 ; MA # ( ‎ﮯ‎ → ‎ى‎ ) ARABIC LETTER YEH BARREE FINAL FORM → ARABIC LETTER ALEF MAKSURA # →‎ے‎→→‎ي‎→
+FBAE ; 0649 ; MA # ( ‎ﮮ‎ → ‎ى‎ ) ARABIC LETTER YEH BARREE ISOLATED FORM → ARABIC LETTER ALEF MAKSURA # →‎ے‎→→‎ي‎→
+
+0679 ; 0649 0615 ; MA # ( ‎ٹ‎ → ‎ىؕ‎ ) ARABIC LETTER TTEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ٮؕ‎→
+FB68 ; 0649 0615 ; MA # ( ‎ﭨ‎ → ‎ىؕ‎ ) ARABIC LETTER TTEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ٹ‎→→‎ٮؕ‎→
+FB69 ; 0649 0615 ; MA # ( ‎ﭩ‎ → ‎ىؕ‎ ) ARABIC LETTER TTEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ٹ‎→→‎ٮؕ‎→
+FB67 ; 0649 0615 ; MA # ( ‎ﭧ‎ → ‎ىؕ‎ ) ARABIC LETTER TTEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ٹ‎→→‎ٮؕ‎→
+FB66 ; 0649 0615 ; MA # ( ‎ﭦ‎ → ‎ىؕ‎ ) ARABIC LETTER TTEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ٹ‎→→‎ٮؕ‎→
+06BB ; 0649 0615 ; MA # ( ‎ڻ‎ → ‎ىؕ‎ ) ARABIC LETTER RNOON → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ںؕ‎→
+FBA2 ; 0649 0615 ; MA # ( ‎ﮢ‎ → ‎ىؕ‎ ) ARABIC LETTER RNOON INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ڻ‎→→‎ںؕ‎→
+FBA3 ; 0649 0615 ; MA # ( ‎ﮣ‎ → ‎ىؕ‎ ) ARABIC LETTER RNOON MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ڻ‎→→‎ںؕ‎→
+FBA1 ; 0649 0615 ; MA # ( ‎ﮡ‎ → ‎ىؕ‎ ) ARABIC LETTER RNOON FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ڻ‎→→‎ںؕ‎→
+FBA0 ; 0649 0615 ; MA # ( ‎ﮠ‎ → ‎ىؕ‎ ) ARABIC LETTER RNOON ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH TAH # →‎ڻ‎→→‎ںؕ‎→
+
+067E ; 0649 06DB ; MA # ( ‎پ‎ → ‎ىۛ‎ ) ARABIC LETTER PEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ڽ‎→→‎ںۛ‎→
+FB58 ; 0649 06DB ; MA # ( ‎ﭘ‎ → ‎ىۛ‎ ) ARABIC LETTER PEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎پ‎→→‎ڽ‎→→‎ںۛ‎→
+FB59 ; 0649 06DB ; MA # ( ‎ﭙ‎ → ‎ىۛ‎ ) ARABIC LETTER PEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎پ‎→→‎ڽ‎→→‎ںۛ‎→
+FB57 ; 0649 06DB ; MA # ( ‎ﭗ‎ → ‎ىۛ‎ ) ARABIC LETTER PEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎پ‎→→‎ڽ‎→→‎ںۛ‎→
+FB56 ; 0649 06DB ; MA # ( ‎ﭖ‎ → ‎ىۛ‎ ) ARABIC LETTER PEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎پ‎→→‎ڽ‎→→‎ںۛ‎→
+062B ; 0649 06DB ; MA # ( ‎ث‎ → ‎ىۛ‎ ) ARABIC LETTER THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ٮۛ‎→
+1EE16 ; 0649 06DB ; MA # ( ‎𞸖‎ → ‎ىۛ‎ ) ARABIC MATHEMATICAL THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+1EE36 ; 0649 06DB ; MA # ( ‎𞸶‎ → ‎ىۛ‎ ) ARABIC MATHEMATICAL INITIAL THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+1EE76 ; 0649 06DB ; MA # ( ‎𞹶‎ → ‎ىۛ‎ ) ARABIC MATHEMATICAL STRETCHED THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+1EE96 ; 0649 06DB ; MA # ( ‎𞺖‎ → ‎ىۛ‎ ) ARABIC MATHEMATICAL LOOPED THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+1EEB6 ; 0649 06DB ; MA # ( ‎𞺶‎ → ‎ىۛ‎ ) ARABIC MATHEMATICAL DOUBLE-STRUCK THEH → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+FE9B ; 0649 06DB ; MA # ( ‎ﺛ‎ → ‎ىۛ‎ ) ARABIC LETTER THEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+FE9C ; 0649 06DB ; MA # ( ‎ﺜ‎ → ‎ىۛ‎ ) ARABIC LETTER THEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+FE9A ; 0649 06DB ; MA # ( ‎ﺚ‎ → ‎ىۛ‎ ) ARABIC LETTER THEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+FE99 ; 0649 06DB ; MA # ( ‎ﺙ‎ → ‎ىۛ‎ ) ARABIC LETTER THEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ث‎→→‎ٮۛ‎→
+06BD ; 0649 06DB ; MA # ( ‎ڽ‎ → ‎ىۛ‎ ) ARABIC LETTER NOON WITH THREE DOTS ABOVE → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎ںۛ‎→
+06D1 ; 0649 06DB ; MA # ( ‎ۑ‎ → ‎ىۛ‎ ) ARABIC LETTER YEH WITH THREE DOTS BELOW → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎پ‎→→‎ڽ‎→→‎ںۛ‎→
+063F ; 0649 06DB ; MA # ( ‎ؿ‎ → ‎ىۛ‎ ) ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS # →‎یۛ‎→
+
+08B7 ; 0649 06DB 06E2 ; MA # ( ‎ࢷ‎ → ‎ىۛۢ‎ ) ARABIC LETTER PEH WITH SMALL MEEM ABOVE → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC SMALL HIGH MEEM ISOLATED FORM # →‎پۢ‎→
+
+0756 ; 0649 0306 ; MA # ( ‎ݖ‎ → ‎ى̆‎ ) ARABIC LETTER BEH WITH SMALL V → ARABIC LETTER ALEF MAKSURA, COMBINING BREVE # →‎ٮٚ‎→
+06CE ; 0649 0306 ; MA # ( ‎ێ‎ → ‎ى̆‎ ) ARABIC LETTER YEH WITH SMALL V → ARABIC LETTER ALEF MAKSURA, COMBINING BREVE # →‎یٚ‎→
+
+08BA ; 0649 0306 0307 ; MA # ( ‎ࢺ‎ → ‎ى̆̇‎ ) ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE → ARABIC LETTER ALEF MAKSURA, COMBINING BREVE, COMBINING DOT ABOVE # →‎يۨ‎→
+
+063D ; 0649 0302 ; MA # ( ‎ؽ‎ → ‎ى̂‎ ) ARABIC LETTER FARSI YEH WITH INVERTED V → ARABIC LETTER ALEF MAKSURA, COMBINING CIRCUMFLEX ACCENT # →‎یٛ‎→
+
+08A8 ; 0649 0654 ; MA # ( ‎ࢨ‎ → ‎ىٔ‎ ) ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE → ARABIC LETTER ALEF MAKSURA, ARABIC HAMZA ABOVE # →‎ئ‎→
+
+FC90 ; 0649 0670 ; MA # ( ‎ﲐ‎ → ‎ىٰ‎ ) ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER SUPERSCRIPT ALEF #
+FC5D ; 0649 0670 ; MA # ( ‎ﱝ‎ → ‎ىٰ‎ ) ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER SUPERSCRIPT ALEF #
+
+FCDE ; 0649 006F ; MA # ( ‎ﳞ‎ → ‎ىo‎ ) ARABIC LIGATURE YEH WITH HEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, LATIN SMALL LETTER O # →‎يه‎→
+FCF1 ; 0649 006F ; MA # ( ‎ﳱ‎ → ‎ىo‎ ) ARABIC LIGATURE YEH WITH HEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, LATIN SMALL LETTER O # →‎يه‎→
+
+FCE6 ; 0649 06DB 006F ; MA # ( ‎ﳦ‎ → ‎ىۛo‎ ) ARABIC LIGATURE THEH WITH HEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, LATIN SMALL LETTER O # →‎ثه‎→
+
+0626 ; 0649 0674 ; MA # ( ‎ئ‎ → ‎ىٴ‎ ) ARABIC LETTER YEH WITH HAMZA ABOVE → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎ٸ‎→→‎يٴ‎→
+FE8B ; 0649 0674 ; MA # ( ‎ﺋ‎ → ‎ىٴ‎ ) ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎ئ‎→→‎ٸ‎→→‎يٴ‎→
+FE8C ; 0649 0674 ; MA # ( ‎ﺌ‎ → ‎ىٴ‎ ) ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎ئ‎→→‎ٸ‎→→‎يٴ‎→
+FE8A ; 0649 0674 ; MA # ( ‎ﺊ‎ → ‎ىٴ‎ ) ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎ئ‎→→‎ٸ‎→→‎يٴ‎→
+FE89 ; 0649 0674 ; MA # ( ‎ﺉ‎ → ‎ىٴ‎ ) ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎ٸ‎→→‎يٴ‎→
+0678 ; 0649 0674 ; MA # ( ‎ٸ‎ → ‎ىٴ‎ ) ARABIC LETTER HIGH HAMZA YEH → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA # →‎يٴ‎→
+
+FBEB ; 0649 0674 006C ; MA # ( ‎ﯫ‎ → ‎ىٴl‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER L # →‎ئا‎→
+FBEA ; 0649 0674 006C ; MA # ( ‎ﯪ‎ → ‎ىٴl‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER L # →‎ئا‎→
+
+FC9B ; 0649 0674 006F ; MA # ( ‎ﲛ‎ → ‎ىٴo‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER O # →‎ئه‎→
+FCE0 ; 0649 0674 006F ; MA # ( ‎ﳠ‎ → ‎ىٴo‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER O # →‎ئه‎→
+FBED ; 0649 0674 006F ; MA # ( ‎ﯭ‎ → ‎ىٴo‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER O # →‎ئە‎→→‎ٴىo‎→→‎ئه‎→
+FBEC ; 0649 0674 006F ; MA # ( ‎ﯬ‎ → ‎ىٴo‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, LATIN SMALL LETTER O # →‎ئە‎→→‎ٴىo‎→→‎ئه‎→
+
+FBF8 ; 0649 0674 067B ; MA # ( ‎ﯸ‎ → ‎ىٴٻ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER BEEH # →‎ئې‎→
+FBF7 ; 0649 0674 067B ; MA # ( ‎ﯷ‎ → ‎ىٴٻ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER BEEH # →‎ئې‎→
+FBF6 ; 0649 0674 067B ; MA # ( ‎ﯶ‎ → ‎ىٴٻ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER BEEH # →‎ئې‎→
+
+FC97 ; 0649 0674 062C ; MA # ( ‎ﲗ‎ → ‎ىٴج‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER JEEM # →‎ئج‎→
+FC00 ; 0649 0674 062C ; MA # ( ‎ﰀ‎ → ‎ىٴج‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER JEEM # →‎ئج‎→
+
+FC98 ; 0649 0674 062D ; MA # ( ‎ﲘ‎ → ‎ىٴح‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER HAH # →‎ئح‎→
+FC01 ; 0649 0674 062D ; MA # ( ‎ﰁ‎ → ‎ىٴح‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER HAH # →‎ئح‎→
+
+FC99 ; 0649 0674 062E ; MA # ( ‎ﲙ‎ → ‎ىٴخ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER KHAH # →‎ئخ‎→
+
+FC64 ; 0649 0674 0631 ; MA # ( ‎ﱤ‎ → ‎ىٴر‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER REH # →‎ئر‎→
+
+FC65 ; 0649 0674 0632 ; MA # ( ‎ﱥ‎ → ‎ىٴز‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ZAIN # →‎ئز‎→
+
+FC9A ; 0649 0674 0645 ; MA # ( ‎ﲚ‎ → ‎ىٴم‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER MEEM # →‎ئم‎→
+FCDF ; 0649 0674 0645 ; MA # ( ‎ﳟ‎ → ‎ىٴم‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER MEEM # →‎ئم‎→
+FC66 ; 0649 0674 0645 ; MA # ( ‎ﱦ‎ → ‎ىٴم‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER MEEM # →‎ئم‎→
+FC02 ; 0649 0674 0645 ; MA # ( ‎ﰂ‎ → ‎ىٴم‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER MEEM # →‎ئم‎→
+
+FC67 ; 0649 0674 0646 ; MA # ( ‎ﱧ‎ → ‎ىٴن‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER NOON # →‎ئن‎→
+
+FBEF ; 0649 0674 0648 ; MA # ( ‎ﯯ‎ → ‎ىٴو‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW # →‎ئو‎→
+FBEE ; 0649 0674 0648 ; MA # ( ‎ﯮ‎ → ‎ىٴو‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW # →‎ئو‎→
+
+FBF1 ; 0649 0674 0648 0313 ; MA # ( ‎ﯱ‎ → ‎ىٴو̓‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, COMBINING COMMA ABOVE # →‎ئۇ‎→
+FBF0 ; 0649 0674 0648 0313 ; MA # ( ‎ﯰ‎ → ‎ىٴو̓‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, COMBINING COMMA ABOVE # →‎ئۇ‎→
+
+FBF3 ; 0649 0674 0648 0306 ; MA # ( ‎ﯳ‎ → ‎ىٴو̆‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, COMBINING BREVE # →‎ئۆ‎→
+FBF2 ; 0649 0674 0648 0306 ; MA # ( ‎ﯲ‎ → ‎ىٴو̆‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, COMBINING BREVE # →‎ئۆ‎→
+
+FBF5 ; 0649 0674 0648 0670 ; MA # ( ‎ﯵ‎ → ‎ىٴوٰ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, ARABIC LETTER SUPERSCRIPT ALEF # →‎ئۈ‎→
+FBF4 ; 0649 0674 0648 0670 ; MA # ( ‎ﯴ‎ → ‎ىٴوٰ‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER WAW, ARABIC LETTER SUPERSCRIPT ALEF # →‎ئۈ‎→
+
+FBFB ; 0649 0674 0649 ; MA # ( ‎ﯻ‎ → ‎ىٴى‎ ) ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئى‎→
+FBFA ; 0649 0674 0649 ; MA # ( ‎ﯺ‎ → ‎ىٴى‎ ) ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئى‎→
+FC68 ; 0649 0674 0649 ; MA # ( ‎ﱨ‎ → ‎ىٴى‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئى‎→
+FBF9 ; 0649 0674 0649 ; MA # ( ‎ﯹ‎ → ‎ىٴى‎ ) ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئى‎→
+FC03 ; 0649 0674 0649 ; MA # ( ‎ﰃ‎ → ‎ىٴى‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئى‎→
+FC69 ; 0649 0674 0649 ; MA # ( ‎ﱩ‎ → ‎ىٴى‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئي‎→→‎ٴىى‎→→‎ئى‎→
+FC04 ; 0649 0674 0649 ; MA # ( ‎ﰄ‎ → ‎ىٴى‎ ) ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HIGH HAMZA, ARABIC LETTER ALEF MAKSURA # →‎ئي‎→→‎ٴىى‎→→‎ئى‎→
+
+FCDA ; 0649 062C ; MA # ( ‎ﳚ‎ → ‎ىج‎ ) ARABIC LIGATURE YEH WITH JEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER JEEM # →‎يج‎→
+FC55 ; 0649 062C ; MA # ( ‎ﱕ‎ → ‎ىج‎ ) ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER JEEM # →‎يج‎→
+
+FC11 ; 0649 06DB 062C ; MA # ( ‎ﰑ‎ → ‎ىۛج‎ ) ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER JEEM # →‎ثج‎→
+
+FDAF ; 0649 062C 0649 ; MA # ( ‎ﶯ‎ → ‎ىجى‎ ) ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER JEEM, ARABIC LETTER ALEF MAKSURA # →‎يجي‎→
+
+FCDB ; 0649 062D ; MA # ( ‎ﳛ‎ → ‎ىح‎ ) ARABIC LIGATURE YEH WITH HAH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HAH # →‎يح‎→
+FC56 ; 0649 062D ; MA # ( ‎ﱖ‎ → ‎ىح‎ ) ARABIC LIGATURE YEH WITH HAH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HAH # →‎يح‎→
+
+FDAE ; 0649 062D 0649 ; MA # ( ‎ﶮ‎ → ‎ىحى‎ ) ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER HAH, ARABIC LETTER ALEF MAKSURA # →‎يحي‎→
+
+FCDC ; 0649 062E ; MA # ( ‎ﳜ‎ → ‎ىخ‎ ) ARABIC LIGATURE YEH WITH KHAH INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER KHAH # →‎يخ‎→
+FC57 ; 0649 062E ; MA # ( ‎ﱗ‎ → ‎ىخ‎ ) ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER KHAH # →‎يخ‎→
+
+FC91 ; 0649 0631 ; MA # ( ‎ﲑ‎ → ‎ىر‎ ) ARABIC LIGATURE YEH WITH REH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER REH # →‎ير‎→
+
+FC76 ; 0649 06DB 0631 ; MA # ( ‎ﱶ‎ → ‎ىۛر‎ ) ARABIC LIGATURE THEH WITH REH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER REH # →‎ثر‎→
+
+FC92 ; 0649 0632 ; MA # ( ‎ﲒ‎ → ‎ىز‎ ) ARABIC LIGATURE YEH WITH ZAIN FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER ZAIN # →‎يز‎→
+
+FC77 ; 0649 06DB 0632 ; MA # ( ‎ﱷ‎ → ‎ىۛز‎ ) ARABIC LIGATURE THEH WITH ZAIN FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ZAIN # →‎ثز‎→
+
+FCDD ; 0649 0645 ; MA # ( ‎ﳝ‎ → ‎ىم‎ ) ARABIC LIGATURE YEH WITH MEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM # →‎يم‎→
+FCF0 ; 0649 0645 ; MA # ( ‎ﳰ‎ → ‎ىم‎ ) ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM # →‎يم‎→
+FC93 ; 0649 0645 ; MA # ( ‎ﲓ‎ → ‎ىم‎ ) ARABIC LIGATURE YEH WITH MEEM FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM # →‎يم‎→
+FC58 ; 0649 0645 ; MA # ( ‎ﱘ‎ → ‎ىم‎ ) ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM # →‎يم‎→
+
+FCA6 ; 0649 06DB 0645 ; MA # ( ‎ﲦ‎ → ‎ىۛم‎ ) ARABIC LIGATURE THEH WITH MEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎ثم‎→
+FCE5 ; 0649 06DB 0645 ; MA # ( ‎ﳥ‎ → ‎ىۛم‎ ) ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎ثم‎→
+FC78 ; 0649 06DB 0645 ; MA # ( ‎ﱸ‎ → ‎ىۛم‎ ) ARABIC LIGATURE THEH WITH MEEM FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎ثم‎→
+FC12 ; 0649 06DB 0645 ; MA # ( ‎ﰒ‎ → ‎ىۛم‎ ) ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER MEEM # →‎ثم‎→
+
+FD9D ; 0649 0645 0645 ; MA # ( ‎ﶝ‎ → ‎ىمم‎ ) ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM, ARABIC LETTER MEEM # →‎يمم‎→
+FD9C ; 0649 0645 0645 ; MA # ( ‎ﶜ‎ → ‎ىمم‎ ) ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM, ARABIC LETTER MEEM # →‎يمم‎→
+
+FDB0 ; 0649 0645 0649 ; MA # ( ‎ﶰ‎ → ‎ىمى‎ ) ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER MEEM, ARABIC LETTER ALEF MAKSURA # →‎يمي‎→
+
+FC94 ; 0649 0646 ; MA # ( ‎ﲔ‎ → ‎ىن‎ ) ARABIC LIGATURE YEH WITH NOON FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER NOON # →‎ين‎→
+
+FC79 ; 0649 06DB 0646 ; MA # ( ‎ﱹ‎ → ‎ىۛن‎ ) ARABIC LIGATURE THEH WITH NOON FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER NOON # →‎ثن‎→
+
+FC95 ; 0649 0649 ; MA # ( ‎ﲕ‎ → ‎ىى‎ ) ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER ALEF MAKSURA # →‎يى‎→
+FC59 ; 0649 0649 ; MA # ( ‎ﱙ‎ → ‎ىى‎ ) ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER ALEF MAKSURA # →‎يى‎→
+FC96 ; 0649 0649 ; MA # ( ‎ﲖ‎ → ‎ىى‎ ) ARABIC LIGATURE YEH WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER ALEF MAKSURA # →‎يي‎→
+FC5A ; 0649 0649 ; MA # ( ‎ﱚ‎ → ‎ىى‎ ) ARABIC LIGATURE YEH WITH YEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC LETTER ALEF MAKSURA # →‎يي‎→
+
+FC7A ; 0649 06DB 0649 ; MA # ( ‎ﱺ‎ → ‎ىۛى‎ ) ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎ثى‎→
+FC13 ; 0649 06DB 0649 ; MA # ( ‎ﰓ‎ → ‎ىۛى‎ ) ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎ثى‎→
+FC7B ; 0649 06DB 0649 ; MA # ( ‎ﱻ‎ → ‎ىۛى‎ ) ARABIC LIGATURE THEH WITH YEH FINAL FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎ثي‎→
+FC14 ; 0649 06DB 0649 ; MA # ( ‎ﰔ‎ → ‎ىۛى‎ ) ARABIC LIGATURE THEH WITH YEH ISOLATED FORM → ARABIC LETTER ALEF MAKSURA, ARABIC SMALL HIGH THREE DOTS, ARABIC LETTER ALEF MAKSURA # →‎ثي‎→
+
+FBB1 ; 06D3 ; MA # ( ‎ﮱ‎ → ‎ۓ‎ ) ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM → ARABIC LETTER YEH BARREE WITH HAMZA ABOVE #
+FBB0 ; 06D3 ; MA # ( ‎ﮰ‎ → ‎ۓ‎ ) ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM → ARABIC LETTER YEH BARREE WITH HAMZA ABOVE #
+
+102B8 ; 2D40 ; MA # ( 𐊸 → ⵀ ) CARIAN LETTER SS → TIFINAGH LETTER YAH #
+
+205E ; 2D42 ; MA #* ( ⁞ → ⵂ ) VERTICAL FOUR DOTS → TIFINAGH LETTER TUAREG YAH #
+2E3D ; 2D42 ; MA #* ( ⸽ → ⵂ ) VERTICAL SIX DOTS → TIFINAGH LETTER TUAREG YAH # →⁞→
+2999 ; 2D42 ; MA #* ( ⦙ → ⵂ ) DOTTED FENCE → TIFINAGH LETTER TUAREG YAH # →⁞→
+
+FE19 ; 2D57 ; MA #* ( ︙ → ⵗ ) PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS → TIFINAGH LETTER TUAREG YAGH # →⁝→
+205D ; 2D57 ; MA #* ( ⁝ → ⵗ ) TRICOLON → TIFINAGH LETTER TUAREG YAGH #
+22EE ; 2D57 ; MA #* ( ⋮ → ⵗ ) VERTICAL ELLIPSIS → TIFINAGH LETTER TUAREG YAGH # →︙→→⁝→
+
+0544 ; 1206 ; MA # ( Մ → ሆ ) ARMENIAN CAPITAL LETTER MEN → ETHIOPIC SYLLABLE HO #
+
+054C ; 1261 ; MA # ( Ռ → ቡ ) ARMENIAN CAPITAL LETTER RA → ETHIOPIC SYLLABLE BU #
+
+053B ; 12AE ; MA # ( Ի → ኮ ) ARMENIAN CAPITAL LETTER INI → ETHIOPIC SYLLABLE KO #
+
+054A ; 1323 ; MA # ( Պ → ጣ ) ARMENIAN CAPITAL LETTER PEH → ETHIOPIC SYLLABLE THAA #
+
+0906 ; 0905 093E ; MA # ( आ → अा ) DEVANAGARI LETTER AA → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA #
+
+0912 ; 0905 093E 0946 ; MA # ( ऒ → अाॆ ) DEVANAGARI LETTER SHORT O → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA, DEVANAGARI VOWEL SIGN SHORT E # →अॊ→→आॆ→
+
+0913 ; 0905 093E 0947 ; MA # ( ओ → अाे ) DEVANAGARI LETTER O → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA, DEVANAGARI VOWEL SIGN E # →अो→→आे→
+
+0914 ; 0905 093E 0948 ; MA # ( औ → अाै ) DEVANAGARI LETTER AU → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA, DEVANAGARI VOWEL SIGN AI # →अौ→→आै→
+
+0904 ; 0905 0946 ; MA # ( ऄ → अॆ ) DEVANAGARI LETTER SHORT A → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT E #
+
+0911 ; 0905 0949 ; MA # ( ऑ → अॉ ) DEVANAGARI LETTER CANDRA O → DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA O #
+
+090D ; 090F 0945 ; MA # ( ऍ → एॅ ) DEVANAGARI LETTER CANDRA E → DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN CANDRA E #
+
+090E ; 090F 0946 ; MA # ( ऎ → एॆ ) DEVANAGARI LETTER SHORT E → DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN SHORT E #
+
+0910 ; 090F 0947 ; MA # ( ऐ → एे ) DEVANAGARI LETTER AI → DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN E #
+
+0908 ; 0930 094D 0907 ; MA # ( ई → र्इ ) DEVANAGARI LETTER II → DEVANAGARI LETTER RA, DEVANAGARI SIGN VIRAMA, DEVANAGARI LETTER I #
+
+0ABD ; 093D ; MA # ( ઽ → ऽ ) GUJARATI SIGN AVAGRAHA → DEVANAGARI SIGN AVAGRAHA #
+
+111DC ; A8FB ; MA # ( 𑇜 → ꣻ ) SHARADA HEADSTROKE → DEVANAGARI HEADSTROKE #
+
+111CB ; 093A ; MA # ( 𑇋 → ऺ ) SHARADA VOWEL MODIFIER MARK → DEVANAGARI VOWEL SIGN OE #
+
+0AC1 ; 0941 ; MA # ( ુ → ु ) GUJARATI VOWEL SIGN U → DEVANAGARI VOWEL SIGN U #
+
+0AC2 ; 0942 ; MA # ( ૂ → ू ) GUJARATI VOWEL SIGN UU → DEVANAGARI VOWEL SIGN UU #
+
+0A4B ; 0946 ; MA # ( ੋ → ॆ ) GURMUKHI VOWEL SIGN OO → DEVANAGARI VOWEL SIGN SHORT E #
+
+0A4D ; 094D ; MA # ( ੍ → ् ) GURMUKHI SIGN VIRAMA → DEVANAGARI SIGN VIRAMA #
+0ACD ; 094D ; MA # ( ્ → ् ) GUJARATI SIGN VIRAMA → DEVANAGARI SIGN VIRAMA #
+
+0986 ; 0985 09BE ; MA # ( আ → অা ) BENGALI LETTER AA → BENGALI LETTER A, BENGALI VOWEL SIGN AA #
+
+09E0 ; 098B 09C3 ; MA # ( ৠ → ঋৃ ) BENGALI LETTER VOCALIC RR → BENGALI LETTER VOCALIC R, BENGALI VOWEL SIGN VOCALIC R #
+09E1 ; 098B 09C3 ; MA # ( ৡ → ঋৃ ) BENGALI LETTER VOCALIC LL → BENGALI LETTER VOCALIC R, BENGALI VOWEL SIGN VOCALIC R # →ঌৢ→→ৠ→
+
+11492 ; 0998 ; MA # ( 𑒒 → ঘ ) TIRHUTA LETTER GHA → BENGALI LETTER GHA #
+
+11494 ; 099A ; MA # ( 𑒔 → চ ) TIRHUTA LETTER CA → BENGALI LETTER CA #
+
+11496 ; 099C ; MA # ( 𑒖 → জ ) TIRHUTA LETTER JA → BENGALI LETTER JA #
+
+11498 ; 099E ; MA # ( 𑒘 → ঞ ) TIRHUTA LETTER NYA → BENGALI LETTER NYA #
+
+11499 ; 099F ; MA # ( 𑒙 → ট ) TIRHUTA LETTER TTA → BENGALI LETTER TTA #
+
+1149B ; 09A1 ; MA # ( 𑒛 → ড ) TIRHUTA LETTER DDA → BENGALI LETTER DDA #
+
+114AA ; 09A3 ; MA # ( 𑒪 → ণ ) TIRHUTA LETTER LA → BENGALI LETTER NNA #
+
+1149E ; 09A4 ; MA # ( 𑒞 → ত ) TIRHUTA LETTER TA → BENGALI LETTER TA #
+
+1149F ; 09A5 ; MA # ( 𑒟 → থ ) TIRHUTA LETTER THA → BENGALI LETTER THA #
+
+114A0 ; 09A6 ; MA # ( 𑒠 → দ ) TIRHUTA LETTER DA → BENGALI LETTER DA #
+
+114A1 ; 09A7 ; MA # ( 𑒡 → ধ ) TIRHUTA LETTER DHA → BENGALI LETTER DHA #
+
+114A2 ; 09A8 ; MA # ( 𑒢 → ন ) TIRHUTA LETTER NA → BENGALI LETTER NA #
+
+114A3 ; 09AA ; MA # ( 𑒣 → প ) TIRHUTA LETTER PA → BENGALI LETTER PA #
+
+114A9 ; 09AC ; MA # ( 𑒩 → ব ) TIRHUTA LETTER RA → BENGALI LETTER BA #
+
+114A7 ; 09AE ; MA # ( 𑒧 → ম ) TIRHUTA LETTER MA → BENGALI LETTER MA #
+
+114A8 ; 09AF ; MA # ( 𑒨 → য ) TIRHUTA LETTER YA → BENGALI LETTER YA #
+
+114AB ; 09B0 ; MA # ( 𑒫 → র ) TIRHUTA LETTER VA → BENGALI LETTER RA #
+
+1149D ; 09B2 ; MA # ( 𑒝 → ল ) TIRHUTA LETTER NNA → BENGALI LETTER LA #
+
+114AD ; 09B7 ; MA # ( 𑒭 → ষ ) TIRHUTA LETTER SSA → BENGALI LETTER SSA #
+
+114AE ; 09B8 ; MA # ( 𑒮 → স ) TIRHUTA LETTER SA → BENGALI LETTER SA #
+
+114C4 ; 09BD ; MA # ( 𑓄 → ঽ ) TIRHUTA SIGN AVAGRAHA → BENGALI SIGN AVAGRAHA #
+
+114B0 ; 09BE ; MA # ( 𑒰 → া ) TIRHUTA VOWEL SIGN AA → BENGALI VOWEL SIGN AA #
+
+114B1 ; 09BF ; MA # ( 𑒱 → ি ) TIRHUTA VOWEL SIGN I → BENGALI VOWEL SIGN I #
+
+114B9 ; 09C7 ; MA # ( 𑒹 → ে ) TIRHUTA VOWEL SIGN E → BENGALI VOWEL SIGN E #
+
+114BC ; 09CB ; MA # ( 𑒼 → ো ) TIRHUTA VOWEL SIGN O → BENGALI VOWEL SIGN O #
+
+114BE ; 09CC ; MA # ( 𑒾 → ৌ ) TIRHUTA VOWEL SIGN AU → BENGALI VOWEL SIGN AU #
+
+114C2 ; 09CD ; MA # ( 𑓂 → ্ ) TIRHUTA SIGN VIRAMA → BENGALI SIGN VIRAMA #
+
+114BD ; 09D7 ; MA # ( 𑒽 → ৗ ) TIRHUTA VOWEL SIGN SHORT O → BENGALI AU LENGTH MARK #
+
+0A09 ; 0A73 0A41 ; MA # ( ਉ → ੳੁ ) GURMUKHI LETTER U → GURMUKHI URA, GURMUKHI VOWEL SIGN U #
+
+0A0A ; 0A73 0A42 ; MA # ( ਊ → ੳੂ ) GURMUKHI LETTER UU → GURMUKHI URA, GURMUKHI VOWEL SIGN UU #
+
+0A06 ; 0A05 0A3E ; MA # ( ਆ → ਅਾ ) GURMUKHI LETTER AA → GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AA #
+
+0A10 ; 0A05 0A48 ; MA # ( ਐ → ਅੈ ) GURMUKHI LETTER AI → GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AI #
+
+0A14 ; 0A05 0A4C ; MA # ( ਔ → ਅੌ ) GURMUKHI LETTER AU → GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AU #
+
+0A07 ; 0A72 0A3F ; MA # ( ਇ → ੲਿ ) GURMUKHI LETTER I → GURMUKHI IRI, GURMUKHI VOWEL SIGN I #
+
+0A08 ; 0A72 0A40 ; MA # ( ਈ → ੲੀ ) GURMUKHI LETTER II → GURMUKHI IRI, GURMUKHI VOWEL SIGN II #
+
+0A0F ; 0A72 0A47 ; MA # ( ਏ → ੲੇ ) GURMUKHI LETTER EE → GURMUKHI IRI, GURMUKHI VOWEL SIGN EE #
+
+0A86 ; 0A85 0ABE ; MA # ( આ → અા ) GUJARATI LETTER AA → GUJARATI LETTER A, GUJARATI VOWEL SIGN AA #
+
+0A91 ; 0A85 0ABE 0AC5 ; MA # ( ઑ → અાૅ ) GUJARATI VOWEL CANDRA O → GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN CANDRA E # →અૉ→→આૅ→
+
+0A93 ; 0A85 0ABE 0AC7 ; MA # ( ઓ → અાે ) GUJARATI LETTER O → GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN E # →અો→→આે→
+
+0A94 ; 0A85 0ABE 0AC8 ; MA # ( ઔ → અાૈ ) GUJARATI LETTER AU → GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN AI # →અૌ→→આૈ→
+
+0A8D ; 0A85 0AC5 ; MA # ( ઍ → અૅ ) GUJARATI VOWEL CANDRA E → GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA E #
+
+0A8F ; 0A85 0AC7 ; MA # ( એ → અે ) GUJARATI LETTER E → GUJARATI LETTER A, GUJARATI VOWEL SIGN E #
+
+0A90 ; 0A85 0AC8 ; MA # ( ઐ → અૈ ) GUJARATI LETTER AI → GUJARATI LETTER A, GUJARATI VOWEL SIGN AI #
+
+0B06 ; 0B05 0B3E ; MA # ( ଆ → ଅା ) ORIYA LETTER AA → ORIYA LETTER A, ORIYA VOWEL SIGN AA #
+
+0BEE ; 0B85 ; MA # ( ௮ → அ ) TAMIL DIGIT EIGHT → TAMIL LETTER A #
+
+0BB0 ; 0B88 ; MA # ( ர → ஈ ) TAMIL LETTER RA → TAMIL LETTER II # →ா→
+0BBE ; 0B88 ; MA # ( ா → ஈ ) TAMIL VOWEL SIGN AA → TAMIL LETTER II #
+
+0BEB ; 0B88 0BC1 ; MA # ( ௫ → ஈு ) TAMIL DIGIT FIVE → TAMIL LETTER II, TAMIL VOWEL SIGN U # →ரு→
+
+0BE8 ; 0B89 ; MA # ( ௨ → உ ) TAMIL DIGIT TWO → TAMIL LETTER U #
+0D09 ; 0B89 ; MA # ( ഉ → உ ) MALAYALAM LETTER U → TAMIL LETTER U #
+
+0B8A ; 0B89 0BB3 ; MA # ( ஊ → உள ) TAMIL LETTER UU → TAMIL LETTER U, TAMIL LETTER LLA #
+
+0D0A ; 0B89 0D57 ; MA # ( ഊ → உൗ ) MALAYALAM LETTER UU → TAMIL LETTER U, MALAYALAM AU LENGTH MARK # →ഉൗ→
+
+0BED ; 0B8E ; MA # ( ௭ → எ ) TAMIL DIGIT SEVEN → TAMIL LETTER E #
+
+0BF7 ; 0B8E 0BB5 ; MA #* ( ௷ → எவ ) TAMIL CREDIT SIGN → TAMIL LETTER E, TAMIL LETTER VA #
+
+0B9C ; 0B90 ; MA # ( ஜ → ஐ ) TAMIL LETTER JA → TAMIL LETTER AI #
+0D1C ; 0B90 ; MA # ( ജ → ஐ ) MALAYALAM LETTER JA → TAMIL LETTER AI # →ஜ→
+
+0BE7 ; 0B95 ; MA # ( ௧ → க ) TAMIL DIGIT ONE → TAMIL LETTER KA #
+
+0BEA ; 0B9A ; MA # ( ௪ → ச ) TAMIL DIGIT FOUR → TAMIL LETTER CA #
+
+0BEC ; 0B9A 0BC1 ; MA # ( ௬ → சு ) TAMIL DIGIT SIX → TAMIL LETTER CA, TAMIL VOWEL SIGN U #
+
+0BF2 ; 0B9A 0BC2 ; MA #* ( ௲ → சூ ) TAMIL NUMBER ONE THOUSAND → TAMIL LETTER CA, TAMIL VOWEL SIGN UU #
+
+0D3A ; 0B9F 0BBF ; MA # ( ഺ → டி ) MALAYALAM LETTER TTTA → TAMIL LETTER TTA, TAMIL VOWEL SIGN I #
+
+0D23 ; 0BA3 ; MA # ( ണ → ண ) MALAYALAM LETTER NNA → TAMIL LETTER NNA #
+
+0BFA ; 0BA8 0BC0 ; MA #* ( ௺ → நீ ) TAMIL NUMBER SIGN → TAMIL LETTER NA, TAMIL VOWEL SIGN II #
+
+0BF4 ; 0BAE 0BC0 ; MA #* ( ௴ → மீ ) TAMIL MONTH SIGN → TAMIL LETTER MA, TAMIL VOWEL SIGN II #
+
+0BF0 ; 0BAF ; MA #* ( ௰ → ய ) TAMIL NUMBER TEN → TAMIL LETTER YA #
+
+0D34 ; 0BB4 ; MA # ( ഴ → ழ ) MALAYALAM LETTER LLLA → TAMIL LETTER LLLA #
+
+0BD7 ; 0BB3 ; MA # ( ௗ → ள ) TAMIL AU LENGTH MARK → TAMIL LETTER LLA #
+
+0BC8 ; 0BA9 ; MA # ( ை → ன ) TAMIL VOWEL SIGN AI → TAMIL LETTER NNNA #
+
+0D36 ; 0BB6 ; MA # ( ശ → ஶ ) MALAYALAM LETTER SHA → TAMIL LETTER SHA #
+
+0BF8 ; 0BB7 ; MA #* ( ௸ → ஷ ) TAMIL AS ABOVE SIGN → TAMIL LETTER SSA #
+
+0D3F ; 0BBF ; MA # ( ി → ி ) MALAYALAM VOWEL SIGN I → TAMIL VOWEL SIGN I #
+0D40 ; 0BBF ; MA # ( ീ → ி ) MALAYALAM VOWEL SIGN II → TAMIL VOWEL SIGN I #
+
+0BCA ; 0BC6 0B88 ; MA # ( ொ → ெஈ ) TAMIL VOWEL SIGN O → TAMIL VOWEL SIGN E, TAMIL LETTER II # →ெர→
+
+0BCC ; 0BC6 0BB3 ; MA # ( ௌ → ெள ) TAMIL VOWEL SIGN AU → TAMIL VOWEL SIGN E, TAMIL LETTER LLA #
+
+0BCB ; 0BC7 0B88 ; MA # ( ோ → ேஈ ) TAMIL VOWEL SIGN OO → TAMIL VOWEL SIGN EE, TAMIL LETTER II # →ேர→
+
+0C85 ; 0C05 ; MA # ( ಅ → అ ) KANNADA LETTER A → TELUGU LETTER A #
+
+0C86 ; 0C06 ; MA # ( ಆ → ఆ ) KANNADA LETTER AA → TELUGU LETTER AA #
+
+0C87 ; 0C07 ; MA # ( ಇ → ఇ ) KANNADA LETTER I → TELUGU LETTER I #
+
+0C60 ; 0C0B 0C3E ; MA # ( ౠ → ఋా ) TELUGU LETTER VOCALIC RR → TELUGU LETTER VOCALIC R, TELUGU VOWEL SIGN AA #
+
+0C61 ; 0C0C 0C3E ; MA # ( ౡ → ఌా ) TELUGU LETTER VOCALIC LL → TELUGU LETTER VOCALIC L, TELUGU VOWEL SIGN AA #
+
+0C92 ; 0C12 ; MA # ( ಒ → ఒ ) KANNADA LETTER O → TELUGU LETTER O #
+
+0C14 ; 0C12 0C4C ; MA # ( ఔ → ఒౌ ) TELUGU LETTER AU → TELUGU LETTER O, TELUGU VOWEL SIGN AU #
+0C94 ; 0C12 0C4C ; MA # ( ಔ → ఒౌ ) KANNADA LETTER AU → TELUGU LETTER O, TELUGU VOWEL SIGN AU # →ఔ→
+
+0C13 ; 0C12 0C55 ; MA # ( ఓ → ఒౕ ) TELUGU LETTER OO → TELUGU LETTER O, TELUGU LENGTH MARK #
+0C93 ; 0C12 0C55 ; MA # ( ಓ → ఒౕ ) KANNADA LETTER OO → TELUGU LETTER O, TELUGU LENGTH MARK # →ఓ→
+
+0C9C ; 0C1C ; MA # ( ಜ → జ ) KANNADA LETTER JA → TELUGU LETTER JA #
+
+0C9E ; 0C1E ; MA # ( ಞ → ఞ ) KANNADA LETTER NYA → TELUGU LETTER NYA #
+
+0C22 ; 0C21 0323 ; MA # ( ఢ → డ̣ ) TELUGU LETTER DDHA → TELUGU LETTER DDA, COMBINING DOT BELOW #
+
+0CA3 ; 0C23 ; MA # ( ಣ → ణ ) KANNADA LETTER NNA → TELUGU LETTER NNA #
+
+0C25 ; 0C27 05BC ; MA # ( థ → ధּ ) TELUGU LETTER THA → TELUGU LETTER DHA, HEBREW POINT DAGESH OR MAPIQ #
+
+0C2D ; 0C2C 0323 ; MA # ( భ → బ̣ ) TELUGU LETTER BHA → TELUGU LETTER BA, COMBINING DOT BELOW #
+
+0CAF ; 0C2F ; MA # ( ಯ → య ) KANNADA LETTER YA → TELUGU LETTER YA #
+
+0C20 ; 0C30 05BC ; MA # ( ఠ → రּ ) TELUGU LETTER TTHA → TELUGU LETTER RA, HEBREW POINT DAGESH OR MAPIQ #
+
+0CB1 ; 0C31 ; MA # ( ಱ → ఱ ) KANNADA LETTER RRA → TELUGU LETTER RRA #
+
+0CB2 ; 0C32 ; MA # ( ಲ → ల ) KANNADA LETTER LA → TELUGU LETTER LA #
+
+0C37 ; 0C35 0323 ; MA # ( ష → వ̣ ) TELUGU LETTER SSA → TELUGU LETTER VA, COMBINING DOT BELOW #
+
+0C39 ; 0C35 0C3E ; MA # ( హ → వా ) TELUGU LETTER HA → TELUGU LETTER VA, TELUGU VOWEL SIGN AA #
+
+0C2E ; 0C35 0C41 ; MA # ( మ → వు ) TELUGU LETTER MA → TELUGU LETTER VA, TELUGU VOWEL SIGN U #
+
+0C42 ; 0C41 0C3E ; MA # ( ూ → ుా ) TELUGU VOWEL SIGN UU → TELUGU VOWEL SIGN U, TELUGU VOWEL SIGN AA #
+
+0C44 ; 0C43 0C3E ; MA # ( ౄ → ృా ) TELUGU VOWEL SIGN VOCALIC RR → TELUGU VOWEL SIGN VOCALIC R, TELUGU VOWEL SIGN AA #
+
+0CE1 ; 0C8C 0CBE ; MA # ( ೡ → ಌಾ ) KANNADA LETTER VOCALIC LL → KANNADA LETTER VOCALIC L, KANNADA VOWEL SIGN AA #
+
+0D08 ; 0D07 0D57 ; MA # ( ഈ → ഇൗ ) MALAYALAM LETTER II → MALAYALAM LETTER I, MALAYALAM AU LENGTH MARK #
+
+0D10 ; 0D0E 0D46 ; MA # ( ഐ → എെ ) MALAYALAM LETTER AI → MALAYALAM LETTER E, MALAYALAM VOWEL SIGN E #
+
+0D13 ; 0D12 0D3E ; MA # ( ഓ → ഒാ ) MALAYALAM LETTER OO → MALAYALAM LETTER O, MALAYALAM VOWEL SIGN AA #
+
+0D14 ; 0D12 0D57 ; MA # ( ഔ → ഒൗ ) MALAYALAM LETTER AU → MALAYALAM LETTER O, MALAYALAM AU LENGTH MARK #
+
+0D61 ; 0D1E ; MA # ( ൡ → ഞ ) MALAYALAM LETTER VOCALIC LL → MALAYALAM LETTER NYA #
+
+0D6B ; 0D26 0D4D 0D30 ; MA # ( ൫ → ദ്ര ) MALAYALAM DIGIT FIVE → MALAYALAM LETTER DA, MALAYALAM SIGN VIRAMA, MALAYALAM LETTER RA #
+
+0D79 ; 0D28 0D41 ; MA #* ( ൹ → നു ) MALAYALAM DATE MARK → MALAYALAM LETTER NA, MALAYALAM VOWEL SIGN U #
+0D0C ; 0D28 0D41 ; MA # ( ഌ → നു ) MALAYALAM LETTER VOCALIC L → MALAYALAM LETTER NA, MALAYALAM VOWEL SIGN U #
+0D19 ; 0D28 0D41 ; MA # ( ങ → നു ) MALAYALAM LETTER NGA → MALAYALAM LETTER NA, MALAYALAM VOWEL SIGN U # →ഌ→
+
+0D6F ; 0D28 0D4D ; MA # ( ൯ → ന് ) MALAYALAM DIGIT NINE → MALAYALAM LETTER NA, MALAYALAM SIGN VIRAMA #
+0D7B ; 0D28 0D4D ; MA # ( ൻ → ന് ) MALAYALAM LETTER CHILLU N → MALAYALAM LETTER NA, MALAYALAM SIGN VIRAMA # →൯→
+
+0D6C ; 0D28 0D4D 0D28 ; MA # ( ൬ → ന്ന ) MALAYALAM DIGIT SIX → MALAYALAM LETTER NA, MALAYALAM SIGN VIRAMA, MALAYALAM LETTER NA #
+
+0D5A ; 0D28 0D4D 0D2E ; MA #* ( ൚ → ന്മ ) MALAYALAM FRACTION THREE EIGHTIETHS → MALAYALAM LETTER NA, MALAYALAM SIGN VIRAMA, MALAYALAM LETTER MA #
+
+0D31 ; 0D30 ; MA # ( റ → ര ) MALAYALAM LETTER RRA → MALAYALAM LETTER RA #
+
+0D6A ; 0D30 0D4D ; MA # ( ൪ → ര് ) MALAYALAM DIGIT FOUR → MALAYALAM LETTER RA, MALAYALAM SIGN VIRAMA #
+0D7C ; 0D30 0D4D ; MA # ( ർ → ര് ) MALAYALAM LETTER CHILLU RR → MALAYALAM LETTER RA, MALAYALAM SIGN VIRAMA # →൪→
+
+0D6E ; 0D35 0D4D 0D30 ; MA # ( ൮ → വ്ര ) MALAYALAM DIGIT EIGHT → MALAYALAM LETTER VA, MALAYALAM SIGN VIRAMA, MALAYALAM LETTER RA #
+
+0D76 ; 0D39 0D4D 0D2E ; MA #* ( ൶ → ഹ്മ ) MALAYALAM FRACTION ONE SIXTEENTH → MALAYALAM LETTER HA, MALAYALAM SIGN VIRAMA, MALAYALAM LETTER MA #
+
+0D42 ; 0D41 ; MA # ( ൂ → ു ) MALAYALAM VOWEL SIGN UU → MALAYALAM VOWEL SIGN U #
+0D43 ; 0D41 ; MA # ( ൃ → ു ) MALAYALAM VOWEL SIGN VOCALIC R → MALAYALAM VOWEL SIGN U # →ൂ→
+
+0D48 ; 0D46 0D46 ; MA # ( ൈ → െെ ) MALAYALAM VOWEL SIGN AI → MALAYALAM VOWEL SIGN E, MALAYALAM VOWEL SIGN E #
+
+0DEA ; 0DA2 ; MA # ( ෪ → ජ ) SINHALA LITH DIGIT FOUR → SINHALA LETTER ALPAPRAANA JAYANNA #
+
+0DEB ; 0DAF ; MA # ( ෫ → ද ) SINHALA LITH DIGIT FIVE → SINHALA LETTER ALPAPRAANA DAYANNA #
+
+11413 ; 11434 11442 11412 ; MA # ( 𑐓 → 𑐴𑑂𑐒 ) NEWA LETTER NGHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER NGA #
+
+11419 ; 11434 11442 11418 ; MA # ( 𑐙 → 𑐴𑑂𑐘 ) NEWA LETTER NYHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER NYA #
+
+11424 ; 11434 11442 11423 ; MA # ( 𑐤 → 𑐴𑑂𑐣 ) NEWA LETTER NHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER NA #
+
+1142A ; 11434 11442 11429 ; MA # ( 𑐪 → 𑐴𑑂𑐩 ) NEWA LETTER MHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER MA #
+
+1142D ; 11434 11442 1142C ; MA # ( 𑐭 → 𑐴𑑂𑐬 ) NEWA LETTER RHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER RA #
+
+1142F ; 11434 11442 1142E ; MA # ( 𑐯 → 𑐴𑑂𑐮 ) NEWA LETTER LHA → NEWA LETTER HA, NEWA SIGN VIRAMA, NEWA LETTER LA #
+
+115D8 ; 11582 ; MA # ( 𑗘 → 𑖂 ) SIDDHAM LETTER THREE-CIRCLE ALTERNATE I → SIDDHAM LETTER I #
+115D9 ; 11582 ; MA # ( 𑗙 → 𑖂 ) SIDDHAM LETTER TWO-CIRCLE ALTERNATE I → SIDDHAM LETTER I #
+
+115DA ; 11583 ; MA # ( 𑗚 → 𑖃 ) SIDDHAM LETTER TWO-CIRCLE ALTERNATE II → SIDDHAM LETTER II #
+
+115DB ; 11584 ; MA # ( 𑗛 → 𑖄 ) SIDDHAM LETTER ALTERNATE U → SIDDHAM LETTER U #
+
+115DC ; 115B2 ; MA # ( 𑗜 → 𑖲 ) SIDDHAM VOWEL SIGN ALTERNATE U → SIDDHAM VOWEL SIGN U #
+
+115DD ; 115B3 ; MA # ( 𑗝 → 𑖳 ) SIDDHAM VOWEL SIGN ALTERNATE UU → SIDDHAM VOWEL SIGN UU #
+
+0E03 ; 0E02 ; MA # ( ฃ → ข ) THAI CHARACTER KHO KHUAT → THAI CHARACTER KHO KHAI #
+
+0E14 ; 0E04 ; MA # ( ด → ค ) THAI CHARACTER DO DEK → THAI CHARACTER KHO KHWAI #
+0E15 ; 0E04 ; MA # ( ต → ค ) THAI CHARACTER TO TAO → THAI CHARACTER KHO KHWAI # →ด→
+
+0E21 ; 0E06 ; MA # ( ม → ฆ ) THAI CHARACTER MO MA → THAI CHARACTER KHO RAKHANG #
+
+0E88 ; 0E08 ; MA # ( ຈ → จ ) LAO LETTER CO → THAI CHARACTER CHO CHAN #
+
+0E0B ; 0E0A ; MA # ( ซ → ช ) THAI CHARACTER SO SO → THAI CHARACTER CHO CHANG #
+
+0E0F ; 0E0E ; MA # ( ฏ → ฎ ) THAI CHARACTER TO PATAK → THAI CHARACTER DO CHADA #
+
+0E17 ; 0E11 ; MA # ( ท → ฑ ) THAI CHARACTER THO THAHAN → THAI CHARACTER THO NANGMONTHO #
+
+0E9A ; 0E1A ; MA # ( ບ → บ ) LAO LETTER BO → THAI CHARACTER BO BAIMAI #
+
+0E9B ; 0E1B ; MA # ( ປ → ป ) LAO LETTER PO → THAI CHARACTER PO PLA #
+
+0E9D ; 0E1D ; MA # ( ຝ → ฝ ) LAO LETTER FO TAM → THAI CHARACTER FO FA #
+
+0E9E ; 0E1E ; MA # ( ພ → พ ) LAO LETTER PHO TAM → THAI CHARACTER PHO PHAN #
+
+0E9F ; 0E1F ; MA # ( ຟ → ฟ ) LAO LETTER FO SUNG → THAI CHARACTER FO FAN #
+
+0E26 ; 0E20 ; MA # ( ฦ → ภ ) THAI CHARACTER LU → THAI CHARACTER PHO SAMPHAO #
+
+0E8D ; 0E22 ; MA # ( ຍ → ย ) LAO LETTER NYO → THAI CHARACTER YO YAK #
+
+17D4 ; 0E2F ; MA #* ( ។ → ฯ ) KHMER SIGN KHAN → THAI CHARACTER PAIYANNOI #
+
+0E45 ; 0E32 ; MA # ( ๅ → า ) THAI CHARACTER LAKKHANGYAO → THAI CHARACTER SARA AA #
+
+0E33 ; 030A 0E32 ; MA # ( ำ → ̊า ) THAI CHARACTER SARA AM → COMBINING RING ABOVE, THAI CHARACTER SARA AA # →ํา→
+
+17B7 ; 0E34 ; MA # ( ិ → ิ ) KHMER VOWEL SIGN I → THAI CHARACTER SARA I #
+
+17B8 ; 0E35 ; MA # ( ី → ี ) KHMER VOWEL SIGN II → THAI CHARACTER SARA II #
+
+17B9 ; 0E36 ; MA # ( ឹ → ึ ) KHMER VOWEL SIGN Y → THAI CHARACTER SARA UE #
+
+17BA ; 0E37 ; MA # ( ឺ → ื ) KHMER VOWEL SIGN YY → THAI CHARACTER SARA UEE #
+
+0EB8 ; 0E38 ; MA # ( ຸ → ุ ) LAO VOWEL SIGN U → THAI CHARACTER SARA U #
+
+0EB9 ; 0E39 ; MA # ( ູ → ู ) LAO VOWEL SIGN UU → THAI CHARACTER SARA UU #
+
+0E41 ; 0E40 0E40 ; MA # ( แ → เเ ) THAI CHARACTER SARA AE → THAI CHARACTER SARA E, THAI CHARACTER SARA E #
+
+0EDC ; 0EAB 0E99 ; MA # ( ໜ → ຫນ ) LAO HO NO → LAO LETTER HO SUNG, LAO LETTER NO #
+
+0EDD ; 0EAB 0EA1 ; MA # ( ໝ → ຫມ ) LAO HO MO → LAO LETTER HO SUNG, LAO LETTER MO #
+
+0EB3 ; 030A 0EB2 ; MA # ( ຳ → ̊າ ) LAO VOWEL SIGN AM → COMBINING RING ABOVE, LAO VOWEL SIGN AA # →ໍາ→
+
+0F02 ; 0F60 0F74 0F82 0F7F ; MA #* ( ༂ → འུྂཿ ) TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA → TIBETAN LETTER -A, TIBETAN VOWEL SIGN U, TIBETAN SIGN NYI ZLA NAA DA, TIBETAN SIGN RNAM BCAD #
+
+0F03 ; 0F60 0F74 0F82 0F14 ; MA #* ( ༃ → འུྂ༔ ) TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA → TIBETAN LETTER -A, TIBETAN VOWEL SIGN U, TIBETAN SIGN NYI ZLA NAA DA, TIBETAN MARK GTER TSHEG #
+
+0F6A ; 0F62 ; MA # ( ཪ → ར ) TIBETAN LETTER FIXED-FORM RA → TIBETAN LETTER RA #
+
+0F00 ; 0F68 0F7C 0F7E ; MA # ( ༀ → ཨོཾ ) TIBETAN SYLLABLE OM → TIBETAN LETTER A, TIBETAN VOWEL SIGN O, TIBETAN SIGN RJES SU NGA RO #
+
+0F77 ; 0FB2 0F71 0F80 ; MA # ( ཷ → ྲཱྀ ) TIBETAN VOWEL SIGN VOCALIC RR → TIBETAN SUBJOINED LETTER RA, TIBETAN VOWEL SIGN AA, TIBETAN VOWEL SIGN REVERSED I #
+
+0F79 ; 0FB3 0F71 0F80 ; MA # ( ཹ → ླཱྀ ) TIBETAN VOWEL SIGN VOCALIC LL → TIBETAN SUBJOINED LETTER LA, TIBETAN VOWEL SIGN AA, TIBETAN VOWEL SIGN REVERSED I #
+
+11CB2 ; 11CAA ; MA # ( 𑲲 → 𑲪 ) MARCHEN VOWEL SIGN U → MARCHEN SUBJOINED LETTER RA #
+
+1081 ; 1002 103E ; MA # ( ႁ → ဂှ ) MYANMAR LETTER SHAN HA → MYANMAR LETTER GA, MYANMAR CONSONANT SIGN MEDIAL HA #
+
+1000 ; 1002 102C ; MA # ( က → ဂာ ) MYANMAR LETTER KA → MYANMAR LETTER GA, MYANMAR VOWEL SIGN AA #
+
+1070 ; 1003 103E ; MA # ( ၰ → ဃှ ) MYANMAR LETTER EASTERN PWO KAREN GHWA → MYANMAR LETTER GHA, MYANMAR CONSONANT SIGN MEDIAL HA #
+
+1066 ; 1015 103E ; MA # ( ၦ → ပှ ) MYANMAR LETTER WESTERN PWO KAREN PWA → MYANMAR LETTER PA, MYANMAR CONSONANT SIGN MEDIAL HA #
+
+101F ; 1015 102C ; MA # ( ဟ → ပာ ) MYANMAR LETTER HA → MYANMAR LETTER PA, MYANMAR VOWEL SIGN AA #
+
+106F ; 1015 102C 103E ; MA # ( ၯ → ပာှ ) MYANMAR LETTER EASTERN PWO KAREN YWA → MYANMAR LETTER PA, MYANMAR VOWEL SIGN AA, MYANMAR CONSONANT SIGN MEDIAL HA # →ဟှ→
+
+107E ; 107D 103E ; MA # ( ၾ → ၽှ ) MYANMAR LETTER SHAN FA → MYANMAR LETTER SHAN PHA, MYANMAR CONSONANT SIGN MEDIAL HA #
+
+1029 ; 101E 103C ; MA # ( ဩ → သြ ) MYANMAR LETTER O → MYANMAR LETTER SA, MYANMAR CONSONANT SIGN MEDIAL RA #
+
+102A ; 101E 103C 1031 102C 103A ; MA # ( ဪ → သြော် ) MYANMAR LETTER AU → MYANMAR LETTER SA, MYANMAR CONSONANT SIGN MEDIAL RA, MYANMAR VOWEL SIGN E, MYANMAR VOWEL SIGN AA, MYANMAR SIGN ASAT # →ဩော်→
+
+109E ; 1083 030A ; MA #* ( ႞ → ႃ̊ ) MYANMAR SYMBOL SHAN ONE → MYANMAR VOWEL SIGN SHAN AA, COMBINING RING ABOVE # →ႃံ→
+
+17A3 ; 17A2 ; MA # ( ឣ → អ ) KHMER INDEPENDENT VOWEL QAQ → KHMER LETTER QA #
+
+19D0 ; 199E ; MA # ( ᧐ → ᦞ ) NEW TAI LUE DIGIT ZERO → NEW TAI LUE LETTER LOW VA #
+
+19D1 ; 19B1 ; MA # ( ᧑ → ᦱ ) NEW TAI LUE DIGIT ONE → NEW TAI LUE VOWEL SIGN AA #
+
+1A80 ; 1A45 ; MA # ( ᪀ → ᩅ ) TAI THAM HORA DIGIT ZERO → TAI THAM LETTER WA #
+1A90 ; 1A45 ; MA # ( ᪐ → ᩅ ) TAI THAM THAM DIGIT ZERO → TAI THAM LETTER WA #
+
+AA53 ; AA01 ; MA # ( ꩓ → ꨁ ) CHAM DIGIT THREE → CHAM LETTER I #
+
+AA56 ; AA23 ; MA # ( ꩖ → ꨣ ) CHAM DIGIT SIX → CHAM LETTER RA #
+
+1B52 ; 1B0D ; MA # ( ᭒ → ᬍ ) BALINESE DIGIT TWO → BALINESE LETTER LA LENGA #
+
+1B53 ; 1B11 ; MA # ( ᭓ → ᬑ ) BALINESE DIGIT THREE → BALINESE LETTER OKARA #
+
+1B58 ; 1B28 ; MA # ( ᭘ → ᬨ ) BALINESE DIGIT EIGHT → BALINESE LETTER PA KAPAL #
+
+A9A3 ; A99D ; MA # ( ꦣ → ꦝ ) JAVANESE LETTER DA MAHAPRANA → JAVANESE LETTER DDA #
+
+1896 ; 185C ; MA # ( ᢖ → ᡜ ) MONGOLIAN LETTER ALI GALI ZA → MONGOLIAN LETTER TODO DZA #
+
+1855 ; 1835 ; MA # ( ᡕ → ᠵ ) MONGOLIAN LETTER TODO YA → MONGOLIAN LETTER JA #
+
+1FF6 ; 13EF ; MA # ( ῶ → Ꮿ ) GREEK SMALL LETTER OMEGA WITH PERISPOMENI → CHEROKEE LETTER YA #
+
+140D ; 1401 00B7 ; MA # ( ᐍ → ᐁ· ) CANADIAN SYLLABICS WEST-CREE WE → CANADIAN SYLLABICS E, MIDDLE DOT # →ᐁᐧ→
+
+142B ; 1401 1420 ; MA # ( ᐫ → ᐁᐠ ) CANADIAN SYLLABICS EN → CANADIAN SYLLABICS E, CANADIAN SYLLABICS FINAL GRAVE #
+
+1411 ; 1404 00B7 ; MA # ( ᐑ → ᐄ· ) CANADIAN SYLLABICS WEST-CREE WII → CANADIAN SYLLABICS II, MIDDLE DOT # →ᐄᐧ→
+
+1413 ; 1405 00B7 ; MA # ( ᐓ → ᐅ· ) CANADIAN SYLLABICS WEST-CREE WO → CANADIAN SYLLABICS O, MIDDLE DOT # →ᐅᐧ→
+
+142D ; 1405 1420 ; MA # ( ᐭ → ᐅᐠ ) CANADIAN SYLLABICS ON → CANADIAN SYLLABICS O, CANADIAN SYLLABICS FINAL GRAVE #
+
+1415 ; 1406 00B7 ; MA # ( ᐕ → ᐆ· ) CANADIAN SYLLABICS WEST-CREE WOO → CANADIAN SYLLABICS OO, MIDDLE DOT # →ᐆᐧ→
+
+1418 ; 140A 00B7 ; MA # ( ᐘ → ᐊ· ) CANADIAN SYLLABICS WEST-CREE WA → CANADIAN SYLLABICS A, MIDDLE DOT # →ᐊᐧ→
+
+142E ; 140A 1420 ; MA # ( ᐮ → ᐊᐠ ) CANADIAN SYLLABICS AN → CANADIAN SYLLABICS A, CANADIAN SYLLABICS FINAL GRAVE #
+
+141A ; 140B 00B7 ; MA # ( ᐚ → ᐋ· ) CANADIAN SYLLABICS WEST-CREE WAA → CANADIAN SYLLABICS AA, MIDDLE DOT # →ᐋᐧ→
+
+18DD ; 141E 18DF ; MA # ( ᣝ → ᐞᣟ ) CANADIAN SYLLABICS WESTERN W → CANADIAN SYLLABICS GLOTTAL STOP, CANADIAN SYLLABICS FINAL RAISED DOT #
+
+14D1 ; 1421 ; MA # ( ᓑ → ᐡ ) CANADIAN SYLLABICS CARRIER NG → CANADIAN SYLLABICS FINAL BOTTOM HALF RING #
+
+1540 ; 1429 ; MA # ( ᕀ → ᐩ ) CANADIAN SYLLABICS WEST-CREE Y → CANADIAN SYLLABICS FINAL PLUS #
+
+143F ; 1432 00B7 ; MA # ( ᐿ → ᐲ· ) CANADIAN SYLLABICS WEST-CREE PWII → CANADIAN SYLLABICS PII, MIDDLE DOT # →ᐲᐧ→
+
+1443 ; 1434 00B7 ; MA # ( ᑃ → ᐴ· ) CANADIAN SYLLABICS WEST-CREE PWOO → CANADIAN SYLLABICS POO, MIDDLE DOT # →ᐴᐧ→
+
+2369 ; 1435 ; MA #* ( ⍩ → ᐵ ) APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS → CANADIAN SYLLABICS Y-CREE POO #
+
+1447 ; 1439 00B7 ; MA # ( ᑇ → ᐹ· ) CANADIAN SYLLABICS WEST-CREE PWAA → CANADIAN SYLLABICS PAA, MIDDLE DOT # →ᐹᐧ→
+
+145C ; 144F 00B7 ; MA # ( ᑜ → ᑏ· ) CANADIAN SYLLABICS WEST-CREE TWII → CANADIAN SYLLABICS TII, MIDDLE DOT # →ᑏᐧ→
+
+2E27 ; 1450 ; MA #* ( ⸧ → ᑐ ) RIGHT SIDEWAYS U BRACKET → CANADIAN SYLLABICS TO # →⊃→
+2283 ; 1450 ; MA #* ( ⊃ → ᑐ ) SUPERSET OF → CANADIAN SYLLABICS TO #
+
+145E ; 1450 00B7 ; MA # ( ᑞ → ᑐ· ) CANADIAN SYLLABICS WEST-CREE TWO → CANADIAN SYLLABICS TO, MIDDLE DOT # →ᑐᐧ→
+
+1469 ; 1450 0027 ; MA # ( ᑩ → ᑐ' ) CANADIAN SYLLABICS TTO → CANADIAN SYLLABICS TO, APOSTROPHE # →ᑐᑊ→
+
+27C9 ; 1450 002F ; MA #* ( ⟉ → ᑐ/ ) SUPERSET PRECEDING SOLIDUS → CANADIAN SYLLABICS TO, SOLIDUS # →⊃/→
+
+2AD7 ; 1450 1455 ; MA #* ( ⫗ → ᑐᑕ ) SUPERSET BESIDE SUBSET → CANADIAN SYLLABICS TO, CANADIAN SYLLABICS TA # →⊃⊂→
+
+1460 ; 1451 00B7 ; MA # ( ᑠ → ᑑ· ) CANADIAN SYLLABICS WEST-CREE TWOO → CANADIAN SYLLABICS TOO, MIDDLE DOT # →ᑑᐧ→
+
+2E26 ; 1455 ; MA #* ( ⸦ → ᑕ ) LEFT SIDEWAYS U BRACKET → CANADIAN SYLLABICS TA # →⊂→
+2282 ; 1455 ; MA #* ( ⊂ → ᑕ ) SUBSET OF → CANADIAN SYLLABICS TA #
+
+1462 ; 1455 00B7 ; MA # ( ᑢ → ᑕ· ) CANADIAN SYLLABICS WEST-CREE TWA → CANADIAN SYLLABICS TA, MIDDLE DOT # →ᑕᐧ→
+
+146A ; 1455 0027 ; MA # ( ᑪ → ᑕ' ) CANADIAN SYLLABICS TTA → CANADIAN SYLLABICS TA, APOSTROPHE # →ᑕᑊ→
+
+1464 ; 1456 00B7 ; MA # ( ᑤ → ᑖ· ) CANADIAN SYLLABICS WEST-CREE TWAA → CANADIAN SYLLABICS TAA, MIDDLE DOT # →ᑖᐧ→
+
+1475 ; 146B 00B7 ; MA # ( ᑵ → ᑫ· ) CANADIAN SYLLABICS WEST-CREE KWE → CANADIAN SYLLABICS KE, MIDDLE DOT # →ᑫᐧ→
+
+1485 ; 146B 0027 ; MA # ( ᒅ → ᑫ' ) CANADIAN SYLLABICS SOUTH-SLAVEY KEH → CANADIAN SYLLABICS KE, APOSTROPHE # →ᑫᑊ→
+
+1479 ; 146E 00B7 ; MA # ( ᑹ → ᑮ· ) CANADIAN SYLLABICS WEST-CREE KWII → CANADIAN SYLLABICS KII, MIDDLE DOT # →ᑮᐧ→
+
+147D ; 1470 00B7 ; MA # ( ᑽ → ᑰ· ) CANADIAN SYLLABICS WEST-CREE KWOO → CANADIAN SYLLABICS KOO, MIDDLE DOT # →ᑰᐧ→
+
+1603 ; 1489 ; MA # ( ᘃ → ᒉ ) CANADIAN SYLLABICS CARRIER NO → CANADIAN SYLLABICS CE #
+
+1493 ; 1489 00B7 ; MA # ( ᒓ → ᒉ· ) CANADIAN SYLLABICS WEST-CREE CWE → CANADIAN SYLLABICS CE, MIDDLE DOT # →ᒉᐧ→
+
+1495 ; 148B 00B7 ; MA # ( ᒕ → ᒋ· ) CANADIAN SYLLABICS WEST-CREE CWI → CANADIAN SYLLABICS CI, MIDDLE DOT # →ᒋᐧ→
+
+1497 ; 148C 00B7 ; MA # ( ᒗ → ᒌ· ) CANADIAN SYLLABICS WEST-CREE CWII → CANADIAN SYLLABICS CII, MIDDLE DOT # →ᒌᐧ→
+
+149B ; 148E 00B7 ; MA # ( ᒛ → ᒎ· ) CANADIAN SYLLABICS WEST-CREE CWOO → CANADIAN SYLLABICS COO, MIDDLE DOT # →ᒎᐧ→
+
+1602 ; 1490 ; MA # ( ᘂ → ᒐ ) CANADIAN SYLLABICS CARRIER NU → CANADIAN SYLLABICS CA #
+
+149D ; 1490 00B7 ; MA # ( ᒝ → ᒐ· ) CANADIAN SYLLABICS WEST-CREE CWA → CANADIAN SYLLABICS CA, MIDDLE DOT # →ᒐᐧ→
+
+149F ; 1491 00B7 ; MA # ( ᒟ → ᒑ· ) CANADIAN SYLLABICS WEST-CREE CWAA → CANADIAN SYLLABICS CAA, MIDDLE DOT # →ᒑᐧ→
+
+14AD ; 14A3 00B7 ; MA # ( ᒭ → ᒣ· ) CANADIAN SYLLABICS WEST-CREE MWE → CANADIAN SYLLABICS ME, MIDDLE DOT # →ᒣᐧ→
+
+14B1 ; 14A6 00B7 ; MA # ( ᒱ → ᒦ· ) CANADIAN SYLLABICS WEST-CREE MWII → CANADIAN SYLLABICS MII, MIDDLE DOT # →ᒦᐧ→
+
+14B3 ; 14A7 00B7 ; MA # ( ᒳ → ᒧ· ) CANADIAN SYLLABICS WEST-CREE MWO → CANADIAN SYLLABICS MO, MIDDLE DOT # →ᒧᐧ→
+
+14B5 ; 14A8 00B7 ; MA # ( ᒵ → ᒨ· ) CANADIAN SYLLABICS WEST-CREE MWOO → CANADIAN SYLLABICS MOO, MIDDLE DOT # →ᒨᐧ→
+
+14B9 ; 14AB 00B7 ; MA # ( ᒹ → ᒫ· ) CANADIAN SYLLABICS WEST-CREE MWAA → CANADIAN SYLLABICS MAA, MIDDLE DOT # →ᒫᐧ→
+
+14CA ; 14C0 00B7 ; MA # ( ᓊ → ᓀ· ) CANADIAN SYLLABICS WEST-CREE NWE → CANADIAN SYLLABICS NE, MIDDLE DOT # →ᓀᐧ→
+
+18C7 ; 14C2 00B7 ; MA # ( ᣇ → ᓂ· ) CANADIAN SYLLABICS OJIBWAY NWI → CANADIAN SYLLABICS NI, MIDDLE DOT # →ᓂᐧ→
+
+18C9 ; 14C3 00B7 ; MA # ( ᣉ → ᓃ· ) CANADIAN SYLLABICS OJIBWAY NWII → CANADIAN SYLLABICS NII, MIDDLE DOT # →ᓃᐧ→
+
+18CB ; 14C4 00B7 ; MA # ( ᣋ → ᓄ· ) CANADIAN SYLLABICS OJIBWAY NWO → CANADIAN SYLLABICS NO, MIDDLE DOT # →ᓄᐧ→
+
+18CD ; 14C5 00B7 ; MA # ( ᣍ → ᓅ· ) CANADIAN SYLLABICS OJIBWAY NWOO → CANADIAN SYLLABICS NOO, MIDDLE DOT # →ᓅᐧ→
+
+14CC ; 14C7 00B7 ; MA # ( ᓌ → ᓇ· ) CANADIAN SYLLABICS WEST-CREE NWA → CANADIAN SYLLABICS NA, MIDDLE DOT # →ᓇᐧ→
+
+14CE ; 14C8 00B7 ; MA # ( ᓎ → ᓈ· ) CANADIAN SYLLABICS WEST-CREE NWAA → CANADIAN SYLLABICS NAA, MIDDLE DOT # →ᓈᐧ→
+
+1604 ; 14D3 ; MA # ( ᘄ → ᓓ ) CANADIAN SYLLABICS CARRIER NE → CANADIAN SYLLABICS LE #
+
+14DD ; 14D3 00B7 ; MA # ( ᓝ → ᓓ· ) CANADIAN SYLLABICS WEST-CREE LWE → CANADIAN SYLLABICS LE, MIDDLE DOT # →ᓓᐧ→
+
+14DF ; 14D5 00B7 ; MA # ( ᓟ → ᓕ· ) CANADIAN SYLLABICS WEST-CREE LWI → CANADIAN SYLLABICS LI, MIDDLE DOT # →ᓕᐧ→
+
+14E1 ; 14D6 00B7 ; MA # ( ᓡ → ᓖ· ) CANADIAN SYLLABICS WEST-CREE LWII → CANADIAN SYLLABICS LII, MIDDLE DOT # →ᓖᐧ→
+
+14E3 ; 14D7 00B7 ; MA # ( ᓣ → ᓗ· ) CANADIAN SYLLABICS WEST-CREE LWO → CANADIAN SYLLABICS LO, MIDDLE DOT # →ᓗᐧ→
+
+14E5 ; 14D8 00B7 ; MA # ( ᓥ → ᓘ· ) CANADIAN SYLLABICS WEST-CREE LWOO → CANADIAN SYLLABICS LOO, MIDDLE DOT # →ᓘᐧ→
+
+1607 ; 14DA ; MA # ( ᘇ → ᓚ ) CANADIAN SYLLABICS CARRIER NA → CANADIAN SYLLABICS LA #
+
+14E7 ; 14DA 00B7 ; MA # ( ᓧ → ᓚ· ) CANADIAN SYLLABICS WEST-CREE LWA → CANADIAN SYLLABICS LA, MIDDLE DOT # →ᓚᐧ→
+
+14E9 ; 14DB 00B7 ; MA # ( ᓩ → ᓛ· ) CANADIAN SYLLABICS WEST-CREE LWAA → CANADIAN SYLLABICS LAA, MIDDLE DOT # →ᓛᐧ→
+
+14F7 ; 14ED 00B7 ; MA # ( ᓷ → ᓭ· ) CANADIAN SYLLABICS WEST-CREE SWE → CANADIAN SYLLABICS SE, MIDDLE DOT # →ᓭᐧ→
+
+14F9 ; 14EF 00B7 ; MA # ( ᓹ → ᓯ· ) CANADIAN SYLLABICS WEST-CREE SWI → CANADIAN SYLLABICS SI, MIDDLE DOT # →ᓯᐧ→
+
+14FB ; 14F0 00B7 ; MA # ( ᓻ → ᓰ· ) CANADIAN SYLLABICS WEST-CREE SWII → CANADIAN SYLLABICS SII, MIDDLE DOT # →ᓰᐧ→
+
+14FD ; 14F1 00B7 ; MA # ( ᓽ → ᓱ· ) CANADIAN SYLLABICS WEST-CREE SWO → CANADIAN SYLLABICS SO, MIDDLE DOT # →ᓱᐧ→
+
+14FF ; 14F2 00B7 ; MA # ( ᓿ → ᓲ· ) CANADIAN SYLLABICS WEST-CREE SWOO → CANADIAN SYLLABICS SOO, MIDDLE DOT # →ᓲᐧ→
+
+1501 ; 14F4 00B7 ; MA # ( ᔁ → ᓴ· ) CANADIAN SYLLABICS WEST-CREE SWA → CANADIAN SYLLABICS SA, MIDDLE DOT # →ᓴᐧ→
+
+1503 ; 14F5 00B7 ; MA # ( ᔃ → ᓵ· ) CANADIAN SYLLABICS WEST-CREE SWAA → CANADIAN SYLLABICS SAA, MIDDLE DOT # →ᓵᐧ→
+
+150C ; 150B 003C ; MA # ( ᔌ → ᔋ< ) CANADIAN SYLLABICS NASKAPI SPWA → CANADIAN SYLLABICS NASKAPI S-W, LESS-THAN SIGN # →ᔋᐸ→
+
+150E ; 150B 0062 ; MA # ( ᔎ → ᔋb ) CANADIAN SYLLABICS NASKAPI SKWA → CANADIAN SYLLABICS NASKAPI S-W, LATIN SMALL LETTER B # →ᔋᑲ→
+
+150D ; 150B 1455 ; MA # ( ᔍ → ᔋᑕ ) CANADIAN SYLLABICS NASKAPI STWA → CANADIAN SYLLABICS NASKAPI S-W, CANADIAN SYLLABICS TA #
+
+150F ; 150B 1490 ; MA # ( ᔏ → ᔋᒐ ) CANADIAN SYLLABICS NASKAPI SCWA → CANADIAN SYLLABICS NASKAPI S-W, CANADIAN SYLLABICS CA #
+
+1518 ; 1510 00B7 ; MA # ( ᔘ → ᔐ· ) CANADIAN SYLLABICS WEST-CREE SHWE → CANADIAN SYLLABICS SHE, MIDDLE DOT # →ᔐᐧ→
+
+151A ; 1511 00B7 ; MA # ( ᔚ → ᔑ· ) CANADIAN SYLLABICS WEST-CREE SHWI → CANADIAN SYLLABICS SHI, MIDDLE DOT # →ᔑᐧ→
+
+151C ; 1512 00B7 ; MA # ( ᔜ → ᔒ· ) CANADIAN SYLLABICS WEST-CREE SHWII → CANADIAN SYLLABICS SHII, MIDDLE DOT # →ᔒᐧ→
+
+151E ; 1513 00B7 ; MA # ( ᔞ → ᔓ· ) CANADIAN SYLLABICS WEST-CREE SHWO → CANADIAN SYLLABICS SHO, MIDDLE DOT # →ᔓᐧ→
+
+1520 ; 1514 00B7 ; MA # ( ᔠ → ᔔ· ) CANADIAN SYLLABICS WEST-CREE SHWOO → CANADIAN SYLLABICS SHOO, MIDDLE DOT # →ᔔᐧ→
+
+1522 ; 1515 00B7 ; MA # ( ᔢ → ᔕ· ) CANADIAN SYLLABICS WEST-CREE SHWA → CANADIAN SYLLABICS SHA, MIDDLE DOT # →ᔕᐧ→
+
+1524 ; 1516 00B7 ; MA # ( ᔤ → ᔖ· ) CANADIAN SYLLABICS WEST-CREE SHWAA → CANADIAN SYLLABICS SHAA, MIDDLE DOT # →ᔖᐧ→
+
+1532 ; 1528 00B7 ; MA # ( ᔲ → ᔨ· ) CANADIAN SYLLABICS WEST-CREE YWI → CANADIAN SYLLABICS YI, MIDDLE DOT # →ᔨᐧ→
+
+1534 ; 1529 00B7 ; MA # ( ᔴ → ᔩ· ) CANADIAN SYLLABICS WEST-CREE YWII → CANADIAN SYLLABICS YII, MIDDLE DOT # →ᔩᐧ→
+
+1536 ; 152A 00B7 ; MA # ( ᔶ → ᔪ· ) CANADIAN SYLLABICS WEST-CREE YWO → CANADIAN SYLLABICS YO, MIDDLE DOT # →ᔪᐧ→
+
+1538 ; 152B 00B7 ; MA # ( ᔸ → ᔫ· ) CANADIAN SYLLABICS WEST-CREE YWOO → CANADIAN SYLLABICS YOO, MIDDLE DOT # →ᔫᐧ→
+
+153A ; 152D 00B7 ; MA # ( ᔺ → ᔭ· ) CANADIAN SYLLABICS WEST-CREE YWA → CANADIAN SYLLABICS YA, MIDDLE DOT # →ᔭᐧ→
+
+153C ; 152E 00B7 ; MA # ( ᔼ → ᔮ· ) CANADIAN SYLLABICS WEST-CREE YWAA → CANADIAN SYLLABICS YAA, MIDDLE DOT # →ᔮᐧ→
+
+1622 ; 1543 ; MA # ( ᘢ → ᕃ ) CANADIAN SYLLABICS CARRIER LU → CANADIAN SYLLABICS R-CREE RE #
+
+18E0 ; 1543 00B7 ; MA # ( ᣠ → ᕃ· ) CANADIAN SYLLABICS R-CREE RWE → CANADIAN SYLLABICS R-CREE RE, MIDDLE DOT # →ᕃᐧ→
+
+1623 ; 1546 ; MA # ( ᘣ → ᕆ ) CANADIAN SYLLABICS CARRIER LO → CANADIAN SYLLABICS RI #
+
+1624 ; 154A ; MA # ( ᘤ → ᕊ ) CANADIAN SYLLABICS CARRIER LE → CANADIAN SYLLABICS WEST-CREE LO #
+
+154F ; 154C 00B7 ; MA # ( ᕏ → ᕌ· ) CANADIAN SYLLABICS WEST-CREE RWAA → CANADIAN SYLLABICS RAA, MIDDLE DOT # →ᕌᐧ→
+
+1583 ; 1550 0062 ; MA # ( ᖃ → ᕐb ) CANADIAN SYLLABICS QA → CANADIAN SYLLABICS R, LATIN SMALL LETTER B # →ᕐᑲ→
+
+1584 ; 1550 0062 0307 ; MA # ( ᖄ → ᕐḃ ) CANADIAN SYLLABICS QAA → CANADIAN SYLLABICS R, LATIN SMALL LETTER B, COMBINING DOT ABOVE # →ᕐᑳ→
+
+1581 ; 1550 0064 ; MA # ( ᖁ → ᕐd ) CANADIAN SYLLABICS QO → CANADIAN SYLLABICS R, LATIN SMALL LETTER D # →ᕐᑯ→
+
+157F ; 1550 0050 ; MA # ( ᕿ → ᕐP ) CANADIAN SYLLABICS QI → CANADIAN SYLLABICS R, LATIN CAPITAL LETTER P # →ᕐᑭ→
+
+166F ; 1550 146B ; MA # ( ᙯ → ᕐᑫ ) CANADIAN SYLLABICS QAI → CANADIAN SYLLABICS R, CANADIAN SYLLABICS KE #
+
+157E ; 1550 146C ; MA # ( ᕾ → ᕐᑬ ) CANADIAN SYLLABICS QAAI → CANADIAN SYLLABICS R, CANADIAN SYLLABICS KAAI #
+
+1580 ; 1550 146E ; MA # ( ᖀ → ᕐᑮ ) CANADIAN SYLLABICS QII → CANADIAN SYLLABICS R, CANADIAN SYLLABICS KII #
+
+1582 ; 1550 1470 ; MA # ( ᖂ → ᕐᑰ ) CANADIAN SYLLABICS QOO → CANADIAN SYLLABICS R, CANADIAN SYLLABICS KOO #
+
+1585 ; 1550 1483 ; MA # ( ᖅ → ᕐᒃ ) CANADIAN SYLLABICS Q → CANADIAN SYLLABICS R, CANADIAN SYLLABICS K #
+
+155C ; 155A 00B7 ; MA # ( ᕜ → ᕚ· ) CANADIAN SYLLABICS WEST-CREE FWAA → CANADIAN SYLLABICS FAA, MIDDLE DOT # →ᕚᐧ→
+
+18E3 ; 155E 00B7 ; MA # ( ᣣ → ᕞ· ) CANADIAN SYLLABICS THWE → CANADIAN SYLLABICS THE, MIDDLE DOT # →ᕞᐧ→
+
+18E4 ; 1566 00B7 ; MA # ( ᣤ → ᕦ· ) CANADIAN SYLLABICS THWA → CANADIAN SYLLABICS THA, MIDDLE DOT # →ᕦᐧ→
+
+1569 ; 1567 00B7 ; MA # ( ᕩ → ᕧ· ) CANADIAN SYLLABICS WEST-CREE THWAA → CANADIAN SYLLABICS THAA, MIDDLE DOT # →ᕧᐧ→
+
+18E5 ; 156B 00B7 ; MA # ( ᣥ → ᕫ· ) CANADIAN SYLLABICS TTHWE → CANADIAN SYLLABICS TTHE, MIDDLE DOT # →ᕫᐧ→
+
+18E8 ; 1586 00B7 ; MA # ( ᣨ → ᖆ· ) CANADIAN SYLLABICS TLHWE → CANADIAN SYLLABICS TLHE, MIDDLE DOT # →ᖆᐧ→
+
+1591 ; 1595 004A ; MA # ( ᖑ → ᖕJ ) CANADIAN SYLLABICS NGO → CANADIAN SYLLABICS NG, LATIN CAPITAL LETTER J # →ᖕᒍ→
+
+1670 ; 1595 1489 ; MA # ( ᙰ → ᖕᒉ ) CANADIAN SYLLABICS NGAI → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CE #
+
+158E ; 1595 148A ; MA # ( ᖎ → ᖕᒊ ) CANADIAN SYLLABICS NGAAI → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CAAI #
+
+158F ; 1595 148B ; MA # ( ᖏ → ᖕᒋ ) CANADIAN SYLLABICS NGI → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CI #
+
+1590 ; 1595 148C ; MA # ( ᖐ → ᖕᒌ ) CANADIAN SYLLABICS NGII → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CII #
+
+1592 ; 1595 148E ; MA # ( ᖒ → ᖕᒎ ) CANADIAN SYLLABICS NGOO → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS COO #
+
+1593 ; 1595 1490 ; MA # ( ᖓ → ᖕᒐ ) CANADIAN SYLLABICS NGA → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CA #
+
+1594 ; 1595 1491 ; MA # ( ᖔ → ᖕᒑ ) CANADIAN SYLLABICS NGAA → CANADIAN SYLLABICS NG, CANADIAN SYLLABICS CAA #
+
+1673 ; 1596 004A ; MA # ( ᙳ → ᖖJ ) CANADIAN SYLLABICS NNGO → CANADIAN SYLLABICS NNG, LATIN CAPITAL LETTER J # →ᖖᒍ→
+
+1671 ; 1596 148B ; MA # ( ᙱ → ᖖᒋ ) CANADIAN SYLLABICS NNGI → CANADIAN SYLLABICS NNG, CANADIAN SYLLABICS CI #
+
+1672 ; 1596 148C ; MA # ( ᙲ → ᖖᒌ ) CANADIAN SYLLABICS NNGII → CANADIAN SYLLABICS NNG, CANADIAN SYLLABICS CII #
+
+1674 ; 1596 148E ; MA # ( ᙴ → ᖖᒎ ) CANADIAN SYLLABICS NNGOO → CANADIAN SYLLABICS NNG, CANADIAN SYLLABICS COO #
+
+1675 ; 1596 1490 ; MA # ( ᙵ → ᖖᒐ ) CANADIAN SYLLABICS NNGA → CANADIAN SYLLABICS NNG, CANADIAN SYLLABICS CA #
+
+1676 ; 1596 1491 ; MA # ( ᙶ → ᖖᒑ ) CANADIAN SYLLABICS NNGAA → CANADIAN SYLLABICS NNG, CANADIAN SYLLABICS CAA #
+
+18EA ; 1597 00B7 ; MA # ( ᣪ → ᖗ· ) CANADIAN SYLLABICS SAYISI SHWE → CANADIAN SYLLABICS SAYISI SHE, MIDDLE DOT # →ᖗᐧ→
+
+1677 ; 15A7 00B7 ; MA # ( ᙷ → ᖧ· ) CANADIAN SYLLABICS WOODS-CREE THWEE → CANADIAN SYLLABICS TH-CREE THE, MIDDLE DOT # →ᖧᐧ→
+
+1678 ; 15A8 00B7 ; MA # ( ᙸ → ᖨ· ) CANADIAN SYLLABICS WOODS-CREE THWI → CANADIAN SYLLABICS TH-CREE THI, MIDDLE DOT # →ᖨᐧ→
+
+1679 ; 15A9 00B7 ; MA # ( ᙹ → ᖩ· ) CANADIAN SYLLABICS WOODS-CREE THWII → CANADIAN SYLLABICS TH-CREE THII, MIDDLE DOT # →ᖩᐧ→
+
+167A ; 15AA 00B7 ; MA # ( ᙺ → ᖪ· ) CANADIAN SYLLABICS WOODS-CREE THWO → CANADIAN SYLLABICS TH-CREE THO, MIDDLE DOT # →ᖪᐧ→
+
+167B ; 15AB 00B7 ; MA # ( ᙻ → ᖫ· ) CANADIAN SYLLABICS WOODS-CREE THWOO → CANADIAN SYLLABICS TH-CREE THOO, MIDDLE DOT # →ᖫᐧ→
+
+167C ; 15AC 00B7 ; MA # ( ᙼ → ᖬ· ) CANADIAN SYLLABICS WOODS-CREE THWA → CANADIAN SYLLABICS TH-CREE THA, MIDDLE DOT # →ᖬᐧ→
+
+167D ; 15AD 00B7 ; MA # ( ᙽ → ᖭ· ) CANADIAN SYLLABICS WOODS-CREE THWAA → CANADIAN SYLLABICS TH-CREE THAA, MIDDLE DOT # →ᖭᐧ→
+
+2AAB ; 15D2 ; MA #* ( ⪫ → ᗒ ) LARGER THAN → CANADIAN SYLLABICS CARRIER WE #
+
+2AAA ; 15D5 ; MA #* ( ⪪ → ᗕ ) SMALLER THAN → CANADIAN SYLLABICS CARRIER WA #
+
+A4F7 ; 15E1 ; MA # ( ꓷ → ᗡ ) LISU LETTER OE → CANADIAN SYLLABICS CARRIER THA #
+
+18F0 ; 15F4 00B7 ; MA # ( ᣰ → ᗴ· ) CANADIAN SYLLABICS CARRIER GWA → CANADIAN SYLLABICS CARRIER GA, MIDDLE DOT # →ᗴᐧ→
+
+18F2 ; 161B 00B7 ; MA # ( ᣲ → ᘛ· ) CANADIAN SYLLABICS CARRIER JWA → CANADIAN SYLLABICS CARRIER JA, MIDDLE DOT # →ᘛᐧ→
+
+1DBB ; 1646 ; MA # ( ᶻ → ᙆ ) MODIFIER LETTER SMALL Z → CANADIAN SYLLABICS CARRIER Z #
+
+A4ED ; 1660 ; MA # ( ꓭ → ᙠ ) LISU LETTER GHA → CANADIAN SYLLABICS CARRIER TSA #
+
+1DBA ; 18D4 ; MA # ( ᶺ → ᣔ ) MODIFIER LETTER SMALL TURNED V → CANADIAN SYLLABICS OJIBWAY P #
+
+1D3E ; 18D6 ; MA # ( ᴾ → ᣖ ) MODIFIER LETTER CAPITAL P → CANADIAN SYLLABICS OJIBWAY K #
+
+18DC ; 18DF 141E ; MA # ( ᣜ → ᣟᐞ ) CANADIAN SYLLABICS EASTERN W → CANADIAN SYLLABICS FINAL RAISED DOT, CANADIAN SYLLABICS GLOTTAL STOP #
+
+02E1 ; 18F3 ; MA # ( ˡ → ᣳ ) MODIFIER LETTER SMALL L → CANADIAN SYLLABICS BEAVER DENE L #
+
+02B3 ; 18F4 ; MA # ( ʳ → ᣴ ) MODIFIER LETTER SMALL R → CANADIAN SYLLABICS BEAVER DENE R #
+
+02E2 ; 18F5 ; MA # ( ˢ → ᣵ ) MODIFIER LETTER SMALL S → CANADIAN SYLLABICS CARRIER DENTAL S #
+18DB ; 18F5 ; MA # ( ᣛ → ᣵ ) CANADIAN SYLLABICS OJIBWAY SH → CANADIAN SYLLABICS CARRIER DENTAL S # →ˢ→
+
+A6B0 ; 16B9 ; MA # ( ꚰ → ᚹ ) BAMUM LETTER TAA → RUNIC LETTER WUNJO WYNN W #
+
+16E1 ; 16BC ; MA # ( ᛡ → ᚼ ) RUNIC LETTER IOR → RUNIC LETTER LONG-BRANCH-HAGALL H #
+
+237F ; 16BD ; MA #* ( ⍿ → ᚽ ) VERTICAL LINE WITH MIDDLE DOT → RUNIC LETTER SHORT-TWIG-HAGALL H # →ᛂ→
+16C2 ; 16BD ; MA # ( ᛂ → ᚽ ) RUNIC LETTER E → RUNIC LETTER SHORT-TWIG-HAGALL H #
+
+1D23F ; 16CB ; MA #* ( 𝈿 → ᛋ ) GREEK INSTRUMENTAL NOTATION SYMBOL-52 → RUNIC LETTER SIGEL LONG-BRANCH-SOL S #
+
+2191 ; 16CF ; MA #* ( ↑ → ᛏ ) UPWARDS ARROW → RUNIC LETTER TIWAZ TIR TYR T #
+
+21BF ; 16D0 ; MA #* ( ↿ → ᛐ ) UPWARDS HARPOON WITH BARB LEFTWARDS → RUNIC LETTER SHORT-TWIG-TYR T #
+
+296E ; 16D0 21C2 ; MA #* ( ⥮ → ᛐ⇂ ) UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT → RUNIC LETTER SHORT-TWIG-TYR T, DOWNWARDS HARPOON WITH BARB RIGHTWARDS # →↿⇂→
+
+2963 ; 16D0 16DA ; MA #* ( ⥣ → ᛐᛚ ) UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT → RUNIC LETTER SHORT-TWIG-TYR T, RUNIC LETTER LAUKAZ LAGU LOGR L # →↿↾→
+
+2D63 ; 16EF ; MA # ( ⵣ → ᛯ ) TIFINAGH LETTER YAZ → RUNIC TVIMADUR SYMBOL #
+
+21BE ; 16DA ; MA #* ( ↾ → ᛚ ) UPWARDS HARPOON WITH BARB RIGHTWARDS → RUNIC LETTER LAUKAZ LAGU LOGR L #
+2A21 ; 16DA ; MA #* ( ⨡ → ᛚ ) Z NOTATION SCHEMA PROJECTION → RUNIC LETTER LAUKAZ LAGU LOGR L # →↾→
+
+22C4 ; 16DC ; MA #* ( ⋄ → ᛜ ) DIAMOND OPERATOR → RUNIC LETTER INGWAZ # →◇→
+25C7 ; 16DC ; MA #* ( ◇ → ᛜ ) WHITE DIAMOND → RUNIC LETTER INGWAZ #
+25CA ; 16DC ; MA #* ( ◊ → ᛜ ) LOZENGE → RUNIC LETTER INGWAZ # →⋄→→◇→
+2662 ; 16DC ; MA #* ( ♢ → ᛜ ) WHITE DIAMOND SUIT → RUNIC LETTER INGWAZ # →◊→→⋄→→◇→
+1F754 ; 16DC ; MA #* ( 🝔 → ᛜ ) ALCHEMICAL SYMBOL FOR SOAP → RUNIC LETTER INGWAZ # →◇→
+118B7 ; 16DC ; MA # ( 𑢷 → ᛜ ) WARANG CITI CAPITAL LETTER BU → RUNIC LETTER INGWAZ # →◇→
+10294 ; 16DC ; MA # ( 𐊔 → ᛜ ) LYCIAN LETTER KK → RUNIC LETTER INGWAZ # →◇→
+
+235A ; 16DC 0332 ; MA #* ( ⍚ → ᛜ̲ ) APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR → RUNIC LETTER INGWAZ, COMBINING LOW LINE # →◇̲→
+
+22C8 ; 16DE ; MA #* ( ⋈ → ᛞ ) BOWTIE → RUNIC LETTER DAGAZ DAEG D #
+2A1D ; 16DE ; MA #* ( ⨝ → ᛞ ) JOIN → RUNIC LETTER DAGAZ DAEG D # →⋈→
+
+104D0 ; 16E6 ; MA # ( 𐓐 → ᛦ ) OSAGE CAPITAL LETTER KHA → RUNIC LETTER LONG-BRANCH-YR #
+
+2195 ; 16E8 ; MA #* ( ↕ → ᛨ ) UP DOWN ARROW → RUNIC LETTER ICELANDIC-YR #
+
+10CFC ; 10C82 ; MA #* ( ‎𐳼‎ → ‎𐲂‎ ) OLD HUNGARIAN NUMBER TEN → OLD HUNGARIAN CAPITAL LETTER EB #
+
+10CFA ; 10CA5 ; MA #* ( ‎𐳺‎ → ‎𐲥‎ ) OLD HUNGARIAN NUMBER ONE → OLD HUNGARIAN CAPITAL LETTER ESZ #
+
+3131 ; 1100 ; MA # ( ㄱ → ᄀ ) HANGUL LETTER KIYEOK → HANGUL CHOSEONG KIYEOK #
+11A8 ; 1100 ; MA # ( ᆨ → ᄀ ) HANGUL JONGSEONG KIYEOK → HANGUL CHOSEONG KIYEOK #
+
+1101 ; 1100 1100 ; MA # ( ᄁ → ᄀᄀ ) HANGUL CHOSEONG SSANGKIYEOK → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK #
+3132 ; 1100 1100 ; MA # ( ㄲ → ᄀᄀ ) HANGUL LETTER SSANGKIYEOK → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK # →ᄁ→
+11A9 ; 1100 1100 ; MA # ( ᆩ → ᄀᄀ ) HANGUL JONGSEONG SSANGKIYEOK → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK # →ᄁ→
+
+11FA ; 1100 1102 ; MA # ( ᇺ → ᄀᄂ ) HANGUL JONGSEONG KIYEOK-NIEUN → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG NIEUN # →ᆨᆫ→
+
+115A ; 1100 1103 ; MA # ( ᅚ → ᄀᄃ ) HANGUL CHOSEONG KIYEOK-TIKEUT → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG TIKEUT #
+
+11C3 ; 1100 1105 ; MA # ( ᇃ → ᄀᄅ ) HANGUL JONGSEONG KIYEOK-RIEUL → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG RIEUL # →ᆨᆯ→
+
+11FB ; 1100 1107 ; MA # ( ᇻ → ᄀᄇ ) HANGUL JONGSEONG KIYEOK-PIEUP → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG PIEUP # →ᆨᆸ→
+
+11AA ; 1100 1109 ; MA # ( ᆪ → ᄀᄉ ) HANGUL JONGSEONG KIYEOK-SIOS → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG SIOS # →ᆨᆺ→
+3133 ; 1100 1109 ; MA # ( ㄳ → ᄀᄉ ) HANGUL LETTER KIYEOK-SIOS → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG SIOS # →ᆪ→→ᆨᆺ→
+
+11C4 ; 1100 1109 1100 ; MA # ( ᇄ → ᄀᄉᄀ ) HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᆨᆺᆨ→
+
+11FC ; 1100 110E ; MA # ( ᇼ → ᄀᄎ ) HANGUL JONGSEONG KIYEOK-CHIEUCH → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG CHIEUCH # →ᆨᆾ→
+
+11FD ; 1100 110F ; MA # ( ᇽ → ᄀᄏ ) HANGUL JONGSEONG KIYEOK-KHIEUKH → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KHIEUKH # →ᆨᆿ→
+
+11FE ; 1100 1112 ; MA # ( ᇾ → ᄀᄒ ) HANGUL JONGSEONG KIYEOK-HIEUH → HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG HIEUH # →ᆨᇂ→
+
+3134 ; 1102 ; MA # ( ㄴ → ᄂ ) HANGUL LETTER NIEUN → HANGUL CHOSEONG NIEUN #
+11AB ; 1102 ; MA # ( ᆫ → ᄂ ) HANGUL JONGSEONG NIEUN → HANGUL CHOSEONG NIEUN #
+
+1113 ; 1102 1100 ; MA # ( ᄓ → ᄂᄀ ) HANGUL CHOSEONG NIEUN-KIYEOK → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG KIYEOK #
+11C5 ; 1102 1100 ; MA # ( ᇅ → ᄂᄀ ) HANGUL JONGSEONG NIEUN-KIYEOK → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG KIYEOK # →ᄓ→
+
+1114 ; 1102 1102 ; MA # ( ᄔ → ᄂᄂ ) HANGUL CHOSEONG SSANGNIEUN → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG NIEUN #
+3165 ; 1102 1102 ; MA # ( ㅥ → ᄂᄂ ) HANGUL LETTER SSANGNIEUN → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG NIEUN # →ᄔ→
+11FF ; 1102 1102 ; MA # ( ᇿ → ᄂᄂ ) HANGUL JONGSEONG SSANGNIEUN → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG NIEUN # →ᆫᆫ→
+
+1115 ; 1102 1103 ; MA # ( ᄕ → ᄂᄃ ) HANGUL CHOSEONG NIEUN-TIKEUT → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG TIKEUT #
+3166 ; 1102 1103 ; MA # ( ㅦ → ᄂᄃ ) HANGUL LETTER NIEUN-TIKEUT → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG TIKEUT # →ᄕ→
+11C6 ; 1102 1103 ; MA # ( ᇆ → ᄂᄃ ) HANGUL JONGSEONG NIEUN-TIKEUT → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG TIKEUT # →ᄕ→
+
+D7CB ; 1102 1105 ; MA # ( ퟋ → ᄂᄅ ) HANGUL JONGSEONG NIEUN-RIEUL → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG RIEUL # →ᆫᆯ→
+
+1116 ; 1102 1107 ; MA # ( ᄖ → ᄂᄇ ) HANGUL CHOSEONG NIEUN-PIEUP → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG PIEUP #
+
+115B ; 1102 1109 ; MA # ( ᅛ → ᄂᄉ ) HANGUL CHOSEONG NIEUN-SIOS → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG SIOS #
+11C7 ; 1102 1109 ; MA # ( ᇇ → ᄂᄉ ) HANGUL JONGSEONG NIEUN-SIOS → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG SIOS # →ᆫᆺ→
+3167 ; 1102 1109 ; MA # ( ㅧ → ᄂᄉ ) HANGUL LETTER NIEUN-SIOS → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG SIOS # →ᇇ→→ᆫᆺ→
+
+115C ; 1102 110C ; MA # ( ᅜ → ᄂᄌ ) HANGUL CHOSEONG NIEUN-CIEUC → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG CIEUC #
+11AC ; 1102 110C ; MA # ( ᆬ → ᄂᄌ ) HANGUL JONGSEONG NIEUN-CIEUC → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG CIEUC # →ᆫᆽ→
+3135 ; 1102 110C ; MA # ( ㄵ → ᄂᄌ ) HANGUL LETTER NIEUN-CIEUC → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG CIEUC # →ᆬ→→ᆫᆽ→
+
+D7CC ; 1102 110E ; MA # ( ퟌ → ᄂᄎ ) HANGUL JONGSEONG NIEUN-CHIEUCH → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG CHIEUCH # →ᆫᆾ→
+
+11C9 ; 1102 1110 ; MA # ( ᇉ → ᄂᄐ ) HANGUL JONGSEONG NIEUN-THIEUTH → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG THIEUTH # →ᆫᇀ→
+
+115D ; 1102 1112 ; MA # ( ᅝ → ᄂᄒ ) HANGUL CHOSEONG NIEUN-HIEUH → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG HIEUH #
+11AD ; 1102 1112 ; MA # ( ᆭ → ᄂᄒ ) HANGUL JONGSEONG NIEUN-HIEUH → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG HIEUH # →ᆫᇂ→
+3136 ; 1102 1112 ; MA # ( ㄶ → ᄂᄒ ) HANGUL LETTER NIEUN-HIEUH → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG HIEUH # →ᆭ→→ᆫᇂ→
+
+11C8 ; 1102 1140 ; MA # ( ᇈ → ᄂᅀ ) HANGUL JONGSEONG NIEUN-PANSIOS → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG PANSIOS # →ᆫᇫ→
+3168 ; 1102 1140 ; MA # ( ㅨ → ᄂᅀ ) HANGUL LETTER NIEUN-PANSIOS → HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG PANSIOS # →ᇈ→→ᆫᇫ→
+
+3137 ; 1103 ; MA # ( ㄷ → ᄃ ) HANGUL LETTER TIKEUT → HANGUL CHOSEONG TIKEUT #
+11AE ; 1103 ; MA # ( ᆮ → ᄃ ) HANGUL JONGSEONG TIKEUT → HANGUL CHOSEONG TIKEUT #
+
+1117 ; 1103 1100 ; MA # ( ᄗ → ᄃᄀ ) HANGUL CHOSEONG TIKEUT-KIYEOK → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG KIYEOK #
+11CA ; 1103 1100 ; MA # ( ᇊ → ᄃᄀ ) HANGUL JONGSEONG TIKEUT-KIYEOK → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG KIYEOK # →ᄗ→
+
+1104 ; 1103 1103 ; MA # ( ᄄ → ᄃᄃ ) HANGUL CHOSEONG SSANGTIKEUT → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG TIKEUT #
+3138 ; 1103 1103 ; MA # ( ㄸ → ᄃᄃ ) HANGUL LETTER SSANGTIKEUT → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG TIKEUT # →ᄄ→
+D7CD ; 1103 1103 ; MA # ( ퟍ → ᄃᄃ ) HANGUL JONGSEONG SSANGTIKEUT → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG TIKEUT # →ᆮᆮ→
+
+D7CE ; 1103 1103 1107 ; MA # ( ퟎ → ᄃᄃᄇ ) HANGUL JONGSEONG SSANGTIKEUT-PIEUP → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG PIEUP # →ᆮᆮᆸ→
+
+115E ; 1103 1105 ; MA # ( ᅞ → ᄃᄅ ) HANGUL CHOSEONG TIKEUT-RIEUL → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG RIEUL #
+11CB ; 1103 1105 ; MA # ( ᇋ → ᄃᄅ ) HANGUL JONGSEONG TIKEUT-RIEUL → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG RIEUL # →ᆮᆯ→
+
+A960 ; 1103 1106 ; MA # ( ꥠ → ᄃᄆ ) HANGUL CHOSEONG TIKEUT-MIEUM → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG MIEUM #
+
+A961 ; 1103 1107 ; MA # ( ꥡ → ᄃᄇ ) HANGUL CHOSEONG TIKEUT-PIEUP → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG PIEUP #
+D7CF ; 1103 1107 ; MA # ( ퟏ → ᄃᄇ ) HANGUL JONGSEONG TIKEUT-PIEUP → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG PIEUP # →ᆮᆸ→
+
+A962 ; 1103 1109 ; MA # ( ꥢ → ᄃᄉ ) HANGUL CHOSEONG TIKEUT-SIOS → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG SIOS #
+D7D0 ; 1103 1109 ; MA # ( ퟐ → ᄃᄉ ) HANGUL JONGSEONG TIKEUT-SIOS → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG SIOS # →ᆮᆺ→
+
+D7D1 ; 1103 1109 1100 ; MA # ( ퟑ → ᄃᄉᄀ ) HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᆮᆺᆨ→
+
+A963 ; 1103 110C ; MA # ( ꥣ → ᄃᄌ ) HANGUL CHOSEONG TIKEUT-CIEUC → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG CIEUC #
+D7D2 ; 1103 110C ; MA # ( ퟒ → ᄃᄌ ) HANGUL JONGSEONG TIKEUT-CIEUC → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG CIEUC # →ᆮᆽ→
+
+D7D3 ; 1103 110E ; MA # ( ퟓ → ᄃᄎ ) HANGUL JONGSEONG TIKEUT-CHIEUCH → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG CHIEUCH # →ᆮᆾ→
+
+D7D4 ; 1103 1110 ; MA # ( ퟔ → ᄃᄐ ) HANGUL JONGSEONG TIKEUT-THIEUTH → HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG THIEUTH # →ᆮᇀ→
+
+3139 ; 1105 ; MA # ( ㄹ → ᄅ ) HANGUL LETTER RIEUL → HANGUL CHOSEONG RIEUL #
+11AF ; 1105 ; MA # ( ᆯ → ᄅ ) HANGUL JONGSEONG RIEUL → HANGUL CHOSEONG RIEUL #
+
+A964 ; 1105 1100 ; MA # ( ꥤ → ᄅᄀ ) HANGUL CHOSEONG RIEUL-KIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK #
+11B0 ; 1105 1100 ; MA # ( ᆰ → ᄅᄀ ) HANGUL JONGSEONG RIEUL-KIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK # →ᆯᆨ→
+313A ; 1105 1100 ; MA # ( ㄺ → ᄅᄀ ) HANGUL LETTER RIEUL-KIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK # →ᆰ→→ᆯᆨ→
+
+A965 ; 1105 1100 1100 ; MA # ( ꥥ → ᄅᄀᄀ ) HANGUL CHOSEONG RIEUL-SSANGKIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK #
+D7D5 ; 1105 1100 1100 ; MA # ( ퟕ → ᄅᄀᄀ ) HANGUL JONGSEONG RIEUL-SSANGKIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK # →ᆯᆨᆨ→
+
+11CC ; 1105 1100 1109 ; MA # ( ᇌ → ᄅᄀᄉ ) HANGUL JONGSEONG RIEUL-KIYEOK-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG SIOS # →ᆯᆨᆺ→
+3169 ; 1105 1100 1109 ; MA # ( ㅩ → ᄅᄀᄉ ) HANGUL LETTER RIEUL-KIYEOK-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG SIOS # →ᇌ→→ᆯᆨᆺ→
+
+D7D6 ; 1105 1100 1112 ; MA # ( ퟖ → ᄅᄀᄒ ) HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG HIEUH # →ᆯᆨᇂ→
+
+1118 ; 1105 1102 ; MA # ( ᄘ → ᄅᄂ ) HANGUL CHOSEONG RIEUL-NIEUN → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG NIEUN #
+11CD ; 1105 1102 ; MA # ( ᇍ → ᄅᄂ ) HANGUL JONGSEONG RIEUL-NIEUN → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG NIEUN # →ᄘ→
+
+A966 ; 1105 1103 ; MA # ( ꥦ → ᄅᄃ ) HANGUL CHOSEONG RIEUL-TIKEUT → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG TIKEUT #
+11CE ; 1105 1103 ; MA # ( ᇎ → ᄅᄃ ) HANGUL JONGSEONG RIEUL-TIKEUT → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG TIKEUT # →ᆯᆮ→
+316A ; 1105 1103 ; MA # ( ㅪ → ᄅᄃ ) HANGUL LETTER RIEUL-TIKEUT → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG TIKEUT # →ᇎ→→ᆯᆮ→
+
+A967 ; 1105 1103 1103 ; MA # ( ꥧ → ᄅᄃᄃ ) HANGUL CHOSEONG RIEUL-SSANGTIKEUT → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG TIKEUT #
+
+11CF ; 1105 1103 1112 ; MA # ( ᇏ → ᄅᄃᄒ ) HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG TIKEUT, HANGUL CHOSEONG HIEUH # →ᆯᆮᇂ→
+
+1119 ; 1105 1105 ; MA # ( ᄙ → ᄅᄅ ) HANGUL CHOSEONG SSANGRIEUL → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG RIEUL #
+11D0 ; 1105 1105 ; MA # ( ᇐ → ᄅᄅ ) HANGUL JONGSEONG SSANGRIEUL → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG RIEUL # →ᄙ→
+
+D7D7 ; 1105 1105 110F ; MA # ( ퟗ → ᄅᄅᄏ ) HANGUL JONGSEONG SSANGRIEUL-KHIEUKH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KHIEUKH # →ᆯᆯᆿ→
+
+A968 ; 1105 1106 ; MA # ( ꥨ → ᄅᄆ ) HANGUL CHOSEONG RIEUL-MIEUM → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM #
+11B1 ; 1105 1106 ; MA # ( ᆱ → ᄅᄆ ) HANGUL JONGSEONG RIEUL-MIEUM → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM # →ᆯᆷ→
+313B ; 1105 1106 ; MA # ( ㄻ → ᄅᄆ ) HANGUL LETTER RIEUL-MIEUM → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM # →ᆱ→→ᆯᆷ→
+
+11D1 ; 1105 1106 1100 ; MA # ( ᇑ → ᄅᄆᄀ ) HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG KIYEOK # →ᆯᆷᆨ→
+
+11D2 ; 1105 1106 1109 ; MA # ( ᇒ → ᄅᄆᄉ ) HANGUL JONGSEONG RIEUL-MIEUM-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG SIOS # →ᆯᆷᆺ→
+
+D7D8 ; 1105 1106 1112 ; MA # ( ퟘ → ᄅᄆᄒ ) HANGUL JONGSEONG RIEUL-MIEUM-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG HIEUH # →ᆯᆷᇂ→
+
+A969 ; 1105 1107 ; MA # ( ꥩ → ᄅᄇ ) HANGUL CHOSEONG RIEUL-PIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP #
+11B2 ; 1105 1107 ; MA # ( ᆲ → ᄅᄇ ) HANGUL JONGSEONG RIEUL-PIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP # →ᆯᆸ→
+313C ; 1105 1107 ; MA # ( ㄼ → ᄅᄇ ) HANGUL LETTER RIEUL-PIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP # →ᆲ→→ᆯᆸ→
+
+D7D9 ; 1105 1107 1103 ; MA # ( ퟙ → ᄅᄇᄃ ) HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG TIKEUT # →ᆯᆸᆮ→
+
+A96A ; 1105 1107 1107 ; MA # ( ꥪ → ᄅᄇᄇ ) HANGUL CHOSEONG RIEUL-SSANGPIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP #
+
+11D3 ; 1105 1107 1109 ; MA # ( ᇓ → ᄅᄇᄉ ) HANGUL JONGSEONG RIEUL-PIEUP-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS # →ᆯᆸᆺ→
+316B ; 1105 1107 1109 ; MA # ( ㅫ → ᄅᄇᄉ ) HANGUL LETTER RIEUL-PIEUP-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS # →ᇓ→→ᆯᆸᆺ→
+
+A96B ; 1105 1107 110B ; MA # ( ꥫ → ᄅᄇᄋ ) HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG #
+11D5 ; 1105 1107 110B ; MA # ( ᇕ → ᄅᄇᄋ ) HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᆯᆸᆼ→
+
+D7DA ; 1105 1107 1111 ; MA # ( ퟚ → ᄅᄇᄑ ) HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PHIEUPH # →ᆯᆸᇁ→
+
+11D4 ; 1105 1107 1112 ; MA # ( ᇔ → ᄅᄇᄒ ) HANGUL JONGSEONG RIEUL-PIEUP-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG HIEUH # →ᆯᆸᇂ→
+
+A96C ; 1105 1109 ; MA # ( ꥬ → ᄅᄉ ) HANGUL CHOSEONG RIEUL-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG SIOS #
+11B3 ; 1105 1109 ; MA # ( ᆳ → ᄅᄉ ) HANGUL JONGSEONG RIEUL-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG SIOS # →ᆯᆺ→
+313D ; 1105 1109 ; MA # ( ㄽ → ᄅᄉ ) HANGUL LETTER RIEUL-SIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG SIOS # →ᆳ→→ᆯᆺ→
+
+11D6 ; 1105 1109 1109 ; MA # ( ᇖ → ᄅᄉᄉ ) HANGUL JONGSEONG RIEUL-SSANGSIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS # →ᆯᆺᆺ→
+
+111B ; 1105 110B ; MA # ( ᄛ → ᄅᄋ ) HANGUL CHOSEONG KAPYEOUNRIEUL → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG IEUNG #
+D7DD ; 1105 110B ; MA # ( ퟝ → ᄅᄋ ) HANGUL JONGSEONG KAPYEOUNRIEUL → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG IEUNG # →ᆯᆼ→
+
+A96D ; 1105 110C ; MA # ( ꥭ → ᄅᄌ ) HANGUL CHOSEONG RIEUL-CIEUC → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG CIEUC #
+
+A96E ; 1105 110F ; MA # ( ꥮ → ᄅᄏ ) HANGUL CHOSEONG RIEUL-KHIEUKH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KHIEUKH #
+11D8 ; 1105 110F ; MA # ( ᇘ → ᄅᄏ ) HANGUL JONGSEONG RIEUL-KHIEUKH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG KHIEUKH # →ᆯᆿ→
+
+11B4 ; 1105 1110 ; MA # ( ᆴ → ᄅᄐ ) HANGUL JONGSEONG RIEUL-THIEUTH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG THIEUTH # →ᆯᇀ→
+313E ; 1105 1110 ; MA # ( ㄾ → ᄅᄐ ) HANGUL LETTER RIEUL-THIEUTH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG THIEUTH # →ᆴ→→ᆯᇀ→
+
+11B5 ; 1105 1111 ; MA # ( ᆵ → ᄅᄑ ) HANGUL JONGSEONG RIEUL-PHIEUPH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PHIEUPH # →ᆯᇁ→
+313F ; 1105 1111 ; MA # ( ㄿ → ᄅᄑ ) HANGUL LETTER RIEUL-PHIEUPH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PHIEUPH # →ᆵ→→ᆯᇁ→
+
+111A ; 1105 1112 ; MA # ( ᄚ → ᄅᄒ ) HANGUL CHOSEONG RIEUL-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG HIEUH #
+3140 ; 1105 1112 ; MA # ( ㅀ → ᄅᄒ ) HANGUL LETTER RIEUL-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG HIEUH # →ᄚ→
+113B ; 1105 1112 ; MA # ( ᄻ → ᄅᄒ ) HANGUL CHOSEONG SIOS-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG HIEUH # →ᄚ→
+11B6 ; 1105 1112 ; MA # ( ᆶ → ᄅᄒ ) HANGUL JONGSEONG RIEUL-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG HIEUH # →ᄚ→
+D7F2 ; 1105 1112 ; MA # ( ퟲ → ᄅᄒ ) HANGUL JONGSEONG SIOS-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG HIEUH # →ᆺᇂ→→ᄉᄒ→→ᄻ→→ᄚ→
+
+11D7 ; 1105 1140 ; MA # ( ᇗ → ᄅᅀ ) HANGUL JONGSEONG RIEUL-PANSIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PANSIOS # →ᆯᇫ→
+316C ; 1105 1140 ; MA # ( ㅬ → ᄅᅀ ) HANGUL LETTER RIEUL-PANSIOS → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PANSIOS # →ᇗ→→ᆯᇫ→
+
+D7DB ; 1105 114C ; MA # ( ퟛ → ᄅᅌ ) HANGUL JONGSEONG RIEUL-YESIEUNG → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG YESIEUNG # →ᆯᇰ→
+
+11D9 ; 1105 1159 ; MA # ( ᇙ → ᄅᅙ ) HANGUL JONGSEONG RIEUL-YEORINHIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG YEORINHIEUH # →ᆯᇹ→
+316D ; 1105 1159 ; MA # ( ㅭ → ᄅᅙ ) HANGUL LETTER RIEUL-YEORINHIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG YEORINHIEUH # →ᇙ→→ᆯᇹ→
+
+D7DC ; 1105 1159 1112 ; MA # ( ퟜ → ᄅᅙᄒ ) HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH → HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG YEORINHIEUH, HANGUL CHOSEONG HIEUH # →ᆯᇹᇂ→
+
+3141 ; 1106 ; MA # ( ㅁ → ᄆ ) HANGUL LETTER MIEUM → HANGUL CHOSEONG MIEUM #
+11B7 ; 1106 ; MA # ( ᆷ → ᄆ ) HANGUL JONGSEONG MIEUM → HANGUL CHOSEONG MIEUM #
+
+A96F ; 1106 1100 ; MA # ( ꥯ → ᄆᄀ ) HANGUL CHOSEONG MIEUM-KIYEOK → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG KIYEOK #
+11DA ; 1106 1100 ; MA # ( ᇚ → ᄆᄀ ) HANGUL JONGSEONG MIEUM-KIYEOK → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG KIYEOK # →ᆷᆨ→
+
+D7DE ; 1106 1102 ; MA # ( ퟞ → ᄆᄂ ) HANGUL JONGSEONG MIEUM-NIEUN → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG NIEUN # →ᆷᆫ→
+
+D7DF ; 1106 1102 1102 ; MA # ( ퟟ → ᄆᄂᄂ ) HANGUL JONGSEONG MIEUM-SSANGNIEUN → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG NIEUN, HANGUL CHOSEONG NIEUN # →ᆷᆫᆫ→
+
+A970 ; 1106 1103 ; MA # ( ꥰ → ᄆᄃ ) HANGUL CHOSEONG MIEUM-TIKEUT → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG TIKEUT #
+
+11DB ; 1106 1105 ; MA # ( ᇛ → ᄆᄅ ) HANGUL JONGSEONG MIEUM-RIEUL → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG RIEUL # →ᆷᆯ→
+
+D7E0 ; 1106 1106 ; MA # ( ퟠ → ᄆᄆ ) HANGUL JONGSEONG SSANGMIEUM → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG MIEUM # →ᆷᆷ→
+
+111C ; 1106 1107 ; MA # ( ᄜ → ᄆᄇ ) HANGUL CHOSEONG MIEUM-PIEUP → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PIEUP #
+316E ; 1106 1107 ; MA # ( ㅮ → ᄆᄇ ) HANGUL LETTER MIEUM-PIEUP → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PIEUP # →ᄜ→
+11DC ; 1106 1107 ; MA # ( ᇜ → ᄆᄇ ) HANGUL JONGSEONG MIEUM-PIEUP → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PIEUP # →ᄜ→
+
+D7E1 ; 1106 1107 1109 ; MA # ( ퟡ → ᄆᄇᄉ ) HANGUL JONGSEONG MIEUM-PIEUP-SIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS # →ᆷᆸᆺ→
+
+A971 ; 1106 1109 ; MA # ( ꥱ → ᄆᄉ ) HANGUL CHOSEONG MIEUM-SIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG SIOS #
+11DD ; 1106 1109 ; MA # ( ᇝ → ᄆᄉ ) HANGUL JONGSEONG MIEUM-SIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG SIOS # →ᆷᆺ→
+316F ; 1106 1109 ; MA # ( ㅯ → ᄆᄉ ) HANGUL LETTER MIEUM-SIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG SIOS # →ᇝ→→ᆷᆺ→
+
+11DE ; 1106 1109 1109 ; MA # ( ᇞ → ᄆᄉᄉ ) HANGUL JONGSEONG MIEUM-SSANGSIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS # →ᆷᆺᆺ→
+
+111D ; 1106 110B ; MA # ( ᄝ → ᄆᄋ ) HANGUL CHOSEONG KAPYEOUNMIEUM → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG IEUNG #
+3171 ; 1106 110B ; MA # ( ㅱ → ᄆᄋ ) HANGUL LETTER KAPYEOUNMIEUM → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG IEUNG # →ᄝ→
+11E2 ; 1106 110B ; MA # ( ᇢ → ᄆᄋ ) HANGUL JONGSEONG KAPYEOUNMIEUM → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG IEUNG # →ᄝ→
+
+D7E2 ; 1106 110C ; MA # ( ퟢ → ᄆᄌ ) HANGUL JONGSEONG MIEUM-CIEUC → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG CIEUC # →ᆷᆽ→
+
+11E0 ; 1106 110E ; MA # ( ᇠ → ᄆᄎ ) HANGUL JONGSEONG MIEUM-CHIEUCH → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG CHIEUCH # →ᆷᆾ→
+
+11E1 ; 1106 1112 ; MA # ( ᇡ → ᄆᄒ ) HANGUL JONGSEONG MIEUM-HIEUH → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG HIEUH # →ᆷᇂ→
+
+11DF ; 1106 1140 ; MA # ( ᇟ → ᄆᅀ ) HANGUL JONGSEONG MIEUM-PANSIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PANSIOS # →ᆷᇫ→
+3170 ; 1106 1140 ; MA # ( ㅰ → ᄆᅀ ) HANGUL LETTER MIEUM-PANSIOS → HANGUL CHOSEONG MIEUM, HANGUL CHOSEONG PANSIOS # →ᇟ→→ᆷᇫ→
+
+3142 ; 1107 ; MA # ( ㅂ → ᄇ ) HANGUL LETTER PIEUP → HANGUL CHOSEONG PIEUP #
+11B8 ; 1107 ; MA # ( ᆸ → ᄇ ) HANGUL JONGSEONG PIEUP → HANGUL CHOSEONG PIEUP #
+
+111E ; 1107 1100 ; MA # ( ᄞ → ᄇᄀ ) HANGUL CHOSEONG PIEUP-KIYEOK → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG KIYEOK #
+3172 ; 1107 1100 ; MA # ( ㅲ → ᄇᄀ ) HANGUL LETTER PIEUP-KIYEOK → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG KIYEOK # →ᄞ→
+
+111F ; 1107 1102 ; MA # ( ᄟ → ᄇᄂ ) HANGUL CHOSEONG PIEUP-NIEUN → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG NIEUN #
+
+1120 ; 1107 1103 ; MA # ( ᄠ → ᄇᄃ ) HANGUL CHOSEONG PIEUP-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG TIKEUT #
+3173 ; 1107 1103 ; MA # ( ㅳ → ᄇᄃ ) HANGUL LETTER PIEUP-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG TIKEUT # →ᄠ→
+D7E3 ; 1107 1103 ; MA # ( ퟣ → ᄇᄃ ) HANGUL JONGSEONG PIEUP-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG TIKEUT # →ᆸᆮ→
+
+11E3 ; 1107 1105 ; MA # ( ᇣ → ᄇᄅ ) HANGUL JONGSEONG PIEUP-RIEUL → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG RIEUL # →ᆸᆯ→
+
+D7E4 ; 1107 1105 1111 ; MA # ( ퟤ → ᄇᄅᄑ ) HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG RIEUL, HANGUL CHOSEONG PHIEUPH # →ᆸᆯᇁ→
+
+D7E5 ; 1107 1106 ; MA # ( ퟥ → ᄇᄆ ) HANGUL JONGSEONG PIEUP-MIEUM → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG MIEUM # →ᆸᆷ→
+
+1108 ; 1107 1107 ; MA # ( ᄈ → ᄇᄇ ) HANGUL CHOSEONG SSANGPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP #
+3143 ; 1107 1107 ; MA # ( ㅃ → ᄇᄇ ) HANGUL LETTER SSANGPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP # →ᄈ→
+D7E6 ; 1107 1107 ; MA # ( ퟦ → ᄇᄇ ) HANGUL JONGSEONG SSANGPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP # →ᆸᆸ→
+
+112C ; 1107 1107 110B ; MA # ( ᄬ → ᄇᄇᄋ ) HANGUL CHOSEONG KAPYEOUNSSANGPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG #
+3179 ; 1107 1107 110B ; MA # ( ㅹ → ᄇᄇᄋ ) HANGUL LETTER KAPYEOUNSSANGPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᄬ→
+
+1121 ; 1107 1109 ; MA # ( ᄡ → ᄇᄉ ) HANGUL CHOSEONG PIEUP-SIOS → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS #
+3144 ; 1107 1109 ; MA # ( ㅄ → ᄇᄉ ) HANGUL LETTER PIEUP-SIOS → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS # →ᄡ→
+11B9 ; 1107 1109 ; MA # ( ᆹ → ᄇᄉ ) HANGUL JONGSEONG PIEUP-SIOS → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS # →ᄡ→
+
+1122 ; 1107 1109 1100 ; MA # ( ᄢ → ᄇᄉᄀ ) HANGUL CHOSEONG PIEUP-SIOS-KIYEOK → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK #
+3174 ; 1107 1109 1100 ; MA # ( ㅴ → ᄇᄉᄀ ) HANGUL LETTER PIEUP-SIOS-KIYEOK → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᄢ→
+
+1123 ; 1107 1109 1103 ; MA # ( ᄣ → ᄇᄉᄃ ) HANGUL CHOSEONG PIEUP-SIOS-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT #
+3175 ; 1107 1109 1103 ; MA # ( ㅵ → ᄇᄉᄃ ) HANGUL LETTER PIEUP-SIOS-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT # →ᄣ→
+D7E7 ; 1107 1109 1103 ; MA # ( ퟧ → ᄇᄉᄃ ) HANGUL JONGSEONG PIEUP-SIOS-TIKEUT → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT # →ᆸᆺᆮ→
+
+1124 ; 1107 1109 1107 ; MA # ( ᄤ → ᄇᄉᄇ ) HANGUL CHOSEONG PIEUP-SIOS-PIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP #
+
+1125 ; 1107 1109 1109 ; MA # ( ᄥ → ᄇᄉᄉ ) HANGUL CHOSEONG PIEUP-SSANGSIOS → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS #
+
+1126 ; 1107 1109 110C ; MA # ( ᄦ → ᄇᄉᄌ ) HANGUL CHOSEONG PIEUP-SIOS-CIEUC → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CIEUC #
+
+A972 ; 1107 1109 1110 ; MA # ( ꥲ → ᄇᄉᄐ ) HANGUL CHOSEONG PIEUP-SIOS-THIEUTH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG THIEUTH #
+
+112B ; 1107 110B ; MA # ( ᄫ → ᄇᄋ ) HANGUL CHOSEONG KAPYEOUNPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG #
+3178 ; 1107 110B ; MA # ( ㅸ → ᄇᄋ ) HANGUL LETTER KAPYEOUNPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᄫ→
+11E6 ; 1107 110B ; MA # ( ᇦ → ᄇᄋ ) HANGUL JONGSEONG KAPYEOUNPIEUP → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᄫ→
+
+1127 ; 1107 110C ; MA # ( ᄧ → ᄇᄌ ) HANGUL CHOSEONG PIEUP-CIEUC → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG CIEUC #
+3176 ; 1107 110C ; MA # ( ㅶ → ᄇᄌ ) HANGUL LETTER PIEUP-CIEUC → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG CIEUC # →ᄧ→
+D7E8 ; 1107 110C ; MA # ( ퟨ → ᄇᄌ ) HANGUL JONGSEONG PIEUP-CIEUC → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG CIEUC # →ᆸᆽ→
+
+1128 ; 1107 110E ; MA # ( ᄨ → ᄇᄎ ) HANGUL CHOSEONG PIEUP-CHIEUCH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG CHIEUCH #
+D7E9 ; 1107 110E ; MA # ( ퟩ → ᄇᄎ ) HANGUL JONGSEONG PIEUP-CHIEUCH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG CHIEUCH # →ᆸᆾ→
+
+A973 ; 1107 110F ; MA # ( ꥳ → ᄇᄏ ) HANGUL CHOSEONG PIEUP-KHIEUKH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG KHIEUKH #
+
+1129 ; 1107 1110 ; MA # ( ᄩ → ᄇᄐ ) HANGUL CHOSEONG PIEUP-THIEUTH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG THIEUTH #
+3177 ; 1107 1110 ; MA # ( ㅷ → ᄇᄐ ) HANGUL LETTER PIEUP-THIEUTH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG THIEUTH # →ᄩ→
+
+112A ; 1107 1111 ; MA # ( ᄪ → ᄇᄑ ) HANGUL CHOSEONG PIEUP-PHIEUPH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PHIEUPH #
+11E4 ; 1107 1111 ; MA # ( ᇤ → ᄇᄑ ) HANGUL JONGSEONG PIEUP-PHIEUPH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PHIEUPH # →ᄪ→
+
+A974 ; 1107 1112 ; MA # ( ꥴ → ᄇᄒ ) HANGUL CHOSEONG PIEUP-HIEUH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG HIEUH #
+11E5 ; 1107 1112 ; MA # ( ᇥ → ᄇᄒ ) HANGUL JONGSEONG PIEUP-HIEUH → HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG HIEUH # →ᆸᇂ→
+
+3145 ; 1109 ; MA # ( ㅅ → ᄉ ) HANGUL LETTER SIOS → HANGUL CHOSEONG SIOS #
+11BA ; 1109 ; MA # ( ᆺ → ᄉ ) HANGUL JONGSEONG SIOS → HANGUL CHOSEONG SIOS #
+
+112D ; 1109 1100 ; MA # ( ᄭ → ᄉᄀ ) HANGUL CHOSEONG SIOS-KIYEOK → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK #
+317A ; 1109 1100 ; MA # ( ㅺ → ᄉᄀ ) HANGUL LETTER SIOS-KIYEOK → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᄭ→
+11E7 ; 1109 1100 ; MA # ( ᇧ → ᄉᄀ ) HANGUL JONGSEONG SIOS-KIYEOK → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᄭ→
+
+112E ; 1109 1102 ; MA # ( ᄮ → ᄉᄂ ) HANGUL CHOSEONG SIOS-NIEUN → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG NIEUN #
+317B ; 1109 1102 ; MA # ( ㅻ → ᄉᄂ ) HANGUL LETTER SIOS-NIEUN → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG NIEUN # →ᄮ→
+
+112F ; 1109 1103 ; MA # ( ᄯ → ᄉᄃ ) HANGUL CHOSEONG SIOS-TIKEUT → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT #
+317C ; 1109 1103 ; MA # ( ㅼ → ᄉᄃ ) HANGUL LETTER SIOS-TIKEUT → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT # →ᄯ→
+11E8 ; 1109 1103 ; MA # ( ᇨ → ᄉᄃ ) HANGUL JONGSEONG SIOS-TIKEUT → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT # →ᄯ→
+
+1130 ; 1109 1105 ; MA # ( ᄰ → ᄉᄅ ) HANGUL CHOSEONG SIOS-RIEUL → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG RIEUL #
+11E9 ; 1109 1105 ; MA # ( ᇩ → ᄉᄅ ) HANGUL JONGSEONG SIOS-RIEUL → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG RIEUL # →ᄰ→
+
+1131 ; 1109 1106 ; MA # ( ᄱ → ᄉᄆ ) HANGUL CHOSEONG SIOS-MIEUM → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG MIEUM #
+D7EA ; 1109 1106 ; MA # ( ퟪ → ᄉᄆ ) HANGUL JONGSEONG SIOS-MIEUM → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG MIEUM # →ᆺᆷ→
+
+1132 ; 1109 1107 ; MA # ( ᄲ → ᄉᄇ ) HANGUL CHOSEONG SIOS-PIEUP → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP #
+317D ; 1109 1107 ; MA # ( ㅽ → ᄉᄇ ) HANGUL LETTER SIOS-PIEUP → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP # →ᄲ→
+11EA ; 1109 1107 ; MA # ( ᇪ → ᄉᄇ ) HANGUL JONGSEONG SIOS-PIEUP → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP # →ᄲ→
+
+1133 ; 1109 1107 1100 ; MA # ( ᄳ → ᄉᄇᄀ ) HANGUL CHOSEONG SIOS-PIEUP-KIYEOK → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG KIYEOK #
+
+D7EB ; 1109 1107 110B ; MA # ( ퟫ → ᄉᄇᄋ ) HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᆺᆸᆼ→
+
+110A ; 1109 1109 ; MA # ( ᄊ → ᄉᄉ ) HANGUL CHOSEONG SSANGSIOS → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS #
+3146 ; 1109 1109 ; MA # ( ㅆ → ᄉᄉ ) HANGUL LETTER SSANGSIOS → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS # →ᄊ→
+11BB ; 1109 1109 ; MA # ( ᆻ → ᄉᄉ ) HANGUL JONGSEONG SSANGSIOS → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS # →ᄊ→
+
+D7EC ; 1109 1109 1100 ; MA # ( ퟬ → ᄉᄉᄀ ) HANGUL JONGSEONG SSANGSIOS-KIYEOK → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KIYEOK # →ᆺᆺᆨ→
+
+D7ED ; 1109 1109 1103 ; MA # ( ퟭ → ᄉᄉᄃ ) HANGUL JONGSEONG SSANGSIOS-TIKEUT → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG TIKEUT # →ᆺᆺᆮ→
+
+A975 ; 1109 1109 1107 ; MA # ( ꥵ → ᄉᄉᄇ ) HANGUL CHOSEONG SSANGSIOS-PIEUP → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PIEUP #
+
+1134 ; 1109 1109 1109 ; MA # ( ᄴ → ᄉᄉᄉ ) HANGUL CHOSEONG SIOS-SSANGSIOS → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS, HANGUL CHOSEONG SIOS #
+
+1135 ; 1109 110B ; MA # ( ᄵ → ᄉᄋ ) HANGUL CHOSEONG SIOS-IEUNG → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG IEUNG #
+
+1136 ; 1109 110C ; MA # ( ᄶ → ᄉᄌ ) HANGUL CHOSEONG SIOS-CIEUC → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CIEUC #
+317E ; 1109 110C ; MA # ( ㅾ → ᄉᄌ ) HANGUL LETTER SIOS-CIEUC → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CIEUC # →ᄶ→
+D7EF ; 1109 110C ; MA # ( ퟯ → ᄉᄌ ) HANGUL JONGSEONG SIOS-CIEUC → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CIEUC # →ᆺᆽ→
+
+1137 ; 1109 110E ; MA # ( ᄷ → ᄉᄎ ) HANGUL CHOSEONG SIOS-CHIEUCH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CHIEUCH #
+D7F0 ; 1109 110E ; MA # ( ퟰ → ᄉᄎ ) HANGUL JONGSEONG SIOS-CHIEUCH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG CHIEUCH # →ᆺᆾ→
+
+1138 ; 1109 110F ; MA # ( ᄸ → ᄉᄏ ) HANGUL CHOSEONG SIOS-KHIEUKH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG KHIEUKH #
+
+1139 ; 1109 1110 ; MA # ( ᄹ → ᄉᄐ ) HANGUL CHOSEONG SIOS-THIEUTH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG THIEUTH #
+D7F1 ; 1109 1110 ; MA # ( ퟱ → ᄉᄐ ) HANGUL JONGSEONG SIOS-THIEUTH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG THIEUTH # →ᆺᇀ→
+
+113A ; 1109 1111 ; MA # ( ᄺ → ᄉᄑ ) HANGUL CHOSEONG SIOS-PHIEUPH → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PHIEUPH #
+
+D7EE ; 1109 1140 ; MA # ( ퟮ → ᄉᅀ ) HANGUL JONGSEONG SIOS-PANSIOS → HANGUL CHOSEONG SIOS, HANGUL CHOSEONG PANSIOS # →ᆺᇫ→
+
+3147 ; 110B ; MA # ( ㅇ → ᄋ ) HANGUL LETTER IEUNG → HANGUL CHOSEONG IEUNG #
+11BC ; 110B ; MA # ( ᆼ → ᄋ ) HANGUL JONGSEONG IEUNG → HANGUL CHOSEONG IEUNG #
+
+1141 ; 110B 1100 ; MA # ( ᅁ → ᄋᄀ ) HANGUL CHOSEONG IEUNG-KIYEOK → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG KIYEOK #
+11EC ; 110B 1100 ; MA # ( ᇬ → ᄋᄀ ) HANGUL JONGSEONG IEUNG-KIYEOK → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG KIYEOK # →ᅁ→
+
+11ED ; 110B 1100 1100 ; MA # ( ᇭ → ᄋᄀᄀ ) HANGUL JONGSEONG IEUNG-SSANGKIYEOK → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG KIYEOK, HANGUL CHOSEONG KIYEOK # →ᆼᆨᆨ→
+
+1142 ; 110B 1103 ; MA # ( ᅂ → ᄋᄃ ) HANGUL CHOSEONG IEUNG-TIKEUT → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG TIKEUT #
+
+A976 ; 110B 1105 ; MA # ( ꥶ → ᄋᄅ ) HANGUL CHOSEONG IEUNG-RIEUL → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG RIEUL #
+
+1143 ; 110B 1106 ; MA # ( ᅃ → ᄋᄆ ) HANGUL CHOSEONG IEUNG-MIEUM → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG MIEUM #
+
+1144 ; 110B 1107 ; MA # ( ᅄ → ᄋᄇ ) HANGUL CHOSEONG IEUNG-PIEUP → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG PIEUP #
+
+1145 ; 110B 1109 ; MA # ( ᅅ → ᄋᄉ ) HANGUL CHOSEONG IEUNG-SIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG SIOS #
+11F1 ; 110B 1109 ; MA # ( ᇱ → ᄋᄉ ) HANGUL JONGSEONG YESIEUNG-SIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG SIOS # →ᅅ→
+3182 ; 110B 1109 ; MA # ( ㆂ → ᄋᄉ ) HANGUL LETTER YESIEUNG-SIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG SIOS # →ᇱ→→ᅅ→
+
+1147 ; 110B 110B ; MA # ( ᅇ → ᄋᄋ ) HANGUL CHOSEONG SSANGIEUNG → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG IEUNG #
+3180 ; 110B 110B ; MA # ( ㆀ → ᄋᄋ ) HANGUL LETTER SSANGIEUNG → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG IEUNG # →ᅇ→
+11EE ; 110B 110B ; MA # ( ᇮ → ᄋᄋ ) HANGUL JONGSEONG SSANGIEUNG → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG IEUNG # →ᅇ→
+
+1148 ; 110B 110C ; MA # ( ᅈ → ᄋᄌ ) HANGUL CHOSEONG IEUNG-CIEUC → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG CIEUC #
+
+1149 ; 110B 110E ; MA # ( ᅉ → ᄋᄎ ) HANGUL CHOSEONG IEUNG-CHIEUCH → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG CHIEUCH #
+
+11EF ; 110B 110F ; MA # ( ᇯ → ᄋᄏ ) HANGUL JONGSEONG IEUNG-KHIEUKH → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG KHIEUKH # →ᆼᆿ→
+
+114A ; 110B 1110 ; MA # ( ᅊ → ᄋᄐ ) HANGUL CHOSEONG IEUNG-THIEUTH → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG THIEUTH #
+
+114B ; 110B 1111 ; MA # ( ᅋ → ᄋᄑ ) HANGUL CHOSEONG IEUNG-PHIEUPH → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG PHIEUPH #
+
+A977 ; 110B 1112 ; MA # ( ꥷ → ᄋᄒ ) HANGUL CHOSEONG IEUNG-HIEUH → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG HIEUH #
+
+1146 ; 110B 1140 ; MA # ( ᅆ → ᄋᅀ ) HANGUL CHOSEONG IEUNG-PANSIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG PANSIOS #
+11F2 ; 110B 1140 ; MA # ( ᇲ → ᄋᅀ ) HANGUL JONGSEONG YESIEUNG-PANSIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG PANSIOS # →ᅆ→
+3183 ; 110B 1140 ; MA # ( ㆃ → ᄋᅀ ) HANGUL LETTER YESIEUNG-PANSIOS → HANGUL CHOSEONG IEUNG, HANGUL CHOSEONG PANSIOS # →ᇲ→→ᅆ→
+
+3148 ; 110C ; MA # ( ㅈ → ᄌ ) HANGUL LETTER CIEUC → HANGUL CHOSEONG CIEUC #
+11BD ; 110C ; MA # ( ᆽ → ᄌ ) HANGUL JONGSEONG CIEUC → HANGUL CHOSEONG CIEUC #
+
+D7F7 ; 110C 1107 ; MA # ( ퟷ → ᄌᄇ ) HANGUL JONGSEONG CIEUC-PIEUP → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG PIEUP # →ᆽᆸ→
+
+D7F8 ; 110C 1107 1107 ; MA # ( ퟸ → ᄌᄇᄇ ) HANGUL JONGSEONG CIEUC-SSANGPIEUP → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG PIEUP # →ᆽᆸᆸ→
+
+114D ; 110C 110B ; MA # ( ᅍ → ᄌᄋ ) HANGUL CHOSEONG CIEUC-IEUNG → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG IEUNG #
+
+110D ; 110C 110C ; MA # ( ᄍ → ᄌᄌ ) HANGUL CHOSEONG SSANGCIEUC → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG CIEUC #
+3149 ; 110C 110C ; MA # ( ㅉ → ᄌᄌ ) HANGUL LETTER SSANGCIEUC → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG CIEUC # →ᄍ→
+D7F9 ; 110C 110C ; MA # ( ퟹ → ᄌᄌ ) HANGUL JONGSEONG SSANGCIEUC → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG CIEUC # →ᆽᆽ→
+
+A978 ; 110C 110C 1112 ; MA # ( ꥸ → ᄌᄌᄒ ) HANGUL CHOSEONG SSANGCIEUC-HIEUH → HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG CIEUC, HANGUL CHOSEONG HIEUH #
+
+314A ; 110E ; MA # ( ㅊ → ᄎ ) HANGUL LETTER CHIEUCH → HANGUL CHOSEONG CHIEUCH #
+11BE ; 110E ; MA # ( ᆾ → ᄎ ) HANGUL JONGSEONG CHIEUCH → HANGUL CHOSEONG CHIEUCH #
+
+1152 ; 110E 110F ; MA # ( ᅒ → ᄎᄏ ) HANGUL CHOSEONG CHIEUCH-KHIEUKH → HANGUL CHOSEONG CHIEUCH, HANGUL CHOSEONG KHIEUKH #
+
+1153 ; 110E 1112 ; MA # ( ᅓ → ᄎᄒ ) HANGUL CHOSEONG CHIEUCH-HIEUH → HANGUL CHOSEONG CHIEUCH, HANGUL CHOSEONG HIEUH #
+
+314B ; 110F ; MA # ( ㅋ → ᄏ ) HANGUL LETTER KHIEUKH → HANGUL CHOSEONG KHIEUKH #
+11BF ; 110F ; MA # ( ᆿ → ᄏ ) HANGUL JONGSEONG KHIEUKH → HANGUL CHOSEONG KHIEUKH #
+
+314C ; 1110 ; MA # ( ㅌ → ᄐ ) HANGUL LETTER THIEUTH → HANGUL CHOSEONG THIEUTH #
+11C0 ; 1110 ; MA # ( ᇀ → ᄐ ) HANGUL JONGSEONG THIEUTH → HANGUL CHOSEONG THIEUTH #
+
+A979 ; 1110 1110 ; MA # ( ꥹ → ᄐᄐ ) HANGUL CHOSEONG SSANGTHIEUTH → HANGUL CHOSEONG THIEUTH, HANGUL CHOSEONG THIEUTH #
+
+314D ; 1111 ; MA # ( ㅍ → ᄑ ) HANGUL LETTER PHIEUPH → HANGUL CHOSEONG PHIEUPH #
+11C1 ; 1111 ; MA # ( ᇁ → ᄑ ) HANGUL JONGSEONG PHIEUPH → HANGUL CHOSEONG PHIEUPH #
+
+1156 ; 1111 1107 ; MA # ( ᅖ → ᄑᄇ ) HANGUL CHOSEONG PHIEUPH-PIEUP → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG PIEUP #
+11F3 ; 1111 1107 ; MA # ( ᇳ → ᄑᄇ ) HANGUL JONGSEONG PHIEUPH-PIEUP → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG PIEUP # →ᅖ→
+
+D7FA ; 1111 1109 ; MA # ( ퟺ → ᄑᄉ ) HANGUL JONGSEONG PHIEUPH-SIOS → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG SIOS # →ᇁᆺ→
+
+1157 ; 1111 110B ; MA # ( ᅗ → ᄑᄋ ) HANGUL CHOSEONG KAPYEOUNPHIEUPH → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG IEUNG #
+3184 ; 1111 110B ; MA # ( ㆄ → ᄑᄋ ) HANGUL LETTER KAPYEOUNPHIEUPH → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG IEUNG # →ᅗ→
+11F4 ; 1111 110B ; MA # ( ᇴ → ᄑᄋ ) HANGUL JONGSEONG KAPYEOUNPHIEUPH → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG IEUNG # →ᅗ→
+
+D7FB ; 1111 1110 ; MA # ( ퟻ → ᄑᄐ ) HANGUL JONGSEONG PHIEUPH-THIEUTH → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG THIEUTH # →ᇁᇀ→
+
+A97A ; 1111 1112 ; MA # ( ꥺ → ᄑᄒ ) HANGUL CHOSEONG PHIEUPH-HIEUH → HANGUL CHOSEONG PHIEUPH, HANGUL CHOSEONG HIEUH #
+
+314E ; 1112 ; MA # ( ㅎ → ᄒ ) HANGUL LETTER HIEUH → HANGUL CHOSEONG HIEUH #
+11C2 ; 1112 ; MA # ( ᇂ → ᄒ ) HANGUL JONGSEONG HIEUH → HANGUL CHOSEONG HIEUH #
+
+11F5 ; 1112 1102 ; MA # ( ᇵ → ᄒᄂ ) HANGUL JONGSEONG HIEUH-NIEUN → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG NIEUN # →ᇂᆫ→
+
+11F6 ; 1112 1105 ; MA # ( ᇶ → ᄒᄅ ) HANGUL JONGSEONG HIEUH-RIEUL → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG RIEUL # →ᇂᆯ→
+
+11F7 ; 1112 1106 ; MA # ( ᇷ → ᄒᄆ ) HANGUL JONGSEONG HIEUH-MIEUM → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG MIEUM # →ᇂᆷ→
+
+11F8 ; 1112 1107 ; MA # ( ᇸ → ᄒᄇ ) HANGUL JONGSEONG HIEUH-PIEUP → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG PIEUP # →ᇂᆸ→
+
+A97B ; 1112 1109 ; MA # ( ꥻ → ᄒᄉ ) HANGUL CHOSEONG HIEUH-SIOS → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG SIOS #
+
+1158 ; 1112 1112 ; MA # ( ᅘ → ᄒᄒ ) HANGUL CHOSEONG SSANGHIEUH → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG HIEUH #
+3185 ; 1112 1112 ; MA # ( ㆅ → ᄒᄒ ) HANGUL LETTER SSANGHIEUH → HANGUL CHOSEONG HIEUH, HANGUL CHOSEONG HIEUH # →ᅘ→
+
+113D ; 113C 113C ; MA # ( ᄽ → ᄼᄼ ) HANGUL CHOSEONG CHITUEUMSSANGSIOS → HANGUL CHOSEONG CHITUEUMSIOS, HANGUL CHOSEONG CHITUEUMSIOS #
+
+113F ; 113E 113E ; MA # ( ᄿ → ᄾᄾ ) HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS → HANGUL CHOSEONG CEONGCHIEUMSIOS, HANGUL CHOSEONG CEONGCHIEUMSIOS #
+
+317F ; 1140 ; MA # ( ㅿ → ᅀ ) HANGUL LETTER PANSIOS → HANGUL CHOSEONG PANSIOS #
+11EB ; 1140 ; MA # ( ᇫ → ᅀ ) HANGUL JONGSEONG PANSIOS → HANGUL CHOSEONG PANSIOS #
+
+D7F3 ; 1140 1107 ; MA # ( ퟳ → ᅀᄇ ) HANGUL JONGSEONG PANSIOS-PIEUP → HANGUL CHOSEONG PANSIOS, HANGUL CHOSEONG PIEUP # →ᇫᆸ→
+
+D7F4 ; 1140 1107 110B ; MA # ( ퟴ → ᅀᄇᄋ ) HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP → HANGUL CHOSEONG PANSIOS, HANGUL CHOSEONG PIEUP, HANGUL CHOSEONG IEUNG # →ᇫᆸᆼ→
+
+3181 ; 114C ; MA # ( ㆁ → ᅌ ) HANGUL LETTER YESIEUNG → HANGUL CHOSEONG YESIEUNG #
+11F0 ; 114C ; MA # ( ᇰ → ᅌ ) HANGUL JONGSEONG YESIEUNG → HANGUL CHOSEONG YESIEUNG #
+
+D7F5 ; 114C 1106 ; MA # ( ퟵ → ᅌᄆ ) HANGUL JONGSEONG YESIEUNG-MIEUM → HANGUL CHOSEONG YESIEUNG, HANGUL CHOSEONG MIEUM # →ᇰᆷ→
+
+D7F6 ; 114C 1112 ; MA # ( ퟶ → ᅌᄒ ) HANGUL JONGSEONG YESIEUNG-HIEUH → HANGUL CHOSEONG YESIEUNG, HANGUL CHOSEONG HIEUH # →ᇰᇂ→
+
+114F ; 114E 114E ; MA # ( ᅏ → ᅎᅎ ) HANGUL CHOSEONG CHITUEUMSSANGCIEUC → HANGUL CHOSEONG CHITUEUMCIEUC, HANGUL CHOSEONG CHITUEUMCIEUC #
+
+1151 ; 1150 1150 ; MA # ( ᅑ → ᅐᅐ ) HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC → HANGUL CHOSEONG CEONGCHIEUMCIEUC, HANGUL CHOSEONG CEONGCHIEUMCIEUC #
+
+3186 ; 1159 ; MA # ( ㆆ → ᅙ ) HANGUL LETTER YEORINHIEUH → HANGUL CHOSEONG YEORINHIEUH #
+11F9 ; 1159 ; MA # ( ᇹ → ᅙ ) HANGUL JONGSEONG YEORINHIEUH → HANGUL CHOSEONG YEORINHIEUH #
+
+A97C ; 1159 1159 ; MA # ( ꥼ → ᅙᅙ ) HANGUL CHOSEONG SSANGYEORINHIEUH → HANGUL CHOSEONG YEORINHIEUH, HANGUL CHOSEONG YEORINHIEUH #
+
+3164 ; 1160 ; MA # ( → ) HANGUL FILLER → HANGUL JUNGSEONG FILLER #
+
+314F ; 1161 ; MA # ( ㅏ → ᅡ ) HANGUL LETTER A → HANGUL JUNGSEONG A #
+
+11A3 ; 1161 30FC ; MA # ( ᆣ → ᅡー ) HANGUL JUNGSEONG A-EU → HANGUL JUNGSEONG A, KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ᅡᅳ→
+
+1176 ; 1161 1169 ; MA # ( ᅶ → ᅡᅩ ) HANGUL JUNGSEONG A-O → HANGUL JUNGSEONG A, HANGUL JUNGSEONG O #
+
+1177 ; 1161 116E ; MA # ( ᅷ → ᅡᅮ ) HANGUL JUNGSEONG A-U → HANGUL JUNGSEONG A, HANGUL JUNGSEONG U #
+
+1162 ; 1161 4E28 ; MA # ( ᅢ → ᅡ丨 ) HANGUL JUNGSEONG AE → HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅡᅵ→
+3150 ; 1161 4E28 ; MA # ( ㅐ → ᅡ丨 ) HANGUL LETTER AE → HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅢ→→ᅡᅵ→
+
+3151 ; 1163 ; MA # ( ㅑ → ᅣ ) HANGUL LETTER YA → HANGUL JUNGSEONG YA #
+
+1178 ; 1163 1169 ; MA # ( ᅸ → ᅣᅩ ) HANGUL JUNGSEONG YA-O → HANGUL JUNGSEONG YA, HANGUL JUNGSEONG O #
+
+1179 ; 1163 116D ; MA # ( ᅹ → ᅣᅭ ) HANGUL JUNGSEONG YA-YO → HANGUL JUNGSEONG YA, HANGUL JUNGSEONG YO #
+
+11A4 ; 1163 116E ; MA # ( ᆤ → ᅣᅮ ) HANGUL JUNGSEONG YA-U → HANGUL JUNGSEONG YA, HANGUL JUNGSEONG U #
+
+1164 ; 1163 4E28 ; MA # ( ᅤ → ᅣ丨 ) HANGUL JUNGSEONG YAE → HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᅣᅵ→
+3152 ; 1163 4E28 ; MA # ( ㅒ → ᅣ丨 ) HANGUL LETTER YAE → HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᅤ→→ᅣᅵ→
+
+3153 ; 1165 ; MA # ( ㅓ → ᅥ ) HANGUL LETTER EO → HANGUL JUNGSEONG EO #
+
+117C ; 1165 30FC ; MA # ( ᅼ → ᅥー ) HANGUL JUNGSEONG EO-EU → HANGUL JUNGSEONG EO, KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ᅥᅳ→
+
+117A ; 1165 1169 ; MA # ( ᅺ → ᅥᅩ ) HANGUL JUNGSEONG EO-O → HANGUL JUNGSEONG EO, HANGUL JUNGSEONG O #
+
+117B ; 1165 116E ; MA # ( ᅻ → ᅥᅮ ) HANGUL JUNGSEONG EO-U → HANGUL JUNGSEONG EO, HANGUL JUNGSEONG U #
+
+1166 ; 1165 4E28 ; MA # ( ᅦ → ᅥ丨 ) HANGUL JUNGSEONG E → HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅥᅵ→
+3154 ; 1165 4E28 ; MA # ( ㅔ → ᅥ丨 ) HANGUL LETTER E → HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅦ→→ᅥᅵ→
+
+3155 ; 1167 ; MA # ( ㅕ → ᅧ ) HANGUL LETTER YEO → HANGUL JUNGSEONG YEO #
+
+11A5 ; 1167 1163 ; MA # ( ᆥ → ᅧᅣ ) HANGUL JUNGSEONG YEO-YA → HANGUL JUNGSEONG YEO, HANGUL JUNGSEONG YA #
+
+117D ; 1167 1169 ; MA # ( ᅽ → ᅧᅩ ) HANGUL JUNGSEONG YEO-O → HANGUL JUNGSEONG YEO, HANGUL JUNGSEONG O #
+
+117E ; 1167 116E ; MA # ( ᅾ → ᅧᅮ ) HANGUL JUNGSEONG YEO-U → HANGUL JUNGSEONG YEO, HANGUL JUNGSEONG U #
+
+1168 ; 1167 4E28 ; MA # ( ᅨ → ᅧ丨 ) HANGUL JUNGSEONG YE → HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅧᅵ→
+3156 ; 1167 4E28 ; MA # ( ㅖ → ᅧ丨 ) HANGUL LETTER YE → HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅨ→→ᅧᅵ→
+
+3157 ; 1169 ; MA # ( ㅗ → ᅩ ) HANGUL LETTER O → HANGUL JUNGSEONG O #
+
+116A ; 1169 1161 ; MA # ( ᅪ → ᅩᅡ ) HANGUL JUNGSEONG WA → HANGUL JUNGSEONG O, HANGUL JUNGSEONG A #
+3158 ; 1169 1161 ; MA # ( ㅘ → ᅩᅡ ) HANGUL LETTER WA → HANGUL JUNGSEONG O, HANGUL JUNGSEONG A # →ᅪ→
+
+116B ; 1169 1161 4E28 ; MA # ( ᅫ → ᅩᅡ丨 ) HANGUL JUNGSEONG WAE → HANGUL JUNGSEONG O, HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅡᅵ→
+3159 ; 1169 1161 4E28 ; MA # ( ㅙ → ᅩᅡ丨 ) HANGUL LETTER WAE → HANGUL JUNGSEONG O, HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅫ→→ᅩᅡᅵ→
+
+11A6 ; 1169 1163 ; MA # ( ᆦ → ᅩᅣ ) HANGUL JUNGSEONG O-YA → HANGUL JUNGSEONG O, HANGUL JUNGSEONG YA #
+
+11A7 ; 1169 1163 4E28 ; MA # ( ᆧ → ᅩᅣ丨 ) HANGUL JUNGSEONG O-YAE → HANGUL JUNGSEONG O, HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅣᅵ→
+
+117F ; 1169 1165 ; MA # ( ᅿ → ᅩᅥ ) HANGUL JUNGSEONG O-EO → HANGUL JUNGSEONG O, HANGUL JUNGSEONG EO #
+
+1180 ; 1169 1165 4E28 ; MA # ( ᆀ → ᅩᅥ丨 ) HANGUL JUNGSEONG O-E → HANGUL JUNGSEONG O, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅥᅵ→
+
+D7B0 ; 1169 1167 ; MA # ( ힰ → ᅩᅧ ) HANGUL JUNGSEONG O-YEO → HANGUL JUNGSEONG O, HANGUL JUNGSEONG YEO #
+
+1181 ; 1169 1167 4E28 ; MA # ( ᆁ → ᅩᅧ丨 ) HANGUL JUNGSEONG O-YE → HANGUL JUNGSEONG O, HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅧᅵ→
+
+1182 ; 1169 1169 ; MA # ( ᆂ → ᅩᅩ ) HANGUL JUNGSEONG O-O → HANGUL JUNGSEONG O, HANGUL JUNGSEONG O #
+
+D7B1 ; 1169 1169 4E28 ; MA # ( ힱ → ᅩᅩ丨 ) HANGUL JUNGSEONG O-O-I → HANGUL JUNGSEONG O, HANGUL JUNGSEONG O, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅩᅵ→
+
+1183 ; 1169 116E ; MA # ( ᆃ → ᅩᅮ ) HANGUL JUNGSEONG O-U → HANGUL JUNGSEONG O, HANGUL JUNGSEONG U #
+
+116C ; 1169 4E28 ; MA # ( ᅬ → ᅩ丨 ) HANGUL JUNGSEONG OE → HANGUL JUNGSEONG O, CJK UNIFIED IDEOGRAPH-4E28 # →ᅩᅵ→
+315A ; 1169 4E28 ; MA # ( ㅚ → ᅩ丨 ) HANGUL LETTER OE → HANGUL JUNGSEONG O, CJK UNIFIED IDEOGRAPH-4E28 # →ᅬ→→ᅩᅵ→
+
+315B ; 116D ; MA # ( ㅛ → ᅭ ) HANGUL LETTER YO → HANGUL JUNGSEONG YO #
+
+D7B2 ; 116D 1161 ; MA # ( ힲ → ᅭᅡ ) HANGUL JUNGSEONG YO-A → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG A #
+
+D7B3 ; 116D 1161 4E28 ; MA # ( ힳ → ᅭᅡ丨 ) HANGUL JUNGSEONG YO-AE → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅭᅡᅵ→
+
+1184 ; 116D 1163 ; MA # ( ᆄ → ᅭᅣ ) HANGUL JUNGSEONG YO-YA → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG YA #
+3187 ; 116D 1163 ; MA # ( ㆇ → ᅭᅣ ) HANGUL LETTER YO-YA → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG YA # →ᆄ→
+1186 ; 116D 1163 ; MA # ( ᆆ → ᅭᅣ ) HANGUL JUNGSEONG YO-YEO → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG YA # →ᆄ→
+
+1185 ; 116D 1163 4E28 ; MA # ( ᆅ → ᅭᅣ丨 ) HANGUL JUNGSEONG YO-YAE → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᅭᅣᅵ→
+3188 ; 116D 1163 4E28 ; MA # ( ㆈ → ᅭᅣ丨 ) HANGUL LETTER YO-YAE → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᆅ→→ᅭᅣᅵ→
+
+D7B4 ; 116D 1165 ; MA # ( ힴ → ᅭᅥ ) HANGUL JUNGSEONG YO-EO → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG EO #
+
+1187 ; 116D 1169 ; MA # ( ᆇ → ᅭᅩ ) HANGUL JUNGSEONG YO-O → HANGUL JUNGSEONG YO, HANGUL JUNGSEONG O #
+
+1188 ; 116D 4E28 ; MA # ( ᆈ → ᅭ丨 ) HANGUL JUNGSEONG YO-I → HANGUL JUNGSEONG YO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅭᅵ→
+3189 ; 116D 4E28 ; MA # ( ㆉ → ᅭ丨 ) HANGUL LETTER YO-I → HANGUL JUNGSEONG YO, CJK UNIFIED IDEOGRAPH-4E28 # →ᆈ→→ᅭᅵ→
+
+315C ; 116E ; MA # ( ㅜ → ᅮ ) HANGUL LETTER U → HANGUL JUNGSEONG U #
+
+1189 ; 116E 1161 ; MA # ( ᆉ → ᅮᅡ ) HANGUL JUNGSEONG U-A → HANGUL JUNGSEONG U, HANGUL JUNGSEONG A #
+
+118A ; 116E 1161 4E28 ; MA # ( ᆊ → ᅮᅡ丨 ) HANGUL JUNGSEONG U-AE → HANGUL JUNGSEONG U, HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅮᅡᅵ→
+
+116F ; 116E 1165 ; MA # ( ᅯ → ᅮᅥ ) HANGUL JUNGSEONG WEO → HANGUL JUNGSEONG U, HANGUL JUNGSEONG EO #
+315D ; 116E 1165 ; MA # ( ㅝ → ᅮᅥ ) HANGUL LETTER WEO → HANGUL JUNGSEONG U, HANGUL JUNGSEONG EO # →ᅯ→
+
+118B ; 116E 1165 30FC ; MA # ( ᆋ → ᅮᅥー ) HANGUL JUNGSEONG U-EO-EU → HANGUL JUNGSEONG U, HANGUL JUNGSEONG EO, KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ᅮᅥᅳ→
+
+1170 ; 116E 1165 4E28 ; MA # ( ᅰ → ᅮᅥ丨 ) HANGUL JUNGSEONG WE → HANGUL JUNGSEONG U, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅮᅥᅵ→
+315E ; 116E 1165 4E28 ; MA # ( ㅞ → ᅮᅥ丨 ) HANGUL LETTER WE → HANGUL JUNGSEONG U, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅰ→→ᅮᅥᅵ→
+
+D7B5 ; 116E 1167 ; MA # ( ힵ → ᅮᅧ ) HANGUL JUNGSEONG U-YEO → HANGUL JUNGSEONG U, HANGUL JUNGSEONG YEO #
+
+118C ; 116E 1167 4E28 ; MA # ( ᆌ → ᅮᅧ丨 ) HANGUL JUNGSEONG U-YE → HANGUL JUNGSEONG U, HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅮᅧᅵ→
+
+118D ; 116E 116E ; MA # ( ᆍ → ᅮᅮ ) HANGUL JUNGSEONG U-U → HANGUL JUNGSEONG U, HANGUL JUNGSEONG U #
+
+1171 ; 116E 4E28 ; MA # ( ᅱ → ᅮ丨 ) HANGUL JUNGSEONG WI → HANGUL JUNGSEONG U, CJK UNIFIED IDEOGRAPH-4E28 # →ᅮᅵ→
+315F ; 116E 4E28 ; MA # ( ㅟ → ᅮ丨 ) HANGUL LETTER WI → HANGUL JUNGSEONG U, CJK UNIFIED IDEOGRAPH-4E28 # →ᅱ→→ᅮᅵ→
+
+D7B6 ; 116E 4E28 4E28 ; MA # ( ힶ → ᅮ丨丨 ) HANGUL JUNGSEONG U-I-I → HANGUL JUNGSEONG U, CJK UNIFIED IDEOGRAPH-4E28, CJK UNIFIED IDEOGRAPH-4E28 # →ᅮᅵᅵ→
+
+3160 ; 1172 ; MA # ( ㅠ → ᅲ ) HANGUL LETTER YU → HANGUL JUNGSEONG YU #
+
+118E ; 1172 1161 ; MA # ( ᆎ → ᅲᅡ ) HANGUL JUNGSEONG YU-A → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG A #
+
+D7B7 ; 1172 1161 4E28 ; MA # ( ힷ → ᅲᅡ丨 ) HANGUL JUNGSEONG YU-AE → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG A, CJK UNIFIED IDEOGRAPH-4E28 # →ᅲᅡᅵ→
+
+118F ; 1172 1165 ; MA # ( ᆏ → ᅲᅥ ) HANGUL JUNGSEONG YU-EO → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG EO #
+
+1190 ; 1172 1165 4E28 ; MA # ( ᆐ → ᅲᅥ丨 ) HANGUL JUNGSEONG YU-E → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅲᅥᅵ→
+
+1191 ; 1172 1167 ; MA # ( ᆑ → ᅲᅧ ) HANGUL JUNGSEONG YU-YEO → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG YEO #
+318A ; 1172 1167 ; MA # ( ㆊ → ᅲᅧ ) HANGUL LETTER YU-YEO → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG YEO # →ᆑ→
+
+1192 ; 1172 1167 4E28 ; MA # ( ᆒ → ᅲᅧ丨 ) HANGUL JUNGSEONG YU-YE → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅲᅧᅵ→
+318B ; 1172 1167 4E28 ; MA # ( ㆋ → ᅲᅧ丨 ) HANGUL LETTER YU-YE → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᆒ→→ᅲᅧᅵ→
+
+D7B8 ; 1172 1169 ; MA # ( ힸ → ᅲᅩ ) HANGUL JUNGSEONG YU-O → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG O #
+
+1193 ; 1172 116E ; MA # ( ᆓ → ᅲᅮ ) HANGUL JUNGSEONG YU-U → HANGUL JUNGSEONG YU, HANGUL JUNGSEONG U #
+
+1194 ; 1172 4E28 ; MA # ( ᆔ → ᅲ丨 ) HANGUL JUNGSEONG YU-I → HANGUL JUNGSEONG YU, CJK UNIFIED IDEOGRAPH-4E28 # →ᅲᅵ→
+318C ; 1172 4E28 ; MA # ( ㆌ → ᅲ丨 ) HANGUL LETTER YU-I → HANGUL JUNGSEONG YU, CJK UNIFIED IDEOGRAPH-4E28 # →ᆔ→→ᅲᅵ→
+
+318D ; 119E ; MA # ( ㆍ → ᆞ ) HANGUL LETTER ARAEA → HANGUL JUNGSEONG ARAEA #
+
+D7C5 ; 119E 1161 ; MA # ( ퟅ → ᆞᅡ ) HANGUL JUNGSEONG ARAEA-A → HANGUL JUNGSEONG ARAEA, HANGUL JUNGSEONG A #
+
+119F ; 119E 1165 ; MA # ( ᆟ → ᆞᅥ ) HANGUL JUNGSEONG ARAEA-EO → HANGUL JUNGSEONG ARAEA, HANGUL JUNGSEONG EO #
+
+D7C6 ; 119E 1165 4E28 ; MA # ( ퟆ → ᆞᅥ丨 ) HANGUL JUNGSEONG ARAEA-E → HANGUL JUNGSEONG ARAEA, HANGUL JUNGSEONG EO, CJK UNIFIED IDEOGRAPH-4E28 # →ᆞᅥᅵ→
+
+11A0 ; 119E 116E ; MA # ( ᆠ → ᆞᅮ ) HANGUL JUNGSEONG ARAEA-U → HANGUL JUNGSEONG ARAEA, HANGUL JUNGSEONG U #
+
+11A2 ; 119E 119E ; MA # ( ᆢ → ᆞᆞ ) HANGUL JUNGSEONG SSANGARAEA → HANGUL JUNGSEONG ARAEA, HANGUL JUNGSEONG ARAEA #
+
+11A1 ; 119E 4E28 ; MA # ( ᆡ → ᆞ丨 ) HANGUL JUNGSEONG ARAEA-I → HANGUL JUNGSEONG ARAEA, CJK UNIFIED IDEOGRAPH-4E28 # →ᆞᅵ→
+318E ; 119E 4E28 ; MA # ( ㆎ → ᆞ丨 ) HANGUL LETTER ARAEAE → HANGUL JUNGSEONG ARAEA, CJK UNIFIED IDEOGRAPH-4E28 # →ᆡ→→ᆞᅵ→
+
+30D8 ; 3078 ; MA # ( ヘ → へ ) KATAKANA LETTER HE → HIRAGANA LETTER HE #
+
+2341 ; 303C ; MA #* ( ⍁ → 〼 ) APL FUNCTIONAL SYMBOL QUAD SLASH → MASU MARK # →⧄→
+29C4 ; 303C ; MA #* ( ⧄ → 〼 ) SQUARED RISING DIAGONAL SLASH → MASU MARK #
+
+A49E ; A04A ; MA #* ( ꒞ → ꁊ ) YI RADICAL PUT → YI SYLLABLE PUT #
+
+A4AC ; A050 ; MA #* ( ꒬ → ꁐ ) YI RADICAL PYT → YI SYLLABLE PYT #
+
+A49C ; A0C0 ; MA #* ( ꒜ → ꃀ ) YI RADICAL MOP → YI SYLLABLE MOP #
+
+A4A8 ; A132 ; MA #* ( ꒨ → ꄲ ) YI RADICAL TU → YI SYLLABLE TU #
+
+A4BF ; A259 ; MA #* ( ꒿ → ꉙ ) YI RADICAL HXOP → YI SYLLABLE HXOP #
+
+A4BE ; A2B1 ; MA #* ( ꒾ → ꊱ ) YI RADICAL CIP → YI SYLLABLE CIP #
+
+A494 ; A2CD ; MA #* ( ꒔ → ꋍ ) YI RADICAL CYP → YI SYLLABLE CYP #
+
+A4C0 ; A3AB ; MA #* ( ꓀ → ꎫ ) YI RADICAL SHAT → YI SYLLABLE SHAT #
+
+A4C2 ; A3B5 ; MA #* ( ꓂ → ꎵ ) YI RADICAL SHOP → YI SYLLABLE SHOP #
+
+A4BA ; A3BF ; MA #* ( ꒺ → ꎿ ) YI RADICAL SHUR → YI SYLLABLE SHUR #
+
+A4B0 ; A3C2 ; MA #* ( ꒰ → ꏂ ) YI RADICAL SHY → YI SYLLABLE SHY #
+
+A4A7 ; A458 ; MA #* ( ꒧ → ꑘ ) YI RADICAL NYOP → YI SYLLABLE NYOP #
+
+22A5 ; A4D5 ; MA #* ( ⊥ → ꓕ ) UP TACK → LISU LETTER THA #
+27C2 ; A4D5 ; MA #* ( ⟂ → ꓕ ) PERPENDICULAR → LISU LETTER THA # →⊥→
+1D21C ; A4D5 ; MA #* ( 𝈜 → ꓕ ) GREEK VOCAL NOTATION SYMBOL-54 → LISU LETTER THA # →Ʇ→
+A7B1 ; A4D5 ; MA # ( Ʇ → ꓕ ) LATIN CAPITAL LETTER TURNED T → LISU LETTER THA #
+
+A79E ; A4E4 ; MA # ( Ꞟ → ꓤ ) LATIN CAPITAL LETTER VOLAPUK UE → LISU LETTER ZA #
+
+2141 ; A4E8 ; MA #* ( ⅁ → ꓨ ) TURNED SANS-SERIF CAPITAL G → LISU LETTER HHA #
+
+2142 ; A4F6 ; MA #* ( ⅂ → ꓶ ) TURNED SANS-SERIF CAPITAL L → LISU LETTER UH #
+1D215 ; A4F6 ; MA #* ( 𝈕 → ꓶ ) GREEK VOCAL NOTATION SYMBOL-22 → LISU LETTER UH # →⅂→
+1D22B ; A4F6 ; MA #* ( 𝈫 → ꓶ ) GREEK INSTRUMENTAL NOTATION SYMBOL-24 → LISU LETTER UH # →𝈕→→⅂→
+16F26 ; A4F6 ; MA # ( 𖼦 → ꓶ ) MIAO LETTER HA → LISU LETTER UH # →⅂→
+10411 ; A4F6 ; MA # ( 𐐑 → ꓶ ) DESERET CAPITAL LETTER PEE → LISU LETTER UH # →⅂→
+
+2143 ; 16F00 ; MA #* ( ⅃ → 𖼀 ) REVERSED SANS-SERIF CAPITAL L → MIAO LETTER PA #
+
+11AE6 ; 11AE5 11AEF ; MA # ( 𑫦 → 𑫥𑫯 ) PAU CIN HAU RISING TONE → PAU CIN HAU RISING TONE LONG, PAU CIN HAU MID-LEVEL TONE #
+
+11AE8 ; 11AE5 11AE5 ; MA # ( 𑫨 → 𑫥𑫥 ) PAU CIN HAU RISING TONE LONG FINAL → PAU CIN HAU RISING TONE LONG, PAU CIN HAU RISING TONE LONG #
+
+11AE9 ; 11AE5 11AE5 11AEF ; MA # ( 𑫩 → 𑫥𑫥𑫯 ) PAU CIN HAU RISING TONE FINAL → PAU CIN HAU RISING TONE LONG, PAU CIN HAU RISING TONE LONG, PAU CIN HAU MID-LEVEL TONE # →𑫥𑫦→
+
+11AEA ; 11AE5 11AE5 11AF0 ; MA # ( 𑫪 → 𑫥𑫥𑫰 ) PAU CIN HAU SANDHI GLOTTAL STOP FINAL → PAU CIN HAU RISING TONE LONG, PAU CIN HAU RISING TONE LONG, PAU CIN HAU GLOTTAL STOP VARIANT # →𑫥𑫧→
+
+11AE7 ; 11AE5 11AF0 ; MA # ( 𑫧 → 𑫥𑫰 ) PAU CIN HAU SANDHI GLOTTAL STOP → PAU CIN HAU RISING TONE LONG, PAU CIN HAU GLOTTAL STOP VARIANT #
+
+11AF4 ; 11AF3 11AEF ; MA # ( 𑫴 → 𑫳𑫯 ) PAU CIN HAU LOW-FALLING TONE → PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU MID-LEVEL TONE #
+
+11AF6 ; 11AF3 11AF3 ; MA # ( 𑫶 → 𑫳𑫳 ) PAU CIN HAU LOW-FALLING TONE LONG FINAL → PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU LOW-FALLING TONE LONG #
+
+11AF7 ; 11AF3 11AF3 11AEF ; MA # ( 𑫷 → 𑫳𑫳𑫯 ) PAU CIN HAU LOW-FALLING TONE FINAL → PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU MID-LEVEL TONE # →𑫳𑫴→
+
+11AF8 ; 11AF3 11AF3 11AF0 ; MA # ( 𑫸 → 𑫳𑫳𑫰 ) PAU CIN HAU GLOTTAL STOP FINAL → PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU GLOTTAL STOP VARIANT # →𑫳𑫵→
+
+11AF5 ; 11AF3 11AF0 ; MA # ( 𑫵 → 𑫳𑫰 ) PAU CIN HAU GLOTTAL STOP → PAU CIN HAU LOW-FALLING TONE LONG, PAU CIN HAU GLOTTAL STOP VARIANT #
+
+11AEC ; 11AEB 11AEF ; MA # ( 𑫬 → 𑫫𑫯 ) PAU CIN HAU SANDHI TONE → PAU CIN HAU SANDHI TONE LONG, PAU CIN HAU MID-LEVEL TONE #
+
+11AED ; 11AEB 11AEB ; MA # ( 𑫭 → 𑫫𑫫 ) PAU CIN HAU SANDHI TONE LONG FINAL → PAU CIN HAU SANDHI TONE LONG, PAU CIN HAU SANDHI TONE LONG #
+
+11AEE ; 11AEB 11AEB 11AEF ; MA # ( 𑫮 → 𑫫𑫫𑫯 ) PAU CIN HAU SANDHI TONE FINAL → PAU CIN HAU SANDHI TONE LONG, PAU CIN HAU SANDHI TONE LONG, PAU CIN HAU MID-LEVEL TONE # →𑫫𑫬→
+
+2295 ; 102A8 ; MA #* ( ⊕ → 𐊨 ) CIRCLED PLUS → CARIAN LETTER Q #
+2A01 ; 102A8 ; MA #* ( ⨁ → 𐊨 ) N-ARY CIRCLED PLUS OPERATOR → CARIAN LETTER Q # →⊕→
+1F728 ; 102A8 ; MA #* ( 🜨 → 𐊨 ) ALCHEMICAL SYMBOL FOR VERDIGRIS → CARIAN LETTER Q # →⊕→
+A69A ; 102A8 ; MA # ( Ꚛ → 𐊨 ) CYRILLIC CAPITAL LETTER CROSSED O → CARIAN LETTER Q # →⊕→
+
+25BD ; 102BC ; MA #* ( ▽ → 𐊼 ) WHITE DOWN-POINTING TRIANGLE → CARIAN LETTER K #
+1D214 ; 102BC ; MA #* ( 𝈔 → 𐊼 ) GREEK VOCAL NOTATION SYMBOL-21 → CARIAN LETTER K # →▽→
+1F704 ; 102BC ; MA #* ( 🜄 → 𐊼 ) ALCHEMICAL SYMBOL FOR WATER → CARIAN LETTER K # →▽→
+
+29D6 ; 102C0 ; MA #* ( ⧖ → 𐋀 ) WHITE HOURGLASS → CARIAN LETTER G #
+
+A79B ; 1043A ; MA # ( ꞛ → 𐐺 ) LATIN SMALL LETTER VOLAPUK AE → DESERET SMALL LETTER BEE #
+
+A79A ; 10412 ; MA # ( Ꞛ → 𐐒 ) LATIN CAPITAL LETTER VOLAPUK AE → DESERET CAPITAL LETTER BEE #
+
+104A0 ; 10486 ; MA # ( 𐒠 → 𐒆 ) OSMANYA DIGIT ZERO → OSMANYA LETTER DEEL #
+
+103D1 ; 10382 ; MA # ( 𐏑 → 𐎂 ) OLD PERSIAN NUMBER ONE → UGARITIC LETTER GAMLA #
+
+103D3 ; 10393 ; MA # ( 𐏓 → 𐎓 ) OLD PERSIAN NUMBER TEN → UGARITIC LETTER AIN #
+
+12038 ; 1039A ; MA # ( 𒀸 → 𐎚 ) CUNEIFORM SIGN ASH → UGARITIC LETTER TO #
+
+2625 ; 1099E ; MA #* ( ☥ → ‎𐦞‎ ) ANKH → MEROITIC HIEROGLYPHIC SYMBOL VIDJ #
+132F9 ; 1099E ; MA # ( 𓋹 → ‎𐦞‎ ) EGYPTIAN HIEROGLYPH S034 → MEROITIC HIEROGLYPHIC SYMBOL VIDJ # →☥→
+
+3039 ; 5344 ; MA # ( 〹 → 卄 ) HANGZHOU NUMERAL TWENTY → CJK UNIFIED IDEOGRAPH-5344 #
+
+F967 ; 4E0D ; MA # ( 不 → 不 ) CJK COMPATIBILITY IDEOGRAPH-F967 → CJK UNIFIED IDEOGRAPH-4E0D #
+
+2F800 ; 4E3D ; MA # ( 丽 → 丽 ) CJK COMPATIBILITY IDEOGRAPH-2F800 → CJK UNIFIED IDEOGRAPH-4E3D #
+
+FA70 ; 4E26 ; MA # ( 並 → 並 ) CJK COMPATIBILITY IDEOGRAPH-FA70 → CJK UNIFIED IDEOGRAPH-4E26 #
+
+239C ; 4E28 ; MA #* ( ⎜ → 丨 ) LEFT PARENTHESIS EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 # →⎥→→⎮→
+239F ; 4E28 ; MA #* ( ⎟ → 丨 ) RIGHT PARENTHESIS EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 # →⎥→→⎮→
+23A2 ; 4E28 ; MA #* ( ⎢ → 丨 ) LEFT SQUARE BRACKET EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 # →⎥→→⎮→
+23A5 ; 4E28 ; MA #* ( ⎥ → 丨 ) RIGHT SQUARE BRACKET EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 # →⎮→
+23AA ; 4E28 ; MA #* ( ⎪ → 丨 ) CURLY BRACKET EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 # →⎥→→⎮→
+23AE ; 4E28 ; MA #* ( ⎮ → 丨 ) INTEGRAL EXTENSION → CJK UNIFIED IDEOGRAPH-4E28 #
+31D1 ; 4E28 ; MA #* ( ㇑ → 丨 ) CJK STROKE S → CJK UNIFIED IDEOGRAPH-4E28 #
+1175 ; 4E28 ; MA # ( ᅵ → 丨 ) HANGUL JUNGSEONG I → CJK UNIFIED IDEOGRAPH-4E28 # →ㅣ→
+3163 ; 4E28 ; MA # ( ㅣ → 丨 ) HANGUL LETTER I → CJK UNIFIED IDEOGRAPH-4E28 #
+2F01 ; 4E28 ; MA #* ( ⼁ → 丨 ) KANGXI RADICAL LINE → CJK UNIFIED IDEOGRAPH-4E28 #
+
+119C ; 4E28 30FC ; MA # ( ᆜ → 丨ー ) HANGUL JUNGSEONG I-EU → CJK UNIFIED IDEOGRAPH-4E28, KATAKANA-HIRAGANA PROLONGED SOUND MARK # →ᅵᅳ→
+
+1198 ; 4E28 1161 ; MA # ( ᆘ → 丨ᅡ ) HANGUL JUNGSEONG I-A → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG A # →ᅵᅡ→
+
+1199 ; 4E28 1163 ; MA # ( ᆙ → 丨ᅣ ) HANGUL JUNGSEONG I-YA → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YA # →ᅵᅣ→
+
+D7BD ; 4E28 1163 1169 ; MA # ( ힽ → 丨ᅣᅩ ) HANGUL JUNGSEONG I-YA-O → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YA, HANGUL JUNGSEONG O # →ᅵᅣᅩ→
+
+D7BE ; 4E28 1163 4E28 ; MA # ( ힾ → 丨ᅣ丨 ) HANGUL JUNGSEONG I-YAE → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YA, CJK UNIFIED IDEOGRAPH-4E28 # →ᅵᅣᅵ→
+
+D7BF ; 4E28 1167 ; MA # ( ힿ → 丨ᅧ ) HANGUL JUNGSEONG I-YEO → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YEO # →ᅵᅧ→
+
+D7C0 ; 4E28 1167 4E28 ; MA # ( ퟀ → 丨ᅧ丨 ) HANGUL JUNGSEONG I-YE → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YEO, CJK UNIFIED IDEOGRAPH-4E28 # →ᅵᅧᅵ→
+
+119A ; 4E28 1169 ; MA # ( ᆚ → 丨ᅩ ) HANGUL JUNGSEONG I-O → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG O # →ᅵᅩ→
+
+D7C1 ; 4E28 1169 4E28 ; MA # ( ퟁ → 丨ᅩ丨 ) HANGUL JUNGSEONG I-O-I → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG O, CJK UNIFIED IDEOGRAPH-4E28 # →ᅵᅩᅵ→
+
+D7C2 ; 4E28 116D ; MA # ( ퟂ → 丨ᅭ ) HANGUL JUNGSEONG I-YO → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YO # →ᅵᅭ→
+
+119B ; 4E28 116E ; MA # ( ᆛ → 丨ᅮ ) HANGUL JUNGSEONG I-U → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG U # →ᅵᅮ→
+
+D7C3 ; 4E28 1172 ; MA # ( ퟃ → 丨ᅲ ) HANGUL JUNGSEONG I-YU → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG YU # →ᅵᅲ→
+
+119D ; 4E28 119E ; MA # ( ᆝ → 丨ᆞ ) HANGUL JUNGSEONG I-ARAEA → CJK UNIFIED IDEOGRAPH-4E28, HANGUL JUNGSEONG ARAEA # →ᅵᆞ→
+
+D7C4 ; 4E28 4E28 ; MA # ( ퟄ → 丨丨 ) HANGUL JUNGSEONG I-I → CJK UNIFIED IDEOGRAPH-4E28, CJK UNIFIED IDEOGRAPH-4E28 # →ᅵᅵ→
+
+F905 ; 4E32 ; MA # ( 串 → 串 ) CJK COMPATIBILITY IDEOGRAPH-F905 → CJK UNIFIED IDEOGRAPH-4E32 #
+
+2F801 ; 4E38 ; MA # ( 丸 → 丸 ) CJK COMPATIBILITY IDEOGRAPH-2F801 → CJK UNIFIED IDEOGRAPH-4E38 #
+
+F95E ; 4E39 ; MA # ( 丹 → 丹 ) CJK COMPATIBILITY IDEOGRAPH-F95E → CJK UNIFIED IDEOGRAPH-4E39 #
+
+2F802 ; 4E41 ; MA # ( 乁 → 乁 ) CJK COMPATIBILITY IDEOGRAPH-2F802 → CJK UNIFIED IDEOGRAPH-4E41 #
+
+31E0 ; 4E59 ; MA #* ( ㇠ → 乙 ) CJK STROKE HXWG → CJK UNIFIED IDEOGRAPH-4E59 #
+2F04 ; 4E59 ; MA #* ( ⼄ → 乙 ) KANGXI RADICAL SECOND → CJK UNIFIED IDEOGRAPH-4E59 #
+
+31DF ; 4E5A ; MA #* ( ㇟ → 乚 ) CJK STROKE SWG → CJK UNIFIED IDEOGRAPH-4E5A #
+2E83 ; 4E5A ; MA #* ( ⺃ → 乚 ) CJK RADICAL SECOND TWO → CJK UNIFIED IDEOGRAPH-4E5A #
+
+31D6 ; 4E5B ; MA #* ( ㇖ → 乛 ) CJK STROKE HG → CJK UNIFIED IDEOGRAPH-4E5B #
+2E82 ; 4E5B ; MA #* ( ⺂ → 乛 ) CJK RADICAL SECOND ONE → CJK UNIFIED IDEOGRAPH-4E5B # →㇖→
+
+2EF2 ; 4E80 ; MA #* ( ⻲ → 亀 ) CJK RADICAL J-SIMPLIFIED TURTLE → CJK UNIFIED IDEOGRAPH-4E80 #
+
+F91B ; 4E82 ; MA # ( 亂 → 亂 ) CJK COMPATIBILITY IDEOGRAPH-F91B → CJK UNIFIED IDEOGRAPH-4E82 #
+
+31DA ; 4E85 ; MA #* ( ㇚ → 亅 ) CJK STROKE SG → CJK UNIFIED IDEOGRAPH-4E85 #
+2F05 ; 4E85 ; MA #* ( ⼅ → 亅 ) KANGXI RADICAL HOOK → CJK UNIFIED IDEOGRAPH-4E85 #
+
+F9BA ; 4E86 ; MA # ( 了 → 了 ) CJK COMPATIBILITY IDEOGRAPH-F9BA → CJK UNIFIED IDEOGRAPH-4E86 #
+
+30CB ; 4E8C ; MA # ( ニ → 二 ) KATAKANA LETTER NI → CJK UNIFIED IDEOGRAPH-4E8C #
+2F06 ; 4E8C ; MA #* ( ⼆ → 二 ) KANGXI RADICAL TWO → CJK UNIFIED IDEOGRAPH-4E8C #
+
+2F803 ; 20122 ; MA # ( 𠄢 → 𠄢 ) CJK COMPATIBILITY IDEOGRAPH-2F803 → CJK UNIFIED IDEOGRAPH-20122 #
+
+2F07 ; 4EA0 ; MA #* ( ⼇ → 亠 ) KANGXI RADICAL LID → CJK UNIFIED IDEOGRAPH-4EA0 #
+
+F977 ; 4EAE ; MA # ( 亮 → 亮 ) CJK COMPATIBILITY IDEOGRAPH-F977 → CJK UNIFIED IDEOGRAPH-4EAE #
+
+2F08 ; 4EBA ; MA #* ( ⼈ → 人 ) KANGXI RADICAL MAN → CJK UNIFIED IDEOGRAPH-4EBA #
+
+30A4 ; 4EBB ; MA # ( イ → 亻 ) KATAKANA LETTER I → CJK UNIFIED IDEOGRAPH-4EBB # →⺅→
+2E85 ; 4EBB ; MA #* ( ⺅ → 亻 ) CJK RADICAL PERSON → CJK UNIFIED IDEOGRAPH-4EBB #
+
+F9FD ; 4EC0 ; MA # ( 什 → 什 ) CJK COMPATIBILITY IDEOGRAPH-F9FD → CJK UNIFIED IDEOGRAPH-4EC0 #
+
+2F819 ; 4ECC ; MA # ( 仌 → 仌 ) CJK COMPATIBILITY IDEOGRAPH-2F819 → CJK UNIFIED IDEOGRAPH-4ECC #
+
+F9A8 ; 4EE4 ; MA # ( 令 → 令 ) CJK COMPATIBILITY IDEOGRAPH-F9A8 → CJK UNIFIED IDEOGRAPH-4EE4 #
+
+2F804 ; 4F60 ; MA # ( 你 → 你 ) CJK COMPATIBILITY IDEOGRAPH-2F804 → CJK UNIFIED IDEOGRAPH-4F60 #
+
+5002 ; 4F75 ; MA # ( 倂 → 併 ) CJK UNIFIED IDEOGRAPH-5002 → CJK UNIFIED IDEOGRAPH-4F75 #
+2F807 ; 4F75 ; MA # ( 倂 → 併 ) CJK COMPATIBILITY IDEOGRAPH-2F807 → CJK UNIFIED IDEOGRAPH-4F75 # →倂→
+
+FA73 ; 4F80 ; MA # ( 侀 → 侀 ) CJK COMPATIBILITY IDEOGRAPH-FA73 → CJK UNIFIED IDEOGRAPH-4F80 #
+
+F92D ; 4F86 ; MA # ( 來 → 來 ) CJK COMPATIBILITY IDEOGRAPH-F92D → CJK UNIFIED IDEOGRAPH-4F86 #
+
+F9B5 ; 4F8B ; MA # ( 例 → 例 ) CJK COMPATIBILITY IDEOGRAPH-F9B5 → CJK UNIFIED IDEOGRAPH-4F8B #
+
+FA30 ; 4FAE ; MA # ( 侮 → 侮 ) CJK COMPATIBILITY IDEOGRAPH-FA30 → CJK UNIFIED IDEOGRAPH-4FAE #
+2F805 ; 4FAE ; MA # ( 侮 → 侮 ) CJK COMPATIBILITY IDEOGRAPH-2F805 → CJK UNIFIED IDEOGRAPH-4FAE #
+
+2F806 ; 4FBB ; MA # ( 侻 → 侻 ) CJK COMPATIBILITY IDEOGRAPH-2F806 → CJK UNIFIED IDEOGRAPH-4FBB #
+
+F965 ; 4FBF ; MA # ( 便 → 便 ) CJK COMPATIBILITY IDEOGRAPH-F965 → CJK UNIFIED IDEOGRAPH-4FBF #
+
+503C ; 5024 ; MA # ( 值 → 値 ) CJK UNIFIED IDEOGRAPH-503C → CJK UNIFIED IDEOGRAPH-5024 #
+
+F9D4 ; 502B ; MA # ( 倫 → 倫 ) CJK COMPATIBILITY IDEOGRAPH-F9D4 → CJK UNIFIED IDEOGRAPH-502B #
+
+2F808 ; 507A ; MA # ( 偺 → 偺 ) CJK COMPATIBILITY IDEOGRAPH-2F808 → CJK UNIFIED IDEOGRAPH-507A #
+
+2F809 ; 5099 ; MA # ( 備 → 備 ) CJK COMPATIBILITY IDEOGRAPH-2F809 → CJK UNIFIED IDEOGRAPH-5099 #
+
+2F80B ; 50CF ; MA # ( 像 → 像 ) CJK COMPATIBILITY IDEOGRAPH-2F80B → CJK UNIFIED IDEOGRAPH-50CF #
+
+F9BB ; 50DA ; MA # ( 僚 → 僚 ) CJK COMPATIBILITY IDEOGRAPH-F9BB → CJK UNIFIED IDEOGRAPH-50DA #
+
+FA31 ; 50E7 ; MA # ( 僧 → 僧 ) CJK COMPATIBILITY IDEOGRAPH-FA31 → CJK UNIFIED IDEOGRAPH-50E7 #
+2F80A ; 50E7 ; MA # ( 僧 → 僧 ) CJK COMPATIBILITY IDEOGRAPH-2F80A → CJK UNIFIED IDEOGRAPH-50E7 #
+
+2F80C ; 349E ; MA # ( 㒞 → 㒞 ) CJK COMPATIBILITY IDEOGRAPH-2F80C → CJK UNIFIED IDEOGRAPH-349E #
+
+2F09 ; 513F ; MA #* ( ⼉ → 儿 ) KANGXI RADICAL LEGS → CJK UNIFIED IDEOGRAPH-513F #
+
+FA0C ; 5140 ; MA # ( 兀 → 兀 ) CJK COMPATIBILITY IDEOGRAPH-FA0C → CJK UNIFIED IDEOGRAPH-5140 #
+2E8E ; 5140 ; MA #* ( ⺎ → 兀 ) CJK RADICAL LAME ONE → CJK UNIFIED IDEOGRAPH-5140 #
+
+FA74 ; 5145 ; MA # ( 充 → 充 ) CJK COMPATIBILITY IDEOGRAPH-FA74 → CJK UNIFIED IDEOGRAPH-5145 #
+
+FA32 ; 514D ; MA # ( 免 → 免 ) CJK COMPATIBILITY IDEOGRAPH-FA32 → CJK UNIFIED IDEOGRAPH-514D #
+2F80E ; 514D ; MA # ( 免 → 免 ) CJK COMPATIBILITY IDEOGRAPH-2F80E → CJK UNIFIED IDEOGRAPH-514D #
+
+2F80F ; 5154 ; MA # ( 兔 → 兔 ) CJK COMPATIBILITY IDEOGRAPH-2F80F → CJK UNIFIED IDEOGRAPH-5154 #
+
+2F810 ; 5164 ; MA # ( 兤 → 兤 ) CJK COMPATIBILITY IDEOGRAPH-2F810 → CJK UNIFIED IDEOGRAPH-5164 #
+
+2F0A ; 5165 ; MA #* ( ⼊ → 入 ) KANGXI RADICAL ENTER → CJK UNIFIED IDEOGRAPH-5165 #
+
+2F814 ; 5167 ; MA # ( 內 → 內 ) CJK COMPATIBILITY IDEOGRAPH-2F814 → CJK UNIFIED IDEOGRAPH-5167 #
+
+FA72 ; 5168 ; MA # ( 全 → 全 ) CJK COMPATIBILITY IDEOGRAPH-FA72 → CJK UNIFIED IDEOGRAPH-5168 #
+
+F978 ; 5169 ; MA # ( 兩 → 兩 ) CJK COMPATIBILITY IDEOGRAPH-F978 → CJK UNIFIED IDEOGRAPH-5169 #
+
+30CF ; 516B ; MA # ( ハ → 八 ) KATAKANA LETTER HA → CJK UNIFIED IDEOGRAPH-516B #
+2F0B ; 516B ; MA #* ( ⼋ → 八 ) KANGXI RADICAL EIGHT → CJK UNIFIED IDEOGRAPH-516B #
+
+F9D1 ; 516D ; MA # ( 六 → 六 ) CJK COMPATIBILITY IDEOGRAPH-F9D1 → CJK UNIFIED IDEOGRAPH-516D #
+
+2F811 ; 5177 ; MA # ( 具 → 具 ) CJK COMPATIBILITY IDEOGRAPH-2F811 → CJK UNIFIED IDEOGRAPH-5177 #
+
+2F812 ; 2051C ; MA # ( 𠔜 → 𠔜 ) CJK COMPATIBILITY IDEOGRAPH-2F812 → CJK UNIFIED IDEOGRAPH-2051C #
+
+2F91B ; 20525 ; MA # ( 𠔥 → 𠔥 ) CJK COMPATIBILITY IDEOGRAPH-2F91B → CJK UNIFIED IDEOGRAPH-20525 #
+
+FA75 ; 5180 ; MA # ( 冀 → 冀 ) CJK COMPATIBILITY IDEOGRAPH-FA75 → CJK UNIFIED IDEOGRAPH-5180 #
+
+2F813 ; 34B9 ; MA # ( 㒹 → 㒹 ) CJK COMPATIBILITY IDEOGRAPH-2F813 → CJK UNIFIED IDEOGRAPH-34B9 #
+
+2F0C ; 5182 ; MA #* ( ⼌ → 冂 ) KANGXI RADICAL DOWN BOX → CJK UNIFIED IDEOGRAPH-5182 #
+
+2F815 ; 518D ; MA # ( 再 → 再 ) CJK COMPATIBILITY IDEOGRAPH-2F815 → CJK UNIFIED IDEOGRAPH-518D #
+
+2F816 ; 2054B ; MA # ( 𠕋 → 𠕋 ) CJK COMPATIBILITY IDEOGRAPH-2F816 → CJK UNIFIED IDEOGRAPH-2054B #
+
+2F8D2 ; 5192 ; MA # ( 冒 → 冒 ) CJK COMPATIBILITY IDEOGRAPH-2F8D2 → CJK UNIFIED IDEOGRAPH-5192 #
+
+2F8D3 ; 5195 ; MA # ( 冕 → 冕 ) CJK COMPATIBILITY IDEOGRAPH-2F8D3 → CJK UNIFIED IDEOGRAPH-5195 #
+
+2F9CA ; 34BB ; MA # ( 㒻 → 㒻 ) CJK COMPATIBILITY IDEOGRAPH-2F9CA → CJK UNIFIED IDEOGRAPH-34BB #
+
+2F8D4 ; 6700 ; MA # ( 最 → 最 ) CJK COMPATIBILITY IDEOGRAPH-2F8D4 → CJK UNIFIED IDEOGRAPH-6700 #
+
+2F0D ; 5196 ; MA #* ( ⼍ → 冖 ) KANGXI RADICAL COVER → CJK UNIFIED IDEOGRAPH-5196 #
+
+2F817 ; 5197 ; MA # ( 冗 → 冗 ) CJK COMPATIBILITY IDEOGRAPH-2F817 → CJK UNIFIED IDEOGRAPH-5197 #
+
+2F818 ; 51A4 ; MA # ( 冤 → 冤 ) CJK COMPATIBILITY IDEOGRAPH-2F818 → CJK UNIFIED IDEOGRAPH-51A4 #
+
+2F0E ; 51AB ; MA #* ( ⼎ → 冫 ) KANGXI RADICAL ICE → CJK UNIFIED IDEOGRAPH-51AB #
+
+2F81A ; 51AC ; MA # ( 冬 → 冬 ) CJK COMPATIBILITY IDEOGRAPH-2F81A → CJK UNIFIED IDEOGRAPH-51AC #
+
+FA71 ; 51B5 ; MA # ( 况 → 况 ) CJK COMPATIBILITY IDEOGRAPH-FA71 → CJK UNIFIED IDEOGRAPH-51B5 #
+2F81B ; 51B5 ; MA # ( 况 → 况 ) CJK COMPATIBILITY IDEOGRAPH-2F81B → CJK UNIFIED IDEOGRAPH-51B5 #
+
+F92E ; 51B7 ; MA # ( 冷 → 冷 ) CJK COMPATIBILITY IDEOGRAPH-F92E → CJK UNIFIED IDEOGRAPH-51B7 #
+
+F979 ; 51C9 ; MA # ( 凉 → 凉 ) CJK COMPATIBILITY IDEOGRAPH-F979 → CJK UNIFIED IDEOGRAPH-51C9 #
+
+F955 ; 51CC ; MA # ( 凌 → 凌 ) CJK COMPATIBILITY IDEOGRAPH-F955 → CJK UNIFIED IDEOGRAPH-51CC #
+
+F954 ; 51DC ; MA # ( 凜 → 凜 ) CJK COMPATIBILITY IDEOGRAPH-F954 → CJK UNIFIED IDEOGRAPH-51DC #
+
+FA15 ; 51DE ; MA # ( 凞 → 凞 ) CJK COMPATIBILITY IDEOGRAPH-FA15 → CJK UNIFIED IDEOGRAPH-51DE #
+
+2F0F ; 51E0 ; MA #* ( ⼏ → 几 ) KANGXI RADICAL TABLE → CJK UNIFIED IDEOGRAPH-51E0 #
+
+2F80D ; 2063A ; MA # ( 𠘺 → 𠘺 ) CJK COMPATIBILITY IDEOGRAPH-2F80D → CJK UNIFIED IDEOGRAPH-2063A #
+
+2F81D ; 51F5 ; MA # ( 凵 → 凵 ) CJK COMPATIBILITY IDEOGRAPH-2F81D → CJK UNIFIED IDEOGRAPH-51F5 #
+2F10 ; 51F5 ; MA #* ( ⼐ → 凵 ) KANGXI RADICAL OPEN BOX → CJK UNIFIED IDEOGRAPH-51F5 #
+
+2F11 ; 5200 ; MA #* ( ⼑ → 刀 ) KANGXI RADICAL KNIFE → CJK UNIFIED IDEOGRAPH-5200 #
+
+2E89 ; 5202 ; MA #* ( ⺉ → 刂 ) CJK RADICAL KNIFE TWO → CJK UNIFIED IDEOGRAPH-5202 #
+
+2F81E ; 5203 ; MA # ( 刃 → 刃 ) CJK COMPATIBILITY IDEOGRAPH-2F81E → CJK UNIFIED IDEOGRAPH-5203 #
+
+FA00 ; 5207 ; MA # ( 切 → 切 ) CJK COMPATIBILITY IDEOGRAPH-FA00 → CJK UNIFIED IDEOGRAPH-5207 #
+2F850 ; 5207 ; MA # ( 切 → 切 ) CJK COMPATIBILITY IDEOGRAPH-2F850 → CJK UNIFIED IDEOGRAPH-5207 #
+
+F99C ; 5217 ; MA # ( 列 → 列 ) CJK COMPATIBILITY IDEOGRAPH-F99C → CJK UNIFIED IDEOGRAPH-5217 #
+
+F9DD ; 5229 ; MA # ( 利 → 利 ) CJK COMPATIBILITY IDEOGRAPH-F9DD → CJK UNIFIED IDEOGRAPH-5229 #
+
+2F81F ; 34DF ; MA # ( 㓟 → 㓟 ) CJK COMPATIBILITY IDEOGRAPH-2F81F → CJK UNIFIED IDEOGRAPH-34DF #
+
+F9FF ; 523A ; MA # ( 刺 → 刺 ) CJK COMPATIBILITY IDEOGRAPH-F9FF → CJK UNIFIED IDEOGRAPH-523A #
+
+2F820 ; 523B ; MA # ( 刻 → 刻 ) CJK COMPATIBILITY IDEOGRAPH-2F820 → CJK UNIFIED IDEOGRAPH-523B #
+
+2F821 ; 5246 ; MA # ( 剆 → 剆 ) CJK COMPATIBILITY IDEOGRAPH-2F821 → CJK UNIFIED IDEOGRAPH-5246 #
+
+2F822 ; 5272 ; MA # ( 割 → 割 ) CJK COMPATIBILITY IDEOGRAPH-2F822 → CJK UNIFIED IDEOGRAPH-5272 #
+
+2F823 ; 5277 ; MA # ( 剷 → 剷 ) CJK COMPATIBILITY IDEOGRAPH-2F823 → CJK UNIFIED IDEOGRAPH-5277 #
+
+F9C7 ; 5289 ; MA # ( 劉 → 劉 ) CJK COMPATIBILITY IDEOGRAPH-F9C7 → CJK UNIFIED IDEOGRAPH-5289 #
+
+2F9D9 ; 20804 ; MA # ( 𠠄 → 𠠄 ) CJK COMPATIBILITY IDEOGRAPH-2F9D9 → CJK UNIFIED IDEOGRAPH-20804 #
+
+30AB ; 529B ; MA # ( カ → 力 ) KATAKANA LETTER KA → CJK UNIFIED IDEOGRAPH-529B # →⼒→
+F98A ; 529B ; MA # ( 力 → 力 ) CJK COMPATIBILITY IDEOGRAPH-F98A → CJK UNIFIED IDEOGRAPH-529B #
+2F12 ; 529B ; MA #* ( ⼒ → 力 ) KANGXI RADICAL POWER → CJK UNIFIED IDEOGRAPH-529B #
+
+F99D ; 52A3 ; MA # ( 劣 → 劣 ) CJK COMPATIBILITY IDEOGRAPH-F99D → CJK UNIFIED IDEOGRAPH-52A3 #
+
+2F824 ; 3515 ; MA # ( 㔕 → 㔕 ) CJK COMPATIBILITY IDEOGRAPH-2F824 → CJK UNIFIED IDEOGRAPH-3515 #
+
+2F992 ; 52B3 ; MA # ( 劳 → 劳 ) CJK COMPATIBILITY IDEOGRAPH-2F992 → CJK UNIFIED IDEOGRAPH-52B3 #
+
+FA76 ; 52C7 ; MA # ( 勇 → 勇 ) CJK COMPATIBILITY IDEOGRAPH-FA76 → CJK UNIFIED IDEOGRAPH-52C7 #
+2F825 ; 52C7 ; MA # ( 勇 → 勇 ) CJK COMPATIBILITY IDEOGRAPH-2F825 → CJK UNIFIED IDEOGRAPH-52C7 #
+
+FA33 ; 52C9 ; MA # ( 勉 → 勉 ) CJK COMPATIBILITY IDEOGRAPH-FA33 → CJK UNIFIED IDEOGRAPH-52C9 #
+2F826 ; 52C9 ; MA # ( 勉 → 勉 ) CJK COMPATIBILITY IDEOGRAPH-2F826 → CJK UNIFIED IDEOGRAPH-52C9 #
+
+F952 ; 52D2 ; MA # ( 勒 → 勒 ) CJK COMPATIBILITY IDEOGRAPH-F952 → CJK UNIFIED IDEOGRAPH-52D2 #
+
+F92F ; 52DE ; MA # ( 勞 → 勞 ) CJK COMPATIBILITY IDEOGRAPH-F92F → CJK UNIFIED IDEOGRAPH-52DE #
+
+FA34 ; 52E4 ; MA # ( 勤 → 勤 ) CJK COMPATIBILITY IDEOGRAPH-FA34 → CJK UNIFIED IDEOGRAPH-52E4 #
+2F827 ; 52E4 ; MA # ( 勤 → 勤 ) CJK COMPATIBILITY IDEOGRAPH-2F827 → CJK UNIFIED IDEOGRAPH-52E4 #
+
+F97F ; 52F5 ; MA # ( 勵 → 勵 ) CJK COMPATIBILITY IDEOGRAPH-F97F → CJK UNIFIED IDEOGRAPH-52F5 #
+
+2F13 ; 52F9 ; MA #* ( ⼓ → 勹 ) KANGXI RADICAL WRAP → CJK UNIFIED IDEOGRAPH-52F9 #
+
+FA77 ; 52FA ; MA # ( 勺 → 勺 ) CJK COMPATIBILITY IDEOGRAPH-FA77 → CJK UNIFIED IDEOGRAPH-52FA #
+2F828 ; 52FA ; MA # ( 勺 → 勺 ) CJK COMPATIBILITY IDEOGRAPH-2F828 → CJK UNIFIED IDEOGRAPH-52FA #
+
+2F829 ; 5305 ; MA # ( 包 → 包 ) CJK COMPATIBILITY IDEOGRAPH-2F829 → CJK UNIFIED IDEOGRAPH-5305 #
+
+2F82A ; 5306 ; MA # ( 匆 → 匆 ) CJK COMPATIBILITY IDEOGRAPH-2F82A → CJK UNIFIED IDEOGRAPH-5306 #
+
+2F9DD ; 208DE ; MA # ( 𠣞 → 𠣞 ) CJK COMPATIBILITY IDEOGRAPH-2F9DD → CJK UNIFIED IDEOGRAPH-208DE #
+
+2F14 ; 5315 ; MA #* ( ⼔ → 匕 ) KANGXI RADICAL SPOON → CJK UNIFIED IDEOGRAPH-5315 #
+
+F963 ; 5317 ; MA # ( 北 → 北 ) CJK COMPATIBILITY IDEOGRAPH-F963 → CJK UNIFIED IDEOGRAPH-5317 #
+2F82B ; 5317 ; MA # ( 北 → 北 ) CJK COMPATIBILITY IDEOGRAPH-2F82B → CJK UNIFIED IDEOGRAPH-5317 #
+
+2F15 ; 531A ; MA #* ( ⼕ → 匚 ) KANGXI RADICAL RIGHT OPEN BOX → CJK UNIFIED IDEOGRAPH-531A #
+
+2F16 ; 5338 ; MA #* ( ⼖ → 匸 ) KANGXI RADICAL HIDING ENCLOSURE → CJK UNIFIED IDEOGRAPH-5338 #
+
+F9EB ; 533F ; MA # ( 匿 → 匿 ) CJK COMPATIBILITY IDEOGRAPH-F9EB → CJK UNIFIED IDEOGRAPH-533F #
+
+2F17 ; 5341 ; MA #* ( ⼗ → 十 ) KANGXI RADICAL TEN → CJK UNIFIED IDEOGRAPH-5341 #
+3038 ; 5341 ; MA # ( 〸 → 十 ) HANGZHOU NUMERAL TEN → CJK UNIFIED IDEOGRAPH-5341 #
+
+303A ; 5345 ; MA # ( 〺 → 卅 ) HANGZHOU NUMERAL THIRTY → CJK UNIFIED IDEOGRAPH-5345 #
+
+2F82C ; 5349 ; MA # ( 卉 → 卉 ) CJK COMPATIBILITY IDEOGRAPH-2F82C → CJK UNIFIED IDEOGRAPH-5349 #
+
+0FD6 ; 534D ; MA #* ( ࿖ → 卍 ) LEFT-FACING SVASTI SIGN → CJK UNIFIED IDEOGRAPH-534D #
+
+0FD5 ; 5350 ; MA #* ( ࿕ → 卐 ) RIGHT-FACING SVASTI SIGN → CJK UNIFIED IDEOGRAPH-5350 #
+
+FA35 ; 5351 ; MA # ( 卑 → 卑 ) CJK COMPATIBILITY IDEOGRAPH-FA35 → CJK UNIFIED IDEOGRAPH-5351 #
+2F82D ; 5351 ; MA # ( 卑 → 卑 ) CJK COMPATIBILITY IDEOGRAPH-2F82D → CJK UNIFIED IDEOGRAPH-5351 #
+
+2F82E ; 535A ; MA # ( 博 → 博 ) CJK COMPATIBILITY IDEOGRAPH-2F82E → CJK UNIFIED IDEOGRAPH-535A #
+
+30C8 ; 535C ; MA # ( ト → 卜 ) KATAKANA LETTER TO → CJK UNIFIED IDEOGRAPH-535C # →⼘→
+2F18 ; 535C ; MA #* ( ⼘ → 卜 ) KANGXI RADICAL DIVINATION → CJK UNIFIED IDEOGRAPH-535C #
+
+2F19 ; 5369 ; MA #* ( ⼙ → 卩 ) KANGXI RADICAL SEAL → CJK UNIFIED IDEOGRAPH-5369 #
+
+2E8B ; 353E ; MA #* ( ⺋ → 㔾 ) CJK RADICAL SEAL → CJK UNIFIED IDEOGRAPH-353E #
+
+2F82F ; 5373 ; MA # ( 即 → 即 ) CJK COMPATIBILITY IDEOGRAPH-2F82F → CJK UNIFIED IDEOGRAPH-5373 #
+
+F91C ; 5375 ; MA # ( 卵 → 卵 ) CJK COMPATIBILITY IDEOGRAPH-F91C → CJK UNIFIED IDEOGRAPH-5375 #
+
+2F830 ; 537D ; MA # ( 卽 → 卽 ) CJK COMPATIBILITY IDEOGRAPH-2F830 → CJK UNIFIED IDEOGRAPH-537D #
+
+2F831 ; 537F ; MA # ( 卿 → 卿 ) CJK COMPATIBILITY IDEOGRAPH-2F831 → CJK UNIFIED IDEOGRAPH-537F #
+2F832 ; 537F ; MA # ( 卿 → 卿 ) CJK COMPATIBILITY IDEOGRAPH-2F832 → CJK UNIFIED IDEOGRAPH-537F #
+2F833 ; 537F ; MA # ( 卿 → 卿 ) CJK COMPATIBILITY IDEOGRAPH-2F833 → CJK UNIFIED IDEOGRAPH-537F #
+
+2F1A ; 5382 ; MA #* ( ⼚ → 厂 ) KANGXI RADICAL CLIFF → CJK UNIFIED IDEOGRAPH-5382 #
+
+2F834 ; 20A2C ; MA # ( 𠨬 → 𠨬 ) CJK COMPATIBILITY IDEOGRAPH-2F834 → CJK UNIFIED IDEOGRAPH-20A2C #
+
+2F1B ; 53B6 ; MA #* ( ⼛ → 厶 ) KANGXI RADICAL PRIVATE → CJK UNIFIED IDEOGRAPH-53B6 #
+
+F96B ; 53C3 ; MA # ( 參 → 參 ) CJK COMPATIBILITY IDEOGRAPH-F96B → CJK UNIFIED IDEOGRAPH-53C3 #
+
+2F1C ; 53C8 ; MA #* ( ⼜ → 又 ) KANGXI RADICAL AGAIN → CJK UNIFIED IDEOGRAPH-53C8 #
+
+2F836 ; 53CA ; MA # ( 及 → 及 ) CJK COMPATIBILITY IDEOGRAPH-2F836 → CJK UNIFIED IDEOGRAPH-53CA #
+
+2F837 ; 53DF ; MA # ( 叟 → 叟 ) CJK COMPATIBILITY IDEOGRAPH-2F837 → CJK UNIFIED IDEOGRAPH-53DF #
+
+2F838 ; 20B63 ; MA # ( 𠭣 → 𠭣 ) CJK COMPATIBILITY IDEOGRAPH-2F838 → CJK UNIFIED IDEOGRAPH-20B63 #
+
+30ED ; 53E3 ; MA # ( ロ → 口 ) KATAKANA LETTER RO → CJK UNIFIED IDEOGRAPH-53E3 # →⼞→→⼝→
+2F1D ; 53E3 ; MA #* ( ⼝ → 口 ) KANGXI RADICAL MOUTH → CJK UNIFIED IDEOGRAPH-53E3 #
+56D7 ; 53E3 ; MA # ( 囗 → 口 ) CJK UNIFIED IDEOGRAPH-56D7 → CJK UNIFIED IDEOGRAPH-53E3 # →⼞→→⼝→
+2F1E ; 53E3 ; MA #* ( ⼞ → 口 ) KANGXI RADICAL ENCLOSURE → CJK UNIFIED IDEOGRAPH-53E3 # →⼝→
+
+F906 ; 53E5 ; MA # ( 句 → 句 ) CJK COMPATIBILITY IDEOGRAPH-F906 → CJK UNIFIED IDEOGRAPH-53E5 #
+
+2F839 ; 53EB ; MA # ( 叫 → 叫 ) CJK COMPATIBILITY IDEOGRAPH-2F839 → CJK UNIFIED IDEOGRAPH-53EB #
+
+2F83A ; 53F1 ; MA # ( 叱 → 叱 ) CJK COMPATIBILITY IDEOGRAPH-2F83A → CJK UNIFIED IDEOGRAPH-53F1 #
+
+2F83B ; 5406 ; MA # ( 吆 → 吆 ) CJK COMPATIBILITY IDEOGRAPH-2F83B → CJK UNIFIED IDEOGRAPH-5406 #
+
+F9DE ; 540F ; MA # ( 吏 → 吏 ) CJK COMPATIBILITY IDEOGRAPH-F9DE → CJK UNIFIED IDEOGRAPH-540F #
+
+F9ED ; 541D ; MA # ( 吝 → 吝 ) CJK COMPATIBILITY IDEOGRAPH-F9ED → CJK UNIFIED IDEOGRAPH-541D #
+
+2F83D ; 5438 ; MA # ( 吸 → 吸 ) CJK COMPATIBILITY IDEOGRAPH-2F83D → CJK UNIFIED IDEOGRAPH-5438 #
+
+F980 ; 5442 ; MA # ( 呂 → 呂 ) CJK COMPATIBILITY IDEOGRAPH-F980 → CJK UNIFIED IDEOGRAPH-5442 #
+
+2F83E ; 5448 ; MA # ( 呈 → 呈 ) CJK COMPATIBILITY IDEOGRAPH-2F83E → CJK UNIFIED IDEOGRAPH-5448 #
+
+2F83F ; 5468 ; MA # ( 周 → 周 ) CJK COMPATIBILITY IDEOGRAPH-2F83F → CJK UNIFIED IDEOGRAPH-5468 #
+
+2F83C ; 549E ; MA # ( 咞 → 咞 ) CJK COMPATIBILITY IDEOGRAPH-2F83C → CJK UNIFIED IDEOGRAPH-549E #
+
+2F840 ; 54A2 ; MA # ( 咢 → 咢 ) CJK COMPATIBILITY IDEOGRAPH-2F840 → CJK UNIFIED IDEOGRAPH-54A2 #
+
+F99E ; 54BD ; MA # ( 咽 → 咽 ) CJK COMPATIBILITY IDEOGRAPH-F99E → CJK UNIFIED IDEOGRAPH-54BD #
+
+439B ; 3588 ; MA # ( 䎛 → 㖈 ) CJK UNIFIED IDEOGRAPH-439B → CJK UNIFIED IDEOGRAPH-3588 #
+
+2F841 ; 54F6 ; MA # ( 哶 → 哶 ) CJK COMPATIBILITY IDEOGRAPH-2F841 → CJK UNIFIED IDEOGRAPH-54F6 #
+
+2F842 ; 5510 ; MA # ( 唐 → 唐 ) CJK COMPATIBILITY IDEOGRAPH-2F842 → CJK UNIFIED IDEOGRAPH-5510 #
+
+2F843 ; 5553 ; MA # ( 啓 → 啓 ) CJK COMPATIBILITY IDEOGRAPH-2F843 → CJK UNIFIED IDEOGRAPH-5553 #
+555F ; 5553 ; MA # ( 啟 → 啓 ) CJK UNIFIED IDEOGRAPH-555F → CJK UNIFIED IDEOGRAPH-5553 #
+
+FA79 ; 5555 ; MA # ( 啕 → 啕 ) CJK COMPATIBILITY IDEOGRAPH-FA79 → CJK UNIFIED IDEOGRAPH-5555 #
+
+2F844 ; 5563 ; MA # ( 啣 → 啣 ) CJK COMPATIBILITY IDEOGRAPH-2F844 → CJK UNIFIED IDEOGRAPH-5563 #
+
+2F845 ; 5584 ; MA # ( 善 → 善 ) CJK COMPATIBILITY IDEOGRAPH-2F845 → CJK UNIFIED IDEOGRAPH-5584 #
+2F846 ; 5584 ; MA # ( 善 → 善 ) CJK COMPATIBILITY IDEOGRAPH-2F846 → CJK UNIFIED IDEOGRAPH-5584 #
+
+F90B ; 5587 ; MA # ( 喇 → 喇 ) CJK COMPATIBILITY IDEOGRAPH-F90B → CJK UNIFIED IDEOGRAPH-5587 #
+
+FA7A ; 5599 ; MA # ( 喙 → 喙 ) CJK COMPATIBILITY IDEOGRAPH-FA7A → CJK UNIFIED IDEOGRAPH-5599 #
+2F847 ; 5599 ; MA # ( 喙 → 喙 ) CJK COMPATIBILITY IDEOGRAPH-2F847 → CJK UNIFIED IDEOGRAPH-5599 #
+
+FA36 ; 559D ; MA # ( 喝 → 喝 ) CJK COMPATIBILITY IDEOGRAPH-FA36 → CJK UNIFIED IDEOGRAPH-559D #
+FA78 ; 559D ; MA # ( 喝 → 喝 ) CJK COMPATIBILITY IDEOGRAPH-FA78 → CJK UNIFIED IDEOGRAPH-559D #
+
+2F848 ; 55AB ; MA # ( 喫 → 喫 ) CJK COMPATIBILITY IDEOGRAPH-2F848 → CJK UNIFIED IDEOGRAPH-55AB #
+
+2F849 ; 55B3 ; MA # ( 喳 → 喳 ) CJK COMPATIBILITY IDEOGRAPH-2F849 → CJK UNIFIED IDEOGRAPH-55B3 #
+
+FA0D ; 55C0 ; MA # ( 嗀 → 嗀 ) CJK COMPATIBILITY IDEOGRAPH-FA0D → CJK UNIFIED IDEOGRAPH-55C0 #
+
+2F84A ; 55C2 ; MA # ( 嗂 → 嗂 ) CJK COMPATIBILITY IDEOGRAPH-2F84A → CJK UNIFIED IDEOGRAPH-55C2 #
+
+FA7B ; 55E2 ; MA # ( 嗢 → 嗢 ) CJK COMPATIBILITY IDEOGRAPH-FA7B → CJK UNIFIED IDEOGRAPH-55E2 #
+
+FA37 ; 5606 ; MA # ( 嘆 → 嘆 ) CJK COMPATIBILITY IDEOGRAPH-FA37 → CJK UNIFIED IDEOGRAPH-5606 #
+2F84C ; 5606 ; MA # ( 嘆 → 嘆 ) CJK COMPATIBILITY IDEOGRAPH-2F84C → CJK UNIFIED IDEOGRAPH-5606 #
+
+2F84E ; 5651 ; MA # ( 噑 → 噑 ) CJK COMPATIBILITY IDEOGRAPH-2F84E → CJK UNIFIED IDEOGRAPH-5651 #
+
+2F84F ; 5674 ; MA # ( 噴 → 噴 ) CJK COMPATIBILITY IDEOGRAPH-2F84F → CJK UNIFIED IDEOGRAPH-5674 #
+
+FA38 ; 5668 ; MA # ( 器 → 器 ) CJK COMPATIBILITY IDEOGRAPH-FA38 → CJK UNIFIED IDEOGRAPH-5668 #
+
+F9A9 ; 56F9 ; MA # ( 囹 → 囹 ) CJK COMPATIBILITY IDEOGRAPH-F9A9 → CJK UNIFIED IDEOGRAPH-56F9 #
+
+2F84B ; 5716 ; MA # ( 圖 → 圖 ) CJK COMPATIBILITY IDEOGRAPH-2F84B → CJK UNIFIED IDEOGRAPH-5716 #
+
+2F84D ; 5717 ; MA # ( 圗 → 圗 ) CJK COMPATIBILITY IDEOGRAPH-2F84D → CJK UNIFIED IDEOGRAPH-5717 #
+
+2F1F ; 571F ; MA #* ( ⼟ → 土 ) KANGXI RADICAL EARTH → CJK UNIFIED IDEOGRAPH-571F #
+58EB ; 571F ; MA # ( 士 → 土 ) CJK UNIFIED IDEOGRAPH-58EB → CJK UNIFIED IDEOGRAPH-571F # →⼠→→⼟→
+2F20 ; 571F ; MA #* ( ⼠ → 土 ) KANGXI RADICAL SCHOLAR → CJK UNIFIED IDEOGRAPH-571F # →⼟→
+
+2F855 ; 578B ; MA # ( 型 → 型 ) CJK COMPATIBILITY IDEOGRAPH-2F855 → CJK UNIFIED IDEOGRAPH-578B #
+
+2F852 ; 57CE ; MA # ( 城 → 城 ) CJK COMPATIBILITY IDEOGRAPH-2F852 → CJK UNIFIED IDEOGRAPH-57CE #
+
+39B3 ; 363D ; MA # ( 㦳 → 㘽 ) CJK UNIFIED IDEOGRAPH-39B3 → CJK UNIFIED IDEOGRAPH-363D #
+
+2F853 ; 57F4 ; MA # ( 埴 → 埴 ) CJK COMPATIBILITY IDEOGRAPH-2F853 → CJK UNIFIED IDEOGRAPH-57F4 #
+
+2F854 ; 580D ; MA # ( 堍 → 堍 ) CJK COMPATIBILITY IDEOGRAPH-2F854 → CJK UNIFIED IDEOGRAPH-580D #
+
+2F857 ; 5831 ; MA # ( 報 → 報 ) CJK COMPATIBILITY IDEOGRAPH-2F857 → CJK UNIFIED IDEOGRAPH-5831 #
+
+2F856 ; 5832 ; MA # ( 堲 → 堲 ) CJK COMPATIBILITY IDEOGRAPH-2F856 → CJK UNIFIED IDEOGRAPH-5832 #
+
+FA39 ; 5840 ; MA # ( 塀 → 塀 ) CJK COMPATIBILITY IDEOGRAPH-FA39 → CJK UNIFIED IDEOGRAPH-5840 #
+
+FA10 ; 585A ; MA # ( 塚 → 塚 ) CJK COMPATIBILITY IDEOGRAPH-FA10 → CJK UNIFIED IDEOGRAPH-585A #
+FA7C ; 585A ; MA # ( 塚 → 塚 ) CJK COMPATIBILITY IDEOGRAPH-FA7C → CJK UNIFIED IDEOGRAPH-585A #
+
+F96C ; 585E ; MA # ( 塞 → 塞 ) CJK COMPATIBILITY IDEOGRAPH-F96C → CJK UNIFIED IDEOGRAPH-585E #
+
+586B ; 5861 ; MA # ( 填 → 塡 ) CJK UNIFIED IDEOGRAPH-586B → CJK UNIFIED IDEOGRAPH-5861 #
+
+58FF ; 58AB ; MA # ( 壿 → 墫 ) CJK UNIFIED IDEOGRAPH-58FF → CJK UNIFIED IDEOGRAPH-58AB #
+
+2F858 ; 58AC ; MA # ( 墬 → 墬 ) CJK COMPATIBILITY IDEOGRAPH-2F858 → CJK UNIFIED IDEOGRAPH-58AC #
+
+FA7D ; 58B3 ; MA # ( 墳 → 墳 ) CJK COMPATIBILITY IDEOGRAPH-FA7D → CJK UNIFIED IDEOGRAPH-58B3 #
+
+F94A ; 58D8 ; MA # ( 壘 → 壘 ) CJK COMPATIBILITY IDEOGRAPH-F94A → CJK UNIFIED IDEOGRAPH-58D8 #
+
+F942 ; 58DF ; MA # ( 壟 → 壟 ) CJK COMPATIBILITY IDEOGRAPH-F942 → CJK UNIFIED IDEOGRAPH-58DF #
+
+2F859 ; 214E4 ; MA # ( 𡓤 → 𡓤 ) CJK COMPATIBILITY IDEOGRAPH-2F859 → CJK UNIFIED IDEOGRAPH-214E4 #
+
+2F851 ; 58EE ; MA # ( 壮 → 壮 ) CJK COMPATIBILITY IDEOGRAPH-2F851 → CJK UNIFIED IDEOGRAPH-58EE #
+
+2F85A ; 58F2 ; MA # ( 売 → 売 ) CJK COMPATIBILITY IDEOGRAPH-2F85A → CJK UNIFIED IDEOGRAPH-58F2 #
+
+2F85B ; 58F7 ; MA # ( 壷 → 壷 ) CJK COMPATIBILITY IDEOGRAPH-2F85B → CJK UNIFIED IDEOGRAPH-58F7 #
+
+2F21 ; 5902 ; MA #* ( ⼡ → 夂 ) KANGXI RADICAL GO → CJK UNIFIED IDEOGRAPH-5902 #
+
+2F85C ; 5906 ; MA # ( 夆 → 夆 ) CJK COMPATIBILITY IDEOGRAPH-2F85C → CJK UNIFIED IDEOGRAPH-5906 #
+
+2F22 ; 590A ; MA #* ( ⼢ → 夊 ) KANGXI RADICAL GO SLOWLY → CJK UNIFIED IDEOGRAPH-590A #
+
+30BF ; 5915 ; MA # ( タ → 夕 ) KATAKANA LETTER TA → CJK UNIFIED IDEOGRAPH-5915 # →⼣→
+2F23 ; 5915 ; MA #* ( ⼣ → 夕 ) KANGXI RADICAL EVENING → CJK UNIFIED IDEOGRAPH-5915 #
+
+2F85D ; 591A ; MA # ( 多 → 多 ) CJK COMPATIBILITY IDEOGRAPH-2F85D → CJK UNIFIED IDEOGRAPH-591A #
+
+2F85E ; 5922 ; MA # ( 夢 → 夢 ) CJK COMPATIBILITY IDEOGRAPH-2F85E → CJK UNIFIED IDEOGRAPH-5922 #
+
+2F24 ; 5927 ; MA #* ( ⼤ → 大 ) KANGXI RADICAL BIG → CJK UNIFIED IDEOGRAPH-5927 #
+
+FA7E ; 5944 ; MA # ( 奄 → 奄 ) CJK COMPATIBILITY IDEOGRAPH-FA7E → CJK UNIFIED IDEOGRAPH-5944 #
+
+F90C ; 5948 ; MA # ( 奈 → 奈 ) CJK COMPATIBILITY IDEOGRAPH-F90C → CJK UNIFIED IDEOGRAPH-5948 #
+
+F909 ; 5951 ; MA # ( 契 → 契 ) CJK COMPATIBILITY IDEOGRAPH-F909 → CJK UNIFIED IDEOGRAPH-5951 #
+
+FA7F ; 5954 ; MA # ( 奔 → 奔 ) CJK COMPATIBILITY IDEOGRAPH-FA7F → CJK UNIFIED IDEOGRAPH-5954 #
+
+2F85F ; 5962 ; MA # ( 奢 → 奢 ) CJK COMPATIBILITY IDEOGRAPH-2F85F → CJK UNIFIED IDEOGRAPH-5962 #
+
+F981 ; 5973 ; MA # ( 女 → 女 ) CJK COMPATIBILITY IDEOGRAPH-F981 → CJK UNIFIED IDEOGRAPH-5973 #
+2F25 ; 5973 ; MA #* ( ⼥ → 女 ) KANGXI RADICAL WOMAN → CJK UNIFIED IDEOGRAPH-5973 #
+
+2F860 ; 216A8 ; MA # ( 𡚨 → 𡚨 ) CJK COMPATIBILITY IDEOGRAPH-2F860 → CJK UNIFIED IDEOGRAPH-216A8 #
+
+2F861 ; 216EA ; MA # ( 𡛪 → 𡛪 ) CJK COMPATIBILITY IDEOGRAPH-2F861 → CJK UNIFIED IDEOGRAPH-216EA #
+
+2F865 ; 59D8 ; MA # ( 姘 → 姘 ) CJK COMPATIBILITY IDEOGRAPH-2F865 → CJK UNIFIED IDEOGRAPH-59D8 #
+
+2F862 ; 59EC ; MA # ( 姬 → 姬 ) CJK COMPATIBILITY IDEOGRAPH-2F862 → CJK UNIFIED IDEOGRAPH-59EC #
+
+2F863 ; 5A1B ; MA # ( 娛 → 娛 ) CJK COMPATIBILITY IDEOGRAPH-2F863 → CJK UNIFIED IDEOGRAPH-5A1B #
+
+2F864 ; 5A27 ; MA # ( 娧 → 娧 ) CJK COMPATIBILITY IDEOGRAPH-2F864 → CJK UNIFIED IDEOGRAPH-5A27 #
+
+FA80 ; 5A62 ; MA # ( 婢 → 婢 ) CJK COMPATIBILITY IDEOGRAPH-FA80 → CJK UNIFIED IDEOGRAPH-5A62 #
+
+2F866 ; 5A66 ; MA # ( 婦 → 婦 ) CJK COMPATIBILITY IDEOGRAPH-2F866 → CJK UNIFIED IDEOGRAPH-5A66 #
+
+5B00 ; 5AAF ; MA # ( 嬀 → 媯 ) CJK UNIFIED IDEOGRAPH-5B00 → CJK UNIFIED IDEOGRAPH-5AAF #
+
+2F867 ; 36EE ; MA # ( 㛮 → 㛮 ) CJK COMPATIBILITY IDEOGRAPH-2F867 → CJK UNIFIED IDEOGRAPH-36EE #
+
+2F868 ; 36FC ; MA # ( 㛼 → 㛼 ) CJK COMPATIBILITY IDEOGRAPH-2F868 → CJK UNIFIED IDEOGRAPH-36FC #
+
+2F986 ; 5AB5 ; MA # ( 媵 → 媵 ) CJK COMPATIBILITY IDEOGRAPH-2F986 → CJK UNIFIED IDEOGRAPH-5AB5 #
+
+2F869 ; 5B08 ; MA # ( 嬈 → 嬈 ) CJK COMPATIBILITY IDEOGRAPH-2F869 → CJK UNIFIED IDEOGRAPH-5B08 #
+
+FA81 ; 5B28 ; MA # ( 嬨 → 嬨 ) CJK COMPATIBILITY IDEOGRAPH-FA81 → CJK UNIFIED IDEOGRAPH-5B28 #
+
+2F86A ; 5B3E ; MA # ( 嬾 → 嬾 ) CJK COMPATIBILITY IDEOGRAPH-2F86A → CJK UNIFIED IDEOGRAPH-5B3E #
+2F86B ; 5B3E ; MA # ( 嬾 → 嬾 ) CJK COMPATIBILITY IDEOGRAPH-2F86B → CJK UNIFIED IDEOGRAPH-5B3E #
+
+2F26 ; 5B50 ; MA #* ( ⼦ → 子 ) KANGXI RADICAL CHILD → CJK UNIFIED IDEOGRAPH-5B50 #
+
+2F27 ; 5B80 ; MA #* ( ⼧ → 宀 ) KANGXI RADICAL ROOF → CJK UNIFIED IDEOGRAPH-5B80 #
+
+FA04 ; 5B85 ; MA # ( 宅 → 宅 ) CJK COMPATIBILITY IDEOGRAPH-FA04 → CJK UNIFIED IDEOGRAPH-5B85 #
+
+2F86C ; 219C8 ; MA # ( 𡧈 → 𡧈 ) CJK COMPATIBILITY IDEOGRAPH-2F86C → CJK UNIFIED IDEOGRAPH-219C8 #
+
+2F86D ; 5BC3 ; MA # ( 寃 → 寃 ) CJK COMPATIBILITY IDEOGRAPH-2F86D → CJK UNIFIED IDEOGRAPH-5BC3 #
+
+2F86E ; 5BD8 ; MA # ( 寘 → 寘 ) CJK COMPATIBILITY IDEOGRAPH-2F86E → CJK UNIFIED IDEOGRAPH-5BD8 #
+
+F95F ; 5BE7 ; MA # ( 寧 → 寧 ) CJK COMPATIBILITY IDEOGRAPH-F95F → CJK UNIFIED IDEOGRAPH-5BE7 #
+F9AA ; 5BE7 ; MA # ( 寧 → 寧 ) CJK COMPATIBILITY IDEOGRAPH-F9AA → CJK UNIFIED IDEOGRAPH-5BE7 #
+2F86F ; 5BE7 ; MA # ( 寧 → 寧 ) CJK COMPATIBILITY IDEOGRAPH-2F86F → CJK UNIFIED IDEOGRAPH-5BE7 #
+
+F9BC ; 5BEE ; MA # ( 寮 → 寮 ) CJK COMPATIBILITY IDEOGRAPH-F9BC → CJK UNIFIED IDEOGRAPH-5BEE #
+
+2F870 ; 5BF3 ; MA # ( 寳 → 寳 ) CJK COMPATIBILITY IDEOGRAPH-2F870 → CJK UNIFIED IDEOGRAPH-5BF3 #
+
+2F871 ; 21B18 ; MA # ( 𡬘 → 𡬘 ) CJK COMPATIBILITY IDEOGRAPH-2F871 → CJK UNIFIED IDEOGRAPH-21B18 #
+
+2F28 ; 5BF8 ; MA #* ( ⼨ → 寸 ) KANGXI RADICAL INCH → CJK UNIFIED IDEOGRAPH-5BF8 #
+
+2F872 ; 5BFF ; MA # ( 寿 → 寿 ) CJK COMPATIBILITY IDEOGRAPH-2F872 → CJK UNIFIED IDEOGRAPH-5BFF #
+
+2F873 ; 5C06 ; MA # ( 将 → 将 ) CJK COMPATIBILITY IDEOGRAPH-2F873 → CJK UNIFIED IDEOGRAPH-5C06 #
+
+2F29 ; 5C0F ; MA #* ( ⼩ → 小 ) KANGXI RADICAL SMALL → CJK UNIFIED IDEOGRAPH-5C0F #
+
+2F875 ; 5C22 ; MA # ( 尢 → 尢 ) CJK COMPATIBILITY IDEOGRAPH-2F875 → CJK UNIFIED IDEOGRAPH-5C22 #
+2E90 ; 5C22 ; MA #* ( ⺐ → 尢 ) CJK RADICAL LAME THREE → CJK UNIFIED IDEOGRAPH-5C22 #
+2F2A ; 5C22 ; MA #* ( ⼪ → 尢 ) KANGXI RADICAL LAME → CJK UNIFIED IDEOGRAPH-5C22 #
+
+2E8F ; 5C23 ; MA #* ( ⺏ → 尣 ) CJK RADICAL LAME TWO → CJK UNIFIED IDEOGRAPH-5C23 #
+
+2F876 ; 3781 ; MA # ( 㞁 → 㞁 ) CJK COMPATIBILITY IDEOGRAPH-2F876 → CJK UNIFIED IDEOGRAPH-3781 #
+
+2F2B ; 5C38 ; MA #* ( ⼫ → 尸 ) KANGXI RADICAL CORPSE → CJK UNIFIED IDEOGRAPH-5C38 #
+
+F9BD ; 5C3F ; MA # ( 尿 → 尿 ) CJK COMPATIBILITY IDEOGRAPH-F9BD → CJK UNIFIED IDEOGRAPH-5C3F #
+
+2F877 ; 5C60 ; MA # ( 屠 → 屠 ) CJK COMPATIBILITY IDEOGRAPH-2F877 → CJK UNIFIED IDEOGRAPH-5C60 #
+
+F94B ; 5C62 ; MA # ( 屢 → 屢 ) CJK COMPATIBILITY IDEOGRAPH-F94B → CJK UNIFIED IDEOGRAPH-5C62 #
+
+FA3B ; 5C64 ; MA # ( 層 → 層 ) CJK COMPATIBILITY IDEOGRAPH-FA3B → CJK UNIFIED IDEOGRAPH-5C64 #
+
+F9DF ; 5C65 ; MA # ( 履 → 履 ) CJK COMPATIBILITY IDEOGRAPH-F9DF → CJK UNIFIED IDEOGRAPH-5C65 #
+
+FA3C ; 5C6E ; MA # ( 屮 → 屮 ) CJK COMPATIBILITY IDEOGRAPH-FA3C → CJK UNIFIED IDEOGRAPH-5C6E #
+2F878 ; 5C6E ; MA # ( 屮 → 屮 ) CJK COMPATIBILITY IDEOGRAPH-2F878 → CJK UNIFIED IDEOGRAPH-5C6E #
+2F2C ; 5C6E ; MA #* ( ⼬ → 屮 ) KANGXI RADICAL SPROUT → CJK UNIFIED IDEOGRAPH-5C6E #
+
+2F8F8 ; 21D0B ; MA # ( 𡴋 → 𡴋 ) CJK COMPATIBILITY IDEOGRAPH-2F8F8 → CJK UNIFIED IDEOGRAPH-21D0B #
+
+2F2D ; 5C71 ; MA #* ( ⼭ → 山 ) KANGXI RADICAL MOUNTAIN → CJK UNIFIED IDEOGRAPH-5C71 #
+
+2F879 ; 5CC0 ; MA # ( 峀 → 峀 ) CJK COMPATIBILITY IDEOGRAPH-2F879 → CJK UNIFIED IDEOGRAPH-5CC0 #
+
+2F87A ; 5C8D ; MA # ( 岍 → 岍 ) CJK COMPATIBILITY IDEOGRAPH-2F87A → CJK UNIFIED IDEOGRAPH-5C8D #
+
+2F87B ; 21DE4 ; MA # ( 𡷤 → 𡷤 ) CJK COMPATIBILITY IDEOGRAPH-2F87B → CJK UNIFIED IDEOGRAPH-21DE4 #
+
+2F87D ; 21DE6 ; MA # ( 𡷦 → 𡷦 ) CJK COMPATIBILITY IDEOGRAPH-2F87D → CJK UNIFIED IDEOGRAPH-21DE6 #
+
+F9D5 ; 5D19 ; MA # ( 崙 → 崙 ) CJK COMPATIBILITY IDEOGRAPH-F9D5 → CJK UNIFIED IDEOGRAPH-5D19 #
+
+2F87C ; 5D43 ; MA # ( 嵃 → 嵃 ) CJK COMPATIBILITY IDEOGRAPH-2F87C → CJK UNIFIED IDEOGRAPH-5D43 #
+
+F921 ; 5D50 ; MA # ( 嵐 → 嵐 ) CJK COMPATIBILITY IDEOGRAPH-F921 → CJK UNIFIED IDEOGRAPH-5D50 #
+
+2F87F ; 5D6B ; MA # ( 嵫 → 嵫 ) CJK COMPATIBILITY IDEOGRAPH-2F87F → CJK UNIFIED IDEOGRAPH-5D6B #
+
+2F87E ; 5D6E ; MA # ( 嵮 → 嵮 ) CJK COMPATIBILITY IDEOGRAPH-2F87E → CJK UNIFIED IDEOGRAPH-5D6E #
+
+2F880 ; 5D7C ; MA # ( 嵼 → 嵼 ) CJK COMPATIBILITY IDEOGRAPH-2F880 → CJK UNIFIED IDEOGRAPH-5D7C #
+
+2F9F4 ; 5DB2 ; MA # ( 嶲 → 嶲 ) CJK COMPATIBILITY IDEOGRAPH-2F9F4 → CJK UNIFIED IDEOGRAPH-5DB2 #
+
+F9AB ; 5DBA ; MA # ( 嶺 → 嶺 ) CJK COMPATIBILITY IDEOGRAPH-F9AB → CJK UNIFIED IDEOGRAPH-5DBA #
+
+2F2E ; 5DDB ; MA #* ( ⼮ → 巛 ) KANGXI RADICAL RIVER → CJK UNIFIED IDEOGRAPH-5DDB #
+
+2F882 ; 5DE2 ; MA # ( 巢 → 巢 ) CJK COMPATIBILITY IDEOGRAPH-2F882 → CJK UNIFIED IDEOGRAPH-5DE2 #
+
+30A8 ; 5DE5 ; MA # ( エ → 工 ) KATAKANA LETTER E → CJK UNIFIED IDEOGRAPH-5DE5 # →⼯→
+2F2F ; 5DE5 ; MA #* ( ⼯ → 工 ) KANGXI RADICAL WORK → CJK UNIFIED IDEOGRAPH-5DE5 #
+
+2F30 ; 5DF1 ; MA #* ( ⼰ → 己 ) KANGXI RADICAL ONESELF → CJK UNIFIED IDEOGRAPH-5DF1 #
+
+2E92 ; 5DF3 ; MA #* ( ⺒ → 巳 ) CJK RADICAL SNAKE → CJK UNIFIED IDEOGRAPH-5DF3 #
+
+2F883 ; 382F ; MA # ( 㠯 → 㠯 ) CJK COMPATIBILITY IDEOGRAPH-2F883 → CJK UNIFIED IDEOGRAPH-382F #
+
+2F884 ; 5DFD ; MA # ( 巽 → 巽 ) CJK COMPATIBILITY IDEOGRAPH-2F884 → CJK UNIFIED IDEOGRAPH-5DFD #
+
+2F31 ; 5DFE ; MA #* ( ⼱ → 巾 ) KANGXI RADICAL TURBAN → CJK UNIFIED IDEOGRAPH-5DFE #
+
+5E32 ; 5E21 ; MA # ( 帲 → 帡 ) CJK UNIFIED IDEOGRAPH-5E32 → CJK UNIFIED IDEOGRAPH-5E21 #
+
+2F885 ; 5E28 ; MA # ( 帨 → 帨 ) CJK COMPATIBILITY IDEOGRAPH-2F885 → CJK UNIFIED IDEOGRAPH-5E28 #
+
+2F886 ; 5E3D ; MA # ( 帽 → 帽 ) CJK COMPATIBILITY IDEOGRAPH-2F886 → CJK UNIFIED IDEOGRAPH-5E3D #
+
+2F887 ; 5E69 ; MA # ( 幩 → 幩 ) CJK COMPATIBILITY IDEOGRAPH-2F887 → CJK UNIFIED IDEOGRAPH-5E69 #
+
+2F888 ; 3862 ; MA # ( 㡢 → 㡢 ) CJK COMPATIBILITY IDEOGRAPH-2F888 → CJK UNIFIED IDEOGRAPH-3862 #
+
+2F889 ; 22183 ; MA # ( 𢆃 → 𢆃 ) CJK COMPATIBILITY IDEOGRAPH-2F889 → CJK UNIFIED IDEOGRAPH-22183 #
+
+2F32 ; 5E72 ; MA #* ( ⼲ → 干 ) KANGXI RADICAL DRY → CJK UNIFIED IDEOGRAPH-5E72 #
+
+F98E ; 5E74 ; MA # ( 年 → 年 ) CJK COMPATIBILITY IDEOGRAPH-F98E → CJK UNIFIED IDEOGRAPH-5E74 #
+
+2F939 ; 2219F ; MA # ( 𢆟 → 𢆟 ) CJK COMPATIBILITY IDEOGRAPH-2F939 → CJK UNIFIED IDEOGRAPH-2219F #
+
+2E93 ; 5E7A ; MA #* ( ⺓ → 幺 ) CJK RADICAL THREAD → CJK UNIFIED IDEOGRAPH-5E7A #
+2F33 ; 5E7A ; MA #* ( ⼳ → 幺 ) KANGXI RADICAL SHORT THREAD → CJK UNIFIED IDEOGRAPH-5E7A #
+
+2F34 ; 5E7F ; MA #* ( ⼴ → 广 ) KANGXI RADICAL DOTTED CLIFF → CJK UNIFIED IDEOGRAPH-5E7F #
+
+FA01 ; 5EA6 ; MA # ( 度 → 度 ) CJK COMPATIBILITY IDEOGRAPH-FA01 → CJK UNIFIED IDEOGRAPH-5EA6 #
+
+2F88A ; 387C ; MA # ( 㡼 → 㡼 ) CJK COMPATIBILITY IDEOGRAPH-2F88A → CJK UNIFIED IDEOGRAPH-387C #
+
+2F88B ; 5EB0 ; MA # ( 庰 → 庰 ) CJK COMPATIBILITY IDEOGRAPH-2F88B → CJK UNIFIED IDEOGRAPH-5EB0 #
+
+2F88C ; 5EB3 ; MA # ( 庳 → 庳 ) CJK COMPATIBILITY IDEOGRAPH-2F88C → CJK UNIFIED IDEOGRAPH-5EB3 #
+
+2F88D ; 5EB6 ; MA # ( 庶 → 庶 ) CJK COMPATIBILITY IDEOGRAPH-2F88D → CJK UNIFIED IDEOGRAPH-5EB6 #
+
+F928 ; 5ECA ; MA # ( 廊 → 廊 ) CJK COMPATIBILITY IDEOGRAPH-F928 → CJK UNIFIED IDEOGRAPH-5ECA #
+2F88E ; 5ECA ; MA # ( 廊 → 廊 ) CJK COMPATIBILITY IDEOGRAPH-2F88E → CJK UNIFIED IDEOGRAPH-5ECA #
+
+F9A2 ; 5EC9 ; MA # ( 廉 → 廉 ) CJK COMPATIBILITY IDEOGRAPH-F9A2 → CJK UNIFIED IDEOGRAPH-5EC9 #
+
+FA82 ; 5ED2 ; MA # ( 廒 → 廒 ) CJK COMPATIBILITY IDEOGRAPH-FA82 → CJK UNIFIED IDEOGRAPH-5ED2 #
+
+FA0B ; 5ED3 ; MA # ( 廓 → 廓 ) CJK COMPATIBILITY IDEOGRAPH-FA0B → CJK UNIFIED IDEOGRAPH-5ED3 #
+
+FA83 ; 5ED9 ; MA # ( 廙 → 廙 ) CJK COMPATIBILITY IDEOGRAPH-FA83 → CJK UNIFIED IDEOGRAPH-5ED9 #
+
+F982 ; 5EEC ; MA # ( 廬 → 廬 ) CJK COMPATIBILITY IDEOGRAPH-F982 → CJK UNIFIED IDEOGRAPH-5EEC #
+
+2F35 ; 5EF4 ; MA #* ( ⼵ → 廴 ) KANGXI RADICAL LONG STRIDE → CJK UNIFIED IDEOGRAPH-5EF4 #
+
+2F890 ; 5EFE ; MA # ( 廾 → 廾 ) CJK COMPATIBILITY IDEOGRAPH-2F890 → CJK UNIFIED IDEOGRAPH-5EFE #
+2F36 ; 5EFE ; MA #* ( ⼶ → 廾 ) KANGXI RADICAL TWO HANDS → CJK UNIFIED IDEOGRAPH-5EFE #
+
+2F891 ; 22331 ; MA # ( 𢌱 → 𢌱 ) CJK COMPATIBILITY IDEOGRAPH-2F891 → CJK UNIFIED IDEOGRAPH-22331 #
+2F892 ; 22331 ; MA # ( 𢌱 → 𢌱 ) CJK COMPATIBILITY IDEOGRAPH-2F892 → CJK UNIFIED IDEOGRAPH-22331 #
+
+F943 ; 5F04 ; MA # ( 弄 → 弄 ) CJK COMPATIBILITY IDEOGRAPH-F943 → CJK UNIFIED IDEOGRAPH-5F04 #
+
+2F37 ; 5F0B ; MA #* ( ⼷ → 弋 ) KANGXI RADICAL SHOOT → CJK UNIFIED IDEOGRAPH-5F0B #
+
+2F38 ; 5F13 ; MA #* ( ⼸ → 弓 ) KANGXI RADICAL BOW → CJK UNIFIED IDEOGRAPH-5F13 #
+
+2F894 ; 5F22 ; MA # ( 弢 → 弢 ) CJK COMPATIBILITY IDEOGRAPH-2F894 → CJK UNIFIED IDEOGRAPH-5F22 #
+2F895 ; 5F22 ; MA # ( 弢 → 弢 ) CJK COMPATIBILITY IDEOGRAPH-2F895 → CJK UNIFIED IDEOGRAPH-5F22 #
+
+2F39 ; 5F50 ; MA #* ( ⼹ → 彐 ) KANGXI RADICAL SNOUT → CJK UNIFIED IDEOGRAPH-5F50 #
+
+2E94 ; 5F51 ; MA #* ( ⺔ → 彑 ) CJK RADICAL SNOUT ONE → CJK UNIFIED IDEOGRAPH-5F51 #
+
+2F874 ; 5F53 ; MA # ( 当 → 当 ) CJK COMPATIBILITY IDEOGRAPH-2F874 → CJK UNIFIED IDEOGRAPH-5F53 #
+
+2F896 ; 38C7 ; MA # ( 㣇 → 㣇 ) CJK COMPATIBILITY IDEOGRAPH-2F896 → CJK UNIFIED IDEOGRAPH-38C7 #
+
+2F3A ; 5F61 ; MA #* ( ⼺ → 彡 ) KANGXI RADICAL BRISTLE → CJK UNIFIED IDEOGRAPH-5F61 #
+
+2F899 ; 5F62 ; MA # ( 形 → 形 ) CJK COMPATIBILITY IDEOGRAPH-2F899 → CJK UNIFIED IDEOGRAPH-5F62 #
+
+FA84 ; 5F69 ; MA # ( 彩 → 彩 ) CJK COMPATIBILITY IDEOGRAPH-FA84 → CJK UNIFIED IDEOGRAPH-5F69 #
+
+2F89A ; 5F6B ; MA # ( 彫 → 彫 ) CJK COMPATIBILITY IDEOGRAPH-2F89A → CJK UNIFIED IDEOGRAPH-5F6B #
+
+2F3B ; 5F73 ; MA #* ( ⼻ → 彳 ) KANGXI RADICAL STEP → CJK UNIFIED IDEOGRAPH-5F73 #
+
+F9D8 ; 5F8B ; MA # ( 律 → 律 ) CJK COMPATIBILITY IDEOGRAPH-F9D8 → CJK UNIFIED IDEOGRAPH-5F8B #
+
+2F89B ; 38E3 ; MA # ( 㣣 → 㣣 ) CJK COMPATIBILITY IDEOGRAPH-2F89B → CJK UNIFIED IDEOGRAPH-38E3 #
+
+2F89C ; 5F9A ; MA # ( 徚 → 徚 ) CJK COMPATIBILITY IDEOGRAPH-2F89C → CJK UNIFIED IDEOGRAPH-5F9A #
+
+F966 ; 5FA9 ; MA # ( 復 → 復 ) CJK COMPATIBILITY IDEOGRAPH-F966 → CJK UNIFIED IDEOGRAPH-5FA9 #
+
+FA85 ; 5FAD ; MA # ( 徭 → 徭 ) CJK COMPATIBILITY IDEOGRAPH-FA85 → CJK UNIFIED IDEOGRAPH-5FAD #
+
+2F3C ; 5FC3 ; MA #* ( ⼼ → 心 ) KANGXI RADICAL HEART → CJK UNIFIED IDEOGRAPH-5FC3 #
+
+2E96 ; 5FC4 ; MA #* ( ⺖ → 忄 ) CJK RADICAL HEART ONE → CJK UNIFIED IDEOGRAPH-5FC4 #
+
+2E97 ; 38FA ; MA #* ( ⺗ → 㣺 ) CJK RADICAL HEART TWO → CJK UNIFIED IDEOGRAPH-38FA #
+
+2F89D ; 5FCD ; MA # ( 忍 → 忍 ) CJK COMPATIBILITY IDEOGRAPH-2F89D → CJK UNIFIED IDEOGRAPH-5FCD #
+
+2F89E ; 5FD7 ; MA # ( 志 → 志 ) CJK COMPATIBILITY IDEOGRAPH-2F89E → CJK UNIFIED IDEOGRAPH-5FD7 #
+
+F9A3 ; 5FF5 ; MA # ( 念 → 念 ) CJK COMPATIBILITY IDEOGRAPH-F9A3 → CJK UNIFIED IDEOGRAPH-5FF5 #
+
+2F89F ; 5FF9 ; MA # ( 忹 → 忹 ) CJK COMPATIBILITY IDEOGRAPH-2F89F → CJK UNIFIED IDEOGRAPH-5FF9 #
+
+F960 ; 6012 ; MA # ( 怒 → 怒 ) CJK COMPATIBILITY IDEOGRAPH-F960 → CJK UNIFIED IDEOGRAPH-6012 #
+
+F9AC ; 601C ; MA # ( 怜 → 怜 ) CJK COMPATIBILITY IDEOGRAPH-F9AC → CJK UNIFIED IDEOGRAPH-601C #
+
+FA6B ; 6075 ; MA # ( 恵 → 恵 ) CJK COMPATIBILITY IDEOGRAPH-FA6B → CJK UNIFIED IDEOGRAPH-6075 #
+
+2F8A2 ; 391C ; MA # ( 㤜 → 㤜 ) CJK COMPATIBILITY IDEOGRAPH-2F8A2 → CJK UNIFIED IDEOGRAPH-391C #
+
+2F8A1 ; 393A ; MA # ( 㤺 → 㤺 ) CJK COMPATIBILITY IDEOGRAPH-2F8A1 → CJK UNIFIED IDEOGRAPH-393A #
+
+2F8A0 ; 6081 ; MA # ( 悁 → 悁 ) CJK COMPATIBILITY IDEOGRAPH-2F8A0 → CJK UNIFIED IDEOGRAPH-6081 #
+
+FA3D ; 6094 ; MA # ( 悔 → 悔 ) CJK COMPATIBILITY IDEOGRAPH-FA3D → CJK UNIFIED IDEOGRAPH-6094 #
+2F8A3 ; 6094 ; MA # ( 悔 → 悔 ) CJK COMPATIBILITY IDEOGRAPH-2F8A3 → CJK UNIFIED IDEOGRAPH-6094 #
+
+2F8A5 ; 60C7 ; MA # ( 惇 → 惇 ) CJK COMPATIBILITY IDEOGRAPH-2F8A5 → CJK UNIFIED IDEOGRAPH-60C7 #
+
+FA86 ; 60D8 ; MA # ( 惘 → 惘 ) CJK COMPATIBILITY IDEOGRAPH-FA86 → CJK UNIFIED IDEOGRAPH-60D8 #
+
+F9B9 ; 60E1 ; MA # ( 惡 → 惡 ) CJK COMPATIBILITY IDEOGRAPH-F9B9 → CJK UNIFIED IDEOGRAPH-60E1 #
+
+2F8A4 ; 226D4 ; MA # ( 𢛔 → 𢛔 ) CJK COMPATIBILITY IDEOGRAPH-2F8A4 → CJK UNIFIED IDEOGRAPH-226D4 #
+
+FA88 ; 6108 ; MA # ( 愈 → 愈 ) CJK COMPATIBILITY IDEOGRAPH-FA88 → CJK UNIFIED IDEOGRAPH-6108 #
+
+FA3E ; 6168 ; MA # ( 慨 → 慨 ) CJK COMPATIBILITY IDEOGRAPH-FA3E → CJK UNIFIED IDEOGRAPH-6168 #
+
+F9D9 ; 6144 ; MA # ( 慄 → 慄 ) CJK COMPATIBILITY IDEOGRAPH-F9D9 → CJK UNIFIED IDEOGRAPH-6144 #
+
+2F8A6 ; 6148 ; MA # ( 慈 → 慈 ) CJK COMPATIBILITY IDEOGRAPH-2F8A6 → CJK UNIFIED IDEOGRAPH-6148 #
+
+2F8A7 ; 614C ; MA # ( 慌 → 慌 ) CJK COMPATIBILITY IDEOGRAPH-2F8A7 → CJK UNIFIED IDEOGRAPH-614C #
+2F8A9 ; 614C ; MA # ( 慌 → 慌 ) CJK COMPATIBILITY IDEOGRAPH-2F8A9 → CJK UNIFIED IDEOGRAPH-614C #
+
+FA87 ; 614E ; MA # ( 慎 → 慎 ) CJK COMPATIBILITY IDEOGRAPH-FA87 → CJK UNIFIED IDEOGRAPH-614E #
+2F8A8 ; 614E ; MA # ( 慎 → 慎 ) CJK COMPATIBILITY IDEOGRAPH-2F8A8 → CJK UNIFIED IDEOGRAPH-614E #
+
+FA8A ; 6160 ; MA # ( 慠 → 慠 ) CJK COMPATIBILITY IDEOGRAPH-FA8A → CJK UNIFIED IDEOGRAPH-6160 #
+
+2F8AA ; 617A ; MA # ( 慺 → 慺 ) CJK COMPATIBILITY IDEOGRAPH-2F8AA → CJK UNIFIED IDEOGRAPH-617A #
+
+FA3F ; 618E ; MA # ( 憎 → 憎 ) CJK COMPATIBILITY IDEOGRAPH-FA3F → CJK UNIFIED IDEOGRAPH-618E #
+FA89 ; 618E ; MA # ( 憎 → 憎 ) CJK COMPATIBILITY IDEOGRAPH-FA89 → CJK UNIFIED IDEOGRAPH-618E #
+2F8AB ; 618E ; MA # ( 憎 → 憎 ) CJK COMPATIBILITY IDEOGRAPH-2F8AB → CJK UNIFIED IDEOGRAPH-618E #
+
+F98F ; 6190 ; MA # ( 憐 → 憐 ) CJK COMPATIBILITY IDEOGRAPH-F98F → CJK UNIFIED IDEOGRAPH-6190 #
+
+2F8AD ; 61A4 ; MA # ( 憤 → 憤 ) CJK COMPATIBILITY IDEOGRAPH-2F8AD → CJK UNIFIED IDEOGRAPH-61A4 #
+
+2F8AE ; 61AF ; MA # ( 憯 → 憯 ) CJK COMPATIBILITY IDEOGRAPH-2F8AE → CJK UNIFIED IDEOGRAPH-61AF #
+
+2F8AC ; 61B2 ; MA # ( 憲 → 憲 ) CJK COMPATIBILITY IDEOGRAPH-2F8AC → CJK UNIFIED IDEOGRAPH-61B2 #
+
+FAD0 ; 22844 ; MA # ( 𢡄 → 𢡄 ) CJK COMPATIBILITY IDEOGRAPH-FAD0 → CJK UNIFIED IDEOGRAPH-22844 #
+
+FACF ; 2284A ; MA # ( 𢡊 → 𢡊 ) CJK COMPATIBILITY IDEOGRAPH-FACF → CJK UNIFIED IDEOGRAPH-2284A #
+
+2F8AF ; 61DE ; MA # ( 懞 → 懞 ) CJK COMPATIBILITY IDEOGRAPH-2F8AF → CJK UNIFIED IDEOGRAPH-61DE #
+
+FA40 ; 61F2 ; MA # ( 懲 → 懲 ) CJK COMPATIBILITY IDEOGRAPH-FA40 → CJK UNIFIED IDEOGRAPH-61F2 #
+FA8B ; 61F2 ; MA # ( 懲 → 懲 ) CJK COMPATIBILITY IDEOGRAPH-FA8B → CJK UNIFIED IDEOGRAPH-61F2 #
+2F8B0 ; 61F2 ; MA # ( 懲 → 懲 ) CJK COMPATIBILITY IDEOGRAPH-2F8B0 → CJK UNIFIED IDEOGRAPH-61F2 #
+
+F90D ; 61F6 ; MA # ( 懶 → 懶 ) CJK COMPATIBILITY IDEOGRAPH-F90D → CJK UNIFIED IDEOGRAPH-61F6 #
+2F8B1 ; 61F6 ; MA # ( 懶 → 懶 ) CJK COMPATIBILITY IDEOGRAPH-2F8B1 → CJK UNIFIED IDEOGRAPH-61F6 #
+
+F990 ; 6200 ; MA # ( 戀 → 戀 ) CJK COMPATIBILITY IDEOGRAPH-F990 → CJK UNIFIED IDEOGRAPH-6200 #
+
+2F3D ; 6208 ; MA #* ( ⼽ → 戈 ) KANGXI RADICAL HALBERD → CJK UNIFIED IDEOGRAPH-6208 #
+
+2F8B2 ; 6210 ; MA # ( 成 → 成 ) CJK COMPATIBILITY IDEOGRAPH-2F8B2 → CJK UNIFIED IDEOGRAPH-6210 #
+
+2F8B3 ; 621B ; MA # ( 戛 → 戛 ) CJK COMPATIBILITY IDEOGRAPH-2F8B3 → CJK UNIFIED IDEOGRAPH-621B #
+
+F9D2 ; 622E ; MA # ( 戮 → 戮 ) CJK COMPATIBILITY IDEOGRAPH-F9D2 → CJK UNIFIED IDEOGRAPH-622E #
+
+FA8C ; 6234 ; MA # ( 戴 → 戴 ) CJK COMPATIBILITY IDEOGRAPH-FA8C → CJK UNIFIED IDEOGRAPH-6234 #
+
+2F3E ; 6236 ; MA #* ( ⼾ → 戶 ) KANGXI RADICAL DOOR → CJK UNIFIED IDEOGRAPH-6236 #
+6238 ; 6236 ; MA # ( 戸 → 戶 ) CJK UNIFIED IDEOGRAPH-6238 → CJK UNIFIED IDEOGRAPH-6236 # →⼾→
+
+2F3F ; 624B ; MA #* ( ⼿ → 手 ) KANGXI RADICAL HAND → CJK UNIFIED IDEOGRAPH-624B #
+
+2E98 ; 624C ; MA #* ( ⺘ → 扌 ) CJK RADICAL HAND → CJK UNIFIED IDEOGRAPH-624C #
+
+2F8B4 ; 625D ; MA # ( 扝 → 扝 ) CJK COMPATIBILITY IDEOGRAPH-2F8B4 → CJK UNIFIED IDEOGRAPH-625D #
+
+2F8B5 ; 62B1 ; MA # ( 抱 → 抱 ) CJK COMPATIBILITY IDEOGRAPH-2F8B5 → CJK UNIFIED IDEOGRAPH-62B1 #
+
+F925 ; 62C9 ; MA # ( 拉 → 拉 ) CJK COMPATIBILITY IDEOGRAPH-F925 → CJK UNIFIED IDEOGRAPH-62C9 #
+
+F95B ; 62CF ; MA # ( 拏 → 拏 ) CJK COMPATIBILITY IDEOGRAPH-F95B → CJK UNIFIED IDEOGRAPH-62CF #
+
+FA02 ; 62D3 ; MA # ( 拓 → 拓 ) CJK COMPATIBILITY IDEOGRAPH-FA02 → CJK UNIFIED IDEOGRAPH-62D3 #
+
+2F8B6 ; 62D4 ; MA # ( 拔 → 拔 ) CJK COMPATIBILITY IDEOGRAPH-2F8B6 → CJK UNIFIED IDEOGRAPH-62D4 #
+
+2F8BA ; 62FC ; MA # ( 拼 → 拼 ) CJK COMPATIBILITY IDEOGRAPH-2F8BA → CJK UNIFIED IDEOGRAPH-62FC #
+
+F973 ; 62FE ; MA # ( 拾 → 拾 ) CJK COMPATIBILITY IDEOGRAPH-F973 → CJK UNIFIED IDEOGRAPH-62FE #
+
+2F8B8 ; 22B0C ; MA # ( 𢬌 → 𢬌 ) CJK COMPATIBILITY IDEOGRAPH-2F8B8 → CJK UNIFIED IDEOGRAPH-22B0C #
+
+2F8B9 ; 633D ; MA # ( 挽 → 挽 ) CJK COMPATIBILITY IDEOGRAPH-2F8B9 → CJK UNIFIED IDEOGRAPH-633D #
+
+2F8B7 ; 6350 ; MA # ( 捐 → 捐 ) CJK COMPATIBILITY IDEOGRAPH-2F8B7 → CJK UNIFIED IDEOGRAPH-6350 #
+
+2F8BB ; 6368 ; MA # ( 捨 → 捨 ) CJK COMPATIBILITY IDEOGRAPH-2F8BB → CJK UNIFIED IDEOGRAPH-6368 #
+
+F9A4 ; 637B ; MA # ( 捻 → 捻 ) CJK COMPATIBILITY IDEOGRAPH-F9A4 → CJK UNIFIED IDEOGRAPH-637B #
+
+2F8BC ; 6383 ; MA # ( 掃 → 掃 ) CJK COMPATIBILITY IDEOGRAPH-2F8BC → CJK UNIFIED IDEOGRAPH-6383 #
+
+F975 ; 63A0 ; MA # ( 掠 → 掠 ) CJK COMPATIBILITY IDEOGRAPH-F975 → CJK UNIFIED IDEOGRAPH-63A0 #
+
+2F8C1 ; 63A9 ; MA # ( 掩 → 掩 ) CJK COMPATIBILITY IDEOGRAPH-2F8C1 → CJK UNIFIED IDEOGRAPH-63A9 #
+
+FA8D ; 63C4 ; MA # ( 揄 → 揄 ) CJK COMPATIBILITY IDEOGRAPH-FA8D → CJK UNIFIED IDEOGRAPH-63C4 #
+
+2F8BD ; 63E4 ; MA # ( 揤 → 揤 ) CJK COMPATIBILITY IDEOGRAPH-2F8BD → CJK UNIFIED IDEOGRAPH-63E4 #
+
+FA8F ; 6452 ; MA # ( 摒 → 摒 ) CJK COMPATIBILITY IDEOGRAPH-FA8F → CJK UNIFIED IDEOGRAPH-6452 #
+
+2F8BE ; 22BF1 ; MA # ( 𢯱 → 𢯱 ) CJK COMPATIBILITY IDEOGRAPH-2F8BE → CJK UNIFIED IDEOGRAPH-22BF1 #
+
+FA8E ; 641C ; MA # ( 搜 → 搜 ) CJK COMPATIBILITY IDEOGRAPH-FA8E → CJK UNIFIED IDEOGRAPH-641C #
+
+2F8BF ; 6422 ; MA # ( 搢 → 搢 ) CJK COMPATIBILITY IDEOGRAPH-2F8BF → CJK UNIFIED IDEOGRAPH-6422 #
+
+2F8C0 ; 63C5 ; MA # ( 揅 → 揅 ) CJK COMPATIBILITY IDEOGRAPH-2F8C0 → CJK UNIFIED IDEOGRAPH-63C5 #
+
+2F8C3 ; 6469 ; MA # ( 摩 → 摩 ) CJK COMPATIBILITY IDEOGRAPH-2F8C3 → CJK UNIFIED IDEOGRAPH-6469 #
+
+2F8C6 ; 6477 ; MA # ( 摷 → 摷 ) CJK COMPATIBILITY IDEOGRAPH-2F8C6 → CJK UNIFIED IDEOGRAPH-6477 #
+
+2F8C4 ; 647E ; MA # ( 摾 → 摾 ) CJK COMPATIBILITY IDEOGRAPH-2F8C4 → CJK UNIFIED IDEOGRAPH-647E #
+
+2F8C2 ; 3A2E ; MA # ( 㨮 → 㨮 ) CJK COMPATIBILITY IDEOGRAPH-2F8C2 → CJK UNIFIED IDEOGRAPH-3A2E #
+
+6409 ; 3A41 ; MA # ( 搉 → 㩁 ) CJK UNIFIED IDEOGRAPH-6409 → CJK UNIFIED IDEOGRAPH-3A41 #
+
+F991 ; 649A ; MA # ( 撚 → 撚 ) CJK COMPATIBILITY IDEOGRAPH-F991 → CJK UNIFIED IDEOGRAPH-649A #
+
+2F8C5 ; 649D ; MA # ( 撝 → 撝 ) CJK COMPATIBILITY IDEOGRAPH-2F8C5 → CJK UNIFIED IDEOGRAPH-649D #
+
+F930 ; 64C4 ; MA # ( 擄 → 擄 ) CJK COMPATIBILITY IDEOGRAPH-F930 → CJK UNIFIED IDEOGRAPH-64C4 #
+
+2F8C7 ; 3A6C ; MA # ( 㩬 → 㩬 ) CJK COMPATIBILITY IDEOGRAPH-2F8C7 → CJK UNIFIED IDEOGRAPH-3A6C #
+
+2F40 ; 652F ; MA #* ( ⽀ → 支 ) KANGXI RADICAL BRANCH → CJK UNIFIED IDEOGRAPH-652F #
+
+2F41 ; 6534 ; MA #* ( ⽁ → 攴 ) KANGXI RADICAL RAP → CJK UNIFIED IDEOGRAPH-6534 #
+
+2E99 ; 6535 ; MA #* ( ⺙ → 攵 ) CJK RADICAL RAP → CJK UNIFIED IDEOGRAPH-6535 #
+
+FA41 ; 654F ; MA # ( 敏 → 敏 ) CJK COMPATIBILITY IDEOGRAPH-FA41 → CJK UNIFIED IDEOGRAPH-654F #
+2F8C8 ; 654F ; MA # ( 敏 → 敏 ) CJK COMPATIBILITY IDEOGRAPH-2F8C8 → CJK UNIFIED IDEOGRAPH-654F #
+
+FA90 ; 6556 ; MA # ( 敖 → 敖 ) CJK COMPATIBILITY IDEOGRAPH-FA90 → CJK UNIFIED IDEOGRAPH-6556 #
+
+2F8C9 ; 656C ; MA # ( 敬 → 敬 ) CJK COMPATIBILITY IDEOGRAPH-2F8C9 → CJK UNIFIED IDEOGRAPH-656C #
+
+F969 ; 6578 ; MA # ( 數 → 數 ) CJK COMPATIBILITY IDEOGRAPH-F969 → CJK UNIFIED IDEOGRAPH-6578 #
+
+2F8CA ; 2300A ; MA # ( 𣀊 → 𣀊 ) CJK COMPATIBILITY IDEOGRAPH-2F8CA → CJK UNIFIED IDEOGRAPH-2300A #
+
+2F42 ; 6587 ; MA #* ( ⽂ → 文 ) KANGXI RADICAL SCRIPT → CJK UNIFIED IDEOGRAPH-6587 #
+
+2EEB ; 6589 ; MA #* ( ⻫ → 斉 ) CJK RADICAL J-SIMPLIFIED EVEN → CJK UNIFIED IDEOGRAPH-6589 #
+
+2F43 ; 6597 ; MA #* ( ⽃ → 斗 ) KANGXI RADICAL DIPPER → CJK UNIFIED IDEOGRAPH-6597 #
+
+F9BE ; 6599 ; MA # ( 料 → 料 ) CJK COMPATIBILITY IDEOGRAPH-F9BE → CJK UNIFIED IDEOGRAPH-6599 #
+
+2F44 ; 65A4 ; MA #* ( ⽄ → 斤 ) KANGXI RADICAL AXE → CJK UNIFIED IDEOGRAPH-65A4 #
+
+2F45 ; 65B9 ; MA #* ( ⽅ → 方 ) KANGXI RADICAL SQUARE → CJK UNIFIED IDEOGRAPH-65B9 #
+
+F983 ; 65C5 ; MA # ( 旅 → 旅 ) CJK COMPATIBILITY IDEOGRAPH-F983 → CJK UNIFIED IDEOGRAPH-65C5 #
+
+2F46 ; 65E0 ; MA #* ( ⽆ → 无 ) KANGXI RADICAL NOT → CJK UNIFIED IDEOGRAPH-65E0 #
+
+2E9B ; 65E1 ; MA #* ( ⺛ → 旡 ) CJK RADICAL CHOKE → CJK UNIFIED IDEOGRAPH-65E1 #
+
+FA42 ; 65E2 ; MA # ( 既 → 既 ) CJK COMPATIBILITY IDEOGRAPH-FA42 → CJK UNIFIED IDEOGRAPH-65E2 #
+
+2F8CB ; 65E3 ; MA # ( 旣 → 旣 ) CJK COMPATIBILITY IDEOGRAPH-2F8CB → CJK UNIFIED IDEOGRAPH-65E3 #
+
+2F47 ; 65E5 ; MA #* ( ⽇ → 日 ) KANGXI RADICAL SUN → CJK UNIFIED IDEOGRAPH-65E5 #
+
+F9E0 ; 6613 ; MA # ( 易 → 易 ) CJK COMPATIBILITY IDEOGRAPH-F9E0 → CJK UNIFIED IDEOGRAPH-6613 #
+
+66F6 ; 3ADA ; MA # ( 曶 → 㫚 ) CJK UNIFIED IDEOGRAPH-66F6 → CJK UNIFIED IDEOGRAPH-3ADA #
+
+2F8D1 ; 3AE4 ; MA # ( 㫤 → 㫤 ) CJK COMPATIBILITY IDEOGRAPH-2F8D1 → CJK UNIFIED IDEOGRAPH-3AE4 #
+
+2F8CD ; 6649 ; MA # ( 晉 → 晉 ) CJK COMPATIBILITY IDEOGRAPH-2F8CD → CJK UNIFIED IDEOGRAPH-6649 #
+
+6669 ; 665A ; MA # ( 晩 → 晚 ) CJK UNIFIED IDEOGRAPH-6669 → CJK UNIFIED IDEOGRAPH-665A #
+
+FA12 ; 6674 ; MA # ( 晴 → 晴 ) CJK COMPATIBILITY IDEOGRAPH-FA12 → CJK UNIFIED IDEOGRAPH-6674 #
+FA91 ; 6674 ; MA # ( 晴 → 晴 ) CJK COMPATIBILITY IDEOGRAPH-FA91 → CJK UNIFIED IDEOGRAPH-6674 #
+
+FA43 ; 6691 ; MA # ( 暑 → 暑 ) CJK COMPATIBILITY IDEOGRAPH-FA43 → CJK UNIFIED IDEOGRAPH-6691 #
+2F8CF ; 6691 ; MA # ( 暑 → 暑 ) CJK COMPATIBILITY IDEOGRAPH-2F8CF → CJK UNIFIED IDEOGRAPH-6691 #
+
+F9C5 ; 6688 ; MA # ( 暈 → 暈 ) CJK COMPATIBILITY IDEOGRAPH-F9C5 → CJK UNIFIED IDEOGRAPH-6688 #
+
+2F8D0 ; 3B08 ; MA # ( 㬈 → 㬈 ) CJK COMPATIBILITY IDEOGRAPH-2F8D0 → CJK UNIFIED IDEOGRAPH-3B08 #
+
+2F8D5 ; 669C ; MA # ( 暜 → 暜 ) CJK COMPATIBILITY IDEOGRAPH-2F8D5 → CJK UNIFIED IDEOGRAPH-669C #
+
+FA06 ; 66B4 ; MA # ( 暴 → 暴 ) CJK COMPATIBILITY IDEOGRAPH-FA06 → CJK UNIFIED IDEOGRAPH-66B4 #
+
+F98B ; 66C6 ; MA # ( 曆 → 曆 ) CJK COMPATIBILITY IDEOGRAPH-F98B → CJK UNIFIED IDEOGRAPH-66C6 #
+
+2F8CE ; 3B19 ; MA # ( 㬙 → 㬙 ) CJK COMPATIBILITY IDEOGRAPH-2F8CE → CJK UNIFIED IDEOGRAPH-3B19 #
+
+2F897 ; 232B8 ; MA # ( 𣊸 → 𣊸 ) CJK COMPATIBILITY IDEOGRAPH-2F897 → CJK UNIFIED IDEOGRAPH-232B8 #
+
+2F48 ; 66F0 ; MA #* ( ⽈ → 曰 ) KANGXI RADICAL SAY → CJK UNIFIED IDEOGRAPH-66F0 #
+
+F901 ; 66F4 ; MA # ( 更 → 更 ) CJK COMPATIBILITY IDEOGRAPH-F901 → CJK UNIFIED IDEOGRAPH-66F4 #
+
+2F8CC ; 66F8 ; MA # ( 書 → 書 ) CJK COMPATIBILITY IDEOGRAPH-2F8CC → CJK UNIFIED IDEOGRAPH-66F8 #
+
+2F49 ; 6708 ; MA #* ( ⽉ → 月 ) KANGXI RADICAL MOON → CJK UNIFIED IDEOGRAPH-6708 #
+
+2F980 ; 2335F ; MA # ( 𣍟 → 𣍟 ) CJK COMPATIBILITY IDEOGRAPH-2F980 → CJK UNIFIED IDEOGRAPH-2335F #
+
+80A6 ; 670C ; MA # ( 肦 → 朌 ) CJK UNIFIED IDEOGRAPH-80A6 → CJK UNIFIED IDEOGRAPH-670C #
+
+80D0 ; 670F ; MA # ( 胐 → 朏 ) CJK UNIFIED IDEOGRAPH-80D0 → CJK UNIFIED IDEOGRAPH-670F #
+
+80CA ; 6710 ; MA # ( 胊 → 朐 ) CJK UNIFIED IDEOGRAPH-80CA → CJK UNIFIED IDEOGRAPH-6710 #
+
+8101 ; 6713 ; MA # ( 脁 → 朓 ) CJK UNIFIED IDEOGRAPH-8101 → CJK UNIFIED IDEOGRAPH-6713 #
+
+80F6 ; 3B35 ; MA # ( 胶 → 㬵 ) CJK UNIFIED IDEOGRAPH-80F6 → CJK UNIFIED IDEOGRAPH-3B35 #
+
+F929 ; 6717 ; MA # ( 朗 → 朗 ) CJK COMPATIBILITY IDEOGRAPH-F929 → CJK UNIFIED IDEOGRAPH-6717 #
+FA92 ; 6717 ; MA # ( 朗 → 朗 ) CJK COMPATIBILITY IDEOGRAPH-FA92 → CJK UNIFIED IDEOGRAPH-6717 #
+2F8D8 ; 6717 ; MA # ( 朗 → 朗 ) CJK COMPATIBILITY IDEOGRAPH-2F8D8 → CJK UNIFIED IDEOGRAPH-6717 #
+
+8127 ; 6718 ; MA # ( 脧 → 朘 ) CJK UNIFIED IDEOGRAPH-8127 → CJK UNIFIED IDEOGRAPH-6718 #
+
+FA93 ; 671B ; MA # ( 望 → 望 ) CJK COMPATIBILITY IDEOGRAPH-FA93 → CJK UNIFIED IDEOGRAPH-671B #
+2F8D9 ; 671B ; MA # ( 望 → 望 ) CJK COMPATIBILITY IDEOGRAPH-2F8D9 → CJK UNIFIED IDEOGRAPH-671B #
+
+5E50 ; 3B3A ; MA # ( 幐 → 㬺 ) CJK UNIFIED IDEOGRAPH-5E50 → CJK UNIFIED IDEOGRAPH-3B3A #
+
+4420 ; 3B3B ; MA # ( 䐠 → 㬻 ) CJK UNIFIED IDEOGRAPH-4420 → CJK UNIFIED IDEOGRAPH-3B3B #
+
+2F989 ; 23393 ; MA # ( 𣎓 → 𣎓 ) CJK COMPATIBILITY IDEOGRAPH-2F989 → CJK UNIFIED IDEOGRAPH-23393 #
+
+81A7 ; 6723 ; MA # ( 膧 → 朣 ) CJK UNIFIED IDEOGRAPH-81A7 → CJK UNIFIED IDEOGRAPH-6723 #
+
+2F98A ; 2339C ; MA # ( 𣎜 → 𣎜 ) CJK COMPATIBILITY IDEOGRAPH-2F98A → CJK UNIFIED IDEOGRAPH-2339C #
+
+2F4A ; 6728 ; MA #* ( ⽊ → 木 ) KANGXI RADICAL TREE → CJK UNIFIED IDEOGRAPH-6728 #
+
+F9E1 ; 674E ; MA # ( 李 → 李 ) CJK COMPATIBILITY IDEOGRAPH-F9E1 → CJK UNIFIED IDEOGRAPH-674E #
+
+2F8DC ; 6753 ; MA # ( 杓 → 杓 ) CJK COMPATIBILITY IDEOGRAPH-2F8DC → CJK UNIFIED IDEOGRAPH-6753 #
+
+FA94 ; 6756 ; MA # ( 杖 → 杖 ) CJK COMPATIBILITY IDEOGRAPH-FA94 → CJK UNIFIED IDEOGRAPH-6756 #
+
+2F8DB ; 675E ; MA # ( 杞 → 杞 ) CJK COMPATIBILITY IDEOGRAPH-2F8DB → CJK UNIFIED IDEOGRAPH-675E #
+
+2F8DD ; 233C3 ; MA # ( 𣏃 → 𣏃 ) CJK COMPATIBILITY IDEOGRAPH-2F8DD → CJK UNIFIED IDEOGRAPH-233C3 #
+
+67FF ; 676E ; MA # ( 柿 → 杮 ) CJK UNIFIED IDEOGRAPH-67FF → CJK UNIFIED IDEOGRAPH-676E #
+
+F9C8 ; 677B ; MA # ( 杻 → 杻 ) CJK COMPATIBILITY IDEOGRAPH-F9C8 → CJK UNIFIED IDEOGRAPH-677B #
+
+2F8E0 ; 6785 ; MA # ( 枅 → 枅 ) CJK COMPATIBILITY IDEOGRAPH-2F8E0 → CJK UNIFIED IDEOGRAPH-6785 #
+
+F9F4 ; 6797 ; MA # ( 林 → 林 ) CJK COMPATIBILITY IDEOGRAPH-F9F4 → CJK UNIFIED IDEOGRAPH-6797 #
+
+2F8DE ; 3B49 ; MA # ( 㭉 → 㭉 ) CJK COMPATIBILITY IDEOGRAPH-2F8DE → CJK UNIFIED IDEOGRAPH-3B49 #
+
+FAD1 ; 233D5 ; MA # ( 𣏕 → 𣏕 ) CJK COMPATIBILITY IDEOGRAPH-FAD1 → CJK UNIFIED IDEOGRAPH-233D5 #
+
+F9C9 ; 67F3 ; MA # ( 柳 → 柳 ) CJK COMPATIBILITY IDEOGRAPH-F9C9 → CJK UNIFIED IDEOGRAPH-67F3 #
+
+2F8DF ; 67FA ; MA # ( 柺 → 柺 ) CJK COMPATIBILITY IDEOGRAPH-2F8DF → CJK UNIFIED IDEOGRAPH-67FA #
+
+F9DA ; 6817 ; MA # ( 栗 → 栗 ) CJK COMPATIBILITY IDEOGRAPH-F9DA → CJK UNIFIED IDEOGRAPH-6817 #
+
+2F8E5 ; 681F ; MA # ( 栟 → 栟 ) CJK COMPATIBILITY IDEOGRAPH-2F8E5 → CJK UNIFIED IDEOGRAPH-681F #
+
+2F8E1 ; 6852 ; MA # ( 桒 → 桒 ) CJK COMPATIBILITY IDEOGRAPH-2F8E1 → CJK UNIFIED IDEOGRAPH-6852 #
+
+2F8E3 ; 2346D ; MA # ( 𣑭 → 𣑭 ) CJK COMPATIBILITY IDEOGRAPH-2F8E3 → CJK UNIFIED IDEOGRAPH-2346D #
+
+F97A ; 6881 ; MA # ( 梁 → 梁 ) CJK COMPATIBILITY IDEOGRAPH-F97A → CJK UNIFIED IDEOGRAPH-6881 #
+
+FA44 ; 6885 ; MA # ( 梅 → 梅 ) CJK COMPATIBILITY IDEOGRAPH-FA44 → CJK UNIFIED IDEOGRAPH-6885 #
+2F8E2 ; 6885 ; MA # ( 梅 → 梅 ) CJK COMPATIBILITY IDEOGRAPH-2F8E2 → CJK UNIFIED IDEOGRAPH-6885 #
+
+2F8E4 ; 688E ; MA # ( 梎 → 梎 ) CJK COMPATIBILITY IDEOGRAPH-2F8E4 → CJK UNIFIED IDEOGRAPH-688E #
+
+F9E2 ; 68A8 ; MA # ( 梨 → 梨 ) CJK COMPATIBILITY IDEOGRAPH-F9E2 → CJK UNIFIED IDEOGRAPH-68A8 #
+
+2F8E6 ; 6914 ; MA # ( 椔 → 椔 ) CJK COMPATIBILITY IDEOGRAPH-2F8E6 → CJK UNIFIED IDEOGRAPH-6914 #
+
+2F8E8 ; 6942 ; MA # ( 楂 → 楂 ) CJK COMPATIBILITY IDEOGRAPH-2F8E8 → CJK UNIFIED IDEOGRAPH-6942 #
+
+FAD2 ; 3B9D ; MA # ( 㮝 → 㮝 ) CJK COMPATIBILITY IDEOGRAPH-FAD2 → CJK UNIFIED IDEOGRAPH-3B9D #
+2F8E7 ; 3B9D ; MA # ( 㮝 → 㮝 ) CJK COMPATIBILITY IDEOGRAPH-2F8E7 → CJK UNIFIED IDEOGRAPH-3B9D #
+
+69E9 ; 3BA3 ; MA # ( 槩 → 㮣 ) CJK UNIFIED IDEOGRAPH-69E9 → CJK UNIFIED IDEOGRAPH-3BA3 #
+
+6A27 ; 699D ; MA # ( 樧 → 榝 ) CJK UNIFIED IDEOGRAPH-6A27 → CJK UNIFIED IDEOGRAPH-699D #
+
+2F8E9 ; 69A3 ; MA # ( 榣 → 榣 ) CJK COMPATIBILITY IDEOGRAPH-2F8E9 → CJK UNIFIED IDEOGRAPH-69A3 #
+
+2F8EA ; 69EA ; MA # ( 槪 → 槪 ) CJK COMPATIBILITY IDEOGRAPH-2F8EA → CJK UNIFIED IDEOGRAPH-69EA #
+
+F914 ; 6A02 ; MA # ( 樂 → 樂 ) CJK COMPATIBILITY IDEOGRAPH-F914 → CJK UNIFIED IDEOGRAPH-6A02 #
+F95C ; 6A02 ; MA # ( 樂 → 樂 ) CJK COMPATIBILITY IDEOGRAPH-F95C → CJK UNIFIED IDEOGRAPH-6A02 #
+F9BF ; 6A02 ; MA # ( 樂 → 樂 ) CJK COMPATIBILITY IDEOGRAPH-F9BF → CJK UNIFIED IDEOGRAPH-6A02 #
+
+F94C ; 6A13 ; MA # ( 樓 → 樓 ) CJK COMPATIBILITY IDEOGRAPH-F94C → CJK UNIFIED IDEOGRAPH-6A13 #
+
+2F8EC ; 236A3 ; MA # ( 𣚣 → 𣚣 ) CJK COMPATIBILITY IDEOGRAPH-2F8EC → CJK UNIFIED IDEOGRAPH-236A3 #
+
+2F8EB ; 6AA8 ; MA # ( 檨 → 檨 ) CJK COMPATIBILITY IDEOGRAPH-2F8EB → CJK UNIFIED IDEOGRAPH-6AA8 #
+
+F931 ; 6AD3 ; MA # ( 櫓 → 櫓 ) CJK COMPATIBILITY IDEOGRAPH-F931 → CJK UNIFIED IDEOGRAPH-6AD3 #
+
+2F8ED ; 6ADB ; MA # ( 櫛 → 櫛 ) CJK COMPATIBILITY IDEOGRAPH-2F8ED → CJK UNIFIED IDEOGRAPH-6ADB #
+
+F91D ; 6B04 ; MA # ( 欄 → 欄 ) CJK COMPATIBILITY IDEOGRAPH-F91D → CJK UNIFIED IDEOGRAPH-6B04 #
+
+2F8EE ; 3C18 ; MA # ( 㰘 → 㰘 ) CJK COMPATIBILITY IDEOGRAPH-2F8EE → CJK UNIFIED IDEOGRAPH-3C18 #
+
+2F4B ; 6B20 ; MA #* ( ⽋ → 欠 ) KANGXI RADICAL LACK → CJK UNIFIED IDEOGRAPH-6B20 #
+
+2F8EF ; 6B21 ; MA # ( 次 → 次 ) CJK COMPATIBILITY IDEOGRAPH-2F8EF → CJK UNIFIED IDEOGRAPH-6B21 #
+
+2F8F0 ; 238A7 ; MA # ( 𣢧 → 𣢧 ) CJK COMPATIBILITY IDEOGRAPH-2F8F0 → CJK UNIFIED IDEOGRAPH-238A7 #
+
+2F8F1 ; 6B54 ; MA # ( 歔 → 歔 ) CJK COMPATIBILITY IDEOGRAPH-2F8F1 → CJK UNIFIED IDEOGRAPH-6B54 #
+
+2F8F2 ; 3C4E ; MA # ( 㱎 → 㱎 ) CJK COMPATIBILITY IDEOGRAPH-2F8F2 → CJK UNIFIED IDEOGRAPH-3C4E #
+
+2F4C ; 6B62 ; MA #* ( ⽌ → 止 ) KANGXI RADICAL STOP → CJK UNIFIED IDEOGRAPH-6B62 #
+
+2EED ; 6B6F ; MA #* ( ⻭ → 歯 ) CJK RADICAL J-SIMPLIFIED TOOTH → CJK UNIFIED IDEOGRAPH-6B6F #
+
+2F8F3 ; 6B72 ; MA # ( 歲 → 歲 ) CJK COMPATIBILITY IDEOGRAPH-2F8F3 → CJK UNIFIED IDEOGRAPH-6B72 #
+
+F98C ; 6B77 ; MA # ( 歷 → 歷 ) CJK COMPATIBILITY IDEOGRAPH-F98C → CJK UNIFIED IDEOGRAPH-6B77 #
+
+FA95 ; 6B79 ; MA # ( 歹 → 歹 ) CJK COMPATIBILITY IDEOGRAPH-FA95 → CJK UNIFIED IDEOGRAPH-6B79 #
+2F4D ; 6B79 ; MA #* ( ⽍ → 歹 ) KANGXI RADICAL DEATH → CJK UNIFIED IDEOGRAPH-6B79 #
+
+2E9E ; 6B7A ; MA #* ( ⺞ → 歺 ) CJK RADICAL DEATH → CJK UNIFIED IDEOGRAPH-6B7A #
+
+2F8F4 ; 6B9F ; MA # ( 殟 → 殟 ) CJK COMPATIBILITY IDEOGRAPH-2F8F4 → CJK UNIFIED IDEOGRAPH-6B9F #
+
+F9A5 ; 6BAE ; MA # ( 殮 → 殮 ) CJK COMPATIBILITY IDEOGRAPH-F9A5 → CJK UNIFIED IDEOGRAPH-6BAE #
+
+2F4E ; 6BB3 ; MA #* ( ⽎ → 殳 ) KANGXI RADICAL WEAPON → CJK UNIFIED IDEOGRAPH-6BB3 #
+
+F970 ; 6BBA ; MA # ( 殺 → 殺 ) CJK COMPATIBILITY IDEOGRAPH-F970 → CJK UNIFIED IDEOGRAPH-6BBA #
+FA96 ; 6BBA ; MA # ( 殺 → 殺 ) CJK COMPATIBILITY IDEOGRAPH-FA96 → CJK UNIFIED IDEOGRAPH-6BBA #
+2F8F5 ; 6BBA ; MA # ( 殺 → 殺 ) CJK COMPATIBILITY IDEOGRAPH-2F8F5 → CJK UNIFIED IDEOGRAPH-6BBA #
+
+2F8F6 ; 6BBB ; MA # ( 殻 → 殻 ) CJK COMPATIBILITY IDEOGRAPH-2F8F6 → CJK UNIFIED IDEOGRAPH-6BBB #
+
+2F8F7 ; 23A8D ; MA # ( 𣪍 → 𣪍 ) CJK COMPATIBILITY IDEOGRAPH-2F8F7 → CJK UNIFIED IDEOGRAPH-23A8D #
+
+2F4F ; 6BCB ; MA #* ( ⽏ → 毋 ) KANGXI RADICAL DO NOT → CJK UNIFIED IDEOGRAPH-6BCB #
+
+2E9F ; 6BCD ; MA #* ( ⺟ → 母 ) CJK RADICAL MOTHER → CJK UNIFIED IDEOGRAPH-6BCD #
+
+2F8F9 ; 23AFA ; MA # ( 𣫺 → 𣫺 ) CJK COMPATIBILITY IDEOGRAPH-2F8F9 → CJK UNIFIED IDEOGRAPH-23AFA #
+
+2F50 ; 6BD4 ; MA #* ( ⽐ → 比 ) KANGXI RADICAL COMPARE → CJK UNIFIED IDEOGRAPH-6BD4 #
+
+2F51 ; 6BDB ; MA #* ( ⽑ → 毛 ) KANGXI RADICAL FUR → CJK UNIFIED IDEOGRAPH-6BDB #
+
+2F52 ; 6C0F ; MA #* ( ⽒ → 氏 ) KANGXI RADICAL CLAN → CJK UNIFIED IDEOGRAPH-6C0F #
+
+2EA0 ; 6C11 ; MA #* ( ⺠ → 民 ) CJK RADICAL CIVILIAN → CJK UNIFIED IDEOGRAPH-6C11 #
+
+2F53 ; 6C14 ; MA #* ( ⽓ → 气 ) KANGXI RADICAL STEAM → CJK UNIFIED IDEOGRAPH-6C14 #
+
+2F54 ; 6C34 ; MA #* ( ⽔ → 水 ) KANGXI RADICAL WATER → CJK UNIFIED IDEOGRAPH-6C34 #
+
+2EA1 ; 6C35 ; MA #* ( ⺡ → 氵 ) CJK RADICAL WATER ONE → CJK UNIFIED IDEOGRAPH-6C35 #
+
+2EA2 ; 6C3A ; MA #* ( ⺢ → 氺 ) CJK RADICAL WATER TWO → CJK UNIFIED IDEOGRAPH-6C3A #
+
+2F8FA ; 6C4E ; MA # ( 汎 → 汎 ) CJK COMPATIBILITY IDEOGRAPH-2F8FA → CJK UNIFIED IDEOGRAPH-6C4E #
+
+2F8FE ; 6C67 ; MA # ( 汧 → 汧 ) CJK COMPATIBILITY IDEOGRAPH-2F8FE → CJK UNIFIED IDEOGRAPH-6C67 #
+
+F972 ; 6C88 ; MA # ( 沈 → 沈 ) CJK COMPATIBILITY IDEOGRAPH-F972 → CJK UNIFIED IDEOGRAPH-6C88 #
+
+2F8FC ; 6CBF ; MA # ( 沿 → 沿 ) CJK COMPATIBILITY IDEOGRAPH-2F8FC → CJK UNIFIED IDEOGRAPH-6CBF #
+
+F968 ; 6CCC ; MA # ( 泌 → 泌 ) CJK COMPATIBILITY IDEOGRAPH-F968 → CJK UNIFIED IDEOGRAPH-6CCC #
+
+2F8FD ; 6CCD ; MA # ( 泍 → 泍 ) CJK COMPATIBILITY IDEOGRAPH-2F8FD → CJK UNIFIED IDEOGRAPH-6CCD #
+
+F9E3 ; 6CE5 ; MA # ( 泥 → 泥 ) CJK COMPATIBILITY IDEOGRAPH-F9E3 → CJK UNIFIED IDEOGRAPH-6CE5 #
+
+2F8FB ; 23CBC ; MA # ( 𣲼 → 𣲼 ) CJK COMPATIBILITY IDEOGRAPH-2F8FB → CJK UNIFIED IDEOGRAPH-23CBC #
+
+F915 ; 6D1B ; MA # ( 洛 → 洛 ) CJK COMPATIBILITY IDEOGRAPH-F915 → CJK UNIFIED IDEOGRAPH-6D1B #
+
+FA05 ; 6D1E ; MA # ( 洞 → 洞 ) CJK COMPATIBILITY IDEOGRAPH-FA05 → CJK UNIFIED IDEOGRAPH-6D1E #
+
+2F907 ; 6D34 ; MA # ( 洴 → 洴 ) CJK COMPATIBILITY IDEOGRAPH-2F907 → CJK UNIFIED IDEOGRAPH-6D34 #
+
+2F900 ; 6D3E ; MA # ( 派 → 派 ) CJK COMPATIBILITY IDEOGRAPH-2F900 → CJK UNIFIED IDEOGRAPH-6D3E #
+
+F9CA ; 6D41 ; MA # ( 流 → 流 ) CJK COMPATIBILITY IDEOGRAPH-F9CA → CJK UNIFIED IDEOGRAPH-6D41 #
+FA97 ; 6D41 ; MA # ( 流 → 流 ) CJK COMPATIBILITY IDEOGRAPH-FA97 → CJK UNIFIED IDEOGRAPH-6D41 #
+2F902 ; 6D41 ; MA # ( 流 → 流 ) CJK COMPATIBILITY IDEOGRAPH-2F902 → CJK UNIFIED IDEOGRAPH-6D41 #
+
+2F8FF ; 6D16 ; MA # ( 洖 → 洖 ) CJK COMPATIBILITY IDEOGRAPH-2F8FF → CJK UNIFIED IDEOGRAPH-6D16 #
+
+2F903 ; 6D69 ; MA # ( 浩 → 浩 ) CJK COMPATIBILITY IDEOGRAPH-2F903 → CJK UNIFIED IDEOGRAPH-6D69 #
+
+F92A ; 6D6A ; MA # ( 浪 → 浪 ) CJK COMPATIBILITY IDEOGRAPH-F92A → CJK UNIFIED IDEOGRAPH-6D6A #
+
+FA45 ; 6D77 ; MA # ( 海 → 海 ) CJK COMPATIBILITY IDEOGRAPH-FA45 → CJK UNIFIED IDEOGRAPH-6D77 #
+2F901 ; 6D77 ; MA # ( 海 → 海 ) CJK COMPATIBILITY IDEOGRAPH-2F901 → CJK UNIFIED IDEOGRAPH-6D77 #
+
+2F904 ; 6D78 ; MA # ( 浸 → 浸 ) CJK COMPATIBILITY IDEOGRAPH-2F904 → CJK UNIFIED IDEOGRAPH-6D78 #
+
+2F905 ; 6D85 ; MA # ( 涅 → 涅 ) CJK COMPATIBILITY IDEOGRAPH-2F905 → CJK UNIFIED IDEOGRAPH-6D85 #
+
+2F906 ; 23D1E ; MA # ( 𣴞 → 𣴞 ) CJK COMPATIBILITY IDEOGRAPH-2F906 → CJK UNIFIED IDEOGRAPH-23D1E #
+
+F9F5 ; 6DCB ; MA # ( 淋 → 淋 ) CJK COMPATIBILITY IDEOGRAPH-F9F5 → CJK UNIFIED IDEOGRAPH-6DCB #
+
+F94D ; 6DDA ; MA # ( 淚 → 淚 ) CJK COMPATIBILITY IDEOGRAPH-F94D → CJK UNIFIED IDEOGRAPH-6DDA #
+
+F9D6 ; 6DEA ; MA # ( 淪 → 淪 ) CJK COMPATIBILITY IDEOGRAPH-F9D6 → CJK UNIFIED IDEOGRAPH-6DEA #
+
+2F90E ; 6DF9 ; MA # ( 淹 → 淹 ) CJK COMPATIBILITY IDEOGRAPH-2F90E → CJK UNIFIED IDEOGRAPH-6DF9 #
+
+FA46 ; 6E1A ; MA # ( 渚 → 渚 ) CJK COMPATIBILITY IDEOGRAPH-FA46 → CJK UNIFIED IDEOGRAPH-6E1A #
+
+2F908 ; 6E2F ; MA # ( 港 → 港 ) CJK COMPATIBILITY IDEOGRAPH-2F908 → CJK UNIFIED IDEOGRAPH-6E2F #
+
+2F909 ; 6E6E ; MA # ( 湮 → 湮 ) CJK COMPATIBILITY IDEOGRAPH-2F909 → CJK UNIFIED IDEOGRAPH-6E6E #
+
+6F59 ; 6E88 ; MA # ( 潙 → 溈 ) CJK UNIFIED IDEOGRAPH-6F59 → CJK UNIFIED IDEOGRAPH-6E88 #
+
+FA99 ; 6ECB ; MA # ( 滋 → 滋 ) CJK COMPATIBILITY IDEOGRAPH-FA99 → CJK UNIFIED IDEOGRAPH-6ECB #
+2F90B ; 6ECB ; MA # ( 滋 → 滋 ) CJK COMPATIBILITY IDEOGRAPH-2F90B → CJK UNIFIED IDEOGRAPH-6ECB #
+
+F9CB ; 6E9C ; MA # ( 溜 → 溜 ) CJK COMPATIBILITY IDEOGRAPH-F9CB → CJK UNIFIED IDEOGRAPH-6E9C #
+
+F9EC ; 6EBA ; MA # ( 溺 → 溺 ) CJK COMPATIBILITY IDEOGRAPH-F9EC → CJK UNIFIED IDEOGRAPH-6EBA #
+
+2F90C ; 6EC7 ; MA # ( 滇 → 滇 ) CJK COMPATIBILITY IDEOGRAPH-2F90C → CJK UNIFIED IDEOGRAPH-6EC7 #
+
+F904 ; 6ED1 ; MA # ( 滑 → 滑 ) CJK COMPATIBILITY IDEOGRAPH-F904 → CJK UNIFIED IDEOGRAPH-6ED1 #
+
+FA98 ; 6EDB ; MA # ( 滛 → 滛 ) CJK COMPATIBILITY IDEOGRAPH-FA98 → CJK UNIFIED IDEOGRAPH-6EDB #
+
+2F90A ; 3D33 ; MA # ( 㴳 → 㴳 ) CJK COMPATIBILITY IDEOGRAPH-2F90A → CJK UNIFIED IDEOGRAPH-3D33 #
+
+F94E ; 6F0F ; MA # ( 漏 → 漏 ) CJK COMPATIBILITY IDEOGRAPH-F94E → CJK UNIFIED IDEOGRAPH-6F0F #
+
+FA47 ; 6F22 ; MA # ( 漢 → 漢 ) CJK COMPATIBILITY IDEOGRAPH-FA47 → CJK UNIFIED IDEOGRAPH-6F22 #
+FA9A ; 6F22 ; MA # ( 漢 → 漢 ) CJK COMPATIBILITY IDEOGRAPH-FA9A → CJK UNIFIED IDEOGRAPH-6F22 #
+
+F992 ; 6F23 ; MA # ( 漣 → 漣 ) CJK COMPATIBILITY IDEOGRAPH-F992 → CJK UNIFIED IDEOGRAPH-6F23 #
+
+2F90D ; 23ED1 ; MA # ( 𣻑 → 𣻑 ) CJK COMPATIBILITY IDEOGRAPH-2F90D → CJK UNIFIED IDEOGRAPH-23ED1 #
+
+2F90F ; 6F6E ; MA # ( 潮 → 潮 ) CJK COMPATIBILITY IDEOGRAPH-2F90F → CJK UNIFIED IDEOGRAPH-6F6E #
+
+2F910 ; 23F5E ; MA # ( 𣽞 → 𣽞 ) CJK COMPATIBILITY IDEOGRAPH-2F910 → CJK UNIFIED IDEOGRAPH-23F5E #
+
+2F911 ; 23F8E ; MA # ( 𣾎 → 𣾎 ) CJK COMPATIBILITY IDEOGRAPH-2F911 → CJK UNIFIED IDEOGRAPH-23F8E #
+
+2F912 ; 6FC6 ; MA # ( 濆 → 濆 ) CJK COMPATIBILITY IDEOGRAPH-2F912 → CJK UNIFIED IDEOGRAPH-6FC6 #
+
+F922 ; 6FEB ; MA # ( 濫 → 濫 ) CJK COMPATIBILITY IDEOGRAPH-F922 → CJK UNIFIED IDEOGRAPH-6FEB #
+
+F984 ; 6FFE ; MA # ( 濾 → 濾 ) CJK COMPATIBILITY IDEOGRAPH-F984 → CJK UNIFIED IDEOGRAPH-6FFE #
+
+2F915 ; 701B ; MA # ( 瀛 → 瀛 ) CJK COMPATIBILITY IDEOGRAPH-2F915 → CJK UNIFIED IDEOGRAPH-701B #
+
+FA9B ; 701E ; MA # ( 瀞 → 瀞 ) CJK COMPATIBILITY IDEOGRAPH-FA9B → CJK UNIFIED IDEOGRAPH-701E #
+2F914 ; 701E ; MA # ( 瀞 → 瀞 ) CJK COMPATIBILITY IDEOGRAPH-2F914 → CJK UNIFIED IDEOGRAPH-701E #
+
+2F913 ; 7039 ; MA # ( 瀹 → 瀹 ) CJK COMPATIBILITY IDEOGRAPH-2F913 → CJK UNIFIED IDEOGRAPH-7039 #
+
+2F917 ; 704A ; MA # ( 灊 → 灊 ) CJK COMPATIBILITY IDEOGRAPH-2F917 → CJK UNIFIED IDEOGRAPH-704A #
+
+2F916 ; 3D96 ; MA # ( 㶖 → 㶖 ) CJK COMPATIBILITY IDEOGRAPH-2F916 → CJK UNIFIED IDEOGRAPH-3D96 #
+
+2F55 ; 706B ; MA #* ( ⽕ → 火 ) KANGXI RADICAL FIRE → CJK UNIFIED IDEOGRAPH-706B #
+
+2EA3 ; 706C ; MA #* ( ⺣ → 灬 ) CJK RADICAL FIRE → CJK UNIFIED IDEOGRAPH-706C #
+
+2F835 ; 7070 ; MA # ( 灰 → 灰 ) CJK COMPATIBILITY IDEOGRAPH-2F835 → CJK UNIFIED IDEOGRAPH-7070 #
+
+2F919 ; 7077 ; MA # ( 灷 → 灷 ) CJK COMPATIBILITY IDEOGRAPH-2F919 → CJK UNIFIED IDEOGRAPH-7077 #
+
+2F918 ; 707D ; MA # ( 災 → 災 ) CJK COMPATIBILITY IDEOGRAPH-2F918 → CJK UNIFIED IDEOGRAPH-707D #
+
+F9FB ; 7099 ; MA # ( 炙 → 炙 ) CJK COMPATIBILITY IDEOGRAPH-F9FB → CJK UNIFIED IDEOGRAPH-7099 #
+
+2F91A ; 70AD ; MA # ( 炭 → 炭 ) CJK COMPATIBILITY IDEOGRAPH-2F91A → CJK UNIFIED IDEOGRAPH-70AD #
+
+F99F ; 70C8 ; MA # ( 烈 → 烈 ) CJK COMPATIBILITY IDEOGRAPH-F99F → CJK UNIFIED IDEOGRAPH-70C8 #
+
+F916 ; 70D9 ; MA # ( 烙 → 烙 ) CJK COMPATIBILITY IDEOGRAPH-F916 → CJK UNIFIED IDEOGRAPH-70D9 #
+
+FA48 ; 716E ; MA # ( 煮 → 煮 ) CJK COMPATIBILITY IDEOGRAPH-FA48 → CJK UNIFIED IDEOGRAPH-716E #
+FA9C ; 716E ; MA # ( 煮 → 煮 ) CJK COMPATIBILITY IDEOGRAPH-FA9C → CJK UNIFIED IDEOGRAPH-716E #
+
+2F91D ; 24263 ; MA # ( 𤉣 → 𤉣 ) CJK COMPATIBILITY IDEOGRAPH-2F91D → CJK UNIFIED IDEOGRAPH-24263 #
+
+2F91C ; 7145 ; MA # ( 煅 → 煅 ) CJK COMPATIBILITY IDEOGRAPH-2F91C → CJK UNIFIED IDEOGRAPH-7145 #
+
+F993 ; 7149 ; MA # ( 煉 → 煉 ) CJK COMPATIBILITY IDEOGRAPH-F993 → CJK UNIFIED IDEOGRAPH-7149 #
+
+FA6C ; 242EE ; MA # ( 𤋮 → 𤋮 ) CJK COMPATIBILITY IDEOGRAPH-FA6C → CJK UNIFIED IDEOGRAPH-242EE #
+
+2F91E ; 719C ; MA # ( 熜 → 熜 ) CJK COMPATIBILITY IDEOGRAPH-2F91E → CJK UNIFIED IDEOGRAPH-719C #
+
+F9C0 ; 71CE ; MA # ( 燎 → 燎 ) CJK COMPATIBILITY IDEOGRAPH-F9C0 → CJK UNIFIED IDEOGRAPH-71CE #
+
+F9EE ; 71D0 ; MA # ( 燐 → 燐 ) CJK COMPATIBILITY IDEOGRAPH-F9EE → CJK UNIFIED IDEOGRAPH-71D0 #
+
+2F91F ; 243AB ; MA # ( 𤎫 → 𤎫 ) CJK COMPATIBILITY IDEOGRAPH-2F91F → CJK UNIFIED IDEOGRAPH-243AB #
+
+F932 ; 7210 ; MA # ( 爐 → 爐 ) CJK COMPATIBILITY IDEOGRAPH-F932 → CJK UNIFIED IDEOGRAPH-7210 #
+
+F91E ; 721B ; MA # ( 爛 → 爛 ) CJK COMPATIBILITY IDEOGRAPH-F91E → CJK UNIFIED IDEOGRAPH-721B #
+
+2F920 ; 7228 ; MA # ( 爨 → 爨 ) CJK COMPATIBILITY IDEOGRAPH-2F920 → CJK UNIFIED IDEOGRAPH-7228 #
+
+2F56 ; 722A ; MA #* ( ⽖ → 爪 ) KANGXI RADICAL CLAW → CJK UNIFIED IDEOGRAPH-722A #
+
+FA49 ; 722B ; MA # ( 爫 → 爫 ) CJK COMPATIBILITY IDEOGRAPH-FA49 → CJK UNIFIED IDEOGRAPH-722B #
+2EA4 ; 722B ; MA #* ( ⺤ → 爫 ) CJK RADICAL PAW ONE → CJK UNIFIED IDEOGRAPH-722B #
+
+FA9E ; 7235 ; MA # ( 爵 → 爵 ) CJK COMPATIBILITY IDEOGRAPH-FA9E → CJK UNIFIED IDEOGRAPH-7235 #
+2F921 ; 7235 ; MA # ( 爵 → 爵 ) CJK COMPATIBILITY IDEOGRAPH-2F921 → CJK UNIFIED IDEOGRAPH-7235 #
+
+2F57 ; 7236 ; MA #* ( ⽗ → 父 ) KANGXI RADICAL FATHER → CJK UNIFIED IDEOGRAPH-7236 #
+
+2F58 ; 723B ; MA #* ( ⽘ → 爻 ) KANGXI RADICAL DOUBLE X → CJK UNIFIED IDEOGRAPH-723B #
+
+2EA6 ; 4E2C ; MA #* ( ⺦ → 丬 ) CJK RADICAL SIMPLIFIED HALF TREE TRUNK → CJK UNIFIED IDEOGRAPH-4E2C #
+
+2F59 ; 723F ; MA #* ( ⽙ → 爿 ) KANGXI RADICAL HALF TREE TRUNK → CJK UNIFIED IDEOGRAPH-723F #
+
+2F5A ; 7247 ; MA #* ( ⽚ → 片 ) KANGXI RADICAL SLICE → CJK UNIFIED IDEOGRAPH-7247 #
+
+2F922 ; 7250 ; MA # ( 牐 → 牐 ) CJK COMPATIBILITY IDEOGRAPH-2F922 → CJK UNIFIED IDEOGRAPH-7250 #
+
+2F5B ; 7259 ; MA #* ( ⽛ → 牙 ) KANGXI RADICAL FANG → CJK UNIFIED IDEOGRAPH-7259 #
+
+2F923 ; 24608 ; MA # ( 𤘈 → 𤘈 ) CJK COMPATIBILITY IDEOGRAPH-2F923 → CJK UNIFIED IDEOGRAPH-24608 #
+
+2F5C ; 725B ; MA #* ( ⽜ → 牛 ) KANGXI RADICAL COW → CJK UNIFIED IDEOGRAPH-725B #
+
+F946 ; 7262 ; MA # ( 牢 → 牢 ) CJK COMPATIBILITY IDEOGRAPH-F946 → CJK UNIFIED IDEOGRAPH-7262 #
+
+2F924 ; 7280 ; MA # ( 犀 → 犀 ) CJK COMPATIBILITY IDEOGRAPH-2F924 → CJK UNIFIED IDEOGRAPH-7280 #
+
+2F925 ; 7295 ; MA # ( 犕 → 犕 ) CJK COMPATIBILITY IDEOGRAPH-2F925 → CJK UNIFIED IDEOGRAPH-7295 #
+
+2F5D ; 72AC ; MA #* ( ⽝ → 犬 ) KANGXI RADICAL DOG → CJK UNIFIED IDEOGRAPH-72AC #
+
+2EA8 ; 72AD ; MA #* ( ⺨ → 犭 ) CJK RADICAL DOG → CJK UNIFIED IDEOGRAPH-72AD #
+
+FA9F ; 72AF ; MA # ( 犯 → 犯 ) CJK COMPATIBILITY IDEOGRAPH-FA9F → CJK UNIFIED IDEOGRAPH-72AF #
+
+F9FA ; 72C0 ; MA # ( 狀 → 狀 ) CJK COMPATIBILITY IDEOGRAPH-F9FA → CJK UNIFIED IDEOGRAPH-72C0 #
+
+2F926 ; 24735 ; MA # ( 𤜵 → 𤜵 ) CJK COMPATIBILITY IDEOGRAPH-2F926 → CJK UNIFIED IDEOGRAPH-24735 #
+
+F92B ; 72FC ; MA # ( 狼 → 狼 ) CJK COMPATIBILITY IDEOGRAPH-F92B → CJK UNIFIED IDEOGRAPH-72FC #
+
+FA16 ; 732A ; MA # ( 猪 → 猪 ) CJK COMPATIBILITY IDEOGRAPH-FA16 → CJK UNIFIED IDEOGRAPH-732A #
+FAA0 ; 732A ; MA # ( 猪 → 猪 ) CJK COMPATIBILITY IDEOGRAPH-FAA0 → CJK UNIFIED IDEOGRAPH-732A #
+
+2F927 ; 24814 ; MA # ( 𤠔 → 𤠔 ) CJK COMPATIBILITY IDEOGRAPH-2F927 → CJK UNIFIED IDEOGRAPH-24814 #
+
+F9A7 ; 7375 ; MA # ( 獵 → 獵 ) CJK COMPATIBILITY IDEOGRAPH-F9A7 → CJK UNIFIED IDEOGRAPH-7375 #
+
+2F928 ; 737A ; MA # ( 獺 → 獺 ) CJK COMPATIBILITY IDEOGRAPH-2F928 → CJK UNIFIED IDEOGRAPH-737A #
+
+2F5E ; 7384 ; MA #* ( ⽞ → 玄 ) KANGXI RADICAL PROFOUND → CJK UNIFIED IDEOGRAPH-7384 #
+
+F961 ; 7387 ; MA # ( 率 → 率 ) CJK COMPATIBILITY IDEOGRAPH-F961 → CJK UNIFIED IDEOGRAPH-7387 #
+F9DB ; 7387 ; MA # ( 率 → 率 ) CJK COMPATIBILITY IDEOGRAPH-F9DB → CJK UNIFIED IDEOGRAPH-7387 #
+
+2F5F ; 7389 ; MA #* ( ⽟ → 玉 ) KANGXI RADICAL JADE → CJK UNIFIED IDEOGRAPH-7389 #
+
+2F929 ; 738B ; MA # ( 王 → 王 ) CJK COMPATIBILITY IDEOGRAPH-2F929 → CJK UNIFIED IDEOGRAPH-738B #
+
+2F92A ; 3EAC ; MA # ( 㺬 → 㺬 ) CJK COMPATIBILITY IDEOGRAPH-2F92A → CJK UNIFIED IDEOGRAPH-3EAC #
+
+2F92B ; 73A5 ; MA # ( 玥 → 玥 ) CJK COMPATIBILITY IDEOGRAPH-2F92B → CJK UNIFIED IDEOGRAPH-73A5 #
+
+F9AD ; 73B2 ; MA # ( 玲 → 玲 ) CJK COMPATIBILITY IDEOGRAPH-F9AD → CJK UNIFIED IDEOGRAPH-73B2 #
+
+2F92C ; 3EB8 ; MA # ( 㺸 → 㺸 ) CJK COMPATIBILITY IDEOGRAPH-2F92C → CJK UNIFIED IDEOGRAPH-3EB8 #
+2F92D ; 3EB8 ; MA # ( 㺸 → 㺸 ) CJK COMPATIBILITY IDEOGRAPH-2F92D → CJK UNIFIED IDEOGRAPH-3EB8 #
+
+F917 ; 73DE ; MA # ( 珞 → 珞 ) CJK COMPATIBILITY IDEOGRAPH-F917 → CJK UNIFIED IDEOGRAPH-73DE #
+
+F9CC ; 7409 ; MA # ( 琉 → 琉 ) CJK COMPATIBILITY IDEOGRAPH-F9CC → CJK UNIFIED IDEOGRAPH-7409 #
+
+F9E4 ; 7406 ; MA # ( 理 → 理 ) CJK COMPATIBILITY IDEOGRAPH-F9E4 → CJK UNIFIED IDEOGRAPH-7406 #
+
+FA4A ; 7422 ; MA # ( 琢 → 琢 ) CJK COMPATIBILITY IDEOGRAPH-FA4A → CJK UNIFIED IDEOGRAPH-7422 #
+
+2F92E ; 7447 ; MA # ( 瑇 → 瑇 ) CJK COMPATIBILITY IDEOGRAPH-2F92E → CJK UNIFIED IDEOGRAPH-7447 #
+
+2F92F ; 745C ; MA # ( 瑜 → 瑜 ) CJK COMPATIBILITY IDEOGRAPH-2F92F → CJK UNIFIED IDEOGRAPH-745C #
+
+F9AE ; 7469 ; MA # ( 瑩 → 瑩 ) CJK COMPATIBILITY IDEOGRAPH-F9AE → CJK UNIFIED IDEOGRAPH-7469 #
+
+FAA1 ; 7471 ; MA # ( 瑱 → 瑱 ) CJK COMPATIBILITY IDEOGRAPH-FAA1 → CJK UNIFIED IDEOGRAPH-7471 #
+2F930 ; 7471 ; MA # ( 瑱 → 瑱 ) CJK COMPATIBILITY IDEOGRAPH-2F930 → CJK UNIFIED IDEOGRAPH-7471 #
+
+2F931 ; 7485 ; MA # ( 璅 → 璅 ) CJK COMPATIBILITY IDEOGRAPH-2F931 → CJK UNIFIED IDEOGRAPH-7485 #
+
+F994 ; 7489 ; MA # ( 璉 → 璉 ) CJK COMPATIBILITY IDEOGRAPH-F994 → CJK UNIFIED IDEOGRAPH-7489 #
+
+F9EF ; 7498 ; MA # ( 璘 → 璘 ) CJK COMPATIBILITY IDEOGRAPH-F9EF → CJK UNIFIED IDEOGRAPH-7498 #
+
+2F932 ; 74CA ; MA # ( 瓊 → 瓊 ) CJK COMPATIBILITY IDEOGRAPH-2F932 → CJK UNIFIED IDEOGRAPH-74CA #
+
+2F60 ; 74DC ; MA #* ( ⽠ → 瓜 ) KANGXI RADICAL MELON → CJK UNIFIED IDEOGRAPH-74DC #
+
+2F61 ; 74E6 ; MA #* ( ⽡ → 瓦 ) KANGXI RADICAL TILE → CJK UNIFIED IDEOGRAPH-74E6 #
+
+2F933 ; 3F1B ; MA # ( 㼛 → 㼛 ) CJK COMPATIBILITY IDEOGRAPH-2F933 → CJK UNIFIED IDEOGRAPH-3F1B #
+
+FAA2 ; 7506 ; MA # ( 甆 → 甆 ) CJK COMPATIBILITY IDEOGRAPH-FAA2 → CJK UNIFIED IDEOGRAPH-7506 #
+
+2F62 ; 7518 ; MA #* ( ⽢ → 甘 ) KANGXI RADICAL SWEET → CJK UNIFIED IDEOGRAPH-7518 #
+
+2F63 ; 751F ; MA #* ( ⽣ → 生 ) KANGXI RADICAL LIFE → CJK UNIFIED IDEOGRAPH-751F #
+
+2F934 ; 7524 ; MA # ( 甤 → 甤 ) CJK COMPATIBILITY IDEOGRAPH-2F934 → CJK UNIFIED IDEOGRAPH-7524 #
+
+2F64 ; 7528 ; MA #* ( ⽤ → 用 ) KANGXI RADICAL USE → CJK UNIFIED IDEOGRAPH-7528 #
+
+2F65 ; 7530 ; MA #* ( ⽥ → 田 ) KANGXI RADICAL FIELD → CJK UNIFIED IDEOGRAPH-7530 #
+
+FAA3 ; 753B ; MA # ( 画 → 画 ) CJK COMPATIBILITY IDEOGRAPH-FAA3 → CJK UNIFIED IDEOGRAPH-753B #
+
+2F936 ; 753E ; MA # ( 甾 → 甾 ) CJK COMPATIBILITY IDEOGRAPH-2F936 → CJK UNIFIED IDEOGRAPH-753E #
+
+2F935 ; 24C36 ; MA # ( 𤰶 → 𤰶 ) CJK COMPATIBILITY IDEOGRAPH-2F935 → CJK UNIFIED IDEOGRAPH-24C36 #
+
+F9CD ; 7559 ; MA # ( 留 → 留 ) CJK COMPATIBILITY IDEOGRAPH-F9CD → CJK UNIFIED IDEOGRAPH-7559 #
+
+F976 ; 7565 ; MA # ( 略 → 略 ) CJK COMPATIBILITY IDEOGRAPH-F976 → CJK UNIFIED IDEOGRAPH-7565 #
+
+F962 ; 7570 ; MA # ( 異 → 異 ) CJK COMPATIBILITY IDEOGRAPH-F962 → CJK UNIFIED IDEOGRAPH-7570 #
+2F938 ; 7570 ; MA # ( 異 → 異 ) CJK COMPATIBILITY IDEOGRAPH-2F938 → CJK UNIFIED IDEOGRAPH-7570 #
+
+2F937 ; 24C92 ; MA # ( 𤲒 → 𤲒 ) CJK COMPATIBILITY IDEOGRAPH-2F937 → CJK UNIFIED IDEOGRAPH-24C92 #
+
+2F66 ; 758B ; MA #* ( ⽦ → 疋 ) KANGXI RADICAL BOLT OF CLOTH → CJK UNIFIED IDEOGRAPH-758B #
+
+2F67 ; 7592 ; MA #* ( ⽧ → 疒 ) KANGXI RADICAL SICKNESS → CJK UNIFIED IDEOGRAPH-7592 #
+
+F9E5 ; 75E2 ; MA # ( 痢 → 痢 ) CJK COMPATIBILITY IDEOGRAPH-F9E5 → CJK UNIFIED IDEOGRAPH-75E2 #
+
+2F93A ; 7610 ; MA # ( 瘐 → 瘐 ) CJK COMPATIBILITY IDEOGRAPH-2F93A → CJK UNIFIED IDEOGRAPH-7610 #
+
+FAA5 ; 761F ; MA # ( 瘟 → 瘟 ) CJK COMPATIBILITY IDEOGRAPH-FAA5 → CJK UNIFIED IDEOGRAPH-761F #
+
+FAA4 ; 761D ; MA # ( 瘝 → 瘝 ) CJK COMPATIBILITY IDEOGRAPH-FAA4 → CJK UNIFIED IDEOGRAPH-761D #
+
+F9C1 ; 7642 ; MA # ( 療 → 療 ) CJK COMPATIBILITY IDEOGRAPH-F9C1 → CJK UNIFIED IDEOGRAPH-7642 #
+
+F90E ; 7669 ; MA # ( 癩 → 癩 ) CJK COMPATIBILITY IDEOGRAPH-F90E → CJK UNIFIED IDEOGRAPH-7669 #
+
+2F68 ; 7676 ; MA #* ( ⽨ → 癶 ) KANGXI RADICAL DOTTED TENT → CJK UNIFIED IDEOGRAPH-7676 #
+
+2F69 ; 767D ; MA #* ( ⽩ → 白 ) KANGXI RADICAL WHITE → CJK UNIFIED IDEOGRAPH-767D #
+
+2F93B ; 24FA1 ; MA # ( 𤾡 → 𤾡 ) CJK COMPATIBILITY IDEOGRAPH-2F93B → CJK UNIFIED IDEOGRAPH-24FA1 #
+
+2F93C ; 24FB8 ; MA # ( 𤾸 → 𤾸 ) CJK COMPATIBILITY IDEOGRAPH-2F93C → CJK UNIFIED IDEOGRAPH-24FB8 #
+
+2F6A ; 76AE ; MA #* ( ⽪ → 皮 ) KANGXI RADICAL SKIN → CJK UNIFIED IDEOGRAPH-76AE #
+
+2F6B ; 76BF ; MA #* ( ⽫ → 皿 ) KANGXI RADICAL DISH → CJK UNIFIED IDEOGRAPH-76BF #
+
+2F93D ; 25044 ; MA # ( 𥁄 → 𥁄 ) CJK COMPATIBILITY IDEOGRAPH-2F93D → CJK UNIFIED IDEOGRAPH-25044 #
+
+2F93E ; 3FFC ; MA # ( 㿼 → 㿼 ) CJK COMPATIBILITY IDEOGRAPH-2F93E → CJK UNIFIED IDEOGRAPH-3FFC #
+
+FA17 ; 76CA ; MA # ( 益 → 益 ) CJK COMPATIBILITY IDEOGRAPH-FA17 → CJK UNIFIED IDEOGRAPH-76CA #
+FAA6 ; 76CA ; MA # ( 益 → 益 ) CJK COMPATIBILITY IDEOGRAPH-FAA6 → CJK UNIFIED IDEOGRAPH-76CA #
+
+FAA7 ; 76DB ; MA # ( 盛 → 盛 ) CJK COMPATIBILITY IDEOGRAPH-FAA7 → CJK UNIFIED IDEOGRAPH-76DB #
+
+F933 ; 76E7 ; MA # ( 盧 → 盧 ) CJK COMPATIBILITY IDEOGRAPH-F933 → CJK UNIFIED IDEOGRAPH-76E7 #
+
+2F93F ; 4008 ; MA # ( 䀈 → 䀈 ) CJK COMPATIBILITY IDEOGRAPH-2F93F → CJK UNIFIED IDEOGRAPH-4008 #
+
+2F6C ; 76EE ; MA #* ( ⽬ → 目 ) KANGXI RADICAL EYE → CJK UNIFIED IDEOGRAPH-76EE #
+
+FAA8 ; 76F4 ; MA # ( 直 → 直 ) CJK COMPATIBILITY IDEOGRAPH-FAA8 → CJK UNIFIED IDEOGRAPH-76F4 #
+2F940 ; 76F4 ; MA # ( 直 → 直 ) CJK COMPATIBILITY IDEOGRAPH-2F940 → CJK UNIFIED IDEOGRAPH-76F4 #
+
+2F942 ; 250F2 ; MA # ( 𥃲 → 𥃲 ) CJK COMPATIBILITY IDEOGRAPH-2F942 → CJK UNIFIED IDEOGRAPH-250F2 #
+
+2F941 ; 250F3 ; MA # ( 𥃳 → 𥃳 ) CJK COMPATIBILITY IDEOGRAPH-2F941 → CJK UNIFIED IDEOGRAPH-250F3 #
+
+F96D ; 7701 ; MA # ( 省 → 省 ) CJK COMPATIBILITY IDEOGRAPH-F96D → CJK UNIFIED IDEOGRAPH-7701 #
+
+FAD3 ; 4018 ; MA # ( 䀘 → 䀘 ) CJK COMPATIBILITY IDEOGRAPH-FAD3 → CJK UNIFIED IDEOGRAPH-4018 #
+
+2F943 ; 25119 ; MA # ( 𥄙 → 𥄙 ) CJK COMPATIBILITY IDEOGRAPH-2F943 → CJK UNIFIED IDEOGRAPH-25119 #
+
+2F945 ; 771E ; MA # ( 眞 → 眞 ) CJK COMPATIBILITY IDEOGRAPH-2F945 → CJK UNIFIED IDEOGRAPH-771E #
+
+2F946 ; 771F ; MA # ( 真 → 真 ) CJK COMPATIBILITY IDEOGRAPH-2F946 → CJK UNIFIED IDEOGRAPH-771F #
+2F947 ; 771F ; MA # ( 真 → 真 ) CJK COMPATIBILITY IDEOGRAPH-2F947 → CJK UNIFIED IDEOGRAPH-771F #
+
+2F944 ; 25133 ; MA # ( 𥄳 → 𥄳 ) CJK COMPATIBILITY IDEOGRAPH-2F944 → CJK UNIFIED IDEOGRAPH-25133 #
+
+FAAA ; 7740 ; MA # ( 着 → 着 ) CJK COMPATIBILITY IDEOGRAPH-FAAA → CJK UNIFIED IDEOGRAPH-7740 #
+
+FAA9 ; 774A ; MA # ( 睊 → 睊 ) CJK COMPATIBILITY IDEOGRAPH-FAA9 → CJK UNIFIED IDEOGRAPH-774A #
+2F948 ; 774A ; MA # ( 睊 → 睊 ) CJK COMPATIBILITY IDEOGRAPH-2F948 → CJK UNIFIED IDEOGRAPH-774A #
+
+9FC3 ; 4039 ; MA # ( 鿃 → 䀹 ) CJK UNIFIED IDEOGRAPH-9FC3 → CJK UNIFIED IDEOGRAPH-4039 # →䀹→
+FAD4 ; 4039 ; MA # ( 䀹 → 䀹 ) CJK COMPATIBILITY IDEOGRAPH-FAD4 → CJK UNIFIED IDEOGRAPH-4039 #
+2F949 ; 4039 ; MA # ( 䀹 → 䀹 ) CJK COMPATIBILITY IDEOGRAPH-2F949 → CJK UNIFIED IDEOGRAPH-4039 #
+
+6663 ; 403F ; MA # ( 晣 → 䀿 ) CJK UNIFIED IDEOGRAPH-6663 → CJK UNIFIED IDEOGRAPH-403F #
+
+2F94B ; 4046 ; MA # ( 䁆 → 䁆 ) CJK COMPATIBILITY IDEOGRAPH-2F94B → CJK UNIFIED IDEOGRAPH-4046 #
+
+2F94A ; 778B ; MA # ( 瞋 → 瞋 ) CJK COMPATIBILITY IDEOGRAPH-2F94A → CJK UNIFIED IDEOGRAPH-778B #
+
+FAD5 ; 25249 ; MA # ( 𥉉 → 𥉉 ) CJK COMPATIBILITY IDEOGRAPH-FAD5 → CJK UNIFIED IDEOGRAPH-25249 #
+
+FA9D ; 77A7 ; MA # ( 瞧 → 瞧 ) CJK COMPATIBILITY IDEOGRAPH-FA9D → CJK UNIFIED IDEOGRAPH-77A7 #
+
+2F6D ; 77DB ; MA #* ( ⽭ → 矛 ) KANGXI RADICAL SPEAR → CJK UNIFIED IDEOGRAPH-77DB #
+
+2F6E ; 77E2 ; MA #* ( ⽮ → 矢 ) KANGXI RADICAL ARROW → CJK UNIFIED IDEOGRAPH-77E2 #
+
+2F6F ; 77F3 ; MA #* ( ⽯ → 石 ) KANGXI RADICAL STONE → CJK UNIFIED IDEOGRAPH-77F3 #
+
+2F94C ; 4096 ; MA # ( 䂖 → 䂖 ) CJK COMPATIBILITY IDEOGRAPH-2F94C → CJK UNIFIED IDEOGRAPH-4096 #
+
+2F94D ; 2541D ; MA # ( 𥐝 → 𥐝 ) CJK COMPATIBILITY IDEOGRAPH-2F94D → CJK UNIFIED IDEOGRAPH-2541D #
+
+784F ; 7814 ; MA # ( 硏 → 研 ) CJK UNIFIED IDEOGRAPH-784F → CJK UNIFIED IDEOGRAPH-7814 #
+
+2F94E ; 784E ; MA # ( 硎 → 硎 ) CJK COMPATIBILITY IDEOGRAPH-2F94E → CJK UNIFIED IDEOGRAPH-784E #
+
+F9CE ; 786B ; MA # ( 硫 → 硫 ) CJK COMPATIBILITY IDEOGRAPH-F9CE → CJK UNIFIED IDEOGRAPH-786B #
+
+F93B ; 788C ; MA # ( 碌 → 碌 ) CJK COMPATIBILITY IDEOGRAPH-F93B → CJK UNIFIED IDEOGRAPH-788C #
+2F94F ; 788C ; MA # ( 碌 → 碌 ) CJK COMPATIBILITY IDEOGRAPH-2F94F → CJK UNIFIED IDEOGRAPH-788C #
+
+FA4B ; 7891 ; MA # ( 碑 → 碑 ) CJK COMPATIBILITY IDEOGRAPH-FA4B → CJK UNIFIED IDEOGRAPH-7891 #
+
+F947 ; 78CA ; MA # ( 磊 → 磊 ) CJK COMPATIBILITY IDEOGRAPH-F947 → CJK UNIFIED IDEOGRAPH-78CA #
+
+FAAB ; 78CC ; MA # ( 磌 → 磌 ) CJK COMPATIBILITY IDEOGRAPH-FAAB → CJK UNIFIED IDEOGRAPH-78CC #
+2F950 ; 78CC ; MA # ( 磌 → 磌 ) CJK COMPATIBILITY IDEOGRAPH-2F950 → CJK UNIFIED IDEOGRAPH-78CC #
+
+F964 ; 78FB ; MA # ( 磻 → 磻 ) CJK COMPATIBILITY IDEOGRAPH-F964 → CJK UNIFIED IDEOGRAPH-78FB #
+
+2F951 ; 40E3 ; MA # ( 䃣 → 䃣 ) CJK COMPATIBILITY IDEOGRAPH-2F951 → CJK UNIFIED IDEOGRAPH-40E3 #
+
+F985 ; 792A ; MA # ( 礪 → 礪 ) CJK COMPATIBILITY IDEOGRAPH-F985 → CJK UNIFIED IDEOGRAPH-792A #
+
+2F70 ; 793A ; MA #* ( ⽰ → 示 ) KANGXI RADICAL SPIRIT → CJK UNIFIED IDEOGRAPH-793A #
+
+2EAD ; 793B ; MA #* ( ⺭ → 礻 ) CJK RADICAL SPIRIT TWO → CJK UNIFIED IDEOGRAPH-793B #
+
+FA18 ; 793C ; MA # ( 礼 → 礼 ) CJK COMPATIBILITY IDEOGRAPH-FA18 → CJK UNIFIED IDEOGRAPH-793C #
+
+FA4C ; 793E ; MA # ( 社 → 社 ) CJK COMPATIBILITY IDEOGRAPH-FA4C → CJK UNIFIED IDEOGRAPH-793E #
+
+FA4E ; 7948 ; MA # ( 祈 → 祈 ) CJK COMPATIBILITY IDEOGRAPH-FA4E → CJK UNIFIED IDEOGRAPH-7948 #
+
+FA4D ; 7949 ; MA # ( 祉 → 祉 ) CJK COMPATIBILITY IDEOGRAPH-FA4D → CJK UNIFIED IDEOGRAPH-7949 #
+
+2F952 ; 25626 ; MA # ( 𥘦 → 𥘦 ) CJK COMPATIBILITY IDEOGRAPH-2F952 → CJK UNIFIED IDEOGRAPH-25626 #
+
+FA4F ; 7950 ; MA # ( 祐 → 祐 ) CJK COMPATIBILITY IDEOGRAPH-FA4F → CJK UNIFIED IDEOGRAPH-7950 #
+
+FA50 ; 7956 ; MA # ( 祖 → 祖 ) CJK COMPATIBILITY IDEOGRAPH-FA50 → CJK UNIFIED IDEOGRAPH-7956 #
+2F953 ; 7956 ; MA # ( 祖 → 祖 ) CJK COMPATIBILITY IDEOGRAPH-2F953 → CJK UNIFIED IDEOGRAPH-7956 #
+
+FA51 ; 795D ; MA # ( 祝 → 祝 ) CJK COMPATIBILITY IDEOGRAPH-FA51 → CJK UNIFIED IDEOGRAPH-795D #
+
+FA19 ; 795E ; MA # ( 神 → 神 ) CJK COMPATIBILITY IDEOGRAPH-FA19 → CJK UNIFIED IDEOGRAPH-795E #
+
+FA1A ; 7965 ; MA # ( 祥 → 祥 ) CJK COMPATIBILITY IDEOGRAPH-FA1A → CJK UNIFIED IDEOGRAPH-7965 #
+
+FA61 ; 8996 ; MA # ( 視 → 視 ) CJK COMPATIBILITY IDEOGRAPH-FA61 → CJK UNIFIED IDEOGRAPH-8996 #
+FAB8 ; 8996 ; MA # ( 視 → 視 ) CJK COMPATIBILITY IDEOGRAPH-FAB8 → CJK UNIFIED IDEOGRAPH-8996 #
+
+F93C ; 797F ; MA # ( 祿 → 祿 ) CJK COMPATIBILITY IDEOGRAPH-F93C → CJK UNIFIED IDEOGRAPH-797F #
+
+2F954 ; 2569A ; MA # ( 𥚚 → 𥚚 ) CJK COMPATIBILITY IDEOGRAPH-2F954 → CJK UNIFIED IDEOGRAPH-2569A #
+
+FA52 ; 798D ; MA # ( 禍 → 禍 ) CJK COMPATIBILITY IDEOGRAPH-FA52 → CJK UNIFIED IDEOGRAPH-798D #
+
+FA53 ; 798E ; MA # ( 禎 → 禎 ) CJK COMPATIBILITY IDEOGRAPH-FA53 → CJK UNIFIED IDEOGRAPH-798E #
+
+FA1B ; 798F ; MA # ( 福 → 福 ) CJK COMPATIBILITY IDEOGRAPH-FA1B → CJK UNIFIED IDEOGRAPH-798F #
+2F956 ; 798F ; MA # ( 福 → 福 ) CJK COMPATIBILITY IDEOGRAPH-2F956 → CJK UNIFIED IDEOGRAPH-798F #
+
+2F955 ; 256C5 ; MA # ( 𥛅 → 𥛅 ) CJK COMPATIBILITY IDEOGRAPH-2F955 → CJK UNIFIED IDEOGRAPH-256C5 #
+
+F9B6 ; 79AE ; MA # ( 禮 → 禮 ) CJK COMPATIBILITY IDEOGRAPH-F9B6 → CJK UNIFIED IDEOGRAPH-79AE #
+
+2F71 ; 79B8 ; MA #* ( ⽱ → 禸 ) KANGXI RADICAL TRACK → CJK UNIFIED IDEOGRAPH-79B8 #
+
+2F72 ; 79BE ; MA #* ( ⽲ → 禾 ) KANGXI RADICAL GRAIN → CJK UNIFIED IDEOGRAPH-79BE #
+
+F995 ; 79CA ; MA # ( 秊 → 秊 ) CJK COMPATIBILITY IDEOGRAPH-F995 → CJK UNIFIED IDEOGRAPH-79CA #
+
+2F958 ; 412F ; MA # ( 䄯 → 䄯 ) CJK COMPATIBILITY IDEOGRAPH-2F958 → CJK UNIFIED IDEOGRAPH-412F #
+
+2F957 ; 79EB ; MA # ( 秫 → 秫 ) CJK COMPATIBILITY IDEOGRAPH-2F957 → CJK UNIFIED IDEOGRAPH-79EB #
+
+F956 ; 7A1C ; MA # ( 稜 → 稜 ) CJK COMPATIBILITY IDEOGRAPH-F956 → CJK UNIFIED IDEOGRAPH-7A1C #
+
+2F95A ; 7A4A ; MA # ( 穊 → 穊 ) CJK COMPATIBILITY IDEOGRAPH-2F95A → CJK UNIFIED IDEOGRAPH-7A4A #
+
+FA54 ; 7A40 ; MA # ( 穀 → 穀 ) CJK COMPATIBILITY IDEOGRAPH-FA54 → CJK UNIFIED IDEOGRAPH-7A40 #
+2F959 ; 7A40 ; MA # ( 穀 → 穀 ) CJK COMPATIBILITY IDEOGRAPH-2F959 → CJK UNIFIED IDEOGRAPH-7A40 #
+
+2F95B ; 7A4F ; MA # ( 穏 → 穏 ) CJK COMPATIBILITY IDEOGRAPH-2F95B → CJK UNIFIED IDEOGRAPH-7A4F #
+
+2F73 ; 7A74 ; MA #* ( ⽳ → 穴 ) KANGXI RADICAL CAVE → CJK UNIFIED IDEOGRAPH-7A74 #
+
+FA55 ; 7A81 ; MA # ( 突 → 突 ) CJK COMPATIBILITY IDEOGRAPH-FA55 → CJK UNIFIED IDEOGRAPH-7A81 #
+
+2F95C ; 2597C ; MA # ( 𥥼 → 𥥼 ) CJK COMPATIBILITY IDEOGRAPH-2F95C → CJK UNIFIED IDEOGRAPH-2597C #
+
+FAAC ; 7AB1 ; MA # ( 窱 → 窱 ) CJK COMPATIBILITY IDEOGRAPH-FAAC → CJK UNIFIED IDEOGRAPH-7AB1 #
+
+F9F7 ; 7ACB ; MA # ( 立 → 立 ) CJK COMPATIBILITY IDEOGRAPH-F9F7 → CJK UNIFIED IDEOGRAPH-7ACB #
+2F74 ; 7ACB ; MA #* ( ⽴ → 立 ) KANGXI RADICAL STAND → CJK UNIFIED IDEOGRAPH-7ACB #
+
+2EEF ; 7ADC ; MA #* ( ⻯ → 竜 ) CJK RADICAL J-SIMPLIFIED DRAGON → CJK UNIFIED IDEOGRAPH-7ADC #
+
+2F95D ; 25AA7 ; MA # ( 𥪧 → 𥪧 ) CJK COMPATIBILITY IDEOGRAPH-2F95D → CJK UNIFIED IDEOGRAPH-25AA7 #
+2F95E ; 25AA7 ; MA # ( 𥪧 → 𥪧 ) CJK COMPATIBILITY IDEOGRAPH-2F95E → CJK UNIFIED IDEOGRAPH-25AA7 #
+
+2F95F ; 7AEE ; MA # ( 竮 → 竮 ) CJK COMPATIBILITY IDEOGRAPH-2F95F → CJK UNIFIED IDEOGRAPH-7AEE #
+
+2F75 ; 7AF9 ; MA #* ( ⽵ → 竹 ) KANGXI RADICAL BAMBOO → CJK UNIFIED IDEOGRAPH-7AF9 #
+
+F9F8 ; 7B20 ; MA # ( 笠 → 笠 ) CJK COMPATIBILITY IDEOGRAPH-F9F8 → CJK UNIFIED IDEOGRAPH-7B20 #
+
+FA56 ; 7BC0 ; MA # ( 節 → 節 ) CJK COMPATIBILITY IDEOGRAPH-FA56 → CJK UNIFIED IDEOGRAPH-7BC0 #
+FAAD ; 7BC0 ; MA # ( 節 → 節 ) CJK COMPATIBILITY IDEOGRAPH-FAAD → CJK UNIFIED IDEOGRAPH-7BC0 #
+
+2F960 ; 4202 ; MA # ( 䈂 → 䈂 ) CJK COMPATIBILITY IDEOGRAPH-2F960 → CJK UNIFIED IDEOGRAPH-4202 #
+
+2F961 ; 25BAB ; MA # ( 𥮫 → 𥮫 ) CJK COMPATIBILITY IDEOGRAPH-2F961 → CJK UNIFIED IDEOGRAPH-25BAB #
+
+2F962 ; 7BC6 ; MA # ( 篆 → 篆 ) CJK COMPATIBILITY IDEOGRAPH-2F962 → CJK UNIFIED IDEOGRAPH-7BC6 #
+
+2F964 ; 4227 ; MA # ( 䈧 → 䈧 ) CJK COMPATIBILITY IDEOGRAPH-2F964 → CJK UNIFIED IDEOGRAPH-4227 #
+
+2F963 ; 7BC9 ; MA # ( 築 → 築 ) CJK COMPATIBILITY IDEOGRAPH-2F963 → CJK UNIFIED IDEOGRAPH-7BC9 #
+
+2F965 ; 25C80 ; MA # ( 𥲀 → 𥲀 ) CJK COMPATIBILITY IDEOGRAPH-2F965 → CJK UNIFIED IDEOGRAPH-25C80 #
+
+FAD6 ; 25CD0 ; MA # ( 𥳐 → 𥳐 ) CJK COMPATIBILITY IDEOGRAPH-FAD6 → CJK UNIFIED IDEOGRAPH-25CD0 #
+
+F9A6 ; 7C3E ; MA # ( 簾 → 簾 ) CJK COMPATIBILITY IDEOGRAPH-F9A6 → CJK UNIFIED IDEOGRAPH-7C3E #
+
+F944 ; 7C60 ; MA # ( 籠 → 籠 ) CJK COMPATIBILITY IDEOGRAPH-F944 → CJK UNIFIED IDEOGRAPH-7C60 #
+
+2F76 ; 7C73 ; MA #* ( ⽶ → 米 ) KANGXI RADICAL RICE → CJK UNIFIED IDEOGRAPH-7C73 #
+
+FAAE ; 7C7B ; MA # ( 类 → 类 ) CJK COMPATIBILITY IDEOGRAPH-FAAE → CJK UNIFIED IDEOGRAPH-7C7B #
+
+F9F9 ; 7C92 ; MA # ( 粒 → 粒 ) CJK COMPATIBILITY IDEOGRAPH-F9F9 → CJK UNIFIED IDEOGRAPH-7C92 #
+
+FA1D ; 7CBE ; MA # ( 精 → 精 ) CJK COMPATIBILITY IDEOGRAPH-FA1D → CJK UNIFIED IDEOGRAPH-7CBE #
+
+2F966 ; 7CD2 ; MA # ( 糒 → 糒 ) CJK COMPATIBILITY IDEOGRAPH-2F966 → CJK UNIFIED IDEOGRAPH-7CD2 #
+
+FA03 ; 7CD6 ; MA # ( 糖 → 糖 ) CJK COMPATIBILITY IDEOGRAPH-FA03 → CJK UNIFIED IDEOGRAPH-7CD6 #
+
+2F968 ; 7CE8 ; MA # ( 糨 → 糨 ) CJK COMPATIBILITY IDEOGRAPH-2F968 → CJK UNIFIED IDEOGRAPH-7CE8 #
+
+2F967 ; 42A0 ; MA # ( 䊠 → 䊠 ) CJK COMPATIBILITY IDEOGRAPH-2F967 → CJK UNIFIED IDEOGRAPH-42A0 #
+
+2F969 ; 7CE3 ; MA # ( 糣 → 糣 ) CJK COMPATIBILITY IDEOGRAPH-2F969 → CJK UNIFIED IDEOGRAPH-7CE3 #
+
+F97B ; 7CE7 ; MA # ( 糧 → 糧 ) CJK COMPATIBILITY IDEOGRAPH-F97B → CJK UNIFIED IDEOGRAPH-7CE7 #
+
+2F77 ; 7CF8 ; MA #* ( ⽷ → 糸 ) KANGXI RADICAL SILK → CJK UNIFIED IDEOGRAPH-7CF8 #
+
+2EAF ; 7CF9 ; MA #* ( ⺯ → 糹 ) CJK RADICAL SILK → CJK UNIFIED IDEOGRAPH-7CF9 #
+
+2F96B ; 25F86 ; MA # ( 𥾆 → 𥾆 ) CJK COMPATIBILITY IDEOGRAPH-2F96B → CJK UNIFIED IDEOGRAPH-25F86 #
+
+2F96A ; 7D00 ; MA # ( 紀 → 紀 ) CJK COMPATIBILITY IDEOGRAPH-2F96A → CJK UNIFIED IDEOGRAPH-7D00 #
+
+F9CF ; 7D10 ; MA # ( 紐 → 紐 ) CJK COMPATIBILITY IDEOGRAPH-F9CF → CJK UNIFIED IDEOGRAPH-7D10 #
+
+F96A ; 7D22 ; MA # ( 索 → 索 ) CJK COMPATIBILITY IDEOGRAPH-F96A → CJK UNIFIED IDEOGRAPH-7D22 #
+
+F94F ; 7D2F ; MA # ( 累 → 累 ) CJK COMPATIBILITY IDEOGRAPH-F94F → CJK UNIFIED IDEOGRAPH-7D2F #
+
+7D76 ; 7D55 ; MA # ( 絶 → 絕 ) CJK UNIFIED IDEOGRAPH-7D76 → CJK UNIFIED IDEOGRAPH-7D55 #
+
+2F96C ; 7D63 ; MA # ( 絣 → 絣 ) CJK COMPATIBILITY IDEOGRAPH-2F96C → CJK UNIFIED IDEOGRAPH-7D63 #
+
+FAAF ; 7D5B ; MA # ( 絛 → 絛 ) CJK COMPATIBILITY IDEOGRAPH-FAAF → CJK UNIFIED IDEOGRAPH-7D5B #
+
+F93D ; 7DA0 ; MA # ( 綠 → 綠 ) CJK COMPATIBILITY IDEOGRAPH-F93D → CJK UNIFIED IDEOGRAPH-7DA0 #
+
+F957 ; 7DBE ; MA # ( 綾 → 綾 ) CJK COMPATIBILITY IDEOGRAPH-F957 → CJK UNIFIED IDEOGRAPH-7DBE #
+
+2F96E ; 7DC7 ; MA # ( 緇 → 緇 ) CJK COMPATIBILITY IDEOGRAPH-2F96E → CJK UNIFIED IDEOGRAPH-7DC7 #
+
+F996 ; 7DF4 ; MA # ( 練 → 練 ) CJK COMPATIBILITY IDEOGRAPH-F996 → CJK UNIFIED IDEOGRAPH-7DF4 #
+FA57 ; 7DF4 ; MA # ( 練 → 練 ) CJK COMPATIBILITY IDEOGRAPH-FA57 → CJK UNIFIED IDEOGRAPH-7DF4 #
+FAB0 ; 7DF4 ; MA # ( 練 → 練 ) CJK COMPATIBILITY IDEOGRAPH-FAB0 → CJK UNIFIED IDEOGRAPH-7DF4 #
+
+2F96F ; 7E02 ; MA # ( 縂 → 縂 ) CJK COMPATIBILITY IDEOGRAPH-2F96F → CJK UNIFIED IDEOGRAPH-7E02 #
+
+2F96D ; 4301 ; MA # ( 䌁 → 䌁 ) CJK COMPATIBILITY IDEOGRAPH-2F96D → CJK UNIFIED IDEOGRAPH-4301 #
+
+FA58 ; 7E09 ; MA # ( 縉 → 縉 ) CJK COMPATIBILITY IDEOGRAPH-FA58 → CJK UNIFIED IDEOGRAPH-7E09 #
+
+F950 ; 7E37 ; MA # ( 縷 → 縷 ) CJK COMPATIBILITY IDEOGRAPH-F950 → CJK UNIFIED IDEOGRAPH-7E37 #
+
+FA59 ; 7E41 ; MA # ( 繁 → 繁 ) CJK COMPATIBILITY IDEOGRAPH-FA59 → CJK UNIFIED IDEOGRAPH-7E41 #
+
+2F970 ; 7E45 ; MA # ( 繅 → 繅 ) CJK COMPATIBILITY IDEOGRAPH-2F970 → CJK UNIFIED IDEOGRAPH-7E45 #
+
+2F898 ; 261DA ; MA # ( 𦇚 → 𦇚 ) CJK COMPATIBILITY IDEOGRAPH-2F898 → CJK UNIFIED IDEOGRAPH-261DA #
+
+2F971 ; 4334 ; MA # ( 䌴 → 䌴 ) CJK COMPATIBILITY IDEOGRAPH-2F971 → CJK UNIFIED IDEOGRAPH-4334 #
+
+2F78 ; 7F36 ; MA #* ( ⽸ → 缶 ) KANGXI RADICAL JAR → CJK UNIFIED IDEOGRAPH-7F36 #
+
+2F972 ; 26228 ; MA # ( 𦈨 → 𦈨 ) CJK COMPATIBILITY IDEOGRAPH-2F972 → CJK UNIFIED IDEOGRAPH-26228 #
+
+FAB1 ; 7F3E ; MA # ( 缾 → 缾 ) CJK COMPATIBILITY IDEOGRAPH-FAB1 → CJK UNIFIED IDEOGRAPH-7F3E #
+
+2F973 ; 26247 ; MA # ( 𦉇 → 𦉇 ) CJK COMPATIBILITY IDEOGRAPH-2F973 → CJK UNIFIED IDEOGRAPH-26247 #
+
+2F79 ; 7F51 ; MA #* ( ⽹ → 网 ) KANGXI RADICAL NET → CJK UNIFIED IDEOGRAPH-7F51 #
+
+2EAB ; 7F52 ; MA #* ( ⺫ → 罒 ) CJK RADICAL EYE → CJK UNIFIED IDEOGRAPH-7F52 #
+2EB2 ; 7F52 ; MA #* ( ⺲ → 罒 ) CJK RADICAL NET TWO → CJK UNIFIED IDEOGRAPH-7F52 #
+
+2EB1 ; 7F53 ; MA #* ( ⺱ → 罓 ) CJK RADICAL NET ONE → CJK UNIFIED IDEOGRAPH-7F53 #
+
+2F974 ; 4359 ; MA # ( 䍙 → 䍙 ) CJK COMPATIBILITY IDEOGRAPH-2F974 → CJK UNIFIED IDEOGRAPH-4359 #
+
+FA5A ; 7F72 ; MA # ( 署 → 署 ) CJK COMPATIBILITY IDEOGRAPH-FA5A → CJK UNIFIED IDEOGRAPH-7F72 #
+
+2F975 ; 262D9 ; MA # ( 𦋙 → 𦋙 ) CJK COMPATIBILITY IDEOGRAPH-2F975 → CJK UNIFIED IDEOGRAPH-262D9 #
+
+F9E6 ; 7F79 ; MA # ( 罹 → 罹 ) CJK COMPATIBILITY IDEOGRAPH-F9E6 → CJK UNIFIED IDEOGRAPH-7F79 #
+
+2F976 ; 7F7A ; MA # ( 罺 → 罺 ) CJK COMPATIBILITY IDEOGRAPH-2F976 → CJK UNIFIED IDEOGRAPH-7F7A #
+
+F90F ; 7F85 ; MA # ( 羅 → 羅 ) CJK COMPATIBILITY IDEOGRAPH-F90F → CJK UNIFIED IDEOGRAPH-7F85 #
+
+2F977 ; 2633E ; MA # ( 𦌾 → 𦌾 ) CJK COMPATIBILITY IDEOGRAPH-2F977 → CJK UNIFIED IDEOGRAPH-2633E #
+
+2F7A ; 7F8A ; MA #* ( ⽺ → 羊 ) KANGXI RADICAL SHEEP → CJK UNIFIED IDEOGRAPH-7F8A #
+
+2F978 ; 7F95 ; MA # ( 羕 → 羕 ) CJK COMPATIBILITY IDEOGRAPH-2F978 → CJK UNIFIED IDEOGRAPH-7F95 #
+
+F9AF ; 7F9A ; MA # ( 羚 → 羚 ) CJK COMPATIBILITY IDEOGRAPH-F9AF → CJK UNIFIED IDEOGRAPH-7F9A #
+
+FA1E ; 7FBD ; MA # ( 羽 → 羽 ) CJK COMPATIBILITY IDEOGRAPH-FA1E → CJK UNIFIED IDEOGRAPH-7FBD #
+2F7B ; 7FBD ; MA #* ( ⽻ → 羽 ) KANGXI RADICAL FEATHER → CJK UNIFIED IDEOGRAPH-7FBD #
+
+2F979 ; 7FFA ; MA # ( 翺 → 翺 ) CJK COMPATIBILITY IDEOGRAPH-2F979 → CJK UNIFIED IDEOGRAPH-7FFA #
+
+F934 ; 8001 ; MA # ( 老 → 老 ) CJK COMPATIBILITY IDEOGRAPH-F934 → CJK UNIFIED IDEOGRAPH-8001 #
+2F7C ; 8001 ; MA #* ( ⽼ → 老 ) KANGXI RADICAL OLD → CJK UNIFIED IDEOGRAPH-8001 #
+
+2EB9 ; 8002 ; MA #* ( ⺹ → 耂 ) CJK RADICAL OLD → CJK UNIFIED IDEOGRAPH-8002 #
+
+FA5B ; 8005 ; MA # ( 者 → 者 ) CJK COMPATIBILITY IDEOGRAPH-FA5B → CJK UNIFIED IDEOGRAPH-8005 #
+FAB2 ; 8005 ; MA # ( 者 → 者 ) CJK COMPATIBILITY IDEOGRAPH-FAB2 → CJK UNIFIED IDEOGRAPH-8005 #
+2F97A ; 8005 ; MA # ( 者 → 者 ) CJK COMPATIBILITY IDEOGRAPH-2F97A → CJK UNIFIED IDEOGRAPH-8005 #
+
+2F7D ; 800C ; MA #* ( ⽽ → 而 ) KANGXI RADICAL AND → CJK UNIFIED IDEOGRAPH-800C #
+
+2F97B ; 264DA ; MA # ( 𦓚 → 𦓚 ) CJK COMPATIBILITY IDEOGRAPH-2F97B → CJK UNIFIED IDEOGRAPH-264DA #
+
+2F7E ; 8012 ; MA #* ( ⽾ → 耒 ) KANGXI RADICAL PLOW → CJK UNIFIED IDEOGRAPH-8012 #
+
+2F97C ; 26523 ; MA # ( 𦔣 → 𦔣 ) CJK COMPATIBILITY IDEOGRAPH-2F97C → CJK UNIFIED IDEOGRAPH-26523 #
+
+2F7F ; 8033 ; MA #* ( ⽿ → 耳 ) KANGXI RADICAL EAR → CJK UNIFIED IDEOGRAPH-8033 #
+
+F9B0 ; 8046 ; MA # ( 聆 → 聆 ) CJK COMPATIBILITY IDEOGRAPH-F9B0 → CJK UNIFIED IDEOGRAPH-8046 #
+
+2F97D ; 8060 ; MA # ( 聠 → 聠 ) CJK COMPATIBILITY IDEOGRAPH-2F97D → CJK UNIFIED IDEOGRAPH-8060 #
+
+2F97E ; 265A8 ; MA # ( 𦖨 → 𦖨 ) CJK COMPATIBILITY IDEOGRAPH-2F97E → CJK UNIFIED IDEOGRAPH-265A8 #
+
+F997 ; 806F ; MA # ( 聯 → 聯 ) CJK COMPATIBILITY IDEOGRAPH-F997 → CJK UNIFIED IDEOGRAPH-806F #
+
+2F97F ; 8070 ; MA # ( 聰 → 聰 ) CJK COMPATIBILITY IDEOGRAPH-2F97F → CJK UNIFIED IDEOGRAPH-8070 #
+
+F945 ; 807E ; MA # ( 聾 → 聾 ) CJK COMPATIBILITY IDEOGRAPH-F945 → CJK UNIFIED IDEOGRAPH-807E #
+
+2F80 ; 807F ; MA #* ( ⾀ → 聿 ) KANGXI RADICAL BRUSH → CJK UNIFIED IDEOGRAPH-807F #
+
+2EBA ; 8080 ; MA #* ( ⺺ → 肀 ) CJK RADICAL BRUSH ONE → CJK UNIFIED IDEOGRAPH-8080 #
+
+2F81 ; 8089 ; MA #* ( ⾁ → 肉 ) KANGXI RADICAL MEAT → CJK UNIFIED IDEOGRAPH-8089 #
+
+F953 ; 808B ; MA # ( 肋 → 肋 ) CJK COMPATIBILITY IDEOGRAPH-F953 → CJK UNIFIED IDEOGRAPH-808B #
+
+2F8D6 ; 80AD ; MA # ( 肭 → 肭 ) CJK COMPATIBILITY IDEOGRAPH-2F8D6 → CJK UNIFIED IDEOGRAPH-80AD #
+
+2F982 ; 80B2 ; MA # ( 育 → 育 ) CJK COMPATIBILITY IDEOGRAPH-2F982 → CJK UNIFIED IDEOGRAPH-80B2 #
+
+2F981 ; 43D5 ; MA # ( 䏕 → 䏕 ) CJK COMPATIBILITY IDEOGRAPH-2F981 → CJK UNIFIED IDEOGRAPH-43D5 #
+
+2F8D7 ; 43D9 ; MA # ( 䏙 → 䏙 ) CJK COMPATIBILITY IDEOGRAPH-2F8D7 → CJK UNIFIED IDEOGRAPH-43D9 #
+
+8141 ; 80FC ; MA # ( 腁 → 胼 ) CJK UNIFIED IDEOGRAPH-8141 → CJK UNIFIED IDEOGRAPH-80FC #
+
+2F983 ; 8103 ; MA # ( 脃 → 脃 ) CJK COMPATIBILITY IDEOGRAPH-2F983 → CJK UNIFIED IDEOGRAPH-8103 #
+
+2F985 ; 813E ; MA # ( 脾 → 脾 ) CJK COMPATIBILITY IDEOGRAPH-2F985 → CJK UNIFIED IDEOGRAPH-813E #
+
+2F984 ; 440B ; MA # ( 䐋 → 䐋 ) CJK COMPATIBILITY IDEOGRAPH-2F984 → CJK UNIFIED IDEOGRAPH-440B #
+
+2F8DA ; 6721 ; MA # ( 朡 → 朡 ) CJK COMPATIBILITY IDEOGRAPH-2F8DA → CJK UNIFIED IDEOGRAPH-6721 #
+
+2F987 ; 267A7 ; MA # ( 𦞧 → 𦞧 ) CJK COMPATIBILITY IDEOGRAPH-2F987 → CJK UNIFIED IDEOGRAPH-267A7 #
+
+2F988 ; 267B5 ; MA # ( 𦞵 → 𦞵 ) CJK COMPATIBILITY IDEOGRAPH-2F988 → CJK UNIFIED IDEOGRAPH-267B5 #
+
+6726 ; 4443 ; MA # ( 朦 → 䑃 ) CJK UNIFIED IDEOGRAPH-6726 → CJK UNIFIED IDEOGRAPH-4443 #
+
+F926 ; 81D8 ; MA # ( 臘 → 臘 ) CJK COMPATIBILITY IDEOGRAPH-F926 → CJK UNIFIED IDEOGRAPH-81D8 #
+
+2F82 ; 81E3 ; MA #* ( ⾂ → 臣 ) KANGXI RADICAL MINISTER → CJK UNIFIED IDEOGRAPH-81E3 #
+
+F9F6 ; 81E8 ; MA # ( 臨 → 臨 ) CJK COMPATIBILITY IDEOGRAPH-F9F6 → CJK UNIFIED IDEOGRAPH-81E8 #
+
+2F83 ; 81EA ; MA #* ( ⾃ → 自 ) KANGXI RADICAL SELF → CJK UNIFIED IDEOGRAPH-81EA #
+
+FA5C ; 81ED ; MA # ( 臭 → 臭 ) CJK COMPATIBILITY IDEOGRAPH-FA5C → CJK UNIFIED IDEOGRAPH-81ED #
+
+2F84 ; 81F3 ; MA #* ( ⾄ → 至 ) KANGXI RADICAL ARRIVE → CJK UNIFIED IDEOGRAPH-81F3 #
+
+2F85 ; 81FC ; MA #* ( ⾅ → 臼 ) KANGXI RADICAL MORTAR → CJK UNIFIED IDEOGRAPH-81FC #
+
+2F893 ; 8201 ; MA # ( 舁 → 舁 ) CJK COMPATIBILITY IDEOGRAPH-2F893 → CJK UNIFIED IDEOGRAPH-8201 #
+2F98B ; 8201 ; MA # ( 舁 → 舁 ) CJK COMPATIBILITY IDEOGRAPH-2F98B → CJK UNIFIED IDEOGRAPH-8201 #
+
+2F98C ; 8204 ; MA # ( 舄 → 舄 ) CJK COMPATIBILITY IDEOGRAPH-2F98C → CJK UNIFIED IDEOGRAPH-8204 #
+
+2F86 ; 820C ; MA #* ( ⾆ → 舌 ) KANGXI RADICAL TONGUE → CJK UNIFIED IDEOGRAPH-820C #
+
+FA6D ; 8218 ; MA # ( 舘 → 舘 ) CJK COMPATIBILITY IDEOGRAPH-FA6D → CJK UNIFIED IDEOGRAPH-8218 #
+
+2F87 ; 821B ; MA #* ( ⾇ → 舛 ) KANGXI RADICAL OPPOSE → CJK UNIFIED IDEOGRAPH-821B #
+
+2F88 ; 821F ; MA #* ( ⾈ → 舟 ) KANGXI RADICAL BOAT → CJK UNIFIED IDEOGRAPH-821F #
+
+2F98E ; 446B ; MA # ( 䑫 → 䑫 ) CJK COMPATIBILITY IDEOGRAPH-2F98E → CJK UNIFIED IDEOGRAPH-446B #
+
+2F89 ; 826E ; MA #* ( ⾉ → 艮 ) KANGXI RADICAL STOPPING → CJK UNIFIED IDEOGRAPH-826E #
+
+F97C ; 826F ; MA # ( 良 → 良 ) CJK COMPATIBILITY IDEOGRAPH-F97C → CJK UNIFIED IDEOGRAPH-826F #
+
+2F8A ; 8272 ; MA #* ( ⾊ → 色 ) KANGXI RADICAL COLOR → CJK UNIFIED IDEOGRAPH-8272 #
+
+2F8B ; 8278 ; MA #* ( ⾋ → 艸 ) KANGXI RADICAL GRASS → CJK UNIFIED IDEOGRAPH-8278 #
+
+FA5D ; 8279 ; MA # ( 艹 → 艹 ) CJK COMPATIBILITY IDEOGRAPH-FA5D → CJK UNIFIED IDEOGRAPH-8279 #
+FA5E ; 8279 ; MA # ( 艹 → 艹 ) CJK COMPATIBILITY IDEOGRAPH-FA5E → CJK UNIFIED IDEOGRAPH-8279 #
+2EBE ; 8279 ; MA #* ( ⺾ → 艹 ) CJK RADICAL GRASS ONE → CJK UNIFIED IDEOGRAPH-8279 #
+2EBF ; 8279 ; MA #* ( ⺿ → 艹 ) CJK RADICAL GRASS TWO → CJK UNIFIED IDEOGRAPH-8279 # →艹→
+2EC0 ; 8279 ; MA #* ( ⻀ → 艹 ) CJK RADICAL GRASS THREE → CJK UNIFIED IDEOGRAPH-8279 # →艹→
+
+2F990 ; 828B ; MA # ( 芋 → 芋 ) CJK COMPATIBILITY IDEOGRAPH-2F990 → CJK UNIFIED IDEOGRAPH-828B #
+
+2F98F ; 8291 ; MA # ( 芑 → 芑 ) CJK COMPATIBILITY IDEOGRAPH-2F98F → CJK UNIFIED IDEOGRAPH-8291 #
+
+2F991 ; 829D ; MA # ( 芝 → 芝 ) CJK COMPATIBILITY IDEOGRAPH-2F991 → CJK UNIFIED IDEOGRAPH-829D #
+
+2F993 ; 82B1 ; MA # ( 花 → 花 ) CJK COMPATIBILITY IDEOGRAPH-2F993 → CJK UNIFIED IDEOGRAPH-82B1 #
+
+2F994 ; 82B3 ; MA # ( 芳 → 芳 ) CJK COMPATIBILITY IDEOGRAPH-2F994 → CJK UNIFIED IDEOGRAPH-82B3 #
+
+2F995 ; 82BD ; MA # ( 芽 → 芽 ) CJK COMPATIBILITY IDEOGRAPH-2F995 → CJK UNIFIED IDEOGRAPH-82BD #
+
+F974 ; 82E5 ; MA # ( 若 → 若 ) CJK COMPATIBILITY IDEOGRAPH-F974 → CJK UNIFIED IDEOGRAPH-82E5 #
+2F998 ; 82E5 ; MA # ( 若 → 若 ) CJK COMPATIBILITY IDEOGRAPH-2F998 → CJK UNIFIED IDEOGRAPH-82E5 #
+
+2F996 ; 82E6 ; MA # ( 苦 → 苦 ) CJK COMPATIBILITY IDEOGRAPH-2F996 → CJK UNIFIED IDEOGRAPH-82E6 #
+
+2F997 ; 26B3C ; MA # ( 𦬼 → 𦬼 ) CJK COMPATIBILITY IDEOGRAPH-2F997 → CJK UNIFIED IDEOGRAPH-26B3C #
+
+F9FE ; 8336 ; MA # ( 茶 → 茶 ) CJK COMPATIBILITY IDEOGRAPH-F9FE → CJK UNIFIED IDEOGRAPH-8336 #
+
+FAB3 ; 8352 ; MA # ( 荒 → 荒 ) CJK COMPATIBILITY IDEOGRAPH-FAB3 → CJK UNIFIED IDEOGRAPH-8352 #
+
+2F99A ; 8363 ; MA # ( 荣 → 荣 ) CJK COMPATIBILITY IDEOGRAPH-2F99A → CJK UNIFIED IDEOGRAPH-8363 #
+
+2F999 ; 831D ; MA # ( 茝 → 茝 ) CJK COMPATIBILITY IDEOGRAPH-2F999 → CJK UNIFIED IDEOGRAPH-831D #
+
+2F99C ; 8323 ; MA # ( 茣 → 茣 ) CJK COMPATIBILITY IDEOGRAPH-2F99C → CJK UNIFIED IDEOGRAPH-8323 #
+
+2F99D ; 83BD ; MA # ( 莽 → 莽 ) CJK COMPATIBILITY IDEOGRAPH-2F99D → CJK UNIFIED IDEOGRAPH-83BD #
+
+2F9A0 ; 8353 ; MA # ( 荓 → 荓 ) CJK COMPATIBILITY IDEOGRAPH-2F9A0 → CJK UNIFIED IDEOGRAPH-8353 #
+
+F93E ; 83C9 ; MA # ( 菉 → 菉 ) CJK COMPATIBILITY IDEOGRAPH-F93E → CJK UNIFIED IDEOGRAPH-83C9 #
+
+2F9A1 ; 83CA ; MA # ( 菊 → 菊 ) CJK COMPATIBILITY IDEOGRAPH-2F9A1 → CJK UNIFIED IDEOGRAPH-83CA #
+
+2F9A2 ; 83CC ; MA # ( 菌 → 菌 ) CJK COMPATIBILITY IDEOGRAPH-2F9A2 → CJK UNIFIED IDEOGRAPH-83CC #
+
+2F9A3 ; 83DC ; MA # ( 菜 → 菜 ) CJK COMPATIBILITY IDEOGRAPH-2F9A3 → CJK UNIFIED IDEOGRAPH-83DC #
+
+2F99E ; 83E7 ; MA # ( 菧 → 菧 ) CJK COMPATIBILITY IDEOGRAPH-2F99E → CJK UNIFIED IDEOGRAPH-83E7 #
+
+FAB4 ; 83EF ; MA # ( 華 → 華 ) CJK COMPATIBILITY IDEOGRAPH-FAB4 → CJK UNIFIED IDEOGRAPH-83EF #
+
+F958 ; 83F1 ; MA # ( 菱 → 菱 ) CJK COMPATIBILITY IDEOGRAPH-F958 → CJK UNIFIED IDEOGRAPH-83F1 #
+
+FA5F ; 8457 ; MA # ( 著 → 著 ) CJK COMPATIBILITY IDEOGRAPH-FA5F → CJK UNIFIED IDEOGRAPH-8457 #
+2F99F ; 8457 ; MA # ( 著 → 著 ) CJK COMPATIBILITY IDEOGRAPH-2F99F → CJK UNIFIED IDEOGRAPH-8457 #
+
+2F9A4 ; 26C36 ; MA # ( 𦰶 → 𦰶 ) CJK COMPATIBILITY IDEOGRAPH-2F9A4 → CJK UNIFIED IDEOGRAPH-26C36 #
+
+2F99B ; 83AD ; MA # ( 莭 → 莭 ) CJK COMPATIBILITY IDEOGRAPH-2F99B → CJK UNIFIED IDEOGRAPH-83AD #
+
+F918 ; 843D ; MA # ( 落 → 落 ) CJK COMPATIBILITY IDEOGRAPH-F918 → CJK UNIFIED IDEOGRAPH-843D #
+
+F96E ; 8449 ; MA # ( 葉 → 葉 ) CJK COMPATIBILITY IDEOGRAPH-F96E → CJK UNIFIED IDEOGRAPH-8449 #
+
+853F ; 848D ; MA # ( 蔿 → 蒍 ) CJK UNIFIED IDEOGRAPH-853F → CJK UNIFIED IDEOGRAPH-848D #
+
+2F9A6 ; 26CD5 ; MA # ( 𦳕 → 𦳕 ) CJK COMPATIBILITY IDEOGRAPH-2F9A6 → CJK UNIFIED IDEOGRAPH-26CD5 #
+
+2F9A5 ; 26D6B ; MA # ( 𦵫 → 𦵫 ) CJK COMPATIBILITY IDEOGRAPH-2F9A5 → CJK UNIFIED IDEOGRAPH-26D6B #
+
+F999 ; 84EE ; MA # ( 蓮 → 蓮 ) CJK COMPATIBILITY IDEOGRAPH-F999 → CJK UNIFIED IDEOGRAPH-84EE #
+
+2F9A8 ; 84F1 ; MA # ( 蓱 → 蓱 ) CJK COMPATIBILITY IDEOGRAPH-2F9A8 → CJK UNIFIED IDEOGRAPH-84F1 #
+
+2F9A9 ; 84F3 ; MA # ( 蓳 → 蓳 ) CJK COMPATIBILITY IDEOGRAPH-2F9A9 → CJK UNIFIED IDEOGRAPH-84F3 #
+
+F9C2 ; 84FC ; MA # ( 蓼 → 蓼 ) CJK COMPATIBILITY IDEOGRAPH-F9C2 → CJK UNIFIED IDEOGRAPH-84FC #
+
+2F9AA ; 8516 ; MA # ( 蔖 → 蔖 ) CJK COMPATIBILITY IDEOGRAPH-2F9AA → CJK UNIFIED IDEOGRAPH-8516 #
+
+2F9A7 ; 452B ; MA # ( 䔫 → 䔫 ) CJK COMPATIBILITY IDEOGRAPH-2F9A7 → CJK UNIFIED IDEOGRAPH-452B #
+
+2F9AC ; 8564 ; MA # ( 蕤 → 蕤 ) CJK COMPATIBILITY IDEOGRAPH-2F9AC → CJK UNIFIED IDEOGRAPH-8564 #
+
+2F9AD ; 26F2C ; MA # ( 𦼬 → 𦼬 ) CJK COMPATIBILITY IDEOGRAPH-2F9AD → CJK UNIFIED IDEOGRAPH-26F2C #
+
+F923 ; 85CD ; MA # ( 藍 → 藍 ) CJK COMPATIBILITY IDEOGRAPH-F923 → CJK UNIFIED IDEOGRAPH-85CD #
+
+2F9AE ; 455D ; MA # ( 䕝 → 䕝 ) CJK COMPATIBILITY IDEOGRAPH-2F9AE → CJK UNIFIED IDEOGRAPH-455D #
+
+2F9B0 ; 26FB1 ; MA # ( 𦾱 → 𦾱 ) CJK COMPATIBILITY IDEOGRAPH-2F9B0 → CJK UNIFIED IDEOGRAPH-26FB1 #
+
+2F9AF ; 4561 ; MA # ( 䕡 → 䕡 ) CJK COMPATIBILITY IDEOGRAPH-2F9AF → CJK UNIFIED IDEOGRAPH-4561 #
+
+F9F0 ; 85FA ; MA # ( 藺 → 藺 ) CJK COMPATIBILITY IDEOGRAPH-F9F0 → CJK UNIFIED IDEOGRAPH-85FA #
+
+F935 ; 8606 ; MA # ( 蘆 → 蘆 ) CJK COMPATIBILITY IDEOGRAPH-F935 → CJK UNIFIED IDEOGRAPH-8606 #
+
+2F9B2 ; 456B ; MA # ( 䕫 → 䕫 ) CJK COMPATIBILITY IDEOGRAPH-2F9B2 → CJK UNIFIED IDEOGRAPH-456B #
+
+FA20 ; 8612 ; MA # ( 蘒 → 蘒 ) CJK COMPATIBILITY IDEOGRAPH-FA20 → CJK UNIFIED IDEOGRAPH-8612 #
+
+F91F ; 862D ; MA # ( 蘭 → 蘭 ) CJK COMPATIBILITY IDEOGRAPH-F91F → CJK UNIFIED IDEOGRAPH-862D #
+
+2F9B1 ; 270D2 ; MA # ( 𧃒 → 𧃒 ) CJK COMPATIBILITY IDEOGRAPH-2F9B1 → CJK UNIFIED IDEOGRAPH-270D2 #
+
+8641 ; 8637 ; MA # ( 虁 → 蘷 ) CJK UNIFIED IDEOGRAPH-8641 → CJK UNIFIED IDEOGRAPH-8637 #
+
+F910 ; 863F ; MA # ( 蘿 → 蘿 ) CJK COMPATIBILITY IDEOGRAPH-F910 → CJK UNIFIED IDEOGRAPH-863F #
+
+2F8C ; 864D ; MA #* ( ⾌ → 虍 ) KANGXI RADICAL TIGER → CJK UNIFIED IDEOGRAPH-864D #
+
+2EC1 ; 864E ; MA #* ( ⻁ → 虎 ) CJK RADICAL TIGER → CJK UNIFIED IDEOGRAPH-864E #
+
+2F9B3 ; 8650 ; MA # ( 虐 → 虐 ) CJK COMPATIBILITY IDEOGRAPH-2F9B3 → CJK UNIFIED IDEOGRAPH-8650 #
+
+F936 ; 865C ; MA # ( 虜 → 虜 ) CJK COMPATIBILITY IDEOGRAPH-F936 → CJK UNIFIED IDEOGRAPH-865C #
+2F9B4 ; 865C ; MA # ( 虜 → 虜 ) CJK COMPATIBILITY IDEOGRAPH-2F9B4 → CJK UNIFIED IDEOGRAPH-865C #
+
+2F9B5 ; 8667 ; MA # ( 虧 → 虧 ) CJK COMPATIBILITY IDEOGRAPH-2F9B5 → CJK UNIFIED IDEOGRAPH-8667 #
+
+2F9B6 ; 8669 ; MA # ( 虩 → 虩 ) CJK COMPATIBILITY IDEOGRAPH-2F9B6 → CJK UNIFIED IDEOGRAPH-8669 #
+
+2F8D ; 866B ; MA #* ( ⾍ → 虫 ) KANGXI RADICAL INSECT → CJK UNIFIED IDEOGRAPH-866B #
+
+2F9B7 ; 86A9 ; MA # ( 蚩 → 蚩 ) CJK COMPATIBILITY IDEOGRAPH-2F9B7 → CJK UNIFIED IDEOGRAPH-86A9 #
+
+2F9B8 ; 8688 ; MA # ( 蚈 → 蚈 ) CJK COMPATIBILITY IDEOGRAPH-2F9B8 → CJK UNIFIED IDEOGRAPH-8688 #
+
+2F9BA ; 86E2 ; MA # ( 蛢 → 蛢 ) CJK COMPATIBILITY IDEOGRAPH-2F9BA → CJK UNIFIED IDEOGRAPH-86E2 #
+
+2F9B9 ; 870E ; MA # ( 蜎 → 蜎 ) CJK COMPATIBILITY IDEOGRAPH-2F9B9 → CJK UNIFIED IDEOGRAPH-870E #
+
+2F9BC ; 8728 ; MA # ( 蜨 → 蜨 ) CJK COMPATIBILITY IDEOGRAPH-2F9BC → CJK UNIFIED IDEOGRAPH-8728 #
+
+2F9BD ; 876B ; MA # ( 蝫 → 蝫 ) CJK COMPATIBILITY IDEOGRAPH-2F9BD → CJK UNIFIED IDEOGRAPH-876B #
+
+2F9C0 ; 87E1 ; MA # ( 蟡 → 蟡 ) CJK COMPATIBILITY IDEOGRAPH-2F9C0 → CJK UNIFIED IDEOGRAPH-87E1 #
+
+FAB5 ; 8779 ; MA # ( 蝹 → 蝹 ) CJK COMPATIBILITY IDEOGRAPH-FAB5 → CJK UNIFIED IDEOGRAPH-8779 #
+2F9BB ; 8779 ; MA # ( 蝹 → 蝹 ) CJK COMPATIBILITY IDEOGRAPH-2F9BB → CJK UNIFIED IDEOGRAPH-8779 #
+
+2F9BE ; 8786 ; MA # ( 螆 → 螆 ) CJK COMPATIBILITY IDEOGRAPH-2F9BE → CJK UNIFIED IDEOGRAPH-8786 #
+
+2F9BF ; 45D7 ; MA # ( 䗗 → 䗗 ) CJK COMPATIBILITY IDEOGRAPH-2F9BF → CJK UNIFIED IDEOGRAPH-45D7 #
+
+2F9AB ; 273CA ; MA # ( 𧏊 → 𧏊 ) CJK COMPATIBILITY IDEOGRAPH-2F9AB → CJK UNIFIED IDEOGRAPH-273CA #
+
+F911 ; 87BA ; MA # ( 螺 → 螺 ) CJK COMPATIBILITY IDEOGRAPH-F911 → CJK UNIFIED IDEOGRAPH-87BA #
+
+2F9C1 ; 8801 ; MA # ( 蠁 → 蠁 ) CJK COMPATIBILITY IDEOGRAPH-2F9C1 → CJK UNIFIED IDEOGRAPH-8801 #
+
+2F9C2 ; 45F9 ; MA # ( 䗹 → 䗹 ) CJK COMPATIBILITY IDEOGRAPH-2F9C2 → CJK UNIFIED IDEOGRAPH-45F9 #
+
+F927 ; 881F ; MA # ( 蠟 → 蠟 ) CJK COMPATIBILITY IDEOGRAPH-F927 → CJK UNIFIED IDEOGRAPH-881F #
+
+2F8E ; 8840 ; MA #* ( ⾎ → 血 ) KANGXI RADICAL BLOOD → CJK UNIFIED IDEOGRAPH-8840 #
+
+FA08 ; 884C ; MA # ( 行 → 行 ) CJK COMPATIBILITY IDEOGRAPH-FA08 → CJK UNIFIED IDEOGRAPH-884C #
+2F8F ; 884C ; MA #* ( ⾏ → 行 ) KANGXI RADICAL WALK ENCLOSURE → CJK UNIFIED IDEOGRAPH-884C #
+
+2F9C3 ; 8860 ; MA # ( 衠 → 衠 ) CJK COMPATIBILITY IDEOGRAPH-2F9C3 → CJK UNIFIED IDEOGRAPH-8860 #
+
+2F9C4 ; 8863 ; MA # ( 衣 → 衣 ) CJK COMPATIBILITY IDEOGRAPH-2F9C4 → CJK UNIFIED IDEOGRAPH-8863 #
+2F90 ; 8863 ; MA #* ( ⾐ → 衣 ) KANGXI RADICAL CLOTHES → CJK UNIFIED IDEOGRAPH-8863 #
+
+2EC2 ; 8864 ; MA #* ( ⻂ → 衤 ) CJK RADICAL CLOTHES → CJK UNIFIED IDEOGRAPH-8864 #
+
+F9A0 ; 88C2 ; MA # ( 裂 → 裂 ) CJK COMPATIBILITY IDEOGRAPH-F9A0 → CJK UNIFIED IDEOGRAPH-88C2 #
+
+2F9C5 ; 27667 ; MA # ( 𧙧 → 𧙧 ) CJK COMPATIBILITY IDEOGRAPH-2F9C5 → CJK UNIFIED IDEOGRAPH-27667 #
+
+F9E7 ; 88CF ; MA # ( 裏 → 裏 ) CJK COMPATIBILITY IDEOGRAPH-F9E7 → CJK UNIFIED IDEOGRAPH-88CF #
+
+2F9C6 ; 88D7 ; MA # ( 裗 → 裗 ) CJK COMPATIBILITY IDEOGRAPH-2F9C6 → CJK UNIFIED IDEOGRAPH-88D7 #
+
+2F9C7 ; 88DE ; MA # ( 裞 → 裞 ) CJK COMPATIBILITY IDEOGRAPH-2F9C7 → CJK UNIFIED IDEOGRAPH-88DE #
+
+F9E8 ; 88E1 ; MA # ( 裡 → 裡 ) CJK COMPATIBILITY IDEOGRAPH-F9E8 → CJK UNIFIED IDEOGRAPH-88E1 #
+
+F912 ; 88F8 ; MA # ( 裸 → 裸 ) CJK COMPATIBILITY IDEOGRAPH-F912 → CJK UNIFIED IDEOGRAPH-88F8 #
+
+2F9C9 ; 88FA ; MA # ( 裺 → 裺 ) CJK COMPATIBILITY IDEOGRAPH-2F9C9 → CJK UNIFIED IDEOGRAPH-88FA #
+
+2F9C8 ; 4635 ; MA # ( 䘵 → 䘵 ) CJK COMPATIBILITY IDEOGRAPH-2F9C8 → CJK UNIFIED IDEOGRAPH-4635 #
+
+FA60 ; 8910 ; MA # ( 褐 → 褐 ) CJK COMPATIBILITY IDEOGRAPH-FA60 → CJK UNIFIED IDEOGRAPH-8910 #
+
+FAB6 ; 8941 ; MA # ( 襁 → 襁 ) CJK COMPATIBILITY IDEOGRAPH-FAB6 → CJK UNIFIED IDEOGRAPH-8941 #
+
+F924 ; 8964 ; MA # ( 襤 → 襤 ) CJK COMPATIBILITY IDEOGRAPH-F924 → CJK UNIFIED IDEOGRAPH-8964 #
+
+2F91 ; 897E ; MA #* ( ⾑ → 襾 ) KANGXI RADICAL WEST → CJK UNIFIED IDEOGRAPH-897E #
+
+2EC4 ; 897F ; MA #* ( ⻄ → 西 ) CJK RADICAL WEST TWO → CJK UNIFIED IDEOGRAPH-897F #
+
+2EC3 ; 8980 ; MA #* ( ⻃ → 覀 ) CJK RADICAL WEST ONE → CJK UNIFIED IDEOGRAPH-8980 #
+
+FAB7 ; 8986 ; MA # ( 覆 → 覆 ) CJK COMPATIBILITY IDEOGRAPH-FAB7 → CJK UNIFIED IDEOGRAPH-8986 #
+
+FA0A ; 898B ; MA # ( 見 → 見 ) CJK COMPATIBILITY IDEOGRAPH-FA0A → CJK UNIFIED IDEOGRAPH-898B #
+2F92 ; 898B ; MA #* ( ⾒ → 見 ) KANGXI RADICAL SEE → CJK UNIFIED IDEOGRAPH-898B #
+
+2F9CB ; 278AE ; MA # ( 𧢮 → 𧢮 ) CJK COMPATIBILITY IDEOGRAPH-2F9CB → CJK UNIFIED IDEOGRAPH-278AE #
+
+2EC5 ; 89C1 ; MA #* ( ⻅ → 见 ) CJK RADICAL C-SIMPLIFIED SEE → CJK UNIFIED IDEOGRAPH-89C1 #
+
+2F93 ; 89D2 ; MA #* ( ⾓ → 角 ) KANGXI RADICAL HORN → CJK UNIFIED IDEOGRAPH-89D2 #
+
+2F94 ; 8A00 ; MA #* ( ⾔ → 言 ) KANGXI RADICAL SPEECH → CJK UNIFIED IDEOGRAPH-8A00 #
+
+2F9CC ; 27966 ; MA # ( 𧥦 → 𧥦 ) CJK COMPATIBILITY IDEOGRAPH-2F9CC → CJK UNIFIED IDEOGRAPH-27966 #
+
+8A7D ; 8A2E ; MA # ( 詽 → 訮 ) CJK UNIFIED IDEOGRAPH-8A7D → CJK UNIFIED IDEOGRAPH-8A2E #
+
+8A1E ; 46B6 ; MA # ( 訞 → 䚶 ) CJK UNIFIED IDEOGRAPH-8A1E → CJK UNIFIED IDEOGRAPH-46B6 #
+
+2F9CD ; 46BE ; MA # ( 䚾 → 䚾 ) CJK COMPATIBILITY IDEOGRAPH-2F9CD → CJK UNIFIED IDEOGRAPH-46BE #
+
+2F9CE ; 46C7 ; MA # ( 䛇 → 䛇 ) CJK COMPATIBILITY IDEOGRAPH-2F9CE → CJK UNIFIED IDEOGRAPH-46C7 #
+
+2F9CF ; 8AA0 ; MA # ( 誠 → 誠 ) CJK COMPATIBILITY IDEOGRAPH-2F9CF → CJK UNIFIED IDEOGRAPH-8AA0 #
+
+F96F ; 8AAA ; MA # ( 說 → 說 ) CJK COMPATIBILITY IDEOGRAPH-F96F → CJK UNIFIED IDEOGRAPH-8AAA #
+F9A1 ; 8AAA ; MA # ( 說 → 說 ) CJK COMPATIBILITY IDEOGRAPH-F9A1 → CJK UNIFIED IDEOGRAPH-8AAA #
+
+FAB9 ; 8ABF ; MA # ( 調 → 調 ) CJK COMPATIBILITY IDEOGRAPH-FAB9 → CJK UNIFIED IDEOGRAPH-8ABF #
+
+FABB ; 8ACB ; MA # ( 請 → 請 ) CJK COMPATIBILITY IDEOGRAPH-FABB → CJK UNIFIED IDEOGRAPH-8ACB #
+
+F97D ; 8AD2 ; MA # ( 諒 → 諒 ) CJK COMPATIBILITY IDEOGRAPH-F97D → CJK UNIFIED IDEOGRAPH-8AD2 #
+
+F941 ; 8AD6 ; MA # ( 論 → 論 ) CJK COMPATIBILITY IDEOGRAPH-F941 → CJK UNIFIED IDEOGRAPH-8AD6 #
+
+FABE ; 8AED ; MA # ( 諭 → 諭 ) CJK COMPATIBILITY IDEOGRAPH-FABE → CJK UNIFIED IDEOGRAPH-8AED #
+2F9D0 ; 8AED ; MA # ( 諭 → 諭 ) CJK COMPATIBILITY IDEOGRAPH-2F9D0 → CJK UNIFIED IDEOGRAPH-8AED #
+
+FA22 ; 8AF8 ; MA # ( 諸 → 諸 ) CJK COMPATIBILITY IDEOGRAPH-FA22 → CJK UNIFIED IDEOGRAPH-8AF8 #
+FABA ; 8AF8 ; MA # ( 諸 → 諸 ) CJK COMPATIBILITY IDEOGRAPH-FABA → CJK UNIFIED IDEOGRAPH-8AF8 #
+
+F95D ; 8AFE ; MA # ( 諾 → 諾 ) CJK COMPATIBILITY IDEOGRAPH-F95D → CJK UNIFIED IDEOGRAPH-8AFE #
+FABD ; 8AFE ; MA # ( 諾 → 諾 ) CJK COMPATIBILITY IDEOGRAPH-FABD → CJK UNIFIED IDEOGRAPH-8AFE #
+
+FA62 ; 8B01 ; MA # ( 謁 → 謁 ) CJK COMPATIBILITY IDEOGRAPH-FA62 → CJK UNIFIED IDEOGRAPH-8B01 #
+FABC ; 8B01 ; MA # ( 謁 → 謁 ) CJK COMPATIBILITY IDEOGRAPH-FABC → CJK UNIFIED IDEOGRAPH-8B01 #
+
+FA63 ; 8B39 ; MA # ( 謹 → 謹 ) CJK COMPATIBILITY IDEOGRAPH-FA63 → CJK UNIFIED IDEOGRAPH-8B39 #
+FABF ; 8B39 ; MA # ( 謹 → 謹 ) CJK COMPATIBILITY IDEOGRAPH-FABF → CJK UNIFIED IDEOGRAPH-8B39 #
+
+F9FC ; 8B58 ; MA # ( 識 → 識 ) CJK COMPATIBILITY IDEOGRAPH-F9FC → CJK UNIFIED IDEOGRAPH-8B58 #
+
+F95A ; 8B80 ; MA # ( 讀 → 讀 ) CJK COMPATIBILITY IDEOGRAPH-F95A → CJK UNIFIED IDEOGRAPH-8B80 #
+
+8B8F ; 8B86 ; MA # ( 讏 → 讆 ) CJK UNIFIED IDEOGRAPH-8B8F → CJK UNIFIED IDEOGRAPH-8B86 #
+
+FAC0 ; 8B8A ; MA # ( 變 → 變 ) CJK COMPATIBILITY IDEOGRAPH-FAC0 → CJK UNIFIED IDEOGRAPH-8B8A #
+2F9D1 ; 8B8A ; MA # ( 變 → 變 ) CJK COMPATIBILITY IDEOGRAPH-2F9D1 → CJK UNIFIED IDEOGRAPH-8B8A #
+
+2EC8 ; 8BA0 ; MA #* ( ⻈ → 讠 ) CJK RADICAL C-SIMPLIFIED SPEECH → CJK UNIFIED IDEOGRAPH-8BA0 #
+
+2F95 ; 8C37 ; MA #* ( ⾕ → 谷 ) KANGXI RADICAL VALLEY → CJK UNIFIED IDEOGRAPH-8C37 #
+
+2F96 ; 8C46 ; MA #* ( ⾖ → 豆 ) KANGXI RADICAL BEAN → CJK UNIFIED IDEOGRAPH-8C46 #
+
+F900 ; 8C48 ; MA # ( 豈 → 豈 ) CJK COMPATIBILITY IDEOGRAPH-F900 → CJK UNIFIED IDEOGRAPH-8C48 #
+
+2F9D2 ; 8C55 ; MA # ( 豕 → 豕 ) CJK COMPATIBILITY IDEOGRAPH-2F9D2 → CJK UNIFIED IDEOGRAPH-8C55 #
+2F97 ; 8C55 ; MA #* ( ⾗ → 豕 ) KANGXI RADICAL PIG → CJK UNIFIED IDEOGRAPH-8C55 #
+
+8C63 ; 8C5C ; MA # ( 豣 → 豜 ) CJK UNIFIED IDEOGRAPH-8C63 → CJK UNIFIED IDEOGRAPH-8C5C #
+
+2F98 ; 8C78 ; MA #* ( ⾘ → 豸 ) KANGXI RADICAL BADGER → CJK UNIFIED IDEOGRAPH-8C78 #
+
+2F9D3 ; 27CA8 ; MA # ( 𧲨 → 𧲨 ) CJK COMPATIBILITY IDEOGRAPH-2F9D3 → CJK UNIFIED IDEOGRAPH-27CA8 #
+
+2F99 ; 8C9D ; MA #* ( ⾙ → 貝 ) KANGXI RADICAL SHELL → CJK UNIFIED IDEOGRAPH-8C9D #
+
+2F9D4 ; 8CAB ; MA # ( 貫 → 貫 ) CJK COMPATIBILITY IDEOGRAPH-2F9D4 → CJK UNIFIED IDEOGRAPH-8CAB #
+
+2F9D5 ; 8CC1 ; MA # ( 賁 → 賁 ) CJK COMPATIBILITY IDEOGRAPH-2F9D5 → CJK UNIFIED IDEOGRAPH-8CC1 #
+
+F948 ; 8CC2 ; MA # ( 賂 → 賂 ) CJK COMPATIBILITY IDEOGRAPH-F948 → CJK UNIFIED IDEOGRAPH-8CC2 #
+
+F903 ; 8CC8 ; MA # ( 賈 → 賈 ) CJK COMPATIBILITY IDEOGRAPH-F903 → CJK UNIFIED IDEOGRAPH-8CC8 #
+
+FA64 ; 8CD3 ; MA # ( 賓 → 賓 ) CJK COMPATIBILITY IDEOGRAPH-FA64 → CJK UNIFIED IDEOGRAPH-8CD3 #
+
+FA65 ; 8D08 ; MA # ( 贈 → 贈 ) CJK COMPATIBILITY IDEOGRAPH-FA65 → CJK UNIFIED IDEOGRAPH-8D08 #
+FAC1 ; 8D08 ; MA # ( 贈 → 贈 ) CJK COMPATIBILITY IDEOGRAPH-FAC1 → CJK UNIFIED IDEOGRAPH-8D08 #
+
+2F9D6 ; 8D1B ; MA # ( 贛 → 贛 ) CJK COMPATIBILITY IDEOGRAPH-2F9D6 → CJK UNIFIED IDEOGRAPH-8D1B #
+
+2EC9 ; 8D1D ; MA #* ( ⻉ → 贝 ) CJK RADICAL C-SIMPLIFIED SHELL → CJK UNIFIED IDEOGRAPH-8D1D #
+
+2F9A ; 8D64 ; MA #* ( ⾚ → 赤 ) KANGXI RADICAL RED → CJK UNIFIED IDEOGRAPH-8D64 #
+
+2F9B ; 8D70 ; MA #* ( ⾛ → 走 ) KANGXI RADICAL RUN → CJK UNIFIED IDEOGRAPH-8D70 #
+
+2F9D7 ; 8D77 ; MA # ( 起 → 起 ) CJK COMPATIBILITY IDEOGRAPH-2F9D7 → CJK UNIFIED IDEOGRAPH-8D77 #
+
+8D86 ; 8D7F ; MA # ( 趆 → 赿 ) CJK UNIFIED IDEOGRAPH-8D86 → CJK UNIFIED IDEOGRAPH-8D7F #
+
+FAD7 ; 27ED3 ; MA # ( 𧻓 → 𧻓 ) CJK COMPATIBILITY IDEOGRAPH-FAD7 → CJK UNIFIED IDEOGRAPH-27ED3 #
+
+2F9D8 ; 27F2F ; MA # ( 𧼯 → 𧼯 ) CJK COMPATIBILITY IDEOGRAPH-2F9D8 → CJK UNIFIED IDEOGRAPH-27F2F #
+
+2F9C ; 8DB3 ; MA #* ( ⾜ → 足 ) KANGXI RADICAL FOOT → CJK UNIFIED IDEOGRAPH-8DB3 #
+
+2F9DA ; 8DCB ; MA # ( 跋 → 跋 ) CJK COMPATIBILITY IDEOGRAPH-2F9DA → CJK UNIFIED IDEOGRAPH-8DCB #
+
+2F9DB ; 8DBC ; MA # ( 趼 → 趼 ) CJK COMPATIBILITY IDEOGRAPH-2F9DB → CJK UNIFIED IDEOGRAPH-8DBC #
+
+8DFA ; 8DE5 ; MA # ( 跺 → 跥 ) CJK UNIFIED IDEOGRAPH-8DFA → CJK UNIFIED IDEOGRAPH-8DE5 #
+
+F937 ; 8DEF ; MA # ( 路 → 路 ) CJK COMPATIBILITY IDEOGRAPH-F937 → CJK UNIFIED IDEOGRAPH-8DEF #
+
+2F9DC ; 8DF0 ; MA # ( 跰 → 跰 ) CJK COMPATIBILITY IDEOGRAPH-2F9DC → CJK UNIFIED IDEOGRAPH-8DF0 #
+
+8E9B ; 8E97 ; MA # ( 躛 → 躗 ) CJK UNIFIED IDEOGRAPH-8E9B → CJK UNIFIED IDEOGRAPH-8E97 #
+
+2F9D ; 8EAB ; MA #* ( ⾝ → 身 ) KANGXI RADICAL BODY → CJK UNIFIED IDEOGRAPH-8EAB #
+
+F902 ; 8ECA ; MA # ( 車 → 車 ) CJK COMPATIBILITY IDEOGRAPH-F902 → CJK UNIFIED IDEOGRAPH-8ECA #
+2F9E ; 8ECA ; MA #* ( ⾞ → 車 ) KANGXI RADICAL CART → CJK UNIFIED IDEOGRAPH-8ECA #
+
+2F9DE ; 8ED4 ; MA # ( 軔 → 軔 ) CJK COMPATIBILITY IDEOGRAPH-2F9DE → CJK UNIFIED IDEOGRAPH-8ED4 #
+
+8F27 ; 8EFF ; MA # ( 輧 → 軿 ) CJK UNIFIED IDEOGRAPH-8F27 → CJK UNIFIED IDEOGRAPH-8EFF #
+
+F998 ; 8F26 ; MA # ( 輦 → 輦 ) CJK COMPATIBILITY IDEOGRAPH-F998 → CJK UNIFIED IDEOGRAPH-8F26 #
+
+F9D7 ; 8F2A ; MA # ( 輪 → 輪 ) CJK COMPATIBILITY IDEOGRAPH-F9D7 → CJK UNIFIED IDEOGRAPH-8F2A #
+
+FAC2 ; 8F38 ; MA # ( 輸 → 輸 ) CJK COMPATIBILITY IDEOGRAPH-FAC2 → CJK UNIFIED IDEOGRAPH-8F38 #
+2F9DF ; 8F38 ; MA # ( 輸 → 輸 ) CJK COMPATIBILITY IDEOGRAPH-2F9DF → CJK UNIFIED IDEOGRAPH-8F38 #
+
+FA07 ; 8F3B ; MA # ( 輻 → 輻 ) CJK COMPATIBILITY IDEOGRAPH-FA07 → CJK UNIFIED IDEOGRAPH-8F3B #
+
+F98D ; 8F62 ; MA # ( 轢 → 轢 ) CJK COMPATIBILITY IDEOGRAPH-F98D → CJK UNIFIED IDEOGRAPH-8F62 #
+
+2ECB ; 8F66 ; MA #* ( ⻋ → 车 ) CJK RADICAL C-SIMPLIFIED CART → CJK UNIFIED IDEOGRAPH-8F66 #
+
+2F9F ; 8F9B ; MA #* ( ⾟ → 辛 ) KANGXI RADICAL BITTER → CJK UNIFIED IDEOGRAPH-8F9B #
+
+2F98D ; 8F9E ; MA # ( 辞 → 辞 ) CJK COMPATIBILITY IDEOGRAPH-2F98D → CJK UNIFIED IDEOGRAPH-8F9E #
+
+F971 ; 8FB0 ; MA # ( 辰 → 辰 ) CJK COMPATIBILITY IDEOGRAPH-F971 → CJK UNIFIED IDEOGRAPH-8FB0 #
+2FA0 ; 8FB0 ; MA #* ( ⾠ → 辰 ) KANGXI RADICAL MORNING → CJK UNIFIED IDEOGRAPH-8FB0 #
+
+2FA1 ; 8FB5 ; MA #* ( ⾡ → 辵 ) KANGXI RADICAL WALK → CJK UNIFIED IDEOGRAPH-8FB5 #
+
+FA66 ; 8FB6 ; MA # ( 辶 → 辶 ) CJK COMPATIBILITY IDEOGRAPH-FA66 → CJK UNIFIED IDEOGRAPH-8FB6 #
+2ECC ; 8FB6 ; MA #* ( ⻌ → 辶 ) CJK RADICAL SIMPLIFIED WALK → CJK UNIFIED IDEOGRAPH-8FB6 #
+2ECD ; 8FB6 ; MA #* ( ⻍ → 辶 ) CJK RADICAL WALK ONE → CJK UNIFIED IDEOGRAPH-8FB6 #
+
+2F881 ; 5DE1 ; MA # ( 巡 → 巡 ) CJK COMPATIBILITY IDEOGRAPH-2F881 → CJK UNIFIED IDEOGRAPH-5DE1 #
+
+F99A ; 9023 ; MA # ( 連 → 連 ) CJK COMPATIBILITY IDEOGRAPH-F99A → CJK UNIFIED IDEOGRAPH-9023 #
+
+FA25 ; 9038 ; MA # ( 逸 → 逸 ) CJK COMPATIBILITY IDEOGRAPH-FA25 → CJK UNIFIED IDEOGRAPH-9038 #
+FA67 ; 9038 ; MA # ( 逸 → 逸 ) CJK COMPATIBILITY IDEOGRAPH-FA67 → CJK UNIFIED IDEOGRAPH-9038 #
+
+FAC3 ; 9072 ; MA # ( 遲 → 遲 ) CJK COMPATIBILITY IDEOGRAPH-FAC3 → CJK UNIFIED IDEOGRAPH-9072 #
+
+F9C3 ; 907C ; MA # ( 遼 → 遼 ) CJK COMPATIBILITY IDEOGRAPH-F9C3 → CJK UNIFIED IDEOGRAPH-907C #
+
+2F9E0 ; 285D2 ; MA # ( 𨗒 → 𨗒 ) CJK COMPATIBILITY IDEOGRAPH-2F9E0 → CJK UNIFIED IDEOGRAPH-285D2 #
+
+2F9E1 ; 285ED ; MA # ( 𨗭 → 𨗭 ) CJK COMPATIBILITY IDEOGRAPH-2F9E1 → CJK UNIFIED IDEOGRAPH-285ED #
+
+F913 ; 908F ; MA # ( 邏 → 邏 ) CJK COMPATIBILITY IDEOGRAPH-F913 → CJK UNIFIED IDEOGRAPH-908F #
+
+2FA2 ; 9091 ; MA #* ( ⾢ → 邑 ) KANGXI RADICAL CITY → CJK UNIFIED IDEOGRAPH-9091 #
+
+2F9E2 ; 9094 ; MA # ( 邔 → 邔 ) CJK COMPATIBILITY IDEOGRAPH-2F9E2 → CJK UNIFIED IDEOGRAPH-9094 #
+
+F92C ; 90CE ; MA # ( 郎 → 郎 ) CJK COMPATIBILITY IDEOGRAPH-F92C → CJK UNIFIED IDEOGRAPH-90CE #
+90DE ; 90CE ; MA # ( 郞 → 郎 ) CJK UNIFIED IDEOGRAPH-90DE → CJK UNIFIED IDEOGRAPH-90CE # →郎→
+FA2E ; 90CE ; MA # ( 郞 → 郎 ) CJK COMPATIBILITY IDEOGRAPH-FA2E → CJK UNIFIED IDEOGRAPH-90CE # →郞→→郎→
+
+2F9E3 ; 90F1 ; MA # ( 郱 → 郱 ) CJK COMPATIBILITY IDEOGRAPH-2F9E3 → CJK UNIFIED IDEOGRAPH-90F1 #
+
+FA26 ; 90FD ; MA # ( 都 → 都 ) CJK COMPATIBILITY IDEOGRAPH-FA26 → CJK UNIFIED IDEOGRAPH-90FD #
+
+2F9E5 ; 2872E ; MA # ( 𨜮 → 𨜮 ) CJK COMPATIBILITY IDEOGRAPH-2F9E5 → CJK UNIFIED IDEOGRAPH-2872E #
+
+2F9E4 ; 9111 ; MA # ( 鄑 → 鄑 ) CJK COMPATIBILITY IDEOGRAPH-2F9E4 → CJK UNIFIED IDEOGRAPH-9111 #
+
+2F9E6 ; 911B ; MA # ( 鄛 → 鄛 ) CJK COMPATIBILITY IDEOGRAPH-2F9E6 → CJK UNIFIED IDEOGRAPH-911B #
+
+2FA3 ; 9149 ; MA #* ( ⾣ → 酉 ) KANGXI RADICAL WINE → CJK UNIFIED IDEOGRAPH-9149 #
+
+F919 ; 916A ; MA # ( 酪 → 酪 ) CJK COMPATIBILITY IDEOGRAPH-F919 → CJK UNIFIED IDEOGRAPH-916A #
+
+FAC4 ; 9199 ; MA # ( 醙 → 醙 ) CJK COMPATIBILITY IDEOGRAPH-FAC4 → CJK UNIFIED IDEOGRAPH-9199 #
+
+F9B7 ; 91B4 ; MA # ( 醴 → 醴 ) CJK COMPATIBILITY IDEOGRAPH-F9B7 → CJK UNIFIED IDEOGRAPH-91B4 #
+
+2FA4 ; 91C6 ; MA #* ( ⾤ → 釆 ) KANGXI RADICAL DISTINGUISH → CJK UNIFIED IDEOGRAPH-91C6 #
+
+F9E9 ; 91CC ; MA # ( 里 → 里 ) CJK COMPATIBILITY IDEOGRAPH-F9E9 → CJK UNIFIED IDEOGRAPH-91CC #
+2FA5 ; 91CC ; MA #* ( ⾥ → 里 ) KANGXI RADICAL VILLAGE → CJK UNIFIED IDEOGRAPH-91CC #
+
+F97E ; 91CF ; MA # ( 量 → 量 ) CJK COMPATIBILITY IDEOGRAPH-F97E → CJK UNIFIED IDEOGRAPH-91CF #
+
+F90A ; 91D1 ; MA # ( 金 → 金 ) CJK COMPATIBILITY IDEOGRAPH-F90A → CJK UNIFIED IDEOGRAPH-91D1 #
+2FA6 ; 91D1 ; MA #* ( ⾦ → 金 ) KANGXI RADICAL GOLD → CJK UNIFIED IDEOGRAPH-91D1 #
+
+F9B1 ; 9234 ; MA # ( 鈴 → 鈴 ) CJK COMPATIBILITY IDEOGRAPH-F9B1 → CJK UNIFIED IDEOGRAPH-9234 #
+
+2F9E7 ; 9238 ; MA # ( 鈸 → 鈸 ) CJK COMPATIBILITY IDEOGRAPH-2F9E7 → CJK UNIFIED IDEOGRAPH-9238 #
+
+FAC5 ; 9276 ; MA # ( 鉶 → 鉶 ) CJK COMPATIBILITY IDEOGRAPH-FAC5 → CJK UNIFIED IDEOGRAPH-9276 #
+
+2F9E8 ; 92D7 ; MA # ( 鋗 → 鋗 ) CJK COMPATIBILITY IDEOGRAPH-2F9E8 → CJK UNIFIED IDEOGRAPH-92D7 #
+
+2F9E9 ; 92D8 ; MA # ( 鋘 → 鋘 ) CJK COMPATIBILITY IDEOGRAPH-2F9E9 → CJK UNIFIED IDEOGRAPH-92D8 #
+
+2F9EA ; 927C ; MA # ( 鉼 → 鉼 ) CJK COMPATIBILITY IDEOGRAPH-2F9EA → CJK UNIFIED IDEOGRAPH-927C #
+
+F93F ; 9304 ; MA # ( 錄 → 錄 ) CJK COMPATIBILITY IDEOGRAPH-F93F → CJK UNIFIED IDEOGRAPH-9304 #
+
+F99B ; 934A ; MA # ( 鍊 → 鍊 ) CJK COMPATIBILITY IDEOGRAPH-F99B → CJK UNIFIED IDEOGRAPH-934A #
+
+93AE ; 93AD ; MA # ( 鎮 → 鎭 ) CJK UNIFIED IDEOGRAPH-93AE → CJK UNIFIED IDEOGRAPH-93AD #
+
+2F9EB ; 93F9 ; MA # ( 鏹 → 鏹 ) CJK COMPATIBILITY IDEOGRAPH-2F9EB → CJK UNIFIED IDEOGRAPH-93F9 #
+
+2F9EC ; 9415 ; MA # ( 鐕 → 鐕 ) CJK COMPATIBILITY IDEOGRAPH-2F9EC → CJK UNIFIED IDEOGRAPH-9415 #
+
+2F9ED ; 28BFA ; MA # ( 𨯺 → 𨯺 ) CJK COMPATIBILITY IDEOGRAPH-2F9ED → CJK UNIFIED IDEOGRAPH-28BFA #
+
+2ED0 ; 9485 ; MA #* ( ⻐ → 钅 ) CJK RADICAL C-SIMPLIFIED GOLD → CJK UNIFIED IDEOGRAPH-9485 #
+
+2ED1 ; 9577 ; MA #* ( ⻑ → 長 ) CJK RADICAL LONG ONE → CJK UNIFIED IDEOGRAPH-9577 #
+2FA7 ; 9577 ; MA #* ( ⾧ → 長 ) KANGXI RADICAL LONG → CJK UNIFIED IDEOGRAPH-9577 #
+
+2ED2 ; 9578 ; MA #* ( ⻒ → 镸 ) CJK RADICAL LONG TWO → CJK UNIFIED IDEOGRAPH-9578 #
+
+2ED3 ; 957F ; MA #* ( ⻓ → 长 ) CJK RADICAL C-SIMPLIFIED LONG → CJK UNIFIED IDEOGRAPH-957F #
+
+2FA8 ; 9580 ; MA #* ( ⾨ → 門 ) KANGXI RADICAL GATE → CJK UNIFIED IDEOGRAPH-9580 #
+
+2F9EE ; 958B ; MA # ( 開 → 開 ) CJK COMPATIBILITY IDEOGRAPH-2F9EE → CJK UNIFIED IDEOGRAPH-958B #
+
+2F9EF ; 4995 ; MA # ( 䦕 → 䦕 ) CJK COMPATIBILITY IDEOGRAPH-2F9EF → CJK UNIFIED IDEOGRAPH-4995 #
+
+F986 ; 95AD ; MA # ( 閭 → 閭 ) CJK COMPATIBILITY IDEOGRAPH-F986 → CJK UNIFIED IDEOGRAPH-95AD #
+
+2F9F0 ; 95B7 ; MA # ( 閷 → 閷 ) CJK COMPATIBILITY IDEOGRAPH-2F9F0 → CJK UNIFIED IDEOGRAPH-95B7 #
+
+2F9F1 ; 28D77 ; MA # ( 𨵷 → 𨵷 ) CJK COMPATIBILITY IDEOGRAPH-2F9F1 → CJK UNIFIED IDEOGRAPH-28D77 #
+
+2ED4 ; 95E8 ; MA #* ( ⻔ → 门 ) CJK RADICAL C-SIMPLIFIED GATE → CJK UNIFIED IDEOGRAPH-95E8 #
+
+2FA9 ; 961C ; MA #* ( ⾩ → 阜 ) KANGXI RADICAL MOUND → CJK UNIFIED IDEOGRAPH-961C #
+
+2ECF ; 961D ; MA #* ( ⻏ → 阝 ) CJK RADICAL CITY → CJK UNIFIED IDEOGRAPH-961D #
+2ED6 ; 961D ; MA #* ( ⻖ → 阝 ) CJK RADICAL MOUND TWO → CJK UNIFIED IDEOGRAPH-961D #
+
+F9C6 ; 962E ; MA # ( 阮 → 阮 ) CJK COMPATIBILITY IDEOGRAPH-F9C6 → CJK UNIFIED IDEOGRAPH-962E #
+
+F951 ; 964B ; MA # ( 陋 → 陋 ) CJK COMPATIBILITY IDEOGRAPH-F951 → CJK UNIFIED IDEOGRAPH-964B #
+
+FA09 ; 964D ; MA # ( 降 → 降 ) CJK COMPATIBILITY IDEOGRAPH-FA09 → CJK UNIFIED IDEOGRAPH-964D #
+
+F959 ; 9675 ; MA # ( 陵 → 陵 ) CJK COMPATIBILITY IDEOGRAPH-F959 → CJK UNIFIED IDEOGRAPH-9675 #
+
+F9D3 ; 9678 ; MA # ( 陸 → 陸 ) CJK COMPATIBILITY IDEOGRAPH-F9D3 → CJK UNIFIED IDEOGRAPH-9678 #
+
+FAC6 ; 967C ; MA # ( 陼 → 陼 ) CJK COMPATIBILITY IDEOGRAPH-FAC6 → CJK UNIFIED IDEOGRAPH-967C #
+
+F9DC ; 9686 ; MA # ( 隆 → 隆 ) CJK COMPATIBILITY IDEOGRAPH-F9DC → CJK UNIFIED IDEOGRAPH-9686 #
+
+F9F1 ; 96A3 ; MA # ( 隣 → 隣 ) CJK COMPATIBILITY IDEOGRAPH-F9F1 → CJK UNIFIED IDEOGRAPH-96A3 #
+
+2F9F2 ; 49E6 ; MA # ( 䧦 → 䧦 ) CJK COMPATIBILITY IDEOGRAPH-2F9F2 → CJK UNIFIED IDEOGRAPH-49E6 #
+
+2FAA ; 96B6 ; MA #* ( ⾪ → 隶 ) KANGXI RADICAL SLAVE → CJK UNIFIED IDEOGRAPH-96B6 #
+
+FA2F ; 96B7 ; MA # ( 隷 → 隷 ) CJK COMPATIBILITY IDEOGRAPH-FA2F → CJK UNIFIED IDEOGRAPH-96B7 #
+96B8 ; 96B7 ; MA # ( 隸 → 隷 ) CJK UNIFIED IDEOGRAPH-96B8 → CJK UNIFIED IDEOGRAPH-96B7 # →隸→
+F9B8 ; 96B7 ; MA # ( 隸 → 隷 ) CJK COMPATIBILITY IDEOGRAPH-F9B8 → CJK UNIFIED IDEOGRAPH-96B7 #
+
+2FAB ; 96B9 ; MA #* ( ⾫ → 隹 ) KANGXI RADICAL SHORT TAILED BIRD → CJK UNIFIED IDEOGRAPH-96B9 #
+
+2F9F3 ; 96C3 ; MA # ( 雃 → 雃 ) CJK COMPATIBILITY IDEOGRAPH-2F9F3 → CJK UNIFIED IDEOGRAPH-96C3 #
+
+F9EA ; 96E2 ; MA # ( 離 → 離 ) CJK COMPATIBILITY IDEOGRAPH-F9EA → CJK UNIFIED IDEOGRAPH-96E2 #
+
+FA68 ; 96E3 ; MA # ( 難 → 難 ) CJK COMPATIBILITY IDEOGRAPH-FA68 → CJK UNIFIED IDEOGRAPH-96E3 #
+FAC7 ; 96E3 ; MA # ( 難 → 難 ) CJK COMPATIBILITY IDEOGRAPH-FAC7 → CJK UNIFIED IDEOGRAPH-96E3 #
+
+2FAC ; 96E8 ; MA #* ( ⾬ → 雨 ) KANGXI RADICAL RAIN → CJK UNIFIED IDEOGRAPH-96E8 #
+
+F9B2 ; 96F6 ; MA # ( 零 → 零 ) CJK COMPATIBILITY IDEOGRAPH-F9B2 → CJK UNIFIED IDEOGRAPH-96F6 #
+
+F949 ; 96F7 ; MA # ( 雷 → 雷 ) CJK COMPATIBILITY IDEOGRAPH-F949 → CJK UNIFIED IDEOGRAPH-96F7 #
+
+2F9F5 ; 9723 ; MA # ( 霣 → 霣 ) CJK COMPATIBILITY IDEOGRAPH-2F9F5 → CJK UNIFIED IDEOGRAPH-9723 #
+
+2F9F6 ; 29145 ; MA # ( 𩅅 → 𩅅 ) CJK COMPATIBILITY IDEOGRAPH-2F9F6 → CJK UNIFIED IDEOGRAPH-29145 #
+
+F938 ; 9732 ; MA # ( 露 → 露 ) CJK COMPATIBILITY IDEOGRAPH-F938 → CJK UNIFIED IDEOGRAPH-9732 #
+
+F9B3 ; 9748 ; MA # ( 靈 → 靈 ) CJK COMPATIBILITY IDEOGRAPH-F9B3 → CJK UNIFIED IDEOGRAPH-9748 #
+
+2FAD ; 9751 ; MA #* ( ⾭ → 靑 ) KANGXI RADICAL BLUE → CJK UNIFIED IDEOGRAPH-9751 #
+
+2ED8 ; 9752 ; MA #* ( ⻘ → 青 ) CJK RADICAL BLUE → CJK UNIFIED IDEOGRAPH-9752 #
+
+FA1C ; 9756 ; MA # ( 靖 → 靖 ) CJK COMPATIBILITY IDEOGRAPH-FA1C → CJK UNIFIED IDEOGRAPH-9756 #
+FAC8 ; 9756 ; MA # ( 靖 → 靖 ) CJK COMPATIBILITY IDEOGRAPH-FAC8 → CJK UNIFIED IDEOGRAPH-9756 #
+
+2F81C ; 291DF ; MA # ( 𩇟 → 𩇟 ) CJK COMPATIBILITY IDEOGRAPH-2F81C → CJK UNIFIED IDEOGRAPH-291DF #
+
+2FAE ; 975E ; MA #* ( ⾮ → 非 ) KANGXI RADICAL WRONG → CJK UNIFIED IDEOGRAPH-975E #
+
+2FAF ; 9762 ; MA #* ( ⾯ → 面 ) KANGXI RADICAL FACE → CJK UNIFIED IDEOGRAPH-9762 #
+
+2F9F7 ; 2921A ; MA # ( 𩈚 → 𩈚 ) CJK COMPATIBILITY IDEOGRAPH-2F9F7 → CJK UNIFIED IDEOGRAPH-2921A #
+
+2FB0 ; 9769 ; MA #* ( ⾰ → 革 ) KANGXI RADICAL LEATHER → CJK UNIFIED IDEOGRAPH-9769 #
+
+2F9F8 ; 4A6E ; MA # ( 䩮 → 䩮 ) CJK COMPATIBILITY IDEOGRAPH-2F9F8 → CJK UNIFIED IDEOGRAPH-4A6E #
+
+2F9F9 ; 4A76 ; MA # ( 䩶 → 䩶 ) CJK COMPATIBILITY IDEOGRAPH-2F9F9 → CJK UNIFIED IDEOGRAPH-4A76 #
+
+2FB1 ; 97CB ; MA #* ( ⾱ → 韋 ) KANGXI RADICAL TANNED LEATHER → CJK UNIFIED IDEOGRAPH-97CB #
+
+FAC9 ; 97DB ; MA # ( 韛 → 韛 ) CJK COMPATIBILITY IDEOGRAPH-FAC9 → CJK UNIFIED IDEOGRAPH-97DB #
+
+2F9FA ; 97E0 ; MA # ( 韠 → 韠 ) CJK COMPATIBILITY IDEOGRAPH-2F9FA → CJK UNIFIED IDEOGRAPH-97E0 #
+
+2ED9 ; 97E6 ; MA #* ( ⻙ → 韦 ) CJK RADICAL C-SIMPLIFIED TANNED LEATHER → CJK UNIFIED IDEOGRAPH-97E6 #
+
+2FB2 ; 97ED ; MA #* ( ⾲ → 韭 ) KANGXI RADICAL LEEK → CJK UNIFIED IDEOGRAPH-97ED #
+
+2F9FB ; 2940A ; MA # ( 𩐊 → 𩐊 ) CJK COMPATIBILITY IDEOGRAPH-2F9FB → CJK UNIFIED IDEOGRAPH-2940A #
+
+2FB3 ; 97F3 ; MA #* ( ⾳ → 音 ) KANGXI RADICAL SOUND → CJK UNIFIED IDEOGRAPH-97F3 #
+
+FA69 ; 97FF ; MA # ( 響 → 響 ) CJK COMPATIBILITY IDEOGRAPH-FA69 → CJK UNIFIED IDEOGRAPH-97FF #
+FACA ; 97FF ; MA # ( 響 → 響 ) CJK COMPATIBILITY IDEOGRAPH-FACA → CJK UNIFIED IDEOGRAPH-97FF #
+
+2FB4 ; 9801 ; MA #* ( ⾴ → 頁 ) KANGXI RADICAL LEAF → CJK UNIFIED IDEOGRAPH-9801 #
+
+2F9FC ; 4AB2 ; MA # ( 䪲 → 䪲 ) CJK COMPATIBILITY IDEOGRAPH-2F9FC → CJK UNIFIED IDEOGRAPH-4AB2 #
+
+FACB ; 980B ; MA # ( 頋 → 頋 ) CJK COMPATIBILITY IDEOGRAPH-FACB → CJK UNIFIED IDEOGRAPH-980B #
+2F9FE ; 980B ; MA # ( 頋 → 頋 ) CJK COMPATIBILITY IDEOGRAPH-2F9FE → CJK UNIFIED IDEOGRAPH-980B #
+2F9FF ; 980B ; MA # ( 頋 → 頋 ) CJK COMPATIBILITY IDEOGRAPH-2F9FF → CJK UNIFIED IDEOGRAPH-980B #
+
+F9B4 ; 9818 ; MA # ( 領 → 領 ) CJK COMPATIBILITY IDEOGRAPH-F9B4 → CJK UNIFIED IDEOGRAPH-9818 #
+
+2FA00 ; 9829 ; MA # ( 頩 → 頩 ) CJK COMPATIBILITY IDEOGRAPH-2FA00 → CJK UNIFIED IDEOGRAPH-9829 #
+
+2F9FD ; 29496 ; MA # ( 𩒖 → 𩒖 ) CJK COMPATIBILITY IDEOGRAPH-2F9FD → CJK UNIFIED IDEOGRAPH-29496 #
+
+FA6A ; 983B ; MA # ( 頻 → 頻 ) CJK COMPATIBILITY IDEOGRAPH-FA6A → CJK UNIFIED IDEOGRAPH-983B #
+FACC ; 983B ; MA # ( 頻 → 頻 ) CJK COMPATIBILITY IDEOGRAPH-FACC → CJK UNIFIED IDEOGRAPH-983B #
+
+F9D0 ; 985E ; MA # ( 類 → 類 ) CJK COMPATIBILITY IDEOGRAPH-F9D0 → CJK UNIFIED IDEOGRAPH-985E #
+
+2EDA ; 9875 ; MA #* ( ⻚ → 页 ) CJK RADICAL C-SIMPLIFIED LEAF → CJK UNIFIED IDEOGRAPH-9875 #
+
+2FB5 ; 98A8 ; MA #* ( ⾵ → 風 ) KANGXI RADICAL WIND → CJK UNIFIED IDEOGRAPH-98A8 #
+
+2FA01 ; 295B6 ; MA # ( 𩖶 → 𩖶 ) CJK COMPATIBILITY IDEOGRAPH-2FA01 → CJK UNIFIED IDEOGRAPH-295B6 #
+
+2EDB ; 98CE ; MA #* ( ⻛ → 风 ) CJK RADICAL C-SIMPLIFIED WIND → CJK UNIFIED IDEOGRAPH-98CE #
+
+2FB6 ; 98DB ; MA #* ( ⾶ → 飛 ) KANGXI RADICAL FLY → CJK UNIFIED IDEOGRAPH-98DB #
+
+2EDC ; 98DE ; MA #* ( ⻜ → 飞 ) CJK RADICAL C-SIMPLIFIED FLY → CJK UNIFIED IDEOGRAPH-98DE #
+
+2EDD ; 98DF ; MA #* ( ⻝ → 食 ) CJK RADICAL EAT ONE → CJK UNIFIED IDEOGRAPH-98DF #
+2FB7 ; 98DF ; MA #* ( ⾷ → 食 ) KANGXI RADICAL EAT → CJK UNIFIED IDEOGRAPH-98DF #
+
+2EDF ; 98E0 ; MA #* ( ⻟ → 飠 ) CJK RADICAL EAT THREE → CJK UNIFIED IDEOGRAPH-98E0 #
+
+2FA02 ; 98E2 ; MA # ( 飢 → 飢 ) CJK COMPATIBILITY IDEOGRAPH-2FA02 → CJK UNIFIED IDEOGRAPH-98E2 #
+
+FA2A ; 98EF ; MA # ( 飯 → 飯 ) CJK COMPATIBILITY IDEOGRAPH-FA2A → CJK UNIFIED IDEOGRAPH-98EF #
+
+FA2B ; 98FC ; MA # ( 飼 → 飼 ) CJK COMPATIBILITY IDEOGRAPH-FA2B → CJK UNIFIED IDEOGRAPH-98FC #
+
+2FA03 ; 4B33 ; MA # ( 䬳 → 䬳 ) CJK COMPATIBILITY IDEOGRAPH-2FA03 → CJK UNIFIED IDEOGRAPH-4B33 #
+
+FA2C ; 9928 ; MA # ( 館 → 館 ) CJK COMPATIBILITY IDEOGRAPH-FA2C → CJK UNIFIED IDEOGRAPH-9928 #
+
+2FA04 ; 9929 ; MA # ( 餩 → 餩 ) CJK COMPATIBILITY IDEOGRAPH-2FA04 → CJK UNIFIED IDEOGRAPH-9929 #
+
+2EE0 ; 9963 ; MA #* ( ⻠ → 饣 ) CJK RADICAL C-SIMPLIFIED EAT → CJK UNIFIED IDEOGRAPH-9963 #
+
+2FB8 ; 9996 ; MA #* ( ⾸ → 首 ) KANGXI RADICAL HEAD → CJK UNIFIED IDEOGRAPH-9996 #
+
+2FB9 ; 9999 ; MA #* ( ⾹ → 香 ) KANGXI RADICAL FRAGRANT → CJK UNIFIED IDEOGRAPH-9999 #
+
+2FA05 ; 99A7 ; MA # ( 馧 → 馧 ) CJK COMPATIBILITY IDEOGRAPH-2FA05 → CJK UNIFIED IDEOGRAPH-99A7 #
+
+2FBA ; 99AC ; MA #* ( ⾺ → 馬 ) KANGXI RADICAL HORSE → CJK UNIFIED IDEOGRAPH-99AC #
+
+2FA06 ; 99C2 ; MA # ( 駂 → 駂 ) CJK COMPATIBILITY IDEOGRAPH-2FA06 → CJK UNIFIED IDEOGRAPH-99C2 #
+
+F91A ; 99F1 ; MA # ( 駱 → 駱 ) CJK COMPATIBILITY IDEOGRAPH-F91A → CJK UNIFIED IDEOGRAPH-99F1 #
+
+2FA07 ; 99FE ; MA # ( 駾 → 駾 ) CJK COMPATIBILITY IDEOGRAPH-2FA07 → CJK UNIFIED IDEOGRAPH-99FE #
+
+F987 ; 9A6A ; MA # ( 驪 → 驪 ) CJK COMPATIBILITY IDEOGRAPH-F987 → CJK UNIFIED IDEOGRAPH-9A6A #
+
+2EE2 ; 9A6C ; MA #* ( ⻢ → 马 ) CJK RADICAL C-SIMPLIFIED HORSE → CJK UNIFIED IDEOGRAPH-9A6C #
+
+2FBB ; 9AA8 ; MA #* ( ⾻ → 骨 ) KANGXI RADICAL BONE → CJK UNIFIED IDEOGRAPH-9AA8 #
+
+2FA08 ; 4BCE ; MA # ( 䯎 → 䯎 ) CJK COMPATIBILITY IDEOGRAPH-2FA08 → CJK UNIFIED IDEOGRAPH-4BCE #
+
+2FBC ; 9AD8 ; MA #* ( ⾼ → 高 ) KANGXI RADICAL TALL → CJK UNIFIED IDEOGRAPH-9AD8 #
+
+2FBD ; 9ADF ; MA #* ( ⾽ → 髟 ) KANGXI RADICAL HAIR → CJK UNIFIED IDEOGRAPH-9ADF #
+
+2FA09 ; 29B30 ; MA # ( 𩬰 → 𩬰 ) CJK COMPATIBILITY IDEOGRAPH-2FA09 → CJK UNIFIED IDEOGRAPH-29B30 #
+
+FACD ; 9B12 ; MA # ( 鬒 → 鬒 ) CJK COMPATIBILITY IDEOGRAPH-FACD → CJK UNIFIED IDEOGRAPH-9B12 #
+2FA0A ; 9B12 ; MA # ( 鬒 → 鬒 ) CJK COMPATIBILITY IDEOGRAPH-2FA0A → CJK UNIFIED IDEOGRAPH-9B12 #
+
+2FBE ; 9B25 ; MA #* ( ⾾ → 鬥 ) KANGXI RADICAL FIGHT → CJK UNIFIED IDEOGRAPH-9B25 #
+
+2FBF ; 9B2F ; MA #* ( ⾿ → 鬯 ) KANGXI RADICAL SACRIFICIAL WINE → CJK UNIFIED IDEOGRAPH-9B2F #
+
+2FC0 ; 9B32 ; MA #* ( ⿀ → 鬲 ) KANGXI RADICAL CAULDRON → CJK UNIFIED IDEOGRAPH-9B32 #
+
+2FC1 ; 9B3C ; MA #* ( ⿁ → 鬼 ) KANGXI RADICAL GHOST → CJK UNIFIED IDEOGRAPH-9B3C #
+2EE4 ; 9B3C ; MA #* ( ⻤ → 鬼 ) CJK RADICAL GHOST → CJK UNIFIED IDEOGRAPH-9B3C #
+
+2FC2 ; 9B5A ; MA #* ( ⿂ → 魚 ) KANGXI RADICAL FISH → CJK UNIFIED IDEOGRAPH-9B5A #
+
+F939 ; 9B6F ; MA # ( 魯 → 魯 ) CJK COMPATIBILITY IDEOGRAPH-F939 → CJK UNIFIED IDEOGRAPH-9B6F #
+
+2FA0B ; 9C40 ; MA # ( 鱀 → 鱀 ) CJK COMPATIBILITY IDEOGRAPH-2FA0B → CJK UNIFIED IDEOGRAPH-9C40 #
+
+F9F2 ; 9C57 ; MA # ( 鱗 → 鱗 ) CJK COMPATIBILITY IDEOGRAPH-F9F2 → CJK UNIFIED IDEOGRAPH-9C57 #
+
+2EE5 ; 9C7C ; MA #* ( ⻥ → 鱼 ) CJK RADICAL C-SIMPLIFIED FISH → CJK UNIFIED IDEOGRAPH-9C7C #
+
+2FC3 ; 9CE5 ; MA #* ( ⿃ → 鳥 ) KANGXI RADICAL BIRD → CJK UNIFIED IDEOGRAPH-9CE5 #
+
+2FA0C ; 9CFD ; MA # ( 鳽 → 鳽 ) CJK COMPATIBILITY IDEOGRAPH-2FA0C → CJK UNIFIED IDEOGRAPH-9CFD #
+
+2FA0D ; 4CCE ; MA # ( 䳎 → 䳎 ) CJK COMPATIBILITY IDEOGRAPH-2FA0D → CJK UNIFIED IDEOGRAPH-4CCE #
+
+2FA0F ; 9D67 ; MA # ( 鵧 → 鵧 ) CJK COMPATIBILITY IDEOGRAPH-2FA0F → CJK UNIFIED IDEOGRAPH-9D67 #
+
+2FA0E ; 4CED ; MA # ( 䳭 → 䳭 ) CJK COMPATIBILITY IDEOGRAPH-2FA0E → CJK UNIFIED IDEOGRAPH-4CED #
+
+2FA10 ; 2A0CE ; MA # ( 𪃎 → 𪃎 ) CJK COMPATIBILITY IDEOGRAPH-2FA10 → CJK UNIFIED IDEOGRAPH-2A0CE #
+
+FA2D ; 9DB4 ; MA # ( 鶴 → 鶴 ) CJK COMPATIBILITY IDEOGRAPH-FA2D → CJK UNIFIED IDEOGRAPH-9DB4 #
+
+2FA12 ; 2A105 ; MA # ( 𪄅 → 𪄅 ) CJK COMPATIBILITY IDEOGRAPH-2FA12 → CJK UNIFIED IDEOGRAPH-2A105 #
+
+2FA11 ; 4CF8 ; MA # ( 䳸 → 䳸 ) CJK COMPATIBILITY IDEOGRAPH-2FA11 → CJK UNIFIED IDEOGRAPH-4CF8 #
+
+F93A ; 9DFA ; MA # ( 鷺 → 鷺 ) CJK COMPATIBILITY IDEOGRAPH-F93A → CJK UNIFIED IDEOGRAPH-9DFA #
+
+2FA13 ; 2A20E ; MA # ( 𪈎 → 𪈎 ) CJK COMPATIBILITY IDEOGRAPH-2FA13 → CJK UNIFIED IDEOGRAPH-2A20E #
+
+F920 ; 9E1E ; MA # ( 鸞 → 鸞 ) CJK COMPATIBILITY IDEOGRAPH-F920 → CJK UNIFIED IDEOGRAPH-9E1E #
+
+9E43 ; 9E42 ; MA # ( 鹃 → 鹂 ) CJK UNIFIED IDEOGRAPH-9E43 → CJK UNIFIED IDEOGRAPH-9E42 #
+
+2FC4 ; 9E75 ; MA #* ( ⿄ → 鹵 ) KANGXI RADICAL SALT → CJK UNIFIED IDEOGRAPH-9E75 #
+
+F940 ; 9E7F ; MA # ( 鹿 → 鹿 ) CJK COMPATIBILITY IDEOGRAPH-F940 → CJK UNIFIED IDEOGRAPH-9E7F #
+2FC5 ; 9E7F ; MA #* ( ⿅ → 鹿 ) KANGXI RADICAL DEER → CJK UNIFIED IDEOGRAPH-9E7F #
+
+2FA14 ; 2A291 ; MA # ( 𪊑 → 𪊑 ) CJK COMPATIBILITY IDEOGRAPH-2FA14 → CJK UNIFIED IDEOGRAPH-2A291 #
+
+F988 ; 9E97 ; MA # ( 麗 → 麗 ) CJK COMPATIBILITY IDEOGRAPH-F988 → CJK UNIFIED IDEOGRAPH-9E97 #
+
+F9F3 ; 9E9F ; MA # ( 麟 → 麟 ) CJK COMPATIBILITY IDEOGRAPH-F9F3 → CJK UNIFIED IDEOGRAPH-9E9F #
+
+2FC6 ; 9EA5 ; MA #* ( ⿆ → 麥 ) KANGXI RADICAL WHEAT → CJK UNIFIED IDEOGRAPH-9EA5 #
+
+2EE8 ; 9EA6 ; MA #* ( ⻨ → 麦 ) CJK RADICAL SIMPLIFIED WHEAT → CJK UNIFIED IDEOGRAPH-9EA6 #
+
+2FA15 ; 9EBB ; MA # ( 麻 → 麻 ) CJK COMPATIBILITY IDEOGRAPH-2FA15 → CJK UNIFIED IDEOGRAPH-9EBB #
+2FC7 ; 9EBB ; MA #* ( ⿇ → 麻 ) KANGXI RADICAL HEMP → CJK UNIFIED IDEOGRAPH-9EBB #
+
+2F88F ; 2A392 ; MA # ( 𪎒 → 𪎒 ) CJK COMPATIBILITY IDEOGRAPH-2F88F → CJK UNIFIED IDEOGRAPH-2A392 #
+
+2FC8 ; 9EC3 ; MA #* ( ⿈ → 黃 ) KANGXI RADICAL YELLOW → CJK UNIFIED IDEOGRAPH-9EC3 #
+
+2EE9 ; 9EC4 ; MA #* ( ⻩ → 黄 ) CJK RADICAL SIMPLIFIED YELLOW → CJK UNIFIED IDEOGRAPH-9EC4 #
+
+2FC9 ; 9ECD ; MA #* ( ⿉ → 黍 ) KANGXI RADICAL MILLET → CJK UNIFIED IDEOGRAPH-9ECD #
+
+F989 ; 9ECE ; MA # ( 黎 → 黎 ) CJK COMPATIBILITY IDEOGRAPH-F989 → CJK UNIFIED IDEOGRAPH-9ECE #
+
+2FA16 ; 4D56 ; MA # ( 䵖 → 䵖 ) CJK COMPATIBILITY IDEOGRAPH-2FA16 → CJK UNIFIED IDEOGRAPH-4D56 #
+
+2FCA ; 9ED1 ; MA #* ( ⿊ → 黑 ) KANGXI RADICAL BLACK → CJK UNIFIED IDEOGRAPH-9ED1 #
+9ED2 ; 9ED1 ; MA # ( 黒 → 黑 ) CJK UNIFIED IDEOGRAPH-9ED2 → CJK UNIFIED IDEOGRAPH-9ED1 # →⿊→
+
+FA3A ; 58A8 ; MA # ( 墨 → 墨 ) CJK COMPATIBILITY IDEOGRAPH-FA3A → CJK UNIFIED IDEOGRAPH-58A8 #
+
+2FA17 ; 9EF9 ; MA # ( 黹 → 黹 ) CJK COMPATIBILITY IDEOGRAPH-2FA17 → CJK UNIFIED IDEOGRAPH-9EF9 #
+2FCB ; 9EF9 ; MA #* ( ⿋ → 黹 ) KANGXI RADICAL EMBROIDERY → CJK UNIFIED IDEOGRAPH-9EF9 #
+
+2FCC ; 9EFD ; MA #* ( ⿌ → 黽 ) KANGXI RADICAL FROG → CJK UNIFIED IDEOGRAPH-9EFD #
+
+2FA19 ; 9F05 ; MA # ( 鼅 → 鼅 ) CJK COMPATIBILITY IDEOGRAPH-2FA19 → CJK UNIFIED IDEOGRAPH-9F05 #
+
+2FA18 ; 9EFE ; MA # ( 黾 → 黾 ) CJK COMPATIBILITY IDEOGRAPH-2FA18 → CJK UNIFIED IDEOGRAPH-9EFE #
+
+2FCD ; 9F0E ; MA #* ( ⿍ → 鼎 ) KANGXI RADICAL TRIPOD → CJK UNIFIED IDEOGRAPH-9F0E #
+
+2FA1A ; 9F0F ; MA # ( 鼏 → 鼏 ) CJK COMPATIBILITY IDEOGRAPH-2FA1A → CJK UNIFIED IDEOGRAPH-9F0F #
+
+2FCE ; 9F13 ; MA #* ( ⿎ → 鼓 ) KANGXI RADICAL DRUM → CJK UNIFIED IDEOGRAPH-9F13 #
+
+2FA1B ; 9F16 ; MA # ( 鼖 → 鼖 ) CJK COMPATIBILITY IDEOGRAPH-2FA1B → CJK UNIFIED IDEOGRAPH-9F16 #
+
+2FCF ; 9F20 ; MA #* ( ⿏ → 鼠 ) KANGXI RADICAL RAT → CJK UNIFIED IDEOGRAPH-9F20 #
+
+2FA1C ; 9F3B ; MA # ( 鼻 → 鼻 ) CJK COMPATIBILITY IDEOGRAPH-2FA1C → CJK UNIFIED IDEOGRAPH-9F3B #
+2FD0 ; 9F3B ; MA #* ( ⿐ → 鼻 ) KANGXI RADICAL NOSE → CJK UNIFIED IDEOGRAPH-9F3B #
+
+FAD8 ; 9F43 ; MA # ( 齃 → 齃 ) CJK COMPATIBILITY IDEOGRAPH-FAD8 → CJK UNIFIED IDEOGRAPH-9F43 #
+
+2FD1 ; 9F4A ; MA #* ( ⿑ → 齊 ) KANGXI RADICAL EVEN → CJK UNIFIED IDEOGRAPH-9F4A #
+
+2EEC ; 9F50 ; MA #* ( ⻬ → 齐 ) CJK RADICAL C-SIMPLIFIED EVEN → CJK UNIFIED IDEOGRAPH-9F50 #
+
+2FD2 ; 9F52 ; MA #* ( ⿒ → 齒 ) KANGXI RADICAL TOOTH → CJK UNIFIED IDEOGRAPH-9F52 #
+
+2FA1D ; 2A600 ; MA # ( 𪘀 → 𪘀 ) CJK COMPATIBILITY IDEOGRAPH-2FA1D → CJK UNIFIED IDEOGRAPH-2A600 #
+
+2EEE ; 9F7F ; MA #* ( ⻮ → 齿 ) CJK RADICAL C-SIMPLIFIED TOOTH → CJK UNIFIED IDEOGRAPH-9F7F #
+
+F9C4 ; 9F8D ; MA # ( 龍 → 龍 ) CJK COMPATIBILITY IDEOGRAPH-F9C4 → CJK UNIFIED IDEOGRAPH-9F8D #
+2FD3 ; 9F8D ; MA #* ( ⿓ → 龍 ) KANGXI RADICAL DRAGON → CJK UNIFIED IDEOGRAPH-9F8D #
+
+FAD9 ; 9F8E ; MA # ( 龎 → 龎 ) CJK COMPATIBILITY IDEOGRAPH-FAD9 → CJK UNIFIED IDEOGRAPH-9F8E #
+
+2EF0 ; 9F99 ; MA #* ( ⻰ → 龙 ) CJK RADICAL C-SIMPLIFIED DRAGON → CJK UNIFIED IDEOGRAPH-9F99 #
+
+F907 ; 9F9C ; MA # ( 龜 → 龜 ) CJK COMPATIBILITY IDEOGRAPH-F907 → CJK UNIFIED IDEOGRAPH-9F9C #
+F908 ; 9F9C ; MA # ( 龜 → 龜 ) CJK COMPATIBILITY IDEOGRAPH-F908 → CJK UNIFIED IDEOGRAPH-9F9C #
+FACE ; 9F9C ; MA # ( 龜 → 龜 ) CJK COMPATIBILITY IDEOGRAPH-FACE → CJK UNIFIED IDEOGRAPH-9F9C #
+2FD4 ; 9F9C ; MA #* ( ⿔ → 龜 ) KANGXI RADICAL TURTLE → CJK UNIFIED IDEOGRAPH-9F9C #
+
+2EF3 ; 9F9F ; MA #* ( ⻳ → 龟 ) CJK RADICAL C-SIMPLIFIED TURTLE → CJK UNIFIED IDEOGRAPH-9F9F #
+
+2FD5 ; 9FA0 ; MA #* ( ⿕ → 龠 ) KANGXI RADICAL FLUTE → CJK UNIFIED IDEOGRAPH-9FA0 #
+
+# total: 6311
diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el
index d6b5a476bb0..0a9fd5108ce 100644
--- a/admin/unidata/unidata-gen.el
+++ b/admin/unidata/unidata-gen.el
@@ -89,6 +89,7 @@
;; PROPn: string representing the nth property value
(eval-when-compile (require 'cl-lib))
+(require 'generate-lisp-file)
(defvar unidata-list nil)
@@ -209,9 +210,15 @@ Property value is one of the following symbols:
;; The assignment of default values to blocks of code points
;; follows the file DerivedBidiClass.txt from the Unicode
;; Character Database (UCD).
- (L (#x0600 #x06FF AL) (#xFB50 #xFDFF AL) (#xFE70 #xFEFF AL)
- (#x0590 #x05FF R) (#x07C0 #x08FF R)
- (#xFB1D #xFB4F R) (#x10800 #x10FFF R) (#x1E800 #x1EFFF R))
+ (L (#x0600 #x07BF AL) (#x0860 #x08FF AL) (#xFB50 #xFDCF AL)
+ (#xFDF0 #xFDFF AL) (#xFE70 #xFEFF AL) (#x10D00 #x10D3F AL)
+ (#x10F30 #x10F6F AL) (#x1EC70 #x1ECBF AL) (#x1ED00 #x1ED4F AL)
+ (#x1EE00 #x1EEFF AL)
+ (#x0590 #x05FF R) (#x07C0 #x085F R) (#xFB1D #xFB4F R)
+ (#x10800 #x10CFF R) (#x10D40 #x10F2F R) (#x10F70 #x10FFF R)
+ (#x1E800 #x1EC6F R) (#x1ECC0 #x1ECFF R) (#x1ED50 #x1EDFF R)
+ (#x1EF00 #x1EFFF R)
+ (#x20A0 #x20CF ET))
;; The order of elements must be in sync with bidi_type_t in
;; src/dispextern.h.
(L R EN AN BN B AL LRE LRO RLE RLO PDF LRI RLI FSI PDI
@@ -1416,13 +1423,13 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)."
(or elt (user-error "Unknown output file: %s" basename))
(or noninteractive (message "Generating %s..." file))
(with-temp-file file
- (insert ";;; " basename " -*- lexical-binding:t -*-
-;; " copyright "
-;; Generated from Unicode data files by unidata-gen.el.
-;; The sources for this file are found in the admin/unidata/ directory in
-;; the Emacs sources. The Unicode data files are used under the
-;; Unicode Terms of Use, as contained in the file copyright.html in that
-;; same directory.\n")
+ (generate-lisp-file-heading
+ basename 'unidata-gen-file
+ :commentary (concat copyright " \
+The sources for this file are found in the admin/unidata/ directory in \
+the Emacs sources. The Unicode data files are used under the \
+Unicode Terms of Use, as contained in the file copyright.html in that \
+same directory."))
(dolist (proplist (cdr elt))
(let ((prop (unidata-prop-prop proplist))
(index (unidata-prop-index proplist))
@@ -1440,38 +1447,189 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)."
(set-char-table-extra-slot table 3 describer))
(insert (format "(define-char-code-property '%S\n %S\n %S)\n"
prop table docstring))))
- (insert ";; Local Variables:\n"
- ";; coding: utf-8\n"
- ";; version-control: never\n"
- ";; no-byte-compile: t\n"
- ";; no-update-autoloads: t\n"
- ";; End:\n\n"
- (format ";;; %s ends here\n" basename)))))
+ (generate-lisp-file-trailer basename :inhibit-provide t))))
(or noninteractive (message "Generating %s...done" file)))
-(defun unidata-gen-charprop (&optional charprop-file)
+(defun unidata-gen-charprop (&optional charprop-file text)
(or charprop-file (setq charprop-file (pop command-line-args-left)))
(with-temp-file charprop-file
- (insert ";; Automatically generated by unidata-gen.el."
- " -*- lexical-binding: t -*-\n"
- ";; See the admin/unidata/ directory in the Emacs sources.\n")
- (dolist (elt unidata-file-alist)
- (dolist (proplist (cdr elt))
- (insert (format "(define-char-code-property '%S %S\n %S)\n"
- (unidata-prop-prop proplist) (car elt)
- (unidata-prop-docstring proplist)))))
+ (generate-lisp-file-heading
+ charprop-file 'unidata-gen-charprop
+ :commentary "See the admin/unidata/ directory in the Emacs sources.")
+ (if text
+ (insert text)
+ (dolist (elt unidata-file-alist)
+ (dolist (proplist (cdr elt))
+ (insert (format "(define-char-code-property '%S %S\n %S)\n"
+ (unidata-prop-prop proplist) (car elt)
+ (unidata-prop-docstring proplist))))))
(or noninteractive (message "Writing %s..." charprop-file))
- (insert "\n"
- "(provide 'charprop)\n"
- " \n"
- ";; Local Variables:\n"
- ";; coding: utf-8\n"
- ";; version-control: never\n"
- ";; no-byte-compile: t\n"
- ";; no-update-autoloads: t\n"
- ";; End:\n\n"
- (format ";;; %s ends here\n"
- (file-name-nondirectory charprop-file)))))
+ (generate-lisp-file-trailer charprop-file)))
+
+(defun unidata-gen-scripts (&optional file)
+ ;; Running from Makefile.
+ (unless file
+ (setq file (pop command-line-args-left)))
+ (let ((aliases (unidata-gen--read-script-aliases))
+ (table (make-char-table nil))
+ (segmented (make-hash-table :test #'equal)))
+ ;; First parse the scripts.
+ (with-temp-buffer
+ (unidata-gen--insert-file "Scripts.txt")
+ (while (not (eobp))
+ ;; 1700..1711 ; Tagalog # Lo [18] TAGALOG LETTER A..TAGALOG
+ (when (looking-at "\\([0-9A-F]+\\)\\(?:\\.\\.\\([0-9A-F]+\\)\\)? +; +\\([^ ]+\\) +#")
+ (let ((start (string-to-number (match-string 1) 16))
+ (end (and (match-string 2)
+ (string-to-number (match-string 2) 16)))
+ (scripts (list (intern (string-replace
+ "_" "-"
+ (downcase (match-string 3)))))))
+ (set-char-table-range
+ table (if end (cons start end) start) scripts)))
+ (forward-line 1)))
+
+ ;; Then parse the file that lists "other scripts" that characters
+ ;; may appear in, and add those.
+ (with-temp-buffer
+ (unidata-gen--insert-file "ScriptExtensions.txt")
+ (while (not (eobp))
+ ;; 102E0 ; Arab Copt # Mn COPTIC EPACT THOUSANDS MARK
+ (when (looking-at "\\([0-9A-F]+\\)\\(?:\\.\\.\\([0-9A-F]+\\)\\)? +; +\\([^#]+\\)")
+ (let ((start (string-to-number (match-string 1) 16))
+ (end (and (match-string 2)
+ (string-to-number (match-string 2) 16)))
+ (scripts
+ (mapcar
+ (lambda (alias)
+ (intern (string-replace
+ "_" "-" (downcase
+ (gethash alias aliases)))))
+ (split-string (string-trim (match-string 3))))))
+ (dolist (script scripts)
+ (dotimes (i (- (1+ (or end start)) start))
+ (set-char-table-range
+ table (+ i start)
+ (append (elt table (+ i start)) (list script)))))))
+ (forward-line 1)))
+
+ ;; Then go through the data and collect into buckets based on
+ ;; identical script lists.
+ (map-char-table
+ (lambda (key value)
+ ;; `map-char-table' is reused, so copy it.
+ (push (if (consp key)
+ (cons (car key) (cdr key))
+ key)
+ ;; Keep the first element first, but sort the rest.
+ (gethash (cons (car value)
+ (sort (remq (car value) value) #'string<))
+ segmented)))
+ table)
+
+ ;; Then go through the data and collect into buckets based on
+ (let ((scripts nil))
+ (maphash
+ (lambda (segment chars)
+ (push (cons segment chars) scripts))
+ segmented)
+ (setq scripts (sort scripts (lambda (s1 s2)
+ (string< (caar s1) (caar s2)))))
+ (with-temp-buffer
+ (insert "(textsec--create-script-table '(\n")
+ (dolist (script scripts)
+ (insert "(" (prin1-to-string (car script)) "\n")
+ (insert " " (prin1-to-string (cdr script)))
+ (insert ")\n"))
+ (insert "))\n")
+ ;; Write the file.
+ (unidata-gen-charprop file (buffer-string))))))
+
+(defun unidata-gen--read-script-aliases ()
+ (let ((aliases (make-hash-table :test #'equal)))
+ (with-temp-buffer
+ (unidata-gen--insert-file "PropertyValueAliases.txt")
+ (unless (re-search-forward "^# Script " nil t)
+ (error "Can't find the Script section"))
+ (forward-line 2)
+ (while (looking-at "sc *;")
+ (let ((elem (split-string (buffer-substring (point) (line-end-position))
+ ";" nil "[ \t]+")))
+ (setf (gethash (nth 1 elem) aliases)
+ (nth 2 elem)))
+ (forward-line 1))
+ aliases)))
+
+(defun unidata-gen--insert-file (name)
+ (insert-file-contents
+ (expand-file-name (concat "../admin/unidata/" name)
+ data-directory)))
+
+(defun unidata-gen-confusable (&optional file)
+ ;; Running from Makefile.
+ (unless file
+ (setq file (pop command-line-args-left)))
+ (let ((regexp
+ (concat "^\\([[:xdigit:]]+\\)"
+ "[ \t]*;[ \t]*"
+ "\\([[:space:][:xdigit:]]+\\)"
+ "[ \t]*;"))
+ (map (make-hash-table)))
+ (with-temp-buffer
+ (unidata-gen--insert-file "confusables.txt")
+ (while (re-search-forward regexp nil t)
+ (let ((from (match-string 1))
+ (to (string-trim (match-string 2))))
+ (setf (gethash (string-to-number from 16) map)
+ (apply #'string (mapcar (lambda (string)
+ (string-to-number string 16))
+ (split-string to)))))))
+ (with-temp-buffer
+ (insert "(defconst uni-confusable-table\n")
+ (let ((print-length nil))
+ (prin1 map (current-buffer)))
+ (insert ")")
+ (unidata-gen-charprop file (buffer-string)))))
+
+(defun unidata-gen-idna-mapping (&optional file)
+ ;; Running from Makefile.
+ (unless file
+ (setq file (pop command-line-args-left)))
+ (let ((map (make-char-table nil)))
+ (with-temp-buffer
+ (unidata-gen--insert-file "IdnaMappingTable.txt")
+ (while (re-search-forward "^\\([0-9A-F]+\\)\\(?:\\.\\.\\([0-9A-F]+\\)\\)? +; +\\([^ ]+\\) +\\(?:; +\\([ 0-9A-F]+\\)\\)?"
+ nil t)
+ (let ((start (match-string 1))
+ (end (match-string 2))
+ (status (match-string 3))
+ (mapped (match-string 4)))
+ ;; Make reading the file slightly faster by using `t'
+ ;; instead of `disallowed' all over the place.
+ (when (string-match-p "\\`disallowed" status)
+ (setq status "t"))
+ (unless (or (equal status "valid")
+ (equal status "deviation"))
+ (set-char-table-range
+ map
+ (if end
+ (cons (string-to-number start 16)
+ (string-to-number end 16))
+ (string-to-number start 16))
+ (cond
+ ((equal status "mapped")
+ (apply #'string
+ (mapcar (lambda (char)
+ (string-to-number char 16))
+ (split-string (string-trim mapped)))))
+ (t
+ (intern status))))))))
+ (with-temp-buffer
+ (insert "(defconst idna-mapping-table\n")
+ (let ((print-length nil))
+ (prin1 map (current-buffer)))
+ (insert ")")
+ (unidata-gen-charprop file (buffer-string)))))
diff --git a/admin/upload-manuals b/admin/upload-manuals
index 1fa9865e657..1b7950ede80 100755
--- a/admin/upload-manuals
+++ b/admin/upload-manuals
@@ -334,7 +334,10 @@ for d in html_node/*; do
[ -e $webdir/manual/$d ] || {
echo "New directory: $d"
mkdir $webdir/manual/$d
- $cvs add $webdir/manual/$d || die "add error"
+ (
+ cd $webdir/manual
+ $cvs add $d || die "add error"
+ )
}
new=
diff --git a/autogen.sh b/autogen.sh
index 03f647e576c..041468edcd9 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -35,7 +35,7 @@
progs="autoconf"
## Minimum versions we need:
-autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac`
+autoconf_min=`sed -n 's/^ *AC_PREREQ(\[\([0-9\.]*\)]).*/\1/p' configure.ac`
## $1 = program, eg "autoconf".
diff --git a/build-aux/config.guess b/build-aux/config.guess
index 1105a749838..1817bdce90d 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,14 +1,14 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2021 Free Software Foundation, Inc.
+# Copyright 1992-2022 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2021-11-30'
+timestamp='2022-05-25'
# This file 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
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2021 Free Software Foundation, Inc.
+Copyright 1992-2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -929,6 +929,9 @@ EOF
i*:PW*:*)
GUESS=$UNAME_MACHINE-pc-pw32
;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
*:Interix*:*)
case $UNAME_MACHINE in
x86)
@@ -1148,16 +1151,27 @@ EOF
;;
x86_64:Linux:*:*)
set_cc_for_build
+ CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI=${LIBC}x32
- fi
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
fi
- GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@@ -1364,8 +1378,11 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
- x86_64:Haiku:*:*)
- GUESS=x86_64-unknown-haiku
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 5ba9a97d2c9..dba16e84c77 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,14 +1,14 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2021 Free Software Foundation, Inc.
+# Copyright 1992-2022 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2021-12-25'
+timestamp='2022-01-03'
# This file 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
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2021 Free Software Foundation, Inc.
+Copyright 1992-2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
diff --git a/build-aux/git-hooks/pre-commit b/build-aux/git-hooks/pre-commit
index a55004680fa..49bf05f2d9f 100755
--- a/build-aux/git-hooks/pre-commit
+++ b/build-aux/git-hooks/pre-commit
@@ -45,7 +45,9 @@ git_diff='git diff --cached --name-only --diff-filter=A'
# 'git diff' will backslash escape tabs and newlines, so we don't have
# to worry about word splitting here.
-$git_diff $head | sane_egrep 'ChangeLog|^-|/-|[^-+./_0-9A-Z_a-z]' | while IFS= read -r new_name; do
+$git_diff $head |
+LC_ALL=C grep -E 'ChangeLog|^-|/-|[^-+./_0-9A-Z_a-z]' |
+while IFS= read -r new_name; do
case $new_name in
-* | */-*)
echo "$new_name: File name component begins with '-'."
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
index 1c6847ae3b3..82d9f973366 100755
--- a/build-aux/gitlog-to-changelog
+++ b/build-aux/gitlog-to-changelog
@@ -35,7 +35,7 @@
eval 'exec perl -wSx "$0" "$@"'
if 0;
-my $VERSION = '2021-02-24 23:42'; # UTC
+my $VERSION = '2022-01-27 18:49'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
diff --git a/build-aux/update-copyright b/build-aux/update-copyright
index 51b25dd0a5e..81b691e8570 100755
--- a/build-aux/update-copyright
+++ b/build-aux/update-copyright
@@ -7,7 +7,7 @@
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
+# the Free Software Foundation, either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
diff --git a/config.bat b/config.bat
index 29742eec52b..e9a180c8eed 100644
--- a/config.bat
+++ b/config.bat
@@ -310,6 +310,9 @@ rm -f makefile.tmp
sed -f ../msdos/sedlibcf.inp < gnulib.mk-in > gnulib.tmp
sed -f ../msdos/sedlibmk.inp < gnulib.tmp > gnulib.mk
rm -f gnulib.tmp
+Rem Create directories in lib/ that MKDIR_P is supposed to create
+Rem but I have no idea how to do that on MS-DOS.
+mkdir sys
Rem Create .d files for new files in lib/ and lib/malloc/
If Not Exist deps\stamp mkdir deps
for %%f in (*.c) do @call ..\msdos\depfiles.bat %%f
diff --git a/configure.ac b/configure.ac
index baf8c8018ec..45b62647e71 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,9 +21,10 @@ dnl
dnl You should have received a copy of the GNU General Public License
dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-AC_PREREQ(2.65)
+AC_PREREQ([2.65])
dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el.
-AC_INIT(GNU Emacs, 29.0.50, bug-gnu-emacs@gnu.org, , https://www.gnu.org/software/emacs/)
+AC_INIT([GNU Emacs], [29.0.50], [bug-gnu-emacs@gnu.org], [],
+ [https://www.gnu.org/software/emacs/])
dnl Set emacs_config_options to the options of 'configure', quoted for the shell,
dnl and then quoted again for a C string. Separate options with spaces.
@@ -64,13 +65,13 @@ for opt in "$@" CFLAGS CPPFLAGS LDFLAGS; do
optsep=' '
done
-AC_CONFIG_HEADERS(src/config.h:src/config.in)
-AC_CONFIG_SRCDIR(src/lisp.h)
-AC_CONFIG_AUX_DIR(build-aux)
-AC_CONFIG_MACRO_DIR(m4)
+AC_CONFIG_HEADERS([src/config.h:src/config.in])
+AC_CONFIG_SRCDIR([src/lisp.h])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_MACRO_DIR([m4])
xcsdkdir=
-AC_CHECK_PROGS(XCRUN, [xcrun])
+AC_CHECK_PROGS([XCRUN], [xcrun])
if test -n "$XCRUN"; then
if test -z "$MAKE"; then
dnl Call the variable MAKE_PROG, not MAKE, to avoid confusion with
@@ -199,7 +200,7 @@ etcdocdir='${datadir}/emacs/${version}/etc'
gamedir='${localstatedir}/games/emacs'
dnl Special option to disable the most of other options.
-AC_ARG_WITH(all,
+AC_ARG_WITH([all],
[AS_HELP_STRING([--without-all],
[omit almost all features and build
small executable with minimal dependencies])],
@@ -278,41 +279,45 @@ AC_ARG_WITH([pop],
*) with_pop=no-by-default;;
esac])
if test "$with_pop" = yes; then
- AC_DEFINE(MAIL_USE_POP)
+ AC_DEFINE([MAIL_USE_POP])
fi
-AH_TEMPLATE(MAIL_USE_POP, [Define to support POP mail retrieval.])dnl
+AH_TEMPLATE([MAIL_USE_POP], [Define to support POP mail retrieval.])dnl
OPTION_DEFAULT_OFF([kerberos],[support Kerberos-authenticated POP])
if test "$with_kerberos" != no; then
- AC_DEFINE(KERBEROS)
+ AC_DEFINE([KERBEROS])
fi
-AH_TEMPLATE(KERBEROS,
+AH_TEMPLATE([KERBEROS],
[Define to support Kerberos-authenticated POP mail retrieval.])dnl
OPTION_DEFAULT_OFF([kerberos5],[support Kerberos version 5 authenticated POP])
if test "${with_kerberos5}" != no; then
if test "${with_kerberos}" = no; then
with_kerberos=yes
- AC_DEFINE(KERBEROS)
+ AC_DEFINE([KERBEROS])
fi
- AC_DEFINE(KERBEROS5, 1, [Define to use Kerberos 5 instead of Kerberos 4.])
+ AC_DEFINE([KERBEROS5], [1],
+ [Define to use Kerberos 5 instead of Kerberos 4.])
fi
OPTION_DEFAULT_OFF([hesiod],[support Hesiod to get the POP server host])
dnl FIXME hesiod support may not be present, so it seems like an error
dnl to define, or at least use, this unconditionally.
if test "$with_hesiod" != no; then
- AC_DEFINE(HESIOD, 1, [Define to support using a Hesiod database to find the POP server.])
+ AC_DEFINE([HESIOD], [1],
+ [Define to support using a Hesiod database to find the POP server.])
fi
OPTION_DEFAULT_OFF([mail-unlink],[unlink, rather than empty, mail spool after reading])
if test "$with_mail_unlink" != no; then
- AC_DEFINE(MAIL_UNLINK_SPOOL, 1, [Define to unlink, rather than empty, mail spool after reading.])
+ AC_DEFINE([MAIL_UNLINK_SPOOL], [1],
+ [Define to unlink, rather than empty, mail spool after reading.])
fi
AC_ARG_WITH([mailhost],[AS_HELP_STRING([--with-mailhost=HOSTNAME],
[string giving default POP mail host])],
- AC_DEFINE_UNQUOTED(MAILHOST, ["$withval"], [String giving fallback POP mail host.]))
+ AC_DEFINE_UNQUOTED([MAILHOST], ["$withval"],
+ [String giving fallback POP mail host.]))
AC_ARG_WITH([sound],[AS_HELP_STRING([--with-sound=VALUE],
[compile with sound support (VALUE one of: yes, alsa, oss, bsd-ossaudio, no;
@@ -395,7 +400,8 @@ if test "$with_dumping" = "unexec" && test "$with_unexec" = "no"; then
fi
if test "$with_pdumper" = "yes"; then
- AC_DEFINE([HAVE_PDUMPER], 1, [Define to build with portable dumper support])
+ AC_DEFINE([HAVE_PDUMPER], [1],
+ [Define to build with portable dumper support])
HAVE_PDUMPER=yes
else
HAVE_PDUMPER=no
@@ -403,7 +409,7 @@ fi
AC_SUBST([HAVE_PDUMPER])
DUMPING=$with_dumping
-AC_SUBST(DUMPING)
+AC_SUBST([DUMPING])
dnl FIXME currently it is not the last.
dnl This should be the last --with option, because --with-x is
@@ -436,7 +442,7 @@ OPTION_DEFAULT_OFF([wide-int],
at the cost of 10% to 30% slowdown of Lisp interpreter
and larger memory footprint])
if test "$with_wide_int" = yes; then
- AC_DEFINE([WIDE_EMACS_INT], 1, [Use long long for EMACS_INT if available.])
+ AC_DEFINE([WIDE_EMACS_INT], [1], [Use long long for EMACS_INT if available.])
fi
dnl _ON results in a '--without' option in the --help output, so
@@ -471,7 +477,7 @@ AC_ARG_WITH([ns],[AS_HELP_STRING([--with-ns],
[use Nextstep (macOS Cocoa or GNUstep) windowing system.
On by default on macOS.])],[],[with_ns=maybe])
OPTION_DEFAULT_OFF([w32], [use native MS Windows GUI in a Cygwin build])
-OPTION_DEFAULT_OFF([pgtk], [use pure GTK build without reliance on X libs (Wayland support) (requires cairo) - Experimental])
+OPTION_DEFAULT_OFF([pgtk], [use GTK to support window systems other than X])
OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
@@ -490,7 +496,8 @@ OPTION_DEFAULT_ON([modules],[don't compile with dynamic modules support])
OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
OPTION_DEFAULT_OFF([native-compilation],[compile with Emacs Lisp native compiler support])
OPTION_DEFAULT_OFF([cygwin32-native-compilation],[use native compilation on 32-bit Cygwin])
-OPTION_DEFAULT_OFF([xinput2],[use version 2 of the X Input Extension for input])
+OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input])
+OPTION_DEFAULT_OFF([small-ja-dic],[generate a smaller-size Japanese dictionary])
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
@@ -521,7 +528,7 @@ OPTION_DEFAULT_OFF([be-cairo],
[enable use of cairo under Haiku's Application Kit])
## Makefile.in needs the cache file name.
-AC_SUBST(cache_file)
+AC_SUBST([cache_file])
## This is an option because I do not know if all info/man support
## compressed files, nor how to test if they do so.
@@ -529,7 +536,7 @@ OPTION_DEFAULT_ON([compress-install],
[don't compress some files (.el, .info, etc.) when installing. Equivalent to:
make GZIP_PROG= install])
-AC_ARG_WITH(gameuser,dnl
+AC_ARG_WITH([gameuser],
[AS_HELP_STRING([--with-gameuser=USER_OR_GROUP],
[user for shared game score files.
An argument prefixed by ':' specifies a group instead.])])
@@ -542,7 +549,7 @@ case ${with_gameuser} in
*) gameuser=${with_gameuser} ;;
esac
-AC_ARG_WITH([gnustep-conf],dnl
+AC_ARG_WITH([gnustep-conf],
[AS_HELP_STRING([--with-gnustep-conf=FILENAME],
[name of GNUstep configuration file to use on systems where the command
'gnustep-config' does not work; default $GNUSTEP_CONFIG_FILE, or
@@ -552,24 +559,24 @@ test "X${with_gnustep_conf}" != X && test "${with_gnustep_conf}" != yes && \
test "X$GNUSTEP_CONFIG_FILE" = "X" && \
GNUSTEP_CONFIG_FILE=/etc/GNUstep/GNUstep.conf
-AC_ARG_ENABLE(ns-self-contained,
+AC_ARG_ENABLE([ns-self-contained],
[AS_HELP_STRING([--disable-ns-self-contained],
[disable self contained build under NeXTstep])],
- EN_NS_SELF_CONTAINED=$enableval,
- EN_NS_SELF_CONTAINED=yes)
+ [EN_NS_SELF_CONTAINED=$enableval],
+ [EN_NS_SELF_CONTAINED=yes])
locallisppathset=no
-AC_ARG_ENABLE(locallisppath,
+AC_ARG_ENABLE([locallisppath],
[AS_HELP_STRING([--enable-locallisppath=PATH],
[directories Emacs should search for lisp files specific
to this site])],
-if test "${enableval}" = "no"; then
+[if test "${enableval}" = "no"; then
locallisppath=
elif test "${enableval}" != "yes"; then
locallisppath=${enableval} locallisppathset=yes
-fi)
+fi])
-AC_ARG_ENABLE(checking,
+AC_ARG_ENABLE([checking],
[AS_HELP_STRING([--enable-checking@<:@=LIST@:>@],
[enable expensive checks. With LIST,
enable only specific categories of checks.
@@ -602,17 +609,17 @@ do
stringfreelist) ac_gc_check_string_free_list=1 ;;
structs) CHECK_STRUCTS=true ;;
glyphs) ac_glyphs_debug=1 ;;
- *) AC_MSG_ERROR(unknown check category $check) ;;
+ *) AC_MSG_ERROR([unknown check category $check]) ;;
esac
done
IFS="$ac_save_IFS"
if test x$ac_enable_checking != x ; then
- AC_DEFINE(ENABLE_CHECKING, 1,
+ AC_DEFINE([ENABLE_CHECKING], [1],
[Define to 1 if expensive run-time data type and consistency checks are enabled.])
fi
if $CHECK_STRUCTS; then
- AC_DEFINE([CHECK_STRUCTS], 1,
+ AC_DEFINE([CHECK_STRUCTS], [1],
[Define this to check whether someone updated the portable dumper
code after changing the layout of a structure that it uses.
If you change one of these structures, check that the pdumper.c
@@ -621,21 +628,21 @@ if $CHECK_STRUCTS; then
fi
AC_SUBST([CHECK_STRUCTS])
if test x$ac_gc_check_stringbytes != x ; then
- AC_DEFINE(GC_CHECK_STRING_BYTES, 1,
+ AC_DEFINE([GC_CHECK_STRING_BYTES], [1],
[Define this temporarily to hunt a bug. If defined, the size of
strings is redundantly recorded in sdata structures so that it can
be compared to the sizes recorded in Lisp strings.])
fi
if test x$ac_gc_check_string_overrun != x ; then
- AC_DEFINE(GC_CHECK_STRING_OVERRUN, 1,
+ AC_DEFINE([GC_CHECK_STRING_OVERRUN], [1],
[Define this to check for short string overrun.])
fi
if test x$ac_gc_check_string_free_list != x ; then
- AC_DEFINE(GC_CHECK_STRING_FREE_LIST, 1,
+ AC_DEFINE([GC_CHECK_STRING_FREE_LIST], [1],
[Define this to check the string free list.])
fi
if test x$ac_glyphs_debug != x ; then
- AC_DEFINE(GLYPH_DEBUG, 1,
+ AC_DEFINE([GLYPH_DEBUG], [1],
[Define this to enable glyphs debugging code.])
fi
@@ -643,7 +650,7 @@ dnl The name of this option is unfortunate. It predates, and has no
dnl relation to, the "sampling-based elisp profiler" added in 24.3.
dnl Actually, it stops it working.
dnl https://lists.gnu.org/r/emacs-devel/2012-11/msg00393.html
-AC_ARG_ENABLE(profiling,
+AC_ARG_ENABLE([profiling],
[AS_HELP_STRING([--enable-profiling],
[build emacs with low-level, gprof profiling support.
Mainly useful for debugging Emacs itself. May not work on
@@ -654,15 +661,15 @@ if test x$ac_enable_profiling != x ; then
else
PROFILING_CFLAGS=
fi
-AC_SUBST(PROFILING_CFLAGS)
+AC_SUBST([PROFILING_CFLAGS])
-AC_ARG_ENABLE(autodepend,
+AC_ARG_ENABLE([autodepend],
[AS_HELP_STRING([--enable-autodepend],
[automatically generate dependencies to .h-files.
Requires gcc, enabled if found.])],
[ac_enable_autodepend="${enableval}"],[ac_enable_autodepend=yes])
-AC_ARG_ENABLE(gtk-deprecation-warnings,
+AC_ARG_ENABLE([gtk-deprecation-warnings],
[AS_HELP_STRING([--enable-gtk-deprecation-warnings],
[Show Gtk+/Gdk deprecation warnings for Gtk+ >= 3.0])],
[ac_enable_gtk_deprecation_warnings="${enableval}"],[])
@@ -865,7 +872,7 @@ AC_DEFUN([_AC_PROG_CC_C89], [$2])
dnl Sets GCC=yes if using gcc.
AC_PROG_CC([gcc cc cl clang "$XCRUN gcc" "$XCRUN clang"])
if test -n "$XCRUN"; then
- AC_CHECK_PROGS(AR, [ar "$XCRUN ar"])
+ AC_CHECK_PROGS([AR], [ar "$XCRUN ar"])
test -n "$AR" && export AR
fi
@@ -965,6 +972,17 @@ AC_DEFUN([gl_GCC_VERSION_IFELSE],
]
)
+# clang is unduly picky about some things.
+AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #ifndef __clang__
+ error "not clang";
+ #endif
+ ]])],
+ [emacs_cv_clang=yes],
+ [emacs_cv_clang=no])])
+
AC_ARG_ENABLE([gcc-warnings],
[AS_HELP_STRING([--enable-gcc-warnings@<:@=TYPE@:>@],
[control generation of GCC warnings. The TYPE 'yes'
@@ -984,7 +1002,11 @@ AC_ARG_ENABLE([gcc-warnings],
# just a release imported into Git for patch management.
gl_gcc_warnings=no
if test -e "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then
- gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])
+ # Clang typically identifies itself as GCC 4.2 or something similar
+ # even if it is recent enough to accept the warnings we enable.
+ AS_IF([test "$emacs_cv_clang" = yes],
+ [gl_gcc_warnings=warn-only],
+ [gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])])
fi])
AC_ARG_ENABLE([check-lisp-object-type],
@@ -992,21 +1014,10 @@ AC_ARG_ENABLE([check-lisp-object-type],
[Enable compile time checks for the Lisp_Object data type,
which can catch some bugs during development.])])
if test "$enable_check_lisp_object_type" = yes; then
- AC_DEFINE([CHECK_LISP_OBJECT_TYPE], 1,
+ AC_DEFINE([CHECK_LISP_OBJECT_TYPE], [1],
[Define to enable compile-time checks for the Lisp_Object data type.])
fi
-# clang is unduly picky about some things.
-AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
- [AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([[
- #ifndef __clang__
- error "not clang";
- #endif
- ]])],
- [emacs_cv_clang=yes],
- [emacs_cv_clang=no])])
-
WERROR_CFLAGS=
# When compiling with GCC, prefer -isystem to -I when including system
# include files, to avoid generating useless diagnostics for the files.
@@ -1020,6 +1031,7 @@ AS_IF([test $gl_gcc_warnings = no],
gl_WARN_ADD([-Wno-pointer-sign])
gl_WARN_ADD([-Wno-string-plus-int])
gl_WARN_ADD([-Wno-unknown-attributes])
+ gl_WARN_ADD([-Wno-unknown-pragmas])
])
],[
isystem='-isystem '
@@ -1075,8 +1087,12 @@ AS_IF([test $gl_gcc_warnings = no],
# option problematic.
nw="$nw -Wsuggest-attribute=pure"
+ # Emacs doesn't need this paranoia.
+ nw="$nw -Wbidi-chars=any,ucn"
+
if test "$emacs_cv_clang" = yes; then
nw="$nw -Wdouble-promotion"
+ nm="$nm -Wunknown-pragmas"
fi
# This causes too much noise in the MinGW build.
@@ -1096,11 +1112,14 @@ AS_IF([test $gl_gcc_warnings = no],
gl_WARN_ADD([-Wno-type-limits]) # Too many warnings for now
gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now
gl_WARN_ADD([-Wno-format-nonliteral])
+ gl_WARN_ADD([-Wno-bidi-chars])
# clang is unduly picky about some things.
if test "$emacs_cv_clang" = yes; then
gl_WARN_ADD([-Wno-missing-braces])
gl_WARN_ADD([-Wno-null-pointer-arithmetic])
+ gl_WARN_ADD([-Wno-implicit-const-int-float-conversion])
+ gl_WARN_ADD([-Wno-int-in-bool-context])
fi
# This causes too much noise in the MinGW build
@@ -1144,7 +1163,7 @@ edit_cflags="
s/^ //
"
-AC_ARG_ENABLE(link-time-optimization,
+AC_ARG_ENABLE([link-time-optimization],
[AS_HELP_STRING([--enable-link-time-optimization],
[build with link-time optimization
(experimental; see INSTALL)])],
@@ -1201,6 +1220,8 @@ dnl Automake replacements.
AC_DEFUN([AM_CONDITIONAL],
[$2 && $1_CONDITION=1 || $1_CONDITION=
AC_SUBST([$1_CONDITION])])
+AC_DEFUN([AM_COND_IF],
+ [AS_IF([test "$$1_CONDITION"], [$2], [$3])])
dnl Prefer silent make output. For verbose output, use
dnl 'configure --disable-silent-rules' or 'make V=1' .
@@ -1252,7 +1273,7 @@ fi
rm -f conf$$ conf$$.file])
LN_S_FILEONLY=$emacs_cv_ln_s_fileonly
-AC_SUBST(LN_S_FILEONLY)
+AC_SUBST([LN_S_FILEONLY])
dnl AC_PROG_LN_S sets LN_S to 'cp -pR' for MinGW, on the premise that 'ln'
@@ -1271,13 +1292,13 @@ dnl if called via an absolute file name.
dnl Use the entirely-identical-but-quieter ginstall-info instead if present.
dnl Sadly some people may have an old ginstall-info installed on
dnl non-Debian systems, so we can't use this.
-dnl AC_PATH_PROGS(INSTALL_INFO, [ginstall-info install-info], :,
-dnl $PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin)
+dnl AC_PATH_PROGS([INSTALL_INFO], [ginstall-info install-info], [:],
+dnl [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
-AC_PATH_PROG(INSTALL_INFO, install-info, :,
- $PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin)
+AC_PATH_PROG([INSTALL_INFO], [install-info], [:],
+ [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
dnl Don't use GZIP, which is used by gzip for additional parameters.
-AC_PATH_PROG(GZIP_PROG, gzip)
+AC_PATH_PROG([GZIP_PROG], [gzip])
test $with_compress_install != yes && test -n "$GZIP_PROG" && \
GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)"
@@ -1346,7 +1367,7 @@ AC_SUBST([SETFATTR])
# Makeinfo on macOS is ancient, check whether there is a more recent
# version installed by Homebrew.
-AC_CHECK_PROGS(BREW, [brew])
+AC_CHECK_PROGS([BREW], [brew])
if test -n "$BREW"; then
AC_PATH_PROG([MAKEINFO], [makeinfo], [],
[`$BREW --prefix texinfo 2>/dev/null`/bin$PATH_SEPARATOR$PATH])
@@ -1354,7 +1375,7 @@ fi
# Check MacPorts on macOS.
if test $opsys = darwin; then
- AC_PATH_PROG(HAVE_MACPORTS, port)
+ AC_PATH_PROG([HAVE_MACPORTS], [port])
fi
## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals.
@@ -1394,7 +1415,7 @@ if test $opsys = mingw32; then
else
DOCMISC_W32=
fi
-AC_SUBST(DOCMISC_W32)
+AC_SUBST([DOCMISC_W32])
dnl Add our options to ac_link now, after it is set up.
@@ -1453,7 +1474,7 @@ AC_CACHE_CHECK([whether addresses are sanitized],
[emacs_cv_sanitize_address=no])])
if test $with_unexec = yes; then
- AC_DEFINE([HAVE_UNEXEC], 1, [Define if Emacs supports unexec.])
+ AC_DEFINE([HAVE_UNEXEC], [1], [Define if Emacs supports unexec.])
if test "$emacs_cv_sanitize_address" = yes; then
AC_MSG_WARN([[Addresses are sanitized; suggest --without-unexec]])
fi
@@ -1490,7 +1511,7 @@ case "$opsys" in
UNEXEC_OBJ=unexelf.o
;;
esac
-AC_SUBST(UNEXEC_OBJ)
+AC_SUBST([UNEXEC_OBJ])
LD_SWITCH_SYSTEM=
test "$with_unexec" = no || case "$opsys" in
@@ -1520,7 +1541,7 @@ test "$with_unexec" = no || case "$opsys" in
LD_SWITCH_SYSTEM="-Z"
;;
esac
-AC_SUBST(LD_SWITCH_SYSTEM)
+AC_SUBST([LD_SWITCH_SYSTEM])
ac_link="$ac_link $LD_SWITCH_SYSTEM"
@@ -1556,7 +1577,7 @@ case $canonical in
fi
;;
esac
-AC_SUBST(C_SWITCH_MACHINE)
+AC_SUBST([C_SWITCH_MACHINE])
C_SWITCH_SYSTEM=
## Some programs in src produce warnings saying certain subprograms
@@ -1572,7 +1593,7 @@ if test "$opsys" = "mingw32"; then
fi
## gnu-linux might need -D_BSD_SOURCE on old libc5 systems.
## It is redundant in glibc2, since we define _GNU_SOURCE.
-AC_SUBST(C_SWITCH_SYSTEM)
+AC_SUBST([C_SWITCH_SYSTEM])
LIBS_SYSTEM=
@@ -1594,7 +1615,7 @@ case "$opsys" in
haiku) LIBS_SYSTEM="-lnetwork" ;;
esac
-AC_SUBST(LIBS_SYSTEM)
+AC_SUBST([LIBS_SYSTEM])
### Make sure subsequent tests use flags consistent with the build flags.
@@ -1609,16 +1630,63 @@ AC_DEFUN([AC_TYPE_SIZE_T])
# Likewise for obsolescent test for uid_t, gid_t; Emacs assumes them.
AC_DEFUN([AC_TYPE_UID_T])
-# sqrt and other floating-point functions such as fmod and frexp
-# are found in -lm on many systems.
-OLD_LIBS=$LIBS
-AC_SEARCH_LIBS([sqrt], [m])
-if test "X$LIBS" = "X$OLD_LIBS"; then
- LIB_MATH=
-else
- LIB_MATH=$ac_cv_search_sqrt
-fi
-LIBS=$OLD_LIBS
+# Check for all math.h functions that Emacs uses; on some platforms,
+# -lm is needed for some of these functions.
+AC_CACHE_CHECK([for math library],
+ [emacs_cv_lib_math],
+ [OLD_LIBS=$LIBS
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE([[
+ #include <math.h>
+ int
+ main (int argc, char **argv)
+ {
+ double d = argc;
+ float f = argc;
+ int i = argc;
+ long l = argc;
+ d = acos (d);
+ d = asin (d);
+ d = atan (d);
+ d = atan2 (d, d);
+ d = ceil (d);
+ d = copysign (d, d);
+ d = cos (d);
+ d = exp (d);
+ d = fabs (d);
+ d = floor (d);
+ d = fmod (d, d);
+ d = frexp (d, &i);
+ d = ldexp (d, i);
+ d = log (d);
+ d = log2 (d);
+ d = log10 (d);
+ d = pow (d, d);
+ d = rint (d);
+ d = scalbn (d, l);
+ d = sin (d);
+ d = sqrt (d);
+ d = tan (d);
+ d = trunc (d);
+ f = fabsf (f);
+ f = powf (f, f);
+ i = ilogb (d);
+ i = signbit (d);
+ l = lrint (d);
+ l = lround (d);
+ return d == f && i == l;
+ }
+ ]])],
+ [emacs_cv_lib_math='none required'],
+ [LIBS="-lm $LIBS"
+ AC_LINK_IFELSE([],
+ [emacs_cv_lib_math=-lm],
+ [AC_MSG_ERROR([Math library (-lm) not found])])])
+ LIBS=$OLD_LIBS])
+case $emacs_cv_lib_math in
+ -*) LIB_MATH=$emacs_cv_lib_math;;
+ *) LIB_MATH=;;
+esac
dnl Current possibilities handled by sed (aix4-2 -> aix,
dnl gnu-linux -> gnu/linux, etc.):
@@ -1655,8 +1723,8 @@ case $opsys in
esac
-AC_SUBST(LIB_MATH)
-AC_DEFINE_UNQUOTED(SYSTEM_TYPE, "$SYSTEM_TYPE",
+AC_SUBST([LIB_MATH])
+AC_DEFINE_UNQUOTED([SYSTEM_TYPE], ["$SYSTEM_TYPE"],
[The type of system you are compiling for; sets 'system-type'.])
AC_SUBST([SYSTEM_TYPE])
@@ -1664,11 +1732,11 @@ AC_SUBST([SYSTEM_TYPE])
pre_PKG_CONFIG_CFLAGS=$CFLAGS
pre_PKG_CONFIG_LIBS=$LIBS
-PKG_PROG_PKG_CONFIG(0.9.0)
+PKG_PROG_PKG_CONFIG([0.9.0])
-dnl EMACS_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4)
-dnl acts like PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4,
-dnl HAVE_GSTUFF=yes, HAVE_GSTUFF=no) -- see pkg-config man page --
+dnl EMACS_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4])
+dnl acts like PKG_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4],
+dnl [HAVE_GSTUFF=yes], [HAVE_GSTUFF=no]) -- see pkg-config man page --
dnl except that it postprocesses CFLAGS as needed for --enable-gcc-warnings.
dnl EMACS_CHECK_MODULES accepts optional 3rd and 4th arguments that
dnl can take the place of the default HAVE_GSTUFF=yes and HAVE_GSTUFF=no
@@ -1683,7 +1751,7 @@ HAVE_SOUND=no
if test "${with_sound}" != "no"; then
# Sound support for GNU/Linux, the free BSDs, MinGW, and Cygwin.
AC_CHECK_HEADERS([machine/soundcard.h sys/soundcard.h soundcard.h mmsystem.h],
- have_sound_header=yes, [], [
+ [have_sound_header=yes], [], [
#ifdef __MINGW32__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -1694,13 +1762,13 @@ if test "${with_sound}" != "no"; then
if test "${with_sound}" = "bsd-ossaudio" || test "${with_sound}" = "yes"; then
# Emulation library used on NetBSD.
- AC_CHECK_LIB(ossaudio, _oss_ioctl, LIBSOUND=-lossaudio, LIBSOUND=)
+ AC_CHECK_LIB([ossaudio], [_oss_ioctl], [LIBSOUND=-lossaudio], [LIBSOUND=])
test "${with_sound}" = "bsd-ossaudio" && test -z "$LIBSOUND" && \
AC_MSG_ERROR([bsd-ossaudio sound support requested but not found.])
dnl FIXME? If we did find ossaudio, should we set with_sound=bsd-ossaudio?
dnl Traditionally, we go on to check for alsa too. Does that make sense?
fi
- AC_SUBST(LIBSOUND)
+ AC_SUBST([LIBSOUND])
if test "${with_sound}" = "alsa" || test "${with_sound}" = "yes"; then
ALSA_REQUIRED=1.0.0
@@ -1709,7 +1777,7 @@ if test "${with_sound}" != "no"; then
if test $HAVE_ALSA = yes; then
LIBSOUND="$LIBSOUND $ALSA_LIBS"
CFLAGS_SOUND="$CFLAGS_SOUND $ALSA_CFLAGS"
- AC_DEFINE(HAVE_ALSA, 1, [Define to 1 if ALSA is available.])
+ AC_DEFINE([HAVE_ALSA], [1], [Define to 1 if ALSA is available.])
elif test "${with_sound}" = "alsa"; then
AC_MSG_ERROR([ALSA sound support requested but not found.])
fi
@@ -1725,25 +1793,25 @@ if test "${with_sound}" != "no"; then
dnl defined __FreeBSD__ || defined __NetBSD__ || defined __linux__
dnl Adjust the --with-sound help text if you change this.
gnu-linux|freebsd|netbsd|mingw32|cygwin)
- AC_DEFINE(HAVE_SOUND, 1, [Define to 1 if you have sound support.])
+ AC_DEFINE([HAVE_SOUND], [1], [Define to 1 if you have sound support.])
HAVE_SOUND=yes
;;
esac
fi
- AC_SUBST(CFLAGS_SOUND)
+ AC_SUBST([CFLAGS_SOUND])
fi
dnl checks for header files
AC_CHECK_HEADERS_ONCE(
- linux/fs.h
+ [linux/fs.h
malloc.h
sys/systeminfo.h
sys/sysinfo.h
coff.h pty.h
sys/resource.h
sys/utsname.h pwd.h utmp.h util.h
- sanitizer/lsan_interface.h)
+ sanitizer/lsan_interface.h])
AC_CACHE_CHECK([for ADDR_NO_RANDOMIZE],
[emacs_cv_personality_addr_no_randomize],
@@ -1770,10 +1838,11 @@ if test "$ac_cv_header_sys_sysinfo_h" = yes; then
emacs_cv_linux_sysinfo=yes, emacs_cv_linux_sysinfo=no)])
if test $emacs_cv_linux_sysinfo = yes; then
- AC_DEFINE([HAVE_LINUX_SYSINFO], 1, [Define to 1 if you have Linux sysinfo function.])
+ AC_DEFINE([HAVE_LINUX_SYSINFO], [1],
+ [Define to 1 if you have Linux sysinfo function.])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/sysinfo.h>]],
[[struct sysinfo si; return si.mem_unit]])],
- AC_DEFINE(LINUX_SYSINFO_UNIT, 1,
+ AC_DEFINE([LINUX_SYSINFO_UNIT], [1],
[Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.]))
fi
fi
@@ -1781,19 +1850,20 @@ fi
dnl On Solaris 8 there's a compilation warning for term.h because
dnl it doesn't define 'bool'.
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <term.h>]],[[]])],
- AC_DEFINE(HAVE_TERM_H, 1, [Define to 1 if you have the <term.h> header file.]))
+ [AC_DEFINE([HAVE_TERM_H], [1],
+ [Define to 1 if you have the <term.h> header file.])])
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS_ONCE(sys/socket.h)
-AC_CHECK_HEADERS(net/if.h, , , [AC_INCLUDES_DEFAULT
+AC_CHECK_HEADERS_ONCE([sys/socket.h])
+AC_CHECK_HEADERS([net/if.h], [], [], [AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif])
-AC_CHECK_HEADERS(ifaddrs.h, , , [AC_INCLUDES_DEFAULT
+AC_CHECK_HEADERS([ifaddrs.h], [], [], [AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif])
-AC_CHECK_HEADERS(net/if_dl.h, , , [AC_INCLUDES_DEFAULT
+AC_CHECK_HEADERS([net/if_dl.h], [], [], [AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif])
@@ -1802,7 +1872,7 @@ dnl checks for structure members
AC_CHECK_MEMBERS([struct ifreq.ifr_flags, struct ifreq.ifr_hwaddr,
struct ifreq.ifr_netmask, struct ifreq.ifr_broadaddr,
struct ifreq.ifr_addr,
- struct ifreq.ifr_addr.sa_len], , ,
+ struct ifreq.ifr_addr.sa_len], [], [],
[AC_INCLUDES_DEFAULT
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -1832,7 +1902,7 @@ if test "$GCC" = yes && test "$ac_enable_autodepend" = yes; then
AUTO_DEPEND=yes
fi
fi
-AC_SUBST(AUTO_DEPEND)
+AC_SUBST([AUTO_DEPEND])
#### Choose a window system.
@@ -1882,7 +1952,7 @@ ${x_library}/X11/%T/%N%S"
fi
done
fi
-AC_SUBST(LD_SWITCH_X_SITE_RPATH)
+AC_SUBST([LD_SWITCH_X_SITE_RPATH])
if test "${x_includes}" != NONE && test -n "${x_includes}"; then
C_SWITCH_X_SITE=$isystem`AS_ECHO(["$x_includes"]) | sed -e "s/:/ $isystem/g"`
@@ -1966,17 +2036,20 @@ if test "${with_ns}" != no; then
dnl GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS to 0 or 1.
dnl If they had chosen to either define it or not, we could have
dnl just used AC_CHECK_DECL here.
- AC_CACHE_CHECK(if GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS,
- emacs_cv_objc_exceptions,
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <GNUstepBase/GSConfig.h>]],
+ AC_CACHE_CHECK([if GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS],
+ [emacs_cv_objc_exceptions],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <GNUstepBase/GSConfig.h>]],
[[#if defined BASE_NATIVE_OBJC_EXCEPTIONS && BASE_NATIVE_OBJC_EXCEPTIONS > 0
1;
#else
fail;
-#endif]])], emacs_cv_objc_exceptions=yes, emacs_cv_objc_exceptions=no ) )
+#endif]])],
+ [emacs_cv_objc_exceptions=yes],
+ [emacs_cv_objc_exceptions=no])])
if test $emacs_cv_objc_exceptions = yes; then
dnl _NATIVE_OBJC_EXCEPTIONS is used by the GNUstep headers.
- AC_DEFINE(_NATIVE_OBJC_EXCEPTIONS, 1,
+ AC_DEFINE([_NATIVE_OBJC_EXCEPTIONS], [1],
[Define if GNUstep uses ObjC exceptions.])
GNU_OBJC_CFLAGS="$GNU_OBJC_CFLAGS -fobjc-exceptions"
fi
@@ -2013,8 +2086,8 @@ Either fix this, or re-configure with the option '--without-ns'.])])
#endif
#endif
])],
- ns_osx_have_106=yes,
- ns_osx_have_106=no)
+ [ns_osx_have_106=yes],
+ [ns_osx_have_106=no])
AC_MSG_RESULT([$ns_osx_have_106])
if test $ns_osx_have_106 = no; then
@@ -2022,13 +2095,24 @@ Either fix this, or re-configure with the option '--without-ns'.])])
fi
fi
+ AC_CACHE_CHECK([for Mac OS X 12.0 or later],
+ [emacs_cv_macosx_12_0],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+Mac OS X 12.x or later.
+#endif
+ ]])], [emacs_cv_macosx_12_0=no],
+ [emacs_cv_macosx_12_0=yes]))
+
if test "${with_native_image_api}" = yes; then
- AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.])
+ AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1],
+ [Define to use native OS APIs for images.])
NATIVE_IMAGE_API="yes (ns)"
fi
fi
-AC_SUBST(LIBS_GNUSTEP)
+AC_SUBST([LIBS_GNUSTEP])
INSTALL_ARCH_INDEP_EXTRA=install-etc
ns_self_contained=no
@@ -2042,7 +2126,7 @@ if test "${HAVE_NS}" = yes; then
window_system=nextstep
# set up packaging dirs
if test "${EN_NS_SELF_CONTAINED}" = yes; then
- AC_DEFINE(NS_SELF_CONTAINED, 1, [Build an NS bundled app])
+ AC_DEFINE([NS_SELF_CONTAINED], [1], [Build an NS bundled app])
ns_self_contained=yes
prefix=${ns_appresdir}
exec_prefix=${ns_appbindir}
@@ -2065,10 +2149,10 @@ if test "${HAVE_NS}" = yes; then
fi
CFLAGS="$tmp_CFLAGS"
CPPFLAGS="$tmp_CPPFLAGS"
-AC_SUBST(INSTALL_ARCH_INDEP_EXTRA)
-AC_SUBST(ns_self_contained)
-AC_SUBST(NS_OBJ)
-AC_SUBST(NS_OBJC_OBJ)
+AC_SUBST([INSTALL_ARCH_INDEP_EXTRA])
+AC_SUBST([ns_self_contained])
+AC_SUBST([NS_OBJ])
+AC_SUBST([NS_OBJC_OBJ])
if test "${HAVE_NS}" = yes; then
AC_CACHE_CHECK(
@@ -2079,12 +2163,12 @@ if test "${HAVE_NS}" = yes; then
[AC_LANG_SOURCE([[@interface Test
+ (instancetype)test;
@end]])],
- emacs_cv_objc_instancetype=yes,
- emacs_cv_objc_instancetype=no)
+ [emacs_cv_objc_instancetype=yes],
+ [emacs_cv_objc_instancetype=no])
AC_LANG_POP([Objective C])])
if test x$emacs_cv_objc_instancetype = xyes ; then
- AC_DEFINE(NATIVE_OBJC_INSTANCETYPE, 1,
+ AC_DEFINE([NATIVE_OBJC_INSTANCETYPE], [1],
[Define if ObjC compiler supports instancetype natively.])
fi
@@ -2094,8 +2178,8 @@ if test "${HAVE_NS}" = yes; then
[AC_LANG_PUSH([Objective C])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [[for (int i = 0;;);]])],
- emacs_cv_objc_c99=yes,
- emacs_cv_objc_c99=no)
+ [emacs_cv_objc_c99=yes],
+ [emacs_cv_objc_c99=no])
AC_LANG_POP([Objective C])])
if test x$emacs_cv_objc_c99 = xno ; then
@@ -2117,7 +2201,7 @@ re-configure with the option '--without-be-app'.])])
AC_LANG_POP([C++])
fi
-AC_SUBST(HAVE_BE_APP)
+AC_SUBST([HAVE_BE_APP])
HAVE_W32=no
W32_OBJ=
@@ -2165,11 +2249,11 @@ NTLIB=
CM_OBJ="cm.o"
XARGS_LIMIT=
if test "${HAVE_W32}" = "yes"; then
- AC_DEFINE(HAVE_NTGUI, 1, [Define to use native MS Windows GUI.])
+ AC_DEFINE([HAVE_NTGUI], [1], [Define to use native MS Windows GUI.])
if test "$with_toolkit_scroll_bars" = "no"; then
AC_MSG_ERROR([Non-toolkit scroll bars are not implemented for w32 build.])
fi
- AC_CHECK_TOOL(WINDRES, [windres],
+ AC_CHECK_TOOL([WINDRES], [windres],
[AC_MSG_ERROR([No resource compiler found.])])
W32_OBJ="w32fns.o w32menu.o w32reg.o w32font.o w32term.o"
W32_OBJ="$W32_OBJ w32xfns.o w32select.o w32uniscribe.o w32cygwinx.o"
@@ -2182,8 +2266,8 @@ if test "${HAVE_W32}" = "yes"; then
comma_version=`echo "${PACKAGE_VERSION}.0.0" | sed -e 's/\./,/g' -e 's/^\([[^,]]*,[[^,]]*,[[^,]]*,[[^,]]*\).*/\1/'`
comma_space_version=`echo "$comma_version" | sed 's/,/, /g'`
- AC_SUBST(comma_version)
- AC_SUBST(comma_space_version)
+ AC_SUBST([comma_version])
+ AC_SUBST([comma_space_version])
AC_CONFIG_FILES([nt/emacs.rc nt/emacsclient.rc])
if test "${opsys}" = "cygwin"; then
W32_LIBS="$W32_LIBS -lkernel32 -luser32 -lusp10 -lgdi32"
@@ -2196,7 +2280,8 @@ if test "${HAVE_W32}" = "yes"; then
dnl FIXME: This should probably be supported for Cygwin/w32 as
dnl well, but the Cygwin build needs to link against -lgdiplus
if test "${with_native_image_api}" = yes; then
- AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.])
+ AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1],
+ [Define to use native OS APIs for images.])
NATIVE_IMAGE_API="yes (w32)"
W32_OBJ="$W32_OBJ w32image.o"
fi
@@ -2220,20 +2305,20 @@ if test "${HAVE_W32}" = "no" && test "${opsys}" = "cygwin"; then
W32_OBJ="w32cygwinx.o"
fi
-AC_SUBST(W32_OBJ)
-AC_SUBST(W32_LIBS)
-AC_SUBST(EMACSRES)
-AC_SUBST(EMACS_MANIFEST)
-AC_SUBST(CLIENTRES)
-AC_SUBST(CLIENTW)
-AC_SUBST(W32_RES_LINK)
-AC_SUBST(FIRSTFILE_OBJ)
-AC_SUBST(NTDIR)
-AC_SUBST(CM_OBJ)
-AC_SUBST(LIBS_ECLIENT)
-AC_SUBST(LIB_WSOCK32)
-AC_SUBST(NTLIB)
-AC_SUBST(XARGS_LIMIT)
+AC_SUBST([W32_OBJ])
+AC_SUBST([W32_LIBS])
+AC_SUBST([EMACSRES])
+AC_SUBST([EMACS_MANIFEST])
+AC_SUBST([CLIENTRES])
+AC_SUBST([CLIENTW])
+AC_SUBST([W32_RES_LINK])
+AC_SUBST([FIRSTFILE_OBJ])
+AC_SUBST([NTDIR])
+AC_SUBST([CM_OBJ])
+AC_SUBST([LIBS_ECLIENT])
+AC_SUBST([LIB_WSOCK32])
+AC_SUBST([NTLIB])
+AC_SUBST([XARGS_LIMIT])
if test "${HAVE_W32}" = "yes"; then
window_system=w32
@@ -2250,7 +2335,7 @@ if test "$opsys" = "haiku"; then
fi
if test "${HAVE_BE_APP}" = "yes"; then
- AC_DEFINE([HAVE_HAIKU], 1,
+ AC_DEFINE([HAVE_HAIKU], [1],
[Define if Emacs will be built with Haiku windowing support])
fi
@@ -2262,16 +2347,17 @@ if test "${HAVE_BE_APP}" = "yes"; then
HAIKU_LIBS="-lbe -lgame -ltranslation -ltracker" # -lgame is needed for set_mouse_position.
if test "${with_native_image_api}" = yes; then
- AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.])
+ AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1],
+ [Define to use native OS APIs for images.])
NATIVE_IMAGE_API="yes (haiku)"
HAIKU_OBJ="$HAIKU_OBJ haikuimage.o"
fi
fi
-AC_SUBST(HAIKU_LIBS)
-AC_SUBST(HAIKU_OBJ)
-AC_SUBST(HAIKU_CXX_OBJ)
-AC_SUBST(HAIKU_CFLAGS)
+AC_SUBST([HAIKU_LIBS])
+AC_SUBST([HAIKU_OBJ])
+AC_SUBST([HAIKU_CXX_OBJ])
+AC_SUBST([HAIKU_CFLAGS])
## $window_system is now set to the window system we will
## ultimately use.
@@ -2318,16 +2404,16 @@ dnl use the toolkit if we have gtk, or X11R5 or newer.
with_gtk3=yes
USE_X_TOOLKIT=none
HAVE_PGTK=yes
- AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.])
+ AC_DEFINE([HAVE_PGTK], [1], [Define to 1 if you have pure Gtk+-3.])
;;
haiku )
term_header=haikuterm.h
;;
esac
-AC_SUBST(HAVE_PGTK)
+AC_SUBST([HAVE_PGTK])
if test "$window_system" = none && test "X$with_x" != "Xno"; then
- AC_CHECK_PROG(HAVE_XSERVER, X, true, false)
+ AC_CHECK_PROG([HAVE_XSERVER], [X], [true], [false])
if test "$HAVE_XSERVER" = true ||
test -n "$DISPLAY" ||
{
@@ -2391,7 +2477,7 @@ fi
GMALLOC_OBJ=
HYBRID_MALLOC=
if test "${system_malloc}" = "yes"; then
- AC_DEFINE([SYSTEM_MALLOC], 1,
+ AC_DEFINE([SYSTEM_MALLOC], [1],
[Define to 1 to use the system memory allocator, even if it is not
Doug Lea style.])
GNU_MALLOC=no
@@ -2399,7 +2485,7 @@ if test "${system_malloc}" = "yes"; then
(The GNU allocators don't work with this system configuration.)"
VMLIMIT_OBJ=
elif test "$hybrid_malloc" = yes; then
- AC_DEFINE(HYBRID_MALLOC, 1,
+ AC_DEFINE([HYBRID_MALLOC], [1],
[Define to use gmalloc before dumping and the system malloc after.])
HYBRID_MALLOC=1
GNU_MALLOC=no
@@ -2419,21 +2505,21 @@ else
[emacs_cv_data_start=yes],
[emacs_cv_data_start=no])])
if test $emacs_cv_data_start = yes; then
- AC_DEFINE([HAVE_DATA_START], 1,
+ AC_DEFINE([HAVE_DATA_START], [1],
[Define to 1 if data_start is the address of the start
of the main data segment.])
fi
fi
AC_SUBST([HYBRID_MALLOC])
-AC_SUBST(GMALLOC_OBJ)
-AC_SUBST(VMLIMIT_OBJ)
+AC_SUBST([GMALLOC_OBJ])
+AC_SUBST([VMLIMIT_OBJ])
if test "$doug_lea_malloc" = "yes" && test "$hybrid_malloc" != yes; then
if test "$GNU_MALLOC" = yes ; then
GNU_MALLOC_reason="
(Using Doug Lea's new malloc from the GNU C Library.)"
fi
- AC_DEFINE(DOUG_LEA_MALLOC, 1,
+ AC_DEFINE([DOUG_LEA_MALLOC], [1],
[Define to 1 if the system memory allocator is Doug Lea style,
with malloc hooks and malloc_set_state.])
@@ -2457,18 +2543,19 @@ esac
AC_FUNC_MMAP
if test $use_mmap_for_buffers = yes; then
- AC_DEFINE(USE_MMAP_FOR_BUFFERS, 1, [Define to use mmap to allocate buffer text.])
+ AC_DEFINE([USE_MMAP_FOR_BUFFERS], [1],
+ [Define to use mmap to allocate buffer text.])
REL_ALLOC=no
fi
LIBS="$LIBS_SYSTEM $LIBS"
dnl FIXME replace main with a function we actually want from this library.
-AC_CHECK_LIB(Xbsd, main, LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd")
+AC_CHECK_LIB([Xbsd], [main], [LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd"])
dnl Check for the POSIX thread library.
LIB_PTHREAD=
-AC_CHECK_HEADERS_ONCE(pthread.h)
+AC_CHECK_HEADERS_ONCE([pthread.h])
if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then
AC_CACHE_CHECK([for pthread library],
[emacs_cv_pthread_lib],
@@ -2503,7 +2590,7 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then
fi
done])
if test "$emacs_cv_pthread_lib" != no; then
- AC_DEFINE([HAVE_PTHREAD], 1, [Define to 1 if you have POSIX threads.])
+ AC_DEFINE([HAVE_PTHREAD], [1], [Define to 1 if you have POSIX threads.])
case $emacs_cv_pthread_lib in
-*) LIB_PTHREAD=$emacs_cv_pthread_lib;;
esac
@@ -2513,10 +2600,10 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then
# definition of 'errno' in <errno.h>.
case $opsys in
hpux* | solaris)
- AC_DEFINE([_REENTRANT], 1,
+ AC_DEFINE([_REENTRANT], [1],
[Define to 1 if your system requires this in multithreaded code.]);;
aix4-2)
- AC_DEFINE([_THREAD_SAFE], 1,
+ AC_DEFINE([_THREAD_SAFE], [1],
[Define to 1 if your system requires this in multithreaded code.]);;
esac
fi
@@ -2527,12 +2614,12 @@ AC_MSG_CHECKING([for thread support])
threads_enabled=no
if test "$with_threads" = yes; then
if test "$emacs_cv_pthread_lib" != no; then
- AC_DEFINE(THREADS_ENABLED, 1,
+ AC_DEFINE([THREADS_ENABLED], [1],
[Define to 1 if you want elisp thread support.])
threads_enabled=yes
elif test "${opsys}" = "mingw32"; then
dnl MinGW can do native Windows threads even without pthreads
- AC_DEFINE(THREADS_ENABLED, 1,
+ AC_DEFINE([THREADS_ENABLED], [1],
[Define to 1 if you want elisp thread support.])
threads_enabled=yes
fi
@@ -2617,38 +2704,42 @@ if test "${HAVE_X11}" = "yes"; then
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <X11/Xlib.h>
#include <X11/XKBlib.h>]],
[[XkbDescPtr kb = XkbGetKeyboard (0, XkbAllComponentsMask, XkbUseCoreKbd);]])],
- emacs_cv_xkb=yes, emacs_cv_xkb=no)])
+ [emacs_cv_xkb=yes],
+ [emacs_cv_xkb=no])])
if test $emacs_cv_xkb = yes; then
- AC_DEFINE(HAVE_XKB, 1, [Define to 1 if you have the Xkb extension.])
+ AC_DEFINE([HAVE_XKB], [1], [Define to 1 if you have the Xkb extension.])
+ AC_CHECK_FUNCS([XkbRefreshKeyboardMapping XkbFreeNames])
fi
- AC_CHECK_FUNCS(XrmSetDatabase XScreenResourceString \
-XScreenNumberOfScreen)
+ AC_CHECK_FUNCS([XrmSetDatabase XScreenResourceString XScreenNumberOfScreen])
+ AC_CHECK_FUNCS([XDisplayCells XDestroySubwindows])
fi
if test "${window_system}" = "x11"; then
- AC_MSG_CHECKING(X11 version 6)
- AC_CACHE_VAL(emacs_cv_x11_version_6,
+ AC_MSG_CHECKING([X11 version 6])
+ AC_CACHE_VAL([emacs_cv_x11_version_6],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <X11/Xlib.h>]],
[[#if XlibSpecificationRelease < 6
fail;
#endif
-]])], emacs_cv_x11_version_6=yes, emacs_cv_x11_version_6=no)])
+]])], [emacs_cv_x11_version_6=yes],
+ [emacs_cv_x11_version_6=no])])
if test $emacs_cv_x11_version_6 = yes; then
- AC_MSG_RESULT(6 or newer)
- AC_DEFINE(HAVE_X11R6, 1,
+ AC_MSG_RESULT([6 or newer])
+ AC_DEFINE([HAVE_X11R6], [1],
[Define to 1 if you have the X11R6 or newer version of Xlib.])
- AC_DEFINE(HAVE_X_I18N, 1, [Define if you have usable i18n support.])
+ AC_DEFINE([HAVE_X_I18N], [1], [Define if you have usable i18n support.])
+ AC_CHECK_MEMBERS([XICCallback.callback], [], [], [#include <X11/Xlib.h>])
## inoue@ainet.or.jp says Solaris has a bug related to X11R6-style
## XIM support.
case "$opsys" in
solaris) : ;;
- *) AC_DEFINE(HAVE_X11R6_XIM, 1,
+ *) AC_DEFINE([HAVE_X11R6_XIM], [1],
[Define if you have usable X11R6-style XIM support.])
;;
esac
else
- AC_MSG_RESULT(before 6)
+ AC_MSG_RESULT([before 6])
fi
fi
@@ -2663,11 +2754,11 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" \
RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED"
EMACS_CHECK_MODULES([RSVG], [$RSVG_MODULE])
- AC_SUBST(RSVG_CFLAGS)
- AC_SUBST(RSVG_LIBS)
+ AC_SUBST([RSVG_CFLAGS])
+ AC_SUBST([RSVG_LIBS])
if test $HAVE_RSVG = yes; then
- AC_DEFINE(HAVE_RSVG, 1, [Define to 1 if using librsvg.])
+ AC_DEFINE([HAVE_RSVG], [1], [Define to 1 if using librsvg.])
CFLAGS="$CFLAGS $RSVG_CFLAGS"
# Windows loads librsvg dynamically
if test "${opsys}" = "mingw32"; then
@@ -2687,11 +2778,14 @@ if test "${with_webp}" != "no"; then
WEBP_MODULE="libwebp >= $WEBP_REQUIRED"
EMACS_CHECK_MODULES([WEBP], [$WEBP_MODULE])
- AC_SUBST(WEBP_CFLAGS)
- AC_SUBST(WEBP_LIBS)
+ if test "$HAVE_WEBP" = "yes"; then
+ WEBP_LIBS="-lwebp -lwebpdemux"
+ fi
+ AC_SUBST([WEBP_CFLAGS])
+ AC_SUBST([WEBP_LIBS])
fi
if test $HAVE_WEBP = yes; then
- AC_DEFINE(HAVE_WEBP, 1, [Define to 1 if using libwebp.])
+ AC_DEFINE([HAVE_WEBP], [1], [Define to 1 if using libwebp.])
CFLAGS="$CFLAGS $WEBP_CFLAGS"
# Windows loads libwebp dynamically
if test "${opsys}" = "mingw32"; then
@@ -2703,20 +2797,25 @@ fi
### Use -lsqlite3 if available, unless '--with-sqlite3=no'
HAVE_SQLITE3=no
if test "${with_sqlite3}" != "no"; then
- AC_CHECK_LIB(sqlite3, sqlite3_open_v2, HAVE_SQLITE3=yes, HAVE_SQLITE3=no)
+ AC_CHECK_LIB([sqlite3], [sqlite3_open_v2],
+ [HAVE_SQLITE3=yes],
+ [HAVE_SQLITE3=no])
if test "$HAVE_SQLITE3" = "yes"; then
SQLITE3_LIBS=-lsqlite3
- AC_SUBST(SQLITE3_LIBS)
+ AC_SUBST([SQLITE3_LIBS])
LIBS="$SQLITE3_LIBS $LIBS"
- AC_DEFINE(HAVE_SQLITE3, 1, [Define to 1 if you have the libsqlite3 library (-lsqlite).])
+ AC_DEFINE([HAVE_SQLITE3], [1],
+ [Define to 1 if you have the libsqlite3 library (-lsqlite).])
# Windows loads libsqlite dynamically
if test "${opsys}" = "mingw32"; then
SQLITE3_LIBS=
fi
- AC_CHECK_LIB(sqlite3, sqlite3_load_extension,
- HAVE_SQLITE3_LOAD_EXTENSION=yes, HAVE_SQLITE3_LOAD_EXTENSION=no)
+ AC_CHECK_LIB([sqlite3], [sqlite3_load_extension],
+ [HAVE_SQLITE3_LOAD_EXTENSION=yes],
+ [HAVE_SQLITE3_LOAD_EXTENSION=no])
if test "$HAVE_SQLITE3_LOAD_EXTENSION" = "yes"; then
- AC_DEFINE(HAVE_SQLITE3_LOAD_EXTENSION, 1, [Define to 1 if sqlite3 supports loading extensions.])
+ AC_DEFINE([HAVE_SQLITE3_LOAD_EXTENSION], [1],
+ [Define to 1 if sqlite3 supports loading extensions.])
fi
fi
fi
@@ -2733,7 +2832,8 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}"
EMACS_CHECK_MODULES([IMAGEMAGICK], [MagickWand >= 7])
if test $HAVE_IMAGEMAGICK = yes; then
- AC_DEFINE([HAVE_IMAGEMAGICK7], 1, [Define to 1 if using ImageMagick7.])
+ AC_DEFINE([HAVE_IMAGEMAGICK7], [1],
+ [Define to 1 if using ImageMagick7.])
else
## 6.3.5 is the earliest version known to work; see Bug#17339.
## 6.8.2 makes Emacs crash; see Bug#13867.
@@ -2757,7 +2857,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}"
fi
fi
if test $HAVE_IMAGEMAGICK = yes; then
- AC_DEFINE([HAVE_IMAGEMAGICK], 1, [Define to 1 if using ImageMagick.])
+ AC_DEFINE([HAVE_IMAGEMAGICK], [1], [Define to 1 if using ImageMagick.])
else
if test "${with_imagemagick}" != "no"; then
AC_MSG_ERROR([ImageMagick wanted, but it does not compile. Maybe some library files are missing?]);
@@ -2770,12 +2870,12 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}"
fi
fi
-AC_CHECK_LIB(anl, getaddrinfo_a, HAVE_GETADDRINFO_A=yes)
+AC_CHECK_LIB([anl], [getaddrinfo_a], [HAVE_GETADDRINFO_A=yes])
if test "${HAVE_GETADDRINFO_A}" = "yes"; then
- AC_DEFINE(HAVE_GETADDRINFO_A, 1,
+ AC_DEFINE([HAVE_GETADDRINFO_A], [1],
[Define to 1 if you have getaddrinfo_a for asynchronous DNS resolution.])
GETADDRINFO_A_LIBS="-lanl"
- AC_SUBST(GETADDRINFO_A_LIBS)
+ AC_SUBST([GETADDRINFO_A_LIBS])
fi
HAVE_GTK=no
@@ -2786,17 +2886,21 @@ gtk3_pkg_errors=
if test "${opsys}" != "mingw32"; then
if test "${with_gtk3}" = "yes" || test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "maybe"; then
GLIB_REQUIRED=2.37.5
- GTK_REQUIRED=3.10
+ if test "${window_system}" = "x11"; then
+ GTK_REQUIRED=3.10
+ else
+ GTK_REQUIRED=3.22.23
+ fi
GTK_MODULES="gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
dnl Checks for libraries.
EMACS_CHECK_MODULES([GTK], [$GTK_MODULES],
[pkg_check_gtk=yes], [pkg_check_gtk=no])
if test "$pkg_check_gtk" = "no" && test "$with_gtk3" = "yes"; then
- AC_MSG_ERROR($GTK_PKG_ERRORS)
+ AC_MSG_ERROR([$GTK_PKG_ERRORS])
fi
if test "$pkg_check_gtk" = "yes"; then
- AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.])
+ AC_DEFINE([HAVE_GTK3], [1], [Define to 1 if using GTK 3 or later.])
GTK_OBJ=emacsgtkfixed.o
gtk_term_header=gtkutil.h
USE_GTK_TOOLKIT="GTK3"
@@ -2806,9 +2910,6 @@ if test "${opsys}" != "mingw32"; then
AC_DEFINE([GLIB_DISABLE_DEPRECATION_WARNINGS], [1],
[Define to 1 to disable Glib deprecation warnings.])
fi
- if test "$window_system" = pgtk; then
- GLIB_GSETTINGS
- fi
else
check_gtk2=yes
gtk3_pkg_errors="$GTK_PKG_ERRORS "
@@ -2826,7 +2927,7 @@ if test "${opsys}" != "mingw32"; then
if test "$pkg_check_gtk" = "no" &&
{ test "$with_gtk" = yes || test "$with_gtk2" = "yes"; }
then
- AC_MSG_ERROR($gtk3_pkg_errors$GTK_PKG_ERRORS)
+ AC_MSG_ERROR([$gtk3_pkg_errors$GTK_PKG_ERRORS])
fi
test "$pkg_check_gtk" = "yes" && USE_GTK_TOOLKIT="GTK2"
fi
@@ -2837,7 +2938,7 @@ OLD_LIBS=$LIBS
if test x"$pkg_check_gtk" = xyes; then
- AC_SUBST(GTK_LIBS)
+ AC_SUBST([GTK_LIBS])
CFLAGS="$CFLAGS $GTK_CFLAGS"
LIBS="$GTK_LIBS $LIBS"
dnl Try to compile a simple GTK program.
@@ -2869,7 +2970,7 @@ if test x"$pkg_check_gtk" = xyes; then
else
C_SWITCH_X_SITE="$C_SWITCH_X_SITE $GTK_CFLAGS"
HAVE_GTK=yes
- AC_DEFINE(USE_GTK, 1, [Define to 1 if using GTK.])
+ AC_DEFINE([USE_GTK], [1], [Define to 1 if using GTK.])
GTK_OBJ="gtkutil.o $GTK_OBJ"
term_header=$gtk_term_header
USE_X_TOOLKIT=none
@@ -2881,7 +2982,7 @@ if test x"$pkg_check_gtk" = xyes; then
fi
fi
-AC_SUBST(GTK_OBJ)
+AC_SUBST([GTK_OBJ])
if test "${HAVE_GTK}" = "yes"; then
@@ -2901,52 +3002,20 @@ if test "${HAVE_GTK}" = "yes"; then
dnl but not declared if deprecated featured has been selected out.
dnl AC_CHECK_DECL checks for a macro, so check for GTK_TYPE_FILE_SELECTION.
HAVE_GTK_FILE_SELECTION=no
- AC_CHECK_DECL(GTK_TYPE_FILE_SELECTION, HAVE_GTK_FILE_SELECTION=yes,
- HAVE_GTK_FILE_SELECTION=no, [AC_INCLUDES_DEFAULT
+ AC_CHECK_DECL([GTK_TYPE_FILE_SELECTION],
+ [HAVE_GTK_FILE_SELECTION=yes],
+ [HAVE_GTK_FILE_SELECTION=no],
+ [AC_INCLUDES_DEFAULT
#include <gtk/gtk.h>])
if test "$HAVE_GTK_FILE_SELECTION" = yes; then
- AC_CHECK_FUNCS(gtk_file_selection_new)
+ AC_CHECK_FUNCS([gtk_file_selection_new])
fi
dnl This procedure causes a bug on certain Ubuntu GTK+2 builds
- AC_CHECK_FUNCS(gtk_window_set_has_resize_grip)
+ AC_CHECK_FUNCS([gtk_window_set_has_resize_grip])
fi
fi
-
-dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
-dnl Enable xwidgets if macOS Cocoa and WebKit framework are available.
-HAVE_XWIDGETS=no
-XWIDGETS_OBJ=
-if test "$with_xwidgets" != "no"; then
- if test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none"; then
- WEBKIT_REQUIRED=2.12
- WEBKIT_MODULES="webkit2gtk-4.0 >= $WEBKIT_REQUIRED"
- EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
- HAVE_XWIDGETS=$HAVE_WEBKIT
- XWIDGETS_OBJ="xwidget.o"
- elif test "${NS_IMPL_COCOA}" = "yes"; then
- dnl FIXME: Check framework WebKit2
- dnl WEBKIT_REQUIRED=M.m.p
- WEBKIT_LIBS="-Wl,-framework -Wl,WebKit"
- WEBKIT_CFLAGS="-I/System/Library/Frameworks/WebKit.framework/Headers"
- HAVE_WEBKIT="yes"
- HAVE_XWIDGETS=$HAVE_WEBKIT
- XWIDGETS_OBJ="xwidget.o"
- NS_OBJC_OBJ="$NS_OBJC_OBJ nsxwidget.o"
- dnl Update NS_OBJC_OBJ with added nsxwidget.o
- AC_SUBST(NS_OBJC_OBJ)
- else
- AC_MSG_ERROR([xwidgets requested, it requires GTK3 as X window toolkit or macOS Cocoa as window system.])
- fi
-
- test $HAVE_XWIDGETS = yes ||
- AC_MSG_ERROR([xwidgets requested but WebKitGTK+ or WebKit framework not found.])
-
- AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.])
-fi
-AC_SUBST(XWIDGETS_OBJ)
-
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
@@ -2956,8 +3025,10 @@ if test "$window_system" = "pgtk"; then
PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o pgtkim.o xsettings.o"
PGTK_LIBS="$GTK_LIBS"
fi
-AC_SUBST(PGTK_OBJ)
-AC_SUBST(PGTK_LIBS)
+AC_SUBST([PGTK_OBJ])
+AC_SUBST([PGTK_LIBS])
+
+AC_CHECK_FUNCS([malloc_trim])
dnl D-Bus has been tested under GNU/Linux only. Must be adapted for
dnl other platforms.
@@ -2966,25 +3037,25 @@ DBUS_OBJ=
if test "${with_dbus}" = "yes"; then
EMACS_CHECK_MODULES([DBUS], [dbus-1 >= 1.0])
if test "$HAVE_DBUS" = yes; then
- AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if using D-Bus.])
+ AC_DEFINE([HAVE_DBUS], [1], [Define to 1 if using D-Bus.])
dnl dbus_watch_get_unix_fd has been introduced in D-Bus 1.1.1.
dnl dbus_type_is_valid and dbus_validate_* have been introduced in
dnl D-Bus 1.5.12.
OLD_LIBS=$LIBS
LIBS="$LIBS $DBUS_LIBS"
- AC_CHECK_FUNCS(dbus_watch_get_unix_fd \
+ AC_CHECK_FUNCS([dbus_watch_get_unix_fd \
dbus_type_is_valid \
dbus_validate_bus_name \
dbus_validate_path \
dbus_validate_interface \
- dbus_validate_member)
+ dbus_validate_member])
LIBS=$OLD_LIBS
DBUS_OBJ=dbusbind.o
fi
fi
-AC_SUBST(DBUS_CFLAGS)
-AC_SUBST(DBUS_LIBS)
-AC_SUBST(DBUS_OBJ)
+AC_SUBST([DBUS_CFLAGS])
+AC_SUBST([DBUS_LIBS])
+AC_SUBST([DBUS_OBJ])
dnl GSettings has been tested under GNU/Linux only.
HAVE_GSETTINGS=no
@@ -3009,7 +3080,7 @@ if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gse
[emacs_cv_gsettings_in_gio=yes], [emacs_cv_gsettings_in_gio=no])])
if test "$emacs_cv_gsettings_in_gio" = "yes"; then
- AC_DEFINE(HAVE_GSETTINGS, 1, [Define to 1 if using GSettings.])
+ AC_DEFINE([HAVE_GSETTINGS], [1], [Define to 1 if using GSettings.])
SETTINGS_CFLAGS="$GSETTINGS_CFLAGS"
SETTINGS_LIBS="$GSETTINGS_LIBS"
test "$with_gconf" = "yes" || with_gconf=no
@@ -3018,7 +3089,7 @@ if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gse
LIBS=$old_LIBS
fi
fi
-AC_SUBST(HAVE_GSETTINGS)
+AC_SUBST([HAVE_GSETTINGS])
dnl GConf has been tested under GNU/Linux only.
dnl The version is really arbitrary, it is about the same age as Gtk+ 2.6.
@@ -3026,7 +3097,7 @@ HAVE_GCONF=no
if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gconf}" != "no"; then
EMACS_CHECK_MODULES([GCONF], [gconf-2.0 >= 2.13])
if test "$HAVE_GCONF" = yes; then
- AC_DEFINE(HAVE_GCONF, 1, [Define to 1 if using GConf.])
+ AC_DEFINE([HAVE_GCONF], [1], [Define to 1 if using GConf.])
dnl Newer GConf doesn't link with g_objects, so this is not defined.
SETTINGS_CFLAGS="$SETTINGS_CFLAGS $GCONF_CFLAGS"
SETTINGS_LIBS="$SETTINGS_LIBS $GCONF_LIBS"
@@ -3046,33 +3117,35 @@ if test "$HAVE_GSETTINGS" = "yes" || test "$HAVE_GCONF" = "yes"; then
CFLAGS="$SAVE_CFLAGS"
LIBS="$SAVE_LIBS"
fi
-AC_SUBST(SETTINGS_CFLAGS)
-AC_SUBST(SETTINGS_LIBS)
+AC_SUBST([SETTINGS_CFLAGS])
+AC_SUBST([SETTINGS_LIBS])
USE_STARTUP_NOTIFICATION=no
if test "${HAVE_GTK}" = "yes"; then
USE_STARTUP_NOTIFICATION=yes
fi
-AC_SUBST(USE_STARTUP_NOTIFICATION)
+AC_SUBST([USE_STARTUP_NOTIFICATION])
dnl SELinux is available for GNU/Linux only.
HAVE_LIBSELINUX=no
LIBSELINUX_LIBS=
if test "${with_selinux}" = "yes"; then
- AC_CHECK_LIB([selinux], [lgetfilecon], HAVE_LIBSELINUX=yes, HAVE_LIBSELINUX=no)
+ AC_CHECK_LIB([selinux], [lgetfilecon],
+ [HAVE_LIBSELINUX=yes],
+ [HAVE_LIBSELINUX=no])
if test "$HAVE_LIBSELINUX" = yes; then
- AC_DEFINE(HAVE_LIBSELINUX, 1, [Define to 1 if using SELinux.])
+ AC_DEFINE([HAVE_LIBSELINUX], [1], [Define to 1 if using SELinux.])
LIBSELINUX_LIBS=-lselinux
fi
fi
-AC_SUBST(LIBSELINUX_LIBS)
+AC_SUBST([LIBSELINUX_LIBS])
HAVE_GNUTLS=no
if test "${with_gnutls}" != "no" ; then
EMACS_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.12.2],
[HAVE_GNUTLS=yes], [HAVE_GNUTLS=no])
if test "${HAVE_GNUTLS}" = "yes"; then
- AC_DEFINE(HAVE_GNUTLS, 1, [Define if using GnuTLS.])
+ AC_DEFINE([HAVE_GNUTLS], [1], [Define if using GnuTLS.])
fi
# Windows loads GnuTLS dynamically
@@ -3081,8 +3154,8 @@ if test "${with_gnutls}" != "no" ; then
fi
fi
-AC_SUBST(LIBGNUTLS_LIBS)
-AC_SUBST(LIBGNUTLS_CFLAGS)
+AC_SUBST([LIBGNUTLS_LIBS])
+AC_SUBST([LIBGNUTLS_CFLAGS])
HAVE_LIBSYSTEMD=no
if test "${with_libsystemd}" = "yes" ; then
@@ -3092,12 +3165,12 @@ if test "${with_libsystemd}" = "yes" ; then
EMACS_CHECK_MODULES([LIBSYSTEMD], [libsystemd >= 222],
[HAVE_LIBSYSTEMD=yes], [HAVE_LIBSYSTEMD=no])
if test "${HAVE_LIBSYSTEMD}" = "yes"; then
- AC_DEFINE(HAVE_LIBSYSTEMD, 1, [Define if using libsystemd.])
+ AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define if using libsystemd.])
fi
fi
-AC_SUBST(LIBSYSTEMD_LIBS)
-AC_SUBST(LIBSYSTEMD_CFLAGS)
+AC_SUBST([LIBSYSTEMD_LIBS])
+AC_SUBST([LIBSYSTEMD_CFLAGS])
HAVE_JSON=no
JSON_OBJ=
@@ -3106,7 +3179,7 @@ if test "${with_json}" != no; then
EMACS_CHECK_MODULES([JSON], [jansson >= 2.7],
[HAVE_JSON=yes], [HAVE_JSON=no])
if test "${HAVE_JSON}" = yes; then
- AC_DEFINE(HAVE_JSON, 1, [Define if using Jansson.])
+ AC_DEFINE([HAVE_JSON], [1], [Define if using Jansson.])
JSON_OBJ=json.o
fi
@@ -3116,9 +3189,9 @@ if test "${with_json}" != no; then
fi
fi
-AC_SUBST(JSON_LIBS)
-AC_SUBST(JSON_CFLAGS)
-AC_SUBST(JSON_OBJ)
+AC_SUBST([JSON_LIBS])
+AC_SUBST([JSON_CFLAGS])
+AC_SUBST([JSON_OBJ])
NOTIFY_OBJ=
NOTIFY_SUMMARY=no
@@ -3131,9 +3204,9 @@ case $with_file_notification,$opsys in
Consider using gfile instead.])
;;
w32,* | yes,mingw32)
- AC_CHECK_HEADER(windows.h)
+ AC_CHECK_HEADER([windows.h])
if test "$ac_cv_header_windows_h" = yes ; then
- AC_DEFINE(HAVE_W32NOTIFY, 1, [Define to 1 to use w32notify.])
+ AC_DEFINE([HAVE_W32NOTIFY], [1], [Define to 1 to use w32notify.])
NOTIFY_OBJ=w32notify.o
NOTIFY_SUMMARY="yes (w32)"
fi ;;
@@ -3142,11 +3215,11 @@ esac
dnl inotify is available only on GNU/Linux.
case $with_file_notification,$NOTIFY_OBJ in
inotify, | yes,)
- AC_CHECK_HEADER(sys/inotify.h)
+ AC_CHECK_HEADER([sys/inotify.h])
if test "$ac_cv_header_sys_inotify_h" = yes ; then
- AC_CHECK_FUNC(inotify_init1)
+ AC_CHECK_FUNC([inotify_init1])
if test "$ac_cv_func_inotify_init1" = yes; then
- AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.])
+ AC_DEFINE([HAVE_INOTIFY], [1], [Define to 1 to use inotify.])
NOTIFY_OBJ=inotify.o
NOTIFY_SUMMARY="yes -lglibc (inotify)"
fi
@@ -3158,16 +3231,16 @@ case $with_file_notification,$NOTIFY_OBJ in
kqueue,* | yes,)
EMACS_CHECK_MODULES([KQUEUE], [libkqueue])
if test "$HAVE_KQUEUE" = "yes"; then
- AC_DEFINE(HAVE_KQUEUE, 1, [Define to 1 to use kqueue.])
+ AC_DEFINE([HAVE_KQUEUE], [1], [Define to 1 to use kqueue.])
CPPFLAGS="$CPPFLAGS -I/usr/include/kqueue"
NOTIFY_CFLAGS=$KQUEUE_CFLAGS
NOTIFY_LIBS=$KQUEUE_LIBS
NOTIFY_OBJ=kqueue.o
NOTIFY_SUMMARY="yes -lkqueue"
else
- AC_SEARCH_LIBS(kqueue, [])
+ AC_SEARCH_LIBS([kqueue], [])
if test "$ac_cv_search_kqueue" != no; then
- AC_DEFINE(HAVE_KQUEUE, 1, [Define to 1 to use kqueue.])
+ AC_DEFINE([HAVE_KQUEUE], [1], [Define to 1 to use kqueue.])
NOTIFY_OBJ=kqueue.o
NOTIFY_SUMMARY="yes (kqueue)"
fi
@@ -3185,7 +3258,7 @@ Consider kqueue instead.])
else
EMACS_CHECK_MODULES([GFILENOTIFY], [gio-2.0 >= 2.24])
if test "$HAVE_GFILENOTIFY" = "yes"; then
- AC_DEFINE(HAVE_GFILENOTIFY, 1, [Define to 1 if using GFile.])
+ AC_DEFINE([HAVE_GFILENOTIFY], [1], [Define to 1 if using GFile.])
NOTIFY_CFLAGS=$GFILENOTIFY_CFLAGS
NOTIFY_LIBS=$GFILENOTIFY_LIBS
NOTIFY_OBJ=gfilenotify.o
@@ -3200,11 +3273,12 @@ case $with_file_notification,$NOTIFY_OBJ in
esac
if test -n "$NOTIFY_OBJ"; then
- AC_DEFINE(USE_FILE_NOTIFY, 1, [Define to 1 if using file notifications.])
+ AC_DEFINE([USE_FILE_NOTIFY], [1],
+ [Define to 1 if using file notifications.])
fi
-AC_SUBST(NOTIFY_CFLAGS)
-AC_SUBST(NOTIFY_LIBS)
-AC_SUBST(NOTIFY_OBJ)
+AC_SUBST([NOTIFY_CFLAGS])
+AC_SUBST([NOTIFY_LIBS])
+AC_SUBST([NOTIFY_OBJ])
dnl Do not put whitespace before the #include statements below.
dnl Older compilers (eg sunos4 cc) choke on it.
@@ -3212,36 +3286,37 @@ HAVE_XAW3D=no
LUCID_LIBW=
if test x"${USE_X_TOOLKIT}" = xmaybe || test x"${USE_X_TOOLKIT}" = xLUCID; then
if test "$with_xaw3d" != no; then
- AC_CACHE_VAL(emacs_cv_xaw3d,
+ AC_CACHE_VAL([emacs_cv_xaw3d],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <X11/Intrinsic.h>
#include <X11/Xaw3d/Simple.h>]],
[[]])],
- [AC_CHECK_LIB(Xaw3d, XawScrollbarSetThumb,
- emacs_cv_xaw3d=yes, emacs_cv_xaw3d=no)],
- emacs_cv_xaw3d=no)])
+ [AC_CHECK_LIB([Xaw3d], [XawScrollbarSetThumb],
+ [emacs_cv_xaw3d=yes],
+ [emacs_cv_xaw3d=no])],
+ [emacs_cv_xaw3d=no])])
else
emacs_cv_xaw3d=no
fi
if test $emacs_cv_xaw3d = yes; then
- AC_MSG_CHECKING(for xaw3d)
+ AC_MSG_CHECKING([for xaw3d])
AC_MSG_RESULT([yes; using Lucid toolkit])
USE_X_TOOLKIT=LUCID
HAVE_XAW3D=yes
LUCID_LIBW=-lXaw3d
- AC_DEFINE(HAVE_XAW3D, 1,
+ AC_DEFINE([HAVE_XAW3D], [1],
[Define to 1 if you have the Xaw3d library (-lXaw3d).])
else
- AC_MSG_CHECKING(for xaw3d)
- AC_MSG_RESULT(no)
- AC_MSG_CHECKING(for libXaw)
- AC_CACHE_VAL(emacs_cv_xaw,
+ AC_MSG_CHECKING([for xaw3d])
+ AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for libXaw])
+ AC_CACHE_VAL([emacs_cv_xaw],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <X11/Intrinsic.h>
#include <X11/Xaw/Simple.h>]],
[[]])],
- emacs_cv_xaw=yes,
- emacs_cv_xaw=no)])
+ [emacs_cv_xaw=yes],
+ [emacs_cv_xaw=no])])
if test $emacs_cv_xaw = yes; then
AC_MSG_RESULT([yes; using Lucid toolkit])
USE_X_TOOLKIT=LUCID
@@ -3263,17 +3338,18 @@ X_TOOLKIT_TYPE=$USE_X_TOOLKIT
LIBXTR6=
LIBXMU=
if test "${USE_X_TOOLKIT}" != "none"; then
- AC_MSG_CHECKING(X11 toolkit version)
- AC_CACHE_VAL(emacs_cv_x11_toolkit_version_6,
+ AC_MSG_CHECKING([X11 toolkit version])
+ AC_CACHE_VAL([emacs_cv_x11_toolkit_version_6],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <X11/Intrinsic.h>]],
[[#if XtSpecificationRelease < 6
fail;
#endif
-]])], emacs_cv_x11_toolkit_version_6=yes, emacs_cv_x11_toolkit_version_6=no)])
+]])], [emacs_cv_x11_toolkit_version_6=yes],
+ [emacs_cv_x11_toolkit_version_6=no])])
HAVE_X11XTR6=$emacs_cv_x11_toolkit_version_6
if test $emacs_cv_x11_toolkit_version_6 = yes; then
- AC_MSG_RESULT(6 or newer)
- AC_DEFINE(HAVE_X11XTR6, 1,
+ AC_MSG_RESULT([6 or newer])
+ AC_DEFINE([HAVE_X11XTR6], [1],
[Define to 1 if you have the X11R6 or newer version of Xt.])
LIBXTR6="-lSM -lICE"
case "$opsys" in
@@ -3281,7 +3357,7 @@ fail;
unixware) LIBXTR6="$LIBXTR6 -lw" ;;
esac
else
- AC_MSG_RESULT(before 6)
+ AC_MSG_RESULT([before 6])
fi
dnl If using toolkit, check whether libXmu.a exists.
@@ -3299,8 +3375,8 @@ dnl tranle@intellicorp.com says libXmu.a can need XtMalloc in libXt.a to link.
LIBS=$OLDLIBS
dnl ac_cv_search_XmuConvertStandardSelection is also referenced below.
fi
-AC_SUBST(LIBXTR6)
-AC_SUBST(LIBXMU)
+AC_SUBST([LIBXTR6])
+AC_SUBST([LIBXMU])
LIBXP=
if test "${USE_X_TOOLKIT}" = "MOTIF"; then
@@ -3318,21 +3394,21 @@ if test "${USE_X_TOOLKIT}" = "MOTIF"; then
else
emacs_cv_openmotif=no
fi
- AC_CACHE_CHECK(for (Open)Motif version 2.1, emacs_cv_motif_version_2_1,
+ AC_CACHE_CHECK([for (Open)Motif version 2.1], [emacs_cv_motif_version_2_1],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <Xm/Xm.h>]],
[[#if XmVERSION > 2 || (XmVERSION == 2 && XmREVISION >= 1)
int x = 5;
#else
Motif version prior to 2.1.
#endif]])],
- emacs_cv_motif_version_2_1=yes, emacs_cv_motif_version_2_1=no)])
+ [emacs_cv_motif_version_2_1=yes],
+ [emacs_cv_motif_version_2_1=no])])
if test $emacs_cv_motif_version_2_1 = yes; then
- AC_CHECK_LIB(Xp, XpCreateContext, LIBXP=-lXp)
+ AC_CHECK_LIB([Xp], [XpCreateContext], [LIBXP=-lXp])
if test x$emacs_cv_openmotif = xyes; then
REAL_CPPFLAGS="-I/usr/include/openmotif $REAL_CPPFLAGS"
fi
else
- AC_CACHE_CHECK(for LessTif where some systems put it, emacs_cv_lesstif,
# We put this in CFLAGS temporarily to precede other -I options
# that might be in CFLAGS temporarily.
# We put this in CPPFLAGS where it precedes the other -I options.
@@ -3340,9 +3416,14 @@ Motif version prior to 2.1.
OLD_CFLAGS=$CFLAGS
CPPFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CPPFLAGS"
CFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CFLAGS"
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include </usr/X11R6/LessTif/Motif1.2/include/Xm/Xm.h>]],
- [[int x = 5;]])],
- emacs_cv_lesstif=yes, emacs_cv_lesstif=no)])
+ AC_CACHE_CHECK([for LessTif where some systems put it], [emacs_cv_lesstif],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include </usr/X11R6/LessTif/Motif1.2/include/Xm/Xm.h>
+ ]],
+ [[int x = 5;]])],
+ [emacs_cv_lesstif=yes],
+ [emacs_cv_lesstif=no])])
if test $emacs_cv_lesstif = yes; then
# Make sure this -I option remains in CPPFLAGS after it is set
# back to REAL_CPPFLAGS.
@@ -3364,32 +3445,34 @@ dnl Use toolkit scroll bars if configured for GTK or X toolkit and either
dnl using Motif or Xaw3d is available, and unless
dnl --with-toolkit-scroll-bars=no was specified.
-AH_TEMPLATE(USE_TOOLKIT_SCROLL_BARS,
+AH_TEMPLATE([USE_TOOLKIT_SCROLL_BARS],
[Define to 1 if we should use toolkit scroll bars.])dnl
USE_TOOLKIT_SCROLL_BARS=no
if test "${with_toolkit_scroll_bars}" != "no"; then
if test "${USE_X_TOOLKIT}" != "none"; then
if test "${USE_X_TOOLKIT}" = "MOTIF"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
HAVE_XAW3D=no
USE_TOOLKIT_SCROLL_BARS=yes
elif test "${HAVE_XAW3D}" = "yes" || test "${USE_X_TOOLKIT}" = "LUCID"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
USE_TOOLKIT_SCROLL_BARS=yes
fi
elif test "${HAVE_GTK}" = "yes"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
USE_TOOLKIT_SCROLL_BARS=yes
elif test "${HAVE_NS}" = "yes"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
USE_TOOLKIT_SCROLL_BARS=yes
elif test "${HAVE_W32}" = "yes"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
USE_TOOLKIT_SCROLL_BARS=yes
elif test "${HAVE_BE_APP}" = "yes"; then
- AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+ AC_DEFINE([USE_TOOLKIT_SCROLL_BARS])
USE_TOOLKIT_SCROLL_BARS=yes
fi
+elif test "${window_system}" != "x11" && test "${window_system}" != "none"; then
+ AC_MSG_ERROR([Non-toolkit scroll bars are not implemented for your system])
fi
dnl See if XIM is available.
@@ -3398,52 +3481,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <X11/Xresource.h>]],
[[XIMProc callback;]])],
[HAVE_XIM=yes
- AC_DEFINE(HAVE_XIM, 1, [Define to 1 if XIM is available])],
- HAVE_XIM=no)
+ AC_DEFINE([HAVE_XIM], [1], [Define to 1 if XIM is available])],
+ [HAVE_XIM=no])
dnl Note this is non-standard. --with-xim does not control whether
dnl XIM support is compiled in, it only affects the runtime default of
dnl use_xim in xterm.c.
if test "${with_xim}" != "no"; then
- AC_DEFINE(USE_XIM, 1,
+ AC_DEFINE([USE_XIM], [1],
[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 <X11/Xlib.h>
-#include <X11/Xresource.h>]],
-[[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
@@ -3456,8 +3504,8 @@ if test "${HAVE_X11}" = "yes"; then
[AC_CHECK_LIB([Xrender], [XRenderQueryExtension], [HAVE_XRENDER=yes])])
if test $HAVE_XRENDER = yes; then
XRENDER_LIBS="-lXrender"
- AC_SUBST(XRENDER_LIBS)
- AC_DEFINE([HAVE_XRENDER], 1, [Define to 1 if XRender is available.])
+ AC_SUBST([XRENDER_LIBS])
+ AC_DEFINE([HAVE_XRENDER], [1], [Define to 1 if XRender is available.])
fi
fi
@@ -3466,46 +3514,99 @@ if test "${HAVE_X11}" = "yes"; then
if test "${with_cairo}" != "no"; then
CAIRO_REQUIRED=1.8.0
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
- EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE)
+ EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE])
if test $HAVE_CAIRO = yes; then
- AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
+ CAIRO_XCB_MODULE="cairo-xcb >= $CAIRO_REQUIRED"
+ EMACS_CHECK_MODULES([CAIRO_XCB], [$CAIRO_XCB_MODULE])
+ if test $HAVE_CAIRO_XCB = yes; then
+ CAIRO_CFLAGS="$CAIRO_CFLAGS $CAIRO_XCB_CFLAGS"
+ CAIRO_LIBS="$CAIRO_LIBS $CAIRO_XCB_LIBS"
+ AC_DEFINE([USE_CAIRO_XCB], [1],
+ [Define to 1 if cairo XCB surfaces are available.])
+ fi
+ AC_DEFINE([USE_CAIRO], [1], [Define to 1 if using cairo.])
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $CAIRO_LIBS"
- AC_SUBST(CAIRO_CFLAGS)
- AC_SUBST(CAIRO_LIBS)
+ AC_SUBST([CAIRO_CFLAGS])
+ AC_SUBST([CAIRO_LIBS])
else
AC_MSG_WARN([cairo requested but not found.])
fi
fi
fi
+dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
+dnl Enable xwidgets if macOS Cocoa and WebKit framework are available.
+HAVE_XWIDGETS=no
+XWIDGETS_OBJ=
+if test "$with_xwidgets" != "no"; then
+ if test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none"; then
+ WEBKIT_REQUIRED=2.12
+ WEBKIT_MODULES="webkit2gtk-4.0 >= $WEBKIT_REQUIRED"
+ EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
+ HAVE_XWIDGETS=$HAVE_WEBKIT
+ XWIDGETS_OBJ="xwidget.o"
+ if test "$HAVE_X_WINDOWS" = "yes" && test "${with_cairo}" = "no"; then
+ CAIRO_XLIB_MODULES="cairo >= 1.8.0 cairo-xlib >= 1.8.0"
+ EMACS_CHECK_MODULES([CAIRO_XLIB], [$CAIRO_XLIB_MODULES])
+ if test $HAVE_CAIRO_XLIB = "yes"; then
+ CAIRO_CFLAGS="$CAIRO_XLIB_CFLAGS"
+ CAIRO_LIBS="$CAIRO_XLIB_LIBS"
+ AC_SUBST([CAIRO_CFLAGS])
+ AC_SUBST([CAIRO_LIBS])
+ else
+ AC_MSG_ERROR([xwidgets requested, but a suitable cairo installation wasn't found])
+ fi
+ fi
+ elif test "${NS_IMPL_COCOA}" = "yes"; then
+ dnl FIXME: Check framework WebKit2
+ dnl WEBKIT_REQUIRED=M.m.p
+ WEBKIT_LIBS="-Wl,-framework -Wl,WebKit"
+ WEBKIT_CFLAGS="-I/System/Library/Frameworks/WebKit.framework/Headers"
+ HAVE_WEBKIT="yes"
+ HAVE_XWIDGETS=$HAVE_WEBKIT
+ XWIDGETS_OBJ="xwidget.o"
+ NS_OBJC_OBJ="$NS_OBJC_OBJ nsxwidget.o"
+ dnl Update NS_OBJC_OBJ with added nsxwidget.o
+ AC_SUBST([NS_OBJC_OBJ])
+ else
+ AC_MSG_ERROR([xwidgets requested, it requires GTK3 as X window toolkit or macOS Cocoa as window system.])
+ fi
+
+ test $HAVE_XWIDGETS = yes ||
+ AC_MSG_ERROR([xwidgets requested but WebKitGTK+ or WebKit framework not found.])
+
+ AC_DEFINE([HAVE_XWIDGETS], [1], [Define to 1 if you have xwidgets support.])
+fi
+AC_SUBST([XWIDGETS_OBJ])
+
if test "$window_system" = "pgtk"; then
CAIRO_REQUIRED=1.12.0
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
- EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE)
+ EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE])
if test $HAVE_CAIRO = yes; then
- AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
+ AC_DEFINE([USE_CAIRO], [1], [Define to 1 if using cairo.])
else
AC_MSG_ERROR([cairo required but not found.])
fi
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $CAIRO_LIBS"
- AC_SUBST(CAIRO_CFLAGS)
- AC_SUBST(CAIRO_LIBS)
+ AC_SUBST([CAIRO_CFLAGS])
+ AC_SUBST([CAIRO_LIBS])
fi
if test "${HAVE_BE_APP}" = "yes"; then
if test "${with_be_cairo}" != "no"; then
CAIRO_REQUIRED=1.8.0
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
- EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE)
+ EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE])
if test $HAVE_CAIRO = yes; then
- AC_DEFINE(USE_BE_CAIRO, 1, [Define to 1 if using cairo on Haiku.])
+ AC_DEFINE([USE_BE_CAIRO], [1], [Define to 1 if using cairo on Haiku.])
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $CAIRO_LIBS"
- AC_SUBST(CAIRO_CFLAGS)
- AC_SUBST(CAIRO_LIBS)
+ AC_SUBST([CAIRO_CFLAGS])
+ AC_SUBST([CAIRO_LIBS])
else
AC_MSG_WARN([cairo requested but not found.])
fi
@@ -3525,11 +3626,12 @@ if test "${HAVE_X11}" = "yes"; then
dnl The following is needed to set FREETYPE_LIBS.
EMACS_CHECK_MODULES([FREETYPE], [freetype2])
- test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(cairo requires libfreetype)
+ test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR([cairo requires libfreetype])
EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0])
- test "$HAVE_FONTCONFIG" = "no" && AC_MSG_ERROR(cairo requires libfontconfig)
+ test "$HAVE_FONTCONFIG" = "no" &&
+ AC_MSG_ERROR([cairo requires libfontconfig])
dnl For the "Does Emacs use" message at the end.
HAVE_XFT=no
else
@@ -3556,13 +3658,15 @@ if test "${HAVE_X11}" = "yes"; then
CPPFLAGS="$CPPFLAGS $XFT_CFLAGS"
CFLAGS="$CFLAGS $XFT_CFLAGS"
LIBS="$XFT_LIBS $LIBS"
- AC_CHECK_HEADER(X11/Xft/Xft.h,
- AC_CHECK_LIB(Xft, XftFontOpen, HAVE_XFT=yes, , $XFT_LIBS) , ,
+ AC_CHECK_HEADER([X11/Xft/Xft.h],
+ [AC_CHECK_LIB([Xft], [XftFontOpen], [HAVE_XFT=yes],
+ [], [$XFT_LIBS])],
+ [],
[[#include <X11/X.h>]])
if test "${HAVE_XFT}" = "yes"; then
- AC_DEFINE(HAVE_XFT, 1, [Define to 1 if you have the Xft library.])
- AC_SUBST(XFT_LIBS)
+ AC_DEFINE([HAVE_XFT], [1], [Define to 1 if you have the Xft library.])
+ AC_SUBST([XFT_LIBS])
C_SWITCH_X_SITE="$C_SWITCH_X_SITE $XFT_CFLAGS"
fi # "${HAVE_XFT}" = "yes"
CPPFLAGS=$OLD_CPPFLAGS
@@ -3585,34 +3689,35 @@ if test "${HAVE_X11}" = "yes"; then
dnl The following is needed to set FREETYPE_LIBS.
EMACS_CHECK_MODULES([FREETYPE], [freetype2])
- test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(libxft requires libfreetype)
+ test "$HAVE_FREETYPE" = "no" &&
+ AC_MSG_ERROR([libxft requires libfreetype])
fi
fi # $HAVE_CAIRO != yes
HAVE_LIBOTF=no
if test "${HAVE_FREETYPE}" = "yes"; then
- AC_DEFINE(HAVE_FREETYPE, 1,
+ AC_DEFINE([HAVE_FREETYPE], [1],
[Define to 1 if using the freetype and fontconfig libraries.])
OLD_CFLAGS=$CFLAGS
OLD_LIBS=$LIBS
CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
LIBS="$FREETYPE_LIBS $LIBS"
- AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex)
+ AC_CHECK_FUNCS([FT_Face_GetCharVariantIndex])
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
if test "${with_libotf}" != "no"; then
EMACS_CHECK_MODULES([LIBOTF], [libotf])
if test "$HAVE_LIBOTF" = "yes"; then
- AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.])
- AC_CHECK_LIB(otf, OTF_get_variation_glyphs,
- HAVE_OTF_GET_VARIATION_GLYPHS=yes,
- HAVE_OTF_GET_VARIATION_GLYPHS=no)
+ AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.])
+ AC_CHECK_LIB([otf], [OTF_get_variation_glyphs],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=yes],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=no])
if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then
- AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1,
+ AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1],
[Define to 1 if libotf has OTF_get_variation_glyphs.])
fi
if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then
- AC_DEFINE(HAVE_OTF_KANNADA_BUG, 1,
+ AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1],
[Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.])
fi
fi
@@ -3626,7 +3731,7 @@ if test "${HAVE_X11}" = "yes"; then
if test "${with_m17n_flt}" != "no"; then
EMACS_CHECK_MODULES([M17N_FLT], [m17n-flt])
if test "$HAVE_M17N_FLT" = "yes"; then
- AC_DEFINE(HAVE_M17N_FLT, 1, [Define to 1 if using libm17n-flt.])
+ AC_DEFINE([HAVE_M17N_FLT], [1], [Define to 1 if using libm17n-flt.])
fi
fi
fi
@@ -3635,20 +3740,20 @@ else # "${HAVE_X11}" != "yes"
EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0])
EMACS_CHECK_MODULES([FREETYPE], [freetype2])
if test "$HAVE_FONTCONFIG" != yes -o "$HAVE_FREETYPE" != yes; then
- AC_MSG_ERROR(fontconfig and freetype is required.)
+ AC_MSG_ERROR([fontconfig and freetype is required.])
fi
HAVE_LIBOTF=no
- AC_DEFINE(HAVE_FREETYPE, 1,
+ AC_DEFINE([HAVE_FREETYPE], [1],
[Define to 1 if using the freetype and fontconfig libraries.])
if test "${with_libotf}" != "no"; then
EMACS_CHECK_MODULES([LIBOTF], [libotf])
if test "$HAVE_LIBOTF" = "yes"; then
- AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.])
- AC_CHECK_LIB(otf, OTF_get_variation_glyphs,
- HAVE_OTF_GET_VARIATION_GLYPHS=yes,
- HAVE_OTF_GET_VARIATION_GLYPHS=no)
+ AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.])
+ AC_CHECK_LIB([otf], [OTF_get_variation_glyphs],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=yes],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=no])
if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then
- AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1,
+ AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1],
[Define to 1 if libotf has OTF_get_variation_glyphs.])
fi
fi
@@ -3675,7 +3780,7 @@ if test "${HAVE_X11}" = "yes" && test "${HAVE_FREETYPE}" = "yes" \
if test "${with_harfbuzz}" != "no"; then
EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver])
if test "$HAVE_HARFBUZZ" = "yes"; then
- AC_DEFINE(HAVE_HARFBUZZ, 1, [Define to 1 if using HarfBuzz.])
+ AC_DEFINE([HAVE_HARFBUZZ], [1], [Define to 1 if using HarfBuzz.])
### mingw32 and Cygwin-w32 don't use -lharfbuzz, since they load
### the library dynamically.
if test "${HAVE_W32}" = "yes"; then
@@ -3689,36 +3794,38 @@ fi
if test "${HAVE_BE_APP}" = "yes"; then
if test $HAVE_CAIRO = "yes"; then
EMACS_CHECK_MODULES([FREETYPE], [freetype2 >= 2.5.0])
- test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfreetype)
+ test "$HAVE_FREETYPE" = "no" &&
+ AC_MSG_ERROR([cairo on Haiku requires libfreetype])
EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0])
- test "$HAVE_FONTCONFIG" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfontconfig)
+ test "$HAVE_FONTCONFIG" = "no" &&
+ AC_MSG_ERROR([cairo on Haiku requires libfontconfig])
fi
HAVE_LIBOTF=no
if test "${HAVE_FREETYPE}" = "yes"; then
- AC_DEFINE(HAVE_FREETYPE, 1,
+ AC_DEFINE([HAVE_FREETYPE], [1],
[Define to 1 if using the freetype and fontconfig libraries.])
OLD_CFLAGS=$CFLAGS
OLD_LIBS=$LIBS
CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
LIBS="$FREETYPE_LIBS $LIBS"
- AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex)
+ AC_CHECK_FUNCS([FT_Face_GetCharVariantIndex])
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
if test "${with_libotf}" != "no"; then
EMACS_CHECK_MODULES([LIBOTF], [libotf])
if test "$HAVE_LIBOTF" = "yes"; then
- AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.])
- AC_CHECK_LIB(otf, OTF_get_variation_glyphs,
- HAVE_OTF_GET_VARIATION_GLYPHS=yes,
- HAVE_OTF_GET_VARIATION_GLYPHS=no)
+ AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.])
+ AC_CHECK_LIB([otf], [OTF_get_variation_glyphs],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=yes],
+ [HAVE_OTF_GET_VARIATION_GLYPHS=no])
if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then
- AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1,
+ AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1],
[Define to 1 if libotf has OTF_get_variation_glyphs.])
fi
if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then
- AC_DEFINE(HAVE_OTF_KANNADA_BUG, 1,
+ AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1],
[Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.])
fi
fi
@@ -3732,38 +3839,50 @@ if test "${HAVE_BE_APP}" = "yes" && test "${HAVE_FREETYPE}" = "yes"; then
if test "${with_harfbuzz}" != "no"; then
EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver])
if test "$HAVE_HARFBUZZ" = "yes"; then
- AC_DEFINE(HAVE_HARFBUZZ, 1, [Define to 1 if using HarfBuzz.])
+ AC_DEFINE([HAVE_HARFBUZZ], [1], [Define to 1 if using HarfBuzz.])
fi
fi
fi
### End of font-backend section.
-AC_SUBST(FREETYPE_CFLAGS)
-AC_SUBST(FREETYPE_LIBS)
-AC_SUBST(FONTCONFIG_CFLAGS)
-AC_SUBST(FONTCONFIG_LIBS)
-AC_SUBST(HARFBUZZ_CFLAGS)
-AC_SUBST(HARFBUZZ_LIBS)
-AC_SUBST(LIBOTF_CFLAGS)
-AC_SUBST(LIBOTF_LIBS)
-AC_SUBST(M17N_FLT_CFLAGS)
-AC_SUBST(M17N_FLT_LIBS)
-
+AC_SUBST([FREETYPE_CFLAGS])
+AC_SUBST([FREETYPE_LIBS])
+AC_SUBST([FONTCONFIG_CFLAGS])
+AC_SUBST([FONTCONFIG_LIBS])
+AC_SUBST([HARFBUZZ_CFLAGS])
+AC_SUBST([HARFBUZZ_LIBS])
+AC_SUBST([LIBOTF_CFLAGS])
+AC_SUBST([LIBOTF_LIBS])
+AC_SUBST([M17N_FLT_CFLAGS])
+AC_SUBST([M17N_FLT_LIBS])
+
+XCB_LIBS=
if test "${HAVE_X11}" = "yes"; then
- AC_CHECK_HEADER(X11/Xlib-xcb.h,
- AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes))
+ AC_CHECK_HEADER([X11/Xlib-xcb.h],
+ [AC_CHECK_LIB([xcb], [xcb_translate_coordinates], [HAVE_XCB=yes])])
if test "${HAVE_XCB}" = "yes"; then
- AC_CHECK_LIB(X11-xcb, XGetXCBConnection, HAVE_X11_XCB=yes)
+ AC_CHECK_LIB([X11-xcb], [XGetXCBConnection], [HAVE_X11_XCB=yes])
if test "${HAVE_X11_XCB}" = "yes"; then
- AC_DEFINE(USE_XCB, 1,
+ AC_CHECK_LIB([xcb-util], [xcb_aux_sync], [HAVE_XCB_UTIL=yes])
+ if test "${HAVE_XCB_UTIL}" = "yes"; then
+ AC_DEFINE([USE_XCB], [1],
[Define to 1 if you have the XCB library and X11-XCB library for mixed
- X11/XCB programming.])
- XCB_LIBS="-lX11-xcb -lxcb"
- AC_SUBST(XCB_LIBS)
+ X11/XCB programming.])
+ XCB_LIBS="-lX11-xcb -lxcb -lxcb-util"
+ else
+ AC_CHECK_LIB([xcb-aux], [xcb_aux_sync], [HAVE_XCB_AUX=yes])
+ if test "${HAVE_XCB_AUX}" = "yes"; then
+ AC_DEFINE([USE_XCB], [1],
+[Define to 1 if you have the XCB library and X11-XCB library for mixed
+ X11/XCB programming.])
+ XCB_LIBS="-lX11-xcb -lxcb -lxcb-aux"
+ fi
+ fi
fi
fi
fi
+AC_SUBST([XCB_LIBS])
### Use -lXpm if available, unless '--with-xpm=no'.
### mingw32 doesn't use -lXpm, since it loads the library dynamically.
@@ -3775,18 +3894,18 @@ if test "${HAVE_W32}" = "yes" && test "${opsys}" = "cygwin"; then
if test "${with_xpm}" != "no"; then
SAVE_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -L/usr/lib/noX"
- AC_CHECK_HEADER(noX/xpm.h,
- [AC_CHECK_LIB(Xpm, XpmReadFileToImage, HAVE_XPM=yes)])
+ AC_CHECK_HEADER([noX/xpm.h],
+ [AC_CHECK_LIB([Xpm], [XpmReadFileToImage], [HAVE_XPM=yes])])
if test "${HAVE_XPM}" = "yes"; then
AC_CACHE_CHECK([for XpmReturnAllocPixels preprocessor define],
[emacs_cv_cpp_xpm_return_alloc_pixels],
- [AC_EGREP_CPP(no_return_alloc_pixels,
+ [AC_EGREP_CPP([no_return_alloc_pixels],
[#include "noX/xpm.h"
#ifndef XpmReturnAllocPixels
no_return_alloc_pixels
#endif
- ], emacs_cv_cpp_xpm_return_alloc_pixels=no,
- emacs_cv_cpp_xpm_return_alloc_pixels=yes)])
+ ], [emacs_cv_cpp_xpm_return_alloc_pixels=no],
+ [emacs_cv_cpp_xpm_return_alloc_pixels=yes])])
if test "$emacs_cv_cpp_xpm_return_alloc_pixels" = "no"; then
HAVE_XPM=no
@@ -3796,7 +3915,8 @@ no_return_alloc_pixels
fi
if test "${HAVE_XPM}" = "yes"; then
- AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).])
+ AC_DEFINE([HAVE_XPM], [1],
+ [Define to 1 if you have the Xpm library (-lXpm).])
LIBXPM=-lXpm
fi
fi
@@ -3809,18 +3929,19 @@ if test "${HAVE_X11}" = "yes"; then
esac
if test "${with_xpm}" != "no"; then
- AC_CHECK_HEADER(X11/xpm.h,
- [AC_CHECK_LIB(Xpm, XpmReadFileToPixmap, HAVE_XPM=yes, , -lX11)])
+ AC_CHECK_HEADER([X11/xpm.h],
+ [AC_CHECK_LIB([Xpm], [XpmReadFileToPixmap],
+ [HAVE_XPM=yes], [], [-lX11])])
if test "${HAVE_XPM}" = "yes"; then
AC_CACHE_CHECK([for XpmReturnAllocPixels preprocessor define],
[emacs_cv_cpp_xpm_return_alloc_pixels],
- [AC_EGREP_CPP(no_return_alloc_pixels,
+ [AC_EGREP_CPP([no_return_alloc_pixels],
[#include "X11/xpm.h"
#ifndef XpmReturnAllocPixels
no_return_alloc_pixels
#endif
- ], emacs_cv_cpp_xpm_return_alloc_pixels=no,
- emacs_cv_cpp_xpm_return_alloc_pixels=yes)])
+ ], [emacs_cv_cpp_xpm_return_alloc_pixels=no],
+ [emacs_cv_cpp_xpm_return_alloc_pixels=yes])])
if test "$emacs_cv_cpp_xpm_return_alloc_pixels" = "no"; then
HAVE_XPM=no
@@ -3829,7 +3950,8 @@ no_return_alloc_pixels
fi
if test "${HAVE_XPM}" = "yes"; then
- AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).])
+ AC_DEFINE([HAVE_XPM], [1],
+ [Define to 1 if you have the Xpm library (-lXpm).])
LIBXPM=-lXpm
elif test "$opsys,$LUCID_LIBW" = aix4-2,-lXaw; then
dnl AIX -lXaw needs -lXpm linked too; see Bug#17598 Message#152.
@@ -3843,16 +3965,17 @@ fi
### run time).
if test "${opsys}" = "mingw32"; then
if test "${with_xpm}" != "no"; then
- AC_CHECK_HEADER(X11/xpm.h, HAVE_XPM=yes, HAVE_XPM=no, [
+ AC_CHECK_HEADER([X11/xpm.h], [HAVE_XPM=yes], [HAVE_XPM=no], [
#define FOR_MSW 1])
fi
if test "${HAVE_XPM}" = "yes"; then
- AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).])
+ AC_DEFINE([HAVE_XPM], [1],
+ [Define to 1 if you have the Xpm library (-lXpm).])
fi
fi
-AC_SUBST(LIBXPM)
+AC_SUBST([LIBXPM])
### Use -ljpeg if available, unless '--with-jpeg=no'.
HAVE_JPEG=no
@@ -3891,7 +4014,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
done])
if test "$emacs_cv_jpeglib" != no; then
HAVE_JPEG=yes
- AC_DEFINE([HAVE_JPEG], 1,
+ AC_DEFINE([HAVE_JPEG], [1],
[Define to 1 if you have the jpeg library (typically -ljpeg).])
### mingw32 doesn't use -ljpeg, since it loads the library
### dynamically when needed, and doesn't want a run-time
@@ -3901,7 +4024,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
fi
fi
fi
-AC_SUBST(LIBJPEG)
+AC_SUBST([LIBJPEG])
HAVE_LCMS2=no
LCMS2_CFLAGS=
@@ -3910,14 +4033,15 @@ if test "${with_lcms2}" != "no"; then
EMACS_CHECK_MODULES([LCMS2], [lcms2])
fi
if test "${HAVE_LCMS2}" = "yes"; then
- AC_DEFINE([HAVE_LCMS2], 1, [Define to 1 if you have the lcms2 library (-llcms2).])
+ AC_DEFINE([HAVE_LCMS2], [1],
+ [Define to 1 if you have the lcms2 library (-llcms2).])
### mingw32 doesn't use -llcms2, since it loads the library dynamically.
if test "${opsys}" = "mingw32"; then
LCMS2_LIBS=
fi
fi
-AC_SUBST(LCMS2_CFLAGS)
-AC_SUBST(LCMS2_LIBS)
+AC_SUBST([LCMS2_CFLAGS])
+AC_SUBST([LCMS2_LIBS])
HAVE_ZLIB=no
LIBZ=
@@ -3930,13 +4054,14 @@ if test "${with_zlib}" != "no"; then
esac
fi
if test "${HAVE_ZLIB}" = "yes"; then
- AC_DEFINE([HAVE_ZLIB], 1, [Define to 1 if you have the zlib library (-lz).])
+ AC_DEFINE([HAVE_ZLIB], [1],
+ [Define to 1 if you have the zlib library (-lz).])
### mingw32 doesn't use -lz, since it loads the library dynamically.
if test "${opsys}" = "mingw32"; then
LIBZ=
fi
fi
-AC_SUBST(LIBZ)
+AC_SUBST([LIBZ])
### Dynamic modules support
LIBMODULES=
@@ -3952,6 +4077,16 @@ case "${opsys}" in
darwin) MODULES_SECONDARY_SUFFIX='.so' ;;
*) MODULES_SECONDARY_SUFFIX='' ;;
esac
+
+# pgtkterm.c uses dlsym
+if test $window_system = pgtk; then
+ case $opsys in
+ gnu|gnu-linux)
+ LIBMODULES="-ldl"
+ ;;
+ esac
+fi
+
if test "${with_modules}" != "no"; then
case $opsys in
gnu|gnu-linux)
@@ -3980,19 +4115,20 @@ fi
if test "${HAVE_MODULES}" = yes; then
MODULES_OBJ="emacs-module.o"
NEED_DYNLIB=yes
- AC_DEFINE(HAVE_MODULES, 1, [Define to 1 if dynamic modules are enabled])
- AC_DEFINE_UNQUOTED(MODULES_SUFFIX, "$MODULES_SUFFIX",
+ AC_DEFINE([HAVE_MODULES], [1], [Define to 1 if dynamic modules are enabled])
+ AC_DEFINE_UNQUOTED([MODULES_SUFFIX], ["$MODULES_SUFFIX"],
[System extension for dynamic libraries])
if test -n "${MODULES_SECONDARY_SUFFIX}"; then
- AC_DEFINE_UNQUOTED(MODULES_SECONDARY_SUFFIX, "$MODULES_SECONDARY_SUFFIX",
+ AC_DEFINE_UNQUOTED([MODULES_SECONDARY_SUFFIX],
+ ["$MODULES_SECONDARY_SUFFIX"],
[Alternative system extension for dynamic libraries.])
fi
fi
-AC_SUBST(MODULES_OBJ)
-AC_SUBST(LIBMODULES)
-AC_SUBST(HAVE_MODULES)
-AC_SUBST(MODULES_SUFFIX)
-AC_SUBST(MODULES_SECONDARY_SUFFIX)
+AC_SUBST([MODULES_OBJ])
+AC_SUBST([LIBMODULES])
+AC_SUBST([HAVE_MODULES])
+AC_SUBST([MODULES_SUFFIX])
+AC_SUBST([MODULES_SECONDARY_SUFFIX])
AC_CONFIG_FILES([src/emacs-module.h])
AC_SUBST_FILE([module_env_snippet_25])
@@ -4006,7 +4142,7 @@ module_env_snippet_27="$srcdir/src/module-env-27.h"
module_env_snippet_28="$srcdir/src/module-env-28.h"
module_env_snippet_29="$srcdir/src/module-env-29.h"
emacs_major_version="${PACKAGE_VERSION%%.*}"
-AC_SUBST(emacs_major_version)
+AC_SUBST([emacs_major_version])
### Emacs Lisp native compiler support
@@ -4105,7 +4241,7 @@ if test "${with_native_compilation}" != "no"; then
MAC_CFLAGS="-I$(dirname $($BREW ls -v libgccjit | \
grep libgccjit.h))"
MAC_LIBS="-L$(dirname $($BREW ls -v libgccjit| \
- grep libgccjit.so\$))"
+ grep -E 'libgccjit\.(so|dylib)$'))"
fi
fi
@@ -4133,8 +4269,9 @@ if test "${with_native_compilation}" != "no"; then
fi
# Check if libgccjit is available.
- AC_CHECK_LIB(gccjit, gcc_jit_context_acquire, [], [libgccjit_not_found])
- AC_CHECK_HEADERS(libgccjit.h, [], [libgccjit_dev_not_found])
+ AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire],
+ [], [libgccjit_not_found])
+ AC_CHECK_HEADERS([libgccjit.h], [], [libgccjit_dev_not_found])
# Check if libgccjit really works.
AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken])
HAVE_NATIVE_COMP=yes
@@ -4151,22 +4288,23 @@ if test "${with_native_compilation}" != "no"; then
LIBGCCJIT_LIBS="-lgccjit -ldl" ;;
esac
NEED_DYNLIB=yes
- AC_DEFINE(HAVE_NATIVE_COMP, 1, [Define to 1 if native compiler is available.])
+ AC_DEFINE([HAVE_NATIVE_COMP], [1],
+ [Define to 1 if native compiler is available.])
CFLAGS=$SAVE_CFLAGS
LIBS=$SAVE_LIBS
fi
-AC_DEFINE_UNQUOTED(NATIVE_ELISP_SUFFIX, ".eln",
+AC_DEFINE_UNQUOTED([NATIVE_ELISP_SUFFIX], [".eln"],
[System extension for native compiled elisp])
-AC_SUBST(HAVE_NATIVE_COMP)
-AC_SUBST(LIBGCCJIT_CFLAGS)
-AC_SUBST(LIBGCCJIT_LIBS)
+AC_SUBST([HAVE_NATIVE_COMP])
+AC_SUBST([LIBGCCJIT_CFLAGS])
+AC_SUBST([LIBGCCJIT_LIBS])
DYNLIB_OBJ=
if test "${NEED_DYNLIB}" = yes; then
DYNLIB_OBJ="dynlib.o"
fi
-AC_SUBST(DYNLIB_OBJ)
+AC_SUBST([DYNLIB_OBJ])
### Use -lpng if available, unless '--with-png=no'.
HAVE_PNG=no
@@ -4238,8 +4376,8 @@ if test $HAVE_PNG = yes; then
]])
CFLAGS=$SAVE_CFLAGS
fi
-AC_SUBST(LIBPNG)
-AC_SUBST(PNG_CFLAGS)
+AC_SUBST([LIBPNG])
+AC_SUBST([PNG_CFLAGS])
### Use -ltiff if available, unless '--with-tiff=no'.
### mingw32 doesn't use -ltiff, since it loads the library dynamically.
@@ -4247,29 +4385,32 @@ HAVE_TIFF=no
LIBTIFF=
if test "${opsys}" = "mingw32"; then
if test "${with_tiff}" != "no"; then
- AC_CHECK_HEADER(tiffio.h, HAVE_TIFF=yes, HAVE_TIFF=no)
+ AC_CHECK_HEADER([tiffio.h], [HAVE_TIFF=yes], [HAVE_TIFF=no])
fi
if test "${HAVE_TIFF}" = "yes"; then
- AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).])
+ AC_DEFINE([HAVE_TIFF], [1],
+ [Define to 1 if you have the tiff library (-ltiff).])
fi
elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes" \
|| test "$window_system" = "pgtk"; then
if test "${with_tiff}" != "no"; then
- AC_CHECK_HEADER(tiffio.h,
+ AC_CHECK_HEADER([tiffio.h],
[tifflibs="-lz -lm"
# At least one tiff package requires the jpeg library.
if test "${HAVE_JPEG}" = yes; then tifflibs="-ljpeg $tifflibs"; fi
- AC_CHECK_LIB(tiff, TIFFGetVersion, HAVE_TIFF=yes, , $tifflibs)])
+ AC_CHECK_LIB([tiff], [TIFFGetVersion], [HAVE_TIFF=yes], [],
+ [$tifflibs])])
fi
if test "${HAVE_TIFF}" = "yes"; then
- AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).])
+ AC_DEFINE([HAVE_TIFF], [1],
+ [Define to 1 if you have the tiff library (-ltiff).])
dnl FIXME -lz -lm, as per libpng?
LIBTIFF=-ltiff
fi
fi
-AC_SUBST(LIBTIFF)
+AC_SUBST([LIBTIFF])
### Use -lgif or -lungif if available, unless '--with-gif=no'.
### mingw32 doesn't use -lgif/-lungif, since it loads the library dynamically.
@@ -4277,33 +4418,40 @@ HAVE_GIF=no
LIBGIF=
if test "${opsys}" = "mingw32"; then
if test "${with_gif}" != "no"; then
- AC_CHECK_HEADER(gif_lib.h, HAVE_GIF=yes, HAVE_GIF=no)
+ AC_CHECK_HEADER([gif_lib.h], [HAVE_GIF=yes], [HAVE_GIF=no])
fi
if test "${HAVE_GIF}" = "yes"; then
- AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.])
+ AC_DEFINE([HAVE_GIF], [1],
+ [Define to 1 if you have a gif (or ungif) library.])
fi
elif test "${HAVE_X11}" = "yes" && test "${with_gif}" != "no" \
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \
- || test "${HAVE_BE_APP}" = "yes" || test "$window_system" = "pgtk"; then
- AC_CHECK_HEADER(gif_lib.h,
+ || test "${HAVE_BE_APP}" = "yes" || test "$window_system" = "pgtk" \
+ && test "${with_gif}" != "no"; then
+ AC_CHECK_HEADER([gif_lib.h],
# EGifPutExtensionLast only exists from version libungif-4.1.0b1.
# Earlier versions can crash Emacs, but version 5.0 removes EGifPutExtensionLast.
- [AC_CHECK_LIB(gif, GifMakeMapObject, HAVE_GIF=yes,
- [AC_CHECK_LIB(gif, EGifPutExtensionLast, HAVE_GIF=yes, HAVE_GIF=maybe)])])
+ [AC_CHECK_LIB([gif], [GifMakeMapObject], [HAVE_GIF=yes],
+ [AC_CHECK_LIB([gif], [EGifPutExtensionLast],
+ [HAVE_GIF=yes],
+ [HAVE_GIF=maybe])])])
if test "$HAVE_GIF" = yes; then
LIBGIF=-lgif
elif test "$HAVE_GIF" = maybe; then
# If gif_lib.h but no libgif, try libungif.
- AC_CHECK_LIB(ungif, EGifPutExtensionLast, HAVE_GIF=yes, HAVE_GIF=no)
+ AC_CHECK_LIB([ungif], [EGifPutExtensionLast],
+ [HAVE_GIF=yes],
+ [HAVE_GIF=no])
test "$HAVE_GIF" = yes && LIBGIF=-lungif
fi
if test "${HAVE_GIF}" = "yes"; then
- AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.])
+ AC_DEFINE([HAVE_GIF], [1],
+ [Define to 1 if you have a gif (or ungif) library.])
fi
fi
-AC_SUBST(LIBGIF)
+AC_SUBST([LIBGIF])
dnl Check for required libraries.
MISSING=
@@ -4363,28 +4511,33 @@ fi
HAVE_GPM=no
LIBGPM=
if test "${with_gpm}" != "no"; then
- AC_CHECK_HEADER(gpm.h,
- [AC_CHECK_LIB(gpm, Gpm_Open, HAVE_GPM=yes)])
+ AC_CHECK_HEADER([gpm.h],
+ [AC_CHECK_LIB([gpm], [Gpm_Open], [HAVE_GPM=yes])])
if test "${HAVE_GPM}" = "yes"; then
- AC_DEFINE(HAVE_GPM, 1, [Define to 1 if you have the gpm library (-lgpm).])
+ AC_DEFINE([HAVE_GPM], [1],
+ [Define to 1 if you have the gpm library (-lgpm).])
LIBGPM=-lgpm
fi
fi
-AC_SUBST(LIBGPM)
+AC_SUBST([LIBGPM])
dnl Check for malloc/malloc.h on darwin
-AC_CHECK_HEADERS_ONCE(malloc/malloc.h)
+AC_CHECK_HEADERS_ONCE([malloc/malloc.h])
GNUSTEP_CFLAGS=
### Use NeXTstep API to implement GUI.
if test "${HAVE_NS}" = "yes"; then
- AC_DEFINE(HAVE_NS, 1, [Define to 1 if you are using the NeXTstep API, either GNUstep or Cocoa on macOS.])
+ AC_DEFINE([HAVE_NS], [1],
+ [Define to 1 if you are using the NeXTstep API,
+ either GNUstep or Cocoa on macOS.])
if test "${NS_IMPL_COCOA}" = "yes"; then
- AC_DEFINE(NS_IMPL_COCOA, 1, [Define to 1 if you are using NS windowing under macOS.])
+ AC_DEFINE([NS_IMPL_COCOA], [1],
+ [Define to 1 if you are using NS windowing under macOS.])
fi
if test "${NS_IMPL_GNUSTEP}" = "yes"; then
- AC_DEFINE(NS_IMPL_GNUSTEP, 1, [Define to 1 if you are using NS windowing under GNUstep.])
+ AC_DEFINE([NS_IMPL_GNUSTEP], [1],
+ [Define to 1 if you are using NS windowing under GNUstep.])
if test $NS_GNUSTEP_CONFIG != yes; then
# See also .m.o rule in src/Makefile.in. */
# FIXME: are all these flags really needed? Document here why. */
@@ -4400,15 +4553,16 @@ fi
HAVE_X_SM=no
LIBXSM=
if test "${HAVE_X11}" = "yes"; then
- AC_CHECK_HEADER(X11/SM/SMlib.h,
- [AC_CHECK_LIB(SM, SmcOpenConnection, HAVE_X_SM=yes, , -lICE)])
+ AC_CHECK_HEADER([X11/SM/SMlib.h],
+ [AC_CHECK_LIB([SM], [SmcOpenConnection], [HAVE_X_SM=yes], [], [-lICE])])
if test "${HAVE_X_SM}" = "yes"; then
- AC_DEFINE(HAVE_X_SM, 1, [Define to 1 if you have the SM library (-lSM).])
+ AC_DEFINE([HAVE_X_SM], [1],
+ [Define to 1 if you have the SM library (-lSM).])
LIBXSM="-lSM -lICE"
fi
fi
-AC_SUBST(LIBXSM)
+AC_SUBST([LIBXSM])
### Use XRandr (-lXrandr) if available
HAVE_XRANDR=no
@@ -4420,8 +4574,8 @@ if test "${HAVE_X11}" = "yes"; then
# Test old way in case pkg-config doesn't have it (older machines).
# Include Xrender.h by hand to work around bug in older Xrandr.h
# (e.g. RHEL5) and silence (harmless) configure warning (bug#18465).
- AC_CHECK_HEADER(X11/extensions/Xrandr.h,
- [AC_CHECK_LIB(Xrandr, XRRGetScreenResources, HAVE_XRANDR=yes)],
+ AC_CHECK_HEADER([X11/extensions/Xrandr.h],
+ [AC_CHECK_LIB([Xrandr], [XRRGetScreenResources], [HAVE_XRANDR=yes])],
[], [AC_INCLUDES_DEFAULT
#include <X11/extensions/Xrender.h>])
if test $HAVE_XRANDR = yes; then
@@ -4429,11 +4583,12 @@ if test "${HAVE_X11}" = "yes"; then
fi
fi
if test $HAVE_XRANDR = yes; then
- AC_DEFINE(HAVE_XRANDR, 1, [Define to 1 if you have the XRandr extension.])
+ AC_DEFINE([HAVE_XRANDR], [1],
+ [Define to 1 if you have the XRandr extension.])
fi
fi
-AC_SUBST(XRANDR_CFLAGS)
-AC_SUBST(XRANDR_LIBS)
+AC_SUBST([XRANDR_CFLAGS])
+AC_SUBST([XRANDR_LIBS])
### Use Xinerama (-lXinerama) if available
HAVE_XINERAMA=no
@@ -4443,18 +4598,20 @@ if test "${HAVE_X11}" = "yes"; then
EMACS_CHECK_MODULES([XINERAMA], [$XINERAMA_MODULES])
if test $HAVE_XINERAMA = no; then
# Test old way in case pkg-config doesn't have it (older machines).
- AC_CHECK_HEADER(X11/extensions/Xinerama.h,
- [AC_CHECK_LIB(Xinerama, XineramaQueryExtension, HAVE_XINERAMA=yes)])
+ AC_CHECK_HEADER([X11/extensions/Xinerama.h],
+ [AC_CHECK_LIB([Xinerama], [XineramaQueryExtension],
+ [HAVE_XINERAMA=yes])])
if test $HAVE_XINERAMA = yes; then
XINERAMA_LIBS=-lXinerama
fi
fi
if test $HAVE_XINERAMA = yes; then
- AC_DEFINE(HAVE_XINERAMA, 1, [Define to 1 if you have the Xinerama extension.])
+ AC_DEFINE([HAVE_XINERAMA], [1],
+ [Define to 1 if you have the Xinerama extension.])
fi
fi
-AC_SUBST(XINERAMA_CFLAGS)
-AC_SUBST(XINERAMA_LIBS)
+AC_SUBST([XINERAMA_CFLAGS])
+AC_SUBST([XINERAMA_LIBS])
### Use Xfixes (-lXfixes) if available
HAVE_XFIXES=no
@@ -4464,18 +4621,19 @@ if test "${HAVE_X11}" = "yes"; then
EMACS_CHECK_MODULES([XFIXES], [$XFIXES_MODULES])
if test $HAVE_XFIXES = no; then
# Test old way in case pkg-config doesn't have it (older machines).
- AC_CHECK_HEADER(X11/extensions/Xfixes.h,
- [AC_CHECK_LIB(Xfixes, XFixesHideCursor, HAVE_XFIXES=yes)])
+ AC_CHECK_HEADER([X11/extensions/Xfixes.h],
+ [AC_CHECK_LIB([Xfixes], [XFixesHideCursor], [HAVE_XFIXES=yes])])
if test $HAVE_XFIXES = yes; then
XFIXES_LIBS=-lXfixes
fi
fi
if test $HAVE_XFIXES = yes; then
- AC_DEFINE(HAVE_XFIXES, 1, [Define to 1 if you have the Xfixes extension.])
+ AC_DEFINE([HAVE_XFIXES], [1],
+ [Define to 1 if you have the Xfixes extension.])
fi
fi
-AC_SUBST(XFIXES_CFLAGS)
-AC_SUBST(XFIXES_LIBS)
+AC_SUBST([XFIXES_CFLAGS])
+AC_SUBST([XFIXES_LIBS])
## Use XInput 2.0 if available
HAVE_XINPUT2=no
@@ -4483,33 +4641,51 @@ if test "${HAVE_X11}" = "yes" && test "${with_xinput2}" != "no"; then
EMACS_CHECK_MODULES([XINPUT], [xi])
if test $HAVE_XINPUT = yes; then
# Now check for XInput2.h
- AC_CHECK_HEADER(X11/extensions/XInput2.h,
- [AC_CHECK_LIB(Xi, XIGrabButton, HAVE_XINPUT2=yes)])
+ AC_CHECK_HEADER([X11/extensions/XInput2.h],
+ [AC_CHECK_LIB([Xi], [XIGrabButton], [HAVE_XINPUT2=yes])])
fi
if test $HAVE_XINPUT2 = yes; then
- AC_DEFINE(HAVE_XINPUT2, 1, [Define to 1 if the X Input Extension version 2.0 or later is present.])
+ AC_DEFINE([HAVE_XINPUT2], [1],
+ [Define to 1 if the X Input Extension version 2.0 or later is present.])
if test "$USE_GTK_TOOLKIT" = "GTK2"; then
AC_MSG_WARN([You are building Emacs with GTK+ 2 and the X Input Extension version 2.
This might lead to problems if your version of GTK+ is not built with support for XInput 2.])
fi
- # Detect both faulty installations of libXi where gesture event
- # types are defined but gesture event structures are not, and
- # also where gesture event structures are empty.
- AC_CHECK_MEMBERS([XIGesturePinchEvent.delta_unaccel_y],
- [AC_DEFINE(HAVE_USABLE_XI_GESTURE_PINCH_EVENT, 1,
- [Define to 1 if XInput headers define gesture structures correctly.])],
- [], [[#include <X11/extensions/XInput2.h>]])
+
+ # Now check for some members (which used in conjunction with
+ # protocol definitions) can be used to determine the version of
+ # XInput supported.
+ AC_CHECK_MEMBERS([XIScrollClassInfo.type, XITouchClassInfo.type,
+ XIBarrierReleasePointerInfo.deviceid, XIGestureClassInfo.type],
+ [], [], [#include <X11/extensions/XInput2.h>])
fi
fi
-AC_SUBST(XINPUT_CFLAGS)
-AC_SUBST(XINPUT_LIBS)
+AC_SUBST([XINPUT_CFLAGS])
+AC_SUBST([XINPUT_LIBS])
+
+XSYNC_LIBS=
+XSYNC_CFLAGS=
+HAVE_XSYNC=no
+if test "${HAVE_X11}" = "yes"; then
+ AC_CHECK_HEADER([X11/extensions/sync.h],
+ [AC_CHECK_LIB([Xext], [XSyncQueryExtension], [HAVE_XSYNC=yes])],
+ [], [#include <X11/Xlib.h>])
+
+ if test "${HAVE_XSYNC}" = "yes"; then
+ AC_DEFINE([HAVE_XSYNC], [1],
+ [Define to 1 if the X Synchronization Extension is available.])
+ XSYNC_LIBS="-lXext"
+ fi
+fi
+AC_SUBST([XSYNC_LIBS])
+AC_SUBST([XSYNC_CFLAGS])
### Use Xdbe (-lXdbe) if available
HAVE_XDBE=no
if test "${HAVE_X11}" = "yes"; then
if test "${with_xdbe}" != "no"; then
- AC_CHECK_HEADER(X11/extensions/Xdbe.h,
- [AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=yes)],
+ AC_CHECK_HEADER([X11/extensions/Xdbe.h],
+ [AC_CHECK_LIB([Xext], [XdbeAllocateBackBufferName], [HAVE_XDBE=yes])],
[],
[#include <X11/Xlib.h>
])
@@ -4518,11 +4694,62 @@ if test "${HAVE_X11}" = "yes"; then
XDBE_LIBS=-lXext
fi
if test $HAVE_XDBE = yes; then
- AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extension.])
+ AC_DEFINE([HAVE_XDBE], [1], [Define to 1 if you have the Xdbe extension.])
fi
fi
-AC_SUBST(XDBE_CFLAGS)
-AC_SUBST(XDBE_LIBS)
+AC_SUBST([XDBE_CFLAGS])
+AC_SUBST([XDBE_LIBS])
+
+### Use the Nonrectangular Window Shape extension if available.
+HAVE_XSHAPE=no
+HAVE_XCB_SHAPE=no
+if test "${HAVE_X11}" = "yes"; then
+ AC_CHECK_HEADER([X11/extensions/shape.h],
+ [AC_CHECK_LIB([Xext], [XShapeQueryVersion], [HAVE_XSHAPE=yes])],
+ [],
+ [#include <X11/extensions/shape.h>
+ ])
+ if test $HAVE_XSHAPE = yes; then
+ XSHAPE_LIBS=-lXext
+ AC_CHECK_HEADER([xcb/shape.h],
+ [AC_CHECK_LIB([xcb-shape], [xcb_shape_combine], [HAVE_XCB_SHAPE=yes])],
+ [],
+ [#include <xcb/shape.h>])
+
+ if test $HAVE_XCB_SHAPE = yes && test "$XCB_LIBS" != ""; then
+ XSHAPE_LIBS="$XSHAPE_LIBS -lxcb-shape"
+ AC_DEFINE([HAVE_XCB_SHAPE], [1],
+ [Define to 1 if XCB supports the
+ Nonrectangular Window Shape extension.])
+ fi
+ fi
+ if test $HAVE_XSHAPE = yes; then
+ AC_DEFINE([HAVE_XSHAPE], [1],
+ [Define to 1 if you have the Nonrectangular Window Shape extension.])
+ fi
+fi
+AC_SUBST([XSHAPE_CFLAGS])
+AC_SUBST([XSHAPE_LIBS])
+
+### Use Xcomposite (-lXcomposite) if available
+HAVE_XCOMPOSITE=no
+if test "${HAVE_X11}" = "yes"; then
+ AC_CHECK_HEADER([X11/extensions/Xcomposite.h],
+ [AC_CHECK_LIB([Xcomposite], [XCompositeRedirectWindow],
+ [HAVE_XCOMPOSITE=yes])],
+ [],
+ [#include <X11/extensions/Xcomposite.h>
+ ])
+ if test $HAVE_XCOMPOSITE = yes; then
+ XCOMPOSITE_LIBS=-lXcomposite
+ fi
+ if test $HAVE_XCOMPOSITE = yes; then
+ AC_DEFINE([HAVE_XCOMPOSITE], [1],
+ [Define to 1 if you have the XCOMPOSITE extension.])
+ fi
+fi
+AC_SUBST([XCOMPOSITE_CFLAGS])
+AC_SUBST([XCOMPOSITE_LIBS])
### Use libxml (-lxml2) if available
### mingw32 doesn't use -lxml2, since it loads the library dynamically.
@@ -4542,8 +4769,8 @@ if test "${with_xml2}" != "no"; then
esac
fi
CPPFLAGS="$CPPFLAGS -isystem${xcsdkdir}/usr/include/libxml2"
- AC_CHECK_HEADER(libxml/HTMLparser.h,
- [AC_CHECK_DECL(HTML_PARSE_RECOVER, HAVE_LIBXML2=yes, ,
+ AC_CHECK_HEADER([libxml/HTMLparser.h],
+ [AC_CHECK_DECL([HTML_PARSE_RECOVER], [HAVE_LIBXML2=yes], [],
[#include <libxml/HTMLparser.h>])])
CPPFLAGS="$SAVE_CPPFLAGS"
if test "${HAVE_LIBXML2}" = "yes"; then
@@ -4553,21 +4780,24 @@ if test "${with_xml2}" != "no"; then
fi
if test "${HAVE_LIBXML2}" = "yes"; then
if test "${opsys}" != "mingw32"; then
- AC_CHECK_LIB(xml2, htmlReadMemory, HAVE_LIBXML2=yes, HAVE_LIBXML2=no,
+ AC_CHECK_LIB([xml2], [htmlReadMemory],
+ [HAVE_LIBXML2=yes],
+ [HAVE_LIBXML2=no],
[$LIBXML2_LIBS])
else
LIBXML2_LIBS=""
fi
if test "${HAVE_LIBXML2}" = "yes"; then
- AC_DEFINE(HAVE_LIBXML2, 1, [Define to 1 if you have the libxml library (-lxml2).])
+ AC_DEFINE([HAVE_LIBXML2], [1],
+ [Define to 1 if you have the libxml library (-lxml2).])
else
LIBXML2_LIBS=""
LIBXML2_CFLAGS=""
fi
fi
fi
-AC_SUBST(LIBXML2_LIBS)
-AC_SUBST(LIBXML2_CFLAGS)
+AC_SUBST([LIBXML2_LIBS])
+AC_SUBST([LIBXML2_CFLAGS])
BLESSMAIL_TARGET=
LIBS_MAIL=
@@ -4666,14 +4896,14 @@ AC_CHECK_HEADERS(
]])])
AC_SUBST([HAVE_SECCOMP])
-EMACS_CHECK_MODULES([LIBSECCOMP], [libseccomp >= 2.4.0])
+EMACS_CHECK_MODULES([LIBSECCOMP], [libseccomp >= 2.5.2])
AC_SUBST([HAVE_LIBSECCOMP])
AC_SUBST([LIBSECCOMP_LIBS])
AC_SUBST([LIBSECCOMP_CFLAGS])
OLD_LIBS=$LIBS
LIBS="$LIB_PTHREAD $LIB_MATH $LIBS"
-AC_CHECK_FUNCS(accept4 fchdir gethostname \
+AC_CHECK_FUNCS([accept4 fchdir gethostname \
getrusage get_current_dir_name \
lrand48 random rint trunc \
select getpagesize setlocale newlocale \
@@ -4683,7 +4913,7 @@ sendto recvfrom getsockname getifaddrs freeifaddrs \
gai_strerror sync \
getpwent endpwent getgrent endgrent \
cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \
-pthread_set_name_np)
+pthread_set_name_np])
LIBS=$OLD_LIBS
if test "$ac_cv_func_pthread_setname_np" = "yes"; then
@@ -4698,7 +4928,7 @@ if test "$ac_cv_func_pthread_setname_np" = "yes"; then
[emacs_cv_pthread_setname_np_1arg=no])])
if test "$emacs_cv_pthread_setname_np_1arg" = "yes"; then
AC_DEFINE(
- HAVE_PTHREAD_SETNAME_NP_1ARG, 1,
+ [HAVE_PTHREAD_SETNAME_NP_1ARG], [1],
[Define to 1 if pthread_setname_np takes a single argument.])
else
AC_CACHE_CHECK(
@@ -4712,7 +4942,7 @@ if test "$ac_cv_func_pthread_setname_np" = "yes"; then
[emacs_cv_pthread_setname_np_3arg=no])])
if test "$emacs_cv_pthread_setname_np_3arg" = "yes"; then
AC_DEFINE(
- HAVE_PTHREAD_SETNAME_NP_3ARG, 1,
+ [HAVE_PTHREAD_SETNAME_NP_3ARG], [1],
[Define to 1 if pthread_setname_np takes three arguments.])
fi
fi
@@ -4745,28 +4975,28 @@ AC_CACHE_CHECK([for __builtin_frame_address],
[emacs_cv_func___builtin_frame_address=yes],
[emacs_cv_func___builtin_frame_address=no])])
if test $emacs_cv_func___builtin_frame_address = yes; then
- AC_DEFINE([HAVE___BUILTIN_FRAME_ADDRESS], 1,
+ AC_DEFINE([HAVE___BUILTIN_FRAME_ADDRESS], [1],
[Define to 1 if you have the '__builtin_frame_address' function.])
fi
AC_CACHE_CHECK([for __builtin_unwind_init],
- emacs_cv_func___builtin_unwind_init,
+ [emacs_cv_func___builtin_unwind_init],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_unwind_init ();])],
- emacs_cv_func___builtin_unwind_init=yes,
- emacs_cv_func___builtin_unwind_init=no)])
+ [emacs_cv_func___builtin_unwind_init=yes],
+ [emacs_cv_func___builtin_unwind_init=no])])
if test $emacs_cv_func___builtin_unwind_init = yes; then
- AC_DEFINE(HAVE___BUILTIN_UNWIND_INIT, 1,
+ AC_DEFINE([HAVE___BUILTIN_UNWIND_INIT], [1],
[Define to 1 if you have the '__builtin_unwind_init' function.])
fi
-AC_CHECK_HEADERS_ONCE(sys/un.h)
+AC_CHECK_HEADERS_ONCE([sys/un.h])
AC_FUNC_FSEEKO
# UNIX98 PTYs.
-AC_CHECK_FUNCS(grantpt)
+AC_CHECK_FUNCS([grantpt])
# PTY-related GNU extensions.
-AC_CHECK_FUNCS(getpt posix_openpt)
+AC_CHECK_FUNCS([getpt posix_openpt])
dnl Run a test program that contains a call to tputs, a call that is
dnl never executed. This tests whether a pre-'main' dynamic linker
@@ -4838,14 +5068,15 @@ case "$opsys" in
freebsd)
AC_MSG_CHECKING([whether FreeBSD is new enough to use terminfo])
- AC_CACHE_VAL(emacs_cv_freebsd_terminfo,
+ AC_CACHE_VAL([emacs_cv_freebsd_terminfo],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <osreldate.h>]],
[[#if __FreeBSD_version < 400000
fail;
#endif
-]])], emacs_cv_freebsd_terminfo=yes, emacs_cv_freebsd_terminfo=no)])
+]])], [emacs_cv_freebsd_terminfo=yes],
+ [emacs_cv_freebsd_terminfo=no])])
- AC_MSG_RESULT($emacs_cv_freebsd_terminfo)
+ AC_MSG_RESULT([$emacs_cv_freebsd_terminfo])
if test $emacs_cv_freebsd_terminfo = yes; then
LIBS_TERMCAP="-lncurses"
@@ -4880,7 +5111,8 @@ esac
TERMCAP_OBJ=tparam.o
if test $TERMINFO = yes; then
- AC_DEFINE(TERMINFO, 1, [Define to 1 if you use terminfo instead of termcap.])
+ AC_DEFINE([TERMINFO], [1],
+ [Define to 1 if you use terminfo instead of termcap.])
TERMCAP_OBJ=terminfo.o
AC_CACHE_CHECK([whether $LIBS_TERMCAP library defines BC],
[emacs_cv_terminfo_defines_BC],
@@ -4891,15 +5123,15 @@ if test $TERMINFO = yes; then
[emacs_cv_terminfo_defines_BC=no])
LIBS=$OLD_LIBS])
if test "$emacs_cv_terminfo_defines_BC" = yes; then
- AC_DEFINE([TERMINFO_DEFINES_BC], 1, [Define to 1 if the
+ AC_DEFINE([TERMINFO_DEFINES_BC], [1], [Define to 1 if the
terminfo library defines the variables BC, PC, and UP.])
fi
fi
if test "X$LIBS_TERMCAP" = "X-lncurses"; then
- AC_DEFINE(USE_NCURSES, 1, [Define to 1 if you use ncurses.])
+ AC_DEFINE([USE_NCURSES], [1], [Define to 1 if you use ncurses.])
fi
-AC_SUBST(LIBS_TERMCAP)
-AC_SUBST(TERMCAP_OBJ)
+AC_SUBST([LIBS_TERMCAP])
+AC_SUBST([TERMCAP_OBJ])
# GNU/Linux-specific timer functions.
AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd],
@@ -4912,7 +5144,7 @@ AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd],
[emacs_cv_have_timerfd=yes],
[emacs_cv_have_timerfd=no])])
if test "$emacs_cv_have_timerfd" = yes; then
- AC_DEFINE([HAVE_TIMERFD], 1,
+ AC_DEFINE([HAVE_TIMERFD], [1],
[Define to 1 if timerfd functions are supported as in GNU/Linux.])
fi
@@ -4939,25 +5171,26 @@ LIBRESOLV=
if test "$with_hesiod" != no ; then
# Don't set $LIBS here -- see comments above. FIXME which comments?
resolv=no
- AC_CHECK_FUNC(res_send, , [AC_CHECK_FUNC(__res_send, ,
- [AC_CHECK_LIB(resolv, res_send, resolv=yes,
- [AC_CHECK_LIB(resolv, __res_send, resolv=yes)])])])
+ AC_CHECK_FUNC([res_send], [], [AC_CHECK_FUNC([__res_send], [],
+ [AC_CHECK_LIB([resolv], [res_send], [resolv=yes],
+ [AC_CHECK_LIB([resolv], [__res_send], [resolv=yes])])])])
if test "$resolv" = yes ; then
RESOLVLIB=-lresolv
else
RESOLVLIB=
fi
hesiod=no
- AC_CHECK_FUNC(hes_getmailhost, , [AC_CHECK_LIB(hesiod, hes_getmailhost,
- hesiod=yes, :, $RESOLVLIB)])
+ AC_CHECK_FUNC([hes_getmailhost], [],
+ [AC_CHECK_LIB([hesiod], [hes_getmailhost],
+ [hesiod=yes], [:], [$RESOLVLIB])])
if test x"$hesiod" = xyes; then
LIBHESIOD=-lhesiod
LIBRESOLV=$RESOLVLIB
fi
fi
-AC_SUBST(LIBHESIOD)
-AC_SUBST(LIBRESOLV)
+AC_SUBST([LIBHESIOD])
+AC_SUBST([LIBRESOLV])
# These tell us which Kerberos-related libraries to use.
COM_ERRLIB=
@@ -4968,45 +5201,51 @@ KRB4LIB=
if test "${with_kerberos}" != no; then
OLD_LIBS=$LIBS
- AC_CHECK_LIB(com_err, com_err, have_com_err=yes, have_com_err=no)
+ AC_CHECK_LIB([com_err], [com_err], [have_com_err=yes], [have_com_err=no])
if test $have_com_err = yes; then
COM_ERRLIB=-lcom_err
LIBS="$COM_ERRLIB $LIBS"
fi
- AC_CHECK_LIB(crypto, mit_des_cbc_encrypt, have_crypto=yes, have_crypto=no)
+ AC_CHECK_LIB([crypto], [mit_des_cbc_encrypt],
+ [have_crypto=yes],
+ [have_crypto=no])
if test $have_crypto = yes; then
CRYPTOLIB=-lcrypto
LIBS="$CRYPTOLIB $LIBS"
fi
- AC_CHECK_LIB(k5crypto, mit_des_cbc_encrypt, have_k5crypto=yes, have_k5crypto=no)
+ AC_CHECK_LIB([k5crypto], [mit_des_cbc_encrypt],
+ [have_k5crypto=yes],
+ [have_k5crypto=no])
if test $have_k5crypto = yes; then
CRYPTOLIB=-lk5crypto
LIBS="$CRYPTOLIB $LIBS"
fi
- AC_CHECK_LIB(krb5, krb5_init_context, have_krb5=yes, have_krb5=no)
+ AC_CHECK_LIB([krb5], [krb5_init_context], [have_krb5=yes], [have_krb5=no])
if test $have_krb5=yes; then
KRB5LIB=-lkrb5
LIBS="$KRB5LIB $LIBS"
fi
dnl FIXME Simplify. Does not match 22 logic, thanks to default_off?
if test "${with_kerberos5}" = no; then
- AC_CHECK_LIB(des425, des_cbc_encrypt, have_des425=yes, have_des425=no )
+ AC_CHECK_LIB([des425], [des_cbc_encrypt],
+ [have_des425=yes],
+ [have_des425=no])
if test $have_des425 = yes; then
DESLIB=-ldes425
LIBS="$DESLIB $LIBS"
else
- AC_CHECK_LIB(des, des_cbc_encrypt, have_des=yes, have_des=no)
+ AC_CHECK_LIB([des], [des_cbc_encrypt], [have_des=yes], [have_des=no])
if test $have_des = yes; then
DESLIB=-ldes
LIBS="$DESLIB $LIBS"
fi
fi
- AC_CHECK_LIB(krb4, krb_get_cred, have_krb4=yes, have_krb4=no)
+ AC_CHECK_LIB([krb4], [krb_get_cred], [have_krb4=yes], [have_krb4=no])
if test $have_krb4 = yes; then
KRB4LIB=-lkrb4
LIBS="$KRB4LIB $LIBS"
else
- AC_CHECK_LIB(krb, krb_get_cred, have_krb=yes, have_krb=no)
+ AC_CHECK_LIB([krb], [krb_get_cred], [have_krb=yes], [have_krb=no])
if test $have_krb = yes; then
KRB4LIB=-lkrb
LIBS="$KRB4LIB $LIBS"
@@ -5015,25 +5254,25 @@ if test "${with_kerberos}" != no; then
fi
if test "${with_kerberos5}" != no; then
- AC_CHECK_HEADERS(krb5.h,
- [AC_CHECK_MEMBERS([krb5_error.text, krb5_error.e_text],,,
+ AC_CHECK_HEADERS([krb5.h],
+ [AC_CHECK_MEMBERS([krb5_error.text, krb5_error.e_text], [], [],
[#include <krb5.h>])])
else
- AC_CHECK_HEADERS(krb.h,,
- [AC_CHECK_HEADERS(kerberosIV/krb.h,,
- [AC_CHECK_HEADERS(kerberos/krb.h)])])
+ AC_CHECK_HEADERS([krb.h], [],
+ [AC_CHECK_HEADERS([kerberosIV/krb.h], [],
+ [AC_CHECK_HEADERS([kerberos/krb.h])])])
fi
- AC_CHECK_HEADERS(com_err.h)
+ AC_CHECK_HEADERS([com_err.h])
LIBS=$OLD_LIBS
fi
-AC_SUBST(COM_ERRLIB)
-AC_SUBST(CRYPTOLIB)
-AC_SUBST(KRB5LIB)
-AC_SUBST(DESLIB)
-AC_SUBST(KRB4LIB)
+AC_SUBST([COM_ERRLIB])
+AC_SUBST([CRYPTOLIB])
+AC_SUBST([KRB5LIB])
+AC_SUBST([DESLIB])
+AC_SUBST([KRB4LIB])
-AC_CHECK_HEADERS(valgrind/valgrind.h)
+AC_CHECK_HEADERS([valgrind/valgrind.h])
AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include <linux/kd.h>]])
@@ -5043,7 +5282,7 @@ AC_FUNC_FORK
dnl AC_CHECK_FUNCS_ONCE wouldn’t be right for snprintf, which needs
dnl the current CFLAGS etc.
-AC_CHECK_FUNCS(snprintf)
+AC_CHECK_FUNCS([snprintf])
dnl posix_spawn. The chdir and setsid functionality is relatively
dnl recent, so we check for it specifically.
@@ -5087,12 +5326,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM(
CFLAGS="$OLDCFLAGS"
LIBS="$OLDLIBS"])
if test "${emacs_cv_links_glib}" = "yes"; then
- AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib is linked in.])
+ AC_DEFINE([HAVE_GLIB], [1], [Define to 1 if GLib is linked in.])
if test "$HAVE_NS" = no ; then
XGSELOBJ=xgselect.o
fi
fi
-AC_SUBST(XGSELOBJ)
+AC_SUBST([XGSELOBJ])
dnl Adapted from Haible's version.
AC_CACHE_CHECK([for nl_langinfo and CODESET], [emacs_cv_langinfo_codeset],
@@ -5102,7 +5341,7 @@ AC_CACHE_CHECK([for nl_langinfo and CODESET], [emacs_cv_langinfo_codeset],
[emacs_cv_langinfo_codeset=no])
])
if test "$emacs_cv_langinfo_codeset" = yes; then
- AC_DEFINE([HAVE_LANGINFO_CODESET], 1,
+ AC_DEFINE([HAVE_LANGINFO_CODESET], [1],
[Define if you have <langinfo.h> and nl_langinfo (CODESET).])
AC_CACHE_CHECK([for nl_langinfo and _NL_PAPER_WIDTH],
@@ -5113,7 +5352,7 @@ if test "$emacs_cv_langinfo_codeset" = yes; then
[emacs_cv_langinfo__nl_paper_width=no])
])
if test "$emacs_cv_langinfo__nl_paper_width" = yes; then
- AC_DEFINE([HAVE_LANGINFO__NL_PAPER_WIDTH], 1,
+ AC_DEFINE([HAVE_LANGINFO__NL_PAPER_WIDTH], [1],
[Define if you have <langinfo.h> and nl_langinfo (_NL_PAPER_WIDTH).])
fi
fi
@@ -5126,15 +5365,17 @@ dnl The following looks like a useful start.
dnl
dnl AC_SYS_POSIX_TERMIOS
dnl if test $ac_cv_sys_posix_termios = yes; then
-dnl AC_DEFINE(HAVE_TERMIOS, 1, [Define to 1 if you have POSIX-style functions
-dnl and macros for terminal control.])
-dnl AC_DEFINE(HAVE_TCATTR, 1, [Define to 1 if you have tcgetattr and tcsetattr.])
+dnl AC_DEFINE([HAVE_TERMIOS], [1],
+dnl [Define to 1 if you have POSIX-style
+dnl functions and macros for terminal control.])
+dnl AC_DEFINE([HAVE_TCATTR], [1],
+dnl [Define to 1 if you have tcgetattr and tcsetattr.])
dnl fi
dnl Turned on June 1996 supposing nobody will mind it.
dnl MinGW emulates passwd database, so this feature doesn't make sense there.
if test "${opsys}" != "mingw32"; then
- AC_DEFINE(AMPERSAND_FULL_NAME, 1, [Define to use the convention that &
+ AC_DEFINE([AMPERSAND_FULL_NAME], [1], [Define to use the convention that &
in the full name stands for the login id.])
fi
@@ -5142,22 +5383,23 @@ dnl Everybody supports this, except MS.
dnl Seems like the kind of thing we should be testing for, though.
## Note: PTYs are broken on darwin <6. Use at your own risk.
if test "${opsys}" != "mingw32"; then
- AC_DEFINE(HAVE_PTYS, 1, [Define if the system supports pty devices.])
+ AC_DEFINE([HAVE_PTYS], [1], [Define if the system supports pty devices.])
fi
dnl Everybody supports this, except MS-DOS.
dnl Seems like the kind of thing we should be testing for, though.
-AC_DEFINE(HAVE_SOCKETS, 1, [Define if the system supports
+AC_DEFINE([HAVE_SOCKETS], [1], [Define if the system supports
4.2-compatible sockets.])
-AH_TEMPLATE(INTERNAL_TERMINAL, [This is substituted when $TERM is "internal".])
+AH_TEMPLATE([INTERNAL_TERMINAL],
+ [This is substituted when $TERM is "internal".])
-AH_TEMPLATE(NULL_DEVICE, [Name of the file to open to get
+AH_TEMPLATE([NULL_DEVICE], [Name of the file to open to get
a null file, or a data sink.])
if test "${opsys}" = "mingw32"; then
- AC_DEFINE(NULL_DEVICE, ["NUL:"])
+ AC_DEFINE([NULL_DEVICE], ["NUL:"])
else
- AC_DEFINE(NULL_DEVICE, ["/dev/null"])
+ AC_DEFINE([NULL_DEVICE], ["/dev/null"])
fi
if test "${opsys}" = "mingw32"; then
@@ -5165,7 +5407,8 @@ if test "${opsys}" = "mingw32"; then
else
SEPCHAR=':'
fi
-AC_DEFINE_UNQUOTED(SEPCHAR, ['$SEPCHAR'], [Character that separates PATH elements.])
+AC_DEFINE_UNQUOTED([SEPCHAR], ['$SEPCHAR'],
+ [Character that separates PATH elements.])
dnl This is for MinGW, and is used in test/Makefile.in.
dnl The MSYS Bash has heuristics for replacing ':' with ';' when it
dnl decides that a command-line argument to be passed to a MinGW program
@@ -5175,34 +5418,35 @@ dnl sees a colon-separated list of file names; e.g. ":." is left alone,
dnl which breaks in-tree builds. So we do this manually instead.
dnl Note that we cannot rely on PATH_SEPARATOR, as that one will always
dnl be computed as ':' in MSYS Bash.
-AC_SUBST(SEPCHAR)
+AC_SUBST([SEPCHAR])
dnl Everybody supports this, except MS-DOS.
-AC_DEFINE(subprocesses, 1, [Define to enable asynchronous subprocesses.])
+AC_DEFINE([subprocesses], [1], [Define to enable asynchronous subprocesses.])
-AC_DEFINE(USER_FULL_NAME, [pw->pw_gecos], [How to get a user's full name.])
+AC_DEFINE([USER_FULL_NAME], [pw->pw_gecos], [How to get a user's full name.])
-AC_DEFINE(DIRECTORY_SEP, ['/'],
+AC_DEFINE([DIRECTORY_SEP], ['/'],
[Character that separates directories in a file name.])
if test "${opsys}" = "mingw32"; then
- AC_DEFINE(IS_DEVICE_SEP(_c_), [((_c_) == ':')],
+ AC_DEFINE([IS_DEVICE_SEP(_c_)], [((_c_) == ':')],
[Returns true if character is a device separator.])
- AC_DEFINE(IS_DIRECTORY_SEP(_c_), [((_c_) == '/' || (_c_) == '\\')],
+ AC_DEFINE([IS_DIRECTORY_SEP(_c_)], [((_c_) == '/' || (_c_) == '\\')],
[Returns true if character is a directory separator.])
- AC_DEFINE(IS_ANY_SEP(_c_), [(IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP(_c_))],
+ AC_DEFINE([IS_ANY_SEP(_c_)],
+ [(IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP (_c_))],
[Returns true if character is any form of separator.])
else
- AC_DEFINE(IS_DEVICE_SEP(_c_), 0,
+ AC_DEFINE([IS_DEVICE_SEP(_c_)], 0,
[Returns true if character is a device separator.])
- AC_DEFINE(IS_DIRECTORY_SEP(_c_), [((_c_) == DIRECTORY_SEP)],
+ AC_DEFINE([IS_DIRECTORY_SEP(_c_)], [((_c_) == DIRECTORY_SEP)],
[Returns true if character is a directory separator.])
- AC_DEFINE(IS_ANY_SEP(_c_), [(IS_DIRECTORY_SEP (_c_))],
+ AC_DEFINE([IS_ANY_SEP(_c_)], [(IS_DIRECTORY_SEP (_c_))],
[Returns true if character is any form of separator.])
fi
@@ -5227,7 +5471,7 @@ if test "$USE_X_TOOLKIT" != "none"; then
[[#include <X11/Intrinsic.h>
#include <X11/Xmu/Editres.h>]],
[[_XEditResCheckMessages (0, 0, 0, 0);]])],
- [AC_DEFINE([X_TOOLKIT_EDITRES], 1,
+ [AC_DEFINE([X_TOOLKIT_EDITRES], [1],
[Define to 1 if we should use XEditRes.])])
LIBS=$OLDLIBS
fi
@@ -5239,7 +5483,7 @@ case $opsys in
dnl instead, there's a system variable _sys_nsig. Unfortunately, we
dnl need the constant to dimension an array. So wire in the appropriate
dnl value here.
- AC_DEFINE(NSIG_MINIMUM, 32, [Minimum value of NSIG.])
+ AC_DEFINE([NSIG_MINIMUM], [32], [Minimum value of NSIG.])
;;
esac
@@ -5272,7 +5516,7 @@ case $opsys in
dnl of this file, so that we do not check for get_current_dir_name
dnl on AIX. But that might be fragile if something else ends
dnl up testing for get_current_dir_name as a dependency.
- AC_DEFINE(BROKEN_GET_CURRENT_DIR_NAME, 1, [Define if
+ AC_DEFINE([BROKEN_GET_CURRENT_DIR_NAME], [1], [Define if
get_current_dir_name should not be used.])
;;
@@ -5290,7 +5534,7 @@ case $opsys in
dnl successfully after processing (for example with CRs added if the
dnl terminal is set up that way which it is here). The same bytes will
dnl be seen again in a later read(2), without the CRs.
- AC_DEFINE(BROKEN_PTY_READ_AFTER_EAGAIN, 1, [Define on FreeBSD to
+ AC_DEFINE([BROKEN_PTY_READ_AFTER_EAGAIN], [1], [Define on FreeBSD to
work around an issue when reading from a PTY.])
;;
esac
@@ -5298,13 +5542,13 @@ esac
case $opsys in
gnu-* | solaris )
dnl FIXME Can't we test if this exists (eg /proc/$$)?
- AC_DEFINE(HAVE_PROCFS, 1, [Define if you have the /proc filesystem.])
+ AC_DEFINE([HAVE_PROCFS], [1], [Define if you have the /proc filesystem.])
;;
esac
case $opsys in
darwin | dragonfly | freebsd | netbsd | openbsd )
- AC_DEFINE(DONT_REOPEN_PTY, 1, [Define if process.c does not need to
+ AC_DEFINE([DONT_REOPEN_PTY], [1], [Define if process.c does not need to
close a pty to make it a controlling terminal (it is already a
controlling terminal of the subprocess, because we did ioctl TIOCSCTTY).])
;;
@@ -5317,7 +5561,7 @@ case $opsys in
esac
dnl Used in sound.c
-AC_DEFINE_UNQUOTED(DEFAULT_SOUND_DEVICE, "$sound_device",
+AC_DEFINE_UNQUOTED([DEFAULT_SOUND_DEVICE], ["$sound_device"],
[Name of the default sound device.])
@@ -5344,7 +5588,7 @@ dnl to read the input and send it to the true Emacs process
dnl through a pipe.
case $opsys in
darwin | gnu-linux | gnu-kfreebsd)
- AC_DEFINE(INTERRUPT_INPUT, 1, [Define to read input using SIGIO.])
+ AC_DEFINE([INTERRUPT_INPUT], [1], [Define to read input using SIGIO.])
;;
esac
@@ -5356,73 +5600,78 @@ dnl NARROWPROTO, we will see the wrong function prototypes for X functions
dnl taking float or double parameters.
case $opsys in
cygwin|gnu|gnu-linux|gnu-kfreebsd|freebsd|netbsd|openbsd)
- AC_DEFINE(NARROWPROTO, 1, [Define if system's imake configuration
+ AC_DEFINE([NARROWPROTO], [1], [Define if system's imake configuration
file defines 'NeedWidePrototypes' as 'NO'.])
;;
esac
dnl Used in process.c, this must be a loop, even if it only runs once.
-AH_TEMPLATE(PTY_ITERATION, [How to iterate over PTYs.])
+AH_TEMPLATE([PTY_ITERATION], [How to iterate over PTYs.])
dnl Only used if !PTY_ITERATION. Iterate from FIRST_PTY_LETTER to z,
dnl trying suffixes 0-16.
-AH_TEMPLATE(FIRST_PTY_LETTER, [Letter to use in finding device name of
+AH_TEMPLATE([FIRST_PTY_LETTER], [Letter to use in finding device name of
first PTY, if PTYs are supported.])
-AH_TEMPLATE(PTY_OPEN, [How to open a PTY, if non-standard.])
-AH_TEMPLATE(PTY_NAME_SPRINTF, [How to get the device name of the control
+AH_TEMPLATE([PTY_OPEN], [How to open a PTY, if non-standard.])
+AH_TEMPLATE([PTY_NAME_SPRINTF], [How to get the device name of the control
end of a PTY, if non-standard.])
-AH_TEMPLATE(PTY_TTY_NAME_SPRINTF, [How to get device name of the tty
+AH_TEMPLATE([PTY_TTY_NAME_SPRINTF], [How to get device name of the tty
end of a PTY, if non-standard.])
case $opsys in
aix4-2 )
- AC_DEFINE(PTY_ITERATION, [int c; for (c = 0; !c ; c++)])
+ AC_DEFINE([PTY_ITERATION], [int c; for (c = 0; !c ; c++)])
dnl You allocate a pty by opening /dev/ptc to get the master side.
dnl To get the name of the slave side, you just ttyname() the master side.
- AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptc");])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [strcpy (pty_name, ttyname (fd));])
+ AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptc");])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF], [strcpy (pty_name, ttyname (fd));])
;;
cygwin )
- AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)])
+ AC_DEFINE([PTY_ITERATION], [int i; for (i = 0; i < 1; i++)])
dnl multi-line AC_DEFINEs are hard. :(
- AC_DEFINE(PTY_OPEN, [ do { int dummy; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; pthread_sigmask (SIG_SETMASK, &procmask, 0); if (fd >= 0) emacs_close (dummy); } while (false)])
- AC_DEFINE(PTY_NAME_SPRINTF, [])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [])
+ AC_DEFINE([PTY_OPEN],
+ [ do { int dummy; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; pthread_sigmask (SIG_SETMASK, &procmask, 0); if (fd >= 0) emacs_close (dummy); } while (false)])
+ AC_DEFINE([PTY_NAME_SPRINTF], [])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF], [])
;;
gnu | qnxnto )
- AC_DEFINE(FIRST_PTY_LETTER, ['p'])
+ AC_DEFINE([FIRST_PTY_LETTER], ['p'])
;;
gnu-linux | gnu-kfreebsd | dragonfly | freebsd | openbsd | netbsd | darwin | nacl )
dnl if HAVE_GRANTPT
if test "x$ac_cv_func_grantpt" = xyes; then
- AC_DEFINE(UNIX98_PTYS, 1, [Define if the system has Unix98 PTYs.])
- AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)])
+ AC_DEFINE([UNIX98_PTYS], [1], [Define if the system has Unix98 PTYs.])
+ AC_DEFINE([PTY_ITERATION], [int i; for (i = 0; i < 1; i++)])
dnl Note that grantpt and unlockpt may fork. We must block SIGCHLD
dnl to prevent sigchld_handler from intercepting the child's death.
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname = 0; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (!ptyname) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF],
+ [{ char *ptyname = 0; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (!ptyname) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
dnl if HAVE_POSIX_OPENPT
if test "x$ac_cv_func_posix_openpt" = xyes; then
- AC_DEFINE(PTY_OPEN, [do { fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY); if (fd < 0 && errno == EINVAL) fd = posix_openpt (O_RDWR | O_NOCTTY); } while (false)])
- AC_DEFINE(PTY_NAME_SPRINTF, [])
+ AC_DEFINE([PTY_OPEN],
+ [do { fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY); if (fd < 0 && errno == EINVAL) fd = posix_openpt (O_RDWR | O_NOCTTY); } while (false)])
+ AC_DEFINE([PTY_NAME_SPRINTF], [])
dnl if HAVE_GETPT
elif test "x$ac_cv_func_getpt" = xyes; then
- AC_DEFINE(PTY_OPEN, [fd = getpt ()])
- AC_DEFINE(PTY_NAME_SPRINTF, [])
+ AC_DEFINE([PTY_OPEN], [fd = getpt ()])
+ AC_DEFINE([PTY_NAME_SPRINTF], [])
else
- AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptmx");])
+ AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptmx");])
fi
else
- AC_DEFINE(FIRST_PTY_LETTER, ['p'])
+ AC_DEFINE([FIRST_PTY_LETTER], ['p'])
fi
;;
hpux*)
- AC_DEFINE(FIRST_PTY_LETTER, ['p'])
- AC_DEFINE(PTY_NAME_SPRINTF, [sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [sprintf (pty_name, "/dev/pty/tty%c%x", c, i);])
+ AC_DEFINE([FIRST_PTY_LETTER], ['p'])
+ AC_DEFINE([PTY_NAME_SPRINTF],
+ [sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF],
+ [sprintf (pty_name, "/dev/pty/tty%c%x", c, i);])
;;
solaris )
@@ -5430,22 +5679,25 @@ case $opsys in
dnl O_CLOEXEC when opening the pty, and keep the SIGCHLD handler
dnl from intercepting that death. If any child but grantpt's should die
dnl within, it should be caught after sigrelse(2).
- AC_DEFINE(PTY_OPEN, [fd = open (pty_name, O_RDWR | O_NONBLOCK)])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
+ AC_DEFINE([PTY_OPEN], [fd = open (pty_name, O_RDWR | O_NONBLOCK)])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF],
+ [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
;;
unixware )
dnl Comments are as per solaris.
- AC_DEFINE(PTY_OPEN, [fd = open (pty_name, O_RDWR | O_NONBLOCK)])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
+ AC_DEFINE([PTY_OPEN], [fd = open (pty_name, O_RDWR | O_NONBLOCK)])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF],
+ [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
;;
haiku*)
- AC_DEFINE(FIRST_PTY_LETTER, ['s'])
- AC_DEFINE(PTY_NAME_SPRINTF, [])
+ AC_DEFINE([FIRST_PTY_LETTER], ['s'])
+ AC_DEFINE([PTY_NAME_SPRINTF], [])
dnl on Haiku pty names aren't distinctive, thus the use of posix_openpt
- AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_NONBLOCK)])
- AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
+ AC_DEFINE([PTY_OPEN], [fd = posix_openpt (O_RDWR | O_NONBLOCK)])
+ AC_DEFINE([PTY_TTY_NAME_SPRINTF],
+ [{ char *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
;;
esac
@@ -5454,21 +5706,22 @@ case $opsys in
solaris | unixware )
dnl This change means that we don't loop through allocate_pty too
dnl many times in the (rare) event of a failure.
- AC_DEFINE(FIRST_PTY_LETTER, ['z'])
- AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptmx");])
+ AC_DEFINE([FIRST_PTY_LETTER], ['z'])
+ AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptmx");])
dnl Push various streams modules onto a PTY channel. Used in process.c.
- AC_DEFINE(SETUP_SLAVE_PTY, [if (ioctl (std_in, I_PUSH, "ptem") == -1) fatal ("ioctl I_PUSH ptem"); if (ioctl (std_in, I_PUSH, "ldterm") == -1) fatal ("ioctl I_PUSH ldterm"); if (ioctl (std_in, I_PUSH, "ttcompat") == -1) fatal ("ioctl I_PUSH ttcompat");], [How to set up a slave PTY, if needed.])
+ AC_DEFINE([SETUP_SLAVE_PTY],
+ [if (ioctl (std_in, I_PUSH, "ptem") == -1) fatal ("ioctl I_PUSH ptem"); if (ioctl (std_in, I_PUSH, "ldterm") == -1) fatal ("ioctl I_PUSH ldterm"); if (ioctl (std_in, I_PUSH, "ttcompat") == -1) fatal ("ioctl I_PUSH ttcompat");], [How to set up a slave PTY, if needed.])
;;
esac
-AH_TEMPLATE(SIGNALS_VIA_CHARACTERS, [Make process_send_signal work by
+AH_TEMPLATE([SIGNALS_VIA_CHARACTERS], [Make process_send_signal work by
"typing" a signal character on the pty.])
case $opsys in
dnl Perry Smith <pedz@ddivt1.austin.ibm.com> says this is correct for AIX.
aix4-2 | cygwin | gnu | dragonfly | freebsd | netbsd | openbsd | darwin )
- AC_DEFINE(SIGNALS_VIA_CHARACTERS, 1)
+ AC_DEFINE([SIGNALS_VIA_CHARACTERS], [1])
;;
dnl 21 Jun 06: Eric Hanchrow <offby1@blarg.net> says this works.
@@ -5481,35 +5734,41 @@ case $opsys in
#if LINUX_VERSION_CODE < 0x20400
# error "Linux version too old"
#endif
- ]], [[]])], emacs_cv_signals_via_chars=yes, emacs_cv_signals_via_chars=no)])
+ ]], [[]])],
+ [emacs_cv_signals_via_chars=yes],
+ [emacs_cv_signals_via_chars=no])])
- test "$emacs_cv_signals_via_chars" = yes && AC_DEFINE(SIGNALS_VIA_CHARACTERS, 1)
+ test "$emacs_cv_signals_via_chars" = yes &&
+ AC_DEFINE([SIGNALS_VIA_CHARACTERS], [1])
;;
esac
-AH_TEMPLATE(TAB3, [Undocumented.])
+AH_TEMPLATE([TAB3], [Undocumented.])
case $opsys in
- darwin) AC_DEFINE(TAB3, OXTABS) ;;
+ darwin) AC_DEFINE([TAB3], [OXTABS]) ;;
gnu | dragonfly | freebsd | netbsd | openbsd )
- AC_DEFINE(TABDLY, OXTABS, [Undocumented.])
- AC_DEFINE(TAB3, OXTABS)
+ AC_DEFINE([TABDLY], [OXTABS], [Undocumented.])
+ AC_DEFINE([TAB3], [OXTABS])
;;
gnu-linux | gnu-kfreebsd )
- AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
+ AC_PREPROC_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
#ifndef __ia64__
# error "not ia64"
#endif
- ]], [[]])], AC_DEFINE(GC_MARK_SECONDARY_STACK(),
+ ]], [[]])],
+ [AC_DEFINE([GC_MARK_SECONDARY_STACK()],
[do { extern void *__libc_ia64_register_backing_store_base; __builtin_ia64_flushrs (); mark_memory (__libc_ia64_register_backing_store_base, __builtin_ia64_bsp ());} while (false)],
- [Mark a secondary stack, like the register stack on the ia64.]), [])
+ [Mark a secondary stack, like the register stack on the ia64.])], [])
;;
hpux*)
- AC_DEFINE(RUN_TIME_REMAP, 1, [Define if emacs.c needs to call
+ AC_DEFINE([RUN_TIME_REMAP], [1], [Define if emacs.c needs to call
run_time_remap; for HPUX.])
;;
esac
@@ -5517,7 +5776,7 @@ esac
dnl This won't be used automatically yet. We also need to know, at least,
dnl that the stack is continuous.
-AH_TEMPLATE(GC_SETJMP_WORKS, [Define if setjmp is known to save all
+AH_TEMPLATE([GC_SETJMP_WORKS], [Define if setjmp is known to save all
registers relevant for conservative garbage collection in the jmp_buf.])
@@ -5537,18 +5796,18 @@ case $opsys in
#else
# error "setjmp not known to work on this arch"
#endif
- ]], [[]])], AC_DEFINE(GC_SETJMP_WORKS, 1))
+ ]], [[]])], [AC_DEFINE([GC_SETJMP_WORKS], [1])])
;;
esac
if test x$GCC = xyes; then
dnl GC_SETJMP_WORKS is nearly always appropriate for GCC.
- AC_DEFINE(GC_SETJMP_WORKS, 1)
+ AC_DEFINE([GC_SETJMP_WORKS], [1])
else
case $opsys in
aix* | dragonfly | freebsd | netbsd | openbsd | solaris )
- AC_DEFINE(GC_SETJMP_WORKS, 1)
+ AC_DEFINE([GC_SETJMP_WORKS], [1])
;;
esac
fi dnl GCC?
@@ -5568,7 +5827,7 @@ AC_CACHE_CHECK([for _setjmp], [emacs_cv_func__setjmp],
[emacs_cv_func__setjmp=yes],
[emacs_cv_func__setjmp=no])])
if test $emacs_cv_func__setjmp = yes; then
- AC_DEFINE([HAVE__SETJMP], 1, [Define to 1 if _setjmp and _longjmp work.])
+ AC_DEFINE([HAVE__SETJMP], [1], [Define to 1 if _setjmp and _longjmp work.])
fi
# We need to preserve signal mask to handle C stack overflows.
@@ -5583,13 +5842,13 @@ AC_CACHE_CHECK([for sigsetjmp], [emacs_cv_func_sigsetjmp],
[emacs_cv_func_sigsetjmp=yes],
[emacs_cv_func_sigsetjmp=no])])
if test $emacs_cv_func_sigsetjmp = yes; then
- AC_DEFINE([HAVE_SIGSETJMP], 1,
+ AC_DEFINE([HAVE_SIGSETJMP], [1],
[Define to 1 if sigsetjmp and siglongjmp work.])
fi
case $emacs_cv_func_sigsetjmp,$emacs_cv_alternate_stack,$opsys in
yes,yes,* | *,*,mingw32)
- AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], 1,
+ AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
[Define to 1 if C stack overflow can be handled in some cases.]);;
esac
@@ -5598,7 +5857,7 @@ case $opsys in
dnl TIOCGPGRP is broken in SysVr4, so we can't send signals to PTY
dnl subprocesses the usual way. But TIOCSIGNAL does work for PTYs,
dnl and this is all we need.
- AC_DEFINE(TIOCSIGSEND, TIOCSIGNAL, [Some platforms redefine this.])
+ AC_DEFINE([TIOCSIGSEND], [TIOCSIGNAL], [Some platforms redefine this.])
;;
esac
@@ -5606,7 +5865,7 @@ esac
case $opsys in
hpux* | solaris )
dnl Used in xfaces.c.
- AC_DEFINE(XOS_NEEDS_TIME_H, 1, [Compensate for a bug in Xos.h on
+ AC_DEFINE([XOS_NEEDS_TIME_H], [1], [Compensate for a bug in Xos.h on
some systems, where it requires time.h.])
;;
esac
@@ -5614,64 +5873,67 @@ esac
dnl Define symbols to identify the version of Unix this is.
dnl Define all the symbols that apply correctly.
-AH_TEMPLATE(DOS_NT, [Define if the system is MS DOS or MS Windows.])
-AH_TEMPLATE(MSDOS, [Define if the system is MS DOS.])
-AH_TEMPLATE(USG, [Define if the system is compatible with System III.])
-AH_TEMPLATE(USG5_4, [Define if the system is compatible with System V Release 4.])
+AH_TEMPLATE([DOS_NT], [Define if the system is MS DOS or MS Windows.])
+AH_TEMPLATE([MSDOS], [Define if the system is MS DOS.])
+AH_TEMPLATE([USG], [Define if the system is compatible with System III.])
+AH_TEMPLATE([USG5_4],
+ [Define if the system is compatible with System V Release 4.])
case $opsys in
aix4-2)
- AC_DEFINE(USG, [])
+ AC_DEFINE([USG], [])
dnl This symbol should be defined on AIX Version 3 ???????
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
#ifndef _AIX
# error "_AIX not defined"
#endif
- ]], [[]])], [], AC_DEFINE(_AIX, [], [Define if the system is AIX.]))
+ ]], [[]])], [], [AC_DEFINE([_AIX], [], [Define if the system is AIX.])])
;;
cygwin)
- AC_DEFINE(CYGWIN, 1, [Define if the system is Cygwin.])
+ AC_DEFINE([CYGWIN], [1], [Define if the system is Cygwin.])
;;
darwin)
dnl Not __APPLE__, as this may not be defined on non-macOS Darwin.
dnl Not DARWIN, because Panther and lower CoreFoundation.h use DARWIN to
dnl distinguish macOS from pure Darwin.
- AC_DEFINE(DARWIN_OS, [], [Define if the system is Darwin.])
+ AC_DEFINE([DARWIN_OS], [], [Define if the system is Darwin.])
;;
gnu-linux | gnu-kfreebsd )
- AC_DEFINE(USG, [])
- AC_DEFINE(GNU_LINUX, [], [Define if ths system is compatible with GNU/Linux.])
+ AC_DEFINE([USG], [])
+ AC_DEFINE([GNU_LINUX], [],
+ [Define if ths system is compatible with GNU/Linux.])
;;
hpux*)
- AC_DEFINE(USG, [])
- AC_DEFINE(HPUX, [], [Define if the system is HPUX.])
+ AC_DEFINE([USG], [])
+ AC_DEFINE([HPUX], [], [Define if the system is HPUX.])
;;
mingw32)
- AC_DEFINE(DOS_NT, [])
- AC_DEFINE(WINDOWSNT, 1, [Define if compiling for native MS Windows.])
+ AC_DEFINE([DOS_NT], [])
+ AC_DEFINE([WINDOWSNT], [1], [Define if compiling for native MS Windows.])
if test "x$ac_enable_checking" != "x" ; then
- AC_DEFINE(EMACSDEBUG, 1, [Define to 1 to enable w32 debug facilities.])
+ AC_DEFINE([EMACSDEBUG], [1],
+ [Define to 1 to enable w32 debug facilities.])
fi
;;
solaris)
- AC_DEFINE(USG, [])
- AC_DEFINE(USG5_4, [])
- AC_DEFINE(SOLARIS2, [], [Define if the system is Solaris.])
+ AC_DEFINE([USG], [])
+ AC_DEFINE([USG5_4], [])
+ AC_DEFINE([SOLARIS2], [], [Define if the system is Solaris.])
;;
unixware)
- AC_DEFINE(USG, [])
- AC_DEFINE(USG5_4, [])
+ AC_DEFINE([USG], [])
+ AC_DEFINE([USG5_4], [])
;;
haiku)
- AC_DEFINE(HAIKU, [], [Define if the system is Haiku.])
+ AC_DEFINE([HAIKU], [], [Define if the system is Haiku.])
;;
esac
@@ -5752,13 +6014,13 @@ case $opsys in
hpux11)
dnl It works to open the pty's tty in the parent (Emacs), then
dnl close and reopen it in the child.
- AC_DEFINE(USG_SUBTTY_WORKS, 1, [Define for USG systems where it
+ AC_DEFINE([USG_SUBTTY_WORKS], [1], [Define for USG systems where it
works to open a pty's tty in the parent process, then close and
reopen it in the child.])
;;
solaris)
- AC_DEFINE(_STRUCTURED_PROC, 1, [Needed for system_process_attributes
+ AC_DEFINE([_STRUCTURED_PROC], [1], [Needed for system_process_attributes
on Solaris.])
;;
esac
@@ -5781,72 +6043,72 @@ fi
version=$PACKAGE_VERSION
copyright="Copyright (C) 2022 Free Software Foundation, Inc."
-AC_DEFINE_UNQUOTED(COPYRIGHT, ["$copyright"],
+AC_DEFINE_UNQUOTED([COPYRIGHT], ["$copyright"],
[Short copyright string for this version of Emacs.])
-AC_SUBST(copyright)
+AC_SUBST([copyright])
### Specify what sort of things we'll be editing into Makefile and config.h.
### Use configuration here uncanonicalized to avoid exceeding size limits.
-AC_SUBST(version)
-AC_SUBST(configuration)
+AC_SUBST([version])
+AC_SUBST([configuration])
## Unused?
-AC_SUBST(canonical)
-AC_SUBST(srcdir)
-AC_SUBST(prefix)
-AC_SUBST(exec_prefix)
-AC_SUBST(bindir)
-AC_SUBST(datadir)
-AC_SUBST(gsettingsschemadir)
-AC_SUBST(sharedstatedir)
-AC_SUBST(libexecdir)
-AC_SUBST(mandir)
-AC_SUBST(infodir)
-AC_SUBST(lispdirrel)
-AC_SUBST(lispdir)
-AC_SUBST(standardlisppath)
-AC_SUBST(locallisppath)
-AC_SUBST(lisppath)
-AC_SUBST(x_default_search_path)
-AC_SUBST(etcdir)
-AC_SUBST(archlibdir)
-AC_SUBST(etcdocdir)
-AC_SUBST(bitmapdir)
-AC_SUBST(gamedir)
-AC_SUBST(gameuser)
-AC_SUBST(gamegroup)
+AC_SUBST([canonical])
+AC_SUBST([srcdir])
+AC_SUBST([prefix])
+AC_SUBST([exec_prefix])
+AC_SUBST([bindir])
+AC_SUBST([datadir])
+AC_SUBST([gsettingsschemadir])
+AC_SUBST([sharedstatedir])
+AC_SUBST([libexecdir])
+AC_SUBST([mandir])
+AC_SUBST([infodir])
+AC_SUBST([lispdirrel])
+AC_SUBST([lispdir])
+AC_SUBST([standardlisppath])
+AC_SUBST([locallisppath])
+AC_SUBST([lisppath])
+AC_SUBST([x_default_search_path])
+AC_SUBST([etcdir])
+AC_SUBST([archlibdir])
+AC_SUBST([etcdocdir])
+AC_SUBST([bitmapdir])
+AC_SUBST([gamedir])
+AC_SUBST([gameuser])
+AC_SUBST([gamegroup])
## FIXME? Nothing uses @LD_SWITCH_X_SITE@.
## src/Makefile.in did add LD_SWITCH_X_SITE (as a cpp define) to the
## end of LIBX_BASE, but nothing ever set it.
-AC_SUBST(LD_SWITCH_X_SITE)
-AC_SUBST(C_SWITCH_X_SITE)
-AC_SUBST(GNUSTEP_CFLAGS)
-AC_SUBST(CFLAGS)
+AC_SUBST([LD_SWITCH_X_SITE])
+AC_SUBST([C_SWITCH_X_SITE])
+AC_SUBST([GNUSTEP_CFLAGS])
+AC_SUBST([CFLAGS])
## Used in lwlib/Makefile.in.
-AC_SUBST(X_TOOLKIT_TYPE)
-AC_SUBST(ns_appdir)
-AC_SUBST(ns_appbindir)
-AC_SUBST(ns_applibexecdir)
-AC_SUBST(ns_applibdir)
-AC_SUBST(ns_appresdir)
-AC_SUBST(ns_appsrc)
-AC_SUBST(GNU_OBJC_CFLAGS)
-AC_SUBST(OTHER_FILES)
+AC_SUBST([X_TOOLKIT_TYPE])
+AC_SUBST([ns_appdir])
+AC_SUBST([ns_appbindir])
+AC_SUBST([ns_applibexecdir])
+AC_SUBST([ns_applibdir])
+AC_SUBST([ns_appresdir])
+AC_SUBST([ns_appsrc])
+AC_SUBST([GNU_OBJC_CFLAGS])
+AC_SUBST([OTHER_FILES])
if test -n "${term_header}"; then
- AC_DEFINE_UNQUOTED(TERM_HEADER, "${term_header}",
+ AC_DEFINE_UNQUOTED([TERM_HEADER], ["${term_header}"],
[Define to the header for the built-in window system.])
fi
-AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}",
+AC_DEFINE_UNQUOTED([EMACS_CONFIGURATION], ["${canonical}"],
[Define to the canonical Emacs configuration name.])
-AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${emacs_config_options}",
+AC_DEFINE_UNQUOTED([EMACS_CONFIG_OPTIONS], "${emacs_config_options}",
[Define to the options passed to configure.])
XMENU_OBJ=
XOBJ=
FONT_OBJ=
if test "${HAVE_X_WINDOWS}" = "yes" ; then
- AC_DEFINE(HAVE_X_WINDOWS, 1,
+ AC_DEFINE([HAVE_X_WINDOWS], [1],
[Define to 1 if you want to use the X window system.])
XMENU_OBJ=xmenu.o
XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o"
@@ -5873,20 +6135,20 @@ fi
if test "${HAVE_HARFBUZZ}" = "yes" ; then
FONT_OBJ="$FONT_OBJ hbfont.o"
fi
-AC_SUBST(FONT_OBJ)
-AC_SUBST(XMENU_OBJ)
-AC_SUBST(XOBJ)
-AC_SUBST(FONT_OBJ)
+AC_SUBST([FONT_OBJ])
+AC_SUBST([XMENU_OBJ])
+AC_SUBST([XOBJ])
+AC_SUBST([FONT_OBJ])
WIDGET_OBJ=
MOTIF_LIBW=
if test "${USE_X_TOOLKIT}" != "none" ; then
WIDGET_OBJ=widget.o
- AC_DEFINE(USE_X_TOOLKIT, 1, [Define to 1 if using an X toolkit.])
+ AC_DEFINE([USE_X_TOOLKIT], [1], [Define to 1 if using an X toolkit.])
if test "${USE_X_TOOLKIT}" = "LUCID"; then
- AC_DEFINE(USE_LUCID, 1, [Define to 1 if using the Lucid X toolkit.])
+ AC_DEFINE([USE_LUCID], [1], [Define to 1 if using the Lucid X toolkit.])
elif test "${USE_X_TOOLKIT}" = "MOTIF"; then
- AC_DEFINE(USE_MOTIF, 1, [Define to 1 if using the Motif X toolkit.])
+ AC_DEFINE([USE_MOTIF], [1], [Define to 1 if using the Motif X toolkit.])
MOTIF_LIBW=-lXm
case "$opsys" in
gnu-linux)
@@ -5908,7 +6170,7 @@ if test "${USE_X_TOOLKIT}" != "none" ; then
MOTIF_LIBW="$MOTIF_LIBW $LIBXP"
fi
fi
-AC_SUBST(WIDGET_OBJ)
+AC_SUBST([WIDGET_OBJ])
TOOLKIT_LIBW=
case "$USE_X_TOOLKIT" in
@@ -5919,7 +6181,7 @@ esac
if test "$HAVE_XWIDGETS" = "yes"; then
TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite"
fi
-AC_SUBST(TOOLKIT_LIBW)
+AC_SUBST([TOOLKIT_LIBW])
if test "${opsys}" != "mingw32"; then
if test "$USE_X_TOOLKIT" = "none"; then
@@ -5928,16 +6190,16 @@ if test "${opsys}" != "mingw32"; then
LIBXT_OTHER="\$(LIBXMU) -lXt \$(LIBXTR6) -lXext"
fi
fi
-AC_SUBST(LIBXT_OTHER)
+AC_SUBST([LIBXT_OTHER])
if test "${HAVE_X11}" = "yes" ; then
- AC_DEFINE(HAVE_X11, 1,
+ AC_DEFINE([HAVE_X11], [1],
[Define to 1 if you want to use version 11 of X windows.])
LIBX_OTHER="\$(LIBXT) \$(LIBX_EXTRA)"
else
LIBX_OTHER=
fi
-AC_SUBST(LIBX_OTHER)
+AC_SUBST([LIBX_OTHER])
HAVE_OLDXMENU=no
if test "$HAVE_GTK" = yes || test "$HAVE_X11" != yes; then
@@ -5950,7 +6212,7 @@ else
LIBXMENU='$(lwlibdir)/liblw.a'
AUTODEPEND_PARENTS="$AUTODEPEND_PARENTS lwlib"
fi
-AC_SUBST(LIBXMENU)
+AC_SUBST([LIBXMENU])
AC_CACHE_CHECK([for struct alignment],
[emacs_cv_struct_alignment],
@@ -5963,7 +6225,7 @@ AC_CACHE_CHECK([for struct alignment],
[emacs_cv_struct_alignment=yes],
[emacs_cv_struct_alignment=no])])
if test "$emacs_cv_struct_alignment" = yes; then
- AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], 1,
+ AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], [1],
[Define to 1 if 'struct __attribute__ ((aligned (N)))' aligns the
structure to an N-byte boundary.])
fi
@@ -5977,24 +6239,24 @@ AC_CACHE_CHECK([for statement expressions],
[emacs_cv_statement_expressions=yes],
[emacs_cv_statement_expressions=no])])
if test "$emacs_cv_statement_expressions" = yes; then
- AC_DEFINE([HAVE_STATEMENT_EXPRESSIONS], 1,
+ AC_DEFINE([HAVE_STATEMENT_EXPRESSIONS], [1],
[Define to 1 if statement expressions work.])
fi
if test "${GNU_MALLOC}" = "yes" ; then
- AC_DEFINE(GNU_MALLOC, 1,
+ AC_DEFINE([GNU_MALLOC], [1],
[Define to 1 if you want to use the GNU memory allocator.])
fi
RALLOC_OBJ=
if test "${REL_ALLOC}" = "yes" ; then
- AC_DEFINE(REL_ALLOC, 1,
+ AC_DEFINE([REL_ALLOC], [1],
[Define REL_ALLOC if you want to use the relocating allocator for
buffer space.])
test "$system_malloc" != "yes" && RALLOC_OBJ=ralloc.o
fi
-AC_SUBST(RALLOC_OBJ)
+AC_SUBST([RALLOC_OBJ])
if test "$opsys" = "cygwin"; then
CYGWIN_OBJ="cygw32.o"
@@ -6010,9 +6272,9 @@ else
PRE_ALLOC_OBJ=lastfile.o
POST_ALLOC_OBJ=
fi
-AC_SUBST(CYGWIN_OBJ)
-AC_SUBST(PRE_ALLOC_OBJ)
-AC_SUBST(POST_ALLOC_OBJ)
+AC_SUBST([CYGWIN_OBJ])
+AC_SUBST([PRE_ALLOC_OBJ])
+AC_SUBST([POST_ALLOC_OBJ])
dnl Call this 'FORTIFY_SOUR' so that it sorts before the 'FORTIFY_SOURCE'
dnl verbatim defined above. The tricky name is apropos, as this hack
@@ -6060,7 +6322,7 @@ LIBS=$SAVE_LIBS
# timer_getoverrun needs the same library as timer_settime
OLD_LIBS=$LIBS
LIBS="$LIB_TIMER_TIME $LIBS"
-AC_CHECK_FUNCS(timer_getoverrun)
+AC_CHECK_FUNCS([timer_getoverrun])
LIBS=$OLD_LIBS
if test "${opsys}" = "mingw32"; then
@@ -6080,6 +6342,9 @@ case "$opsys" in
if test "$NS_IMPL_COCOA" = "yes"; then
libs_nsgui="$libs_nsgui -framework IOKit -framework Carbon \
-framework IOSurface -framework QuartzCore"
+ if test "$emacs_cv_macosx_12_0" = "yes"; then
+ libs_nsgui="$libs_nsgui -framework UniformTypeIdentifiers"
+ fi
fi
else
libs_nsgui=
@@ -6171,16 +6436,17 @@ fi
LD_SWITCH_SYSTEM_TEMACS="$LDFLAGS_NOCOMBRELOC $LD_SWITCH_SYSTEM_TEMACS"
-AC_SUBST(LD_SWITCH_SYSTEM_TEMACS)
+AC_SUBST([LD_SWITCH_SYSTEM_TEMACS])
## Common for all window systems
if test "$window_system" != "none"; then
- AC_DEFINE(HAVE_WINDOW_SYSTEM, 1, [Define if you have a window system.])
- AC_DEFINE(POLL_FOR_INPUT, 1, [Define if you poll periodically to detect C-g.])
+ AC_DEFINE([HAVE_WINDOW_SYSTEM], [1], [Define if you have a window system.])
+ AC_DEFINE([POLL_FOR_INPUT], [1],
+ [Define if you poll periodically to detect C-g.])
WINDOW_SYSTEM_OBJ="fontset.o fringe.o image.o"
fi
-AC_SUBST(WINDOW_SYSTEM_OBJ)
+AC_SUBST([WINDOW_SYSTEM_OBJ])
AH_TOP([/* GNU Emacs site configuration template file.
@@ -6297,7 +6563,7 @@ for opt in ACL BE_APP CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTING
AS_VAR_APPEND([emacs_config_features], ["$optsep$opt"])
optsep=' '
done
-AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}",
+AC_DEFINE_UNQUOTED([EMACS_CONFIG_FEATURES], ["${emacs_config_features}"],
[Summary of some of the main features enabled by configure.])
AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D}
@@ -6340,7 +6606,8 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
Does Emacs support legacy unexec dumping? ${with_unexec}
Which dumping strategy does Emacs use? ${with_dumping}
Does Emacs have native lisp compiler? ${HAVE_NATIVE_COMP}
- Does Emacs use version 2 of the the X Input Extension? ${HAVE_XINPUT2}
+ Does Emacs use version 2 of the X Input Extension? ${HAVE_XINPUT2}
+ Does Emacs generate a smaller-size Japanese dictionary? ${with_small_ja_dic}
"])
if test -n "${EMACSDATA}"; then
@@ -6374,7 +6641,7 @@ case $opsys,$emacs_uname_r in
echo
;;
cygwin,3.0.[[0-7]]'('* | cygwin,3.1.[[0-2]]'('*)
- AC_DEFINE([HAVE_CYGWIN_O_PATH_BUG], 1,
+ AC_DEFINE([HAVE_CYGWIN_O_PATH_BUG], [1],
[Define to 1 if opening a FIFO, socket, or symlink with O_PATH is buggy.]);;
esac
@@ -6396,7 +6663,7 @@ if test "$HAVE_NS" = "yes"; then
nextstep/Cocoa/Emacs.base/Contents/Resources/English.lproj/InfoPlist.strings:nextstep/templates/InfoPlist.strings.in])
ns_check_file=Contents/Info.plist
fi
- AC_SUBST(ns_check_file)
+ AC_SUBST([ns_check_file])
fi
AC_CONFIG_FILES([Makefile lib/gnulib.mk])
@@ -6437,7 +6704,10 @@ fi dnl -d admin
SUBDIR_MAKEFILES_IN=`echo " ${SUBDIR_MAKEFILES}" | sed -e 's| | $(srcdir)/|g' -e 's|Makefile|Makefile.in|g'`
-AC_SUBST(SUBDIR_MAKEFILES_IN)
+AC_SUBST([SUBDIR_MAKEFILES_IN])
+
+SMALL_JA_DIC=$with_small_ja_dic
+AC_SUBST([SMALL_JA_DIC])
dnl You might wonder (I did) why epaths.h is generated by running make,
dnl rather than just letting configure generate it from epaths.in.
diff --git a/doc/emacs/ChangeLog.1 b/doc/emacs/ChangeLog.1
index c1c5f5407da..048b7bd99a5 100644
--- a/doc/emacs/ChangeLog.1
+++ b/doc/emacs/ChangeLog.1
@@ -8529,7 +8529,7 @@
* text.texi (Cell Justification):
* trouble.texi (After a Crash):
* xresources.texi (GTK styles):
- Delete duplicate duplicate words.
+ Delete duplicate words.
2005-07-17 Richard M. Stallman <rms@gnu.org>
diff --git a/doc/emacs/abbrevs.texi b/doc/emacs/abbrevs.texi
index 9f339a03577..07f66ec10ac 100644
--- a/doc/emacs/abbrevs.texi
+++ b/doc/emacs/abbrevs.texi
@@ -411,10 +411,13 @@ away in the buffer to search for an expansion.
@vindex dabbrev-check-all-buffers
@vindex dabbrev-check-other-buffers
+@vindex dabbrev-ignored-buffer-modes
After scanning the current buffer, @kbd{M-/} normally searches other
buffers. The variables @code{dabbrev-check-all-buffers} and
@code{dabbrev-check-other-buffers} can be used to determine which
-other buffers, if any, are searched.
+other buffers, if any, are searched. Buffers that have major modes
+derived from any of the modes in @code{dabbrev-ignored-buffer-modes}
+are ignored.
@vindex dabbrev-ignored-buffer-names
@vindex dabbrev-ignored-buffer-regexps
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index bb88fddc04f..b86037f2a63 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -31,10 +31,6 @@ back in time. The @code{ftx} font backend is again part of Emacs, for
the same reasons.
@item
-As Motif becomes more and more important with moving farther into the
-past, we've reinstated the code which supports Motif in Emacs.
-
-@item
Emacs once again supports versions 5.3 and older OpenBSD systems,
which will be needed as you move back in time.
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index 196a28be5a1..1a4abdc9ecd 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -347,11 +347,11 @@ move to the column number specified by the argument's numeric value.
@kindex C-x C-n
@findex set-goal-column
Use the current column of point as the @dfn{semipermanent goal column}
-for @kbd{C-n} and @kbd{C-p} (@code{set-goal-column}) in the current
-buffer. When a semipermanent goal column is in effect, those commands
-always try to move to this column, or as close as possible to it,
-after moving vertically. The goal column remains in effect until
-canceled.
+(@code{set-goal-column}) in the current buffer. When a semipermanent
+goal column is in effect, @kbd{C-n}, @kbd{C-p}, @kbd{<prior>} and
+@kbd{<next>} always try to move to this column, or as close as
+possible to it, after moving vertically. The goal column remains in
+effect until canceled.
@item C-u C-x C-n
Cancel the goal column. Henceforth, @kbd{C-n} and @kbd{C-p} try to
@@ -653,14 +653,14 @@ Toggle automatic display of the current line number or column number.
displayed before each line, see @ref{Display Custom}.
@item M-=
-Display the number of lines, words, and characters that are present in
-the region (@code{count-words-region}). @xref{Mark}, for information
-about the region.
+Display the number of lines, sentences, words, and characters that are
+present in the region (@code{count-words-region}). @xref{Mark}, for
+information about the region.
@item M-x count-words
-Display the number of lines, words, and characters that are present in
-the buffer. If the region is active (@pxref{Mark}), display the
-numbers for the region instead.
+Display the number of lines, sentences, words, and characters that are
+present in the buffer. If the region is active (@pxref{Mark}),
+display the numbers for the region instead.
@item C-x =
Display the character code of character after point, character position of
@@ -689,7 +689,7 @@ narrowed region and the line number relative to the whole buffer.
@kindex M-=
@findex count-words-region
@kbd{M-=} (@code{count-words-region}) displays a message reporting
-the number of lines, words, and characters in the region
+the number of lines, sentences, words, and characters in the region
(@pxref{Mark}, for an explanation of the region). With a prefix
argument, @kbd{C-u M-=}, the command displays a count for the entire
buffer.
diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi
index 8a8584689fc..120c957ff86 100644
--- a/doc/emacs/buffers.texi
+++ b/doc/emacs/buffers.texi
@@ -616,10 +616,11 @@ select it in another window (@code{clone-indirect-buffer-other-window}).
The text of the indirect buffer is always identical to the text of its
base buffer; changes made by editing either one are visible immediately
-in the other. But in all other respects, the indirect buffer and its
+in the other. ``Text'' here includes both the characters and their text
+properties. But in all other respects, the indirect buffer and its
base buffer are completely separate. They can have different names,
different values of point, different narrowing, different markers,
-different major modes, and different local variables.
+different overlays, different major modes, and different local variables.
An indirect buffer cannot visit a file, but its base buffer can. If
you try to save the indirect buffer, that actually works by saving the
@@ -629,7 +630,6 @@ buffer, but killing an indirect buffer has no effect on its base buffer.
One way to use indirect buffers is to display multiple views of an
outline. @xref{Outline Views}.
-@vindex clone-indirect-buffer-hook
A quick and handy way to make an indirect buffer is with the command
@kbd{M-x clone-indirect-buffer}. It creates and selects an indirect
buffer whose base buffer is the current buffer. With a numeric
@@ -637,14 +637,27 @@ argument, it prompts for the name of the indirect buffer; otherwise it
uses the name of the current buffer, with a @samp{<@var{n}>} suffix
added. @kbd{C-x 4 c} (@code{clone-indirect-buffer-other-window})
works like @kbd{M-x clone-indirect-buffer}, but it selects the new
-buffer in another window. These functions run the hook
-@code{clone-indirect-buffer-hook} after creating the indirect buffer.
+buffer in another window.
The more general way to make an indirect buffer is with the command
@kbd{M-x make-indirect-buffer}. It creates an indirect buffer
named @var{indirect-name} from a buffer @var{base-buffer}, prompting for
both using the minibuffer.
+@vindex clone-indirect-buffer-hook
+ The functions that create indirect buffers run the hook
+@code{clone-indirect-buffer-hook} after creating the indirect buffer.
+When this hook runs, the newly created indirect buffer is the current
+buffer.
+
+Note: When a modification is made to the text of a buffer, the
+modification hooks are run only in the base buffer, because most of
+the functions on those hooks are not prepared to work correctly in
+indirect buffers. So if you need a modification hook function in an
+indirect buffer, you need to manually add that function to the hook
+@emph{in the base buffer} and then make the function operate in the
+desired indirect buffer.
+
@node Buffer Convenience
@section Convenience Features and Customization of Buffer Handling
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index 5b68b1ef9fa..b79fa0a755c 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -138,6 +138,14 @@ of environment variable settings; each element should be a string of
the form @code{"@var{envvarname}=@var{value}"}. These environment
variable settings override the usual ones.
+@vindex compilation-max-output-line-length
+ Displaying extremely long lines in compilation output can slow Emacs
+down. Lines that are longer than
+@code{compilation-max-output-line-length} will have the portion that's
+exceeds that limit hidden behind a button that can be clicked on to
+reveal the hidden portion. Set this variable to @code{nil} to never
+hide anything.
+
@node Compilation Mode
@section Compilation Mode
@@ -170,7 +178,9 @@ list of customization variables and faces.
If you change the variable
@code{compilation-auto-jump-to-first-error} to a non-@code{nil} value,
Emacs automatically visits the locus of the first error message that
-appears in the @file{*compilation*} buffer.
+appears in the @file{*compilation*} buffer. (This variable can also
+have the values @code{if-location-known} and @code{first-known}, which
+modify the conditions for automatically visiting the error locus.)
Compilation mode provides the following additional commands. These
commands can also be used in @file{*grep*} buffers, where the
@@ -279,6 +289,19 @@ window so that the current error message is @var{n} lines from the
top, whether or not there is a fringe; the default value, @code{nil},
gives the behavior described above.
+@vindex compilation-hidden-output
+ Compilation output can sometimes be very verbose, and much of it isn't
+of particular interest to a user. The
+@code{compilation-hidden-output} user option should either be a regexp
+or a list of regexps, and output that matches will be made invisible.
+For instance, to hide the verbose output from recursive makefiles, you
+can say something like:
+
+@lisp
+(setq compilation-hidden-output
+ '("^make[^\n]+\n"))
+@end lisp
+
@vindex compilation-error-regexp-alist
@vindex grep-regexp-alist
To parse messages from the compiler, Compilation mode uses the
@@ -1734,6 +1757,10 @@ which is provided for evaluating Emacs Lisp expressions interactively.
Its major mode is Lisp Interaction mode. You can also enable Lisp
Interaction mode by typing @kbd{M-x lisp-interaction-mode}.
+@findex scratch-buffer
+ If you kill the @file{*scratch*} buffer, you can recreate it with
+the @kbd{M-x scratch-buffer} command.
+
@findex eval-print-last-sexp
@kindex C-j @r{(Lisp Interaction mode)}
In the @file{*scratch*} buffer, and other Lisp Interaction mode
diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index 5c444fc6488..0f7acd87978 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -294,6 +294,22 @@ which will invoke Emacs with @samp{--script} and supply the name of
the script file as @var{file}. Emacs Lisp then treats the @samp{#!}
on this first line as a comment delimiter.
+@item -x
+@opindex -x
+This option can only be used in executable script files, and should be
+invoked like this:
+
+@example
+#!/usr/bin/emacs -x
+@end example
+
+This is like @samp{--script}, but suppresses loading the init files
+(like @code{--quick}), and can't be used on a normal command line
+(since it doesn't specify the script to load). In addition, when it
+reaches the end of the script, it exits Emacs and uses the value of
+the final form as the exit value from the script (if the final value
+is numerical). Otherwise, it will always exit with a zero value.
+
@item --no-build-details
@opindex --no-build-details
@cindex build details
@@ -329,6 +345,10 @@ option does this too, but other options like @samp{-q} do not.
Do not include the @file{site-lisp} directories in @code{load-path}
(@pxref{Init File}). The @samp{-Q} option does this too.
+@item --init-directory
+@opindex --init-directory
+Specify the directory to use when looking for the Emacs init files.
+
@item --no-splash
@opindex --no-splash
@cindex splash screen
@@ -780,29 +800,45 @@ changing any environment or registry settings.
@pindex addpm, MS-Windows installation program
@cindex registry, setting environment variables (MS-Windows)
-On MS-Windows, the installation program @command{addpm.exe} adds
-values for @env{emacs_dir}, @env{EMACSLOADPATH}, @env{EMACSDATA},
-@env{EMACSPATH}, @env{EMACSDOC}, @env{SHELL} and @env{TERM} to the
-@file{HKEY_LOCAL_MACHINE} section of the system registry, under
-@file{/Software/GNU/Emacs}. It does this because there is no standard
-place to set environment variables across different versions of
-Windows. Running @command{addpm.exe} is no longer strictly necessary
-in recent versions of Emacs, but if you are upgrading from an older
-version, running @command{addpm.exe} ensures that you do not have
-older registry entries from a previous installation, which may not be
-compatible with the latest version of Emacs.
-
-When Emacs starts, as well as checking the environment, it also checks
-the System Registry for those variables and for @env{HOME}, @env{LANG}
-and @env{PRELOAD_WINSOCK}.
+On MS-Windows, the environment variables @env{emacs_dir},
+@env{EMACSLOADPATH}, @env{EMACSDATA}, @env{EMACSPATH}, @env{EMACSDOC},
+@env{SHELL}, @env{TERM}, @env{HOME}, @env{LANG}, and
+@env{PRELOAD_WINSOCK} can also be set in the @file{HKEY_CURRENT_USER}
+or the @file{HKEY_LOCAL_MACHINE} section of the system registry, under
+the @file{/Software/GNU/Emacs} key. When Emacs starts, as well as
+checking the environment, it also checks the system registry for those
+variables.
To determine the value of those variables, Emacs goes through the
-following procedure. First, the environment is checked. If the
-variable is not found there, Emacs looks for registry keys by that
-name under @file{/Software/GNU/Emacs}; first in the
+following procedure. First, it checks the environment. If the
+variable is not found there, Emacs looks for a registry key by the
+name of the variable under @file{/Software/GNU/Emacs}; first in the
@file{HKEY_CURRENT_USER} section of the registry, and if not found
there, in the @file{HKEY_LOCAL_MACHINE} section. Finally, if Emacs
-still cannot determine the values, compiled-in defaults are used.
+still cannot determine the values, it uses the compiled-in defaults.
+
+Note that the registry settings have global system-wide effect: they
+will affect all Emacs sessions run on the system. Thus, if you run
+different Emacs versions, or use both installed and un-installed Emacs
+executables, or build newer versions of Emacs, the settings in the
+registry will cause all of them to use the same directories, which is
+probably not what you want. For this reason, @emph{we recommend
+against setting these variables in the registry}. If you have such
+settings in the registry, we recommend that you remove them.
+
+If you run the Emacs MS-Windows installation program
+@command{addpm.exe}, it will update any existing registry settings of
+the @env{emacs_dir}, @env{EMACSLOADPATH}, @env{EMACSDATA},
+@env{EMACSPATH}, @env{EMACSDOC}, @env{SHELL}, and @env{TERM} variables
+to have the values suitable for the installed Emacs version with which
+@command{addpm.exe} came. Note that @command{addpm.exe} will
+@emph{not} create any registry setting that didn't exist, it will only
+update existing settings, which are most probably inherited from an
+old Emacs installation, so that they are compatible with the newly
+installed Emacs version. Running @command{addpm.exe} is no longer
+necessary when installing recent versions of Emacs, so we only
+recommend doing that if you are upgrading from an older version, and
+cannot remove these settings from the registry for some reason.
In addition to the environment variables above, you can also add
settings to the @file{/Software/GNU/Emacs} registry key to specify X
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index b2dd5eb6980..46a2291b74d 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -844,6 +844,21 @@ otherwise stated, affects only the current Emacs session. The only
way to alter the variable in future sessions is to put something in
your initialization file (@pxref{Init File}).
+ If you're setting a customizable variable in your initialization
+file, and you don't want to use the Customize interface, you can use
+the @code{setopt} macro. For instance:
+
+@findex setopt
+@example
+(setopt fill-column 75)
+@end example
+
+This works the same as @code{setq}, but if the variable has any
+special setter functions, they will be run automatically when using
+@code{setopt}. You can also use @code{setopt} on other,
+non-customizable variables, but this is less efficient than using
+@code{setq}.
+
@node Hooks
@subsection Hooks
@cindex hook
@@ -1217,6 +1232,28 @@ Manual}.
These four keywords are not really variables; setting them in any
other context has no special meaning.
+ If you're editing a file across Emacs versions, and a new mode has
+been introduced to handle a file in a newer Emacs version, you can use
+several @code{mode} entries to use the new mode (called
+@code{my-new-mode}) in the new Emacs, and fall back to the old mode
+(called @code{my-old-mode}) in older Emacs versions. If you're
+enabling the modes in the first line of the file, can say:
+
+@example
+-*- mode: my-old; mode: my-new -*-
+@end example
+
+ Emacs will use the final defined mode it finds, so in older Emacs
+versions it will ignore @code{my-new-mode}, while in Emacs versions
+where @code{my-new-mode} is defined, it'll ignore @code{my-old-mode}.
+Similarly, in a local variable block at the end of the file:
+
+@example
+Local variables:
+mode: my-old
+mode: my-new
+@end example
+
Do not use the @code{mode} keyword for minor modes. To enable or
disable a minor mode in a local variables list, use the @code{eval}
keyword with a Lisp expression that runs the mode command
@@ -2219,6 +2256,22 @@ is included in the message displayed when the command is used:
"It's better to use `kill-region' instead.\n")
@end example
+@findex command-query
+ As a less heavy-handed alternative to disabling commands, you may
+want to be queried before executing a command. For instance, to be
+queried before executing the @kbd{M->} (@code{end-of-buffer})
+command, you could put something like the following in your init file:
+
+@example
+(command-query
+ 'end-of-buffer
+ "Do you really want to go to the end of the buffer?")
+@end example
+
+By default, you'll be queried with a @kbd{y}/@kbd{n} question, but if
+you give a non-@code{nil} value to the third, optional argument,
+you'll be queried with @kbd{yes}/@kbd{no} instead.
+
@findex disable-command
@findex enable-command
You can make a command disabled either by editing the initialization
@@ -2338,8 +2391,8 @@ mode when you set them with Customize, but ordinary @code{setq} won't
do that; to enable the mode in your init file, call the minor mode
command. Finally, a few customizable user options are initialized in
complex ways, and these have to be set either via the customize
-interface (@pxref{Customization}) or by using
-@code{customize-set-variable} (@pxref{Examining}).
+interface (@pxref{Customization}), or by using
+@code{customize-set-variable}/@code{setopt} (@pxref{Examining}).
The second argument to @code{setq} is an expression for the new
value of the variable. This can be a constant, a variable, or a
@@ -2492,7 +2545,7 @@ Change the coding system used when using the clipboard
(@pxref{Communication Coding}).
@example
-(customize-set-variable 'selection-coding-system 'utf-8)
+(setopt selection-coding-system 'utf-8)
@end example
@item
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 700b3f21911..292c986c1c6 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -113,11 +113,17 @@ a directory's name.
@findex dired-jump-other-window
@kindex C-x C-j
@kindex C-x 4 C-j
- Typing @kbd{C-x C-j} (@code{dired-jump}) in any buffer will open a
-Dired buffer and move point to the line corresponding to the current
-file. In Dired, move up a level and go to the previous directory's
-line. Typing @kbd{C-x 4 C-j} (@code{dired-jump-other-window} has the
-same effect but opens a new window for the Dired buffer.
+ You can ask Emacs to invoke Dired on the default-directory
+(@pxref{File Names, default-directory}) of any buffer, by typing
+@kbd{C-x C-j} (@code{dired-jump}). If the buffer visits a file, this
+command will move point to that file's line in the Dired buffer it
+shows; otherwise, point will end up on the first file in the directory
+listing. As an exception, if you type @kbd{C-x C-j} in a Dired
+buffer, Emacs displays the directory listing of the parent directory
+and places point on the line that corresponds to the directory where
+you invoked @code{dired-jump}. Typing @kbd{C-x 4 C-j}
+(@code{dired-jump-other-window}) has the same effect, but displays the
+Dired buffer in a new window.
The variable @code{dired-listing-switches} specifies the options to
give to @command{ls} for listing the directory; this string
@@ -770,6 +776,11 @@ symbolic links as links or after dereferencing (like @samp{cp -L}).
The default is @code{nil}, which means that the symbolic links are
copied by creating new ones.
+@vindex dired-keep-marker-copy
+The @code{dired-keep-marker-copy} user option controls how this
+command handles file marking. The default is to mark all new copies
+of files with a @samp{C} mark.
+
@item D
@findex dired-do-delete
@kindex D @r{(Dired)}
@@ -833,6 +844,26 @@ This is like @samp{ln -s}. The argument @var{new} is the directory to
make the links in, or (if making just one link) the name to give the
link.
+@findex dired-do-relsymlink
+@kindex Y @r{(Dired)}
+@item Y @var{new} @key{RET}
+Make relative symbolic links to the specified files
+(@code{dired-do-relsymlink}). The argument @var{new} is the directory
+to make the links in, or (if making just one link) the name to give
+the link. This is like @code{dired-do-symlink} but creates relative
+symbolic links. For example:
+
+@example
+ foo -> ../bar/foo
+@end example
+
+@noindent
+It does not create absolute ones like:
+
+@example
+ foo -> /path/that/may/change/any/day/bar/foo
+@end example
+
@findex dired-do-chmod
@kindex M @r{(Dired)}
@cindex changing file permissions (in Dired)
@@ -952,6 +983,18 @@ Byte compile the specified Emacs Lisp files
(@code{dired-do-byte-compile}). @xref{Byte Compilation,, Byte
Compilation, elisp, The Emacs Lisp Reference Manual}.
+@findex dired-do-info
+@kindex I @r{(Dired)}
+@cindex running info on files (in Dired)
+@item I
+Run Info on this file (assumed to be a file in Info format).
+
+@findex dired-do-man
+@kindex N @r{(Dired)}
+@cindex running man on files (in Dired)
+@item N
+Run man on this file (assumed to be a file in @code{nroff} format).
+
@kindex A @r{(Dired)}
@findex dired-do-find-regexp
@cindex search multiple files (in Dired)
@@ -1001,6 +1044,7 @@ subdirectories whose names match @code{grep-find-ignored-directories}.
@findex dired-do-shell-command
@kindex ! @r{(Dired)}
@kindex X @r{(Dired)}
+@vindex dired-confirm-shell-command
The Dired command @kbd{!} (@code{dired-do-shell-command}) reads a
shell command string in the minibuffer, and runs that shell command on
one or more files. The files that the shell command operates on are
@@ -1037,7 +1081,8 @@ list of file names, putting them into one tar file @file{foo.tar}.
If you want to use @samp{*} as a shell wildcard with whitespace around
it, write @samp{*""}. In the shell, this is equivalent to @samp{*};
but since the @samp{*} is not surrounded by whitespace, Dired does not
-treat it specially.
+treat it specially. Emacs will prompt for confirmation if you do
+this, unless @code{dired-confirm-shell-command} is @code{nil}.
@item
Otherwise, if the command string contains @samp{?} surrounded by
@@ -1125,9 +1170,12 @@ Rename each of the selected files to a lower-case name
@itemx % S @var{from} @key{RET} @var{to} @key{RET}
@kindex % S @r{(Dired)}
@findex dired-do-symlink-regexp
-These four commands rename, copy, make hard links and make soft links,
-in each case computing the new name by regular-expression substitution
-from the name of the old file.
+@itemx % Y @var{from} @key{RET} @var{to} @key{RET}
+@kindex % Y @r{(Dired)}
+@findex dired-do-relsymlink-regexp
+These five commands rename, copy, make hard links, make soft links,
+and make relative soft links, in each case computing the new name by
+regular-expression substitution from the name of the old file.
@end table
The four regular-expression substitution commands effectively
@@ -1285,6 +1333,12 @@ parent directory.
@kindex > @r{(Dired)}
@item >
Move down to the next directory-file line (@code{dired-next-dirline}).
+
+@findex dired-goto-subdir
+@kindex M-G @r{(Dired)}
+@item M-G
+Prompt for a directory and move to its directory-file line
+(@code{dired-goto-subdir}).
@end table
@node Hiding Subdirectories
@@ -1689,9 +1743,18 @@ directory than in this one. It also marks files with no counterpart,
in both directories, as always.
@cindex drag and drop, Dired
- On the X Window System, Emacs supports the drag and drop
-protocol. You can drag a file object from another program, and drop
-it onto a Dired buffer; this either moves, copies, or creates a link
-to the file in that directory. Precisely which action is taken is
-determined by the originating program. Dragging files out of a Dired
-buffer is currently not supported.
+@vindex dired-mouse-drag-files
+ On the X Window System, Emacs supports the drag and drop protocol.
+You can drag a file object from another program, and drop it onto a
+Dired buffer; this either moves, copies, or creates a link to the file
+in that directory. Precisely which action is taken is determined by
+the originating program. Dragging files out of a Dired buffer is also
+supported, by enabling the user option @code{dired-mouse-drag-files},
+the mouse can be used to drag files onto other programs. When set to
+@code{link}, it will make the other program (typically a file manager)
+create a symbolic link to the file; when set to @code{move}, it will
+make the other program move the file to a new location, and setting it
+to any other non-@code{nil} value will make the other program open or
+create a copy of the file. The keyboard modifiers pressed during the
+drag-and-drop operation can also control what action the other program
+takes towards the file.
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 4fcd2a3f7de..cadac7e4538 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -854,7 +854,8 @@ would be selected if you click a mouse or press @key{RET}.
@node Text Scale
@section Text Scale
-@cindex adjust buffer face height
+@cindex adjust buffer font size
+@cindex font size of @code{default} face, increase or decrease
@findex text-scale-adjust
@kindex C-x C-+
@kindex C-x C--
@@ -862,17 +863,27 @@ would be selected if you click a mouse or press @key{RET}.
@kindex C-x C-0
@kindex C-wheel-down
@kindex C-wheel-up
- To increase the height of the default face in the current buffer,
-type @kbd{C-x C-+} or @kbd{C-x C-=}. To decrease it, type @kbd{C-x
-C--}. To restore the default (global) face height, type @kbd{C-x
-C-0}. These keys are all bound to the same command,
+ To increase the font size of the @code{default} face in the current
+buffer, type @kbd{C-x C-+} or @kbd{C-x C-=}. To decrease it, type
+@kbd{C-x C--}. To restore the default (global) font size, type
+@kbd{C-x C-0}. These keys are all bound to the same command,
@code{text-scale-adjust}, which looks at the last key typed to
-determine which action to take.
+determine which action to take and adjusts the font size accordingly
+by changing the height of the default face.
+
+ Most faces don't have an explicit setting of the @code{:height}
+attribute, and thus inherit the height from the @code{default} face.
+Those faces are also scaled by the above commands.
+
+ Faces other than @code{default} that have an explicit setting of the
+@code{:height} attribute are not affected by these font size changes.
+The @code{header-line} face is an exception: it will be scaled even if
+it has an explicit setting of the @code{:height} attribute.
Similarly, scrolling the mouse wheel with the @kbd{Ctrl} modifier
pressed, when the mouse pointer is above buffer text, will increase or
-decrease the height of the default face, depending on the direction of
-the scrolling.
+decrease the font size of the affected faces, depending on the
+direction of the scrolling.
The final key of these commands may be repeated without the leading
@kbd{C-x}. For instance, @kbd{C-x C-= C-= C-=} increases the face
@@ -882,21 +893,37 @@ of 1.2; to change this factor, customize the variable
to the @code{text-scale-adjust} command restores the default height,
the same as typing @kbd{C-x C-0}.
-@cindex increase buffer face height
+@cindex ajust global font size
+@findex global-text-scale-adjust
+@vindex global-text-scale-adjust-resizes-frames
+@kindex C-x C-M-+
+@kindex C-x C-M-=
+@kindex C-x C-M--
+@kindex C-x C-M-0
+@kindex C-M-wheel-down
+@kindex C-M-wheel-up
+ Similarly, to change the sizes of the fonts globally, type @kbd{C-x
+C-M-+}, @kbd{C-x C-M-=}, @kbd{C-x C-M--} or @kbd{C-x C-M-0}, or scroll
+the mouse wheel with both the @kbd{Ctrl} and @kbd{Meta} modifiers
+pressed. To enable frame resizing when the font size is changed
+globally, customize the variable
+@code{global-text-scale-adjust-resizes-frames} (@pxref{Easy
+Customization}).
+
+@cindex increase buffer font size
@findex text-scale-increase
-@cindex decrease buffer face height
+@cindex decrease buffer font size
@findex text-scale-decrease
The commands @code{text-scale-increase} and
-@code{text-scale-decrease} increase or decrease the height of the
-default face, just like @kbd{C-x C-+} and @kbd{C-x C--} respectively.
-You may find it convenient to bind to these commands, rather than
-@code{text-scale-adjust}.
+@code{text-scale-decrease} increase or decrease the size of the font
+in the current buffer, just like @kbd{C-x C-+} and @kbd{C-x C--}
+respectively. You may find it convenient to bind to these commands,
+rather than @code{text-scale-adjust}.
-@cindex set buffer face height
+@cindex set buffer font size
@findex text-scale-set
- The command @code{text-scale-set} scales the height of the default
-face in the current buffer to an absolute level specified by its
-prefix argument.
+ The command @code{text-scale-set} scales the size of the font in the
+current buffer to an absolute level specified by its prefix argument.
@findex text-scale-mode
The above commands automatically enable the minor mode
@@ -1011,10 +1038,15 @@ in C comments, use this:
@end example
@findex font-lock-remove-keywords
+@vindex font-lock-ignore
@noindent
To remove keywords from the font-lock highlighting patterns, use the
function @code{font-lock-remove-keywords}. @xref{Search-based
Fontification,,, elisp, The Emacs Lisp Reference Manual}.
+Alternatively, you can selectively disable highlighting due to some
+keywords by customizing the @code{font-lock-ignore} option,
+@pxref{Customizing Keywords,,, elisp, The Emacs Lisp Reference
+Manual}.
@cindex just-in-time (JIT) font-lock
@cindex background syntax highlighting
@@ -1589,7 +1621,9 @@ charge on the mode-line, by using the command
@code{battery-mode-line-format} determines the way the battery charge
is displayed; the exact mode-line message depends on the operating
system, and it usually shows the current battery charge as a
-percentage of the total charge.
+percentage of the total charge. The functions in
+@code{battery-update-functions} are run after updating the mode line,
+and can be used to trigger actions based on the battery status.
@cindex mode line, 3D appearance
@cindex attributes of mode line, changing
@@ -1894,12 +1928,22 @@ logical lines, so having a fringe indicator for each wrapped line
would be visually distracting. You can change this by customizing the
variable @code{visual-line-fringe-indicators}.
+@vindex word-wrap-whitespace-mode
+ By default, Emacs only breaks lines after whitespace characters like
+@key{SPC} and @key{TAB}, but does not break after whitespace
+characters like @key{EN QUAD}. Emacs provides a minor mode called
+@code{word-wrap-whitespace-mode} that switches on word wrapping in the
+current mode, and sets up which characters to wrap lines on based on
+the @code{word-wrap-whitespace-characters} user option. There's also
+a globalized version of that mode called
+@code{global-word-wrap-whitespace-mode}.
+
@vindex word-wrap-by-category
@findex modify-category-entry
@findex char-category-set
@findex category-set-mnemonics
- By default, Emacs only breaks lines after whitespace characters.
-That produces incorrect results when CJK and Latin text are mixed
+ Only breaking after whitespace character produces incorrect
+results when CJK and Latin text are mixed
together (because CJK characters don't use whitespace to separate
words). You can customize the option @code{word-wrap-by-category} to
allow Emacs to break lines after any character with @samp{|} category
@@ -1965,7 +2009,7 @@ The command @kbd{M-x display-line-numbers-mode} provides a
convenient way to turn on display of line numbers. This mode has a globalized
variant, @code{global-display-line-numbers-mode}. The user option
@code{display-line-numbers-type} controls which sub-mode of
-line-number display, described above, will these modes activate.
+line-number display, described above, these modes will activate.
@noindent
Note that line numbers are not displayed in the minibuffer and in the
@@ -2082,3 +2126,14 @@ argument to suppress the effect of bold-face in this case.
byte with a decimal value of 128 is displayed as @code{\200}. To
change display to the hexadecimal format of @code{\x80}, set the
variable @code{display-raw-bytes-as-hex} to @code{t}.
+Care may be needed when interpreting a raw byte when copying
+text from a terminal containing an Emacs session, or when a terminal's
+@code{escape-glyph} face looks like the default face. For example, by
+default Emacs displays the four characters @samp{\}, @samp{2},
+@samp{0}, @samp{0} with the same characters it displays a byte with
+decimal value 128. The problem can be worse with hex displays, where
+the raw byte 128 followed by the character @samp{7} is displayed as
+@code{\x807}, which Emacs Lisp reads as the single character U+0807
+SAMARITAN LETTER IT; this confusion does not occur with the
+corresponding octal display @code{\2007} because octal escapes contain
+at most three digits.
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index ad0fa5f0cd0..5e72699bbe8 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -1183,7 +1183,6 @@ The Emacs Initialization File
Dealing with Emacs Trouble
-* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
* Stuck Recursive:: '[...]' in mode line around the parentheses.
* Screen Garbled:: Garbage on the screen.
* Text Garbled:: Garbage in the text.
@@ -1192,6 +1191,7 @@ Dealing with Emacs Trouble
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
* Long Lines:: Mitigating slowness due to extremely long lines.
+* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
Reporting Bugs
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 84eb7275da7..7b4e31e5f84 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -326,6 +326,48 @@ of @code{require-final-newline} (@pxref{Customize Save}). If you have
already visited the same file in the usual (non-literal) manner, this
command asks you whether to visit it literally instead.
+@findex find-sibling-file
+@vindex find-sibling-rules
+Files are sometimes (loosely) tied to other files, and you could call
+these files @dfn{sibling files}. For instance, when editing C files,
+if you have a file called @samp{"foo.c"}, you often also have a file
+called @samp{"foo.h"}, and that could be its sibling file. Or you may
+have different versions of a file, for instance
+@samp{"src/emacs/emacs-27/lisp/allout.el"} and
+@samp{"src/emacs/emacs-28/lisp/allout.el"} might be considered
+siblings. Emacs provides the @code{find-sibling-file} command to jump
+between sibling files, but it's impossible to guess at which files a
+user might want to be considered siblings, so Emacs lets you configure
+this freely by altering the @code{find-sibling-rules} user option.
+This is a list of match/expansion elements.
+
+For instance, to do the @samp{".c"} to @samp{".h"} mapping, you could
+say:
+
+@lisp
+(setq find-sibling-rules
+ '(("\\([^/]+\\)\\.c\\'" "\\1.h")))
+@end lisp
+
+(@code{ff-find-related-file} offers similar functionality especially
+geared towards C files, @pxref{Other C Commands}.)
+
+Or, if you want to consider all files under
+@samp{"src/emacs/DIR/file-name"} to be siblings of other @var{dir}s,
+you could say:
+
+@lisp
+(setq find-sibling-rules
+ '(("src/emacs/[^/]+/\\(.*\\)\\'" "src/emacs/.*/\\1")))
+@end lisp
+
+As you can see, this is a list of @var{(MATCH EXPANSION...)} elements.
+The @var{match} is a regular expression that matches the visited file
+name, and each @var{expansion} may refer to match groups by using
+@samp{\\1} and so on. The resulting expansion string is then applied
+to the file system to see if any files match this expansion
+(interpreted as a regexp).
+
@vindex find-file-hook
@vindex find-file-not-found-functions
Two special hook variables allow extensions to modify the operation
@@ -378,6 +420,9 @@ With prefix argument (@kbd{C-u}), mark the current buffer as changed.
Save the current buffer with a specified file name (@code{write-file}).
@item M-x set-visited-file-name
Change the file name under which the current buffer will be saved.
+@item M-x rename-visited-file
+The same as @kbd{M-x set-visited-file-name}, but also rename the file
+the buffer is visiting (if any).
@end table
@kindex C-x C-s
@@ -610,10 +655,10 @@ Never make numbered backups; always make single backups.
The usual way to set this variable is globally, through your init file
or the customization buffer. However, you can set
@code{version-control} locally in an individual buffer to control the
-making of backups for that buffer's file (@pxref{Locals}). You can
-have Emacs set @code{version-control} locally whenever you visit a
-given file (@pxref{File Variables}). Some modes, such as Rmail mode,
-set this variable.
+making of backups for that buffer's file (@pxref{Locals}). Some
+modes, such as Rmail mode, set this variable. You can also have Emacs
+set @code{version-control} locally whenever you visit a given file
+(@pxref{File Variables}).
@cindex @env{VERSION_CONTROL} environment variable
If you set the environment variable @env{VERSION_CONTROL}, to tell
@@ -1467,8 +1512,8 @@ specified buffers.
The command @kbd{M-x compare-windows} compares the text in the
current window with that in the window that was the selected window
before you selected the current one. (For more information about
-windows in Emacs, @ref{Windows}.) Comparison starts at point in each
-window, after pushing each initial point value on the mark ring
+windows in Emacs, @pxref{Windows}.) Comparison starts at point in
+each window, after pushing each initial point value on the mark ring
(@pxref{Mark Ring}) in its respective buffer. Then it moves point
forward in each window, one character at a time, until it reaches
characters that don't match. Then the command exits.
@@ -1828,6 +1873,22 @@ argument to @kbd{M-x delete-file} or @kbd{M-x delete-directory} makes
them delete outright, instead of using the Trash, regardless of
@code{delete-by-moving-to-trash}.
+ If you have @code{delete-by-moving-to-trash} set, and you want to
+delete files manually in Emacs from the Trash directory, using
+commands like @kbd{D} (@code{dired-do-delete}) doesn't work well in
+the Trash directory (it'll just give the file a new name, but won't
+delete anything). If you want to be able to do this, you should
+create a @code{.dir-locals.el} file containing something like the
+following in the Trash directory:
+
+@example
+((dired-mode . ((delete-by-moving-to-trash . nil))))
+@end example
+
+ Note, however, if you use the system ``empty trash'' command, it's
+liable to also delete this @code{.dir-locals.el} file, so this should
+only be done if you delete files from the Trash directory manually.
+
@ifnottex
If a file is under version control (@pxref{Version Control}), you
should delete it using @kbd{M-x vc-delete-file} instead of @kbd{M-x
@@ -2164,13 +2225,16 @@ recently-opened files, reading file names from a buffer.
@findex recentf-mode
@vindex recentf-mode
+@findex recentf-open
@findex recentf-save-list
@findex recentf-edit-list
- If you enable Recentf mode, with @kbd{M-x recentf-mode}, the
-@samp{File} menu includes a submenu containing a list of recently
-opened files. @kbd{M-x recentf-save-list} saves the current
-@code{recentf-list} to a file, and @kbd{M-x recentf-edit-list} edits
-it.
+ If you enable Recentf mode, with @kbd{M-x recentf-mode}, Emacs
+maintains a list of recently opened files. To open a file from this
+list, use the @kbd{M-x recentf-open} command. When this mode is
+enabled, the @samp{File} menu will include a submenu that you can use
+to visit one of these files. @kbd{M-x recentf-save-list} saves the
+current @code{recentf-list} to a file, and @kbd{M-x recentf-edit-list}
+edits it.
@c FIXME partial-completion-mode (complete.el) is obsolete.
The @kbd{M-x ffap} command generalizes @code{find-file} with more
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index ce43408101d..d78cbffaa71 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -128,6 +128,12 @@ In addition, the text in the region becomes the primary selection
non-@code{nil} value, dragging the mouse over a stretch of text also
adds the text to the kill ring. The default is @code{nil}.
+ If this variable is @code{non-empty}, only copy to the kill ring if
+the region is non-empty. For instance, if you mouse drag an area that
+is less than a half a character, you'd normally get the empty string
+in your kill ring, but with @code{non-empty}, this short mouse drag
+won't affect the kill ring.
+
@vindex mouse-scroll-min-lines
If you move the mouse off the top or bottom of the window while
dragging, the window scrolls at a steady rate until you move the mouse
@@ -136,6 +142,12 @@ entirely on the screen. The number of lines scrolled per step depends
on how far away from the window edge the mouse has gone; the variable
@code{mouse-scroll-min-lines} specifies a minimum step size.
+@vindex mouse-drag-mode-line-buffer
+ If you enable the option @code{mouse-drag-mode-line-buffer} and
+dragging files is supported by the window system, then dragging the
+mouse on the buffer name portion of the mode line will drag that
+buffer's file to another program or frame.
+
@findex mouse-yank-primary
@findex mouse-yank-at-click
Clicking with the middle mouse button, @kbd{mouse-2}, moves point to
@@ -211,8 +223,8 @@ mouse-wheel-mode}. The variables @code{mouse-wheel-follow-mouse} and
buffers are scrolled. The variable
@code{mouse-wheel-progressive-speed} determines whether the scroll
speed is linked to how fast you move the wheel. This mode also
-supports increasing or decreasing the height of the default face, by
-default bound to scrolling with the @key{Ctrl} modifier.
+supports increasing or decreasing the font size, by default bound to
+scrolling with the @key{Ctrl} modifier.
@vindex mouse-wheel-scroll-amount-horizontal
Emacs also supports horizontal scrolling with the @key{Shift}
@@ -512,6 +524,16 @@ frames by specifying @dfn{frame parameters}. @xref{Frame Parameters}.
Delete the selected frame (@code{delete-frame}). This signals an
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.
+
@item C-z
@kindex C-z @r{(X windows)}
Minimize (or iconify) the selected Emacs frame
@@ -939,6 +961,7 @@ Speedbar,,speedbar, Speedbar Manual}.
@node Multiple Displays
@section Multiple Displays
@cindex multiple displays
+@cindex display server
A single Emacs can talk to more than one X display. Initially, Emacs
uses just one display---the one specified with the @env{DISPLAY}
@@ -1185,6 +1208,18 @@ the variable @code{dnd-open-file-other-window}.
The XDND and Motif drag and drop protocols, and the old KDE 1.x
protocol, are currently supported.
+@vindex dnd-indicate-insertion-point
+@vindex dnd-scroll-margin
+
+ It can be difficult to scroll a window or determine where dropped
+text will be inserted while dragging text onto an Emacs window.
+Setting the option @code{dnd-indicate-insertion-point} to a
+non-@code{nil} value makes point move to the location any dropped text
+will be inserted when the mouse moves in a window during drag, and
+setting @code{dnd-scroll-margin} to an integer value causes a window
+to be scrolled if the mouse moves within that many lines of the top
+or bottom of the window during drag.
+
@vindex mouse-drag-and-drop-region
Emacs can also optionally drag the region with the mouse into
another portion of this or another buffer. To enable that, customize
@@ -1209,6 +1244,17 @@ cursor during dragging. To suppress such behavior, set the options
@code{mouse-drag-and-drop-region-show-tooltip} and/or
@code{mouse-drag-and-drop-region-show-cursor} to @code{nil}.
+@vindex mouse-drag-and-drop-region-cross-program
+To drag text from Emacs to other programs, set the option
+@code{mouse-drag-and-drop-region-cross-program} to a non-@code{nil}
+value.
+
+ On the X window system, some programs can drop files on Emacs,
+expecting Emacs to save them. Normally, Emacs will prompt for a file
+name under which the file will be saved, and then open the file, but
+that behavior can be changed by changing the variable
+@code{x-dnd-direct-save-function}. @xref{Drag and Drop,,, elisp, The
+Emacs Lisp Reference Manual}.
@node Menu Bars
@section Menu Bars
@@ -1623,13 +1669,18 @@ Parameters,,, elisp, The Emacs Lisp Reference Manual}, and also
For additional customization options for displaying tooltips, use
@kbd{M-x customize-group @key{RET} tooltip @key{RET}}.
-@vindex x-gtk-use-system-tooltips
- If Emacs is built with GTK+ support, it displays tooltips via GTK+,
-using the default appearance of GTK+ tooltips. To disable this,
-change the variable @code{x-gtk-use-system-tooltips} to @code{nil}.
-If you do this, or if Emacs is built without GTK+ support, most
-attributes of the tooltip text are specified by the @code{tooltip}
-face, and by X resources (@pxref{X Resources}).
+@vindex use-system-tooltips
+ If Emacs is built with the GTK+ toolkit, Nextstep windowing, or
+Haiku windowing support, it displays tooltips via the toolkit, using
+the default appearance of the toolkit's tooltips.@footnote{The
+foreground and background colors of toolkit-created tooltips on
+Nextstep can also be customized by setting the @code{foreground} and
+@code{background} frame parameters that are part of
+@code{tooltip-frame-parameters}.} To disable this, change the variable
+@code{use-system-tooltips} to @code{nil}. If you do this, or if Emacs
+is built without the appropriate windowing support, most attributes of
+the tooltip text are specified by the @code{tooltip} face, and by X
+resources (@pxref{X Resources}).
@dfn{GUD tooltips} are special tooltips that show the values of
variables when debugging a program with GUD@. @xref{Debugger
diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi
index 7e0c84d7237..5224e313407 100644
--- a/doc/emacs/glossary.texi
+++ b/doc/emacs/glossary.texi
@@ -182,6 +182,7 @@ corresponding Control character. @xref{User Input,C-M-}.
Case conversion means changing text from upper case to lower case or
vice versa. @xref{Case}.
+@cindex ignore case
@item Case Folding
Case folding means ignoring the differences between case variants of
the same letter: upper-case, lower-case, and title-case. Emacs
@@ -229,9 +230,11 @@ from a variety of coding systems when reading or writing it.
@item Command
A command is a Lisp function specially defined to be able to serve as
a key binding in Emacs or to be invoked by its name
-(@pxref{Glossary---Command Name}). When you type a key sequence
-(q.v.), its binding (q.v.@:) is looked up in the relevant keymaps
-(q.v.@:) to find the command to run. @xref{Commands}.
+(@pxref{Glossary---Command Name}). (Another term for @dfn{command} is
+@dfn{interactive function}---they are used interchangeably.) When you
+type a key sequence (q.v.), its binding (q.v.@:) is looked up in the
+relevant keymaps (q.v.@:) to find the command to run.
+@xref{Commands}.
@item Command History
@xref{Glossary---Minibuffer History}.
@@ -775,6 +778,14 @@ typing sequences of @acronym{ASCII} characters (q.v.). @xref{Input Methods}.
Insertion means adding text into the buffer, either from the keyboard
or from some other place in Emacs.
+@item Interactive Function
+A different term for @dfn{command} (q.v.).
+
+@item Interactive Invocation
+A function can be called from Lisp code, or called as a user level
+command (via @kbd{M-x}, a key binding or a menu). In the latter case,
+the function is said to be @dfn{called interactively}.
+
@item Interlocking
@xref{Glossary---File Locking}.
diff --git a/doc/emacs/haiku.texi b/doc/emacs/haiku.texi
index 0c76990caed..ac631a39a69 100644
--- a/doc/emacs/haiku.texi
+++ b/doc/emacs/haiku.texi
@@ -85,16 +85,24 @@ instead.
@cindex tooltips (haiku)
@cindex haiku tooltips
-@vindex haiku-use-system-tooltips
On Haiku, Emacs defaults to using the system tooltip mechanism.
This usually leads to more responsive tooltips, but the tooltips will
not be able to display text properties or faces. If you need those
-features, customize the variable @code{haiku-use-system-tooltips} to
-the nil value, and Emacs will use its own implementation of tooltips.
-
- Both system tooltips and Emacs's own tooltips cannot display above
-the menu bar, so help text in the menu bar will display in the echo
-area instead.
+features, customize the variable @code{use-system-tooltips} to the
+@code{nil} value, and Emacs will use its own implementation of
+tooltips.
+
+@cindex X resources on Haiku
+ Unlike the X window system, Haiku does not have a system-wide
+resource database. Since many important options are specified via
+X resources (@pxref{X Resources}), an emulation is provided: upon
+startup, Emacs will load a file named @file{GNU Emacs} inside the user
+configuration directory (normally @file{/boot/home/config/settings}),
+which should be a flattened system message where keys and values are
+both strings, and correspond to attributes and their values
+respectively.
+
+You can create such a file with the @command{xmlbmessage} tool.
@subsection What to do when Emacs crashes
@cindex crashes, Haiku
diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 5a458209d2f..d206dee3859 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -20,10 +20,28 @@ commands (@code{help-for-help}). You can scroll the list with
@key{SPC} and @key{DEL}, then type the help command you want. To
cancel, type @kbd{C-g}.
+@cindex help buffer
Many help commands display their information in a special @dfn{help
buffer}. In this buffer, you can type @key{SPC} and @key{DEL} to
scroll and type @key{RET} to follow hyperlinks. @xref{Help Mode}.
+@vindex help-window-select
+ By default, help commands display the help buffer in a separate
+window without selecting that window. The variable
+@code{help-window-select} controls this: its default value is
+@code{nil}; if it's customized to the value @code{t}, the help window
+is unconditionally selected by help commands, and if its value is
+@code{other}, the help window is selected only if there are more than
+two windows on the selected frame.
+
+@vindex help-window-keep-selected
+ Conversely, many commands in the @samp{*Help*} buffer will pop up a
+new window to display the results. For instance, clicking on the link
+to show the source code, or using the @key{i} command to display the
+manual entry, will (by default) pop up a new window. If
+@code{help-window-keep-selected} is changed to non-@code{nil}, the
+window displaying the @samp{*Help*} buffer will be reused instead.
+
@cindex searching documentation efficiently
@cindex looking for a subject in documentation
If you are looking for a certain feature, but don't know what it is
@@ -182,7 +200,10 @@ programming language you are editing (@code{info-lookup-symbol}).
@item C-h .
Display the help message for a special text area, if point is in one
(@code{display-local-help}). (These include, for example, links in
-@file{*Help*} buffers.) @xref{Help Echo}.
+@file{*Help*} buffers.) @xref{Help Echo}. If you invoke
+this command with a prefix argument, @kbd{C-u C-h .}, and point is on
+a button or a widget, this command will pop a new buffer that
+describes that button/widget.
@end table
@node Key Help
@@ -332,9 +353,9 @@ are included varies depending on the command used.
@cindex apropos
The @dfn{apropos} commands answer questions like, ``What are the
-commands for working with files?'' More precisely, you specify an
-@dfn{apropos pattern}, which means either a word, a list of words, or
-a regular expression.
+commands for working with files?'' More precisely, you specify your
+query as an @dfn{apropos pattern}, which is either a word, a list of
+words, or a regular expression.
Each of the following apropos commands reads an apropos pattern in
the minibuffer, searches for items that match the pattern, and
@@ -393,6 +414,12 @@ comes with a brief description and a list of keys you can currently
invoke it with. In our example, it would say that you can invoke
@code{find-file} by typing @kbd{C-x C-f}.
+@vindex help-window-select@r{, and apropos commands}
+ By default, the window showing the apropos buffer with the results
+of the query is not selected, but you can cause it to be selected by
+customizing the variable @code{help-window-select} to any
+non-@code{nil} value.
+
For more information about a function definition, variable or symbol
property listed in an apropos buffer, you can click on it with
@kbd{mouse-1} or @kbd{mouse-2}, or move there and type @key{RET}.
@@ -478,6 +505,9 @@ View the source of the current help topic (if any)
(@code{help-view-source}).
@item i
Look up the current topic in the manual(s) (@code{help-goto-info}).
+@item I
+Look up the current topic in the Emacs Lisp manual
+(@code{help-goto-lispref-info}).
@item c
Customize the variable or the face (@code{help-customize}).
@end table
@@ -512,6 +542,11 @@ previous hyperlink. These commands act cyclically; for instance,
typing @key{TAB} at the last hyperlink moves back to the first
hyperlink.
+@vindex help-clean-buttons
+ By default, many links in the help buffer are displayed surrounded
+by quote characters. If the @code{help-clean-buttons} user option is
+non-@code{nil}, these quote characters are removed from the buffer.
+
@kindex n @r{(Help mode)}
@kindex p @r{(Help mode)}
@findex help-goto-next-page
diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi
index e3de2bc2faf..bb8d51158ae 100644
--- a/doc/emacs/killing.texi
+++ b/doc/emacs/killing.texi
@@ -111,24 +111,27 @@ active (@pxref{Using Region}).
@kindex M-\
@findex delete-horizontal-space
-@kindex M-SPC
-@findex just-one-space
-@findex cycle-spacing
- The other delete commands are those that delete only whitespace
+The other delete commands are those that delete only whitespace
characters: spaces, tabs and newlines. @kbd{M-\}
(@code{delete-horizontal-space}) deletes all the spaces and tab
characters before and after point. With a prefix argument, this only
-deletes spaces and tab characters before point. @kbd{M-@key{SPC}}
-(@code{just-one-space}) does likewise but leaves a single space before
+deletes spaces and tab characters before point.
+
+@findex just-one-space
+@code{just-one-space} does likewise but leaves a single space before
point, regardless of the number of spaces that existed previously
(even if there were none before). With a numeric argument @var{n}, it
leaves @var{n} spaces before point if @var{n} is positive; if @var{n}
is negative, it deletes newlines in addition to spaces and tabs,
-leaving @minus{}@var{n} spaces before point. The command @code{cycle-spacing}
-acts like a more flexible version of @code{just-one-space}. It
-does different things if you call it repeatedly in succession.
-The first call acts like @code{just-one-space}, the next removes
-all whitespace, and a third call restores the original whitespace.
+leaving @minus{}@var{n} spaces before point.
+
+@kindex M-SPC
+@findex cycle-spacing
+@vindex cycle-spacing-actions
+The command @code{cycle-spacing} (@kbd{M-@key{SPC}}) acts like a more
+flexible version of @code{just-one-space}. It performs different
+space cleanup actions defined by @code{cycle-spacing-actions}, in a
+cyclic manner, if you call it repeatedly in succession.
@kbd{C-x C-o} (@code{delete-blank-lines}) deletes all blank lines
after the current line. If the current line is blank, it deletes all
@@ -540,11 +543,11 @@ clipboard.
clipboard contents are normally lost. Optionally, Emacs can save the
existing clipboard contents to the kill ring, preventing you from
losing the old clipboard data. If
-@code{save-interprogram-paste-before-kill} changed to a number, then
-this data is copied over if it's smaller (in characters) than this
-number. If this variable is any other non-@code{nil} value, it's
-always copied over---at the risk of high memory consumption if that
-data turns out to be large.
+@code{save-interprogram-paste-before-kill} has been set to a number,
+then the data is copied over if it's smaller (in characters) than
+this number. If this variable is any other non-@code{nil} value, the
+data is always copied over---at the risk of high memory consumption if
+that data turns out to be large.
Yank commands, such as @kbd{C-y} (@code{yank}), also use the
clipboard. If another application ``owns'' the clipboard---i.e., if
@@ -567,8 +570,8 @@ change the variable @code{select-enable-clipboard} to @code{nil}.
instance, a web browser will usually let you choose ``Copy Image'' on
images, and this image will be put on the clipboard. On capable
platforms, Emacs can yank these objects with the @code{yank-media}
-command---but only in modes that have support for it (@pxref{Yanking
-Media,,, elisp, The Emacs Lisp Reference Manual}).
+command---but only in modes that have support for it (@w{@pxref{Yanking
+Media,,, elisp, The Emacs Lisp Reference Manual}}).
@cindex clipboard manager
@vindex x-select-enable-clipboard-manager
@@ -607,14 +610,14 @@ yanks the contents of the clipboard at point.
@cindex primary selection
@cindex selection, primary
- Under the X Window System, there exists a @dfn{primary selection}
-containing the last stretch of text selected in an X application
-(usually by dragging the mouse). Typically, this text can be inserted
-into other X applications by @kbd{mouse-2} clicks. The primary
-selection is separate from the clipboard. Its contents are more
-fragile; they are overwritten each time you select text with the
-mouse, whereas the clipboard is only overwritten by explicit cut
-or copy commands.
+ Under the X Window System, PGTK and Haiku, there exists a
+@dfn{primary selection} containing the last stretch of text selected
+in an X application (usually by dragging the mouse). Typically, this
+text can be inserted into other X applications by @kbd{mouse-2}
+clicks. The primary selection is separate from the clipboard. Its
+contents are more fragile; they are overwritten each time you select
+text with the mouse, whereas the clipboard is only overwritten by
+explicit cut or copy commands.
Under X, whenever the region is active (@pxref{Mark}), the text in
the region is saved in the primary selection. This applies regardless
@@ -636,6 +639,13 @@ regions to the primary selection entirely.
(@kbd{C-y}) to insert this text if @code{select-enable-primary} is set
(@pxref{Clipboard}).
+@cindex lost-selection-mode
+ By default, Emacs keeps the region active even after text is
+selected in another program; this is contrary to typical X behavior.
+To make Emacs deactivate the region after another program places data
+in the primary selection, enable the global minor mode
+@code{lost-selection-mode}.
+
@cindex MS-Windows, and primary selection
MS-Windows provides no primary selection, but Emacs emulates it
within a single Emacs session by storing the selected text internally.
@@ -698,6 +708,9 @@ lines, much like @kbd{mouse-1}.
If @code{mouse-yank-at-point} is non-@code{nil}, @kbd{M-mouse-2} yanks
at point. Then it does not matter precisely where you click, or even
which of the frame's windows you click on. @xref{Mouse Commands}.
+This user option also effects interactive search: if it is
+non-@code{nil}, yanking with the mouse anywhere in the frame will add
+the text to the search string.
@node Accumulating Text
@section Accumulating Text
diff --git a/doc/emacs/kmacro.texi b/doc/emacs/kmacro.texi
index 60880941db3..88df2937659 100644
--- a/doc/emacs/kmacro.texi
+++ b/doc/emacs/kmacro.texi
@@ -179,7 +179,7 @@ itself counts as the first repetition, since it is executed as you
define it, so @kbd{C-u 4 C-x )} executes the macro immediately 3
additional times.
-@findex kdb-macro-redisplay
+@findex kmacro-redisplay
@kindex C-x C-k d
While executing a long-running keyboard macro, it can sometimes be
useful to trigger a redisplay (to show how far we've gotten). The
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index ab143707fdd..d7c432d420e 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -223,6 +223,7 @@ keystrokes. Here is a list of these events.
@table @key
@item ns-open-file
+@cindex ns-open-file event
@vindex ns-pop-up-frames
This event occurs when another Nextstep application requests that
Emacs open a file. A typical reason for this would be a user
@@ -239,52 +240,29 @@ means to always visit the file in a new frame. A value of @code{nil}
means to always visit the file in the selected frame.
@item ns-open-temp-file
+@cindex ns-open-temp-file event
This event occurs when another application requests that Emacs open a
temporary file. By default, this is handled by just generating a
@code{ns-open-file} event, the results of which are described above.
@item ns-open-file-line
+@cindex ns-open-file-line event
Some applications, such as ProjectBuilder and gdb, request not only a
particular file, but also a particular line or sequence of lines in
the file. Emacs handles this by visiting that file and highlighting
the requested line (@code{ns-open-file-select-line}).
-@item ns-drag-n-drop
-This event occurs when a user drags an object from another application
-into an Emacs frame. The default behavior is to open a file in the
-window under the mouse, or to insert text at point of the window under
-the mouse.
-
-The sending application has some limited ability to decide how Emacs
-handles the sent object, but the user may override the default
-behavior by holding one or more modifier key.
-
-@table @kbd
-@item control
-Insert as text in the current buffer. If the object is a file, this
-will insert the filename.
-@item alt/option
-Attempt to open the object as though it is a file or URL.
-@item super/command
-Perform the default action for the type. This can be useful when an
-application is overriding the default behavior.
-@end table
-
-The modifier keys listed above are defined by macOS and are unaffected
-by user changes to the modifiers in Emacs.
-
-@item ns-change-font
-This event occurs when the user selects a font in a Nextstep font
-panel (which can be opened with @kbd{Cmd-t}). The default behavior is
-to adjust the font of the selected frame
-(@code{ns-respond-to-changefont}). The name and size of the selected
-font are stored in the variables @code{ns-input-font} and
-@code{ns-input-fontsize}, respectively.
-
@item ns-power-off
+@cindex ns-power-off event
This event occurs when the user logs out and Emacs is still running, or when
``Quit Emacs'' is chosen from the application menu.
The default behavior is to save all file-visiting buffers.
+
+@item ns-show-prefs
+@cindex ns-show-prefs event
+This event occurs when the user selects ``Preferences'' from the
+application menu. By default, it is bound to the command
+@code{customize}.
@end table
@cindex using Nextstep services (macOS)
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 9a23f23e0ed..60169d8d8c8 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1055,15 +1055,6 @@ prefix argument is a repeat count.
Move to the next revision entry. A numeric prefix argument is a
repeat count.
-@item P
-Move to the log of the previous file, if showing logs for a multi-file
-VC fileset. Otherwise, just move to the beginning of the log. A
-numeric prefix argument is a repeat count.
-
-@item N
-Move to the log of the next file, if showing logs for a multi-file VC
-fileset. A numeric prefix argument is a repeat count.
-
@item a
Annotate the revision on the current line (@pxref{Old Revisions}).
@@ -1325,6 +1316,12 @@ point is on a directory entry, mark all files in that directory tree
(@code{vc-dir-mark-all-files}). With a prefix argument, mark all
listed files and directories.
+@findex vc-dir-mark-by-regexp
+@item %
+You can use this command to mark files by regexp
+(@code{vc-dir-mark-by-regexp}). If given a prefix, unmark files
+instead.
+
@item G
Add the file under point to the list of files that the VC should
ignore (@code{vc-dir-ignore}). For instance, if the VC is Git, it
@@ -1669,6 +1666,9 @@ support additional types of projects.
Which files do or don't belong to a project is also determined by
the project back-end. For example, the VC back-end doesn't consider
``ignored'' files (@pxref{VC Ignore}) to be part of the project.
+Also, the VC Project back-end considers ``untracked'' files by default.
+That behavior is controllable with the variable
+@code{project-vc-include-untracked}.
@menu
* Project File Commands:: Commands for handling project files.
@@ -1728,6 +1728,7 @@ doesn't seem to belong to a recognizable project, these commands
prompt you for the project directory.
@findex project-find-file
+@vindex vc-directory-exclusion-list
The command @kbd{C-x p f} (@code{project-find-file}) is a convenient
way of visiting files (@pxref{Visiting}) that belong to the current
project. Unlike @kbd{C-x C-f}, this command doesn't require to type
@@ -1736,7 +1737,9 @@ base name (i.e., omit the leading directories). In addition, the
completion candidates considered by the command include only the files
belonging to the current project, and nothing else. If there's a file
name at point, this command offers that file as the first element of
-the ``future history''.
+the ``future history''. If given a prefix, include all files under
+the project root, except for @acronym{VCS} directories listed in
+@code{vc-directory-exclusion-list}.
@findex project-find-regexp
The command @kbd{C-x p g} (@code{project-find-regexp}) is similar to
@@ -1831,11 +1834,14 @@ buffers as candidates for completion.
@findex project-kill-buffers
@vindex project-kill-buffer-conditions
+@vindex project-kill-buffers-display-buffer-list
When you finish working on the project, you may wish to kill all the
buffers that belong to the project, to keep your Emacs session
smaller. The command @kbd{C-x p k} (@code{project-kill-buffers})
accomplishes that: it kills all the buffers that belong to the current
-project that satisfy any of @code{project-kill-buffer-conditions}.
+project that satisfy any of @code{project-kill-buffer-conditions}. If
+@code{project-kill-buffers-display-buffer-list} is non-@code{nil}, the
+buffers to be killed will be displayed first.
@node Switching Projects
@subsection Switching Projects
@@ -2216,8 +2222,8 @@ where you were with @kbd{M-,}.
@kindex C-M-,
@findex xref-go-forward
- Go forward to a place from where you previously went back using @kbd{M-,}.
-This is useful if you find that you went back too far.
+ If you previously went back too far with @kbd{M-,}, @kbd{C-M-,}
+(@code{xref-go-forward}) can be used to go forward again.
@findex xref-etags-mode
Some major modes install @code{xref} support facilities that might
@@ -2317,10 +2323,15 @@ them.
@item M-?
Find all the references for the identifier at point.
-@item M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET}
+@item M-x xref-query-replace-in-results @key{RET} @var{replacement} @key{RET}
+@itemx C-u M-x xref-query-replace-in-results @key{RET} @var{regexp} @key{RET} @var{replacement} @key{RET}
Interactively replace @var{regexp} with @var{replacement} in the names
of all the identifiers shown in the @file{*xref*} buffer.
+@item M-x xref-find-references-and-replace @key{RET} @var{from} @key{RET} @var{to} @key{RET}
+Interactively rename all instances of the identifier @var{from} to the
+new name @var{to}.
+
@item M-x tags-search @key{RET} @var{regexp} @key{RET}
Search for @var{regexp} through the files in the selected tags
table.
@@ -2358,13 +2369,21 @@ shown. The default value is @code{nil}, which just shows the results
in the @file{*xref*} buffer, but doesn't select any of them.
@findex xref-query-replace-in-results
- @kbd{M-x xref-query-replace-in-results} reads a regexp to match identifier
-names and a replacement string, just like ordinary @kbd{M-x
-query-replace-regexp}. It then performs the specified replacement in
-the names of the matching identifiers in all the places in all the
-files where these identifiers are referenced. This is useful when you
+ @kbd{M-x xref-query-replace-in-results} reads a @var{replacement}
+string, just like ordinary @kbd{M-x query-replace-regexp}. It then
+renames the identifiers shown in the @file{*xref*} buffer in all the
+places in all the files where these identifiers are referenced, such
+that their new name is @var{replacement}. This is useful when you
rename your identifiers as part of refactoring. This command should
-be invoked in the @file{*xref*} buffer generated by @kbd{M-?}.
+be invoked in the @file{*xref*} buffer generated by @kbd{M-?}. With a
+prefix argument, the command also prompts for a regexp to match
+identifier names, and renames that regexp in the names of the matching
+identifiers with @var{replacement}.
+
+@findex xref-find-references-and-replace
+ @kbd{M-x xref-find-references-and-replace} works similarly to
+@code{xref-query-replace-in-results}, but is more convenient when you
+want to rename a single identifier specified by its name @var{from}.
@findex tags-search
@kbd{M-x tags-search} reads a regexp using the minibuffer, then
@@ -2807,6 +2826,13 @@ place of a file name on the command line. @command{etags} will read from
standard input and mark the produced tags as belonging to the file
@var{file}.
+ For C and C++, if the source files don't observe the GNU Coding
+Standards' convention if having braces (@samp{@{} and @samp{@}}) in
+column zero only for top-level definitions, like functions and
+@code{struct} definitions, we advise that you use the
+@samp{--ignore-indentation} option, to prevent @command{etags} from
+incorrectly interpreting closing braces in column zero.
+
@samp{etags --help} outputs the list of the languages @command{etags}
knows, and the file name rules for guessing the language. It also prints
a list of all the available @command{etags} options, together with a short
@@ -2979,11 +3005,12 @@ etags --language=none \
@findex visit-tags-table
Emacs has at any time at most one @dfn{selected} tags table. All
-the commands for working with tags tables use the selected one. To
-select a tags table, type @kbd{M-x visit-tags-table}, which reads the
-tags table file name as an argument, with @file{TAGS} defaulting to
-the first directory that contains a file named @file{TAGS} encountered
-when recursively searching upward from the default directory.
+the commands for working with tags tables use the selected one first.
+To select a tags table, type @kbd{M-x visit-tags-table}, which reads
+the tags table file name as an argument, with @file{TAGS} defaulting
+to the first directory that contains a file named @file{TAGS}
+encountered when recursively searching upward from the default
+directory.
@vindex tags-file-name
Emacs does not actually read in the tags table contents until you
@@ -2993,16 +3020,25 @@ variable's initial value is @code{nil}; that value tells all the
commands for working with tags tables that they must ask for a tags
table file name to use.
- Using @code{visit-tags-table} when a tags table is already loaded
-gives you a choice: you can add the new tags table to the current list
-of tags tables, or start a new list. The tags commands use all the tags
-tables in the current list. If you start a new list, the new tags table
-is used @emph{instead} of others. If you add the new table to the
-current list, it is used @emph{as well as} the others.
+ In addition to the selected tags table, Emacs maintains the list of
+several tags tables that you use together. For example, if you are
+working on a program that uses a library, you may wish to have the
+tags tables of both the program and the library available, so that
+Emacs could easily find identifiers from both. If the selected tags
+table doesn't have the identifier or doesn't mention the source file a
+tags command needs, the command will try using all the other tags
+tables in the current list of tags tables.
+
+ Using @code{visit-tags-table} to load a new tags table when another
+tags table is already loaded gives you a choice: you can add the new
+tags table to the current list of tags tables, or discard the current
+list and start a new list. If you start a new list, the new tags
+table is used @emph{instead} of others. If you add the new table to
+the current list, it is used @emph{as well as} the others.
@vindex tags-table-list
You can specify a precise list of tags tables by setting the variable
-@code{tags-table-list} to a list of strings, like this:
+@code{tags-table-list} to a list of directory names, like this:
@c keep this on two lines for formatting in smallbook
@example
diff --git a/doc/emacs/mark.texi b/doc/emacs/mark.texi
index 91c44d527b3..ad25ed6a8aa 100644
--- a/doc/emacs/mark.texi
+++ b/doc/emacs/mark.texi
@@ -291,12 +291,23 @@ instead signal an error if the mark is inactive.
@cindex Delete Selection mode
@cindex mode, Delete Selection
@findex delete-selection-mode
+@vindex delete-selection-temporary-region
By default, text insertion occurs normally even if the mark is
active---for example, typing @kbd{a} inserts the character @samp{a},
then deactivates the mark. Delete Selection mode, a minor mode,
modifies this behavior: if you enable that mode, then inserting text
while the mark is active causes the text in the region to be deleted
-first. To toggle Delete Selection mode on or off, type @kbd{M-x
+first. However, you can tune this behavior by customizing the
+@code{delete-selection-temporary-region} option. Its default value is
+@code{nil}, but you can set it to @code{t}, in which case only
+temporarily-active regions will be replaced: those which are set by
+dragging the mouse (@pxref{Setting Mark}) or by shift-selection
+(@pxref{Shift Selection}), as well as by @kbd{C-u C-x C-x} when
+Transient Mark Mode is disabled. You can further tune the behavior by
+setting @code{delete-selection-temporary-region} to @code{selection}:
+then temporary regions by @kbd{C-u C-x C-x} won't be replaced, only
+the ones activated by dragging the mouse or shift-selection. To
+toggle Delete Selection mode on or off, type @kbd{M-x
delete-selection-mode}.
@node Mark Ring
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index 979be34fac7..4e71793b66e 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -195,7 +195,14 @@ use the @kbd{C-o} (@code{open-line}) command (@pxref{Blank Lines}).
often bound to @dfn{completion commands}, which allow you to easily
fill in the desired text without typing all of it. @xref{Completion}.
As with @key{RET}, you can use @kbd{C-q} to insert a @key{TAB},
-@key{SPC}, or @samp{?} character.
+@key{SPC}, or @samp{?} character. If you want to make @key{SPC} and
+@key{?} insert normally instead of starting completion, you can put
+the following in your init file:
+
+@lisp
+(keymap-unset minibuffer-local-completion-map "SPC")
+(keymap-unset minibuffer-local-completion-map "?")
+@end lisp
For convenience, @kbd{C-a} (@code{move-beginning-of-line}) in a
minibuffer moves point to the beginning of the argument text, not the
@@ -371,6 +378,20 @@ window. You can display the same list with @kbd{?}
used with the completion list:
@table @kbd
+@vindex minibuffer-completion-auto-choose
+@item M-@key{DOWN}
+@itemx M-@key{UP}
+While in the minibuffer, these keys navigate through the completions
+displayed in the completions buffer. When
+@code{minibuffer-completion-auto-choose} is non-@code{nil} (which is
+the default), using these commands also inserts the current completion
+candidate into the minibuffer. If
+@code{minibuffer-completion-auto-choose} is @code{nil}, you can use
+the @kbd{M-@key{RET}} command to insert the completion candidates into
+the minibuffer. By default, that exits the minibuffer, but with a
+prefix argument, @kbd{C-u M-@key{RET}} inserts the currently active
+candidate without exiting the minibuffer.
+
@findex switch-to-completions
@item M-v
@itemx @key{PageUp}
@@ -386,7 +407,10 @@ ways (@pxref{Windows}).
@itemx mouse-1
@itemx mouse-2
While in the completion list buffer, this chooses the completion at
-point (@code{choose-completion}).
+point (@code{choose-completion}). With a prefix argument, @kbd{C-u
+@key{RET}} inserts the completion at point into the minibuffer, but
+doesn't exit the minibuffer---thus, you can change your mind and
+choose another candidate.
@findex next-completion
@item @key{TAB}
@@ -617,11 +641,34 @@ completion alternatives in the completion list.
@vindex completion-auto-help
If @code{completion-auto-help} is set to @code{nil}, the completion
commands never display the completion list buffer; you must type
-@kbd{?} to display the list. If the value is @code{lazy}, Emacs only
+@kbd{?} to display the list. If the value is @code{lazy}, Emacs only
shows the completion list buffer on the second attempt to complete.
In other words, if there is nothing to complete, the first @key{TAB}
echoes @samp{Next char not unique}; the second @key{TAB} shows the
-completion list buffer.
+completion list buffer. If the value is @code{always}, the completion
+list buffer is always shown when completion is attempted.
+
+The display of the completion list buffer after it is shown for the
+first time is also controlled by @code{completion-auto-help}. If the
+value is @code{t} or @code{lazy}, the window showing the completions
+pops down when Emacs is able to complete (and may pop up again if
+Emacs is again unable to complete after you type some more text); if
+the value is @code{always}, the window pops down only when you exit
+the completion. The value @code{visible} is a hybrid: it behaves like
+@code{t} when it decides whether to pop up the window showing the
+completion list buffer, and like @code{always} when it decides whether
+to pop it down.
+
+@vindex completion-auto-select
+ Emacs can optionally select the window showing the completions when
+it shows that window. To enable this behavior, customize the user
+option @code{completion-auto-select} to @code{t}, which changes the
+behavior of @key{TAB} when Emacs pops up the completions: pressing
+@kbd{@key{TAB}} will switch to the completion list buffer, and you can
+then move to a candidate by cursor motion commands and select it with
+@kbd{@key{RET}}. If the value of @code{completion-auto-select} is
+@code{second-tab}, then the first @kbd{@key{TAB}} will pop up the
+completions list buffer, and the second one will switch to it.
@vindex completion-cycle-threshold
If @code{completion-cycle-threshold} is non-@code{nil}, completion
@@ -638,11 +685,50 @@ behavior only when there are @var{n} or fewer alternatives.
@vindex completions-format
When displaying completions, Emacs will normally pop up a new buffer
-to display the completions. The completions will (by default) be
-sorted in columns horizontally in alphabetical order, but this can be
-changed by changing the @code{completions-format} user option. If
-@code{vertical}, sort the completions vertically in columns instead,
-and if @code{one-column}, just use a single column.
+to display the completions. The completions will by default be sorted
+horizontally, using as many columns as will fit in the window-width,
+but this can be changed by customizing the @code{completions-format}
+user option. If its value is @code{vertical}, Emacs will sort the
+completions vertically instead, and if it's @code{one-column}, Emacs
+will use just one column.
+
+@vindex completions-sort
+ The @code{completions-sort} user option controls the order in which
+the completions are sorted in the @samp{*Completions*} buffer. The
+default is @code{alphabetical}, which sorts in alphabetical order.
+The value @code{nil} disables sorting. The value can also be a
+function, which will be called with the list of completions, and
+should return the list in the desired order.
+
+@vindex completions-max-height
+ When @code{completions-max-height} is non-@code{nil}, it limits the
+size of the completions window. It is specified in lines and include
+mode, header line and a bottom divider, if any. For a more complex
+control of the Completion window display properties, you can use
+@code{display-buffer-alist} (@pxref{Buffer Display Action
+Alists,,Action Alists for Buffer Display, elisp, The Emacs Lisp
+Reference Manual}).
+
+@vindex completions-header-format
+The variable @code{completions-header-format} is a format spec string to
+control the informative line shown before the completions list of
+candidates. If it contains a @samp{%s} construct, that get replaced
+by the number of completions shown in the completion list buffer. To
+suppress the display of the heading line, customize this variable to
+@code{nil}. The string that is the value of this variable can have
+text properties to change the visual appearance of the heading line;
+some useful properties @code{face} or @code{cursor-intangible}
+(@pxref{Special Properties,,Properties with Special Meanings, elisp,
+The Emacs Lisp Reference Manual}).
+
+@vindex completions-highlight-face
+When @code{completions-highlight-face} names a face, the current
+completion candidate, the one that will be selected by typing
+@kbd{@key{RET}} or clicking the mouse, will be highlighted using that
+face. The default value of this variable is
+@code{completions-highlight}; the value is @code{nil} disables this
+highlighting. This feature uses the special text property
+@code{cursor-face}.
@node Minibuffer History
@section Minibuffer History
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index df1e5ef2381..9709c6ddc1f 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -455,20 +455,27 @@ servers the user has connected to. If this variable is @code{t},
@cindex PostScript file
@cindex OpenDocument file
@cindex Microsoft Office file
+@cindex EPUB file
+@cindex CBZ file
+@cindex FB2 file
+@cindex XPS file
+@cindex OXPS file
@cindex DocView mode
@cindex mode, DocView
@cindex document viewer (DocView)
@findex doc-view-mode
DocView mode is a major mode for viewing DVI, PostScript (PS), PDF,
-OpenDocument, and Microsoft Office documents. It provides features
-such as slicing, zooming, and searching inside documents. It works by
-converting the document to a set of images using the @command{gs}
-(GhostScript) or @command{mudraw}/@command{pdfdraw} (MuPDF) commands
-and other external tools @footnote{For PostScript files, GhostScript
-is a hard requirement. For DVI files, @code{dvipdf} or @code{dvipdfm}
-is needed. For OpenDocument and Microsoft Office documents, the
-@code{unoconv} tool is needed.}, and displaying those images.
+OpenDocument, Microsoft Office, EPUB, CBZ, FB2, XPS and OXPS
+documents. It provides features such as slicing, zooming, and
+searching inside documents. It works by converting the document to a
+set of images using the @command{gs} (GhostScript) or
+@command{pdfdraw}/@command{mutool draw} (MuPDF) commands and other
+external tools @footnote{PostScript files require GhostScript, DVI
+files require @code{dvipdf} or @code{dvipdfm}, OpenDocument and
+Microsoft Office documents require the @code{unoconv} tool, and EPUB,
+CBZ, FB2, XPS and OXPS files require @code{mutool} to be available.},
+and displaying those images.
@findex doc-view-toggle-display
@findex doc-view-minor-mode
@@ -849,6 +856,9 @@ Restores the position of point as it was before inserting the
shell-command output.
@end table
+In case the output buffer is not the current buffer, shell command
+output is appended at the end of this buffer.
+
@node Interactive Shell
@subsection Interactive Subshell
@@ -886,6 +896,19 @@ also rename the @file{*shell*} buffer using @kbd{M-x rename-uniquely},
then create a new @file{*shell*} buffer using plain @kbd{M-x shell}.
Subshells in different buffers run independently and in parallel.
+ Emacs attempts to keep track of what the current directory is by
+looking at the commands you enter, looking for @samp{cd} commands and
+the like. This is an error-prone solution, since there are many ways
+to change the current directory, so Emacs also looks for special
+@acronym{OSC} (Operating System Commands) escape codes that are
+designed to convey this information in a more reliable fashion. You
+should arrange for your shell to print the appropriate escape sequence
+at each prompt, for instance with the following command:
+
+@example
+printf "\e]7;file://%s%s\e\\" "$HOSTNAME" "$PWD"
+@end example
+
@vindex explicit-shell-file-name
@cindex environment variables for subshells
@cindex @env{ESHELL} environment variable
@@ -2760,7 +2783,12 @@ will by default ask you whether to use the locked desktop file. You
can avoid the question by customizing the variable
@code{desktop-load-locked-desktop} to either @code{nil}, which means
never load the desktop in this case, or @code{t}, which means load the
-desktop without asking.
+desktop without asking. Finally, the @code{check-pid} value means to
+load the file if the Emacs process that has locked the desktop is not
+running on the local machine. This should not be used in
+circumstances where the locking Emacs might still be running on
+another machine. This could be the case in multi-user environments
+where your home directory is mounted remotely using NFS or similar.
@cindex desktop restore in daemon mode
When Emacs starts in daemon mode, it cannot ask you any questions,
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 09fedb7f9f2..5f303418383 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -50,13 +50,14 @@ others.
@item
You can insert non-@acronym{ASCII} characters or search for them. To do that,
-you can specify an input method (@pxref{Select Input Method}) suitable
+you can specify an Emacs input method (@pxref{Select Input Method}) suitable
for your language, or use the default input method set up when you choose
your language environment. If
your keyboard can produce non-@acronym{ASCII} characters, you can select an
appropriate keyboard coding system (@pxref{Terminal Coding}), and Emacs
-will accept those characters. Latin-1 characters can also be input by
-using the @kbd{C-x 8} prefix, see @ref{Unibyte Mode}.
+will accept those characters. On graphical displays, modern systems
+typically provide their native input methods, and Latin-1 characters
+can also be input by using the @kbd{C-x 8} prefix, see @ref{Unibyte Mode}.
With the X Window System, your locale should be set to an appropriate
value to make sure Emacs interprets keyboard input correctly; see
@@ -449,10 +450,13 @@ for that key.
@cindex input methods
An @dfn{input method} is a kind of character conversion designed
-specifically for interactive input. In Emacs, typically each language
-has its own input method; sometimes several languages that use the same
-characters can share one input method. A few languages support several
-input methods.
+specifically for interactive input. This section describes input
+methods that come with Emacs; for native input methods provided by the
+underlying OS, @pxref{Unibyte Mode}.
+
+ In Emacs, typically each language has its own input method;
+sometimes several languages that use the same characters can share one
+input method. A few languages support several input methods.
The simplest kind of input method works by mapping @acronym{ASCII} letters
into another alphabet; this allows you to use one other alphabet
@@ -1798,12 +1802,38 @@ as @code{xterm}, you can arrange for Meta to be converted to @key{ESC}
and still be able to type 8-bit characters present directly on the
keyboard or using @key{Compose} or @key{AltGr} keys. @xref{User Input}.
+@cindex input methods, native
+@cindex XIM, X Input Methods
+@cindex GTK input methods
+Many modern systems provide @dfn{native input methods} for many
+languages whose characters don't have keyboard keys assigned to them.
+If Emacs was built with support for these native input methods, you
+can activate such an input method and type the characters they
+support. How to activate and use these input methods depends on the
+system and the input method, and will not be described here; see your
+system documentation. Here we describe some Emacs facilities to
+control the use of the native input methods.
+
+@vindex x-gtk-use-native-input
+In Emacs built with the GTK toolkit, the variable
+@code{x-gtk-use-native-input} controls whether Emacs should receive
+characters produced by GTK input methods. If the value is @code{nil},
+the default, Emacs uses the X input methods (@acronym{XIM}), otherwise
+it uses the GTK input methods. The @code{useXIM} X resource controls
+whether to use @acronym{XIM}, and @code{inputStyle} X resource
+controls the display on X of preview text generated by the native
+input methods; @pxref{Table of Resources}.
+
+On MS-Windows, Emacs supports native inputs methods provided by
+@acronym{IMM}, the Input Method Manager, but that can be turned off if
+needed; @pxref{Windows Keyboard}.
+
@cindex @code{iso-transl} library
@cindex compose character
@cindex dead character
@item
You can use the key @kbd{C-x 8} as a compose-character prefix for
-entry of non-@acronym{ASCII} Latin-1 and a few other printing
+entry of non-@acronym{ASCII} Latin-1 and other printing
characters. @kbd{C-x 8} is good for insertion (in the minibuffer as
well as other buffers), for searching, and in any other context where
a key sequence is allowed.
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index caa65bf33b6..7e16c82cf5c 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -89,6 +89,11 @@ list of available packages from package archive servers. If the
network is unavailable, it falls back on the most recently retrieved
list.
+The main command to use in the package list buffer is the @key{x}
+command. If the package under point isn't installed already, this
+command will install it. If the package under point is already
+installed, this command will delete it.
+
The following commands are available in the package menu:
@table @kbd
@@ -162,7 +167,10 @@ installed versions (marked with status @samp{obsolete}).
@findex package-menu-execute
Download and install all packages marked with @kbd{i}, and their
dependencies; also, delete all packages marked with @kbd{d}
-(@code{package-menu-execute}). This also removes the marks.
+(@code{package-menu-execute}). This also removes the marks. If no
+packages are marked, this command will install the package under point
+(if it isn't installed already), or delete the package under point (if
+it's already installed).
@item g
@item r
@@ -320,10 +328,15 @@ version of the package, a newer version is also installed.
@section Package Installation
@findex package-install
+@findex package-update
+@findex package-update-all
Packages are most conveniently installed using the package menu
(@pxref{Package Menu}), but you can also use the command @kbd{M-x
package-install}. This prompts for the name of a package with the
-@samp{available} status, then downloads and installs it.
+@samp{available} status, then downloads and installs it. Similarly,
+if you want to update a package, you can use the @kbd{M-x
+package-update} command, and if you just want to update all the
+packages, you can use the @kbd{M-x package-update-all} command.
@cindex package requirements
A package may @dfn{require} certain other packages to be installed,
@@ -470,6 +483,16 @@ The default value is just @code{'(all)}.
installed will be ignored. The @samp{muse} package will be listed in
the package menu with the @samp{held} status.
+@findex package-recompile
+@findex package-recompile-all
+ Emacs byte code is quite stable, but it's possible for byte code to
+become outdated, or for the compiled files to rely on macros that have
+changed in new versions of Emacs. You can use the command @w{@kbd{M-x
+package-recompile}} to recompile a particular package, or
+@w{@kbd{M-x package-recompile-all}} to recompile all the packages. (The
+latter command might take quite a while to run if you have many
+installed packages.)
+
@node Package Files
@section Package Files and Directory Layout
@cindex package directory
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index ff4405f1fbc..795aabee743 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -250,10 +250,10 @@ where it treats each chapter, section, etc., as a definition.
together.)
@findex imenu
- If you type @kbd{M-x imenu}, it reads the name of a definition using
-the minibuffer, then moves point to that definition. You can use
-completion to specify the name; the command always displays the whole
-list of valid names.
+ If you type @kbd{M-g i} (@code{imenu}), it reads the name of a
+definition using the minibuffer, then moves point to that definition.
+You can use completion to specify the name; the command always
+displays the whole list of valid names.
@findex imenu-add-menubar-index
Alternatively, you can bind the command @code{imenu} to a mouse
@@ -1439,9 +1439,13 @@ performs completion using the function, variable, or property names
defined in the current Emacs session.
In all other respects, in-buffer symbol completion behaves like
-minibuffer completion. For instance, if Emacs cannot complete to a
-unique symbol, it displays a list of completion alternatives in
-another window. @xref{Completion}.
+minibuffer completion. For instance, if Emacs cannot complete to
+a unique symbol, it displays a list of completion alternatives in
+another window. Then you can use the keys @kbd{M-@key{DOWN}} and
+@kbd{M-@key{UP}} to navigate through the completions displayed
+in the completions buffer without leaving the original buffer,
+and the key @kbd{M-@key{RET}} to insert the currently highlighted
+completion to the buffer. @xref{Completion}.
In Text mode and related modes, @kbd{M-@key{TAB}} completes words
based on the spell-checker's dictionary. @xref{Spelling}.
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index c12992c239a..f4e12d29e99 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -422,7 +422,7 @@ characters, that disables character folding during that search.
search string.
To search for non-@acronym{ASCII} characters, use one of the
-following methods:
+following methods during incremental search:
@itemize @bullet
@item
@@ -436,14 +436,6 @@ incremental search adds the @samp{control-S} character to the search
string.
@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}).
-
-@item
@kindex C-^ @r{(Incremental Search)}
@findex isearch-toggle-input-method
@findex isearch-toggle-specified-input-method
@@ -471,8 +463,26 @@ 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.
+
+@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)}
+ You can also include Emoji sequences in the search string. Type
+@w{@kbd{C-x 8 e @key{RET}}} (@code{isearch-emoji-by-name}), followed
+by the Unicode name of an Emoji (for example, @kbd{smiling face} or
+@kbd{heart with arrow}). This adds the specified Emoji to the search
+string. If you don't know the name of the Emoji you want to search
+for, you can use @kbd{C-x 8 e l} (@code{emoji-list}) and @kbd{C-x 8 e
+d} (@code{emoji-describe}) (@pxref{Input Methods}).
+
@kindex M-s o @r{(Incremental Search)}
@findex isearch-occur
Typing @kbd{M-s o} in incremental search invokes
@@ -889,11 +899,13 @@ character folding during incremental regexp search with @kbd{M-s '},
the search becomes a non-regexp search and the search pattern you
typed is interpreted as a literal string.)
+@cindex pending, in incremental search
In some cases, adding characters to the regexp in an incremental
regexp search can make the cursor move back and start again. For
example, if you have searched for @samp{foo} and you add @samp{\|bar},
the cursor backs up in case the first @samp{bar} precedes the first
-@samp{foo}. @xref{Regexps}.
+@samp{foo}. (The prompt will change to say ``Pending'' to notify the
+user that this recalculation has happened.) @xref{Regexps}.
Forward and backward regexp search are not symmetrical, because
regexp matching in Emacs always operates forward, starting with the
@@ -1015,24 +1027,11 @@ you search for @samp{a.*?$} against the text @samp{abbab} followed by
a newline, it matches the whole string. Since it @emph{can} match
starting at the first @samp{a}, it does.
-@item @kbd{\@{@var{n}\@}}
-is a postfix operator specifying @var{n} repetitions---that is, the
-preceding regular expression must match exactly @var{n} times in a
-row. For example, @samp{x\@{4\@}} matches the string @samp{xxxx} and
-nothing else.
-
-@item @kbd{\@{@var{n},@var{m}\@}}
-is a postfix operator specifying between @var{n} and @var{m}
-repetitions---that is, the preceding regular expression must match at
-least @var{n} times, but no more than @var{m} times. If @var{m} is
-omitted, then there is no upper limit, but the preceding regular
-expression must match at least @var{n} times.@* @samp{\@{0,1\@}} is
-equivalent to @samp{?}. @* @samp{\@{0,\@}} is equivalent to
-@samp{*}. @* @samp{\@{1,\@}} is equivalent to @samp{+}.
-
+@cindex set of alternative characters, in regular expressions
+@cindex character set, in regular expressions
@item @kbd{[ @dots{} ]}
-is a @dfn{character set}, beginning with @samp{[} and terminated by
-@samp{]}.
+is a @dfn{set of alternative characters}, or a @dfn{character set},
+beginning with @samp{[} and terminated by @samp{]}.
In the simplest case, the characters between the two brackets are what
this set can match. Thus, @samp{[ad]} matches either one @samp{a} or
@@ -1049,9 +1048,10 @@ which matches any lower-case @acronym{ASCII} letter or @samp{$}, @samp{%} or
period. As another example, @samp{[α-ωί]} matches all lower-case
Greek letters.
+@cindex character classes, in regular expressions
You can also include certain special @dfn{character classes} in a
character set. A @samp{[:} and balancing @samp{:]} enclose a
-character class inside a character alternative. For instance,
+character class inside a set of alternative characters. For instance,
@samp{[[:alnum:]]} matches any letter or digit. @xref{Char Classes,,,
elisp, The Emacs Lisp Reference Manual}, for a list of character
classes.
@@ -1119,13 +1119,13 @@ no preceding expression on which the @samp{*} can act. It is poor practice
to depend on this behavior; it is better to quote the special character anyway,
regardless of where it appears.
-As a @samp{\} is not special inside a character alternative, it can
-never remove the special meaning of @samp{-} or @samp{]}. So you
-should not quote these characters when they have no special meaning
-either. This would not clarify anything, since backslashes can
-legitimately precede these characters where they @emph{have} special
-meaning, as in @samp{[^\]} (@code{"[^\\]"} for Lisp string syntax),
-which matches any single character except a backslash.
+As a @samp{\} is not special inside a set of alternative characters, it can
+never remove the special meaning of @samp{-}, @samp{^} or @samp{]}.
+You should not quote these characters when they have no special
+meaning. This would not clarify anything, since backslashes
+can legitimately precede these characters where they @emph{have}
+special meaning, as in @samp{[^\]} (@code{"[^\\]"} for Lisp string
+syntax), which matches any single character except a backslash.
@node Regexp Backslash
@section Backslash in Regular Expressions
@@ -1190,11 +1190,11 @@ matches the same text that matched the @var{d}th occurrence of a
@samp{\( @dots{} \)} construct. This is called a @dfn{back
reference}.
-After the end of a @samp{\( @dots{} \)} construct, the matcher remembers
-the beginning and end of the text matched by that construct. Then,
-later on in the regular expression, you can use @samp{\} followed by the
-digit @var{d} to mean ``match the same text matched the @var{d}th time
-by the @samp{\( @dots{} \)} construct''.
+After the end of a @samp{\( @dots{} \)} construct, the matcher
+remembers the beginning and end of the text matched by that construct.
+Then, later on in the regular expression, you can use @samp{\}
+followed by the digit @var{d} to mean ``match the same text matched
+the @var{d}th @samp{\( @dots{} \)} construct''.
The strings matching the first nine @samp{\( @dots{} \)} constructs
appearing in a regular expression are assigned numbers 1 through 9 in
@@ -1211,6 +1211,21 @@ If a particular @samp{\( @dots{} \)} construct matches more than once
(which can easily happen if it is followed by @samp{*}), only the last
match is recorded.
+@item @kbd{\@{@var{m}\@}}
+is a postfix operator specifying @var{m} repetitions---that is, the
+preceding regular expression must match exactly @var{m} times in a
+row. For example, @samp{x\@{4\@}} matches the string @samp{xxxx} and
+nothing else.
+
+@item @kbd{\@{@var{m},@var{n}\@}}
+is a postfix operator specifying between @var{m} and @var{n}
+repetitions---that is, the preceding regular expression must match at
+least @var{m} times, but no more than @var{n} times. If @var{n} is
+omitted, then there is no upper limit, but the preceding regular
+expression must match at least @var{m} times.@* @samp{\@{0,1\@}} is
+equivalent to @samp{?}. @* @samp{\@{0,\@}} is equivalent to
+@samp{*}. @* @samp{\@{1,\@}} is equivalent to @samp{+}.
+
@item \`
matches the empty string, but only at the beginning of the string or
buffer (or its accessible portion) being matched against.
@@ -1812,12 +1827,18 @@ occurrence of @var{string}. When done, exit the recursive editing level
with @kbd{C-M-c} to proceed to the next occurrence.
@item e
-@itemx E
to edit the replacement string in the minibuffer. When you exit the
minibuffer by typing @key{RET}, the minibuffer contents replace the
current occurrence of the pattern. They also become the new
replacement string for any further occurrences.
+@item E
+is like @kbd{e}, but the next replacement will be done with exact
+case. I.e., if you have a @code{query-replace} from @samp{foo} to
+@samp{bar}, a text like @samp{Foo} will be normally be replaced with
+@samp{Bar}. Use this command to do the current replacement with exact
+case.
+
@item C-l
to redisplay the screen. Then you must type another character to
specify what to do with this occurrence.
@@ -1864,12 +1885,12 @@ replacing regexp matches in file names.
@node Other Repeating Search
@section Other Search-and-Loop Commands
- Here are some other commands that find matches for a regular
-expression. They all ignore case in matching, if the pattern contains
+ Here are some other commands that find matches for regular
+expressions. They all ignore case in matching, if the pattern contains
no upper-case letters and @code{case-fold-search} is non-@code{nil}.
Aside from @code{multi-occur} and @code{multi-occur-in-matching-buffers},
-which always search the whole buffer, all operate on the text from point
-to the end of the buffer, or on the region if it is active.
+which always search the whole buffer, all of the commands operate on the
+text from point to the end of the buffer, or on the region if it is active.
@table @kbd
@findex multi-isearch-buffers
@@ -1943,19 +1964,27 @@ is not considered a match.
@kindex RET @r{(Occur mode)}
@kindex o @r{(Occur mode)}
@kindex C-o @r{(Occur mode)}
-In the @file{*Occur*} buffer, you can click on each entry, or move
-point there and type @key{RET}, to visit the corresponding position in
-the buffer that was searched. @kbd{o} and @kbd{C-o} display the match
-in another window; @kbd{C-o} does not select it. Alternatively, you
-can use the @kbd{M-g M-n} (@code{next-error}) command to visit the
-occurrences one by one (@pxref{Compilation Mode}).
+The @file{*Occur*} buffer uses the Occur mode as its major mode. You
+can use the @kbd{n} and @kbd{p} keys to move to the next or previous
+match; with prefix numeric argument, these commands move that many
+matches. Digit keys are bound to @code{digit-argument}, so @kbd{5 n}
+moves to the fifth next match (you don't have to type @kbd{C-u}).
+@key{SPC} and @key{DEL} scroll the @file{*Occur*} buffer up and down.
+Clicking on a match or moving point there and typing @key{RET} visits
+the corresponding position in the original buffer that was searched.
+@kbd{o} and @kbd{C-o} display the match in another window; @kbd{C-o}
+does not select that window. Alternatively, you can use the @kbd{M-g
+M-n} (@code{next-error}) command to visit the occurrences one by one
+(@pxref{Compilation Mode}). Finally, @kbd{q} quits the window showing
+the @file{*Occur*} buffer and buries the buffer.
@cindex Occur Edit mode
@cindex mode, Occur Edit
-Typing @kbd{e} in the @file{*Occur*} buffer switches to Occur Edit
-mode, in which edits made to the entries are also applied to the text
-in the originating buffer. Type @kbd{C-c C-c} to return to Occur
-mode.
+Typing @kbd{e} in the @file{*Occur*} buffer makes the buffer writable
+and enters the Occur Edit mode, in which you can edit the matching
+lines and have those edits reflected in the text in the originating
+buffer. Type @kbd{C-c C-c} to leave the Occur Edit mode and return to
+the Occur mode.
@findex list-matching-lines
The command @kbd{M-x list-matching-lines} is a synonym for @kbd{M-x
diff --git a/doc/emacs/sending.texi b/doc/emacs/sending.texi
index ea87e0a77b6..cc54224200a 100644
--- a/doc/emacs/sending.texi
+++ b/doc/emacs/sending.texi
@@ -659,6 +659,7 @@ such as MIME support. Another available mode is MH-E
(@pxref{Top,,MH-E,mh-e, The Emacs Interface to MH}).
@vindex mail-user-agent
+@findex define-mail-user-agent
You can choose any of these @dfn{mail user agents} as your preferred
method for editing and sending mail. The commands @kbd{C-x m},
@kbd{C-x 4 m} and @kbd{C-x 5 m} use whichever agent you have
@@ -667,7 +668,10 @@ the bug reporter (@pxref{Bugs}). To specify a mail user agent,
customize the variable @code{mail-user-agent}. Currently, legitimate
values include @code{message-user-agent} (Message mode)
@code{sendmail-user-agent} (Mail mode), @code{gnus-user-agent}, and
-@code{mh-e-user-agent}.
+@code{mh-e-user-agent}. Additional options may be available; check
+in the manual of your mail user agent package for details. You may
+also define another mail user agent using
+@code{define-mail-user-agent}.
If you select a different mail-composition method, the information
in this chapter about the mail buffer and Message mode does not apply;
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index c5b54777a8c..fa8eaf09245 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -1259,6 +1259,17 @@ and related functions treat hidden text, @pxref{Query Replace}.)
You can also automatically make text visible as you navigate in it by
using Reveal mode (@kbd{M-x reveal-mode}), a buffer-local minor mode.
+@vindex outline-default-state
+ The @code{outline-default-state} variable controls what headings
+will be visible after Outline mode is turned on. If non-@code{nil},
+some headings are initially outlined. If equal to a number, show only
+headings up to and including the corresponding level. If equal to
+@code{outline-show-all}, all text of buffer is shown. If equal to
+@code{outline-show-only-headings}, show only headings, whatever their
+level is. If equal to a lambda function or function name, this
+function is expected to toggle headings visibility, and will be called
+without arguments after the mode is enabled.
+
@node Outline Views
@subsection Viewing One Outline in Multiple Views
@@ -1702,17 +1713,17 @@ to work with them.
@table @kbd
@item C-c C-o
Insert @samp{\begin} and @samp{\end} for @LaTeX{} block and position
-point on a line between them (@code{tex-latex-block}).
+point on a line between them (@code{latex-insert-block}).
@item C-c C-e
Close the innermost @LaTeX{} block not yet closed
-(@code{tex-close-latex-block}).
+(@code{latex-close-block}).
@end table
-@findex tex-latex-block
+@findex latex-insert-block
@kindex C-c C-o @r{(@LaTeX{} mode)}
In @LaTeX{} input, @samp{\begin} and @samp{\end} tags are used to
group blocks of text. To insert a block, type @kbd{C-c C-o}
-(@code{tex-latex-block}). This prompts for a block type, and inserts
+(@code{latex-insert-block}). This prompts for a block type, and inserts
the appropriate matching @samp{\begin} and @samp{\end} tags, leaving a
blank line between the two and moving point there.
@@ -1723,11 +1734,11 @@ completion list contains the standard @LaTeX{} block types. If you
want additional block types for completion, customize the list
variable @code{latex-block-names}.
-@findex tex-close-latex-block
+@findex latex-close-block
@kindex C-c C-e @r{(@LaTeX{} mode)}
@findex latex-electric-env-pair-mode
In @LaTeX{} input, @samp{\begin} and @samp{\end} tags must balance.
-You can use @kbd{C-c C-e} (@code{tex-close-latex-block}) to insert an
+You can use @kbd{C-c C-e} (@code{latex-close-block}) to insert an
@samp{\end} tag which matches the last unmatched @samp{\begin}. It
also indents the @samp{\end} to match the corresponding @samp{\begin},
and inserts a newline after the @samp{\end} tag if point is at the
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index e966565f000..f06b93759d8 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -151,7 +151,6 @@ garbled displays, running out of memory, and crashes and hangs.
Emacs.
@menu
-* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
* Stuck Recursive:: '[...]' in mode line around the parentheses.
* Screen Garbled:: Garbage on the screen.
* Text Garbled:: Garbage in the text.
@@ -160,65 +159,9 @@ Emacs.
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
* Long Lines:: Mitigating slowness due to extremely long lines.
+* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
@end menu
-@node DEL Does Not Delete
-@subsection If @key{DEL} Fails to Delete
-@cindex @key{DEL} vs @key{BACKSPACE}
-@cindex @key{BACKSPACE} vs @key{DEL}
-@cindex @key{DEL} does not delete
-
- Every keyboard has a large key, usually labeled @key{BACKSPACE},
-which is ordinarily used to erase the last character that you typed.
-In Emacs, this key is supposed to be equivalent to @key{DEL}.
-
- When Emacs starts up on a graphical display, it determines
-automatically which key should be @key{DEL}. In some unusual cases,
-Emacs gets the wrong information from the system, and @key{BACKSPACE}
-ends up deleting forwards instead of backwards.
-
- Some keyboards also have a @key{Delete} key, which is ordinarily
-used to delete forwards. If this key deletes backward in Emacs, that
-too suggests Emacs got the wrong information---but in the opposite
-sense.
-
- On a text terminal, if you find that @key{BACKSPACE} prompts for a
-Help command, like @kbd{Control-h}, instead of deleting a character,
-it means that key is actually sending the @samp{BS} character. Emacs
-ought to be treating @key{BS} as @key{DEL}, but it isn't.
-
-@findex normal-erase-is-backspace-mode
- In all of those cases, the immediate remedy is the same: use the
-command @kbd{M-x normal-erase-is-backspace-mode}. This toggles
-between the two modes that Emacs supports for handling @key{DEL}, so
-if Emacs starts in the wrong mode, this should switch to the right
-mode. On a text terminal, if you want to ask for help when @key{BS}
-is treated as @key{DEL}, use @key{F1} instead of @kbd{C-h}; @kbd{C-?}
-may also work, if it sends character code 127.
-
- To fix the problem in every Emacs session, put one of the following
-lines into your initialization file (@pxref{Init File}). For the
-first case above, where @key{BACKSPACE} deletes forwards instead of
-backwards, use this line to make @key{BACKSPACE} act as @key{DEL}:
-
-@lisp
-(normal-erase-is-backspace-mode 0)
-@end lisp
-
-@noindent
-For the other two cases, use this line:
-
-@lisp
-(normal-erase-is-backspace-mode 1)
-@end lisp
-
-@vindex normal-erase-is-backspace
- Another way to fix the problem for every Emacs session is to
-customize the variable @code{normal-erase-is-backspace}: the value
-@code{t} specifies the mode where @key{BS} or @key{BACKSPACE} is
-@key{DEL}, and @code{nil} specifies the other mode. @xref{Easy
-Customization}.
-
@node Stuck Recursive
@subsection Recursive Editing Levels
@cindex stuck in recursive editing
@@ -296,6 +239,31 @@ editing in the same Emacs session.
out of memory, because the Buffer Menu needs a fair amount of memory
itself, and the reserve supply may not be enough.
+@cindex out of memory killer, GNU/Linux
+@cindex OOM killer
+ On GNU/Linux systems, Emacs does not normally get notified about
+out-of-memory situations; instead, the OS can kill the Emacs process
+when it runs out of memory. This feature is known as the
+@dfn{out-of-memory killer}, or @dfn{@acronym{OOM} killer}. When this
+behavior is in effect, Emacs is unable to detect the out-of-memory
+situation in time, and won't be able to let you save your buffer as
+described above. However, it is possible to turn off this behavior of
+the OS, and thus allow Emacs a chance to handle the out-of-memory
+situation in a more useful manner, before it is killed. To do that,
+become the super user, edit the file @code{/etc/sysctl.conf} to
+contain the lines shown below, and then invoke the command
+@w{@kbd{sysctl -p}} from the shell prompt:
+
+@example
+vm.overcommit_memory=2
+vm.overcommit_ratio=0
+@end example
+
+@noindent
+Please note that the above setting affects all the processes on the
+system, and in general the behavior of the system under memory
+pressure, not just the Emacs process alone.
+
@node Crashing
@subsection When Emacs Crashes
@@ -500,6 +468,86 @@ be substantial.
Use @kbd{M-x so-long-commentary} to view the documentation for this
library and learn more about how to enable and configure it.
+@vindex max-redisplay-ticks
+ If even @code{so-long-mode} doesn't help making Emacs responsive
+enough, or if you'd rather not disable the display-related features
+that @code{so-long-mode} turns off, you can instead customize the
+variable @code{max-redisplay-ticks} to a non-zero value. Then Emacs
+will abort redisplay of a window and commands, like @kbd{C-n} and
+@kbd{M-v}, which use the display code to do their job, if processing a
+window needs more low-level display operations than the value of this
+variable. The display of the offending window will then remain
+outdated, and possibly incomplete, on the screen, but Emacs should
+otherwise be responsive, and you could then switch to another buffer,
+or kill the problematic buffer, or turn on @code{so-long-mode} or
+@code{so-long-minor-mode} in that buffer. When the display of a
+window is aborted due to this reason, the buffer shown in that window
+will not have any of its windows redisplayed until the buffer is
+modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of
+that buffer's windows.
+
+ If you decide to customize this variable to a non-zero value, we
+recommend to use a value between 100,000 and 1,000,000, depending on
+your patience and the speed of your system. The default value is
+zero, which disables this feature.
+
+@node DEL Does Not Delete
+@subsection If @key{DEL} Fails to Delete
+@cindex @key{DEL} vs @key{BACKSPACE}
+@cindex @key{BACKSPACE} vs @key{DEL}
+@cindex @key{DEL} does not delete
+
+ Every keyboard has a large key, usually labeled @key{BACKSPACE},
+which is ordinarily used to erase the last character that you typed.
+In Emacs, this key is supposed to be equivalent to @key{DEL}.
+
+ When Emacs starts up on a graphical display, it determines
+automatically which key should be @key{DEL}. In some unusual cases,
+Emacs gets the wrong information from the system, and @key{BACKSPACE}
+ends up deleting forwards instead of backwards.
+
+ Some keyboards also have a @key{Delete} key, which is ordinarily
+used to delete forwards. If this key deletes backward in Emacs, that
+too suggests Emacs got the wrong information---but in the opposite
+sense.
+
+ On a text terminal, if you find that @key{BACKSPACE} prompts for a
+Help command, like @kbd{Control-h}, instead of deleting a character,
+it means that key is actually sending the @samp{BS} character. Emacs
+ought to be treating @key{BS} as @key{DEL}, but it isn't.
+
+@findex normal-erase-is-backspace-mode
+ In all of those cases, the immediate remedy is the same: use the
+command @kbd{M-x normal-erase-is-backspace-mode}. This toggles
+between the two modes that Emacs supports for handling @key{DEL}, so
+if Emacs starts in the wrong mode, this should switch to the right
+mode. On a text terminal, if you want to ask for help when @key{BS}
+is treated as @key{DEL}, use @key{F1} instead of @kbd{C-h}; @kbd{C-?}
+may also work, if it sends character code 127.
+
+ To fix the problem in every Emacs session, put one of the following
+lines into your initialization file (@pxref{Init File}). For the
+first case above, where @key{BACKSPACE} deletes forwards instead of
+backwards, use this line to make @key{BACKSPACE} act as @key{DEL}:
+
+@lisp
+(normal-erase-is-backspace-mode 0)
+@end lisp
+
+@noindent
+For the other two cases, use this line:
+
+@lisp
+(normal-erase-is-backspace-mode 1)
+@end lisp
+
+@vindex normal-erase-is-backspace
+ Another way to fix the problem for every Emacs session is to
+customize the variable @code{normal-erase-is-backspace}: the value
+@code{t} specifies the mode where @key{BS} or @key{BACKSPACE} is
+@key{DEL}, and @code{nil} specifies the other mode. @xref{Easy
+Customization}.
+
@node Bugs
@section Reporting Bugs
@@ -782,10 +830,12 @@ Emacs, so you will have to report the bug somewhere else.
@item
The type of machine you are using, and the operating system name and
-version number (again, automatically included by @kbd{M-x
-report-emacs-bug}). @kbd{M-x emacs-version @key{RET}} provides this
-information too. Copy its output from the @file{*Messages*} buffer,
-so that you get it all and get it accurately.
+version number (again, automatically included by @w{@kbd{M-x
+report-emacs-bug}}). @w{@kbd{M-x emacs-version @key{RET}}} provides
+this information too. Copy its output from the @file{*Messages*}
+buffer, so that you get it all and get it accurately, or use
+@w{@kbd{C-u M-x emacs-version @key{RET}}} to insert the version
+information into the current buffer.
@item
The operands given to the @code{configure} command when Emacs was
diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi
index 2d984f4b926..3ccad507159 100644
--- a/doc/emacs/vc1-xtra.texi
+++ b/doc/emacs/vc1-xtra.texi
@@ -269,7 +269,7 @@ with the file's version control type.
@vindex vc-handled-backends
The variable @code{vc-handled-backends} determines which version
control systems VC should handle. The default value is @code{(RCS CVS
-SVN SCCS SRC Bzr Git Hg Mtn)}, so it contains all the version systems
+SVN SCCS SRC Bzr Git Hg)}, so it contains all the version systems
that are currently supported. If you want VC to ignore one or more of
these systems, exclude its name from the list. To disable VC
entirely, set this variable to @code{nil}.
diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi
index 4a3862562c2..4537f8157e8 100644
--- a/doc/emacs/windows.texi
+++ b/doc/emacs/windows.texi
@@ -442,8 +442,8 @@ selected window write:
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*scratch\\*" (display-buffer-same-window))))
@end group
@end example
@@ -468,8 +468,8 @@ Lisp Reference Manual}) as follows:
@example
@group
-(customize-set-variable
- 'display-buffer-base-action
+(setopt
+ display-buffer-base-action
'((display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . 0)))
@end group
@@ -535,8 +535,8 @@ the following form in your initialization file (@pxref{Init File}):
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*Completions\\*" display-buffer-below-selected)))
@end group
@end example
diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index c5dc4e8150f..2c2700bc15b 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -149,6 +149,15 @@ various X toolkits (GTK+, Lucid, etc.)---we indicate below when this
is the case.
@table @asis
+@item @code{alpha} (class @code{Alpha})
+Sets the @samp{alpha} frame parameter, determining frame transparency
+(@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}).
+
+@item @code{alphaBackground} (class @code{AlphaBackground})
+Sets the @samp{alpha-background} frame parameter, determining background
+transparency
+(@pxref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}).
+
@item @code{background} (class @code{Background})
Background color (@pxref{Colors}).
@@ -355,11 +364,26 @@ Let the input method decide how to display itself. This is usually
equivalent to @samp{overthespot}, but it might work with more input
methods.
+@item native
+Use the toolkit for handling input methods. This is currently
+implemented only on GTK.
+
@item root
Use some location on display specific to the input method for
displaying the preview text.
@end table
+@item @code{synchronizeResize} (class @code{SynchronizeResize})
+If @samp{off} or @samp{false}, Emacs will not try to tell the window
+manager when it has finished redrawing the display in response to a
+frame being resized. Otherwise, the window manager will postpone
+drawing a frame that was just resized until its contents are updated,
+which prevents blank areas of a frame that have not yet been painted
+from being displayed. If set to @samp{extended}, it will enable use
+of an alternative frame synchronization protocol, which might be
+supported by some compositing window managers that don't support the
+protocol Emacs uses by default.
+
@item @code{verticalScrollBars} (class @code{ScrollBars})
Give frames scroll bars on the left if @samp{left}, on the right if
@samp{right}; don't have scroll bars if @samp{off} (@pxref{Scroll Bars}).
@@ -585,7 +609,7 @@ those are governed by normal X resources (@pxref{Resources}).
The following sections describe how to customize GTK+ resources for
Emacs. For details about GTK+ resources, see the GTK+ API document at
-@uref{https://developer.gnome.org/gtk2/stable/gtk2-Resource-Files.html}.
+@uref{https://developer-old.gnome.org/gtk2/stable/gtk2-Resource-Files.html}.
In GTK+ version 3, GTK+ resources have been replaced by a completely
different system. The appearance of GTK+ widgets is now determined by
@@ -595,7 +619,7 @@ style settings (where @var{theme} is the name of the current GTK+
theme). Therefore, the description of GTK+ resources in this section
does not apply to GTK+ 3. For details about the GTK+ 3 styling
system, see
-@uref{https://developer.gnome.org/gtk3/3.0/GtkCssProvider.html}.
+@uref{https://developer-old.gnome.org/gtk3/3.0/GtkCssProvider.html}.
@menu
* GTK Resource Basics:: Basic usage of GTK+ resources.
diff --git a/doc/lispintro/Makefile.in b/doc/lispintro/Makefile.in
index d554f3d7a68..42e6d2c1c87 100644
--- a/doc/lispintro/Makefile.in
+++ b/doc/lispintro/Makefile.in
@@ -63,7 +63,7 @@ ENVADD = \
MAKEINFO="$(MAKEINFO) $(MAKEINFO_OPTS)"
DVI_TARGETS = emacs-lisp-intro.dvi
-HTML_TARGETS = emacs-lisp-intro.html
+HTML_TARGETS = eintr.html
PDF_TARGETS = emacs-lisp-intro.pdf
PS_TARGETS = emacs-lisp-intro.ps
@@ -95,7 +95,7 @@ emacs-lisp-intro.dvi: ${srcs}
emacs-lisp-intro.pdf: ${srcs}
$(ENVADD) $(TEXI2PDF) $<
-emacs-lisp-intro.html: ${srcs}
+eintr.html: ${srcs}
$(AM_V_GEN)$(MAKEINFO) $(MAKEINFO_OPTS) $(HTML_OPTS) -o $@ $<
emacs-lisp-intro.ps: emacs-lisp-intro.dvi
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index 9d4520b040e..049c8a65a8f 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -1,8 +1,6 @@
\input texinfo @c -*- mode: texinfo; coding: utf-8 -*-
@comment %**start of header
@setfilename ../../info/eintr.info
-@c setfilename emacs-lisp-intro.info
-@c sethtmlfilename emacs-lisp-intro.html
@settitle Programming in Emacs Lisp
@include docstyle.texi
@syncodeindex vr cp
@@ -15347,7 +15345,10 @@ nil
@group
(20615 27034 579989 697000)
(17905 55681 0 0)
-(20615 26327 734791 805000)
+(20615 26327 734791 805000)@footnote{If @code{current-time-list} is
+@code{nil} the three timestamps are @code{(1351051674579989697
+. 1000000000)}, @code{(1173477761000000000 . 1000000000)}, and
+@code{(1351050967734791805 . 1000000000)}, respectively.}
13188
"-rw-r--r--"
@end group
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index 1fe5a60b356..aee440fe782 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -541,10 +541,12 @@ file formerly visited.
@ref{Text}.
@defun buffer-modified-p &optional buffer
-This function returns @code{t} if the buffer @var{buffer} has been modified
-since it was last read in from a file or saved, or @code{nil}
-otherwise. If @var{buffer} is not supplied, the current buffer
-is tested.
+This function returns non-@code{nil} if @var{buffer} has
+been modified since it was last read in from a file or saved, or
+@code{nil} otherwise. If @var{buffer} has been auto-saved since the
+time it was last modified, this function returns the symbol
+@code{autosaved}. If @var{buffer} is @code{nil} or omitted, it
+defaults to the current buffer.
@end defun
@defun set-buffer-modified-p flag
@@ -563,8 +565,10 @@ function @code{force-mode-line-update} works by doing this:
@end defun
@defun restore-buffer-modified-p flag
-Like @code{set-buffer-modified-p}, but does not force redisplay
-of mode lines.
+Like @code{set-buffer-modified-p}, but does not force redisplay of
+mode lines. This function also allows @var{flag}'s value to be
+the symbol @code{autosaved}, which marks the buffer as modified and
+auto-saved after the last modification.
@end defun
@deffn Command not-modified &optional arg
@@ -953,15 +957,64 @@ with a @code{nil} @var{norecord} argument since this may lead to
infinite recursion.
@end defvar
+@defun buffer-match-p condition buffer-or-name &optional arg
+This function checks if a buffer designated by @code{buffer-or-name}
+satisfies a @code{condition}. Optional third argument @var{arg} is
+passed to the predicate function in @var{condition}. A condition can
+be one of the following:
+@itemize @bullet{}
+@item
+A string, interpreted as a regular expression. The buffer
+satisfies the condition if the regular expression matches the buffer
+name.
+@item
+A predicate function, which should return non-@code{nil} if the buffer
+matches. If the function expects one argument, it is called with
+@var{buffer-or-name} as the argument; if it expects 2 arguments, the
+first argument is @var{buffer-or-name} and the second is @var{arg}
+(or @code{nil} if @var{arg} is omitted).
+@item
+A cons-cell @code{(@var{oper} . @var{expr})} where @var{oper} is one
+of
+@table @code
+@item not
+Satisfied if @var{expr} doesn't satisfy @code{buffer-match-p} with
+the same buffer and @code{arg}.
+@item or
+Satisfied if @var{expr} is a list and @emph{any} condition in
+@var{expr} satisfies @code{buffer-match-p}, with the same buffer and
+@code{arg}.
+@item and
+Satisfied if @var{expr} is a list and @emph{all} conditions in
+@var{expr} satisfy @code{buffer-match-p}, with the same buffer and
+@code{arg}.
+@item derived-mode
+Satisfied if the buffer's major mode derives from @var{expr}.
+@item major-mode
+Satisfied if the buffer's major mode is equal to @var{expr}. Prefer
+using @code{derived-mode} instead when both can work.
+@end table
+@end itemize
+@end defun
+
+@defun match-buffers condition &optional buffer-list arg
+This function returns a list of all buffers that satisfy a
+@code{condition}, as defined for @code{buffer-match-p}. By default
+all buffers are considered, but this can be restricted via the second
+optional @code{buffer-list} argument. Optional third argument
+@var{arg} will be used by @var{condition} in the same way as
+@code{buffer-match-p} does.
+@end defun
+
@node Creating Buffers
@section Creating Buffers
@cindex creating buffers
@cindex buffers, creating
This section describes the two primitives for creating buffers.
-@code{get-buffer-create} creates a buffer if it finds no existing buffer
-with the specified name; @code{generate-new-buffer} always creates a new
-buffer and gives it a unique name.
+@code{get-buffer-create} creates a buffer if it finds no existing
+buffer with the specified name; @code{generate-new-buffer} always
+creates a new buffer and gives it a unique name.
Both functions accept an optional argument @var{inhibit-buffer-hooks}.
If it is non-@code{nil}, the buffer they create does not run the hooks
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index fdbc05ce3d6..1718978a395 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -312,6 +312,25 @@ If @var{function} is an interactively callable function
specifies how to compute its arguments. Otherwise, the value is
@code{nil}. If @var{function} is a symbol, its function definition is
used.
+When called on an OClosure, the work is delegated to the generic
+function @code{oclosure-interactive-form}.
+@end defun
+
+@defun oclosure-interactive-form function
+Just like @code{interactive-form}, this function takes a command and
+returns its interactive form. The difference is that it is a generic
+function and it is only called when @var{function} is an OClosure.
+The purpose is to make it possible for some OClosure types to compute
+their interactive forms dynamically instead of carrying it in one of
+their slots.
+
+This is used for example for @code{kmacro} functions in order to
+reduce their memory size, since they all share the same interactive
+form. It is also used for @code{advice} functions, where the
+interactive form is computed from the interactive forms of its
+components, so as to make this computation more lazily and to
+correctly adjust the interactive form when one of its component's
+is redefined.
@end defun
@node Interactive Codes
@@ -878,6 +897,10 @@ keymaps. This command is the normal definition of @kbd{M-S-x}
(that's ``meta shift x'').
@end deffn
+Both these commands prompt for a command name, but with different
+completion rules. You can toggle between these two modes by using the
+@kbd{M-S-x} command while being prompted.
+
@node Distinguish Interactive
@section Distinguish Interactive Calls
@cindex distinguish interactive calls
@@ -1127,6 +1150,96 @@ frame, the value is the frame to which the event was redirected.
If the last event came from a keyboard macro, the value is @code{macro}.
@end defvar
+@cindex input devices
+@cindex device names
+Input events must come from somewhere; sometimes, that is a keyboard
+macro, a signal, or `unread-command-events', but it is usually a
+physical input device connected to a computer that is controlled by
+the user. Those devices are referred to as @dfn{input devices}, and
+Emacs associates each input event with the input device from which it
+originated. They are identified by a name that is unique to each
+input device.
+
+The ability to determine the precise input device used depends on the
+details of each system. When that information is unavailable, Emacs
+reports keyboard events as originating from the @samp{"Virtual core
+keyboard"}, and other events as originating from the @samp{"Virtual
+core pointer"}. (These values are used on every platform because the
+X server reports them when detailed device information is not known.)
+
+@defvar last-event-device
+This variable records the name of the input device from which the last
+input event read was generated. It is @code{nil} if no such device
+exists, i.e., the last input event was read from
+@code{unread-command-events}, or it came from a keyboard macro.
+
+When the X Input Extension is being used on X Windows, the device name
+is a string that is unique to each physical keyboard, pointing device
+and touchscreen attached to the X server. Otherwise, it is either the
+string @samp{"Virtual core pointer"} or @samp{"Virtual core
+keyboard"}, depending on whether the event was generated by a pointing
+device (such as a mouse) or a keyboard.
+@end defvar
+
+@defun device-class frame name
+There are various different types of devices, which can be determined
+from their names. This function can be used to determined the correct
+type of the device @var{name} for an event originating from
+@var{frame}.
+
+The return value is one of the following symbols (``device classes''):
+
+@table @code
+@item core-keyboard
+The core keyboard; this is means the device is a keyboard-like device,
+but no other characteristics are unknown.
+
+@item core-pointer
+The core pointer; this means the device is a pointing device, but no
+other characteristics are known.
+
+@item mouse
+A computer mouse.
+
+@item trackpoint
+A trackpoint or joystick (or other similar control.)
+
+@item eraser
+The other end of a stylus on a graphics tablet, or a standalone
+eraser.
+
+@item pen
+The pointed end of a pen on a graphics tablet, a stylus, or some other
+similar device.
+
+@item puck
+A device that looks like a computer mouse, but reports absolute
+coordinates relative to some other surface.
+
+@item power-button
+A power button or volume button (or other similar control.)
+
+@item keyboard
+A computer keyboard.
+
+@item touchscreen
+A computer touchpad.
+
+@item pad
+A collection of sensitive buttons, rings, and strips commonly found
+around a drawing tablet.
+
+@item touchpad
+An indirect touch device such as a touchpad.
+
+@item piano
+A musical instrument such as an electronic keyboard.
+
+@item test
+A device used by the XTEST extension to report input.
+@end table
+@end defun
+
@node Adjusting Point
@section Adjusting Point After Commands
@cindex adjusting point
@@ -2091,11 +2204,24 @@ wheel.
@vindex mouse-wheel-up-event
@vindex mouse-wheel-down-event
-This kind of event is generated only on some kinds of systems. On some
-systems, @code{mouse-4} and @code{mouse-5} are used instead. For
-portable code, use the variables @code{mouse-wheel-up-event} and
-@code{mouse-wheel-down-event} defined in @file{mwheel.el} to determine
-what event types to expect for the mouse wheel.
+This kind of event is generated only on some kinds of systems. On
+some systems, @code{mouse-4} and @code{mouse-5} are used instead. For
+portable code, use the variables @code{mouse-wheel-up-event},
+@code{mouse-wheel-up-alternate-event}, @code{mouse-wheel-down-event}
+and @code{mouse-wheel-down-alternate-event} defined in
+@file{mwheel.el} to determine what event types to expect for the mouse
+wheel.
+
+@vindex mouse-wheel-left-event
+@vindex mouse-wheel-right-event
+Similarly, some mice can generate @code{mouse-wheel-left-event} and
+@code{mouse-wheel-right-event} and can be used to scroll if
+@code{mouse-wheel-tilt-scroll} is non-@code{nil}. However, some mice
+also generate other events at the same time as they're generating
+these scroll events which may get in the way. The way to fix this is
+generally to unbind these events (for instance, @code{mouse-6} or
+@code{mouse-7}, but this is very hardware and operating system
+dependent).
@cindex @code{pinch} event
@item (pinch @var{position} @var{dx} @var{dy} @var{scale} @var{angle})
@@ -2139,19 +2265,29 @@ On X, @var{arg} is a string describing some text to place behind the
cursor. It can be @code{nil}, which means to remove any text
previously displayed.
-On PGTK, @var{arg} is a list of strings with color information. Its
-structure is as follows:
+On PGTK frames (@pxref{Frames}), @var{arg} is a list of strings with
+information about their color and underline attributes. It has the
+following form:
@example
- (
- (TEXT (ul . COLOR) (bg . COLOR) (fg . COLOR))
- ; ...
+@group
+ ((@var{string1}
+ (ul . @var{underline-color})
+ (bg . @var{background-color})
+ (fg . @var{foreground-color}))
+ (@var{string2}
+ (ul . @var{underline-color})
+ (bg . @var{background-color})
+ (fg . @var{foreground-color}))
+ @dots{}
)
+@end group
@end example
-Color information can be omitted. @code{COLOR} of @code{ul} can be
-@code{t} or a string. @var{arg} can be @code{nil}, which means to
-remove any text previously displayed.
+Color information can be omitted, leaving just the text of the
+strings. @var{underline-color} can be @code{t}, meaning underlined
+text with default underline color, or it can be a string, the name of
+the color to draw the underline.
This is a special event (@pxref{Special Events}), which normally
should not be bound by the user to any command. Emacs will typically
@@ -2494,7 +2630,7 @@ POSITION is assumed to lie in a window text area."
@end example
@end defun
-@defun posn-col-row position
+@defun posn-col-row position &optional use-window
This function returns a cons cell @w{@code{(@var{col} . @var{row})}},
containing the estimated column and row corresponding to buffer
position described by @var{position}. The return value is given in
@@ -2502,7 +2638,11 @@ units of the frame's default character width and default line height
(including spacing), as computed from the @var{x} and @var{y} values
corresponding to @var{position}. (So, if the actual characters have
non-default sizes, the actual row and column may differ from these
-computed values.)
+computed values.) If the optional @var{window} argument is
+non-@code{nil}, use the default character width in the window
+indicated by @var{position} instead of the frame. (This makes a
+difference if that window is showing a buffer with a non-default
+zooming level, for instance.)
Note that @var{row} is counted from the top of the text area. If the
window given by @var{position} possesses a header line (@pxref{Header
@@ -3073,7 +3213,7 @@ causes it to evaluate @code{help-form} and display the result. It
then continues to wait for a valid input character, or keyboard-quit.
@end defun
-@defun read-multiple-choice prompt choices &optional help-string show-help
+@defun read-multiple-choice prompt choices &optional help-string show-help long-form
Ask user a multiple choice question. @var{prompt} should be a string
that will be displayed as the prompt.
@@ -3092,6 +3232,11 @@ If optional argument @var{show-help} is non-@code{nil}, the help
buffer will be displayed immediately, before any user input. If it is
a string, use it as the name of the help buffer.
+If optional argument @var{long-form} is non-@code{nil}, the user
+will have to type in long-form answers (using @code{completing-read})
+instead of hitting a single key. The answers must be among the second
+elements of the values in the @var{choices} list.
+
The return value is the matching value from @var{choices}.
@lisp
@@ -3935,6 +4080,15 @@ what happens when a disabled command is invoked interactively.
Disabling a command has no effect on calling it as a function from Lisp
programs.
+@findex command-query
+ The value of the @code{disabled} property can also be a list where
+the first element is the symbol @code{query}. In that case, the user
+will be queried whether to execute the command. The second element in
+the list should be @code{nil} or non-@code{nil} to say whether to use
+@code{y-or-n-p} or @code{yes-or-no-p}, respectively, and the third
+element is the question to use. The @code{command-query} convenience
+function should be used to enable querying for a command.
+
@deffn Command enable-command command
Allow @var{command} (a symbol) to be executed without special
confirmation from now on, and alter the user's init file (@pxref{Init
diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi
index 2b6ec849d28..3670225dc49 100644
--- a/doc/lispref/compile.texi
+++ b/doc/lispref/compile.texi
@@ -61,7 +61,7 @@ Here is an example:
@group
(silly-loop 50000000)
-@result{} 10.235304117202759
+@result{} 5.200886011123657
@end group
@group
@@ -71,12 +71,12 @@ Here is an example:
@group
(silly-loop 50000000)
-@result{} 3.705854892730713
+@result{} 0.6239290237426758
@end group
@end example
- In this example, the interpreted code required 10 seconds to run,
-whereas the byte-compiled code required less than 4 seconds. These
+ In this example, the interpreted code required more than 5 seconds to run,
+whereas the byte-compiled code required less than 1 second. These
results are representative, but actual results may vary.
@node Compilation Functions
@@ -135,10 +135,10 @@ definition of @var{symbol} (@pxref{Byte-Code Objects}).
@group
(byte-compile 'factorial)
@result{}
-#[(integer)
- "^H\301U\203^H^@@\301\207\302^H\303^HS!\"\207"
- [integer 1 * factorial]
- 4 "Compute factorial of INTEGER."]
+#[257
+ "\211\300U\203^H^@@\300\207\211\301^BS!_\207"
+ [1 factorial] 4
+ "Compute factorial of INTEGER.\n\n(fn INTEGER)"]
@end group
@end example
@@ -688,11 +688,11 @@ Lisp source; these do not appear in the output of @code{disassemble}.
(disassemble 'factorial)
@print{} byte-code for factorial:
doc: Compute factorial of an integer.
- args: (integer)
+ args: (arg1)
@end group
@group
-0 varref integer ; @r{Get the value of @code{integer} and}
+0 dup ; @r{Get the value of @code{integer} and}
; @r{push it onto the stack.}
1 constant 1 ; @r{Push 1 onto stack.}
@end group
@@ -707,9 +707,9 @@ Lisp source; these do not appear in the output of @code{disassemble}.
7 return ; @r{Return the top element of the stack.}
@end group
@group
-8:1 varref integer ; @r{Push value of @code{integer} onto stack.}
+8:1 dup ; @r{Push value of @code{integer} onto stack.}
9 constant factorial ; @r{Push @code{factorial} onto stack.}
-10 varref integer ; @r{Push value of @code{integer} onto stack.}
+10 stack-ref 2 ; @r{Push value of @code{integer} onto stack.}
11 sub1 ; @r{Pop @code{integer}, decrement value,}
; @r{push new value onto stack.}
12 call 1 ; @r{Call function @code{factorial} using first}
@@ -717,9 +717,9 @@ Lisp source; these do not appear in the output of @code{disassemble}.
; @r{push returned value onto stack.}
@end group
@group
-13 mult ; @r{Pop top two values off stack, multiply}
+13 mult ; @r{Pop top two values off stack, multiply}
; @r{them, and push result onto stack.}
-14 return ; @r{Return the top element of the stack.}
+14 return ; @r{Return the top element of the stack.}
@end group
@end example
@@ -740,7 +740,7 @@ The @code{silly-loop} function is somewhat more complex:
(disassemble 'silly-loop)
@print{} byte-code for silly-loop:
doc: Return time before and after N iterations of a loop.
- args: (n)
+ args: (arg1)
@end group
@group
@@ -749,24 +749,21 @@ The @code{silly-loop} function is somewhat more complex:
@end group
@group
1 call 0 ; @r{Call @code{current-time-string} with no}
- ; @r{argument, push result onto stack.}
+ ; @r{argument, push result onto stack as @code{t1}.}
@end group
@group
-2 varbind t1 ; @r{Pop stack and bind @code{t1} to popped value.}
-@end group
-@group
-3:1 varref n ; @r{Get value of @code{n} from the environment}
+2:1 stack-ref 1 ; @r{Get value of the argument @code{n}}
; @r{and push the value on the stack.}
-4 sub1 ; @r{Subtract 1 from top of stack.}
+3 sub1 ; @r{Subtract 1 from top of stack.}
@end group
@group
-5 dup ; @r{Duplicate top of stack; i.e., copy the top}
+4 dup ; @r{Duplicate top of stack; i.e., copy the top}
; @r{of the stack and push copy onto stack.}
-6 varset n ; @r{Pop the top of the stack,}
- ; @r{and bind @code{n} to the value.}
+5 stack-set 3 ; @r{Pop the top of the stack,}
+ ; @r{and set @code{n} to the value.}
-;; @r{(In effect, the sequence @code{dup varset} copies the top of the stack}
-;; @r{into the value of @code{n} without popping it.)}
+;; @r{(In effect, the sequence @code{dup stack-set} copies the top of}
+;; @r{the stack into the value of @code{n} without popping it.)}
@end group
@group
@@ -781,16 +778,15 @@ The @code{silly-loop} function is somewhat more complex:
; @r{else continue.}
@end group
@group
-12 varref t1 ; @r{Push value of @code{t1} onto stack.}
+12 dup ; @r{Push value of @code{t1} onto stack.}
13 constant current-time-string ; @r{Push @code{current-time-string}}
; @r{onto the top of the stack.}
14 call 0 ; @r{Call @code{current-time-string} again.}
@end group
@group
-15 unbind 1 ; @r{Unbind @code{t1} in local environment.}
-16 list2 ; @r{Pop top two elements off stack, create a}
+15 list2 ; @r{Pop top two elements off stack, create a}
; @r{list of them, and push it onto stack.}
-17 return ; @r{Return value of the top of stack.}
+16 return ; @r{Return value of the top of stack.}
@end group
@end example
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 634d46a7854..d4520ebdee5 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -525,7 +525,7 @@ core pattern can have the following forms:
@table @code
-@item _
+@item _@r{ (underscore)}
Matches any @var{expval}.
This is also known as @dfn{don't care} or @dfn{wildcard}.
@@ -629,7 +629,10 @@ Attempts to match @var{pattern1}, @var{pattern2}, @dots{}, in order,
until one of them succeeds. In that case, @code{or} likewise matches,
and the rest of the sub-patterns are not tested.
-To present a consistent environment (@pxref{Intro Eval})
+To present a consistent environment
+@ifnottex
+(@pxref{Intro Eval})
+@end ifnottex
to @var{body-forms} (thus avoiding an evaluation error on match),
the set of variables bound by the pattern is the union of the
variables bound by each sub-pattern. If a variable is not bound by
@@ -1326,6 +1329,20 @@ Assign values to variables in a @code{setq} form, destructuring each
@var{value} according to its respective @var{pattern}.
@end defmac
+@defmac pcase-lambda lambda-list &rest body
+This is like @code{lambda}, but allows each argument to be a pattern.
+For instance, here's a simple function that takes a cons cell as the
+argument:
+
+@example
+(setq fun
+ (pcase-lambda (`(,key . ,val))
+ (vector key (* val 10))))
+(funcall fun '(foo . 2))
+ @result{} [foo 20]
+@end example
+@end defmac
+
@node Iteration
@section Iteration
@cindex iteration
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 54059d7b6ed..528421bf3b4 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -376,7 +376,7 @@ name) and the new value, and should do whatever is necessary to update
the value properly for this option (which may not mean simply setting
the option as a Lisp variable); preferably, though, it should not
modify its value argument destructively. The default for
-@var{setfunction} is @code{set-default}.
+@var{setfunction} is @code{set-default-toplevel-value}.
If you specify this keyword, the variable's documentation string
should describe how to do the same job in hand-written Lisp code.
@@ -387,7 +387,7 @@ Specify @var{getfunction} as the way to extract the value of this
option. The function @var{getfunction} should take one argument, a
symbol, and should return whatever customize should use as the
current value for that symbol (which need not be the symbol's Lisp
-value). The default is @code{default-value}.
+value). The default is @code{default-toplevel-value}.
You have to really understand the workings of Custom to use
@code{:get} correctly. It is meant for values that are treated in
@@ -409,11 +409,11 @@ do not reinitialize it if it is already non-void.
@item custom-initialize-default
Like @code{custom-initialize-set}, but use the function
-@code{set-default} to set the variable, instead of the variable's
-@code{:set} function. This is the usual choice for a variable whose
-@code{:set} function enables or disables a minor mode; with this choice,
-defining the variable will not call the minor mode function, but
-customizing the variable will do so.
+@code{set-default-toplevel-value} to set the variable, instead of the
+variable's @code{:set} function. This is the usual choice for a
+variable whose @code{:set} function enables or disables a minor mode;
+with this choice, defining the variable will not call the minor mode
+function, but customizing the variable will do so.
@item custom-initialize-reset
Always use the @code{:set} function to initialize the variable. If
@@ -424,7 +424,7 @@ This is the default @code{:initialize} function.
@item custom-initialize-changed
Use the @code{:set} function to initialize the variable, if it is
already set or has been customized; otherwise, just use
-@code{set-default}.
+@code{set-default-toplevel-value}.
@item custom-initialize-delay
This function behaves like @code{custom-initialize-set}, but it
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 469ff2d943d..058c9319544 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -196,6 +196,17 @@ echo area. For example, this can be useful when trying to find the
cause of a particular message.
@end defvar
+@defvar debug-allow-recursive-debug
+You can evaluate forms in the current stack frame in the
+@samp{*Backtrace*} buffer with the @key{e} command, and while
+edebugging you can use the @key{e} and @key{C-x C-e} commands to do
+something similar. By default, the debugger is inhibited by these
+commands (because (re-)entering the debugger at this point will
+usually take you out of the debugging context you're in). Set
+@code{debug-allow-recursive-debug} to a non-@code{nil} value to allow
+these commands to enter the debugger recursively.
+@end defvar
+
To debug an error that happens during loading of the init
file, use the option @samp{--debug-init}. This binds
@code{debug-on-error} to @code{t} while loading the init file, and
@@ -387,11 +398,9 @@ possibilities.)
variable is temporarily set according to
@code{eval-expression-debug-on-error}. If the latter variable is
non-@code{nil}, @code{debug-on-error} will temporarily be set to
-@code{t}. This means that any further errors that occur while doing a
-debugging session will (by default) trigger another backtrace. If
-this is not what you want, you can either set
-@code{eval-expression-debug-on-error} to @code{nil}, or set
-@code{debug-on-error} to @code{nil} in @code{debugger-mode-hook}.
+@code{t}. However, further errors that occur while debugging won't
+(by default) trigger another debugger, because @code{inhibit-debugger}
+will also be bound to non-@code{nil}.
The debugger itself must be run byte-compiled, since it makes
assumptions about the state of the Lisp interpreter. These
@@ -522,6 +531,7 @@ Flag the current frame like @kbd{b}. Then continue execution like
@kbd{c}, but temporarily disable break-on-entry for all functions that
are set up to do so by @code{debug-on-entry}.
+@vindex debug-allow-recursive-debug
@item e
Read a Lisp expression in the minibuffer, evaluate it (with the
relevant lexical environment, if applicable), and print the
@@ -530,7 +540,11 @@ variables, and the current buffer, as part of its operation; @kbd{e}
temporarily restores their values from outside the debugger, so you can
examine and change them. This makes the debugger more transparent. By
contrast, @kbd{M-:} does nothing special in the debugger; it shows you
-the variable values within the debugger.
+the variable values within the debugger. By default, this command
+suppresses the debugger during evaluation, so that an error in the
+evaluated expression won't add a new error on top of the existing one.
+Set the @code{debug-allow-recursive-debug} user option to a
+non-@code{nil} value to override this.
@item R
Like @kbd{e}, but also save the result of evaluation in the
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 4bc7884e9ed..08bf7441df0 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -336,7 +336,10 @@ functions call it with no arguments when their argument message is
Usually this function is called when the next input event arrives
after displaying an echo-area message. The function is expected to
clear the message displayed by its counterpart function specified by
-@code{set-message-function}.
+@code{set-message-function}, but doesn't have to. If the function
+wants the echo area to remain uncleared, it should return the symbol
+@code{dont-clear-message}; any other value will result in the echo
+area being cleared.
The default value is the function that clears the message displayed in
an active minibuffer.
@@ -612,6 +615,16 @@ how to display a message and prevent it from being logged:
@end example
@end defopt
+@defvar messages-buffer-name
+This variable has the name of the buffer where messages should be
+logged to, and defaults to @file{*Messages*}. Some packages may find
+it useful to temporarily redirect the output to a different buffer
+(perhaps to write the buffer out to a log file later), and they can
+bind this variable to a different buffer name. (Note that this buffer
+(if it doesn't exist already), will be created and put into
+@code{messages-buffer-mode}.)
+@end defvar
+
To make @file{*Messages*} more convenient for the user, the logging
facility combines successive identical messages. It also combines
successive related messages for the sake of two cases: question
@@ -1997,6 +2010,11 @@ Tables}). The width of a tab character is usually @code{tab-width}
(@pxref{Usual Display}).
@end defun
+@defun char-uppercase-p char
+Return non-@code{nil} if @var{char} is an uppercase character
+according to Unicode.
+@end defun
+
@defun string-width string &optional from to
This function returns the width in columns of the string @var{string},
if it were displayed in the current buffer and the selected window.
@@ -2132,7 +2150,7 @@ the buffer might contain long lines that will be truncated anyway.
The optional argument @var{y-limit}, if non-@code{nil}, specifies the
maximum Y coordinate beyond which text is to be ignored; it is
therefore also the maximum pixel-height that the function can return.
-If @var{y-limit} is nil or omitted, it means to considers all the
+If @var{y-limit} is @code{nil} or omitted, it means to consider all the
lines of text till the buffer position specified by @var{to}. Since
calculating the pixel-height of a large buffer can take some time, it
makes sense to specify this argument; in particular, if the caller
@@ -2456,6 +2474,7 @@ Otherwise, it returns @code{nil}.
The following table lists all the face attributes, their possible
values, and their effects.
+@cindex unspecified, face attribute value
Apart from the values given below, each face attribute can have the
value @code{unspecified}. This special value means that the face
doesn't specify that attribute directly. An @code{unspecified}
@@ -2464,7 +2483,13 @@ description @code{:inherit} attribute below); or, failing that, to an
underlying face (@pxref{Displaying Faces}). (However,
@code{unspecified} is not a valid value in @code{defface}.)
- The @code{default} face must specify all attributes.
+@cindex reset, face attribute value
+ A face attribute can also have the value @code{reset}. This special
+value stands for the value of the corresponding attribute of the
+@code{default} face.
+
+ The @code{default} face must explicitly specify all attributes, and
+cannot use the special value @code{reset}.
Some of these attributes are meaningful only on certain kinds of
displays. If your display cannot handle a certain attribute, the
@@ -2555,13 +2580,16 @@ Underline with the foreground color of the face.
@item @var{color}
Underline in color @var{color}, a string specifying a color.
-@item @code{(:color @var{color} :style @var{style})}
+@item @code{(:color @var{color} :style @var{style} :position @var{position})}
@var{color} is either a string, or the symbol @code{foreground-color},
meaning the foreground color of the face. Omitting the attribute
@code{:color} means to use the foreground color of the face.
@var{style} should be a symbol @code{line} or @code{wave}, meaning to
use a straight or wavy line. Omitting the attribute @code{:style}
-means to use a straight line.
+means to use a straight line. @var{position}, if non-nil, means to
+display the underline at the descent of the text, instead of at the
+baseline level. If it is a number, then it specifies the amount of
+pixels above the descent to display the underline.
@end table
@cindex overlined text
@@ -2641,9 +2669,10 @@ used automatically to handle certain shades of gray.
@item :font
The font used to display the face. Its value should be a font object
-or a fontset. @xref{Low-Level Font}, for information about font
-objects, font specs, and font entities. @xref{Fontsets}, for
-information about fontsets.
+or a fontset. If it is a font object, it specifies the font to be
+used by the face for displaying ASCII characters. @xref{Low-Level
+Font}, for information about font objects, font specs, and font
+entities. @xref{Fontsets}, for information about fontsets.
@anchor{face-font-attribute}
When specifying this attribute using @code{set-face-attribute} or
@@ -2684,6 +2713,13 @@ doesn't specify an explicit value for a face, the value from the
original face definition by @code{defface} is inherited
(@pxref{Defining Faces}).
+Some modes, like @code{hl-line-mode}, use a face with an
+@code{:extend} property to mark the entire current line. Note,
+however, that Emacs will always allow you to move point after the
+final character in a buffer, and if the buffer ends with a newline
+character, point can be placed on what is seemingly a line at the end
+of the buffer---but Emacs can't highlight that ``line'', because it
+doesn't really exist.
@end table
@defun font-family-list &optional frame
@@ -2802,7 +2838,7 @@ apply to. Here are the possible values of @var{characteristic}:
The kind of window system the terminal uses---either @code{graphic}
(any graphics-capable display), @code{x}, @code{pc} (for the MS-DOS
console), @code{w32} (for MS Windows 9X/NT/2K/XP), @code{haiku} (for
-Haiku), @code{pgtk} (for GTK), or @code{tty} (a non-graphics-capable
+Haiku), @code{pgtk} (for pure GTK), or @code{tty} (a non-graphics-capable
display). @xref{Window Systems, window-system}.
@item class
@@ -2910,7 +2946,8 @@ modifying the attributes of a named face.
@defun face-attribute face attribute &optional frame inherit
This function returns the value of the @var{attribute} attribute for
-@var{face} on @var{frame}.
+@var{face} on @var{frame}. @xref{Face Attributes}, for the supported
+attributes.
If @var{frame} is omitted or @code{nil}, that means the selected frame
(@pxref{Input Focus}). If @var{frame} is @code{t}, this function
@@ -2993,7 +3030,8 @@ for all frames. This function is mostly intended for internal usage.
@defun set-face-attribute face frame &rest arguments
This function sets one or more attributes of @var{face} for
@var{frame}. The attributes specified in this way override the face
-spec(s) belonging to @var{face}.
+spec(s) belonging to @var{face}. @xref{Face Attributes}, for the
+supported attributes.
The extra arguments @var{arguments} specify the attributes to set, and
the values for them. They should consist of alternating attribute
@@ -3007,12 +3045,21 @@ names (such as @code{:family} or @code{:underline}) and values. Thus,
sets the attribute @code{:weight} to @code{bold} and the attribute
@code{:slant} to @code{italic}.
-
If @var{frame} is @code{t}, this function sets the default attributes
for newly created frames; they will effectively override the attribute
values specified by @code{defface}. If @var{frame} is @code{nil},
this function sets the attributes for all existing frames, as well as
-for newly created frames.
+for newly created frames. However, if you want to @emph{reset} the
+value of an attribute to @code{unspecified} in a way that also affects
+newly created frames, you @emph{must} explicitly call this function
+with @var{frame} set to @code{t} and the value of the attribute set to
+@code{unspecified} (@emph{not} @code{nil}!@:), in addition to the call
+with @var{frame} set to @code{nil}. This is because the default
+attributes for newly created frames are merged with the face's spec in
+@code{defface} when a new frame is created, and so having
+@code{unspecified} in the default attributes for new frames will be
+unable to override @code{defface}; the special call to this function
+as described above will arrange for @code{defface} to be overridden.
@end defun
The following commands and functions mostly provide compatibility
@@ -3087,13 +3134,19 @@ return value is always specified, use a value of @code{default} for
@var{inherit}.
@defun face-font face &optional frame character
-This function returns the name of the font of face @var{face}.
+This function returns the name of the font used by the specified
+@var{face}.
If the optional argument @var{frame} is specified, it returns the name
-of the font of @var{face} for that frame. If @var{frame} is omitted or
-@code{nil}, the selected frame is used. In the latter case, if the
-optional third argument @var{character} is supplied, it returns the font
-name used for @var{character}.
+of the font of @var{face} for that frame; @var{frame} defaults to the
+selected frame if it is @code{nil} or omitted. If @var{frame} is
+@code{t}, the function reports on the font defaults for @var{face} to
+be used for new frames.
+
+By default, the returned font is for displaying ASCII characters, but
+if @var{frame} is anything but @code{t}, and the optional third
+argument @var{character} is supplied, the function returns the font
+name used by @var{face} for that character.
@end defun
@defun face-foreground face &optional frame inherit
@@ -3283,10 +3336,10 @@ and @code{face-remap-reset-base} functions; it is intended for major
modes to remap faces in the buffers they control.
@defun face-remap-add-relative face &rest specs
-This function adds the face spec in @var{specs} as relative
-remappings for face @var{face} in the current buffer. The remaining
-arguments, @var{specs}, should form either a list of face names, or a
-property list of attribute/value pairs.
+This function adds @var{specs} as relative remappings for face
+@var{face} in the current buffer. @var{specs} should be a list where
+each element is either a face name, or a property list of
+attribute/value pairs.
The return value is a Lisp object that serves as a cookie; you can
pass this object as an argument to @code{face-remap-remove-relative}
@@ -3300,6 +3353,16 @@ if you need to remove the remapping later.
;; Increase the size of the 'default' face by 50%:
(face-remap-add-relative 'default :height 1.5)
@end example
+
+Note that buffer-local face remapping does not work reliably for
+parent faces of basic faces (@pxref{Basic Faces}). (These are the
+faces that are used in mode lines, header lines, and other basic
+decorations of windows and frames.) For instance,
+@code{mode-line-inactive} inherits from @code{mode-line}, but
+remapping @code{mode-line} won't normally have the desired effect on
+@code{mode-line-inactive}, especially if done locally for some
+buffers. Instead you have to remap @code{mode-line-inactive}
+directly.
@end defun
@defun face-remap-remove-relative cookie
@@ -3425,10 +3488,10 @@ usually assign faces to around 400 to 600 characters at each call.
If your Emacs Lisp program needs to assign some faces to text, it is
often a good idea to use certain existing faces or inherit from them,
rather than defining entirely new faces. This way, if other users
-have customized the basic faces to give Emacs a certain look, your
-program will fit in without additional customization.
+have customized those existing faces to give Emacs a certain look,
+your program will fit in without additional customization.
- Some of the basic faces defined in Emacs are listed below. In
+ Some of the @dfn{basic faces} defined in Emacs are listed below. In
addition to these, you might want to make use of the Font Lock faces
for syntactic highlighting, if highlighting is not already handled by
Font Lock mode, or if some Font Lock faces are not in use.
@@ -3440,6 +3503,28 @@ The default face, whose attributes are all specified. All other faces
implicitly inherit from it: any unspecified attribute defaults to the
attribute on this face (@pxref{Face Attributes}).
+@item mode-line-active
+@itemx mode-line-inactive
+@itemx header-line
+@itemx tab-line
+Basic faces used for the mode line, header line, and tab line.
+
+@item tool-bar
+@itemx tab-bar
+@itemx fringe
+@itemx scroll-bar
+@itemx window-divider
+@itemx border
+@itemx child-frame-border
+Basic faces used for the corresponding decorations of GUI frames.
+
+@item cursor
+The basic face used for the text cursor.
+
+@item mouse
+The basic face used for displaying mouse-sensitive text when the mouse
+pointer is on that text.
+
@item bold
@itemx italic
@itemx bold-italic
@@ -3746,57 +3831,62 @@ Then, the font specifications for all but Chinese GB2312 characters have
Chinese GB2312 characters has a wild card @samp{*} in the @var{family}
field.
-@defun set-fontset-font name character font-spec &optional frame add
-This function modifies the existing fontset @var{name} to use the font
-matching with @var{font-spec} for the specified @var{character}.
+@defun set-fontset-font fontset characters font-spec &optional frame add
+This function modifies the existing @var{fontset} to use the font
+specified by @var{font-spec} for displaying the specified
+@var{characters}.
-If @var{name} is @code{nil}, this function modifies the fontset of the
-selected frame or that of @var{frame} if @var{frame} is not
+If @var{fontset} is @code{nil}, this function modifies the fontset of
+the selected frame or that of @var{frame} if @var{frame} is not
@code{nil}.
-If @var{name} is @code{t}, this function modifies the default
-fontset, whose short name is @samp{fontset-default}.
+If @var{fontset} is @code{t}, this function modifies the default
+fontset, whose short name as a string is @samp{fontset-default}.
-In addition to specifying a single codepoint, @var{character} may be a
-cons @code{(@var{from} . @var{to})}, where @var{from} and @var{to} are
-character codepoints. In that case, use @var{font-spec} for all the
-characters in the range @var{from} and @var{to} (inclusive).
+The @var{characters} argument can be a single character which should
+be displayed using @var{font-spec}. It can also be a cons cell
+@w{@code{(@var{from} . @var{to})}}, where @var{from} and @var{to} are
+characters. In that case, use @var{font-spec} for all the characters
+in the range @var{from} and @var{to} (inclusive).
-@var{character} may be a charset (@pxref{Character Sets}). In that
-case, use @var{font-spec} for all the characters in the charset.
+@var{characters} may be a charset symbol (@pxref{Character Sets}). In
+that case, use @var{font-spec} for all the characters in the charset.
-@var{character} may be a script name (@pxref{Character Properties,
+@var{characters} may be a script symbol (@pxref{Character Properties,
char-script-table}). In that case, use @var{font-spec} for all the
characters belonging to the script.
-@var{character} may be @code{nil}, which means to use @var{font-spec}
-for any character which no font-spec is specified.
+@var{characters} may be @code{nil}, which means to use @var{font-spec}
+for any character in @var{fontset} for which no font-spec is
+specified.
@var{font-spec} may be a font-spec object created by the function
@code{font-spec} (@pxref{Low-Level Font}).
-@var{font-spec} may be a cons; @code{(@var{family} . @var{registry})},
-where @var{family} is a family name of a font (possibly including a
-foundry name at the head), @var{registry} is a registry name of a font
-(possibly including an encoding name at the tail).
+@var{font-spec} may be a cons cell @w{@code{(@var{family}
+. @var{registry})}}, where @var{family} is a family name of a font
+(possibly including a foundry name at the head), and @var{registry} is
+a registry name of a font (possibly including an encoding name at the
+tail).
@var{font-spec} may be a font name, a string.
@var{font-spec} may be @code{nil}, which explicitly specifies that
-there's no font for the specified @var{character}. This is useful,
+there's no font for the specified @var{characters}. This is useful,
for example, to avoid expensive system-wide search for fonts for
characters that have no glyphs, like those from the Unicode Private
Use Area (PUA).
The optional argument @var{add}, if non-@code{nil}, specifies how to
-add @var{font-spec} to the font specifications previously set. If it
-is @code{prepend}, @var{font-spec} is prepended. If it is
-@code{append}, @var{font-spec} is appended. By default,
-@var{font-spec} overrides the previous settings.
+add @var{font-spec} to the font specifications previously set for
+@var{characters}. If it is @code{prepend}, @var{font-spec} is
+prepended to the existing specs. If it is @code{append},
+@var{font-spec} is appended. By default, @var{font-spec} overwrites
+the previously set font specs.
-For instance, this changes the default fontset to use a font of which
+For instance, this changes the default fontset to use a font whose
family name is @samp{Kochi Gothic} for all characters belonging to
-the charset @code{japanese-jisx0208}.
+the charset @code{japanese-jisx0208}:
@smallexample
(set-fontset-font t 'japanese-jisx0208
@@ -3936,13 +4026,26 @@ required; and @code{gpos} is a list of OpenType GPOS feature tag
symbols, or @code{nil} if none is required. If @code{gsub} or
@code{gpos} is a list, a @code{nil} element in that list means that
the font must not match any of the remaining tag symbols. The
-@code{gpos} element may be omitted.
+@code{gpos} element may be omitted. For the list of OpenType script,
+language, and feature tags, see
+@uref{https://docs.microsoft.com/en-us/typography/opentype/spec/ttoreg,
+the list of registered OTF tags}.
+
+@item :type
+@cindex font backend
+The symbol that specifies the @dfn{font backend} used to draw the
+characters. The possible values depend on the platform and on how
+Emacs was configured at build time. Typical values include
+@code{ftcrhb} and @code{xfthb} on X, @code{harfbuzz} on MS-Windows,
+@code{ns} on GNUstep, etc. It can also be @code{nil} if left
+unspecified, typically in a font-spec.
@end table
@end defun
@defun font-put font-spec property value
Set the font property @var{property} in the font-spec @var{font-spec}
-to @var{value}.
+to @var{value}. The @var{property} can any of the ones described
+above.
@end defun
@cindex font entity
@@ -3986,12 +4089,28 @@ object, a font entity, or a font spec.
@defun font-get font property
This function returns the value of the font property @var{property}
-for @var{font}.
+for @var{font}. The @var{property} can any of the ones that
+@code{font-spec} supports.
If @var{font} is a font spec and the font spec does not specify
@var{property}, the return value is @code{nil}. If @var{font} is a
font object or font entity, the value for the @var{:script} property
-may be a list of scripts supported by the font.
+may be a list of scripts supported by the font, and the value of the
+@code{:otf} property is a cons of the form @w{@code{(@var{gsub}
+. @var{gpos})}}, where @var{gsub} and @var{gpos} are lists
+representing OpenType features supported by the font, of the form
+
+@smallexample
+((@var{script-tag} (@var{langsys-tag} @var{feature}@dots{}) @dots{}) @dots{})
+@end smallexample
+
+@noindent where @var{script-tag}, @var{langsys-tag}, and @var{feature}
+are symbols representing OpenType layout tags.
+
+If @var{font} is a font object, the special property
+@code{:combining-capability} is non-@code{nil} if the font backend of
+@var{font} supports rendering of combining characters for non-OpenType
+fonts.
@end defun
@defun font-face-attributes font &optional frame
@@ -4581,14 +4700,15 @@ about to be executed. This feature has nothing to do with
@defvar overlay-arrow-string
This variable holds the string to display to call attention to a
particular line, or @code{nil} if the arrow feature is not in use.
-On a graphical display the contents of the string are ignored; instead a
-glyph is displayed in the fringe area to the left of the display area.
+On a graphical display the contents of the string are ignored if the
+left fringe is shown; instead a glyph is displayed in the fringe area
+to the left of the display area.
@end defvar
@defvar overlay-arrow-position
This variable holds a marker that indicates where to display the overlay
arrow. It should point at the beginning of a line. On a non-graphical
-display the arrow text
+display, or when the left fringe is not shown, the arrow text
appears at the beginning of that line, overlaying any text that would
otherwise appear. Since the arrow is usually short, and the line
usually begins with indentation, normally nothing significant is
@@ -4620,11 +4740,12 @@ this list.
Each variable on this list can have properties
@code{overlay-arrow-string} and @code{overlay-arrow-bitmap} that
-specify an overlay arrow string (for text terminals) or fringe bitmap
-(for graphical terminals) to display at the corresponding overlay
-arrow position. If either property is not set, the default
-@code{overlay-arrow-string} or @code{overlay-arrow} fringe indicator
-is used.
+specify an overlay arrow string (for text terminals or graphical
+terminals without the left fringe shown) or fringe bitmap
+(for graphical terminals with a left fringe) to display at the
+corresponding overlay arrow position. If either property is not set,
+the default @code{overlay-arrow-string} or @code{overlay-arrow} fringe
+indicator is used.
@node Scroll Bars
@@ -4950,7 +5071,7 @@ which are evaluated at display time. This could be unsafe in certain
situations, e.g., when the display specification was generated by some
external program/agent. Wrapping a display specification in a list
that begins with the special symbol @code{disable-eval}, as in
-@w{@code{('disable-eval @var{spec})}}, will disable evaluation of any
+@w{@code{(disable-eval @var{spec})}}, will disable evaluation of any
Lisp in @var{spec}, while still supporting all the other display
property features.
@@ -5226,7 +5347,7 @@ is partitioned using the identity of the parameter, which is why the
parameter is a list with one element. For instance:
@lisp
-(insert (propertize "foo" '(display (min-width (6.0)))))
+(insert (propertize "foo" 'display '(min-width (6.0))))
@end lisp
This will add padding after @samp{foo} bringing the total width up to
@@ -5444,6 +5565,12 @@ symbol}. The symbols for the above formats are, respectively,
@code{pbm}, @code{xbm}, @code{xpm}, @code{gif}, @code{jpeg},
@code{tiff}, @code{png}, @code{svg}, and @code{webp}.
+ On some platforms, the built-in image support that doesn't require
+any optional libraries includes BMP images.@footnote{
+On MS-Windows, this requires @code{w32-use-native-image-API} to be set
+non-@code{nil}.
+}
+
Furthermore, if you build Emacs with ImageMagick
(@code{libMagickWand}) support, Emacs can display any image format
that ImageMagick can. @xref{ImageMagick Images}. All images
@@ -5597,6 +5724,12 @@ are supported, unless the image type is @code{imagemagick}. Positive
values rotate clockwise, negative values counter-clockwise. Rotation
is performed after scaling and cropping.
+@item :flip @var{flip}
+If this is @code{t}, the image will be horizontally flipped.
+Currently it has no effect if the image type is @code{imagemagick}.
+Vertical flipping can be achieved by rotating the image 180 degrees
+and toggling this value.
+
@item :transform-smoothing @var{smooth}
If this is @code{t}, any image transform will have smoothing applied;
if @code{nil}, no smoothing will be applied. The exact algorithm used
@@ -5810,13 +5943,10 @@ There are three formats you can use for @var{data}:
@itemize @bullet
@item
A vector of strings or bool-vectors, each specifying one line of the
-image. Do specify @code{:height} and @code{:width}.
+image. Do specify @code{:data-height} and @code{:data-width}.
@item
A string containing the same byte sequence as an XBM file would contain.
-You must not specify @code{:height} and @code{:width} in this case,
-because omitting them is what indicates the data has the format of an
-XBM file. The file contents specify the height and width of the image.
@item
A string or a bool-vector containing the bits of the image (plus
@@ -5824,26 +5954,11 @@ perhaps some extra bits at the end that will not be used). It should
contain at least @w{@code{@var{stride} * @var{height}}} bits, where
@var{stride} is the smallest multiple of 8 greater than or equal to
the width of the image. In this case, you should specify
-@code{:height}, @code{:width} and @code{:stride}, both to indicate
-that the string contains just the bits rather than a whole XBM file,
-and to specify the size of the image.
+@code{:data-height}, @code{:data-width} and @code{:stride}, both to
+indicate that the string contains just the bits rather than a whole
+XBM file, and to specify the size of the image.
@end itemize
-@item :width @var{width}
-The value, @var{width}, specifies the width of the image, in pixels.
-
-@item :height @var{height}
-The value, @var{height}, specifies the height of the image, in pixels.
-
-Note that @code{:width} and @code{:height} can only be used if passing
-in data that doesn't specify the width and height (e.g., a string or a
-vector containing the bits of the image). @acronym{XBM} files usually
-specify this themselves, and it's an error to use these two properties
-on these files. Also note that @code{:width} and @code{:height} are
-used by most other image formats to specify what the displayed image
-is supposed to be, which usually means performing some sort of
-scaling. This isn't supported for @acronym{XBM} images.
-
@item :stride @var{stride}
The number of bool vector entries stored for each row; the smallest
multiple of 8 greater than or equal to @var{width}.
@@ -6616,7 +6731,9 @@ buffer's text.
The argument @var{slice} specifies a slice of the image to insert. If
@var{slice} is @code{nil} or omitted the whole image is inserted.
-Otherwise, @var{slice} is a list @code{(@var{x} @var{y} @var{width}
+(However, note that images are chopped on display at the window's
+right edge, because wrapping images is not supported.) Otherwise,
+@var{slice} is a list @code{(@var{x} @var{y} @var{width}
@var{height})} which specifies the @var{x} and @var{y} positions and
@var{width} and @var{height} of the image area to insert. Integer
values are in units of pixels. A floating-point number in the range
@@ -7297,7 +7414,7 @@ current buffer, and returns it.
@end defun
@defun insert-button label &rest properties
-This insert a button with the label @var{label} at point,
+This inserts a button with the label @var{label} at point,
and returns it.
@end defun
@@ -7446,7 +7563,7 @@ end of the buffer continues from the other end. If
@var{display-message} is non-@code{nil}, the button's help-echo string
is displayed. Any button with a non-@code{nil} @code{skip} property
is skipped over. Returns the button found, and signals an error if no
-buttons can be found. If @var{no-error} is non-@code{nil}, return nil
+buttons can be found. If @var{no-error} is non-@code{nil}, return @code{nil}
instead of signaling the error.
@end deffn
@@ -7458,7 +7575,7 @@ end of the buffer continues from the other end. If
@var{display-message} is non-@code{nil}, the button's help-echo string
is displayed. Any button with a non-@code{nil} @code{skip} property
is skipped over. Returns the button found, and signals an error if no
-buttons can be found. If @var{no-error} is non-@code{nil}, return nil
+buttons can be found. If @var{no-error} is non-@code{nil}, return @code{nil}
instead of signaling the error.
@end deffn
@@ -8104,7 +8221,10 @@ help buffer.
The window's display table, if there is one, takes precedence over the
buffer's display table. If neither exists, Emacs tries to use the
standard display table; if that is @code{nil}, Emacs uses the usual
-character display conventions (@pxref{Usual Display}).
+character display conventions (@pxref{Usual Display}). (Emacs does
+not ``merge'' display tables: For instance, if the window has a
+display table, the buffer's display table and the standard display
+table are completely ignored.)
Note that display tables affect how the mode line is displayed, so
if you want to force redisplay of the mode line using a new display
@@ -8210,7 +8330,7 @@ there is no available font (on a graphical display), and characters
which cannot be encoded by the terminal's coding system (on a text
terminal).
-@vindex glyphless-display-mode
+@findex glyphless-display-mode
The @code{glyphless-display-mode} minor mode can be used to toggle
displaying glyphless characters in a convenient manner in the current
buffer. If this mode is enabled, all the glyphless characters are
@@ -8386,6 +8506,8 @@ GNUstep and macOS).
Emacs is displaying the frame using MS-DOS direct screen writes.
@item haiku
Emacs is displaying the frame using the Application Kit on Haiku.
+@item pgtk
+Emacs is displaying the frame using pure GTK facilities.
@item nil
Emacs is displaying the frame on a character-based terminal.
@end table
@@ -8433,13 +8555,14 @@ displayed in the echo area.
@end defun
@cindex system tooltips
-@vindex x-gtk-use-system-tooltips
-When Emacs is built with GTK+ support, it by default displays tooltips
-using GTK+ functions, and the appearance of the tooltips is then
-controlled by GTK+ settings. GTK+ tooltips can be disabled by
-changing the value of the variable @code{x-gtk-use-system-tooltips} to
-@code{nil}. The rest of this subsection describes how to control
-non-GTK+ tooltips, which are presented by Emacs itself.
+@vindex use-system-tooltips
+When Emacs is built with the GTK+ toolkit or Haiku windowing support,
+it by default displays tooltips using toolkit functions, and the
+appearance of the tooltips is then controlled by the toolkit's
+settings. Toolkit-provided tooltips can be disabled by changing the
+value of the variable @code{use-system-tooltips} to @code{nil}. The
+rest of this subsection describes how to control non-toolkit tooltips,
+which are presented by Emacs itself.
@cindex tooltip frames
Tooltips are displayed in special frames called tooltip frames, which
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index eff9621628e..56f7b7bdfad 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -700,8 +700,16 @@ on this process.
@table @kbd
@item e @var{exp} @key{RET}
Evaluate expression @var{exp} in the context outside of Edebug
-(@code{edebug-eval-expression}). That is, Edebug tries to minimize its
-interference with the evaluation.
+(@code{edebug-eval-expression}). That is, Edebug tries to minimize
+its interference with the evaluation. The result is shown in the echo
+area, or, if this command is given a prefix, pop up a new buffer and
+pretty-print the result there.
+
+By default, this command
+suppresses the debugger during evaluation, so that an error in the
+evaluated expression won't add a new error on top of the existing one.
+Set the @code{debug-allow-recursive-debug} user option to a
+non-@code{nil} value to override this.
@item M-: @var{exp} @key{RET}
Evaluate expression @var{exp} in the context of Edebug itself
@@ -711,7 +719,8 @@ Evaluate expression @var{exp} in the context of Edebug itself
Evaluate the expression before point, in the context outside of Edebug
(@code{edebug-eval-last-sexp}). With the prefix argument of zero
(@kbd{C-u 0 C-x C-e}), don't shorten long items (like strings and
-lists).
+lists). Any other prefix will result in the value being
+pretty-printed in a separate buffer.
@end table
@cindex lexical binding (Edebug)
@@ -832,7 +841,6 @@ you continue execution, and recreated next time it is needed.
@cindex printing (Edebug)
@cindex printing circular structures
-@pindex cust-print
If an expression in your program produces a value containing circular
list structure, you may get an error when Edebug attempts to print it.
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index 3254a4dba81..a3d1d804086 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -448,6 +448,9 @@ Symbols
* Creating Symbols:: How symbols are kept unique.
* Symbol Properties:: Each symbol has a property list
for recording miscellaneous information.
+* Shorthands:: Properly organize your symbol names but
+ type less of them.
+* Symbols with Position:: Symbol variants containing integer positions
Symbol Properties
@@ -589,6 +592,7 @@ Advising Emacs Lisp Functions
* Advising Named Functions:: Advising named functions.
* Advice Combinators:: Ways to compose advice.
* Porting Old Advice:: Adapting code using the old defadvice.
+* Advice and Byte Code:: Not all functions can be advised.
Macros
@@ -735,6 +739,7 @@ Reading and Printing Lisp Objects
* Output Functions:: Functions to print Lisp objects as text.
* Output Variables:: Variables that control what the printing
functions do.
+* Output Overrides:: Overriding output variables.
Minibuffers
@@ -1228,6 +1233,7 @@ Text
* Decompression:: Dealing with compressed data.
* Base 64:: Conversion to or from base 64 encoding.
* Checksum/Hash:: Computing cryptographic hashes.
+* Suspicious Text:: Determining whether a string is suspicious.
* GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS.
* Database:: Interacting with an SQL database.
* Parsing HTML/XML:: Parsing HTML and XML.
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index e94e222e6a6..ed3cf56e098 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -435,7 +435,7 @@ expansion.
@cindex forms, special
@cindex evaluation of special forms
- A @dfn{special form} is a primitive function specially marked so that
+ A @dfn{special form} is a primitive specially marked so that
its arguments are not all evaluated. Most special forms define control
structures or perform variable bindings---things which functions cannot
do.
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 6e59e87d286..986fb22c75b 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -581,9 +581,12 @@ contents of the file. This is better than simply deleting the buffer
contents and inserting the whole file, because (1) it preserves some
marker positions and (2) it puts less data in the undo list.
-It is possible to read a special file (such as a FIFO or an I/O device)
-with @code{insert-file-contents}, as long as @var{replace} and
-@var{visit} are @code{nil}.
+It is possible to read a special file (such as a FIFO or an I/O
+device) with @code{insert-file-contents}, as long as @var{replace},
+and @var{visit} and @var{beg} are @code{nil}. However, you should
+normally use an @var{end} argument for these files to avoid inserting
+(potentially) unlimited data into the buffer (for instance, when
+inserting data from @file{/dev/urandom}).
@end defun
@defun insert-file-contents-literally filename &optional visit beg end replace
@@ -1450,13 +1453,19 @@ is owned by the user with name @samp{lh}.
is in the group with name @samp{users}.
@item (20614 64019 50040 152000)
-was last accessed on October 23, 2012, at 20:12:03.050040152 UTC.
+was last accessed on October 23, 2012, at 20:12:03.050040152 UTC@.
+(This timestamp is @code{(1351023123050040152 . 1000000000)}
+if @code{current-time-list} is @code{nil}.)
@item (20000 23 0 0)
-was last modified on July 15, 2001, at 08:53:43 UTC.
+was last modified on July 15, 2001, at 08:53:43.000000000 UTC@.
+(This timestamp is @code{(1310720023000000000 . 1000000000)}
+if @code{current-time-list} is @code{nil}.)
@item (20614 64555 902289 872000)
-last had its status changed on October 23, 2012, at 20:20:59.902289872 UTC.
+last had its status changed on October 23, 2012, at 20:20:59.902289872 UTC@.
+(This timestamp is @code{(1351023659902289872 . 1000000000)}
+if @code{current-time-list} is @code{nil}.)
@item 122295
is 122295 bytes long. (It may not contain 122295 characters, though,
@@ -2436,6 +2445,15 @@ You can use this function for directory names and for file names,
because it recognizes abbreviations even as part of the name.
@end defun
+@defun file-parent-directory filename
+This function returns the directory name of the parent directory of
+@var{filename}. If @var{filename} is at the root directory of the
+filesystem, it returns @code{nil}. A relative @var{filename} is
+assumed to be relative to @code{default-directory}, and the return
+value will also be relative in that case. If the return value is
+non-@code{nil}, it ends in a slash.
+@end defun
+
@node File Name Expansion
@subsection Functions that Expand Filenames
@cindex expansion of file names
@@ -3106,10 +3124,16 @@ except those two. It is useful as the @var{match-regexp} argument to
returns @code{nil}, if directory @samp{/foo} is empty.
@end defvr
-@defun file-expand-wildcards pattern &optional full
+@defun file-expand-wildcards pattern &optional full regexp
This function expands the wildcard pattern @var{pattern}, returning
a list of file names that match it.
+@var{pattern} is, by default, a ``glob''/wildcard string, e.g.,
+@samp{"/tmp/*.png"} or @samp{"/*/*/foo.png"}, but can also be a
+regular expression if the optional @var{regexp} parameter is non-nil.
+In any case, the matches are applied per sub-directory, so a match
+can't span a parent/sub directory.
+
If @var{pattern} is written as an absolute file name,
the values are absolute also.
@@ -3344,6 +3368,7 @@ first, before handlers for jobs such as remote file access.
@code{get-file-buffer},
@code{insert-directory},
@code{insert-file-contents},@*
+@code{list-system-processes},
@code{load}, @code{lock-file},
@code{make-auto-save-file-name},
@code{make-directory},
@@ -3352,7 +3377,7 @@ first, before handlers for jobs such as remote file access.
@code{make-nearby-temp-file},
@code{make-process},
@code{make-symbolic-link},@*
-@code{process-file},
+@code{process-attributes}, @code{process-file},
@code{rename-file}, @code{set-file-acl}, @code{set-file-modes},
@code{set-file-selinux-context}, @code{set-file-times},
@code{set-visited-file-modtime}, @code{shell-command},
@@ -3405,6 +3430,7 @@ first, before handlers for jobs such as remote file access.
@code{get-file-buffer},
@code{insert-directory},
@code{insert-file-contents},
+@code{list-system-processes},
@code{load}, @code{lock-file},
@code{make-auto-save-file-name},
@code{make-direc@discretionary{}{}{}tory},
@@ -3413,7 +3439,7 @@ first, before handlers for jobs such as remote file access.
@code{make-nearby-temp-file},
@code{make-process},
@code{make-symbolic-link},
-@code{process-file},
+@code{process-attributes}, @code{process-file},
@code{rename-file}, @code{set-file-acl}, @code{set-file-modes},
@code{set-file-selinux-context}, @code{set-file-times},
@code{set-visited-file-modtime}, @code{shell-command},
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index ceaa11529f7..ed56fa777d2 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -60,6 +60,8 @@ The frame is displayed on a GNUstep or Macintosh Cocoa graphical
terminal.
@item pc
The frame is displayed on an MS-DOS terminal.
+@item pgtk
+The frame is displayed using pure GTK facilities.
@end table
@end defun
@@ -456,6 +458,18 @@ monitor, the same string as returned by the function
@var{display} should be the name of an X display (a string).
@end deffn
+@cindex monitor change functions
+@defvar display-monitors-changed-functions
+This variable is an abnormal hook run when the monitor configuration
+changes, which can happen if a monitor is rotated, moved, added or
+removed from a multiple-monitor setup, if the primary monitor changes,
+or if the resolution of a monitor changes. It is called with a single
+argument consisting of the terminal on which the monitor configuration
+changed. Programs should call @code{display-monitor-attributes-list}
+with the terminal as the argument to retrieve the new monitor
+configuration on that terminal.
+@end defvar
+
@node Frame Geometry
@section Frame Geometry
@cindex frame geometry
@@ -681,9 +695,9 @@ The position of the top left corner of the native frame specifies the
indicate that position for the various builds:
@itemize @w{}
-@item (1) non-toolkit and terminal frames
+@item (1) non-toolkit, Haiku, and terminal frames
-@item (2) Lucid, Motif, MS-Windows, and Haiku frames
+@item (2) Lucid, Motif, and MS-Windows frames
@item (3) GTK+ and NS frames
@end itemize
@@ -1732,17 +1746,16 @@ fit will be clipped by the window manager.
@item fullscreen
This parameter specifies whether to maximize the frame's width, height
or both. Its value can be @code{fullwidth}, @code{fullheight},
-@code{fullboth}, or @code{maximized}.@footnote{On Haiku, setting
-@code{fullscreen} to @code{fullwidth} or @code{fullheight} has no
-effect.} A @dfn{fullwidth} frame is as
-wide as possible, a @dfn{fullheight} frame is as tall as possible, and
-a @dfn{fullboth} frame is both as wide and as tall as possible. A
-@dfn{maximized} frame is like a ``fullboth'' frame, except that it usually
-keeps its title bar and the buttons for resizing
-and closing the frame. Also, maximized frames typically avoid hiding
-any task bar or panels displayed on the desktop. A ``fullboth'' frame,
-on the other hand, usually omits the title bar and occupies the entire
-available screen space.
+@code{fullboth}, or @code{maximized}.@footnote{On PGTK frames, setting
+the values @code{fullheight} and @code{fullwidth} has no effect.} A
+@dfn{fullwidth} frame is as wide as possible, a @dfn{fullheight} frame
+is as tall as possible, and a @dfn{fullboth} frame is both as wide and
+as tall as possible. A @dfn{maximized} frame is like a ``fullboth''
+frame, except that it usually keeps its title bar and the buttons for
+resizing and closing the frame. Also, maximized frames typically
+avoid hiding any task bar or panels displayed on the desktop. A
+``fullboth'' frame, on the other hand, usually omits the title bar and
+occupies the entire available screen space.
Full-height and full-width frames are more similar to maximized
frames in this regard. However, these typically display an external
@@ -2166,6 +2179,11 @@ prevent hanging with those window managers.
If non-@code{nil}, the frame is visible on all virtual desktops on systems
with virtual desktops.
+@vindex shaded@r{, a frame parameter}
+@item sticky
+If non-@code{nil}, tell the window manager to display the frame in a
+way that its contents are hidden, leaving only the title bar.
+
@vindex inhibit-double-buffering@r{, a frame parameter}
@item inhibit-double-buffering
If non-@code{nil}, the frame is drawn to the screen without double
@@ -2431,6 +2449,16 @@ opacity when it is not selected.
Some window systems do not support the @code{alpha} parameter for child
frames (@pxref{Child Frames}).
+
+@vindex alpha-background@r{, a frame parameter}
+@item alpha-background
+@cindex opacity, frame
+@cindex transparency, frame
+Sets the background transparency of the frame. Unlike the @code{alpha}
+frame parameter, this only controls the transparency of the background
+while keeping foreground elements such as text fully opaque. It
+should be an integer between 0 and 100, where 0 means
+completely transparent and 100 means completely opaque (default).
@end table
The following frame parameters are semi-obsolete in that they are
@@ -3152,10 +3180,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
@@ -3497,10 +3523,18 @@ enabled. Typically, @var{body} would use @code{read-event} to read
the motion events and modify the display accordingly. @xref{Motion
Events}, for the format of mouse motion events.
-The value of @code{track-mouse} is that of the last form in @var{body}.
-You should design @var{body} to return when it sees the up-event that
-indicates the release of the button, or whatever kind of event means
-it is time to stop tracking.
+The value of @code{track-mouse} is that of the last form in
+@var{body}. You should design @var{body} to return when it sees the
+up-event that indicates the release of the button, or whatever kind of
+event means it is time to stop tracking. Its value also controls how
+mouse events are reported while a mouse button is held down: if it is
+@code{dropping} or @code{drag-source}, the motion events are reported
+relative to the frame underneath the pointer. If there is no such
+frame, the events will be reported relative to the frame the mouse
+buttons were first pressed on. In addition, the @code{posn-window} of
+the mouse position list will be @code{nil} if the value is
+@code{drag-source}. This is useful to determine if a frame is not
+directly visible underneath the mouse pointer.
The @code{track-mouse} form causes Emacs to generate mouse motion
events by binding the variable @code{track-mouse} to a
@@ -3744,6 +3778,13 @@ still use a menu keymap to implement it. To make the contents vary, add
a hook function to @code{menu-bar-update-hook} to update the contents of
the menu keymap as necessary.
+@defvar x-pre-popup-menu-hook
+ A normal hook run immediately before a pop-up menu is displayed,
+either directly by calling @code{x-popup-menu}, or through a menu
+keymap. It won't be called if @code{x-popup-menu} returns for some
+other reason without displaying a pop-up menu.
+@end defvar
+
@node Dialog Boxes
@section Dialog Boxes
@cindex dialog boxes
@@ -3847,8 +3888,9 @@ in the buffer. The default is to use the @code{arrow} (non-text)
pointer style.
@end defopt
- When using X, you can specify what the @code{text} pointer style
-really looks like by setting the variable @code{x-pointer-shape}.
+ When using some window systems, you can specify what the @code{text}
+pointer style really looks like by setting the variable
+@code{x-pointer-shape}.
@defvar x-pointer-shape
This variable specifies the pointer shape to use ordinarily in the
@@ -3896,11 +3938,18 @@ upper-case names, in accord with X Window System conventions. If
@var{type} is @code{nil}, that stands for @code{PRIMARY}.
If @var{data} is @code{nil}, it means to clear out the selection.
-Otherwise, @var{data} may be a string, a symbol, an integer (or a cons
-of two integers or list of two integers), an overlay, or a cons of two
-markers pointing to the same buffer. An overlay or a pair of markers
-stands for text in the overlay or between the markers. The argument
-@var{data} may also be a vector of valid non-vector selection values.
+Otherwise, @var{data} may be a string, a symbol, an integer, an
+overlay, or a cons of two markers pointing to the same buffer. An
+overlay or a pair of markers stands for text in the overlay or between
+the markers. The argument @var{data} may also be a vector of valid
+non-vector selection values.
+
+If @var{data} is a string, then its text properties can specify values
+used for individual data types. For example, if @var{data} has a
+property named @code{text/uri-list}, then a call to
+@code{gui-get-selection} with the data type @code{text/uri-list} will
+result in the value of that property being used instead of @var{data}
+itself.
This function returns @var{data}.
@end deffn
@@ -3988,16 +4037,46 @@ amount of different data types on the clipboard.
@section Drag and Drop
@cindex drag and drop
+ When the user drops something from another application over Emacs,
+Emacs will try to insert any text and open any URL that was dropped.
+If text was dropped, then it will always be inserted at the location
+of the mouse pointer when the drop happened, or saved in the kill ring
+if insertion failed (which can happen if the buffer is read-only). If
+it was an URL, then Emacs tries to call an appropriate handler
+function by first matching the URL against regexps defined in
+@code{dnd-protocol-alist}, and then against @code{browse-url-handlers}
+and @code{browse-url-default-handlers}, and failing that, inserting
+the URL as plain text.
+
+@defvar dnd-protocol-alist
+ This variable is a list of cons cells of the form
+@w{@code{(@var{pattern} . @var{action})}}. @var{pattern} is a regexp
+that URLs are matched against after being dropped. @var{action} is a
+function that is called with two arguments should a URL being dropped
+match @var{pattern}: the URL being dropped, and the action being
+performed for the drop (one of the symbols @code{copy}, @code{move},
+@code{link}, @code{private} or @code{ask}).
+@end defvar
+
+@cindex drag and drop, X
+@cindex drag and drop, other formats
+ Emacs implements drag-and-drop for text and URLs individually for
+each window system, and does not by default support the dropping of
+anything else. Code that wishes to support the dropping of content
+types not supported by Emacs can utilize the X-specific interface
+described below:
+
@vindex x-dnd-test-function
@vindex x-dnd-known-types
- When a user drags something from another application over Emacs, that other
-application expects Emacs to tell it if Emacs can handle the data that is
-dragged. The variable @code{x-dnd-test-function} is used by Emacs to determine
-what to reply. The default value is @code{x-dnd-default-test-function}
-which accepts drops if the type of the data to be dropped is present in
-@code{x-dnd-known-types}. You can customize @code{x-dnd-test-function} and/or
-@code{x-dnd-known-types} if you want Emacs to accept or reject drops based
-on some other criteria.
+ When a user drags something from another application over Emacs on
+the X Window System, that other application expects Emacs to tell it
+if Emacs can handle the data that was dragged. The variable
+@code{x-dnd-test-function} is used by Emacs to determine what to
+reply. The default value is @code{x-dnd-default-test-function} which
+accepts drops if the type of the data to be dropped is present in
+@code{x-dnd-known-types}. You can customize
+@code{x-dnd-test-function} and/or @code{x-dnd-known-types} if you want
+Emacs to accept or reject drops based on some other criteria.
@vindex x-dnd-types-alist
If you want to change the way Emacs handles drop of different types
@@ -4005,16 +4084,228 @@ or add a new type, customize @code{x-dnd-types-alist}. This requires
detailed knowledge of what types other applications use for drag and
drop.
-@vindex dnd-protocol-alist
-@vindex browse-url-handlers
-@vindex browse-url-default-handlers
- When an URL is dropped on Emacs it may be a file, but it may also be
-another URL type (https, etc.). Emacs first checks
-@code{dnd-protocol-alist} to determine what to do with the URL@. If
-there is no match there, Emacs looks for a match in
-@code{browse-url-handlers} and @code{browse-url-default-handlers}. If
-still no match has been found, the text for the URL is inserted. If
-you want to alter Emacs behavior, you can customize these variables.
+ Those data types are typically implemented as special data types an
+X selection provided by the other application can be converted to.
+They can either be the same data types that are typically accepted by
+@code{gui-set-selection}, or they can be MIME types, depending on the
+specific drag-n-drop protocol being used. Plain text may be
+@code{"STRING"} or @code{"text/plain"}, for example.
+
+@vindex x-dnd-direct-save-function
+ However, @code{x-dnd-types-alist} does not handle a special kind of
+drop sent by a program which wants Emacs to save a file in a location
+Emacs must determine by itself. These drops are handled via the
+variable @code{x-dnd-direct-save-function}, which should be a function
+that accepts two arguments. If the first argument is non-@code{nil},
+then the second argument is a string describing the name (with no
+leading directory) that the other program recommends the file be saved
+under, and the function should return the complete file name under
+which it will be saved. Otherwise, the file has already been saved,
+and the second argument is the complete name of the file. The
+function should then perform whatever action is appropriate (i.e.,
+open the file or refresh the directory listing.)
+
+@cindex initiating drag-and-drop
+ On capable window systems, Emacs also supports dragging contents
+from its frames to windows of other applications.
+
+@cindex drop target, in drag-and-drop operations
+@defun dnd-begin-text-drag text &optional frame action allow-same-frame
+This function begins dragging text from @var{frame} to another program
+(known as the @dfn{drop target}), and returns the result of
+drag-and-drop operation when the text is dropped or the drag-and-drop
+operation is canceled. @var{text} is the text that will be inserted
+by the drop target.
+
+@var{action} must be one of the symbols @code{copy} or @code{move},
+where @code{copy} means that @var{text} should be inserted by the drop
+target, and @code{move} means the same as @code{copy}, but in addition
+the caller may have to delete @var{text} from its source as explained
+below.
+
+@var{frame} is the frame where the mouse is currently held down, or
+@code{nil}, which means to use the selected frame. This function may
+return immediately if no mouse buttons are held down, so it should be
+only called immediately after a @code{down-mouse-1} or similar event
+(@pxref{Mouse Events}), with @var{frame} set to the frame where that
+event was generated (@pxref{Click Events}).
+
+@var{allow-same-frame} specifies whether or not drops on top of
+@var{frame} itself are to be ignored.
+
+The return value specifies the action that the drop target actually
+performed, and optionally what the caller should do. It can be one of
+the following symbols:
+
+@table @code
+@item copy
+The drop target inserted the dropped text.
+
+@item move
+The drop target inserted the dropped text, but in addition the caller
+should delete @var{text} from wherever it originated, such as its
+buffer.
+
+@item private
+The drop target performed some other unspecified action.
+
+@item nil
+The drag-and-drop operation was canceled.
+@end table
+
+@end defun
+
+@defun dnd-begin-file-drag file &optional frame action allow-same-frame
+This function begins dragging @var{file} from @var{frame} to another
+program, and returns the result of the drag-and-drop operation when
+the file is dropped or the drag-and-drop operation is canceled.
+
+If @var{file} is a remote file, then a temporary copy will be made.
+
+@var{action} must be one of the symbols @code{copy}, @code{move} or
+@code{link}, where @code{copy} means that @var{file} should be opened
+or copied by the drop target, @code{move} means the drop target should
+move the file to another location, and @code{link} means the drop
+target should create a symbolic link to @var{file}. It is an error to
+specify @code{link} as the action if @var{file} is a remote file.
+
+@var{frame} and @var{allow-same-frame} have the same meaning as in
+@code{dnd-begin-text-drag}.
+
+The return value is the action that the drop target actually
+performed, which can be one of the following symbols:
+
+@table @code
+@item copy
+The drop target opened or copied @var{file} to a different location.
+
+@item move
+The drop target moved @var{file} to a different location.
+
+@item link
+The drop target (usually a file manager) created a symbolic link to
+@var{file}.
+
+@item private
+The drop target performed some other unspecified action.
+
+@item nil
+The drag-and-drop operation was canceled.
+@end table
+
+@end defun
+
+@defun dnd-begin-drag-files files &optional frame action allow-same-frame
+This function is like @code{dnd-begin-file-drag}, except that
+@var{files} is a list of files. If the drop target doesn't support
+dropping multiple files, then the first file will be used instead.
+@end defun
+
+@defun dnd-direct-save file name &optional frame allow-same-frame
+This function is similar to @code{dnd-begin-file-drag} (with the
+default action of copy), but instead of specifying the action you
+specify the name of the copy created by the target program in
+@code{name}.
+@end defun
+
+@cindex initiating drag-and-drop, low-level
+ The high-level interfaces described above are implemented on top of
+a lower-level primitive. If you need to drag content other than files
+or text, use the low-level interface @code{x-begin-drag}
+instead. However, using it will require detailed knowledge of the
+data types and actions used by the programs to transfer content via
+drag-and-drop on each platform you want to support.
+
+@defun x-begin-drag targets &optional action frame return-frame allow-current-frame follow-tooltip
+This function begins a drag from @var{frame}, and returns when the
+drag-and-drop operation ends, either because the drop was successful,
+or because the drop was rejected. The drop occurs when all mouse
+buttons are released on top of an X window other than @var{frame} (the
+@dfn{drop target}), or any X window if @var{allow-current-frame} is
+non-@code{nil}. If no mouse buttons are held down when the
+drag-and-drop operation begins, this function may immediately return
+@code{nil}.
+
+@var{targets} is a list of strings describing selection targets, much
+like the @var{data-type} argument to @code{gui-get-selection}, that
+the drop target can request from Emacs (@pxref{Window System
+Selections}).
+
+@var{action} is a symbol describing the action recommended to the
+target. It can either be @code{XdndActionCopy}, which
+means to copy the contents of the selection @code{XdndSelection} to
+the drop target; or @code{XdndActionMove}, which means copy as with
+@code{XdndActionCopy}, and in addition the caller should delete
+whatever was stored in that selection after copying it.
+
+@var{action} may also be an alist which associates between symbols
+describing the available actions, and strings that the drop target is
+expected to present to the user to choose between the available
+actions.
+
+If @var{return-frame} is non-@code{nil} and the mouse moves over an
+Emacs frame after first moving out of @var{frame}, then the frame to
+which the mouse moves will be returned immediately. If
+@var{return-frame} is the symbol @code{now}, then any frame underneath
+the mouse pointer will be returned without waiting for the mouse to
+first move out of @var{frame}. @var{return-frame} is useful when you
+want to treat dragging content from one frame to another specially,
+while also being able to drag content to other programs, but it is not
+guaranteed to work on all systems and with all window managers.
+
+If @var{follow-tooltip} is non-@code{nil}, the position of any tooltip
+(such as one shown by @code{tooltip-show}) will follow the location of
+the mouse pointer whenever it moves during the drag-and-drop
+operation. The tooltip will be hidden once all mouse buttons are
+released.
+
+If the drop was rejected or no drop target was found, this function
+returns @code{nil}. Otherwise, it returns a symbol describing the
+action the target chose to perform, which can differ from @var{action}
+if that isn't supported by the drop target. @code{XdndActionPrivate}
+is also a valid return value in addition to @code{XdndActionCopy} and
+@code{XdndActionMove}; it means that the drop target chose to perform
+an unspecified action, and no further processing is required by the
+caller.
+
+The caller must cooperate with the target to fully perform the action
+chosen by the target. For example, callers should delete the buffer
+text that was dragged if this function returns @code{XdndActionMove}.
+@end defun
+
+@cindex drag and drop protocols, X
+
+ On X Windows, several different drag-and-drop protocols are
+supported by @code{x-begin-drag}. When dragging content that is known
+to not be supported by a specific drag-and-drop protocol, it might be
+desirable to turn that protocol off, by changing the values of the
+following variables:
+
+@defvar x-dnd-disable-motif-protocol
+When this is non-@code{nil}, the Motif drag and drop protocols are
+disabled, and dropping onto programs that only understand them will
+not work.
+@end defvar
+
+@defvar x-dnd-use-offix-drop
+When this is @code{nil}, the OffiX (old KDE) drag and drop protocol is
+disabled. When this is the symbol @code{files}, the OffiX protocol
+will only be used if @code{"FILE_NAME"} is one of the targets given to
+@code{x-begin-drag}. Any other value means to use the OffiX protocol
+to drop all supported content.
+@end defvar
+
+@defvar x-dnd-use-unsupported-drop
+When one of the @code{"STRING"}, @code{"UTF8_STRING"},
+@code{"COMPOUND_TEXT"} or @code{"TEXT"} targets is present in the list
+given to @code{x-begin-drag}, Emacs will try to use synthesized mouse
+events and the primary selection to insert the text if the drop target
+doesn't support any drag-and-drop protocol at all.
+
+A side effect is that Emacs will become the owner of the primary
+selection upon such a drop. If that is not desired, then the drop
+emulation can be disabled by setting this variable to @code{nil}.
+@end defvar
@node Color Names
@section Color Names
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 96fecc8c892..e3de6009e90 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -22,6 +22,7 @@ define them.
* Function Cells:: Accessing or setting the function definition
of a symbol.
* Closures:: Functions that enclose a lexical environment.
+* OClosures:: Function objects
* Advising Functions:: Adding to the definition of a function.
* Obsolete Functions:: Declaring functions obsolete.
* Inline Functions:: Functions that the compiler will expand inline.
@@ -145,7 +146,12 @@ function:
This function returns @code{t} if @var{object} is any kind of
function, i.e., can be passed to @code{funcall}. Note that
@code{functionp} returns @code{t} for symbols that are function names,
-and returns @code{nil} for special forms.
+and returns @code{nil} for symbols that are macros or special forms.
+
+If @var{object} is not a function, this function ordinarily returns
+@code{nil}. However, the representation of function objects is
+complicated, and for efficiency reasons in rare cases this function
+can return @code{t} even when @var{object} is not a function.
@end defun
It is also possible to find out how many arguments an arbitrary
@@ -669,6 +675,22 @@ purposes, it is better to use @code{fset}, which does not keep such
records. @xref{Function Cells}.
@end defun
+@defun function-alias-p object &optional noerror
+Checks whether @var{object} is a function alias. If it is, it returns
+a list of symbols representing the function alias chain, else
+@code{nil}. For instance, if @code{a} is an alias for @code{b}, and
+@code{b} is an alias for @code{c}:
+
+@example
+(function-alias-p 'a)
+ @result{} (b c)
+@end example
+
+If there's a loop in the definitions, an error will be signalled. If
+@var{noerror} is non-@code{nil}, the non-looping parts of the chain is
+returned instead.
+@end defun
+
You cannot create a new primitive function with @code{defun} or
@code{defalias}, but you can use them to change the function definition of
any symbol, even one such as @code{car} or @code{x-popup-menu} whose
@@ -1493,6 +1515,116 @@ exposed to the rest of the Lisp world is considered an internal
implementation detail. For this reason, we recommend against directly
examining or altering the structure of closure objects.
+@node OClosures
+@section Open Closures
+
+Traditionally, functions are opaque objects which offer no other
+functionality but to call them. Emacs Lisp functions aren't fully
+opaque since you can extract some info out of them such as their
+docstring, their arglist, or their interactive spec, but they are
+mostly opaque. This is usually what we want, but occasionally we need
+functions to expose a bit more information about themselves.
+
+OClosures are functions which carry additional type information,
+and expose some information in the form of slots which you can access
+via accessor functions.
+
+They are defined in two steps: first @code{oclosure-define} is used to
+define new OClosure types by specifying the slots carried by those
+OClosures, and then @code{oclosure-lambda} is used to create an
+OClosure object of a given type.
+
+Say we want to define keyboard macros, i.e. interactive functions
+which re-execute a sequence of key events. You could do it with
+a plain function as follows:
+@example
+(defun kbd-macro (key-sequence)
+ (lambda (&optional arg)
+ (interactive "P")
+ (execute-kbd-macro key-sequence arg)))
+@end example
+But with such a definition there is no easy way to extract the
+@var{key-sequence} from that function, for example to print it.
+
+We can solve this problem using OClosures as follows. First we define
+the type of our keyboard macros (to which we decided to add
+a @code{counter} slot while at it):
+@example
+(oclosure-define kbd-macro
+ "Keyboard macro."
+ keys (counter :mutable t))
+@end example
+After which we can rewrite our @code{kbd-macro} function:
+@example
+(defun kbd-macro (key-sequence)
+ (oclosure-lambda (kbd-macro (keys key-sequence) (counter 0))
+ (&optional arg)
+ (interactive "p")
+ (execute-kbd-macro keys arg)
+ (setq counter (1+ counter))))
+@end example
+As you can see, the @code{keys} and @code{counter} slots of the
+OClosure can be accessed as local variables from within the body
+of the OClosure. But we can now also access them from outside of the
+body of the OClosure, for example to describe a keyboard macro:
+@example
+(defun describe-kbd-macro (km)
+ (if (not (eq 'kbd-macro (oclosure-type km)))
+ (message "Not a keyboard macro")
+ (let ((keys (kbd-macro--keys km))
+ (counter (kbd-macro--counter km)))
+ (message "Keys=%S, called %d times" keys counter))))
+@end example
+Where @code{kbd-macro--keys} and @code{kbd-macro--counter} are
+accessor functions generated by the @code{oclosure-define} macro.
+
+@defmac oclosure-define name &optional docstring &rest slots
+This macro defines a new OClosure type along with accessor functions
+for its slots. @var{name} can be a symbol (the name of
+the new type), or a list of the form @code{(@var{name} . @var{type-props})} in
+which case @var{type-props} is a list of additional properties.
+@var{slots} is a list of slot descriptions where each slot can be
+either a symbol (the name of the slot) or it can be of the form
+@code{(@var{slot-name} . @var{slot-props})} where @var{slot-props} is
+a property list.
+
+For each slot, the macro creates an accessor function named
+@code{@var{name}--@var{slot-name}}. By default slots are immutable.
+If you need a slot to be mutable, you need to specify it with the
+@code{:mutable} slot property, after which it can be mutated for
+example with @code{setf}.
+
+Beside slot accessors, the macro can create a predicate and
+functional update functions according to @var{type-props}:
+a @code{(:predicate @var{pred-name})} in the @var{type-props} causes
+the definition of a predicate function under the name @var{pred-name},
+and @code{(:copier @var{copier-name} @var{copier-arglist})} causes the
+definition of a functional update function which takes an OClosure of
+type @var{name} as first argument and returns a copy of it with the
+slots named in @var{copier-arglist} modified to the value passed in the
+corresponding argument.
+@end defmac
+
+@defmac oclosure-lambda (type . slots) arglist &rest body
+This macro creates an anonymous OClosure of type @var{type}.
+@var{slots} should be a list of elements of the form @code{(@var{slot-name}
+@var{exp})}.
+At run time, each @var{exp} is evaluated, in order, after which
+the OClosure is created with its slots initialized with the
+resulting values.
+
+When called as a function, the OClosure will accept arguments
+according to @var{arglist} and will execute the code in @var{body}.
+@var{body} can refer to the value of any of its slot directly as if it
+were a local variable that had been captured by static scoping.
+@end defmac
+
+@defun oclosure-type object
+This function returns the OClosure type (a symbol) of @var{object} if it is an
+OClosure, and @code{nil} otherwise.
+@end defun
+
+
@node Advising Functions
@section Advising Emacs Lisp Functions
@cindex advising functions
@@ -1585,6 +1717,7 @@ ways to do it. The added function is also called a piece of @emph{advice}.
* Advising Named Functions:: Advising named functions.
* Advice Combinators:: Ways to compose advice.
* Porting Old Advice:: Adapting code using the old defadvice.
+* Advice and Byte Code:: Not all functions can be advised.
@end menu
@node Core Advising Primitives
@@ -2006,6 +2139,37 @@ changing @code{ad-return-value}, whereas new @code{:after} advice cannot, so
when porting such old @code{after} advice, you'll need to turn it into new
@code{:around} or @code{:filter-return} advice instead.
+@c This is its own node because we link to it from *Help* buffers.
+@node Advice and Byte Code
+@subsection Advice and Byte Code
+@cindex compiler macros, advising
+@cindex @code{byte-compile} and @code{byte-optimize}, advising
+
+ Not all functions can be reliably advised. The byte compiler may
+choose to replace a call to a function with a sequence of instructions
+that doesn't call the function you were interested in altering.
+
+This usually happens due to one of the three following mechanisms:
+
+@table @asis
+@item @code{byte-compile} properties
+If a function's symbol has a @code{byte-compile} property, that
+property will be used instead of the symbol's function definition.
+@xref{Compilation Functions}.
+
+@item @code{byte-optimize} properties
+If a function's symbol has a @code{byte-optimize} property, the byte
+compiler may rewrite the function arguments, or decide to use a
+different function altogether.
+
+@item @code{compiler-macro} declare forms
+A function can have a special @code{compiler-macro} @code{declare}
+form in its definition (@pxref{Declare Form}) that defines an
+@dfn{expander} to call when compiling the function. The expander
+could then cause the produced byte-code not to call the original
+function.
+@end table
+
@node Obsolete Functions
@section Declaring Functions Obsolete
@cindex obsolete functions
@@ -2137,8 +2301,8 @@ worry about how many times the body uses the arguments, as you do for
macros.
Alternatively, you can define a function by providing the code which
-will inline it as a compiler macro. The following macros make this
-possible.
+will inline it as a compiler macro (@pxref{Declare Form}). The
+following macros make this possible.
@c FIXME: Can define-inline use the interactive spec?
@defmac define-inline name args [doc] [declare] body@dots{}
@@ -2294,6 +2458,7 @@ which case the warning message gives no extra details). @var{when}
should be a string indicating when the function or macro was first
made obsolete.
+@cindex compiler macro
@item (compiler-macro @var{expander})
This can only be used for functions, and tells the compiler to use
@var{expander} as an optimization function. When encountering a call to the
diff --git a/doc/lispref/hash.texi b/doc/lispref/hash.texi
index a566d898240..d3ae673d44d 100644
--- a/doc/lispref/hash.texi
+++ b/doc/lispref/hash.texi
@@ -203,7 +203,8 @@ association in @var{table}.
@defun puthash key value table
This function enters an association for @var{key} in @var{table}, with
value @var{value}. If @var{key} already has an association in
-@var{table}, @var{value} replaces the old associated value.
+@var{table}, @var{value} replaces the old associated value. This
+function always returns @var{value}.
@end defun
@defun remhash key table
@@ -219,10 +220,7 @@ otherwise. In Emacs Lisp, @code{remhash} always returns @code{nil}.
@defun clrhash table
This function removes all the associations from hash table @var{table},
so that it becomes empty. This is also called @dfn{clearing} the hash
-table.
-
-@b{Common Lisp note:} In Common Lisp, @code{clrhash} returns the empty
-@var{table}. In Emacs Lisp, it returns @code{nil}.
+table. @code{clrhash} returns the empty @var{table}.
@end defun
@defun maphash function table
@@ -289,9 +287,13 @@ If two objects @var{obj1} and @var{obj2} are @code{equal}, then
are the same integer.
If the two objects are not @code{equal}, the values returned by
-@code{sxhash-equal} are usually different, but not always; once in a
-rare while, by luck, you will encounter two distinct-looking objects
-that give the same result from @code{sxhash-equal}.
+@code{sxhash-equal} are usually different, but not always.
+@code{sxhash-equal} is designed to be reasonably fast (since it's used
+for indexing hash tables) so it won't recurse deeply into nested
+structures. In addition; once in a rare while, by luck, you will
+encounter two distinct-looking simple objects that give the same
+result from @code{sxhash-equal}. So you can't, in general, use
+@code{sxhash-equal} to check whether an object has changed.
@b{Common Lisp note:} In Common Lisp a similar function is called
@code{sxhash}. Emacs provides this name as a compatibility alias for
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 10a12940a15..463039c5a0e 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -158,6 +158,13 @@ the function definition has no documentation string. In that case,
@code{documentation} returns @code{nil}.
@end defun
+@defun function-documentation function
+Generic function used by @code{documentation} to extract the raw
+docstring from a function object. You can specify how to get the
+docstring of a specific function type by adding a corresponding method
+to it.
+@end defun
+
@defun face-documentation face
This function returns the documentation string of @var{face} as a
face.
@@ -338,7 +345,10 @@ stands for a key sequence @var{KEYSEQ}, which will use the same face
as a command substitution. This should be used only when a key
sequence has no corresponding command, for example when it is read
directly with @code{read-key-sequence}. It must be a valid key
-sequence according to @code{key-valid-p}.
+sequence according to @code{key-valid-p}. It can also be used with
+command names, like @samp{\`M-x foo'}, where you want this to be
+fontified like a keyboard sequence, but you want to inhibit
+translating it into a key sequence like @samp{\[foo]} does.
@item `
(grave accent) stands for a left quote.
@@ -355,6 +365,10 @@ depending on the value of @code{text-quoting-style}.
quotes the following character and is discarded; thus, @samp{\=`} puts
@samp{`} into the output, @samp{\=\[} puts @samp{\[} into the output,
and @samp{\=\=} puts @samp{\=} into the output.
+
+@item \+
+This indicates that the symbol directly following should not be marked
+as link in the @file{*Help*} buffer.
@end table
@strong{Please note:} Each @samp{\} must be doubled when written in a
@@ -379,7 +393,7 @@ quotes. You can customize it freely according to your personal
preference.
@end defopt
-@defun substitute-command-keys string &optional no-face
+@defun substitute-command-keys string &optional no-face include-menus
@vindex help-key-binding@r{ (face)}
This function scans @var{string} for the above special sequences and
replaces them by what they stand for, returning the result as a string.
@@ -429,6 +443,9 @@ RET minibuffer-complete-and-exit
C-g abort-recursive-edit
"
+The keymap description will normally exclude menu items, but if
+@var{include-menus} is non-@code{nil}, include them.
+
@group
(substitute-command-keys
"To abort a recursive edit from the minibuffer, type \
diff --git a/doc/lispref/hooks.texi b/doc/lispref/hooks.texi
index 107d036202e..59b7930732f 100644
--- a/doc/lispref/hooks.texi
+++ b/doc/lispref/hooks.texi
@@ -290,7 +290,6 @@ auto-fill-function
command-error-function
compose-chars-after-function
composition-function-table
-deferred-action-function
input-method-function
load-read-function
load-source-file-function
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index bc73ff28a69..8d2089bad8b 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1637,7 +1637,7 @@ This function returns the value of a Lisp float specified by
@var{arg}, as a C @code{double} value.
@end deftypefn
-@deftypefn Function struct timespec extract_time (emacs_env *@var{env}, emacs_value @var{arg})
+@deftypefn Function {struct timespec} extract_time (emacs_env *@var{env}, emacs_value @var{arg})
This function, which is available since Emacs 27, interprets @var{arg}
as an Emacs Lisp time value and returns the corresponding @code{struct
timespec}. @xref{Time of Day}. @code{struct timespec} represents a
@@ -1942,7 +1942,7 @@ garbage-collected. Don't run any expensive code in a finalizer,
because GC must finish quickly to keep Emacs responsive.
@end deftypefn
-@deftypefn Function void *get_user_ptr (emacs_env *@var{env}, emacs_value @var{arg})
+@deftypefn Function {void *}get_user_ptr (emacs_env *@var{env}, emacs_value @var{arg})
This function extracts the C pointer from the Lisp object represented
by @var{arg}.
@end deftypefn
@@ -2060,7 +2060,7 @@ to quit, use the following function, which is available since Emacs
27.1.
@anchor{process_input}
-@deftypefn Function enum emacs_process_input_result process_input (emacs_env *@var{env})
+@deftypefn Function {enum emacs_process_input_result} process_input (emacs_env *@var{env})
This function processes pending input events. It returns
@code{emacs_process_input_quit} if the user wants to quit or an error
occurred while processing signals. In that case, we recommend that
@@ -2135,7 +2135,7 @@ Therefore, we recommend that your module functions check for nonlocal
exit conditions and recover from them, using the functions described
below.
-@deftypefn Function enum emacs_funcall_exit non_local_exit_check (emacs_env *@var{env})
+@deftypefn Function {enum emacs_funcall_exit} non_local_exit_check (emacs_env *@var{env})
This function returns the kind of nonlocal exit condition stored in
@var{env}. The possible values are:
@@ -2150,7 +2150,7 @@ The last @acronym{API} function exited via @code{throw}.
@end vtable
@end deftypefn
-@deftypefn Function enum emacs_funcall_exit non_local_exit_get (emacs_env *@var{env}, emacs_value *@var{symbol}, emacs_value *@var{data})
+@deftypefn Function {enum emacs_funcall_exit} non_local_exit_get (emacs_env *@var{env}, emacs_value *@var{symbol}, emacs_value *@var{data})
This function returns the kind of nonlocal exit condition stored in
@var{env}, like @code{non_local_exit_check} does, but it also returns
the full information about the nonlocal exit, if any. If the return
diff --git a/doc/lispref/intro.texi b/doc/lispref/intro.texi
index 5afd2f4ecf2..975215d6976 100644
--- a/doc/lispref/intro.texi
+++ b/doc/lispref/intro.texi
@@ -503,9 +503,11 @@ if the information is not available.
@example
@group
emacs-build-time
- @result{} (20614 63694 515336 438000)
+ @result{} (25194 55894 8547 617000)
@end group
@end example
+(This timestamp is @code{(1651169878008547617 . 1000000000)}
+if @code{current-time-list} was @code{nil} when Emacs was built.)
@end defvar
@defvar emacs-version
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 9d3dc8fe420..f5341f40f0a 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -579,11 +579,10 @@ override any non-@code{nil} binding in any other of the @var{maps}.
@code{button-buffer-map} and @code{special-mode-map}:
@example
-(defvar help-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map
- (make-composed-keymap button-buffer-map special-mode-map))
- ... map) ... )
+(defvar-keymap help-mode-map
+ :parent (make-composed-keymap button-buffer-map
+ special-mode-map)
+ ...)
@end example
@@ -1064,6 +1063,20 @@ The optional argument @var{on-exit}, if non-@code{nil}, specifies a
function that is called, with no arguments, after @var{keymap} is
deactivated.
+The optional argument @var{message} specifies the message to display
+after activating the transient map. If @var{message} is a string, it
+is the format string for the message, and any @samp{%k} specifier in
+that string is replaced with the list of keys from the transient map.
+Any other non-@code{nil} value of @var{message} stands for the default
+message format @samp{Repeat with %k}.
+
+@vindex set-transient-map-timeout
+If the optional argument @var{timeout} is non-@code{nil}, it should be
+a number that specifies how many seconds of idle time to wait before
+deactivating @var{keymap}. The value of the variable
+@code{set-transient-map-timeout}, if non-@code{nil}, overrides the
+value of this argument.
+
This function works by adding and removing @var{keymap} from the
variable @code{overriding-terminal-local-map}, which takes precedence
over all other active keymaps (@pxref{Searching Keymaps}).
@@ -1643,7 +1656,7 @@ non-@code{nil}, the definition will be removed. This is almost the
same as setting the definition to @code{nil}, but makes a difference
if the @var{keymap} has a parent, and @var{key} is shadowing the same
binding in the parent. With @var{remove}, subsequent lookups will
-return the binding in the parent, and with a nil @var{def}, the
+return the binding in the parent, whereas with a @code{nil} definition the
lookups will return @code{nil}.
@end defun
@@ -2209,6 +2222,11 @@ If @var{no-remap} is @code{nil}, return the bindings for
non-@code{nil}, return the bindings for @var{command}, ignoring the
fact that it is remapped.
@end table
+
+If a command maps to a key binding like @code{[some-event]}, and
+@code{some-event} has a symbol plist containing a non-@code{nil}
+@code{non-key-event} property, then that binding is ignored by
+@code{where-is-internal}.
@end defun
@deffn Command describe-bindings &optional prefix buffer-or-name
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index 4a862ab0de2..a4f0ba815b1 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -1925,9 +1925,10 @@ and later discarded; this is not possible with a property list.
The following functions can be used to manipulate property lists.
They all compare property names using @code{eq}.
-@defun plist-get plist property
+@defun plist-get plist property &optional predicate
This returns the value of the @var{property} property stored in the
-property list @var{plist}. It accepts a malformed @var{plist}
+property list @var{plist}. Comparisons are done with @var{predicate},
+and defaults to @code{eq}. It accepts a malformed @var{plist}
argument. If @var{property} is not found in the @var{plist}, it
returns @code{nil}. For example,
@@ -1943,9 +1944,10 @@ returns @code{nil}. For example,
@end example
@end defun
-@defun plist-put plist property value
+@defun plist-put plist property value &optional predicate
This stores @var{value} as the value of the @var{property} property in
-the property list @var{plist}. It may modify @var{plist} destructively,
+the property list @var{plist}. Comparisons are done with @var{predicate},
+and defaults to @code{eq}. It may modify @var{plist} destructively,
or it may construct a new list structure without altering the old. The
function returns the modified property list, so you can store that back
in the place where you got @var{plist}. For example,
@@ -1961,19 +1963,20 @@ in the place where you got @var{plist}. For example,
@end defun
@defun lax-plist-get plist property
-Like @code{plist-get} except that it compares properties
-using @code{equal} instead of @code{eq}.
+This obsolete function is like @code{plist-get} except that it
+compares properties using @code{equal} instead of @code{eq}.
@end defun
@defun lax-plist-put plist property value
-Like @code{plist-put} except that it compares properties
-using @code{equal} instead of @code{eq}.
+This obsolete function is like @code{plist-put} except that it
+compares properties using @code{equal} instead of @code{eq}.
@end defun
-@defun plist-member plist property
+@defun plist-member plist property &optional predicate
This returns non-@code{nil} if @var{plist} contains the given
-@var{property}. Unlike @code{plist-get}, this allows you to distinguish
-between a missing property and a property with the value @code{nil}.
-The value is actually the tail of @var{plist} whose @code{car} is
-@var{property}.
+@var{property}. Comparisons are done with @var{predicate}, and
+defaults to @code{eq}. Unlike @code{plist-get}, this allows you to
+distinguish between a missing property and a property with the value
+@code{nil}. The value is actually the tail of @var{plist} whose
+@code{car} is @var{property}.
@end defun
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 5957b8ac385..54fc16ec9f0 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -149,10 +149,9 @@ up the execution of uncompiled code. Sometimes, this macro expansion
cannot be done, owing to a cyclic dependency. In the simplest
example of this, the file you are loading refers to a macro defined
in another file, and that file in turn requires the file you are
-loading. This is generally harmless. Emacs prints a warning
+loading. Emacs will issue an error about
(@samp{Eager macro-expansion skipped due to cycle@dots{}})
-giving details of the problem, but it still loads the file, just
-leaving the macro unexpanded for now. You may wish to restructure
+giving details of the problem. You have to restructure
your code so that this does not happen. Loading a compiled file does
not cause macroexpansion, because this should already have happened
during compilation. @xref{Compiling Macros}.
@@ -529,7 +528,7 @@ primitive for autoloading; any Lisp program can call @code{autoload} at
any time. Magic comments are the most convenient way to make a function
autoload, for packages installed along with Emacs. These comments do
nothing on their own, but they serve as a guide for the command
-@code{update-file-autoloads}, which constructs calls to @code{autoload}
+@code{loaddefs-generate}, which constructs calls to @code{autoload}
and arranges to execute them when Emacs is built.
@defun autoload function filename &optional docstring interactive type
@@ -627,22 +626,19 @@ subroutines not loaded successfully because they come later in the file.
macro, then an error is signaled with data @code{"Autoloading failed to
define function @var{function-name}"}.
-@findex update-file-autoloads
-@findex make-directory-autoloads
+@findex loaddefs-generate
@cindex magic autoload comment
@cindex autoload cookie
@anchor{autoload cookie}
A magic autoload comment (often called an @dfn{autoload cookie})
consists of @samp{;;;###autoload}, on a line by itself,
just before the real definition of the function in its
-autoloadable source file. The command @kbd{M-x update-file-autoloads}
+autoloadable source file. The function @code{loaddefs-generate}
writes a corresponding @code{autoload} call into @file{loaddefs.el}.
(The string that serves as the autoload cookie and the name of the
-file generated by @code{update-file-autoloads} can be changed from the
+file generated by @code{loaddefs-generate} can be changed from the
above defaults, see below.)
Building Emacs loads @file{loaddefs.el} and thus calls @code{autoload}.
-@kbd{M-x make-directory-autoloads} is even more powerful; it updates
-autoloads for all files in the current directory.
The same magic comment can copy any kind of form into
@file{loaddefs.el}. The form following the magic comment is copied
@@ -675,7 +671,7 @@ and @code{define-global-minor-mode}.
@emph{without} executing it when the file itself is loaded. To do this,
write the form @emph{on the same line} as the magic comment. Since it
is in a comment, it does nothing when you load the source file; but
-@kbd{M-x update-file-autoloads} copies it to @file{loaddefs.el}, where
+@code{loaddefs-generate} copies it to @file{loaddefs.el}, where
it is executed while building Emacs.
The following example shows how @code{doctor} is prepared for
@@ -728,11 +724,11 @@ corresponding autoload calls written into a file whose name is
different from the default @file{loaddefs.el}. Emacs provides two
variables to control this:
-@defvar generate-autoload-cookie
-The value of this variable should be a string whose syntax is a Lisp
-comment. @kbd{M-x update-file-autoloads} copies the Lisp form that
-follows the cookie into the autoload file it generates. The default
-value of this variable is @code{";;;###autoload"}.
+@defvar lisp-mode-autoload-regexp
+The value of this constant is a regexp that matches autoload cookies.
+@code{loaddefs-generate} copies the Lisp form that follows the
+cookie into the autoload file it generates. This will match comments
+like @samp{;;;###autoload} and @samp{;;;###calc-autoload}.
@end defvar
@defvar generated-autoload-file
@@ -769,7 +765,7 @@ contain definitions matching the prefix being completed. The variable
@code{definition-prefixes} holds a hashtable which maps a prefix to
the corresponding list of files to load for it. Entries to this
mapping are added by calls to @code{register-definition-prefixes}
-which are generated by @code{update-file-autoloads}
+which are generated by @code{loaddefs-generate}
(@pxref{Autoload}). Files which don't contain any definitions worth
loading (test files, for examples), should set
@code{autoload-compute-prefixes} to @code{nil} as a file-local
@@ -1067,13 +1063,8 @@ list elements have these forms:
The symbol @var{var} was defined as a variable.
@item (defun . @var{fun})
The function @var{fun} was defined.
-@item (t . @var{fun})
-The function @var{fun} was previously an autoload before this library
-redefined it as a function. The following element is always
@code{(defun . @var{fun})}, which represents defining @var{fun} as a
function.
-@item (autoload . @var{fun})
-The function @var{fun} was defined as an autoload.
@item (defface . @var{face})
The face @var{face} was defined.
@item (require . @var{feature})
@@ -1096,6 +1087,23 @@ The value of @code{load-history} may have one element whose @sc{car} is
by adding the symbols defined to the element for the file being visited,
rather than replacing that element. @xref{Eval}.
+@kindex function-history @r{(function symbol property)}
+In addition to @code{load-history}, every function keeps track of its
+own history in the symbol property @code{function-history}.
+The reason why functions are treated specially in this respect is that
+it is common for functions to be defined in two steps in two different
+files (typically, one of them is an autoload), so in order to be
+able to properly @emph{unload} a file, we need to know more precisely
+what that file did to the function definition.
+
+The symbol property @code{function-history} holds a list of the form
+@w{@code{(@var{file1} @var{def2} @var{file2} @var{def3} ...)}}, where
+@var{file1} is the last file that changed the definition and
+@var{def2} was the definition before @var{file1}, set by @var{file2},
+etc. Logically this list should end with the name of the first file
+that defined this function, but to save space this last element
+is usually omitted.
+
@node Unloading
@section Unloading
@cindex unloading packages
@@ -1110,7 +1118,7 @@ It undefines all functions, macros, and variables defined in that
library with @code{defun}, @code{defalias}, @code{defsubst},
@code{defmacro}, @code{defconst}, @code{defvar}, and @code{defcustom}.
It then restores any autoloads formerly associated with those symbols.
-(Loading saves these in the @code{autoload} property of the symbol.)
+(Loading saves these in the @code{function-history} property of the symbol.)
Before restoring the previous definitions, @code{unload-feature} runs
@code{remove-hook} to remove functions defined by the library from certain
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index f05f087ba70..f2adc01c8f7 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -244,6 +244,13 @@ This function works by calling the
value))
@end group
@end smallexample
+
+@findex read-string-from-buffer
+If you have a long string (for instance, one that is several lines
+long) that you wish to edit, using @code{read-string} may not be
+ideal. In that case, popping to a new, normal buffer where the user
+can edit the string may be more convenient, and you can use the
+@code{read-string-from-buffer} function to do that.
@end defun
@defun read-regexp prompt &optional defaults history
@@ -302,6 +309,22 @@ The optional argument @var{history}, if non-@code{nil}, is a symbol
specifying a minibuffer history list to use (@pxref{Minibuffer
History}). If it is omitted or @code{nil}, the history list defaults
to @code{regexp-history}.
+
+@cindex @code{case-fold}, text property
+@findex read-regexp-case-fold-search
+The user can use the @kbd{M-c} command to indicate whether case
+folding should be on or off. If the user has used this command, the
+returned string will have the text property @code{case-fold} set to
+either @code{fold} or @code{inhibit-fold}. It is up to the caller of
+@code{read-regexp} to actually use this value, and the convenience
+function @code{read-regexp-case-fold-search} is provided for that. A
+typical usage pattern here might look like:
+
+@lisp
+(let* ((regexp (read-regexp "Search for: "))
+ (case-fold-search (read-regexp-case-fold-search regexp)))
+ (re-search-forward regexp))
+@end lisp
@end defun
@defopt read-regexp-defaults-function
@@ -1115,6 +1138,11 @@ completion command (i.e., one of the commands in
not an element of @var{collection}. @xref{Completion Commands}.
@item
+If a function, it is called with the input as the only argument. The
+function should return a non-@code{nil} value if the input is
+acceptable.
+
+@item
Any other value of @var{require-match} behaves like @code{t}, except
that the exit commands won't exit if it performs completion.
@end itemize
@@ -1936,6 +1964,7 @@ completion function is trying to complete. If the symbol matches one
of the keys in @code{completion-category-overrides}, the usual
completion behavior is overridden. @xref{Completion Variables}.
+@cindex @code{annotation-function}, in completion
@item annotation-function
The value should be a function for @dfn{annotating} completions. The
function should take one argument, @var{string}, which is a possible
@@ -1945,6 +1974,7 @@ Unless this function puts own face on the annotation suffix string,
the @code{completions-annotations} face is added by default to
that string.
+@cindex @code{affixation-function}, in completion
@item affixation-function
The value should be a function for adding prefixes and suffixes to
completions. The function should take one argument,
@@ -1955,6 +1985,7 @@ the completion string in the @file{*Completions*} buffer, and
a suffix displayed after the completion string. This function
takes priority over @code{annotation-function}.
+@cindex @code{group-function}, in completion
@item group-function
The value should be a function for grouping the completion candidates.
The function must take two arguments, @var{completion}, which is a
@@ -1965,12 +1996,14 @@ can also be @code{nil}. Otherwise the function must return the
transformed candidate. The transformation can for example remove a
redundant prefix, which is displayed in the group title.
+@cindex @code{display-sort-function}, in completion
@item display-sort-function
The value should be a function for sorting completions. The function
should take one argument, a list of completion strings, and return a
sorted list of completion strings. It is allowed to alter the input
list destructively.
+@cindex @code{cycle-sort-function}, in completion
@item cycle-sort-function
The value should be a function for sorting completions, when
@code{completion-cycle-threshold} is non-@code{nil} and the user is
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 5fc831536e8..2ba37e413c0 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -762,6 +762,9 @@ uncompression packages: an entry of the form @code{("\\.gz\\'"
@var{function} t)} can uncompress the file and then put the uncompressed
file in the proper mode according to the name sans @samp{.gz}.
+If @code{auto-mode-alist} has more than one element whose @var{regexp}
+matches the file name, Emacs will use the first match.
+
Here is an example of how to prepend several pattern pairs to
@code{auto-mode-alist}. (You might use this sort of expression in your
init file.)
@@ -1058,12 +1061,22 @@ very end of every properly-written major mode command.
@cindex Tabulated List mode
Tabulated List mode is a major mode for displaying tabulated data,
-i.e., data consisting of @dfn{entries}, each entry occupying one row of
-text with its contents divided into columns. Tabulated List mode
+i.e., data consisting of @dfn{entries}, each entry occupying one row
+of text with its contents divided into columns. Tabulated List mode
provides facilities for pretty-printing rows and columns, and sorting
the rows according to the values in each column. It is derived from
Special mode (@pxref{Basic Major Modes}).
+@findex make-vtable
+@cindex variable pitch tables
+ Tabulated List mode is geared towards displaying text using
+monospaced fonts, using a single font and text size. If you want to
+display a table using variable pitch fonts or images,
+@code{make-vtable} can be used instead. vtable also support having
+more than a single table in a buffer, or having a buffer that contains
+both a table and additional text in it. @xref{Introduction,,, vtable},
+for more information.
+
Tabulated List mode is intended to be used as a parent mode by a more
specialized major mode. Examples include Process Menu mode
(@pxref{Process Information}) and Package Menu mode (@pxref{Package
@@ -1899,6 +1912,16 @@ This means ``use in modes derived from @code{text-mode}, but nowhere
else''. (There's an implicit @code{nil} element at the end.)
@end defmac
+@findex buffer-local-restore-state
+@defmac buffer-local-set-state variable value...
+Minor modes often set buffer-local variables that affect some features
+in Emacs. When a minor mode is switched off, the mode is expected to
+restore the previous state of these variables. This convenience macro
+helps with doing that: It works much like @code{setq-local}, but
+returns an object that can be used to restore these values back to
+their previous values/states (using the companion function
+@code{buffer-local-restore-state}).
+@end defmac
@node Mode Line Format
@section Mode Line Format
@@ -1961,8 +1984,26 @@ This function also forces an update of the menu bar and frame title.
@end defun
The selected window's mode line is usually displayed in a different
-color using the face @code{mode-line}. Other windows' mode lines appear
-in the face @code{mode-line-inactive} instead. @xref{Faces}.
+color using the face @code{mode-line-active}. Other windows' mode
+lines appear in the face @code{mode-line-inactive} instead.
+@xref{Faces}.
+
+@defun mode-line-window-selected-p
+If you want to have more extensive differences between the mode lines
+in selected and non-selected windows, you can use this predicate in an
+@code{:eval} construct. For instance, if you want to display the
+buffer name in bold in selected windows, but in italics in the other
+windows, you can say something like:
+
+@lisp
+(setq-default
+ mode-line-buffer-identification
+ '(:eval (propertize "%12b"
+ 'face (if (mode-line-window-selected-p)
+ 'bold
+ 'italic))))
+@end lisp
+@end defun
@vindex mode-line-compact
Some modes put a lot of data in the mode line, pushing elements at
@@ -2534,7 +2575,23 @@ mode line feature, except that it's controlled by
This variable, local in every buffer, specifies how to display the
header line, for windows displaying the buffer. The format of the value
is the same as for @code{mode-line-format} (@pxref{Mode Line Data}).
-It is normally @code{nil}, so that ordinary buffers have no header line.
+It is normally @code{nil}, so that ordinary buffers have no header
+line.
+
+@findex header-line-indent-mode
+If @code{display-line-numbers-mode} is used, and you want the header
+line to be indented by the same amount as the buffer contents, you can
+use the @code{header-line-indent-mode} minor mode. This minor mode
+keeps the @code{header-line-indent} variable updated, so that you can
+say something like:
+
+@lisp
+(setq header-line-format
+ `("" header-line-format ,my-header-line))
+@end lisp
+
+This can be useful if you're displaying columnar data, and the header
+line should align with that data in the buffer.
@end defvar
@defun window-header-line-height &optional window
@@ -3173,7 +3230,9 @@ Non-@code{nil} means that regular expression matching for the sake of
You can use @code{font-lock-add-keywords} to add additional
search-based fontification rules to a major mode, and
-@code{font-lock-remove-keywords} to remove rules.
+@code{font-lock-remove-keywords} to remove rules. You can also
+customize the @code{font-lock-ignore} option to selectively disable
+fontification rules for keywords that match certain criteria.
@defun font-lock-add-keywords mode keywords &optional how
This function adds highlighting @var{keywords}, for the current buffer
@@ -3243,6 +3302,99 @@ mode @emph{and} all modes derived from it, do this instead:
font-lock-keyword-face)))))
@end smallexample
+@defopt font-lock-ignore
+@cindex selectively disabling font-lock fontifications
+This option defines conditions for selectively disabling
+fontifications due to certain Font Lock keywords. If non-@code{nil},
+its value is a list of elements of the following form:
+
+@example
+(@var{symbol} @var{condition} @dots{})
+@end example
+
+Here, @var{symbol} is a symbol, usually a major or minor mode. The
+subsequent @var{condition}s of a @var{symbol}'s list element will be in
+effect if @var{symbol} is bound and its value is non-@code{nil}. For
+a mode's symbol, it means that the current major mode is derived from
+that mode, or that minor mode is enabled in the buffer. When a
+@var{condition} is in effect, any fontifications caused by
+@code{font-lock-keywords} elements that match the @var{condition} will
+be disabled.
+
+Each @var{condition} can be one of the following:
+
+@table @asis
+@item a symbol
+This condition matches any element of Font Lock keywords that
+references the symbol. This is usually a face, but can be any symbol
+referenced by an element of the @code{font-lock-keywords} list. The
+symbol can contain wildcards: @code{*} matches any string in the
+symbol'ss name, @code{?} matches a single character, and
+@code{[@var{char-set}]}, where @var{char-set} is a string of one or
+more characters, matches a single character from the set.
+
+@item a string
+This condition matches any element of Font Lock keywords whose
+@var{matcher} is a regexp which matches the string. In other words,
+this condition matches a Font Lock rule which highlights the string.
+Thus, the string could be a specific program keyword whose
+highlighting you want to disable.
+
+@item @code{(pred @var{function})}
+This condition matches any element of Font Lock keywords for which
+@var{function}, when called with the element as the argument, returns
+non-@code{nil}.
+
+@item @code{(not @var{condition})}
+This matches if @var{condition} doesn’t.
+
+@item @code{(and @var{condition} @dots{})}
+This matches if each of the @var{condition}s matches.
+
+@item @code{(or @var{condition} @dots{})}
+This matches if at least one of the @var{condition}s matches.
+
+@item @code{(except @var{condition})}
+This condition can only be used at top level or inside an
+@code{or} clause. It undoes the effect of a previously matching
+condition on the same level.
+@end table
+@end defopt
+
+As an example, consider the following setting:
+
+@smallexample
+(setq font-lock-ignore
+ '((prog-mode font-lock-*-face
+ (except help-echo))
+ (emacs-lisp-mode (except ";;;###autoload)")
+ (whitespace-mode whitespace-empty-at-bob-regexp)
+ (makefile-mode (except *))))
+@end smallexample
+
+Line by line, this does the following:
+
+@enumerate
+@item
+In all programming modes, disable fontifications due to all font-lock
+keywords that apply one of the standard font-lock faces (excluding
+strings and comments, which are covered by syntactic Font Lock).
+
+@item
+However, keep any keywords that add a @code{help-echo} text property.
+
+@item
+In Emacs Lisp mode, also keep the highlighting of autoload cookies,
+which would have been excluded by the first condition.
+
+@item
+When @code{whitespace-mode} (a minor mode) is enabled, also don't
+highlight an empty line at beginning of buffer.
+
+@item
+Finally, in Makefile mode, don't apply any conditions.
+@end enumerate
+
@node Other Font Lock Variables
@subsection Other Font Lock Variables
@@ -3321,7 +3473,8 @@ fontification functions, and gives it two arguments, @var{start} and
@var{end}, which specify the region to be fontified or refontified.
If @var{function} performs fontifications, it can return a list of the
form @w{@code{(jit-lock-bounds @var{beg} . @var{end})}}, to indicate
-the bounds of the region it actually fontified; JIT font-lock will use
+the bounds of the region it actually fontified; Just-In-Time (a.k.a.@:
+@acronym{``JIT''}) font-lock will use
this information to optimize subsequent redisplay cycles and regions
of buffer text it will pass to future calls to @var{function}.
@@ -3341,6 +3494,19 @@ If @var{function} was previously registered as a fontification
function using @code{jit-lock-register}, this function unregisters it.
@end defun
+@cindex debugging font-lock
+@cindex jit-lock functions, debugging
+@deffn Command jit-lock-debug-mode &optional arg
+This is a minor mode whose purpose is to help in debugging code that
+is run by JIT font-lock. When this mode is enabled, most of the code
+that JIT font-lock normally runs during redisplay cycles, where Lisp
+errors are suppressed, is instead run by a timer. Thus, this mode
+allows using debugging aids such as @code{debug-on-error}
+(@pxref{Error Debugging}) and Edebug (@pxref{Edebug}) for finding and
+fixing problems in font-lock code and any other code run by JIT
+font-lock.
+@end deffn
+
@node Levels of Font Lock
@subsection Levels of Font Lock
@@ -3513,6 +3679,10 @@ the value is @code{nil}, Font Lock will call @code{jit-lock-register}
(@pxref{Other Font Lock Variables}) to set up for automatic
refontification of buffer text following a modified line to reflect
the new syntactic context due to the change.
+
+To use only syntactic fontification, this variable should
+be non-@code{nil}, while @code{font-lock-keywords} should be set to
+@code{nil} (@pxref{Font Lock Basics}).
@end defvar
@defvar font-lock-syntax-table
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index f495910fcd6..6dc23637a79 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -280,11 +280,12 @@ to the codepoints @code{#x3FFF80} through @code{#x3FFFFF}, inclusive
@defun string-to-unibyte string
This function returns a unibyte string containing the same sequence of
-characters as @var{string}. It signals an error if @var{string}
-contains a non-@acronym{ASCII} character. If @var{string} is a
-unibyte string, it is returned unchanged. Use this function for
-@var{string} arguments that contain only @acronym{ASCII} and eight-bit
-characters.
+characters as @var{string}. If @var{string} is a unibyte string, it
+is returned unchanged. Otherwise, @acronym{ASCII} characters and
+characters in the @code{eight-bit} charset are converted to their
+corresponding byte values. Use this function for @var{string}
+arguments that contain only @acronym{ASCII} and eight-bit characters;
+the function signals an error if any other characters are encountered.
@end defun
@defun byte-to-string byte
@@ -855,15 +856,24 @@ function to all or part of the characters in a charset:
Call @var{function} for characters in @var{charset}. @var{function}
is called with two arguments. The first one is a cons cell
@code{(@var{from} . @var{to})}, where @var{from} and @var{to}
-indicate a range of characters contained in charset. The second
-argument passed to @var{function} is @var{arg}.
+indicate a range of characters contained in @var{charset}. The second
+argument passed to @var{function} is @var{arg}, or @code{nil} if
+@var{arg} is omitted.
By default, the range of codepoints passed to @var{function} includes
all the characters in @var{charset}, but optional arguments
@var{from-code} and @var{to-code} limit that to the range of
characters between these two codepoints of @var{charset}. If either
of them is @code{nil}, it defaults to the first or last codepoint of
-@var{charset}, respectively.
+@var{charset}, respectively. Note that @var{from-code} and
+@var{to-code} are @var{charset}'s codepoints, not the Emacs codes of
+characters; by contrast, the values @var{from} and @var{to} in the
+cons cell passed to @var{function} @emph{are} Emacs character codes.
+Those Emacs character codes are either Unicode code points, or Emacs
+internal code points that extend Unicode and are beyond the Unicode
+range of characters @code{0..#x10FFFF} (@pxref{Text Representations}).
+The latter happens rarely, with legacy CJK charsets for codepoints of
+@var{charset} which specify characters not yet unified with Unicode.
@end defun
@node Scanning Charsets
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 07caaa2a07a..1bae1924557 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -178,6 +178,12 @@ files.
Skip the next @samp{N} characters (@pxref{Comments}). This is used in
byte-compiled files, and is not meant to be used in Emacs Lisp source
files.
+
+@item #f
+Indicates that the following form isn't readable by the Emacs Lisp
+reader. This is only in text for display purposes (when that would
+look prettier than alternative ways of indicating an unreadable form)
+and will never appear in any Lisp file.
@end table
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 3750abc4e8a..2b49818ed33 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -329,10 +329,10 @@ file will not inhibit the message for someone else.
@end defopt
@defopt initial-scratch-message
-This variable, if non-@code{nil}, should be a string, which is
-treated as documentation to be
-inserted into the @file{*scratch*} buffer when Emacs starts up. If it
-is @code{nil}, the @file{*scratch*} buffer is empty.
+This variable, if non-@code{nil}, should be a string, which is treated
+as documentation to be inserted into the @file{*scratch*} buffer when
+Emacs starts up or when that buffer is recreated. If it is
+@code{nil}, the @file{*scratch*} buffer is empty.
@end defopt
@noindent
@@ -363,6 +363,9 @@ Do not load the @file{site-start} library.
@itemx -Q
Equivalent to @samp{-q --no-site-file --no-splash}.
@c and --no-site-lisp, but let's not mention that here.
+
+@item --init-directory
+Specify the directory to use when finding the Emacs init files.
@end table
@@ -696,7 +699,7 @@ If you started Emacs from a terminal, the parent process normally
resumes control. The low-level primitive for killing Emacs is
@code{kill-emacs}.
-@deffn Command kill-emacs &optional exit-data
+@deffn Command kill-emacs &optional exit-data restart
This command calls the hook @code{kill-emacs-hook}, then exits the
Emacs process and kills it.
@@ -711,6 +714,10 @@ input) can read them.
If @var{exit-data} is neither an integer nor a string, or is omitted,
that means to use the (system-specific) exit status which indicates
successful program termination.
+
+If @var{restart} is non-@code{nil}, instead of just exiting at the
+end, start a new Emacs process, using the same command line arguments
+as the currently running Emacs process.
@end deffn
@cindex SIGTERM
@@ -753,6 +760,13 @@ the remaining functions in this hook. Calling @code{kill-emacs}
directly does not run this hook.
@end defopt
+@deffn Command restart-emacs
+This command does the same as @code{save-buffers-kill-emacs}, but
+instead of just killing the current Emacs process at the end, it'll
+restart a new Emacs process, using the same command line arguments as
+the currently running Emacs process.
+@end deffn
+
@node Suspending Emacs
@subsection Suspending Emacs
@cindex suspending Emacs
@@ -1300,10 +1314,16 @@ zone.
@cindex Lisp timestamp
@cindex timestamp, Lisp
+@cindex Coordinated Universal Time
+@cindex Universal Time
+@cindex UTC
+@cindex leap seconds
Many functions like @code{current-time} and @code{file-attributes}
return @dfn{Lisp timestamp} values that count seconds, and that can
represent absolute time by counting seconds since the @dfn{epoch} of
-1970-01-01 00:00:00 UTC.
+1970-01-01 00:00:00 UTC (Coordinated Universal Time). Typically these
+counts ignore leap seconds; however, GNU and some other operating
+systems can be configured to count leap seconds.
Although traditionally Lisp timestamps were integer pairs, their
form has evolved and programs ordinarily should not depend on the
@@ -1325,11 +1345,7 @@ A pair of integers @code{(@var{ticks} . @var{hz})}, where @var{hz} is
positive. This represents @var{ticks}/@var{hz} seconds, which is the
same time as plain @var{ticks} if @var{hz} is 1. A common value for
@var{hz} is 1000000000, for a nanosecond-resolution
-clock.@footnote{Currently @var{hz} should be at least 65536 to avoid
-compatibility warnings when the timestamp is passed to standard
-functions, as previous versions of Emacs would interpret such a
-timestamps differently due to backward-compatibility concerns. These
-warnings are intended to be removed in a future Emacs version.}
+clock.
@item
A list of four integers @code{(@var{high} @var{low} @var{micro}
@@ -1343,7 +1359,8 @@ This represents the number of seconds using the formula:
@tex
$high \times 2^{16} + low + micro \times 10^{-6} + pico \times 10^{-12}$.
@end tex
-In some cases, functions may default to returning two- or
+If @code{current-time-list} is @code{t},
+some functions may default to returning two- or
three-element lists, with omitted @var{micro} and @var{pico}
components defaulting to zero.
On all current machines @var{pico} is a multiple of 1000, but this
@@ -1354,7 +1371,7 @@ may change as higher-resolution clocks become available.
Function arguments, e.g., the @var{time} argument to
@code{format-time-string}, accept a more-general @dfn{time value}
format, which can be a Lisp timestamp, @code{nil} for the current
-time, a single floating-point number for seconds, or a list
+time, a finite floating-point number for seconds, or a list
@code{(@var{high} @var{low} @var{micro})} or @code{(@var{high}
@var{low})} that is a truncated list timestamp with missing elements
taken to be zero.
@@ -1364,8 +1381,8 @@ Time values can be converted to and from calendrical and other forms.
Some of these conversions rely on operating system functions that
limit the range of possible time values, and signal an error such as
@samp{"Specified time is not representable"} if the
-limits are exceeded. For instance, a system may not support years
-before 1970, or years before 1901, or years far in the future.
+limits are exceeded. For instance, a system might not support
+timestamps before the epoch, or years far in the future.
You can convert a time value into
a human-readable string using @code{format-time-string}, into a Lisp
timestamp using @code{time-convert}, and into other forms using
@@ -1397,13 +1414,28 @@ The operating system limits the range of time and zone values.
@end example
@end defun
+@defvar current-time-list
+This boolean variable is a transition aid. If @code{t},
+@code{current-time} and related functions return timestamps in list
+form, typically @code{(@var{high} @var{low} @var{micro} @var{pico})};
+otherwise, they use @code{(@var{ticks} . @var{hz})} form. Currently
+this variable defaults to @code{t}, for behavior compatible with
+previous Emacs versions. Developers are encouraged to test
+timestamp-related code with this variable set to @code{nil}, as it
+will default to @code{nil} in a future Emacs version, and will be
+removed in some version after that.
+@end defvar
+
@defun current-time
This function returns the current time as a Lisp timestamp.
-Although the timestamp takes the form @code{(@var{high} @var{low}
-@var{micro} @var{pico})} in the current Emacs release, this is
-planned to change in a future Emacs version. You can use the
-@code{time-convert} function to convert a timestamp to some other
-form. @xref{Time Conversion}.
+If @code{current-time-list} is @code{nil},
+the timestamp has the form @code{(@var{ticks} . @var{hz})} where
+@var{ticks} counts clock ticks and @var{hz} is the clock ticks per second.
+Otherwise, the timestamp has the list form
+@code{(@var{high} @var{low} @var{usec} @var{psec})}.
+You can use @code{(time-convert nil t)} or @code{(time-convert nil 'list)}
+to obtain a particular form regardless of the value of
+@code{current-time-list}. @xref{Time Conversion}.
@end defun
@defun float-time &optional time
@@ -1419,6 +1451,13 @@ as @samp{0.1} but is slightly greater than 1/10.
@code{time-to-seconds} is an alias for this function.
@end defun
+@defun current-cpu-time
+Return the current @acronym{CPU} time along with its resolution. The
+return value is a pair @code{(CPU-TICKS . TICKS-PER-SEC)}. The
+@var{CPU-TICKS} counter can wrap around, so values cannot be
+meaningfully compared if too much time has passed between them.
+@end defun
+
@node Time Zone Rules
@section Time Zone Rules
@cindex time zone rules
@@ -1431,11 +1470,11 @@ to default to Universal Time with @code{(setenv "TZ" "UTC0")}. If
which is a platform-dependent default time zone.
The set of supported @env{TZ} strings is system-dependent. GNU and
-many other systems support the tzdata database, e.g.,
+many other systems support TZDB timezones, e.g.,
@samp{"America/New_York"} specifies the time zone and daylight saving
time history for locations near New York City. GNU and most other
systems support POSIX-style @env{TZ} strings, e.g.,
-@samp{"EST+5EDT,M4.1.0/2,M10.5.0/2"} specifies the rules used in New
+@samp{"EST5EDT,M4.1.0,M10.5.0"} specifies the rules used in New
York from 1987 through 2006. All systems support the string
@samp{"UTC0"} meaning Universal Time.
@@ -1487,18 +1526,20 @@ The operating system limits the range of time and zone values.
These functions convert time values (@pxref{Time of Day}) to Lisp
timestamps, or into calendrical information and vice versa.
- Many 32-bit operating systems are limited to system times containing
-32 bits of information in their seconds component; these systems
-typically handle only the times from 1901-12-13 20:45:52 through
-2038-01-19 03:14:07 Universal Time. However, 64-bit and some 32-bit operating
-systems have larger seconds components, and can represent times far in
-the past or future.
-
- Calendrical conversion functions always use the Gregorian calendar, even
-for dates before the Gregorian calendar was introduced. Year numbers
-count the number of years since the year 1 BC, and do not skip zero
+ Many operating systems use 64-bit signed integers to count seconds,
+and can represent times far in the past or future. However, some are
+more limited. For example, old-fashioned operating systems that use
+32-bit signed integers typically handle only times from 1901-12-13
+20:45:52 through 2038-01-19 03:14:07 Universal Time.
+
+ Calendrical conversion functions use the Gregorian calendar even for
+dates before the Gregorian calendar was introduced, and for dates in
+the far distant past or future for which the Gregorian calendar
+is wildly inaccurate and disagrees with common practice in scientific fields
+like astronomy and paleontology, which use Julian-calendar year lengths.
+Year numbers count since the year 1 BCE, and do not skip zero
as traditional Gregorian years do; for example, the year number
-@minus{}37 represents the Gregorian year 38 BC@.
+@minus{}37 represents the Gregorian year 38 BCE@.
@defun time-convert time &optional form
This function converts a time value into a Lisp timestamp.
@@ -1510,20 +1551,20 @@ integer, it specifies a clock frequency and this function returns an
integer-pair timestamp @code{(@var{ticks} . @var{form})}. If @var{form} is
@code{t}, this function treats it as a positive integer suitable for
representing the timestamp; for example, it is treated as 1000000000
-if @var{time} is nil and the platform timestamp has nanosecond
+if @var{time} is @code{nil} and the platform timestamp has nanosecond
resolution. If @var{form} is @code{list}, this function returns an
integer list @code{(@var{high} @var{low} @var{micro} @var{pico})}.
Although an omitted or @code{nil} @var{form} currently acts like
@code{list}, this is planned to change in a future Emacs version, so
callers requiring list timestamps should pass @code{list} explicitly.
-If @var{time} is infinite or a NaN, this function signals an error.
+If @var{time} is not a time value, this function signals an error.
Otherwise, if @var{time} cannot be represented exactly, conversion
truncates it toward minus infinity. When @var{form} is @code{t},
conversion is always exact so no truncation occurs, and the returned
clock resolution is no less than that of @var{time}. By way of
-contrast, @code{float-time} can convert any Lisp time value without
-signaling an error, although the result might not be exact.
+contrast, although @code{float-time} can also convert any time value
+without signaling an error, the result might not be exact.
@xref{Time of Day}.
For efficiency this function might return a value that is @code{eq} to
@@ -1608,62 +1649,15 @@ this default may change in future Emacs releases, so callers requiring
a particular form should specify @var{form}.
@strong{Common Lisp Note:} Common Lisp has different meanings for
-@var{dow} and @var{utcoff}, and its @var{second} is an integer between
-0 and 59 inclusive.
+@var{dow}, @code{dst} and @var{utcoff}, and its @var{second} is an
+integer between 0 and 59 inclusive.
-To access (or alter) the elements in the time value, the
+To access (or alter) the elements in the calendrical information, the
@code{decoded-time-second}, @code{decoded-time-minute},
@code{decoded-time-hour}, @code{decoded-time-day},
@code{decoded-time-month}, @code{decoded-time-year},
@code{decoded-time-weekday}, @code{decoded-time-dst} and
@code{decoded-time-zone} accessors can be used.
-
-For instance, to increase the year in a decoded time, you could say:
-
-@lisp
-(setf (decoded-time-year decoded-time)
- (+ (decoded-time-year decoded-time) 4))
-@end lisp
-
-Also see the following function.
-
-@end defun
-
-@defun decoded-time-add time delta
-This function takes a decoded time structure and adds @var{delta}
-(also a decoded time structure) to it. Elements in @var{delta} that
-are @code{nil} are ignored.
-
-For instance, if you want ``same time next month'', you
-could say:
-
-@lisp
-(let ((time (decode-time nil nil t))
- (delta (make-decoded-time :month 2)))
- (encode-time (decoded-time-add time delta)))
-@end lisp
-
-If this date doesn't exist (if you're running this on January 31st,
-for instance), then the date will be shifted back until you get a
-valid date (which will be February 28th or 29th, depending).
-
-Fields are added in a most to least significant order, so if the
-adjustment described above happens, it happens before adding days,
-hours, minutes or seconds.
-
-The values in @var{delta} can be negative to subtract values instead.
-
-The return value is a decoded time structure.
-@end defun
-
-@defun make-decoded-time &key second minute hour day month year dst zone
-Return a decoded time structure with only the given keywords filled
-out, leaving the rest @code{nil}. For instance, to get a structure
-that represents ``two months'', you could say:
-
-@lisp
-(make-decoded-time :month 2)
-@end lisp
@end defun
@defun encode-time time &rest obsolescent-arguments
@@ -1673,9 +1667,26 @@ It can act as the inverse of @code{decode-time}.
Ordinarily the first argument is a list
@code{(@var{second} @var{minute} @var{hour} @var{day} @var{month}
@var{year} @var{ignored} @var{dst} @var{zone})} that specifies a
-decoded time in the style of @code{decode-time}, so that
-@code{(encode-time (decode-time ...))} works. For the meanings of
-these list members, see the table under @code{decode-time}.
+decoded time in the style of @code{decode-time}. For the meanings of
+these list elements, see the table under @code{decode-time}.
+In particular, @var{dst} says how to interpret timestamps during a
+daylight saving fallback when timestamps are repeated.
+If @var{dst} is @minus{}1, the DST value is guessed; if it
+is @code{t} or @code{nil} the timestamp with that DST value
+is returned, with an error signaled if no such timestamp exists.
+Unfortunately a @var{dst} value of @code{t} or @code{nil} does not
+disambiguate timestamps duplicated when a TZDB-based timezone moves
+further west of Greenwich, such as disambiguating the two
+standard-time timestamps 2020-12-27 01:30 when @var{zone} is
+@samp{"Europe/Volgograd"}, which at 02:00 that day changed
+standard time from 4 to 3 hours east of Greenwich; if you need to
+handle situations like this you can use a numeric @var{zone} to
+disambiguate instead.
+
+The first argument can also be a list @code{(@var{second} @var{minute}
+@var{hour} @var{day} @var{month} @var{year})}, which is treated like
+the list @code{(@var{second} @var{minute} @var{hour} @var{day}
+@var{month} @var{year} nil -1 nil)}.
As an obsolescent calling convention, this function can be given six
or more arguments. The first six arguments @var{second},
@@ -1684,14 +1695,18 @@ specify most of the components of a decoded time. If there are more
than six arguments the @emph{last} argument is used as @var{zone} and
any other extra arguments are ignored, so that @code{(apply
#'encode-time (decode-time ...))} works. In this obsolescent
-convention, @var{zone} defaults to the current time zone rule
-(@pxref{Time Zone Rules}), and @var{dst} is treated as if it was
-@minus{}1.
+convention, @var{dst} is @minus{}1 and @var{zone} defaults to the
+current time zone rule (@pxref{Time Zone Rules}).
+When modernizing an obsolescent caller, ensure that the more-modern
+list equivalent contains 9 elements with a @code{dst} element that
+is @minus{}1, not @code{nil}.
Year numbers less than 100 are not treated specially. If you want them
to stand for years above 1900, or years above 2000, you must alter them
yourself before you call @code{encode-time}.
The operating system limits the range of time and zone values.
+However, timestamps ranging from the epoch to the near future are
+always supported.
The @code{encode-time} function acts as a rough inverse to
@code{decode-time}. For example, you can pass the output of
@@ -1704,6 +1719,33 @@ the latter to the former as follows:
You can perform simple date arithmetic by using out-of-range values for
@var{seconds}, @var{minutes}, @var{hour}, @var{day}, and @var{month};
for example, day 0 means the day preceding the given month.
+Take care when doing so, as it is common for this to fail in some cases.
+For example:
+
+@lisp
+;; Try to compute the time one month from now.
+;; Watch out; this might not work as expected.
+(let ((time (decode-time)))
+ (setf (decoded-time-month time)
+ (+ (decoded-time-month time) 1))
+ time)
+@end lisp
+
+@noindent
+Unfortunately, this code might not work as expected if the resulting
+time is invalid due to month length differences,
+daylight saving transitions, time zone changes,
+or missing leap days or leap seconds. For example, if executed on
+January 30 this code yields a nonexistent date February 30,
+which @code{encode-time} would adjust to early March.
+Similarly, adding four years to February 29, 2096 would yield the
+nonexistent date February 29, 2100; and adding one hour to 01:30 on
+March 13, 2022 in New York would yield a timestamp 02:30 that does not
+exist because clocks sprang forward from 02:00 to 03:00 that day.
+To avoid some (though not all) of the problem, you
+can base calculations on the middle of the affected unit, e.g., start
+at the 15th of the month when adding months. Alternatively, you can use the
+@file{calendar} and @file{time-date} libraries.
@end defun
@node Time Parsing
@@ -1712,9 +1754,10 @@ for example, day 0 means the day preceding the given month.
@cindex time formatting
@cindex formatting time values
- These functions convert time values to text in a string, and vice versa.
-Time values include @code{nil}, numbers, and Lisp timestamps
-(@pxref{Time of Day}).
+ These functions convert time values to text in a string, and vice
+versa. Time values are either represented as a Lisp timestamp
+(@pxref{Time of Day}) or a decoded time structure (@pxref{Time
+Conversion}).
@defun date-to-time string
This function parses the time-string @var{string} and returns the
@@ -1727,22 +1770,11 @@ The operating system limits the range of time and zone values.
@end defun
@defun parse-time-string string
-This function parses the time-string @var{string} into a list of the
-following form:
-
-@example
-(@var{sec} @var{min} @var{hour} @var{day} @var{mon} @var{year} @var{dow} @var{dst} @var{tz})
-@end example
-
-@noindent
-The format of this list is the same as what @code{decode-time} accepts
-(@pxref{Time Conversion}), and is described in more detail there. Any
-@code{dst} element that cannot be determined from the input is set to
-@minus{}1, and any other unknown element is set to
-@code{nil}. The argument @var{string} should resemble an RFC 822 (or later) or
-ISO 8601 string, like ``Fri, 25 Mar 2016 16:24:56 +0100'' or
-``1998-09-12T12:21:54-0200'', but this function will attempt to parse
-less well-formed time strings as well.
+This function parses the time-string @var{string} into a decoded time
+structure (@pxref{Time Conversion}). The argument @var{string} should
+resemble an RFC 822 (or later) or ISO 8601 string, like ``Fri, 25 Mar
+2016 16:24:56 +0100'' or ``1998-09-12T12:21:54-0200'', but this
+function will attempt to parse less well-formed time strings as well.
@end defun
@vindex ISO 8601 date/time strings
@@ -1759,11 +1791,11 @@ time structures, except the final one, which returns three of them
@end defun
@defun format-time-string format-string &optional time zone
-
-This function converts @var{time} (or the current time, if
-@var{time} is omitted or @code{nil}) to a string according to
-@var{format-string}. The conversion uses the time zone rule @var{zone}, which
-defaults to the current time zone rule. @xref{Time Zone Rules}. The argument
+This function converts @var{time} (which should be a Lisp timestamp,
+and defaults to the current time if @var{time} is omitted or
+@code{nil}) to a string according to @var{format-string}. The
+conversion uses the time zone rule @var{zone}, which defaults to the
+current time zone rule. @xref{Time Zone Rules}. The argument
@var{format-string} may contain @samp{%}-sequences which say to
substitute parts of the time. Here is a table of what the
@samp{%}-sequences mean:
@@ -1958,6 +1990,10 @@ encountered. For example, the default format used by
@w{@code{"%Y, %D, %H, %M, %z%S"}} means that the number of seconds
will always be produced, but years, days, hours, and minutes will only
be shown if they are non-zero.
+@item %x
+Non-printing control flag that works along the same lines as
+@samp{%z}, but instead suppresses printing of trailing zero-value time
+elements.
@item %%
Produces a literal @samp{%}.
@end table
@@ -2021,25 +2057,23 @@ interactively, it prints the duration in the echo area.
These functions perform calendrical computations using time values
(@pxref{Time of Day}). As with any time value, a value of
@code{nil} for any of their
-time-value arguments stands for the current system time, and a single
+time-value arguments stands for the current system time, and a finite
number stands for the number of seconds since the epoch.
@defun time-less-p t1 t2
-This returns @code{t} if time value @var{t1} is less than time value
+This returns @code{t} if the time value @var{t1} is less than the time value
@var{t2}.
-The result is @code{nil} if either argument is a NaN.
@end defun
@defun time-equal-p t1 t2
-This returns @code{t} if @var{t1} and @var{t2} are equal time values.
-The result is @code{nil} if either argument is a NaN.
+This returns @code{t} if the two time values @var{t1} and @var{t2} are
+equal.
@end defun
@defun time-subtract t1 t2
This returns the time difference @var{t1} @minus{} @var{t2} between
-two time values, as a Lisp time value. The result is exact and its clock
+two time values, as a Lisp timestamp. The result is exact and its clock
resolution is no worse than the worse of its two arguments' resolutions.
-The result is floating-point only if it is infinite or a NaN@.
If you need the difference in units
of elapsed seconds, you can convert it with @code{time-convert} or
@code{float-time}. @xref{Time Conversion}.
@@ -2291,7 +2325,8 @@ can use in calling @code{cancel-timer} (@pxref{Timers}).
@end deffn
@cindex idleness
- Emacs becomes @dfn{idle} when it starts waiting for user input, and
+ Emacs becomes @dfn{idle} when it starts waiting for user input
+(unless it waits for input with a timeout, @pxref{Reading One Event}), and
it remains idle until the user provides some input. If a timer is set
for five seconds of idleness, it runs approximately five seconds after
Emacs first becomes idle. Even if @var{repeat} is non-@code{nil},
@@ -2703,6 +2738,13 @@ if it is non-@code{nil}; this can be overridden by binding
@code{coding-system-for-write} to a coding system of you choice
(@pxref{Explicit Encoding}).
+In batch mode, Emacs will enlarge the value of the
+@code{gc-cons-percentage} variable from the default of @samp{0.1} up to
+@samp{1.0}. Batch jobs that are supposed to run for a long time
+should adjust the limit back down again, because this means that less
+garbage collection will be performed by default (and more memory
+consumed).
+
@defvar noninteractive
This variable is non-@code{nil} when Emacs is running in batch mode.
@end defvar
@@ -3094,21 +3136,21 @@ This function removes the tray notification given by its unique
@cindex watch, for filesystem events
Several operating systems support watching of filesystems for changes
-of files. If configured properly, Emacs links a respective library
-like @file{inotify}, @file{kqueue}, @file{gfilenotify}, or
-@file{w32notify} statically. These libraries enable watching of
-filesystems on the local machine.
+to files or their attributes. If configured properly, Emacs links a
+respective library like @file{inotify}, @file{kqueue},
+@file{gfilenotify}, or @file{w32notify} statically. These libraries
+enable watching of filesystems on the local machine.
It is also possible to watch filesystems on remote machines,
-@pxref{Remote Files,, Remote Files, emacs, The GNU Emacs Manual}
+@pxref{Remote Files,, Remote Files, emacs, The GNU Emacs Manual}.
This does not depend on one of the libraries linked to Emacs.
-Since all these libraries emit different events on notified file
-changes, there is the Emacs library @code{filenotify} which provides a
-unified interface. Lisp programs that want to receive file
-notifications should always use this library in preference to the
-native ones.
-
+Since all these libraries emit different events upon notified file
+changes, Emacs provides a special library @code{filenotify} which
+presents a unified interface to applications. Lisp programs that want
+to receive file notifications should always use this library in
+preference to the native ones. This section documents the
+@code{filenotify} library functions and variables.
@defun file-notify-add-watch file flags callback
Add a watch for filesystem events pertaining to @var{file}. This
@@ -3116,31 +3158,33 @@ arranges for filesystem events pertaining to @var{file} to be reported
to Emacs.
The returned value is a descriptor for the added watch. Its type
-depends on the underlying library, it cannot be assumed to be an
-integer as in the example below. It should be used for comparison by
-@code{equal} only.
+depends on the underlying library, and in general cannot be assumed to
+be an integer as in the example below. It should be used for
+comparison by @code{equal} only.
If the @var{file} cannot be watched for some reason, this function
signals a @code{file-notify-error} error.
Sometimes, mounted filesystems cannot be watched for file changes.
-This is not detected by this function, a non-@code{nil} return value
-does not guarantee that changes on @var{file} will be notified.
+This is not detected by this function, and so a non-@code{nil} return
+value does not guarantee that changes on @var{file} will be actually
+notified.
@var{flags} is a list of conditions to set what will be watched for.
It can include the following symbols:
@table @code
@item change
-watch for file changes
+watch for changes in file's contents
@item attribute-change
-watch for file attribute changes, like permissions or modification
+watch for changes in file attributes, like permissions or modification
time
@end table
If @var{file} is a directory, @code{change} watches for file creation
-or deletion in that directory. Some of the file notification backends
-report also file changes. This does not work recursively.
+and deletion in that directory. Some of the native file notification
+libraries also report file changes in that case. This does not work
+recursively.
When any event happens, Emacs will call the @var{callback} function
passing it a single argument @var{event}, which is of the form
@@ -3166,19 +3210,20 @@ reports attribute changes as well
@item attribute-changed
a @var{file} attribute was changed
@item stopped
-watching @var{file} has been stopped
+watching @var{file} has stopped
@end table
Note that the @file{w32notify} library does not report
@code{attribute-changed} events. When some file's attribute, like
permissions or modification time, has changed, this library reports a
@code{changed} event. Likewise, the @file{kqueue} library does not
-report reliably file attribute changes when watching a directory.
+reliably report file attribute changes when watching a directory.
-The @code{stopped} event reports, that watching the file has been
-stopped. This could be because @code{file-notify-rm-watch} was called
-(see below), or because the file being watched was deleted, or due to
-another error reported from the underlying library.
+The @code{stopped} event means that watching the file has been
+discontinued. This could be because @code{file-notify-rm-watch} was
+called (see below), or because the file being watched was deleted, or
+due to another error reported from the underlying library which makes
+further watching impossible.
@var{file} and @var{file1} are the name of the file(s) whose event is
being reported. For example:
@@ -3222,7 +3267,7 @@ being reported. For example:
@end group
@end example
-Whether the action @code{renamed} is returned, depends on the used
+Whether the action @code{renamed} is returned depends on the used
watch library. Otherwise, the actions @code{deleted} and
@code{created} could be returned in a random order.
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index a38a84e22b3..80c371e1c6a 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -197,7 +197,7 @@ gives special treatment to certain characters, and if these characters
occur in the file name, they will confuse the shell. To handle these
characters, use the function @code{shell-quote-argument}:
-@defun shell-quote-argument argument
+@defun shell-quote-argument argument &optional posix
This function returns a string that represents, in shell syntax,
an argument whose actual contents are @var{argument}. It should
work reliably to concatenate the return value into a shell command
@@ -227,6 +227,15 @@ a shell command:
" "
(shell-quote-argument newfile))
@end example
+
+If the optional @var{posix} argument is non-@code{nil}, @var{argument}
+is quoted according to POSIX shell quoting rules, regardless of the
+system’s shell. This is useful when your shell could run on a remote
+host, which requires a POSIX shell in general.
+
+@example
+(shell-quote-argument "foo > bar" (file-remote-p default-directory))
+@end example
@end defun
@cindex quoting and unquoting command-line arguments
@@ -1002,16 +1011,18 @@ terminated (due to calling @code{exit} or to a signal). If it is
they exit.
@end defopt
-@defun delete-process process
+@defun delete-process &optional process
This function deletes a process, killing it with a @code{SIGKILL}
signal if the process was running a program. The argument may be a
process, the name of a process, a buffer, or the name of a buffer. (A
buffer or buffer-name stands for the process that
-@code{get-buffer-process} returns.) Calling @code{delete-process} on
-a running process terminates it, updates the process status, and runs
-the sentinel immediately. If the process has already terminated,
-calling @code{delete-process} has no effect on its status, or on the
-running of its sentinel (which will happen sooner or later).
+@code{get-buffer-process} returns, and a missing or @code{nil}
+@var{process} means that the current buffer's process should be
+killed.) Calling @code{delete-process} on a running process
+terminates it, updates the process status, and runs the sentinel
+immediately. If the process has already terminated, calling
+@code{delete-process} has no effect on its status, or on the running
+of its sentinel (which will happen sooner or later).
If the process object represents a network, serial, or pipe
connection, its status changes to @code{closed}; otherwise, it changes
@@ -1422,11 +1433,13 @@ non-@code{nil}, you can think of this function as typing @kbd{C-c}
on the terminal by which Emacs talks to the subprocess.
@end defun
-@defun kill-process &optional process current-group
-This function kills the process @var{process} by sending the
+@deffn Command kill-process &optional process current-group
+This command kills the process @var{process} by sending the
signal @code{SIGKILL}. This signal kills the subprocess immediately,
-and cannot be handled by the subprocess.
-@end defun
+and cannot be handled by the subprocess. Interactively, it'll prompt
+the user for a process name, defaulting to the process (if any) in the
+current buffer.
+@end deffn
@defun quit-process &optional process current-group
This function sends the signal @code{SIGQUIT} to the process
@@ -1461,7 +1474,7 @@ incoming data from the connection. For serial connections, data that
arrived during the time the process was stopped might be lost.
@end defun
-@deffn Command signal-process process signal
+@deffn Command signal-process process signal &optional remote
This function sends a signal to process @var{process}. The argument
@var{signal} specifies which signal to send; it should be an integer,
or a symbol whose name is a signal.
@@ -1469,12 +1482,18 @@ or a symbol whose name is a signal.
The @var{process} argument can be a system process @acronym{ID} (an
integer); that allows you to send signals to processes that are not
children of Emacs. @xref{System Processes}.
+
+If @var{process} is a process object which contains the property
+@code{remote-pid}, or @var{process} is a number and @var{remote} is a
+remote file name, @var{process} is interpreted as process on the
+respective remote host, which will be the process to signal.
@end deffn
Sometimes, it is necessary to send a signal to a non-local
asynchronous process. This is possible by writing an own
-@code{interrupt-process} implementation. This function must be added
-then to @code{interrupt-process-functions}.
+@code{interrupt-process} or @code{signal-process} implementation.
+This function must be added then to @code{interrupt-process-functions}
+or @code{signal-process-functions}, respectively.
@defvar interrupt-process-functions
This variable is a list of functions to be called for
@@ -1487,6 +1506,17 @@ default function, which shall always be the last in this list, is
This is the mechanism, how Tramp implements @code{interrupt-process}.
@end defvar
+@defvar signal-process-functions
+This variable is a list of functions to be called for
+@code{signal-process}. The arguments of the functions are the same as
+for @code{signal-process}. These functions are called in the order of
+the list, until one of them returns non-@code{nil}. The default
+function, which shall always be the last in this list, is
+@code{internal-default-signal-process}.
+
+This is the mechanism, how Tramp implements @code{signal-process}.
+@end defvar
+
@node Output from Processes
@section Receiving Output from Processes
@cindex process output
@@ -2230,9 +2260,8 @@ query flag of all processes is ignored.
In addition to accessing and manipulating processes that are
subprocesses of the current Emacs session, Emacs Lisp programs can
-also access other processes running on the same machine. We call
-these @dfn{system processes}, to distinguish them from Emacs
-subprocesses.
+also access other processes. We call these @dfn{system processes}, to
+distinguish them from Emacs subprocesses.
Emacs provides several primitives for accessing system processes.
Not all platforms support these primitives; on those which don't,
@@ -2244,6 +2273,9 @@ system. Each process is identified by its @acronym{PID}, a numerical
process ID that is assigned by the OS and distinguishes the process
from all the other processes running on the same machine at the same
time.
+
+If @code{default-directory} points to a remote host, processes of that
+host are returned.
@end defun
@defun process-attributes pid
@@ -2255,6 +2287,9 @@ attribute @var{key}s that this function can return are listed below.
Not all platforms support all of these attributes; if an attribute is
not supported, its association will not appear in the returned alist.
+If @code{default-directory} points to a remote host, @var{pid} is
+regarded as process of that host.
+
@table @code
@item euid
The effective user ID of the user who invoked the process. The
@@ -2380,8 +2415,9 @@ occupied by the process in the machine's physical memory.
@item pcpu
The percentage of the CPU time used by the process since it started.
-The corresponding @var{value} is a floating-point number between 0 and
-100.
+The corresponding @var{value} is a nonnegative floating-point number.
+Although in theory the number can exceed 100 on a multicore platform,
+it is usually less than 100 because Emacs is typically single-threaded.
@item pmem
The percentage of the total physical memory installed on the machine
@@ -3434,20 +3470,64 @@ type values:
@itemx byte
Unsigned byte, with length 1.
-@item uint @var{bitlen}
-Unsigned integer in network byte order, with @var{bitlen} bits.
+@item uint @var{bitlen} &optional @var{le}
+Unsigned integer in network byte order (big-endian), with @var{bitlen} bits.
@var{bitlen} has to be a multiple of 8.
+If @var{le} is non-@code{nil}, then use little-endian byte order.
-@item uintr @var{bitlen}
-Unsigned integer in little endian order, with @var{bitlen} bits.
+@item sint @var{bitlen} @var{le}
+Signed integer in network byte order (big-endian), with @var{bitlen} bits.
@var{bitlen} has to be a multiple of 8.
+If @var{le} is non-@code{nil}, then use little-endian byte order.
@item str @var{len}
-String of bytes of length @var{len}.
+Unibyte string (@pxref{Text Representations}) of length @var{len} bytes.
+When packing, the first @var{len} bytes of the input string are copied
+to the packed output. If the input string is shorter than @var{len},
+the remaining bytes will be null (zero) unless a pre-allocated string
+was provided to @code{bindat-pack}, in which case the remaining bytes
+are left unmodified. If the input string is multibyte with only ASCII
+and @code{eight-bit} characters, it is converted to unibyte before it
+is packed; other multibyte strings signal an error. When unpacking,
+any null bytes in the packed input string will appear in the unpacked
+output.
@item strz &optional @var{len}
-Zero-terminated string of bytes, can be of arbitrary length or in a fixed-size
-field with length @var{len}.
+If @var{len} is not provided, this is a variable-length
+null-terminated unibyte string (@pxref{Text Representations}). When
+packing into @code{strz}, the entire input string is copied to the
+packed output followed by a null (zero) byte. (If pre-allocated
+string is provided for packing into @code{strz}, that pre-allocated
+string should have enough space for the additional null byte appended
+to the output string contents, @pxref{Bindat Functions}). The length
+of the packed output is the length of the input string plus one (for
+the null terminator). The input string must not contain any null
+bytes. If the input string is multibyte with only ASCII and
+@code{eight-bit} characters, it is converted to unibyte before it is
+packed; other multibyte strings signal an error. When unpacking a
+@code{strz}, the resulting output string will contain all bytes up to
+(but excluding) the null byte that terminated the input string.
+
+If @var{len} is provided, @code{strz} behaves the same as @code{str},
+but with a couple of differences:
+
+@itemize @bullet
+@item
+When packing, a null terminator is written after the packed input
+string if the number of characters in the input string is less than
+@var{len}.
+
+@item
+When unpacking, the first null byte encountered in the packed string
+is interpreted as the terminating byte, and it and all subsequent
+bytes are excluded from the result of the unpacking.
+@end itemize
+
+@quotation Caution
+The packed output will not be null-terminated unless the input string
+is shorter than @var{len} bytes or it contains a null byte within the
+first @var{len} bytes.
+@end quotation
@item vec @var{len} [@var{type}]
Vector of @var{len} elements. The type of the elements is given by
@@ -3467,7 +3547,7 @@ and @code{#x1c} @code{#x28} to @w{@code{(3 5 10 11 12)}}.
@item fill @var{len}
@var{len} bytes used as a mere filler. In packing, these bytes are
-are left unchanged, which normally means they remain zero.
+left unchanged, which normally means they remain zero.
When unpacking, this just returns nil.
@item align @var{len}
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index c9828f9c868..21a2c6c51e4 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -549,12 +549,12 @@ can act. It is poor practice to depend on this behavior; quote the
special character anyway, regardless of where it appears.
As a @samp{\} is not special inside a character alternative, it can
-never remove the special meaning of @samp{-} or @samp{]}. So you
-should not quote these characters when they have no special meaning
-either. This would not clarify anything, since backslashes can
-legitimately precede these characters where they @emph{have} special
-meaning, as in @samp{[^\]} (@code{"[^\\]"} for Lisp string syntax),
-which matches any single character except a backslash.
+never remove the special meaning of @samp{-}, @samp{^} or @samp{]}.
+You should not quote these characters when they have no special
+meaning. This would not clarify anything, since backslashes
+can legitimately precede these characters where they @emph{have}
+special meaning, as in @samp{[^\]} (@code{"[^\\]"} for Lisp string
+syntax), which matches any single character except a backslash.
In practice, most @samp{]} that occur in regular expressions close a
character alternative and hence are special. However, occasionally a
@@ -823,21 +823,22 @@ the characters that stand for them.
matches any character whose syntax is not @var{code}.
@cindex category, regexp search for
-@item \c@var{c}
-matches any character whose category is @var{c}. Here @var{c} is a
-character that represents a category: thus, @samp{c} for Chinese
-characters or @samp{g} for Greek characters in the standard category
-table. You can see the list of all the currently defined categories
-with @kbd{M-x describe-categories @key{RET}}. You can also define
-your own categories in addition to the standard ones using the
-@code{define-category} function (@pxref{Categories}).
-
-@item \C@var{c}
-matches any character whose category is not @var{c}.
+@item \c@var{code}
+matches any character whose category is @var{code}. Here @var{code}
+is a character that represents a category: for example, in the standard
+category table, @samp{c} stands for Chinese characters and @samp{g}
+stands for Greek characters. You can see the list of all the
+currently defined categories with @w{@kbd{M-x describe-categories
+@key{RET}}}. You can also define your own categories in addition to
+the standard ones using the @code{define-category} function
+(@pxref{Categories}).
+
+@item \C@var{code}
+matches any character whose category is not @var{code}.
@end table
The following regular expression constructs match the empty string---that is,
-they don't use up any characters---but whether they match depends on the
+they don't consume any characters---but whether they match depends on the
context. For all, the beginning and end of the accessible portion of
the buffer are treated as if they were the actual beginning and end of
the buffer.
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index c3f4cff3015..39230d0adc4 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -577,6 +577,20 @@ starting from the first one for which @var{predicate} returns @code{nil}.
@end example
@end defun
+@defun seq-split sequence length
+ This function returns a list consisting of sub-sequences of
+@var{sequence} of (at most) length @var{length}. (The final element
+may be shorter than @var{length} if the length of @var{sequence} isn't
+a multiple of @var{length}.
+
+@example
+@group
+(seq-split [0 1 2 3 4] 2)
+@result{} ([0 1] [2 3] [4])
+@end group
+@end example
+@end defun
+
@defun seq-do function sequence
This function applies @var{function} to each element of
@var{sequence} in turn (presumably for side effects), and returns
diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi
index c6b3397ae11..bba1dc2eee9 100644
--- a/doc/lispref/streams.texi
+++ b/doc/lispref/streams.texi
@@ -21,6 +21,7 @@ reading) or where to put it (if printing).
* Output Streams:: Various data types that can be used as output streams.
* Output Functions:: Functions to print Lisp objects as text.
* Output Variables:: Variables that control what the printing functions do.
+* Output Overrides:: Overriding output variables.
@end menu
@node Streams Intro
@@ -327,6 +328,15 @@ For example:
@end example
@end defun
+@defun read-positioning-symbols &optional stream
+This function reads one textual expression from @var{stream}, like
+@code{read} does, but additionally positions the read symbols to the
+positions in @var{stream} where they occurred. Only the symbol
+@code{nil} is not positioned, this for efficiency reasons.
+@xref{Symbols with Position}. This function is used by the byte
+compiler.
+@end defun
+
@defvar standard-input
This variable holds the default input stream---the stream that
@code{read} uses when the @var{stream} argument is @code{nil}.
@@ -358,6 +368,15 @@ mode for @var{stream}. On POSIX hosts, it always returns a
non-@code{nil} value and does nothing except flushing pending output.
@end defun
+@defun readablep object
+@cindex readable syntax
+This predicate says whether @var{object} has @dfn{readable syntax},
+i.e., it can be written out and then read back by the Emacs Lisp
+reader. If it can't, this function returns @code{nil}; if it can,
+this function returns a printed representation (via @code{prin1},
+@pxref{Output Functions}) of @var{object}.
+@end defun
+
@node Output Streams
@section Output Streams
@cindex stream (for printing)
@@ -616,7 +635,7 @@ characters are used. @code{print} returns @var{object}. For example:
@end example
@end defun
-@defun prin1 object &optional stream
+@defun prin1 object &optional stream overrides
This function outputs the printed representation of @var{object} to
@var{stream}. It does not print newlines to separate output as
@code{print} does, but it does use quoting characters just like
@@ -631,6 +650,10 @@ This function outputs the printed representation of @var{object} to
@result{} " came back"
@end group
@end example
+
+If @var{overrides} is non-@code{nil}, it should either be @code{t}
+(which tells @code{prin1} to use the defaults for all printer related
+variables), or a list of settings. @xref{Output Overrides}, for details.
@end defun
@defun princ object &optional stream
@@ -667,7 +690,16 @@ This function outputs @var{character} to @var{stream}. It returns
@var{character}.
@end defun
-@defun prin1-to-string object &optional noescape
+@defun flush-standard-output
+If you have Emacs-based batch scripts that send output to the
+terminal, Emacs will automatically display the output whenever you
+write a newline characters to @code{standard-output}. This function
+allows you to flush to @code{standard-output} without sending a
+newline character first, which enables you to display incomplete
+lines.
+@end defun
+
+@defun prin1-to-string object &optional noescape overrides
@cindex object to string
This function returns a string containing the text that @code{prin1}
would have printed for the same argument.
@@ -681,6 +713,10 @@ would have printed for the same argument.
(prin1-to-string (mark-marker))
@result{} "#<marker at 2773 in strings.texi>"
@end group
+
+If @var{overrides} is non-@code{nil}, it should either be @code{t}
+(which tells @code{prin1} to use the defaults for all printer related
+variables), or a list of settings. @xref{Output Overrides}, for details.
@end example
If @var{noescape} is non-@code{nil}, that inhibits use of quoting
@@ -872,6 +908,32 @@ If non-@code{nil}, this variable enables detection of circular and
shared structure in printing. @xref{Circular Objects}.
@end defvar
+@defvar print-unreadable-function
+By default, Emacs prints unreadable objects as @samp{#<...>"}. For
+instance:
+
+@example
+(prin1-to-string (make-marker))
+ @result{} "#<marker in no buffer>"
+@end example
+
+If this variable is non-@code{nil}, it should be a function that will
+be called to handle printing of these objects. The function will be
+called with two arguments: the object and the @var{noescape} flag used by
+the printing functions (@pxref{Output Functions}).
+
+The function should return either @code{nil} (print the object as
+usual), or a string (which will be printed), or any other object
+(don't print the object). For instance:
+
+@example
+(let ((print-unreadable-function
+ (lambda (object escape) "hello")))
+ (prin1-to-string (make-marker)))
+ @result{} "hello"
+@end example
+@end defvar
+
@defvar print-gensym
If non-@code{nil}, this variable enables detection of uninterned symbols
(@pxref{Creating Symbols}) in printing. When this is enabled,
@@ -918,3 +980,84 @@ Letter, Number, Punctuation, Symbol and Private-use
(@pxref{Character Properties}), as well as the control characters
having their own escape syntax such as newline.
@end defvar
+
+@node Output Overrides
+@section Overriding Output Variables
+@cindex overrides, in output functions
+@cindex output variables, overriding
+
+The previous section (@pxref{Output Functions}) lists the numerous
+variables that control how the Emacs Lisp printer formats data for
+outputs. These are generally available for users to change, but
+sometimes you want to output data in the default format, or override
+the user settings in some other way. For instance, if you're storing
+Emacs Lisp data in a file, you don't want that data to be shortened by
+a @code{print-length} setting.
+
+The @code{prin1} and @code{prin1-to-string} functions therefore have
+an optional @var{overrides} argument. This argument can either be
+@code{t} (which means that all printing variables should be reset to
+the default values), or a list of settings for some of the variables.
+Each element in the list can be either @code{t} (which means ``reset
+to defaults'', and will usually be the first element of the list), or
+a pair whose @code{car} is a symbol that stands for an output variable
+and whose @code{cdr} is the value for that variable.
+
+For instance, this prints using nothing but defaults:
+
+@lisp
+(prin1 object nil t)
+@end lisp
+
+This prints @var{object} using the current printing settings, but
+overrides the value of @code{print-length} to be 5:
+
+@lisp
+(prin1 object nil '((length . 5)))
+@end lisp
+
+And finally, this prints @var{object} using only default settings, but
+with @code{print-length} bound to 5:
+
+@lisp
+(prin1 object nil '(t (length . 5)))
+@end lisp
+
+Below is a list of symbols that can be used, and which variables they
+map to:
+
+@table @code
+@item length
+This overrides @code{print-length}.
+@item level
+This overrides @code{print-level}.
+@item circle
+This overrides @code{print-circle}.
+@item quoted
+This overrides @code{print-quoted}.
+@item escape-newlines
+This overrides @code{print-escape-newlines}.
+@item escape-control-characters
+This overrides @code{print-escape-control-characters}.
+@item escape-nonascii
+This overrides @code{print-escape-nonascii}.
+@item escape-multibyte
+This overrides @code{print-escape-multibyte}.
+@item charset-text-property
+This overrides @code{print-charset-text-property}.
+@item unreadeable-function
+This overrides @code{print-unreadable-function}.
+@item gensym
+This overrides @code{print-gensym}.
+@item continuous-numbering
+This overrides @code{print-continuous-numbering}.
+@item number-table
+This overrides @code{print-number-table}.
+@item float-format
+This overrides @code{float-output-format}.
+@item integers-as-characters
+This overrides @code{print-integers-as-characters}.
+@end table
+
+In the future, more overrides may be offered that do not map directly
+to a variable, but can only be used via this parameter.
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index d31807ad2aa..addf195fad2 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -434,18 +434,21 @@ display purposes; use @code{truncate-string-to-width} or
(@pxref{Size of Displayed Text}).
@end defun
-@defun string-lines string &optional omit-nulls
+@defun string-lines string &optional omit-nulls keep-newlines
Split @var{string} into a list of strings on newline boundaries. If
-@var{omit-nulls}, remove empty lines from the results.
+the optional argument @var{omit-nulls} is non-@code{nil}, remove empty
+lines from the results. If the optional argument @var{keep-newlines}
+is non-@code{nil}, don't remove the trailing newlines from the result
+strings.
@end defun
@defun string-pad string length &optional padding start
-Pad @var{string} to the be of @var{length} using @var{padding} as the
-padding character (defaulting to the space character). If
-@var{string} is shorter than @var{length}, no padding is done. If
-@var{start} is @code{nil} (or not present), the padding is done to the
-end of the string, and if it's non-@code{nil}, to the start of the
-string.
+Pad @var{string} to be of the given @var{length} using @var{padding}
+as the padding character. @var{padding} defaults to the space
+character. If @var{string} is longer than @var{length}, no padding is
+done. If @var{start} is @code{nil} or omitted, the padding is
+appended to the characters of @var{string}, and if it's
+non-@code{nil}, the padding is prepended to @var{string}'s characters.
@end defun
@defun string-chop-newline string
@@ -461,23 +464,29 @@ Remove the final newline, if any, from @var{string}.
described in this section. @xref{Mutability}.
The most basic way to alter the contents of an existing string is with
-@code{aset} (@pxref{Array Functions}). @code{(aset @var{string}
-@var{idx} @var{char})} stores @var{char} into @var{string} at index
-@var{idx}. Each character occupies one or more bytes, and if @var{char}
-needs a different number of bytes from the character already present at
-that index, @code{aset} signals an error.
+@code{aset} (@pxref{Array Functions}). @w{@code{(aset @var{string}
+@var{idx} @var{char})}} stores @var{char} into @var{string} at character
+index @var{idx}. It will automatically convert a pure-@acronym{ASCII}
+@var{string} to a multibyte string (@pxref{Text Representations}) if
+needed, but we recommend to always make sure @var{string} is multibyte
+(e.g., by using @code{string-to-multibyte}, @pxref{Converting
+Representations}), if @var{char} is a non-@acronym{ASCII} character, not
+a raw byte.
A more powerful function is @code{store-substring}:
@defun store-substring string idx obj
-This function alters part of the contents of the string @var{string}, by
-storing @var{obj} starting at index @var{idx}. The argument @var{obj}
-may be either a character or a (smaller) string.
-
-Since it is impossible to change the length of an existing string, it is
-an error if @var{obj} doesn't fit within @var{string}'s actual length,
-or if any new character requires a different number of bytes from the
-character currently present at that point in @var{string}.
+This function alters part of the contents of the specified @var{string},
+by storing @var{obj} starting at character index @var{idx}. The
+argument @var{obj} may be either a character (in which case the function
+behaves exactly as @code{aset}) or a (smaller) string. If @var{obj}
+is a multibyte string, we recommend to make sure @var{string} is also
+multibyte, even if it's pure-@acronym{ASCII}.
+
+Since it is impossible to change the number of characters in an
+existing string, it is en error if @var{obj} consists of more
+characters than would fit in @var{string} starting at character index
+@var{idx}.
@end defun
To clear out a string that contained a password, use
@@ -853,9 +862,7 @@ between 2 and 16 (inclusive), and integers are converted in that base.
If @var{base} is @code{nil}, then base ten is used. Floating-point
conversion only works in base ten; we have not implemented other
radices for floating-point numbers, because that would be much more
-work and does not seem useful. If @var{string} looks like an integer
-but its value is too large to fit into a Lisp integer,
-@code{string-to-number} returns a floating-point result.
+work and does not seem useful.
The parsing skips spaces and tabs at the beginning of @var{string},
then reads as much of @var{string} as it can interpret as a number in
@@ -1347,7 +1354,7 @@ given width, if specified.
This flag converts the substituted text to upper case (@pxref{Case
Conversion}).
-@item _
+@item _@r{ (underscore)}
This flag converts the substituted text to lower case (@pxref{Case
Conversion}).
@end table
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index a951e9be8ae..336fa9c9182 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -23,15 +23,15 @@ otherwise.
@end defun
@menu
-* Symbol Components:: Symbols have names, values, function definitions
+* Symbol Components:: Symbols have names, values, function definitions
and property lists.
-* Definitions:: A definition says how a symbol will be used.
-* Creating Symbols:: How symbols are kept unique.
-* Symbol Properties:: Each symbol has a property list
+* Definitions:: A definition says how a symbol will be used.
+* Creating Symbols:: How symbols are kept unique.
+* Symbol Properties:: Each symbol has a property list
for recording miscellaneous information.
-* Shorthands:: Properly organize your symbol names but
+* Shorthands:: Properly organize your symbol names but
type less of them.
-
+* Symbols with Position:: Symbol variants containing integer positions
@end menu
@node Symbol Components
@@ -432,8 +432,8 @@ symbol's property list cell (@pxref{Symbol Components}), in the form
of a property list (@pxref{Property Lists}).
@menu
-* Symbol Plists:: Accessing symbol properties.
-* Standard Properties:: Standard meanings of symbol properties.
+* Symbol Plists:: Accessing symbol properties.
+* Standard Properties:: Standard meanings of symbol properties.
@end menu
@node Symbol Plists
@@ -751,3 +751,70 @@ those names.
@item
Symbol forms whose names start with @samp{#_} are not transformed.
@end itemize
+
+@node Symbols with Position
+@section Symbols with Position
+@cindex symbol with position
+
+@cindex bare symbol
+A @dfn{symbol with position} is a symbol, the @dfn{bare symbol},
+together with an unsigned integer called the @dfn{position}. These
+objects are intended for use by the byte compiler, which records in
+them the position of each symbol occurrence and uses those positions
+in warning and error messages.
+
+The printed representation of a symbol with position uses the hash
+notation outlined in @ref{Printed Representation}. It looks like
+@samp{#<symbol foo at 12345>}. It has no read syntax. You can cause
+just the bare symbol to be printed by binding the variable
+@code{print-symbols-bare} to non-@code{nil} around the print
+operation. The byte compiler does this before writing its output to
+the compiled Lisp file.
+
+For most purposes, when the flag variable
+@code{symbols-with-pos-enabled} is non-@code{nil}, symbols with
+positions behave just as bare symbols do. For example, @samp{(eq
+#<symbol foo at 12345> foo)} has a value @code{t} when that variable
+is set (but @code{nil} when it isn't set). Most of the time in Emacs this
+variable is @code{nil}, but the byte compiler binds it to @code{t}
+when it runs.
+
+Typically, symbols with position are created by the byte compiler
+calling the reader function @code{read-positioning-symbols}
+(@pxref{Input Functions}). One can also be created with the function
+@code{position-symbol}.
+
+@defvar symbols-with-pos-enabled
+When this variable is non-@code{nil}, symbols with position behave
+like the contained bare symbol. Emacs runs a little more slowly in
+this case.
+@end defvar
+
+@defvar print-symbols-bare
+When bound to non-nil, the Lisp printer prints only the bare symbol of
+a symbol with position, ignoring the position.
+@end defvar
+
+@defun symbol-with-pos-p symbol.
+This function returns @code{t} if @var{symbol} is a symbol with
+position, @code{nil} otherwise.
+@end defun
+
+@defun bare-symbol symbol
+This function returns the bare symbol contained in @var{symbol}, or
+@var{symbol} itself if it is already a bare symbol. For any other
+type of object, it signals an error.
+@end defun
+
+@defun symbol-with-pos-pos symbol
+This function returns the position, a number, from a symbol with
+position. For any other type of object, it signals an error.
+@end defun
+
+@defun position-symbol sym pos
+Make a new symbol with position. @var{sym} is either a bare symbol or
+a symbol with position, and supplies the symbol part of the new
+object. @var{pos} is either an integer which becomes the number part
+of the new object, or a symbol with position whose position is used.
+Emacs signals an error if either argument is invalid.
+@end defun
diff --git a/doc/lispref/syntax.texi b/doc/lispref/syntax.texi
index 9120e637274..e84b901eaa9 100644
--- a/doc/lispref/syntax.texi
+++ b/doc/lispref/syntax.texi
@@ -770,7 +770,7 @@ This function returns the parser state that the parser would reach at
position @var{pos} starting from the beginning of the visible portion
of the buffer.
@iftex
-See the next section for
+See the next section
@end iftex
@ifnottex
@xref{Parser State},
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index b9df66dbdb4..ab46afc838b 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -59,6 +59,7 @@ the character after point.
* Decompression:: Dealing with compressed data.
* Base 64:: Conversion to or from base 64 encoding.
* Checksum/Hash:: Computing cryptographic hashes.
+* Suspicious Text:: Determining whether a string is suspicious.
* GnuTLS Cryptography:: Cryptographic algorithms imported from GnuTLS.
* Database:: Interacting with an SQL database.
* Parsing HTML/XML:: Parsing HTML and XML.
@@ -242,10 +243,8 @@ using a function specified by the variable
The default filter function consults the obsolete wrapper hook
@code{filter-buffer-substring-functions} (see the documentation string
of the macro @code{with-wrapper-hook} for the details about this
-obsolete facility), and the obsolete variable
-@code{buffer-substring-filters}. If both of these are @code{nil}, it
-returns the unaltered text from the buffer, i.e., what
-@code{buffer-substring} would return.
+obsolete facility). If it is @code{nil}, it returns the unaltered
+text from the buffer, i.e., what @code{buffer-substring} would return.
If @var{delete} is non-@code{nil}, the function deletes the text
between @var{start} and @var{end} after copying it, like
@@ -281,22 +280,12 @@ the same as those of @code{filter-buffer-substring}.
The first hook function is passed a @var{fun} that is equivalent to
the default operation of @code{filter-buffer-substring}, i.e., it
-returns the buffer-substring between @var{start} and @var{end}
-(processed by any @code{buffer-substring-filters}) and optionally
-deletes the original text from the buffer. In most cases, the hook
-function will call @var{fun} once, and then do its own processing of
-the result. The next hook function receives a @var{fun} equivalent to
-this, and so on. The actual return value is the result of all the
-hook functions acting in sequence.
-@end defvar
-
-@defvar buffer-substring-filters
-The value of this obsolete variable should be a list of functions
-that accept a single string argument and return another string.
-The default @code{filter-buffer-substring} function passes the buffer
-substring to the first function in this list, and the return value of
-each function is passed to the next function. The return value of the
-last function is passed to @code{filter-buffer-substring-functions}.
+returns the buffer-substring between @var{start} and @var{end} and
+optionally deletes the original text from the buffer. In most cases,
+the hook function will call @var{fun} once, and then do its own
+processing of the result. The next hook function receives a @var{fun}
+equivalent to this, and so on. The actual return value is the result
+of all the hook functions acting in sequence.
@end defvar
@defun current-word &optional strict really-word
@@ -1033,6 +1022,9 @@ text in @var{string} according to the @code{yank-handler} text
property, as well as the variables @code{yank-handled-properties} and
@code{yank-excluded-properties} (see below), before inserting the
result into the current buffer.
+
+@var{string} will be run through @code{yank-transform-functions} (see
+below) before inserting.
@end defun
@defun insert-buffer-substring-as-yank buf &optional start end
@@ -1107,6 +1099,23 @@ or specifying key bindings. It takes effect after
@code{yank-handled-properties}.
@end defopt
+@defvar yank-transform-functions
+This variable is a list of functions. Each function is called (in
+order) with the string to be yanked as the argument, and should
+return a (possibly transformed) string. This variable can be set
+globally, but can also be used to create new commands that are
+variations on @code{yank}. For instance, to create a command that
+works like @code{yank}, but cleans up whitespace before inserting, you
+could say something like:
+
+@lisp
+(defun yank-with-clean-whitespace ()
+ (interactive)
+ (let ((yank-transform-functions
+ '(string-clean-whitespace)))
+ (call-interactively #'yank)))
+@end lisp
+@end defvar
@node Yank Commands
@subsection Functions for Yanking
@@ -1730,8 +1739,9 @@ filling when @var{justify} is non-@code{nil}.
If @var{nosqueeze} is non-@code{nil}, that means to leave whitespace
other than line breaks untouched. If @var{squeeze-after} is
-non-@code{nil}, it specifies a position in the region, and means don't
-canonicalize spaces before that position.
+non-@code{nil}, it specifies a position in the region, and means
+that whitespace other than line breaks should be left untouched before
+that position.
In Adaptive Fill mode, this command calls @code{fill-context-prefix} to
choose a fill prefix by default. @xref{Adaptive Fill}.
@@ -2967,6 +2977,12 @@ character after position @var{pos} in @var{object} (a buffer or
string). The argument @var{object} is optional and defaults to the
current buffer.
+If @var{position} is at the end of @var{object}, the value is
+@code{nil}, but note that buffer narrowing does not affect the value.
+That is, if @var{object} is a buffer or @code{nil}, and the buffer is
+narrowed and @var{position} is at the end of the narrowed buffer, the
+result may be non-@code{nil}.
+
If there is no @var{prop} property strictly speaking, but the character
has a property category that is a symbol, then @code{get-text-property} returns
the @var{prop} property of that symbol.
@@ -3019,6 +3035,12 @@ properties take precedence over this variable.
This function returns the entire property list of the character at
@var{position} in the string or buffer @var{object}. If @var{object} is
@code{nil}, it defaults to the current buffer.
+
+If @var{position} is at the end of @var{object}, the value is
+@code{nil}, but note that buffer narrowing does not affect the value.
+That is, if @var{object} is a buffer or @code{nil}, and the buffer is
+narrowed and @var{position} is at the end of the narrowed buffer, the
+result may be non-@code{nil}.
@end defun
@defvar default-text-properties
@@ -3451,7 +3473,7 @@ This will give you a list of all those URLs.
@end defun
@defun text-property-search-backward prop &optional value predicate not-current
-This is just like @code{text-property-search-backward}, but searches
+This is just like @code{text-property-search-forward}, but searches
backward instead. Point is placed at the beginning of the matched
region instead of the end, though.
@end defun
@@ -3539,16 +3561,30 @@ special modes that implement their own highlighting.
@item mouse-face
@kindex mouse-face @r{(text property)}
-This property is used instead of @code{face} when the mouse is on or
-near the character. For this purpose, ``near'' means that all text
-between the character and where the mouse is have the same
-@code{mouse-face} property value.
+This property is used instead of @code{face} when the mouse pointer
+hovers over the text which has this property. When this happens, the
+entire stretch of text that has the same @code{mouse-face} property
+value, not just the character under the mouse, is highlighted.
Emacs ignores all face attributes from the @code{mouse-face} property
that alter the text size (e.g., @code{:height}, @code{:weight}, and
@code{:slant}). Those attributes are always the same as for the
unhighlighted text.
+@item cursor-face
+@kindex cursor-face @r{(text property)}
+@findex cursor-face-highlight-mode
+@vindex cursor-face-highlight-nonselected-window
+This property is similar to @code{mouse-face}, but it is used when
+point (not the mouse) is inside text that has this property. The
+highlighting happens only if the mode
+@code{cursor-face-highlight-mode} is enabled. When the variable
+@code{cursor-face-highlight-nonselected-window} is non-@code{nil}, the
+text with this face is highlighted even if the window is not selected,
+similarly to what @code{highlight-nonselected-windows} does for the
+region (@pxref{Mark,, The Mark and the Region, emacs, The GNU Emacs
+Manual}).
+
@item fontified
@kindex fontified @r{(text property)}
This property says whether the text is ready for display. If
@@ -4943,6 +4979,92 @@ It should be somewhat more efficient on larger buffers than
@c according to what we find useful.
@end defun
+@node Suspicious Text
+@section Suspicious Text
+@cindex suspicious text
+@cindex insecure text
+@cindex security vulnerabilities in text
+
+ Emacs can display text from many external sources, like email and Web
+sites. Attackers may attempt to confuse the user reading this text by
+using obfuscated @acronym{URL}s or email addresses, and tricking the
+user into visiting a web page they didn't intend to visit, or sending
+an email to the wrong address.
+
+This usually involves using characters from scripts that visually look
+like @acronym{ASCII} characters (i.e., are homoglyphs), but there are
+also other techniques used, like using bidirectional overrides, or
+having an @acronym{HTML} link text that says one thing, while the
+underlying @acronym{URL} points somewhere else.
+
+@cindex suspicious text strings
+To help identify these @dfn{suspicious text strings}, Emacs provides a
+library to do a number of checks on text. (See
+@url{https://www.unicode.org/reports/tr39/, UTS #39: Unicode Security
+Mechanisms} for the rationale behind the checks that are available and
+more details about them.) Packages that present data that might be
+suspicious should use this library to flag suspicious text on display.
+
+@vindex textsec-check
+@defun textsec-suspicious-p object type
+This function is the high-level interface function that packages
+should use. It respects the @code{textsec-check} user option, which
+allows the user to disable the checks.
+
+This function checks @var{object} (whose data type depends on
+@var{type}) to see if it looks suspicious when interpreted as a thing
+of @var{type}. The available types and the corresponding @var{object}
+data types are:
+
+@table @code
+@item domain
+Check whether a domain (e.g., @samp{www.gnu.org} looks suspicious.
+@var{object} should be a string, the domain name.
+
+@item url
+Check whether an @acronym{URL} (e.g., @samp{http://gnu.org/foo/bar})
+looks suspicious. @var{object} should be a string, the @acronym{URL}
+to check.
+
+@item link
+Check whether an @acronym{HTML} link (e.g., @samp{<a
+href='http://gnu.org'>fsf.org</a>} looks suspicious. In this case,
+@var{object} should be a @code{cons} cell where the @code{car} is the
+@acronym{URL} string, and the @code{cdr} is the link text. The link
+is deemed suspicious if the link text contains a domain name, and that
+domain name points to something other than the @acronym{URL}.
+
+@item email-address
+Check whether an email address (e.g., @samp{foo@@example.org}) looks
+suspicious. @var{object} should be a string.
+
+@item local-address
+Check whether the local part of an email address (the bit before the
+@samp{@@} sign) looks suspicious. @var{object} should be a string.
+
+@item name
+Check whether a name (used in an email address header) looks
+suspicious. @var{object} should be a string.
+
+@item email-address-header
+Check whether a full RFC2822 email address header (e.g.,
+@samp{=?utf-8?Q?=C3=81?= <foo@@example.com>}) looks suspicious.
+@var{object} should be a string.
+@end table
+
+If @var{object} is suspicious, this function returns a string that
+explains why it is suspicious. If @var{object} is not suspicious, the
+function returns @code{nil}.
+@end defun
+
+@vindex textsec-suspicious@r{ (face)}
+If the text is suspicious, the application should mark the suspicious
+text with the @code{textsec-suspicious} face, and make the explanation
+returned by @code{textsec-suspicious-p} available to the user in some way
+(for example, in a tooltip). The application might also prompt the
+user for confirmation before taking any action on a suspicious string
+(like sending an email to a suspicious email address).
+
@node GnuTLS Cryptography
@section GnuTLS Cryptography
@cindex MD5 checksum
@@ -5195,6 +5317,24 @@ interpolation).
@code{sqlite-execute} returns the number of affected rows. For
instance, an @samp{insert} statement will return @samp{1}, whereas an
@samp{update} statement may return zero or a higher number.
+
+Strings in SQLite are, by default, stored as @code{utf-8}, and
+selecting a text column will decode the string using that charset.
+Selecting a blob column will return the raw data without any decoding
+(i.e., it will return a unibyte string containing the bytes as stored
+in the database). Inserting binary data into blob columns, however,
+requires some care, as @code{sqlite-execute} will, by default,
+interpret all strings as @code{utf-8}.
+
+So if you have, for instance, @acronym{GIF} data in a unibyte string
+called @var{gif}, you have to mark it specially to let
+@code{sqlite-execute} know this:
+
+@lisp
+(put-text-property 0 1 'coding-system 'binary gif)
+(sqlite-execute db "insert into foo values (?, ?)" (list gif 2))
+@end lisp
+
@end defun
@defun sqlite-select db query &optional values result-type
@@ -5306,6 +5446,12 @@ Extensions are usually shared-library files; on GNU and Unix systems,
they have the @file{.so} file-name extension.
@end defun
+@findex sqlite-mode-open-file
+If you wish to list the contents of an SQLite file, you can use the
+@code{sqlite-mode-open-file} command. This will pop to a buffer using
+@code{sqlite-mode}, which allows you to examine (and alter) the
+contents of an SQLite database.
+
@node Parsing HTML/XML
@section Parsing HTML and XML
@cindex parsing html
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 061a5d672ec..30146a89ebf 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -694,26 +694,24 @@ starting double-quote is not part of the string!
@cindex curly quotes
@cindex curved quotes
When a documentation string refers to a Lisp symbol, write it as it
-would be printed (which usually means in lower case), surrounding it
-with curved single quotes (@t{‘..’}). There are two exceptions: write
-@code{t} and @code{nil} without surrounding punctuation. For example:
+would be printed (which usually means in lower case), with a grave
+accent @samp{`} before and apostrophe @samp{'} after it. There are
+two exceptions: write @code{t} and @code{nil} without surrounding
+punctuation. For example:
@example
- CODE can be ‘lambda’, nil, or t.
+ CODE can be `lambda', nil, or t.
@end example
-@noindent
-@xref{Quotation Marks,,, emacs, The GNU Emacs Manual}, for how to
-enter curved single quotes.
-
-Documentation strings can also use an older single-quoting convention,
-which quotes symbols with grave accent @t{`} and apostrophe
-@t{'}: @t{`like-this'} rather than @t{‘like-this’}. This
-older convention was designed for now-obsolete displays in which grave
-accent and apostrophe were mirror images.
-Documentation using this convention is converted to the user's
-preferred format when it is copied into a help buffer. @xref{Keys in
-Documentation}.
+Note that when Emacs displays these doc strings, Emacs will usually
+display @samp{`} (grave accent) as @samp{‘} (left single quotation
+mark) and @samp{'} (apostrophe) as @samp{’} (right single quotation
+mark), if the display supports displaying these characters.
+@xref{Keys in Documentation}. (Some previous versions of this section
+recommended using the non-@acronym{ASCII} single quotation marks
+directly in doc strings, but this is now discouraged, since that leads
+to broken help string displays on terminals that don't support
+displaying those characters.)
@cindex hyperlinks in documentation strings
Help mode automatically creates a hyperlink when a documentation string
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 34c73e70b72..c29547d00db 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -527,10 +527,11 @@ If @var{symbol} has a buffer-local binding in the current buffer,
rather than the buffer-local binding. It sets the default value if
the default value is void. @xref{Buffer-Local Variables}.
-If @var{symbol} is already lexically bound (e.g., if the @code{defvar}
-form occurs in a @code{let} form with lexical binding enabled), then
-@code{defvar} sets the dynamic value. The lexical binding remains in
-effect until its binding construct exits. @xref{Variable Scoping}.
+If @var{symbol} is already let bound (e.g., if the @code{defvar}
+form occurs in a @code{let} form), then @code{defvar} sets the toplevel
+default value, like @code{set-default-toplevel-value}.
+The let binding remains in effect until its binding construct exits.
+@xref{Variable Scoping}.
@cindex @code{eval-defun}, and @code{defvar} forms
@cindex @code{eval-last-sexp}, and @code{defvar} forms
@@ -861,6 +862,40 @@ error is signaled.
@end example
@end defun
+@defmac setopt [symbol form]@dots{}
+This is like @code{setq} (see above), but meant for user options.
+This macro uses the Customize machinery to set the variable(s). In
+particular, @code{setopt} will run the setter function associated with
+the variable. For instance, if you have:
+
+@example
+@group
+(defcustom my-var 1
+ "My var."
+ :type 'number
+ :set (lambda (var val)
+ (set-default var val)
+ (message "We set %s to %s" var val)))
+@end group
+@end example
+
+@noindent
+then the following, in addition to setting @code{my-var} to @samp{2},
+will also issue a message:
+
+@example
+(setopt my-var 2)
+@end example
+
+@code{setopt} also checks whether the value is valid for the user
+option. For instance, using @code{setopt} to set a user option
+defined with a @code{number} type to a string will signal an error.
+
+The @code{setopt} macro can be used on regular, non-user option
+variables, but is much less efficient than @code{setq}. The main use
+case for this macro is setting user options in the user's init file.
+@end defmac
+
@node Watching Variables
@section Running a function when a variable is changed.
@cindex variable watchpoints
@@ -2261,13 +2296,28 @@ list in @var{variables} is an alist of the form
'((null-device . "/dev/null")))
@end group
@end example
+
+@findex connection-local-get-profile-variables
+If you want to append variable settings to an existing profile, you
+could use the function @code{connection-local-get-profile-variables}
+in order to retrieve the existing settings, like
+
+@example
+@group
+(connection-local-set-profile-variables
+ 'remote-bash
+ (append
+ (connection-local-get-profile-variables 'remote-bash)
+ '((shell-command-dont-erase-buffer . t))))
+@end group
+@end example
@end defun
-@defvar connection-local-profile-alist
+@deffn {User Option} connection-local-profile-alist
This alist holds the connection profile symbols and the associated
variable settings. It is updated by
@code{connection-local-set-profile-variables}.
-@end defvar
+@end deffn
@defun connection-local-set-profiles criteria &rest profiles
This function assigns @var{profiles}, which are symbols, to all remote
@@ -2321,11 +2371,11 @@ Therefore, the example above would be equivalent to
defined by @code{connection-local-set-profile-variables}.
@end defun
-@defvar connection-local-criteria-alist
+@deffn {User Option} connection-local-criteria-alist
This alist contains connection criteria and their assigned profile
names. The function @code{connection-local-set-profiles} updates this
list.
-@end defvar
+@end deffn
@defun hack-connection-local-variables criteria
This function collects applicable connection-local variables
@@ -2384,6 +2434,37 @@ are unwound. Example:
@end example
@end defmac
+@defvar connection-local-default-application
+The default application, a symbol, to be applied in
+@code{with-connection-local-variables}. It defaults to @code{tramp},
+but in case you want to overwrite Tramp's settings temporarily, you
+could let-bind it like
+
+@example
+@group
+(connection-local-set-profile-variables
+ 'my-remote-perl
+ '((perl-command-name . "/usr/local/bin/perl5")
+ (perl-command-switch . "-e %s")))
+@end group
+
+@group
+(connection-local-set-profiles
+ '(:application 'my-app :protocol "ssh" :machine "remotehost")
+ 'my-remote-perl)
+@end group
+
+@group
+(let ((default-directory "/ssh:remotehost:/working/dir/")
+ (connection-local-default-application 'my-app))
+ (with-connection-local-variables
+ do something useful))
+@end group
+@end example
+
+This variable must not be changed globally.
+@end defvar
+
@defvar enable-connection-local-variables
If @code{nil}, connection-local variables are ignored. This variable
shall be changed temporarily only in special modes.
@@ -2709,13 +2790,13 @@ implemented this way:
(gv-define-expander substring
(lambda (do place from &optional to)
(gv-letplace (getter setter) place
- (macroexp-let2* nil ((start from) (end to))
- (funcall do `(substring ,getter ,start ,end)
+ (macroexp-let2* (from to)
+ (funcall do `(substring ,getter ,from ,to)
(lambda (v)
- (macroexp-let2 nil v v
+ (macroexp-let2* (v)
`(progn
,(funcall setter `(cl--set-substring
- ,getter ,start ,end ,v))
+ ,getter ,from ,to ,v))
,v))))))))
@end example
@end defmac
@@ -2728,7 +2809,7 @@ of Common Lisp could be implemented this way:
@example
(defmacro incf (place &optional n)
(gv-letplace (getter setter) place
- (macroexp-let2 nil v (or n 1)
+ (macroexp-let2* ((v (or n 1)))
(funcall setter `(+ ,v ,getter)))))
@end example
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 56b4bc5183e..535571b3161 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -829,14 +829,18 @@ This function returns the height, in lines, of the body of window
@var{window}. If @var{window} is omitted or @code{nil}, it defaults to
the selected window; otherwise it must be a live window.
-If the optional argument @var{pixelwise} is non-@code{nil}, this
-function returns the body height of @var{window} counted in pixels.
+The optional argument @var{pixelwise} defines the units to use for the
+height. If @code{nil}, return the body height of @var{window} in
+characters, rounded down to the nearest integer, if necessary. This
+means that if a line at the bottom of the text area is only partially
+visible, that line is not counted. It also means that the height of a
+window's body can never exceed its total height as returned by
+@code{window-total-height}.
-If @var{pixelwise} is @code{nil}, the return value is rounded down to
-the nearest integer, if necessary. This means that if a line at the
-bottom of the text area is only partially visible, that line is not
-counted. It also means that the height of a window's body can never
-exceed its total height as returned by @code{window-total-height}.
+If @var{pixelwise} is @code{remap} and the default face is remapped
+(@pxref{Face Remapping}), use the remapped face to determine the
+character height. For any other non-@code{nil} value, return the
+height in pixels.
@end defun
@cindex window body width
@@ -857,14 +861,18 @@ This function returns the width, in columns, of the body of window
@var{window}. If @var{window} is omitted or @code{nil}, it defaults to
the selected window; otherwise it must be a live window.
-If the optional argument @var{pixelwise} is non-@code{nil}, this
-function returns the body width of @var{window} in units of pixels.
+The optional argument @var{pixelwise} defines the units to use for the
+width. If @code{nil}, return the body width of @var{window} in
+characters, rounded down to the nearest integer, if necessary. This
+means that if a column on the right of the text area is only partially
+visible, that column is not counted. It also means that the width of
+a window's body can never exceed its total width as returned by
+@code{window-total-width}.
-If @var{pixelwise} is @code{nil}, the return value is rounded down to
-the nearest integer, if necessary. This means that if a column on the
-right of the text area is only partially visible, that column is not
-counted. It also means that the width of a window's body can never
-exceed its total width as returned by @code{window-total-width}.
+If @var{pixelwise} is @code{remap} and the default face is remapped
+(@pxref{Face Remapping}), use the remapped face to determine the
+character width. For any other non-@code{nil} value, return the width
+in pixels.
@end defun
@cindex window body size
@@ -1150,11 +1158,13 @@ frame to its buffer using the command @code{fit-frame-to-buffer}.
This command adjusts the size of @var{frame} to display the contents of
its buffer exactly. @var{frame} can be any live frame and defaults to
the selected one. Fitting is done only if @var{frame}'s root window is
-live. The arguments @var{max-height}, @var{min-height}, @var{max-width}
-and @var{min-width} specify bounds on the new total size of
-@var{frame}'s root window. @var{min-height} and @var{min-width} default
-to the values of @code{window-min-height} and @code{window-min-width}
-respectively.
+live.
+
+The arguments @var{max-height}, @var{min-height}, @var{max-width} and
+@var{min-width}, if non-@code{nil}, specify bounds on the new body size
+of @var{frame}'s root window. A non-@code{nil} value specified by any
+of these arguments overrides the corresponding value specified by
+the option @code{fit-frame-to-buffer-sizes} described below.
If the optional argument @var{only} is @code{vertically}, this function
may resize the frame vertically only. If @var{only} is
@@ -1179,10 +1189,10 @@ here can be overridden for a specific frame by that frame's
@defopt fit-frame-to-buffer-sizes
This option specifies size boundaries for @code{fit-frame-to-buffer}.
-It specifies the total maximum and minimum lines and maximum and minimum
-columns of the root window of any frame that shall be fit to its buffer.
-If any of these values is non-@code{nil}, it overrides the corresponding
-argument of @code{fit-frame-to-buffer}.
+It specifies the maximum and minimum lines and maximum and minimum
+columns of the root window's body of any frame that shall be fit to its
+buffer. Any value this option specifies will be overridden by the
+corresponding argument of @code{fit-frame-to-buffer}, if non-@code{nil}.
@end defopt
@deffn Command shrink-window-if-larger-than-buffer &optional window
@@ -2596,13 +2606,11 @@ default value is an empty display action, i.e., @w{@code{(nil . nil)}}.
@defopt display-buffer-alist
The value of this option is an alist mapping conditions to display
-actions. Each condition may be either a regular expression matching a
-buffer name or a function that takes two arguments: a buffer name and
-the @var{action} argument passed to @code{display-buffer}. If either
-the name of the buffer passed to @code{display-buffer} matches a
-regular expression in this alist, or the function specified by a
-condition returns non-@code{nil}, then @code{display-buffer} uses the
-corresponding display action to display the buffer.
+actions. Each condition is passed to @code{buffer-match-p}, along
+with the buffer name and the @var{action} argument passed to
+@code{display-buffer}. If it returns a non-nil value, then
+@code{display-buffer} uses the corresponding display action to display
+the buffer.
@end defopt
@defopt display-buffer-base-action
@@ -2838,6 +2846,11 @@ the function specified in @code{pop-up-frame-function}
the newly created frame's parameters.
@end defun
+@defun display-buffer-full-frame buffer alist
+This function displays the buffer on the current frame, deleting all
+other windows so that it takes up the full frame.
+@end defun
+
@defun display-buffer-in-child-frame buffer alist
This function tries to display @var{buffer} in a child frame
(@pxref{Child Frames}) of the selected frame, either reusing an
@@ -2968,13 +2981,14 @@ follows:
@code{nil} means consider only windows on the selected frame.
(Actually, the last frame used that is not a minibuffer-only frame.)
@item
-@code{t} means consider windows on all frames.
-@item
@code{visible} means consider windows on all visible frames.
@item
0 means consider windows on all visible or iconified frames.
@item
A frame means consider windows on that frame only.
+@item
+@code{t} means consider windows on all frames. (Note that this value
+is rarely the right thing to use---it might also return a tooltip frame.)
@end itemize
Note that the meaning of @code{nil} differs slightly from that of the
@@ -3292,6 +3306,13 @@ window has at least that many columns. If the value is @code{nil},
that means not to split this way.
@end defopt
+@defopt display-buffer-avoid-small-windows
+If non-@code{nil}, this should be a number. Windows that have fewer
+lines than that will be avoided when choosing an existing window. The
+value is interpreted in units of the frame's canonical line height,
+like @code{window-total-height} does (@pxref{Window Sizes}).
+@end defopt
+
@defopt even-window-sizes
This variable, if non-@code{nil}, causes @code{display-buffer} to even
window sizes whenever it reuses an existing window, and that window is
@@ -3377,8 +3398,8 @@ functions it should try instead as, for example:
@example
@group
-(customize-set-variable
- 'display-buffer-base-action
+(setopt
+ display-buffer-base-action
'((display-buffer-reuse-window display-buffer-same-window
display-buffer-in-previous-window
display-buffer-use-some-window)))
@@ -3392,8 +3413,8 @@ Instead of customizing this variable to @code{t}, customize
@example
@group
-(customize-set-variable
- 'display-buffer-base-action
+(setopt
+ display-buffer-base-action
'((display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . 0)))
@end group
@@ -3409,8 +3430,8 @@ specifying the action function @code{display-buffer-same-window}.
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
(cons '("\\*foo\\*" (display-buffer-same-window))
display-buffer-alist))
@end group
@@ -3483,8 +3504,8 @@ another frame. Such a user might provide the following customization:
@example
@group
-(customize-set-variable
- 'display-buffer-base-action
+(setopt
+ display-buffer-base-action
'((display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . 0)))
@end group
@@ -3529,8 +3550,8 @@ In fact, this:
@example
@group
-(customize-set-variable
- 'display-buffer-base-action
+(setopt
+ display-buffer-base-action
'(display-buffer-pop-up-frame (reusable-frames . 0)))
@end group
@end example
@@ -3586,8 +3607,8 @@ by customizing the option @code{display-buffer-alist} as follows:
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*foo\\*"
(display-buffer-reuse-window display-buffer-pop-up-frame))))
@end group
@@ -3609,8 +3630,8 @@ we would have to specify that separately, however:
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*foo\\*"
(display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . visible))))
@@ -3716,8 +3737,8 @@ written that as
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*foo\\*"
(display-buffer-reuse-window display-buffer-pop-up-frame)
(inhibit-same-window . t)
@@ -3860,8 +3881,8 @@ follows:
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*foo\\*"
(display-buffer-below-selected display-buffer-at-bottom)
(inhibit-same-window . t)
@@ -3874,8 +3895,8 @@ To add a customization for a second buffer one would then write:
@example
@group
-(customize-set-variable
- 'display-buffer-alist
+(setopt
+ display-buffer-alist
'(("\\*foo\\*"
(display-buffer-below-selected display-buffer-at-bottom)
(inhibit-same-window . t)
@@ -4165,6 +4186,13 @@ ignore this option, for example, when there is only one buffer left
these functions can switch to.
@end defopt
+@defopt switch-to-prev-buffer-skip-regexp
+This user option should be either a regular expression or a list of
+regular expressions. Buffers whose names match one of those regular
+expressions will be ignored by @code{switch-to-prev-buffer} and
+@code{switch-to-next-buffer} (except when there's no other buffer to
+switch to).
+@end defopt
@node Dedicated Windows
@section Dedicated Windows
@@ -5281,13 +5309,6 @@ other window is selected. When it is non-@code{nil} and the
minibuffer is selected, it takes precedence over
@code{other-window-scroll-buffer}. @xref{Definition of
minibuffer-scroll-window}.
-
-When the minibuffer is active, it is the next window if the selected
-window is the one at the bottom right corner. In this case,
-@code{scroll-other-window} attempts to scroll the minibuffer. If the
-minibuffer contains just one line, it has nowhere to scroll to, so the
-line reappears after the echo area momentarily displays the message
-@samp{End of buffer}.
@end deffn
@deffn Command scroll-other-window-down &optional count
@@ -5507,7 +5528,7 @@ pixels, rather than in units of the normal line height.
@end example
@end defun
-@defun set-window-vscroll window lines &optional pixels-p
+@defun set-window-vscroll window lines &optional pixels-p preserve-vscroll-p
This function sets @var{window}'s vertical scroll position to
@var{lines}. If @var{window} is @code{nil}, the selected window is
used. The argument @var{lines} should be zero or positive; if not, it
@@ -5529,6 +5550,12 @@ The return value is the result of this rounding.
If @var{pixels-p} is non-@code{nil}, @var{lines} specifies a number of
pixels. In this case, the return value is @var{lines}.
+
+Normally, the vscroll does not take effect on windows that aren't the
+@code{minibuffer-scroll-window} or the selected window when the
+mini-window is resized (@pxref{Minibuffer Windows}). This ``frozen''
+behavior is disabled when the @var{preserve-vscroll-p} parameter is
+non-@code{nil}, which means to set the vscroll as usual.
@end defun
@defvar auto-window-vscroll
@@ -6122,11 +6149,10 @@ configuration on the current frame.
This function returns @code{t} if @var{object} is a window configuration.
@end defun
-@defun compare-window-configurations config1 config2
-This function compares two window configurations as regards the
-structure of windows, but ignores the values of point and the
-saved scrolling positions---it can return @code{t} even if those
-aspects differ.
+@defun window-configuration-equal-p config1 config2
+This function says whether two window configurations have the same
+window layout, but ignores the values of point and the saved scrolling
+positions---it can return @code{t} even if those aspects differ.
@end defun
@defun window-configuration-frame config
diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in
index 9fdf65e0ff7..7b2b5539795 100644
--- a/doc/man/emacs.1.in
+++ b/doc/man/emacs.1.in
@@ -1,5 +1,5 @@
.\" See section COPYING for copyright and redistribution information.
-.TH EMACS 1 "2021-09-28" "GNU Emacs @version@" "GNU"
+.TH EMACS 1 "2022-06-07" "GNU Emacs @version@" "GNU"
.
.
.SH NAME
@@ -117,6 +117,10 @@ Load
.IR user 's
init file.
.TP
+.BI \-\-init\-directory= "directory"
+Start emacs with user-emacs-directory set to
+.IR directory .
+.TP
.BI \-t " file\fR,\fP " \-\-terminal= "file"
Use specified
.I file
diff --git a/doc/man/etags.1 b/doc/man/etags.1
index d345b8bd73f..4681a9dadbf 100644
--- a/doc/man/etags.1
+++ b/doc/man/etags.1
@@ -1,5 +1,5 @@
.\" See section COPYING for copyright and redistribution information.
-.TH ETAGS 1 "2021-03-30" "GNU Tools" "GNU"
+.TH ETAGS 1 "2022-06-10" "GNU Tools" "GNU"
.de BP
.sp
.ti -.2i
@@ -122,7 +122,9 @@ current file. Only \fBetags\fP accepts this option.
.B \-I, \-\-ignore\-indentation
Don't rely on indentation as much as we normally do. Currently, this
means not to assume that a closing brace in the first column is the
-final brace of a function or structure definition in C and C++.
+final brace of a function or structure definition in C and C++. This
+is important for code that doesn't observe the GNU Coding conventions
+of placing only top-level braces in column zero.
.TP
\fB\-l\fP \fIlanguage\fP, \fB\-\-language=\fIlanguage\fP
Parse the following files according to the given language. More than
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 6c1e9cbc910..1d881a5fc7f 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -73,8 +73,8 @@ INFO_COMMON = auth autotype bovine calc ccmode cl \
flymake forms gnus emacs-gnutls htmlfontify idlwave ido info.info \
mairix-el message mh-e modus-themes newsticker nxml-mode octave-mode \
org pcl-cvs pgg rcirc remember reftex sasl \
- sc semantic ses sieve smtpmail speedbar srecode todo-mode tramp \
- url vhdl-mode vip viper widget wisent woman
+ sc semantic ses sieve smtpmail speedbar srecode todo-mode transient \
+ tramp url vhdl-mode vip viper vtable widget wisent woman
## Info files to install on current platform.
INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32)
@@ -234,6 +234,10 @@ ${buildinfodir}/tramp.info tramp.html: ${srcdir}/trampver.texi
abs_top_builddir = @abs_top_builddir@
+
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
EMACS = ${abs_top_builddir}/src/emacs
emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefer-newer t)'
@@ -244,6 +248,7 @@ emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefe
define org_template
$(1:.org=.texi): $(1) ${top_srcdir}/lisp/org/ox-texinfo.el
$${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \
+ --eval '(setq gc-cons-threshold 50000000)' \
-f org-texinfo-export-to-texinfo-batch $$(notdir $$<) $$(notdir $$@)
endef
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi
index b28ae247ea9..829d7f4fa03 100644
--- a/doc/misc/auth.texi
+++ b/doc/misc/auth.texi
@@ -191,7 +191,7 @@ get fancy, the default and simplest configuration is:
(setq auth-sources '("secrets:Login"))
;;; use pass (@file{~/.password-store})
;;; (@pxref{The Unix password store})
-(setq auth-sources '(password-store))
+(auth-source-pass-enable)
;;; JSON data in format [@{ "machine": "SERVER",
;;; "login": "USER", "password": "PASSWORD" @}...]
(setq auth-sources '("~/.authinfo.json.gpg"))
@@ -579,10 +579,7 @@ from Gnus's @code{nnimap.el}.
:create t))))
(if found
(list (plist-get found :user)
- (let ((secret (plist-get found :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))
+ (auth-info-password found)
(plist-get found :save-function))
nil)))
@end example
@@ -602,7 +599,7 @@ Later, after a successful login, @code{nnimap.el} calls the
@example
(when (functionp (nth 2 credentials))
- (funcall (nth 2 credentials)))
+ (funcall (nth 2 credentials)))
@end example
This will work whether the @code{:save-function} was provided or not.
@@ -637,6 +634,16 @@ This function forgets any cached data matching @var{spec}.
It returns the number of items forgotten.
@end defun
+@defun auth-source-pick-first-password &rest spec
+This function returns the password of the first record found by
+applying @code{auth-source-search} to @var{spec}.
+@end defun
+
+@defun auth-info-password auth-info
+This function extracts the password string from the @var{auth-info}
+record.
+@end defun
+
@node GnuPG and EasyPG Assistant Configuration
@appendix GnuPG and EasyPG Assistant Configuration
diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi
index a3b0f16df9c..b005c9c34f7 100644
--- a/doc/misc/autotype.texi
+++ b/doc/misc/autotype.texi
@@ -274,13 +274,13 @@ empty file is visited. This is accomplished by putting
@vindex auto-insert-alist
What gets inserted, if anything, is determined by the variable
-@code{auto-insert-alist}. The @sc{car}s of this list are each either
-a mode name, making an element applicable when a buffer is in that
-mode. Or they can be a string, which is a regexp matched against the
-buffer's file name. In that way different kinds of files that have
-the same mode in Emacs can be distinguished. The @sc{car}s may also
-be cons cells consisting of mode name or regexp as above and an
-additional descriptive string.
+@code{auto-insert-alist}. The @sc{car} of each element of this list
+is either a mode name, making the element applicable when a buffer is
+in that mode, or a string, which is a regexp matched against a
+buffer's file name (the latter allows to distinguish between different
+kinds of files that have the same mode in Emacs). The @sc{car} of an
+element may also be a cons cell, consisting of mode name or regexp, as
+above, and an additional descriptive string.
When a matching element is found, the @sc{cdr} says what to do. It may
be a string, which is a file name, whose contents are to be inserted, if
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index d83edc15f30..9bda6af1c5b 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -29877,6 +29877,12 @@ with no argument copies only the number itself into the kill ring, whereas
@kbd{C-k} with a prefix argument of 1 copies the number with its trailing
newline.
+You can customize @code{calc-kill-line-numbering} to nil to exclude
+line numbering from kills and copies made by @code{calc-kill} and
+@code{calc-copy-as-kill}. This option does not affect calc kill and
+copy commands which operate on the region, as that would not make
+sense.
+
@node Yanking Into Stack
@section Yanking into the Stack
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 8b36d1afd7a..1f12c30b1f8 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -6278,6 +6278,32 @@ expressions for the operands.
@comment ------------------------------------------------------------
+@defun c-lineup-argcont-+
+@findex lineup-argcont-+ (c-)
+Indent a continued argument @code{c-basic-offset} spaces from the
+start of the first argument at the current level of nesting on a
+previous line.
+
+@example
+@group
+foo (xyz, uvw, aaa + bbb + ccc
+ + ddd + eee + fff); <- c-lineup-argcont-+
+ <--> c-basic-offset
+@end group
+@end example
+
+Only continuation lines like this are touched, @code{nil} being
+returned on lines which are the start of an argument.
+
+Within a gcc @code{asm} block, @code{:} is recognized as an argument
+separator, but of course only between operand specifications, not in the
+expressions for the operands.
+
+@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}.
+@end defun
+
+@comment ------------------------------------------------------------
+
@defun c-lineup-arglist-operators
@findex lineup-arglist-operators @r{(c-)}
Line up lines starting with an infix operator under the open paren.
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index a6fe29e1026..6134b977517 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -444,7 +444,7 @@ the ``rest'' argument is bound to the keyword list as it appears
in the call. For example:
@example
-(cl-defun find-thing (thing &rest rest &key need &allow-other-keys)
+(cl-defun find-thing (thing thing-list &rest rest &key need &allow-other-keys)
(or (apply 'cl-member thing thing-list :allow-other-keys t rest)
(if need (error "Thing not found"))))
@end example
@@ -843,6 +843,7 @@ constructs.
* Iteration:: @code{cl-do}, @code{cl-dotimes}, @code{cl-dolist}, @code{cl-do-symbols}.
* Loop Facility:: The Common Lisp @code{loop} macro.
* Multiple Values:: @code{cl-values}, @code{cl-multiple-value-bind}, etc.
+* Macro-Writing Macros:: @code{cl-with-gensyms}, @code{cl-once-only}.
@end menu
@node Assignment
@@ -2513,6 +2514,86 @@ in @code{cl-multiple-value-bind}.
Since a perfect emulation is not feasible in Emacs Lisp, this
package opts to keep it as simple and predictable as possible.
+@node Macro-Writing Macros
+@section Macro-Writing Macros
+
+@noindent
+This package includes two classic Common Lisp macro-writing macros to
+help render complex macrology easier to read.
+
+@defmac cl-with-gensyms names@dots{} body
+This macro expands to code that executes @var{body} with each of the
+variables in @var{names} bound to a fresh uninterned symbol, or
+@dfn{gensym}, in Common Lisp parlance. For macros requiring more than
+one gensym, use of @code{cl-with-gensyms} shortens the code and
+renders one's intentions clearer. Compare:
+
+@example
+(defmacro my-macro (foo)
+ (let ((bar (gensym "bar"))
+ (baz (gensym "baz"))
+ (quux (gensym "quux")))
+ `(let ((,bar (+ @dots{})))
+ @dots{})))
+
+(defmacro my-macro (foo)
+ (cl-with-gensyms (bar baz quux)
+ `(let ((,bar (+ @dots{})))
+ @dots{})))
+@end example
+@end defmac
+
+@defmac cl-once-only ((variable form)@dots{}) body
+This macro is primarily to help the macro programmer ensure that forms
+supplied by the user of the macro are evaluated just once by its
+expansion even though the result of evaluating the form is to occur
+more than once. Less often, this macro is used to ensure that forms
+supplied by the macro programmer are evaluated just once.
+
+Each @var{variable} may be used to refer to the result of evaluating
+@var{form} in @var{body}. @code{cl-once-only} binds each
+@var{variable} to a fresh uninterned symbol during the evaluation of
+@var{body}. Then, @code{cl-once-only} wraps the final expansion in
+code to evaluate each @var{form} and bind the result to the
+corresponding uninterned symbol. Thus, when the macro writer
+substitutes the value for @var{variable} into the expansion they are
+effectively referring to the result of evaluating @var{form}, rather
+than @var{form} itself. Another way to put this is that each
+@var{variable} is bound to an expression for the (singular) result of
+evaluating @var{form}.
+
+The most common case is where @var{variable} is one of the arguments
+to the macro being written, so @code{(variable variable)} may be
+abbreviated to just @code{variable}.
+
+For example, consider this macro:
+
+@example
+(defmacro my-list (x y &rest forms)
+ (let ((x-result (gensym))
+ (y-result (gensym)))
+ `(let ((,x-result ,x)
+ (,y-result ,y))
+ (list ,x-result ,y-result ,x-result ,y-result
+ (progn ,@@forms))))
+@end example
+
+In a call like @w{@code{(my-list (pop foo) @dots{})}} the intermediate
+binding to @code{x-result} ensures that the @code{pop} is not done
+twice. But as a result the code is rather complex: the reader must
+keep track of how @code{x-result} really just means the first
+parameter of the call to the macro, and the required use of multiple
+gensyms to avoid variable capture by @code{(progn ,@@forms)} obscures
+things further. @code{cl-once-only} takes care of these details:
+
+@example
+(defmacro my-list (x y &rest forms)
+ (cl-once-only (x y)
+ `(list ,x ,y ,x ,y
+ (progn ,@@forms))))
+@end example
+@end defmac
+
@node Macros
@chapter Macros
@@ -2868,6 +2949,7 @@ out the property and value cells.
@node Creating Symbols
@section Creating Symbols
+@cindex gensym
@noindent
These functions create unique symbols, typically for use as
@@ -5028,13 +5110,13 @@ The above @code{incf} example could be written using
@example
(defmacro incf (place &optional n)
(gv-letplace (getter setter) place
- (macroexp-let2 nil v (or n 1)
+ (cl-once-only ((v (or n 1)))
(funcall setter `(+ ,v ,getter)))))
@end example
@ignore
(defmacro concatf (place &rest args)
(gv-letplace (getter setter) place
- (macroexp-let2 nil v (mapconcat 'identity args)
+ (cl-once-only ((v `(mapconcat 'identity ',args)))
(funcall setter `(concat ,getter ,v)))))
@end ignore
@end defmac
diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi
index 0b4f53ba136..bb97446d127 100644
--- a/doc/misc/dbus.texi
+++ b/doc/misc/dbus.texi
@@ -795,13 +795,7 @@ and interface. Example:
(dbus-get-all-managed-objects
:session "org.gnome.SettingsDaemon" "/")
-@result{} (("/org/gnome/SettingsDaemon/MediaKeys"
- ("org.gnome.SettingsDaemon.MediaKeys")
- ("org.freedesktop.DBus.Peer")
- ("org.freedesktop.DBus.Introspectable")
- ("org.freedesktop.DBus.Properties")
- ("org.freedesktop.DBus.ObjectManager"))
- ("/org/gnome/SettingsDaemon/Power"
+@result{} (("/org/gnome/SettingsDaemon/Power"
("org.gnome.SettingsDaemon.Power.Keyboard")
("org.gnome.SettingsDaemon.Power.Screen")
("org.gnome.SettingsDaemon.Power"
diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi
index 754ccf4065c..50d9914081c 100644
--- a/doc/misc/dired-x.texi
+++ b/doc/misc/dired-x.texi
@@ -165,10 +165,8 @@ When @file{dired-x.el} is loaded, some standard Dired functions from
Dired}), if it is active. @code{dired-find-buffer-nocreate} and
@code{dired-initial-position} respect the value of
@code{dired-find-subdir} (@pxref{Miscellaneous Commands}).
-@code{dired-clean-up-after-deletion} respects the value of
-@code{dired-clean-up-buffers-too}. @code{dired-read-shell-command} uses
-@code{dired-guess-shell-command} (@pxref{Shell Command Guessing}) to
-offer a smarter default command.
+@code{dired-read-shell-command} uses @code{dired-guess-shell-command}
+(@pxref{Shell Command Guessing}) to offer a smarter default command.
@node Installation
@chapter Installation
@@ -884,15 +882,6 @@ normal and a wildcard buffer for the same directory, @kbd{C-x d @key{RET}}
will toggle between those two.
@end table
-@table @kbd
-@findex dired-goto-subdir
-@kindex M-G
-@item M-G
-(@code{dired-goto-subdir}) Go to the header line of an inserted directory.
-This command reads its argument, with completion derived from the names of the
-inserted subdirectories.
-@end table
-
@table @code
@item dired-vm
@@ -920,55 +909,6 @@ to @kbd{V}. Otherwise, @code{dired-bind-rmail} will be bound.
@findex dired-rmail
Bound to @kbd{V} if @code{dired-bind-vm} is @code{nil}. Run Rmail on this
file (assumed to be mail folder in Rmail format).
-
-@item dired-info
-@kindex I
-@cindex running info.
-@findex dired-info
-Bound to @kbd{I}. Run Info on this file (assumed to be a file in Info
-format).
-
-@vindex dired-bind-info
-If the variable @code{dired-bind-info} is @code{nil}, @code{dired-info} will
-not be bound to @kbd{I}.
-
-@item dired-man
-@cindex running man.
-@kindex N
-@findex dired-man
-Bound to @kbd{N}. Run man on this file (assumed to be a file in @code{nroff}
-format).
-
-@vindex dired-bind-man
-If the variable @code{dired-bind-man} is @code{nil}, @code{dired-man} will not
-be bound to @kbd{N}.
-
-@item dired-do-relsymlink
-@cindex relative symbolic links.
-@kindex Y
-@findex dired-do-relsymlink
-Bound to @kbd{Y}. Relative symlink all marked (or next ARG) files into a
-directory, or make a relative symbolic link to the current file. This creates
-relative symbolic links like
-
-@example
- foo -> ../bar/foo
-@end example
-
-@noindent
-not absolute ones like
-
-@example
- foo -> /ugly/path/that/may/change/any/day/bar/foo
-@end example
-
-@item dired-do-relsymlink-regexp
-@kindex %Y
-@findex dired-do-relsymlink-regexp
-Bound to @kbd{%Y}. Relative symlink all marked files containing
-@var{regexp} to @var{newname}. See functions
-@code{dired-do-rename-regexp} and @code{dired-do-relsymlink} for more
-info.
@end table
@node Bugs
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index d81ba158a19..39b09b29b3f 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -1866,7 +1866,8 @@ These variables specify the options to pass to the above utilities.
In @code{ediff-diff-options}, it may be useful to specify options
such as @samp{-w} that ignore certain kinds of changes. However,
Ediff does not let you use the option @samp{-c}, as it doesn't recognize this
-format yet.
+format yet. (If you alter this variable, it should be done via the
+Customize interface instead of using @code{setq} directly.)
@item ediff-coding-system-for-read
@vindex ediff-coding-system-for-read
diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi
index 8dcdb121abe..084b5a3254e 100644
--- a/doc/misc/efaq-w32.texi
+++ b/doc/misc/efaq-w32.texi
@@ -130,10 +130,8 @@ from Windows 98 onward, and all versions of the NT family starting
from NT 4.0; this includes all the modern versions from Windows XP and
on. The Windows port is built using the Win32 API and supports most
features of the X version, including variable width fonts, images and
-tooltips.
-
-Emacs on Windows can be compiled as either a 32-bit or a 64-bit
-executable, using the MinGW GCC compiler and development tools.
+tooltips. Emacs on Windows can be compiled as either a 64-bit or a
+32-bit executable.
@node Other versions of Emacs
@section What other versions of Emacs run on Windows?
@@ -177,8 +175,8 @@ best-effort basis in the @file{windows} subdirectory of the above ftp
site (as zip files digitally signed by the person who built them).
See the @file{README} file in that directory for more information.
Building Emacs from source yourself should be straightforward,
-following the instructions in @file{nt/INSTALL}, so we encourage you
-to give it a try. @xref{Compiling}.
+following the instructions in the @file{nt} directory, so we
+encourage you to give it a try. @xref{Compiling}.
@cindex latest development version of Emacs
@cindex Emacs Development
@@ -190,21 +188,27 @@ development site.
@section How can I compile Emacs myself?
@cindex compiling Emacs
-To compile Emacs on Windows, you will need the MinGW port of GCC and
-Binutils, the MinGW runtime and development environment, and the MSYS
-suite of tools. For the details, see the file @file{nt/INSTALL} in
-the Emacs source distribution.
+To compile Emacs on a 64-bit version of Windows 7 or newer, we
+recommend to use the MinGW-w64 port of GCC and Binutils with the MSYS2
+suite of tools. For the details, see the file @file{nt/INSTALL.W64}
+in the Emacs source distribution.
+
+If you need to build or run Emacs on MS Windows before Windows 7, you
+have to use the MinGW port of GCC and the MSYS suite of tools. The
+file @file{nt/INSTALL} in Emacs source distribution contains the
+details.
Support for displaying images, as well as XML/HTML rendering and TLS
networking requires external libraries, the headers and import
libraries for which will need to be installed where your compiler can
find them. Again, the details, including URLs of sites where you can
-download these libraries are in @file{nt/INSTALL}. @xref{Other useful
-ports}, for auxiliary tools you may wish to install and use in
-conjunction with Emacs.
+download these libraries are in @file{nt/INSTALL.W64} or
+@file{nt/INSTALL}. @xref{Other useful ports}, for auxiliary tools you
+may wish to install and use in conjunction with Emacs.
After unpacking the source, or checking out of the repository, be sure
-to read the instructions in @file{nt/README} and @file{nt/INSTALL}.
+to read the instructions in @file{nt/README} and the respective
+install file.
@node Debugging
@section How do I use a debugger on Emacs?
@@ -222,18 +226,18 @@ specific notes about debugging Emacs.
@cindex debugging Emacs with GDB
GDB is the GNU debugger, which can be used to debug Emacs when it has
-been compiled with MinGW GCC@. The best results will be obtained if
-you start gdb from the @file{src} directory as @kbd{gdb ./emacs.exe}.
+been compiled with GCC@. The best results will be obtained if you
+start gdb from the @file{src} directory as @kbd{gdb ./emacs.exe}.
This will load the init file @file{.gdbinit}@footnote{
Latest versions of GDB might refuse to load the init file for security
reasons, unless you customize GDB; alternatively, use an explicit
@kbd{source ./gdbinit} command after entering GDB.
} in that directory, to define some extra commands for working with
-lisp while debugging, and set up breakpoints to catch abnormal
-aborts.
+lisp while debugging, and set up breakpoints to catch abnormal aborts.
-A Windows port of GDB can be found on MinGW download sites and on some
-others.
+A Windows port of GDB is installed with MinGW64-w64 and MSYS2
+(@samp{mingw-w64-<arch>-toolchain} group) or can be found on MinGW
+download sites and on some others.
@c ------------------------------------------------------------
@node Installing Emacs
@@ -307,8 +311,8 @@ bsdtar -xf emacs-@value{EMACSVER}.tar.xz
Expect @command{bsdtar} to unpack the whole distribution without any
complaints.
-Once you unpack the source distribution, look in @file{nt/INSTALL}
-file for build instructions.
+Once you unpack the source distribution, look in the @file{nt}
+directory for build instructions.
@node Installing binaries
@section How do I install Emacs after unpacking the binary zip?
@@ -1645,8 +1649,8 @@ obtained the packages from if you want to use them.
In your @env{HOME} directory create a file called @file{.mailcap},
with contents like the following:
@example
-application/zip "C:/Program Files/7-Zip/7zFM.exe"
-video/* "C:/Program Files/VideoLAN/VLC/vlc.exe"
+application/zip; "C:/Program Files/7-Zip/7zFM.exe"
+video/*; "C:/Program Files/VideoLAN/VLC/vlc.exe"
@end example
@strong{Warning:} Associating MIME types with @command{start} or other
@@ -1742,23 +1746,6 @@ You will need an implementation of TeX for Windows.
A number of implementations are listed on the
@uref{http://www.tug.org/interest.html#free, TeX Users Group} website.
-@menu
-* AUCTeX::
-@end menu
-
-@node AUCTeX
-@subsection AUCTeX
-@cindex auctex, precompiled for Windows
-@cindex latex
-@cindex preview-latex
-
-AUCTeX is an Emacs package for writing LaTeX files, which also
-includes preview-latex, an Emacs mode for previewing the formatted
-contents of LaTeX documents. Pre-compiled versions for Windows are
-available from
-@uref{https://www.gnu.org/software/auctex/download-for-windows.html, the
-AUCTeX site}.
-
@node Spell check
@section How do I perform spell checks?
@cindex spell checking
@@ -1771,11 +1758,13 @@ AUCTeX site}.
Emacs has support for spell checking on demand (@code{ispell}) and as
your type (@code{flyspell}). Both packages depend on a copy of
@command{ispell} 3.2 or a compatible spell-checking program.
-GNU Aspell is a popular choice these days, Windows installers are
-available from the @uref{http://aspell.net/win32/, official site}.
+GNU Aspell is a popular choice these days, outdated Windows installers
+are available from the @uref{http://aspell.net/win32/, official site}.
Another possibility is Hunspell, which is available from
@uref{https://sourceforge.net/projects/ezwinports/files/?source=navbar,
-the ezwinports site}.
+the ezwinports site}. If you're using the MSYS2 distribution, you can
+install a recent version of either GNU Aspell or Hunspell through the
+package manager Pacman. @xref{Other useful ports}.
Once installed, you will need to configure @code{ispell-program-name}
to tell ispell and flyspell to use @command{aspell} or
@@ -2113,9 +2102,9 @@ suggestions} for improving the interaction of perldb and Emacs.
@menu
* Cygwin::
-* MinGW::
+* MinGW-w64::
* EZWinPorts::
-* UWIN::
+* MinGW::
* GnuWin32::
* GTK::
* Read man pages::
@@ -2150,22 +2139,25 @@ Cygwin on your system @env{PATH} for this reason. Instead you can
make the Cygwin tools available within Emacs by setting @code{exec-path}
in your init file.
-@node MinGW
-@section MinGW and MSYS
-@cindex mingw tools
-@cindex msys environment
-@cindex subprocesses, mingw and msys
+@node MinGW-w64
+@section MinGW-w64 and MSYS2
+@cindex mingw-w64 tools
+@cindex msys2 environment
+@cindex subprocesses, mingw-w64 and msys2
-@uref{http://www.mingw.org/}
+@uref{https://www.msys2.org/}
-MinGW is a set of development tools that produce native Windows
+MinGW-w64 is a set of development tools that produce native Windows
executables, not dependent on Cygwin's POSIX emulation DLLs.
+MinGW-w64 has forked the original MinGW in 2007 in order to provide
+support for 64 bits and new APIs.
-MSYS is a POSIX shell and minimal set of tools that are commonly used in
-configure scripts. Like Cygwin, this environment uses a non-native
-filesystem mapping to appear more POSIX like to the scripts that it
-runs. This is intended to complement the MinGW tools to make it easier
-to port software to Windows.
+MSYS2 is software distribution and a building platform for Windows.
+MSYS2 is an independent rewrite of MSYS, based on modern Cygwin and
+MinGW-w64 with the aim of better interoperability with native Windows
+software. It plays the same role MSYS does in MinGW. Being a
+distribution, MSYS2 provides tools to build software as well as more
+than 2.600 precompiled packages ready for use.
@node EZWinPorts
@section EZWinPorts
@@ -2178,16 +2170,22 @@ software. This includes all the optional libraries used by Emacs
@command{man} command, Grep, xz, bzip2, bsdtar, ID Utils, Findutils,
Hunspell, Gawk, GNU Make, Groff, GDB.
-@node UWIN
-@section UWIN
-@cindex uwin environment
-@cindex subprocesses, uwin
+@node MinGW
+@section MinGW and MSYS
+@cindex mingw tools
+@cindex msys environment
+@cindex subprocesses, mingw and msys
-@uref{http://www.research.att.com/sw/tools/uwin/}
+@uref{https://osdn.net/projects/mingw/}
-UWIN is another POSIX emulation environment, like Cygwin and MSYS,
-that provides a large number of ported tools. The shell used by UWIN
-is @command{ksh}, the Korn shell.
+MinGW is another set of development tools that produce native Windows
+executables, not dependent on Cygwin's POSIX emulation DLLs.
+
+MSYS is a POSIX shell and minimal set of tools that are commonly used in
+configure scripts. Like Cygwin, this environment uses a non-native
+filesystem mapping to appear more POSIX like to the scripts that it
+runs. This is intended to complement the MinGW tools to make it easier
+to port software to Windows.
@node GnuWin32
@section GnuWin32
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index ed8a919ac7e..a98c4b6a614 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -9,10 +9,9 @@
@copying
Copyright @copyright{} 2001--2022 Free Software Foundation, Inc.@*
-Copyright @copyright{} 1994, 1995, 1996, 1997, 1998, 1999, 2000
-Reuven M. Lerner@*
-Copyright @copyright{} 1992, 1993 Steven Byrnes@*
-Copyright @copyright{} 1990, 1991, 1992 Joseph Brian Wells@*
+Copyright @copyright{} 1994--2000 Reuven M. Lerner@*
+Copyright @copyright{} 1992--1993 Steven Byrnes@*
+Copyright @copyright{} 1990--1992 Joseph Brian Wells@*
@quotation
This list of frequently asked questions about GNU Emacs with answers
@@ -259,12 +258,13 @@ name displayed by this will be the full pathname of the installed
@code{data-directory}, and @kbd{C-h v} displays the value and the
documentation of a variable.)
-The location of your Info directory (i.e., where Info documentation
-is stored) is kept in the variable @code{Info-default-directory-list}. Use
-@kbd{C-h v Info-default-directory-list @key{RET}} to see the value of
-this variable, which will be a list of directory names. The last
-directory in that list is probably where most Info files are stored. By
-default, Emacs Info documentation is placed in @file{/usr/local/share/info}.
+The location of your Info directory (i.e., where Info documentation is
+stored) is kept in the variable @code{Info-directory-list}. Use
+@kbd{C-h v Info-directory-list @key{RET}} to see the value of this
+variable, which will be a list of directory names (after Info has been
+started). The last directory in that list is probably where most Info
+files are stored. By default, Emacs Info documentation is placed in
+@file{/usr/local/share/info}.
For information on some of the files in the @file{etc} directory,
@pxref{Informational files for Emacs}.
@@ -701,7 +701,7 @@ directory which is a subdirectory of your home directory named @file{Info},
you could put this in your @file{.emacs} file:
@lisp
-(add-to-list 'Info-default-directory-list "~/Info")
+(add-to-list 'Info-default-directory-list "~/Info/")
@end lisp
You will need a top-level Info file named @file{dir} in this directory
@@ -881,10 +881,11 @@ divergent TECO command sets and key bindings at MIT, and completed by
RMS.
Many people have said that TECO code looks a lot like line noise; you
-can read more at @uref{news:alt.lang.teco}. Someone has written a TECO
-implementation in Emacs Lisp (to find it, see @ref{Packages that do not
-come with Emacs}); it would be an interesting project to run the
-original TECO Emacs inside of Emacs.
+can read more on
+@uref{https://en.wikipedia.org/wiki/TECO_(text_editor), Wikipedia}.
+Someone has written a TECO implementation in Emacs Lisp (to find it,
+see @ref{Packages that do not come with Emacs}); it would be an
+interesting project to run the original TECO Emacs inside of Emacs.
@cindex Why Emacs?
For some not-so-serious alternative reasons for Emacs to have that
@@ -3376,56 +3377,13 @@ bottom of files by setting the variable @code{enable-local-eval}.
@xref{File Variables,,, emacs, The GNU Emacs Manual}.
@item
-Synthetic X events. (Yes, a risk; use @samp{MIT-MAGIC-COOKIE-1} or
-better.)
+Browsing the web.
-Emacs accepts synthetic X events generated by the @code{SendEvent}
-request as though they were regular events. As a result, if you are
-using the trivial host-based authentication, other users who can open X
-connections to your X workstation can make your Emacs process do
-anything, including run other processes with your privileges.
-
-The only fix for this is to prevent other users from being able to open
-X connections. The standard way to prevent this is to use a real
-authentication mechanism, such as @samp{MIT-MAGIC-COOKIE-1}. If using
-the @code{xauth} program has any effect, then you are probably using
-@samp{MIT-MAGIC-COOKIE-1}. Your site may be using a superior
-authentication method; ask your system administrator.
-
-If real authentication is not a possibility, you may be satisfied by
-just allowing hosts access for brief intervals while you start your X
-programs, then removing the access. This reduces the risk somewhat by
-narrowing the time window when hostile users would have access, but
-@emph{does not eliminate the risk}.
-
-On most computers running Unix and X, you enable and disable
-access using the @code{xhost} command. To allow all hosts access to
-your X server, use
-
-@example
-xhost +
-@end example
-
-@noindent
-at the shell prompt, which (on an HP machine, at least) produces the
-following message:
-
-@example
-access control disabled, clients can connect from any host
-@end example
-
-To deny all hosts access to your X server (except those explicitly
-allowed by name), use
-
-@example
-xhost -
-@end example
-
-On the test HP computer, this command generated the following message:
-
-@example
-access control enabled, only authorized clients can connect
-@end example
+Emacs relies on C libraries to parse images, and historically, many of
+these have had exploitable weaknesses. If you're browsing the web
+with the eww browser, it will usually download and display images
+using these libraries. If an image library has a weakness, it may be
+used by an attacker to gain access.
@end itemize
@@ -3754,7 +3712,6 @@ information is available from
* Compose Character::
* Binding combinations of modifiers and function keys::
* Meta key does not work in xterm::
-* SPC no longer completes file names::
@end menu
@node Binding keys to commands
@@ -4200,10 +4157,6 @@ If there is an @code{rlogin} connection between @code{xterm} and Emacs, the
of every character.
@item
-If Emacs is running on Ultrix, it is reported that evaluating
-@code{(set-input-mode t nil)} helps.
-
-@item
If all else fails, you can make @code{xterm} generate @kbd{@key{ESC} W} when
you type @kbd{M-W}, which is the same conversion Emacs would make if it
got the @kbd{M-W} anyway. In X11R4, the following resource
@@ -4228,22 +4181,6 @@ You might have to replace @samp{Meta} with @samp{Alt}.
@end itemize
-@node SPC no longer completes file names
-@section Why doesn't @key{SPC} complete file names anymore?
-@cindex @kbd{SPC} file name completion
-
-Starting with Emacs 22.1, @kbd{SPC} no longer completes file names in
-the minibuffer, so that file names with embedded spaces could be typed
-without the need to quote the spaces.
-
-You can get the old behavior by binding @kbd{SPC} to
-@code{minibuffer-complete-word} in the minibuffer, as follows:
-
-@lisp
-(define-key minibuffer-local-filename-completion-map (kbd "SPC")
- 'minibuffer-complete-word)
-@end lisp
-
@c ------------------------------------------------------------
@node Alternate character sets
@chapter Alternate character sets
@@ -4337,75 +4274,6 @@ add the following line to your @file{~/.emacs}:
(setq ps-multibyte-buffer 'bdf-font-except-latin)
@end lisp
-A few additional steps are necessary for MS-Windows; they are listed
-below.
-
-First, make sure @emph{all} the directories with BDF font files are
-mentioned in @code{bdf-directory-list}. On Unix and GNU/Linux
-systems, one normally runs @kbd{make install} to install the BDF fonts
-in the same directory. By contrast, Windows users typically don't run
-the Intlfonts installation command, but unpack the distribution in
-some directory, which leaves the BDF fonts in its subdirectories. For
-example, assume that you unpacked Intlfonts in @file{C:/Intlfonts};
-then you should set @code{bdf-directory-list} as follows:
-
-@lisp
- (setq bdf-directory-list
- '("C:/Intlfonts/Asian"
- "C:/Intlfonts/Chinese" "C:/Intlfonts/Chinese.X"
- "C:/Intlfonts/Chinese.BIG" "C:/Intlfonts/Ethiopic"
- "C:/Intlfonts/European" "C:/Intlfonts/European.BIG"
- "C:/Intlfonts/Japanese" "C:/Intlfonts/Japanese.X"
- "C:/Intlfonts/Japanese.BIG" "C:/Intlfonts/Korean.X"
- "C:/Intlfonts/Misc"))
-@end lisp
-
-@cindex @code{w32-bdf-filename-alist}
-@cindex @code{w32-find-bdf-fonts}
-Next, you need to set up the variable @code{w32-bdf-filename-alist} to
-an alist of the BDF fonts and their corresponding file names.
-Assuming you have set @code{bdf-directory-list} to name all the
-directories with the BDF font files, the following Lisp snippet will
-set up @code{w32-bdf-filename-alist}:
-
-@lisp
- (setq w32-bdf-filename-alist
- (w32-find-bdf-fonts bdf-directory-list))
-@end lisp
-
-Now, create fontsets for the BDF fonts:
-
-@smallexample
- (create-fontset-from-fontset-spec
- "-*-fixed-medium-r-normal-*-16-*-*-*-c-*-fontset-bdf,
- japanese-jisx0208:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0208.1983-*,
- katakana-jisx0201:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0201*-*,
- latin-jisx0201:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0201*-*,
- japanese-jisx0208-1978:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0208.1978-*,
- thai-tis620:-misc-fixed-medium-r-normal--16-160-72-72-m-80-tis620.2529-1,
- lao:-misc-fixed-medium-r-normal--16-160-72-72-m-80-MuleLao-1,
- tibetan-1-column:-TibMdXA-fixed-medium-r-normal--16-160-72-72-m-80-MuleTibetan-1,
- ethiopic:-Admas-Ethiomx16f-Medium-R-Normal--16-150-100-100-M-160-Ethiopic-Unicode,
- tibetan:-TibMdXA-fixed-medium-r-normal--16-160-72-72-m-160-MuleTibetan-0")
-@end smallexample
-
-Many of the international bdf fonts from Intlfonts are type 0, and
-therefore need to be added to font-encoding-alist:
-
-@lisp
- (setq font-encoding-alist
- (append '(("MuleTibetan-0" (tibetan . 0))
- ("GB2312" (chinese-gb2312 . 0))
- ("JISX0208" (japanese-jisx0208 . 0))
- ("JISX0212" (japanese-jisx0212 . 0))
- ("VISCII" (vietnamese-viscii-lower . 0))
- ("KSC5601" (korean-ksc5601 . 0))
- ("MuleArabic-0" (arabic-digit . 0))
- ("MuleArabic-1" (arabic-1-column . 0))
- ("MuleArabic-2" (arabic-2-column . 0)))
- font-encoding-alist))
-@end lisp
-
You can now use the Emacs font menu to select the @samp{bdf: 16-dot medium}
fontset, or you can select it by setting the default font in your
@file{~/.emacs}:
@@ -4414,7 +4282,6 @@ fontset, or you can select it by setting the default font in your
(set-frame-font "fontset-bdf")
@end lisp
-
@c ------------------------------------------------------------
@node Mail and news
@chapter Mail and news
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index b9297738ea2..3db83197f9e 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -545,20 +545,27 @@ Non-interactively, it takes the following keyword arguments.
@item @var{server}
@item @var{port}
@item @var{nick}
+@item @var{user}
@item @var{password}
@item @var{full-name}
+@item @var{id}
@end itemize
-That is, if called with the following arguments, @var{server} and
-@var{full-name} will be set to those values, whereas
-@code{erc-compute-port} and @code{erc-compute-nick} will be invoked
-for the values of the other parameters.
+For example, calling the command like so
-@example
+@example lisp
(erc :server "irc.libera.chat" :full-name "J. Random Hacker")
@end example
+
+@noindent
+sets @var{server} and @var{full-name} directly while leaving the rest
+up to functions like @code{erc-compute-port}. Note that some
+arguments can't be specified interactively. @var{id}, in particular,
+is rarely needed (@pxref{Network Identifier}).
+
@end defun
+@noindent
To connect securely over an encrypted TLS connection, use @kbd{M-x
erc-tls}.
@@ -570,21 +577,25 @@ Non-interactively, it takes the following keyword arguments.
@item @var{server}
@item @var{port}
@item @var{nick}
+@item @var{user}
@item @var{password}
@item @var{full-name}
+@item @var{id}
@item @var{client-certificate}
@end itemize
-That is, if called with the following arguments, @var{server} and
-@var{full-name} will be set to those values, whereas
-@code{erc-compute-port} and @code{erc-compute-nick} will be invoked
-for the values of the other parameters, and @code{client-certificate}
-will be @code{nil}.
+That is, if called in the following manner
-@example
+@example lisp
(erc-tls :server "irc.libera.chat" :full-name "J. Random Hacker")
@end example
+@noindent
+the command will set @var{server} and @var{full-name} accordingly,
+while helpers, like @code{erc-compute-nick}, will determine other
+parameters, and some, like @code{client-certificate}, will just be
+@code{nil}.
+
To use a certificate with @code{erc-tls}, specify the optional
@var{client-certificate} keyword argument, whose value should be as
described in the documentation of @code{open-network-stream}: if
@@ -719,29 +730,139 @@ ERC should automatically attempt to connect with another nickname.
You can manually set another nickname with the /NICK command.
@end defopt
+@subheading User
+@defun erc-compute-user &optional user
+Determine a suitable value to send as the first argument of the
+opening @samp{USER} IRC command by consulting the following sources:
+
+@itemize
+@item
+@var{user}, the argument passed to this function
+@item
+The option @code{erc-email-userid}, assuming @code{erc-anonymous-login}
+is non-@code{nil}
+@item
+The result of calling the function @code{user-login-name}
+@end itemize
+
+@end defun
+
+@defopt erc-email-userid
+A permanent username value to send for all connections. It should be
+a string abiding by the rules of the network.
+@end defopt
+
@subheading Password
@cindex password
@defopt erc-prompt-for-password
-If non-@code{nil} (the default), @kbd{M-x erc} prompts for a password.
+If non-@code{nil} (the default), @kbd{M-x erc} and @kbd{M-x erc-tls}
+prompt for a server password. This only affects interactive
+invocations of @code{erc} and @code{erc-tls}.
@end defopt
+@noindent
If you prefer, you can set this option to @code{nil} and use the
@code{auth-source} mechanism to store your password. For instance, if
-you use @file{~/.authinfo} as your auth-source backend, then put
+the option @code{auth-sources} contains @file{~/.authinfo}, put
something like the following in that file:
@example
-machine irc.example.net login "#fsf" password sEcReT
+machine irc.example.net login mynick password sEcReT
@end example
@noindent
-ERC also consults @code{auth-source} to find any channel keys required
-for the channels that you wish to autojoin, as specified by the
-variable @code{erc-autojoin-channels-alist}.
+For server passwords, that is, passwords sent for the IRC @samp{PASS}
+command, the @samp{host} field (@w{@code{machine irc.example.net}} in
+the above example)
+corresponds to the @var{server} parameter used by @code{erc} and
+@code{erc-tls}. Unfortunately, specifying a network, like
+@samp{Libera.Chat}, or a specific network server, like
+@samp{platinum.libera.chat}, won't normally work for looking up a server
+password because such information isn't available during opening
+introductions. (Actually, ERC @emph{can} find entries with arbitrary
+@samp{host} values for any context, including server passwords, but
+that requires customizing the more advanced options below.)
+
+If ERC can't find a suitable server password, it will just skip the IRC
+@samp{PASS} command altogether, something users may want when using
+CertFP or engaging NickServ via ERC's ``services'' module. If that is
+what you'd like to do, you can also customize the option
+@code{erc-auth-source-server-function} to @code{nil} to skip
+server-password lookup for all servers. Note that some networks and
+IRCds may accept account-services authentication via server password
+using the nonstandard @samp{mynick:sEcReT} convention.
+
+As just mentioned, you can also use @code{auth-source} to authenticate
+to account services the traditional way, through a bot called
+@samp{NickServ}. To tell ERC to do that, set
+@code{erc-use-auth-source-for-nickserv-password} to @code{t}. For
+these and most other queries, entries featuring custom identifiers and
+networks are matched first, followed by network-specific servers and
+dialed endpoints (typically, the @var{server} argument passed to
+@code{erc}). The following netrc-style entries appear in order of
+precedence:
-For more details, @pxref{Top,,auth-source, auth, Emacs auth-source Library}.
+@example
+machine Libera/cellphone login MyNick password sEcReT
+machine Libera.Chat login MyNick password sEcReT
+machine zirconium.libera.chat login MyNick password sEcReT
+machine irc.libera.chat login MyNick password sEcReT
+@end example
+@noindent
+Remember that field labels vary per backend, so @samp{machine} (in
+netrc's case) maps to auth-source's generalized notion of a host,
+hence the @samp{:host} keyword property. Also, be sure to mind the
+syntax of your chosen backend medium. For example, always quote
+channel names in a netrc file.
+
+If this all seems overly nuanced or just plain doesn't appeal to you,
+see options @code{erc-auth-source-services-function} and friends, described
+below. These let you query auth-source your way. Most users can
+simply ignore the passed-in arguments and get by with something like
+the following:
+
+@lisp
+(defun my-fancy-auth-source-func (&rest _)
+ (let* ((host (read-string "host: " nil nil "default"))
+ (pass (auth-source-pick-first-password :host host)))
+ (if (and pass (string-search "libera" host))
+ (concat "MyNick:" pass)
+ pass)))
+@end lisp
+
+Lastly, ERC also consults @code{auth-source} to find ``keys'' that may
+be required by certain channels you join. When modifying a
+traditional @code{auth-source} entry for this purpose, put the channel
+name in the @samp{user} field (for example, @samp{login "#fsf"}, in
+netrc's case). The actual key goes in the @samp{password} (or
+@samp{secret}) field.
+
+@noindent
+For details, @pxref{Top,,auth-source, auth, Emacs auth-source Library}.
+
+@defopt erc-auth-source-server-function
+@end defopt
+@defopt erc-auth-source-services-function
+@end defopt
+@defopt erc-auth-source-join-function
+
+ERC calls these functions with keyword arguments recognized by
+@code{auth-source-search}, namely, those deemed most relevant to the
+current context, if any. For example, with NickServ queries,
+@code{:user} is the ``desired'' nickname rather than the current one.
+Generalized names, like @code{:user} and @code{:host}, are always used
+over back-end specific ones, like @code{:login} or @code{:machine}.
+ERC expects a string to use as the secret or nil, if the search fails.
+
+@findex erc-auth-source-search
+The default value for all three options is the function
+@code{erc-auth-source-search}. It tries to merge relevant contextual
+parameters with those provided or discovered from the logical connection
+or the underlying transport. Some auth-source back ends may not be
+compatible; netrc, plstore, json, and secrets are currently supported.
+@end defopt
@subheading Full name
@@ -752,10 +873,14 @@ This tries a number of increasingly more default methods until a
non-@code{nil} value is found.
@itemize @bullet
-@item @var{full-name} (the argument passed to this function)
-@item The @code{erc-user-full-name} option
-@item The value of the IRCNAME environment variable
-@item The result from the @code{user-full-name} function
+@item
+@var{full-name} (the argument passed to this function)
+@item
+The @code{erc-user-full-name} option
+@item
+The value of the IRCNAME environment variable
+@item
+The result from the @code{user-full-name} function
@end itemize
@end defun
@@ -766,6 +891,31 @@ User full name.
This can be either a string or a function to call.
@end defopt
+
+@subheading ID
+@anchor{Network Identifier}
+
+ERC uses an abstract designation, called @dfn{network context
+identifier}, for referring to a connection internally. While normally
+derived from a combination of logical and physical connection
+parameters, an ID can also be explicitly provided via an entry-point
+command (like @code{erc-tls}). Use this in rare situations where ERC
+would otherwise have trouble discerning between connections.
+
+One such situation might arise when using multiple connections to the
+same network with the same nick but different (nonstandard) @samp{device}
+identifiers, which some bouncers may support. Another might be when
+mimicking the experience offered by popular standalone clients, which
+normally offer ``named'' persistent configurations with server buffers
+reflecting those names. Yet another use case might involve
+third-party code needing to identify a connection unequivocally, but in
+a human-friendly way suitable for UI components.
+
+When providing an ID as an entry-point argument, strings and symbols
+make the most sense, but any reasonably printable object is
+acceptable.
+
+
@node Sample Configuration
@section Sample Configuration
@cindex configuration, sample
@@ -827,12 +977,6 @@ stuff, to the current ERC buffer."
(setq erc-autojoin-channels-alist
'(("Libera.Chat" "#emacs" "#erc")))
-;; Rename server buffers to reflect the current network name instead
-;; of SERVER:PORT (e.g., "Libera.Chat" instead of
-;; "irc.libera.chat:6667"). This is useful when using a bouncer like
-;; ZNC where you have multiple connections to the same server.
-(setq erc-rename-buffers t)
-
;; Interpret mIRC-style color commands in IRC chats
(setq erc-interpret-mirc-color t)
@@ -891,15 +1035,6 @@ lurkers. The function @code{erc-lurker-p} determines whether a given
nickname is considered a lurker.
@end defopt
-@defopt erc-rename-buffers
-If non, @code{nil}, this will rename server buffers to reflect the
-current network name instead of IP:PORT
-
-@example
-(setq erc-rename-buffers t)
-@end example
-@end defopt
-
@node Getting Help and Reporting Bugs
@chapter Getting Help and Reporting Bugs
@cindex help, getting
@@ -924,7 +1059,7 @@ contributors are frequently around and willing to answer your
questions.
@item
-To report a bug in ERC, use @kbd{M-x report-emacs-bug}.
+To report a bug in ERC, use @kbd{M-x erc-bug}.
@end itemize
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi
index 0d01efb0355..1b7f38daadf 100644
--- a/doc/misc/ert.texi
+++ b/doc/misc/ert.texi
@@ -321,7 +321,7 @@ Show the list of @code{should} forms executed in the test
@kindex m@r{, in ert results buffer}
@findex ert-results-pop-to-messages-for-test-at-point
Show any messages that were generated (with the Lisp function
-@code{message}) in in a test or any of the code that it invoked
+@code{message}) in a test or any of the code that it invoked
(@code{ert-results-pop-to-messages-for-test-at-point}).
@item L
@@ -444,8 +444,9 @@ emacs -batch -l ert -l my-tests.el \
@vindex EMACS_TEST_VERBOSE@r{, environment variable}
By default, ERT test failure summaries are quite brief in batch
mode---only the names of the failed tests are listed. If the
-@env{EMACS_TEST_VERBOSE} environment variable is set, the failure
-summaries will also include the data from the failing test.
+@env{EMACS_TEST_VERBOSE} environment variable is set and is non-empty,
+the failure summaries will also include the data from the failing
+test.
@vindex EMACS_TEST_JUNIT_REPORT@r{, environment variable}
ERT can produce JUnit test reports in batch mode. If the environment
@@ -821,7 +822,7 @@ that's pretty difficult to read and write, especially when the text in
question is multi-line.
So ert provides a function called @code{ert-test-erts-file} that takes
-two parameters: The name of a specially-formatted @dfn{erts} file, and
+two parameters: the name of a specially-formatted @dfn{erts} file, and
(optionally) a function that performs the transform.
@findex erts-mode
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 83d324c7e1b..2e3ba4c273b 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -228,15 +228,39 @@ other background process in Emacs.
@node Arguments
@section Arguments
-Command arguments are passed to the functions as either strings or
-numbers, depending on what the parser thinks they look like. If you
-need to use a function that takes some other data type, you will need to
-call it in an Elisp expression (which can also be used with
-@ref{Expansion, expansions}). As with other shells, you can
-escape special characters and spaces with the backslash (@code{\}) and
-apostrophes (@code{''}) and double quotes (@code{""}). This is needed
-especially for file names with special characters like pipe
-(@code{|}), which could be part of remote file names.
+Ordinarily, command arguments are parsed by Eshell as either strings
+or numbers, depending on what the parser thinks they look like. To
+specify an argument of some other data type, you can use an
+@ref{Dollars Expansion, Elisp expression}:
+
+@example
+~ $ echo (list 1 2 3)
+(1 2 3)
+@end example
+
+Additionally, many built-in Eshell commands (@pxref{Built-ins, Eshell
+commands}) will flatten the arguments they receive, so passing a list
+as an argument will ``spread'' the elements into multiple arguments:
+
+@example
+~ $ printnl (list 1 2) 3
+1
+2
+3
+@end example
+
+@subsection Quoting and escaping
+
+As with other shells, you can escape special characters and spaces
+with by prefixing the character with a backslash (@code{\}), or by
+surrounding the string with apostrophes (@code{''}) or double quotes
+(@code{""}). This is needed especially for file names with special
+characters like pipe (@code{|}), which could be part of remote file
+names.
+
+When using expansions (@pxref{Expansion}) in an Eshell command, the
+result may potentially be of any data type. To ensure that the result
+is always a string, the expansion can be surrounded by double quotes.
@node Built-ins
@section Built-in commands
@@ -407,9 +431,16 @@ Summarize disk usage for each file.
@item echo
@cmindex echo
-Echoes its input. If @code{eshell-plain-echo-behavior} is
-non-@code{nil}, @command{echo} will try to behave more like a plain
-shell's @command{echo}.
+Echoes its input. By default, this prints in a Lisp-friendly fashion
+(so that the value is useful to a Lisp command using the result of
+@command{echo} as an argument). If a single argument is passed,
+@command{echo} prints that; if multiple arguments are passed, it
+prints a list of all the arguments; otherwise, it prints the empty
+string.
+
+If @code{eshell-plain-echo-behavior} is non-@code{nil}, @command{echo}
+will try to behave more like a plain shell's @command{echo}, printing
+each argument as a string, separated by a space.
@item env
@cmindex env
@@ -694,6 +725,126 @@ Print the current user. This Eshell version of @command{whoami}
supports Tramp.
@end table
+@subsection Defining new built-in commands
+While Eshell can run Lisp functions directly as commands, it may be
+more convenient to provide a special built-in command for
+Eshell. Built-in commands are just ordinary Lisp functions designed
+to be called from Eshell. When defining an Eshell-specific version of
+an existing function, you can give that function a name starting with
+@code{eshell/} so that Eshell knows to use it.
+
+@defmac eshell-eval-using-options name macro-args options body@dots{}
+This macro processes a list of @var{macro-args} for the command
+@var{name} using a set of command line @var{options}. If the
+arguments are parsed successfully, it will store the resulting values
+in local symbols and execute @var{body}; any remaining arguments will
+be available in the locally let-bound variable @code{args}. The
+return value is the value of the last form in @var{body}.
+
+If an unknown option was passed in @var{macro-args} and an external
+command was specified (see below), this macro will start a process for
+that command and throw the tag @code{eshell-external} with the new
+process as its value.
+
+@var{options} should be a list beginning with one or more elements of
+the following form, with each element representing a particular
+command-line switch:
+
+@example
+(@var{short} @var{long} @var{value} @var{symbol} @var{help-string})
+@end example
+
+@table @var
+@item short
+This element, if non-nil, should be a character to be used as a short
+switch, like @code{-@var{short}}. At least one of this element and
+@var{long} must be non-nil.
+
+@item long
+This element, if non-nil, should be a string to be used as a long
+switch, like @code{--@var{long}}.
+
+@item value
+This element is the value associated with the option. It can be
+either:
+
+@table @asis
+@item @code{t}
+The option needs a value to be specified after the switch.
+
+@item @code{nil}
+The option is given the value @code{t}.
+
+@item anything else
+The option is given the specified value.
+@end table
+
+@item symbol
+This element is the Lisp symbol that will be bound to @var{value}. If
+@var{symbol} is @code{nil}, specifying this switch will instead call
+@code{eshell-show-usage}, and so is appropriate for an option like
+@code{--help}.
+
+@item help-string
+This element is a documentation string for the option, which will be
+displayed when @code{eshell-show-usage} is invoked.
+@end table
+
+After the list of command-line switch elements, @var{options} can
+include additional keyword arguments to control how
+@code{eshell-eval-using-options} behaves. Some of these take
+arguments, while others don't. The recognized keywords are:
+
+@table @code
+@item :external @var{string}
+Specify @var{string} as an external command to run if there are
+unknown switches in @var{macro-args}.
+
+@item :usage @var{string}
+Set @var{string} as the initial part of the command's documentation
+string. It appears before the options are listed.
+
+@item :post-usage @var{string}
+Set @var{string} to be the (optional) trailing part of the command's
+documentation string. It appears after the list of options, but
+before the final part of the documentation about the associated
+external command, if there is one.
+
+@item :show-usage
+If present, then show the usage message if the command is called with
+no arguments.
+
+@item :preserve-args
+Normally, @code{eshell-eval-using-options} flattens the list of
+arguments in @var{macro-args} and converts each to a string. If this
+keyword is present, avoid doing that, instead preserving the original
+arguments. This is useful for commands which want to accept arbitrary
+Lisp objects.
+
+@item :parse-leading-options-only
+If present, do not parse dash or switch arguments after the first
+positional argument. Instead, treat them as positional arguments
+themselves.
+@end table
+
+For example, you could handle a subset of the options for the
+@code{ls} command like this:
+
+@example
+(eshell-eval-using-options
+ "ls" macro-args
+ '((?a nil nil show-all "show all files")
+ (?I "ignore" t ignore-pattern "ignore files matching pattern")
+ (nil "help" nil nil "show this help message")
+ :external "ls"
+ :usage "[OPTION]... [FILE]...
+ List information about FILEs (the current directory by default).")
+ ;; List the files in ARGS somehow...
+ )
+@end example
+
+@end defmac
+
@subsection Built-in variables
Eshell knows a few built-in variables:
@@ -866,15 +1017,42 @@ parsers (such as @command{cpp} and @command{m4}), but in a command
shell, they are less often used for constants, and usually for using
variables and string manipulation.@footnote{Eshell has no
string-manipulation expansions because the Elisp library already
-provides many functions for this.} For example, @code{$var} on a line
-expands to the value of the variable @code{var} when the line is
+provides many functions for this.} For example, @code{$@var{var}} on
+a line expands to the value of the variable @var{var} when the line is
executed. Expansions are usually passed as arguments, but may also be
-used as commands.@footnote{E.g., entering just @samp{$var} at the prompt
-is equivalent to entering the value of @code{var} at the prompt.}
+used as commands.@footnote{E.g., entering just @samp{$@var{var}} at
+the prompt is equivalent to entering the value of @var{var} at the
+prompt.}
+
+You can concatenate expansions with regular string arguments or even
+other expansions. In the simplest case, when the expansion returns a
+string value, this is equivalent to ordinary string concatenation; for
+example, @samp{$@{echo "foo"@}bar} returns @samp{foobar}. The exact
+behavior depends on the types of each value being concatenated:
+
+@table @asis
+
+@item both strings
+Concatenate both values together.
+
+@item one or both numbers
+Concatenate the string representation of each value, converting back to
+a number if possible.
+
+@item one or both (non-@code{nil}) lists
+Concatenate ``adjacent'' elements of each value (possibly converting
+back to a number as above). For example, @samp{$list("a" "b")c}
+returns @samp{("a" "bc")}.
+
+@item anything else
+Concatenate the string represenation of each value.
+
+@end table
@menu
* Dollars Expansion::
* Globbing::
+* Argument Predication and Modification::
@end menu
@node Dollars Expansion
@@ -885,65 +1063,433 @@ of familiarity.
@table @code
-@item $var
-Expands to the value bound to @code{var}. This is the main way to use
+@item $@var{var}
+Expands to the value bound to @var{var}. This is the main way to use
variables in command invocations.
-@item $#var
-Expands to the length of the value bound to @code{var}. Raises an error
-if the value is not a sequence
-(@pxref{Sequences Arrays Vectors, Sequences, , elisp, The Emacs Lisp Reference Manual}).
+@item $"@var{var}"
+@item $'@var{var}'
+Expands to the value bound to @var{var}. This is useful to
+disambiguate the variable name when concatenating it with another
+value, such as @samp{$"@var{var}"-suffix}.
+
+@item $(@var{lisp})
+Expands to the result of evaluating the S-expression @code{(@var{lisp})}. On
+its own, this is identical to just @code{(@var{lisp})}, but with the @code{$},
+it can be used inside double quotes or within a longer string, such as
+@samp{/some/path/$(@var{lisp}).txt}.
+
+@item $@{@var{command}@}
+Returns the output of @command{@var{command}}, which can be any valid
+Eshell command invocation, and may even contain expansions. Similar
+to @code{$(@var{lisp})}, this is identical to @code{@{@var{command}@}}
+when on its own, but the @code{$} allows it to be used inside double
+quotes or as part of a string.
+
+Normally, the output is split line-by-line, returning a list (or the
+first element if there's only one line of output); if
+@code{eshell-convert-numeric-arguments} is non-@code{nil} and every
+line of output looks like a number, convert each line to a number.
+However, when this expansion is surrounded by double quotes, it
+returns the output as a single string instead.
+
+@item $<@var{command}>
+As with @samp{$@{@var{command}@}}, evaluates the Eshell command invocation
+@command{@var{command}}, but writes the output to a temporary file and
+returns the file name.
+
+@item $@var{expr}[@var{i...}]
+Expands to the @var{i}th element of the result of @var{expr}, an
+expression in one of the above forms listed here. If multiple indices
+are supplied, this will return a list containing the elements for each
+index. The exact behavior depends on the type of @var{expr}'s value:
+
+@table @asis
-@item $(lisp)
-Expands to the result of evaluating the S-expression @code{(lisp)}. On
-its own, this is identical to just @code{(lisp)}, but with the @code{$},
-it can be used in a string, such as @samp{/some/path/$(lisp).txt}.
+@item a sequence
+Expands to the element at the (zero-based) index @var{i} of the
+sequence (@pxref{Sequences Arrays Vectors, Sequences, , elisp, The
+Emacs Lisp Reference Manual}).
-@item $@{command@}
-Returns the output of @command{command}, which can be any valid Eshell
-command invocation, and may even contain expansions.
+@item a string
+Split the string at whitespace, and then expand to the @var{i}th
+element of the resulting sequence.
-@item $var[i]
-Expands to the @code{i}th element of the value bound to @code{var}. If
-the value is a string, it will be split at whitespace to make it a list.
-Again, raises an error if the value is not a sequence.
+@item an alist
+If @var{i} is a non-numeric value, expand to the value associated with
+the key @code{"@var{i}"} in the alist. For example, if @var{var} is
+@samp{(("dog" . "fido") ("cat" . "felix"))}, then
+@samp{$@var{var}[dog]} expands to @code{"fido"}. Otherwise, this
+behaves as with sequences; e.g., @samp{$@var{var}[0]} expands to
+@code{("dog" . "fido")}. @xref{Association List Type, Association
+Lists, , elisp, The Emacs Lisp Reference Manual}.
-@item $var[: i]
-As above, but now splitting occurs at the colon character.
+@item anything else
+Signals an error.
-@item $var[: i j]
-As above, but instead of returning just a string, it now returns a list
-of two strings. If the result is being interpolated into a larger
-string, this list will be flattened into one big string, with each
-element separated by a space.
+@end table
-@item $var["\\\\" i]
-Separate on backslash characters. Actually, the first argument -- if it
-doesn't have the form of a number, or a plain variable name -- can be
-any regular expression. So to split on numbers, use @samp{$var["[0-9]+" 10 20]}.
+Multiple sets of indices can also be specified. For example, if
+@var{var} is @samp{((1 2) (3 4))}, then @samp{$@var{var}[0][1]} will
+expand to @code{2}, i.e.@: the second element of the first list member
+(all indices are zero-based).
-@item $var[hello]
-Calls @code{assoc} on @code{var} with @code{"hello"}, expecting it to be
-an alist (@pxref{Association List Type, Association Lists, , elisp,
-The Emacs Lisp Reference Manual}).
+@item $@var{expr}[@var{regexp} @var{i...}]
+As above (when @var{expr} expands to a string), but use @var{regexp}
+to split the string. @var{regexp} can be any form other than a
+number. For example, @samp{$@var{var}[: 0]} will return the first
+element of a colon-delimited string.
-@item $#var[hello]
-Returns the length of the cdr of the element of @code{var} who car is equal
-to @code{"hello"}.
+@item $#@var{expr}
+Expands to the length of the result of @var{expr}, an expression in
+one of the above forms. For example, @samp{$#@var{var}} returns the
+length of the variable @var{var} and @samp{$#@var{var}[0]} returns the
+length of the first element of @var{var}. Again, signals an error if
+the result of @var{expr} is not a string or a sequence.
@end table
@node Globbing
@section Globbing
-Eshell's globbing syntax is very similar to that of Zsh. Users coming
-from Bash can still use Bash-style globbing, as there are no
-incompatibilities. Most globbing is pattern-based expansion, but there
-is also predicate-based expansion. @xref{Filename Generation, , ,
-zsh, The Z Shell Manual},
-for full syntax. To customize the syntax and behavior of globbing in
-Eshell see the Customize@footnote{@xref{Easy Customization, , , emacs,
-The GNU Emacs Manual}.}
-groups ``eshell-glob'' and ``eshell-pred''.
+@vindex eshell-glob-case-insensitive
+Eshell's globbing syntax is very similar to that of Zsh
+(@pxref{Filename Generation, , , zsh, The Z Shell Manual}). Users
+coming from Bash can still use Bash-style globbing, as there are no
+incompatibilities.
+
+By default, globs are case sensitive, except on MS-DOS/MS-Windows
+systems. You can control this behavior via the
+@code{eshell-glob-case-insensitive} option. You can further customize
+the syntax and behavior of globbing in Eshell via the Customize group
+``eshell-glob'' (@pxref{Easy Customization, , , emacs, The GNU Emacs
+Manual}).
+
+@table @samp
+
+@item *
+Matches any string (including the empty string). For example,
+@samp{*.el} matches any file with the @file{.el} extension.
+
+@item ?
+Matches any single character. For example, @samp{?at} matches
+@file{cat} and @file{bat}, but not @file{goat}.
+
+@item **/
+Matches zero or more subdirectories in a file name. For example,
+@samp{**/foo.el} matches @file{foo.el}, @file{bar/foo.el},
+@file{bar/baz/foo.el}, etc. Note that this cannot be combined with
+any other patterns in the same file name segment, so while
+@samp{foo/**/bar.el} is allowed, @samp{foo**/bar.el} is not.
+
+@item ***/
+Like @samp{**/}, but follows symlinks as well.
+
+@cindex character sets, in Eshell glob patterns
+@cindex character classes, in Eshell glob patterns
+@item [ @dots{} ]
+Defines a @dfn{character set} (@pxref{Regexps, , , emacs, The GNU
+Emacs Manual}). A character set matches characters between the two
+brackets; for example, @samp{[ad]} matches @file{a} and @file{d}. You
+can also include ranges of characters in the set by separating the
+start and end with @samp{-}. Thus, @samp{[a-z]} matches any
+lower-case @acronym{ASCII} letter. Note that, unlike in Zsh,
+character ranges are interpreted in the Unicode codepoint order, not
+in the locale-dependent collation order.
+
+Additionally, you can include @dfn{character classes} in a character
+set. A @samp{[:} and balancing @samp{:]} enclose a character class
+inside a character set. For instance, @samp{[[:alnum:]]}
+matches any letter or digit. @xref{Char Classes, , , elisp, The Emacs
+Lisp Reference Manual}, for a list of character classes.
+
+@cindex complemented character sets, in Eshell glob patterns
+@item [^ @dots{} ]
+Defines a @dfn{complemented character set}. This behaves just like a
+character set, but matches any character @emph{except} the ones
+specified.
+
+@cindex groups, in Eshell glob patterns
+@item ( @dots{} )
+Defines a @dfn{group}. A group matches the pattern between @samp{(}
+and @samp{)}. Note that a group can only match a single file name
+component, so a @samp{/} inside a group will signal an error.
+
+@item @var{x}|@var{y}
+Inside of a group, matches either @var{x} or @var{y}. For example,
+@samp{e(m|sh)-*} matches any file beginning with @file{em-} or
+@file{esh-}.
+
+@item @var{x}#
+Matches zero or more copies of the glob pattern @var{x}. For example,
+@samp{fo#.el} matches @file{f.el}, @file{fo.el}, @file{foo.el}, etc.
+
+@item @var{x}##
+Matches one or more copies of the glob pattern @var{x}. Thus,
+@samp{fo#.el} matches @file{fo.el}, @file{foo.el}, @file{fooo.el},
+etc.
+
+@item @var{x}~@var{y}
+Matches anything that matches the pattern @var{x} but not @var{y}. For
+example, @samp{[[:digit:]]#~4?} matches @file{1} and @file{12}, but
+not @file{42}. Note that unlike in Zsh, only a single @samp{~}
+operator can be used in a pattern, and it cannot be inside of a group
+like @samp{(@var{x}~@var{y})}.
+
+@end table
+
+@node Argument Predication and Modification
+@section Argument Predication and Modification
+@cindex argument predication
+@cindex argument modification
+Eshell supports @dfn{argument predication}, to filter elements of a
+glob, and @dfn{argument modification}, to manipulate argument values.
+These are similar to glob qualifiers in Zsh (@pxref{Glob Qualifiers, ,
+, zsh, The Z Shell Manual}).
+
+Predicates and modifiers are introduced with @samp{(@var{filters})}
+after any list argument, where @var{filters} is a list of predicates
+or modifiers. For example, @samp{*(.)} expands to all regular files
+in the current directory and @samp{*(^@@:U^u0)} expands to all
+non-symlinks not owned by @code{root}, upper-cased.
+
+Some predicates and modifiers accept string parameters, such as
+@samp{*(u'@var{user}')}, which matches all files owned by @var{user}.
+These parameters must be surrounded by delimiters; you can use any of
+the following pairs of delimiters: @code{"@dots{}"}, @code{'@dots{}'},
+@code{/@dots{}/}, @code{|@dots{}|}, @code{(@dots{})},
+@code{[@dots{}]}, @code{<@dots{}>}, or @code{@{@dots{}@}}.
+
+You can customize the syntax and behavior of predicates and modifiers
+in Eshell via the Customize group ``eshell-pred'' (@pxref{Easy
+Customization, , , emacs, The GNU Emacs Manual}).
+
+@menu
+* Argument Predicates::
+* Argument Modifiers::
+@end menu
+
+@node Argument Predicates
+@subsection Argument Predicates
+You can use argument predicates to filter lists of file names based on
+various properties of those files. This is most useful when combined
+with globbing, but can be used on any list of files names. Eshell
+supports the following argument predicates:
+
+@table @asis
+
+@item @samp{/}
+Matches directories.
+
+@item @samp{.} @r{(Period)}
+Matches regular files.
+
+@item @samp{@@}
+Matches symbolic links.
+
+@item @samp{=}
+Matches sockets.
+
+@item @samp{p}
+Matches named pipes.
+
+@item @samp{%}
+Matches block or character devices.
+
+@item @samp{%b}
+Matches block devices.
+
+@item @samp{%c}
+Matches character devices.
+
+@item @samp{*}
+Matches regular files that can be executed by the current user.
+
+@item @samp{r}
+@item @samp{A}
+@item @samp{R}
+Matches files that are readable by their owners (@samp{r}), their
+groups (@samp{A}), or the world (@samp{R}).
+
+@item @samp{w}
+@item @samp{I}
+@item @samp{W}
+Matches files that are writable by their owners (@samp{w}), their
+groups (@samp{I}), or the world (@samp{W}).
+
+@item @samp{x}
+@item @samp{E}
+@item @samp{X}
+Matches files that are executable by their owners (@samp{x}), their
+groups (@samp{E}), or the world (@samp{X}).
+
+@item @samp{s}
+Matches files with the setuid flag set.
+
+@item @samp{S}
+Matches files with the setgid flag set.
+
+@item @samp{t}
+Matches files with the sticky bit set.
+
+@item @samp{U}
+Matches files owned by the current effective user ID.
+
+@item @samp{G}
+Matches files owned by the current effective group ID.
+
+@item @samp{l@option{[+-]}@var{n}}
+Matches files with @var{n} links. With @option{+} (or @option{-}),
+matches files with more than (or less than) @var{n} links,
+respectively.
+
+@item @samp{u@var{uid}}
+@item @samp{u'@var{user-name}'}
+Matches files owned by user ID @var{uid} or user name @var{user-name}.
+
+@item @samp{g@var{gid}}
+@item @samp{g'@var{group-name}'}
+Matches files owned by group ID @var{gid} or group name
+@var{group-name}.
+
+@item @samp{a@option{[@var{unit}]}@option{[+-]}@var{n}}
+@item @samp{a@option{[+-]}'@var{file}'}
+Matches files last accessed exactly @var{n} days ago. With @option{+}
+(or @option{-}), matches files accessed more than (or less than)
+@var{n} days ago, respectively.
+
+With @var{unit}, @var{n} is a quantity in that unit of time, so
+@samp{aw-1} matches files last accessed within one week. @var{unit}
+can be @samp{M} (30-day months), @samp{w} (weeks), @samp{h} (hours),
+@samp{m} (minutes), or @samp{s} (seconds).
+
+If @var{file} is specified instead, compare against the modification
+time of @file{file}. Thus, @samp{a-'hello.txt'} matches all files
+accessed after @file{hello.txt} was last accessed.
+
+@item @samp{m@option{[@var{unit}]}@option{[+-]}@var{n}}
+@item @samp{m@option{[+-]}'@var{file}'}
+Like @samp{a}, but examines modification time.
+
+@item @samp{c@option{[@var{unit}]}@option{[+-]}@var{n}}
+@item @samp{c@option{[+-]}'@var{file}'}
+Like @samp{a}, but examines status change time.
+
+@item @samp{L@option{[@var{unit}]}@option{[+-]}@var{n}}
+Matches files exactly @var{n} bytes in size. With @option{+} (or
+@option{-}), matches files larger than (or smaller than) @var{n}
+bytes, respectively.
+
+With @var{unit}, @var{n} is a quantity in that unit of size, so
+@samp{Lm+5} matches files larger than 5 MiB in size. @var{unit} can
+be one of the following (case-insensitive) characters: @samp{m}
+(megabytes), @samp{k} (kilobytes), or @samp{p} (512-byte blocks).
+
+@end table
+
+The @samp{^} and @samp{-} operators are not argument predicates
+themselves, but they modify the behavior of all subsequent predicates.
+@samp{^} inverts the meaning of subsequent predicates, so
+@samp{*(^RWX)} expands to all files whose permissions disallow the
+world from accessing them in any way (i.e., reading, writing to, or
+modifying them). When examining a symbolic link, @samp{-} applies the
+subsequent predicates to the link's target instead of the link itself.
+
+@node Argument Modifiers
+@subsection Argument Modifiers
+You can use argument modifiers to manipulate argument values. For
+example, you can sort lists, remove duplicate values, capitalize
+words, etc. All argument modifiers are prefixed by @samp{:}, so
+@samp{$exec-path(:h:u:x/^\/home/)} lists all of the unique parent
+directories of the elements in @code{exec-path}, excluding those in
+@file{/home}.
+
+@table @samp
+
+@item E
+Re-evaluates the value as an Eshell argument. For example, if
+@var{foo} is @code{"$@{echo hi@}"}, then the result of @samp{$foo(:E)}
+is @code{hi}.
+
+@item L
+Converts the value to lower case.
+
+@item U
+Converts the value to upper case.
+
+@item C
+Capitalizes the value.
+
+@item h
+Treating the value as a file name, gets the directory name (the
+``head''). For example, @samp{foo/bar/baz.el(:h)} expands to
+@samp{foo/bar/}.
+
+@item t
+Treating the value as a file name, gets the base name (the ``tail'').
+For example, @samp{foo/bar/baz.el(:h)} expands to @samp{baz.el}.
+
+@item e
+Treating the value as a file name, gets the final extension of the
+file, excluding the dot. For example, @samp{foo.tar.gz(:e)}
+expands to @code{gz}.
+
+@item r
+Treating the value as a file name, gets the file name excluding the
+final extension. For example, @samp{foo/bar/baz.tar.gz(:r)} expands
+to @samp{foo/bar/baz.tar}.
+
+@item q
+Marks that the value should be interpreted by Eshell literally, so
+that any special characters like @samp{$} no longer have any special
+meaning.
+
+@item s/@var{pattern}/@var{replace}/
+Replaces the first instance of the regular expression @var{pattern}
+with @var{replace}. Signals an error if no match is found.
+
+As with other modifiers taking string parameters, you can use
+different delimiters to separate @var{pattern} and @var{replace}, such
+as @samp{s'@dots{}'@dots{}'}, @samp{s[@dots{}][@dots{}]}, or even
+@samp{s[@dots{}]/@dots{}/}.
+
+@item gs/@var{pattern}/@var{replace}/
+Replaces all instances of the regular expression @var{pattern} with
+@var{replace}.
+
+@item i/@var{pattern}/
+Filters a list of values to include only the elements matching the
+regular expression @var{pattern}.
+
+@item x/@var{pattern}/
+Filters a list of values to exclude all the elements matching the
+regular expression @var{pattern}.
+
+@item S
+@item S/@var{pattern}/
+Splits the value using the regular expression @var{pattern} as a
+delimiter. If @var{pattern} is omitted, split on spaces.
+
+@item j
+@item j/@var{delim}/
+Joins a list of values, inserting the string @var{delim} between each
+value. If @var{delim} is omitted, use a single space as the
+delimiter.
+
+@item o
+Sorts a list of strings in ascending lexicographic order, comparing
+pairs of characters according to their character codes (@pxref{Text
+Comparison, , , elisp, The Emacs Lisp Reference Manual}).
+
+@item O
+Sorts a list of strings in descending lexicographic order.
+
+@item u
+Removes any duplicate elements from a list of values.
+
+@item R
+Reverses the order of a list of values.
+
+@end table
@node Input/Output
@chapter Input/Output
@@ -1015,6 +1561,48 @@ the output function.
The output function is called once on each line of output until
@code{nil} is passed, indicating end of output.
+@section Running Shell Pipelines Natively
+When constructing shell pipelines that will move a lot of data, it is
+a good idea to bypass Eshell's own pipelining support and use the
+operating system shell's instead. This is especially relevant when
+executing commands on a remote machine using Eshell's Tramp
+integration: using the remote shell's pipelining avoids copying the
+data which will flow through the pipeline to local Emacs buffers and
+then right back again.
+
+Eshell recognises a special syntax to make it easier to convert
+pipelines so as to bypass Eshell's pipelining. Prefixing at least one
+@code{|}, @code{<} or @code{>} with an asterisk marks a command as
+intended for the operating system shell. To make it harder to invoke
+this functionality accidentally, it is also required that the asterisk
+be preceded by whitespace or located at the start of input. For
+example,
+
+@example
+ cat *.ogg *| my-cool-decoder >file
+@end example
+
+Executing this command will not copy all the data in the *.ogg files,
+nor the decoded data, into Emacs buffers, as would normally happen.
+
+The command is interpreted as extending up to the next @code{|}
+character which is not preceded by an unescaped asterisk following
+whitespace, or the end of the input if there is no such character.
+Thus, all @code{<} and @code{>} redirections occuring before the next
+asterisk-unprefixed @code{|} are implicitly prefixed with (whitespace
+and) asterisks. An exception is that Eshell-specific redirects right
+at the end of the command are excluded. This allows input like this:
+
+@example
+ foo *| baz >#<buffer quux>
+@end example
+
+@noindent which is equivalent to input like this:
+
+@example
+ sh -c "foo | baz" >#<buffer quux>
+@end example
+
@node Extension modules
@chapter Extension modules
Eshell provides a facility for defining extension modules so that they
@@ -1045,6 +1633,7 @@ Eshell module.} You also need to load the following as shown:
* Key rebinding::
* Smart scrolling::
* Terminal emulation::
+* Electric forward slash::
@end menu
@node Writing a module
@@ -1077,6 +1666,61 @@ This section is not yet written.
This section is not yet written.
+@node Electric forward slash
+@section Electric forward slash
+
+To help with supplying absolute file name arguments to remote
+commands, you can add the @code{eshell-elecslash} module to
+@code{eshell-modules-list}. Then, typing @kbd{/} as the first
+character of a command line argument will automatically insert the
+Tramp prefix @file{/method:host:}. If this is not what you want
+(e.g.@: because you want to refer to a local file), you can type
+another @kbd{/} to undo the automatic insertion. Typing @kbd{~/} also
+inserts the Tramp prefix. The automatic insertion applies only when
+@code{default-directory} is remote and the command is a Lisp function.
+In particular, typing arguments to external commands doesn't insert
+the prefix.
+
+The result is that in most cases of supplying absolute file name
+arguments to commands you should see the Tramp prefix inserted
+automatically only when that's what you'd reasonably expect. This
+frees you from having to keep track of whether commands are Lisp
+functions or external when typing command line arguments. For
+example, suppose you execute
+
+@example
+ cd /ssh:root@@example.com:
+ find /etc -name "*gnu*"
+@end example
+
+@noindent and in reviewing the output of the command, you identify a
+file @file{/etc/gnugnu} that should be moved somewhere else. So you
+type
+
+@example
+ mv /etc/gnugnu /tmp
+@end example
+
+@noindent But since @command{mv} refers to the local Lisp function
+@code{eshell/mv}, not a remote shell command, to say this is to
+request that the local file @file{/etc/gnugnu} be moved into the local
+@file{/tmp} directory. After you add @code{eshell-elecslash} to
+@code{eshell-modules-list}, then when you type the above @command{mv}
+invocation you will get the following input, which is what you
+intended:
+
+@example
+ mv /ssh:root@@example.com:/etc/gnugnu /ssh:root@@example.com:/tmp
+@end example
+
+The code that determines whether or not the Tramp prefix should be
+inserted uses simple heuristics. A limitation of the current
+implementation is that it inspects whether only the command at the
+very beginning of input is a Lisp function or external program. Thus
+when chaining commands with the operators @code{&&}, @code{||},
+@code{|} and @code{;}, the electric forward slash is active only
+within the first command.
+
@node Bugs and ideas
@chapter Bugs and ideas
@cindex reporting bugs and ideas
@@ -1114,14 +1758,6 @@ alias arg=blah
function arg () @{ blah $* @}
@end example
-@item @samp{for i in 1 2 3 @{ grep -q a b && *echo has it @} | wc -l} outputs result after prompt
-
-In fact, piping to a process from a looping construct doesn't work in
-general. If I change the call to @code{eshell-copy-handles} in
-@code{eshell-rewrite-for-command} to use @code{eshell-protect}, it seems
-to work, but the output occurs after the prompt is displayed. The whole
-structured command thing is too complicated at present.
-
@item Pcomplete sometimes gets stuck
You press @key{TAB}, but no completions appear, even though the
@@ -1266,11 +1902,6 @@ glob match.
At the moment, this is not supported.
-@item Error if a glob doesn't expand due to a predicate
-
-An error should be generated only if @code{eshell-error-if-no-glob} is
-non-@code{nil}.
-
@item @samp{(+ @key{RET} @key{SPC} @key{TAB}} does not cause @code{indent-according-to-mode} to occur
@item Create @code{eshell-auto-accumulate-list}
@@ -1480,11 +2111,12 @@ only. That way, it could be listed as a login shell.
@item The first keypress after @kbd{M-x watson} triggers
@code{eshell-send-input}
-@item Make @kbd{/} electric
+@item Make @kbd{/} more electric
-So that it automatically expands and corrects pathnames. Or make
-pathname completion for Pcomplete auto-expand @samp{/u/i/std@key{TAB}} to
-@samp{/usr/include/std@key{TAB}}.
+@noindent so that it automatically expands and corrects file names,
+beyond what the @code{em-elecslash} module is able to do. Or make
+file name completion for Pcomplete auto-expand
+@samp{/u/i/std@key{TAB}} to @samp{/usr/include/std@key{TAB}}.
@item Write the @command{pushd} stack to disk along with @code{last-dir-ring}
diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index e9cf4cfade9..7fd5add67ea 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -192,9 +192,9 @@ email composition buffers (@pxref{Inline Query Expansion})
@lisp
(with-eval-after-load "message"
- (define-key message-mode-map [(control ?c) (tab)] 'eudc-expand-inline))
+ (define-key message-mode-map [(control ?c) (tab)] 'eudc-expand-try-all))
(with-eval-after-load "sendmail"
- (define-key mail-mode-map [(control ?c) (tab)] 'eudc-expand-inline))
+ (define-key mail-mode-map [(control ?c) (tab)] 'eudc-expand-try-all))
@end lisp
@menu
@@ -254,7 +254,9 @@ To: * Smith
@noindent
will return all LDAP entries with surnames that begin with
@code{Smith}. In every LDAP query it makes, EUDC implicitly appends
-the wildcard character to the end of the last word.
+the wildcard character to the end of the last word, except if the word
+corresponds to an attribute which is a member of
+`eudc-ldap-no-wildcard-attributes'.
@menu
* Emacs-only Configuration:: Configure with @file{.emacs}
@@ -281,19 +283,20 @@ LDAP:
@vindex message-mode-map
@findex eudc-expand-inline
+@findex eudc-expand-try-all
@vindex eudc-server-hotlist
@vindex ldap-host-parameters-alist
@lisp
(with-eval-after-load "message"
- (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline))
-(customize-set-variable 'eudc-server-hotlist
- '(("" . bbdb)
- ("ldaps://ldap.gnu.org" . ldap)))
-(customize-set-variable 'ldap-host-parameters-alist
- '(("ldaps://ldap.gnu.org"
- base "ou=people,dc=gnu,dc=org"
- binddn "gnu\\emacsuser"
- passwd ldap-password-read)))
+ (define-key message-mode-map (kbd "TAB") 'eudc-expand-try-all))
+(setopt eudc-server-hotlist
+ '(("" . bbdb)
+ ("ldaps://ldap.gnu.org" . ldap)))
+(setopt 'ldap-host-parameters-alist
+ '(("ldaps://ldap.gnu.org"
+ base "ou=people,dc=gnu,dc=org"
+ binddn "gnu\\emacsuser"
+ passwd ldap-password-read)))
@end lisp
@findex ldap-password-read
@@ -337,17 +340,18 @@ configure EUDC for LDAP:
@vindex message-mode-map
@findex eudc-expand-inline
+@findex eudc-expand-try-all
@vindex eudc-server-hotlist
@vindex ldap-host-parameters-alist
@lisp
(with-eval-after-load "message"
- (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline))
-(customize-set-variable 'eudc-server-hotlist
- '(("" . bbdb)
- ("ldaps://ldap.gnu.org" . ldap)))
-(customize-set-variable 'ldap-host-parameters-alist
- '(("ldaps://ldap.gnu.org"
- auth-source t)))
+ (define-key message-mode-map (kbd "TAB") 'eudc-expand-try-all))
+(setopt 'eudc-server-hotlist
+ '(("" . bbdb)
+ ("ldaps://ldap.gnu.org" . ldap)))
+(setopt 'ldap-host-parameters-alist
+ '(("ldaps://ldap.gnu.org"
+ auth-source t)))
@end lisp
For this example where we only care about one server, the server name
@@ -366,15 +370,16 @@ and the @file{.emacs} expressions become:
@vindex message-mode-map
@findex eudc-expand-inline
+@findex eudc-expand-try-all
@vindex eudc-server-hotlist
@vindex ldap-host-parameters-alist
@lisp
(with-eval-after-load "message"
- (define-key message-mode-map (kbd "TAB") 'eudc-expand-inline))
-(customize-set-variable 'eudc-server-hotlist
- '(("" . bbdb) ("" . ldap)))
-(customize-set-variable 'ldap-host-parameters-alist
- '(("" auth-source t)))
+ (define-key message-mode-map (kbd "TAB") 'eudc-expand-try-all))
+(setopt 'eudc-server-hotlist
+ '(("" . bbdb) ("" . ldap)))
+(setopt 'ldap-host-parameters-alist
+ '(("" auth-source t)))
@end lisp
@node Troubleshooting
@@ -708,32 +713,49 @@ be passed to the program.
@node Inline Query Expansion
@section Inline Query Expansion
-
-Inline query expansion is a powerful method to get completion from your
-directory server. The most common usage is for expanding names to email
-addresses in mail message buffers. The expansion is performed by the
-command @kbd{M-x eudc-expand-inline} which is available from the
-@samp{Expand Inline Query} menu item but can also be conveniently
-bound to a key shortcut (@pxref{Installation}). The operation is
-controlled by the variables @code{eudc-inline-expansion-format},
-@code{eudc-inline-query-format},
+@subsection Inline Query Expansion Using a Key Binding
+
+Inline query expansion is a powerful method to get completion from
+your directory servers. The most common usage is for expanding names
+to email addresses in mail message buffers. The expansion is
+performed by the command @kbd{M-x eudc-expand-try-all} which is
+available from the @samp{Expand Inline Query Trying All Servers} menu
+item but can also be conveniently bound to a key shortcut
+(@pxref{Installation}). The operation is controlled by the variables
+@code{eudc-inline-expansion-format}, @code{eudc-inline-query-format},
@code{eudc-expanding-overwrites-query} and
@code{eudc-multiple-match-handling-method}.
-If the query fails for a server, other servers may be tried successively
-until one of them finds a match (@pxref{Multi-server Queries}).
+If the query fails for a server, other servers may be tried
+successively until one of them finds a match (@pxref{Multi-server
+Queries}), or all servers can be tried and all matches returned.
+
+@deffn Command eudc-expand-try-all try-all-servers-p
+Query some or all servers and expand the query string before point.
+The query string consists of the buffer substring from the point back
+to the preceding comma, colon or beginning of line.
+@code{eudc-inline-query-format} controls how individual words are
+mapped onto directory attribute names. After querying the server or
+servers for the given string, the expansion specified by
+@code{eudc-inline-expansion-format} is inserted in the buffer at
+point. If multiple matches are available, a selection window is
+displayed. If @var{try-all-servers-p} is non-@code{nil} then all
+servers are queried.
+@end deffn
-@deffn Command eudc-expand-inline replace-p
+@deffn Command eudc-expand-inline save-query-as-kill-p
Query the server and expand the query string before point. The query
string consists of the buffer substring from the point back to the
-preceding comma, colon or beginning of
-line. @code{eudc-inline-query-format} controls how individual words
-are mapped onto directory attribute names. After querying the server
-for the given string, the expansion specified by
+preceding comma, colon or beginning of line.
+@code{eudc-inline-query-format} controls how individual words are
+mapped onto directory attribute names. After querying the server for
+the given string, the expansion specified by
@code{eudc-inline-expansion-format} is inserted in the buffer at
-point. If @var{replace-p} is @code{t} then this expansion replaces the
-query string in the buffer. If @code{eudc-expanding-overwrites-query}
-is non-@code{nil} then the meaning of @var{replace-p} is negated.
+point. If multiple matches are available, a selection window is
+displayed. If @var{save-query-as-kill-p} is @code{t} then the query
+string is saved to the kill ring. If
+@code{eudc-expansion-save-query-as-kill} is non-@code{nil} then the
+meaning of @var{save-query-as-kill-p} is negated.
@end deffn
@defvar eudc-inline-query-format
@@ -776,12 +798,73 @@ against the @code{cn} attribute of LDAP servers:
@end defvar
@defvar eudc-inline-expansion-format
-This variable lets you control exactly what is inserted into the buffer
-upon an inline expansion request. It is a list whose first element is a
-string passed to @code{format}. Remaining elements are symbols
-corresponding to directory attribute names. The corresponding attribute
-values are passed as additional arguments to @code{format}. Default is
-@code{("%s %s <%s>" firstname name email)}.
+This variable lets you control exactly what is inserted into the
+buffer upon an inline expansion request. It can be set to @code{nil},
+to a function, or to a list. Default is @code{nil}.
+
+When the value is a list, the first element is a string passed to
+@code{format}. Remaining elements are symbols corresponding to
+directory attribute names. The corresponding attribute values are
+passed as additional arguments to @code{format}.
+
+When the value is @code{nil}, the expansion result will be formatted
+according to @url{https://datatracker.ietf.org/doc/html/rfc5322, RFC
+5322}. The @var{phrase} part will be formatted as ``firstname name'',
+quoting the result if necessary. No @var{comment} part will be added
+in this case. This will produce any of the default formats
+@center @var{address}
+@center @var{first} @code{<}@var{address}@code{>}
+@center @var{last} @code{<}@var{address}@code{>}
+@center @var{first} @var{last} @code{<}@var{address}@code{>}
+depending on whether a first and/or last name are returned by the
+query, or not.
+
+When the value is a function, the expansion result will be formatted
+according to @url{https://datatracker.ietf.org/doc/html/rfc5322, RFC
+5322}, and the referenced function is called to format the
+@var{phrase}, and @var{comment} parts, respectively. The formatted
+@var{phrase} part will be quoted if necessary. Thus one can produce
+any of the formats:
+@center @var{address}
+@center @var{phrase} @code{<}@var{address}@code{>}
+@center @var{address} @code{(}@var{comment}@code{)}
+@center @var{phrase} @code{<}@var{address}@code{>} @code{(}@var{comment}@code{)}
+
+Email address specifications, as are generated by inline expansion,
+need to comply with RFC 5322 in order to be useful in email
+messages. When an invalid address specification is present in an email
+message header, the message is likely to be rejected by a receiving
+MTA. It is hence recommended to switch old configurations, which use
+a list value, to the new @code{nil}, or function value type since it
+ensures that the inserted address specifications will be in line with
+@url{https://datatracker.ietf.org/doc/html/rfc5322, RFC 5322}. At
+minimum, and to achieve the same semantics as with the old list
+default value, this variable should now be set to @code{nil}:
+@lisp
+(customize-set-variable 'eudc-inline-expansion-format nil)
+@end lisp
+
+A function value can for example be used to get @emph{``last, first
+<address>''} instead of the default @emph{``first last <address>''}:
+@lisp
+(defun my-phrase-last-comma-first (search-res-alist)
+ (let* (phrase
+ (my-attrs (eudc-translate-attribute-list '(firstname name)))
+ (first-name (cdr (assq (nth 0 my-attrs) search-res-alist)))
+ (last-name (cdr (assq (nth 1 my-attrs) search-res-alist)))
+ (comment nil))
+ (setq phrase (concat last-name ", " first-name))
+ (cons phrase comment)))
+
+(customize-set-variable 'eudc-inline-expansion-format
+ #'my-phrase-last-comma-first)
+@end lisp
+To set the @var{comment} part, too, instead of @code{nil} as in this
+example, also provide a string as the @code{cdr} of the @code{cons}
+being returned. Do not include any double quotes in the @var{phrase}
+part, as they are added automatically if needed. Neither include
+parentheses in the @var{comment} part as they, too, are added
+automatically.
@end defvar
@defvar eudc-multiple-match-handling-method
@@ -803,6 +886,29 @@ An error is signaled. The expansion aborts.
Default is @code{select}
@end defvar
+@subsection Inline Query Expansion Using completion-at-point
+
+In addition to providing a dedicated EUDC function for binding to a
+key shortcut (@pxref{Inline Query Expansion}), EUDC also provides a
+function to contribute search results to the Emacs in-buffer
+completion system available via the function
+@code{completion-at-point} (@pxref{Identifier
+Inquiries,,,maintaining}) in @code{message-mode} buffers
+(@pxref{Top,Message,, message, Message}). When using this mechanism,
+queries are made in the multi-server query mode of operation
+(@pxref{Multi-server Queries}).
+
+When a buffer in @code{message-mode} is created, EUDC's inline
+expansion function is automatically added to the variable
+@code{completion-at-point-functions}. As a result, whenever
+@code{completion-at-point} is invoked in a @code{message-mode} buffer,
+EUDC will be queried for email addresses matching the words before
+point. Since this will be useful only when editing specific message
+header fields that require specifying one or more email addresses, an
+additional check is performed whether point is actually in one of
+those header fields. Thus, any matching email addresses will be
+offered for completion in suitable message header fields only, and not
+in other places, like for example the body of the message.
@node The Server Hotlist
diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index 6d1ba3962f3..1060cd805ab 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -69,7 +69,7 @@ Indices
@chapter Overview
@dfn{EWW}, the Emacs Web Wowser, is a web browser for GNU Emacs. It
can load, parse, and display various web pages using @dfn{shr.el}.
-However a GNU Emacs with @code{libxml2} support is required.
+However, a GNU Emacs with @code{libxml2} support is required.
@node Basics
@chapter Basic Usage
@@ -213,7 +213,7 @@ switch EWW buffers through a minibuffer prompt, press @kbd{s}
@cindex External Browser
Although EWW and shr.el do their best to render webpages in GNU
Emacs some websites use features which can not be properly represented
-or are not implemented (E.g., JavaScript). If you have trouble
+or are not implemented (e.g., JavaScript). If you have trouble
viewing a website with EWW then hit @kbd{&}
(@code{eww-browse-with-external-browser}) inside the EWW buffer to
open the website in the external browser specified by
@@ -311,11 +311,9 @@ state the directionality.
size or content. By customizing @code{shr-max-image-proportion} you
can set the maximal image proportion in relation to the window they
are displayed in. E.g., 0.7 means an image is allowed to take up 70%
-of the width and height. If Emacs supports image scaling (ImageMagick
-support required) then larger images are scaled down. You can block
-specific images completely by customizing @code{shr-blocked-images},
-or, if you want to only allow some specific images, customize
-@code{shr-allowed-images}.
+of the width and height. If Emacs supports image scaling, then larger
+images are scaled down. You can block specific images completely by
+customizing @code{shr-blocked-images}.
@vindex shr-inhibit-images
You can control image display by customizing
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index 0db02608dd2..953e4605e98 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -265,6 +265,9 @@ This section summarizes customization variables used for the
configuration of the Flymake user interface.
@vtable @code
+@item flymake-mode-line-lighter
+The name of the mode. Defaults to @samp{Flymake}.
+
@item flymake-mode-line-format
Format to use for the Flymake mode line indicator.
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index 14a8c4c12d6..4923efb3dbe 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -100,10 +100,9 @@ misprints are the Gnus team's fault, sorry.
* FAQ 1-1:: What is the latest version of Gnus?
* FAQ 1-2:: What's new in 5.10?
* FAQ 1-3:: Where and how to get Gnus?
-* FAQ 1-4:: What to do with the tarball now?
-* FAQ 1-5:: I sometimes read references to No Gnus and Oort Gnus,
+* FAQ 1-4:: I sometimes read references to No Gnus and Oort Gnus,
what are those?
-* FAQ 1-6:: Which version of Emacs do I need?
+* FAQ 1-5:: Which version of Emacs do I need?
@end menu
@node FAQ 1-1
@@ -165,34 +164,6 @@ Gnus is bundled with Emacs.
@node FAQ 1-4
@subsubheading Question 1.4
-What to do with the tarball now?
-
-@subsubheading Answer
-
-Untar it via @samp{tar xvzf gnus.tar.gz} and do the common
-@samp{./configure; make; make install} circle.
-(under MS-Windows either get the Cygwin environment from
-@uref{https://www.cygwin.com}
-which allows you to do what's described above or unpack the
-tarball with some packer (e.g., Winace)
-and use the batch-file make.bat included in the tarball to install
-Gnus.) If you don't want to (or aren't allowed to) install Gnus
-system-wide, you can install it in your home directory and add the
-following lines to your ~/.emacs:
-
-@example
-(add-to-list 'load-path "/path/to/gnus/lisp")
-(add-to-list 'Info-default-directory-list "/path/to/gnus/texi/")
-@end example
-@noindent
-
-Make sure that you don't have any Gnus related stuff
-before this line, on MS Windows use something like
-"C:/path/to/lisp" (yes, "/").
-
-@node FAQ 1-5
-@subsubheading Question 1.5
-
I sometimes read references to No Gnus and Oort Gnus,
what are those?
@@ -205,8 +176,8 @@ once become Gnus 5.12 or Gnus 6. (If you're wondering why
not 5.11, the odd version numbers are normally used for
the Gnus versions bundled with Emacs)
-@node FAQ 1-6
-@subsubheading Question 1.6
+@node FAQ 1-5
+@subsubheading Question 1.5
Which version of Emacs do I need?
@@ -653,8 +624,7 @@ about the server there.
(add-to-list 'gnus-secondary-select-methods
'(nnimap "Give the baby a name"
(nnimap-address "imap.yourProvider.net")
- (nnimap-port 143)
- (nnimap-list-pattern "archive.*")))
+ (nnimap-port 143)))
@end example
@noindent
@@ -2193,18 +2163,9 @@ How to speed up the process of entering a group?
A speed killer is setting the variable
gnus-fetch-old-headers to anything different from @code{nil},
-so don't do this if speed is an issue. To speed up
-building of summary say
-
-@example
-(gnus-compile)
-@end example
-@noindent
+so don't do this if speed is an issue.
-at the bottom of your @file{~/.gnus.el}, this will make gnus
-byte-compile things like
-gnus-summary-line-format.
-then you could increase the value of gc-cons-threshold
+You could increase the value of gc-cons-threshold
by saying something like
@example
@@ -2212,21 +2173,7 @@ by saying something like
@end example
@noindent
-in ~/.emacs. If you don't care about width of CJK
-characters or use Gnus 5.10 or younger together with a
-recent GNU Emacs, you should say
-
-@example
-(setq gnus-use-correct-string-widths nil)
-@end example
-@noindent
-
-in @file{~/.gnus.el} (thanks to Jesper harder for the last
-two suggestions). Finally if you are still using 5.8.8
-or 5.9 and experience speed problems with summary
-buffer generation, you definitely should update to
-5.10 since there quite some work on improving it has
-been done.
+in ~/.emacs.
@node FAQ 9-3
@subsubheading Question 9.3
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 61870311ed8..a0be13dac88 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -12223,7 +12223,6 @@ controlling variable is a predicate list, as described above.
@vindex gnus-treat-highlight-citation
@vindex gnus-treat-highlight-headers
@vindex gnus-treat-highlight-signature
-@vindex gnus-treat-play-sounds
@vindex gnus-treat-x-pgp-sig
@vindex gnus-treat-unfold-headers
@vindex gnus-treat-fold-headers
@@ -12359,8 +12358,6 @@ is controlled by @code{gnus-body-boundary-delimiter}.
@xref{Article Highlighting}.
-@vindex gnus-treat-play-sounds
-@item gnus-treat-play-sounds
@item gnus-treat-ansi-sequences (t)
@vindex gnus-treat-x-pgp-sig
@item gnus-treat-x-pgp-sig (head)
@@ -14841,12 +14838,17 @@ mail belongs in that group.
The last of these groups should always be a general one, and the regular
expression should @emph{always} be @samp{""} so that it matches any mails
that haven't been matched by any of the other regexps. (These rules are
-processed from the beginning of the alist toward the end. The first rule
-to make a match will ``win'', unless you have crossposting enabled. In
-that case, all matching rules will ``win''.) If no rule matched, the mail
-will end up in the @samp{bogus} group. When new groups are created by
-splitting mail, you may want to run @code{gnus-group-find-new-groups} to
-see the new groups. This also applies to the @samp{bogus} group.
+processed from the beginning of the alist toward the end.
+
+If multiple rules match (excluding the general @samp{""} group), mail
+is crossposted to all these groups. However, if
+@code{nnmail-crosspost} is set to @code{nil}, the first rule to make a
+match will ``win''.
+
+If no rule matched, the mail will end up in the @samp{bogus} group.
+When new groups are created by splitting mail, you may want to run
+@code{gnus-group-find-new-groups} to see the new groups. This also
+applies to the @samp{bogus} group.
If you like to tinker with this yourself, you can set this variable to a
function of your choice. This function will be called without any
@@ -18076,6 +18078,17 @@ parameter of @code{nnselect-rescan} will allow automatic refreshing.
A refresh can always be invoked manually through
@code{gnus-group-get-new-news-this-group}.
+By default a compressed version of the selection is stored (for
+permanent groups) along with other group information in the newsrc.
+For cases where this might be undesirable (for example if the
+selection is a very long list that doesn't compress well) a
+non-@code{nil} group parameter of @code{nnselect-always-regenerate}
+will prevent the list from being stored, and instead regenerate the
+list each time it is needed. If more flexibility is desired,
+@code{nnselect-get-artlist-override-function} and
+@code{nnselect-store-artlist-override-function} may be set to
+functions that get and store the list of articles.
+
Gnus includes engines for searching a variety of backends. While the
details of each search engine vary, the result of a search is always a
vector of the sort used by the nnselect method, and the results of
@@ -21638,6 +21651,9 @@ are:
@item
@code{gnus-search-namazu}
+
+@item
+@code{gnus-search-mu}
@end itemize
If you need more granularity, you can specify a search engine in the
@@ -21652,7 +21668,7 @@ buffer. That might look like:
(config-file "/home/user/.mail/.notmuch_config")))
@end example
-Search engines like notmuch, namazu and mairix are similar in
+Search engines like notmuch, namazu, mairix and mu are similar in
behavior: they use a local executable to create an index of a message
store, and run command line search queries against those messages,
and return a list of absolute file names of matching messages.
@@ -21672,7 +21688,9 @@ engine.
@item remove-prefix
The directory part to be removed from the filenames returned by the
search query. This absolute path should include everything up to the
-top level of the message store.
+top level of the message store. Note that this is the path to the
+location of the actual messages, not to the search engine's indexes
+(nor, in the case of Mairix, to its symlink directories).
@item switches
Additional command-line switches to be fed to the search program. The
@@ -21689,8 +21707,8 @@ The customization options are formed on the pattern
non-standard notmuch program, you might set
@code{gnus-search-notmuch-program} to @file{/usr/local/bin/notmuch}.
This would apply to all notmuch engines. The engines that use these
-options are: ``notmuch'', ``namazu'', ``mairix'', ``swish-e'' and
-``swish++''.
+options are: ``notmuch'', ``namazu'', ``mairix'', ``mu'', ``swish-e''
+and ``swish++''.
Alternately, the options can be set directly on your Gnus server
definitions, for instance, in the @code{nnmaildir} example above.
@@ -21731,6 +21749,12 @@ articles are drawn. If you want to create a @emph{persistent} group
that sticks around after exit from the summary buffer, you can call
@code{gnus-group-make-search-group} (bound to @kbd{G g}).
+Unlike persistent groups, ephemeral groups by default do not run
+articles through the expiry process on exiting. If you want expiry to
+happen in ephemeral search groups you can customize the variable
+@code{nnselect-allow-ephemeral-expiry}. In all cases the expiry
+process uses the underlying group's expiry parameters.
+
So you just performed a search whose results are so fabulous you
wished you had done a persistent search rather than an ephemeral one?
No problem; you can create such a group by calling
@@ -24137,37 +24161,19 @@ If you want to see them in the Cc and To fields, set:
@end lisp
-@subsubsection Toolbar
+@subsubsection Tool bar
@table @code
-@item gnus-use-toolbar
-@vindex gnus-use-toolbar
-This variable specifies the position to display the toolbar. If
-@code{nil}, don't display toolbars. If it is non-@code{nil}, it should
-be one of the symbols @code{default}, @code{top}, @code{bottom},
-@code{right}, and @code{left}. @code{default} means to use the default
-toolbar, the rest mean to display the toolbar on the place which those
-names show. The default is @code{default}.
-
-@item gnus-toolbar-thickness
-@vindex gnus-toolbar-thickness
-Cons of the height and the width specifying the thickness of a toolbar.
-The height is used for the toolbar displayed on the top or the bottom,
-the width is used for the toolbar displayed on the right or the left.
-The default is that of the default toolbar.
-
-@item gnus-group-toolbar
-@vindex gnus-group-toolbar
-The toolbar in the group buffer.
+@item gnus-group-tool-bar
+@vindex gnus-group-tool-bar
+Specifies the tool bar in the group buffer. It can be either a list
+or a symbol referring to a list.
-@item gnus-summary-toolbar
-@vindex gnus-summary-toolbar
-The toolbar in the summary buffer.
-
-@item gnus-summary-mail-toolbar
-@vindex gnus-summary-mail-toolbar
-The toolbar in the summary buffer of mail groups.
+@item gnus-summary-tool-bar
+@vindex gnus-summary-tool-bar
+Specifies the tool bar in the summary buffer. It can be either a list
+or a symbol referring to a list.
@end table
@@ -29679,10 +29685,9 @@ Gnus not to use @acronym{NOV}.
As the variables for the other back ends, there are
@code{nndiary-nov-is-evil}, @code{nndir-nov-is-evil},
-@code{nnfolder-nov-is-evil}, @code{nnimap-nov-is-evil},
-@code{nnml-nov-is-evil}, and @code{nnspool-nov-is-evil}. Note that a
-non-@code{nil} value for @code{gnus-nov-is-evil} overrides all those
-variables.
+@code{nnfolder-nov-is-evil}, @code{nnml-nov-is-evil}, and
+@code{nnspool-nov-is-evil}. Note that a non-@code{nil} value for
+@code{gnus-nov-is-evil} overrides all those variables.
@end table
diff --git a/doc/misc/info.texi b/doc/misc/info.texi
index 98e0dceb5a2..4db35ebf0fc 100644
--- a/doc/misc/info.texi
+++ b/doc/misc/info.texi
@@ -1083,7 +1083,9 @@ If you aren't sure which manual documents the topic you are looking
for, try the @kbd{M-x info-apropos} command in Emacs, or the @kbd{M-x
index-apropos} command in the stand-alone reader. It prompts for
a string and then looks up that string in all the indices of all the
-Info documents installed on your system.
+Info documents installed on your system. In Emacs, giving a prefix
+argument to the command will try to search for a regular expression
+instead of a string.
@node Go to node
@section @kbd{g} goes to a node by name
@@ -1191,8 +1193,9 @@ info-stnd, GNU Info}.
The list of directories to search for Info files. Each element is a
string (directory name) or @code{nil} (try default directory). If not
initialized Info uses the environment variable @env{INFOPATH} to
-initialize it, or @code{Info-default-directory-list} if there is no
-@env{INFOPATH} variable in the environment.
+initialize it, or @code{Info-default-directory-list} in addition to
+the value returned by the @code{Info--default-directory-list} function
+if there is no @env{INFOPATH} variable in the environment.
If you wish to customize the Info directory search list for both Emacs
Info and stand-alone Info, it is best to set the @env{INFOPATH}
diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org
index 35bc8853fd3..446bfaa422a 100644
--- a/doc/misc/modus-themes.org
+++ b/doc/misc/modus-themes.org
@@ -5,9 +5,9 @@
#+options: ':t toc:nil author:t email:t num:t
#+startup: content
-#+macro: stable-version 2.0.0
-#+macro: release-date 2021-12-24
-#+macro: development-version 2.1.0-dev
+#+macro: stable-version 2.4.0
+#+macro: release-date 2022-06-01
+#+macro: development-version 2.5.0-dev
#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
#+macro: space @@texinfo:@: @@
#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
@@ -15,7 +15,7 @@
#+texinfo_filename: modus-themes.info
#+texinfo_dir_category: Emacs misc features
#+texinfo_dir_title: Modus Themes: (modus-themes)
-#+texinfo_dir_desc: Highly accessible themes (WCAG AAA)
+#+texinfo_dir_desc: Elegant, highly legible and customizable themes
#+texinfo_header: @set MAINTAINERSITE @uref{https://protesilaos.com,maintainer webpage}
#+texinfo_header: @set MAINTAINER Protesilaos Stavrou
#+texinfo_header: @set MAINTAINEREMAIL @email{info@protesilaos.com}
@@ -34,6 +34,10 @@ explicitly marked as such.
Current development target is {{{development-version}}}.
++ Homepage: https://protesilaos.com/emacs/modus-themes.
++ Git repository: https://git.sr.ht/~protesilaos/modus-themes.
++ Mailing list: https://lists.sr.ht/~protesilaos/modus-themes.
+
#+toc: headlines 8 insert TOC here, with eight headline levels
* COPYING
@@ -42,7 +46,7 @@ Current development target is {{{development-version}}}.
:custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3
:end:
-Copyright (C) 2020-2022 Free Software Foundation, Inc.
+Copyright (C) 2020-2022 Free Software Foundation, Inc.
#+begin_quote
Permission is granted to copy, distribute and/or modify this document
@@ -165,14 +169,10 @@ The themes are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][
The ~modus-themes~ package is available from the GNU ELPA archive, which
is configured by default.
-Prior to querying any package archive, make sure to have updated the
-index, with {{{kbd(M-x package-refresh-contents)}}}. Then all you need to do
+Prior to querying any package archive, make sure to update the index,
+with {{{kbd(M-x package-refresh-contents)}}}. Then all you need to do
is type {{{kbd(M-x package-install)}}} and specify the ~modus-themes~.
-Note that older versions of the themes used to be distributed as
-standalone packages. This practice has been discontinued starting with
-version 1.0.0 of this project.
-
Once installed, the themes are ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
** Install on GNU/Linux
@@ -211,6 +211,34 @@ guix package -i emacs-modus-themes
They are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]].
+** Dealing with byte compilation errors
+:properties:
+:custom_id: h:e6268471-e847-4c9d-998f-49a83257b7f1
+:end:
+
+From time to time, we receive bug reports pertaining to errors with byte
+compilation. These seldom have to do with faulty code in the themes: it
+might be a shortcoming of =package.el=, some regression in the current
+development target of Emacs, a misconfiguration in an otherwise exotic
+setup, and the like.
+
+The common solution with a stable version of Emacs is to:
+
+1. Delete the =modus-themes= package.
+2. Close the current Emacs session.
+3. Install the =modus-themes= again.
+
+For those building Emacs directly from source, the solution may involve
+reverting to an earlier commit in emacs.git.
+
+At any rate, if you encounter such an issue please report it: we will
+either fix the bug on our end if it is truly ours, or help forward it to
+the relevant upstream maintainer. Whatever you do, please understand
+that a build failure does not mean we are necessarily doing something
+wrong.
+
+[[#h:6536c8d5-3f98-43ab-a787-b94120e735e8][Issues you can help with]].
+
* Enable and load
:properties:
:custom_id: h:3f3c3728-1b34-437d-9d0c-b110f5b161a9
@@ -222,16 +250,16 @@ They are now ready to be used: [[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable
#+cindex: Essential configuration
#+vindex: modus-themes-after-load-theme-hook
-Users of the built-in themes can load and automatically enable the theme
-of their preference by adding either form to their init file:
+Users of the built-in themes cannot ~require~ the package as usual
+because there is no package to speak of. Instead, things are simpler as
+all one needs is to load the theme of their preference by adding either
+form to their init file:
#+begin_src emacs-lisp
(load-theme 'modus-operandi) ; Light theme
(load-theme 'modus-vivendi) ; Dark theme
#+end_src
-This is all one needs.
-
Users of packaged variants of the themes must add a few more lines to
ensure that everything works as intended. First, one has to require the
main library before loading either theme:
@@ -260,24 +288,39 @@ a theme with either of the following expressions:
Changes to the available customization options must always be evaluated
before loading a theme ([[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization Options]]). An exception to this
norm is when using the various Custom interfaces or with commands like
-{{{kbd(M-x customize-set-variable)}}}, which automatically reload the theme by
-default ([[#h:9001527a-4e2c-43e0-98e8-3ef72d770639][Option for inhibiting theme reload]]). This is how a basic setup
-could look like:
+{{{kbd(M-x customize-set-variable)}}}, which can optionally
+automatically reload the theme ([[#h:9001527a-4e2c-43e0-98e8-3ef72d770639][Option for inhibiting theme reload]]).
+
+This is how a basic setup could look like:
#+begin_src emacs-lisp
+;;; For the built-in themes which cannot use `require':
+;; Add all your customizations prior to loading the themes
+(setq modus-themes-italic-constructs t
+ modus-themes-bold-constructs nil
+ modus-themes-region '(bg-only no-extend))
+
+;; Load the theme of your choice:
+(load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi)
+
+(define-key global-map (kbd "<f5>") #'modus-themes-toggle)
+
+
+
+;;; For packaged versions which must use `require':
(require 'modus-themes)
-;; Your customisations here. For example:
-(setq modus-themes-bold-constructs t
- modus-themes-mode-line '3d)
+;; Add all your customizations prior to loading the themes
+(setq modus-themes-italic-constructs t
+ modus-themes-bold-constructs nil
+ modus-themes-region '(bg-only no-extend))
-;; Load the theme files before enabling a theme (else you get an error).
+;; Load the theme files before enabling a theme
(modus-themes-load-themes)
-;; Enable the theme of your preference:
-(modus-themes-load-operandi)
+;; Load the theme of your choice:
+(modus-themes-load-operandi) ;; OR (modus-themes-load-vivendi)
-;; Optionally add a key binding for the toggle between the themes:
(define-key global-map (kbd "<f5>") #'modus-themes-toggle)
#+end_src
@@ -307,15 +350,30 @@ It is common for Emacs users to rely on ~use-package~ for declaring
package configurations in their setup. We use this as an example:
#+begin_src emacs-lisp
+;;; For the built-in themes which cannot use `require':
+(use-package emacs
+ :init
+ ;; Add all your customizations prior to loading the themes
+ (setq modus-themes-italic-constructs t
+ modus-themes-bold-constructs nil
+ modus-themes-region '(bg-only no-extend))
+ :config
+ ;; Load the theme of your choice:
+ (load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi)
+ :bind ("<f5>" . modus-themes-toggle)
+
+
+
+;;; For packaged versions which must use `require':
(use-package modus-themes
- :ensure ; omit this to use the built-in themes
+ :ensure
:init
;; Add all your customizations prior to loading the themes
(setq modus-themes-italic-constructs t
modus-themes-bold-constructs nil
modus-themes-region '(bg-only no-extend))
- ;; Load the theme files before enabling a theme (else you get an error).
+ ;; Load the theme files before enabling a theme
(modus-themes-load-themes)
:config
;; Load the theme of your choice:
@@ -326,6 +384,20 @@ package configurations in their setup. We use this as an example:
The same without ~use-package~:
#+begin_src emacs-lisp
+;;; For the built-in themes which cannot use `require':
+;; Add all your customizations prior to loading the themes
+(setq modus-themes-italic-constructs t
+ modus-themes-bold-constructs nil
+ modus-themes-region '(bg-only no-extend))
+
+;; Load the theme of your choice:
+(load-theme 'modus-operandi) ;; OR (load-theme 'modus-vivendi)
+
+(define-key global-map (kbd "<f5>") #'modus-themes-toggle)
+
+
+
+;;; For packaged versions which must use `require':
(require 'modus-themes)
;; Add all your customizations prior to loading the themes
@@ -372,9 +444,9 @@ it might appear to the unsuspecting user that the themes are somehow
broken whenever they try to assign a new value to a customization option
or some face.
-This "reset" that ~load-theme~ conducts does, however, come at the cost
-of being somewhat slower than ~enable-theme~. Users who have a stable
-setup and who seldom update their variables during a given Emacs
+This "reset" that ~load-theme~ brings about does, however, come at the
+cost of being somewhat slower than ~enable-theme~. Users who have a
+stable setup and who seldom update their variables during a given Emacs
session, are better off using something like this:
#+begin_src emacs-lisp
@@ -385,6 +457,8 @@ session, are better off using something like this:
(enable-theme 'modus-operandi) ;; OR (enable-theme 'modus-vivendi)
#+end_src
+[[#h:b40aca50-a3b2-4c43-be58-2c26fcd14237][Toggle themes without reloading them]].
+
[[#h:e979734c-a9e1-4373-9365-0f2cd36107b8][Sample configuration with and without use-package]].
With the above granted, other sections of the manual discuss how to
@@ -416,7 +490,7 @@ this manual.
modus-themes-bold-constructs nil
modus-themes-mixed-fonts nil
modus-themes-subtle-line-numbers nil
- modus-themes-intense-markup t
+ modus-themes-intense-mouseovers nil
modus-themes-deuteranopia t
modus-themes-tabs-accented t
modus-themes-variable-pitch-ui nil
@@ -432,8 +506,19 @@ this manual.
;; Options for `modus-themes-mode-line' are either nil, or a list
;; that can combine any of `3d' OR `moody', `borderless',
- ;; `accented', and a natural number for extra padding
- modus-themes-mode-line '(4 accented borderless)
+ ;; `accented', a natural number for extra padding (or a cons cell
+ ;; of padding and NATNUM), and a floating point for the height of
+ ;; the text relative to the base font size (or a cons cell of
+ ;; height and FLOAT)
+ modus-themes-mode-line '(accented borderless (padding . 4) (height . 0.9))
+
+ ;; Same as above:
+ ;; modus-themes-mode-line '(accented borderless 4 0.9)
+
+ ;; Options for `modus-themes-markup' are either nil, or a list
+ ;; that can combine any of `bold', `italic', `background',
+ ;; `intense'.
+ modus-themes-markup '(background italic)
;; Options for `modus-themes-syntax' are either nil (the default),
;; or a list of properties that may include any of those symbols:
@@ -456,14 +541,37 @@ this manual.
;; `bold', `italic', `background'
modus-themes-links '(neutral-underline background)
+ ;; Options for `modus-themes-box-buttons' are either nil (the
+ ;; default), or a list that can combine any of `flat', `accented',
+ ;; `faint', `variable-pitch', `underline', `all-buttons', the
+ ;; symbol of any font weight as listed in `modus-themes-weights',
+ ;; and a floating point number (e.g. 0.9) for the height of the
+ ;; button's text.
+ modus-themes-box-buttons '(variable-pitch flat faint 0.9)
+
;; Options for `modus-themes-prompts' are either nil (the
;; default), or a list of properties that may include any of those
;; symbols: `background', `bold', `gray', `intense', `italic'
modus-themes-prompts '(intense bold)
- modus-themes-completions 'moderate ; {nil,'moderate,'opinionated}
-
- modus-themes-mail-citations nil ; {nil,'faint,'monochrome}
+ ;; The `modus-themes-completions' is an alist that reads three
+ ;; keys: `matches', `selection', `popup'. Each accepts a nil
+ ;; value (or empty list) or a list of properties that can include
+ ;; any of the following (for WEIGHT read further below):
+ ;;
+ ;; `matches' - `background', `intense', `underline', `italic', WEIGHT
+ ;; `selection' - `accented', `intense', `underline', `italic', `text-also' WEIGHT
+ ;; `popup' - same as `selected'
+ ;; `t' - applies to any key not explicitly referenced (check docs)
+ ;;
+ ;; WEIGHT is a symbol such as `semibold', `light', or anything
+ ;; covered in `modus-themes-weights'. Bold is used in the absence
+ ;; of an explicit WEIGHT.
+ modus-themes-completions '((matches . (extrabold))
+ (selection . (semibold accented))
+ (popup . (accented intense)))
+
+ modus-themes-mail-citations nil ; {nil,'intense,'faint,'monochrome}
;; Options for `modus-themes-region' are either nil (the default),
;; or a list of properties that may include any of those symbols:
@@ -510,7 +618,7 @@ By default, customizing a theme-related user option through the Custom
interfaces or with {{{kbd(M-x customize-set-variable)}}} will not reload the
currently active Modus theme.
-Enable this behaviour by setting this variable to ~nil~.
+Enable this behavior by setting this variable to ~nil~.
Regardless of this option, the active theme must be reloaded for changes
to user options to take effect ([[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]).
@@ -711,7 +819,7 @@ possible options are ~org-variable-pitch~ and ~mixed-pitch~.
:properties:
:alt_title: Link styles
:description: Choose among several styles, with or without underline
-:custom_id: h:c119d7b2-fcd4-4e44-890e-5e25733d5e52
+:custom_id: h:5808be52-361a-4d18-88fd-90129d206f9b
:end:
#+vindex: modus-themes-links
@@ -780,6 +888,101 @@ controlled by ~x-use-underline-position-properties~,
~x-underline-at-descent-line~, ~underline-minimum-offset~. Please refer to
their documentation strings.
+** Option for box buttons
+:properties:
+:alt_title: Box buttons
+:description: Choose among several styles for buttons
+:custom_id: h:8b85f711-ff40-45b0-b7fc-4727503cd2ec
+:end:
+#+vindex: modus-themes-box-buttons
+
+Brief: Control the style of buttons in the Custom UI and related.
+
+Symbol: ~modus-themes-box-buttons~ (=choice= type, list of properties)
+
+Possible values are expressed as a list of properties (default is ~nil~ or
+an empty list). The list can include any of the following symbols:
+
++ ~flat~
++ ~accented~
++ ~faint~
++ ~variable-pitch~
++ ~underline~
++ A font weight, which must be supported by the underlying typeface:
+ - ~thin~
+ - ~ultralight~
+ - ~extralight~
+ - ~light~
+ - ~semilight~
+ - ~regular~
+ - ~medium~
+ - ~semibold~
+ - ~bold~
+ - ~heavy~
+ - ~extrabold~
+ - ~ultrabold~
++ A floating point as a height multiple of the default or a cons cell in
+ the form of =(height . FLOAT)=
++ ~all-buttons~
+
+The default (a nil value or an empty list) is a gray background combined
+with a pseudo three-dimensional effect.
+
+The ~flat~ property makes the button two dimensional.
+
+The ~accented~ property changes the background from gray to an accent
+color.
+
+The ~faint~ property reduces the overall coloration.
+
+The ~variable-pitch~ property applies a proportionately spaced typeface
+to the button~s text.
+
+[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]].
+
+The ~underline~ property draws a line below the affected text and
+removes whatever box effect. This is optimal when Emacs runs inside a
+terminal emulator ([[#h:fbb5e254-afd6-4313-bb05-93b3b4f67358][More accurate colors in terminal emulators]]). If
+~flat~ and ~underline~ are defined together, the latter takes
+precedence.
+
+The symbol of a weight attribute adjusts the font of the button
+accordingly, such as ~light~, ~semibold~, etc. Valid symbols are
+defined in the variable ~modus-themes-weights~.
+
+[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]].
+
+A number, expressed as a floating point (e.g. =0.9=), adjusts the height
+of the button's text to that many times the base font size. The default
+height is the same as =1.0=, though it need not be explicitly stated.
+Instead of a floating point, an acceptable value can be in the form of a
+cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is
+the given number.
+
+The ~all-buttons~ property extends the box button effect (or the
+aforementioned properties) to the faces of the generic widget library.
+By default, those do not look like the buttons of the Custom UI as they
+are ordinary text wrapped in square brackets.
+
+Combinations of any of those properties are expressed as a list,
+like in these examples:
+
+#+begin_src emacs-lisp
+(flat)
+(variable-pitch flat)
+(variable-pitch flat semibold 0.9)
+(variable-pitch flat semibold (height 0.9)) ; same as above
+(variable-pitch flat semibold (height . 0.9)) ; same as above
+#+end_src
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+#+begin_src emacs-lisp
+(setq modus-themes-box-buttons '(variable-pitch flat 0.9))
+#+end_src
+
** Option for command prompt styles
:properties:
:alt_title: Command prompts
@@ -859,7 +1062,10 @@ effect, color, and border visibility:
- ~moody~
+ ~accented~
+ ~borderless~
-+ A natural number > 1 for extra padding
++ A natural number > 1 for extra padding or a cons cell in the form of
+ ~(padding . NATNUM)~.
++ A floating point to set the height of the mode line's text. It can
+ also be a cons cell in the form of ~(height . FLOAT)~.
The default (a nil value or an empty list) is a two-dimensional
rectangle with a border around it. The active and the inactive mode
@@ -895,6 +1101,17 @@ bottom of the mode line, set ~x-underline-at-descent-line~ to non-nil
users on Emacs 29, the ~x-use-underline-position-properties~ variable must
also be set to nil.
+The padding can also be expressed as a cons cell in the form of
+=(padding . NATNUM)= or =(padding NATNUM)= where the key is constant and
+NATNUM is the desired natural number.
+
+A floating point applies an adjusted height to the mode line's text as a
+multiple of the main font size. The default rate is 1.0 and does not
+need to be specified. Apart from a floating point, the height may also
+be expressed as a cons cell in the form of =(height . FLOAT)= or
+=(height FLOAT)= where the key is constant and the FLOAT is the desired
+number.
+
Combinations of any of those properties are expressed as a list, like in
these examples:
@@ -904,6 +1121,15 @@ these examples:
(moody accented borderless)
#+end_src
+Same as above, using the padding and height as an example (these
+all yield the same result):
+
+#+begin_src emacs-lisp
+(accented borderless 4 0.9)
+(accented borderless (padding . 4) (height . 0.9))
+(accented borderless (padding 4) (height 0.9))
+#+end_src
+
The order in which the properties are set is not significant.
In user configuration files the form may look like this:
@@ -964,49 +1190,106 @@ Centaur tabs package.
** Option for completion framework aesthetics
:properties:
:alt_title: Completion UIs
-:description: Choose among standard, moderate, or opinionated looks
+:description: Choose among several styles for completion UIs
:custom_id: h:f1c20c02-7b34-4c35-9c65-99170efb2882
:end:
#+vindex: modus-themes-completions
Brief: Set the overall style of completion framework interfaces.
-Symbol: ~modus-themes-completions~ (=choice= type)
+Symbol: ~modus-themes-completions~ (=alist= type properties)
-Possible values:
+This affects Company, Corfu, Flx, Helm, Icomplete/Fido, Ido, Ivy, Mct,
+Orderless, Selectrum, Vertico. The value is an alist that takes the
+form of a =(key . properties)= combination. Here is a sample, followed
+by a description of the particularities:
-1. ~nil~ (default)
-2. ~moderate~
-3. ~opinionated~
-
-This is a special option that has different effects depending on the
-completion UI. The interfaces can be grouped in two categories, based
-on their default aesthetics: (i) those that only or mostly use
-foreground colors for their interaction model, and (ii) those that
-combine background and foreground values for some of their metaphors.
-The former category encompasses Icomplete, Ido, Selectrum, Vertico, as
-well as pattern matching styles like Orderless and Flx. The latter
-covers Helm and Ivy.
-
-A value of ~nil~ (the default) will simply respect the metaphors of each
-completion framework.
-
-Option ~moderate~ applies a combination of background and foreground that
-is fairly subtle. For Icomplete and friends this constitutes a
-departure from their default aesthetics, however the difference is
-small. While Helm, Ivy et al appear slightly different than their
-original looks, as they are toned down a bit.
-
-Option ~opinionated~ uses color combinations that refashion the completion
-UI. For the Icomplete camp this means that intense background and
-foreground combinations are used: in effect their looks emulate those of
-Helm, Ivy and co. in their original style. Whereas the other group of
-packages will revert to an even more nuanced aesthetic with some
-additional changes to the choice of hues.
-
-To appreciate the scope of this customization option, you should spend
-some time with every one of the ~nil~ (default), ~moderate~, and ~opinionated~
-possibilities.
+#+begin_src emacs-lisp
+(setq modus-themes-completions
+ '((matches . (extrabold background intense))
+ (selection . (semibold accented intense))
+ (popup . (accented))))
+#+end_src
+
+The ~matches~ key refers to the highlighted characters that correspond
+to the user's input. By default (nil or an empty list), they have a
+bold weight and a colored foreground. The list of properties may
+include any of the following symbols regardless of the order they may
+appear in:
+
+- ~background~ to add a background color;
+
+- ~intense~ to increase the overall coloration (also amplifies
+ the ~background~, if present);
+
+- ~underline~ to draw a line below the characters;
+
+- ~italic~ to use a slanted font (italic or oblique forms);
+
+- The symbol of a font weight attribute such as ~light~, ~semibold~, et
+ cetera. Valid symbols are defined in the ~modus-themes-weights~
+ variable. The absence of a weight means that bold will be used.
+
+The ~selection~ key applies to the current line or currently matched
+candidate, depending on the specifics of the User Interface. By default
+(nil or an empty list), it has a subtle gray background, a bold weight,
+and the base foreground value for the text. The list of properties it
+accepts is as follows (order is not significant):
+
+- ~accented~ to make the background colorful instead of gray;
+
+- ~text-also~ to apply extra color to the text of the selected line;
+
+- ~intense~ to increase the overall coloration;
+
+- ~underline~ to draw a line below the characters;
+
+- ~italic~ to use a slanted font (italic or oblique forms);
+
+- The symbol of a font weight attribute such as ~light~, ~semibold~, et
+ cetera. Valid symbols are defined in the ~modus-themes-weights~
+ variable. The absence of a weight means that bold will be used.
+
+The ~popup~ key takes the same values as ~selection~.
+
+Apart from specfying each key separately, a fallback list is accepted.
+This is only useful when the desired aesthetic is the same across all
+keys that are not explicitly referenced. For example, this:
+
+#+begin_src emacs-lisp
+(setq modus-themes-completions
+ '((t . (extrabold intense))))
+#+end_src
+
+Is the same as:
+
+#+begin_src emacs-lisp
+(setq modus-themes-completions
+ '((matches . (extrabold intense))
+ (selection . (extrabold intense))
+ (popup . (extrabold intense))))
+#+end_src
+
+In the case of the fallback, any property that does not apply to the
+corresponding key is simply ignored (~matches~ does not have ~accented~
+and ~text-also~, while ~selection~ and ~popup~ do not have
+~background~).
+
+A concise expression of those associations can be written as follows,
+where the ~car~ is always the key and the ~cdr~ is the list of
+properties (whatever order they may appear in):
+
+#+begin_src emacs-lisp
+(setq modus-themes-completions
+ '((matches extrabold background intense)
+ (selection semibold accented intense)
+ (popup accented)))
+#+end_src
+
+[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]].
+
+Also refer to the Orderless documentation for its intersection with
+Company (if you choose to use those in tandem).
** Option for mail citations
:properties:
@@ -1024,17 +1307,21 @@ Symbol: ~modus-themes-mail-citations~ (=choice= type)
Possible values:
1. ~nil~ (default)
-2. ~faint~
-3. ~monochrome~
+2. ~intense~
+3. ~faint~
+4. ~monochrome~
-By default, citations in email-related buffers apply contrasting hues to
-different levels of depth in cited text. The colors are fairly easy to
-tell apart.
+By default (a nil value) citations are styled with contrasting hues to
+denote their depth. Colors are easy to tell apart because they
+complement each other, but they otherwise are not very prominent.
-A value of ~faint~ makes all citation levels less intense, while retaining
-the default style of contrasting hues (albeit very subtle ones).
+Option ~intense~ is similar to the default in terms of using contrasting
+and complementary hues, but applies more saturated colors.
-Option ~monochrome~ turns all citations in to a uniform shade of gray.
+Option ~faint~ maintains the same color-based distinction between citation
+levels though the colors it uses have subtle differences between them.
+
+Option ~monochrome~ turns all quotes into a shade of gray.
Whatever the value assigned to this variable, citations in emails are
controlled by typographic elements or indentation, which the themes do
@@ -1220,29 +1507,83 @@ Instead they retain the primary background of the theme, blending with
the rest of the buffer. Foreground values for all relevant faces are
updated to accommodate this aesthetic.
-** Option for intense markup in Org and others
+** Option for mouseover effects
:properties:
-:alt_title: Intense markup
-:description: Toggle intense style for markup in Org and others
-:custom_id: h:9d9a4e64-99ac-4018-8f66-3051b9c43fd7
+:alt_title: Mouse hover effects
+:description: Toggle intense style for mouseover highlights
+:custom_id: h:9b869620-fcc5-4b5f-9ab8-225d73b7f22f
:end:
-#+vindex: modus-themes-intense-markup
+#+vindex: modus-themes-intense-mouseovers
-Brief: Toggle intense style for inline code and related markup.
+Brief: Toggle intense mouse hover effects.
-Symbol: ~modus-themes-intense-markup~ (=boolean= type)
+Symbol: ~modus-themes-intense-mouseovers~ (=boolean= type)
Possible value:
1. ~nil~ (default)
2. ~t~
-The default style for certain markup types like inline code and verbatim
-constructs in Org and related major modes is a subtle foreground color
-combined with a subtle background.
+By default all mouseover effects apply a highlight with a subtle colored
+background. When non-nil, these have a more pronounced effect.
+
+Note that this affects the generic ~highlight~ which, strictly speaking,
+is not limited to mouse usage.
+
+** Option for markup style in Org and others
+:properties:
+:alt_title: Markup
+:description: Choose style for markup in Org and others
+:custom_id: h:9d9a4e64-99ac-4018-8f66-3051b9c43fd7
+:end:
+#+vindex: modus-themes-markup
+
+Brief: Choose style of markup in Org, Markdown, and others (affects
+constructs such as Org's ==verbatim== and =~code~=).
+
+Symbol: ~modus-themes-markup~ (=boolean= type)
+
+Possible values are expressed as a list of properties (default is ~nil~ or
+an empty list). The list can include any of the following symbols:
+
+1. ~bold~
+2. ~italic~
+3. ~background~
+4. ~intense~
+
+The ~italic~ property applies a typographic slant (italics).
+
+The ~bold~ property applies a heavier typographic weight.
+
+[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]].
-With a non-nil value (~t~), these constructs will use a more prominent
-background and foreground color combination instead.
+The ~background~ property adds a background color. The background is a
+shade of gray, unless the ~intense~ property is also set.
+
+The ~intense~ property amplifies the existing coloration. When
+~background~ is used, the background color is enhanced as well and
+becomes tinted instead of being gray.
+
+Combinations of any of those properties are expressed as a list,
+like in these examples:
+
+#+begin_src emacs-lisp
+(bold)
+(bold italic)
+(bold italic intense)
+(bold italic intense background)
+#+end_src
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+#+begin_src emacs-lisp
+(setq modus-themes-markup '(bold italic))
+#+end_src
+
+Also check the variables ~org-hide-emphasis-markers~,
+~org-hide-macro-markers~.
** Option for parenthesis matching
:properties:
@@ -1387,6 +1728,8 @@ contrast threshold.
[[#h:e2aed9eb-5e1e-45ec-bbd7-bc4faeab3236][Diffs with only the foreground]].
+[[#h:b0b31802-0216-427e-b071-1a47adcfe608][Ediff without diff color-coding]].
+
** Option for org-mode block styles
:properties:
:alt_title: Org mode blocks
@@ -1405,20 +1748,28 @@ Possible values:
2. ~gray-background~ (value ~grayscale~ exists for backward compatibility)
3. ~tinted-background~ (value ~rainbow~ exists for backward compatibility)
-The default means that the block has no distinct background of its own
-and uses the one that applies to the rest of the buffer.
+Nil (the default) means that the block has no background of its own: it
+uses the one that applies to the rest of the buffer. In this case, the
+delimiter lines have a gray color for their text, making them look
+exactly like all other Org properties.
Option ~gray-background~ applies a subtle gray background to the block's
-contents. It also affects the begin and end lines of the block: their
-background extends to the edge of the window for Emacs version >= 27
-where the ~:extend~ keyword is recognized by ~set-face-attribute~ (this is
-contingent on the variable ~org-fontify-whole-block-delimiter-line~).
+contents. It also affects the begin and end lines of the block as they
+get another shade of gray as their background, which differentiates them
+from the contents of the block. All background colors extend to the
+edge of the window, giving the area a rectangular, "blocky"
+presentation.
Option ~tinted-background~ uses a slightly colored background for the
contents of the block. The exact color will depend on the programming
language and is controlled by the variable ~org-src-block-faces~ (refer to
the theme's source code for the current association list). For this to
-take effect, Org must be restarted with {{{kbd(M-x org-mode-restart)}}}.
+take effect, the Org buffer needs to be restarted with ~org-mode-restart~.
+In this scenario, it may be better to inhibit the extension of the
+delimiter lines' background to the edge of the window because Org does
+not provide a mechanism to update their colors depending on the contents
+of the block. Disable the extension of such backgrounds by setting
+~org-fontify-whole-block-delimiter-line~ to nil.
Code blocks use their major mode's colors only when the variable
~org-src-fontify-natively~ is non-nil. While quote/verse blocks require
@@ -1464,17 +1815,23 @@ come in the form of a list that can include either or both of those
properties:
- ~variable-pitch~ to use a proportionately spaced typeface;
+
- A number as a floating point (e.g. 1.5) to set the height of the text
to that many times the default font height. A float of 1.0 or the
- symbol ~no-scale~ have the same effect of making the font to the same
- height as the rest of the buffer. When neither a number nor ~no-scale~
- are present, the default is a small increase in height (a value of
- 1.15).
+ symbol ~no-scale~ have the same effect of making the font the same
+ height as the rest of the buffer. When neither a number nor
+ `no-scale' are present, the default is a small increase in height (a
+ value of 1.15).
+
+ Instead of a floating point, an acceptable value can be in the form of
+ a cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT
+ is the given number.
+
- The symbol of a weight attribute adjusts the font of the heading
- accordingly, such as ~light~, ~semibold~, etc. Valid symbols are defined
- in the internal variable ~modus-themes--heading-weights~. The absence
- of a weight means that bold will be used by virtue of inheriting the
- ~bold~ face.
+ accordingly, such as ~light~, ~semibold~, etc. Valid symbols are
+ defined in the variable ~modus-themes-weights~. The absence of a
+ weight means that bold will be used by virtue of inheriting the ~bold~
+ face.
[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]].
@@ -1499,16 +1856,24 @@ the following properties:
- ~grayscale~ to make weekdays use the main foreground color and
weekends a more subtle gray;
+
- ~workaholic~ to make weekdays and weekends look the same in
terms of color;
+
- ~bold-today~ to apply a bold typographic weight to the current
date;
+
- ~bold-all~ to render all date headings in a bold weight;
+
- ~underline-today~ applies an underline to the current date while
removing the background it has by default;
+
- A number as a floating point (e.g. 1.2) to set the height of the text
to that many times the default font height. The default is the same
- as the base font height (the equivalent of 1.0).
+ as the base font height (the equivalent of 1.0). Instead of a
+ floating point, an acceptable value can be in the form of a cons cell
+ like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is the given
+ number.
For example:
@@ -1594,10 +1959,10 @@ passed as a symbol. Those are:
being too late. The difference between ready and clear states is
attenuated by painting both of them using shades of green. This
option thus highlights the alert and overdue states.
-- When ~modus-themes-deuteranopia~ is non-nil the habit graph uses a
- three-color style like the aforementioned ~traffic-light~ variant,
- except that shades of blue are applied instead of green. This is
- suitable for users with red-green color deficiency (deuteranopia).
+- When ~modus-themes-deuteranopia~ is non-nil the exact style of the habit
+ graph adapts to the needs of users with red-green color deficiency by
+ substituting every instance of green with blue or cyan (depending on
+ the specifics).
[[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]].
@@ -1674,7 +2039,8 @@ Properties:
- ~extrabold~
- ~ultrabold~
+ ~no-bold~ (deprecated alias of a ~regular~ weight)
-+ A floating point as a height multiple of the default
++ A floating point as a height multiple of the default or a cons cell in
+ the form of =(height . FLOAT)=.
By default (a ~nil~ value for this variable), all headings have a bold
typographic weight and use a desaturated text color.
@@ -1695,10 +2061,10 @@ A ~variable-pitch~ property changes the font family of the heading to that
of the ~variable-pitch~ face (normally a proportionately spaced typeface).
The symbol of a weight attribute adjusts the font of the heading
-accordingly, such as ~light~, ~semibold~, etc. Valid symbols are defined in
-the internal variable ~modus-themes--heading-weights~. The absence of a
-weight means that bold will be used by virtue of inheriting the ~bold~
-face. For backward compatibility, the ~no-bold~ value is accepted, though
+accordingly, such as ~light~, ~semibold~, etc. Valid symbols are
+defined in the variable ~modus-themes-weights~. The absence of a weight
+means that bold will be used by virtue of inheriting the ~bold~ face.
+For backward compatibility, the ~no-bold~ value is accepted, though
users are encouraged to specify a ~regular~ weight instead.
[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]].
@@ -1706,6 +2072,9 @@ users are encouraged to specify a ~regular~ weight instead.
A number, expressed as a floating point (e.g. 1.5), adjusts the height
of the heading to that many times the base font size. The default
height is the same as 1.0, though it need not be explicitly stated.
+Instead of a floating point, an acceptable value can be in the form of a
+cons cell like =(height . FLOAT)= or =(height FLOAT)=, where FLOAT is
+the given number.
Combinations of any of those properties are expressed as a list, like in
these examples:
@@ -1714,6 +2083,8 @@ these examples:
(semibold)
(rainbow background)
(overline monochrome semibold 1.3)
+(overline monochrome semibold (height 1.3)) ; same as above
+(overline monochrome semibold (height . 1.3)) ; same as above
#+end_src
The order in which the properties are set is not significant.
@@ -1793,6 +2164,128 @@ their own local tweaks and who are willing to deal with any possible
incompatibilities between versioned releases of the themes. As such,
they are labelled as "do-it-yourself" or "DIY".
+** More accurate colors in terminal emulators
+:PROPERTIES:
+:CUSTOM_ID: h:fbb5e254-afd6-4313-bb05-93b3b4f67358
+:END:
+#+cindex: Color accuracy of terminal emulators
+
+[ This is based on partial information. Please help verify and/or
+ expand these findings. ]
+
+The graphical version of Emacs can reproduce color values accurately.
+Whereas things get more tricky when Emacs is used in a terminal
+emulator, because the terminals' own capabilities determine the number
+of colors that may be displayed: the Modus themes don't look as good in
+that case.
+
+There is, however, a way to instruct supported terminal emulators to use
+more accurate colors. In a shell prompt type =toe -a | grep direct= to
+get a list of relevant terminfo entries. There should be items such as
+=xterm-direct=, =alacritty-direct=, =kitty-direct=. Once you find the one
+that corresponds to your terminal, call Emacs with an environment
+variable like =TERM=xterm-direct=. Example that can be adapted to shell
+aliases:
+
+: TERM=xterm-direct emacsclient -nw
+
+Another example that can be bound to a key:
+
+: TERM=xterm-direct uxterm -e emacsclient -nw
+
+** Range of color with terminal emulators
+:PROPERTIES:
+:CUSTOM_ID: h:6b8211b0-d11b-4c00-9543-4685ec3b742f
+:END:
+#+cindex: Pure white and pure black in terminal emulators
+
+[ This is based on partial information. Please help verify and/or
+ expand these findings. ]
+
+When Emacs runs in a non-windowed session its color reproduction
+capacity is framed or determined by the underlying terminal emulator
+([[#h:fbb5e254-afd6-4313-bb05-93b3b4f67358][More accurate colors in terminal emulators]]). Emacs cannot produce a
+color that lies outside the range of what the terminal's color palette
+renders possible.
+
+This is immediately noticeable when the terminal's first 16 codes do not
+include a pure black value for the =termcol0= entry and a pure white for
+=termcol15=. Emacs cannot set the correct background (white for
+~modus-operandi~; black for ~modus-vivendi~) or foreground (inverse of
+the background). It thus falls back to the closest approximation, which
+seldom is appropriate for the purposes of the Modus themes.
+
+In such a case, the user is expected to update their terminal's color
+palette such as by adapting these resources:
+
+#+begin_src emacs-lisp
+! Theme: modus-operandi
+! Description: XTerm port of modus-operandi (Modus themes for GNU Emacs)
+! Author: Protesilaos Stavrou, <https://protesilaos.com>
+xterm*background: #ffffff
+xterm*foreground: #000000
+xterm*color0: #000000
+xterm*color1: #a60000
+xterm*color2: #005e00
+xterm*color3: #813e00
+xterm*color4: #0031a9
+xterm*color5: #721045
+xterm*color6: #00538b
+xterm*color7: #bfbfbf
+xterm*color8: #595959
+xterm*color9: #972500
+xterm*color10: #315b00
+xterm*color11: #70480f
+xterm*color12: #2544bb
+xterm*color13: #5317ac
+xterm*color14: #005a5f
+xterm*color15: #ffffff
+
+! Theme: modus-vivendi
+! Description: XTerm port of modus-vivendi (Modus themes for GNU Emacs)
+! Author: Protesilaos Stavrou, <https://protesilaos.com>
+xterm*background: #000000
+xterm*foreground: #ffffff
+xterm*color0: #000000
+xterm*color1: #ff8059
+xterm*color2: #44bc44
+xterm*color3: #d0bc00
+xterm*color4: #2fafff
+xterm*color5: #feacd0
+xterm*color6: #00d3d0
+xterm*color7: #bfbfbf
+xterm*color8: #595959
+xterm*color9: #ef8b50
+xterm*color10: #70b900
+xterm*color11: #c0c530
+xterm*color12: #79a8ff
+xterm*color13: #b6a0ff
+xterm*color14: #6ae4b9
+xterm*color15: #ffffff
+#+end_src
+
+** Visualize the active Modus theme's palette
+:properties:
+:custom_id: h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d
+:end:
+#+findex: modus-themes-list-colors
+#+findex: modus-themes-list-colors-current
+#+cindex: Preview color values
+
+The command ~modus-themes-list-colors~ prompts for a choice between
+=modus-operandi= and =modus-vivendi= to produce a help buffer that shows a
+preview of each variable in the given theme's color palette. The
+command ~modus-themes-list-colors-current~ skips the prompt, using the
+current Modus theme.
+
+Each row shows a foreground and background coloration using the
+underlying value it references. For example a line with =#a60000= (a
+shade of red) will show red text followed by a stripe with that same
+color as a backdrop.
+
+The name of the buffer describes the given Modus theme. It is thus
+called =*modus-operandi-list-colors*= or =*modus-vivendi-list-colors*=.
+
** Per-theme customization settings
:properties:
:custom_id: h:a897b302-8e10-4a26-beab-3caaee1e1193
@@ -1868,7 +2361,11 @@ The function always extracts the color value of the active Modus theme.
#+end_src
Do {{{kbd(C-h v)}}} on the aforementioned variables to check all the available
-symbols that can be passed to this function.
+symbols that can be passed to this function. Or simply invoke the
+command ~modus-themes-list-colors~ to produce a buffer with a preview of
+each entry in the palette.
+
+[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]].
With that granted, let us expand the example to actually change the
~cursor~ face's background property. We employ the built-in function of
@@ -1947,7 +2444,10 @@ The ~modus-themes-with-colors~ macro lets you retrieve multiple color
values by employing the backquote/backtick and comma notation. The
values are stored in the alists ~modus-themes-operandi-colors~ and
~modus-themes-vivendi-colors~, while the macro always queries that of the
-active Modus theme.
+active Modus theme (preview the current palette with the command
+~modus-themes-list-colors~).
+
+[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]].
Here is an abstract example that just returns a list of color values
while ~modus-operandi~ is enabled:
@@ -2124,7 +2624,7 @@ contrast on an on-demand basis.
One way to achieve this is to design a command that cycles through three
distinct levels of intensity, though the following can be adapted to any
-kind of cyclic behaviour, such as to switch between red, green, and
+kind of cyclic behavior, such as to switch between red, green, and
blue.
In the following example, we employ the ~modus-themes-color~ function
@@ -2285,9 +2785,11 @@ The themes provide a mechanism for overriding their color values. This
is controlled by the variables ~modus-themes-operandi-color-overrides~ and
~modus-themes-vivendi-color-overrides~, which are alists that should
mirror a subset of the associations in ~modus-themes-operandi-colors~ and
-~modus-themes-vivendi-colors~ respectively. As with all customisations,
+~modus-themes-vivendi-colors~ respectively. As with all customizations,
overriding must be done before loading the affected theme.
+[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]].
+
Let us approach the present topic one step at a time. Here is a
simplified excerpt of the default palette for Modus Operandi with some
basic background values that apply to buffers and the mode line
@@ -2348,8 +2850,7 @@ both themes and expands to some more assosiations in the palette:
(bg-header . "#ede3e0")
(bg-tab-bar . "#dcd3d3")
(bg-tab-active . "#fdf6eb")
- (bg-tab-inactive . "#c8bab8")
- (fg-unfocused . "#55556f"))
+ (bg-tab-inactive . "#c8bab8"))
modus-themes-vivendi-color-overrides
'((bg-main . "#100b17")
(bg-dim . "#161129")
@@ -2361,19 +2862,36 @@ both themes and expands to some more assosiations in the palette:
(bg-header . "#202037")
(bg-tab-bar . "#262b41")
(bg-tab-active . "#120f18")
- (bg-tab-inactive . "#3a3a5a")
- (fg-unfocused . "#9a9aab")))
+ (bg-tab-inactive . "#3a3a5a")))
(setq modus-themes-operandi-color-overrides nil
modus-themes-vivendi-color-overrides nil)))
#+end_src
-With this in place, one can invoke {{{kbd(M-x my-modus-themes-tinted)}}} and
-then load the Modus theme of their choice. The new palette subset will
-come into effect: subtle ochre tints for Modus Operandi and night sky
-shades for Modus Vivendi. Switching between the two themes, such as
-with {{{kbd(M-x modus-themes-toggle)}}} will also use the overrides.
+A more neutral style for ~modus-themes-operandi-color-overrides~ can
+look like this:
+
+#+begin_src emacs-lisp
+'((bg-main . "#f7f7f7")
+ (bg-dim . "#f2f2f2")
+ (bg-alt . "#e8e8e8")
+ (bg-hl-line . "#eaeaef")
+ (bg-active . "#e0e0e0")
+ (bg-inactive . "#e6e6e6")
+ (bg-region . "#b5b5b5")
+ (bg-header . "#e4e4e4")
+ (bg-tab-bar . "#d1d1d4")
+ (bg-tab-active . "#f5f5f5")
+ (bg-tab-inactive . "#c0c0c0"))
+#+end_src
+
+With those in place, one can use {{{kbd(M-x my-modus-themes-tinted)}}}
+and then load the Modus theme of their choice. The new palette subset
+will come into effect: subtle ochre tints (or shades of gray) for Modus
+Operandi and night sky blue shades for Modus Vivendi. Switching between
+the two themes, such as with {{{kbd(M-x modus-themes-toggle)}}} will
+also use the overrides.
-Given that this is a user-level customisation, one is free to implement
+Given that this is a user-level customization, one is free to implement
whatever color values they desire, even if the possible combinations
fall below the minimum 7:1 contrast ratio that governs the design of the
themes (the WCAG AAA legibility standard). Alternatively, this can also
@@ -2509,6 +3027,71 @@ inspiration from the ~modus-themes-toggle~ we already provide:
('modus-vivendi (modus-themes-load-vivendi))))
#+end_src
+** Override colors through blending
+:properties:
+:custom_id: h:80c326bf-fe32-47b2-8c59-58022256fd6e
+:end:
+#+cindex: Change theme colors through blending
+
+This is yet another method of overriding color values.
+
+[[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]].
+
+[[#h:4589acdc-2505-41fc-9f5e-699cfc45ab00][Override color saturation]].
+
+Building on ideas and concepts from the previous sections, this method
+blends the entire palette at once with the chosen colors. The function
+~my-modus-themes-interpolate~ blends two colors, taking a value from the
+themes and mixing it with a user-defined color to arrive at a midpoint.
+This scales to all background and foreground colors with the help of the
+~my-modus-themes-tint-palette~ function.
+
+#+begin_src emacs-lisp
+(setq my-modus-operandi-bg-blend "#fbf1c7"
+ my-modus-operandi-fg-blend "#3a6084"
+ my-modus-vivendi-bg-blend "#3a4042"
+ my-modus-vivendi-fg-blend "#d7b765")
+
+;; Adapted from the `kurecolor-interpolate' function of kurecolor.el
+(defun my-modus-themes-interpolate (color1 color2)
+ (cl-destructuring-bind (r g b)
+ (mapcar #'(lambda (n) (* (/ n 2) 255.0))
+ (cl-mapcar '+ (color-name-to-rgb color1) (color-name-to-rgb color2)))
+ (format "#%02X%02X%02X" r g b)))
+
+(defun my-modus-themes-tint-palette (palette bg-blend fg-blend)
+ "Modify Modus PALETTE programmatically and return a new palette.
+Blend background colors with BG-BLEND and foreground colors with FG-BLEND."
+ (let (name cons colors)
+ (dolist (cons palette)
+ (let ((blend (if (string-match "bg" (symbol-name (car cons)))
+ bg-blend
+ fg-blend)))
+ (setq name (my-modus-themes-interpolate (cdr cons) blend)))
+ (setq name (format "%s" name))
+ (setq cons `(,(car cons) . ,name))
+ (push cons colors))
+ colors))
+
+(define-minor-mode modus-themes-tinted-mode
+ "Tweak some Modus themes colors."
+ :init-value nil
+ :global t
+ (if modus-themes-tinted-mode
+ (setq modus-themes-operandi-color-overrides
+ (my-modus-themes-tint-palette modus-themes-operandi-colors
+ my-modus-operandi-bg-blend
+ my-modus-operandi-fg-blend)
+ modus-themes-vivendi-color-overrides
+ (my-modus-themes-tint-palette modus-themes-vivendi-colors
+ my-modus-vivendi-bg-blend
+ my-modus-vivendi-fg-blend))
+ (setq modus-themes-operandi-color-overrides nil
+ modus-themes-vivendi-color-overrides nil)))
+
+(modus-themes-tinted-mode 1)
+#+end_src
+
** Font configurations for Org and others
:properties:
:custom_id: h:defcf4fc-8fa8-4c29-b12e-7119582cc929
@@ -2670,11 +3253,11 @@ of the themes, which can make it easier to redefine faces in bulk).
[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]].
-** Custom Org user faces
+** Custom Org todo keyword and priority faces
:properties:
:custom_id: h:89f0678d-c5c3-4a57-a526-668b2bb2d7ad
:end:
-#+cindex: Org extra faces
+#+cindex: Org custom todo faces
Users of ~org-mode~ have the option to configure various keywords and
priority cookies to better match their workflow. User options are
@@ -2758,6 +3341,139 @@ it if you plan to control face attributes.
[[#h:02e25930-e71a-493d-828a-8907fc80f874][Check color combinations]].
+** Custom Org emphasis faces
+:properties:
+:custom_id: h:26026302-47f4-4471-9004-9665470e7029
+:end:
+#+cindex: Org custom emphasis faces
+
+Org provides the user option ~org-emphasis-alist~ which assosiates a
+character with a face, list of faces, or face attributes. The default
+specification of that variable looks like this:
+
+#+begin_src emacs-lisp
+(setq org-emphasis-alist
+ '(("*" bold)
+ ("/" italic)
+ ("_" underline)
+ ("=" org-verbatim verbatim)
+ ("~" org-code verbatim)
+ ("+" (:strike-through t))))
+#+end_src
+
+With the exception of ~org-verbatim~ and ~org-code~ faces, everything else
+uses the corresponding type of emphasis: a bold typographic weight, or
+italicised, underlined, and struck through text.
+
+The best way for users to add some extra attributes, such as a
+foreground color, is to define their own faces and assign them to the
+given emphasis marker/character.
+
+This is a custom face that extends the standard ~bold~ face with a red
+foreground value (so it colorises the text in addition to the bold
+weight):
+
+#+begin_src emacs-lisp
+(defface my-org-emphasis-bold
+ '((default :inherit bold)
+ (((class color) (min-colors 88) (background light))
+ :foreground "#a60000")
+ (((class color) (min-colors 88) (background dark))
+ :foreground "#ff8059"))
+ "My bold emphasis for Org.")
+#+end_src
+
+This face definition reads as follows:
+
++ Always inherit the ~bold~ face ([[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]).
++ For versions of Emacs that support at least 88 colors (graphical
+ Emacs, for example) and use a light background, apply the =#a60000=
+ value.
++ For the same kind of Emacs that has a dark background use the =#ff8059=
+ color instead.
+
+Same principle for how to extend ~italic~ and ~underline~ with, for example,
+green and yellow hues, respectively:
+
+#+begin_src emacs-lisp
+(defface my-org-emphasis-italic
+ '((default :inherit italic)
+ (((class color) (min-colors 88) (background light))
+ :foreground "#005e00")
+ (((class color) (min-colors 88) (background dark))
+ :foreground "#44bc44"))
+ "My italic emphasis for Org.")
+
+(defface my-org-emphasis-underline
+ '((default :inherit underline)
+ (((class color) (min-colors 88) (background light))
+ :foreground "#813e00")
+ (((class color) (min-colors 88) (background dark))
+ :foreground "#d0bc00"))
+ "My underline emphasis for Org.")
+#+end_src
+
+In the case of a strike-through effect, we have no generic face to
+inherit from, so we can write it as follows to also change the
+foreground to a more subtle gray:
+
+#+begin_src emacs-lisp
+(defface my-org-emphasis-strike-through
+ '((default :strike-through t)
+ (((class color) (min-colors 88) (background light))
+ :foreground "#505050")
+ (((class color) (min-colors 88) (background dark))
+ :foreground "#a8a8a8"))
+ "My strike-through emphasis for Org.")
+#+end_src
+
+Or we can just change the color of the line that strikes through the
+text to, for example, a shade of red:
+
+#+begin_src emacs-lisp
+(defface my-org-emphasis-strike-through
+ '((((class color) (min-colors 88) (background light))
+ :strike-through "#972500")
+ (((class color) (min-colors 88) (background dark))
+ :strike-through "#ef8b50"))
+ "My strike-through emphasis for Org.")
+#+end_src
+
+It is possible to combine those effects:
+
+#+begin_src emacs-lisp
+(defface my-org-emphasis-strike-through
+ '((((class color) (min-colors 88) (background light))
+ :strike-through "#972500" :foreground "#505050")
+ (((class color) (min-colors 88) (background dark))
+ :strike-through "#ef8b50" :foreground "#a8a8a8"))
+ "My strike-through emphasis for Org.")
+#+end_src
+
+One may inspect the variables ~modus-themes-operandi-colors~ and
+~modus-themes-vivendi-colors~ for possible color values. Or call the
+command ~modus-themes-list-colors~ to show a buffer that previews each
+entry in the palette.
+
+[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]].
+
+Once we have defined the faces we need, we must update the
+~org-emphasis-alist~. Given that ~org-verbatim~ and ~org-code~ are already
+styled by the themes, it probably is best not to edit them:
+
+#+begin_src emacs-lisp
+(setq org-emphasis-alist
+ '(("*" my-org-emphasis-bold)
+ ("/" my-org-emphasis-italic)
+ ("_" my-org-emphasis-underline)
+ ("=" org-verbatim verbatim)
+ ("~" org-code verbatim)
+ ("+" my-org-emphasis-strike-through)))
+#+end_src
+
+That's it! For changes to take effect in already visited Org files,
+invoke {{{kbd(M-x org-mode-restart)}}}.
+
** Update Org block delimiter fontification
:properties:
:custom_id: h:f44cc6e3-b0f1-4a5e-8a90-9e48fa557b50
@@ -2954,13 +3670,20 @@ at something like the following, which builds on the above example:
(pdf-view-midnight-minor-mode -1))
(my-pdf-tools-backdrop)))
+(defun my-pdf-tools-themes-toggle ()
+ (mapc
+ (lambda (buf)
+ (with-current-buffer buf
+ (my-pdf-tools-midnight-mode-toggle)))
+ (buffer-list)))
+
(add-hook 'pdf-tools-enabled-hook #'my-pdf-tools-midnight-mode-toggle)
-(add-hook 'modus-themes-after-load-theme-hook #'my-pdf-tools-midnight-mode-toggle)
+(add-hook 'modus-themes-after-load-theme-hook #'my-pdf-tools-themes-toggle)
#+end_src
With those in place, PDFs have a distinct backdrop for their page, while
-they automatically switch to their dark mode when ~modus-themes-toggle~ is
-called from inside a buffer whose major-mode is ~pdf-view-mode~.
+buffers with major-mode as ~pdf-view-mode~ automatically switches to dark
+mode when ~modus-themes-toggle~ is called.
** Decrease mode line height
:properties:
@@ -3057,6 +3780,35 @@ to be specified as well:
(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
#+end_src
+** Toggle themes without reloading them
+:properties:
+:custom_id: h:b40aca50-a3b2-4c43-be58-2c26fcd14237
+:end:
+#+cindex: Switch themes without load-theme
+
+Users who have a stable setup and who only ever need to toggle between
+the themes without triggering a full reload, are better off defining
+their own command which calls ~enable-theme~ instead of ~load-theme~:
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-toggle ()
+ "Toggle between `modus-operandi' and `modus-vivendi' themes.
+This uses `enable-theme' instead of the standard method of
+`load-theme'. The technicalities are covered in the Modus themes
+manual."
+ (interactive)
+ (pcase (modus-themes--current-theme)
+ ('modus-operandi (progn (enable-theme 'modus-vivendi)
+ (disable-theme 'modus-operandi)))
+ ('modus-vivendi (progn (enable-theme 'modus-operandi)
+ (disable-theme 'modus-vivendi)))
+ (_ (error "No Modus theme is loaded; evaluate `modus-themes-load-themes' first"))))
+#+end_src
+
+[[#h:e68560b3-7fb0-42bc-a151-e015948f8a35][Differences between loading and enabling]].
+
+Recall that ~modus-themes-toggle~ uses ~load-theme~.
+
** A theme-agnostic hook for theme loading
:properties:
:custom_id: h:86f6906b-f090-46cc-9816-1fe8aeb38776
@@ -3161,6 +3913,212 @@ This used to be an optional style of ~modus-themes-diffs~, but has been
removed since version =2.0.0= to ensure that the accessibility standard
and aesthetic quality of the themes is not compromised.
+** Ediff without diff color-coding
+:properties:
+:custom_id: h:b0b31802-0216-427e-b071-1a47adcfe608
+:end:
+
+Ediff uses the same color-coding as ordinary diffs in ~diff-mode~, Magit,
+etc. ([[#h:ea7ac54f-5827-49bd-b09f-62424b3b6427][Option for diff buffer looks]]). This is consistent with the
+principle of least surprise.
+
+Users may, however, prefer to treat Ediff differently on the premise
+that it does not need any particular color-coding to show added or
+removed lines/words: it does not use the =+= or =-= markers, after all.
+
+This can be achieved by customizing the Ediff faces with color
+combinations that do not carry the same connotations as those of diffs.
+Consider this example, which leverages the ~modus-themes-with-colors~
+macro ([[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]):
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-custom-faces ()
+ (modus-themes-with-colors
+ (custom-set-faces
+ `(ediff-current-diff-A ((,class :inherit unspecified :background ,bg-special-faint-cold :foreground ,fg-special-cold)))
+ `(ediff-current-diff-B ((,class :inherit unspecified :background ,bg-special-faint-warm :foreground ,fg-special-warm)))
+ `(ediff-current-diff-C ((,class :inherit unspecified :background ,bg-special-faint-calm :foreground ,fg-special-calm)))
+ `(ediff-fine-diff-A ((,class :inherit unspecified :background ,bg-special-cold :foreground ,fg-special-cold)))
+ `(ediff-fine-diff-B ((,class :inherit unspecified :background ,bg-special-warm :foreground ,fg-special-warm)))
+ `(ediff-fine-diff-C ((,class :inherit unspecified :background ,bg-special-calm :foreground ,fg-special-calm))))))
+
+;; This is so that the changes persist when switching between
+;; `modus-operandi' and `modus-vivendi'.
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
+#+end_src
+
+Remove the =:foreground= and its value to preserve the underlying
+coloration.
+
+[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]].
+
+** Near-monochrome syntax highlighting
+:properties:
+:custom_id: h:c1f3fa8e-7a63-4a6f-baf3-a7febc0661f0
+:end:
+#+cindex: Monochrome code syntax
+
+While the Modus themes do provide a user option to control the overall
+style of syntax highlighting in programming major modes, they do not
+cover the possibility of a monochromatic or near-monochromatic design
+([[#h:c119d7b2-fcd4-4e44-890e-5e25733d5e52][Option for syntax highlighting]]). This is due to the multitude of
+preferences involved: one may like comments to be styled with an accent
+value, another may want certain constructs to be bold, a third may apply
+italics to doc strings but not comments... The possibilities are
+virtually endless. As such, this sort of design is best handled at the
+user level in accordance with the information furnished elsewhere in
+this manual.
+
+[[#h:1487c631-f4fe-490d-8d58-d72ffa3bd474][Case-by-case face specs using the themes' palette]].
+
+[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]].
+
+The gist is that we want to override the font-lock faces. For our
+changes to persist while switching between ~modus-operandi~ and
+~modus-vivendi~ we wrap our face overrides in a function that we hook to
+~modus-themes-after-load-theme-hook~.
+
+Users who want to replicate the structure of the themes' source code are
+advised to use the examples with ~custom-set-faces~. Those who prefer a
+different approach can use the snippets which call ~set-face-attribute~.
+Below are the code blocks.
+
+The following uses a yellow accent value for comments and green hues for
+strings. Regexp grouping constructs have color values that work in the
+context of a green string. All other elements use the main foreground
+color, except warnings such as the ~user-error~ function in Elisp
+buffers which gets a subtle red tint (not to be confused with the
+~warning~ face which is used for genuine warnings). Furthermore, notice
+the ~modus-themes-bold~ and ~modus-themes-slant~ which apply the
+preference set in the user options ~modus-themes-bold-constructs~ and
+~modus-themes-italic-constructs~, respectively. Users who do not want
+this conditionally must replace these faces with ~bold~ and ~italic~
+respectively (or ~unspecified~ to disable the effect altogether).
+
+#+begin_src emacs-lisp
+;; This is the hook. It will not be replicated across all code samples.
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-subtle-syntax)
+
+(defun my-modus-themes-subtle-syntax ()
+ (modus-themes-with-colors
+ (custom-set-faces
+ `(font-lock-builtin-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-comment-delimiter-face ((,class :inherit font-lock-comment-face)))
+ `(font-lock-comment-face ((,class :inherit unspecified :foreground ,fg-comment-yellow)))
+ `(font-lock-constant-face ((,class :foreground unspecified)))
+ `(font-lock-doc-face ((,class :inherit modus-themes-slant :foreground ,fg-special-mild)))
+ `(font-lock-function-name-face ((,class :foreground unspecified)))
+ `(font-lock-keyword-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-negation-char-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-preprocessor-face ((,class :foreground unspecified)))
+ `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground ,yellow)))
+ `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground ,blue-alt-other)))
+ `(font-lock-string-face ((,class :foreground ,green-alt-other)))
+ `(font-lock-type-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-variable-name-face ((,class :foreground unspecified)))
+ `(font-lock-warning-face ((,class :inherit modus-themes-bold :foreground ,red-nuanced-fg))))))
+
+;; Same as above with `set-face-attribute' instead of `custom-set-faces'
+(defun my-modus-themes-subtle-syntax ()
+ (modus-themes-with-colors
+ (set-face-attribute 'font-lock-builtin-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-comment-delimiter-face nil :inherit 'font-lock-comment-face)
+ (set-face-attribute 'font-lock-comment-face nil :inherit 'unspecified :foreground fg-comment-yellow)
+ (set-face-attribute 'font-lock-constant-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-doc-face nil :inherit 'modus-themes-slant :foreground fg-special-mild)
+ (set-face-attribute 'font-lock-function-name-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-keyword-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-negation-char-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-preprocessor-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-regexp-grouping-backslash nil :inherit 'bold :foreground yellow)
+ (set-face-attribute 'font-lock-regexp-grouping-construct nil :inherit 'bold :foreground blue-alt-other)
+ (set-face-attribute 'font-lock-string-face nil :foreground green-alt-other)
+ (set-face-attribute 'font-lock-type-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-variable-name-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-warning-face nil :inherit 'modus-themes-bold :foreground red-nuanced-fg)))
+#+end_src
+
+The following sample is the same as above, except strings are blue and
+comments are gray. Regexp constructs are adapted accordingly.
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-subtle-syntax ()
+ (modus-themes-with-colors
+ (custom-set-faces
+ `(font-lock-builtin-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-comment-delimiter-face ((,class :inherit font-lock-comment-face)))
+ `(font-lock-comment-face ((,class :inherit unspecified :foreground ,fg-alt)))
+ `(font-lock-constant-face ((,class :foreground unspecified)))
+ `(font-lock-doc-face ((,class :inherit modus-themes-slant :foreground ,fg-docstring)))
+ `(font-lock-function-name-face ((,class :foreground unspecified)))
+ `(font-lock-keyword-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-negation-char-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-preprocessor-face ((,class :foreground unspecified)))
+ `(font-lock-regexp-grouping-backslash ((,class :inherit bold :foreground ,fg-escape-char-backslash)))
+ `(font-lock-regexp-grouping-construct ((,class :inherit bold :foreground ,fg-escape-char-construct)))
+ `(font-lock-string-face ((,class :foreground ,blue-alt)))
+ `(font-lock-type-face ((,class :inherit modus-themes-bold :foreground unspecified)))
+ `(font-lock-variable-name-face ((,class :foreground unspecified)))
+ `(font-lock-warning-face ((,class :inherit modus-themes-bold :foreground ,red-nuanced-fg))))))
+
+;; Same as above with `set-face-attribute' instead of `custom-set-faces'
+(defun my-modus-themes-subtle-syntax ()
+ (modus-themes-with-colors
+ (set-face-attribute 'font-lock-builtin-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-comment-delimiter-face nil :inherit 'font-lock-comment-face)
+ (set-face-attribute 'font-lock-comment-face nil :inherit 'unspecified :foreground fg-alt)
+ (set-face-attribute 'font-lock-constant-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-doc-face nil :inherit 'modus-themes-slant :foreground fg-docstring)
+ (set-face-attribute 'font-lock-function-name-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-keyword-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-negation-char-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-preprocessor-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-regexp-grouping-backslash nil :inherit 'bold :foreground fg-escape-char-backslash)
+ (set-face-attribute 'font-lock-regexp-grouping-construct nil :inherit 'bold :foreground fg-escape-char-construct)
+ (set-face-attribute 'font-lock-string-face nil :foreground blue-alt)
+ (set-face-attribute 'font-lock-type-face nil :inherit 'modus-themes-bold :foreground 'unspecified)
+ (set-face-attribute 'font-lock-variable-name-face nil :foreground 'unspecified)
+ (set-face-attribute 'font-lock-warning-face nil :inherit 'modus-themes-bold :foreground red-nuanced-fg)))
+#+end_src
+
+** Custom hl-todo colors
+:PROPERTIES:
+:CUSTOM_ID: h:2ef83a21-2f0a-441e-9634-473feb940743
+:END:
+
+The =hl-todo= package provides the user option ~hl-todo-keyword-faces~:
+it specifies a pair of keyword and corresponding color value. The Modus
+themes configure that option in the interest of legibility. While this
+works for our purposes, users may still prefer to apply their custom
+values, in which case the following approach is necessary:
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-hl-todo-faces ()
+ (setq hl-todo-keyword-faces '(("TODO" . "#ff0000")
+ ("HACK" . "#ffff00")
+ ("XXX" . "#00ffff")
+ ("NOTE" . "#ff00ff"))))
+
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-hl-todo-faces)
+#+end_src
+
+Or include a ~let~ form, if needed:
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-hl-todo-faces ()
+ (let ((red "#ff0000")
+ (blue "#0000ff"))
+ (setq hl-todo-keyword-faces `(("TODO" . ,blue)
+ ("HACK" . ,red)
+ ("XXX" . ,red)
+ ("NOTE" . ,blue)))))
+
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-hl-todo-faces)
+#+end_src
+
+Normally, we do not touch user options, though this is an exception:
+otherwise the defaults are not always legible.
+
* Face coverage
:properties:
:custom_id: h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19
@@ -3186,6 +4144,8 @@ have lots of extensions, so the "full support" may not be 100% true…
+ ace-window
+ alert
+ all-the-icons
++ all-the-icons-dired
++ all-the-icons-ibuffer
+ annotate
+ ansi-color
+ anzu
@@ -3204,11 +4164,13 @@ have lots of extensions, so the "full support" may not be 100% true…
+ breakpoint (provided by the built-in {{{file(gdb-mi.el)}}} library)
+ calendar and diary
+ calfw
++ calibredb
+ centaur-tabs
+ cfrs
+ change-log and log-view (such as ~vc-print-log~, ~vc-print-root-log~)
+ cider
+ circe
++ citar
+ color-rg
+ column-enforce-mode
+ company-mode*
@@ -3217,6 +4179,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ completions
+ consult
+ corfu
++ corfu-quick
+ counsel*
+ counsel-css
+ cov
@@ -3231,6 +4194,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ deadgrep
+ debbugs
+ deft
++ devdocs
+ dictionary
+ diff-hl
+ diff-mode
@@ -3250,6 +4214,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ easy-jekyll
+ ebdb
+ ediff
++ ein (Emacs IPython Notebook)
+ eglot
+ el-search
+ eldoc-box
@@ -3257,6 +4222,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ elfeed-score
+ elpher
+ embark
++ ement
+ emms
+ enh-ruby-mode (enhanced-ruby-mode)
+ epa
@@ -3348,8 +4314,10 @@ have lots of extensions, so the "full support" may not be 100% true…
+ marginalia
+ markdown-mode
+ markup-faces (~adoc-mode~)
++ mct
+ mentor
+ messages
++ mini-modeline
+ minimap
+ mmm-mode
+ mode-line
@@ -3395,6 +4363,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ proced
+ prodigy
+ pulse
++ pyim
+ quick-peek
+ racket-mode
+ rainbow-blocks
@@ -3417,6 +4386,8 @@ have lots of extensions, so the "full support" may not be 100% true…
+ side-notes
+ sieve-mode
+ skewer-mode
++ slime (slbd)
++ sly
+ smart-mode-line
+ smartparens
+ smerge
@@ -3438,9 +4409,11 @@ have lots of extensions, so the "full support" may not be 100% true…
+ telephone-line
+ terraform-mode
+ term
++ textsec
+ tomatinho
+ transient (pop-up windows such as Magit's)
+ trashed
++ tree-sitter
+ treemacs
+ tty-menu
+ tuareg
@@ -3454,6 +4427,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ visible-mark
+ visual-regexp
+ vterm
++ vundo
+ wcheck-mode
+ web-mode
+ wgrep
@@ -3492,8 +4466,11 @@ supported by the themes.
+ counsel-org-capture-string
+ define-word
+ disk-usage
++ dtache
+ easy-kill
+ edit-indirect
++ egerrit
++ elfeed-summary
+ evil-owl
+ flyspell-correct
+ fortran-mode
@@ -3504,6 +4481,7 @@ supported by the themes.
+ i3wm-config-mode
+ minibuffer-line
+ no-emoji
++ org-remark
+ parrot
+ perl-mode
+ php-mode
@@ -3513,6 +4491,7 @@ supported by the themes.
+ swift-mode
+ tab-bar-echo-area
+ tide
++ undo-hl
+ vdiff
+ vertico-indexed
+ vertico-mouse
@@ -3525,40 +4504,6 @@ supported by the themes.
This section covers information that may be of interest to users of
individual packages.
-** Note on avy hints
-:properties:
-:custom_id: h:2fdce705-6de7-44e6-ab7f-18f59af99e01
-:end:
-
-Hints can appear everywhere, in wildly varying contexts, hence, their
-appearance, by necessity, is a compromise. However, there are various
-options for making them stand out. First is dimming the surroundings:
-
-#+begin_src emacs-lisp
-(setq avy-background t)
-#+end_src
-
-Dimming works well when you find it difficult to spot hints, any hint.
-Second is limiting the number of faces used by hints:
-
-#+begin_src emacs-lisp
-(setq avy-lead-faces
- '(avy-lead-face
- avy-lead-face-1
- avy-lead-face-1
- avy-lead-face-1
- avy-lead-face-1))
-#+end_src
-
-Limiting the number of faces works well with longer hints when you find
-it difficult to identify individual hints, especially with hints
-touching each other. The first character of the hint will have an
-intense color, the remaining ones the same neutral color.
-
-Third is preferring commands that produce fewer candidates. Fewer hints
-is less noise: ~avy-goto-char-timer~ is an excellent alternative to
-~avy-goto-char~.
-
** Note on calendar.el weekday and weekend colors
:properties:
:custom_id: h:b2db46fb-32f4-44fd-8e11-d2b261cf51ae
@@ -3588,6 +4533,72 @@ weekends uniformly.
For changes to take effect, the Calendar buffer needs to be generated
anew.
+** Note on git-gutter in Doom Emacs
+:PROPERTIES:
+:CUSTOM_ID: h:a195e37c-e58c-4148-b254-8ba1ed8a731a
+:END:
+
+The =git-gutter= and =git-gutter-fr= packages default to drawing bitmaps
+for the indicators they display (e.g. bitmap of a plus sign for added
+lines). In Doom Emacs, these bitmaps are replaced with contiguous lines
+which may look nicer, but require a change to the foreground of the
+relevant faces to yield the desired colour combinations.
+
+Since this is Doom-specific, we urge users to apply changes in their
+local setup. Below is some sample code, based on what we cover at
+length elsewhere in this manual:
+
+[[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]].
+
+[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]].
+
+#+begin_src emacs-lisp
+(defun my-modus-themes-custom-faces ()
+ (modus-themes-with-colors
+ (custom-set-faces
+ ;; Replace green with blue if you use `modus-themes-deuteranopia'.
+ `(git-gutter-fr:added ((,class :foreground ,green-fringe-bg)))
+ `(git-gutter-fr:deleted ((,class :foreground ,red-fringe-bg)))
+ `(git-gutter-fr:modified ((,class :foreground ,yellow-fringe-bg))))))
+
+(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
+#+end_src
+
+If the above does not work, try this instead:
+
+#+begin_src emacs-lisp
+(after! modus-themes
+ (modus-themes-with-colors
+ (custom-set-faces
+ ;; Replace green with blue if you use `modus-themes-deuteranopia'.
+ `(git-gutter-fr:added ((,class :foreground ,green-fringe-bg)))
+ `(git-gutter-fr:deleted ((,class :foreground ,red-fringe-bg)))
+ `(git-gutter-fr:modified ((,class :foreground ,yellow-fringe-bg))))))
+#+end_src
+
+Replace ~green-fringe-bg~ with ~blue-fringe-bg~ if you want to optimize
+for red-green color deficiency.
+
+[[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]].
+
+** Note on php-mode multiline comments
+:PROPERTIES:
+:CUSTOM_ID: h:d0a3157b-9c04-46e8-8742-5fb2a7ae8798
+:END:
+
+Depending on your build of Emacs and/or the environment it runs in,
+multiline comments in PHP with the =php-mode= package use the
+~font-lock-doc-face~ instead of ~font-lock-comment-face~.
+
+This seems to make all comments use the appropriate face:
+
+#+begin_src emacs-lisp
+(defun my-multine-comments ()
+ (setq-local c-doc-face-name 'font-lock-comment-face))
+
+(add-hook 'php-mode-hook #'my-multine-comments)
+#+end_src
+
** Note on underlines in compilation buffers
:properties:
:custom_id: h:420f5a33-c7a9-4112-9b04-eaf2cbad96bd
@@ -3597,14 +4608,15 @@ Various buffers that produce compilation results or run tests on code
apply an underline to the file names they reference or to relevant
messages. Users may consider this unnecessary or excessive.
-To outright disable the effect, use this:
+To outright disable the effect, use this (buffers need to be generated
+anew):
#+begin_src emacs-lisp
(setq compilation-message-face nil)
#+end_src
If some element of differentiation is still desired, a good option is to
-render the affected text using the ~italic~ face:
+render the affected text with the ~italic~ face:
#+begin_src emacs-lisp
(setq compilation-message-face 'italic)
@@ -3668,33 +4680,35 @@ package: it draws too much attention to unfocused windows.
:custom_id: h:2a602816-bc1b-45bf-9675-4cbbd7bf6cab
:end:
-While designing the style for ~display-fill-column-indicator-mode~, we
-stayed close to the mode's defaults: to apply a subtle foreground color
-to the ~fill-column-indicator~ face, which blends well with the rest of
-theme and is consistent with the role of that mode. This is to not
-upset the expectations of users.
-
-Nevertheless, ~display-fill-column-indicator-mode~ has some known
-limitations pertaining to its choice of using typographic characters to
-draw its indicator. What should be a continuous vertical line might
-appear as a series of dashes in certain contexts or under specific
-conditions: a non-default value for ~line-spacing~, scaled and/or
-variable-pitch headings have been observed to cause this effect.
+The ~display-fill-column-indicator-mode~ uses a typographic character to
+draw its line. This has the downside of creating a dashed line. The
+dashes are further apart depending on how tall the font's glyph height
+is and what integer the ~line-spacing~ is set to.
-Given that we cannot control such factors, it may be better for affected
-users to deviate from the default style of the ~fill-column-indicator~
-face. Instead of setting a foreground color, one could use a background
-and have the foreground be indistinguishable from it. For example:
+At the theme level we eliminate this effect by making the character one
+pixel tall: the line is contiguous. Users who prefer the dashed line
+are advised to change the ~fill-column-indicator~ face, as explained
+elsewhere in this document. For example:
#+begin_src emacs-lisp
(modus-themes-with-colors
(custom-set-faces
- `(fill-column-indicator ((,class :background ,bg-inactive
- :foreground ,bg-inactive)))))
+ `(fill-column-indicator ((,class :foreground ,bg-active)))))
#+end_src
[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]].
+To make the line thicker, set the height to be equal to the base font
+size instead of the one pixel we use. This is done by specifying a rate
+instead of an absolute number, as in =:height 1.0= versus =:height 1=.
+For example:
+
+#+begin_src emacs-lisp
+(modus-themes-with-colors
+ (custom-set-faces
+ `(fill-column-indicator ((,class :height 1.0 :background ,bg-inactive :foreground ,bg-inactive)))))
+#+end_src
+
** Note on highlight-parentheses.el
:PROPERTIES:
:CUSTOM_ID: h:24bab397-dcb2-421d-aa6e-ec5bd622b913
@@ -3885,7 +4899,7 @@ implements an alternative to the typical coloration of code. Instead of
highlighting the syntactic constructs, it applies color to different
levels of depth in the code structure.
-As {{{file(prism.el)}}} offers a broad range of customisations, we cannot
+As {{{file(prism.el)}}} offers a broad range of customizations, we cannot
style it directly at the theme level: that would run contrary to the
spirit of the package. Instead, we may offer preset color schemes.
Those should offer a starting point for users to adapt to their needs.
@@ -4073,22 +5087,68 @@ Emacs' HTML rendering library ({{{file(shr.el)}}}) may need explicit
configuration to respect the theme's colors instead of whatever
specifications the webpage provides.
-Consult {{{kbd(C-h v shr-use-colors)}}}.
+Consult the doc string of ~shr-use-colors~.
-** Note on EWW and Elfeed fonts
+** Note on SHR fonts
:properties:
:custom_id: h:e6c5451f-6763-4be7-8fdb-b4706a422a4c
:end:
+#+cindex: Fonts in EWW, Elfeed, Ement, and SHR
-EWW and Elfeed rely on the Simple HTML Renderer to display their
-content. The {{{file(shr.el)}}} library contains the variable ~shr-use-fonts~
-that controls whether the text in the buffer is set to a ~variable-pitch~
-typeface (proportionately spaced) or if just retains whatever the
-default font family is. Its default value is non-nil, which means that
-~variable-pitch~ is applied.
+By default, packages that build on top of the Simple HTML Remember (=shr=)
+use proportionately spaced fonts. This is controlled by the user option
+~shr-use-fonts~, which is set to non-nil by default. To use the standard
+font instead, set that variable to nil.
[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]].
+Packages affected by this are:
+
++ elfeed
++ ement
++ eww
+
+This is a non-exhaustive list.
+
+** Note on Ement colors and fonts
+:properties:
+:custom_id: h:8e636056-356c-4ca7-bc78-ebe61031f585
+:end:
+
+The =ement.el= library by Adam Porter (also known as "alphapapa") defaults
+to a method of colorizing usernames in a rainbow style. This is
+controlled by the user option ~ement-room-prism~ and can be disabled with:
+
+#+begin_src emacs-lisp
+(setq ement-room-prism nil)
+#+end_src
+
+The contrast ratio of these colors is governed by another user option:
+~ement-room-prism-minimum-contrast~. By default, it is set to 6 which is
+slightly below our nominal target. Try this instead:
+
+#+begin_src emacs-lisp
+(setq ement-room-prism-minimum-contrast 7)
+#+end_src
+
+With regard to fonts, Ement depends on =shr= ([[#h:e6c5451f-6763-4be7-8fdb-b4706a422a4c][Note on SHR fonts]]).
+
+Since we are here, here is an excerpt from Ement's source code:
+
+#+begin_src emacs-lisp
+(defcustom ement-room-prism-minimum-contrast 6
+ "Attempt to enforce this minimum contrast ratio for user faces.
+This should be a reasonable number from, e.g. 0-7 or so."
+ ;; Prot would almost approve of this default. :) I would go all the way
+ ;; to 7, but 6 already significantly dilutes the colors in some cases.
+ :type 'number)
+#+end_src
+
+Yes, I do approve of that default. Even a 4.5 (the WCAG AA rating)
+would be a good baseline for many themes and/or user configurations.
+Our target is the highest of the sort, though we do not demand that
+everyone conforms with it.
+
** Note on Helm grep
:properties:
:custom_id: h:d28879a2-8e4b-4525-986e-14c0f873d229
@@ -4189,6 +5249,20 @@ you've customized any faces.
"-draw" "text %X,%Y '%c'"))))
#+end_src
+** Note on the Notmuch logo
+:properties:
+:custom_id: h:636af312-54a5-4918-84a6-0698e85a3c6d
+:end:
+
+By default, the "hello" buffer of Notmuch includes a header with the
+programs' logo and a couple of buttons. The logo has the effect of
+enlarging the height of the line, which negatively impacts the shape of
+those buttons. Disabling the logo fixes the problem:
+
+#+begin_src emacs-lisp
+(setq notmuch-show-logo nil)
+#+end_src
+
* Frequently Asked Questions
:properties:
:custom_id: h:b3384767-30d3-4484-ba7f-081729f03a47
@@ -4312,8 +5386,8 @@ and hints of green give us suitable shades of purple.
Due to the need of maintaining some difference in hueness between
adjacent colors, it is not possible to make red, green, and yellow the
-primary colors, because blue could not be used to control their
-luminance and, thus the relevant space would shrink considerably.
+main colors, because blue cannot be used to control their luminance and,
+thus the relevant space will shrink considerably.
[[#h:5ce7ae2e-9348-4e55-b4cf-9302345b1826][Is the contrast ratio about adjacent colors?]]
@@ -4400,6 +5474,139 @@ The color combinations may have been optimized for accessibility, though
the remaining contributing factors in each case need to be considered in
full.
+** Are these color schemes?
+:properties:
+:custom_id: h:a956dbd3-8fd2-4f5d-8b01-5f881268cf2b
+:end:
+#+cindex: Themes, not color schemes
+
+No, the Modus themes are not color schemes.
+
+A color scheme is a collection of colors. A good color scheme is a
+combination of colors with an inner logic or abstract structure.
+
+A theme is a set of patterns that are applied across different contexts.
+A good theme is one that does so with consistency, though not
+uniformity.
+
+In practical terms, a color scheme is what one uses when, for example,
+they edit the first sixteen escape sequences of a terminal emulator to
+the hues of their preference. The terminal offers the option to choose,
+say, the exact value of what counts as "red", but does not provide the
+means to control where that is mapped to and whether it should also have
+other qualities such as a bold weight for the underlying text or an
+added background color. In contradistinction, Emacs uses constructs
+known as "faces" which allow the user/developer to specify where a given
+color will be used and whether it should be accompanied by other
+typographic or stylistic attributes.
+
+By configuring the multitude of faces on offer we thus control both
+which colors are applied and how they appear in their context. When a
+package wants to render each instance of "foo" with the "bar" face, it
+is not requesting a specific color, which makes things considerably more
+flexible as we can treat "bar" in its own right without necessarily
+having to use some color value that we hardcoded somewhere.
+
+Which brings us to the distinction between consistency and uniformity
+where our goal is always the former: we want things to look similar
+across all interfaces, but we must never force a visual identity where
+that runs contrary to the functionality of the given interface. For
+instance, all links are underlined by default yet there are cases such
+as when viewing listings of emails in Gnus (and Mu4e, Notmuch) where (i)
+it is already understood that one must follow the indicator or headline
+to view its contents and (ii) underlining everything would make the
+interface virtually unusable.
+
+[[#h:5808be52-361a-4d18-88fd-90129d206f9b][Option for links]].
+
+Again, one must exercise judgement in order to avoid discrimination,
+where "discrimination" refers to:
+
++ The treatment of substantially different magnitudes as if they were of
+ the same class.
++ Or the treatment of the same class of magnitudes as if they were of a
+ different class.
+
+(To treat similar things differently; to treat dissimilar things alike.)
+
+If, in other words, one was to enforce uniformity without accounting for
+the particular requirements of each case---the contextual demands for
+usability beyond matters of color---they would be making a
+not-so-obvious error of treating different cases as if they were the
+same.
+
+The Modus themes prioritise "thematic consistency" over abstract harmony
+or regularity among their applicable colors. In concrete terms, we do
+not claim that, say, our yellows are the best complements for our blues
+because we generally avoid using complementary colors side-by-side, so
+it is wrong to optimise for a decontextualised blue+yellow combination.
+Not to imply that our colors do not work well together because they do,
+just to clarify that consistency of context is what themes must strive
+for, and that requires widening the scope of the design beyond the
+particularities of a color scheme.
+
+Long story short: color schemes and themes have different requirements.
+Please do not conflate the two.
+
+** Port the Modus themes to other platforms?
+:properties:
+:custom_id: h:7156b949-917d-488e-9a72-59f70d80729c
+:end:
+#+cindex: Porting the themes to other editors
+
+There is no plan to port the themes to other platforms or text editors.
+I (Protesilaos) only use GNU Emacs and thus cannot maintain code that
+targets software I am either not familiar with or am not using on a
+daily basis.
+
+While it is possible to produce a simulacrum based on a given template,
+doing so would run contrary to how this project is maintained where
+details matter greatly.
+
+Each program has its own requirements so it won't always be
+possible---or indeed desirable---to have 1:1 correspondence between what
+applies to Emacs and what should be done elsewhere. No port should ever
+strive to be a faithful copy of the Emacs implementation, as no other
+program is an Emacs equivalent, but instead try to follow the spirit of
+the design. For example, some of the customization options accept a
+list as their value, or an alist, which may not be possible to reproduce
+on other platforms.
+
+[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization options]].
+
+In other words, if something must be done differently on a certain
+editor then that is acceptable so long as (i) the accessibility
+standards are not compromised and (ii) the overall character of the
+themes remains consistent.
+
+The former criterion should be crystal clear as it pertains to the
+scientific foundations of the themes: high legibility and taking care of
+the needs of users with red-green color deficiency (deuteranopia) by
+avoiding red+green color coding paradigms and/or by providing red+blue
+variants.
+
+The latter criterion is the "je ne sais quoi" of the artistic aspect of
+the themes, which is partially fleshed out in this manual.
+
+[[#h:b3384767-30d3-4484-ba7f-081729f03a47][Frequently Asked Questions]].
+
+With regard to the artistic aspect (where "art" qua skill may amount to
+an imprecise science), there is no hard-and-fast rule in effect as it
+requires one to exercise discretion and make decisions based on
+context-dependent information or constraints. As is true with most
+things in life, when in doubt, do not cling on to the letter of the law
+but try to understand its spirit.
+
+For a trivial example: the curly underline that Emacs draws for spelling
+errors is thinner than, e.g., what a graphical web browser has, so if I
+was to design for an editor than has a thicker curly underline I would
+make the applicable colors less intense to counterbalance the
+typographic intensity of the added thickness.
+
+With those granted, if anyone is willing to develop a port of the
+themes, they are welcome to contact me and I will do my best to help
+them in their efforts.
+
* Contributing
:properties:
:custom_id: h:9c3cd842-14b7-44d7-84b2-a5c8bc3fc3b1
@@ -4416,8 +5623,8 @@ in which you can contribute to their ongoing development.
The ~modus-operandi~ and ~modus-vivendi~ themes are built into Emacs 28.
-The source code of the themes is [[https://gitlab.com/protesilaos/modus-themes/][available on Gitlab]], for the time
-being. A [[https://github.com/protesilaos/modus-themes/][mirror on Github]] is also on offer.
+The source code of the themes is [[https://git.sr.ht/~protesilaos/modus-themes][available on SourceHut]]. Or check the
+[[https://gitlab.com/protesilaos/modus-themes/][GitLab mirror (former main source)]] and the [[https://github.com/protesilaos/modus-themes/][GitHub mirror]].
An HTML version of this manual is provided as an extension of the
[[https://protesilaos.com/emacs/modus-themes/][author's personal website]] (does not rely on any non-free code).
@@ -4428,7 +5635,10 @@ An HTML version of this manual is provided as an extension of the
:end:
#+cindex: Contributing
-A few tasks you can help with:
+#+findex: modus-themes-report-bug
+A few tasks you can help with by sending an email to the general
+[[https://lists.sr.ht/~protesilaos/modus-themes][modus-themes public mailing list]] (or use the command
+~modus-themes-report-bug~).
+ Suggest refinements to packages that are covered.
+ Report packages not covered thus far.
@@ -4436,7 +5646,8 @@ A few tasks you can help with:
+ Help expand the documentation of covered-but-not-styled packages.
+ Suggest refinements to the color palette.
+ Help expand this document or any other piece of documentation.
-+ Merge requests for code refinements.
++ Send patches for code refinements (if you need, ask me for help with
+ Git---we all start out as beginners).
[[#h:111773e2-f26f-4b68-8c4f-9794ca6b9633][Patches require copyright assignment to the FSF]].
@@ -4444,6 +5655,10 @@ It is preferable that your feedback includes some screenshots, GIFs, or
short videos, as well as further instructions to reproduce a given
setup. Though this is not a requirement.
+#+findex: modus-themes-version
+Also consider mentioning the version of the themes you are using, such
+as by invoking the command ~modus-themes-version~.
+
Whatever you do, bear in mind the overarching objective of the Modus
themes: to keep a contrast ratio that is greater or equal to 7:1 between
background and foreground colors. If a compromise is ever necessary
@@ -4475,7 +5690,7 @@ will send you the assignment form for your past and future changes.
Please use your full legal name (in ASCII characters) as the subject
line of the message.
-----------------------------------------------------------------------
+
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES
[What is the name of the program or package you're contributing to?]
@@ -4523,40 +5738,48 @@ The Modus themes are a collective effort. Every bit of work matters.
+ Author/maintainer :: Protesilaos Stavrou.
-+ Contributions to code or documentation :: Anders Johansson, Basil
- L.{{{space()}}} Contovounesios, Björn Lindström, Carlo Zancanaro, Christian
- Tietze, Daniel Mendler, Eli Zaretskii, Fritz Grabo, Illia Ostapyshyn,
- Kévin Le Gouguec, Kostadin Ninev, Madhavan Krishnan, Markus Beppler,
- Matthew Stevenson, Mauro Aranda, Nicolas De Jaeghere, Philip
- Kaludercic, Rudolf Adamkovič, Stephen Gildea, Shreyas Ragavan, Stefan
- Kangas, Vincent Murphy, Xinglu Chen.
++ Contributions to code or documentation :: Alex Griffin, Anders
+ Johansson, Basil L.{{{space()}}} Contovounesios, Björn Lindström,
+ Carlo Zancanaro, Christian Tietze, Daniel Mendler, Eli Zaretskii,
+ Fritz Grabo, Illia Ostapyshyn, Kévin Le Gouguec, Kostadin Ninev,
+ Madhavan Krishnan, Manuel Giraud, Markus Beppler, Matthew Stevenson,
+ Mauro Aranda, Nicolas De Jaeghere, Philip Kaludercic, Pierre
+ Téchoueyres, Rudolf Adamkovič, Stephen Gildea, Shreyas Ragavan, Stefan
+ Kangas, Utkarsh Singh, Vincent Murphy, Xinglu Chen, Yuanchen Xie.
+ Ideas and user feedback :: Aaron Jensen, Adam Porter, Adam Spiers,
- Adrian Manea, Alex Griffin, Alex Peitsinis, Alexey Shmalko, Alok
- Singh, Anders Johansson, André Alexandre Gomes, Arif Rezai, Basil
- L.{{{space()}}} Contovounesios, Burgess Chang, Christian Tietze, Christopher
- Dimech, Damien Cassou, Daniel Mendler, Dario Gjorgjevski, David
- Edmondson, Davor Rotim, Divan Santana, Eliraz Kedmi, Emanuele Michele
- Alberto Monterosso, Farasha Euker, Feng Shu, Gautier Ponsinet, Gerry
- Agbobada, Gianluca Recchia, Guilherme Semente, Gustavo Barros,
- Hörmetjan Yiltiz, Ilja Kocken, Iris Garcia, Jeremy Friesen, Jerry
- Zhang, Johannes Grødem, John Haman, Joshua O'Connor, Kevin Fleming,
- Kévin Le Gouguec, Kostadin Ninev, Len Trigg, Manuel Uberti, Mark
- Burton, Markus Beppler, Mauro Aranda, Michael Goldenberg, Morgan
- Smith, Murilo Pereira, Nicky van Foreest, Nicolas De Jaeghere, Paul
- Poloskov, Pengji Zhang, Pete Kazmier, Peter Wu, Philip Kaludercic,
- Pierre Téchoueyres, Roman Rudakov, Ryan Phillips, Rudolf Adamkovič,
- Sam Kleinman, Shreyas Ragavan, Simon Pugnet, Tassilo Horn, Thibaut
- Verron, Thomas Heartman, Trey Merkley, Togan Muftuoglu, Toon Claes,
- Uri Sharf, Utkarsh Singh, Vincent Foley. As well as users: Ben,
- CsBigDataHub1, Emacs Contrib, Eugene, Fourchaux, Fredrik, Moesasji,
- Nick, TheBlob42, Trey, bepolymathe, doolio, fleimgruber, iSeeU,
- jixiuf, okamsn, pRot0ta1p.
-
-+ Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii, Glenn
- Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core Emacs),
- Stefan Monnier (GNU Elpa), André Alexandre Gomes, Dimakakos Dimos,
- Morgan Smith, Nicolas Goaziou (Guix), Dhavan Vaidya (Debian).
+ Adrian Manea, Alex Griffin, Alex Koen, Alex Peitsinis, Alexey Shmalko,
+ Alok Singh, Anders Johansson, André Alexandre Gomes, Andrew Tropin,
+ Antonio Hernández Blas, Arif Rezai, Augusto Stoffel, Basil
+ L.{{{space()}}} Contovounesios, Burgess Chang, Christian Tietze,
+ Christopher Dimech, Christopher League, Damien Cassou, Daniel Mendler,
+ Dario Gjorgjevski, David Edmondson, Davor Rotim, Divan Santana, Eliraz
+ Kedmi, Emanuele Michele Alberto Monterosso, Farasha Euker, Feng Shu,
+ Gautier Ponsinet, Gerry Agbobada, Gianluca Recchia, Gonçalo Marrafa,
+ Guilherme Semente, Gustavo Barros, Hörmetjan Yiltiz, Ilja Kocken, Iris
+ Garcia, Ivan Popovych, Jeremy Friesen, Jerry Zhang, Johannes Grødem,
+ John Haman, Jorge Morais, Joshua O'Connor, Julio C. Villasante, Kenta
+ Usami, Kevin Fleming, Kévin Le Gouguec, Kostadin Ninev, Len Trigg,
+ Lennart C. Karssen, Magne Hov, Manuel Uberti, Mark Bestley, Mark
+ Burton, Markus Beppler, Mauro Aranda, Maxime Tréca, Michael
+ Goldenberg, Morgan Smith, Morgan Willcock, Murilo Pereira, Nicky van
+ Foreest, Nicolas De Jaeghere, Paul Poloskov, Pengji Zhang, Pete
+ Kazmier, Peter Wu, Philip Kaludercic, Pierre Téchoueyres, Przemysław
+ Kryger, Robert Hepple, Roman Rudakov, Ryan Phillips, Rytis Paškauskas,
+ Rudolf Adamkovič, Sam Kleinman, Samuel Culpepper, Saša Janiška,
+ Shreyas Ragavan, Simon Pugnet, Tassilo Horn, Thibaut Verron, Thomas
+ Heartman, Togan Muftuoglu, Tony Zorman, Trey Merkley, Tomasz
+ Hołubowicz, Toon Claes, Uri Sharf, Utkarsh Singh, Vincent Foley. As
+ well as users: Ben, CsBigDataHub1, Emacs Contrib, Eugene, Fourchaux,
+ Fredrik, Moesasji, Nick, TheBlob42, Trey, bepolymathe, bit9tream,
+ derek-upham, doolio, fleimgruber, gitrj95, iSeeU, jixiuf, okamsn,
+ pRot0ta1p.
+
++ Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii,
+ Glenn Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core
+ Emacs), Stefan Monnier (GNU Elpa), André Alexandre Gomes, Andrew
+ Tropin, Dimakakos Dimos, Morgan Smith, Nicolas Goaziou (Guix), Dhavan
+ Vaidya (Debian).
+ Inspiration for certain features :: Bozhidar Batsov (zenburn-theme),
Fabrice Niessen (leuven-theme).
@@ -4566,7 +5789,7 @@ Jaeghere, and Omar Antolín Camarena for their long time contributions
and insightful commentary on key aspects of the themes' design and/or
aspects of their functionality.
-* Meta
+* Other notes about the project
:properties:
:custom_id: h:13752581-4378-478c-af17-165b6e76bc1b
:end:
@@ -4589,12 +5812,18 @@ of this sort):
+ [[https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/][Modus themes: review of select "faint" colours]] (2021-01-11)
+ [[https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/][The Modus themes now cover deuteranopia in diffs]] (2021-02-25)
+ [[https://protesilaos.com/codelog/2021-06-02-modus-themes-org-agenda/][Introducing the variable modus-themes-org-agenda]] (2021-06-02)
++ [[https://protesilaos.com/codelog/2022-01-02-review-modus-themes-org-habit-colours/][Modus themes: review of the org-habit graph colours]] (2022-01-02)
++ [[https://protesilaos.com/codelog/2022-01-03-modus-themes-port-faq/][Re: VSCode or Vim ports of the Emacs modus-themes?]] (2022-01-03)
++ [[https://protesilaos.com/codelog/2022-04-20-modus-themes-case-study-avy/][Modus themes: case study on Avy faces and colour combinations]] (2022-04-20)
++ [[https://protesilaos.com/codelog/2022-04-21-modus-themes-colour-theory/][Emacs: colour theory and techniques used in the Modus themes]] (2022-04-21)
-And here are the canonical sources of this project's documentation:
+And here are the canonical sources of this project:
+ Manual :: <https://protesilaos.com/emacs/modus-themes>
+ Change Log :: <https://protesilaos.com/emacs/modus-themes-changelog>
+ Screenshots :: <https://protesilaos.com/emacs/modus-themes-pictures>
++ Git repository :: https://git.sr.ht/~protesilaos/modus-themes
++ Mailing list :: https://lists.sr.ht/~protesilaos/modus-themes
* GNU Free Documentation License
:properties:
diff --git a/doc/misc/org.org b/doc/misc/org.org
index 60af81ea2cf..fa8fa408c7e 100644
--- a/doc/misc/org.org
+++ b/doc/misc/org.org
@@ -3352,7 +3352,7 @@ current buffer:
~org-link-email-description-format~. By default, it refers to the
addressee and the subject.
-- /Web browsers: W3, W3M and EWW/ ::
+- /Web browsers: W3M and EWW/ ::
Here the link is the current URL, with the page title as the
description.
@@ -6405,7 +6405,7 @@ special repeaters =++= and =.+=. For example:
Marking this DONE shifts the date to one month after today.
,** TODO Wash my hands
- DEADLINE: <2019-04-05 08:00 Sun .+1h>
+ DEADLINE: <2019-04-05 08:00 Fri .+1h>
Marking this DONE shifts the date to exactly one hour from now.
#+end_example
@@ -8544,8 +8544,8 @@ commands:
Search for a regular expression in all agenda files and additionally
in the files listed in ~org-agenda-text-search-extra-files~. This
uses the Emacs command ~multi-occur~. A prefix argument can be used
- to specify the number of context lines for each match, default is
- 1.
+ to specify the number of context lines for each match, the default
+ is 1.
- {{{kbd(#)}}} ::
@@ -12442,7 +12442,7 @@ should in principle be exportable as a Beamer presentation.
When =ignoreheading= is set, Org export ignores the entry's headline
but not its content. This is useful for inserting content between
frames. It is also useful for properly closing a =column=
- environment. @end itemize
+ environment.
#+cindex: @samp{BEAMER_ACT}, property
#+cindex: @samp{BEAMER_OPT}, property
diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi
index b18ab2a6b29..8c798d6c33b 100644
--- a/doc/misc/rcirc.texi
+++ b/doc/misc/rcirc.texi
@@ -154,8 +154,11 @@ deego: fsbot rules!
@cindex nick completion
@cindex completion of nicks
+@vindex rcirc-cycle-completion-flag
@kindex TAB
Since this is so common, you can use @key{TAB} to do nick completion.
+By default rcirc will use the default completion system, but you can
+enable @code{rcirc-cycle-completion-flag} to cycle nicks in place.
@node Getting started with rcirc
@section Getting started with rcirc
@@ -636,9 +639,9 @@ password to use.
@item certfp
@cindex certfp authentication
Use this symbol if you want to use CertFP authentication. The
-necessary arguments are the path to the client certificate key and
-password. The CertFP authentication requires a @acronym{TLS}
-connection.
+necessary arguments are the path to the key and to the client
+certificate associated with the account. The CertFP authentication
+requires a @acronym{TLS} connection.
@end table
diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi
index 0acb7bf3f15..6d0415cdbbb 100644
--- a/doc/misc/ses.texi
+++ b/doc/misc/ses.texi
@@ -220,7 +220,14 @@ You move around with the regular Emacs movement commands.
@table @kbd
@item j
-Moves point to cell, specified by identifier (@code{ses-jump}).
+Moves point to cell, specified by identifier (@code{ses-jump}). Unless
+the cell is a renamed cell, the identifier is case-insensitive. A
+prefix argument @math{n} move to cell with coordinates @math{(n\div R,
+n \% C)} for a spreadsheet of @math{R} rows and @math{C} columns, and
+A1 being of coordinates @math{(0,0)}. The way the identifier or the
+command prefix argument are interpreted can be customized through
+variables @code{ses-jump-cell-name-function} and
+@code{ses-jump-prefix-function}.
@end table
Point is always at the left edge of a cell, or at the empty endline.
@@ -726,10 +733,6 @@ yank. This doesn't make any difference?
@section Customizing @acronym{SES}
@cindex customizing
@vindex enable-local-eval
-@vindex ses-mode-hook
-@vindex safe-functions
-@vindex enable-local-eval
-
By default, a newly-created spreadsheet has 1 row and 1 column. The
column width is 7 and the default printer is @samp{"%.7g"}. Each of these
@@ -740,9 +743,34 @@ cell. You can customize @code{ses-after-entry-functions} to move left or
up or down. For diagonal movement, select two functions from the
list.
+@vindex ses-jump-cell-name-function
+@code{ses-jump-cell-name-function} is a customizable variable by
+default set to the @code{upcase} function. This function is called
+when you pass a cell name to the @command{ses-jump} command (@kbd{j}),
+it changes the entered cell name to that where to jump. The default
+setting @code{upcase} allows you to enter the cell name in low
+case. Another use of @code{ses-jump-cell-name-function} could be some
+internationalisation to convert non latin characters into latin
+equivalents to name the cell. Instead of a cell name, the function may
+return cell coordinates in the form of a cons, for instance @code{(0
+. 0)} for cell @code{A1}, @code{(1 . 0)} for cell @code{A2}, etc.
+
+@vindex ses-jump-prefix-function
+@code{ses-jump-prefix-function} is a customisable variable by default
+set to the @code{ses-jump-prefix} function. This function is called
+when you give a prefix argument to the @command{ses-jump} command
+(@kbd{j}). It returns a cell name or cell coordinates corresponding to
+the prefix argument. Cell coordinates are in the form of a cons, for
+instance @code{(1 . 0)} for cell @code{A2}. The default setting
+@code{ses-jump-prefix} will number cells left to right and then top
+down, so assuming a 4x3 spreadsheet prefix argument 0 jumps to cell
+A1, prefix argument 2 jumps to C1, prefix argument 3 jumps to A2, etc.
+
+@vindex ses-mode-hook
@code{ses-mode-hook} is a normal mode hook (list of functions to
execute when starting @acronym{SES} mode for a buffer).
+@vindex safe-functions
The variable @code{safe-functions} is a list of possibly-unsafe
functions to be treated as safe when analyzing formulas and printers.
@xref{Virus protection}. Before customizing @code{safe-functions},
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index 58b6abee78c..8872e5e055f 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,9 +3,9 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2022-01-02.12}
+\def\texinfoversion{2022-04-09.08}
%
-% Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc.
+% Copyright 1985, 1986, 1988, 1990-2022 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
@@ -3171,16 +3171,8 @@ end
% Default is `distinct'.
\kbdinputstyle distinct
-% @kbd is like @code, except that if the argument is just one @key command,
-% then @kbd has no effect.
-\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}}
-
-\def\xkey{\key}
-\def\kbdsub#1#2#3\par{%
- \def\one{#1}\def\three{#3}\def\threex{??}%
- \ifx\one\xkey\ifx\threex\three \key{#2}%
- \else{\tclose{\kbdfont\setcodequotes\look}}\fi
- \else{\tclose{\kbdfont\setcodequotes\look}}\fi
+\def\kbd#1{%
+ \tclose{\kbdfont\setcodequotes#1}%
}
% definition of @key that produces a lozenge. Doesn't adjust to text size.
@@ -4417,7 +4409,7 @@ $$%
% Find the correct column width
\hsize=\expandafter\csname col\the\colcount\endcsname
%
- \rightskip=0pt
+ \advance\rightskip by -1\rightskip % Zero leaving only any stretch
\ifnum\colcount=1
\advance\hsize by\leftskip % Add indent of surrounding text
\else
@@ -5961,7 +5953,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Chapters, sections, etc.
% Let's start with @part.
-\outer\parseargdef\part{\partzzz{#1}}
+\parseargdef\part{\partzzz{#1}}
\def\partzzz#1{%
\chapoddpage
\null
@@ -8680,9 +8672,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
}
\def\wordTop{Top}
-% Until the next @node or @bye command, divert output to a box that is not
-% output.
-\def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}%
+% Until the next @node, @part or @bye command, divert output to a box that
+% is not output.
+\def\ignorenode{\setbox\dummybox\vbox\bgroup
+\def\part{\egroup\part}%
+\def\node{\egroup\node}%
\ignorenodebye
}
@@ -9391,13 +9385,12 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\catcode`\^^M = 5 % in case we're inside an example
\normalturnoffactive % allow _ et al. in names
\makevalueexpandable
- % If the image is by itself, center it.
\ifvmode
\imagevmodetrue
\else \ifx\centersub\centerV
% for @center @image, we need a vbox so we can have our vertical space
\imagevmodetrue
- \vbox\bgroup % vbox has better behavior than vtop herev
+ \vbox\bgroup % vbox has better behavior than vtop here
\fi\fi
%
\ifimagevmode
@@ -9405,11 +9398,14 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Usually we'll have text after the image which will insert
% \parskip glue, so insert it here too to equalize the space
% above and below.
- \nobreak\vskip\parskip
- \nobreak
+ \vskip\parskip
+ %
+ % Place image in a \vtop for a top page margin that is (close to) correct,
+ % as \topskip glue is relative to the first baseline.
+ \vtop\bgroup\hrule height 0pt\vskip-\parskip
\fi
%
- % Leave vertical mode so that indentation from an enclosing
+ % Enter horizontal mode so that indentation from an enclosing
% environment such as @quotation is respected.
% However, if we're at the top level, we don't want the
% normal paragraph indentation.
@@ -9438,6 +9434,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi
%
\ifimagevmode
+ \egroup
\medskip % space after a standalone image
\fi
\ifx\centersub\centerV \egroup \fi
@@ -10898,6 +10895,9 @@ directory should work if nowhere else does.}
\DeclareUnicodeCharacter{1EF8}{\~Y}%
\DeclareUnicodeCharacter{1EF9}{\~y}%
%
+ % Exotic spaces
+ \DeclareUnicodeCharacter{2007}{\hphantom{0}}%
+ %
% Punctuation
\DeclareUnicodeCharacter{2013}{--}%
\DeclareUnicodeCharacter{2014}{---}%
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 3c159558600..2699ca92c12 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -50,13 +50,10 @@ This file documents @w{@value{tramp} @value{trampver}}, a remote file
editing package for Emacs.
@value{tramp} stands for ``Transparent Remote (file) Access, Multiple
-Protocol''. This package provides remote file editing, similar to
-Ange FTP@.
-
-The difference is that Ange FTP uses FTP to transfer files between the
-local and the remote host, whereas @value{tramp} uses a combination of
-@command{rsh} and @command{rcp} or other work-alike programs, such as
-@command{ssh}/@command{scp}.
+Protocol''. This package provides an easy, convenient, and consistent
+interface to editing remote files transparently, just as if they are
+local files. This extends to editing, version control, @code{dired},
+and more.
You can find the latest version of this document on the web at
@uref{@value{trampurl}}.
@@ -133,19 +130,21 @@ Configuring @value{tramp} for use
* Multi-hops:: Connecting to a remote host using multiple hops.
* Firewalls:: Passing firewalls.
* Customizing Methods:: Using Non-Standard Methods.
-* Customizing Completion:: Selecting config files for user/host name completion.
+* Customizing Completion:: Selecting config files for user/host name @c
+completion.
* Password handling:: Reusing passwords for several connections.
* Connection caching:: Reusing connection related information.
* Predefined connection information::
Setting own connection related information.
-* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
+* Remote programs:: How @value{tramp} finds and uses programs @c
+on the remote host.
* Remote shell setup:: Remote shell setup hints.
+* Ssh setup:: Ssh setup hints.
* FUSE setup:: @acronym{FUSE} setup hints.
* Android shell setup:: Android shell setup hints.
* Auto-save File Lock and Backup::
Auto-save, File Lock and Backup.
* Keeping files encrypted:: Protect remote files by encryption.
-* Windows setup hints:: Issues with Cygwin ssh.
Using @value{tramp}
@@ -155,6 +154,7 @@ Using @value{tramp}
@end ifset
* File name completion:: File name completion.
* Ad-hoc multi-hops:: Declaring multiple hops in the file name.
+* Home directories:: Expanding @file{~} to home directory.
* Remote processes:: Integration with other Emacs packages.
* Cleanup remote connections:: Cleanup remote connections.
* Renaming remote files:: Renaming remote files.
@@ -179,10 +179,11 @@ interface to remote files as if they are local files. @value{tramp}'s
transparency extends to editing, version control, and @code{dired}.
@value{tramp} can access remote hosts using any number of access
-methods, such as @command{rsh}, @command{rlogin}, @command{telnet},
-and related programs. If these programs can successfully pass
-@acronym{ASCII} characters, @value{tramp} can use them.
-@value{tramp} does not require or mandate 8-bit clean connections.
+methods, such as @command{ssh}, @command{rsh}, @command{rlogin},
+@command{telnet}, and related programs. If these programs can
+successfully pass @acronym{ASCII} characters, @value{tramp} can use
+them. @value{tramp} does not require or mandate 8-bit clean
+connections.
@value{tramp}'s most common access method is through @command{ssh}, a
more secure alternative to @command{ftp} and other older access
@@ -309,7 +310,7 @@ I hope this has provided you with a basic overview of what happens
behind the scenes when you open a file with @value{tramp}.
-@c For the end user
+@c For the end user.
@node Obtaining @value{tramp}
@chapter Obtaining @value{tramp}
@cindex obtaining @value{tramp}
@@ -523,7 +524,7 @@ performed on another host, it can be comnbined with a leading
connects first to the other host with non-administrative credentials,
and changes to administrative credentials on that host afterwards. In
a simple case, the syntax looks like
-@file{@value{prefix}ssh@value{postfixhop}user@@host|sudo@value{postfixhop}@value{postfix}/path/to/file}.
+@file{@trampfn{ssh@value{postfixhop}user@@host|sudo,,/path/to/file}}.
@xref{Ad-hoc multi-hops}.
@@ -683,19 +684,21 @@ may be used in your init file:
* Multi-hops:: Connecting to a remote host using multiple hops.
* Firewalls:: Passing firewalls.
* Customizing Methods:: Using Non-Standard Methods.
-* Customizing Completion:: Selecting config files for user/host name completion.
+* Customizing Completion:: Selecting config files for user/host name @c
+completion.
* Password handling:: Reusing passwords for several connections.
* Connection caching:: Reusing connection related information.
* Predefined connection information::
Setting own connection related information.
-* Remote programs:: How @value{tramp} finds and uses programs on the remote host.
+* Remote programs:: How @value{tramp} finds and uses programs @c
+on the remote host.
* Remote shell setup:: Remote shell setup hints.
+* Ssh setup:: Ssh setup hints.
* FUSE setup:: @acronym{FUSE} setup hints.
* Android shell setup:: Android shell setup hints.
* Auto-save File Lock and Backup::
Auto-save, File Lock and Backup.
* Keeping files encrypted:: Protect remote files by encryption.
-* Windows setup hints:: Issues with Cygwin ssh.
@end menu
@@ -1234,7 +1237,8 @@ be populated in your @command{Online Accounts} application outside Emacs.
Since Google Drive uses cryptic blob file names internally,
@value{tramp} works with the @code{display-name} of the files. This
could produce unexpected behavior in case two files in the same
-directory have the same @code{display-name}, such a situation must be avoided.
+directory have the same @code{display-name}, such a situation must be
+avoided.
@item @option{mtp}
@cindex method @option{mtp}
@@ -1448,7 +1452,7 @@ External methods might be more efficient for large files, but most
@value{tramp} users edit small files more often than large files.
Enable compression, @code{tramp-inline-compress-start-size}, for a
-performance boost for large files.
+performance boost for large files with inline methods.
Since @command{ssh} has become the most common method of remote host
access and it has the most reasonable security protocols, use
@@ -1474,6 +1478,10 @@ For editing large files, @option{scp} is faster than @option{ssh}.
@option{pscp} is faster than @option{plink}. But this speed
improvement is not always true.
+When copying large files between two different remote hosts via
+@option{scp}, set @code{tramp-use-scp-direct-remote-copying} to
+non-@code{nil}.
+
@node Default User
@section Selecting a default user
@@ -1654,7 +1662,7 @@ local one, first connect via @command{ssh}, and then apply
(add-to-list 'tramp-default-proxies-alist
'(nil "\\`root\\'" "@trampfn{ssh,%h,}"))
(add-to-list 'tramp-default-proxies-alist
- '((regexp-quote (system-name)) nil nil))
+ `(,(regexp-quote (system-name)) nil nil))
@end group
@end lisp
@end defopt
@@ -1689,8 +1697,8 @@ Sometimes, it is not possible to reach a remote host directly. A
firewall might be in the way, which could be passed via a proxy
server.
-Both ssh and PuTTY support such proxy settings, using an HTTP tunnel
-via the @command{CONNECT} command (conforming to RFC 2616, 2817
+Both OpenSSH and PuTTY support such proxy settings, using an HTTP
+tunnel via the @command{CONNECT} command (conforming to RFC 2616, 2817
specifications). Proxy servers using HTTP 1.1 or later protocol
support this command.
@@ -1799,12 +1807,23 @@ Access of a hadoop/hdfs file system. A file is accessed via
the user that you want to use, and @samp{node} is the name of the
hadoop server.
+@item tramp-nspawn
+@cindex method @option{nspawn}
+@cindex @option{nspawn} method
+Access to environments provided by systemd-nspawn. A file is accessed
+via @file{@trampfn{nspawn,user@@container,/path/to/file}}, where
+@samp{user} is the (optional) user that you want to use, and
+@samp{container} is the container to connect to. systemd-nspawn and
+its container utilities often require super user access to run, use
+multi-hop file names with @option{doas} or @option{sudo} to raise your
+privileges.
+
@item vagrant-tramp
@cindex method @option{vagrant}
@cindex @option{vagrant} method
Convenience method to access vagrant boxes. It is often used in
multi-hop file names like
-@file{@value{prefix}vagrant@value{postfixhop}box|sudo@value{postfixhop}box@value{postfix}/path/to/file},
+@file{@trampfn{vagrant@value{postfixhop}box|sudo,box,/path/to/file}},
where @samp{box} is the name of the vagrant box.
@end table
@@ -1860,29 +1879,25 @@ Example:
The following predefined functions parsing configuration files exist:
-@table @asis
+@ftable @asis
@item @code{tramp-parse-rhosts}
-@findex tramp-parse-rhosts
This function parses files which are syntactical equivalent to
@file{~/.rhosts}. It returns both host names and user names, if
specified.
@item @code{tramp-parse-shosts}
-@findex tramp-parse-shosts
This function parses files which are syntactical equivalent to
@file{~/.ssh/known_hosts}. Since there are no user names specified
in such files, it can return host names only.
@item @code{tramp-parse-sconfig}
-@findex tramp-parse-sconfig
This function returns the host nicknames defined by @option{Host}
entries in @file{~/.ssh/config} style files.
@item @code{tramp-parse-shostkeys}
-@findex tramp-parse-shostkeys
SSH2 parsing of directories @file{/etc/ssh2/hostkeys/*} and
@file{~/ssh2/hostkeys/*}. Hosts are coded in file names
@@ -1890,7 +1905,6 @@ SSH2 parsing of directories @file{/etc/ssh2/hostkeys/*} and
are always @code{nil}.
@item @code{tramp-parse-sknownhosts}
-@findex tramp-parse-sknownhosts
Another SSH2 style parsing of directories like
@file{/etc/ssh2/knownhosts/*} and @file{~/ssh2/knownhosts/*}. This
@@ -1898,26 +1912,22 @@ case, hosts names are coded in file names
@file{@var{host-name}.@var{algorithm}.pub}. User names are always @code{nil}.
@item @code{tramp-parse-hosts}
-@findex tramp-parse-hosts
A function dedicated to @file{/etc/hosts} for host names.
@item @code{tramp-parse-passwd}
-@findex tramp-parse-passwd
A function which parses @file{/etc/passwd} for user names.
@item @code{tramp-parse-etc-group}
-@findex tramp-parse-etc-group
A function which parses @file{/etc/group} for group names.
@item @code{tramp-parse-netrc}
-@findex tramp-parse-netrc
A function which parses @file{~/.netrc} and @file{~/.authinfo}-style files.
-@end table
+@end ftable
To keep a custom file with custom data in a custom structure, a custom
function has to be provided. This function must meet the following
@@ -1977,6 +1987,20 @@ file name syntax, must be appended to the machine and login items:
machine melancholia#4711 port davs login daniel%BIZARRE password geheim
@end example
+For the methods @option{doas}, @option{sudo} and @option{sudoedit} the
+password of the user requesting the connection is needed, and not the
+password of the target user. If these connections happen on the local
+host, an entry with the local user and local host is used:
+
+@example
+machine @var{HOST} port sudo login @var{USER} password secret
+@end example
+
+@var{USER} and @var{HOST} are the strings returned by
+@code{(user-login-name)} and @code{(system-name)}. If one of these
+methods is connected via a multi hop (@pxref{Multi-hops}), the
+credentials of the previous hop are used.
+
@vindex auth-source-save-behavior
If no proper entry exists, the password is read
interactively. After successful login (verification of the password),
@@ -2142,6 +2166,14 @@ reestablished. A value of @code{nil} disables this feature. Most of
the methods do not set this property except the @option{sudo} and
@option{doas} methods, which use predefined values.
+@item @t{"~"}@*
+@t{"~user"}
+
+This is the home directory on the remote host. Setting this
+connection property helps especially for methods which cannot expand
+to a remote home directory, like @option{adb}, @option{rclone} and
+@option{sshfs}. @ref{Home directories} for an example.
+
@item @t{"tmpdir"}
The temporary directory on the remote host. If not specified, the
@@ -2606,6 +2638,246 @@ where @samp{192.168.0.1} is the remote host IP address
@end table
+@node Ssh setup
+@section Ssh setup hints
+
+The most common @value{tramp} connection family is based on either
+@command{ssh} or @command{scp} of OpenSSH, or @command{plink} or
+@command{pscp} of PuTTY on MS Windows. In the following, some
+configuration recommendations are given.
+
+
+@subsection Using ssh config include for host name completion
+
+@vindex Include@r{, ssh option}
+@findex tramp-set-completion-function
+@findex tramp-get-completion-function
+OpenSSH configuration files can use an @option{Include} option for
+further configuration files. Default @value{tramp} host name
+completion ignores this option. However, you can configure this
+yourself.
+
+Given, your @file{~/.ssh/config} file contains the following option:
+
+@example
+Include ~/.ssh/conf.d/*
+@end example
+
+The following code snippet in your @file{.emacs} uses all files in
+that directory for host name completion:
+
+@lisp
+@group
+(tramp-set-completion-function
+ "ssh" (append (tramp-get-completion-function "ssh")
+ (mapcar (lambda (file) `(tramp-parse-sconfig ,file))
+ (directory-files
+ "~/.ssh/conf.d/"
+ 'full directory-files-no-dot-files-regexp))))
+@end group
+@end lisp
+
+This code snippet does it for the @option{ssh} method. If you replace
+@t{"ssh"} by @t{"scp"}, it does it also for that method (or any other
+method you like).
+
+
+@subsection Detection of session hangouts
+
+@vindex ServerAliveInterval@r{, ssh option}
+@vindex ServerAliveCountMax@r{, ssh option}
+@command{ssh} sessions on the local host hang when the network is
+down. @value{tramp} cannot safely detect such hangs. OpenSSH can be
+configured to kill such hangs with the following settings in
+@file{~/.ssh/config}:
+
+@example
+@group
+Host *
+ ServerAliveInterval 5
+ ServerAliveCountMax 2
+@end group
+@end example
+
+The corresponding PuTTY configuration is in the @option{Connection}
+entry, @option{Seconds between keepalives} option. Set this to 5.
+There is no counter which could be set.
+
+
+@subsection Using ssh connection sharing
+
+@vindex ControlPath@r{, ssh option}
+@vindex ControlPersist@r{, ssh option}
+@value{tramp} uses the @option{ControlMaster=auto} OpenSSH option by
+default, if possible. However, it overwrites @option{ControlPath}
+settings when initiating @command{ssh} sessions. @value{tramp} does
+this to fend off a stall if a master session opened outside the Emacs
+session is no longer open. That is why @value{tramp} prompts for the
+password again even if there is an @command{ssh} already open.
+
+@vindex tramp-ssh-controlmaster-options
+Some OpenSSH versions support a @option{ControlPersist} option, which
+allows you to set the @option{ControlPath} provided the variable
+@code{tramp-ssh-controlmaster-options} is customized as follows:
+
+@lisp
+@group
+(customize-set-variable
+ 'tramp-ssh-controlmaster-options
+ (concat
+ "-o ControlPath=/tmp/ssh-ControlPath-%%r@@%%h:%%p "
+ "-o ControlMaster=auto -o ControlPersist=yes"))
+@end group
+@end lisp
+
+Note how @samp{%r}, @samp{%h} and @samp{%p} must be encoded as
+@samp{%%r}, @samp{%%h} and @samp{%%p}.
+
+@vindex tramp-use-ssh-controlmaster-options
+If the @file{~/.ssh/config} file is configured appropriately for the
+above behavior, then any changes to @command{ssh} can be suppressed
+with this @code{nil} setting:
+
+@lisp
+(customize-set-variable 'tramp-use-ssh-controlmaster-options nil)
+@end lisp
+
+@vindex ProxyCommand@r{, ssh option}
+@vindex ProxyJump@r{, ssh option}
+This should also be set to @code{nil} if you use the
+@option{ProxyCommand} or @option{ProxyJump} options in your
+@command{ssh} configuration.
+
+In order to use the @option{ControlMaster} option, @value{tramp} must
+check whether the @command{ssh} client supports this option. This is
+only possible on the local host, for the first hop. @value{tramp}
+does not use this option on proxy hosts, therefore.
+
+If you want to use this option also for the other hops, you must
+configure @file{~/.ssh/config} on the proxy host:
+
+@example
+@group
+Host *
+ ControlMaster auto
+ ControlPath tramp.%C
+ ControlPersist no
+@end group
+@end example
+
+Check the @samp{ssh_config(5)} man page whether these options are
+supported on your proxy host.
+
+On MS Windows, @code{tramp-use-ssh-controlmaster-options} is set to
+@code{nil} by default, because the MS Windows and MSYS2
+implementations of @command{OpenSSH} do not support this option properly.
+
+In PuTTY, you can achieve connection sharing in the @option{Connection/SSH}
+entry, enabling the @option{Share SSH connections if possible} option.
+
+
+@subsection Configure direct copying between two remote servers
+
+@vindex tramp-use-scp-direct-remote-copying
+@value{tramp} uses a temporary local copy when copying two files
+between different remote hosts via external methods. This behavior is
+due to authentication problems @value{tramp} cannot handle
+sufficiently. However, for @option{scp} connections this can be
+changed. When a file shall be copied between two different remote
+hosts @samp{source} and @samp{target}, and
+
+@itemize @minus
+@item
+Variable @code{tramp-use-scp-direct-remote-copying} is non-@code{nil},
+
+@item
+Remote host @samp{source} doesn't use the @option{RemoteCommand}
+option in @file{~/.ssh/config},
+
+@item
+Remote host @samp{target} shows the same host key when seen from the
+local host and from host @samp{source}, and
+
+@item
+@command{scp} running on host @samp{source} can authenticate to host
+@samp{target} without requiring a password,
+@end itemize
+
+@noindent
+@value{tramp} applies direct remote copying between hosts
+@samp{source} and @samp{target} like
+
+@example
+scp -p -T -R -q -r source:/path/to/file target:/path/to/another/file
+@end example
+
+This protects also your local temporary directory from overrun when
+copying large files.
+
+If these conditions do not apply, and
+@code{tramp-use-scp-direct-remote-copying} is non-@code{nil}, the
+option @samp{-3} is used instead of @samp{-R}.
+
+@c FIXME
+When @value{tramp} uses direct remote copying, password caches are not
+consulted.
+
+
+@subsection Issues with Cygwin ssh
+@cindex cygwin, issues
+
+This section is incomplete. Please share your solutions.
+
+@cindex method @option{sshx} with cygwin
+@cindex @option{sshx} method with cygwin
+
+Cygwin's @command{ssh} works only with a Cygwin version of Emacs. To
+check for compatibility: type @kbd{M-x eshell @key{RET}}, and start
+@kbd{ssh test.host @key{RET}}. Incompatibilities trigger this
+message:
+
+@example
+Pseudo-terminal will not be allocated because stdin is not a terminal.
+@end example
+
+Some older versions of Cygwin's @command{ssh} work with the
+@option{sshx} access method. Consult Cygwin's FAQ at
+@uref{https://cygwin.com/faq/} for details.
+
+@cindex cygwin and @command{fakecygpty}
+@cindex @command{fakecygpty} and cygwin
+
+On @uref{https://www.emacswiki.org/emacs/SshWithNTEmacs, the Emacs
+Wiki} it is explained how to use the helper program
+@command{fakecygpty} to fix this problem.
+
+@cindex method @option{scpx} with cygwin
+@cindex @option{scpx} method with cygwin
+
+When using the @option{scpx} access method, Emacs may call
+@command{scp} with MS Windows file naming, such as @file{c:/foo}. But
+the version of @command{scp} that is installed with Cygwin does not
+know about MS Windows file naming, which causes it to incorrectly look
+for a host named @samp{c}.
+
+A workaround: write a wrapper script for @option{scp} to convert
+Windows file names to Cygwin file names.
+
+@cindex cygwin and @command{ssh-agent}
+@cindex @env{SSH_AUTH_SOCK} and emacs on ms windows
+@vindex SSH_AUTH_SOCK@r{, environment variable}
+
+When using the @command{ssh-agent} on MS Windows for password-less
+interaction, @option{ssh} methods depend on the environment variable
+@env{SSH_AUTH_SOCK}. But this variable is not set when Emacs is
+started from a Desktop shortcut and authentication fails.
+
+One workaround is to use an MS Windows based SSH Agent, such as
+@command{Pageant}. It is part of the PuTTY Suite of tools.
+
+The fallback is to start Emacs from a shell.
+
+
@node FUSE setup
@section @acronym{FUSE} setup hints
@@ -2665,6 +2937,7 @@ Additionally, it declares also the arguments for running remote
processes, using the @command{ssh} command. These don't need to be
changed.
+
@node Android shell setup
@section Android shell setup hints
@cindex android shell setup for ssh
@@ -2828,10 +3101,10 @@ Example:
The backup file name of
@file{@trampfn{su,root@@localhost,/etc/secretfile}} would be
@ifset unified
-@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/!su:root@@localhost:!etc!secretfile~}}
+@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/!su:root@@localhost:!etc!secretfile~}}.
@end ifset
@ifset separate
-@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/![su!root@@localhost]!etc!secretfile~}}
+@file{@trampfn{su,root@@localhost,~/.emacs.d/backups/![su!root@@localhost]!etc!secretfile~}}.
@end ifset
@vindex auto-save-file-name-transforms
@@ -2849,6 +3122,14 @@ auto-saved files to the same directory as the original file.
Alternatively, set the user option @code{tramp-auto-save-directory}
to direct all auto saves to that location.
+@c Since Emacs 29.
+@vindex remote-file-name-inhibit-auto-save-visited
+An alternative to @code{auto-save-mode} is
+@code{auto-save-visited-mode}. In this mode, auto-saving is identical
+to explicit saving. If you want to disable this behavior for remote
+files, set user option
+@code{remote-file-name-inhibit-auto-save-visited} to non-@code{nil}.
+
@vindex lock-file-name-transforms
And still more issues to handle. Since @w{Emacs 28}, file locks use a
similar user option as auto-save files, called
@@ -2857,7 +3138,7 @@ similar user option as auto-save files, called
original file.
If you change @code{lock-file-name-transforms} in order to keep file
-locks for remote files somewhere else, you will loose Emacs' feature
+locks for remote files somewhere else, you will lose Emacs's feature
to warn you, if a file is changed in parallel from different Emacs
sessions, or via different remote connections. Be careful with such
settings.
@@ -2926,7 +3207,7 @@ you, for example, mark the remote directory
@file{@trampfn{nextcloud,user@@host,/path/to/dir}} for encryption, the
configuration file is saved as
@file{tramp-%2Fnextcloud%3Auser%40host%3A%2Fpath%2Fto%2Fdir%2F.encfs6.xml}
-in @code{user-emacs-directory}. Do not loose this file and the
+in @code{user-emacs-directory}. Do not lose this file and the
corresponding password; otherwise there is no way to decrypt your
encrypted files.
@@ -2985,62 +3266,6 @@ subdirectories will remain encrypted.
@end deffn
-@node Windows setup hints
-@section Issues with Cygwin ssh
-@cindex cygwin, issues
-
-This section is incomplete. Please share your solutions.
-
-@cindex method @option{sshx} with cygwin
-@cindex @option{sshx} method with cygwin
-
-Cygwin's @command{ssh} works only with a Cygwin version of Emacs. To
-check for compatibility: type @kbd{M-x eshell @key{RET}}, and start
-@kbd{ssh test.host @key{RET}}. Incompatibilities trigger this
-message:
-
-@example
-Pseudo-terminal will not be allocated because stdin is not a terminal.
-@end example
-
-Some older versions of Cygwin's @command{ssh} work with the
-@option{sshx} access method. Consult Cygwin's FAQ at
-@uref{https://cygwin.com/faq/} for details.
-
-@cindex cygwin and @command{fakecygpty}
-@cindex @command{fakecygpty} and cygwin
-
-On @uref{https://www.emacswiki.org/emacs/SshWithNTEmacs, the Emacs
-Wiki} it is explained how to use the helper program
-@command{fakecygpty} to fix this problem.
-
-@cindex method @option{scpx} with cygwin
-@cindex @option{scpx} method with cygwin
-
-When using the @option{scpx} access method, Emacs may call
-@command{scp} with MS Windows file naming, such as @file{c:/foo}. But
-the version of @command{scp} that is installed with Cygwin does not
-know about MS Windows file naming, which causes it to incorrectly look
-for a host named @samp{c}.
-
-A workaround: write a wrapper script for @option{scp} to convert
-Windows file names to Cygwin file names.
-
-@cindex cygwin and @command{ssh-agent}
-@cindex @env{SSH_AUTH_SOCK} and emacs on ms windows
-@vindex SSH_AUTH_SOCK@r{, environment variable}
-
-When using the @command{ssh-agent} on MS Windows for password-less
-interaction, @option{ssh} methods depend on the environment variable
-@env{SSH_AUTH_SOCK}. But this variable is not set when Emacs is
-started from a Desktop shortcut and authentication fails.
-
-One workaround is to use an MS Windows based SSH Agent, such as
-Pageant. It is part of the Putty Suite of tools.
-
-The fallback is to start Emacs from a shell.
-
-
@node Usage
@chapter Using @value{tramp}
@cindex using @value{tramp}
@@ -3069,6 +3294,7 @@ is a feature of Emacs that may cause missed prompts when using
@end ifset
* File name completion:: File name completion.
* Ad-hoc multi-hops:: Declaring multiple hops in the file name.
+* Home directories:: Expanding @file{~} to home directory.
* Remote processes:: Integration with other Emacs packages.
* Cleanup remote connections:: Cleanup remote connections.
* Renaming remote files:: Renaming remote files.
@@ -3084,6 +3310,7 @@ is a feature of Emacs that may cause missed prompts when using
@file{@trampfn{method,host,/path/to/file}} opens file @var{/path/to/file}
on the remote host @var{host}, using the method @var{method}.
+@c We cannot use @trampfn{} in @item.
@table @file
@item @value{prefix}ssh@value{postfixhop}melancholia@value{postfix}.emacs
For the file @file{.emacs} located in the home directory, on the host
@@ -3115,12 +3342,9 @@ brackets @file{@value{ipv6prefix}} and @file{@value{ipv6postfix}}.
@end ifset
By default, @value{tramp} will use the current local user name as the
-remote user name for log in to the remote host. Specifying a different
-name using the proper syntax will override this default behavior:
-
-@example
-@trampfn{method,user@@host,path/to/file}
-@end example
+remote user name for log in to the remote host. Specifying a
+different name using the proper syntax will override this default
+behavior: @file{@trampfn{method,user@@host,path/to/file}}.
@file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file
@file{.emacs} in @code{daniel}'s home directory on the host,
@@ -3316,8 +3540,9 @@ remote host name and file name. For example, hopping over a single
proxy @samp{bird@@bastion} to a remote file on @samp{you@@remotehost}:
@example
-@c @kbd{C-x C-f @trampfn{ssh@value{postfixhop}bird@@bastion|ssh,you,remotehost,/path} @key{RET}}
-@kbd{C-x C-f @value{prefix}ssh@value{postfixhop}bird@@bastion|ssh@value{postfixhop}you@@remotehost@value{postfix}/path @key{RET}}
+@c @kbd{C-x C-f @trampfn{ssh@value{postfixhop}bird@@bastion|ssh,you@@remotehost,/path} @key{RET}}
+@kbd{C-x C-f @value{prefix}ssh@value{postfixhop}bird@@bastion|@c
+ssh@value{postfixhop}you@@remotehost@value{postfix}/path @key{RET}}
@end example
Each involved method must be an inline method (@pxref{Inline methods}).
@@ -3345,12 +3570,72 @@ Ad-hoc proxies can take patterns @code{%h} or @code{%u} like in
@code{tramp-default-proxies-alist}. The following file name expands
to user @samp{root} on host @samp{remotehost}, starting with an
@option{ssh} session on host @samp{remotehost}:
-@samp{@value{prefix}ssh@value{postfixhop}%h|su@value{postfixhop}remotehost@value{postfix}}.
+@samp{@trampfn{ssh@value{postfixhop}%h|su,remotehost,}}.
-On the other hand, if a trailing hop does not specify a host name,
-the host name of the previous hop is reused. Therefore, the following
+On the other hand, if a trailing hop does not specify a host name, the
+host name of the previous hop is reused. Therefore, the following
file name is equivalent to the previous example:
-@samp{@value{prefix}ssh@value{postfixhop}remotehost|su@value{postfixhop}@value{postfix}}.
+@samp{@trampfn{ssh@value{postfixhop}remotehost|su,,}}.
+
+
+@node Home directories
+@section Expanding @file{~} to home directory
+
+Home directories on remote hosts can be typed as tilde @file{~}. If
+possible, they are expanded to the remote user's home directory on the
+remote host. Example:
+
+@example
+@group
+@trampfn{ssh,user@@host,~}
+@result{} @trampfn{ssh,user@@host,/home/user}
+@end group
+@end example
+
+This works in general for @option{ssh}-like methods, and for
+@option{sudoedit}. These methods allow also the home directory
+expansion for another user, like
+
+@example
+@group
+@trampfn{sudoedit,,~otheruser}
+@result{} @trampfn{sudoedit,root@@localhost,/home/otheruser}
+@end group
+@end example
+
+For other methods, a home directory can be expanded only if supported.
+This happens for example for the @option{sftp} method. Methods, which
+require a share directory in the remote file name (@option{afp},
+@option{smb}), use the value of this share directory as home
+directory:
+
+@example
+@group
+@trampfn{smb,user@@host,~}
+@result{} @trampfn{smb,user@@host,/share}
+@end group
+@end example
+
+Since Tramp cannot know in advance which share directory is intended
+to use, this expansion can be applied only when a share directory has
+been used already.
+
+The methods @option{adb}, @option{rclone} and @option{sshfs} do not
+support home directory expansion at all. However, @value{tramp} keeps
+the home directory in the cache. Therefore, those methods could be
+configured to expand a home directory via a connection property,
+@xref{Predefined connection information}. Example:
+
+@lisp
+@group
+(add-to-list 'tramp-connection-properties
+ (list (regexp-quote "@trampfn{sshfs,user@@randomhost.your.domain,}")
+ "~user" "/home/user"))
+@end group
+@end lisp
+
+When your remote file name does not contain a @samp{user} part, the
+connection property @t{"~"} must be used instead.
@node Remote processes
@@ -3767,6 +4052,127 @@ using the @code{:connection-type} keyword. If this keyword is not
used, the value of @code{process-connection-type} is applied instead.
+@subsection Process properties of asynchronous remote processes
+@cindex Asynchronous remote processes
+
+When available, @value{tramp} adds process properties to process
+objects of asynchronous properties. However, it is not guaranteed
+that all these properties are set.
+
+@itemize
+@item @code{remote-tty}
+
+This is the name of the terminal a @var{process} uses on the remote
+host, i.e., it reads and writes on.
+
+@item @code{remote-pid}
+
+The process id of the command executed on the remote host. This is
+used when sending signals remotely.
+
+@item @code{remote-command}
+
+The remote command which has been invoked via @code{make-process} or
+@code{start-file-process}, a list of strings (program and its
+arguments). This does not show the additional shell sugar
+@value{tramp} makes around the commands, in order to see this you must
+inspect @value{tramp} @ref{Traces and Profiles, traces}.
+@end itemize
+
+@findex list-system-processes
+@findex process-attributes
+The functions @code{list-system-processes} and
+@code{process-attributes} return information about system processes on
+the respective remote host. In order to retrieve this information,
+they use the command @command{ps}, driven by the following constants:
+
+@defvr Constant tramp-process-attributes-ps-args
+This is a list of arguments (strings) @command{ps} is called with.
+The default value is appropriate for GNU/Linux remote hosts.
+@end defvr
+
+@defvr Constant tramp-process-attributes-ps-format
+This is a list of cons cells @code{(@var{key} . @var{type})} for
+interpretation of the @command{ps} output. @var{key} is a key used in
+the @code{process-attributes} output plus the key @code{pid}, and
+@var{type} is the respective value returned by @command{ps}. It can
+be
+
+
+@multitable {@bullet{} @code{numberp}} {--- a string of @var{number} width, could contain spaces}
+@item @bullet{} @code{numberp} @tab --- a number
+@item @bullet{} @code{stringp} @tab --- a string without spaces
+@item @bullet{} @var{number}
+@tab --- a string of @var{number} width, could contain spaces
+@item @bullet{} @code{nil} @tab --- a string until end of line
+@end multitable
+
+The default value is appropriate for GNU/Linux remote hosts.
+@end defvr
+
+If, for example, @code{tramp-process-attributes-ps-args} is declared
+as @code{("-eww" "-o" "pid,euid,euser,egid,egroup,comm:40,state")},
+the output of the respective @command{ps} command would look like
+
+@smallexample
+@group
+ PID EUID EUSER EGID EGROUP COMMAND S
+ 1 0 root 0 root systemd S
+ 1610 0 root 0 root NFSv4 callback S
+ @dots{}
+@end group
+@end smallexample
+
+The corresponding @code{tramp-process-attributes-ps-format} has the value
+
+@smallexample
+@group
+@code{((pid . numberp) (euid . numberp) (user . stringp)
+ (egid . numberp) (group . stringp) (comm . 40) (state . stringp))}
+@end group
+@end smallexample
+
+@vindex tramp-adb-connection-local-default-ps-profile
+@vindex tramp-adb-connection-local-default-ps-variables
+@vindex tramp-connection-local-bsd-ps-profile
+@vindex tramp-connection-local-bsd-ps-variables
+@vindex tramp-connection-local-busybox-ps-profile
+@vindex tramp-connection-local-busybox-ps-variables
+@vindex tramp-connection-local-darwin-ps-profile
+@vindex tramp-connection-local-darwin-ps-variables
+The default values for @code{tramp-process-attributes-ps-args} and
+@code{tramp-process-attributes-ps-format} can be overwritten by
+connection-local variables.
+@ifinfo
+@xref{Connection Variables, , , emacs}.
+@end ifinfo
+This is already done by @value{tramp} for the @option{adb} method, see
+@code{tramp-adb-connection-local-default-ps-profile} and
+@code{tramp-adb-connection-local-default-ps-variables}.
+
+There are three further predefined sets of connection-local variables
+for remote BSD systems, for remote macOS systems, and for a remote
+@command{ps} command implemented with @command{busybox}. These are
+called @code{tramp-connection-local-*-ps-profile} and
+@code{tramp-connection-local-*-ps-variables}. Use them like
+
+@lisp
+@group
+(connection-local-set-profiles
+ '(:application tramp :machine "mybsdhost")
+ 'tramp-connection-local-bsd-ps-profile)
+@end group
+@end lisp
+
+@cindex proced
+@vindex proced-show-remote-processes
+If you want to see a listing of remote system processes when calling
+@code{proced}, set user option @code{proced-show-remote-processes} to
+non-@code{nil}, or invoke that command with a negative argument like
+@kbd{C-u - M-x proced @key{RET}} when your buffer has a remote
+@code{default-directory}.
+
+
@anchor{Improving performance of asynchronous remote processes}
@subsection Improving performance of asynchronous remote processes
@cindex Asynchronous remote processes
@@ -3804,8 +4210,8 @@ Furthermore, this approach has the following limitations:
@itemize
@item
-It works only for connection methods defined in @file{tramp-sh.el} and
-@file{tramp-adb.el}.
+It works only for connection methods defined in @file{tramp-adb.el},
+@file{tramp-sh.el} and @file{tramp-sshfs.el}.
@item
It does not support interactive user authentication. With
@@ -3971,7 +4377,9 @@ would trigger renaming of buffer file names on @samp{badhost} to
@samp{goodhost}, including changing the directory name.
@lisp
-("@trampfn{ssh,.+\\\\.company\\\\.org,}" . "@value{prefix}ssh@value{postfixhop}multi.hop|ssh@value{postfixhop}%h@value{postfix}")
+("@trampfn{ssh,.+\\\\.company\\\\.org,}" @c
+. "@value{prefix}ssh@value{postfixhop}multi.hop|@c
+ssh@value{postfixhop}%h@value{postfix}")
@end lisp
routes all connections to a host in @samp{company.org} via
@@ -4006,8 +4414,10 @@ methods}. Internally, file archives are mounted via the
@acronym{GVFS} @option{archive} method.
A file archive is a regular file of kind @file{/path/to/dir/file.EXT}.
-The extension @samp{.EXT} identifies the type of the file archive. A
-file inside a file archive, called archive file name, has the name
+The extension @samp{.EXT} identifies the type of the file archive. To
+examine the contents of an archive with Dired, open file name as if it
+were a directory (i.e., open @file{/path/to/dir/file.EXT/}). A file
+inside a file archive, called archive file name, has the name
@file{/path/to/dir/file.EXT/dir/file}.
Most of the @ref{Magic File Names, , magic file name operations,
@@ -4074,6 +4484,11 @@ HP-UX SD depots
@cindex @file{depot} file archive suffix
@cindex file archive suffix @file{depot}
+@item @samp{.epub} ---
+Electronic publications
+@cindex @file{epub} file archive suffix
+@cindex file archive suffix @file{epub}
+
@item @samp{.exe} ---
Self extracting Microsoft Windows EXE files
@cindex @file{exe} file archive suffix
@@ -4231,7 +4646,8 @@ It is even possible to access file archives in file archives, as
(progn
(url-handler-mode 1)
(find-file
- "https://ftp.debian.org/debian/pool/main/c/coreutils/coreutils_8.28-1_amd64.deb/control.tar.gz/control"))
+ "https://ftp.debian.org/debian/pool/main/c/coreutils/\
+coreutils_8.28-1_amd64.deb/control.tar.gz/control"))
@end group
@end lisp
@@ -4333,6 +4749,20 @@ there.
@itemize @bullet
@item
+What is the official name - ``Tramp'' or ``@value{tramp}''?
+
+The official name is ``Tramp''. This is used in comments, docstrings,
+and everywhere speaking about @value{tramp}.
+
+However, for historical reasons this is formatted as ``@@sc@{Tramp@}''
+in the @value{tramp} manual.
+@ifinfo
+@pxref{Smallcaps, , , texinfo}.
+@end ifinfo
+So it looks different there.
+
+
+@item
Where is the latest @value{tramp}?
@value{tramp} is available at the GNU URL:
@@ -4538,97 +4968,6 @@ In order to disable those optimizations, set user option
@item
-@value{tramp} does not recognize if a @command{ssh} session hangs
-
-@vindex ServerAliveInterval@r{, ssh option}
-@command{ssh} sessions on the local host hang when the network is
-down. @value{tramp} cannot safely detect such hangs. The network
-configuration for @command{ssh} can be configured to kill such hangs
-with the following command in the @file{~/.ssh/config}:
-
-@example
-@group
-Host *
- ServerAliveInterval 5
-@end group
-@end example
-
-
-@item
-@value{tramp} does not use default @command{ssh} @option{ControlPath}
-
-@vindex ControlPath@r{, ssh option}
-@vindex ControlPersist@r{, ssh option}
-@value{tramp} overwrites @option{ControlPath} settings when initiating
-@command{ssh} sessions. @value{tramp} does this to fend off a stall
-if a master session opened outside the Emacs session is no longer
-open. That is why @value{tramp} prompts for the password again even
-if there is an @command{ssh} already open.
-
-@vindex tramp-ssh-controlmaster-options
-Some @command{ssh} versions support a @option{ControlPersist} option,
-which allows you to set the @option{ControlPath} provided the variable
-@code{tramp-ssh-controlmaster-options} is customized as follows:
-
-@lisp
-@group
-(customize-set-variable
- 'tramp-ssh-controlmaster-options
- (concat
- "-o ControlPath=/tmp/ssh-ControlPath-%%r@@%%h:%%p "
- "-o ControlMaster=auto -o ControlPersist=yes"))
-@end group
-@end lisp
-
-Note how @samp{%r}, @samp{%h} and @samp{%p} must be encoded as
-@samp{%%r}, @samp{%%h} and @samp{%%p}.
-
-@vindex tramp-use-ssh-controlmaster-options
-If the @file{~/.ssh/config} file is configured appropriately for the
-above behavior, then any changes to @command{ssh} can be suppressed
-with this @code{nil} setting:
-
-@lisp
-(customize-set-variable 'tramp-use-ssh-controlmaster-options nil)
-@end lisp
-
-@vindex ProxyCommand@r{, ssh option}
-@vindex ProxyJump@r{, ssh option}
-This should also be set to @code{nil} if you use the
-@option{ProxyCommand} or @option{ProxyJump} options in your
-@command{ssh} configuration.
-
-On MS Windows, @code{tramp-use-ssh-controlmaster-options} is set to
-@code{nil} by default, because the MS Windows and MSYS2
-implementations of @command{OpenSSH} do not support this option properly.
-
-
-@item
-On multi-hop connections, @value{tramp} does not use @command{ssh}
-@option{ControlMaster}
-
-In order to use the @option{ControlMaster} option, @value{tramp} must
-check whether the @command{ssh} client supports this option. This is
-only possible on the local host, for the first hop. @value{tramp}
-does not use this option on proxy hosts.
-
-If you want to use this option also for the other hops, you must
-configure @file{~/.ssh/config} on the proxy host:
-
-@example
-@group
-Host *
- ControlMaster auto
- ControlPath tramp.%C
- ControlPersist no
-@end group
-@end example
-
-Check the @samp{ssh_config(5)} man page whether these options are
-supported on your proxy host.
-
-
-@item
Does @value{tramp} support @acronym{SSH} security keys?
Yes. @command{OpenSSH} has added support for @acronym{FIDO} hardware
@@ -4821,6 +5160,26 @@ be restored by moving them manually from
@item
+How to identify temporary files produced by @value{tramp}?
+
+@vindex tramp-temp-name-prefix
+Temporary files are kept in your @code{temporary-file-directory}
+directory, which is often @file{/tmp/}. By default, they have the
+file name prefix @t{"tramp."}. If you want to change this prefix, for
+example because you want to identify temporary files produced by
+@code{file-local-copy} in your package, you can bind the variable
+@code{tramp-temp-name-prefix} temporarily:
+
+@example
+@group
+(let ((tramp-temp-name-prefix "my-prefix."))
+ (file-local-copy "@trampfn{ssh,,.emacs}"))
+@result{} "/tmp/my-prefix.HDfgDZ"
+@end group
+@end example
+
+
+@item
How to shorten long file names when typing in @value{tramp}?
Adapt several of these approaches to reduce typing. If the full name
@@ -4972,13 +5331,6 @@ minibuffer:
(before my-minibuffer-complete activate)
(expand-abbrev))
@end group
-
-@group
-;; If you use partial-completion-mode
-(defadvice PC-do-completion
- (before my-PC-do-completion activate)
- (expand-abbrev))
-@end group
@end lisp
The reduced typing: @kbd{C-x C-f xy @key{TAB}}.
@@ -5075,7 +5427,8 @@ Why saved multi-hop file names do not work in a new Emacs session?
When saving ad-hoc multi-hop @value{tramp} file names (@pxref{Ad-hoc
multi-hops}) via bookmarks, recent files, filecache, bbdb, or another
package, use the full ad-hoc file name including all hops, like
-@file{@trampfn{ssh,bird@@bastion|ssh@value{postfixhop}news.my.domain,/opt/news/etc}}.
+@file{@trampfn{ssh,bird@@bastion|ssh@value{postfixhop}@c
+news.my.domain,/opt/news/etc}}.
Alternatively, when saving abbreviated multi-hop file names
@file{@trampfn{ssh,news@@news.my.domain,/opt/news/etc}}, the user
@@ -5325,10 +5678,19 @@ local host's root directory as @file{/ssh:example.com:}.
To unload @value{tramp}, type @kbd{M-x tramp-unload-tramp @key{RET}}.
Unloading @value{tramp} resets Ange FTP plugins also.
@end itemize
+
+
+@item
+What is the difference between Ange FTP and @value{tramp}?
+
+The difference is that Ange FTP uses @command{ftp} to transfer files
+between the local and the remote host, whereas @value{tramp} uses a
+combination of @command{rsh} and @command{rcp} or other work-alike
+programs, such as @command{ssh}/@command{scp}.
@end itemize
-@c For the developer
+@c For the developer.
@node Files directories and localnames
@chapter How file names, directories and localnames are mangled and managed
@@ -5384,7 +5746,7 @@ bind it to non-@code{nil} value.
Keeping a local cache of remote file attributes in sync with the
remote host is a time-consuming operation. Flushing and re-querying
these attributes can tax @value{tramp} to a grinding halt on busy
-remote servers.
+remote hosts.
To get around these types of slow-downs in @value{tramp}'s
responsiveness, set the @code{process-file-side-effects} to @code{nil}
@@ -5539,6 +5901,8 @@ function call traces are written to the buffer @file{*trace-output*}.
@c
@c * Say something about the .login and .profile files of the remote
@c shells.
+@c
@c * Explain how tramp.el works in principle: open a shell on a remote
@c host and then send commands to it.
+@c
@c * Consistent small or capitalized words especially in menus.
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
new file mode 100644
index 00000000000..d634ad5197a
--- /dev/null
+++ b/doc/misc/transient.texi
@@ -0,0 +1,2560 @@
+\input texinfo @c -*- texinfo -*-
+@c %**start of header
+@setfilename transient.info
+@settitle Transient User and Developer Manual
+@documentencoding UTF-8
+@documentlanguage en
+@c %**end of header
+
+@copying
+@quotation
+Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+You can redistribute this document and/or modify it under the terms
+of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any
+later version.
+
+This document 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.
+
+@end quotation
+@end copying
+
+@dircategory Emacs misc features
+@direntry
+* Transient: (transient). Transient Commands.
+@end direntry
+
+@finalout
+@titlepage
+@title Transient User and Developer Manual
+@subtitle for version 0.3.7
+@author Jonas Bernoulli
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@ifnottex
+@node Top
+@top Transient User and Developer Manual
+
+Taking inspiration from prefix keys and prefix arguments, Transient
+implements a similar abstraction involving a prefix command, infix
+arguments and suffix commands. We could call this abstraction a
+``transient command'', but because it always involves at least two
+commands (a prefix and a suffix) we prefer to call it just a
+``transient''.
+
+When the user calls a transient prefix command, a transient
+(temporary) keymap is activated, which binds the transient's infix
+and suffix commands, and functions that control the transient state
+are added to @code{pre-command-hook} and @code{post-command-hook}. The available
+suffix and infix commands and their state are shown in a popup buffer
+until the transient is exited by invoking a suffix command.
+
+Calling an infix command causes its value to be changed, possibly by
+reading a new value in the minibuffer.
+
+Calling a suffix command usually causes the transient to be exited
+but suffix commands can also be configured to not exit the transient.
+
+@noindent
+This manual is for Transient version 0.3.7.
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::
+* Usage::
+* Modifying Existing Transients::
+* Defining New Commands::
+* Classes and Methods::
+* Related Abstractions and Packages::
+* FAQ::
+* Keystroke Index::
+* Command and Function Index::
+* Variable Index::
+* Concept Index::
+* GNU General Public License::
+
+@detailmenu
+--- The Detailed Node Listing ---
+
+Usage
+
+* Invoking Transients::
+* Aborting and Resuming Transients::
+* Common Suffix Commands::
+* Saving Values::
+* Using History::
+* Getting Help for Suffix Commands::
+* Enabling and Disabling Suffixes::
+* Other Commands::
+* Other Options::
+
+Defining New Commands
+
+* Defining Transients::
+* Binding Suffix and Infix Commands::
+* Defining Suffix and Infix Commands::
+* Using Infix Arguments::
+* Transient State::
+
+Binding Suffix and Infix Commands
+
+* Group Specifications::
+* Suffix Specifications::
+
+
+Classes and Methods
+
+* Group Classes::
+* Group Methods::
+* Prefix Classes::
+* Suffix Classes::
+* Suffix Methods::
+* Prefix Slots::
+* Suffix Slots::
+* Predicate Slots::
+
+Suffix Methods
+
+* Suffix Value Methods::
+* Suffix Format Methods::
+
+
+Related Abstractions and Packages
+
+* Comparison With Prefix Keys and Prefix Arguments::
+* Comparison With Other Packages::
+
+@end detailmenu
+@end menu
+
+@node Introduction
+@chapter Introduction
+
+Taking inspiration from prefix keys and prefix arguments, Transient
+implements a similar abstraction involving a prefix command, infix
+arguments and suffix commands. We could call this abstraction a
+``transient command'', but because it always involves at least two
+commands (a prefix and a suffix) we prefer to call it just a
+``transient''.
+
+@quotation
+Transient keymaps are a feature provided by Emacs. Transients as
+implemented by this package involve the use of transient keymaps.
+
+@cindex transient prefix command
+Emacs provides a feature that it calls @dfn{prefix commands}. When we
+talk about ``prefix commands'' in this manual, then we mean our own kind
+of ``prefix commands'', unless specified otherwise. To avoid ambiguity
+we sometimes use the terms @dfn{transient prefix command} for our kind and
+``regular prefix command'' for the Emacs' kind.
+
+@end quotation
+
+When the user calls a transient prefix command, a transient
+(temporary) keymap is activated, which binds the transient's infix and
+suffix commands, and functions that control the transient state are
+added to @code{pre-command-hook} and @code{post-command-hook}. The available suffix
+and infix commands and their state are shown in a popup buffer until
+the transient state is exited by invoking a suffix command.
+
+Calling an infix command causes its value to be changed. How that is
+done depends on the type of the infix command. The simplest case is
+an infix command that represents a command-line argument that does not
+take a value. Invoking such an infix command causes the switch to be
+toggled on or off. More complex infix commands may read a value from
+the user, using the minibuffer.
+
+Calling a suffix command usually causes the transient to be exited;
+the transient keymaps and hook functions are removed, the popup buffer
+no longer shows information about the (no longer bound) suffix
+commands, the values of some public global variables are set, while
+some internal global variables are unset, and finally the command is
+actually called. Suffix commands can also be configured to not exit
+the transient.
+
+A suffix command can, but does not have to, use the infix arguments in
+much the same way any command can choose to use or ignore the prefix
+arguments. For a suffix command that was invoked from a transient, the
+variable @code{transient-current-suffixes} and the function @code{transient-args}
+serve about the same purpose as the variables @code{prefix-arg} and
+@code{current-prefix-arg} do for any command that was called after the prefix
+arguments have been set using a command such as @code{universal-argument}.
+
+The information shown in the popup buffer while a transient is active
+looks a bit like this:
+
+@example
+,-----------------------------------------
+|Arguments
+| -f Force (--force)
+| -a Annotate (--annotate)
+|
+|Create
+| t tag
+| r release
+`-----------------------------------------
+@end example
+
+@quotation
+This is a simplified version of @code{magit-tag}. Info manuals do not
+support images or colored text, so the above ``screenshot'' lacks some
+information; in practice you would be able to tell whether the
+arguments @code{--force} and @code{--annotate} are enabled or not based on their
+color.
+
+@end quotation
+
+@cindex command dispatchers
+Transient can be used to implement simple ``command dispatchers''. The
+main benefit then is that the user can see all the available commands
+in a popup buffer. That is useful by itself because it frees the user
+from having to remember all the keys that are valid after a certain
+prefix key or command. Magit's @code{magit-dispatch} (on @code{C-x M-g}) command is
+an example of using Transient to merely implement a command
+dispatcher.
+
+In addition to that, Transient also allows users to interactively pass
+arguments to commands. These arguments can be much more complex than
+what is reasonable when using prefix arguments. There is a limit to
+how many aspects of a command can be controlled using prefix
+arguments. Furthermore, what a certain prefix argument means for
+different commands can be completely different, and users have to read
+documentation to learn and then commit to memory what a certain prefix
+argument means to a certain command.
+
+Transient suffix commands, on the other hand, can accept dozens of
+different arguments without the user having to remember anything.
+When using Transient, one can call a command with arguments that
+are just as complex as when calling the same function non-interactively
+from Lisp.
+
+Invoking a transient command with arguments is similar to invoking a
+command in a shell with command-line completion and history enabled.
+One benefit of the Transient interface is that it remembers history
+not only on a global level (``this command was invoked using these
+arguments, and previously it was invoked using those other arguments''),
+but also remembers the values of individual arguments independently.
+@xref{Using History}.
+
+After a transient prefix command is invoked, @kbd{C-h @var{key}} can be used to
+show the documentation for the infix or suffix command that @kbd{@var{key}} is
+bound to (@pxref{Getting Help for Suffix Commands}), and infixes and
+suffixes can be removed from the transient using @kbd{C-x l @var{key}}. Infixes
+and suffixes that are disabled by default can be enabled the same way.
+@xref{Enabling and Disabling Suffixes}.
+
+Transient ships with support for a few different types of specialized
+infix commands. A command that sets a command line option, for example,
+has different needs than a command that merely toggles a boolean flag.
+Additionally, Transient provides abstractions for defining new types,
+which the author of Transient did not anticipate (or didn't get around
+to implementing yet).
+
+@node Usage
+@chapter Usage
+
+@menu
+* Invoking Transients::
+* Aborting and Resuming Transients::
+* Common Suffix Commands::
+* Saving Values::
+* Using History::
+* Getting Help for Suffix Commands::
+* Enabling and Disabling Suffixes::
+* Other Commands::
+* Other Options::
+@end menu
+
+@node Invoking Transients
+@section Invoking Transients
+@cindex invoking transients
+
+A transient prefix command is invoked like any other command by
+pressing the key that is bound to that command. The main difference
+to other commands is that a transient prefix command activates a
+transient keymap, which temporarily binds the transient's infix and
+suffix commands. Bindings from other keymaps may, or may not, be
+disabled while the transient state is in effect.
+
+There are two kinds of commands that are available after invoking a
+transient prefix command; infix and suffix commands. Infix commands
+set some value (which is then shown in a popup buffer), without
+leaving the transient. Suffix commands, on the other hand, usually quit
+the transient and they may use the values set by the infix commands,
+i.e.@: the infix @strong{arguments}.
+
+Instead of setting arguments to be used by a suffix command, infix
+commands may also set some value by side-effect, e.g., by setting the
+value of some variable.
+
+@node Aborting and Resuming Transients
+@section Aborting and Resuming Transients
+@cindex aborting transients
+@cindex resuming transients
+
+@cindex quit transient
+To quit the transient without invoking a suffix command press @code{C-g}.
+
+Key bindings in transient keymaps may be longer than a single event.
+After pressing a valid prefix key, all commands whose bindings do not
+begin with that prefix key are temporarily unavailable and grayed out.
+To abort the prefix key press @kbd{C-g} (which in this case only quits the
+prefix key, but not the complete transient).
+
+A transient prefix command can be bound as a suffix of another
+transient. Invoking such a suffix replaces the current transient
+state with a new transient state, i.e.@: the available bindings change
+and the information displayed in the popup buffer is updated
+accordingly. Pressing @kbd{C-g} while a nested transient is active only
+quits the innermost transient, causing a return to the previous
+transient.
+
+@kbd{C-q} or @kbd{C-z} on the other hand always exits all transients. If you use
+the latter, then you can later resume the stack of transients using
+@kbd{M-x transient-resume}.
+
+@table @asis
+@kindex C-g
+@findex transient-quit-seq
+@item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-seq})
+@kindex C-g
+@findex transient-quit-one
+@item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-one})
+
+This key quits the currently active incomplete key sequence, if any,
+or else the current transient. When quitting the current transient,
+it returns to the previous transient, if any.
+@end table
+
+Transient's predecessor bound @kbd{q} instead of @kbd{C-g} to the quit command.
+To learn how to get that binding back see @code{transient-bind-q-to-quit}'s
+doc string.
+
+@table @asis
+@kindex C-q
+@findex transient-quit-all
+@item @kbd{C-q} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-all})
+
+This command quits the currently active incomplete key sequence, if
+any, and all transients, including the active transient and all
+suspended transients, if any.
+
+@kindex C-z
+@findex transient-suspend
+@item @kbd{C-z} @tie{}@tie{}@tie{}@tie{}(@code{transient-suspend})
+
+Like @code{transient-quit-all}, this command quits an incomplete key
+sequence, if any, and all transients. Additionally, it saves the
+stack of transients so that it can easily be resumed (which is
+particularly useful if you quickly need to do ``something else'', and
+the stack is deeper than a single transient, and/or you have already
+changed the values of some infix arguments).
+
+Note that only a single stack of transients can be saved at a time.
+If another stack is already saved, then saving a new stack discards
+the previous stack.
+
+@kindex M-x transient-resume
+@findex transient-resume
+@item @kbd{M-x transient-resume} @tie{}@tie{}@tie{}@tie{}(@code{transient-resume})
+
+This command resumes the previously suspended stack of transients,
+if any.
+@end table
+
+@node Common Suffix Commands
+@section Common Suffix Commands
+@cindex common suffix commands
+
+A few shared suffix commands are available in all transients. These
+suffix commands are not shown in the popup buffer by default.
+
+This includes the aborting commands mentioned in the previous section, as
+well as some other commands that are all bound to @kbd{C-x @var{key}}. After
+@kbd{C-x} is pressed, a section featuring all these common commands is
+temporarily shown in the popup buffer. After invoking one of them,
+the section disappears again. Note, however, that one of these commands
+is described as ``Show common permanently''; invoke that if you want the
+common commands to always be shown for all transients.
+
+@table @asis
+@kindex C-x t
+@findex transient-toggle-common
+@item @kbd{C-x t} @tie{}@tie{}@tie{}@tie{}(@code{transient-toggle-common})
+
+This command toggles whether the generic commands that are common to
+all transients are always displayed or only after typing the
+incomplete prefix key sequence @kbd{C-x}. This only affects the current
+Emacs session.
+
+@end table
+
+@defopt transient-show-common-commands
+
+This option controls whether shared suffix commands are shown
+alongside the transient-specific infix and suffix commands. By
+default, the shared commands are not shown to avoid overwhelming
+the user with too many options.
+
+While a transient is active, pressing @kbd{C-x} always shows the common
+commands. The value of this option can be changed for the current
+Emacs session by typing @kbd{C-x t} while a transient is active.
+@end defopt
+
+The other common commands are described in either the previous or
+in one of the following sections.
+
+Some of Transient's key bindings differ from the respective bindings
+of Magit-Popup; see @ref{FAQ} for more information.
+
+@node Saving Values
+@section Saving Values
+@cindex saving values of arguments
+
+After setting the infix arguments in a transient, the user can save
+those arguments for future invocations.
+
+Most transients will start out with the saved arguments when they are
+invoked. There are a few exceptions, though. Some transients are
+designed so that the value that they use is stored externally as the
+buffer-local value of some variable. Invoking such a transient again
+uses the buffer-local value.@footnote{
+@code{magit-diff} and @code{magit-log} are two prominent examples, and their
+handling of buffer-local values is actually a bit more complicated
+than outlined above and even customizable.}
+
+If the user does not save the value and just exits using a regular
+suffix command, then the value is merely saved to the transient's
+history. That value won't be used when the transient is next invoked,
+but it is easily accessible (@pxref{Using History}).
+
+@table @asis
+@kindex C-x s
+@findex transient-set
+@item @kbd{C-x s} @tie{}@tie{}@tie{}@tie{}(@code{transient-set})
+
+This command saves the value of the active transient for this Emacs
+session.
+
+@kindex C-x C-s
+@findex transient-save
+@item @kbd{C-x C-s} @tie{}@tie{}@tie{}@tie{}(@code{transient-save})
+
+Save the value of the active transient persistently across Emacs
+sessions.
+
+@end table
+
+@defopt transient-values-file
+
+This option names the file that is used to persist the values of
+transients between Emacs sessions.
+@end defopt
+
+@node Using History
+@section Using History
+@cindex value history
+
+Every time the user invokes a suffix command the transient's current
+value is saved to its history. These values can be cycled through the
+same way one can cycle through the history of commands that read
+user-input in the minibuffer.
+
+@table @asis
+@kindex C-M-p
+@findex transient-history-prev
+@item @kbd{C-M-p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev})
+@kindex C-x p
+@findex transient-history-prev
+@item @kbd{C-x p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev})
+
+This command switches to the previous value used for the active
+transient.
+
+@kindex C-M-n
+@findex transient-history-next
+@item @kbd{C-M-n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next})
+@kindex C-x n
+@findex transient-history-next
+@item @kbd{C-x n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next})
+
+This command switches to the next value used for the active
+transient.
+@end table
+
+In addition to the transient-wide history, Transient of course
+supports per-infix history. When an infix reads user-input using the
+minibuffer, the user can use the regular minibuffer history
+commands to cycle through previously used values. Usually the same
+keys as those mentioned above are bound to those commands.
+
+Authors of transients should arrange for different infix commands that
+read the same kind of value to also use the same history key
+(@pxref{Suffix Slots}).
+
+Both kinds of history are saved to a file when Emacs is exited.
+
+@defopt transient-history-file
+
+This option names the file that is used to persist the history of
+transients and their infixes between Emacs sessions.
+@end defopt
+
+@defopt transient-history-limit
+
+This option controls how many history elements are kept at the time
+the history is saved in @code{transient-history-file}.
+@end defopt
+
+@node Getting Help for Suffix Commands
+@section Getting Help for Suffix Commands
+@cindex getting help
+
+Transients can have many suffixes and infixes that the user might not
+be familiar with. To make it trivial to get help for these, Transient
+provides access to the documentation directly from the active
+transient.
+
+@table @asis
+@kindex C-h
+@findex transient-help
+@item @kbd{C-h} @tie{}@tie{}@tie{}@tie{}(@code{transient-help})
+
+This command enters help mode. When help mode is active,
+typing a key shows information about the suffix command that the key
+is normally bound to (instead of invoking it). Pressing @kbd{C-h} a
+second time shows information about the @emph{prefix} command.
+
+After typing a key, the stack of transient states is suspended and
+information about the suffix command is shown instead. Typing @kbd{q} in
+the help buffer buries that buffer and resumes the transient state.
+@end table
+
+What sort of documentation is shown depends on how the transient was
+defined. For infix commands that represent command-line arguments
+this ideally shows the appropriate manpage. @code{transient-help} then tries
+to jump to the correct location within that. Info manuals are also
+supported. The fallback is to show the command's doc string, for
+non-infix suffixes this is usually appropriate.
+
+@node Enabling and Disabling Suffixes
+@section Enabling and Disabling Suffixes
+@cindex enabling suffixes
+@cindex disabling suffixes
+
+The user base of a package that uses transients can be very diverse.
+This is certainly the case for Magit; some users have been using it and
+Git for a decade, while others are just getting started now.
+
+@cindex levels
+For that reason a mechanism is needed that authors can use to classify a
+transient's infixes and suffixes along the essentials@dots{}everything
+spectrum. We use the term @dfn{levels} to describe that mechanism.
+
+@cindex transient-level
+Each suffix command is placed on a level and each transient has a
+level (called @dfn{transient-level}), which controls which suffix commands
+are available. Integers between 1 and 7 (inclusive) are valid levels.
+For suffixes, 0 is also valid; it means that the suffix is not
+displayed at any level.
+
+The levels of individual transients and/or their individual suffixes
+can be changed interactively, by invoking the transient and then
+pressing @kbd{C-x l} to enter the ``edit'' mode, see below.
+
+The default level for both transients and their suffixes is 4. The
+@code{transient-default-level} option only controls the default for
+transients. The default suffix level is always 4. The authors of
+transients should place certain suffixes on a higher level, if they
+expect that it won't be of use to most users, and they should place
+very important suffixes on a lower level, so that they remain
+available even if the user lowers the transient level.
+
+@defopt transient-default-level
+
+This option controls which suffix levels are made available by
+default. It sets the transient-level for transients for which the
+user has not set that individually.
+@end defopt
+
+@defopt transient-levels-file
+
+This option names the file that is used to persist the levels of
+transients and their suffixes between Emacs sessions.
+@end defopt
+
+@table @asis
+@kindex C-x l
+@findex transient-set-level
+@item @kbd{C-x l} @tie{}@tie{}@tie{}@tie{}(@code{transient-set-level})
+
+This command enters edit mode. When edit mode is active, then all
+infixes and suffixes that are currently usable are displayed along
+with their levels. The colors of the levels indicate whether they
+are enabled or not. The level of the transient is also displayed
+along with some usage information.
+
+In edit mode, pressing the key that would usually invoke a certain
+suffix instead prompts the user for the level that suffix should be
+placed on.
+
+Help mode is available in edit mode.
+
+To change the transient level press @kbd{C-x l} again.
+
+To exit edit mode press @kbd{C-g}.
+
+Note that edit mode does not display any suffixes that are not
+currently usable. @code{magit-rebase}, for example, shows different suffixes
+depending on whether a rebase is already in progress or not. The
+predicates also apply in edit mode.
+
+Therefore, to control which suffixes are available given a certain
+state, you have to make sure that that state is currently active.
+@end table
+
+@node Other Commands
+@section Other Commands
+
+When invoking a transient in a small frame, the transient window may
+not show the complete buffer, making it necessary to scroll, using the
+following commands. These commands are never shown in the transient
+window, and the key bindings are the same as for @code{scroll-up-command} and
+@code{scroll-down-command} in other buffers.
+
+@findex transient-scroll-up arg
+@deffn Command transient-scroll-up arg
+
+This command scrolls text of transient popup window upward @var{arg}
+lines. If @var{arg} is @code{nil}, then it scrolls near full screen. This
+is a wrapper around @code{scroll-up-command} (which see).
+@end deffn
+
+@findex transient-scroll-down arg
+@deffn Command transient-scroll-down arg
+
+This command scrolls text of transient popup window down @var{arg}
+lines. If @var{arg} is @code{nil}, then it scrolls near full screen. This
+is a wrapper around @code{scroll-down-command} (which see).
+@end deffn
+
+@node Other Options
+@section Other Options
+
+@defopt transient-show-popup
+
+This option controls whether the current transient's infix and
+suffix commands are shown in the popup buffer.
+
+@itemize
+@item
+If @code{t} (the default) then the popup buffer is shown as soon as a
+transient prefix command is invoked.
+
+
+@item
+If @code{nil}, then the popup buffer is not shown unless the user
+explicitly requests it, by pressing an incomplete prefix key
+sequence.
+
+
+@item
+If a number, then the a brief one-line summary is shown instead of
+the popup buffer. If zero or negative, then not even that summary
+is shown; only the pressed key itself is shown.
+
+The popup is shown when the user explicitly requests it by
+pressing an incomplete prefix key sequence. Unless this is zero,
+the popup is shown after that many seconds of inactivity
+(using the absolute value).
+@end itemize
+@end defopt
+
+@defopt transient-enable-popup-navigation
+
+This option controls whether navigation commands are enabled in the
+transient popup buffer.
+
+While a transient is active the transient popup buffer is not the
+current buffer, making it necessary to use dedicated commands to act
+on that buffer itself. This is disabled by default. If this option
+is non-nil, then the following features are available:
+
+@itemize
+@item
+@key{UP} moves the cursor to the previous suffix.
+@key{DOWN} moves the cursor to the next suffix.
+@key{RET} invokes the suffix the cursor is on.
+
+@item
+@key{mouse-1} invokes the clicked on suffix.
+
+@item
+@kbd{C-s} and @kbd{C-r} start isearch in the popup buffer.
+@end itemize
+@end defopt
+
+@defopt transient-display-buffer-action
+
+This option specifies the action used to display the transient popup
+buffer. The transient popup buffer is displayed in a window using
+@code{(display-buffer @var{buffer} transient-display-buffer-action)}.
+
+The value of this option has the form @code{(@var{function} . @var{alist})},
+where @var{function} is a function or a list of functions. Each such
+function should accept two arguments: a buffer to display and an
+alist of the same form as @var{alist}. @xref{Choosing Window,,,elisp,},
+for details.
+
+The default is:
+
+@lisp
+(display-buffer-in-side-window
+ (side . bottom)
+ (inhibit-same-window . t)
+ (window-parameters (no-other-window . t)))
+@end lisp
+
+This displays the window at the bottom of the selected frame.
+Another useful @var{function} is @code{display-buffer-below-selected}, which
+is what @code{magit-popup} used by default. For more alternatives see
+@ref{Buffer Display Action Functions,,,elisp,}, and see @ref{Buffer Display
+Action Alists,,,elisp,}.
+
+Note that the buffer that was current before the transient buffer
+is shown should remain the current buffer. Many suffix commands
+act on the thing at point, if appropriate, and if the transient
+buffer became the current buffer, then that would change what is
+at point. To that effect @code{inhibit-same-window} ensures that the
+selected window is not used to show the transient buffer.
+
+It may be possible to display the window in another frame, but
+whether that works in practice depends on the window-manager.
+If the window manager selects the new window (Emacs frame),
+then that unfortunately changes which buffer is current.
+
+If you change the value of this option, then you might also
+want to change the value of @code{transient-mode-line-format}.
+@end defopt
+
+@defopt transient-mode-line-format
+
+This option controls whether the transient popup buffer has a
+mode-line, separator line, or neither.
+
+If @code{nil}, then the buffer has no mode-line. If the buffer is not
+displayed right above the echo area, then this probably is not a
+good value.
+
+If @code{line} (the default), then the buffer also has no mode-line, but a
+thin line is drawn instead, using the background color of the face
+@code{transient-separator}. Text-mode frames cannot display thin lines, and
+therefore fall back to treating @code{line} like @code{nil}.
+
+Otherwise this can be any mode-line format. @xref{Mode Line
+Format,,,elisp,}, for details.
+@end defopt
+
+@defopt transient-read-with-initial-input
+
+This option controls whether the last history element is used as the
+initial minibuffer input when reading the value of an infix argument
+from the user. If @code{nil}, there is no initial input and the first
+element has to be accessed the same way as the older elements.
+@end defopt
+
+@defopt transient-highlight-mismatched-keys
+
+This option controls whether key bindings of infix commands that do
+not match the respective command-line argument should be highlighted.
+For other infix commands this option has no effect.
+
+When this option is non-@code{nil}, the key binding for an infix argument
+is highlighted when only a long argument (e.g., @code{--verbose}) is
+specified but no shorthand (e.g., @code{-v}). In the rare case that a
+shorthand is specified but the key binding does not match, then it
+is highlighted differently.
+
+Highlighting mismatched key bindings is useful when learning the
+arguments of the underlying command-line tool; you wouldn't want to
+learn any short-hands that do not actually exist.
+
+The highlighting is done using one of the faces
+@code{transient-mismatched-key} and @code{transient-nonstandard-key}.
+@end defopt
+
+@defopt transient-substitute-key-function
+
+This function is used to modify key bindings. If the value of this
+option is @code{nil} (the default), then no substitution is performed.
+
+This function is called with one argument, the prefix object, and
+must return a key binding description, either the existing key
+description it finds in the @code{key} slot, or the key description that
+replaces the prefix key. It could be used to make other
+substitutions, but that is discouraged.
+
+For example, @kbd{=} is hard to reach using my custom keyboard layout,
+so I substitute @kbd{(} for that, which is easy to reach using a layout
+optimized for lisp.
+
+@lisp
+(setq transient-substitute-key-function
+ (lambda (obj)
+ (let ((key (oref obj key)))
+ (if (string-match "\\`\\(=\\)[a-zA-Z]" key)
+ (replace-match "(" t t key 1)
+ key))))
+@end lisp
+@end defopt
+
+@defopt transient-detect-key-conflicts
+
+This option controls whether key binding conflicts should be
+detected at the time the transient is invoked. If so, this
+results in an error, which prevents the transient from being used.
+Because of that, conflicts are ignored by default.
+
+Conflicts cannot be determined earlier, i.e.@: when the transient is
+being defined and when new suffixes are being added, because at that
+time there can be false-positives. It is actually valid for
+multiple suffixes to share a common key binding, provided the
+predicates of those suffixes prevent that more than one of them is
+enabled at a time.
+@end defopt
+
+@defopt transient-force-fixed-pitch
+
+This option controls whether to force the use of a monospaced font
+in popup buffer. Even if you use a proportional font for the
+@code{default} face, you might still want to use a monospaced font in
+transient's popup buffer. Setting this option to @code{t} causes @code{default}
+to be remapped to @code{fixed-pitch} in that buffer.
+@end defopt
+
+@node Modifying Existing Transients
+@chapter Modifying Existing Transients
+@cindex modifying existing transients
+
+To an extent, transients can be customized interactively, see @ref{Enabling and Disabling Suffixes}. This section explains how existing transients
+can be further modified non-interactively.
+
+The following functions share a few arguments:
+
+@itemize
+@item
+@var{prefix} is a transient prefix command, a symbol.
+
+
+@item
+@var{suffix} is a transient infix or suffix specification in the same form
+as expected by @code{transient-define-prefix}. Note that an infix is a
+special kind of suffix. Depending on context ``suffixes'' means
+``suffixes (including infixes)'' or ``non-infix suffixes''. Here it
+means the former. @xref{Suffix Specifications}.
+
+@var{suffix} may also be a group in the same form as expected by
+@code{transient-define-prefix}. @xref{Group Specifications}.
+
+
+@item
+@var{loc} is a command, a key vector, a key description (a string as
+returned by @code{key-description}), or a list specifying coordinates (the
+last element may also be a command or key). For example @code{(1 0 -1)}
+identifies the last suffix (@code{-1}) of the first subgroup (@code{0}) of the
+second group (@code{1}).
+
+If @var{loc} is a list of coordinates, then it can be used to identify a
+group, not just an individual suffix command.
+
+The function @code{transient-get-suffix} can be useful to determine whether
+a certain coordination list identifies the suffix or group that you
+expect it to identify. In hairy cases it may be necessary to look
+at the definition of the transient prefix command.
+@end itemize
+
+These functions operate on the information stored in the
+@code{transient--layout} property of the @var{prefix} symbol. Suffix entries in
+that tree are not objects but have the form @code{(@var{level}
+@var{class} @var{plist})}, where
+@var{plist} should set at least @code{:key}, @code{:description} and
+@code{:command}.
+
+@defun transient-insert-suffix prefix loc suffix
+
+This function inserts suffix or group @var{suffix} into @var{prefix}
+before @var{loc}.
+@end defun
+
+@defun transient-append-suffix prefix loc suffix
+
+This function inserts suffix or group @var{suffix} into @var{prefix}
+after @var{loc}.
+@end defun
+
+@defun transient-replace-suffix prefix loc suffix
+
+This function replaces the suffix or group at @var{loc} in @var{prefix} with
+suffix or group @var{suffix}.
+@end defun
+
+@defun transient-remove-suffix prefix loc
+
+This function removes the suffix or group at @var{loc} in @var{prefix}.
+@end defun
+
+@defun transient-get-suffix prefix loc
+
+This function returns the suffix or group at @var{loc} in @var{prefix}. The
+returned value has the form mentioned above.
+@end defun
+
+@defun transient-suffix-put prefix loc prop value
+
+This function edits the suffix or group at @var{loc} in @var{prefix},
+by setting the @var{prop} of its plist to @var{value}.
+@end defun
+
+Most of these functions do not signal an error if they cannot perform
+the requested modification. The functions that insert new suffixes
+show a warning if @var{loc} cannot be found in @var{prefix}, without
+signaling an error. The reason for doing it like this is that
+establishing a key binding (and that is what we essentially are trying
+to do here) should not prevent the rest of the configuration from
+loading. Among these functions only @code{transient-get-suffix} and
+@code{transient-suffix-put} may signal an error.
+
+@node Defining New Commands
+@chapter Defining New Commands
+
+@menu
+* Defining Transients::
+* Binding Suffix and Infix Commands::
+* Defining Suffix and Infix Commands::
+* Using Infix Arguments::
+* Transient State::
+@end menu
+
+@node Defining Transients
+@section Defining Transients
+
+A transient consists of a prefix command and at least one suffix
+command, though usually a transient has several infix and suffix
+commands. The below macro defines the transient prefix command @strong{and}
+binds the transient's infix and suffix commands. In other words, it
+defines the complete transient, not just the transient prefix command
+that is used to invoke that transient.
+
+@defmac transient-define-prefix name arglist [docstring] [keyword value]@dots{} group@dots{} [body@dots{}]
+
+This macro defines @var{name} as a transient prefix command and binds the
+transient's infix and suffix commands.
+
+@var{arglist} are the arguments that the prefix command takes.
+@var{docstring} is the documentation string and is optional.
+
+These arguments can optionally be followed by keyword-value pairs.
+Each key has to be a keyword symbol, either @code{:class} or a keyword
+argument supported by the constructor of that class. The
+@code{transient-prefix} class is used if the class is not specified
+explicitly.
+
+@var{group}s add key bindings for infix and suffix commands and specify
+how these bindings are presented in the popup buffer. At least one
+@var{group} has to be specified. @xref{Binding Suffix and Infix Commands}.
+
+The @var{body} is optional. If it is omitted, then @var{arglist} is ignored and
+the function definition becomes:
+
+@lisp
+(lambda ()
+ (interactive)
+ (transient-setup 'NAME))
+@end lisp
+
+If @var{body} is specified, then it must begin with an @code{interactive} form
+that matches @var{arglist}, and it must call @code{transient-setup}. It may,
+however, call that function only when some condition is satisfied.
+
+@cindex scope of a transient
+All transients have a (possibly @code{nil}) value, which is exported when
+suffix commands are called, so that they can consume that value.
+For some transients it might be necessary to have a sort of
+secondary value, called a ``scope''. Such a scope would usually be
+set in the command's @code{interactive} form and has to be passed to the
+setup function:
+
+@lisp
+(transient-setup 'NAME nil nil :scope SCOPE)
+@end lisp
+
+For example, the scope of the @code{magit-branch-configure} transient is
+the branch whose variables are being configured.
+@end defmac
+
+@node Binding Suffix and Infix Commands
+@section Binding Suffix and Infix Commands
+
+The macro @code{transient-define-prefix} is used to define a transient.
+This defines the actual transient prefix command (@pxref{Defining
+Transients}) and adds the transient's infix and suffix bindings, as
+described below.
+
+Users and third-party packages can add additional bindings using
+functions such as @code{transient-insert-suffix} (@pxref{Modifying
+Existing Transients}). These functions take a ``suffix
+specification'' as one of their arguments, which has the same form as
+the specifications used in @code{transient-define-prefix}.
+
+@menu
+* Group Specifications::
+* Suffix Specifications::
+@end menu
+
+@node Group Specifications
+@subsection Group Specifications
+@cindex group specifications
+
+The suffix and infix commands of a transient are organized in groups.
+The grouping controls how the descriptions of the suffixes are
+outlined visually but also makes it possible to set certain properties
+for a set of suffixes.
+
+Several group classes exist, some of which organize suffixes in
+subgroups. In most cases the class does not have to be specified
+explicitly, but see @ref{Group Classes}.
+
+Groups are specified in the call to @code{transient-define-prefix}, using
+vectors. Because groups are represented using vectors, we cannot use
+square brackets to indicate an optional element and instead use curly
+brackets to do the latter.
+
+Group specifications then have this form:
+
+@lisp
+[@{@var{level}@} @{@var{description}@}
+ @{@var{keyword} @var{value}@}...
+ @var{element}...]
+@end lisp
+
+The @var{level} is optional and defaults to 4. @xref{Enabling and
+Disabling Suffixes}.
+
+The @var{description} is optional. If present, it is used as the heading of
+the group.
+
+The @var{keyword}-@var{value} pairs are optional. Each keyword has to be a
+keyword symbol, either @code{:class} or a keyword argument supported by the
+constructor of that class.
+
+@itemize
+@item
+One of these keywords, @code{:description}, is equivalent to specifying
+@var{description} at the very beginning of the vector. The recommendation
+is to use @code{:description} if some other keyword is also used, for
+consistency, or @var{description} otherwise, because it looks better.
+
+@item
+Likewise @code{:level} is equivalent to @var{level}.
+
+@item
+Other important keywords include the @code{:if...} keywords. These
+keywords control whether the group is available in a certain
+situation.
+
+For example, one group of the @code{magit-rebase} transient uses
+@code{:if magit-rebase-in-progress-p}, which contains the suffixes
+that are useful while rebase is already in progress; and another that uses
+@code{:if-not magit-rebase-in-progress-p}, which contains the suffixes that
+initiate a rebase.
+
+These predicates can also be used on individual suffixes and are
+only documented once, see @ref{Predicate Slots}.
+
+@item
+The value of @code{:hide}, if non-@code{nil}, is a predicate that controls
+whether the group is hidden by default. The key bindings for
+suffixes of a hidden group should all use the same prefix key.
+Pressing that prefix key should temporarily show the group and its
+suffixes, which assumes that a predicate like this is used:
+
+@lisp
+(lambda ()
+ (eq (car transient--redisplay-key)
+ ?\C-c)) ; the prefix key shared by all bindings
+@end lisp
+
+@item
+The value of @code{:setup-children}, if non-@code{nil}, is a function
+that takes two arguments the group object itself and a list of children.
+The children are given as a, potentially empty, list consisting
+of either group or suffix specifications. It can make arbitrary
+changes to the children including constructing new children from
+scratch. Also see @code{transient-setup-children}.
+
+@item
+The boolean @code{:pad-keys} argument controls whether keys of all suffixes
+contained in a group are right padded, effectively aligning the
+descriptions.
+@end itemize
+
+The @var{element}s are either all subgroups (vectors), or all suffixes
+(lists) and strings. (At least currently no group type exists that
+would allow mixing subgroups with commands at the same level, though
+in principle there is nothing that prevents that.)
+
+If the @var{element}s are not subgroups, then they can be a mixture of lists
+that specify commands and strings. Strings are inserted verbatim.
+The empty string can be used to insert gaps between suffixes, which is
+particularly useful if the suffixes are outlined as a table.
+
+Variables are supported inside group specifications. For example in
+place of a direct subgroup specification, a variable can be used whose
+value is a vector that qualifies as a group specification. Likewise, a
+variable can be used where a suffix specification is expected. Lists
+of group or suffix specifications are also supported. Indirect
+specifications are resolved when the transient prefix is being
+defined.
+
+The form of suffix specifications is documented in the next node.
+
+@node Suffix Specifications
+@subsection Suffix Specifications
+@cindex suffix specifications
+
+A transient's suffix and infix commands are bound when the transient
+prefix command is defined using @code{transient-define-prefix}, see
+@ref{Defining Transients}. The commands are organized into groups, see
+@ref{Group Specifications}. Here we describe the form used to bind an
+individual suffix command.
+
+The same form is also used when later binding additional commands
+using functions such as @code{transient-insert-suffix},
+see @ref{Modifying Existing Transients}.
+
+Note that an infix is a special kind of suffix. Depending on context
+``suffixes'' means ``suffixes (including infixes)'' or ``non-infix
+suffixes''. Here it means the former.
+
+Suffix specifications have this form:
+
+@lisp
+([@var{level}]
+ [@var{key}] [@var{description}]
+ @var{command}|@var{argument} [@var{keyword} @var{value}]...)
+@end lisp
+
+@var{level}, @var{key} and @var{description} can also be specified using the @var{keyword}s
+@code{:level}, @code{:key} and @code{:description}. If the object that is associated with
+@var{command} sets these properties, then they do not have to be specified
+here. You can however specify them here anyway, possibly overriding
+the object's values just for the binding inside this transient.
+
+@itemize
+@item
+@var{level} is the suffix level, an integer between 1 and 7.
+@xref{Enabling and Disabling Suffixes}.
+
+@item
+@var{key} is the key binding, either a vector or key description string.
+
+@item
+@var{description} is the description, either a string or a function that
+returns a string. The function should be a lambda expression to
+avoid ambiguity. In some cases a symbol that is bound as a function
+would also work but to be safe you should use @code{:description} in that
+case.
+@end itemize
+
+The next element is either a command or an argument. This is the only
+argument that is mandatory in all cases.
+
+@itemize
+@item
+Usually @var{command} is a symbol that is bound as a function, which has
+to be defined or at least autoloaded as a command by the time the
+containing prefix command is invoked.
+
+Any command will do; it does not need to have an object associated
+with it (as would be the case if @code{transient-define-suffix} or
+@code{transient-define-infix} were used to define it).
+
+The command can also be a closure or lambda expression, but that
+should only be used for dynamic transients whose suffixes are
+defined when the prefix command is invoked. See information about
+the @code{:setup-children} function in @ref{Group Specifications}.
+
+As mentioned above, the object that is associated with a command can
+be used to set the default for certain values that otherwise have to
+be set in the suffix specification. Therefore if there is no object,
+then you have to make sure to specify the @var{key} and the @var{description}.
+
+As a special case, if you want to add a command that might be neither
+defined nor autoloaded, you can use a workaround like:
+
+@lisp
+(transient-insert-suffix 'some-prefix "k"
+ '("!" "Ceci n'est pas une commande" no-command
+ :if (lambda () (featurep 'no-library))))
+@end lisp
+
+Instead of @code{featurep} you could also use @code{require} with a
+non-nil value for @var{noerror}.
+
+@item
+The mandatory argument can also be a command-line argument, a
+string. In that case an anonymous command is defined and bound.
+
+Instead of a string, this can also be a list of two strings, in
+which case the first string is used as the short argument (which can
+also be specified using @code{:shortarg}) and the second as the long argument
+(which can also be specified using @code{:argument}).
+
+Only the long argument is displayed in the popup buffer. See
+@code{transient-detect-key-conflicts} for how the short argument may be
+used.
+
+Unless the class is specified explicitly, the appropriate class is
+guessed based on the long argument. If the argument ends with @samp{=}
+(e.g. @samp{--format=}) then @code{transient-option} is used, otherwise
+@code{transient-switch}.
+@end itemize
+
+Finally, details can be specified using optional
+@var{keyword}-@var{value} pairs.
+Each keyword has to be a keyword symbol, either @code{:class} or a keyword
+argument supported by the constructor of that class. See @ref{Suffix Slots}.
+
+@node Defining Suffix and Infix Commands
+@section Defining Suffix and Infix Commands
+@cindex defining suffix commands
+@cindex defining infix commands
+
+Note that an infix is a special kind of suffix. Depending on context
+``suffixes'' means ``suffixes (including infixes)'' or ``non-infix
+suffixes''.
+
+@defmac transient-define-suffix name arglist [docstring] [keyword value]@dots{} body@dots{}
+
+This macro defines @var{name} as a transient suffix command.
+
+@var{arglist} are the arguments that the command takes.
+@var{docstring} is the documentation string and is optional.
+
+These arguments can optionally be followed by keyword-value pairs.
+Each keyword has to be a keyword symbol, either @code{:class} or a keyword
+argument supported by the constructor of that class. The
+@code{transient-suffix} class is used if the class is not specified
+explicitly.
+
+The @var{body} must begin with an @code{interactive} form that matches @var{arglist}.
+The infix arguments are usually accessed by using @code{transient-args}
+inside @code{interactive}.
+@end defmac
+
+@defmac transient-define-infix name arglist [docstring] [keyword value]@dots{}
+
+This macro defines @var{name} as a transient infix command.
+
+@var{arglist} is always ignored (but mandatory never-the-less) and
+reserved for future use. @var{docstring} is the documentation string and
+is optional.
+
+The keyword-value pairs are mandatory. All transient infix commands
+are @code{equal} to each other (but not @code{eq}), so it is meaningless to define
+an infix command without also setting at least @code{:class} and one other
+keyword (which it is depends on the used class, usually @code{:argument} or
+@code{:variable}).
+
+Each keyword has to be a keyword symbol, either @code{:class} or a keyword
+argument supported by the constructor of that class. The
+@code{transient-switch} class is used if the class is not specified
+explicitly.
+
+The function definition is always:
+
+@lisp
+(lambda ()
+ (interactive)
+ (let ((obj (transient-suffix-object)))
+ (transient-infix-set obj (transient-infix-read obj)))
+ (transient--show))
+@end lisp
+
+@code{transient-infix-read} and @code{transient-infix-set} are generic functions.
+Different infix commands behave differently because the concrete
+methods are different for different infix command classes. In rare
+cases the above command function might not be suitable, even if you
+define your own infix command class. In that case you have to use
+@code{transient-suffix-command} to define the infix command and use @code{t} as
+the value of the @code{:transient} keyword.
+@end defmac
+
+@defmac transient-define-argument name arglist [docstring] [keyword value]@dots{}
+
+This macro defines @var{name} as a transient infix command.
+
+This is an alias for @code{transient-define-infix}. Only use this alias
+to define an infix command that actually sets an infix argument.
+To define an infix command that, for example, sets a variable, use
+@code{transient-define-infix} instead.
+@end defmac
+
+@node Using Infix Arguments
+@section Using Infix Arguments
+@cindex using infix arguments
+
+The functions and the variables described below allow suffix commands
+to access the value of the transient from which they were invoked;
+which is the value of its infix arguments. These variables are set
+when the user invokes a suffix command that exits the transient, but
+before actually calling the command.
+
+When returning to the command-loop after calling the suffix command,
+the arguments are reset to @code{nil} (which causes the function to return
+@code{nil} too).
+
+Like for Emacs' prefix arguments, it is advisable, but not mandatory,
+to access the infix arguments inside the command's @code{interactive} form.
+The preferred way of doing that is to call the @code{transient-args}
+function, which for infix arguments serves about the same purpose as
+@code{prefix-arg} serves for prefix arguments.
+
+@defun transient-args prefix
+
+This function returns the value of the transient prefix command
+@var{prefix}.
+
+If the current command was invoked from the transient prefix command
+@var{prefix}, then it returns the active infix arguments. If the current
+command was not invoked from @var{prefix}, then it returns the set, saved
+or default value for @var{prefix}.
+@end defun
+
+@defun transient-arg-value arg args
+
+This function return the value of @var{arg} as it appears in @var{args}.
+
+For a switch a boolean is returned. For an option the value is
+returned as a string, using the empty string for the empty value,
+or @code{nil} if the option does not appear in @var{args}.
+@end defun
+
+@defun transient-suffixes prefix
+
+This function returns the suffixes of the transient prefix command
+@var{prefix}. This is a list of objects. This function should only be
+used if you need the objects (as opposed to just their values) and
+if the current command is not being invoked from @var{prefix}.
+@end defun
+
+@defvar transient-current-suffixes
+
+The suffixes of the transient from which this suffix command was
+invoked. This is a list of objects. Usually it is sufficient to
+instead use the function @code{transient-args}, which returns a list of
+values. In complex cases it might be necessary to use this variable
+instead, i.e.@: if you need access to information beside the value.
+@end defvar
+
+@defvar transient-current-prefix
+
+The transient from which this suffix command was invoked. The
+returned value is a @code{transient-prefix} object, which holds information
+associated with the transient prefix command.
+@end defvar
+
+@defvar transient-current-command
+
+The transient from which this suffix command was invoked. The
+returned value is a symbol, the transient prefix command.
+@end defvar
+
+@node Transient State
+@section Transient State
+@cindex transient state
+
+Invoking a transient prefix command ``activates'' the respective
+transient, i.e.@: it puts a transient keymap into effect, which binds
+the transient's infix and suffix commands.
+
+The default behavior while a transient is active is as follows:
+
+@itemize
+@item
+Invoking an infix command does not affect the transient state; the
+transient remains active.
+
+@item
+Invoking a (non-infix) suffix command ``deactivates'' the transient
+state by removing the transient keymap and performing some
+additional cleanup.
+
+@item
+Invoking a command that is bound in a keymap other than the
+transient keymap is disallowed and trying to do so results in a
+warning. This does not ``deactivate'' the transient.
+@end itemize
+
+But these are just the defaults. Whether a certain command
+deactivates or ``exits'' the transient is configurable. There is more
+than one way in which a command can be ``transient'' or ``non-transient'';
+the exact behavior is implemented by calling a so-called ``pre-command''
+function. Whether non-suffix commands are allowed to be called is
+configurable per transient.
+
+@itemize
+@item
+The transient-ness of suffix commands (including infix commands) is
+controlled by the value of their @code{transient} slot, which can be set
+either when defining the command or when adding a binding to a
+transient while defining the respective transient prefix command.
+
+Valid values are booleans and the pre-commands described below.
+
+@itemize
+@item
+@code{t} is equivalent to @code{transient--do-stay}.
+
+@item
+@code{nil} is equivalent to @code{transient--do-exit}.
+
+@item
+If @code{transient} is unbound (and that is actually the default for
+non-infix suffixes) then the value of the prefix's
+@code{transient-suffix} slot is used instead. The default value of that
+slot is @code{nil}, so the suffix's @code{transient} slot being unbound is
+essentially equivalent to it being @code{nil}.
+@end itemize
+
+@item
+A suffix command can be a prefix command itself, i.e. a
+``sub-prefix''. While a sub-prefix is active we nearly always want
+@kbd{C-g} to take the user back to the ``super-prefix''. However in rare
+cases this may not be desirable, and that makes the following
+complication necessary:
+
+For @code{transient-suffix} objects the @code{transient} slot is unbound. We can
+ignore that for the most part because, as stated above, @code{nil} and the
+slot being unbound are equivalent, and mean ``do exit''. That isn't
+actually true for suffixes that are sub-prefixes though. For such
+suffixes unbound means ``do exit but allow going back'', which is the
+default, while @code{nil} means ``do exit permanently'', which requires that
+slot to be explicitly set to that value.
+
+@item
+The transient-ness of certain built-in suffix commands is specified
+using @code{transient-predicate-map}. This is a special keymap, which
+binds commands to pre-commands (as opposed to keys to commands) and
+takes precedence over the @code{transient} slot.
+@end itemize
+
+The available pre-command functions are documented below. They are
+called by @code{transient--pre-command}, a function on @code{pre-command-hook} and
+the value that they return determines whether the transient is exited.
+To do so the value of one of the constants @code{transient--exit} or
+@code{transient--stay} is used (that way we don't have to remember if @code{t} means
+``exit'' or ``stay'').
+
+Additionally, these functions may change the value of @code{this-command}
+(which explains why they have to be called using @code{pre-command-hook}),
+call @code{transient-export}, @code{transient--stack-zap} or @code{transient--stack-push};
+and set the values of @code{transient--exitp}, @code{transient--helpp} or
+@code{transient--editp}.
+
+@anchor{Pre-commands for Infixes}
+@subheading Pre-commands for Infixes
+
+The default for infixes is @code{transient--do-stay}. This is also the only
+function that makes sense for infixes.
+
+@defun transient--do-stay
+
+Call the command without exporting variables and stay transient.
+@end defun
+
+@anchor{Pre-commands for Suffixes}
+@subheading Pre-commands for Suffixes
+
+The default for suffixes is @code{transient--do-exit}.
+
+@defun transient--do-exit
+
+Call the command after exporting variables and exit the transient.
+@end defun
+
+@defun transient--do-call
+
+Call the command after exporting variables and stay transient.
+@end defun
+
+@defun transient--do-replace
+
+Call the transient prefix command, replacing the active transient.
+
+This is used for suffixes that are prefixes themselves, i.e.@: for
+sub-prefixes.
+@end defun
+
+@anchor{Pre-commands for Non-Suffixes}
+@subheading Pre-commands for Non-Suffixes
+
+The default for non-suffixes, i.e@: commands that are bound in other
+keymaps beside the transient keymap, is @code{transient--do-warn}. Silently
+ignoring the user-error is also an option, though probably not a good
+one.
+
+If you want to let the user invoke non-suffix commands, then use
+@code{transient--do-stay} as the value of the prefix's @code{transient-non-suffix}
+slot.
+
+@defun transient--do-warn
+
+Call @code{transient-undefined} and stay transient.
+@end defun
+
+@defun transient--do-noop
+
+Call @code{transient-noop} and stay transient.
+@end defun
+
+@anchor{Special Pre-Commands}
+@subheading Special Pre-Commands
+
+@defun transient--do-quit-one
+
+If active, quit help or edit mode, else exit the active transient.
+
+This is used when the user pressed @kbd{C-g}.
+@end defun
+
+@defun transient--do-quit-all
+
+Exit all transients without saving the transient stack.
+
+This is used when the user pressed @kbd{C-q}.
+@end defun
+
+@defun transient--do-suspend
+
+Suspend the active transient, saving the transient stack.
+
+This is used when the user pressed @kbd{C-z}.
+@end defun
+
+@node Classes and Methods
+@chapter Classes and Methods
+@cindex classes and methods
+
+Transient uses classes and generic functions to make it possible to
+define new types of suffix commands that are similar to existing
+types, but behave differently in some aspects. It does the same for
+groups and prefix commands, though at least for prefix commands that
+@strong{currently} appears to be less important.
+
+Every prefix, infix and suffix command is associated with an object,
+which holds information that controls certain aspects of its behavior.
+This happens in two ways.
+
+@itemize
+@item
+Associating a command with a certain class gives the command a type.
+This makes it possible to use generic functions to do certain things
+that have to be done differently depending on what type of command
+it acts on.
+
+That in turn makes it possible for third-parties to add new types
+without having to convince the maintainer of Transient that that new
+type is important enough to justify adding a special case to a dozen
+or so functions.
+
+@item
+Associating a command with an object makes it possible to easily
+store information that is specific to that particular command.
+
+Two commands may have the same type, but obviously their key
+bindings and descriptions still have to be different, for example.
+
+The values of some slots are functions. The @code{reader} slot for example
+holds a function that is used to read a new value for an infix
+command. The values of such slots are regular functions.
+
+Generic functions are used when a function should do something
+different based on the type of the command, i.e. when all commands
+of a certain type should behave the same way but different from the
+behavior for other types. Object slots that hold a regular function
+as value are used when the task that they perform is likely to
+differ even between different commands of the same type.
+@end itemize
+
+@menu
+* Group Classes::
+* Group Methods::
+* Prefix Classes::
+* Suffix Classes::
+* Suffix Methods::
+* Prefix Slots::
+* Suffix Slots::
+* Predicate Slots::
+@end menu
+
+@node Group Classes
+@section Group Classes
+
+The type of a group can be specified using the @code{:class} property at the
+beginning of the class specification, e.g. @code{[:class transient-columns
+...]} in a call to @code{transient-define-prefix}.
+
+@itemize
+@item
+The abstract @code{transient-child} class is the base class of both
+@code{transient-group} (and therefore all groups) as well as of
+@code{transient-suffix} (and therefore all suffix and infix commands).
+
+This class exists because the elements (a.k.a.@: ``children'') of certain
+groups can be other groups instead of suffix and infix commands.
+
+@item
+The abstract @code{transient-group} class is the superclass of all other
+group classes.
+
+@item
+The @code{transient-column} class is the simplest group.
+
+This is the default ``flat'' group. If the class is not specified
+explicitly and the first element is not a vector (i.e. not a group),
+then this class is used.
+
+This class displays each element on a separate line.
+
+@item
+The @code{transient-row} class displays all elements on a single line.
+
+@item
+The @code{transient-columns} class displays commands organized in columns.
+
+Direct elements have to be groups whose elements have to be commands
+or strings. Each subgroup represents a column. This class takes
+care of inserting the subgroups' elements.
+
+This is the default ``nested'' group. If the class is not specified
+explicitly and the first element is a vector (i.e.@: a group), then
+this class is used.
+
+@item
+The @code{transient-subgroups} class wraps other groups.
+
+Direct elements have to be groups whose elements have to be commands
+or strings. This group inserts an empty line between subgroups.
+The subgroups themselves are responsible for displaying their
+elements.
+@end itemize
+
+@node Group Methods
+@section Group Methods
+
+@defun transient-setup-children group children
+
+This generic function can be used to setup the children or a group.
+
+The default implementation usually just returns the children
+unchanged, but if the @code{setup-children} slot of @var{group} is non-nil, then
+it calls that function with @var{children} as the only argument and
+returns the value.
+
+The children are given as a (potentially empty) list consisting of
+either group or suffix specifications. These functions can make
+arbitrary changes to the children including constructing new
+children from scratch.
+@end defun
+
+@defun transient--insert-group group
+
+This generic function formats the group and its elements and inserts
+the result into the current buffer, which is a temporary buffer.
+The contents of that buffer are later inserted into the popup buffer.
+
+Functions that are called by this function may need to operate in
+the buffer from which the transient was called. To do so they can
+temporarily make the @code{transient--source-buffer} the current buffer.
+@end defun
+
+@node Prefix Classes
+@section Prefix Classes
+
+Currently the @code{transient-prefix} class is being used for all prefix
+commands and there is only a single generic function that can be
+specialized based on the class of a prefix command.
+
+@defun transient--history-init obj
+
+This generic function is called while setting up the transient and
+is responsible for initializing the @code{history} slot. This is the
+transient-wide history; many individual infixes also have a history
+of their own.
+
+The default (and currently only) method extracts the value from the
+global variable @code{transient-history}.
+@end defun
+
+A transient prefix command's object is stored in the @code{transient--prefix}
+property of the command symbol. While a transient is active, a clone
+of that object is stored in the variable @code{transient--prefix}. A clone
+is used because some changes that are made to the active transient's
+object should not affect later invocations.
+
+@node Suffix Classes
+@section Suffix Classes
+
+@itemize
+@item
+All suffix and infix classes derive from @code{transient-suffix}, which in
+turn derives from @code{transient-child}, from which @code{transient-group} also
+derives (@pxref{Group Classes}).
+
+@item
+All infix classes derive from the abstract @code{transient-infix} class,
+which in turn derives from the @code{transient-suffix} class.
+
+Infixes are a special type of suffixes. The primary difference is
+that infixes always use the @code{transient--do-stay} pre-command, while
+non-infix suffixes use a variety of pre-commands (see @ref{Transient State}). Doing that is most easily achieved by using this class,
+though theoretically it would be possible to define an infix class
+that does not do so. If you do that then you get to implement many
+methods.
+
+Also, infixes and non-infix suffixes are usually defined using
+different macros (@pxref{Defining Suffix and Infix Commands}).
+
+@item
+Classes used for infix commands that represent arguments should
+be derived from the abstract @code{transient-argument} class.
+
+@item
+The @code{transient-switch} class (or a derived class) is used for infix
+arguments that represent command-line switches (arguments that do
+not take a value).
+
+@item
+The @code{transient-option} class (or a derived class) is used for infix
+arguments that represent command-line options (arguments that do
+take a value).
+
+@item
+The @code{transient-switches} class can be used for a set of mutually
+exclusive command-line switches.
+
+@item
+The @code{transient-files} class can be used for a @samp{--} argument that
+indicates that all remaining arguments are files.
+
+@item
+Classes used for infix commands that represent variables should
+derived from the abstract @code{transient-variables} class.
+@end itemize
+
+Magit defines additional classes, which can serve as examples for the
+fancy things you can do without modifying Transient. Some of these
+classes will likely get generalized and added to Transient. For now
+they are very much subject to change and not documented.
+
+@node Suffix Methods
+@section Suffix Methods
+
+To get information about the methods implementing these generic
+functions use @code{describe-function}.
+
+@menu
+* Suffix Value Methods::
+* Suffix Format Methods::
+@end menu
+
+@node Suffix Value Methods
+@subsection Suffix Value Methods
+
+@defun transient-init-value obj
+
+This generic function sets the initial value of the object @var{obj}.
+
+This function is called for all suffix commands, but unless a
+concrete method is implemented this falls through to the default
+implementation, which is a noop. In other words this usually
+only does something for infix commands, but note that this is
+not implemented for the abstract class @code{transient-infix}, so if
+your class derives from that directly, then you must implement
+a method.
+@end defun
+
+@defun transient-infix-read obj
+
+This generic function determines the new value of the infix object
+@var{obj}.
+
+This function merely determines the value; @code{transient-infix-set} is
+used to actually store the new value in the object.
+
+For most infix classes this is done by reading a value from the
+user using the reader specified by the @code{reader} slot (using the
+@code{transient-infix-value} method described below).
+
+For some infix classes the value is changed without reading
+anything in the minibuffer, i.e.@: the mere act of invoking the
+infix command determines what the new value should be, based
+on the previous value.
+@end defun
+
+@defun transient-prompt obj
+
+This generic function returns the prompt to be used to read infix
+object @var{obj}'s value.
+@end defun
+
+@defun transient-infix-set obj value
+
+This generic function sets the value of infix object @var{obj} to @var{value}.
+@end defun
+
+@defun transient-infix-value obj
+
+This generic function returns the value of the suffix object @var{obj}.
+
+This function is called by @code{transient-args} (which see), meaning this
+function is how the value of a transient is determined so that the
+invoked suffix command can use it.
+
+Currently most values are strings, but that is not set in stone.
+@code{nil} is not a value, it means ``no value''.
+
+Usually only infixes have a value, but see the method for
+@code{transient-suffix}.
+@end defun
+
+@defun transient-init-scope obj
+
+This generic function sets the scope of the suffix object @var{obj}.
+
+The scope is actually a property of the transient prefix, not of
+individual suffixes. However it is possible to invoke a suffix
+command directly instead of from a transient. In that case, if
+the suffix expects a scope, then it has to determine that itself
+and store it in its @code{scope} slot.
+
+This function is called for all suffix commands, but unless a
+concrete method is implemented this falls through to the default
+implementation, which is a noop.
+@end defun
+
+@node Suffix Format Methods
+@subsection Suffix Format Methods
+
+@defun transient-format obj
+
+This generic function formats and returns @var{obj} for display.
+
+When this function is called, then the current buffer is some
+temporary buffer. If you need the buffer from which the prefix
+command was invoked to be current, then do so by temporarily
+making @code{transient--source-buffer} current.
+@end defun
+
+@defun transient-format-key obj
+
+This generic function formats @var{obj}'s @code{key} for display and returns the
+result.
+@end defun
+
+@defun transient-format-description obj
+
+This generic function formats @var{obj}'s @code{description} for display and
+returns the result.
+@end defun
+
+@defun transient-format-value obj
+
+This generic function formats @var{obj}'s value for display and returns
+the result.
+@end defun
+
+@defun transient-show-help obj
+
+Show help for the prefix, infix or suffix command represented by
+@var{obj}.
+
+For prefixes, show the info manual, if that is specified using the
+@code{info-manual} slot. Otherwise, show the manpage if that is specified
+using the @code{man-page} slot. Otherwise, show the command's doc string.
+
+For suffixes, show the command's doc string.
+
+For infixes, show the manpage if that is specified. Otherwise show
+the command's doc string.
+@end defun
+
+@node Prefix Slots
+@section Prefix Slots
+
+@itemize
+@item
+@code{man-page} or @code{info-manual} can be used to specify the documentation for
+the prefix and its suffixes. The command @code{transient-help} uses the
+method @code{transient-show-help} (which see) to lookup and use these
+values.
+
+@item
+@code{history-key} If multiple prefix commands should share a single value,
+then this slot has to be set to the same value for all of them. You
+probably don't want that.
+
+@item
+@code{transient-suffix} and @code{transient-non-suffix} play a part when
+determining whether the currently active transient prefix command
+remains active/transient when a suffix or abitrary non-suffix
+command is invoked. @xref{Transient State}.
+
+@item
+@code{incompatible} A list of lists. Each sub-list specifies a set of
+mutually exclusive arguments. Enabling one of these arguments
+causes the others to be disabled. An argument may appear in
+multiple sub-lists.
+
+@item
+@code{scope} For some transients it might be necessary to have a sort of
+secondary value, called a ``scope''. See @code{transient-define-prefix}.
+@end itemize
+
+@anchor{Internal Prefix Slots}
+@subheading Internal Prefix Slots
+
+These slots are mostly intended for internal use. They should not be
+set in calls to @code{transient-define-prefix}.
+
+@itemize
+@item
+@code{prototype} When a transient prefix command is invoked, then a clone
+of that object is stored in the global variable @code{transient--prefix}
+and the prototype is stored in the clone's @code{prototype} slot.
+
+@item
+@code{command} The command, a symbol. Each transient prefix command
+consists of a command, which is stored in a symbol's function slot
+and an object, which is stored in the @code{transient--prefix} property
+of the same symbol.
+
+@item
+@code{level} The level of the prefix commands. The suffix commands whose
+layer is equal or lower are displayed. @pxref{Enabling and Disabling Suffixes}.
+
+@item
+@code{value} The likely outdated value of the prefix. Instead of accessing
+this slot directly you should use the function @code{transient-get-value},
+which is guaranteed to return the up-to-date value.
+
+@item
+@code{history} and @code{history-pos} are used to keep track of historic values.
+Unless you implement your own @code{transient-infix-read} method you should
+not have to deal with these slots.
+@end itemize
+
+@node Suffix Slots
+@section Suffix Slots
+
+Here we document most of the slots that are only available for suffix
+objects. Some slots are shared by suffix and group objects, they are
+documented in @ref{Predicate Slots}.
+
+Also see @ref{Suffix Classes}.
+
+@anchor{Slots of @code{transient-suffix}}
+@subheading Slots of @code{transient-suffix}
+
+@itemize
+@item
+@code{key} The key, a key vector or a key description string.
+
+@item
+@code{command} The command, a symbol.
+
+@item
+@code{transient} Whether to stay transient. @xref{Transient State}.
+
+@item
+@code{format} The format used to display the suffix in the popup buffer.
+It must contain the following %-placeholders:
+
+@itemize
+@item
+@code{%k} For the key.
+
+@item
+@code{%d} For the description.
+
+@item
+@code{%v} For the infix value. Non-infix suffixes don't have a value.
+@end itemize
+
+@item
+@code{description} The description, either a string or a function that is
+called with no argument and returns a string.
+@end itemize
+
+@anchor{Slots of @code{transient-infix}}
+@subheading Slots of @code{transient-infix}
+
+Some of these slots are only meaningful for some of the subclasses.
+They are defined here anyway to allow sharing certain methods.
+
+@itemize
+@item
+@code{argument} The long argument, e.g. @code{--verbose}.
+
+@item
+@code{shortarg} The short argument, e.g. @code{-v}.
+
+@item
+@code{value} The value. Should not be accessed directly.
+
+@item
+@code{init-value} Function that is responsible for setting the object's
+value. If bound, then this is called with the object as the only
+argument. Usually this is not bound, in which case the object's
+primary @code{transient-init-value} method is called instead.
+
+@item
+@code{unsavable} Whether the value of the suffix is not saved as part of
+the prefixes.
+
+@item
+@code{multi-value} For options, whether the option can have multiple
+values. If non-nil, then default to use @code{completing-read-multiple}.
+
+@item
+@code{always-read} For options, whether to read a value on every invocation.
+If this is nil, then options that have a value are simply unset and
+have to be invoked a second time to set a new value.
+
+@item
+@code{allow-empty} For options, whether the empty string is a valid value.
+
+@item
+@code{history-key} The key used to store the history. This defaults to the
+command name. This is useful when multiple infixes should share the
+same history because their values are of the same kind.
+
+@item
+@code{reader} The function used to read the value of an infix. Not used
+for switches. The function takes three arguments, @var{prompt},
+@var{initial-input} and @var{history}, and must return a string.
+
+@item
+@code{prompt} The prompt used when reading the value, either a string or a
+function that takes the object as the only argument and which
+returns a prompt string.
+
+@item
+@code{choices} A list of valid values. How exactly that is used depends on
+the class of the object.
+@end itemize
+
+@anchor{Slots of @code{transient-variable}}
+@subheading Slots of @code{transient-variable}
+
+@itemize
+@item
+@code{variable} The variable.
+@end itemize
+
+@anchor{Slots of @code{transient-switches}}
+@subheading Slots of @code{transient-switches}
+
+@itemize
+@item
+@code{argument-format} The display format. Must contain @code{%s}, one of the
+@code{choices} is substituted for that. E.g., @code{--%s-order}.
+
+@item
+@code{argument-regexp} The regexp used to match any one of the switches.
+E.g., @code{\\(--\\(topo\\|author-date\\|date\\)-order\\)}.
+@end itemize
+
+@node Predicate Slots
+@section Predicate Slots
+
+Suffix and group objects share some predicate slots that control
+whether a group or suffix should be available depending on some state.
+Only one of these slots can be used at the same time. It is undefined
+what happens if you use more than one.
+
+@itemize
+@item
+@code{if} Enable if predicate returns non-@code{nil}.
+
+@item
+@code{if-not} Enable if predicate returns @code{nil}.
+
+@item
+@code{if-non-nil} Enable if variable's value is non-@code{nil}.
+
+@item
+@code{if-nil} Enable if variable's value is @code{nil}.
+
+@item
+@code{if-mode} Enable if major-mode matches value.
+
+@item
+@code{if-not-mode} Enable if major-mode does not match value.
+
+@item
+@code{if-derived} Enable if major-mode derives from value.
+
+@item
+@code{if-not-derived} Enable if major-mode does not derive from value.
+@end itemize
+
+One more slot is shared between group and suffix classes, @code{level}. Like
+the slots documented above, it is a predicate, but it is used for a
+different purpose. The value has to be an integer between 1
+and 7. @code{level} controls whether a suffix or a group should be
+available depending on user preference.
+@xref{Enabling and Disabling Suffixes}.
+
+@node Related Abstractions and Packages
+@chapter Related Abstractions and Packages
+
+@menu
+* Comparison With Prefix Keys and Prefix Arguments::
+* Comparison With Other Packages::
+@end menu
+
+@node Comparison With Prefix Keys and Prefix Arguments
+@section Comparison With Prefix Keys and Prefix Arguments
+
+While transient commands were inspired by regular prefix keys and
+prefix arguments, they are also quite different and much more complex.
+
+The following diagrams illustrate some of the differences.
+
+@itemize
+@item
+@code{(c)} represents a return to the command loop.
+
+@item
+@code{(+)} represents the user's choice to press one key or another.
+
+@item
+@code{@{@var{word}@}} are possible behaviors.
+
+@item
+@code{@{@var{number}@}} is a footnote.
+@end itemize
+
+@anchor{Regular Prefix Commands}
+@subheading Regular Prefix Commands
+
+@xref{Prefix Keys,,,elisp,}.
+
+@example
+ ,--> command1 --> (c)
+ |
+(c)-(+)-> prefix command or key --+--> command2 --> (c)
+ |
+ `--> command3 --> (c)
+@end example
+
+@anchor{Regular Prefix Arguments}
+@subheading Regular Prefix Arguments
+
+@xref{Prefix Command Arguments,,,elisp,}.
+
+@example
+ ,----------------------------------,
+ | |
+ v |
+(c)-(+)---> prefix argument command --(c)-(+)-> any command --> (c)
+ | ^ |
+ | | |
+ `-- sets or changes --, ,-- maybe used --' |
+ | | |
+ v | |
+ prefix argument state |
+ ^ |
+ | |
+ `-------- discards --------'
+@end example
+
+@anchor{Transients}
+@subheading Transients
+
+(∩`-´)⊃━☆゚.*・。゚
+
+This diagram ignores the infix value and external state:
+
+@example
+(c)
+ | ,- @{stay@} ------<-,-<------------<-,-<---,
+(+) | | | |
+ | | | | |
+ | | ,--> infix1 --| | |
+ | | | | | |
+ | | |--> infix2 --| | |
+ v v | | | |
+ prefix -(c)-(+)-> infix3 --' ^ |
+ | | |
+ |---------------> suffix1 -->--| |
+ | | |
+ |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
+ | |
+ |---------------> suffix3 -------------> @{exit@} --> (c)
+ | |
+ `--> any command --@{2@}-> @{warn@} -->--|
+ | |
+ |--> @{noop@} -->--|
+ | |
+ |--> @{call@} -->--'
+ |
+ `------------------> @{exit@} --> (c)
+@end example
+
+This diagram takes the infix value into account to an extend, while
+still ignoring external state:
+
+@example
+(c)
+ | ,- @{stay@} ------<-,-<------------<-,-<---,
+(+) | | | |
+ | | | | |
+ | | ,--> infix1 --| | |
+ | | | | | | |
+ | | ,--> infix2 --| | |
+ v v | | | | |
+ prefix -(c)-(+)-> infix3 --' | |
+ | | ^ |
+ | | | |
+ |---------------> suffix1 -->--| |
+ | | ^ | |
+ | | | | |
+ |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
+ | | ^ | |
+ | | | | v
+ | | | | |
+ |---------------> suffix3 -------------> @{exit@} --> (c)
+ | | ^ | |
+ | sets | | v
+ | | maybe | |
+ | | used | |
+ | | | | |
+ | | infix --' | |
+ | `---> value | |
+ | ^ | |
+ | | | |
+ | hides | |
+ | | | |
+ | `--------------------------<---|
+ | | |
+ `--> any command --@{2@}-> @{warn@} -->--| |
+ | | |
+ |--> @{noop@} -->--| |
+ | | |
+ |--> @{call@} -->--' ^
+ | |
+ `------------------> @{exit@} --> (c)
+@end example
+
+This diagram provides more information about the infix value
+and also takes external state into account.
+
+@example
+ ,----sets--- "anything"
+ |
+ v
+ ,---------> external
+ | state
+ | | |
+ | initialized | ☉‿⚆
+ sets from |
+ | | maybe
+ | ,----------' used
+ | | |
+(c) | | v
+ | ,- @{stay@} --|---<-,-<------|-----<-,-<---,
+(+) | | | | | | |
+ | | | v | | | |
+ | | ,--> infix1 --| | | |
+ | | | | | | | | |
+ | | | | v | | | |
+ | | ,--> infix2 --| | | |
+ | | | | ^ | | | |
+ v v | | | | | | |
+ prefix -(c)-(+)-> infix3 --' | | |
+ | | ^ | ^ |
+ | | | v | |
+ |---------------> suffix1 -->--| |
+ | | | ^ | | |
+ | | | | v | |
+ |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
+ | | | ^ | | |
+ | | | | | | v
+ | | | | v | |
+ |---------------> suffix3 -------------> @{exit@} --> (c)
+ | | | ^ | |
+ | sets | | | v
+ | | initialized maybe | |
+ | | from used | |
+ | | | | | |
+ | | `-- infix ---' | |
+ | `---> value -----------------------------> persistent
+ | ^ ^ | | across
+ | | | | | invocations -,
+ | hides | | | |
+ | | `----------------------------------------------'
+ | | | |
+ | `--------------------------<---|
+ | | |
+ `--> any command --@{2@}-> @{warn@} -->--| |
+ | | |
+ |--> @{noop@} -->--| |
+ | | |
+ |--> @{call@} -->--' ^
+ | |
+ `------------------> @{exit@} --> (c)
+@end example
+
+@itemize
+@item
+@code{@{1@}} Transients can be configured to be exited when a suffix command
+is invoked. The default is to do so for all suffixes except for
+those that are common to all transients and which are used to
+perform tasks such as providing help and saving the value of the
+infix arguments for future invocations. The behavior can also be
+specified for individual suffix commands and may even depend on
+state.
+
+@item
+@code{@{2@}} Transients can be configured to allow the user to invoke
+non-suffix commands. The default is to not allow that and instead
+warn the user.
+@end itemize
+
+Despite already being rather complex, even the last diagram leaves out
+many details. Most importantly it implies that the decision whether
+to remain transient is made later than it actually is made (for the
+most part a function on @code{pre-command-hook} is responsible). But such
+implementation details are of little relevance to users and are
+covered elsewhere.
+
+@node Comparison With Other Packages
+@section Comparison With Other Packages
+
+@anchor{Magit-Popup}
+@subheading Magit-Popup
+
+Transient is the successor to Magit-Popup (@pxref{Top,,,magit-popup,}).
+
+One major difference between these two implementations of the same
+ideas is that while Transient uses transient keymaps and embraces the
+command-loop, Magit-Popup implemented an inferior mechanism that does
+not use transient keymaps and that instead of using the command-loop
+implements a naive alternative based on @code{read-char}.
+
+Magit-Popup does not use classes and generic functions and defining a
+new command type is near impossible as it involves adding hard-coded
+special-cases to many functions. Because of that only a single new
+type was added, which was not already part of Magit-Popup's initial
+release.
+
+A lot of things are hard-coded in Magit-Popup. One random example is
+that the key bindings for switches must begin with @code{-} and those for
+options must begin with @code{=}.
+
+@anchor{Hydra}
+@subheading Hydra
+
+Hydra (see @uref{https://github.com/abo-abo/hydra}) is another package that
+provides features similar to those of Transient.
+
+Both packages use transient keymaps to make a set of commands
+temporarily available and show the available commands in a popup
+buffer.
+
+A Hydra ``body'' is equivalent to a Transient ``prefix'' and a Hydra
+``head'' is equivalent to a Transient ``suffix''. Hydra has no equivalent
+of a Transient ``infix''.
+
+Both hydras and transients can be used as simple command dispatchers.
+Used like this they are similar to regular prefix commands and prefix
+keys, except that the available commands are shown in the popup buffer.
+
+(Another package that does this is @code{which-key}. It does so automatically
+for any incomplete key sequence. The advantage of that approach is
+that no additional work is necessary; the disadvantage is that the
+available commands are not organized semantically.)
+
+Both Hydra and Transient provide features that go beyond simple
+command dispatchers:
+
+@itemize
+@item
+Invoking a command from a hydra does not necessarily exit the hydra.
+That makes it possible to invoke the same command again, but using a
+shorter key sequence (i.e. the key that was used to enter the hydra
+does not have to be pressed again).
+
+Transient supports that too, but for now this feature is not a focus
+and the interface is a bit more complicated. A very basic example
+using the current interface:
+
+@lisp
+(transient-define-prefix outline-navigate ()
+ :transient-suffix 'transient--do-stay
+ :transient-non-suffix 'transient--do-warn
+ [("p" "previous visible heading" outline-previous-visible-heading)
+ ("n" "next visible heading" outline-next-visible-heading)])
+@end lisp
+
+
+@item
+Transient supports infix arguments; values that are set by infix
+commands and then consumed by the invoked suffix command(s).
+
+To my knowledge, Hydra does not support that.
+@end itemize
+
+Both packages make it possible to specify how exactly the available
+commands are outlined:
+
+@itemize
+@item
+With Hydra this is often done using an explicit format string, which
+gives authors a lot of flexibility and makes it possible to do fancy
+things.
+
+The downside of this is that it becomes harder for a user to add
+additional commands to an existing hydra and to change key bindings.
+
+@item
+Transient allows the author of a transient to organize the commands
+into groups and the use of generic functions allows authors of
+transients to control exactly how a certain command type is
+displayed.
+
+However while Transient supports giving sections a heading it does
+not currently support giving the displayed information more
+structure by, for example, using box-drawing characters.
+
+That could be implemented by defining a new group class, which lets
+the author specify a format string. It should be possible to
+implement that without modifying any existing code, but it does not
+currently exist.
+@end itemize
+
+@node FAQ
+@appendix FAQ
+
+
+
+@anchor{Can I control how the popup buffer is displayed?}
+@appendixsec Can I control how the popup buffer is displayed?
+
+Yes, see @code{transient-display-buffer-action} in @ref{Other Options}.
+
+@anchor{Why did some of the key bindings change?}
+@appendixsec Why did some of the key bindings change?
+
+You may have noticed that the bindings for some of the common commands
+do @strong{not} have the prefix @code{C-x} and that furthermore some of these commands
+are grayed out while others are not. That unfortunately is a bit
+confusing if the section of common commands is not shown permanently,
+making the following explanation necessary.
+
+The purpose of usually hiding that section but showing it after the
+user pressed the respective prefix key is to conserve space and not
+overwhelm users with too much noise, while allowing the user to
+quickly list common bindings on demand.
+
+That however should not keep us from using the best possible key
+bindings. The bindings that do use a prefix do so to avoid wasting
+too many non-prefix bindings, keeping them available for use in
+individual transients. The bindings that do not use a prefix and that
+are @strong{not} grayed out are very important bindings that are @strong{always}
+available, even when invoking the ``common command key prefix'' or @strong{any
+other} transient-specific prefix. The non-prefix keys that @strong{are} grayed
+out however, are not available when any incomplete prefix key sequence
+is active. They do not use the ``common command key prefix'' because it
+is likely that users want to invoke them several times in a row and
+e.g. @kbd{M-p M-p M-p} is much more convenient than
+@kbd{C-x M-p C-x M-p C-x M-p}.
+
+You may also have noticed that the "Set" command is bound to @kbd{C-x s},
+while Magit-Popup used to bind @kbd{C-c C-c} instead. I have seen several
+users praise the latter binding (sic), so I did not change it
+willy-nilly. The reason that I changed it is that using different
+prefix keys for different common commands, would have made the
+temporary display of the common commands even more confusing,
+i.e. after pressing @kbd{C-c} all the @kbd{C-x ...} bindings would be grayed out.
+
+Using a single prefix for common commands key means that all other
+potential prefix keys can be used for transient-specific commands
+@strong{without} the section of common commands also popping up. @code{C-c} in
+particular is a prefix that I want to (and already do) use for Magit, and
+also using that for a common command would prevent me from doing so.
+
+(Also see the next question.)
+
+@anchor{Why does @code{q} not quit popups anymore?}
+@appendixsec Why does @code{q} not quit popups anymore?
+
+I agree that @kbd{q} is a good binding for commands that quit something.
+This includes quitting whatever transient is currently active, but it
+also includes quitting whatever it is that some specific transient is
+controlling. The transient @code{magit-blame} for example binds @code{q} to the
+command that turns @code{magit-blame-mode} off.
+
+So I had to decide if @kbd{q} should quit the active transient (like
+Magit-Popup used to) or whether @kbd{C-g} should do that instead, so
+that @kbd{q}
+could be bound in individual transient to whatever commands make sense
+for them. Because all other letters are already reserved for use by
+individual transients, I have decided to no longer make an exception
+for @kbd{q}.
+
+If you want to get @kbd{q}'s old binding back then you can do so. Doing
+that is a bit more complicated than changing a single key binding, so
+I have implemented a function, @code{transient-bind-q-to-quit} that makes the
+necessary changes. See its doc string for more information.
+
+@node Keystroke Index
+@appendix Keystroke Index
+
+@printindex ky
+
+@node Command and Function Index
+@appendix Command and Function Index
+
+@printindex fn
+
+@node Variable Index
+@appendix Variable Index
+
+@printindex vr
+
+@node Concept Index
+@appendix Concept and Feature Index
+
+@printindex cp
+
+@node GNU General Public License
+@appendix GNU General Public License
+
+@include gpl.texi
+
+@bye
diff --git a/doc/misc/vtable.texi b/doc/misc/vtable.texi
new file mode 100644
index 00000000000..296dc520a1b
--- /dev/null
+++ b/doc/misc/vtable.texi
@@ -0,0 +1,577 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename ../../info/vtable.info
+@settitle Variable Pitch Tables
+@include docstyle.texi
+@c Merge all indexes into a single Index node.
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex ky cp
+@c %**end of header
+
+@copying
+This file documents the GNU vtable.el package.
+
+Copyright @copyright{} 2022 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below. A copy of the license
+is included in the section entitled ``GNU Free Documentation License.''
+
+(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+modify this GNU manual.''
+@end quotation
+@end copying
+
+@dircategory Emacs misc features
+@direntry
+* vtable: (vtable). Variable Pitch Tables.
+@end direntry
+
+@finalout
+
+@titlepage
+@title Variable Pitch Tables
+@subtitle Columnar Display of Data.
+
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@ifnottex
+@node Top
+@top vtable
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction:: Introduction and examples.
+* Concepts:: vtable concepts.
+* Making A Table:: The main interface function.
+* Commands:: vtable commands.
+* Interface Functions:: Interface functions.
+
+Appendices
+* GNU Free Documentation License:: The license for this documentation.
+
+Indices
+* Index::
+@end menu
+
+@node Introduction
+@chapter Introduction and Tutorial
+
+Most modes that display tabular data in Emacs use
+@code{tabulated-list-mode}, but it has some limitations: It assumes
+that the text it's displaying is monospaced, which makes it difficult
+to mix fonts and images in a single list. The @dfn{vtable} (``variable
+pitch tables'') package tackles this instead.
+
+@code{tabulated-list-mode} is a major mode, and assumes that it
+controls the entire buffer. A vtable doesn't assume that---you can have
+a vtable in the middle of other data, or have several vtables in the
+same buffer.
+
+Here's just about the simplest vtable that can be created:
+
+@lisp
+(make-vtable
+ :objects '(("Foo" 1034)
+ ("Gazonk" 45)))
+@end lisp
+
+By default, vtable uses the @code{vtable} face (which inherits from
+the @code{variable-pitch} face), and right-aligns columns that have
+only numerical data (and left-aligns the rest).
+
+You'd normally want to name the columns:
+
+@lisp
+(make-vtable
+ :columns '("Name" "ID")
+ :objects '(("Foo" 1034)
+ ("Gazonk" 45)))
+@end lisp
+
+Clicking on the column names will sort the table based on the data in
+each column (which, in this example, corresponds to an element in a
+list).
+
+By default, the data is displayed ``as is'', that is, the way
+@samp{(format "%s" ...)} would display it, but you can override that.
+
+@lisp
+(make-vtable
+ :columns '("Name" "ID")
+ :objects '(("Foo" 1034)
+ ("Gazonk" 45))
+ :formatter (lambda (value column &rest _)
+ (if (= column 1)
+ (file-size-human-readable value)
+ value)))
+@end lisp
+
+In this case, that @samp{1034} will be displayed as @samp{1k}---but
+will still sort after @samp{45}, because sorting is done on the actual
+data, and not the displayed data.
+
+Alternatively, instead of having a general formatter for the table,
+you can put the formatter in the column definition:
+
+@lisp
+(make-vtable
+ :columns '("Name"
+ (:name "ID" :formatter file-size-human-readable))
+ :objects '(("Foo" 1034)
+ ("Gazonk" 45)))
+@end lisp
+
+The data doesn't have to be simple lists---you can give any type of
+object to vtable, but then you also have to write a function that
+returns the data for each column. For instance, here's a very simple
+version of @kbd{M-x list-buffers}:
+
+@lisp
+(make-vtable
+ :columns '("Name" "Size" "File")
+ :objects (buffer-list)
+ :actions '("k" kill-buffer
+ "RET" display-buffer)
+ :getter (lambda (object column vtable)
+ (pcase (vtable-column vtable column)
+ ("Name" (buffer-name object))
+ ("Size" (buffer-size object))
+ ("File" (or (buffer-file-name object) "")))))
+@end lisp
+
+@var{objects} in this case is a list of buffers. To get the data to
+be displayed, vtable calls the @dfn{getter} function, which is called
+for each column of every object, and which should return the data that
+will eventually be displayed.
+
+Also note the @dfn{actions}: These are simple commands that will be
+called with the object under point. So hitting @kbd{@key{RET}} on a line
+will result in @code{display-buffer} being called with a buffer object
+as the parameter. (You can also supply a keymap to be used, but then
+you have to write commands that call @code{vtable-current-object} to
+get at the object.)
+
+Note that the actions aren't called with the data displayed in the
+buffer---they're called with the original objects.
+
+Finally, here's an example that uses just about all the features:
+
+@lisp
+(make-vtable
+ :columns `(( :name "Thumb" :width "500px"
+ :displayer
+ ,(lambda (value max-width table)
+ (propertize "*" 'display
+ (create-image value nil nil
+ :max-width max-width))))
+ (:name "Size" :width 10
+ :formatter file-size-human-readable)
+ (:name "Time" :width 10 :primary ascend)
+ "Name")
+ :objects-function (lambda ()
+ (directory-files "/tmp/" t "\\.jpg\\'"))
+ :actions '("RET" find-file)
+ :getter (lambda (object column table)
+ (pcase (vtable-column table column)
+ ("Name" (file-name-nondirectory object))
+ ("Thumb" object)
+ ("Size" (file-attribute-size (file-attributes object)))
+ ("Time" (format-time-string
+ "%F" (file-attribute-modification-time
+ (file-attributes object))))))
+ :separator-width 5
+ :keymap (define-keymap
+ "q" #'kill-buffer))
+@end lisp
+
+This vtable implements a simple image browser that displays image
+thumbnails (that change sizes dynamically depending on the width of
+the column), human-readable file sizes, date and file name. The
+separator width is 5 typical characters wide. Hitting @kbd{@key{RET}} on a
+line will open the image in a new window, and hitting @kbd{q} will
+kill a buffer.
+
+@node Concepts
+@chapter Concepts
+
+@cindex vtable
+A vtable lists data about a number of @dfn{objects}. Each object can
+be a list or a vector, but it can also be anything else.
+
+@cindex getter of a vtable
+To get the @dfn{value} for a particular column, the @dfn{getter}
+function is called on the object. If no getter function is defined,
+the default is to try to index the object as a sequence. In any case,
+we end up with a value that is then used for sorting.
+
+@cindex formatter of a vtable
+This value is then @dfn{formatted} via a @dfn{formatter} function,
+which is called with the @dfn{value} as the argument. The formatter
+commonly makes the value more reader friendly.
+
+@cindex displayer of a vtable
+Finally, the formatted value is passed to the @dfn{displayer}
+function, which is responsible for putting the table face on the
+formatted value, and also ensuring that it's not wider than the column
+width. The displayer will commonly truncate too-long strings and
+scale image sizes.
+
+All these three transforms, the getter, the formatter and the display
+functions, can be defined on a per-column basis, and also on a
+per-table basis. (The per-column transform takes precedence over the
+per-table transform.)
+
+User commands that are defined on a table does not work on the
+displayed data. Instead they are called with the original object as
+the argument.
+
+@node Making A Table
+@chapter Making A Table
+
+@findex make-vtable
+The interface function for making (and optionally inserting a table
+into a buffer) is @code{make-vtable}. It returns a table object.
+
+The keyword parameters are described below.
+
+There are many callback interface functions possible in
+@code{make-vtable}, and many of them take a @var{object} argument (an
+object from the @code{:objects} list), a column index argument (an
+integer starting at zero), and a table argument (the object returned
+by @code{make-vtable}).
+
+@table @code
+@item :objects
+This is a list of objects to be displayed. It should either be a list
+of strings (which will then be displayed as a single-column table), or
+a list where each element is a sequence containing a mixture of
+strings, numbers, and other objects that can be displayed ``simply''.
+
+In the latter case, if @code{:columns} is non-@code{nil} and there's
+more elements in the sequence than there is in @code{:columns}, only
+the @code{:columns} first elements are displayed.
+
+@item :objects-function
+It's often convenient to generate the objects dynamically (for
+instance, to make reversion work automatically). In that case, this
+should be a function (which will be called with no arguments), and
+should return a value as accepted as an @code{:objects} list.
+
+@item :columns
+This is a list where each element is either a string (the column
+name), a plist of keyword/values (to make a @code{vtable-column}
+object), or a full @code{vtable-column} object. A
+@code{vtable-column} object has the following slots:
+
+@table @code
+@item name
+The name of the column.
+
+@item width
+The width of the column. This is either a number (the width of that
+many @samp{x} characters in the table's face), or a string on the form
+@samp{Xe@var{x}}, where @var{x} is a number of @samp{x} characters, or a
+string on the form @samp{Xp@var{x}} (denoting a number of pixels), or a
+string on the form @samp{X%} (a percentage of the window's width).
+
+@item min-width
+This uses the same format as @code{width}, but specifies the minimum
+width (and overrides @code{width} if @code{width} is smaller than this.
+
+@item max-width
+This uses the same format as @code{width}, but specifies the maximum
+width (and overrides @code{width} if @code{width} is larger than this.
+@code{min-width}/@code{max-width} can be useful if @code{width} is
+given as a percentage of the window width, and you want to ensure that
+the column doesn't grow pointlessly large or unreadably narrow.
+
+@item primary
+Whether this is the primary column---this will be used for initial
+sorting. This should be either @code{ascend} or @code{descend} to say
+in which order the table should be sorted.
+
+@item getter
+If present, this function will be called to return the column value.
+
+@defun column-getter object table
+It's called with two parameters: the object and the table.
+@end defun
+
+@item formatter
+If present, this function will be called to format the value.
+
+@defun column-formatter value
+It's called with one parameter: the column value.
+@end defun
+
+@item displayer
+If present, this function will be called to prepare the formatted
+value for display. This function should return a string with the
+table face applied, and also limit the width of the string to the
+display width.
+
+@defun column-displayer fvalue max-width table
+@var{fvalue} is the formatted value; @var{max-width} is the maximum
+width (in pixels), and @var{table} is the table.
+@end defun
+
+@item align
+Should be either @code{right} or @code{left}.
+@end table
+
+@item :getter
+If given, this is a function that should return the values to use in
+the table, and will be called once for each element in the table
+(unless overridden by a column getter function).
+
+@defun getter object index table
+For a simple object (like a sequence), this function will typically
+just return the element corresponding to the column index (zero-based), but the
+function can do any computation it wants. If it's more convenient to
+write the function based on column names rather than the column index,
+the @code{vtable-column} function can be used to map from index to name.
+@end defun
+
+@item :formatter
+If present, this is a function that should format the value, and it
+will be called on all values in the table (unless overridden by a
+column formatter).
+
+@defun formatter value index table
+This function is called with three parameters: the value (as returned
+by the getter); the column index, and the table. It can return any
+value.
+
+This can be used to (for instance) format numbers in a human-readable
+form.
+@end defun
+
+@item :displayer
+Before displaying an element, it's passed to the displaying function
+(if any).
+
+@defun displayer fvalue index max-width table
+This is called with four arguments: the formatted value of the element
+(as returned by the formatter function); the column index; the display
+width (in pixels); and the table.
+
+This function should return a string with the table face applied, and
+truncated to the display width.
+
+This can be used to (for instance) change the size of images that are
+displayed in the table.
+@end defun
+
+@item :use-header-line
+If non-@code{nil} (which is the default), display the column names on
+the header line. This is the most common use
+case, but if there's other text in the buffer before the table, or
+there are several tables in the same buffer, then this should be
+@code{nil}.
+
+@item :face
+The face to be used. This defaults to @code{vtable}. This face
+doesn't override the faces in the data, or the faces supplied by the
+getter and formatter functions.
+
+@item :row-colors
+If present, this should be a list of color names to be used as the
+background color on the rows. If there are fewer colors here than
+there are rows, the rows will be repeated. The most common use
+case here is to have alternating background colors on the rows, so
+this would usually be a list of two colors. This can also be a list
+of faces to be used.
+
+@item :column-colors
+If present, this should be a list of color names to be used as the
+background color on the columns. If there are fewer colors here than
+there are columns, the colors will be repeated. The most common use
+case here is to have alternating background colors on the columns, so
+this would usually be a list of two colors. This can also be a list
+of faces to be used. If both @code{:row-colors} and
+@code{:column-colors} is present, the colors will be ``blended'' to
+produce the final colors in the table.
+
+@item :actions
+This uses the same syntax as @code{define-keymap}, but doesn't refer
+to commands directly. Instead each key is bound to a command that
+picks out the current object, and then calls the function specified
+with that as the argument.
+
+@item :keymap
+This is a keymap used on the table. The commands here are called as
+usual, and if they're supposed to work on the object displayed on the
+current line, they can use the @code{vtable-current-object} function
+(@pxref{Interface Functions}) to determine what that object is.
+
+@item :separator-width
+The width of the blank space between columns.
+
+@item :divider-width
+@itemx :divider
+You can have a divider inserted between the columns. This can either
+be specified by using @code{:divider}, which should be a string to be
+displayed between the columns, or @code{:divider-width}, which
+specifies the width of the space to be used as the divider.
+
+@item :sort-by
+This should be a list of tuples, and specifies how the table is to be
+sorted. Each tuple should consist of an integer (the column index)
+and either @code{ascend} or @code{descend}.
+
+The table is first sorted by the first element in this list, and then
+the next, until the end is reached.
+
+@item :ellipsis
+By default, when shortening displayed values, an ellipsis will be
+shown. If this is @code{nil}, no ellipsis is shown. (The text to use
+as the ellipsis is determined by the @code{truncate-string-ellipsis}
+function.)
+
+@findex vtable-insert
+@item :insert
+By default, @code{make-vtable} will insert the table at point. If this
+is @code{nil}, nothing is inserted, but the vtable object is returned,
+and you can insert it later with the @code{vtable-insert} function.
+@end table
+
+@code{make-table} returns a @code{vtable} object. You can access the
+slots in that object by using accessor functions that have names based
+on the keywords described above. For instance, to access the face,
+use @code{vtable-face}.
+
+@node Commands
+@chapter Commands
+@cindex vtable commands
+
+When point is placed on a vtable, the following keys are bound:
+
+@table @kbd
+@findex vtable-sort-by-current-column
+@item S
+Sort the table by the current column
+(@code{vtable-sort-by-current-column}). Note that the table is sorted
+according to the data returned by the getter function (@pxref{Making A
+Table}), not by how it's
+displayed in the buffer. Columns that have only numerical data is
+sorted as numbers, the rest are sorted as strings.
+
+@findex vtable-narrow-current-column
+@item @{
+Make the current column narrower
+(@code{vtable-narrow-current-column}).
+
+@findex vtable-widen-current-column
+@item @}
+Make the current column wider
+(@code{vtable-widen-current-column}).
+
+@findex vtable-previous-column
+@item M-<left>
+Move to the previous column (@code{vtable-previous-column}).
+
+@findex vtable-next-column
+@item M-<right>
+Move to the next column (@code{vtable-next-column}).
+
+@findex vtable-revert-command
+@item g
+Regenerate the table (@code{vtable-revert-command}). This command
+mostly makes sense if the table has a @code{:objects-function} that
+can fetch new data.
+@end table
+
+@node Interface Functions
+@chapter Interface Functions
+
+If you need to write a mode based on vtable, you will have to interact
+with the table in
+various ways---for instance, you'll need to write commands that
+updates an object
+and then displays the result. This chapter describes functions for
+such interaction.
+
+@defun vtable-current-table
+This function returns the table under point.
+@end defun
+
+@defun vtable-current-object
+This function returns the object on the current line. (Note that this
+is the original object, not the characters displayed in the
+buffer.)
+@end defun
+
+@defun vtable-current-column
+This function returns the column index of the column under point.
+@end defun
+
+@defun vtable-goto-table table
+Move point to the start of @var{table} and return the position. If
+@var{table} can't be found in the current buffer, don't move point and
+return @code{nil}.
+@end defun
+
+@defun vtable-goto-object object
+Move point to the start of the line where @var{object} is displayed in
+the current table and return the position. If @var{object} can't be found,
+don't move point and return @code{nil}.
+@end defun
+
+@defun vtable-goto-column index
+Move point to the start of the @var{index}th column. (The first
+column is numbered zero.)
+@end defun
+
+@defun vtable-beginning-of-table
+Move to the beginning of the current table.
+@end defun
+
+@defun vtable-end-of-table
+Move to the end of the current table.
+@end defun
+
+@defun vtable-remove-object table object
+Remove @var{object} from @var{table}. This also updates the displayed
+table.
+@end defun
+
+@defun vtable-insert-object table object &optional after-object
+Insert @var{object} into @var{table}. If @var{after-object}, insert
+the object after this object; otherwise append to @var{table}. This
+also updates the displayed table.
+@end defun
+
+@defun vtable-update-object table object old-object
+Change @var{old-object} into @var{object} in @var{table}. This also
+updates the displayed table.
+
+This has the same effect as calling @code{vtable-remove-object} and
+then @code{vtable-insert-object}, but is more efficient.
+@end defun
+
+@defun vtable-column table index
+Return the column name of the @var{index}th column in @var{table}.
+@end defun
+
+@node GNU Free Documentation License
+@chapter GNU Free Documentation License
+@include doclicense.texi
+
+@node Index
+@unnumbered Index
+@printindex cp
+
+@bye
diff --git a/etc/AUTHORS b/etc/AUTHORS
index 60b1ee4bd01..b5444e60a76 100644
--- a/etc/AUTHORS
+++ b/etc/AUTHORS
@@ -105,9 +105,9 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-fonts.el
cc-langs.el cc-mode.el cc-styles.el cc-vars.el
and changed cc-mode.texi minibuf.c bytecomp.el edebug.el follow.el
window.c display.texi subr.el syntax.texi progmodes/compile.el
- programs.texi keyboard.c lisp.h modes.texi window.el windows.texi
- cus-start.el eval.c font-lock.el isearch.el newcomment.el
- and 166 other files
+ programs.texi eval.c keyboard.c lisp.h modes.texi window.el
+ windows.texi cus-start.el font-lock.el frame.c isearch.el
+ and 167 other files
Alan Modra: changed unexelf.c
@@ -127,8 +127,7 @@ and changed nsterm.m nsterm.h nsfns.m image.c nsmenu.m configure.ac
Alastair Burt: changed gnus-art.el smiley.el
Albert Krewinkel: co-wrote sieve-manage.el
-and changed sieve.el gnus-msg.el gnus.texi mail/sieve-manage.el
- message.el sieve.texi
+and changed sieve.el gnus-msg.el gnus.texi message.el sieve.texi
Albert L. Ting: changed gnus-group.el mail-hist.el
@@ -181,7 +180,7 @@ Alexandre Julliard: wrote vc-git.el
and changed vc.el ewoc.el
Alexandre Oliva: wrote gnus-mlspl.el
-and changed unexelf.c emacs-regex.c format.el iris4d.h iris5d.h unexsgi.c
+and changed unexelf.c format.el iris4d.h iris5d.h regex-emacs.c unexsgi.c
Alexandre Veyrenc: changed fr-refcard.tex
@@ -332,9 +331,9 @@ Andreas Schwab: changed configure.ac lisp.h xdisp.c process.c alloc.c
Andreas Seltenreich: changed nnweb.el gnus.texi message.el gnus-sum.el
gnus.el nnslashdot.el gnus-srvr.el gnus-util.el mm-url.el mm-uu.el
- url-http.el xterm.c battery.el comint.el doc/misc/gnus.texi
- easy-mmode.el gmm-utils.el gnus-art.el gnus-cite.el gnus-draft.el
- gnus-group.el and 7 other files
+ url-http.el xterm.c battery.el comint.el easy-mmode.el gmm-utils.el
+ gnus-art.el gnus-cite.el gnus-draft.el gnus-group.el gnus-ml.el
+ and 6 other files
Andreas Vögele: changed pgg-def.el
@@ -376,9 +375,9 @@ Andrew Hyatt: changed bug-triage CONTRIBUTE org-archive.el org.el
org.texi
Andrew Innes: changed makefile.nt w32fns.c w32term.c w32.c w32proc.c
- fileio.c w32-fns.el dos-w32.el inc/ms-w32.h w32term.h makefile.def
+ fileio.c ms-w32.h w32-fns.el dos-w32.el w32term.h makefile.def
unexw32.c w32menu.c w32xfns.c addpm.c cmdproxy.c emacs.c w32-win.el
- w32inevt.c configure.bat lread.c and 129 other files
+ w32inevt.c configure.bat lread.c and 128 other files
Andrew L. Moore: changed executable.el
@@ -442,8 +441,9 @@ Antoine Levitt: changed gnus-group.el gnus-sum.el message.texi
Antonin Houska: changed newcomment.el
-Arash Esbati: changed reftex-vars.el reftex-auc.el reftex-ref.el
- reftex.el nnmaildir.el reftex-cite.el reftex-dcr.el reftex-toc.el
+Arash Esbati: changed reftex-vars.el efaq-w32.texi reftex-auc.el
+ reftex-ref.el reftex.el gnus.texi nnmaildir.el reftex-cite.el
+ reftex-dcr.el reftex-toc.el
Arik Mitschang: changed smime.el
@@ -479,11 +479,11 @@ Arthur Miller: changed help-fns.el ange-ftp.el bytecomp.el comp.c comp.el
Artur Malabarba: wrote char-fold-tests.el faces-tests.el isearch-tests.el
let-alist.el simple-tests.el sort-tests.el tabulated-list-tests.el
-and changed package.el isearch.el lisp/char-fold.el files.el
- tabulated-list.el package-test.el menu-bar.el replace.el bytecomp.el
- faces.el files-x.el custom.el custom.texi help-fns.el
- let-alist-tests.el simple.el subr-tests.el align.el bindings.el
- cl-lib-tests.el cl-macs.el and 43 other files
+and changed package.el isearch.el char-fold.el files.el tabulated-list.el
+ package-test.el menu-bar.el replace.el bytecomp.el faces.el files-x.el
+ custom.el custom.texi help-fns.el let-alist-tests.el simple.el
+ subr-tests.el align.el bindings.el cl-lib-tests.el cl-macs.el
+ and 43 other files
Artyom Loenko: changed Info.plist.in
@@ -543,7 +543,7 @@ Basil L. Contovounesios: changed simple.el message.el subr.el eww.el
custom.el bibtex.el text.texi gnus-sum.el modes.texi customize.texi
files.texi gnus-group.el gnus-win.el gravatar.el internals.texi json.el
shr.el window.c battery-tests.el button.el custom-tests.el
- and 278 other files
+ and 279 other files
Bastian Beischer: changed semantic/complete.el calc-yank.el include.el
mru-bookmark.el refs.el senator.el
@@ -576,7 +576,7 @@ and changed org-clock.el org.el
Benjamin Ragheb: changed fortune.el
Benjamin Riefenstahl: changed files.el image-mode.el nnrss-tests.el
- w32select.c emacs.c image.el inc/ms-w32.h lisp.h mac-win.el macterm.c
+ w32select.c emacs.c image.el lisp.h mac-win.el macterm.c ms-w32.h
mule-cmds.el nnrss.el runemacs.c tcl.el w32.c w32.h
Benjamin Rutt: co-wrote gnus-dired.el
@@ -584,7 +584,7 @@ and changed vc.el gnus-msg.el message.el diff-mode.el ffap.el nnimap.el
nnmbox.el simple.el vc-cvs.el
Ben Key: changed w32.c w32fns.c w32menu.c configure.bat INSTALL w32.h
- w32term.c configure.ac emacs.c inc/ms-w32.h keyboard.c make-docfile.c
+ w32term.c configure.ac emacs.c keyboard.c make-docfile.c ms-w32.h
nsfont.m nsterm.m sound.c xfaces.c
Ben Menasha: changed nnmh.el
@@ -656,8 +656,8 @@ Bob Nnamtrop: changed viper-cmd.el
Bob Olson: co-wrote cperl-mode.el
Bob Rogers: changed vc-dir.el vc-svn.el cperl-mode.el diff.el ewoc.el
- ffap.el files.el maintaining.texi sql.el thingatpt.el vc.el
- vc1-xtra.texi
+ ffap.el files.el ietf-drums.el maintaining.texi sql.el thingatpt.el
+ vc.el vc1-xtra.texi
Bob Weiner: changed info.el quail.el dframe.el etags.c rmail.el
rmailsum.el speedbar.el
@@ -709,7 +709,8 @@ Brian Fox: changed Makefile.in Makefile configure.ac minibuf.c dired.el
Brian Jenkins: changed frame.c frames.texi hooks.texi
Brian Leung: changed comint.el gud.el advice.el comp.c comp.el em-hist.el
- files.el find-func.el gdb-mi.el help.el nadvice.el shell.el shortdoc.el
+ files.el find-func.el flymake.el gdb-mi.el help.el nadvice.el shell.el
+ shortdoc.el
Brian Marick: co-wrote hideif.el
@@ -751,7 +752,9 @@ Caleb Deupree: changed w32-fns.el
Callum Cameron: changed term.el
Cameron Desautels: changed cus-edit.el custom.texi help.el regexp-opt.el
- ruby-mode.el
+ ruby-mode.el titdic-cnv.el
+
+Campbell Barton: changed bookmark.el
Carl D. Roth: changed gnus-nocem.el
@@ -848,8 +851,8 @@ Chris Hall: changed callproc.c frame.c
Chris Hanson: changed xscheme.el scheme.el xterm.c hpux.h x11term.c
hp9000s300.h keyboard.c process.c texinfmt.el sort.el syntax.c
- texnfo-upd.el x11fns.c xfns.c dired.el emacs-regex.c emacsclient.c
- fileio.c hp9000s800.h indent.c info.el and 17 other files
+ texnfo-upd.el x11fns.c xfns.c dired.el emacsclient.c fileio.c
+ hp9000s800.h indent.c info.el man.el and 17 other files
Chris Hecker: changed calc-aent.el
@@ -869,6 +872,8 @@ Chris Prince: changed w32term.c
Chris Smith: wrote icon.el
and changed icon-mode.el
+Christer Enfors: changed erc.texi
+
Christian Egli: changed org-taskjuggler.el org.texi
Christian Faulhammer: changed configure configure.ac src/Makefile.in
@@ -969,12 +974,10 @@ Claudio Fontana: changed Makefile.in leim/Makefile.in lib-src/Makefile.in
Clemens Radermacher: changed cus-start.el frame.c minibuf.texi window.el
-Clément Pit--Claudel: changed debugging.texi emacs-lisp/debug.el eval.c
- progmodes/python.el subr-tests.el subr.el url-http.el url-vars.el
-
Clément Pit-Claudel: changed Dockerfile.emba button.el configure.ac
- display.texi ert.el gitlab-ci.yml keyboard.c tex-mode.el text.texi
- xdisp.c
+ debugging.texi display.texi emacs-lisp/debug.el ert.el eval.c
+ gitlab-ci.yml keyboard.c progmodes/python.el subr-tests.el subr.el
+ tex-mode.el text.texi url-http.el url-vars.el xdisp.c
Codruț Constantin Gușoi: changed files.el
@@ -1028,11 +1031,11 @@ Dale Sedivec: changed sgml-mode.el wisent/python.el
Damien Cassou: wrote auth-source-pass-tests.el hierarchy-tests.el
hierarchy.el
and co-wrote auth-source-pass.el auth-source-tests.el
-and changed auth.texi checkdoc.el ispell.el message.el seq-tests.el
- seq.el simple-tests.el simple.el auth-source.el autorevert.el
+and changed simple.el auth.texi checkdoc.el ispell.el message.el
+ seq-tests.el seq.el simple-tests.el auth-source.el autorevert.el
checkdoc-tests.el imenu-tests.el imenu.el info.el isearch.el
- json-tests.el json.el message-tests.el package.el rmc.el sequences.texi
- xref.el
+ json-tests.el json.el message-tests.el package.el rmc.el sending.texi
+ and 3 other files
Damien Elmes: changed erc.el erc-dcc.el erc-track.el erc-log.el
erc-pcomplete.el README erc-button.el erc-nets.el erc-ring.el Makefile
@@ -1110,9 +1113,9 @@ Daniel Lublin: changed dns-mode.el
Daniel Martín: changed shortdoc.el nsterm.m erc.texi files.el files.texi
msdos-xtra.texi ns-win.el basic.texi cmacexp.el compilation.txt
- compile-tests.el cscope.el diff.el dired.el editfns.c emacs.texi
- files-tests.el find-func-tests.el find-func.el frame.c frame.el
- and 16 other files
+ compile-tests.el cscope.el diff.el dired.el display.texi editfns.c
+ emacs.texi files-tests.el find-func-tests.el find-func.el frame.c
+ and 18 other files
Daniel McClanahan: changed lisp-mode.el
@@ -1269,7 +1272,7 @@ David Hedbor: changed nnmail.el
David Hull: changed etags.c vc-hg.el
-David Hunter: changed flymake.el inc/ms-w32.h process.c
+David Hunter: changed flymake.el ms-w32.h process.c
David J. Biesack: changed antlr-mode.el quickurl.el
@@ -1473,7 +1476,7 @@ and changed xref.el ruby-mode.el project.el vc-git.el elisp-mode.el
etags.el ruby-mode-tests.el js.el vc.el vc-hg.el package.el
symref/grep.el dired-aux.el simple.el log-edit.el minibuffer.el
progmodes/grep.el ido.el maintaining.texi menu-bar.el package-test.el
- and 123 other files
+ and 122 other files
Dmitry Kurochkin: changed isearch.el
@@ -1511,8 +1514,8 @@ and changed dired.el cus-edit.el imenu.el info.el ls-lisp.el menu-bar.el
apropos.el bindings.el and 22 other files
Earl Hyatt: changed ffap.el seq-tests.el sequences.texi windows.texi
- control.texi cus-edit.el hi-lock.el misc.texi pcase-tests.el pcase.el
- replace.el search.texi seq.el tab-bar.el
+ autotype.texi control.texi cus-edit.el hi-lock.el misc.texi
+ pcase-tests.el pcase.el replace.el search.texi seq.el tab-bar.el
E. Choroba: changed cperl-mode.el simple.el
@@ -1569,9 +1572,9 @@ Eli Zaretskii: wrote [bidirectional display in xdisp.c]
chartab-tests.el coding-tests.el etags-tests.el rxvt.el tty-colors.el
and co-wrote help-tests.el
and changed xdisp.c display.texi w32.c msdos.c w32fns.c simple.el
- files.el fileio.c keyboard.c emacs.c w32term.c text.texi dispnew.c
- w32proc.c files.texi frames.texi configure.ac lisp.h dispextern.h
- process.c editfns.c and 1231 other files
+ files.el fileio.c emacs.c keyboard.c w32term.c text.texi dispnew.c
+ w32proc.c files.texi frames.texi configure.ac dispextern.h lisp.h
+ process.c ms-w32.h and 1236 other files
Eliza Velasquez: changed server.el
@@ -1759,10 +1762,10 @@ Fabrice Nicol: changed etags.c etags.1
Fabrice Niessen: wrote leuven-theme.el
and changed org-agenda.el
-Fabrice Popineau: changed w32.c ms-w32.h w32fns.c w32heap.c w32term.c
+Fabrice Popineau: changed ms-w32.h w32.c w32fns.c w32heap.c w32term.c
configure.ac lisp.h unexw32.c buffer.c emacs.c image.c w32heap.h
w32proc.c w32term.h INSTALL addsection.c alloc.c dispextern.h
- emacs-regex.c emacs-x64.manifest emacs-x86.manifest and 25 other files
+ emacs-x64.manifest emacs-x86.manifest etags.c and 24 other files
Fan Kai: changed esh-arg.el
@@ -1780,6 +1783,8 @@ Felicián Németh: changed project.el xref.el
Felipe Ochoa: changed faces.el js.el paren.el
+Felix Dietrich: changed tramp-archive.el
+
Felix E. Klee: co-wrote svg.el
and changed display.texi
@@ -1817,7 +1822,7 @@ Florian Adamsky: changed recentf.el
Florian Beck: changed org.el
-Florian Ragwitz: changed gnus-html.el mail/sieve-manage.el
+Florian Ragwitz: changed gnus-html.el sieve-manage.el
Florian V. Savigny: changed sql.el
@@ -1945,7 +1950,7 @@ and changed edebug.el cl-print.el edebug.texi emacs-lisp/debug.el
cl-print-tests.el debugging.texi cl-macs.el edebug-test-code.el subr.el
testcases.el testcover.el cl-generic.el ert-x.el eval.c eieio-compat.el
elisp.texi ert.el ert.texi eval-tests.el generator.el print.c
- and 24 other files
+ and 23 other files
Geoff Gole: changed align.el ibuffer.el whitespace.el
@@ -1956,9 +1961,9 @@ Geoff Kuenning: changed gnus-art.el gnus.texi
Geoff Voelker: wrote ms-w32.h w32-fns.el w32.c w32.h w32heap.c w32heap.h
w32inevt.c w32proc.c w32term.c
and changed makefile.nt w32fns.c fileio.c makefile.def callproc.c
- s/ms-w32.h emacs.bat.in unexw32.c w32term.h dos-w32.el loadup.el
- w32-win.el emacs.c keyboard.c ntterm.c process.c w32console.c addpm.c
- cmdproxy.c comint.el files.el and 100 other files
+ emacs.bat.in unexw32.c w32term.h dos-w32.el loadup.el w32-win.el
+ emacs.c keyboard.c ntterm.c process.c w32console.c addpm.c cmdproxy.c
+ comint.el files.el sysdep.c and 97 other files
Georg C. F. Greve: changed pgg-gpg.el
@@ -2004,7 +2009,7 @@ and changed configure.ac Makefile.in src/Makefile.in calendar.el
lisp/Makefile.in diary-lib.el files.el make-dist rmail.el
progmodes/f90.el bytecomp.el admin.el misc/Makefile.in simple.el
authors.el startup.el emacs.texi lib-src/Makefile.in display.texi
- ack.texi subr.el and 1790 other files
+ ack.texi subr.el and 1786 other files
Glynn Clements: wrote gamegrid.el snake.el tetris.el
@@ -2116,6 +2121,8 @@ Harald Meland: changed gnus-art.el gnus-salt.el gnus-score.el
Harri Kiiskinen: changed org-protocol.el ox-publish.el
+Hayden Shenk: changed tramp-adb.el
+
H. Dieter Wilhelm: changed calc-help.el maintaining.texi paragraphs.el
Heiko Muenkel: changed b2m.c
@@ -2214,7 +2221,8 @@ Ihor Radchenko: changed fns.c
Iku Iwasa: changed auth-source-pass-tests.el auth-source-pass.el
-Ikumi Keita: changed characters.el japan-util.el kinsoku.el minibuf.c
+Ikumi Keita: changed characters.el display.texi files.el japan-util.el
+ kinsoku.el minibuf.c
Ilja Weis: co-wrote gnus-topic.el
@@ -2228,7 +2236,7 @@ Ilya Shlyakhter: changed org.el ob-lilypond.el org-clock.el
Ilya Zakharevich: wrote tmm.el
and co-wrote cperl-mode.el
and changed w32fns.c syntax.c intervals.c syntax.h textprop.c dired.c
- emacs-regex.c emacs-regex.h font-lock.el intervals.h search.c
+ font-lock.el intervals.h regex-emacs.c regex-emacs.h search.c
Ilya Zonov: changed org-mouse.el
@@ -2452,7 +2460,7 @@ Jason Rumney: wrote w32-vars.el
and changed w32fns.c w32term.c w32font.c w32menu.c w32-win.el w32term.h
w32.c w32uniscribe.c w32-fns.el makefile.nt w32console.c w32bdf.c
configure.bat keyboard.c w32proc.c w32select.c font.c image.c w32font.h
- w32gui.h xdisp.c and 153 other files
+ w32gui.h xdisp.c and 152 other files
Jason S. Cornez: changed keyboard.c
@@ -2517,7 +2525,7 @@ and changed mh-e.el mh-comp.el mh-utils.el mh-mime.el mh-customize.el
Jeff Spencer: changed dired.el
-Jeff Walsh: changed xwidget.c
+Jeff Walsh: changed comp.c xwidget.c
Jelle Licht: changed auth-source-pass-tests.el auth-source-pass.el
@@ -2569,8 +2577,8 @@ Jesper Harder: wrote yenc.el
and changed gnus-sum.el gnus-art.el message.el gnus-group.el gnus-msg.el
gnus.el gnus-util.el rfc2047.el mm-bodies.el mm-util.el mml.el
mm-decode.el nnrss.el gnus-srvr.el gnus-topic.el nnmail.el
- gnus-start.el gnus-uu.el spam-stat.el gnus-score.el gnus.texi
- and 202 other files
+ gnus-start.el gnus-uu.el gnus.texi spam-stat.el gnus-score.el
+ and 200 other files
Jhair Tocancipa Triana: changed gnus-audio.el
@@ -2606,10 +2614,10 @@ Jimmy Yuen Ho Wong: changed nsm.el gnutls.c gnutls.el disass.el
Jim Paris: changed process.c
Jim Porter: changed delsel.el ansi-color-tests.el ansi-color.el
- bindings.el term-tests.el term.el tramp.el callproc.c
- dichromacy-theme.el diff-mode.el files-tests.el gdb-mi.el grep-tests.el
- ispell.el leuven-theme.el man.el menu-bar.el misterioso-theme.el
- process.c process.h progmodes/grep.el and 6 other files
+ bindings.el esh-var.el term-tests.el term.el tramp.el callproc.c
+ dichromacy-theme.el diff-mode.el em-pred.el eshell-tests.el eshell.texi
+ files-tests.el gdb-mi.el grep-tests.el ispell.el leuven-theme.el man.el
+ menu-bar.el and 10 other files
Jim Radford: changed gnus-start.el
@@ -2792,7 +2800,7 @@ and changed epa.el epa-file.el lisp-mnt.el tips.texi dired-aux.el
dired-x.el dired.el eieio.el epa-dired.el font-lock.el
progmodes/compile.el simple.el allout.el button.el comint.el
cus-edit.el eldoc.el emacs-module-tests.el epa-hook.el epg-config.el
- epg.el and 9 other files
+ epg.el and 11 other files
Jonas Hoersch: changed org-inlinetask.el org.el
@@ -2899,7 +2907,7 @@ and co-wrote help-tests.el keymap-tests.el
and changed subr.el desktop.el w32fns.c faces.el simple.el emacsclient.c
files.el server.el bs.el help-fns.el xdisp.c org.el w32term.c w32.c
buffer.c keyboard.c ido.el image.c window.c eval.c allout.el
- and 1226 other files
+ and 1223 other files
Juan Pechiar: changed ob-octave.el
@@ -2922,7 +2930,7 @@ Julien Danjou: wrote erc-desktop-notifications.el gnus-gravatar.el
and co-wrote color.el
and changed shr.el org-agenda.el gnus-art.el nnimap.el gnus-html.el
gnus.el message.el gnus-group.el gnus-sum.el gnus-util.el mm-decode.el
- mm-view.el org.el gnus.texi mail/sieve-manage.el nnir.el mm-uu.el
+ mm-view.el org.el gnus.texi nnir.el sieve-manage.el mm-uu.el
color-lab.el gnus-demon.el gnus-int.el gnus-msg.el and 96 other files
Julien Gilles: wrote gnus-ml.el
@@ -2938,15 +2946,15 @@ Jure Cuhalev: changed ispell.el
Jürgen Hartmann: changed window.el
Jürgen Hötzel: wrote tramp-adb.el
-and changed tramp-gvfs.el tramp-sh.el comint.el em-unix.el esh-util.el
- tramp-cache.el tramp.el url-handlers.el wid-edit.el
+and changed tramp-gvfs.el tramp-sh.el callproc.c comint.el em-unix.el
+ esh-util.el tramp-cache.el tramp.el url-handlers.el wid-edit.el
Juri Linkov: wrote compose.el files-x.el misearch.el repeat-tests.el
- replace-tests.el tab-bar.el tab-line.el
+ replace-tests.el tab-bar-tests.el tab-bar.el tab-line.el
and changed isearch.el simple.el info.el replace.el dired.el dired-aux.el
progmodes/grep.el subr.el window.el image-mode.el mouse.el diff-mode.el
files.el menu-bar.el minibuffer.el progmodes/compile.el startup.el
- faces.el vc.el display.texi search.texi and 444 other files
+ faces.el vc.el display.texi search.texi and 446 other files
Jussi Lahdenniemi: changed w32fns.c ms-w32.h msdos.texi w32.c w32.h
w32console.c w32heap.c w32inevt.c w32term.h
@@ -3005,8 +3013,8 @@ Karl Eichwalder: changed Makefile.in add-log.el bookmark.el dired-aux.el
Karl Fogel: wrote bookmark.el mail-hist.el saveplace.el
and co-wrote pcvs.el
-and changed simple.el files.el doc-view.el image-mode.el info.el
- isearch.el vc-svn.el CONTRIBUTE INSTALL autogen.sh editfns.c
+and changed simple.el files.el CONTRIBUTE doc-view.el image-mode.el
+ info.el isearch.el vc-svn.el INSTALL autogen.sh editfns.c
internals.texi menu-bar.el simple-test.el subr.el tex-mode.el
thingatpt.el INSTALL.REPO comint.el configure configure.ac
and 21 other files
@@ -3044,7 +3052,7 @@ Katsumi Yamaoka: wrote canlock.el
and changed gnus-art.el gnus-sum.el message.el mm-decode.el gnus.texi
mm-util.el mm-view.el gnus-group.el gnus-util.el gnus-msg.el mml.el
shr.el rfc2047.el gnus-start.el gnus.el nntp.el gnus-agent.el nnrss.el
- mm-uu.el nnmail.el emacs-mime.texi and 161 other files
+ mm-uu.el nnmail.el emacs-mime.texi and 159 other files
Kaushal Modi: changed dired-aux.el files.el isearch.el apropos.el
calc-yank.el custom.texi desktop.el dired.el dired.texi ediff-diff.el
@@ -3058,7 +3066,7 @@ Kaveh R. Ghazi: changed delta88k.h xterm.c
Kayvan Sylvan: changed supercite.el
Kazuhiro Ito: changed coding.c uudecode.el flow-fill.el font.c
- japan-util.el keyboard.c make-mode.el net/starttls.el xdisp.c
+ japan-util.el keyboard.c make-mode.el starttls.el xdisp.c
Kazushi Marukawa: changed filelock.c hexl.c profile.c unexalpha.c
@@ -3143,7 +3151,7 @@ and changed edt.texi
Kevin Gallo: wrote w32-win.el
and changed makefile.nt dispnew.c addpm.c config.w95 dispextern.h emacs.c
facemenu.el faces.el fns.c frame.c frame.h keyboard.c makefile.def
- mouse.el ntterm.c process.c s/ms-w32.h scroll.c startup.el sysdep.c
+ mouse.el ms-w32.h ntterm.c process.c scroll.c startup.el sysdep.c
term.c and 18 other files
Kevin Greiner: wrote legacy-gnus-agent.el
@@ -3155,9 +3163,9 @@ and changed gnus-agent.el gnus-sum.el gnus-start.el gnus-int.el nntp.el
Kevin Layer: changed mml.el w32proc.c
-Kévin Le Gouguec: changed font-lock.el gnus-sum.el dired-aux-tests.el
- dired-aux.el electric-tests.el font-lock-tests.el gnus.el message.texi
- project.el sh-script.el shr.el
+Kévin Le Gouguec: changed font-lock.el gnus-sum.el progmodes/python.el
+ dired-aux-tests.el dired-aux.el electric-tests.el font-lock-tests.el
+ gnus.el message.texi project.el python-tests.el sh-script.el shr.el
Kevin Rodgers: changed compile.el mailabbrev.el progmodes/compile.el
dired-x.el files.el ange-ftp.el byte-opt.el desktop.el diff-mode.el
@@ -3300,10 +3308,10 @@ and co-wrote gnus-kill.el gnus-mh.el gnus-msg.el gnus-score.el
mm-encode.el mm-util.el nnbabyl.el nndoc.el nneething.el nnfolder.el
nnheader.el nnimap.el nnmbox.el nnmh.el nnml.el nnspool.el nnvirtual.el
rfc2047.el svg.el time-date.el
-and changed gnus.texi simple.el subr.el files.el process.c text.texi
- display.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el
- auth-source.el url-http.el edebug.el gnus-cite.el image.el pop3.el
- dired-aux.el fns.c image.c and 860 other files
+and changed gnus.texi simple.el subr.el files.el process.c display.texi
+ text.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el
+ auth-source.el url-http.el edebug.el image.el gnus-cite.el pop3.el
+ dired-aux.el fns.c image.c and 866 other files
Lars Rasmusson: changed ebrowse.c
@@ -3329,7 +3337,7 @@ Lee Duhem: changed eval.c
Leigh Stoller: changed emacsclient.c server.el
-Lele Gaifax: changed progmodes/python.el TUTORIAL.it flymake.el
+Lele Gaifax: changed TUTORIAL.it progmodes/python.el flymake.el
python-tests.el flymake-proc.el flymake.texi isearch.el
Lennart Borgman: co-wrote ert-x.el
@@ -3375,6 +3383,8 @@ Liang Wang: changed etags.el
Liāu, Kiong-Gē 廖宮毅: changed comp.c mingw-cfg.site
+Lin Zhou: changed w32fns.c w32term.h
+
Lixin Chin: changed bibtex.el
Lloyd Zusman: changed mml.el pgg-gpg.el
@@ -3612,9 +3622,9 @@ Martin Neitzel: changed supercite.el
Martin Pohlack: changed iimage.el pc-select.el
Martin Rudalics: changed window.el window.c windows.texi frame.c xdisp.c
- xterm.c w32fns.c frames.texi w32term.c xfns.c frame.el display.texi
+ xterm.c frames.texi w32fns.c w32term.c xfns.c frame.el display.texi
frame.h cus-start.el help.el buffer.c window.h mouse.el dispnew.c
- nsfns.m gtkutil.c and 211 other files
+ nsfns.m gtkutil.c and 212 other files
Martin Stjernholm: wrote cc-bytecomp.el
and co-wrote cc-align.el cc-cmds.el cc-compat.el cc-defs.el cc-engine.el
@@ -3728,7 +3738,7 @@ Mattias Engdegård: changed byte-opt.el rx.el rx-tests.el searching.texi
bytecomp-tests.el bytecomp.el calc-tests.el progmodes/compile.el
subr.el autorevert.el gdb-mi.el files.el regex-emacs-tests.el mouse.el
regexp-opt.el replace.el calc.el coding.c filenotify.el regex-emacs.c
- calc-ext.el and 537 other files
+ calc-ext.el and 539 other files
Mattias M: changed asm-mode-tests.el asm-mode.el
@@ -3771,7 +3781,7 @@ and co-wrote tramp-cache.el tramp-sh.el tramp.el
and changed tramp.texi tramp-adb.el trampver.el trampver.texi dbusbind.c
files.el ange-ftp.el file-notify-tests.el files.texi dbus.texi
autorevert.el tramp-fish.el kqueue.c tramp-gw.el os.texi shell.el
- tramp-imap.el gitlab-ci.yml lisp.h README xesam.el and 280 other files
+ tramp-imap.el gitlab-ci.yml lisp.h README xesam.el and 278 other files
Michael Ben-Gershon: changed acorn.h configure.ac riscix1-1.h riscix1-2.h
unexec.c
@@ -3874,8 +3884,8 @@ Michael Staats: wrote pc-select.el
Michael Vehrs: changed quail.el woman.el
Michael Welsh Duggan: changed nnimap.el lisp.h sh-script.el w32term.c
- buffer.c gnus-spec.el gud.el keyboard.c mail/sieve-manage.el nnir.el
- nnmail.el print.c termhooks.h url-http.el w32-win.el w32fns.c w32menu.c
+ buffer.c gnus-spec.el gud.el keyboard.c nnir.el nnmail.el print.c
+ sieve-manage.el termhooks.h url-http.el w32-win.el w32fns.c w32menu.c
w32term.h woman.el xdisp.c xterm.c
Michael Weylandt: changed ox-latex.el
@@ -3893,11 +3903,11 @@ Michał Krzywkowski: changed elide-head.el
Michal Nazarewicz: wrote cc-mode-tests.el descr-text-tests.el
tildify-tests.el
and co-wrote tildify.el
-and changed emacs-regex.c casefiddle.c simple.el
- test/src/regex-emacs-tests.el casefiddle-tests.el emacs-regex.h
- message.el search.c buffer.h cc-mode.el cc-mode.texi ert-x.el files.el
- frame.c remember.el sgml-mode.el unidata-gen.el README
- SpecialCasing.txt bindings.el buffer.c and 41 other files
+and changed regex-emacs.c casefiddle.c regex-emacs-tests.el simple.el
+ casefiddle-tests.el message.el regex-emacs.h search.c buffer.h
+ cc-mode.el cc-mode.texi ert-x.el files.el frame.c remember.el
+ sgml-mode.el unidata-gen.el README SpecialCasing.txt bindings.el
+ buffer.c and 41 other files
Michal Nowak: changed gnutls.el
@@ -4164,7 +4174,7 @@ Nils Ackermann: changed message.el nnmh.el reftex-vars.el
Nitish Chinta: changed progmodes/python.el sendmail.el simple.el
-N. Jackson: changed emacs.texi forms.texi os.texi
+N. Jackson: changed emacs.texi forms.texi gnus.info os.texi
Noah Evans: changed follow.el
@@ -4183,7 +4193,7 @@ Noam Postavsky: changed progmodes/python.el lisp-mode.el bytecomp.el
lisp-mode-tests.el term.el xdisp.c cl-macs.el eval.c simple.el data.c
emacs-lisp/debug.el modes.texi help-fns.el subr.el elisp-mode.el ert.el
isearch.el processes.texi search.c cl-print.el diff-mode.el
- and 363 other files
+ and 362 other files
Nobuyoshi Nakada: co-wrote ruby-mode.el
and changed ruby-mode-tests.el
@@ -4270,10 +4280,11 @@ and co-wrote eudc-bob.el eudc-export.el eudc-hotlist.el eudc-vars.el
eudc.el eudcb-bbdb.el eudcb-ldap.el eudcb-ph.el
and changed ph.el
-Óscar Fuentes: changed ido.el password-cache.el ses.el vc-hooks.el xfns.c
- CPP-DEFINES addpm.c addsection.c browse-url.el callproc.c cmdproxy.c
- configure.ac diff-mode.el emacsclient.c keyboard.c ms-w32.h preprep.c
- progmodes/grep.el vc-bzr.el vc-cvs.el vc-git.el and 9 other files
+Óscar Fuentes: changed ido.el password-cache.el progmodes/grep.el ses.el
+ vc-hooks.el xfns.c CPP-DEFINES addpm.c addsection.c browse-url.el
+ callproc.c cmdproxy.c configure.ac diff-mode.el em-cmpl.el
+ emacsclient.c keyboard.c ms-w32.h preprep.c vc-bzr.el vc-cvs.el
+ and 10 other files
Øyvind Stegard: changed gnus-msg.el
@@ -4300,9 +4311,9 @@ and changed imenu.el make-mode.el
Paul Eggert: wrote rcs2log
and co-wrote cal-dst.el
and changed lisp.h configure.ac alloc.c fileio.c process.c editfns.c
- sysdep.c xdisp.c fns.c image.c keyboard.c emacs.c data.c lread.c
+ sysdep.c xdisp.c fns.c image.c keyboard.c data.c emacs.c lread.c
xterm.c eval.c gnulib-comp.m4 callproc.c Makefile.in frame.c buffer.c
- and 1851 other files
+ and 1847 other files
Paul Fisher: changed fns.c
@@ -4503,9 +4514,9 @@ Philipp Stephani: wrote callint-tests.el checkdoc-tests.el
cl-preloaded-tests.el ediff-diff-tests.el eval-tests.el ido-tests.el
lread-tests.el mouse-tests.el startup-tests.el xt-mouse-tests.el
and changed emacs-module.c emacs-module-tests.el configure.ac json.c
- eval.c process.c json-tests.el process-tests.el internals.texi alloc.c
- emacs-module.h.in emacs.c lread.c nsterm.m lisp.h bytecomp.el pdumper.c
- callproc.c seccomp-filter.c gtkutil.c files.el and 179 other files
+ process.c eval.c internals.texi json-tests.el process-tests.el alloc.c
+ emacs-module.h.in emacs.c lread.c nsterm.m lisp.h pdumper.c bytecomp.el
+ callproc.c seccomp-filter.c gtkutil.c files.el and 184 other files
Phillip Lord: wrote ps-print-tests.el w32-feature.el
and changed build-zips.sh build-dep-zips.py lisp/Makefile.in undo.c
@@ -4559,7 +4570,10 @@ and changed xdisp.c comp.c fns.c pdumper.c alloc.c byte-opt.el
ccl-tests.el ccl.c ccl.el cmds.c comint.el comp-test-funcs.el
comp-tests.el comp.el composite.c and 28 other files
-Po Lu: changed xdisp.c browse-url.el cc-compat.el nsfns.m nsterm.m
+Po Lu: changed xdisp.c anti.texi browse-url.el callproc.c cc-compat.el
+ config.bat esh-cmd.el fileio.c langinfo.h loadup.el mouse.el msdos.c
+ msdos.h nsfns.m nsterm.m process.c sed1v2.inp sed2v2.inp sed3v2.inp
+ sedlibmk.inp tooltip.el xterm.c
Pontus Michael: changed simple.el
@@ -4655,7 +4669,7 @@ Reiner Steib: wrote gmm-utils.el
and changed message.el gnus.texi gnus-art.el gnus-sum.el gnus-group.el
gnus.el mml.el gnus-faq.texi mm-util.el gnus-score.el message.texi
gnus-msg.el gnus-start.el gnus-util.el spam-report.el mm-uu.el spam.el
- mm-decode.el files.el gnus-agent.el nnmail.el and 172 other files
+ mm-decode.el files.el gnus-agent.el nnmail.el and 171 other files
Remek Trzaska: changed gnus-ems.el
@@ -4689,6 +4703,8 @@ Richard Dawe: changed config.in src/Makefile.in
Richard G. Bielawski: changed modes.texi paren.el
+Richard Hansen: changed easy-mmode.el
+
Richard Hoskins: changed message.el
Richard Kim: wrote wisent/python.el
@@ -4719,7 +4735,7 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-langs.el
and changed files.el keyboard.c simple.el xterm.c xdisp.c rmail.el
fileio.c process.c sysdep.c buffer.c xfns.c window.c subr.el
configure.ac startup.el sendmail.el emacs.c Makefile.in editfns.c
- info.el dired.el and 1338 other files
+ info.el dired.el and 1336 other files
Richard Ryniker: changed sendmail.el
@@ -4769,7 +4785,7 @@ Robert Pluim: wrote nsm-tests.el
and changed configure.ac process.c blocks.awk network-stream-tests.el
font.c processes.texi ftfont.c gtkutil.c vc-git.el process-tests.el
emoji-zwj.awk gnutls.el network-stream.el nsm.el tramp.texi mml-sec.el
- nsterm.m unicode xfns.c auth.texi composite.c and 133 other files
+ nsterm.m unicode xfns.c auth.texi composite.c and 136 other files
Robert Thorpe: changed cus-start.el indent.el rmail.texi
@@ -4969,7 +4985,7 @@ Sean O'Rourke: changed complete.el comint.el dabbrev.el find-func.el
Sean Sieger: changed emacs-lisp-intro.texi
Sean Whitton: changed project.el bindings.el files.texi simple.el
- repeat.el
+ killing.texi rect.el repeat.el
Sebastian Freundt: changed nnmaildir.el
@@ -5025,6 +5041,7 @@ Sergey Poznyakoff: changed rmail.el mh-mime.el rmail.texi smtpmail.el
Sergey Trofimov: changed window.el
Sergey Vinokurov: changed emacs-module-tests.el emacs-module.c
+ memory-report.el
Sergio Durigan Junior: changed eudcb-bbdb.el gdb-mi.el
@@ -5106,9 +5123,8 @@ and co-wrote gnus-sieve.el gssapi.el mml1991.el nnfolder.el nnimap.el
nnml.el rot13.el sieve-manage.el
and changed message.el gnus-sum.el gnus-art.el smtpmail.el pgg-gpg.el
pgg.el gnus-agent.el mml2015.el mml.el gnus-group.el mm-decode.el
- gnus-msg.el gnus.texi mail/sieve-manage.el pgg-pgp5.el browse-url.el
- gnus-int.el gnus.el hashcash.el mm-view.el password.el
- and 101 other files
+ gnus-msg.el gnus.texi pgg-pgp5.el browse-url.el gnus-int.el gnus.el
+ hashcash.el mm-view.el password.el gnus-cache.el and 99 other files
Simon Lang: changed building.texi icomplete.el misterioso-theme.el
progmodes/grep.el
@@ -5162,9 +5178,8 @@ Stefan Kangas: wrote bookmark-tests.el cal-julian-tests.el
and co-wrote help-tests.el keymap-tests.el
and changed efaq.texi checkdoc.el package.el cperl-mode.el bookmark.el
help.el keymap.c subr.el simple.el erc.el ediff-util.el idlwave.el
- time.el bytecomp-tests.el comp.el speedbar.el bytecomp.el
- emacs-lisp-intro.texi flyspell.el ibuffer.el package-tests.el
- and 1337 other files
+ time.el bytecomp-tests.el comp.el speedbar.el bytecomp.el edebug.el
+ emacs-lisp-intro.texi flyspell.el ibuffer.el and 1339 other files
Stefan Merten: co-wrote rst.el
@@ -5181,7 +5196,7 @@ and co-wrote font-lock.el gitmerge.el pcvs.el
and changed subr.el simple.el keyboard.c bytecomp.el cl-macs.el files.el
lisp.h vc.el xdisp.c alloc.c eval.c sh-script.el progmodes/compile.el
keymap.c buffer.c window.c tex-mode.el lisp-mode.el newcomment.el
- help-fns.el lread.c and 1616 other files
+ help-fns.el lread.c and 1612 other files
Stefano Facchini: changed gtkutil.c
@@ -5329,10 +5344,9 @@ Svante Carl V. Erichsen: changed cl-indent.el
Svend Tollak Munkejord: changed deuglify.el
Sven Joachim: changed files.el de-refcard.tex dired-aux.el emacs.1
- arc-mode.el dired-x.el doc/misc/gnus.texi em-cmpl.el em-hist.el
- em-ls.el esh-cmd.el esh-ext.el esh-io.el files.texi gnus-sum.el
- gnus.texi help.el make-dist message.el movemail.c mule.texi
- and 9 other files
+ gnus.texi arc-mode.el dired-x.el em-cmpl.el em-hist.el em-ls.el
+ esh-cmd.el esh-ext.el esh-io.el files.texi gnus-sum.el help.el
+ make-dist message.el movemail.c mule.texi sed3v2.inp and 8 other files
Sylvain Chouleur: changed gnus-icalendar.el icalendar.el
@@ -5359,7 +5373,7 @@ Takahashi Naoto: wrote ethio-util.el language/ethiopic.el latin-post.el
and co-wrote latin-ltx.el quail.el
and changed ethiopic.el fontset.el mule-conf.el
-Takai Kousuke: changed ccl.el image/compface.el
+Takai Kousuke: changed ccl.el compface.el
Takeshi Yamada: changed fns.c
@@ -5379,8 +5393,8 @@ and co-wrote ol-gnus.el
and changed bug-reference.el reftex-vars.el tex-mode.el browse-url.el
gnus.texi reftex-cite.el tsdh-dark-theme.el tsdh-light-theme.el
gnus-sum.el maintaining.texi file-notify-tests.el gnus-art.el misc.texi
- reftex.el org-gnus.el prog-mode.el subword.el image-mode.el json.el
- lisp-mode.el rcirc.el and 99 other files
+ reftex.el org-gnus.el prog-mode.el subword.el dired.el image-mode.el
+ json.el lisp-mode.el and 99 other files
Tatsuya Ichikawa: changed gnus-agent.el gnus-cache.el
@@ -5464,7 +5478,7 @@ Thomas Dye: changed org.texi org-bibtex.el ob-R.el org.el
Thomas Fitzsimmons: wrote soap-client.el
and changed soap-inspect.el ldap.el eudc.texi eudc-vars.el eudc.el
- ntlm.el url-http.el eudcb-ldap.el eudcb-bbdb.el ntlm-tests.el
+ ntlm.el url-http.el eudcb-bbdb.el eudcb-ldap.el ntlm-tests.el
eudc-bob.el eudc-export.el eudcb-ph.el package.el README authinfo
diary-lib.el display.texi eudc-hotlist.el eudcb-macos-contacts.el
icalendar.el and 3 other files
@@ -5669,8 +5683,8 @@ Tsuchiya Masatoshi: changed gnus-art.el mm-view.el gnus-sum.el
Tsugutomo Enami: changed frame.c keyboard.c configure.ac dispnew.c
fileio.c process.c simple.el sysdep.c xdisp.c add-log.el bytecomp.el
- editfns.c emacs-regex.c emacs-regex.h emacs.c frame.h gnus-group.el
- netbsd.h nnheader.el nnimap.el perl-mode.el and 6 other files
+ editfns.c emacs.c frame.h gnus-group.el netbsd.h nnheader.el nnimap.el
+ perl-mode.el regex-emacs.c regex-emacs.h and 6 other files
Tsuyoshi Akiho: changed gnus-sum.el nnrss.el
@@ -5779,6 +5793,8 @@ and changed ps-prin1.ps ps-bdf.el ps-prin0.ps blank-mode.el ps-prin3.ps
easymenu.el loading.texi menu-bar.el misc.texi progmodes/compile.el
ps-print-def.el ps-vars.el
+Visuwesh M: changed dired-aux.el
+
Vitalie Spinu: changed comint.el eieio-base.el message.el ob-R.el
ob-core.el ob-tangle.el subr.el
@@ -5936,7 +5952,7 @@ Yamamoto Mitsuharu: wrote uvs.el
and changed macterm.c macfns.c mac-win.el xterm.c mac.c macterm.h image.c
macmenu.c macgui.h xdisp.c ftfont.c xfns.c keyboard.c macselect.c
ftcrfont.c macfont.m configure.ac w32term.c dispextern.h
- src/Makefile.in unexmacosx.c and 108 other files
+ src/Makefile.in unexmacosx.c and 111 other files
Yan Gajdos: changed vc-git.el
@@ -6025,6 +6041,8 @@ Zhang Wei: changed chinese.el characters.el mule-cmds.el xfns.c erc.el
Zhang Weize: wrote ob-plantuml.el
+Zhehao Lin: changed xfaces.c
+
Zhiwei Chen: changed hideif.el
Zhongwei Yao: changed tramp-adb.el
diff --git a/etc/DEBUG b/etc/DEBUG
index dd33b42f19a..7d2f810d078 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -947,10 +947,10 @@ several kinds of low-level problems in C code, including:
* Passing invalid values to some builtin functions, e.g., __builtin_clz (0).
* Reaching __builtin_unreachable calls (in Emacs, 'eassume' failure).
-To use UndefinedBehaviorSanitizer with GCC and similar compilers,
-append '-fsanitize=undefined' to CFLAGS, either when running
-'configure' or running 'make'. When supported, you can also specify
-'bound-strict' and 'float-cast-overflow'. For example:
+To use GCC's UndefinedBehaviorSanitizer, append '-fsanitize=undefined'
+to CFLAGS, either when running 'configure' or running 'make'.
+When supported, you can also specify 'bound-strict' and
+'float-cast-overflow'. For example:
./configure \
CFLAGS='-O0 -g3 -fsanitize=undefined,bounds-strict,float-cast-overflow'
@@ -958,6 +958,11 @@ append '-fsanitize=undefined' to CFLAGS, either when running
You may need to append '-static-libubsan' to CFLAGS if your version of
GCC is installed in an unusual location.
+Clang's UB sanitizer can also be used, but has coverage problems.
+You'll need '-fsanitize=undefined -fno-sanitize=pointer-overflow' to
+suppress misguided warnings about adding zero to a null pointer,
+although this also suppresses any valid pointer overflow warnings.
+
When using GDB to debug an executable with undefined-behavior
sanitization, the GDB command:
diff --git a/etc/DEVEL.HUMOR b/etc/DEVEL.HUMOR
index 6db69bb4b58..bd51845cb11 100644
--- a/etc/DEVEL.HUMOR
+++ b/etc/DEVEL.HUMOR
@@ -188,3 +188,19 @@ wouldn't worry about it too much."
"Kind of late, but thanks for letting us know. I've just revoked your
write access to the repository for the obvious safety reasons,"
-- Bastien Guerry and Stefan Monnier
+
+----------------------------------------------------------------------
+
+ "I should have known better than to think I could be right and you
+wrong about some Emacs code I've just started looking at. Sorry about
+that."
+
+ "No problem. It's one of the many joys of working on a code base
+that's up to almost 40 years old: First you have to figure out what
+the (no doubt smart) programmer meant to achieve with the code, and
+then try to figure out whether it ever even did that, and then whether
+it's still working the same way, and then whether it's still relevant
+due to changes elsewhere, and then finally whether it can be improved
+without breaking odd edge cases on obscure systems you don't have
+access to. 🙃"
+ -- Ignacio Casso and Lars Ingebrigtsen
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index bdcd943c37f..7f95cdd39a2 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -12,6 +12,96 @@ extensible IRC (Internet Relay Chat) client distributed with
GNU Emacs since Emacs version 22.1.
+* Changes in ERC 5.5
+
+** Smarter buffer naming for withstanding collisions.
+ERC buffers now remain tied to their logical network contexts, even
+while offline. These associations can survive regional server changes
+and the intercession of proxies. As has long been practiced in other
+areas of Emacs, "uniquified" buffer renaming prevents collisions
+between buffers of different contexts. ERC's approach prioritizes
+predictability over economy, favoring fully qualified suffixes without
+elided or omitted components. Potential avenues for confusion remain
+but will die out with the adoption of emerging protocol extensions.
+
+** Option 'erc-rename-buffers' deprecated.
+The promises made by its old "on" state are now fully realized and
+enabled permanently by default. Its old behavior when disabled has
+been preserved and will remain available (with warnings) for years to
+come.
+
+** Option 'erc-reuse-buffers' deprecated.
+This ancient option has been a constant source of confusion, as
+exhibited most recently when its "disabled" meaning was partially
+inverted. Introduced in ERC 5.4 (Emacs 28.1), this regression saw
+existing channel buffers transparently reassociated instead of created
+anew. The pre-5.4 "disabled" behavior has been restored and will
+remain accessible for the foreseeable future, warts and all (e.g.,
+with its often superfluous "/DIALED-HOST" suffixing always present).
+
+** Tighter auth-source integration with bigger changes on the horizon.
+The days of hit-and-miss auth-source queries are hopefully behind us.
+With the overhaul of the services module temporarily shelved and the
+transition to SASL-based authentication still underway, users may feel
+left in the lurch to endure yet another release cycle of backtick
+hell. For some, auth-source may provide a workaround in the form of
+nonstandard server passwords. See the "Connection" node in the manual
+under the subheading "Password".
+
+If you require SASL immediately, please participate in ERC development
+by volunteering to try (and give feedback on) edge features, one of
+which is SASL. All known external offerings, past and present, are
+valiant efforts whose use is nevertheless discouraged.
+
+** Username argument for entry-point commands.
+Commands 'erc' and 'erc-tls' now accept a ':user' keyword argument,
+which, when present, becomes the first argument passed to the "USER"
+IRC command. The traditional way of setting this globally, via
+'erc-email-userid', is still honored.
+
+** Additional display options for updated buffers.
+Additional flexibility is now available for controlling the behavior
+of newly created target buffers, especially during reconnection.
+
+** Improved handling of multiline prompt input.
+This means better detection and handling of intervening and trailing
+blanks when 'erc-send-whitespace-lines' is active. New options have
+also been added for warning when input spans multiple lines. Although
+off by default, new users are encouraged to enable them.
+
+** Miscellaneous behavioral changes impacting the user experience.
+A bug has been fixed that saw prompts being mangled, doubled, or
+erased in server buffers upon disconnection. Instead, input prompts
+now collapse into an alternate form designated by the option
+'erc-prompt-hidden'. Behavior differs for query and channel buffers
+but can be fine-tuned via the repurposed, formerly abandoned option
+'erc-hide-prompt'.
+
+A bug has been fixed affecting users of the Soju bouncer: outgoing
+messages during periods of heavy traffic no longer disappear.
+
+Although rare, server passwords containing white space are now handled
+correctly.
+
+** Miscellaneous behavioral changes in the library API.
+The function 'erc-network' always returns non-nil in server and target
+buffers belonging to a successfully established IRC connection, even
+after that connection has been closed.
+
+In 5.4, support for network symbols as keys was added for
+'erc-autojoin-channels-alist'. This has been extended to include
+explicit symbols passed to 'erc-tls' and 'erc' as so-called
+network-context identifiers via a new ':id' keyword. The latter
+carries wider significance beyond autojoin and can be used for
+unequivocally identifying a connection in a human-readable way.
+
+The function 'erc-auto-query', unused internally, and basically
+inscrutable when read, has been deprecated with no public replacement.
+This raises a related issue: if you use ERC as a library and need
+something only offered internally, please lobby to have it exported by
+writing to emacs-erc@gnu.org.
+
+
* Changes in ERC 5.4.1
** No user-visible changes since ERC 5.4, but a few tweaks in some ERC
diff --git a/etc/HELLO b/etc/HELLO
index 5b2002ff933..d73465318ca 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -1,9 +1,11 @@
Content-Type: text/enriched
Text-Width: 70
-This is a list of ways to say hello in various languages.
-It is not intended to be comprehensive, but to demonstrate
-some of the character sets that Emacs supports.
+This is a list of ways to write a <x-color><param>orange red</param>"hello"</x-color> greeting using
+various scripts. It is not intended to be comprehensive,
+but to demonstrate some of the character sets and writing
+systems that Emacs supports. Look for the script used to
+write your language, to see if it is supported.
Non-ASCII examples:
@@ -11,7 +13,7 @@ Non-ASCII examples:
Cześć!,</x-charset><x-charset><param>latin-iso8859-2</param> Dobrý den,</x-charset><x-charset><param>cyrillic-iso8859-5</param> Здравствуйте!,</x-charset><x-charset><param>greek-iso8859-7</param> Γειά σας,</x-charset> გამარჯობა
Africa: <x-charset><param>ethiopic</param>ሠላም</x-charset>
Middle/Near East:<x-charset><param>hebrew-iso8859-8</param> שָׁלוֹם,</x-charset> السّلام عليكم
- South Asia: નમસ્તે, नमस्ते, ನಮಸ್ಕಾರ, നമസ്കാരം, ଶୁଣିବେ,
+ South Asia: નમસ્તે, नमस्ते, ನಮಸ್ಕಾರ, നമസ്കാരം, ନମସ୍କାର,
ආයුබෝවන්, வணக்கம், నమస్కారం,<x-charset><param>tibetan</param> བཀྲ་ཤིས་བདེ་ལེགས༎</x-charset>
South East Asia: ជំរាបសួរ,<x-charset><param>lao</param> ສະບາຍດີ,</x-charset> မင်္ဂလာပါ,<x-charset><param>thai-tis620</param> สวัสดีครับ,</x-charset><x-charset><param>vietnamese-viscii-lower</param> </x-charset><x-charset><param>vietnamese-viscii-upper</param>C</x-charset><x-charset><param>vietnamese-viscii-lower</param>hào bạn</x-charset>
East Asia:<x-charset><param>chinese-gb2312</param> 你好,</x-charset><x-charset><param>chinese-big5-1</param> 早晨,</x-charset><x-charset><param>japanese-jisx0208</param> こんにちは,</x-charset><x-charset><param>korean-ksc5601</param> 안녕하세요</x-charset>
@@ -25,17 +27,23 @@ LANGUAGE (NATIVE NAME) HELLO
Amharic (አማርኛ) ሠላም
Arabic (العربيّة) السّلام عليكم
Armenian (հայերեն) Բարև ձեզ
+Balinese (ᬅᬓ᭄ᬱᬭᬩᬮᬶ) ᬒᬁᬲ᭄ᬯᬲ᭄ᬢ᭄ᬬᬲ᭄ᬢᬸ
+Batak (ᯘᯮᯒᯗ᯲ᯅᯗᯂ᯲) ᯂᯬᯒᯘ᯲ / ᯔᯧᯐᯬᯀᯱᯐᯬᯀᯱ
Belarusian (беларуская) Прывітанне
Bengali (বাংলা) নমস্কার
+Brahmi (𑀩𑁆𑀭𑀸𑀳𑁆𑀫𑀻) 𑀦𑀫𑀲𑁆𑀢𑁂
+
Braille ⠓⠑⠇⠇⠕
+Buginese (ᨒᨚᨈᨑ) ᨖᨒᨚ
Burmese (မြန်မာ) မင်္ဂလာပါ
-C printf ("Hello, world!\n");
+C printf (<x-color><param>orange red</param>"Hello, world!\n"</x-color>);
Cham (ꨌꩌ) ꨦꨤꩌ ꨦꨁꨰ
Cherokee (ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ) ᎣᏏᏲ / ᏏᏲ
Comanche /kəˈmæntʃiː/ Haa marʉ́awe
Cree (ᓀᐦᐃᔭᐍᐏᐣ) ᑕᓂᓯ / ᐙᒋᔮ
Czech (čeština) Dobrý den
Danish (dansk) Hej / Goddag / Halløj
+Devanagari (देवनागरी) नमस्ते / नमस्कार
Dutch (Nederlands) Hallo / Dag
Efik /ˈɛfɪk/ Mɔkɔm
Egyptian Hieroglyphs (𓂋𓏤𓈖𓆎𓅓‌𓏏𓊖) 𓅓𓊵𓏏𓊪, 𓇍𓇋𓂻𓍘𓇋
@@ -48,39 +56,60 @@ Finnish (suomi) Hei / Hyvää päivää
French (français) Bonjour / Salut
Georgian (ქართული) გამარჯობა
German (Deutsch) Guten Tag / Grüß Gott
+Grantha (𑌗𑍍𑌰𑌨𑍍𑌥) 𑌨𑌮𑌸𑍍𑌤𑍇 / 𑌨𑌮𑌸𑍍𑌕𑌾𑌰𑌃
Greek (ελληνικά) Γειά σας
Greek, ancient (ἑλληνική) Οὖλέ τε καὶ μέγα χαῖρε
Gujarati (ગુજરાતી) નમસ્તે
+Gurmukhi (ਗੁਰਮੁਖੀ) ਸਤ ਸ੍ਰੀ ਅਕਾਲ
+Hanifi Rohingya (𐴌𐴟𐴇𐴥𐴝𐴚𐴒𐴙𐴝 𐴇𐴝𐴕𐴞𐴉𐴞 𐴓𐴠𐴑𐴤𐴝) 𐴀𐴝𐴏𐴓𐴝𐴀𐴡𐴤𐴛𐴝𐴓𐴝𐴙𐴑𐴟𐴔
+Hanunoo (ᜱᜨᜳᜨᜳᜢ) ᜫᜬᜧ᜴ ᜣᜭᜯᜥ᜴ ᜰᜲᜭᜥ᜴
Hebrew (עִבְרִית) שָׁלוֹם
+Hindi (हिन्दी) प्रणाम / पाय लागू
Hungarian (magyar) Szép jó napot!
-Hindi (हिंदी) नमस्ते / नमस्कार ।
Inuktitut (ᐃᓄᒃᑎᑐᑦ) ᐊᐃ
Italian (italiano) Ciao / Buon giorno
Javanese (ꦧꦱꦗꦮꦶ) console.log("ꦲꦭꦺꦴ");
+
+Kaithi (𑂍𑂶𑂟𑂲) 𑂩𑂰𑂧𑂩𑂰𑂧
Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ
+Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁
Khmer (ភាសាខ្មែរ) ជំរាបសួរ
Lakota (Lakȟotiyapi) Taŋyáŋ yahí!
Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ
+Lepcha (ᰛᰩᰵᰛᰧᰵᰶ) ᰂᰦᰕᰥᰬ
+Limbu (ᤕᤰᤌᤢᤱ ᤐᤠᤴ) ᤛᤣᤘᤠᤖᤥ
+Makasar (𑻪𑻢𑻪𑻢) 𑻦𑻤𑻵𑻱
Malayalam (മലയാളം) നമസ്കാരം
Maldivian (ދިވެހި) އައްސަލާމު ޢަލައިކުމް / ކިހިނެހް؟
Maltese (il-Malti) Bonġu / Saħħa
Mathematics ∀ p ∈ world • hello p □
+Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ
+Modi (𑘦𑘻𑘚𑘲) 𑘡𑘦𑘭𑘿𑘎𑘰𑘨
Mongolian (монгол хэл) Сайн байна уу?
+Northern Thai (ᨣᩣᩴᨾᩮᩬᩥᨦ / ᨽᩣᩈᩣᩃ᩶ᩣ᩠ᨶᨶᩣ) ᩈ᩠ᩅᩢᩔ᩠ᨯᩦᨣᩕᩢ᩠ᨸ
Norwegian (norsk) Hei / God dag
-Oriya (ଓଡ଼ିଆ) ଶୁଣିବେ
+Odia (ଓଡ଼ିଆ) ନମସ୍କାର
Polish (język polski) Dzień dobry! / Cześć!
+Rejang (ꥆꤰ꥓ꤼꤽ ꤽꥍꤺꥏ) ꤸꥉꥐꤺꥉꥂꥎ
Russian (русский) Здра́вствуйте!
+Sharada (𑆯𑆳𑆫𑆢𑆳) 𑆤𑆩𑆱𑇀𑆑𑆳𑆫
+Siddham (𑖭𑖰𑖟𑖿𑖠𑖽) 𑖡𑖦𑖫𑖿𑖝𑖸
Sinhala (සිංහල) ආයුබෝවන්
Slovak (slovenčina) Dobrý deň
Slovenian (slovenščina) Pozdravljeni!
Spanish (español) ¡Hola!
+Sundanese (ᮃᮊ᮪ᮟᮛᮞᮥᮔ᮪ᮓ) ᮞᮙ᮪ᮕᮥᮛᮞᮥᮔ᮪
Swedish (svenska) Hej / Goddag / Hallå
+Syloti Nagri (ꠍꠤꠟꠐꠤ ꠘꠣꠉꠞꠤ) ꠀꠌ꠆ꠍꠣꠟꠣꠝꠥ ꠀꠟꠣꠁꠇꠥꠝ / ꠘꠝꠡ꠆ꠇꠣꠞ
Tamil (தமிழ்) வணக்கம்
Telugu (తెలుగు) నమస్కారం
+Tagalog (ᜊᜌ᜔ᜊᜌᜒᜈ᜔) ᜃᜓᜋᜓᜐ᜔ᜆ
+Tagbanwa (ᝦᝪᝯ) ᝫᝩᝬᝥ ᝣᝮᝧᝯ
TaiViet (ꪁꪫꪱꪣ ꪼꪕ) ꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ
Thai (ภาษาไทย) สวัสดีครับ / สวัสดีค่ะ
Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎
Tigrigna (ትግርኛ) ሰላማት
+Tirhuta (𑒞𑒱𑒩𑒯𑒳𑒞𑒰) 𑒣𑓂𑒩𑒢𑒰𑒧 / 𑒮𑒲𑒞𑒰𑒩𑒰𑒧
Turkish (Türkçe) Merhaba
Ukrainian (українська) Вітаю
Vietnamese (tiếng Việt) Chào bạn
diff --git a/etc/HISTORY b/etc/HISTORY
index 1d6425e9380..bb4e3e38e1b 100644
--- a/etc/HISTORY
+++ b/etc/HISTORY
@@ -224,6 +224,8 @@ GNU Emacs 27.1 (2020-08-10) emacs-27.1
GNU Emacs 27.2 (2021-03-25) emacs-27.2
+GNU Emacs 28.1 (2022-04-04) emacs-28.1
+
----------------------------------------------------------------------
This file is part of GNU Emacs.
diff --git a/etc/NEWS b/etc/NEWS
index ea08f7f3de7..660ea7d7201 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -29,6 +29,7 @@ applies, and please also update docstrings as needed.
This uses the popular sqlite3 library, and can be disabled by using
the '--without-sqlite3' option to the 'configure' script.
++++
** Emacs has been ported to the Haiku operating system.
The configuration process should automatically detect and build for
Haiku. There is also an optional window-system port to Haiku, which
@@ -39,74 +40,458 @@ the option '--with-be-app', the resulting Emacs will only run in
text-mode terminals.
+++
-*** Cairo drawing support has been enabled for Haiku builds.
+** Cairo drawing support has been enabled for Haiku builds.
To enable Cairo support, ensure that the Cairo and FreeType
development files are present on your system, and configure Emacs with
'--with-be-cairo'.
---
-*** Double buffering is now enabled on the Haiku operating system.
+** Double buffering is now enabled on the Haiku operating system.
Unlike X, there is no compile-time option to enable or disable
double-buffering. If you wish to disable double-buffering, change the
frame parameter 'inhibit-double-buffering' instead.
+---
** Emacs now installs the ".pdmp" file using a unique fingerprint in the name.
The file is typically installed using a file name akin to
"...dir/libexec/emacs/29.1/x86_64-pc-linux-gnu/emacs-<fingerprint>.pdmp".
If a constant file name is required, the file can be renamed to
"emacs.pdmp", and Emacs will find it during startup anyway.
-** Emacs now supports use of XInput 2 for input events.
-If your X server has support and you have the XInput 2 development headers
-installed, you can configure Emacs with the option '--with-xinput2' to enable
-this support.
-
-The named feature 'xinput2' can be used to test for the presence of
-XInput 2 support from Lisp programs.
+---
+** Emacs now uses of XInput 2 for input events.
+If your X server has support and you have the XInput 2 development
+headers installed, Emacs will use the X Input Extension for handling
+input. If this causes problems, you can configure Emacs with the
+option '--without-xinput2' to disable this support.
-** Emacs now supports being built with pure GTK.
-To use this option, make sure the GTK 3 and Cairo development files
-are installed, and configure Emacs with the option '--with-pgtk'.
-Unlike the default X and GTK build, the resulting Emacs binary will
-work on any underlying window system supported by GDK, such as
-Wayland and Broadway.
+'(featurep 'xinput2)' can be used to test for the presence of XInput 2
+support from Lisp programs.
---
-** The docstrings of preloaded files are not in 'etc/DOC' any more.
-Instead, they're fetched as needed from the corresponding '.elc' file,
+** Emacs no longer reduces the size of the Japanese dictionary.
+Building Emacs includes generation of a Japanese dictionary, which is
+used by Japanese input methods. Previously, the build included a step
+of reducing the size of this dictionary's vocabulary. This vocabulary
+reduction is now optional, by default off. If you need the Emacs
+build to include the vocabulary reduction, configure Emacs with the
+option '--with-small-ja-dic'. In an Emacs source tree already
+configured without that option, you can force the vocabulary reduction
+by saying
+
+ make -C leim generate-ja-dic JA_DIC_NO_REDUCTION_OPTION=''
+
+after deleting lisp/leim/ja-dic/ja-dic.el.
+
++++
+** Emacs now supports being built with pure GTK.
+To use this option, make sure the GTK 3 (version 3.22.23 or later) and
+Cairo development files are installed, and configure Emacs with the
+option '--with-pgtk'. Unlike the default X and GTK build, the
+resulting Emacs binary will work on any underlying window system
+supported by GDK, such as Wayland and Broadway. We do not recommend
+that you use this configuration, unless you are running a window
+system that's supported by GDK other than X. Running this
+configuration on X is known to have problems, such as undesirable
+frame positioning and various issues with keyboard input of sequences
+such as 'C-;' and 'C-S-u'.
+
+---
+** The docstrings of preloaded files are not in "etc/DOC" any more.
+Instead, they're fetched as needed from the corresponding ".elc" file,
as was already the case for all the non-preloaded files.
+** Emacs Sessions (Desktop)
+
++++
+*** New option to load a locked desktop if locking Emacs is not running.
+The option 'desktop-load-locked-desktop' can now be set to the value
+'check-pid', which means to allow loading a locked ".emacs.desktop"
+file if the Emacs process which locked it is no longer running on the
+local machine. This allows avoiding questions about locked desktop
+files when the Emacs session which locked it crashes, or was otherwise
+interrupted, and didn't exit gracefully. See the "(emacs) Saving
+Emacs Sessions" node in the Emacs manual for more details.
+
* Startup Changes in Emacs 29.1
+++
+** -batch and -script now adjusts the garbage collection levels.
+These switches now set 'gc-cons-percentage' to 1.0 (up from the
+default of 0.1). This means that batch processes will typically use
+more memory than before, but use less time doing garbage collection.
+Batch jobs that are supposed to run for a long time should adjust the
+limit back down again.
+
++++
+** Emacs can now be used more easily in an executable script.
+If you start an executable script with
+
+ #!/usr/bin/emacs -x
+
+Emacs will start without reading any init files (like with '--quick'),
+and then execute the rest of the script file as Emacs Lisp. When it
+reaches the end of the script, Emacs will exit with an exit code from
+the value of the final form.
+
++++
+** Emacs now supports setting 'user-emacs-directory' via '--init-directory'.
+
++++
** Emacs now has a '--fingerprint' option.
This will output a string identifying the current Emacs build.
+++
** New hook 'after-pdump-load-hook'.
-This is run at the end of the Emacs startup process, and it meant to
+This is run at the end of the Emacs startup process, and is meant to
be used to reinitialize structures that would normally be done at load
time.
+** Native Compilation
+
+---
+*** New command 'native-compile-prune-cache'.
+This command deletes older .eln cache entries (but not the ones for
+the current Emacs version).
+
+---
+*** New function 'startup-redirect-eln-cache'.
+This function can be called in your init files to change the
+user-specific directory where Emacs stores the "*.eln" files produced
+by native compilation of Lisp packages Emacs loads. The default
+eln-cache directory is unchanged: it is the 'eln-cache' subdirectory
+of 'user-emacs-directory'.
+
* Incompatible changes in Emacs 29.1
++++
+** Warning about "eager macro-expansion failure" is changed into an error.
+
+---
+** Previously, the X reverseVideo value at startup was heeded for all frames.
+This meant that if you had a reverseVideo resource on the initial
+display, and then opened up a new frame on a display without any
+explicit reverseVideo setting, it would get heeded there, too. (This
+included terminal frames.) In Emacs 29, the reverseVideo X resource
+is handled like all the other X resources, and set on a per-frame basis.
+
++++
+** 'E' in 'query-replace' now edits the replacement with exact case.
+Previously, this command did the same as 'e'.
+
+---
+** '/ a' in *Packages* now limits by package name(s) instead of regexp.
+
++++
+** Setting the goal columns now also affects '<prior>' and '<next>'.
+Previously, 'C-x C-n' only affected 'next-line' and 'previous-line',
+but it now also affects 'scroll-up-command' and 'scroll-down-command'.
+
+---
+** The 'd' command in Dired now more consistently skip dot files.
+In previous Emacs versions, commands like `C-u 10 d' would put the "D"
+mark on the next ten files, no matter whether they were dot files
+(i.e., "." and "..") or not, while marking the next ten lines with the
+mouse (in 'transient-mark-mode') and then hitting 'd' would skip dot
+files. These now work equivalently.
+
+---
+** Isearch in "*Help*" and "*info*" now char-folds quote characters by default.
+This means that you can say 'C-s `foo' (GRAVE ACCENT) if the buffer
+contains "‘foo" (LEFT SINGLE QUOTATION MARK) and the like. These
+quotation characters look somewhat similar in some fonts. To switch
+this off, disable the new 'isearch-fold-quotes-mode' minor mode.
+
+---
+** Sorting commands no longer necessarily change modification status.
+In earlier Emacs versions, commands like 'M-x sort-lines' would always
+change buffer modification status to "modified", whether they changed
+something in the buffer or not. This has been changed: The buffer is
+marked as modified only if the sorting ended up changing the contents
+of the buffer.
+
+---
+** 'string-lines' handles trailing newlines differently.
+It no longer returns an empty final string if the string ends with a
+newline.
+
+---
+** 'TAB' and '<backtab>' are now bound in 'button-map'.
+This means that if point is on a button, 'TAB' will take you to the
+next button, even if the mode has bound it to something else. This
+also means that 'TAB' on a button in an 'outline-minor-mode' heading
+will move point instead of collapsing the outline.
+
+---
+** 'Info-default-directory-list' is no longer populated at Emacs startup.
+If you have code in your init file that removes directories from
+'Info-default-directory-list', this will no longer work.
+
+---
+** 'C-k' no longer deletes files in 'ido-mode'.
+To get the previous action back, put something like the following in
+your Init file:
+
+ (require 'ido)
+ (keymap-set ido-file-completion-map "C-k" #'ido-delete-file-at-head)
+
+---
+** New user option 'term-clear-full-screen-programs'.
+By default, term will now work like most terminals when displaying
+full-screen programs: When they exit, the output is cleared, leaving
+what was displayed in the window before the programs started. Set
+this user option to nil to revert back to the old behavior.
+
---
** Support for old EIEIO functions is not autoloaded any more.
-You need an explicit (require 'eieio-compat) to use 'defmethod'
-and 'defgeneric' (which have been made obsolete in Emacs-25 with
+You need an explicit '(require 'eieio-compat)' to use 'defmethod'
+and 'defgeneric' (which have been made obsolete in Emacs 25.1 with
'cl-defmethod' and 'cl-defgeneric').
-Similarly you might need to (require 'eieio-compat) before loading
+Similarly you might need to '(require 'eieio-compat)' before loading
files that were compiled with an old EIEIO (Emacs<25).
---
** 'C-x 8 .' has been moved to 'C-x 8 . .'.
This is to open up the 'C-x 8 .' map to bind further characters there.
+---
+** 'C-x 8 =' moved to 'C-x 8 = ='.
+You can now use 'C-x 8 =' to insert several characters with macron;
+for example, 'C-x 8 = a' will insert U+0101 LATIN SMALL LETTER A WITH
+MACRON. To insert a lone macron, type 'C-x 8 = =' instead of the
+previous 'C-x ='.
+
+** Eshell
+
+---
+*** 'source' and '.' no longer accept the '--help' option.
+This is for compatibility with the shell versions of these commands,
+which don't handle options like '--help' in any special way.
+
++++
+*** String delimiters in argument predicates/modifiers are more restricted.
+Previously, some argument predicates/modifiers allowed arbitrary
+characters as string delimiters. To provide more unified behavior
+across all predicates/modifiers, the list of allowed delimiters has
+been restricted to "...", '...', /.../, |...|, (...), [...], <...>,
+and {...}. See the "(eshell) Argument Predication and Modification"
+node in the Eshell manual for more details.
+
+---
+** The 'delete-forward-char' command now deletes by grapheme clusters.
+This command is by default bound to the <Delete> function key
+(a.k.a. <deletechar>). When invoked without a prefix argument or with
+a positive prefix numeric argument, the command will now delete
+complete grapheme clusters produced by character composition. For
+example, if point is before an Emoji sequence, pressing <Delete> will
+delete the entire sequence, not just a single character at its
+beginning.
+
++++
+** 'load-history' does not treat autoloads specially any more.
+An autoload definition appears just as a '(defun . NAME)' and the
+'(t . NAME)' entries are not generated any more.
+
+---
+** The Tamil input methods no longer insert Tamil digits.
+The input methods 'tamil-itrans' and 'tamil-inscript' no longer insert
+the Tamil digits, as those digit characters are not used nowadays by
+speakers of the Tamil language. To get back the previous behavior,
+use the new 'tamil-itrans-digits' and 'tamil-inscript-digits' input
+methods instead.
+
++++
+** New variable 'current-time-list' governing default timestamp form.
+Functions like 'current-time' now yield '(TICKS . HZ)' timestamps if
+this new variable is nil. The variable defaults to t, which means
+these functions default to timestamps of the forms '(HI LO US PS)',
+'(HI LO US)' or '(HI LO)', which are less regular and less efficient.
+This is part of a long-planned change first documented in Emacs 27.
+Developers are encouraged to test timestamp-related code with this
+variable set to nil, as it will default to nil in a future Emacs
+version and will be removed some time after that.
+
++++
+** Functions which recreate the "*scratch*" buffer now also initialize it.
+When functions like 'other-buffer' and 'server-execute' recreate
+"*scratch*", they now also insert 'initial-scratch-message' and set
+the major mode according to 'initial-major-mode', like at Emacs
+startup. Previously, these functions ignored
+'initial-scratch-message' and left "*scratch*" in 'fundamental-mode'.
+
* Changes in Emacs 29.1
+---
+** 'longlines-mode' is no longer obsolete.
+
++++
+** New command to change the font size globally.
+To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
+decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x
+C-M-0'. The final key in these commands may be repeated without the
+leading 'C-x' and without the modifiers, e.g. 'C-x C-M-+ C-M-+ C-M-+'
+and 'C-x C-M-+ + +' increase the font size by three steps. When
+mouse-wheel-mode is enabled, 'C-M-wheel-up' and 'C-M-wheel-down' also
+increase and decrease the font size globally. Additionally, the
+variable 'global-text-scale-adjust-resizes-frames' controls whether
+the frames are resized when the font size is changed.
+
++++
+** New function 'file-parent-directory'.
+Get the parent directory of a file.
+
+** New config variable 'syntax-wholeline-max' to reduce the cost of long lines.
+This variable is used by some operations (mostly syntax-propertization
+and font-locking) to treat lines longer than this variable as if they
+were made up of various smaller lines. This can help reduce the
+pathological slowdowns seen in buffers made of a single long line, but
+can also cause misbehavior in the presence of such long lines (tho
+most of that misbehavior should usually be limited to mis-highlighting).
+You can recover the previous behavior with:
+
+ (setq syntax-wholeline-max most-positive-fixnum)
+
+---
+** New bindings in 'find-function-setup-keys' for 'find-library'.
+When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to
+'find-library', 'C-x 4 L' is now bound to 'find-library-other-window'
+and 'C-x 5 L' is now bound to 'find-library-other-frame'.
+
++++
+** New key binding after 'M-x' or 'M-X': 'M-X'.
+Emacs allows different completion predicates to be used with 'M-x'
+(i.e., 'execute-extended-command') via the
+'read-extended-command-predicate' user option. Emacs also has the
+'M-X' (note upper case) command, which only displays commands
+especially relevant to the current buffer. Emacs now allows toggling
+between these modes while the user is inputting a command by hitting
+'M-X' while in the minibuffer.
+
+---
+** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved.
+
+---
+** New command 'duplicate-line'.
+This command duplicates the current line the specified number of times.
+
+---
+** Files with the '.eld' extension are now visited in 'lisp-data-mode'.
+
++++
+** New command 'find-sibling-file'.
+This command jumps to a file considered a "sibling file", which is
+determined according to the new user option 'find-sibling-rules'.
+
++++
+** New user option 'delete-selection-temporary-region'.
+When non-nil, 'delete-selection-mode' will only delete the temporary
+regions (usually set by mouse-dragging or shift-selection).
+
++++
+** New user option 'switch-to-prev-buffer-skip-regexp'.
+This should be a regexp or a list of regexps; buffers whose names
+match those regexps will be ignored by 'switch-to-prev-buffer' and
+'switch-to-next-buffer'.
+
++++
+** New command 'rename-visited-file'.
+This command renames the file visited by the current buffer by moving
+it to a new location, and also makes the buffer visit this new file.
+
+** Menus
+
+---
+*** The entries following the buffers in the "Buffers" menu can now be altered.
+Change the 'menu-bar-buffers-menu-command-entries' variable to alter
+the entries that follow the buffer list.
+
+---
+** 'delete-process' is now a command.
+When called interactively, it will kill the process running in the
+current buffer (if any). This can be useful if you have runaway
+output in the current buffer (from a process or a network connection),
+and want to stop it.
+
++++
+** New command 'restart-emacs'.
+This is like 'save-buffers-kill-emacs', but instead of just killing
+the current Emacs process at the end, it starts a new Emacs process
+(using the same command line arguments as the running Emacs process).
+'kill-emacs' and 'save-buffers-kill-emacs' have also gained new
+optional parameters to restart instead of just killing the current
+process.
+
++++
+** New user option 'mouse-drag-mode-line-buffer'.
+If non-nil, dragging on the buffer name part of the mode-line will
+drag the buffer's associated file to other programs. This option is
+currently only available on X, Haiku and Nextstep (GNUstep or macOS).
+
++++
+** New user option 'mouse-drag-and-drop-region-cross-program'.
+If non-nil, this option allows dragging text in the region from Emacs
+to another program.
+
+---
+** New user option 'mouse-drag-and-drop-region-scroll-margin'.
+If non-nil, this option allows scrolling a window while dragging text
+around without a scroll wheel.
+
++++
+*** 'mouse-drag-copy-region' can now be 'non-empty'.
+This inhibits putting empty strings onto the kill ring.
+
++++
+** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'.
+These options allow adjusting point and scrolling a window when
+dragging items from another program.
+
++++
+** The X Direct Save (XDS) protocol is now supported.
+This means dropping an image or file link from programs such as
+Firefox will no longer create a temporary file in a random directory,
+instead asking you where to save the file first.
+
++++
+** New user option 'record-all-keys'.
+If non-nil, this option will force recording of all input keys,
+including those typed in response to passwords prompt (this was the
+previous behavior). The default is nil, which inhibits recording of
+passwords.
+
++++
+** New user option 'longlines-breakpoint-chars'.
+This is a string containing chars that could be used as breakpoint in
+longlines mode.
+
++++
+** New function 'command-query'.
+This function makes its argument command prompt the user for
+confirmation before executing.
+
++++
+** The 'disabled' property of a command's symbol can now be a list.
+The first element of the list should be the symbol 'query', which will
+cause the command disabled this way prompt the user with a y/n or a
+yes/no question before executing. The new function 'command-query' is
+a convenient method of making commands disabled in this way.
+
+---
+** 'count-lines' will now report buffer totals if given a prefix.
+
++++
+** 'count-words' will now report sentence count when used interactively.
+
+---
+** New user option 'find-library-include-other-files'.
+If set to nil, commands like 'find-library' will only include library
+files in the completion candidates. The default is t, which preserves
+previous behavior, whereby non-library files could also be included.
+
++++
** New command 'sqlite-mode-open-file' for examining an sqlite3 file.
This uses the new 'sqlite-mode' which allows listing the tables in a
DB file, and examining and modifying the columns and the contents of
@@ -135,6 +520,12 @@ This inherits from the 'mode-line' face, but is the face actually used
on the mode lines (along with 'mode-line-inactive').
+++
+** New face attribute pseudo-value 'reset'.
+This value stands for the value of the corresponding attribute of the
+'default' face. It can be used to reset attribute values produced by
+inheriting from other faces.
+
++++
** New function 'buffer-text-pixel-size'.
This is similar to 'window-text-pixel-size', but can be used when the
buffer isn't displayed.
@@ -149,6 +540,60 @@ and pop-up menus.
This controls the style of the pre-edit and status areas of X input
methods.
++++
+** On X11, Emacs now tries to synchronize window resize with the window manager.
+This leads to less flicker and empty areas of a frame being displayed
+when a frame is being resized. Unfortunately, it does not work on
+some ancient buggy window managers, so if Emacs appears to freeze, but
+is still responsive to input, you can turn it off by setting the X
+resource "synchronizeResize" to "off".
+
++++
+** New frame parameter 'alpha-background' and X resource "alphaBackground".
+This controls the opacity of the text background when running on a
+composited display.
+
++++
+** New frame parameter 'shaded'.
+With window managers which support this, it controls whether or not a
+frame's contents will be hidden, leaving only the title bar on display.
+
+---
+** New user option 'x-gtk-use-native-input'.
+This controls whether or not GTK input methods are used by Emacs,
+instead of XIM input methods.
+
++++
+** New user option 'use-system-tooltips'.
+This controls whether to use the toolkit tooltips, or Emacs's own
+native implementation of tooltips as small frames. This option is
+only meaningful if Emacs was built with GTK+, Nextstep, or Haiku
+support, and defaults to t, which makes Emacs use the toolkit
+tooltips. The existing GTK-specific option
+'x-gtk-use-system-tooltips' is now an alias of this new option.
+
++++
+** Non-native tooltips are now supported on Nextstep.
+This means Emacs built with GNUstep or built on macOS is now able to
+display different faces and images inside tooltips when the
+'use-system-tooltips' user option is nil.
+
+** Connection-local variables
+
++++
+*** Some connection-local variables are now user options.
+The variables 'connection-local-profile-alist' and
+'connection-local-criteria-alist' are now user options, in order to
+make it more convenient to inspect and modify them.
+
++++
+*** The default connection-local application can be changed temporarily.
+Running 'with-connection-local-variables' defaults to application
+'tramp'. This can be changed by let-binding
+'connection-local-default-application' to another symbol. This is
+useful when running code in a buffer where Tramp has already set some
+connection-local variables.
+
---
** New minor mode 'pixel-scroll-precision-mode'.
When enabled, and if your mouse supports it, you can scroll the
@@ -165,6 +610,12 @@ This is in addition to previously-supported ways of discovering 24-bit
color support: either via the "RGB" or "setf24" capabilities, or if
the 'COLORTERM' environment variable is set to the value "truecolor".
+*** Select active regions with xterm selection support.
+On terminals with xterm setSelection support, the active region may be
+saved to the X primary selection, following the
+'select-active-regions' variable. This support is enabled when
+'tty-select-active-regions' is non-nil.
+
** ERT
+++
@@ -185,6 +636,7 @@ When environment variable 'EMACS_TEST_JUNIT_REPORT' is set, ERT
generates a JUnit test report under this file name. This is useful
for Emacs integration into CI/CD test environments.
+---
*** Unbound test symbols now signal an 'ert-test-unbound' error.
This affects the 'ert-select-tests' function and its callers.
@@ -218,9 +670,69 @@ inserted.
This command will tell you the name of the Emoji at point. (This
command also works for non-Emoji characters.)
+---
+*** New commands 'emoji-zoom-increase' and 'emoji-zoom-decrease'.
+These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They
+can be used on any character, but are mainly useful for emoji.
+
+---
+*** New input method 'emoji'.
+This allows you to enter emoji using short strings, eg ':face_palm:'
+or ':scream:'.
+
** Help
---
+*** Variable values displayed by 'C-h v' in *Help* are now font-locked.
+
++++
+*** New user option 'help-clean-buttons'.
+If non-nil, link buttons in *Help* will have any surrounding quotes
+removed.
+
+---
+*** 'M-x apropos-variable' output now includes values of variables.
+
++++
+*** New doc string syntax to indicate that symbols shouldn't be links.
+When displaying doc strings in "*Help*" buffers, strings that are
+"`like-this'" are made into links (if they point to a bound
+function/variable). This can lead to false positives when talking
+about values that are symbols that happen to have the same names as
+functions/variables. To inhibit this buttonification, the new
+"\\+`like-this'" syntax can be used.
+
++++
+*** New user option 'help-window-keep-selected'.
+If non-nil, commands to show the info manual and the source will reuse
+the same window the "*Help*" buffer is shown in.
+
+---
+*** Commands like 'C-h f' have changed how they describe menu bindings.
+For instance, previously a command might be described as having the
+following bindings:
+
+ It is bound to <open>, C-x C-f, <menu-bar> <file> <new-file>.
+
+This has been changed to:
+
+ It is bound to <open> and C-x C-f.
+ It can also be invoked from the menu: File → Visit New File...
+
++++
+*** The 'C-h .' command now accepts a prefix argument.
+'C-u C-h .' would previously inhibit displaying a warning message if
+there's no local help at point. This has been changed to call
+'button-describe'/'widget-describe' and display button/widget help
+instead.
+
+---
+*** New user option 'help-enable-variable-value-editing'.
+If enabled, 'e' on a value in "*Help*" will pop you to a new buffer
+where you can edit the value. This is not enabled by default, because
+it's easy to make an edit that yields an invalid result.
+
+---
*** 'C-h b' uses outlining by default.
Set 'describe-bindings-outline' to nil to get the old behavior.
@@ -236,12 +748,44 @@ These will take you (respectively) to the next and previous "page".
---
*** 'describe-char' now also outputs the name of emoji combinations.
++++
+*** New key binding in "*Help*" buffer: 'I'.
+This will take you to the Emacs Lisp manual entry for the item
+displayed, if any.
+
+---
+*** The 'C-h m' ('describe-mode') "*Help*" buffer has been reformatted.
+It now only includes local minor modes at the start, and the global
+minor modes are listed after the major mode.
+
++++
+*** The user option 'help-window-select' now affects apropos commands.
+The apropos commands will now select the apropos window if
+'help-window-select' is non-nil.
+
+---
+*** 'describe-keymap' now considers the symbol at point.
+If the symbol at point is a keymap, 'describe-keymap' suggests it as
+the default candidate.
+
+** Outline Mode
+
++++
+*** Support for customizing the default visibility state of headings.
+Customize the user option 'outline-default-state' to define what
+headings will be visible after Outline mode is turned on. When equal
+to a number, the user option 'outline-default-rules' determines the
+visibility of the subtree starting at the corresponding level. Values
+are provided to control showing a heading subtree depending on whether
+the heading matches a regexp, or on whether its subtree has long lines
+or is itself too long.
+
** Outline Minor Mode
+++
*** New user option 'outline-minor-mode-use-buttons'.
If non-nil, Outline Minor Mode will use buttons to hide/show outlines
-in addition to the ellipsis. Default nil.
+in addition to the ellipsis. The default is nil.
---
*** New user option 'outline-minor-mode-buttons'.
@@ -250,11 +794,21 @@ This is a list of pairs of open/close strings used to display buttons.
+++
** Support for the WebP image format.
This support is built by default when the libwebp library is
-available. To disable it, use the '--without-webp' configure flag.
-Image specifiers can now use ':type webp'.
+available, and includes support for animated WebP images. To disable
+WebP support, use the '--without-webp' configure flag. Image
+specifiers can now use ':type webp'.
** Windows
+*** New user option 'display-buffer-avoid-small-windows'.
+If non-nil, this should be a window height, a number. Windows smaller
+than this will be avoided by 'display-buffer', if possible.
+
++++
+*** New display action 'display-buffer-full-frame'.
+This action removes other windows on the frame when displaying a
+buffer.
+
+++
*** 'display-buffer' now can set up the body size of the chosen window.
For example, a 'display-buffer-alist' entry of
@@ -264,10 +818,19 @@ For example, a 'display-buffer-alist' entry of
will make the body of the chosen window 40 columns wide. For the
height use 'window-height' in combination with 'body-lines'.
-** Rcirc
+---
+*** You can customize which window 'scroll-other-window' operates on.
+This is controlled by the new 'other-window-scroll-default' user option.
+
+** Frames
+++
-*** New command 'rcirc-when'.
+*** 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.
** Tab Bars and Tab Lines
@@ -279,6 +842,7 @@ height use 'window-height' in combination with 'body-lines'.
By default, it contains 'C-c <left>' and 'C-c <right>' to browse
the history of tab window configurations back and forward.
+---
** Better detection of text suspiciously reordered on display.
The function 'bidi-find-overridden-directionality' has been extended
to detect reordering effects produced by embeddings and isolates
@@ -300,14 +864,64 @@ The Emacs server will be automatically stopped when certain conditions
are met. The conditions are given by the argument, which can be
'empty', 'delete-frame' or 'kill-terminal'.
+** Rcirc
+
++++
+*** New command 'rcirc-when'.
+
++++
+*** New user option 'rcirc-cycle-completion-flag'.
+Rcirc will use the default 'completion-at-point' mechanism. The
+conventional IRC behaviour of completing by cycling through the
+available options can be restored by enabling this option.
+
+** Imenu
+
++++
+*** 'imenu' is now bound to 'M-g i' globally.
+
+---
+*** New function 'imenu-flush-cache'.
+Use it if you want Imenu to forget the buffer's index alist and
+recreate it anew next time 'imenu' is invoked.
+
++++
+** Emacs is now capable of abandoning a window's redisplay that takes too long.
+This is controlled by the new variable 'max-redisplay-ticks'. If that
+variable is set to a non-zero value, display of a window will be
+aborted after that many low-level redisplay operations, thus
+preventing Emacs from becoming wedged when visiting files with very
+long lines.
+
* Editing Changes in Emacs 29.1
++++
+** 'M-SPC' is now bound to 'cycle-spacing'.
+Formerly it invoked 'just-one-space'. The actions performed by
+'cycle-spacing' and their order can now be customized via the user
+option 'cycle-spacing-actions'.
+
+---
+** 'zap-to-char' and 'zap-up-to-char' are case-sensitive for upper-case chars.
+These commands now behave as case-sensitive for interactive calls when
+they are invoked with an uppercase character, regardless of the
+`case-fold-search' value.
+
+---
+** 'scroll-other-window' and 'scroll-other-window-down' now respect remapping.
+These commands (bound to 'C-M-v' and 'C-M-V') used to scroll the other
+windows without looking a customizations in that other window. These
+functions now check whether they have been rebound in the buffer in
+that other window, and then call the remapped function instead. In
+addition, these commands now also respect the
+'scroll-error-top-bottom' user option.
+
---
** Indentation of 'cl-flet' and 'cl-labels' has changed.
These forms now indent like this:
(cl-flet ((bla (x)
- (* x x)))
+ (* x x)))
(bla 42))
This change also affects 'cl-macrolet', 'cl-flet*' and
@@ -315,7 +929,7 @@ This change also affects 'cl-macrolet', 'cl-flet*' and
+++
** New user option 'translate-upper-case-key-bindings'.
-This can be set to nil to inhibit translating upper case keys to lower
+Set this option to nil to inhibit translating upper case keys to lower
case keys.
+++
@@ -325,8 +939,8 @@ point.
---
** Improved mouse behavior with auto-scrolling modes.
-When clicking inside the 'scroll-margin' or 'hscroll-margin' region
-the point is now moved only when releasing the mouse button. This no
+When clicking inside the 'scroll-margin' or 'hscroll-margin' region,
+point is now moved only when releasing the mouse button. This no
longer results in a bogus selection, unless the mouse has been
effectively dragged.
@@ -338,6 +952,7 @@ effectively dragged.
Customize this option to limit the number of entries in the menu
"Edit->Paste from Kill Menu". The default is 60.
++++
** Performing a pinch gesture on a touchpad now increases the text scale.
** show-paren-mode
@@ -346,13 +961,18 @@ Customize this option to limit the number of entries in the menu
*** New user option 'show-paren-context-when-offscreen'.
When non-nil, if the point is in a closing delimiter and the opening
delimiter is offscreen, shows some context around the opening
-delimiter in the echo area. Default nil.
+delimiter in the echo area. The default is nil.
+
+May also be set to the symbols 'overlay' or 'child-frame', in which
+case the context is shown in an overlay or child-frame at the top-left
+of the current window. The latter option requires a graphical frame.
+On non-graphical frames, the context is shown in the echo area.
** Comint
+++
*** 'comint-term-environment' is now aware of connection-local variables.
-The user option 'comint-terminfo-terminal' and variable
+The user option 'comint-terminfo-terminal' and the variable
'system-uses-terminfo' can now be set as connection-local variables to
change the terminal used on a remote host.
@@ -360,31 +980,398 @@ change the terminal used on a remote host.
---
*** New user options for alternate wheel events.
-The options 'mouse-wheel-down-alternate-event', 'mouse-wheel-up-alternate-event',
-'mouse-wheel-left-alternate-event', and 'mouse-wheel-right-alternate-event' have
-been added to better support systems where two kinds of wheel events can be
-received.
+The options 'mouse-wheel-down-alternate-event',
+'mouse-wheel-up-alternate-event', 'mouse-wheel-left-alternate-event',
+and 'mouse-wheel-right-alternate-event' have been added to better
+support systems where two kinds of wheel events can be received.
+
+** Internationalization changes
+
+*** The <Delete> function key now allows deleting the entire composed sequence.
+For the details, see the item about the 'delete-forward-char' command
+above.
+
+*** New user option 'composition-break-at-point'.
+Setting it to a non-nil value temporarily disables automatic
+composition of character sequences at point, and thus makes it easier
+to edit such sequences by allowing point to "enter" the sequence.
+
+---
+*** Support for many old scripts and writing systems.
+Emacs now supports and has language-environments and input methods for
+several dozens of old scripts that were used in the past for various
+languages in South and South-East Asia. For each such script Emacs
+now has font-selection and character composition rules, a language
+environment, and an input method. The newly-added scripts and the
+corresponding language environments are:
+
+**** Tai Tham script and the Northern Thai language environment
+**** Brahmi script and language environment
+**** Kaithi script and language environment
+**** Tirhuta script and language environment
+**** Sharada script and language environment
+**** Siddham script and language environment
+**** Syloti Nagri script and language environment
+**** Modi script and language environment
+**** Baybayin script and Tagalog language environment
+**** Hanunoo script and language environment
+**** Buhid script and language environment
+**** Tagbanwa script and language environment
+**** Limbu script and language environment
+**** Balinese script and language environment
+**** Javanese script and language environment
+**** Sundanese script and language environment
+**** Batak script and language environment
+**** Rejang script and language environment
+**** Makasar script and language environment
+**** Lontara script and language environment
+**** Hanifi Rohingya script and language environment
+**** Grantha script and language environment
+**** Kharoshthi script and language environment
+**** Lepcha script and language environment
+**** Meetei Mayek script and language environment
+
+---
+*** The "Oriya" language environment was renamed to "Odia".
+This is to follow the change in the official name of the script. The
+'oriya' input method was also renamed to 'odia'. However, the old
+name of the language environment and the input method are still
+supported.
+
+---
+*** New Greek translation of the Emacs tutorial.
+Type 'C-u C-h t' to select it in case your language setup does not do
+so automatically.
* Changes in Specialized Modes and Packages in Emacs 29.1
+** Dired
+
+---
+*** 'dired-clean-up-buffers-too' moved from dired-x to dired.
+This means that Dired now offers to kill buffers visiting files and
+dirs when they are deleted in Dired. Before, you had to require
+'dired-x' to enable this behavior. To disable this behavior,
+customize the user option 'dired-clean-up-buffers-too' to nil. The
+related user option 'dired-clean-confirm-killing-deleted-buffers'
+(which see) has also been moved to 'dired'.
+
++++
+*** 'dired-do-relsymlink' moved from dired-x to dired.
+The corresponding key "Y" is now bound by default in Dired.
+
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+
++++
+*** 'dired-info' and 'dired-man' moved from dired-x to dired.
+The 'dired-info' and 'dired-man' commands have been moved from the
+'dired-x' package to 'dired'. They have also been renamed to
+'dired-do-info' and 'dired-do-man'; the old command names are obsolete
+aliases.
+
+The keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound
+in Dired mode by default. The user options 'dired-bind-man' and
+'dired-bind-info' no longer have any effect and are obsolete.
+
+To get the old behavior back and unbind these keys in Dired mode, add
+the following to your Init file:
+
+(with-eval-after-load 'dired
+ (keymap-set dired-mode-map "N" nil)
+ (keymap-set dired-mode-map "I" nil))
+
+---
+*** New command 'dired-do-eww'.
+This command visits the file on the current line with EWW.
+
+** Elisp
+
+*** New command 'elisp-eval-buffer' (bound to 'C-c C-e').
+This command evals the forms in the current buffer.
+
+*** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'.
+These commands (bound to 'C-c C-f' and 'C-c C-b', respectively)
+byte-compile the visited file and the current buffer, respectively.
+
+** Games
+
+---
+*** New user option 'tetris-allow-repetitions'.
+This controls how randomness is implemented (whether to use pure
+randomness as before or whether to use a bag).
+
+** Battery
+
++++
+*** New user option 'battery-update-functions'.
+This can be used to trigger actions based on the battery status.
+
+** Enriched Mode
+
++++
+*** New command 'enriched-toggle-markup'.
+This allows you to see the markup in 'enriched-mode' buffers (e.g.,
+the HELLO file).
+
+** Shell Script Mode
+
+---
+*** New user option 'sh-indent-statement-after-and'.
+This controls how statements like the following are indented:
+
+ foo &&
+ bar
+
+** Cperl Mode
+---
+*** New user option 'cperl-file-style'.
+This option determines the indentation style to be used. It can also
+be used as a file-local variable.
+
+** Gud
+
+---
+*** 'gud-go' is now bound to 'C-c C-v'.
+If given a prefix, it will query the user for an argument to use for
+the run/continue command.
+
+** Customize
+
+---
+*** New command 'custom-toggle-hide-all-widgets'.
+This is bound to 'H' and toggles whether to hide or show the widget
+contents.
+
+** Ispell
+
+---
+*** 'ispell-region' and 'ispell-buffer' now push the mark.
+These commands push onto the mark ring the location of the last
+misspelled word where corrections were offered, so that you can then
+skip back to that location with 'C-x C-x'.
+
+** Dabbrev
+
+---
+*** New function 'dabbrev-capf' for use on 'completion-at-point-functions'.
+
++++
+*** New user option 'dabbrev-ignored-buffer-modes'.
+Buffers with major modes in this list will be ignored. By default,
+this includes "binary" buffers like 'archive-mode' and 'image-mode'.
+
+** Package
+
++++
+*** New command 'package-update'.
+This command allows you to upgrade packages without using 'M-x
+list-packages'.
+
++++
+*** New command 'package-update-all'.
+This command allows updating all packages without any queries.
+
++++
+*** New commands 'package-recompile' and 'package-recompile-all'.
+These commands can be useful if the .elc files are out of date
+(invalid byte code and macros).
+
++++
+*** New DWIM action on 'x' in "*Packages*" buffer.
+If no packages are marked, 'x' will install the package under point if
+it isn't already, and remove it if it is installed.
+
+** Miscellaneous
+
++++
+*** New command 'scratch-buffer'.
+This command switches to the "*scratch*" buffer. If "*scratch*" doesn't
+exist, the command creates it first. You can use this command if you
+inadvertently delete the "*scratch*" buffer.
+
+** Debugging
+
+---
+*** 'q' in a *Backtrace* buffer no longer clears the buffer.
+Instead it just buries the buffer and switches the mode from
+'debugger-mode' to 'backtrace-mode', since commands like 'e' are no
+longer available after exiting the recursive edit.
+
++++
+*** New user option 'debug-allow-recursive-debug'.
+This user option controls whether the 'e' (in a "*Backtrace*"
+buffer or while edebugging) and 'C-x C-e' (while edebugging) commands
+lead to a (further) backtrace. By default, this variable is nil,
+which is a change in behaviour from previous Emacs versions.
+
++++
+*** 'e' in edebug can now take a prefix arg to pretty-print the results.
+When invoked with a prefix argument, as in 'C-u e', this command will
+pop up a new buffer and show the full pretty-printed value there.
+
++++
+*** 'C-x C-e' now interprets a non-zero prefix arg to pretty-print the results.
+When invoked with a non-zero prefix argument, as in 'C-u C-x C-e',
+this command will pop up a new buffer and show the full pretty-printed
+value there.
+
+** Compile
+
++++
+*** New user option 'compilation-hidden-output'.
+This can be used to make specific parts of compilation output
+invisible.
+
++++
+*** The 'compilation-auto-jump-to-first-error' user option has been extended.
+It can now have the additional values 'if-location-known' (which will
+only jump if the location of the first error is known), and
+'first-known' (which will jump to the first known error location).
+
++++
+*** New user option 'compilation-max-output-line-length'.
+Lines longer than this will have the ends hidden, with a button to
+reveal the hidden text. This speeds up operations like grepping on
+files that have few newlines.
+
+** Flymake
+
++++
+*** New user option 'flymake-mode-line-lighter'.
+
++++
+** New minor mode 'word-wrap-whitespace-mode' for extending 'word-wrap'.
+This mode switches 'word-wrap' on, and breaks on all the whitespace
+characters instead of just SPC and TAB.
+
+---
+** New mode, 'emacs-news-mode', for editing the NEWS file.
+This mode adds some highlighting, fixes the 'M-q' command, and has
+commands for doing maintenance.
+
+---
+** Kmacro
+Kmacros are now OClosures and have a new constructor 'kmacro' which
+uses the 'key-parse' syntax. It replaces the old 'kmacro-lambda-form'
+(which is now declared obsolete).
+
+---
+** 'savehist.el' can now truncate variables that are too long.
+An element of 'savehist-additional-variables' can now be of the form
+'(VARIABLE . MAX-ELTS)', which means to truncate the VARIABLE's value to
+at most MAX-ELTS elements (if the value is a list) before saving the
+value.
+
** Minibuffer and Completions
-*** The *Completions* buffer can now be automatically selected.
-To enable this behavior, customize the option 'completion-auto-select'
-to t. Then pressing TAB will switch to the *Completions* buffer when
-it pops up that buffer.
++++
+*** New commands for navigating completions from the minibuffer.
+When the minibuffer is the current buffer, typing 'M-<up>' or
+'M-<down>' selects a previous/next completion candidate from the
+"*Completions*" buffer and inserts it to the minibuffer.
+When the user option 'minibuffer-completion-auto-choose' is nil,
+'M-<up>' and 'M-<down>' do the same, but without inserting
+a completion candidate to the minibuffer, then 'M-RET' can be used
+to choose the currently active candidate from the "*Completions*"
+buffer and exit the minibuffer. With a prefix argument, 'C-u M-RET'
+inserts the currently active candidate to the minibuffer, but doesn't
+exit the minibuffer. These keys are also available for in-buffer
+completion, but they don't insert candidates automatically, you need
+to type 'M-RET' to insert the selected candidate to the buffer.
-*** New user option 'completion-wrap-movement'.
++++
+*** The "*Completions*" buffer can now be automatically selected.
+To enable this behavior, customize the user option
+'completion-auto-select' to t, then pressing 'TAB' will switch to the
+"*Completions*" buffer when it pops up that buffer. If the value is
+'second-tab', then the first 'TAB' will display "*Completions*", and
+the second one will switch to the "*Completions*" buffer.
+
+---
+*** New user option 'completion-auto-wrap'.
When non-nil, the commands 'next-completion' and 'previous-completion'
automatically wrap around on reaching the beginning or the end of
-the *Completions* buffer.
+the "*Completions*" buffer.
+
++++
+*** New values for the 'completion-auto-help' user option.
+There are two new values to control the way the "*Completions*" buffer
+behaves after pressing a 'TAB' if completion is not unique. The value
+'always' updates or shows the "*Completions*" buffer after any attempt
+to complete. The value 'visual' is like 'always', but only updates
+the completions if they are already visible. The default value 't'
+always hides the completion buffer after some completion is made.
+
+*** New commands to complete the minibuffer history.
+'minibuffer-complete-history' ('C-x up') is like 'minibuffer-complete'
+but completes on the history items instead of the default completion
+table. 'minibuffer-complete-defaults' ('C-x down') completes
+on the list of default items.
+
++++
+*** New user option 'completions-sort'.
+This option controls the sorting of the completion candidates in
+the "*Completions*" buffer. Available styles are no sorting,
+alphabetical (the default), or a custom sort function.
+
++++
+*** New user option 'completions-max-height'.
+This option limits the height of the "*Completions*" buffer.
+
++++
+*** New user option 'completions-header-format'.
+This is a string to control the heading line to show in the
+"*Completions*" buffer before the list of completions.
+If it contains "%s", that is replaced with the number of completions.
+If nil, the heading line is not shown.
+
++++
+*** New user option 'completions-highlight-face'.
+When this user option names a face, the current
+candidate in the "*Completions*" buffer is highlighted with that face.
+The nil value disables this highlighting.
+
++++
+*** Choosing a completion with a prefix argument doesn't exit the minibuffer.
+This means that typing 'C-u RET' on a completion candidate in the
+"*Completions*" buffer inserts the completion to the minibuffer,
+but doesn't exit the minibuffer.
+
++++
+*** You can now define abbrevs for the fundamental minibuffer modes.
+'minibuffer-mode-abbrev-table' and
+'minibuffer-inactive-mode-abbrev-table' are now defined.
** Isearch and Replace
+++
-*** New user option 'char-fold-override' disables default character equivalences.
+*** Changes in how Isearch responds to 'mouse-yank-at-point'.
+If a user does 'C-s' and then uses '<mouse-2>' ('mouse-yank-primary')
+outside the echo area, Emacs will, by default, end the Isearch and
+yank the text at mouse cursor. But if 'mouse-yank-at-point' is
+non-nil, the text will now be added to the Isearch instead.
+
++++
+*** New user option 'char-fold-override'.
+Non-nil means that the default definitions of equivalent characters
+are overridden.
+
++++
+*** New command 'isearch-emoji-by-name'.
+It is bound to 'C-x 8 e RET' during an incremental search. The
+command accepts the Unicode name of an Emoji (for example, "smiling
+face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
+completion, and adds the Emoji into the search string.
++++
** New minor mode 'glyphless-display-mode'.
This allows an easy way to toggle seeing all glyphless characters in
the current buffer.
@@ -398,7 +1385,7 @@ For instance, to enable jumping to the "*Messages*" buffer with
(set-register ?m '(buffer . "*Messages*"))
-** pixel-fill
+** Pixel-fill
+++
*** This is a new package that deals with filling variable-pitch text.
@@ -409,12 +1396,20 @@ This fills the region to be no wider than a specified pixel width.
** Info
++++
+*** 'M-x info-apropos' now takes a prefix argument to search for regexps.
+
---
*** New command 'Info-goto-node-web' and key binding 'G'.
This will take you to the gnu.org web server's version of the current
info node. This command only works for the Emacs and Emacs Lisp manuals.
-** vc
+** VC
+
++++
+*** New command '%' ('vc-dir-mark-by-regexp').
+This command marks files based on a regexp. If given a prefix
+argument, unmark instead.
---
*** 'C-x v v' on an unregistered file will now use the most specific backend.
@@ -433,7 +1428,7 @@ If non-nil, 'C-c C-a' will put attached files at the end of the message.
---
*** Message Mode now supports image yanking.
----
++++
*** New user option 'message-server-alist'.
This controls automatic insertion of the "X-Message-SMTP-Method"
header before sending a message.
@@ -449,7 +1444,57 @@ header before sending a message.
*** 'texinfo-mode' now has a specialised 'narrow-to-defun' definition.
It narrows to the current node.
-** eww/shr
+** EUDC
+
++++
+*** 'eudc-expansion-overwrites-query' to 'eudc-expansion-save-query-as-kill'.
+'eudc-expansion-overwrites-query' is renamed to
+'eudc-expansion-save-query-as-kill' to reflect the actual behavior of
+the user option.
+
++++
+*** New command 'eudc-expand-try-all'.
+This command can be used in place of 'eudc-expand-inline'. It takes a
+prefix argument that causes 'eudc-expand-try-all' to return matches
+from all servers instead of just the matches from the first server to
+return any. This is useful for example, if one wants to search LDAP
+for a name that happens to match a contact in one's BBDB.
+
++++
+*** New behavior and default for user option 'eudc-inline-expansion-format'.
+EUDC inline expansion result formatting defaulted to
+
+ '("%s %s <%s>" firstname name email)
+
+Since email address specifications need to comply with RFC 5322 in
+order to be useful in messages, there was a risk to produce syntax
+which was standard with RFC 822, but is marked as obsolete syntax by
+its successor RFC 5322. Also, the first and last name part was never
+enclosed in double quotes, potentially producing invalid address
+specifications, which may be rejected by a receiving MTA. Thus, this
+variable can now additionally be set to nil (the new default), or a
+function. In both cases, the formatted result will be in compliance
+with RFC 5322. When set to nil, a default format very similar to the
+old default will be produced. When set to a function, that function
+is called, and the returned values are used to populate the phrase and
+comment parts (see RFC 5322 for definitions). In both cases, the
+phrase part will be automatically quoted if necessary.
+
++++
+*** New function 'eudc-capf-complete' with 'message-mode' integration.
+EUDC can now contribute email addresses to 'completion-at-point' by
+adding the new function 'eudc-capf-complete' to
+'completion-at-point-functions' in 'message-mode'.
+
+** EWW/SHR
+
++++
+*** New user option to automatically rename EWW buffers.
+The 'eww-auto-rename-buffer' user option can be configured to rename
+rendered web pages by using their title, URL, or a user-defined
+function which returns a string. For the first two cases, the length
+of the resulting name is controlled by 'eww-buffer-name-length'. By
+default, no automatic renaming is performed.
+++
*** New user option 'shr-allowed-images'.
@@ -460,7 +1505,7 @@ allowed images.
*** New user option 'shr-use-xwidgets-for-media'.
If non-nil (and Emacs has been built with support for xwidgets),
display <video> elements with an xwidget. Note that this is
-experimental, and is known to crash Emacs on some systems, and just
+experimental; it is known to crash Emacs on some systems, and just
doesn't work on other systems. Also see etc/PROBLEMS.
+++
@@ -468,8 +1513,25 @@ doesn't work on other systems. Also see etc/PROBLEMS.
These are used to alter an URL before using it. By default it removes
the common "utm_" trackers from URLs.
+** Find-Dired
+
+*** New command 'find-dired-with-command'.
+This enables users to run 'find-dired' with an arbitrary command,
+enabling running commands previously unsupported and also enabling new
+commands to be built on top.
+
** Gnus
++++
+*** Tool bar changes in Gnus/Message.
+There were previously two styles of tool bars available in Gnus and
+Message, referred to as 'gnus-summary-tool-bar-retro',
+'gnus-group-tool-bar-retro' and 'message-tool-bar-retro', and
+'gnus-summary-tool-bar-gnome', 'gnus-group-tool-bar-gnome' and
+'message-tool-bar-gnome'. The "retro" tool bars have been removed (as
+well as the icons used), and the "Gnome" tool bars are now the only
+pre-defined toolbars.
+
---
*** Gnus now uses a variable-pitch font in the headers by default.
To get the monospace font back, you can put something like the
@@ -487,19 +1549,30 @@ All other 'gnus-header-*' faces inherit from this face now.
+++
*** New user option 'gnus-treat-emojize-symbols'.
If non-nil, symbols that have an emoji representation will be
-displayed as emojis. Default nil.
+displayed as emojis. The default is nil.
+++
*** New command 'gnus-article-emojize-symbols'.
This is bound to 'W D e' and will display symbols that have emoji
representation as emojis.
++++
+*** New mu backend for gnus-search.
+Configuration is very similar to the notmuch and namazu backends. It
+supports the unified search syntax.
+
+---
+*** 'gnus-html-image-cache-ttl' is now a seconds count.
+Formerly it was a pair of numbers '(A B)' that represented 65536*A + B,
+to cater to older Emacs implementations that lacked bignums.
+The older form still works but is undocumented.
+
** EIEIO
+++
*** 'slot-value' can now be used to access slots of 'cl-defstruct' objects.
-** align
+** Align
---
*** Alignment in 'text-mode' has changed.
@@ -508,25 +1581,21 @@ M-x align' for it to work. This has now been changed. The default
regexp for 'C-u M-x align-regexp' has also been changed to be easier
for inexperienced users to use.
-** eww
-
-+++
-*** New user option to automatically rename EWW buffers.
-The 'eww-auto-rename-buffer' user option can be configured to rename
-rendered web pages by using their title, URL, or a user-defined
-function which returns a string. For the first two cases, the length
-of the resulting name is controlled by 'eww-buffer-name-length'. By
-default, no automatic renaming is performed.
-
** Help
+---
+*** New mode, 'emacs-news-view-mode', for viewing the NEWS file.
+This mode is used by the 'C-h N' command, and adds buttons to manual
+entries and symbol references.
+
+---
*** New user option 'help-link-key-to-documentation'.
When this option is non-nil (which is the default), key bindings
displayed in the "*Help*" buffer will be linked to the documentation
for the command they are bound to. This does not affect listings of
key bindings and functions (such as 'C-h b').
-** info-look
+** Info-look
---
*** info-look specs can now be expanded at run time instead of a load time.
@@ -534,31 +1603,38 @@ The new ':doc-spec-function' element can be used to compute the
':doc-spec' element when the user asks for info on that particular
mode (instead of at load time).
-** subr-x
+** Subr-x
+++
*** New macro 'with-memoization' provides a very primitive form of memoization.
-** ansi-color
+** Ansi-color
---
*** Support for ANSI 256-color and 24-bit colors.
256-color and 24-bit color codes are now handled by ANSI color
filters and displayed with the specified color.
-** term-mode
+** Term-mode
+
+---
+*** New user option 'term-bind-function-keys'.
+If non-nil, 'term-mode' will pass the function keys on to the
+underlying shell instead of using the normal Emacs bindings.
---
*** Support for ANSI 256-color and 24-bit colors, italic and other fonts.
-Term-mode can now display 256-color and 24-bit color codes. It can
+'term-mode' can now display 256-color and 24-bit color codes. It can
also handle ANSI codes for faint, italic and blinking text, displaying
it with new 'term-{faint,italic,slow-blink,fast-blink}' faces.
** Xref
++++
*** 'project-find-file' and 'project-or-external-find-file' now accept
a prefix argument which is interpreted to mean "include all files".
++++
*** 'project-kill-buffers' can display the list of buffers to kill.
Customize the user option 'project-kill-buffers-display-buffer-list'
to enable the display of the buffer list.
@@ -568,6 +1644,21 @@ to enable the display of the buffer list.
It is bound to 'C-M-,' and jumps to the location where 'xref-go-back'
('M-,', also known as 'xref-pop-marker-stack') was invoked previously.
++++
+*** 'xref-query-replace-in-results' prompting change.
+This command no longer prompts for FROM when called without prefix
+argument. This makes the most common case faster: replacing entire
+matches.
+
++++
+*** New command 'xref-find-references-and-replace' to rename one identifier.
+
+---
+*** New variable 'xref-current-item' (renamed from a private version).
+
+---
+*** New function 'xref-show-xrefs'.
+
** File notifications
+++
@@ -599,6 +1690,7 @@ The keybinding for 'image-transform-fit-to-width' is now 's i'.
*** User option 'image-auto-resize' can now be set to 'fit-window'.
This works like 'image-transform-fit-to-window'.
+---
*** New user option 'image-auto-resize-max-scale-percent'.
The new 'fit-window' option will never scale an image more than this
much (in percent). It is nil by default, which means no limit.
@@ -609,6 +1701,10 @@ This controls whether or not to show a message when opening certain
image formats saying how to edit it as text. The default is to show
this message for SVG and XPM.
++++
+*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'.
+These commands horizontally and vertically flip the image under point.
+
** Image-Dired
+++
@@ -630,11 +1726,11 @@ user options that are no longer needed are now obsolete:
*** Navigation and marking commands now work in image display buffer.
The following new bindings have been added:
- n / SPC image-dired-display-next-thumbnail-original
- p / DEL image-dired-display-previous-thumbnail-original
- m image-dired-mark-thumb-original-file
- d image-dired-flag-thumb-original-file
- u image-dired-unmark-thumb-original-file
+ n or SPC image-dired-display-next-thumbnail-original
+ p or DEL image-dired-display-previous-thumbnail-original
+ m image-dired-mark-thumb-original-file
+ d image-dired-flag-thumb-original-file
+ u image-dired-unmark-thumb-original-file
---
*** Reduce dependency on external "exiftool" command.
@@ -705,13 +1801,25 @@ Emacs for tens of seconds. In addition, you can now customize this
option to nil to disable this confirmation completely.
---
-*** Make 'image-dired-rotate-thumbnail-(left|right)' obsolete.
-Instead, use 'M-x image-dired-refresh-thumb' to generate a new
-thumbnail, or 'M-x image-rotate' to rotate the thumbnail without
-updating the thumbnail file.
+*** 'image-dired-rotate-thumbnail-(left|right)' is now obsolete.
+Instead, use commands 'image-dired-refresh-thumb' to generate a new
+thumbnail, or 'image-rotate' to rotate the thumbnail without updating
+the thumbnail file.
** Dired
+---
+*** New user option 'dired-omit-lines'.
+This is used by 'dired-omit-mode', and now allows you to hide based on
+other things than just the file names.
+
++++
+*** New user option 'dired-mouse-drag-files'.
+If non-nil, dragging file names with the mouse in a Dired buffer will
+initiate a drag-and-drop session allowing them to be opened in other
+programs.
+
++++
*** New user option 'dired-free-space'.
Dired will now, by default, include the free space in the first line
instead of having it on a separate line. To get the previous behavior
@@ -725,8 +1833,31 @@ If non-nil (which is the default), hitting 'RET' or 'mouse-1' on
the directory components at the directory displayed at the start of
the buffer will take you to that directory.
+---
+*** Search and replace in Dired/Wdired supports more regexps.
+For example, the regexp ".*" will match only characters that are part
+of the file name. Also "^.*$" can be used to match at the beginning
+of the file name and at the end of the file name.
+
+** Bookmarks
+
+---
+*** 'list-bookmarks' now includes a type column.
+Types are registered via a 'bookmark-handler-type' symbol property on
+the jumping function.
+
++++
+*** 'bookmark-sort-flag' can now be set to 'last-modified'.
+This will display bookmark list from most recently set to least
+recently set.
+
+---
+*** When editing a bookmark annotation, 'C-c C-k' will now cancel.
+It is bound to the new command 'bookmark-edit-annotation-cancel'.
+
** Exif
+---
*** New function 'exif-field'.
This is a convenience function to extract the field data from
'exif-parse-file' and 'exif-parse-buffer'.
@@ -735,13 +1866,12 @@ This is a convenience function to extract the field data from
---
*** New user option 'xwidget-webkit-buffer-name-format'.
-Using this option you can control how the xwidget-webkit buffers are
-named.
+This option controls how xwidget-webkit buffers are named.
---
*** New user option 'xwidget-webkit-cookie-file'.
-Using this option you can control whether the xwidget-webkit buffers
-save cookies set by web pages, and if so, in which file to save them.
+This option controls whether the xwidget-webkit buffers save cookies
+set by web pages, and if so, in which file to save them.
+++
*** New minor mode 'xwidget-webkit-edit-mode'.
@@ -775,13 +1905,32 @@ and friends.
---
*** Tramp supports abbreviating remote home directories now.
-When calling 'abbreviate-file-name' on a Tramp filename, the result
+When calling 'abbreviate-file-name' on a Tramp file name, the result
will abbreviate the user's home directory, for example by abbreviating
"/ssh:user@host:/home/user" to "/ssh:user@host:~".
++++
+*** New user option 'tramp-use-scp-direct-remote-copying'.
+When set to non-nil, Tramp does not copy files between two remote
+hosts via a local copy in its temporary directory, but lets the 'scp'
+command do this job.
+
++++
+*** Proper password prompts for methods "doas", "sudo" and "sudoedit".
+The password prompts for these methods reflect now the credentials of
+the user requesting such a connection, and not of the user who is the
+target. This has always been needed, just the password prompt and the
+related 'auth-sources' entry were wrong.
+
** Browse URL
---
+*** New user option 'browse-url-default-scheme'.
+This user option decides which URL scheme that 'browse-url' and
+related functions will use by default. For example, you could
+customize this to "https" to always prefer HTTPS URLs.
+
+---
*** Support for the Netscape web browser has been removed.
This support has been obsolete since Emacs 25.1. The final version of
the Netscape web browser was released in February, 2008.
@@ -791,10 +1940,173 @@ the Netscape web browser was released in February, 2008.
This support has been obsolete since Emacs 25.1. The final version of
the Galeon web browser was released in September, 2008.
+---
+*** Support for the "Mozilla" web browser is now obsolete.
+Note that this historical web browser is different from Mozilla
+Firefox; it is its predecessor.
+
+** Ruby Mode
+
+---
+*** New user option 'ruby-toggle-block-space-before-parameters'.
+
+** Eshell
+
++++
+*** New feature to easily bypass Eshell's own pipelining.
+Prefixing '|', '<' or '>' with an asterisk, i.e. '*|', '*<' or '*>',
+will cause the whole command to be passed to the operating system
+shell. This is particularly useful to bypass Eshell's own pipelining
+support for pipelines which will move a lot of data. See section
+"Running Shell Pipelines Natively" in the Eshell manual, node
+"(eshell) Input/Output".
+
++++
+*** New module to help supplying absolute file names to remote commands.
+After enabling the new 'eshell-elecslash' module, typing a forward
+slash as the first character of a command line argument will
+automatically insert the Tramp prefix. The automatic insertion
+applies only when 'default-directory' is remote and the command is a
+Lisp function. This frees you from having to keep track of whether
+commands are Lisp function or external when supplying absolute file
+name arguments. See "Electric forward slash" in the Eshell manual.
+
++++
+*** Double-quoting an Eshell expansion now treats the result as a single string.
+If an Eshell expansion like '$FOO' is surrounded by double quotes, the
+result will always be a single string, no matter the type that would
+otherwise be returned.
+
++++
+*** Concatenating Eshell expansions now works more similarly to other shells.
+When concatenating an Eshell expansion that returns a list, "adjacent"
+elements of each operand are now concatenated together,
+e.g. '$list("a" "b")c' returns '("a" "bc")'. See the "(eshell)
+Expansion" node in the Eshell manual for more details.
+
++++
+*** Eshell subcommands with multiline numeric output return lists of numbers.
+If every line of the output of an Eshell subcommand like '${COMMAND}'
+is numeric, the result will be a list of numbers (or a single number
+if only one line of output). Previously, this only converted numbers
+when there was a single line of output.
+
+---
+*** Built-in Eshell commands now follow POSIX/GNU argument syntax conventions.
+Built-in commands in Eshell now accept command-line options with
+values passed as a single token, such as '-oVALUE' or
+'--option=VALUE'. New commands can take advantage of this with the
+'eshell-eval-using-options' macro. See "Defining new built-in
+commands" in the "(eshell) Built-ins" node of the Eshell manual.
+
+---
+*** Eshell globs ending with '/' now match only directories.
+Additionally, globs ending with '**/' or '***/' no longer raise an
+error, and now expand to all directories recursively (following
+symlinks in the latter case).
+
+** Shell
+
+---
+*** New user option 'shell-kill-buffer-on-exit'.
+Enabling this will automatically kill a *shell* buffer as soon as the
+shell session terminates.
+
+** Calc
+
++++
+*** New user option 'calc-kill-line-numbering'.
+Set it to nil to exclude line numbering from kills and copies.
+
+** Miscellaneous
+
++++
+*** New user option 'font-lock-ignore'.
+This option provides a mechanism to selectively disable font-lock
+keyword-driven fontifications.
+
+---
+*** New user option 'auto-save-visited-predicate'.
+This user option is a predicate function which is called by
+'auto-save-visited-mode' to decide whether or not to save a buffer.
+You can use it to automatically save only specific buffers, for
+example buffers using a particular mode or in some directory.
+
+---
+*** New user option 'remote-file-name-inhibit-auto-save-visited'.
+If this user option is non-nil, 'auto-save-visited-mode' will not
+auto-save remote buffers. The default is nil.
+
++++
+*** New package vtable.el for formatting tabular data.
+This package allows formatting data using variable-pitch fonts.
+The resulting tables can display text in variable pitch fonts, text
+using fonts of different sizes, and images. See the "(vtable) Top"
+manual for more details.
+
+---
+*** New minor mode 'elide-head-mode'.
+Enabling this minor mode turns on hiding header material, like
+'elide-head' does; disabling it shows the header. The commands
+'elide-head' and 'elide-head-show' are now obsolete.
+
++++
+*** New user option 'project-vc-include-untracked'.
+If non-nil, files untracked by a VCS are considered to be part of
+the project by a VC project based on that VCS.
+
+---
+*** 'recentf-mode' now uses shortened filenames by default.
+This means that e.g. "/home/foo/bar" is now displayed as "~/bar".
+Customize the user option 'recentf-filename-handlers' to nil to get
+back the old behavior.
+
+---
+*** New command 'recentf-open'.
+This command prompts for a recently opened file in the minibuffer, and
+visits it.
+
+---
+*** 'ffap-machine-at-point' no longer pings hosts by default.
+It will now simply look at a hostname to determine if it is valid,
+instead of also trying to ping it. Customize the user option
+'ffap-machine-p-known' to 'ping' to get the old behavior back.
+
+---
+*** The 'run-dig' command is now obsolete; use 'dig' instead.
+
+---
+** The autoarg.el library is now marked obsolete.
+This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor
+modes to emulate the behavior of the historical editor Twenex Emacs.
+It is believed to no longer be useful.
+
+---
+** proced.el shows system processes of remote hosts.
+When 'default-directory' is remote, and 'proced' is invoked with a
+negative argument like 'C-u - proced', the system processes of that
+remote host are shown. Alternatively, the user option
+'proced-show-remote-processes' can be set to non-nil.
+'proced-signal-function' has been marked obsolete.
+
* New Modes and Packages in Emacs 29.1
+++
+** New package 'oclosure'.
+Allows the creation of "functions with slots" or "function objects"
+via the macros 'oclosure-define' and 'oclosure-lambda'.
+
+*** New generic function 'oclosure-interactive-form'.
+Used by 'interactive-form' when called on an OClosure.
+This allows specific OClosure types to compute their interactive specs
+on demand rather than precompute them when created.
+
+---
+** New theme 'leuven-dark'.
+This is a dark version of the 'leuven' theme.
+
++++
** New mode 'erts-mode'.
This mode is used to edit files geared towards testing actions in
Emacs buffers, like indentation and the like. The new ert function
@@ -803,6 +2115,79 @@ Emacs buffers, like indentation and the like. The new ert function
* Incompatible Lisp Changes in Emacs 29.1
+---
+** 'find-image' now uses 'create-image'.
+This means that images found through 'find-image' also has
+auto-scaling applied. (This only makes a difference on HiDPI
+displays.)
+
++++
+** Changes to "raw" in-memory xbm images are specified.
+Some years back Emacs gained the ability to scale images, and you
+could then specify :width and :height when using 'create-image' on all
+image types -- except xbm images, because this format already used the
+:width and :height arguments to specify the width/height of the "raw"
+in-memory format. This meant that if you used these specifications
+on, for instance, xbm files, Emacs would refuse to display them. This
+has been changed, and :width/:height now works as with all other image
+formats, and the way to specify the width/height of the "raw"
+in-memory format is now by using :data-width and :data-height.
+
++++
+** loaddefs.el generation has been reimplemented.
+The various loaddefs.el files in the Emacs tree (which contain
+information about autoloads, built-in packages and package prefixes)
+used to be generated by functions in autoloads.el. These are now
+generated by loaddefs-gen.el instead. This leads to functionally
+equivalent loaddef files, but they do not use exactly the same syntax,
+so using 'M-x update-file-autoloads' no longer works. (This didn't
+work well in most files in the past, either, but it will now signal an
+error in any file.)
+
+In addition, files are scanned in a slightly different way.
+Previously ;;;### specs inside a top-level form (i.e., something like
+(when ... ;;;### ...) would be ignored. They are now parsed as
+normal.
+
++++
+** 'buffer-modified-p' has been extended.
+This function was previously documented to return only nil or t. This
+has been changed to nil/'autosaved'/non-nil. The new 'autosaved'
+value means that the buffer is modified, but that it hasn't been
+modified since the time of last auto-save.
+
+---
+** 'with-silent-modifications' also restores buffer autosave status.
+'with-silent-modifications' is a macro meant to be used by the font
+locking machinery to allow applying text properties without changing
+the modification status of the buffer. However, it didn't restore the
+buffer autosave status, so applying font locking to a modified buffer
+that had already been auto-saved would trigger another auto-saving.
+This is no longer the case.
+
+---
+** 'prin1' doesn't always escape "." and "?" in symbols any more.
+Previously, symbols like 'foo.bar' would be printed by 'prin1' as
+"foo\.bar". This now prints as "foo.bar" instead. The Emacs Lisp
+reader interprets these strings as referring to the same symbol, so
+this is virtually always backwards-compatible, but there may
+theoretically be code out there that expects a specific printed
+representation.
+
+The same is the case with the "?" character: The 'foo?' symbol is now
+printed as "foo?" instead of "foo\?".
+
+If the "." and "?" characters are the first character in the symbol,
+they will still be escaped, so the '.foo' symbol is still printed as
+"\.foo" and the '?bar' symbol is still printed as "\?bar".
+
++++
+** Remapping 'mode-line' no longer works as expected.
+'mode-line' is now the parent face of the new 'mode-line-active' face,
+and remapping parent of basic faces does not work reliably.
+Instead of remapping 'mode-line', you have to remap 'mode-line-active'.
+
+---
** User option 'mail-source-ignore-errors' is now obsolete.
The whole mechanism for prompting users to continue in case of
mail-source errors has been removed, so this option is no longer
@@ -819,6 +2204,7 @@ a weight of 'normal' and the font doesn't have this weight, Emacs
won't find the font spec. In these cases, replacing ":weight 'normal"
with ":weight 'medium" should fix the issue.
+---
** Keymap descriptions have changed.
'help--describe-command', 'C-h b' and associated functions that output
keymap descriptions have changed. In particular, prefix commands are
@@ -866,7 +2252,7 @@ like:
---
** The 'inhibit-changing-match-data' variable is now obsolete.
Instead, functions like 'string-match' and 'looking-at' now take an
-optional 'inhibit-modify' argument.
+optional INHIBIT-MODIFY argument.
---
** 'gnus-define-keys' is now obsolete.
@@ -885,12 +2271,68 @@ Use 'exif-parse-file' and 'exif-field' instead.
** 'insert-directory' alternatives should not change the free disk space line.
This change is now applied in 'dired-insert-directory'.
+---
+** Some functions and variables obsolete since Emacs 24 have been removed:
+'Info-edit-map', 'allout-abbreviate-flattened-numbering',
+'allout-mode-deactivate-hook', 'ansi-color-unfontify-region',
+'auth-source-forget-user-or-password', 'auth-source-hide-passwords',
+'auth-source-user-or-password', 'bibtex-complete',
+'bibtex-entry-field-alist', 'buffer-substring-filters',
+'byte-compile-disable-print-circle', 'cfengine-mode-abbrevs',
+'chart-map', 'comint-dynamic-complete',
+'comint-dynamic-complete-as-filename',
+'comint-dynamic-simple-complete', 'command-history-map',
+'completion-annotate-function', 'condition-case-no-debug',
+'count-lines-region', 'data-debug-map', 'deferred-action-list',
+'deferred-action-function', 'dired-x-submit-report',
+'eieio-defgeneric', 'eieio-defmethod', 'emacs-lock-from-exiting',
+'erc-complete-word', 'eshell-cmpl-suffix-list', 'eshell-for',
+'font-lock-maximum-size', 'gnus-carpal',
+'gnus-debug-exclude-variables', 'gnus-debug-files',
+'gnus-local-domain', 'gnus-outgoing-message-group',
+'gnus-registry-user-format-function-M', 'image-extension-data',
+'image-library-alist', 'inhibit-first-line-modes-regexps',
+'inhibit-first-line-modes-suffixes', 'intdos',
+'mail-complete-function', 'mail-completion-at-point-function',
+'mail-mailer-swallows-blank-line', 'mail-sent-via', 'make-register',
+'makefile-complete', 'menu-bar-kill-ring-save',
+'meta-complete-symbol', 'meta-mode-map',
+'minibuffer-completing-symbol',
+'minibuffer-local-filename-must-match-map', 'mode25', 'mode4350',
+'msb-after-load-hooks', 'nnimap-split-rule', 'ns-alternatives-map',
+'ns-store-cut-buffer-internal', 'package-menu-view-commentary',
+'pascal-last-completions', 'pascal-show-completions',
+'pascal-toggle-completions', 'prolog-char-quote-workaround',
+'read-filename-at-point', 'reftex-index-map',
+'reftex-index-phrases-map', 'reftex-select-bib-map',
+'reftex-select-label-map', 'reftex-toc-map', 'register-name-alist',
+'register-value', 'report-emacs-bug-pretest-address',
+'rmail-default-dont-reply-to-names', 'rmail-dont-reply-to',
+'rmail-dont-reply-to-names', 'rst-block-face', 'rst-comment-face',
+'rst-definition-face', 'rst-directive-face', 'rst-emphasis1-face',
+'rst-emphasis2-face', 'rst-external-face', 'rst-literal-face',
+'rst-reference-face', 'semantic-grammar-map',
+'semantic-grammar-syntax-table', 'set-register-value',
+'speedbar-key-map', 'speedbar-syntax-table',
+'starttls-any-program-available', 'strokes-report-bug',
+'toggle-emacs-lock', 'tooltip-use-echo-area', 'turn-on-cwarn-mode',
+'turn-on-iimage-mode', 'vc-toggle-read-only', 'view-return-to-alist',
+'view-return-to-alist-update', 'w32-default-color-map' (function),
+'which-func-mode' (function), 'x-cut-buffer-or-selection-value'.
+
+---
** Some functions and variables obsolete since Emacs 23 have been removed:
'find-emacs-lisp-shadows', 'newsticker-cache-filename',
'unify-8859-on-decoding-mode', 'unify-8859-on-encoding-mode',
'vc-arch-command'.
+++
+** New generic function 'function-doumentation'.
+Can dynamically generate a raw docstring depending on the type of
+a function.
+Used mainly for docstrings of OClosures.
+
++++
** Base64 encoding no longer tolerates latin-1 input.
The functions 'base64-encode-string', 'base64url-encode-string',
'base64-encode-region' and 'base64url-encode-region' no longer accept
@@ -898,16 +2340,292 @@ characters in the range U+0080..U+00FF as substitutes for single bytes
in the range 128..255, but signal an error for all multibyte characters.
The input must be encoded text.
++++
+** The 'clone-indirect-buffer-hook' is now run by 'make-indirect-buffer'.
+It was previously only run by 'clone-indirect-buffer' and
+'clone-indirect-buffer-other-window'. Since 'make-indirect-buffer' is
+called by both of these, the hook is now run by all 3 of these
+functions.
+
+---
+** '?\' at the end of a line now signals an error.
+Previously it produced a nonsense value, -1, that was never intended.
+
+** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed:
+abbrevlist.el, assoc.el, complete.el, cust-print.el,
+erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el,
+patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
+
* Lisp Changes in Emacs 29.1
+++
+** New arguments MESSAGE and TIMEOUT of 'set-transient-map'.
+MESSAGE specifies a message to display after activating the transient
+map, including a special formatting spec to list available keys.
+TIMEOUT is the idle time after which to deactivate the transient map.
+The default timeout value can be defined by the new variable
+'set-transient-map-timeout'.
+
++++
+** New function 'seq-split'.
+This returns a list of sub-sequences of the specified sequence.
+
++++
+** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
+These function now take an optional comparison predicate argument.
+
++++
+** 'read-multiple-choice' can now use long-form answers.
+
++++
+** 'M-c' in 'read-regexp' now toggles case folding.
+
++++
+** 'completing-read' now allows a function as its REQUIRE-MATCH argument.
+This function is called to see whether what the user has typed in is a
+match. This is also available from functions that call
+'completing-read', like 'read-file-name'.
+
++++
+** 'posn-col-row' can now give position data based on windows.
+Previously, it reported data only based on the frame.
+
++++
+** 'file-expand-wildcards' can now also take a regexp as PATTERN argument.
+
+---
+** vc-mtn (the backend for Monotone) has been made obsolete.
+
++++
+** 'gui-set-selection' can now specify different values for different data types.
+If DATA is a string, then its text properties are searched for values
+for each specific data type while the selection is being converted.
+
+---
+** New eldoc function: 'elisp-eldoc-var-docstring-with-value'.
+This function includes the current value of the variable in eldoc display
+and can be used as a more detailed alternative to 'elisp-eldoc-var-docstring'.
+
+** 'save-some-buffers' can now be extended to save other things.
+Traditionally, 'save-some-buffers' saved buffers, and also saved
+abbrevs. This has been generalized via the
+'save-some-buffers-functions', and packages can now register things to
+be saved.
+
+** Themes
+
+---
+*** New hooks 'enable-theme-functions' and 'disable-theme-functions'.
+These are run after enabling and disabling a theme, respectively.
+
+---
+*** Themes can now be made obsolete.
+Using 'make-obsolete' on a theme is now supported. This will make
+'load-theme' issue a warning when loading the theme.
+
++++
+** New hook 'display-monitors-changed-functions'.
+It is called whenever the configuration of different monitors on a
+display changes.
+
++++
+** 'prin1' and 'prin1-to-string' now take an optional OVERRIDES parameter.
+This parameter can be used to override values of print-related settings.
+
++++
+** New minor mode 'header-line-indent-mode'.
+This is meant to be used in modes that have a header line that should
+be kept aligned with the buffer contents when the user switches
+'display-line-numbers-mode' on or off.
+
++++
+** New minor mode 'lost-selection-mode'.
+This minor mode makes Emacs deactivate the mark in all buffers when
+the primary selection is obtained by another program.
+
++++
+** New predicate 'char-uppercase-p'.
+This returns non-nil if its argument its an uppercase character.
+
+** Byte compilation
+
+---
+*** Byte compilation will now warn about some quoting mistakes in doc strings.
+When writing code snippets that contains the ' character (APOSTROPHE),
+that quote character has to be escaped to avoid Emacs displaying it as
+’ (LEFT SINGLE QUOTATION MARK), which would make code examples like
+
+ (setq foo '(1 2 3))
+
+invalid. Emacs will now warn during byte compilation if it seems
+something like that, and also warn about when using RIGHT/LEFT SINGLE
+QUOTATION MARK directly. In both these cases, if these characters
+should really be present in the doc string, they should be quoted with
+\=.
+
+---
+*** Byte compilation will now warn about some malformed 'defcustom' types.
+It's very common to write 'defcustom' types on the form:
+
+ :type '(choice (const :tag "foo" 'bar))
+
+I.e., double-quoting the 'bar', which is almost never the correct
+value. The byte compiler will now issue a warning if it encounters
+these forms.
+
++++
+*** 'restore-buffer-modified-p' can now alter buffer auto-save state.
+With a FLAG value of 'autosaved', it will mark the buffer as having
+been auto-saved since the time of last modification.
+
+---
+*** New minor mode 'isearch-fold-quotes-mode'.
+This sets up 'search-default-mode' so that quote characters are
+char-folded into each other. It is used, by default, in "*Help*" and
+"*info*" buffers.
+
++++
+** New macro 'buffer-local-set-state'.
+This is a helper macro to be used by minor modes that wish to restore
+buffer-local variables back to their original states when the mode is
+switched off.
+
+---
+** New macro 'with-buffer-unmodified-if-unchanged'.
+If the buffer is marked as unmodified, and code does modifications
+that, in total, means that the buffer is identical to the buffer
+before, mark the buffer as unmodified again.
+
+---
+** New function 'malloc-trim'.
+This function allows returning unused memory back to the operating
+system, and is mainly meant as a debugging tool. It is currently
+available only when Emacs was built with glibc as the C library.
+
+---
+** 'x-show-tip' no longer hard-codes a timeout default.
+The new 'x-show-tooltip-timeout' variable allows the user to alter
+this for packages that don't use 'tooltip-show', but instead call the
+lower level function directly.
+
+---
+** New function 'current-cpu-time'.
+It gives access to the CPU time used by the Emacs process, for
+example for benchmarking purposes.
+
+---
+** New function 'string-edit'.
+This is meant to be used when the user has to edit a (potentially)
+long string. It pops you to a new buffer where you can edit the
+string, and a callback is called when the user types 'C-c C-c'.
+
++++
+** New function 'read-string-from-buffer'.
+This is a modal version of 'string-edit', and can be used as an
+alternative to 'read-string'.
+
++++
+** The return value of 'clear-message-function' is not ignored anymore.
+If the function returns 'dont-clear-message', then the message is not
+cleared, with the assumption that the function cleared it itself.
+
++++
+** The local variable section now supports defining fallback modes.
+This was previously only available when using a property line (i.e.,
+putting the modes on the first line of a file).
+
++++
+** New function 'flush-standard-output'.
+This enables you to display incomplete lines from batch-based Emacs
+scripts.
+
++++
+** New convenience function 'buttonize-region'.
+This works like 'buttonize', but for a region instead of a string.
+
++++
+** 'macroexp-let2*' can omit TEST arg and use single-var bindings.
+
++++
+** New macro-writing macros, 'cl-with-gensyms' and 'cl-once-only'.
+See the "(cl) Macro-Writing Macros" manual section for descriptions.
+
++++
+** New variable 'last-event-device' and new function 'device-class'.
+On X Windows, 'last-event-device' specifies the input extension device
+from which the last input event originated, and 'device-class' can be
+used to determine the type of an input device.
+
++++
+** 'track-mouse' can be a new value 'drag-source'.
+This means the same as 'dropping', but modifies the mouse position
+list in reported motion events if there is no frame underneath the
+mouse pointer.
+
++++
+** New functions for dragging items from Emacs to other programs.
+The new functions 'x-begin-drag', 'dnd-begin-file-drag',
+'dnd-begin-drag-files', and 'dnd-direct-save' allow dragging contents
+(such as files and text) from Emacs to other programs.
+
+---
+** New function 'ietf-drums-parse-date-string'.
+This function parses RFC5322 (and RFC822) date strings, and should be
+used instead of 'parse-time-string' when parsing data that's standards
+compliant.
+
++++
+** New macro 'setopt'.
+This is like 'setq', but is meant to be used for user options instead
+of plain variables, and
+uses 'custom-set'/'set-default' to set them.
+
++++
+** New utility predicate 'mode-line-window-selected-p'.
+This is meant to be used from ':eval' mode line constructs to create
+different mode line looks for selected and unselected windows.
+
++++
+** New variable 'messages-buffer-name'.
+This variable (defaulting to "*Messages*") allows packages to override
+where messages are logged.
+
++++
+** New function 'readablep'.
+This function says whether an object can be written out and then
+read back by the Emacs Lisp reader.
+
++++
+** New variable 'print-unreadable-function'.
+This variable allows changing how Emacs prints unreadable objects.
+
+---
+** The user option 'polling-period' now accepts floating point values.
+This means Emacs can now poll for input during Lisp execution more
+frequently than once in a second.
+
+---
+** New function 'bidi-string-strip-control-characters'.
+This utility function is meant for displaying strings when it's
+essential that there's no bidirectional context.
+
+---
+** The Gnus range functions have been moved to a new library, range.el.
+All the old names have been made obsolete.
+
++++
+** New function 'function-alias-p'.
+This predicate says whether an object is a function alias, and if it
+is, the alias chain is returned.
+
++++
** New variable 'lisp-directory' holds the directory of Emacs's own Lisp files.
+++
** New facility for handling session state: 'multisession-value'.
This can be used as a convenient way to store (simple) application
-state, and 'M-x list-multisession-values' allows users to list
+state, and the command 'list-multisession-values' allows users to list
(and edit) this data.
+++
@@ -925,23 +2643,83 @@ property.
This allows setting a minimum display width for a region of text.
+++
+** New 'cursor-face' text property.
+This uses 'cursor-face' instead of the default face when cursor is on or
+near the character and 'cursor-face-highlight-mode' is enabled. The
+user option 'cursor-face-highlight-nonselected-window' is similar to
+'highlight-nonselected-windows', but for this property.
+
++++
** New event type 'touch-end'.
This event is sent whenever the user's finger moves off the mouse
wheel on some mice, or when the user's finger moves off the touchpad.
+++
** New event type 'pinch'.
-This event is sent when a user peforms a pinch gesture on a touchpad,
+This event is sent when a user performs a pinch gesture on a touchpad,
which is comprised of placing two fingers on the touchpad and moving
them towards or away from each other.
++++
+** New hook 'x-pre-popup-menu-hook'.
+This hook is run before 'x-popup-menu' is about to display a
+deck-of-cards menu on screen.
+
+** New function 'buffer-match-p'.
+Check if a buffer satisfies some condition. Some examples for
+conditions can be regular expressions that match a buffer name, a
+cons-cell like '(major-mode . shell-mode)' that matches any buffer
+where 'major-mode' is 'shell-mode' or a combined with a condition like
+'(and "\\`\\*.+\\*\\'" (major-mode . special-mode))'.
+
+** New function 'match-buffers'.
+Use 'buffer-match-p' to gather a list of buffers that match a
+condition.
+
+---
+** New optional arguments 'text-face' and 'default-face' for 'tooltip-show'.
+They allow changing the faces used for the tooltip text and frame
+colors of the resulting tooltip frame from the default 'tooltip' face.
+
+** Text security and suspiciousness
+
++++
+*** New library textsec.el.
+This library contains a number of checks for whether a string is
+"suspicious". This usually means that the string contains characters
+that have glyphs that can be confused with other, more commonly used
+glyphs, or contain bidirectional (or other) formatting characters that
+may be used to confuse a user.
+
++++
+*** New user option 'textsec-check'.
+If non-nil (which is the default), Emacs packages that are vulnerable
+to attackers trying to confuse the users will use the textsec library
+to mark suspicious text. For instance shr/eww will mark suspicious
+URLs and links, Gnus will mark suspicious From addresses, and
+Message mode will query the user if the user is sending mail to a
+suspicious address. If this variable is nil, these checks aren't
+performed.
+
++++
+*** New function 'textsec-suspicious-p'.
+This is the main function Emacs applications should be using to check
+whether a string is suspicious. It heeds the 'textsec-check' user
+option.
+
** Keymaps and key definitions
+++
-*** New functions for defining and manipulating keystrokes have been added.
-These all take just the syntax defined by 'key-valid-p'. None of the
-older functions have been depreciated or altered, but are deemphasised
-in the documentation.
+*** 'where-is-internal' can now filter events marked as non key events.
+If a command maps to a key binding like [some-event], and 'some-event'
+has a symbol plist containing a non-nil 'non-key-event' property, then
+that binding is ignored by 'where-is-internal'.
+
++++
+*** New functions for defining and manipulating keystrokes.
+These all take the syntax defined by 'key-valid-p'. None of the older
+functions have been deprecated or altered, but they are now
+de-emphasized in the documentation.
+++
*** Use 'keymap-set' instead of 'define-key'.
@@ -1030,6 +2808,19 @@ This command lets you examine all data in the current selection and
the clipboard, and insert it into the buffer.
+++
+** New variable 'yank-transform-functions'.
+This variable allows the user to alter the string to be inserted.
+
+---
+** New command 'yank-in-context'.
+This command tries to preserve string/comment syntax when yanking.
+
+---
+** New function 'minibuffer-lazy-highlight-setup'.
+This function allows setting up the minibuffer so that lazy
+highlighting of its content is applied in the original window.
+
++++
** New text property 'inhibit-isearch'.
If set, 'isearch' will skip these areas, which can be useful (for
instance) when covering huge amounts of data (that has no meaningful
@@ -1041,6 +2832,26 @@ It marks the image with the 'inhibit-isearch' text property, which
inhibits 'isearch' matching the STRING parameter.
---
+** New variable 'replace-regexp-function'.
+Function to call to convert the entered FROM string to an Emacs
+regexp in 'query-replace' and similar commands. It can be used to
+implement a different regexp syntax for search/replace.
+
+---
+** New variables to customize defaults of FROM for 'query-replace*' commands.
+The new variable 'query-replace-read-from-default' can be set to a
+function that returns the default value of FROM when 'query-replace'
+prompts for a string to be replaced. An example of such a function is
+'find-tag-default'.
+
+The new variable 'query-replace-read-from-regexp-default' can be set
+to a function (such as 'find-tag-default-as-regexp') that returns the
+default value of FROM when 'query-replace-regexp' prompts for a regexp
+whose matches are to be replaced. If these variables are nil (which
+is the default), 'query-replace' and 'query-replace-regexp' take the
+default value from the previous FROM-TO pair.
+
+---
** New user option 'pp-use-max-width'.
If non-nil, 'pp' will attempt to limit the line length when formatting
long lists and vectors.
@@ -1065,18 +2876,30 @@ This can be used to check whether a specific font has a glyph for a
character.
+++
-** 'window-text-pixel-size' now accepts a new argument 'ignore-line-at-end'.
+** 'window-text-pixel-size' now accepts a new argument IGNORE-LINE-AT-END.
This controls whether or not the last screen line of the text being
measured will be counted for the purpose of calculating the text
dimensions.
+++
-** 'window-text-pixel-size' understands a new meaning of 'from'.
-Specifying a cons as the from argument allows to start measuring text
+** 'window-text-pixel-size' understands a new meaning of FROM.
+Specifying a cons as the FROM argument allows to start measuring text
from a specified amount of pixels above or below a position.
++++
+** 'window-body-width' and 'window-body-height' can use remapped faces.
+Specifying 'remap' as the PIXELWISE argument now checks if the default
+face was remapped, and if so, uses the remapped face to determine the
+character width/height.
+
++++
+** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P.
+This means the vscroll will not be reset when set on a window that is
+"frozen" due to a mini-window being resized.
+
** XDG support
+---
*** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable.
This new location, introduced in the XDG Base Directory Specification
version 0.8 (8th May 2021), "contains state data that should persist
@@ -1104,6 +2927,12 @@ This holds the value of the previous call to 'set-locale-environment'.
This macro can be used to change the locale temporarily while
executing code.
+** table.el
+
+---
+*** New user option 'table-latex-environment'.
+This allows switching between "table" and "tabular".
+
** Tabulated List Mode
+++
@@ -1113,7 +2942,7 @@ descriptor, which means to insert an image in that column instead of
text. See the documentation string of that variable for details.
+++
-** :keys in 'menu-item' can now be a function.
+** ':keys' in 'menu-item' can now be a function.
If so, it is called whenever the menu is computed, and can be used to
calculate the keys dynamically.
@@ -1131,11 +2960,6 @@ local variables.
** Third 'mapconcat' argument SEPARATOR is now optional.
An explicit nil always meant the empty string, now it can be left out.
----
-** Themes can now be made obsolete.
-Using 'make-obsolete' on a theme is now supported. This will make
-'load-theme' issue a warning when loading the theme.
-
+++
** New function 'define-keymap'.
This function allows defining a number of keystrokes with one form.
@@ -1207,18 +3031,17 @@ for performing searches on WebKit xwidgets.
+++
*** New function 'xwidget-webkit-back-forward-list'.
-This function is used to obtain the history of page-loads in a given
-WebKit xwidget.
+This function returns the history of page-loads in a WebKit xwidget.
+++
*** New function 'xwidget-webkit-estimated-load-progress'.
-This function is used to obtain the estimated progress of page loading
-in a given WebKit xwidget.
+This function returns the estimated progress of page loading in a
+WebKit xwidget.
+++
*** New function 'xwidget-webkit-stop-loading'.
-This function is used to terminate all data transfer during page loads
-in a given WebKit xwidget.
+This function terminates all data transfer during page loads in a
+WebKit xwidget.
+++
*** 'load-changed' xwidget events are now more detailed.
@@ -1239,21 +3062,32 @@ that should be displayed, and the xwidget that asked to display it.
This function is used to control where and if an xwidget stores
cookies set by web pages on disk.
+---
** New variable 'help-buffer-under-preparation'.
This variable is bound to t during the preparation of a "*Help*" buffer.
+++
-** Timestamps like (1 . 1000) now work without warnings being generated.
-For example, (time-add nil '(1 . 1000)) no longer warns that the
-(1 . 1000) acts like (1000 . 1000000). This warning, which was a
+** Timestamps like '(1 . 1000)' now work without warnings being generated.
+For example, '(time-add nil '(1 . 1000))' no longer warns that the
+'(1 . 1000)' acts like '(1000 . 1000000)'. This warning, which was a
temporary transition aid for Emacs 27, has served its purpose.
+++
+** 'encode-time' now also accepts a 6-element list with just time and date.
+'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR))' is now short for
+'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR nil -1 nil))'.
+
++++
** 'date-to-time' now assumes earliest values if its argument lacks
month, day, or time. For example, (date-to-time "2021-12-04") now
assumes a time of 00:00 instead of signaling an error.
+++
+** 'format-seconds' now allows suppressing zero-value trailing elements.
+The new "%x" non-printing control character will suppress zero-value
+elements that appear after "%x".
+
++++
** New events for taking advantage of touchscreen devices.
The events 'touchscreen-begin, 'touchscreen-update', and
'touchscreen-end' have been added to take better advantage of
@@ -1265,11 +3099,79 @@ This is a subcategory of 'file-error', and is signaled when some file
operation fails because the OS doesn't allow Emacs to access a file or
a directory.
++++
+** The ':underline' face attribute now accepts a new property.
+The property ':position' now specifies the position of the underline
+when used as part of a property list specification for the
+':underline' attribute.
+
++++
+** 'defalias' records a more precise history of definitions.
+This is recorded in the 'function-history' symbol property.
+
+---
+** New hook 'save-place-after-find-file-hook'.
+This is called at the end of 'save-place-find-file-hook'.
+
+---
+** 'indian-tml-base-table' no longer translates digits.
+Use 'indian-tml-base-digits-table' if you want digits translation.
+
+---
+** 'indian-tml-itrans-v5-hash' no longer translates digits.
+Use 'indian-tml-itrans-digits-v5-hash' if you want digits
+translation.
+
++++
+** 'shell-quote-argument' has a new optional parameter POSIX.
+This is useful when quoting shell arguments for a remote shell
+invocation. Such shells are POSIX conformant by default.
+
++++
+** 'signal-process' now consults the list 'signal-process-functions'.
+This is to determine which function has to be called in order to
+deliver the signal. This allows Tramp to send the signal to remote
+asynchronous processes. The hitherto existing implementation has been
+moved to 'internal-default-signal-process'.
+
++++
+** 'list-system-processes' now returns remote process IDs.
+This happens only when the current buffer's 'default-directory' is
+remote. In order to preserve the old behavior, apply
+
+ (let ((default-directory temporary-file-directory))
+ (list-system-processes))
+
++++
+** 'process-attributes' expects a remote process ID now.
+When current buffer's 'default-directory' is remote, the PID argument
+of 'process-attributes' is regarded as a remote process ID. In order
+to preserve the old behavior, apply
+
+ (let ((default-directory temporary-file-directory))
+ (process-attributes pid))
+
+
* Changes in Emacs 29.1 on Non-Free Operating Systems
** MS-Windows
+---
+*** Emacs now supports double-buffering on MS-Windows to reduce display flicker.
+(This was supported on Free systems since Emacs 26.1.)
+
+To disable double-buffering (e.g., if it causes display problems), set
+the frame parameter 'inhibit-double-buffering' to a non-nil value.
+You can do that either by adding
+
+ '(inhibit-double-buffering . t)
+
+to 'default-frame-alist', or by modifying the frame parameters of the
+selected frame by evaluating
+
+ (modify-frame-parameters nil '((inhibit-double-buffering . t)))
+
+++
*** Emacs now supports system dark mode.
On Windows 10 (version 1809 and higher) and Windows 11, Emacs will now
@@ -1277,6 +3179,29 @@ follow the system's dark mode: GUI frames use the appropriate light or
dark title bar and scroll bars, based on the user's Windows-wide color
settings.
+---
+*** Emacs now uses native image APIs to display some image formats.
+On Windows 2000 and later, Emacs now defaults to using the native
+image APIs for displaying the BMP, GIF, JPEG, PNG, and TIFF images.
+This means Emacs on MS-Windows needs no longer use external image
+support libraries to display those images. Other image types -- XPM,
+SVG, and WEBP -- still need support libraries for Emacs to be able to
+display them.
+
+The use of native image APIs is controlled by the variable
+'w32-use-native-image-API', whose value now defaults to t on systems
+where those APIs are available.
+
++++
+*** Emacs now supports display of BMP images using native image APIs.
+When 'w32-use-native-image-API' is non-nil, Emacs on MS-Windows now
+has built-in support for displaying BMP images.
+
+** Cygwin
+
+---
+*** 'process-attributes' is now implemented.
+
----------------------------------------------------------------------
This file is part of GNU Emacs.
@@ -1298,5 +3223,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
Local variables:
coding: utf-8
mode: outline
+mode: emacs-news
paragraph-separate: "[ ]*$"
end:
diff --git a/etc/NEWS.28 b/etc/NEWS.28
index 1e882883b5a..7409e428de9 100644
--- a/etc/NEWS.28
+++ b/etc/NEWS.28
@@ -15,11 +15,67 @@ in older Emacs versions.
You can narrow news to a specific version by calling 'view-emacs-news'
with a prefix argument or by typing 'C-u C-h C-n'.
-Temporary note:
-+++ indicates that all relevant manuals in doc/ have been updated.
---- means no change in the manuals is needed.
-When you add a new item, use the appropriate mark if you are sure it
-applies, and please also update docstrings as needed.
+
+* Installation Changes in Emacs 28.2
+
+** To install the Emacs binary in a non-standard directory, use '--bindir='.
+If you install Emacs in a way that places the Emacs executable file in
+a directory other than "${prefix}/bin", you will now need to specify
+that at configure time, if you build Emacs with native-compilation
+support. To this end, add the '--bindir=DIRECTORY' switch to the
+command line of the 'configure' script, where DIRECTORY is the
+directory in which you will install the executable file "emacs". This
+is required even if you place a symlink under "${prefix}/bin" that
+points to the real executable file in some other DIRECTORY.
+
+It is no longer enough to specify 'bindir=DIRECTORY' on the command
+line of the "make install" command.
+
+The reason for this new requirement is that Emacs needs to locate at
+startup the directory with its "*.eln" natively-compiled files for the
+preloaded Lisp packages, and the relative name of that directory needs
+therefore to be recorded in the executable as part of the build.
+
+
+* Startup Changes in Emacs 28.2
+
+
+* Changes in Emacs 28.2
+
+This is a bug-fix release with no new features.
+
+
+* Editing Changes in Emacs 28.2
+
+
+* Changes in Specialized Modes and Packages in Emacs 28.2
+
+** The command 'kdb-macro-redisplay' was renamed to 'kmacro-redisplay'.
+This is to fix an embarrassing typo in the original name.
+
+** 'desktop-save-mode' now saves the desktop in 'save-buffers-kill-emacs'.
+Previously, the desktop was saved in 'kill-emacs' via
+'kill-emacs-hook'. However, that violated the convention that
+functions in 'kill-emacs-hook' cannot interact with the user, and in
+particular didn't play well with ending daemon sessions of Emacs. So
+we moved the saving of the desktop to 'save-buffers-kill-emacs', via
+'kill-emacs-query-functions'. To make sure the desktop is saved,
+terminate Emacs with 'save-buffers-kill-emacs', not with 'kill-emacs'.
+
+(This change was done in Emacs 28.1, but we didn't announce it in NEWS
+back then.)
+
+
+* New Modes and Packages in Emacs 28.2
+
+
+* Incompatible Lisp Changes in Emacs 28.2
+
+
+* Lisp Changes in Emacs 28.2
+
+
+* Changes in Emacs 28.2 on Non-Free Operating Systems
* Installation Changes in Emacs 28.1
@@ -33,8 +89,8 @@ more details.
If you build Emacs with native compilation, but without zlib, be sure
to configure with the '--without-compress-install' option, so that the
-installed *.el files are not compressed; otherwise, you will not be
-able to use JIT native compilation of the installed *.el files.
+installed "*.el" files are not compressed; otherwise, you will not be
+able to use JIT native compilation of the installed "*.el" files.
Note that JIT native compilation is done in a fresh session of Emacs
that is run in a subprocess, so it can legitimately report some
@@ -43,11 +99,10 @@ recommend examining any such warnings before you decide they are
false.
** The Cairo graphics library is now used by default if present.
-'--with-cairo' is now the default, if the appropriate development files
-are found by 'configure'. Note that building with Cairo means using
-Pango instead of libXFT for font support. Since Pango 1.44 has
-removed support for bitmapped fonts, this may require you to adjust
-your font settings.
+'--with-cairo' is now the default, if the appropriate development
+files are found by 'configure'. Building with Cairo is known to cause
+some problems with bitmap fonts. This may require you to adjust your
+font settings, or to build with Xft support instead.
Note also that 'FontBackend' settings in ".Xdefaults" or
".Xresources", or 'font-backend' frame parameter settings in your init
@@ -59,30 +114,25 @@ still be available when HarfBuzz is supported, but will not be used by
default. We strongly recommend building with HarfBuzz support. 'x' is
still a valid backend.
----
** 'configure' now warns about building with libXft support.
libXft is unmaintained, and causes a number of problems with modern
fonts including but not limited to crashes; support for it may be
removed in a future version of Emacs. Please consider using
Cairo + HarfBuzz instead.
----
** 'configure' now warns about not using HarfBuzz if using Cairo.
We want to encourage people to use the most modern font features
available, and this is the Cairo graphics library + HarfBuzz for font
shaping, so 'configure' now recommends that combination.
----
** Building without double buffering support.
'configure --with-xdbe=no' can now be used to disable double buffering
at build time.
----
** The configure option '--without-makeinfo' has been removed.
This was only ever relevant when building from a repository checkout.
This now requires makeinfo, which is part of the texinfo package.
----
** New configure option '--disable-year2038'.
This causes Emacs to use only 32-bit time_t on platforms that have
both 32- and 64-bit time_t. This may help when linking Emacs with a
@@ -91,16 +141,13 @@ currently affects only 32-bit ARM and x86 running GNU/Linux with glibc
2.34 and later. Emacs now defaults to 64-bit time_t on these
platforms.
----
** Support for building with '-fcheck-pointer-bounds' has been removed.
GCC has withdrawn the '-fcheck-pointer-bounds' option and support for
its implementation has been removed from the Linux kernel.
----
** The ftx font backend driver has been removed.
It was declared obsolete in Emacs 27.1.
----
** Emacs no longer supports old OpenBSD systems.
OpenBSD 5.3 and older releases are no longer supported, as they lack
proper pty support that Emacs needs.
@@ -108,13 +155,11 @@ proper pty support that Emacs needs.
* Startup Changes in Emacs 28.1
----
** In GTK builds, Emacs now supports startup notification.
This means that Emacs won't steal keyboard focus upon startup
(when started via the Desktop) if the user is typing into another
application.
----
** Errors in 'kill-emacs-hook' no longer prevent Emacs from shutting down.
If a function in that hook signals an error in an interactive Emacs,
the user will be prompted on whether to continue. If the user doesn't
@@ -137,7 +182,6 @@ lacks the terminfo database, you can instruct Emacs to support 24-bit
true color by setting 'COLORTERM=truecolor' in the environment. This is
useful on systems such as FreeBSD which ships only with "etc/termcap".
----
** File names given on the command line are now be pushed onto history.
The file names will be pushed onto 'file-name-history', like the names
of files visited via 'C-x C-f' and other commands.
@@ -145,10 +189,8 @@ of files visited via 'C-x C-f' and other commands.
* Changes in Emacs 28.1
----
** Emacs now supports Unicode Standard version 14.0.
-+++
** Improved support for Emoji.
On capable systems, Emacs now correctly displays Emoji and Emoji
sequences by default, provided that a suitable font is available to
@@ -172,20 +214,17 @@ the above example. (Previously, the Emoji characters were assigned to
the 'symbol' script, together with other symbol and punctuation
characters.)
-+++
** 'glyphless-char-display-control' now applies to Variation Selectors.
VS-1 through VS-16 are now displayed as 'thin-space' by default when
not composed with previous characters (typically, as part of Emoji
sequences).
-+++
** New command 'execute-extended-command-for-buffer'.
This new command, bound to 'M-S-x', works like
'execute-extended-command', but limits the set of commands to the
commands that have been determined to be particularly useful with the
current mode.
-+++
** New user option 'read-extended-command-predicate'.
This user option controls how 'M-x' performs completion of commands when
you type 'TAB'. By default, any command that matches what you have
@@ -194,36 +233,30 @@ option to exclude commands that are not applicable to the current
buffer's major and minor modes, and respect the command's completion
predicate (if any).
-+++
** Completion on 'M-x' shows key bindings for commands.
When 'suggest-key-bindings' is non-nil (as it is by default), the
completion list popped up by 'M-x' shows the key bindings for all the
commands shown in the list of candidate completions that have a key
binding.
-+++
** New user option 'completions-detailed'.
When non-nil, some commands like 'describe-symbol' show more detailed
completions with more information in completion prefix and suffix.
The default is nil.
----
** 'C-s' in 'M-x' now once again searches over completions.
In Emacs 23, typing 'M-x' ('read-extended-command') and then 'C-s' (to
do an interactive search) would search over possible completions.
This was lost in Emacs 24, but is now back again.
-+++
** User option 'completions-format' supports a new value 'one-column'.
-+++
** New system for displaying documentation for groups of functions.
This can either be used by saying 'M-x shortdoc-display-group' and
choosing a group, or clicking a button in the "*Help*" buffers when
looking at the doc string of a function that belongs to one of these
groups.
-+++
** New minor mode 'context-menu-mode' for context menus popped by 'mouse-3'.
When this mode is enabled, clicking 'down-mouse-3' (usually, the
right mouse button) anywhere in the buffer pops up a menu whose
@@ -233,7 +266,6 @@ by customizing the user option 'context-menu-functions'. You can also
invoke the context menu by pressing 'S-<F10>' or, on macOS, by
clicking 'C-down-mouse-1'.
-+++
** A new keymap for buffer actions has been added.
The 'C-x x' keymap now holds keystrokes for various buffer-oriented
commands. The new keystrokes are 'C-x x g' ('revert-buffer-quick'),
@@ -241,34 +273,29 @@ commands. The new keystrokes are 'C-x x g' ('revert-buffer-quick'),
('clone-buffer'), 'C-x x i' ('insert-buffer'), 'C-x x t'
('toggle-truncate-lines') and 'C-x x f' ('font-lock-update').
-+++
** Modifiers now go outside angle brackets in pretty-printed key bindings.
For example, 'RET' with Control and Meta modifiers is now shown as
'C-M-<return>' instead of '<C-M-return>'. Either variant can be used
as input; functions such as 'kbd' and 'read-kbd-macro' accept both
styles as equivalent (they have done so for a long time).
----
** 'eval-expression' no longer signals an error on incomplete expressions.
Previously, typing 'M-: ( RET' would result in Emacs saying "End of
file during parsing" and dropping out of the minibuffer. The user
would have to type 'M-: M-p' to edit and redo the expression. Now
Emacs will echo the message and allow the user to continue editing.
-+++
** 'eval-last-sexp' now handles 'defvar'/'defcustom'/'defface' specially.
This command would previously not redefine values defined by these
forms, but this command has now been changed to work more like
'eval-defun', and reset the values as specified.
----
** New user option 'use-short-answers'.
When non-nil, the function 'y-or-n-p' is used instead of
'yes-or-no-p'. This eliminates the need to define an alias that maps
one to another in the init file. The same user option also controls
whether the function 'read-answer' accepts short answers.
-+++
** New user option 'kill-buffer-delete-auto-save-files'.
If non-nil, killing a buffer that has an auto-save file will prompt
the user for whether that auto-save file should be deleted. (Note
@@ -278,37 +305,31 @@ unsaved changes, but this has apparently not worked for several
decades, so the documented semantics of this variable has been changed
to match the behavior.)
-+++
** New user option 'next-error-message-highlight'.
In addition to a fringe arrow, 'next-error' error may now optionally
highlight the current error message in the 'next-error' buffer.
This user option can be also customized to keep highlighting on all
visited errors, so you can have an overview what errors were already visited.
----
** New choice 'next-error-quit-window' for 'next-error-found-function'.
When 'next-error-found-function' is customized to 'next-error-quit-window',
then typing the numeric prefix argument 0 before the command 'next-error'
will quit the source window after visiting the next occurrence.
-+++
** New user option 'file-preserve-symlinks-on-save'.
This controls what Emacs does when saving buffers that visit files via
symbolic links, and 'file-precious-flag' is non-nil.
-+++
** New user option 'copy-directory-create-symlink'.
If non-nil, will make 'copy-directory' (when used on a symbolic
link) copy the link instead of following the link. The default is
nil, so the default behavior is unchanged.
-+++
** New user option 'ignored-local-variable-values'.
This is the opposite of 'safe-local-variable-values' -- it's an alist
of variable-value pairs that are to be ignored when reading a
local-variables section of a file.
----
** Specific warnings can now be disabled from the warning buffer.
When a warning is displayed to the user, the resulting buffer now has
buttons which allow making permanent changes to the treatment of that
@@ -316,21 +337,17 @@ warning. Automatic showing of the warning can be disabled (although
it is still logged to the "*Messages*" buffer), or the warning can be
disabled entirely.
-+++
** ".dir-locals.el" now supports setting 'auto-mode-alist'.
The new 'auto-mode-alist' specification in ".dir-locals.el" files can
now be used to override the global 'auto-mode-alist' in the current
directory tree.
----
** User option 'uniquify-buffer-name-style' can now be a function.
This user option can be one of the predefined styles or a function to
personalize the uniquified buffer name.
----
** 'remove-hook' is now an interactive command.
----
** 'expand-file-name' now checks for null bytes in filenames.
The function will now check for null bytes in both NAME and
DEFAULT-DIRECTORY arguments, as well as in the 'default-directory'
@@ -340,22 +357,18 @@ This means that practically all file-related operations will now check
file names for null bytes, thus avoiding subtle bugs with silently
using only the part of file name up to the first null byte.
----
** Frames
-+++
*** The key prefix 'C-x 5 5' displays next command buffer in a new frame.
It's bound to the command 'other-frame-prefix' that requests the buffer
of the next command to be displayed in a new frame.
-+++
*** New command 'clone-frame' (bound to 'C-x 5 c').
This is like 'C-x 5 2', but uses the window configuration and frame
parameters of the current frame instead of 'default-frame-alist'.
When called interactively with a prefix arg, the window configuration
is not cloned.
----
*** Default values of 'frame-title-format' and 'icon-title-format' have changed.
These variables are used to display the title bar of visible frames
and the title bar of an iconified frame. They now show the name of
@@ -366,68 +379,56 @@ your init file:
(setq frame-title-format '(multiple-frames "%b"
("" invocation-name "@" system-name)))
-+++
*** New frame parameter 'drag-with-tab-line'.
This parameter, similar to 'drag-with-header-line', allows moving frames
by dragging the tab lines of their topmost windows with the mouse.
-+++
*** New optional behavior of 'delete-other-frames'.
When invoked with a prefix argument, 'delete-other-frames' now
iconifies frames, rather than deleting them.
----
*** Commands 'set-frame-width' and 'set-frame-height' now prompt for values.
These commands now prompt for the value via the minibuffer, instead of
requiring the user to specify the value via the prefix argument.
** Windows
-+++
*** The key prefix 'C-x 4 1' displays next command buffer in the same window.
It's bound to the command 'same-window-prefix' that requests the buffer
of the next command to be displayed in the same window.
-+++
*** The key prefix 'C-x 4 4' displays next command buffer in a new window.
It's bound to the command 'other-window-prefix' that requests the buffer
of the next command to be displayed in a new window.
-+++
*** New command 'recenter-other-window', bound to 'S-M-C-l'.
Like 'recenter-top-bottom', but acting on the other window.
-+++
*** New user option 'delete-window-choose-selected'.
This allows specifying how Emacs chooses which window will be the
frame's selected window after the currently selected window is
deleted.
-+++
*** New argument NO-OTHER for some window functions.
'get-lru-window', 'get-mru-window' and 'get-largest-window' now accept a
new optional argument NO-OTHER which, if non-nil, avoids returning a
window whose 'no-other-window' parameter is non-nil.
-+++
*** New 'display-buffer' function 'display-buffer-use-least-recent-window'.
This is like 'display-buffer-use-some-window', but won't reuse the
current window, and when called repeatedly will try not to reuse a
previously selected window.
-+++
*** New function 'window-bump-use-time'.
This updates the use time of a window.
** Minibuffer
-+++
*** Minibuffer scrolling is now conservative by default.
This is controlled by the new variable 'scroll-minibuffer-conservatively'.
It is t by default; setting it to nil will cause scrolling in the
minibuffer obey the value of 'scroll-conservatively'.
-+++
*** Improved handling of minibuffers on switching frames.
By default, when you switch to another frame, an active minibuffer now
moves to the newly selected frame. Nevertheless, the effect of what
@@ -440,14 +441,12 @@ behavior, which mixed these two, can be approximated by customizing
'minibuffer-follows-selected-frame' to a value which is neither nil
nor t.
-+++
*** New user option 'read-minibuffer-restore-windows'.
When customized to nil, it uses 'minibuffer-restore-windows' in
'minibuffer-exit-hook' to remove only the window showing the
"*Completions*" buffer, but keeps all other windows created
while the minibuffer was active.
----
*** New variable 'redisplay-adhoc-scroll-in-resize-mini-windows'.
Customizing it to nil will disable the ad-hoc auto-scrolling of
minibuffer text shown in mini-windows when resizing those windows.
@@ -458,13 +457,11 @@ cases anyway.
** Mode Line
-+++
*** New user option 'mode-line-compact'.
If non-nil, repeating spaces are compressed into a single space. If
'long', this is only done when the mode line is longer than the
current window width (in columns).
-+++
*** New user options to control format of line/column numbers in the mode line.
'mode-line-position-line-format' is the line number format (when
'line-number-mode' is on), 'mode-line-position-column-format' is
@@ -474,16 +471,13 @@ both modes are on).
** Tab Bars and Tab Lines
-+++
*** The prefix key 'C-x t t' can be used to display a buffer in a new tab.
Typing 'C-x t t' before a command will cause the buffer shown by that
command to be displayed in a new tab. 'C-x t t' is bound to the
command 'other-tab-prefix'.
-+++
*** New command 'C-x t C-r' to open file read-only in the other tab.
-+++
*** The tab bar now supports more mouse commands.
Clicking 'mouse-2' closes the tab, 'mouse-3' displays the context menu
with items that operate on the clicked tab. Dragging the tab with
@@ -491,20 +485,17 @@ with items that operate on the clicked tab. Dragging the tab with
scrolling switches to the previous/next tab, and holding the Shift key
during scrolling moves the tab to the left/right.
-+++
*** Frame-specific appearance of the tab bar when 'tab-bar-show' is a number.
When 'tab-bar-show' is a number, the tab bar on different frames can
be shown or hidden independently, as determined by the number of tabs
on each frame compared to the numerical value of 'tab-bar-show'.
-+++
*** New command 'toggle-frame-tab-bar'.
It can be used to enable/disable the tab bar on the currently selected
frame regardless of the values of 'tab-bar-mode' and 'tab-bar-show'.
This allows enabling/disabling the tab bar independently on different
frames.
-+++
*** New user option 'tab-bar-format' defines a list of tab bar items.
When it contains 'tab-bar-format-global' (possibly appended after
'tab-bar-format-align-right'), then after enabling 'display-time-mode'
@@ -513,7 +504,6 @@ aligned to the right on the tab bar instead of on the mode line.
When 'tab-bar-format-tabs' is replaced with 'tab-bar-format-tabs-groups',
the tab bar displays tab groups.
-+++
*** New optional key binding for 'tab-last'.
If you customize the user option 'tab-bar-select-tab-modifiers' to
allow selecting tabs using their index numbers, the '<MODIFIER>-9' key
@@ -523,20 +513,16 @@ is any of the modifiers in the list that is the value of
which count from the last tab: 1 is the last tab, 2 the one before
that, etc.
----
*** New command 'tab-duplicate' bound to 'C-x t n'.
----
*** 'C-x t N' creates a new tab at the specified absolute position.
The position is provided as prefix arg, and specifies an index that
starts at 1. Negative values count from the end of the tab bar.
----
*** 'C-x t M' moves the current tab to the specified absolute position.
The position is provided as prefix arg, whose interpretation is as in
'C-x t N'.
----
*** 'C-x t G' assigns a tab to a named group of tabs.
'tab-close-group' closes all tabs that belong to the selected group.
The user option 'tab-bar-new-tab-group' defines the default group of
@@ -544,18 +530,14 @@ new tabs. After customizing 'tab-bar-tab-post-change-group-functions'
to 'tab-bar-move-tab-to-group', changing the group of a tab will also
move it closer to other tabs in the same group.
----
*** New user option 'tab-bar-tab-name-format-function'.
----
*** New user option 'tab-line-tab-name-format-function'.
----
*** The tabs in the tab line can now be scrolled using horizontal scroll.
If your mouse or trackpad supports it, you can now scroll tabs when
the mouse pointer is in the tab line by scrolling left or right.
----
*** New tab-line faces and user options.
The face 'tab-line-tab-special' is used for tabs whose buffers are
special, i.e. buffers that don't visit a file. The face
@@ -570,17 +552,14 @@ in other ways.
** Mouse wheel
----
*** Mouse wheel scrolling now defaults to one line at a time.
----
*** Mouse wheel scrolling now works on more parts of frame's display.
When using 'mouse-wheel-mode', the mouse wheel will now scroll also when
the mouse cursor is on the scroll bars, fringes, margins, header line,
and mode line. ('mouse-wheel-mode' is enabled by default on most graphical
displays.)
-+++
*** Mouse wheel scrolling with Shift modifier now scrolls horizontally.
This works in text buffers and over images. Typing a numeric prefix arg
(e.g. 'M-5') before starting horizontal scrolling changes its step value.
@@ -588,10 +567,8 @@ The value is saved in the user option 'mouse-wheel-scroll-amount-horizontal'.
** Customize
----
*** Customize buffers can now be reverted with 'C-x x g'.
----
*** Most customize commands now hide obsolete user options.
Obsolete user options are no longer shown in the listings produced by
the commands 'customize', 'customize-group', 'customize-apropos' and
@@ -600,35 +577,28 @@ the commands 'customize', 'customize-group', 'customize-apropos' and
To customize obsolete user options, use 'customize-option' or
'customize-saved'.
----
*** New SVG icons for checkboxes and arrows.
They will be used automatically instead of the old icons. If Emacs is
built without SVG support, the old icons will be used instead.
** Help
----
*** The order of things displayed in the "*Help*" buffer has been changed.
The indented "administrative" block (containing the "probably
introduced" and "other relevant functions" (and similar things) has
been moved to after the doc string.
-+++
*** New command 'describe-command' shows help for a command.
This can be used instead of 'describe-function' for interactive
commands and is globally bound to 'C-h x'.
-+++
*** New command 'describe-keymap' describes keybindings in a keymap.
----
*** New command 'apropos-function'.
This works like 'C-u M-x apropos-command' but is more discoverable.
----
*** New keybinding 'C-h R' prompts for an Info manual and displays it.
----
*** Keybindings in 'help-mode' use the new 'help-key-binding' face.
This face is added by 'substitute-command-keys' to any "\[command]"
substitution. The return value of that function should consequently
@@ -639,99 +609,82 @@ with the new optional argument NO-FACE non-nil.
Note that the new face will also be used in tooltips. When using the
GTK toolkit, this is only true if 'x-gtk-use-system-tooltips' is t.
-+++
*** New user option 'help-enable-symbol-autoload'.
If non-nil, displaying help for an autoloaded function whose
'autoload' form provides no documentation string will try to load the
file it's from. This will give more extensive help for such
functions.
----
*** The 'help-for-help' ('C-h C-h') screen has been redesigned.
-+++
-*** New convenience commands with short keys in the Help buffer.
+*** New convenience commands with short keys in the "*Help*" buffer.
New command 'help-view-source' ('s') will view the source file (if
any) of the current help topic. New command 'help-goto-info' ('i')
will look up the current symbol (if any) in Info. New command
'help-customize' ('c') will customize the user option or the face
-(if any) whose doc string is being shown in the Help buffer.
+(if any) whose doc string is being shown in the "*Help*" buffer.
----
*** New user option 'describe-bindings-outline'.
It enables outlines in the output buffer of 'describe-bindings' that
can provide a better overview in a long list of available bindings.
-+++
*** New commands to describe buttons and widgets.
-'widget-describe' (on a widget) will pop up a help buffer and give a
-description of the properties. Likewise 'button-describe' does the
-same for a button.
+'widget-describe' (on a widget) will pop up the "*Help*" buffer and
+give a description of the properties. Likewise 'button-describe' does
+the same for a button.
----
*** Improved "find definition" feature of "*Help*" buffers.
Now clicking on the link to find the definition of functions generated
by 'cl-defstruct', or variables generated by 'define-derived-mode',
for example, will go to the exact place where they are defined.
----
*** New commands 'apropos-next-symbol' and 'apropos-previous-symbol'.
These new navigation commands are bound to 'n' and 'p' in
'apropos-mode'.
----
*** The command 'view-lossage' can now be invoked from the menu bar.
The menu bar "Help" menu now has a "Show Recent Inputs" item under the
"Describe" sub-menu.
-+++
*** New command 'lossage-size'.
It allows users to change the maximum number of keystrokes and
commands recorded for the purpose of 'view-lossage'.
----
*** Closing the "*Help*" buffer from the toolbar now buries the buffer.
In previous Emacs versions, the "*Help*" buffer was killed instead when
clicking the "X" icon in the tool bar.
----
*** 'g' ('revert-buffer') in 'help-mode' no longer requires confirmation.
** File Locks
-+++
*** New user option 'lock-file-name-transforms'.
This option allows controlling where lock files are written. It uses
the same syntax as 'auto-save-file-name-transforms'.
-+++
*** New user option 'remote-file-name-inhibit-locks'.
When non-nil, this option suppresses lock files for remote files.
Default is nil.
-+++
*** New minor mode 'lock-file-mode'.
This command, called interactively, toggles the local value of
'create-lockfiles' in the current buffer.
** Emacs Server
-+++
*** New user option 'server-client-instructions'.
When emacsclient connects, Emacs will (by default) output a message
about how to exit the client frame. If 'server-client-instructions'
is set to nil, this message is inhibited.
-+++
*** New command 'server-edit-abort'.
This command (not bound to any key by default) can be used to abort
an edit instead of marking it as "Done" (which the 'C-x #' command
does). The 'emacsclient' program exits with an abnormal status as
result of this command.
-+++
*** New desktop integration for connecting to the server.
-If your operating system’s desktop environment is
+If your operating system's desktop environment is
freedesktop.org-compatible (which is true of most GNU/Linux and other
recent Unix-like desktops), you may use the new "Emacs (Client)"
desktop menu entry to open files in an existing Emacs instance rather
@@ -740,25 +693,20 @@ running.
** Miscellaneous
-+++
*** New command 'font-lock-update', bound to 'C-x x f'.
This command updates the syntax highlighting in this buffer.
-+++
*** New command 'memory-report'.
This command opens a new buffer called "*Memory Report*" and gives a
summary of where Emacs is using memory currently.
-+++
*** New command 'submit-emacs-patch'.
This works like 'report-emacs-bug', but is more geared towards sending
patches to the Emacs issue tracker.
----
*** New face 'apropos-button'.
Applies to buttons that indicate a face.
-+++
*** New face 'font-lock-doc-markup-face'.
Intended for documentation mark-up syntax and tags inside text that
uses 'font-lock-doc-face', which it should appropriately stand out
@@ -767,41 +715,34 @@ documentation comments in program source code by language-specific
modes, for mark-up conventions like Haddock, Javadoc or Doxygen. By
default this face inherits from 'font-lock-constant-face'.
-+++
*** New face box style 'flat-button'.
This is a plain 2D button, but uses the background color instead of
the foreground color.
----
*** New faces 'shortdoc-heading' and 'shortdoc-section'.
Applied to shortdoc headings and sections.
----
*** New face 'separator-line'.
This is used by 'make-separator-line' (see below).
-+++
*** 'redisplay-skip-fontification-on-input' helps Emacs keep up with fast input.
This is another attempt to solve the problem of handling high key repeat rate
and other "slow scrolling" situations. It is hoped it behaves better
than 'fast-but-imprecise-scrolling' and 'jit-lock-defer-time'.
It is not enabled by default.
----
*** Obsolete aliases are no longer hidden from command completion.
Completion of command names now considers obsolete aliases as
candidates, if they were marked obsolete in the current major version
of Emacs. Invoking a command via an obsolete alias now mentions the
obsolescence fact and shows the new name of the command.
-+++
*** Support for '(box . SIZE)' 'cursor-type'.
By default, 'box' cursor always has a filled box shape. But if you
specify 'cursor-type' to be '(box . SIZE)', the cursor becomes a hollow
box if the point is on an image larger than SIZE pixels in any
dimension.
-+++
*** The user can now customize how "default" values are prompted for.
The new utility function 'format-prompt' has been added which uses the
new 'minibuffer-default-prompt-format' user option to format "default"
@@ -811,7 +752,6 @@ number [10]", or not have the default displayed at all, like "Enter a
number". (This only affects callers that were altered to use
'format-prompt'.)
----
*** New help window when Emacs prompts before opening a large file.
Commands like 'find-file' or 'visit-tags-table' ask to visit a file
normally or literally when the file is larger than a certain size (by
@@ -819,20 +759,17 @@ default, 9.5 MiB). Press '?' or 'C-h' in that prompt to read more
about the different options to visit a file, how you can disable the
prompt, and how you can tweak the file size threshold.
-+++
*** Emacs now defaults to UTF-8 instead of ISO-8859-1.
This is only for the default, where the user has set no 'LANG' (or
similar) variable or environment. This change should lead to no
user-visible changes for normal usage.
----
*** 'global-display-fill-column-indicator-mode' skips some buffers.
By default, turning on 'global-display-fill-column-indicator-mode'
doesn't turn on 'display-fill-column-indicator-mode' in special-mode
buffers. This can be controlled by customizing the user option
'global-display-fill-column-indicator-modes'.
-+++
*** 'nobreak-char-display' now also affects all non-ASCII space characters.
Previously, this was limited only to 'NO-BREAK SPACE' and hyphen
characters. Now it also covers the rest of the non-ASCII Unicode
@@ -841,7 +778,6 @@ non-ASCII characters are displayed as themselves when
'nobreak-char-display' is t, i.e. they are not replaced on display
with the ASCII space and hyphen characters.
----
*** New backward compatibility variable 'nobreak-char-ascii-display'.
This variable is nil by default, and non-ASCII space and hyphen
characters are displayed as themselves, even if 'nobreak-char-display'
@@ -855,7 +791,6 @@ t. You may need this on text-mode terminals that produce messed up
display when non-ASCII spaces and hyphens are written to the display.
(This variable is only effective when 'nobreak-char-display' is t.)
-+++
*** Improved support for terminal emulators that encode the Meta flag.
Some terminal emulators set the 8th bit of Meta characters, and then
encode the resulting character code as if it were non-ASCII character
@@ -866,7 +801,6 @@ Meta characters to Emacs, e.g., send "ESC x" when the user types
emulators by using the new input-meta-mode with the special value
'encoded' with these terminal emulators.
----
*** 'auto-composition-mode' can now be selectively disabled on some TTYs.
Some text-mode terminals produce display glitches trying to compose
characters. The 'auto-composition-mode' can now have a string value
@@ -875,14 +809,12 @@ function compares equal with that string, automatic composition will
be disabled in windows shown on that terminal. The Linux terminal
sets this up by default.
----
*** Support for the 'strike-through' face attribute on TTY frames.
If your terminal's termcap or terminfo database entry has the 'smxx'
capability defined, Emacs will now emit the prescribed escape
sequences necessary to render faces with the 'strike-through'
attribute on TTY frames.
----
*** TTY menu navigation is now supported in 'xterm-mouse-mode'.
TTY menus support mouse navigation and selection when 'xterm-mouse-mode'
is active. When run on a terminal, clicking on the menu bar with the
@@ -890,19 +822,15 @@ mouse now pops up a TTY menu by default instead of running the command
'tmm-menubar'. To restore the old behavior, set the user option
'tty-menu-open-use-tmm' to non-nil.
----
*** 'M-x report-emacs-bug' will no longer include "Recent messages" section.
These were taken from the "*Messages*" buffer, and may inadvertently
leak information from the reporting user.
----
*** 'C-u M-x dig' will now prompt for a query type to use.
----
*** Rudimentary support for the 'st' terminal emulator.
Emacs now supports 256 color display on the 'st' terminal emulator.
-+++
*** Update IRC-related references to point to Libera.Chat.
The Free Software Foundation and the GNU Project have moved their
official IRC channels from the Freenode network to Libera.Chat. For the
@@ -922,12 +850,10 @@ https://lists.gnu.org/archive/html/info-gnu-emacs/2021-06/msg00000.html
* Incompatible Editing Changes in Emacs 28.1
----
** 'toggle-truncate-lines' now disables 'visual-line-mode'.
This is for symmetry with 'visual-line-mode', which disables
'truncate-lines'.
----
** 'electric-indent-mode' now also indents inside strings and comments.
(This only happens when indentation function also supports this.)
@@ -936,7 +862,6 @@ To recover the previous behavior you can use:
(add-hook 'electric-indent-functions
(lambda (_) (if (nth 8 (syntax-ppss)) 'no-indent)))
----
** The 'M-o' ('facemenu-keymap') global binding has been removed.
To restore the old binding, say something like:
@@ -948,7 +873,6 @@ To restore the old binding, say something like:
The last two lines are not strictly necessary if you don't care about
having those two commands on the 'M-o' keymap; see the next section.
----
** The 'M-o M-s' and 'M-o M-S' global bindings have been removed.
Use 'M-x center-line' and 'M-x center-paragraph' instead. See the
previous section for how to get back the old bindings. Alternatively,
@@ -958,12 +882,10 @@ had before, you can add the following to your init file:
(define-key global-map "\M-o\M-s" 'center-line)
(define-key global-map "\M-o\M-S" 'center-paragraph)
----
** The 'M-o M-o' global binding has been removed.
Use 'M-x font-lock-fontify-block' instead, or the new 'C-x x f'
command, which updates the syntax highlighting in the current buffer.
----
** The escape sequence '\e[29~' in Xterm is now mapped to 'menu'.
Xterm sends this sequence for both 'F16' and 'Menu' keys
It used to be mapped to 'print' but we couldn't find a terminal
@@ -971,26 +893,21 @@ that uses this sequence for any kind of 'Print' key.
This makes the Menu key (see https://en.wikipedia.org/wiki/Menu_key)
work for 'context-menu-mode' in Xterm.
----
** New user option 'xterm-store-paste-on-kill-ring'.
If non-nil (the default), Emacs pushes pasted text onto the kill ring
(if using an xterm-like terminal that supports bracketed paste).
Setting this to nil inhibits that.
----
** 'vc-print-branch-log' shows the change log from its root directory.
It previously used to use the default directory.
----
** 'project-shell' and 'shell' now use 'pop-to-buffer-same-window'.
This is to keep the same behavior as Eshell.
----
** In 'nroff-mode', 'center-line' is no longer bound to a key.
-The original key binding was 'M-s', which interfered with I-search,
+The original key binding was 'M-s', which interfered with Isearch,
since the latter uses 'M-s' as a prefix key of the search prefix map.
----
** In 'f90-mode', the backslash character ('\') no longer escapes.
For about a decade, the backslash character has no longer had a
special escape syntax in Fortran F90. To get the old behavior back,
@@ -998,7 +915,6 @@ say something like:
(modify-syntax-entry ?\\ "\\" f90-mode-syntax-table)
-+++
** Setting 'fill-column' to nil is obsolete.
This undocumented use of 'fill-column' is now obsolete. To disable
auto filling, turn off 'auto-fill-mode' instead.
@@ -1013,7 +929,6 @@ file:
** Input methods
-+++
*** Emacs now supports "transient" input methods.
A transient input method is enabled for inserting a single character,
and is then automatically disabled. 'C-x \' temporarily enables the
@@ -1025,33 +940,27 @@ character '½', and disable the 'compose' input method afterwards.
You can use 'C-x \' in incremental search to insert a single character
to the search string.
----
*** New input method 'compose' based on X Multi_key sequences.
----
*** New input method 'iso-transl' with the same keys as 'C-x 8'.
After selecting it as a transient input method with 'C-u C-x \
iso-transl RET', it supports the same key sequences as 'C-x 8',
so e.g. like 'C-x 8 [' inserts a left single quotation mark,
'C-x \ [' does the same.
----
*** New user option 'read-char-by-name-sort'.
It defines the sorting order of characters for completion of 'C-x 8 RET TAB'
and can be customized to sort them by codepoints instead of character names.
Additionally, you can group characters by Unicode blocks after customizing
'completions-group' and 'completions-group-sort'.
----
*** Improved language transliteration in Malayalam input methods.
Added a new Mozhi scheme. The inapplicable ITRANS scheme is now
deprecated. Errors in the Inscript method were corrected.
----
*** New input method 'cham'.
There's also a Cham greeting in "etc/HELLO".
----
*** New input methods for Lakota language orthographies.
Two orthographies are represented here, the Suggested Lakota
Orthography and what is known as the White Hat Orthography. Input
@@ -1059,7 +968,6 @@ methods 'lakota-slo-prefix', 'lakota-slo-postfix', and
'lakota-white-hat-postfix' have been added. There is also a Lakota
greeting in "etc/HELLO".
-+++
** Standalone 'M-y' allows interactive selection from previous kills.
'M-y' can now be typed after a command that is not a yank command.
When invoked like that, it prompts in the minibuffer for one of the
@@ -1069,14 +977,12 @@ in Isearch can be invoked if you bind 'C-s M-y' to the command
'isearch-yank-pop'. When the user option 'yank-from-kill-ring-rotate'
is nil the kill ring is not rotated after 'yank-from-kill-ring'.
-+++
** New user option 'word-wrap-by-category'.
When word-wrap is enabled, and this option is non-nil, that allows
Emacs to break lines after more characters than just whitespace
characters. In particular, this significantly improves word-wrapping
for CJK text mixed with Latin text.
-+++
** New command 'undo-redo'.
It undoes previous undo commands, but doesn't record itself as an
undoable command. It is bound to 'C-?' and 'C-M-_', the first binding
@@ -1085,43 +991,35 @@ works well in graphical mode, and the second one is easy to hit on tty.
For full conventional undo/redo behavior, you can also customize the
user option 'undo-no-redo' to t.
-+++
** New commands 'copy-matching-lines' and 'kill-matching-lines'.
These commands are similar to the command 'flush-lines',
but add the matching lines to the kill ring as a single string,
including the newlines that separate the lines.
-+++
** New user option 'kill-transform-function'.
This can be used to transform (and suppress) strings from entering the
kill ring.
-+++
** 'save-interprogram-paste-before-kill' can now be a number.
In that case, it's interpreted as a limit on the size of the clipboard
data that will be saved to the 'kill-ring' prior to killing text: if
the size of the clipboard data is greater than or equal to the limit,
it will not be saved.
-+++
** New user option 'tab-first-completion'.
If 'tab-always-indent' is 'complete', this new user option can be used to
further tweak whether to complete or indent.
----
** 'indent-tabs-mode' is now a global minor mode instead of just a variable.
-+++
** New choice 'permanent' for 'shift-select-mode'.
When the mark was activated by shifted motion keys, non-shifted motion
keys don't deactivate the mark after customizing 'shift-select-mode'
to 'permanent'. Similarly, the active mark will not be deactivated by
typing shifted motion keys.
-+++
** The "Edit => Clear" menu item now obeys a rectangular region.
-+++
** New command 'revert-buffer-with-fine-grain'.
Revert a buffer trying to be as non-destructive as possible,
preserving markers, properties and overlays. The new variable
@@ -1129,18 +1027,15 @@ preserving markers, properties and overlays. The new variable
number of seconds that 'revert-buffer-with-fine-grain' should spend
trying to be non-destructive, with a default value of 2 seconds.
-+++
** New command 'revert-buffer-quick'.
This is bound to 'C-x x g' and is like 'revert-buffer', but prompts
less.
-+++
** New user option 'revert-buffer-quick-short-answers'.
This controls how the new 'revert-buffer-quick' ('C-x x g') command
prompts. A non-nil value will make it use 'y-or-n-p' rather than
'yes-or-no-p'. Defaults to nil.
-+++
** New user option 'query-about-changed-file'.
If non-nil (the default), Emacs prompts as before when re-visiting a
file that has changed externally after it was visited the first time.
@@ -1148,30 +1043,25 @@ If nil, Emacs does not prompt, but instead shows the buffer with its
contents before the change, and provides instructions how to revert
the buffer.
----
** New value 'save-some-buffers-root' of 'save-some-buffers-default-predicate'.
When using this predicate, only buffers under the current project root
will be considered when saving buffers with 'save-some-buffers'.
----
** New user option 'save-place-abbreviate-file-names'.
This can simplify sharing the 'save-place-file' file across
different hosts.
----
** New user options 'copy-region-blink-delay' and 'delete-pair-blink-delay'.
'copy-region-blink-delay' specifies a delay to indicate the region
copied by 'kill-ring-save'. 'delete-pair-blink-delay' specifies
a delay to show the paired character to delete.
----
** 'zap-up-to-char' now uses 'read-char-from-minibuffer'.
This allows navigating through the history of characters that have
been input. This is mostly useful for characters that have complex
input methods where inputting the character again may involve many
keystrokes.
-+++
** Input history for 'goto-line' can now be made local to every buffer.
In any event, line numbers used with 'goto-line' are kept in their own
history list. This should help make faster the process of finding
@@ -1179,7 +1069,6 @@ line numbers that were previously jumped to. By default, all buffers
share a single history list. To make every buffer have its own
history list, customize the user option 'goto-line-history-local'.
-+++
** New command 'goto-line-relative' for use in a narrowed buffer.
It moves point to the line relative to the accessible portion of the
narrowed buffer. 'M-g M-g' in Info is rebound to this command.
@@ -1187,20 +1076,17 @@ When 'widen-automatically' is non-nil, 'goto-line' widens the narrowed
buffer to be able to move point to the inaccessible portion.
'goto-line-relative' is bound to 'C-x n g'.
-+++
** 'goto-char' prompts for the character position.
When called interactively, 'goto-char' now offers the position at
point as the default.
** Auto-saving via 'auto-save-visited-mode' can now be inhibited.
-Set the variable 'auto-save-visited-mode' buffer-locally to nil to
+Set the user option 'auto-save-visited-mode' buffer-locally to nil to
achieve that.
-+++
** New command 'kdb-macro-redisplay' to force redisplay in keyboard macros.
This command is bound to 'C-x C-k d'.
----
** 'blink-cursor-mode' is now enabled by default regardless of the UI.
It used to be enabled when Emacs is started in GUI mode but not when started
in text mode. The cursor still only actually blinks in GUI frames.
@@ -1209,7 +1095,6 @@ in text mode. The cursor still only actually blinks in GUI frames.
To go back to the previous behavior, customize the user option of the
same name to nil.
-+++
** New minor mode 'show-paren-local-mode'.
It serves as a local counterpart for 'show-paren-mode', allowing you
to toggle it separately in different buffers. To use it only in
@@ -1222,7 +1107,6 @@ programming modes, for example, add the following to your init file:
** Isearch and Replace
-+++
*** Interactive regular expression search now uses faces for sub-groups.
E.g., 'C-M-s foo-\([0-9]+\)' will now use the 'isearch-group-1' face
on the part of the regexp that matches the sub-expression "[0-9]+".
@@ -1234,12 +1118,10 @@ This is controlled by the 'search-highlight-submatches' user option.
This feature is available only on terminals that have enough colors to
distinguish between sub-expression highlighting.
-+++
*** Interactive regular expression replace now uses faces for sub-groups.
Like 'search-highlight-submatches', this is controlled by the new user option
'query-replace-highlight-submatches'.
-+++
*** New key 'M-s M-.' starts isearch looking for the thing at point.
This key is bound to the new command 'isearch-forward-thing-at-point'.
The new user option 'isearch-forward-thing-at-point' defines
@@ -1247,39 +1129,34 @@ a list of symbols to try to get the "thing" at point. By default,
the first element of the list is 'region' that tries to yank
the currently active region to the search string.
-+++
*** New user option 'isearch-wrap-pause' defines how to wrap the search.
There are choices to disable wrapping completely and to wrap immediately.
When wrapping immediately, it consistently handles the numeric arguments
of 'C-s' ('isearch-repeat-forward') and 'C-r' ('isearch-repeat-backward'),
continuing with the remaining count after wrapping.
-+++
*** New user option 'isearch-repeat-on-direction-change'.
When this option is set, direction changes in Isearch move to another
search match, if there is one, instead of moving point to the other
end of the current match.
-+++
*** New user option 'isearch-allow-motion'.
When 'isearch-allow-motion' is set, the commands 'beginning-of-buffer',
'end-of-buffer', 'scroll-up-command' and 'scroll-down-command', when
-invoked during I-search, move respectively to the first occurrence of
+invoked during Isearch, move respectively to the first occurrence of
the current search string in the buffer, the last one, the first one
after the current window, and the last one before the current window.
Additionally, users can change the meaning of other motion commands
-during I-search by using their 'isearch-motion' property. The user
+during Isearch by using their 'isearch-motion' property. The user
option 'isearch-motion-changes-direction' controls whether the
direction of the search changes after a motion command.
-+++
*** New user option 'lazy-highlight-no-delay-length'.
Lazy highlighting of matches in Isearch now starts immediately if the
search string is at least this long. 'lazy-highlight-initial-delay'
still applies for shorter search strings, which avoids flicker in the
search buffer due to too many matches being highlighted.
-+++
*** The default 'search-whitespace-regexp' value has changed.
This used to be "\\s-+", which meant that it was mode-dependent whether
newlines were included in the whitespace set. This has now been
@@ -1287,52 +1164,43 @@ changed to only match spaces and tab characters.
** Dired
-+++
*** New user option 'dired-kill-when-opening-new-dired-buffer'.
If non-nil, Dired will kill the current buffer when selecting a new
directory to display.
-+++
*** Behavior change on 'dired-do-chmod'.
-As a security precaution, Dired's M command no longer follows symbolic
-links. Instead, it changes the symbolic link's own mode; this always
-fails on platforms where such modes are immutable.
+As a security precaution, Dired's 'M' command no longer follows
+symbolic links. Instead, it changes the symbolic link's own mode;
+this always fails on platforms where such modes are immutable.
----
*** Behavior change on 'dired-clean-confirm-killing-deleted-buffers'.
Previously, if 'dired-clean-up-buffers-too' was non-nil, and
'dired-clean-confirm-killing-deleted-buffers' was nil, the buffers
wouldn't be killed. This combination will now kill the buffers.
-+++
*** New user option 'dired-switches-in-mode-line'.
This user option controls how 'ls' switches are displayed in the mode
line, and allows truncating them (to preserve space on the mode line)
or showing them literally, either instead of, or in addition to,
displaying "by name" or "by date" sort order.
-+++
*** New user option 'dired-compress-directory-default-suffix'.
This user option controls the default suffix for compressing a
directory. If it's nil, ".tar.gz" will be used. Refer to
'dired-compress-files-alist' for a list of supported suffixes.
-+++
*** New user option 'dired-compress-file-default-suffix'.
This user option controls the default suffix for compressing files.
If it's nil, ".gz" will be used. Refer to 'dired-compress-file-alist'
for a list of supported suffixes.
----
*** Broken and circular links are shown with the 'dired-broken-symlink' face.
----
*** '=' ('dired-diff') will now put all backup files into the 'M-n' history.
When using '=' on a file with backup files, the default file to use
for diffing is the newest backup file. You can now use 'M-n' to quickly
select a different backup file instead.
-+++
*** New user option 'dired-maybe-use-globstar'.
If set, enables globstar (recursive globbing) in shells that support
this feature, but have it turned off by default. This allows producing
@@ -1341,19 +1209,16 @@ subdirectories of a given directory. The new variable
'dired-enable-globstar-in-shell' lists which shells can have globstar
enabled, and how to enable it.
-+++
*** New user option 'dired-copy-dereference'.
If set to non-nil, Dired will dereference symbolic links when copying.
This can be switched off on a per-usage basis by providing
'dired-do-copy' with a 'C-u' prefix.
----
*** New user option 'dired-do-revert-buffer'.
Non-nil reverts the destination Dired buffer after performing one
of these operations: 'dired-do-copy', 'dired-do-rename',
'dired-do-symlink', 'dired-do-hardlink'.
----
*** New user option 'dired-mark-region'.
This option affects all Dired commands that mark files. When non-nil
and the region is active in Transient Mark mode, then Dired commands
@@ -1361,12 +1226,10 @@ operate only on files in the active region. The values 'file' and
'line' of this user option define the details of marking the file at
the end of the region.
-+++
*** State changing VC operations are supported in Dired.
These operations are supported on files and directories via the new
command 'dired-vc-next-action'.
-+++
*** 'dired-jump' and 'dired-jump-other-window' moved from 'dired-x' to 'dired'.
The 'dired-jump' and 'dired-jump-other-window' commands have been
moved from the 'dired-x' package to 'dired'. The user option
@@ -1379,25 +1242,21 @@ keys, add the following to your init file:
(global-set-key "\C-x\C-j" nil)
(global-set-key "\C-x4\C-j" nil)
----
*** 'dired-query' now uses 'read-char-from-minibuffer'.
Using it instead of 'read-char-choice' allows using 'C-x o'
to switch to the help window displayed after typing 'C-h'.
-+++
** Emacs 28.1 comes with Org v9.5.
See the file ORG-NEWS for user-visible changes in Org.
** Outline
-+++
*** New commands to cycle heading visibility.
Typing 'TAB' on a heading line cycles the current section between
"hide all", "subheadings", and "show all" states. Typing 'S-TAB'
anywhere in the buffer cycles the whole buffer between "only top-level
headings", "all headings and subheadings", and "show all" states.
-+++
*** New user option 'outline-minor-mode-cycle'.
This user option customizes 'outline-minor-mode', with the difference
that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
@@ -1406,7 +1265,6 @@ Typing 'TAB' on a heading line cycles the current section between
heading line cycles the whole buffer between "only top-level
headings", "all headings and subheadings", and "show all" states.
----
*** New user option 'outline-minor-mode-highlight'.
This user option customizes 'outline-minor-mode'. It puts
highlighting on heading lines using standard outline faces. This
@@ -1415,27 +1273,22 @@ major mode.
** Ispell
-+++
*** 'ispell-comments-and-strings' now accepts START and END arguments.
These arguments default to the active region when used interactively.
-+++
*** New command 'ispell-comment-or-string-at-point'.
----
*** New user option 'ispell-help-timeout'.
This controls how long the ispell help (on the '?' key) is displayed.
** Flyspell mode
-+++
*** Corrections and actions menu can be optionally bound to 'mouse-3'.
When Flyspell mode highlights a word as misspelled, you can click on
it to display a menu of possible corrections and actions. You can now
easily bind this menu to 'down-mouse-3' (usually the right mouse button)
instead of 'mouse-2' (the default) by enabling 'context-menu-mode'.
----
*** The current dictionary is now displayed in the minor mode lighter.
Clicking the dictionary name changes the current dictionary.
@@ -1445,7 +1298,6 @@ Clicking the dictionary name changes the current dictionary.
Thus, packages on NonGNU ELPA will appear by default in the list shown
by 'list-packages'.
----
*** '/ s' ('package-menu-filter-by-status') changed parameter handling.
The command was documented to take a comma-separated list of statuses
to filter by, but instead it used the parameter as a regexp. The
@@ -1453,10 +1305,8 @@ command has been changed so that it now works as documented, and
checks statuses not as a regexp, but instead an exact match from the
comma-separated list.
-+++
*** New command 'package-browse-url' and keystroke 'w'.
-+++
*** New commands to filter the package list.
The filter commands are bound to the following keys:
@@ -1471,7 +1321,7 @@ key binding
/ v package-menu-filter-by-version
/ m package-menu-filter-marked
/ u package-menu-filter-upgradable
-/ / package-menu-filter-clear
+/ / package-menu-clear-filter
*** Option to automatically native-compile packages upon installation.
Customize the user option 'package-native-compile' to enable automatic
@@ -1483,7 +1333,6 @@ run the native-compilation of the package files. (Be sure to leave
Emacs running until these asynchronous subprocesses exit, or else the
native-compilation will be aborted when you exit Emacs.)
----
*** Column widths in 'list-packages' display can now be customized.
See the new user options 'package-name-column-width',
'package-version-column-width', 'package-status-column-width', and
@@ -1491,7 +1340,6 @@ See the new user options 'package-name-column-width',
** Info
----
*** New user option 'Info-warn-on-index-alternatives-wrap'.
This option affects what happens when using the ',' command after
looking up an entry with 'i' in info buffers. If non-nil (the
@@ -1501,7 +1349,6 @@ you to the first match.
** Abbrev mode
-+++
*** Emacs can now suggest to use an abbrev based on text you type.
A new user option, 'abbrev-suggest', enables the new abbrev suggestion
feature. When enabled, if a user manually types a piece of text that
@@ -1511,17 +1358,14 @@ used instead.
** Bookmarks
----
*** Bookmarks can now be targets for new tabs.
When the bookmark.el library is loaded, a customize choice is added
to 'tab-bar-new-tab-choice' for new tabs to show the bookmark list.
----
*** New user option 'bookmark-set-fringe-mark'.
If non-nil, setting a bookmark will set a fringe mark on the current
line, and jumping to a bookmark will also set this mark.
----
*** New user option 'bookmark-menu-confirm-deletion'.
In Bookmark Menu mode, Emacs by default does not prompt for
confirmation when you type 'x' to execute the deletion of bookmarks
@@ -1529,7 +1373,6 @@ that have been marked for deletion. However, if this new option is
non-nil then Emacs will require confirmation with 'yes-or-no-p' before
deleting.
----
*** The 'list-bookmarks' menu is now based on 'tabulated-list-mode'.
The interactive bookmark list will now benefit from features in
'tabulated-list-mode' like sorting columns or changing column width.
@@ -1541,17 +1384,14 @@ The variables 'bookmark-bmenu-use-header-line' and
** Recentf
----
*** The recentf files are no longer backed up.
----
*** 'recentf-auto-cleanup' now repeats daily when set to a time string.
When 'recentf-auto-cleanup' is set to a time string, it now repeats
every day, rather than only running once after the mode is turned on.
** Calc
----
*** The behavior when doing forward-delete has been changed.
Previously, using the 'C-d' command would delete the final number in
the input field, no matter where point was. This has been changed to
@@ -1559,42 +1399,35 @@ work more traditionally, with 'C-d' deleting the next character.
Likewise, point isn't moved to the end of the string before inserting
digits.
-+++
*** Setting the word size to zero disables word clipping.
The word size normally clips the results of certain bit-oriented
operations such as shifts and bitwise XOR. A word size of zero, set
by 'b w', makes the operation have effect on the whole argument values
and the result is not truncated in any way.
----
*** The '/' operator now has higher precedence in (La)TeX input mode.
It no longer has lower precedence than '+' and '-'.
----
*** New user option 'calc-make-windows-dedicated'.
When this user option is non-nil, Calc will mark its windows as
dedicated.
** Calendar
-+++
*** New user option 'calendar-time-zone-style'.
If 'numeric', calendar functions (eg 'calendar-sunrise-sunset') that display
time zones will use a form like "+0100" instead of "CET".
** Imenu
-+++
*** New user option 'imenu-max-index-time'.
If creating the imenu index takes longer than specified by this
option (default 5 seconds), imenu indexing is stopped.
-** ido
+** Ido
----
*** Switching on 'ido-mode' now also overrides 'ffap-file-finder'.
----
*** Killing virtual ido buffers interactively will make them go away.
Previously, killing a virtual ido buffer with 'ido-kill-buffer' didn't
do anything. This has now been changed, and killing virtual buffers
@@ -1602,13 +1435,11 @@ with that command will remove the buffer from recentf.
** So Long
----
*** New 'so-long-predicate' function 'so-long-statistics-excessive-p'.
It efficiently detects the presence of a long line anywhere in the
buffer using 'buffer-line-statistics' (see above). This is now the
default predicate (replacing 'so-long-detected-long-line-p').
----
*** Default values 'so-long-threshold' and 'so-long-max-lines' increased.
The values of these user options have been raised to 10000 bytes and 500
lines respectively, to reduce the likelihood of false-positives when
@@ -1616,14 +1447,12 @@ lines respectively, to reduce the likelihood of false-positives when
by the old predicate, as the new predicate knows the longest line in
the entire buffer.
----
*** 'so-long-target-modes' now includes 'fundamental-mode' by default.
This means that 'global-so-long-mode' will also process files which were
not recognised. (This only has an effect if 'set-auto-mode' chooses
'fundamental-mode'; buffers which are simply in 'fundamental-mode' by
default are unaffected.)
----
*** New user options to preserve modes and variables.
The new options 'so-long-mode-preserved-minor-modes' and
'so-long-mode-preserved-variables' allow specified mode and variable
@@ -1632,7 +1461,6 @@ mode. By default, these new options support 'view-mode'.
** Grep
-+++
*** New user option 'grep-match-regexp' matches grep markers to highlight.
Grep emits SGR ANSI escape sequences to color its output. The new
user option 'grep-match-regexp' holds the regular expression to match
@@ -1640,7 +1468,6 @@ the appropriate markers in order to provide highlighting in the source
buffer. The user option can be customized to accommodate other
grep-like tools.
----
*** The 'lgrep' command now ignores directories.
On systems where the grep command supports it, directories will be
skipped.
@@ -1654,40 +1481,34 @@ any directory names on the 'find' command lines end in a slash.
This change is for better compatibility with old versions of non-GNU
'find', such as the one used on macOS.
----
*** New utility function 'grep-file-at-point'.
This returns the name of the file at point (if any) in 'grep-mode'
buffers.
** Shell
----
-*** New command in 'shell-mode': 'narrow-to-prompt'.
+*** New command in 'shell-mode': 'shell-narrow-to-prompt'.
This is bound to 'C-x n d' in 'shell-mode' buffers, and narrows to the
command line under point (and any following output).
----
*** New user option 'shell-has-auto-cd'.
If non-nil, 'shell-mode' handles implicit "cd" commands, changing the
directory if the command is a directory. Useful for shells like "zsh"
that has this feature.
-** term-mode
+** Term mode
----
*** New user option 'term-scroll-snap-to-bottom'.
By default, 'term' and 'ansi-term' will now recenter the buffer so
that the prompt is on the final line in the window. Setting this new
user option to nil inhibits this behavior.
----
-*** New user option 'term-set-terminal-size'
+*** New user option 'term-set-terminal-size'.
If non-nil, the 'LINES' and 'COLUMNS' environment variables will be set
based on the current window size. In previous versions of Emacs, this
was always done (and that could lead to odd displays when resizing the
window after starting). This variable defaults to nil.
----
*** 'term-mode' now supports "bright" color codes.
"Bright" ANSI color codes are now displayed using the color values
defined in 'term-color-bright-*'. In addition, bold text with regular
@@ -1696,17 +1517,14 @@ is non-nil.
** Eshell
----
*** 'eshell-hist-ignoredups' can now also be used to mimic "erasedups" in bash.
----
*** Environment variable 'INSIDE_EMACS' is now copied to subprocesses.
Its value contains the result of evaluating '(format "%s,eshell"
emacs-version)'. Other package names, like "tramp", could also be included.
----
*** Eshell no longer re-initializes its keymap every call.
-This allows users to use (define-key eshell-mode-map ...) as usual.
+This allows users to use '(define-key eshell-mode-map ...)' as usual.
Some modules have their own minor mode now to account for these
changes.
@@ -1716,8 +1534,7 @@ will create a bookmark that opens the current directory in Eshell.
** Archive mode
----
-*** Archive Mode can now parse ".squashfs" files.
+*** Archive mode can now parse ".squashfs" files.
*** Can now modify members of 'ar' archives.
@@ -1728,12 +1545,11 @@ New user option 'archive-hidden-columns' and new command
'archive-hideshow-column' let you control which columns are displayed
and which are kept hidden.
----
*** New command bound to 'C': 'archive-copy-file'.
This command extracts the file at point and writes its data to a
file.
-** browse-url
+** Browse URL
*** Added support for custom URL handlers.
There is a new variable 'browse-url-default-handlers' and a user
@@ -1757,27 +1573,23 @@ symbol property to the browsing commands. With a new command
'browse-url-with-browser-kind', an URL can explicitly be browsed with
either an internal or external browser.
----
*** Support for browsing of remote files.
If a remote file is specified, a local temporary copy of that file is
passed to the browser.
----
*** Support for the conkeror browser is now obsolete.
----
*** Support for the Mosaic browser has been removed.
This support has been obsolete since 25.1.
-** Completion List Mode
+** Completion list mode
*** Improved navigation in the "*Completions*" buffer.
New key bindings have been added to 'completion-list-mode': 'n' and
'p' now navigate completions, and 'M-g M-c' switches to the
minibuffer and back to the completion list buffer.
-+++
-** profiler.el
+** Profiler
The results displayed by 'profiler-report' now have the usage figures
at the left hand side followed by the function name. This is intended
to make better use of the horizontal space, in particular eliminating
@@ -1786,34 +1598,28 @@ layout back.
** Icomplete
----
*** New user option 'icomplete-matches-format'.
This allows controlling the current/total number of matches for the
prompt prefix.
-+++
*** New minor modes 'icomplete-vertical-mode' and 'fido-vertical-mode'.
-These modes modify Icomplete ('M-x icomplete-mode') and Fido ('M-x
-fido-mode'), to display completion candidates vertically instead of
+These modes modify Icomplete ('icomplete-mode') and Fido
+('fido-mode'), to display completion candidates vertically instead of
horizontally. In Icomplete, completions are rotated and selection
kept at the top. In Fido, completions scroll like a typical dropdown
widget. Both these new minor modes will turn on their non-vertical
counterparts first, if they are not on already.
----
*** Default value of 'icomplete-compute-delay' has been changed to 0.15 s.
----
*** Default value of 'icomplete-max-delay-chars' has been changed to 2.
----
*** Reduced blinking while completing the next completions set.
Icomplete doesn't hide the hint with the previously computed
completions anymore when compute delay is in effect, or the previous
computation has been aborted by input. Instead it shows the previous
completions until the new ones are ready.
----
*** Change in meaning of 'icomplete-show-matches-on-no-input'.
Previously, choosing a different completion with commands like 'C-.'
and then hitting 'RET' would choose the default completion. Doing this
@@ -1823,7 +1629,6 @@ with initial input as the default directory.
** Windmove
-+++
*** New user options to customize windmove keybindings.
These options include 'windmove-default-keybindings',
'windmove-display-default-keybindings',
@@ -1833,81 +1638,68 @@ Also new mode 'windmove-mode' enables the customized keybindings.
** Occur mode
----
-*** New bindings in occur-mode.
+*** New bindings in 'occur-mode'.
The command 'next-error-no-select' is now bound to 'n' and
'previous-error-no-select' is bound to 'p'.
----
*** New command 'recenter-current-error'.
It is bound to 'l' in Occur or compilation buffers, and recenters the
current displayed occurrence/error.
----
*** Matches in target buffers are now highlighted as in 'compilation-mode'.
The method of highlighting is specified by the user options
'next-error-highlight' and 'next-error-highlight-no-select'.
----
*** A fringe arrow in the "*Occur*" buffer indicates the selected match.
----
*** Occur mode may use a different type for 'occur-target' property values.
The value was previously always a marker set to the start of the first
match on the line but can now also be a list of '(BEGIN . END)' pairs
of markers delimiting each match on the line.
-This is a fully compatible change to the internal occur-mode
-implementation, and code creating their own occur-mode buffers will
+This is a fully compatible change to the internal 'occur-mode'
+implementation, and code creating their own 'occur-mode' buffers will
work as before.
** Emacs Lisp mode
----
*** The mode-line now indicates whether we're using lexical or dynamic scoping.
-+++
*** A space between an open paren and a symbol changes the indentation rule.
The presence of a space between an open paren and a symbol now is
taken as a statement by the programmer that this should be indented
as a data list rather than as a piece of code.
-** Lisp Mode
+** Lisp mode
*** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'.
The mode provides refined highlighting of built-in functions, types,
and variables.
----
*** Lisp mode now uses 'common-lisp-indent-function'.
To revert to the previous behavior,
'(setq lisp-indent-function 'lisp-indent-function)' from 'lisp-mode-hook'.
** Change Logs and VC
-+++
*** 'vc-revert-show-diff' now has a third possible value: 'kill'.
If this user option is 'kill', then the diff buffer will be killed
after the 'vc-revert' action instead of buried.
----
*** More VC commands can be used from non-file buffers.
The relevant commands are those that don't change the VC state.
The non-file buffers which can use VC commands are those that have
their 'default-directory' under VC.
----
*** New face 'log-view-commit-body'.
This is used when expanding commit messages from 'vc-print-root-log'
and similar commands.
----
*** New faces for 'vc-dir' buffers.
Those are: 'vc-dir-header', 'vc-dir-header-value', 'vc-dir-directory',
'vc-dir-file', 'vc-dir-mark-indicator', 'vc-dir-status-warning',
'vc-dir-status-edited', 'vc-dir-status-up-to-date',
'vc-dir-status-ignored'.
----
*** The responsible VC backend is now the most specific one.
'vc-responsible-backend' loops over the backends in
'vc-handled-backends' to determine which backend is responsible for a
@@ -1915,41 +1707,32 @@ specific (unregistered) file. Previously, the first matching backend
was chosen, but now the one with the most specific path is chosen (in
case there's a directory handled by one backend inside another).
----
*** New command 'vc-dir-root' uses the root directory without asking.
----
*** New commands 'vc-dir-mark-registered-files' (bound to '* r') and
'vc-dir-mark-unregistered-files'.
----
*** Support for bookmark.el.
Bookmark locations can refer to VC directory buffers.
----
*** New user option 'vc-hg-create-bookmark'.
It controls whether a bookmark or branch will be created when you
invoke 'C-u C-x v s' ('vc-create-tag').
----
*** 'vc-hg' now uses 'hg summary' to populate extra 'vc-dir' headers.
----
*** New user option 'vc-git-revision-complete-only-branches'.
If non-nil, only branches and remotes are considered when doing
completion over Git branch names. The default is nil, which causes
tags to be considered as well.
----
*** New user option 'vc-git-log-switches'.
String or list of strings specifying switches for Git log under VC.
----
*** Command 'vc-switch-backend' is now obsolete.
If you are still using it with any regularity, please file a bug
report with some details.
----
*** New variable 'vc-git-use-literal-pathspecs'.
The Git backend's function now treat all file names "literally", where
some of them previously could interpret file names (pathspecs) as
@@ -1958,35 +1741,28 @@ the aforementioned variable to nil locally to avoid this.
** Gnus
-+++
*** New user option 'gnus-topic-display-predicate'.
This can be used to inhibit the display of some topics completely.
-+++
*** nnimap now supports the oauth2.el library.
-+++
*** New Summary buffer sort options for extra headers.
The extra header sort option ('C-c C-s C-x') prompts for a header
and fails if no sort function has been defined. Sorting by
Newsgroups ('C-c C-s C-u') has been pre-defined.
-+++
*** The '#' command in the Group and Summary buffer now toggles,
instead of sets, the process mark.
-+++
*** New user option 'gnus-process-mark-toggle'.
If non-nil (the default), the '#' command in the Group and Summary
buffers will toggle, instead of set, the process mark.
-+++
*** New user option 'gnus-registry-register-all'.
If non-nil (the default), create registry entries for all messages.
If nil, don't automatically create entries, they must be created
manually.
-+++
*** New user options to customise the summary line specs "%[" and "%]".
Four new options introduced in customisation group
'gnus-summary-format'. These are 'gnus-sum-opening-bracket',
@@ -1999,29 +1775,24 @@ the value of 'gnus-sum-opening-bracket', but can also be
normally display the value of 'gnus-sum-closing-bracket', but can also
be 'gnus-sum-closing-bracket-adopted' for the adopted articles.
-+++
*** New user option 'gnus-paging-select-next'.
This controls what happens when using commands like 'SPC' and 'DEL' to
page the current article. If non-nil (the default), go to the
next/prev article, but if nil, do nothing at the end/start of the article.
-+++
*** New gnus-search library.
A new unified search syntax which can be used across multiple
supported search engines. Set 'gnus-search-use-parsed-queries' to
non-nil to enable.
-+++
*** New value for user option 'smiley-style'.
Smileys can now be rendered with emojis instead of small images when
using the new 'emoji' value in 'smiley-style'.
-+++
*** New user option 'gnus-agent-eagerly-store-articles'.
If non-nil (which is the default), the Gnus Agent will store all read
articles in the Agent cache.
-+++
*** New user option 'gnus-global-groups'.
Gnus handles private groups differently from public (i.e., NNTP-like)
groups. Most importantly, Gnus doesn't download external images from
@@ -2029,17 +1800,14 @@ mail-like groups. This can be overridden by putting group names in
'gnus-global-groups': Any group present in that list will be treated
like a public group.
-+++
*** New scoring types for the Date header.
You can now score based on the relative age of an article with the new
'<' and '>' date scoring types.
-+++
*** User-defined scoring is now possible.
The new type is 'score-fn'. More information in the Gnus manual node
"(gnus) Score File Format".
-+++
*** New backend 'nnselect'.
The newly added 'nnselect' backend allows creating groups from an
arbitrary list of articles that may come from multiple groups and
@@ -2062,35 +1830,29 @@ has been removed; its functionality is now available directly in the
'gnus-refer-thread-use-nnir' has been renamed to
'gnus-refer-thread-use-search'.
-+++
*** New user option 'gnus-dbus-close-on-sleep'.
On systems with D-Bus support, it is now possible to register a signal
to close all Gnus servers before the system sleeps.
-+++
*** The key binding of 'gnus-summary-search-article-forward' has changed.
This command was previously on 'M-s' and shadowed the global 'M-s'
search prefix. The command has now been moved to 'M-s M-s'. (For
consistency, the 'M-s M-r' key binding has been added for the
'gnus-summary-search-article-backward' command.)
----
*** The value for "all" in the 'large-newsgroup-initial' group parameter has changed.
It was previously nil, which didn't work, because nil is
indistinguishable from not being present. The new value for "all" is
the symbol 'all'.
-+++
*** The name of dependent Gnus sessions has changed from "slave" to "child".
The names of the commands 'gnus-slave', 'gnus-slave-no-server' and
'gnus-slave-unplugged' have changed to 'gnus-child',
'gnus-child-no-server' and 'gnus-child-unplugged' respectively.
-+++
*** The 'W Q' summary mode command now takes a numerical prefix to
allow adjusting the fill width.
-+++
*** New variable 'mm-inline-font-lock'.
This variable is supposed to be bound by callers to determine whether
inline MIME parts (that support it) are supposed to be font-locked or
@@ -2098,23 +1860,19 @@ not.
** Message
----
*** Respect 'message-forward-ignored-headers' more.
Previously, this user option would not be consulted if
'message-forward-show-mml' was nil and forwarding as MIME.
-+++
*** New user option 'message-forward-included-mime-headers'.
This is used when forwarding messages as MIME, but not using MML.
-+++
*** Message now supports the OpenPGP header.
To generate these headers, add the new function
'message-add-openpgp-header' to 'message-send-hook'. The header will
be generated according to the new 'message-openpgp-header' user
option.
----
*** A change to how "Mail-Copies-To: never" is handled.
If a user has specified "Mail-Copies-To: never", and Message was asked
to do a "wide reply", some other arbitrary recipient would end up in
@@ -2124,7 +1882,6 @@ you're responding to a specific person in particular. This has been
changed so that all the recipients are put in the "To" header in these
instances.
-+++
*** New command to start Emacs in Message mode to send an email.
Emacs can be defined as a handler for the "x-scheme-handler/mailto"
MIME type with the following command: "emacs -f message-mailto %u".
@@ -2137,7 +1894,6 @@ Emacs with headers filled out according to the link, e.g.
emacsclient, use "emacsclient -e '(message-mailto "%u")'"
or "emacsclient-mail.desktop".
----
*** Change to default value of 'message-draft-headers' user option.
The 'Date' symbol has been removed from the default value, meaning that
draft or delayed messages will get a date reflecting when the message
@@ -2145,7 +1901,6 @@ was sent. To restore the original behavior of dating a message
from when it is first saved or delayed, add the symbol 'Date' back to
this user option.
-+++
*** New command to take screenshots.
In Message mode buffers, the 'C-c C-p' ('message-insert-screenshot')
command has been added. It depends on using an external program to
@@ -2153,30 +1908,25 @@ take the actual screenshot, and defaults to "ImageMagick import".
** Smtpmail
-+++
*** smtpmail now supports using the oauth2.el library.
-+++
*** New user option 'smtpmail-store-queue-variables'.
If non-nil, SMTP variables will be stored together with the queued
-messages, and will then be used when sending with
-'M-x smtpmail-send-queued-mail'.
+messages, and will then be used when sending with command
+'smtpmail-send-queued-mail'.
-+++
*** Allow direct selection of smtp authentication mechanism.
A server entry retrieved by auth-source can request a desired smtp
authentication mechanism by setting a value for the key 'smtp-auth'.
** ElDoc
-+++
*** New user option 'eldoc-echo-area-display-truncation-message'.
If non-nil (the default), eldoc will display a message saying
something like "(Documentation truncated. Use `M-x eldoc-doc-buffer'
to see rest)" when a message has been truncated. If nil, truncated
messages will be marked with just "..." at the end.
-+++
*** New hook 'eldoc-documentation-functions'.
This hook is intended to be used for registering doc string functions.
These functions don't need to produce the doc string right away, they
@@ -2191,7 +1941,6 @@ functions receive the doc string composed according to
the user. Examples of such functions would use the echo area, a
separate buffer, or a tooltip.
-+++
*** New user option 'eldoc-documentation-strategy'.
The built-in choices available for this user option let users compose
the results of 'eldoc-documentation-functions' in various ways, even
@@ -2207,33 +1956,27 @@ it when producing a doc string.
** Tramp
-+++
*** New connection method "mtp".
It allows accessing media devices like cell phones, tablets or
cameras.
-+++
*** New connection method "sshfs".
It allows accessing remote files via a file system mounted with
'sshfs'.
-+++
*** Tramp supports SSH authentication via a hardware security key now.
This requires at least OpenSSH 8.2, and a FIDO U2F compatible
security key, like yubikey, solokey, or nitrokey.
-+++
*** Trashed remote files are moved to the local trash directory.
All remote files that are trashed are moved to the local trash
directory, except remote encrypted files, which are always deleted.
-+++
*** New command 'tramp-crypt-add-directory'.
This command marks a remote directory to contain only encrypted files.
See the "(tramp) Keeping files encrypted" node of the Tramp manual for
details. This feature is experimental.
-+++
*** Support of direct asynchronous process invocation.
When Tramp connection property "direct-async-process" is set to
non-nil for a given connection, 'make-process' and 'start-file-process'
@@ -2243,33 +1986,28 @@ performance of asynchronous remote processes" node of the Tramp manual
for details, and also for a discussion or restrictions. This feature
is experimental.
-+++
*** New user option 'tramp-debug-to-file'.
When non-nil, this user option instructs Tramp to mirror the debug
buffer to a file under the "/tmp/" directory. This is useful, if (in
rare cases) Tramp blocks Emacs, and we need further debug information.
-+++
*** Tramp supports lock files now.
In order to deactivate this, set user option
'remote-file-name-inhibit-locks' to t.
-+++
*** Writing sensitive data locally requires confirmation.
Writing auto-save, backup or lock files to the local temporary
directory must be confirmed. In order to suppress this confirmation,
set user option 'tramp-allow-unsafe-temporary-files' to t.
-+++
*** 'make-directory' of a remote directory honors the default file modes.
-** gdb-mi
+** GDB/MI
*** New user option 'gdb-registers-enable-filter'.
If non-nil, apply a register filter based on
'gdb-registers-filter-pattern-list'.
-+++
*** gdb-mi can now save and restore window configurations.
Use 'gdb-save-window-configuration' to save window configuration to a
file and 'gdb-load-window-configuration' to load from a file. These
@@ -2277,31 +2015,26 @@ commands can also be accessed through the menu bar under "Gud =>
GDB-Windows". 'gdb-default-window-configuration-file', when non-nil,
is loaded when GDB starts up.
-+++
*** gdb-mi can now restore window configuration after quitting.
Set 'gdb-restore-window-configuration-after-quit' to non-nil and Emacs
will remember the window configuration before GDB started and restore
it after GDB quits. A toggle button is also provided under "Gud =>
GDB-Windows" menu item.
-+++
*** gdb-mi now has a better logic for displaying source buffers.
Now GDB only uses one source window to display source file by default.
Customize 'gdb-max-source-window-count' to use more than one window.
Control source file display by 'gdb-display-source-buffer-action'.
-+++
*** The default value of 'gdb-mi-decode-strings' is now t.
This means that the default coding-system is now used to decode strings
and source file names from GDB.
** Compilation mode
----
*** New function 'ansi-color-compilation-filter'.
This function is meant to be used in 'compilation-filter-hook'.
----
*** New user option 'ansi-color-for-compilation-mode'.
This controls what 'ansi-color-compilation-filter' does.
@@ -2311,7 +2044,6 @@ case-insensitive matching of messages when the old behavior is
required, but the recommended solution is to use a correctly matching
regexp instead.
----
*** New user option 'compilation-search-all-directories'.
When doing parallel builds, directories and compilation errors may
arrive in the "*compilation*" buffer out-of-order. If this option is
@@ -2319,45 +2051,37 @@ non-nil (the default), Emacs will now search backwards in the buffer
for any directory the file with errors may be in. If nil, this won't
be done (and this restores how this previously worked).
----
*** Messages from ShellCheck are now recognized.
----
*** Messages from Visual Studio that mention column numbers are now recognized.
** Hi Lock mode
----
*** Matching in 'hi-lock-mode' can be case-sensitive.
The matching is case-sensitive when a regexp contains upper case
characters and 'search-upper-case' is non-nil. 'highlight-phrase'
also uses 'search-whitespace-regexp' to substitute spaces in regexp
search.
----
*** The default value of 'hi-lock-highlight-range' was enlarged.
The new default value is 2000000 (2 megabytes).
** Whitespace mode
-+++
*** New style 'missing-newline-at-eof'.
If present in 'whitespace-style' (as it is by default), the final
character in the buffer will be highlighted if the buffer doesn't end
with a newline.
----
*** The default 'whitespace-enable-predicate' predicate has changed.
It used to check elements in the list version of
'whitespace-global-modes' with 'eq', but now uses 'derived-mode-p'.
** Texinfo
----
*** New user option 'texinfo-texi2dvi-options'.
This is used when invoking 'texi2dvi' from 'texinfo-tex-buffer'.
----
*** New commands for moving in and between environments.
An "environment" is something that ends with '@end'. The commands are
'C-c C-c C-f' (next end), 'C-c C-c C-b' (previous end),
@@ -2367,19 +2091,16 @@ current environment.
** Rmail
----
*** New user option 'rmail-re-abbrevs'.
Its default value matches localized abbreviations of the "reply"
prefix on the Subject line in various languages.
----
*** New user option 'rmail-show-message-set-modified'.
If set non-nil, showing an unseen message will set the Rmail buffer's
modified flag. The default is nil, to preserve the old behavior.
-** CC Mode
+** CC mode
-+++
*** Added support for Doxygen documentation style.
'doxygen' is now a valid 'c-doc-comment-style' which recognises all
comment styles supported by Doxygen (namely '///', '//!', '/** … */'
@@ -2394,7 +2115,6 @@ use 'doxygen' by default one might evaluate:
or use it in a custom 'c-style'.
-+++
*** Added support to line up '?' and ':' of a ternary operator.
The new 'c-lineup-ternary-bodies' function can be used as a lineup
function to align question mark and colon which are part of a ternary
@@ -2414,30 +2134,25 @@ To enable, add it to appropriate entries in 'c-offsets-alist', e.g.:
** Images
----
*** You can explicitly specify base_uri for svg images.
':base-uri' image property can be used to explicitly specify base_uri
for embedded images into svg. ':base-uri' is supported for both file
and data svg images.
-+++
*** 'svg-embed-base-uri-image' added to embed images.
'svg-embed-base-uri-image' can be used to embed images located
relatively to 'file-name-directory' of the ':base-uri' svg image property.
This works much faster than 'svg-embed'.
-+++
*** New function 'image-cache-size'.
This function returns the size of the current image cache, in bytes.
----
*** Animated images stop automatically under high CPU pressure sooner.
Previously, an animated image would stop animating if any single image
took more than two seconds to display. The new algorithm maintains a
decaying average of delays, and if this number gets too high, the
animation is stopped.
-+++
*** The 'n' and 'p' commands (next/previous image) now respect Dired order.
These commands would previously display the next/previous image in
lexicographic order, but will now find the "parent" Dired buffer and
@@ -2446,7 +2161,6 @@ sorted there. The commands have also been extended to work when the
"parent" buffer is an archive mode (i.e., zip file or the like) or tar
mode buffer.
----
*** 'image-converter' is now restricted to formats in 'auto-mode-alist'.
When using external image converters, the external program is queried
for what formats it supports. This list may contain formats that are
@@ -2454,7 +2168,6 @@ problematic in some contexts (like PDFs), so this list is now filtered
based on 'auto-mode-alist'. Only file names that map to 'image-mode'
are now supported.
----
*** The background and foreground of images now default to face colors.
When an image doesn't specify a foreground or background color, Emacs
now uses colors from the face used to draw the surrounding text
@@ -2470,7 +2183,6 @@ To load images with the default frame colors use the ':foreground' and
This change only affects image types that support foreground and
background colors or transparency, such as xbm, pbm, svg, png and gif.
-+++
*** Image smoothing can now be explicitly enabled or disabled.
Smoothing applies a bilinear filter while scaling or rotating an image
to prevent aliasing and other unwanted effects. The new image
@@ -2480,13 +2192,11 @@ and nil to disable smoothing.
The default behavior of smoothing on down-scaling and not smoothing
on up-scaling remains unchanged.
-+++
*** New user option 'image-transform-smoothing'.
This controls whether to use smoothing or not for an image. Values
include nil (no smoothing), t (do smoothing) or a predicate function
that's called with the image object and should return nil/t.
-+++
*** SVG images now support user stylesheets.
The ':css' image attribute can be used to override the default CSS
stylesheet for an image. The default sets 'font-family' and
@@ -2495,7 +2205,6 @@ will match the font size in use where it is embedded.
This feature relies on librsvg 2.48 or above being available.
-+++
*** Image properties support 'em' sizes.
Size image properties, for example ':height', ':max-height', etc., can
be given a cons of the form '(SIZE . em)', where SIZE is an integer or
@@ -2504,50 +2213,42 @@ size, and 'em' is a symbol.
** EWW
-+++
*** New user option 'eww-use-browse-url'.
This is a regexp that can be set to alter how links are followed in eww.
-+++
*** New user option 'eww-retrieve-command'.
This can be used to download data via an external command. If nil
(the default), then 'url-retrieve' is used. When 'sync', then
'url-retrieve-synchronously' is used. A list of strings specifies
an external program with parameters.
-+++
*** New Emacs command line convenience command.
The 'eww-browse' command has been added, which allows you to register
Emacs as a MIME handler for "text/x-uri", and will call 'eww' on the
supplied URL. Usage example: "emacs -f eww-browse https://gnu.org".
-+++
*** 'eww-download-directory' will now use the XDG location, if defined.
However, if "~/Downloads/" already exists, that will continue to be
used.
----
-*** The command 'eww-follow-link' now supports custom mailto: handlers.
+*** The command 'eww-follow-link' now supports custom 'mailto:' handlers.
The function that is invoked when clicking on or otherwise following a
'mailto:' link in an EWW buffer can now be customized. For more
information, see the related entry about 'shr-browse-url' below.
----
*** Support for bookmark.el.
The command 'bookmark-set' (bound to 'C-x r m') is now supported, and
will create a bookmark that opens the current URL in EWW.
** SHR
----
-*** The command 'shr-browse-url' now supports custom mailto handlers.
+*** The command 'shr-browse-url' now supports custom 'mailto:' handlers.
Clicking on or otherwise following a 'mailto:' link in an HTML buffer
-rendered by SHR previously invoked the command 'browse-url-mailto'.
+rendered by SHR previously invoked the command 'browse-url-mail'.
This is still the case by default, but if you customize
'browse-url-mailto-function' or 'browse-url-handlers' to call some
other function, it will now be called instead of the default.
----
*** New user option 'shr-offer-extend-specpdl'.
If this is nil, rendering of HTML that requires enlarging
'max-specpdl-size', the number of Lisp variable bindings, will be
@@ -2555,7 +2256,6 @@ aborted, and Emacs will not ask you whether to enlarge
'max-specpdl-size' to complete the rendering. The default is t, which
preserves the original behavior.
-+++
*** New user option 'shr-max-width'.
If this user option is non-nil, and 'shr-width' is nil, then SHR will
use the value of 'shr-max-width' to limit the width of the rendered
@@ -2565,80 +2265,64 @@ to a more readable text. Customize it to nil to get the previous
behavior of rendering as wide as the 'window-width' allows. If
'shr-width' is non-nil, it overrides this option.
----
*** New faces for heading elements.
Those are 'shr-h1', 'shr-h2', 'shr-h3', 'shr-h4', 'shr-h5', 'shr-h6'.
** Project
----
*** New user option 'project-vc-merge-submodules'.
----
*** Project commands now have their own history.
Previously used project directories are now suggested by all commands
that prompt for a project directory.
-+++
*** New prefix keymap 'project-prefix-map'.
Key sequences that invoke project-related commands start with the
prefix 'C-x p'. Type 'C-x p C-h' to show the full list.
-+++
*** New commands 'project-dired', 'project-vc-dir', 'project-shell',
'project-eshell'. These commands run Dired/VC-Dir and Shell/Eshell in
a project's root directory, respectively.
-+++
*** New command 'project-compile'.
This command runs compilation in the current project's root directory.
-+++
*** New command 'project-switch-project'.
This command lets you "switch" to another project and run a project
command chosen from a dispatch menu.
-+++
*** New commands 'project-shell-command' and 'project-async-shell-command'.
These commands run 'shell-command' and 'async-shell-command' in a
project's root directory, respectively.
-+++
*** New user option 'project-list-file'.
This specifies the file in which to save the list of known projects.
-+++
*** New command 'project-remember-projects-under'.
This command can automatically locate and index projects in a
directory and optionally also its subdirectories, storing them in
'project-list-file'.
-+++
*** New commands 'project-forget-project' and 'project-forget-projects-under'.
These commands let you interactively remove entries from the list of projects
in 'project-list-file'.
-+++
*** New command 'project-forget-zombie-projects'.
This command detects indexed projects that have since been deleted,
and removes them from the list of known projects in 'project-list-file'.
----
*** 'project-find-file' now accepts non-existent file names.
This is to allow easy creation of files inside some nested
sub-directory.
-+++
*** 'project-find-file' doesn't use the string at point as default input.
Now it's only suggested as part of the "future history", accessible
via 'M-n'.
-+++
*** New command 'project-find-dir' runs Dired in a directory inside project.
** Xref
-+++
*** New user options to automatically show the first Xref match.
The new user option 'xref-auto-jump-to-first-definition' controls the
behavior of 'xref-find-definitions' and its variants, like
@@ -2652,59 +2336,49 @@ behavior of Xref commands such as 'xref-find-references',
display many matches that the user would like to
visit. 'xref-auto-jump-to-first-xref' changes their behavior much in
the same way as 'xref-auto-jump-to-first-definition' affects the
-"find-definitions" commands.
+'xref-find-definitions*' commands.
----
*** New user options 'xref-search-program' and 'xref-search-program-alist'.
So far 'grep' and 'ripgrep' are supported. 'ripgrep' seems to offer better
performance in certain cases, in particular for case-insensitive
searches.
-+++
*** New commands 'xref-prev-group' and 'xref-next-group'.
These commands are bound respectively to 'P' and 'N', and navigate to
the first item of the previous or next group in the "*xref*" buffer.
----
*** New alternative value for 'xref-show-definitions-function':
'xref-show-definitions-completing-read'.
----
*** The two existing alternatives for 'xref-show-definitions-function'
have been renamed to have "proper" public names and documented
('xref-show-definitions-buffer' and
'xref-show-definitions-buffer-at-bottom').
-+++
*** New command 'xref-quit-and-pop-marker-stack'.
This command is bound to 'M-,' in "*xref*" buffers. This combination
is easy to press semi-accidentally if the user wants to go back in the
middle of choosing the exact definition to go to, and this should do
TRT.
----
*** New value 'project-relative' for 'xref-file-name-display'.
If chosen, file names in "*xref*" buffers will be displayed relative
to the 'project-root' of the current project, when available.
----
*** Prefix arg of 'xref-goto-xref' quits the "*xref*" buffer.
So typing 'C-u RET' in the "*xref*" buffer quits its window
before navigating to the selected location.
-+++
*** The 'TAB' key binding in "*xref*" buffers is obsolete.
Use 'C-u RET' instead. The 'TAB' binding in "*xref*" buffers is still
supported, but we plan on removing it in a future version; at that
time, the command 'xref-quit-and-goto-xref' will no longer have a key
binding in 'xref--xref-buffer-mode-map'.
----
*** New user option 'etags-xref-prefer-current-file'.
When non-nil, matches for identifiers in the file visited by the
current buffer will be shown first in the "*xref*" buffer.
-+++
*** The etags Xref backend now honors 'tags-apropos-additional-actions'.
You can customize it to augment the output of 'xref-find-apropos',
like it affected the output of 'tags-apropos', which is obsolete since
@@ -2712,7 +2386,6 @@ Emacs 25.1.
** Battery
----
*** UPower is now the default battery status backend when available.
UPower support via the function 'battery-upower' was added in Emacs
26.1, but was disabled by default. It is now the default value of
@@ -2722,7 +2395,6 @@ service. The user options 'battery-upower-device' and
whether to respond to status change notifications in addition to
polling, respectively.
----
*** A richer syntax can be used to format battery status information.
The user options 'battery-mode-line-format' and
'battery-echo-area-format' now support the full formatting syntax of
@@ -2730,9 +2402,8 @@ the function 'format-spec' documented under node "(elisp) Custom Format
Strings". The new syntax includes specifiers for padding and
truncation, amongst other things.
-** bug-reference.el
+** Bug Reference
----
*** Bug reference mode uses auto-setup.
If 'bug-reference-mode' or 'bug-reference-prog-mode' have been
activated, their respective hook has been run, and both
@@ -2747,19 +2418,16 @@ variables 'bug-reference-setup-from-vc-alist',
'bug-reference-setup-from-mail-alist', and
'bug-reference-setup-from-irc-alist'.
-** HTML Mode
+** HTML mode
----
*** A new skeleton for adding relative URLs has been added.
It's bound to the 'C-c C-c f' keystroke, and prompts for a local file
name.
** Widget
-+++
*** 'widget-choose' now supports menus in extended format.
----
*** The 'editable-list' widget now supports moving items up and down.
You can now move items up and down by deleting and then reinserting
them, using the 'DEL' and 'INS' buttons respectively. This is useful
@@ -2768,62 +2436,50 @@ a list.
** Diff
----
*** New face 'diff-changed-unspecified'.
This is used to highlight "changed" lines (those marked with '!') in
context diffs, when 'diff-use-changed-face' is non-nil.
----
*** New 'diff-mode' font locking face 'diff-error'.
This face is used for error messages from 'diff'.
-+++
*** New command 'diff-refresh-hunk'.
This new command (bound to 'C-c C-l') regenerates the current hunk.
-** thing-at-point
+** Thing at point
-+++
*** New 'thing-at-point' target: 'existing-filename'.
This is like 'filename', but is a full path, and is nil if the file
doesn't exist.
-+++
*** New 'thing-at-point' target: 'string'.
If point is inside a string, it returns that string.
-+++
*** New variable 'thing-at-point-provider-alist'.
This allows mode-specific alterations to how 'thing-at-point' works.
----
-*** thing-at-point now respects fields.
+*** 'thing-at-point' now respects fields.
'thing-at-point' (and all functions that use it, like
'symbol-at-point') will narrow to the current field (if any) before
trying to identify the thing at point.
----
*** New function 'thing-at-mouse'.
This is like 'thing-at-point', but uses the mouse event position instead.
-** Image-Dired
+** Image Dired
-+++
*** New user option 'image-dired-thumb-visible-marks'.
If non-nil (the default), use the new face 'image-dired-thumb-mark'
for marked images.
----
*** New command 'image-dired-delete-marked'.
----
*** 'image-dired-mouse-toggle-mark' is now sensitive to the active region.
If the region is active, this command now toggles Dired marks of all
the thumbnails in the region.
** Flymake mode
-+++
*** New command 'flymake-show-project-diagnostics'.
This lists all diagnostics for buffers in the currently active
project. The listing is similar to the one obtained by
@@ -2832,7 +2488,6 @@ project-relative file name. For backends which support it,
'flymake-show-project-diagnostics' also lists diagnostics for files
that have not yet been visited.
-+++
*** New user options to customize Flymake's mode-line.
The new user option 'flymake-mode-line-format' is a mix of strings and
symbols like 'flymake-mode-line-title', 'flymake-mode-line-exception'
@@ -2843,7 +2498,6 @@ like 'flymake-mode-line-error-counter',
** Time
----
*** 'display-time-world' has been renamed to 'world-clock'.
'world-clock' creates a buffer with an updating time display using
several time zones. It is hoped that the new names are more
@@ -2866,45 +2520,37 @@ The following user options have been renamed:
The old names are now obsolete.
----
*** 'world-clock-mode' can no longer be turned on interactively.
Use 'world-clock' to turn on that mode.
** Python mode
----
*** New user option 'python-forward-sexp-function'.
This allows the user easier customization of whether to use block-based
navigation or not.
----
*** 'python-shell-interpreter' now defaults to python3 on systems with python3.
----
*** 'C-c C-r' can now be used on arbitrary regions.
The command previously extended the start of the region to the start
of the line, but will now actually send the marked region, as
documented.
-** Ruby Mode
+** Ruby mode
----
*** 'ruby-use-smie' is declared obsolete.
SMIE is now always enabled and 'ruby-use-smie' only controls whether
indentation is done using SMIE or with the old ad-hoc code.
----
*** Indentation has changed when 'ruby-align-chained-calls' is non-nil.
This previously used to align subsequent lines with the last sibling,
but it now aligns with the first sibling (which is the preferred style
in Ruby).
-** CPerl Mode
+** CPerl mode
----
*** New face 'perl-heredoc', used for heredoc elements.
----
*** The command 'cperl-set-style' offers the new value "PBP".
This value customizes Emacs to use the style recommended in Damian
Conway's book "Perl Best Practices" for indentation and formatting
@@ -2912,32 +2558,27 @@ of conditionals.
** Perl mode
----
*** New face 'perl-non-scalar-variable'.
This is used to fontify non-scalar variables.
-** Octave Mode
+** Octave mode
-+++
*** Line continuations in double-quoted strings now use a backslash.
Typing 'C-M-j' (bound to 'octave-indent-new-comment-line') now follows
the behavior introduced in Octave 3.8 of using a backslash as a line
continuation marker within double-quoted strings, and an ellipsis
everywhere else.
-+++
** EasyPG
GPG key servers can now be queried for keys with the
-'M-x epa-search-keys' command. Keys can then be added to your
+'epa-search-keys' command. Keys can then be added to your
personal key ring.
** Etags
-+++
*** Etags now supports the Mercury programming language.
See https://mercurylang.org.
-+++
*** Etags command line option '--declarations' now has Mercury-specific behavior.
All Mercury declarations are tagged by default. However, for
compatibility with 'etags' support for Prolog, predicates and
@@ -2946,9 +2587,8 @@ invoked with the '--declarations' command-line option.
** Comint
-+++
*** Support for OSC escape sequences.
-Adding the new 'comint-osc-process-output' to
+Adding the new function 'comint-osc-process-output' to
'comint-output-filter-functions' enables the interpretation of OSC
("Operating System Command") escape sequences in comint buffers. By
default, only OSC 8, for hyperlinks, and OSC 7, for directory
@@ -2956,18 +2596,15 @@ tracking, are acted upon. Adding more entries to
'comint-osc-handlers' allows a customized treatment of further escape
sequences.
-+++
*** 'comint-delete-output' can now save deleted text in the kill-ring.
Interactively, 'C-u C-c C-o' triggers this new optional behavior.
-** ansi-color.el
+** ANSI color
----
*** Colors are now defined by faces.
ANSI SGR codes now have corresponding faces to describe their
appearance, e.g. 'ansi-color-bold'.
----
*** Support for "bright" color codes.
"Bright" ANSI color codes are now displayed when applying ANSI color
filters using the color values defined by the faces
@@ -2980,47 +2617,39 @@ non-nil.
*** Starting with Emacs 28.1 and ERC 5.4, see the ERC-NEWS file for
user-visible changes in ERC.
-** xwidget-webkit mode
+** Xwidget Webkit mode
----
*** New xwidget commands.
'xwidget-webkit-uri' (return the current URL), 'xwidget-webkit-title'
(return the current title), and 'xwidget-webkit-goto-history' (goto a
point in history).
----
*** Downloading files from xwidget-webkit is now supported.
The new user option 'xwidget-webkit-download-dir' says where to download to.
----
*** New command 'xwidget-webkit-clone-and-split-below'.
Open a new window below displaying the current URL.
----
*** New command 'xwidget-webkit-clone-and-split-right'.
Open a new window to the right displaying the current URL.
----
*** Pixel-based scrolling.
The 'xwidget-webkit-scroll-up', 'xwidget-webkit-scroll-down' commands
now supports scrolling arbitrary pixel values. It now treats the
optional 2nd argument as the pixel values to scroll.
----
*** New commands for scrolling.
The new commands 'xwidget-webkit-scroll-up-line',
'xwidget-webkit-scroll-down-line', 'xwidget-webkit-scroll-forward',
'xwidget-webkit-scroll-backward' can be used to scroll webkit by the
height of lines or width of chars.
----
*** New user option 'xwidget-webkit-bookmark-jump-new-session'.
When non-nil, use a new xwidget webkit session after bookmark jump.
Otherwise, it will use 'xwidget-webkit-last-session'.
** Checkdoc
----
*** No longer warns about command substitutions by default.
Checkdoc used to warn about "too many command substitutions" (as in
"\\[foo-command]"), even if you only used ten of them in a docstring.
@@ -3029,19 +2658,16 @@ substitutions before it becomes a performance issue, so this warning
is now disabled by default. To re-enable this warning, customize the
user option 'checkdoc-max-keyref-before-warn'.
----
*** New user option 'checkdoc-column-zero-backslash-before-paren'.
Checkdoc warns if there is a left parenthesis in column zero of a
documentation string. That warning can now be disabled by customizing
this new user option to nil. This is useful if you don't expect
your code to be edited with an Emacs older than version 27.1.
----
*** Now checks the prompt format for 'yes-or-no-p'.
In addition to verifying the format of the prompt for 'y-or-n-p',
checkdoc will now check the format of 'yes-or-no-p'.
----
*** New command 'checkdoc-dired'.
This can be used to run checkdoc on files from a Dired buffer.
@@ -3053,105 +2679,83 @@ this warning therefore mostly led to false positives.
** Enriched mode
----
*** 'C-a' is by default no longer bound to 'beginning-of-line-text'.
This is so 'C-a' works as in other modes, and in particular holding
Shift while typing 'C-a', i.e. 'C-S-a', will now highlight the text.
** Gravatar
----
*** New user option 'gravatar-service' for host to query for gravatars.
-Defaults to 'libravatar', with 'unicornify' and 'gravatar' as options.
+Defaults to 'gravatar', with 'unicornify' and 'libravatar' as options.
** MH-E mail handler for Emacs
Functions and variables related to handling junk mail have been
renamed to not associate color with sender quality.
-+++
*** New names for mh-junk interactive functions.
Function 'mh-junk-whitelist' is renamed 'mh-junk-allowlist'.
Function 'mh-junk-blacklist' is renamed 'mh-junk-blocklist'.
-+++
*** New binding for 'mh-junk-allowlist'.
The key binding for 'mh-junk-allowlist' is changed from 'J w' to 'J a'.
The old binding is supported but warns that it is obsolete.
-+++
*** New names for some hooks.
'mh-whitelist-msg-hook' is renamed 'mh-allowlist-msg-hook'.
'mh-blacklist-msg-hook' is renamed 'mh-blocklist-msg-hook'.
-+++
*** New names for some user options.
User option 'mh-whitelist-preserves-sequences-flag' is renamed
'mh-allowlist-preserves-sequences-flag'.
-+++
*** New names for some faces.
Face 'mh-folder-blacklisted' is renamed 'mh-folder-blocklisted'.
Face 'mh-folder-whitelisted' is renamed 'mh-folder-allowlisted'.
** Rcirc
-+++
*** rcirc now supports SASL authentication.
----
*** #emacs on Libera.chat has been added to 'rcirc-server-alist'.
----
*** rcirc connects asynchronously.
----
*** Integrate formatting into 'rcirc-send-string'.
The function now accepts a variable number of arguments.
-+++
*** Deprecate 'rcirc-command' in favor of 'rcirc-define-command'.
The new macro handles multiple and optional arguments.
----
*** Add basic IRCv3 support.
This includes support for the capabilities: 'server-time', 'batch',
'message-ids', 'invite-notify', 'multi-prefix' and 'standard-replies'.
----
*** Add mouse property support to 'rcirc-track-minor-mode'.
----
*** Improve support for IRC markup codes.
----
*** Check 'auth-sources' for server passwords.
-+++
*** Implement repeated reconnection strategy.
See 'rcirc-reconnect-attempts'.
** MPC
----
*** New command 'mpc-goto-playing-song'.
This command, bound to 'o' in any 'mpc-mode' buffer, moves point to
the currently playing song in the "*MPC-Songs*" buffer.
----
*** New user option 'mpc-cover-image-re'.
If non-nil, it is a regexp that should match a valid cover image.
** Miscellaneous
----
*** 'shell-script-mode' now supports 'outline-minor-mode'.
The outline headings have lines that start with "###".
----
*** fileloop will now skip missing files instead of signalling an error.
----
*** 'tabulated-list-mode' can now restore original display order.
Many commands (like 'C-x C-b') are derived from 'tabulated-list-mode',
and that mode allows the user to sort on any column. There was
@@ -3159,73 +2763,58 @@ previously no easy way to get back to the original displayed order
after sorting, but giving a -1 numerical prefix to the sorting command
will now restore the original order.
----
*** 'M-left' and 'M-right' now move between columns in 'tabulated-list-mode'.
----
*** New variable 'hl-line-overlay-priority'.
This can be used to change the priority of the hl-line overlays.
-+++
*** New command 'mailcap-view-file'.
This command will open a viewer based on the file type, as determined
by "~/.mailcap" and related files and variables.
----
*** New user option 'remember-diary-regexp'.
----
*** New user option 'remember-text-format-function'.
----
*** New user option 'authinfo-hide-elements'.
This can be set to nil to inhibit hiding passwords in ".authinfo" files.
----
*** 'hexl-mode' scrolling commands now heed 'next-screen-context-lines'.
Previously, 'hexl-scroll-down' and 'hexl-scroll-up' would scroll
up/down an entire window, but they now work more like the standard
scrolling commands.
----
*** New user option 'bibtex-unify-case-function'.
This new option allows the user to customize how case is converted
when unifying entries.
----
*** The user option 'bibtex-maintain-sorted-entries' now permits
user-defined sorting schemes.
----
*** New user option 'reveal-auto-hide'.
If non-nil (the default), revealed text is automatically hidden when
-point leaves the text. If nil, the text is not hidden again. Instead
-'M-x reveal-hide-revealed' can be used to hide all the revealed text.
+point leaves the text. If nil, the text is not hidden again. Instead the
+command 'reveal-hide-revealed' can be used to hide all the revealed text.
----
*** New user option 'ffap-file-name-with-spaces'.
If non-nil, 'find-file-at-point' and friends will try to guess more
expansively to identify a file name with spaces. Default value is
nil.
----
*** Two new commands for centering in 'doc-view-mode'.
The new commands 'doc-view-center-page-horizontally' (bound to 'c h')
and 'doc-view-center-page-vertically' (bound to 'c v') center the page
horizontally and vertically, respectively.
----
*** 'tempo-define-template' can now re-assign templates to tags.
Previously, assigning a new template to an already defined tag had no
effect.
----
*** The width of the buffer-name column in 'list-buffers' is now dynamic.
The width now depends on the width of the window, but will never be
wider than the length of the longest buffer name, except that it will
never be narrower than 19 characters.
-+++
*** New diary sexp 'diary-offset'.
It offsets another diary sexp by a number of days. This is useful
when for example your organization has a committee meeting two days
@@ -3233,21 +2822,17 @@ after every monthly meeting which takes place on the third Thursday,
or if you would like to attend a virtual meeting scheduled in a
different timezone causing a difference in the date.
----
*** The old non-SMIE indentation of 'sh-mode' has been removed.
----
*** 'mspools-show' is now autoloaded.
----
*** Loading dunnet.el in batch mode doesn't start the game any more.
-Instead you need to do "emacs -f dun-batch" to start the game in
+Instead you need to do "emacs --batch -f dunnet" to start the game in
batch mode.
* New Modes and Packages in Emacs 28.1
-+++
** New mode 'repeat-mode' to allow shorter key sequences.
Type 'M-x repeat-mode' to enable this mode. You can then type
'C-x u u' instead of 'C-x u C-x u' to undo many changes, 'C-x o o'
@@ -3270,10 +2855,9 @@ window navigation direction with 'C-x o M-- o o' or to set a new step
with 'C-x { C-5 { { {', which will set the window resizing step to 5
columns.
-'M-x describe-repeat-maps' will display a buffer showing
+Command 'describe-repeat-maps' will display a buffer showing
which commands are repeatable in 'repeat-mode'.
----
** New themes 'modus-vivendi' and 'modus-operandi'.
These themes are designed to conform with the highest standard for
color-contrast accessibility (WCAG AAA). You can load either of them
@@ -3289,14 +2873,12 @@ This is a mode for searching a RFC 2229 dictionary server.
the mouse in 'dictionary-tooltip-dictionary' (which must be customized
first).
----
** Lisp Data mode
The new command 'lisp-data-mode' enables a major mode for buffers
composed of Lisp symbolic expressions that do not form a computer
program. The ".dir-locals.el" file is automatically set to use this
mode, as are other data files produced by Emacs.
-+++
** New global mode 'global-goto-address-mode'.
This will enable 'goto-address-mode' in all buffers.
@@ -3310,7 +2892,6 @@ similar to prefix arguments, but are more flexible and discoverable.
This library can create, query, navigate and display hierarchical
structures.
----
** New major mode for displaying the "etc/AUTHORS" file.
This new 'etc-authors-mode' provides font-locking for displaying the
"etc/AUTHORS" file from the Emacs distribution, and not much else.
@@ -3318,13 +2899,11 @@ This new 'etc-authors-mode' provides font-locking for displaying the
* Incompatible Lisp Changes in Emacs 28.1
-+++
** Emacs now prints a backtrace when signaling an error in batch mode.
This makes debugging Emacs Lisp scripts run in batch mode easier. To
get back the old behavior, set the new variable
'backtrace-on-error-noninteractive' to a nil value.
----
** Some floating-point numbers are now handled differently by the Lisp reader.
In previous versions of Emacs, numbers with a trailing dot and an exponent
were read as integers and the exponent ignored: 2.e6 was interpreted as the
@@ -3332,28 +2911,24 @@ integer 2. Such numerals are now read as floats with the exponent included:
2.e6 is now read as the floating-point value 2000000.0.
That is, '(read-from-string "1.e3")' => '(1000.0 . 4)' now.
----
** 'equal' no longer examines some contents of window configurations.
Instead, it considers window configurations to be equal only if they
are 'eq'. To compare contents, use 'compare-window-configurations'
instead. This change helps fix a bug in 'sxhash-equal', which returned
incorrect hashes for window configurations and some other objects.
-+++
** The 'lexical-binding' local variable is always enabled.
Previously, if 'enable-local-variables' was nil, a 'lexical-binding'
local variable would not be heeded. This has now changed, and a file
with a 'lexical-binding' cookie is always heeded. To revert to the
old behavior, set 'permanently-enabled-local-variables' to nil.
-+++
** '&rest' in argument lists must always be followed by a variable name.
Omitting the variable name after '&rest' was previously tolerated in
some cases but not consistently so; it could lead to crashes or
outright wrong results. Since the utility was marginal at best, it is
now an error to omit the variable.
----
** 'kill-all-local-variables' has changed how it handles non-symbol hooks.
The function is documented to eliminate all buffer-local bindings
except variables with a 'permanent-local' property, or hooks that
@@ -3361,14 +2936,12 @@ have elements with a 'permanent-local-hook' property. In addition, it
would also keep lambda expressions in hooks sometimes. The latter has
now been changed: The function will now also remove these.
-+++
** Temporary buffers no longer run certain buffer hooks.
The macros 'with-temp-buffer' and 'with-temp-file' no longer run the
hooks 'kill-buffer-hook', 'kill-buffer-query-functions', and
'buffer-list-update-hook' for the temporary buffers they create. This
avoids slowing them down when a lot of these hooks are defined.
-+++
** New face 'child-frame-border' and frame parameter 'child-frame-border-width'.
The face and width of child frames borders can now be determined
separately from those of normal frames. To minimize backward
@@ -3377,7 +2950,6 @@ parameter will fall back to using 'internal-border-width'. However,
the new 'child-frame-border' face does constitute a breaking change
since child frames' borders no longer use the 'internal-border' face.
----
** 'run-at-time' now tries harder to implement the t TIME parameter.
If TIME is t, the timer runs at an integral multiple of REPEAT.
(I.e., if given a REPEAT of 60, it'll run at 08:11:00, 08:12:00,
@@ -3388,18 +2960,15 @@ has now changed, and the timer code now recomputes the integral
multiple every time it runs, which means that if the laptop wakes at
08:16:43, it'll fire at that time, but then at 08:17:00, 08:18:00...
----
** 'parse-partial-sexp' now signals an error if TO is smaller than FROM.
Previously, this would lead to the function interpreting FROM as TO and
vice versa, which would be confusing when passing in OLDSTATE, which
refers to the old state at FROM.
-+++
** 'global-mode-string' constructs should end with a space.
This was previously not formalized, which led to combinations of modes
displaying data "smushed together" on the mode line.
-+++
** 'overlays-in' now handles zero-length overlays slightly differently.
Previously, zero-length overlays at the end of the buffer were included
in the result (if the region queried for stopped at that position).
@@ -3407,7 +2976,6 @@ The same was not the case if the buffer had been narrowed to exclude
the real end of the buffer. This has now been changed, and
zero-length overlays at 'point-max' are always included in the results.
----
** 'replace-match' now runs modification hooks slightly later.
The function is documented to leave point after the replacement text,
but this was not always the case if a modification hook inserted text
@@ -3416,28 +2984,23 @@ point where the end of the inserted text would have been before the
hook ran. 'replace-match' now always leaves point after the
replacement text.
-+++
** 'completing-read-default' sets completion variables buffer-locally.
'minibuffer-completion-table' and related variables are now set buffer-locally
in the minibuffer instead of being set via a global let-binding.
----
** XML serialization functions now reject invalid characters.
Previously, 'xml-print' would produce invalid XML when given a string
with characters that are not valid in XML (see
https://www.w3.org/TR/xml/#charsets). Now it rejects such strings.
----
** JSON
----
*** JSON number parsing is now stricter.
Numbers with a leading plus sign, leading zeros, or a missing integer
component are now rejected by 'json-read' and friends. This makes
them more compliant with the JSON specification and consistent with
the native JSON parsing functions.
----
*** JSON functions support the semantics of RFC 8259.
The JSON functions 'json-serialize', 'json-insert',
'json-parse-string', and 'json-parse-buffer' now implement some of the
@@ -3445,7 +3008,6 @@ semantics of RFC 8259 instead of the earlier RFC 4627. In particular,
these functions now accept top-level JSON values that are neither
arrays nor objects.
----
*** Some JSON encoding functions are now obsolete.
The functions 'json-encode-number', 'json-encode-hash-table',
'json-encode-key', and 'json-encode-list' are now obsolete.
@@ -3455,7 +3017,6 @@ used instead. Uses of 'json-encode-list' should be changed to call
one of 'json-encode', 'json-encode-alist', 'json-encode-plist', or
'json-encode-array' instead.
-+++
*** Native JSON functions now signal an error if libjansson is unavailable.
This affects 'json-serialize', 'json-insert', 'json-parse-string',
and 'json-parse-buffer'. This can happen if Emacs was compiled with
@@ -3463,148 +3024,117 @@ libjansson, but the DLL cannot be found and/or loaded by Emacs at run
time. Previously, Emacs would display a message and return nil in
these cases.
-+++
** The use of positional arguments in 'define-minor-mode' is obsolete.
These were actually rendered obsolete in Emacs 21 but were never
marked as such.
----
** 'pcomplete-ignore-case' is now an obsolete alias of 'completion-ignore-case'.
-+++
** 'completions-annotations' face is not used when the caller puts own face.
This affects the suffix specified by completion 'annotation-function'.
-+++
** An active minibuffer now has major mode 'minibuffer-mode'.
This is instead of the erroneous 'minibuffer-inactive-mode' it
formerly had.
----
** 'make-text-button' no longer modifies text properties of its first argument.
When its first argument is a string, 'make-text-button' no longer
modifies the string's text properties; instead, it uses and returns
a copy of the string. This helps avoid trouble when strings are
shared or constants.
-+++
** Some properties from completion tables are now preserved.
If 'minibuffer-allow-text-properties' is non-nil, doing completion
over a table of strings with properties will no longer remove all the
properties before returning. This affects things like 'completing-read'.
----
** 'dns-query' now consistently uses Lisp integers to represent integers.
Formerly it made an exception for integer components of SOA records,
because SOA serial numbers can exceed fixnum ranges on 32-bit platforms.
Emacs now supports bignums so this old glitch is no longer needed.
-+++
** The '&define' keyword in an Edebug specification now disables backtracking.
The implementation was buggy, and multiple '&define' forms in an '&or'
form should be exceedingly rare. See the Info node "(elisp) Backtracking" in
the Emacs Lisp reference manual for background.
-+++
** The error 'ftp-error' belongs also to category 'remote-file-error'.
-+++
** The WHEN argument of 'make-obsolete' and related functions is mandatory.
The use of those functions without a WHEN argument was marked obsolete
back in Emacs 23.1. The affected functions are: 'make-obsolete',
'define-obsolete-function-alias', 'make-obsolete-variable',
'define-obsolete-variable-alias'.
-+++
** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'.
----
** Some functions are no longer considered safe by 'unsafep':
'replace-regexp-in-string', 'catch', 'throw', 'error', 'signal'
and 'play-sound-file'.
----
** 'sql-*-statement-starters' are no longer user options.
These variables describe facts about the SQL standard and
product-specific additions. There should be no need for users to
customize them.
----
** Some locale-related variables have been removed.
The Lisp variables 'previous-system-messages-locale' and
'previous-system-time-locale' have been removed, as they were created
by mistake and were not useful to Lisp code.
----
** Function 'lm-maintainer' is replaced with 'lm-maintainers'.
The former is now declared obsolete.
-+++
** facemenu.el is no longer preloaded.
To use functions/variables from the package, you now have to say
'(require 'facemenu)' or similar.
----
** 'facemenu-color-alist' is now obsolete, and is not used.
----
** The variable 'keyboard-type' is obsolete and not dynamically scoped any more.
-+++
** The 'values' variable is now obsolete.
Using it just contributes to the growth of the Emacs memory
footprint.
----
** The 'load-dangerous-libraries' variable is now obsolete.
It was used to allow loading Lisp libraries compiled by XEmacs, a
modified version of Emacs which is no longer actively maintained.
This is no longer supported, and setting this variable has no effect.
-+++
** The macro 'with-displayed-buffer-window' is now obsolete.
Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
----
** The rfc2368.el library is now obsolete.
Use rfc6068.el instead. The main difference is that
'rfc2368-parse-mailto-url' and 'rfc2368-unhexify-string' assumed that
the strings were all-ASCII, while 'rfc6068-parse-mailto-url' and
'rfc6068-unhexify-string' parse UTF-8 strings.
----
** The inversion.el library is now obsolete.
----
** The metamail.el library is now obsolete.
** Edebug changes
----
*** 'get-edebug-spec' is obsolete, replaced by 'edebug-get-spec'.
-+++
*** The spec operator ':name NAME' is obsolete, use '&name' instead.
-+++
*** The spec element 'function-form' is obsolete, use 'form' instead.
-+++
*** New function 'def-edebug-elem-spec' to define Edebug spec elements.
These used to be defined with 'def-edebug-spec' thus conflating the
two name spaces, which lead to name collisions.
The use of 'def-edebug-spec' to define Edebug spec elements is
declared obsolete.
----
** The sb-image.el library is now obsolete.
This was a compatibility kludge which is no longer needed.
----
** Some libraries obsolete since Emacs 23 have been removed:
ledit.el, lmenu.el, lucid.el and old-whitespace.el.
----
** Some functions and variables obsolete since Emacs 23 have been removed:
'GOLD-map', 'advertised-xscheme-send-previous-expression',
'allout-init', 'bookmark-jump-noselect',
@@ -3676,20 +3206,16 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
'vcursor-toggle-vcursor-map', 'w32-focus-frame', 'w32-select-font',
'wisent-lex-make-token-table'.
----
** Some functions and variables obsolete since Emacs 22 have been removed:
'erc-current-network', 'gnus-article-hide-pgp-hook',
'gnus-inews-mark-gcc-as-read', 'gnus-treat-display-xface',
'gnus-treat-strip-pgp', 'nnmail-spool-file'.
----
** The obsolete function 'thread-alive-p' has been removed.
----
** The variable 'force-new-style-backquotes' has been removed.
This removes the final remaining trace of old-style backquotes.
----
** Some obsolete variable and function aliases in dbus.el have been removed.
In Emacs 24.3, the variable 'dbus-event-error-hooks' was renamed to
'dbus-event-error-functions' and the function
@@ -3697,7 +3223,6 @@ In Emacs 24.3, the variable 'dbus-event-error-hooks' was renamed to
The old names, which were kept as obsolete aliases of the new names,
have now been removed.
----
** 'find-function-source-path' renamed and re-documented.
The 'find-function' command (and various related commands) were
documented to respect 'find-function-source-path', and to search for
@@ -3710,10 +3235,9 @@ still being used by 'find-library' and related commands, so the
user option has been renamed to 'find-library-source-path', and
'find-function-source-path' is now an obsolete variable alias.
----
** The macro 'vc-call' no longer evaluates its second argument twice.
-** Xref migrated from EIEIO to cl-defstruct for its core objects.
+** Xref migrated from EIEIO to 'cl-defstruct' for its core objects.
This means that 'oref' and 'with-slots' no longer works on them, and
'make-instance' can no longer be used to create those instances (which
wasn't recommended anyway). Packages should restrict themselves to
@@ -3730,7 +3254,6 @@ use with "match items" without adding EIEIO as a dependency.
* Lisp Changes in Emacs 28.1
-+++
** The 'interactive' syntax has been extended to allow listing applicable modes.
Forms like '(interactive "p" dired-mode)' can be used to annotate the
commands as being applicable for modes derived from 'dired-mode',
@@ -3738,10 +3261,9 @@ or if the mode is a minor mode, when the current buffer has that
minor mode activated. Note that using this form will create byte code
that is not compatible with byte code in previous Emacs versions.
Also note that by default these annotations have no effect, unless the
-new option 'read-extended-command-predicate' option is customized to call
-'command-completion-default-include-p' or a similar function.
+new user option 'read-extended-command-predicate' option is customized
+to call 'command-completion-default-include-p' or a similar function.
-+++
** New 'declare' forms to control completion of commands in 'M-x'.
'(declare (completion PREDICATE))' can be used as a general predicate
to say whether the command should be considered a completion candidate
@@ -3754,80 +3276,67 @@ MODE..., or, if it's a minor mode, when that minor mode is enabled in
the current buffer.
Note that these forms will only have their effect if the
-'read-extended-command-predicate' option is customized to call
+'read-extended-command-predicate' user option is customized to call
'command-completion-default-include-p' or a similar function. The
default value of 'read-extended-command-predicate' is nil, which means
no commands that match what you have typed are excluded from being
completion candidates.
-+++
-** 'define-minor-mode' now takes an ':interactive' argument.
+** 'define-minor-mode' now takes an ':interactive' argument.
This can be used for specifying which modes this minor mode is meant
for, or to make the new minor mode non-interactive. The default value
is t.
-+++
** 'define-derived-mode' now takes an ':interactive' argument.
This can be used to control whether the defined mode is a command
or not, and is useful when defining commands that aren't meant to be
used by users directly.
-+++
** 'define-globalized-minor-mode' now takes a ':predicate' parameter.
This can be used to control which major modes the minor mode should be
used in.
-+++
** 'condition-case' now allows for a success handler.
It is written as '(:success BODY...)' where BODY is executed
whenever the protected form terminates without error, with the
specified variable bound to the value of the protected form.
-+++
** New function 'benchmark-call' to measure the execution time of a function.
Additionally, the number of repetitions can be expressed as a minimal duration
in seconds.
-+++
** The value thrown to the 'exit' label can now be a function.
This is in addition to values t or nil. If the value is a function,
the command loop will call it with zero arguments before returning.
-+++
** The behavior of 'format-spec' is now closer to that of 'format'.
In order for the two functions to behave more consistently,
'format-spec' now pads and truncates based on string width rather than
length, and also supports format specifications that include a
truncating precision field, such as "%.2a".
----
** 'defvar' detects the error of defining a variable currently lexically bound.
Such mixes are always signs that the outer lexical binding was an
error and should have used dynamic binding instead.
----
** New variable 'inhibit-mouse-event-check'.
If bound to non-nil, a command with '(interactive "e")' doesn't signal
an error when invoked by input event that is not a mouse click (e.g.,
a key sequence).
----
** New variable 'redisplay-skip-initial-frame' to enable batch redisplay tests.
Setting it to nil forces the redisplay to do its job even in the
initial frame used in batch mode.
-+++
** Doc strings can now link to customization groups.
Text like "customization group `whitespace'" will be made into a
button. When clicked, it will open a Custom buffer displaying that
customization group.
-+++
** Doc strings can now link to man pages.
Text like "man page `chmod(1)'" will be made into a button. When
clicked, it will open a Man mode buffer displaying that man page.
-+++
** Buffers can now be created with certain hooks disabled.
The functions 'get-buffer-create' and 'generate-new-buffer' accept a
new optional argument INHIBIT-BUFFER-HOOKS. If non-nil, the new
@@ -3836,78 +3345,63 @@ buffer does not run the hooks 'kill-buffer-hook',
avoids slowing down internal or temporary buffers that are never
presented to users or passed on to other applications.
-+++
** New command 'make-directory-autoloads'.
This does the same as the old command 'update-directory-autoloads',
but has different semantics: Instead of passing in the output file via
the dynamically bound 'generated-autoload-file' variable, the output
-file is now a explicit parameter.
+file is now an explicit parameter.
----
** Dragging a file into Emacs pushes the file name onto 'file-name-history'.
----
** The 'easymenu' library is now preloaded.
----
** The 'iso-transl' library is now preloaded.
This means that keystrokes like 'Alt-[' are defined by default,
instead of only becoming available after doing (for instance)
'C-x 8 <letter>'.
----
** ':safe' settings in 'defcustom' are now propagated to the loaddefs files.
-+++
** New ':type' for 'defcustom' for nonnegative integers.
The new 'natnum' type can be used for options that should be
nonnegative integers.
-+++
** ERT can now output more verbose test failure reports.
If the 'EMACS_TEST_VERBOSE' environment variable is set, failure
summaries will include the failing condition.
** Byte compiler changes
-+++
*** New byte-compiler check for missing dynamic variable declarations.
It is meant as an (experimental) aid for converting Emacs Lisp code
to lexical binding, where dynamic (special) variables bound in one
-file can affect code in another. For details, see the manual section
+file can affect code in another. For details, see the Info node
"(elisp) Converting to Lexical Binding".
-+++
-*** 'byte-recompile-directory' can now compile symlinked ".el" files.
+*** 'byte-recompile-directory' can now compile symlinked "*.el" files.
This is achieved by giving a non-nil FOLLOW-SYMLINKS parameter.
----
*** The byte-compiler now warns about too wide documentation strings.
By default, it will warn if a documentation string is wider than the
largest of 'byte-compile-docstring-max-column' or 'fill-column'
characters.
-+++
*** 'byte-compile-file' optional argument LOAD is now obsolete.
To load the file after byte-compiling, add a call to 'load' from Lisp
or use 'M-x emacs-lisp-byte-compile-and-load' interactively.
** Macroexp
----
*** New function 'macroexp-file-name' to know the name of the current file.
----
*** New function 'macroexp-compiling-p' to know if we're compiling.
----
*** New function 'macroexp-warn-and-return' to help emit warnings.
This used to be named 'macroexp--warn-and-return' and has proved useful
and well-behaved enough to lose the "internal" marker.
** map.el
----
*** Alist keys are now consistently compared with 'equal' by default.
Until now, 'map-elt' and 'map-delete' compared alist keys with 'eq' by
default. They now use 'equal' instead, for consistency with
@@ -3917,14 +3411,11 @@ default. They now use 'equal' instead, for consistency with
A pattern like '(map :sym)' binds the map's value for ':sym' to 'sym',
equivalent to '(map (:sym sym))'.
----
*** The function 'map-copy' now uses 'copy-alist' on alists.
This is a slightly deeper copy than the previous 'copy-sequence'.
----
*** The function 'map-contains-key' now supports plists.
----
*** More consistent duplicate key handling in 'map-merge-with'.
Until now, 'map-merge-with' promised to call its function argument
whenever multiple maps contained 'eql' keys. However, this did not
@@ -3932,28 +3423,23 @@ always coincide with the keys that were actually merged, which could
be 'equal' instead. The function argument is now called whenever keys
are merged, for greater consistency with 'map-merge' and 'map-elt'.
-** pcase
+** Pcase
-+++
*** The 'or' pattern now binds the union of the vars of its sub-patterns.
If a variable is not bound by the subpattern that matched, it gets bound
to nil. This was already sometimes the case, but it is now guaranteed.
-+++
*** The 'pred' pattern can now take the form '(pred (not FUN))'.
This is like '(pred (lambda (x) (not (FUN x))))' but results
in better code.
----
*** New function 'pcase-compile-patterns' to write other macros.
-+++
*** Added 'cl-type' pattern.
The new 'cl-type' pattern compares types using 'cl-typep', which allows
comparing simple types like '(cl-type integer)', as well as forms like
'(cl-type (integer 0 10))'.
-+++
*** New macro 'pcase-setq'.
This macro is the 'setq' equivalent of 'pcase-let', which allows for
destructuring patterns in a 'setq' form.
@@ -3962,49 +3448,40 @@ destructuring patterns in a 'setq' form.
*** Edebug specification lists can use some new keywords:
-+++
-**** '&interpose SPEC FUN ARGS..' lets FUN control parsing after SPEC.
-More specifically, FUN is called with 'HEAD PF ARGS..' where
+**** '&interpose SPEC FUN ARGS...' lets FUN control parsing after SPEC.
+More specifically, FUN is called with 'HEAD PF ARGS...' where
PF is a parsing function that expects a single argument (the specs to
use) and HEAD is the code that matched SPEC.
-+++
**** '&error MSG' unconditionally aborts the current edebug instrumentation.
-+++
**** '&name SPEC FUN' extracts the current name from the code matching SPEC.
** Dynamic modules changes
-+++
*** Type aliases for module functions and finalizers.
-The module header 'emacs-module.h' now contains type aliases
+The module header "emacs-module.h" now contains type aliases
'emacs_function' and 'emacs_finalizer' for module functions and
finalizers, respectively.
-+++
*** Module functions can now be made interactive.
Use 'make_interactive' to give a module function an interactive
specification.
-+++
*** Module functions can now install an optional finalizer.
The finalizer is called when the function object is garbage-collected.
Use 'set_function_finalizer' to set the finalizer and
'get_function_finalizer' to retrieve it.
-+++
*** Modules can now open a channel to an existing pipe process.
Modules can use the new module function 'open_channel' to do that.
On capable systems, modules can use this functionality to
asynchronously send data back to Emacs.
-+++
*** A new module API 'make_unibyte_string'.
It can be used to create Lisp strings with arbitrary byte sequences
(a.k.a. "raw bytes").
-+++
** Shorthands for Lisp symbols.
Shorthands are a general purpose namespacing system to make Emacs
Lisp's symbol-naming etiquette easier to use. A shorthand is any
@@ -4012,233 +3489,185 @@ symbolic form found in Lisp source that "abbreviates" a symbol's print
name. Among other applications, this feature can be used to avoid
name clashes and namespace pollution by renaming an entire file's
worth of symbols with proper and longer prefixes, without actually
-touching the Lisp source. For details, see the manual section
-"(elisp) Shorthands".
+touching the Lisp source. For details, see the Info node "(elisp)
+Shorthands".
-+++
** New function 'string-search'.
This function takes two string parameters and returns the position of
the first instance of the former string in the latter.
-+++
** New function 'string-replace'.
This function works along the line of 'replace-regexp-in-string', but
it matches on fixed strings instead of regexps, and does not change
the global match state.
-+++
** New function 'ensure-list'.
This function makes a list of its object if it's not a list already.
If it's already a list, the list is returned as is.
-+++
** New function 'split-string-shell-command'.
This splits a shell command string into separate components,
respecting quoting with single ('like this') and double ("like this")
quotes, as well as backslash quoting (like\ this).
-+++
** New function 'string-clean-whitespace'.
This removes whitespace from a string.
-+++
** New function 'string-fill'.
Word-wrap a string so that no lines are longer that a specific length.
-+++
** New function 'string-limit'.
Return (up to) a specific substring length.
-+++
** New function 'string-lines'.
Return a list of strings representing the individual lines in a
string.
-+++
** New function 'string-pad'.
Pad a string to a specific length.
-+++
** New function 'string-chop-newline'.
Remove a trailing newline from a string.
-+++
** New function 'replace-regexp-in-region'.
-+++
** New function 'replace-string-in-region'.
-+++
** New function 'file-name-with-extension'.
This function allows a canonical way to set/replace the extension of a
file name.
-+++
** New function 'file-modes-number-to-symbolic' to convert a numeric
file mode specification into symbolic form.
-+++
** New function 'file-name-concat'.
This appends file name components to a directory name and returns the
result.
-+++
** New function 'file-backup-file-names'.
This function returns the list of file names of all the backup files
for the specified file.
-+++
** New function 'directory-empty-p'.
This predicate tests whether a given file name is an accessible
directory and whether it contains no other directories or files.
-+++
** New function 'buffer-local-boundp'.
This predicate says whether a symbol is bound in a specific buffer.
-+++
** New function 'always'.
This is identical to 'ignore', but returns t instead.
-+++
** New function 'sxhash-equal-including-properties'.
This is identical to 'sxhash-equal' but also accounts for string
properties.
----
** New function 'buffer-line-statistics'.
This function returns some statistics about the line lengths in a buffer.
----
** New function 'color-values-from-color-spec'.
This can be used to parse RGB color specs in several formats and
convert them to a list '(R G B)' of primary color values.
----
** New function 'custom-add-choice'.
This function can be used by modes to add elements to the
'choice' customization type of a variable.
----
** New function 'decoded-time-period'.
It interprets a decoded time structure as a period and returns the
equivalent period in seconds.
-+++
** New function 'dom-print'.
-+++
** New function 'dom-remove-attribute'.
----
** New function 'dns-query-asynchronous'.
It takes the same parameters as 'dns-query', but adds a callback
parameter.
** New function 'garbage-collect-maybe' to trigger GC early.
----
** New function 'get-locale-names'.
This utility function returns a list of names of locales available on
the current system.
-+++
** New function 'insert-into-buffer'.
This inserts the contents of the current buffer into another buffer.
-+++
** New function 'json-available-p'.
This predicate returns non-nil if Emacs is built with libjansson
support, and it is available on the current system.
----
** New function 'mail-header-parse-addresses-lax'.
This takes a comma-separated string and returns a list of mail/name
pairs.
----
** New function 'mail-header-parse-address-lax'.
Parse a string as a mail address-like string.
----
** New function 'make-separator-line'.
Make a string appropriate for usage as a visual separator line.
-+++
** New function 'num-processors'.
Return the number of processors on the system.
-+++
** New function 'object-intervals'.
This function returns a copy of the list of intervals (i.e., text
properties) in the object in question (which must either be a string
or a buffer).
-+++
** New function 'process-lines-ignore-status'.
This is like 'process-lines', but does not signal an error if the
return status is non-zero. 'process-lines-handling-status' has also
been added, and takes a callback to handle the return status.
-+++
** New function 'require-theme'.
This function is like 'require', but searches 'custom-theme-load-path'
instead of 'load-path'. It can be used by Custom themes to load
supporting Lisp files when 'require' is unsuitable.
-+++
** New function 'seq-union'.
This function takes two sequences and returns a list of all elements
that appear in either of them, with no two elements that compare equal
appearing in the result.
-+++
** New function 'syntax-class-to-char'.
This does almost the opposite of 'string-to-syntax' -- it returns the
syntax descriptor (a character) given a raw syntax descriptor (an
integer).
-+++
** New functions 'null-device' and 'path-separator'.
These functions return the connection local value of the respective
variables. This can be used for remote hosts.
-+++
** New predicate functions 'length<', 'length>' and 'length='.
Using these functions may be more efficient than using 'length' (if
the length of a (long) list is being computed just to compare this
length to a number).
-+++
** New macro 'dlet' to dynamically bind variables.
-+++
** New macro 'with-existing-directory'.
This macro binds 'default-directory' to some other existing directory
if 'default-directory' doesn't exist, and then executes the body forms.
-+++
** New variable 'current-minibuffer-command'.
This is like 'this-command', but it is bound recursively when entering
the minibuffer.
-+++
** New variable 'inhibit-interaction' to make user prompts signal an error.
If this is bound to something non-nil, functions like
'read-from-minibuffer', 'read-char' (and related) will signal an
'inhibited-interaction' error.
----
** New variable 'indent-line-ignored-functions'.
This allows modes to cycle through a set of indentation functions
appropriate for those modes.
-+++
** New variable 'print-integers-as-characters' modifies integer printing.
If this variable is non-nil, character syntax is used for printing
numbers when this makes sense, such as '?A' for 65.
-+++
** New variable 'tty-menu-calls-mouse-position-function'.
This controls whether 'mouse-position-function' is called by functions
that retrieve the mouse position when that happens during TTY menu
@@ -4246,47 +3675,39 @@ handling. Lisp programs that set 'mouse-position-function' should
also set this variable non-nil if they are compatible with the tty
menu handling.
-+++
** New variables that hold default buffer names for shell output.
The new constants 'shell-command-buffer-name' and
'shell-command-buffer-name-async' store the default buffer names
for the output of, respectively, synchronous and async shell
commands.
----
** New variables 'read-char-choice-use-read-key' and 'y-or-n-p-use-read-key'.
When non-nil, then functions 'read-char-choice' and 'y-or-n-p'
(respectively) use the function 'read-key' to read a character instead
of using the minibuffer.
-+++
** New variable 'global-minor-modes'.
This variable holds a list of currently enabled global minor modes (as
a list of symbols).
-+++
** New buffer-local variable 'local-minor-modes'.
This permanently buffer-local variable holds a list of currently
enabled non-global minor modes in the current buffer (as a list of
symbols).
-+++
** New completion function 'affixation-function' to add prefix/suffix.
It accepts a list of completions and should return a list where
each element is a list with three elements: a completion,
a prefix string, and a suffix string.
-+++
** New completion function 'group-function' for grouping candidates.
It takes two arguments: a completion candidate and a 'transform' flag.
-+++
** New error symbol 'minibuffer-quit'.
Signaling it has almost the same effect as 'quit' except that it
doesn't cause keyboard macro termination.
-+++
-** New error 'remote-file-error', a subcategory of 'file-error'.
+** New error symbol 'remote-file-error', a subcategory of 'file-error'.
It is signaled if a remote file operation fails due to internal
reasons, and could block Emacs. It does not replace 'file-error'
signals for the usual cases. Timers, process filters and process
@@ -4296,13 +3717,12 @@ against this error.
If such an error occurs, please report this as bug via 'M-x report-emacs-bug'.
Until it is solved you could ignore such errors by performing
- (setq debug-ignored-errors (cons 'remote-file-error debug-ignored-errors))
+ (setq debug-ignored-errors
+ (cons 'remote-file-error debug-ignored-errors))
-+++
-** New macro 'named-let' added to subr-x.el.
+** New macro 'named-let'.
It provides Scheme's "named let" looping construct.
----
** Emacs now attempts to test for high-rate subprocess output more fairly.
When several subprocesses produce output simultaneously at high rate,
Emacs will now by default attempt to service them all in a round-robin
@@ -4311,81 +3731,66 @@ non-nil value to get back the old behavior, whereby after reading
from a subprocess, Emacs would check for output of other subprocesses
in a way that is likely to read from the same process again.
-+++
** 'set-process-buffer' now updates the process mark.
The mark will be set to point to the end of the new buffer.
-+++
** 'unlock-buffer' displays warnings instead of signaling.
Instead of signaling 'file-error' conditions for file system level
errors, the function now calls 'display-warning' and continues as if
the error did not occur.
-+++
** 'read-char-from-minibuffer' and 'y-or-n-p' support 'help-form'.
If you bind 'help-form' to a non-nil value while calling these functions,
then pressing 'C-h' ('help-char') causes the function to evaluate 'help-form'
and display the result.
-+++
** 'read-number' now has its own history variable.
-Additionally, the function now accepts a HIST argument which can be
-used to specify a custom history variable.
+Additionally, the function now accepts an optional HIST argument which
+can be used to specify a custom history variable.
-+++
** 'set-window-configuration' now takes two optional parameters,
-'dont-set-frame' and 'dont-set-miniwindow'. The first of these, when
+DONT-SET-FRAME and DONT-SET-MINIWINDOW. The first of these, when
non-nil, instructs the function not to select the frame recorded in
the configuration. The second prevents the current minibuffer being
replaced by the one stored in the configuration.
----
** 'count-windows' now takes an optional parameter ALL-FRAMES.
The semantics are as with 'walk-windows'.
-+++
** 'truncate-string-ellipsis' now uses '…' by default.
Modes that use 'truncate-string-to-width' with non-nil, non-string
argument ELLIPSIS, will now indicate truncation using '…' when
the selected frame can display it, and using "..." otherwise.
-+++
** 'string-width' now accepts two optional arguments FROM and TO.
This allows calculating the width of a substring without consing a
new string.
-+++
** 'directory-files' now takes an additional COUNT parameter.
The parameter makes 'directory-files' return COUNT first file names
from a directory. If MATCH is also given, the function will return
first COUNT file names that match the expression. The same COUNT
parameter has been added to 'directory-files-and-attributes'.
-+++
** 'count-lines' can now ignore invisible lines.
This is controlled by the optional parameter IGNORE-INVISIBLE-LINES.
----
** 'count-words' now crosses field boundaries.
Originally, 'count-words' would stop counting at the first field
boundary it encountered; now it keeps counting all the way to the
region's (or buffer's) end.
-+++
** File-related APIs can optionally follow symlinks.
The functions 'file-modes', 'set-file-modes', and 'set-file-times' now
have an optional argument specifying whether to follow symbolic links.
-+++
** 'format-seconds' can now be used for sub-second times.
The new optional "," parameter has been added, and
'(format-seconds "%mm %,1ss" 66.4)' will now result in "1m 6.4s".
-+++
** 'parse-time-string' can now parse ISO 8601 format strings.
These have a format like "2020-01-15T16:12:21-08:00".
----
** 'lookup-key' is more allowing when searching for extended menu items.
When looking for a menu item '[menu-bar Foo-Bar]', first try to find
an exact match, then look for the lowercased '[menu-bar foo-bar]'.
@@ -4393,7 +3798,6 @@ It will only try to downcase ASCII characters in the range "A-Z".
This improves backwards-compatibility when converting menus to use
'easy-menu-define'.
----
** 'make-network-process', 'make-serial-process' ':coding' behavior change.
Previously, passing ':coding nil' to either of these functions would
override any non-nil binding for 'coding-system-for-read' and
@@ -4403,92 +3807,73 @@ Emacs depended on the previous behavior; if you really want the
process' coding-system to be nil, use 'set-process-coding-system'
after the process has been created, or pass in ':coding '(nil nil)'.
-+++
** 'open-network-stream' now accepts a ':coding' argument.
This allows specifying the coding systems used by a network process
for encoding and decoding without having to bind
'coding-system-for-{read,write}' or call 'set-process-coding-system'.
-+++
** 'open-network-stream' can now take a ':capability-command' that's a function.
The function is called with the greeting from the server as its only
parameter, and allows sending different TLS capability commands to the
server based on that greeting.
-+++
** 'open-gnutls-stream' now also accepts a ':coding' argument.
----
** 'process-attributes' now works under OpenBSD, too.
-+++
** 'format-spec' now takes an optional SPLIT parameter.
If non-nil, 'format-spec' will split the resulting string into a list
of strings, based on where the format specs (and expansions) were.
----
** 'unload-feature' now also tries to undo additions to buffer-local hooks.
----
** 'while-no-input-ignore-events' accepts more special events.
The special events 'dbus-event' and 'file-notify' are now ignored in
'while-no-input' when added to this variable.
----
** 'start-process-shell-command' and 'start-file-process-shell-command'
do not support the old calling conventions any longer.
-+++
** 'yes-or-no-p' and 'y-or-n-p' PROMPT parameter no longer needs trailing space.
In other words, the prompt can now end with "?" instead of "? ". This
has been the case since Emacs 24.4 but was not announced or documented
until now. (Checkdoc has also been updated to accept this convention.)
-+++
-** The 'uniquify' argument in 'auto-save-file-name-transforms' can be a symbol.
+** The UNIQUIFY argument in 'auto-save-file-name-transforms' can be a symbol.
If this symbol is one of the members of 'secure-hash-algorithms',
Emacs constructs the nondirectory part of the auto-save file name by
applying that 'secure-hash' to the buffer file name. This avoids any
risk of excessively long file names.
-+++
** New user option 'process-file-return-signal-string'.
It controls, whether 'process-file' returns a string when a remote
process is interrupted by a signal.
** EIEIO Changes
-+++
*** The macro 'oref-default' can now be used with 'setf'.
It is now defined as a generalized variable that can be used with
'setf' to modify the value stored in a given class slot.
----
*** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated.
This corresponds to the behavior of defmethod in Common Lisp Object System.
For compatibility, '(eql SYMBOL)' does not evaluate SYMBOL, for now.
** D-Bus
-+++
*** Property values can be typed explicitly.
'dbus-register-property' and 'dbus-set-property' accept now optional
type symbols. Both functions propagate D-Bus errors.
-+++
*** Registered properties can have the new access type ':write'.
-+++
*** In case of problems, handlers can emit proper D-Bus error messages now.
-+++
*** D-Bus errors, which have been converted from incoming D-Bus error
messages, contain the error name of that message now.
-+++
*** D-Bus messages can be monitored with the new command 'dbus-monitor'.
-+++
*** D-Bus events have changed their internal structure.
They carry now the destination and the error-name of an event. They
also keep the type information of their arguments. Use the
@@ -4496,19 +3881,16 @@ also keep the type information of their arguments. Use the
** Buttons
-+++
*** New minor mode 'button-mode'.
This minor mode does nothing except install 'button-buffer-map' as
a minor mode map (which binds the 'TAB' / 'S-TAB' key bindings to navigate
to buttons), and can be used in any view-mode-like buffer that has
buttons in it.
-+++
*** New utility function 'button-buttonize'.
This function takes a string and returns a string propertized in a way
that makes it a valid button.
----
** 'text-scale-mode' can now adjust font size of the header line.
When the new buffer local variable 'text-scale-remap-header-line'
is non-nil, 'text-scale-adjust' will also scale the text in the header
@@ -4519,10 +3901,8 @@ form below the header line. It is enabled by default in
'tabulated-list-mode' and its derived modes, and disabled by default
elsewhere.
----
** 'ascii' is now a coding system alias for 'us-ascii'.
----
** New coding-systems for EBCDIC variants.
New coding-systems 'ibm256', 'ibm273', 'ibm274', 'ibm277', 'ibm278',
'ibm280', 'ibm281', 'ibm284', 'ibm285', 'ibm290', 'ibm297'. These are
@@ -4532,14 +3912,12 @@ locales. They are also available as aliases 'ebcdic-cp-*' (e.g.,
'cp278' for 'ibm278'). There are also new charsets 'ibm2xx' to
support these coding-systems.
-+++
-** New 'Bindat type expression' description language.
+** New "Bindat type expression" description language.
This new system is provided by the new macro 'bindat-type' and
obsoletes the old data layout specifications. It supports
arbitrary-size integers, recursive types, and more. See the Info node
"(elisp) Byte Packing" in the ELisp manual for more details.
-+++
** New macro 'with-environment-variables'.
This macro allows setting environment variables temporarily when
executing a form.
@@ -4547,7 +3925,6 @@ executing a form.
* Changes in Emacs 28.1 on Non-Free Operating Systems
-+++
** On MS-Windows, Emacs can now use the native image API to display images.
Emacs can now use the MS-Windows GDI+ library to load and display
images in JPEG, PNG, GIF and TIFF formats. This support is available
@@ -4558,7 +3935,6 @@ To turn this on, set the variable 'w32-use-native-image-API' to a
non-nil value. Please report any bugs you find while using the native
image API via 'M-x report-emacs-bug'.
-+++
** On MS-Windows, Emacs can now toggle the IME.
A new function 'w32-set-ime-open-status' can now be used to disable
and enable the MS-Windows native Input Method Editor (IME) at run
@@ -4570,26 +3946,21 @@ current IME activation status.
'move-beginning-of-line' and 'move-end-of-line' respectively. The commands
to select previous/next frame are still bound to 's-~' and 's-`'.
-+++
** On macOS, Emacs can now load dynamic modules with a ".dylib" suffix.
'module-file-suffix' now has the value ".dylib" on macOS, but the
".so" suffix is supported as well.
----
** On macOS, the user option 'make-pointer-invisible' is now honored.
----
** On macOS, Xwidget is now supported.
If Emacs was built with xwidget support, you can access the embedded
-webkit browser with 'M-x xwidget-webkit-browse-url'. Viewing two
+webkit browser with command 'xwidget-webkit-browse-url'. Viewing two
instances of xwidget webkit is not supported.
----
*** New user option 'xwidget-webkit-enable-plugins'.
If non-nil, enable plugins in xwidget. (This is only available on
macOS.)
-+++
** New macOS Contacts back-end for EUDC.
This backend works on newer versions of macOS and is generally
preferred over the eudcb-mab.el backend.
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index e4bb706e08c..37a39131d93 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -451,10 +451,6 @@ you can now configure them.
(the default) or use the attachment directory of the current node, if
it is correctly configured as a Git repository.
-*** Some faces now use fixed-pitch
-
-See [[msg:875z8njaol.fsf@protesilaos.com][this thread]].
-
*** New option ~org-attach-sync-delete-empty-dir~
~org-attach-sync-delete-empty-dir~ controls the deletion of an empty
@@ -509,7 +505,7 @@ heading, except return nil.
In the past, faces of todo keywords, emphasised text, tags, and
priority cookies inherited =default= face. The resulting headline
-fontification was not always consistent, as discussed in [[https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00331.html][this bug
+fontification was not always consistent, as discussed in [[msg::87h7sawubl.fsf@protesilaos.com][this bug
report]]. Now, the relevant faces adapt to face used to fontify the
current headline level.
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 9040c492563..14c1df25b16 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -651,6 +651,46 @@ And then rename the system's readline so that it won't be loaded:
See <https://pypi.python.org/pypi/gnureadline> for more details on
installation.
+*** On MS-Windows, invoking "M-x run-python" signals an error.
+
+If the error says something like this:
+
+ Python was not found; run with arguments to install
+ from the Microsoft Store, or disable this shortcut
+ from Settings > Manage App Execution Aliases.
+
+ Process Python exited abnormally with code 49
+
+then this is due to the MS-Windows "feature" that is intended to
+encourage you to install the latest available Python version. It
+works by placing "fake" python.exe and python3.exe executables in a
+special directory, and having that directory on your Path _before_ the
+directory where the real Python executable is installed. That "fake"
+Python then decides whether to redirect you to the Microsoft Store or
+invoke the actual Python. The directory where Windows keeps those
+"fake" executables is under your Windows user's 'AppData' directory,
+typically 'C:\Users\<user>\AppData\Local\Microsoft\WindowsApps', where
+"<user>" is the user name of your Windows user.
+
+To solve this, you have several alternatives:
+
+ . Go to "Settings > Manage App Execution Aliases" and turn OFF the
+ aliases for python.exe and/or python3.exe. This will affect only
+ Python, and may require you to manage upgrades to your Python
+ installation manually, instead of being automatically prompted by
+ MS-Windows.
+ . Move the directory with the "fake" executables to the end of Path,
+ or at least after the directory where the real Python is
+ installed. Depending on the position in Path where you move it,
+ it will affect Python and/or other programs which Windows monitors
+ via the "App Execution Aliases" feature.
+ . Manually remove python.exe and/or python3.exe from the above
+ directory. Again, this affects only your Python installation.
+
+Whatever you do, you will need to restart Emacs to refresh its notion
+of the directory where python.exe/python3.exe lives, because that is
+recorded when Python mode is started.
+
*** Visiting files in some auto-mounted directories causes Emacs to print
'Error reading dir-locals: (file-error "Read error" "is a directory" ...'
@@ -765,6 +805,22 @@ to take advantage of.
* Runtime problems related to font handling
+** Some fonts are detected but not usable under Xft.
+
+Some fonts might not be usable under Emacs even though they show up in
+the font family list when Emacs is built with Xft. This is because
+Emacs prevents fonts that have color glyphs (such as color Emoji) from
+being used, since they typically cause Xft crashes.
+
+On some GNU/Linux systems, fonts (such as Source Code Pro) that do not
+have color glyphs are reported as color fonts, causing them to be
+unavailable when using Xft. This is known to happen under Fedora
+GNU/Linux 36 or later, and possibly other distributions as well.
+
+If you encounter a such a font, you can enable it while ignoring other
+fonts that actually have color glyphs by adding its family name to the
+list `xft-color-font-whitelist'.
+
** Characters are displayed as empty boxes or with wrong font under X.
*** This may be due to your local fontconfig customization.
@@ -1009,6 +1065,15 @@ index 5504171..431adf8 100644
If you can't modify that file directly, copy it to the directory
~/.m17n.d/ (create it if it doesn't exist), and apply the patch.
+** On Haiku, some proportionally-spaced fonts display with artifacting.
+
+This is a Haiku bug: https://dev.haiku-os.org/ticket/17229, which can
+be remedied by using a different font that does not exhibit this
+problem, or by configuring Emacs '--with-be-cairo'.
+
+So far, Bitstream Charter and Noto Sans have been known to exhibit
+this problem, while Noto Sans Display is known to not do so.
+
** On MS-Windows, some characters display as boxes with hex code.
Also, some characters could display with wrong fonts.
@@ -1022,14 +1087,20 @@ modern fonts are used, such as Noto Emoji or Ebrima.
The solution is to switch to a configuration that uses HarfBuzz as its
shaping engine, where these problems don't exist.
-** On Haiku, some proportionally-spaced fonts display with artifacting.
+** On MS-Windows, selecting some fonts as the default font doesn't work.
-This is a Haiku bug: https://dev.haiku-os.org/ticket/17229, which can
-be remedied by using a different font that does not exhibit this
-problem, or by configuring Emacs '--with-be-cairo'.
+This can happen if you select font variants such as "Light" or "Thin"
+or "Semibold" or "Heavy", and some others. The APIs used by Emacs on
+Windows to enumerate fonts in a font family consider only 4 font
+variants to belong to the same family: Regular, Italic, Bold, and
+Bold-Italic. All the other variants aren't returned by those APIs
+when we request to list all the fonts in a family, and thus aren't
+considered by Emacs to belong to the family. So any font variant that
+is not one of those 4 will likely not work as expected; in most cases
+Emacs will select some other font instead.
-So far, Bitstream Charter and Noto Sans have been known to exhibit
-this problem, while Noto Sans Display is known to not do so.
+The only workaround is not to choose such font variants as the default
+font when running Emacs on MS-Windows.
* Internationalization problems
@@ -1304,6 +1375,13 @@ and then Alt-F7). A bug for it is here:
https://bugs.launchpad.net/ubuntu/+source/metacity/+bug/231034.
Note that a permanent fix seems to be to disable "assistive technologies".
+*** Enlightenment: Frames not redrawn after switching virtual desktops
+
+With Enlightenment version 0.25, Emacs frames may no be redrawn orderly
+after switching back from another virtual desktop. Setting the variable
+'x-set-frame-visibility-more-laxly' to one of 'focus-in', 'expose' or
+'t' should fix this.
+
*** Gnome: Emacs receives input directly from the keyboard, bypassing XIM.
This seems to happen when gnome-settings-daemon version 2.12 or later
@@ -1690,7 +1768,15 @@ This happens on the proprietary X server ASTEC-X when the number of
monitors is changed after the server has started. A workaround is to
restart the X server after the monitor configuration has been changed.
-*** Touchpad gestures don't work and emit warning messages.
+*** Touchpad gestures don't work and/or emit warning messages.
+
+Support for touch gestures in Emacs requires a sufficiently new X
+server. We currently know of only one: version 21.1.0 or later of the
+X.Org server, coupled with the xf86-input-libinput input driver.
+
+Type 'M-: (x-server-input-extension-version) RET'; if that doesn't
+return '(2 4)' (version 2.4) or later, your version of the X server
+and libraries are too old and need to be upgraded.
When pinching or swiping on your touchpad, you might see a warning
message that looks like:
@@ -1702,7 +1788,75 @@ actual version of libXi installed does not. The solution is to
upgrade your libXi binaries to libXi 1.8.0 or later, to correspond
with your XInput headers.
-* Runtime problems on character terminals
+*** Requesting a private colormap makes Emacs hang.
+
+The part of Xlib that provides this feature is broken in modern
+incarnations of Xlib, so it cannot possibly work. The solution is to
+remove anything that looks like this:
+
+ Emacs.privateColormap: on
+
+From your X defaults file. Your X server might also provide a
+different visual class that will do what you want. You can experiment
+with `TrueColor-8', by placing this:
+
+ Emacs.visualClass: TrueColor-8
+
+in your ~/.Xresources, and loading that file.
+
+*** Colors messed up on Cairo or GTK builds.
+
+If your display defaults to a visual where pixel values cannot be
+directly converted to their corresponding real colors, a build with
+Cairo drawing or GTK will display colors incorrectly. This is because
+Cairo and GTK foolishly assume that all RGB values can be converted
+directly from their individual components, without asking the X server
+to allocate the color.
+
+Your X server might have a different visual which is decomposed and
+not colormapped. Try the following in your ~/.Xresources:
+
+ Emacs.visualClass: TrueColor-N
+
+where "N" is the bit depth of the visual your X server defaults to.
+If that does not work, you lose. Configure Emacs '--without-cairo'
+and '--with-x-toolkit=lucid' instead.
+
+*** GUI widgets don't display on GTK builds, except for scrollbars.
+
+This can happen if your visual does not have a decomposed colormap,
+and your X server has the X rendering extension.
+
+To solve the problem, disable the X rendering extension on your X
+server, or rebuild Emacs without GTK+.
+
+*** On Accelerated X, the GTK 3 menu bar does not select items.
+
+The solution is to run Emacs with the environment variable 'GDK_DEBUG'
+set to "nograbs", like this (where "..." stands for the other
+command-line arguments you intend to pass to Emacs):
+
+ GDK_DEBUG=nograbs emacs ...
+
+Accelerated X is a proprietary X server. Aside from being
+proprietary, it has many other disadvantages, such as not supporting
+most recent hardware and most modern extensions to the X protocol.
+Consider switching to a free X server, such as X.Org.
+
+If setting GDK_DEBUG causes GTK to complain about not being built with
+support for debugging options, then there is nothing you can do,
+except switch to a free X server.
+
+*** 'set-mouse-position' does not move the pointer on Xwayland.
+
+This is because Wayland does not allow programs to warp the pointer.
+There is nothing that can be done about this problem, except to switch
+to an X session.
+
+Some versions of the Xwayland server will pretend to warp the pointer,
+so mouse-motion events might be sent to the position the mouse was
+supposed to have moved to, even though the cursor displays at the same
+on-screen position.
*** With X forwarding, mouse highlighting can make Emacs slow.
@@ -1711,6 +1865,23 @@ remote X server, try this:
(setq mouse-highlight nil)
+*** Dropping text on xterm doesn't work.
+
+Emacs sends sythetic button events to legacy clients such as xterm
+that do not support either the XDND or Motif drag-and-drop protocols
+in order to "paste" the text that was dropped. Unfortunately, xterm
+is configured to ignore these events by default. Add the following to
+your X defaults file to avoid the problem:
+
+ XTerm.*.allowSendEvents: True
+
+Note that this can in theory pose a security risk, but in practice
+modern X servers have so many other ways to send input to clients
+without signifying that the event is synthesized that it does not
+matter.
+
+* Runtime problems on character terminals
+
** The meta key does not work on xterm.
Typing M-x rings the terminal bell, and inserts a string like ";120~".
@@ -1727,6 +1898,33 @@ this, you can remove the X resource or put this in your init file:
(xterm-remove-modify-other-keys)
+** The shift TAB key combination works as meta TAB on a Linux console.
+
+This happens because on your keyboard layout, S-TAB produces the same
+keycodes as typing ESC TAB individually. The best way to solve this
+is to modify your keyboard layout to produce different codes, and tell
+Emacs what these new codes mean.
+
+The current keyboard layout will probably be a .map.gz file somewhere
+under /usr/share/keymaps. Identify this file, possibly from a system
+initialization file such as /etc/conf.d/keymaps. Run gunzip on it to
+decompress it, and amend the entries for keycode 15 to look something
+like this:
+
+keycode 15 = Tab
+ alt keycode 15 = Meta_Tab
+ shift keycode 15 = F219
+string F219 = "\033[4}\011" # Shift+<tab>
+
+After possibly saving this file under a different name, compress it
+again using gzip. Amend /etc/conf.d/keyamps, etc., if needed.
+Further details can be found in the man page for loadkeys.
+
+Then add the following line near the start of your site-start.el or
+.emacs or init.el file:
+
+(define-key input-decode-map "\e[4}\t" 'backtab)
+
** Emacs spontaneously displays "I-search: " at the bottom of the screen.
This means that Control-S/Control-Q (XON/XOFF) "flow control" is being
@@ -2350,6 +2548,11 @@ Emacs so that it isn't compiled with '-O5'.
We list bugs in current versions here. See also the section on legacy
systems.
+*** On Solaris 10 sparc, Emacs crashes during the build while saving state.
+This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with
+Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent,
+and running GNU Make a second time would typically finish the build.
+
*** On Solaris 10, Emacs crashes during the build process.
(This applies only with './configure --with-unexec=yes', which is rare.)
This was reported for Emacs 25.2 on i386-pc-solaris2.10 with Sun
@@ -2830,6 +3033,28 @@ when started from the command line.
Especially, PGTK Emacs needs environment variables LANG and
GTK_IM_MODULE.
+** 'set-mouse-position' does nothing.
+
+GTK does not allow programs to warp the pointer anymore. There is
+nothing that can be done about this problem.
+
+** Certain keys such as 'C-S-u' are not reported correctly.
+
+Some keys with modifiers such as Shift and Control might not be
+reported correctly due to incorrectly written GTK input method
+modules. This is known to happen to 'C-S-u' and 'C->', which are
+misreported as 'C-u' and '>'.
+
+To disable the use of GTK input methods, evaluate:
+
+ (pgtk-use-im-context nil)
+
+This will also cause system input methods and features such as the
+Compose key to stop working.
+
+On X Windows, users should not use Emacs configured with PGTK, since
+this and many other problems do not exist on the regular X builds.
+
* Build-time problems
** Configuration
diff --git a/etc/TODO b/etc/TODO
index 80e77bba60d..5c55a8b9992 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -722,8 +722,6 @@ bar. In the mean time, it should process other messages.
** Get some major packages installed
-*** W3 (development version needs significant work)
-
*** PSGML, _possibly_ ECB
https://lists.gnu.org/r/emacs-devel/2007-05/msg01493.html Check the
assignments file for other packages which might go in and have been
@@ -806,7 +804,7 @@ kermit, log-edit, makesum, midnight [other than in Kill Buffer node],
mouse-copy [?], mouse-drag, mouse-sel, net-utils, rcompile, snmp-mode
[?], soundex [should be interactive?], strokes [start from the web
page], talk, thingatpt [interactive functions?], type-break, vcursor,
-xscheme, zone-mode [?], mlconvert [?], iso-cvt, feedmail [?], uce,
+xscheme, zone-mode [?], mlconvert [?], iso-cvt, feedmail [?],
gametree, page-ext, refbib, refer, scribe, texinfo, underline,
cmacexp, hideif, pcomplete, xml, cvs-status (should be described in
PCL-CVS manual); other progmodes, probably in separate manual.
@@ -907,17 +905,17 @@ It would make it easy to add (and remove) mappings like
*** Missing features
This sections contains features found in other official Emacs ports.
-**** Support for xwidgets
-Emacs 25 has support for xwidgets, a system to include operating
-system components into an Emacs buffer. The components range from
-simple buttons to webkit (effectively, a web browser).
+**** Improved xwidgets support
+Emacs 25 has support for xwidgets, a system to include WebKit widgets
+into an Emacs buffer.
-Currently, xwidgets work only for the gtk+ framework but they are
-designed to be compatible with multiple Emacs ports.
+They work on NS, but not very well. For example, trying to display a
+xwidget in the "killed" state will make Emacs crash. This is because
+the NS code has not been updated to keep with recent changes to the
+X11 and GTK code.
-(See the scratch/nsxwidget branch, and the discussion around
-Objective-C code and GCC at
-https://lists.gnu.org/r/emacs-devel/2019-08/msg00072.html )
+Many features such as xwidget-webkit-edit-mode do not work correctly
+on NS either.
**** Respect 'frame-inhibit-implied-resize'
When the variable 'frame-inhibit-implied-resize' is non-nil, frames
@@ -990,29 +988,16 @@ It has been maintained in parallel to the official Cocoa-based NS
interface. The Carbon interface has been enhanced, and a number of the
features of that interface could be implemented NS.
-**** Smooth scrolling -- maybe not a good idea
-Today, by default, scrolling with a trackpad makes the text move in
-steps of one line. (Scrolling with SHIFT scrolls horizontally.)
-
-The "mac" port provides smooth, pixel-based, scrolling. This is a very
-popular feature. However, there are drawbacks to this method: what
-happens if only a fraction of a line is visible at the top of a
-window, is the partially visible text considered part of the window or
-not? (Technically, what should 'window-start' return.)
-
-Note: This feature might not be allowed to be implemented until also
-implemented in Emacs for a free system.
-
**** Mouse gestures
The "mac" port defines the gestures 'swipe-left/right/up/down',
'magnify-up/down', and 'rotate-left/right'.
-It also binds the magnification commands to change the font
-size. (This should be not be done in a specific interface, instead
-Emacs should do this binding globally.)
+The magnify gestures have now been implemented on X11 and NS. The
+event is named differently: it is named `pinch', but it does the same
+thing.
-Note: This feature might not be allowed to be implemented until also
-implemented in Emacs for a free system.
+Someone needs to figure out what the other gestures do in the Mac
+port, implement them on X, and then following that, on NS.
**** Synthesize bold fonts
diff --git a/etc/compilation.txt b/etc/compilation.txt
index 5601ce272aa..111b2a37dce 100644
--- a/etc/compilation.txt
+++ b/etc/compilation.txt
@@ -424,7 +424,7 @@ symbol: oracle
This stupid precompiler wraps lines at column 80 in the middle of a file name.
There is no obvious way of detecting this or turning it off. But if you
-delete the newline (probably needs M-x toggle-read-only), the file name will
+delete the newline (probably needs M-x read-only-mode), the file name will
automatically be reparsed, so that you can then go there.
Semantic error at line 528, column 5, file erosacqdb.pc:
@@ -542,7 +542,7 @@ cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3
* ShellCheck
In autogen.sh line 38:
-autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac`
+autoconf_min=`sed -n 's/^ *AC_PREREQ(\[\([0-9\.]*\)]).*/\1/p' configure.ac`
^----------^ SC2034: autoconf_min appears unused. Verify use (or export if used externally).
^-- SC2006: Use $(...) notation instead of legacy backticked `...`.
diff --git a/etc/e/eterm-color b/etc/e/eterm-color
index bf44fa0f36d..fadac25ffcb 100644
--- a/etc/e/eterm-color
+++ b/etc/e/eterm-color
Binary files differ
diff --git a/etc/e/eterm-color.ti b/etc/e/eterm-color.ti
index eeb9b0b6e6a..84b27aef5d9 100644
--- a/etc/e/eterm-color.ti
+++ b/etc/e/eterm-color.ti
@@ -16,6 +16,7 @@ eterm-color|Emacs term.el terminal emulator term-protocol-version 0.96,
am,
mir,
msgr,
+ nrrmc,
xenl,
bel=^G,
blink=\E[5m,
@@ -77,8 +78,8 @@ eterm-color|Emacs term.el terminal emulator term-protocol-version 0.96,
smso=\E[7m,
u6=\E[%i%d;%dR,
u7=\E[6n,
-# smcup=\E[?47h,
-# rmcup=\E[?47l,
+ smcup=\E[47h,
+ rmcup=\E[47l,
# rs2 may need to be added
eterm-direct|Emacs term.el with direct-color indexing term-protocol-version 0.96,
diff --git a/etc/e/eterm-direct b/etc/e/eterm-direct
index c113c371369..f4c16621eb1 100644
--- a/etc/e/eterm-direct
+++ b/etc/e/eterm-direct
Binary files differ
diff --git a/etc/enriched.txt b/etc/enriched.txt
index 5c74c610aec..2d970d197b8 100644
--- a/etc/enriched.txt
+++ b/etc/enriched.txt
@@ -137,7 +137,7 @@ Unfortunately this does not look as nice with a fixed-width font
as it does in a proportionally-spaced printed document; the extra
spaces that are needed on the screen can make it hard to read.</flushboth>
-<center>
+ <center>
<bold>Center</bold>
@@ -149,7 +149,6 @@ spaces that are needed on the screen can make it hard to read.</flushboth>
justification.
-
</center><flushboth>Note that justification can only change at hard newlines, because
that is the unit over which filling gets done.</flushboth></indent>
@@ -189,7 +188,14 @@ as possible.
The text/enriched standard is defined in </indent>Internet<indent> RFC 1896
-(<<http://www.ietf.org/rfc/rfc1896.txt>).</indent>
+(<<http://www.ietf.org/rfc/rfc1896.txt>).
+
+
+To make format annotations visible and possibly edit them, tell
+Emacs to display the markup:
+
+
+<fixed><indent>M-x enriched-toggle-markup RET</indent></fixed></indent>
<x-bg-color><param>blue</param><x-color><param>white</param><bold>CUSTOMIZATION</bold></x-color></x-bg-color><bold>
diff --git a/etc/images/gnus/catchup.pbm b/etc/images/gnus/catchup.pbm
deleted file mode 100644
index 3fc571bdf80..00000000000
--- a/etc/images/gnus/catchup.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/catchup.xpm b/etc/images/gnus/catchup.xpm
deleted file mode 100644
index cba849712df..00000000000
--- a/etc/images/gnus/catchup.xpm
+++ /dev/null
@@ -1,33 +0,0 @@
-/* XPM */
-static char * catchup_xpm[] = {
-"24 24 6 1",
-" c None",
-". c #FFFFFFFFFFFF",
-"X c #E1E1E0E0E0E0",
-"o c #A5A5A5A59595",
-"O c #999999999999",
-"+ c #000000000000",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" . ",
-" . .X ",
-" ... .oX . ",
-" ..oooX.oXo .X ",
-" .oooXXXX..oXXoXX ",
-" .oXXXX.XoX.oXooX ",
-" X...X.X.XX.XoXX ",
-" Xo..X.XXX.XXXX ",
-" . Xo.oXX..XXXXXX ",
-"OOOOXoXXXXXo.XXXXX++OOOO",
-"OOOOOX..X.XXXXXXXX++OOOO",
-"OOOOOX..XXXXXXXXX++OOOOO",
-"OOOOOOXXXXXXXXX+++OOOOOO",
-"OOOOOOOOOXXXX++++OOOOOOO",
-"OOOOOOOOO+++++OOOOOOOOOO",
-"OOOOOOOOOO+OOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO"};
diff --git a/etc/images/gnus/cu-exit.pbm b/etc/images/gnus/cu-exit.pbm
deleted file mode 100644
index 210869cce78..00000000000
--- a/etc/images/gnus/cu-exit.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/cu-exit.xpm b/etc/images/gnus/cu-exit.xpm
deleted file mode 100644
index 17236223fed..00000000000
--- a/etc/images/gnus/cu-exit.xpm
+++ /dev/null
@@ -1,31 +0,0 @@
-/* XPM */
-static char * cu_exit_xpm[] = {
-"24 24 4 1",
-" c None",
-". c #000000000000",
-"X c #FFFFFFFFFFFF",
-"o c #999999999999",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ..... ",
-" .. .XXX. ",
-" ..X..XXXX... ",
-" .XXXX.XXXX.X... ",
-" ..XXXX.XXX.XXX.. ",
-" .XXX.......... ",
-" .XXX.XXX.XXX.. ",
-" .XX.XXX.XXX. ",
-" .XX.XXX.XX.. ",
-" ............ ",
-" .X.X.X.X.. ",
-"ooooooo..........ooooooo",
-"ooooooo.X.X.X.X.oooooooo",
-"ooooooo.........oooooooo",
-"ooooooo..X...X..oooooooo",
-"ooooooo...X.X...oooooooo",
-"ooooooo........ooooooooo",
-"ooooooooo.....oooooooooo",
-"oooooooooooooooooooooooo"};
diff --git a/etc/images/gnus/describe-group.pbm b/etc/images/gnus/describe-group.pbm
deleted file mode 100644
index de7bf110431..00000000000
--- a/etc/images/gnus/describe-group.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/describe-group.xpm b/etc/images/gnus/describe-group.xpm
deleted file mode 100644
index b4a6f42a94b..00000000000
--- a/etc/images/gnus/describe-group.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char * describe_group_xpm[] = {
-"24 24 5 1",
-". c None",
-" c #000000000000",
-"o c #FFFFF5F5ACAC",
-"+ c #E1E1E0E0E0E0",
-"@ c #C7C7C6C6C6C6",
-"........................",
-"........................",
-".................oooo...",
-" .. .. .. .. .. oo oo o.",
-"..............oooooooooo",
-".............ooooooooooo",
-" .. .. .. .. oo oo oo oo",
-"............oooooooooooo",
-"............oooooooooooo",
-" .. .. .. .. oo oo oo oo",
-"............oooooooooooo",
-"............oooooooooooo",
-" .. .. .. .. oo oo oo oo",
-"............oooooooooooo",
-"..... ...oooooooooooo",
-" .. ++ .. .o oo oo oo",
-"... @@@+ ....ooooooooo",
-"... @ ....oooooooo.",
-" . . .. .. .. ..",
-". ..............",
-" ................",
-" .. .. .. .. .. ..",
-" ..................",
-" ...................."};
diff --git a/etc/images/gnus/exit-gnus.pbm b/etc/images/gnus/exit-gnus.pbm
deleted file mode 100644
index 32ad0e0ebe9..00000000000
--- a/etc/images/gnus/exit-gnus.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/exit-gnus.xpm b/etc/images/gnus/exit-gnus.xpm
deleted file mode 100644
index 534f3c2fafb..00000000000
--- a/etc/images/gnus/exit-gnus.xpm
+++ /dev/null
@@ -1,33 +0,0 @@
-/* XPM */
-static char * exit_gnus_xpm[] = {
-"24 24 6 1",
-" c None",
-". c #8686ADAD7D7D",
-"X c #919187876969",
-"o c #C2C2B9B99C9C",
-"O c #A8A8F0F0ECEC",
-"+ c #EFEFEFEFEFEF",
-" ",
-" .... . ",
-" .. .. . ",
-" ............. ",
-" . . . .... ",
-" ............. ",
-" .............. .. ",
-" . . .......... . ",
-" .XXXX... .. ",
-" o.XXX. . .. ",
-" oo.X. .. ... ",
-" ooX. . ... ",
-" oXo. .. ",
-" ooX . . ",
-" ooX ",
-"OOOOoXXOOOOOOOOOOOOOOOOO",
-"OOOoXoXOOOOOOOOOOOOOOOOO",
-"OOOooXXOOOO+OOOOOOOOOOOO",
-"O+OoooXOO+OOO+OO+OOO+OOO",
-"OXXoXoXoXOO++O++OO++OO+O",
-"XXXXXXXXXXXX+OOOOOOOOOOO",
-"XXXXXXXXXXXXXX+O++OO++OO",
-"XXXXXXXXXXXXXXXXOOOOOOOO",
-"O++O++++O+OO++OOOO++OOO+"};
diff --git a/etc/images/gnus/exit-summ.pbm b/etc/images/gnus/exit-summ.pbm
deleted file mode 100644
index d0192310607..00000000000
--- a/etc/images/gnus/exit-summ.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/exit-summ.xpm b/etc/images/gnus/exit-summ.xpm
deleted file mode 100644
index 5234ccb11ec..00000000000
--- a/etc/images/gnus/exit-summ.xpm
+++ /dev/null
@@ -1,30 +0,0 @@
-/* XPM */
-static char * exit_summ_xpm[] = {
-"24 24 3 1",
-". c None",
-" c #000000000000",
-"X c #E1E1E0E0E0E0",
-" .. .. .. .. .. .. .. ..",
-"........................",
-"........................",
-" .. .. .. ..",
-"...... XXXX .....",
-"...... XXXXXXX .....",
-" .. .. XX XX XX .. ..",
-"...... XXXXXXXX .....",
-"...... XXXXXXX .....",
-" .. .. X XX .. ..",
-"...... XXXX .....",
-"...... XXXX .....",
-" .. .. X XXXXX .. ..",
-"...... XXXXXXX .....",
-"...... XXXXX XX .....",
-" .. .. X XXXXX .. ..",
-"...... XXXXX .....",
-"...... X .....",
-" .. . . .. ..",
-"........................",
-"........................",
-" .. .. .. .. .. .. .. ..",
-"........................",
-"........................"};
diff --git a/etc/images/gnus/get-news.pbm b/etc/images/gnus/get-news.pbm
deleted file mode 100644
index c0080716c44..00000000000
--- a/etc/images/gnus/get-news.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/get-news.xpm b/etc/images/gnus/get-news.xpm
deleted file mode 100644
index d7e7b4a3553..00000000000
--- a/etc/images/gnus/get-news.xpm
+++ /dev/null
@@ -1,31 +0,0 @@
-/* XPM */
-static char * get_news_xpm[] = {
-"24 24 4 1",
-". c None",
-"X c #A5A5A5A59595",
-"o c #E1E1E0E0E0E0",
-"O c #C7C7C6C6C6C6",
-"........................",
-"........................",
-"........................",
-".....XXX................",
-"...XXoooXXXXX...........",
-"XXXoooooXXoooX.XXX......",
-"XoXooXXXooooXXXoooX.....",
-"XooXoXoXooXXXoooooX.....",
-"XooXXXooXoXoXooooooX....",
-"XooXOXooXXXooXooooooX...",
-"XoXOOXooXOXooXXooooooX..",
-"OXOOOXoXOOXooXoooooooX..",
-"OXOooOXOOOXoXOooooooooX.",
-".OXooOXOooOXOOooooooooX.",
-".OXoooOXooOXOooooooooooX",
-"..OXooOXoooOXooooooooooX",
-"..OXooOOXooOXooooooooooX",
-"...OXooOXoooOXoooooooXXX",
-"...OXooXOXooOXooooooXOO.",
-"....OXXOOXooXOXoooXXO...",
-".....OO..OXXOOXooXOO....",
-"..........OO..OXXO......",
-"...............OO.......",
-"........................"};
diff --git a/etc/images/gnus/gnntg.pbm b/etc/images/gnus/gnntg.pbm
deleted file mode 100644
index 2f5e5261a97..00000000000
--- a/etc/images/gnus/gnntg.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/gnntg.xpm b/etc/images/gnus/gnntg.xpm
deleted file mode 100644
index 21bc5f16eb2..00000000000
--- a/etc/images/gnus/gnntg.xpm
+++ /dev/null
@@ -1,31 +0,0 @@
-/* XPM */
-static char * gnntg_xpm[] = {
-"24 24 4 1",
-" c None",
-". c #000000000000",
-"X c #FFFFFFFFFFFF",
-"o c #C7C7C6C6C6C6",
-" ",
-" ....... ",
-" .XXXXX. ",
-" .XXXXX. ... ",
-" .XXXXX... .ooo. ",
-" .XXXXX.... ..ooo.. ",
-" .XXXXX..o.. ..ooo.. ",
-" .XXXXX...o.. ..o.. ",
-" .XXXXX. ..o........ ",
-" .XXXXX. ..oooooooo. ",
-" ....... .oooooooo.. ",
-" .ooooo..o. ",
-" .oooo..o. ",
-" .oooo..o. ",
-" .oooo..o. ",
-" .oooo..o. ",
-" ......... ",
-" ......oo. ",
-" .ooooo... ",
-" .oo..o... ",
-" .oo..o.. ",
-" ........ ",
-" .... ... ",
-" ... ... "};
diff --git a/etc/images/gnus/important.pbm b/etc/images/gnus/important.pbm
deleted file mode 100644
index 7139ff2d69e..00000000000
--- a/etc/images/gnus/important.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/important.xpm b/etc/images/gnus/important.xpm
deleted file mode 100644
index e972facff24..00000000000
--- a/etc/images/gnus/important.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char *magick[] = {
-/* columns rows colors chars-per-pixel */
-"24 24 2 1",
-"! c red",
-"w c Gray75",
-/* pixels */
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwww!!!wwwwwwwwwwww",
-"wwwwwwwww!!!wwwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwww!!!!!!!wwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwwww!!!wwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwww!!!wwwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwww!!!!!wwwwwwwwwww",
-"wwwwwwwww!!!wwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww"
-};
diff --git a/etc/images/gnus/next-ur.pbm b/etc/images/gnus/next-ur.pbm
deleted file mode 100644
index 678bbb09f8b..00000000000
--- a/etc/images/gnus/next-ur.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/next-ur.xpm b/etc/images/gnus/next-ur.xpm
deleted file mode 100644
index bea13280b68..00000000000
--- a/etc/images/gnus/next-ur.xpm
+++ /dev/null
@@ -1,35 +0,0 @@
-/* XPM */
-static char * next_ur_xpm[] = {
-"24 24 8 1",
-". c None",
-" c #000000000000",
-"X c #A5A5A5A59595",
-"o c #C7C7C6C6C6C6",
-"O c #FFFF00000000",
-"+ c #9A9A6C6C4E4E",
-"@ c #E1E1E0E0E0E0",
-"# c #FFFFFFFFFFFF",
-" .. .. .. .. .. .. .. ..",
-"........................",
-"............X...........",
-" .. .. .. .XXX. .. .. ..",
-".........XXooOX.........",
-".......XXooo+O@X........",
-" .. XXXoooo++@@@X. .. ..",
-"....X@Xoooooo@@@X.......",
-"....X@@Xooo@@@@@@X......",
-" .. X@@XXoo@@@@@@@X.. ..",
-"....X@@Xoo@@@@@@@@@X....",
-"....X@Xo@@@XX@@@@@@oX...",
-" .. oXoo@XXooO@@@@@@X ..",
-"....oXoXXooo+OX@@@@Xo...",
-"....XXXoooo++@@X@@Xo....",
-" .. X@Xoooooo@@@XX .. ..",
-"....X@@Xooo@@@@@@X......",
-"....X@@XXoo@@@@@@@X.....",
-" .. X@@Xoo@@@@@@@@@X. ..",
-"....X@Xo@ @@@@@@@ X...",
-"... oXoo ## @@ @@ ## ...",
-" .. oXo #### @ #### ..",
-".....oX #### @@@ #### ..",
-".....oX@ ## @@@@X ## ..."};
diff --git a/etc/images/gnus/post.pbm b/etc/images/gnus/post.pbm
deleted file mode 100644
index 577d6236bfd..00000000000
--- a/etc/images/gnus/post.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/post.xpm b/etc/images/gnus/post.xpm
deleted file mode 100644
index 7a3eaa5e3b1..00000000000
--- a/etc/images/gnus/post.xpm
+++ /dev/null
@@ -1,35 +0,0 @@
-/* XPM */
-static char * post_xpm[] = {
-"24 24 8 1",
-". c None",
-" c #434343434343",
-"X c #A5A5A5A59595",
-"O c #000000000000",
-"+ c #C7C7C6C6C6C6",
-"@ c #FFFF00000000",
-"# c #9A9A6C6C4E4E",
-"$ c #E1E1E0E0E0E0",
-"O..O..O..O..O..O..O..O..",
-"........................",
-"............X...........",
-"O..O..O..O.XXX.O..O..O..",
-".........XX++@X.........",
-".......XX+++#@$X........",
-"O..OXXX++++##$$$X.O..O..",
-"....X$X++++++$$$X.......",
-"....X$$X+++$$$$$$X......",
-"O..OX$$XX++$$$$$$$X..O..",
-"....X$$X++$$$$$$$$$X....",
-"....X$X+$$$$$$$$$$$+X...",
-"O..O+X++$$$$$$$$$$$$XO..",
-"....+X+$$$$$$$$$$$$X+...",
-".....+X$$$$$$$$$$$X+....",
-"O..O.+X$$$$$$$$$XXO..O..",
-"......+X$$$$$$$X++......",
-"......+X$$$$$XX+........",
-"O..O..O+X$$$X++O..O..O..",
-".......+X$$X++..........",
-"........+XX+............",
-"O..O..O..O+.O..O..O..O..",
-"........................",
-"........................"};
diff --git a/etc/images/gnus/prev-ur.pbm b/etc/images/gnus/prev-ur.pbm
deleted file mode 100644
index 49389198bdf..00000000000
--- a/etc/images/gnus/prev-ur.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/prev-ur.xpm b/etc/images/gnus/prev-ur.xpm
deleted file mode 100644
index 80131332832..00000000000
--- a/etc/images/gnus/prev-ur.xpm
+++ /dev/null
@@ -1,35 +0,0 @@
-/* XPM */
-static char * prev_ur_xpm[] = {
-"24 24 8 1",
-". c None",
-" c #000000000000",
-"X c #A5A5A5A59595",
-"o c #C7C7C6C6C6C6",
-"O c #FFFF00000000",
-"+ c #9A9A6C6C4E4E",
-"@ c #E1E1E0E0E0E0",
-"# c #FFFFFFFFFFFF",
-" .. .. .. .. .. .. .. ..",
-"........................",
-"............X...........",
-" .. .. .. .XXX. .. .. ..",
-".........XXooOX.........",
-".......XXooo+O@X........",
-" .. XXXoooo++@@@X. .. ..",
-"....X@Xoooooo@@@X.......",
-"....X@@Xooo@@@@@@X......",
-" .. X@@XXoo@@@@@@@X.. ..",
-"....X@@Xo @@@@@@ X....",
-"....X@Xo ## X @ ## X...",
-" .. oXo #XXXoO@ #### ..",
-"....oXoXXooo+OX #### ...",
-"....XXXoooo++@@X ## ....",
-" .. X@Xoooooo@@@X .. ..",
-"....X@@Xooo@@@@@@X......",
-"....X@@XXoo@@@@@@@X.....",
-" .. X@@Xoo@@@@@@@@@X. ..",
-"....X@Xo@@@@@@@@@@@@X...",
-"... oXoo@@@@@@@@@@@@X...",
-" .. oXo@@@@@@@@@@@@X....",
-".....oX@@@@@@@@@@@X.....",
-".....oX@@@@@@@@@@X......"};
diff --git a/etc/images/gnus/receipt.pbm b/etc/images/gnus/receipt.pbm
deleted file mode 100644
index 5595239f40d..00000000000
--- a/etc/images/gnus/receipt.pbm
+++ /dev/null
@@ -1,3 +0,0 @@
-P4
-24 24
- \ No newline at end of file
diff --git a/etc/images/gnus/receipt.xpm b/etc/images/gnus/receipt.xpm
deleted file mode 100644
index 18caaf1cf78..00000000000
--- a/etc/images/gnus/receipt.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char * receipt_xpm[] = {
-"24 24 5 1",
-" c None",
-". c #FFFFFFFFFFFF",
-"X c #676766666363",
-"o c #FFFF00000000",
-"O c #AEAE3E3E4848",
-" ",
-" ",
-" .. ",
-" . ",
-" . ",
-" . ",
-" .. ",
-" Xooo .. ",
-" Xoooooooo.. ",
-" Xoooooooooooooo ... ",
-" oooooooooooOOoo . ",
-" ooooooooooOOOOo. ",
-" oooooooooOO...o ",
-" ooooooooooOOooo ",
-" ooooooooooooooo ",
-" ooooooooooooooo ",
-" oooooooooooooo ",
-" ooooooooooo ",
-" ooooooo ",
-" oooo ",
-" oo ",
-" ",
-" ",
-" "};
diff --git a/etc/images/gnus/reply-wo.pbm b/etc/images/gnus/reply-wo.pbm
deleted file mode 100644
index def54da8ede..00000000000
--- a/etc/images/gnus/reply-wo.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/reply-wo.xpm b/etc/images/gnus/reply-wo.xpm
deleted file mode 100644
index 370678af70d..00000000000
--- a/etc/images/gnus/reply-wo.xpm
+++ /dev/null
@@ -1,31 +0,0 @@
-/* XPM */
-static char * reply_wo_xpm[] = {
-"24 24 4 1",
-" c None",
-". c #000000000000",
-"X c #E1E1E0E0E0E0",
-"O c #FFFFFFFFFFFF",
-" ",
-" ",
-" ",
-" .... ",
-" ..X.... ",
-" ..XX.XX.. ",
-" .O.XX.XXXX.. ",
-" ..O.XXX.XXXX... ",
-" .OO.XXXX.X....... ",
-" .OO.XXXX...XXX.OO.. ",
-" ..OO.XX....XXXX.OOOO.. ",
-" .......XX.XXXX.OOO.... ",
-" .OOO.XXX.XXXX.OO..OOO. ",
-" .OOOO....XXX....OOOOO. ",
-" .OOOOOOO..XX..OOOOOOO. ",
-" .OOOOOOO......OOOOOOO. ",
-" .OOOOOO.OO..O..OOOOOO. ",
-" .OOOOO.OOOOOOOO.OOOOO. ",
-" .OOOO.OOOOOOOOOO.OOOO. ",
-" .OOO.OOOOOOOOOOOO.OOO. ",
-" .O..OOOOOOOOOOOOOO..O. ",
-" ..OOOOOOOOOOOOOOOOOO.. ",
-" ...................... ",
-" "};
diff --git a/etc/images/gnus/reply.pbm b/etc/images/gnus/reply.pbm
deleted file mode 100644
index ee181e663be..00000000000
--- a/etc/images/gnus/reply.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/reply.xpm b/etc/images/gnus/reply.xpm
deleted file mode 100644
index a45884803fe..00000000000
--- a/etc/images/gnus/reply.xpm
+++ /dev/null
@@ -1,31 +0,0 @@
-/* XPM */
-static char * reply_xpm[] = {
-"24 24 4 1",
-" c None",
-". c #000000000000",
-"X c #E1E1E0E0E0E0",
-"O c #FFFFFFFFFFFF",
-" ",
-" ",
-" ",
-" .... ",
-" ..XXX.. ",
-" ..XXXXX.. ",
-" .O.XXXXXXX.. ",
-" ..O.XXXXXXXXX.. ",
-" .OO.XXXXXXXXXX... ",
-" .OO.XXXXXXXXXX.OO.. ",
-" ..OO.XXXXXXXXXX.OOOO.. ",
-" .....XXXXXXXXX.OOO.... ",
-" .OOO.XXXXXXXX.OO..OOO. ",
-" .OOOO...XXXXX...OOOOO. ",
-" .OOOOOOO..XX..OOOOOOO. ",
-" .OOOOOOO......OOOOOOO. ",
-" .OOOOOO.OO..O..OOOOOO. ",
-" .OOOOO.OOOOOOOO.OOOOO. ",
-" .OOOO.OOOOOOOOOO.OOOO. ",
-" .OOO.OOOOOOOOOOOO.OOO. ",
-" .O..OOOOOOOOOOOOOO..O. ",
-" ..OOOOOOOOOOOOOOOOOO.. ",
-" ...................... ",
-" "};
diff --git a/etc/images/gnus/rot13.pbm b/etc/images/gnus/rot13.pbm
deleted file mode 100644
index 800d9d6327b..00000000000
--- a/etc/images/gnus/rot13.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/rot13.xpm b/etc/images/gnus/rot13.xpm
deleted file mode 100644
index 18faa3e92da..00000000000
--- a/etc/images/gnus/rot13.xpm
+++ /dev/null
@@ -1,128 +0,0 @@
-/* XPM */
-static char * rot13_xpm[] = {
-"24 24 101 2",
-" g None",
-". g #000000",
-"+ g #212121",
-"@ g #9E9E9E",
-"# g #E6E6E6",
-"$ g #E7E7E7",
-"% g #C8C8C8",
-"& g #A0A0A0",
-"* g #131313",
-"= g #5F5F5F",
-"- g #EDEDED",
-"; g #D6D6D6",
-"> g #D5D5D5",
-", g #DDDDDD",
-"' g #D8D8D8",
-") g #A1A1A1",
-"! g #3C3C3C",
-"~ g #353535",
-"{ g #EFEFEF",
-"] g #CFCFCF",
-"^ g #4C4C4C",
-"/ g #141414",
-"( g #6A6A6A",
-"_ g #D0D0D0",
-": g #B2B2B2",
-"< g #454545",
-"[ g #E2E2E2",
-"} g #292929",
-"| g #0F0F0F",
-"1 g #949494",
-"2 g #E9E9E9",
-"3 g #C3C3C3",
-"4 g #1C1C1C",
-"5 g #E1E1E1",
-"6 g #272727",
-"7 g #DEDEDE",
-"8 g #B6B6B6",
-"9 g #0C0C0C",
-"0 g #262626",
-"a g #1F1F1F",
-"b g #616161",
-"c g #5B5B5B",
-"d g #232323",
-"e g #111111",
-"f g #181818",
-"g g #3D3D3D",
-"h g #636363",
-"i g #545454",
-"j g #2E2E2E",
-"k g #242424",
-"l g #070707",
-"m g #DCDCDC",
-"n g #D3D3D3",
-"o g #C5C5C5",
-"p g #C2C2C2",
-"q g #BFBFBF",
-"r g #B5B5B5",
-"s g #696969",
-"t g #ACACAC",
-"u g #999999",
-"v g #8F8F8F",
-"w g #868686",
-"x g #686868",
-"y g #B1B1B1",
-"z g #9A9A9A",
-"A g #909090",
-"B g #878787",
-"C g #DBDBDB",
-"D g #A6A6A6",
-"E g #979797",
-"F g #8A8A8A",
-"G g #8D8D8D",
-"H g #838383",
-"I g #666666",
-"J g #BBBBBB",
-"K g #9F9F9F",
-"L g #8B8B8B",
-"M g #828282",
-"N g #676767",
-"O g #A3A3A3",
-"P g #8E8E8E",
-"Q g #888888",
-"R g #8C8C8C",
-"S g #BABABA",
-"T g #818181",
-"U g #757575",
-"V g #DADADA",
-"W g #AFAFAF",
-"X g #848484",
-"Y g #7F7F7F",
-"Z g #7B7B7B",
-"` g #B8B8B8",
-" . g #D9D9D9",
-".. g #ABABAB",
-"+. g #929292",
-"@. g #939393",
-"#. g #808080",
-"$. g #919191",
-"%. g #ADADAD",
-"&. g #969696",
-"*. g #4A4A4A",
-" ",
-" ",
-" . . . . . ",
-" . + @ # $ % & * ",
-" . = - # ; > , ' ) ! . ",
-" ~ { ] ^ . . / ( _ : < ",
-" . [ ' } . | ( % 1 . ",
-" * 2 3 . 4 5 @ . ",
-" 6 7 8 . . $ 8 . ",
-" 9 0 a b c d e 6 a f a g h i j k l ",
-" . 7 m ' ; n o p p p p q r r r s . ",
-" . 7 p 8 : t t t t t t t u v w x . ",
-" . m p 8 y t t t t t t t z A B s . ",
-" . C p r D E E E E E E A F G H I . ",
-" . , p 8 J t t t t t t t K L M N . ",
-" . m p y O E E E E E E P Q R H ( . ",
-" . m p r S t t t t t t t K L T U . ",
-" . V p W & E E E E E E F X B Y Z . ",
-" . C p y ` t t t t t t t K F B T . ",
-" . .p W ..E E E E E E E +.G @.#.. ",
-" . $.%.z &.A L F F G $.A A P X *.. ",
-" . . . . . . . . . . . . . . . ",
-" ",
-" "};
diff --git a/etc/images/gnus/save-aif.pbm b/etc/images/gnus/save-aif.pbm
deleted file mode 100644
index 15829c289e7..00000000000
--- a/etc/images/gnus/save-aif.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/save-aif.xpm b/etc/images/gnus/save-aif.xpm
deleted file mode 100644
index f0325ac2fb9..00000000000
--- a/etc/images/gnus/save-aif.xpm
+++ /dev/null
@@ -1,33 +0,0 @@
-/* XPM */
-static char * save_aif_xpm[] = {
-"24 24 6 1",
-" c None",
-". c #999999999999",
-"X c #E1E1E0E0E0E0",
-"o c #C7C7C6C6C6C6",
-"O c #000000000000",
-"+ c #FFFFFFFFFFFF",
-" ",
-" ",
-" ............. ",
-" .XXXXXXXXXX.X.. ",
-" .XXXXXXXXXX.XX. ",
-" .XXXXXXXXXX.... ",
-" .XXXXXXXXXXooo. ",
-" .XXXXXXXXXXXXX. ",
-" .XXXXXXXXXXXXX. ",
-" .XXXXXXXXXXXXX. ",
-" OOOOOOOOOOOOOOXXXXXX. ",
-" O..O+++++++O.OXXXXXX. ",
-" O..O+++++++O.OXXXXXX. ",
-" O..O+++++++O.OXXXXXX. ",
-" O..O+++++++O.OXXXXXX. ",
-" O..O+++++++O.OXXXXXX. ",
-" O..OOOOOOOOO.OXXXXXX. ",
-" O............OXXXXXX. ",
-" O............OXXXXXX. ",
-" O..OOOOOOOOO.O....... ",
-" O..OoooooO++.O ",
-" O..OoooooO++.O ",
-" O.OoooooO++.O ",
-" OOOOOOOOOOOO "};
diff --git a/etc/images/gnus/save-art.pbm b/etc/images/gnus/save-art.pbm
deleted file mode 100644
index 68fe0cb3098..00000000000
--- a/etc/images/gnus/save-art.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/save-art.xpm b/etc/images/gnus/save-art.xpm
deleted file mode 100644
index fe9726fa3fe..00000000000
--- a/etc/images/gnus/save-art.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char * save_art_xpm[] = {
-"24 24 5 1",
-" c None",
-". c #000000000000",
-"X c #FFFFFFFFFFFF",
-"o c #999999999999",
-"O c #C7C7C6C6C6C6",
-" ",
-" ",
-" .................. ",
-" ...XXXXXXXXXXXXX.. ",
-" .XX..XXXXXXXXX..X. ",
-" .XXXX..XXXXX..XXX. ",
-" .XXXXX......XXXXX. ",
-" .XXX..XX..XX..XXX. ",
-" .XX..XXXXXXXX..XX. ",
-" ...XXXXXXXXXXXX... ",
-" ..............XXXXXXX. ",
-" .oo.XXXXXXX.o......... ",
-" .oo.XXXXXXX.o. ",
-" .oo.XXXXXXX.o. ",
-" .oo.XXXXXXX.o. ",
-" .oo.XXXXXXX.o. ",
-" .oo.........o. ",
-" .oooooooooooo. ",
-" .oooooooooooo. ",
-" .oo.........o. ",
-" .oo.OOOOO.XXo. ",
-" .oo.OOOOO.XXo. ",
-" .o.OOOOO.XXo. ",
-" ............ "};
diff --git a/etc/images/gnus/subscribe.pbm b/etc/images/gnus/subscribe.pbm
deleted file mode 100644
index fe6b3920d36..00000000000
--- a/etc/images/gnus/subscribe.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/subscribe.xpm b/etc/images/gnus/subscribe.xpm
deleted file mode 100644
index ff193a9e8ab..00000000000
--- a/etc/images/gnus/subscribe.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char * subscribe_xpm[] = {
-"24 24 5 1",
-" c None",
-". c #A5A5A5A59595",
-"X c #E1E1E0E0E0E0",
-"o c #C7C7C6C6C6C6",
-"O c #8686ADAD7D7D",
-" ",
-" ",
-" ",
-" ... ",
-" ..XXX..... ",
-"...XXXXX..XXX. ... ",
-".X.XX...XXXX...XXX. ",
-".XX.X.X.XX...XXXXX. ",
-".XX...XX.X.X.XXXXXX. ",
-".XX.o.XX...XX.XXXXXX. ",
-".X.oo.XX.o.XX..XXXXXX. ",
-"o.ooo.X.oo.XX.XXXOXXX. ",
-"o.oXXo.ooo.X.oXXOXXXXX. ",
-" o.XXo.oXXo.ooXXOXXXXX. ",
-" o.XXXo.XXo.oXXXOXXXXXX.",
-" o.XXo.XXXo.XOOOOXXXXX.",
-" o.XXoo.XXo.XXXOOXXXXX.",
-" o.XXo.XXXo.XXXXXXX...",
-" o.XX.o.XXo.XXXXXX.oo ",
-" o..oo.XX.o.XXX..o ",
-" oo o..oo.XX.oo ",
-" oo o..o ",
-" oo ",
-" "};
diff --git a/etc/images/gnus/unimportant.pbm b/etc/images/gnus/unimportant.pbm
deleted file mode 100644
index 26a87216247..00000000000
--- a/etc/images/gnus/unimportant.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/unimportant.xpm b/etc/images/gnus/unimportant.xpm
deleted file mode 100644
index 4298224e56c..00000000000
--- a/etc/images/gnus/unimportant.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char *magick[] = {
-/* columns rows colors chars-per-pixel */
-"24 24 2 1",
-"! c blue",
-"w c Gray75",
-/* pixels */
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"ww!!!wwwwww!!!wwwwww!!!w",
-"www!!!wwwww!!!wwwww!!!ww",
-"wwww!!!wwww!!!wwww!!!www",
-"wwwww!!!www!!!www!!!wwww",
-"wwwwww!!!ww!!!ww!!!wwwww",
-"wwwwwww!!!w!!!w!!!wwwwww",
-"wwwwwwww!!!!!!!!!wwwwwww",
-"wwwwwwwww!!!!!!!wwwwwwww",
-"wwwwwwwwww!!!!!wwwwwwwww",
-"wwwwwwwwwww!!!wwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww",
-"wwwwwwwwwwwwwwwwwwwwwwww"
-};
diff --git a/etc/images/gnus/unsubscribe.pbm b/etc/images/gnus/unsubscribe.pbm
deleted file mode 100644
index 7d869fb53fe..00000000000
--- a/etc/images/gnus/unsubscribe.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/unsubscribe.xpm b/etc/images/gnus/unsubscribe.xpm
deleted file mode 100644
index a91180d00f8..00000000000
--- a/etc/images/gnus/unsubscribe.xpm
+++ /dev/null
@@ -1,32 +0,0 @@
-/* XPM */
-static char * unsubscribe_xpm[] = {
-"24 24 5 1",
-" c None",
-". c #A5A5A5A59595",
-"X c #E1E1E0E0E0E0",
-"o c #C7C7C6C6C6C6",
-"O c #FFFF00000000",
-" ",
-" ",
-" ",
-" ... ",
-" ..XXX..... ",
-"...XXXXX..XXX. ... ",
-".X.XX...XXXX...XXX. ",
-".XX.X.X.XX...XXXXX. ",
-".XX...XX.X.X.XXXXXX. ",
-".XX.o.XX...XX.XXXXXX. ",
-".X.oo.XX.o.XX..XXXXXX. ",
-"o.ooo.X.oo.XX.XXXXXXX. ",
-"o.oXXo.ooo.X.oXXXXXXXX. ",
-" o.XXo.oXXo.ooXXOXXXXX. ",
-" o.XXXo.XXo.oXXXOXXXXXX.",
-" o.XXo.XXXo.XOOOXXXXXX.",
-" o.XXoo.XXo.XoOOOXXXXX.",
-" o.XXo.XXXo.XOoOXXX...",
-" o.XX.o.XXo.XOXoXX.oo ",
-" o..oo.XX.o.oXX..o ",
-" oo o..oo.XX.oo ",
-" oo o..o ",
-" oo ",
-" "};
diff --git a/etc/images/gnus/uu-decode.pbm b/etc/images/gnus/uu-decode.pbm
deleted file mode 100644
index 2b7fada1473..00000000000
--- a/etc/images/gnus/uu-decode.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/uu-decode.xpm b/etc/images/gnus/uu-decode.xpm
deleted file mode 100644
index b9d940cc99e..00000000000
--- a/etc/images/gnus/uu-decode.xpm
+++ /dev/null
@@ -1,36 +0,0 @@
-/* XPM */
-static char * uu_decode_xpm[] = {
-"24 24 9 1",
-" c None",
-". c #919187876969",
-"X c #C2C2B9B99C9C",
-"o c #868686868686",
-"O c #8F8F8F8F8F8F",
-"+ c #000000000000",
-"@ c #4C4C4C4C4C4C",
-"# c #E9E9EFEFE8E8",
-"$ c #8686ADAD7D7D",
-" ",
-" ",
-" ",
-" .............. ",
-" X.o.........O.++ ",
-" XX++++++++++..++ ",
-" XX@########+..++ ",
-" XX@########+..++ ",
-" XX@$#$$$#$#+..++ ",
-" XX@#$$$$$$#+..++ ",
-" XX@##$#####+..++ ",
-" XX@##$#$$##+..++ ",
-" XX@##$#$$##+..++ ",
-" XX@##$$#$$#+..++ ",
-" XX@######$#+..++ ",
-" XX@########+..++ ",
-" XX@########+..++ ",
-" XX.@@@@@@@@@..++ ",
-" X.XXXXXXXXXX..++ ",
-" .XXXXXXXXXXXX.++ ",
-" +++++++++++++++ ",
-" +++++++++++++++ ",
-" ",
-" "};
diff --git a/etc/images/gnus/uu-post.pbm b/etc/images/gnus/uu-post.pbm
deleted file mode 100644
index a5face70980..00000000000
--- a/etc/images/gnus/uu-post.pbm
+++ /dev/null
Binary files differ
diff --git a/etc/images/gnus/uu-post.xpm b/etc/images/gnus/uu-post.xpm
deleted file mode 100644
index 7c4204c6957..00000000000
--- a/etc/images/gnus/uu-post.xpm
+++ /dev/null
@@ -1,35 +0,0 @@
-/* XPM */
-static char * uu_post_xpm[] = {
-"24 24 8 1",
-". c None",
-"X c #000000000000",
-"+ c #C2C2B9B99C9C",
-"@ c #919187876969",
-"# c #868686868686",
-"% c #4C4C4C4C4C4C",
-"& c #E9E9EFEFE8E8",
-"* c #8686ADAD7D7D",
-"X..X..X..X.XX..X..X..X..",
-"..........X.X...........",
-".........X...X..........",
-"X..X..X.XX..X.XX..X..X..",
-".......X.......X........",
-"......X.........X.......",
-"X..X+X@@@@@@@@@@@XX..X..",
-"....+@@@@@@@@@@@@@......",
-"....++XXXXXXXXXX@@......",
-"X..X++%&&&&&&&&X@@X..X..",
-"....++%&&&&&&&&X@@......",
-"....++%*&***&*&X@@......",
-"X..X++%&******&X@@X..X..",
-"....++%&&*&&&&&X@@......",
-"....++%&&*&**&&X@@......",
-"X..X++%&&*&**&&X@@X..X..",
-"....++%&&**&**&X@@......",
-"....++%&&&&&&*&X@@......",
-"X..X++%&&&&&&&&X@@X..X..",
-"....++%&&&&&&&&X@@......",
-"....++@%%%%%%%%%@@......",
-"X..X+@++++++++++@@X..X..",
-"....+++++++++++++@......",
-"........................"};
diff --git a/etc/images/tree-widget/default/nohandle-guide.png b/etc/images/tree-widget/default/nohandle-guide.png
new file mode 100644
index 00000000000..85fa0c87b7b
--- /dev/null
+++ b/etc/images/tree-widget/default/nohandle-guide.png
Binary files differ
diff --git a/etc/images/tree-widget/default/nohandle-guide.xpm b/etc/images/tree-widget/default/nohandle-guide.xpm
new file mode 100644
index 00000000000..85b3cec00ce
--- /dev/null
+++ b/etc/images/tree-widget/default/nohandle-guide.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char * guide_xpm[] = {
+"6 21 2 1",
+" c None",
+". c #ADA5C6",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" ."};
diff --git a/etc/images/tree-widget/folder/nohandle-guide.png b/etc/images/tree-widget/folder/nohandle-guide.png
new file mode 100644
index 00000000000..8535f86f3bf
--- /dev/null
+++ b/etc/images/tree-widget/folder/nohandle-guide.png
Binary files differ
diff --git a/etc/images/tree-widget/folder/nohandle-guide.xpm b/etc/images/tree-widget/folder/nohandle-guide.xpm
new file mode 100644
index 00000000000..647d0590173
--- /dev/null
+++ b/etc/images/tree-widget/folder/nohandle-guide.xpm
@@ -0,0 +1,27 @@
+/* XPM */
+static char * guide_xpm[] = {
+"6 22 2 1",
+" c None",
+". c #ADA5C6",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" .",
+" ",
+" ."};
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index fb018d626a7..18cb313a321 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -9,7 +9,7 @@
// ===BEGIN ICANN DOMAINS===
-// ac : https://en.wikipedia.org/wiki/.ac
+// ac : http://nic.ac/rules.htm
ac
com.ac
edu.ac
@@ -22,8 +22,7 @@ org.ac
ad
nom.ad
-// ae : https://en.wikipedia.org/wiki/.ae
-// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
+// ae : https://tdra.gov.ae/en/aeda/ae-policies
ae
co.ae
net.ae
@@ -865,6 +864,7 @@ gov.cx
// cy : http://www.nic.cy/
// Submitted by registry Panayiotou Fotia <cydns@ucy.ac.cy>
+// namespace policies URL https://www.nic.cy/portal//sites/default/files/symfonia_gia_eggrafi.pdf
cy
ac.cy
biz.cy
@@ -872,10 +872,9 @@ com.cy
ekloges.cy
gov.cy
ltd.cy
-name.cy
+mil.cy
net.cy
org.cy
-parliament.cy
press.cy
pro.cy
tm.cy
@@ -1341,7 +1340,7 @@ tt.im
tv.im
// in : https://en.wikipedia.org/wiki/.in
-// see also: https://registry.in/Policies
+// see also: https://registry.in/policies
// Please note, that nic.in is not an official eTLD, but used by most
// government institutions.
in
@@ -1366,7 +1365,7 @@ info
int
eu.int
-// io : http://www.nic.io/rules.html
+// io : http://www.nic.io/rules.htm
// list of other 2nd level tlds ?
io
com.io
@@ -3765,11 +3764,10 @@ org.kw
// ky : http://www.icta.ky/da_ky_reg_dom.php
// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
ky
-edu.ky
-gov.ky
com.ky
-org.ky
+edu.ky
net.ky
+org.ky
// kz : https://en.wikipedia.org/wiki/.kz
// see also: http://www.nic.kz/rules/index.jsp
@@ -6037,7 +6035,7 @@ gov.sg
edu.sg
per.sg
-// sh : http://www.nic.sh/registrar.html
+// sh : http://nic.sh/rules.htm
sh
com.sh
net.sh
@@ -7132,7 +7130,7 @@ org.zw
// newGTLDs
-// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-12-30T15:13:57Z
+// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-06-14T15:15:19Z
// This list is auto-generated, don't edit it manually.
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa
@@ -7335,7 +7333,7 @@ audi
// audible : 2015-06-25 Amazon Registry Services, Inc.
audible
-// audio : 2014-03-20 UNR Corp.
+// audio : 2014-03-20 XYZ.COM LLC
audio
// auspost : 2015-08-13 Australian Postal Corporation
@@ -7473,7 +7471,7 @@ bio
// black : 2014-01-16 Afilias Limited
black
-// blackfriday : 2014-01-16 UNR Corp.
+// blackfriday : 2014-01-16 Registry Services, LLC
blackfriday
// blockbuster : 2015-07-30 Dish DBS Corporation
@@ -7557,9 +7555,6 @@ brother
// brussels : 2014-02-06 DNS.be vzw
brussels
-// budapest : 2013-11-21 Minds + Machines Group Limited
-budapest
-
// bugatti : 2015-07-23 Bugatti International SA
bugatti
@@ -7596,7 +7591,7 @@ call
// calvinklein : 2015-07-30 PVH gTLD Holdings LLC
calvinklein
-// cam : 2016-04-21 AC Webconnecting Holding B.V.
+// cam : 2016-04-21 Cam Connecting SARL
cam
// camera : 2013-08-27 Binky Moon, LLC
@@ -7692,7 +7687,7 @@ chanel
// channel : 2014-05-08 Charleston Road Registry Inc.
channel
-// charity : 2018-04-11 Binky Moon, LLC
+// charity : 2018-04-11 Public Interest Registry
charity
// chase : 2015-04-30 JPMorgan Chase Bank, National Association
@@ -7707,7 +7702,7 @@ cheap
// chintai : 2015-06-11 CHINTAI Corporation
chintai
-// christmas : 2013-11-21 UNR Corp.
+// christmas : 2013-11-21 XYZ.COM LLC
christmas
// chrome : 2014-07-24 Charleston Road Registry Inc.
@@ -7839,7 +7834,7 @@ coupon
// coupons : 2015-03-26 Binky Moon, LLC
coupons
-// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD
+// courses : 2014-12-04 Registry Services, LLC
courses
// cpa : 2019-06-10 American Institute of Certified Public Accountants
@@ -7869,9 +7864,6 @@ cruise
// cruises : 2013-12-05 Binky Moon, LLC
cruises
-// csc : 2014-09-25 Alliance-One Services, Inc.
-csc
-
// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S.
cuisinella
@@ -7959,7 +7951,7 @@ dhl
// diamonds : 2013-09-22 Binky Moon, LLC
diamonds
-// diet : 2014-06-26 UNR Corp.
+// diet : 2014-06-26 XYZ.COM LLC
diet
// digital : 2014-03-06 Binky Moon, LLC
@@ -8205,7 +8197,7 @@ flir
// florist : 2013-11-07 Binky Moon, LLC
florist
-// flowers : 2014-10-09 UNR Corp.
+// flowers : 2014-10-09 XYZ.COM LLC
flowers
// fly : 2014-05-08 Charleston Road Registry Inc.
@@ -8235,7 +8227,7 @@ forsale
// forum : 2015-04-02 Fegistry, LLC
forum
-// foundation : 2013-12-05 Binky Moon, LLC
+// foundation : 2013-12-05 Public Interest Registry
foundation
// fox : 2015-09-11 FOX Registry, LLC
@@ -8292,7 +8284,7 @@ gallo
// gallup : 2015-02-19 Gallup, Inc.
gallup
-// game : 2015-05-28 UNR Corp.
+// game : 2015-05-28 XYZ.COM LLC
game
// games : 2015-05-28 Dog Beach, LLC
@@ -8316,7 +8308,7 @@ gdn
// gea : 2014-12-04 GEA Group Aktiengesellschaft
gea
-// gent : 2014-01-23 COMBELL NV
+// gent : 2014-01-23 Easyhost BV
gent
// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
@@ -8334,7 +8326,7 @@ gift
// gifts : 2014-07-03 Binky Moon, LLC
gifts
-// gives : 2014-03-06 Dog Beach, LLC
+// gives : 2014-03-06 Public Interest Registry
gives
// giving : 2014-11-13 Giving Limited
@@ -8427,7 +8419,7 @@ guge
// guide : 2013-09-13 Binky Moon, LLC
guide
-// guitars : 2013-11-14 UNR Corp.
+// guitars : 2013-11-14 XYZ.COM LLC
guitars
// guru : 2013-08-27 Binky Moon, LLC
@@ -8460,7 +8452,7 @@ health
// healthcare : 2014-06-12 Binky Moon, LLC
healthcare
-// help : 2014-06-26 UNR Corp.
+// help : 2014-06-26 Innovation service Limited
help
// helsinki : 2015-02-05 City of Helsinki
@@ -8475,7 +8467,7 @@ hermes
// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc.
hgtv
-// hiphop : 2014-03-06 UNR Corp.
+// hiphop : 2014-03-06 Dot Hip Hop, LLC
hiphop
// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc.
@@ -8523,7 +8515,7 @@ hospital
// host : 2014-04-17 Radix FZC
host
-// hosting : 2014-05-29 UNR Corp.
+// hosting : 2014-05-29 XYZ.COM LLC
hosting
// hot : 2015-08-27 Amazon Registry Services, Inc.
@@ -8859,7 +8851,7 @@ lincoln
// linde : 2014-12-04 Linde Aktiengesellschaft
linde
-// link : 2013-11-14 UNR Corp.
+// link : 2013-11-14 Nova Registry Ltd
link
// lipsy : 2015-06-25 Lipsy Ltd
@@ -8874,7 +8866,7 @@ living
// llc : 2017-12-14 Afilias Limited
llc
-// llp : 2019-08-26 UNR Corp.
+// llp : 2019-08-26 Intercap Registry Inc.
llp
// loan : 2014-11-20 dot Loan Limited
@@ -8892,7 +8884,7 @@ locus
// loft : 2015-07-30 Annco, Inc.
loft
-// lol : 2015-01-30 UNR Corp.
+// lol : 2015-01-30 XYZ.COM LLC
lol
// london : 2013-11-14 Dot London Domains Limited
@@ -9048,7 +9040,7 @@ moe
// moi : 2014-12-18 Amazon Registry Services, Inc.
moi
-// mom : 2015-04-16 UNR Corp.
+// mom : 2015-04-16 XYZ.COM LLC
mom
// monash : 2013-09-30 Monash University
@@ -9315,7 +9307,7 @@ philips
// phone : 2016-06-02 Dish DBS Corporation
phone
-// photo : 2013-11-14 UNR Corp.
+// photo : 2013-11-14 Registry Services, LLC
photo
// photography : 2013-09-20 Binky Moon, LLC
@@ -9327,7 +9319,7 @@ photos
// physio : 2014-05-01 PhysBiz Pty Ltd
physio
-// pics : 2013-11-14 UNR Corp.
+// pics : 2013-11-14 XYZ.COM LLC
pics
// pictet : 2014-06-26 Pictet Europe S.A.
@@ -9558,7 +9550,7 @@ rsvp
// rugby : 2016-12-15 World Rugby Strategic Developments Limited
rugby
-// ruhr : 2013-10-02 regiodot GmbH & Co. KG
+// ruhr : 2013-10-02 dotSaarland GmbH
ruhr
// run : 2015-03-19 Binky Moon, LLC
@@ -9849,7 +9841,7 @@ stream
// studio : 2015-02-11 Dog Beach, LLC
studio
-// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
+// study : 2014-12-11 Registry Services, LLC
study
// style : 2014-12-04 Binky Moon, LLC
@@ -9909,7 +9901,7 @@ tatamotors
// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
tatar
-// tattoo : 2013-08-30 UNR Corp.
+// tattoo : 2013-08-30 Top Level Design, LLC
tattoo
// tax : 2014-03-20 Binky Moon, LLC
@@ -10002,7 +9994,7 @@ toray
// toshiba : 2014-04-10 TOSHIBA Corporation
toshiba
-// total : 2015-08-06 Total SA
+// total : 2015-08-06 TOTAL SE
total
// tours : 2015-01-22 Binky Moon, LLC
@@ -10640,6 +10632,16 @@ hlx3.page
// Submitted by Przemyslaw Plewa <it-admin@domena.pl>
beep.pl
+// Airkit : https://www.airkit.com/
+// Submitted by Grant Cooksey <security@airkit.com>
+airkitapps.com
+airkitapps-au.com
+airkitapps.eu
+
+// Aiven: https://aiven.io/
+// Submitted by Etienne Stalmans <security@aiven.io>
+aivencloud.com
+
// alboto.ca : http://alboto.ca
// Submitted by Anton Avramov <avramov@alboto.ca>
barsy.ca
@@ -10812,6 +10814,10 @@ myasustor.com
// Submitted by Sam Smyth <devloop@atlassian.com>
cdn.prod.atlassian-dev.net
+// Authentick UG (haftungsbeschränkt) : https://authentick.net
+// Submitted by Lukas Reschke <lukas@authentick.net>
+translated.page
+
// AVM : https://avm.de
// Submitted by Andreas Weise <a.weise@avm.de>
myfritz.net
@@ -10826,7 +10832,7 @@ onavstack.net
*.advisor.ws
// AZ.pl sp. z.o.o: https://az.pl
-// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
+// Submitted by Krzysztof Wolski <krzysztof.wolski@home.eu>
ecommerce-shop.pl
// b-data GmbH : https://www.b-data.io
@@ -10865,6 +10871,10 @@ theshop.jp
shopselect.net
base.shop
+// Beget Ltd
+// Submitted by Lev Nekrasov <lnekrasov@beget.com>
+*.beget.app
+
// BetaInABox
// Submitted by Adrian <adrian@betainabox.com>
betainabox.com
@@ -11106,6 +11116,10 @@ cloudns.us
// Submitted by Angelo Gladding <angelo@lahacker.net>
cnpy.gdn
+// Codeberg e. V. : https://codeberg.org
+// Submitted by Moritz Marquardt <git@momar.de>
+codeberg.page
+
// CoDNS B.V.
co.nl
co.no
@@ -11232,11 +11246,21 @@ deno-staging.dev
// Submitted by Peter Thomassen <peter@desec.io>
dedyn.io
+// Deta: https://www.deta.sh/
+// Submitted by Aavash Shrestha <aavash@deta.sh>
+deta.app
+deta.dev
+
// Diher Solutions : https://diher.solutions
// Submitted by Didi Hermawan <mail@diher.solutions>
*.rss.my.id
*.diher.solutions
+// Discord Inc : https://discord.com
+// Submitted by Sahn Lam <slam@discordapp.com>
+discordsays.com
+discordsez.com
+
// DNS Africa Ltd https://dns.business
// Submitted by Calvin Browne <calvin@dns.business>
jozi.biz
@@ -11644,6 +11668,11 @@ en-root.fr
mytuleap.com
tuleap-partners.com
+// Encoretivity AB: https://encore.dev
+// Submitted by André Eriksson <andre@encore.dev>
+encr.app
+encoreapi.com
+
// ECG Robotics, Inc: https://ecgrobotics.org
// Submitted by <frc1533@ecgrobotics.org>
onred.one
@@ -11856,8 +11885,6 @@ app.os.stg.fedoraproject.org
// FearWorks Media Ltd. : https://fearworksmedia.co.uk
// submitted by Keith Fairley <domains@fearworksmedia.co.uk>
-couk.me
-ukco.me
conn.uk
copro.uk
hosp.uk
@@ -11961,10 +11988,22 @@ futuremailing.at
*.kunden.ortsinfo.at
*.statics.cloud
-// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains
-// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk>
+// GDS : https://www.gov.uk/service-manual/technology/managing-domain-names
+// Submitted by Stephen Ford <hostmaster@digital.cabinet-office.gov.uk>
+independent-commission.uk
+independent-inquest.uk
+independent-inquiry.uk
+independent-panel.uk
+independent-review.uk
+public-inquiry.uk
+royal-commission.uk
+campaign.gov.uk
service.gov.uk
+// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk
+// Submitted by Jamie Tanna <jamie.tanna@digital.cabinet-office.gov.uk>
+api.gov.uk
+
// Gehirn Inc. : https://www.gehirn.co.jp/
// Submitted by Kohei YOSHIDA <tech@gehirn.co.jp>
gehirn.ne.jp
@@ -12014,8 +12053,114 @@ co.ro
shop.ro
// GMO Pepabo, Inc. : https://pepabo.com/
-// Submitted by dojineko <admin@pepabo.com>
+// Submitted by Hosting Div <admin@pepabo.com>
lolipop.io
+angry.jp
+babyblue.jp
+babymilk.jp
+backdrop.jp
+bambina.jp
+bitter.jp
+blush.jp
+boo.jp
+boy.jp
+boyfriend.jp
+but.jp
+candypop.jp
+capoo.jp
+catfood.jp
+cheap.jp
+chicappa.jp
+chillout.jp
+chips.jp
+chowder.jp
+chu.jp
+ciao.jp
+cocotte.jp
+coolblog.jp
+cranky.jp
+cutegirl.jp
+daa.jp
+deca.jp
+deci.jp
+digick.jp
+egoism.jp
+fakefur.jp
+fem.jp
+flier.jp
+floppy.jp
+fool.jp
+frenchkiss.jp
+girlfriend.jp
+girly.jp
+gloomy.jp
+gonna.jp
+greater.jp
+hacca.jp
+heavy.jp
+her.jp
+hiho.jp
+hippy.jp
+holy.jp
+hungry.jp
+icurus.jp
+itigo.jp
+jellybean.jp
+kikirara.jp
+kill.jp
+kilo.jp
+kuron.jp
+littlestar.jp
+lolipopmc.jp
+lolitapunk.jp
+lomo.jp
+lovepop.jp
+lovesick.jp
+main.jp
+mods.jp
+mond.jp
+mongolian.jp
+moo.jp
+namaste.jp
+nikita.jp
+nobushi.jp
+noor.jp
+oops.jp
+parallel.jp
+parasite.jp
+pecori.jp
+peewee.jp
+penne.jp
+pepper.jp
+perma.jp
+pigboat.jp
+pinoko.jp
+punyu.jp
+pupu.jp
+pussycat.jp
+pya.jp
+raindrop.jp
+readymade.jp
+sadist.jp
+schoolbus.jp
+secret.jp
+staba.jp
+stripper.jp
+sub.jp
+sunnyday.jp
+thick.jp
+tonkotsu.jp
+under.jp
+upper.jp
+velvet.jp
+verse.jp
+versus.jp
+vivian.jp
+watson.jp
+weblike.jp
+whitesnow.jp
+zombie.jp
+heteml.net
// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/
// Submitted by Tom Whitwell <gov-uk-paas-support@digital.cabinet-office.gov.uk>
@@ -12137,6 +12282,10 @@ blogspot.vn
// Submitted by Niels Martignene <hello@goupile.fr>
goupile.fr
+// Government of the Netherlands: https://www.government.nl
+// Submitted by <domeinnaam@minaz.nl>
+gov.nl
+
// Group 53, LLC : https://www.group53.com
// Submitted by Tyler Todd <noc@nova53.net>
awsmppl.com
@@ -12147,7 +12296,7 @@ günstigbestellen.de
günstigliefern.de
// Hakaran group: http://hakaran.cz
-// Submited by Arseniy Sokolov <security@hakaran.cz>
+// Submitted by Arseniy Sokolov <security@hakaran.cz>
fin.ci
free.hr
caa.li
@@ -12190,7 +12339,7 @@ development.run
ravendb.run
// home.pl S.A.: https://home.pl
-// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
+// Submitted by Krzysztof Wolski <krzysztof.wolski@home.eu>
homesklep.pl
// Hong Kong Productivity Council: https://www.hkpc.org/
@@ -12213,7 +12362,6 @@ ltd.ng
ngo.ng
edu.scot
sch.so
-org.yt
// HostyHosting (hostyhosting.com)
hostyhosting.io
@@ -12231,6 +12379,11 @@ moonscale.net
// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi
+// iliad italia: https://www.iliad.it
+// Submitted by Marios Makassikis <mmakassikis@freebox.fr>
+ibxos.it
+iliadboxos.it
+
// Impertrix Solutions : <https://impertrixcdn.com>
// Submitted by Zhixiang Zhao <csuite@impertrix.com>
impertrixcdn.com
@@ -12300,7 +12453,7 @@ to.leg.br
pixolino.com
// Internet-Pro, LLP: https://netangels.ru/
-// Submited by Vasiliy Sheredeko <piphon@gmail.com>
+// Submitted by Vasiliy Sheredeko <piphon@gmail.com>
na4u.ru
// iopsys software solutions AB : https://iopsys.eu/
@@ -12311,9 +12464,11 @@ iopsys.se
// Submitted by Matthew Hardeman <mhardeman@ipifony.com>
ipifony.net
-// IServ GmbH : https://iserv.eu
-// Submitted by Kim-Alexander Brodowski <info@iserv.eu>
+// IServ GmbH : https://iserv.de
+// Submitted by Mario Hoberg <info@iserv.de>
+iservschule.de
mein-iserv.de
+schulplattform.de
schulserver.de
test-iserv.de
iserv.dev
@@ -12323,7 +12478,7 @@ iserv.dev
iobb.net
// Jelastic, Inc. : https://jelastic.com/
-// Submited by Ihor Kolodyuk <ik@jelastic.com>
+// Submitted by Ihor Kolodyuk <ik@jelastic.com>
mel.cloudlets.com.au
cloud.interhostsolutions.be
users.scale.virtualcloud.com.br
@@ -12434,6 +12589,14 @@ js.org
kaas.gg
khplay.nl
+// Kakao : https://www.kakaocorp.com/
+// Submitted by JaeYoong Lee <cec@kakaocorp.com>
+ktistory.com
+
+// Kapsi : https://kapsi.fi
+// Submitted by Tomi Juntunen <erani@kapsi.fi>
+kapsi.fi
+
// Keyweb AG : https://www.keyweb.de
// Submitted by Martin Dannehl <postmaster@keymachine.de>
keymachine.de
@@ -12515,6 +12678,10 @@ ip.linodeusercontent.com
// Submitted by Victor Velchev <admin@liquidnetlimited.com>
we.bs
+// Localcert : https://localcert.dev
+// Submitted by Lann Martin <security@localcert.dev>
+*.user.localcert.dev
+
// localzone.xyz
// Submitted by Kenny Niehage <hello@yahe.sh>
localzone.xyz
@@ -12623,6 +12790,10 @@ hra.health
miniserver.com
memset.net
+// Messerli Informatik AG : https://www.messerli.ch/
+// Submitted by Ruben Schmidmeister <psl-maintainers@messerli.ch>
+messerli.app
+
// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by Zdeněk Šustr <zdenek.sustr@cesnet.cz>
*.cloud.metacentrum.cz
@@ -12642,12 +12813,13 @@ eu.meteorapp.com
co.pl
// Microsoft Corporation : http://microsoft.com
-// Submitted by Mitch Webster <miwebst@microsoft.com>
+// Submitted by Public Suffix List Admin <msftpsladmin@microsoft.com>
*.azurecontainer.io
azurewebsites.net
azure-mobile.net
cloudapp.net
azurestaticapps.net
+1.azurestaticapps.net
centralus.azurestaticapps.net
eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
@@ -12751,7 +12923,10 @@ noop.app
// Northflank Ltd. : https://northflank.com/
// Submitted by Marco Suter <marco@northflank.com>
*.northflank.app
+*.build.run
*.code.run
+*.database.run
+*.migration.run
// Noticeable : https://noticeable.io
// Submitted by Laurent Pellegrino <security@noticeable.io>
@@ -12934,8 +13109,12 @@ orsites.com
// Submitted by Yngve Pettersen <yngve@opera.com>
operaunite.com
+// Orange : https://www.orange.com
+// Submitted by Alexandre Linte <alexandre.linte@orange.com>
+tech.orange
+
// Oursky Limited : https://authgear.com/, https://skygear.io/
-// Submited by Authgear Team <hello@authgear.com>, Skygear Developer <hello@skygear.io>
+// Submitted by Authgear Team <hello@authgear.com>, Skygear Developer <hello@skygear.io>
authgear-staging.com
authgearapps.com
skygearapp.com
@@ -13043,6 +13222,10 @@ pleskns.com
// Submitted by Maximilian Schieder <maxi@zeug.co>
dyn53.io
+// Porter : https://porter.run/
+// Submitted by Rudraksh MK <rudi@porter.run>
+onporter.run
+
// Positive Codes Technology Company : http://co.bn/faq.html
// Submitted by Zulfais <pc@co.bn>
co.bn
@@ -13204,6 +13387,10 @@ itcouldbewor.se
// Submitted by Jennifer Herting <jchits@rit.edu>
git-pages.rit.edu
+// Rocky Enterprise Software Foundation : https://resf.org
+// Submitted by Neil Hanlon <neil@resf.org>
+rocky.page
+
// Rusnames Limited: http://rusnames.ru/
// Submitted by Sergey Zotov <admin@rusnames.ru>
биз.рус
@@ -13217,6 +13404,12 @@ git-pages.rit.edu
спб.рус
я.рус
+// Salesforce.com, Inc. https://salesforce.com/
+// Submitted by Michael Biven <mbiven@salesforce.com>
+*.builder.code.com
+*.dev-builder.code.com
+*.stg-builder.code.com
+
// Sandstorm Development Group, Inc. : https://sandcats.io/
// Submitted by Asheesh Laroia <asheesh@sandstorm.io>
sandcats.io
@@ -13226,6 +13419,34 @@ sandcats.io
logoip.de
logoip.com
+// Scaleway : https://www.scaleway.com/
+// Submitted by Rémy Léone <rleone@scaleway.com>
+fr-par-1.baremetal.scw.cloud
+fr-par-2.baremetal.scw.cloud
+nl-ams-1.baremetal.scw.cloud
+fnc.fr-par.scw.cloud
+functions.fnc.fr-par.scw.cloud
+k8s.fr-par.scw.cloud
+nodes.k8s.fr-par.scw.cloud
+s3.fr-par.scw.cloud
+s3-website.fr-par.scw.cloud
+whm.fr-par.scw.cloud
+priv.instances.scw.cloud
+pub.instances.scw.cloud
+k8s.scw.cloud
+k8s.nl-ams.scw.cloud
+nodes.k8s.nl-ams.scw.cloud
+s3.nl-ams.scw.cloud
+s3-website.nl-ams.scw.cloud
+whm.nl-ams.scw.cloud
+k8s.pl-waw.scw.cloud
+nodes.k8s.pl-waw.scw.cloud
+s3.pl-waw.scw.cloud
+s3-website.pl-waw.scw.cloud
+scalebook.scw.cloud
+smartlabeling.scw.cloud
+dedibox.fr
+
// schokokeks.org GbR : https://schokokeks.org/
// Submitted by Hanno Böck <hanno@schokokeks.org>
schokokeks.net
@@ -13346,6 +13567,8 @@ srht.site
stackhero-network.com
// Staclar : https://staclar.com
+// Submitted by Q Misell <q@staclar.com>
+musician.io
// Submitted by Matthias Merkel <matthias.merkel@staclar.com>
novecore.site
@@ -13444,19 +13667,20 @@ syncloud.it
// Synology, Inc. : https://www.synology.com/
// Submitted by Rony Weng <ronyweng@synology.com>
-diskstation.me
dscloud.biz
-dscloud.me
-dscloud.mobi
+direct.quickconnect.cn
dsmynas.com
-dsmynas.net
-dsmynas.org
familyds.com
-familyds.net
-familyds.org
+diskstation.me
+dscloud.me
i234.me
myds.me
synology.me
+dscloud.mobi
+dsmynas.net
+familyds.net
+dsmynas.org
+familyds.org
vpnplus.to
direct.quickconnect.to
@@ -13480,6 +13704,10 @@ gdynia.pl
med.pl
sopot.pl
+// team.blue https://team.blue
+// Submitted by Cedric Dubois <cedric.dubois@team.blue>
+site.tb-hosting.com
+
// Teckids e.V. : https://www.teckids.org
// Submitted by Dominik George <dominik.george@teckids.org>
edugit.io
@@ -13561,6 +13789,10 @@ lima.zone
*.transurl.eu
*.transurl.nl
+// TransIP: https://www.transip.nl
+// Submitted by Cedric Dubois <cedric.dubois@team.blue>
+site.transip.me
+
// TuxFamily : http://tuxfamily.org
// Submitted by TuxFamily administrators <adm@staff.tuxfamily.org>
tuxfamily.org
@@ -13581,6 +13813,10 @@ syno-ds.de
synology-diskstation.de
synology-ds.de
+// Typedream : https://typedream.com
+// Submitted by Putri Karunia <putri@typedream.com>
+typedream.app
+
// Typeform : https://www.typeform.com
// Submitted by Sergi Ferriz <sergi.ferriz@typeform.com>
pro.typeform.com
@@ -13597,6 +13833,15 @@ hk.org
ltd.hk
inc.hk
+// UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/
+// see also: whois -h whois.udr.org.yt help
+// Submitted by Atanunu Igbunuroghene <publicsuffixlist@udr.org.yt>
+name.pm
+sch.tf
+biz.wf
+sch.wf
+org.yt
+
// United Gameserver GmbH : https://united-gameserver.de
// Submitted by Stefan Schwarz <sysadm@united-gameserver.de>
virtualuser.de
@@ -13683,19 +13928,14 @@ me.vu
// Submitted by Serhii Rostilo <sergey@rostilo.kiev.ua>
v.ua
+// Vultr Objects : https://www.vultr.com/products/object-storage/
+// Submitted by Niels Maumenee <storage@vultr.com>
+*.vultrobjects.com
+
// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com
// Submitted by Masayuki Note <masa@blade.wafflecell.com>
wafflecell.com
-// WapBlog.ID : https://www.wapblog.id
-// Submitted by Fajar Sodik <official@wapblog.id>
-idnblogger.com
-indowapblog.com
-bloger.id
-wblog.id
-wbq.me
-fastblog.net
-
// WebHare bv: https://www.webhare.com/
// Submitted by Arnold Hendriks <info@webhare.com>
*.webhare.dev
@@ -13732,6 +13972,10 @@ wmcloud.org
panel.gg
daemon.panel.gg
+// Wizard Zines : https://wizardzines.com
+// Submitted by Julia Evans <julia@wizardzines.com>
+messwithdns.com
+
// WoltLab GmbH : https://www.woltlab.com
// Submitted by Tim Düsterhus <security@woltlab.cloud>
woltlab-demo.com
diff --git a/etc/refcards/Makefile b/etc/refcards/Makefile
index 6f8913c5f01..4c5daa9f44c 100644
--- a/etc/refcards/Makefile
+++ b/etc/refcards/Makefile
@@ -233,10 +233,11 @@ pl-refcard.pdf: $(pl_refcard_deps)
fi
$(ENVADD) pdftex -output-format=pdf pl-refcard.tex
pl-refcard.dvi: $(pl_refcard_deps)
- if ! kpsewhich -format=fmt mex > /dev/null; then \
- echo "No mex format found."; false; \
+ if kpsewhich -format=fmt mex > /dev/null; then \
+ $(ENVADD) tex pl-refcard.tex; \
+ else \
+ $(ENVADD) mex pl-refcard.tex; \
fi
- $(ENVADD) tex pl-refcard.tex
pl-refcard.ps: pl-refcard.dvi
dvips -t a4 -o $@ pl-refcard.dvi
diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex
index dec4d174c43..bb4bc5b25df 100644
--- a/etc/refcards/orgcard.tex
+++ b/etc/refcards/orgcard.tex
@@ -1,5 +1,5 @@
% Reference Card for Org Mode
-\def\orgversionnumber{9.5.2}
+\def\orgversionnumber{9.5.4}
\def\versionyear{2021} % latest update
\input emacsver.tex
diff --git a/etc/srecode/ede-autoconf.srt b/etc/srecode/ede-autoconf.srt
index 19dc14202de..ecca7afd007 100644
--- a/etc/srecode/ede-autoconf.srt
+++ b/etc/srecode/ede-autoconf.srt
@@ -44,10 +44,10 @@ template ede-empty :project
AC_INIT({{PROJECT_NAME}}, {{PROJECT_VERSION}})
AM_INIT_AUTOMAKE([{{PROGRAM}}], 0)
-AM_CONFIG_HEADER(config.h)
+AM_CONFIG_HEADER([config.h])
{{comment_prefix}} End the configure script.
-AC_OUTPUT(Makefile, [date > stamp-h] )
+AC_OUTPUT([Makefile], [date > stamp-h] )
----
diff --git a/etc/themes/leuven-dark-theme.el b/etc/themes/leuven-dark-theme.el
new file mode 100644
index 00000000000..3fbb9d6c995
--- /dev/null
+++ b/etc/themes/leuven-dark-theme.el
@@ -0,0 +1,1095 @@
+;;; leuven-dark-theme.el --- Awesome Emacs color theme on dark background -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
+;; Contributor: Thibault Polge <(concat "thibault" at-sign "thb.lt")>
+;; URL: https://github.com/fniessen/emacs-leuven-dark-theme
+;; Version: 20220202.1126
+;; Keywords: color theme
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This elegant Org-enhancing color theme "leuven-dark" ROCKS!
+;; ... and not just for Org mode.
+;;
+;; To use it, put the following in your Emacs configuration file:
+;;
+;; (load-theme 'leuven-dark t)
+;;
+;; Requirements: Emacs 24+.
+;;
+;; NOTE -- Would you like implement a version of this for dark backgrounds,
+;; please do so! I'm willing to integrate it...
+
+;;; Code:
+
+;;; Options.
+
+(defgroup leuven-dark nil
+ "Leuven theme options.
+The theme has to be reloaded after changing anything in this group."
+ :group 'faces)
+
+(defcustom leuven-dark-scale-org-document-title t
+ "Scale Org document title.
+This can be nil for unscaled, t for using the theme default, or a scaling
+number."
+ :type '(choice
+ (const :tag "Unscaled" nil)
+ (const :tag "Default provided by theme" t)
+ (number :tag "Set scaling")))
+
+(defcustom leuven-dark-scale-outline-headlines t
+ "Scale `outline' (and `org') level-1 headlines.
+This can be nil for unscaled, t for using the theme default, or a scaling
+number."
+ :type '(choice
+ (const :tag "Unscaled" nil)
+ (const :tag "Default provided by theme" t)
+ (number :tag "Set scaling")))
+
+(defcustom leuven-dark-scale-org-agenda-structure t
+ "Scale Org agenda structure lines, like dates.
+This can be nil for unscaled, t for using the theme default, or a scaling
+number."
+ :type '(choice
+ (const :tag "Unscaled" nil)
+ (const :tag "Default provided by theme" t)
+ (number :tag "Set scaling")))
+
+(defcustom leuven-dark-scale-volatile-highlight t
+ "Increase size in the `next-error' face.
+This can be nil for unscaled, t for using the theme default, or a scaling
+number."
+ :type '(choice
+ (const :tag "Unscaled" nil)
+ (const :tag "Default provided by theme" t)
+ (number :tag "Set scaling")))
+
+;;;###autoload
+(defun leuven-dark-scale-font (control default-height)
+ "Function for splicing optional font heights into face descriptions.
+CONTROL can be a number, nil, or t. When t, use DEFAULT-HEIGHT."
+ (cond
+ ((numberp control) (list :height control))
+ ((eq t control) (list :height default-height))
+ (t nil)))
+
+;;; Theme Faces.
+
+(deftheme leuven-dark
+ "Face colors with a light background.
+Basic, Font Lock, Isearch, Gnus, Message, Org mode, Diff, Ediff,
+Flyspell, Semantic, and Ansi-Color faces are included -- and much
+more...")
+
+(let ((class '((class color) (min-colors 89)))
+
+ ;; Leuven generic colors.
+ (cancel '(:slant italic :strike-through t :foreground "#5b5660"))
+ ;; (clock-line '(:box (:line-width 1 :color "#cfa161") :foreground "#ffffff" :background "#1636ff"))
+ (code-block '(:foreground "#ffff7f" :background "#252046"))
+ (code-inline '(:foreground "#ff9bff" :background "#262031"))
+ (column '(:height 1.0 :weight normal :slant normal :underline nil :strike-through nil :foreground "#1e52b8" :background "#252c48"))
+ (completion-inline '(:weight normal :foreground "#443f49" :inherit hl-line)) ; Like Google.
+ (completion-other-candidates '(:weight bold :foreground "#ffffff" :background "#372a2a"))
+ (completion-selected-candidate '(:weight bold :foreground "#25202a" :background "#ffad65"))
+ (diff-added '(:background "#442049"))
+ (diff-changed '(:foreground "#ffff0b" :background "#443f2a"))
+ (diff-header '(:weight bold :foreground "#83ffff" :background "#252073"))
+ (diff-hunk-header '(:foreground "#6bff6f" :background "#252f2a"))
+ (diff-none '(:foreground "#7b777f"))
+ (diff-refine-added '(:background "#6d0d73"))
+ (diff-refine-removed '(:background "#06494f"))
+ (diff-removed '(:background "#25353e"))
+ (directory '(:weight bold :foreground "#ffff0b" :background "#252053"))
+ (file '(:foreground "#ffffff"))
+ (function-param '(:foreground "#de8d83"))
+ (grep-file-name '(:weight bold :foreground "#d8b76b")) ; Used for grep hits.
+ (grep-line-number '(:weight bold :foreground "#5fca5b"))
+ (highlight-blue '(:background "#3c312a"))
+ ;; (highlight-blue2 '(:background "#3e2d2f"))
+ (highlight-gray '(:background "#3e3944"))
+ ;; (highlight-green '(:background "#2f0e3a"))
+ ;; (highlight-red '(:background "#063741"))
+ (highlight-yellow '(:background "#2d2058"))
+ (link '(:weight normal :underline t :foreground "#ff925a"))
+ (link-no-underline '(:weight normal :foreground "#ff925a"))
+ (mail-header-name '(:family "Sans Serif" :weight normal :foreground "#615c67"))
+ (mail-header-other '(:family "Sans Serif" :slant normal :foreground "#9d99a1"))
+ (mail-read '(:foreground "#77737b"))
+ (mail-read-high '(:foreground "#837f87"))
+ (mail-ticked '(:foreground "#06ccff"))
+ (mail-to '(:family "Sans Serif" :underline nil :foreground "#ff925a"))
+ (mail-unread '(:weight bold :foreground "#ffffff"))
+ (mail-unread-high '(:weight bold :foreground "#eea682"))
+ (marked-line '(:foreground "#5affff" :background "#06555f"))
+ (match '(:weight bold :background "#0601ff")) ; occur patterns + match in helm for files + match in Org files.
+ (ol1 `(,@(leuven-dark-scale-font leuven-dark-scale-outline-headlines 1.3) :weight bold :overline "#5d5862" :foreground "#c7c3cb" :background "#322d37"))
+ (ol2 '(:height 1.0 :weight bold :overline "#efcab2" :foreground "#efcab2" :background "#3d2a2d"))
+ (ol3 '(:height 1.0 :weight bold :foreground "#ffaae3" :background "#332038"))
+ (ol4 '(:height 1.0 :weight bold :slant normal :foreground "#1a9cff"))
+ (ol5 '(:height 1.0 :weight bold :slant normal :foreground "#21da7a"))
+ (ol6 '(:height 1.0 :weight bold :slant italic :foreground "#ff883d"))
+ (ol7 '(:height 1.0 :weight bold :slant italic :foreground "#d451d9"))
+ (ol8 '(:height 1.0 :weight bold :slant italic :foreground "#077ffa"))
+ (paren-matched '(:background "#7B4B98")) ; XXX Edited by hqnd.
+ (paren-unmatched '(:weight bold :underline "#06ffff" :foreground "#ffffff" :background "#065a64"))
+ (region '(:background "#752c0b"))
+ (shadow '(:foreground "#848088"))
+ (string '(:foreground "#ff7fff")) ; or #34c8d8
+ (subject '(:family "Sans Serif" :weight bold :foreground "#ffffff"))
+ (symlink '(:foreground "#e37233"))
+ (tab '(:foreground "#3a353f" :background "#25202a"))
+ (trailing '(:foreground "#3a353f" :background "#252076"))
+ (volatile-highlight '(:underline nil :foreground "#25202a" :background "#66c96f"))
+ (volatile-highlight-supersize `(,@(leuven-dark-scale-font leuven-dark-scale-volatile-highlight 1.1) :underline nil :foreground "#25202a" :background "#66c96f")) ; flash-region
+ (vc-branch '(:box (:line-width 1 :color "#ff33d2") :foreground "#ffffff" :background "#5a015f"))
+ (xml-attribute '(:foreground "#119cd0"))
+ (xml-tag '(:foreground "#56e46f"))
+ (highlight-current-tag '(:background "#3a352a")) ; #342b32 or #0614df
+ )
+
+ (custom-theme-set-faces
+ 'leuven-dark
+ `(default ((,class (:foreground "#cfccd2" :background "#25202a"))))
+ `(bold ((,class (:weight bold :foreground "#ffffff"))))
+ `(bold-italic ((,class (:weight bold :slant italic :foreground "#ffffff"))))
+ `(italic ((,class (:slant italic :foreground "#e8e5eb"))))
+ `(underline ((,class (:underline t))))
+ `(cursor ((,class (:background "#e1420b"))))
+
+ ;; Lucid toolkit emacs menus.
+ `(menu ((,class (:foreground "#25202a" :background "#cfccd2"))))
+
+ ;; Highlighting faces.
+ `(fringe ((,class (:foreground "#b76130" :background "#25202a"))))
+ `(highlight ((,class ,highlight-blue)))
+ `(region ((,class ,region)))
+ `(secondary-selection ((,class ,match))) ; Used by Org-mode for highlighting matched entries and keywords.
+ `(isearch ((,class (:underline "#ffffff" :foreground "#25202a" :background "#aa8b5e"))))
+ `(isearch-fail ((,class (:weight bold :foreground "#ffffff" :background "#06333d"))))
+ `(lazy-highlight ((,class (:foreground "#ffffff" :background "#0601ff")))) ; Isearch others (see `match').
+ `(trailing-whitespace ((,class ,trailing)))
+ `(query-replace ((,class (:inherit isearch))))
+ `(whitespace-hspace ((,class (:foreground "#322d37")))) ; see also `nobreak-space'
+ `(whitespace-indentation ((,class ,tab)))
+ `(whitespace-line ((,class (:foreground "#38ffff" :background "#06017f"))))
+ `(whitespace-tab ((,class ,tab)))
+ `(whitespace-trailing ((,class ,trailing)))
+
+ ;; Mode line faces.
+ `(mode-line ((,class (:box (:line-width 1 :color "#e8d0b3") :foreground "#7e311e" :background "#cfa161"))))
+ `(mode-line-inactive ((,class (:box (:line-width 1 :color "#b5b1bb") :foreground "#322d38" :background "#696371"))))
+ `(mode-line-buffer-id ((,class (:weight bold :foreground "#25202a"))))
+ `(mode-line-emphasis ((,class (:weight bold :foreground "#25202a"))))
+ `(mode-line-highlight ((,class (:foreground "#0601ff"))))
+
+ ;; Escape and prompt faces.
+ `(minibuffer-prompt ((,class (:weight bold :foreground "#ffffff" :background "#0628ff"))))
+ `(minibuffer-noticeable-prompt ((,class (:weight bold :foreground "#ffffff" :background "#0628ff"))))
+ `(escape-glyph ((,class (:foreground "#ff7138"))))
+ `(error ((,class (:foreground "#06ffff"))))
+ `(warning ((,class (:weight bold :foreground "#065aff"))))
+ `(success ((,class (:foreground "#ff01ff"))))
+
+ ;; Font lock faces.
+ `(font-lock-builtin-face ((,class (:foreground "#ff9029"))))
+ `(font-lock-comment-delimiter-face ((,class (:foreground "#767283")))) ; #9a969e
+ `(font-lock-comment-face ((,class (:slant italic :foreground "#767283")))) ; #9a969e
+ `(font-lock-constant-face ((,class (:foreground "#34c8d8"))))
+ `(font-lock-doc-face ((,class (:foreground "#fd95fa"))))
+ ;; `(font-lock-doc-string-face ((,class (:foreground "#ff7fff")))) ; XEmacs only, but is used for HTML exports from org2html (and not interactively)
+ `(font-lock-function-name-face ((,class (:weight normal :foreground "#ff996f"))))
+ `(font-lock-keyword-face ((,class (:bold nil :foreground "#ffff0b")))) ; #ccab2d
+ `(font-lock-preprocessor-face ((,class (:foreground "#837f87"))))
+ `(font-lock-regexp-grouping-backslash ((,class (:weight bold :inherit nil))))
+ `(font-lock-regexp-grouping-construct ((,class (:weight bold :inherit nil))))
+ `(font-lock-string-face ((,class ,string)))
+ `(font-lock-type-face ((,class (:weight normal :foreground "#9fcb66"))))
+ `(font-lock-variable-name-face ((,class (:weight normal :foreground "#4ac964")))) ; #83ff87
+ `(font-lock-warning-face ((,class (:weight bold :foreground "#06ffff"))))
+
+ ;; Button and link faces.
+ `(link ((,class ,link)))
+ `(link-visited ((,class (:underline t :foreground "#1f879a"))))
+ `(button ((,class (:underline t :foreground "#ff925a"))))
+ `(header-line ((,class (:box (:line-width 1 :color "#ffffff") :foreground "#ffffff" :background "#322d37"))))
+
+ ;; Gnus faces.
+ `(gnus-button ((,class (:weight normal))))
+ `(gnus-cite-attribution-face ((,class (:foreground "#b3af59"))))
+ `(gnus-cite-1 ((,class (:foreground "#b3af59" :background "#2d2832"))))
+ `(gnus-cite-2 ((,class (:foreground "#9dffa1" :background "#2d2832"))))
+ `(gnus-cite-3 ((,class (:foreground "#ff8890" :background "#2d2832"))))
+ `(gnus-cite-4 ((,class (:foreground "#6bffff" :background "#2d2832"))))
+ `(gnus-cite-5 ((,class (:foreground "#ffff6f" :background "#2d2832"))))
+ `(gnus-cite-6 ((,class (:foreground "#4999ff" :background "#2d2832"))))
+ `(gnus-cite-7 ((,class (:foreground "#b3af59" :background "#2d2832"))))
+ `(gnus-cite-8 ((,class (:foreground "#9dffa1" :background "#2d2832"))))
+ `(gnus-cite-9 ((,class (:foreground "#ff8890" :background "#2d2832"))))
+ `(gnus-cite-10 ((,class (:foreground "#6bffff" :background "#2d2832"))))
+ `(gnus-emphasis-bold ((,class (:weight bold))))
+ `(gnus-emphasis-highlight-words ((,class (:foreground "#0601ff" :background "#ffffff"))))
+ `(gnus-group-mail-1 ((,class (:weight bold :foreground "#06af59"))))
+ `(gnus-group-mail-1-empty ((,class (:foreground "#b3af59"))))
+ `(gnus-group-mail-2 ((,class (:weight bold :foreground "#06ffa1"))))
+ `(gnus-group-mail-2-empty ((,class (:foreground "#9dffa1"))))
+ `(gnus-group-mail-3 ((,class ,mail-unread)))
+ `(gnus-group-mail-3-empty ((,class ,mail-read)))
+ `(gnus-group-mail-low ((,class ,cancel)))
+ `(gnus-group-mail-low-empty ((,class ,cancel)))
+ `(gnus-group-news-1 ((,class (:weight bold :foreground "#06af59"))))
+ `(gnus-group-news-1-empty ((,class (:foreground "#b3af59"))))
+ `(gnus-group-news-2 ((,class (:weight bold :foreground "#06ffa1"))))
+ `(gnus-group-news-2-empty ((,class (:foreground "#9dffa1"))))
+ `(gnus-group-news-3 ((,class ,mail-unread)))
+ `(gnus-group-news-3-empty ((,class ,mail-read)))
+ `(gnus-group-news-4 ((,class (:weight bold :foreground "#06ffff"))))
+ `(gnus-group-news-4-empty ((,class (:foreground "#6bffff"))))
+ `(gnus-group-news-5 ((,class (:weight bold :foreground "#06ff6f"))))
+ `(gnus-group-news-5-empty ((,class (:foreground "#ffff6f"))))
+ `(gnus-group-news-6 ((,class (:weight bold :foreground "#848088"))))
+ `(gnus-group-news-6-empty ((,class (:foreground "#837f87"))))
+ `(gnus-header-content ((,class ,mail-header-other)))
+ `(gnus-header-from ((,class (:family "Sans Serif" :foreground "#ffffff"))))
+ `(gnus-header-name ((,class ,mail-header-name)))
+ `(gnus-header-newsgroups ((,class (:family "Sans Serif" :foreground "#cf663d"))))
+ `(gnus-header-subject ((,class ,subject)))
+ `(gnus-picon ((,class (:foreground "#0601ff" :background "#25202a"))))
+ `(gnus-picon-xbm ((,class (:foreground "#0601ff" :background "#25202a"))))
+ `(gnus-server-closed ((,class (:slant italic :foreground "#ffff0b" :background "#25202a"))))
+ `(gnus-server-denied ((,class (:weight bold :foreground "#06ffff" :background "#25202a"))))
+ `(gnus-server-opened ((,class (:family "Sans Serif" :foreground "#25202a" :foreground "#bd9432"))))
+ `(gnus-signature ((,class (:slant italic :foreground "#787279"))))
+ `(gnus-splash ((,class (:foreground "#0673ff"))))
+ `(gnus-summary-cancelled ((,class ,cancel)))
+ `(gnus-summary-high-ancient ((,class ,mail-unread-high)))
+ `(gnus-summary-high-read ((,class ,mail-read-high)))
+ `(gnus-summary-high-ticked ((,class ,mail-ticked)))
+ `(gnus-summary-high-unread ((,class ,mail-unread-high)))
+ `(gnus-summary-low-ancient ((,class (:slant italic :foreground "#ffffff"))))
+ `(gnus-summary-low-read ((,class (:slant italic :foreground "#6b666f" :background "#413c46"))))
+ `(gnus-summary-low-ticked ((,class ,mail-ticked)))
+ `(gnus-summary-low-unread ((,class (:slant italic :foreground "#ffffff"))))
+ `(gnus-summary-normal-ancient ((,class ,mail-read)))
+ `(gnus-summary-normal-read ((,class ,mail-read)))
+ `(gnus-summary-normal-ticked ((,class ,mail-ticked)))
+ `(gnus-summary-normal-unread ((,class ,mail-unread)))
+ `(gnus-summary-selected ((,class (:foreground "#25202a" :background "#ff7332"))))
+ `(gnus-x-face ((,class (:foreground "#ffffff" :background "#25202a"))))
+
+ ;; Message faces.
+ `(message-header-name ((,class ,mail-header-name)))
+ `(message-header-cc ((,class ,mail-to)))
+ `(message-header-other ((,class ,mail-header-other)))
+ `(message-header-subject ((,class ,subject)))
+ `(message-header-to ((,class ,mail-to)))
+ `(message-cited-text ((,class (:foreground "#b3af59" :background "#2d2832"))))
+ `(message-separator ((,class (:family "Sans Serif" :weight normal :foreground "#473d43"))))
+ `(message-header-newsgroups ((,class (:family "Sans Serif" :foreground "#cf663d"))))
+ `(message-header-xheader ((,class ,mail-header-other)))
+ `(message-mml ((,class (:foreground "#e074e3"))))
+
+ ;; Diff.
+ `(diff-added ((,class ,diff-added)))
+ `(diff-changed ((,class ,diff-changed)))
+ `(diff-context ((,class ,diff-none)))
+ `(diff-file-header ((,class ,diff-header)))
+ `(diff-file1-hunk-header ((,class (:foreground "#78ff7c" :background "#382c33"))))
+ `(diff-file2-hunk-header ((,class (:foreground "#d781db" :background "#382c33"))))
+ `(diff-function ((,class (:foreground "#38663d"))))
+ `(diff-header ((,class ,diff-header)))
+ `(diff-hunk-header ((,class ,diff-hunk-header)))
+ `(diff-index ((,class ,diff-header)))
+ `(diff-indicator-added ((,class (:foreground "#c966cc" :background "#53204e"))))
+ `(diff-indicator-changed ((,class (:background "#46302a"))))
+ `(diff-indicator-removed ((,class (:foreground "#38ccd2" :background "#254046"))))
+ `(diff-refine-added ((,class ,diff-refine-added)))
+ `(diff-refine-change ((,class (:background "#443f2a"))))
+ `(diff-refine-removed ((,class ,diff-refine-removed)))
+ `(diff-removed ((,class ,diff-removed)))
+
+ ;; SMerge.
+ `(smerge-mine ((,class ,diff-changed)))
+ `(smerge-other ((,class ,diff-added)))
+ `(smerge-base ((,class ,diff-removed)))
+ `(smerge-markers ((,class (:background "#253859"))))
+ `(smerge-refined-change ((,class (:background "#5a550b"))))
+
+ ;; Ediff.
+ `(ediff-current-diff-A ((,class (:background "#253f49"))))
+ `(ediff-current-diff-B ((,class (:background "#442049"))))
+ `(ediff-current-diff-C ((,class (:background "#ff010b"))))
+ `(ediff-even-diff-A ((,class (:background "#312c36"))))
+ `(ediff-even-diff-B ((,class (:background "#312c36"))))
+ `(ediff-fine-diff-A ((,class (:background "#06555f"))))
+ `(ediff-fine-diff-B ((,class (:background "#ae01b2"))))
+ `(ediff-odd-diff-A ((,class (:background "#312c36"))))
+ `(ediff-odd-diff-B ((,class (:background "#312c36"))))
+
+ ;; Flyspell.
+ (if (version< emacs-version "24.4")
+ `(flyspell-duplicate ((,class (:underline "#101487" :inherit nil))))
+ `(flyspell-duplicate ((,class (:underline (:style wave :color "#101487") :background "#292759" :inherit nil)))))
+ (if (version< emacs-version "24.4")
+ `(flyspell-incorrect ((,class (:underline "#0a5864" :inherit nil))))
+ `(flyspell-incorrect ((,class (:underline (:style wave :color "#0a5864") :background "#2f454c":inherit nil)))))
+
+ ;; ;; Semantic faces.
+ ;; `(semantic-decoration-on-includes ((,class (:underline ,cham-4))))
+ ;; `(semantic-decoration-on-private-members-face ((,class (:background ,alum-2))))
+ ;; `(semantic-decoration-on-protected-members-face ((,class (:background ,alum-2))))
+ `(semantic-decoration-on-unknown-includes ((,class (:background "#252630"))))
+ ;; `(semantic-decoration-on-unparsed-includes ((,class (:underline ,orange-3))))
+ `(semantic-highlight-func-current-tag-face ((,class ,highlight-current-tag)))
+ `(semantic-tag-boundary-face ((,class (:overline "#8c8890")))) ; Method separator.
+ ;; `(semantic-unmatched-syntax-face ((,class (:underline ,red-1))))
+
+ `(Info-title-1-face ((,class ,ol1)))
+ `(Info-title-2-face ((,class ,ol2)))
+ `(Info-title-3-face ((,class ,ol3)))
+ `(Info-title-4-face ((,class ,ol4)))
+ `(ace-jump-face-foreground ((,class (:weight bold :foreground "#ffffff" :background "#065aff"))))
+ `(ahs-face ((,class (:background "#3e392a"))))
+ `(ahs-definition-face ((,class (:background "#064943"))))
+ `(ahs-plugin-defalt-face ((,class (:background "#25392a")))) ; Current.
+ `(anzu-match-1 ((,class (:foreground "#ffffff" :background "#840135"))))
+ `(anzu-match-2 ((,class (:foreground "#ffffff" :background "springgreen"))))
+ `(anzu-match-3 ((,class (:foreground "#ffffff" :background "#06ffff"))))
+ `(anzu-mode-line ((,class (:foreground "#ffffff" :background "#830187"))))
+ `(anzu-mode-line-no-match ((,class (:foreground "#ffffff" :background "#067f87"))))
+ `(anzu-replace-highlight ((,class (:inherit query-replace))))
+ `(anzu-replace-to ((,class (:weight bold :foreground "#47cc0c" :background "#0742d2"))))
+ `(auto-dim-other-buffers-face ((,class (:background "#2c2731"))))
+ `(avy-background-face ((,class (:background "#5b5660"))))
+ `(avy-lead-face ((,class (:weight bold :foreground "#ffffff" :background "#065aff"))))
+ `(bbdb-company ((,class (:slant italic :foreground "#bd7d55"))))
+ `(bbdb-field-name ((,class (:weight bold :foreground "#bd7d55"))))
+ `(bbdb-field-value ((,class (:foreground "#bd7d55"))))
+ `(bbdb-name ((,class (:underline t :foreground "#0699d2"))))
+ `(bmkp-light-autonamed ((,class (:background "#322d37"))))
+ `(bmkp-light-fringe-autonamed ((,class (:foreground "#a9a5ad" :background "#302b35"))))
+ `(bmkp-light-fringe-non-autonamed ((,class (:foreground "#252059" :background "#fe010e")))) ; default
+ `(bmkp-light-non-autonamed ((,class (:background "#60202a"))))
+ `(bmkp-no-local ((,class (:background "#063f3e"))))
+ `(browse-kill-ring-separator-face ((,class (:foreground "#06ffff"))))
+ `(calendar-month-header ((,class (:weight bold :foreground "#b4b5ca" :background "#252059"))))
+ `(calendar-today ((,class (:weight bold :foreground "#b4b5ca" :background "#252059"))))
+ `(calendar-weekday-header ((,class (:weight bold :foreground "#ec9d5a"))))
+ `(calendar-weekend-header ((,class (:weight bold :foreground "#b5b1b9"))))
+ `(cfw:face-annotation ((,class (:foreground "#ff01ff" :background "#06ffff"))))
+ `(cfw:face-day-title ((,class (:foreground "#3b3640"))))
+ `(cfw:face-default-content ((,class (:foreground "#d9ad66"))))
+ `(cfw:face-default-day ((,class (:weight bold))))
+ `(cfw:face-disable ((,class (:foreground "#5b5660"))))
+ `(cfw:face-grid ((,class (:foreground "#27222c"))))
+ `(cfw:face-header ((,class (:foreground "#ec9d5a" :background "#25202a" :weight bold))))
+ `(cfw:face-holiday ((,class (:foreground "#8c8890" :background "#3e322a"))))
+ `(cfw:face-periods ((,class (:foreground "#25202a" :background "#9d7330" :slant italic))))
+ `(cfw:face-saturday ((,class (:foreground "#b5b1b9" :background "#25202a" :weight bold))))
+ `(cfw:face-select ((,class (:foreground "#b96a1e" :background "#352d2e"))))
+ `(cfw:face-sunday ((,class (:foreground "#b5b1b9" :background "#25202a" :weight bold))))
+ `(cfw:face-title ((,class (:height 2.0 :foreground "#9c98a0" :weight bold :inherit variable-pitch))))
+ `(cfw:face-today ((,class (:foreground "#b4b5ca" :background "#252059"))))
+ `(cfw:face-today-title ((,class (:foreground "#25202a" :background "#eb9958"))))
+ `(cfw:face-toolbar ((,class (:background "#25202a"))))
+ `(cfw:face-toolbar-button-off ((,class (:foreground "#35303a" :background "#25202a"))))
+ `(cfw:face-toolbar-button-on ((,class (:foreground "#a5a1a9" :background "#2d2832"))))
+ `(change-log-date ((,class (:foreground "#64df19"))))
+ `(change-log-file ((,class (:weight bold :foreground "#c27c45"))))
+ `(change-log-list ((,class (:foreground "#ffffff" :background "#8e1142"))))
+ `(change-log-name ((,class (:foreground "#ff7fff"))))
+ `(circe-highlight-all-nicks-face ((,class (:foreground "#ffff0b" :background "#322d37")))) ; other nick names
+ `(circe-highlight-nick-face ((,class (:foreground "#ff6cff" :background "#322d37")))) ; messages with my nick cited
+ `(circe-my-message-face ((,class (:foreground "#78747c" :background "#322d37"))))
+ `(circe-originator-face ((,class (:foreground "#ffff0b"))))
+ `(circe-prompt-face ((,class (:foreground "#06ffff"))))
+ `(circe-server-face ((,class (:foreground "#6b3524"))))
+ `(comint-highlight-input ((,class (:weight bold :foreground "#ffff0b" :inherit nil))))
+ ;; `(comint-highlight-prompt ((,class (:weight bold :foreground "#ffffff" :background "#0628ff"))))
+ `(comint-highlight-prompt ((,class (:weight bold :foreground "#ffff0b" :inherit nil))))
+
+ ;; `(ac-selection-face ((,class ,completion-selected-candidate)))
+ `(ac-selection-face ((,class (:weight bold :foreground "#25202a" :background "#065aff")))) ; TEMP For diff'ing AC from Comp.
+ `(ac-candidate-face ((,class ,completion-other-candidates)))
+ `(ac-completion-face ((,class ,completion-inline)))
+ `(ac-candidate-mouse-face ((,class (:inherit highlight))))
+ `(popup-scroll-bar-background-face ((,class (:background "#372a2a"))))
+ `(popup-scroll-bar-foreground-face ((,class (:background "#332525")))) ; Scrollbar (visible).
+
+ ;; Company.
+ `(company-tooltip-common-selection ((,class (:weight normal :foreground "#2a3159" :inherit company-tooltip-selection)))) ; Prefix + common part in tooltip (for selection).
+ `(company-tooltip-selection ((,class ,completion-selected-candidate))) ; Suffix in tooltip (for selection).
+ `(company-tooltip-annotation-selection ((,class (:weight normal :foreground "#2a3159")))) ; Annotation (for selection).
+
+ `(company-tooltip-common ((,class (:weight normal :foreground "#54ff59" :inherit company-tooltip)))) ; Prefix + common part in tooltip.
+ `(company-tooltip ((,class ,completion-other-candidates))) ; Suffix in tooltip.
+ `(company-tooltip-annotation ((,class (:weight normal :foreground "#deea0b")))) ; Annotation.
+ `(company-preview ((,class ,completion-inline)))
+ `(company-preview-common ((,class ,completion-inline)))
+ `(company-scrollbar-bg ((,class (:background "#372a2a"))))
+ `(company-scrollbar-fg ((,class (:background "#332525")))) ; Scrollbar (visible).
+
+ `(compare-windows ((,class (:background "#0601ff"))))
+ ;; `(completions-common-part ((,class (:foreground "#06ffff" :weight bold))))
+ ;; `(completions-first-difference ((,class (:foreground "#ff01ff" :weight bold))))
+ `(compilation-error ((,class (:weight bold :foreground "#06ffff")))) ; Used for grep error messages.
+ `(compilation-info ((,class ,grep-file-name)))
+ `(compilation-line-number ((,class ,grep-line-number)))
+ `(compilation-warning ((,class (:weight bold :foreground "#065aff"))))
+ `(compilation-mode-line-exit ((,class (:weight bold :foreground "#ff01ff")))) ; :exit[matched]
+ `(compilation-mode-line-fail ((,class (:weight bold :foreground "#167d1b")))) ; :exit[no match]
+ `(compilation-mode-line-run ((,class (:weight bold :foreground "#065aff")))) ; :run
+ `(css-property ((,class (:foreground "#ff55ff"))))
+ `(css-selector ((,class (:weight bold :foreground "#ffff0b"))))
+ `(custom-button ((,class (:box (:line-width 2 :style released-button) :foreground "gray20" :background "lightgrey"))))
+ `(custom-button-mouse ((,class (:box (:line-width 2 :style released-button) :foreground "#ffffff" :background "#3d3842"))))
+ `(custom-button-pressed ((,class (:box (:line-width 2 :style pressed-button) :foreground "#ffffff" :background "#312c36"))))
+ `(custom-button-pressed-unraised ((,class (:underline t :foreground "#78ff7c"))))
+ `(custom-button-unraised ((,class (:underline t))))
+ `(custom-changed ((,class (:foreground "#25202a" :background "#ffff0b"))))
+ `(custom-comment ((,class (:background "#2b2630"))))
+ `(custom-comment-tag ((,class (:foreground "#ffff7c"))))
+ `(custom-documentation ((,class (nil))))
+ `(custom-face-tag ((,class (:family "Sans Serif" :height 1.2 :weight bold))))
+ `(custom-group-tag ((,class (:height 1.2 :weight bold :foreground "#ffff0b"))))
+ `(custom-group-tag-1 ((,class (:family "Sans Serif" :height 1.2 :weight bold :foreground "#06ffff"))))
+ `(custom-invalid ((,class (:foreground "#0601ff" :background "#06ffff"))))
+ `(custom-link ((,class (:underline t :foreground "#ffff0b"))))
+ `(custom-modified ((,class (:foreground "#25202a" :background "#ffff0b"))))
+ `(custom-rogue ((,class (:foreground "#063f3e" :background "#ffffff"))))
+ `(custom-saved ((,class (:underline t))))
+ `(custom-set ((,class (:foreground "#ffff0b" :background "#25202a"))))
+ `(custom-state ((,class (:foreground "#ff74ff"))))
+ `(custom-themed ((,class (:foreground "#25202a" :background "#ffff0b"))))
+ `(custom-variable-button ((,class (:weight bold :underline t))))
+ `(custom-variable-tag ((,class (:family "Sans Serif" :height 1.2 :weight bold :foreground "#ffff0b"))))
+ `(custom-visibility ((,class ,link)))
+ `(diff-hl-change ((,class (:foreground "#ffff3c" :background "#46302a"))))
+ `(diff-hl-delete ((,class (:foreground "#37ffff" :background "#254046"))))
+ `(diff-hl-dired-change ((,class (:weight bold :foreground "#ffffff" :background "#065cd0"))))
+ `(diff-hl-dired-delete ((,class (:weight bold :foreground "#2dc6ef"))))
+ `(diff-hl-dired-ignored ((,class (:weight bold :foreground "#25202a" :background "#44445e"))))
+ `(diff-hl-dired-insert ((,class (:weight bold :foreground "#4b464f"))))
+ `(diff-hl-dired-unknown ((,class (:foreground "#25202a" :background "#c4c455"))))
+ `(diff-hl-insert ((,class (:foreground "#ff74ff" :background "#53204e"))))
+ `(diff-hl-unknown ((,class (:foreground "#25202a" :background "#c4c455"))))
+ `(diary-face ((,class (:foreground "#7c360d"))))
+ `(dircolors-face-asm ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-backup ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-compress ((,class (:foreground "#06ffff"))))
+ `(dircolors-face-dir ((,class ,directory)))
+ `(dircolors-face-doc ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-dos ((,class (:foreground "#e074e3"))))
+ `(dircolors-face-emacs ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-exec ((,class (:foreground "#e074e3"))))
+ `(dircolors-face-html ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-img ((,class (:foreground "#37ff3c"))))
+ `(dircolors-face-lang ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-lang-interface ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-make ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-objet ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-package ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-paddb ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-ps ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-sound ((,class (:foreground "#ff400b"))))
+ `(dircolors-face-tar ((,class (:foreground "#06ffff"))))
+ `(dircolors-face-text ((,class (:foreground "#ffffff"))))
+ `(dircolors-face-yacc ((,class (:foreground "#ffffff"))))
+ `(dired-directory ((,class ,directory)))
+ `(dired-header ((,class ,directory)))
+ `(dired-ignored ((,class (:strike-through t :foreground "#06ffff"))))
+ `(dired-mark ((,class ,marked-line)))
+ `(dired-marked ((,class ,marked-line)))
+ `(dired-symlink ((,class ,symlink)))
+ `(diredfl-compressed-file-suffix ((,class (:foreground "#ffffff" :background "#2526c0"))))
+ `(diredp-compressed-file-suffix ((,class (:foreground "#06ffff"))))
+ `(diredp-date-time ((,class (:foreground "#64df19"))))
+ `(diredp-dir-heading ((,class ,directory)))
+ `(diredp-dir-name ((,class ,directory)))
+ `(diredp-dir-priv ((,class ,directory)))
+ `(diredp-exec-priv ((,class (:background "#fd3fcb"))))
+ `(diredp-executable-tag ((,class (:foreground "#e074e3" :background "#25202a"))))
+ `(diredp-file-name ((,class ,file)))
+ `(diredp-file-suffix ((,class (:foreground "#443f49"))))
+ `(diredp-flag-mark-line ((,class ,marked-line)))
+ `(diredp-ignored-file-name ((,class ,shadow)))
+ `(diredp-read-priv ((,class (:background "#f7660b"))))
+ `(diredp-write-priv ((,class (:foreground "#25202a" :background "#06bfc7"))))
+ `(doom-modeline-panel ((,class (:foreground "#ffffff" :background "#2526c0"))))
+ `(eldoc-highlight-function-argument ((,class (:weight bold :foreground "#06ffff" :background "#25392a"))))
+ `(elfeed-search-filter-face ((,class (:foreground "#46414b"))))
+ ;; `(eww-form-checkbox ((,class ())))
+ ;; `(eww-form-select ((,class ())))
+ ;; `(eww-form-submit ((,class ())))
+ `(eww-form-text ((,class (:weight bold :foreground "#c3a798" :background "#5d3218"))))
+ ;; `(eww-form-textarea ((,class ())))
+ `(file-name-shadow ((,class ,shadow)))
+ `(flycheck-error ((,class (:underline (:color "#06dae7" :style wave) :weight bold :background "#253c46"))))
+ `(flycheck-error-list-line-number ((,class (:foreground "#5fca5b"))))
+ `(flycheck-fringe-error ((,class (:foreground "#06dae7"))))
+ `(flycheck-fringe-info ((,class (:foreground "#ed75ef"))))
+ `(flycheck-fringe-warning ((,class (:foreground "#1056cd"))))
+ `(flycheck-info ((,class (:underline (:color "#ed75ef" :style wave) :weight bold))))
+ `(flycheck-warning ((,class (:underline (:color "#1056cd" :style wave) :weight bold :background "#252066"))))
+ `(font-latex-bold-face ((,class (:weight bold :foreground "#ffffff"))))
+ `(fancy-narrow-blocked-face ((,class (:foreground "#6b6765"))))
+ `(flycheck-color-mode-line-error-face ((, class (:background "#35a4b1"))))
+ `(flycheck-color-mode-line-warning-face ((, class (:background "#1938ff"))))
+ `(flycheck-color-mode-line-info-face ((, class (:background "#0601ff"))))
+ `(font-latex-italic-face ((,class (:slant italic :foreground "#e8e5eb"))))
+ `(font-latex-math-face ((,class (:foreground "#ffff0b"))))
+ `(font-latex-sectioning-1-face ((,class (:family "Sans Serif" :height 2.7 :weight bold :foreground "#9f6a1c"))))
+ `(font-latex-sectioning-2-face ((,class ,ol1)))
+ `(font-latex-sectioning-3-face ((,class ,ol2)))
+ `(font-latex-sectioning-4-face ((,class ,ol3)))
+ `(font-latex-sectioning-5-face ((,class ,ol4)))
+ `(font-latex-sedate-face ((,class (:foreground "#06aaff"))))
+ `(font-latex-string-face ((,class (:weight bold :foreground "#ff990b"))))
+ `(font-latex-verbatim-face ((,class (:foreground "#ffff7f" :background "#252046" :inherit nil))))
+ `(git-commit-summary-face ((,class (:foreground "#ffffff"))))
+ `(git-commit-comment-face ((,class (:slant italic :foreground "#9a969e"))))
+ `(git-timemachine-commit ((,class ,diff-removed)))
+ `(git-timemachine-minibuffer-author-face ((,class ,diff-added)))
+ `(git-timemachine-minibuffer-detail-face ((,class ,diff-header)))
+ `(google-translate-text-face ((,class (:foreground "#8c8890" :background "#2e2933"))))
+ `(google-translate-phonetic-face ((,class (:inherit shadow))))
+ `(google-translate-translation-face ((,class (:weight normal :foreground "#d2861c" :background "#3f3336"))))
+ `(google-translate-suggestion-label-face ((,class (:foreground "#06ffff"))))
+ `(google-translate-suggestion-face ((,class (:slant italic :underline t))))
+ `(google-translate-listen-button-face ((,class (:height 0.8))))
+ `(helm-action ((,class (:foreground "#ffffff"))))
+ `(helm-bookmark-file ((,class ,file)))
+ `(helm-bookmarks-su-face ((,class (:foreground "#06ffff"))))
+ `(helm-buffer-directory ((,class ,directory)))
+ ;; `(helm-non-file-buffer ((,class (:slant italic :foreground "#ffff0b"))))
+ ;; `(helm-buffer-file ((,class (:foreground "#cfccd2"))))
+ `(helm-buffer-modified ((,class (:slant italic :foreground "#4ac964"))))
+ `(helm-buffer-process ((,class (:foreground "#ff7dff"))))
+ `(helm-candidate-number ((,class (:foreground "#ffffff" :background "#0601a1"))))
+ `(helm-dir-heading ((,class (:foreground "#ffff0b" :background "#063f3e"))))
+ `(helm-dir-priv ((,class (:foreground "#78ffff" :background "#312c36"))))
+ `(helm-ff-directory ((,class ,directory)))
+ `(helm-ff-dotted-directory ((,class ,directory)))
+ `(helm-ff-executable ((,class (:foreground "#ff32ff" :background "#25202a"))))
+ `(helm-ff-file ((,class (:foreground "#ffffff"))))
+ `(helm-ff-invalid-symlink ((,class (:foreground "#0601ff" :background "#06ffff"))))
+ `(helm-ff-symlink ((,class ,symlink)))
+ `(helm-file-name ((,class (:foreground "#ffff0b"))))
+ `(helm-gentoo-match-face ((,class (:foreground "#06ffff"))))
+ `(helm-grep-file ((,class ,grep-file-name)))
+ `(helm-grep-lineno ((,class ,grep-line-number)))
+ `(helm-grep-match ((,class ,match)))
+ `(helm-grep-running ((,class (:weight bold :foreground "#25202a"))))
+ `(helm-isearch-match ((,class (:background "#38013d"))))
+ `(helm-lisp-show-completion ((,class ,volatile-highlight-supersize))) ; See `helm-dabbrev'.
+ ;; `(helm-ls-git-added-copied-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-added-modified-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-conflict-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-deleted-and-staged-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-deleted-not-staged-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-modified-and-staged-face ((,class (:foreground ""))))
+ `(helm-ls-git-modified-not-staged-face ((,class (:foreground "#4ac964"))))
+ ;; `(helm-ls-git-renamed-modified-face ((,class (:foreground ""))))
+ ;; `(helm-ls-git-untracked-face ((,class (:foreground ""))))
+ `(helm-match ((,class ,match)))
+ `(helm-moccur-buffer ((,class (:foreground "#ff993d"))))
+ `(helm-selection ((,class (:background "#cb8a33" :foreground "#25202a"))))
+ `(helm-selection-line ((,class ,highlight-gray))) ; ???
+ `(helm-separator ((,class (:foreground "#06ffff"))))
+ `(helm-source-header ((,class (:weight bold :box (:line-width 1 :color "#3d3842") :background "#433e48" :foreground "#ffffff"))))
+ `(helm-swoop-target-line-block-face ((,class (:background "#3833ff" :foreground "#e0dde3"))))
+ `(helm-swoop-target-line-face ((,class (:background "#38330b"))))
+ `(helm-swoop-target-word-face ((,class (:weight bold :foreground nil :background "#0742d2"))))
+ `(helm-visible-mark ((,class ,marked-line)))
+ `(helm-w3m-bookmarks-face ((,class (:underline t :foreground "#ff010b"))))
+ `(highlight-changes ((,class (:foreground nil)))) ;; blue "#d4f754"
+ `(highlight-changes-delete ((,class (:strike-through nil :foreground nil)))) ;; red "#4ff7d7"
+ `(highlight-symbol-face ((,class (:background "#252080"))))
+ `(hl-line ((,class ,highlight-yellow))) ; Highlight current line.
+ `(hl-tags-face ((,class ,highlight-current-tag))) ; ~ Pair highlighting (matching tags).
+ `(holiday-face ((,class (:foreground "#8c8890" :background "#3e322a"))))
+ `(html-helper-bold-face ((,class (:weight bold :foreground "#ffffff"))))
+ `(html-helper-italic-face ((,class (:slant italic :foreground "#ffffff"))))
+ `(html-helper-underline-face ((,class (:underline t :foreground "#ffffff"))))
+ `(html-tag-face ((,class (:foreground "#ffff0b"))))
+ `(ilog-non-change-face ((,class (:height 2.0 :foreground "#9fcb66"))))
+ `(ilog-change-face ((,class (:height 2.0 :foreground "#ff7dff"))))
+ `(ilog-echo-face ((,class (:height 2.0 :foreground "#ff9029"))))
+ `(ilog-load-face ((,class (:foreground "#4ac964"))))
+ `(ilog-message-face ((,class (:foreground "#837f87"))))
+ `(indent-guide-face ((,class (:foreground "#312c36"))))
+ `(info-file ((,class (:family "Sans Serif" :height 1.8 :weight bold :box (:line-width 1 :color "#ffff3d") :foreground "#9f6a1c" :background "#563c2a"))))
+ `(info-header-node ((,class (:underline t :foreground "#065aff")))) ; nodes in header
+ `(info-header-xref ((,class (:underline t :foreground "#e46f0b")))) ; cross references in header
+ `(info-index-match ((,class (:weight bold :foreground nil :background "#0742d2")))) ; when using `i'
+ `(info-menu-header ((,class ,ol2))) ; menu titles (headers) -- major topics
+ `(info-menu-star ((,class (:foreground "#ffffff")))) ; every 3rd menu item
+ `(info-node ((,class (:underline t :foreground "#ffff0b")))) ; node names
+ `(info-quoted-name ((,class ,code-inline)))
+ `(info-string ((,class ,string)))
+ `(info-title-1 ((,class ,ol1)))
+ `(info-xref ((,class (:underline t :foreground "#ff925a")))) ; unvisited cross-references
+ `(info-xref-visited ((,class (:underline t :foreground "#78ff7c")))) ; previously visited cross-references
+ ;; js2-highlight-vars-face (~ auto-highlight-symbol)
+ `(js2-error ((,class (:box (:line-width 1 :color "#06c8cf") :background "#063741")))) ; DONE.
+ `(js2-external-variable ((,class (:foreground "#06ffff" :background "#252630")))) ; DONE.
+ `(js2-function-param ((,class ,function-param)))
+ `(js2-instance-member ((,class (:foreground "#6bcd3d"))))
+ `(js2-jsdoc-html-tag-delimiter ((,class (:foreground "#34c8d8"))))
+ `(js2-jsdoc-html-tag-name ((,class (:foreground "#34c8d8"))))
+ `(js2-jsdoc-tag ((,class (:weight normal :foreground "#9fcb66"))))
+ `(js2-jsdoc-type ((,class (:foreground "#bd7d55"))))
+ `(js2-jsdoc-value ((,class (:weight normal :foreground "#4ac964")))) ; #83ff87
+ `(js2-magic-paren ((,class (:underline t))))
+ `(js2-private-function-call ((,class (:foreground "#2a5ae5"))))
+ `(js2-private-member ((,class (:foreground "#375073"))))
+ `(js2-warning ((,class (:underline "#065aff"))))
+
+ ;; Org non-standard faces.
+ `(leuven-dark-org-deadline-overdue ((,class (:foreground "#12d9ae"))))
+ `(leuven-dark-org-deadline-today ((,class (:weight bold :foreground "#b4b5ca" :background "#252059"))))
+ `(leuven-dark-org-deadline-tomorrow ((,class (:foreground "#c357f8"))))
+ `(leuven-dark-org-deadline-future ((,class (:foreground "#c357f8"))))
+ `(leuven-dark-gnus-unseen ((,class (:weight bold :foreground "#088dfd"))))
+ `(leuven-dark-gnus-date ((,class (:foreground "#067f4a"))))
+ `(leuven-dark-gnus-size ((,class (:foreground "#7440a7"))))
+ `(leuven-dark-todo-items-face ((,class (:weight bold :foreground "#06cee0" :background "#06017f"))))
+
+ `(light-symbol-face ((,class (:background "#252080"))))
+ `(linum ((,class (:foreground "#6a656f" :background "#35303a"))))
+ `(log-view-file ((,class (:foreground "#ffff3d" :background "#382c33"))))
+ `(log-view-message ((,class (:foreground "#ffffff" :background "#171593"))))
+ `(lsp-modeline-code-actions-preferred-face ((,class (:foreground "#ffffff" :background "#2526c0"))))
+ `(lsp-ui-doc-background ((,class (:background "#2d2058"))))
+ `(lsp-ui-sideline-code-action ((,class (:foreground "#ffffff" :background "#2526c0"))))
+ `(lui-button-face ((,class ,link)))
+ `(lui-highlight-face ((,class (:box '(:line-width 1 :color "#38ffff") :foreground "#38ffff" :background "#06017f")))) ; my nickname
+ `(lui-time-stamp-face ((,class (:foreground "#64df19"))))
+ `(magit-blame-header ((,class (:inherit magit-diff-file-header))))
+ `(magit-blame-heading ((,class (:overline "#5d5862" :foreground "#06ffff" :background "#3c3741"))))
+ `(magit-blame-hash ((,class (:overline "#5d5862" :foreground "#06ffff" :background "#3c3741"))))
+ `(magit-blame-name ((,class (:overline "#5d5862" :foreground "#fd95fa" :background "#3c3741"))))
+ `(magit-blame-date ((,class (:overline "#5d5862" :foreground "#ffff0b" :background "#3c3741"))))
+ `(magit-blame-summary ((,class (:overline "#5d5862" :weight bold :foreground "#938f97" :background "#3c3741"))))
+ `(magit-branch ((,class ,vc-branch)))
+ `(magit-diff-add ((,class ,diff-added)))
+ `(magit-diff-del ((,class ,diff-removed)))
+ `(magit-diff-file-header ((,class (:height 1.1 :weight bold :foreground "#c27c45"))))
+ `(magit-diff-hunk-header ((,class ,diff-hunk-header)))
+ `(magit-diff-none ((,class ,diff-none)))
+ `(magit-header ((,class (:foreground "#25202a" :background "#06bfc7"))))
+ `(magit-item-highlight ((,class (:background "#382c33"))))
+ `(magit-item-mark ((,class ,marked-line)))
+ `(magit-log-head-label ((,class (:box (:line-width 1 :color "#ffff0b" :style nil)))))
+ `(magit-log-tag-label ((,class (:box (:line-width 1 :color "#ff33ff" :style nil)))))
+ `(magit-section-highlight ((,class (:background "#2d2058"))))
+ `(magit-section-title ((,class (:family "Sans Serif" :height 1.8 :weight bold :foreground "#9f6a1c" :inherit nil))))
+ `(makefile-space-face ((,class (:background "#069655"))))
+ `(makefile-targets ((,class (:weight bold :foreground "#ffff0b"))))
+ ;; `(markdown-blockquote-face ((,class ())))
+ `(markdown-bold-face ((,class (:inherit bold))))
+ ;; `(markdown-comment-face ((,class ())))
+ ;; `(markdown-footnote-face ((,class ())))
+ ;; `(markdown-header-delimiter-face ((,class ())))
+ ;; `(markdown-header-face ((,class ())))
+ `(markdown-header-face-1 ((,class ,ol1)))
+ `(markdown-header-face-2 ((,class ,ol2)))
+ `(markdown-header-face-3 ((,class ,ol3)))
+ `(markdown-header-face-4 ((,class ,ol4)))
+ `(markdown-header-face-5 ((,class ,ol5)))
+ `(markdown-header-face-6 ((,class ,ol6)))
+ ;; `(markdown-header-rule-face ((,class ())))
+ `(markdown-inline-code-face ((,class ,code-inline)))
+ `(markdown-italic-face ((,class (:inherit italic))))
+ `(markdown-language-keyword-face ((,class (:inherit org-block-begin-line))))
+ ;; `(markdown-line-break-face ((,class ())))
+ `(markdown-link-face ((,class ,link-no-underline)))
+ ;; `(markdown-link-title-face ((,class ())))
+ ;; `(markdown-list-face ((,class ())))
+ ;; `(markdown-math-face ((,class ())))
+ ;; `(markdown-metadata-key-face ((,class ())))
+ ;; `(markdown-metadata-value-face ((,class ())))
+ ;; `(markdown-missing-link-face ((,class ())))
+ `(markdown-pre-face ((,class (:inherit org-block-background))))
+ ;; `(markdown-reference-face ((,class ())))
+ ;; `(markdown-strike-through-face ((,class ())))
+ `(markdown-url-face ((,class ,link)))
+ `(match ((,class ,match))) ; Used for grep matches.
+ `(mc/cursor-bar-face ((,class (:height 1.0 :foreground "#ec9b45" :background "#ec9b45"))))
+ `(mc/cursor-face ((,class (:inverse-video t))))
+ `(mc/region-face ((,class (:inherit region))))
+ `(mm-uu-extract ((,class ,code-block)))
+ `(moccur-current-line-face ((,class (:foreground "#ffffff" :background "#252059"))))
+ `(moccur-face ((,class (:foreground "#ffffff" :background "#06016f"))))
+ `(next-error ((,class ,volatile-highlight-supersize)))
+ `(nobreak-space ((,class (:background "#543532"))))
+ `(nxml-attribute-local-name-face ((,class ,xml-attribute)))
+ `(nxml-attribute-value-delimiter-face ((,class (:foreground "#ff74ff"))))
+ `(nxml-attribute-value-face ((,class (:foreground "#ff74ff"))))
+ `(nxml-comment-content-face ((,class (:slant italic :foreground "#06ffff"))))
+ `(nxml-comment-delimiter-face ((,class (:foreground "#06ffff"))))
+ `(nxml-element-local-name ((,class ,xml-tag)))
+ `(nxml-element-local-name-face ((,class (:foreground "#ffff0b"))))
+ `(nxml-processing-instruction-target-face ((,class (:foreground "#69cf0b"))))
+ `(nxml-tag-delimiter-face ((,class (:foreground "#ffff0b"))))
+ `(nxml-tag-slash-face ((,class (:foreground "#ffff0b"))))
+ `(org-agenda-block-count ((,class (:weight bold :foreground "#5f5a64"))))
+ `(org-agenda-calendar-event ((,class (:weight bold :foreground "#cc8b3d" :background "#3e322a"))))
+ `(org-agenda-calendar-sexp ((,class (:foreground "#d0853c" :background "#30272c"))))
+ `(org-agenda-clocking ((,class (:foreground "#ffffff" :background "#1636ff"))))
+ `(org-agenda-column-dateline ((,class ,column)))
+ `(org-agenda-current-time ((,class (:underline t :foreground "#ec9d5a"))))
+ `(org-agenda-date ((,class (,@(leuven-dark-scale-font leuven-dark-scale-org-agenda-structure 1.6) :weight bold :foreground "#ec9d5a"))))
+ `(org-agenda-date-today ((,class (,@(leuven-dark-scale-font leuven-dark-scale-org-agenda-structure 1.6) :weight bold :foreground "#b4b5ca" :background "#252059"))))
+ `(org-agenda-date-weekend ((,class (,@(leuven-dark-scale-font leuven-dark-scale-org-agenda-structure 1.6) :weight bold :foreground "#b5b1b9"))))
+ `(org-agenda-diary ((,class (:weight bold :foreground "#ff74ff" :background "#572723"))))
+ `(org-agenda-dimmed-todo-face ((,class (:foreground "#1636ff"))))
+ `(org-agenda-done ((,class (:foreground "#aeaab2"))))
+ `(org-agenda-filter-category ((,class (:weight bold :foreground "#065aff"))))
+ `(org-agenda-filter-effort ((,class (:weight bold :foreground "#065aff"))))
+ `(org-agenda-filter-regexp ((,class (:weight bold :foreground "#065aff"))))
+ `(org-agenda-filter-tags ((,class (:weight bold :foreground "#065aff"))))
+ `(org-agenda-restriction-lock ((,class (:background "#1d82a4"))))
+ `(org-agenda-structure ((,class (,@(leuven-dark-scale-font leuven-dark-scale-org-agenda-structure 1.6) :weight bold :foreground "#e37233"))))
+ `(org-archived ((,class (:foreground "#514c56"))))
+ `(org-beamer-tag ((,class (:box (:line-width 1 :color "#0a43ed") :foreground "#d6d3d9" :background "#252655"))))
+ `(org-block ((,class ,code-block)))
+ `(org-block-background ((,class (:background "#252046")))) ;; :inherit fixed-pitch))))
+ `(org-block-begin-line ((,class (:underline "#5d595f" :foreground "#aeaab2" :background "#221e34"))))
+ `(org-block-end-line ((,class (:overline "#5d595f" :foreground "#aeaab2" :background "#221e34"))))
+ `(org-checkbox ((,class (:weight bold :box (:line-width 1 :style pressed-button) :foreground "#efcab2" :background "#615c66"))))
+ `(org-clock-overlay ((,class (:foreground "#25202a" :background "#b98f7c"))))
+ `(org-code ((,class ,code-inline)))
+ `(org-column ((,class ,column)))
+ `(org-column-title ((,class ,column)))
+ `(org-date ((,class (:underline t :foreground "#ffba6b"))))
+ `(org-default ((,class (:foreground "#cfccd2" :background "#25202a"))))
+ `(org-dim ((,class (:foreground "#5a555f"))))
+ `(org-document-info ((,class (:foreground "#bbb7bf"))))
+ `(org-document-info-keyword ((,class (:foreground "#ff7138" :background "#38332a"))))
+ `(org-document-title ((,class (,@(leuven-dark-scale-font leuven-dark-scale-org-document-title 1.8) :weight bold :foreground "#ffffff"))))
+ `(org-done ((,class (:weight bold :box (:line-width 1 :color "#49444e") :foreground "#49444e" :background "#322d37"))))
+ `(org-drawer ((,class (:weight bold :foreground "#ff44ff" :background "#38203d"))))
+ `(org-ellipsis ((,class (:underline nil :foreground "#6b666f")))) ; #0611a5
+ `(org-example ((,class (:foreground "#ffff0b" :background "#38203d"))))
+ `(org-footnote ((,class (:underline t :foreground "#ff7138"))))
+ `(org-formula ((,class (:foreground "#0680e1"))))
+ ;; org-habit colours are thanks to zenburn
+ `(org-habit-ready-face ((t :background "#7F9F7F"))) ; ,zenburn-green
+ `(org-habit-alert-face ((t :background "#E0CF9F" :foreground "#3F3F3F"))) ; ,zenburn-yellow-1 fg ,zenburn-bg
+ `(org-habit-clear-face ((t :background "#5C888B"))) ; ,zenburn-blue-3
+ `(org-habit-overdue-face ((t :background "#9C6363"))) ; ,zenburn-red-3
+ `(org-habit-clear-future-face ((t :background "#4C7073"))) ; ,zenburn-blue-4
+ `(org-habit-ready-future-face ((t :background "#5F7F5F"))) ; ,zenburn-green-2
+ `(org-habit-alert-future-face ((t :background "#D0BF8F" :foreground "#3F3F3F"))) ; ,zenburn-yellow-2 fg ,zenburn-bg
+ `(org-habit-overdue-future-face ((t :background "#8C5353"))) ; ,zenburn-red-4
+ `(org-headline-done ((,class (:height 1.0 :weight normal :foreground "#57525c"))))
+ `(org-hide ((,class (:foreground "#403b45"))))
+ `(org-inlinetask ((,class (:box (:line-width 1 :color "#37323c") :foreground "#8c8890" :background "#252050"))))
+ `(org-latex-and-related ((,class (:foreground "#cf996f" :background "#25202a"))))
+ `(org-level-1 ((,class ,ol1)))
+ `(org-level-2 ((,class ,ol2)))
+ `(org-level-3 ((,class ,ol3)))
+ `(org-level-4 ((,class ,ol4)))
+ `(org-level-5 ((,class ,ol5)))
+ `(org-level-6 ((,class ,ol6)))
+ `(org-level-7 ((,class ,ol7)))
+ `(org-level-8 ((,class ,ol8)))
+ `(org-link ((,class ,link)))
+ `(org-list-dt ((,class (:weight bold :foreground "#cfa161"))))
+ `(org-macro ((,class (:weight bold :foreground "#1747fd"))))
+ `(org-meta-line ((,class (:slant normal :foreground "#ff7138" :background "#38332a"))))
+ `(org-mode-line-clock ((,class (:box (:line-width 1 :color "#cfa161") :foreground "#ffffff" :background "#065cd0"))))
+ `(org-mode-line-clock-overrun ((,class (:weight bold :box (:line-width 1 :color "#cfa161") :foreground "#25202a" :background "#06bfc7"))))
+ `(org-number-of-items ((,class (:weight bold :foreground "#25202a" :background "#8a458e"))))
+ `(org-property-value ((,class (:foreground "#ff5fff"))))
+ `(org-quote ((,class (:slant italic :foreground "#9a969e" :background "#252046"))))
+ `(org-scheduled ((,class (:foreground "#cfccd2"))))
+ `(org-scheduled-previously ((,class (:foreground "#ed9943"))))
+ `(org-scheduled-today ((,class (:weight bold :foreground "#b4b5ca" :background "#252059"))))
+ `(org-sexp-date ((,class (:foreground "#cc8b3d"))))
+ `(org-special-keyword ((,class (:weight bold :foreground "#ff44ff" :background "#38203d"))))
+ `(org-table ((,class (:foreground "#ff9bff" :background "#38203d")))) ;; :inherit fixed-pitch))))
+ `(org-tag ((,class (:weight normal :slant italic :foreground "#6a6065" :background "#25202a"))))
+ `(org-target ((,class (:foreground "#06925a"))))
+ `(org-time-grid ((,class (:foreground "#35303a"))))
+ `(org-todo ((,class (:weight bold :box (:line-width 1 :color "#2c5462") :foreground "#2c5462" :background "#253743"))))
+ `(org-upcoming-deadline ((,class (:foreground "#06aab2"))))
+ `(org-verbatim ((,class (:foreground "#ff993d" :background "#2c212a"))))
+ `(org-verse ((,class (:slant italic :foreground "#9a969e" :background "#342f39"))))
+ `(org-warning ((,class (:weight bold :foreground "#ffffff" :background "#54362a"))))
+ `(outline-1 ((,class ,ol1)))
+ `(outline-2 ((,class ,ol2)))
+ `(outline-3 ((,class ,ol3)))
+ `(outline-4 ((,class ,ol4)))
+ `(outline-5 ((,class ,ol5)))
+ `(outline-6 ((,class ,ol6)))
+ `(outline-7 ((,class ,ol7)))
+ `(outline-8 ((,class ,ol8)))
+ `(pabbrev-debug-display-label-face ((,class (:foreground "#25202a" :background "#5edeb3"))))
+ `(pabbrev-suggestions-face ((,class (:weight bold :foreground "#25202a" :background "#06ffff"))))
+ `(pabbrev-suggestions-label-face ((,class (:weight bold :foreground "#25202a" :background "#64df19"))))
+ `(paren-face-match ((,class ,paren-matched)))
+ `(paren-face-mismatch ((,class ,paren-unmatched)))
+ `(paren-face-no-match ((,class ,paren-unmatched)))
+ `(persp-selected-face ((,class (:weight bold :foreground "#34292a"))))
+ `(powerline-active1 ((,class (:foreground "#7e311e" :background "#cbc7ce" :inherit mode-line))))
+ `(powerline-active2 ((,class (:foreground "#7e311e" :background "#c38f53" :inherit mode-line))))
+ `(powerline-inactive1 ((,class (:foreground "#322d38" :background "#9b979f" :inherit mode-line-inactive))))
+ `(powerline-inactive2 ((,class (:foreground "#322d38" :background "#5b5660" :inherit mode-line-inactive))))
+ `(rainbow-delimiters-depth-1-face ((,class (:foreground "#938e84"))))
+ `(rainbow-delimiters-depth-2-face ((,class (:foreground "#907733"))))
+ `(rainbow-delimiters-depth-3-face ((,class (:foreground "#736e84"))))
+ `(rainbow-delimiters-depth-4-face ((,class (:foreground "#936797"))))
+ `(rainbow-delimiters-depth-5-face ((,class (:foreground "#738c94"))))
+ `(rainbow-delimiters-depth-6-face ((,class (:foreground "#a1894f"))))
+ `(rainbow-delimiters-depth-7-face ((,class (:foreground "#7e7a87"))))
+ `(rainbow-delimiters-depth-8-face ((,class (:foreground "#835787"))))
+ `(rainbow-delimiters-depth-9-face ((,class (:foreground "#7b8f97"))))
+ `(rainbow-delimiters-mismatched-face ((,class ,paren-unmatched)))
+ `(rainbow-delimiters-unmatched-face ((,class ,paren-unmatched)))
+ `(recover-this-file ((,class (:weight bold :background "#06c0c8"))))
+ `(rng-error ((,class (:weight bold :foreground "#06ffff" :background "#283a43"))))
+ `(sh-heredoc ((,class (:foreground "#ffff0b" :background "#34292a"))))
+ `(sh-quoted-exec ((,class (:foreground "#06eb74"))))
+ `(shadow ((,class ,shadow))) ; Used for grep context lines.
+ `(shell-option-face ((,class (:foreground "#e074e3"))))
+ `(shell-output-2-face ((,class (:foreground "#ffff0b"))))
+ `(shell-output-3-face ((,class (:foreground "#64df19"))))
+ `(shell-output-face ((,class (:foreground "#ffffff"))))
+ ;; `(shell-prompt-face ((,class (:weight bold :foreground "#0601ff"))))
+ `(shm-current-face ((,class (:background "#343551"))))
+ `(shm-quarantine-face ((,class (:background "lemonchiffon"))))
+ `(show-paren-match ((,class ,paren-matched)))
+ `(show-paren-mismatch ((,class ,paren-unmatched)))
+ `(sml-modeline-end-face ((,class (:background "#985213")))) ; #cfa161
+ `(sml-modeline-vis-face ((,class (:background "#e9863f"))))
+ `(term ((,class (:foreground "#cfccd2" :background "#25202a"))))
+
+ ;; `(sp-pair-overlay-face ((,class ())))
+ ;; `(sp-show-pair-enclosing ((,class ())))
+ ;; `(sp-show-pair-match-face ((,class ()))) ; ~ Pair highlighting (matching tags).
+ ;; `(sp-show-pair-mismatch-face ((,class ())))
+ ;; `(sp-wrap-overlay-closing-pair ((,class ())))
+ ;; `(sp-wrap-overlay-face ((,class ())))
+ ;; `(sp-wrap-overlay-opening-pair ((,class ())))
+ ;; `(sp-wrap-tag-overlay-face ((,class ())))
+
+ `(speedbar-button-face ((,class (:foreground "#ff74ff"))))
+ `(speedbar-directory-face ((,class (:foreground "#ffff7c"))))
+ `(speedbar-file-face ((,class (:foreground "#ff747c"))))
+ `(speedbar-highlight-face ((,class ,volatile-highlight)))
+ `(speedbar-selected-face ((,class (:underline t :foreground "#06ffff"))))
+ `(speedbar-tag-face ((,class (:foreground "#5fd5db"))))
+ `(svn-status-directory-face ((,class ,directory)))
+ `(svn-status-filename-face ((,class (:weight bold :foreground "#c27c45"))))
+ `(svn-status-locked-face ((,class (:weight bold :foreground "#06ffff"))))
+ `(svn-status-marked-face ((,class ,marked-line)))
+ `(svn-status-marked-popup-face ((,class (:weight bold :foreground "#ff32ff"))))
+ `(svn-status-switched-face ((,class (:slant italic :foreground "#77737b"))))
+ `(svn-status-symlink-face ((,class ,symlink)))
+ `(svn-status-update-available-face ((,class (:foreground "#065aff"))))
+ `(tex-verbatim ((,class (:foreground "#ffff0b"))))
+ `(tool-bar ((,class (:box (:line-width 1 :style released-button) :foreground "#ffffff" :background "#45404a"))))
+ `(tooltip ((,class (:foreground "#ffffff" :background "#252046"))))
+ `(traverse-match-face ((,class (:weight bold :foreground "#79d427"))))
+ `(vc-annotate-face-3F3FFF ((,class (:foreground "#c4c00b" :background "#ffffff"))))
+ `(vc-annotate-face-3F6CFF ((,class (:foreground "#c4c00b" :background "#ffffff"))))
+ `(vc-annotate-face-3F99FF ((,class (:foreground "#c4660b" :background "#ffffff"))))
+ `(vc-annotate-face-3FC6FF ((,class (:foreground "#c4660b" :background "#ffffff"))))
+ `(vc-annotate-face-3FF3FF ((,class (:foreground "#c40c0b" :background "#ffffff"))))
+ `(vc-annotate-face-3FFF56 ((,class (:foreground "#b801bc" :background "#ffffff"))))
+ `(vc-annotate-face-3FFF83 ((,class (:foreground "#c40159" :background "#ffffff"))))
+ `(vc-annotate-face-3FFFB0 ((,class (:foreground "#c40159" :background "#ffffff"))))
+ `(vc-annotate-face-3FFFDD ((,class (:foreground "#c40c0b" :background "#ffffff"))))
+ `(vc-annotate-face-56FF3F ((,class (:foreground "#b801bc" :background "#ffffff"))))
+ `(vc-annotate-face-83FF3F ((,class (:foreground "#5401c8" :background "#ffffff"))))
+ `(vc-annotate-face-B0FF3F ((,class (:foreground "#5401c8" :background "#ffffff"))))
+ `(vc-annotate-face-DDFF3F ((,class (:foreground "#060cc8" :background "#ffffff"))))
+ `(vc-annotate-face-F6FFCC ((,class (:foreground "#ffffff" :background "#252064"))))
+ `(vc-annotate-face-FF3F3F ((,class (:foreground "#06c0c8" :background "#ffffff"))))
+ `(vc-annotate-face-FF6C3F ((,class (:foreground "#06c0c8" :background "#ffffff"))))
+ `(vc-annotate-face-FF993F ((,class (:foreground "#0666c8" :background "#ffffff"))))
+ `(vc-annotate-face-FFC63F ((,class (:foreground "#0666c8" :background "#ffffff"))))
+ `(vc-annotate-face-FFF33F ((,class (:foreground "#060cc8" :background "#ffffff"))))
+
+ ;; ;; vc
+ ;; (vc-up-to-date-state ((,c :foreground ,(gc 'green-1))))
+ ;; (vc-edited-state ((,c :foreground ,(gc 'yellow+1))))
+ ;; (vc-missing-state ((,c :foreground ,(gc 'red))))
+ ;; (vc-conflict-state ((,c :foreground ,(gc 'red+2) :weight bold)))
+ ;; (vc-locked-state ((,c :foreground ,(gc 'cyan-1))))
+ ;; (vc-locally-added-state ((,c :foreground ,(gc 'blue))))
+ ;; (vc-needs-update-state ((,c :foreground ,(gc 'magenta))))
+ ;; (vc-removed-state ((,c :foreground ,(gc 'red-1))))
+
+ `(vhl/default-face ((,class ,volatile-highlight))) ; `volatile-highlights.el' (for undo, yank).
+ `(w3m-anchor ((,class ,link)))
+ `(w3m-arrived-anchor ((,class (:foreground "#69cf0b"))))
+ `(w3m-bitmap-image-face ((,class (:foreground "#f7f5f9" :background "#ff01ff"))))
+ `(w3m-bold ((,class (:weight bold :foreground "#ffffff"))))
+ `(w3m-current-anchor ((,class (:weight bold :underline t :foreground "#ffff0b"))))
+ `(w3m-form ((,class (:underline t :foreground "#065ab8"))))
+ `(w3m-form-button-face ((,class (:weight bold :underline t :foreground "#f7f5f9" :background "#312c36"))))
+ `(w3m-form-button-mouse-face ((,class (:underline t :foreground "#312c36" :background "#d781db"))))
+ `(w3m-form-button-pressed-face ((,class (:weight bold :underline t :foreground "#f7f5f9" :background "#312c36"))))
+ `(w3m-header-line-location-content-face ((,class (:foreground "#848088":background "#2c2731"))))
+ `(w3m-header-line-location-title-face ((,class (:foreground "#d6aa58" :background "#2c2731"))))
+ `(w3m-history-current-url-face ((,class (:foreground "#252458"))))
+ `(w3m-image-face ((,class (:weight bold :foreground "#501155"))))
+ `(w3m-link-numbering ((,class (:foreground "#50381e")))) ; mouseless browsing
+ `(w3m-strike-through-face ((,class (:strike-through t))))
+ `(w3m-underline-face ((,class (:underline t))))
+
+ ;; `(web-mode-block-attr-name-face ((,class ())))
+ ;; `(web-mode-block-attr-value-face ((,class ())))
+ ;; `(web-mode-block-comment-face ((,class ())))
+ ;; `(web-mode-block-control-face ((,class ())))
+ ;; `(web-mode-block-delimiter-face ((,class ())))
+ ;; `(web-mode-block-face ((,class ())))
+ ;; `(web-mode-block-string-face ((,class ())))
+ ;; `(web-mode-bold-face ((,class ())))
+ ;; `(web-mode-builtin-face ((,class ())))
+ ;; `(web-mode-comment-face ((,class ())))
+ ;; `(web-mode-comment-keyword-face ((,class ())))
+ ;; `(web-mode-constant-face ((,class ())))
+ ;; `(web-mode-css-at-rule-face ((,class ())))
+ ;; `(web-mode-css-color-face ((,class ())))
+ ;; `(web-mode-css-comment-face ((,class ())))
+ ;; `(web-mode-css-function-face ((,class ())))
+ ;; `(web-mode-css-priority-face ((,class ())))
+ ;; `(web-mode-css-property-name-face ((,class ())))
+ ;; `(web-mode-css-pseudo-class-face ((,class ())))
+ ;; `(web-mode-css-selector-face ((,class ())))
+ ;; `(web-mode-css-string-face ((,class ())))
+ ;; `(web-mode-css-variable-face ((,class ())))
+ ;; `(web-mode-current-column-highlight-face ((,class ())))
+ `(web-mode-current-element-highlight-face ((,class (:background "#6b330b")))) ; #061187
+ ;; `(web-mode-doctype-face ((,class ())))
+ ;; `(web-mode-error-face ((,class ())))
+ ;; `(web-mode-filter-face ((,class ())))
+ `(web-mode-folded-face ((,class (:box (:line-width 1 :color "#8c8890") :foreground "#6a659d" :background "#110cbe"))))
+ ;; `(web-mode-function-call-face ((,class ())))
+ ;; `(web-mode-function-name-face ((,class ())))
+ ;; `(web-mode-html-attr-custom-face ((,class ())))
+ ;; `(web-mode-html-attr-engine-face ((,class ())))
+ ;; `(web-mode-html-attr-equal-face ((,class ())))
+ `(web-mode-html-attr-name-face ((,class ,xml-attribute)))
+ ;; `(web-mode-html-attr-value-face ((,class ())))
+ ;; `(web-mode-html-entity-face ((,class ())))
+ `(web-mode-html-tag-bracket-face ((,class ,xml-tag)))
+ ;; `(web-mode-html-tag-custom-face ((,class ())))
+ `(web-mode-html-tag-face ((,class ,xml-tag)))
+ ;; `(web-mode-html-tag-namespaced-face ((,class ())))
+ ;; `(web-mode-inlay-face ((,class ())))
+ ;; `(web-mode-italic-face ((,class ())))
+ ;; `(web-mode-javascript-comment-face ((,class ())))
+ ;; `(web-mode-javascript-string-face ((,class ())))
+ ;; `(web-mode-json-comment-face ((,class ())))
+ ;; `(web-mode-json-context-face ((,class ())))
+ ;; `(web-mode-json-key-face ((,class ())))
+ ;; `(web-mode-json-string-face ((,class ())))
+ ;; `(web-mode-jsx-depth-1-face ((,class ())))
+ ;; `(web-mode-jsx-depth-2-face ((,class ())))
+ ;; `(web-mode-jsx-depth-3-face ((,class ())))
+ ;; `(web-mode-jsx-depth-4-face ((,class ())))
+ ;; `(web-mode-keyword-face ((,class ())))
+ ;; `(web-mode-param-name-face ((,class ())))
+ ;; `(web-mode-part-comment-face ((,class ())))
+ `(web-mode-part-face ((,class (:background "#252046"))))
+ ;; `(web-mode-part-string-face ((,class ())))
+ ;; `(web-mode-preprocessor-face ((,class ())))
+ `(web-mode-script-face ((,class (:background "#332d37"))))
+ ;; `(web-mode-sql-keyword-face ((,class ())))
+ ;; `(web-mode-string-face ((,class ())))
+ ;; `(web-mode-style-face ((,class ())))
+ ;; `(web-mode-symbol-face ((,class ())))
+ ;; `(web-mode-type-face ((,class ())))
+ ;; `(web-mode-underline-face ((,class ())))
+ ;; `(web-mode-variable-name-face ((,class ())))
+ ;; `(web-mode-warning-face ((,class ())))
+ ;; `(web-mode-whitespace-face ((,class ())))
+
+ `(which-func ((,class (:weight bold :slant italic :foreground "#25202a"))))
+ ;; `(which-key-command-description-face)
+ ;; `(which-key-group-description-face)
+ ;; `(which-key-highlighted-command-face)
+ ;; `(which-key-key-face)
+ `(which-key-local-map-description-face ((,class (:weight bold :background "#30272c" :inherit which-key-command-description-face))))
+ ;; `(which-key-note-face)
+ ;; `(which-key-separator-face)
+ ;; `(which-key-special-key-face)
+ `(widget-button ((,class ,link)))
+ `(widget-button-pressed ((,class (:foreground "#06ffff"))))
+ `(widget-documentation ((,class (:foreground "#ff74ff"))))
+ `(widget-field ((,class (:background "#2b2630"))))
+ `(widget-inactive ((,class (:foreground "#9a969e"))))
+ `(widget-single-line-field ((,class (:background "#2b2630"))))
+ `(woman-bold ((,class (:weight bold :foreground "#13c2ca"))))
+ `(woman-italic ((,class (:weight bold :slant italic :foreground "#bd41ea"))))
+ `(woman-symbol ((,class (:weight bold :foreground "#64df19"))))
+ `(yas-field-debug-face ((,class (:foreground "#25202a" :background "#5edeb3"))))
+ `(yas-field-highlight-face ((,class (:box (:line-width 1 :color "#807c84") :foreground "#ffffff" :background "#302331"))))
+
+ ;; `(ztreep-arrow-face ((,class ())))
+ ;; `(ztreep-diff-header-face ((,class ())))
+ ;; `(ztreep-diff-header-small-face ((,class ())))
+ `(ztreep-diff-model-add-face ((,class (:weight bold :foreground "#ff77ff"))))
+ `(ztreep-diff-model-diff-face ((,class (:weight bold :foreground "#ffbb2c"))))
+ `(ztreep-diff-model-ignored-face ((,class (:strike-through t :foreground "#66616b"))))
+ `(ztreep-diff-model-normal-face ((,class (:foreground "#ffffff"))))
+ ;; `(ztreep-expand-sign-face ((,class ())))
+ ;; `(ztreep-header-face ((,class ())))
+ ;; `(ztreep-leaf-face ((,class ())))
+ ;; `(ztreep-node-face ((,class ())))
+
+ ))
+
+(custom-theme-set-variables 'leuven-dark
+
+ ;; highlight-sexp-mode.
+ '(hl-sexp-background-color "#33323e")
+
+ '(ansi-color-faces-vector
+ [default default default italic underline success warning error])
+
+ ;; Colors used in Shell mode.
+ '(ansi-color-names-vector
+ ["#ffffff" "#37ffff" "#e074e3" "#3732ff" "#ffff0b" "#37ff3c" "#ff400b" "#848088"])
+ )
+
+;;;###autoload
+(when (and (boundp 'custom-theme-load-path)
+ load-file-name)
+ ;; Add theme folder to `custom-theme-load-path' when installing over MELPA.
+ (add-to-list 'custom-theme-load-path
+ (file-name-as-directory (file-name-directory load-file-name))))
+
+(provide-theme 'leuven-dark)
+
+;; This is for the sake of Emacs.
+;; Local Variables:
+;; time-stamp-end: "$"
+;; time-stamp-format: "%:y%02m%02d.%02H%02M"
+;; time-stamp-start: "Version: "
+;; End:
+
+;;; leuven-dark-theme.el ends here
diff --git a/etc/themes/manoj-dark-theme.el b/etc/themes/manoj-dark-theme.el
index b70620fe213..af5576386c6 100644
--- a/etc/themes/manoj-dark-theme.el
+++ b/etc/themes/manoj-dark-theme.el
@@ -380,7 +380,7 @@ jarring angry fruit salad look to reduce eye fatigue.")
:foreground "black" :background "grey"
:weight bold ))))
'(calendar-today-face ((t (:underline t :bold t :foreground "cornsilk"))))
- '(change-log-acknowledgement-face ((t (:italic t :slant oblique :foreground "AntiqueWhite3"))))
+ '(change-log-acknowledgment ((t (:italic t :slant oblique :foreground "AntiqueWhite3"))))
'(change-log-conditionals-face ((t (:foreground "Aquamarine"))))
'(change-log-date-face ((t (:italic t :slant oblique :foreground "BurlyWood"))))
'(change-log-email-face ((t (:foreground "Aquamarine"))))
@@ -400,7 +400,7 @@ jarring angry fruit salad look to reduce eye fatigue.")
'(compilation-warning-face ((t (:bold t :foreground "Orange" :weight bold))))
'(completions-common-part ((t (:width normal :weight normal
:slant normal :foreground "WhiteSmoke"
- :background "black" :height 81))))
+ :background "black" :height 0.9))))
'(completions-first-difference ((t (:bold t :weight bold))))
'(css-selector ((t (:foreground "LightSteelBlue"))))
diff --git a/etc/themes/modus-operandi-theme.el b/etc/themes/modus-operandi-theme.el
index a5e8fc701c4..646504636f0 100644
--- a/etc/themes/modus-operandi-theme.el
+++ b/etc/themes/modus-operandi-theme.el
@@ -1,10 +1,10 @@
-;;; modus-operandi-theme.el --- Accessible light theme (WCAG AAA) -*- lexical-binding:t -*-
+;;; modus-operandi-theme.el --- Elegant, highly legible and customizable light theme -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
-;; URL: https://gitlab.com/protesilaos/modus-themes
-;; Version: 2.0.0
+;; URL: https://git.sr.ht/~protesilaos/modus-themes
+;; Version: 2.4.1
;; Package-Requires: ((emacs "27.1"))
;; Keywords: faces, theme, accessibility
@@ -56,17 +56,17 @@
(equal (file-name-directory load-file-name)
(expand-file-name "themes/" data-directory))
(require-theme 'modus-themes t))
- (require 'modus-themes)))
+ (require 'modus-themes))
-(deftheme modus-operandi
- "Accessible and customizable light theme (WCAG AAA standard).
+ (deftheme modus-operandi
+ "Elegant, highly legible and customizable light theme.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1.")
+7:1 (WCAG AAA standard).")
-(modus-themes-theme modus-operandi)
+ (modus-themes-theme modus-operandi)
-(provide-theme 'modus-operandi)
+ (provide-theme 'modus-operandi))
;;; modus-operandi-theme.el ends here
diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el
index 8afa961ba3c..c543e7ec431 100644
--- a/etc/themes/modus-themes.el
+++ b/etc/themes/modus-themes.el
@@ -1,11 +1,11 @@
-;;; modus-themes.el --- Highly accessible themes (WCAG AAA) -*- lexical-binding:t -*-
+;;; modus-themes.el --- Elegant, highly legible and customizable themes -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
-;; URL: https://gitlab.com/protesilaos/modus-themes
-;; Version: 2.0.0
-;; Last-Modified: <2021-12-24 12:35:25 +0200>
+;; URL: https://git.sr.ht/~protesilaos/modus-themes
+;; Mailing list: https://lists.sr.ht/~protesilaos/modus-themes
+;; Version: 2.4.1
;; Package-Requires: ((emacs "27.1"))
;; Keywords: faces, theme, accessibility
@@ -35,23 +35,25 @@
;;
;; The themes share the following customization variables:
;;
+;; modus-themes-completions (alist)
;; modus-themes-headings (alist)
;; modus-themes-org-agenda (alist)
;; modus-themes-bold-constructs (boolean)
;; modus-themes-deuteranopia (boolean)
;; modus-themes-inhibit-reload (boolean)
-;; modus-themes-intense-markup (boolean)
+;; modus-themes-intense-mouseovers (boolean)
;; modus-themes-italic-constructs (boolean)
;; modus-themes-mixed-fonts (boolean)
;; modus-themes-subtle-line-numbers (boolean)
;; modus-themes-variable-pitch-ui (boolean)
-;; modus-themes-completions (choice)
+;; modus-themes-box-buttons (choice)
;; modus-themes-diffs (choice)
;; modus-themes-fringes (choice)
;; modus-themes-hl-line (choice)
;; modus-themes-lang-checkers (choice)
;; modus-themes-links (choice)
;; modus-themes-mail-citations (choice)
+;; modus-themes-markup (choice)
;; modus-themes-mode-line (choice)
;; modus-themes-org-blocks (choice)
;; modus-themes-paren-match (choice)
@@ -66,295 +68,8 @@
;; modus-themes-operandi-color-overrides (alist)
;; modus-themes-vivendi-color-overrides (alist)
;;
-;; Below is the list of explicitly supported packages or face groups
-;; (there are implicitly supported packages as well, which inherit from
-;; font-lock or some basic group). You are encouraged to report any
-;; missing package or change you would like to see.
-;;
-;; ace-window
-;; alert
-;; all-the-icons
-;; annotate
-;; ansi-color
-;; anzu
-;; apropos
-;; artbollocks-mode
-;; auctex and TeX
-;; auto-dim-other-buffers
-;; avy
-;; awesome-tray
-;; bbdb
-;; binder
-;; bm
-;; bongo
-;; boon
-;; bookmark
-;; breakpoint (provided by built-in gdb-mi.el)
-;; calendar and diary
-;; calfw
-;; centaur-tabs
-;; cfrs
-;; change-log and log-view (`vc-print-log' and `vc-print-root-log')
-;; cider
-;; circe
-;; color-rg
-;; column-enforce-mode
-;; company-mode
-;; company-posframe
-;; compilation-mode
-;; completions
-;; consult
-;; corfu
-;; counsel
-;; counsel-css
-;; cov
-;; cperl-mode
-;; css-mode
-;; csv-mode
-;; ctrlf
-;; cursor-flash
-;; custom (M-x customize)
-;; dap-mode
-;; dashboard (emacs-dashboard)
-;; deadgrep
-;; debbugs
-;; deft
-;; dictionary
-;; diff-hl
-;; diff-mode
-;; dim-autoload
-;; dir-treeview
-;; Dired
-;; dired-async
-;; dired-git
-;; dired-git-info
-;; dired-narrow
-;; dired-subtree
-;; diredfl
-;; diredp (dired+)
-;; display-fill-column-indicator-mode
-;; doom-modeline
-;; dynamic-ruler
-;; easy-jekyll
-;; ebdb
-;; ediff
-;; eglot
-;; el-search
-;; eldoc
-;; eldoc-box
-;; elfeed
-;; elfeed-score
-;; elpher
-;; embark
-;; emms
-;; enh-ruby-mode (enhanced-ruby-mode)
-;; epa
-;; equake
-;; erc
-;; eros
-;; ert
-;; eshell
-;; eshell-fringe-status
-;; eshell-git-prompt
-;; eshell-prompt-extras (epe)
-;; eshell-syntax-highlighting
-;; evil (evil-mode)
-;; evil-goggles
-;; evil-snipe
-;; evil-visual-mark-mode
-;; eww
-;; exwm
-;; eyebrowse
-;; fancy-dabbrev
-;; flycheck
-;; flycheck-color-mode-line
-;; flycheck-indicator
-;; flycheck-posframe
-;; flymake
-;; flyspell
-;; flx
-;; freeze-it
-;; frog-menu
-;; focus
-;; fold-this
-;; font-lock (generic syntax highlighting)
-;; forge
-;; fountain (fountain-mode)
-;; geiser
-;; git-commit
-;; git-gutter (and variants)
-;; git-rebase
-;; git-timemachine
-;; gnus
-;; gotest
-;; golden-ratio-scroll-screen
-;; helm
-;; helm-ls-git
-;; helm-switch-shell
-;; helm-xref
-;; helpful
-;; highlight-indentation
-;; highlight-numbers
-;; highlight-thing
-;; hl-defined
-;; hl-fill-column
-;; hl-line-mode
-;; hl-todo
-;; hydra
-;; ibuffer
-;; icomplete
-;; ido-mode
-;; iedit
-;; iflipb
-;; image-dired
-;; imenu-list
-;; indium
-;; info
-;; info-colors
-;; interaction-log
-;; ioccur
-;; isearch, occur, etc.
-;; ivy
-;; ivy-posframe
-;; jira (org-jira)
-;; journalctl-mode
-;; js2-mode
-;; julia
-;; jupyter
-;; kaocha-runner
-;; keycast
-;; ledger-mode
-;; line numbers (`display-line-numbers-mode' and global variant)
-;; lsp-mode
-;; lsp-ui
-;; macrostep
-;; magit
-;; magit-imerge
-;; make-mode
-;; man
-;; marginalia
-;; markdown-mode
-;; markup-faces (`adoc-mode')
-;; mentor
-;; messages
-;; minimap
-;; mmm-mode
-;; mode-line
-;; mood-line
-;; mpdel
-;; mu4e
-;; multiple-cursors
-;; nano-modeline
-;; neotree
-;; notmuch
-;; num3-mode
-;; nxml-mode
-;; orderless
-;; org
-;; org-journal
-;; org-noter
-;; org-pomodoro
-;; org-recur
-;; org-roam
-;; org-superstar
-;; org-table-sticky-header
-;; org-tree-slide
-;; org-treescope
-;; origami
-;; outline-mode
-;; outline-minor-faces
-;; package (M-x list-packages)
-;; page-break-lines
-;; pandoc-mode
-;; paradox
-;; paren-face
-;; pass
-;; pdf-tools
-;; persp-mode
-;; perspective
-;; phi-grep
-;; pomidor
-;; popup
-;; powerline
-;; powerline-evil
-;; prism (see "Note for prism.el" in the manual)
-;; proced
-;; prodigy
-;; pulse
-;; quick-peek
-;; racket-mode
-;; rainbow-blocks
-;; rainbow-delimiters
-;; rcirc
-;; recursion-indicator
-;; regexp-builder (also known as `re-builder')
-;; rg
-;; ripgrep
-;; rmail
-;; ruler-mode
-;; selectrum
-;; selectrum-prescient
-;; semantic
-;; sesman
-;; shell-script-mode
-;; shortdoc
-;; show-paren-mode
-;; shr
-;; side-notes
-;; sieve-mode
-;; skewer-mode
-;; smart-mode-line
-;; smartparens
-;; smerge
-;; spaceline
-;; speedbar
-;; stripes
-;; suggest
-;; switch-window
-;; swiper
-;; sx
-;; symbol-overlay
-;; syslog-mode
-;; tab-bar-groups
-;; tab-bar-mode
-;; tab-line-mode
-;; table (built-in table.el)
-;; telega
-;; telephone-line
-;; terraform-mode
-;; term
-;; tomatinho
-;; transient (pop-up windows like Magit's)
-;; trashed
-;; treemacs
-;; tty-menu
-;; tuareg
-;; typescript
-;; undo-tree
-;; vc (vc-dir.el, vc-hooks.el)
-;; vc-annotate (C-x v g)
-;; vertico
-;; vertico-quick
-;; vimish-fold
-;; visible-mark
-;; visual-regexp
-;; vterm
-;; wcheck-mode
-;; web-mode
-;; wgrep
-;; which-function-mode
-;; which-key
-;; whitespace-mode
-;; window-divider-mode
-;; winum
-;; writegood-mode
-;; woman
-;; xah-elisp-mode
-;; xref
-;; xterm-color (and ansi-colors)
-;; yaml-mode
-;; yasnippet
-;; ztree
+;; Check the manual for all supported packages (there are hundreds of
+;; them).
;;
;; For a complete view of the project, also refer to the following files
;; (should be distributed in the same repository/directory as the
@@ -367,7 +82,9 @@
-(eval-when-compile (require 'cl-lib))
+(eval-when-compile
+ (require 'cl-lib)
+ (require 'subr-x))
(defgroup modus-themes ()
"Options for `modus-operandi', `modus-vivendi'.
@@ -391,6 +108,36 @@ cover the blue-cyan-magenta side of the spectrum."
:prefix "modus-themes-"
:tag "Modus Themes Faces")
+(defvar modus-themes--version "2.5.0-dev"
+ "Current version of the Modus themes.
+
+The version either is the last tagged release, such as '2.4.0',
+or an in-development version like '2.5.0-dev'. As we use
+semantic versioning, tags of the '2.4.1' sort are not reported:
+those would count as part of '2.5.0-dev'.")
+
+;;;###autoload
+(defun modus-themes-version (&optional insert)
+ "Print `modus-themes--version' in the echo area.
+If optional INSERT argument is provided from Lisp or as a prefix
+argument, insert the `modus-themes--version' at point."
+ (interactive "P")
+ (if-let ((version modus-themes--version)
+ ((or insert current-prefix-arg)))
+ (insert version)
+ (message version)))
+
+;;;###autoload
+(defun modus-themes-report-bug ()
+ "Submit a bug report or issue to the Modus themes developers."
+ (interactive)
+ (reporter-submit-bug-report
+ "~protesilaos/modus-themes@lists.sr.ht"
+ (format "modus-themes (%s)\n" modus-themes--version)
+ ;; I am just getting started with this. Let's first see what people
+ ;; think about it.
+ nil nil nil nil))
+
;;; Variables for each theme variant
;;;; Modus Operandi
@@ -412,10 +159,10 @@ cover the blue-cyan-magenta side of the spectrum."
;; highlighted constructs; they must either be used as pairs based
;; on their name or each can be combined with {fg,bg}-{main,alt,dim}
;; always in accordance with their role as background or foreground
- (bg-special-cold . "#dde3f4") (fg-special-cold . "#093060")
- (bg-special-mild . "#c4ede0") (fg-special-mild . "#184034")
- (bg-special-warm . "#f0e0d4") (fg-special-warm . "#5d3026")
- (bg-special-calm . "#f8ddea") (fg-special-calm . "#61284f")
+ (bg-special-cold . "#dde3f4") (bg-special-faint-cold . "#f0f1ff") (fg-special-cold . "#093060")
+ (bg-special-mild . "#c4ede0") (bg-special-faint-mild . "#ebf5eb") (fg-special-mild . "#184034")
+ (bg-special-warm . "#f0e0d4") (bg-special-faint-warm . "#fef2ea") (fg-special-warm . "#5d3026")
+ (bg-special-calm . "#f8ddea") (bg-special-faint-calm . "#faeff9") (fg-special-calm . "#61284f")
;; foregrounds that can be combined with bg-main, bg-dim, bg-alt
(red . "#a60000")
(red-alt . "#972500")
@@ -495,18 +242,18 @@ cover the blue-cyan-magenta side of the spectrum."
;; those background values should only be used for graphs or similar
;; applications where colored blocks are expected to be positioned
;; next to each other
- (red-graph-0-bg . "#ef6f79")
- (red-graph-1-bg . "#ff9f9f")
- (green-graph-0-bg . "#49d239")
- (green-graph-1-bg . "#6dec6d")
- (yellow-graph-0-bg . "#efec08")
- (yellow-graph-1-bg . "#dbff4e")
- (blue-graph-0-bg . "#55a2f0")
- (blue-graph-1-bg . "#7fcfff")
- (magenta-graph-0-bg . "#ba86ef")
- (magenta-graph-1-bg . "#e7afff")
- (cyan-graph-0-bg . "#30d3f0")
- (cyan-graph-1-bg . "#6fefff")
+ (red-graph-0-bg . "#ef7969")
+ (red-graph-1-bg . "#ffaab4")
+ (green-graph-0-bg . "#4faa09")
+ (green-graph-1-bg . "#8fef00")
+ (yellow-graph-0-bg . "#ffcf00")
+ (yellow-graph-1-bg . "#f9ff00")
+ (blue-graph-0-bg . "#7090ff")
+ (blue-graph-1-bg . "#9fc6ff")
+ (magenta-graph-0-bg . "#e07fff")
+ (magenta-graph-1-bg . "#fad0ff")
+ (cyan-graph-0-bg . "#70d3f0")
+ (cyan-graph-1-bg . "#afefff")
;; the following are for cases where both the foreground and the
;; background need to have a similar hue and so must be combined
;; with themselves, even though the foregrounds can be paired with
@@ -545,6 +292,9 @@ cover the blue-cyan-magenta side of the spectrum."
;; while bg-tab-inactive should be combined with fg-dim, whereas
;; bg-tab-inactive-alt goes together with fg-main
;;
+ ;; bg-completion-* and bg-char-* variants are meant to be combined
+ ;; with fg-main
+ ;;
;; fg-escape-char-construct and fg-escape-char-backslash can
;; be combined bg-main, bg-dim, bg-alt
;;
@@ -564,7 +314,7 @@ cover the blue-cyan-magenta side of the spectrum."
;; all pairs are combinable with themselves
(bg-hl-line . "#f2eff3")
(bg-hl-line-intense . "#e0e0e0")
- (bg-hl-line-intense-accent . "#b9e1ef")
+ (bg-hl-line-intense-accent . "#cfe2ff")
(bg-hl-alt . "#fbeee0")
(bg-hl-alt-intense . "#e8dfd1")
(bg-paren-match . "#e0af82")
@@ -574,6 +324,13 @@ cover the blue-cyan-magenta side of the spectrum."
(bg-region-accent . "#afafef")
(bg-region-accent-subtle . "#efdfff")
+ (bg-completion . "#b7dbff")
+ (bg-completion-subtle . "#def3ff")
+
+ (bg-char-0 . "#7feaff")
+ (bg-char-1 . "#ffaaff")
+ (bg-char-2 . "#dff000")
+
(bg-tab-active . "#f6f6f6")
(bg-tab-inactive . "#b7b7b7")
(bg-tab-inactive-accent . "#a9b4f6")
@@ -653,10 +410,10 @@ symbol and the latter as a string.")
;; highlighted constructs; they must either be used as pairs based
;; on their name or each can be combined with {fg,bg}-{main,alt,dim}
;; always in accordance with their role as background or foreground
- (bg-special-cold . "#203448") (fg-special-cold . "#c6eaff")
- (bg-special-mild . "#00322e") (fg-special-mild . "#bfebe0")
- (bg-special-warm . "#382f27") (fg-special-warm . "#f8dec0")
- (bg-special-calm . "#392a48") (fg-special-calm . "#fbd6f4")
+ (bg-special-cold . "#203448") (bg-special-faint-cold . "#0e183a") (fg-special-cold . "#c6eaff")
+ (bg-special-mild . "#00322e") (bg-special-faint-mild . "#001f1a") (fg-special-mild . "#bfebe0")
+ (bg-special-warm . "#382f27") (bg-special-faint-warm . "#241613") (fg-special-warm . "#f8dec0")
+ (bg-special-calm . "#392a48") (bg-special-faint-calm . "#251232") (fg-special-calm . "#fbd6f4")
;; foregrounds that can be combined with bg-main, bg-dim, bg-alt
(red . "#ff8059")
(red-alt . "#ef8b50")
@@ -736,18 +493,18 @@ symbol and the latter as a string.")
;; those background values should only be used for graphs or similar
;; applications where colored blocks are expected to be positioned
;; next to each other
- (red-graph-0-bg . "#af0404")
- (red-graph-1-bg . "#801f2f")
- (green-graph-0-bg . "#24ba2f")
- (green-graph-1-bg . "#0f8f07")
- (yellow-graph-0-bg . "#ffd03e")
- (yellow-graph-1-bg . "#d7d800")
- (blue-graph-0-bg . "#406fff")
- (blue-graph-1-bg . "#2f50c8")
- (magenta-graph-0-bg . "#af7bee")
- (magenta-graph-1-bg . "#7f59cf")
- (cyan-graph-0-bg . "#47dcfa")
- (cyan-graph-1-bg . "#0bc0df")
+ (red-graph-0-bg . "#b52c2c")
+ (red-graph-1-bg . "#702020")
+ (green-graph-0-bg . "#4fd100")
+ (green-graph-1-bg . "#007800")
+ (yellow-graph-0-bg . "#f1e00a")
+ (yellow-graph-1-bg . "#b08600")
+ (blue-graph-0-bg . "#2fafef")
+ (blue-graph-1-bg . "#1f2f8f")
+ (magenta-graph-0-bg . "#bf94fe")
+ (magenta-graph-1-bg . "#5f509f")
+ (cyan-graph-0-bg . "#47dfea")
+ (cyan-graph-1-bg . "#00808f")
;; the following are for cases where both the foreground and the
;; background need to have a similar hue and so must be combined
;; with themselves, even though the foregrounds can be paired with
@@ -786,6 +543,9 @@ symbol and the latter as a string.")
;; while bg-tab-inactive should be combined with fg-dim, whereas
;; bg-tab-inactive-alt goes together with fg-main
;;
+ ;; bg-completion-* and bg-char-* variants are meant to be combined
+ ;; with fg-main
+ ;;
;; fg-escape-char-construct and fg-escape-char-backslash can
;; be combined bg-main, bg-dim, bg-alt
;;
@@ -805,16 +565,23 @@ symbol and the latter as a string.")
;; all pairs are combinable with themselves
(bg-hl-line . "#151823")
(bg-hl-line-intense . "#292929")
- (bg-hl-line-intense-accent . "#00353f")
+ (bg-hl-line-intense-accent . "#002a4f")
(bg-hl-alt . "#181732")
(bg-hl-alt-intense . "#282e46")
- (bg-paren-match . "#5f362f")
+ (bg-paren-match . "#6f3355")
(bg-paren-match-intense . "#7416b5")
(bg-paren-expression . "#221044")
(bg-region . "#3c3c3c")
(bg-region-accent . "#4f3d88")
(bg-region-accent-subtle . "#240f55")
+ (bg-completion . "#142f69")
+ (bg-completion-subtle . "#0e194b")
+
+ (bg-char-0 . "#0050af")
+ (bg-char-1 . "#7f1f7f")
+ (bg-char-2 . "#625a00")
+
(bg-tab-active . "#0e0e0e")
(bg-tab-inactive . "#424242")
(bg-tab-inactive-accent . "#35398f")
@@ -888,7 +655,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-green nil
"Subtle green background combined with a dimmed foreground.
@@ -896,7 +663,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-yellow nil
"Subtle yellow background combined with a dimmed foreground.
@@ -904,7 +671,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-blue nil
"Subtle blue background combined with a dimmed foreground.
@@ -912,7 +679,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-magenta nil
"Subtle magenta background combined with a dimmed foreground.
@@ -920,7 +687,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-cyan nil
"Subtle cyan background combined with a dimmed foreground.
@@ -928,7 +695,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-subtle-neutral nil
"Subtle gray background combined with a dimmed foreground.
@@ -936,7 +703,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-red nil
"Intense red background combined with the main foreground.
@@ -944,7 +711,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-green nil
"Intense green background combined with the main foreground.
@@ -952,7 +719,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-yellow nil
"Intense yellow background combined with the main foreground.
@@ -960,7 +727,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-blue nil
"Intense blue background combined with the main foreground.
@@ -968,7 +735,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-magenta nil
"Intense magenta background combined with the main foreground.
@@ -976,7 +743,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-cyan nil
"Intense cyan background combined with the main foreground.
@@ -984,7 +751,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-intense-neutral nil
"Intense gray background combined with the main foreground.
@@ -992,7 +759,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-red nil
"Combination of accented red background and foreground.
@@ -1000,7 +767,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-green nil
"Combination of accented green background and foreground.
@@ -1008,7 +775,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-yellow nil
"Combination of accented yellow background and foreground.
@@ -1016,7 +783,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-blue nil
"Combination of accented blue background and foreground.
@@ -1024,7 +791,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-magenta nil
"Combination of accented magenta background and foreground.
@@ -1032,7 +799,7 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-refine-cyan nil
"Combination of accented cyan background and foreground.
@@ -1040,91 +807,91 @@ This is used for general purpose highlighting, mostly in buffers
or for completion interfaces.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-red nil
"A red background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-green nil
"A green background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-yellow nil
"A yellow background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-blue nil
"A blue background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-magenta nil
"A magenta background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-active-cyan nil
"A cyan background meant for use on the mode line or similar.
This is combined with the mode lines primary foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-red nil
"A red background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-green nil
"A green background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-yellow nil
"A yellow background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-blue nil
"A blue background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-magenta nil
"A magenta background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fringe-cyan nil
"A cyan background meant for use on the fringe or similar.
This is combined with the main foreground value.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-red nil
"A nuanced red background.
@@ -1134,7 +901,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-green nil
"A nuanced green background.
@@ -1144,7 +911,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-yellow nil
"A nuanced yellow background.
@@ -1154,7 +921,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-blue nil
"A nuanced blue background.
@@ -1164,7 +931,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-magenta nil
"A nuanced magenta background.
@@ -1174,7 +941,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-nuanced-cyan nil
"A nuanced cyan background.
@@ -1184,7 +951,7 @@ headings, and any other surface that needs to retain the colors
on display.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-special-cold nil
"Combines the 'special cold' background and foreground values.
@@ -1193,7 +960,7 @@ suitable and where a combination of more saturated colors would
not be appropriate.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-special-mild nil
"Combines the 'special mild' background and foreground values.
@@ -1202,7 +969,7 @@ suitable and where a combination of more saturated colors would
not be appropriate.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-special-warm nil
"Combines the 'special warm' background and foreground values.
@@ -1211,7 +978,7 @@ suitable and where a combination of more saturated colors would
not be appropriate.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-special-calm nil
"Combines the 'special calm' background and foreground values.
@@ -1220,7 +987,7 @@ suitable and where a combination of more saturated colors would
not be appropriate.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-added nil
"Combines green colors for the 'added' state in diffs.
@@ -1228,7 +995,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-changed nil
"Combines yellow colors for the 'changed' state in diffs.
@@ -1236,7 +1003,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-removed nil
"Combines red colors for the 'removed' state in diffs.
@@ -1244,7 +1011,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-refine-added nil
"Combines green colors for word-wise 'added' state in diffs.
@@ -1252,7 +1019,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-refine-changed nil
"Combines yellow colors for word-wise 'changed' state in diffs.
@@ -1260,7 +1027,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-refine-removed nil
"Combines red colors for word-wise 'removed' state in diffs.
@@ -1268,7 +1035,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-focus-added nil
"Combines green colors for the focused 'added' state in diffs.
@@ -1276,7 +1043,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-focus-changed nil
"Combines yellow colors for the focused 'changed' state in.
@@ -1284,7 +1051,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-focus-removed nil
"Combines red colors for the focused 'removed' state in diffs.
@@ -1292,7 +1059,7 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-diff-heading nil
"Combines blue colors for the diff hunk heading.
@@ -1300,40 +1067,40 @@ The applied colors are contingent on the value assigned to
`modus-themes-diffs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-pseudo-header nil
"Generic style for some elements that function like headings.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-mark-alt nil
"Combines yellow colors for marking special lines.
This is intended for use in modes such as Dired, Ibuffer, Proced.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-mark-del nil
"Combines red colors for marking deletable lines.
This is intended for use in modes such as Dired, Ibuffer, Proced.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-mark-sel nil
"Combines green colors for marking lines.
This is intended for use in modes such as Dired, Ibuffer, Proced.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-mark-symbol nil
"Applies a blue color and other styles for mark indicators.
This is intended for use in modes such as Dired, Ibuffer, Proced.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-1 nil
"General purpose face for use in headings level 1.
@@ -1341,7 +1108,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-2 nil
"General purpose face for use in headings level 2.
@@ -1349,7 +1116,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-3 nil
"General purpose face for use in headings level 3.
@@ -1357,7 +1124,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-4 nil
"General purpose face for use in headings level 4.
@@ -1365,7 +1132,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-5 nil
"General purpose face for use in headings level 5.
@@ -1373,7 +1140,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-6 nil
"General purpose face for use in headings level 6.
@@ -1381,7 +1148,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-7 nil
"General purpose face for use in headings level 7.
@@ -1389,7 +1156,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-heading-8 nil
"General purpose face for use in headings level 8.
@@ -1397,7 +1164,7 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-headings' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-hl-line nil
"General purpose face for the current line.
@@ -1405,150 +1172,41 @@ The exact attributes assigned to this face are contingent on the
values assigned to the `modus-themes-hl-line' variable.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-bold nil
"Generic face for applying a conditional bold weight.
This behaves in accordance with `modus-themes-bold-constructs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-slant nil
"Generic face for applying a conditional slant (italics).
This behaves in accordance with `modus-themes-italic-constructs'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-variable-pitch nil
"Generic face for applying a conditional `variable-pitch'.
-This behaves in accordance with `modus-themes-mixed-fonts',
-`modus-themes-variable-pitch-headings' for all heading levels,
-and `modus-themes-variable-pitch-ui'.
+This behaves in accordance with `modus-themes-mixed-fonts' and/or
+`modus-themes-variable-pitch-ui'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-fixed-pitch nil
"Generic face for applying a conditional `fixed-pitch'.
This behaves in accordance with `modus-themes-mixed-fonts'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-ui-variable-pitch nil
"Face for `modus-themes-variable-pitch-ui'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-red-0 nil
- "Special subdued red face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-red-1 nil
- "Special prominent red face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-green-0 nil
- "Special subdued green face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-green-1 nil
- "Special prominent green face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-yellow-0 nil
- "Special subdued yellow face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-yellow-1 nil
- "Special prominent yellow face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-blue-0 nil
- "Special subdued blue face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-blue-1 nil
- "Special prominent blue face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-magenta-0 nil
- "Special subdued magenta face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-magenta-1 nil
- "Special prominent magenta face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-cyan-0 nil
- "Special subdued cyan face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
-
-(defface modus-themes-graph-cyan-1 nil
- "Special prominent cyan face for use in graphs.
-This is intended to be applied in contexts such as the Org agenda
-habit graph where faithfulness to the semantics of a color value
-is of paramount importance.
-
-The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-lang-note nil
"Generic face for linter or spell checker notes.
@@ -1556,7 +1214,7 @@ The exact attributes and color combinations are controlled by
`modus-themes-lang-checkers'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-lang-warning nil
"Generic face for linter or spell checker warnings.
@@ -1564,7 +1222,7 @@ The exact attributes and color combinations are controlled by
`modus-themes-lang-checkers'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-lang-error nil
"Generic face for linter or spell checker errors.
@@ -1572,7 +1230,7 @@ The exact attributes and color combinations are controlled by
`modus-themes-lang-checkers'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-reset-soft nil
"Generic face to set most face properties to nil.
@@ -1583,7 +1241,7 @@ text should not be underlined as well) yet still blend in. Also
see `modus-themes-reset-hard'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-reset-hard nil
"Generic face to set all face properties to nil.
@@ -1594,32 +1252,32 @@ text should not be underlined as well) and not blend in. Also
see `modus-themes-reset-soft'.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-key-binding nil
"Generic face for key bindings.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-search-success nil
"Generic face for successful search.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-search-success-modeline nil
"Generic mode line indicator for successful search.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-search-success-lazy nil
"Generic face for successful, lazily highlighted search.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
(defface modus-themes-prompt nil
"Generic face for command prompts.
The actual styling of the face is done by `modus-themes-faces'."
- :group 'modus-theme-faces)
+ :group 'modus-themes-faces)
;; "Grue" is "green" and "blue".
(defface modus-themes-grue nil
@@ -1682,11 +1340,81 @@ The actual styling of the face is done by `modus-themes-faces'."
The actual styling of the face is done by `modus-themes-faces'."
:group 'modus-themes-faces)
+(defface modus-themes-markup-code nil
+ "Face of inline code markup.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-markup-macro nil
+ "Face of macro markup.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
(defface modus-themes-markup-verbatim nil
"Face of verbatim markup.
The actual styling of the face is done by `modus-themes-faces'."
:group 'modus-themes-faces)
+(define-obsolete-face-alias
+ 'modus-themes-completion-standard-first-match
+ 'modus-themes-completion-selected
+ "2.2.0")
+
+(define-obsolete-face-alias
+ 'modus-themes-completion-standard-selected
+ 'modus-themes-completion-selected
+ "2.2.0")
+
+(define-obsolete-face-alias
+ 'modus-themes-completion-extra-selected
+ 'modus-themes-completion-selected
+ "2.2.0")
+
+(define-obsolete-face-alias
+ 'modus-themes-completion-key-binding
+ 'modus-themes-key-binding
+ "2.2.0")
+
+(defface modus-themes-completion-selected nil
+ "Face for current selection in completion UIs.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-completion-selected-popup nil
+ "Face for current selection in completion UI popups.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-completion-match-0 nil
+ "Face for completions matches 0.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-completion-match-1 nil
+ "Face for completions matches 1.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-completion-match-2 nil
+ "Face for completions matches 2.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-completion-match-3 nil
+ "Face for completions matches 3.
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-box-button nil
+ "Face for widget buttons (e.g. in the Custom UI).
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
+(defface modus-themes-box-button-pressed nil
+ "Face for pressed widget buttons (e.g. in the Custom UI).
+The actual styling of the face is done by `modus-themes-faces'."
+ :group 'modus-themes-faces)
+
;;; Customization variables
@@ -1698,7 +1426,7 @@ By default, customizing a theme-related user option through the
Custom interfaces or with `customize-set-variable' will not
reload the currently active Modus theme.
-Enable this behaviour by setting this variable to nil."
+Enable this behavior by setting this variable to nil."
:group 'modus-themes
:package-version '(modus-themes . "1.5.0")
:version "28.1"
@@ -1755,10 +1483,7 @@ For form, see `modus-themes-vivendi-colors'."
(put 'modus-themes-vivendi-color-overrides
'custom-options (copy-sequence colors)))
-(define-obsolete-variable-alias
- 'modus-themes-slanted-constructs
- 'modus-themes-italic-constructs
- "1.5.0")
+(defvaralias 'modus-themes-slanted-constructs 'modus-themes-italic-constructs)
(defcustom modus-themes-italic-constructs nil
"Use italic font forms in more code constructs."
@@ -1780,18 +1505,6 @@ For form, see `modus-themes-vivendi-colors'."
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Bold constructs"))
-(defcustom modus-themes-variable-pitch-headings nil
- "DEPRECATED: specify `variable-pitch' in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.0.0")
- :version "28.1"
- :type 'boolean
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default
- :link '(info-link "(modus-themes) Headings' typeface"))
-
-(make-obsolete 'modus-themes-variable-pitch-headings 'modus-themes-headings "2.0.0")
-
(defcustom modus-themes-variable-pitch-ui nil
"Use proportional fonts (variable-pitch) in UI elements.
This includes the mode line, header line, tab bar, and tab line."
@@ -1803,10 +1516,6 @@ This includes the mode line, header line, tab bar, and tab line."
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) UI typeface"))
-(define-obsolete-variable-alias
- 'modus-themes-no-mixed-fonts
- 'modus-themes-mixed-fonts "On 2021-10-02 for version 1.7.0")
-
(defcustom modus-themes-mixed-fonts nil
"Non-nil to enable inheritance from `fixed-pitch' in some faces.
@@ -1824,9 +1533,23 @@ Users may need to explicitly configure the font family of
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Mixed fonts"))
+(defcustom modus-themes-intense-mouseovers nil
+ "When non-nil use more intense style for mouse hover effects.
+
+This affects the generic `highlight' face which, strictly
+speaking, is not limited to mouse usage."
+ :group 'modus-themes
+ :package-version '(modus-themes . "2.3.0")
+ :version "29.1"
+ :type 'boolean
+ :set #'modus-themes--set-option
+ :initialize #'custom-initialize-default
+ :link '(info-link "(modus-themes) Mouse hover effects"))
+
(defconst modus-themes--headings-choice
'(set :tag "Properties" :greedy t
(const :tag "Background color" background)
+ (const :tag "Proportionately spaced font (variable-pitch)" variable-pitch)
(const :tag "Overline" overline)
(choice :tag "Font weight (must be supported by the typeface)"
(const :tag "Bold (default)" nil)
@@ -1840,7 +1563,11 @@ Users may need to explicitly configure the font family of
(const :tag "Semi-bold" semibold)
(const :tag "Extra-bold" extrabold)
(const :tag "Ultra-bold" ultrabold))
- (float :tag "Number (float) to adjust height by" :value 1.1)
+ (radio :tag "Height"
+ (float :tag "Floating point to adjust height by")
+ (cons :tag "Cons cell of `(height . FLOAT)'"
+ (const :tag "The `height' key (constant)" height)
+ (float :tag "Floating point")))
(choice :tag "Colors"
(const :tag "Subtle colors" nil)
(const :tag "Rainbow colors" rainbow)
@@ -1890,17 +1617,19 @@ proportionately spaced typeface).
The symbol of a weight attribute adjusts the font of the heading
accordingly, such as `light', `semibold', etc. Valid symbols are
-defined in the internal variable `modus-themes--heading-weights'.
-The absence of a weight means that bold will be used by virtue of
-inheriting the `bold' face (check the manual for tweaking bold
-and italic faces). For backward compatibility, the `no-bold'
-value is accepted, though users are encouraged to specify a
-`regular' weight instead.
+defined in the variable `modus-themes-weights'. The absence of a
+weight means that bold will be used by virtue of inheriting the
+`bold' face (check the manual for tweaking bold and italic
+faces). For backward compatibility, the `no-bold' value is
+accepted, though users are encouraged to specify a `regular'
+weight instead.
A number, expressed as a floating point (e.g. 1.5), adjusts the
height of the heading to that many times the base font size. The
default height is the same as 1.0, though it need not be
-explicitly stated.
+explicitly stated. Instead of a floating point, an acceptable
+value can be in the form of a cons cell like (height . FLOAT)
+or (height FLOAT), where FLOAT is the given number.
Combinations of any of those properties are expressed as a list,
like in these examples:
@@ -1908,6 +1637,8 @@ like in these examples:
(semibold)
(rainbow background)
(overline monochrome semibold 1.3)
+ (overline monochrome semibold (height 1.3)) ; same as above
+ (overline monochrome semibold (height . 1.3)) ; same as above
The order in which the properties are set is not significant.
@@ -1937,7 +1668,7 @@ For Org users, the extent of the heading depends on the variable
and `background' properties. Depending on the version of Org,
there may be others, such as `org-fontify-done-headline'."
:group 'modus-themes
- :package-version '(modus-themes . "2.0.0")
+ :package-version '(modus-themes . "2.3.0")
:version "29.1"
:type `(alist
:options ,(mapcar (lambda (el)
@@ -1971,18 +1702,24 @@ font size. Acceptable values come in the form of a list that can
include either or both of those properties:
- `variable-pitch' to use a proportionately spaced typeface;
+
- A number as a floating point (e.g. 1.5) to set the height of
the text to that many times the default font height. A float
of 1.0 or the symbol `no-scale' have the same effect of making
- the font to the same height as the rest of the buffer. When
+ the font the same height as the rest of the buffer. When
neither a number nor `no-scale' are present, the default is a
small increase in height (a value of 1.15).
+
+ Instead of a floating point, an acceptable value can be in the
+ form of a cons cell like (height . FLOAT) or (height FLOAT),
+ where FLOAT is the given number.
+
- The symbol of a weight attribute adjusts the font of the
heading accordingly, such as `light', `semibold', etc. Valid
- symbols are defined in the internal variable
- `modus-themes--heading-weights'. The absence of a weight means
- that bold will be used by virtue of inheriting the `bold'
- face (check the manual for tweaking bold and italic faces).
+ symbols are defined in the variable `modus-themes-weights'.
+ The absence of a weight means that bold will be used by virtue
+ of inheriting the `bold' face (check the manual for tweaking
+ bold and italic faces).
In case both a number and `no-scale' are in the list, the latter
takes precedence. If two numbers are specified, the first one is
@@ -2004,17 +1741,24 @@ that can include any of the following properties:
- `grayscale' to make weekdays use the main foreground color and
weekends a more subtle gray;
+
- `workaholic' to make weekdays and weekends look the same in
terms of color;
+
- `bold-today' to apply a bold typographic weight to the current
date;
+
- `bold-all' to render all date headings in a bold weight;
+
- `underline-today' applies an underline to the current date
while removing the background it has by default;
+
- A number as a floating point (e.g. 1.2) to set the height of
the text to that many times the default font height. The
default is the same as the base font height (the equivalent of
- 1.0).
+ 1.0). Instead of a floating point, an acceptable value can be
+ in the form of a cons cell like (height . FLOAT) or (height
+ FLOAT), where FLOAT is the given number.
For example:
@@ -2100,11 +1844,10 @@ value are passed as a symbol. Those are:
The difference between ready and clear states is attenuated by
painting both of them using shades of green. This option thus
highlights the alert and overdue states.
-- When `modus-themes-deuteranopia' is non-nil the habit graph
- uses a three-color style like the aforementioned
- `traffic-light' variant, except that shades of blue are applied
- instead of green. This is suitable for users with red-green
- color deficiency (deuteranopia).
+- When `modus-themes-deuteranopia' is non-nil the exact style of
+ the habit graph adapts to the needs of users with red-green
+ color deficiency by substituting every instance of green with
+ blue or cyan (depending on the specifics).
For example:
@@ -2112,7 +1855,7 @@ For example:
(habit . simplified)
(habit . traffic-light)"
:group 'modus-themes
- :package-version '(modus-themes . "2.0.0")
+ :package-version '(modus-themes . "2.3.0")
:version "29.1"
:type '(set
(cons :tag "Block header"
@@ -2133,10 +1876,14 @@ For example:
(const :tag "Semi-bold" semibold)
(const :tag "Extra-bold" extrabold)
(const :tag "Ultra-bold" ultrabold))
- (choice :tag "Scaling"
+ (radio :tag "Scaling"
(const :tag "Slight increase in height (default)" nil)
(const :tag "Do not scale" no-scale)
- (float :tag "Number (float) to adjust height by" :value 1.3))))
+ (radio :tag "Number (float) to adjust height by"
+ (float :tag "Just the number")
+ (cons :tag "Cons cell of `(height . FLOAT)'"
+ (const :tag "The `height' key (constant)" height)
+ (float :tag "Floating point"))))))
(cons :tag "Date header" :greedy t
(const header-date)
(set :tag "Header presentation" :greedy t
@@ -2144,8 +1891,12 @@ For example:
(const :tag "Do not differentiate weekdays from weekends" workaholic)
(const :tag "Make today bold" bold-today)
(const :tag "Make all dates bold" bold-all)
- (float :tag "Number (float) to adjust height by" :value 1.05)
- (const :tag "Make today underlined; remove the background" underline-today)))
+ (const :tag "Make today underlined; remove the background" underline-today)
+ (radio :tag "Number (float) to adjust height by"
+ (float :tag "Just the number")
+ (cons :tag "Cons cell of `(height . FLOAT)'"
+ (const :tag "The `height' key (constant)" height)
+ (float :tag "Floating point")))))
(cons :tag "Event entry" :greedy t
(const event)
(set :tag "Text presentation" :greedy t
@@ -2166,84 +1917,6 @@ For example:
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Org agenda"))
-(defcustom modus-themes-scale-headings nil
- "DEPRECATED: specify height in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.2.0")
- :version "28.1"
- :type 'boolean
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-headings 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-1 1.05
- "DEPRECATED: specify height in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.2.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-1 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-2 1.1
- "DEPRECATED: specify height in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.2.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-2 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-3 1.15
- "DEPRECATED: specify height in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.2.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-3 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-4 1.2
- "DEPRECATED: specify height in `modus-themes-headings'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.2.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-4 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-title 1.3
- "DEPRECATED: specify height in `modus-themes-headings'.
-Same principle for `modus-themes-org-agenda'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.5.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-title 'modus-themes-headings "2.0.0")
-
-(defcustom modus-themes-scale-small 0.9
- "DEPRECATED."
- :group 'modus-themes
- :package-version '(modus-themes . "1.6.0")
- :version "28.1"
- :type 'number
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default)
-
-(make-obsolete 'modus-themes-scale-small nil "2.0.0")
-
(defcustom modus-themes-fringes nil
"Define the visibility of fringes.
@@ -2323,25 +1996,32 @@ variables `flymake-fringe-indicator-position' and
:link '(info-link "(modus-themes) Language checkers"))
(defcustom modus-themes-org-blocks nil
- "Use a subtle gray or color-coded background for Org blocks.
+ "Set the overall style of Org code blocks, quotes, and the like.
-Nil (the default) means that the block has no distinct background
-of its own and uses the one that applies to the rest of the
-buffer.
+Nil (the default) means that the block has no background of its
+own: it uses the one that applies to the rest of the buffer. In
+this case, the delimiter lines have a gray color for their text,
+making them look exactly like all other Org properties.
Option `gray-background' applies a subtle gray background to the
block's contents. It also affects the begin and end lines of the
-block: their background extends to the edge of the window for
-Emacs version >= 27 where the ':extend' keyword is recognized by
-`set-face-attribute' (this is contingent on the variable
-`org-fontify-whole-block-delimiter-line').
+block as they get another shade of gray as their background,
+which differentiates them from the contents of the block. All
+background colors extend to the edge of the window, giving the
+area a rectangular, \"blocky\" presentation.
Option `tinted-background' uses a slightly colored background for
the contents of the block. The exact color will depend on the
programming language and is controlled by the variable
`org-src-block-faces' (refer to the theme's source code for the
current association list). For this to take effect, the Org
-buffer needs to be restarted with `org-mode-restart'.
+buffer needs to be restarted with `org-mode-restart'. In this
+scenario, it may be better to inhibit the extension of the
+delimiter lines' background to the edge of the window because Org
+does not provide a mechanism to update their colors depending on
+the contents of the block. Disable the extension of such
+backgrounds by setting `org-fontify-whole-block-delimiter-line'
+to nil.
Code blocks use their major mode's colors only when the variable
`org-src-fontify-natively' is non-nil. While quote/verse blocks
@@ -2353,7 +2033,7 @@ Older versions of the themes provided options `grayscale' (or
are aliases for `gray-background' and `tinted-background',
respectively."
:group 'modus-themes
- :package-version '(modus-themes . "1.4.0")
+ :package-version '(modus-themes . "2.1.0")
:version "28.1"
:type '(choice
(const :format "[%v] %t\n" :tag "No Org block background (default)" nil)
@@ -2406,6 +2086,17 @@ the `borderless' property is also set). For users on Emacs 29,
the `x-use-underline-position-properties' variable must also be
set to nil.
+The padding can also be expressed as a cons cell in the form
+of (padding . NATNUM) or (padding NATNUM) where the key is
+constant and NATNUM is the desired natural number.
+
+A floating point (e.g. 0.9) applies an adjusted height to the
+mode line's text as a multiple of the main font size. The
+default rate is 1.0 and does not need to be specified. Apart
+from a floating point, the height may also be expressed as a cons
+cell in the form of (height . FLOAT) or (height FLOAT) where the
+key is constant and the FLOAT is the desired number.
+
Combinations of any of those properties are expressed as a list,
like in these examples:
@@ -2413,6 +2104,13 @@ like in these examples:
(borderless 3d)
(moody accented borderless)
+Same as above, using the padding and height as an example (these
+all yield the same result):
+
+ (accented borderless 4 0.9)
+ (accented borderless (padding . 4) (height . 0.9))
+ (accented borderless (padding 4) (height 0.9))
+
The order in which the properties are set is not significant.
In user configuration files the form may look like this:
@@ -2444,8 +2142,8 @@ Furthermore, because Moody expects an underline and overline
instead of a box style, it is strongly advised to set
`x-underline-at-descent-line' to a non-nil value."
:group 'modus-themes
- :package-version '(modus-themes . "1.6.0")
- :version "28.1"
+ :package-version '(modus-themes . "2.3.0")
+ :version "29.1"
:type '(set :tag "Properties" :greedy t
(choice :tag "Overall style"
(const :tag "Rectangular Border" nil)
@@ -2453,23 +2151,20 @@ instead of a box style, it is strongly advised to set
(const :tag "No box effects (Moody-compatible)" moody))
(const :tag "Colored background" accented)
(const :tag "Without border color" borderless)
- (natnum :tag "With extra padding" :value 6))
+ (radio :tag "Padding"
+ (natnum :tag "Natural number (e.g. 4)")
+ (cons :tag "Cons cell of `(padding . NATNUM)'"
+ (const :tag "The `padding' key (constant)" padding)
+ (natnum :tag "Natural number")))
+ (radio :tag "Height"
+ (float :tag "Floating point (e.g. 0.9)")
+ (cons :tag "Cons cell of `(height . FLOAT)'"
+ (const :tag "The `height' key (constant)" height)
+ (float :tag "Floating point"))))
:set #'modus-themes--set-option
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Mode line"))
-(defcustom modus-themes-mode-line-padding 6
- "DEPRECATED: Set natural number in `modus-themes-mode-line'."
- :group 'modus-themes
- :package-version '(modus-themes . "1.7.0")
- :version "29.1"
- :type 'natnum
- :set #'modus-themes--set-option
- :initialize #'custom-initialize-default
- :link '(info-link "(modus-themes) Mode line"))
-
-(make-obsolete 'modus-themes-mode-line-padding 'modus-themes-mode-line "2.0.0")
-
(defcustom modus-themes-diffs nil
"Adjust the overall style of diffs.
@@ -2501,45 +2196,160 @@ interest of optimizing for such a use-case."
:link '(info-link "(modus-themes) Diffs"))
(defcustom modus-themes-completions nil
- "Control the style of the completion framework's interface.
-
-This is a special option that has different effects depending on
-the completion UI. The interfaces can be grouped in two
-categories, based on their default aesthetics: (i) those that
-only or mostly use foreground colors for their interaction model,
-and (ii) those that combine background and foreground values for
-some of their metaphors. The former category encompasses
-Icomplete, Ido, Selectrum, Vertico, as well as pattern matching
-styles like Orderless and Flx. The latter covers Helm and Ivy.
-
-A value of nil (the default) will simply respect the metaphors of
-each completion framework.
-
-Option `moderate' applies a combination of background and
-foreground that is fairly subtle. For Icomplete and friends this
-constitutes a departure from their default aesthetics, however
-the difference is small. While Helm, Ivy et al appear slightly
-different than their original looks, as they are toned down a
-bit.
-
-Option `opinionated' uses color combinations that refashion the
-completion UI. For the Icomplete camp this means that intense
-background and foreground combinations are used: in effect their
-looks emulate those of Helm, Ivy and company in their original
-style. Whereas the other group of packages will revert to an
-even more nuanced aesthetic with some additional changes to the
-choice of hues.
-
-To appreciate the scope of this customization option, you should
-spend some time with every one of the nil (default), `moderate',
-and `opinionated' possibilities."
+ "Control the style of completion user interfaces.
+
+This affects Company, Corfu, Flx, Helm, Icomplete/Fido, Ido, Ivy,
+Mct, Orderless, Selectrum, Vertico. The value is an alist that
+takes the form of a (key . properties) combination. Here is a
+sample, followed by a description of the particularities:
+
+ (setq modus-themes-completions
+ (quote ((matches . (extrabold background intense))
+ (selection . (semibold accented intense))
+ (popup . (accented)))))
+
+The `matches' key refers to the highlighted characters that
+correspond to the user's input. By default (nil or an empty
+list), they have a bold weight and a colored foreground. The
+list of properties may include any of the following symbols
+regardless of the order they may appear in:
+
+- `background' to add a background color;
+
+- `intense' to increase the overall coloration (also amplifies
+ the `background', if present);
+
+- `underline' to draw a line below the characters;
+
+- `italic' to use a slanted font (italic or oblique forms);
+
+- The symbol of a font weight attribute such as `light',
+ `semibold', et cetera. Valid symbols are defined in the
+ variable `modus-themes-weights'. The absence of a weight means
+ that bold will be used.
+
+The `selection' key applies to the current line or currently
+matched candidate, depending on the specifics of the User
+Interface. By default (nil or an empty list), it has a subtle
+gray background, a bold weight, and the base foreground value
+for the text. The list of properties it accepts is as
+follows (order is not significant):
+
+- `accented' to make the background colorful instead of gray;
+
+- `text-also' to apply extra color to the text of the selected
+ line;
+
+- `intense' to increase the overall coloration;
+
+- `underline' to draw a line below the characters;
+
+- `italic' to use a slanted font (italic or oblique forms);
+
+- The symbol of a font weight attribute such as `light',
+ `semibold', et cetera. Valid symbols are defined in the
+ variable `modus-themes-weights'. The absence of a weight means
+ that bold will be used.
+
+The `popup' key takes the same values as `selection'.
+
+Apart from specfying each key separately, a fallback list is
+accepted. This is only useful when the desired aesthetic is the
+same across all keys that are not explicitly referenced. For
+example, this:
+
+ (setq modus-themes-completions
+ (quote ((t . (extrabold intense)))))
+
+Is the same as:
+
+ (setq modus-themes-completions
+ (quote ((matches . (extrabold intense))
+ (selection . (extrabold intense))
+ (popup . (extrabold intense)))))
+
+In the case of the fallback, any property that does not apply to
+the corresponding key is simply ignored (`matches' does not have
+`accented' and `text-also', while `selection' and `popup' do not
+have `background').
+
+A concise expression of those associations can be written as
+follows, where the `car' is always the key and the `cdr' is the
+list of properties (whatever order they may appear in):
+
+ (setq modus-themes-completions
+ (quote ((matches extrabold background intense)
+ (selection semibold accented intense)
+ (popup accented))))
+
+Check the manual for tweaking `bold' and `italic' faces: Info
+node `(modus-themes) Configure bold and italic faces'.
+
+Also refer to the Orderless documentation for its intersection
+with Company (if you choose to use those in tandem)."
:group 'modus-themes
- :package-version '(modus-themes . "1.0.0")
- :version "28.1"
- :type '(choice
- (const :format "[%v] %t\n" :tag "Respect the framework's established aesthetic (default)" nil)
- (const :format "[%v] %t\n" :tag "Subtle backgrounds for various elements" moderate)
- (const :format "[%v] %t\n" :tag "Radical alternative to the framework's looks" opinionated))
+ :package-version '(modus-themes . "2.3.0")
+ :version "29.1"
+ :type `(set
+ (cons :tag "Matches"
+ (const matches)
+ (set :tag "Style of matches" :greedy t
+ (choice :tag "Font weight (must be supported by the typeface)"
+ (const :tag "Bold (default)" nil)
+ (const :tag "Thin" thin)
+ (const :tag "Ultra-light" ultralight)
+ (const :tag "Extra-light" extralight)
+ (const :tag "Light" light)
+ (const :tag "Semi-light" semilight)
+ (const :tag "Regular" regular)
+ (const :tag "Medium" medium)
+ (const :tag "Semi-bold" semibold)
+ (const :tag "Extra-bold" extrabold)
+ (const :tag "Ultra-bold" ultrabold))
+ (const :tag "With added background" background)
+ (const :tag "Increased coloration" intense)
+ (const :tag "Italic font (oblique or slanted forms)" italic)
+ (const :tag "Underline" underline)))
+ (cons :tag "Selection"
+ (const selection)
+ (set :tag "Style of selection" :greedy t
+ (choice :tag "Font weight (must be supported by the typeface)"
+ (const :tag "Bold (default)" nil)
+ (const :tag "Thin" thin)
+ (const :tag "Ultra-light" ultralight)
+ (const :tag "Extra-light" extralight)
+ (const :tag "Light" light)
+ (const :tag "Semi-light" semilight)
+ (const :tag "Regular" regular)
+ (const :tag "Medium" medium)
+ (const :tag "Semi-bold" semibold)
+ (const :tag "Extra-bold" extrabold)
+ (const :tag "Ultra-bold" ultrabold))
+ (const :tag "Apply color to the line's text" text-also)
+ (const :tag "With accented background" accented)
+ (const :tag "Increased coloration" intense)
+ (const :tag "Italic font (oblique or slanted forms)" italic)
+ (const :tag "Underline" underline)))
+ (cons :tag "Popup"
+ (const popup)
+ (set :tag "Style of completion pop-ups" :greedy t
+ (choice :tag "Font weight (must be supported by the typeface)"
+ (const :tag "Bold (default)" nil)
+ (const :tag "Thin" thin)
+ (const :tag "Ultra-light" ultralight)
+ (const :tag "Extra-light" extralight)
+ (const :tag "Light" light)
+ (const :tag "Semi-light" semilight)
+ (const :tag "Regular" regular)
+ (const :tag "Medium" medium)
+ (const :tag "Semi-bold" semibold)
+ (const :tag "Extra-bold" extrabold)
+ (const :tag "Ultra-bold" ultrabold))
+ (const :tag "Apply color to the line's text" text-also)
+ (const :tag "With accented background" accented)
+ (const :tag "Increased coloration" intense)
+ (const :tag "Italic font (oblique or slanted forms)" italic)
+ (const :tag "Underline" underline))))
:set #'modus-themes--set-option
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Completion UIs"))
@@ -2646,21 +2456,56 @@ results with underlines."
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Line numbers"))
-(defcustom modus-themes-intense-markup nil
- "Use more intense markup in Org, Markdown, and related.
-The default style for certain markup types like inline code and
-verbatim constructs in Org and related major modes is a subtle
-foreground color combined with a subtle background.
+(defcustom modus-themes-markup nil
+ "Style markup in Org, Markdown, and others.
-With a non-nil value (t), these constructs will use a more
-prominent background and foreground color combination instead."
+This affects constructs such as Org's =verbatim= and ~code~.
+
+The value is a list of properties, each designated by a symbol.
+The default (a nil value or an empty list) is a foreground
+color.
+
+The `italic' property applies a typographic slant (italics).
+
+The `bold' property applies a heavier typographic weight.
+
+The `background' property adds a background color. The
+background is a shade of gray, unless the `intense' property is
+also set.
+
+The `intense' property amplifies the existing coloration. When
+`background' is used, the background color is enhanced as well
+and becomes tinted instead of being gray.
+
+Combinations of any of those properties are expressed as a list,
+like in these examples:
+
+ (bold)
+ (bold italic)
+ (bold italic intense)
+ (bold italic intense background)
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+ (setq modus-themes-markup (quote (bold italic)))
+
+Also check the variables `org-hide-emphasis-markers',
+`org-hide-macro-markers'."
:group 'modus-themes
- :package-version '(modus-themes . "1.7.0")
+ :package-version '(modus-themes . "2.1.0")
:version "29.1"
- :type 'boolean
+ :type '(set :tag "Properties" :greedy t
+ (const :tag "Added background" background)
+ (const :tag "Intense colors" intense)
+ (const :tag "Bold weight" bold)
+ (const :tag "Italics (slanted text)" italic))
:set #'modus-themes--set-option
:initialize #'custom-initialize-default
- :link '(info-link "(modus-themes) Intense markup"))
+ :link '(info-link "(modus-themes) Markup"))
+
+(make-obsolete 'modus-themes-intense-markup 'modus-themes-markup "2.1.0")
(defcustom modus-themes-paren-match nil
"Control the style of matching parentheses or delimiters.
@@ -2862,11 +2707,6 @@ In user configuration files the form may look like this:
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Active region"))
-(define-obsolete-variable-alias
- 'modus-themes-success-deuteranopia
- 'modus-themes-deuteranopia
- "2.0.0")
-
(defcustom modus-themes-deuteranopia nil
"When non-nil use red/blue color-coding instead of red/green.
@@ -2895,23 +2735,32 @@ the spectrum."
:link '(info-link "(modus-themes) Deuteranopia style"))
(defcustom modus-themes-mail-citations nil
- "Control the color of citations in messages or email clients.
+ "Control the color of citations/quotes in messages or emails.
+
+By default (a nil value) citations are styled with contrasting
+hues to denote their depth. Colors are easy to tell apart
+because they complement each other, but they otherwise are not
+very prominent.
+
+Option `intense' is similar to the default in terms of using
+contrasting and complementary hues, but applies more saturated
+colors.
-Nil (the default) means to use a variety of contrasting hues to
-denote depth in nested citations. Colors are fairly easy to tell
-apart.
+Option `faint' maintains the same color-based distinction between
+citation levels though the colors it uses have subtle differences
+between them.
-Option `faint' maintains a color-based distinction between
-citation levels but the colors it applies have very subtle
-differences between them.
+Option `monochrome' turns all quotes into a shade of gray.
-Option `monochrome' turns all citations that would otherwise be
-colored into a uniform shade of shade of gray."
+Whatever the value assigned to this variable, citations in emails
+are controlled by typographic elements and/or indentation, which
+the themes do not touch."
:group 'modus-themes
- :package-version '(modus-themes . "1.4.0")
- :version "28.1"
+ :package-version '(modus-themes . "2.1.0")
+ :version "29.1"
:type '(choice
- (const :format "[%v] %t\n" :tag "Colorful mail citations with contrasting hues (default)" nil)
+ (const :format "[%v] %t\n" :tag "Colorful email citations with contrasting hues (default)" nil)
+ (const :format "[%v] %t\n" :tag "Like the default, but with more saturated colors" intense)
(const :format "[%v] %t\n" :tag "Like the default, but with less saturated colors" faint)
(const :format "[%v] %t\n" :tag "Deprecated alias of `faint'" desaturated)
(const :format "[%v] %t\n" :tag "Uniformly gray mail citations" monochrome))
@@ -2931,10 +2780,121 @@ as the Centaur tabs package."
:initialize #'custom-initialize-default
:link '(info-link "(modus-themes) Tab style"))
+(defcustom modus-themes-box-buttons nil
+ "Control the style of buttons in the Custom UI and related.
+
+The value is a list of properties, each designated by a symbol.
+The default (a nil value or an empty list) is a gray background
+combined with a pseudo three-dimensional effect.
+
+The `flat' property makes the button two dimensional.
+
+The `accented' property changes the background from gray to an
+accent color.
+
+The `faint' property reduces the overall coloration.
+
+The `variable-pitch' property applies a proportionately spaced
+typeface to the button's text.
+
+The `underline' property draws a line below the affected text and
+removes whatever box effect. This is optimal when Emacs runs
+inside a terminal emulator. If `flat' and `underline' are
+defined together, the latter takes precedence.
+
+The symbol of a weight attribute adjusts the font of the button
+accordingly, such as `light', `semibold', etc. Valid symbols are
+defined in the variable `modus-themes-weights'.
+
+A number, expressed as a floating point (e.g. 0.9), adjusts the
+height of the button's text to that many times the base font
+size. The default height is the same as 1.0, though it need not
+be explicitly stated. Instead of a floating point, an acceptable
+value can be in the form of a cons cell like (height . FLOAT)
+or (height FLOAT), where FLOAT is the given number.
+
+The `all-buttons' property extends the box button effect (or the
+aforementioned properties) to the faces of the generic widget
+library. By default, those do not look like the buttons of the
+Custom UI as they are ordinary text wrapped in square brackets.
+
+Combinations of any of those properties are expressed as a list,
+like in these examples:
+
+ (flat)
+ (variable-pitch flat)
+ (variable-pitch flat semibold 0.9)
+ (variable-pitch flat semibold (height 0.9)) ; same as above
+ (variable-pitch flat semibold (height . 0.9)) ; same as above
+
+The order in which the properties are set is not significant.
+
+In user configuration files the form may look like this:
+
+ (setq modus-themes-box-buttons (quote (variable-pitch flat 0.9)))"
+ :group 'modus-themes
+ :package-version '(modus-themes . "2.3.0")
+ :version "29.1"
+ :type '(set :tag "Properties" :greedy t
+ (const :tag "Two-dimensional button" flat)
+ (const :tag "Accented background instead of gray" accented)
+ (const :tag "Reduce overall coloration" faint)
+ (const :tag "Proportionately spaced font (variable-pitch)" variable-pitch)
+ (const :tag "Underline instead of a box effect" underline)
+ (const :tag "Apply box button style to generic widget faces" all-buttons)
+ (choice :tag "Font weight (must be supported by the typeface)"
+ (const :tag "Thin" thin)
+ (const :tag "Ultra-light" ultralight)
+ (const :tag "Extra-light" extralight)
+ (const :tag "Light" light)
+ (const :tag "Semi-light" semilight)
+ (const :tag "Regular (default)" nil)
+ (const :tag "Medium" medium)
+ (const :tag "Bold" bold)
+ (const :tag "Semi-bold" semibold)
+ (const :tag "Extra-bold" extrabold)
+ (const :tag "Ultra-bold" ultrabold))
+ (radio :tag "Height"
+ (float :tag "Floating point to adjust height by")
+ (cons :tag "Cons cell of `(height . FLOAT)'"
+ (const :tag "The `height' key (constant)" height)
+ (float :tag "Floating point"))))
+ :set #'modus-themes--set-option
+ :initialize #'custom-initialize-default
+ :link '(info-link "(modus-themes) Box buttons"))
+
;;; Internal functions
+(defun modus-themes--warn (option)
+ "Warn that OPTION has changed."
+ (prog1 nil
+ (display-warning
+ 'modus-themes
+ (format "`%s' has changed; please read the updated documentation" option)
+ :warning)))
+
+(defun modus-themes--list-or-warn (option)
+ "Return list or nil value of OPTION, else `modus-themes--warn'."
+ (let* ((value (symbol-value option)))
+ (if (or (null value) (listp value))
+ value
+ (modus-themes--warn option))))
+
+(defun modus-themes--property-lookup (properties alist-key list-pred default)
+ "Return value from property alist or list.
+Check PROPERTIES for an alist value that corresponds to
+ALIST-KEY. If no alist is present, search the PROPERTIES
+list given LIST-PRED, using DEFAULT as a fallback."
+ (if-let* ((val (or (alist-get alist-key properties)
+ (cl-loop for x in properties
+ if (funcall list-pred x) return x)
+ default))
+ ((listp val)))
+ (car val)
+ val))
+
(defun modus-themes--palette (theme)
"Return color palette for Modus theme THEME.
THEME is a symbol, either `modus-operandi' or `modus-vivendi'."
@@ -2973,8 +2933,12 @@ Those are stored in `modus-themes-faces' and
(custom-theme-set-variables ',name ,@modus-themes-custom-variables))))
(defun modus-themes--current-theme ()
- "Return current theme."
- (car custom-enabled-themes))
+ "Return current modus theme."
+ (car
+ (seq-filter
+ (lambda (theme)
+ (string-match-p "^modus" (symbol-name theme)))
+ custom-enabled-themes)))
;; Helper functions that are meant to ease the implementation of the
;; above customization variables.
@@ -2985,9 +2949,8 @@ Those are stored in `modus-themes-faces' and
(defun modus-themes--slant ()
"Conditional use of italics for slant attribute."
- (if modus-themes-italic-constructs
- (list 'italic)
- (list 'normal)))
+ (when modus-themes-italic-constructs
+ (list :inherit 'italic)))
(defun modus-themes--fixed-pitch ()
"Conditional application of `fixed-pitch' inheritance."
@@ -3016,14 +2979,41 @@ combines with the theme's primary background (white/black)."
(list :background (or altbg 'unspecified) :foreground altfg)
(list :background mainbg :foreground mainfg)))
-(defun modus-themes--markup (mainfg intensefg &optional mainbg intensebg)
+(defun modus-themes--markup (mainfg intensefg subtlebg intensebg)
"Conditional use of colors for markup in Org and others.
-MAINBG is the default background. MAINFG is the default
-foreground. INTENSEBG and INTENSEFG must be more colorful
-variants."
- (if modus-themes-intense-markup
- (list :background (or intensebg 'unspecified) :foreground intensefg)
- (list :background (or mainbg 'unspecified) :foreground mainfg)))
+MAINFG is the default foreground. SUBTLEBG is a gray background.
+INTENSEBG is a colorful background for use with the main
+foreground. INTENSEFG is an alternative to the default."
+ (let ((properties modus-themes-markup))
+ (list
+ :inherit
+ (cond
+ ((and (memq 'bold properties)
+ (memq 'italic properties))
+ (list 'bold-italic 'modus-themes-fixed-pitch))
+ ((memq 'italic properties)
+ (list 'italic 'modus-themes-fixed-pitch))
+ ((memq 'bold properties)
+ (list 'bold 'modus-themes-fixed-pitch))
+ (t 'modus-themes-fixed-pitch))
+ :background
+ (cond
+ ((and (memq 'background properties)
+ (memq 'intense properties))
+ intensebg)
+ ((memq 'background properties)
+ subtlebg)
+ (t
+ 'unspecified))
+ :foreground
+ (cond
+ ((and (memq 'background properties)
+ (memq 'intense properties))
+ mainfg)
+ ((memq 'intense properties)
+ intensefg)
+ (t
+ mainfg)))))
(defun modus-themes--lang-check (underline subtlefg intensefg intensefg-alt subtlebg intensebg faintfg)
"Conditional use of foreground colors for language checkers.
@@ -3033,45 +3023,36 @@ pattern and represent a value that is faint or vibrant
respectively. INTENSEFG-ALT is used when the intensity is high.
SUBTLEBG and INTENSEBG are color-coded background colors that
differ in overall intensity. FAINTFG is a nuanced color."
- (let ((modus-themes-lang-checkers
- (if (listp modus-themes-lang-checkers)
- modus-themes-lang-checkers
- (pcase modus-themes-lang-checkers
- ('colored-background '(background intense))
- ('intense-foreground '(intense))
- ('intense-foreground-straight-underline '(intense straight-underline))
- ('subtle-foreground '(text-also))
- ('subtle-foreground-straight-underline '(text-also straight-underline))
- ('straight-underline '(straight-underline))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-lang-checkers)))
(list :underline
(list :color
- (if (memq 'faint modus-themes-lang-checkers)
+ (if (memq 'faint properties)
faintfg underline)
:style
- (if (memq 'straight-underline modus-themes-lang-checkers)
+ (if (memq 'straight-underline properties)
'line 'wave))
:background
(cond
- ((and (memq 'background modus-themes-lang-checkers)
- (memq 'faint modus-themes-lang-checkers))
+ ((and (memq 'background properties)
+ (memq 'faint properties))
subtlebg)
- ((and (memq 'background modus-themes-lang-checkers)
- (memq 'intense modus-themes-lang-checkers))
+ ((and (memq 'background properties)
+ (memq 'intense properties))
intensebg)
- ((memq 'background modus-themes-lang-checkers)
+ ((memq 'background properties)
subtlebg)
('unspecified))
:foreground
(cond
- ((and (memq 'faint modus-themes-lang-checkers)
- (memq 'text-also modus-themes-lang-checkers))
+ ((and (memq 'faint properties)
+ (memq 'text-also properties))
faintfg)
- ((and (memq 'background modus-themes-lang-checkers)
- (memq 'intense modus-themes-lang-checkers))
+ ((and (memq 'background properties)
+ (memq 'intense properties))
intensefg-alt)
- ((memq 'intense modus-themes-lang-checkers)
+ ((memq 'intense properties)
intensefg)
- ((memq 'text-also modus-themes-lang-checkers)
+ ((memq 'text-also properties)
subtlefg)
('unspecified)))))
@@ -3090,19 +3071,7 @@ should be combinable with INTENSEBG-FG.
SUBTLEBGGRAY and INTENSEBGGRAY are background values. The former
can be combined with GRAYFG, while the latter only works with the
theme's fallback text color."
- (let ((properties
- (if (listp modus-themes-prompts)
- modus-themes-prompts
- ;; translation layer for legacy values
- (pcase modus-themes-prompts
- ;; `subtle' is the same as `subtle-accented', while `intense' is
- ;; equal to `intense-accented' for backward compatibility
- ('subtle '(background))
- ('subtle-accented '(background))
- ('subtle-gray '(background gray))
- ('intense '(background intense))
- ('intense-accented '(background intense))
- ('intense-gray '(background intense gray))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-prompts)))
(list :foreground
(cond
((and (memq 'gray properties)
@@ -3148,16 +3117,7 @@ NORMALBG should be the special palette color 'bg-paren-match' or
something similar. INTENSEBG must be easier to discern next to
other backgrounds, such as the special palette color
'bg-paren-match-intense'."
- (let ((properties
- (if (listp modus-themes-paren-match)
- modus-themes-paren-match
- ;; translation layer for legacy values
- (pcase modus-themes-paren-match
- ;; `subtle' is the same as `subtle-accented', while `intense' is
- ;; equal to `intense-accented' for backward compatibility
- ('intense-bold '(intense bold))
- ('subtle-bold '(bold))
- ('intense '(intense))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-paren-match)))
(list :inherit
(if (memq 'bold properties)
'bold
@@ -3175,18 +3135,7 @@ other backgrounds, such as the special palette color
"Apply foreground value to code syntax.
FG is the default. FAINT is typically the same color in its
desaturated version."
- (let ((properties
- (if (listp modus-themes-syntax)
- modus-themes-syntax
- ;; translation layer for legacy values
- (pcase modus-themes-syntax
- ('faint '(faint))
- ('faint-yellow-comments '(faint yellow-comments))
- ('green-strings '(green-strings))
- ('yellow-comments '(yellow-comments))
- ('yellow-comments-green-strings '(green-strings yellow-comments))
- ('alt-syntax '(alt-syntax))
- ('alt-syntax-yellow-comments '(alt-syntax yellow-comments))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-syntax)))
(list :foreground
(cond
((memq 'faint properties)
@@ -3198,18 +3147,7 @@ desaturated version."
FG is the default. FAINT is typically the same color in its
desaturated version. ALT is another hue while optional FAINT-ALT
is its subtle alternative."
- (let ((properties
- (if (listp modus-themes-syntax)
- modus-themes-syntax
- ;; translation layer for legacy values
- (pcase modus-themes-syntax
- ('faint '(faint))
- ('faint-yellow-comments '(faint yellow-comments))
- ('green-strings '(green-strings))
- ('yellow-comments '(yellow-comments))
- ('yellow-comments-green-strings '(green-strings yellow-comments))
- ('alt-syntax '(alt-syntax))
- ('alt-syntax-yellow-comments '(alt-syntax yellow-comments))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-syntax)))
(list :foreground
(cond
((and (memq 'alt-syntax properties)
@@ -3228,18 +3166,7 @@ desaturated version. GREEN is a color variant in that side of
the spectrum. ALT is another hue. Optional FAINT-GREEN is a
subtle alternative to GREEN. Optional FAINT-ALT is a subtle
alternative to ALT."
- (let ((properties
- (if (listp modus-themes-syntax)
- modus-themes-syntax
- ;; translation layer for legacy values
- (pcase modus-themes-syntax
- ('faint '(faint))
- ('faint-yellow-comments '(faint yellow-comments))
- ('green-strings '(green-strings))
- ('yellow-comments '(yellow-comments))
- ('yellow-comments-green-strings '(green-strings yellow-comments))
- ('alt-syntax '(alt-syntax))
- ('alt-syntax-yellow-comments '(alt-syntax yellow-comments))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-syntax)))
(list :foreground
(cond
((and (memq 'faint properties)
@@ -3261,18 +3188,7 @@ alternative to ALT."
FG is the default. YELLOW is a color variant of that name while
optional FAINT-YELLOW is its subtle variant. Optional FAINT is
an alternative to the default value."
- (let ((properties
- (if (listp modus-themes-syntax)
- modus-themes-syntax
- ;; translation layer for legacy values
- (pcase modus-themes-syntax
- ('faint '(faint))
- ('faint-yellow-comments '(faint yellow-comments))
- ('green-strings '(green-strings))
- ('yellow-comments '(yellow-comments))
- ('yellow-comments-green-strings '(green-strings yellow-comments))
- ('alt-syntax '(alt-syntax))
- ('alt-syntax-yellow-comments '(alt-syntax yellow-comments))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-syntax)))
(list :foreground
(cond
((and (memq 'faint properties)
@@ -3292,12 +3208,17 @@ an alternative to the default value."
"Get cdr of KEY in ALIST."
(cdr (assoc key alist)))
-(defvar modus-themes--heading-weights
+(define-obsolete-variable-alias
+ 'modus-themes--heading-weights
+ 'modus-themes-weights
+ "2.1.0")
+
+(defconst modus-themes-weights
'( thin ultralight extralight light semilight regular medium
semibold bold heavy extrabold ultrabold)
- "List of font weights used by `modus-themes--heading'.")
+ "List of font weights.")
-(defun modus-themes--heading-weight (list)
+(defun modus-themes--weight (list)
"Search for `modus-themes--heading' weight in LIST."
(catch 'found
(dolist (elt list)
@@ -3316,33 +3237,12 @@ that combines well with the background and foreground."
(let* ((key (modus-themes--key-cdr level modus-themes-headings))
(style (or key (modus-themes--key-cdr t modus-themes-headings)))
(style-listp (listp style))
- (properties
- (if style-listp
- style
- ;; translation layer for legacy values
- (pcase style
- ('highlight '(background))
- ('highlight-no-bold '(background no-bold))
- ('line '(overline))
- ('line-no-bold '(no-bold overline))
- ('no-bold '(no-bold))
- ('no-color '(monochrome))
- ('no-color-no-bold '(no-bold monochrome))
- ('rainbow '(rainbow))
- ('rainbow-highlight '(rainbow background))
- ('rainbow-highlight-no-bold '(no-bold rainbow background))
- ('rainbow-line '(rainbow overline))
- ('rainbow-no-bold '(no-bold rainbow))
- ('rainbow-line-no-bold '(rainbow overline no-bold))
- ('rainbow-section '(rainbow overline background))
- ('rainbow-section-no-bold '(no-bold rainbow background overline))
- ('section '(background overline))
- ('section-no-bold '(background overline no-bold)))))
+ (properties style)
(var (when (memq 'variable-pitch properties) 'variable-pitch))
(varbold (if var
(append (list 'bold) (list var))
'bold))
- (weight (when style-listp (modus-themes--heading-weight style))))
+ (weight (when style-listp (modus-themes--weight style))))
(list :inherit
(cond
;; `no-bold' is for backward compatibility because we cannot
@@ -3366,7 +3266,7 @@ that combines well with the background and foreground."
fg-alt)
(fg))
:height
- (seq-find #'floatp properties 'unspecified)
+ (modus-themes--property-lookup properties 'height #'floatp 'unspecified)
:weight
(or weight 'unspecified)
:overline
@@ -3378,7 +3278,7 @@ that combines well with the background and foreground."
"Control the style of the Org agenda structure.
FG is the foreground color to use."
(let* ((properties (modus-themes--key-cdr 'header-block modus-themes-org-agenda))
- (weight (modus-themes--heading-weight properties)))
+ (weight (modus-themes--weight properties)))
(list :inherit
(cond
((and weight (memq 'variable-pitch properties))
@@ -3391,7 +3291,7 @@ FG is the foreground color to use."
(or weight 'unspecified)
:height
(cond ((memq 'no-scale properties) 'unspecified)
- ((seq-find #'floatp properties 1.15)))
+ ((modus-themes--property-lookup properties 'height #'floatp 1.15)))
:foreground fg)))
(defun modus-themes--agenda-date (defaultfg grayscalefg &optional workaholicfg grayscaleworkaholicfg bg bold ul)
@@ -3426,7 +3326,7 @@ weight. Optional UL applies an underline."
(t
defaultfg))
:height
- (seq-find #'floatp properties 'unspecified)
+ (modus-themes--property-lookup properties 'height #'floatp 'unspecified)
:underline
(if (and ul (memq 'underline-today properties))
t
@@ -3479,18 +3379,28 @@ clearly distinguishes past, present, future tasks."
('rainbow (list :foreground rainbowfg))
(_ (list :foreground defaultfg))))
-(defun modus-themes--agenda-habit (default traffic simple &optional traffic-deuteran)
+(defun modus-themes--agenda-habit (default traffic simple &optional default-d traffic-d simple-d)
"Specify background values for `modus-themes-org-agenda' habits.
DEFAULT is the original foregrounc color. TRAFFIC is to be used
when the 'traffic-light' style is applied, while SIMPLE
-corresponds to the 'simplified style'. Optional TRAFFIC-DEUTERAN
-is an alternative to TRAFFIC, meant for deuteranopia."
- (if modus-themes-deuteranopia
- (list :background (or traffic-deuteran traffic))
- (pcase (modus-themes--key-cdr 'habit modus-themes-org-agenda)
- ('traffic-light (list :background traffic))
- ('simplified (list :background simple))
- (_ (list :background default)))))
+corresponds to the 'simplified style'.
+
+Optional DEFAULT-D, TRAFFIC-D, SIMPLE-D are alternatives to the
+main colors, meant for dopia when `modus-themes-deuteranopia' is
+non-nil."
+ (let ((habit (modus-themes--key-cdr 'habit modus-themes-org-agenda)))
+ (cond
+ ((and modus-themes-deuteranopia (null habit))
+ (list :background (or default-d default)))
+ ((and modus-themes-deuteranopia (eq habit 'traffic-light))
+ (list :background (or traffic-d traffic)))
+ ((and modus-themes-deuteranopia (eq habit 'simplified))
+ (list :background (or simple-d simple)))
+ (t
+ (pcase habit
+ ('traffic-light (list :background traffic))
+ ('simplified (list :background simple))
+ (_ (list :background default)))))))
(defun modus-themes--org-block (bgblk fgdefault &optional fgblk)
"Conditionally set the background of Org blocks.
@@ -3526,8 +3436,9 @@ set to `rainbow'."
('gray-background (list :background bg :foreground fg :extend t))
('grayscale (list :background bg :foreground fg :extend t))
('greyscale (list :background bg :foreground fg :extend t))
+ ('tinted-background (list :background bgaccent :foreground fgaccent :extend nil))
('rainbow (list :background bgaccent :foreground fgaccent :extend nil))
- (_ (list :background bg :foreground fg :extend nil))))
+ (_ (list :foreground fg :extend nil))))
(defun modus-themes--mode-line-attrs
(fg bg fg-alt bg-alt fg-accent bg-accent border border-3d &optional alt-style fg-distant)
@@ -3545,23 +3456,9 @@ line's box property.
Optional FG-DISTANT should be close to the main background
values. It is intended to be used as a distant-foreground
property."
- (let* ((properties
- (if (listp modus-themes-mode-line)
- modus-themes-mode-line
- ;; translation layer for legacy values
- (alist-get modus-themes-mode-line
- '((3d . (3d))
- (moody . (moody))
- (borderless . (borderless))
- (borderless-3d . (borderless 3d))
- (borderless-moody . (borderless moody))
- (accented . (accented))
- (accented-3d . (accented 3d))
- (accented-moody . (accented moody))
- (borderless-accented . (borderless accented))
- (borderless-accented-3d . (borderless accented 3d))
- (borderless-accented-moody . (borderless accented moody))))))
- (padding (seq-find #'natnump properties 1))
+ (let* ((properties (modus-themes--list-or-warn 'modus-themes-mode-line))
+ (padding (modus-themes--property-lookup properties 'padding #'natnump 1))
+ (height (modus-themes--property-lookup properties 'height #'floatp 'unspecified))
(padded (> padding 1))
(base (cond ((memq 'accented properties)
(cons fg-accent bg-accent))
@@ -3584,6 +3481,7 @@ property."
(border))))
(list :foreground (car base)
:background (cdr base)
+ :height height
:box
(cond ((memq 'moody properties)
'unspecified)
@@ -3622,7 +3520,17 @@ property."
fg-distant
'unspecified))))
-(defun modus-themes--diff (mainbg mainfg altbg altfg &optional deuteranbg deuteranfg bg-only-fg)
+;; Basically this is just for the keycast key indicator.
+(defun modus-themes--mode-line-padded-box (color)
+ "Set padding of mode line box attribute with given COLOR."
+ (list :box (list :color color
+ :line-width
+ (or (cl-loop
+ for x in modus-themes-mode-line
+ if (natnump x) return x)
+ 1))))
+
+(defun modus-themes--diff (mainbg mainfg altbg altfg &optional deubg deufg deualtbg deualtfg bg-only-fg)
"Color combinations for `modus-themes-diffs'.
MAINBG must be one of the dedicated backgrounds for diffs while
@@ -3632,13 +3540,20 @@ ALTBG needs to be a slightly accented background that is meant to
be combined with ALTFG. Both must be less intense than MAINBG
and MAINFG respectively.
-DEUTERANBG and DEUTERANFG must be combinations of colors that account
-for red-green color defficiency (deuteranopia).
+DEUBG and DEUFG must be combinations of colors that account for
+red-green color defficiency (deuteranopia). They are the
+equivalent of MAINBG and MAINFG.
-Optional BG-ONLY-FG applies ALTFG else leaves the foreground
-unspecified."
+DEUALTBG and DEUALTFG are the equivalent of ALTBG and ALTFG for
+deuteranopia.
+
+Optional non-nil BG-ONLY-FG applies ALTFG else leaves the
+foreground unspecified."
(if modus-themes-deuteranopia
- (list :background (or deuteranbg mainbg) :foreground (or deuteranfg mainfg))
+ (pcase modus-themes-diffs
+ ('desaturated (list :background (or deualtbg altbg) :foreground (or deualtfg altfg)))
+ ('bg-only (list :background (or deualtbg altbg) :foreground (if bg-only-fg (or deualtfg altfg) 'unspecified)))
+ (_ (list :background (or deubg mainbg) :foreground (or deufg mainfg))))
(pcase modus-themes-diffs
('desaturated (list :background altbg :foreground altfg))
('bg-only (list :background altbg :foreground (if bg-only-fg altfg 'unspecified)))
@@ -3650,39 +3565,93 @@ unspecified."
(list deuteran)
(list main)))
-(defun modus-themes--standard-completions (mainfg subtlebg intensebg intensefg)
- "Combinations for `modus-themes-completions'.
-
-MAINFG is an accented foreground value. SUBTLEBG is an accented
-background value that can be combined with MAINFG. INTENSEBG and
-INTENSEFG are accented colors that are designed to be used in
-tandem.
-
-These are intended for Icomplete, Ido, and related."
- (pcase modus-themes-completions
- ('opinionated (list :background intensebg :foreground intensefg))
- ('moderate (list :background subtlebg :foreground mainfg))
- (_ (list :foreground mainfg))))
-
-(defun modus-themes--extra-completions (subtleface intenseface altface &optional altfg bold)
- "Combinations for `modus-themes-completions'.
-
-SUBTLEFACE and INTENSEFACE are custom theme faces that combine a
-background and foreground value. The difference between the two
-is a matter of degree.
-
-ALTFACE is a combination of colors that represents a departure
-from the UI's default aesthetics. Optional ALTFG is meant to be
-used in tandem with it.
-
-Optional BOLD will apply a heavier weight to the text.
-
-These are intended for Helm, Ivy, etc."
- (pcase modus-themes-completions
- ('opinionated (list :inherit (list altface bold)
- :foreground (or altfg 'unspecified)))
- ('moderate (list :inherit (list subtleface bold)))
- (_ (list :inherit (list intenseface bold)))))
+(make-obsolete 'modus-themes--completion 'modus-themes--completion-line "2.3.0")
+(make-obsolete 'modus-themes--completion 'modus-themes--completion-match "2.3.0")
+
+(defun modus-themes--completion-line (key bg fg bgintense fgintense &optional bgaccent bgaccentintense)
+ "Styles for `modus-themes-completions'.
+KEY is the key of a cons cell. BG and FG are the main colors.
+BGINTENSE works with the main foreground. FGINTENSE works on its
+own. BGACCENT and BGACCENTINTENSE are colorful variants of the
+other backgrounds."
+ (let* ((var (modus-themes--list-or-warn 'modus-themes-completions))
+ (properties (or (alist-get key var) (alist-get t var)))
+ (popup (eq key 'popup))
+ (selection (eq key 'selection))
+ (line (or popup selection))
+ (text (memq 'text-also properties))
+ (accented (memq 'accented properties))
+ (intense (memq 'intense properties))
+ (italic (memq 'italic properties))
+ (weight (modus-themes--weight properties))
+ (bold (when (and weight (eq weight 'bold)) 'bold)))
+ (list
+ :inherit
+ (cond
+ ((and italic weight (not (eq weight 'bold)))
+ 'italic)
+ ((and weight (not (eq weight 'bold)))
+ 'unspecified)
+ (italic 'bold-italic)
+ ('bold))
+ :background
+ (cond
+ ((and accented intense line)
+ bgaccentintense)
+ ((and accented line)
+ bgaccent)
+ (intense bgintense)
+ (bg))
+ :foreground
+ (cond
+ ((and line text intense)
+ fgintense)
+ ((and line text)
+ fg)
+ ('unspecified))
+ :underline
+ (if (memq 'underline properties) t 'unspecified)
+ :weight
+ (if (and weight (null bold)) weight 'unspecified))))
+
+(defun modus-themes--completion-match (key bg fg bgintense fgintense)
+ "Styles for `modus-themes-completions'.
+KEY is the key of a cons cell. BG and FG are the main colors.
+BGINTENSE works with the main foreground. FGINTENSE works on its
+own."
+ (let* ((var (modus-themes--list-or-warn 'modus-themes-completions))
+ (properties (or (alist-get key var) (alist-get t var)))
+ (background (memq 'background properties))
+ (intense (memq 'intense properties))
+ (italic (memq 'italic properties))
+ (weight (modus-themes--weight properties))
+ (bold (when (and weight (eq weight 'bold)) 'bold)))
+ (list
+ :inherit
+ (cond
+ ((and italic weight (not (eq weight 'bold)))
+ 'italic)
+ ((and weight (not (eq weight 'bold)))
+ 'unspecified)
+ (italic 'bold-italic)
+ ('bold))
+ :background
+ (cond
+ ((and background intense)
+ bgintense)
+ (background bg)
+ ('unspecified))
+ :foreground
+ (cond
+ ((and background intense)
+ 'unspecified)
+ (background fg)
+ (intense fgintense)
+ (fg))
+ :underline
+ (if (memq 'underline properties) t 'unspecified)
+ :weight
+ (if (and weight (null bold)) weight 'unspecified))))
(defun modus-themes--link (fg fgfaint underline bg bgneutral)
"Conditional application of link styles.
@@ -3690,17 +3659,7 @@ FG is the link's default color for its text and underline
property. FGFAINT is a desaturated color for the text and
underline. UNDERLINE is a gray color only for the undeline. BG
is a background color and BGNEUTRAL is its fallback value."
- (let ((properties
- (if (listp modus-themes-links)
- modus-themes-links
- ;; translation layer for legacy values
- (pcase modus-themes-links
- ('faint '(faint))
- ('neutral-underline '(neutral-underline))
- ('faint-neutral-underline '(neutral-underline faint))
- ('no-underline '(no-underline))
- ('underline-only '(no-color))
- ('neutral-underline-only '(no-color neutral-underline))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-links)))
(list :inherit
(cond
((and (memq 'bold properties)
@@ -3738,17 +3697,7 @@ is a background color and BGNEUTRAL is its fallback value."
"Extend `modus-themes--link'.
FG is the main accented foreground. FGFAINT is also accented,
yet desaturated. Optional NEUTRALFG is a gray value."
- (let ((properties
- (if (listp modus-themes-links)
- modus-themes-links
- ;; translation layer for legacy values
- (pcase modus-themes-links
- ('faint '(faint))
- ('neutral-underline '(neutral-underline))
- ('faint-neutral-underline '(neutral-underline faint))
- ('no-underline '(no-underline))
- ('underline-only '(no-color))
- ('neutral-underline-only '(no-color neutral-underline))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-links)))
(list :foreground
(cond
((memq 'no-color properties)
@@ -3772,16 +3721,7 @@ is a subtle background value that can be combined with all colors
used to fontify text and code syntax. BGACCENT is a colored
background that combines well with FG. BGACCENTSUBTLE can be
combined with all colors used to fontify text."
- (let ((properties
- (if (listp modus-themes-region)
- modus-themes-region
- ;; translation layer for legacy values
- (pcase modus-themes-region
- ('bg-only '(bg-only))
- ('bg-only-no-extend '(bg-only no-extend))
- ('accent '(accented))
- ('accent-no-extend '(accented no-extend))
- ('no-extend '(no-extend))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-region)))
(list :background
(cond
((and (memq 'accented properties)
@@ -3817,17 +3757,7 @@ LINEACCENT are color values that can remain distinct against the
buffer's possible backgrounds: the former is neutral, the latter
is accented. LINENEUTRALINTENSE and LINEACCENTINTENSE are their
more prominent alternatives."
- (let ((properties
- (if (listp modus-themes-hl-line)
- modus-themes-hl-line
- ;; translation layer for legacy values
- (pcase modus-themes-hl-line
- ('intense-background '(intense))
- ('accented-background '(accented))
- ('underline-neutral '(underline))
- ('underline-accented '(underline accented))
- ('underline-only-neutral '(underline)) ; only underline styles have been removed
- ('underline-only-accented '(underline accented))))))
+ (let ((properties (modus-themes--list-or-warn 'modus-themes-hl-line)))
(list :background
(cond
((and (memq 'intense properties)
@@ -3855,13 +3785,14 @@ more prominent alternatives."
lineneutral)
('unspecified)))))
-(defun modus-themes--mail-cite (mainfg subtlefg)
+(defun modus-themes--mail-cite (mainfg intensefg subtlefg)
"Combinations for `modus-themes-mail-citations'.
MAINFG is an accented foreground value. SUBTLEFG is its
-desaturated counterpart."
+desaturated counterpart. INTENSEFG is a more saturated variant."
(pcase modus-themes-mail-citations
('monochrome (list :inherit 'shadow))
+ ('intense (list :foreground intensefg))
('faint (list :foreground subtlefg))
('desaturated (list :foreground subtlefg))
(_ (list :foreground mainfg))))
@@ -3890,10 +3821,123 @@ application of a variable-pitch font."
:foreground (or foreground 'unspecified)
:box (if box-p (list :line-width 2 :color background) 'unspecified))))
+(defun modus-themes--button (bg bgfaint bgaccent bgaccentfaint border &optional pressed-button-p)
+ "Apply `modus-themes-box-buttons' styles.
+
+BG is the main background. BGFAINT is its subtle alternative.
+BGACCENT is its accented variant and BGACCENTFAINT is the same
+but less intense. BORDER is the color around the box.
+
+When optional PRESSED-BUTTON-P is non-nil, the box uses the
+pressed button style, else the released button."
+ (let* ((properties modus-themes-box-buttons)
+ (weight (modus-themes--weight properties)))
+ (list :inherit
+ (cond
+ ((and (memq 'variable-pitch properties)
+ (eq weight 'bold))
+ (list 'bold 'variable-pitch))
+ ((memq 'variable-pitch properties)
+ 'variable-pitch)
+ ((eq weight 'bold)
+ 'bold)
+ ('unspecified))
+ :background
+ (cond
+ ((and (memq 'accented properties)
+ (memq 'faint properties)
+ bgaccentfaint))
+ ((memq 'faint properties)
+ bgfaint)
+ ((memq 'accented properties)
+ bgaccent)
+ (bg))
+ :box
+ (cond
+ ((memq 'underline properties)
+ 'unspecified)
+ ((memq 'flat properties)
+ (list :line-width -1 :color border))
+ ((list :line-width -1
+ :style (if pressed-button-p
+ 'pressed-button
+ 'released-button)
+ :color border)))
+ :weight
+ (cond
+ ((eq weight 'bold)
+ 'unspecified) ; we :inherit the `bold' face above
+ (weight weight)
+ ('unspecified))
+ :height
+ (modus-themes--property-lookup properties 'height #'floatp 'unspecified)
+ :underline
+ (if (memq 'underline properties)
+ t
+ 'unspecified))))
+
;;;; Utilities for DIY users
+;;;;; List colors (a respin of M-x list-colors-display)
+
+(defun modus-themes--list-colors-render (buffer palette)
+ "Render colors in BUFFER from PALETTE.
+Routine for `modus-themes-list-colors'."
+ (with-help-window buffer
+ (with-current-buffer standard-output
+ (erase-buffer)
+ ;; We need this to properly render the first line.
+ (insert " ")
+ (dolist (cell palette)
+ (let* ((name (car cell))
+ (color (cdr cell))
+ (fg (readable-foreground-color color))
+ (pad (make-string 5 ?\s)))
+ (let ((old-point (point)))
+ (insert (format "%s %s" color pad))
+ (put-text-property old-point (point) 'face `( :foreground ,color)))
+ (let ((old-point (point)))
+ (insert (format " %s %s %s\n" color pad name))
+ (put-text-property old-point (point)
+ 'face `( :background ,color
+ :foreground ,fg
+ :extend t)))
+ ;; We need this to properly render the last line.
+ (insert " "))))))
+
+(defvar modus-themes--list-colors-prompt-history '()
+ "Minibuffer history for `modus-themes--list-colors-prompt'.")
+
+(defun modus-themes--list-colors-prompt ()
+ "Prompt for Modus theme.
+Helper function for `modus-themes-list-colors'."
+ (let ((def (format "%s" (modus-themes--current-theme))))
+ (completing-read
+ (format "Use palette from theme [%s]: " def)
+ '(modus-operandi modus-vivendi) nil t nil
+ 'modus-themes--list-colors-prompt-history def)))
+
+(defun modus-themes-list-colors (theme)
+ "Preview palette of the Modus THEME of choice."
+ (interactive
+ (list (intern (modus-themes--list-colors-prompt))))
+ (let ((palette (pcase theme
+ ('modus-operandi modus-themes-operandi-colors)
+ ('modus-vivendi modus-themes-vivendi-colors)
+ (_ (user-error "`%s' is not a Modus theme" theme)))))
+ (modus-themes--list-colors-render
+ (format "*%s-list-colors*" theme)
+ palette)))
+
+(defun modus-themes-list-colors-current ()
+ "Call `modus-themes-list-colors' for the current Modus theme."
+ (interactive)
+ (modus-themes-list-colors (modus-themes--current-theme)))
+
+;;;;; Formula to measure relative luminance
+
;; This is the WCAG formula: https://www.w3.org/TR/WCAG20-TECHS/G18.html
(defun modus-themes-wcag-formula (hex)
"Get WCAG value of color value HEX.
@@ -3913,6 +3957,8 @@ C1 and C2 are color values written in hexadecimal RGB."
(+ (modus-themes-wcag-formula c2) 0.05))))
(max ct (/ ct))))
+;;;;; Retrieve colors from the themes
+
(defun modus-themes-current-palette ()
"Return current color palette."
(modus-themes--palette (modus-themes--current-theme)))
@@ -3977,30 +4023,6 @@ as when they are declared in the `:config' phase)."
(defvar modus-themes-after-load-theme-hook nil
"Hook that runs after the `modus-themes-toggle' routines.")
-;; The reason we use `load-theme' instead of `enable-theme' is that the
-;; former does a kind of "reset" on the face specs. So it plays nicely
-;; with `custom-set-faces', as well as defcustom user customizations,
-;; including the likes of `modus-themes-operandi-color-overrides'.
-;;
-;; Tests show that `enable-theme' does not re-read those variables, so
-;; it might appear to the unsuspecting user that the themes are somehow
-;; broken.
-;;
-;; This "reset", however, comes at the cost of being a bit slower than
-;; `enable-theme'. User who have a stable setup and seldom update their
-;; variables during a given Emacs session, are better off using
-;; something like this:
-;;
-;; (defun modus-themes-toggle-enabled ()
-;; "Toggle between `modus-operandi' and `modus-vivendi' themes."
-;; (interactive)
-;; (pcase (modus-themes--current-theme)
-;; ('modus-operandi (progn (enable-theme 'modus-vivendi)
-;; (disable-theme 'modus-operandi)))
-;; ('modus-vivendi (progn (enable-theme 'modus-operandi)
-;; (disable-theme 'modus-vivendi)))
-;; (_ (error "No Modus theme is loaded; evaluate `modus-themes-load-themes' first"))))
-
;;;###autoload
(defun modus-themes-load-operandi ()
"Load `modus-operandi' and disable `modus-vivendi'.
@@ -4113,7 +4135,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
((,class ,@(modus-themes--diff
bg-diff-focus-added fg-diff-focus-added
green-nuanced-bg fg-diff-added
- bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran))))
+ bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran
+ blue-nuanced-bg fg-diff-added-deuteran))))
`(modus-themes-diff-changed
((,class ,@(modus-themes--diff
bg-diff-focus-changed fg-diff-focus-changed
@@ -4126,7 +4149,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
((,class ,@(modus-themes--diff
bg-diff-refine-added fg-diff-refine-added
bg-diff-focus-added fg-diff-focus-added
- bg-diff-refine-added-deuteran fg-diff-refine-added-deuteran))))
+ bg-diff-refine-added-deuteran fg-diff-refine-added-deuteran
+ bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran))))
`(modus-themes-diff-refine-changed
((,class ,@(modus-themes--diff
bg-diff-refine-changed fg-diff-refine-changed
@@ -4139,7 +4163,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
((,class ,@(modus-themes--diff
bg-diff-focus-added fg-diff-focus-added
bg-diff-added fg-diff-added
- bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran))))
+ bg-diff-focus-added-deuteran fg-diff-focus-added-deuteran
+ bg-diff-added-deuteran fg-diff-added-deuteran))))
`(modus-themes-diff-focus-changed
((,class ,@(modus-themes--diff
bg-diff-focus-changed fg-diff-focus-changed
@@ -4153,6 +4178,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
bg-diff-heading fg-diff-heading
cyan-nuanced-bg cyan-nuanced-fg
bg-header fg-main
+ bg-header fg-main
t))))
;;;;; deuteranopia-specific
`(modus-themes-grue ((,class :foreground ,@(modus-themes--deuteran blue green))))
@@ -4215,19 +4241,6 @@ by virtue of calling either of `modus-themes-load-operandi' and
((,class ,@(modus-themes--heading
8 magenta-nuanced-fg magenta
bg-alt bg-alt bg-region))))
-;;;;; graph-specific faces
- `(modus-themes-graph-red-0 ((,class :background ,red-graph-0-bg)))
- `(modus-themes-graph-red-1 ((,class :background ,red-graph-1-bg)))
- `(modus-themes-graph-green-0 ((,class :background ,green-graph-0-bg)))
- `(modus-themes-graph-green-1 ((,class :background ,green-graph-1-bg)))
- `(modus-themes-graph-yellow-0 ((,class :background ,yellow-graph-0-bg)))
- `(modus-themes-graph-yellow-1 ((,class :background ,yellow-graph-1-bg)))
- `(modus-themes-graph-blue-0 ((,class :background ,blue-graph-0-bg)))
- `(modus-themes-graph-blue-1 ((,class :background ,blue-graph-1-bg)))
- `(modus-themes-graph-magenta-0 ((,class :background ,magenta-graph-0-bg)))
- `(modus-themes-graph-magenta-1 ((,class :background ,magenta-graph-1-bg)))
- `(modus-themes-graph-cyan-0 ((,class :background ,cyan-graph-0-bg)))
- `(modus-themes-graph-cyan-1 ((,class :background ,cyan-graph-1-bg)))
;;;;; language checkers
`(modus-themes-lang-error ((,class ,@(modus-themes--lang-check
fg-lang-underline-error fg-lang-error
@@ -4241,21 +4254,78 @@ by virtue of calling either of `modus-themes-load-operandi' and
;;;;; links
`(modus-themes-link-broken ((,class :inherit button ,@(modus-themes--link-color red red-faint))))
`(modus-themes-link-symlink ((,class :inherit button ,@(modus-themes--link-color cyan cyan-faint))))
+;;;;; markup
+ `(modus-themes-markup-code
+ ((,class ,@(modus-themes--markup cyan-alt-other cyan-intense bg-alt
+ bg-special-faint-mild))))
+ `(modus-themes-markup-macro
+ ((,class ,@(modus-themes--markup magenta-alt-other purple-intense bg-alt
+ bg-special-faint-cold))))
+ `(modus-themes-markup-verbatim
+ ((,class ,@(modus-themes--markup magenta-alt magenta-intense bg-alt
+ bg-special-faint-calm))))
+;;;;; search
+ `(modus-themes-search-success ((,class :inherit ,@(modus-themes--deuteran
+ 'modus-themes-intense-blue
+ 'modus-themes-intense-green))))
+ `(modus-themes-search-success-lazy ((,class :inherit ,@(modus-themes--deuteran
+ 'modus-themes-special-mild
+ 'modus-themes-refine-cyan))))
+ `(modus-themes-search-success-modeline ((,class :foreground ,@(modus-themes--deuteran
+ blue-active
+ green-active))))
;;;;; tabs
`(modus-themes-tab-active ((,class ,@(modus-themes--tab bg-tab-active nil nil nil t t))))
`(modus-themes-tab-backdrop ((,class ,@(modus-themes--tab bg-active bg-active-accent nil nil nil nil t))))
`(modus-themes-tab-inactive ((,class ,@(modus-themes--tab bg-tab-inactive bg-tab-inactive-accent fg-dim nil t))))
-;;;;; other custom faces
+;;;;; completion frameworks
+ `(modus-themes-completion-match-0
+ ((,class ,@(modus-themes--completion-match
+ 'matches bg-special-faint-calm magenta-alt
+ magenta-subtle-bg magenta-intense))))
+ `(modus-themes-completion-match-1
+ ((,class ,@(modus-themes--completion-match
+ 'matches bg-special-faint-cold cyan
+ cyan-subtle-bg cyan-intense))))
+ `(modus-themes-completion-match-2
+ ((,class ,@(modus-themes--completion-match
+ 'matches bg-special-faint-mild green
+ green-subtle-bg green-intense))))
+ `(modus-themes-completion-match-3
+ ((,class ,@(modus-themes--completion-match
+ 'matches bg-special-faint-warm yellow
+ yellow-subtle-bg orange-intense))))
+ `(modus-themes-completion-selected
+ ((,class ,@(modus-themes--completion-line
+ 'selection bg-inactive blue-alt
+ bg-active blue-active
+ bg-completion-subtle bg-completion))))
+ `(modus-themes-completion-selected-popup
+ ((,class ,@(modus-themes--completion-line
+ 'popup bg-active blue-alt
+ bg-region blue-active
+ cyan-subtle-bg cyan-refine-bg))))
+;;;;; buttons
+ `(modus-themes-box-button
+ ((,class ,@(modus-themes--button bg-active bg-main bg-active-accent
+ bg-special-cold bg-region))))
+ `(modus-themes-box-button-pressed
+ ((,class ,@(modus-themes--button bg-active bg-main bg-active-accent
+ bg-special-cold bg-region t))))
+;;;;; typography
`(modus-themes-bold ((,class ,@(modus-themes--bold-weight))))
+ `(modus-themes-fixed-pitch ((,class ,@(modus-themes--fixed-pitch))))
+ `(modus-themes-slant ((,class ,@(modus-themes--slant))))
+ `(modus-themes-ui-variable-pitch ((,class ,@(modus-themes--variable-pitch-ui))))
+;;;;; other custom faces
`(modus-themes-hl-line ((,class ,@(modus-themes--hl-line
bg-hl-line bg-hl-line-intense
bg-hl-line-intense-accent blue-nuanced-bg
bg-region blue-intense-bg
- fg-alt cyan-intense)
+ fg-alt blue-intense)
:extend t)))
- `(modus-themes-key-binding ((,class ,@(if (facep 'help-key-binding) ; check emacs28 face
- (list :inherit 'help-key-binding)
- (list :inherit 'bold :foreground blue-alt-other)))))
+ `(modus-themes-key-binding ((,class :inherit (bold modus-themes-fixed-pitch)
+ :foreground ,blue-alt-other)))
`(modus-themes-prompt ((,class ,@(modus-themes--prompt
cyan-alt-other blue-alt-other fg-alt
cyan-nuanced-bg blue-refine-bg fg-main
@@ -4264,21 +4334,6 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(modus-themes-reset-soft ((,class :background ,bg-main :foreground ,fg-main
:weight normal :slant normal :strike-through nil
:box nil :underline nil :overline nil :extend nil)))
- `(modus-themes-search-success ((,class :inherit ,@(modus-themes--deuteran
- 'modus-themes-intense-blue
- 'modus-themes-intense-green))))
- `(modus-themes-search-success-lazy ((,class :inherit ,@(modus-themes--deuteran
- 'modus-themes-special-mild
- 'modus-themes-refine-cyan))))
- `(modus-themes-search-success-modeline ((,class :foreground ,@(modus-themes--deuteran
- blue-active
- green-active))))
- `(modus-themes-slant ((,class :inherit italic :slant ,@(modus-themes--slant))))
- `(modus-themes-ui-variable-pitch ((,class ,@(modus-themes--variable-pitch-ui))))
- `(modus-themes-fixed-pitch ((,class ,@(modus-themes--fixed-pitch))))
- `(modus-themes-markup-verbatim ((,class :inherit modus-themes-fixed-pitch
- ,@(modus-themes--markup fg-special-calm magenta-alt
- bg-alt magenta-nuanced-bg))))
;;;; standard faces
;;;;; absolute essentials
`(default ((,class :background ,bg-main :foreground ,fg-main)))
@@ -4289,33 +4344,38 @@ by virtue of calling either of `modus-themes-load-operandi' and
;;;;; basic and/or ungrouped styles
`(bold ((,class :weight bold)))
`(bold-italic ((,class :inherit (bold italic))))
+ `(underline ((,class :underline ,fg-alt)))
`(buffer-menu-buffer ((,class :inherit bold)))
+ `(child-frame-border ((,class :background ,fg-window-divider-inner)))
`(comint-highlight-input ((,class :inherit bold)))
`(comint-highlight-prompt ((,class :inherit modus-themes-prompt)))
`(confusingly-reordered ((,class :inherit modus-themes-lang-error)))
+ `(elisp-shorthand-font-lock-face ((,class :inherit font-lock-variable-name-face)))
`(error ((,class :inherit bold :foreground ,red)))
`(escape-glyph ((,class :foreground ,fg-escape-char-construct)))
- `(file-name-shadow ((,class :inherit (shadow italic))))
+ `(file-name-shadow ((,class :inherit shadow)))
`(header-line ((,class :inherit modus-themes-ui-variable-pitch
:background ,bg-header :foreground ,fg-header)))
- `(header-line-highlight ((,class :inherit modus-themes-active-blue)))
+ `(header-line-highlight ((,class :inherit highlight)))
`(help-argument-name ((,class :inherit modus-themes-slant :foreground ,cyan)))
- `(help-key-binding ((,class :box (:line-width (-1 . -1) :color ,bg-active) ; NOTE: box syntax is for Emacs28
- :background ,bg-alt)))
+ `(help-key-binding ((,class :inherit modus-themes-key-binding)))
`(homoglyph ((,class :foreground ,red-alt-faint)))
`(ibuffer-locked-buffer ((,class :foreground ,yellow-alt-other-faint)))
`(italic ((,class :slant italic)))
`(nobreak-hyphen ((,class :foreground ,fg-escape-char-construct)))
`(nobreak-space ((,class :foreground ,fg-escape-char-construct :underline t)))
+ `(menu ((,class :inverse-video unspecified :inherit modus-themes-intense-neutral)))
`(minibuffer-prompt ((,class :inherit modus-themes-prompt)))
`(mm-command-output ((,class :foreground ,red-alt-other)))
`(mm-uu-extract ((,class :background ,bg-dim :foreground ,fg-special-mild)))
`(next-error ((,class :inherit modus-themes-subtle-red :extend t)))
- `(rectangle-preview ((,class :inherit modus-themes-special-mild)))
+ `(pgtk-im-0 ((,class :inherit modus-themes-fringe-blue :underline t)))
+ `(rectangle-preview ((,class :background ,bg-special-faint-warm :foreground ,fg-special-warm)))
`(region ((,class ,@(modus-themes--region bg-region fg-main
bg-hl-alt-intense bg-region-accent
bg-region-accent-subtle))))
`(secondary-selection ((,class :inherit modus-themes-special-cold)))
+ `(separator-line ((,class :underline ,bg-region)))
`(shadow ((,class :foreground ,fg-alt)))
`(success ((,class :inherit (bold modus-themes-grue))))
`(trailing-whitespace ((,class :background ,red-intense-bg)))
@@ -4329,10 +4389,14 @@ by virtue of calling either of `modus-themes-load-operandi' and
,@(modus-themes--link-color
magenta-alt-other magenta-alt-other-faint fg-alt))))
`(tooltip ((,class :background ,bg-special-cold :foreground ,fg-main)))
- `(widget-button ((,class :inherit bold :foreground ,blue-alt)))
- `(widget-button-pressed ((,class :inherit widget-button :foreground ,magenta)))
+ `(widget-button ((,class ,@(if (memq 'all-buttons modus-themes-box-buttons)
+ (list :inherit 'modus-themes-box-button)
+ (list :inherit 'bold :foreground blue-alt)))))
+ `(widget-button-pressed ((,class ,@(if (memq 'all-buttons modus-themes-box-buttons)
+ (list :inherit 'modus-themes-box-button-pressed)
+ (list :inherit 'bold :foreground magenta-alt)))))
`(widget-documentation ((,class :foreground ,green)))
- `(widget-field ((,class :background ,bg-alt :foreground ,fg-dim)))
+ `(widget-field ((,class :background ,bg-alt :foreground ,fg-main :extend nil)))
`(widget-inactive ((,class :inherit shadow :background ,bg-dim)))
`(widget-single-line-field ((,class :inherit widget-field)))
;;;;; alert
@@ -4342,41 +4406,47 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(alert-trivial-face ((,class :foreground ,fg-special-calm)))
`(alert-urgent-face ((,class :inherit bold :foreground ,red-intense)))
;;;;; all-the-icons
- `(all-the-icons-blue ((,class :foreground ,blue)))
+ `(all-the-icons-blue ((,class :foreground ,blue-alt-other)))
`(all-the-icons-blue-alt ((,class :foreground ,blue-alt)))
- `(all-the-icons-cyan ((,class :foreground ,cyan)))
+ `(all-the-icons-cyan ((,class :foreground ,cyan-intense)))
`(all-the-icons-cyan-alt ((,class :foreground ,cyan-alt)))
- `(all-the-icons-dblue ((,class :foreground ,blue-alt-other)))
- `(all-the-icons-dcyan ((,class :foreground ,cyan-alt-other)))
- `(all-the-icons-dgreen ((,class :foreground ,green-alt-other)))
- `(all-the-icons-dired-dir-face ((,class :foreground ,blue)))
- `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-other)))
- `(all-the-icons-dorange ((,class :foreground ,red-alt-other)))
- `(all-the-icons-dpink ((,class :foreground ,magenta)))
- `(all-the-icons-dpurple ((,class :foreground ,magenta-alt)))
- `(all-the-icons-dred ((,class :foreground ,red)))
- `(all-the-icons-dsilver ((,class :foreground ,fg-special-cold)))
- `(all-the-icons-dyellow ((,class :foreground ,yellow)))
- `(all-the-icons-green ((,class :foreground ,green)))
- `(all-the-icons-lblue ((,class :foreground ,blue-refine-fg)))
- `(all-the-icons-lcyan ((,class :foreground ,cyan-refine-fg)))
- `(all-the-icons-lgreen ((,class :foreground ,green-refine-fg)))
- `(all-the-icons-lmaroon ((,class :foreground ,magenta-refine-fg)))
- `(all-the-icons-lorange ((,class :foreground ,red-refine-fg)))
- `(all-the-icons-lpink ((,class :foreground ,magenta-refine-fg)))
- `(all-the-icons-lpurple ((,class :foreground ,magenta-refine-fg)))
- `(all-the-icons-lred ((,class :foreground ,red-refine-fg)))
- `(all-the-icons-lsilver ((,class :foreground ,fg-special-cold)))
- `(all-the-icons-lyellow ((,class :foreground ,yellow-refine-fg)))
- `(all-the-icons-maroon ((,class :foreground ,magenta)))
- `(all-the-icons-orange ((,class :foreground ,red-alt)))
- `(all-the-icons-pink ((,class :foreground ,magenta)))
- `(all-the-icons-purple ((,class :foreground ,magenta-alt)))
- `(all-the-icons-purple-alt ((,class :foreground ,magenta-alt-other)))
- `(all-the-icons-red ((,class :foreground ,red)))
- `(all-the-icons-red-alt ((,class :foreground ,red-alt)))
+ `(all-the-icons-dblue ((,class :foreground ,blue-faint)))
+ `(all-the-icons-dcyan ((,class :foreground ,cyan-faint)))
+ `(all-the-icons-dgreen ((,class :foreground ,green)))
+ `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-faint)))
+ `(all-the-icons-dorange ((,class :foreground ,red-alt-faint)))
+ `(all-the-icons-dpink ((,class :foreground ,magenta-faint)))
+ `(all-the-icons-dpurple ((,class :foreground ,magenta-alt-other-faint)))
+ `(all-the-icons-dred ((,class :foreground ,red-faint)))
+ `(all-the-icons-dsilver ((,class :foreground ,cyan-alt-faint)))
+ `(all-the-icons-dyellow ((,class :foreground ,yellow-alt-faint)))
+ `(all-the-icons-green ((,class :foreground ,green-intense)))
+ `(all-the-icons-lblue ((,class :foreground ,blue-alt-other)))
+ `(all-the-icons-lcyan ((,class :foreground ,cyan)))
+ `(all-the-icons-lgreen ((,class :foreground ,green-alt-other)))
+ `(all-the-icons-lmaroon ((,class :foreground ,magenta-alt)))
+ `(all-the-icons-lorange ((,class :foreground ,red-alt)))
+ `(all-the-icons-lpink ((,class :foreground ,magenta)))
+ `(all-the-icons-lpurple ((,class :foreground ,magenta-faint)))
+ `(all-the-icons-lred ((,class :foreground ,red)))
+ `(all-the-icons-lsilver ((,class :foreground ,fg-docstring)))
+ `(all-the-icons-lyellow ((,class :foreground ,yellow-alt)))
+ `(all-the-icons-maroon ((,class :foreground ,magenta-intense)))
+ `(all-the-icons-orange ((,class :foreground ,orange-intense)))
+ `(all-the-icons-pink ((,class :foreground ,fg-special-calm)))
+ `(all-the-icons-purple ((,class :foreground ,magenta-alt-other)))
+ `(all-the-icons-purple-alt ((,class :foreground ,purple-intense)))
+ `(all-the-icons-red ((,class :foreground ,red-intense)))
+ `(all-the-icons-red-alt ((,class :foreground ,red-alt-other)))
`(all-the-icons-silver ((,class :foreground ,fg-special-cold)))
`(all-the-icons-yellow ((,class :foreground ,yellow)))
+;;;;; all-the-icons-dired
+ `(all-the-icons-dired-dir-face ((,class :foreground ,cyan-faint)))
+;;;;; all-the-icons-ibuffer
+ `(all-the-icons-ibuffer-dir-face ((,class :foreground ,cyan-faint)))
+ `(all-the-icons-ibuffer-file-face ((,class :foreground ,blue-faint)))
+ `(all-the-icons-ibuffer-mode-face ((,class :foreground ,cyan)))
+ `(all-the-icons-ibuffer-size-face ((,class :foreground ,cyan-alt-other)))
;;;;; annotate
`(annotate-annotation ((,class :inherit modus-themes-subtle-blue)))
`(annotate-annotation-secondary ((,class :inherit modus-themes-subtle-green)))
@@ -4430,18 +4500,13 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(font-latex-italic-face ((,class :inherit italic)))
`(font-latex-math-face ((,class :inherit font-lock-constant-face)))
`(font-latex-script-char-face ((,class :inherit font-lock-builtin-face)))
- `(font-latex-sectioning-0-face ((,class :inherit modus-themes-heading-1)))
- `(font-latex-sectioning-1-face ((,class :inherit modus-themes-heading-2)))
- `(font-latex-sectioning-2-face ((,class :inherit modus-themes-heading-3)))
- `(font-latex-sectioning-3-face ((,class :inherit modus-themes-heading-4)))
- `(font-latex-sectioning-4-face ((,class :inherit modus-themes-heading-5)))
- `(font-latex-sectioning-5-face ((,class :inherit modus-themes-heading-6)))
+ `(font-latex-sectioning-5-face ((,class :inherit (bold modus-themes-variable-pitch) :foreground ,blue-nuanced-fg)))
`(font-latex-sedate-face ((,class :inherit font-lock-keyword-face)))
`(font-latex-slide-title-face ((,class :inherit modus-themes-heading-1)))
`(font-latex-string-face ((,class :inherit font-lock-string-face)))
`(font-latex-subscript-face ((,class :height 0.95)))
`(font-latex-superscript-face ((,class :height 0.95)))
- `(font-latex-verbatim-face ((,class :background ,bg-dim :foreground ,fg-special-mild)))
+ `(font-latex-verbatim-face ((,class :inherit modus-themes-markup-verbatim)))
`(font-latex-warning-face ((,class :inherit font-lock-warning-face)))
`(tex-match ((,class :foreground ,blue-alt-other)))
`(tex-verbatim ((,class :inherit modus-themes-markup-verbatim)))
@@ -4454,11 +4519,11 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(auto-dim-other-buffers-face ((,class :background ,bg-alt)))
;;;;; avy
`(avy-background-face ((,class :background ,bg-dim :foreground ,fg-dim :extend t)))
- `(avy-goto-char-timer-face ((,class :inherit (modus-themes-intense-yellow bold))))
- `(avy-lead-face ((,class :inherit (modus-themes-intense-magenta bold modus-themes-reset-soft))))
- `(avy-lead-face-0 ((,class :inherit (modus-themes-refine-cyan bold modus-themes-reset-soft))))
- `(avy-lead-face-1 ((,class :inherit (modus-themes-intense-neutral bold modus-themes-reset-soft))))
- `(avy-lead-face-2 ((,class :inherit (modus-themes-refine-red bold modus-themes-reset-soft))))
+ `(avy-goto-char-timer-face ((,class :inherit (modus-themes-intense-neutral bold))))
+ `(avy-lead-face ((,class :inherit (bold modus-themes-reset-soft) :background ,bg-char-0)))
+ `(avy-lead-face-0 ((,class :inherit (bold modus-themes-reset-soft) :background ,bg-char-1)))
+ `(avy-lead-face-1 ((,class :inherit (modus-themes-special-warm modus-themes-reset-soft))))
+ `(avy-lead-face-2 ((,class :inherit (bold modus-themes-reset-soft) :background ,bg-char-2)))
;;;;; aw (ace-window)
`(aw-background-face ((,class :foreground ,fg-unfocused)))
`(aw-key-face ((,class :inherit modus-themes-key-binding)))
@@ -4545,6 +4610,27 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(cfw:face-toolbar-button-off ((,class :inherit shadow)))
`(cfw:face-toolbar-button-on ((,class :inherit bold :background ,blue-nuanced-bg
:foreground ,blue-alt)))
+;;;;; calibredb
+ `(calibredb-archive-face ((,class :foreground ,magenta-alt-faint)))
+ `(calibredb-author-face ((,class :foreground ,blue-faint)))
+ `(calibredb-comment-face ((,class :inherit shadow)))
+ `(calibredb-date-face ((,class :foreground ,cyan)))
+ `(calibredb-edit-annotation-header-title-face ((,class :inherit bold)))
+ `(calibredb-favorite-face ((,class :foreground ,red-alt)))
+ `(calibredb-file-face (( )))
+ `(calibredb-format-face ((,class :foreground ,cyan-faint)))
+ `(calibredb-highlight-face ((,class :inherit success)))
+ `(calibredb-id-face (( )))
+ `(calibredb-ids-face (( )))
+ `(calibredb-search-header-highlight-face ((,class :inherit modus-themes-hl-line)))
+ `(calibredb-search-header-library-name-face ((,class :foreground ,blue-active)))
+ `(calibredb-search-header-library-path-face ((,class :inherit bold)))
+ `(calibredb-search-header-sort-face ((,class :inherit bold :foreground ,magenta-active)))
+ `(calibredb-search-header-total-face ((,class :inherit bold :foreground ,cyan-active)))
+ `(calibredb-search-header-filter-face ((,class :inherit bold)))
+ `(calibredb-mark-face ((,class :inherit modus-themes-mark-sel)))
+ `(calibredb-size-face (( )))
+ `(calibredb-tag-face ((,class :foreground ,magenta-alt-faint)))
;;;;; centaur-tabs
`(centaur-tabs-active-bar-face ((,class :background ,blue-active)))
`(centaur-tabs-close-mouse-face ((,class :inherit bold :foreground ,red-active :underline t)))
@@ -4552,7 +4638,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(centaur-tabs-close-unselected ((,class :inherit centaur-tabs-unselected)))
`(centaur-tabs-modified-marker-selected ((,class :inherit centaur-tabs-selected)))
`(centaur-tabs-modified-marker-unselected ((,class :inherit centaur-tabs-unselected)))
- `(centaur-tabs-default (( )))
+ `(centaur-tabs-default ((,class :background ,bg-main)))
`(centaur-tabs-selected ((,class :inherit modus-themes-tab-active)))
`(centaur-tabs-selected-modified ((,class :inherit (italic centaur-tabs-selected))))
`(centaur-tabs-unselected ((,class :inherit modus-themes-tab-inactive)))
@@ -4617,6 +4703,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(lui-button-face ((,class :inherit button)))
`(lui-highlight-face ((,class :foreground ,magenta-alt)))
`(lui-time-stamp-face ((,class :foreground ,blue-nuanced-fg)))
+;;;;; citar
+ `(citar ((,class :inherit shadow)))
+ `(citar-highlight (( )))
;;;;; color-rg
`(color-rg-font-lock-column-number ((,class :foreground ,magenta-alt-other)))
`(color-rg-font-lock-command ((,class :inherit bold :foreground ,fg-main)))
@@ -4635,45 +4724,38 @@ by virtue of calling either of `modus-themes-load-operandi' and
;;;;; column-enforce-mode
`(column-enforce-face ((,class :inherit modus-themes-refine-yellow)))
;;;;; company-mode
- `(company-echo-common ((,class :foreground ,magenta-alt-other)))
+ `(company-echo-common ((,class :inherit modus-themes-completion-match-0)))
`(company-preview ((,class :background ,bg-dim :foreground ,fg-dim)))
- `(company-preview-common ((,class :foreground ,blue-alt)))
+ `(company-preview-common ((,class :inherit company-echo-common)))
`(company-preview-search ((,class :inherit modus-themes-special-calm)))
`(company-template-field ((,class :inherit modus-themes-intense-magenta)))
- `(company-tooltip ((,class :background ,bg-alt :foreground ,fg-alt)))
- `(company-tooltip-annotation ((,class :inherit modus-themes-slant :foreground ,fg-special-cold)))
- `(company-tooltip-annotation-selection ((,class :inherit bold :foreground ,fg-main)))
- `(company-tooltip-common ((,class :inherit bold :foreground ,blue-alt)))
- `(company-tooltip-common-selection ((,class :foreground ,fg-main)))
+ `(company-tooltip ((,class :background ,bg-alt)))
+ `(company-tooltip-annotation ((,class :inherit completions-annotations)))
+ `(company-tooltip-common ((,class :inherit company-echo-common)))
`(company-tooltip-deprecated ((,class :inherit company-tooltip :strike-through t)))
- `(company-tooltip-mouse ((,class :inherit modus-themes-intense-blue)))
+ `(company-tooltip-mouse ((,class :inherit highlight)))
`(company-tooltip-scrollbar-thumb ((,class :background ,fg-active)))
`(company-tooltip-scrollbar-track ((,class :background ,bg-active)))
`(company-tooltip-search ((,class :inherit (modus-themes-search-success-lazy bold))))
`(company-tooltip-search-selection ((,class :inherit (modus-themes-search-success bold) :underline t)))
- `(company-tooltip-selection ((,class :inherit (modus-themes-subtle-cyan bold))))
+ `(company-tooltip-selection ((,class :inherit modus-themes-completion-selected-popup)))
;;;;; company-posframe
`(company-posframe-active-backend-name ((,class :inherit bold :background ,bg-active :foreground ,blue-active)))
`(company-posframe-inactive-backend-name ((,class :background ,bg-active :foreground ,fg-active)))
`(company-posframe-metadata ((,class :background ,bg-inactive :foreground ,fg-inactive)))
-;;;;; compilation feedback
- `(compilation-column-number ((,class :foreground ,magenta-alt-other)))
+;;;;; compilation
+ `(compilation-column-number ((,class :inherit compilation-line-number)))
`(compilation-error ((,class :inherit modus-themes-bold :foreground ,red)))
`(compilation-info ((,class :inherit modus-themes-bold :foreground ,fg-special-cold)))
`(compilation-line-number ((,class :foreground ,fg-special-warm)))
- `(compilation-mode-line-exit ((,class :inherit modus-themes-bold :foreground ,blue-active)))
+ `(compilation-mode-line-exit ((,class :inherit bold)))
`(compilation-mode-line-fail ((,class :inherit modus-themes-bold :foreground ,red-active)))
- `(compilation-mode-line-run ((,class :inherit modus-themes-bold :foreground ,magenta-active)))
- `(compilation-warning ((,class :inherit modus-themes-bold :foreground ,yellow)))
+ `(compilation-mode-line-run ((,class :inherit modus-themes-bold :foreground ,cyan-active)))
+ `(compilation-warning ((,class :inherit modus-themes-bold :foreground ,yellow-alt)))
;;;;; completions
`(completions-annotations ((,class :inherit modus-themes-slant :foreground ,cyan-faint)))
- `(completions-common-part ((,class ,@(modus-themes--standard-completions
- blue-alt blue-nuanced-bg
- cyan-refine-bg cyan-refine-fg))))
- `(completions-first-difference ((,class :inherit bold
- ,@(modus-themes--standard-completions
- magenta-alt blue-nuanced-bg
- magenta-intense-bg fg-main))))
+ `(completions-common-part ((,class :inherit modus-themes-completion-match-0)))
+ `(completions-first-difference ((,class :inherit modus-themes-completion-match-1)))
;;;;; consult
`(consult-async-running ((,class :inherit bold :foreground ,blue)))
`(consult-async-split ((,class :foreground ,magenta-alt)))
@@ -4688,10 +4770,13 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(consult-preview-error ((,class :inherit modus-themes-intense-red)))
`(consult-preview-line ((,class :background ,bg-hl-alt-intense)))
;;;;; corfu
- `(corfu-current ((,class :inherit bold :background ,cyan-subtle-bg)))
+ `(corfu-current ((,class :inherit modus-themes-completion-selected-popup)))
`(corfu-bar ((,class :background ,fg-alt)))
`(corfu-border ((,class :background ,bg-active)))
`(corfu-default ((,class :background ,bg-alt)))
+;;;;; corfu-quick
+ `(corfu-quick1 ((,class :inherit bold :background ,bg-char-0)))
+ `(corfu-quick2 ((,class :inherit bold :background ,bg-char-1)))
;;;;; counsel
`(counsel-active-mode ((,class :foreground ,magenta-alt-other)))
`(counsel-application-name ((,class :foreground ,red-alt-other)))
@@ -4736,12 +4821,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
;;;;; cursor-flash
`(cursor-flash-face ((,class :inherit modus-themes-intense-blue)))
;;;;; custom (M-x customize)
- `(custom-button ((,class :box (:line-width 2 :color nil :style released-button)
- :background ,bg-active :foreground ,fg-main)))
- `(custom-button-mouse ((,class :box (:line-width 2 :color nil :style released-button)
- :background ,bg-active :foreground ,fg-active)))
- `(custom-button-pressed ((,class :box (:line-width 2 :color nil :style pressed-button)
- :background ,bg-active :foreground ,fg-main)))
+ `(custom-button ((,class :inherit modus-themes-box-button)))
+ `(custom-button-mouse ((,class :inherit (highlight custom-button))))
+ `(custom-button-pressed ((,class :inherit modus-themes-box-button-pressed)))
`(custom-changed ((,class :inherit modus-themes-subtle-cyan)))
`(custom-comment ((,class :inherit shadow)))
`(custom-comment-tag ((,class :background ,bg-alt :foreground ,yellow-alt-other)))
@@ -4752,9 +4834,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(custom-modified ((,class :inherit modus-themes-subtle-cyan)))
`(custom-rogue ((,class :inherit modus-themes-refine-magenta)))
`(custom-set ((,class :foreground ,blue-alt)))
- `(custom-state ((,class :foreground ,cyan-alt-other)))
+ `(custom-state ((,class :foreground ,red-alt-faint)))
`(custom-themed ((,class :inherit modus-themes-subtle-blue)))
- `(custom-variable-tag ((,class :inherit bold :foreground ,cyan)))
+ `(custom-variable-obsolete ((,class :inherit shadow)))
+ `(custom-variable-tag ((,class :foreground ,cyan)))
;;;;; dap-mode
`(dap-mouse-eval-thing-face ((,class :box (:line-width -1 :color ,blue-active :style nil)
:background ,bg-active :foreground ,fg-main)))
@@ -4802,6 +4885,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(deft-summary-face ((,class :inherit (shadow modus-themes-slant))))
`(deft-time-face ((,class :foreground ,fg-special-cold)))
`(deft-title-face ((,class :inherit bold :foreground ,fg-main)))
+;;;;; devdocs
+ `(devdocs-code-block ((,class :inherit modus-themes-fixed-pitch :background ,bg-dim :extend t)))
;;;;; dictionary
`(dictionary-button-face ((,class :inherit bold :foreground ,fg-special-cold)))
`(dictionary-reference-face ((,class :inherit button)))
@@ -4947,7 +5032,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(diredp-tagged-autofile-name ((,class :inherit modus-themes-refine-magenta)))
`(diredp-write-priv ((,class :foreground ,cyan)))
;;;;; display-fill-column-indicator-mode
- `(fill-column-indicator ((,class :foreground ,bg-active)))
+ `(fill-column-indicator ((,class :height 1 :background ,bg-inactive :foreground ,bg-inactive)))
;;;;; doom-modeline
`(doom-modeline-bar ((,class :inherit modus-themes-active-blue)))
`(doom-modeline-bar-inactive ((,class :background ,fg-inactive :foreground ,bg-main)))
@@ -5023,6 +5108,13 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(ediff-odd-diff-Ancestor ((,class :inherit ediff-even-diff-Ancestor)))
`(ediff-odd-diff-B ((,class :inherit ediff-even-diff-B)))
`(ediff-odd-diff-C ((,class :inherit ediff-even-diff-C)))
+;;;;; ein (Emacs IPython Notebook)
+ `(ein:basecell-input-area-face ((,class :background ,bg-dim :extend t)))
+ `(ein:cell-output-area (( )))
+ `(ein:cell-output-area-error ((,class :background ,red-nuanced-bg :extend t)))
+ `(ein:cell-output-stderr ((,class :background ,red-nuanced-bg :extend t)))
+ `(ein:markdowncell-input-area-face (( )))
+ `(ein:notification-tab-normal ((,class :underline t)))
;;;;; eglot
`(eglot-mode-line ((,class :inherit modus-themes-bold :foreground ,magenta-active)))
;;;;; el-search
@@ -5032,7 +5124,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(el-search-occur-match ((,class :inherit modus-themes-special-calm)))
;;;;; eldoc
;; NOTE: see https://github.com/purcell/package-lint/issues/187
- (list 'eldoc-highlight-function-argument `((,class :inherit bold :foreground ,blue-alt-other)))
+ (list 'eldoc-highlight-function-argument `((,class :inherit bold
+ :background ,yellow-nuanced-bg
+ :foreground ,yellow-alt-other)))
;;;;; eldoc-box
`(eldoc-box-body ((,class :background ,bg-alt :foreground ,fg-main)))
`(eldoc-box-border ((,class :background ,fg-alt)))
@@ -5045,10 +5139,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(elfeed-search-date-face ((,class :foreground ,cyan)))
`(elfeed-search-feed-face ((,class :foreground ,blue-faint)))
`(elfeed-search-filter-face ((,class :inherit bold :foreground ,magenta-active)))
- `(elfeed-search-last-update-face ((,class :foreground ,cyan-active)))
- `(elfeed-search-tag-face ((,class :foreground ,cyan-alt-other)))
+ `(elfeed-search-last-update-face ((,class :inherit bold :foreground ,cyan-active)))
+ `(elfeed-search-tag-face ((,class :foreground ,magenta-alt-faint)))
`(elfeed-search-title-face ((,class :foreground ,fg-dim)))
- `(elfeed-search-unread-count-face ((,class :foreground ,green-active)))
+ `(elfeed-search-unread-count-face ((,class :inherit bold :foreground ,fg-active)))
`(elfeed-search-unread-title-face ((,class :inherit bold :foreground ,fg-main)))
;;;;; elfeed-score
`(elfeed-score-date-face ((,class :foreground ,blue)))
@@ -5062,6 +5156,19 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(elpher-gemini-heading3 ((,class :inherit modus-themes-heading-3)))
;;;;; embark
`(embark-keybinding ((,class :inherit modus-themes-key-binding)))
+ `(embark-collect-marked ((,class :inherit modus-themes-mark-sel)))
+;;;;; ement (ement.el)
+ `(ement-room-fully-read-marker ((,class :background ,cyan-subtle-bg)))
+ `(ement-room-membership ((,class :inherit shadow)))
+ `(ement-room-mention ((,class :background ,bg-hl-alt-intense)))
+ `(ement-room-name ((,class :inherit bold)))
+ `(ement-room-reactions ((,class :inherit shadow)))
+ `(ement-room-read-receipt-marker ((,class :background ,yellow-subtle-bg)))
+ `(ement-room-self ((,class :inherit bold :foreground ,magenta)))
+ `(ement-room-self-message ((,class :foreground ,magenta-faint)))
+ `(ement-room-timestamp ((,class :inherit shadow)))
+ `(ement-room-timestamp-header ((,class :inherit bold :foreground ,cyan)))
+ `(ement-room-user ((,class :inherit bold :foreground ,blue)))
;;;;; emms
`(emms-browser-album-face ((,class :foreground ,magenta-alt-other)))
`(emms-browser-artist-face ((,class :foreground ,cyan)))
@@ -5239,10 +5346,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(eww-form-checkbox ((,class :inherit eww-form-text)))
`(eww-form-file ((,class :inherit eww-form-submit)))
`(eww-form-select ((,class :inherit eww-form-submit)))
- `(eww-form-submit ((,class :box (:line-width 2 :style released-button)
- :background ,bg-active)))
- `(eww-form-text ((,class :box ,bg-active :background ,bg-alt)))
- `(eww-form-textarea ((,class :background ,bg-alt)))
+ `(eww-form-submit ((,class :inherit modus-themes-box-button)))
+ `(eww-form-text ((,class :inherit widget-field)))
+ `(eww-form-textarea ((,class :inherit eww-form-text)))
;;;;; eyebrowse
`(eyebrowse-mode-line-active ((,class :inherit bold :foreground ,blue-active)))
;;;;; fancy-dabbrev
@@ -5294,12 +5400,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(flyspell-duplicate ((,class :inherit modus-themes-lang-warning)))
`(flyspell-incorrect ((,class :inherit modus-themes-lang-error)))
;;;;; flx
- `(flx-highlight-face ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-magenta
- 'modus-themes-intense-magenta
- 'modus-themes-nuanced-magenta
- magenta-alt
- 'bold))))
+ `(flx-highlight-face ((,class :inherit modus-themes-completion-match-0)))
;;;;; freeze-it
`(freeze-it-show ((,class :background ,bg-dim :foreground ,fg-special-warm)))
;;;;; frog-menu
@@ -5328,7 +5429,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(font-lock-doc-face ((,class :inherit modus-themes-slant
,@(modus-themes--syntax-string
fg-docstring fg-special-cold
- fg-special-mild magenta-nuanced-fg
+ fg-special-mild fg-special-calm
fg-special-mild magenta-nuanced-fg))))
`(font-lock-function-name-face ((,class ,@(modus-themes--syntax-extra
magenta magenta-faint
@@ -5342,30 +5443,31 @@ by virtue of calling either of `modus-themes-load-operandi' and
yellow yellow-faint))))
`(font-lock-preprocessor-face ((,class ,@(modus-themes--syntax-extra
red-alt-other red-alt-other-faint
- blue-alt blue-alt-faint))))
- `(font-lock-regexp-grouping-backslash ((,class :inherit bold
+ cyan-alt-other cyan-alt-faint))))
+ `(font-lock-regexp-grouping-backslash ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-string
fg-escape-char-backslash yellow-alt-faint
- yellow magenta-alt
- yellow-faint red-faint))))
- `(font-lock-regexp-grouping-construct ((,class :inherit bold
+ yellow-alt magenta-alt
+ red-faint green-alt-other-faint))))
+ `(font-lock-regexp-grouping-construct ((,class :inherit modus-themes-bold
,@(modus-themes--syntax-string
fg-escape-char-construct red-alt-other-faint
- blue blue-alt-other
+ red-alt-other blue-alt-other
blue-faint blue-alt-other-faint))))
`(font-lock-string-face ((,class ,@(modus-themes--syntax-string
blue-alt blue-alt-faint
- green red
- green-faint red-faint))))
+ green-alt-other red-alt-other
+ green-alt-faint red-alt-faint))))
`(font-lock-type-face ((,class :inherit modus-themes-bold
- ,@(modus-themes--syntax-foreground
- cyan-alt-other cyan-alt-faint))))
+ ,@(modus-themes--syntax-extra
+ cyan-alt-other cyan-alt-faint
+ magenta-alt-other magenta-alt-other-faint))))
`(font-lock-variable-name-face ((,class ,@(modus-themes--syntax-extra
cyan cyan-faint
- blue-alt-other blue-alt-other-faint))))
+ blue-alt blue-alt-faint))))
`(font-lock-warning-face ((,class :inherit modus-themes-bold
- ,@(modus-themes--syntax-comment
- yellow-active red-active red-faint yellow-faint))))
+ ,@(modus-themes--syntax-foreground
+ yellow-active yellow-alt-faint))))
;;;;; forge
`(forge-post-author ((,class :inherit bold :foreground ,fg-main)))
`(forge-post-date ((,class :foreground ,fg-special-cold)))
@@ -5376,7 +5478,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(forge-topic-unread ((,class :inherit bold :foreground ,fg-main)))
;;;;; fountain-mode
`(fountain-character ((,class :foreground ,blue-alt-other)))
- `(fountain-comment ((,class :inherit modus-themes-slant :foreground ,fg-alt)))
+ `(fountain-comment ((,class :inherit font-lock-comment-face)))
`(fountain-dialog ((,class :foreground ,blue-alt)))
`(fountain-metadata-key ((,class :foreground ,green-alt-other)))
`(fountain-metadata-value ((,class :foreground ,blue)))
@@ -5395,8 +5497,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(fountain-synopsis ((,class :foreground ,cyan-alt)))
`(fountain-trans ((,class :foreground ,yellow-alt-other)))
;;;;; geiser
- `(geiser-font-lock-autodoc-current-arg ((,class :inherit font-lock-function-name-face)))
- `(geiser-font-lock-autodoc-identifier ((,class :inherit font-lock-constant-face)))
+ `(geiser-font-lock-autodoc-current-arg ((,class :inherit bold
+ :background ,yellow-nuanced-bg
+ :foreground ,yellow-alt-other)))
+ `(geiser-font-lock-autodoc-identifier ((,class :foreground ,cyan)))
`(geiser-font-lock-doc-button ((,class :inherit button :foreground ,fg-docstring)))
`(geiser-font-lock-doc-link ((,class :inherit button)))
`(geiser-font-lock-error-link ((,class :inherit button :foreground ,red)))
@@ -5408,11 +5512,11 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(geiser-font-lock-xref-link ((,class :inherit button)))
;;;;; git-commit
`(git-commit-comment-action ((,class :inherit font-lock-comment-face)))
- `(git-commit-comment-branch-local ((,class :inherit modus-themes-slant :foreground ,blue-alt)))
- `(git-commit-comment-branch-remote ((,class :inherit modus-themes-slant :foreground ,magenta-alt)))
- `(git-commit-comment-detached ((,class :inherit modus-themes-slant :foreground ,cyan-alt)))
- `(git-commit-comment-file ((,class :inherit modus-themes-slant :foreground ,cyan)))
- `(git-commit-comment-heading ((,class :inherit (bold modus-themes-slant))))
+ `(git-commit-comment-branch-local ((,class :inherit font-lock-comment-face :foreground ,blue-alt)))
+ `(git-commit-comment-branch-remote ((,class :inherit font-lock-comment-face :foreground ,magenta-alt)))
+ `(git-commit-comment-detached ((,class :inherit font-lock-comment-face :foreground ,cyan-alt)))
+ `(git-commit-comment-file ((,class :inherit font-lock-comment-face :foreground ,cyan)))
+ `(git-commit-comment-heading ((,class :inherit (bold font-lock-comment-face))))
`(git-commit-keyword ((,class :foreground ,magenta)))
`(git-commit-known-pseudo-header ((,class :foreground ,cyan-alt-other)))
`(git-commit-nonempty-second-line ((,class :inherit error)))
@@ -5430,8 +5534,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(git-gutter-fr:deleted ((,class :inherit modus-themes-fringe-red)))
`(git-gutter-fr:modified ((,class :inherit modus-themes-fringe-yellow)))
;;;;; git-rebase
- `(git-rebase-comment-hash ((,class :inherit modus-themes-slant :foreground ,cyan)))
- `(git-rebase-comment-heading ((,class :inherit (bold modus-themes-slant))))
+ `(git-rebase-comment-hash ((,class :inherit font-lock-comment-face :foreground ,cyan)))
+ `(git-rebase-comment-heading ((,class :inherit (bold font-lock-comment-face))))
`(git-rebase-description ((,class :foreground ,fg-main)))
`(git-rebase-hash ((,class :foreground ,cyan-alt-other)))
;;;;; git-timemachine
@@ -5549,11 +5653,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(helm-eshell-prompts-promptidx ((,class :foreground ,cyan-active)))
`(helm-etags-file ((,class :foreground ,fg-dim :underline t)))
`(helm-ff-backup-file ((,class :inherit shadow)))
- `(helm-ff-denied ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-red
- 'modus-themes-intense-red
- 'modus-themes-nuanced-red
- red))))
+ `(helm-ff-denied ((,class :inherit modus-themes-intense-red)))
`(helm-ff-directory ((,class :inherit helm-buffer-directory)))
`(helm-ff-dirs ((,class :inherit bold :foreground ,blue-alt-other)))
`(helm-ff-dotted-directory ((,class :inherit bold :background ,bg-alt :foreground ,fg-alt)))
@@ -5562,84 +5662,39 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(helm-ff-file ((,class :foreground ,fg-main)))
`(helm-ff-file-extension ((,class :foreground ,fg-special-warm)))
`(helm-ff-invalid-symlink ((,class :inherit modus-themes-link-broken)))
- `(helm-ff-pipe ((,class ,@(modus-themes--extra-completions
- 'modus-themes-refine-magenta
- 'modus-themes-subtle-magenta
- 'modus-themes-nuanced-magenta
- magenta))))
- `(helm-ff-prefix ((,class ,@(modus-themes--extra-completions
- 'modus-themes-refine-yellow
- 'modus-themes-subtle-yellow
- 'modus-themes-nuanced-yellow
- yellow-alt-other))))
+ `(helm-ff-pipe ((,class :inherit modus-themes-special-calm)))
+ `(helm-ff-prefix ((,class :inherit modus-themes-special-warm)))
`(helm-ff-socket ((,class :foreground ,red-alt-other)))
- `(helm-ff-suid ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-red
- 'modus-themes-refine-red
- 'modus-themes-nuanced-yellow
- red-alt))))
+ `(helm-ff-suid ((,class :inherit modus-themes-special-warm)))
`(helm-ff-symlink ((,class :inherit modus-themes-link-symlink)))
`(helm-ff-truename ((,class :foreground ,blue-alt-other)))
- `(helm-fd-finish ((,class :foreground ,green-active)))
+ `(helm-fd-finish ((,class :inherit success)))
`(helm-grep-cmd-line ((,class :foreground ,yellow-alt-other)))
`(helm-grep-file ((,class :inherit bold :foreground ,fg-special-cold)))
- `(helm-grep-finish ((,class :foreground ,green-active)))
+ `(helm-grep-finish ((,class :inherit bold)))
`(helm-grep-lineno ((,class :foreground ,fg-special-warm)))
`(helm-grep-match ((,class :inherit modus-themes-special-calm)))
`(helm-header ((,class :inherit bold :foreground ,fg-special-cold)))
`(helm-header-line-left-margin ((,class :inherit bold :foreground ,yellow-intense)))
- `(helm-history-deleted ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-red
- 'modus-themes-intense-red
- 'modus-themes-nuanced-red
- red
- 'bold))))
+ `(helm-history-deleted ((,class :inherit modus-themes-special-warm)))
`(helm-history-remote ((,class :foreground ,red-alt-other)))
- `(helm-lisp-completion-info ((,class :foreground ,fg-special-warm)))
- `(helm-lisp-show-completion ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-yellow
- 'modus-themes-refine-yellow
- 'modus-themes-nuanced-yellow
- yellow
- 'bold))))
- `(helm-locate-finish ((,class :foreground ,green-active)))
- `(helm-match ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-cyan
- 'modus-themes-refine-cyan
- 'modus-themes-nuanced-cyan
- cyan
- 'bold))))
- `(helm-match-item ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-neutral
- 'modus-themes-subtle-cyan
- 'modus-themes-nuanced-cyan
- cyan-alt-other))))
+ `(helm-lisp-completion-info ((,class :inherit modus-themes-bold :foreground ,fg-special-cold)))
+ `(helm-lisp-show-completion ((,class :inherit modus-themes-special-warm)))
+ `(helm-locate-finish ((,class :inherit success)))
+ `(helm-match ((,class :inherit modus-themes-completion-match-0)))
+ `(helm-match-item ((,class :inherit helm-match)))
`(helm-minibuffer-prompt ((,class :inherit modus-themes-prompt)))
`(helm-moccur-buffer ((,class :inherit button :foreground ,cyan-alt-other)))
- `(helm-mode-prefix ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-magenta
- 'modus-themes-intense-magenta
- 'modus-themes-nuanced-magenta
- magenta-alt
- 'bold))))
+ `(helm-mode-prefix ((,class :inherit modus-themes-special-calm)))
`(helm-non-file-buffer ((,class :inherit shadow)))
`(helm-prefarg ((,class :foreground ,red-active)))
- `(helm-resume-need-update ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-magenta
- 'modus-themes-refine-magenta
- 'modus-themes-nuanced-magenta
- magenta-alt-other))))
- `(helm-selection ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-blue
- 'modus-themes-refine-blue
- 'modus-themes-special-cold
- nil
- 'bold))))
- `(helm-selection-line ((,class :inherit modus-themes-special-cold)))
+ `(helm-resume-need-update ((,class :inherit modus-themes-special-calm)))
+ `(helm-selection ((,class :inherit modus-themes-completion-selected)))
+ `(helm-selection-line ((,class :background ,bg-hl-alt-intense)))
`(helm-separator ((,class :foreground ,fg-special-mild)))
`(helm-time-zone-current ((,class :foreground ,green)))
`(helm-time-zone-home ((,class :foreground ,magenta)))
- `(helm-source-header ((,class :inherit modus-themes-pseudo-header :foreground ,fg-special-cold)))
+ `(helm-source-header ((,class :inherit modus-themes-pseudo-header :foreground ,fg-special-warm)))
`(helm-top-columns ((,class :inherit helm-header)))
`(helm-ucs-char ((,class :foreground ,yellow-alt-other)))
`(helm-visible-mark ((,class :inherit modus-themes-subtle-cyan)))
@@ -5654,15 +5709,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(helm-ls-git-renamed-modified-face ((,class :foreground ,magenta)))
`(helm-ls-git-untracked-face ((,class :foreground ,fg-special-cold)))
;;;;; helm-switch-shell
- `(helm-switch-shell-new-shell-face ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-magenta
- 'modus-themes-refine-magenta
- 'modus-themes-nuanced-magenta
- magenta-alt-other
- 'bold))))
+ `(helm-switch-shell-new-shell-face ((,class :inherit modus-themes-completion-match-0)))
;;;;; helm-xref
- `(helm-xref-file-name ((,class :inherit bold :foreground ,fg-special-cold)))
- `(helm-xref-file-name ((,class :foreground ,fg-special-warm)))
+ `(helm-xref-file-name ((,class :inherit modus-themes-bold :foreground ,fg-special-cold)))
;;;;; helpful
`(helpful-heading ((,class :inherit modus-themes-heading-1)))
;;;;; highlight region or ad-hoc regexp
@@ -5678,7 +5727,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(hi-red-b ((,class :inherit bold :background ,red-intense-bg :foreground ,fg-main)))
`(hi-salmon ((,class :background ,red-subtle-bg :foreground ,fg-main)))
`(hi-yellow ((,class :background ,yellow-subtle-bg :foreground ,fg-main)))
- `(highlight ((,class :background ,blue-subtle-bg :foreground ,fg-main)))
+ `(highlight ((,class ,@(if modus-themes-intense-mouseovers
+ (list :background blue-intense-bg :foreground fg-main)
+ (list :background cyan-subtle-bg :foreground fg-main)))))
`(highlight-changes ((,class :foreground ,red-alt :underline nil)))
`(highlight-changes-delete ((,class :background ,red-nuanced-bg
:foreground ,red :underline t)))
@@ -5705,29 +5756,17 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(hydra-face-red ((,class :inherit bold :foreground ,red-faint)))
`(hydra-face-teal ((,class :inherit bold :foreground ,cyan-alt-other)))
;;;;; icomplete
- `(icomplete-first-match ((,class :inherit bold
- ,@(modus-themes--standard-completions
- magenta bg-alt
- bg-active fg-main))))
- `(icomplete-selected-match ((,class :inherit bold :foreground ,fg-main
- :background ,@(pcase modus-themes-completions
- ('opinionated (list bg-active))
- (_ (list bg-inactive))))))
+ `(icomplete-first-match ((,class :inherit modus-themes-completion-match-0)))
+ `(icomplete-selected-match ((,class :inherit modus-themes-completion-selected)))
;;;;; icomplete-vertical
`(icomplete-vertical-separator ((,class :inherit shadow)))
;;;;; ido-mode
- `(ido-first-match ((,class :inherit bold
- ,@(modus-themes--standard-completions
- magenta bg-alt
- bg-active fg-main))))
+ `(ido-first-match ((,class :inherit modus-themes-completion-match-0)))
`(ido-incomplete-regexp ((,class :inherit error)))
`(ido-indicator ((,class :inherit modus-themes-subtle-yellow)))
- `(ido-only-match ((,class :inherit bold
- ,@(modus-themes--standard-completions
- green green-nuanced-bg
- green-intense-bg fg-main))))
+ `(ido-only-match ((,class :inherit ido-first-match)))
`(ido-subdir ((,class :foreground ,blue)))
- `(ido-virtual ((,class :foreground ,fg-special-warm)))
+ `(ido-virtual ((,class :foreground ,magenta-alt-other)))
;;;;; iedit
`(iedit-occurrence ((,class :inherit modus-themes-refine-blue)))
`(iedit-read-only-occurrence ((,class :inherit modus-themes-intense-yellow)))
@@ -5759,7 +5798,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(info-header-node ((,class :inherit (shadow bold))))
`(info-header-xref ((,class :foreground ,blue-active)))
`(info-index-match ((,class :inherit match)))
- `(info-menu-header ((,class :inherit modus-themes-heading-3)))
+ `(info-menu-header ((,class :inherit modus-themes-pseudo-header)))
`(info-menu-star ((,class :foreground ,red)))
`(info-node ((,class :inherit bold)))
`(info-title-1 ((,class :inherit modus-themes-heading-1)))
@@ -5803,64 +5842,22 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(match ((,class :inherit modus-themes-special-calm)))
`(query-replace ((,class :inherit (modus-themes-intense-yellow bold))))
;;;;; ivy
- `(ivy-action ((,class :inherit bold :foreground ,red-alt)))
- `(ivy-completions-annotations ((,class :inherit completions-annotations)))
- `(ivy-confirm-face ((,class :foreground ,cyan)))
- `(ivy-current-match ((,class ,@(modus-themes--extra-completions
- 'modus-themes-refine-cyan
- 'modus-themes-intense-cyan
- 'modus-themes-special-cold
- nil
- 'bold))))
+ `(ivy-action ((,class :inherit modus-themes-key-binding)))
+ `(ivy-confirm-face ((,class :inherit success)))
+ `(ivy-current-match ((,class :inherit modus-themes-completion-selected)))
`(ivy-cursor ((,class :background ,fg-main :foreground ,bg-main)))
- `(ivy-grep-info ((,class :foreground ,cyan-alt)))
- `(ivy-grep-line-number ((,class :foreground ,fg-special-warm)))
`(ivy-highlight-face ((,class :foreground ,magenta)))
`(ivy-match-required-face ((,class :inherit error)))
- `(ivy-minibuffer-match-face-1 ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-neutral
- 'modus-themes-intense-neutral
- 'modus-themes-nuanced-cyan
- fg-alt))))
- `(ivy-minibuffer-match-face-2 ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-green
- 'modus-themes-refine-green
- 'modus-themes-nuanced-green
- green-alt-other
- 'bold))))
- `(ivy-minibuffer-match-face-3 ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-blue
- 'modus-themes-refine-blue
- 'modus-themes-nuanced-blue
- blue-alt-other
- 'bold))))
- `(ivy-minibuffer-match-face-4 ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-magenta
- 'modus-themes-refine-magenta
- 'modus-themes-nuanced-magenta
- magenta-alt-other
- 'bold))))
- `(ivy-minibuffer-match-highlight ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-cyan
- 'modus-themes-intense-cyan
- 'modus-themes-nuanced-cyan
- cyan-alt-other
- 'bold))))
- `(ivy-modified-buffer ((,class :inherit modus-themes-slant :foreground ,yellow)))
- `(ivy-modified-outside-buffer ((,class :inherit modus-themes-slant :foreground ,yellow-alt)))
+ `(ivy-minibuffer-match-face-1 (( )))
+ `(ivy-minibuffer-match-face-2 ((,class :inherit modus-themes-completion-match-0)))
+ `(ivy-minibuffer-match-face-3 ((,class :inherit modus-themes-completion-match-1)))
+ `(ivy-minibuffer-match-face-4 ((,class :inherit modus-themes-completion-match-2)))
`(ivy-org ((,class :foreground ,cyan-alt-other)))
- `(ivy-prompt-match ((,class :inherit ivy-current-match)))
`(ivy-remote ((,class :foreground ,magenta)))
`(ivy-separator ((,class :inherit shadow)))
- `(ivy-subdir ((,class :foreground ,blue-alt-other)))
+ `(ivy-subdir ((,class :foreground ,blue)))
`(ivy-virtual ((,class :foreground ,magenta-alt-other)))
- `(ivy-yanked-word ((,class ,@(modus-themes--extra-completions
- 'modus-themes-subtle-blue
- 'modus-themes-refine-blue
- 'modus-themes-nuanced-blue
- blue-alt))))
;;;;; ivy-posframe
- `(ivy-posframe ((,class :background ,bg-dim :foreground ,fg-main)))
`(ivy-posframe-border ((,class :background ,fg-window-divider-inner)))
`(ivy-posframe-cursor ((,class :background ,fg-main :foreground ,bg-main)))
;;;;; jira (org-jira)
@@ -5910,7 +5907,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(kaocha-runner-warning-face ((,class :inherit warning)))
;;;;; keycast
`(keycast-command ((,class :inherit bold :foreground ,blue-active)))
- `(keycast-key ((,class :background ,blue-active :foreground ,bg-main)))
+ ;; FIXME 2022-05-03: The padding breaks `keycast-tab-bar-mode'
+ `(keycast-key ((,class ;; ,@(modus-themes--mode-line-padded-box blue-active)
+ :background ,blue-active :foreground ,bg-main)))
;;;;; ledger-mode
`(ledger-font-auto-xact-face ((,class :foreground ,magenta)))
`(ledger-font-account-name-face ((,class :foreground ,fg-special-cold)))
@@ -5923,23 +5922,26 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(ledger-font-payee-uncleared-face ((,class :foreground ,red-alt-other)))
`(ledger-font-xact-highlight-face ((,class :background ,bg-hl-alt)))
;;;;; line numbers (display-line-numbers-mode and global variant)
+ ;; Here we cannot inherit `modus-themes-fixed-pitch'. We need to
+ ;; fall back to `default' otherwise line numbers do not scale when
+ ;; using `text-scale-adjust'.
`(line-number
- ((,class :inherit default
+ ((,class :inherit ,(if modus-themes-mixed-fonts 'fixed-pitch 'default)
,@(modus-themes--line-numbers
fg-alt bg-dim
fg-unfocused))))
`(line-number-current-line
- ((,class :inherit (bold default)
+ ((,class :inherit (bold line-number)
,@(modus-themes--line-numbers
fg-main bg-active
blue-alt-other))))
`(line-number-major-tick
- ((,class :inherit (bold default)
+ ((,class :inherit (bold line-number)
,@(modus-themes--line-numbers
yellow-nuanced-fg yellow-nuanced-bg
red-alt))))
`(line-number-minor-tick
- ((,class :inherit (bold default)
+ ((,class :inherit (bold line-number)
,@(modus-themes--line-numbers
fg-alt bg-inactive
fg-inactive))))
@@ -5992,9 +5994,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(macrostep-gensym-5 ((,class :inherit bold :foreground ,magenta :box t)))
`(macrostep-macro-face ((,class :inherit button :foreground ,green-alt)))
;;;;; magit
- `(magit-bisect-bad ((,class :foreground ,red-alt-other)))
- `(magit-bisect-good ((,class :foreground ,green-alt-other)))
- `(magit-bisect-skip ((,class :foreground ,yellow-alt-other)))
+ `(magit-bisect-bad ((,class :inherit error)))
+ `(magit-bisect-good ((,class :inherit success)))
+ `(magit-bisect-skip ((,class :inherit warning)))
`(magit-blame-date ((,class :foreground ,blue)))
`(magit-blame-dimmed ((,class :inherit (shadow modus-themes-reset-hard))))
`(magit-blame-hash ((,class :foreground ,fg-special-warm)))
@@ -6023,7 +6025,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(magit-diff-added ((,class ,@(modus-themes--diff
bg-diff-added fg-diff-added
green-nuanced-bg fg-diff-added
- bg-diff-added-deuteran fg-diff-added-deuteran))))
+ bg-diff-added-deuteran fg-diff-added-deuteran
+ blue-nuanced-bg fg-diff-added-deuteran))))
`(magit-diff-added-highlight ((,class :inherit modus-themes-diff-focus-added)))
`(magit-diff-base ((,class ,@(modus-themes--diff
bg-diff-changed fg-diff-changed
@@ -6044,6 +6047,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
bg-active fg-inactive
bg-inactive fg-inactive
bg-inactive fg-inactive
+ nil nil
t))))
;; NOTE: we do not follow the pattern of inheriting from
;; modus-themes-grue-* faces, as this is a special case.
@@ -6073,19 +6077,19 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(magit-log-author ((,class :foreground ,cyan)))
`(magit-log-date ((,class :inherit shadow)))
`(magit-log-graph ((,class :foreground ,fg-dim)))
- `(magit-mode-line-process ((,class :inherit bold :foreground ,blue-active)))
+ `(magit-mode-line-process ((,class :inherit bold :foreground ,cyan-active)))
`(magit-mode-line-process-error ((,class :inherit bold :foreground ,red-active)))
`(magit-process-ng ((,class :inherit error)))
`(magit-process-ok ((,class :inherit success)))
- `(magit-reflog-amend ((,class :background ,bg-main :foreground ,magenta-intense)))
- `(magit-reflog-checkout ((,class :background ,bg-main :foreground ,blue-intense)))
- `(magit-reflog-cherry-pick ((,class :background ,bg-main :foreground ,green-intense)))
- `(magit-reflog-commit ((,class :background ,bg-main :foreground ,green-intense)))
- `(magit-reflog-merge ((,class :background ,bg-main :foreground ,green-intense)))
- `(magit-reflog-other ((,class :background ,bg-main :foreground ,cyan-intense)))
- `(magit-reflog-rebase ((,class :background ,bg-main :foreground ,magenta-intense)))
- `(magit-reflog-remote ((,class :background ,bg-main :foreground ,cyan-intense)))
- `(magit-reflog-reset ((,class :background ,bg-main :foreground ,red-intense)))
+ `(magit-reflog-amend ((,class :inherit warning)))
+ `(magit-reflog-checkout ((,class :inherit bold :foreground ,blue-alt)))
+ `(magit-reflog-cherry-pick ((,class :inherit success)))
+ `(magit-reflog-commit ((,class :inherit bold)))
+ `(magit-reflog-merge ((,class :inherit success)))
+ `(magit-reflog-other ((,class :inherit bold :foreground ,cyan)))
+ `(magit-reflog-rebase ((,class :inherit bold :foreground ,magenta)))
+ `(magit-reflog-remote ((,class :inherit bold :foreground ,magenta-alt-other)))
+ `(magit-reflog-reset ((,class :inherit error)))
`(magit-refname ((,class :inherit shadow)))
`(magit-refname-pullreq ((,class :inherit shadow)))
`(magit-refname-stash ((,class :inherit shadow)))
@@ -6094,21 +6098,21 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(magit-section-heading ((,class :inherit bold :foreground ,cyan)))
`(magit-section-heading-selection ((,class :inherit (modus-themes-refine-cyan bold))))
`(magit-section-highlight ((,class :background ,bg-alt)))
- `(magit-sequence-done ((,class :inherit modus-themes-grue)))
- `(magit-sequence-drop ((,class :foreground ,red-alt)))
- `(magit-sequence-exec ((,class :foreground ,magenta-alt)))
- `(magit-sequence-head ((,class :foreground ,cyan-alt)))
- `(magit-sequence-onto ((,class :inherit shadow)))
- `(magit-sequence-part ((,class :foreground ,yellow-alt)))
- `(magit-sequence-pick ((,class :foreground ,blue-alt)))
- `(magit-sequence-stop ((,class :foreground ,red)))
- `(magit-signature-bad ((,class :inherit bold :foreground ,red)))
- `(magit-signature-error ((,class :foreground ,red-alt)))
- `(magit-signature-expired ((,class :foreground ,yellow)))
+ `(magit-sequence-done ((,class :inherit success)))
+ `(magit-sequence-drop ((,class :inherit error)))
+ `(magit-sequence-exec ((,class :inherit bold :foreground ,magenta-alt)))
+ `(magit-sequence-head ((,class :inherit bold :foreground ,cyan-alt)))
+ `(magit-sequence-onto ((,class :inherit (bold shadow))))
+ `(magit-sequence-part ((,class :inherit warning)))
+ `(magit-sequence-pick ((,class :inherit bold)))
+ `(magit-sequence-stop ((,class :inherit error)))
+ `(magit-signature-bad ((,class :inherit error)))
+ `(magit-signature-error ((,class :inherit error)))
+ `(magit-signature-expired ((,class :inherit warning)))
`(magit-signature-expired-key ((,class :foreground ,yellow)))
- `(magit-signature-good ((,class :inherit modus-themes-grue)))
- `(magit-signature-revoked ((,class :foreground ,magenta)))
- `(magit-signature-untrusted ((,class :foreground ,cyan)))
+ `(magit-signature-good ((,class :inherit success)))
+ `(magit-signature-revoked ((,class :inherit bold :foreground ,magenta)))
+ `(magit-signature-untrusted ((,class :inherit (bold shadow))))
`(magit-tag ((,class :foreground ,yellow-alt-other)))
;;;;; magit-imerge
`(magit-imerge-overriding-value ((,class :inherit bold :foreground ,red-alt)))
@@ -6116,9 +6120,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(makefile-makepp-perl ((,class :background ,cyan-nuanced-bg)))
`(makefile-space ((,class :background ,magenta-nuanced-bg)))
;;;;; man
- `(Man-overstrike ((,class :inherit bold :foreground ,magenta)))
+ `(Man-overstrike ((,class :inherit bold :foreground ,fg-special-calm)))
`(Man-reverse ((,class :inherit modus-themes-subtle-magenta)))
- `(Man-underline ((,class :foreground ,cyan :underline t)))
;;;;; marginalia
`(marginalia-archive ((,class :foreground ,cyan-alt-other)))
`(marginalia-char ((,class :foreground ,magenta)))
@@ -6134,14 +6137,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(marginalia-file-priv-rare ((,class :foreground ,red)))
`(marginalia-file-priv-read ((,class :foreground ,fg-main)))
`(marginalia-file-priv-write ((,class :foreground ,cyan)))
- ;; Here we make an exception of not applying the bespoke
- ;; `modus-themes-key-binding' for two reasons: (1) completion
- ;; highlights can be fairly intense, so we do not want more
- ;; components to compete with them for attention, (2) the
- ;; `marginalia-key' may not be used for key bindings specifically,
- ;; so we might end up applying styles in places we should not.
`(marginalia-function ((,class :foreground ,magenta-alt-faint)))
- `(marginalia-key ((,class :foreground ,magenta-alt-other)))
+ `(marginalia-key ((,class :inherit modus-themes-key-binding)))
`(marginalia-lighter ((,class :foreground ,blue-alt)))
`(marginalia-list ((,class :foreground ,magenta-alt-other-faint)))
`(marginalia-mode ((,class :foreground ,cyan)))
@@ -6172,6 +6169,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(markdown-header-face-5 ((,class :inherit modus-themes-heading-5)))
`(markdown-header-face-6 ((,class :inherit modus-themes-heading-6)))
`(markdown-header-rule-face ((,class :inherit bold :foreground ,fg-special-warm)))
+ `(markdown-highlighting-face ((,class :inherit modus-themes-refine-yellow)))
`(markdown-hr-face ((,class :inherit bold :foreground ,fg-special-warm)))
`(markdown-html-attr-name-face ((,class :inherit modus-themes-fixed-pitch
:foreground ,cyan)))
@@ -6237,6 +6235,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(markup-title-4-face ((,class :inherit modus-themes-heading-5)))
`(markup-title-5-face ((,class :inherit modus-themes-heading-6)))
`(markup-verbatim-face ((,class :inherit modus-themes-fixed-pitch :background ,bg-alt)))
+;;;;; mct
+ `(mct-highlight-candidate ((,class :inherit modus-themes-completion-selected)))
;;;;; mentor
`(mentor-download-message ((,class :foreground ,fg-special-warm)))
`(mentor-download-name ((,class :foreground ,fg-special-cold)))
@@ -6248,10 +6248,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(mentor-highlight-face ((,class :inherit modus-themes-subtle-blue)))
`(mentor-tracker-name ((,class :foreground ,magenta-alt)))
;;;;; messages
- `(message-cited-text-1 ((,class ,@(modus-themes--mail-cite blue-faint fg-alt))))
- `(message-cited-text-2 ((,class ,@(modus-themes--mail-cite green-faint fg-comment-yellow))))
- `(message-cited-text-3 ((,class ,@(modus-themes--mail-cite red-faint fg-special-cold))))
- `(message-cited-text-4 ((,class ,@(modus-themes--mail-cite yellow-faint fg-special-calm))))
+ `(message-cited-text-1 ((,class ,@(modus-themes--mail-cite blue-faint blue fg-special-cold))))
+ `(message-cited-text-2 ((,class ,@(modus-themes--mail-cite yellow-faint yellow yellow-alt-faint))))
+ `(message-cited-text-3 ((,class ,@(modus-themes--mail-cite magenta-alt-faint magenta-alt fg-special-calm))))
+ `(message-cited-text-4 ((,class ,@(modus-themes--mail-cite cyan-alt-other-faint cyan-alt-other fg-special-mild))))
`(message-header-cc ((,class :foreground ,blue-alt-other)))
`(message-header-name ((,class :inherit bold :foreground ,cyan)))
`(message-header-newsgroups ((,class :inherit message-header-other)))
@@ -6261,6 +6261,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(message-header-xheader ((,class :foreground ,blue-alt)))
`(message-mml ((,class :foreground ,cyan-alt-other)))
`(message-separator ((,class :inherit modus-themes-intense-neutral)))
+;;;;; mini-modeline
+ `(mini-modeline-mode-line ((,class :background ,blue-intense :height 0.14)))
+ `(mini-modeline-mode-line-inactive ((,class :background ,fg-window-divider-inner :height 0.1)))
;;;;; minimap
`(minimap-active-region-background ((,class :background ,bg-active)))
`(minimap-current-line-face ((,class :background ,cyan-intense-bg :foreground ,fg-main)))
@@ -6283,8 +6286,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
'alt-style bg-main))))
`(mode-line-active ((,class :inherit mode-line)))
`(mode-line-buffer-id ((,class :inherit bold)))
- `(mode-line-emphasis ((,class :inherit bold :foreground ,blue-active)))
- `(mode-line-highlight ((,class :inherit modus-themes-active-blue :box (:line-width -1 :style pressed-button))))
+ `(mode-line-emphasis ((,class :inherit bold :foreground ,magenta-active)))
+ `(mode-line-highlight ((,class ,@(if modus-themes-intense-mouseovers
+ (list :inherit 'modus-themes-active-blue)
+ (list :inherit 'highlight)))))
`(mode-line-inactive ((,class :inherit modus-themes-ui-variable-pitch
,@(modus-themes--mode-line-attrs
fg-inactive bg-inactive
@@ -6434,26 +6439,14 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(nxml-ref ((,class :inherit modus-themes-bold :foreground ,fg-special-mild)))
`(rng-error ((,class :inherit error)))
;;;;; orderless
- `(orderless-match-face-0 ((,class :inherit bold
- ,@(modus-themes--standard-completions
- blue-alt-other blue-nuanced-bg
- blue-refine-bg blue-refine-fg))))
- `(orderless-match-face-1 ((,class :inherit bold
- ,@(modus-themes--standard-completions
- magenta-alt magenta-nuanced-bg
- magenta-refine-bg magenta-refine-fg))))
- `(orderless-match-face-2 ((,class :inherit bold
- ,@(modus-themes--standard-completions
- green green-nuanced-bg
- green-refine-bg green-refine-fg))))
- `(orderless-match-face-3 ((,class :inherit bold
- ,@(modus-themes--standard-completions
- yellow yellow-nuanced-bg
- yellow-refine-bg yellow-refine-fg))))
+ `(orderless-match-face-0 ((,class :inherit modus-themes-completion-match-0)))
+ `(orderless-match-face-1 ((,class :inherit modus-themes-completion-match-1)))
+ `(orderless-match-face-2 ((,class :inherit modus-themes-completion-match-2)))
+ `(orderless-match-face-3 ((,class :inherit modus-themes-completion-match-3)))
;;;;; org
`(org-agenda-calendar-event ((,class ,@(modus-themes--agenda-event blue-alt))))
`(org-agenda-calendar-sexp ((,class ,@(modus-themes--agenda-event blue-alt t))))
- `(org-agenda-clocking ((,class :inherit modus-themes-special-cold :extend t)))
+ `(org-agenda-clocking ((,class :background ,yellow-nuanced-bg :foreground ,red-alt)))
`(org-agenda-column-dateline ((,class :background ,bg-alt)))
`(org-agenda-current-time ((,class :foreground ,blue-alt-other-faint)))
`(org-agenda-date ((,class ,@(modus-themes--agenda-date cyan fg-main))))
@@ -6484,22 +6477,16 @@ by virtue of calling either of `modus-themes-load-operandi' and
bg-dim fg-special-cold
bg-alt fg-alt))))
`(org-block-end-line ((,class :inherit org-block-begin-line)))
- `(org-checkbox ((,class :box (:line-width 1 :color ,bg-active)
- :background ,bg-inactive :foreground ,fg-active)))
+ `(org-checkbox (( )))
`(org-checkbox-statistics-done ((,class :inherit org-done)))
`(org-checkbox-statistics-todo ((,class :inherit org-todo)))
- `(org-clock-overlay ((,class :inherit modus-themes-special-cold)))
- `(org-code ((,class :inherit modus-themes-fixed-pitch
- ,@(modus-themes--markup fg-special-mild green-alt-other
- bg-alt green-nuanced-bg)
- :extend t)))
+ `(org-clock-overlay ((,class :background ,yellow-nuanced-bg :foreground ,red-alt-faint)))
+ `(org-code ((,class :inherit modus-themes-markup-code :extend t)))
`(org-column ((,class :inherit (modus-themes-fixed-pitch default)
:background ,bg-alt)))
`(org-column-title ((,class :inherit (bold modus-themes-fixed-pitch default)
:underline t :background ,bg-alt)))
- `(org-date ((,class :inherit ,(if modus-themes-mixed-fonts
- '(fixed-pitch modus-themes-link-symlink)
- 'modus-themes-link-symlink))))
+ `(org-date ((,class :inherit (modus-themes-link-symlink modus-themes-fixed-pitch))))
`(org-date-selected ((,class :foreground ,blue-alt :inverse-video t)))
`(org-dispatcher-highlight ((,class :inherit (bold modus-themes-mark-alt))))
`(org-document-info ((,class :foreground ,fg-special-cold)))
@@ -6515,7 +6502,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(org-habit-alert-face ((,class ,@(modus-themes--agenda-habit
yellow-graph-0-bg
yellow-graph-0-bg
- yellow-graph-1-bg))))
+ yellow-graph-1-bg)
+ :foreground "black"))) ; special case
`(org-habit-alert-future-face ((,class ,@(modus-themes--agenda-habit
yellow-graph-1-bg
yellow-graph-0-bg
@@ -6524,11 +6512,14 @@ by virtue of calling either of `modus-themes-load-operandi' and
blue-graph-0-bg
green-graph-1-bg
blue-graph-1-bg
- blue-graph-1-bg))))
+ blue-graph-1-bg
+ blue-graph-1-bg)
+ :foreground "black"))) ; special case
`(org-habit-clear-future-face ((,class ,@(modus-themes--agenda-habit
blue-graph-1-bg
green-graph-1-bg
blue-graph-1-bg
+ blue-graph-1-bg
blue-graph-1-bg))))
`(org-habit-overdue-face ((,class ,@(modus-themes--agenda-habit
red-graph-0-bg
@@ -6542,18 +6533,23 @@ by virtue of calling either of `modus-themes-load-operandi' and
green-graph-0-bg
green-graph-0-bg
green-graph-1-bg
- blue-graph-0-bg))))
+ cyan-graph-0-bg
+ blue-graph-0-bg
+ cyan-graph-1-bg)
+ :foreground "black"))) ; special case
`(org-habit-ready-future-face ((,class ,@(modus-themes--agenda-habit
green-graph-1-bg
green-graph-0-bg
green-graph-1-bg
- blue-graph-0-bg))))
+ cyan-graph-1-bg
+ blue-graph-0-bg
+ cyan-graph-1-bg))))
`(org-headline-done ((,class :inherit (modus-themes-variable-pitch modus-themes-grue-nuanced))))
`(org-headline-todo ((,class :inherit modus-themes-variable-pitch :foreground ,red-nuanced-fg)))
`(org-hide ((,class :foreground ,bg-main)))
`(org-indent ((,class :inherit (fixed-pitch org-hide))))
`(org-imminent-deadline ((,class :foreground ,red-intense)))
- `(org-latex-and-related ((,class :foreground ,magenta-refine-fg)))
+ `(org-latex-and-related ((,class :foreground ,magenta-faint)))
`(org-level-1 ((,class :inherit modus-themes-heading-1)))
`(org-level-2 ((,class :inherit modus-themes-heading-2)))
`(org-level-3 ((,class :inherit modus-themes-heading-3)))
@@ -6564,9 +6560,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(org-level-8 ((,class :inherit modus-themes-heading-8)))
`(org-link ((,class :inherit button)))
`(org-list-dt ((,class :inherit bold)))
- `(org-macro ((,class :inherit modus-themes-fixed-pitch
- ,@(modus-themes--markup cyan-nuanced-fg cyan
- cyan-nuanced-bg cyan-nuanced-bg))))
+ `(org-macro ((,class :inherit modus-themes-markup-macro)))
`(org-meta-line ((,class :inherit (shadow modus-themes-fixed-pitch))))
`(org-mode-line-clock ((,class :foreground ,fg-main)))
`(org-mode-line-clock-overrun ((,class :inherit bold :foreground ,red-active)))
@@ -6701,15 +6695,15 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(pomidor-work-face ((,class :inherit modus-themes-grue)))
;;;;; popup
`(popup-face ((,class :background ,bg-alt :foreground ,fg-main)))
- `(popup-isearch-match ((,class :inherit (modus-themes-refine-cyan bold))))
- `(popup-menu-mouse-face ((,class :inherit modus-themes-intense-blue)))
- `(popup-menu-selection-face ((,class :inherit (modus-themes-subtle-cyan bold))))
+ `(popup-isearch-match ((,class :inherit (modus-themes-search-success bold))))
+ `(popup-menu-mouse-face ((,class :inherit highlight)))
+ `(popup-menu-selection-face ((,class :inherit modus-themes-completion-selected-popup)))
`(popup-scroll-bar-background-face ((,class :background ,bg-active)))
`(popup-scroll-bar-foreground-face ((,class :foreground ,fg-active)))
`(popup-summary-face ((,class :background ,bg-active :foreground ,fg-inactive)))
`(popup-tip-face ((,class :inherit modus-themes-refine-yellow)))
;;;;; powerline
- `(powerline-active0 ((,class :background ,bg-main :foreground ,blue-faint :inverse-video t)))
+ `(powerline-active0 ((,class :background ,blue-faint :foreground ,bg-main)))
`(powerline-active1 ((,class :background ,blue-nuanced-bg :foreground ,blue-nuanced-fg)))
`(powerline-active2 ((,class :background ,bg-active :foreground ,fg-active)))
`(powerline-inactive0 ((,class :background ,bg-special-cold :foreground ,fg-special-cold)))
@@ -6734,6 +6728,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(prodigy-yellow-face ((,class :inherit warning)))
;;;;; pulse
`(pulse-highlight-start-face ((,class :background ,bg-active-accent :extend t)))
+;;;;; pyim
+ `(pyim-page ((,class :background ,bg-active :foreground ,fg-active)))
+ `(pyim-page-selection ((,class :inherit bold :background ,bg-active :foreground ,blue-active)))
+ `(pyim-page-subword ((,class :background ,bg-inactive)))
;;;;; quick-peek
`(quick-peek-background-face ((,class :background ,bg-alt)))
`(quick-peek-border-face ((,class :background ,fg-window-divider-inner :height 1)))
@@ -6834,27 +6832,15 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(ruler-mode-pad ((,class :inherit ruler-mode-default :background ,bg-active :foreground ,fg-inactive)))
`(ruler-mode-tab-stop ((,class :inherit ruler-mode-default :foreground ,fg-special-warm)))
;;;;; selectrum
- `(selectrum-current-candidate
- ((,class :inherit bold :foreground ,fg-main
- :background ,@(pcase modus-themes-completions
- ('opinionated (list bg-active))
- (_ (list bg-inactive))))))
+ `(selectrum-current-candidate ((,class :inherit modus-themes-completion-selected)))
`(selectrum-mouse-highlight ((,class :inherit highlight)))
`(selectrum-quick-keys-highlight
((,class :inherit modus-themes-refine-red)))
`(selectrum-quick-keys-match
((,class :inherit (bold modus-themes-search-success))))
;;;;; selectrum-prescient
- `(selectrum-prescient-primary-highlight
- ((,class :inherit bold
- ,@(modus-themes--standard-completions
- magenta-alt magenta-nuanced-bg
- magenta-refine-bg magenta-refine-fg))))
- `(selectrum-prescient-secondary-highlight
- ((,class :inherit bold
- ,@(modus-themes--standard-completions
- cyan-alt-other cyan-nuanced-bg
- cyan-refine-bg cyan-refine-fg))))
+ `(selectrum-prescient-primary-highlight ((,class :inherit modus-themes-completion-match-0)))
+ `(selectrum-prescient-secondary-highlight ((,class :inherit modus-themes-completion-match-1)))
;;;;; semantic
`(semantic-complete-inline-face ((,class :foreground ,fg-special-warm :underline t)))
`(semantic-decoration-on-fileless-includes ((,class :inherit modus-themes-refine-green)))
@@ -6886,13 +6872,14 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(show-paren-match-expression ((,class :background ,bg-paren-expression)))
`(show-paren-mismatch ((,class :inherit modus-themes-intense-red)))
;;;;; shr
+ `(shr-abbreviation ((,class :inherit modus-themes-lang-note)))
+ `(shr-code ((,class :inherit modus-themes-markup-verbatim)))
`(shr-h1 ((,class :inherit modus-themes-heading-1)))
`(shr-h2 ((,class :inherit modus-themes-heading-2)))
`(shr-h3 ((,class :inherit modus-themes-heading-3)))
`(shr-h4 ((,class :inherit modus-themes-heading-4)))
`(shr-h5 ((,class :inherit modus-themes-heading-5)))
`(shr-h6 ((,class :inherit modus-themes-heading-6)))
- `(shr-abbreviation ((,class :inherit modus-themes-lang-note)))
`(shr-selected-link ((,class :inherit modus-themes-subtle-red)))
;;;;; side-notes
`(side-notes ((,class :background ,bg-dim :foreground ,fg-dim)))
@@ -6903,6 +6890,33 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(sieve-test-commands ((,class :inherit font-lock-function-name-face)))
;;;;; skewer-mode
`(skewer-error-face ((,class :foreground ,red :underline t)))
+;;;;; slime (sldb)
+ `(sldb-condition-face ((,class :inherit font-lock-preprocessor-face)))
+ `(sldb-restart-number-face ((,class :inherit bold)))
+ `(sldb-restart-type-face ((,class :inherit font-lock-type-face)))
+ `(sldb-restartable-frame-line-face ((,class :inherit success)))
+ `(sldb-section-face ((,class :inherit modus-themes-pseudo-header)))
+ `(slime-error-face ((,class :inherit modus-themes-lang-error)))
+ `(slime-note-face ((,class :underline t)))
+ `(slime-repl-input-face ((,class :inherit bold)))
+ `(slime-repl-inputed-output-face ((,class :inherit font-lock-string-face)))
+ `(slime-repl-output-mouseover-face ((,class :inherit highlight)))
+ `(slime-repl-prompt-face ((,class :inherit modus-themes-prompt)))
+ `(slime-style-warning-face ((,class :inherit modus-themes-lang-note)))
+ `(slime-warning-face ((,class :inherit modus-themes-lang-warning)))
+;;;;; sly
+ `(sly-action-face ((,class :inherit font-lock-type-face)))
+ `(sly-db-condition-face ((,class :inherit font-lock-preprocessor-face)))
+ `(sly-db-restartable-frame-line-face ((,class :inherit success)))
+ `(sly-error-face ((,class :inherit modus-themes-lang-error)))
+ `(sly-mode-line ((,class :inherit mode-line-emphasis)))
+ `(sly-mrepl-output-face ((,class :inherit font-lock-string-face)))
+ `(sly-mrepl-output-face ((,class :inherit font-lock-string-face)))
+ `(sly-mrepl-prompt-face ((,class :inherit modus-themes-prompt)))
+ `(sly-note-face ((,class :inherit modus-themes-lang-note)))
+ `(sly-stickers-placed-face ((,class :inherit modus-themes-subtle-neutral)))
+ `(sly-style-warning-face ((,class :inherit modus-themes-lang-note)))
+ `(sly-warning-face ((,class :inherit modus-themes-lang-warning)))
;;;;; smart-mode-line
`(sml/charging ((,class :foreground ,green-active)))
`(sml/discharging ((,class :foreground ,red-active)))
@@ -6984,15 +6998,15 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(switch-window-background ((,class :background ,bg-dim)))
`(switch-window-label ((,class :height 3.0 :foreground ,blue-intense)))
;;;;; swiper
- `(swiper-background-match-face-1 ((,class :inherit modus-themes-subtle-neutral)))
- `(swiper-background-match-face-2 ((,class :inherit modus-themes-refine-cyan)))
- `(swiper-background-match-face-3 ((,class :inherit modus-themes-refine-magenta)))
- `(swiper-background-match-face-4 ((,class :inherit modus-themes-refine-yellow)))
- `(swiper-line-face ((,class :inherit modus-themes-special-cold)))
- `(swiper-match-face-1 ((,class :inherit (bold modus-themes-intense-neutral))))
- `(swiper-match-face-2 ((,class :inherit (bold modus-themes-intense-green))))
- `(swiper-match-face-3 ((,class :inherit (bold modus-themes-intense-blue))))
- `(swiper-match-face-4 ((,class :inherit (bold modus-themes-intense-red))))
+ `(swiper-background-match-face-1 (( )))
+ `(swiper-background-match-face-2 ((,class :inherit modus-themes-completion-match-0)))
+ `(swiper-background-match-face-3 ((,class :inherit modus-themes-completion-match-1)))
+ `(swiper-background-match-face-4 ((,class :inherit modus-themes-completion-match-2)))
+ `(swiper-line-face ((,class :background ,bg-hl-alt-intense)))
+ `(swiper-match-face-1 (( )))
+ `(swiper-match-face-2 ((,class :inherit modus-themes-completion-match-0)))
+ `(swiper-match-face-3 ((,class :inherit modus-themes-completion-match-1)))
+ `(swiper-match-face-4 ((,class :inherit modus-themes-completion-match-2)))
;;;;; sx
`(sx-inbox-item-type ((,class :foreground ,magenta-alt-other)))
`(sx-inbox-item-type-unread ((,class :inherit (sx-inbox-item-type bold))))
@@ -7082,6 +7096,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(telega-entity-type-code ((,class :inherit modus-themes-fixed-pitch)))
`(telega-entity-type-mention ((,class :foreground ,cyan)))
`(telega-entity-type-pre ((,class :inherit modus-themes-fixed-pitch)))
+ `(telega-entity-type-spoiler ((,class :background ,fg-main :foreground ,fg-main)))
`(telega-msg-heading ((,class :background ,bg-alt)))
`(telega-msg-self-title ((,class :inherit bold)))
`(telega-root-heading ((,class :inherit modus-themes-subtle-neutral)))
@@ -7128,6 +7143,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(term-color-white ((,class :background "gray65" :foreground "gray65")))
`(term-color-yellow ((,class :background ,yellow :foreground ,yellow)))
`(term-underline ((,class :underline t)))
+;;;;; textsec
+ `(textsec-suspicious ((,class :inherit modus-themes-refine-red)))
;;;;; tomatinho
`(tomatinho-ok-face ((,class :foreground ,blue-intense)))
`(tomatinho-pause-face ((,class :foreground ,yellow-intense)))
@@ -7135,7 +7152,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
;;;;; transient
`(transient-active-infix ((,class :inherit modus-themes-special-mild)))
`(transient-amaranth ((,class :inherit bold :foreground ,yellow-alt)))
- `(transient-argument ((,class :inherit bold :foreground ,green)))
+ ;; Placate the compiler for what is a spurious warning. We also
+ ;; have to do this with `eldoc-highlight-function-argument'.
+ (list 'transient-argument `((,class :inherit bold :background ,cyan-nuanced-bg :foreground ,cyan)))
`(transient-blue ((,class :inherit bold :foreground ,blue)))
`(transient-disabled-suffix ((,class :inherit modus-themes-intense-red)))
`(transient-enabled-suffix ((,class :inherit modus-themes-grue-background-subtle)))
@@ -7146,11 +7165,12 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(transient-mismatched-key ((,class :underline t)))
`(transient-nonstandard-key ((,class :underline t)))
`(transient-pink ((,class :inherit bold :foreground ,magenta-alt-faint)))
+ `(transient-purple ((,class :inherit bold :foreground ,magenta-alt-other)))
`(transient-red ((,class :inherit bold :foreground ,red-faint)))
`(transient-teal ((,class :inherit bold :foreground ,cyan-alt-other)))
- `(transient-unreachable ((,class :foreground ,fg-unfocused)))
- `(transient-unreachable-key ((,class :foreground ,fg-unfocused)))
- `(transient-value ((,class :inherit bold :foreground ,magenta-alt-other)))
+ `(transient-unreachable ((,class :inherit shadow)))
+ `(transient-unreachable-key ((,class :inherit shadow)))
+ `(transient-value ((,class :inherit bold :background ,yellow-nuanced-bg :foreground ,yellow-alt-other)))
;;;;; trashed
`(trashed-deleted ((,class :inherit modus-themes-mark-del)))
`(trashed-directory ((,class :foreground ,blue)))
@@ -7158,6 +7178,24 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(trashed-marked ((,class :inherit modus-themes-mark-alt)))
`(trashed-restored ((,class :inherit modus-themes-mark-sel)))
`(trashed-symlink ((,class :inherit modus-themes-link-symlink)))
+;;;;; tree-sitter
+ `(tree-sitter-hl-face:attribute ((,class :inherit font-lock-variable-name-face)))
+ `(tree-sitter-hl-face:constant.builtin ((,class :inherit tree-sitter-hl-face:constant)))
+ `(tree-sitter-hl-face:escape ((,class :inherit font-lock-regexp-grouping-backslash)))
+ `(tree-sitter-hl-face:function ((,class :inherit font-lock-function-name-face)))
+ `(tree-sitter-hl-face:function.call ((,class :inherit tree-sitter-hl-face:function)))
+ `(tree-sitter-hl-face:label (( )))
+ `(tree-sitter-hl-face:method.call (( )))
+ `(tree-sitter-hl-face:operator ((,class :inherit modus-themes-bold)))
+ `(tree-sitter-hl-face:property (( )))
+ `(tree-sitter-hl-face:property.definition ((,class :inherit font-lock-variable-name-face)))
+ `(tree-sitter-hl-face:punctuation (( )))
+ `(tree-sitter-hl-face:punctuation.bracket (( )))
+ `(tree-sitter-hl-face:punctuation.delimiter (( )))
+ `(tree-sitter-hl-face:punctuation.special ((,class :inherit font-lock-regexp-grouping-construct)))
+ `(tree-sitter-hl-face:string.special ((,class :inherit tree-sitter-hl-face:string)))
+ `(tree-sitter-hl-face:tag ((,class :inherit font-lock-function-name-face)))
+ `(tree-sitter-hl-face:type.argument (( )))
;;;;; treemacs
`(treemacs-directory-collapsed-face ((,class :foreground ,magenta-alt)))
`(treemacs-directory-face ((,class :inherit dired-directory)))
@@ -7237,13 +7275,10 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(vc-state-base ((,class :foreground ,fg-active)))
`(vc-up-to-date-state ((,class :foreground ,fg-special-cold)))
;;;;; vertico
- `(vertico-current ((,class :inherit bold :foreground ,fg-main
- :background ,@(pcase modus-themes-completions
- ('opinionated (list bg-active))
- (_ (list bg-inactive))))))
+ `(vertico-current ((,class :inherit modus-themes-completion-selected)))
;;;;; vertico-quick
- `(vertico-quick1 ((,class :inherit (modus-themes-intense-magenta bold))))
- `(vertico-quick2 ((,class :inherit (modus-themes-refine-cyan bold))))
+ `(vertico-quick1 ((,class :inherit bold :background ,bg-char-0)))
+ `(vertico-quick2 ((,class :inherit bold :background ,bg-char-1)))
;;;;; vimish-fold
`(vimish-fold-fringe ((,class :foreground ,cyan-active)))
`(vimish-fold-mouse-face ((,class :inherit modus-themes-intense-blue)))
@@ -7273,6 +7308,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(vterm-color-underline ((,class :foreground ,fg-special-warm :underline t)))
`(vterm-color-white ((,class :background "gray65" :foreground "gray65")))
`(vterm-color-yellow ((,class :background ,yellow :foreground ,yellow)))
+;;;;; vundo
+ `(vundo-highlight ((,class :inherit (bold vundo-node) :foreground ,red-intense)))
;;;;; wcheck-mode
`(wcheck-default-face ((,class :foreground ,red :underline t)))
;;;;; web-mode
@@ -7365,7 +7402,7 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(which-key-local-map-description-face ((,class :foreground ,fg-main)))
`(which-key-note-face ((,class :foreground ,fg-special-warm)))
`(which-key-separator-face ((,class :inherit shadow)))
- `(which-key-special-key-face ((,class :inherit bold :foreground ,orange-intense)))
+ `(which-key-special-key-face ((,class :inherit bold :foreground ,red-alt)))
;;;;; whitespace-mode
`(whitespace-big-indent ((,class :inherit modus-themes-subtle-red)))
`(whitespace-empty ((,class :inherit modus-themes-intense-magenta)))
@@ -7390,9 +7427,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(writegood-weasels-face ((,class :inherit modus-themes-lang-error)))
;;;;; woman
`(woman-addition ((,class :foreground ,magenta-alt-other)))
- `(woman-bold ((,class :inherit bold :foreground ,magenta)))
- `(woman-italic ((,class :inherit italic :foreground ,cyan)))
- `(woman-unknown ((,class :inherit italic :foreground ,yellow)))
+ `(woman-bold ((,class :inherit bold :foreground ,fg-special-calm)))
+ `(woman-unknown ((,class :foreground ,cyan)))
;;;;; xah-elisp-mode
`(xah-elisp-at-symbol ((,class :inherit font-lock-warning-face)))
`(xah-elisp-cap-variable ((,class :inherit font-lock-preprocessor-face)))
@@ -7435,6 +7471,9 @@ by virtue of calling either of `modus-themes-load-operandi' and
`(flymake-error-bitmap '(flymake-double-exclamation-mark modus-themes-fringe-red))
`(flymake-warning-bitmap '(exclamation-mark modus-themes-fringe-yellow))
`(flymake-note-bitmap '(exclamation-mark modus-themes-fringe-cyan))
+;;;; highlight-changes
+ `(highlight-changes-colors nil)
+ `(highlight-changes-face-list '(success warning error bold bold-italic))
;;;; ibuffer
`(ibuffer-deletion-face 'modus-themes-mark-del)
`(ibuffer-filter-group-name-face 'modus-themes-pseudo-header)
@@ -7460,6 +7499,8 @@ by virtue of calling either of `modus-themes-load-operandi' and
("XXX+" . ,red-alt)
("REVIEW" . ,cyan-alt-other)
("DEPRECATED" . ,blue-nuanced-fg)))
+;;;; mini-modeline
+ `(mini-modeline-face-attr '(:background unspecified))
;;;; pdf-tools
`(pdf-view-midnight-colors
'(,fg-main . ,bg-dim))
@@ -7486,6 +7527,20 @@ by virtue of calling either of `modus-themes-load-operandi' and
(340 . ,blue-alt-other)
(360 . ,magenta-alt-other)))
`(vc-annotate-very-old-color nil)
+;;;; wid-edit
+ `(widget-link-prefix ,(if (memq 'all-buttons modus-themes-box-buttons)
+ " "
+ "["))
+ `(widget-link-suffix ,(if (memq 'all-buttons modus-themes-box-buttons)
+ " "
+ "]"))
+ `(widget-mouse-face '(highlight widget-button))
+ `(widget-push-button-prefix ,(if (memq 'all-buttons modus-themes-box-buttons)
+ " "
+ "["))
+ `(widget-push-button-suffix ,(if (memq 'all-buttons modus-themes-box-buttons)
+ " "
+ "]"))
;;;; xterm-color
`(xterm-color-names ["black" ,red ,green ,yellow ,blue ,magenta ,cyan "gray65"])
`(xterm-color-names-bright ["gray35" ,red-alt ,green-alt ,yellow-alt ,blue-alt ,magenta-alt ,cyan-alt "white"])
@@ -7520,9 +7575,4 @@ by virtue of calling either of `modus-themes-load-operandi' and
(add-to-list 'custom-theme-load-path dir))))
(provide 'modus-themes)
-
-;; Local Variables:
-;; time-stamp-pattern: "Last-Modified: <%Y-%02m-%02d %02H:%02M:%02S %5z>"
-;; End:
-
;;; modus-themes.el ends here
diff --git a/etc/themes/modus-vivendi-theme.el b/etc/themes/modus-vivendi-theme.el
index 738753741cf..fe52aefc84d 100644
--- a/etc/themes/modus-vivendi-theme.el
+++ b/etc/themes/modus-vivendi-theme.el
@@ -1,10 +1,10 @@
-;;; modus-vivendi-theme.el --- Accessible dark theme (WCAG AAA) -*- lexical-binding:t -*-
+;;; modus-vivendi-theme.el --- Elegant, highly legible and customizable light theme -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
-;; URL: https://gitlab.com/protesilaos/modus-themes
-;; Version: 2.0.0
+;; URL: https://git.sr.ht/~protesilaos/modus-themes
+;; Version: 2.4.1
;; Package-Requires: ((emacs "27.1"))
;; Keywords: faces, theme, accessibility
@@ -56,17 +56,17 @@
(equal (file-name-directory load-file-name)
(expand-file-name "themes/" data-directory))
(require-theme 'modus-themes t))
- (require 'modus-themes)))
+ (require 'modus-themes))
-(deftheme modus-vivendi
- "Accessible and customizable dark theme (WCAG AAA standard).
+ (deftheme modus-vivendi
+ "Elegant, highly legible and customizable dark theme.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1.")
+7:1 (WCAG AAA standard).")
-(modus-themes-theme modus-vivendi)
+ (modus-themes-theme modus-vivendi)
-(provide-theme 'modus-vivendi)
+ (provide-theme 'modus-vivendi))
;;; modus-vivendi-theme.el ends here
diff --git a/etc/tutorials/TUTORIAL.cn b/etc/tutorials/TUTORIAL.cn
index 5d03014e41a..770d9a83be3 100644
--- a/etc/tutorials/TUTORIAL.cn
+++ b/etc/tutorials/TUTORIAL.cn
@@ -905,6 +905,15 @@ Dired 能够在一个缓冲区里列出一个目录下的所有文件(可以
Emacs 使用手册里还有许许多多的精彩功能等着你来了解。
+* 安装包裹(INSTALLING PACKAGES)
+---------------------------
+
+Emacs 社区著作了许多持有扩展性的包裹(packages),其中包括对各种语言的
+支持、色彩鲜艳的主题、用于集成外部程序的包裹,等等。
+
+使用 M-x list-packages 便可浏览存在的包裹。这个命令显示的界面中可以安
+装和卸载包裹,以及查看包裹的简介。Emacs 使用手册中有对包裹管理更详细的
+介绍。
* 总结(CONCLUSION)
--------------------
diff --git a/etc/tutorials/TUTORIAL.el_GR b/etc/tutorials/TUTORIAL.el_GR
new file mode 100644
index 00000000000..88d9712b8e5
--- /dev/null
+++ b/etc/tutorials/TUTORIAL.el_GR
@@ -0,0 +1,1267 @@
+Εκμάθηση του Emacs. Δες το τέλος για όρους αντιγραφής.
+
+Στο Emacs οι εντολές γενικά περιλαμβάνουν το πλήκτρο CONTROL (συχνά
+αναγράφεται ως Ctrl) ή το πλήκτρο META (συνήθως επισημαίνεται ως ALT).
+Αντί να γράφουμε το πλήρες όνομα κάθε φορά, θα χρησιμοποιούμε τις εξής
+συντομογραφίες:
+
+ C-<χαρ> σημαίνει κράτα πατημένο το πλήκτρο CONTROL καθώς
+ πληκτρολογείς τον χαρακτήρα <χάρ>. Συνεπώς, C-f είναι:
+ κράτα πατημένο το CONTROL και πληκτρολόγησε το f.
+ M-<χαρ> σημαίνει κράτα πατημένο το πλήκτρο META ή ALT καθώς
+ πληκτρολογείς τον χαρακτήρα <χάρ>. Σε περίπτωση που δεν
+ υπάρχει πλήκτρο META ή ALT, πληκτρολόγησε και απελευθέρωσε
+ το πλήκτρο ESC και κατόπιν πληκτρολόγησε τον <χάρ>.
+ Γράφουμε <ESC> για το πλήκτρο ESC.
+
+Σημαντική σημείωση: για να τερματίσεις το Emacs, πληκτρολόγησε C-x
+C-c. (Δύο χαρακτήρες.) Για να ακυρώσεις μια μερικώς πληκτρολογημένη
+εντολή, πληκτρολόγησε C-g.
+Για να σταματήσεις την εκμάθηση, πληκτρολόγησε C-x k, κατόπιν <Return>
+στην προτροπή.
+Οι χαρακτήρες ">>" στο αριστερό περιθώριο δείχνουν οδηγίες για να
+δοκιμάσεις μια εντολή. Για παράδειγμα:
+<<Blank lines inserted around following line by help-with-tutorial>>
+[Κενό για διδακτικούς σκοπούς. Το κείμενο συνεχίζεται παρακάτω.]
+
+>> Τώρα πληκτρολόγησε C-v (δες επόμενη οθόνη) ώστε να κυλήσεις πιο
+ κάτω στην παρούσα εκμάθηση. (Κάνε το, κρατώντας πατημένο το
+ πλήκτρο CONTROL και πληκτρολογώντας v.) Από εδώ και στο εξής,
+ παρακαλώ κάνε αυτό όποτε φτάνεις στο τέλος της οθόνης.
+
+Σημείωσε πως υπάρχει επικάλυψη δύο γραμμών όταν κυλάς μια πλήρη οθόνη:
+αυτή σου προσφέρει κάποια συνέχεια ώστε να συνεχίσεις να διαβάζεις το
+κείμενο.
+
+Αυτό είναι αντίγραφο του κειμένου εκμάθησης του Emacs, ελαφρά
+τροποποιημένο για εσένα. Παρακάτω θα σου αναθέσουμε να δοκιμάσεις
+μερικές εντολές που τροποποιούν το εν λόγω κείμενο. Μην ανησυχείς αν
+τροποποιήσεις αυτό το κείμενο πριν σου το ζητήσουμε· η πράξη αυτή
+αναφέρεται ως «επεξεργασία» και το Emacs χρησιμοποιείται για αυτόν τον
+σκοπό.
+
+Το πρώτο πράγμα που πρέπει να γνωρίζεις είναι πως να κινείσαι από το
+ένα σημείο σε άλλο σημείο του κειμένου. Ήδη ξέρεις πως να πηγαίνεις
+μια οθόνη προς τα κάτω με το C-v. Για να κινηθείς αντίστροφα,
+πληκτρολόγησε M-v (κράτα πατημένο το META και πληκτρολόγησε το v, ή
+πληκτρολόγησε <ESC>v εάν δεν έχει πλήκτρο META ή ALT).
+
+>> Δοκίμασε να πληκτρολογήσεις M-v και μετά C-v μερικές φορές.
+
+Είναι αποδεκτό να κυλήσεις το κείμενο με άλλους τρόπους, αν τους
+ξέρεις.
+
+* ΣΥΝΟΨΗ
+--------
+
+Οι εξής εντολές είναι χρήσιμες για να βλέπεις πλήρης οθόνες:
+
+ C-v Κινήσου μπροστά/κάτω μια πλήρη οθόνη
+ M-v Κινήσου πίσω/πάνω μια πλήρη οθόνη
+
+ C-l Καθάρισε την οθόνη επανεμφανίζοντας το κείμενο της και
+ μεταφέροντας τον δείκτη (κέρσορα) στο κέντρο της.
+ (Αυτό είναι CONTROL-L, όχι CONTROL-1.)
+
+>> Εντόπισε τον δείκτη και σημείωσε το κείμενο πέριξ του. Μετά
+ πληκτρολόγησε C-l. Ξαναβρές τον δείκτη και παρατήρησε το κείμενο
+ δίπλα του, αλλά τώρα πρόσεξε πως βρίσκεται στο κέντρο της οθόνης.
+ Εάν πατήσεις C-l πάλι, το κείμενο αυτό θα μετατοπιστεί στο πάνω
+ μέρος της οθόνης. Πάτα το C-l ξανά και θα πάει στο κάτω μέρος.
+
+Μπορείς επίσης να χρησιμοποιήσεις τα πλήκτρα PageUp και PageDn για να
+κινηθείς ανά πλήρη οθόνη, εάν ο ακροδέκτης (τερματικό) σου τα έχει,
+ωστόσο είναι πιο αποτελεσματικό να χρησιμοποιείς τα C-v και M-v.
+
+
+* ΒΑΣΙΚΟΣ ΕΛΕΓΧΟΣ ΤΟΥ ΔΕΙΚΤΗ
+----------------------------
+
+Η κίνηση ανά πλήρη οθόνη είναι χρήσιμη, αλλά πως θα πας σε
+συγκεκριμένο σημείο εντός του κειμένου της οθόνης;
+
+Υπάρχουν πολλοί τρόποι να το επιτύχεις αυτό. Μπορείς να
+χρησιμοποιήσεις τα πλήκτρα με τα βέλη, αλλά είναι πιο αποτελεσματικό
+να κρατήσεις τα χέρια σου στην κανονική θέση και να χρησιμοποιήσεις
+τις εντολές C-p, C-b, C-f, και C-n. Οι χαρακτήρες αυτοί είναι το
+αντίστοιχο των τεσσάρων πλήκτρων με τα βέλη, κατά αυτόν τον τρόπο:
+
+ Προηγούμενη γραμμή, C-p
+ :
+ :
+ Πίσω, C-b .... Παρούσα θέση του δείκτη .... Εμπρός, C-f
+ :
+ :
+ Επόμενη γραμμή, C-n
+
+>> Μετακίνησε τον δείκτη στη μέση του διαγράμματος αυτού
+ χρησιμοποιώντας C-n ή C-p. Μετά πληκτρολόγησε C-l για να δεις το
+ όλο διάγραμμα στο κέντρο της οθόνης.
+
+Θα σου είναι ευκολότερο να θυμάσαι αυτά τα γράμματα από τις λέξεις τις
+οποίες αναφέρουν στην Αγγλική: P για προηγούμενο (previous), N για
+επόμενο (next), B για πίσω (backward), και F για εμπρός (forward). Θα
+χρησιμοποιείς διαρκώς αυτές τις βασικές εντολές για την τοποθέτηση του
+δείκτη.
+
+>> Κάνε μερικά C-n μέχρι να φέρεις τον δείκτη σε αυτή την γραμμή.
+
+>> Κινήσου εντός της γραμμής με μερικά C-f και μετά πάνω με κάποια
+ C-p. Δες τι κάνει το C-p όταν βρίσκεται στην μέση της γραμμής.
+
+Κάθε γραμμή κειμένου τελειώνει με τον χαρακτήρα νέας γραμμής, που
+επιτελεί τον σκοπό του διαχωρισμού της μίας γραμμής από την άλλη.
+(Συνήθως η τελευταία γραμμή σε ένα αρχείο τελειώνει με τον χαρακτήρα
+νέας γραμμής, ωστόσο το Emacs δεν απαιτεί κάτι τέτοιο.)
+
+>> Δοκίμασε το C-b στην αρχή της γραμμής. Θα μετακινήσει τον δείκτη
+ στο τέλος της προηγούμενης γραμμής. Διότι κινείται προς τα πίσω
+ προσπερνώντας τον χαρακτήρα νέας γραμμής.
+
+Το C-f έχει την ίδια συμπεριφορά με το C-b.
+
+>> Κάνε μερικά ακόμα C-b, ώστε να εντοπίσεις τον δείκτη. Κατόπιν
+ κάνε C-f για να γυρίσεις στο τέλος της γραμμής. Μετά ένα ακόμα C-f
+ για να κινηθείς στην αρχή της επόμενης γραμμής.
+
+Όταν κινείσαι πέρα από το πάνω ή κάτω μέρος της οθόνης, το κείμενο
+πέραν της άκρης μετατοπίζεται εντός της οθόνης. Αυτό ονομάζεται
+«κύλιση». Επιτρέπει στο Emacs να φέρει τον δείκτη στο ορισμένο
+σημείο του κειμένου χωρίς να κινηθεί εκτός της οθόνης.
+
+>> Δοκίμασε να κινήσεις τον δείκτη πέρα από το κάτω μέρος της οθόνης
+ με το C-n και δες τι συμβαίνει.
+
+Εάν η κίνηση ανά χαρακτήρα είναι πολύ αργή, μπορείς να κινηθείς ανά
+λέξη. Το M-f (META-f) πάει μπροστά μια λέξη και M-b πίσω μια λέξη.
+
+>> Πληκτρολόγησε μερικά M-f και M-b.
+
+Όταν βρίσκεσαι στο μέσο μιας λέξης, το M-f πηγαίνει στο τέλος της.
+Όταν βρίσκεσαι σε κενό μεταξύ λέξεων, το M-f κινείται στο τέλος της
+ακόλουθης λέξης. Το M-b λειτουργεί αναλόγως προς την αντίθετη
+κατεύθυνση.
+
+>> Πληκτρολόγησε M-f και M-b μερικές φορές, με C-f και C-b μεταξύ τους
+ ώστε να παρατηρήσεις την δράση των M-f και M-b σε διάφορα σημεία
+ εντός και μεταξύ λέξεων.
+
+Παρατήρησε την παράλληλο μεταξύ C-f και C-b από την μία, και M-f και
+M-b από την άλλη. Πολύ συχνά οι Meta χαρακτήρες χρησιμοποιούνται για
+πράξεις που σχετίζονται με μονάδες που ορίζει η εκάστοτε γλώσσα
+(λέξεις, προτάσεις, παραγράφους), ενώ οι Control χαρακτήρες επιδρούν
+σε βασικά στοιχεία που είναι ανεξάρτητα του τι επεξεργάζεσαι
+(χαρακτήρες, γραμμές, κτλ.).
+
+Αυτή η παράλληλος ισχύει μεταξύ γραμμών και προτάσεων. C-a και C-e
+πηγαίνουν στην αρχή και το τέλος της γραμμής, ενώ M-a και M-e
+πηγαίνουν στην αρχή και το τέλος της πρότασης.
+
+>> Δοκίμασε δύο C-a και ύστερα δύο C-e.
+ Δοκίμασε δύο M-a και ύστερα δύο M-e.
+
+Παρατήρησε πως αλλεπάλληλα C-a δεν κάνουν τίποτα, ενώ επανειλημμένα
+M-a συνεχίζουν να κινούνται ανά μία πρόταση. Παρότι δεν είναι
+ανάλογα, το καθένα φαντάζει φυσικό.
+
+Η θέση του δείκτη εντός του κειμένου ονομάζεται «σημείο» (point). Με
+άλλα λόγια, ο δείκτης δείχνει που βρίσκεται το σημείο εντός του
+κειμένου στην οθόνη.
+
+Ιδού μία σύνοψη των απλών κινήσεων του δείκτη, συμπεριλαμβανομένων
+των εντολών για κίνηση ανά λέξη και πρόταση:
+
+ C-f Κινήσου εμπρός ένα χαρακτήρα
+ C-b Κινήσου πίσω ένα χαρακτήρα
+
+ M-f Κινήσου εμπρός μία λέξη
+ M-b Κινήσου πίσω μία λέξη
+
+ C-n Κινήσου στην επόμενη γραμμή
+ C-p Κινήσου στην προηγούμενη γραμμή
+
+ C-a Κινήσου στην αρχή της γραμμής
+ C-e Κινήσου στο τέλος της γραμμής
+
+ M-a Κινήσου πίσω στην αρχή της πρότασης
+ M-e Κινήσου εμπρός στο τέλος της πρότασης
+
+>> Δοκίμασε όλες αυτές τις εντολές μερικές φορές για εξάσκηση. Αυτές
+ είναι οι πιο συνηθισμένες εντολές.
+
+Δύο άλλες σημαντικές κινήσεις του δείκτη είναι το M-< (META
+Μικρότερο), που κινείται στην αρχή ολόκληρου του κειμένου, και M->
+(META Μεγαλύτερο) που κινείται στο τέλος ολόκληρου του κειμένου.
+
+Στους πλείστους ακροδέκτες (τερματικά), το '<' είναι στο ίδιο πλήκτρο
+με το κόμμα, οπότε πρέπει να κρατάς πατημένο το shift για να το
+πληκτρολογήσεις. Σε αυτούς τους ακροδέκτες πρέπει να χρησιμοποιήσεις
+το shift και για το M-<, αλλιώς θα πατάς M-κόμμα.
+
+>> Δοκίμασε το M-< τώρα για να κινηθείς στην αρχή αυτής της εκμάθησης.
+ Κατόπιν χρησιμοποίησε το C-v επανειλημμένα για να επιστρέψεις εδώ.
+
+>> Τώρα δοκίμασε το M-> για να κινηθείς στο τέλος αυτής της εκμάθησης.
+ Κατόπιν χρησιμοποίησε το M-v επανειλημμένα για να επιστρέψεις εδώ.
+
+Μπορείς επίσης να χρησιμοποιήσεις τα πλήκτρα με τα βέλη, εάν ο
+ακροδέκτης σου τα υποστηρίζει. Προτείνουμε να μάθεις τα C-b, C-f, C-n
+και C-p για τρεις λόγους. Πρώτον, δουλεύουν σε όλων των ειδών τους
+ακροδέκτες. Δεύτερον, όταν αποκτήσεις εμπειρία στην χρήση του Emacs,
+θα διαπιστώσεις πως αυτοί οι χαρακτήρες του Control είναι πιο γρήγοροι
+στην χρήση παρά τα βέλη (διότι δεν απομακρύνεις τα χέρια σου από την
+θέση πληκτρολόγησης δια αφής). Τρίτον, εφόσον διαμορφώσεις την
+συνήθεια να χρησιμοποιείς τις εντολές με τους Control χαρακτήρες,
+μπορείς πιο εύκολα να μάθεις πιο προηγμένες εντολές κίνησης.
+
+Οι πλείστες εντολές του Emacs δέχονται αριθμητική παράμετρο: για τις
+περισσότερες εντολές αυτή λειτουργεί ως μετρητής επανάληψης. Ο τρόπος
+που δίνεις σε μια εντολή αριθμητική παράμετρο γίνεται πληκτρολογώντας
+το C-u και μετά τα ψηφία προτού πληκτρολογήσεις την εντολή. Εάν έχεις
+το πλήκτρο META (ή ALT), υπάρχει άλλος εναλλακτικός τρόπος εισαγωγής
+αριθμητικής παραμέτρου: πληκτρολόγησε τα ψηφία κρατώντας πατημένο το
+πλήκτρο META. Συνιστούμε να μάθεις την μέθοδο του C-u γιατί ισχύει σε
+όλους τους ακροδέκτες. Η αριθμητική παράμετρος ονομάζεται επίσης
+«προθεματική παράμετρος», καθώς πληκτρολογείς την παράμετρο πριν την
+εντολή στην οποία δίνεται.
+
+Για παράδειγμα, C-u 8 C-f κινείται εμπρός οκτώ χαρακτήρες.
+
+>> Δοκίμασε να χρησιμοποιήσεις το C-n ή C-p με αριθμητική παράμετρο
+ για να κινήσεις τον δείκτη σε μια γραμμή κοντά σε αυτή με μόνο μία
+ εντολή.
+
+Οι πλείστες εντολές χρησιμοποιούν την αριθμητική παράμετρο ως μετρητή
+επανάληψης, αλλά μερικές εντολές την χρησιμοποιούν με διαφορετικό
+τρόπο. Αρκετές εντολές (αλλά καμία από αυτές που έμαθες έως τώρα) την
+χρησιμοποιούν ως ένδειξη--η παρουσία προθεματικής παραμέτρου,
+ανεξαρτήτως της αξίας της, κάνει την εντολή να εκτελέσει κάτι
+διαφορετικό.
+
+Τα C-v και M-v συνιστούν άλλο ένα είδος εξαίρεσης. Όταν τους δοθεί
+παράμετρος, κυλούν το κείμενο πάνω ή κάτω κατά τόσες γραμμές, αντί για
+πλήρη οθόνη. Για παράδειγμα, C-u 8 C-v κυλάει πάνω κατά 8 γραμμές.
+
+>> Δοκίμασε να πληκτρολογήσεις C-u 8 C-v τώρα.
+
+Αυτό πρέπει να κύλησε το κείμενο πάνω κατά 8 γραμμές. Αν θέλεις να το
+φέρεις κάτω πάλι δοκίμασε την ίδια αριθμητική παράμετρο με το M-v.
+
+Εάν χρησιμοποιείς γραφική προβολή, όπως το X ή MS-Windows, θα πρέπει
+να υπάρχει μια ψηλή, ορθογώνια επιφάνεια σε πλευρά του παραθύρου του
+Emacs που είναι γνωστή και ως η μπάρα κύλισης (scroll bar). Μπορείς
+να κυλήσεις το κείμενο πατώντας με το ποντίκι πάνω στην μπάρα κύλισης.
+
+Αν το ποντίκι σου έχει ροδέλα, μπορείς να την χρησιμοποιήσεις για
+κύλιση.
+
+
+* ΑΝ ΤΟ EMACS ΠΑΨΕΙ ΝΑ ΑΝΤΑΠΟΚΡΙΝΕΤΑΙ
+-------------------------------------
+
+Αν το Emacs πάψει να ανταποκρίνεται στις εντολές σου, μπορείς να το
+σταματήσεις με ασφάλεια πληκτρολογώντας C-g. Μπορείς να
+χρησιμοποιήσεις το C-g για να σταματήσεις μια εντολή που παίρνει πολύ
+χρόνο να εκτελεστεί.
+
+Μπορείς επίσης να χρησιμοποιήσεις το C-g για να καταργήσεις μια
+αριθμητική παράμετρο ή την αρχή μιας εντολής που δεν θέλεις να
+ολοκληρώσεις.
+
+>> Πληκτρολόγησε C-u 100 για να φτιάξεις μια αριθμητική παράμετρο του
+ 100, μετά πληκτρολόγησε C-g. Τώρα πληκτρολόγησε C-f. Θα πρέπει να
+ κινηθεί μόνο ένα χαρακτήρα, διότι ακύρωσες την παράμετρο με το C-g.
+
+Σε περίπτωση που έχεις πληκτρολογήσει το <ESC> κατά λάθος, μπορείς να
+το ξεφορτωθείς με το C-g.
+
+
+* ΑΠΕΝΕΡΓΟΠΟΙΗΜΕΝΕΣ ΕΝΤΟΛΕΣ
+---------------------------
+
+Κάποιες εντολές του Emacs είναι «απενεργοποιημένες» ώστε νέοι χρήστες
+να μην τις χρησιμοποιήσουν κατά λάθος.
+
+Αν πληκτρολογήσεις μία από αυτές τις απενεργοποιημένες εντολές, το
+Emacs παρουσιάζει μήνυμα που αναφέρει ποια είναι η εντολή και σου ζητά
+αν θέλεις να την εκτελέσεις.
+
+Εάν πράγματι θες να δοκιμάσεις την εντολή, πληκτρολόγησε <SPC> (το
+κενό) ως απάντηση στην ερώτηση. Κανονικά, αν δεν θέλεις να εκτελέσεις
+την απενεργοποιημένη εντολή απαντάς με το «n».
+
+>> Πληκτρολόγησε C-x C-l (που είναι απενεργοποιημένη εντολή) και μετά
+ πληκτρολόγησε n ως απάντηση.
+
+
+* ΠΑΡΑΘΥΡΑ
+----------
+
+Το Emacs μπορεί να έχει πολλά «παράθυρα», με το καθένα να δείχνει το
+δικό του κείμενο. Θα εξηγήσουμε παρακάτω πως να χρησιμοποιείς πολλά
+παράθυρα. Για την ώρα θέλουμε να εξηγήσουμε πως θα ξεφορτωθείς
+πλεονάζοντα παράθυρα για να επιστρέψεις στην βασική επεξεργασία εντός
+ενός παραθύρου. Είναι απλό:
+
+ C-x 1 Ένα παράθυρο (δηλαδή εξαφάνισε όλα τα άλλα παράθυρα)
+
+Αυτό πρόκειται για το CONTROL-x που ακολουθείται από το ψηφίο 1. Το
+C-x 1 μεγιστοποιεί το παράθυρο που περιέχει τον δείκτη. Διαγράφει τα
+άλλα παράθυρα.
+
+>> Φέρε τον δείκτη σε αυτή την γραμμή και πληκτρολόγησε C-u 0 C-l.
+>> Πληκτρολόγησε C-h k C-f.
+ Δες πως το παράθυρο συρρικνώνεται, καθώς ένα νέο εμφανίζεται για να
+ παρουσιάσει την καταγραφή της εντολής C-f.
+
+>> Πληκτρολόγησε C-x 1 και δες πως το παράθυρο της καταγραφής
+ εξαφανίζεται.
+
+Υπάρχει σειρά εντολών που ξεκινούν με το CONTROL-x· πολλές εξ αυτών
+έχουν να κάνουν με παράθυρα (windows), αρχεία (files), ενταμιευτές
+(buffers), και τα σχετικά. Αυτές οι εντολές είναι δύο, τρία ή τέσσερα
+γράμματα μάκρος.
+
+
+* ΕΙΣΑΓΟΝΤΑΣ ΚΑΙ ΔΙΑΓΡΑΦΟΝΤΑΣ
+-----------------------------
+
+Αν θέλεις να εισάγεις κείμενο, απλά πληκτρολόγησε το. Κοινοί
+χαρακτήρες, όπως το Α, 7, *, κτλ. εισάγονται καθώς τους πληκτρολογείς.
+Για να εισάγεις τον χαρακτήρα νέας γραμμής, πληκτρολόγησε <Return>
+(αυτό είναι το πλήκτρο που μερικές φορές αναγράφεται ως «Enter»).
+
+Για να διαγράψεις τον χαρακτήρα ακριβώς πριν από το τωρινό σημείο του
+δείκτη, πληκτρολόγησε <DEL>. Αυτό είναι το πλήκτρο που συνήθως
+αναγράφεται στο πληκτρολόγιο ως «Backspace»--το ίδιο θα
+χρησιμοποιούσες κανονικά κι εκτός Emacs για να διαγράψεις τον
+τελευταίο χαρακτήρα που εισήγαγες.
+
+Συνήθως υπάρχει άλλο ένα πλήκτρο που αναγράφεται ως <Delete>, αλλά
+αυτό είναι διαφορετικό από αυτό που προαναφέραμε και που εννοούμε με
+το <DEL> του Emacs.
+
+>> Κάνε αυτό τώρα--πληκτρολόγησε μερικούς χαρακτήρες, μετά διάγραψε
+ τους πατώντας το <DEL> μερικές φορές. Μην ανησυχείς για την
+ τροποποίηση αυτού του αρχείου: δεν τροποποιείς το κύριο κείμενο
+ εκμάθησης. Αυτό είναι το προσωπικό σου αντίγραφο.
+
+Όταν η γραμμή του κειμένου γίνεται πολύ μεγάλη για μια γραμμή της
+οθόνης, η γραμμή του κειμένου «συνεχίζεται» σε δεύτερη γραμμή οθόνης.
+Εάν χρησιμοποιείς γραφική προβολή, καμπυλωτά βελάκια θα εμφανιστούν
+στα στενά πλαίσια που βρίσκονται στα άκρα της επιφάνειας του κειμένου
+(οι «παρυφές» αριστερά και δεξιά), για να επισημάνουν που συνεχίζεται
+η γραμμή. Εάν χρησιμοποιείται προβολή κειμένου, η συνεχιζόμενη γραμμή
+παρουσιάζεται με την αντίστροφη κάθετο ('\') στην δεξιότερη στήλη της
+οθόνης.
+
+>> Εισήγαγε κείμενο μέχρις ότου φτάσεις στο δεξί περιθώριο και
+ συνέχισε να προσθέτεις. Θα δεις να εμφανίζεται η γραμμή συνέχειας.
+
+>> Πάτα <DEL> επανειλημμένα για να διαγράψεις το κείμενο μέχρι που η
+ γραμμή να χωράει ξανά στην οθόνη. Η γραμμή συνέχειας θα χαθεί.
+
+Μπορείς να διαγράψεις τον χαρακτήρα νέας γραμμής όπως κάθε άλλο
+χαρακτήρα. Διαγράφοντας τον χαρακτήρα νέας γραμμής μεταξύ δύο γραμμών
+έχει σαν αποτέλεσμα την συνένωση τους σε μία γραμμή. Εάν σαν
+αποτέλεσμα η γραμμή είναι πολύ μεγάλη, θα παρουσιαστεί με την γραμμή
+συνέχειας.
+
+>> Μετακίνησε τον δείκτη στην αρχή της γραμμής και πληκτρολόγησε
+ <DEL>. Αυτό θα συνενώσει την γραμμή με την από πάνω της.
+
+>> Πληκτρολόγησε <Return> για να επανεισάγεις τον χαρακτήρα νέας
+ γραμμής που μόλις διέγραψες.
+
+Το πλήκτρο <Return> είναι ειδικό, καθώς πληκτρολογώντας το μπορεί να
+κάνει περισσότερα πράγματα πέραν της εισαγωγής του χαρακτήρα νέας
+γραμμής. Ανάλογα με το περιβάλλων κείμενο, μπορεί να προσθέσει κενό
+μετά τον χαρακτήρα νέας γραμμής, ώστε όταν αρχίσεις να γράφεις στην
+νέα γραμμή, το κείμενο να στοιχίζεται με την προηγούμενη γραμμή.
+Ονομάζουμε αυτή την συμπεριφορά (όπου το πάτημα ενός πλήκτρου κάνει
+κάτι παραπάνω από την εισαγωγή του σχετικού χαρακτήρα) «ηλεκτρική».
+
+>> Ιδού ένα παράδειγμα της ηλεκτρικότητας του <Return>.
+ Πληκτρολόγησε <Return> στο τέλος αυτής της γραμμής.
+
+Κανονικά θα δεις πως μετά την εισαγωγή του χαρακτήρα νέας γραμμής, το
+Emacs εισάγει κενά ώστε ο δείκτης να βρίσκεται ακριβώς κάτω από το
+«Π» του «Πληκτρολόγησε».
+
+Θυμήσου πως οι πλείστες εντολές του Emacs δέχονται μετρητή επανάληψης·
+αυτό περιλαμβάνει την εισαγωγή κειμένου. Επαναλαμβάνοντας ένα
+χαρακτήρα κειμένου τον εισάγει πολλές φορές.
+
+>> Δοκίμασε το τώρα -- πληκτρολόγησε C-u 8 * για να εισάγεις ********.
+
+Έχεις ήδη μάθει τους πιο βασικούς τρόπους για την πληκτρολόγηση
+κειμένου στο Emacs και την διόρθωση των λαθών. Μπορείς επίσης να
+διαγράψεις λέξεις και γραμμές. Ιδού η σύνοψη των πράξεων διαγραφής:
+
+ <DEL> Διάγραψε τον χαρακτήρα ακριβώς πριν τον δείκτη
+ C-d Διάγραψε τον χαρακτήρα ακριβώς μετά τον δείκτη
+
+ M-<DEL> Εξαφάνισε την λέξη ακριβώς πριν τον δείκτη
+ M-d Εξαφάνισε την λέξη μετά τον δείκτη
+
+ C-k Εξαφάνισε από το σημείο του δείκτη ως το τέλος της γραμμής
+ M-k Εξαφάνισε ως το τέλος της παρούσας πρότασης
+
+Πρόσεξε πως το <DEL> και C-d σε σύγκριση με M-<DEL> και M-d
+προεκτείνουν την παράλληλο που άρχισε με το C-f και M-f (κατ'ακρίβεια,
+το <DEL> δεν είναι χαρακτήρας control, αλλά ας μην ανησυχούμε για
+αυτό). Τα C-k και M-k είναι κατά τρόπο όπως το C-e και M-e καθώς οι
+γραμμές ταιριάζουν με τις προτάσεις.
+
+Μπορείς επίσης να εξαφανίσεις ένα μέρος κειμένου με ενιαίο τρόπο.
+Κινήσου σε μία άκρη του και πληκτρολόγησε C-<SPC>. (<SPC> είναι το
+πλήκτρο του κενού.) Κατόπιν, μετακίνησε τον δείκτη στην άλλη άκρη του
+κειμένου που θέλεις να εξαφανίσεις. Καθώς το κάνεις αυτό, το Emacs
+επισημαίνει το κείμενο μεταξύ των δύο άκρων του δείκτη και του σημείου
+όπου πληκτρολόγησες C-<SPC>. Τέλος, πληκτρολόγησε C-w. Αυτό
+εξαφανίζει το κείμενο μεταξύ των δύο σημείων.
+
+>> Μετακίνησε τον δείκτη στο γράμμα Μ στην αρχή της προηγούμενης
+ παραγράφου.
+>> Πληκτρολόγησε C-<SPC>. Το Emacs θα σου γράψει μήνυμα στο κάτω
+ μέρος της οθόνης πως τέθηκε σημάδι («Mark set»).
+>> Μετακίνησε τον δείκτη στο κ της λέξης «άκρη» στην δεύτερη γραμμή
+ της παραγράφου.
+>> Πληκτρολόγησε C-w. Αυτό θα εξαφανίσει το κείμενο που άρχιζε με Μ
+ και τελειώνει ακριβώς πριν το κ.
+
+Η διαφορά μεταξύ της «εξαφάνισης» και της «διαγραφής» είναι πως το
+«εξαφανισμένο» κείμενο μπορεί να επανεισαχθεί (σε οποιαδήποτε θέση),
+ενώ τα «διαγραμμένα» πράγματα δεν μπορούν να επανεισαχθούν κατά αυτόν
+τον τρόπο (μπορείς, ωστόσο, να αναιρέσεις την διαγραφή--δες παρακάτω).
+Επανεισαγωγή εξαφανισμένου κειμένου ονομάζεται «τράβηγμα» («yanking»).
+(Φαντάσου πως τραβάς κάτι πίσω το οποίο είχε αφαιρεθεί.) Γενικά, οι
+εντολές που αφαιρούν πολύ κείμενο το εξαφανίζουν, ενώ οι εντολές που
+αφαιρούν απλά ένα χαρακτήρα, ή μόνο κενές γραμμές ή κενά, κάνουν
+διαγραφή (οπότε δεν μπορείς να τα τραβήξεις πίσω). <DEL> και C-d
+κάνουν διαγραφή στην απλή περίπτωση, χωρίς παράμετρο. Αν τους δοθεί
+παράμετρος, τότε κάνουν εξαφάνιση.
+
+>> Μετακίνησε τον δείκτη στην αρχή μιας γραμμής που δεν είναι κενή.
+ Κατόπιν πληκτρολόγησε C-k για να εξαφανίσεις το κείμενο ως το τέλος
+ της γραμμής.
+>> Πληκτρολόγησε C-k δεύτερη φορά. Θα δεις πως εξαφανίζει τον
+ χαρακτήρα νέας γραμμής που ακολουθεί εκείνη την γραμμή.
+
+Σημείωσε πως ένα C-k εξαφανίζει το περιεχόμενο της γραμμής, ενώ
+δεύτερο C-k εξαφανίζει την ίδια την γραμμή και κάνει όλες τις
+ακόλουθες γραμμές να μετατοπιστούν προς τα πάνω. Το C-k ερμηνεύει την
+αριθμητική παράμετρο με ειδικό τρόπο: εξαφανίζει τις γραμμές ΚΑΙ το
+περιεχόμενο τους. Αυτό δεν πρόκειται για απλή επανάληψη. C-u 2 C-k
+εξαφανίζει δύο γραμμές και τους αντίστοιχους χαρακτήρες νέας γραμμής·
+ενώ πληκτρολογώντας το C-k δύο φορές δεν θα το έκανε αυτό.
+
+Μπορείς να τραβήξεις εξαφανισμένο κείμενο στο ίδιο σημείο από όπου
+εξαφανίστηκε, ή σε κάποιο άλλο σημείο που επεξεργάζεσαι, ή ακόμα σε
+άλλο αρχείο. Μπορείς να τραβήξεις το ίδιο κείμενο πολλές φορές· αυτό
+δημιουργεί πολλαπλά αντίγραφα του. Άλλοι κειμενογράφοι ονομάζουν την
+εξαφάνιση και το τράβηγμα «αποκοπή» και «επικόλληση» (δες το γλωσσάριο
+στο εγχειρίδιο του Emacs).
+
+Η εντολή για τράβηγμα είναι C-y. Εισάγει το τελευταίο εξαφανισμένο
+κείμενο στην τρέχουσα θέση του δείκτη.
+
+>> Δοκίμασε το· πληκτρολόγησε C-y για τα τραβήξεις το κείμενο πίσω.
+
+Εάν κάνεις πολλά C-k στην σειρά, όλο το εξαφανισμένο κείμενο
+αποθηκεύεται μαζί, ώστε ένα C-y τραβάει όλες τις γραμμές συλλήβδην.
+
+>> Κάνε το τώρα· πληκτρολόγησε C-k αρκετές φορές.
+
+Τώρα ανάκτησε το εξαφανισμένο κείμενο:
+
+>> Πληκτρολόγησε C-y. Κατόπιν μετακίνησε τον δείκτη κάτω μερικές
+ γραμμές και πληκτρολόγησε C-y ξανά. Τώρα βλέπεις πως να
+ αντιγράψεις ορισμένο κείμενο.
+
+Τι κάνει εάν έχεις κείμενο που θέλεις να τραβήξεις πίσω και μετά να
+εξαφανίσεις κάτι άλλο; Το C-y θα τραβήξει την πιο πρόσφατη εξαφάνιση.
+Αλλά η προηγούμενη της δεν έχει χαθεί. Μπορείς να επιστρέψεις σε αυτή
+χρησιμοποιώντας την εντολή M-y. Αφού έχεις κάνει C-y για να πάρεις
+την πιο πρόσφατη εξαφάνιση, πληκτρολογώντας το M-y αντικαθιστά το
+τραβηγμένο κείμενο με το λιγότερο πρόσφατο εξαφανισμένο κείμενο.
+Πληκτρολογώντας M-y ξανά και ξανά επαναφέρει ολοένα και παλαιότερες
+εξαφανίσεις. Όταν βρεις το κείμενο που ψάχνεις, δεν χρειάζεται να
+κάνεις κάτι άλλο για να το κρατήσεις. Απλά συνέχισε την επεξεργασία,
+αφήνοντας το τραβηγμένο κείμενο εκεί που είναι.
+
+Εάν χρησιμοποιήσεις το M-y αρκετές φορές, θα επιστρέψεις στο αρχικό
+σημείο (την πιο πρόσφατη εξαφάνιση).
+
+>> Εξαφάνισε μια γραμμή, κινήσου κάπου αλλού, εξαφάνισε άλλη γραμμή.
+ Μετά πάτα C-y για να επαναφέρεις την δεύτερη εξαφανισμένη γραμμή.
+ Μετά κάνε M-y κι αυτή θα αντικατασταθεί με την πρώτη εξαφανισμένη
+ γραμμή. Κάνε κι άλλα M-y να δεις τι θα σου βγάλει. Συνέχισε ώσπου
+ να σου δώσει πάλι την δεύτερη εξαφανισμένη γραμμή. Αν θέλεις
+ μπορείς να περάσεις στο M-y θετικές ή αρνητικές παραμέτρους.
+
+
+* ΑΝΑΙΡΕΣΗ
+----------
+
+Εάν κάνεις αλλαγή στο κείμενο κι ύστερα κρίνεις πως ήταν λάθος,
+μπορείς να την αναιρέσεις με την εντολή αναίρεσης C-/.
+
+Κανονικά, το C-/ αναιρεί τις αλλαγές που επέφερε μία εντολή. Αν
+επαναλάβεις το C-/ πολλές φορές στη σειρά, κάθε επανάληψη αναιρεί
+ακόμα μία εντολή.
+
+Ωστόσο υπάρχουν δύο εξαιρέσεις: εντολές που δεν τροποποιούν κείμενο
+δεν μετρούν (όπως εντολές που κινούν τον δείκτη ή κυλούν το κείμενο)
+και χαρακτήρες που αυτό-εισάγονται συνήθως κρίνονται ως ομάδες έως 20
+μέλη. (Αυτό είναι για να περιορίσει τον αριθμό των C-/ που
+απαιτούνται για την αναίρεση εισαγωγής κειμένου.)
+
+>> Εξαφάνισε αυτή την γραμμή με C-k και πληκτρολόγησε C-/ ώστε να
+ επανεμφανιστεί.
+
+Το C-_ είναι εναλλακτική εντολή αναίρεσης που λειτουργεί το ίδιο με το
+C-/. Σε ορισμένους ακροδέκτες κειμένου, ενδέχεται να μην χρειάζεται
+το shift για να εισάγεις το C-_. Σε ορισμένους ακροδέκτες κειμένου,
+το C-/ στέλνει το σήμα του C-_ στο Emacs. Εναλλακτικά, το C-x u
+λειτουργεί ακριβώς όπως το C-/, αλλά είναι λίγο πιο δύσκολο να το
+πληκτρολογήσεις.
+
+Η αριθμητική παράμετρος στα C-/, C-_, C-x u δρα ως μετρητής
+επανάληψης.
+
+Μπορείς να αναιρέσεις την διαγραφή κειμένου κατά τον ίδιο τρόπο που
+αναιρείς την εξαφάνιση κειμένου. Ο διαχωρισμός μεταξύ εξαφάνισης και
+διαγραφής έχει σημασία μόνο όταν θες να τραβήξεις κάτι πίσω με το C-y:
+δεν έχει καμιά διαφορά για τους σκοπούς της αναίρεσης.
+
+
+* ΑΡΧΕΙΑ
+--------
+
+Για να καταστήσεις μόνιμο το κείμενο που επεξεργάζεσαι, πρέπει να το
+βάλεις σε αρχείο. Αλλιώς θα χαθεί όταν κλείσεις το Emacs. Για να
+βάλεις κείμενο σε αρχείο, πρέπει να το «βρεις» πριν εισάγεις το
+κείμενο. (Η πράξη αυτή ονομάζεται επίσης ως «επίσκεψη» στην τοποθεσία
+του αρχείου.)
+
+Εξεύρεση του αρχείο σημαίνει πως βλέπεις το περιεχόμενο του εντός του
+Emacs. Κατά πολλούς τρόπους, είναι σαν να επεξεργάζεσαι το αρχείο
+απευθείας. Ωστόσο, οι αλλαγές που κάνεις καθίστανται μόνιμες μόνο
+αφού «αποθηκεύσεις» το αρχείο. Αυτό γίνεται ώστε να μην μένουν
+μισοτελειωμένα αρχεία στο σύστημα ενάντια στην θέληση σου. Ακόμα κι
+αν αποθηκεύσεις τις αλλαγές, το Emacs διατηρεί αντίγραφο του γνησίου
+αρχείου υπό ελαφρώς τροποποιημένο όνομα, ώστε να μπορείς να το
+επαναφέρεις σε περίπτωση που συνέβη κάποιο λάθος.
+
+Αν κοιτάξεις προς το κάτω μέρος της οθόνης θα δεις μια γραμμή που
+αρχίζει με παύλες και αναφέρει « -:--- TUTORIAL.el_GR» ή κάπως έτσι.
+Αυτό το μέρος της οθόνης συνήθως δείχνει το όνομα του αρχείου που
+επισκέπτεσαι. Τώρα επισκέπτεσαι το προσωπικό σου αντίγραφο του
+κειμένου εκμάθησης του Emacs, που ονομάζεται «TUTORIAL.el_GR». Όταν
+βρίσκεις ένα αρχείο με το Emacs, το όνομα του θα εμφανιστεί σε εκείνο
+ακριβώς το σημείο.
+
+Μια ειδική πτυχή της εντολής για εξεύρεση αρχείου είναι πως πρέπει να
+προσδιορίσεις ποιο αρχείο θέλεις. Λέμε πως η εντολή «διαβάζει την
+παράμετρο» (στην προκειμένη περίπτωση αυτή είναι το όνομα του
+αρχείου). Αφού πληκτρολογήσεις την εντολή
+
+ C-x C-f Βρες ένα αρχείο
+
+το Emacs θα σου ζητήσει να πληκτρολογήσεις το όνομα του. Το όνομα
+του αρχείου που εισάγεις εμφανίζεται στο κάτω μέρος της οθόνης. Η
+τελευταία γραμμή ονομάζεται μικροενταμιευτής (minibuffer) όταν
+χρησιμοποιείται για τέτοιους σκοπούς εισαγωγής εντολής. Μπορείς να
+χρησιμοποιήσεις τις κοινές εντολές του Emacs για επεξεργασία κειμένου
+καθώς γράφεις το όνομα του αρχείου.
+
+Ενόσω δακτυλογραφείς το όνομα του αρχείο (ή κάθε άλλο κείμενο στον
+μικροενταμιευτή), μπορείς να ακυρώσεις την εντολή με το C-g.
+
+>> Πληκτρολόγησε C-x C-f και μετά C-g. Αυτό ακυρώνει τον
+ μικροενταμιευτή και την εντολή C-x C-f που τον χρησιμοποιούσε.
+ Συνεπώς δεν θα βρεις κανένα αρχείο.
+
+Όταν ολοκληρώσεις την εισαγωγή του ονόματος ενός αρχείου, πάτα
+<Return> για να την επικυρώσεις. Ο μικροενταμιευτής εξαφανίζεται
+καθώς το C-x C-f αναλαμβάνει δράση για να βρει το αρχείο που του
+όρισες.
+
+Το περιεχόμενο του αρχείου τώρα εμφανίζεται στην οθόνη και μπορείς να
+το επεξεργαστείς. Όταν θέλεις να μονιμοποιήσεις τις αλλαγές που
+έκανες, χρησιμοποίησε την εντολή
+
+ C-x C-s Αποθήκευσε το αρχείο
+
+Αυτή αντιγράφει το κείμενο που βρίσκεται στο Emacs στο εν λόγω αρχείο.
+Την πρώτη φορά που το κάνεις αυτό, το Emacs μετονομάζει το γνήσιο ώστε
+να μην χαθεί. Το νέο όνομα περιέχει το σύμβολο «~» ως κατάληξη του
+αρχικού ονόματος. Όταν ολοκληρωθεί η αποθήκευση, το Emacs παρουσιάζει
+το όνομα του αρχείου όπου γράφτηκαν οι αλλαγές.
+
+>> Πληκτρολόγησε C-x C-s TUTORIAL.el_GR <Return>.
+ Αυτό θα αποθηκεύσει αυτό το κείμενο σε αρχείο με το όνομα
+ TUTORIAL.el_GR και θα αναφέρει πως έγραψε σε αυτό στο κάτω μέρος
+ της οθόνης.
+
+Μπορείς να βρεις υφιστάμενο αρχείο είτε για να το δεις ή να το
+επεξεργαστείς. Μπορείς επίσης να βρεις αρχείο το οποίο δεν
+προϋπάρχει. Έτσι το Emacs θα δημιουργήσει το αρχείο: θα βρεις το νέο
+αρχείο, το οποίο είναι κενό, και κατόπιν θα εισάγεις κείμενο σε αυτό.
+Όταν επιχειρήσεις να το αποθηκεύσεις, το Emacs θα δημιουργήσει το
+αρχείο αυτό με το περιεχόμενο που του έδωσες. Από εκεί και πέρα
+θεώρησε πως επεξεργάζεσαι ένα υφιστάμενο αρχείο.
+
+
+* ΕΝΤΑΜΙΕΥΤΕΣ
+-------------
+
+Εάν βρεις δεύτερο αρχείο με το C-x C-f, το πρώτο παραμένει εντός του
+Emacs. Μπορείς να επανέλθεις σε αυτό αν το ξαναβρείς με το C-x C-f.
+Έτσι δύναται να έχεις πολλά αρχεία ανοιχτά εντός του Emacs.
+
+Το Emacs αποθηκεύει το περιεχόμενο του κάθε αρχείου σε αντικείμενο το
+οποίο ονομάζεται «ενταμιευτής» (buffer). Η εξεύρεση αρχείου
+δημιουργεί νέο ενταμιευτή εντός του Emacs. Για να δεις την λίστα με
+όλους τους υφιστάμενους ενταμιευτές, πληκτρολόγησε
+
+ C-x C-b Παράθεσε ενταμιευτές
+
+>> Δοκίμασε το C-x C-b τώρα.
+
+Παρατήρησε πως κάθε ενταμιευτής έχει όνομα ενώ δύναται να έχει επίσης
+κι όνομα αρχείου του οποίο το περιεχόμενο κρατεί. ΟΤΙΔΗΠΟΤΕ βλέπεις
+σε παράθυρο Emacs πάντα είναι μέρος ενός ενταμιευτή.
+
+>> Πληκτρολόγησε C-x 1 για να εξαφανίσεις το παράθυρο που παραθέτει
+ τους ενταμιευτές.
+
+Όταν έχεις πολλούς ενταμιευτές, μόνο ένας είναι ο «τρέχον» σε κάθε
+στιγμή. Πρόκειται για τον ενταμιευτή που επεξεργάζεσαι. Εάν θες να
+επεξεργαστείς κάποιον άλλο ενταμιευτή, πρέπει να «μεταβείς» σε αυτόν.
+Αν θα μεταβείς σε ενταμιευτής που επισκέπτεται αρχείο, μπορείς να το
+κάνεις με το C-x C-f προσδιορίζοντας το όνομα του αρχείου. Αλλά
+υπάρχει ευκολότερος τρόπος: χρησιμοποίησε την εντολή C-x b. Σε αυτή
+την εντολή, πρέπει να εισάγεις το όνομα του ενταμιευτή.
+
+>> Δημιούργησε αρχείο ονόματι «foo»: γράψε C-x C-f foo <Return>.
+ Μετά πληκτρολόγησε C-x b TUTORIAL.el_GR <Return> για να επιστρέψεις
+ σε αυτό το κείμενο εκμάθησης του Emacs.
+
+Συνήθως, το όνομα του ενταμιευτή αντιστοιχεί σε αυτό του αρχείου
+(χωρίς το μέρος του αρχείου που αναφέρει τον κατάλογο/φάκελο στον
+οποίο βρίσκεται). Ωστόσο αυτό δεν ισχύει πάντοτε. Η παράθεση
+ενταμιευτών που φτιάχνει το C-x C-b δείχνει τόσο το όνομα του
+ενταμιευτή όσο κι αυτό του αρχείου.
+
+Κάποιοι ενταμιευτές δεν ανταποκρίνονται σε αρχεία. Ο ενταμιευτής
+ονόματι «*Buffer List*», που περιέχει τα στοιχεία του C-x C-b, δεν
+έχει κάποιο υποκείμενο αρχείο. Ο ενταμιευτής αυτού του
+TUTORIAL.el_GR αρχικά δεν είχε κάποιο αρχείο, αλλά τώρα έχει, καθώς
+στην προηγούμενη ενότητα χρησιμοποίησες το C-x C-s για να τον
+αποθηκεύσεις σε αρχείο.
+
+Ο ενταμιευτής με το όνομα «*Messages*» επίσης δεν έχει αρχείο. Αυτός
+περιέχει όλα τα μηνύματα που εμφανίζονται στο κάτω μέρος της οθόνης
+κατά την λειτουργία του Emacs.
+
+>> Πληκτρολόγησε C-x b *Messages* <Return> για να δεις τον ενταμιευτή
+ με τα μηνύματα. Μετά πληκτρολόγησε C-x b TUTORIAL.el_GR <Return>
+ για να επανέλθεις εδώ.
+
+Εάν κάνεις αλλαγές στο κείμενο ενός αρχείου, μετά βρεις κάποιο άλλο
+αρχείο, η πράξη αυτή δεν αποθηκεύει τις αλλαγές που έκανες στο πρώτο
+αρχείο. Οι αλλαγές παραμένουν εντός του Emacs, στον ενταμιευτή που
+ανταποκρίνεται σε εκείνο το αρχείο. Η δημιουργία ή επεξεργασία του
+δεύτερου αρχείου δεν επηρεάζει το πρώτο. Αυτό είναι πολύ χρήσιμο,
+ωστόσο σημαίνει πως χρειάζεσαι έναν βολικό τρόπο να αποθηκεύεις
+αλλαγές σε πολλούς ενταμιευτές. Το να πρέπει να επιστρέψεις στο
+πρώτο αρχείο απλά και μόνο για να το αποθηκεύσεις είναι ενοχλητικό.
+Οπότε έχουμε
+
+ C-x s Αποθήκευσε ορισμένους ενταμιευτές στα αρχεία τους
+
+Το C-x s ρωτά για κάθε ενταμιευτή που επισκέπτεται αρχείο και που
+κρατά αλλαγές οι οποίες δεν έχουν αποθηκευτεί. Σε ρωτά για κάθε
+ενταμιευτή κατά πόσον να αποθηκευτούν οι αλλαγές του στο αρχείο.
+
+>> Εισήγαγε μια γραμμή κειμένου και πληκτρολόγησε C-x s.
+ Θα σε ρωτήσει κατά πόσον θες να αποθηκεύσεις τον ενταμιευτή με
+ όνομα TUTORIAL.el_GR. Απάντα καταφατικά με το «y» (yes).
+
+
+* ΕΠΕΚΤΕΙΝΟΝΤΑΣ ΤΟ ΣΥΝΟΛΟ ΕΝΤΟΛΩΝ
+---------------------------------
+
+Υπάρχουν πάρα πολλές εντολές του Emacs που δεν μπορούν να χωρέσουν σε
+όλους τους control και meta χαρακτήρες. Το Emacs ξεπερνά αυτό το
+εμπόδιο με την εντολή επέκτασης (eXtend). Αυτή έχει δύο μορφές:
+
+ C-x Χαρακτήρος επέκταση. Ακολουθείται από τον χαρακτήρα.
+ M-x Ονόματος επέκταση. Ακολουθείται από όνομα.
+
+Αυτές είναι εντολές που είναι χρήσιμες εν γένει αλλά χρησιμοποιούνται
+σχετικά λιγότερο από αυτές που έμαθες έως τώρα. Έχεις ήδη δει εντολές
+επέκτασης, όπως το C-x C-f και το C-x C-s. Άλλο παράδειγμα είναι η
+εντολή που κλείνει το Emacs--αυτή είναι C-x C-c. (Μην ανησυχείς για
+απώλεια αλλαγών που έκανες· το C-x C-c ρωτά να αποθηκεύσει αλλαγές σε
+κάθε αρχείο πριν τερματίσει το Emacs.)
+
+Εάν χρησιμοποιείς γραφική προβολή, δεν χρειάζεσαι κάποια ειδική εντολή
+για να μεταβείς από το Emacs σε κάποια άλλη εφαρμογή. Μπορείς να το
+κάνεις με το ποντίκι ή τις εντολές του διαχειριστή παραθύρων. Αν όμως
+χρησιμοποιείς ακροδέκτη κειμένου ο οποίος προβάλει μόνο μία εφαρμογή,
+τότε πρέπει να «αναστείλεις» το Emacs για να επιλέξεις οποιαδήποτε
+άλλη εφαρμογή.
+
+C-z είναι η εντολή της *προσωρινής* εξόδου από το Emacs--μπορείς να
+επιστρέψεις στην ίδια συνεδρία υστερότερα. Όταν το Emacs λειτουργεί
+εντός ακροδέκτη κειμένου, το C-z «αναστέλλει» το Emacs· δηλαδή
+επιστρέφει στο περίβλημα (shell) χωρίς να καταστρέψει την εργασία του
+Emacs. Στα πλείστα περιβλήματα, μπορείς να επαναφέρεις το Emacs με
+την εντολή «fg» ή την «%emacs».
+
+Χρησιμοποιείς το C-x C-c όταν θες να αποσυνδεθείς πλήρως. Είναι η
+σωστή πράξη για έξοδο από το Emacs, παράδειγμα για περιπτώσεις ταχείας
+επεξεργασίας κειμένου όπως στην διαχείριση ηλεκτρονικού ταχυδρομείου.
+
+Υπάρχουν πολλές εντολές του τύπου C-x. Παραθέτουμε αυτές που έμαθες:
+
+ C-x C-f Εξεύρεση αρχείου
+ C-x C-s Αποθήκευση ενταμιευτή σε αρχείο
+ C-x s Αποθήκευση μερικών ενταμιευτών στα αρχεία τους
+ C-x C-b Παράθεση ενταμιευτών
+ C-x b Μετάβαση σε ενταμιευτή
+ C-x C-c Έξοδος από το Emacs
+ C-x 1 Διαγραφή όλων πλην ενός παραθύρου
+ C-x u Αναίρεση
+
+Επώνυμες εκτεταμένες εντολές είναι αυτές που χρησιμοποιούνται με
+λιγότερη συχνότητα, ή εντολές που χρησιμοποιούνται μόνο σε
+συγκεκριμένες λειτουργίες. Ως παράδειγμα έχουμε την εντολή
+replace-string, η οποία αντικαθιστά μια σειρά (αλληλουχία) χαρακτήρων
+με μια άλλη εντός του ενταμιευτή. Όταν πληκτρολογείς M-x, το Emacs
+σε προτρέπει στο κάτω μέρος της οθόνης για το όνομα της εντολής·
+«replace-string» σε αυτή την περίπτωση. Απλά να πληκτρολογήσεις το
+«repl s<TAB>» και το Emacs θα ολοκληρώσει το όνομα. (<TAB> αναφέρεται
+στο πλήκτρο Tab, που συνήθως βρίσκεται πάνω από το Caps Lock ή το
+Shift στην αριστερή πλευρά του πληκτρολογίου.) Κατάθεσε το όνομα της
+εντολής με το <Return>.
+
+Η εντολή replace-string απαιτεί δύο παραμέτρους--την σειρά χαρακτήρων
+προς αντικατάσταση και αυτή που θα την αντικαταστήσει. Κάθε
+παράμετρος τελειώνει με το <Return>.
+
+>> Μετακίνησε τον δείκτη στην κενή γραμμή δύο γραμμές κάτω από αυτήν.
+ Πληκτρολόγησε M-x repl s<Return>αλλάξει<Return>μετατραπεί<Return>
+
+ Πρόσεξε πως αυτή η γραμμή έχει αλλάξει: αντικατέστησες την λέξη
+ «αλλάξει» με την «μετατραπεί» όπου αυτή υπήρχε μετά την αρχική θέση
+ του δείκτη.
+
+
+* ΑΥΤΟΜΑΤΗ ΑΠΟΘΗΚΕΥΣΗ
+---------------------
+
+Όταν έχεις κάνει αλλαγές σε ένα αρχείο, αλλά δεν τις έχεις αποθηκεύσει
+ακόμα, ενδέχεται να χαθούν αν ο υπολογιστής κλείσει. Για να σε
+προστατέψει από αυτό το ενδεχόμενο, το Emacs κατά διαστήματα γράφει σε
+ένα αρχείο «αυτόματης αποθήκευσης» κάθε αρχείο που επεξεργάζεσαι. Το
+όνομα αυτού του αρχείου έχει ένα # στην αρχή κι ένα στο τέλος· για
+παράδειγμα, αν το αρχείο σου ονομάζεται «hello.c», η αυτόματη
+αποθήκευση γίνεται στο «#hello.c#». Όταν αποθηκεύσεις το αρχείο με
+τον φυσιολογικό τρόπο, το Emacs διαγράφει το αρχείο αυτόματης
+αποθήκευσης.
+
+Εάν ο υπολογιστής κλείσει αναπάντεχα μπορείς να ανακτήσεις αυτό που
+επεξεργαζόσουν με το να βρεις το αρχείο (το κανονικό αρχείο, όχι αυτό
+της αυτόματης αντιγραφής του) και να πληκτρολογήσεις M-x
+recover-this-file <Return>. Όταν σου ζητηθεί επιβεβαίωση,
+πληκτρολόγησε yes<Return> για την ανάκτηση των δεδομένων.
+
+
+* ΤΟΠΟΣ ΑΝΤΗΧΗΣΗΣ
+-----------------
+
+Αν το Emacs διακρίνει πως πληκτρολογείς τους χαρακτήρες μιας
+μακροσκελούς εντολής με σχετικά αργό ρυθμό, θα σου τους δείξει στο
+κάτω μέρος της οθόνης σε αυτό που ονομάζεται «τόπος αντήχησης». Ο
+τόπος αντήχησης περιλαμβάνει την τελευταία γραμμή της οθόνης.
+
+
+* ΓΡΑΜΜΗ ΚΑΤΑΣΤΑΣΗΣ
+-------------------
+
+Η γραμμή ακριβώς πάνω από τον τόπο αντήχησης ονομάζεται «γραμμή
+κατάστασης». Αυτή αναφέρει πληροφορίες όπως:
+
+ -:**- TUTORIAL.el_GR 63% L800 (Fundamental)
+
+Αυτή η γραμμή έχει χρήσιμες πληροφορίες για την κατάσταση του Emacs
+και του κειμένου που επεξεργάζεσαι.
+
+Ήδη γνωρίζεις τι σημαίνει το πεδίο ονόματος του αρχείου--αναφέρει το
+αρχείο που έχεις επισκεφθεί. Το ΝΝ% δείχνει την τρέχουσα θέση σου
+στον ενταμιευτή του κειμένου: σημαίνει πως ΝΝ επί τις εκατό του
+ενταμιευτή βρίσκεται πέρα από το πάνω μέρος της οθόνης. Εάν το πάνω
+μέρος περιέχει όλο το προηγούμενο κείμενο, τότε θα γράφει «Top» αντί
+για «0%». Αν είναι στο κάτω μέρος του ενταμιευτή, τότε θα αναγράφει
+«Bot». Αν ο ενταμιευτής είναι μικρός ώστε όλο το περιεχόμενο του να
+χωράει στην οθόνη, τότε η γραμμή κατάστασης θα γράφει «All».
+
+Το L και τα ψηφία δείχνουν την θέση με άλλο τρόπο: τον αριθμό της
+γραμμής όπου βρίσκεται το σημείο.
+
+Οι αστερίσκοι κοντά στην αρχή δείχνουν πως έχουν υπάρξει τροποποιήσεις
+στο κείμενο. Μόλις επισκεφθείς ή αποθηκεύσεις ένα αρχείο, εκείνο το
+τμήμα δεν δείχνει αστερίσκους παρά μόνο παύλες.
+
+Το τμήμα της γραμμής κατάστασης εντός παρενθέσεων αναφέρει τις
+λειτουργίες επεξεργασίας που ισχύουν. Η βασική λειτουργία ονομάζεται
+Fundamental κι είναι αυτή που χρησιμοποιείς τώρα. Πρόκειται για
+παράδειγμα «αξιωματικής λειτουργίας» (major mode).
+
+Το Emacs έχει πολλές αξιωματικές λειτουργίες. Κάποιες αφορούν την
+επεξεργασία κειμένου σε διάφορες γλώσσες προγραμματισμού ή για διάφορα
+ήδη κειμένου, όπως Lisp mode, Text mode, κτλ. Μόνο μια αξιωματική
+λειτουργία γίνεται να είναι σε ισχύ, και το όνομα της βρίσκεται στην
+γραμμή κατάστασης όπου τώρα υπάρχει το «Fundamental».
+
+Κάθε αξιωματική λειτουργία κάνει κάποιες εντολές να συμπεριφέρονται με
+διαφορετικό τρόπο. Για παράδειγμα, υπάρχουν εντολές για την
+δημιουργία σχολίων σε ένα πρόγραμμα, και καθώς κάθε γλώσσα έχει τις
+δικές τις ιδέες για το τι συνιστά σχόλιο, η εκάστοτε αξιωματική
+λειτουργία εισάγει σχόλια ιδιοτρόπως.
+
+Κάθε αξιωματική λειτουργία φέρει το όνομα μιας εκτεταμένης εντολής,
+που είναι ένας τρόπος να αλλάξεις σε αυτή. Για παράδειγμα, M-x
+fundamental-mode είναι η εντολή που θέτει σε ισχύ το Fundamental mode.
+
+Αν θα επεξεργάζεσαι κείμενο σε ανθρώπινη γλώσσα, όπως αυτό το αρχείο,
+μάλλον θες να χρησιμοποιήσεις το Text mode.
+
+>> Πληκτρολόγησε M-x text-mode <Return>.
+
+Μην ανησυχείς, καθώς καμία από τις εντολές που έχεις μάθει δεν αλλάζει
+με ουσιαστικό τρόπο. Ωστόσο θα διαπιστώσεις πως M-f και M-b τώρα
+θεωρούν τα εισαγωγικά ως μέρος της λέξης. Πριν, στο Fundamental mode,
+M-f και M-b διάβαζαν τα εισαγωγικά ως διαχωριστικά λέξεων.
+
+Αξιωματικές λειτουργίες κάνουν τέτοιες εκλεπτυσμένες αλλαγές: οι
+πλείστες εντολές «διεκπεραιώνουν το ίδιο έργο» σε κάθε αξιωματική
+λειτουργία, αλλά ίσως το επιτυγχάνουν με ελαφρώς διαφορετικό τρόπο.
+
+Για να μάθεις περισσότερα σχετικά με την τρέχουσα αξιωματική
+λειτουργία, πληκτρολόγησε C-h m.
+
+>> Μετακίνησε τον δείκτη στην γραμμή μετά από αυτήν.
+>> Πληκτρολόγησε C-l C-l ώστε να έρθει αυτή η γραμμή στο πάνω μέρος
+ της οθόνης.
+>> Πληκτρολόγησε C-h m για να διαβάσεις πως διαφέρει το Text mode από
+ το Fundamental mode.
+>> Πληκτρολόγησε C-x 1 για να αφαιρέσεις την καταγραφή από την οθόνη.
+
+Οι αξιωματικές λειτουργίες ονομάζονται έτσι διότι υπάρχουν και οι
+ελάσσονες λειτουργίες (minor modes). Ελάσσονες λειτουργίες δεν
+υποκαθιστούν τις αξιωματικές λειτουργίες, παρά μόνο επί μέρους πτυχές
+τους. Κάθε ελάσσων λειτουργία μπορεί να ενεργοποιηθεί ή
+απενεργοποιηθεί αυτοτελώς, ανεξάρτητα από άλλες ελάσσονες λειτουργίες
+ή οποιονδήποτε συνδυασμό τους.
+
+Μια ελάσσων λειτουργία που είναι πολύ χρήσιμη, ειδικά για την
+επεξεργασία κειμένου ανθρώπινης γλώσσας, είναι η Auto Fill mode. Όταν
+αυτή η λειτουργία ενεργοποιηθεί, το Emacs αυτόματα διαχωρίζει τις
+γραμμές μεταξύ των λέξεων όταν αυτές γίνονται πολύ πλατιές.
+
+Το Auto Fill mode ενεργοποιείται με M-x auto-fill-mode <Return>. Όταν
+η λειτουργία είναι σε ισχύ, μπορεί να απενεργοποιηθεί πάλι με M-x
+auto-fill-mode <Return>. Αν είναι απενεργοποιημένη, τότε η εντολή
+αυτή την ενεργοποιεί, και το αντίστροφο. Λέμε πως η εντολή
+«εναλλάσσει την λειτουργία».
+
+>> Πληκτρολόγησε M-x auto-fill-mode <Return> τώρα. Κατόπιν
+ πληκτρολόγησε μια γραμμή με «ασδφ » πολλές φορές ως που να δεις ότι
+ διαιρείται σε δύο γραμμές. Πρέπει να έχει κενά μεταξύ των
+ χαρακτήρων, διότι μόνο με βάση αυτά λειτουργεί το Auto Fill (δεν
+ κόβει λέξεις).
+
+Το μήκος συνήθως ορίζεται στους 70 χαρακτήρες, αλλά μπορείς να το
+αλλάξεις με την εντολή C-x f. Όρισε τον αριθμό που επιθυμείς ως
+αριθμητική παράμετρο.
+
+>> Πληκτρολόγησε C-x f με παράμετρο το 20. (C-u 2 0 C-x f). Κατόπιν
+ πληκτρολόγησε τυχαίο κείμενο με κενά και πρόσεξε πως το Emacs
+ συμπληρώνει τις γραμμές έως τους 20 χαρακτήρες. Μετά θέσε πάλι το
+ μήκος τους 70 χαρακτήρες χρησιμοποιώντας C-x f με αριθμητική
+ παράμετρο.
+
+Αν κάνεις αλλαγές στην μέση της παραγράφου, το Auto Fill mode δεν
+επανασυμπληρώνει για χάρη σου.
+Για να επανασυμπληρώσεις μια παράγραφο χειροκίνητα, πληκτρολόγησε M-q
+(META-q) με τον δείκτη εντός της παραγράφου εκείνης.
+
+>> Μετακίνησε τον δείκτη στην προηγούμενη παράγραφο και πληκτρολόγησε
+ M-q.
+
+
+* ΑΝΑΖΗΤΗΣΗ
+-----------
+
+Το Emacs μπορεί να αναζητήσει σειρές (σειρά (string) είναι αλληλουχία
+χαρακτήρων) είτε προς τα εμπρός είτε ανάποδα. Αναζήτηση σειράς
+συνιστά κίνηση του δείκτη· μετακινεί τον δείκτη όπου εμφανίζεται η
+σειρά.
+
+Η εντολή αναζήτησης του Emacs είναι «τμηματική». Αυτό σημαίνει πως η
+αναζήτηση γίνεται ενόσω δακτυλογραφείς τους χαρακτήρες της σειράς που
+αναζητείς.
+
+Η εντολή προς εκκίνηση αναζήτησης είναι C-s για κίνηση προς τα εμπρός
+και C-r και κίνηση όπισθεν. ΑΛΛΑ ΠΕΡΙΜΕΝΕ! Μην τις δοκιμάσεις ακόμα.
+
+Όταν πληκτρολογείς C-s θα δεις πως η σειρά «I-search» εμφανίζεται ως
+προτροπή στον τόπο αντήχησης. Αυτό σου λέει πως το Emacs βρίσκεται σε
+αυτό που ονομάζεται «τμηματική αναζήτηση» και περιμένει να
+πληκτρολογήσεις αυτό το οποίο ψάχνεις. <Return> ολοκληρώνει την
+αναζήτηση.
+
+>> Τώρα πληκτρολόγησε C-s για να αρχίσεις την αναζήτηση. ΑΡΓΑ, ένα
+ γράμμα τη φορά, γράψε «δείκτη», κάνοντας παύση αφού εισάγεις τον
+ κάθε χαρακτήρα για να δεις τι συμβαίνει με τον δείκτη.
+ Τώρα έχεις αναζητήσει για «δείκτη» μία φορά.
+>> Πάτα πάλι C-s για να ψάξεις την επόμενη εμφάνιση του «δείκτη».
+>> Τώρα πληκτρολόγησε <DEL> τέσσερις φορές και δες πως κινείται ο
+ δείκτης.
+>> Πληκτρολόγησε <Return> για να τερματίσεις την αναζήτηση.
+
+Είδες τι έγινε; Το Emacs, σε τμηματική αναζήτηση, προσπαθεί να
+εντοπίσει την επόμενη εμφάνιση της σειράς χαρακτήρων που έγραψες. Για
+να μεταφερθείς στην επόμενη εμφάνιση, πάτα C-s ξανά. Εάν δεν υπάρχει
+άλλη, το Emacs θα σηματοδοτήσει «αποτυχία» (failing). Το C-g μπορεί
+να τερματίσει την αναζήτηση.
+
+Κατά την διάρκεια μιας τμηματικής αναζήτησης εάν πατήσεις <DEL>, η
+αναζήτηση «υποχωρεί» σε πρότερο σημείο. Αν πατήσεις <DEL> αμέσως
+αφότου έχεις πληκτρολογήσει C-s για μετακίνηση στην επόμενη εμφάνιση
+μιας σειράς χαρακτήρων, θα μεταβείς πίσω στην προηγούμενη εμφάνιση.
+Εάν δεν υπάρχει προηγούμενη εμφάνιση, το <DEL> διαγράφει τον τελευταίο
+χαρακτήρα στην σειρά. Για παράδειγμα, φαντάσου πως έγραψες «δ» για να
+βρεις την πρώτη εμφάνιση του. Τώρα αν προσθέσεις το «ε» θα πας στην
+πρώτη εμφάνιση του «δε». Τώρα πάτα <DEL>. Διαγράφει το «ε» από την
+σειρά και μετακινεί τον δείκτη πίσω στην πρώτη εμφάνιση του «δ».
+
+Αν είσαι στο μέσον μιας αναζήτησης και πληκτρολογήσεις ένα χαρακτήρα
+control ή meta (με κάποιες εξαιρέσεις--όπως C-s και C-r που έχουν
+ειδική σημασία στην αναζήτηση), η αναζήτηση θα τερματιστεί.
+
+Το C-s ξεκινά αναζήτηση που ψάχνει για κάθε εμφάνιση της αναζητούμενης
+σειράς ΑΠΟ την τρέχουσα θέση του δείκτη. Εάν θες να βρεις
+προηγούμενες εμφανίσεις, χρησιμοποίησε το C-r. Όσα είπαμε για το C-s
+ισχύουν για το C-r, με μόνη διαφορά την κατεύθυνση της αναζήτησης.
+
+
+* ΠΟΛΛΑΠΛΑ ΠΑΡΑΘΥΡΑ
+-------------------
+
+Ένα από τα καλά του Emacs είναι πως μπορείς να παρουσιάσεις πέραν του
+ενός παραθύρου στην οθόνη. (Σημείωσε πως το Emacs χρησιμοποιεί τον
+όρο «πλαίσιο» (frame)--επεξηγείται στην επόμενη ενότητα--για αυτό που
+ορισμένες εφαρμογές αποκαλούν «παράθυρο» (window). Το εγχειρίδιο του
+Emacs περιέχει γλωσσάριο με όλους τους όρους.)
+
+>> Φέρε τον δείκτη σε αυτή την γραμμή και πληκτρολόγησε C-l C-l.
+
+>> Τώρα πάτα C-x 2, που μοιράζει την οθόνη σε δύο παράθυρα.
+ Και τα δύο παράθυρα παρουσιάζουν αυτή την εκμάθηση. Ο δείκτης
+ επεξεργασίας παραμένει στο πάνω παράθυρο.
+
+>> Πληκτρολόγησε C-M-v για να κυλήσεις το κάτω παράθυρο. (Εάν δεν
+ έχεις META ή ALT πλήκτρο, τότε πληκτρολόγησε <ESC> C-v.)
+
+>> Πληκτρολόγησε C-x o («o» είναι για το «άλλο» στην αγγλική (other))
+ ώστε να επιλέξεις το έτερο παράθυρο.
+
+>> Χρησιμοποίησε C-v και M-v στο κάτω παράθυρο για να το κυλήσεις.
+ Συνέχισε να διαβάζεις αυτές τις οδηγίες στο πάνω παράθυρο.
+
+>> Πάτα C-x o και πάλι ώστε να φέρεις τον δείκτη πίσω στο πάνω
+ παράθυρο. Ο δείκτης στο πάνω παράθυρο είναι εκεί που ήταν και
+ πριν.
+
+Μπορείς να συνεχίσεις να χρησιμοποιείς C-x o για εναλλαγή μεταξύ των
+παραθύρων. Το «επιλεγμένο παράθυρο», όπου γίνεται η επεξεργασία,
+είναι αυτό που έχει ένα φανερό δείκτη που αναβοσβήνει καθώς γράφεις.
+Τα άλλα παράθυρα έχουν τις δικές τους θέσεις για τον δείκτη· αν
+χρησιμοποιείς γραφική προβολή του Emacs, αυτοί οι δείκτες
+παρουσιάζονται ως άδεια κουτιά που δεν αναβοσβήνουν.
+
+Η εντολή C-M-v είναι πολύ χρήσιμη όταν επεξεργάζεται κείμενο σε ένα
+παράθυρο και χρησιμοποιείς το έτερο παράθυρο για αναφορά. Χωρίς να
+φύγεις από το επιλεγμένο παράθυρο, μπορείς να κυλήσεις το παράθυρο με
+C-M-v.
+
+Το C-M-v αποτελεί παράδειγμα CONTROL-META χαρακτήρα. Αν έχεις META (ή
+ALT) πλήκτρο, πληκτρολογείς C-M-v κρατώντας πατημένα τόσο το CONTROL
+όσο και το META και πληκτρολογώντας v. Δεν έχει σημασία αν το CONTROL
+ή το META «έρχεται πρώτο», καθώς αμφότερα μεταβάλουν τον χαρακτήρα που
+εισάγεις.
+
+Αν δεν έχεις το πλήκτρο META (ή ALT), και χρησιμοποιείς το <ESC>, τότε
+η σειρά έχει σημασία: πρώτα πατάς κι αφήνεις το <ESC> κι ακολουθείς με
+CONTROL-v, διότι CONTROL-<ESC>-v δεν θα δουλέψει. Αυτό γιατί το <ESC>
+είναι χαρακτήρας από μόνο του, κι όχι πλήκτρο μετατροπής χαρακτήρων.
+
+>> Πληκτρολόγησε C-x 1 στο πάνω παράθυρο για να κλείσεις το κάτω
+ παράθυρο.
+
+(Άν πατούσες C-x 1 στο κάτω παράθυρο, θα έκλεινες το πάνω. Φαντάσου
+πως αυτή η εντολή λέει «κράτα ένα παράθυρο--αυτό που έχω επιλεγμένο.»)
+
+Δεν είναι απαραίτητο να παρουσιάζεις τον ίδιο ενταμιευτή σε πολλά
+παράθυρα. Αν χρησιμοποιήσεις το C-x C-f για να βρεις ένα αρχείο στο
+ένα παράθυρο, το έτερο παράθυρο δεν αλλάζει. Μπορείς να βρεις ένα
+αρχείο σε κάθε παράθυρο ανεξάρτητα από τα άλλα.
+
+Ιδού άλλος ένα τρόπος για να χρησιμοποιείς δύο παράθυρα που δείχνουν
+διαφορετικά πράγματα:
+
+>> Πληκτρολόγησε C-x 4 C-f και δώσε όνομα αρχείου στην σχετική
+ προτροπή που εμφανίζεται στο κάτω μέρος της οθόνης. Επικύρωσε την
+ επιλογή σου με το <Return>. Δες πως το επιλεγμένο αρχείο
+ εμφανίζεται στο κάτω παράθυρο. Ο δείκτης πάει κι αυτός εκεί.
+
+>> Πληκτρολόγησε C-x o για να επιστρέψεις στο πάνω παράθυρο και μετά
+ C-x 1 για να κλείσεις το κάτω παράθυρο.
+
+
+* ΠΟΛΛΑΠΛΑ ΠΛΑΙΣΙΑ
+------------------
+
+Το Emacs μπορεί επίσης να δημιουργήσει πολλά «πλαίσια». Πλαίσιο
+ονομάζουμε αυτό που περιέχει ένα ή περισσότερα παράθυρα, μαζί με τα
+μενού, μπάρες κύλισης, τόπο αντήχησης, κτλ. Σε γραφικές προβολές,
+αυτό που το Emacs αποκαλεί «πλαίσιο» είναι το ίδιο που άλλες εφαρμογές
+ονομάζουν «παράθυρο». Πολλά γραφικά πλαίσια μπορούν να εμφανίζονται
+στην οθόνη ταυτόχρονα. Σε ακροδέκτη κειμένου, μόνο ένα πλαίσιο μπορεί
+να παρουσιάζεται κάθε φορά.
+
+>> Πληκτρολόγησε C-x 5 2.
+ Δες ένα νέο πλαίσιο που εμφανίστηκε στην οθόνη.
+
+Μπορείς να κάνεις όσα έκανες στο αρχικό πλαίσιο και στο νέο πλαίσιο.
+Δεν υπάρχει τίποτα το ειδικό για το ένα ή το άλλο.
+
+>> Πληκτρολόγησε C-x 5 0.
+ Αυτό αφαιρεί το επιλεγμένο πλαίσιο.
+
+Μπορείς πάντοτε να αφαιρέσεις ένα πλαίσιο με τον κοινό τρόπο που
+προσφέρει το σύστημα γραφικών (συνήθως πατάς με το ποντίκι πάνω σε ένα
+εικονίδιο «X» σε ένα από τα πάνω άκρα του πλαισίου). Αν αφαιρέσεις το
+τελευταίο πλαίσιο της λειτουργίας του Emacs κατά αυτόν τον τρόπο, τότε
+κλείνει το Emacs.
+
+
+* ΕΠΙΠΕΔΑ ΑΝΑΔΡΟΜΙΚΗΣ ΕΠΕΞΕΡΓΑΣΙΑΣ
+----------------------------------
+
+Κάποιες φορές θα βρεθείς σε αυτό που ονομάζουμε «επίπεδο αναδρομικής
+επεξεργασίας». Αυτό επισημαίνεται από αγκύλες στην γραμμή κατάστασης
+που περιβάλλουν τις παρενθέσεις γύρω από την αξιωματική λειτουργία.
+Για παράδειγμα, ίσως δεις [(Fundamental)] αντί για (Fundamental).
+
+Για να βγεις από επίπεδο αναδρομικής επεξεργασίας, πληκτρολόγησε <ESC>
+<ESC> <ESC>. Αυτή είναι η γενική εντολή εξόδου. Μπορείς να την
+χρησιμοποιήσεις για να κλείσεις όλα τα έτερα παράθυρα και για να βγεις
+από τον μικροενταμιευτή.
+
+>> Πληκτρολόγησε M-x για να μπεις στον μικροενταμιευτή· κατόπιν πάτα
+ <ESC> <ESC> <ESC> για να εξέλθεις.
+
+Δεν μπορείς να χρησιμοποιήσεις C-g για να βγεις από επίπεδο
+αναδρομικής επεξεργασίας. Αυτό είναι έτσι γιατί το C-g ακυρώνει
+εντολές ή τις παραμέτρους αυτών ΕΝΤΟΣ του τρέχοντος επιπέδου
+αναδρομικής επεξεργασίας.
+
+
+* ΠΕΡΙΣΣΟΤΕΡΗ ΒΟΗΘΕΙΑ
+---------------------
+
+Σε αυτό τον οδηγό προσπαθήσαμε να προσφέρουμε βασικές γνώσεις για να
+αρχίσεις να χρησιμοποιείς το Emacs. Υπάρχουν τόσα πολλά στο Emacs που
+θα ήταν αδύνατο να τα εξηγήσουμε όλα εδώ. Ωστόσο, μάλλον θα θέλεις να
+μάθεις περισσότερα για τις διάφορες δυνατότητες που παρέχει το Emacs.
+Προς αυτόν τον σκοπό, το Emacs προσφέρει εντολές για την εξεύρεση κι
+ανάγνωση οδηγιών. Αυτές οι εντολές «βοήθειας» (help) όλες αρχίζουν με
+τον χαρακτήρα CONTROL-h, που αποκαλείται «ο χαρακτήρας βοηθείας».
+
+Για να χρησιμοποιήσεις τις υπηρεσίες βοηθείας, πληκτρολόγησε C-h, και
+μετά ένα χαρακτήρα που ανταποκρίνεται στο είδος της βοήθειας που
+επιζητείς. Αν είσαι σε ΠΡΑΓΜΑΤΙΚΑ δύσκολη θέση, πάτα C-h ? και το
+Emacs θα σου πει τι είδη βοηθείας υπάρχουν. Αν έχεις ήδη πατήσει C-h
+και αποφάσισες πως δεν θέλεις καμία βοήθεια, απλά ακύρωσε το με C-g.
+
+(Αν το C-h δεν προβάλει μήνυμα για βοήθεια στο κάτω μέρος της οθόνης,
+δοκίμασε το πλήκτρο F1, αλλιώς M-x help <Return>.)
+
+Η πιο βασική βοήθεια προσφέρεται από το C-h c. Πληκτρολόγησε C-h,
+ύστερα το c, και μετά τον χαρακτήρα ή αλληλουχία χαρακτήρων
+οποιασδήποτε εντολής: το Emacs θα εμφανίσει μια σύντομη περιγραφή της
+εντολής.
+
+>> Πληκτρολόγησε C-h c C-p
+
+Το μήνυμα θα είναι κάπως έτσι:
+
+ C-p εκτελεί την εντολή previous-line
+
+Αυτό σου λέει το «όνομα της συνάρτησης». Καθώς οι συναρτήσεις έχουν
+ονόματα που φανερώνουν την λειτουργία τους, μπορούν να ερμηνευθούν κι
+ως πολύ σύντομες περιγραφές--επαρκείς για να σου υπενθυμίσουν κάτι που
+ήδη έχεις μάθει.
+
+Εντολές με πολλούς χαρακτήρες, όπως C-x C-s ή <ESC>v (αντί του M-v για
+όσους δεν έχουν πλήκτρο META ή ALT) μπορούν κι αυτές να δοθούν μετά το
+C-h c.
+
+Για περισσότερες πληροφορίες αναφορικά με μια εντολή, χρησιμοποίησε το
+C-h k αντί του C-h c.
+
+>> Πληκτρολόγησε C-h k C-p.
+
+Αυτό δείχνει την πλήρη καταγραφή της συνάρτησης, καθώς και το όνομα
+της, σε νέο παράθυρο του Emacs. Όταν το διαβάσεις, πάτα C-x 1 για να
+κλείσεις εκείνο το παράθυρο. Δεν χρειάζεται να το κάνεις αυτό αμέσως.
+Ίσως θες πρώτα να επεξεργαστείς κάτι καθώς αναφέρεσαι στο κείμενο
+βοηθείας και μετά να πληκτρολογήσεις C-x 1.
+
+Ιδού άλλες χρήσιμες επιλογές με το C-h:
+
+ C-h x Περιέγραψε μια εντολή. Ζητά το όνομα της εντολής.
+
+>> Προσπάθησε C-h x previous-line <Return>.
+ Δείχνει όλες τις πληροφορίες που έχει το Emacs σχετικά με την
+ συνάρτηση που δίνει την εντολή C-p.
+
+Παρόμοια εντολή είναι αυτή του C-h v που δείχνει την καταγραφή μιας
+μεταβλητής, συμπεριλαμβανομένων αυτών που μπορείς να τροποποιήσεις για
+να αλλάξεις την συμπεριφορά του Emacs. Πρέπει να γράψεις το όνομα της
+μεταβλητής στην σχετική προτροπή.
+
+ C-h a Συναφή εντολών (command apropos). Γράψε μια
+ λέξη-κλειδί και το Emacs θα παραθέσει όλες τις εντολές
+ των οποίων το όνομα περιέχει αυτήν την λέξη. Όλες
+ αυτές οι εντολές μπορούν να κληθούν με το META-x. Για
+ ορισμένες εντολές, τα συναφή εντολών περιέχουν και την
+ σχετική αλληλουχία χαρακτήρων που εκτελεί την εντολή.
+
+>> Πληκτρολόγησε C-h a file <Return>.
+
+Αυτό παραθέτει σε έτερο παράθυρο όλες τις εντολές M-x που περιέχουν
+τον όρο «file» στο όνομα τους. Θα δεις εντολές χαρακτήρος μεταξύ των
+επονομαζομένων (όπως C-x C-f πέριξ του find-file).
+
+>> Πληκτρολόγησε C-M-v για να κυλήσεις το παράθυρο βοηθείας. Κάνε το
+ μερικές φορές.
+
+>> Πληκτρολόγησε C-x 1 για να κλείσεις το παράθυρο βοηθείας.
+
+ C-h i Διάβασε τα εγχειρίδια (Info manuals). Αυτή η εντολή
+ σε βάζει σε ειδικό ενταμιευτή που ονομάζεται «*info*»
+ όπου μπορείς να διαβάσεις εγχειρίδια για τις
+ συσκευασίες που είναι εγκατεστημένες στο σύστημα σου.
+ Πληκτρολόγησε m emacs <Return> για να διαβάσεις το
+ εγχειρίδιο του Emacs. Αν δεν έχεις χρησιμοποιήσει το
+ Info ποτέ, πληκτρολόγησε h και το Emacs θα σου δείξει
+ τις σχετικές λειτουργίες. Αφού ολοκληρώσεις αυτή την
+ εκμάθηση, να αναφέρεσε στο εγχειρίδιο του Emacs ως την
+ κύρια πηγή όλων των καταγραφών.
+
+
+* ΑΛΛΕΣ ΛΕΙΤΟΥΡΓΙΕΣ
+-------------------
+
+Μπορείς να μάθεις περισσότερα για το Emacs διαβάζοντας το εγχειρίδιο
+του, είτε ως έντυπο βιβλίο, είτε εντός του Emacs (χρησιμοποίησε τον
+κατάλογο βοηθείας ή πληκτρολόγησε C-h r). Δύο λειτουργίες που ίσως να
+σου φανούν χρήσιμες είναι η «ολοκλήρωση», που εξοικονομεί στην
+δακτυλογράφηση, και το Dired, που απλοποιεί την διαχείριση αρχείων.
+
+Η ολοκλήρωση είναι τρόπος αποφυγής αχρείαστης πληκτρολόγησης. Για
+παράδειγμα, αν θες να μεταβείς στον ενταμιευτή *Messages*,
+πληκτρολογείς C-x b *M<Tab> και το Emacs θα συμπληρώσει το υπόλοιπο
+του ονόματος ως εκεί που μπορεί να κρίνει αντιστοιχία με αυτό που
+έχεις ήδη γράψει. Η ολοκλήρωση δουλεύει επίσης για ονόματα εντολών κι
+αρχείων. Στο εγχειρίδιο καταγράφεται στην ενότητα «Completion».
+
+Το Dired σου επιτρέπει να παραθέτεις κατάλογο αρχείων (και προαιρετικά
+υποκαταλόγους), να επιλέγεις, επισκέπτεσαι, μετονομάζεις, διαγράφεις,
+ή γενικά να επιδράς πάνω σε αρχεία. Το Dired καταγράφεται στο
+εγχειρίδιο στην ενότητα «Dired».
+
+Το εγχειρίδιο καταγράφει πολλές άλλες λειτουργίες του Emacs.
+
+
+* ΕΓΚΑΤΑΣΤΑΣΗ ΣΥΣΚΕΥΑΣΙΩΝ
+-------------------------
+
+Υπάρχει πλούσιος όγκος συσκευασιών (packages) του Emacs που έχουν
+παρασκευαστεί από την κοινότητα των χρηστών του, που επεκτείνουν τις
+δυνατότητες του Emacs. Αυτές οι συσκευασίες περιλαμβάνουν υποστήριξη
+για νέες γλώσσες, πρόσθετα θέματα χρωμάτων, προεκτάσεις για εξωτερικές
+εφαρμογές, και άλλα πολλά.
+
+Για παράθεση των διαθέσιμων συσκευασιών, πληκτρολόγησε M-x
+list-packages. Στη σχετική λίστα, μπορείς να εγκαταστήσεις ή
+απεγκαταστήσεις συσκευασίες, καθώς και να διαβάσεις τις περιγραφές
+τους. Για περισσότερες πληροφορίες περί διαχείρισης συσκευασιών, δες
+το εγχειρίδιο του Emacs.
+
+
+* ΚΑΤΑΛΗΚΤΙΚΑ
+-------------
+
+Για έξοδο από το Emacs, χρησιμοποίησε C-x C-c.
+
+Αυτή η εκμάθηση γράφτηκε για να είναι κατανοητή σε όλους τους νέους
+χρήστες. Αν λοιπόν κάτι παραμένει ασαφές, μην κάτσεις εκεί να
+κατηγορείς τον εαυτό σου - πες μας για το πρόβλημα σου!
+
+
+* ΑΝΤΙΓΡΑΦΗ
+-----------
+
+Αυτό το κείμενο εκμάθησης είναι συνέχεια μιας μακράς γραμμής κειμένων
+εκμάθησης του Emacs, αρχής γενομένης αυτού του Stuart Cracraft για το
+αρχικό Emacs.
+
+Αυτή η έκδοση της εκμάθησης είναι μέρος του GNU Emacs. Έχει
+πνευματικά δικαιώματα και δίνεται με την άδεια διανομής αντιγράφων υπό
+κάποιους όρους.
+
+ Πνευματικά Δικαιώματα (C) 1985, 1996, 1998, 2001-2022 Free Software
+ Foundation, Inc.
+
+ Αυτό το αρχείο είναι μέρος του GNU Emacs.
+
+ Το GNU Emacs είναι ελεύθερο λογισμικό: μπορείτε να το αναδιανέμετε
+ ή/και να το τροποποιήσετε σύμφωνα με τους όρους της GNU Γενική
+ Δημόσια Άδεια (GNU General Public License) όπως δημοσιεύθηκε από το
+ Ίδρυμα Ελεύθερου Λογισμικού (Free Software Foundation), είτε την
+ έκδοση 3 της άδειας, είτε (κατά την επιλογή σας) οποιαδήποτε
+ μεταγενέστερη έκδοση.
+
+ Το GNU Emacs διανέμεται με την ελπίδα πως θα είναι χρήσιμο, αλλά
+ ΧΩΡΙΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ· χωρίς καν την συνεπαγόμενη εγγύηση της
+ ΕΜΠΟΡΕΥΣΙΜΟΤΗΤΑΣ ή ΚΑΤΑΛΛΗΛΟΤΗΤΑΣ ΓΙΑ ΣΥΓΚΕΚΡΙΜΕΝΟ ΣΚΟΠΟ. Δείτε την
+ GNU Γενική Δημόσια Άδεια (GNU General Public License) για
+ περισσότερες λεπτομέρειες.
+
+ Οφείλατε να λάβετε αντίγραφο της GNU Γενικής Δημόσιας Άδειας (GNU
+ General Public License) μαζί με το GNU Emacs. Εάν όχι, δείτε
+ <https://www.gnu.org/licenses/>.
+
+Παρακαλώ όπως διαβάσετε το αρχείο COPYING και δώσετε αντίγραφα του GNU
+Emacs στους φίλους σας. Βοηθήστε στην καταπολέμηση του περιορισμού
+(«ιδιοκτησία») του λογισμικού δια της χρήσης, γραφής, και κοινοποίησης
+ελεύθερου λογισμικού!
diff --git a/etc/tutorials/TUTORIAL.it b/etc/tutorials/TUTORIAL.it
index dba941cfd57..d7682a4a624 100644
--- a/etc/tutorials/TUTORIAL.it
+++ b/etc/tutorials/TUTORIAL.it
@@ -1110,7 +1110,7 @@ mentre fai riferimento al testo di aiuto e poi usare un C-x 1.
Ecco altre utili opzioni di C-h:
- C-h x Descrive un comando. Inserisci il nome della comando.
+ C-h x Descrive un comando. Inserisci il nome del comando.
>> Prova con C-h x previous-line <Invio>.
Questo mostrerà tutte le informazioni che Emacs possiede sulla
diff --git a/etc/tutorials/TUTORIAL.nl b/etc/tutorials/TUTORIAL.nl
index 2ec3fac11bd..7aaed218ff6 100644
--- a/etc/tutorials/TUTORIAL.nl
+++ b/etc/tutorials/TUTORIAL.nl
@@ -1158,7 +1158,7 @@ overeenkomende commandonaam zoals find-file.
--------------------
Je kunt meer over Emacs leren door haar handleiding te lezen. Deze is
-zowel als boek als in in Emacs beschikbaar (gebruik het Help menu of
+zowel als boek als in Emacs beschikbaar (gebruik het Help menu of
tik C-h r). Kijk bijvoorbeeld eens naar "completion", wat minder
tikwerk oplevert, of "dired" wat het omgaan met bestanden
vereenvoudigt.
diff --git a/etc/tutorials/TUTORIAL.translators b/etc/tutorials/TUTORIAL.translators
index b6b95787068..891b6a16824 100644
--- a/etc/tutorials/TUTORIAL.translators
+++ b/etc/tutorials/TUTORIAL.translators
@@ -26,6 +26,10 @@ Maintainer: Dale Gulledge <dsplat@rochester.rr.com>
Author: Rafael Sepúlveda <drs@gnulinux.org.mx>
Maintainer: Rafael Sepúlveda <drs@gnulinux.org.mx>
+* TUTORIAL.el_GR:
+Author: Protesilaos Stavrou <info@protesilaos.com>
+Maintainer: Protesilaos Stavrou <info@protesilaos.com>
+
* TUTORIAL.fr:
Author: Éric Jacoboni <jaco@teaser.fr>
Maintainer: Éric Jacoboni <jaco@teaser.fr>
diff --git a/leim/Makefile.in b/leim/Makefile.in
index a574a108454..29b9f3b2f86 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -32,18 +32,23 @@ leimdir = ${srcdir}/../lisp/leim
EXEEXT = @EXEEXT@
+SMALL_JA_DIC = @SMALL_JA_DIC@
+JA_DIC_NO_REDUCTION_OPTION = --no-reduction
+ifeq ($(SMALL_JA_DIC), yes)
+ JA_DIC_NO_REDUCTION_OPTION =
+endif
+
-include ${top_builddir}/src/verbose.mk
# Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
# Which Emacs to use to convert TIT files to Emacs Lisp files,
# and generate the file leim-list.el.
EMACS = ../src/emacs${EXEEXT}
# How to run Emacs.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems.
-RUN_EMACS = EMACSLOADPATH= '$(EMACS)' -batch --no-site-file --no-site-lisp
+RUN_EMACS = '$(EMACS)' -batch --no-site-file --no-site-lisp
MKDIR_P = @MKDIR_P@
@@ -81,7 +86,7 @@ MISC= \
TIT_MISC = ${TIT_GB} ${TIT_BIG5} ${MISC}
-all: ${leimdir}/leim-list.el ${leimdir}/ja-dic/ja-dic.el
+all: ${leimdir}/leim-list.el
.PHONY: all
@@ -123,15 +128,19 @@ leim-list.el: ${leimdir}/leim-list.el
${leimdir}/leim-list.el: ${srcdir}/leim-ext.el ${TIT_MISC}
$(AM_V_GEN)rm -f $@
$(AM_V_at)${RUN_EMACS} -l international/quail \
+ --eval "(setq max-specpdl-size 5000)" \
--eval "(update-leim-list-file (unmsys--file-name \"${leimdir}\"))"
$(AM_V_at)sed -n -e '/^[^;]/p' -e 's/^;\(;*\)inc /;\1 /p' < $< >> $@
${leimdir}/ja-dic/ja-dic.el: | $(leimdir)/ja-dic
+.PHONY: generate-ja-dic
+generate-ja-dic: ${leimdir}/ja-dic/ja-dic.el
${leimdir}/ja-dic/ja-dic.el: $(srcdir)/SKK-DIC/SKK-JISYO.L
$(AM_V_GEN)$(RUN_EMACS) -batch -l ja-dic-cnv \
- -f batch-skkdic-convert -dir "$(leimdir)/ja-dic" "$<"
+ --eval "(setq max-specpdl-size 5000)" \
+ -f batch-skkdic-convert -dir "$(leimdir)/ja-dic" $(JA_DIC_NO_REDUCTION_OPTION) "$<"
${srcdir}/../lisp/language/pinyin.el: ${srcdir}/MISC-DIC/pinyin.map
$(AM_V_GEN)${RUN_EMACS} -l titdic-cnv -f pinyin-convert $< $@
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index c25ba5c974d..0453b935068 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -20,6 +20,9 @@
SHELL = @SHELL@
+# Prevent any settings in the user environment causing problems.
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
+
# Following ../lisp/Makefile.in.
EMACS = ../src/emacs${EXEEXT}
EMACSOPT = -batch --no-site-file --no-site-lisp
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 <https://www.gnu.org/licenses/>. */
#include <Application.h>
#include <Catalog.h>
#include <Roster.h>
+#include <Bitmap.h>
+#include <Rect.h>
+#include <View.h>
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/lib-src/ebrowse.c b/lib-src/ebrowse.c
index 04ae018464e..641570da02e 100644
--- a/lib-src/ebrowse.c
+++ b/lib-src/ebrowse.c
@@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <assert.h>
#include <getopt.h>
+#include <attribute.h>
#include <flexmember.h>
#include <min-max.h>
#include <unlocked-io.h>
@@ -1208,17 +1209,14 @@ sym_scope (struct sym *p)
}
-/* Dump the list of members M to file FP. Value is the length of the
- list. */
+/* Dump the list of members M to file FP. */
-static int
+static void
dump_members (FILE *fp, struct member *m)
{
- int n;
-
putc ('(', fp);
- for (n = 0; m; m = m->next, ++n)
+ for (; m; m = m->next)
{
fputs (MEMBER_STRUCT, fp);
putstr (m->name, fp);
@@ -1238,7 +1236,6 @@ dump_members (FILE *fp, struct member *m)
putc (')', fp);
putc ('\n', fp);
- return n;
}
@@ -1267,15 +1264,11 @@ dump_sym (FILE *fp, struct sym *root)
}
-/* Dump class ROOT and its subclasses to file FP. Value is the
- number of classes written. */
+/* Dump class ROOT and its subclasses to file FP. */
-static int
+static void
dump_tree (FILE *fp, struct sym *root)
{
- struct link *lk;
- unsigned n = 0;
-
dump_sym (fp, root);
if (f_verbose)
@@ -1286,20 +1279,20 @@ dump_tree (FILE *fp, struct sym *root)
putc ('(', fp);
- for (lk = root->subs; lk; lk = lk->next)
+ for (struct link *lk = root->subs; lk; lk = lk->next)
{
fputs (TREE_STRUCT, fp);
- n += dump_tree (fp, lk->sym);
+ dump_tree (fp, lk->sym);
putc (']', fp);
}
putc (')', fp);
dump_members (fp, root->vars);
- n += dump_members (fp, root->fns);
+ dump_members (fp, root->fns);
dump_members (fp, root->static_vars);
- n += dump_members (fp, root->static_fns);
- n += dump_members (fp, root->friends);
+ dump_members (fp, root->static_fns);
+ dump_members (fp, root->friends);
dump_members (fp, root->types);
/* Superclasses. */
@@ -1311,7 +1304,6 @@ dump_tree (FILE *fp, struct sym *root)
putc (')', fp);
putc ('\n', fp);
- return n;
}
@@ -1320,9 +1312,6 @@ dump_tree (FILE *fp, struct sym *root)
static void
dump_roots (FILE *fp)
{
- int i, n = 0;
- struct sym *r;
-
/* Output file header containing version string, command line
options etc. */
if (!f_append)
@@ -1346,12 +1335,12 @@ dump_roots (FILE *fp)
mark_inherited_virtual ();
/* Dump the roots of the graph. */
- for (i = 0; i < TABLE_SIZE; ++i)
- for (r = class_table[i]; r; r = r->next)
+ for (int i = 0; i < TABLE_SIZE; ++i)
+ for (struct sym *r = class_table[i]; r; r = r->next)
if (!r->supers)
{
fputs (TREE_STRUCT, fp);
- n += dump_tree (fp, r);
+ dump_tree (fp, r);
putc (']', fp);
}
@@ -1925,7 +1914,15 @@ matching_regexp (void)
*--s = *--t;
if (*s == '"' || *s == '\\')
- *--s = '\\';
+ {
+ if (s > matching_regexp_buffer)
+ *--s = '\\';
+ else
+ {
+ s++;
+ break;
+ }
+ }
}
*(matching_regexp_end_buf - 1) = '\0';
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 365e803e1cd..73c8e45a865 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -80,6 +80,7 @@ char *w32_getenv (const char *);
#include <sys/stat.h>
#include <unistd.h>
+#include <attribute.h>
#include <filename.h>
#include <intprops.h>
#include <min-max.h>
@@ -1430,8 +1431,7 @@ local_sockname (int s, char sockname[socknamesize], int tmpdirlen,
char *emacsdirend = sockname + tmpdirlen + suffixlen -
strlen(server_name) - 1;
*emacsdirend = '\0';
- int dir = openat (AT_FDCWD, sockname,
- O_PATH | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ int dir = open (sockname, O_PATH | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
*emacsdirend = '/';
if (dir < 0)
return errno;
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 758c7b64e3f..7b00e4f822f 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -112,6 +112,7 @@ University of California, as described above. */
# define O_CLOEXEC O_NOINHERIT
#endif /* WINDOWSNT */
+#include <attribute.h>
#include <inttypes.h>
#include <limits.h>
#include <unistd.h>
@@ -1427,14 +1428,30 @@ main (int argc, char **argv)
if (CTAGS)
if (append_to_tagfile || update)
{
- char *cmd = xmalloc (2 * strlen (tagfile) + sizeof "sort -u -o..");
/* Maybe these should be used:
setenv ("LC_COLLATE", "C", 1);
setenv ("LC_ALL", "C", 1); */
- char *z = stpcpy (cmd, "sort -u -o ");
+ char *cmd = xmalloc (8 * strlen (tagfile) + sizeof "sort -u -o '' ''");
+#if defined WINDOWSNT || defined MSDOS
+ /* Quote "like this". No need to escape the quotes in the file name,
+ since it is not allowed in file names on these systems. */
+ char *z = stpcpy (cmd, "sort -u -o \"");
z = stpcpy (z, tagfile);
- *z++ = ' ';
- strcpy (z, tagfile);
+ z = stpcpy (z, "\" \"");
+ z = stpcpy (z, tagfile);
+ stpcpy (z, "\"");
+#else
+ /* Quote 'like this', and escape the apostrophe in the file name. */
+ char *z = stpcpy (cmd, "sort -u -o '");
+ char *escaped_tagfile = z;
+ for (; *tagfile; *z++ = *tagfile++)
+ if (*tagfile == '\'')
+ z = stpcpy (z, "'\\'");
+ ptrdiff_t escaped_tagfile_len = z - escaped_tagfile;
+ z = stpcpy (z, "' '");
+ z = mempcpy (z, escaped_tagfile, escaped_tagfile_len);
+ strcpy (z, "'");
+#endif
return system (cmd);
}
return EXIT_SUCCESS;
@@ -4161,6 +4178,9 @@ C_entries (int c_ext, /* extension of C */
if (definedef != dnone)
break;
bracelev -= 1;
+ /* If we see a closing brace in column zero, and we weren't told to
+ ignore indentation, we assume this the final brace of a function
+ or struct definition, and reset bracelev to zero. */
if (!ignoreindent && lp == newlb.buffer + 1)
{
if (bracelev != 0)
@@ -6396,7 +6416,8 @@ mercury_decl (char *s, size_t pos)
size_t origpos;
origpos = pos;
- while (s + pos != NULL && (c_isalnum (s[pos]) || s[pos] == '_')) ++pos;
+ while (c_isalnum (s[pos]) || s[pos] == '_')
+ pos++;
unsigned char decl_type_length = pos - origpos;
char buf[decl_type_length + 1];
@@ -6440,9 +6461,9 @@ mercury_decl (char *s, size_t pos)
so this is the hard case. */
if (strcmp (buf, "solver") == 0)
{
- ++pos;
- while (s + pos != NULL && (c_isalnum (s[pos]) || s[pos] == '_'))
- ++pos;
+ do
+ pos++;
+ while (c_isalnum (s[pos]) || s[pos] == '_');
decl_type_length = pos - origpos;
char buf2[decl_type_length + 1];
@@ -6492,7 +6513,6 @@ mercury_decl (char *s, size_t pos)
while (c_isalnum (s[pos])
|| s[pos] == '_'
|| (s[pos] == '.' /* A module dot. */
- && s + pos + 1 != NULL
&& (c_isalnum (s[pos + 1]) || s[pos + 1] == '_')
&& (module_dot_pos = pos))) /* Record module dot position.
Erase module from name. */
@@ -6536,10 +6556,10 @@ mercury_decl (char *s, size_t pos)
}
else if (is_mercury_quantifier && s[pos] == '[') /* :- some [T] pred/func. */
{
- for (++pos; s + pos != NULL && s[pos] != ']'; ++pos) {}
- if (s + pos == NULL) return null_pos;
- ++pos;
- pos = skip_spaces (s + pos) - s;
+ char *close_bracket = strchr (s + pos + 1, ']');
+ if (!close_bracket)
+ return null_pos;
+ pos = skip_spaces (close_bracket + 1) - s;
mercury_pos_t position = mercury_decl (s, pos);
position.totlength += pos - origpos;
return position;
@@ -7243,8 +7263,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
{
/* We're at the end of linebuffer: expand it. */
xrnew (buffer, lbp->size, 2);
+ p = buffer + lbp->size;
lbp->size *= 2;
- p += buffer - lbp->buffer;
pend = buffer + lbp->size;
lbp->buffer = buffer;
}
@@ -7665,21 +7685,21 @@ relative_filename (char *file, char *dir)
{
char *fp, *dp, *afn, *res;
ptrdiff_t i;
+ char *dir_last_slash UNINIT;
/* Find the common root of file and dir (with a trailing slash). */
afn = absolute_filename (file, cwd);
fp = afn;
dp = dir;
while (*fp++ == *dp++)
- continue;
- fp--, dp--; /* back to the first differing char */
+ if (dp[-1] == '/')
+ dir_last_slash = dp - 1;
#ifdef DOS_NT
- if (fp == afn && afn[0] != '/') /* cannot build a relative name */
- return afn;
+ if (fp - 1 == afn && afn[0] != '/')
+ return afn; /* Cannot build a relative name. */
#endif
- do /* look at the equal chars until '/' */
- fp--, dp--;
- while (*fp != '/');
+ fp -= dp - dir_last_slash;
+ dp = dir_last_slash;
/* Build a sequence of "../" strings for the resulting relative file name. */
i = 0;
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index f42b1988a2b..908d73f5253 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -42,6 +42,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <string.h>
+#include <attribute.h>
#include <binary-io.h>
#include <c-ctype.h>
#include <intprops.h>
@@ -1067,7 +1068,7 @@ scan_c_stream (FILE *infile)
attributes: attribute1 attribute2 ...)
(Lisp_Object arg...)
- Now only ’const’, ’noinline’ and 'noreturn' attributes
+ Now only `const', `noinline' and `noreturn' attributes
are used. */
/* Advance to the end of docstring. */
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index 888688f90b1..aa3c15e72e8 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -69,6 +69,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <signal.h>
#include <string.h>
+#include <attribute.h>
#include <unlocked-io.h>
#include "syswait.h"
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c
index 552a9862391..9f0de7d64f8 100644
--- a/lib-src/seccomp-filter.c
+++ b/lib-src/seccomp-filter.c
@@ -59,7 +59,8 @@ variants of those files that can be used to sandbox Emacs before
#include <seccomp.h>
#include <unistd.h>
-#include "verify.h"
+#include <attribute.h>
+#include <verify.h>
#ifndef ARCH_CET_STATUS
#define ARCH_CET_STATUS 0x3001
@@ -228,6 +229,7 @@ main (int argc, char **argv)
capabilities, and operating on them shouldn't cause security
issues. */
RULE (SCMP_ACT_ALLOW, SCMP_SYS (read));
+ RULE (SCMP_ACT_ALLOW, SCMP_SYS (pread64));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (write));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (close));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (lseek));
@@ -239,6 +241,9 @@ main (int argc, char **argv)
should be further restricted using mount namespaces. */
RULE (SCMP_ACT_ALLOW, SCMP_SYS (access));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (faccessat));
+#ifdef __NR_faccessat2
+ RULE (SCMP_ACT_ALLOW, SCMP_SYS (faccessat2));
+#endif
RULE (SCMP_ACT_ALLOW, SCMP_SYS (stat));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (stat64));
RULE (SCMP_ACT_ALLOW, SCMP_SYS (lstat));
diff --git a/lib/acl-errno-valid.c b/lib/acl-errno-valid.c
index 39717c35174..a364e413256 100644
--- a/lib/acl-errno-valid.c
+++ b/lib/acl-errno-valid.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index 75a80bf0df2..be244c67a2a 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index 582f9e1c1a1..93533762dd0 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/acl.h b/lib/acl.h
index 8b933c20b94..f4d0df80618 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
index e4c014ce715..677de23e0cb 100644
--- a/lib/acl_entries.c
+++ b/lib/acl_entries.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/at-func.c b/lib/at-func.c
index 92d65f6341f..afcc819beb0 100644
--- a/lib/at-func.c
+++ b/lib/at-func.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/cdefs.h b/lib/cdefs.h
index abf13a90862..7b8ed5b344b 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -41,7 +41,9 @@
Similarly for __has_builtin, etc. */
#if (defined __has_attribute \
&& (!defined __clang_minor__ \
- || 3 < __clang_major__ + (5 <= __clang_minor__)))
+ || (defined __apple_build_version__ \
+ ? 6000000 <= __apple_build_version__ \
+ : 3 < __clang_major__ + (5 <= __clang_minor__))))
# define __glibc_has_attribute(attr) __has_attribute (attr)
#else
# define __glibc_has_attribute(attr) 0
@@ -143,7 +145,8 @@
#define __bos0(ptr) __builtin_object_size (ptr, 0)
/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */
-#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0)
+#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \
+ || __GNUC_PREREQ (12, 0))
# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
#else
@@ -161,13 +164,13 @@
|| (__builtin_constant_p (__l) && (__l) > 0))
/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
- condition can be folded to a constant and if it is true. The -1 check is
- redundant because since it implies that __glibc_safe_len_cond is true. */
+ condition can be folded to a constant and if it is true, or unknown (-1) */
#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
- (__glibc_unsigned_or_positive (__l) \
- && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
- __s, __osz)) \
- && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+ ((__osz) == (__SIZE_TYPE__) -1 \
+ || (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ (__s), (__osz))) \
+ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz))))
/* Conversely, we know at compile time that the length is unsafe if the
__L * __S <= __OBJSZ condition can be folded to a constant and if it is
diff --git a/lib/close-stream.c b/lib/close-stream.c
index 54f3e3c3d0c..9b0e97b271d 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/close-stream.h b/lib/close-stream.h
index 537506c4896..2b4c8ed8f5b 100644
--- a/lib/close-stream.h
+++ b/lib/close-stream.h
@@ -4,7 +4,7 @@
This file 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,
+ by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c
index 96f1ec7c5e8..1ec7f4de67c 100644
--- a/lib/copy-file-range.c
+++ b/lib/copy-file-range.c
@@ -20,11 +20,45 @@
#include <errno.h>
+#if defined __linux__ && HAVE_COPY_FILE_RANGE
+# include <sys/utsname.h>
+#endif
+
ssize_t
copy_file_range (int infd, off_t *pinoff,
int outfd, off_t *poutoff,
size_t length, unsigned int flags)
{
+#undef copy_file_range
+
+#if defined __linux__ && HAVE_COPY_FILE_RANGE
+ /* The implementation of copy_file_range (which first appeared in
+ Linux kernel release 4.5) had many issues before release 5.3
+ <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux
+ kernels 5.2 and earlier.
+
+ This workaround, and the configure-time check for Linux, can be
+ removed when such kernels (released March 2016 through September
+ 2019) are no longer a consideration. As of January 2021, the
+ furthest-future planned kernel EOL is December 2024 for kernel
+ release 4.19. */
+
+ static signed char ok;
+
+ if (! ok)
+ {
+ struct utsname name;
+ uname (&name);
+ char *p = name.release;
+ ok = ((p[1] != '.' || '5' < p[0]
+ || (p[0] == '5' && (p[3] != '.' || '2' < p[2])))
+ ? 1 : -1);
+ }
+
+ if (0 < ok)
+ return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
+#endif
+
/* There is little need to emulate copy_file_range with read+write,
since programs that use copy_file_range must fall back on
read+write anyway. */
diff --git a/lib/diffseq.h b/lib/diffseq.h
index 0c901a6ecfd..0f76ea1d5ad 100644
--- a/lib/diffseq.h
+++ b/lib/diffseq.h
@@ -5,7 +5,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/dtoastr.c b/lib/dtoastr.c
index eaade8fa016..71af14c9df4 100644
--- a/lib/dtoastr.c
+++ b/lib/dtoastr.c
@@ -4,7 +4,7 @@
This file 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,
+ by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c
index 225a2be67c4..b62a8bd6cfc 100644
--- a/lib/dtotimespec.c
+++ b/lib/dtotimespec.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/faccessat.c b/lib/faccessat.c
index 2c0c07aac10..c1737d03a10 100644
--- a/lib/faccessat.c
+++ b/lib/faccessat.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
index 506e6badd7d..164e2c4a95f 100644
--- a/lib/fchmodat.c
+++ b/lib/fchmodat.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -83,9 +83,10 @@ fchmodat (int dir, char const *file, mode_t mode, int flags)
# if NEED_FCHMODAT_NONSYMLINK_FIX
if (flags == AT_SYMLINK_NOFOLLOW)
{
- struct stat st;
+# if HAVE_READLINKAT
+ char readlink_buf[1];
-# if defined O_PATH && defined AT_EMPTY_PATH
+# ifdef O_PATH
/* Open a file descriptor with O_NOFOLLOW, to make sure we don't
follow symbolic links, if /proc is mounted. O_PATH is used to
avoid a failure if the file is not readable.
@@ -94,49 +95,29 @@ fchmodat (int dir, char const *file, mode_t mode, int flags)
if (fd < 0)
return fd;
- /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the
- chmod call below will change the permissions of the symbolic link
- - which is undesired - and on many file systems (ext4, btrfs, jfs,
- xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is
- misleading. Therefore test for a symbolic link explicitly.
- Use fstatat because fstat does not work on O_PATH descriptors
- before Linux 3.6. */
- if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0)
+ int err;
+ if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
+ err = EOPNOTSUPP;
+ else if (errno == EINVAL)
{
- int stat_errno = errno;
- close (fd);
- errno = stat_errno;
- return -1;
- }
- if (S_ISLNK (st.st_mode))
- {
- close (fd);
- errno = EOPNOTSUPP;
- return -1;
+ static char const fmt[] = "/proc/self/fd/%d";
+ char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+ sprintf (buf, fmt, fd);
+ err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
}
+ else
+ err = errno == ENOENT ? -1 : errno;
-# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__
- static char const fmt[] = "/proc/self/fd/%d";
- char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
- sprintf (buf, fmt, fd);
- int chmod_result = chmod (buf, mode);
- int chmod_errno = errno;
close (fd);
- if (chmod_result == 0)
- return chmod_result;
- if (chmod_errno != ENOENT)
- {
- errno = chmod_errno;
- return chmod_result;
- }
+
+ errno = err;
+ if (0 <= err)
+ return err == 0 ? 0 : -1;
# endif
- /* /proc is not mounted or would not work as in GNU/Linux. */
-# else
- int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW);
- if (fstatat_result != 0)
- return fstatat_result;
- if (S_ISLNK (st.st_mode))
+ /* O_PATH + /proc is not supported. */
+
+ if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf))
{
errno = EOPNOTSUPP;
return -1;
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 3e0c302af33..9270ced8973 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -435,6 +435,10 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
# define AT_EACCESS 4
#endif
+/* Ignore this flag if not supported. */
+#ifndef AT_NO_AUTOMOUNT
+# define AT_NO_AUTOMOUNT 0
+#endif
#endif /* _@GUARD_PREFIX@_FCNTL_H */
#endif /* _@GUARD_PREFIX@_FCNTL_H */
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index a61bad66e23..c2b0e1ed347 100644
--- a/lib/fdopendir.c
+++ b/lib/fdopendir.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 2b6f91ff20a..e02f0626ad3 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/filemode.c b/lib/filemode.c
index cb508ad12d1..a8cbea844c8 100644
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -5,7 +5,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/filemode.h b/lib/filemode.h
index 7c645c16b51..bf38181cdcd 100644
--- a/lib/filemode.h
+++ b/lib/filemode.h
@@ -5,7 +5,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/filevercmp.c b/lib/filevercmp.c
index b3e6e2f3cb8..7e54793e613 100644
--- a/lib/filevercmp.c
+++ b/lib/filevercmp.c
@@ -1,11 +1,12 @@
-/*
+/* Compare file names containing version numbers.
+
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
Copyright (C) 2008-2022 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
@@ -19,60 +20,69 @@
#include <config.h>
#include "filevercmp.h"
-#include <sys/types.h>
-#include <stdlib.h>
#include <stdbool.h>
-#include <string.h>
#include <c-ctype.h>
#include <limits.h>
-
-/* Match a file suffix defined by this regular expression:
- /(\.[A-Za-z~][A-Za-z0-9~]*)*$/
- Scan the string *STR and return a pointer to the matching suffix, or
- NULL if not found. Upon return, *STR points to terminating NUL. */
-static const char *
-match_suffix (const char **str)
+#include <idx.h>
+#include <verify.h>
+
+/* Return the length of a prefix of S that corresponds to the suffix
+ defined by this extended regular expression in the C locale:
+ (\.[A-Za-z~][A-Za-z0-9~]*)*$
+ Use the longest suffix matching this regular expression,
+ except do not use all of S as a suffix if S is nonempty.
+ If *LEN is -1, S is a string; set *LEN to S's length.
+ Otherwise, *LEN should be nonnegative, S is a char array,
+ and *LEN does not change. */
+static idx_t
+file_prefixlen (char const *s, ptrdiff_t *len)
{
- const char *match = NULL;
- bool read_alpha = false;
- while (**str)
+ size_t n = *len; /* SIZE_MAX if N == -1. */
+ idx_t prefixlen = 0;
+
+ for (idx_t i = 0; ; )
{
- if (read_alpha)
- {
- read_alpha = false;
- if (!c_isalpha (**str) && '~' != **str)
- match = NULL;
- }
- else if ('.' == **str)
+ if (*len < 0 ? !s[i] : i == n)
{
- read_alpha = true;
- if (!match)
- match = *str;
+ *len = i;
+ return prefixlen;
}
- else if (!c_isalnum (**str) && '~' != **str)
- match = NULL;
- (*str)++;
+
+ i++;
+ prefixlen = i;
+ while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1])
+ || s[i + 1] == '~'))
+ for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++)
+ continue;
}
- return match;
}
-/* verrevcmp helper function */
+/* Return a version sort comparison value for S's byte at position POS.
+ S has length LEN. If POS == LEN, sort before all non-'~' bytes. */
+
static int
-order (unsigned char c)
+order (char const *s, idx_t pos, idx_t len)
{
+ if (pos == len)
+ return -1;
+
+ unsigned char c = s[pos];
if (c_isdigit (c))
return 0;
else if (c_isalpha (c))
return c;
else if (c == '~')
- return -1;
+ return -2;
else
- return (int) c + UCHAR_MAX + 1;
+ {
+ verify (UCHAR_MAX <= (INT_MAX - 1 - 2) / 2);
+ return c + UCHAR_MAX + 1;
+ }
}
/* slightly modified verrevcmp function from dpkg
- S1, S2 - compared string
- S1_LEN, S2_LEN - length of strings to be scanned
+ S1, S2 - compared char array
+ S1_LEN, S2_LEN - length of arrays to be scanned
This implements the algorithm for comparison of version strings
specified by Debian and now widely adopted. The detailed
@@ -81,37 +91,38 @@ order (unsigned char c)
implements that from s5.6.12 of Debian Policy v3.8.0.1
https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */
static int _GL_ATTRIBUTE_PURE
-verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+verrevcmp (const char *s1, idx_t s1_len, const char *s2, idx_t s2_len)
{
- size_t s1_pos = 0;
- size_t s2_pos = 0;
+ idx_t s1_pos = 0;
+ idx_t s2_pos = 0;
while (s1_pos < s1_len || s2_pos < s2_len)
{
int first_diff = 0;
while ((s1_pos < s1_len && !c_isdigit (s1[s1_pos]))
|| (s2_pos < s2_len && !c_isdigit (s2[s2_pos])))
{
- int s1_c = (s1_pos == s1_len) ? 0 : order (s1[s1_pos]);
- int s2_c = (s2_pos == s2_len) ? 0 : order (s2[s2_pos]);
+ int s1_c = order (s1, s1_pos, s1_len);
+ int s2_c = order (s2, s2_pos, s2_len);
if (s1_c != s2_c)
return s1_c - s2_c;
s1_pos++;
s2_pos++;
}
- while (s1[s1_pos] == '0')
+ while (s1_pos < s1_len && s1[s1_pos] == '0')
s1_pos++;
- while (s2[s2_pos] == '0')
+ while (s2_pos < s2_len && s2[s2_pos] == '0')
s2_pos++;
- while (c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos]))
+ while (s1_pos < s1_len && s2_pos < s2_len
+ && c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos]))
{
if (!first_diff)
first_diff = s1[s1_pos] - s2[s2_pos];
s1_pos++;
s2_pos++;
}
- if (c_isdigit (s1[s1_pos]))
+ if (s1_pos < s1_len && c_isdigit (s1[s1_pos]))
return 1;
- if (c_isdigit (s2[s2_pos]))
+ if (s2_pos < s2_len && c_isdigit (s2[s2_pos]))
return -1;
if (first_diff)
return first_diff;
@@ -124,58 +135,56 @@ verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
int
filevercmp (const char *s1, const char *s2)
{
- const char *s1_pos;
- const char *s2_pos;
- const char *s1_suffix, *s2_suffix;
- size_t s1_len, s2_len;
- int result;
-
- /* easy comparison to see if strings are identical */
- int simple_cmp = strcmp (s1, s2);
- if (simple_cmp == 0)
- return 0;
+ return filenvercmp (s1, -1, s2, -1);
+}
- /* special handle for "", "." and ".." */
- if (!*s1)
- return -1;
- if (!*s2)
- return 1;
- if (0 == strcmp (".", s1))
- return -1;
- if (0 == strcmp (".", s2))
- return 1;
- if (0 == strcmp ("..", s1))
- return -1;
- if (0 == strcmp ("..", s2))
+/* Compare versions A (of length ALEN) and B (of length BLEN).
+ See filevercmp.h for function description. */
+int
+filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen)
+{
+ /* Special case for empty versions. */
+ bool aempty = alen < 0 ? !a[0] : !alen;
+ bool bempty = blen < 0 ? !b[0] : !blen;
+ if (aempty)
+ return -!bempty;
+ if (bempty)
return 1;
- /* special handle for other hidden files */
- if (*s1 == '.' && *s2 != '.')
- return -1;
- if (*s1 != '.' && *s2 == '.')
- return 1;
- if (*s1 == '.' && *s2 == '.')
+ /* Special cases for leading ".": "." sorts first, then "..", then
+ other names with leading ".", then other names. */
+ if (a[0] == '.')
{
- s1++;
- s2++;
- }
+ if (b[0] != '.')
+ return -1;
- /* "cut" file suffixes */
- s1_pos = s1;
- s2_pos = s2;
- s1_suffix = match_suffix (&s1_pos);
- s2_suffix = match_suffix (&s2_pos);
- s1_len = (s1_suffix ? s1_suffix : s1_pos) - s1;
- s2_len = (s2_suffix ? s2_suffix : s2_pos) - s2;
-
- /* restore file suffixes if strings are identical after "cut" */
- if ((s1_suffix || s2_suffix) && (s1_len == s2_len)
- && 0 == strncmp (s1, s2, s1_len))
- {
- s1_len = s1_pos - s1;
- s2_len = s2_pos - s2;
+ bool adot = alen < 0 ? !a[1] : alen == 1;
+ bool bdot = blen < 0 ? !b[1] : blen == 1;
+ if (adot)
+ return -!bdot;
+ if (bdot)
+ return 1;
+
+ bool adotdot = a[1] == '.' && (alen < 0 ? !a[2] : alen == 2);
+ bool bdotdot = b[1] == '.' && (blen < 0 ? !b[2] : blen == 2);
+ if (adotdot)
+ return -!bdotdot;
+ if (bdotdot)
+ return 1;
}
+ else if (b[0] == '.')
+ return 1;
+
+ /* Cut file suffixes. */
+ idx_t aprefixlen = file_prefixlen (a, &alen);
+ idx_t bprefixlen = file_prefixlen (b, &blen);
+
+ /* If both suffixes are empty, a second pass would return the same thing. */
+ bool one_pass_only = aprefixlen == alen && bprefixlen == blen;
+
+ int result = verrevcmp (a, aprefixlen, b, bprefixlen);
- result = verrevcmp (s1, s1_len, s2, s2_len);
- return result == 0 ? simple_cmp : result;
+ /* Return the initial result if nonzero, or if no second pass is needed.
+ Otherwise, restore the suffixes and try again. */
+ return result || one_pass_only ? result : verrevcmp (a, alen, b, blen);
}
diff --git a/lib/filevercmp.h b/lib/filevercmp.h
index 98020e66674..57949760b25 100644
--- a/lib/filevercmp.h
+++ b/lib/filevercmp.h
@@ -1,11 +1,12 @@
-/*
+/* Compare file names containing version numbers.
+
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
Copyright (C) 2008-2022 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
@@ -19,24 +20,59 @@
#ifndef FILEVERCMP_H
#define FILEVERCMP_H
-/* Compare version strings:
+#include <stddef.h>
+
+/* Compare strings A and B as file names containing version numbers,
+ and return an integer that is negative, zero, or positive depending
+ on whether A compares less than, equal to, or greater than B.
+
+ Use the following version sort algorithm:
+
+ 1. Compare the strings' maximal-length non-digit prefixes lexically.
+ If there is a difference return that difference.
+ Otherwise discard the prefixes and continue with the next step.
+
+ 2. Compare the strings' maximal-length digit prefixes, using
+ numeric comparison of the numbers represented by each prefix.
+ (Treat an empty prefix as zero; this can happen only at string end.)
+ If there is a difference, return that difference.
+ Otherwise discard the prefixes and continue with the next step.
+
+ 3. If both strings are empty, return 0. Otherwise continue with step 1.
+
+ In version sort, lexical comparison is left to right, byte by byte,
+ using the byte's numeric value (0-255), except that:
+
+ 1. ASCII letters sort before other bytes.
+ 2. A tilde sorts before anything, even an empty string.
+
+ In addition to the version sort rules, the following strings have
+ special priority and sort before all other strings (listed in order):
- This function compares strings S1 and S2:
- 1) By PREFIX in the same way as strcmp.
- 2) Then by VERSION (most similarly to version compare of Debian's dpkg).
- Leading zeros in version numbers are ignored.
- 3) If both (PREFIX and VERSION) are equal, strcmp function is used for
- comparison. So this function can return 0 if (and only if) strings S1
- and S2 are identical.
+ 1. The empty string.
+ 2. ".".
+ 3. "..".
+ 4. Strings starting with "." sort before other strings.
- It returns number >0 for S1 > S2, 0 for S1 == S2 and number <0 for S1 < S2.
+ Before comparing two strings where both begin with non-".",
+ or where both begin with "." but neither is "." or "..",
+ suffixes matching the C-locale extended regular expression
+ (\.[A-Za-z~][A-Za-z0-9~]*)*$ are removed and the strings compared
+ without them, using version sort without special priority;
+ if they do not compare equal, this comparison result is used and
+ the suffixes are effectively ignored. Otherwise, the entire
+ strings are compared using version sort. When removing a suffix
+ from a nonempty string, remove the maximal-length suffix such that
+ the remaining string is nonempty.
- This function compares strings, in a way that if VER1 and VER2 are version
- numbers and PREFIX and SUFFIX (SUFFIX defined as (\.[A-Za-z~][A-Za-z0-9~]*)*)
- are strings then VER1 < VER2 implies filevercmp (PREFIX VER1 SUFFIX,
- PREFIX VER2 SUFFIX) < 0.
+ This function is intended to be a replacement for strverscmp. */
+int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE;
- This function is intended to be a replacement for strverscmp. */
-int filevercmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE;
+/* Like filevercmp, except compare the byte arrays A (of length ALEN)
+ and B (of length BLEN) so that A and B can contain '\0', which
+ sorts just before '\1'. But if ALEN is -1 treat A as a string
+ terminated by '\0', and similarly for BLEN. */
+int filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen)
+ _GL_ATTRIBUTE_PURE;
#endif /* FILEVERCMP_H */
diff --git a/lib/fpending.c b/lib/fpending.c
index 617f3977f8f..6408cff4647 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/fpending.h b/lib/fpending.h
index 2b45e9031bb..43542c5b8ad 100644
--- a/lib/fpending.h
+++ b/lib/fpending.h
@@ -5,7 +5,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/fstatat.c b/lib/fstatat.c
index 56de0cab4b2..6e8344964bc 100644
--- a/lib/fstatat.c
+++ b/lib/fstatat.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/fsusage.c b/lib/fsusage.c
index 734f0fc7460..18f790f6e7b 100644
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -5,7 +5,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/fsusage.h b/lib/fsusage.h
index f4f50aba29c..0443d19f922 100644
--- a/lib/fsusage.h
+++ b/lib/fsusage.h
@@ -5,7 +5,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/ftoastr.c b/lib/ftoastr.c
index 4349c8c5611..91057529221 100644
--- a/lib/ftoastr.c
+++ b/lib/ftoastr.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/ftoastr.h b/lib/ftoastr.h
index 065574a9ff4..bac32a387e2 100644
--- a/lib/ftoastr.h
+++ b/lib/ftoastr.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/futimens.c b/lib/futimens.c
index 97228242b1e..bc3e41a9439 100644
--- a/lib/futimens.c
+++ b/lib/futimens.c
@@ -3,7 +3,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index a17b791c8d8..ff79adae72f 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index 53d1b81a3ba..37e82808671 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -8,7 +8,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/gettime.c b/lib/gettime.c
index a44a69dfc43..541af18bbfa 100644
--- a/lib/gettime.c
+++ b/lib/gettime.c
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index a8a6cd782d5..2ffe89d4239 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -3,7 +3,7 @@
#
# This file 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
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
@@ -35,6 +35,7 @@
# --macro-prefix=gl \
# --no-vc-files \
# --avoid=btowc \
+# --avoid=chmod \
# --avoid=close \
# --avoid=crypto/af_alg \
# --avoid=dup \
@@ -129,6 +130,7 @@
# minmax \
# mkostemp \
# mktime \
+# nanosleep \
# nproc \
# nstrftime \
# pathmax \
@@ -191,6 +193,10 @@ BUILD_DETAILS = @BUILD_DETAILS@
BYTESWAP_H = @BYTESWAP_H@
CAIRO_CFLAGS = @CAIRO_CFLAGS@
CAIRO_LIBS = @CAIRO_LIBS@
+CAIRO_XCB_CFLAGS = @CAIRO_XCB_CFLAGS@
+CAIRO_XCB_LIBS = @CAIRO_XCB_LIBS@
+CAIRO_XLIB_CFLAGS = @CAIRO_XLIB_CFLAGS@
+CAIRO_XLIB_LIBS = @CAIRO_XLIB_LIBS@
CC = @CC@
CFLAGS = @CFLAGS@
CFLAGS_SOUND = @CFLAGS_SOUND@
@@ -203,7 +209,6 @@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTOLIB = @CRYPTOLIB@
CXX = @CXX@
-CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CYGWIN_OBJ = @CYGWIN_OBJ@
C_SWITCH_MACHINE = @C_SWITCH_MACHINE@
@@ -247,7 +252,60 @@ GETOPT_CDEFS_H = @GETOPT_CDEFS_H@
GETOPT_H = @GETOPT_H@
GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@
GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@
+GL_CFLAG_ALLOW_WARNINGS = @GL_CFLAG_ALLOW_WARNINGS@
+GL_CFLAG_GNULIB_WARNINGS = @GL_CFLAG_GNULIB_WARNINGS@
GL_COND_LIBTOOL_CONDITION = @GL_COND_LIBTOOL_CONDITION@
+GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION = @GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION@
+GL_COND_OBJ_COPY_FILE_RANGE_CONDITION = @GL_COND_OBJ_COPY_FILE_RANGE_CONDITION@
+GL_COND_OBJ_DIRFD_CONDITION = @GL_COND_OBJ_DIRFD_CONDITION@
+GL_COND_OBJ_DUP2_CONDITION = @GL_COND_OBJ_DUP2_CONDITION@
+GL_COND_OBJ_EUIDACCESS_CONDITION = @GL_COND_OBJ_EUIDACCESS_CONDITION@
+GL_COND_OBJ_EXECINFO_CONDITION = @GL_COND_OBJ_EXECINFO_CONDITION@
+GL_COND_OBJ_EXPLICIT_BZERO_CONDITION = @GL_COND_OBJ_EXPLICIT_BZERO_CONDITION@
+GL_COND_OBJ_FACCESSAT_CONDITION = @GL_COND_OBJ_FACCESSAT_CONDITION@
+GL_COND_OBJ_FCHMODAT_CONDITION = @GL_COND_OBJ_FCHMODAT_CONDITION@
+GL_COND_OBJ_FCNTL_CONDITION = @GL_COND_OBJ_FCNTL_CONDITION@
+GL_COND_OBJ_FDOPENDIR_CONDITION = @GL_COND_OBJ_FDOPENDIR_CONDITION@
+GL_COND_OBJ_FPENDING_CONDITION = @GL_COND_OBJ_FPENDING_CONDITION@
+GL_COND_OBJ_FREE_CONDITION = @GL_COND_OBJ_FREE_CONDITION@
+GL_COND_OBJ_FSTATAT_CONDITION = @GL_COND_OBJ_FSTATAT_CONDITION@
+GL_COND_OBJ_FSUSAGE_CONDITION = @GL_COND_OBJ_FSUSAGE_CONDITION@
+GL_COND_OBJ_FSYNC_CONDITION = @GL_COND_OBJ_FSYNC_CONDITION@
+GL_COND_OBJ_FUTIMENS_CONDITION = @GL_COND_OBJ_FUTIMENS_CONDITION@
+GL_COND_OBJ_GETDTABLESIZE_CONDITION = @GL_COND_OBJ_GETDTABLESIZE_CONDITION@
+GL_COND_OBJ_GETGROUPS_CONDITION = @GL_COND_OBJ_GETGROUPS_CONDITION@
+GL_COND_OBJ_GETLOADAVG_CONDITION = @GL_COND_OBJ_GETLOADAVG_CONDITION@
+GL_COND_OBJ_GETOPT_CONDITION = @GL_COND_OBJ_GETOPT_CONDITION@
+GL_COND_OBJ_GETRANDOM_CONDITION = @GL_COND_OBJ_GETRANDOM_CONDITION@
+GL_COND_OBJ_GETTIMEOFDAY_CONDITION = @GL_COND_OBJ_GETTIMEOFDAY_CONDITION@
+GL_COND_OBJ_GROUP_MEMBER_CONDITION = @GL_COND_OBJ_GROUP_MEMBER_CONDITION@
+GL_COND_OBJ_LCHMOD_CONDITION = @GL_COND_OBJ_LCHMOD_CONDITION@
+GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@
+GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@
+GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@
+GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@
+GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@
+GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@
+GL_COND_OBJ_OPEN_CONDITION = @GL_COND_OBJ_OPEN_CONDITION@
+GL_COND_OBJ_PSELECT_CONDITION = @GL_COND_OBJ_PSELECT_CONDITION@
+GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION = @GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION@
+GL_COND_OBJ_RAWMEMCHR_CONDITION = @GL_COND_OBJ_RAWMEMCHR_CONDITION@
+GL_COND_OBJ_READLINKAT_CONDITION = @GL_COND_OBJ_READLINKAT_CONDITION@
+GL_COND_OBJ_READLINK_CONDITION = @GL_COND_OBJ_READLINK_CONDITION@
+GL_COND_OBJ_REGEX_CONDITION = @GL_COND_OBJ_REGEX_CONDITION@
+GL_COND_OBJ_SIG2STR_CONDITION = @GL_COND_OBJ_SIG2STR_CONDITION@
+GL_COND_OBJ_SIGDESCR_NP_CONDITION = @GL_COND_OBJ_SIGDESCR_NP_CONDITION@
+GL_COND_OBJ_STDIO_READ_CONDITION = @GL_COND_OBJ_STDIO_READ_CONDITION@
+GL_COND_OBJ_STDIO_WRITE_CONDITION = @GL_COND_OBJ_STDIO_WRITE_CONDITION@
+GL_COND_OBJ_STPCPY_CONDITION = @GL_COND_OBJ_STPCPY_CONDITION@
+GL_COND_OBJ_STRNLEN_CONDITION = @GL_COND_OBJ_STRNLEN_CONDITION@
+GL_COND_OBJ_STRTOIMAX_CONDITION = @GL_COND_OBJ_STRTOIMAX_CONDITION@
+GL_COND_OBJ_STRTOLL_CONDITION = @GL_COND_OBJ_STRTOLL_CONDITION@
+GL_COND_OBJ_SYMLINK_CONDITION = @GL_COND_OBJ_SYMLINK_CONDITION@
+GL_COND_OBJ_TIMEGM_CONDITION = @GL_COND_OBJ_TIMEGM_CONDITION@
+GL_COND_OBJ_TIME_RZ_CONDITION = @GL_COND_OBJ_TIME_RZ_CONDITION@
+GL_COND_OBJ_TIME_R_CONDITION = @GL_COND_OBJ_TIME_R_CONDITION@
+GL_COND_OBJ_UTIMENSAT_CONDITION = @GL_COND_OBJ_UTIMENSAT_CONDITION@
GL_GENERATE_ALLOCA_H_CONDITION = @GL_GENERATE_ALLOCA_H_CONDITION@
GL_GENERATE_BYTESWAP_H_CONDITION = @GL_GENERATE_BYTESWAP_H_CONDITION@
GL_GENERATE_ERRNO_H_CONDITION = @GL_GENERATE_ERRNO_H_CONDITION@
@@ -270,6 +328,7 @@ GL_GNULIB_CALLOC_GNU = @GL_GNULIB_CALLOC_GNU@
GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@
GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@
GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@
+GL_GNULIB_CHMOD = @GL_GNULIB_CHMOD@
GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@
GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@
GL_GNULIB_CLOSEDIR = @GL_GNULIB_CLOSEDIR@
@@ -873,6 +932,7 @@ LIB_EXECINFO = @LIB_EXECINFO@
LIB_GETRANDOM = @LIB_GETRANDOM@
LIB_HAS_ACL = @LIB_HAS_ACL@
LIB_MATH = @LIB_MATH@
+LIB_NANOSLEEP = @LIB_NANOSLEEP@
LIB_PTHREAD = @LIB_PTHREAD@
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
LIB_TIMER_TIME = @LIB_TIMER_TIME@
@@ -971,9 +1031,11 @@ REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@
REPLACE_CALLOC_FOR_CALLOC_GNU = @REPLACE_CALLOC_FOR_CALLOC_GNU@
REPLACE_CALLOC_FOR_CALLOC_POSIX = @REPLACE_CALLOC_FOR_CALLOC_POSIX@
REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
+REPLACE_CHMOD = @REPLACE_CHMOD@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@
+REPLACE_COPY_FILE_RANGE = @REPLACE_COPY_FILE_RANGE@
REPLACE_CREAT = @REPLACE_CREAT@
REPLACE_CTIME = @REPLACE_CTIME@
REPLACE_DIRFD = @REPLACE_DIRFD@
@@ -1137,6 +1199,7 @@ SETTINGS_LIBS = @SETTINGS_LIBS@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
+SMALL_JA_DIC = @SMALL_JA_DIC@
SQLITE3_LIBS = @SQLITE3_LIBS@
STDALIGN_H = @STDALIGN_H@
STDDEF_H = @STDDEF_H@
@@ -1179,6 +1242,8 @@ WINDRES = @WINDRES@
WINT_T_SUFFIX = @WINT_T_SUFFIX@
XARGS_LIMIT = @XARGS_LIMIT@
XCB_LIBS = @XCB_LIBS@
+XCOMPOSITE_CFLAGS = @XCOMPOSITE_CFLAGS@
+XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
XCRUN = @XCRUN@
XDBE_CFLAGS = @XDBE_CFLAGS@
XDBE_LIBS = @XDBE_LIBS@
@@ -1197,6 +1262,10 @@ XOBJ = @XOBJ@
XRANDR_CFLAGS = @XRANDR_CFLAGS@
XRANDR_LIBS = @XRANDR_LIBS@
XRENDER_LIBS = @XRENDER_LIBS@
+XSHAPE_CFLAGS = @XSHAPE_CFLAGS@
+XSHAPE_LIBS = @XSHAPE_LIBS@
+XSYNC_CFLAGS = @XSYNC_CFLAGS@
+XSYNC_LIBS = @XSYNC_LIBS@
XWIDGETS_OBJ = @XWIDGETS_OBJ@
X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@
ac_ct_CC = @ac_ct_CC@
@@ -1251,8 +1320,10 @@ gl_GNULIB_ENABLED_rawmemchr_CONDITION = @gl_GNULIB_ENABLED_rawmemchr_CONDITION@
gl_GNULIB_ENABLED_scratch_buffer_CONDITION = @gl_GNULIB_ENABLED_scratch_buffer_CONDITION@
gl_GNULIB_ENABLED_strtoll_CONDITION = @gl_GNULIB_ENABLED_strtoll_CONDITION@
gl_GNULIB_ENABLED_utimens_CONDITION = @gl_GNULIB_ENABLED_utimens_CONDITION@
+gl_LIBOBJDEPS = @gl_LIBOBJDEPS@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
+gltests_LIBOBJDEPS = @gltests_LIBOBJDEPS@
gltests_LIBOBJS = @gltests_LIBOBJS@
gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
gltests_WITNESS = @gltests_WITNESS@
@@ -1303,6 +1374,7 @@ x_default_search_path = @x_default_search_path@
noinst_LIBRARIES += libgnu.a
libgnu_a_SOURCES =
+libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
libgnu_a_LIBADD = $(gl_LIBOBJS)
libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
EXTRA_libgnu_a_SOURCES =
@@ -1432,10 +1504,9 @@ endif
## begin gnulib module canonicalize-lgpl
ifeq (,$(OMIT_GNULIB_MODULE_canonicalize-lgpl))
-
-EXTRA_DIST += canonicalize-lgpl.c
-
-EXTRA_libgnu_a_SOURCES += canonicalize-lgpl.c
+ifneq (,$(GL_COND_OBJ_CANONICALIZE_LGPL_CONDITION))
+libgnu_a_SOURCES += canonicalize-lgpl.c
+endif
endif
## end gnulib module canonicalize-lgpl
@@ -1475,10 +1546,9 @@ endif
## begin gnulib module copy-file-range
ifeq (,$(OMIT_GNULIB_MODULE_copy-file-range))
-
-EXTRA_DIST += copy-file-range.c
-
-EXTRA_libgnu_a_SOURCES += copy-file-range.c
+ifneq (,$(GL_COND_OBJ_COPY_FILE_RANGE_CONDITION))
+libgnu_a_SOURCES += copy-file-range.c
+endif
endif
## end gnulib module copy-file-range
@@ -1621,13 +1691,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_dirfd))
ifneq (,$(gl_GNULIB_ENABLED_dirfd_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_DIRFD_CONDITION))
+libgnu_a_SOURCES += dirfd.c
endif
-EXTRA_DIST += dirfd.c
-
-EXTRA_libgnu_a_SOURCES += dirfd.c
endif
+endif
## end gnulib module dirfd
## begin gnulib module dtoastr
@@ -1653,10 +1722,9 @@ endif
## begin gnulib module dup2
ifeq (,$(OMIT_GNULIB_MODULE_dup2))
-
-EXTRA_DIST += dup2.c
-
-EXTRA_libgnu_a_SOURCES += dup2.c
+ifneq (,$(GL_COND_OBJ_DUP2_CONDITION))
+libgnu_a_SOURCES += dup2.c
+endif
endif
## end gnulib module dup2
@@ -1747,13 +1815,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_euidaccess))
ifneq (,$(gl_GNULIB_ENABLED_euidaccess_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_EUIDACCESS_CONDITION))
+libgnu_a_SOURCES += euidaccess.c
endif
-EXTRA_DIST += euidaccess.c
-
-EXTRA_libgnu_a_SOURCES += euidaccess.c
endif
+endif
## end gnulib module euidaccess
## begin gnulib module execinfo
@@ -1773,9 +1840,11 @@ execinfo.h: $(top_builddir)/config.status
endif
MOSTLYCLEANFILES += execinfo.h execinfo.h-t
-EXTRA_DIST += execinfo.c execinfo.in.h
+ifneq (,$(GL_COND_OBJ_EXECINFO_CONDITION))
+libgnu_a_SOURCES += execinfo.c
+endif
-EXTRA_libgnu_a_SOURCES += execinfo.c
+EXTRA_DIST += execinfo.in.h
endif
## end gnulib module execinfo
@@ -1783,10 +1852,9 @@ endif
## begin gnulib module explicit_bzero
ifeq (,$(OMIT_GNULIB_MODULE_explicit_bzero))
-
-EXTRA_DIST += explicit_bzero.c
-
-EXTRA_libgnu_a_SOURCES += explicit_bzero.c
+ifneq (,$(GL_COND_OBJ_EXPLICIT_BZERO_CONDITION))
+libgnu_a_SOURCES += explicit_bzero.c
+endif
endif
## end gnulib module explicit_bzero
@@ -1794,10 +1862,13 @@ endif
## begin gnulib module faccessat
ifeq (,$(OMIT_GNULIB_MODULE_faccessat))
+ifneq (,$(GL_COND_OBJ_FACCESSAT_CONDITION))
+libgnu_a_SOURCES += faccessat.c
+endif
-EXTRA_DIST += at-func.c faccessat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module faccessat
@@ -1805,10 +1876,13 @@ endif
## begin gnulib module fchmodat
ifeq (,$(OMIT_GNULIB_MODULE_fchmodat))
+ifneq (,$(GL_COND_OBJ_FCHMODAT_CONDITION))
+libgnu_a_SOURCES += fchmodat.c
+endif
-EXTRA_DIST += at-func.c fchmodat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c fchmodat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module fchmodat
@@ -1816,10 +1890,9 @@ endif
## begin gnulib module fcntl
ifeq (,$(OMIT_GNULIB_MODULE_fcntl))
-
-EXTRA_DIST += fcntl.c
-
-EXTRA_libgnu_a_SOURCES += fcntl.c
+ifneq (,$(GL_COND_OBJ_FCNTL_CONDITION))
+libgnu_a_SOURCES += fcntl.c
+endif
endif
## end gnulib module fcntl
@@ -1866,10 +1939,9 @@ endif
## begin gnulib module fdopendir
ifeq (,$(OMIT_GNULIB_MODULE_fdopendir))
-
-EXTRA_DIST += fdopendir.c
-
-EXTRA_libgnu_a_SOURCES += fdopendir.c
+ifneq (,$(GL_COND_OBJ_FDOPENDIR_CONDITION))
+libgnu_a_SOURCES += fdopendir.c
+endif
endif
## end gnulib module fdopendir
@@ -1925,10 +1997,11 @@ endif
## begin gnulib module fpending
ifeq (,$(OMIT_GNULIB_MODULE_fpending))
+ifneq (,$(GL_COND_OBJ_FPENDING_CONDITION))
+libgnu_a_SOURCES += fpending.c
+endif
-EXTRA_DIST += fpending.c fpending.h stdio-impl.h
-
-EXTRA_libgnu_a_SOURCES += fpending.c
+EXTRA_DIST += fpending.h stdio-impl.h
endif
## end gnulib module fpending
@@ -1936,10 +2009,9 @@ endif
## begin gnulib module free-posix
ifeq (,$(OMIT_GNULIB_MODULE_free-posix))
-
-EXTRA_DIST += free.c
-
-EXTRA_libgnu_a_SOURCES += free.c
+ifneq (,$(GL_COND_OBJ_FREE_CONDITION))
+libgnu_a_SOURCES += free.c
+endif
endif
## end gnulib module free-posix
@@ -1947,10 +2019,13 @@ endif
## begin gnulib module fstatat
ifeq (,$(OMIT_GNULIB_MODULE_fstatat))
+ifneq (,$(GL_COND_OBJ_FSTATAT_CONDITION))
+libgnu_a_SOURCES += fstatat.c
+endif
-EXTRA_DIST += at-func.c fstatat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module fstatat
@@ -1958,10 +2033,11 @@ endif
## begin gnulib module fsusage
ifeq (,$(OMIT_GNULIB_MODULE_fsusage))
+ifneq (,$(GL_COND_OBJ_FSUSAGE_CONDITION))
+libgnu_a_SOURCES += fsusage.c
+endif
-EXTRA_DIST += fsusage.c fsusage.h
-
-EXTRA_libgnu_a_SOURCES += fsusage.c
+EXTRA_DIST += fsusage.h
endif
## end gnulib module fsusage
@@ -1969,10 +2045,9 @@ endif
## begin gnulib module fsync
ifeq (,$(OMIT_GNULIB_MODULE_fsync))
-
-EXTRA_DIST += fsync.c
-
-EXTRA_libgnu_a_SOURCES += fsync.c
+ifneq (,$(GL_COND_OBJ_FSYNC_CONDITION))
+libgnu_a_SOURCES += fsync.c
+endif
endif
## end gnulib module fsync
@@ -1980,10 +2055,9 @@ endif
## begin gnulib module futimens
ifeq (,$(OMIT_GNULIB_MODULE_futimens))
-
-EXTRA_DIST += futimens.c
-
-EXTRA_libgnu_a_SOURCES += futimens.c
+ifneq (,$(GL_COND_OBJ_FUTIMENS_CONDITION))
+libgnu_a_SOURCES += futimens.c
+endif
endif
## end gnulib module futimens
@@ -2013,35 +2087,32 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize))
ifneq (,$(gl_GNULIB_ENABLED_getdtablesize_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_GETDTABLESIZE_CONDITION))
+libgnu_a_SOURCES += getdtablesize.c
endif
-EXTRA_DIST += getdtablesize.c
-
-EXTRA_libgnu_a_SOURCES += getdtablesize.c
endif
+endif
## end gnulib module getdtablesize
## begin gnulib module getgroups
ifeq (,$(OMIT_GNULIB_MODULE_getgroups))
ifneq (,$(gl_GNULIB_ENABLED_getgroups_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_GETGROUPS_CONDITION))
+libgnu_a_SOURCES += getgroups.c
endif
-EXTRA_DIST += getgroups.c
-
-EXTRA_libgnu_a_SOURCES += getgroups.c
endif
+endif
## end gnulib module getgroups
## begin gnulib module getloadavg
ifeq (,$(OMIT_GNULIB_MODULE_getloadavg))
-
-EXTRA_DIST += getloadavg.c
-
-EXTRA_libgnu_a_SOURCES += getloadavg.c
+ifneq (,$(GL_COND_OBJ_GETLOADAVG_CONDITION))
+libgnu_a_SOURCES += getloadavg.c
+endif
endif
## end gnulib module getloadavg
@@ -2083,9 +2154,11 @@ endif
MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t
-EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c getopt.in.h getopt1.c getopt_int.h
+ifneq (,$(GL_COND_OBJ_GETOPT_CONDITION))
+libgnu_a_SOURCES += getopt.c getopt1.c
+endif
-EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c
+EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.in.h getopt_int.h
endif
## end gnulib module getopt-posix
@@ -2093,10 +2166,9 @@ endif
## begin gnulib module getrandom
ifeq (,$(OMIT_GNULIB_MODULE_getrandom))
-
-EXTRA_DIST += getrandom.c
-
-EXTRA_libgnu_a_SOURCES += getrandom.c
+ifneq (,$(GL_COND_OBJ_GETRANDOM_CONDITION))
+libgnu_a_SOURCES += getrandom.c
+endif
endif
## end gnulib module getrandom
@@ -2122,10 +2194,9 @@ endif
## begin gnulib module gettimeofday
ifeq (,$(OMIT_GNULIB_MODULE_gettimeofday))
-
-EXTRA_DIST += gettimeofday.c
-
-EXTRA_libgnu_a_SOURCES += gettimeofday.c
+ifneq (,$(GL_COND_OBJ_GETTIMEOFDAY_CONDITION))
+libgnu_a_SOURCES += gettimeofday.c
+endif
endif
## end gnulib module gettimeofday
@@ -2143,13 +2214,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_group-member))
ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_GROUP_MEMBER_CONDITION))
+libgnu_a_SOURCES += group-member.c
endif
-EXTRA_DIST += group-member.c
-
-EXTRA_libgnu_a_SOURCES += group-member.c
endif
+endif
## end gnulib module group-member
## begin gnulib module idx
@@ -2249,13 +2319,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_lchmod))
ifneq (,$(gl_GNULIB_ENABLED_lchmod_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_LCHMOD_CONDITION))
+libgnu_a_SOURCES += lchmod.c
endif
-EXTRA_DIST += lchmod.c
-
-EXTRA_libgnu_a_SOURCES += lchmod.c
endif
+endif
## end gnulib module lchmod
## begin gnulib module libc-config
@@ -2291,9 +2360,13 @@ gmp.h: $(top_builddir)/config.status
endif
MOSTLYCLEANFILES += gmp.h gmp.h-t
-EXTRA_DIST += mini-gmp-gnulib.c mini-gmp.c mini-gmp.h
+ifneq (,$(GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION))
+libgnu_a_SOURCES += mini-gmp-gnulib.c
+endif
-EXTRA_libgnu_a_SOURCES += mini-gmp-gnulib.c mini-gmp.c
+EXTRA_DIST += mini-gmp.c mini-gmp.h
+
+EXTRA_libgnu_a_SOURCES += mini-gmp.c
endif
## end gnulib module libgmp
@@ -2329,10 +2402,9 @@ endif
## begin gnulib module lstat
ifeq (,$(OMIT_GNULIB_MODULE_lstat))
-
-EXTRA_DIST += lstat.c
-
-EXTRA_libgnu_a_SOURCES += lstat.c
+ifneq (,$(GL_COND_OBJ_LSTAT_CONDITION))
+libgnu_a_SOURCES += lstat.c
+endif
endif
## end gnulib module lstat
@@ -2377,10 +2449,9 @@ endif
## begin gnulib module mempcpy
ifeq (,$(OMIT_GNULIB_MODULE_mempcpy))
-
-EXTRA_DIST += mempcpy.c
-
-EXTRA_libgnu_a_SOURCES += mempcpy.c
+ifneq (,$(GL_COND_OBJ_MEMPCPY_CONDITION))
+libgnu_a_SOURCES += mempcpy.c
+endif
endif
## end gnulib module mempcpy
@@ -2388,10 +2459,9 @@ endif
## begin gnulib module memrchr
ifeq (,$(OMIT_GNULIB_MODULE_memrchr))
-
-EXTRA_DIST += memrchr.c
-
-EXTRA_libgnu_a_SOURCES += memrchr.c
+ifneq (,$(GL_COND_OBJ_MEMRCHR_CONDITION))
+libgnu_a_SOURCES += memrchr.c
+endif
endif
## end gnulib module memrchr
@@ -2407,10 +2477,9 @@ endif
## begin gnulib module mkostemp
ifeq (,$(OMIT_GNULIB_MODULE_mkostemp))
-
-EXTRA_DIST += mkostemp.c
-
-EXTRA_libgnu_a_SOURCES += mkostemp.c
+ifneq (,$(GL_COND_OBJ_MKOSTEMP_CONDITION))
+libgnu_a_SOURCES += mkostemp.c
+endif
endif
## end gnulib module mkostemp
@@ -2439,6 +2508,16 @@ EXTRA_libgnu_a_SOURCES += mktime.c
endif
## end gnulib module mktime-internal
+## begin gnulib module nanosleep
+ifeq (,$(OMIT_GNULIB_MODULE_nanosleep))
+
+ifneq (,$(GL_COND_OBJ_NANOSLEEP_CONDITION))
+libgnu_a_SOURCES += nanosleep.c
+endif
+
+endif
+## end gnulib module nanosleep
+
## begin gnulib module nproc
ifeq (,$(OMIT_GNULIB_MODULE_nproc))
@@ -2463,13 +2542,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_open))
ifneq (,$(gl_GNULIB_ENABLED_open_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_OPEN_CONDITION))
+libgnu_a_SOURCES += open.c
endif
-EXTRA_DIST += open.c
-
-EXTRA_libgnu_a_SOURCES += open.c
endif
+endif
## end gnulib module open
## begin gnulib module openat-h
@@ -2503,10 +2581,9 @@ endif
## begin gnulib module pselect
ifeq (,$(OMIT_GNULIB_MODULE_pselect))
-
-EXTRA_DIST += pselect.c
-
-EXTRA_libgnu_a_SOURCES += pselect.c
+ifneq (,$(GL_COND_OBJ_PSELECT_CONDITION))
+libgnu_a_SOURCES += pselect.c
+endif
endif
## end gnulib module pselect
@@ -2514,10 +2591,9 @@ endif
## begin gnulib module pthread_sigmask
ifeq (,$(OMIT_GNULIB_MODULE_pthread_sigmask))
-
-EXTRA_DIST += pthread_sigmask.c
-
-EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
+ifneq (,$(GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION))
+libgnu_a_SOURCES += pthread_sigmask.c
+endif
endif
## end gnulib module pthread_sigmask
@@ -2534,11 +2610,12 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_rawmemchr))
ifneq (,$(gl_GNULIB_ENABLED_rawmemchr_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_RAWMEMCHR_CONDITION))
+libgnu_a_SOURCES += rawmemchr.c
endif
-EXTRA_DIST += rawmemchr.c rawmemchr.valgrind
-EXTRA_libgnu_a_SOURCES += rawmemchr.c
+endif
+EXTRA_DIST += rawmemchr.valgrind
endif
## end gnulib module rawmemchr
@@ -2546,10 +2623,9 @@ endif
## begin gnulib module readlink
ifeq (,$(OMIT_GNULIB_MODULE_readlink))
-
-EXTRA_DIST += readlink.c
-
-EXTRA_libgnu_a_SOURCES += readlink.c
+ifneq (,$(GL_COND_OBJ_READLINK_CONDITION))
+libgnu_a_SOURCES += readlink.c
+endif
endif
## end gnulib module readlink
@@ -2557,10 +2633,13 @@ endif
## begin gnulib module readlinkat
ifeq (,$(OMIT_GNULIB_MODULE_readlinkat))
+ifneq (,$(GL_COND_OBJ_READLINKAT_CONDITION))
+libgnu_a_SOURCES += readlinkat.c
+endif
-EXTRA_DIST += at-func.c readlinkat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c readlinkat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module readlinkat
@@ -2594,10 +2673,13 @@ endif
## begin gnulib module regex
ifeq (,$(OMIT_GNULIB_MODULE_regex))
+ifneq (,$(GL_COND_OBJ_REGEX_CONDITION))
+libgnu_a_SOURCES += regex.c
+endif
-EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c
+EXTRA_DIST += regcomp.c regex.h regex_internal.c regex_internal.h regexec.c
-EXTRA_libgnu_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c
+EXTRA_libgnu_a_SOURCES += regcomp.c regex_internal.c regexec.c
endif
## end gnulib module regex
@@ -2641,10 +2723,11 @@ endif
## begin gnulib module sig2str
ifeq (,$(OMIT_GNULIB_MODULE_sig2str))
+ifneq (,$(GL_COND_OBJ_SIG2STR_CONDITION))
+libgnu_a_SOURCES += sig2str.c
+endif
-EXTRA_DIST += sig2str.c sig2str.h
-
-EXTRA_libgnu_a_SOURCES += sig2str.c
+EXTRA_DIST += sig2str.h
endif
## end gnulib module sig2str
@@ -2652,10 +2735,9 @@ endif
## begin gnulib module sigdescr_np
ifeq (,$(OMIT_GNULIB_MODULE_sigdescr_np))
-
-EXTRA_DIST += sigdescr_np.c
-
-EXTRA_libgnu_a_SOURCES += sigdescr_np.c
+ifneq (,$(GL_COND_OBJ_SIGDESCR_NP_CONDITION))
+libgnu_a_SOURCES += sigdescr_np.c
+endif
endif
## end gnulib module sigdescr_np
@@ -3004,6 +3086,13 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
$(AM_V_at)mv $@-t $@
MOSTLYCLEANFILES += stdio.h stdio.h-t
+ifneq (,$(GL_COND_OBJ_STDIO_READ_CONDITION))
+libgnu_a_SOURCES += stdio-read.c
+endif
+ifneq (,$(GL_COND_OBJ_STDIO_WRITE_CONDITION))
+libgnu_a_SOURCES += stdio-write.c
+endif
+
EXTRA_DIST += stdio.in.h
endif
@@ -3163,10 +3252,9 @@ endif
## begin gnulib module stpcpy
ifeq (,$(OMIT_GNULIB_MODULE_stpcpy))
-
-EXTRA_DIST += stpcpy.c
-
-EXTRA_libgnu_a_SOURCES += stpcpy.c
+ifneq (,$(GL_COND_OBJ_STPCPY_CONDITION))
+libgnu_a_SOURCES += stpcpy.c
+endif
endif
## end gnulib module stpcpy
@@ -3287,10 +3375,9 @@ endif
## begin gnulib module strnlen
ifeq (,$(OMIT_GNULIB_MODULE_strnlen))
-
-EXTRA_DIST += strnlen.c
-
-EXTRA_libgnu_a_SOURCES += strnlen.c
+ifneq (,$(GL_COND_OBJ_STRNLEN_CONDITION))
+libgnu_a_SOURCES += strnlen.c
+endif
endif
## end gnulib module strnlen
@@ -3298,10 +3385,9 @@ endif
## begin gnulib module strtoimax
ifeq (,$(OMIT_GNULIB_MODULE_strtoimax))
-
-EXTRA_DIST += strtoimax.c
-
-EXTRA_libgnu_a_SOURCES += strtoimax.c
+ifneq (,$(GL_COND_OBJ_STRTOIMAX_CONDITION))
+libgnu_a_SOURCES += strtoimax.c
+endif
endif
## end gnulib module strtoimax
@@ -3310,11 +3396,14 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_strtoll))
ifneq (,$(gl_GNULIB_ENABLED_strtoll_CONDITION))
+ifneq (,$(GL_COND_OBJ_STRTOLL_CONDITION))
+libgnu_a_SOURCES += strtoll.c
+endif
endif
-EXTRA_DIST += strtol.c strtoll.c
+EXTRA_DIST += strtol.c
-EXTRA_libgnu_a_SOURCES += strtol.c strtoll.c
+EXTRA_libgnu_a_SOURCES += strtol.c
endif
## end gnulib module strtoll
@@ -3322,10 +3411,9 @@ endif
## begin gnulib module symlink
ifeq (,$(OMIT_GNULIB_MODULE_symlink))
-
-EXTRA_DIST += symlink.c
-
-EXTRA_libgnu_a_SOURCES += symlink.c
+ifneq (,$(GL_COND_OBJ_SYMLINK_CONDITION))
+libgnu_a_SOURCES += symlink.c
+endif
endif
## end gnulib module symlink
@@ -3413,6 +3501,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
-e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
-e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \
+ -e 's/@''GNULIB_CHMOD''@/$(GL_GNULIB_CHMOD)/g' \
-e 's/@''GNULIB_FCHMODAT''@/$(GL_GNULIB_FCHMODAT)/g' \
-e 's/@''GNULIB_FSTAT''@/$(GL_GNULIB_FSTAT)/g' \
-e 's/@''GNULIB_FSTATAT''@/$(GL_GNULIB_FSTATAT)/g' \
@@ -3444,6 +3533,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \
-e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
-e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
+ -e 's|@''REPLACE_CHMOD''@|$(REPLACE_CHMOD)|g' \
-e 's|@''REPLACE_FCHMODAT''@|$(REPLACE_FCHMODAT)|g' \
-e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \
-e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \
@@ -3602,10 +3692,9 @@ endif
## begin gnulib module time_r
ifeq (,$(OMIT_GNULIB_MODULE_time_r))
-
-EXTRA_DIST += time_r.c
-
-EXTRA_libgnu_a_SOURCES += time_r.c
+ifneq (,$(GL_COND_OBJ_TIME_R_CONDITION))
+libgnu_a_SOURCES += time_r.c
+endif
endif
## end gnulib module time_r
@@ -3613,10 +3702,11 @@ endif
## begin gnulib module time_rz
ifeq (,$(OMIT_GNULIB_MODULE_time_rz))
+ifneq (,$(GL_COND_OBJ_TIME_RZ_CONDITION))
+libgnu_a_SOURCES += time_rz.c
+endif
-EXTRA_DIST += time-internal.h time_rz.c
-
-EXTRA_libgnu_a_SOURCES += time_rz.c
+EXTRA_DIST += time-internal.h
endif
## end gnulib module time_rz
@@ -3624,10 +3714,11 @@ endif
## begin gnulib module timegm
ifeq (,$(OMIT_GNULIB_MODULE_timegm))
+ifneq (,$(GL_COND_OBJ_TIMEGM_CONDITION))
+libgnu_a_SOURCES += timegm.c
+endif
-EXTRA_DIST += mktime-internal.h timegm.c
-
-EXTRA_libgnu_a_SOURCES += timegm.c
+EXTRA_DIST += mktime-internal.h
endif
## end gnulib module timegm
@@ -3821,6 +3912,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
sed -e 's|@''REPLACE_ACCESS''@|$(REPLACE_ACCESS)|g' \
-e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
-e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \
+ -e 's|@''REPLACE_COPY_FILE_RANGE''@|$(REPLACE_COPY_FILE_RANGE)|g' \
-e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
-e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
-e 's|@''REPLACE_EXECL''@|$(REPLACE_EXECL)|g' \
@@ -3909,10 +4001,13 @@ endif
## begin gnulib module utimensat
ifeq (,$(OMIT_GNULIB_MODULE_utimensat))
+ifneq (,$(GL_COND_OBJ_UTIMENSAT_CONDITION))
+libgnu_a_SOURCES += utimensat.c
+endif
-EXTRA_DIST += at-func.c utimensat.c
+EXTRA_DIST += at-func.c
-EXTRA_libgnu_a_SOURCES += at-func.c utimensat.c
+EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module utimensat
@@ -3954,3 +4049,7 @@ mostlyclean-local: mostlyclean-generic
fi; \
done; \
:
+distclean-local: distclean-gnulib-libobjs
+distclean-gnulib-libobjs:
+ -rm -f @gl_LIBOBJDEPS@
+maintainer-clean-local: distclean-gnulib-libobjs
diff --git a/lib/intprops.h b/lib/intprops.h
index 68d6daa5706..d4a917f72a0 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -229,11 +229,15 @@
/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
(A, B, P) work when P is non-null. */
-#if defined __has_builtin
+#ifdef __EDG__
+/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned
+ <https://bugs.gnu.org/53256>. */
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
+#elif defined __has_builtin
# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
-#elif 7 <= __GNUC__ && !defined __EDG__
+#elif 7 <= __GNUC__
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
#else
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
diff --git a/lib/lchmod.c b/lib/lchmod.c
index 479ed776cba..8410a2d835f 100644
--- a/lib/lchmod.c
+++ b/lib/lchmod.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -25,17 +25,9 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
-#ifdef __osf__
-/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
- eliminates this include because of the preliminary #include <sys/stat.h>
- above. */
-# include "sys/stat.h"
-#else
-# include <sys/stat.h>
-#endif
-
#include <intprops.h>
/* Work like chmod, except when FILE is a symbolic link.
@@ -45,7 +37,9 @@
int
lchmod (char const *file, mode_t mode)
{
-#if defined O_PATH && defined AT_EMPTY_PATH
+ char readlink_buf[1];
+
+#ifdef O_PATH
/* Open a file descriptor with O_NOFOLLOW, to make sure we don't
follow symbolic links, if /proc is mounted. O_PATH is used to
avoid a failure if the file is not readable.
@@ -54,56 +48,46 @@ lchmod (char const *file, mode_t mode)
if (fd < 0)
return fd;
- /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the
- chmod call below will change the permissions of the symbolic link
- - which is undesired - and on many file systems (ext4, btrfs, jfs,
- xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is
- misleading. Therefore test for a symbolic link explicitly.
- Use fstatat because fstat does not work on O_PATH descriptors
- before Linux 3.6. */
- struct stat st;
- if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0)
+ int err;
+ if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
+ err = EOPNOTSUPP;
+ else if (errno == EINVAL)
{
- int stat_errno = errno;
- close (fd);
- errno = stat_errno;
- return -1;
- }
- if (S_ISLNK (st.st_mode))
- {
- close (fd);
- errno = EOPNOTSUPP;
- return -1;
+ static char const fmt[] = "/proc/self/fd/%d";
+ char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+ sprintf (buf, fmt, fd);
+ err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
}
+ else
+ err = errno == ENOENT ? -1 : errno;
-# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__
- static char const fmt[] = "/proc/self/fd/%d";
- char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
- sprintf (buf, fmt, fd);
- int chmod_result = chmod (buf, mode);
- int chmod_errno = errno;
close (fd);
- if (chmod_result == 0)
- return chmod_result;
- if (chmod_errno != ENOENT)
+
+ errno = err;
+ if (0 <= err)
+ return err == 0 ? 0 : -1;
+#endif
+
+ size_t len = strlen (file);
+ if (len && file[len - 1] == '/')
{
- errno = chmod_errno;
- return chmod_result;
+ struct stat st;
+ if (lstat (file, &st) < 0)
+ return -1;
+ if (!S_ISDIR (st.st_mode))
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
}
-# endif
- /* /proc is not mounted or would not work as in GNU/Linux. */
-
-#elif HAVE_LSTAT
- struct stat st;
- int lstat_result = lstat (file, &st);
- if (lstat_result != 0)
- return lstat_result;
- if (S_ISLNK (st.st_mode))
+
+ /* O_PATH + /proc is not supported. */
+
+ if (0 <= readlink (file, readlink_buf, sizeof readlink_buf))
{
errno = EOPNOTSUPP;
return -1;
}
-#endif
/* Fall back on chmod, despite a possible race. */
return chmod (file, mode);
diff --git a/lib/libc-config.h b/lib/libc-config.h
index 8fec4893787..a56665b1ce3 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -121,6 +121,7 @@
# undef __attr_dealloc
# undef __attr_dealloc_free
# undef __attribute__
+# undef __attribute_alloc_align__
# undef __attribute_alloc_size__
# undef __attribute_artificial__
# undef __attribute_const__
@@ -129,6 +130,7 @@
# undef __attribute_format_arg__
# undef __attribute_format_strfmon__
# undef __attribute_malloc__
+# undef __attribute_maybe_unused__
# undef __attribute_noinline__
# undef __attribute_nonstring__
# undef __attribute_pure__
@@ -142,16 +144,24 @@
# undef __extern_always_inline
# undef __extern_inline
# undef __flexarr
+# undef __fortified_attr_access
# undef __fortify_function
# undef __glibc_c99_flexarr_available
+# undef __glibc_fortify
+# undef __glibc_fortify_n
# undef __glibc_has_attribute
# undef __glibc_has_builtin
# undef __glibc_has_extension
+# undef __glibc_likely
# undef __glibc_macro_warning
# undef __glibc_macro_warning1
# undef __glibc_objsize
# undef __glibc_objsize0
+# undef __glibc_safe_len_cond
+# undef __glibc_safe_or_unknown_len
# undef __glibc_unlikely
+# undef __glibc_unsafe_len
+# undef __glibc_unsigned_or_positive
# undef __inline
# undef __ptr_t
# undef __restrict
@@ -159,6 +169,7 @@
# undef __va_arg_pack
# undef __va_arg_pack_len
# undef __warnattr
+# undef __wur
/* Include our copy of glibc <sys/cdefs.h>. */
# include <cdefs.h>
diff --git a/lib/md5.h b/lib/md5.h
index 5b92eac5ec8..611c230b817 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -24,6 +24,9 @@
#include <stdint.h>
# if HAVE_OPENSSL_MD5
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/md5.h>
# endif
diff --git a/lib/memrchr.c b/lib/memrchr.c
index e853996ad0a..90fdb86f1f1 100644
--- a/lib/memrchr.c
+++ b/lib/memrchr.c
@@ -11,7 +11,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c
index 7620da38dbb..7d09c80e9e9 100644
--- a/lib/mini-gmp-gnulib.c
+++ b/lib/mini-gmp-gnulib.c
@@ -6,7 +6,7 @@
It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
You can redistribute it and/or modify it under either
- the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 3, or (at your
+ by the Free Software Foundation, either version 3, or (at your
option) any later version, or
- the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option)
@@ -40,7 +40,8 @@
#endif
/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */
-#if defined NDEBUG && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+#if (defined NDEBUG \
+ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__))
# pragma GCC diagnostic ignored "-Wunused-variable"
#endif
diff --git a/lib/mini-gmp.c b/lib/mini-gmp.c
index 8577b59ef6d..95f067f82d6 100644
--- a/lib/mini-gmp.c
+++ b/lib/mini-gmp.c
@@ -90,6 +90,7 @@ see https://www.gnu.org/licenses/. */
#define gmp_assert_nocarry(x) do { \
mp_limb_t __cy = (x); \
assert (__cy == 0); \
+ (void) (__cy); \
} while (0)
#define gmp_clz(count, x) do { \
@@ -1937,9 +1938,8 @@ mpz_neg (mpz_t r, const mpz_t u)
void
mpz_swap (mpz_t u, mpz_t v)
{
- MP_SIZE_T_SWAP (u->_mp_size, v->_mp_size);
MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc);
- MP_PTR_SWAP (u->_mp_d, v->_mp_d);
+ MPN_PTR_SWAP (u->_mp_d, u->_mp_size, v->_mp_d, v->_mp_size);
}
diff --git a/lib/mktime.c b/lib/mktime.c
index aa12e28e168..7dc9d67ef9d 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -429,8 +429,13 @@ __mktime_internal (struct tm *tp,
time with the right value, and use its UTC offset.
Heuristic: probe the adjacent timestamps in both directions,
- looking for the desired isdst. This should work for all real
- time zone histories in the tz database. */
+ looking for the desired isdst. If none is found within a
+ reasonable duration bound, assume a one-hour DST difference.
+ This should work for all real time zone histories in the tz
+ database. */
+
+ /* +1 if we wanted standard time but got DST, -1 if the reverse. */
+ int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
/* Distance between probes when looking for a DST boundary. In
tzdata2003a, the shortest period of DST is 601200 seconds
@@ -441,12 +446,14 @@ __mktime_internal (struct tm *tp,
periods when probing. */
int stride = 601200;
- /* The longest period of DST in tzdata2003a is 536454000 seconds
- (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
- period of non-DST is much longer, but it makes no real sense
- to search for more than a year of non-DST, so use the DST
- max. */
- int duration_max = 536454000;
+ /* In TZDB 2021e, the longest period of DST (or of non-DST), in
+ which the DST (or adjacent DST) difference is not one hour,
+ is 457243209 seconds: e.g., America/Cambridge_Bay with leap
+ seconds, starting 1965-10-31 00:00 in a switch from
+ double-daylight time (-05) to standard time (-07), and
+ continuing to 1980-04-27 02:00 in a switch from standard time
+ (-07) to daylight time (-06). */
+ int duration_max = 457243209;
/* Search in both directions, so the maximum distance is half
the duration; add the stride to avoid off-by-1 problems. */
@@ -483,6 +490,11 @@ __mktime_internal (struct tm *tp,
}
}
+ /* No unusual DST offset was found nearby. Assume one-hour DST. */
+ t += 60 * 60 * dst_difference;
+ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
+ goto offset_found;
+
__set_errno (EOVERFLOW);
return -1;
}
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
new file mode 100644
index 00000000000..446794edc0b
--- /dev/null
+++ b/lib/nanosleep.c
@@ -0,0 +1,195 @@
+/* Provide a replacement for the POSIX nanosleep function.
+
+ Copyright (C) 1999-2000, 2002, 2004-2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering
+ and Bruno Haible for the native Windows part */
+
+#include <config.h>
+
+#include <time.h>
+
+#include "intprops.h"
+#include "verify.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <signal.h>
+
+#include <errno.h>
+
+#include <unistd.h>
+
+
+enum { BILLION = 1000 * 1000 * 1000 };
+
+#if HAVE_BUG_BIG_NANOSLEEP
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+# undef nanosleep
+{
+ /* nanosleep mishandles large sleeps due to internal overflow problems.
+ The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
+ can't sleep more than 24.85 days (2^31 milliseconds). Similarly,
+ cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds).
+ Solve this by breaking the sleep up into smaller chunks. */
+
+ if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ {
+ /* Verify that time_t is large enough. */
+ verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);
+ const time_t limit = 24 * 24 * 60 * 60;
+ time_t seconds = requested_delay->tv_sec;
+ struct timespec intermediate;
+ intermediate.tv_nsec = requested_delay->tv_nsec;
+
+ while (limit < seconds)
+ {
+ int result;
+ intermediate.tv_sec = limit;
+ result = nanosleep (&intermediate, remaining_delay);
+ seconds -= limit;
+ if (result)
+ {
+ if (remaining_delay)
+ remaining_delay->tv_sec += seconds;
+ return result;
+ }
+ intermediate.tv_nsec = 0;
+ }
+ intermediate.tv_sec = seconds;
+ return nanosleep (&intermediate, remaining_delay);
+ }
+}
+
+#elif defined _WIN32 && ! defined __CYGWIN__
+/* Native Windows platforms. */
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+/* The Windows API function Sleep() has a resolution of about 15 ms and takes
+ at least 5 ms to execute. We use this function for longer time periods.
+ Additionally, we use busy-looping over short time periods, to get a
+ resolution of about 0.01 ms. In order to measure such short timespans,
+ we use the QueryPerformanceCounter() function. */
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+{
+ static bool initialized;
+ /* Number of performance counter increments per nanosecond,
+ or zero if it could not be determined. */
+ static double ticks_per_nanosecond;
+
+ if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* For requested delays of one second or more, 15ms resolution is
+ sufficient. */
+ if (requested_delay->tv_sec == 0)
+ {
+ if (!initialized)
+ {
+ /* Initialize ticks_per_nanosecond. */
+ LARGE_INTEGER ticks_per_second;
+
+ if (QueryPerformanceFrequency (&ticks_per_second))
+ ticks_per_nanosecond =
+ (double) ticks_per_second.QuadPart / 1000000000.0;
+
+ initialized = true;
+ }
+ if (ticks_per_nanosecond)
+ {
+ /* QueryPerformanceFrequency worked. We can use
+ QueryPerformanceCounter. Use a combination of Sleep and
+ busy-looping. */
+ /* Number of milliseconds to pass to the Sleep function.
+ Since Sleep can take up to 8 ms less or 8 ms more than requested
+ (or maybe more if the system is loaded), we subtract 10 ms. */
+ int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10;
+ /* Determine how many ticks to delay. */
+ LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;
+ /* Start. */
+ LARGE_INTEGER counter_before;
+ if (QueryPerformanceCounter (&counter_before))
+ {
+ /* Wait until the performance counter has reached this value.
+ We don't need to worry about overflow, because the performance
+ counter is reset at reboot, and with a frequency of 3.6E6
+ ticks per second 63 bits suffice for over 80000 years. */
+ LONGLONG wait_until = counter_before.QuadPart + wait_ticks;
+ /* Use Sleep for the longest part. */
+ if (sleep_millis > 0)
+ Sleep (sleep_millis);
+ /* Busy-loop for the rest. */
+ for (;;)
+ {
+ LARGE_INTEGER counter_after;
+ if (!QueryPerformanceCounter (&counter_after))
+ /* QueryPerformanceCounter failed, but succeeded earlier.
+ Should not happen. */
+ break;
+ if (counter_after.QuadPart >= wait_until)
+ /* The requested time has elapsed. */
+ break;
+ }
+ goto done;
+ }
+ }
+ }
+ /* Implementation for long delays and as fallback. */
+ Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);
+
+ done:
+ /* Sleep is not interruptible. So there is no remaining delay. */
+ if (remaining_delay != NULL)
+ {
+ remaining_delay->tv_sec = 0;
+ remaining_delay->tv_nsec = 0;
+ }
+ return 0;
+}
+
+#else
+/* Other platforms lacking nanosleep.
+ It's not clear whether these are still practical porting targets.
+ For now, just fall back on pselect. */
+
+/* Suspend execution for at least *REQUESTED_DELAY seconds. The
+ *REMAINING_DELAY part isn't implemented yet. */
+
+int
+nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+{
+ return pselect (0, NULL, NULL, NULL, requested_delay, NULL);
+}
+#endif
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index 190ff4d8f20..c1dd5542478 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -3,7 +3,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
@@ -1158,7 +1158,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
case L_('q'): /* GNU extension. */
DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
- break;
case L_('R'):
subfmt = L_("%H:%M");
diff --git a/lib/openat-priv.h b/lib/openat-priv.h
index 451cac10cc6..5d60810709d 100644
--- a/lib/openat-priv.h
+++ b/lib/openat-priv.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
index d5f4296d478..3bacf7dbd13 100644
--- a/lib/openat-proc.c
+++ b/lib/openat-proc.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/openat.h b/lib/openat.h
index dcb2864ffc8..56919ef8dc4 100644
--- a/lib/openat.h
+++ b/lib/openat.h
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -98,12 +98,14 @@ lchmodat (int fd, char const *file, mode_t mode)
# define STATAT_INLINE _GL_INLINE
# endif
+_GL_ATTRIBUTE_DEPRECATED
STATAT_INLINE int
statat (int fd, char const *name, struct stat *st)
{
return fstatat (fd, name, st, 0);
}
+_GL_ATTRIBUTE_DEPRECATED
STATAT_INLINE int
lstatat (int fd, char const *name, struct stat *st)
{
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index 42ae68ffc1d..37fb179260d 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index f3d39604d2e..ab45e140b59 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/regcomp.c b/lib/regcomp.c
index b607c85320f..122c3de58c3 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -2038,15 +2038,25 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
}
switch (c)
{
- case '-':
- token->type = OP_CHARSET_RANGE;
- break;
case ']':
token->type = OP_CLOSE_BRACKET;
break;
case '^':
token->type = OP_NON_MATCH_LIST;
break;
+ case '-':
+ /* In V7 Unix grep and Unix awk and mawk, [...---...]
+ (3 adjacent minus signs) stands for a single minus sign.
+ Support that without breaking anything else. */
+ if (! (re_string_cur_idx (input) + 2 < re_string_length (input)
+ && re_string_peek_byte (input, 1) == '-'
+ && re_string_peek_byte (input, 2) == '-'))
+ {
+ token->type = OP_CHARSET_RANGE;
+ break;
+ }
+ re_string_skip_bytes (input, 2);
+ FALLTHROUGH;
default:
token->type = CHARACTER;
}
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 3945ee7ecbf..0e6919f3400 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -1396,24 +1396,22 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
if (__glibc_unlikely (new_nodes == NULL))
return -1;
dfa->nodes = new_nodes;
+ dfa->nodes_alloc = new_nodes_alloc;
new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc);
+ if (new_nexts != NULL)
+ dfa->nexts = new_nexts;
new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc);
+ if (new_indices != NULL)
+ dfa->org_indices = new_indices;
new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+ if (new_edests != NULL)
+ dfa->edests = new_edests;
new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
+ if (new_eclosures != NULL)
+ dfa->eclosures = new_eclosures;
if (__glibc_unlikely (new_nexts == NULL || new_indices == NULL
|| new_edests == NULL || new_eclosures == NULL))
- {
- re_free (new_nexts);
- re_free (new_indices);
- re_free (new_edests);
- re_free (new_eclosures);
- return -1;
- }
- dfa->nexts = new_nexts;
- dfa->org_indices = new_indices;
- dfa->edests = new_edests;
- dfa->eclosures = new_eclosures;
- dfa->nodes_alloc = new_nodes_alloc;
+ return -1;
}
dfa->nodes[dfa->nodes_len] = token;
dfa->nodes[dfa->nodes_len].constraint = 0;
diff --git a/lib/regexec.c b/lib/regexec.c
index aea1e7da52c..521cb028415 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -1308,8 +1308,8 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
re_node_set *eps_via_nodes)
{
reg_errcode_t err;
- Idx num = fs->num++;
- if (fs->num == fs->alloc)
+ Idx num = fs->num;
+ if (num == fs->alloc)
{
struct re_fail_stack_ent_t *new_array;
new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t,
@@ -1324,6 +1324,7 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs);
if (fs->stack[num].regs == NULL)
return REG_ESPACE;
+ fs->num = num + 1;
memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs);
err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
index 7aa124c42f8..90e8a0747ce 100644
--- a/lib/save-cwd.h
+++ b/lib/save-cwd.h
@@ -5,7 +5,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index 7a7c5e4ed0e..c1a4b82a0d0 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/sha1.h b/lib/sha1.h
index 098678d8da6..bc3470a508d 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -23,6 +23,9 @@
# include <stdint.h>
# if HAVE_OPENSSL_SHA1
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
diff --git a/lib/sha256.h b/lib/sha256.h
index dc9d87e615f..533173a59e8 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -22,6 +22,9 @@
# include <stdint.h>
# if HAVE_OPENSSL_SHA256
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
diff --git a/lib/sha512.h b/lib/sha512.h
index f38819faf0f..1eb18702278 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -22,6 +22,9 @@
# include "u64.h"
# if HAVE_OPENSSL_SHA512
+# ifndef OPENSSL_API_COMPAT
+# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */
+# endif
# include <openssl/sha.h>
# endif
diff --git a/lib/sig2str.c b/lib/sig2str.c
index f2f01d1f6fc..8e2fc0c0754 100644
--- a/lib/sig2str.c
+++ b/lib/sig2str.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/sig2str.h b/lib/sig2str.h
index a507170b64a..a45af7f9686 100644
--- a/lib/sig2str.h
+++ b/lib/sig2str.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index d52c2f79638..a86643c3ca3 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -184,7 +184,11 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - "
# undef free
# define free rpl_free
# endif
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_FUNCDECL_RPL (free, void, (void *ptr) throw ());
+# else
_GL_FUNCDECL_RPL (free, void, (void *ptr));
+# endif
_GL_CXXALIAS_RPL (free, void, (void *ptr));
# else
_GL_CXXALIAS_SYS (free, void, (void *ptr));
diff --git a/lib/str-two-way.h b/lib/str-two-way.h
index 7ee344aea14..b00017c0b4b 100644
--- a/lib/str-two-way.h
+++ b/lib/str-two-way.h
@@ -231,7 +231,7 @@ critical_factorization (const unsigned char *needle, size_t needle_len,
most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
-static RETURN_TYPE
+static RETURN_TYPE _GL_ATTRIBUTE_PURE
two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
const unsigned char *needle, size_t needle_len)
{
@@ -325,7 +325,7 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
sublinear performance is not possible. */
-static RETURN_TYPE
+static RETURN_TYPE _GL_ATTRIBUTE_PURE
two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
const unsigned char *needle, size_t needle_len)
{
diff --git a/lib/strftime.h b/lib/strftime.h
index 9e5cdc3f32c..a9847084f01 100644
--- a/lib/strftime.h
+++ b/lib/strftime.h
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/string.in.h b/lib/string.in.h
index 03e6a17a36d..3996da9fcb5 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -122,17 +122,33 @@ _GL_EXTERN_C void rpl_free (void *);
# undef _GL_ATTRIBUTE_DEALLOC_FREE
# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1)
# else
-# if defined _MSC_VER
-_GL_EXTERN_C void __cdecl free (void *);
+# if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+# if defined _DLL
+ __declspec (dllimport)
+# endif
+ void __cdecl free (void *);
# else
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) throw ();
+# else
_GL_EXTERN_C void free (void *);
+# endif
# endif
# endif
#else
-# if defined _MSC_VER
-_GL_EXTERN_C void __cdecl free (void *);
+# if defined _MSC_VER && !defined free
+_GL_EXTERN_C
+# if defined _DLL
+ __declspec (dllimport)
+# endif
+ void __cdecl free (void *);
# else
+# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
+_GL_EXTERN_C void free (void *) throw ();
+# else
_GL_EXTERN_C void free (void *);
+# endif
# endif
#endif
@@ -230,10 +246,11 @@ _GL_CXXALIAS_SYS_CAST2 (memchr,
void const *, (void const *__s, int __c, size_t __n));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ());
_GL_CXXALIASWARN1 (memchr, void const *,
- (void const *__s, int __c, size_t __n));
+ (void const *__s, int __c, size_t __n) throw ());
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (memchr);
# endif
@@ -315,9 +332,10 @@ _GL_CXXALIAS_SYS_CAST2 (memrchr,
void *, (void const *, int, size_t),
void const *, (void const *, int, size_t));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t));
-_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ());
+_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw ());
# else
_GL_CXXALIASWARN (memrchr);
# endif
@@ -345,9 +363,11 @@ _GL_CXXALIAS_SYS_CAST2 (rawmemchr,
void *, (void const *__s, int __c_in),
void const *, (void const *__s, int __c_in));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in));
-_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (rawmemchr, void const *,
+ (void const *__s, int __c_in) throw ());
# else
_GL_CXXALIASWARN (rawmemchr);
# endif
@@ -449,9 +469,11 @@ _GL_CXXALIAS_SYS_CAST2 (strchrnul,
char const *, (char const *__s, int __c_in));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in));
-_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (strchrnul, char const *,
+ (char const *__s, int __c_in) throw ());
# else
_GL_CXXALIASWARN (strchrnul);
# endif
@@ -563,22 +585,35 @@ _GL_WARN_ON_USE (strncat, "strncat is unportable - "
# undef strndup
# define strndup rpl_strndup
# endif
-_GL_FUNCDECL_RPL (strndup, char *, (char const *__s, size_t __n)
- _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_RPL (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
_GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n));
# else
-# if ! @HAVE_DECL_STRNDUP@
-_GL_FUNCDECL_SYS (strndup, char *, (char const *__s, size_t __n)
- _GL_ARG_NONNULL ((1)));
+# if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup)
+_GL_FUNCDECL_SYS (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
# endif
_GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n));
# endif
_GL_CXXALIASWARN (strndup);
-#elif defined GNULIB_POSIXCHECK
-# undef strndup
-# if HAVE_RAW_DECL_STRNDUP
+#else
+# if __GNUC__ >= 11 && !defined strndup
+/* For -Wmismatched-dealloc: Associate strndup with free or rpl_free. */
+_GL_FUNCDECL_SYS (strndup, char *,
+ (char const *__s, size_t __n)
+ _GL_ARG_NONNULL ((1))
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef strndup
+# if HAVE_RAW_DECL_STRNDUP
_GL_WARN_ON_USE (strndup, "strndup is unportable - "
"use gnulib module strndup for portability");
+# endif
# endif
#endif
@@ -638,10 +673,11 @@ _GL_CXXALIAS_SYS_CAST2 (strpbrk,
char *, (char const *__s, char const *__accept),
const char *, (char const *__s, char const *__accept));
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw ());
_GL_CXXALIASWARN1 (strpbrk, char const *,
- (char const *__s, char const *__accept));
+ (char const *__s, char const *__accept) throw ());
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strpbrk);
# endif
@@ -746,10 +782,12 @@ _GL_CXXALIAS_SYS_CAST2 (strstr,
const char *, (const char *haystack, const char *needle));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strstr, char *,
+ (char *haystack, const char *needle) throw ());
_GL_CXXALIASWARN1 (strstr, const char *,
- (const char *haystack, const char *needle));
+ (const char *haystack, const char *needle) throw ());
# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strstr);
# endif
@@ -795,10 +833,12 @@ _GL_CXXALIAS_SYS_CAST2 (strcasestr,
const char *, (const char *haystack, const char *needle));
# endif
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
- && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
-_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle));
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ || defined __clang__)
+_GL_CXXALIASWARN1 (strcasestr, char *,
+ (char *haystack, const char *needle) throw ());
_GL_CXXALIASWARN1 (strcasestr, const char *,
- (const char *haystack, const char *needle));
+ (const char *haystack, const char *needle) throw ());
# else
_GL_CXXALIASWARN (strcasestr);
# endif
diff --git a/lib/strtoimax.c b/lib/strtoimax.c
index d562746ee78..cad12d0d9be 100644
--- a/lib/strtoimax.c
+++ b/lib/strtoimax.c
@@ -5,7 +5,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/strtol.c b/lib/strtol.c
index 457f7a5d649..6c2e9333abc 100644
--- a/lib/strtol.c
+++ b/lib/strtol.c
@@ -8,7 +8,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/strtoll.c b/lib/strtoll.c
index 5124168c1bb..acea42ee003 100644
--- a/lib/strtoll.c
+++ b/lib/strtoll.c
@@ -5,7 +5,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/symlink.c b/lib/symlink.c
index 51850b2732c..26310af7b12 100644
--- a/lib/symlink.c
+++ b/lib/symlink.c
@@ -3,7 +3,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 28ddd42f818..714c3cb189e 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -391,7 +391,33 @@ struct stat
#endif
-#if @GNULIB_MDA_CHMOD@
+#if @GNULIB_CHMOD@
+# if @REPLACE_CHMOD@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod rpl_chmod
+# endif
+_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode));
+# elif defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod _chmod
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (chmod);
+#elif defined GNULIB_POSIXCHECK
+# undef chmod
+# if HAVE_RAW_DECL_CHMOD
+_GL_WARN_ON_USE (chmod, "chmod has portability problems - "
+ "use gnulib module chmod for portability");
+# endif
+#elif @GNULIB_MDA_CHMOD@
/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not
required. In C++ with GNULIB_NAMESPACE, avoid differences between
platforms by defining GNULIB_NAMESPACE::chmod always. */
diff --git a/lib/time-internal.h b/lib/time-internal.h
index e1bb56e53ec..c8a2a8ce6bc 100644
--- a/lib/time-internal.h
+++ b/lib/time-internal.h
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/time_rz.c b/lib/time_rz.c
index d0ae717f308..1a91d3778e7 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
index cd0b5f5f5be..0f270e5bc8c 100644
--- a/lib/timespec-add.c
+++ b/lib/timespec-add.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c
index 2b2aaa59373..36747833e39 100644
--- a/lib/timespec-sub.c
+++ b/lib/timespec-sub.c
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/timespec.c b/lib/timespec.c
index 82630c2f5a0..9d136cb803b 100644
--- a/lib/timespec.c
+++ b/lib/timespec.c
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/timespec.h b/lib/timespec.h
index e130d2c6e25..9e358289a2a 100644
--- a/lib/timespec.h
+++ b/lib/timespec.h
@@ -5,7 +5,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 3386f0b0f75..57df09ecdf4 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -415,16 +415,30 @@ _GL_CXXALIASWARN (close);
#if @GNULIB_COPY_FILE_RANGE@
-# if !@HAVE_COPY_FILE_RANGE@
+# if @REPLACE_COPY_FILE_RANGE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef copy_file_range
+# define copy_file_range rpl_copy_file_range
+# endif
+_GL_FUNCDECL_RPL (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+_GL_CXXALIAS_RPL (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+# else
+# if !@HAVE_COPY_FILE_RANGE@
_GL_FUNCDECL_SYS (copy_file_range, ssize_t, (int ifd, off_t *ipos,
int ofd, off_t *opos,
size_t len, unsigned flags));
+# endif
_GL_CXXALIAS_SYS (copy_file_range, ssize_t, (int ifd, off_t *ipos,
int ofd, off_t *opos,
size_t len, unsigned flags));
# endif
_GL_CXXALIASWARN (copy_file_range);
#elif defined GNULIB_POSIXCHECK
+# undef copy_file_range
# if HAVE_RAW_DECL_COPY_FILE_RANGE
_GL_WARN_ON_USE (copy_file_range,
"copy_file_range is unportable - "
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index ce52f8f9773..7461d740959 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/utimens.c b/lib/utimens.c
index f4907ae4e61..2fa12518507 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/utimens.h b/lib/utimens.h
index c3054da0c67..2ccc06e5ed6 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -4,7 +4,7 @@
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 3 of the
+ published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
diff --git a/lib/utimensat.c b/lib/utimensat.c
index 2e4c7bf9660..f81b0c790ef 100644
--- a/lib/utimensat.c
+++ b/lib/utimensat.c
@@ -3,7 +3,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lib/verify.h b/lib/verify.h
index 07b2f4866f2..c5c63ae97c6 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -34,7 +34,7 @@
#ifndef __cplusplus
# if (201112L <= __STDC_VERSION__ \
|| (!defined __STRICT_ANSI__ \
- && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 4 <= __clang_major__)))
+ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__)))
# define _GL_HAVE__STATIC_ASSERT 1
# endif
# if (202000L <= __STDC_VERSION__ \
@@ -215,6 +215,9 @@ template <int w>
# define _GL_VERIFY(R, DIAGNOSTIC, ...) \
extern int (*_GL_GENSYM (_gl_verify_function) (void)) \
[_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
+# if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wnested-externs"
+# endif
#endif
/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */
diff --git a/lib/vla.h b/lib/vla.h
index adc8f8f68b6..ce02428f53a 100644
--- a/lib/vla.h
+++ b/lib/vla.h
@@ -4,7 +4,7 @@
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index d29dec08a5e..9516f2fc364 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -59,15 +59,6 @@ BYTE_COMPILE_EXTRA_FLAGS =
# BYTE_COMPILE_EXTRA_FLAGS = --eval '(setq byte-compile-warnings (quote (not unresolved)))'
# The example above is just for developers, it should not be used by default.
-# Those automatically generated autoload files that need special rules
-# to build; i.e. not including things created via generated-autoload-file
-# (eg calc/calc-loaddefs.el).
-LOADDEFS = $(lisp)/calendar/cal-loaddefs.el \
- $(lisp)/calendar/diary-loaddefs.el \
- $(lisp)/calendar/hol-loaddefs.el \
- $(lisp)/mh-e/mh-loaddefs.el \
- $(lisp)/net/tramp-loaddefs.el
-
# All generated autoload files.
loaddefs = $(shell find ${srcdir} -name '*loaddefs.el' ! -name '.*')
# Elisp files auto-generated.
@@ -76,14 +67,20 @@ AUTOGENEL = ${loaddefs} ${srcdir}/cus-load.el ${srcdir}/finder-inf.el \
# Set load-prefer-newer for the benefit of the non-bootstrappers.
BYTE_COMPILE_FLAGS = \
- --eval '(setq load-prefer-newer t)' $(BYTE_COMPILE_EXTRA_FLAGS)
+ --eval "(setq load-prefer-newer t byte-compile-warnings 'all)" \
+ $(BYTE_COMPILE_EXTRA_FLAGS)
+# ... but we must prefer .elc files for those in the early bootstrap.
+# A larger `max-specpdl-size' is needed for emacs-lisp/comp.el.
+compile-first: BYTE_COMPILE_FLAGS = \
+ --eval '(setq max-specpdl-size 5000)' $(BYTE_COMPILE_EXTRA_FLAGS)
# Files to compile before others during a bootstrap. This is done to
# speed up the bootstrap process. They're ordered by size, so we use
-# the slowest-compiler on the smallest file and move to larger files as the
-# compiler gets faster. 'autoload.elc' comes last because it is not used by
-# the compiler (so its compilation does not speed up subsequent compilations),
-# it's only placed here so as to speed up generation of the loaddefs.el file.
+# the slowest-compiler on the smallest file and move to larger files
+# as the compiler gets faster. 'loaddefs-gen.elc'/'radix-tree.el'
+# comes last because they're not used by the compiler (so its
+# compilation does not speed up subsequent compilations), it's only
+# placed here so as to speed up generation of the loaddefs.el files.
COMPILE_FIRST = \
$(lisp)/emacs-lisp/macroexp.elc \
@@ -94,18 +91,24 @@ ifeq ($(HAVE_NATIVE_COMP),yes)
COMPILE_FIRST += $(lisp)/emacs-lisp/comp.elc
COMPILE_FIRST += $(lisp)/emacs-lisp/comp-cstr.elc
endif
-COMPILE_FIRST += $(lisp)/emacs-lisp/autoload.elc
+COMPILE_FIRST += $(lisp)/emacs-lisp/loaddefs-gen.elc
+COMPILE_FIRST += $(lisp)/emacs-lisp/radix-tree.elc
# Files to compile early in compile-main. Works around bug#25556.
+# Also compile the ja-dic file used to convert the Japanese dictionary
+# to speed things up. The org files are used to convert org files to
+# texi files.
MAIN_FIRST = ./emacs-lisp/eieio.el ./emacs-lisp/eieio-base.el \
- ./cedet/semantic/db.el ./emacs-lisp/cconv.el
+ ./cedet/semantic/db.el ./emacs-lisp/cconv.el \
+ ./international/ja-dic-cnv.el \
+ ./org/ox.el ./org/ox-texinfo.el ./org/org-macro.el ./org/org-element.el \
+ ./org/oc.el ./org/ol.el ./emacs-lisp/cl-lib.el
# Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH
# The actual Emacs command run in the targets below.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems.
-emacs = EMACSLOADPATH= '$(EMACS)' $(EMACSOPT)
+emacs = '$(EMACS)' $(EMACSOPT)
## Subdirectories, relative to builddir.
SUBDIRS = $(sort $(shell find ${srcdir} -type d -print))
@@ -122,10 +125,12 @@ SUBDIRS_SUBDIRS = $(filter-out ${srcdir}/cedet% ${srcdir}/leim%,${SUBDIRS})
# cus-load and finder-inf are not explicitly requested by anything, so
# we add them here to make sure they get built.
-all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el
+all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el generate-ja-dic \
+ org-manuals
PHONY_EXTRAS =
-.PHONY: all custom-deps finder-data autoloads update-subdirs $(PHONY_EXTRAS)
+.PHONY: all custom-deps finder-data autoloads update-subdirs $(PHONY_EXTRAS) \
+ generate-ja-dic org-manuals
# custom-deps and finder-data both used to scan _all_ the *.el files.
# This could lead to problems in parallel builds if automatically
@@ -156,6 +161,14 @@ $(lisp)/finder-inf.el:
--eval '(setq generated-finder-keywords-file (unmsys--file-name "$(srcdir)/finder-inf.el"))' \
-f finder-compile-keywords-make-dist ${SUBDIRS_FINDER}
+# This is the OKURO-NASI compilation trigger.
+generate-ja-dic: main-first
+ $(AM_V_at)$(MAKE) -C ../leim generate-ja-dic EMACS="$(EMACS)"
+ $(AM_V_at)$(MAKE) compile-targets TARGETS="./leim/ja-dic/ja-dic.elc"
+
+org-manuals: main-first
+ $(AM_V_at)$(MAKE) -C ../doc/misc org.texi modus-themes.texi
+
## Comments on loaddefs generation:
# loaddefs depends on gen-lisp for two reasons:
@@ -164,6 +177,9 @@ $(lisp)/finder-inf.el:
# gets created before the final emacs is dumped. Having leim
# dependencies in ../src as well would create a parallel race condition.
#
+# FIXME: 2) is no longer correct, so perhaps we could add unidata to
+# gen-lisp now?
+#
# 2) Files that are marked no-update-autoloads still get recorded in loaddefs.
# So those files should be generated before we make autoloads, if we
# don't want a successive make autoloads to change the output file.
@@ -183,19 +199,13 @@ $(lisp)/finder-inf.el:
# We make $(lisp)/loaddefs.el a dependency of .PHONY to cause Make to
# ignore its time stamp. That's because the real dependencies of
# loaddefs.el aren't known to Make, they are implemented in
-# batch-update-autoloads, which only updates the autoloads whose
-# sources have changed.
-
-# Use expand-file-name rather than $abs_scrdir so that Emacs does not
-# get confused when it compares file-names for equality.
+# loaddefs-generate--emacs-batch.
autoloads .PHONY: $(lisp)/loaddefs.el
-$(lisp)/loaddefs.el: gen-lisp $(LOADDEFS)
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval '(setq autoload-ensure-writable t)' \
- --eval '(setq autoload-builtin-package-versions t)' \
- --eval '(setq generated-autoload-file (expand-file-name (unmsys--file-name "$@")))' \
- -f batch-update-autoloads ${SUBDIRS_ALMOST}
+$(lisp)/loaddefs.el: gen-lisp $(LOADDEFS) $(lisp)/emacs-lisp/loaddefs-gen.elc
+ $(AM_V_GEN)$(emacs) \
+ -l $(lisp)/emacs-lisp/loaddefs-gen.elc \
+ -f loaddefs-generate--emacs-batch ${SUBDIRS_ALMOST}
# autoloads only runs when loaddefs.el is nonexistent, although it
# generates a number of different files. Provide a force option to enable
@@ -304,9 +314,23 @@ endif
# An old-fashioned suffix rule, which, according to the GNU Make manual,
# cannot have prerequisites.
ifeq ($(HAVE_NATIVE_COMP),yes)
+ifeq ($(ANCIENT),yes)
+# The first compilation of compile-first, using an interpreted compiler:
+# The resulting .elc files get given a date of 1971-01-01 so that their
+# date stamp is earlier than the source files, causing these to be compiled
+# into native code at the second recursive invocation of this $(MAKE),
+# using these .elc's. This is faster than just compiling the native code
+# directly using the interpreted compile-first files. (Note: 1970-01-01
+# fails on some systems.)
+.el.elc:
+ $(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) \
+ -l comp -f batch-byte-compile $<
+ touch -t 197101010000 $@
+else
.el.elc:
$(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) \
-l comp -f batch-byte+native-compile $<
+endif
else
.el.elc:
$(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) -f batch-byte-compile $<
@@ -439,57 +463,6 @@ compile-one-process: $(LOADDEFS) compile-first
$(emacs) $(BYTE_COMPILE_FLAGS) \
--eval "(batch-byte-recompile-directory 0)" $(lisp)
-# Update MH-E internal autoloads. These are not to be confused with
-# the autoloads for the MH-E entry points, which are already in loaddefs.el.
-MH_E_DIR = $(lisp)/mh-e
-MH_E_SRC = $(sort $(wildcard ${MH_E_DIR}/mh*.el))
-MH_E_SRC := $(filter-out ${MH_E_DIR}/mh-loaddefs.el,${MH_E_SRC})
-
-.PHONY: mh-autoloads
-mh-autoloads: $(MH_E_DIR)/mh-loaddefs.el
-$(MH_E_DIR)/mh-loaddefs.el: $(MH_E_SRC)
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval "(setq generate-autoload-cookie \";;;###mh-autoload\")" \
- --eval "(setq generated-autoload-file (expand-file-name (unmsys--file-name \"$@\")))" \
- -f batch-update-autoloads $(MH_E_DIR)
-
-# Update TRAMP internal autoloads. Maybe we could move tramp*.el into
-# an own subdirectory. OTOH, it does not hurt to keep them in
-# lisp/net.
-TRAMP_DIR = $(lisp)/net
-TRAMP_SRC = $(sort $(wildcard ${TRAMP_DIR}/tramp*.el))
-TRAMP_SRC := $(filter-out ${TRAMP_DIR}/tramp-loaddefs.el,${TRAMP_SRC})
-
-$(TRAMP_DIR)/tramp-loaddefs.el: $(TRAMP_SRC)
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval "(setq generate-autoload-cookie \";;;###tramp-autoload\")" \
- --eval "(setq generated-autoload-file (expand-file-name (unmsys--file-name \"$@\")))" \
- -f batch-update-autoloads $(TRAMP_DIR)
-
-CAL_DIR = $(lisp)/calendar
-## Those files that may contain internal calendar autoload cookies.
-CAL_SRC = $(addprefix ${CAL_DIR}/,diary-lib.el holidays.el lunar.el solar.el)
-CAL_SRC := $(sort ${CAL_SRC} $(wildcard ${CAL_DIR}/cal-*.el))
-CAL_SRC := $(filter-out ${CAL_DIR}/cal-loaddefs.el,${CAL_SRC})
-
-$(CAL_DIR)/cal-loaddefs.el: $(CAL_SRC)
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval "(setq generate-autoload-cookie \";;;###cal-autoload\")" \
- --eval "(setq generated-autoload-file (expand-file-name (unmsys--file-name \"$@\")))" \
- -f batch-update-autoloads $(CAL_DIR)
-
-$(CAL_DIR)/diary-loaddefs.el: $(CAL_SRC) $(CAL_DIR)/cal-loaddefs.el
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval "(setq generate-autoload-cookie \";;;###diary-autoload\")" \
- --eval "(setq generated-autoload-file (expand-file-name (unmsys--file-name \"$@\")))" \
- -f batch-update-autoloads $(CAL_DIR)
-
-$(CAL_DIR)/hol-loaddefs.el: $(CAL_SRC) $(CAL_DIR)/diary-loaddefs.el
- $(AM_V_GEN)$(emacs) -l autoload \
- --eval "(setq generate-autoload-cookie \";;;###holiday-autoload\")" \
- --eval "(setq generated-autoload-file (expand-file-name (unmsys--file-name \"$@\")))" \
- -f batch-update-autoloads $(CAL_DIR)
-
.PHONY: bootstrap-clean distclean maintainer-clean
bootstrap-clean:
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index 448e1842558..21aa3311d6f 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -42,12 +42,12 @@
(defcustom abbrev-file-name
(locate-user-emacs-file "abbrev_defs" ".abbrev_defs")
- "Default name of file from which to read abbrevs."
+ "Default name of file from which to read and where to save abbrevs."
:initialize 'custom-initialize-delay
:type 'file)
(defcustom only-global-abbrevs nil
- "Non-nil means user plans to use global abbrevs only.
+ "Non-nil means user plans to use only global abbrevs.
This makes the commands that normally define mode-specific abbrevs
define global abbrevs instead."
:type 'boolean
@@ -59,7 +59,8 @@ define global abbrevs instead."
In Abbrev mode, inserting an abbreviation causes it to expand and
be replaced by its expansion."
- ;; It's defined in C, this stops the d-m-m macro defining it again.
+ ;; It's defined in C, this stops the 'define-minor-mode' macro from
+ ;; defining it again.
:variable abbrev-mode)
(put 'abbrev-mode 'safe-local-variable 'booleanp)
@@ -67,13 +68,11 @@ be replaced by its expansion."
(define-obsolete-variable-alias 'edit-abbrevs-map
'edit-abbrevs-mode-map "24.4")
-(defvar edit-abbrevs-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-x\C-s" 'abbrev-edit-save-buffer)
- (define-key map "\C-x\C-w" 'abbrev-edit-save-to-file)
- (define-key map "\C-c\C-c" 'edit-abbrevs-redefine)
- map)
- "Keymap used in `edit-abbrevs'.")
+(defvar-keymap edit-abbrevs-mode-map
+ :doc "Keymap used in `edit-abbrevs'."
+ "C-x C-s" #'abbrev-edit-save-buffer
+ "C-x C-w" #'abbrev-edit-save-to-file
+ "C-c C-c" #'edit-abbrevs-redefine)
(defun kill-all-abbrevs ()
"Undefine all defined abbrevs."
@@ -83,7 +82,8 @@ be replaced by its expansion."
(defun copy-abbrev-table (table)
"Make a new abbrev-table with the same abbrevs as TABLE.
-Does not copy property lists."
+This function does not copy property lists of the abbrevs.
+See `define-abbrev' for the documentation of abbrev properties."
(let ((new-table (make-abbrev-table)))
(obarray-map
(lambda (symbol)
@@ -95,8 +95,8 @@ Does not copy property lists."
new-table))
(defun insert-abbrevs ()
- "Insert after point a description of all defined abbrevs.
-Mark is set after the inserted text."
+ "Insert the description of all defined abbrevs after point.
+Set mark after the inserted text."
(interactive)
(push-mark
(save-excursion
@@ -105,15 +105,15 @@ Mark is set after the inserted text."
(point))))
(defun list-abbrevs (&optional local)
- "Display a list of defined abbrevs.
-If LOCAL is non-nil, interactively when invoked with a
-prefix arg, display only local, i.e. mode-specific, abbrevs.
-Otherwise display all abbrevs."
+ "Display a list of the defined abbrevs.
+If LOCAL is non-nil (interactively, when invoked with a
+prefix arg), display only local, i.e. mode-specific, abbrevs.
+Otherwise display all the abbrevs."
(interactive "P")
(display-buffer (prepare-abbrev-list-buffer local)))
(defun abbrev-table-name (table)
- "Value is the name of abbrev table TABLE."
+ "Return the name of the specified abbrev TABLE."
(let ((tables abbrev-table-name-list)
found)
(while (and (not found) tables)
@@ -137,27 +137,33 @@ Otherwise display all abbrevs."
(dolist (table (nreverse empty-tables))
(insert-abbrev-table-description table t)))
;; Note: `list-abbrevs' can display only local abbrevs, in
- ;; which case editing could lose abbrevs of other tables. Thus
- ;; enter `edit-abbrevs-mode' only if LOCAL is nil.
+ ;; which case editing could lose abbrevs of other tables.
+ ;; Thus enter `edit-abbrevs-mode' only if LOCAL is nil.
(edit-abbrevs-mode))
(goto-char (point-min))
(set-buffer-modified-p nil)
(current-buffer))))
(defun edit-abbrevs ()
- "Alter abbrev definitions by editing a list of them.
-Selects a buffer containing a list of abbrev definitions with
-point located in the abbrev table for the current buffer, and
-turns on `edit-abbrevs-mode' in that buffer.
-You can edit them and type \\<edit-abbrevs-map>\\[edit-abbrevs-redefine] to redefine abbrevs
+ "Alter abbrev definitions by editing the list of abbrevs.
+This selects a buffer containing the list of abbrev definitions
+with point located in the abbrev table for the current buffer, and
+turns on `edit-abbrevs-mode' in the buffer with the list of abbrevs.
+
+You can edit the abbrevs and type \\<edit-abbrevs-mode-map>\\[edit-abbrevs-redefine] \
+to redefine abbrevs
according to your editing.
+
The abbrevs editing buffer contains a header line for each
abbrev table, which is the abbrev table name in parentheses.
-This is followed by one line per abbrev in that table:
-NAME USECOUNT EXPANSION HOOK
+
+The header line is followed by one line per abbrev in that table:
+
+ NAME USECOUNT EXPANSION HOOK
+
where NAME and EXPANSION are strings with quotes,
USECOUNT is an integer, and HOOK is any valid function
-or may be omitted (it is usually omitted)."
+that may be omitted (it is usually omitted)."
(interactive)
(let ((table-name (abbrev-table-name local-abbrev-table)))
(switch-to-buffer (prepare-abbrev-list-buffer))
@@ -168,7 +174,7 @@ or may be omitted (it is usually omitted)."
(defun edit-abbrevs-redefine ()
"Redefine abbrevs according to current buffer contents."
- (interactive)
+ (interactive nil edit-abbrevs-mode)
(save-restriction
(widen)
(define-abbrevs t)
@@ -178,8 +184,9 @@ or may be omitted (it is usually omitted)."
"Define abbrevs according to current visible buffer contents.
See documentation of `edit-abbrevs' for info on the format of the
text you must have in the buffer.
-With argument, eliminate all abbrev definitions except
-the ones defined from the buffer now."
+If ARG is non-nil (interactively, when invoked with a prefix
+argument), eliminate all abbrev definitions except the ones
+defined by the current buffer contents."
(interactive "P")
(if arg (kill-all-abbrevs))
(save-excursion
@@ -210,7 +217,8 @@ the ones defined from the buffer now."
"Read abbrev definitions from file written with `write-abbrev-file'.
Optional argument FILE is the name of the file to read;
it defaults to the value of `abbrev-file-name'.
-Optional second argument QUIETLY non-nil means don't display a message."
+Optional second argument QUIETLY non-nil means don't display a message
+about loading the abbrevs."
(interactive
(list
(read-file-name (format-prompt "Read abbrev file" abbrev-file-name)
@@ -219,22 +227,22 @@ Optional second argument QUIETLY non-nil means don't display a message."
(setq abbrevs-changed nil))
(defun quietly-read-abbrev-file (&optional file)
- "Read abbrev definitions from file written with `write-abbrev-file'.
+ "Quietly read abbrev definitions from file written with `write-abbrev-file'.
Optional argument FILE is the name of the file to read;
it defaults to the value of `abbrev-file-name'.
-Does not display any message."
+Do not display any messages about loading the abbrevs."
;(interactive "fRead abbrev file: ")
(read-abbrev-file file t))
(defun write-abbrev-file (&optional file verbose)
"Write all user-level abbrev definitions to a file of Lisp code.
This does not include system abbrevs; it includes only the abbrev tables
-listed in listed in `abbrev-table-name-list'.
+listed in `abbrev-table-name-list'.
The file written can be loaded in another session to define the same abbrevs.
-The argument FILE is the file name to write. If omitted or nil, the file
-specified in `abbrev-file-name' is used.
-If VERBOSE is non-nil, display a message indicating where abbrevs
-have been saved."
+The argument FILE is the file name to write. If omitted or nil, it defaults
+to the value of `abbrev-file-name'.
+If VERBOSE is non-nil, display a message indicating the file where the
+abbrevs have been saved."
(interactive
(list
(read-file-name "Write abbrev file: "
@@ -247,10 +255,10 @@ have been saved."
(dolist (table
;; We sort the table in order to ease the automatic
;; merging of different versions of the user's abbrevs
- ;; file. This is useful, for example, for when the
+ ;; file. This is useful, for example, when the
;; user keeps their home directory in a revision
- ;; control system, and is therefore keeping multiple
- ;; slightly-differing copies loosely synchronized.
+ ;; control system, and therefore keeps multiple
+ ;; slightly-differing loosely synchronized copies.
(sort (copy-sequence abbrev-table-name-list)
(lambda (s1 s2)
(string< (symbol-name s1)
@@ -264,33 +272,35 @@ have been saved."
(write-region nil nil file nil (and (not verbose) 0)))))
(defun abbrev-edit-save-to-file (file)
- "Save all user-level abbrev definitions in current buffer to FILE."
+ "Save to FILE all the user-level abbrev definitions in current buffer."
(interactive
(list (read-file-name "Save abbrevs to file: "
(file-name-directory
(expand-file-name abbrev-file-name))
- abbrev-file-name)))
+ abbrev-file-name))
+ edit-abbrevs-mode)
(edit-abbrevs-redefine)
(write-abbrev-file file t))
(defun abbrev-edit-save-buffer ()
- "Save all user-level abbrev definitions in current buffer.
+ "Save all the user-level abbrev definitions in current buffer.
The saved abbrevs are written to the file specified by
`abbrev-file-name'."
- (interactive)
+ (interactive nil edit-abbrevs-mode)
(abbrev-edit-save-to-file abbrev-file-name))
(defun add-mode-abbrev (arg)
- "Define mode-specific abbrev for last word(s) before point.
-Argument is how many words before point form the expansion;
-or zero means the region is the expansion.
-A negative argument means to undefine the specified abbrev.
-Reads the abbreviation in the minibuffer.
+ "Define a mode-specific abbrev whose expansion is the last word before point.
+Prefix argument ARG says how many words before point to use for the expansion;
+zero means the entire region is the expansion.
+A negative ARG means to undefine the specified abbrev.
+
+This command reads the abbreviation from the minibuffer.
See also `inverse-add-mode-abbrev', which performs the opposite task:
-if the abbrev text is already in the buffer, use this command to
-define an abbrev by specifying the expansion in the minibuffer.
+if the abbreviation is already in the buffer, use that command to define
+a mode-specific abbrev by specifying its expansion in the minibuffer.
Don't use this function in a Lisp program; use `define-abbrev' instead."
(interactive "p")
@@ -302,15 +312,16 @@ Don't use this function in a Lisp program; use `define-abbrev' instead."
"Mode" arg))
(defun add-global-abbrev (arg)
- "Define global (all modes) abbrev for last word(s) before point.
-The prefix argument specifies the number of words before point that form the
-expansion; or zero means the region is the expansion.
-A negative argument means to undefine the specified abbrev.
-This command uses the minibuffer to read the abbreviation.
+ "Define a global (all modes) abbrev whose expansion is last word before point.
+Prefix argument ARG says how many words before point to use for the expansion;
+zero means the entire region is the expansion.
+A negative ARG means to undefine the specified abbrev.
+
+This command reads the abbreviation from the minibuffer.
See also `inverse-add-global-abbrev', which performs the opposite task:
-if the abbrev text is already in the buffer, use this command to
-define an abbrev by specifying the expansion in the minibuffer.
+if the abbreviation is already in the buffer, use that command to define
+a global abbrev by specifying its expansion in the minibuffer.
Don't use this function in a Lisp program; use `define-abbrev' instead."
(interactive "p")
@@ -324,25 +335,30 @@ Don't use this function in a Lisp program; use `define-abbrev' instead."
(save-excursion (forward-word (- arg)) (point))))))
name)
(setq name
- (read-string (format (if exp "%s abbrev for \"%s\": "
+ (read-string (format (if exp "%s abbrev that expands into \"%s\": "
"Undefine %s abbrev: ")
type exp)))
(set-text-properties 0 (length name) nil name)
(if (or (null exp)
(not (abbrev-expansion name table))
- (y-or-n-p (format "%s expands to \"%s\"; redefine? "
+ (y-or-n-p (format "%s expands into \"%s\"; redefine? "
name (abbrev-expansion name table))))
(define-abbrev table (downcase name) exp))))
(defun inverse-add-mode-abbrev (n)
- "Define last word before point as a mode-specific abbrev.
-With prefix argument N, defines the Nth word before point.
-This command uses the minibuffer to read the expansion.
-Expands the abbreviation after defining it.
+ "Define the word before point as a mode-specific abbreviation.
+With prefix argument N, define the Nth word before point as the
+abbreviation. Negative N means use the Nth word after point.
+
+If `only-global-abbrevs' is non-nil, this command defines a
+global (mode-independent) abbrev instead of a mode-specific one.
+
+This command reads the expansion from the minibuffer, defines the
+abbrev, and then expands the abbreviation in the current buffer.
See also `add-mode-abbrev', which performs the opposite task:
-if the expansion is already in the buffer, use this command
-to define an abbrev by specifying the abbrev in the minibuffer."
+if the expansion is already in the buffer, use that command
+to define an abbrev by specifying the abbreviation in the minibuffer."
(interactive "p")
(inverse-add-abbrev
(if only-global-abbrevs
@@ -352,14 +368,16 @@ to define an abbrev by specifying the abbrev in the minibuffer."
"Mode" n))
(defun inverse-add-global-abbrev (n)
- "Define last word before point as a global (mode-independent) abbrev.
-With prefix argument N, defines the Nth word before point.
-This command uses the minibuffer to read the expansion.
-Expands the abbreviation after defining it.
+ "Define the word before point as a global (mode-independent) abbreviation.
+With prefix argument N, define the Nth word before point as the
+abbreviation. Negative N means use the Nth word after point.
+
+This command reads the expansion from the minibuffer, defines the
+abbrev, and then expands the abbreviation in the current buffer.
See also `add-global-abbrev', which performs the opposite task:
-if the expansion is already in the buffer, use this command
-to define an abbrev by specifying the abbrev in the minibuffer."
+if the expansion is already in the buffer, use that command
+to define an abbrev by specifying the abbreviation in the minibuffer."
(interactive "p")
(inverse-add-abbrev global-abbrev-table "Global" n))
@@ -373,10 +391,10 @@ to define an abbrev by specifying the abbrev in the minibuffer."
(setq start (point)
name (buffer-substring-no-properties start end)))
- (setq exp (read-string (format "%s expansion for \"%s\": " type name)
+ (setq exp (read-string (format "Expansion for %s abbrev \"%s\": " type name)
nil nil nil t))
(when (or (not (abbrev-expansion name table))
- (y-or-n-p (format "%s expands to \"%s\"; redefine? "
+ (y-or-n-p (format "%s expands into \"%s\"; redefine? "
name (abbrev-expansion name table))))
(define-abbrev table (downcase name) exp)
(save-excursion
@@ -384,10 +402,11 @@ to define an abbrev by specifying the abbrev in the minibuffer."
(expand-abbrev)))))
(defun abbrev-prefix-mark (&optional arg)
- "Mark current point as the beginning of an abbrev.
-The abbrev to be expanded starts here rather than at beginning of
-word. This way, you can expand an abbrev with a prefix: insert
-the prefix, use this command, then insert the abbrev.
+ "Mark point as the beginning of an abbreviation.
+The abbrev to be expanded starts at point rather than at the
+beginning of a word. This way, you can expand an abbrev with
+a prefix: insert the prefix, use this command, then insert the
+abbrev.
This command inserts a hyphen after the prefix, and if the abbrev
is subsequently expanded, this hyphen will be removed.
@@ -402,8 +421,8 @@ argument."
(insert "-"))
(defun expand-region-abbrevs (start end &optional noquery)
- "For abbrev occurrence in the region, offer to expand it.
-The user is asked to type \\`y' or \\`n' for each occurrence.
+ "For each abbrev occurrence in the region, offer to expand it.
+Ask the user to type `y' or `n' for each occurrence.
A prefix argument means don't query; expand all abbrevs."
(interactive "r\nP")
(save-excursion
@@ -424,18 +443,19 @@ A prefix argument means don't query; expand all abbrevs."
;;; Abbrev properties.
(defun abbrev-table-get (table prop)
- "Get the PROP property of abbrev table TABLE."
+ "Get the property PROP of abbrev table TABLE."
(let ((sym (obarray-get table "")))
(if sym (get sym prop))))
(defun abbrev-table-put (table prop val)
- "Set the PROP property of abbrev table TABLE to VAL."
+ "Set the property PROP of abbrev table TABLE to VAL."
(let ((sym (obarray-put table "")))
(set sym nil) ; Make sure it won't be confused for an abbrev.
(put sym prop val)))
(defalias 'abbrev-get 'get
"Get the property PROP of abbrev ABBREV
+See `define-abbrev' for the effect of some special properties.
\(fn ABBREV PROP)")
@@ -470,7 +490,8 @@ PROPS is a list of properties."
(defun abbrev-table-p (object)
"Return non-nil if OBJECT is an abbrev table."
(and (obarrayp object)
- (numberp (abbrev-table-get object :abbrev-table-modiff))))
+ (numberp (ignore-error 'wrong-type-argument
+ (abbrev-table-get object :abbrev-table-modiff)))))
(defun abbrev-table-empty-p (object &optional ignore-system)
"Return nil if there are no abbrev symbols in OBJECT.
@@ -494,7 +515,8 @@ for any particular abbrev defined in both.")
(defvar abbrev-minor-mode-table-alist nil
"Alist of abbrev tables to use for minor modes.
Each element looks like (VARIABLE . ABBREV-TABLE);
-ABBREV-TABLE is active whenever VARIABLE's value is non-nil.
+ABBREV-TABLE is active whenever VARIABLE's value is non-nil;
+VARIABLE is supposed to be a minor-mode variable.
ABBREV-TABLE can also be a list of abbrev tables.")
(defvar fundamental-mode-abbrev-table
@@ -505,11 +527,11 @@ ABBREV-TABLE can also be a list of abbrev tables.")
"The abbrev table of mode-specific abbrevs for Fundamental Mode.")
(defvar abbrevs-changed nil
- "Set non-nil by defining or altering any word abbrevs.
+ "Non-nil if any word abbrevs were defined or altered.
This causes `save-some-buffers' to offer to save the abbrevs.")
(defcustom abbrev-all-caps nil
- "Non-nil means expand multi-word abbrevs all caps if abbrev was so."
+ "Non-nil means expand multi-word abbrevs in all caps if the abbrev was so."
:type 'boolean
:group 'abbrev-mode)
@@ -526,17 +548,17 @@ Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.")
"The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'.")
(defvar last-abbrev-text nil
- "The exact text of the last abbrev expanded.
+ "The exact text of the last abbrev that was expanded.
It is nil if the abbrev has already been unexpanded.")
(defvar last-abbrev-location 0
- "The location of the start of the last abbrev expanded.")
+ "The location of the start of the last abbrev that was expanded.")
;; (defvar-local local-abbrev-table fundamental-mode-abbrev-table
;; "Local (mode-specific) abbrev table of current buffer.")
(defun clear-abbrev-table (table)
- "Undefine all abbrevs in abbrev table TABLE, leaving it empty."
+ "Undefine all abbrevs in abbrev table TABLE, leaving TABLE empty."
(setq abbrevs-changed t)
(let* ((sym (obarray-get table "")))
(dotimes (i (length table))
@@ -551,9 +573,9 @@ It is nil if the abbrev has already been unexpanded.")
;; For backward compatibility, always return nil.
nil)
-(defun define-abbrev (table name expansion &optional hook &rest props)
- "Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
-NAME must be a string, and should be lower-case.
+(defun define-abbrev (table abbrev expansion &optional hook &rest props)
+ "Define ABBREV in TABLE, to expand into EXPANSION and optionally call HOOK.
+ABBREV must be a string, and should be lower-case.
EXPANSION should usually be a string.
To undefine an abbrev, define it with EXPANSION = nil.
If HOOK is non-nil, it should be a function of no arguments;
@@ -577,8 +599,8 @@ PROPS is a property list. The following properties are special:
overwrite a non-system abbreviation of the same name.
- `:case-fixed': non-nil means that abbreviations are looked up without
case-folding, and the expansion is not capitalized/upcased.
-- `:enable-function': a function of no argument which returns non-nil if the
- abbrev should be used for a particular call of `expand-abbrev'.
+- `:enable-function': a function of no arguments which returns non-nil
+ if the abbrev should be used for a particular call of `expand-abbrev'.
An obsolete but still supported calling form is:
@@ -593,7 +615,7 @@ An obsolete but still supported calling form is:
(setq props (plist-put props :abbrev-table-modiff
(abbrev-table-get table :abbrev-table-modiff)))
(let ((system-flag (plist-get props :system))
- (sym (obarray-put table name)))
+ (sym (obarray-put table abbrev)))
;; Don't override a prior user-defined abbrev with a system abbrev,
;; unless system-flag is `force'.
(unless (and (not (memq system-flag '(nil force)))
@@ -613,7 +635,7 @@ An obsolete but still supported calling form is:
(if (eq 'force system-flag) (plist-put props :system t) props))
(abbrev-table-put table :abbrev-table-modiff
(1+ (abbrev-table-get table :abbrev-table-modiff))))
- name))
+ abbrev))
(defun abbrev--check-chars (abbrev global)
"Check if the characters in ABBREV have word syntax in either the
@@ -633,7 +655,7 @@ current (if global is nil) or standard syntax table."
(if global "in the standard syntax" "in this mode"))))))
(defun define-global-abbrev (abbrev expansion)
- "Define ABBREV as a global abbreviation for EXPANSION.
+ "Define ABBREV as a global abbreviation that expands into EXPANSION.
The characters in ABBREV must all be word constituents in the standard
syntax table."
(interactive "sDefine global abbrev: \nsExpansion for %s: ")
@@ -641,7 +663,7 @@ syntax table."
(define-abbrev global-abbrev-table (downcase abbrev) expansion))
(defun define-mode-abbrev (abbrev expansion)
- "Define ABBREV as a mode-specific abbreviation for EXPANSION.
+ "Define ABBREV as a mode-specific abbreviation that expands into EXPANSION.
The characters in ABBREV must all be word-constituents in the current mode."
(interactive "sDefine mode abbrev: \nsExpansion for %s: ")
(unless local-abbrev-table
@@ -650,8 +672,8 @@ The characters in ABBREV must all be word-constituents in the current mode."
(define-abbrev local-abbrev-table (downcase abbrev) expansion))
(defun abbrev--active-tables (&optional tables)
- "Return the list of abbrev tables currently active.
-TABLES if non-nil overrides the usual rules. It can hold
+ "Return the list of abbrev tables that are currently active.
+TABLES, if non-nil, overrides the usual rules. It can hold
either a single abbrev table or a list of abbrev tables."
;; We could just remove the `tables' arg and let callers use
;; (or table (abbrev--active-tables)) but then they'd have to be careful
@@ -677,7 +699,7 @@ either a single abbrev table or a list of abbrev tables."
"Return the symbol representing abbrev named ABBREV in TABLE.
This symbol's name is ABBREV, but it is not the canonical symbol of that name;
it is interned in the abbrev-table TABLE rather than the normal obarray.
-The value is nil if that abbrev is not defined."
+The value is nil if such an abbrev is not defined."
(let* ((case-fold (not (abbrev-table-get table :case-fixed)))
;; In case the table doesn't set :case-fixed but some of the
;; abbrevs do, we have to be careful.
@@ -694,11 +716,11 @@ The value is nil if that abbrev is not defined."
sym)))
(defun abbrev-symbol (abbrev &optional table)
- "Return the symbol representing abbrev named ABBREV.
+ "Return the symbol representing the abbrev named ABBREV in TABLE.
This symbol's name is ABBREV, but it is not the canonical symbol of that name;
it is interned in an abbrev-table rather than the normal obarray.
-The value is nil if that abbrev is not defined.
-Optional second arg TABLE is abbrev table to look it up in.
+The value is nil if such an abbrev is not defined.
+Optional second arg TABLE is the abbrev table to look it up in.
The default is to try buffer's mode-specific abbrev table, then global table."
(let ((tables (abbrev--active-tables table))
sym)
@@ -711,7 +733,7 @@ The default is to try buffer's mode-specific abbrev table, then global table."
(defun abbrev-expansion (abbrev &optional table)
"Return the string that ABBREV expands into in the current buffer.
-Optionally specify an abbrev table as second arg;
+Optionally specify an abbrev TABLE as second arg;
then ABBREV is looked up in that table only."
(symbol-value (abbrev-symbol abbrev table)))
@@ -775,9 +797,9 @@ then ABBREV is looked up in that table only."
(defun abbrev-insert (abbrev &optional name wordstart wordend)
"Insert abbrev ABBREV at point.
If non-nil, NAME is the name by which this abbrev was found.
-If non-nil, WORDSTART is the place where to insert the abbrev.
-If WORDEND is non-nil, the abbrev replaces the previous text between
-WORDSTART and WORDEND.
+If non-nil, WORDSTART is the buffer position where to insert the abbrev.
+If WORDEND is non-nil, it is a buffer position; the abbrev replaces the
+previous text between WORDSTART and WORDEND.
Return ABBREV if the expansion should be considered as having taken place.
The return value can be influenced by a `no-self-insert' property;
see `define-abbrev' for details."
@@ -842,7 +864,8 @@ see `define-abbrev' for details."
(defvar abbrev-expand-function #'abbrev--default-expand
"Function that `expand-abbrev' uses to perform abbrev expansion.
-Takes no argument and should return the abbrev symbol if expansion took place.")
+Takes no arguments, and should return the abbrev symbol if expansion
+took place.")
(defcustom abbrev-suggest nil
"Non-nil means suggest using abbrevs to save typing.
@@ -862,8 +885,8 @@ longer than the abbrev, the benefit of informing the user is not
significant. If you always want to be informed about existing
abbrevs for the text you type, set this value to zero or less.
This setting only applies if `abbrev-suggest' is non-nil."
- :type 'number
- :version "28.1")
+ :type 'natnum
+ :version "28.1")
(defun abbrev--suggest-get-active-tables-including-parents ()
"Return a list of all active abbrev tables, including parent tables."
@@ -901,15 +924,17 @@ Expansion is a string of one or more words."
(defun abbrev--suggest-above-threshold (expansion)
"Return non-nil if the abbrev in EXPANSION provides significant savings.
-A significant saving, here, is the difference in length between
-the abbrev and the abbrev expansion. EXPANSION is a cons cell
-where the car is the expansion and the cdr is the abbrev."
+A significant saving, here, means the difference in length between
+the abbrev and its expansion is not below the threshold specified
+by the value of `abbrev-suggest-hint-threshold'.
+EXPANSION is a cons cell where the car is the expansion and the cdr is
+the abbrev."
(>= (- (length (car expansion))
(length (cdr expansion)))
abbrev-suggest-hint-threshold))
(defvar abbrev--suggest-saved-recommendations nil
- "Keeps a list of expansions that have abbrevs defined.
+ "Keeps the list of expansions that have abbrevs defined.
The user can show this list by calling
`abbrev-suggest-show-report'.")
@@ -925,7 +950,7 @@ EXPANSION is a cons cell where the `car' is the expansion and the
(push expansion abbrev--suggest-saved-recommendations))
(defun abbrev--suggest-shortest-abbrev (new current)
- "Return the shortest abbrev of NEW and CURRENT.
+ "Return the shortest of the two abbrevs given by NEW and CURRENT.
NEW and CURRENT are cons cells where the `car' is the expansion
and the `cdr' is the abbrev."
(if (not current)
@@ -954,8 +979,8 @@ informed about the existing abbrev."
(defun abbrev--suggest-get-totals ()
"Return a list of all expansions and how many times they were used.
-Each expansion is a cons cell where the `car' is the expansion
-and the `cdr' is the number of times the expansion has been
+Each expansion in the returned list is a cons cell where the `car' is the
+expansion text and the `cdr' is the number of times the expansion has been
typed."
(let (total cell)
(dolist (expansion abbrev--suggest-saved-recommendations)
@@ -1083,11 +1108,11 @@ Presumes that `standard-output' points to `current-buffer'."
(defun insert-abbrev-table-description (name &optional readable)
"Insert before point a full description of abbrev table named NAME.
NAME is a symbol whose value is an abbrev table.
-If optional 2nd arg READABLE is non-nil, a human-readable description
-is inserted.
+If optional 2nd arg READABLE is non-nil, insert a human-readable
+description.
-If READABLE is nil, an expression is inserted. The expression is
-a call to `define-abbrev-table' that when evaluated will define
+If READABLE is nil, insert an expression. The expression is
+a call to `define-abbrev-table' that, when evaluated, will define
the abbrev table NAME exactly as it is currently defined.
Abbrevs marked as \"system abbrevs\" are ignored."
(let ((symbols (abbrev--table-symbols name readable)))
@@ -1134,10 +1159,10 @@ Properties with special meaning:
case-folding, and the expansion is not capitalized/upcased.
- `:regexp' is a regular expression that specifies how to extract the
name of the abbrev before point. The submatch 1 is treated
- as the potential name of an abbrev. If :regexp is nil, the default
+ as the potential name of an abbrev. If `:regexp' is nil, the default
behavior uses `backward-word' and `forward-word' to extract the name
- of the abbrev, which can therefore only be a single word.
-- `:enable-function' can be set to a function of no argument which returns
+ of the abbrev, which can therefore by default only be a single word.
+- `:enable-function' can be set to a function of no arguments which returns
non-nil if and only if the abbrevs in this table should be used for this
instance of `expand-abbrev'."
(declare (doc-string 3) (indent defun))
@@ -1166,7 +1191,7 @@ Properties with special meaning:
(defun abbrev-table-menu (table &optional prompt sortfun)
"Return a menu that shows all abbrevs in TABLE.
-Selecting an entry runs `abbrev-insert'.
+Selecting an entry runs `abbrev-insert' for that entry's abbrev.
PROMPT is the prompt to use for the keymap.
SORTFUN is passed to `sort' to change the default ordering."
(unless sortfun (setq sortfun 'string-lessp))
@@ -1188,7 +1213,30 @@ SORTFUN is passed to `sort' to change the default ordering."
(define-derived-mode edit-abbrevs-mode fundamental-mode "Edit-Abbrevs"
"Major mode for editing the list of abbrev definitions.
This mode is for editing abbrevs in a buffer prepared by `edit-abbrevs',
-which see.")
+which see."
+ :interactive nil)
+
+(defun abbrev--possibly-save (query &optional arg)
+ ;; Query mode.
+ (if (eq query 'query)
+ (and save-abbrevs abbrevs-changed)
+ ;; Maybe save abbrevs, and record whether we either saved them or
+ ;; asked to.
+ (and save-abbrevs
+ abbrevs-changed
+ (progn
+ (if (or arg
+ (eq save-abbrevs 'silently)
+ (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
+ (progn
+ (write-abbrev-file nil)
+ nil)
+ ;; Don't keep bothering user if they say no.
+ (setq abbrevs-changed nil)
+ ;; Inhibit message in `save-some-buffers'.
+ t)))))
+
+(add-hook 'save-some-buffers-functions #'abbrev--possibly-save)
(provide 'abbrev)
diff --git a/lisp/align.el b/lisp/align.el
index 2279c659b43..1ee6bb0cacb 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -160,7 +160,8 @@ string), this heuristic is used to determine how far before and after
point we should search in looking for a region separator. Larger
values can mean slower performance in large files, although smaller
values may cause unexpected behavior at times."
- :type 'integer
+ :type '(choice (const :tag "Don't use heuristic when aligning a region" nil)
+ integer)
:group 'align)
(defcustom align-highlight-change-face 'highlight
@@ -176,7 +177,7 @@ values may cause unexpected behavior at times."
(defcustom align-large-region 10000
"If an integer, defines what constitutes a \"large\" region.
If nil, then no messages will ever be printed to the minibuffer."
- :type 'integer
+ :type '(choice (const :tag "Align a large region silently" nil) integer)
:group 'align)
(defcustom align-c++-modes '(c++-mode c-mode java-mode)
@@ -356,11 +357,11 @@ The possible settings for `align-region-separate' are:
(cons :tag "Valid"
(const :tag "(Return non-nil if rule is valid)"
valid)
- (function :value t))
+ (function :value always))
(cons :tag "Run If"
(const :tag "(Return non-nil if rule should run)"
run-if)
- (function :value t))
+ (function :value always))
(cons :tag "Column"
(const :tag "(Column to fix alignment at)" column)
(choice :value comment-column
@@ -545,15 +546,16 @@ The possible settings for `align-region-separate' are:
(regexp . "\\(\\s-*\\)\\\\\\\\")
(modes . align-tex-modes))
- ;; With a numeric prefix argument, or C-u, space delimited text
- ;; tables will be aligned.
+ ;; Align space delimited text as columns.
(text-column
(regexp . "\\(^\\|\\S-\\)\\([ \t]+\\)\\(\\S-\\|$\\)")
(group . 2)
(modes . align-text-modes)
(repeat . t)
(run-if . ,(lambda ()
- (not (eq '- current-prefix-arg)))))
+ (and (not (eq '- current-prefix-arg))
+ (not (apply #'provided-mode-derived-p
+ major-mode align-tex-modes))))))
;; With a negative prefix argument, lists of dollar figures will
;; be aligned.
@@ -839,8 +841,8 @@ Interactively, BEG and END are the mark/point of the current region.
Many modes define specific alignment rules, and some of these
rules in some modes react to the current prefix argument. For
-instance, in `text-mode', `M-x align' will align into columns
-based on space delimiters, while `C-u - M-x align' will align
+instance, in `text-mode', \\`M-x align' will align into columns
+based on space delimiters, while \\`C-u -' \\`M-x align' will align
into columns based on the \"$\" character. See the
`align-rules-list' variable definition for the specific rules.
diff --git a/lisp/allout.el b/lisp/allout.el
index 4624c236f5a..e07bac4ef99 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -26,7 +26,7 @@
;;; Commentary:
;; Allout outline minor mode provides extensive outline formatting and
-;; and manipulation beyond standard Emacs outline mode. Some features:
+;; manipulation beyond standard Emacs outline mode. Some features:
;;
;; - Classic outline-mode topic-oriented navigation and exposure adjustment
;; - Topic-oriented editing including coherent topic and subtopic
@@ -733,8 +733,6 @@ Set this var to the bullet you want to use for file cross-references."
(put 'allout-presentation-padding 'safe-local-variable #'integerp)
;;;_ = allout-flattened-numbering-abbreviation
-(define-obsolete-variable-alias 'allout-abbreviate-flattened-numbering
- 'allout-flattened-numbering-abbreviation "24.1")
(defcustom allout-flattened-numbering-abbreviation nil
"If non-nil, `allout-flatten-exposed-to-buffer' abbreviates topic
numbers to minimal amount with some context. Otherwise, entire
@@ -1350,11 +1348,6 @@ their settings before `allout-mode' was started."
;;;_ = allout-mode-hook
(defvar allout-mode-hook nil
"Hook run when allout mode starts.")
-;;;_ = allout-mode-deactivate-hook
-(define-obsolete-variable-alias 'allout-mode-deactivate-hook
- 'allout-mode-off-hook "24.1")
-(defvar allout-mode-deactivate-hook nil
- "Hook run when allout mode ends.")
;;;_ = allout-exposure-category
(defvar allout-exposure-category nil
"Symbol for use as allout invisible-text overlay category.")
@@ -1779,7 +1772,6 @@ hooks, by which independent code can cooperate with allout
without changes to the allout core. Here are key ones:
`allout-mode-hook'
-`allout-mode-deactivate-hook' (deprecated)
`allout-mode-off-hook'
`allout-exposure-change-functions'
`allout-structure-added-functions'
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 3973d9db08e..6f1c270c239 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -234,7 +234,7 @@ This vector holds the faces used for SGR control sequence parameters 0
to 7.
This variable is obsolete. To customize the display of faces used by
-ansi-color, change 'ansi-color-FACE', e.g. `ansi-color-bold'. To
+ansi-color, change `ansi-color-FACE', e.g. `ansi-color-bold'. To
customize the actual faces used (e.g. to temporarily display SGR
control sequences differently), use `ansi-color-basic-faces-vector'."
:type '(vector face face face face face face face face)
@@ -249,7 +249,7 @@ This vector holds the colors used for SGR control sequence parameters
30 to 37 (foreground colors) and 40 to 47 (background colors).
This variable is obsolete. To customize the display of colors used by
-ansi-color, change 'ansi-color-COLOR', e.g. `ansi-color-red'. To
+ansi-color, change `ansi-color-COLOR', e.g. `ansi-color-red'. To
customize the actual faces used (e.g. to temporarily display SGR
control sequences differently), use `ansi-color-normal-colors-vector'."
:type '(vector (choice color (cons color color))
@@ -347,6 +347,10 @@ version of that color."
"\e\\[[\x30-\x3F]*[\x20-\x2F]*[\x40-\x7E]"
"Regexp matching an ANSI control sequence.")
+(defconst ansi-color--control-seq-fragment-regexp
+ "\e\\[[\x30-\x3F]*[\x20-\x2F]*\\|\e"
+ "Regexp matching a partial ANSI control sequence.")
+
(defconst ansi-color-parameter-regexp "\\([0-9]*\\)[m;]"
"Regexp that matches SGR control sequence parameters.")
@@ -452,9 +456,6 @@ variable, and is meant to be used in `compilation-filter-hook'."
(_
(ansi-color-apply-on-region compilation-filter-start (point))))))
-(define-obsolete-function-alias 'ansi-color-unfontify-region
- 'font-lock-default-unfontify-region "24.1")
-
;; Working with strings
(defvar-local ansi-color-context nil
"Context saved between two calls to `ansi-color-apply'.
@@ -492,7 +493,11 @@ This function can be added to `comint-preoutput-filter-functions'."
;; save context, add the remainder of the string to the result
(let ((fragment ""))
(push (substring string start
- (if (string-match "\033" string start)
+ (if (string-match
+ (concat "\\(?:"
+ ansi-color--control-seq-fragment-regexp
+ "\\)\\'")
+ string start)
(let ((pos (match-beginning 0)))
(setq fragment (substring string pos))
pos)
@@ -549,7 +554,9 @@ This function can be added to `comint-preoutput-filter-functions'."
(put-text-property start (length string)
'font-lock-face face string))
;; save context, add the remainder of the string to the result
- (if (string-match "\033" string start)
+ (if (string-match
+ (concat "\\(?:" ansi-color--control-seq-fragment-regexp "\\)\\'")
+ string start)
(let ((pos (match-beginning 0)))
(setcar (cdr context) (substring string pos))
(push (substring string start pos) result))
@@ -685,7 +692,11 @@ it will override BEGIN, the start of the region. Set
(while (re-search-forward ansi-color-control-seq-regexp end-marker t)
(delete-region (match-beginning 0) (match-end 0)))
;; save context, add the remainder of the string to the result
- (if (re-search-forward "\033" end-marker t)
+ (set-marker start (point))
+ (while (re-search-forward ansi-color--control-seq-fragment-regexp
+ end-marker t))
+ (if (and (/= (point) start)
+ (= (point) end-marker))
(set-marker start (match-beginning 0))
(set-marker start nil)))))
@@ -742,10 +753,12 @@ being deleted."
;; Otherwise, strip.
(delete-region esc-beg esc-end))))
;; search for the possible start of a new escape sequence
- (if (re-search-forward "\033" end-marker t)
+ (while (re-search-forward ansi-color--control-seq-fragment-regexp
+ end-marker t))
+ (if (and (/= (point) start-marker)
+ (= (point) end-marker))
(progn
- (while (re-search-forward "\033" end-marker t))
- (backward-char)
+ (goto-char (match-beginning 0))
(funcall ansi-color-apply-face-function
start-marker (point)
(ansi-color--face-vec-face face-vec))
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 6ff444f8680..0b84f9fa63b 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -493,7 +493,12 @@ Intended as a value for `revert-buffer-function'."
\\{apropos-mode-map}"
(make-local-variable 'apropos--current)
- (setq-local revert-buffer-function #'apropos--revert-buffer))
+ (setq-local revert-buffer-function #'apropos--revert-buffer)
+ (setq-local outline-regexp "^[^ \n]+"
+ outline-level (lambda () 1)
+ outline-minor-mode-cycle t
+ outline-minor-mode-highlight t
+ outline-minor-mode-use-buttons t))
(defvar apropos-multi-type t
"If non-nil, this apropos query concerns multiple types.
@@ -513,7 +518,7 @@ variables, not just user options."
(if (or current-prefix-arg apropos-do-all)
"variable" "user option"))
current-prefix-arg))
- (apropos-command pattern nil
+ (apropos-command pattern (or do-all apropos-do-all)
(if (or do-all apropos-do-all)
(lambda (symbol)
(and (boundp symbol)
@@ -658,7 +663,10 @@ search for matches for any two (or more) of those words.
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil,
consider all symbols (if they match PATTERN).
-Return list of symbols and documentation found."
+Return list of symbols and documentation found.
+
+The *Apropos* window will be selected if `help-window-select' is
+non-nil."
(interactive (list (apropos-read-pattern "symbol")
current-prefix-arg))
(setq apropos--current (list #'apropos pattern do-all))
@@ -846,7 +854,7 @@ Returns list of symbols and values found."
f v p)
apropos-accumulator))))))
(let ((apropos-multi-type do-all))
- (apropos-print nil "\n----------------\n")))
+ (apropos-print nil "\n")))
;;;###autoload
(defun apropos-local-value (pattern &optional buffer)
@@ -866,7 +874,7 @@ Optional arg BUFFER (default: current buffer) is the buffer to check."
apropos-all-words apropos-accumulator))
(setq var (apropos-value-internal #'local-variable-if-set-p symb
#'symbol-value)))
- (when (and (fboundp 'apropos-false-hit-str) (apropos-false-hit-str var))
+ (when (apropos-false-hit-str var)
(setq var nil))
(when var
(setq apropos-accumulator (cons (list symb (apropos-score-str var) nil var)
@@ -940,13 +948,14 @@ Returns list of symbols and documentation found."
(defun apropos-value-internal (predicate symbol function)
(when (funcall predicate symbol)
- (setq symbol (prin1-to-string
- (if (memq symbol '(command-history minibuffer-history))
- ;; The value we're looking for will always be in
- ;; the first element of these two lists, so skip
- ;; that value.
- (cdr (funcall function symbol))
- (funcall function symbol))))
+ (let ((print-escape-newlines t))
+ (setq symbol (prin1-to-string
+ (if (memq symbol '(command-history minibuffer-history))
+ ;; The value we're looking for will always be in
+ ;; the first element of these two lists, so skip
+ ;; that value.
+ (cdr (funcall function symbol))
+ (funcall function symbol)))))
(when (string-match apropos-regexp symbol)
(if apropos-match-face
(put-text-property (match-beginning 0) (match-end 0)
@@ -1046,7 +1055,13 @@ non-nil."
(setq sepa (goto-char sepb)))))
(defun apropos-documentation-check-elc-file (file)
- (if (member file apropos-files-scanned)
+ ;; .elc files have the location of the file specified as #$, but for
+ ;; built-in files, that's a relative name (while for the rest, it's
+ ;; absolute). So expand the name in the former case.
+ (unless (file-name-absolute-p file)
+ (setq file (expand-file-name file lisp-directory)))
+ (if (or (member file apropos-files-scanned)
+ (not (file-exists-p file)))
nil
(let (symbol doc beg end this-is-a-variable)
(setq apropos-files-scanned (cons file apropos-files-scanned))
@@ -1156,13 +1171,15 @@ as a heading."
(old-buffer (current-buffer))
(inhibit-read-only t)
(button-end 0)
+ (first t)
symbol item)
(set-buffer standard-output)
(apropos-mode)
(apropos--preamble text)
(dolist (apropos-item p)
- (when (and spacing (not (bobp)))
- (princ spacing))
+ (if (and spacing (not first))
+ (princ spacing)
+ (setq first nil))
(setq symbol (car apropos-item))
;; Insert dummy score element for backwards compatibility with 21.x
;; apropos-item format.
@@ -1236,12 +1253,27 @@ as a heading."
'apropos-user-option
'apropos-variable)
(not nosubst))
+ ;; Insert an excerpt of variable values.
+ (when (boundp symbol)
+ (insert " Value: ")
+ (let* ((print-escape-newlines t)
+ (value (prin1-to-string (symbol-value symbol)))
+ (truncated (truncate-string-to-width
+ value (- (window-width) 20) nil nil t)))
+ (insert truncated)
+ (unless (equal value truncated)
+ (buttonize-region (1- (point)) (point)
+ (lambda (_)
+ (message "Value: %s" value))))
+ (insert "\n")))
(apropos-print-doc 7 'apropos-group t)
(apropos-print-doc 6 'apropos-face t)
(apropos-print-doc 5 'apropos-widget t)
(apropos-print-doc 4 'apropos-plist nil))
(setq-local truncate-partial-width-windows t)
- (setq-local truncate-lines t))))
+ (setq-local truncate-lines t)))
+ (when help-window-select
+ (select-window (get-buffer-window "*Apropos*"))))
(prog1 apropos-accumulator
(setq apropos-accumulator ()))) ; permit gc
@@ -1249,12 +1281,13 @@ as a heading."
(let ((doc (nth i apropos-item)))
(when (stringp doc)
(if apropos-compact-layout
- (insert (propertize "\t" 'display '(space :align-to 32)) " ")
- (insert " "))
+ (insert (propertize "\t" 'display '(space :align-to 32)))
+ (insert " "))
(if apropos-multi-type
(let ((button-face (button-type-get type 'face)))
(unless (consp button-face)
(setq button-face (list button-face)))
+ (insert " ")
(insert-text-button
(if apropos-compact-layout
(format "<%s>" (button-type-get type 'apropos-short-label))
@@ -1276,7 +1309,9 @@ as a heading."
(cond ((equal doc "")
(setq doc "(not documented)"))
(do-keys
- (setq doc (substitute-command-keys doc))))
+ (setq doc (or (ignore-errors
+ (substitute-command-keys doc))
+ doc))))
(insert doc)
(if (equal doc "(not documented)")
(put-text-property opoint (point) 'font-lock-face 'shadow))
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 4f0edbbfa98..c52f2a44322 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -101,6 +101,7 @@
;;; Code:
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
;; -------------------------------------------------------------------------
;;; Section: Configuration.
@@ -1063,7 +1064,8 @@ NEW-NAME."
#'archive--file-desc-ext-file-name
(or (archive-get-marked ?*) (list (archive-get-descr))))))
(list names
- (read-file-name (format "Copy %s to: " (string-join names ", "))))))
+ (read-file-name (format "Copy %s to: " (string-join names ", "))
+ nil default-directory))))
(unless (consp files)
(setq files (list files)))
(when (and (> (length files) 1)
@@ -1340,7 +1342,8 @@ NEW-NAME."
t)
(defun archive-*-write-file-member (archive descr command)
- (let* ((ename (archive--file-desc-ext-file-name descr))
+ (let* ((archive (expand-file-name archive))
+ (ename (archive--file-desc-ext-file-name descr))
(tmpfile (expand-file-name ename archive-tmpdir))
(top (directory-file-name (file-name-as-directory archive-tmpdir)))
(default-directory (file-name-as-directory top)))
@@ -1364,6 +1367,7 @@ NEW-NAME."
(setq ename
(encode-coding-string ename archive-file-name-coding-system))
(let* ((coding-system-for-write 'no-conversion)
+ (default-directory (file-name-as-directory archive-tmpdir))
(exitcode (apply #'call-process
(car command)
nil
diff --git a/lisp/array.el b/lisp/array.el
index 31cf9cf3028..08c5ff45ddd 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -767,29 +767,27 @@ Return COLUMN."
;;; Array mode.
-(defvar array-mode-map
- (let ((map (make-keymap)))
- (define-key map "\M-ad" #'array-display-local-variables)
- (define-key map "\M-am" #'array-make-template)
- (define-key map "\M-ae" #'array-expand-rows)
- (define-key map "\M-ar" #'array-reconfigure-rows)
- (define-key map "\M-a=" #'array-what-position)
- (define-key map "\M-ag" #'array-goto-cell)
- (define-key map "\M-af" #'array-fill-rectangle)
- (define-key map "\C-n" #'array-next-row)
- (define-key map "\C-p" #'array-previous-row)
- (define-key map "\C-f" #'array-forward-column)
- (define-key map "\C-b" #'array-backward-column)
- (define-key map "\M-n" #'array-copy-down)
- (define-key map "\M-p" #'array-copy-up)
- (define-key map "\M-f" #'array-copy-forward)
- (define-key map "\M-b" #'array-copy-backward)
- (define-key map "\M-\C-n" #'array-copy-row-down)
- (define-key map "\M-\C-p" #'array-copy-row-up)
- (define-key map "\M-\C-f" #'array-copy-column-forward)
- (define-key map "\M-\C-b" #'array-copy-column-backward)
- map)
- "Keymap used in array mode.")
+(defvar-keymap array-mode-map
+ :doc "Keymap used in array mode."
+ "M-a d" #'array-display-local-variables
+ "M-a m" #'array-make-template
+ "M-a e" #'array-expand-rows
+ "M-a r" #'array-reconfigure-rows
+ "M-a =" #'array-what-position
+ "M-a g" #'array-goto-cell
+ "M-a f" #'array-fill-rectangle
+ "C-n" #'array-next-row
+ "C-p" #'array-previous-row
+ "C-f" #'array-forward-column
+ "C-b" #'array-backward-column
+ "M-n" #'array-copy-down
+ "M-p" #'array-copy-up
+ "M-f" #'array-copy-forward
+ "M-b" #'array-copy-backward
+ "C-M-n" #'array-copy-row-down
+ "C-M-p" #'array-copy-row-up
+ "C-M-f" #'array-copy-column-forward
+ "C-M-b" #'array-copy-column-backward)
(put 'array-mode 'mode-class 'special)
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 80c220561a6..12da2c3d73d 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -164,8 +164,6 @@ Overrides `password-cache-expiry' through a let-binding."
(defvar auth-source-creation-prompts nil
"Default prompts for token values. Usually let-bound.")
-(make-obsolete 'auth-source-hide-passwords nil "24.1")
-
(defcustom auth-source-save-behavior 'ask
"If set, auth-source will respect it for save behavior."
:version "23.2" ;; No Gnus
@@ -280,15 +278,16 @@ can get pretty complex."
(const :tag "default" default))))
(repeat :tag "Extra Parameters" :inline t
(choice :tag "Extra parameter"
+ :value (:host t)
(list
- :tag "Host"
+ :tag "Host" :inline t
(const :format "" :value :host)
(choice :tag "Host (machine) choice"
(const :tag "Any" t)
(regexp
:tag "Regular expression")))
(list
- :tag "Protocol"
+ :tag "Protocol" :inline t
(const :format "" :value :port)
(choice
:tag "Protocol"
@@ -572,19 +571,24 @@ which says:
or P. The resulting token will only have keys user, host, and
port.\"
-:create \\='(A B C) also means to create a token if possible.
+:create \\='(A B C) or
+:create \\='(:unencrypted A B :encrypted C)
+also means to create a token if possible.
The behavior is like :create t but if the list contains any
parameter, that parameter will be required in the resulting
-token. The value for that parameter will be obtained from the
-search parameters or from user input. If any queries are needed,
-the alist `auth-source-creation-defaults' will be checked for the
-default value. If the user, host, or port are missing, the alist
-`auth-source-creation-prompts' will be used to look up the
-prompts IN THAT ORDER (so the `user' prompt will be queried first,
-then `host', then `port', and finally `secret'). Each prompt string
-can use %u, %h, and %p to show the user, host, and port. The prompt
-is formatted with `format-prompt', a trailing \": \" is removed.
+token (the second form is used only with the plstore backend and
+specifies if any of the extra parameters should be stored in
+encrypted format.) The value for that parameter will be obtained
+from the search parameters or from user input. If any queries
+are needed, the alist `auth-source-creation-defaults' will be
+checked for the default value. If the user, host, or port are
+missing, the alist `auth-source-creation-prompts' will be used to
+look up the prompts IN THAT ORDER (so the `user' prompt will be
+queried first, then `host', then `port', and finally `secret').
+Each prompt string can use %u, %h, and %p to show the user, host,
+and port. The prompt is formatted with `format-prompt', a
+trailing \": \" is removed.
Here's an example:
@@ -853,15 +857,17 @@ while \(:host t) would find all host entries."
(cl-return 'no)))
'no))))
-(defun auth-source-pick-first-password (&rest spec)
- "Pick the first secret found from applying SPEC to `auth-source-search'."
- (let* ((result (nth 0 (apply #'auth-source-search (plist-put spec :max 1))))
- (secret (plist-get result :secret)))
-
+(defun auth-info-password (auth-info)
+ "Return the :secret password from the AUTH-INFO."
+ (let ((secret (plist-get auth-info :secret)))
(if (functionp secret)
(funcall secret)
secret)))
+(defun auth-source-pick-first-password (&rest spec)
+ "Pick the first secret found by applying `auth-source-search' to SPEC."
+ (auth-info-password (car (apply #'auth-source-search (plist-put spec :max 1)))))
+
(defun auth-source-format-prompt (prompt alist)
"Format PROMPT using %x (for any character x) specifiers in ALIST.
Remove trailing \": \"."
@@ -1800,10 +1806,9 @@ authentication tokens:
(plist-put
artificial
:save-function
- (let* ((collection collection)
- (item (plist-get artificial :label))
- (secret (plist-get artificial :secret))
- (secret (if (functionp secret) (funcall secret) secret)))
+ (let ((collection collection)
+ (item (plist-get artificial :label))
+ (secret (auth-info-password artificial)))
(lambda ()
(auth-source-secrets-saver collection item secret args)))))
@@ -1951,7 +1956,7 @@ entries for git.gnus.org:
(defun auth-source--decode-octal-string (string)
- "Convert octal STRING to utf-8 string. E.g: 'a\134b' to 'a\b'."
+ "Convert octal STRING to utf-8 string. E.g: \"a\134b\" to \"a\b\"."
(let ((list (string-to-list string))
(size (length string)))
(decode-coding-string
@@ -2129,12 +2134,17 @@ entries for git.gnus.org:
(let* ((base-required '(host user port secret))
(base-secret '(secret))
;; we know (because of an assertion in auth-source-search) that the
- ;; :create parameter is either t or a list (which includes nil)
- (create-extra (if (eq t create) nil create))
+ ;; :create parameter is either t, or a list (which includes nil
+ ;; or a plist)
+ (create-extra-secret (plist-get create :encrypted))
+ (create-extra (if (eq t create) nil
+ (or (append (plist-get create :unencrypted)
+ create-extra-secret) create)))
(current-data (car (auth-source-search :max 1
:host host
:port port)))
(required (append base-required create-extra))
+ (required-secret (append base-secret create-extra-secret))
;; `valist' is an alist
valist
;; `artificial' will be returned if no creation is needed
@@ -2156,10 +2166,11 @@ entries for git.gnus.org:
(auth-source--aput valist br br-choice))))))
;; for extra required elements, see if the spec includes a value for them
- (dolist (er create-extra)
- (let ((k (auth-source--symbol-keyword er))
- (keys (cl-loop for i below (length spec) by 2
- collect (nth i spec))))
+ (let ((keys (cl-loop for i below (length spec) by 2
+ collect (nth i spec)))
+ k)
+ (dolist (er create-extra)
+ (setq k (auth-source--symbol-keyword er))
(when (memq k keys)
(auth-source--aput valist er (plist-get spec k)))))
@@ -2223,7 +2234,7 @@ entries for git.gnus.org:
(eval default)))))
(when data
- (if (member r base-secret)
+ (if (member r required-secret)
(setq secret-artificial
(plist-put secret-artificial
(auth-source--symbol-keyword r)
@@ -2312,89 +2323,6 @@ See `auth-source-search' for details on SPEC."
(push item all)))
(nreverse all)))
-;;; older API
-
-;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz")
-
-;; deprecate the old interface
-(make-obsolete 'auth-source-user-or-password
- 'auth-source-search "24.1")
-(make-obsolete 'auth-source-forget-user-or-password
- 'auth-source-forget "24.1")
-
-(defun auth-source-user-or-password
- (mode host port &optional username create-missing delete-existing)
- "Find MODE (string or list of strings) matching HOST and PORT.
-
-DEPRECATED in favor of `auth-source-search'!
-
-USERNAME is optional and will be used as \"login\" in a search
-across the Secret Service API (see secrets.el) if the resulting
-items don't have a username. This means that if you search for
-username \"joe\" and it matches an item but the item doesn't have
-a :user attribute, the username \"joe\" will be returned.
-
-A non-nil DELETE-EXISTING means deleting any matching password
-entry in the respective sources. This is useful only when
-CREATE-MISSING is non-nil as well; the intended use case is to
-remove wrong password entries.
-
-If no matching entry is found, and CREATE-MISSING is non-nil,
-the password will be retrieved interactively, and it will be
-stored in the password database which matches best (see
-`auth-sources').
-
-MODE can be \"login\" or \"password\"."
- (auth-source-do-debug
- "auth-source-user-or-password: DEPRECATED get %s for %s (%s) + user=%s"
- mode host port username)
-
- (let* ((listy (listp mode))
- (mode (if listy mode (list mode)))
- ;; (cname (if username
- ;; (format "%s %s:%s %s" mode host port username)
- ;; (format "%s %s:%s" mode host port)))
- (search (list :host host :port port))
- (search (if username (append search (list :user username)) search))
- (search (if create-missing
- (append search (list :create t))
- search))
- (search (if delete-existing
- (append search (list :delete t))
- search))
- ;; (found (if (not delete-existing)
- ;; (gethash cname auth-source-cache)
- ;; (remhash cname auth-source-cache)
- ;; nil)))
- (found nil))
- (if found
- (progn
- (auth-source-do-debug
- "auth-source-user-or-password: DEPRECATED cached %s=%s for %s (%s) + %s"
- mode
- ;; don't show the password
- (if (and (member "password" mode) t)
- "SECRET"
- found)
- host port username)
- found) ; return the found data
- ;; else, if not found, search with a max of 1
- (let ((choice (nth 0 (apply #'auth-source-search
- (append '(:max 1) search)))))
- (when choice
- (dolist (m mode)
- (cond
- ((equal "password" m)
- (push (if (plist-get choice :secret)
- (funcall (plist-get choice :secret))
- nil) found))
- ((equal "login" m)
- (push (plist-get choice :user) found)))))
- (setq found (nreverse found))
- (setq found (if listy found (car-safe found)))))
-
- found))
-
(defun auth-source-user-and-password (host &optional user)
(let* ((auth-info (car
(if user
@@ -2410,9 +2338,7 @@ MODE can be \"login\" or \"password\"."
:require '(:user :secret)
:create nil))))
(user (plist-get auth-info :user))
- (password (plist-get auth-info :secret)))
- (when (functionp password)
- (setq password (funcall password)))
+ (password (auth-info-password auth-info)))
(list user password auth-info)))
;;; Tiny mode for editing .netrc/.authinfo modes (that basically just
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
index f60aa9be6fa..29d10bc6295 100644
--- a/lisp/autoinsert.el
+++ b/lisp/autoinsert.el
@@ -67,7 +67,7 @@ Possible values:
other insert if possible, but mark as unmodified.
Insertion is possible when something appropriate is found in
`auto-insert-alist'. When the insertion is marked as unmodified, you can
-save it with \\[write-file] RET.
+save it with \\[write-file] \\`RET'.
This variable is used when the function `auto-insert' is called, e.g.
when you do (add-hook \\='find-file-hook \\='auto-insert).
With \\[auto-insert], this is always treated as if it were t."
@@ -76,6 +76,9 @@ With \\[auto-insert], this is always treated as if it were t."
(other :tag "insert if possible, mark as unmodified."
not-modified)))
+;;;###autoload
+(put 'auto-insert 'safe-local-variable #'null)
+
(defcustom auto-insert-query 'function
"Non-nil means ask user before auto-inserting.
When this is `function', only ask when called non-interactively."
@@ -89,9 +92,10 @@ If this contains a %s, that will be replaced by the matching rule."
:type 'string
:version "28.1")
+(declare-function sgml-tag "textmodes/sgml-mode" (&optional str arg))
(defcustom auto-insert-alist
- '((("\\.\\([Hh]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'" . "C / C++ header")
+ `((("\\.\\([Hh]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'" . "C / C++ header")
(replace-regexp-in-string
"[^A-Z0-9]" "_"
(string-replace
@@ -113,7 +117,7 @@ If this contains a %s, that will be replaced by the matching rule."
(("[Mm]akefile\\'" . "Makefile") . "makefile.inc")
- (html-mode . (lambda () (sgml-tag "html")))
+ (html-mode . ,(lambda () (sgml-tag "html")))
(plain-tex-mode . "tex-insert.tex")
(bibtex-mode . "tex-insert.tex")
@@ -128,9 +132,9 @@ If this contains a %s, that will be replaced by the matching rule."
"\n\\end{document}")
(("/bin/.*[^/]\\'" . "Shell-Script mode magic number") .
- (lambda ()
- (if (eq major-mode (default-value 'major-mode))
- (sh-mode))))
+ ,(lambda ()
+ (if (eq major-mode (default-value 'major-mode))
+ (sh-mode))))
(ada-mode . ada-header)
@@ -171,7 +175,7 @@ If this contains a %s, that will be replaced by the matching rule."
'(setq v1 (let (modes)
(mapatoms (lambda (mode)
(let ((name (symbol-name mode)))
- (when (string-match "-mode$" name)
+ (when (string-match "-mode\\'" name)
(push name modes)))))
(sort modes 'string<)))
(completing-read "Local variables for mode: " v1 nil t)
@@ -210,7 +214,8 @@ If this contains a %s, that will be replaced by the matching rule."
"\n"))
((let ((minibuffer-help-form v2))
(completing-read "Keyword, C-h: " v1 nil t))
- str ", ") & -2 "
+ str ", ")
+ & -2 "
\;; This program is free software; you can redistribute it and/or modify
\;; it under the terms of the GNU General Public License as published by
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 97a122b7bcf..918c0c7f19d 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -692,7 +692,7 @@ system.")
(defun auto-revert-notify-handler (event)
"Handle an EVENT returned from file notification."
- (with-demoted-errors
+ (with-demoted-errors "Error while auto-reverting: %S"
(let* ((descriptor (car event))
(action (nth 1 event))
(file (nth 2 event))
diff --git a/lisp/avoid.el b/lisp/avoid.el
index b53d84d2e8d..2e77c8feff1 100644
--- a/lisp/avoid.el
+++ b/lisp/avoid.el
@@ -293,6 +293,8 @@ accumulated, and tries to keep it close to zero."
(mouse-avoidance-set-mouse-position (cons (+ (car (cdr cur)) deltax)
(+ (cdr (cdr cur)) deltay))))))
+(defvar x-pointer-invisible) ; silence byte-compiler
+
(defun mouse-avoidance-random-shape ()
"Return a random cursor shape.
This assumes that any variable whose name begins with x-pointer- and
@@ -300,12 +302,14 @@ has an integer value is a valid cursor shape. You might want to
redefine this function to suit your own tastes."
(if (null mouse-avoidance-pointer-shapes)
(progn
- (setq mouse-avoidance-pointer-shapes
- (mapcar (lambda (x) (symbol-value (intern x)))
- (all-completions "x-pointer-" obarray
- (lambda (x)
- (and (boundp x)
- (integerp (symbol-value x)))))))))
+ (dolist (i (all-completions "x-pointer-" obarray
+ (lambda (x)
+ (and (boundp x)
+ (integerp (symbol-value x))))))
+ (ignore-errors
+ (let ((value (symbol-value (intern i))))
+ (when (< value x-pointer-invisible)
+ (push value mouse-avoidance-pointer-shapes)))))))
(seq-random-elt mouse-avoidance-pointer-shapes))
(defun mouse-avoidance-ignore-p ()
@@ -317,7 +321,8 @@ redefine this function to suit your own tastes."
(not (eq (car mp) (selected-frame)))
;; Don't interfere with ongoing `mouse-drag-and-drop-region'
;; (Bug#36269).
- (eq track-mouse 'dropping)
+ (or (eq track-mouse 'dropping)
+ (eq track-mouse 'drag-source))
;; Don't do anything if last event was a mouse event.
;; FIXME: this code fails in the case where the mouse was moved
;; since the last key-press but without generating any event.
diff --git a/lisp/battery.el b/lisp/battery.el
index 45334163fa6..3cff3167a6c 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -96,12 +96,14 @@ Value does not include \".\" or \"..\"."
(cond ((member battery-upower-service (dbus-list-activatable-names))
#'battery-upower)
((and (eq system-type 'gnu/linux)
+ (file-readable-p "/sys/")
(battery--find-linux-sysfs-batteries))
#'battery-linux-sysfs)
((and (eq system-type 'gnu/linux)
(file-directory-p "/proc/acpi/battery"))
#'battery-linux-proc-acpi)
((and (eq system-type 'gnu/linux)
+ (file-readable-p "/proc/")
(file-readable-p "/proc/apm"))
#'battery-linux-proc-apm)
((and (eq system-type 'berkeley-unix)
@@ -230,6 +232,40 @@ The text being displayed in the echo area is controlled by the variables
(funcall battery-status-function))
"Battery status not available")))
+(defcustom battery-update-functions nil
+ "Functions run by `display-battery-mode' after updating the status.
+These functions will be called with one parameter, an alist that
+contains data about the current battery status. The keys in the
+alist are single characters and the values are strings.
+Different battery backends deliver different information, so some
+of the following information may or may not be available:
+
+ v: driver-version
+ V: bios-version
+ I: bios-interface
+ L: line-status
+ B: battery-status
+ b: battery-status-symbol
+ p: load-percentage
+ s: seconds
+ m: minutes
+ h: hours
+ t: remaining-time
+
+For instance, to play an alarm when the battery power dips below
+10%, you could use a function like the following:
+
+(defvar my-prev-battery nil)
+(defun my-battery-alarm (data)
+ (when (and my-prev-battery
+ (equal (alist-get ?L data) \"off-line\")
+ (< (string-to-number (alist-get ?p data)) 10)
+ (>= (string-to-number (alist-get ?p my-prev-battery)) 10))
+ (play-sound-file \"~/alarm.wav\" 5))
+ (setq my-prev-battery data))"
+ :version "29.1"
+ :type '(repeat function))
+
;;;###autoload
(define-minor-mode display-battery-mode
"Toggle battery status display in mode line (Display Battery mode).
@@ -237,7 +273,11 @@ The text being displayed in the echo area is controlled by the variables
The text displayed in the mode line is controlled by
`battery-mode-line-format' and `battery-status-function'.
The mode line is be updated every `battery-update-interval'
-seconds."
+seconds.
+
+The function which updates the mode-line display will call the
+functions in `battery-update-functions', which can be used to
+trigger actions based on battery-related events."
:global t
(setq battery-mode-line-string "")
(or global-mode-string (setq global-mode-string '("")))
@@ -277,7 +317,8 @@ seconds."
((< percentage battery-load-low)
(add-face-text-property 0 len 'battery-load-low t res)))
(put-text-property 0 len 'help-echo "Battery status information" res))
- (setq battery-mode-line-string (or res "")))
+ (setq battery-mode-line-string (or res ""))
+ (run-hook-with-args 'battery-update-functions data))
(force-mode-line-update t))
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 86c0ea1a908..0cf1834a4fd 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -654,6 +654,18 @@ By default, this shows the information specified by `global-mode-string'.")
(with-selected-window (posn-window (event-start event))
(previous-buffer)))
+(defun mode-line-window-selected-p ()
+ "Return non-nil if we're updating the mode line for the selected window.
+This function is meant to be called in `:eval' mode line
+constructs to allow altering the look of the mode line depending
+on whether the mode line belongs to the currently selected window
+or not."
+ (let ((window (selected-window)))
+ (or (eq window (old-selected-window))
+ (and (minibuffer-window-active-p (minibuffer-window))
+ (with-selected-window (minibuffer-window)
+ (eq window (minibuffer-selected-window)))))))
+
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil.
Note that if `lexical-binding' is in effect, this function isn't
@@ -978,7 +990,7 @@ if `inhibit-field-text-motion' is non-nil."
(define-key esc-map "\\" 'delete-horizontal-space)
(define-key esc-map "m" 'back-to-indentation)
(define-key ctl-x-map "\C-o" 'delete-blank-lines)
-(define-key esc-map " " 'just-one-space)
+(define-key esc-map " " 'cycle-spacing)
(define-key esc-map "z" 'zap-to-char)
(define-key esc-map "=" 'count-words-region)
(define-key ctl-x-map "=" 'what-cursor-position)
@@ -1001,7 +1013,7 @@ if `inhibit-field-text-motion' is non-nil."
(let ((map (make-sparse-keymap)))
(define-key map "u" 'undo)
map)
- "Keymap to repeat undo key sequences `C-x u u'. Used in `repeat-mode'.")
+ "Keymap to repeat undo key sequences \\`C-x u u'. Used in `repeat-mode'.")
(put 'undo 'repeat-map 'undo-repeat-map)
(define-key global-map '[(control ??)] 'undo-redo)
@@ -1115,6 +1127,7 @@ if `inhibit-field-text-motion' is non-nil."
(define-key goto-map "p" 'previous-error)
(define-key goto-map "\M-p" 'previous-error)
(define-key goto-map "\t" 'move-to-column)
+(define-key goto-map "i" 'imenu)
(defvar search-map (make-sparse-keymap)
"Keymap for search related commands.")
@@ -1148,7 +1161,9 @@ if `inhibit-field-text-motion' is non-nil."
;(define-key global-map [delete] 'backward-delete-char)
;; natural bindings for terminal keycaps --- defined in X keysym order
-(define-key global-map [Scroll_Lock] 'scroll-lock-mode)
+(define-key global-map
+ (if (eq system-type 'windows-nt) [scroll] [Scroll_Lock])
+ #'scroll-lock-mode)
(define-key global-map [C-S-backspace] 'kill-whole-line)
(define-key global-map [home] 'move-beginning-of-line)
(define-key global-map [C-home] 'beginning-of-buffer)
@@ -1324,7 +1339,15 @@ if `inhibit-field-text-motion' is non-nil."
;; can use S-tab instead to access that binding.
(define-key function-key-map [S-tab] [backtab])
-(define-key global-map [mouse-movement] 'ignore)
+(defun ignore-preserving-kill-region (&rest _)
+ "Like `ignore', but don't overwrite `last-event' if it's `kill-region'."
+ (declare (completion ignore))
+ (interactive)
+ (when (eq last-command 'kill-region)
+ (setq this-command 'kill-region))
+ nil)
+
+(define-key global-map [mouse-movement] #'ignore-preserving-kill-region)
(define-key global-map "\C-t" 'transpose-chars)
(define-key esc-map "t" 'transpose-words)
@@ -1388,10 +1411,8 @@ if `inhibit-field-text-motion' is non-nil."
(define-key esc-map [?\C-\ ] 'mark-sexp)
(define-key esc-map "\C-d" 'down-list)
(define-key esc-map "\C-k" 'kill-sexp)
-;;; These are dangerous in various situations,
-;;; so let's not encourage anyone to use them.
-;;;(define-key global-map [C-M-delete] 'backward-kill-sexp)
-;;;(define-key global-map [C-M-backspace] 'backward-kill-sexp)
+(define-key global-map [C-M-delete] 'backward-kill-sexp)
+(define-key global-map [C-M-backspace] 'backward-kill-sexp)
(define-key esc-map [C-delete] 'backward-kill-sexp)
(define-key esc-map [C-backspace] 'backward-kill-sexp)
(define-key esc-map "\C-n" 'forward-list)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 0279d5ea83a..b2130557dcc 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -115,10 +115,18 @@ just use the value of `version-control'."
(defcustom bookmark-sort-flag t
- "Non-nil means that bookmarks will be displayed sorted by bookmark name.
-Otherwise they will be displayed in LIFO order (that is, most
-recently set ones come first, oldest ones come last)."
- :type 'boolean)
+ "This controls the bookmark display sorting.
+nil means they will be displayed in LIFO order (that is, most
+recently created ones come first, oldest ones come last).
+
+`last-modified' means that bookmarks will be displayed sorted
+from most recently modified to least recently modified.
+
+Other values means that bookmarks will be displayed sorted by
+bookmark name."
+ :type '(choice (const :tag "By name" t)
+ (const :tag "By modified time" last-modified)
+ (const :tag "By creation time" nil)))
(defcustom bookmark-menu-confirm-deletion nil
@@ -152,7 +160,7 @@ This includes the annotations column.")
(defcustom bookmark-bmenu-file-column 30
"Column at which to display filenames in a buffer listing bookmarks.
You can toggle whether files are shown with \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-toggle-filenames]."
- :type 'integer)
+ :type 'natnum)
(defcustom bookmark-bmenu-toggle-filenames t
@@ -166,7 +174,7 @@ A non-nil value may result in truncated bookmark names."
(defcustom bookmark-menu-length 70
"Maximum length of a bookmark name displayed on a popup menu."
- :type 'integer)
+ :type 'natnum)
;; FIXME: Is it really worth a customization option?
(defcustom bookmark-search-delay 0.2
@@ -208,10 +216,10 @@ A non-nil value may result in truncated bookmark names."
;; Set up these bindings dumping time *only*;
;; if the user alters them, don't override the user when loading bookmark.el.
-;;;###autoload (define-key ctl-x-r-map "b" 'bookmark-jump)
-;;;###autoload (define-key ctl-x-r-map "m" 'bookmark-set)
-;;;###autoload (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite)
-;;;###autoload (define-key ctl-x-r-map "l" 'bookmark-bmenu-list)
+;;;###autoload (keymap-set ctl-x-r-map "b" #'bookmark-jump)
+;;;###autoload (keymap-set ctl-x-r-map "m" #'bookmark-set)
+;;;###autoload (keymap-set ctl-x-r-map "M" #'bookmark-set-no-overwrite)
+;;;###autoload (keymap-set ctl-x-r-map "l" #'bookmark-bmenu-list)
;;;###autoload
(defvar-keymap bookmark-map
@@ -246,11 +254,13 @@ functions have a binding in this keymap."
Bookmark functions update the value automatically.
You probably do NOT want to change the value yourself.
-The value is an alist with bookmarks of the form
+The value is an alist whose elements are of the form
(BOOKMARK-NAME . PARAM-ALIST)
-or the deprecated form (BOOKMARK-NAME PARAM-ALIST).
+or the deprecated form (BOOKMARK-NAME PARAM-ALIST). The alist is
+ordered from most recently created bookmark at the front to least
+recently created bookmark at the end.
BOOKMARK-NAME is the name you gave to the bookmark when creating it.
@@ -344,6 +354,17 @@ This point is in `bookmark-current-buffer'.")
BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'."
(car bookmark-record))
+(defun bookmark-type-from-full-record (bookmark-record)
+ "Return then type of BOOKMARK-RECORD.
+BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'. It's
+type is read from the symbol property named
+`bookmark-handler-type' read on the record handler function."
+ (let ((handler (bookmark-get-handler bookmark-record)))
+ (when (autoloadp (symbol-function handler))
+ (autoload-do-load (symbol-function handler)))
+ (if (symbolp handler)
+ (get handler 'bookmark-handler-type)
+ "")))
(defun bookmark-all-names ()
"Return a list of all current bookmark names."
@@ -447,6 +468,17 @@ In other words, return all information but the name."
"Return the handler function for BOOKMARK-NAME-OR-RECORD, or nil if none."
(bookmark-prop-get bookmark-name-or-record 'handler))
+
+(defun bookmark-get-last-modified (bookmark-name-or-record)
+ "Return the last-modified for BOOKMARK-NAME-OR-RECORD, or nil if none."
+ (bookmark-prop-get bookmark-name-or-record 'last-modified))
+
+
+(defun bookmark-update-last-modified (bookmark-name-or-record)
+ "Update the last-modified date of BOOKMARK-NAME-OR-RECORD to the current time."
+ (bookmark-prop-set bookmark-name-or-record 'last-modified (current-time)))
+
+
(defvar bookmark-history nil
"The history list for bookmark functions.")
@@ -484,6 +516,24 @@ See user option `bookmark-set-fringe'."
(when (eq 'bookmark (overlay-get temp 'category))
(delete-overlay (setq found temp))))))))))
+(defun bookmark-maybe-sort-alist ()
+ "Return `bookmark-alist' for display.
+If `bookmark-sort-flag' is T, then return a sorted by name copy of the alist.
+If `bookmark-sort-flag' is LAST-MODIFIED, then return a sorted by last modified
+copy of the alist. Otherwise, just return `bookmark-alist', which by default
+is ordered from most recently created to least recently created bookmark."
+ (let ((copy (copy-alist bookmark-alist)))
+ (cond ((eq bookmark-sort-flag t)
+ (sort copy (lambda (x y) (string-lessp (car x) (car y)))))
+ ((eq bookmark-sort-flag 'last-modified)
+ (sort copy (lambda (x y)
+ (let ((tx (bookmark-get-last-modified x))
+ (ty (bookmark-get-last-modified y)))
+ (cond ((null tx) nil)
+ ((null ty) t)
+ (t (time-less-p ty tx)))))))
+ (t copy))))
+
(defun bookmark-completing-read (prompt &optional default)
"Prompting with PROMPT, read a bookmark name in completion.
PROMPT will get a \": \" stuck on the end no matter what, so you
@@ -493,10 +543,8 @@ If DEFAULT is nil then return empty string for empty input."
(bookmark-maybe-load-default-file) ; paranoia
(if (listp last-nonmenu-event)
(bookmark-menu-popup-paned-menu t prompt
- (if bookmark-sort-flag
- (sort (bookmark-all-names)
- 'string-lessp)
- (bookmark-all-names)))
+ (mapcar 'bookmark-name-from-full-record
+ (bookmark-maybe-sort-alist)))
(let* ((completion-ignore-case bookmark-completion-ignore-case)
(default (unless (equal "" default) default)))
(completing-read (format-prompt prompt default)
@@ -572,10 +620,10 @@ old one."
;; Modify using the new (NAME . ALIST) format.
(setcdr bm alist))
- ;; otherwise just cons it onto the front (either the bookmark
- ;; doesn't exist already, or there is no prefix arg. In either
- ;; case, we want the new bookmark consed onto the alist...)
-
+ ;; Otherwise just put it onto the front of the list. Either the
+ ;; bookmark doesn't exist already, or there is no prefix arg.
+ ;; In either case, we want the new bookmark on the front of the
+ ;; list, since the list is kept in reverse order of creation.
(push (cons stripped-name alist) bookmark-alist))
;; Added by db
@@ -617,7 +665,8 @@ If POSN is non-nil, record POSN as the point instead of `(point)'."
(point)
(- (point) bookmark-search-size))
nil))))
- (position . ,(or posn (point)))))
+ (position . ,(or posn (point)))
+ (last-modified . ,(current-time))))
;;; File format stuff
@@ -978,10 +1027,13 @@ annotations."
bookmark-name)
(format-message
"# All lines which start with a `#' will be deleted.\n")
- "# Type C-c C-c when done.\n#\n"
+ (substitute-command-keys
+ (concat
+ "# Type \\[bookmark-edit-annotation-confirm] when done. Type "
+ "\\[bookmark-edit-annotation-cancel] to cancel.\n#\n"))
"# Author: " (user-full-name) " <" (user-login-name) "@"
(system-name) ">\n"
- "# Date: " (current-time-string) "\n"))
+ "# Date: " (current-time-string) "\n"))
(defvar bookmark-edit-annotation-text-func 'bookmark-default-annotation-text
@@ -991,7 +1043,8 @@ It takes one argument, the name of the bookmark, as a string.")
(defvar-keymap bookmark-edit-annotation-mode-map
:doc "Keymap for editing an annotation of a bookmark."
:parent text-mode-map
- "C-c C-c" #'bookmark-send-edited-annotation)
+ "C-c C-c" #'bookmark-edit-annotation-confirm
+ "C-c C-k" #'bookmark-edit-annotation-cancel)
(defun bookmark-insert-annotation (bookmark-name-or-record)
"Insert annotation for BOOKMARK-NAME-OR-RECORD at point."
@@ -1005,12 +1058,32 @@ It takes one argument, the name of the bookmark, as a string.")
(define-derived-mode bookmark-edit-annotation-mode
text-mode "Edit Bookmark Annotation"
"Mode for editing the annotation of bookmarks.
-When you have finished composing, type \\[bookmark-send-edited-annotation].
+\\<bookmark-edit-annotation-mode-map>\
+When you have finished composing, type \\[bookmark-edit-annotation-confirm] \
+or \\[bookmark-edit-annotation-cancel] to cancel.
\\{bookmark-edit-annotation-mode-map}")
+(defmacro bookmark-edit-annotation--maybe-display-list (&rest body)
+ "Display bookmark list after editing if appropriate."
+ `(let ((from-bookmark-list bookmark--annotation-from-bookmark-list)
+ (old-buffer (current-buffer)))
+ ,@body
+ (quit-window)
+ (bookmark-bmenu-surreptitiously-rebuild-list)
+ (when from-bookmark-list
+ (pop-to-buffer (get-buffer bookmark-bmenu-buffer))
+ (goto-char (point-min))
+ (bookmark-bmenu-bookmark))
+ (kill-buffer old-buffer)))
+
+(defun bookmark-edit-annotation-cancel ()
+ "Cancel the current annotation edit."
+ (interactive nil bookmark-edit-annotation-mode)
+ (bookmark-edit-annotation--maybe-display-list
+ (message "Canceled by user")))
-(defun bookmark-send-edited-annotation ()
+(defun bookmark-edit-annotation-confirm ()
"Use buffer contents as annotation for a bookmark.
Lines beginning with `#' are ignored."
(interactive nil bookmark-edit-annotation-mode)
@@ -1022,21 +1095,14 @@ Lines beginning with `#' are ignored."
(bookmark-kill-line t)
(forward-line 1)))
;; Take no chances with text properties.
- (let ((annotation (buffer-substring-no-properties (point-min) (point-max)))
- (bookmark-name bookmark-annotation-name)
- (from-bookmark-list bookmark--annotation-from-bookmark-list)
- (old-buffer (current-buffer)))
- (bookmark-set-annotation bookmark-name annotation)
- (setq bookmark-alist-modification-count
- (1+ bookmark-alist-modification-count))
- (message "Annotation updated for \"%s\"" bookmark-name)
- (quit-window)
- (bookmark-bmenu-surreptitiously-rebuild-list)
- (when from-bookmark-list
- (pop-to-buffer (get-buffer bookmark-bmenu-buffer))
- (goto-char (point-min))
- (bookmark-bmenu-bookmark))
- (kill-buffer old-buffer)))
+ (bookmark-edit-annotation--maybe-display-list
+ (let ((annotation (buffer-substring-no-properties (point-min) (point-max)))
+ (bookmark-name bookmark-annotation-name))
+ (bookmark-set-annotation bookmark-name annotation)
+ (bookmark-update-last-modified bookmark-name)
+ (setq bookmark-alist-modification-count
+ (1+ bookmark-alist-modification-count))
+ (message "Annotation updated for \"%s\"" bookmark-name))))
(defun bookmark-edit-annotation (bookmark-name-or-record &optional from-bookmark-list)
@@ -1044,8 +1110,8 @@ Lines beginning with `#' are ignored."
If optional argument FROM-BOOKMARK-LIST is non-nil, return to the
bookmark list when editing is done."
(pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
- (bookmark-insert-annotation bookmark-name-or-record)
(bookmark-edit-annotation-mode)
+ (bookmark-insert-annotation bookmark-name-or-record)
(setq bookmark--annotation-from-bookmark-list from-bookmark-list)
(setq bookmark-annotation-name bookmark-name-or-record))
@@ -1127,13 +1193,6 @@ it to the name of the bookmark currently being set, advancing
(car bookmark-bookmarks-timestamp)))))))
(bookmark-load (car bookmark-bookmarks-timestamp) t t))))
-(defun bookmark-maybe-sort-alist ()
- "Return `bookmark-alist' for display.
-If `bookmark-sort-flag' is non-nil, then return a sorted copy of the alist."
- (if bookmark-sort-flag
- (sort (copy-alist bookmark-alist)
- (lambda (x y) (string-lessp (car x) (car y))))
- bookmark-alist))
(defvar bookmark-after-jump-hook nil
@@ -1274,7 +1333,10 @@ then offer interactively to relocate BOOKMARK-NAME-OR-RECORD."
(defun bookmark-default-handler (bmk-record)
"Default handler to jump to a particular bookmark location.
BMK-RECORD is a bookmark record, not a bookmark name (i.e., not a string).
-Changes current buffer and point and returns nil, or signals a `file-error'."
+Changes current buffer and point and returns nil, or signals a `file-error'.
+
+If BMK-RECORD has a property called `buffer', it should be a live
+buffer object, and this buffer will be selected."
(let ((file (bookmark-get-filename bmk-record))
(buf (bookmark-prop-get bmk-record 'buffer))
(forward-str (bookmark-get-front-context-string bmk-record))
@@ -1317,6 +1379,7 @@ after a bookmark was set in it."
(format "Relocate %s to: " bookmark-name)
(file-name-directory bmrk-filename))))))
(bookmark-set-filename bookmark-name newloc)
+ (bookmark-update-last-modified bookmark-name)
(setq bookmark-alist-modification-count
(1+ bookmark-alist-modification-count))
(if (bookmark-time-to-save-p)
@@ -1348,7 +1411,6 @@ minibuffer history list `bookmark-history'."
(bookmark-get-filename bookmark-name-or-record)
"-- Unknown location --"))
-
;;;###autoload
(defun bookmark-rename (old-name &optional new-name)
"Change the name of OLD-NAME bookmark to NEW-NAME name.
@@ -1374,12 +1436,13 @@ name."
(read-from-minibuffer
"New name: "
nil
- (let ((now-map (copy-keymap minibuffer-local-map)))
- (define-key now-map "\C-w" 'bookmark-yank-word)
- now-map)
+ (define-keymap
+ :parent minibuffer-local-map
+ "C-w" #'bookmark-yank-word)
nil
'bookmark-history))))
(bookmark-set-name old-name final-new-name)
+ (bookmark-update-last-modified final-new-name)
(setq bookmark-current-bookmark final-new-name)
(bookmark-bmenu-surreptitiously-rebuild-list)
(setq bookmark-alist-modification-count
@@ -1715,6 +1778,7 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
"x" #'bookmark-bmenu-execute-deletions
"d" #'bookmark-bmenu-delete
"D" #'bookmark-bmenu-delete-all
+ "S-SPC" #'previous-line
"SPC" #'next-line
"DEL" #'bookmark-bmenu-backup-unmark
"u" #'bookmark-bmenu-unmark
@@ -1787,6 +1851,7 @@ Don't affect the buffer ring order."
(let (entries)
(dolist (full-record (bookmark-maybe-sort-alist))
(let* ((name (bookmark-name-from-full-record full-record))
+ (type (bookmark-type-from-full-record full-record))
(annotation (bookmark-get-annotation full-record))
(location (bookmark-location full-record)))
(push (list
@@ -1800,11 +1865,39 @@ Don't affect the buffer ring order."
'follow-link t
'help-echo "mouse-2: go to this bookmark in other window")
name)
+ ,(or type "")
,@(if bookmark-bmenu-toggle-filenames
(list location))])
entries)))
- (tabulated-list-init-header)
- (setq tabulated-list-entries entries))
+ ;; The value of `bookmark-sort-flag' might have changed since the
+ ;; last time the buffer contents were generated, so re-check it.
+ (cond ((eq bookmark-sort-flag t)
+ (setq tabulated-list-sort-key '("Bookmark Name" . nil)
+ tabulated-list-entries entries))
+ ((or (null bookmark-sort-flag)
+ (eq bookmark-sort-flag 'last-modified))
+ (setq tabulated-list-sort-key nil)
+ ;; And since we're not sorting by bookmark name, show bookmarks
+ ;; according to order of creation, with the most recently
+ ;; created bookmarks at the top and the least recently created
+ ;; at the bottom.
+ ;;
+ ;; Note that clicking the column sort toggle for the bookmark
+ ;; name column will invoke the `tabulated-list-mode' sort, which
+ ;; uses `bookmark-bmenu--name-predicate' to sort lexically by
+ ;; bookmark name instead of by (reverse) creation order.
+ ;; Clicking the toggle again will reverse the lexical sort, but
+ ;; the sort will still be lexical not creation-order. However,
+ ;; if the user reverts the buffer, then the above check of
+ ;; `bookmark-sort-flag' will happen again and the buffer will
+ ;; go back to a creation-order sort. This is all expected
+ ;; behavior, as documented in `bookmark-bmenu-mode'.
+ (setq tabulated-list-entries (reverse entries))))
+ ;; Generate the header only after `tabulated-list-sort-key' is
+ ;; settled, because if that's non-nil then the sort-direction
+ ;; indicator will be shown in the named column, but if it's
+ ;; nil then the indicator will not be shown.
+ (tabulated-list-init-header))
(tabulated-list-print t))
;;;###autoload
@@ -1848,6 +1941,18 @@ deletion, or > if it is flagged for displaying."
Each line describes one of the bookmarks in Emacs.
Letters do not insert themselves; instead, they are commands.
Bookmark names preceded by a \"*\" have annotations.
+
+If `bookmark-sort-flag' is non-nil, then sort the list by
+bookmark name (case-insensitively, in collation order); the
+direction of that sort can be reversed by using the column sort
+toggle for the bookmark name column.
+
+If `bookmark-sort-flag' is nil, then sort the list by bookmark
+creation order, with most recently created bookmarks on top.
+However, the column sort toggle will still activate (and
+thereafter toggle the direction of) lexical sorting by bookmark name.
+At any time you may use \\[revert-buffer] to go back to sorting by creation order.
+
\\<bookmark-bmenu-mode-map>
\\[bookmark-bmenu-mark] -- mark bookmark to be displayed.
\\[bookmark-bmenu-mark-all] -- mark all listed bookmarks to be displayed.
@@ -1880,18 +1985,24 @@ Bookmark names preceded by a \"*\" have annotations.
in another buffer.
\\[bookmark-bmenu-show-all-annotations] -- show the annotations of all bookmarks in another buffer.
\\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current bookmark.
-\\[bookmark-bmenu-search] -- incrementally search for bookmarks."
+\\[bookmark-bmenu-search] -- incrementally search for bookmarks.
+\\[revert-buffer] -- refresh the buffer, and thus refresh the sort order (useful
+ if `bookmark-sort-flag' is nil)."
(setq truncate-lines t)
(setq buffer-read-only t)
;; FIXME: The header could also display the current default bookmark file
;; according to `bookmark-bookmarks-timestamp'.
(setq tabulated-list-format
`[("" 1) ;; Space to add "*" for bookmark with annotation
- ("Bookmark" ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate)
+ ("Bookmark Name"
+ ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate)
+ ("Type" 8 bookmark-bmenu--type-predicate)
,@(if bookmark-bmenu-toggle-filenames
'(("File" 0 bookmark-bmenu--file-predicate)))])
(setq tabulated-list-padding bookmark-bmenu-marks-width)
- (setq tabulated-list-sort-key '("Bookmark" . nil))
+ (when (and bookmark-sort-flag
+ (not (eq bookmark-sort-flag 'last-modified)))
+ (setq tabulated-list-sort-key '("Bookmark Name" . nil)))
(add-hook 'tabulated-list-revert-hook #'bookmark-bmenu--revert nil t)'
(setq revert-buffer-function 'bookmark-bmenu--revert)
(tabulated-list-init-header))
@@ -1900,13 +2011,19 @@ Bookmark names preceded by a \"*\" have annotations.
(defun bookmark-bmenu--name-predicate (a b)
"Predicate to sort \"*Bookmark List*\" buffer by the name column.
This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
- (string< (caar a) (caar b)))
+ (string-collate-lessp (caar a) (caar b) nil t))
+(defun bookmark-bmenu--type-predicate (a b)
+ "Predicate to sort \"*Bookmark List*\" buffer by the type column.
+This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
+ (string-collate-lessp (elt (cadr a) 2) (elt (cadr b) 2) nil t))
(defun bookmark-bmenu--file-predicate (a b)
"Predicate to sort \"*Bookmark List*\" buffer by the file column.
This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
- (string< (bookmark-location (car a)) (bookmark-location (car b))))
+ (string-collate-lessp (bookmark-location (car a))
+ (bookmark-location (car b))
+ nil t))
(defun bookmark-bmenu-toggle-filenames (&optional show)
@@ -2454,6 +2571,12 @@ This also runs `bookmark-exit-hook'."
(run-hooks 'bookmark-load-hook)
+
+;;; Obsolete:
+
+(define-obsolete-function-alias 'bookmark-send-edited-annotation
+ #'bookmark-edit-annotation-confirm "29.1")
+
(provide 'bookmark)
;;; bookmark.el ends here
diff --git a/lisp/bs.el b/lisp/bs.el
index cff19c81cb0..00d8326115e 100644
--- a/lisp/bs.el
+++ b/lisp/bs.el
@@ -1,6 +1,7 @@
;;; bs.el --- menu for selecting and displaying buffers -*- lexical-binding: t -*-
;; Copyright (C) 1998-2022 Free Software Foundation, Inc.
+
;; Author: Olaf Sylvester <Olaf.Sylvester@netsurf.de>
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
@@ -434,58 +435,61 @@ Used internally, only.")
(defvar bs--marked-buffers nil
"Currently marked buffers in Buffer Selection Menu.")
-(defvar bs-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map " " 'bs-select)
- (define-key map "f" 'bs-select)
- (define-key map "v" 'bs-view)
- (define-key map "!" 'bs-select-in-one-window)
- (define-key map [mouse-2] 'bs-mouse-select)
- (define-key map "F" 'bs-select-other-frame)
- (let ((key ?1))
- (while (<= key ?9)
- (define-key map (char-to-string key) 'digit-argument)
- (setq key (1+ key))))
- (define-key map "-" 'negative-argument)
- (define-key map "\e-" 'negative-argument)
- (define-key map "o" 'bs-select-other-window)
- (define-key map "\C-o" 'bs-tmp-select-other-window)
- (define-key map [mouse-3] 'bs-mouse-select-other-frame)
- (define-key map [up] 'bs-up)
- (define-key map "n" 'bs-down)
- (define-key map "p" 'bs-up)
- (define-key map [down] 'bs-down)
- (define-key map "\C-m" 'bs-select)
- (define-key map "b" 'bs-bury-buffer)
- (define-key map "s" 'bs-save)
- (define-key map "S" 'bs-show-sorted)
- (define-key map "a" 'bs-toggle-show-all)
- (define-key map "d" 'bs-delete)
- (define-key map "\C-d" 'bs-delete-backward)
- (define-key map "k" 'bs-delete)
- (define-key map "g" 'bs-refresh)
- (define-key map "C" 'bs-set-configuration-and-refresh)
- (define-key map "c" 'bs-select-next-configuration)
- (define-key map "q" 'bs-kill)
- ;; (define-key map "z" 'bs-kill)
- (define-key map "\C-c\C-c" 'bs-kill)
- (define-key map "\C-g" 'bs-abort)
- (define-key map "\C-]" 'bs-abort)
- (define-key map "%" 'bs-toggle-readonly)
- (define-key map "~" 'bs-clear-modified)
- (define-key map "M" 'bs-toggle-current-to-show)
- (define-key map "+" 'bs-set-current-buffer-to-show-always)
- ;;(define-key map "-" 'bs-set-current-buffer-to-show-never)
- (define-key map "t" 'bs-visit-tags-table)
- (define-key map "m" 'bs-mark-current)
- (define-key map "u" 'bs-unmark-current)
- (define-key map "U" 'bs-unmark-all)
- (define-key map "\177" 'bs-unmark-previous)
- (define-key map ">" 'scroll-right)
- (define-key map "<" 'scroll-left)
- (define-key map "?" 'bs-help)
- map)
- "Keymap of `bs-mode'.")
+(defvar-keymap bs-mode-map
+ :doc "Keymap of `bs-mode'."
+ "SPC" #'bs-select
+ "f" #'bs-select
+ "v" #'bs-view
+ "!" #'bs-select-in-one-window
+ "F" #'bs-select-other-frame
+ "1" #'digit-argument
+ "2" #'digit-argument
+ "3" #'digit-argument
+ "4" #'digit-argument
+ "5" #'digit-argument
+ "6" #'digit-argument
+ "7" #'digit-argument
+ "8" #'digit-argument
+ "9" #'digit-argument
+ "-" #'negative-argument
+ "ESC -" #'negative-argument
+ "o" #'bs-select-other-window
+ "C-o" #'bs-tmp-select-other-window
+ "<up>" #'bs-up
+ "n" #'bs-down
+ "p" #'bs-up
+ "<down>" #'bs-down
+ "C-m" #'bs-select
+ "b" #'bs-bury-buffer
+ "s" #'bs-save
+ "S" #'bs-show-sorted
+ "a" #'bs-toggle-show-all
+ "d" #'bs-delete
+ "C-d" #'bs-delete-backward
+ "k" #'bs-delete
+ "g" #'bs-refresh
+ "C" #'bs-set-configuration-and-refresh
+ "c" #'bs-select-next-configuration
+ "q" #'bs-kill
+ ;; "z" #'bs-kill
+ "C-c C-c" #'bs-kill
+ "C-g" #'bs-abort
+ "C-]" #'bs-abort
+ "%" #'bs-toggle-readonly
+ "~" #'bs-clear-modified
+ "M" #'bs-toggle-current-to-show
+ "+" #'bs-set-current-buffer-to-show-always
+ ;; "-" #'bs-set-current-buffer-to-show-never
+ "t" #'bs-visit-tags-table
+ "m" #'bs-mark-current
+ "u" #'bs-unmark-current
+ "U" #'bs-unmark-all
+ "DEL" #'bs-unmark-previous
+ ">" #'scroll-right
+ "<" #'scroll-left
+ "?" #'bs-help
+ "<mouse-2>" #'bs-mouse-select
+ "<mouse-3>" #'bs-mouse-select-other-frame)
;; ----------------------------------------------------------------------
;; Functions
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 50c2c155caf..539ef673f0b 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -92,13 +92,13 @@ number."
(defcustom Buffer-menu-size-width 7
"Width of buffer size column in the Buffer Menu."
- :type 'number
+ :type 'natnum
:group 'Buffer-menu
:version "24.3")
(defcustom Buffer-menu-mode-width 16
"Width of mode name column in the Buffer Menu."
- :type 'number
+ :type 'natnum
:group 'Buffer-menu)
(defcustom Buffer-menu-use-frame-buffer-list t
@@ -527,13 +527,18 @@ If UNMARK is non-nil, unmark them."
(multi-occur (Buffer-menu-marked-buffers) regexp nlines))
+(autoload 'etags-verify-tags-table "etags")
(defun Buffer-menu-visit-tags-table ()
"Visit the tags table in the buffer on this line. See `visit-tags-table'."
(interactive nil Buffer-menu-mode)
- (let ((file (buffer-file-name (Buffer-menu-buffer t))))
- (if file
- (visit-tags-table file)
- (error "Specified buffer has no file"))))
+ (let* ((buf (Buffer-menu-buffer t))
+ (file (buffer-file-name buf)))
+ (cond
+ ((not file) (error "Specified buffer has no file"))
+ ((and buf (with-current-buffer buf
+ (etags-verify-tags-table)))
+ (visit-tags-table file))
+ (t (error "Specified buffer is not a tags-table")))))
(defun Buffer-menu-1-window ()
"Select this line's buffer, alone, in full frame."
diff --git a/lisp/button.el b/lisp/button.el
index 8a7751d00da..80b73033d68 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -55,29 +55,24 @@
"Default face used for buttons."
:group 'basic-faces)
-(defvar button-map
- (let ((map (make-sparse-keymap)))
- ;; The following definition needs to avoid using escape sequences that
- ;; might get converted to ^M when building loaddefs.el
- (define-key map [(control ?m)] 'push-button)
- (define-key map [mouse-2] 'push-button)
- (define-key map [follow-link] 'mouse-face)
- ;; FIXME: You'd think that for keymaps coming from text-properties on the
- ;; mode-line or header-line, the `mode-line' or `header-line' prefix
- ;; shouldn't be necessary!
- (define-key map [mode-line mouse-2] 'push-button)
- (define-key map [header-line mouse-2] 'push-button)
- map)
- "Keymap used by buttons.")
-
-(defvar button-buffer-map
- (let ((map (make-sparse-keymap)))
- (define-key map [?\t] 'forward-button)
- (define-key map "\e\t" 'backward-button)
- (define-key map [backtab] 'backward-button)
- map)
- "Keymap useful for buffers containing buttons.
-Mode-specific keymaps may want to use this as their parent keymap.")
+(defvar-keymap button-buffer-map
+ :doc "Keymap useful for buffers containing buttons.
+Mode-specific keymaps may want to use this as their parent keymap."
+ "TAB" #'forward-button
+ "ESC TAB" #'backward-button
+ "<backtab>" #'backward-button)
+
+(defvar-keymap button-map
+ :doc "Keymap used by buttons."
+ :parent button-buffer-map
+ "RET" #'push-button
+ "<mouse-2>" #'push-button
+ "<follow-link>" 'mouse-face
+ ;; FIXME: You'd think that for keymaps coming from text-properties on the
+ ;; mode-line or header-line, the `mode-line' or `header-line' prefix
+ ;; shouldn't be necessary!
+ "<mode-line> <mouse-2>" #'push-button
+ "<header-line> <mouse-2>" #'push-button)
(define-minor-mode button-mode
"A minor mode for navigating to buttons with the TAB key."
@@ -625,17 +620,34 @@ When clicked, CALLBACK will be called with the DATA as the
function argument. If DATA isn't present (or is nil), the button
itself will be used instead as the function argument.
-If HELP-ECHO, use that as the `help-echo' property."
- (propertize string
- 'face 'button
- 'mouse-face 'highlight
- 'help-echo help-echo
- 'button t
- 'follow-link t
- 'category t
- 'button-data data
- 'keymap button-map
- 'action callback))
+If HELP-ECHO, use that as the `help-echo' property.
+
+Also see `buttonize-region'."
+ (apply #'propertize string
+ (button--properties callback data help-echo)))
+
+(defun button--properties (callback data help-echo)
+ (list 'face 'button
+ 'font-lock-face 'button
+ 'mouse-face 'highlight
+ 'help-echo help-echo
+ 'button t
+ 'follow-link t
+ 'category t
+ 'button-data data
+ 'keymap button-map
+ 'action callback))
+
+(defun buttonize-region (start end callback &optional data help-echo)
+ "Make the region between START and END into a button.
+When clicked, CALLBACK will be called with the DATA as the
+function argument. If DATA isn't present (or is nil), the button
+itself will be used instead as the function argument.
+
+If HELP-ECHO, use that as the `help-echo' property.
+
+Also see `buttonize'."
+ (add-text-properties start end (button--properties callback data help-echo)))
(provide 'button)
diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el
index 9a580d9602a..bb427ef86e6 100644
--- a/lisp/calc/calc-embed.el
+++ b/lisp/calc/calc-embed.el
@@ -335,7 +335,8 @@
(message (concat
"Embedded Calc mode enabled; "
(if calc-embedded-quiet
- "Type `C-x * x'"
+ (substitute-command-keys
+ "Type \\`C-x * x'")
"Give this command again")
" to return to normal")))))
(scroll-down 0))) ; fix a bug which occurs when truncate-lines is changed.
diff --git a/lisp/calc/calc-misc.el b/lisp/calc/calc-misc.el
index bd1635f2bf4..7c75e79a268 100644
--- a/lisp/calc/calc-misc.el
+++ b/lisp/calc/calc-misc.el
@@ -61,48 +61,48 @@
;;;###autoload
(defun calc-dispatch-help (arg)
- "C-x* is a prefix key sequence; follow it with one of these letters:
+ "\\`C-x *' is a prefix key sequence; follow it with one of these letters:
For turning Calc on and off:
- C calc. Start the Calculator in a window at the bottom of the screen.
- O calc-other-window. Start the Calculator but don't select its window.
- B calc-big-or-small. Control whether to use the full Emacs screen for Calc.
- Q quick-calc. Use the Calculator in the minibuffer.
- K calc-keypad. Start the Calculator in keypad mode (X window system only).
- E calc-embedded. Use the Calculator on a formula in this editing buffer.
- J calc-embedded-select. Like E, but select appropriate half of => or :=.
- W calc-embedded-word. Like E, but activate a single word, i.e., a number.
- Z calc-user-invocation. Invoke Calc in the way you defined with `Z I' cmd.
- X calc-quit. Turn Calc off.
+ \\`C' calc. Start the Calculator in a window at the bottom of the screen.
+ \\`O' calc-other-window. Start the Calculator but don't select its window.
+ \\`B' calc-big-or-small. Toggle using the full Emacs screen for Calc.
+ \\`Q' quick-calc. Use the Calculator in the minibuffer.
+ \\`K' calc-keypad. Start the Calculator in keypad mode (X window system only).
+ \\`E' calc-embedded. Use the Calculator on a formula in this editing buffer.
+ \\`J' calc-embedded-select. Like \\`E', but select appropriate half of => or :=.
+ \\`W' calc-embedded-word. Like \\`E', but activate a single word, i.e., a number.
+ \\`Z' calc-user-invocation. Invoke Calc in the way you defined with `Z I' cmd.
+ \\`X' calc-quit. Turn Calc off.
For moving data into and out of Calc:
- G calc-grab-region. Grab the region defined by mark and point into Calc.
- R calc-grab-rectangle. Grab the rectangle defined by mark, point into Calc.
- : calc-grab-sum-down. Grab a rectangle and sum the columns.
- _ calc-grab-sum-across. Grab a rectangle and sum the rows.
- Y calc-copy-to-buffer. Copy a value from the stack into the editing buffer.
+ \\`G' calc-grab-region. Grab the region defined by mark and point into Calc.
+ \\`R' calc-grab-rectangle. Grab the rectangle defined by mark, point into Calc.
+ \\`:' calc-grab-sum-down. Grab a rectangle and sum the columns.
+ \\`_' calc-grab-sum-across. Grab a rectangle and sum the rows.
+ \\`Y' calc-copy-to-buffer. Copy a value from the stack into the editing buffer.
For use with Embedded mode:
- A calc-embedded-activate. Find and activate all :='s and =>'s in buffer.
- D calc-embedded-duplicate. Make a copy of this formula and select it.
- F calc-embedded-new-formula. Insert a new formula at current point.
- N calc-embedded-next. Advance cursor to next known formula in buffer.
- P calc-embedded-previous. Advance cursor to previous known formula.
- U calc-embedded-update-formula. Re-evaluate formula at point.
- \\=` calc-embedded-edit. Use calc-edit to edit formula at point.
+ \\`A' calc-embedded-activate. Find and activate all :='s and =>'s in buffer.
+ \\`D' calc-embedded-duplicate. Make a copy of this formula and select it.
+ \\`F' calc-embedded-new-formula. Insert a new formula at current point.
+ \\`N' calc-embedded-next. Advance cursor to next known formula in buffer.
+ \\`P' calc-embedded-previous. Advance cursor to previous known formula.
+ \\`U' calc-embedded-update-formula. Re-evaluate formula at point.
+ \\``' calc-embedded-edit. Use calc-edit to edit formula at point.
Documentation:
- I calc-info. Read the Calculator manual in the Emacs Info system.
- T calc-tutorial. Run the Calculator Tutorial using the Emacs Info system.
- S calc-summary. Read the Summary from the Calculator manual in Info.
+ \\`I' calc-info. Read the Calculator manual in the Emacs Info system.
+ \\`T' calc-tutorial. Run the Calculator Tutorial using the Emacs Info system.
+ \\`S' calc-summary. Read the Summary from the Calculator manual in Info.
Miscellaneous:
- L calc-load-everything. Load all parts of the Calculator into memory.
- M read-kbd-macro. Read a region of keystroke names as a keyboard macro.
- 0 (zero) calc-reset. Reset Calc stack and modes to default state.
+ \\`L' calc-load-everything. Load all parts of the Calculator into memory.
+ \\`M' read-kbd-macro. Read a region of keystroke names as a keyboard macro.
+ \\`0' (zero) calc-reset. Reset Calc stack and modes to default state.
-Press `*' twice (`C-x * *') to turn Calc on or off using the same
-Calc user interface as before (either C-x * C or C-x * K; initially C-x * C)."
+Press \\`*' twice (\\`C-x * *') to turn Calc on or off using the same
+Calc user interface as before (either \\`C-x * C' or \\`C-x * K'; initially \\`C-x * C')."
(interactive "P")
(calc-check-defines)
(if calc-dispatch-help
diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index dc2a086bbd7..f11d9741ec7 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -678,7 +678,7 @@
(or last-kbd-macro
(error "No keyboard macro defined"))
(setq calc-invocation-macro last-kbd-macro)
- (message "Use `C-x * Z' to invoke this macro"))
+ (message (substitute-command-keys "Use \\`C-x * Z' to invoke this macro")))
(defun calc-user-define-edit ()
(interactive) ; but no calc-wrapper!
@@ -1949,7 +1949,7 @@ Redefine the corresponding command."
;; The variable math-exp-env is local to math-define-body, but is
;; used by math-define-exp, which is called (indirectly) by
-;; by math-define-body.
+;; math-define-body.
(defvar math-exp-env)
(defun math-define-body (body exp-env)
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index 8c6d3f51e5d..71cc68b0c20 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -47,6 +47,8 @@
(calc-check-stack num)
(let ((stuff (calc-top-list n (- num n -1))))
(calc-cursor-stack-index num)
+ (unless calc-kill-line-numbering
+ (re-search-forward "\\=[0-9]+:\\s-+" (point-at-eol) t))
(let ((first (point)))
(calc-cursor-stack-index (- num n))
(if (null nn)
@@ -264,14 +266,16 @@ as well as set the contents of the Emacs register REGISTER to TEXT."
"Return the CALCVAL portion of the contents of the Calc register REG,
unless the TEXT portion doesn't match the contents of the Emacs register REG,
in which case either return the contents of the Emacs register (if it is
-text) or nil."
+text or a number) or nil."
(let ((cval (cdr (assq reg calc-register-alist)))
(val (cdr (assq reg register-alist))))
- (if (stringp val)
- (if (and (stringp (car cval))
- (string= (car cval) val))
- (cdr cval)
- val))))
+ (cond
+ ((stringp val)
+ (if (and (stringp (car cval))
+ (string= (car cval) val))
+ (cdr cval)
+ val))
+ ((numberp val) (number-to-string val)))))
(defun calc-copy-to-register (register start end &optional delete-flag)
"Copy the lines in the region into register REGISTER.
@@ -711,9 +715,9 @@ To cancel the edit, simply kill the *Calc Edit* buffer."
(insert (propertize
(concat
(or title title "Calc Edit Mode. ")
- (format-message "Press `C-c C-c'")
+ (substitute-command-keys "Press \\`C-c C-c'")
(if allow-ret "" " or RET")
- (format-message " to finish, `C-x k RET' to cancel.\n\n"))
+ (substitute-command-keys " to finish, \\`C-x k RET' to cancel.\n\n"))
'font-lock-face 'italic 'read-only t 'rear-nonsticky t 'front-sticky t))
(setq-local calc-edit-top (point))))
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 3b1cf248fd9..254c703ee22 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -412,7 +412,7 @@ and deleted by `calc-pop'."
(defcustom calc-undo-length 100
"The number of undo steps that will be preserved when Calc is quit."
- :type 'integer)
+ :type 'natnum)
(defcustom calc-highlight-selections-with-faces nil
"If non-nil, use a separate face to indicate selected sub-formulas.
@@ -439,6 +439,14 @@ to be identified as that note."
:version "24.1"
:type 'string)
+(defcustom calc-kill-line-numbering t
+ "If non-nil, calculator kills include any line numbering.
+
+This option does not affect calc kill and copy commands which
+operate on the region, such as `calc-copy-region-as-kill'."
+ :version "29.1"
+ :type 'boolean)
+
(defvar math-format-date-cache) ; calc-forms.el
(defface calc-nonselected-face
@@ -1375,7 +1383,7 @@ Notations: 3.14e6 3.14 * 10^6
LONG is a desired text for a wide window, SHORT is a desired
abbreviated text, and width is the buffer width, which will be
-some fraction of the 'parent' window width (At the time of
+some fraction of the \"parent\" window width (At the time of
writing, 2/3 for calc, 1/3 for trail). The optional FUDGE is a
trial-and-error adjustment number for the edge-cases at the
border of the two cases."
@@ -1816,7 +1824,7 @@ See calc-keypad for details."
(if win
(progn
(calc-cursor-stack-index 0)
- (vertical-motion (- 2 (window-height win)))
+ (vertical-motion (- 3 (window-height win 'floor)))
(set-window-start win (point)))))
(calc-cursor-stack-index 0)
(if (looking-at " *\\.$")
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
index ebdafb438e3..a7d13cff9a1 100644
--- a/lisp/calendar/appt.el
+++ b/lisp/calendar/appt.el
@@ -510,9 +510,13 @@ The time should be in either 24 hour format or am/pm format.
Optional argument WARNTIME is an integer (or string) giving the number
of minutes before the appointment at which to start warning.
The default is `appt-message-warning-time'."
- (interactive "sTime (hh:mm[am/pm]): \nsMessage: \n\
-sMinutes before the appointment to start warning: ")
- (unless (string-match appt-time-regexp time)
+ (interactive (list (let ((time (read-string "Time (hh:mm[am/pm]): ")))
+ (unless (string-match-p appt-time-regexp time)
+ (user-error "Unacceptable time-string"))
+ time)
+ (read-string "Message: ")
+ (read-string "Minutes before the appointment to start warning: ")))
+ (unless (string-match-p appt-time-regexp time)
(user-error "Unacceptable time-string"))
(and (stringp warntime)
(setq warntime (unless (string-equal warntime "")
diff --git a/lisp/calendar/cal-hebrew.el b/lisp/calendar/cal-hebrew.el
index 61ce029e077..1c08de53fbd 100644
--- a/lisp/calendar/cal-hebrew.el
+++ b/lisp/calendar/cal-hebrew.el
@@ -798,6 +798,10 @@ In this case, the following civil date corresponds to the Hebrew birthday."
(diary-ordinal-suffix age)
(if (= b-date d) "" " (evening)")))))
+(defvar diary-hebrew-omer-sefirot
+ ["Hesed" "Gevurah" "Tiferet" "Netzach" "Hod" "Yesod" "Malchut"]
+ "The order of Sefirot for counting the Omer.
+See https://opensiddur.org/prayers/solilunar/solar-cycles/sefirat-haomer/the-order-of-counting-the-omer-in-the-spring/")
;;;###diary-autoload
(defun diary-hebrew-omer (&optional mark)
"Omer count diary entry.
@@ -813,7 +817,7 @@ use when highlighting the day in the calendar."
(day (% omer 7)))
(if (and (> omer 0) (< omer 50))
(cons mark
- (format "Day %d%s of the omer (until sunset)"
+ (format "Day %d%s of the omer (until sunset) %s she'be'%s"
omer
(if (zerop week)
""
@@ -823,7 +827,10 @@ use when highlighting the day in the calendar."
(if (zerop day)
""
(format " and %d day%s"
- day (if (= day 1) "" "s"))))))))))
+ day (if (= day 1) "" "s")))))
+ (aref diary-hebrew-omer-sefirot (% (+ 6 day) 7))
+ (aref diary-hebrew-omer-sefirot
+ (+ (if (zerop day) -1 0) week)))))))
(autoload 'diary-make-date "diary-lib")
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 48d308afade..c1f176050c2 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -211,7 +211,7 @@ If you change this variable directly (without using customize)
after starting `calendar', you should call `calendar-redraw' to
update the calendar display to reflect the change, otherwise
movement commands will not work correctly."
- :type 'integer
+ :type 'natnum
;; Change the initialize so that if you reload calendar.el, it will not
;; cause a redraw.
:initialize 'custom-initialize-default
@@ -511,7 +511,7 @@ Then redraw the calendar, if necessary."
:initialize #'custom-initialize-default
:set (lambda (sym val)
(calendar-set-layout-variable sym val 1))
- :type 'integer
+ :type 'natnum
:version "23.1")
;; FIXME calendar-month-column-width?
@@ -520,7 +520,7 @@ Then redraw the calendar, if necessary."
:initialize #'custom-initialize-default
:set (lambda (sym val)
(calendar-set-layout-variable sym val 3))
- :type 'integer
+ :type 'natnum
:version "23.1")
(defun calendar-day-header-construct (&optional width)
@@ -553,7 +553,7 @@ Must be at least one less than `calendar-column-width'."
:initialize #'custom-initialize-default
:set (lambda (sym val)
(calendar-set-layout-variable sym val 2))
- :type 'integer
+ :type 'natnum
:version "23.1")
(defcustom calendar-intermonth-header nil
@@ -565,7 +565,7 @@ See `calendar-intermonth-text'."
:set (lambda (sym val)
(set sym val)
(calendar-redraw))
- :type '(choice (const nil :tag "Nothing")
+ :type '(choice (const :value nil :tag "Nothing")
(string :tag "Fixed string")
(sexp :value
(propertize "WK" 'font-lock-face
@@ -597,7 +597,7 @@ See also `calendar-intermonth-header'."
:set (lambda (sym val)
(set sym val)
(calendar-redraw))
- :type '(choice (const nil :tag "Nothing")
+ :type '(choice (const :value nil :tag "Nothing")
(string :tag "Fixed string")
(sexp :value
(propertize
@@ -742,9 +742,9 @@ Setting this variable directly does not take effect (if the
calendar package is already loaded). Rather, use either
\\[customize] or the function `calendar-set-date-style'."
:version "23.1"
- :type '(choice (const american :tag "Month/Day/Year")
- (const european :tag "Day/Month/Year")
- (const iso :tag "Year/Month/Day"))
+ :type '(choice (const :value american :tag "American (Month/Day/Year)")
+ (const :value european :tag "European (Day/Month/Year)")
+ (const :value iso :tag "ISO 8601 (Year/Month/Day)"))
:initialize 'custom-initialize-default
:set (lambda (_symbol value)
(calendar-set-date-style value))
@@ -1066,7 +1066,7 @@ calendar."
;; fixme should have a :set that changes calendar-standard-time-zone-name etc.
(defcustom calendar-time-zone-style 'symbolic
"Your preferred style for time zones.
-If 'numeric, use numeric time zones like \"+0100\".
+If `numeric', use numeric time zones like \"+0100\".
Otherwise, use symbolic time zones like \"CET\"."
:type '(choice (const numeric) (other symbolic))
:version "28.1"
@@ -1861,7 +1861,9 @@ concatenated and the result truncated."
buffs))
(defun calendar-exit (&optional kill)
- "Get out of the calendar window and hide it and related buffers."
+ "Get out of the calendar window and hide it and related buffers.
+If KILL (interactively, the prefix), kill the buffers instead of
+hiding them."
(interactive "P")
(let ((diary-buffer (get-file-buffer diary-file))
(calendar-buffers (calendar-buffer-list)))
@@ -1880,7 +1882,12 @@ concatenated and the result truncated."
(iconify-frame (window-frame w)))
(quit-window kill w))))
(dolist (b calendar-buffers)
- (quit-windows-on b kill))))))
+ (quit-windows-on b kill)))
+ ;; Finally, kill non-displayed buffers (if requested).
+ (when kill
+ (dolist (b calendar-buffers)
+ (when (buffer-live-p b)
+ (kill-buffer b)))))))
(defun calendar-current-date (&optional offset)
"Return the current date in a list (month day year).
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index 45df0c6259c..084d2d7d55e 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -1,7 +1,6 @@
;;; diary-lib.el --- diary functions -*- lexical-binding:t -*-
-;; Copyright (C) 1989-1990, 1992-1995, 2001-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1989-2022 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -101,11 +100,11 @@ are: `string', `symbol', `int', `tnil', `stringtnil'."
:type '(repeat (list (regexp :tag "Regular expression")
(integer :tag "Sub-expression")
(symbol :tag "Attribute (e.g. :foreground)")
- (choice (const string :tag "A string")
- (const symbol :tag "A symbol")
- (const int :tag "An integer")
- (const tnil :tag "t or nil")
- (const stringtnil
+ (choice (const :value string :tag "A string")
+ (const :value symbol :tag "A symbol")
+ (const :value int :tag "An integer")
+ (const :value tnil :tag "t or nil")
+ (const :value stringtnil
:tag "A string, t, or nil"))))
:group 'diary)
@@ -2246,12 +2245,10 @@ Prefix argument ARG makes the entry nonmarking."
;; Return value suitable for `write-contents-functions'.
nil)
-(defvar diary-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-s" 'diary-show-all-entries)
- (define-key map "\C-c\C-q" 'quit-window)
- map)
- "Keymap for `diary-mode'.")
+(defvar-keymap diary-mode-map
+ :doc "Keymap for `diary-mode'."
+ "C-c C-s" #'diary-show-all-entries
+ "C-c C-q" #'quit-window)
(defun diary-font-lock-sexps (limit)
"Recognize sexp diary entry up to LIMIT for font-locking."
diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el
index 2afa667a56c..5aa0d26d192 100644
--- a/lisp/calendar/holidays.el
+++ b/lisp/calendar/holidays.el
@@ -30,7 +30,7 @@
;;; Code:
(require 'calendar)
-(load "hol-loaddefs" nil t)
+(load "holiday-loaddefs" nil t)
(defgroup holidays nil
"Holidays support in calendar."
@@ -400,6 +400,36 @@ This function is suitable for execution in an init file."
(displayed-year (calendar-extract-year date)))
(calendar-list-holidays))))
+(defun holiday-available-holiday-lists ()
+ "Return a list of all holiday lists.
+This is used by `list-holidays', and you can customize the return
+value by using `add-function'."
+ (delq
+ nil
+ (list
+ (cons "All" calendar-holidays)
+ (cons "Equinoxes/Solstices"
+ (list (list 'solar-equinoxes-solstices)))
+ (if holiday-general-holidays
+ (cons "General" holiday-general-holidays))
+ (if holiday-local-holidays
+ (cons "Local" holiday-local-holidays))
+ (if holiday-other-holidays
+ (cons "Other" holiday-other-holidays))
+ (if holiday-christian-holidays
+ (cons "Christian" holiday-christian-holidays))
+ (if holiday-hebrew-holidays
+ (cons "Hebrew" holiday-hebrew-holidays))
+ (if holiday-islamic-holidays
+ (cons "Islamic" holiday-islamic-holidays))
+ (if holiday-bahai-holidays
+ (cons "Bahá’í" holiday-bahai-holidays))
+ (if holiday-oriental-holidays
+ (cons "Oriental" holiday-oriental-holidays))
+ (if holiday-solar-holidays
+ (cons "Solar" holiday-solar-holidays))
+ (cons "Ask" nil))))
+
;; rms: "Emacs commands to display a list of something generally start
;; with `list-'. Please make `list-holidays' the principal name."
;;;###autoload
@@ -421,7 +451,12 @@ documentation of `calendar-holidays' for a list of the variables
that control the choices, as well as a description of the format
of a holiday list.
-The optional LABEL is used to label the buffer created."
+The optional LABEL is used to label the buffer created.
+
+The list of holiday lists is computed by the
+`holiday-available-holiday-lists' and you can alter the results
+by redefining that function, or use `add-function' to add
+values."
(interactive
(let* ((start-year (calendar-read-sexp
"Starting year of holidays (>0)"
@@ -433,30 +468,7 @@ The optional LABEL is used to label the buffer created."
start-year
start-year))
(completion-ignore-case t)
- (lists
- (list
- (cons "All" calendar-holidays)
- (cons "Equinoxes/Solstices"
- (list (list 'solar-equinoxes-solstices)))
- (if holiday-general-holidays
- (cons "General" holiday-general-holidays))
- (if holiday-local-holidays
- (cons "Local" holiday-local-holidays))
- (if holiday-other-holidays
- (cons "Other" holiday-other-holidays))
- (if holiday-christian-holidays
- (cons "Christian" holiday-christian-holidays))
- (if holiday-hebrew-holidays
- (cons "Hebrew" holiday-hebrew-holidays))
- (if holiday-islamic-holidays
- (cons "Islamic" holiday-islamic-holidays))
- (if holiday-bahai-holidays
- (cons "Bahá’í" holiday-bahai-holidays))
- (if holiday-oriental-holidays
- (cons "Oriental" holiday-oriental-holidays))
- (if holiday-solar-holidays
- (cons "Solar" holiday-solar-holidays))
- (cons "Ask" nil)))
+ (lists (holiday-available-holiday-lists))
(choice (capitalize
(completing-read "List (TAB for choices): " lists nil t)))
(which (if (string-equal choice "Ask")
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 1a5a071e202..cf542939897 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -1144,7 +1144,8 @@ FExport diary data into iCalendar file: ")
(cdr contents-n-summary))))
(setq result (concat result header contents alarm
"\nEND:VEVENT")))
- (if (consp cns-cons-or-list)
+ (if (and (consp cns-cons-or-list)
+ (not (listp (cdr cns-cons-or-list))))
(list cns-cons-or-list)
cns-cons-or-list)))
;; handle errors
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index e31120f52ff..6827a957a6f 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -114,6 +114,11 @@
iso8601--duration-week-match
iso8601--duration-combined-match)))
+;; "Z" dnd "z" are standard time; nil and [-+][0-9][0-9]... are local time
+;; with unknown DST.
+(defun iso8601--zone-dst (zone)
+ (if (= (length zone) 1) nil -1))
+
(defun iso8601-parse (string &optional form)
"Parse an ISO 8601 date/time string and return a `decode-time' structure.
@@ -140,7 +145,7 @@ See `decode-time' for the meaning of FORM."
(setf (decoded-time-zone date)
;; The time zone in decoded times are in seconds.
(* (iso8601-parse-zone zone-string) 60))
- (setf (decoded-time-dst date) nil))
+ (setf (decoded-time-dst date) (iso8601--zone-dst zone-string)))
date)))
(defun iso8601-parse-date (string)
@@ -256,6 +261,7 @@ See `decode-time' for the meaning of FORM."
(iso8601--decoded-time :hour hour
:minute (or minute 0)
:second (or second 0)
+ :dst (iso8601--zone-dst zone)
:zone (and zone
(* 60 (iso8601-parse-zone
zone)))))))))
@@ -364,7 +370,7 @@ Return the number of minutes."
(cl-defun iso8601--decoded-time (&key second minute hour
day month year
- dst zone)
+ (dst -1) zone)
(list (iso8601--value second)
(iso8601--value minute)
(iso8601--value hour)
@@ -372,7 +378,7 @@ Return the number of minutes."
(iso8601--value month)
(iso8601--value year)
nil
- (if (or dst zone) dst -1)
+ dst
zone))
(defun iso8601--encode-time (time)
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 51cf7eb213f..d1afd8ce95a 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -287,17 +287,23 @@ use. \"%,1s\" means \"use one decimal\".
The \"%z\" specifier does not print anything. When it is used, specifiers
must be given in order of decreasing size. To the left of \"%z\", nothing
-is output until the first non-zero unit is encountered."
+is output until the first non-zero unit is encountered.
+
+The \"%x\" specifier does not print anything. When it is used,
+specifiers must be given in order of decreasing size. To the
+right of \"%x\", trailing zero units are not output."
(let ((start 0)
(units '(("y" "year" 31536000)
("d" "day" 86400)
("h" "hour" 3600)
("m" "minute" 60)
("s" "second" 1)
- ("z")))
+ ("z")
+ ("x")))
(case-fold-search t)
- spec match usedunits zeroflag larger prev name unit num zeropos
- fraction)
+ spec match usedunits zeroflag larger prev name unit num
+ leading-zeropos trailing-zeropos fraction
+ chop-leading chop-trailing)
(while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start)
(setq start (match-end 0)
spec (match-string 2 string))
@@ -306,15 +312,16 @@ is output until the first non-zero unit is encountered."
(error "Bad format specifier: `%s'" spec))
(if (assoc (downcase spec) usedunits)
(error "Multiple instances of specifier: `%s'" spec))
- (if (string-equal (car match) "z")
+ (if (or (string-equal (car match) "z")
+ (string-equal (car match) "x"))
(setq zeroflag t)
(unless larger
(setq unit (nth 2 match)
larger (and prev (> unit prev))
prev unit)))
(push match usedunits)))
- (and zeroflag larger
- (error "Units are not in decreasing order of size"))
+ (when (and zeroflag larger)
+ (error "Units are not in decreasing order of size"))
(unless (numberp seconds)
(setq seconds (float-time seconds)))
(setq fraction (mod seconds 1)
@@ -326,18 +333,28 @@ is output until the first non-zero unit is encountered."
(when (string-match
(format "%%\\(\\.?[0-9]+\\)?\\(,[0-9]+\\)?\\(%s\\)" spec)
string)
- (if (string-equal spec "z") ; must be last in units
- (setq string
- (replace-regexp-in-string
- "%z" ""
- (substring string (min (or zeropos (match-end 0))
- (match-beginning 0)))))
+ (cond
+ ((string-equal spec "z")
+ (setq chop-leading (and leading-zeropos
+ (min leading-zeropos (match-beginning 0)))))
+ ((string-equal spec "x")
+ (setq chop-trailing t))
+ (t
;; Cf article-make-date-line in gnus-art.
(setq num (floor seconds unit)
seconds (- seconds (* num unit)))
- ;; Start position of the first non-zero unit.
- (or zeropos
- (setq zeropos (unless (zerop num) (match-beginning 0))))
+ (let ((is-zero (zerop (if (= unit 1)
+ (+ num fraction)
+ num))))
+ ;; Start position of the first non-zero unit.
+ (when (and (not leading-zeropos)
+ (not is-zero))
+ (setq leading-zeropos (match-beginning 0)))
+ (unless is-zero
+ (setq trailing-zeropos nil))
+ (when (and (not trailing-zeropos)
+ is-zero)
+ (setq trailing-zeropos (match-beginning 0))))
(setq string
(replace-match
(format (if (match-string 2 string)
@@ -360,7 +377,17 @@ is output until the first non-zero unit is encountered."
(format " %s%s" name
(if (= num 1) "" "s"))))
t t string))))))
- (string-replace "%%" "%" string))
+ (let ((pre string))
+ (when (and chop-trailing trailing-zeropos)
+ (setq string (substring string 0 trailing-zeropos)))
+ (when chop-leading
+ (setq string (substring string chop-leading)))
+ ;; If we ended up removing everything, return the formatted
+ ;; string in full.
+ (when (equal string "")
+ (setq string pre)))
+ (setq string (replace-regexp-in-string "%[zx]" "" string)))
+ (string-trim (string-replace "%%" "%" string)))
(defvar seconds-to-string
(list (list 1 "ms" 0.001)
@@ -525,16 +552,20 @@ changes in daylight saving time are not taken into account."
(cl-defun make-decoded-time (&key second minute hour
day month year
- dst zone)
+ (dst -1) zone)
"Return a `decoded-time' structure with only the keywords given filled out."
(list second minute hour day month year nil dst zone))
(defun decoded-time-set-defaults (time &optional default-zone)
- "Set any nil values in `decoded-time' TIME to default values.
+ "Set most nil values in `decoded-time' TIME to default values.
+This can set TIME's year, month, day, hour, minute and second.
The default value is based on January 1st, 1970 at midnight.
This year is used to guarantee portability; see Info
node `(elisp) Time of Day'.
+Optional argument DEFAULT-ZONE specifies what time zone to
+default to when TIME's time zone is nil (meaning local time).
+
TIME is modified and returned."
(unless (decoded-time-second time)
(setf (decoded-time-second time) 0))
@@ -550,18 +581,16 @@ TIME is modified and returned."
(unless (decoded-time-year time)
(setf (decoded-time-year time) 1970))
- ;; When we don't have a time zone, default to DEFAULT-ZONE without
- ;; DST if DEFAULT-ZONE if given, and to unknown DST otherwise.
(unless (decoded-time-zone time)
- (if default-zone
- (progn (setf (decoded-time-zone time) default-zone)
- (setf (decoded-time-dst time) nil))
- (setf (decoded-time-dst time) -1)))
+ (setf (decoded-time-zone time) default-zone))
+
+ ;; Do not set decoded-time-weekday or decoded-time-dst,
+ ;; as encode-time can infer them well enough when unknown.
time)
(defun decoded-time-period (time)
- "Interpret DECODED as a period and return its length in seconds.
+ "Interpret TIME as a period and return its length in seconds.
For computational purposes, years are 365 days long and months
are 30 days long."
(+ (if (consp (decoded-time-second time))
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 1c6a557a0d3..7bdaf7ceff6 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -86,7 +86,7 @@
(defcustom timeclock-workday (* 8 60 60)
"The length of a work period in seconds."
- :type 'integer)
+ :type 'natnum)
(defvar timeclock--previous-workday nil)
diff --git a/lisp/cedet/data-debug.el b/lisp/cedet/data-debug.el
index 0edc853edda..e7635c0aec5 100644
--- a/lisp/cedet/data-debug.el
+++ b/lisp/cedet/data-debug.el
@@ -854,7 +854,6 @@ If PARENT is non-nil, it is somehow related as a parent to thing."
table)
"Syntax table used in data-debug macro buffers.")
-(define-obsolete-variable-alias 'data-debug-map 'data-debug-mode-map "24.1")
(defvar data-debug-mode-map
(let ((km (make-sparse-keymap)))
(suppress-keymap km)
@@ -1028,11 +1027,9 @@ Do nothing if already contracted."
(defun data-debug-edebug-expr (expr)
"Dump out the contents of some expression EXPR in edebug with ddebug."
(interactive
- (list (let ((minibuffer-completing-symbol t))
- (read-from-minibuffer "Eval: "
- nil read-expression-map t
- 'read-expression-history))
- ))
+ (list (read-from-minibuffer "Eval: "
+ nil read-expression-map t
+ 'read-expression-history)))
(let ((v (eval expr t)))
(if (not v)
(message "Expression %s is nil." expr)
@@ -1043,10 +1040,9 @@ Do nothing if already contracted."
If the result is something simple, show it in the echo area.
If the result is a list or vector, then use the data debugger to display it."
(interactive
- (list (let ((minibuffer-completing-symbol t))
- (read-from-minibuffer "Eval: "
- nil read-expression-map t
- 'read-expression-history))))
+ (list (read-from-minibuffer "Eval: "
+ nil read-expression-map t
+ 'read-expression-history)))
(let (result)
(if (null eval-expression-debug-on-error)
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index 5a23f504f78..cbe766cedb6 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -59,7 +59,7 @@ Return a tuple of ( EMACSNAME . VERSION )."
(file-exists-p (setq configure_ac "configure.in")))
(insert-file-contents configure_ac)
(goto-char (point-min))
- (re-search-forward "AC_INIT(\\(?:GNU \\)?[eE]macs,\\s-*\\([0-9.]+\\)\\s-*[,)]")
+ (re-search-forward "AC_INIT(\\[?\\(?:GNU \\)?[eE]macs]?,\\s-*\\[?\\([0-9.]+\\)]?\\s-*[,)]")
(setq ver (match-string 1))
)
)
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index 3b9002a6e31..b8acb192c17 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -257,7 +257,7 @@ If optional EXACT is non-nil, only return exact matches for DIR."
(defun ede-flush-directory-hash ()
"Flush the project directory hash.
Do this only when developing new projects that are incorrectly putting
-'nomatch tokens into the hash."
+`nomatch' tokens into the hash."
(interactive)
(setq ede-project-directory-hash (make-hash-table :test 'equal))
;; Also slush the current project's locator hash.
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el
index 0c65af15c4a..7c56ca19936 100644
--- a/lisp/cedet/ede/proj-elisp.el
+++ b/lisp/cedet/ede/proj-elisp.el
@@ -319,8 +319,7 @@ Lays claim to all .elc files that match .el files in this target."
("require" . "$(foreach r,$(1),(require (quote $(r))))"))
:commands
'("$(EMACS) $(EMACSFLAGS) $(addprefix -L ,$(LOADPATH)) \
---eval '(setq generated-autoload-file \"$(abspath $(LOADDEFS))\")' \
--f batch-update-autoloads $(abspath $(LOADDIRS))")
+-f loaddefs-generate-batch $(abspath $(LOADDEFS)) $(abspath $(LOADDIRS))")
:rules (list (ede-makefile-rule :target "clean-autoloads" :phony t :rules '("rm -f $(LOADDEFS)")))
:sourcetype '(ede-source-emacs)
)
diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el
index 2803e1c3071..544e39b8729 100644
--- a/lisp/cedet/ede/project-am.el
+++ b/lisp/cedet/ede/project-am.el
@@ -191,8 +191,9 @@ other meta-variable based on this name.")
"Encode one makefile.")
;;; Code:
-(cl-defmethod project-add-file ((ot project-am-target))
+(cl-defmethod project-add-file ((ot project-am-target) &optional _file)
"Add the current buffer into a project.
+_FILE is ignored.
OT is the object target. DIR is the directory to start in."
(let* ((target (if ede-object (error "Already associated w/ a target")
(let ((amf (project-am-load default-directory)))
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index b1a4fe4d547..ce37a28c351 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -877,10 +877,9 @@ META-NAME is a cons (OVERLOADABLE-SYMBOL . MAJOR-MODE)."
"Display mode local bindings active in BUFFER-OR-MODE.
Optional argument INTERACTIVE-P is non-nil if the calling command was
invoked interactively."
- (when (fboundp 'help-setup-xref)
- (help-setup-xref
- (list 'mode-local-describe-bindings-1 buffer-or-mode)
- interactive-p))
+ (help-setup-xref
+ (list 'mode-local-describe-bindings-1 buffer-or-mode)
+ interactive-p)
(with-output-to-temp-buffer (help-buffer) ; "*Help*"
(with-current-buffer standard-output
(mode-local-describe-bindings-2 buffer-or-mode))))
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index dc6751db6cf..78002dd8abc 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -497,8 +497,8 @@ is requested."
(defvar semantic-working-type 'percent
"The type of working message to use when parsing.
-'percent means we are doing a linear parse through the buffer.
-'dynamic means we are reparsing specific tags.")
+`percent' means we are doing a linear parse through the buffer.
+`dynamic' means we are reparsing specific tags.")
(defvar semantic-minimum-working-buffer-size (* 1024 5)
"The minimum size of a buffer before working messages are displayed.
diff --git a/lisp/cedet/semantic/bovine/grammar.el b/lisp/cedet/semantic/bovine/grammar.el
index d478b12f645..67366ad445e 100644
--- a/lisp/cedet/semantic/bovine/grammar.el
+++ b/lisp/cedet/semantic/bovine/grammar.el
@@ -260,7 +260,8 @@ QUOTEMODE is the mode in which quoted symbols are slurred."
(insert ")\n")))
)
-(defun bovine-grammar-parsetable-builder ()
+(define-mode-local-override semantic-grammar-parsetable-builder
+ bovine-grammar-mode ()
"Return the parser table expression as a string value.
The format of a bovine parser table is:
@@ -409,7 +410,8 @@ The source directory is relative to some root in the load path."
newdir))
(error (buffer-name))))
-(defun bovine-grammar-setupcode-builder ()
+(define-mode-local-override semantic-grammar-setupcode-builder
+ bovine-grammar-mode ()
"Return the text of the setup code."
(format
"(setq semantic--parse-table %s\n\
@@ -435,10 +437,7 @@ Menu items are appended to the common grammar menu.")
;;;###autoload
(define-derived-mode bovine-grammar-mode semantic-grammar-mode "BY"
"Major mode for editing Bovine grammars."
- (semantic-grammar-setup-menu bovine-grammar-menu)
- (semantic-install-function-overrides
- '((semantic-grammar-parsetable-builder . bovine-grammar-parsetable-builder)
- (semantic-grammar-setupcode-builder . bovine-grammar-setupcode-builder))))
+ (semantic-grammar-setup-menu bovine-grammar-menu))
(add-to-list 'auto-mode-alist '("\\.by\\'" . bovine-grammar-mode))
@@ -461,7 +460,7 @@ Menu items are appended to the common grammar menu.")
(defun bovine--make-parser-1 (infile &optional outdir)
(if outdir (setq outdir (file-name-directory (expand-file-name outdir))))
;; It would be nicer to use a temp-buffer rather than find-file-noselect.
- ;; The only thing stopping us is bovine-grammar-setupcode-builder's
+ ;; The only thing stopping us is bovine's semantic-grammar-setupcode-builder's
;; use of (buffer-name). Perhaps that could be changed to
;; (file-name-nondirectory (buffer-file-name)) ?
;; (with-temp-buffer
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index 2c608fca38a..6a09adca32d 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -1761,7 +1761,8 @@ Return a cons cell (X . Y)."
(defvar tooltip-frame-parameters)
-(declare-function tooltip-show "tooltip" (text &optional use-echo-area))
+(declare-function tooltip-show "tooltip" (text &optional use-echo-area
+ text-face default-face))
(defun semantic-displayer-tooltip-show (text)
"Display a tooltip with TEXT near cursor."
diff --git a/lisp/cedet/semantic/db-el.el b/lisp/cedet/semantic/db-el.el
index 73ef37ea2aa..02ebde40785 100644
--- a/lisp/cedet/semantic/db-el.el
+++ b/lisp/cedet/semantic/db-el.el
@@ -213,9 +213,7 @@ TOKTYPE is a hint to the type of tag desired."
(symbol-name sym)
nil ;; return type
(semantic-elisp-desymbolify arglist)
- :user-visible-flag (condition-case nil
- (interactive-form sym)
- (error nil)))))
+ :user-visible-flag (commandp sym))))
((and (eq toktype 'variable) (boundp sym))
(semantic-tag-new-variable
(symbol-name sym)
diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el
index 7f25a848918..82785ec6d2e 100644
--- a/lisp/cedet/semantic/db.el
+++ b/lisp/cedet/semantic/db.el
@@ -729,7 +729,7 @@ Exit the save between databases if there is user input."
(defvar semanticdb-project-predicate-functions nil
"List of predicates to try that indicate a directory belongs to a project.
This list is used when `semanticdb-persistent-path' contains the value
-'project. If the predicate list is nil, then presume all paths are valid.
+`project'. If the predicate list is nil, then presume all paths are valid.
Project Management software (such as EDE and JDE) should add their own
predicates with `add-hook' to this variable, and semanticdb will save tag
diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el
index 76230d438a1..4679500ed99 100644
--- a/lisp/cedet/semantic/edit.el
+++ b/lisp/cedet/semantic/edit.el
@@ -610,7 +610,7 @@ This function is for internal use by `semantic-edits-incremental-parser'."
(setq last-cond "Beginning of buffer")
(setq parse-start
;; Don't worry about parents since
- ;; there there would be an exact
+ ;; there would be an exact
;; match in the tag list otherwise
;; and the routine would fail.
(point-min)
diff --git a/lisp/cedet/semantic/find.el b/lisp/cedet/semantic/find.el
index e894022315f..92644ce0066 100644
--- a/lisp/cedet/semantic/find.el
+++ b/lisp/cedet/semantic/find.el
@@ -591,7 +591,7 @@ in the new list.
If optional argument SEARCH-PARTS is non-nil, all sub-parts of tags
are searched. The overloadable function `semantic-tag-components' is
used for the searching child lists. If SEARCH-PARTS is the symbol
-'positiononly, then only children that have positional information are
+`positiononly', then only children that have positional information are
searched.
If SEARCH-INCLUDES has not been implemented.
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index fd61751cb50..113323cb339 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -191,12 +191,20 @@ will throw a warning when it encounters this symbol."
(not (string-match "cedet" (macroexp-file-name)))
)
(make-obsolete-overload oldfnalias newfn when)
- (byte-compile-warn
- "%s: `%s' obsoletes overload `%s'"
- (macroexp-file-name)
- newfn
- (with-suppressed-warnings ((obsolete semantic-overload-symbol-from-function))
- (semantic-overload-symbol-from-function oldfnalias)))))
+ (if (fboundp 'byte-compile-warn-x)
+ (byte-compile-warn-x
+ newfn
+ "%s: `%s' obsoletes overload `%s'"
+ (macroexp-file-name)
+ newfn
+ (with-suppressed-warnings ((obsolete semantic-overload-symbol-from-function))
+ (semantic-overload-symbol-from-function oldfnalias)))
+ (byte-compile-warn
+ "%s: `%s' obsoletes overload `%s'"
+ (macroexp-file-name)
+ newfn
+ (with-suppressed-warnings ((obsolete semantic-overload-symbol-from-function))
+ (semantic-overload-symbol-from-function oldfnalias))))))
(defun semantic-varalias-obsolete (oldvaralias newvar when)
"Make OLDVARALIAS an alias for variable NEWVAR.
@@ -209,10 +217,14 @@ will throw a warning when it encounters this symbol."
(error
;; Only throw this warning when byte compiling things.
(when (macroexp-compiling-p)
- (byte-compile-warn
- "variable `%s' obsoletes, but isn't alias of `%s'"
- newvar oldvaralias)
- ))))
+ (if (fboundp 'byte-compile-warn-x)
+ (byte-compile-warn-x
+ newvar
+ "variable `%s' obsoletes, but isn't alias of `%s'"
+ newvar oldvaralias)
+ (byte-compile-warn
+ "variable `%s' obsoletes, but isn't alias of `%s'"
+ newvar oldvaralias))))))
;;; Help debugging
;;
@@ -275,7 +287,8 @@ later installation should be done in MODE hook."
(cons (intern (format "semantic-%s" name)) (cdr e)))))
overrides)
(list 'constant-flag (not transient)
- 'override-flag t)))
+ 'override-flag t)
+ nil))
;;; User Interrupt handling
;;
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 74d4a229fac..97456265ead 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1123,8 +1123,6 @@ END is the limit of the search."
;;;; Define major mode
;;;;
-(define-obsolete-variable-alias 'semantic-grammar-syntax-table
- 'semantic-grammar-mode-syntax-table "24.1")
(defvar semantic-grammar-mode-syntax-table
(let ((table (make-syntax-table (standard-syntax-table))))
(modify-syntax-entry ?\: "." table) ;; COLON
@@ -1197,8 +1195,6 @@ END is the limit of the search."
semantic-grammar-mode-keywords-1
"Font Lock keywords used to highlight Semantic grammar buffers.")
-(define-obsolete-variable-alias 'semantic-grammar-map
- 'semantic-grammar-mode-map "24.1")
(defvar semantic-grammar-mode-map
(let ((km (make-sparse-keymap)))
diff --git a/lisp/cedet/semantic/html.el b/lisp/cedet/semantic/html.el
index 718ce3c4c74..00e19dbc892 100644
--- a/lisp/cedet/semantic/html.el
+++ b/lisp/cedet/semantic/html.el
@@ -82,6 +82,11 @@ or
tag :members (mapcar #'semantic-html-expand-tag chil)))
(car (semantic--tag-expand tag))))
+(define-mode-local-override semantic-tag-components html-mode (tag)
+ "Return components belonging to TAG."
+ ;; Keep this η-regexp because `semantic-html-components' is called
+ ;; from elsewhere.
+ (semantic-html-components tag))
(defun semantic-html-components (tag)
"Return components belonging to TAG."
(semantic-tag-get-attribute tag :members))
@@ -245,12 +250,7 @@ tag with greater section value than LEVEL is found."
senator-step-at-start-end-tag-classes '(section)
senator-step-at-tag-classes '(section)
semantic-stickyfunc-sticky-classes '(section)
- )
- (semantic-install-function-overrides
- '((semantic-tag-components . semantic-html-components)
- )
- t)
- )
+ ))
;; `html-helper-mode' hasn't been updated since 2004, so it's not very
;; relevant nowadays.
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index 235965a9955..37dc9632729 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -39,7 +39,8 @@
(require 'semantic/sort)
(require 'imenu)
-(declare-function pulse-momentary-highlight-one-line "pulse" (o &optional face))
+(declare-function pulse-momentary-highlight-one-line "pulse"
+ (&optional point face))
(declare-function semanticdb-semantic-init-hook-fcn "db-mode")
;; Because semantic imenu tags will hose the current imenu handling
diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el
index a7c02032e22..53fd4de2975 100644
--- a/lisp/cedet/semantic/java.el
+++ b/lisp/cedet/semantic/java.el
@@ -37,25 +37,24 @@
;;; Lexical analysis
;;
(defconst semantic-java-number-regexp
- (eval-when-compile
- (concat "\\("
- "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[.][fFdD]\\>"
- "\\|"
- "\\<[0-9]+[.]"
- "\\|"
- "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>"
- "\\|"
- "\\<0[xX][[:xdigit:]]+[lL]?\\>"
- "\\|"
- "\\<[0-9]+[lLfFdD]?\\>"
- "\\)"
- ))
+ (concat "\\("
+ "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[.][fFdD]\\>"
+ "\\|"
+ "\\<[0-9]+[.]"
+ "\\|"
+ "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>"
+ "\\|"
+ "\\<0[xX][[:xdigit:]]+[lL]?\\>"
+ "\\|"
+ "\\<[0-9]+[lLfFdD]?\\>"
+ "\\)"
+ )
"Lexer regexp to match Java number terminals.
Following is the specification of Java number literals.
@@ -391,7 +390,7 @@ That is TAG `symbol-name' without the leading `@'."
Return the list of FUN results. If optional PROPERTY is non-nil only
call FUN for javadoc keywords which have a value for PROPERTY. FUN
receives two arguments: the javadoc keyword and its associated
-'javadoc property list. It can return any value. All nil values are
+`javadoc' property list. It can return any value. All nil values are
removed from the result list."
(delq nil
(mapcar
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 26a3b39f0d6..4bdaaf77acf 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -726,7 +726,7 @@ Returns position with the end of that macro."
(point))))))
(defun semantic-lex-spp-get-overlay (&optional point)
- "Return first overlay which has a 'semantic-spp property."
+ "Return first overlay which has a `semantic-spp' property."
(let ((overlays (overlays-at (or point (point)))))
(while (and overlays
(null (overlay-get (car overlays) 'semantic-spp)))
@@ -1074,7 +1074,7 @@ and variable state from the current buffer."
))
;; Second Cheat: copy key variables regarding macro state from the
- ;; the originating buffer we are parsing. We need to do this every time
+ ;; originating buffer we are parsing. We need to do this every time
;; since the state changes.
(dolist (V important-vars)
(set V (buffer-local-value V origbuff)))
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index 885ffbf5a73..9c64cc9f7e5 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -574,25 +574,24 @@ may need to be overridden for some special languages.")
(defvar-local semantic-lex-number-expression
;; This expression was written by David Ponce for Java, and copied
;; here for C and any other similar language.
- (eval-when-compile
- (concat "\\("
- "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[.][fFdD]\\>"
- "\\|"
- "\\<[0-9]+[.]"
- "\\|"
- "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
- "\\|"
- "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>"
- "\\|"
- "\\<0[xX][[:xdigit:]]+[lL]?\\>"
- "\\|"
- "\\<[0-9]+[lLfFdD]?\\>"
- "\\)"
- ))
+ (concat "\\("
+ "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[.][fFdD]\\>"
+ "\\|"
+ "\\<[0-9]+[.]"
+ "\\|"
+ "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
+ "\\|"
+ "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>"
+ "\\|"
+ "\\<0[xX][[:xdigit:]]+[lL]?\\>"
+ "\\|"
+ "\\<[0-9]+[lLfFdD]?\\>"
+ "\\)"
+ )
"Regular expression for matching a number.
If this value is nil, no number extraction is done during lex.
This expression tries to match C and Java like numbers.
diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el
index ebc4159a4c5..1d16b024a5e 100644
--- a/lisp/cedet/semantic/senator.el
+++ b/lisp/cedet/semantic/senator.el
@@ -735,12 +735,9 @@ yanked to."
Optional argument KILL-FLAG will delete the text of the tag to the
kill ring.
-Interactively, reads the register using `register-read-with-preview',
-if available."
- (interactive (list (if (fboundp 'register-read-with-preview)
- (register-read-with-preview "Tag to register: ")
- (read-char "Tag to register: "))
- current-prefix-arg))
+Interactively, reads the register using `register-read-with-preview'."
+ (interactive (list (register-read-with-preview "Tag to register: ")
+ current-prefix-arg))
(semantic-fetch-tags)
(let ((ft (semantic-obtain-foreign-tag)))
(when ft
diff --git a/lisp/cedet/semantic/sort.el b/lisp/cedet/semantic/sort.el
index 1503a766dc8..756b949c0d1 100644
--- a/lisp/cedet/semantic/sort.el
+++ b/lisp/cedet/semantic/sort.el
@@ -310,7 +310,7 @@ may re-organize the list with side-effects."
;; class tag.
;;
(defvar-local semantic-orphaned-member-metaparent-type "class"
- "In `semantic-adopt-external-members', the type of 'type for metaparents.
+ "In `semantic-adopt-external-members', the type of `type' for metaparents.
A metaparent is a made-up type semantic token used to hold the child list
of orphaned members of a named type.")
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index ba236059f66..e48cefa4ca6 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -101,7 +101,7 @@ Where PREDICATE is a function that takes a directory name for the
root of a project, and returns non-nil if the tool represented by KEY
is supported.
-If no tools are supported, then 'grep is assumed.")
+If no tools are supported, then `grep' is assumed.")
(defun semantic-symref-calculate-rootdir ()
"Calculate the root directory for a symref search.
@@ -475,7 +475,7 @@ already."
Return the Semantic tag associated with HIT.
SEARCHTXT is the text that is being searched for.
Used to narrow the in-buffer search.
-SEARCHTYPE is the type of search (such as 'symbol or 'tagname).
+SEARCHTYPE is the type of search (such as `symbol' or `tagname').
If there is no database, or if the searchtype is wrong, return nil."
;; Allowed search types for this mechanism:
;; tagname, tagregexp, tagcompletions
@@ -506,7 +506,7 @@ If there is no database, or if the searchtype is wrong, return nil."
Return the Semantic tag associated with HIT.
SEARCHTXT is the text that is being searched for.
Used to narrow the in-buffer search.
-SEARCHTYPE is the type of search (such as 'symbol or 'tagname).
+SEARCHTYPE is the type of search (such as `symbol' or `tagname').
Optional OPEN-BUFFERS, when nil will use a faster version of
`find-file' when a file needs to be opened. If non-nil, then
normal buffer initialization will be used.
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index 1917bcb40a6..d005b7a854c 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -55,20 +55,17 @@ The field position is the field number (based at 1) where the
name of this section is.")
;;; Code:
-(defun semantic-texi-parse-region (&rest _ignore)
+(define-mode-local-override semantic-parse-region texinfo-mode (&rest _ignore)
"Parse the current texinfo buffer for semantic tags.
IGNORE any arguments, always parse the whole buffer.
Each tag returned is of the form:
(\"NAME\" section (:members CHILDREN))
or
- (\"NAME\" def)
-
-It is an override of `semantic-parse-region' and must be installed by the
-function `semantic-install-function-overrides'."
+ (\"NAME\" def)"
(mapcar #'semantic-texi-expand-tag
(semantic-texi-parse-headings)))
-(defun semantic-texi-parse-changes ()
+(define-mode-local-override semantic-parse-changes texinfo-mode ()
"Parse changes in the current texinfo buffer."
;; NOTE: For now, just schedule a full reparse.
;; To be implemented later.
@@ -445,9 +442,6 @@ that start with that symbol."
(defun semantic-default-texi-setup ()
"Set up a buffer for parsing of Texinfo files."
;; This will use our parser.
- (semantic-install-function-overrides
- '((semantic-parse-region . semantic-texi-parse-region)
- (semantic-parse-changes . semantic-texi-parse-changes)))
(setq semantic-parser-name "TEXI"
;; Setup a dummy parser table to enable parsing!
semantic--parse-table t
diff --git a/lisp/cedet/semantic/wisent/comp.el b/lisp/cedet/semantic/wisent/comp.el
index f842b3c364b..ba67d250604 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -65,6 +65,7 @@
(defmacro wisent-defcontext (name &rest vars)
"Define a context NAME that will bind variables VARS."
(declare (indent 1))
+ (declare-function wisent-context-name nil (name))
(let* ((context (wisent-context-name name))
(declarations (mapcar (lambda (v) (list 'defvar v)) vars)))
`(progn
@@ -75,6 +76,7 @@
(defmacro wisent-with-context (name &rest body)
"Bind variables in context NAME then eval BODY."
(declare (indent 1))
+ (declare-function wisent-context-bindings nil (name))
`(dlet ,(wisent-context-bindings name)
,@body))
diff --git a/lisp/cedet/semantic/wisent/grammar.el b/lisp/cedet/semantic/wisent/grammar.el
index 5ca22bac86c..a4104e333d3 100644
--- a/lisp/cedet/semantic/wisent/grammar.el
+++ b/lisp/cedet/semantic/wisent/grammar.el
@@ -284,13 +284,15 @@ Return the expanded expression."
(assocs (wisent-grammar-assocs)))
(cons terminals (cons assocs nonterminals))))
-(defun wisent-grammar-parsetable-builder ()
+(define-mode-local-override semantic-grammar-parsetable-builder
+ wisent-grammar-mode ()
"Return the value of the parser table."
`(wisent-compiled-grammar
,(wisent-grammar-grammar)
,(semantic-grammar-start)))
-(defun wisent-grammar-setupcode-builder ()
+(define-mode-local-override semantic-grammar-setupcode-builder
+ wisent-grammar-mode ()
"Return the parser setup code."
(format
"(semantic-install-function-overrides\n\
@@ -322,10 +324,7 @@ Menu items are appended to the common grammar menu.")
(define-derived-mode wisent-grammar-mode semantic-grammar-mode "WY"
"Major mode for editing Wisent grammars."
(semantic-grammar-setup-menu wisent-grammar-menu)
- (setq-local semantic-grammar-require-form '(require 'semantic/wisent))
- (semantic-install-function-overrides
- '((semantic-grammar-parsetable-builder . wisent-grammar-parsetable-builder)
- (semantic-grammar-setupcode-builder . wisent-grammar-setupcode-builder))))
+ (setq-local semantic-grammar-require-form '(require 'semantic/wisent)))
(defvar-mode-local wisent-grammar-mode semantic-grammar-macros
'(
diff --git a/lisp/cedet/srecode/texi.el b/lisp/cedet/srecode/texi.el
index 50b0e150ff3..c297429e408 100644
--- a/lisp/cedet/srecode/texi.el
+++ b/lisp/cedet/srecode/texi.el
@@ -246,7 +246,7 @@ that class.
class => @code{class} @xref{class}
unknown => @code{unknown}
\"text\" => \\=`\\=`text\\='\\='
- 'quoteme => @code{quoteme}
+ \\='quoteme => @code{quoteme}
non-nil => non-@code{nil}
t => @code{t}
:tag => @code{:tag}
diff --git a/lisp/chistory.el b/lisp/chistory.el
index dd0f4997433..9dce60a19fe 100644
--- a/lisp/chistory.el
+++ b/lisp/chistory.el
@@ -119,8 +119,6 @@ The buffer is left in Command History mode."
(error "No command history")
(command-history-mode)))))
-(define-obsolete-variable-alias 'command-history-map
- 'command-history-mode-map "24.1")
(defvar command-history-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map (make-composed-keymap lisp-mode-shared-map
@@ -165,11 +163,11 @@ The buffer for that command is the previous current buffer."
"Examine commands from variable `command-history' in a buffer.
The number of commands listed is controlled by `list-command-history-max'.
The command history is filtered by `list-command-history-filter' if non-nil.
-Use \\<command-history-map>\\[command-history-repeat] to repeat the command on the current line.
+Use \\<command-history-mode-map>\\[command-history-repeat] to repeat the command on the current line.
Otherwise much like Emacs-Lisp Mode except that there is no self-insertion
and digits provide prefix arguments. Tab does not indent.
-\\{command-history-map}
+\\{command-history-mode-map}
This command always recompiles the Command History listing
and runs the normal hook `command-history-hook'."
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index e64d9d28dd6..22a465f5b61 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -195,6 +195,7 @@ to continue it."
(scheme-mode-variables)
(setq mode-line-process '(":%s"))
(setq comint-input-filter (function scheme-input-filter))
+ (setq-local comint-prompt-read-only t)
(setq comint-get-old-input (function scheme-get-old-input)))
(defcustom inferior-scheme-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
diff --git a/lisp/color.el b/lisp/color.el
index 0fe663d97a7..410659869ae 100644
--- a/lisp/color.el
+++ b/lisp/color.el
@@ -39,6 +39,10 @@
COLOR should be a color name (e.g. \"white\") or an RGB triplet
string (e.g. \"#ffff1122eecc\").
+COLOR can also be the symbol `unspecified' or one of the strings
+\"unspecified-fg\" or \"unspecified-bg\", in which case the
+return value is nil.
+
Normally the return value is a list of three floating-point
numbers, (RED GREEN BLUE), each between 0.0 and 1.0 inclusive.
@@ -403,7 +407,7 @@ See `color-desaturate-hsl'."
Given a color defined in terms of hue, saturation, and luminance
\(arguments H, S, and L), return a color that is PERCENT lighter.
Returns a list (HUE SATURATION LUMINANCE)."
- (list H S (color-clamp (+ L (/ percent 100.0)))))
+ (list H S (color-clamp (+ L (* L (/ percent 100.0))))))
(defun color-lighten-name (name percent)
"Make a color with a specified NAME lighter by PERCENT.
diff --git a/lisp/comint.el b/lisp/comint.el
index fdea3e33bb4..d52623c00ae 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -330,12 +330,12 @@ This variable is buffer-local in all Comint buffers."
"The maximum size in lines for Comint buffers.
Comint buffers are truncated from the top to be no greater than this number, if
the function `comint-truncate-buffer' is on `comint-output-filter-functions'."
- :type 'integer
+ :type 'natnum
:group 'comint)
(defcustom comint-input-ring-size 500
"Size of the input history ring in `comint-mode'."
- :type 'integer
+ :type 'natnum
:group 'comint
:version "23.2")
@@ -1110,7 +1110,8 @@ See also `comint-read-input-ring'."
(use-local-map keymap))
(forward-line 3)
(while (search-backward "completion" nil 'move)
- (replace-match "history reference")))
+ (replace-match (apply #'propertize "history reference"
+ (text-properties-at (point))))))
(sit-for 0)
(message "Hit space to flush")
(setq comint-dynamic-list-input-ring-window-conf conf)
@@ -1465,7 +1466,7 @@ A useful command to bind to SPC. See `comint-replace-by-expanded-history'."
(defcustom comint-history-isearch nil
"Non-nil to Isearch in input history only, not in comint buffer output.
-If t, usual Isearch keys like `C-r' and `C-M-r' in comint mode search
+If t, usual Isearch keys like \\`C-r' and \\`C-M-r' in comint mode search
in the input history.
If `dwim', Isearch keys search in the input history only when initial
point position is at the comint command line. When starting Isearch
@@ -1515,6 +1516,7 @@ Intended to be added to `isearch-mode-hook' in `comint-mode'."
#'comint-history-isearch-wrap)
(setq-local isearch-push-state-function
#'comint-history-isearch-push-state)
+ (setq-local isearch-lazy-count nil)
(add-hook 'isearch-mode-end-hook 'comint-history-isearch-end nil t)))
(defun comint-history-isearch-end ()
@@ -1526,6 +1528,7 @@ Intended to be added to `isearch-mode-hook' in `comint-mode'."
(setq isearch-message-function nil)
(setq isearch-wrap-function nil)
(setq isearch-push-state-function nil)
+ (kill-local-variable 'isearch-lazy-count)
(remove-hook 'isearch-mode-end-hook 'comint-history-isearch-end t)
(unless isearch-suspended
(custom-reevaluate-setting 'comint-history-isearch)))
@@ -2512,8 +2515,9 @@ This function could be in the list `comint-output-filter-functions'."
(1+ comint--prompt-recursion-depth)))
(if (> comint--prompt-recursion-depth 10)
(message "Password prompt recursion too deep")
- (comint-send-invisible
- (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+"))))))
+ (when (get-buffer-process (current-buffer))
+ (comint-send-invisible
+ (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+")))))))
(current-buffer))))
;; Low-level process communication
@@ -2808,7 +2812,7 @@ Interactively, if no prefix argument is given, the last argument is inserted.
Repeated interactive invocations will cycle through the same argument
from progressively earlier commands (using the value of INDEX specified
with the first command). Values of INDEX < 0 count from the end, so
-INDEX = -1 is the last argument. This command is like `M-.' in
+INDEX = -1 is the last argument. This command is like \"M-.\" in
Bash and zsh."
(interactive "P")
(unless (null index)
@@ -3191,8 +3195,8 @@ inside of a \"[...]\" (see `skip-chars-forward'), plus all non-ASCII characters.
(while (not giveup)
(let ((startpoint (point)))
(skip-chars-backward (concat "\\\\" word-chars))
- (if (and comint-file-name-quote-list
- (eq (char-before (1- (point))) ?\\))
+ (if (and (eq (char-before (1- (point))) ?\\)
+ (memq (char-before) comint-file-name-quote-list))
(forward-char -2))
;; FIXME: This isn't consistent with Bash, at least -- not
;; all non-ASCII chars should be word constituents.
@@ -3295,10 +3299,6 @@ Magic characters are those in `comint-file-name-quote-list'."
(defun comint-completion-at-point ()
(run-hook-with-args-until-success 'comint-dynamic-complete-functions))
-(define-obsolete-function-alias
- 'comint-dynamic-complete
- 'completion-at-point "24.1")
-
(defun comint-dynamic-complete-filename ()
"Dynamically complete the filename at point.
Completes if after a filename.
@@ -3379,13 +3379,6 @@ See `completion-table-with-quoting' and `comint-unquote-function'.")
(goto-char (match-end 0))
(insert filesuffix)))))))))
-(defun comint-dynamic-complete-as-filename ()
- "Dynamically complete at point as a filename.
-See `comint-dynamic-complete-filename'. Returns t if successful."
- (declare (obsolete comint-filename-completion "24.1"))
- (let ((data (comint--complete-file-name-data)))
- (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data))))
-
(defun comint-replace-by-expanded-filename ()
"Dynamically expand and complete the filename at point.
Replace the filename with an expanded, canonicalized and
@@ -3400,65 +3393,6 @@ filename absolute. For expansion see `expand-file-name' and
(replace-match (expand-file-name filename) t t)
(comint-dynamic-complete-filename))))
-
-(defun comint-dynamic-simple-complete (stub candidates)
- "Dynamically complete STUB from CANDIDATES list.
-This function inserts completion characters at point by
-completing STUB from the strings in CANDIDATES. If completion is
-ambiguous, possibly show a completions listing in a separate
-buffer.
-
-Return nil if no completion was inserted.
-Return `sole' if completed with the only completion match.
-Return `shortest' if completed with the shortest match.
-Return `partial' if completed as far as possible.
-Return `listed' if a completion listing was shown.
-
-See also `comint-dynamic-complete-filename'."
- (declare (obsolete completion-in-region "24.1"))
- (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt cygwin)))
- (minibuffer-p (window-minibuffer-p))
- (suffix (cond ((not comint-completion-addsuffix) "")
- ((not (consp comint-completion-addsuffix)) " ")
- (t (cdr comint-completion-addsuffix))))
- (completions (all-completions stub candidates)))
- (cond ((null completions)
- (if minibuffer-p
- (minibuffer-message "No completions of %s" stub)
- (message "No completions of %s" stub))
- nil)
- ((= 1 (length completions)) ; Gotcha!
- (let ((completion (car completions)))
- (if (string-equal completion stub)
- (unless minibuffer-p
- (message "Sole completion"))
- (insert (substring completion (length stub)))
- (unless minibuffer-p
- (message "Completed")))
- (insert suffix)
- 'sole))
- (t ; There's no unique completion.
- (let ((completion (try-completion stub candidates)))
- ;; Insert the longest substring.
- (insert (substring completion (length stub)))
- (cond ((and comint-completion-recexact comint-completion-addsuffix
- (string-equal stub completion)
- (member completion completions))
- ;; It's not unique, but user wants shortest match.
- (insert suffix)
- (unless minibuffer-p
- (message "Completed shortest"))
- 'shortest)
- ((or comint-completion-autolist
- (string-equal stub completion))
- ;; It's not unique, list possible completions.
- (comint-dynamic-list-completions completions stub)
- 'listed)
- (t
- (unless minibuffer-p
- (message "Partially completed"))
- 'partial)))))))
-
(defun comint-dynamic-list-filename-completions ()
"Display a list of possible completions for the filename at point."
(interactive)
@@ -3975,10 +3909,12 @@ REGEXP-GROUP is the regular expression group in REGEXP to use."
;;; OSC escape sequences (Operating System Commands)
;;============================================================================
-;; Adding `comint-osc-process-output' to `comint-output-filter-functions'
-;; enables the interpretation of OSC escape sequences. By default, only
-;; OSC 8, for hyperlinks, is acted upon. Adding more entries to
-;; `comint-osc-handlers' allows a customized treatment of further sequences.
+;; Adding `comint-osc-process-output' to
+;; `comint-output-filter-functions' enables the interpretation of OSC
+;; escape sequences. By default, OSC 7 and 8 (for current directory
+;; and hyperlinks respectively) are acted upon. Adding more entries
+;; to `comint-osc-handlers' allows a customized treatment of further
+;; sequences.
(defvar-local comint-osc-handlers '(("7" . comint-osc-directory-tracker)
("8" . comint-osc-hyperlink-handler))
@@ -4023,9 +3959,9 @@ arguments, with point where the escape sequence was located."
;; Current directory tracking (OSC 7)
-(declare-function url-host "url-parse.el")
-(declare-function url-type "url-parse.el")
-(declare-function url-filename "url-parse.el")
+(declare-function url-host "url/url-parse.el")
+(declare-function url-type "url/url-parse.el")
+(declare-function url-filename "url/url-parse.el")
(defun comint-osc-directory-tracker (_ text)
"Update `default-directory' from OSC 7 escape sequences.
diff --git a/lisp/composite.el b/lisp/composite.el
index d7ac75708c9..6fcf637584e 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -474,6 +474,25 @@ after a sequence of character events."
(aset gstring (1- len) nil))
gstring)
+(defun lgstring-glyph-boundary (gstring startpos endpos)
+ "Return buffer position at or after ENDPOS where grapheme from GSTRING ends.
+STARTPOS is the position where the grapheme cluster starts; it is returned
+by `find-composition'."
+ (let ((nglyphs (lgstring-glyph-len gstring))
+ (idx 0)
+ glyph found)
+ (while (and (not found) (< idx nglyphs))
+ (setq glyph (lgstring-glyph gstring idx))
+ (cond
+ ((or (null glyph)
+ (= (+ startpos (lglyph-from glyph)) endpos))
+ (setq found endpos))
+ ((>= (+ startpos (lglyph-to glyph)) endpos)
+ (setq found (+ startpos (lglyph-to glyph) 1)))
+ (t
+ (setq idx (1+ idx)))))
+ (or found endpos)))
+
(defun compose-glyph-string (gstring from to)
(let ((glyph (lgstring-glyph gstring from))
from-pos to-pos)
diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el
index 87dcbbb004f..47d2cac3be1 100644
--- a/lisp/cus-dep.el
+++ b/lisp/cus-dep.el
@@ -156,9 +156,9 @@ Usage: emacs -batch -l ./cus-dep.el -f custom-make-dependencies DIRS"
(set-buffer (find-file-noselect generated-custom-dependencies-file))
(setq buffer-undo-list t)
(erase-buffer)
- (insert (autoload-rubric generated-custom-dependencies-file
- "custom dependencies" t))
- (search-backward " ")
+ (generate-lisp-file-heading
+ generated-custom-dependencies-file 'custom-make-dependencies
+ :title "custom dependencies")
(let (alist)
(mapatoms (lambda (symbol)
(let ((members (get symbol 'custom-group))
@@ -241,6 +241,7 @@ This is an alist whose members have as car a version string, and as
elements the files that have variables or faces that contain that
version. These files should be loaded before showing the customization
buffer that `customize-changed' generates.\")\n\n"))
+ (generate-lisp-file-trailer generated-custom-dependencies-file)
(save-buffer)
(byte-compile-info
(format "Generating %s...done" generated-custom-dependencies-file) t))
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 3e350c611a3..50dce5ee285 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -441,6 +441,7 @@ Use group `text' for this instead. This group is deprecated."
(define-key map "u" 'Custom-goto-parent)
(define-key map "n" 'widget-forward)
(define-key map "p" 'widget-backward)
+ (define-key map "H" 'custom-toggle-hide-all-widgets)
map)
"Keymap for `Custom-mode'.")
@@ -745,6 +746,9 @@ groups after non-groups, if nil do not order groups at all."
(or custom-file user-init-file)
"Un-customize settings in this and future sessions." "delete" "Uncustomize"
(modified set changed rogue saved))
+ (" Toggle hiding all values " custom-toggle-hide-all-widgets
+ t "Toggle hiding all values."
+ "hide" "Hide" t)
(" Help for Customize " Custom-help t "Get help for using Customize."
"help" "Help" t)
(" Exit " Custom-buffer-done t "Exit Customize." "exit" "Exit" t))
@@ -1045,6 +1049,36 @@ If given a prefix (or a COMMENT argument), also prompt for a comment."
value)
;;;###autoload
+(defmacro setopt (&rest pairs)
+ "Set VARIABLE/VALUE pairs, and return the final VALUE.
+This is like `setq', but is meant for user options instead of
+plain variables. This means that `setopt' will execute any
+`custom-set' form associated with VARIABLE.
+
+\(fn [VARIABLE VALUE]...)"
+ (declare (debug setq))
+ (unless (zerop (mod (length pairs) 2))
+ (error "PAIRS must have an even number of variable/value members"))
+ (let ((expr nil))
+ (while pairs
+ (unless (symbolp (car pairs))
+ (error "Attempting to set a non-symbol: %s" (car pairs)))
+ (push `(setopt--set ',(car pairs) ,(cadr pairs))
+ expr)
+ (setq pairs (cddr pairs)))
+ (macroexp-progn (nreverse expr))))
+
+;;;###autoload
+(defun setopt--set (variable value)
+ (custom-load-symbol variable)
+ ;; Check that the type is correct.
+ (when-let ((type (get variable 'custom-type)))
+ (unless (widget-apply (widget-convert type) :match value)
+ (user-error "Value `%S' does not match type %s" value type)))
+ (put variable 'custom-check-value (list value))
+ (funcall (or (get variable 'custom-set) #'set-default) variable value))
+
+;;;###autoload
(defun customize-save-variable (variable value &optional comment)
"Set the default for VARIABLE to VALUE, and save it for future sessions.
Return VALUE.
@@ -1465,7 +1499,7 @@ symbols `custom-face' or `custom-variable'."
(custom-buffer-create (custom-sort-items found t nil)
"*Customize Saved*"))))
-(declare-function apropos-parse-pattern "apropos" (pattern))
+(declare-function apropos-parse-pattern "apropos" (pattern &optional di-all))
(defvar apropos-regexp)
;;;###autoload
@@ -1531,12 +1565,12 @@ If TYPE is `groups', include only groups."
;;;###autoload
(defun custom-prompt-customize-unsaved-options ()
"Prompt user to customize any unsaved customization options.
-Return non-nil if user chooses to customize, for use in
+Return nil if user chooses to customize, for use in
`kill-emacs-query-functions'."
(not (and (custom-unsaved-options)
- (yes-or-no-p "Some customized options have not been saved; Examine? ")
- (customize-unsaved)
- t)))
+ (yes-or-no-p
+ "Some customized options have not been saved; Examine? ")
+ (progn (customize-unsaved) t))))
;;; Buffer.
@@ -2550,7 +2584,13 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
Normally just return the docstring. But if VARIABLE automatically
becomes buffer local when set, append a message to that effect.
Also append any obsolescence information."
- (format "%s%s%s" (documentation-property variable 'variable-documentation t)
+ (format "%s%s%s"
+ (with-temp-buffer
+ (insert
+ (or (documentation-property variable 'variable-documentation t)
+ ""))
+ (untabify (point-min) (point-max))
+ (buffer-string))
(if (and (local-variable-if-set-p variable)
(or (not (local-variable-p variable))
(with-temp-buffer
@@ -2805,6 +2845,39 @@ try matching its doc string against `custom-guess-doc-alist'."
(custom-add-parent-links widget))
(custom-add-see-also widget)))))
+(defvar custom--hidden-state)
+
+(defun custom-toggle-hide-all-widgets ()
+ "Hide or show details of all customizable settings in a Custom buffer.
+This command is for use in a Custom buffer that shows many
+customizable settings, like \"*Customize Group*\" or \"*Customize Faces*\".
+It toggles the display of each of the customizable settings in the buffer
+between the expanded view, where the values of the settings and the value
+menus to change them are visible; and the concise view, where only the
+minimal details are shown, usually the name, the doc string and little
+else."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ ;; Surely there's a better way to find all the "top level" widgets
+ ;; in a buffer, but I couldn't find it.
+ (while (not (eobp))
+ (when-let* ((widget (widget-at (point)))
+ (parent (widget-get widget :parent))
+ (state (widget-get parent :custom-state)))
+ (when (eq state 'changed)
+ (setq state 'standard))
+ (when (and (eq (widget-type widget) 'custom-visibility)
+ (eq state custom--hidden-state))
+ (custom-toggle-parent widget)))
+ (forward-line 1)))
+ (setq custom--hidden-state (if (eq custom--hidden-state 'hidden)
+ 'standard
+ 'hidden))
+ (if (eq custom--hidden-state 'hidden)
+ (message "All variables hidden")
+ (message "All variables shown")))
+
(defun custom-toggle-hide-variable (visibility-widget &rest _ignore)
"Toggle the visibility of a `custom-variable' parent widget.
By default, this signals an error if the parent has unsaved
@@ -3976,6 +4049,18 @@ Optional EVENT is the location for the menu."
(setq comment nil)
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
+ ;; When modifying the default face, we need to save the standard or themed
+ ;; attrs, in case the user asks to revert to them in the future.
+ ;; In GUIs, when resetting the attributes of the default face, the frame
+ ;; parameters associated with this face won't change, unless explicitly
+ ;; passed a value. Storing this known attrs allows us to tell faces.el to
+ ;; set those attributes to specified values, making the relevant frame
+ ;; parameters stay in sync with the default face.
+ (when (and (eq symbol 'default)
+ (not (get symbol 'custom-face-default-attrs))
+ (memq (custom-face-state symbol) '(standard themed)))
+ (put symbol 'custom-face-default-attrs
+ (custom-face-get-current-spec symbol)))
(custom-push-theme 'theme-face symbol 'user 'set value)
(face-spec-set symbol value 'customized-face)
(put symbol 'face-comment comment)
@@ -3994,6 +4079,12 @@ Optional EVENT is the location for the menu."
(setq comment nil)
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
+ ;; See the comments in `custom-face-set'.
+ (when (and (eq symbol 'default)
+ (not (get symbol 'custom-face-default-attrs))
+ (memq (custom-face-state symbol) '(standard themed)))
+ (put symbol 'custom-face-default-attrs
+ (custom-face-get-current-spec symbol)))
(custom-push-theme 'theme-face symbol 'user 'set value)
(face-spec-set symbol value (if standard 'reset 'saved-face))
(put symbol 'face-comment comment)
@@ -4007,7 +4098,14 @@ Optional EVENT is the location for the menu."
(defun custom-face-save (widget)
"Save the face edited by WIDGET."
- (let ((form (widget-get widget :custom-form)))
+ (let ((form (widget-get widget :custom-form))
+ (symbol (widget-value widget)))
+ ;; See the comments in `custom-face-set'.
+ (when (and (eq symbol 'default)
+ (not (get symbol 'custom-face-default-attrs))
+ (memq (custom-face-state symbol) '(standard themed)))
+ (put symbol 'custom-face-default-attrs
+ (custom-face-get-current-spec symbol)))
(if (memq form '(all lisp))
(custom-face-mark-to-save widget)
;; The user is working on only a selected terminal type;
@@ -4035,10 +4133,20 @@ uncustomized (themed or standard) face."
(saved-face (get face 'saved-face))
(comment (get face 'saved-face-comment))
(comment-widget (widget-get widget :comment-widget)))
+ ;; If resetting the default face and there isn't a saved value,
+ ;; push a fake user setting, so that reverting to the default
+ ;; attributes works.
(custom-push-theme 'theme-face face 'user
- (if saved-face 'set 'reset)
- saved-face)
+ (if (or saved-face (eq face 'default)) 'set 'reset)
+ (or saved-face
+ ;; If this is t, then MODE is 'reset,
+ ;; and `custom-push-theme' ignores this argument.
+ (not (eq face 'default))
+ (get face 'custom-face-default-attrs)))
(face-spec-set face saved-face 'saved-face)
+ (when (and (not saved-face) (eq face 'default))
+ ;; Remove the fake user setting.
+ (custom-push-theme 'theme-face face 'user 'reset))
(put face 'face-comment comment)
(put face 'customized-face-comment nil)
(widget-value-set child saved-face)
@@ -4060,8 +4168,15 @@ redraw the widget immediately."
(comment-widget (widget-get widget :comment-widget)))
(unless value
(user-error "No standard setting for this face"))
- (custom-push-theme 'theme-face symbol 'user 'reset)
+ ;; If erasing customizations for the default face, push a fake user setting,
+ ;; so that reverting to the default attributes works.
+ (custom-push-theme 'theme-face symbol 'user
+ (if (eq symbol 'default) 'set 'reset)
+ (or (not (eq symbol 'default))
+ (get symbol 'custom-face-default-attrs)))
(face-spec-set symbol value 'reset)
+ ;; Remove the fake user setting.
+ (custom-push-theme 'theme-face symbol 'user 'reset)
(put symbol 'face-comment nil)
(put symbol 'customized-face-comment nil)
(if (and custom-reset-standard-faces-list
@@ -4727,7 +4842,11 @@ if only the first line of the docstring is shown."))
(delay-mode-hooks (emacs-lisp-mode)))
(let ((inhibit-read-only t)
(print-length nil)
- (print-level nil))
+ (print-level nil)
+ ;; We might be saving byte-code with embedded NULs, which
+ ;; can cause problems when read back, so print them
+ ;; readably. (Bug#52554)
+ (print-escape-control-characters t))
(atomic-change-group
(custom-save-variables)
(custom-save-faces)))
@@ -5155,7 +5274,8 @@ if that value is non-nil."
:label (nth 5 arg)))
custom-commands)
(setq custom-tool-bar-map map))))
- (setq-local custom--invocation-options nil)
+ (setq-local custom--invocation-options nil
+ custom--hidden-state 'hidden)
(setq-local revert-buffer-function #'custom--revert-buffer)
(make-local-variable 'custom-options)
(make-local-variable 'custom-local-buffer)
diff --git a/lisp/cus-face.el b/lisp/cus-face.el
index fa6d940d7c1..73a33f064c8 100644
--- a/lisp/cus-face.el
+++ b/lisp/cus-face.el
@@ -46,7 +46,7 @@
;;; Face attributes.
(defconst custom-face-attributes
- '((:family
+ `((:family
(string :tag "Font Family"
:help-echo "Font family or fontset alias name."))
@@ -83,9 +83,9 @@
(:height
(choice :tag "Height"
- :help-echo "Face's font height."
+ :help-echo "Face's font size."
:value 1.0 ; default
- (integer :tag "Height in 1/10 pt")
+ (integer :tag "Font size in 1/10 pt")
(number :tag "Scale" 1.0)))
(:weight
@@ -133,7 +133,7 @@
:help-echo "Control text underlining."
(const :tag "Off" nil)
(list :tag "On"
- :value (:color foreground-color :style line)
+ :value (:color foreground-color :style line :position nil)
(const :format "" :value :color)
(choice :tag "Color"
(const :tag "Foreground Color" foreground-color)
@@ -141,28 +141,36 @@
(const :format "" :value :style)
(choice :tag "Style"
(const :tag "Line" line)
- (const :tag "Wave" wave))))
+ (const :tag "Wave" wave))
+ (const :format "" :value :position)
+ (choice :tag "Position"
+ (const :tag "At Default Position" nil)
+ (const :tag "At Bottom Of Text" t)
+ (integer :tag "Pixels Above Bottom Of Text"))))
;; filter to make value suitable for customize
- (lambda (real-value)
- (and real-value
- (let ((color
- (or (and (consp real-value) (plist-get real-value :color))
- (and (stringp real-value) real-value)
- 'foreground-color))
- (style
- (or (and (consp real-value) (plist-get real-value :style))
- 'line)))
- (list :color color :style style))))
+ ,(lambda (real-value)
+ (and real-value
+ (let ((color
+ (or (and (consp real-value) (plist-get real-value :color))
+ (and (stringp real-value) real-value)
+ 'foreground-color))
+ (style
+ (or (and (consp real-value) (plist-get real-value :style))
+ 'line))
+ (position (and (consp real-value)
+ (plist-get real-value :style))))
+ (list :color color :style style :position position))))
;; filter to make customized-value suitable for storing
- (lambda (cus-value)
- (and cus-value
- (let ((color (plist-get cus-value :color))
- (style (plist-get cus-value :style)))
- (cond ((eq style 'line)
- ;; Use simple value for default style
- (if (eq color 'foreground-color) t color))
- (t
- `(:color ,color :style ,style)))))))
+ ,(lambda (cus-value)
+ (and cus-value
+ (let ((color (plist-get cus-value :color))
+ (style (plist-get cus-value :style))
+ (position (plist-get cus-value :position)))
+ (cond ((and (eq style 'line) (not position))
+ ;; Use simple value for default style
+ (if (eq color 'foreground-color) t color))
+ (t
+ `(:color ,color :style ,style :position ,position)))))))
(:overline
(choice :tag "Overline"
@@ -198,40 +206,40 @@
(const :tag "Flat" flat-button)
(const :tag "None" nil))))
;; filter to make value suitable for customize
- (lambda (real-value)
- (and real-value
- (let ((lwidth
- (or (and (consp real-value)
- (if (listp (cdr real-value))
- (plist-get real-value :line-width)
- real-value))
- (and (integerp real-value) real-value)
- '(1 . 1)))
- (color
- (or (and (consp real-value) (plist-get real-value :color))
- (and (stringp real-value) real-value)
- nil))
- (style
- (and (consp real-value) (plist-get real-value :style))))
- (if (integerp lwidth)
- (setq lwidth (cons (abs lwidth) lwidth)))
- (list :line-width lwidth :color color :style style))))
+ ,(lambda (real-value)
+ (and real-value
+ (let ((lwidth
+ (or (and (consp real-value)
+ (if (listp (cdr real-value))
+ (plist-get real-value :line-width)
+ real-value))
+ (and (integerp real-value) real-value)
+ '(1 . 1)))
+ (color
+ (or (and (consp real-value) (plist-get real-value :color))
+ (and (stringp real-value) real-value)
+ nil))
+ (style
+ (and (consp real-value) (plist-get real-value :style))))
+ (if (integerp lwidth)
+ (setq lwidth (cons (abs lwidth) lwidth)))
+ (list :line-width lwidth :color color :style style))))
;; filter to make customized-value suitable for storing
- (lambda (cus-value)
- (and cus-value
- (let ((lwidth (plist-get cus-value :line-width))
- (color (plist-get cus-value :color))
- (style (plist-get cus-value :style)))
- (cond ((and (null color) (null style))
- lwidth)
- ((and (null lwidth) (null style))
- ;; actually can't happen, because LWIDTH is always an int
- color)
- (t
- ;; Keep as a plist, but remove null entries
- (nconc (and lwidth `(:line-width ,lwidth))
- (and color `(:color ,color))
- (and style `(:style ,style)))))))))
+ ,(lambda (cus-value)
+ (and cus-value
+ (let ((lwidth (plist-get cus-value :line-width))
+ (color (plist-get cus-value :color))
+ (style (plist-get cus-value :style)))
+ (cond ((and (null color) (null style))
+ lwidth)
+ ((and (null lwidth) (null style))
+ ;; actually can't happen, because LWIDTH is always an int
+ color)
+ (t
+ ;; Keep as a plist, but remove null entries
+ (nconc (and lwidth `(:line-width ,lwidth))
+ (and color `(:color ,color))
+ (and style `(:style ,style)))))))))
(:inverse-video
(choice :tag "Inverse-video"
@@ -268,18 +276,18 @@
:help-echo "List of faces to inherit attributes from."
(face :Tag "Face" default))
;; filter to make value suitable for customize
- (lambda (real-value)
- (cond ((or (null real-value) (eq real-value 'unspecified))
- nil)
- ((symbolp real-value)
- (list real-value))
- (t
- real-value)))
+ ,(lambda (real-value)
+ (cond ((or (null real-value) (eq real-value 'unspecified))
+ nil)
+ ((symbolp real-value)
+ (list real-value))
+ (t
+ real-value)))
;; filter to make customized-value suitable for storing
- (lambda (cus-value)
- (if (and (consp cus-value) (null (cdr cus-value)))
- (car cus-value)
- cus-value))))
+ ,(lambda (cus-value)
+ (if (and (consp cus-value) (null (cdr cus-value)))
+ (car cus-value)
+ cus-value))))
"Alist of face attributes.
@@ -321,12 +329,12 @@ If FRAME is nil, use the global defaults for FACE."
"Apply a list of face specs for user customizations.
This works by calling `custom-theme-set-faces' for the `user'
theme, a special theme referring to settings made via Customize.
-The arguments should be a list where each entry has the form:
+The arguments ARGS should be a list where each entry has the form:
(FACE SPEC [NOW [COMMENT]])
See the documentation of `custom-theme-set-faces' for details."
- (apply 'custom-theme-set-faces 'user args))
+ (apply #'custom-theme-set-faces 'user args))
(defun custom-theme-set-faces (theme &rest args)
"Apply a list of face specs associated with theme THEME.
@@ -411,7 +419,7 @@ Each of the arguments ARGS has this form:
(FACE FROM-THEME)
This means reset FACE to its value in FROM-THEME."
- (apply 'custom-theme-reset-faces 'user args))
+ (apply #'custom-theme-reset-faces 'user args))
(define-obsolete-function-alias 'custom-facep #'facep "28.1")
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 667e36b211c..ca2fca4eb77 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -356,6 +356,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
(const :tag "Iconify" t))
"26.1")
(tooltip-reuse-hidden-frame tooltip boolean "26.1")
+ (use-system-tooltips tooltip boolean "29.1")
;; fringe.c
(overflow-newline-into-fringe fringe boolean)
;; image.c
@@ -369,7 +370,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
(auto-save-timeout auto-save (choice (const :tag "off" nil)
(integer :format "%v")))
(echo-keystrokes minibuffer number)
- (polling-period keyboard integer)
+ (polling-period keyboard float)
(double-click-time mouse (restricted-sexp
:match-alternatives (integerp 'nil 't)))
(double-click-fuzz mouse integer "22.1")
@@ -397,6 +398,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
;; (const :tag " current dir" nil)
;; (directory :format "%v"))))
(load-prefer-newer lisp boolean "24.4")
+ (record-all-keys keyboard boolean)
;; minibuf.c
(minibuffer-follows-selected-frame
minibuffer (choice (const :tag "Always" t)
@@ -810,6 +812,7 @@ since it could result in memory overflow and make Emacs crash."
character)
"27.1"
:safe (lambda (value) (or (characterp value) (null value))))
+ (composition-break-at-point display boolean "29.1")
;; xfaces.c
(scalable-fonts-allowed
display (choice (const :tag "Don't allow scalable fonts" nil)
@@ -829,6 +832,8 @@ since it could result in memory overflow and make Emacs crash."
(x-stretch-cursor display boolean "21.1")
(scroll-bar-adjust-thumb-portion windows boolean "24.4")
(x-scroll-event-delta-factor mouse float "29.1")
+ (x-gtk-use-native-input keyboard boolean "29.1")
+ (x-dnd-disable-motif-drag dnd boolean "29.1")
;; xselect.c
(x-select-enable-clipboard-manager killing boolean "24.1")
;; xsettings.c
@@ -855,6 +860,11 @@ since it could result in memory overflow and make Emacs crash."
(featurep 'ns))
((string-match "\\`haiku-" (symbol-name symbol))
(featurep 'haiku))
+ ((eq symbol 'process-error-pause-time)
+ (not (eq system-type 'ms-dos)))
+ ((eq symbol 'x-gtk-use-native-input)
+ (and (featurep 'x)
+ (featurep 'gtk)))
((string-match "\\`x-.*gtk" (symbol-name symbol))
(featurep 'gtk))
((string-match "clipboard-manager" (symbol-name symbol))
@@ -862,6 +872,8 @@ since it could result in memory overflow and make Emacs crash."
((or (equal "scroll-bar-adjust-thumb-portion"
(symbol-name symbol))
(equal "x-scroll-event-delta-factor"
+ (symbol-name symbol))
+ (equal "x-dnd-disable-motif-drag"
(symbol-name symbol)))
(featurep 'x))
((string-match "\\`x-" (symbol-name symbol))
diff --git a/lisp/custom.el b/lisp/custom.el
index 76c14831cac..bbbe70c5ea8 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -67,8 +67,10 @@ symbol."
(defun custom-initialize-set (symbol exp)
"Initialize SYMBOL based on EXP.
-If the symbol doesn't have a default binding already,
-then set it using its `:set' function (or `set-default' if it has none).
+If the symbol doesn't have a default binding already, then set it
+using its `:set' function (or `set-default-toplevel-value' if it
+has none).
+
The value is either the value in the symbol's `saved-value' property,
if any, or the value of EXP."
(condition-case nil
@@ -81,11 +83,27 @@ if any, or the value of EXP."
(defun custom-initialize-reset (symbol exp)
"Initialize SYMBOL based on EXP.
-Set the symbol, using its `:set' function (or `set-default' if it has none).
+Set the symbol, using its `:set' function (or `set-default-toplevel-value'
+if it has none).
+
The value is either the symbol's current value
(as obtained using the `:get' function), if any,
or the value in the symbol's `saved-value' property if any,
or (last of all) the value of EXP."
+ ;; If this value has been set with `setopt' (for instance in
+ ;; ~/.emacs), we didn't necessarily know the type of the user option
+ ;; then. So check now, and issue a warning if it's wrong.
+ (let ((value (get symbol 'custom-check-value)))
+ (when value
+ (let ((type (get symbol 'custom-type)))
+ (when (and type
+ (boundp symbol)
+ (eq (car value) (symbol-value symbol))
+ ;; Check that the type is correct.
+ (not (widget-apply (widget-convert type)
+ :match (car value))))
+ (warn "Value `%S' for `%s' does not match type %s"
+ value symbol type)))))
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
symbol
(condition-case nil
@@ -100,7 +118,7 @@ or (last of all) the value of EXP."
"Initialize SYMBOL with EXP.
Like `custom-initialize-reset', but only use the `:set' function if
not using the standard setting.
-For the standard setting, use `set-default'."
+For the standard setting, use `set-default-toplevel-value'."
(condition-case nil
(let ((def (default-toplevel-value symbol)))
(funcall (or (get symbol 'custom-set) #'set-default-toplevel-value)
@@ -114,7 +132,7 @@ For the standard setting, use `set-default'."
symbol
(eval (car (get symbol 'saved-value)))))
(t
- (set-default symbol (eval exp)))))))
+ (set-default-toplevel-value symbol (eval exp)))))))
(defvar custom-delayed-init-variables nil
"List of variables whose initialization is pending until startup.
@@ -262,11 +280,11 @@ The following keywords are meaningful:
when using the Customize user interface. It takes two arguments,
the symbol to set and the value to give it. The function should
not modify its value argument destructively. The default choice
- of function is `set-default'.
+ of function is `set-default-toplevel-value'.
:get VALUE should be a function to extract the value of symbol.
The function takes one argument, a symbol, and should return
the current value for that symbol. The default choice of function
- is `default-value'.
+ is `default-toplevel-value'.
:require
VALUE should be a feature symbol. If you save a value
for this option, then when your init file loads the value,
@@ -717,7 +735,7 @@ this sets the local binding in that buffer instead."
(if custom-local-buffer
(with-current-buffer custom-local-buffer
(set variable value))
- (set-default variable value)))
+ (set-default-toplevel-value variable value)))
(defun custom-set-minor-mode (variable value)
":set function for minor mode variables.
@@ -1422,6 +1440,22 @@ are not directories are omitted from the expansion."
;;; Enabling and disabling loaded themes.
+(defcustom enable-theme-functions nil
+ "Abnormal hook that is run after a theme has been enabled.
+The functions in the hook are called with one parameter -- the
+ name of the theme that's been enabled (as a symbol)."
+ :type 'hook
+ :group 'customize
+ :version "29.1")
+
+(defcustom disable-theme-functions nil
+ "Abnormal hook that is run after a theme has been disabled.
+The functions in the hook are called with one parameter -- the
+ name of the theme that's been disabled (as a symbol)."
+ :type 'hook
+ :group 'customize
+ :version "29.1")
+
(defun enable-theme (theme)
"Reenable all variable and face settings defined by THEME.
THEME should be either `user', or a theme loaded via `load-theme'.
@@ -1430,7 +1464,9 @@ After this function completes, THEME will have the highest
precedence (after `user') among enabled themes.
Note that any already-enabled themes remain enabled after this
-function runs. To disable other themes, use `disable-theme'."
+function runs. To disable other themes, use `disable-theme'.
+
+After THEME has been enabled, runs `enable-theme-functions'."
(interactive (list (intern
(completing-read
"Enable custom theme: "
@@ -1478,7 +1514,9 @@ function runs. To disable other themes, use `disable-theme'."
(setq custom-enabled-themes
(cons theme (remq theme custom-enabled-themes)))
;; Give the `user' theme the highest priority.
- (enable-theme 'user)))
+ (enable-theme 'user))
+ ;; Allow callers to react to the enabling.
+ (run-hook-with-args 'enable-theme-functions theme))
(defcustom custom-enabled-themes nil
"List of enabled Custom Themes, highest precedence first.
@@ -1523,7 +1561,9 @@ Setting this variable through Customize calls `enable-theme' or
(defun disable-theme (theme)
"Disable all variable and face settings defined by THEME.
-See `custom-enabled-themes' for a list of enabled themes."
+See `custom-enabled-themes' for a list of enabled themes.
+
+After THEME has been disabled, runs `disable-theme-functions'."
(interactive (list (intern
(completing-read
"Disable custom theme: "
@@ -1567,7 +1607,9 @@ See `custom-enabled-themes' for a list of enabled themes."
"unspecified-fg" "black"))
(face-set-after-frame-default frame))
(setq custom-enabled-themes
- (delq theme custom-enabled-themes))))
+ (delq theme custom-enabled-themes))
+ ;; Allow callers to react to the disabling.
+ (run-hook-with-args 'disable-theme-functions theme)))
;; Only used if window-system not null.
(declare-function x-get-resource "frame.c"
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index 220a2f52e92..215425f1367 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -225,18 +225,27 @@ or matched by `dabbrev-ignored-buffer-regexps'."
(defcustom dabbrev-ignored-buffer-names '("*Messages*" "*Buffer List*")
"List of buffer names that dabbrev should not check.
-See also `dabbrev-ignored-buffer-regexps'."
+See also `dabbrev-ignored-buffer-regexps' and
+`dabbrev-ignored-buffer-modes'."
:type '(repeat (string :tag "Buffer name"))
:group 'dabbrev
:version "20.3")
(defcustom dabbrev-ignored-buffer-regexps nil
"List of regexps matching names of buffers that dabbrev should not check.
-See also `dabbrev-ignored-buffer-names'."
+See also `dabbrev-ignored-buffer-names' and
+`dabbrev-ignored-buffer-modes'."
:type '(repeat regexp)
:group 'dabbrev
:version "21.1")
+(defcustom dabbrev-ignored-buffer-modes '(archive-mode image-mode)
+ "Inhibit looking for abbreviations in buffers derived from these modes.
+See also `dabbrev-ignored-buffer-names' and
+`dabbrev-ignored-buffer-regexps'."
+ :type '(repeat symbol)
+ :version "29.1")
+
(defcustom dabbrev-check-other-buffers t
"Should \\[dabbrev-expand] look in other buffers?
nil: Don't look in other buffers.
@@ -383,6 +392,14 @@ If the prefix argument is 16 (which comes from \\[universal-argument] \\[univers
then it searches *all* buffers."
(interactive "*P")
(dabbrev--reset-global-variables)
+ (setq dabbrev--check-other-buffers (and arg t))
+ (setq dabbrev--check-all-buffers
+ (and arg (= (prefix-numeric-value arg) 16)))
+ (let ((completion-at-point-functions '(dabbrev-capf)))
+ (completion-at-point)))
+
+(defun dabbrev-capf ()
+ "Dabbrev completion function for `completion-at-point-functions'."
(let* ((abbrev (dabbrev--abbrev-at-point))
(beg (progn (search-backward abbrev) (point)))
(end (progn (search-forward abbrev) (point)))
@@ -420,10 +437,7 @@ then it searches *all* buffers."
(t
(mapcar #'downcase completion-list)))))))
(complete-with-action a list s p)))))
- (setq dabbrev--check-other-buffers (and arg t))
- (setq dabbrev--check-all-buffers
- (and arg (= (prefix-numeric-value arg) 16)))
- (completion-in-region beg end table)))
+ (list beg end table)))
;;;###autoload
(defun dabbrev-expand (arg)
@@ -537,8 +551,9 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
(if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found)
(minibuffer-window-active-p (selected-window))))
(progn
- (message "Expansion found in `%s'"
- (buffer-name dabbrev--last-buffer))
+ (when (buffer-name dabbrev--last-buffer)
+ (message "Expansion found in `%s'"
+ (buffer-name dabbrev--last-buffer)))
(setq dabbrev--last-buffer-found dabbrev--last-buffer))
(message nil))
(if (and (or (eq (current-buffer) dabbrev--last-buffer)
@@ -632,19 +647,29 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
"Return a list of other buffers to search for a possible abbrev.
The current buffer is not included in the list.
-This function makes a list of all the buffers returned by `buffer-list',
-then discards buffers whose names match `dabbrev-ignored-buffer-names'
-or `dabbrev-ignored-buffer-regexps'. It also discards buffers for which
-`dabbrev-friend-buffer-function', if it is bound, returns nil when called
-with the buffer as argument.
-It returns the list of the buffers that are not discarded."
+This function makes a list of all the buffers returned by
+`buffer-list', then discards buffers whose names match
+`dabbrev-ignored-buffer-names' or
+`dabbrev-ignored-buffer-regexps', and major modes that match
+`dabbrev-ignored-buffer-modes'. It also discards buffers for
+which `dabbrev-friend-buffer-function', if it is bound, returns
+nil when called with the buffer as argument. It returns the list
+of the buffers that are not discarded."
(dabbrev-filter-elements
- buffer (buffer-list)
+ buffer (dabbrev--filter-buffer-modes)
(and (not (eq (current-buffer) buffer))
(not (dabbrev--ignore-buffer-p buffer))
(boundp 'dabbrev-friend-buffer-function)
(funcall dabbrev-friend-buffer-function buffer))))
+(defun dabbrev--filter-buffer-modes ()
+ (seq-filter (lambda (buffer)
+ (not (apply
+ #'provided-mode-derived-p
+ (buffer-local-value 'major-mode buffer)
+ dabbrev-ignored-buffer-modes)))
+ (buffer-list)))
+
(defun dabbrev--try-find (abbrev reverse n ignore-case)
"Search for ABBREV, backwards if REVERSE, N times.
If IGNORE-CASE is non-nil, ignore case while searching.
@@ -746,17 +771,41 @@ of the start of the occurrence."
(make-progress-reporter
"Scanning for dabbrevs..."
(- (length dabbrev--friend-buffer-list)) 0 0 1 1.5))))
- ;; Walk through the buffers till we find a match.
- (let (expansion)
- (while (and (not expansion) dabbrev--friend-buffer-list)
- (setq dabbrev--last-buffer (pop dabbrev--friend-buffer-list))
- (set-buffer dabbrev--last-buffer)
- (progress-reporter-update dabbrev--progress-reporter
- (- (length dabbrev--friend-buffer-list)))
- (setq dabbrev--last-expansion-location (point-min))
- (setq expansion (dabbrev--try-find abbrev nil 1 ignore-case)))
- (progress-reporter-done dabbrev--progress-reporter)
- expansion)))))
+ (let ((file-name (buffer-file-name))
+ file-name-buffer)
+ (unwind-protect
+ (progn
+ ;; Include the file name components into the abbrev
+ ;; list (because if you have a file name "foobar", it's
+ ;; somewhat likely that you'll be talking about foobar
+ ;; stuff in the file itself).
+ (when file-name
+ (setq file-name-buffer (generate-new-buffer " *abbrev-file*"))
+ (with-current-buffer file-name-buffer
+ (dolist (part (file-name-split file-name))
+ (insert part "\n")))
+ (setq dabbrev--friend-buffer-list
+ (append dabbrev--friend-buffer-list
+ (list file-name-buffer))))
+ ;; Walk through the buffers till we find a match.
+ (let (expansion)
+ (while (and (not expansion) dabbrev--friend-buffer-list)
+ (setq dabbrev--last-buffer
+ (pop dabbrev--friend-buffer-list))
+ (set-buffer dabbrev--last-buffer)
+ (progress-reporter-update
+ dabbrev--progress-reporter
+ (- (length dabbrev--friend-buffer-list)))
+ (setq dabbrev--last-expansion-location (point-min))
+ (setq expansion (dabbrev--try-find
+ abbrev nil 1 ignore-case)))
+ (progress-reporter-done dabbrev--progress-reporter)
+ expansion))
+ (when (buffer-live-p file-name-buffer)
+ (kill-buffer file-name-buffer))
+ (setq dabbrev--friend-buffer-list
+ (seq-filter #'buffer-live-p
+ dabbrev--friend-buffer-list))))))))
;; Compute the list of buffers to scan.
;; If dabbrev-search-these-buffers-only, then the current buffer
@@ -779,7 +828,7 @@ of the start of the occurrence."
(setq list
(append list
(dabbrev-filter-elements
- buffer (buffer-list)
+ buffer (dabbrev--filter-buffer-modes)
(and (not (memq buffer list))
(not (dabbrev--ignore-buffer-p buffer)))))))
;; Remove the current buffer.
diff --git a/lisp/delsel.el b/lisp/delsel.el
index f5fe7cf7939..5310328e5fd 100644
--- a/lisp/delsel.el
+++ b/lisp/delsel.el
@@ -64,6 +64,19 @@
"If non-nil, deleted region text is stored in this register.
Value must be the register (key) to use.")
+(defcustom delete-selection-temporary-region nil
+ "Whether to delete only temporary regions.
+When non-nil, typed text replaces only the regions set by
+mouse-dragging, shift-selection, and \"\\[universal-argument] \\[exchange-point-and-mark]\" when
+`transient-mark-mode' is turned off. If the value is the symbol
+`selection', then replace only the regions set by mouse-dragging
+and shift-selection."
+ :version "29.1"
+ :group 'editing-basics
+ :type '(choice (const :tag "Replace all regions" nil)
+ (const :tag "Replace region from mouse, shift-selection, and \"C-u C-x C-x\"" t)
+ (const :tag "Replace region from mouse and shift-selection" selection)))
+
;;;###autoload
(defalias 'pending-delete-mode 'delete-selection-mode)
@@ -108,7 +121,8 @@ the active region is killed instead of deleted."
"Repeat replacing text of highlighted region with typed text.
Search for the next stretch of text identical to the region last replaced
by typing text over it and replaces it with the same stretch of text.
-With ARG, repeat that many times. `\\[universal-argument]' means until end of buffer."
+With ARG (interactively, prefix numeric argument), repeat that many times.
+Just `\\[universal-argument]' means repeat until the end of the buffer's accessible portion."
(interactive "P")
(let ((old-text (and delete-selection-save-to-register
(get-register delete-selection-save-to-register)))
@@ -251,7 +265,13 @@ property on their symbol; commands which insert text but don't
have this property won't delete the selection.
See `delete-selection-helper'."
(when (and delete-selection-mode (use-region-p)
- (not buffer-read-only))
+ (not buffer-read-only)
+ (or (null delete-selection-temporary-region)
+ (and delete-selection-temporary-region
+ (consp transient-mark-mode)
+ (eq (car transient-mark-mode) 'only))
+ (and (not (eq delete-selection-temporary-region 'selection))
+ (eq transient-mark-mode 'lambda))))
(delete-selection-helper (and (symbolp this-command)
(get this-command 'delete-selection)))))
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index a8160889325..16971aa6611 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -176,6 +176,10 @@ otherwise."
(insert "\n"))
;; Text properties
(when properties
+ (when (plist-get properties 'invisible)
+ (insert "\nNote that character has an invisibility property,\n"
+ " so the character displayed at point in the buffer may\n"
+ " differ from the character described here.\n"))
(newline)
(insert "There are text properties here:\n")
(describe-property-list properties)))))
@@ -697,6 +701,7 @@ The character information includes:
(looking-at-p "[ \t]+$")))
'trailing-whitespace)
((and nobreak-char-display char
+ (> char 127)
(eq (get-char-code-property char 'general-category) 'Zs))
'nobreak-space)
((and nobreak-char-display char
diff --git a/lisp/desktop.el b/lisp/desktop.el
index e7a368e21f5..850d2a86efa 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -44,10 +44,11 @@
;; (info "(emacs)Saving Emacs Sessions") in the GNU Emacs Manual.
;; When the desktop module is loaded, the function `desktop-kill' is
-;; added to the `kill-emacs-hook'. This function is responsible for
-;; saving the desktop when Emacs is killed. Furthermore an anonymous
-;; function is added to the `after-init-hook'. This function is
-;; responsible for loading the desktop when Emacs is started.
+;; added to the `kill-emacs-query-functions'. This function is
+;; responsible for saving the desktop and deleting the desktop lock
+;; file when Emacs is killed. In addition, an anonymous function is
+;; added to the `after-init-hook'. This function is responsible for
+;; loading the desktop when Emacs is started.
;; Special handling.
;; -----------------
@@ -230,16 +231,26 @@ Zero or nil means disable auto-saving due to idleness."
(defcustom desktop-load-locked-desktop 'ask
"Specifies whether the desktop should be loaded if locked.
Possible values are:
- t -- load anyway.
- nil -- don't load.
- ask -- ask the user.
-If the value is nil, or `ask' and the user chooses not to load the desktop,
-the normal hook `desktop-not-loaded-hook' is run."
+ t -- load anyway.
+ nil -- don't load.
+ ask -- ask the user.
+ check-pid -- load if locking Emacs process is missing locally.
+
+If the value is nil, or `ask' and the user chooses not to load
+the desktop, the normal hook `desktop-not-loaded-hook' is run.
+
+If the value is `check-pid', load the desktop if the Emacs
+process that has locked it is not running on the local machine.
+This should not be used in circumstances where the locking Emacs
+might still be running on another machine. That could be the
+case if you have remotely mounted (NFS) paths in
+`desktop-dirname'."
:type
'(choice
(const :tag "Load anyway" t)
(const :tag "Don't load" nil)
- (const :tag "Ask the user" ask))
+ (const :tag "Ask the user" ask)
+ (const :tag "Load if no local process" check-pid))
:group 'desktop
:version "22.2")
@@ -424,7 +435,9 @@ If `all', also restores frames that are partially offscreen onscreen.
Note that checking of frame boundaries is only approximate.
It can fail to reliably detect frames whose onscreen/offscreen state
depends on a few pixels, especially near the right / bottom borders
-of the screen."
+of the screen.
+Text-mode frames are always considered onscreen, so this option has
+no effect on restoring frames in a non-GUI session."
:type '(choice (const :tag "Only fully offscreen frames" t)
(const :tag "Also partially offscreen frames" all)
(const :tag "Do not force frames onscreen" nil))
@@ -468,7 +481,7 @@ If value is t, all buffers are restored immediately."
(defcustom desktop-lazy-idle-delay 5
"Idle delay before starting to create buffers.
See `desktop-restore-eager'."
- :type 'integer
+ :type 'natnum
:group 'desktop
:version "22.1")
@@ -635,6 +648,14 @@ Only valid during frame saving & restoring; intended for internal use.")
"When the desktop file was last modified to the knowledge of this Emacs.
Used to detect desktop file conflicts.")
+(defun desktop--get-file-modtime ()
+ "Get desktop file modtime, in list form for desktop format version 208."
+ (setq desktop-file-modtime
+ (time-convert (file-attribute-modification-time
+ (file-attributes
+ (desktop-full-file-name)))
+ 'list)))
+
(defvar desktop-var-serdes-funs
(list (list
'mark-ring
@@ -662,6 +683,44 @@ DIRNAME omitted or nil means use `desktop-dirname'."
(integerp owner)))
owner)))
+(defun desktop--emacs-pid-running-p (pid)
+ "Return non-nil if an Emacs process whose ID is PID might still be running."
+ (when-let ((attr (process-attributes pid)))
+ (let ((proc-cmd (alist-get 'comm attr))
+ (my-cmd (file-name-nondirectory (car command-line-args)))
+ (case-fold-search t))
+ (or (equal proc-cmd my-cmd)
+ (and (eq system-type 'windows-nt)
+ (eq t (compare-strings proc-cmd
+ nil
+ (if (string-suffix-p ".exe" proc-cmd t)
+ -4)
+ my-cmd
+ nil
+ (if (string-suffix-p ".exe" my-cmd t)
+ -4))))
+ ;; We should err on the safe side here: if any of the
+ ;; executables is something like "emacs-nox" or "emacs-42.1"
+ ;; or "gemacs" or "xemacs", let's recognize them as well.
+ (and (string-match-p "emacs" proc-cmd)
+ (string-match-p "emacs" my-cmd))))))
+
+(defun desktop--load-locked-desktop-p (owner)
+ "Return t if a locked desktop should be loaded.
+OWNER is the pid in the lock file.
+The return value of this function depends on the value of
+`desktop-load-locked-desktop'."
+ (pcase desktop-load-locked-desktop
+ ('ask
+ (unless (daemonp)
+ (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\n\
+Using it may cause conflicts. Use it anyway? " owner))))
+ ('check-pid
+ (or (eq (emacs-pid) owner)
+ (not (desktop--emacs-pid-running-p owner))))
+ ('nil nil)
+ (_ t)))
+
(defun desktop-claim-lock (&optional dirname)
"Record this Emacs process as the owner of the desktop file in DIRNAME.
DIRNAME omitted or nil means use `desktop-dirname'."
@@ -799,15 +858,16 @@ buffer, which is (in order):
,(buffer-name)
,major-mode
;; minor modes
- ,(let (ret)
- (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
- (and (boundp minor-mode)
- (symbol-value minor-mode)
- (let* ((special (assq minor-mode desktop-minor-mode-table))
- (value (cond (special (cadr special))
- ((get minor-mode :minor-mode-function))
- ((functionp minor-mode) minor-mode))))
- (when value (cl-pushnew value ret))))))
+ ,(seq-filter
+ (lambda (minor-mode)
+ ;; Just two sanity checks.
+ (and (boundp minor-mode)
+ (symbol-value minor-mode)
+ (let ((special
+ (assq minor-mode desktop-minor-mode-table)))
+ (or (not special)
+ (cadr special)))))
+ local-minor-modes)
;; point and mark, and read-only status
,(point)
,(list (mark t) mark-active)
@@ -1072,7 +1132,7 @@ no questions asked."
(file-attributes (desktop-full-file-name)))))
(when
(or (not new-modtime) ; nothing to overwrite
- (equal desktop-file-modtime new-modtime)
+ (time-equal-p desktop-file-modtime new-modtime)
(yes-or-no-p (if desktop-file-modtime
(if (time-less-p desktop-file-modtime
new-modtime)
@@ -1172,9 +1232,7 @@ no questions asked."
(write-region (point-min) (point-max) (desktop-full-file-name) nil 'nomessage))
(setq desktop-file-checksum checksum)
;; We remember when it was modified (which is presumably just now).
- (setq desktop-file-modtime (file-attribute-modification-time
- (file-attributes
- (desktop-full-file-name)))))))))))
+ (desktop--get-file-modtime))))))))
;; ----------------------------------------------------------------------------
;;;###autoload
@@ -1196,7 +1254,11 @@ This function also sets `desktop-dirname' to nil."
;; ----------------------------------------------------------------------------
(defun desktop-restoring-frameset-p ()
"True if calling `desktop-restore-frameset' will actually restore it."
- (and desktop-restore-frames desktop-saved-frameset (display-graphic-p) t))
+ (and desktop-restore-frames desktop-saved-frameset
+ ;; Don't restore frames when the selected frame is the daemon's
+ ;; initial frame.
+ (not (and (daemonp) (not (frame-parameter nil 'client))))
+ t))
(defun desktop-restore-frameset ()
"Restore the state of a set of frames.
@@ -1207,7 +1269,17 @@ being set (usually, by reading it from the desktop)."
:reuse-frames (eq desktop-restore-reuses-frames t)
:cleanup-frames (not (eq desktop-restore-reuses-frames 'keep))
:force-display desktop-restore-in-current-display
- :force-onscreen desktop-restore-forces-onscreen)))
+ :force-onscreen (and desktop-restore-forces-onscreen
+ (display-graphic-p)))
+ ;; When at least one restored frame contains a tab bar,
+ ;; enable `tab-bar-mode' that takes care about recalculating
+ ;; the correct values of the frame parameter `tab-bar-lines'
+ ;; (that depends on `tab-bar-show'), and also loads graphical buttons.
+ (when (seq-some
+ (lambda (frame)
+ (menu-bar-positive-p (frame-parameter frame 'tab-bar-lines)))
+ (frame-list))
+ (tab-bar-mode 1))))
;; Just to silence the byte compiler.
;; Dynamically bound in `desktop-read'.
@@ -1263,11 +1335,7 @@ It returns t if a desktop file was loaded, nil otherwise.
(desktop-save nil)
(desktop-autosave-was-enabled))
(if (and owner
- (memq desktop-load-locked-desktop '(nil ask))
- (or (null desktop-load-locked-desktop)
- (daemonp)
- (not (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\n\
-Using it may cause conflicts. Use it anyway? " owner)))))
+ (not (desktop--load-locked-desktop-p owner)))
(let ((default-directory desktop-dirname))
(setq desktop-dirname nil)
(run-hooks 'desktop-not-loaded-hook)
@@ -1287,9 +1355,7 @@ Using it may cause conflicts. Use it anyway? " owner)))))
'window-configuration-change-hook)))
(desktop-auto-save-disable)
;; Evaluate desktop buffer and remember when it was modified.
- (setq desktop-file-modtime (file-attribute-modification-time
- (file-attributes
- (desktop-full-file-name))))
+ (desktop--get-file-modtime)
(load (desktop-full-file-name) t t t)
;; If it wasn't already, mark it as in-use, to bother other
;; desktop instances.
diff --git a/lisp/dframe.el b/lisp/dframe.el
index 6593708a13c..9580a3187fd 100644
--- a/lisp/dframe.el
+++ b/lisp/dframe.el
@@ -120,9 +120,7 @@
:prefix "dframe-"
:group 'dframe)
-(defvar dframe-have-timer-flag (if (fboundp 'display-graphic-p)
- (display-graphic-p)
- window-system)
+(defvar dframe-have-timer-flag (display-graphic-p)
"Non-nil means that timers are available for this Emacs.
This is nil for terminals, since updating a frame in a terminal
is not useful to the user.")
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 637f8695f31..b9f33036e31 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -796,6 +796,15 @@ offer a smarter default choice of shell command."
'read-shell-command prompt nil nil))))
;;;###autoload
+(defcustom dired-confirm-shell-command t
+ "Whether to prompt for confirmation for `dired-do-shell-command'.
+If non-nil, prompt for confirmation if the command contains potentially
+dangerous characters. If nil, never prompt for confirmation."
+ :type 'boolean
+ :group 'dired
+ :version "29.1")
+
+;;;###autoload
(defun dired-do-async-shell-command (command &optional arg file-list)
"Run a shell command COMMAND on the marked files asynchronously.
@@ -810,7 +819,9 @@ are executed in the background on each file sequentially waiting
for each command to terminate before running the next command.
In shell syntax this means separating the individual commands with `;'.
-The output appears in the buffer named by `shell-command-buffer-name-async'."
+The output appears in the buffer named by `shell-command-buffer-name-async'.
+
+Commands that are run asynchronously do not accept user input."
(interactive
(let ((files (dired-get-marked-files t current-prefix-arg nil nil t)))
(list
@@ -873,7 +884,9 @@ can be produced by `dired-get-marked-files', for example.
`dired-guess-shell-alist-default' and
`dired-guess-shell-alist-user' are consulted when the user is
-prompted for the shell command to use interactively."
+prompted for the shell command to use interactively.
+
+Also see the `dired-confirm-shell-command' variable."
;; Functions dired-run-shell-command and dired-shell-stuff-it do the
;; actual work and can be redefined for customization.
(interactive
@@ -891,6 +904,8 @@ prompted for the shell command to use interactively."
(ok (cond
((not (or on-each no-subst))
(error "You can not combine `*' and `?' substitution marks"))
+ ((not dired-confirm-shell-command)
+ t)
((setq confirmations (dired--need-confirm-positions command "*"))
(dired--no-subst-confirm confirmations command))
((setq confirmations (dired--need-confirm-positions command "?"))
@@ -954,6 +969,13 @@ prompted for the shell command to use interactively."
(setq retval (replace-match x t t retval 2)))
retval))
(lambda (x) (concat cmd-prefix command dired-mark-separator x)))))
+ ;; If a file name starts with "-", add a "./" to avoid the command
+ ;; interpreting it as a command line switch.
+ (setq file-list (mapcar (lambda (file)
+ (if (string-match "\\`-" file)
+ (concat "./" file)
+ file))
+ file-list))
(concat
(cond
(on-each
@@ -976,8 +998,15 @@ prompted for the shell command to use interactively."
file-list dired-mark-separator)))
(when (cdr file-list)
(setq files (concat dired-mark-prefix files dired-mark-postfix)))
- (funcall stuff-it files))))
- (or (and in-background "&") ""))))
+ (concat
+ (funcall stuff-it files)
+ ;; Be consistent in how we treat inputs to commands -- do
+ ;; the same here as in the `on-each' case.
+ (if (and in-background (not w32-shell))
+ "&wait"
+ "")))))
+ (or (and in-background "&")
+ ""))))
;; This is an extra function so that it can be redefined by ange-ftp.
;;;###autoload
@@ -1027,18 +1056,19 @@ Return the result of `process-file' - zero for success."
(dir default-directory))
(with-current-buffer (get-buffer-create out-buffer)
(erase-buffer)
- (let* ((default-directory dir)
- (res (process-file
- shell-file-name
- nil
- t
- nil
- shell-command-switch
- cmd)))
- (dired-uncache dir)
- (unless (zerop res)
- (pop-to-buffer out-buffer))
- res))))
+ (let ((default-directory dir) res)
+ (with-connection-local-variables
+ (setq res (process-file
+ shell-file-name
+ nil
+ t
+ nil
+ shell-command-switch
+ cmd))
+ (dired-uncache dir)
+ (unless (zerop res)
+ (pop-to-buffer out-buffer))
+ res)))))
;;; Commands that delete or redisplay part of the dired buffer
@@ -1066,45 +1096,46 @@ With a prefix argument, kill that many lines starting with the current line.
(dired-move-to-filename)))
;;;###autoload
-(defun dired-do-kill-lines (&optional arg fmt)
- "Kill all marked lines (not the files).
-With a prefix argument, kill that many lines starting with the current line.
-\(A negative argument kills backward.)
+(defun dired-do-kill-lines (&optional arg fmt init-count)
+ "Remove all marked lines, or the next ARG lines.
+The files or directories on those lines are _not_ deleted. Only the
+Dired listing is affected. To restore the removals, use `\\[revert-buffer]'.
-If you use this command with a prefix argument to kill the line
-for a file that is a directory, which you have inserted in the
-Dired buffer as a subdirectory, then it deletes that subdirectory
-from the buffer as well.
+With a numeric prefix arg, remove that many lines going forward,
+starting with the current line. (A negative prefix arg removes lines
+going backward.)
-To kill an entire subdirectory \(without killing its line in the
-parent directory), go to its directory header line and use this
-command with a prefix argument (the value does not matter).
+If you use a prefix arg to remove the line for a subdir whose listing
+you have inserted into the Dired buffer, then that subdir listing is
+also removed.
-To undo the killing, the undo command can be used as normally.
+To remove a subdir listing _without_ removing the subdir's line in its
+parent listing, go to the header line of the subdir listing and use
+this command with any prefix arg.
-This function returns the number of killed lines.
+When called from Lisp, non-nil INIT-COUNT is added to the number of
+lines removed by this invocation, for the reporting message.
-FMT is a format string used for messaging the user about the
-killed lines, and defaults to \"Killed %d line%s.\" if not
-present. A FMT of \"\" will suppress the messaging."
+A FMT of \"\" will suppress the messaging."
+ ;; Returns count of killed lines.
(interactive "P")
(if arg
(if (dired-get-subdir)
- (dired-kill-subdir)
- (dired-kill-line arg))
+ (dired-kill-subdir)
+ (dired-kill-line arg))
(save-excursion
(goto-char (point-min))
- (let (buffer-read-only
- (count 0)
- (regexp (dired-marker-regexp)))
- (while (and (not (eobp))
- (re-search-forward regexp nil t))
- (setq count (1+ count))
- (delete-region (line-beginning-position)
- (progn (forward-line 1) (point))))
- (or (equal "" fmt)
- (message (or fmt "Killed %d line%s.") count (dired-plural-s count)))
- count))))
+ (let ((count (or init-count 0))
+ (regexp (dired-marker-regexp))
+ (inhibit-read-only t))
+ (while (and (not (eobp))
+ (re-search-forward regexp nil t))
+ (setq count (1+ count))
+ (delete-region (line-beginning-position)
+ (progn (forward-line 1) (point))))
+ (unless (equal "" fmt)
+ (message (or fmt "Killed %d line%s.") count (dired-plural-s count)))
+ count))))
;;; Compression
@@ -1244,7 +1275,8 @@ and `dired-compress-files-alist'."
(when (zerop
(dired-shell-command
(format-spec (cdr rule)
- `((?o . ,(shell-quote-argument out-file))
+ `((?o . ,(shell-quote-argument
+ (file-local-name out-file)))
(?i . ,(mapconcat
(lambda (in-file)
(shell-quote-argument
@@ -1876,22 +1908,23 @@ rename them using `vc-rename-file'."
"Rename FILE to NEWNAME.
Signal a `file-already-exists' error if a file NEWNAME already exists
unless OK-IF-ALREADY-EXISTS is non-nil."
- (dired-handle-overwrite newname)
- (dired-maybe-create-dirs (file-name-directory newname))
- (if (and dired-vc-rename-file
- (vc-backend file)
- (ignore-errors (vc-responsible-backend newname)))
- (vc-rename-file file newname)
- ;; error is caught in -create-files
- (rename-file file newname ok-if-already-exists))
- ;; Silently rename the visited file of any buffer visiting this file.
- (and (get-file-buffer file)
- (with-current-buffer (get-file-buffer file)
- (set-visited-file-name newname nil t)))
- (dired-remove-file file)
- ;; See if it's an inserted subdir, and rename that, too.
- (when (file-directory-p file)
- (dired-rename-subdir file newname)))
+ (let ((file-is-dir-p (file-directory-p file)))
+ (dired-handle-overwrite newname)
+ (dired-maybe-create-dirs (file-name-directory newname))
+ (if (and dired-vc-rename-file
+ (vc-backend file)
+ (ignore-errors (vc-responsible-backend newname)))
+ (vc-rename-file file newname)
+ ;; error is caught in -create-files
+ (rename-file file newname ok-if-already-exists))
+ ;; Silently rename the visited file of any buffer visiting this file.
+ (and (get-file-buffer file)
+ (with-current-buffer (get-file-buffer file)
+ (set-visited-file-name newname nil t)))
+ (dired-remove-file file)
+ ;; See if it's an inserted subdir, and rename that, too.
+ (when file-is-dir-p
+ (dired-rename-subdir file newname))))
(defun dired-rename-subdir (from-dir to-dir)
(setq from-dir (file-name-as-directory from-dir)
@@ -1904,7 +1937,7 @@ unless OK-IF-ALREADY-EXISTS is non-nil."
(while blist
(with-current-buffer (car blist)
(if (and buffer-file-name
- (file-in-directory-p buffer-file-name expanded-from-dir))
+ (dired-in-this-tree-p buffer-file-name expanded-from-dir))
(let ((modflag (buffer-modified-p))
(to-file (replace-regexp-in-string
(concat "^" (regexp-quote from-dir))
@@ -1923,7 +1956,7 @@ unless OK-IF-ALREADY-EXISTS is non-nil."
(while alist
(setq elt (car alist)
alist (cdr alist))
- (if (file-in-directory-p (car elt) expanded-dir)
+ (if (dired-in-this-tree-p (car elt) expanded-dir)
;; ELT's subdir is affected by the rename
(dired-rename-subdir-2 elt dir to)))
(if (equal dir default-directory)
@@ -2145,18 +2178,23 @@ Prompt user for a target directory in which to create the new
one file is marked. The initial suggestion for target is the
Dired buffer's current directory (or, if `dired-dwim-target' is
non-nil, the current directory of a neighboring Dired window).
+
OP-SYMBOL is the symbol for the operation. Function `dired-mark-pop-up'
will determine whether pop-ups are appropriate for this OP-SYMBOL.
+
FILE-CREATOR and OPERATION as in `dired-create-files'.
+
ARG as in `dired-get-marked-files'.
+
Optional arg MARKER-CHAR as in `dired-create-files'.
+
Optional arg OP1 is an alternate form for OPERATION if there is
only one file.
+
Optional arg HOW-TO determines how to treat the target.
If HOW-TO is nil, use `file-directory-p' to determine if the
target is a directory. If so, the marked file(s) are created
- inside that directory. Otherwise, the target is a plain file;
- an error is raised unless there is exactly one marked file.
+ inside that directory.
If HOW-TO is t, target is always treated as a plain file.
Otherwise, HOW-TO should be a function of one argument, TARGET.
If its return value is nil, TARGET is regarded as a plain file.
@@ -2169,6 +2207,11 @@ Optional arg HOW-TO determines how to treat the target.
target - the name of the target itself.
The rest of elements of the list returned by HOW-TO are optional
arguments for the function that is the first element of the list.
+
+ This can be useful because by default, copying a single file
+ would replace the tar file. But this could be overridden to
+ add or replace entries in the tar file.
+
For any other return value, TARGET is treated as a directory."
(or op1 (setq op1 operation))
(let* ((fn-list (dired-get-marked-files nil arg nil nil t))
@@ -2417,7 +2460,7 @@ If FILE already exists, signal an error."
(defvar dired-copy-how-to-fn nil
"Either nil or a function used by `dired-do-copy' to determine target.
-See HOW-TO argument for `dired-do-create-files'.")
+See HOW-TO argument for `dired-do-create-files' for an explanation.")
;;;###autoload
(defun dired-do-copy (&optional arg)
@@ -2438,6 +2481,10 @@ If `dired-copy-preserve-time' is non-nil, this command preserves
the modification time of each old file in the copy, similar to
the \"-p\" option for the \"cp\" shell command.
+The `dired-keep-marker-copy' user option controls how this
+command handles file marking. The default is to mark all new
+copies of files with a \"C\" mark.
+
This command copies symbolic links by creating new ones,
similar to the \"-d\" option for the \"cp\" shell command.
But if `dired-copy-dereference' is non-nil, the symbolic
@@ -2475,6 +2522,73 @@ Also see `dired-do-revert-buffer'."
"Symlink" arg dired-keep-marker-symlink))
;;;###autoload
+(defun dired-do-relsymlink (&optional arg)
+ "Relative symlink all marked (or next ARG) files into a directory.
+Otherwise make a relative symbolic link to the current file.
+This creates relative symbolic links like
+
+ foo -> ../bar/foo
+
+not absolute ones like
+
+ foo -> /ugly/file/name/that/may/change/any/day/bar/foo
+
+For absolute symlinks, use \\[dired-do-symlink]."
+ (interactive "P")
+ (dired-do-create-files 'relsymlink #'dired-make-relative-symlink
+ "RelSymLink" arg dired-keep-marker-relsymlink))
+
+(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists)
+ "Make a symbolic link (pointing to FILE1) in FILE2.
+The link is relative (if possible), for example
+
+ \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\"
+
+results in
+
+ \"../../tex/bin/foo\" \"/vol/local/bin/foo\""
+ (interactive "FRelSymLink: \nFRelSymLink %s: \np")
+ (let (name1 name2 len1 len2 (index 0) sub)
+ (setq file1 (expand-file-name file1)
+ file2 (expand-file-name file2)
+ len1 (length file1)
+ len2 (length file2))
+ ;; Find common initial file name components:
+ (let (next)
+ (while (and (setq next (string-search "/" file1 index))
+ (< (setq next (1+ next)) (min len1 len2))
+ ;; For the comparison, both substrings must end in
+ ;; `/', so NEXT is *one plus* the result of the
+ ;; string-search.
+ ;; E.g., consider the case of linking "/tmp/a/abc"
+ ;; to "/tmp/abc" erroneously giving "/tmp/a" instead
+ ;; of "/tmp/" as common initial component
+ (string-equal (substring file1 0 next)
+ (substring file2 0 next)))
+ (setq index next))
+ (setq name2 file2
+ sub (substring file1 0 index)
+ name1 (substring file1 index)))
+ (if (string-equal sub "/")
+ ;; No common initial file name found
+ (setq name1 file1)
+ ;; Else they have a common parent directory
+ (let ((tem (substring file2 index))
+ (start 0)
+ (count 0))
+ ;; Count number of slashes we must compensate for ...
+ (while (setq start (string-search "/" tem start))
+ (setq count (1+ count)
+ start (1+ start)))
+ ;; ... and prepend a "../" for each slash found:
+ (dotimes (_ count)
+ (setq name1 (concat "../" name1)))))
+ (make-symbolic-link
+ (directory-file-name name1) ; must not link to foo/
+ ; (trailing slash!)
+ name2 ok-if-already-exists)))
+
+;;;###autoload
(defun dired-do-hardlink (&optional arg)
"Add names (hard links) current file or all marked (or next ARG) files.
When operating on just the current file, you specify the new name.
@@ -2634,6 +2748,16 @@ See function `dired-do-rename-regexp' for more info."
#'make-symbolic-link
"SymLink" arg regexp newname whole-name dired-keep-marker-symlink))
+;;;###autoload
+(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name)
+ "RelSymlink all marked files containing REGEXP to NEWNAME.
+See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
+for more info."
+ (interactive (dired-mark-read-regexp "RelSymLink"))
+ (dired-do-create-files-regexp
+ #'dired-make-relative-symlink
+ "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink))
+
;;; Change case of file names
@@ -2771,7 +2895,7 @@ This function takes some pains to conform to `ls -lR' output."
(setq switches (string-replace "R" "" switches))
(dolist (cur-ass dired-subdir-alist)
(let ((cur-dir (car cur-ass)))
- (and (file-in-directory-p cur-dir dirname)
+ (and (dired-in-this-tree-p cur-dir dirname)
(let ((cur-cons (assoc-string cur-dir dired-switches-alist)))
(if cur-cons
(setcdr cur-cons switches)
@@ -2783,7 +2907,7 @@ This function takes some pains to conform to `ls -lR' output."
(defun dired-insert-subdir-validate (dirname &optional switches)
;; Check that it is valid to insert DIRNAME with SWITCHES.
;; Signal an error if invalid (e.g. user typed `i' on `..').
- (or (file-in-directory-p dirname (expand-file-name default-directory))
+ (or (dired-in-this-tree-p dirname (expand-file-name default-directory))
(error "%s: Not in this directory tree" dirname))
(let ((real-switches (or switches dired-subdir-switches)))
(when real-switches
@@ -2976,18 +3100,20 @@ When called interactively and not on a subdir line, go to this subdir's line."
;;;###autoload
(defun dired-goto-subdir (dir)
- "Go to end of header line of DIR in this dired buffer.
+ "Go to end of header line of inserted directory DIR in this Dired buffer.
+When called interactively, prompt for the inserted subdirectory
+to go to.
+
Return value of point on success, otherwise return nil.
The next char is \\n."
(interactive
(prog1 ; let push-mark display its message
(list (expand-file-name
- (completing-read "Goto in situ directory: " ; prompt
- dired-subdir-alist ; table
- nil ; predicate
- t ; require-match
- (dired-current-directory))))
- (push-mark)))
+ (completing-read "Goto inserted directory: "
+ dired-subdir-alist nil t
+ (dired-current-directory))))
+ (push-mark))
+ dired-mode)
(setq dir (file-name-as-directory dir))
(let ((elt (assoc dir dired-subdir-alist)))
(and elt
@@ -3125,16 +3251,16 @@ a file name. Otherwise, it searches the whole buffer without restrictions."
(define-minor-mode dired-isearch-filenames-mode
"Toggle file names searching on or off.
-When on, Isearch skips matches outside file names using the predicate
-`dired-isearch-filter-filenames' that matches only at file names.
-When off, it uses the original predicate."
+When on, Isearch skips matches outside file names using the search function
+`dired-isearch-search-filenames' that matches only at file names.
+When off, it uses the default search function."
:lighter nil
(if dired-isearch-filenames-mode
- (add-function :before-while (local 'isearch-filter-predicate)
- #'dired-isearch-filter-filenames
+ (add-function :around (local 'isearch-search-fun-function)
+ #'dired-isearch-search-filenames
'((isearch-message-prefix . "filename ")))
- (remove-function (local 'isearch-filter-predicate)
- #'dired-isearch-filter-filenames))
+ (remove-function (local 'isearch-search-fun-function)
+ #'dired-isearch-search-filenames))
(when isearch-mode
(setq isearch-success t isearch-adjusted t)
(isearch-update)))
@@ -3158,12 +3284,12 @@ Intended to be added to `isearch-mode-hook'."
(unless isearch-suspended
(kill-local-variable 'dired-isearch-filenames)))
-(defun dired-isearch-filter-filenames (beg end)
- "Test whether some part of the current search match is inside a file name.
-This function returns non-nil if some part of the text between BEG and END
-is part of a file name (i.e., has the text property `dired-filename')."
- (text-property-not-all (min beg end) (max beg end)
- 'dired-filename nil))
+(defun dired-isearch-search-filenames (orig-fun)
+ "Return the function that searches inside file names.
+The returned function narrows the search to match the search string
+only as part of a file name enclosed by the text property `dired-filename'.
+It's intended to override the default search function."
+ (isearch-search-fun-in-text-property (funcall orig-fun) 'dired-filename))
;;;###autoload
(defun dired-isearch-filenames ()
@@ -3216,9 +3342,14 @@ To continue searching for next match, use command \\[fileloop-continue]."
;;;###autoload
(defun dired-do-query-replace-regexp (from to &optional delimited)
"Do `query-replace-regexp' of FROM with TO, on all marked files.
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
-If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
-with the command \\[tags-loop-continue]."
+If you exit the query-replace loop (\\[keyboard-quit], RET or q), you can
+resume the query replace with the command \\[fileloop-continue]."
(interactive
(let ((common
(query-replace-read-args
@@ -3235,7 +3366,6 @@ with the command \\[tags-loop-continue]."
delimited)
(fileloop-continue))
-(declare-function xref--show-xrefs "xref")
(declare-function xref-query-replace-in-results "xref")
(declare-function project--files-in-directory "project")
@@ -3271,7 +3401,7 @@ REGEXP should use constructs supported by your local `grep' command."
(project--files-in-directory mark ignores "*")
files))
(push mark files)))
- (nreverse marks))
+ (reverse marks))
(message "Searching...")
(setq xrefs
(xref-matches-in-files regexp files))
@@ -3279,12 +3409,17 @@ REGEXP should use constructs supported by your local `grep' command."
(user-error "No matches for: %s" regexp))
(message "Searching...done")
xrefs))))
- (xref--show-xrefs fetcher nil)))
+ (xref-show-xrefs fetcher nil)))
;;;###autoload
(defun dired-do-find-regexp-and-replace (from to)
"Replace matches of FROM with TO, in all marked files.
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
If no files are marked, use the file under point.
For any marked directory, matches in all of its files are replaced,
@@ -3292,7 +3427,10 @@ recursively. However, files matching `grep-find-ignored-files'
and subdirectories matching `grep-find-ignored-directories' are skipped
in the marked directories.
-REGEXP should use constructs supported by your local `grep' command."
+REGEXP should use constructs supported by your local `grep' command.
+
+Also see `query-replace' for user options that affect how this
+function works."
(interactive
(let ((common
(query-replace-read-args
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index bdf416b3edc..9edf8374815 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -1,7 +1,6 @@
;;; dired-x.el --- extra Dired functionality -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 1997, 2001-2022 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1993-2022 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
;; Lawrence R. Dodd <dodd@roebling.poly.edu>
@@ -51,11 +50,6 @@
"Extended directory editing (dired-x)."
:group 'dired)
-(defgroup dired-keys nil
- "Dired keys customizations."
- :prefix "dired-"
- :group 'dired-x)
-
(defcustom dired-bind-vm nil
"Non-nil means \"V\" runs `dired-vm', otherwise \"V\" runs `dired-rmail'.
RMAIL files in the old Babyl format (used before Emacs 23.1)
@@ -63,34 +57,16 @@ contain \"-*- rmail -*-\" at the top, so `dired-find-file'
will run `rmail' on these files. New RMAIL files use the standard
mbox format, and so cannot be distinguished in this way."
:type 'boolean
- :group 'dired-keys)
+ :group 'dired-x)
(defvar dired-bind-jump t)
(make-obsolete-variable 'dired-bind-jump "not used." "28.1")
-(defcustom dired-bind-man t
- "Non-nil means bind `dired-man' to \"N\" in Dired, otherwise do not.
-Setting this variable directly after dired-x is loaded has no effect -
-use \\[customize]."
- :type 'boolean
- :set (lambda (sym val)
- (if (set sym val)
- (define-key dired-mode-map "N" 'dired-man)
- (if (eq 'dired-man (lookup-key dired-mode-map "N"))
- (define-key dired-mode-map "N" nil))))
- :group 'dired-keys)
-
-(defcustom dired-bind-info t
- "Non-nil means bind `dired-info' to \"I\" in Dired, otherwise do not.
-Setting this variable directly after dired-x is loaded has no effect -
-use \\[customize]."
- :type 'boolean
- :set (lambda (sym val)
- (if (set sym val)
- (define-key dired-mode-map "I" 'dired-info)
- (if (eq 'dired-info (lookup-key dired-mode-map "I"))
- (define-key dired-mode-map "I" nil))))
- :group 'dired-keys)
+(defvar dired-bind-man t)
+(make-obsolete-variable 'dired-bind-man "not used." "29.1")
+
+(defvar dired-bind-info t)
+(make-obsolete-variable 'dired-bind-info "not used." "29.1")
(defcustom dired-vm-read-only-folders nil
"If non-nil, \\[dired-vm] will visit all folders read-only.
@@ -101,11 +77,12 @@ files not writable by you are visited read-only."
(other :tag "non-writable only" if-file-read-only))
:group 'dired-x)
-(defcustom dired-omit-size-limit 30000
+(defcustom dired-omit-size-limit 100000
"Maximum size for the \"omitting\" feature.
If nil, there is no maximum size."
:type '(choice (const :tag "no maximum" nil) integer)
- :group 'dired-x)
+ :group 'dired-x
+ :version "29.1")
(defcustom dired-omit-case-fold 'filesystem
"Determine whether \"omitting\" patterns are case-sensitive.
@@ -125,14 +102,49 @@ folding to be used on case-insensitive filesystems only."
(file-name-case-insensitive-p dir)
dired-omit-case-fold))
+(defcustom dired-omit-lines nil
+ "Regexp matching lines to be omitted by `dired-omit-mode'.
+The value can also be a variable whose value is such a regexp.
+The value can also be nil, which means do no line matching.
+
+Some predefined regexp variables for Dired, which you can use as the
+option value:
+
+* `dired-re-inode-size'
+* `dired-re-mark'
+* `dired-re-maybe-mark'
+* `dired-re-dir'
+* `dired-re-sym'
+* `dired-re-exe'
+* `dired-re-perms'
+* `dired-re-dot'
+* `dired-re-no-dot'"
+ :type `(choice
+ (const :tag "Do not match lines to omit" nil)
+ (regexp
+ :tag "Regexp to match lines to omit (default omits executables)"
+ :value ,dired-re-exe)
+ (restricted-sexp
+ :tag "Variable with regexp value (default: `dired-re-exe')"
+ :match-alternatives
+ ((lambda (obj) (and (symbolp obj) (boundp obj))))
+ :value dired-re-exe))
+ :group 'dired-x)
+
;;;###autoload
(define-minor-mode dired-omit-mode
"Toggle omission of uninteresting files in Dired (Dired-Omit mode).
+With prefix argument ARG, enable Dired-Omit mode if ARG is positive,
+and disable it otherwise.
+
+If called from Lisp, enable the mode if ARG is omitted or nil.
+
+Dired-Omit mode is a buffer-local minor mode.
-Dired-Omit mode is a buffer-local minor mode. When enabled in a
-Dired buffer, Dired does not list files whose filenames match
-regexp `dired-omit-files', nor files ending with extensions in
-`dired-omit-extensions'.
+When enabled in a Dired buffer, Dired does not list files whose
+filenames match regexp `dired-omit-files', files ending with
+extensions in `dired-omit-extensions', or files listed on lines
+matching `dired-omit-lines'.
To enable omitting in every Dired buffer, you can put this in
your init file:
@@ -141,10 +153,16 @@ your init file:
See Info node `(dired-x) Omitting Variables' for more information."
:group 'dired-x
- (if dired-omit-mode
- ;; This will mention how many lines were omitted:
- (let ((dired-omit-size-limit nil)) (dired-omit-expunge))
- (revert-buffer)))
+ (if (not dired-omit-mode)
+ (revert-buffer)
+ (let ((dired-omit-size-limit nil)
+ (file-count 0))
+ ;; Omit by file-name match, then omit by line match.
+ ;; Use count of file-name match as INIT-COUNT for line match.
+ ;; Return total count. (Return value is not used anywhere, so far).
+ (setq file-count (dired-omit-expunge))
+ (when dired-omit-lines
+ (dired-omit-expunge dired-omit-lines 'LINEP file-count)))))
(put 'dired-omit-mode 'safe-local-variable 'booleanp)
@@ -207,17 +225,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
(string :tag "Switches"))
:group 'dired-x)
-(defcustom dired-clean-up-buffers-too t
- "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired."
- :type 'boolean
- :group 'dired-x)
-
-(defcustom dired-clean-confirm-killing-deleted-buffers t
- "If nil, don't ask whether to kill buffers visiting deleted files."
- :version "26.1"
- :type 'boolean
- :group 'dired-x)
-
;;; Key bindings
@@ -226,15 +233,10 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
(define-key dired-mode-map "*O" 'dired-mark-omitted)
(define-key dired-mode-map "*." 'dired-mark-extension))
-(when (keymapp (lookup-key dired-mode-map "%"))
- (define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp))
-
(define-key dired-mode-map "\C-x\M-o" 'dired-omit-mode)
(define-key dired-mode-map "\M-(" 'dired-mark-sexp)
(define-key dired-mode-map "\M-!" 'dired-smart-shell-command)
-(define-key dired-mode-map "\M-G" 'dired-goto-subdir)
(define-key dired-mode-map "F" 'dired-do-find-marked-files)
-(define-key dired-mode-map "Y" 'dired-do-relsymlink)
(define-key dired-mode-map "V" 'dired-do-run-mail)
@@ -245,12 +247,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
["Find Files" dired-do-find-marked-files
:help "Find current or marked files"]
"Shell Command...")
- (easy-menu-add-item menu '("Operate")
- ["Relative Symlink to..." dired-do-relsymlink
- :visible (fboundp 'make-symbolic-link)
- :help "Make relative symbolic links for current or \
-marked files"]
- "Hardlink to...")
(easy-menu-add-item menu '("Mark")
["Flag Extension..." dired-flag-extension
:help "Flag files with a certain extension for deletion"]
@@ -264,12 +260,6 @@ marked files"]
:help "Mark files matching `dired-omit-files' \
and `dired-omit-extensions'"]
"Unmark All")
- (easy-menu-add-item menu '("Regexp")
- ["Relative Symlink..." dired-do-relsymlink-regexp
- :visible (fboundp 'make-symbolic-link)
- :help "Make relative symbolic links for files \
-matching regexp"]
- "Hardlink...")
(easy-menu-add-item menu '("Immediate")
["Omit Mode" dired-omit-mode
:style toggle :selected dired-omit-mode
@@ -287,8 +277,6 @@ files"]
"Automatically put on `dired-mode-hook' to get extra Dired features:
\\<dired-mode-map>
\\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm')
- \\[dired-info]\t-- run info on file
- \\[dired-man]\t-- run man on file
\\[dired-do-find-marked-files]\t-- visit all marked files simultaneously
\\[dired-omit-mode]\t-- toggle omitting of files
\\[dired-mark-sexp]\t-- mark by Lisp expression
@@ -297,10 +285,8 @@ To see the options you can set, use \\[customize-group] RET dired-x RET.
See also the functions:
`dired-flag-extension'
`dired-virtual'
- `dired-man'
`dired-vm'
`dired-rmail'
- `dired-info'
`dired-do-find-marked-files'"
(interactive)
;; These must be done in each new dired buffer.
@@ -486,45 +472,61 @@ variables `dired-omit-mode' and `dired-omit-files'."
:type '(repeat string)
:group 'dired-x)
-(defun dired-omit-expunge (&optional regexp)
- "Erases all unmarked files matching REGEXP.
-Does nothing if global variable `dired-omit-mode' is nil, or if called
- non-interactively and buffer is bigger than `dired-omit-size-limit'.
-If REGEXP is nil or not specified, uses `dired-omit-files', and also omits
- filenames ending in `dired-omit-extensions'.
-If REGEXP is the empty string, this function is a no-op.
-
-This functions works by temporarily binding `dired-marker-char' to
-`dired-omit-marker-char' and calling `dired-do-kill-lines'."
- (interactive "sOmit files (regexp): ")
+(defun dired-omit-expunge (&optional regexp linep init-count)
+ "Erase all unmarked files whose names match REGEXP.
+With a prefix arg (non-nil LINEP when called from Lisp), match REGEXP
+against the whole line. Otherwise, match it against the file name.
+
+If REGEXP is nil, use `dired-omit-files', and also omit file names
+ending in `dired-omit-extensions'.
+
+Do nothing if REGEXP is the empty string, `dired-omit-mode' is nil, or
+if called from Lisp and buffer is bigger than `dired-omit-size-limit'.
+
+Optional arg INIT-COUNT is an initial count tha'is added to the number
+of lines omitted by this invocation of `dired-omit-expunge', in the
+status message."
+ (interactive "sOmit files (regexp): \nP")
+ ;; Bind `dired-marker-char' to `dired-omit-marker-char',
+ ;; then call `dired-do-kill-lines'.
(if (and dired-omit-mode
(or (called-interactively-p 'interactive)
(not dired-omit-size-limit)
(< (buffer-size) dired-omit-size-limit)
- (progn
- (when dired-omit-verbose
- (message "Not omitting: directory larger than %d characters."
- dired-omit-size-limit))
- (setq dired-omit-mode nil)
- nil)))
+ (progn
+ (when dired-omit-verbose
+ (message "Not omitting: directory larger than %d characters."
+ dired-omit-size-limit))
+ (setq dired-omit-mode nil)
+ nil)))
(let ((omit-re (or regexp (dired-omit-regexp)))
(old-modified-p (buffer-modified-p))
- count)
- (or (string= omit-re "")
- (let ((dired-marker-char dired-omit-marker-char))
- (when dired-omit-verbose (message "Omitting..."))
- (if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp
- (dired-omit-case-fold-p (if (stringp dired-directory)
- dired-directory
- (car dired-directory))))
- (progn
- (setq count (dired-do-kill-lines
- nil
- (if dired-omit-verbose "Omitted %d line%s." "")))
- (force-mode-line-update))
- (when dired-omit-verbose (message "(Nothing to omit)")))))
- ;; Try to preserve modified state of buffer. So `%*' doesn't appear
- ;; in mode-line of omitted buffers.
+ (count (or init-count 0)))
+ (unless (string= omit-re "")
+ (let ((dired-marker-char dired-omit-marker-char))
+ (when dired-omit-verbose (message "Omitting..."))
+ (if (not (if linep
+ (dired-mark-if
+ (and (= (following-char) ?\s) ; Not already marked
+ (string-match-p
+ omit-re (buffer-substring
+ (line-beginning-position)
+ (line-end-position))))
+ nil)
+ (dired-mark-unmarked-files
+ omit-re nil nil dired-omit-localp
+ (dired-omit-case-fold-p (if (stringp dired-directory)
+ dired-directory
+ (car dired-directory))))))
+ (when dired-omit-verbose (message "(Nothing to omit)"))
+ (setq count (+ count
+ (dired-do-kill-lines
+ nil
+ (if dired-omit-verbose "Omitted %d line%s" "")
+ init-count)))
+ (force-mode-line-update))))
+ ;; Try to preserve modified state, so `%*' doesn't appear in
+ ;; `mode-line'.
(set-buffer-modified-p (and old-modified-p
(save-excursion
(goto-char (point-min))
@@ -639,8 +641,8 @@ you can relist single subdirs using \\[dired-do-redisplay]."
":\n"))
(dired-mode dirname (or switches dired-listing-switches))
(setq mode-name "Virtual Dired"
- revert-buffer-function 'dired-virtual-revert)
- (setq-local dired-subdir-alist nil)
+ revert-buffer-function 'dired-virtual-revert
+ dired-subdir-alist nil)
(dired-build-subdir-alist)
(goto-char (point-min))
(dired-initial-position dirname))
@@ -1021,95 +1023,6 @@ See `dired-guess-shell-alist-user'."
(if (equal val "") default val))))
-;;; Relative symbolic links
-
-(declare-function make-symbolic-link "fileio.c")
-
-(defvar dired-keep-marker-relsymlink ?S
- "See variable `dired-keep-marker-move'.")
-
-(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists)
- "Make a symbolic link (pointing to FILE1) in FILE2.
-The link is relative (if possible), for example
-
- \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\"
-
-results in
-
- \"../../tex/bin/foo\" \"/vol/local/bin/foo\""
- (interactive "FRelSymLink: \nFRelSymLink %s: \np")
- (let (name1 name2 len1 len2 (index 0) sub)
- (setq file1 (expand-file-name file1)
- file2 (expand-file-name file2)
- len1 (length file1)
- len2 (length file2))
- ;; Find common initial file name components:
- (let (next)
- (while (and (setq next (string-search "/" file1 index))
- (< (setq next (1+ next)) (min len1 len2))
- ;; For the comparison, both substrings must end in
- ;; `/', so NEXT is *one plus* the result of the
- ;; string-search.
- ;; E.g., consider the case of linking "/tmp/a/abc"
- ;; to "/tmp/abc" erroneously giving "/tmp/a" instead
- ;; of "/tmp/" as common initial component
- (string-equal (substring file1 0 next)
- (substring file2 0 next)))
- (setq index next))
- (setq name2 file2
- sub (substring file1 0 index)
- name1 (substring file1 index)))
- (if (string-equal sub "/")
- ;; No common initial file name found
- (setq name1 file1)
- ;; Else they have a common parent directory
- (let ((tem (substring file2 index))
- (start 0)
- (count 0))
- ;; Count number of slashes we must compensate for ...
- (while (setq start (string-search "/" tem start))
- (setq count (1+ count)
- start (1+ start)))
- ;; ... and prepend a "../" for each slash found:
- (dotimes (_ count)
- (setq name1 (concat "../" name1)))))
- (make-symbolic-link
- (directory-file-name name1) ; must not link to foo/
- ; (trailing slash!)
- name2 ok-if-already-exists)))
-
-(autoload 'dired-do-create-files "dired-aux")
-
-;;;###autoload
-(defun dired-do-relsymlink (&optional arg)
- "Relative symlink all marked (or next ARG) files into a directory.
-Otherwise make a relative symbolic link to the current file.
-This creates relative symbolic links like
-
- foo -> ../bar/foo
-
-not absolute ones like
-
- foo -> /ugly/file/name/that/may/change/any/day/bar/foo
-
-For absolute symlinks, use \\[dired-do-symlink]."
- (interactive "P")
- (dired-do-create-files 'relsymlink #'dired-make-relative-symlink
- "RelSymLink" arg dired-keep-marker-relsymlink))
-
-(autoload 'dired-mark-read-regexp "dired-aux")
-(autoload 'dired-do-create-files-regexp "dired-aux")
-
-(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name)
- "RelSymlink all marked files containing REGEXP to NEWNAME.
-See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
-for more info."
- (interactive (dired-mark-read-regexp "RelSymLink"))
- (dired-do-create-files-regexp
- #'dired-make-relative-symlink
- "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink))
-
-
;;; Visit all marked files simultaneously
;; Brief Description:
@@ -1181,31 +1094,6 @@ NOSELECT the files are merely found but not selected."
;;; Miscellaneous commands
-;; Run man on files.
-
-(declare-function Man-getpage-in-background "man" (topic))
-
-(defvar manual-program) ; from man.el
-
-(defun dired-man ()
- "Run `man' on this file."
- ;; Used also to say: "Display old buffer if buffer name matches filename."
- ;; but I have no idea what that means.
- (interactive)
- (require 'man)
- (let* ((file (dired-get-filename))
- (manual-program (string-replace "*" "%s"
- (dired-guess-shell-command
- "Man command: " (list file)))))
- (Man-getpage-in-background file)))
-
-;; Run Info on files.
-
-(defun dired-info ()
- "Run `info' on this file."
- (interactive)
- (info (dired-get-filename)))
-
;; Run mail on mail folders.
(declare-function vm-visit-folder "ext:vm" (folder &optional read-only))
@@ -1249,14 +1137,6 @@ otherwise."
;;; Miscellaneous internal functions
-;; This should be a builtin
-(defun dired-buffer-more-recently-used-p (buffer1 buffer2)
- "Return t if BUFFER1 is more recently used than BUFFER2.
-Considers buffers closer to the car of `buffer-list' to be more recent."
- (and (not (equal buffer1 buffer2))
- (memq buffer1 (buffer-list))
- (not (memq buffer1 (memq buffer2 (buffer-list))))))
-
;; Needed if ls -lh is supported and also for GNU ls -ls.
(defun dired-x--string-to-number (str)
"Like `string-to-number' but recognize a trailing unit prefix.
@@ -1458,12 +1338,13 @@ Binding direction based on `dired-x-hands-off-my-keys'."
(interactive)
(if (called-interactively-p 'interactive)
(setq dired-x-hands-off-my-keys
- (not (y-or-n-p "Bind dired-x-find-file over find-file? "))))
+ (not (y-or-n-p (format-message
+ "Bind `dired-x-find-file' over `find-file'?")))))
(unless dired-x-hands-off-my-keys
- (define-key (current-global-map) [remap find-file]
- 'dired-x-find-file)
- (define-key (current-global-map) [remap find-file-other-window]
- 'dired-x-find-file-other-window)))
+ (keymap-set (current-global-map) "<remap> <find-file>"
+ #'dired-x-find-file)
+ (keymap-set (current-global-map) "<remap> <find-file-other-window>"
+ #'dired-x-find-file-other-window)))
;; Now call it so binding is correct. This could go in the :initialize
;; slot, but then dired-x-bind-find-file has to be defined before the
@@ -1531,13 +1412,8 @@ If `current-prefix-arg' is non-nil, uses name at point as guess."
nil (file-name-nondirectory guess)))
(read-file-name prompt default-directory)))
-(define-obsolete-function-alias 'read-filename-at-point
- 'dired-x-read-filename-at-point "24.1") ; is this even needed?
-
-
-;;; Epilog
-
-(define-obsolete-function-alias 'dired-x-submit-report 'report-emacs-bug "24.1")
+(define-obsolete-function-alias 'dired-man #'dired-do-man "29.1")
+(define-obsolete-function-alias 'dired-info #'dired-do-info "29.1")
;; As Barry Warsaw would say: "This might be useful..."
diff --git a/lisp/dired.el b/lisp/dired.el
index 9813fca4359..43563d969f1 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -38,9 +38,7 @@
(eval-when-compile (require 'cl-lib))
;; When bootstrapping dired-loaddefs has not been generated.
(require 'dired-loaddefs nil t)
-
-(declare-function dired-buffer-more-recently-used-p
- "dired-x" (buffer1 buffer2))
+(require 'dnd)
;;; Customizable variables
@@ -105,10 +103,10 @@ If `dired-maybe-use-globstar' is non-nil, then `dired-insert-directory'
checks this alist to enable globstar in the shell subprocess.")
(defcustom dired-chown-program
- (purecopy (cond ((executable-find "chown") "chown")
- ((file-executable-p "/usr/sbin/chown") "/usr/sbin/chown")
- ((file-executable-p "/etc/chown") "/etc/chown")
- (t "chown")))
+ (cond ((executable-find "chown") "chown")
+ ((file-executable-p "/usr/sbin/chown") "/usr/sbin/chown")
+ ((file-executable-p "/etc/chown") "/etc/chown")
+ (t "chown"))
"Name of chown command (usually `chown')."
:group 'dired
:type 'file)
@@ -163,7 +161,7 @@ always set this variable to t."
:type 'boolean
:group 'dired-mark)
-(defcustom dired-trivial-filenames (purecopy "\\`\\.\\.?\\'\\|\\`\\.?#")
+(defcustom dired-trivial-filenames "\\`\\.\\.?\\'\\|\\`\\.?#"
"Regexp of files to skip when finding first file of a directory.
A value of nil means move to the subdir line.
A value of t means move to first file."
@@ -209,6 +207,11 @@ If a character, new links are unconditionally marked with that character."
(character :tag "Mark"))
:group 'dired-mark)
+(defvar dired-keep-marker-relsymlink ?S
+ "Controls marking of newly made relative symbolic links.
+If t, they are marked if and as the files linked to were marked.
+If a character, new links are unconditionally marked with that character.")
+
(defcustom dired-free-space 'first
"Whether and how to display the amount of free disk space in Dired buffers.
If nil, don't display.
@@ -248,6 +251,44 @@ The target is used in the prompt for file copy, rename etc."
(other :tag "Try to guess" t))
:group 'dired)
+
+(defcustom dired-mouse-drag-files nil
+ "If non-nil, allow the mouse to drag files from inside a Dired buffer.
+Dragging the mouse and then releasing it over the window of
+another program will result in that program opening or creating a
+copy of the file underneath the mouse pointer (or all marked
+files if it was marked). This feature is supported only on X
+Windows, Haiku, and Nextstep (macOS or GNUstep).
+
+If the value is `link', then a symbolic link will be created to
+the file instead by the other program (usually a file manager).
+
+If the value is `move', then the default action will be for the
+other program to move the file to a different location. For this
+to work optimally, `auto-revert-mode' should be enabled in the
+Dired buffer.
+
+If the Meta key is held down when the mouse button is pressed,
+then this will always be equivalent to `link'.
+
+If the Control key is held down when the mouse button is pressed,
+then dragging the file will always copy it to the new location.
+
+If the Shift key is held down when the mouse button is pressed,
+then this will always be equivalent to `move'."
+ :set (lambda (option value)
+ (set-default option value)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (derived-mode-p 'dired-mode)
+ (revert-buffer nil t)))))
+ :type '(choice (const :tag "Don't allow dragging" nil)
+ (const :tag "Copy file to new location" t)
+ (const :tag "Move file to new location" t)
+ (const :tag "Create symbolic link to file" link))
+ :group 'dired
+ :version "29.1")
+
(defcustom dired-copy-preserve-time t
"If non-nil, Dired preserves the last-modified time in a file copy.
\(This works on only some systems.)"
@@ -408,7 +449,7 @@ action argument symbol is `window-height' and its value is nil." "24.3")
(defvar dired-file-version-alist)
;;;###autoload
-(defvar dired-directory nil
+(defvar-local dired-directory nil
"The directory name or wildcard spec that this Dired directory lists.
Local to each Dired buffer. May be a list, in which case the car is the
directory name and the cdr is the list of files to mention.
@@ -455,7 +496,7 @@ The directory name must be absolute, but need not be fully expanded.")
(defvar dired-re-dot "^.* \\.\\.?/?$")
;; The subdirectory names in the next two lists are expanded.
-(defvar dired-subdir-alist nil
+(defvar-local dired-subdir-alist nil
"Alist of listed directories and their buffer positions.
Alist elements have the form (DIRNAME . STARTMARKER), where
DIRNAME is the absolute name of the directory and STARTMARKER is
@@ -786,6 +827,9 @@ that commands on the next ARG (instead of the marked) files can
be chained easily.
For any other non-nil value of ARG, use the current file.
+If ARG is `marked', don't return the current file if nothing else
+is marked.
+
If optional third arg SHOW-PROGRESS evaluates to non-nil,
redisplay the dired buffer after each file is processed.
@@ -807,7 +851,7 @@ marked file, return (t FILENAME) instead of (FILENAME)."
;;This warning should not apply any longer, sk 2-Sep-1991 14:10.
`(prog1
(let ((inhibit-read-only t) case-fold-search found results)
- (if ,arg
+ (if (and ,arg (not (eq ,arg 'marked)))
(if (integerp ,arg)
(progn ;; no save-excursion, want to move point.
(dired-repeat-over-lines
@@ -818,8 +862,8 @@ marked file, return (t FILENAME) instead of (FILENAME)."
(if (< ,arg 0)
(nreverse results)
results))
- ;; non-nil, non-integer ARG means use current file:
- (list ,body))
+ ;; non-nil, non-integer, non-marked ARG means use current file:
+ (list ,body))
(let ((regexp (dired-marker-regexp)) next-position)
(save-excursion
(goto-char (point-min))
@@ -844,7 +888,8 @@ marked file, return (t FILENAME) instead of (FILENAME)."
(setq results (cons t results)))
(if found
results
- (list ,body)))))
+ (unless (eq ,arg 'marked)
+ (list ,body))))))
;; save-excursion loses, again
(dired-move-to-filename)))
@@ -1012,8 +1057,11 @@ If a directory or nothing is found at point, return nil."
;;;###autoload
(defun dired (dirname &optional switches)
"\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
-Optional second argument SWITCHES specifies the `ls' options used.
-\(Interactively, use a prefix argument to be able to specify SWITCHES.)
+Optional second argument SWITCHES specifies the options to be used
+when invoking `insert-directory-program', usually `ls', which produces
+the listing of the directory files and their attributes.
+Interactively, a prefix argument will cause the command to prompt
+for SWITCHES.
If DIRNAME is a string, Dired displays a list of files in DIRNAME (which
may also have shell wildcards appended to select certain files).
@@ -1260,39 +1308,42 @@ The return value is the target column for the file names."
;; This differs from dired-buffers-for-dir in that it does not consider
;; subdirs of default-directory and searches for the first match only.
;; Also, the major mode must be MODE.
- (if (and (featurep 'dired-x)
- dired-find-subdir
- ;; Don't try to find a wildcard as a subdirectory.
- (string-equal dirname (file-name-directory dirname)))
- (let* ((cur-buf (current-buffer))
- (buffers (nreverse (dired-buffers-for-dir dirname)))
- (cur-buf-matches (and (memq cur-buf buffers)
- ;; Wildcards must match, too:
- (equal dired-directory dirname))))
- ;; We don't want to switch to the same buffer---
- (setq buffers (delq cur-buf buffers))
- (or (car (sort buffers #'dired-buffer-more-recently-used-p))
- ;; ---unless it's the only possibility:
- (and cur-buf-matches cur-buf)))
- ;; No dired-x, or dired-find-subdir nil.
- (setq dirname (expand-file-name dirname))
- (let (found (blist dired-buffers)) ; was (buffer-list)
- (or mode (setq mode 'dired-mode))
- (while blist
- (if (null (buffer-name (cdr (car blist))))
- (setq blist (cdr blist))
- (with-current-buffer (cdr (car blist))
- (if (and (eq major-mode mode)
- dired-directory ;; nil during find-alternate-file
- (equal dirname
- (expand-file-name
- (if (consp dired-directory)
- (car dired-directory)
- dired-directory))))
- (setq found (cdr (car blist))
- blist nil)
- (setq blist (cdr blist))))))
- found)))
+ ;; We bind `non-essential' in order to avoid hangs in remote buffers
+ ;; with a blocked connection. (Bug#54542)
+ (let ((non-essential t))
+ (if (and (featurep 'dired-x)
+ dired-find-subdir
+ ;; Don't try to find a wildcard as a subdirectory.
+ (string-equal dirname (file-name-directory dirname)))
+ (let* ((cur-buf (current-buffer))
+ (buffers (nreverse (dired-buffers-for-dir dirname)))
+ (cur-buf-matches (and (memq cur-buf buffers)
+ ;; Wildcards must match, too:
+ (equal dired-directory dirname))))
+ ;; We don't want to switch to the same buffer---
+ (setq buffers (delq cur-buf buffers))
+ (or (car (sort buffers #'dired-buffer-more-recently-used-p))
+ ;; ---unless it's the only possibility:
+ (and cur-buf-matches cur-buf)))
+ ;; No dired-x, or dired-find-subdir nil.
+ (setq dirname (expand-file-name dirname))
+ (let (found (blist dired-buffers)) ; was (buffer-list)
+ (or mode (setq mode 'dired-mode))
+ (while blist
+ (if (null (buffer-name (cdr (car blist))))
+ (setq blist (cdr blist))
+ (with-current-buffer (cdr (car blist))
+ (if (and (eq major-mode mode)
+ dired-directory ;; nil during find-alternate-file
+ (equal dirname
+ (expand-file-name
+ (if (consp dired-directory)
+ (car dired-directory)
+ dired-directory))))
+ (setq found (cdr (car blist))
+ blist nil)
+ (setq blist (cdr blist))))))
+ found))))
;;; Read in a new dired buffer
@@ -1336,7 +1387,7 @@ wildcards, erases the buffer, and builds the subdir-alist anew
(goto-char (point-min))
;; Must first make alist buffer local and set it to nil because
;; dired-build-subdir-alist will call dired-clear-alist first
- (setq-local dired-subdir-alist nil)
+ (setq dired-subdir-alist nil)
(dired-build-subdir-alist))
(let ((attributes (file-attributes dirname)))
(if (eq (car attributes) t)
@@ -1674,6 +1725,85 @@ see `dired-use-ls-dired' for more details.")
beg))
beg))))
+(declare-function x-begin-drag "xfns.c")
+
+(defun dired-mouse-drag (event)
+ "Begin a drag-and-drop operation for the file at EVENT.
+If there are marked files and that file is marked, drag every
+other marked file as well. Otherwise, unmark all files."
+ (interactive "e")
+ (when mark-active
+ (deactivate-mark))
+ (let* ((modifiers (event-modifiers event))
+ (action (cond ((memq 'control modifiers) 'copy)
+ ((memq 'shift modifiers) 'move)
+ ((memq 'meta modifiers) 'link)
+ (t (if (memq dired-mouse-drag-files
+ '(copy move link))
+ dired-mouse-drag-files
+ 'copy)))))
+ (save-excursion
+ (with-selected-window (posn-window (event-end event))
+ (goto-char (posn-point (event-end event))))
+ (track-mouse
+ (let ((beginning-position (mouse-pixel-position))
+ new-event)
+ (catch 'track-again
+ (setq new-event (read-event))
+ (if (not (eq (event-basic-type new-event) 'mouse-movement))
+ (when (eq (event-basic-type new-event) 'mouse-1)
+ (push new-event unread-command-events))
+ (let ((current-position (mouse-pixel-position)))
+ ;; If the mouse didn't move far enough, don't
+ ;; inadvertently trigger a drag.
+ (when (and (eq (car current-position) (car beginning-position))
+ (ignore-errors
+ (and (> 3 (abs (- (cadr beginning-position)
+ (cadr current-position))))
+ (> 3 (abs (- (caddr beginning-position)
+ (caddr current-position)))))))
+ (throw 'track-again nil)))
+ ;; We can get an error if there's by some chance no file
+ ;; name at point.
+ (condition-case error
+ (let ((filename (with-selected-window (posn-window
+ (event-end event))
+ (let ((marked-files (dired-map-over-marks (dired-get-filename
+ nil 'no-error-if-not-filep)
+ 'marked))
+ (file-name (dired-get-filename nil 'no-error-if-not-filep)))
+ (if (and marked-files
+ (member file-name marked-files))
+ marked-files
+ (when marked-files
+ (dired-map-over-marks (dired-unmark nil)
+ 'marked))
+ file-name)))))
+ (when filename
+ (if (and (consp filename)
+ (cdr filename))
+ (dnd-begin-drag-files filename nil action t)
+ (dnd-begin-file-drag (if (stringp filename)
+ filename
+ (car filename))
+ nil action t))))
+ (error (when (eq (event-basic-type new-event) 'mouse-1)
+ (push new-event unread-command-events))
+ ;; Errors from `dnd-begin-drag-files' should be
+ ;; treated as user errors, since they should
+ ;; only occur when the user performs an invalid
+ ;; action, such as trying to create a link to
+ ;; a remote file.
+ (user-error (cadr error)))))))))))
+
+(defvar dired-mouse-drag-files-map (let ((keymap (make-sparse-keymap)))
+ (define-key keymap [down-mouse-1] #'dired-mouse-drag)
+ (define-key keymap [C-down-mouse-1] #'dired-mouse-drag)
+ (define-key keymap [S-down-mouse-1] #'dired-mouse-drag)
+ (define-key keymap [M-down-mouse-1] #'dired-mouse-drag)
+ keymap)
+ "Keymap applied to file names when `dired-mouse-drag-files' is enabled.")
+
(defun dired-insert-set-properties (beg end)
"Add various text properties to the lines in the region, from BEG to END."
(save-excursion
@@ -1688,15 +1818,27 @@ see `dired-use-ls-dired' for more details.")
'invisible 'dired-hide-details-information))
(put-text-property (+ (line-beginning-position) 1) (1- (point))
'invisible 'dired-hide-details-detail)
+ (when (and dired-mouse-drag-files (fboundp 'x-begin-drag))
+ (put-text-property (point)
+ (save-excursion
+ (dired-move-to-end-of-filename)
+ (backward-char)
+ (point))
+ 'keymap
+ dired-mouse-drag-files-map))
(add-text-properties
(point)
(progn
(dired-move-to-end-of-filename)
(point))
- '(mouse-face
+ `(mouse-face
highlight
dired-filename t
- help-echo "mouse-2: visit this file in other window"))
+ help-echo ,(if (and dired-mouse-drag-files
+ (fboundp 'x-begin-drag))
+ "down-mouse-1: drag this file to another program
+mouse-2: visit this file in other window"
+ "mouse-2: visit this file in other window")))
(when (< (+ (point) 4) (line-end-position))
(put-text-property (+ (point) 4) (line-end-position)
'invisible 'dired-hide-details-link))))
@@ -1939,8 +2081,10 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
"D" #'dired-do-delete
"G" #'dired-do-chgrp
"H" #'dired-do-hardlink
+ "I" #'dired-do-info
"L" #'dired-do-load
"M" #'dired-do-chmod
+ "N" #'dired-do-man
"O" #'dired-do-chown
"P" #'dired-do-print
"Q" #'dired-do-find-regexp-and-replace
@@ -1948,6 +2092,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
"S" #'dired-do-symlink
"T" #'dired-do-touch
"X" #'dired-do-shell-command
+ "Y" #'dired-do-relsymlink
"Z" #'dired-do-compress
"c" #'dired-do-compress-to
"!" #'dired-do-shell-command
@@ -1977,6 +2122,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
"% H" #'dired-do-hardlink-regexp
"% R" #'dired-do-rename-regexp
"% S" #'dired-do-symlink-regexp
+ "% Y" #'dired-do-relsymlink-regexp
"% &" #'dired-flag-garbage-files
;; Commands for marking and unmarking.
"* *" #'dired-mark-executables
@@ -2028,6 +2174,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
"S-SPC" #'dired-previous-line
"<remap> <next-line>" #'dired-next-line
"<remap> <previous-line>" #'dired-previous-line
+ "M-G" #'dired-goto-subdir
;; hiding
"$" #'dired-hide-subdir
"M-$" #'dired-hide-all
@@ -2154,6 +2301,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
["Symlink..." dired-do-symlink-regexp
:visible (fboundp 'make-symbolic-link)
:help "Make symbolic links for files matching regexp"]
+ ["Relative Symlink..." dired-do-relsymlink-regexp
+ :visible (fboundp 'make-symbolic-link)
+ :help "Make relative symbolic links for files matching regexp"]
["Hardlink..." dired-do-hardlink-regexp
:help "Make hard links for files matching regexp"]
["Upcase" dired-upcase
@@ -2223,6 +2373,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
["Symlink to..." dired-do-symlink
:visible (fboundp 'make-symbolic-link)
:help "Make symbolic links for current or marked files"]
+ ["Relative Symlink to..." dired-do-relsymlink
+ :visible (fboundp 'make-symbolic-link)
+ :help "Make relative symbolic links for current or marked files"]
["Hardlink to..." dired-do-hardlink
:help "Make hard links for current or marked files"]
["Print..." dired-do-print
@@ -2327,7 +2480,7 @@ Type \\[dired-do-copy] to Copy files.
Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches.
Type \\[revert-buffer] to read all currently expanded directories aGain.
This retains all marks and hides subdirs again that were hidden before.
-Use `SPC' and `DEL' to move down and up by lines.
+Use \\`SPC' and \\`DEL' to move down and up by lines.
If Dired ever gets confused, you can either type \\[revert-buffer] \
to read the
@@ -2365,7 +2518,7 @@ Keybindings:
(setq-local buffer-stale-function #'dired-buffer-stale-p)
(setq-local buffer-auto-revert-by-notification t)
(setq-local page-delimiter "\n\n")
- (setq-local dired-directory (or dirname default-directory))
+ (setq dired-directory (or dirname default-directory))
;; list-buffers uses this to display the dir being edited in this buffer.
(setq list-buffers-directory
(expand-file-name (if (listp dired-directory)
@@ -2416,6 +2569,8 @@ If the current buffer can be edited with Wdired, (i.e. the major
mode is `dired-mode'), call `wdired-change-to-wdired-mode'.
Otherwise, toggle `read-only-mode'."
(interactive)
+ (unless (file-exists-p default-directory)
+ (user-error "The current directory no longer exists"))
(when (and (not (file-writable-p default-directory))
(not (y-or-n-p
"Directory isn't writable; edit anyway? ")))
@@ -2756,7 +2911,7 @@ permissions are hidden from view.
See options: `dired-hide-details-hide-symlink-targets' and
`dired-hide-details-hide-information-lines'."
:group 'dired
- (unless (derived-mode-p 'dired-mode)
+ (unless (derived-mode-p 'dired-mode 'wdired-mode)
(error "Not a Dired buffer"))
(dired-hide-details-update-invisibility-spec)
(if dired-hide-details-mode
@@ -2949,12 +3104,10 @@ You can then feed the file name(s) to other commands with \\[yank]."
;;; Keeping Dired buffers in sync with the filesystem and with each other
-(defun dired-buffers-for-dir (dir &optional file subdirs)
+(defun dired-buffers-for-dir (dir &optional file)
"Return a list of buffers for DIR (top level or in-situ subdir).
If FILE is non-nil, include only those whose wildcard pattern (if any)
matches FILE.
-If SUBDIRS is non-nil, also include the dired buffers of
-directories below DIR.
The list is in reverse order of buffer creation, most recent last.
As a side effect, killed dired buffers for DIR are removed from
`dired-buffers'."
@@ -2966,20 +3119,35 @@ As a side effect, killed dired buffers for DIR are removed from
((null (buffer-name buf))
;; Buffer is killed - clean up:
(setq dired-buffers (delq elt dired-buffers)))
- ((dired-in-this-tree-p (car elt) dir)
+ ((dired-in-this-tree-p dir (car elt))
(with-current-buffer buf
- (when (and (or subdirs
- (assoc dir dired-subdir-alist))
- (or (null file)
- (if (stringp dired-directory)
- (let ((wildcards (file-name-nondirectory
- dired-directory)))
- (or (zerop (length wildcards))
- (string-match-p (dired-glob-regexp wildcards)
- file)))
- (member (expand-file-name file dir)
- (cdr dired-directory)))))
- (setq result (cons buf result)))))))
+ (and (assoc dir dired-subdir-alist)
+ (or (null file)
+ (if (stringp dired-directory)
+ (let ((wildcards (file-name-nondirectory
+ dired-directory)))
+ (or (zerop (length wildcards))
+ (string-match-p (dired-glob-regexp wildcards)
+ file)))
+ (member (expand-file-name file dir)
+ (cdr dired-directory))))
+ (setq result (cons buf result)))))))
+ result))
+
+(defun dired-buffers-for-dir-or-subdir (dir)
+ "Return a list of buffers for DIR or a subdirectory thereof.
+As a side effect, killed dired buffers for DIR are removed from
+`dired-buffers'."
+ (setq dir (file-name-as-directory dir))
+ (let (result buf)
+ (dolist (elt dired-buffers)
+ (setq buf (cdr elt))
+ (cond
+ ((null (buffer-name buf))
+ ;; Buffer is killed - clean up:
+ (setq dired-buffers (delq elt dired-buffers)))
+ ((dired-in-this-tree-p (car elt) dir)
+ (setq result (cons buf result)))))
result))
(defun dired-glob-regexp (pattern)
@@ -3335,6 +3503,14 @@ is the directory where the file on this line resides."
(point-max)
(point))))
+;; This should be a builtin
+(defun dired-buffer-more-recently-used-p (buffer1 buffer2)
+ "Return t if BUFFER1 is more recently used than BUFFER2.
+Considers buffers closer to the car of `buffer-list' to be more recent."
+ (and (not (equal buffer1 buffer2))
+ (memq buffer1 (buffer-list))
+ (not (memq buffer1 (memq buffer2 (buffer-list))))))
+
;;; Deleting files
@@ -3535,13 +3711,21 @@ See `dired-delete-file' in case you wish that."
(dired-remove-entry file)
(dired-clean-up-after-deletion file))
-(defvar dired-clean-up-buffers-too)
-(defvar dired-clean-confirm-killing-deleted-buffers)
+(defcustom dired-clean-up-buffers-too t
+ "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired."
+ :type 'boolean
+ :group 'dired)
+
+(defcustom dired-clean-confirm-killing-deleted-buffers t
+ "If nil, don't ask whether to kill buffers visiting deleted files."
+ :type 'boolean
+ :group 'dired
+ :version "26.1")
(defun dired-clean-up-after-deletion (fn)
"Clean up after a deleted file or directory FN.
-Removes any expanded subdirectory of deleted directory. If
-`dired-x' is loaded and `dired-clean-up-buffers-too' is non-nil,
+Removes any expanded subdirectory of deleted directory.
+If `dired-clean-up-buffers-too' is non-nil,
kill any buffers visiting those files, prompting for
confirmation. To disable the confirmation, see
`dired-clean-confirm-killing-deleted-buffers'."
@@ -3558,14 +3742,16 @@ confirmation. To disable the confirmation, see
(file-name-nondirectory fn))))
(not dired-clean-confirm-killing-deleted-buffers))
(kill-buffer buf)))
- (let ((buf-list (dired-buffers-for-dir fn nil 'subdirs)))
+ (let ((buf-list (dired-buffers-for-dir-or-subdir
+ (expand-file-name fn))))
(and buf-list
(or (and dired-clean-confirm-killing-deleted-buffers
(y-or-n-p
(format
- (ngettext "Kill Dired buffer of %s, too? "
- "Kill Dired buffers of %s, too? "
- (length buf-list))
+ (ngettext
+ "Kill Dired buffer of %s, too? "
+ "Kill Dired buffers of %s and its sub-directories, too? "
+ (length buf-list))
(file-name-nondirectory
;; FN may end in a / if `dired-listing-switches'
;; contains -p, so we need to strip that
@@ -3823,7 +4009,11 @@ this subdir."
(let ((inhibit-read-only t))
(dired-repeat-over-lines
(prefix-numeric-value arg)
- (lambda () (delete-char 1) (insert dired-marker-char)))))))
+ (lambda ()
+ (when (or (not (looking-at-p dired-re-dot))
+ (not (equal dired-marker-char dired-del-marker)))
+ (delete-char 1)
+ (insert dired-marker-char))))))))
(defun dired-unmark (arg &optional interactive)
"Unmark the file at point in the Dired buffer.
@@ -4634,6 +4824,42 @@ Interactively with prefix argument, read FILE-NAME."
(read-file-name "Jump to Dired file: "))))
(dired-jump t file-name))
+(defvar-keymap dired-jump-map
+ :doc "Keymap to repeat `dired-jump'. Used in `repeat-mode'."
+ "j" #'dired-jump
+ "C-j" #'dired-jump)
+(put 'dired-jump 'repeat-map 'dired-jump-map)
+
+
+;;; Miscellaneous commands
+
+(declare-function Man-getpage-in-background "man" (topic))
+(declare-function dired-guess-shell-command "dired-x" (prompt files))
+(defvar manual-program) ; from man.el
+
+(defun dired-do-man ()
+ "In Dired, run `man' on this file."
+ (interactive nil dired-mode)
+ (require 'man)
+ ;; FIXME: Move `dired-guess-shell-command' to dired.el to remove the
+ ;; need for requiring `dired-x'.
+ (require 'dired-x)
+ (let* ((file (dired-get-file-for-visit))
+ (manual-program (string-replace "*" "%s"
+ (dired-guess-shell-command
+ "Man command: " (list file)))))
+ (Man-getpage-in-background file)))
+
+(defun dired-do-info ()
+ "In Dired, run `info' on this file."
+ (interactive nil dired-mode)
+ (info (dired-get-file-for-visit)))
+
+(defun dired-do-eww ()
+ "In Dired, visit file in EWW."
+ (interactive nil dired-mode)
+ (eww-open-file (dired-get-file-for-visit)))
+
(provide 'dired)
(run-hooks 'dired-load-hook) ; for your customizations
diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el
index 860aa758bce..897a88398fd 100644
--- a/lisp/display-line-numbers.el
+++ b/lisp/display-line-numbers.el
@@ -108,6 +108,84 @@ the mode is on, set `display-line-numbers' directly."
(define-globalized-minor-mode global-display-line-numbers-mode
display-line-numbers-mode display-line-numbers--turn-on)
+
+
+;;;###autoload
+(defvar header-line-indent ""
+ "String to indent at the start if the header line.
+This is used in `header-line-indent-mode', and buffers that have
+this switched on should have a `header-line-format' that look like:
+
+ (\"\" header-line-indent THE-REST...)
+
+Also see `header-line-indent-width'.")
+
+;;;###autoload
+(defvar header-line-indent-width 0
+ "The width of the current line numbers displayed.
+This is updated when `header-line-indent-mode' is switched on.
+
+Also see `header-line-indent'.")
+
+(defun header-line-indent--line-number-width ()
+ "Return the width taken by `display-line-numbers' in the current buffer."
+ ;; line-number-display-width returns the value for the selected
+ ;; window, which might not be the window in which the current buffer
+ ;; is displayed.
+ (if (not display-line-numbers)
+ 0
+ (let ((cbuf-window (get-buffer-window (current-buffer) t)))
+ (if (window-live-p cbuf-window)
+ (with-selected-window cbuf-window
+ (truncate (line-number-display-width 'columns)))
+ 4))))
+
+(defun header-line-indent--watch-line-number-width (_window)
+ (let ((width (header-line-indent--line-number-width)))
+ (setq header-line-indent-width width)
+ (unless (= (length header-line-indent) width)
+ (setq header-line-indent (make-string width ?\s)))))
+
+(defun header-line-indent--window-scroll-function (window _start)
+ (let ((width (with-selected-window window
+ (truncate (line-number-display-width 'columns)))))
+ (setq header-line-indent-width width)
+ (unless (= (length header-line-indent) width)
+ (setq header-line-indent (make-string width ?\s)))))
+
+;;;###autoload
+(define-minor-mode header-line-indent-mode
+ "Mode to indent the header line in `display-line-numbers-mode' buffers.
+This means that the header line will be kept indented so that it
+has blank space that's as wide as the displayed line numbers in
+the buffer.
+
+Buffers that have this switched on should have a
+`header-line-format' that look like:
+
+ (\"\" header-line-indent THE-REST...)
+
+The `header-line-indent-width' variable is also kept updated, and
+has the width of `header-line-format'. This can be used, for
+instance, in `:align-to' specs, like:
+
+ (space :align-to (+ header-line-indent-width 10))"
+ :lighter nil
+ (if header-line-indent-mode
+ (progn
+ (setq-local header-line-indent ""
+ header-line-indent-width 0)
+ (add-hook 'pre-redisplay-functions
+ #'header-line-indent--watch-line-number-width nil t)
+ (add-hook 'window-scroll-functions
+ #'header-line-indent--window-scroll-function nil t))
+ (setq-local header-line-indent ""
+ header-line-indent-width 0)
+ (remove-hook 'pre-redisplay-functions
+ #'header-line-indent--watch-line-number-width t)
+ (remove-hook 'window-scroll-functions
+ #'header-line-indent--window-scroll-function t)))
+
(provide 'display-line-numbers)
;;; display-line-numbers.el ends here
diff --git a/lisp/dnd.el b/lisp/dnd.el
index 97e81e9bf11..ade61917e96 100644
--- a/lisp/dnd.el
+++ b/lisp/dnd.el
@@ -33,6 +33,9 @@
;;; Customizable variables
+(eval-when-compile
+ (require 'cl-lib))
+
(defgroup dnd nil
"Handling data from drag and drop."
:group 'environment)
@@ -42,8 +45,7 @@
`((,(purecopy "^file:///") . dnd-open-local-file) ; XDND format.
(,(purecopy "^file://") . dnd-open-file) ; URL with host
(,(purecopy "^file:") . dnd-open-local-file) ; Old KDE, Motif, Sun
- (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)
- )
+ (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file))
"The functions to call for different protocols when a drop is made.
This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'.
@@ -57,7 +59,8 @@ If no match is found, the URL is inserted as text by calling `dnd-insert-text'.
The function shall return the action done (move, copy, link or private)
if some action was made, or nil if the URL is ignored."
:version "22.1"
- :type '(repeat (cons (regexp) (function))))
+ :type '(repeat (cons (regexp) (function)))
+ :group 'dnd)
(defcustom dnd-open-remote-file-function
@@ -73,17 +76,82 @@ Predefined functions are `dnd-open-local-file' and `dnd-open-remote-url'.
is the default on MS-Windows. `dnd-open-remote-url' uses `url-handler-mode'
and is the default except for MS-Windows."
:version "22.1"
- :type 'function)
+ :type 'function
+ :group 'dnd)
(defcustom dnd-open-file-other-window nil
"If non-nil, always use `find-file-other-window' to open dropped files."
:version "22.1"
- :type 'boolean)
-
+ :type 'boolean
+ :group 'dnd)
+
+(defcustom dnd-scroll-margin nil
+ "The scroll margin inside a window underneath the cursor during drag-and-drop.
+If the mouse moves this many lines close to the top or bottom of
+a window while dragging text, then that window will be scrolled
+down and up respectively."
+ :type '(choice (const :tag "Don't scroll during mouse movement")
+ (integer :tag "This many lines from window top or bottom"))
+ :version "29.1"
+ :group 'dnd)
+
+(defcustom dnd-indicate-insertion-point nil
+ "Whether or not point should follow the position of the mouse.
+If non-nil, the point of the window underneath the mouse will be
+adjusted to reflect where any text will be inserted upon drop
+when the mouse moves while receiving a drop from another
+program."
+ :type 'boolean
+ :version "29.1"
+ :group 'dnd)
+
+(defcustom dnd-direct-save-remote-files 'x
+ "Whether or not to perform a direct save of remote files.
+This is compatible with less programs, but means dropped files
+will be saved with their actual file names, and not a temporary
+file name provided by TRAMP.
+
+This defaults to `x', which means only to drop that way on X
+Windows."
+ :type '(choice (const :tag "Only use direct save on X Windows" x)
+ (const :tag "Use direct save everywhere" t)
+ (const :tag "Don't use direct save")))
;; Functions
+(defun dnd-handle-movement (posn)
+ "Handle mouse movement to POSN when receiving a drop from another program."
+ (when (windowp (posn-window posn))
+ (with-selected-window (posn-window posn)
+ (when (and dnd-scroll-margin
+ ;; TODO: handle scroll bars reasonably.
+ (not (posn-area posn)))
+ (ignore-errors
+ (let* ((row (cdr (posn-col-row posn)))
+ (window (when (windowp (posn-window posn))
+ (posn-window posn)))
+ (text-height (window-text-height window))
+ ;; Make sure it's possible to scroll both up
+ ;; and down if the margin is too large for the
+ ;; window.
+ (margin (min (/ text-height 3) dnd-scroll-margin)))
+ ;; At 2 lines, the window becomes too small for any
+ ;; meaningful scrolling.
+ (unless (<= text-height 2)
+ (cond
+ ;; Inside the bottom scroll margin, scroll up.
+ ((> row (- text-height margin))
+ (with-selected-window window
+ (scroll-up 1)))
+ ;; Inside the top scroll margin, scroll down.
+ ((< row margin)
+ (with-selected-window window
+ (scroll-down 1))))))))
+ (when dnd-indicate-insertion-point
+ (ignore-errors
+ (goto-char (posn-point posn)))))))
+
(defun dnd-handle-one-url (window action url)
"Handle one dropped url by calling the appropriate handler.
The handler is first located by looking at `dnd-protocol-alist'.
@@ -227,6 +295,276 @@ TEXT is the text as a string, WINDOW is the window where the drop happened."
(insert text))
action)
+
+;;; Functions for dragging stuff to other programs. These build upon
+;;; the lower-level `x-begin-drag' interface, but take care of data
+;;; types and abstracting around the different return values.
+
+(defvar dnd-last-dragged-remote-file nil
+ "If non-nil, the name of a local copy of the last remote file that was dragged.
+This may also be a list of files, if multiple files were dragged.
+It can't be removed immediately after the drag-and-drop operation
+completes, since there is no way to determine when the drop
+target has finished opening it. So instead, this file is removed
+when Emacs exits or the user drags another file.")
+
+(defun dnd-remove-last-dragged-remote-file ()
+ "Remove the local copy of the last remote file to be dragged.
+If `dnd-last-dragged-remote-file' is a list, remove all the files
+in that list instead."
+ (when dnd-last-dragged-remote-file
+ (unwind-protect
+ (if (consp dnd-last-dragged-remote-file)
+ (mapc #'delete-file dnd-last-dragged-remote-file)
+ (delete-file dnd-last-dragged-remote-file))
+ (setq dnd-last-dragged-remote-file nil)))
+ (remove-hook 'kill-emacs-hook
+ #'dnd-remove-last-dragged-remote-file))
+
+(declare-function x-begin-drag "xfns.c")
+
+(defun dnd-begin-text-drag (text &optional frame action allow-same-frame)
+ "Begin dragging TEXT from FRAME.
+Initate a drag-and-drop operation allowing the user to drag text
+from Emacs to another program (the drop target), then block until
+the drop is completed or is cancelled.
+
+If the drop completed, return the action that the drop target
+actually performed, which can be one of the following symbols:
+
+ - `copy', which means TEXT was inserted by the drop target.
+
+ - `move', which means TEXT was inserted, and the caller should
+ additionally delete TEXT from its source (such as the buffer
+ where it originated).
+
+ - `private', which means the drop target chose to perform an
+ unspecified action.
+
+Return nil if the drop was cancelled.
+
+TEXT is a string containing text that will be inserted by the
+program where the drop happened. FRAME is the frame where the
+mouse is currently held down, or nil, which stands for the
+current frame. ACTION is one of the symbols `copy' or `move',
+where `copy' means that the text should be inserted by the drop
+target, and `move' means the same as `copy', but in addition
+the caller might have to delete TEXT from its source after this
+function returns. If ALLOW-SAME-FRAME is nil, ignore any drops
+on FRAME itself.
+
+This function might return immediately if no mouse buttons are
+currently being held down. It should only be called upon a
+`down-mouse-1' (or similar) event."
+ (unless (fboundp 'x-begin-drag)
+ (error "Dragging text from Emacs is not supported by this window system"))
+ (gui-set-selection 'XdndSelection text)
+ (unless action
+ (setq action 'copy))
+ (let ((return-value
+ (x-begin-drag '(;; Traditional X selection targets used by GTK, the
+ ;; Motif drag-and-drop protocols, and programs like
+ ;; Xterm. `STRING' is also used on NS and Haiku.
+ "STRING" "TEXT" "COMPOUND_TEXT" "UTF8_STRING"
+ ;; Used by Xdnd clients that strictly comply with
+ ;; the standard (i.e. Qt programs).
+ "text/plain" "text/plain;charset=utf-8")
+ (cl-ecase action
+ ('copy 'XdndActionCopy)
+ ('move 'XdndActionMove))
+ frame nil allow-same-frame)))
+ (cond
+ ((eq return-value 'XdndActionCopy) 'copy)
+ ((eq return-value 'XdndActionMove) 'move)
+ ((not return-value) nil)
+ (t 'private))))
+
+(defun dnd-begin-file-drag (file &optional frame action allow-same-frame)
+ "Begin dragging FILE from FRAME.
+Initate a drag-and-drop operation allowing the user to drag a file
+from Emacs to another program (the drop target), then block until
+the drop happens or is cancelled.
+
+Return the action that the drop target actually performed, which
+can be one of the following symbols:
+
+ - `copy', which means FILE was opened by the drop target.
+
+ - `move', which means FILE was moved to another location by the
+ drop target.
+
+ - `link', which means a symbolic link was created to FILE by
+ the drop target, usually a file manager.
+
+ - `private', which means the drop target chose to perform an
+ unspecified action.
+
+Return nil if the drop was cancelled.
+
+FILE is the file name that will be sent to the program where the
+drop happened. If it is a remote file, Emacs will make a
+temporary copy and pass that. FRAME is the frame where the mouse
+is currently held down, or nil (which means to use the current
+frame). ACTION is one of the symbols `copy', `move' or `link',
+where `copy' means that the file should be opened or copied by
+the drop target, `move' means the drop target should move the
+file to another location, and `link' means the drop target should
+create a symbolic link to FILE. It is an error to specify `link'
+as the action if FILE is a remote file. If ALLOW-SAME-FRAME is
+nil, any drops on FRAME itself will be ignored.
+
+This function might return immediately if no mouse buttons are
+currently being held down. It should only be called upon a
+`down-mouse-1' (or similar) event."
+ (unless (fboundp 'x-begin-drag)
+ (error "Dragging files from Emacs is not supported by this window system"))
+ (dnd-remove-last-dragged-remote-file)
+ (unless action
+ (setq action 'copy))
+ (if (and (or (and (eq dnd-direct-save-remote-files 'x)
+ (eq (framep (or frame
+ (selected-frame)))
+ 'x))
+ (and dnd-direct-save-remote-files
+ (not (eq dnd-direct-save-remote-files 'x))))
+ (eq action 'copy)
+ (file-remote-p file))
+ (dnd-direct-save file (file-name-nondirectory file)
+ frame allow-same-frame)
+ (let ((original-file file))
+ (when (file-remote-p file)
+ (if (eq action 'link)
+ (error "Cannot create symbolic link to remote file")
+ (setq file (file-local-copy file))
+ (setq dnd-last-dragged-remote-file file)
+ (add-hook 'kill-emacs-hook
+ #'dnd-remove-last-dragged-remote-file)))
+ (gui-set-selection 'XdndSelection
+ (propertize (expand-file-name file) 'text/uri-list
+ (concat "file://"
+ (expand-file-name file))))
+ (let ((return-value
+ (x-begin-drag '(;; Xdnd types used by GTK, Qt, and most other
+ ;; modern programs that expect filenames to
+ ;; be supplied as URIs.
+ "text/uri-list" "text/x-xdnd-username"
+ ;; Traditional X selection targets used by
+ ;; programs supporting the Motif
+ ;; drag-and-drop protocols. Also used by NS
+ ;; and Haiku.
+ "FILE_NAME" "FILE" "HOST_NAME"
+ ;; ToolTalk filename. Mostly used by CDE
+ ;; programs.
+ "_DT_NETFILE")
+ (cl-ecase action
+ ('copy 'XdndActionCopy)
+ ('move 'XdndActionMove)
+ ('link 'XdndActionLink))
+ frame nil allow-same-frame)))
+ (cond
+ ((eq return-value 'XdndActionCopy) 'copy)
+ ((eq return-value 'XdndActionMove)
+ (prog1 'move
+ ;; If original-file is a remote file, delete it from the
+ ;; remote as well.
+ (when (file-remote-p original-file)
+ (ignore-errors
+ (delete-file original-file)))))
+ ((eq return-value 'XdndActionLink) 'link)
+ ((not return-value) nil)
+ (t 'private))))))
+
+(defun dnd-begin-drag-files (files &optional frame action allow-same-frame)
+ "Begin dragging FILES from FRAME.
+This is like `dnd-begin-file-drag', except with multiple files.
+FRAME, ACTION and ALLOW-SAME-FRAME mean the same as in
+`dnd-begin-file-drag'.
+
+FILES is a list of files that will be dragged. If the drop
+target doesn't support dropping multiple files, the first file in
+FILES will be dragged."
+ (unless (fboundp 'x-begin-drag)
+ (error "Dragging files from Emacs is not supported by this window system"))
+ (dnd-remove-last-dragged-remote-file)
+ (let* ((new-files (copy-sequence files))
+ (tem new-files))
+ (while tem
+ (setcar tem (expand-file-name (car tem)))
+ (when (file-remote-p (car tem))
+ (when (eq action 'link)
+ (error "Cannot create symbolic link to remote file"))
+ (condition-case error
+ (progn (setcar tem (file-local-copy (car tem)))
+ (push (car tem) dnd-last-dragged-remote-file))
+ (error (message "Failed to download file: %s" error)
+ (setcar tem nil))))
+ (setq tem (cdr tem)))
+ (when dnd-last-dragged-remote-file
+ (add-hook 'kill-emacs-hook
+ #'dnd-remove-last-dragged-remote-file))
+ ;; Remove any files that failed to download from a remote host.
+ (setq new-files (delq nil new-files))
+ (unless new-files
+ (error "No files were specified or no remote file could be downloaded"))
+ (unless action
+ (setq action 'copy))
+ (gui-set-selection 'XdndSelection
+ (propertize (car new-files)
+ 'text/uri-list
+ (cl-loop for file in new-files
+ collect (concat "file://" file)
+ into targets finally return
+ (apply #'vector targets))
+ 'FILE_NAME (apply #'vector new-files)))
+ (let ((return-value
+ (x-begin-drag '(;; Xdnd types used by GTK, Qt, and most other
+ ;; modern programs that expect filenames to
+ ;; be supplied as URIs.
+ "text/uri-list" "text/x-xdnd-username"
+ ;; Traditional X selection targets used by
+ ;; programs supporting the Motif
+ ;; drag-and-drop protocols. Also used by NS
+ ;; and Haiku.
+ "FILE_NAME" "HOST_NAME")
+ (cl-ecase action
+ ('copy 'XdndActionCopy)
+ ('move 'XdndActionMove)
+ ('link 'XdndActionLink))
+ frame nil allow-same-frame)))
+ (cond
+ ((eq return-value 'XdndActionCopy) 'copy)
+ ((eq return-value 'XdndActionMove)
+ (prog1 'move
+ ;; If original-file is a remote file, delete it from the
+ ;; remote as well.
+ (dolist (original-file files)
+ (when (file-remote-p original-file)
+ (ignore-errors
+ (delete-file original-file))))))
+ ((eq return-value 'XdndActionLink) 'link)
+ ((not return-value) nil)
+ (t 'private)))))
+
+(declare-function x-dnd-do-direct-save "x-dnd.el")
+
+(defun dnd-direct-save (file name &optional frame allow-same-frame)
+ "Drag FILE from FRAME, but do not treat it as an actual file.
+Instead, ask the target window to insert the file with NAME.
+File managers will create a file in the displayed directory with
+the contents of FILE and the name NAME, while text editors will
+insert the contents of FILE in a new document named
+NAME.
+
+ALLOW-SAME-FRAME means the same as in `dnd-begin-file-drag'.
+Return `copy' if the drop was successful, else nil."
+ (setq file (expand-file-name file))
+ (cond ((eq window-system 'x)
+ (when (x-dnd-do-direct-save file name frame
+ allow-same-frame)
+ 'copy))
+ ;; Avoid infinite recursion.
+ (t (let ((dnd-direct-save-remote-files nil))
+ (dnd-begin-file-drag file frame nil allow-same-frame)))))
(provide 'dnd)
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 5b462b24f5a..0f659fb8b37 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2007-2022 Free Software Foundation, Inc.
;;
;; Author: Tassilo Horn <tsdh@gnu.org>
-;; Keywords: files, pdf, ps, dvi
+;; Keywords: files, pdf, ps, dvi, djvu, epub, cbz, fb2, xps, openxps
;; This file is part of GNU Emacs.
@@ -25,17 +25,19 @@
;; Viewing PS/PDF/DVI files requires Ghostscript, `dvipdf' (comes with
;; Ghostscript) or `dvipdfm' (comes with teTeX or TeXLive) and
;; `pdftotext', which comes with xpdf (https://www.foolabs.com/xpdf/)
-;; or poppler (https://poppler.freedesktop.org/).
-;; Djvu documents require `ddjvu' (from DjVuLibre).
-;; ODF files require `soffice' (from LibreOffice).
+;; or poppler (https://poppler.freedesktop.org/). EPUB, CBZ, FB2, XPS
+;; and OXPS documents require `mutool' which comes with mupdf
+;; (https://mupdf.com/index.html). Djvu documents require `ddjvu'
+;; (from DjVuLibre). ODF files require `soffice' (from LibreOffice).
;;; Commentary:
;; DocView is a document viewer for Emacs. It converts a number of
-;; document formats (including PDF, PS, DVI, Djvu and ODF files) to a
-;; set of PNG files, one PNG for each page, and displays the PNG
-;; images inside an Emacs buffer. This buffer uses `doc-view-mode'
-;; which provides convenient key bindings for browsing the document.
+;; document formats (including PDF, PS, DVI, Djvu, ODF, EPUB, CBZ,
+;; FB2, XPS and OXPS files) to a set of PNG (or TIFF for djvu) files,
+;; one image for each page, and displays the images inside an Emacs
+;; buffer. This buffer uses `doc-view-mode' which provides convenient
+;; key bindings for browsing the document.
;;
;; To use it simply open a document file with
;;
@@ -142,12 +144,16 @@
(require 'dired)
(require 'image-mode)
(require 'jka-compr)
+(require 'filenotify)
(eval-when-compile (require 'subr-x))
;;;; Customization Options
(defgroup doc-view nil
- "In-buffer viewer for PDF, PostScript, DVI, and DJVU files."
+ "In-buffer document viewer.
+The viewer handles PDF, PostScript, DVI, DJVU, ODF, EPUB, CBZ,
+FB2, XPS and OXPS files, if the appropriate converter programs
+are available (see Info node `(emacs)Document View')"
:link '(function-link doc-view)
:version "22.2"
:group 'applications
@@ -219,7 +225,68 @@
(defcustom doc-view-resolution 100
"Dots per inch resolution used to render the documents.
Higher values result in larger images."
- :type 'number)
+ :type 'natnum)
+
+(defvar doc-view-doc-type nil
+ "The type of document in the current buffer.
+Can be `dvi', `pdf', `ps', `djvu', `odf', `epub', `cbz', `fb2',
+`xps' or `oxps'.")
+
+(defvar doc-view--epub-stylesheet-watcher nil
+ "File watcher for `doc-view-epub-user-stylesheet'.")
+
+(defun doc-view--epub-reconvert (&optional _event)
+ "Reconvert all epub buffers.
+
+EVENT is unused, but neccesary to work with the filenotify API"
+ (dolist (x (buffer-list))
+ (with-current-buffer x
+ (when (eq doc-view-doc-type 'epub)
+ (doc-view-reconvert-doc)))))
+
+(defun doc-view-custom-set-epub-user-stylesheet (option-name new-value)
+ "Setter for `doc-view-epub-user-stylesheet'.
+
+Reconverts existing epub buffers when the file used as a user
+stylesheet is switched, or its contents modified."
+ (set-default option-name new-value)
+ (file-notify-rm-watch doc-view--epub-stylesheet-watcher)
+ (doc-view--epub-reconvert)
+ (setq doc-view--epub-stylesheet-watcher
+ (when new-value
+ (file-notify-add-watch new-value '(change) #'doc-view--epub-reconvert))))
+
+(defcustom doc-view-epub-user-stylesheet nil
+ "User stylesheet to use when converting EPUB documents to PDF."
+ :type '(choice (const nil)
+ (file :must-match t))
+ :version "29.1"
+ :set #'doc-view-custom-set-epub-user-stylesheet)
+
+(defvar-local doc-view--current-cache-dir nil
+ "Only used internally.")
+
+(defun doc-view-custom-set-epub-font-size (option-name new-value)
+ (set-default option-name new-value)
+ (doc-view--epub-reconvert))
+
+;; FIXME: The doc-view-current-* definitions below are macros because they
+;; map to accessors which we want to use via `setf' as well!
+(defmacro doc-view-current-page (&optional win)
+ `(image-mode-window-get 'page ,win))
+(defmacro doc-view-current-info () '(image-mode-window-get 'info))
+(defmacro doc-view-current-overlay () '(image-mode-window-get 'overlay))
+(defmacro doc-view-current-image () '(image-mode-window-get 'image))
+(defmacro doc-view-current-slice () '(image-mode-window-get 'slice))
+
+(defvar-local doc-view--current-cache-dir nil
+ "Only used internally.")
+
+(defcustom doc-view-epub-font-size nil
+ "Font size in points for EPUB layout."
+ :type '(choice (const nil) integer)
+ :set #'doc-view-custom-set-epub-font-size
+ :version "29.1")
(defcustom doc-view-scale-internally t
"Whether we should try to rescale images ourselves.
@@ -234,7 +301,7 @@ scaling."
Has only an effect if `doc-view-scale-internally' is non-nil and support for
scaling is compiled into Emacs."
:version "24.1"
- :type 'number)
+ :type 'natnum)
(defcustom doc-view-dvipdfm-program "dvipdfm"
"Program to convert DVI files to PDF.
@@ -256,9 +323,7 @@ If this and `doc-view-dvipdfm-program' are set,
`doc-view-dvipdf-program' will be preferred."
:type 'file)
-(define-obsolete-variable-alias 'doc-view-unoconv-program
- 'doc-view-odf->pdf-converter-program
- "24.4")
+(define-obsolete-variable-alias 'doc-view-unoconv-program 'doc-view-odf->pdf-converter-program "24.4")
(defcustom doc-view-odf->pdf-converter-program
(cond
@@ -313,7 +378,8 @@ After such a refresh newly converted pages will be available for
viewing. If set to nil there won't be any refreshes and the
pages won't be displayed before conversion of the whole document
has finished."
- :type 'integer)
+ :type '(choice natnum
+ (const :value nil :tag "No refreshes")))
(defcustom doc-view-continuous nil
"In Continuous mode reaching the page edge advances to next/previous page.
@@ -363,9 +429,6 @@ of the page moves to the previous page."
(defvar-local doc-view--current-timer nil
"Only used internally.")
-(defvar-local doc-view--current-cache-dir nil
- "Only used internally.")
-
(defvar-local doc-view--current-search-matches nil
"Only used internally.")
@@ -380,10 +443,6 @@ files inside an archive it is a temporary copy of
the (uncompressed, extracted) file residing in
`doc-view-cache-directory'.")
-(defvar doc-view-doc-type nil
- "The type of document in the current buffer.
-Can be `dvi', `pdf', `ps', `djvu' or `odf'.")
-
(defvar doc-view-single-page-converter-function nil
"Function to call to convert a single page of the document to a bitmap file.
May operate on the source document or on some intermediate (typically PDF)
@@ -464,17 +523,17 @@ Typically \"page-%s.png\".")
;; It's normal for this operation to result in a very large undo entry.
(setq-local undo-outer-limit (* 2 (buffer-size))))
(cl-labels ((revert ()
- (let ((revert-buffer-preserve-modes t))
- (apply orig-fun args)
- ;; Update the cached version of the pdf file,
- ;; too. This is the one that's used when
- ;; rendering (bug#26996).
- (unless (equal buffer-file-name
- doc-view--buffer-file-name)
- ;; FIXME: Lars says he needed to recreate
- ;; the dir, we should figure out why.
- (doc-view-make-safe-dir doc-view-cache-directory)
- (write-region nil nil doc-view--buffer-file-name)))))
+ (let ((revert-buffer-preserve-modes t))
+ (apply orig-fun args)
+ ;; Update the cached version of the pdf file,
+ ;; too. This is the one that's used when
+ ;; rendering (bug#26996).
+ (unless (equal buffer-file-name
+ doc-view--buffer-file-name)
+ ;; FIXME: Lars says he needed to recreate
+ ;; the dir, we should figure out why.
+ (doc-view-make-safe-dir doc-view-cache-directory)
+ (write-region nil nil doc-view--buffer-file-name)))))
(if (and (eq 'pdf doc-view-doc-type)
(executable-find "pdfinfo"))
;; We don't want to revert if the PDF file is corrupted which
@@ -577,15 +636,6 @@ Typically \"page-%s.png\".")
;;;; Navigation Commands
-;; FIXME: The doc-view-current-* definitions below are macros because they
-;; map to accessors which we want to use via `setf' as well!
-(defmacro doc-view-current-page (&optional win)
- `(image-mode-window-get 'page ,win))
-(defmacro doc-view-current-info () '(image-mode-window-get 'info))
-(defmacro doc-view-current-overlay () '(image-mode-window-get 'overlay))
-(defmacro doc-view-current-image () '(image-mode-window-get 'image))
-(defmacro doc-view-current-slice () '(image-mode-window-get 'slice))
-
(defun doc-view-last-page-number ()
(length doc-view--current-files))
@@ -607,17 +657,16 @@ Typically \"page-%s.png\".")
(propertize
(format "Page %d of %d." page len) 'face 'bold)
;; Tell user if converting isn't finished yet
- (if doc-view--current-converter-processes
- " (still converting...)\n"
- "\n")
- ;; Display context infos if this page matches the last search
- (when (and doc-view--current-search-matches
- (assq page doc-view--current-search-matches))
- (concat (propertize "Search matches:\n" 'face 'bold)
+ (and doc-view--current-converter-processes
+ " (still converting...)")
+ ;; Display context infos if this page matches the last search
+ (when (and doc-view--current-search-matches
+ (assq page doc-view--current-search-matches))
+ (concat "\n" (propertize "Search matches:" 'face 'bold)
(let ((contexts ""))
(dolist (m (cdr (assq page
doc-view--current-search-matches)))
- (setq contexts (concat contexts " - \"" m "\"\n")))
+ (setq contexts (concat contexts "\n - \"" m "\"")))
contexts)))))
;; Update the buffer
;; We used to find the file name from doc-view--current-files but
@@ -738,7 +787,7 @@ at the top edge of the page moves to the previous page."
(interactive)
(while (consp doc-view--current-converter-processes)
(ignore-errors ;; Some entries might not be processes, and maybe
- ;; some are dead already?
+ ; some are dead already?
(kill-process (pop doc-view--current-converter-processes))))
(when doc-view--current-timer
(cancel-timer doc-view--current-timer)
@@ -799,8 +848,8 @@ It's a subdirectory of `doc-view-cache-directory'."
;;;###autoload
(defun doc-view-mode-p (type)
"Return non-nil if document type TYPE is available for `doc-view'.
-Document types are symbols like `dvi', `ps', `pdf', or `odf' (any
-OpenDocument format)."
+Document types are symbols like `dvi', `ps', `pdf', `epub',
+`cbz', `fb2', `xps', `oxps', or`odf' (any OpenDocument format)."
(and (display-graphic-p)
(image-type-available-p 'png)
(cond
@@ -811,16 +860,22 @@ OpenDocument format)."
(and doc-view-dvipdfm-program
(executable-find doc-view-dvipdfm-program)))))
((memq type '(postscript ps eps pdf))
- (or (and doc-view-ghostscript-program
+ (or (and doc-view-ghostscript-program
(executable-find doc-view-ghostscript-program))
- (and doc-view-pdfdraw-program
- (executable-find doc-view-pdfdraw-program))))
+ ;; for pdf also check for `doc-view-pdfdraw-program'
+ (when (eq type 'pdf)
+ (and doc-view-pdfdraw-program
+ (executable-find doc-view-pdfdraw-program)))))
((eq type 'odf)
(and doc-view-odf->pdf-converter-program
(executable-find doc-view-odf->pdf-converter-program)
(doc-view-mode-p 'pdf)))
((eq type 'djvu)
(executable-find "ddjvu"))
+ ((memq type '(epub cbz fb2 xps oxps))
+ ;; first check if `doc-view-pdfdraw-program' is set to mutool
+ (and (string= doc-view-pdfdraw-program "mutool")
+ (executable-find "mutool")))
(t ;; unknown image type
nil))))
@@ -1053,7 +1108,7 @@ Should be invoked when the cached images aren't up-to-date."
;; some file-name-handler-managed dir, for example).
(let* ((default-directory (or (unhandled-file-name-directory
default-directory)
- (expand-file-name "~/")))
+ (expand-file-name "~/")))
(proc (apply #'start-process name doc-view-conversion-buffer
program args)))
(push proc doc-view--current-converter-processes)
@@ -1139,14 +1194,25 @@ The test is performed using `doc-view-pdfdraw-program'."
(search-forward "error: cannot authenticate password" nil t)))
(defun doc-view-pdf->png-converter-mupdf (pdf png page callback)
- (let ((pdf-passwd (if (doc-view-pdf-password-protected-pdfdraw-p pdf)
- (read-passwd "Enter password for PDF file: "))))
+ (let* ((pdf-passwd (if (doc-view-pdf-password-protected-pdfdraw-p pdf)
+ (read-passwd "Enter password for PDF file: ")))
+ (options `(,(concat "-o" png)
+ ,(format "-r%d" (round doc-view-resolution))
+ ,@(if pdf-passwd `("-p" ,pdf-passwd)))))
+ (when (eq doc-view-doc-type 'epub)
+ (when doc-view-epub-font-size
+ (setq options (append options
+ (list (format "-S%s" doc-view-epub-font-size)))))
+ (when doc-view-epub-user-stylesheet
+ (setq options
+ (append options
+ (list (format "-U%s"
+ (expand-file-name
+ doc-view-epub-user-stylesheet)))))))
(doc-view-start-process
"pdf->png" doc-view-pdfdraw-program
`(,@(doc-view-pdfdraw-program-subcommand)
- ,(concat "-o" png)
- ,(format "-r%d" (round doc-view-resolution))
- ,@(if pdf-passwd `("-p" ,pdf-passwd))
+ ,@options
,pdf
,@(if page `(,(format "%d" page))))
callback)))
@@ -1189,7 +1255,8 @@ is named like ODF with the extension turned to pdf."
"Convert PDF-PS to PNG asynchronously."
(funcall
(pcase doc-view-doc-type
- ('pdf doc-view-pdf->png-converter-function)
+ ((or 'pdf 'odf 'epub 'cbz 'fb2 'xps 'oxps)
+ doc-view-pdf->png-converter-function)
('djvu #'doc-view-djvu->tiff-converter-ddjvu)
(_ #'doc-view-ps->png-converter-ghostscript))
pdf-ps png nil
@@ -1227,20 +1294,20 @@ Start by converting PAGES, and then the rest."
(let ((rest (cdr pages)))
(funcall doc-view-single-page-converter-function
pdf (format png (car pages)) (car pages)
- (lambda ()
- (if rest
- (doc-view-document->bitmap pdf png rest)
- ;; Yippie, the important pages are done, update the display.
- (clear-image-cache)
- ;; For the windows that have a message (like "Welcome to
- ;; DocView") display property, clearing the image cache is
- ;; not sufficient.
- (dolist (win (get-buffer-window-list (current-buffer) nil 'visible))
- (with-selected-window win
- (when (stringp (overlay-get (doc-view-current-overlay) 'display))
- (doc-view-goto-page (doc-view-current-page)))))
- ;; Convert the rest of the pages.
- (doc-view-pdf/ps->png pdf png)))))))
+ (lambda ()
+ (if rest
+ (doc-view-document->bitmap pdf png rest)
+ ;; Yippie, the important pages are done, update the display.
+ (clear-image-cache)
+ ;; For the windows that have a message (like "Welcome to
+ ;; DocView") display property, clearing the image cache is
+ ;; not sufficient.
+ (dolist (win (get-buffer-window-list (current-buffer) nil 'visible))
+ (with-selected-window win
+ (when (stringp (overlay-get (doc-view-current-overlay) 'display))
+ (doc-view-goto-page (doc-view-current-page)))))
+ ;; Convert the rest of the pages.
+ (doc-view-pdf/ps->png pdf png)))))))
(defun doc-view-pdf->txt (pdf txt callback)
"Convert PDF to TXT asynchronously and call CALLBACK when finished."
@@ -1337,7 +1404,9 @@ Those files are saved in the directory given by the function
;; Rename to doc.pdf
(rename-file opdf pdf)
(doc-view-pdf/ps->png pdf png-file)))))
- ((or 'pdf 'djvu)
+ ;; The doc-view-mode-p check ensures that epub, cbz, fb2 and
+ ;; (o)xps are handled with mutool
+ ((or 'pdf 'djvu 'epub 'cbz 'fb2 'xps 'oxps)
(let ((pages (doc-view-active-pages)))
;; Convert doc to bitmap images starting with the active pages.
(doc-view-document->bitmap doc-view--buffer-file-name png-file pages)))
@@ -1432,7 +1501,7 @@ dragging it to its bottom-right corner. See also
(defun doc-view-guess-paper-size (iw ih)
"Guess the paper size according to the aspect ratio."
(cl-labels ((div (x y)
- (round (/ (* 100.0 x) y))))
+ (round (/ (* 100.0 x) y))))
(let ((ar (div iw ih))
(al (mapcar (lambda (l)
(list (div (nth 1 l) (nth 2 l)) (car l)))
@@ -1597,7 +1666,8 @@ For now these keys are useful:
\\[image-kill-buffer] : Kill the conversion process and this buffer.
\\[doc-view-kill-proc] : Kill the conversion process.\n")))))
-(declare-function tooltip-show "tooltip" (text &optional use-echo-area))
+(declare-function tooltip-show "tooltip" (text &optional use-echo-area
+ text-face default-face))
(defun doc-view-show-tooltip ()
(interactive)
@@ -1869,6 +1939,8 @@ If BACKWARD is non-nil, jump to the previous match."
("dvi" dvi)
;; PDF
("pdf" pdf) ("epdf" pdf)
+ ;; EPUB
+ ("epub" epub)
;; PostScript
("ps" ps) ("eps" ps)
;; DjVu
@@ -1880,7 +1952,13 @@ If BACKWARD is non-nil, jump to the previous match."
;; Microsoft Office formats (also handled by the odf
;; conversion chain).
("doc" odf) ("docx" odf) ("xls" odf) ("xlsx" odf)
- ("ppt" odf) ("pps" odf) ("pptx" odf) ("rtf" odf))
+ ("ppt" odf) ("pps" odf) ("pptx" odf) ("rtf" odf)
+ ;; CBZ
+ ("cbz" cbz)
+ ;; FB2
+ ("fb2" fb2)
+ ;; (Open)XPS
+ ("xps" xps) ("oxps" oxps))
t))))
(content-types
(save-excursion
@@ -1889,7 +1967,12 @@ If BACKWARD is non-nil, jump to the previous match."
((looking-at "%!") '(ps))
((looking-at "%PDF") '(pdf))
((looking-at "\367\002") '(dvi))
- ((looking-at "AT&TFORM") '(djvu))))))
+ ((looking-at "AT&TFORM") '(djvu))
+ ;; The following pattern actually is for recognizing
+ ;; zip-archives, so that this same association is used for
+ ;; cbz files. This is fine, as cbz files should be handled
+ ;; like epub anyway.
+ ((looking-at "PK") '(epub odf))))))
(setq-local
doc-view-doc-type
(car (or (nreverse (seq-intersection name-types content-types #'eq))
@@ -2202,6 +2285,8 @@ See the command `doc-view-mode' for more information on this mode."
(add-hook 'bookmark-after-jump-hook show-fn-sym)
(bookmark-default-handler bmk)))
+(put 'doc-view-bookmark-jump 'bookmark-handler-type "DocView")
+
;; Obsolete.
(defun doc-view-intersection (l1 l2)
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el
index ea54eea6036..edbe9e494f1 100644
--- a/lisp/dos-fns.el
+++ b/lisp/dos-fns.el
@@ -231,9 +231,6 @@ returned unaltered."
(add-hook 'before-init-hook 'dos-reevaluate-defcustoms)
-(define-obsolete-variable-alias
- 'register-name-alist 'dos-register-name-alist "24.1")
-
(defvar dos-register-name-alist
'((ax . 0) (bx . 1) (cx . 2) (dx . 3) (si . 4) (di . 5)
(cflag . 6) (flags . 7)
@@ -243,8 +240,6 @@ returned unaltered."
(defun dos-make-register ()
(make-vector 8 0))
-(define-obsolete-function-alias 'make-register 'dos-make-register "24.1")
-
(defun dos-register-value (regs name)
(let ((where (cdr (assoc name dos-register-name-alist))))
(cond ((consp where)
@@ -256,8 +251,6 @@ returned unaltered."
(aref regs where))
(t nil))))
-(define-obsolete-function-alias 'register-value 'dos-register-value "24.1")
-
(defun dos-set-register-value (regs name value)
(and (numberp value)
(>= value 0)
@@ -274,9 +267,6 @@ returned unaltered."
(aset regs where (logand value 65535))))))
regs)
-(define-obsolete-function-alias
- 'set-register-value 'dos-set-register-value "24.1")
-
(defsubst dos-intdos (regs)
"Issue the DOS Int 21h with registers REGS.
@@ -284,8 +274,6 @@ REGS should be a vector produced by `dos-make-register'
and `dos-set-register-value', which see."
(int86 33 regs))
-(define-obsolete-function-alias 'intdos 'dos-intdos "24.1")
-
;; Backward compatibility for obsolescent functions which
;; set screen size.
@@ -294,8 +282,6 @@ and `dos-set-register-value', which see."
(interactive)
(set-frame-size (selected-frame) 80 25))
-(define-obsolete-function-alias 'mode25 'dos-mode25 "24.1")
-
(defun dos-mode4350 ()
"Change the number of rows to 43 or 50.
Emacs always tries to set the screen height to 50 rows first.
@@ -307,8 +293,6 @@ that your video hardware might not support 50-line mode."
nil ; the original built-in function returned nil
(set-frame-size (selected-frame) 80 43)))
-(define-obsolete-function-alias 'mode4350 'dos-mode4350 "24.1")
-
(provide 'dos-fns)
;;; dos-fns.el ends here
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
index 0c3d4af569d..2b1fc916d9f 100644
--- a/lisp/ebuff-menu.el
+++ b/lisp/ebuff-menu.el
@@ -48,6 +48,7 @@
(define-key map "\C-m" #'Electric-buffer-menu-select)
(define-key map "\C-l" #'recenter)
(define-key map "s" #'Buffer-menu-save)
+ (define-key map "S" #'tabulated-list-sort)
(define-key map "d" #'Buffer-menu-delete)
(define-key map "k" #'Buffer-menu-delete)
(define-key map "\C-d" #'Buffer-menu-delete-backwards)
diff --git a/lisp/ecomplete.el b/lisp/ecomplete.el
index 260657e0f7a..d5f3fc77560 100644
--- a/lisp/ecomplete.el
+++ b/lisp/ecomplete.el
@@ -65,10 +65,11 @@
:type 'file)
(defcustom ecomplete-database-file-coding-system 'iso-2022-7bit
+ ;; FIXME: We should transition to `utf-8-emacs-unix' somehow!
"Coding system used for writing the ecomplete database file."
:type '(symbol :tag "Coding system"))
-(defcustom ecomplete-sort-predicate 'ecomplete-decay
+(defcustom ecomplete-sort-predicate #'ecomplete-decay
"Predicate to use when sorting matched.
The predicate is called with two parameters that represent the
completion. Each parameter is a list where the first element is
@@ -95,13 +96,18 @@ string that was matched."
(defun ecomplete-add-item (type key text)
"Add item TEXT of TYPE to the database, using KEY as the identifier."
+ (unless ecomplete-database (ecomplete-setup))
(let ((elems (assq type ecomplete-database))
(now (time-convert nil 'integer))
entry)
(unless elems
(push (setq elems (list type)) ecomplete-database))
(if (setq entry (assoc key (cdr elems)))
- (setcdr entry (list (1+ (cadr entry)) now text))
+ (pcase-let ((`(,_key ,count ,_time ,oldtext) entry))
+ (setcdr entry (list (1+ count) now
+ ;; Preserve the "more complete" text.
+ (if (>= (length text) (length oldtext))
+ text oldtext))))
(nconc elems (list (list key 1 now text))))))
(defun ecomplete-get-item (type key)
@@ -110,19 +116,23 @@ string that was matched."
(defun ecomplete-save ()
"Write the .ecompleterc file."
- (with-temp-buffer
- (let ((coding-system-for-write ecomplete-database-file-coding-system))
- (insert "(")
- (cl-loop for (type . elems) in ecomplete-database
- do
- (insert (format "(%s\n" type))
- (dolist (entry elems)
- (prin1 entry (current-buffer))
- (insert "\n"))
- (insert ")\n"))
- (insert ")")
- (write-region (point-min) (point-max)
- ecomplete-database-file nil 'silent))))
+ ;; If the database is empty, it might be because we haven't called
+ ;; `ecomplete-setup', so better not save at all, lest we lose the real
+ ;; database!
+ (when ecomplete-database
+ (with-temp-buffer
+ (let ((coding-system-for-write ecomplete-database-file-coding-system))
+ (insert "(")
+ (cl-loop for (type . elems) in ecomplete-database
+ do
+ (insert (format "(%s\n" type))
+ (dolist (entry elems)
+ (prin1 entry (current-buffer))
+ (insert "\n"))
+ (insert ")\n"))
+ (insert ")")
+ (write-region (point-min) (point-max)
+ ecomplete-database-file nil 'silent)))))
(defun ecomplete-get-matches (type match)
(let* ((elems (cdr (assq type ecomplete-database)))
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 2561994f7bd..bdc50c5885a 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -62,6 +62,7 @@
;;; Code:
(require 'cl-lib)
+(require 'seq)
(require 'kmacro)
;;; The user-level commands for editing macros.
@@ -72,11 +73,35 @@ Default nil means to write characters above \\177 in octal notation."
:type 'boolean
:group 'kmacro)
-(defvar edmacro-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-c" #'edmacro-finish-edit)
- (define-key map "\C-c\C-q" #'edmacro-insert-key)
- map))
+(defvar-keymap edmacro-mode-map
+ "C-c C-c" #'edmacro-finish-edit
+ "C-c C-q" #'edmacro-insert-key)
+
+(defface edmacro-label
+ '((default :inherit bold)
+ (((class color) (background dark)) :foreground "light blue")
+ (((min-colors 88) (class color) (background light)) :foreground "DarkBlue")
+ (((class color) (background light)) :foreground "blue")
+ (t :inherit bold))
+ "Face used for labels in `edit-kbd-macro'."
+ :version "29.1"
+ :group 'kmacro)
+
+(defvar edmacro-mode-font-lock-keywords
+ `((,(rx bol (group (or "Command" "Key" "Macro") ":")) 0 'edmacro-label)
+ (,(rx bol
+ (group ";; Keyboard Macro Editor. Press ")
+ (group (*? any))
+ (group " to finish; press "))
+ (1 'font-lock-comment-face)
+ (2 'help-key-binding)
+ (3 'font-lock-comment-face)
+ (,(rx (group (*? any))
+ (group " to cancel" (* any)))
+ nil nil
+ (1 'help-key-binding)
+ (2 'font-lock-comment-face)))
+ (,(rx (one-or-more ";") (zero-or-more any)) 0 'font-lock-comment-face)))
(defvar edmacro-store-hook)
(defvar edmacro-finish-hook)
@@ -86,7 +111,7 @@ Default nil means to write characters above \\177 in octal notation."
(defun edit-kbd-macro (keys &optional prefix finish-hook store-hook)
"Edit a keyboard macro.
At the prompt, type any key sequence which is bound to a keyboard macro.
-Or, type `\\[kmacro-end-and-call-macro]' or RET to edit the last
+Or, type `\\[kmacro-end-and-call-macro]' or \\`RET' to edit the last
keyboard macro, `\\[view-lossage]' to edit the last 300
keystrokes as a keyboard macro, or `\\[execute-extended-command]'
to edit a macro by its command name.
@@ -99,8 +124,7 @@ With a prefix argument, format the macro in a more concise way."
(when keys
(let ((cmd (if (arrayp keys) (key-binding keys) keys))
(cmd-noremap (when (arrayp keys) (key-binding keys nil t)))
- (mac nil) (mac-counter nil) (mac-format nil)
- kmacro)
+ (mac nil) (mac-counter nil) (mac-format nil))
(cond (store-hook
(setq mac keys)
(setq cmd nil))
@@ -131,10 +155,10 @@ With a prefix argument, format the macro in a more concise way."
(t
(setq mac cmd)
(setq cmd nil)))
- (when (setq kmacro (kmacro-extract-lambda mac))
- (setq mac (car kmacro)
- mac-counter (nth 1 kmacro)
- mac-format (nth 2 kmacro)))
+ (when (kmacro-p mac)
+ (setq mac (kmacro--keys mac)
+ mac-counter (kmacro--counter mac)
+ mac-format (kmacro--format mac)))
(unless (arrayp mac)
(error "Key sequence %s is not a keyboard macro"
(key-description keys)))
@@ -154,9 +178,18 @@ With a prefix argument, format the macro in a more concise way."
(setq-local edmacro-original-buffer oldbuf)
(setq-local edmacro-finish-hook finish-hook)
(setq-local edmacro-store-hook store-hook)
+ (setq-local font-lock-defaults
+ '(edmacro-mode-font-lock-keywords nil nil nil nil))
+ (setq font-lock-multiline nil)
(erase-buffer)
- (insert ";; Keyboard Macro Editor. Press C-c C-c to finish; "
- "press C-x k RET to cancel.\n")
+ (insert (substitute-command-keys
+ (concat
+ ;; When editing this, make sure to update
+ ;; `edmacro-mode-font-lock-keywords' to match.
+ ";; Keyboard Macro Editor. Press \\[edmacro-finish-edit] "
+ "to finish; press \\[kill-buffer] \\`RET' to cancel.\n")
+ ;; Use 'no-face argument to not conflict with font-lock.
+ 'no-face))
(insert ";; Original keys: " fmt "\n")
(unless store-hook
(insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n")
@@ -222,7 +255,7 @@ or nil, use a compact 80-column format."
;;; Commands for *Edit Macro* buffer.
(defun edmacro-finish-edit ()
- (interactive)
+ (interactive nil edmacro-mode)
(unless (eq major-mode 'edmacro-mode)
(error
"This command is valid only in buffers created by `edit-kbd-macro'"))
@@ -252,15 +285,14 @@ or nil, use a compact 80-column format."
((looking-at "Key:\\(.*\\)$")
(when edmacro-store-hook
(error "\"Key\" line not allowed in this context"))
- (let ((key (edmacro-parse-keys
- (match-string 1))))
+ (let ((key (kbd (match-string 1))))
(unless (equal key "")
(if (equal key "none")
(setq no-keys t)
(push key keys)
(let ((b (key-binding key)))
(and b (commandp b) (not (arrayp b))
- (not (kmacro-extract-lambda b))
+ (not (kmacro-p b))
(or (not (fboundp b))
(not (or (arrayp (symbol-function b))
(get b 'kmacro))))
@@ -313,10 +345,7 @@ or nil, use a compact 80-column format."
(when cmd
(if (= (length mac) 0)
(fmakunbound cmd)
- (fset cmd
- (if (and mac-counter mac-format)
- (kmacro-lambda-form mac mac-counter mac-format)
- mac))))
+ (fset cmd (kmacro mac mac-counter mac-format))))
(if no-keys
(when cmd
(cl-loop for key in (where-is-internal cmd '(keymap)) do
@@ -327,10 +356,8 @@ or nil, use a compact 80-column format."
(cl-loop for key in keys do
(global-set-key key
(or cmd
- (if (and mac-counter mac-format)
- (kmacro-lambda-form
- mac mac-counter mac-format)
- mac))))))))))
+ (kmacro mac mac-counter
+ mac-format))))))))))
(kill-buffer buf)
(when (buffer-name obuf)
(switch-to-buffer obuf))
@@ -339,7 +366,7 @@ or nil, use a compact 80-column format."
(defun edmacro-insert-key (key)
"Insert the written name of a KEY in the buffer."
- (interactive "kKey to insert: ")
+ (interactive "kKey to insert: " edmacro-mode)
(if (bolp)
(insert (edmacro-format-keys key t) "\n")
(insert (edmacro-format-keys key) " ")))
@@ -347,7 +374,7 @@ or nil, use a compact 80-column format."
(defun edmacro-mode ()
"\\<edmacro-mode-map>Keyboard Macro Editing mode. Press \
\\[edmacro-finish-edit] to save and exit.
-To abort the edit, just kill this buffer with \\[kill-buffer] RET.
+To abort the edit, just kill this buffer with \\[kill-buffer] \\`RET'.
Press \\[edmacro-insert-key] to insert the name of any key by typing the key.
@@ -537,8 +564,8 @@ doubt, use whitespace."
((integerp ch)
(concat
(cl-loop for pf across "ACHMsS"
- for bit in '(?\A-\^@ ?\C-\^@ ?\H-\^@
- ?\M-\^@ ?\s-\^@ ?\S-\^@)
+ for bit in '( ?\A-\0 ?\C-\0 ?\H-\0
+ ?\M-\0 ?\s-\0 ?\S-\0)
when (/= (logand ch bit) 0)
concat (format "%c-" pf))
(let ((ch2 (logand ch (1- (ash 1 18)))))
@@ -645,9 +672,9 @@ This function assumes that the events can be stored in a string."
;;; Parsing a human-readable keyboard macro.
-(defun edmacro-parse-keys (string &optional need-vector)
+(defun edmacro-parse-keys (string &optional _need-vector)
(let ((result (kbd string)))
- (if (and need-vector (stringp result))
+ (if (stringp result)
(seq-into result 'vector)
result)))
diff --git a/lisp/ehelp.el b/lisp/ehelp.el
index 8c1555249ca..0c2f02639fc 100644
--- a/lisp/ehelp.el
+++ b/lisp/ehelp.el
@@ -76,7 +76,10 @@
(define-key map [?\C-7] 'electric-help-undefined)
(define-key map [?\C-8] 'electric-help-undefined)
(define-key map [?\C-9] 'electric-help-undefined)
- (define-key map (char-to-string help-char) 'electric-help-help)
+ (define-key map (if (characterp help-char)
+ (char-to-string help-char)
+ (vector help-char))
+ 'electric-help-help)
(define-key map "?" 'electric-help-help)
(define-key map " " 'scroll-up)
(define-key map [?\S-\ ] 'scroll-down)
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el
index c3fd90e5bfd..4b901071cd9 100644
--- a/lisp/elec-pair.el
+++ b/lisp/elec-pair.el
@@ -188,6 +188,30 @@ be considered.")
;; I also find it often preferable not to pair next to a word.
(eq (char-syntax (following-char)) ?w)))
+(defmacro electric-pair--with-syntax (string-or-comment &rest body)
+ "Run BODY with appropriate syntax table active.
+STRING-OR-COMMENT is the start position of the string/comment
+in which we are, if applicable.
+Uses the text-mode syntax table if within a string or a comment."
+ (declare (debug t) (indent 1))
+ `(electric-pair--with-syntax-1 ,string-or-comment (lambda () ,@body)))
+
+(defun electric-pair--with-syntax-1 (string-or-comment body-fun)
+ (if (not string-or-comment)
+ (funcall body-fun)
+ ;; Here we assume that the `syntax-ppss' cache has already been filled
+ ;; past `string-or-comment' with data corresponding to the "normal" syntax
+ ;; (this should be the case because STRING-OR-COMMENT was returned
+ ;; in the `nth 8' of `syntax-ppss').
+ ;; Maybe we should narrow-to-region so that `syntax-ppss' uses the narrow
+ ;; cache?
+ (syntax-ppss-flush-cache string-or-comment)
+ (let ((syntax-propertize-function nil))
+ (unwind-protect
+ (with-syntax-table electric-pair-text-syntax-table
+ (funcall body-fun))
+ (syntax-ppss-flush-cache string-or-comment)))))
+
(defun electric-pair-syntax-info (command-event)
"Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START).
@@ -202,13 +226,11 @@ inside a comment or string."
(post-string-or-comment (nth 8 (syntax-ppss (point))))
(string-or-comment (and post-string-or-comment
pre-string-or-comment))
- (table (if string-or-comment
- electric-pair-text-syntax-table
- (syntax-table)))
- (table-syntax-and-pair (with-syntax-table table
- (list (char-syntax command-event)
- (or (matching-paren command-event)
- command-event))))
+ (table-syntax-and-pair
+ (electric-pair--with-syntax string-or-comment
+ (list (char-syntax command-event)
+ (or (matching-paren command-event)
+ command-event))))
(fallback (if string-or-comment
(append electric-pair-text-pairs
electric-pair-pairs)
@@ -237,26 +259,10 @@ inside a comment or string."
(electric-layout-allow-duplicate-newlines t))
(self-insert-command 1)))
-(cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body)
- "Like `with-syntax-table', but flush the `syntax-ppss' cache afterwards.
-Use this instead of (with-syntax-table TABLE BODY) when BODY
-contains code which may update the `syntax-ppss' cache. This
-includes calling `parse-partial-sexp' and any sexp-based movement
-functions when `parse-sexp-lookup-properties' is non-nil. The
-cache is flushed from position START, defaulting to point."
- (declare (debug ((form &optional form) body)) (indent 1))
- (let ((start-var (make-symbol "start")))
- `(let ((syntax-propertize-function #'ignore)
- (,start-var ,(or start '(point))))
- (unwind-protect
- (with-syntax-table ,table
- ,@body)
- (syntax-ppss-flush-cache ,start-var)))))
-
(defun electric-pair--syntax-ppss (&optional pos where)
"Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'.
-WHERE is a list defaulting to '(string comment) and indicates
+WHERE is a list defaulting to \\='(string comment) and indicates
when to fallback to `parse-partial-sexp'."
(let* ((pos (or pos (point)))
(where (or where '(string comment)))
@@ -271,8 +277,7 @@ when to fallback to `parse-partial-sexp'."
(skip-syntax-forward " >!")
(point)))))
(if s-or-c-start
- (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table
- s-or-c-start)
+ (electric-pair--with-syntax s-or-c-start
(parse-partial-sexp s-or-c-start pos))
;; HACK! cc-mode apparently has some `syntax-ppss' bugs
(if (memq major-mode '(c-mode c++ mode))
@@ -290,7 +295,8 @@ when to fallback to `parse-partial-sexp'."
(defun electric-pair--balance-info (direction string-or-comment)
"Examine lists forward or backward according to DIRECTION's sign.
-STRING-OR-COMMENT is info suitable for running `parse-partial-sexp'.
+STRING-OR-COMMENT is the position of the start of the comment/string
+in which we are, if applicable.
Return a cons of two descriptions (MATCHED-P . PAIR) for the
innermost and outermost lists that enclose point. The outermost
@@ -301,9 +307,6 @@ If the outermost list is matched, don't rely on its PAIR.
If point is not enclosed by any lists, return ((t) . (t))."
(let* (innermost
outermost
- (table (if string-or-comment
- electric-pair-text-syntax-table
- (syntax-table)))
(at-top-level-or-equivalent-fn
;; called when `scan-sexps' ran perfectly, when it found
;; a parenthesis pointing in the direction of travel.
@@ -325,11 +328,11 @@ If point is not enclosed by any lists, return ((t) . (t))."
(cond ((< direction 0)
(condition-case nil
(eq (char-after pos)
- (electric-pair--with-uncached-syntax
- (table)
- (matching-paren
- (char-before
- (scan-sexps (point) 1)))))
+ (electric-pair--with-syntax
+ string-or-comment
+ (matching-paren
+ (char-before
+ (scan-sexps (point) 1)))))
(scan-error nil)))
(t
;; In this case, no need to use
@@ -343,7 +346,8 @@ If point is not enclosed by any lists, return ((t) . (t))."
(opener (char-after start)))
(and start
(eq (char-before pos)
- (or (with-syntax-table table
+ (or (electric-pair--with-syntax
+ string-or-comment
(matching-paren opener))
opener))))))))
(actual-pair (if (> direction 0)
@@ -356,7 +360,7 @@ If point is not enclosed by any lists, return ((t) . (t))."
(save-excursion
(while (not outermost)
(condition-case err
- (electric-pair--with-uncached-syntax (table)
+ (electric-pair--with-syntax string-or-comment
(scan-sexps (point) (if (> direction 0)
(point-max)
(- (point-max))))
@@ -498,13 +502,13 @@ The decision is taken by order of preference:
corresponding delimiter for C;
* According to C alone, by looking C up in the tables
- `electric-pair-paris' or `electric-pair-text-pairs' (which
+ `electric-pair-pairs' or `electric-pair-text-pairs' (which
see);
* According to C's syntax and the syntactic state of the buffer
(both as defined by the major mode's syntax table). This is
- done by looking up up the variables
- `electric-pair-inhibit-predicate', `electric-pair-skip-self'
+ done by looking up the variables
+ `electric-pair-inhibit-predicate', `electric-pair-skip-self'
and `electric-pair-skip-whitespace' (which see)."
(let* ((pos (and electric-pair-mode (electric--after-char-pos)))
(skip-whitespace-info))
diff --git a/lisp/electric.el b/lisp/electric.el
index 905d4a87c78..0cf3a299cfa 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -310,10 +310,16 @@ column specified by the function `current-left-margin'."
;;;###autoload
(define-minor-mode electric-indent-mode
- "Toggle on-the-fly reindentation (Electric Indent mode).
+ "Toggle on-the-fly reindentation of text lines (Electric Indent mode).
When enabled, this reindents whenever the hook `electric-indent-functions'
-returns non-nil, or if you insert a character from `electric-indent-chars'.
+returns non-nil, or if you insert one of the \"electric characters\".
+The electric characters normally include the newline, but can
+also include other characters as needed by the major mode; see
+`electric-indent-chars' for the actual list.
+
+By \"reindent\" we mean remove any existing indentation, and then
+indent the line according to context and rules of the major mode.
This is a global minor mode. To toggle the mode in a single buffer,
use `electric-indent-local-mode'."
@@ -614,7 +620,7 @@ This requotes when a quoting key is typed."
(define-minor-mode electric-quote-mode
"Toggle on-the-fly requoting (Electric Quote mode).
-When enabled, as you type this replaces \\=` with ‘, \\=' with ’,
+When enabled, as you type this replaces \\=` with \\=‘, \\=' with \\=’,
\\=`\\=` with “, and \\='\\=' with ”. This occurs only in comments, strings,
and text paragraphs, and these are selectively controlled with
`electric-quote-comment', `electric-quote-string', and
diff --git a/lisp/elide-head.el b/lisp/elide-head.el
index dab51cabc41..90bf1fe35b5 100644
--- a/lisp/elide-head.el
+++ b/lisp/elide-head.el
@@ -26,12 +26,12 @@
;; notices) in file headers to avoid clutter when you know what it
;; says.
;;
-;; `elide-head-headers-to-hide' controls what is elided by the command
-;; `elide-head'. A buffer-local invisible overlay manages the
-;; elision.
+;; `elide-head-headers-to-hide' controls what is elided by the minor
+;; mode `elide-head-mode'. A buffer-local invisible overlay manages
+;; the elision.
-;; You might add `elide-head' to appropriate major mode hooks or to
-;; `find-file-hook'. Please do not do this in site init files. If
+;; You might add `elide-head-mode' to appropriate major mode hooks or
+;; to `find-file-hook'. Please do not do this in site init files. If
;; you do, information may be hidden from users who don't know it
;; already.
@@ -73,13 +73,76 @@
The cars of elements of the list are searched for in order. Text is
elided with an invisible overlay from the end of the line where the
first match is found to the end of the match for the corresponding
-cdr."
+cdr.
+
+This affects `elide-head-mode'."
:type '(alist :key-type (regexp :tag "Start regexp")
:value-type (regexp :tag "End regexp"))
:version "29.1")
(defvar-local elide-head-overlay nil)
+(defun elide-head--delete-overlay ()
+ "Delete the overlay in `elide-head-overlay'."
+ (when (overlayp elide-head-overlay)
+ (delete-overlay elide-head-overlay)))
+
+(defun elide-head--hide ()
+ "Hide elided (hidden) headers."
+ (save-excursion
+ (save-restriction
+ (let ((rest elide-head-headers-to-hide)
+ beg end)
+ (widen)
+ (goto-char (point-min))
+ (while rest
+ (save-excursion
+ (when (re-search-forward (caar rest) nil t)
+ (setq beg (point))
+ (when (re-search-forward (cdar rest) nil t)
+ (setq end (point-marker)
+ rest nil))))
+ (if rest (setq rest (cdr rest))))
+ (if (not (and beg end))
+ (if (called-interactively-p 'interactive)
+ (message "No header found"))
+ (goto-char beg)
+ (end-of-line)
+ (if (overlayp elide-head-overlay)
+ (move-overlay elide-head-overlay (point-marker) end)
+ (setq elide-head-overlay (make-overlay (point-marker) end)))
+ (overlay-put elide-head-overlay 'invisible t)
+ (overlay-put elide-head-overlay 'evaporate t)
+ (overlay-put elide-head-overlay 'after-string "..."))))))
+
+(defun elide-head--show ()
+ "Show elided (hidden) headers."
+ (if (and (overlayp elide-head-overlay)
+ (overlay-buffer elide-head-overlay))
+ (elide-head--delete-overlay)
+ (if (called-interactively-p 'interactive)
+ (message "No header hidden"))))
+
+;;;###autoload
+(define-minor-mode elide-head-mode
+ "Toggle eliding (hiding) header material in the current buffer.
+
+When Elide Header mode is enabled, headers are hidden according
+to `elide-head-headers-to-hide'.
+
+This is suitable as an entry on `find-file-hook' or appropriate
+mode hooks."
+ :group 'elide-head
+ (if elide-head-mode
+ (progn
+ (elide-head--hide)
+ (add-hook 'change-major-mode-hook 'elide-head--delete-overlay nil 'local))
+ (elide-head--show)
+ (remove-hook 'change-major-mode-hook 'elide-head--delete-overlay 'local)))
+
+
+;;; Obsolete
+
;;;###autoload
(defun elide-head (&optional arg)
"Hide header material in buffer according to `elide-head-headers-to-hide'.
@@ -88,43 +151,17 @@ The header is made invisible with an overlay. With a prefix arg, show
an elided material again.
This is suitable as an entry on `find-file-hook' or appropriate mode hooks."
+ (declare (obsolete elide-head-mode "29.1"))
(interactive "P")
(if arg
- (elide-head-show)
- (save-excursion
- (save-restriction
- (let ((rest elide-head-headers-to-hide)
- beg end)
- (widen)
- (goto-char (point-min))
- (while rest
- (save-excursion
- (when (re-search-forward (caar rest) nil t)
- (setq beg (point))
- (when (re-search-forward (cdar rest) nil t)
- (setq end (point-marker)
- rest nil))))
- (if rest (setq rest (cdr rest))))
- (if (not (and beg end))
- (if (called-interactively-p 'interactive)
- (message "No header found"))
- (goto-char beg)
- (end-of-line)
- (if (overlayp elide-head-overlay)
- (move-overlay elide-head-overlay (point-marker) end)
- (setq elide-head-overlay (make-overlay (point-marker) end)))
- (overlay-put elide-head-overlay 'invisible t)
- (overlay-put elide-head-overlay 'evaporate t)
- (overlay-put elide-head-overlay 'after-string "...")))))))
+ (elide-head-mode -1)
+ (elide-head-mode 1)))
(defun elide-head-show ()
"Show a header in the current buffer elided by \\[elide-head]."
+ (declare (obsolete elide-head-mode "29.1"))
(interactive)
- (if (and (overlayp elide-head-overlay)
- (overlay-buffer elide-head-overlay))
- (delete-overlay elide-head-overlay)
- (if (called-interactively-p 'interactive)
- (message "No header hidden"))))
+ (elide-head-mode -1))
(provide 'elide-head)
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index 8e43ae68072..86a42b208e7 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -1814,8 +1814,7 @@ Redefining advices affect the construction of an advised definition."
(if (symbolp function)
(setq function (if (fboundp function)
(advice--strip-macro (symbol-function function)))))
- (while (advice--p function) (setq function (advice--cdr function)))
- function)
+ (advice--cd*r function))
(defun ad-clear-advicefunname-definition (function)
(let ((advicefunname (ad-get-advice-info-field function 'advicefunname)))
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index a51fd8ca255..eed88b6faf4 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -28,36 +28,15 @@
;; Lisp source files in various useful ways. To learn more, read the
;; source; if you're going to use this, you'd better be able to.
+;; The functions in this file have been largely superseded by
+;; loaddefs-gen.el.
+
;;; Code:
(require 'lisp-mode) ;for `doc-string-elt' properties.
(require 'lisp-mnt)
(require 'cl-lib)
-
-(defvar generated-autoload-file nil
- "File into which to write autoload definitions.
-A Lisp file can set this in its local variables section to make
-its autoloads go somewhere else.
-
-If this is a relative file name, the directory is determined as
-follows:
- - If a Lisp file defined `generated-autoload-file' as a
- file-local variable, use its containing directory.
- - Otherwise use the \"lisp\" subdirectory of `source-directory'.
-
-The autoload file is assumed to contain a trailer starting with a
-FormFeed character.")
-;;;###autoload
-(put 'generated-autoload-file 'safe-local-variable 'stringp)
-
-(defvar generated-autoload-load-name nil
- "Load name for `autoload' statements generated from autoload cookies.
-If nil, this defaults to the file name, sans extension.
-Typically, you need to set this when the directory containing the file
-is not in `load-path'.
-This also affects the generated cus-load.el file.")
-;;;###autoload
-(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
+(require 'loaddefs-gen)
;; This feels like it should be a defconst, but MH-E sets it to
;; ";;;###mh-autoload" for the autoloads that are to go into mh-loaddefs.el.
@@ -112,165 +91,7 @@ then we use the timestamp of the output file instead. As a result:
(defvar autoload-modified-buffers) ;Dynamically scoped var.
-(defun make-autoload (form file &optional expansion)
- "Turn FORM into an autoload or defvar for source file FILE.
-Returns nil if FORM is not a special autoload form (i.e. a function definition
-or macro definition or a defcustom).
-If EXPANSION is non-nil, we're processing the macro expansion of an
-expression, in which case we want to handle forms differently."
- (let ((car (car-safe form)) expand)
- (cond
- ((and expansion (eq car 'defalias))
- (pcase-let*
- ((`(,_ ,_ ,arg . ,rest) form)
- ;; `type' is non-nil if it defines a macro.
- ;; `fun' is the function part of `arg' (defaults to `arg').
- ((or (and (or `(cons 'macro ,fun) `'(macro . ,fun)) (let type t))
- (and (let fun arg) (let type nil)))
- arg)
- ;; `lam' is the lambda expression in `fun' (or nil if not
- ;; recognized).
- (lam (if (memq (car-safe fun) '(quote function)) (cadr fun)))
- ;; `args' is the list of arguments (or t if not recognized).
- ;; `body' is the body of `lam' (or t if not recognized).
- ((or `(lambda ,args . ,body)
- (and (let args t) (let body t)))
- lam)
- ;; Get the `doc' from `body' or `rest'.
- (doc (cond ((stringp (car-safe body)) (car body))
- ((stringp (car-safe rest)) (car rest))))
- ;; Look for an interactive spec.
- (interactive (pcase body
- ((or `((interactive . ,iargs) . ,_)
- `(,_ (interactive . ,iargs) . ,_))
- ;; List of modes or just t.
- (if (nthcdr 1 iargs)
- (list 'quote (nthcdr 1 iargs))
- t)))))
- ;; Add the usage form at the end where describe-function-1
- ;; can recover it.
- (when (consp args) (setq doc (help-add-fundoc-usage doc args)))
- ;; (message "autoload of %S" (nth 1 form))
- `(autoload ,(nth 1 form) ,file ,doc ,interactive ,type)))
-
- ((and expansion (memq car '(progn prog1)))
- (let ((end (memq :autoload-end form)))
- (when end ;Cut-off anything after the :autoload-end marker.
- (setq form (copy-sequence form))
- (setcdr (memq :autoload-end form) nil))
- (let ((exps (delq nil (mapcar (lambda (form)
- (make-autoload form file expansion))
- (cdr form)))))
- (when exps (cons 'progn exps)))))
-
- ;; For complex cases, try again on the macro-expansion.
- ((and (memq car '(easy-mmode-define-global-mode define-global-minor-mode
- define-globalized-minor-mode defun defmacro
- easy-mmode-define-minor-mode define-minor-mode
- define-inline cl-defun cl-defmacro cl-defgeneric
- cl-defstruct pcase-defmacro))
- (macrop car)
- (setq expand (let ((load-true-file-name file)
- (load-file-name file))
- (macroexpand form)))
- (memq (car expand) '(progn prog1 defalias)))
- (make-autoload expand file 'expansion)) ;Recurse on the expansion.
-
- ;; For special function-like operators, use the `autoload' function.
- ((memq car '(define-skeleton define-derived-mode
- define-compilation-mode define-generic-mode
- easy-mmode-define-global-mode define-global-minor-mode
- define-globalized-minor-mode
- easy-mmode-define-minor-mode define-minor-mode
- cl-defun defun* cl-defmacro defmacro*
- define-overloadable-function))
- (let* ((macrop (memq car '(defmacro cl-defmacro defmacro*)))
- (name (nth 1 form))
- (args (pcase car
- ((or 'defun 'defmacro
- 'defun* 'defmacro* 'cl-defun 'cl-defmacro
- 'define-overloadable-function)
- (nth 2 form))
- ('define-skeleton '(&optional str arg))
- ((or 'define-generic-mode 'define-derived-mode
- 'define-compilation-mode)
- nil)
- (_ t)))
- (body (nthcdr (or (function-get car 'doc-string-elt) 3) form))
- (doc (if (stringp (car body)) (pop body))))
- ;; Add the usage form at the end where describe-function-1
- ;; can recover it.
- (when (listp args) (setq doc (help-add-fundoc-usage doc args)))
- ;; `define-generic-mode' quotes the name, so take care of that
- `(autoload ,(if (listp name) name (list 'quote name))
- ,file ,doc
- ,(or (and (memq car '(define-skeleton define-derived-mode
- define-generic-mode
- easy-mmode-define-global-mode
- define-global-minor-mode
- define-globalized-minor-mode
- easy-mmode-define-minor-mode
- define-minor-mode))
- t)
- (and (eq (car-safe (car body)) 'interactive)
- ;; List of modes or just t.
- (or (if (nthcdr 1 (car body))
- (list 'quote (nthcdr 1 (car body)))
- t))))
- ,(if macrop ''macro nil))))
-
- ;; For defclass forms, use `eieio-defclass-autoload'.
- ((eq car 'defclass)
- (let ((name (nth 1 form))
- (superclasses (nth 2 form))
- (doc (nth 4 form)))
- (list 'eieio-defclass-autoload (list 'quote name)
- (list 'quote superclasses) file doc)))
-
- ;; Convert defcustom to less space-consuming data.
- ((eq car 'defcustom)
- (let* ((varname (car-safe (cdr-safe form)))
- (props (nthcdr 4 form))
- (initializer (plist-get props :initialize))
- (init (car-safe (cdr-safe (cdr-safe form))))
- (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form)))))
- ;; (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form)))))
- )
- `(progn
- ,(if (not (member initializer '(nil 'custom-initialize-default
- #'custom-initialize-default
- 'custom-initialize-reset
- #'custom-initialize-reset)))
- form
- `(defvar ,varname ,init ,doc))
- ;; When we include the complete `form', this `custom-autoload'
- ;; is not indispensable, but it still helps in case the `defcustom'
- ;; doesn't specify its group explicitly, and probably in a few other
- ;; corner cases.
- (custom-autoload ',varname ,file
- ,(condition-case nil
- (null (plist-get props :set))
- (error nil)))
- ;; Propagate the :safe property to the loaddefs file.
- ,@(when-let ((safe (plist-get props :safe)))
- `((put ',varname 'safe-local-variable ,safe))))))
-
- ((eq car 'defgroup)
- ;; In Emacs this is normally handled separately by cus-dep.el, but for
- ;; third party packages, it can be convenient to explicitly autoload
- ;; a group.
- (let ((groupname (nth 1 form)))
- `(let ((loads (get ',groupname 'custom-loads)))
- (if (member ',file loads) nil
- (put ',groupname 'custom-loads (cons ',file loads))))))
-
- ;; When processing a macro expansion, any expression
- ;; before a :autoload-end should be included. These are typically (put
- ;; 'fun 'prop val) and things like that.
- ((and expansion (consp form)) form)
-
- ;; nil here indicates that this is not a special autoload form.
- (t nil))))
+(defalias 'make-autoload #'loaddefs-generate--make-autoload)
;; Forms which have doc-strings which should be printed specially.
;; A doc-string-elt property of ELT says that (nth ELT FORM) is
@@ -340,7 +161,7 @@ put the output in."
(t
(let ((doc-string-elt (function-get (car-safe form) 'doc-string-elt))
(outbuf autoload-print-form-outbuf))
- (if (and doc-string-elt (stringp (nth doc-string-elt form)))
+ (if (and (numberp doc-string-elt) (stringp (nth doc-string-elt form)))
;; We need to hack the printing because the
;; doc-string must be printed specially for
;; make-docfile (sigh).
@@ -379,41 +200,7 @@ put the output in."
(print-escape-nonascii t))
(print form outbuf)))))))
-(defun autoload-rubric (file &optional type feature)
- "Return a string giving the appropriate autoload rubric for FILE.
-TYPE (default \"autoloads\") is a string stating the type of
-information contained in FILE. TYPE \"package\" acts like the default,
-but adds an extra line to the output to modify `load-path'.
-
-If FEATURE is non-nil, FILE will provide a feature. FEATURE may
-be a string naming the feature, otherwise it will be based on
-FILE's name."
- (let ((basename (file-name-nondirectory file))
- (lp (if (equal type "package") (setq type "autoloads"))))
- (concat ";;; " basename
- " --- automatically extracted " (or type "autoloads")
- " -*- lexical-binding: t -*-\n"
- (when (string-match "/lisp/loaddefs\\.el\\'" file)
- ";; This file will be copied to ldefs-boot.el and checked in periodically.\n")
- ";;\n"
- ";;; Code:\n\n"
- (if lp
- "(add-to-list 'load-path (directory-file-name
- (or (file-name-directory #$) (car load-path))))\n\n")
- " \n"
- ;; This is used outside of autoload.el, eg cus-dep, finder.
- (if feature
- (format "(provide '%s)\n"
- (if (stringp feature) feature
- (file-name-sans-extension basename))))
- ";; Local Variables:\n"
- ";; version-control: never\n"
- ";; no-byte-compile: t\n" ;; #$ is byte-compiled into nil.
- ";; no-update-autoloads: t\n"
- ";; coding: utf-8\n"
- ";; End:\n"
- ";;; " basename
- " ends here\n")))
+(defalias 'autoload-rubric #'loaddefs-generate--rubric)
(defvar autoload-ensure-writable nil
"Non-nil means `autoload-find-generated-file' makes existing file writable.")
@@ -480,35 +267,13 @@ if `autoload-timestamps' is non-nil, otherwise a fixed fake time is inserted)."
(hack-local-variables))
(current-buffer)))
+(defalias 'autoload-insert-section-header
+ #'loaddefs-generate--insert-section-header)
+
(defvar no-update-autoloads nil
"File local variable to prevent scanning this file for autoload cookies.")
-(defun autoload-file-load-name (file outfile)
- "Compute the name that will be used to load FILE.
-OUTFILE should be the name of the global loaddefs.el file, which
-is expected to be at the root directory of the files we are
-scanning for autoloads and will be in the `load-path'."
- (let* ((name (file-relative-name file (file-name-directory outfile)))
- (names '())
- (dir (file-name-directory outfile)))
- ;; If `name' has directory components, only keep the
- ;; last few that are really needed.
- (while name
- (setq name (directory-file-name name))
- (push (file-name-nondirectory name) names)
- (setq name (file-name-directory name)))
- (while (not name)
- (cond
- ((null (cdr names)) (setq name (car names)))
- ((file-exists-p (expand-file-name "subdirs.el" dir))
- ;; FIXME: here we only check the existence of subdirs.el,
- ;; without checking its content. This makes it generate wrong load
- ;; names for cases like lisp/term which is not added to load-path.
- (setq dir (expand-file-name (pop names) dir)))
- (t (setq name (mapconcat #'identity names "/")))))
- (if (string-match "\\.elc?\\(\\.\\|\\'\\)" name)
- (substring name 0 (match-beginning 0))
- name)))
+(defalias 'autoload-file-load-name #'loaddefs-generate--file-load-name)
(defun generate-file-autoloads (file)
"Insert at point a loaddefs autoload section for FILE.
@@ -522,13 +287,6 @@ Return non-nil in the case where no autoloads were added at point."
(autoload-generate-file-autoloads file (current-buffer) buffer-file-name)
autoload-modified-buffers))
-(defvar autoload-compute-prefixes t
- "If non-nil, autoload will add code to register the prefixes used in a file.
-Standard prefixes won't be registered anyway. I.e. if a file \"foo.el\" defines
-variables or functions that use \"foo-\" as prefix, that will not be registered.
-But all other prefixes will be included.")
-(put 'autoload-compute-prefixes 'safe #'booleanp)
-
(defconst autoload-def-prefixes-max-entries 5
"Target length of the list of definition prefixes per file.
If set too small, the prefixes will be too generic (i.e. they'll use little
@@ -540,102 +298,7 @@ cost more memory use).")
"Target size of definition prefixes.
Don't try to split prefixes that are already longer than that.")
-(require 'radix-tree)
-
-(defun autoload--make-defs-autoload (defs file)
-
- ;; Remove the defs that obey the rule that file foo.el (or
- ;; foo-mode.el) uses "foo-" as prefix.
- ;; FIXME: help--symbol-completion-table still doesn't know how to use
- ;; the rule that file foo.el (or foo-mode.el) uses "foo-" as prefix.
- ;;(let ((prefix
- ;; (concat (substring file 0 (string-match "-mode\\'" file)) "-")))
- ;; (dolist (def (prog1 defs (setq defs nil)))
- ;; (unless (string-prefix-p prefix def)
- ;; (push def defs))))
-
- ;; Then compute a small set of prefixes that cover all the
- ;; remaining definitions.
- (let* ((tree (let ((tree radix-tree-empty))
- (dolist (def defs)
- (setq tree (radix-tree-insert tree def t)))
- tree))
- (prefixes nil))
- ;; Get the root prefixes, that we should include in any case.
- (radix-tree-iter-subtrees
- tree (lambda (prefix subtree)
- (push (cons prefix subtree) prefixes)))
- ;; In some cases, the root prefixes are too short, e.g. if you define
- ;; "cc-helper" and "c-mode", you'll get "c" in the root prefixes.
- (dolist (pair (prog1 prefixes (setq prefixes nil)))
- (let ((s (car pair)))
- (if (or (and (> (length s) 2) ; Long enough!
- ;; But don't use "def" from deffoo-pkg-thing.
- (not (string= "def" s)))
- (string-match ".[[:punct:]]\\'" s) ;A real (tho short) prefix?
- (radix-tree-lookup (cdr pair) "")) ;Nothing to expand!
- (push pair prefixes) ;Keep it as is.
- (radix-tree-iter-subtrees
- (cdr pair) (lambda (prefix subtree)
- (push (cons (concat s prefix) subtree) prefixes))))))
- ;; FIXME: The expansions done below are mostly pointless, such as
- ;; for `yenc', where we replace "yenc-" with an exhaustive list (5
- ;; elements).
- ;; (while
- ;; (let ((newprefixes nil)
- ;; (changes nil))
- ;; (dolist (pair prefixes)
- ;; (let ((prefix (car pair)))
- ;; (if (or (> (length prefix) autoload-def-prefixes-max-length)
- ;; (radix-tree-lookup (cdr pair) ""))
- ;; ;; No point splitting it any further.
- ;; (push pair newprefixes)
- ;; (setq changes t)
- ;; (radix-tree-iter-subtrees
- ;; (cdr pair) (lambda (sprefix subtree)
- ;; (push (cons (concat prefix sprefix) subtree)
- ;; newprefixes))))))
- ;; (and changes
- ;; (<= (length newprefixes)
- ;; autoload-def-prefixes-max-entries)
- ;; (let ((new nil)
- ;; (old nil))
- ;; (dolist (pair prefixes)
- ;; (unless (memq pair newprefixes) ;Not old
- ;; (push pair old)))
- ;; (dolist (pair newprefixes)
- ;; (unless (memq pair prefixes) ;Not new
- ;; (push pair new)))
- ;; (cl-assert new)
- ;; (message "Expanding %S to %S"
- ;; (mapcar #'car old) (mapcar #'car new))
- ;; t)
- ;; (setq prefixes newprefixes)
- ;; (< (length prefixes) autoload-def-prefixes-max-entries))))
-
- ;; (message "Final prefixes %s : %S" file (mapcar #'car prefixes))
- (when prefixes
- (let ((strings
- (mapcar
- (lambda (x)
- (let ((prefix (car x)))
- (if (or (> (length prefix) 2) ;Long enough!
- (and (eq (length prefix) 2)
- (string-match "[[:punct:]]" prefix)))
- prefix
- ;; Some packages really don't follow the rules.
- ;; Drop the most egregious cases such as the
- ;; one-letter prefixes.
- (let ((dropped ()))
- (radix-tree-iter-mappings
- (cdr x) (lambda (s _)
- (push (concat prefix s) dropped)))
- (message "%s:0: Warning: Not registering prefix \"%s\". Affects: %S"
- file prefix dropped)
- nil))))
- prefixes)))
- `(register-definition-prefixes ,file ',(sort (delq nil strings)
- 'string<))))))
+(defalias 'autoload--make-defs-autoload #'loaddefs-generate--make-prefixes)
(defun autoload--setup-output (otherbuf outbuf absfile load-name output-file)
(let ((outbuf
@@ -687,21 +350,6 @@ Don't try to split prefixes that are already longer than that.")
(defvar autoload-builtin-package-versions nil)
-(defvar autoload-ignored-definitions
- '("define-obsolete-function-alias"
- "define-obsolete-variable-alias"
- "define-category" "define-key"
- "defgroup" "defface" "defadvice"
- "def-edebug-spec"
- ;; Hmm... this is getting ugly:
- "define-widget"
- "define-erc-module"
- "define-erc-response-handler"
- "defun-rcirc-command")
- "List of strings naming definitions to ignore for prefixes.
-More specifically those definitions will not be considered for the
-`register-definition-prefixes' call.")
-
(defun autoload-generate-file-autoloads (file &optional outbuf outfile)
"Insert an autoload section for FILE in the appropriate buffer.
Autoloads are generated for defuns and defmacros in FILE
@@ -1108,6 +756,9 @@ directory or directories specified."
;; Files with no autoload cookies or whose autoloads go to other
;; files because of file-local autoload-generated-file settings.
(no-autoloads nil)
+ ;; Ensure that we don't do odd things when putting the doc
+ ;; strings into the autoloads file.
+ (left-margin 0)
(autoload-modified-buffers nil)
(output-time
(and (file-exists-p output-file)
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 3231877a30c..4f98bf3f4f5 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -58,7 +58,8 @@ Backtrace mode will attempt to abbreviate printing of backtrace
frames by setting `print-level' and `print-length' to make them
shorter than this, but success is not guaranteed. If set to nil
or zero, backtrace mode will not abbreviate the forms it prints."
- :type 'integer
+ :type '(choice natnum
+ (const :value nil :tag "Don't abbreviate"))
:group 'backtrace
:version "27.1")
@@ -199,63 +200,63 @@ functions returns non-nil. When adding a function to this hook,
you should also set the :source-available flag for the backtrace
frames where the source code location is known.")
-(defvar backtrace-mode-map
- (let ((map (copy-keymap special-mode-map)))
- (set-keymap-parent map button-buffer-map)
- (define-key map "n" 'backtrace-forward-frame)
- (define-key map "p" 'backtrace-backward-frame)
- (define-key map "v" 'backtrace-toggle-locals)
- (define-key map "#" 'backtrace-toggle-print-circle)
- (define-key map ":" 'backtrace-toggle-print-gensym)
- (define-key map "s" 'backtrace-goto-source)
- (define-key map "\C-m" 'backtrace-help-follow-symbol)
- (define-key map "+" 'backtrace-multi-line)
- (define-key map "-" 'backtrace-single-line)
- (define-key map "." 'backtrace-expand-ellipses)
- (define-key map [follow-link] 'mouse-face)
- (define-key map [mouse-2] 'mouse-select-window)
- (easy-menu-define nil map ""
- '("Backtrace"
- ["Next Frame" backtrace-forward-frame
- :help "Move cursor forwards to the start of a backtrace frame"]
- ["Previous Frame" backtrace-backward-frame
- :help "Move cursor backwards to the start of a backtrace frame"]
- "--"
- ["Show Variables" backtrace-toggle-locals
- :style toggle
- :active (backtrace-get-index)
- :selected (plist-get (backtrace-get-view) :show-locals)
- :help "Show or hide the local variables for the frame at point"]
- ["Show Circular Structures" backtrace-toggle-print-circle
- :style toggle
- :active (backtrace-get-index)
- :selected (plist-get (backtrace-get-view) :print-circle)
- :help
- "Condense or expand shared or circular structures in the frame at point"]
- ["Show Uninterned Symbols" backtrace-toggle-print-gensym
- :style toggle
- :active (backtrace-get-index)
- :selected (plist-get (backtrace-get-view) :print-gensym)
- :help
- "Toggle unique printing of uninterned symbols in the frame at point"]
- ["Expand \"...\"s" backtrace-expand-ellipses
- :help "Expand all the abbreviated forms in the current frame"]
- ["Show on Multiple Lines" backtrace-multi-line
- :help "Use line breaks and indentation to make a form more readable"]
- ["Show on Single Line" backtrace-single-line]
- "--"
- ["Go to Source" backtrace-goto-source
- :active (and (backtrace-get-index)
- (plist-get (backtrace-frame-flags
- (nth (backtrace-get-index) backtrace-frames))
- :source-available))
- :help "Show the source code for the current frame"]
- ["Help for Symbol" backtrace-help-follow-symbol
- :help "Show help for symbol at point"]
- ["Describe Backtrace Mode" describe-mode
- :help "Display documentation for backtrace-mode"]))
- map)
- "Local keymap for `backtrace-mode' buffers.")
+(defvar-keymap backtrace-mode-map
+ :doc "Local keymap for `backtrace-mode' buffers."
+ :parent (make-composed-keymap special-mode-map
+ button-buffer-map)
+ "n" #'backtrace-forward-frame
+ "p" #'backtrace-backward-frame
+ "v" #'backtrace-toggle-locals
+ "#" #'backtrace-toggle-print-circle
+ ":" #'backtrace-toggle-print-gensym
+ "s" #'backtrace-goto-source
+ "RET" #'backtrace-help-follow-symbol
+ "+" #'backtrace-multi-line
+ "-" #'backtrace-single-line
+ "." #'backtrace-expand-ellipses
+ "<follow-link>" 'mouse-face
+ "<mouse-2>" #'mouse-select-window
+
+ :menu
+ '("Backtrace"
+ ["Next Frame" backtrace-forward-frame
+ :help "Move cursor forwards to the start of a backtrace frame"]
+ ["Previous Frame" backtrace-backward-frame
+ :help "Move cursor backwards to the start of a backtrace frame"]
+ "--"
+ ["Show Variables" backtrace-toggle-locals
+ :style toggle
+ :active (backtrace-get-index)
+ :selected (plist-get (backtrace-get-view) :show-locals)
+ :help "Show or hide the local variables for the frame at point"]
+ ["Show Circular Structures" backtrace-toggle-print-circle
+ :style toggle
+ :active (backtrace-get-index)
+ :selected (plist-get (backtrace-get-view) :print-circle)
+ :help
+ "Condense or expand shared or circular structures in the frame at point"]
+ ["Show Uninterned Symbols" backtrace-toggle-print-gensym
+ :style toggle
+ :active (backtrace-get-index)
+ :selected (plist-get (backtrace-get-view) :print-gensym)
+ :help
+ "Toggle unique printing of uninterned symbols in the frame at point"]
+ ["Expand \"...\"s" backtrace-expand-ellipses
+ :help "Expand all the abbreviated forms in the current frame"]
+ ["Show on Multiple Lines" backtrace-multi-line
+ :help "Use line breaks and indentation to make a form more readable"]
+ ["Show on Single Line" backtrace-single-line]
+ "--"
+ ["Go to Source" backtrace-goto-source
+ :active (and (backtrace-get-index)
+ (plist-get (backtrace-frame-flags
+ (nth (backtrace-get-index) backtrace-frames))
+ :source-available))
+ :help "Show the source code for the current frame"]
+ ["Help for Symbol" backtrace-help-follow-symbol
+ :help "Show help for symbol at point"]
+ ["Describe Backtrace Mode" describe-mode
+ :help "Display documentation for backtrace-mode"]))
(defconst backtrace--flags-width 2
"Width in characters of the flags for a backtrace frame.")
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index c5f621c6c86..882b1d68c48 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -121,7 +121,11 @@ result. The overhead of the `lambda's is accounted for."
(unless (or (natnump repetitions) (and repetitions (symbolp repetitions)))
(setq forms (cons repetitions forms)
repetitions 1))
- `(benchmark-call (byte-compile '(lambda () ,@forms)) ,repetitions))
+ `(benchmark-call (,(if (native-comp-available-p)
+ 'native-compile
+ 'byte-compile)
+ '(lambda () ,@forms))
+ ,repetitions))
;;;###autoload
(defun benchmark (repetitions form)
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index c6d64975eca..0ecac3d52aa 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -77,7 +77,7 @@
;; (bindat-type
;; (type u8)
;; (opcode u8)
-;; (length uintr 32) ;; little endian order
+;; (length uint 32 t) ;; little endian order
;; (id strz 8)
;; (data vec length)
;; (_ align 4)))
@@ -165,12 +165,12 @@
(if (stringp s) s
(apply #'unibyte-string s))))
-(defun bindat--unpack-strz (len)
+(defun bindat--unpack-strz (&optional len)
(let ((i 0) s)
(while (and (if len (< i len) t) (/= (aref bindat-raw (+ bindat-idx i)) 0))
(setq i (1+ i)))
(setq s (substring bindat-raw bindat-idx (+ bindat-idx i)))
- (setq bindat-idx (+ bindat-idx len))
+ (setq bindat-idx (+ bindat-idx (or len (1+ i))))
(if (stringp s) s
(apply #'unibyte-string s))))
@@ -320,72 +320,72 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
(defun bindat--length-group (struct spec)
(if (cl-typep spec 'bindat--type)
(funcall (bindat--type-le spec) struct)
- (with-suppressed-warnings ((lexical struct last))
- (defvar struct) (defvar last))
- (let ((struct struct) last)
- (dolist (item spec)
- (let* ((field (car item))
- (type (nth 1 item))
- (len (nth 2 item))
- (vectype (and (eq type 'vec) (nth 3 item)))
- (tail 3))
- (if (and type (consp type) (eq (car type) 'eval))
- (setq type (eval (car (cdr type)) t)))
- (if (and len (consp len) (eq (car len) 'eval))
- (setq len (eval (car (cdr len)) t)))
- (if (memq field '(eval fill align struct union))
- (setq tail 2
- len type
- type field
- field nil))
- (if (and (consp field) (eq (car field) 'eval))
- (setq field (eval (car (cdr field)) t)))
- (if (and (consp len) (not (eq type 'eval)))
- (setq len (apply #'bindat-get-field struct len)))
- (if (not len)
- (setq len 1))
- (while (eq type 'vec)
- (if (consp vectype)
- (setq len (* len (nth 1 vectype))
- type (nth 2 vectype))
- (setq type (or vectype 'u8)
- vectype nil)))
- (pcase type
- ('eval
- (if field
- (setq struct (cons (cons field (eval len t)) struct))
- (eval len t)))
- ('fill
- (setq bindat-idx (+ bindat-idx len)))
- ('align
- (setq bindat-idx (bindat--align bindat-idx len)))
- ('struct
- (bindat--length-group
- (if field (bindat-get-field struct field) struct) (eval len t)))
- ('repeat
- (dotimes (index len)
- (bindat--length-group
- (nth index (bindat-get-field struct field))
- (nthcdr tail item))))
- ('union
- (with-suppressed-warnings ((lexical tag))
- (defvar tag))
- (let ((tag len) (cases (nthcdr tail item)) case cc)
- (while cases
- (setq case (car cases)
- cases (cdr cases)
- cc (car case))
- (if (or (equal cc tag) (equal cc t)
- (and (consp cc) (eval cc t)))
- (progn
- (bindat--length-group struct (cdr case))
- (setq cases nil))))))
- (_
- (if (setq type (assq type bindat--fixed-length-alist))
- (setq len (* len (cdr type))))
- (if field
- (setq last (bindat-get-field struct field)))
- (setq bindat-idx (+ bindat-idx len)))))))))
+ (with-suppressed-warnings ((lexical struct last))
+ (defvar struct) (defvar last))
+ (let ((struct struct) last)
+ (dolist (item spec)
+ (let* ((field (car item))
+ (type (nth 1 item))
+ (len (nth 2 item))
+ (vectype (and (eq type 'vec) (nth 3 item)))
+ (tail 3))
+ (if (and type (consp type) (eq (car type) 'eval))
+ (setq type (eval (car (cdr type)) t)))
+ (if (and len (consp len) (eq (car len) 'eval))
+ (setq len (eval (car (cdr len)) t)))
+ (if (memq field '(eval fill align struct union))
+ (setq tail 2
+ len type
+ type field
+ field nil))
+ (if (and (consp field) (eq (car field) 'eval))
+ (setq field (eval (car (cdr field)) t)))
+ (if (and (consp len) (not (eq type 'eval)))
+ (setq len (apply #'bindat-get-field struct len)))
+ (if (not len)
+ (setq len 1))
+ (while (eq type 'vec)
+ (if (consp vectype)
+ (setq len (* len (nth 1 vectype))
+ type (nth 2 vectype))
+ (setq type (or vectype 'u8)
+ vectype nil)))
+ (pcase type
+ ('eval
+ (if field
+ (setq struct (cons (cons field (eval len t)) struct))
+ (eval len t)))
+ ('fill
+ (setq bindat-idx (+ bindat-idx len)))
+ ('align
+ (setq bindat-idx (bindat--align bindat-idx len)))
+ ('struct
+ (bindat--length-group
+ (if field (bindat-get-field struct field) struct) (eval len t)))
+ ('repeat
+ (dotimes (index len)
+ (bindat--length-group
+ (nth index (bindat-get-field struct field))
+ (nthcdr tail item))))
+ ('union
+ (with-suppressed-warnings ((lexical tag))
+ (defvar tag))
+ (let ((tag len) (cases (nthcdr tail item)) case cc)
+ (while cases
+ (setq case (car cases)
+ cases (cdr cases)
+ cc (car case))
+ (if (or (equal cc tag) (equal cc t)
+ (and (consp cc) (eval cc t)))
+ (progn
+ (bindat--length-group struct (cdr case))
+ (setq cases nil))))))
+ (_
+ (if (setq type (assq type bindat--fixed-length-alist))
+ (setq len (* len (cdr type))))
+ (if field
+ (setq last (bindat-get-field struct field)))
+ (setq bindat-idx (+ bindat-idx len)))))))))
(defun bindat-length (spec struct)
"Calculate `bindat-raw' length for STRUCT according to bindat SPEC."
@@ -435,15 +435,31 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
(bindat--pack-u32r (ash v -32)))
(defun bindat--pack-str (len v)
- (dotimes (i (min len (length v)))
- (aset bindat-raw (+ bindat-idx i) (aref v i)))
- (setq bindat-idx (+ bindat-idx len)))
-
-(defun bindat--pack-strz (v)
- (let ((len (length v)))
- (dotimes (i len)
+ (let ((v (string-to-unibyte v)))
+ (dotimes (i (min len (length v)))
(aset bindat-raw (+ bindat-idx i) (aref v i)))
- (setq bindat-idx (+ bindat-idx len 1))))
+ (setq bindat-idx (+ bindat-idx len))))
+
+(defun bindat--pack-strz (len v)
+ (let* ((v (string-to-unibyte v))
+ (vlen (length v)))
+ ;; Explicitly write a null terminator (if there's room) in case
+ ;; the user provided a pre-allocated string to `bindat-pack' that
+ ;; wasn't already zeroed.
+ (when (or (null len) (< vlen len))
+ (aset bindat-raw (+ bindat-idx vlen) 0))
+ (if len
+ ;; When len is specified, behave the same as the str type
+ ;; (except for the null terminator possibly written above).
+ (bindat--pack-str len v)
+ (dotimes (i vlen)
+ (when (= (aref v i) 0)
+ ;; Alternatively we could pretend that this was the end of
+ ;; the string and stop packing, but then bindat-length would
+ ;; need to scan the input string looking for a null byte.
+ (error "Null byte encountered in input strz string"))
+ (aset bindat-raw (+ bindat-idx i) (aref v i)))
+ (setq bindat-idx (+ bindat-idx vlen 1)))))
(defun bindat--pack-bits (len v)
(let ((bnum (1- (* 8 len))) j m)
@@ -472,7 +488,8 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
('u24r (bindat--pack-u24r v))
('u32r (bindat--pack-u32r v))
('bits (bindat--pack-bits len v))
- ((or 'str 'strz) (bindat--pack-str len v))
+ ('str (bindat--pack-str len v))
+ ('strz (bindat--pack-strz len v))
('vec
(let ((l (length v)) (vlen 1))
(if (consp vectype)
@@ -663,19 +680,15 @@ is the name of a variable that will hold the value we need to pack.")
(`(length . ,_) `(cl-incf bindat-idx 1))
(`(pack . ,args) `(bindat--pack-u8 . ,args))))
-(cl-defmethod bindat--type (op (_ (eql 'uint)) n)
+(cl-defmethod bindat--type (op (_ (eql 'uint)) n &optional le)
(if (eq n 8) (bindat--type op 'byte)
(bindat--pcase op
- ('unpack `(bindat--unpack-uint ,n))
- (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
- (`(pack . ,args) `(bindat--pack-uint ,n . ,args)))))
-
-(cl-defmethod bindat--type (op (_ (eql 'uintr)) n)
- (if (eq n 8) (bindat--type op 'byte)
- (bindat--pcase op
- ('unpack `(bindat--unpack-uintr ,n))
+ ('unpack
+ `(if ,le (bindat--unpack-uintr ,n) (bindat--unpack-uint ,n)))
(`(length . ,_) `(cl-incf bindat-idx (/ ,n 8)))
- (`(pack . ,args) `(bindat--pack-uintr ,n . ,args)))))
+ (`(pack . ,args)
+ `(if ,le (bindat--pack-uintr ,n . ,args)
+ (bindat--pack-uint ,n . ,args))))))
(cl-defmethod bindat--type (op (_ (eql 'str)) len)
(bindat--pcase op
@@ -688,18 +701,12 @@ is the name of a variable that will hold the value we need to pack.")
('unpack `(bindat--unpack-strz ,len))
(`(length ,val)
`(cl-incf bindat-idx ,(cond
- ((null len) `(length ,val))
+ ;; Optimizations if len is a literal number or nil.
+ ((null len) `(1+ (length ,val)))
((numberp len) len)
- (t `(or ,len (length ,val))))))
- (`(pack . ,args)
- (macroexp-let2 nil len len
- `(if ,len
- ;; Same as non-zero terminated strings since we don't actually add
- ;; the terminating zero anyway (because we rely on the fact that
- ;; `bindat-raw' was presumably initialized with all-zeroes before
- ;; we started).
- (bindat--pack-str ,len . ,args)
- (bindat--pack-strz . ,args))))))
+ ;; General expression support.
+ (t `(or ,len (1+ (length ,val)))))))
+ (`(pack . ,args) `(bindat--pack-strz ,len . ,args))))
(cl-defmethod bindat--type (op (_ (eql 'bits)) len)
(bindat--pcase op
@@ -824,7 +831,7 @@ is the name of a variable that will hold the value we need to pack.")
&optional ":unpack-val" def-form))
(def-edebug-elem-spec 'bindat-type
- '(&or ["uint" def-form]
+ '(&or ["uint" def-form &optional def-form]
["uintr" def-form]
["str" def-form]
["strz" &optional def-form]
@@ -844,8 +851,7 @@ is the name of a variable that will hold the value we need to pack.")
"Return the Bindat type value to pack&unpack TYPE.
TYPE is a Bindat type expression. It can take the following forms:
- uint BITLEN - Big-endian unsigned integer
- uintr BITLEN - Little-endian unsigned integer
+ uint BITLEN [LE] - unsigned integer (big-endian if LE is nil)
str LEN - Byte string
strz [LEN] - Zero-terminated byte-string
bits LEN - Bit vector (LEN is counted in bytes)
@@ -872,7 +878,7 @@ controlled in the following way:
- If the list of fields is preceded with `:pack-var VAR' then the object to
be packed is bound to VAR when evaluating the EXPs of `:pack-val'.
-All the above BITLEN, LEN, COUNT, and EXP are ELisp expressions evaluated
+All the above BITLEN, LEN, LE, COUNT, and EXP are ELisp expressions evaluated
in the current lexical context extended with the previous fields.
TYPE can additionally be one of the Bindat type macros defined with
@@ -886,7 +892,7 @@ a bindat type expression."
:pe ,(bindat--toplevel 'pack type))))
(eval-and-compile
- (defconst bindat--primitives '(byte uint uintr str strz bits fill align
+ (defconst bindat--primitives '(byte uint str strz bits fill align
struct type vec unit)))
(eval-and-compile
@@ -930,9 +936,9 @@ a bindat type expression."
(if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))))
(bindat-defmacro u8 () "Unsigned 8bit integer." '(byte))
-(bindat-defmacro sint (bitlen r)
+(bindat-defmacro sint (bitlen le)
"Signed integer of size BITLEN.
-Bigendian if R is nil and little endian if not."
+Big-endian if LE is nil and little-endian if not."
(let ((bl (make-symbol "bitlen"))
(max (make-symbol "max"))
(wrap (make-symbol "wrap")))
@@ -940,10 +946,14 @@ Bigendian if R is nil and little endian if not."
(,max (ash 1 (1- ,bl)))
(,wrap (+ ,max ,max)))
(struct :pack-var v
- (n if ,r (uintr ,bl) (uint ,bl)
+ (n uint ,bl ,le
:pack-val (if (< v 0) (+ v ,wrap) v))
:unpack-val (if (>= n ,max) (- n ,wrap) n)))))
+(bindat-defmacro uintr (bitlen)
+ "(deprecated since Emacs-29) Little-endian unsigned integer."
+ `(uint ,bitlen t))
+
(bindat-defmacro repeat (count &rest type)
"Like `vec', but unpacks to a list rather than a vector."
`(:pack-var v
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index bd57e2b2030..352ac40663c 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -34,128 +34,13 @@
;; still not going to make it go faster than 70 mph, but it might be easier
;; to get it there.
;;
-
;; TO DO:
;;
-;; (apply (lambda (x &rest y) ...) 1 (foo))
-;;
-;; maintain a list of functions known not to access any global variables
-;; (actually, give them a 'dynamically-safe property) and then
-;; (let ( v1 v2 ... vM vN ) <...dynamically-safe...> ) ==>
-;; (let ( v1 v2 ... vM ) vN <...dynamically-safe...> )
-;; by recursing on this, we might be able to eliminate the entire let.
-;; However certain variables should never have their bindings optimized
-;; away, because they affect everything.
-;; (put 'debug-on-error 'binding-is-magic t)
-;; (put 'debug-on-abort 'binding-is-magic t)
-;; (put 'debug-on-next-call 'binding-is-magic t)
-;; (put 'inhibit-quit 'binding-is-magic t)
-;; (put 'quit-flag 'binding-is-magic t)
-;; (put 't 'binding-is-magic t)
-;; (put 'nil 'binding-is-magic t)
-;; possibly also
-;; (put 'gc-cons-threshold 'binding-is-magic t)
-;; (put 'track-mouse 'binding-is-magic t)
-;; others?
-;;
-;; Simple defsubsts often produce forms like
-;; (let ((v1 (f1)) (v2 (f2)) ...)
-;; (FN v1 v2 ...))
-;; It would be nice if we could optimize this to
-;; (FN (f1) (f2) ...)
-;; but we can't unless FN is dynamically-safe (it might be dynamically
-;; referring to the bindings that the lambda arglist established.)
-;; One of the uncountable lossages introduced by dynamic scope...
-;;
-;; Maybe there should be a control-structure that says "turn on
-;; fast-and-loose type-assumptive optimizations here." Then when
-;; we see a form like (car foo) we can from then on assume that
-;; the variable foo is of type cons, and optimize based on that.
-;; But, this won't win much because of (you guessed it) dynamic
-;; scope. Anything down the stack could change the value.
-;; (Another reason it doesn't work is that it is perfectly valid
-;; to call car with a null argument.) A better approach might
-;; be to allow type-specification of the form
-;; (put 'foo 'arg-types '(float (list integer) dynamic))
-;; (put 'foo 'result-type 'bool)
-;; It should be possible to have these types checked to a certain
-;; degree.
-;;
-;; collapse common subexpressions
-;;
-;; It would be nice if redundant sequences could be factored out as well,
-;; when they are known to have no side-effects:
-;; (list (+ a b c) (+ a b c)) --> a b add c add dup list-2
-;; but beware of traps like
-;; (cons (list x y) (list x y))
-;;
-;; Tail-recursion elimination is not really possible in Emacs Lisp.
-;; Tail-recursion elimination is almost always impossible when all variables
-;; have dynamic scope, but given that the "return" byteop requires the
-;; binding stack to be empty (rather than emptying it itself), there can be
-;; no truly tail-recursive Emacs Lisp functions that take any arguments or
-;; make any bindings.
-;;
-;; Here is an example of an Emacs Lisp function which could safely be
-;; byte-compiled tail-recursively:
-;;
-;; (defun tail-map (fn list)
-;; (cond (list
-;; (funcall fn (car list))
-;; (tail-map fn (cdr list)))))
-;;
-;; However, if there was even a single let-binding around the COND,
-;; it could not be byte-compiled, because there would be an "unbind"
-;; byte-op between the final "call" and "return." Adding a
-;; Bunbind_all byteop would fix this.
-;;
-;; (defun foo (x y z) ... (foo a b c))
-;; ... (const foo) (varref a) (varref b) (varref c) (call 3) END: (return)
-;; ... (varref a) (varbind x) (varref b) (varbind y) (varref c) (varbind z) (goto 0) END: (unbind-all) (return)
-;; ... (varref a) (varset x) (varref b) (varset y) (varref c) (varset z) (goto 0) END: (return)
-;;
-;; this also can be considered tail recursion:
-;;
-;; ... (const foo) (varref a) (call 1) (goto X) ... X: (return)
-;; could generalize this by doing the optimization
-;; (goto X) ... X: (return) --> (return)
-;;
-;; But this doesn't solve all of the problems: although by doing tail-
-;; recursion elimination in this way, the call-stack does not grow, the
-;; binding-stack would grow with each recursive step, and would eventually
-;; overflow. I don't believe there is any way around this without lexical
-;; scope.
-;;
-;; Wouldn't it be nice if Emacs Lisp had lexical scope.
-;;
-;; Idea: the form (lexical-scope) in a file means that the file may be
-;; compiled lexically. This proclamation is file-local. Then, within
-;; that file, "let" would establish lexical bindings, and "let-dynamic"
-;; would do things the old way. (Or we could use CL "declare" forms.)
-;; We'd have to notice defvars and defconsts, since those variables should
-;; always be dynamic, and attempting to do a lexical binding of them
-;; should simply do a dynamic binding instead.
-;; But! We need to know about variables that were not necessarily defvared
-;; in the file being compiled (doing a boundp check isn't good enough.)
-;; Fdefvar() would have to be modified to add something to the plist.
-;;
-;; A major disadvantage of this scheme is that the interpreter and compiler
-;; would have different semantics for files compiled with (dynamic-scope).
-;; Since this would be a file-local optimization, there would be no way to
-;; modify the interpreter to obey this (unless the loader was hacked
-;; in some grody way, but that's a really bad idea.)
-
-;; Other things to consider:
-
-;; ;; Associative math should recognize subcalls to identical function:
-;; (disassemble (lambda (x) (+ (+ (foo) 1) (+ (bar) 2))))
-;; ;; This should generate the same as (1+ x) and (1- x)
-
-;; (disassemble (lambda (x) (cons (+ x 1) (- x 1))))
;; ;; An awful lot of functions always return a non-nil value. If they're
;; ;; error free also they may act as true-constants.
-
+;;
;; (disassemble (lambda (x) (and (point) (foo))))
+
;; ;; When
;; ;; - all but one arguments to a function are constant
;; ;; - the non-constant argument is an if-expression (cond-expression?)
@@ -188,10 +73,6 @@
(eval-when-compile (require 'subr-x))
(defun byte-compile-log-lap-1 (format &rest args)
- ;; Newer byte codes for stack-ref make the slot 0 non-nil again.
- ;; But the "old disassembler" is *really* ancient by now.
- ;; (if (aref byte-code-vector 0)
- ;; (error "The old version of the disassembler is loaded. Reload new-bytecomp as well"))
(byte-compile-log-1
(apply #'format-message format
(let (c a)
@@ -264,8 +145,9 @@ Earlier variables shadow later ones with the same name.")
(cdr (assq name byte-compile-function-environment)))))
(pcase fn
('nil
- (byte-compile-warn "attempt to inline `%s' before it was defined"
- name)
+ (byte-compile-warn-x name
+ "attempt to inline `%s' before it was defined"
+ name)
form)
(`(autoload . ,_)
(error "File `%s' didn't define `%s'" (nth 1 fn) name))
@@ -421,8 +303,8 @@ for speeding up processing.")
(t form)))
(`(quote . ,v)
(if (or (not v) (cdr v))
- (byte-compile-warn "malformed quote form: `%s'"
- (prin1-to-string form)))
+ (byte-compile-warn-x form "malformed quote form: `%s'"
+ form))
;; Map (quote nil) to nil to simplify optimizer logic.
;; Map quoted constants to nil if for-effect (just because).
(and (car v)
@@ -440,8 +322,9 @@ for speeding up processing.")
(cons
(byte-optimize-form (car clause) nil)
(byte-optimize-body (cdr clause) for-effect))
- (byte-compile-warn "malformed cond form: `%s'"
- (prin1-to-string clause))
+ (byte-compile-warn-x
+ clause "malformed cond form: `%s'"
+ clause)
clause))
clauses)))
(`(progn . ,exps)
@@ -455,7 +338,7 @@ for speeding up processing.")
(let ((exps-opt (byte-optimize-body exps t)))
(if (macroexp-const-p exp-opt)
`(progn ,@exps-opt ,exp-opt)
- `(prog1 ,exp-opt ,@exps-opt)))
+ `(,fn ,exp-opt ,@exps-opt)))
exp-opt)))
(`(,(or `save-excursion `save-restriction `save-current-buffer) . ,exps)
@@ -475,7 +358,7 @@ for speeding up processing.")
(then-opt (and test-opt (byte-optimize-form then for-effect)))
(else-opt (and (not (and test-opt const))
(byte-optimize-body else for-effect))))
- `(if ,test-opt ,then-opt . ,else-opt)))
+ `(,fn ,test-opt ,then-opt . ,else-opt)))
(`(,(or 'and 'or) . ,exps)
;; FIXME: We have to traverse the expressions in left-to-right
@@ -514,20 +397,19 @@ for speeding up processing.")
;; as mutated variables have been marked as non-substitutable.
(condition (byte-optimize-form (car condition-body) nil))
(body (byte-optimize-body (cdr condition-body) t)))
- `(while ,condition . ,body)))
+ `(,fn ,condition . ,body)))
(`(interactive . ,_)
- (byte-compile-warn "misplaced interactive spec: `%s'"
- (prin1-to-string form))
+ (byte-compile-warn-x form "misplaced interactive spec: `%s'" form)
nil)
(`(function . ,_)
;; This forms is compiled as constant or by breaking out
;; all the subexpressions and compiling them separately.
- form)
+ (and (not for-effect) form))
(`(condition-case ,var ,exp . ,clauses)
- `(condition-case ,var ;Not evaluated.
+ `(,fn ,var ;Not evaluated.
,(byte-optimize-form exp for-effect)
,@(mapcar (lambda (clause)
(let ((byte-optimize--lexvars
@@ -540,35 +422,29 @@ for speeding up processing.")
(byte-optimize-body (cdr clause) for-effect))))
clauses)))
- (`(unwind-protect ,exp . ,exps)
- ;; The unwinding part of an unwind-protect is compiled (and thus
- ;; optimized) as a top-level form, but run the optimizer for it here
- ;; anyway for lexical variable usage and substitution. But the
- ;; protected part has the same for-effect status as the
- ;; unwind-protect itself. (The unwinding part is always for effect,
- ;; but that isn't handled properly yet.)
- (let ((bodyform (byte-optimize-form exp for-effect)))
- (pcase exps
- (`(:fun-body ,f)
- `(unwind-protect ,bodyform
- :fun-body ,(byte-optimize-form f nil)))
- (_
- `(unwind-protect ,bodyform
- . ,(byte-optimize-body exps t))))))
+ ;; `unwind-protect' is a special form which here takes the shape
+ ;; (unwind-protect EXPR :fun-body UNWIND-FUN).
+ ;; We can treat it as if it were a plain function at this point,
+ ;; although there are specific optimisations possible.
+ ;; In particular, the return value of UNWIND-FUN is never used
+ ;; so its body should really be compiled for-effect, but we
+ ;; don't do that right now.
(`(catch ,tag . ,exps)
- `(catch ,(byte-optimize-form tag nil)
+ `(,fn ,(byte-optimize-form tag nil)
. ,(byte-optimize-body exps for-effect)))
;; Needed as long as we run byte-optimize-form after cconv.
(`(internal-make-closure . ,_)
- ;; Look up free vars and mark them to be kept, so that they
- ;; won't be optimised away.
- (dolist (var (caddr form))
- (let ((lexvar (assq var byte-optimize--lexvars)))
- (when lexvar
- (setcar (cdr lexvar) t))))
- form)
+ (and (not for-effect)
+ (progn
+ ;; Look up free vars and mark them to be kept, so that they
+ ;; won't be optimised away.
+ (dolist (var (caddr form))
+ (let ((lexvar (assq var byte-optimize--lexvars)))
+ (when lexvar
+ (setcar (cdr lexvar) t))))
+ form)))
(`((lambda . ,_) . ,_)
(let ((newform (macroexp--unfold-lambda form)))
@@ -581,46 +457,34 @@ for speeding up processing.")
;; is a *value* and shouldn't appear in the car.
(`((closure . ,_) . ,_) form)
- (`(setq . ,args)
- (let ((var-expr-list nil))
- (while args
- (unless (and (consp args)
- (symbolp (car args)) (consp (cdr args)))
- (byte-compile-warn "malformed setq form: %S" form))
- (let* ((var (car args))
- (expr (cadr args))
- (lexvar (assq var byte-optimize--lexvars))
- (value (byte-optimize-form expr nil)))
- (when lexvar
- (setcar (cdr lexvar) t) ; Mark variable to be kept.
- (setcdr (cdr lexvar) nil) ; Inhibit further substitution.
-
- (when (memq var byte-optimize--aliased-vars)
- ;; Cancel aliasing of variables aliased to this one.
- (dolist (v byte-optimize--lexvars)
- (when (eq (nth 2 v) var)
- ;; V is bound to VAR but VAR is now mutated:
- ;; cancel aliasing.
- (setcdr (cdr v) nil)))))
-
- (push var var-expr-list)
- (push value var-expr-list))
- (setq args (cddr args)))
- (cons fn (nreverse var-expr-list))))
+ (`(setq ,var ,expr)
+ (let ((lexvar (assq var byte-optimize--lexvars))
+ (value (byte-optimize-form expr nil)))
+ (when lexvar
+ (setcar (cdr lexvar) t) ; Mark variable to be kept.
+ (setcdr (cdr lexvar) nil) ; Inhibit further substitution.
+
+ (when (memq var byte-optimize--aliased-vars)
+ ;; Cancel aliasing of variables aliased to this one.
+ (dolist (v byte-optimize--lexvars)
+ (when (eq (nth 2 v) var)
+ ;; V is bound to VAR but VAR is now mutated:
+ ;; cancel aliasing.
+ (setcdr (cdr v) nil)))))
+ `(,fn ,var ,value)))
(`(defvar ,(and (pred symbolp) name) . ,rest)
(let ((optimized-rest (and rest
(cons (byte-optimize-form (car rest) nil)
(cdr rest)))))
(push name byte-optimize--dynamic-vars)
- `(defvar ,name . ,optimized-rest)))
+ `(,fn ,name . ,optimized-rest)))
(`(,(pred byte-code-function-p) . ,exps)
(cons fn (mapcar #'byte-optimize-form exps)))
(`(,(pred (not symbolp)) . ,_)
- (byte-compile-warn "`%s' is a malformed function"
- (prin1-to-string fn))
+ (byte-compile-warn-x fn "`%s' is a malformed function" fn)
form)
((guard (when for-effect
@@ -628,8 +492,10 @@ for speeding up processing.")
(or byte-compile-delete-errors
(eq tmp 'error-free)
(progn
- (byte-compile-warn "value returned from %s is unused"
- (prin1-to-string form))
+ (byte-compile-warn-x
+ form
+ "value returned from %s is unused"
+ form)
nil)))))
(byte-compile-log " %s called for effect; deleted" fn)
;; appending a nil here might not be necessary, but it can't hurt.
@@ -678,49 +544,50 @@ for speeding up processing.")
(defun byte-optimize--rename-var (var new-var form)
"Replace VAR with NEW-VAR in FORM."
- (pcase form
- ((pred symbolp) (if (eq form var) new-var form))
- (`(setq . ,args)
- (let ((new-args nil))
- (while args
- (push (byte-optimize--rename-var var new-var (car args)) new-args)
- (push (byte-optimize--rename-var var new-var (cadr args)) new-args)
- (setq args (cddr args)))
- `(setq . ,(nreverse new-args))))
- ;; In binding constructs like `let', `let*' and `condition-case' we
- ;; rename everything for simplicity, even new bindings named VAR.
- (`(,(and head (or 'let 'let*)) ,bindings . ,body)
- `(,head
- ,(mapcar (lambda (b) (byte-optimize--rename-var-body var new-var b))
- bindings)
- ,@(byte-optimize--rename-var-body var new-var body)))
- (`(condition-case ,res-var ,protected-form . ,handlers)
- `(condition-case ,(byte-optimize--rename-var var new-var res-var)
- ,(byte-optimize--rename-var var new-var protected-form)
- ,@(mapcar (lambda (h)
- (cons (car h)
- (byte-optimize--rename-var-body var new-var (cdr h))))
- handlers)))
- (`(internal-make-closure ,vars ,env . ,rest)
- `(internal-make-closure
- ,vars ,(byte-optimize--rename-var-body var new-var env) . ,rest))
- (`(defvar ,name . ,rest)
- ;; NAME is not renamed here; we only care about lexical variables.
- `(defvar ,name . ,(byte-optimize--rename-var-body var new-var rest)))
-
- (`(cond . ,clauses)
- `(cond ,@(mapcar (lambda (c)
- (byte-optimize--rename-var-body var new-var c))
- clauses)))
-
- (`(function . ,_) form)
- (`(quote . ,_) form)
- (`(lambda . ,_) form)
-
- ;; Function calls and special forms not handled above.
- (`(,head . ,args)
- `(,head . ,(byte-optimize--rename-var-body var new-var args)))
- (_ form)))
+ (let ((fn (car-safe form)))
+ (pcase form
+ ((pred symbolp) (if (eq form var) new-var form))
+ (`(setq . ,args)
+ (let ((new-args nil))
+ (while args
+ (push (byte-optimize--rename-var var new-var (car args)) new-args)
+ (push (byte-optimize--rename-var var new-var (cadr args)) new-args)
+ (setq args (cddr args)))
+ `(,fn . ,(nreverse new-args))))
+ ;; In binding constructs like `let', `let*' and `condition-case' we
+ ;; rename everything for simplicity, even new bindings named VAR.
+ (`(,(and head (or 'let 'let*)) ,bindings . ,body)
+ `(,head
+ ,(mapcar (lambda (b) (byte-optimize--rename-var-body var new-var b))
+ bindings)
+ ,@(byte-optimize--rename-var-body var new-var body)))
+ (`(condition-case ,res-var ,protected-form . ,handlers)
+ `(,fn ,(byte-optimize--rename-var var new-var res-var)
+ ,(byte-optimize--rename-var var new-var protected-form)
+ ,@(mapcar (lambda (h)
+ (cons (car h)
+ (byte-optimize--rename-var-body var new-var (cdr h))))
+ handlers)))
+ (`(internal-make-closure ,vars ,env . ,rest)
+ `(,fn
+ ,vars ,(byte-optimize--rename-var-body var new-var env) . ,rest))
+ (`(defvar ,name . ,rest)
+ ;; NAME is not renamed here; we only care about lexical variables.
+ `(,fn ,name . ,(byte-optimize--rename-var-body var new-var rest)))
+
+ (`(cond . ,clauses)
+ `(,fn ,@(mapcar (lambda (c)
+ (byte-optimize--rename-var-body var new-var c))
+ clauses)))
+
+ (`(function . ,_) form)
+ (`(quote . ,_) form)
+ (`(lambda . ,_) form)
+
+ ;; Function calls and special forms not handled above.
+ (`(,head . ,args)
+ `(,head . ,(byte-optimize--rename-var-body var new-var args)))
+ (_ form))))
(defun byte-optimize-let-form (head form for-effect)
;; Recursively enter the optimizer for the bindings and body
@@ -822,12 +689,8 @@ for speeding up processing.")
(let ((byte-optimize--lexvars nil))
(cons
(mapcar (lambda (binding)
- (if (symbolp binding)
- binding
- (when (or (atom binding) (cddr binding))
- (byte-compile-warn "malformed let binding: `%S'" binding))
- (list (car binding)
- (byte-optimize-form (nth 1 binding) nil))))
+ (list (car binding)
+ (byte-optimize-form (nth 1 binding) nil)))
(car form))
(byte-optimize-body (cdr form) for-effect)))))
@@ -1165,6 +1028,14 @@ See Info node `(elisp) Integer Basics'."
form ; No improvement.
(cons 'concat (nreverse newargs)))))
+(defun byte-optimize-string-greaterp (form)
+ ;; Rewrite in terms of `string-lessp' which has its own bytecode.
+ (pcase (cdr form)
+ (`(,a ,b) (let ((arg1 (make-symbol "arg1")))
+ `(let ((,arg1 ,a))
+ (string-lessp ,b ,arg1))))
+ (_ form)))
+
(put 'identity 'byte-optimizer #'byte-optimize-identity)
(put 'memq 'byte-optimizer #'byte-optimize-memq)
(put 'memql 'byte-optimizer #'byte-optimize-member)
@@ -1188,6 +1059,9 @@ See Info node `(elisp) Integer Basics'."
(put 'string= 'byte-optimizer #'byte-optimize-binary-predicate)
(put 'string-equal 'byte-optimizer #'byte-optimize-binary-predicate)
+(put 'string-greaterp 'byte-optimizer #'byte-optimize-string-greaterp)
+(put 'string> 'byte-optimizer #'byte-optimize-string-greaterp)
+
(put 'concat 'byte-optimizer #'byte-optimize-concat)
;; I'm not convinced that this is necessary. Doesn't the optimizer loop
@@ -1279,21 +1153,21 @@ See Info node `(elisp) Integer Basics'."
(proper-list-p clause))
(if (null (cddr clause))
;; A trivial `progn'.
- (byte-optimize-if `(if ,(cadr clause) ,@(nthcdr 2 form)))
+ (byte-optimize-if `(,(car form) ,(cadr clause) ,@(nthcdr 2 form)))
(nconc (butlast clause)
(list
(byte-optimize-if
- `(if ,(car (last clause)) ,@(nthcdr 2 form)))))))
+ `(,(car form) ,(car (last clause)) ,@(nthcdr 2 form)))))))
((byte-compile-trueconstp clause)
`(progn ,clause ,(nth 2 form)))
((byte-compile-nilconstp clause)
`(progn ,clause ,@(nthcdr 3 form)))
((nth 2 form)
(if (equal '(nil) (nthcdr 3 form))
- (list 'if clause (nth 2 form))
+ (list (car form) clause (nth 2 form))
form))
((or (nth 3 form) (nthcdr 4 form))
- (list 'if
+ (list (car form)
;; Don't make a double negative;
;; instead, take away the one that is there.
(if (and (consp clause) (memq (car clause) '(not null))
@@ -1308,7 +1182,7 @@ See Info node `(elisp) Integer Basics'."
(defun byte-optimize-while (form)
(when (< (length form) 2)
- (byte-compile-warn "too few arguments for `while'"))
+ (byte-compile-warn-x form "too few arguments for `while'"))
(if (nth 1 form)
form))
@@ -1346,9 +1220,10 @@ See Info node `(elisp) Integer Basics'."
(let ((butlast (nreverse (cdr (reverse (cdr (cdr form)))))))
(nconc (list 'funcall fn) butlast
(mapcar (lambda (x) (list 'quote x)) (nth 1 last))))
- (byte-compile-warn
+ (byte-compile-warn-x
+ last
"last arg to apply can't be a literal atom: `%s'"
- (prin1-to-string last))
+ last)
nil))
form))))
@@ -1367,28 +1242,17 @@ See Info node `(elisp) Integer Basics'."
;; Body is empty or just contains a constant.
(`(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p)))))
(if (eq head 'let)
- `(progn ,@(mapcar (lambda (binding)
- (and (consp binding) (cadr binding)))
- bindings)
- ,const)
- `(let* ,(butlast bindings)
- ,@(and (consp (car (last bindings)))
- (cdar (last bindings)))
- ,const)))
+ `(progn ,@(mapcar #'cadr bindings) ,const)
+ `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))
;; Body is last variable.
(`(,head ,(and bindings
- (let last-var (let ((last (car (last bindings))))
- (if (consp last) (car last) last))))
+ (let last-var (caar (last bindings))))
,(and last-var ; non-linear pattern
(pred symbolp) (pred (not keywordp)) (pred (not booleanp))))
(if (eq head 'let)
- `(progn ,@(mapcar (lambda (binding)
- (and (consp binding) (cadr binding)))
- bindings))
- `(let* ,(butlast bindings)
- ,@(and (consp (car (last bindings)))
- (cdar (last bindings))))))
+ `(progn ,@(mapcar #'cadr bindings))
+ `(,head ,(butlast bindings) ,(cadar (last bindings)))))
(_ form)))
@@ -1471,7 +1335,7 @@ See Info node `(elisp) Integer Basics'."
buffer-substring byte-code-function-p
capitalize car-less-than-car car cdr ceiling char-after char-before
char-equal char-to-string char-width compare-strings
- compare-window-configurations concat coordinates-in-window-p
+ window-configuration-equal-p concat coordinates-in-window-p
copy-alist copy-sequence copy-marker copysign cos count-lines
current-time-string current-time-zone
decode-char
@@ -1497,7 +1361,7 @@ See Info node `(elisp) Integer Basics'."
match-beginning match-end
member memq memql min minibuffer-selected-window minibuffer-window
mod multibyte-char-to-unibyte next-window nth nthcdr number-to-string
- parse-colon-path plist-get plist-member
+ parse-colon-path
prefix-numeric-value previous-window prin1-to-string propertize
degrees-to-radians
radians-to-degrees rassq rassoc read-from-string regexp-opt
@@ -1619,7 +1483,7 @@ See Info node `(elisp) Integer Basics'."
;; `assoc' and `assoc-default' are excluded since they are
;; impure if the test function is (consider `string-match').
assq rassq rassoc
- plist-get lax-plist-get plist-member
+ lax-plist-get
aref elt
base64-decode-string base64-encode-string base64url-encode-string
bool-vector-subsetp
@@ -2196,9 +2060,9 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
((and (memq (car lap0) byte-goto-ops)
(memq (car (setq tmp (nth 1 (memq (cdr lap0) lap))))
'(byte-goto byte-return)))
- (cond ((and (not (eq tmp lap0))
- (or (eq (car lap0) 'byte-goto)
- (eq (car tmp) 'byte-goto)))
+ (cond ((and (or (eq (car lap0) 'byte-goto)
+ (eq (car tmp) 'byte-goto))
+ (not (eq (cdr tmp) (cdr lap0))))
(byte-compile-log-lap " %s [%s]\t-->\t%s"
(car lap0) tmp tmp)
(if (eq (car tmp) 'byte-return)
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 47f331fd9d0..dd90bcf4d82 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -30,6 +30,76 @@
;;; Code:
+(defvar byte-run--ssp-seen nil
+ "Which conses/vectors/records have been processed in strip-symbol-positions?
+The value is a hash table, the keys being the elements and the values being t.
+
+The purpose of this is to detect circular structures.")
+
+(defalias 'byte-run--strip-list
+ #'(lambda (arg)
+ "Strip the positions from symbols with position in the list ARG.
+This is done by destructively modifying ARG. Return ARG."
+ (let ((a arg))
+ (while
+ (and
+ (not (gethash a byte-run--ssp-seen))
+ (progn
+ (puthash a t byte-run--ssp-seen)
+ (cond
+ ((symbol-with-pos-p (car a))
+ (setcar a (bare-symbol (car a))))
+ ((consp (car a))
+ (byte-run--strip-list (car a)))
+ ((or (vectorp (car a)) (recordp (car a)))
+ (byte-run--strip-vector/record (car a))))
+ (consp (cdr a))))
+ (setq a (cdr a)))
+ (cond
+ ((symbol-with-pos-p (cdr a))
+ (setcdr a (bare-symbol (cdr a))))
+ ((or (vectorp (cdr a)) (recordp (cdr a)))
+ (byte-run--strip-vector/record (cdr a))))
+ arg)))
+
+(defalias 'byte-run--strip-vector/record
+ #'(lambda (arg)
+ "Strip the positions from symbols with position in the vector/record ARG.
+This is done by destructively modifying ARG. Return ARG."
+ (unless (gethash arg byte-run--ssp-seen)
+ (let ((len (length arg))
+ (i 0)
+ elt)
+ (puthash arg t byte-run--ssp-seen)
+ (while (< i len)
+ (setq elt (aref arg i))
+ (cond
+ ((symbol-with-pos-p elt)
+ (aset arg i elt))
+ ((consp elt)
+ (byte-run--strip-list elt))
+ ((or (vectorp elt) (recordp elt))
+ (byte-run--strip-vector/record elt)))
+ (setq i (1+ i)))))
+ arg))
+
+(defalias 'byte-run-strip-symbol-positions
+ #'(lambda (arg)
+ "Strip all positions from symbols in ARG.
+This modifies destructively then returns ARG.
+
+ARG is any Lisp object, but is usually a list or a vector or a
+record, containing symbols with position."
+ (setq byte-run--ssp-seen (make-hash-table :test 'eq))
+ (cond
+ ((symbol-with-pos-p arg)
+ (bare-symbol arg))
+ ((consp arg)
+ (byte-run--strip-list arg))
+ ((or (vectorp arg) (recordp arg))
+ (byte-run--strip-vector/record arg))
+ (t arg))))
+
(defalias 'function-put
;; We don't want people to just use `put' because we can't conveniently
;; hook into `put' to remap old properties to new ones. But for now, there's
@@ -38,7 +108,7 @@
"Set FUNCTION's property PROP to VALUE.
The namespace for PROP is shared with symbols.
So far, FUNCTION can only be a symbol, not a lambda expression."
- (put function prop value)))
+ (put (bare-symbol function) prop value)))
(function-put 'defmacro 'doc-string-elt 3)
(function-put 'defmacro 'lisp-indent-function 2)
@@ -96,7 +166,7 @@ The return value of this function is not used."
(defalias 'byte-run--set-obsolete
#'(lambda (f _args new-name when)
(list 'make-obsolete
- (list 'quote f) (list 'quote new-name) (list 'quote when))))
+ (list 'quote f) (list 'quote new-name) when)))
(defalias 'byte-run--set-interactive-only
#'(lambda (f _args instead)
@@ -140,12 +210,16 @@ The return value of this function is not used."
(defalias 'byte-run--set-doc-string
#'(lambda (f _args pos)
(list 'function-put (list 'quote f)
- ''doc-string-elt (list 'quote pos))))
+ ''doc-string-elt (if (numberp pos)
+ pos
+ (list 'quote pos)))))
(defalias 'byte-run--set-indent
#'(lambda (f _args val)
(list 'function-put (list 'quote f)
- ''lisp-indent-function (list 'quote val))))
+ ''lisp-indent-function (if (numberp val)
+ val
+ (list 'quote val)))))
(defalias 'byte-run--set-speed
#'(lambda (f _args val)
@@ -202,6 +276,75 @@ This is used by `declare'.")
(list 'function-put (list 'quote name)
''no-font-lock-keyword (list 'quote val))))
+(defalias 'byte-run--parse-body
+ #'(lambda (body allow-interactive)
+ "Decompose BODY into (DOCSTRING DECLARE INTERACTIVE BODY-REST WARNINGS)."
+ (let* ((top body)
+ (docstring nil)
+ (declare-form nil)
+ (interactive-form nil)
+ (warnings nil)
+ (warn #'(lambda (msg form)
+ (push (macroexp-warn-and-return msg nil nil t form)
+ warnings))))
+ (while
+ (and body
+ (let* ((form (car body))
+ (head (car-safe form)))
+ (cond
+ ((or (and (stringp form) (cdr body))
+ (eq head :documentation))
+ (cond
+ (docstring (funcall warn "More than one doc string" top))
+ (declare-form
+ (funcall warn "Doc string after `declare'" declare-form))
+ (interactive-form
+ (funcall warn "Doc string after `interactive'"
+ interactive-form))
+ (t (setq docstring form)))
+ t)
+ ((eq head 'declare)
+ (cond
+ (declare-form
+ (funcall warn "More than one `declare' form" form))
+ (interactive-form
+ (funcall warn "`declare' after `interactive'" form))
+ (t (setq declare-form form)))
+ t)
+ ((eq head 'interactive)
+ (cond
+ ((not allow-interactive)
+ (funcall warn "No `interactive' form allowed here" form))
+ (interactive-form
+ (funcall warn "More than one `interactive' form" form))
+ (t (setq interactive-form form)))
+ t))))
+ (setq body (cdr body)))
+ (list docstring declare-form interactive-form body warnings))))
+
+(defalias 'byte-run--parse-declarations
+ #'(lambda (name arglist clauses construct declarations-alist)
+ (let* ((cl-decls nil)
+ (actions
+ (mapcar
+ #'(lambda (x)
+ (let ((f (cdr (assq (car x) declarations-alist))))
+ (cond
+ (f (apply (car f) name arglist (cdr x)))
+ ;; Yuck!!
+ ((and (featurep 'cl)
+ (memq (car x) ;C.f. cl--do-proclaim.
+ '(special inline notinline optimize warn)))
+ (push (list 'declare x) cl-decls)
+ nil)
+ (t
+ (macroexp-warn-and-return
+ (format-message "Unknown %s property `%S'"
+ construct (car x))
+ nil nil nil (car x))))))
+ clauses)))
+ (cons actions cl-decls))))
+
(defvar macro-declarations-alist
(cons
(list 'debug #'byte-run--set-debug)
@@ -219,7 +362,7 @@ This is used by `declare'.")
(defalias 'defmacro
(cons
'macro
- #'(lambda (name arglist &optional docstring &rest body)
+ #'(lambda (name arglist &rest body)
"Define NAME as a macro.
When the macro is called, as in (NAME ARGS...),
the function (lambda ARGLIST BODY...) is applied to
@@ -230,116 +373,73 @@ DECLS is a list of elements of the form (PROP . VALUES). These are
interpreted according to `macro-declarations-alist'.
The return value is undefined.
-\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)"
- ;; We can't just have `decl' as an &optional argument, because we need
- ;; to distinguish
- ;; (defmacro foo (arg) (bar) nil)
- ;; from
- ;; (defmacro foo (arg) (bar)).
- (let ((decls (cond
- ((eq (car-safe docstring) 'declare)
- (prog1 (cdr docstring) (setq docstring nil)))
- ((and (stringp docstring)
- (eq (car-safe (car body)) 'declare))
- (prog1 (cdr (car body)) (setq body (cdr body)))))))
- (if docstring (setq body (cons docstring body))
- (if (null body) (setq body '(nil))))
- ;; Can't use backquote because it's not defined yet!
- (let* ((fun (list 'function (cons 'lambda (cons arglist body))))
- (def (list 'defalias
- (list 'quote name)
- (list 'cons ''macro fun)))
- (declarations
- (mapcar
- #'(lambda (x)
- (let ((f (cdr (assq (car x) macro-declarations-alist))))
- (if f (apply (car f) name arglist (cdr x))
- (macroexp-warn-and-return
- (format-message
- "Unknown macro property %S in %S"
- (car x) name)
- nil))))
- decls)))
- ;; Refresh font-lock if this is a new macro, or it is an
- ;; existing macro whose 'no-font-lock-keyword declaration
- ;; has changed.
- (if (and
- ;; If lisp-mode hasn't been loaded, there's no reason
- ;; to flush.
- (fboundp 'lisp--el-font-lock-flush-elisp-buffers)
- (or (not (fboundp name)) ;; new macro
- (and (fboundp name) ;; existing macro
- (member `(function-put ',name 'no-font-lock-keyword
- ',(get name 'no-font-lock-keyword))
- declarations))))
- (lisp--el-font-lock-flush-elisp-buffers))
- (if declarations
- (cons 'prog1 (cons def declarations))
+\(fn NAME ARGLIST [DOCSTRING] [DECL] BODY...)"
+ (let* ((parse (byte-run--parse-body body nil))
+ (docstring (nth 0 parse))
+ (declare-form (nth 1 parse))
+ (body (nth 3 parse))
+ (warnings (nth 4 parse))
+ (declarations
+ (and declare-form (byte-run--parse-declarations
+ name arglist (cdr declare-form) 'macro
+ macro-declarations-alist))))
+ (setq body (nconc warnings body))
+ (setq body (nconc (cdr declarations) body))
+ (if docstring
+ (setq body (cons docstring body)))
+ (if (null body)
+ (setq body '(nil)))
+ (let* ((fun (list 'function (cons 'lambda (cons arglist body))))
+ (def (list 'defalias
+ (list 'quote name)
+ (list 'cons ''macro fun))))
+ (if declarations
+ (cons 'prog1 (cons def (car declarations)))
def))))))
;; Now that we defined defmacro we can use it!
-(defmacro defun (name arglist &optional docstring &rest body)
+(defmacro defun (name arglist &rest body)
"Define NAME as a function.
-The definition is (lambda ARGLIST [DOCSTRING] BODY...).
-See also the function `interactive'.
+The definition is (lambda ARGLIST [DOCSTRING] [INTERACTIVE] BODY...).
DECL is a declaration, optional, of the form (declare DECLS...) where
DECLS is a list of elements of the form (PROP . VALUES). These are
interpreted according to `defun-declarations-alist'.
+INTERACTIVE is an optional `interactive' specification.
The return value is undefined.
-\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)"
- ;; We can't just have `decl' as an &optional argument, because we need
- ;; to distinguish
- ;; (defun foo (arg) (toto) nil)
- ;; from
- ;; (defun foo (arg) (toto)).
+\(fn NAME ARGLIST [DOCSTRING] [DECL] [INTERACTIVE] BODY...)"
(declare (doc-string 3) (indent 2))
(or name (error "Cannot define '%s' as a function" name))
(if (null
(and (listp arglist)
(null (delq t (mapcar #'symbolp arglist)))))
(error "Malformed arglist: %s" arglist))
- (let ((decls (cond
- ((eq (car-safe docstring) 'declare)
- (prog1 (cdr docstring) (setq docstring nil)))
- ((and (stringp docstring)
- (eq (car-safe (car body)) 'declare))
- (prog1 (cdr (car body)) (setq body (cdr body)))))))
- (if docstring (setq body (cons docstring body))
- (if (null body) (setq body '(nil))))
- (let ((declarations
- (mapcar
- #'(lambda (x)
- (let ((f (cdr (assq (car x) defun-declarations-alist))))
- (cond
- (f (apply (car f) name arglist (cdr x)))
- ;; Yuck!!
- ((and (featurep 'cl)
- (memq (car x) ;C.f. cl-do-proclaim.
- '(special inline notinline optimize warn)))
- (push (list 'declare x)
- (if (stringp docstring)
- (if (eq (car-safe (cadr body)) 'interactive)
- (cddr body)
- (cdr body))
- (if (eq (car-safe (car body)) 'interactive)
- (cdr body)
- body)))
- nil)
- (t
- (macroexp-warn-and-return
- (format-message "Unknown defun property `%S' in %S"
- (car x) name)
- nil)))))
- decls))
- (def (list 'defalias
+ (let* ((parse (byte-run--parse-body body t))
+ (docstring (nth 0 parse))
+ (declare-form (nth 1 parse))
+ (interactive-form (nth 2 parse))
+ (body (nth 3 parse))
+ (warnings (nth 4 parse))
+ (declarations
+ (and declare-form (byte-run--parse-declarations
+ name arglist (cdr declare-form) 'defun
+ defun-declarations-alist))))
+ (setq body (nconc warnings body))
+ (setq body (nconc (cdr declarations) body))
+ (if interactive-form
+ (setq body (cons interactive-form body)))
+ (if docstring
+ (setq body (cons docstring body)))
+ (if (null body)
+ (setq body '(nil)))
+ (let ((def (list 'defalias
(list 'quote name)
(list 'function
(cons 'lambda
(cons arglist body))))))
(if declarations
- (cons 'prog1 (cons def declarations))
- def))))
+ (cons 'prog1 (cons def (car declarations)))
+ def))))
;; Redefined in byte-opt.el.
@@ -464,7 +564,7 @@ made obsolete, for example a date or a release number.
This macro evaluates all its parameters, and both OBSOLETE-NAME
and CURRENT-NAME should be symbols, so a typical usage would look like:
- (define-obsolete-variable-alias 'foo-thing 'bar-thing \"28.1\")
+ (define-obsolete-variable-alias \\='foo-thing \\='bar-thing \"28.1\")
This macro uses `defvaralias' and `make-obsolete-variable' (which see).
See the Info node `(elisp)Variable Aliases' for more details.
@@ -575,7 +675,7 @@ For the `mapcar' case, only the `mapcar' function can be used in
the symbol list. For `suspicious', only `set-buffer' can be used."
;; Note: during compilation, this definition is overridden by the one in
;; byte-compile-initial-macro-environment.
- (declare (debug (sexp &optional body)) (indent 1))
+ (declare (debug (sexp body)) (indent 1))
(if (not (and (featurep 'macroexp)
(boundp 'byte-compile--suppressed-warnings)))
;; If `macroexp' is not yet loaded, we're in the middle of
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 708e6123606..8df4133b6b0 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -244,11 +244,6 @@ the functions you loaded will not be able to run.")
(make-obsolete-variable 'byte-compile-dynamic "not worthwhile any more." "27.1")
;;;###autoload(put 'byte-compile-dynamic 'safe-local-variable 'booleanp)
-(defvar byte-compile-disable-print-circle nil
- "If non-nil, disable `print-circle' on printing a byte-compiled code.")
-(make-obsolete-variable 'byte-compile-disable-print-circle nil "24.1")
-;;;###autoload(put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp)
-
(defcustom byte-compile-dynamic-docstrings t
"If non-nil, compile doc strings for lazy access.
We bury the doc strings of functions and variables inside comments in
@@ -299,10 +294,10 @@ The information is logged to `byte-compile-log-buffer'."
'(redefine callargs free-vars unresolved
obsolete noruntime interactive-only
make-local mapcar constants suspicious lexical lexical-dynamic
- docstrings not-unused)
+ docstrings docstrings-non-ascii-quotes not-unused)
"The list of warning types used when `byte-compile-warnings' is t.")
(defcustom byte-compile-warnings t
- "List of warnings that the byte-compiler should issue (t for all).
+ "List of warnings that the byte-compiler should issue (t for almost all).
Elements of the list may be:
@@ -325,16 +320,30 @@ Elements of the list may be:
constants let-binding of, or assignment to, constants/nonvariables.
docstrings docstrings that are too wide (longer than
`byte-compile-docstring-max-column' or
- `fill-column' characters, whichever is bigger).
+ `fill-column' characters, whichever is bigger) or
+ have other stylistic issues.
+ docstrings-non-ascii-quotes docstrings that have non-ASCII quotes.
+ This depends on the `docstrings' warning type.
suspicious constructs that usually don't do what the coder wanted.
If the list begins with `not', then the remaining elements specify warnings to
-suppress. For example, (not mapcar) will suppress warnings about mapcar."
+suppress. For example, (not mapcar) will suppress warnings about mapcar.
+
+The t value means \"all non experimental warning types\", and
+excludes the types in `byte-compile--emacs-build-warning-types'.
+A value of `all' really means all."
:type `(choice (const :tag "All" t)
(set :menu-tag "Some"
,@(mapcar (lambda (x) `(const ,x))
byte-compile-warning-types))))
+(defconst byte-compile--emacs-build-warning-types
+ '(docstrings-non-ascii-quotes)
+ "List of warning types that are only enabled during Emacs builds.
+This is typically either warning types that are being phased in
+(but shouldn't be enabled for packages yet), or that are only relevant
+for the Emacs build itself.")
+
(defvar byte-compile--suppressed-warnings nil
"Dynamically bound by `with-suppressed-warnings' to suppress warnings.")
@@ -353,10 +362,15 @@ suppress. For example, (not mapcar) will suppress warnings about mapcar."
(memq symbol (cdr elem)))
(setq suppress t)))
(and (not suppress)
- (or (eq byte-compile-warnings t)
- (if (eq (car byte-compile-warnings) 'not)
- (not (memq warning byte-compile-warnings))
- (memq warning byte-compile-warnings))))))
+ ;; During an Emacs build, we want all warnings.
+ (or (eq byte-compile-warnings 'all)
+ ;; If t, we want almost all the warnings, but not the
+ ;; ones that are Emacs build specific.
+ (and (not (memq warning byte-compile--emacs-build-warning-types))
+ (or (eq byte-compile-warnings t)
+ (if (eq (car byte-compile-warnings) 'not)
+ (not (memq warning byte-compile-warnings))
+ (memq warning byte-compile-warnings))))))))
;;;###autoload
(defun byte-compile-disable-warning (warning)
@@ -468,9 +482,10 @@ Return the compile-time value of FORM."
;; 3.2.3.1, "Processing of Top Level Forms". The semantics are very
;; subtle: see test/lisp/emacs-lisp/bytecomp-tests.el for interesting
;; cases.
- (setf form (macroexp-macroexpand form byte-compile-macro-environment))
+ (let ((print-symbols-bare t)) ; Possibly redundant binding.
+ (setf form (macroexp-macroexpand form byte-compile-macro-environment)))
(if (eq (car-safe form) 'progn)
- (cons 'progn
+ (cons (car form)
(mapcar (lambda (subform)
(byte-compile-recurse-toplevel
subform non-toplevel-case))
@@ -499,8 +514,9 @@ Return the compile-time value of FORM."
byte-compile-new-defuns))
(setf result
(byte-compile-eval
- (byte-compile-top-level
- (byte-compile-preprocess form)))))))
+ (byte-run-strip-symbol-positions
+ (byte-compile-top-level
+ (byte-compile-preprocess form))))))))
(list 'quote result))))
(eval-and-compile . ,(lambda (&rest body)
(byte-compile-recurse-toplevel
@@ -509,10 +525,12 @@ Return the compile-time value of FORM."
;; Don't compile here, since we don't know
;; whether to compile as byte-compile-form
;; or byte-compile-file-form.
- (let ((expanded
- (macroexpand--all-toplevel
- form
- macroexpand-all-environment)))
+ (let* ((print-symbols-bare t) ; Possibly redundant binding.
+ (expanded
+ (byte-run-strip-symbol-positions
+ (macroexpand--all-toplevel
+ form
+ macroexpand-all-environment))))
(eval expanded lexical-binding)
expanded)))))
(with-suppressed-warnings
@@ -615,8 +633,8 @@ Each element is (INDEX . VALUE)")
"Hash byte-code -> byte-to-native-lambda.")
(defvar byte-to-native-top-level-forms nil
"List of top level forms.")
-(defvar byte-to-native-output-file nil
- "Temporary file containing the byte-compilation output.")
+(defvar byte-to-native-output-buffer-file nil
+ "Pair holding byte-compilation output buffer, elc filename.")
(defvar byte-to-native-plist-environment nil
"To spill `overriding-plist-environment'.")
@@ -658,10 +676,13 @@ Each element is (INDEX . VALUE)")
(put 'byte-stack+-info 'tmp-compile-time-value nil)))
-;; These opcodes are special in that they pack their argument into the
-;; opcode word.
-;;
+;; The following opcodes (1-47) use the 3 lowest bits for an immediate
+;; argument.
+
(byte-defop 0 1 byte-stack-ref "for stack reference")
+;; Code 0 is actually unused but reserved as invalid code for detecting
+;; corrupted bytecode. Codes 1-7 are stack-ref.
+
(byte-defop 8 1 byte-varref "for variable reference")
(byte-defop 16 -1 byte-varset "for setting a variable")
(byte-defop 24 -1 byte-varbind "for binding a variable")
@@ -669,11 +690,9 @@ Each element is (INDEX . VALUE)")
(byte-defop 40 0 byte-unbind "for unbinding special bindings")
;; codes 8-47 are consumed by the preceding opcodes
-;; New (in Emacs-24.4) bytecodes for more efficient handling of non-local exits
-;; (especially useful in lexical-binding code).
(byte-defop 48 0 byte-pophandler)
-(byte-defop 50 -1 byte-pushcatch)
(byte-defop 49 -1 byte-pushconditioncase)
+(byte-defop 50 -1 byte-pushcatch)
;; unused: 51-55
@@ -696,9 +715,9 @@ Each element is (INDEX . VALUE)")
(byte-defop 72 -1 byte-aref)
(byte-defop 73 -2 byte-aset)
(byte-defop 74 0 byte-symbol-value)
-(byte-defop 75 0 byte-symbol-function) ; this was commented out
+(byte-defop 75 0 byte-symbol-function)
(byte-defop 76 -1 byte-set)
-(byte-defop 77 -1 byte-fset) ; this was commented out
+(byte-defop 77 -1 byte-fset)
(byte-defop 78 -1 byte-get)
(byte-defop 79 -2 byte-substring)
(byte-defop 80 -1 byte-concat2)
@@ -716,8 +735,9 @@ Each element is (INDEX . VALUE)")
(byte-defop 92 -1 byte-plus)
(byte-defop 93 -1 byte-max)
(byte-defop 94 -1 byte-min)
-(byte-defop 95 -1 byte-mult) ; v19 only
+(byte-defop 95 -1 byte-mult)
(byte-defop 96 1 byte-point)
+(byte-defop 97 0 byte-save-current-buffer-OBSOLETE) ; unused since v20
(byte-defop 98 0 byte-goto-char)
(byte-defop 99 0 byte-insert)
(byte-defop 100 1 byte-point-max)
@@ -739,7 +759,6 @@ Each element is (INDEX . VALUE)")
(byte-defop 115 0 byte-set-mark-OBSOLETE)
(byte-defop 116 1 byte-interactive-p-OBSOLETE)
-;; These ops are new to v19
(byte-defop 117 0 byte-forward-char)
(byte-defop 118 0 byte-forward-word)
(byte-defop 119 -1 byte-skip-chars-forward)
@@ -794,13 +813,8 @@ the unwind-action")
(byte-defop 144 0 byte-temp-output-buffer-setup-OBSOLETE)
(byte-defop 145 -1 byte-temp-output-buffer-show-OBSOLETE)
-;; these ops are new to v19
+;; unused: 146
-;; To unbind back to the beginning of this frame.
-;; Not used yet, but will be needed for tail-recursion elimination.
-(byte-defop 146 0 byte-unbind-all)
-
-;; these ops are new to v19
(byte-defop 147 -2 byte-set-marker)
(byte-defop 148 0 byte-match-beginning)
(byte-defop 149 0 byte-match-end)
@@ -847,10 +861,11 @@ the unwind-action")
"to take a hash table and a value from the stack, and jump to
the address the value maps to, if any.")
-;; unused: 182-191
+;; unused: 184-191
(byte-defop 192 1 byte-constant "for reference to a constant")
-;; codes 193-255 are consumed by byte-constant.
+;; Codes 193-255 are consumed by `byte-constant', which uses the 6
+;; lowest bits for an immediate argument.
(defconst byte-constant-limit 64
"Exclusive maximum index usable in the `byte-constant' opcode.")
@@ -1009,13 +1024,22 @@ CONST2 may be evaluated multiple times."
;; Similarly, replace TAGs in all jump tables with the correct PC index.
(dolist (hash-table byte-compile-jump-tables)
- (maphash #'(lambda (value tag)
- (setq pc (cadr tag))
- ;; We don't need to split PC here, as it is stored as a lisp
- ;; object in the hash table (whereas other goto-* ops store
- ;; it within 2 bytes in the byte string).
- (puthash value pc hash-table))
- hash-table))
+ (let (alist)
+ (maphash #'(lambda (value tag)
+ (setq pc (cadr tag))
+ ;; We don't need to split PC here, as it is stored as a
+ ;; lisp object in the hash table (whereas other goto-*
+ ;; ops store it within 2 bytes in the byte string).
+ ;; De-position any symbols with position in `value'.
+ ;; Since this may change the hash table key, we remove
+ ;; the entry from the table and reinsert it outside the
+ ;; scope of the `maphash'.
+ (setq value (byte-run-strip-symbol-positions value))
+ (push (cons value pc) alist)
+ (remhash value hash-table))
+ hash-table)
+ (dolist (elt alist)
+ (puthash (car elt) (cdr elt) hash-table))))
(let ((bytecode (apply 'unibyte-string (nreverse bytes))))
(when byte-native-compiling
;; Spill LAP for the native compiler here.
@@ -1033,30 +1057,29 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
(hist-nil-orig current-load-list))
(prog1 (eval form lexical-binding)
(when (byte-compile-warning-enabled-p 'noruntime)
- (let ((hist-new load-history)
- (hist-nil-new current-load-list))
+ (let* ((hist-new
+ ;; Get new `current-load-list' for the locally defined funs.
+ (cons (butlast current-load-list
+ (length hist-nil-orig))
+ load-history)))
;; Go through load-history, look for newly loaded files
;; and mark all the functions defined therein.
(while (and hist-new (not (eq hist-new hist-orig)))
- (let ((xs (pop hist-new))
- old-autoloads)
+ (let ((xs (pop hist-new)))
;; Make sure the file was not already loaded before.
(unless (assoc (car xs) hist-orig)
(dolist (s xs)
- (cond
- ((and (consp s) (eq t (car s)))
- (push (cdr s) old-autoloads))
- ((and (consp s) (memq (car s) '(autoload defun)))
- (unless (memq (cdr s) old-autoloads)
- (push (cdr s) byte-compile-noruntime-functions))))))))
- ;; Go through current-load-list for the locally defined funs.
- (let (old-autoloads)
- (while (and hist-nil-new (not (eq hist-nil-new hist-nil-orig)))
- (let ((s (pop hist-nil-new)))
- (when (and (symbolp s) (not (memq s old-autoloads)))
- (push s byte-compile-noruntime-functions))
- (when (and (consp s) (eq t (car s)))
- (push (cdr s) old-autoloads))))))))))
+ (pcase s
+ (`(defun . ,f)
+ ;; If `f' has a history, it's presumably because
+ ;; it was already defined beforehand (typically
+ ;; as an autoload). It could also be because it
+ ;; was defined twice during `form', in which case
+ ;; we arguably should add it to b-c-noruntime-functions,
+ ;; but it's not clear it's worth the trouble
+ ;; trying to recognize that case.
+ (unless (get f 'function-history)
+ (push f byte-compile-noruntime-functions)))))))))))))
(defun byte-compile-eval-before-compile (form)
"Evaluate FORM for `eval-and-compile'."
@@ -1095,10 +1118,8 @@ message buffer `default-directory'."
:type '(repeat (choice (const :tag "Default" nil)
(string :tag "Directory"))))
-(defvar emacs-lisp-compilation-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "g" 'emacs-lisp-compilation-recompile)
- map))
+(defvar-keymap emacs-lisp-compilation-mode-map
+ "g" #'emacs-lisp-compilation-recompile)
(defvar emacs-lisp-compilation--current-file nil)
@@ -1147,60 +1168,6 @@ message buffer `default-directory'."
(t
(insert (format "%s\n" string)))))))
-(defvar byte-compile-read-position nil
- "Character position we began the last `read' from.")
-(defvar byte-compile-last-position nil
- "Last known character position in the input.")
-
-;; copied from gnus-util.el
-(defsubst byte-compile-delete-first (elt list)
- (if (eq (car list) elt)
- (cdr list)
- (let ((total list))
- (while (and (cdr list)
- (not (eq (cadr list) elt)))
- (setq list (cdr list)))
- (when (cdr list)
- (setcdr list (cddr list)))
- total)))
-
-;; The purpose of `byte-compile-set-symbol-position' is to attempt to
-;; set `byte-compile-last-position' to the "current position" in the
-;; raw source code. This is used for warning and error messages.
-;;
-;; The function should be called for most occurrences of symbols in
-;; the forms being compiled, strictly in the order they occur in the
-;; source code. It should never be called twice for any single
-;; occurrence, and should not be called for symbols generated by the
-;; byte compiler itself.
-;;
-;; The function works by scanning the elements in the alist
-;; `read-symbol-positions-list' for the next match for the symbol
-;; after the current value of `byte-compile-last-position', setting
-;; that variable to the match's character position, then deleting the
-;; matching element from the list. Thus the new value for
-;; `byte-compile-last-position' is later than the old value unless,
-;; perhaps, ALLOW-PREVIOUS is non-nil.
-;;
-;; So your're probably asking yourself: Isn't this function a gross
-;; hack? And the answer, of course, would be yes.
-(defun byte-compile-set-symbol-position (sym &optional allow-previous)
- (when byte-compile-read-position
- (let ((last byte-compile-last-position)
- entry)
- (while (progn
- (setq entry (assq sym read-symbol-positions-list))
- (when entry
- (setq byte-compile-last-position
- (+ byte-compile-read-position (cdr entry))
- read-symbol-positions-list
- (byte-compile-delete-first
- entry read-symbol-positions-list)))
- (and entry
- (or (and allow-previous
- (not (= last byte-compile-last-position)))
- (> last byte-compile-last-position))))))))
-
(defvar byte-compile-last-warned-form nil)
(defvar byte-compile-last-logged-file nil)
(defvar byte-compile-root-dir nil
@@ -1213,6 +1180,36 @@ message buffer `default-directory'."
(f2 (file-relative-name file dir)))
(if (< (length f2) (length f1)) f2 f1)))
+(defun byte-compile--first-symbol-with-pos (form)
+ "Return the first symbol with position in form, or nil if none.
+Order is by depth-first search."
+ (cond
+ ((symbol-with-pos-p form) form)
+ ((consp form)
+ (or (byte-compile--first-symbol-with-pos (car form))
+ (let ((sym nil))
+ (setq form (cdr form))
+ (while (and (consp form)
+ (not (setq sym (byte-compile--first-symbol-with-pos
+ (car form)))))
+ (setq form (cdr form)))
+ (or sym
+ (and form (byte-compile--first-symbol-with-pos form))))))
+ ((or (vectorp form) (recordp form))
+ (let ((len (length form))
+ (i 0)
+ (sym nil))
+ (while (and (< i len)
+ (not (setq sym (byte-compile--first-symbol-with-pos
+ (aref form i)))))
+ (setq i (1+ i)))
+ sym))))
+
+(defun byte-compile--warning-source-offset ()
+ "Return a source offset from `byte-compile-form-stack' or nil if none."
+ (let ((sym (byte-compile--first-symbol-with-pos byte-compile-form-stack)))
+ (and sym (symbol-with-pos-pos sym))))
+
;; This is used as warning-prefix for the compiler.
;; It is always called with the warnings buffer current.
(defun byte-compile-warning-prefix (level entry)
@@ -1230,16 +1227,15 @@ message buffer `default-directory'."
(format "%s:" (byte-compile-abbreviate-file
load-file-name dir)))
(t "")))
- (pos (if (and byte-compile-current-file
- (integerp byte-compile-read-position))
+ (offset (byte-compile--warning-source-offset))
+ (pos (if (and byte-compile-current-file offset)
(with-current-buffer byte-compile-current-buffer
- (format "%d:%d:"
- (save-excursion
- (goto-char byte-compile-last-position)
- (1+ (count-lines (point-min) (point-at-bol))))
- (save-excursion
- (goto-char byte-compile-last-position)
- (1+ (current-column)))))
+ (let (new-l new-c)
+ (save-excursion
+ (goto-char offset)
+ (setq new-l (1+ (count-lines (point-min) (point-at-bol)))
+ new-c (1+ (current-column)))
+ (format "%d:%d:" new-l new-c))))
""))
(form (if (eq byte-compile-current-form :end) "end of data"
(or byte-compile-current-form "toplevel form"))))
@@ -1314,20 +1310,21 @@ Called with arguments (STRING POSITION FILL LEVEL). STRING is a
message describing the problem. POSITION is a buffer position
where the problem was detected. FILL is a prefix as in
`warning-fill-prefix'. LEVEL is the level of the
-problem (`:warning' or `:error'). POSITION, FILL and LEVEL may be
-nil.")
+problem (`:warning' or `:error'). FILL and LEVEL may be nil.")
(defun byte-compile-log-warning (string &optional fill level)
"Log a byte-compilation warning.
STRING, FILL and LEVEL are as described in
`byte-compile-log-warning-function', which see."
(funcall byte-compile-log-warning-function
- string byte-compile-last-position
+ string
+ (or (byte-compile--warning-source-offset)
+ (point))
fill
level))
-(defun byte-compile--log-warning-for-byte-compile (string &optional
- _position
+(defun byte-compile--log-warning-for-byte-compile (string _position
+ &optional
fill
level)
"Log a message STRING in `byte-compile-log-buffer'.
@@ -1348,6 +1345,14 @@ function directly; use `byte-compile-warn' or
(error "%s" format) ; byte-compile-file catches and logs it
(byte-compile-log-warning format t :warning)))
+(defun byte-compile-warn-x (arg format &rest args)
+ "Issue a byte compiler warning.
+ARG is the source element (likely a symbol with position) central to
+ the warning, intended to supply source position information.
+FORMAT and ARGS are as in `byte-compile-warn'."
+ (let ((byte-compile-form-stack (cons arg byte-compile-form-stack)))
+ (apply #'byte-compile-warn format args)))
+
(defun byte-compile-warn-obsolete (symbol)
"Warn that SYMBOL (a variable or function) is obsolete."
(when (byte-compile-warning-enabled-p 'obsolete symbol)
@@ -1357,7 +1362,7 @@ function directly; use `byte-compile-warn' or
(or funcp (get symbol 'byte-obsolete-variable))
(if funcp "function" "variable"))))
(unless (and funcp (memq symbol byte-compile-not-obsolete-funcs))
- (byte-compile-warn "%s" msg)))))
+ (byte-compile-warn-x symbol "%s" msg)))))
(defun byte-compile-report-error (error-info &optional fill)
"Report Lisp error in compilation.
@@ -1435,7 +1440,7 @@ when printing the error message."
(and (eq 'macro (car-safe f)) (setq f (cdr f)))
;; Advice wrappers have "catch all" args, so fetch the actual underlying
;; function to find the real arguments.
- (while (advice--p f) (setq f (advice--cdr f)))
+ (setq f (advice--cd*r f))
(if (eq (car-safe f) 'declared)
(byte-compile-arglist-signature (nth 1 f))
(condition-case nil
@@ -1460,7 +1465,6 @@ when printing the error message."
(t (format "%d-%d" (car signature) (cdr signature)))))
(defun byte-compile-function-warn (f nargs def)
- (byte-compile-set-symbol-position f)
(when (and (get f 'byte-obsolete-info)
(byte-compile-warning-enabled-p 'obsolete f))
(byte-compile-warn-obsolete f))
@@ -1477,19 +1481,24 @@ when printing the error message."
(if cons
(or (memq nargs (cddr cons))
(push nargs (cddr cons)))
- (push (list f byte-compile-last-position nargs)
+ (push (list f
+ (if (symbol-with-pos-p f)
+ (symbol-with-pos-pos f)
+ 1) ; Should never happen.
+ nargs)
byte-compile-unresolved-functions)))))
(defun byte-compile-emit-callargs-warn (name actual-args min-args max-args)
- (byte-compile-set-symbol-position name)
- (byte-compile-warn
- "%s called with %d argument%s, but %s %s"
- name actual-args
- (if (= 1 actual-args) "" "s")
- (if (< actual-args min-args)
- "requires"
- "accepts only")
- (byte-compile-arglist-signature-string (cons min-args max-args))))
+ (when (byte-compile-warning-enabled-p 'callargs name)
+ (byte-compile-warn-x
+ name
+ "`%s' called with %d argument%s, but %s %s"
+ name actual-args
+ (if (= 1 actual-args) "" "s")
+ (if (< actual-args min-args)
+ "requires"
+ "accepts only")
+ (byte-compile-arglist-signature-string (cons min-args max-args)))))
(defun byte-compile--check-arity-bytecode (form bytecode)
"Check that the call in FORM matches that allowed by BYTECODE."
@@ -1548,22 +1557,46 @@ extra args."
n)))
(nargs (- (length form) 2)))
(unless (= nargs nfields)
- (byte-compile-warn
+ (byte-compile-warn-x (car form)
"`%s' called with %d args to fill %d format field(s)" (car form)
nargs nfields)))))
(dolist (elt '(format message error))
(put elt 'byte-compile-format-like t))
+(defun byte-compile--suspicious-defcustom-choice (type)
+ "Say whether defcustom TYPE looks odd."
+ ;; Check whether there's anything like (choice (const :tag "foo" ;; 'bar)).
+ ;; We don't actually follow the syntax for defcustom types, but this
+ ;; should be good enough.
+ (catch 'found
+ (if (and (consp type)
+ (proper-list-p type))
+ (if (memq (car type) '(const other))
+ (when (assq 'quote type)
+ (throw 'found t))
+ (when (memq t (mapcar #'byte-compile--suspicious-defcustom-choice
+ type))
+ (throw 'found t)))
+ nil)))
+
;; Warn if a custom definition fails to specify :group, or :type.
(defun byte-compile-nogroup-warn (form)
(let ((keyword-args (cdr (cdr (cdr (cdr form)))))
(name (cadr form)))
(when (eq (car-safe name) 'quote)
- (or (not (eq (car form) 'custom-declare-variable))
- (plist-get keyword-args :type)
- (byte-compile-warn
- "defcustom for `%s' fails to specify type" (cadr name)))
+ (when (eq (car form) 'custom-declare-variable)
+ (let ((type (plist-get keyword-args :type)))
+ (cond
+ ((not type)
+ (byte-compile-warn-x (cadr name)
+ "defcustom for `%s' fails to specify type"
+ (cadr name)))
+ ((byte-compile--suspicious-defcustom-choice type)
+ (byte-compile-warn-x
+ (cadr name)
+ "defcustom for `%s' has syntactically odd type `%s'"
+ (cadr name) type)))))
(if (and (memq (car form) '(custom-declare-face custom-declare-variable))
byte-compile-current-group)
;; The group will be provided implicitly.
@@ -1571,7 +1604,7 @@ extra args."
(or (and (eq (car form) 'custom-declare-group)
(equal name ''emacs))
(plist-get keyword-args :group)
- (byte-compile-warn
+ (byte-compile-warn-x (cadr name)
"%s for `%s' fails to specify containing group"
(cdr (assq (car form)
'((custom-declare-group . defgroup)
@@ -1587,32 +1620,31 @@ extra args."
;; number of arguments.
(defun byte-compile-arglist-warn (name arglist macrop)
;; This is the first definition. See if previous calls are compatible.
- (let ((calls (assq name byte-compile-unresolved-functions))
- nums sig min max)
- (when (and calls macrop)
- (byte-compile-warn "macro `%s' defined too late" name))
- (setq byte-compile-unresolved-functions
- (delq calls byte-compile-unresolved-functions))
- (setq calls (delq t calls)) ;Ignore higher-order uses of the function.
- (when (cddr calls)
- (when (and (symbolp name)
- (eq (function-get name 'byte-optimizer)
- 'byte-compile-inline-expand))
- (byte-compile-warn "defsubst `%s' was used before it was defined"
- name))
- (setq sig (byte-compile-arglist-signature arglist)
- nums (sort (copy-sequence (cddr calls)) (function <))
- min (car nums)
- max (car (nreverse nums)))
- (when (or (< min (car sig))
- (and (cdr sig) (> max (cdr sig))))
- (byte-compile-set-symbol-position name)
- (byte-compile-warn
- "%s being defined to take %s%s, but was previously called with %s"
- name
- (byte-compile-arglist-signature-string sig)
- (if (equal sig '(1 . 1)) " arg" " args")
- (byte-compile-arglist-signature-string (cons min max))))))
+ (let ((calls (assq name byte-compile-unresolved-functions)))
+ (when calls
+ (when macrop
+ (byte-compile-warn-x name "macro `%s' defined too late" name))
+ (setq byte-compile-unresolved-functions
+ (delq calls byte-compile-unresolved-functions))
+ (let ((nums (delq t (cddr calls)))) ; Ignore higher-order uses.
+ (when nums
+ (when (and (symbolp name)
+ (eq (function-get name 'byte-optimizer)
+ 'byte-compile-inline-expand))
+ (byte-compile-warn-x
+ name "defsubst `%s' was used before it was defined" name))
+ (let ((sig (byte-compile-arglist-signature arglist))
+ (min (apply #'min nums))
+ (max (apply #'max nums)))
+ (when (or (< min (car sig))
+ (and (cdr sig) (> max (cdr sig))))
+ (byte-compile-warn-x
+ name
+ "%s being defined to take %s%s, but was previously called with %s"
+ name
+ (byte-compile-arglist-signature-string sig)
+ (if (equal sig '(1 . 1)) " arg" " args")
+ (byte-compile-arglist-signature-string (cons min max)))))))))
(let* ((old (byte-compile-fdefinition name macrop))
(initial (and macrop
(cdr (assq name
@@ -1625,8 +1657,8 @@ extra args."
(let ((sig1 (byte-compile--function-signature old))
(sig2 (byte-compile-arglist-signature arglist)))
(unless (byte-compile-arglist-signatures-congruent-p sig1 sig2)
- (byte-compile-set-symbol-position name)
- (byte-compile-warn
+ (byte-compile-warn-x
+ name
"%s %s used to take %s %s, now takes %s"
(if macrop "macro" "function")
name
@@ -1688,12 +1720,16 @@ The byte-compiler will emit a warning for documentation strings
containing lines wider than this. If `fill-column' has a larger
value, it will override this variable."
:group 'bytecomp
- :type 'integer
- :safe #'integerp
+ :type 'natnum
+ :safe #'natnump
:version "28.1")
-(defun byte-compile-docstring-length-warn (form)
- "Warn if documentation string of FORM is too wide.
+(define-obsolete-function-alias 'byte-compile-docstring-length-warn
+ 'byte-compile-docstring-style-warn "29.1")
+
+(defun byte-compile-docstring-style-warn (form)
+ "Warn if there are stylistic problems with the docstring in FORM.
+Warn if documentation string of FORM is too wide.
It is too wide if it has any lines longer than the largest of
`fill-column' and `byte-compile-docstring-max-column'."
(when (byte-compile-warning-enabled-p 'docstrings)
@@ -1702,7 +1738,8 @@ It is too wide if it has any lines longer than the largest of
(pcase (car form)
((or 'autoload 'custom-declare-variable 'defalias
'defconst 'define-abbrev-table
- 'defvar 'defvaralias)
+ 'defvar 'defvaralias
+ 'custom-declare-face)
(setq kind (nth 0 form))
(setq name (nth 1 form))
(setq docs (nth 3 form)))
@@ -1713,10 +1750,25 @@ It is too wide if it has any lines longer than the largest of
(when (and (consp name) (eq (car name) 'quote))
(setq name (cadr name)))
(setq name (if name (format " `%s' " name) ""))
- (when (and kind docs (stringp docs)
- (byte-compile--wide-docstring-p docs col))
- (byte-compile-warn "%s%sdocstring wider than %s characters"
- kind name col))))
+ (when (and kind docs (stringp docs))
+ (when (byte-compile--wide-docstring-p docs col)
+ (byte-compile-warn-x
+ name
+ "%s%sdocstring wider than %s characters"
+ kind name col))
+ ;; There's a "naked" ' character before a symbol/list, so it
+ ;; should probably be quoted with \=.
+ (when (string-match-p "\\( \"\\|[ \t]\\|^\\)'[a-z(]" docs)
+ (byte-compile-warn-x
+ name "%s%sdocstring has wrong usage of unescaped single quotes (use \\= or different quoting)"
+ kind name))
+ ;; There's a "Unicode quote" in the string -- it should probably
+ ;; be an ASCII one instead.
+ (when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)
+ (when (string-match-p "\\( \"\\|[ \t]\\|^\\)[‘’]" docs)
+ (byte-compile-warn-x
+ name "%s%sdocstring has wrong usage of \"fancy\" single quotation marks"
+ kind name))))))
form)
;; If we have compiled any calls to functions which are not known to be
@@ -1730,10 +1782,10 @@ It is too wide if it has any lines longer than the largest of
(dolist (urf byte-compile-unresolved-functions)
(let ((f (car urf)))
(when (not (memq f byte-compile-new-defuns))
- (let ((byte-compile-last-position (cadr urf)))
- (byte-compile-warn
- (if (fboundp f) "the function `%s' might not be defined at runtime." "the function `%s' is not known to be defined.")
- (car urf))))))))
+ (byte-compile-warn-x
+ f
+ (if (fboundp f) "the function `%s' might not be defined at runtime." "the function `%s' is not known to be defined.")
+ (car urf)))))))
nil)
@@ -1789,7 +1841,8 @@ It is too wide if it has any lines longer than the largest of
(warning-series-started
(and (markerp warning-series)
(eq (marker-buffer warning-series)
- (get-buffer byte-compile-log-buffer)))))
+ (get-buffer byte-compile-log-buffer))))
+ (byte-compile-form-stack byte-compile-form-stack))
(if (or (eq warning-series 'byte-compile-warning-series)
warning-series-started)
;; warning-series does come from compilation,
@@ -1976,12 +2029,51 @@ If compilation is needed, this functions returns the result of
(defvar byte-compile-level 0 ; bug#13787
"Depth of a recursive byte compilation.")
+(defun byte-write-target-file (buffer target-file)
+ "Write BUFFER into TARGET-FILE."
+ (with-current-buffer buffer
+ ;; We must disable any code conversion here.
+ (let* ((coding-system-for-write 'no-conversion)
+ ;; Write to a tempfile so that if another Emacs
+ ;; process is trying to load target-file (eg in a
+ ;; parallel bootstrap), it does not risk getting a
+ ;; half-finished file. (Bug#4196)
+ (tempfile
+ (make-temp-file (when (file-writable-p target-file)
+ (expand-file-name target-file))))
+ (default-modes (default-file-modes))
+ (temp-modes (logand default-modes #o600))
+ (desired-modes (logand default-modes #o666))
+ (kill-emacs-hook
+ (cons (lambda () (ignore-errors
+ (delete-file tempfile)))
+ kill-emacs-hook)))
+ (unless (= temp-modes desired-modes)
+ (set-file-modes tempfile desired-modes 'nofollow))
+ (write-region (point-min) (point-max) tempfile nil 1)
+ ;; This has the intentional side effect that any
+ ;; hard-links to target-file continue to
+ ;; point to the old file (this makes it possible
+ ;; for installed files to share disk space with
+ ;; the build tree, without causing problems when
+ ;; emacs-lisp files in the build tree are
+ ;; recompiled). Previously this was accomplished by
+ ;; deleting target-file before writing it.
+ (if byte-native-compiling
+ ;; Defer elc final renaming.
+ (setf byte-to-native-output-buffer-file
+ (cons tempfile target-file))
+ (rename-file tempfile target-file t)))))
+
;;;###autoload
(defun byte-compile-file (filename &optional load)
"Compile a file of Lisp code named FILENAME into a file of byte code.
The output file's name is generated by passing FILENAME to the
function `byte-compile-dest-file' (which see).
The value is non-nil if there were no errors, nil if errors.
+If the file sets the file variable `no-byte-compile', it is not
+compiled, any existing output file is removed, and the return
+value is `no-byte-compile'.
See also `emacs-lisp-byte-compile-and-load'."
(declare (advertised-calling-convention (filename) "28.1"))
@@ -2107,38 +2199,11 @@ See also `emacs-lisp-byte-compile-and-load'."
;; Need to expand in case TARGET-FILE doesn't
;; include a directory (Bug#45287).
(expand-file-name target-file))))
- ;; We must disable any code conversion here.
- (let* ((coding-system-for-write 'no-conversion)
- ;; Write to a tempfile so that if another Emacs
- ;; process is trying to load target-file (eg in a
- ;; parallel bootstrap), it does not risk getting a
- ;; half-finished file. (Bug#4196)
- (tempfile
- (make-temp-file (when (file-writable-p target-file)
- (expand-file-name target-file))))
- (default-modes (default-file-modes))
- (temp-modes (logand default-modes #o600))
- (desired-modes (logand default-modes #o666))
- (kill-emacs-hook
- (cons (lambda () (ignore-errors
- (delete-file tempfile)))
- kill-emacs-hook)))
- (unless (= temp-modes desired-modes)
- (set-file-modes tempfile desired-modes 'nofollow))
- (write-region (point-min) (point-max) tempfile nil 1)
- ;; This has the intentional side effect that any
- ;; hard-links to target-file continue to
- ;; point to the old file (this makes it possible
- ;; for installed files to share disk space with
- ;; the build tree, without causing problems when
- ;; emacs-lisp files in the build tree are
- ;; recompiled). Previously this was accomplished by
- ;; deleting target-file before writing it.
- (if byte-native-compiling
- ;; Defer elc final renaming.
- (setf byte-to-native-output-file
- (cons tempfile target-file))
- (rename-file tempfile target-file t)))
+ (if byte-native-compiling
+ ;; Defer elc production.
+ (setf byte-to-native-output-buffer-file
+ (cons (current-buffer) target-file))
+ (byte-write-target-file (current-buffer) target-file))
(or noninteractive
byte-native-compiling
(message "Wrote %s" target-file)))
@@ -2159,7 +2224,8 @@ See also `emacs-lisp-byte-compile-and-load'."
"Cannot overwrite file"
"Directory not writable or nonexistent")
target-file))))))
- (kill-buffer (current-buffer)))
+ (unless byte-native-compiling
+ (kill-buffer (current-buffer))))
(if (and byte-compile-generate-call-tree
(or (eq t byte-compile-generate-call-tree)
(y-or-n-p (format "Report call tree for %s? "
@@ -2189,19 +2255,20 @@ With argument ARG, insert value in current buffer after the form."
(save-excursion
(end-of-defun)
(beginning-of-defun)
- (let* ((byte-compile-current-file (current-buffer))
+ (let* ((print-symbols-bare t) ; For the final `message'.
+ (byte-compile-current-file (current-buffer))
(byte-compile-current-buffer (current-buffer))
- (byte-compile-read-position (point))
- (byte-compile-last-position byte-compile-read-position)
+ (start-read-position (point))
(byte-compile-last-warned-form 'nothing)
+ (symbols-with-pos-enabled t)
(value (eval
- (let ((read-with-symbol-positions (current-buffer))
- (read-symbol-positions-list nil))
- (displaying-byte-compile-warnings
- (byte-compile-sexp
+ (displaying-byte-compile-warnings
+ (byte-compile-sexp
+ (let ((form (read-positioning-symbols (current-buffer))))
+ (push form byte-compile-form-stack)
(eval-sexp-add-defvars
- (read (current-buffer))
- byte-compile-read-position))))
+ form
+ start-read-position))))
lexical-binding)))
(cond (arg
(message "Compiling from buffer... done.")
@@ -2211,13 +2278,12 @@ With argument ARG, insert value in current buffer after the form."
(defun byte-compile-from-buffer (inbuffer)
(let ((byte-compile-current-buffer inbuffer)
- (byte-compile-read-position nil)
- (byte-compile-last-position nil)
;; Prevent truncation of flonums and lists as we read and print them
(float-output-format nil)
(case-fold-search nil)
(print-length nil)
(print-level nil)
+ (print-symbols-bare t)
;; Prevent edebug from interfering when we compile
;; and put the output into a file.
;; (edebug-all-defs nil)
@@ -2230,12 +2296,9 @@ With argument ARG, insert value in current buffer after the form."
(byte-compile-depth 0)
(byte-compile-maxdepth 0)
(byte-compile-output nil)
- ;; This allows us to get the positions of symbols read.
- (read-with-symbol-positions inbuffer)
- (read-symbol-positions-list nil)
;; #### This is bound in b-c-close-variables.
;; (byte-compile-warnings byte-compile-warnings)
- )
+ (symbols-with-pos-enabled t))
(byte-compile-close-variables
(with-current-buffer
(setq byte-compile--outbuffer
@@ -2281,18 +2344,17 @@ With argument ARG, insert value in current buffer after the form."
(= (following-char) ?\;))
(forward-line 1))
(not (eobp)))
- (setq byte-compile-read-position (point)
- byte-compile-last-position byte-compile-read-position)
(let* ((lread--unescaped-character-literals nil)
- (form (read inbuffer))
+ ;; Don't bind `load-read-function' to
+ ;; `read-positioning-symbols' here. Calls to `read'
+ ;; at a lower level must not get symbols with
+ ;; position.
+ (form (read-positioning-symbols inbuffer))
(warning (byte-run--unescaped-character-literals-warning)))
- (when warning (byte-compile-warn "%s" warning))
+ (when warning (byte-compile-warn-x form "%s" warning))
(byte-compile-toplevel-file-form form)))
;; Compile pending forms at end of file.
(byte-compile-flush-pending)
- ;; Make warnings about unresolved functions
- ;; give the end of the file as their position.
- (setq byte-compile-last-position (point-max))
(byte-compile-warn-about-unresolved-functions)))
byte-compile--outbuffer)))
@@ -2350,13 +2412,13 @@ Call from the source buffer."
;; Spill output for the native compiler here
(push (make-byte-to-native-top-level :form form :lexical lexical-binding)
byte-to-native-top-level-forms))
- (let ((print-escape-newlines t)
+ (let ((print-symbols-bare t) ; Possibly redundant binding.
+ (print-escape-newlines t)
(print-length nil)
(print-level nil)
(print-quoted t)
(print-gensym t)
- (print-circle ; Handle circular data structures.
- (not byte-compile-disable-print-circle)))
+ (print-circle t)) ; Handle circular data structures.
(if (and (memq (car-safe form) '(defvar defvaralias defconst
autoload custom-declare-variable))
(stringp (nth 3 form)))
@@ -2385,8 +2447,8 @@ list that represents a doc string reference.
;; in the input buffer (now current), not in the output buffer.
(let ((dynamic-docstrings byte-compile-dynamic-docstrings))
(with-current-buffer byte-compile--outbuffer
- (let (position)
-
+ (let (position
+ (print-symbols-bare t)) ; Possibly redundant binding.
;; Insert the doc string, and make it a comment with #@LENGTH.
(and (>= (nth 1 info) 0)
dynamic-docstrings
@@ -2414,8 +2476,7 @@ list that represents a doc string reference.
(print-level nil)
(print-quoted t)
(print-gensym t)
- (print-circle ; Handle circular data structures.
- (not byte-compile-disable-print-circle)))
+ (print-circle t)) ; Handle circular data structures.
(if preface
(progn
;; FIXME: We don't handle uninterned names correctly.
@@ -2468,13 +2529,12 @@ list that represents a doc string reference.
(defun byte-compile-keep-pending (form &optional handler)
(if (memq byte-optimize '(t source))
(setq form (byte-optimize-one-form form t)))
+ ;; To avoid consing up monstrously large forms at load time, we split
+ ;; the output regularly.
+ (when (nthcdr 300 byte-compile-output)
+ (byte-compile-flush-pending))
(if handler
(let ((byte-compile--for-effect t))
- ;; To avoid consing up monstrously large forms at load time, we split
- ;; the output regularly.
- (and (memq (car-safe form) '(fset defalias))
- (nthcdr 300 byte-compile-output)
- (byte-compile-flush-pending))
(funcall handler form)
(if byte-compile--for-effect
(byte-compile-discard)))
@@ -2496,24 +2556,28 @@ list that represents a doc string reference.
byte-compile-jump-tables nil))))
(defun byte-compile-preprocess (form &optional _for-effect)
- (setq form (macroexpand-all form byte-compile-macro-environment))
+ (let ((print-symbols-bare t)) ; Possibly redundant binding.
+ (setq form (macroexpand-all form byte-compile-macro-environment)))
;; FIXME: We should run byte-optimize-form here, but it currently does not
;; recurse through all the code, so we'd have to fix this first.
;; Maybe a good fix would be to merge byte-optimize-form into
;; macroexpand-all.
;; (if (memq byte-optimize '(t source))
;; (setq form (byte-optimize-form form for-effect)))
- (cond
- (lexical-binding (cconv-closure-convert form))
- (t form)))
+ (cconv-closure-convert form))
;; byte-hunk-handlers cannot call this!
(defun byte-compile-toplevel-file-form (top-level-form)
- (byte-compile-recurse-toplevel
- top-level-form
- (lambda (form)
- (let ((byte-compile-current-form nil)) ; close over this for warnings.
- (byte-compile-file-form (byte-compile-preprocess form t))))))
+ ;; (let ((byte-compile-form-stack
+ ;; (cons top-level-form byte-compile-form-stack)))
+ (push top-level-form byte-compile-form-stack)
+ (prog1
+ (byte-compile-recurse-toplevel
+ top-level-form
+ (lambda (form)
+ (let ((byte-compile-current-form nil)) ; close over this for warnings.
+ (byte-compile-file-form (byte-compile-preprocess form t)))))
+ (pop byte-compile-form-stack)))
;; byte-hunk-handlers can call this.
(defun byte-compile-file-form (form)
@@ -2562,8 +2626,9 @@ list that represents a doc string reference.
(delq (assq funsym byte-compile-unresolved-functions)
byte-compile-unresolved-functions)))))
(if (stringp (nth 3 form))
- (prog1 form
- (byte-compile-docstring-length-warn form))
+ (prog1
+ form
+ (byte-compile-docstring-style-warn form))
;; No doc string, so we can compile this as a normal form.
(byte-compile-keep-pending form 'byte-compile-normal-call)))
@@ -2574,7 +2639,8 @@ list that represents a doc string reference.
(when (and (symbolp sym)
(not (string-match "[-*/:$]" (symbol-name sym)))
(byte-compile-warning-enabled-p 'lexical sym))
- (byte-compile-warn "global/dynamic var `%s' lacks a prefix" sym)))
+ (byte-compile-warn-x
+ sym "global/dynamic var `%s' lacks a prefix" sym)))
(defun byte-compile--declare-var (sym)
(byte-compile--check-prefixed-var sym)
@@ -2582,7 +2648,7 @@ list that represents a doc string reference.
(setq byte-compile-lexical-variables
(delq sym byte-compile-lexical-variables))
(when (byte-compile-warning-enabled-p 'lexical sym)
- (byte-compile-warn "Variable `%S' declared after its first use" sym)))
+ (byte-compile-warn-x sym "Variable `%S' declared after its first use" sym)))
(push sym byte-compile-bound-variables)
(push sym byte-compile--seen-defvars))
@@ -2594,11 +2660,11 @@ list that represents a doc string reference.
(if (and (null (cddr form)) ;No `value' provided.
(eq (car form) 'defvar)) ;Just a declaration.
nil
- (byte-compile-docstring-length-warn form)
- (cond ((consp (nth 2 form))
- (setq form (copy-sequence form))
- (setcar (cdr (cdr form))
- (byte-compile-top-level (nth 2 form) nil 'file))))
+ (byte-compile-docstring-style-warn form)
+ (setq form (copy-sequence form))
+ (when (consp (nth 2 form))
+ (setcar (cdr (cdr form))
+ (byte-compile-top-level (nth 2 form) nil 'file)))
form))
(put 'define-abbrev-table 'byte-hunk-handler
@@ -2616,22 +2682,25 @@ list that represents a doc string reference.
(`(defvaralias ,_ ',newname . ,_)
(when (memq newname byte-compile-bound-variables)
(if (byte-compile-warning-enabled-p 'suspicious)
- (byte-compile-warn
+ (byte-compile-warn-x
+ newname
"Alias for `%S' should be declared before its referent" newname)))))
- (byte-compile-docstring-length-warn form)
+ (byte-compile-docstring-style-warn form)
(byte-compile-keep-pending form))
(put 'custom-declare-variable 'byte-hunk-handler
- 'byte-compile-file-form-custom-declare-variable)
-(defun byte-compile-file-form-custom-declare-variable (form)
- (when (byte-compile-warning-enabled-p 'callargs)
- (byte-compile-nogroup-warn form))
- (byte-compile-file-form-defvar-function form))
+ 'byte-compile-file-form-defvar-function)
+
+(put 'custom-declare-face 'byte-hunk-handler
+ 'byte-compile-docstring-style-warn)
(put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
(defun byte-compile-file-form-require (form)
- (let ((args (mapcar 'eval (cdr form)))
- hist-new prov-cons)
+ (let* ((args (mapcar 'eval (cdr form)))
+ ;; The following is for the byte-compile-warn in
+ ;; `do-after-load-evaluation' (in subr.el).
+ (byte-compile-form-stack (cons (car args) byte-compile-form-stack))
+ hist-new prov-cons)
(apply 'require args)
;; Record the functions defined by the require in `byte-compile-new-defuns'.
@@ -2675,7 +2744,8 @@ list that represents a doc string reference.
(put 'make-obsolete 'byte-hunk-handler 'byte-compile-file-form-make-obsolete)
(defun byte-compile-file-form-make-obsolete (form)
(prog1 (byte-compile-keep-pending form)
- (apply 'make-obsolete (mapcar 'eval (cdr form)))))
+ (apply 'make-obsolete
+ (mapcar 'eval (cdr form)))))
(defun byte-compile-file-form-defmumble (name macro arglist body rest)
"Process a `defalias' for NAME.
@@ -2690,23 +2760,23 @@ not to take responsibility for the actual compilation of the code."
'byte-compile-macro-environment))
(this-one (assq name (symbol-value this-kind)))
(that-one (assq name (symbol-value that-kind)))
+ (bare-name (bare-symbol name))
(byte-compile-current-form name)) ; For warnings.
- (byte-compile-set-symbol-position name)
- (push name byte-compile-new-defuns)
+ (push bare-name byte-compile-new-defuns)
;; When a function or macro is defined, add it to the call tree so that
;; we can tell when functions are not used.
(if byte-compile-generate-call-tree
- (or (assq name byte-compile-call-tree)
+ (or (assq bare-name byte-compile-call-tree)
(setq byte-compile-call-tree
- (cons (list name nil nil) byte-compile-call-tree))))
+ (cons (list bare-name nil nil) byte-compile-call-tree))))
(if (byte-compile-warning-enabled-p 'redefine name)
(byte-compile-arglist-warn name arglist macro))
(if byte-compile-verbose
(message "Compiling %s... (%s)"
- (or byte-compile-current-file "") name))
+ (or byte-compile-current-file "") bare-name))
(cond ((not (or macro (listp body)))
;; We do not know positively if the definition is a macro
;; or a function, so we shouldn't emit warnings.
@@ -2715,29 +2785,34 @@ not to take responsibility for the actual compilation of the code."
(that-one
(if (and (byte-compile-warning-enabled-p 'redefine name)
;; Don't warn when compiling the stubs in byte-run...
- (not (assq name byte-compile-initial-macro-environment)))
- (byte-compile-warn
+ (not (assq bare-name byte-compile-initial-macro-environment)))
+ (byte-compile-warn-x
+ name
"`%s' defined multiple times, as both function and macro"
- name))
+ bare-name))
(setcdr that-one nil))
(this-one
(when (and (byte-compile-warning-enabled-p 'redefine name)
;; Hack: Don't warn when compiling the magic internal
;; byte-compiler macros in byte-run.el...
- (not (assq name byte-compile-initial-macro-environment)))
- (byte-compile-warn "%s `%s' defined multiple times in this file"
- (if macro "macro" "function")
- name)))
- ((eq (car-safe (symbol-function name))
+ (not (assq bare-name byte-compile-initial-macro-environment)))
+ (byte-compile-warn-x
+ name
+ "%s `%s' defined multiple times in this file"
+ (if macro "macro" "function")
+ bare-name)))
+ ((eq (car-safe (symbol-function bare-name))
(if macro 'lambda 'macro))
- (when (byte-compile-warning-enabled-p 'redefine name)
- (byte-compile-warn "%s `%s' being redefined as a %s"
- (if macro "function" "macro")
- name
- (if macro "macro" "function")))
+ (when (byte-compile-warning-enabled-p 'redefine bare-name)
+ (byte-compile-warn-x
+ name
+ "%s `%s' being redefined as a %s"
+ (if macro "function" "macro")
+ bare-name
+ (if macro "macro" "function")))
;; Shadow existing definition.
(set this-kind
- (cons (cons name nil)
+ (cons (cons bare-name nil)
(symbol-value this-kind))))
)
@@ -2746,10 +2821,8 @@ not to take responsibility for the actual compilation of the code."
(symbolp (car-safe (cdr-safe body)))
(car-safe (cdr-safe body))
(stringp (car-safe (cdr-safe (cdr-safe body)))))
- ;; FIXME: We've done that already just above, so this looks wrong!
- ;;(byte-compile-set-symbol-position name)
- (byte-compile-warn "probable `\"' without `\\' in doc string of %s"
- name))
+ (byte-compile-warn-x
+ name "probable `\"' without `\\' in doc string of %s" bare-name))
(if (not (listp body))
;; The precise definition requires evaluation to find out, so it
@@ -2757,7 +2830,7 @@ not to take responsibility for the actual compilation of the code."
;; For a macro, that means we can't use that macro in the same file.
(progn
(unless macro
- (push (cons name (if (listp arglist) `(declared ,arglist) t))
+ (push (cons bare-name (if (listp arglist) `(declared ,arglist) t))
byte-compile-function-environment))
;; Tell the caller that we didn't compile it yet.
nil)
@@ -2767,10 +2840,10 @@ not to take responsibility for the actual compilation of the code."
;; A definition in b-c-initial-m-e should always take precedence
;; during compilation, so don't let it be redefined. (Bug#8647)
(or (and macro
- (assq name byte-compile-initial-macro-environment))
+ (assq bare-name byte-compile-initial-macro-environment))
(setcdr this-one code))
(set this-kind
- (cons (cons name code)
+ (cons (cons bare-name code)
(symbol-value this-kind))))
(if rest
@@ -2786,18 +2859,19 @@ not to take responsibility for the actual compilation of the code."
(if (not (stringp (documentation code t))) -1 4)))
(when byte-native-compiling
;; Spill output for the native compiler here.
- (push (if macro
- (make-byte-to-native-top-level
- :form `(defalias ',name '(macro . ,code) nil)
- :lexical lexical-binding)
- (make-byte-to-native-func-def :name name
- :byte-func code))
- byte-to-native-top-level-forms))
+ (push
+ (if macro
+ (make-byte-to-native-top-level
+ :form `(defalias ',name '(macro . ,code) nil)
+ :lexical lexical-binding)
+ (make-byte-to-native-func-def :name name
+ :byte-func code))
+ byte-to-native-top-level-forms))
;; Output the form by hand, that's much simpler than having
;; b-c-output-file-form analyze the defalias.
(byte-compile-output-docform
"\n(defalias '"
- name
+ bare-name
(if macro `(" '(macro . #[" ,index "])") `(" #[" ,index "]"))
(append code nil) ; Turn byte-code-function-p into list.
(and (atom code) byte-compile-dynamic
@@ -2856,6 +2930,7 @@ FUN should be either a `lambda' value or a `closure' value."
(push (pop body) preamble))
(when (eq (car-safe (car body)) 'interactive)
(push (pop body) preamble))
+ (setq preamble (nreverse preamble))
;; Turn the function's closed vars (if any) into local let bindings.
(dolist (binding env)
(cond
@@ -2880,37 +2955,38 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(macro (eq (car-safe fun) 'macro)))
(if macro
(setq fun (cdr fun)))
- (cond
- ;; Up until Emacs-24.1, byte-compile silently did nothing when asked to
- ;; compile something invalid. So let's tune down the complaint from an
- ;; error to a simple message for the known case where signaling an error
- ;; causes problems.
- ((byte-code-function-p fun)
- (message "Function %s is already compiled"
- (if (symbolp form) form "provided"))
- fun)
- (t
- (let (final-eval)
- (when (or (symbolp form) (eq (car-safe fun) 'closure))
- ;; `fun' is a function *value*, so try to recover its corresponding
- ;; source code.
- (setq lexical-binding (eq (car fun) 'closure))
- (setq fun (byte-compile--reify-function fun))
- (setq final-eval t))
- ;; Expand macros.
- (setq fun (byte-compile-preprocess fun))
- (setq fun (byte-compile-top-level fun nil 'eval))
- (if (symbolp form)
- ;; byte-compile-top-level returns an *expression* equivalent to the
- ;; `fun' expression, so we need to evaluate it, tho normally
- ;; this is not needed because the expression is just a constant
- ;; byte-code object, which is self-evaluating.
- (setq fun (eval fun t)))
- (if final-eval
- (setq fun (eval fun t)))
- (if macro (push 'macro fun))
- (if (symbolp form) (fset form fun))
- fun)))))))
+ (prog1
+ (cond
+ ;; Up until Emacs-24.1, byte-compile silently did nothing when asked to
+ ;; compile something invalid. So let's tune down the complaint from an
+ ;; error to a simple message for the known case where signaling an error
+ ;; causes problems.
+ ((byte-code-function-p fun)
+ (message "Function %s is already compiled"
+ (if (symbolp form) form "provided"))
+ fun)
+ (t
+ (let (final-eval)
+ (when (or (symbolp form) (eq (car-safe fun) 'closure))
+ ;; `fun' is a function *value*, so try to recover its corresponding
+ ;; source code.
+ (setq lexical-binding (eq (car fun) 'closure))
+ (setq fun (byte-compile--reify-function fun))
+ (setq final-eval t))
+ ;; Expand macros.
+ (setq fun (byte-compile-preprocess fun))
+ (setq fun (byte-compile-top-level fun nil 'eval))
+ (if (symbolp form)
+ ;; byte-compile-top-level returns an *expression* equivalent to the
+ ;; `fun' expression, so we need to evaluate it, tho normally
+ ;; this is not needed because the expression is just a constant
+ ;; byte-code object, which is self-evaluating.
+ (setq fun (eval fun t)))
+ (if final-eval
+ (setq fun (eval fun t)))
+ (if macro (push 'macro fun))
+ (if (symbolp form) (fset form fun))
+ fun))))))))
(defun byte-compile-sexp (sexp)
"Compile and return SEXP."
@@ -2923,8 +2999,6 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(let (vars)
(while list
(let ((arg (car list)))
- (when (symbolp arg)
- (byte-compile-set-symbol-position arg))
(cond ((or (not (symbolp arg))
(macroexp--const-symbol-p arg t))
(error "Invalid lambda variable %s" arg))
@@ -2941,7 +3015,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
((and (memq arg vars)
;; Allow repetitions for unused args.
(not (string-match "\\`_" (symbol-name arg))))
- (byte-compile-warn "repeated variable %s in lambda-list" arg))
+ (byte-compile-warn-x
+ arg "repeated variable %s in lambda-list" arg))
(t
(push arg vars))))
(setq list (cdr list)))))
@@ -2984,7 +3059,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(defun byte-compile--warn-lexical-dynamic (var context)
(when (byte-compile-warning-enabled-p 'lexical-dynamic var)
- (byte-compile-warn
+ (byte-compile-warn-x
+ var
"`%s' lexically bound in %s here but declared dynamic in: %s"
var context
(mapconcat #'identity
@@ -2996,20 +3072,16 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(defun byte-compile-lambda (fun &optional add-lambda reserved-csts)
"Byte-compile a lambda-expression and return a valid function.
The value is usually a compiled function but may be the original
-lambda-expression.
-When ADD-LAMBDA is non-nil, the symbol `lambda' is added as head
-of the list FUN and `byte-compile-set-symbol-position' is not called.
-Use this feature to avoid calling `byte-compile-set-symbol-position'
-for symbols generated by the byte compiler itself."
+lambda-expression."
(if add-lambda
(setq fun (cons 'lambda fun))
(unless (eq 'lambda (car-safe fun))
- (error "Not a lambda list: %S" fun))
- (byte-compile-set-symbol-position 'lambda))
- (byte-compile-docstring-length-warn fun)
+ (error "Not a lambda list: %S" fun)))
+ (byte-compile-docstring-style-warn fun)
(byte-compile-check-lambda-list (nth 1 fun))
(let* ((arglist (nth 1 fun))
- (arglistvars (byte-compile-arglist-vars arglist))
+ (arglistvars (byte-run-strip-symbol-positions
+ (byte-compile-arglist-vars arglist)))
(byte-compile-bound-variables
(append (if (not lexical-binding) arglistvars)
byte-compile-bound-variables))
@@ -3028,7 +3100,6 @@ for symbols generated by the byte compiler itself."
(byte-compile--warn-lexical-dynamic var 'lambda))))
;; Process the interactive spec.
(when int
- (byte-compile-set-symbol-position 'interactive)
;; Skip (interactive) if it is in front (the most usual location).
(if (eq int (car body))
(setq body (cdr body)))
@@ -3036,8 +3107,8 @@ for symbols generated by the byte compiler itself."
;; Check that the bit after the `interactive' spec is
;; just a list of symbols (i.e., modes).
(unless (seq-every-p #'symbolp (cdr (cdr int)))
- (byte-compile-warn "malformed interactive specc: %s"
- (prin1-to-string int)))
+ (byte-compile-warn-x int "malformed interactive specc: %s"
+ int))
(setq command-modes (cdr (cdr int)))
;; If the interactive spec is a call to `list', don't
;; compile it, because `call-interactively' looks at the
@@ -3049,16 +3120,17 @@ for symbols generated by the byte compiler itself."
(while (consp (cdr form))
(setq form (cdr form)))
(setq form (car form)))
- (when (or (not (eq (car-safe form) 'list))
- ;; For code using lexical-binding, form is not
- ;; valid lisp, but rather an intermediate form
- ;; which may include "calls" to
- ;; internal-make-closure (Bug#29988).
- lexical-binding)
- (setq int `(interactive ,newform)))))
+ (if (or (not (eq (car-safe form) 'list))
+ ;; For code using lexical-binding, form is not
+ ;; valid lisp, but rather an intermediate form
+ ;; which may include "calls" to
+ ;; internal-make-closure (Bug#29988).
+ lexical-binding)
+ (setq int `(,(car int) ,newform))
+ (setq int (byte-run-strip-symbol-positions int))))) ; for compile-defun.
((cdr int) ; Invalid (interactive . something).
- (byte-compile-warn "malformed interactive spec: %s"
- (prin1-to-string int)))))
+ (byte-compile-warn-x int "malformed interactive spec: %s"
+ int))))
;; Process the body.
(let ((compiled
(byte-compile-top-level (cons 'progn body) nil 'lambda
@@ -3069,14 +3141,15 @@ for symbols generated by the byte compiler itself."
(and lexical-binding
(byte-compile-make-lambda-lexenv
arglistvars))
- reserved-csts)))
+ reserved-csts))
+ (bare-arglist (byte-run-strip-symbol-positions arglist))) ; for compile-defun.
;; Build the actual byte-coded function.
(cl-assert (eq 'byte-code (car-safe compiled)))
(let ((out
(apply #'make-byte-code
(if lexical-binding
(byte-compile-make-args-desc arglist)
- arglist)
+ bare-arglist)
(append
;; byte-string, constants-vector, stack depth
(cdr compiled)
@@ -3084,7 +3157,7 @@ for symbols generated by the byte compiler itself."
(cond ((and lexical-binding arglist)
;; byte-compile-make-args-desc lost the args's names,
;; so preserve them in the docstring.
- (list (help-add-fundoc-usage doc arglist)))
+ (list (help-add-fundoc-usage doc bare-arglist)))
((or doc int)
(list doc)))
;; optionally, the interactive spec (and the modes the
@@ -3289,7 +3362,8 @@ for symbols generated by the byte compiler itself."
(setq byte-compile-noruntime-functions
(delq fn byte-compile-noruntime-functions))
;; Delegate the rest to the normal macro definition.
- (macroexpand `(declare-function ,fn ,file ,@args)))
+ (let ((print-symbols-bare t)) ; Possibly redundant binding.
+ (macroexpand `(declare-function ,fn ,file ,@args))))
;; This is the recursive entry point for compiling each subform of an
@@ -3307,18 +3381,14 @@ for symbols generated by the byte compiler itself."
;;
(defun byte-compile-form (form &optional for-effect)
(let ((byte-compile--for-effect for-effect))
+ (push form byte-compile-form-stack)
(cond
((not (consp form))
(cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
- (when (symbolp form)
- (byte-compile-set-symbol-position form))
(byte-compile-constant form))
((and byte-compile--for-effect byte-compile-delete-errors)
- (when (symbolp form)
- (byte-compile-set-symbol-position form))
(setq byte-compile--for-effect nil))
- (t
- (byte-compile-variable-ref form))))
+ (t (byte-compile-variable-ref form))))
((symbolp (car form))
(let* ((fn (car form))
(handler (get fn 'byte-compile))
@@ -3341,20 +3411,20 @@ for symbols generated by the byte compiler itself."
(byte-compile-check-variable (cadr hook) nil))))
(when (and (byte-compile-warning-enabled-p 'suspicious)
(macroexp--const-symbol-p fn))
- (byte-compile-warn "`%s' called as a function" fn))
+ (byte-compile-warn-x fn "`%s' called as a function" fn))
(when (and (byte-compile-warning-enabled-p 'interactive-only fn)
interactive-only)
- (byte-compile-warn "`%s' is for interactive use only%s"
- fn
- (cond ((stringp interactive-only)
- (format "; %s"
- (substitute-command-keys
- interactive-only)))
- ((and (symbolp 'interactive-only)
- (not (eq interactive-only t)))
- (format-message "; use `%s' instead."
- interactive-only))
- (t "."))))
+ (byte-compile-warn-x fn "`%s' is for interactive use only%s"
+ fn
+ (cond ((stringp interactive-only)
+ (format "; %s"
+ (substitute-command-keys
+ interactive-only)))
+ ((and (symbolp 'interactive-only)
+ (not (eq interactive-only t)))
+ (format-message "; use `%s' instead."
+ interactive-only))
+ (t "."))))
(if (eq (car-safe (symbol-function (car form))) 'macro)
(byte-compile-report-error
(format "`%s' defined after use in %S (missing `require' of a library file?)"
@@ -3379,7 +3449,8 @@ for symbols generated by the byte compiler itself."
(setq byte-compile--for-effect nil))
((byte-compile-normal-call form)))
(if byte-compile--for-effect
- (byte-compile-discard))))
+ (byte-compile-discard))
+ (pop byte-compile-form-stack)))
(defun byte-compile-normal-call (form)
(when (and (symbolp (car form))
@@ -3393,8 +3464,8 @@ for symbols generated by the byte compiler itself."
(byte-compile-annotate-call-tree form))
(when (and byte-compile--for-effect (eq (car form) 'mapcar)
(byte-compile-warning-enabled-p 'mapcar 'mapcar))
- (byte-compile-set-symbol-position 'mapcar)
- (byte-compile-warn
+ (byte-compile-warn-x
+ (car form)
"`mapcar' called for effect; use `mapc' or `dolist' instead"))
(byte-compile-push-constant (car form))
(mapc 'byte-compile-form (cdr form)) ; wasteful, but faster.
@@ -3525,16 +3596,16 @@ for symbols generated by the byte compiler itself."
(defun byte-compile-check-variable (var access-type)
"Do various error checks before a use of the variable VAR."
- (when (symbolp var)
- (byte-compile-set-symbol-position var))
(cond ((or (not (symbolp var)) (macroexp--const-symbol-p var))
(when (byte-compile-warning-enabled-p 'constants
(and (symbolp var) var))
- (byte-compile-warn (if (eq access-type 'let-bind)
- "attempt to let-bind %s `%s'"
- "variable reference to %s `%s'")
- (if (symbolp var) "constant" "nonvariable")
- (prin1-to-string var))))
+ (byte-compile-warn-x
+ var
+ (if (eq access-type 'let-bind)
+ "attempt to let-bind %s `%s'"
+ "variable reference to %s `%s'")
+ (if (symbolp var) "constant" "nonvariable")
+ var)))
((let ((od (get var 'byte-obsolete-variable)))
(and od
(not (memq var byte-compile-not-obsolete-vars))
@@ -3559,9 +3630,10 @@ for symbols generated by the byte compiler itself."
(push var byte-compile-bound-variables)
(byte-compile-dynamic-variable-op 'byte-varbind var))
-(defun byte-compile-free-vars-warn (var &optional assignment)
+(defun byte-compile-free-vars-warn (arg var &optional assignment)
"Warn if symbol VAR refers to a free variable.
VAR must not be lexically bound.
+ARG is a position argument, used by byte-compile-warn-x.
If optional argument ASSIGNMENT is non-nil, this is treated as an
assignment (i.e. `setq')."
(unless (or (not (byte-compile-warning-enabled-p 'free-vars var))
@@ -3573,9 +3645,9 @@ assignment (i.e. `setq')."
(let* ((varname (prin1-to-string var))
(desc (if assignment "assignment" "reference"))
(suggestions (help-uni-confusable-suggestions varname)))
- (byte-compile-warn "%s to free variable `%s'%s"
- desc varname
- (if suggestions (concat "\n " suggestions) "")))
+ (byte-compile-warn-x arg "%s to free variable `%s'%s"
+ desc var
+ (if suggestions (concat "\n " suggestions) "")))
(push var (if assignment
byte-compile-free-assignments
byte-compile-free-references))))
@@ -3588,7 +3660,7 @@ assignment (i.e. `setq')."
;; VAR is lexically bound
(byte-compile-stack-ref (cdr lex-binding))
;; VAR is dynamically bound
- (byte-compile-free-vars-warn var)
+ (byte-compile-free-vars-warn var var)
(byte-compile-dynamic-variable-op 'byte-varref var))))
(defun byte-compile-variable-set (var)
@@ -3599,7 +3671,7 @@ assignment (i.e. `setq')."
;; VAR is lexically bound.
(byte-compile-stack-set (cdr lex-binding))
;; VAR is dynamically bound.
- (byte-compile-free-vars-warn var t)
+ (byte-compile-free-vars-warn var var t)
(byte-compile-dynamic-variable-op 'byte-varset var))))
(defmacro byte-compile-get-constant (const)
@@ -3624,9 +3696,9 @@ assignment (i.e. `setq')."
;; Use this for a constant that is not the value of its containing form.
;; This ignores byte-compile--for-effect.
(defun byte-compile-push-constant (const)
- (when (symbolp const)
- (byte-compile-set-symbol-position const))
- (byte-compile-out 'byte-constant (byte-compile-get-constant const)))
+ (byte-compile-out
+ 'byte-constant
+ (byte-compile-get-constant const)))
;; Compile those primitive ordinary functions
;; which have special byte codes just for speed.
@@ -3778,12 +3850,13 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\""
(defun byte-compile-subr-wrong-args (form n)
- (byte-compile-set-symbol-position (car form))
- (byte-compile-warn "`%s' called with %d arg%s, but requires %s"
- (car form) (length (cdr form))
- (if (= 1 (length (cdr form))) "" "s") n)
- ;; Get run-time wrong-number-of-args error.
- (byte-compile-normal-call form))
+ (when (byte-compile-warning-enabled-p 'callargs (car form))
+ (byte-compile-warn-x (car form)
+ "`%s' called with %d arg%s, but requires %s"
+ (car form) (length (cdr form))
+ (if (= 1 (length (cdr form))) "" "s") n)
+ ;; Get run-time wrong-number-of-args error.
+ (byte-compile-normal-call form)))
(defun byte-compile-no-args (form)
(if (not (= (length form) 1))
@@ -3892,7 +3965,9 @@ discarding."
(byte-defop-compiler-1 internal-get-closed-var byte-compile-get-closed-var)
(defun byte-compile-make-closure (form)
- "Byte-compile the special `internal-make-closure' form."
+ "Byte-compile the special `internal-make-closure' form.
+
+This function is never called when `lexical-binding' is nil."
(if byte-compile--for-effect (setq byte-compile--for-effect nil)
(let* ((vars (nth 1 form))
(env (nth 2 form))
@@ -3904,7 +3979,7 @@ discarding."
docstring-exp)) ;Otherwise, we don't need a closure.
(cl-assert (byte-code-function-p fun))
(byte-compile-form
- (if (or (not docstring-exp) (stringp docstring-exp))
+ (if (macroexp-const-p docstring-exp)
;; Use symbols V0, V1 ... as placeholders for closure variables:
;; they should be short (to save space in the .elc file), yet
;; distinct when disassembled.
@@ -3914,24 +3989,33 @@ discarding."
(number-sequence 4 (1- (length fun)))))
(proto-fun
(apply #'make-byte-code
- (aref fun 0) (aref fun 1)
+ (aref fun 0) ; The arglist is always the 15-bit
+ ; form, never the list of symbols.
+ (aref fun 1) ; The byte-code.
;; Prepend dummy cells to the constant vector,
;; to get the indices right when disassembling.
(vconcat dummy-vars (aref fun 2))
- (aref fun 3)
+ (aref fun 3) ; Stack depth of function
(if docstring-exp
- (cons docstring-exp (cdr opt-args))
+ (cons
+ (eval (byte-run-strip-symbol-positions
+ docstring-exp)
+ t)
+ (cdr opt-args)) ; The interactive spec will
+ ; have been stripped in
+ ; `byte-compile-lambda'.
opt-args))))
`(make-closure ,proto-fun ,@env))
;; Nontrivial doc string expression: create a bytecode object
;; from small pieces at run time.
`(make-byte-code
- ',(aref fun 0) ',(aref fun 1)
- (vconcat (vector . ,env) ',(aref fun 2))
+ ',(aref fun 0) ; 15-bit form of arglist descriptor.
+ ',(aref fun 1) ; The byte-code.
+ (vconcat (vector . ,env) ',(aref fun 2)) ; constant vector.
,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun))))
(if docstring-exp
`(,(car rest)
- ,docstring-exp
+ ,(byte-run-strip-symbol-positions docstring-exp)
,@(cddr rest))
rest))))
))))
@@ -4090,7 +4174,8 @@ discarding."
(if (eq 'interactive (car-safe (car body))) (setq body (cdr body)))
(if (and (consp (car body))
(not (eq 'byte-code (car (car body)))))
- (byte-compile-warn
+ (byte-compile-warn-x
+ (nth 2 form)
"A quoted lambda form is the second argument of `fset'. This is probably
not what you want, as that lambda cannot be compiled. Consider using
the syntax #'(lambda (...) ...) instead.")))))
@@ -4144,25 +4229,13 @@ discarding."
(byte-defop-compiler-1 quote)
(defun byte-compile-setq (form)
- (let* ((args (cdr form))
- (len (length args)))
- (if (= (logand len 1) 1)
- (progn
- (byte-compile-report-error
- (format-message
- "missing value for `%S' at end of setq" (car (last args))))
- (byte-compile-form
- `(signal 'wrong-number-of-arguments '(setq ,len))
- byte-compile--for-effect))
- (if args
- (while args
- (byte-compile-form (car (cdr args)))
- (or byte-compile--for-effect (cdr (cdr args))
- (byte-compile-out 'byte-dup 0))
- (byte-compile-variable-set (car args))
- (setq args (cdr (cdr args))))
- ;; (setq), with no arguments.
- (byte-compile-form nil byte-compile--for-effect)))
+ (cl-assert (= (length form) 3)) ; normalised in macroexp
+ (let ((var (nth 1 form))
+ (expr (nth 2 form)))
+ (byte-compile-form expr)
+ (unless byte-compile--for-effect
+ (byte-compile-out 'byte-dup 0))
+ (byte-compile-variable-set var)
(setq byte-compile--for-effect nil)))
(byte-defop-compiler-1 set-default)
@@ -4175,10 +4248,11 @@ discarding."
(macroexp--const-symbol-p var t))
(byte-compile-warning-enabled-p 'constants
(and (symbolp var) var))
- (byte-compile-warn
+ (byte-compile-warn-x
+ var
"variable assignment to %s `%s'"
(if (symbolp var) "constant" "nonvariable")
- (prin1-to-string var)))))
+ var))))
(byte-compile-normal-call form)))
(defun byte-compile-quote (form)
@@ -4711,7 +4785,6 @@ binding slots have been popped."
;; Even when optimization is off, /= is optimized to (not (= ...)).
(defun byte-compile-negation-optimizer (form)
;; an optimizer for forms where <form1> is less efficient than (not <form2>)
- (byte-compile-set-symbol-position (car form))
(list 'not
(cons (or (get (car form) 'byte-compile-negated-op)
(error
@@ -4739,11 +4812,8 @@ binding slots have been popped."
(byte-compile-out-tag endtag)))
(defun byte-compile-unwind-protect (form)
- (pcase (cddr form)
- (`(:fun-body ,f)
- (byte-compile-form f))
- (handlers
- (byte-compile-form `#'(lambda () ,@handlers))))
+ (cl-assert (eq (caddr form) :fun-body))
+ (byte-compile-form (nth 3 form))
(byte-compile-out 'byte-unwind-protect 0)
(byte-compile-form-do-effect (car (cdr form)))
(byte-compile-out 'byte-unbind 1))
@@ -4761,18 +4831,17 @@ binding slots have been popped."
(cons (byte-compile-make-tag) clause))
failure-handlers))
(endtag (byte-compile-make-tag)))
- (byte-compile-set-symbol-position 'condition-case)
(unless (symbolp var)
- (byte-compile-warn
- "`%s' is not a variable-name or nil (in condition-case)" var))
+ (byte-compile-warn-x
+ var "`%s' is not a variable-name or nil (in condition-case)" var))
(dolist (clause (reverse clauses))
(let ((condition (nth 1 clause)))
(unless (consp condition) (setq condition (list condition)))
(dolist (c condition)
(unless (and c (symbolp c))
- (byte-compile-warn
- "`%S' is not a condition name (in condition-case)" c))
+ (byte-compile-warn-x
+ c "`%S' is not a condition name (in condition-case)" c))
;; In reality, the `error-conditions' property is only required
;; for the argument to `signal', not to `condition-case'.
;;(unless (consp (get c 'error-conditions))
@@ -4823,7 +4892,8 @@ binding slots have been popped."
(defun byte-compile-save-excursion (form)
(if (and (eq 'set-buffer (car-safe (car-safe (cdr form))))
(byte-compile-warning-enabled-p 'suspicious 'set-buffer))
- (byte-compile-warn
+ (byte-compile-warn-x
+ form
"Use `with-current-buffer' rather than save-excursion+set-buffer"))
(byte-compile-out 'byte-save-excursion 0)
(byte-compile-body-do-effect (cdr form))
@@ -4857,25 +4927,25 @@ binding slots have been popped."
(push (nth 1 (nth 1 form)) byte-compile-global-not-obsolete-vars))
(byte-compile-normal-call form))
-(defconst byte-compile-tmp-var (make-symbol "def-tmp-var"))
-
(defun byte-compile-defvar (form)
;; This is not used for file-level defvar/consts.
(when (and (symbolp (nth 1 form))
(not (string-match "[-*/:$]" (symbol-name (nth 1 form))))
(byte-compile-warning-enabled-p 'lexical (nth 1 form)))
- (byte-compile-warn "global/dynamic var `%s' lacks a prefix"
- (nth 1 form)))
- (byte-compile-docstring-length-warn form)
+ (byte-compile-warn-x
+ (nth 1 form)
+ "global/dynamic var `%s' lacks a prefix"
+ (nth 1 form)))
+ (byte-compile-docstring-style-warn form)
(let ((fun (nth 0 form))
(var (nth 1 form))
(value (nth 2 form))
(string (nth 3 form)))
- (byte-compile-set-symbol-position fun)
(when (or (> (length form) 4)
(and (eq fun 'defconst) (null (cddr form))))
(let ((ncall (length (cdr form))))
- (byte-compile-warn
+ (byte-compile-warn-x
+ fun
"`%s' called with %d argument%s, but %s %s"
fun ncall
(if (= 1 ncall) "" "s")
@@ -4885,28 +4955,29 @@ binding slots have been popped."
(if (eq fun 'defconst)
(push var byte-compile-const-variables))
(when (and string (not (stringp string)))
- (byte-compile-warn "third arg to `%s %s' is not a string: %s"
- fun var string))
+ (byte-compile-warn-x
+ string
+ "third arg to `%s %s' is not a string: %s"
+ fun var string))
+ ;; Delegate the actual work to the function version of the
+ ;; special form, named with a "-1" suffix.
(byte-compile-form-do-effect
- (if (cddr form) ; `value' provided
- ;; Quote with `quote' to prevent byte-compiling the body,
- ;; which would lead to an inf-loop.
- `(funcall '(lambda (,byte-compile-tmp-var)
- (,fun ,var ,byte-compile-tmp-var ,@(nthcdr 3 form)))
- ,value)
- (if (eq fun 'defconst)
- ;; This will signal an appropriate error at runtime.
- `(eval ',form)
- ;; A simple (defvar foo) just returns foo.
- `',var)))))
+ (cond
+ ((eq fun 'defconst) `(defconst-1 ',var ,@(nthcdr 2 form)))
+ ((not (cddr form)) `',var) ; A simple (defvar foo) just returns foo.
+ (t `(defvar-1 ',var
+ ;; Don't eval `value' if `defvar' wouldn't eval it either.
+ ,(if (macroexp-const-p value) value
+ `(if (boundp ',var) nil ,value))
+ ,@(nthcdr 3 form)))))))
(defun byte-compile-autoload (form)
- (byte-compile-set-symbol-position 'autoload)
(and (macroexp-const-p (nth 1 form))
(macroexp-const-p (nth 5 form))
(memq (eval (nth 5 form)) '(t macro)) ; macro-p
(not (fboundp (eval (nth 1 form))))
- (byte-compile-warn
+ (byte-compile-warn-x
+ form
"The compiler ignores `autoload' except at top level. You should
probably put the autoload of the macro `%s' at top-level."
(eval (nth 1 form))))
@@ -4915,7 +4986,6 @@ binding slots have been popped."
;; Lambdas in valid places are handled as special cases by various code.
;; The ones that remain are errors.
(defun byte-compile-lambda-form (_form)
- (byte-compile-set-symbol-position 'lambda)
(error "`lambda' used as function name is invalid"))
;; Compile normally, but deal with warnings for the function being defined.
@@ -4941,7 +5011,7 @@ binding slots have been popped."
;; - `arg' is the expression to which it is defined.
;; - `rest' is the rest of the arguments.
(`(,_ ',name ,arg . ,rest)
- (byte-compile-docstring-length-warn form)
+ (byte-compile-docstring-style-warn form)
(pcase-let*
;; `macro' is non-nil if it defines a macro.
;; `fun' is the function part of `arg' (defaults to `arg').
@@ -4995,7 +5065,8 @@ binding slots have been popped."
(defun byte-compile-make-variable-buffer-local (form)
(if (and (eq (car-safe (car-safe (cdr-safe form))) 'quote)
(byte-compile-warning-enabled-p 'make-local))
- (byte-compile-warn
+ (byte-compile-warn-x
+ form
"`make-variable-buffer-local' not called at toplevel"))
(byte-compile-normal-call form))
(put 'make-variable-buffer-local
@@ -5075,7 +5146,7 @@ binding slots have been popped."
OP and OPERAND are as passed to `byte-compile-out'."
(if (memq op '(byte-call byte-discardN byte-discardN-preserve-tos))
;; For calls, OPERAND is the number of args, so we pop OPERAND + 1
- ;; elements, and the push the result, for a total of -OPERAND.
+ ;; elements, and then push the result, for a total of -OPERAND.
;; For discardN*, of course, we just pop OPERAND elements.
(- operand)
(or (aref byte-stack+-info (symbol-value op))
@@ -5085,6 +5156,11 @@ OP and OPERAND are as passed to `byte-compile-out'."
(- 1 operand))))
(defun byte-compile-out (op &optional operand)
+ "Push the operation onto `byte-compile-output'.
+OP is an opcode, a symbol. OPERAND is either nil or a number or
+a one-element list of a lisp form."
+ (when (and (consp operand) (null (cdr operand)))
+ (setq operand (byte-run-strip-symbol-positions operand)))
(push (cons op operand) byte-compile-output)
(if (eq op 'byte-return)
;; This is actually an unnecessary case, because there should be no
@@ -5099,24 +5175,26 @@ OP and OPERAND are as passed to `byte-compile-out'."
;;; call tree stuff
(defun byte-compile-annotate-call-tree (form)
- (let (entry)
+ (let ((current-form (byte-run-strip-symbol-positions
+ byte-compile-current-form))
+ (bare-car-form (byte-run-strip-symbol-positions (car form)))
+ entry)
;; annotate the current call
- (if (setq entry (assq (car form) byte-compile-call-tree))
- (or (memq byte-compile-current-form (nth 1 entry)) ;callers
+ (if (setq entry (assq bare-car-form byte-compile-call-tree))
+ (or (memq current-form (nth 1 entry)) ;callers
(setcar (cdr entry)
- (cons byte-compile-current-form (nth 1 entry))))
+ (cons current-form (nth 1 entry))))
(setq byte-compile-call-tree
- (cons (list (car form) (list byte-compile-current-form) nil)
+ (cons (list bare-car-form (list current-form) nil)
byte-compile-call-tree)))
;; annotate the current function
- (if (setq entry (assq byte-compile-current-form byte-compile-call-tree))
- (or (memq (car form) (nth 2 entry)) ;called
+ (if (setq entry (assq current-form byte-compile-call-tree))
+ (or (memq bare-car-form (nth 2 entry)) ;called
(setcar (cdr (cdr entry))
- (cons (car form) (nth 2 entry))))
+ (cons bare-car-form (nth 2 entry))))
(setq byte-compile-call-tree
- (cons (list byte-compile-current-form nil (list (car form)))
- byte-compile-call-tree)))
- ))
+ (cons (list current-form nil (list bare-car-form))
+ byte-compile-call-tree)))))
;; Renamed from byte-compile-report-call-tree
;; to avoid interfering with completion of byte-compile-file.
@@ -5141,14 +5219,15 @@ invoked interactively."
(set-buffer "*Call-Tree*")
(erase-buffer)
(message "Generating call tree... (sorting on %s)"
- byte-compile-call-tree-sort)
+ (remove-pos-from-symbol byte-compile-call-tree-sort))
(insert "Call tree for "
(cond ((null byte-compile-current-file) (or filename "???"))
((stringp byte-compile-current-file)
byte-compile-current-file)
(t (buffer-name byte-compile-current-file)))
" sorted on "
- (prin1-to-string byte-compile-call-tree-sort)
+ (prin1-to-string (remove-pos-from-symbol
+ byte-compile-call-tree-sort))
":\n\n")
(if byte-compile-call-tree-sort
(setq byte-compile-call-tree
@@ -5168,7 +5247,8 @@ invoked interactively."
('name
(lambda (x y) (string< (car x) (car y))))
(_ (error "`byte-compile-call-tree-sort': `%s' - unknown sort mode"
- byte-compile-call-tree-sort))))))
+ (remove-pos-from-symbol
+ byte-compile-call-tree-sort)))))))
(message "Generating call tree...")
(let ((rest byte-compile-call-tree)
(b (current-buffer))
@@ -5315,7 +5395,7 @@ already up-to-date."
(or (not (file-exists-p dest))
(file-newer-than-file-p source dest))))
(if (null (batch-byte-compile-file (car command-line-args-left)))
- (setq error t))))
+ (setq error t))))
(setq command-line-args-left (cdr command-line-args-left)))
(kill-emacs (if error 1 0))))
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index e114ef1075e..7f95fa94fa1 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -25,21 +25,20 @@
;;; Commentary:
;; This takes a piece of Elisp code, and eliminates all free variables from
-;; lambda expressions. The user entry points are cconv-closure-convert and
-;; cconv-closure-convert-toplevel (for toplevel forms).
+;; lambda expressions. The user entry point is `cconv-closure-convert'.
;; All macros should be expanded beforehand.
;;
;; Here is a brief explanation how this code works.
-;; Firstly, we analyze the tree by calling cconv-analyze-form.
+;; Firstly, we analyze the tree by calling `cconv-analyze-form'.
;; This function finds all mutated variables, all functions that are suitable
;; for lambda lifting and all variables captured by closure. It passes the tree
;; once, returning a list of three lists.
;;
;; Then we calculate the intersection of the first and third lists returned by
-;; cconv-analyze form to find all mutated variables that are captured by
+;; `cconv-analyze-form' to find all mutated variables that are captured by
;; closure.
-;; Armed with this data, we call cconv-closure-convert-rec, that rewrites the
+;; Armed with this data, we call `cconv-convert', that rewrites the
;; tree recursively, lifting lambdas where possible, building closures where it
;; is needed and eliminating mutable variables used in closure.
;;
@@ -141,11 +140,9 @@ is less than this number.")
;;;###autoload
(defun cconv-closure-convert (form)
"Main entry point for closure conversion.
--- FORM is a piece of Elisp code after macroexpansion.
--- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST
+FORM is a piece of Elisp code after macroexpansion.
Returns a form where all lambdas don't have any free variables."
- ;; (message "Entering cconv-closure-convert...")
(let ((cconv-freevars-alist '())
(cconv-var-classification '()))
;; Analyze form - fill these variables with new information.
@@ -201,7 +198,10 @@ Returns a form where all lambdas don't have any free variables."
(i 0)
(new-env ()))
;; Build the "formal and actual envs" for the closure-converted function.
- (dolist (fv fvs)
+ ;; Hack for OClosure: `nreverse' here intends to put the captured vars
+ ;; in the closure such that the first one is the one that is bound
+ ;; most closely.
+ (dolist (fv (nreverse fvs))
(let ((exp (or (cdr (assq fv env)) fv)))
(pcase exp
;; If `fv' is a variable that's wrapped in a cons-cell,
@@ -240,7 +240,7 @@ Returns a form where all lambdas don't have any free variables."
;; this case better, we'd need to traverse the tree one more time to
;; collect this data, and I think that it's not worth it.
(mapcar (lambda (mapping)
- (if (not (eq (cadr mapping) 'apply-partially))
+ (if (not (eq (cadr mapping) #'apply-partially))
mapping
(cl-assert (eq (car mapping) (nth 2 mapping)))
`(,(car mapping)
@@ -258,17 +258,16 @@ Returns a form where all lambdas don't have any free variables."
;; unused vars.
(not (intern-soft var))
(eq ?_ (aref (symbol-name var) 0))
- ;; As a special exception, ignore "ignore".
+ ;; As a special exception, ignore "ignored".
(eq var 'ignored))
(let ((suggestions (help-uni-confusable-suggestions (symbol-name var))))
(format "Unused lexical %s `%S'%s"
- varkind var
+ varkind (bare-symbol var)
(if suggestions (concat "\n " suggestions) "")))))
(define-inline cconv--var-classification (binder form)
(inline-quote
- (alist-get (cons ,binder ,form) cconv-var-classification
- nil nil #'equal)))
+ (cdr (assoc (cons ,binder ,form) cconv-var-classification))))
(defun cconv--convert-funcbody (funargs funcbody env parentform)
"Run `cconv-convert' on FUNCBODY, the forms of a lambda expression.
@@ -286,7 +285,7 @@ of converted forms."
(let (and (pred stringp) msg)
(cconv--warn-unused-msg arg "argument")))
(if (assq arg env) (push `(,arg . nil) env)) ;FIXME: Is it needed?
- (push (lambda (body) (macroexp--warn-wrap msg body 'lexical)) wrappers))
+ (push (lambda (body) (macroexp--warn-wrap arg msg body 'lexical)) wrappers))
(_
(if (assq arg env) (push `(,arg . nil) env)))))
(setq funcbody (mapcar (lambda (form)
@@ -367,7 +366,8 @@ places where they originally did not directly appear."
(var (if (not (consp binder))
(prog1 binder (setq binder (list binder)))
(when (cddr binder)
- (byte-compile-warn
+ (byte-compile-warn-x
+ binder
"Malformed `%S' binding: %S"
letsym binder))
(setq value (cadr binder))
@@ -375,9 +375,9 @@ places where they originally did not directly appear."
(cond
;; Ignore bindings without a valid name.
((not (symbolp var))
- (byte-compile-warn "attempt to let-bind nonvariable `%S'" var))
+ (byte-compile-warn-x var "attempt to let-bind nonvariable `%S'" var))
((or (booleanp var) (keywordp var))
- (byte-compile-warn "attempt to let-bind constant `%S'" var))
+ (byte-compile-warn-x var "attempt to let-bind constant `%S'" var))
(t
(let ((new-val
(pcase (cconv--var-classification binder form)
@@ -427,11 +427,14 @@ places where they originally did not directly appear."
;; Declared variable is unused.
(if (assq var new-env)
(push `(,var) new-env)) ;FIXME:Needed?
- (let ((newval
- `(ignore ,(cconv-convert value env extend)))
- (msg (cconv--warn-unused-msg var "variable")))
+ (let* ((Ignore (if (symbol-with-pos-p var)
+ (position-symbol 'ignore var)
+ 'ignore))
+ (newval `(,Ignore
+ ,(cconv-convert value env extend)))
+ (msg (cconv--warn-unused-msg var "variable")))
(if (null msg) newval
- (macroexp--warn-wrap msg newval 'lexical))))
+ (macroexp--warn-wrap var msg newval 'lexical))))
;; Normal default case.
(_
@@ -445,6 +448,9 @@ places where they originally did not directly appear."
(let ((var-def (cconv--lifted-arg var env))
(closedsym (make-symbol (format "closed-%s" var))))
(setq new-env (cconv--remap-llv new-env var closedsym))
+ ;; FIXME: `closedsym' doesn't need to be added to `extend'
+ ;; but adding it makes it easier to write the assertion at
+ ;; the beginning of this function.
(setq new-extend (cons closedsym (remq var new-extend)))
(push `(,closedsym ,var-def) binders-new)))
@@ -490,11 +496,11 @@ places where they originally did not directly appear."
args)))
(`(cond . ,cond-forms) ; cond special form
- `(cond . ,(mapcar (lambda (branch)
- (mapcar (lambda (form)
- (cconv-convert form env extend))
- branch))
- cond-forms)))
+ `(,(car form) . ,(mapcar (lambda (branch)
+ (mapcar (lambda (form)
+ (cconv-convert form env extend))
+ branch))
+ cond-forms)))
(`(function (lambda ,args . ,body) . ,_)
(let ((docstring (if (eq :documentation (car-safe (car body)))
@@ -528,9 +534,9 @@ places where they originally did not directly appear."
(msg (when (eq class :unused)
(cconv--warn-unused-msg var "variable")))
(newprotform (cconv-convert protected-form env extend)))
- `(condition-case ,var
+ `(,(car form) ,var
,(if msg
- (macroexp--warn-wrap msg newprotform 'lexical)
+ (macroexp--warn-wrap var msg newprotform 'lexical)
newprotform)
,@(mapcar
(lambda (handler)
@@ -544,33 +550,23 @@ places where they originally did not directly appear."
`((let ((,var (list ,var))) ,@body))))))
handlers))))
- (`(unwind-protect ,form . ,body)
- `(unwind-protect ,(cconv-convert form env extend)
- :fun-body ,(cconv--convert-function () body env form)))
-
- (`(setq . ,forms) ; setq special form
- (if (= (logand (length forms) 1) 1)
- ;; With an odd number of args, let bytecomp.el handle the error.
- form
- (let ((prognlist ()))
- (while forms
- (let* ((sym (pop forms))
- (sym-new (or (cdr (assq sym env)) sym))
- (value (cconv-convert (pop forms) env extend)))
- (push (pcase sym-new
- ((pred symbolp) `(setq ,sym-new ,value))
- (`(car-safe ,iexp) `(setcar ,iexp ,value))
- ;; This "should never happen", but for variables which are
- ;; mutated+captured+unused, we may end up trying to `setq'
- ;; on a closed-over variable, so just drop the setq.
- (_ ;; (byte-compile-report-error
- ;; (format "Internal error in cconv of (setq %s ..)"
- ;; sym-new))
- value))
- prognlist)))
- (if (cdr prognlist)
- `(progn . ,(nreverse prognlist))
- (car prognlist)))))
+ (`(unwind-protect ,form1 . ,body)
+ `(,(car form) ,(cconv-convert form1 env extend)
+ :fun-body ,(cconv--convert-function () body env form1)))
+
+ (`(setq ,var ,expr)
+ (let ((var-new (or (cdr (assq var env)) var))
+ (value (cconv-convert expr env extend)))
+ (pcase var-new
+ ((pred symbolp) `(,(car form) ,var-new ,value))
+ (`(car-safe ,iexp) `(setcar ,iexp ,value))
+ ;; This "should never happen", but for variables which are
+ ;; mutated+captured+unused, we may end up trying to `setq'
+ ;; on a closed-over variable, so just drop the setq.
+ (_ ;; (byte-compile-report-error
+ ;; (format "Internal error in cconv of (setq %s ..)"
+ ;; sym-new))
+ value))))
(`(,(and (or 'funcall 'apply) callsym) ,fun . ,args)
;; These are not special forms but we treat them separately for the needs
@@ -594,12 +590,20 @@ places where they originally did not directly appear."
(cons fun args)))))))
(`(interactive . ,forms)
- `(interactive . ,(mapcar (lambda (form)
+ `(,(car form) . ,(mapcar (lambda (form)
(cconv-convert form nil nil))
forms)))
(`(declare . ,_) form) ;The args don't contain code.
+ (`(oclosure--fix-type (ignore . ,vars) ,exp)
+ (dolist (var vars)
+ (let ((x (assq var env)))
+ (pcase (cdr x)
+ (`(car-safe . ,_) (error "Slot %S should not be mutated" var))
+ (_ (cl-assert (null (cdr x)))))))
+ (cconv-convert exp env extend))
+
(`(,func . ,forms)
;; First element is function or whatever function-like forms are: or, and,
;; if, catch, progn, prog1, while, until
@@ -624,7 +628,8 @@ FORM is the parent form that binds this var."
;; FIXME: Convert this warning to use `macroexp--warn-wrap'
;; so as to give better position information.
(when (byte-compile-warning-enabled-p 'not-unused var)
- (byte-compile-warn "%s `%S' not left unused" varkind var)))
+ (byte-compile-warn-x
+ var "%s `%S' not left unused" varkind var)))
((and (let (or 'let* 'let) (car form))
`((,var) ;; (or `(,var nil) : Too many false positives: bug#47080
t nil ,_ ,_))
@@ -632,7 +637,7 @@ FORM is the parent form that binds this var."
;; so as to give better position information and obey
;; `byte-compile-warnings'.
(unless (not (intern-soft var))
- (byte-compile-warn "Variable `%S' left uninitialized" var))))
+ (byte-compile-warn-x var "Variable `%S' left uninitialized" var))))
(pcase vardata
(`(,binder nil ,_ ,_ nil)
(push (cons (cons binder form) :unused) cconv-var-classification))
@@ -658,17 +663,19 @@ FORM is the parent form that binds this var."
;; Push it before recursing, so cconv-freevars-alist contains entries in
;; the order they'll be used by closure-convert-rec.
(push freevars cconv-freevars-alist)
- (dolist (arg args)
- (cond
- ((byte-compile-not-lexical-var-p arg)
- (byte-compile-warn
- "Lexical argument shadows the dynamic variable %S"
- arg))
- ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ...
- (t (let ((varstruct (list arg nil nil nil nil)))
- (cl-pushnew arg byte-compile-lexical-variables)
- (push (cons (list arg) (cdr varstruct)) newvars)
- (push varstruct newenv)))))
+ (when lexical-binding
+ (dolist (arg args)
+ (cond
+ ((byte-compile-not-lexical-var-p arg)
+ (byte-compile-warn-x
+ arg
+ "Lexical argument shadows the dynamic variable %S"
+ arg))
+ ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ...
+ (t (let ((varstruct (list arg nil nil nil nil)))
+ (cl-pushnew arg byte-compile-lexical-variables)
+ (push (cons (list arg) (cdr varstruct)) newvars)
+ (push varstruct newenv))))))
(dolist (form body) ;Analyze body forms.
(cconv-analyze-form form newenv))
;; Summarize resulting data about arguments.
@@ -717,7 +724,7 @@ This function does not return anything but instead fills the
(cconv-analyze-form value (if (eq letsym 'let*) env orig-env)))
- (unless (byte-compile-not-lexical-var-p var)
+ (unless (or (byte-compile-not-lexical-var-p var) (not lexical-binding))
(cl-pushnew var byte-compile-lexical-variables)
(let ((varstruct (list var nil nil nil nil)))
(push (cons binder (cdr varstruct)) newvars)
@@ -734,17 +741,17 @@ This function does not return anything but instead fills the
(cconv-analyze-form (cadr (pop body-forms)) env))
(cconv--analyze-function vrs body-forms env form))
- (`(setq . ,forms)
+ (`(setq ,var ,expr)
;; If a local variable (member of env) is modified by setq then
;; it is a mutated variable.
- (while forms
- (let ((v (assq (car forms) env))) ; v = non nil if visible
- (when v (setf (nth 2 v) t)))
- (cconv-analyze-form (cadr forms) env)
- (setq forms (cddr forms))))
+ (let ((v (assq var env))) ; v = non nil if visible
+ (when v
+ (setf (nth 2 v) t)))
+ (cconv-analyze-form expr env))
(`((lambda . ,_) . ,_) ; First element is lambda expression.
- (byte-compile-warn
+ (byte-compile-warn-x
+ (nth 1 (car form))
"Use of deprecated ((lambda %s ...) ...) form" (nth 1 (car form)))
(dolist (exp `((function ,(car form)) . ,(cdr form)))
(cconv-analyze-form exp env)))
@@ -762,9 +769,11 @@ This function does not return anything but instead fills the
(`(condition-case ,var ,protected-form . ,handlers)
(cconv-analyze-form protected-form env)
+ (unless lexical-binding
+ (setq var nil))
(when (and var (symbolp var) (byte-compile-not-lexical-var-p var))
- (byte-compile-warn
- "Lexical variable shadows the dynamic variable %S" var))
+ (byte-compile-warn-x
+ var "Lexical variable shadows the dynamic variable %S" var))
(let* ((varstruct (list var nil nil nil nil)))
(if var (push varstruct env))
(dolist (handler handlers)
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 4186a541f82..716b236d3ab 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -1,7 +1,6 @@
;;; chart.el --- Draw charts (bar charts, etc) -*- lexical-binding: t -*-
-;; Copyright (C) 1996, 1998-1999, 2001, 2004-2005, 2007-2022 Free
-;; Software Foundation, Inc.
+;; Copyright (C) 1996-2022 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.2
@@ -64,7 +63,6 @@
(eval-when-compile (require 'cl-generic))
;;; Code:
-(define-obsolete-variable-alias 'chart-map 'chart-mode-map "24.1")
(defvar chart-mode-map (make-sparse-keymap) "Keymap used in chart mode.")
(defvar-local chart-local-object nil
@@ -76,8 +74,7 @@
Colors will be the background color.")
(defvar chart-face-pixmap-list
- (if (and (fboundp 'display-graphic-p)
- (display-graphic-p))
+ (if (display-graphic-p)
'("dimple1" "scales" "dot" "cross_weave" "boxes" "dimple3"))
"If pixmaps are allowed, display these background pixmaps.
Useful if new Emacs is used on B&W display.")
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index eeefb3de10c..83187acf71e 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -319,10 +319,7 @@ Returns non-nil if any false statements are found."
(setq root (directory-file-name (file-relative-name root)))
(or (file-directory-p root)
(error "Directory `%s' not found" root))
- (let ((files (process-lines find-program root
- "-name" "*.el"
- "-exec" grep-program
- "-l" "^[ \t]*(declare-function" "{}" "+")))
+ (let ((files (directory-files-recursively root "\\.el\\'")))
(when files
(apply #'check-declare-files files))))
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 334988e7135..611f32e23c6 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -165,8 +165,8 @@
(require 'cl-lib)
(require 'help-mode) ;; for help-xref-info-regexp
(require 'thingatpt) ;; for handy thing-at-point-looking-at
-(require 'lisp-mode) ;; for lisp-mode-symbol-regexp
-(require 'dired) ;; for dired-get-filename and dired-map-over-marks
+(require 'lisp-mode) ;; for lisp-mode-symbol regexp
+(eval-when-compile (require 'dired)) ;; for dired-map-over-marks
(require 'lisp-mnt)
(defvar compilation-error-regexp-alist)
@@ -327,7 +327,7 @@ This should be set in an Emacs Lisp file's local variables."
;;;###autoload(put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p)
(defcustom checkdoc-column-zero-backslash-before-paren t
- "Non-nil means to warn if there is no '\\' before '(' in column zero.
+ "Non-nil means to warn if there is no \"\\\" before \"(\" in column zero.
This backslash is no longer needed on Emacs 27.1 or later.
See Info node `(elisp) Documentation Tips' for background."
@@ -1124,12 +1124,20 @@ Skip anything that doesn't have the Emacs Lisp library file
extension (\".el\").
When called from Lisp, FILES is a list of filenames."
(interactive
- (list
- (delq nil
- (mapcar
- ;; skip anything that doesn't look like an Emacs Lisp library
- (lambda (f) (if (equal (file-name-extension f) "el") f nil))
- (nreverse (dired-map-over-marks (dired-get-filename) nil)))))
+ (progn
+ ;; These Dired functions must be defined since we're in a Dired buffer.
+ (declare-function dired-get-filename "dired"
+ (&optional localp no-error-if-not-filep))
+ ;; These functions are used by the expansion of `dired-map-over-marks'.
+ (declare-function dired-move-to-filename "dired"
+ (&optional raise-error eol))
+ (declare-function dired-marker-regexp "dired" ())
+ (list
+ (delq nil
+ (mapcar
+ ;; skip anything that doesn't look like an Emacs Lisp library
+ (lambda (f) (if (equal (file-name-extension f) "el") f nil))
+ (nreverse (dired-map-over-marks (dired-get-filename) nil))))))
dired-mode)
(if (null files)
(error "No files to run checkdoc on")
@@ -1271,38 +1279,30 @@ TEXT, START, END and UNFIXABLE conform to
;;; Minor Mode specification
;;
-(defvar checkdoc-minor-mode-map
- (let ((map (make-sparse-keymap))
- (pmap (make-sparse-keymap)))
- ;; Override some bindings
- (define-key map "\C-\M-x" 'checkdoc-eval-defun)
- (define-key map "\C-x`" 'checkdoc-continue)
- (define-key map [menu-bar emacs-lisp eval-buffer]
- 'checkdoc-eval-current-buffer)
- ;; Add some new bindings under C-c ?
- (define-key pmap "x" 'checkdoc-defun)
- (define-key pmap "X" 'checkdoc-ispell-defun)
- (define-key pmap "`" 'checkdoc-continue)
- (define-key pmap "~" 'checkdoc-ispell-continue)
- (define-key pmap "s" 'checkdoc-start)
- (define-key pmap "S" 'checkdoc-ispell-start)
- (define-key pmap "d" 'checkdoc)
- (define-key pmap "D" 'checkdoc-ispell)
- (define-key pmap "b" 'checkdoc-current-buffer)
- (define-key pmap "B" 'checkdoc-ispell-current-buffer)
- (define-key pmap "e" 'checkdoc-eval-current-buffer)
- (define-key pmap "m" 'checkdoc-message-text)
- (define-key pmap "M" 'checkdoc-ispell-message-text)
- (define-key pmap "c" 'checkdoc-comments)
- (define-key pmap "C" 'checkdoc-ispell-comments)
- (define-key pmap " " 'checkdoc-rogue-spaces)
-
- ;; bind our submap into map
- (define-key map "\C-c?" pmap)
- map)
- "Keymap used to override evaluation key-bindings for documentation checking.")
-
-;; Add in a menubar with easy-menu
+(defvar-keymap checkdoc-minor-mode-map
+ :doc "Keymap used to override evaluation key-bindings for documentation checking."
+ ;; Override some bindings
+ "C-M-x" #'checkdoc-eval-defun
+ "C-x `" #'checkdoc-continue
+ "<menu-bar> <emacs-lisp> <eval-buffer>" #'checkdoc-eval-current-buffer
+
+ ;; Add some new bindings under C-c ?
+ "C-c ? x" #'checkdoc-defun
+ "C-c ? X" #'checkdoc-ispell-defun
+ "C-c ? `" #'checkdoc-continue
+ "C-c ? ~" #'checkdoc-ispell-continue
+ "C-c ? s" #'checkdoc-start
+ "C-c ? S" #'checkdoc-ispell-start
+ "C-c ? d" #'checkdoc
+ "C-c ? D" #'checkdoc-ispell
+ "C-c ? b" #'checkdoc-current-buffer
+ "C-c ? B" #'checkdoc-ispell-current-buffer
+ "C-c ? e" #'checkdoc-eval-current-buffer
+ "C-c ? m" #'checkdoc-message-text
+ "C-c ? M" #'checkdoc-ispell-message-text
+ "C-c ? c" #'checkdoc-comments
+ "C-c ? C" #'checkdoc-ispell-comments
+ "C-c ? SPC" #'checkdoc-rogue-spaces)
(easy-menu-define nil checkdoc-minor-mode-map
"Checkdoc Minor Mode Menu."
@@ -1999,6 +1999,7 @@ from the comment."
(let ((defun (looking-at
"(\\(?:cl-\\)?def\\(un\\|macro\\|subst\\|advice\\|generic\\|method\\)"))
(is-advice (looking-at "(defadvice"))
+ (defun-depth (ppss-depth (syntax-ppss)))
(lst nil)
(ret nil)
(oo (make-vector 3 0))) ;substitute obarray for `read'
@@ -2014,11 +2015,17 @@ from the comment."
(setq ret (cons nil ret))
;; Interactive
(save-excursion
- (setq ret (cons
- (re-search-forward "^\\s-*(interactive"
- (save-excursion (end-of-defun) (point))
- t)
- ret)))
+ (push (and (re-search-forward "^\\s-*(interactive"
+ (save-excursion
+ (end-of-defun)
+ (point))
+ t)
+ ;; Disregard `interactive' from other parts of
+ ;; the function.
+ (= (ppss-depth (syntax-ppss))
+ (+ defun-depth 2))
+ (point))
+ ret))
(skip-chars-forward " \t\n")
(let ((bss (buffer-substring (point) (save-excursion (forward-sexp 1)
(point))))
@@ -2226,7 +2233,7 @@ If the offending word is in a piece of quoted text, then it is skipped."
;;
(defvar ispell-process)
(declare-function ispell-buffer-local-words "ispell" ())
-(declare-function ispell-correct-p "ispell" ())
+(declare-function ispell-correct-p "ispell" (&optional following))
(declare-function ispell-set-spellchecker-params "ispell" ())
(declare-function ispell-accept-buffer-local-defs "ispell" ())
(declare-function ispell-error-checking-word "ispell" (word))
@@ -2456,11 +2463,9 @@ Code:, and others referenced in the style guide."
pos)
(goto-char (point-min))
;; match ";;;###autoload" cookie to keep it with the form
- (require 'autoload)
(while (and cont (re-search-forward
- (concat "^\\("
- (regexp-quote generate-autoload-cookie)
- "\n\\)?"
+ (concat "^\\(" lisp-mode-autoload-regexp
+ "\n\\)?"
"(")
nil t))
(setq pos (match-beginning 0)
@@ -2591,13 +2596,13 @@ The correct format is \"Foo\" or \"some-symbol: Foo\". See also
(unless (let ((case-fold-search nil))
(looking-at (rx (or upper-case "%s"))))
;; A defined Lisp symbol is always okay.
- (unless (and (looking-at (rx (group (regexp lisp-mode-symbol-regexp))))
+ (unless (and (looking-at (rx (group lisp-mode-symbol)))
(or (fboundp (intern (match-string 1)))
(boundp (intern (match-string 1)))))
;; Other Lisp symbols are sometimes okay.
(rx-let ((c (? "\\\n"))) ; `c' is for a continued line
(let ((case-fold-search nil)
- (some-symbol (rx (regexp lisp-mode-symbol-regexp)
+ (some-symbol (rx lisp-mode-symbol
c ":" c (+ (any " \t\n"))))
(lowercase-str (rx c (group (any "a-z") (+ wordchar)))))
(if (looking-at some-symbol)
@@ -2622,7 +2627,7 @@ a space as a style error."
(checkdoc-autofix-ask-replace
(match-beginning 0) (match-end 0)
(format-message
- "`y-or-n-p' argument should end with \"? \". Fix?")
+ "`y-or-n-p' argument should end with \"?\". Fix?")
"?\"" t))
nil
(checkdoc-create-error
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index ed9b1b7d836..8e38df43c87 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -553,10 +553,14 @@ too large if positive or too small if negative)."
,new)))))
(seq-subseq seq start end))
+;;; This isn't a defalias because autoloading defalises doesn't work
+;;; very well.
+
;;;###autoload
-(defalias 'cl-concatenate #'seq-concatenate
+(defun cl-concatenate (type &rest sequences)
"Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.
-\n(fn TYPE SEQUENCE...)")
+\n(fn TYPE SEQUENCE...)"
+ (apply #'seq-concatenate type sequences))
;;; List functions.
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 5090e060372..0560ddda268 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -144,13 +144,20 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value TAG
(cl-defstruct (cl--generic-method
(:constructor nil)
(:constructor cl--generic-make-method
- (specializers qualifiers uses-cnm function))
+ (specializers qualifiers call-con function))
(:predicate nil))
(specializers nil :read-only t :type list)
(qualifiers nil :read-only t :type (list-of atom))
- ;; USES-CNM is a boolean indicating if FUNCTION expects an extra argument
- ;; holding the next-method.
- (uses-cnm nil :read-only t :type boolean)
+ ;; CALL-CON indicates the calling convention expected by FUNCTION:
+ ;; - nil: FUNCTION is just a normal function with no extra arguments for
+ ;; `call-next-method' or `next-method-p' (which it hence can't use).
+ ;; - `curried': FUNCTION is a curried function that first takes the
+ ;; "next combined method" and return the resulting combined method.
+ ;; It can distinguish `next-method-p' by checking if that next method
+ ;; is `cl--generic-isnot-nnm-p'.
+ ;; - t: FUNCTION takes the `call-next-method' function as its first (extra)
+ ;; argument.
+ (call-con nil :read-only t :type symbol)
(function nil :read-only t :type function))
(cl-defstruct (cl--generic
@@ -262,6 +269,16 @@ DEFAULT-BODY, if present, is used as the body of a default method.
(declarations nil)
(methods ())
(options ())
+ (warnings
+ (let ((nonsymargs
+ (delq nil (mapcar (lambda (arg) (unless (symbolp arg) arg))
+ args))))
+ (when nonsymargs
+ (list
+ (macroexp-warn-and-return
+ (format "Non-symbol arguments to cl-defgeneric: %s"
+ (mapconcat #'prin1-to-string nonsymargs ""))
+ nil nil nil nonsymargs)))))
next-head)
(while (progn (setq next-head (car-safe (car options-and-methods)))
(or (keywordp next-head)
@@ -284,14 +301,17 @@ DEFAULT-BODY, if present, is used as the body of a default method.
(setq name (gv-setter (cadr name))))
`(prog1
(progn
+ ,@warnings
(defalias ',name
(cl-generic-define ',name ',args ',(nreverse options))
,(if (consp doc) ;An expression rather than a constant.
`(help-add-fundoc-usage ,doc ',args)
(help-add-fundoc-usage doc args)))
:autoload-end
- ,@(mapcar (lambda (method) `(cl-defmethod ,name ,@method))
- (nreverse methods)))
+ ,(when methods
+ `(with-suppressed-warnings ((obsolete ,name))
+ ,@(mapcar (lambda (method) `(cl-defmethod ,name ,@method))
+ (nreverse methods)))))
,@(mapcar (lambda (declaration)
(let ((f (cdr (assq (car declaration)
defun-declarations-alist))))
@@ -381,14 +401,16 @@ the specializer used will be the one returned by BODY."
. ,(lambda () spec-args))
macroexpand-all-environment)))
(require 'cl-lib) ;Needed to expand `cl-flet' and `cl-function'.
- (when (interactive-form (cadr fun))
- (message "Interactive forms unsupported in generic functions: %S"
- (interactive-form (cadr fun))))
+ (when (assq 'interactive body)
+ (message "Interactive forms not supported in generic functions: %S"
+ (assq 'interactive body)))
;; First macroexpand away the cl-function stuff (e.g. &key and
;; destructuring args, `declare' and whatnot).
(pcase (macroexpand fun macroenv)
(`#'(lambda ,args . ,body)
(let* ((parsed-body (macroexp-parse-body body))
+ (nm (make-symbol "cl--nm"))
+ (arglist (make-symbol "cl--args"))
(cnm (make-symbol "cl--cnm"))
(nmp (make-symbol "cl--nmp"))
(nbody (macroexpand-all
@@ -401,15 +423,49 @@ the specializer used will be the one returned by BODY."
;; is used.
;; FIXME: Also, optimize the case where call-next-method is
;; only called with explicit arguments.
- (uses-cnm (macroexp--fgrep `((,cnm) (,nmp)) nbody)))
- (cons (not (not uses-cnm))
- `#'(lambda (,@(if uses-cnm (list cnm)) ,@args)
- ,@(car parsed-body)
- ,(if (not (assq nmp uses-cnm))
- nbody
- `(let ((,nmp (lambda ()
- (cl--generic-isnot-nnm-p ,cnm))))
- ,nbody))))))
+ (uses-cnm (macroexp--fgrep `((,cnm) (,nmp)) nbody))
+ (λ-lift (mapcar #'car uses-cnm)))
+ (if (not uses-cnm)
+ (cons nil
+ `#'(lambda (,@args)
+ ,@(car parsed-body)
+ ,nbody))
+ (cons 'curried
+ `#'(lambda (,nm) ;Called when constructing the effective method.
+ (let ((,nmp (if (cl--generic-isnot-nnm-p ,nm)
+ #'always #'ignore)))
+ ;; This `(λ (&rest x) .. (apply (λ (args) ..) x))'
+ ;; dance is needed because we need to get the original
+ ;; args as a list when `cl-call-next-method' is
+ ;; called with no arguments. It's important to
+ ;; capture it as a list since it needs to distinguish
+ ;; the nil case from the absent case in optional
+ ;; arguments and it needs to properly remember the
+ ;; original value if `nbody' mutates some of its
+ ;; formal args.
+ ;; FIXME: This `(λ (&rest ,arglist)' could be skipped
+ ;; when we know `cnm' is always called with args, and
+ ;; it could be implemented more efficiently if `cnm'
+ ;; is always called directly and there are no
+ ;; `&optional' args.
+ (lambda (&rest ,arglist)
+ ,@(let* ((prebody (car parsed-body))
+ (ds (if (stringp (car prebody))
+ prebody
+ (setq prebody (cons nil prebody))))
+ (usage (help-split-fundoc (car ds) nil)))
+ (unless usage
+ (setcar ds (help-add-fundoc-usage (car ds)
+ args)))
+ prebody)
+ (let ((,cnm (lambda (&rest args)
+ (apply ,nm (or args ,arglist)))))
+ ;; This `apply+lambda' basically parses
+ ;; `arglist' according to `args'.
+ ;; A destructuring-bind would do the trick
+ ;; as well when/if it's more efficient.
+ (apply (lambda (,@λ-lift ,@args) ,nbody)
+ ,@λ-lift ,arglist)))))))))
(f (error "Unexpected macroexpansion result: %S" f))))))
(put 'cl-defmethod 'function-documentation
@@ -506,23 +562,18 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
(require 'gv)
(declare-function gv-setter "gv" (name))
(setq name (gv-setter (cadr name))))
- (pcase-let* ((`(,uses-cnm . ,fun) (cl--generic-lambda args body)))
+ (pcase-let* ((`(,call-con . ,fun) (cl--generic-lambda args body)))
`(progn
- ,(and (get name 'byte-obsolete-info)
- (or (not (fboundp 'byte-compile-warning-enabled-p))
- (byte-compile-warning-enabled-p 'obsolete name))
- (let* ((obsolete (get name 'byte-obsolete-info)))
- (macroexp-warn-and-return
- (macroexp--obsolete-warning name obsolete "generic function")
- nil)))
;; You could argue that `defmethod' modifies rather than defines the
;; function, so warnings like "not known to be defined" are fair game.
;; But in practice, it's common to use `cl-defmethod'
;; without a previous `cl-defgeneric'.
;; The ",'" is a no-op that pacifies check-declare.
(,'declare-function ,name "")
- (cl-generic-define-method ',name ',(nreverse qualifiers) ',args
- ,uses-cnm ,fun)))))
+ ;; We use #' to quote `name' so as to trigger an
+ ;; obsolescence warning when applicable.
+ (cl-generic-define-method #',name ',(nreverse qualifiers) ',args
+ ',call-con ,fun)))))
(defun cl--generic-member-method (specializers qualifiers methods)
(while
@@ -540,7 +591,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
`(,name ,qualifiers . ,specializers))
;;;###autoload
-(defun cl-generic-define-method (name qualifiers args uses-cnm function)
+(defun cl-generic-define-method (name qualifiers args call-con function)
(pcase-let*
((generic (cl-generic-ensure-function name))
(`(,spec-args . ,_) (cl--generic-split-args args))
@@ -549,7 +600,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
spec-arg (cdr spec-arg)))
spec-args))
(method (cl--generic-make-method
- specializers qualifiers uses-cnm function))
+ specializers qualifiers call-con function))
(mt (cl--generic-method-table generic))
(me (cl--generic-member-method specializers qualifiers mt))
(dispatches (cl--generic-dispatches generic))
@@ -602,11 +653,41 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
(defvar cl--generic-dispatchers (make-hash-table :test #'equal))
+(defvar cl--generic-compiler
+ ;; Don't byte-compile the dispatchers if cl-generic itself is not
+ ;; compiled. Otherwise the byte-compiler and all the code on
+ ;; which it depends needs to be usable before cl-generic is loaded,
+ ;; which imposes a significant burden on the bootstrap.
+ (if (consp (lambda (x) (+ x 1)))
+ (lambda (exp) (eval exp t))
+ ;; But do byte-compile the dispatchers once bootstrap is passed:
+ ;; the performance difference is substantial (like a 5x speedup on
+ ;; the `eieio' elisp-benchmark)).
+ ;; To avoid loading the byte-compiler during the final preload,
+ ;; see `cl--generic-prefill-dispatchers'.
+ #'byte-compile))
+
(defun cl--generic-get-dispatcher (dispatch)
(with-memoization
;; We need `copy-sequence` here because this `dispatch' object might be
;; modified by side-effect in `cl-generic-define-method' (bug#46722).
(gethash (copy-sequence dispatch) cl--generic-dispatchers)
+
+ (when (and purify-flag ;FIXME: Is this a reliable test of the final dump?
+ (eq cl--generic-compiler #'byte-compile))
+ ;; We don't want to preload the byte-compiler!!
+ (error
+ "Missing cl-generic dispatcher in the prefilled cache!
+Missing for: %S
+You might need to add: %S"
+ (mapcar (lambda (x) (if (cl--generic-generalizer-p x)
+ (cl--generic-generalizer-name x)
+ x))
+ dispatch)
+ `(cl--generic-prefill-dispatchers
+ ,@(delq nil (mapcar #'cl--generic-prefill-generalizer-sample
+ dispatch)))))
+
;; (message "cl--generic-get-dispatcher (%S)" dispatch)
(let* ((dispatch-arg (car dispatch))
(generalizers (cdr dispatch))
@@ -646,11 +727,9 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
;; FIXME: For generic functions with a single method (or with 2 methods,
;; one of which always matches), using a tagcode + hash-table is
;; overkill: better just use a `cl-typep' test.
- (byte-compile
+ (funcall
+ cl--generic-compiler
`(lambda (generic dispatches-left methods)
- ;; FIXME: We should find a way to expand `with-memoize' once
- ;; and forall so we don't need `subr-x' when we get here.
- (eval-when-compile (require 'subr-x))
(let ((method-cache (make-hash-table :test #'eql)))
(lambda (,@fixedargs &rest args)
(let ,bindings
@@ -717,29 +796,38 @@ for all those different tags in the method-cache.")
(list (cl--generic-name generic)))
f))))
-(defun cl--generic-no-next-method-function (generic method)
- (lambda (&rest args)
- (apply #'cl-no-next-method generic method args)))
+(oclosure-define (cl--generic-nnm)
+ "Special type for `call-next-method's that just call `no-next-method'.")
(defun cl-generic-call-method (generic method &optional fun)
"Return a function that calls METHOD.
FUN is the function that should be called when METHOD calls
`call-next-method'."
- (if (not (cl--generic-method-uses-cnm method))
- (cl--generic-method-function method)
- (let ((met-fun (cl--generic-method-function method))
- (next (or fun (cl--generic-no-next-method-function
- generic method))))
- (lambda (&rest args)
- (apply met-fun
- ;; FIXME: This sucks: passing just `next' would
- ;; be a lot more efficient than the lambda+apply
- ;; quasi-η, but we need this to implement the
- ;; "if call-next-method is called with no
- ;; arguments, then use the previous arguments".
- (lambda (&rest cnm-args)
- (apply next (or cnm-args args)))
- args)))))
+ (let ((met-fun (cl--generic-method-function method)))
+ (pcase (cl--generic-method-call-con method)
+ ('nil met-fun)
+ ('curried
+ (funcall met-fun (or fun
+ (oclosure-lambda (cl--generic-nnm) (&rest args)
+ (apply #'cl-no-next-method generic method
+ args)))))
+ ;; FIXME: backward compatibility with old convention for `.elc' files
+ ;; compiled before the `curried' convention.
+ (_
+ (lambda (&rest args)
+ (apply met-fun
+ (if fun
+ ;; FIXME: This sucks: passing just `next' would
+ ;; be a lot more efficient than the lambda+apply
+ ;; quasi-η, but we need this to implement the
+ ;; "if call-next-method is called with no
+ ;; arguments, then use the previous arguments".
+ (lambda (&rest cnm-args)
+ (apply fun (or cnm-args args)))
+ (oclosure-lambda (cl--generic-nnm) (&rest cnm-args)
+ (apply #'cl-no-next-method generic method
+ (or cnm-args args))))
+ args))))))
;; Standard CLOS name.
(defalias 'cl-method-qualifiers #'cl--generic-method-qualifiers)
@@ -864,6 +952,20 @@ those methods.")
(if (eq specializer t) (list cl--generic-t-generalizer)
(error "Unknown specializer %S" specializer)))
+(defun cl--generic-prefill-generalizer-sample (x)
+ "Return an example specializer."
+ (if (not (cl--generic-generalizer-p x))
+ x
+ (pcase (cl--generic-generalizer-name x)
+ ('cl--generic-t-generalizer nil)
+ ('cl--generic-head-generalizer '(head 'x))
+ ('cl--generic-eql-generalizer '(eql 'x))
+ ('cl--generic-struct-generalizer 'cl--generic)
+ ('cl--generic-typeof-generalizer 'integer)
+ ('cl--generic-derived-generalizer '(derived-mode c-mode))
+ ('cl--generic-oclosure-generalizer 'oclosure)
+ (_ x))))
+
(eval-when-compile
;; This macro is brittle and only really important in order to be
;; able to preload cl-generic without also preloading the byte-compiler,
@@ -874,11 +976,20 @@ those methods.")
(setq arg-or-context `(&context . ,arg-or-context)))
(unless (fboundp 'cl--generic-get-dispatcher)
(require 'cl-generic))
- (let ((fun (cl--generic-get-dispatcher
- `(,arg-or-context
- ,@(apply #'append
- (mapcar #'cl-generic-generalizers specializers))
- ,cl--generic-t-generalizer))))
+ (let ((fun
+ ;; Let-bind cl--generic-dispatchers so we *re*compute the function
+ ;; from scratch, since the one in the cache may be non-compiled!
+ (let ((cl--generic-dispatchers (make-hash-table))
+ ;; When compiling `cl-generic' during bootstrap, make sure
+ ;; we prefill with compiled dispatchers even though the loaded
+ ;; `cl-generic' is still interpreted.
+ (cl--generic-compiler
+ (if (featurep 'bytecomp) #'byte-compile cl--generic-compiler)))
+ (cl--generic-get-dispatcher
+ `(,arg-or-context
+ ,@(apply #'append
+ (mapcar #'cl-generic-generalizers specializers))
+ ,cl--generic-t-generalizer)))))
;; Recompute dispatch at run-time, since the generalizers may be slightly
;; different (e.g. byte-compiled rather than interpreted).
;; FIXME: There is a risk that the run-time generalizer is not equivalent
@@ -896,36 +1007,9 @@ those methods.")
"Standard support for :after, :before, :around, and `:extra NAME' qualifiers."
(cl--generic-standard-method-combination generic methods))
-(defconst cl--generic-nnm-sample (cl--generic-no-next-method-function t t))
-(defconst cl--generic-cnm-sample
- (funcall (cl--generic-build-combined-method
- nil (list (cl--generic-make-method () () t #'identity)))))
-
(defun cl--generic-isnot-nnm-p (cnm)
"Return non-nil if CNM is the function that calls `cl-no-next-method'."
- ;; ¡Big Gross Ugly Hack!
- ;; `next-method-p' just sucks, we should let it die. But EIEIO did support
- ;; it, and some packages use it, so we need to support it.
- (catch 'found
- (cl-assert (function-equal cnm cl--generic-cnm-sample))
- (if (byte-code-function-p cnm)
- (let ((cnm-constants (aref cnm 2))
- (sample-constants (aref cl--generic-cnm-sample 2)))
- (dotimes (i (length sample-constants))
- (when (function-equal (aref sample-constants i)
- cl--generic-nnm-sample)
- (throw 'found
- (not (function-equal (aref cnm-constants i)
- cl--generic-nnm-sample))))))
- (cl-assert (eq 'closure (car-safe cl--generic-cnm-sample)))
- (let ((cnm-env (cadr cnm)))
- (dolist (vb (cadr cl--generic-cnm-sample))
- (when (function-equal (cdr vb) cl--generic-nnm-sample)
- (throw 'found
- (not (function-equal (cdar cnm-env)
- cl--generic-nnm-sample))))
- (setq cnm-env (cdr cnm-env)))))
- (error "Haven't found no-next-method-sample in cnm-sample")))
+ (not (eq (oclosure-type cnm) 'cl--generic-nnm)))
;;; Define some pre-defined generic functions, used internally.
@@ -1001,9 +1085,12 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
(defun cl--generic-method-info (method)
(let* ((specializers (cl--generic-method-specializers method))
(qualifiers (cl--generic-method-qualifiers method))
- (uses-cnm (cl--generic-method-uses-cnm method))
+ (call-con (cl--generic-method-call-con method))
(function (cl--generic-method-function method))
- (args (help-function-arglist function 'names))
+ (args (help-function-arglist (if (not (eq call-con 'curried))
+ function
+ (funcall function #'ignore))
+ 'names))
(docstring (documentation function))
(qual-string
(if (null qualifiers) ""
@@ -1014,7 +1101,7 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
(let ((split (help-split-fundoc docstring nil)))
(if split (cdr split) docstring))))
(combined-args ()))
- (if uses-cnm (setq args (cdr args)))
+ (if (eq t call-con) (setq args (cdr args)))
(dolist (specializer specializers)
(let ((arg (if (eq '&rest (car args))
(intern (format "arg%d" (length combined-args)))
@@ -1024,6 +1111,19 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
(setq combined-args (append (nreverse combined-args) args))
(list qual-string combined-args doconly)))
+(defun cl--generic-upcase-formal-args (args)
+ (mapcar (lambda (arg)
+ (cond
+ ((symbolp arg)
+ (let ((name (symbol-name arg)))
+ (if (eq ?& (aref name 0)) arg
+ (intern (upcase name)))))
+ ((consp arg)
+ (cons (intern (upcase (symbol-name (car arg))))
+ (cdr arg)))
+ (t arg)))
+ args))
+
(add-hook 'help-fns-describe-function-functions #'cl--generic-describe)
(defun cl--generic-describe (function)
;; Supposedly this is called from help-fns, so help-fns should be loaded at
@@ -1040,9 +1140,20 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
(insert (propertize "Implementations:\n\n" 'face 'bold))
;; Loop over fanciful generics
(dolist (method (cl--generic-method-table generic))
- (let* ((info (cl--generic-method-info method)))
+ (pcase-let*
+ ((`(,qualifiers ,args ,doc) (cl--generic-method-info method)))
;; FIXME: Add hyperlinks for the types as well.
- (insert (format "%s%S" (nth 0 info) (nth 1 info)))
+ (let ((print-quoted nil)
+ (quals (if (length> qualifiers 0)
+ (concat (substring qualifiers
+ 0 (string-match " *\\'"
+ qualifiers))
+ "\n")
+ "")))
+ (insert (format "%s%S"
+ quals
+ (cons function
+ (cl--generic-upcase-formal-args args)))))
(let* ((met-name (cl--generic-load-hist-format
function
(cl--generic-method-qualifiers method)
@@ -1054,7 +1165,7 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
'help-function-def met-name file
'cl-defmethod)
(insert (substitute-command-keys "'.\n"))))
- (insert "\n" (or (nth 2 info) "Undocumented") "\n\n")))))))
+ (insert "\n" (or doc "Undocumented") "\n\n")))))))
(defun cl--generic-specializers-apply-to-type-p (specializers type)
"Return non-nil if a method with SPECIALIZERS applies to TYPE."
@@ -1070,7 +1181,7 @@ MET-NAME is as returned by `cl--generic-load-hist-format'."
(let ((sclass (cl--find-class specializer))
(tclass (cl--find-class type)))
(when (and sclass tclass)
- (member specializer (cl--generic-class-parents tclass))))))
+ (member specializer (cl--class-allparents tclass))))))
(setq applies t)))
applies))
@@ -1199,22 +1310,11 @@ These match if the argument is `eql' to VAL."
;; Use exactly the same code as for `typeof'.
`(if ,name (type-of ,name) 'null))
-(defun cl--generic-class-parents (class)
- (let ((parents ())
- (classes (list class)))
- ;; BFS precedence. FIXME: Use a topological sort.
- (while (let ((class (pop classes)))
- (cl-pushnew (cl--class-name class) parents)
- (setq classes
- (append classes
- (cl--class-parents class)))))
- (nreverse parents)))
-
(defun cl--generic-struct-specializers (tag &rest _)
(and (symbolp tag)
(let ((class (get tag 'cl--class)))
(when (cl-typep class 'cl-structure-class)
- (cl--generic-class-parents class)))))
+ (cl--class-allparents class)))))
(cl-generic-define-generalizer cl--generic-struct-generalizer
50 #'cl--generic-struct-tag
@@ -1263,6 +1363,7 @@ See the full list and their hierarchy in `cl--typeof-types'."
(cl-call-next-method)))
(cl--generic-prefill-dispatchers 0 integer)
+(cl--generic-prefill-dispatchers 1 integer)
(cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
;;; Dispatch on major mode.
@@ -1297,6 +1398,42 @@ Used internally for the (major-mode MODE) context specializers."
(progn (cl-assert (null modes)) mode)
`(derived-mode ,mode . ,modes))))
+;;; Dispatch on OClosure type
+
+;; It would make sense to put this into `oclosure.el' except that when
+;; `oclosure.el' is loaded `cl-defmethod' is not available yet.
+
+(defun cl--generic-oclosure-tag (name &rest _)
+ `(oclosure-type ,name))
+
+(defun cl-generic--oclosure-specializers (tag &rest _)
+ (and (symbolp tag)
+ (let ((class (cl--find-class tag)))
+ (when (cl-typep class 'oclosure--class)
+ (oclosure--class-allparents class)))))
+
+(cl-generic-define-generalizer cl--generic-oclosure-generalizer
+ ;; Give slightly higher priority than the struct specializer, so that
+ ;; for a generic function with methods dispatching structs and on OClosures,
+ ;; we first try `oclosure-type' before `type-of' since `type-of' will return
+ ;; non-nil for an OClosure as well.
+ 51 #'cl--generic-oclosure-tag
+ #'cl-generic--oclosure-specializers)
+
+(cl-defmethod cl-generic-generalizers :extra "oclosure-struct" (type)
+ "Support for dispatch on types defined by `oclosure-define'."
+ (or
+ (when (symbolp type)
+ ;; Use the "cl--struct-class*" (inlinable) functions/macros rather than
+ ;; the "cl-struct-*" variants which aren't inlined, so that dispatch can
+ ;; take place without requiring cl-lib.
+ (let ((class (cl--find-class type)))
+ (and (cl-typep class 'oclosure--class)
+ (list cl--generic-oclosure-generalizer))))
+ (cl-call-next-method)))
+
+(cl--generic-prefill-dispatchers 0 oclosure)
+
;;; Support for unloading.
(cl-defmethod loadhist-unload-element ((x (head cl-defmethod)))
diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el
index 213eecf88d4..fe7e4506d7c 100644
--- a/lisp/emacs-lisp/cl-indent.el
+++ b/lisp/emacs-lisp/cl-indent.el
@@ -378,10 +378,9 @@ instead."
function)
(setq tentative-defun t))
((string-match
- (eval-when-compile
- (concat "\\`\\("
- (regexp-opt '("with" "without" "do"))
- "\\)-"))
+ (concat "\\`\\("
+ (regexp-opt '("with" "without" "do"))
+ "\\)-")
function)
(setq method '(&lambda &body))))))
;; backwards compatibility. Bletch.
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 4e60a3c63d0..3f40ab07605 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -114,7 +114,10 @@ a future Emacs interpreter will be able to use it.")
(defmacro cl-incf (place &optional x)
"Increment PLACE by X (1 by default).
PLACE may be a symbol, or any generalized variable allowed by `setf'.
-The return value is the incremented value of PLACE."
+The return value is the incremented value of PLACE.
+
+If X is specified, it should be an expression that should
+evaluate to a number."
(declare (debug (place &optional form)))
(if (symbolp place)
(list 'setq place (if x (list '+ place x) (list '1+ place)))
@@ -123,7 +126,10 @@ The return value is the incremented value of PLACE."
(defmacro cl-decf (place &optional x)
"Decrement PLACE by X (1 by default).
PLACE may be a symbol, or any generalized variable allowed by `setf'.
-The return value is the decremented value of PLACE."
+The return value is the decremented value of PLACE.
+
+If X is specified, it should be an expression that should
+evaluate to a number."
(declare (debug cl-incf))
(if (symbolp place)
(list 'setq place (if x (list '- place x) (list '1- place)))
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 66c269b6581..6646167b92b 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -394,11 +394,17 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
`(iter-defun ,name ,@(cl--transform-lambda (cons args body) name)))
;; The lambda list for macros is different from that of normal lambdas.
-;; Note that &environment is only allowed as first or last items in the
+
+;; `cl-macro-list' is shared between a few different use cases that
+;; don't all support exactly the same set of special keywords: the
+;; debug spec accepts hence a superset of what the macros
+;; actually support.
+;; For example &environment is only allowed as first or last items in the
;; top level list.
(def-edebug-elem-spec 'cl-macro-list
- '(([&optional "&environment" arg]
+ '(([&optional "&whole" arg] ; Only for compiler-macros or at lower levels.
+ [&optional "&environment" arg] ; Only at top-level.
[&rest cl-macro-arg]
[&optional ["&optional" &rest
&or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
@@ -410,26 +416,12 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
&optional "&allow-other-keys"]]
[&optional ["&aux" &rest
&or (cl-macro-arg &optional def-form) arg]]
- [&optional "&environment" arg]
+ [&optional "&environment" arg] ; Only at top-level.
+ . [&or arg nil] ; Only allowed at lower levels.
)))
(def-edebug-elem-spec 'cl-macro-arg
- '(&or arg cl-macro-list1))
-
-(def-edebug-elem-spec 'cl-macro-list1
- '(([&optional "&whole" arg] ;; only allowed at lower levels
- [&rest cl-macro-arg]
- [&optional ["&optional" &rest
- &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
- [&optional [[&or "&rest" "&body"] cl-macro-arg]]
- [&optional ["&key" [&rest
- [&or ([&or (symbolp cl-macro-arg) arg]
- &optional def-form cl-macro-arg)
- arg]]
- &optional "&allow-other-keys"]]
- [&optional ["&aux" &rest
- &or (cl-macro-arg &optional def-form) arg]]
- . [&or arg nil])))
+ '(&or arg cl-macro-list))
;;;###autoload
(defmacro cl-defmacro (name args &rest body)
@@ -692,7 +684,7 @@ its argument list allows full Common Lisp conventions."
(defmacro cl-destructuring-bind (args expr &rest body)
"Bind the variables in ARGS to the result of EXPR and execute BODY."
(declare (indent 2)
- (debug (&define cl-macro-list1 def-form cl-declarations def-body)))
+ (debug (&define cl-macro-list def-form cl-declarations def-body)))
(let* ((cl--bind-lets nil)
(cl--bind-forms nil)
(cl--bind-defs nil)
@@ -2429,14 +2421,66 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
(append bindings venv))
macroexpand-all-environment))))
(if malformed-bindings
- (macroexp-warn-and-return
- (format-message "Malformed `cl-symbol-macrolet' binding(s): %S"
- (nreverse malformed-bindings))
- expansion)
+ (let ((rev-malformed-bindings (nreverse malformed-bindings)))
+ (macroexp-warn-and-return
+ (format-message "Malformed `cl-symbol-macrolet' binding(s): %S"
+ rev-malformed-bindings)
+ expansion nil nil rev-malformed-bindings))
expansion)))
(unless advised
(advice-remove 'macroexpand #'cl--sm-macroexpand)))))
+;;;###autoload
+(defmacro cl-with-gensyms (names &rest body)
+ "Bind each of NAMES to an uninterned symbol and evaluate BODY."
+ (declare (debug (sexp body)) (indent 1))
+ `(let ,(cl-loop for name in names collect
+ `(,name (gensym (symbol-name ',name))))
+ ,@body))
+
+;;;###autoload
+(defmacro cl-once-only (names &rest body)
+ "Generate code to evaluate each of NAMES just once in BODY.
+
+This macro helps with writing other macros. Each of names is
+either (NAME FORM) or NAME, which latter means (NAME NAME).
+During macroexpansion, each NAME is bound to an uninterned
+symbol. The expansion evaluates each FORM and binds it to the
+corresponding uninterned symbol.
+
+For example, consider this macro:
+
+ (defmacro my-cons (x)
+ (cl-once-only (x)
+ \\=`(cons ,x ,x)))
+
+The call (my-cons (pop y)) will expand to something like this:
+
+ (let ((g1 (pop y)))
+ (cons g1 g1))
+
+The use of `cl-once-only' ensures that the pop is performed only
+once, as intended.
+
+See also `macroexp-let2'."
+ (declare (debug (sexp body)) (indent 1))
+ (setq names (mapcar #'ensure-list names))
+ (let ((our-gensyms (cl-loop for _ in names collect (gensym))))
+ ;; During macroexpansion, obtain a gensym for each NAME.
+ `(let ,(cl-loop for sym in our-gensyms collect `(,sym (gensym)))
+ ;; Evaluate each FORM and bind to the corresponding gensym.
+ ;;
+ ;; We require this explicit call to `list' rather than using
+ ;; (,,@(cl-loop ...)) due to a limitation of Elisp's backquote.
+ `(let ,(list
+ ,@(cl-loop for name in names for gensym in our-gensyms
+ for to-eval = (or (cadr name) (car name))
+ collect ``(,,gensym ,,to-eval)))
+ ;; During macroexpansion, bind each NAME to its gensym.
+ ,(let ,(cl-loop for name in names for gensym in our-gensyms
+ collect `(,(car name) ,gensym))
+ ,@body)))))
+
;;; Multiple values.
;;;###autoload
@@ -2516,7 +2560,7 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
(push x defun-declarations-alist)))
(defun cl--optimize (f _args &rest qualities)
- "Serve 'cl-optimize' in function declarations.
+ "Serve `cl-optimize' in function declarations.
Example:
(defun foo (x)
(declare (cl-optimize (speed 3) (safety 0)))
@@ -2908,18 +2952,10 @@ To see the documentation for a defined struct type, use
(debug
(&define ;Makes top-level form not be wrapped.
[&or symbolp
- (gate
+ (gate ;; FIXME: Why?
symbolp &rest
- [&or symbolp
- (&or [":conc-name" symbolp]
- [":constructor" symbolp &optional cl-lambda-list]
- [":copier" symbolp]
- [":predicate" symbolp]
- [":include" symbolp &rest sexp] ;; Not finished.
- [":print-function" sexp]
- [":type" symbolp]
- [":named"]
- [":initial-offset" natnump])])]
+ [&or (":constructor" &define name &optional cl-lambda-list)
+ sexp])]
[&optional stringp]
;; All the above is for the following def-form.
&rest &or symbolp (symbolp &optional def-form &rest sexp))))
@@ -3118,7 +3154,7 @@ To see the documentation for a defined struct type, use
(macroexp-warn-and-return
(format "Missing value for option `%S' of slot `%s' in struct %s!"
(car (last desc)) slot name)
- 'nil)
+ nil nil nil (car (last desc)))
forms)
(when (and (keywordp (car defaults))
(not (keywordp (car desc))))
@@ -3127,7 +3163,7 @@ To see the documentation for a defined struct type, use
(macroexp-warn-and-return
(format " I'll take `%s' to be an option rather than a default value."
kw)
- 'nil)
+ nil nil nil kw)
forms)
(push kw desc)
(setcar defaults nil))))
@@ -3294,14 +3330,16 @@ the form NAME which is a shorthand for (NAME NAME)."
(funcall orig pred1
(cl--defstruct-predicate t2))))
(funcall orig pred1 pred2))))
-(advice-add 'pcase--mutually-exclusive-p
- :around #'cl--pcase-mutually-exclusive-p)
+(when (fboundp 'advice-add) ;Not available during bootstrap.
+ (advice-add 'pcase--mutually-exclusive-p
+ :around #'cl--pcase-mutually-exclusive-p))
(defun cl-struct-sequence-type (struct-type)
"Return the sequence used to build STRUCT-TYPE.
-STRUCT-TYPE is a symbol naming a struct type. Return `record',
-`vector', or `list' if STRUCT-TYPE is a struct type, nil otherwise."
+STRUCT-TYPE is a symbol naming a struct type. Return values are
+either `vector', `list' or nil (and the latter indicates a
+`record' struct type."
(declare (side-effect-free t) (pure t))
(cl--struct-class-type (cl--struct-get-class struct-type)))
@@ -3366,25 +3404,33 @@ Of course, we really can't know that for sure, so it's just a heuristic."
(boolean . booleanp)
(bool-vector . bool-vector-p)
(buffer . bufferp)
+ (byte-code-function . byte-code-function-p)
(character . natnump)
(char-table . char-table-p)
(command . commandp)
+ (compiled-function . byte-code-function-p)
(hash-table . hash-table-p)
(cons . consp)
(fixnum . fixnump)
(float . floatp)
+ (frame . framep)
(function . functionp)
(integer . integerp)
(keyword . keywordp)
(list . listp)
+ (marker . markerp)
(natnum . natnump)
(number . numberp)
(null . null)
+ (overlay . overlayp)
+ (process . processp)
(real . numberp)
(sequence . sequencep)
+ (subr . subrp)
(string . stringp)
(symbol . symbolp)
(vector . vectorp)
+ (window . windowp)
;; FIXME: Do we really want to consider this a type?
(integer-or-marker . integer-or-marker-p)
))
@@ -3435,16 +3481,19 @@ Of course, we really can't know that for sure, so it's just a heuristic."
(inline-quote (funcall #',(get type 'cl-deftype-satisfies) ,val)))
((and (or 'nil 't) type) (inline-quote ',type))
((and (pred symbolp) type)
- (let* ((name (symbol-name type))
- (namep (intern (concat name "p"))))
- (cond
- ((cl--macroexp-fboundp namep) (inline-quote (funcall #',namep ,val)))
- ((cl--macroexp-fboundp
- (setq namep (intern (concat name "-p"))))
- (inline-quote (funcall #',namep ,val)))
- ((cl--macroexp-fboundp type) (inline-quote (funcall #',type ,val)))
- (t (error "Unknown type %S" type)))))
- (type (error "Bad type spec: %s" type)))))
+ (macroexp-warn-and-return
+ (format-message "Unknown type: %S" type)
+ (let* ((name (symbol-name type))
+ (namep (intern (concat name "p"))))
+ (cond
+ ((cl--macroexp-fboundp namep) (inline-quote (funcall #',namep ,val)))
+ ((cl--macroexp-fboundp
+ (setq namep (intern (concat name "-p"))))
+ (inline-quote (funcall #',namep ,val)))
+ ((cl--macroexp-fboundp type) (inline-quote (funcall #',type ,val)))
+ (t (error "Unknown type %S" type))))
+ nil nil type))
+ (type (error "Bad type spec: %S" type)))))
;;;###autoload
@@ -3500,7 +3549,10 @@ compiler macros are expanded repeatedly until no further expansions are
possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
original function call alone by declaring an initial `&whole foo' parameter
and then returning foo."
- (declare (debug cl-defmacro) (indent 2))
+ ;; Like `cl-defmacro', but with the `&whole' special case.
+ (declare (debug (&define name cl-macro-list
+ cl-declarations-or-string def-body))
+ (indent 2))
(let ((p args) (res nil))
(while (consp p) (push (pop p) res))
(setq args (nconc (nreverse res) (and p (list '&rest p)))))
@@ -3636,7 +3688,7 @@ The type name can then be used in `cl-typecase', `cl-check-type', etc."
(define-inline cl-struct-slot-value (struct-type slot-name inst)
"Return the value of slot SLOT-NAME in INST of STRUCT-TYPE.
-STRUCT and SLOT-NAME are symbols. INST is a structure instance."
+STRUCT-TYPE and SLOT-NAME are symbols. INST is a structure instance."
(declare (side-effect-free t))
(inline-letevals (struct-type slot-name inst)
(inline-quote
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index ef60b266f9e..94f9654b239 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -1,6 +1,6 @@
;;; cl-preloaded.el --- Preloaded part of the CL library -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2021 Free Software Foundation, Inc
+;; Copyright (C) 2015-2022 Free Software Foundation, Inc
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Package: emacs
@@ -53,13 +53,23 @@
(defconst cl--typeof-types
;; Hand made from the source code of `type-of'.
'((integer number number-or-marker atom)
- (symbol atom) (string array sequence atom)
+ (symbol-with-pos symbol atom) (symbol atom) (string array sequence atom)
(cons list sequence)
;; Markers aren't `numberp', yet they are accepted wherever integers are
;; accepted, pretty much.
(marker number-or-marker atom)
(overlay atom) (float number atom) (window-configuration atom)
- (process atom) (window atom) (subr atom) (compiled-function function atom)
+ (process atom) (window atom)
+ ;; FIXME: We'd want to put `function' here, but that's only true
+ ;; for those `subr's which aren't special forms!
+ (subr atom)
+ ;; FIXME: We should probably reverse the order between
+ ;; `compiled-function' and `byte-code-function' since arguably
+ ;; `subr' and also "compiled functions" but not "byte code functions",
+ ;; but it would require changing the value returned by `type-of' for
+ ;; byte code objects, which risks breaking existing code, which doesn't
+ ;; seem worth the trouble.
+ (compiled-function byte-code-function function atom)
(module-function function atom)
(buffer atom) (char-table array sequence atom)
(bool-vector array sequence atom)
@@ -136,13 +146,13 @@ supertypes from the most specific to least specific.")
(while (recordp parent)
(add-to-list (cl--struct-class-children-sym parent) tag)
;; Only register ourselves as a child of the leftmost parent since structs
- ;; can only only have one parent.
+ ;; can only have one parent.
(setq parent (car (cl--struct-class-parents parent)))))
;;;###autoload
(defun cl-struct-define (name docstring parent type named slots children-sym
tag print)
- (cl-check-type name cl--struct-name)
+ (cl-check-type name (satisfies cl--struct-name-p))
(unless type
;; Legacy defstruct, using tagged vectors. Enable backward compatibility.
(cl-old-struct-compat-mode 1))
@@ -305,6 +315,17 @@ supertypes from the most specific to least specific.")
(cl-assert (cl--class-p (cl--find-class 'cl-structure-class)))
(cl-assert (cl--class-p (cl--find-class 'cl-structure-object)))
+(defun cl--class-allparents (class)
+ (let ((parents ())
+ (classes (list class)))
+ ;; BFS precedence. FIXME: Use a topological sort.
+ (while (let ((class (pop classes)))
+ (cl-pushnew (cl--class-name class) parents)
+ (setq classes
+ (append classes
+ (cl--class-parents class)))))
+ (nreverse parents)))
+
;; Make sure functions defined with cl-defsubst can be inlined even in
;; packages which do not require CL. We don't put an autoload cookie
;; directly on that function, since those cookies only go to cl-loaddefs.
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 2aade140e25..30d7e6525a4 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -221,26 +221,11 @@ into a button whose action shows the function's disassembly.")
'byte-code-function object)))))
(princ ")" stream))
-;; This belongs in nadvice.el, of course, but some load-ordering issues make it
-;; complicated: cl-generic uses macros from cl-macs and cl-macs uses advice-add
-;; from nadvice, so nadvice needs to be loaded before cl-generic and hence
-;; can't use cl-defmethod.
-(cl-defmethod cl-print-object :extra "nadvice"
- ((object compiled-function) stream)
- (if (not (advice--p object))
- (cl-call-next-method)
- (princ "#f(advice-wrapper " stream)
- (when (fboundp 'advice--where)
- (princ (advice--where object) stream)
- (princ " " stream))
- (cl-print-object (advice--cdr object) stream)
- (princ " " stream)
- (cl-print-object (advice--car object) stream)
- (let ((props (advice--props object)))
- (when props
- (princ " " stream)
- (cl-print-object props stream)))
- (princ ")" stream)))
+;; This belongs in oclosure.el, of course, but some load-ordering issues make it
+;; complicated.
+(cl-defmethod cl-print-object ((object accessor) stream)
+ ;; FIXME: η-reduce!
+ (oclosure--accessor-cl-print object stream))
(cl-defmethod cl-print-object ((object cl-structure-object) stream)
(if (and cl-print--depth (natnump print-level)
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index ad956dabd8a..6451e34c42f 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
-;; Author: Andrea Corallo <akrl@sdf.com>
+;; Author: Andrea Corallo <akrl@sdf.org>
;; Keywords: lisp
;; Package: emacs
@@ -454,18 +454,20 @@ Return them as multiple value."
(declare (debug (range-body))
(indent defun))
`(with-comp-cstr-accessors
- (when-let ((r1 (range ,src1))
- (r2 (range ,src2)))
- (let* ((l1 (comp-cstr-smallest-in-range r1))
- (l2 (comp-cstr-smallest-in-range r2))
- (h1 (comp-cstr-greatest-in-range r1))
- (h2 (comp-cstr-greatest-in-range r2)))
- (setf (typeset ,dst) (when (cl-some (lambda (x)
- (comp-subtype-p 'float x))
- (append (typeset src1)
- (typeset src2)))
- '(float))
- (range ,dst) ,@range-body)))))
+ (if (or (neg src1) (neg src2))
+ (setf (typeset ,dst) '(number))
+ (when-let ((r1 (range ,src1))
+ (r2 (range ,src2)))
+ (let* ((l1 (comp-cstr-smallest-in-range r1))
+ (l2 (comp-cstr-smallest-in-range r2))
+ (h1 (comp-cstr-greatest-in-range r1))
+ (h2 (comp-cstr-greatest-in-range r2)))
+ (setf (typeset ,dst) (when (cl-some (lambda (x)
+ (comp-subtype-p 'float x))
+ (append (typeset src1)
+ (typeset src2)))
+ '(float))
+ (range ,dst) ,@range-body))))))
(defun comp-cstr-add-2 (dst src1 src2)
"Sum SRC1 and SRC2 into DST."
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index cf2dbd62f11..73285e0f24d 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
-;; Author: Andrea Corallo <akrl@sdf.com>
+;; Author: Andrea Corallo <akrl@sdf.org>
;; Keywords: lisp
;; Package: emacs
@@ -63,7 +63,7 @@ This is intended for debugging the compiler itself.
2 emit debug symbols and dump pseudo C code.
3 emit debug symbols and dump: pseudo C code, GCC intermediate
passes and libgccjit log file."
- :type 'integer
+ :type 'natnum
:safe #'natnump
:version "28.1")
@@ -74,7 +74,7 @@ This is intended for debugging the compiler itself.
1 final LIMPLE is logged.
2 LAP, final LIMPLE, and some pass info are logged.
3 max verbosity."
- :type 'integer
+ :type 'natnum
:risky t
:version "28.1")
@@ -111,7 +111,7 @@ during bootstrap."
"Default number of subprocesses used for async native compilation.
Value of zero means to use half the number of the CPU's execution units,
or one if there's just one execution unit."
- :type 'integer
+ :type 'natnum
:risky t
:version "28.1")
@@ -238,7 +238,7 @@ native compilation runs.")
(defvar comp-curr-allocation-class 'd-default
"Current allocation class.
-Can be one of: 'd-default', 'd-impure' or 'd-ephemeral'. See `comp-ctxt'.")
+Can be one of: `d-default', `d-impure' or `d-ephemeral'. See `comp-ctxt'.")
(defconst comp-passes '(comp-spill-lap
comp-limplify
@@ -475,15 +475,15 @@ Useful to hook into pass checkers.")
(one-window-p (function (&optional t t) boolean))
(overlayp (function (t) boolean))
(parse-colon-path (function (string) cons))
- (plist-get (function (list t) t))
- (plist-member (function (list t) list))
+ (plist-get (function (list t &optional t) t))
+ (plist-member (function (list t &optional t) list))
(point (function () integer))
(point-marker (function () marker))
(point-max (function () integer))
(point-min (function () integer))
(preceding-char (function () fixnum))
(previous-window (function (&optional window t t) window))
- (prin1-to-string (function (t &optional t) string))
+ (prin1-to-string (function (t &optional t t) string))
(processp (function (t) boolean))
(proper-list-p (function (t) integer))
(propertize (function (string &rest t) string))
@@ -898,6 +898,8 @@ non local exit (ends with an `unreachable' insn)."))
:documentation "Doc string.")
(int-spec nil :type list
:documentation "Interactive form.")
+ (command-modes nil :type list
+ :documentation "Command modes.")
(lap () :type list
:documentation "LAP assembly representation.")
(ssa-status nil :type symbol
@@ -942,7 +944,7 @@ CFG is mutated by a pass.")
:documentation "Unique id when in SSA form.")
(slot nil :type (or fixnum symbol)
:documentation "Slot number in the array if a number or
- 'scratch' for scratch slot."))
+ `scratch' for scratch slot."))
(defun comp-mvar-type-hint-match-p (mvar type-hint)
"Match MVAR against TYPE-HINT.
@@ -1021,7 +1023,7 @@ To be used by all entry points."
(defun comp-alloc-class-to-container (alloc-class)
"Given ALLOC-CLASS, return the data container for the current context.
-Assume allocation class 'd-default as default."
+Assume allocation class `d-default' as default."
(cl-struct-slot-value 'comp-ctxt (or alloc-class 'd-default) comp-ctxt))
(defsubst comp-add-const-to-relocs (obj)
@@ -1243,6 +1245,7 @@ clashes."
:c-name c-name
:doc (documentation f t)
:int-spec (interactive-form f)
+ :command-modes (command-modes f)
:speed (comp-spill-speed function-name)
:pure (comp-spill-decl-spec function-name
'pure))))
@@ -1282,10 +1285,12 @@ clashes."
(make-comp-func-l :c-name c-name
:doc (documentation form t)
:int-spec (interactive-form form)
+ :command-modes (command-modes form)
:speed (comp-ctxt-speed comp-ctxt))
(make-comp-func-d :c-name c-name
:doc (documentation form t)
:int-spec (interactive-form form)
+ :command-modes (command-modes form)
:speed (comp-ctxt-speed comp-ctxt)))))
(let ((lap (byte-to-native-lambda-lap
(gethash (aref byte-code 1)
@@ -1327,6 +1332,7 @@ clashes."
(comp-func-byte-func func) byte-func
(comp-func-doc func) (documentation byte-func t)
(comp-func-int-spec func) (interactive-form byte-func)
+ (comp-func-command-modes func) (command-modes byte-func)
(comp-func-c-name func) c-name
(comp-func-lap func) lap
(comp-func-frame-size func) (comp-byte-frame-size byte-func)
@@ -1767,6 +1773,7 @@ This is responsible for generating the proper stack adjustment, when known,
and the annotation emission."
(declare (debug (body))
(indent defun))
+ (declare-function comp-body-eff nil (body op-name sp-delta))
`(pcase op
,@(cl-loop for (op . body) in cases
for sp-delta = (gethash op comp-op-stack-info)
@@ -1945,7 +1952,6 @@ and the annotation emission."
(byte-condition-case) ;; Obsolete
(byte-temp-output-buffer-setup-OBSOLETE)
(byte-temp-output-buffer-show-OBSOLETE)
- (byte-unbind-all) ;; Obsolete
(byte-set-marker auto)
(byte-match-beginning auto)
(byte-match-end auto)
@@ -2079,7 +2085,8 @@ and the annotation emission."
(i (hash-table-count h)))
(puthash i (comp-func-doc f) h)
i)
- (comp-func-int-spec f)))
+ (comp-func-int-spec f)
+ (comp-func-command-modes f)))
;; This is the compilation unit it-self passed as
;; parameter.
(make-comp-mvar :slot 0))))))
@@ -2122,7 +2129,8 @@ These are stored in the reloc data array."
(i (hash-table-count h)))
(puthash i (comp-func-doc func) h)
i)
- (comp-func-int-spec func)))
+ (comp-func-int-spec func)
+ (comp-func-command-modes func)))
;; This is the compilation unit it-self passed as
;; parameter.
(make-comp-mvar :slot 0)))))
@@ -2625,8 +2633,8 @@ TARGET-BB-SYM is the symbol name of the target block."
do (comp-emit-call-cstr target insn-cell cstr)))))))
(defun comp-add-cstrs (_)
- "Rewrite conditional branches adding appropriate 'assume' insns.
-This is introducing and placing 'assume' insns in use by fwprop
+ "Rewrite conditional branches adding appropriate `assume' insns.
+This is introducing and placing `assume' insns in use by fwprop
to propagate conditional branch test information on target basic
blocks."
(maphash (lambda (_ f)
@@ -3474,7 +3482,7 @@ Return the list of m-var ids nuked."
(defun comp-remove-type-hints-func ()
"Remove type hints from the current function.
-These are substituted with a normal 'set' op."
+These are substituted with a normal `set' op."
(cl-loop
for b being each hash-value of (comp-func-blocks comp-func)
do (comp-loop-insn-in-block b
@@ -3570,7 +3578,7 @@ Update all insn accordingly."
;; Symbols imported by C inlined functions. We do this here because
;; is better to add all objs to the relocation containers before we
;; compacting them.
- (mapc #'comp-add-const-to-relocs '(nil t consp listp))
+ (mapc #'comp-add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
(let* ((d-default (comp-ctxt-d-default comp-ctxt))
(d-default-idx (comp-data-container-idx d-default))
@@ -3918,22 +3926,36 @@ display a message."
(file-newer-than-file-p
source-file (comp-el-to-eln-filename source-file)))
do (let* ((expr `((require 'comp)
- ,(when (boundp 'backtrace-line-length)
- `(setf backtrace-line-length ,backtrace-line-length))
- (setf comp-file-preloaded-p ,comp-file-preloaded-p
- native-compile-target-directory ,native-compile-target-directory
- native-comp-speed ,native-comp-speed
- native-comp-debug ,native-comp-debug
- native-comp-verbose ,native-comp-verbose
- comp-libgccjit-reproducer ,comp-libgccjit-reproducer
- comp-async-compilation t
- native-comp-eln-load-path ',native-comp-eln-load-path
- native-comp-compiler-options
- ',native-comp-compiler-options
- native-comp-driver-options
- ',native-comp-driver-options
- load-path ',load-path
- warning-fill-column most-positive-fixnum)
+ (setq comp-async-compilation t)
+ (setq warning-fill-column most-positive-fixnum)
+ ,(let ((set (list 'setq)))
+ (dolist (var '(comp-file-preloaded-p
+ native-compile-target-directory
+ native-comp-speed
+ native-comp-debug
+ native-comp-verbose
+ comp-libgccjit-reproducer
+ native-comp-eln-load-path
+ native-comp-compiler-options
+ native-comp-driver-options
+ load-path
+ backtrace-line-length
+ ;; package-load-list
+ ;; package-user-dir
+ ;; package-directory-list
+ ))
+ (when (boundp var)
+ (push var set)
+ (push `',(symbol-value var) set)))
+ (nreverse set))
+ ;; FIXME: Activating all packages would align the
+ ;; functionality offered with what is usually done
+ ;; for ELPA packages (and thus fix some compilation
+ ;; issues with some ELPA packages), but it's too
+ ;; blunt an instrument (e.g. we don't even know if
+ ;; we're compiling such an ELPA package at
+ ;; this point).
+ ;;(package-activate-all)
,native-comp-async-env-modifier-form
(message "Compiling %s..." ,source-file)
(comp--native-compile ,source-file ,(and load t))))
@@ -3986,7 +4008,7 @@ display a message."
(run-hooks 'native-comp-async-all-done-hook)
(with-current-buffer (get-buffer-create comp-async-buffer-name)
(save-excursion
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(goto-char (point-max))
(insert "Compilation finished.\n"))))
;; `comp-deferred-pending-h' should be empty at this stage.
@@ -4006,56 +4028,71 @@ the deferred compilation mechanism."
(signal 'native-compiler-error
(list "Not a function symbol or file" function-or-file)))
(catch 'no-native-compile
- (let* ((data function-or-file)
+ (let* ((print-symbols-bare t)
+ (max-specpdl-size (max max-specpdl-size 5000))
+ (data function-or-file)
(comp-native-compiling t)
(byte-native-qualities nil)
+ (symbols-with-pos-enabled t)
;; Have byte compiler signal an error when compilation fails.
(byte-compile-debug t)
(comp-ctxt (make-comp-ctxt :output output
:with-late-load with-late-load)))
(comp-log "\n \n" 1)
- (condition-case err
- (cl-loop
- with report = nil
- for t0 = (current-time)
- for pass in comp-passes
- unless (memq pass comp-disabled-passes)
- do
- (comp-log (format "(%s) Running pass %s:\n"
- function-or-file pass)
- 2)
- (setf data (funcall pass data))
- (push (cons pass (float-time (time-since t0))) report)
- (cl-loop for f in (alist-get pass comp-post-pass-hooks)
- do (funcall f data))
- finally
- (when comp-log-time-report
- (comp-log (format "Done compiling %s" data) 0)
- (cl-loop for (pass . time) in (reverse report)
- do (comp-log (format "Pass %s took: %fs." pass time) 0))))
- (native-compiler-skip)
- (t
- (let ((err-val (cdr err)))
- ;; If we are doing an async native compilation print the
- ;; error in the correct format so is parsable and abort.
- (if (and comp-async-compilation
- (not (eq (car err) 'native-compiler-error)))
- (progn
- (message (if err-val
- "%s: Error: %s %s"
- "%s: Error %s")
- function-or-file
- (get (car err) 'error-message)
- (car-safe err-val))
- (kill-emacs -1))
- ;; Otherwise re-signal it adding the compilation input.
- (signal (car err) (if (consp err-val)
- (cons function-or-file err-val)
- (list function-or-file err-val)))))))
- (if (stringp function-or-file)
- data
- ;; So we return the compiled function.
- (native-elisp-load data)))))
+ (unwind-protect
+ (progn
+ (condition-case err
+ (cl-loop
+ with report = nil
+ for t0 = (current-time)
+ for pass in comp-passes
+ unless (memq pass comp-disabled-passes)
+ do
+ (comp-log (format "(%s) Running pass %s:\n"
+ function-or-file pass)
+ 2)
+ (setf data (funcall pass data))
+ (push (cons pass (float-time (time-since t0))) report)
+ (cl-loop for f in (alist-get pass comp-post-pass-hooks)
+ do (funcall f data))
+ finally
+ (when comp-log-time-report
+ (comp-log (format "Done compiling %s" data) 0)
+ (cl-loop for (pass . time) in (reverse report)
+ do (comp-log (format "Pass %s took: %fs."
+ pass time) 0))))
+ (native-compiler-skip)
+ (t
+ (let ((err-val (cdr err)))
+ ;; If we are doing an async native compilation print the
+ ;; error in the correct format so is parsable and abort.
+ (if (and comp-async-compilation
+ (not (eq (car err) 'native-compiler-error)))
+ (progn
+ (message (if err-val
+ "%s: Error: %s %s"
+ "%s: Error %s")
+ function-or-file
+ (get (car err) 'error-message)
+ (car-safe err-val))
+ (kill-emacs -1))
+ ;; Otherwise re-signal it adding the compilation input.
+ (signal (car err) (if (consp err-val)
+ (cons function-or-file err-val)
+ (list function-or-file err-val)))))))
+ (if (stringp function-or-file)
+ data
+ ;; So we return the compiled function.
+ (native-elisp-load data)))
+ ;; We may have created a temporary file when we're being
+ ;; called with something other than a file as the argument.
+ ;; Delete it.
+ (when (and (not (stringp function-or-file))
+ (not output)
+ comp-ctxt
+ (comp-ctxt-output comp-ctxt)
+ (file-exists-p (comp-ctxt-output comp-ctxt)))
+ (delete-file (comp-ctxt-output comp-ctxt)))))))
(defun native-compile-async-skip-p (file load selector)
"Return non-nil if FILE's compilation should be skipped.
@@ -4077,6 +4114,7 @@ LOAD and SELECTOR work as described in `native--compile-async'."
native-comp-deferred-compilation-deny-list))))
(defun native--compile-async (files &optional recursively load selector)
+ ;; BEWARE, this function is also called directly from C.
"Compile FILES asynchronously.
FILES is one filename or a list of filenames or directories.
@@ -4110,16 +4148,17 @@ bytecode definition was not changed in the meantime)."
(unless (listp files)
(setf files (list files)))
(let (file-list)
- (dolist (path files)
- (cond ((file-directory-p path)
+ (dolist (file-or-dir files)
+ (cond ((file-directory-p file-or-dir)
(dolist (file (if recursively
(directory-files-recursively
- path comp-valid-source-re)
- (directory-files path t comp-valid-source-re)))
+ file-or-dir comp-valid-source-re)
+ (directory-files file-or-dir
+ t comp-valid-source-re)))
(push file file-list)))
- ((file-exists-p path) (push path file-list))
+ ((file-exists-p file-or-dir) (push file-or-dir file-list))
(t (signal 'native-compiler-error
- (list "Path not a file nor directory" path)))))
+ (list "Not a file nor directory" file-or-dir)))))
(dolist (file file-list)
(if-let ((entry (cl-find file comp-files-queue :key #'car :test #'string=)))
;; Most likely the byte-compiler has requested a deferred
@@ -4195,9 +4234,9 @@ last directory in `native-comp-eln-load-path')."
if (or (null byte+native-compile)
(cl-notany (lambda (re) (string-match re file))
native-comp-bootstrap-deny-list))
- do (comp--native-compile file)
+ collect (comp--native-compile file)
else
- do (byte-compile-file file))))
+ collect (byte-compile-file file))))
;;;###autoload
(defun batch-byte+native-compile ()
@@ -4206,17 +4245,25 @@ Generate .elc files in addition to the .eln files.
Force the produced .eln to be outputted in the eln system
directory (the last entry in `native-comp-eln-load-path') unless
`native-compile-target-directory' is non-nil. If the environment
-variable 'NATIVE_DISABLED' is set, only byte compile."
+variable \"NATIVE_DISABLED\" is set, only byte compile."
(comp-ensure-native-compiler)
(if (equal (getenv "NATIVE_DISABLED") "1")
(batch-byte-compile)
(cl-assert (length= command-line-args-left 1))
- (let ((byte+native-compile t)
- (byte-to-native-output-file nil))
- (batch-native-compile)
- (pcase byte-to-native-output-file
- (`(,tempfile . ,target-file)
- (rename-file tempfile target-file t))))))
+ (let* ((byte+native-compile t)
+ (byte-to-native-output-buffer-file nil)
+ (eln-file (car (batch-native-compile))))
+ (pcase byte-to-native-output-buffer-file
+ (`(,temp-buffer . ,target-file)
+ (unwind-protect
+ (progn
+ (byte-write-target-file temp-buffer target-file)
+ ;; Touch the .eln in order to have it older than the
+ ;; corresponding .elc.
+ (when (stringp eln-file)
+ (set-file-times eln-file)))
+ (kill-buffer temp-buffer))))
+ (setq command-line-args-left (cdr command-line-args-left)))))
;;;###autoload
(defun native-compile-async (files &optional recursively load selector)
@@ -4241,6 +4288,30 @@ of (commands) to run simultaneously."
(let ((load (not (not load))))
(native--compile-async files recursively load selector)))
+(defun native-compile-prune-cache ()
+ "Remove .eln files that aren't applicable to the current Emacs invocation."
+ (interactive)
+ (dolist (dir native-comp-eln-load-path)
+ ;; If a directory is non absolute it is assumed to be relative to
+ ;; `invocation-directory'.
+ (setq dir (expand-file-name dir invocation-directory))
+ (when (file-exists-p dir)
+ (dolist (subdir (directory-files dir t))
+ (when (and (file-directory-p subdir)
+ (file-writable-p subdir)
+ (not (equal (file-name-nondirectory
+ (directory-file-name subdir))
+ comp-native-version-dir)))
+ (message "Deleting %s..." subdir)
+ ;; We're being overly cautious here -- there shouldn't be
+ ;; anything but .eln files in these directories.
+ (dolist (eln (directory-files subdir t "\\.eln\\(\\.tmp\\)?\\'"))
+ (when (file-writable-p eln)
+ (delete-file eln)))
+ (when (directory-empty-p subdir)
+ (delete-directory subdir))))))
+ (message "Cache cleared"))
+
(provide 'comp)
;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
index 09c6ded2950..e5087672ae7 100644
--- a/lisp/emacs-lisp/copyright.el
+++ b/lisp/emacs-lisp/copyright.el
@@ -150,9 +150,11 @@ This function sets the match data that `copyright-update-year' uses."
(when (copyright-re-search regexp (copyright-limit) t)
;; We may accidentally have landed in the middle of a
;; copyright line, so re-perform the search without the
- ;; search. (Otherwise we may be inserting the new year in the
+ ;; limit. (Otherwise we may be inserting the new year in the
;; middle of the list of years.)
- (goto-char (match-beginning 0))
+ (if copyright-at-end-flag
+ (goto-char (match-end 0))
+ (goto-char (match-beginning 0)))
(copyright-re-search regexp nil t)))))
(defun copyright-find-end ()
@@ -311,7 +313,7 @@ independently replaces consecutive years with a range."
(> prev-year first-year))
(goto-char range-end)
(delete-region range-start range-end)
- (insert (format "%c%d" sep prev-year))
+ (insert (format "-%d" prev-year))
(goto-char p))
(setq first-year year
range-start (point)))))
diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el
index f3e1981732c..9d9c91e510e 100644
--- a/lisp/emacs-lisp/crm.el
+++ b/lisp/emacs-lisp/crm.el
@@ -87,28 +87,23 @@
It should be a regexp that does not match the list of completion candidates.
The default value is `crm-default-separator'.")
-(defvar crm-local-completion-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-completion-map)
- (define-key map [remap minibuffer-complete] #'crm-complete)
- (define-key map [remap minibuffer-complete-word] #'crm-complete-word)
- (define-key map [remap minibuffer-completion-help] #'crm-completion-help)
- map)
- "Local keymap for minibuffer multiple input with completion.
-Analog of `minibuffer-local-completion-map'.")
-
-(defvar crm-local-must-match-map
- (let ((map (make-sparse-keymap)))
- ;; We'd want to have multiple inheritance here.
- (set-keymap-parent map minibuffer-local-must-match-map)
- (define-key map [remap minibuffer-complete] #'crm-complete)
- (define-key map [remap minibuffer-complete-word] #'crm-complete-word)
- (define-key map [remap minibuffer-completion-help] #'crm-completion-help)
- (define-key map [remap minibuffer-complete-and-exit]
- #'crm-complete-and-exit)
- map)
- "Local keymap for minibuffer multiple input with exact match completion.
-Analog of `minibuffer-local-must-match-map' for crm.")
+(defvar-keymap crm-local-completion-map
+ :doc "Local keymap for minibuffer multiple input with completion.
+Analog of `minibuffer-local-completion-map'."
+ :parent minibuffer-local-completion-map
+ "<remap> <minibuffer-complete>" #'crm-complete
+ "<remap> <minibuffer-complete-word>" #'crm-complete-word
+ "<remap> <minibuffer-completion-help>" #'crm-completion-help)
+
+(defvar-keymap crm-local-must-match-map
+ :doc "Local keymap for minibuffer multiple input with exact match completion.
+Analog of `minibuffer-local-must-match-map' for crm."
+ ;; We'd want to have multiple inheritance here.
+ :parent minibuffer-local-must-match-map
+ "<remap> <minibuffer-complete>" #'crm-complete
+ "<remap> <minibuffer-complete-word>" #'crm-complete-word
+ "<remap> <minibuffer-completion-help>" #'crm-completion-help
+ "<remap> <minibuffer-complete-and-exit>" #'crm-complete-and-exit)
(defvar crm-completion-table nil
"An alist whose elements' cars are strings, or an obarray.
@@ -254,6 +249,23 @@ with empty strings removed."
'crm--choose-completion-string nil 'local)
(setq-local minibuffer-completion-table #'crm--collection-fn)
(setq-local minibuffer-completion-predicate predicate)
+ (setq-local completion-list-insert-choice-function
+ (lambda (start end choice)
+ (if (and (stringp start) (stringp end))
+ (let* ((beg (save-excursion
+ (goto-char (minibuffer-prompt-end))
+ (or (search-forward start nil t)
+ (search-forward-regexp crm-separator nil t)
+ (minibuffer-prompt-end))))
+ (end (save-excursion
+ (goto-char (point-max))
+ (or (search-backward end nil t)
+ (progn
+ (goto-char beg)
+ (search-forward-regexp crm-separator nil t))
+ (point-max)))))
+ (completion--replace beg end choice))
+ (completion--replace start end choice))))
;; see completing_read in src/minibuf.c
(setq-local minibuffer-completion-confirm
(unless (eq require-match t) require-match))
diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
new file mode 100644
index 00000000000..a301c73017e
--- /dev/null
+++ b/lisp/emacs-lisp/debug-early.el
@@ -0,0 +1,97 @@
+;;; debug-early.el --- Dump a Lisp backtrace without frills -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Alan Mackenzie <acm@muc.de>
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: internal, backtrace, bootstrap.
+;; Package: emacs
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file dumps a backtrace on stderr when an error is thrown. It
+;; has no dependencies on any Lisp libraries and is thus used for
+;; generating backtraces for bugs in the early parts of bootstrapping.
+;; It is also always used in batch model. It was introduced in Emacs
+;; 29, before which there was no backtrace available during early
+;; bootstrap.
+
+;;; Code:
+
+(defalias 'debug-early-backtrace
+ #'(lambda ()
+ "Print a trace of Lisp function calls currently active.
+The output stream used is the value of `standard-output'.
+
+This is a simplified version of the standard `backtrace'
+function, intended for use in debugging the early parts
+of the build process."
+ (princ "\n")
+ (let ((print-escape-newlines t)
+ (print-escape-control-characters t)
+ (print-escape-nonascii t)
+ (prin1 (if (and (fboundp 'cl-prin1)
+ ;; If we're being called while
+ ;; bootstrapping, we won't be able to load
+ ;; cl-print.
+ (require 'cl-print nil t))
+ #'cl-prin1
+ #'prin1)))
+ (mapbacktrace
+ #'(lambda (evald func args _flags)
+ (let ((args args))
+ (if evald
+ (progn
+ (princ " ")
+ (funcall prin1 func)
+ (princ "("))
+ (progn
+ (princ " (")
+ (setq args (cons func args))))
+ (if args
+ (while (progn
+ (funcall prin1 (car args))
+ (setq args (cdr args)))
+ (princ " ")))
+ (princ ")\n")))))))
+
+(defalias 'debug-early
+ #'(lambda (&rest args)
+ "Print an error message with a backtrace of active Lisp function calls.
+The output stream used is the value of `standard-output'.
+
+The Emacs core calls this function after an error has been
+signaled, and supplies two ARGS. These are the symbol
+`error' (which is ignored) and a cons of the error symbol and the
+error data.
+
+`debug-early' is a simplified version of `debug', and is
+available during the early parts of the build process. It is
+superseded by `debug' after enough Lisp has been loaded to
+support the latter, except in batch mode which always uses
+`debug-early'.
+
+\(In versions of Emacs prior to Emacs 29, no backtrace was
+available before `debug' was usable.)"
+ (princ "\nError: ")
+ (prin1 (car (car (cdr args)))) ; The error symbol.
+ (princ " ")
+ (prin1 (cdr (car (cdr args)))) ; The error data.
+ (debug-early-backtrace)))
+
+;;; debug-early.el ends here.
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 46b0306d64f..460057b3afd 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -90,6 +90,11 @@ The value used here is passed to `quit-restore-window'."
:group 'debugger
:version "24.3")
+(defcustom debug-allow-recursive-debug nil
+ "If non-nil, erroring in debug and edebug won't recursively debug."
+ :type 'boolean
+ :version "29.1")
+
(defvar debugger-step-after-exit nil
"Non-nil means \"single-step\" after the debugger exits.")
@@ -300,16 +305,15 @@ the debugger will not be entered."
(set-buffer debugger-old-buffer)))
;; Forget debugger window, it won't be back (Bug#17882).
(setq debugger-previous-window nil))
- ;; Restore previous state of debugger-buffer in case we were
- ;; in a recursive invocation of the debugger, otherwise just
- ;; erase the buffer.
+ ;; Restore previous state of debugger-buffer in case we
+ ;; were in a recursive invocation of the debugger,
+ ;; otherwise just exit (after changing the mode, since we
+ ;; can't interact with the buffer in the same way).
(when (buffer-live-p debugger-buffer)
(with-current-buffer debugger-buffer
(if debugger-previous-state
(debugger--restore-buffer-state debugger-previous-state)
- (setq backtrace-insert-header-function nil)
- (setq backtrace-frames nil)
- (backtrace-print))))
+ (backtrace-mode))))
(with-timeout-unsuspend debugger-with-timeout-suspend)
(set-match-data debugger-outer-match-data)))
(setq debug-on-next-call debugger-step-after-exit)
@@ -534,62 +538,75 @@ The environment used is the one when entering the activation frame at point."
(error 0)))) ;; If on first line.
(base (debugger--backtrace-base)))
(debugger-env-macro
- (let ((val (backtrace-eval exp nframe base)))
- (prog1
- (debugger--print val t)
- (let ((str (eval-expression-print-format val)))
- (if str (princ str t))))))))
+ (let* ((errored nil)
+ (val (if debug-allow-recursive-debug
+ (backtrace-eval exp nframe base)
+ (condition-case err
+ (backtrace-eval exp nframe base)
+ (error (setq errored
+ (format "%s: %s"
+ (get (car err) 'error-message)
+ (car (cdr err)))))))))
+ (if errored
+ (progn
+ (message "Error: %s" errored)
+ nil)
+ (prog1
+ (debugger--print val t)
+ (let ((str (eval-expression-print-format val)))
+ (if str (princ str t)))))))))
(define-obsolete-function-alias 'debugger-toggle-locals
'backtrace-toggle-locals "28.1")
-(defvar debugger-mode-map
- (let ((map (make-keymap)))
- (set-keymap-parent map backtrace-mode-map)
- (define-key map "b" 'debugger-frame)
- (define-key map "c" 'debugger-continue)
- (define-key map "j" 'debugger-jump)
- (define-key map "r" 'debugger-return-value)
- (define-key map "u" 'debugger-frame-clear)
- (define-key map "d" 'debugger-step-through)
- (define-key map "l" 'debugger-list-functions)
- (define-key map "q" 'debugger-quit)
- (define-key map "e" 'debugger-eval-expression)
- (define-key map "R" 'debugger-record-expression)
- (define-key map [mouse-2] 'push-button)
- (easy-menu-define nil map ""
- '("Debugger"
- ["Step through" debugger-step-through
- :help "Proceed, stepping through subexpressions of this expression"]
- ["Continue" debugger-continue
- :help "Continue, evaluating this expression without stopping"]
- ["Jump" debugger-jump
- :help "Continue to exit from this frame, with all debug-on-entry suspended"]
- ["Eval Expression..." debugger-eval-expression
- :help "Eval an expression, in an environment like that outside the debugger"]
- ["Display and Record Expression" debugger-record-expression
- :help "Display a variable's value and record it in `*Backtrace-record*' buffer"]
- ["Return value..." debugger-return-value
- :help "Continue, specifying value to return."]
- "--"
- ["Debug frame" debugger-frame
- :help "Request entry to debugger when this frame exits"]
- ["Cancel debug frame" debugger-frame-clear
- :help "Do not enter debugger when this frame exits"]
- ["List debug on entry functions" debugger-list-functions
- :help "Display a list of all the functions now set to debug on entry"]
- "--"
- ["Next Line" next-line
- :help "Move cursor down"]
- ["Help for Symbol" backtrace-help-follow-symbol
- :help "Show help for symbol at point"]
- ["Describe Debugger Mode" describe-mode
- :help "Display documentation for debugger-mode"]
- "--"
- ["Quit" debugger-quit
- :help "Quit debugging and return to top level"]))
- map))
+(defvar-keymap debugger-mode-map
+ :full t
+ :parent backtrace-mode-map
+ "b" #'debugger-frame
+ "c" #'debugger-continue
+ "j" #'debugger-jump
+ "r" #'debugger-return-value
+ "u" #'debugger-frame-clear
+ "d" #'debugger-step-through
+ "l" #'debugger-list-functions
+ "q" #'debugger-quit
+ "e" #'debugger-eval-expression
+ "R" #'debugger-record-expression
+
+ "<mouse-2>" #'push-button
+
+ :menu
+ '("Debugger"
+ ["Step through" debugger-step-through
+ :help "Proceed, stepping through subexpressions of this expression"]
+ ["Continue" debugger-continue
+ :help "Continue, evaluating this expression without stopping"]
+ ["Jump" debugger-jump
+ :help "Continue to exit from this frame, with all debug-on-entry suspended"]
+ ["Eval Expression..." debugger-eval-expression
+ :help "Eval an expression, in an environment like that outside the debugger"]
+ ["Display and Record Expression" debugger-record-expression
+ :help "Display a variable's value and record it in `*Backtrace-record*' buffer"]
+ ["Return value..." debugger-return-value
+ :help "Continue, specifying value to return."]
+ "--"
+ ["Debug frame" debugger-frame
+ :help "Request entry to debugger when this frame exits"]
+ ["Cancel debug frame" debugger-frame-clear
+ :help "Do not enter debugger when this frame exits"]
+ ["List debug on entry functions" debugger-list-functions
+ :help "Display a list of all the functions now set to debug on entry"]
+ "--"
+ ["Next Line" next-line
+ :help "Move cursor down"]
+ ["Help for Symbol" backtrace-help-follow-symbol
+ :help "Show help for symbol at point"]
+ ["Describe Debugger Mode" describe-mode
+ :help "Display documentation for debugger-mode"]
+ "--"
+ ["Quit" debugger-quit
+ :help "Quit debugging and return to top level"]))
(put 'debugger-mode 'mode-class 'special)
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index b9958f4951e..8912eb10cc5 100644
--- a/lisp/emacs-lisp/derived.el
+++ b/lisp/emacs-lisp/derived.el
@@ -404,7 +404,7 @@ the first time the mode is used."
t
(eval `(defvar ,(derived-mode-abbrev-table-name mode)
(progn
- (define-abbrev-table (derived-mode-abbrev-table-name mode) nil)
+ (define-abbrev-table (derived-mode-abbrev-table-name ',mode) nil)
(make-abbrev-table))
,(format "Abbrev table for %s." mode)))))
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 2d95e91833a..c3a4e9fc7ab 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -82,11 +82,9 @@ replacing its case-insensitive matches with the literal string in LIGHTER."
(replace-regexp-in-string (regexp-quote lighter) lighter name t t))))
(defconst easy-mmode--arg-docstring
- "
-
-This is a minor mode. If called interactively, toggle the `%s'
-mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+ "This is a %sminor mode. If called interactively, toggle the
+`%s' mode. If the prefix argument is positive, enable the mode,
+and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is `toggle'.
Enable the mode if ARG is nil, omitted, or is a positive number.
@@ -99,28 +97,50 @@ The mode's hook is called both when the mode is enabled and when
it is disabled.")
(defun easy-mmode--mode-docstring (doc mode-pretty-name keymap-sym
- getter)
- (let ((doc (or doc (format "Toggle %s on or off.
-
-\\{%s}" mode-pretty-name keymap-sym))))
- (if (string-match-p "\\bARG\\b" doc)
- doc
- (let* ((fill-prefix nil)
- (docs-fc (bound-and-true-p emacs-lisp-docstring-fill-column))
- (fill-column (if (integerp docs-fc) docs-fc 65))
- (argdoc (format easy-mmode--arg-docstring mode-pretty-name
- ;; Avoid having quotes turn into pretty quotes.
- (string-replace "'" "\\\\='"
- (format "%S" getter))))
- (filled (if (fboundp 'fill-region)
- (with-temp-buffer
- (insert argdoc)
- (fill-region (point-min) (point-max) 'left t)
- (buffer-string))
- argdoc)))
- (replace-regexp-in-string "\\(\n\n\\|\\'\\)\\(.\\|\n\\)*\\'"
- (concat filled "\\1")
- doc nil nil 1)))))
+ getter global)
+ ;; If we have a doc string, and it's already complete (which we
+ ;; guess at with the simple heuristic below), then just return that
+ ;; as is.
+ (if (and doc (string-match-p "\\bARG\\b" doc))
+ doc
+ ;; Compose a new doc string.
+ (with-temp-buffer
+ (let ((lines (if doc
+ (string-lines doc)
+ (list (format "Toggle %s on or off." mode-pretty-name)))))
+ ;; Insert the first line from the doc string.
+ (insert (pop lines))
+ ;; Ensure that we have (only) one blank line after the first
+ ;; line.
+ (ensure-empty-lines)
+ (while (and lines
+ (equal (car lines) ""))
+ (pop lines))
+ ;; Insert the doc string.
+ (dolist (line lines)
+ (insert line "\n"))
+ (ensure-empty-lines)
+ ;; Insert the boilerplate.
+ (let* ((fill-prefix nil)
+ (docs-fc (bound-and-true-p emacs-lisp-docstring-fill-column))
+ (fill-column (if (integerp docs-fc) docs-fc 65))
+ (argdoc (format
+ easy-mmode--arg-docstring
+ (if global "global " "")
+ mode-pretty-name
+ ;; Avoid having quotes turn into pretty quotes.
+ (string-replace "'" "\\='" (format "%S" getter)))))
+ (let ((start (point)))
+ (insert argdoc)
+ (when (fboundp 'fill-region)
+ (fill-region start (point) 'left t))))
+ ;; Finally, insert the keymap.
+ (when (and (boundp keymap-sym)
+ (or (not doc)
+ (not (string-search "\\{" doc))))
+ (ensure-empty-lines)
+ (insert (format "\\{%s}" keymap-sym)))
+ (buffer-string)))))
;;;###autoload
(defalias 'easy-mmode-define-minor-mode #'define-minor-mode)
@@ -317,7 +337,7 @@ or call the function `%s'."))))
warnwrap
`(defun ,modefun (&optional arg ,@extra-args)
,(easy-mmode--mode-docstring doc pretty-name keymap-sym
- getter)
+ getter globalp)
,(when interactive
;; Use `toggle' rather than (if ,mode 0 1) so that using
;; repeat-command still does the toggling correctly.
@@ -388,7 +408,7 @@ or call the function `%s'."))))
No problems result if this variable is not bound.
`add-hook' automatically binds it. (This is true for all hook variables.)"
modefun)))
- ;; Allow using using `M-x customize-variable' on the hook.
+ ;; Allow using `M-x customize-variable' on the hook.
(put ',hook 'custom-type 'hook)
(put ',hook 'standard-value (list nil))
@@ -556,7 +576,7 @@ and nil means \"don't use\". There's an implicit nil at the end of the
list."
mode)
:type '(repeat sexp)
- :group ,group))
+ ,@group))
;; Autoloading define-globalized-minor-mode autoloads everything
;; up-to-here.
@@ -696,8 +716,12 @@ Valid keywords and arguments are:
(defmacro easy-mmode-defmap (m bs doc &rest args)
"Define a constant M whose value is the result of `easy-mmode-define-keymap'.
The M, BS, and ARGS arguments are as per that function. DOC is
-the constant's documentation."
- (declare (indent 1))
+the constant's documentation.
+
+This macro is deprecated; use `defvar-keymap' instead."
+ ;; FIXME: Declare obsolete in favor of `defvar-keymap'. It is still
+ ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first.
+ (declare (doc-string 3) (indent 1))
`(defconst ,m
(easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
,doc))
@@ -724,7 +748,7 @@ the constant's documentation."
(defmacro easy-mmode-defsyntax (st css doc &rest args)
"Define variable ST as a syntax-table.
CSS contains a list of syntax specifications of the form (CHAR . SYNTAX)."
- (declare (indent 1))
+ (declare (doc-string 3) (indent 1))
`(progn
(autoload 'easy-mmode-define-syntax "easy-mmode")
(defconst ,st (easy-mmode-define-syntax ,css ,(cons 'list args)) ,doc)))
@@ -801,7 +825,6 @@ Interactively, COUNT is the prefix numeric argument, and defaults to 1."
,@body))
(put ',prev-sym 'definition-name ',base))))
-
(provide 'easy-mmode)
;;; easy-mmode.el ends here
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index fe97804ec4a..1a1d58d6e36 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -41,7 +41,7 @@
;; See the Emacs Lisp Reference Manual for more details.
;; If you wish to change the default edebug global command prefix, change:
-;; (setq global-edebug-prefix "\C-xX")
+;; (setq edebug-global-prefix "\C-xX")
;; Edebug was written by
;; Daniel LaLiberte
@@ -57,6 +57,7 @@
(require 'cl-lib)
(require 'seq)
(eval-when-compile (require 'pcase))
+(require 'debug)
;;; Options
@@ -98,7 +99,11 @@ This applies to `eval-defun', `eval-region', `eval-buffer', and
You can use the command `edebug-all-defs' to toggle the value of this
variable. You may wish to make it local to each buffer with
\(make-local-variable \\='edebug-all-defs) in your
-`emacs-lisp-mode-hook'."
+`emacs-lisp-mode-hook'.
+
+Note that this user option has no effect unless the edebug
+package has been loaded."
+ :require 'edebug
:type 'boolean)
;;;###autoload
@@ -670,7 +675,7 @@ Maybe clear the markers and delete the symbol's edebug property?"
(or (and (eq (aref edebug-read-syntax-table (following-char))
'symbol)
(not (= (following-char) ?\;)))
- (memq (following-char) '(?\, ?\.)))))
+ (eq (following-char) ?.))))
'symbol
(aref edebug-read-syntax-table (following-char))))
@@ -2573,6 +2578,13 @@ See `edebug-behavior-alist' for implementations.")
;; Let's at least show a backtrace so the user can figure out
;; which function we're talking about.
(debug))
+ ;; If we're in a `track-mouse' setting, then any previous mouse
+ ;; movements will make `input-pending-p' later return true. So
+ ;; discard the inputs in that case. (And `discard-input' doesn't
+ ;; work here.)
+ (when track-mouse
+ (while (input-pending-p)
+ (read-event)))
;; Setup windows for edebug, determine mode, maybe enter recursive-edit.
;; Uses local variables of edebug-enter, edebug-before, edebug-after
;; and edebug-debugger.
@@ -3695,33 +3707,64 @@ Return the result of the last expression."
(defalias 'edebug-format #'format-message)
(defalias 'edebug-message #'message)
-(defun edebug-eval-expression (expr)
+(defun edebug-eval-expression (expr &optional pp)
"Evaluate an expression in the outside environment.
If interactive, prompt for the expression.
-Print result in minibuffer."
- (interactive (list (read--expression "Eval: ")))
- (princ
- (edebug-outside-excursion
- (let ((result (edebug-eval expr)))
- (values--store-value result)
- (concat (edebug-safe-prin1-to-string result)
- (eval-expression-print-format result))))))
-
-(defun edebug-eval-last-sexp (&optional no-truncate)
- "Evaluate sexp before point in the outside environment.
-Print value in minibuffer.
-If NO-TRUNCATE is non-nil (or interactively with a prefix
-argument of zero), show the full length of the expression, not
-limited by `edebug-print-length' or `edebug-print-level'."
+Print result in minibuffer by default, but if PP is non-nil open
+a new window and pretty-print the result there. (Interactively,
+this is the prefix key.)"
+ (interactive (list (read--expression "Edebug eval: ")
+ current-prefix-arg))
+ (let* ((errored nil)
+ (value
+ (edebug-outside-excursion
+ (if debug-allow-recursive-debug
+ (edebug-eval expr)
+ (condition-case err
+ (edebug-eval expr)
+ (error
+ (setq errored
+ (format "%s: %s"
+ (get (car err) 'error-message)
+ (car (cdr err)))))))))
+ (result
+ (unless errored
+ (values--store-value value)
+ (concat (edebug-safe-prin1-to-string value)
+ (eval-expression-print-format value)))))
+ (cond
+ (errored
+ (message "Error: %s" errored))
+ (pp
+ (save-selected-window
+ (pop-to-buffer "*Edebug Results*")
+ (erase-buffer)
+ (pp value (current-buffer))
+ (goto-char (point-min))
+ (lisp-data-mode)))
+ (t
+ (princ result)))))
+
+(defun edebug-eval-last-sexp (&optional display-type)
+ "Evaluate sexp before point in the outside environment.
+If DISPLAY-TYPE is `pretty-print' (interactively, a non-zero
+prefix argument), pretty-print the value in a separate buffer.
+Otherwise, print the value in minibuffer. If DISPLAY-TYPE is any
+other non-nil value (or interactively with a prefix argument of
+zero), show the full length of the expression, not limited by
+`edebug-print-length' or `edebug-print-level'."
(interactive
(list (and current-prefix-arg
- (zerop (prefix-numeric-value current-prefix-arg)))))
- (if no-truncate
- (let ((edebug-print-length nil)
- (edebug-print-level nil))
- (edebug-eval-expression (edebug-last-sexp)))
- (edebug-eval-expression (edebug-last-sexp))))
+ (if (zerop (prefix-numeric-value current-prefix-arg))
+ 'no-truncate
+ 'pretty-print))))
+ (if (or (null display-type)
+ (eq display-type 'pretty-print))
+ (edebug-eval-expression (edebug-last-sexp) display-type)
+ (let ((edebug-print-length nil)
+ (edebug-print-level nil))
+ (edebug-eval-expression (edebug-last-sexp)))))
(defun edebug-eval-print-last-sexp (&optional no-truncate)
"Evaluate sexp before point in outside environment; insert value.
@@ -3766,117 +3809,115 @@ be installed in `emacs-lisp-mode-map'.")
;; The following isn't a GUD binding.
(define-key emacs-lisp-mode-map "\C-x\C-a\C-m" 'edebug-set-initial-mode))
-(defvar edebug-mode-map
- (let ((map (copy-keymap emacs-lisp-mode-map)))
- ;; control
- (define-key map " " 'edebug-step-mode)
- (define-key map "n" 'edebug-next-mode)
- (define-key map "g" 'edebug-go-mode)
- (define-key map "G" 'edebug-Go-nonstop-mode)
- (define-key map "t" 'edebug-trace-mode)
- (define-key map "T" 'edebug-Trace-fast-mode)
- (define-key map "c" 'edebug-continue-mode)
- (define-key map "C" 'edebug-Continue-fast-mode)
-
- ;;(define-key map "f" 'edebug-forward) not implemented
- (define-key map "f" 'edebug-forward-sexp)
- (define-key map "h" 'edebug-goto-here)
-
- (define-key map "I" 'edebug-instrument-callee)
- (define-key map "i" 'edebug-step-in)
- (define-key map "o" 'edebug-step-out)
-
- ;; quitting and stopping
- (define-key map "q" 'top-level)
- (define-key map "Q" 'edebug-top-level-nonstop)
- (define-key map "a" 'abort-recursive-edit)
- (define-key map "S" 'edebug-stop)
-
- ;; breakpoints
- (define-key map "b" 'edebug-set-breakpoint)
- (define-key map "u" 'edebug-unset-breakpoint)
- (define-key map "U" 'edebug-unset-breakpoints)
- (define-key map "B" 'edebug-next-breakpoint)
- (define-key map "x" 'edebug-set-conditional-breakpoint)
- (define-key map "X" 'edebug-set-global-break-condition)
- (define-key map "D" 'edebug-toggle-disable-breakpoint)
-
- ;; evaluation
- (define-key map "r" 'edebug-previous-result)
- (define-key map "e" 'edebug-eval-expression)
- (define-key map "\C-x\C-e" 'edebug-eval-last-sexp)
- (define-key map "E" 'edebug-visit-eval-list)
-
- ;; views
- (define-key map "w" 'edebug-where)
- (define-key map "v" 'edebug-view-outside) ;; maybe obsolete??
- (define-key map "p" 'edebug-bounce-point)
- (define-key map "P" 'edebug-view-outside) ;; same as v
- (define-key map "W" 'edebug-toggle-save-windows)
-
- ;; misc
- (define-key map "?" 'edebug-help)
- (define-key map "d" 'edebug-pop-to-backtrace)
-
- (define-key map "-" 'negative-argument)
-
- ;; statistics
- (define-key map "=" 'edebug-temp-display-freq-count)
-
- ;; GUD bindings
- (define-key map "\C-c\C-s" 'edebug-step-mode)
- (define-key map "\C-c\C-n" 'edebug-next-mode)
- (define-key map "\C-c\C-c" 'edebug-go-mode)
-
- (define-key map "\C-x " 'edebug-set-breakpoint)
- (define-key map "\C-c\C-d" 'edebug-unset-breakpoint)
- (define-key map "\C-c\C-t"
- (lambda () (interactive) (edebug-set-breakpoint t)))
- (define-key map "\C-c\C-l" 'edebug-where)
- map))
+(defvar-keymap edebug-mode-map
+ :parent emacs-lisp-mode-map
+ ;; control
+ "SPC" #'edebug-step-mode
+ "n" #'edebug-next-mode
+ "g" #'edebug-go-mode
+ "G" #'edebug-Go-nonstop-mode
+ "t" #'edebug-trace-mode
+ "T" #'edebug-Trace-fast-mode
+ "c" #'edebug-continue-mode
+ "C" #'edebug-Continue-fast-mode
+
+ ;;"f" #'edebug-forward ; not implemented
+ "f" #'edebug-forward-sexp
+ "h" #'edebug-goto-here
+
+ "I" #'edebug-instrument-callee
+ "i" #'edebug-step-in
+ "o" #'edebug-step-out
+
+ ;; quitting and stopping
+ "q" #'top-level
+ "Q" #'edebug-top-level-nonstop
+ "a" #'abort-recursive-edit
+ "S" #'edebug-stop
+
+ ;; breakpoints
+ "b" #'edebug-set-breakpoint
+ "u" #'edebug-unset-breakpoint
+ "U" #'edebug-unset-breakpoints
+ "B" #'edebug-next-breakpoint
+ "x" #'edebug-set-conditional-breakpoint
+ "X" #'edebug-set-global-break-condition
+ "D" #'edebug-toggle-disable-breakpoint
+
+ ;; evaluation
+ "r" #'edebug-previous-result
+ "e" #'edebug-eval-expression
+ "C-x C-e" #'edebug-eval-last-sexp
+ "E" #'edebug-visit-eval-list
+
+ ;; views
+ "w" #'edebug-where
+ "v" #'edebug-view-outside ; maybe obsolete??
+ "p" #'edebug-bounce-point
+ "P" #'edebug-view-outside ; same as v
+ "W" #'edebug-toggle-save-windows
+
+ ;; misc
+ "?" #'edebug-help
+ "d" #'edebug-pop-to-backtrace
+
+ "-" #'negative-argument
+
+ ;; statistics
+ "=" #'edebug-temp-display-freq-count
+
+ ;; GUD bindings
+ "C-c C-s" #'edebug-step-mode
+ "C-c C-n" #'edebug-next-mode
+ "C-c C-c" #'edebug-go-mode
+
+ "C-x SPC" #'edebug-set-breakpoint
+ "C-c C-d" #'edebug-unset-breakpoint
+ "C-c C-t" (lambda () (interactive) (edebug-set-breakpoint t))
+ "C-c C-l" #'edebug-where)
;; Autoloading these global bindings doesn't make sense because
;; they cannot be used anyway unless Edebug is already loaded and active.
(define-obsolete-variable-alias 'global-edebug-prefix
'edebug-global-prefix "28.1")
-(defvar edebug-global-prefix "\^XX"
+(defvar edebug-global-prefix
+ (when-let ((binding
+ (car (where-is-internal 'Control-X-prefix (list global-map)))))
+ (concat binding [?X]))
"Prefix key for global edebug commands, available from any buffer.")
(define-obsolete-variable-alias 'global-edebug-map
'edebug-global-map "28.1")
-(defvar edebug-global-map
- (let ((map (make-sparse-keymap)))
-
- (define-key map " " 'edebug-step-mode)
- (define-key map "g" 'edebug-go-mode)
- (define-key map "G" 'edebug-Go-nonstop-mode)
- (define-key map "t" 'edebug-trace-mode)
- (define-key map "T" 'edebug-Trace-fast-mode)
- (define-key map "c" 'edebug-continue-mode)
- (define-key map "C" 'edebug-Continue-fast-mode)
-
- ;; breakpoints
- (define-key map "b" 'edebug-set-breakpoint)
- (define-key map "u" 'edebug-unset-breakpoint)
- (define-key map "U" 'edebug-unset-breakpoints)
- (define-key map "x" 'edebug-set-conditional-breakpoint)
- (define-key map "X" 'edebug-set-global-break-condition)
- (define-key map "D" 'edebug-toggle-disable-breakpoint)
-
- ;; views
- (define-key map "w" 'edebug-where)
- (define-key map "W" 'edebug-toggle-save-windows)
-
- ;; quitting
- (define-key map "q" 'top-level)
- (define-key map "Q" 'edebug-top-level-nonstop)
- (define-key map "a" 'abort-recursive-edit)
-
- ;; statistics
- (define-key map "=" 'edebug-display-freq-count)
- map)
- "Global map of edebug commands, available from any buffer.")
+(defvar-keymap edebug-global-map
+ :doc "Global map of edebug commands, available from any buffer."
+ "SPC" #'edebug-step-mode
+ "g" #'edebug-go-mode
+ "G" #'edebug-Go-nonstop-mode
+ "t" #'edebug-trace-mode
+ "T" #'edebug-Trace-fast-mode
+ "c" #'edebug-continue-mode
+ "C" #'edebug-Continue-fast-mode
+
+ ;; breakpoints
+ "b" #'edebug-set-breakpoint
+ "u" #'edebug-unset-breakpoint
+ "U" #'edebug-unset-breakpoints
+ "x" #'edebug-set-conditional-breakpoint
+ "X" #'edebug-set-global-break-condition
+ "D" #'edebug-toggle-disable-breakpoint
+
+ ;; views
+ "w" #'edebug-where
+ "W" #'edebug-toggle-save-windows
+
+ ;; quitting
+ "q" #'top-level
+ "Q" #'edebug-top-level-nonstop
+ "a" #'abort-recursive-edit
+
+ ;; statistics
+ "=" #'edebug-display-freq-count)
(when edebug-global-prefix
(global-unset-key edebug-global-prefix)
@@ -3903,8 +3944,8 @@ Also see bindings for the eval list buffer *edebug* in `edebug-eval-mode'.
The edebug buffer commands:
\\{edebug-mode-map}
-Global commands prefixed by `global-edebug-prefix':
-\\{global-edebug-map}
+Global commands prefixed by `edebug-global-prefix':
+\\{edebug-global-map}
Options:
`edebug-setup-hook'
@@ -4047,16 +4088,14 @@ May only be called from within `edebug--recursive-edit'."
-(defvar edebug-eval-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map lisp-interaction-mode-map)
- (define-key map "\C-c\C-w" 'edebug-where)
- (define-key map "\C-c\C-d" 'edebug-delete-eval-item)
- (define-key map "\C-c\C-u" 'edebug-update-eval-list)
- (define-key map "\C-x\C-e" 'edebug-eval-last-sexp)
- (define-key map "\C-j" 'edebug-eval-print-last-sexp)
- map)
- "Keymap for Edebug Eval mode. Superset of Lisp Interaction mode.")
+(defvar-keymap edebug-eval-mode-map
+ :doc "Keymap for Edebug Eval mode. Superset of Lisp Interaction mode."
+ :parent lisp-interaction-mode-map
+ "C-c C-w" #'edebug-where
+ "C-c C-d" #'edebug-delete-eval-item
+ "C-c C-u" #'edebug-update-eval-list
+ "C-x C-e" #'edebug-eval-last-sexp
+ "C-j" #'edebug-eval-print-last-sexp)
(put 'edebug-eval-mode 'mode-class 'special)
@@ -4071,8 +4110,8 @@ buffer and \\<global-map>\\[edebug-step-mode] in any buffer.
Eval list buffer commands:
\\{edebug-eval-mode-map}
-Global commands prefixed by `global-edebug-prefix':
-\\{global-edebug-map}")
+Global commands prefixed by `edebug-global-prefix':
+\\{edebug-global-map}")
;;; Interface with standard debugger.
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index f36e34261e9..25f2dd40980 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -24,8 +24,8 @@
;;; Commentary:
;;
;; The "core" part of EIEIO is the implementation for the object
-;; system (such as eieio-defclass, or eieio-defmethod) but not the
-;; base classes for the object system, which are defined in EIEIO.
+;; system (such as eieio-defclass-internal, or cl-defmethod) but not
+;; the base classes for the object system, which are defined in EIEIO.
;;
;; See the commentary for eieio.el for more about EIEIO itself.
@@ -92,7 +92,7 @@ Currently under control of this var:
(:copier nil))
children
initarg-tuples ;; initarg tuples list
- (class-slots nil :type eieio--slot)
+ (class-slots nil :type (vector-of eieio--slot))
class-allocation-values ;; class allocated value vector
default-object-cache ;; what a newly created object would look like.
; This will speed up instantiation time as
@@ -130,16 +130,15 @@ Currently under control of this var:
class))
(defsubst eieio--object-class (obj)
- (let ((tag (eieio--object-class-tag obj)))
- (if eieio-backward-compatibility
- (eieio--class-object tag)
- tag)))
+ (eieio--class-object (eieio--object-class-tag obj)))
(defun class-p (x)
"Return non-nil if X is a valid class vector.
X can also be is a symbol."
(eieio--class-p (if (symbolp x) (cl--find-class x) x)))
+(cl-deftype class () `(satisfies class-p))
+
(defun eieio--class-print-name (class)
"Return a printed representation of CLASS."
(format "#<class %s>" (eieio-class-name class)))
@@ -168,6 +167,8 @@ Return nil if that option doesn't exist."
(and (recordp obj)
(eieio--class-p (eieio--object-class obj))))
+(cl-deftype eieio-object () `(satisfies eieio-object-p))
+
(define-obsolete-function-alias 'object-p #'eieio-object-p "25.1")
(defun class-abstract-p (class)
@@ -215,7 +216,7 @@ It creates an autoload function for CNAME's constructor."
(when eieio-backward-compatibility
(set cname cname)
(make-obsolete-variable cname (format "\
-use \\='%s or turn off `eieio-backward-compatibility' instead" cname)
+use '%s or turn off `eieio-backward-compatibility' instead" cname)
"25.1"))
(setf (cl--find-class cname) newc)
@@ -265,6 +266,10 @@ use \\='%s or turn off `eieio-backward-compatibility' instead" cname)
(defvar eieio--known-slot-names nil)
(defvar eieio--known-class-slot-names nil)
+(defun eieio--known-slot-name-p (name)
+ (or (memq name eieio--known-slot-names)
+ (get name 'slot-name)))
+
(defun eieio-defclass-internal (cname superclasses slots options)
"Define CNAME as a new subclass of SUPERCLASSES.
SLOTS are the slots residing in that class definition, and OPTIONS
@@ -340,7 +345,7 @@ See `defclass' for more information."
;; turn this into a usable self-pointing symbol; FIXME: Why?
(when eieio-backward-compatibility
(set cname cname)
- (make-obsolete-variable cname (format "use \\='%s instead" cname)
+ (make-obsolete-variable cname (format "use '%s instead" cname)
"25.1"))
;; Create a handy list of the class test too
@@ -362,7 +367,7 @@ See `defclass' for more information."
(setq obj (cdr obj)))
ans))))
(make-obsolete csym (format
- "use (cl-typep ... \\='(list-of %s)) instead"
+ "use (cl-typep ... '(list-of %s)) instead"
cname)
"25.1")))
@@ -420,7 +425,7 @@ See `defclass' for more information."
(progn
(set initarg initarg)
(make-obsolete-variable
- initarg (format "use \\='%s instead" initarg) "25.1"))))
+ initarg (format "use '%s instead" initarg) "25.1"))))
;; The customgroup should be a list of symbols.
(cond ((and (null customg) custom)
@@ -710,9 +715,9 @@ an error."
(cond
((not (eieio--perform-slot-validation st value))
(signal 'invalid-slot-type
- (list (eieio--class-name class) slot st value)))
+ (list (cl--class-name class) slot st value)))
((alist-get :read-only (cl--slot-descriptor-props sd))
- (signal 'eieio-read-only (list (eieio--class-name class) slot)))))))
+ (signal 'eieio-read-only (list (cl--class-name class) slot)))))))
(defun eieio--validate-class-slot-value (class slot-idx value slot)
"Make sure that for CLASS referencing SLOT-IDX, VALUE is valid.
@@ -725,7 +730,7 @@ an error."
slot-idx))))
(if (not (eieio--perform-slot-validation st value))
(signal 'invalid-slot-type
- (list (eieio--class-name class) slot st value))))))
+ (list (cl--class-name class) slot st value))))))
(defun eieio-barf-if-slot-unbound (value instance slotname fn)
"Throw a signal if VALUE is a representation of an UNBOUND slot.
@@ -746,31 +751,35 @@ Argument FN is the function calling this verifier."
(ignore obj)
(pcase slot
((and (or `',name (and name (pred keywordp)))
- (guard (not (memq name eieio--known-slot-names))))
+ (guard (not (eieio--known-slot-name-p name))))
(macroexp-warn-and-return
(format-message "Unknown slot `%S'" name)
- exp nil 'compile-only))
+ exp nil 'compile-only name))
(_ exp))))
+ ;; FIXME: Make it a gv-expander such that the hash-table lookup is
+ ;; only performed once when used in `push' and friends?
(gv-setter eieio-oset))
(cl-check-type slot symbol)
- (cl-check-type obj (or eieio-object class cl-structure-object))
- (let* ((class (cond ((symbolp obj)
- (error "eieio-oref called on a class: %s" obj)
- (eieio--full-class-object obj))
- (t (eieio--object-class obj))))
- (c (eieio--slot-name-index class slot)))
- (if (not c)
- ;; It might be missing because it is a :class allocated slot.
- ;; Let's check that info out.
- (if (setq c (eieio--class-slot-name-index class slot))
- ;; Oref that slot.
- (aref (eieio--class-class-allocation-values class) c)
- ;; The slot-missing method is a cool way of allowing an object author
- ;; to intercept missing slot definitions. Since it is also the LAST
- ;; thing called in this fn, its return value would be retrieved.
- (slot-missing obj slot 'oref))
- (cl-check-type obj (or eieio-object cl-structure-object))
- (eieio-barf-if-slot-unbound (aref obj c) obj slot 'oref))))
+ (cond
+ ((cl-typep obj '(or eieio-object cl-structure-object))
+ (let* ((class (eieio--object-class obj))
+ (c (eieio--slot-name-index class slot)))
+ (if (not c)
+ ;; It might be missing because it is a :class allocated slot.
+ ;; Let's check that info out.
+ (if (setq c (eieio--class-slot-name-index class slot))
+ ;; Oref that slot.
+ (aref (eieio--class-class-allocation-values class) c)
+ ;; The slot-missing method is a cool way of allowing an object author
+ ;; to intercept missing slot definitions. Since it is also the LAST
+ ;; thing called in this fn, its return value would be retrieved.
+ (slot-missing obj slot 'oref))
+ (eieio-barf-if-slot-unbound (aref obj c) obj slot 'oref))))
+ ((cl-typep obj 'oclosure) (oclosure--slot-value obj slot))
+ (t
+ (signal 'wrong-type-argument
+ (list '(or eieio-object cl-structure-object oclosure) obj)))))
+
(defun eieio-oref-default (class slot)
@@ -782,15 +791,15 @@ Fills in CLASS's SLOT with its default value."
(ignore class)
(pcase slot
((and (or `',name (and name (pred keywordp)))
- (guard (not (memq name eieio--known-slot-names))))
+ (guard (not (eieio--known-slot-name-p name))))
(macroexp-warn-and-return
(format-message "Unknown slot `%S'" name)
- exp nil 'compile-only))
+ exp nil 'compile-only name))
((and (or `',name (and name (pred keywordp)))
(guard (not (memq name eieio--known-class-slot-names))))
(macroexp-warn-and-return
(format-message "Slot `%S' is not class-allocated" name)
- exp nil 'compile-only))
+ exp nil 'compile-only name))
(_ exp)))))
(cl-check-type class (or eieio-object class))
(cl-check-type slot symbol)
@@ -817,24 +826,29 @@ Fills in CLASS's SLOT with its default value."
(defun eieio-oset (obj slot value)
"Do the work for the macro `oset'.
Fills in OBJ's SLOT with VALUE."
- (cl-check-type obj (or eieio-object cl-structure-object))
(cl-check-type slot symbol)
- (let* ((class (eieio--object-class obj))
- (c (eieio--slot-name-index class slot)))
- (if (not c)
- ;; It might be missing because it is a :class allocated slot.
- ;; Let's check that info out.
- (if (setq c
- (eieio--class-slot-name-index class slot))
- ;; Oset that slot.
- (progn
- (eieio--validate-class-slot-value class c value slot)
- (aset (eieio--class-class-allocation-values class)
- c value))
- ;; See oref for comment on `slot-missing'
- (slot-missing obj slot 'oset value))
- (eieio--validate-slot-value class c value slot)
- (aset obj c value))))
+ (cond
+ ((cl-typep obj '(or eieio-object cl-structure-object))
+ (let* ((class (eieio--object-class obj))
+ (c (eieio--slot-name-index class slot)))
+ (if (not c)
+ ;; It might be missing because it is a :class allocated slot.
+ ;; Let's check that info out.
+ (if (setq c
+ (eieio--class-slot-name-index class slot))
+ ;; Oset that slot.
+ (progn
+ (eieio--validate-class-slot-value class c value slot)
+ (aset (eieio--class-class-allocation-values class)
+ c value))
+ ;; See oref for comment on `slot-missing'
+ (slot-missing obj slot 'oset value))
+ (eieio--validate-slot-value class c value slot)
+ (aset obj c value))))
+ ((cl-typep obj 'oclosure) (oclosure--set-slot-value obj slot value))
+ (t
+ (signal 'wrong-type-argument
+ (list '(or eieio-object cl-structure-object oclosure) obj)))))
(defun eieio-oset-default (class slot value)
"Do the work for the macro `oset-default'.
@@ -844,15 +858,15 @@ Fills in the default value in CLASS' in SLOT with VALUE."
(ignore class value)
(pcase slot
((and (or `',name (and name (pred keywordp)))
- (guard (not (memq name eieio--known-slot-names))))
+ (guard (not (eieio--known-slot-name-p name))))
(macroexp-warn-and-return
(format-message "Unknown slot `%S'" name)
- exp nil 'compile-only))
+ exp nil 'compile-only name))
((and (or `',name (and name (pred keywordp)))
(guard (not (memq name eieio--known-class-slot-names))))
(macroexp-warn-and-return
(format-message "Slot `%S' is not class-allocated" name)
- exp nil 'compile-only))
+ exp nil 'compile-only name))
(_ exp)))))
(setq class (eieio--class-object class))
(cl-check-type class eieio--class)
@@ -867,7 +881,7 @@ Fills in the default value in CLASS' in SLOT with VALUE."
(eieio--validate-class-slot-value class c value slot)
(aset (eieio--class-class-allocation-values class) c
value))
- (signal 'invalid-slot-name (list (eieio--class-name class) slot)))
+ (signal 'invalid-slot-name (list (cl--class-name class) slot)))
;; `oset-default' on an instance-allocated slot is allowed by EIEIO but
;; not by CLOS and is mildly inconsistent with the :initform thingy, so
;; it'd be nice to get rid of it.
@@ -896,7 +910,7 @@ The slot is a symbol which is installed in CLASS by the `defclass' call.
If SLOT is the value created with :initarg instead,
reverse-lookup that name, and recurse with the associated slot value."
;; Removed checks to outside this call
- (let* ((fsi (gethash slot (eieio--class-index-table class))))
+ (let* ((fsi (gethash slot (cl--class-index-table class))))
(if (integerp fsi)
fsi
(let ((fn (eieio--initarg-to-attribute class slot)))
diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el
index ebb6f2cd8c8..4b8b4275f1a 100644
--- a/lisp/emacs-lisp/eieio-custom.el
+++ b/lisp/emacs-lisp/eieio-custom.el
@@ -329,11 +329,9 @@ Argument OBJ is the object that has been customized."
Optional argument GROUP is the sub-group of slots to display."
(eieio-customize-object obj group))
-(defvar eieio-custom-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map widget-keymap)
- map)
- "Keymap for EIEIO Custom mode.")
+(defvar-keymap eieio-custom-mode-map
+ :doc "Keymap for EIEIO Custom mode."
+ :parent widget-keymap)
(define-derived-mode eieio-custom-mode fundamental-mode "EIEIO Custom"
"Major mode for customizing EIEIO objects.
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 27bdedb306a..565eaf2d733 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -181,9 +181,11 @@ and reference them using the function `class-option'."
;; Is there an initarg, but allocation of class?
(when (and initarg (eq alloc :class))
- (push (format "Meaningless :initarg for class allocated slot '%S'"
- sname)
- warnings))
+ (push
+ (cons sname
+ (format "Meaningless :initarg for class allocated slot '%S'"
+ sname))
+ warnings))
(let ((init (plist-get soptions :initform)))
(unless (or (macroexp-const-p init)
@@ -194,8 +196,9 @@ and reference them using the function `class-option'."
;; heuristic says and if it disagrees with normal evaluation
;; then tweak the initform to make it fit and emit
;; a warning accordingly.
- (push (format "Ambiguous initform needs quoting: %S" init)
- warnings)))
+ (push
+ (cons init (format "Ambiguous initform needs quoting: %S" init))
+ warnings)))
;; Anyone can have an accessor function. This creates a function
;; of the specified name, and also performs a `defsetf' if applicable
@@ -242,7 +245,8 @@ This method is obsolete."
`(progn
,@(mapcar (lambda (w)
- (macroexp-warn-and-return w `(progn ',w) nil 'compile-only))
+ (macroexp-warn-and-return
+ (cdr w) `(progn ',(cdr w)) nil 'compile-only (car w)))
warnings)
;; This test must be created right away so we can have self-
;; referencing classes. ei, a class whose slot can contain only
@@ -256,7 +260,7 @@ This method is obsolete."
(let ((f (intern (format "%s-child-p" name))))
`((defalias ',f #',testsym2)
(make-obsolete
- ',f ,(format "use (cl-typep ... \\='%s) instead" name)
+ ',f ,(format "use (cl-typep ... '%s) instead" name)
"25.1"))))
;; When using typep, (typep OBJ 'myclass) returns t for objects which
@@ -267,7 +271,8 @@ This method is obsolete."
;; test, so we can let typep have the CLOS documented behavior
;; while keeping our above predicate clean.
- (define-symbol-prop ',name 'cl-deftype-satisfies #',testsym2)
+ (eval-and-compile
+ (define-symbol-prop ',name 'cl-deftype-satisfies #',testsym2))
(eieio-defclass-internal ',name ',superclasses ',slots ',options-and-doc)
@@ -297,7 +302,8 @@ This method is obsolete."
;; Keep the name arg, for backward compatibility,
;; but hide it so we don't trigger indefinitely.
`(,(car whole) (identity ,(car slots))
- ,@(cdr slots)))))))
+ ,@(cdr slots))
+ nil nil (car slots))))))
(apply #'make-instance ',name slots))))))
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 74a20b8a8b7..0b8078579cc 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -5,7 +5,7 @@
;; Author: Noah Friedman <friedman@splode.com>
;; Keywords: extensions
;; Created: 1995-10-06
-;; Version: 1.11.0
+;; Version: 1.12.0
;; Package-Requires: ((emacs "26.3"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -102,7 +102,7 @@ put in the echo area. If a positive integer, the number is used
directly, while a float specifies the number of lines as a
proportion of the echo area frame's height.
-If value is the symbol `truncate-sym-name-if-fit' t, the part of
+If value is the symbol `truncate-sym-name-if-fit', the part of
the doc string that represents a symbol's name may be truncated
if it will enable the rest of the doc string to fit on a single
line, without resizing the echo area.
@@ -387,6 +387,10 @@ Also store it in `eldoc-last-message' and return that value."
;; conflicts with eldoc.
(and (boundp 'show-paren-context-when-offscreen)
show-paren-context-when-offscreen
+ ;; There's no conflict with the child-frame and
+ ;; overlay versions.
+ (not (memq show-paren-context-when-offscreen
+ '(child-frame overlay)))
(not (pos-visible-in-window-p
(overlay-end show-paren--overlay)))))))
@@ -460,19 +464,22 @@ directly from the user or from ElDoc's automatic mechanisms'.")
(defvar eldoc--doc-buffer-docs nil "Documentation items in `eldoc--doc-buffer'.")
-(defun eldoc-doc-buffer ()
- "Display ElDoc documentation buffer.
+(defun eldoc-doc-buffer (&optional interactive)
+ "Get or display ElDoc documentation buffer.
-This holds the results of the last documentation request."
- (interactive)
+The buffer holds the results of the last documentation request.
+If INTERACTIVE, display it. Else, return said buffer."
+ (interactive (list t))
(unless (buffer-live-p eldoc--doc-buffer)
(user-error (format
"ElDoc buffer doesn't exist, maybe `%s' to produce one."
(substitute-command-keys "\\[eldoc]"))))
(with-current-buffer eldoc--doc-buffer
- (rename-buffer (replace-regexp-in-string "^ *" ""
- (buffer-name)))
- (display-buffer (current-buffer))))
+ (cond (interactive
+ (rename-buffer (replace-regexp-in-string "^ *" ""
+ (buffer-name)))
+ (display-buffer (current-buffer)))
+ (t (current-buffer)))))
(defun eldoc--format-doc-buffer (docs)
"Ensure DOCS are displayed in an *eldoc* buffer."
@@ -521,7 +528,8 @@ Helper for `eldoc-display-in-echo-area'."
(goto-char (point-min))
(skip-chars-forward " \t\n")
(point))
- (goto-char (line-end-position available))
+ (forward-visible-line (1- available))
+ (end-of-visible-line)
(skip-chars-backward " \t\n")))
(truncated (save-excursion
(skip-chars-forward " \t\n")
@@ -531,7 +539,8 @@ Helper for `eldoc-display-in-echo-area'."
((and truncated
(> available 1)
eldoc-echo-area-display-truncation-message)
- (goto-char (line-end-position 0))
+ (forward-visible-line -1)
+ (end-of-visible-line)
(concat (buffer-substring start (point))
(format
"\n(Documentation truncated. Use `%s' to see rest)"
@@ -606,7 +615,8 @@ Honor `eldoc-echo-area-use-multiline-p' and
(let ((string
(with-current-buffer (eldoc--format-doc-buffer docs)
(buffer-substring (goto-char (point-min))
- (line-end-position 1)))))
+ (progn (end-of-visible-line)
+ (point))))))
(if (> (length string) width) ; truncation to happen
(unless (eldoc--echo-area-prefer-doc-buffer-p t)
(truncate-string-to-width string width))
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
index e5c94c09c27..03c5b94e3b4 100644
--- a/lisp/emacs-lisp/elp.el
+++ b/lisp/emacs-lisp/elp.el
@@ -287,7 +287,12 @@ type \"nil\" to use `elp-function-list'."
"Instrument for profiling, all functions which start with PREFIX.
For example, to instrument all ELP functions, do the following:
- \\[elp-instrument-package] RET elp- RET"
+ \\[elp-instrument-package] RET elp- RET
+
+Note that only functions that are currently loaded will be
+instrumented. If you run this function, and then later load
+further functions that start with PREFIX, they will not be
+instrumented automatically."
(interactive
(list (completing-read "Prefix of package to instrument: "
obarray 'elp-profilable-p)))
@@ -467,13 +472,11 @@ original definition, use \\[elp-restore-function] or \\[elp-restore-all]."
(insert atstr))
(insert "\n"))))
-(defvar elp-results-symname-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'elp-results-jump-to-definition)
- (define-key map [follow-link] 'mouse-face)
- (define-key map "\C-m" 'elp-results-jump-to-definition)
- map)
- "Keymap used on the function name column." )
+(defvar-keymap elp-results-symname-map
+ :doc "Keymap used on the function name column."
+ "<mouse-2>" #'elp-results-jump-to-definition
+ "<follow-link>" 'mouse-face
+ "RET" #'elp-results-jump-to-definition)
(defun elp-results-jump-to-definition (&optional event)
"Jump to the definition of the function at point."
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index 2818d4b6cc7..4436d0a4b16 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -96,7 +96,7 @@ ERT--THUNK with that buffer as current."
To be used in ERT tests. If BODY finishes successfully, the test
buffer is killed; if there is an error, the test buffer is kept
-around on error for further inspection. Its name is derived from
+around for further inspection. Its name is derived from
the name of the test and the result of NAME-FORM."
(declare (debug ((":name" form) def-body))
(indent 1))
@@ -158,9 +158,6 @@ test for `called-interactively' in the command will fail."
(run-hooks 'pre-command-hook)
(setq return-value (apply (car command) (cdr command)))
(run-hooks 'post-command-hook)
- (and (boundp 'deferred-action-list)
- deferred-action-list
- (run-hooks 'deferred-action-function))
(setq real-last-command (car command)
last-command this-command)
(when (boundp 'last-repeatable-command)
@@ -338,7 +335,8 @@ unless the output is going to the echo area (when PRINTCHARFUN is
t or PRINTCHARFUN is nil and `standard-output' is t). If the
output is destined for the echo area, the advice function will
convert it to a string and pass it to COLLECTOR first."
- (lambda (func object &optional printcharfun)
+ ;;; FIXME: Pass on OVERRIDES.
+ (lambda (func object &optional printcharfun _overrides)
(if (not (eq t (or printcharfun standard-output)))
(funcall func object printcharfun)
(funcall collector (with-output-to-string
@@ -424,10 +422,15 @@ The following keyword arguments are supported:
:text STRING If non-nil, pass STRING to `make-temp-file' as
the TEXT argument.
+:coding CODING If non-nil, bind `coding-system-for-write' to CODING
+ when executing BODY. This is handy when STRING includes
+ non-ASCII characters or the temporary file must have a
+ specific encoding or end-of-line format.
+
See also `ert-with-temp-directory'."
(declare (indent 1) (debug (symbolp body)))
(cl-check-type name symbol)
- (let (keyw prefix suffix directory text extra-keywords)
+ (let (keyw prefix suffix directory text extra-keywords coding)
(while (keywordp (setq keyw (car body)))
(setq body (cdr body))
(pcase keyw
@@ -435,6 +438,7 @@ See also `ert-with-temp-directory'."
(:suffix (setq suffix (pop body)))
(:directory (setq directory (pop body)))
(:text (setq text (pop body)))
+ (:coding (setq coding (pop body)))
(_ (push keyw extra-keywords) (pop body))))
(when extra-keywords
(error "Invalid keywords: %s" (mapconcat #'symbol-name extra-keywords " ")))
@@ -443,7 +447,8 @@ See also `ert-with-temp-directory'."
(suffix (or suffix ert-temp-file-suffix
(ert--with-temp-file-generate-suffix
(or (macroexp-file-name) buffer-file-name)))))
- `(let* ((,temp-file (,(if directory 'file-name-as-directory 'identity)
+ `(let* ((coding-system-for-write ,(or coding coding-system-for-write))
+ (,temp-file (,(if directory 'file-name-as-directory 'identity)
(make-temp-file ,prefix ,directory ,suffix ,text)))
(,name ,(if directory
`(file-name-as-directory ,temp-file)
@@ -475,6 +480,48 @@ The same keyword arguments are supported as in
:directory t
,@body))
+(defun ert-gcc-is-clang-p ()
+ "Return non-nil if the `gcc' command actually runs the Clang compiler."
+ ;; Some macOS machines run llvm when you type gcc. (!)
+ ;; We can't even check if it's a symlink; it's a binary placed in
+ ;; "/usr/bin/gcc". So we need to check the output.
+ (string-match "Apple \\(LLVM\\|[Cc]lang\\)\\|Xcode\\.app"
+ (shell-command-to-string "gcc --version")))
+
+(defvar tramp-default-host-alist)
+(defvar tramp-methods)
+(defvar tramp-remote-path)
+
+;; This should happen on hydra only.
+(when (and (featurep 'tramp) (getenv "EMACS_HYDRA_CI"))
+ (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
+
+;; If this defconst is used in a test file, `tramp' shall be loaded
+;; prior `ert-x'. There is no default value on w32 systems, which
+;; could work out of the box.
+(defconst ert-remote-temporary-file-directory
+ (when (featurep 'tramp)
+ (cond
+ ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
+ ((eq system-type 'windows-nt) null-device)
+ (t (add-to-list
+ 'tramp-methods
+ '("mock"
+ (tramp-login-program "sh")
+ (tramp-login-args (("-i")))
+ (tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
+ (add-to-list
+ 'tramp-default-host-alist
+ `("\\`mock\\'" nil ,(system-name)))
+ ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed
+ ;; in batch mode only, therefore.
+ (unless (and (null noninteractive) (file-directory-p "~/"))
+ (setenv "HOME" temporary-file-directory))
+ (format "/mock::%s" temporary-file-directory))))
+ "Temporary directory for remote file tests.")
+
(provide 'ert-x)
;;; ert-x.el ends here
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index e31ebf5f7bb..49b54c2d00f 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -1,6 +1,6 @@
;;; ert.el --- Emacs Lisp Regression Testing -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2008, 2010-2022 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2022 Free Software Foundation, Inc.
;; Author: Christian Ohler <ohler@gnu.org>
;; Keywords: lisp, tools
@@ -46,14 +46,10 @@
;; processing further, this is useful for checking the test
;; environment (like availability of features, external binaries, etc).
;;
-;; See ERT's info manual as well as the docstrings for more details.
-;; To compile the manual, run `makeinfo ert.texinfo' in the ERT
-;; directory, then C-u M-x info ert.info in Emacs to view it.
-;;
-;; To see some examples of tests written in ERT, see its self-tests in
-;; ert-tests.el. Some of these are tricky due to the bootstrapping
-;; problem of writing tests for a testing tool, others test simple
-;; functions and are straightforward.
+;; See ERT's Info manual `(ert) Top' as well as the docstrings for
+;; more details. To see some examples of tests written in ERT, see
+;; the test suite distributed with the Emacs source distribution (in
+;; the "test" directory).
;;; Code:
@@ -129,7 +125,8 @@ mode.")
(body (cl-assert nil))
(most-recent-result nil)
(expected-result-type ':passed)
- (tags '()))
+ (tags '())
+ (file-name nil))
(defun ert-test-boundp (symbol)
"Return non-nil if SYMBOL names a test."
@@ -240,7 +237,8 @@ in batch mode, an error is signalled.
`(:expected-result-type ,expected-result))
,@(when tags-supplied-p
`(:tags ,tags))
- :body (lambda () ,@body)))
+ :body (lambda () ,@body)
+ :file-name ,(or (macroexp-file-name) buffer-file-name)))
',name))))
(defvar ert--find-test-regexp
@@ -335,15 +333,20 @@ It should only be stopped when ran from inside `ert--run-test-internal'."
(unless (eql ,value ',default-value)
(list :value ,value))
(unless (eql ,value ',default-value)
- (let ((-explainer-
- (and (symbolp ',fn-name)
- (get ',fn-name 'ert-explainer))))
- (when -explainer-
- (list :explanation
- (apply -explainer- ,args))))))
+ (when-let ((-explainer-
+ (ert--get-explainer ',fn-name)))
+ (list :explanation
+ (apply -explainer- ,args)))))
value)
,value))))))))
+(defun ert--get-explainer (fn-name)
+ (when (symbolp fn-name)
+ (cl-loop for fn in (cons fn-name (function-alias-p fn-name))
+ for explainer = (get fn 'ert-explainer)
+ when explainer
+ return explainer)))
+
(defun ert--expand-should (whole form inner-expander)
"Helper function for the `should' macro and its variants.
@@ -1365,6 +1368,22 @@ RESULT must be an `ert-test-result-with-condition'."
(defvar ert-quiet nil
"Non-nil makes ERT only print important information in batch mode.")
+(defun ert-test-location (test)
+ "Return a string description the source location of TEST."
+ (when-let ((loc
+ (ignore-errors
+ (find-function-search-for-symbol
+ (ert-test-name test) 'ert-deftest (ert-test-file-name test)))))
+ (let* ((buffer (car loc))
+ (point (cdr loc))
+ (file (file-relative-name (buffer-file-name buffer)))
+ (line (with-current-buffer buffer
+ (line-number-at-pos point))))
+ (format "at %s:%s" file line))))
+
+(defvar ert-batch-backtrace-right-margin 70
+ "The maximum line length for printing backtraces in `ert-run-tests-batch'.")
+
;;;###autoload
(defun ert-run-tests-batch (&optional selector)
"Run the tests specified by SELECTOR, printing results to the terminal.
@@ -1418,7 +1437,8 @@ Returns the stats object."
(message "%9s %S%s"
(ert-string-for-test-result result nil)
(ert-test-name test)
- (if (getenv "EMACS_TEST_VERBOSE")
+ (if (cl-plusp
+ (length (getenv "EMACS_TEST_VERBOSE")))
(ert-reason-for-test-result result)
""))))
(message "%s" ""))
@@ -1430,7 +1450,8 @@ Returns the stats object."
(message "%9s %S%s"
(ert-string-for-test-result result nil)
(ert-test-name test)
- (if (getenv "EMACS_TEST_VERBOSE")
+ (if (cl-plusp
+ (length (getenv "EMACS_TEST_VERBOSE")))
(ert-reason-for-test-result result)
""))))
(message "%s" ""))
@@ -1490,14 +1511,17 @@ Returns the stats object."
(let* ((max (prin1-to-string (length (ert--stats-tests stats))))
(format-string (concat "%9s %"
(prin1-to-string (length max))
- "s/" max " %S (%f sec)")))
+ "s/" max " %S (%f sec)%s")))
(message format-string
(ert-string-for-test-result result
(ert-test-result-expected-p
test result))
(1+ (ert--stats-test-pos stats test))
(ert-test-name test)
- (ert-test-result-duration result))))))))
+ (ert-test-result-duration result)
+ (if (ert-test-result-expected-p test result)
+ ""
+ (concat " " (ert-test-location test))))))))))
nil))
;;;###autoload
@@ -1510,18 +1534,28 @@ of the tests (e.g. invalid SELECTOR or bug in the code that runs
the tests)."
(or noninteractive
(user-error "This function is only for use in batch mode"))
- ;; Better crash loudly than attempting to recover from undefined
- ;; behavior.
- (setq attempt-stack-overflow-recovery nil
- attempt-orderly-shutdown-on-fatal-signal nil)
- (unwind-protect
- (let ((stats (ert-run-tests-batch selector)))
- (kill-emacs (if (zerop (ert-stats-completed-unexpected stats)) 0 1)))
+ (let ((eln-dir (and (featurep 'native-compile)
+ (make-temp-file "test-nativecomp-cache-" t))))
+ (when eln-dir
+ (startup-redirect-eln-cache eln-dir))
+ ;; Better crash loudly than attempting to recover from undefined
+ ;; behavior.
+ (setq attempt-stack-overflow-recovery nil
+ attempt-orderly-shutdown-on-fatal-signal nil)
(unwind-protect
- (progn
- (message "Error running tests")
- (backtrace))
- (kill-emacs 2))))
+ (let ((stats (ert-run-tests-batch selector)))
+ (when eln-dir
+ (ignore-errors
+ (delete-directory eln-dir t)))
+ (kill-emacs (if (zerop (ert-stats-completed-unexpected stats)) 0 1)))
+ (unwind-protect
+ (progn
+ (message "Error running tests")
+ (backtrace))
+ (when eln-dir
+ (ignore-errors
+ (delete-directory eln-dir t)))
+ (kill-emacs 2)))))
(defvar ert-load-file-name nil
"The name of the loaded ERT test file, a string.
@@ -2846,8 +2880,14 @@ To be used in the ERT results buffer."
nil)
(defun ert-test-erts-file (file &optional transform)
- "Parse FILE as a file containing before/after parts.
-TRANSFORM will be called to get from before to after."
+ "Parse FILE as a file containing before/after parts (an erts file).
+
+This function puts the \"before\" section of an .erts file into a
+temporary buffer, calls the TRANSFORM function, and then compares
+the result with the \"after\" section.
+
+See Info node `(ert) erts files' for more information on how to
+write erts files."
(with-temp-buffer
(insert-file-contents file)
(let ((gen-specs (list (cons 'dummy t)
diff --git a/lisp/emacs-lisp/faceup.el b/lisp/emacs-lisp/faceup.el
index 77689f434c2..b44132dcead 100644
--- a/lisp/emacs-lisp/faceup.el
+++ b/lisp/emacs-lisp/faceup.el
@@ -1006,7 +1006,7 @@ which could be defined as:
(defun my-test-explain (args...)
(let ((faceup-test-explain t))
(the-test args...)))
- (put 'my-test 'ert-explainer 'my-test-explain)
+ (put \\='my-test \\='ert-explainer \\='my-test-explain)
Alternative, you can use the macro `faceup-defexplainer' as follows:
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index c4f48b8a79e..486d5d08614 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -61,6 +61,7 @@
"^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\
foo\\|\\(?:[^icfgv]\\|g[^r]\\)\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\
+cl-\\(?:defun\\|defmethod\\|defgeneric\\)\\|\
menu-bar-make-toggle\\|menu-bar-make-toggle-command\\)"
find-function-space-re
"\\('\\|(quote \\)?%s\\(\\s-\\|$\\|[()]\\)")
@@ -123,6 +124,15 @@ should insert the feature name."
:group 'xref
:version "25.1")
+(defcustom find-ert-deftest-regexp
+ "(ert-deftest +'%s"
+ "The regexp used to search for an ert-deftest definition.
+Note it must contain a `%s' at the place where `format'
+should insert the feature name."
+ :type 'regexp
+ :group 'xref
+ :version "29.1")
+
(defun find-function--defface (symbol)
(catch 'found
(while (re-search-forward (format find-face-regexp symbol) nil t)
@@ -136,7 +146,8 @@ should insert the feature name."
(defvar . find-variable-regexp)
(defface . find-function--defface)
(feature . find-feature-regexp)
- (defalias . find-alias-regexp))
+ (defalias . find-alias-regexp)
+ (ert-deftest . find-ert-deftest-regexp))
"Alist mapping definition types into regexp variables.
Each regexp variable's value should actually be a format string
to be used to substitute the desired symbol name into the regexp.
@@ -173,6 +184,16 @@ See the functions `find-function' and `find-variable'."
:group 'find-function
:version "20.3")
+(defcustom find-library-include-other-files t
+ "If non-nil, `read-library-name' will also include non-library files.
+This affects commands like `read-library'.
+
+If nil, only library files (i.e., \".el\" files) will be offered
+for completion."
+ :type 'boolean
+ :version "29.1"
+ :group 'find-function)
+
;;; Functions:
(defun find-library-suffixes ()
@@ -248,11 +269,7 @@ defined in C.")
If FUNC is not a symbol, return it. Else, if it's not advised,
return the symbol's function definition."
(or (and (symbolp func)
- (featurep 'nadvice)
- (let ((ofunc (advice--symbol-function func)))
- (if (advice--p ofunc)
- (advice--cd*r ofunc)
- ofunc)))
+ (advice--cd*r (symbol-function func)))
func))
(defun find-function-C-source (fun-or-var file type)
@@ -292,7 +309,10 @@ TYPE should be nil to find a function, or `defvar' to find a variable."
Interactively, prompt for LIBRARY using the one at or near point.
This function searches `find-library-source-path' if non-nil, and
-`load-path' otherwise."
+`load-path' otherwise.
+
+See the `find-library-include-other-files' user option for
+customizing the candidate completions."
(interactive (list (read-library-name)))
(prog1
(switch-to-buffer (find-file-noselect (find-library-name library)))
@@ -307,8 +327,6 @@ in a directory under `load-path' (or `find-library-source-path',
if non-nil)."
(let* ((dirs (or find-library-source-path load-path))
(suffixes (find-library-suffixes))
- (table (apply-partially 'locate-file-completion-table
- dirs suffixes))
(def (if (eq (function-called-at-point) 'require)
;; `function-called-at-point' may return 'require
;; with `point' anywhere on this line. So wrap the
@@ -322,10 +340,28 @@ if non-nil)."
(thing-at-point 'symbol))
(error nil))
(thing-at-point 'symbol))))
- (when (and def (not (test-completion def table)))
- (setq def nil))
- (completing-read (format-prompt "Library name" def)
- table nil nil nil nil def)))
+ (if find-library-include-other-files
+ (let ((table (apply-partially #'locate-file-completion-table
+ dirs suffixes)))
+ (when (and def (not (test-completion def table)))
+ (setq def nil))
+ (completing-read (format-prompt "Library name" def)
+ table nil nil nil nil def))
+ (let ((files (read-library-name--find-files dirs suffixes)))
+ (when (and def (not (member def files)))
+ (setq def nil))
+ (completing-read (format-prompt "Library name" def)
+ files nil t nil nil def)))))
+
+(defun read-library-name--find-files (dirs suffixes)
+ "Return a list of all files in DIRS that match SUFFIXES."
+ (let ((files nil)
+ (regexp (concat (regexp-opt suffixes) "\\'")))
+ (dolist (dir dirs)
+ (dolist (file (ignore-errors (directory-files dir nil regexp t)))
+ (and (string-match regexp file)
+ (push (substring file 0 (match-beginning 0)) files))))
+ files))
;;;###autoload
(defun find-library-other-window (library)
@@ -476,8 +512,8 @@ Return t if any PRED returns t."
(defun find-function-library (function &optional lisp-only verbose)
"Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION.
-ORIG-FUNCTION is the original name, after removing all advice and
-resolving aliases. LIBRARY is an absolute file name, a relative
+ORIG-FUNCTION is the original name, after resolving aliases.
+LIBRARY is an absolute file name, a relative
file name inside the C sources directory, or a name of an
autoloaded feature.
@@ -764,7 +800,10 @@ See `find-function-on-key'."
(define-key ctl-x-5-map "K" 'find-function-on-key-other-frame)
(define-key ctl-x-map "V" 'find-variable)
(define-key ctl-x-4-map "V" 'find-variable-other-window)
- (define-key ctl-x-5-map "V" 'find-variable-other-frame))
+ (define-key ctl-x-5-map "V" 'find-variable-other-frame)
+ (define-key ctl-x-map "L" 'find-library)
+ (define-key ctl-x-4-map "L" 'find-library-other-window)
+ (define-key ctl-x-5-map "L" 'find-library-other-frame))
(provide 'find-func)
diff --git a/lisp/emacs-lisp/generate-lisp-file.el b/lisp/emacs-lisp/generate-lisp-file.el
new file mode 100644
index 00000000000..8896a3f7019
--- /dev/null
+++ b/lisp/emacs-lisp/generate-lisp-file.el
@@ -0,0 +1,113 @@
+;;; generate-lisp-file.el --- utility functions for generated files -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Keywords: maint
+;; Package: emacs
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+
+(cl-defun generate-lisp-file-heading (file generator
+ &key title commentary (code t))
+ "Insert a standard header for FILE created by GENERATOR.
+This header will specify that this is a generated file that
+should not be edited.
+
+If `standard-output' is bound to a buffer, insert in that buffer.
+If no, insert at point in the current buffer.
+
+TITLE (if any) will be used in the first line.
+
+COMMENTARY (if given) will be inserted as a comment.
+
+If CODE is non-nil (which is the default), a Code: line is
+inserted."
+ (with-current-buffer (if (bufferp standard-output)
+ standard-output
+ (current-buffer))
+ (insert ";;; " (file-name-nondirectory file)
+ " --- "
+ (or title "automatically generated")
+ " (do not edit) "
+ " -*- lexical-binding: t -*-\n"
+ (format ";; Generated by the `%s' function.\n\n" generator)
+ ";; This file is part of GNU Emacs.\n\n")
+ (when commentary
+ (insert ";;; Commentary:\n\n")
+ (let ((start (point))
+ (fill-prefix ";; "))
+ (insert ";; " commentary)
+ (fill-region start (point))))
+ (ensure-empty-lines 1)
+ (when code
+ (insert ";;; Code:\n\n"))))
+
+(cl-defun generate-lisp-file-trailer (file &key version inhibit-provide
+ (coding 'utf-8-emacs-unix) autoloads
+ compile provide)
+ "Insert a standard trailer for FILE.
+By default, this trailer inhibits version control, byte
+compilation, updating autoloads, and uses a `utf-8-emacs-unix'
+coding system. These can be inhibited by providing non-nil
+values to the VERSION, NO-PROVIDE, AUTOLOADS and COMPILE
+keyword arguments.
+
+CODING defaults to `utf-8-emacs-unix'. Use a nil value to
+inhibit generating this setting, or a coding system value to use
+that.
+
+If PROVIDE is non-nil, use that in the `provide' statement
+instead of using FILE as the basis.
+
+If `standard-output' is bound to a buffer, insert in that buffer.
+If no, insert at point in the current buffer."
+ (with-current-buffer (if (bufferp standard-output)
+ standard-output
+ (current-buffer))
+ (ensure-empty-lines 1)
+ (unless inhibit-provide
+ (insert (format "(provide '%s)\n\n"
+ (or provide
+ (file-name-sans-extension
+ (file-name-nondirectory file))))))
+ ;; Some of the strings below are chopped into bits to inhibit
+ ;; automatic scanning tools from thinking that they are actual
+ ;; directives.
+ (insert ";; Local " "Variables:\n")
+ (unless version
+ (insert ";; version-control: never\n"))
+ (unless compile
+ (insert ";; no-byte-" "compile: t\n")) ;; #$ is byte-compiled into nil.
+ (unless autoloads
+ (insert ";; no-update-autoloads: t\n"))
+ (when coding
+ (insert (format ";; coding: %s\n"
+ (if (eq coding t)
+ 'utf-8-emacs-unix
+ coding))))
+ (insert
+ ";; End:\n\n"
+ ";;; " (file-name-nondirectory file) " ends here\n")))
+
+(provide 'generate-lisp-file)
+
+;;; generate-lisp-file.el ends here
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 1e9793261f9..54ddc7ac757 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -594,7 +594,7 @@ binding mode."
code
(macroexp-warn-and-return
"Use of gv-ref probably requires lexical-binding"
- code))))
+ code nil nil place))))
(defsubst gv-deref (ref)
"Dereference REF, returning the referenced value.
@@ -602,7 +602,7 @@ This is like the `*' operator of the C language.
REF must have been previously obtained with `gv-ref'."
(funcall (car ref)))
;; Don't use `declare' because it seems to introduce circularity problems:
-;; Warning: Eager macro-expansion skipped due to cycle:
+;; Eager macro-expansion skipped due to cycle:
;; … => (load "gv.el") => (macroexpand-all (defsubst gv-deref …)) => (macroexpand (defun …)) => (load "gv.el")
(gv-define-setter gv-deref (v ref) `(funcall (cdr ,ref) ,v))
diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el
index 930dbfe6c49..654dbbc5fef 100644
--- a/lisp/emacs-lisp/helper.el
+++ b/lisp/emacs-lisp/helper.el
@@ -1,6 +1,6 @@
;;; helper.el --- utility help package supporting help in electric modes -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 2001-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2022 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
@@ -39,19 +39,16 @@
;; keymap either.
-(defvar Helper-help-map
- (let ((map (make-sparse-keymap)))
- ;(fillarray map 'undefined)
- (define-key map "m" 'Helper-describe-mode)
- (define-key map "b" 'Helper-describe-bindings)
- (define-key map "c" 'Helper-describe-key-briefly)
- (define-key map "k" 'Helper-describe-key)
- ;(define-key map "f" 'Helper-describe-function)
- ;(define-key map "v" 'Helper-describe-variable)
- (define-key map "?" 'Helper-help-options)
- (define-key map (char-to-string help-char) 'Helper-help-options)
- (fset 'Helper-help-map map)
- map))
+(defvar-keymap Helper-help-map
+ "m" #'Helper-describe-mode
+ "b" #'Helper-describe-bindings
+ "c" #'Helper-describe-key-briefly
+ "k" #'Helper-describe-key
+ ;;"f" #'Helper-describe-function
+ ;;"v" #'Helper-describe-variable
+ "?" #'Helper-help-options
+ (key-description (char-to-string help-char)) #'Helper-help-options)
+(fset 'Helper-help-map Helper-help-map)
(defun Helper-help-scroller ()
(let ((blurb (or (and (boundp 'Helper-return-blurb)
@@ -68,26 +65,30 @@
(setq state (+ (* 2 (if (pos-visible-in-window-p (point-max)) 1 0))
(if (pos-visible-in-window-p (point-min)) 1 0)))
(message
- (nth state
- '("Space forward, Delete back. Other keys %s"
- "Space scrolls forward. Other keys %s"
- "Delete scrolls back. Other keys %s"
- "Type anything to %s"))
+ (nth state
+ (mapcar
+ #'substitute-command-keys
+ '("\\`SPC' forward, \\`DEL' back. Other keys %s"
+ "\\`SPC' scrolls forward. Other keys %s"
+ "\\`DEL' scrolls back. Other keys %s"
+ "Type anything to %s")))
blurb)
(setq continue (read-event))
(cond ((and (memq continue '(?\s ?\C-v)) (< state 2))
(scroll-up))
- ((= continue ?\C-l)
+ ((eq continue ?\C-l)
(recenter))
- ((and (= continue ?\177) (zerop (% state 2)))
+ ((and (or (eq continue 'backspace)
+ (eq continue ?\177))
+ (zerop (% state 2)))
(scroll-down))
(t (setq continue nil))))))))
(defun Helper-help-options ()
"Describe help options."
(interactive)
- (message "c (key briefly), m (mode), k (key), b (bindings)")
- ;(message "c (key briefly), m (mode), k (key), v (variable), f (function)")
+ (message (substitute-command-keys
+ "\\`c' (key briefly), \\`m' (mode), \\`k' (key), \\`b' (bindings)"))
(sit-for 4))
(defun Helper-describe-key-briefly (key)
@@ -140,7 +141,8 @@
(interactive)
(let ((continue t) c)
(while continue
- (message "Help (Type ? for further options)")
+ (message (substitute-command-keys
+ "Help (Type \\`?' for further options)"))
(setq c (read-key-sequence nil))
(setq c (lookup-key Helper-help-map c))
(cond ((eq c 'Helper-help-options)
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index 963e117ff34..de0112db631 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -71,7 +71,7 @@
(defmacro inline-quote (_exp)
"Similar to backquote, but quotes code and only accepts , and not ,@."
- (declare (debug backquote-form))
+ (declare (debug (backquote-form)))
(error "inline-quote can only be used within define-inline"))
(defmacro inline-const-p (_exp)
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
index b871a832466..7c6f89deb11 100644
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ b/lisp/emacs-lisp/lisp-mnt.el
@@ -111,8 +111,6 @@
;;; Code:
-(require 'mail-parse)
-
;;; Variables:
(defgroup lisp-mnt nil
@@ -361,6 +359,8 @@ Return argument is of the form (\"HOLDER\" \"YEAR1\" ... \"YEARN\")"
(defun lm-crack-address (x)
"Split up email address(es) X into full name and real email address.
The value is a list of elements of the form (FULLNAME . ADDRESS)."
+ (require 'mail-parse)
+ (declare-function mail-header-parse-addresses-lax "mail-parse" (string))
(mapcar (lambda (elem)
(cons (cdr elem) (car elem)))
(mail-header-parse-addresses-lax x)))
@@ -505,7 +505,7 @@ absent, return nil."
(if (and page (string-match (rx bol "<" (+ nonl) ">" eol) page))
(substring page 1 -1)
page)))
-(defalias 'lm-homepage 'lm-website) ; for backwards-compatibility
+(defalias 'lm-homepage #'lm-website) ; for backwards-compatibility
;;; Verification and synopses
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 7df40e36f8f..68528e199f8 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -89,73 +89,88 @@
table)
"Syntax table used in `lisp-mode'.")
+(rx-define lisp-mode-symbol (+ (| (syntax word)
+ (syntax symbol)
+ (: "\\" nonl))))
+
(eval-and-compile
- (defconst lisp-mode-symbol-regexp "\\(?:\\sw\\|\\s_\\|\\\\.\\)+"))
+ (defconst lisp-mode-symbol-regexp (rx lisp-mode-symbol)))
(defvar lisp-imenu-generic-expression
(list
(list nil
(purecopy (concat "^\\s-*("
- (eval-when-compile
- (regexp-opt
- '("defun" "defmacro"
- ;; Elisp.
- "defun*" "defsubst" "define-inline"
- "define-advice" "defadvice" "define-skeleton"
- "define-compilation-mode" "define-minor-mode"
- "define-global-minor-mode"
- "define-globalized-minor-mode"
- "define-derived-mode" "define-generic-mode"
- "ert-deftest"
- "cl-defun" "cl-defsubst" "cl-defmacro"
- "cl-define-compiler-macro" "cl-defgeneric"
- "cl-defmethod"
- ;; CL.
- "define-compiler-macro" "define-modify-macro"
- "defsetf" "define-setf-expander"
- "define-method-combination"
- ;; CLOS and EIEIO
- "defgeneric" "defmethod")
- t))
- "\\s-+\\(" lisp-mode-symbol-regexp "\\)"))
+ (regexp-opt
+ '("defun" "defmacro"
+ ;; Elisp.
+ "defun*" "defsubst" "define-inline"
+ "define-advice" "defadvice" "define-skeleton"
+ "define-compilation-mode" "define-minor-mode"
+ "define-global-minor-mode"
+ "define-globalized-minor-mode"
+ "define-derived-mode" "define-generic-mode"
+ "ert-deftest"
+ "cl-defun" "cl-defsubst" "cl-defmacro"
+ "cl-define-compiler-macro" "cl-defgeneric"
+ "cl-defmethod"
+ ;; CL.
+ "define-compiler-macro" "define-modify-macro"
+ "defsetf" "define-setf-expander"
+ "define-method-combination"
+ ;; CLOS and EIEIO
+ "defgeneric" "defmethod")
+ t)
+ "\\s-+\\(" (rx lisp-mode-symbol) "\\)"))
+ 2)
+ ;; Like the previous, but uses a quoted symbol as the name.
+ (list nil
+ (purecopy (concat "^\\s-*("
+ (regexp-opt
+ '("defalias" "define-obsolete-function-alias")
+ t)
+ "\\s-+'\\(" (rx lisp-mode-symbol) "\\)"))
2)
(list (purecopy "Variables")
(purecopy (concat "^\\s-*("
- (eval-when-compile
- (regexp-opt
- '(;; Elisp
- "defconst" "defcustom"
- ;; CL
- "defconstant"
- "defparameter" "define-symbol-macro")
- t))
- "\\s-+\\(" lisp-mode-symbol-regexp "\\)"))
+ (regexp-opt
+ '(;; Elisp
+ "defconst" "defcustom"
+ ;; CL
+ "defconstant"
+ "defparameter" "define-symbol-macro")
+ t)
+ "\\s-+\\(" (rx lisp-mode-symbol) "\\)"))
2)
;; For `defvar'/`defvar-local', we ignore (defvar FOO) constructs.
(list (purecopy "Variables")
(purecopy (concat "^\\s-*(defvar\\(?:-local\\)?\\s-+\\("
- lisp-mode-symbol-regexp "\\)"
+ (rx lisp-mode-symbol) "\\)"
"[[:space:]\n]+[^)]"))
1)
(list (purecopy "Types")
(purecopy (concat "^\\s-*("
- (eval-when-compile
- (regexp-opt
- '(;; Elisp
- "defgroup" "deftheme"
- "define-widget" "define-error"
- "defface" "cl-deftype" "cl-defstruct"
- ;; CL
- "deftype" "defstruct"
- "define-condition" "defpackage"
- ;; CLOS and EIEIO
- "defclass")
- t))
- "\\s-+'?\\(" lisp-mode-symbol-regexp "\\)"))
+ (regexp-opt
+ '(;; Elisp
+ "defgroup" "deftheme"
+ "define-widget" "define-error"
+ "defface" "cl-deftype" "cl-defstruct"
+ ;; CL
+ "deftype" "defstruct"
+ "define-condition" "defpackage"
+ ;; CLOS and EIEIO
+ "defclass")
+ t)
+ "\\s-+'?\\(" (rx lisp-mode-symbol) "\\)"))
2))
"Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
+(defconst lisp-mode-autoload-regexp
+ "^;;;###\\(\\([-[:alnum:]]+?\\)-\\)?\\(autoload\\)"
+ "Regexp to match autoload cookies.
+The second group matches package names used to redirect autoloads
+to a package-local <package>-loaddefs.el file.")
+
;; This was originally in autoload.el and is still used there.
(put 'autoload 'doc-string-elt 3)
(put 'defmethod 'doc-string-elt 3)
@@ -235,6 +250,9 @@
('let
(forward-sexp 1)
(>= pos (point)))
+ ((or 'defun 'defmacro 'cl-defmethod 'cl-defun)
+ (forward-sexp 2)
+ (>= pos (point)))
('condition-case
;; If (cdr paren-posns), then we're in the BODY
;; of HANDLERS.
@@ -251,8 +269,7 @@
;; FIXME: Move to elisp-mode.el.
(catch 'found
(while (re-search-forward
- (eval-when-compile
- (concat "(\\(" lisp-mode-symbol-regexp "\\)\\_>"))
+ (concat "(\\(" (rx lisp-mode-symbol) "\\)\\_>")
limit t)
(let ((sym (intern-soft (match-string 1))))
(when (and (or (special-form-p sym) (macrop sym))
@@ -401,8 +418,8 @@ This will generate compile-time constants from BINDINGS."
;; Any whitespace and defined object.
"[ \t']*"
"\\(([ \t']*\\)?" ;; An opening paren.
- "\\(\\(setf\\)[ \t]+" lisp-mode-symbol-regexp
- "\\|" lisp-mode-symbol-regexp "\\)?")
+ "\\(\\(setf\\)[ \t]+" (rx lisp-mode-symbol)
+ "\\|" (rx lisp-mode-symbol) "\\)?")
(1 font-lock-keyword-face)
(3 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type)))
(cond ((eq type 'var) font-lock-variable-name-face)
@@ -418,7 +435,8 @@ This will generate compile-time constants from BINDINGS."
nil t))
;; Emacs Lisp autoload cookies. Supports the slightly different
;; forms used by mh-e, calendar, etc.
- ("^;;;###\\([-a-z]*autoload\\)" 1 font-lock-warning-face prepend))
+ (,lisp-mode-autoload-regexp (3 font-lock-warning-face prepend)
+ (2 font-lock-function-name-face prepend t)))
"Subdued level highlighting for Emacs Lisp mode.")
(defconst lisp-cl-font-lock-keywords-1
@@ -427,8 +445,8 @@ This will generate compile-time constants from BINDINGS."
;; Any whitespace and defined object.
"[ \t']*"
"\\(([ \t']*\\)?" ;; An opening paren.
- "\\(\\(setf\\)[ \t]+" lisp-mode-symbol-regexp
- "\\|" lisp-mode-symbol-regexp "\\)?")
+ "\\(\\(setf\\)[ \t]+" (rx lisp-mode-symbol)
+ "\\|" (rx lisp-mode-symbol) "\\)?")
(1 font-lock-keyword-face)
(3 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type)))
(cond ((eq type 'var) font-lock-variable-name-face)
@@ -454,23 +472,34 @@ This will generate compile-time constants from BINDINGS."
(lisp--el-match-keyword . 1)
;; Exit/Feature symbols as constants.
(,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>"
- "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?")
+ "[ \t']*\\(" (rx lisp-mode-symbol) "\\)?")
(1 font-lock-keyword-face)
(2 font-lock-constant-face nil t))
- ;; Words inside \\[] tend to be for `substitute-command-keys'.
- (,(concat "\\\\\\\\\\[\\(" lisp-mode-symbol-regexp "\\)\\]")
+ ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for
+ ;; `substitute-command-keys'.
+ (,(rx "\\\\" (or (seq "[" (group-n 1 lisp-mode-symbol) "]")
+ (seq "`" (group-n 1
+ ;; allow multiple words, e.g. "C-x a"
+ lisp-mode-symbol (* " " lisp-mode-symbol))
+ "'")))
(1 font-lock-constant-face prepend))
+ (,(rx "\\\\" (or (seq "<" (group-n 1 lisp-mode-symbol) ">")
+ (seq "{" (group-n 1 lisp-mode-symbol) "}")))
+ (1 font-lock-variable-name-face prepend))
;; Ineffective backslashes (typically in need of doubling).
("\\(\\\\\\)\\([^\"\\]\\)"
(1 (elisp--font-lock-backslash) prepend))
;; Words inside ‘’, '' and `' tend to be symbol names.
- (,(concat "[`‘']\\(" lisp-mode-symbol-regexp "\\)['’]")
+ (,(concat "[`‘']\\(" (rx lisp-mode-symbol) "\\)['’]")
(1 font-lock-constant-face prepend))
+ ;; \\= tends to be an escape in doc strings.
+ (,(rx "\\\\=")
+ (0 font-lock-builtin-face prepend))
;; Constant values.
- (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>")
+ (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>")
(0 font-lock-builtin-face))
;; ELisp and CLisp `&' keywords as types.
- (,(concat "\\_<&" lisp-mode-symbol-regexp "\\_>")
+ (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>")
. font-lock-type-face)
;; ELisp regexp grouping constructs
(,(lambda (bound)
@@ -507,30 +536,30 @@ This will generate compile-time constants from BINDINGS."
(,(concat "(" cl-kws-re "\\_>") . 1)
;; Exit/Feature symbols as constants.
(,(concat "(\\(catch\\|throw\\|provide\\|require\\)\\_>"
- "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?")
+ "[ \t']*\\(" (rx lisp-mode-symbol) "\\)?")
(1 font-lock-keyword-face)
(2 font-lock-constant-face nil t))
;; Erroneous structures.
(,(concat "(" cl-errs-re "\\_>")
(1 font-lock-warning-face))
;; Words inside ‘’ and `' tend to be symbol names.
- (,(concat "[`‘]\\(" lisp-mode-symbol-regexp "\\)['’]")
+ (,(concat "[`‘]\\(" (rx lisp-mode-symbol) "\\)['’]")
(1 font-lock-constant-face prepend))
;; Uninterned symbols, e.g., (defpackage #:my-package ...)
;; must come before keywords below to have effect
- (,(concat "#:" lisp-mode-symbol-regexp "") 0 font-lock-builtin-face)
+ (,(concat "#:" (rx lisp-mode-symbol) "") 0 font-lock-builtin-face)
;; Constant values.
- (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>")
+ (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>")
(0 font-lock-builtin-face))
;; ELisp and CLisp `&' keywords as types.
- (,(concat "\\_<&" lisp-mode-symbol-regexp "\\_>")
+ (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>")
. font-lock-type-face)
;; This is too general -- rms.
;; A user complained that he has functions whose names start with `do'
;; and that they get the wrong color.
;; That user has violated the https://www.cliki.net/Naming+conventions:
;; CL (but not EL!) `with-' (context) and `do-' (iteration)
- (,(concat "(\\(\\(do-\\|with-\\)" lisp-mode-symbol-regexp "\\)")
+ (,(concat "(\\(\\(do-\\|with-\\)" (rx lisp-mode-symbol) "\\)")
(1 font-lock-keyword-face))
(lisp--match-hidden-arg
(0 '(face font-lock-warning-face
@@ -557,16 +586,15 @@ This will generate compile-time constants from BINDINGS."
"Gaudy highlighting from Emacs Lisp mode used in Backtrace mode.")
(defun lisp-string-in-doc-position-p (listbeg startpos)
- "Return non-nil if a doc string may occur at STARTPOS inside a list.
+ "Return non-nil if a doc string may occur at STARTPOS inside a list.
LISTBEG is the position of the start of the innermost list
containing STARTPOS."
(let* ((firstsym (and listbeg
(save-excursion
(goto-char listbeg)
(and (looking-at
- (eval-when-compile
- (concat "([ \t\n]*\\("
- lisp-mode-symbol-regexp "\\)")))
+ (concat "([ \t\n]*\\("
+ (rx lisp-mode-symbol) "\\)"))
(match-string 1)))))
(docelt (and firstsym
(function-get (intern-soft firstsym)
@@ -648,7 +676,9 @@ font-lock keywords will not be case sensitive."
(setq-local indent-line-function 'lisp-indent-line)
(setq-local indent-region-function 'lisp-indent-region)
(setq-local comment-indent-function #'lisp-comment-indent)
- (setq-local outline-regexp ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|(")
+ (setq-local outline-regexp (concat ";;;;* [^ \t\n]\\|(\\|\\("
+ lisp-mode-autoload-regexp
+ "\\)"))
(setq-local outline-level 'lisp-outline-level)
(setq-local add-log-current-defun-function #'lisp-current-defun-name)
(setq-local comment-start ";")
@@ -688,7 +718,8 @@ font-lock keywords will not be case sensitive."
;; Expects outline-regexp is ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|("
;; and point is at the beginning of a matching line.
(let ((len (- (match-end 0) (match-beginning 0))))
- (cond ((looking-at "(\\|;;;###autoload")
+ (cond ((or (looking-at-p "(")
+ (looking-at-p lisp-mode-autoload-regexp))
1000)
((looking-at ";;\\(;+\\) ")
(- (match-end 1) (match-beginning 1)))
@@ -722,17 +753,16 @@ font-lock keywords will not be case sensitive."
(progn (forward-sexp 1)
(point)))))))
-(defvar lisp-mode-shared-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map prog-mode-map)
- (define-key map "\e\C-q" 'indent-sexp)
- (define-key map "\177" 'backward-delete-char-untabify)
- ;; This gets in the way when viewing a Lisp file in view-mode. As
- ;; long as [backspace] is mapped into DEL via the
- ;; function-key-map, this should remain disabled!!
- ;;;(define-key map [backspace] 'backward-delete-char-untabify)
- map)
- "Keymap for commands shared by all sorts of Lisp modes.")
+(defvar-keymap lisp-mode-shared-map
+ :doc "Keymap for commands shared by all sorts of Lisp modes."
+ :parent prog-mode-map
+ "C-M-q" #'indent-sexp
+ "DEL" #'backward-delete-char-untabify
+ ;; This gets in the way when viewing a Lisp file in view-mode. As
+ ;; long as [backspace] is mapped into DEL via the
+ ;; function-key-map, this should remain disabled!!
+ ;;;"<backspace>" #'backward-delete-char-untabify
+ )
(defcustom lisp-mode-hook nil
"Hook run when entering Lisp mode."
@@ -748,14 +778,12 @@ font-lock keywords will not be case sensitive."
;;; Generic Lisp mode.
-(defvar lisp-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map lisp-mode-shared-map)
- (define-key map "\e\C-x" 'lisp-eval-defun)
- (define-key map "\C-c\C-z" 'run-lisp)
- map)
- "Keymap for ordinary Lisp mode.
-All commands in `lisp-mode-shared-map' are inherited by this map.")
+(defvar-keymap lisp-mode-map
+ :doc "Keymap for ordinary Lisp mode.
+All commands in `lisp-mode-shared-map' are inherited by this map."
+ :parent lisp-mode-shared-map
+ "C-M-x" #'lisp-eval-defun
+ "C-c C-z" #'run-lisp)
(easy-menu-define lisp-mode-menu lisp-mode-map
"Menu for ordinary Lisp mode."
@@ -810,9 +838,8 @@ or to switch back to an existing one."
(defcustom lisp-indent-offset nil
"If non-nil, indent second line of expressions that many more columns."
:group 'lisp
- :type '(choice (const nil) integer))
-(put 'lisp-indent-offset 'safe-local-variable
- (lambda (x) (or (null x) (integerp x))))
+ :type '(choice (const nil) integer)
+ :safe (lambda (x) (or (null x) (integerp x))))
(defcustom lisp-indent-function 'lisp-indent-function
"A function to be called by `calculate-lisp-indent'.
@@ -1224,8 +1251,8 @@ Lisp function does not specify a special indentation."
(defcustom lisp-body-indent 2
"Number of columns to indent the second line of a `(def...)' form."
:group 'lisp
- :type 'integer)
-(put 'lisp-body-indent 'safe-local-variable 'integerp)
+ :type 'integer
+ :safe #'integerp)
(defun lisp-indent-specform (count state indent-point normal-indent)
(let ((containing-form-start (elt state 1))
@@ -1386,9 +1413,8 @@ Any non-integer value means do not use a different value of
`fill-column' when filling docstrings."
:type '(choice (integer)
(const :tag "Use the current `fill-column'" t))
+ :safe (lambda (x) (or (eq x t) (integerp x)))
:group 'lisp)
-(put 'emacs-lisp-docstring-fill-column 'safe-local-variable
- (lambda (x) (or (eq x t) (integerp x))))
(defun lisp-fill-paragraph (&optional justify)
"Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings.
@@ -1401,6 +1427,9 @@ and initial semicolons."
;; a comment: Point is on a program line; we are interested
;; particularly in docstring lines.
;;
+ ;; FIXME: The below bindings are probably mostly irrelevant
+ ;; since we're now narrowing to a region before filling.
+ ;;
;; We bind `paragraph-start' and `paragraph-separate' temporarily. They
;; are buffer-local, but we avoid changing them so that they can be set
;; to make `forward-paragraph' and friends do something the user wants.
@@ -1436,29 +1465,58 @@ and initial semicolons."
(derived-mode-p 'emacs-lisp-mode))
emacs-lisp-docstring-fill-column
fill-column)))
- (save-restriction
+ (let ((ppss (syntax-ppss))
+ (start (point)))
(save-excursion
- (let ((ppss (syntax-ppss))
- (start (point)))
- ;; If we're in a string, then narrow (roughly) to that
- ;; string before filling. This avoids filling Lisp
- ;; statements that follow the string.
- (when (ppss-string-terminator ppss)
- (goto-char (ppss-comment-or-string-start ppss))
- (beginning-of-line)
- ;; The string may be unterminated -- in that case, don't
- ;; narrow.
- (when (ignore-errors
- (progn
- (forward-sexp 1)
- t))
- (narrow-to-region (ppss-comment-or-string-start ppss)
- (point))))
- ;; Move back to where we were.
+ (save-restriction
+ ;; If we're not inside a string, then do very basic
+ ;; filling. This avoids corrupting embedded strings in
+ ;; code.
+ (if (not (ppss-comment-or-string-start ppss))
+ (lisp--fill-line-simple)
+ ;; If we're in a string, then narrow (roughly) to that
+ ;; string before filling. This avoids filling Lisp
+ ;; statements that follow the string.
+ (when (ppss-string-terminator ppss)
+ (goto-char (ppss-comment-or-string-start ppss))
+ ;; The string may be unterminated -- in that case, don't
+ ;; narrow.
+ (when (ignore-errors
+ (progn
+ (forward-sexp 1)
+ t))
+ (narrow-to-region (1+ (ppss-comment-or-string-start ppss))
+ (1- (point)))))
+ ;; Move back to where we were.
+ (goto-char start)
+ ;; We should fill the first line of a string
+ ;; separately (since it's usually a doc string).
+ (if (= (line-number-at-pos) 1)
+ (narrow-to-region (line-beginning-position)
+ (line-beginning-position 2))
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (narrow-to-region (point) (point-max))))
+ (fill-paragraph justify)))))))
+ ;; Never return nil.
+ t)
+
+(defun lisp--fill-line-simple ()
+ (narrow-to-region (line-beginning-position) (line-end-position))
+ (goto-char (point-min))
+ (while (and (not (eobp))
+ (re-search-forward "\\_>" nil t))
+ (when (> (current-column) fill-column)
+ (let ((start (point)))
+ (backward-sexp)
+ (if (looking-back "[[(]" (point-min))
(goto-char start)
- (fill-paragraph justify)))))
- ;; Never return nil.
- t))
+ (skip-chars-backward " \t")
+ (insert "\n")
+ (forward-sexp))))
+ (unless (eobp)
+ (forward-char 1))))
(defun indent-code-rigidly (start end arg &optional nochange-regexp)
"Indent all lines of code, starting in the region, sideways by ARG columns.
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 4aeca9c6b00..4b85414943a 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -171,6 +171,8 @@ This command assumes point is not in a string or comment.
If INTERACTIVE is non-nil, as it is interactively,
report errors as appropriate for this kind of usage."
(interactive "^p\nd")
+ (when (ppss-comment-or-string-start (syntax-ppss))
+ (user-error "This command doesn't work in strings or comments"))
(if interactive
(condition-case _
(down-list arg nil)
@@ -855,14 +857,33 @@ The option `delete-pair-blink-delay' can disable blinking."
(delete-char -1)))
(delete-char 1))))
-(defun raise-sexp (&optional arg)
- "Raise ARG sexps higher up the tree."
+(defun raise-sexp (&optional n)
+ "Raise N sexps one level higher up the tree.
+
+This function removes the sexp enclosing the form which follows
+point, and then re-inserts N sexps that originally followe point,
+thus raising those N sexps one level up.
+
+Interactively, N is the numeric prefix argument, and defaults to 1.
+
+For instance, if you have:
+
+ (let ((foo 2))
+ (progn
+ (setq foo 3)
+ (zot)
+ (+ foo 2)))
+
+and point is before (zot), \\[raise-sexp] will give you
+
+ (let ((foo 2))
+ (zot))"
(interactive "p")
(let ((s (if (and transient-mark-mode mark-active)
(buffer-substring (region-beginning) (region-end))
(buffer-substring
(point)
- (save-excursion (forward-sexp arg) (point))))))
+ (save-excursion (forward-sexp n) (point))))))
(backward-up-list 1)
(delete-region (point) (save-excursion (forward-sexp 1) (point)))
(save-excursion (insert s))))
@@ -922,14 +943,7 @@ character."
(defun field-complete (table &optional predicate)
(declare (obsolete completion-in-region "24.4"))
(let ((minibuffer-completion-table table)
- (minibuffer-completion-predicate predicate)
- ;; This made sense for lisp-complete-symbol, but for
- ;; field-complete, this is out of place. --Stef
- ;; (completion-annotate-function
- ;; (unless (eq predicate 'fboundp)
- ;; (lambda (str)
- ;; (if (fboundp (intern-soft str)) " <f>"))))
- )
+ (minibuffer-completion-predicate predicate))
(call-interactively 'minibuffer-complete)))
(defun lisp-complete-symbol (&optional _predicate)
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
new file mode 100644
index 00000000000..2c92a8e7fe8
--- /dev/null
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -0,0 +1,710 @@
+;;; loaddefs-gen.el --- generate loaddefs.el files -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Keywords: maint
+;; Package: emacs
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package generates the main lisp/loaddefs.el file, as well as
+;; all the other loaddefs files, like calendar/diary-loaddefs.el, etc.
+
+;; The main entry point is `loaddefs-generate' (normally called
+;; from loaddefs-generate-batch via lisp/Makefile).
+;;
+;; The "other" loaddefs files are specified either via a file-local
+;; setting of `generated-autoload-file', or by specifying
+;;
+;; ;;;###foo-autoload
+;;
+;; This makes the autoload go to foo-loaddefs.el in the current directory.
+;; Normal ;;;###autoload specs go to the main loaddefs file.
+
+;;; Code:
+
+(require 'radix-tree)
+(require 'lisp-mnt)
+(require 'generate-lisp-file)
+
+(defvar autoload-compute-prefixes t
+ "If non-nil, autoload will add code to register the prefixes used in a file.
+Standard prefixes won't be registered anyway. I.e. if a file
+\"foo.el\" defines variables or functions that use \"foo-\" as
+prefix, that will not be registered. But all other prefixes will
+be included.")
+(put 'autoload-compute-prefixes 'safe-local-variable #'booleanp)
+
+(defvar autoload-ignored-definitions
+ '("define-obsolete-function-alias"
+ "define-obsolete-variable-alias"
+ "define-category" "define-key"
+ "defgroup" "defface" "defadvice"
+ "def-edebug-spec"
+ ;; Hmm... this is getting ugly:
+ "define-widget"
+ "define-erc-module"
+ "define-erc-response-handler"
+ "defun-rcirc-command")
+ "List of strings naming definitions to ignore for prefixes.
+More specifically those definitions will not be considered for the
+`register-definition-prefixes' call.")
+
+(defvar generated-autoload-file nil
+ "File into which to write autoload definitions.
+A Lisp file can set this in its local variables section to make
+its autoloads go somewhere else.
+
+If this is a relative file name, the directory is determined as
+follows:
+ - If a Lisp file defined `generated-autoload-file' as a
+ file-local variable, use its containing directory.
+ - Otherwise use the \"lisp\" subdirectory of `source-directory'.
+
+The autoload file is assumed to contain a trailer starting with a
+FormFeed character.")
+;;;###autoload
+(put 'generated-autoload-file 'safe-local-variable 'stringp)
+
+(defvar generated-autoload-load-name nil
+ "Load name for `autoload' statements generated from autoload cookies.
+If nil, this defaults to the file name, sans extension.
+Typically, you need to set this when the directory containing the file
+is not in `load-path'.
+This also affects the generated cus-load.el file.")
+;;;###autoload
+(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
+
+(defun loaddefs-generate--file-load-name (file outfile)
+ "Compute the name that will be used to load FILE.
+OUTFILE should be the name of the global loaddefs.el file, which
+is expected to be at the root directory of the files we are
+scanning for autoloads and will be in the `load-path'."
+ (let* ((name (file-relative-name file (file-name-directory outfile)))
+ (names '())
+ (dir (file-name-directory outfile)))
+ ;; If `name' has directory components, only keep the
+ ;; last few that are really needed.
+ (while name
+ (setq name (directory-file-name name))
+ (push (file-name-nondirectory name) names)
+ (setq name (file-name-directory name)))
+ (while (not name)
+ (cond
+ ((null (cdr names)) (setq name (car names)))
+ ((file-exists-p (expand-file-name "subdirs.el" dir))
+ ;; FIXME: here we only check the existence of subdirs.el,
+ ;; without checking its content. This makes it generate wrong load
+ ;; names for cases like lisp/term which is not added to load-path.
+ (setq dir (expand-file-name (pop names) dir)))
+ (t (setq name (mapconcat #'identity names "/")))))
+ (if (string-match "\\.elc?\\(\\.\\|\\'\\)" name)
+ (substring name 0 (match-beginning 0))
+ name)))
+
+(defun loaddefs-generate--make-autoload (form file &optional expansion)
+ "Turn FORM into an autoload or defvar for source file FILE.
+Returns nil if FORM is not a special autoload form (i.e. a function definition
+or macro definition or a defcustom).
+If EXPANSION is non-nil, we're processing the macro expansion of an
+expression, in which case we want to handle forms differently."
+ (let ((car (car-safe form)) expand)
+ (cond
+ ((and expansion (eq car 'defalias))
+ (pcase-let*
+ ((`(,_ ,_ ,arg . ,rest) form)
+ ;; `type' is non-nil if it defines a macro.
+ ;; `fun' is the function part of `arg' (defaults to `arg').
+ ((or (and (or `(cons 'macro ,fun) `'(macro . ,fun)) (let type t))
+ (and (let fun arg) (let type nil)))
+ arg)
+ ;; `lam' is the lambda expression in `fun' (or nil if not
+ ;; recognized).
+ (lam (if (memq (car-safe fun) '(quote function)) (cadr fun)))
+ ;; `args' is the list of arguments (or t if not recognized).
+ ;; `body' is the body of `lam' (or t if not recognized).
+ ((or `(lambda ,args . ,body)
+ (and (let args t) (let body t)))
+ lam)
+ ;; Get the `doc' from `body' or `rest'.
+ (doc (cond ((stringp (car-safe body)) (car body))
+ ((stringp (car-safe rest)) (car rest))))
+ ;; Look for an interactive spec.
+ (interactive (pcase body
+ ((or `((interactive . ,iargs) . ,_)
+ `(,_ (interactive . ,iargs) . ,_))
+ ;; List of modes or just t.
+ (if (nthcdr 1 iargs)
+ (list 'quote (nthcdr 1 iargs))
+ t)))))
+ ;; Add the usage form at the end where describe-function-1
+ ;; can recover it.
+ (when (consp args) (setq doc (help-add-fundoc-usage doc args)))
+ ;; (message "autoload of %S" (nth 1 form))
+ `(autoload ,(nth 1 form) ,file ,doc ,interactive ,type)))
+
+ ((and expansion (memq car '(progn prog1)))
+ (let ((end (memq :autoload-end form)))
+ (when end ;Cut-off anything after the :autoload-end marker.
+ (setq form (copy-sequence form))
+ (setcdr (memq :autoload-end form) nil))
+ (let ((exps (delq nil (mapcar (lambda (form)
+ (loaddefs-generate--make-autoload
+ form file expansion))
+ (cdr form)))))
+ (when exps (cons 'progn exps)))))
+
+ ;; For complex cases, try again on the macro-expansion.
+ ((and (memq car '(easy-mmode-define-global-mode define-global-minor-mode
+ define-globalized-minor-mode defun defmacro
+ easy-mmode-define-minor-mode define-minor-mode
+ define-inline cl-defun cl-defmacro cl-defgeneric
+ cl-defstruct pcase-defmacro iter-defun cl-iter-defun))
+ (macrop car)
+ (setq expand (let ((load-true-file-name file)
+ (load-file-name file))
+ (macroexpand form)))
+ (memq (car expand) '(progn prog1 defalias)))
+ ;; Recurse on the expansion.
+ (loaddefs-generate--make-autoload expand file 'expansion))
+
+ ;; For special function-like operators, use the `autoload' function.
+ ((memq car '(define-skeleton define-derived-mode
+ define-compilation-mode define-generic-mode
+ easy-mmode-define-global-mode define-global-minor-mode
+ define-globalized-minor-mode
+ easy-mmode-define-minor-mode define-minor-mode
+ cl-defun defun* cl-defmacro defmacro*
+ define-overloadable-function))
+ (let* ((macrop (memq car '(defmacro cl-defmacro defmacro*)))
+ (name (nth 1 form))
+ (args (pcase car
+ ((or 'defun 'defmacro
+ 'defun* 'defmacro* 'cl-defun 'cl-defmacro
+ 'define-overloadable-function)
+ (nth 2 form))
+ ('define-skeleton '(&optional str arg))
+ ((or 'define-generic-mode 'define-derived-mode
+ 'define-compilation-mode)
+ nil)
+ (_ t)))
+ (body (nthcdr (or (function-get car 'doc-string-elt) 3) form))
+ (doc (if (stringp (car body)) (pop body))))
+ ;; Add the usage form at the end where describe-function-1
+ ;; can recover it.
+ (when (listp args) (setq doc (help-add-fundoc-usage doc args)))
+ ;; `define-generic-mode' quotes the name, so take care of that
+ `(autoload ,(if (listp name) name (list 'quote name))
+ ,file ,doc
+ ,(or (and (memq car '(define-skeleton define-derived-mode
+ define-generic-mode
+ easy-mmode-define-global-mode
+ define-global-minor-mode
+ define-globalized-minor-mode
+ easy-mmode-define-minor-mode
+ define-minor-mode))
+ t)
+ (and (eq (car-safe (car body)) 'interactive)
+ ;; List of modes or just t.
+ (or (if (nthcdr 1 (car body))
+ (list 'quote (nthcdr 1 (car body)))
+ t))))
+ ,(if macrop ''macro nil))))
+
+ ;; For defclass forms, use `eieio-defclass-autoload'.
+ ((eq car 'defclass)
+ (let ((name (nth 1 form))
+ (superclasses (nth 2 form))
+ (doc (nth 4 form)))
+ (list 'eieio-defclass-autoload (list 'quote name)
+ (list 'quote superclasses) file doc)))
+
+ ;; Convert defcustom to less space-consuming data.
+ ((eq car 'defcustom)
+ (let* ((varname (car-safe (cdr-safe form)))
+ (props (nthcdr 4 form))
+ (initializer (plist-get props :initialize))
+ (init (car-safe (cdr-safe (cdr-safe form))))
+ (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form)))))
+ ;; (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form)))))
+ )
+ `(progn
+ ,(if (not (member initializer '(nil 'custom-initialize-default
+ #'custom-initialize-default
+ 'custom-initialize-reset
+ #'custom-initialize-reset)))
+ form
+ `(defvar ,varname ,init ,doc))
+ ;; When we include the complete `form', this `custom-autoload'
+ ;; is not indispensable, but it still helps in case the `defcustom'
+ ;; doesn't specify its group explicitly, and probably in a few other
+ ;; corner cases.
+ (custom-autoload ',varname ,file
+ ,(condition-case nil
+ (null (plist-get props :set))
+ (error nil)))
+ ;; Propagate the :safe property to the loaddefs file.
+ ,@(when-let ((safe (plist-get props :safe)))
+ `((put ',varname 'safe-local-variable ,safe))))))
+
+ ((eq car 'defgroup)
+ ;; In Emacs this is normally handled separately by cus-dep.el, but for
+ ;; third party packages, it can be convenient to explicitly autoload
+ ;; a group.
+ (let ((groupname (nth 1 form)))
+ `(let ((loads (get ',groupname 'custom-loads)))
+ (if (member ',file loads) nil
+ (put ',groupname 'custom-loads (cons ',file loads))))))
+
+ ;; When processing a macro expansion, any expression
+ ;; before a :autoload-end should be included. These are typically (put
+ ;; 'fun 'prop val) and things like that.
+ ((and expansion (consp form)) form)
+
+ ;; nil here indicates that this is not a special autoload form.
+ (t nil))))
+
+(defun loaddefs-generate--make-prefixes (defs file)
+ ;; Remove the defs that obey the rule that file foo.el (or
+ ;; foo-mode.el) uses "foo-" as prefix. Then compute a small set of
+ ;; prefixes that cover all the remaining definitions.
+ (let* ((tree (let ((tree radix-tree-empty))
+ (dolist (def defs)
+ (setq tree (radix-tree-insert tree def t)))
+ tree))
+ (prefixes nil))
+ ;; Get the root prefixes, that we should include in any case.
+ (radix-tree-iter-subtrees
+ tree (lambda (prefix subtree)
+ (push (cons prefix subtree) prefixes)))
+ ;; In some cases, the root prefixes are too short, e.g. if you define
+ ;; "cc-helper" and "c-mode", you'll get "c" in the root prefixes.
+ (dolist (pair (prog1 prefixes (setq prefixes nil)))
+ (let ((s (car pair)))
+ (if (or (and (> (length s) 2) ; Long enough!
+ ;; But don't use "def" from deffoo-pkg-thing.
+ (not (string= "def" s)))
+ (string-match ".[[:punct:]]\\'" s) ;A real (tho short) prefix?
+ (radix-tree-lookup (cdr pair) "")) ;Nothing to expand!
+ (push pair prefixes) ;Keep it as is.
+ (radix-tree-iter-subtrees
+ (cdr pair) (lambda (prefix subtree)
+ (push (cons (concat s prefix) subtree) prefixes))))))
+ (when prefixes
+ (let ((strings
+ (mapcar
+ (lambda (x)
+ (let ((prefix (car x)))
+ (if (or (> (length prefix) 2) ;Long enough!
+ (and (eq (length prefix) 2)
+ (string-match "[[:punct:]]" prefix)))
+ prefix
+ ;; Some packages really don't follow the rules.
+ ;; Drop the most egregious cases such as the
+ ;; one-letter prefixes.
+ (let ((dropped ()))
+ (radix-tree-iter-mappings
+ (cdr x) (lambda (s _)
+ (push (concat prefix s) dropped)))
+ (message "%s:0: Warning: Not registering prefix \"%s\". Affects: %S"
+ file prefix dropped)
+ nil))))
+ prefixes)))
+ `(register-definition-prefixes ,file ',(sort (delq nil strings)
+ 'string<))))))
+
+(defun loaddefs-generate--parse-file (file main-outfile &optional package-data)
+ "Examing FILE for ;;;###autoload statements.
+MAIN-OUTFILE is the main loaddefs file these statements are
+destined for, but this can be overriden by the buffer-local
+setting of `generated-autoload-file' in FILE, and
+by ;;;###foo-autoload statements.
+
+If PACKAGE-DATA is `only', return only the package data. If t,
+include the package data with the rest of the data. Otherwise,
+don't include."
+ (let ((defs nil)
+ (load-name (loaddefs-generate--file-load-name file main-outfile))
+ (compute-prefixes t)
+ local-outfile inhibit-autoloads)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-max))
+ ;; We "open-code" this version of `hack-local-variables',
+ ;; because it's really slow in bootstrap-emacs.
+ (when (search-backward ";; Local Variables:" (- (point-max) 1000) t)
+ (save-excursion
+ (when (re-search-forward "generated-autoload-file: *" nil t)
+ ;; Buffer-local file that should be interpreted relative to
+ ;; the .el file.
+ (setq local-outfile (expand-file-name (read (current-buffer))
+ (file-name-directory file)))))
+ (save-excursion
+ (when (re-search-forward "generated-autoload-load-name: *" nil t)
+ (setq load-name (read (current-buffer)))))
+ (save-excursion
+ (when (re-search-forward "no-update-autoloads: *" nil t)
+ (setq inhibit-autoloads (read (current-buffer)))))
+ (save-excursion
+ (when (re-search-forward "autoload-compute-prefixes: *" nil t)
+ (setq compute-prefixes (read (current-buffer))))))
+
+ ;; We always return the package version (even for pre-dumped
+ ;; files).
+ (if (not package-data)
+ ;; We have to switch `emacs-lisp-mode' when scanning
+ ;; loaddefs for packages so that `syntax-ppss' later gives
+ ;; correct results.
+ (emacs-lisp-mode)
+ (let ((version (lm-header "version"))
+ package)
+ (when (and version
+ (setq version (ignore-errors (version-to-list version)))
+ (setq package (or (lm-header "package")
+ (file-name-sans-extension
+ (file-name-nondirectory file)))))
+ (push (list (or local-outfile main-outfile) file
+ `(push (purecopy ',(cons (intern package) version))
+ package--builtin-versions))
+ defs))))
+
+ ;; Obey the `no-update-autoloads' file local variable.
+ (when (and (not inhibit-autoloads)
+ (not (eq package-data 'only)))
+ (goto-char (point-min))
+ ;; The cookie might be like ;;;###tramp-autoload...
+ (while (re-search-forward lisp-mode-autoload-regexp nil t)
+ (when (or package-data
+ ;; Outside of the main Emacs build (`package-data'
+ ;; is set in the Emacs build), check that we don't
+ ;; have an autoload cookie on the first column of a
+ ;; doc string or the like. (The Emacs tree
+ ;; shouldn't contain any such instances.)
+ (not (ppss-string-terminator (syntax-ppss))))
+ ;; ... and if we have one of these names, then alter outfile.
+ (let* ((aname (match-string 2))
+ (to-file (if aname
+ (expand-file-name
+ (concat aname "-loaddefs.el")
+ (file-name-directory file))
+ (or local-outfile main-outfile))))
+ (if (eolp)
+ ;; We have a form following.
+ (let* ((form (prog1
+ (read (current-buffer))
+ (unless (bolp)
+ (forward-line 1))))
+ (autoload (or (loaddefs-generate--make-autoload
+ form load-name)
+ form)))
+ ;; We get back either an autoload form, or a tree
+ ;; structure of `(progn ...)' things, so unravel that.
+ (let ((forms (if (eq (car autoload) 'progn)
+ (cdr autoload)
+ (list autoload))))
+ (while forms
+ (let ((elem (pop forms)))
+ (if (eq (car elem) 'progn)
+ ;; More recursion; add it to the start.
+ (setq forms (nconc (cdr elem) forms))
+ ;; We have something to add to the defs; do it.
+ (push (list to-file file elem) defs))))))
+ ;; Just put the rest of the line into the loaddefs.
+ ;; FIXME: We skip the first space if there's more
+ ;; whitespace after.
+ (when (looking-at-p " [\t ]")
+ (forward-char 1))
+ (push (list to-file file
+ (buffer-substring (point) (line-end-position)))
+ defs)))))
+
+ (when (and autoload-compute-prefixes
+ compute-prefixes)
+ (when-let ((form (loaddefs-generate--compute-prefixes load-name)))
+ ;; This output needs to always go in the main loaddefs.el,
+ ;; regardless of `generated-autoload-file'.
+ (push (list main-outfile file form) defs)))))
+ defs))
+
+(defun loaddefs-generate--compute-prefixes (load-name)
+ (goto-char (point-min))
+ (let ((prefs nil))
+ ;; Avoid (defvar <foo>) by requiring a trailing space.
+ (while (re-search-forward
+ "^(\\(def[^ ]+\\) ['(]*\\([^' ()\"\n]+\\)[\n \t]" nil t)
+ (unless (member (match-string 1) autoload-ignored-definitions)
+ (let ((name (match-string-no-properties 2)))
+ (when (save-excursion
+ (goto-char (match-beginning 0))
+ (or (bobp)
+ (progn
+ (forward-line -1)
+ (not (looking-at ";;;###autoload")))))
+ (push name prefs)))))
+ (loaddefs-generate--make-prefixes prefs load-name)))
+
+(defun loaddefs-generate--rubric (file &optional type feature)
+ "Return a string giving the appropriate autoload rubric for FILE.
+TYPE (default \"autoloads\") is a string stating the type of
+information contained in FILE. TYPE \"package\" acts like the default,
+but adds an extra line to the output to modify `load-path'.
+
+If FEATURE is non-nil, FILE will provide a feature. FEATURE may
+be a string naming the feature, otherwise it will be based on
+FILE's name."
+ (let ((lp (and (equal type "package") (setq type "autoloads"))))
+ (with-temp-buffer
+ (generate-lisp-file-heading
+ file 'loaddefs-generate
+ :title (concat "automatically extracted " (or type "autoloads"))
+ :commentary (and (string-match "/lisp/loaddefs\\.el\\'" file)
+ "This file will be copied to ldefs-boot.el and checked in periodically."))
+ (when lp
+ (insert "(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))\n\n"))
+ (insert " \n;;; End of scraped data\n\n")
+ (generate-lisp-file-trailer
+ file :provide (and (stringp feature) feature)
+ :inhibit-provide (not feature))
+ (buffer-string))))
+
+(defun loaddefs-generate--insert-section-header (outbuf autoloads
+ load-name file time)
+ "Insert into buffer OUTBUF the section-header line for FILE.
+The header line lists the file name, its \"load name\", its autoloads,
+and the time the FILE was last updated (the time is inserted only
+if `autoload-timestamps' is non-nil, otherwise a fixed fake time is inserted)."
+ (insert "\f\n;;;### ")
+ (prin1 `(autoloads ,autoloads ,load-name ,file ,time)
+ outbuf)
+ (terpri outbuf)
+ ;; Break that line at spaces, to avoid very long lines.
+ ;; Make each sub-line into a comment.
+ (with-current-buffer outbuf
+ (save-excursion
+ (forward-line -1)
+ (while (not (eolp))
+ (move-to-column 64)
+ (skip-chars-forward "^ \n")
+ (or (eolp)
+ (insert "\n" ";;;;;; "))))))
+
+;;;###autoload
+(defun loaddefs-generate (dir output-file &optional excluded-files
+ extra-data include-package-version
+ generate-full)
+ "Generate loaddefs files for Lisp files in the directories DIRS.
+DIR can be either a single directory or a list of directories.
+
+The autoloads will be written to OUTPUT-FILE. If any Lisp file
+binds `generated-autoload-file' as a file-local variable, write
+its autoloads into the specified file instead.
+
+The function does NOT recursively descend into subdirectories of the
+directory or directories specified.
+
+If EXTRA-DATA, include this string at the start of the generated
+file. This will also force generation of OUTPUT-FILE even if
+there are no autoloads to put into the file.
+
+If INCLUDE-PACKAGE-VERSION, include package version data.
+
+If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
+ (let* ((files-re (let ((tmp nil))
+ (dolist (suf (get-load-suffixes))
+ ;; We don't use module-file-suffix below because
+ ;; we don't want to depend on whether Emacs was
+ ;; built with or without modules support, nor
+ ;; what is the suffix for the underlying OS.
+ (unless (string-match "\\.\\(elc\\|so\\|dll\\)" suf)
+ (push suf tmp)))
+ (concat "\\`[^=.].*" (regexp-opt tmp t) "\\'")))
+ (files (apply #'nconc
+ (mapcar (lambda (d)
+ (directory-files (expand-file-name d)
+ t files-re))
+ (if (consp dir) dir (list dir)))))
+ (updating (and (file-exists-p output-file) (not generate-full)))
+ (defs nil))
+
+ ;; Collect all the autoload data.
+ (let ((progress (make-progress-reporter
+ (byte-compile-info
+ (concat "Scraping files for loaddefs"))
+ 0 (length files) nil 10))
+ (output-time
+ (file-attribute-modification-time (file-attributes output-file)))
+ (file-count 0))
+ (dolist (file files)
+ (progress-reporter-update progress (setq file-count (1+ file-count)))
+ (when (or (not updating)
+ (time-less-p output-time
+ (file-attribute-modification-time
+ (file-attributes file))))
+ (setq defs (nconc
+ (loaddefs-generate--parse-file
+ file output-file
+ ;; We only want the package name from the
+ ;; excluded files.
+ (and include-package-version
+ (if (member (expand-file-name file) excluded-files)
+ 'only
+ t)))
+ defs))))
+ (progress-reporter-done progress))
+
+ ;; If we have no autoloads data, but we have EXTRA-DATA, then
+ ;; generate the (almost) empty file anyway.
+ (if (and (not defs) extra-data)
+ (with-temp-buffer
+ (insert (loaddefs-generate--rubric output-file nil t))
+ (search-backward "\f")
+ (insert extra-data)
+ (ensure-empty-lines 1)
+ (write-region (point-min) (point-max) output-file nil 'silent))
+ ;; We have some data, so generate the loaddef files. First
+ ;; group per output file.
+ (dolist (fdefs (seq-group-by #'car defs))
+ (let ((loaddefs-file (car fdefs)))
+ (with-temp-buffer
+ (if (and updating (file-exists-p loaddefs-file))
+ (insert-file-contents loaddefs-file)
+ (insert (loaddefs-generate--rubric loaddefs-file nil t))
+ (search-backward "\f")
+ (when extra-data
+ (insert extra-data)
+ (ensure-empty-lines 1)))
+ ;; Then group by source file (and sort alphabetically).
+ (dolist (section (sort (seq-group-by #'cadr (cdr fdefs))
+ (lambda (e1 e2)
+ (string<
+ (file-name-sans-extension
+ (file-name-nondirectory (car e1)))
+ (file-name-sans-extension
+ (file-name-nondirectory (car e2)))))))
+ (pop section)
+ (let* ((relfile (file-relative-name
+ (cadar section)
+ (file-name-directory loaddefs-file)))
+ (head (concat "\n\f\n;;; Generated autoloads from "
+ relfile "\n\n")))
+ (when (file-exists-p loaddefs-file)
+ ;; If we're updating an old loaddefs file, then see if
+ ;; there's a section here for this file already.
+ (goto-char (point-min))
+ (if (not (search-forward head nil t))
+ ;; It's a new file; put the data at the end.
+ (progn
+ (goto-char (point-max))
+ (search-backward "\f\n"))
+ ;; Delete the old version of the section.
+ (delete-region (match-beginning 0)
+ (and (search-forward "\n\f\n;;;")
+ (match-beginning 0)))
+ (forward-line -2)))
+ (insert head)
+ (dolist (def (reverse section))
+ (setq def (caddr def))
+ (if (stringp def)
+ (princ def (current-buffer))
+ (loaddefs-generate--print-form def))
+ (unless (bolp)
+ (insert "\n")))))
+ (write-region (point-min) (point-max) loaddefs-file nil 'silent)
+ (byte-compile-info (file-relative-name loaddefs-file lisp-directory)
+ t "GEN")))))))
+
+(defun loaddefs-generate--print-form (def)
+ "Print DEF in the way make-docfile.c expects it."
+ (if (or (not (consp def))
+ (not (symbolp (car def)))
+ (memq (car def) '( make-obsolete
+ define-obsolete-function-alias))
+ (not (stringp (nth 3 def))))
+ (prin1 def (current-buffer) t)
+ ;; The salient point here is that we have to have the doc string
+ ;; that starts with a backslash and a newline, and there mustn't
+ ;; be any newlines before that. So -- typically
+ ;; (defvar foo 'value "\
+ ;; Doc string" ...).
+ (insert "(")
+ (dotimes (_ 3)
+ (prin1 (pop def) (current-buffer)
+ '(t (escape-newlines . t)
+ (escape-control-characters . t)))
+ (insert " "))
+ (let ((start (point)))
+ (prin1 (pop def) (current-buffer) t)
+ (save-excursion
+ (goto-char (1+ start))
+ (insert "\\\n")))
+ (while def
+ (insert " ")
+ (prin1 (pop def) (current-buffer) t))
+ (insert ")")))
+
+(defun loaddefs-generate--excluded-files ()
+ ;; Exclude those files that are preloaded on ALL platforms.
+ ;; These are the ones in loadup.el where "(load" is at the start
+ ;; of the line (crude, but it works).
+ (let ((default-directory (file-name-directory lisp-directory))
+ (excludes nil)
+ file)
+ (with-temp-buffer
+ (insert-file-contents "loadup.el")
+ (while (re-search-forward "^(load \"\\([^\"]+\\)\"" nil t)
+ (setq file (match-string 1))
+ (or (string-match "\\.el\\'" file)
+ (setq file (format "%s.el" file)))
+ (or (string-match "\\`site-" file)
+ (push (expand-file-name file) excludes))))
+ ;; Don't scan ldefs-boot.el, either.
+ (cons (expand-file-name "ldefs-boot.el") excludes)))
+
+;;;###autoload
+(defun loaddefs-generate-batch ()
+ "Generate loaddefs.el files in batch mode.
+This scans for ;;;###autoload forms and related things.
+
+The first element on the command line should be the (main)
+loaddefs.el output file, and the rest are the directories to
+use."
+ (let ((args command-line-args-left))
+ (setq command-line-args-left nil)
+ (loaddefs-generate (cdr args) (expand-file-name (car args)))))
+
+(defun loaddefs-generate--emacs-batch ()
+ "Generate the loaddefs for the Emacs build.
+This is like `loaddefs-generate-batch', but has some specific
+rules for built-in packages and excluded files."
+ (let ((args command-line-args-left)
+ (output-file (expand-file-name "loaddefs.el" lisp-directory)))
+ (setq command-line-args-left nil)
+ (loaddefs-generate
+ args output-file
+ (loaddefs-generate--excluded-files)
+ nil t
+ ;; Always do a complete update if loaddefs-gen.el has been
+ ;; updated.
+ (file-newer-than-file-p
+ (expand-file-name "emacs-lisp/loaddefs-gen.el" lisp-directory)
+ output-file))))
+
+(provide 'loaddefs-gen)
+
+;;; loaddefs-gen.el ends here
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index b44917f7d56..4db50bbaa9b 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -28,6 +28,17 @@
;;; Code:
+(defvar byte-compile-form-stack nil
+ "Dynamic list of successive enclosing forms.
+This is used by the warning message routines to determine a
+source code position. The most accessible element is the current
+most deeply nested form.
+
+Normally a form is manually pushed onto the list at the beginning
+of `byte-compile-form', etc., and manually popped off at its end.
+This is to preserve the data in it in the event of a
+condition-case handling a signaled error.")
+
;; Bound by the top-level `macroexpand-all', and modified to include any
;; macros defined by `defmacro'.
(defvar macroexpand-all-environment nil)
@@ -96,10 +107,11 @@ each clause."
(defun macroexp--compiler-macro (handler form)
(condition-case-unless-debug err
- (apply handler form (cdr form))
+ (let ((symbols-with-pos-enabled t))
+ (apply handler form (cdr form)))
(error
- (message "Compiler-macro error for %S: %S" (car form) err)
- form)))
+ (message "Compiler-macro error for %S: Handler: %S\n%S" (car form) handler err)
+ form)))
(defun macroexp--funcall-if-compiled (_form)
"Pseudo function used internally by macroexp to delay warnings.
@@ -135,25 +147,27 @@ Other uses risk returning non-nil value that point to the wrong file."
(defvar macroexp--warned (make-hash-table :test #'equal :weakness 'key))
-(defun macroexp--warn-wrap (msg form category)
+(defun macroexp--warn-wrap (arg msg form category)
(let ((when-compiled
(lambda ()
(when (if (consp category)
(apply #'byte-compile-warning-enabled-p category)
(byte-compile-warning-enabled-p category))
- (byte-compile-warn "%s" msg)))))
+ (byte-compile-warn-x arg "%s" msg)))))
`(progn
(macroexp--funcall-if-compiled ',when-compiled)
,form)))
(define-obsolete-function-alias 'macroexp--warn-and-return
#'macroexp-warn-and-return "28.1")
-(defun macroexp-warn-and-return (msg form &optional category compile-only)
+(defun macroexp-warn-and-return (msg form &optional category compile-only arg)
"Return code equivalent to FORM labeled with warning MSG.
CATEGORY is the category of the warning, like the categories that
can appear in `byte-compile-warnings'.
COMPILE-ONLY non-nil means no warning should be emitted if the code
-is executed without being compiled first."
+is executed without being compiled first.
+ARG is a symbol (or a form) giving the source code position for the message.
+It should normally be a symbol with position and it defaults to FORM."
(cond
((null msg) form)
((macroexp-compiling-p)
@@ -163,7 +177,7 @@ is executed without being compiled first."
;; macroexpand-all gets right back to macroexpanding `form'.
form
(puthash form form macroexp--warned)
- (macroexp--warn-wrap msg form category)))
+ (macroexp--warn-wrap (or arg form) msg form category)))
(t
(unless compile-only
(message "%sWarning: %s"
@@ -223,7 +237,7 @@ is executed without being compiled first."
fun obsolete
(if (symbolp (symbol-function fun))
"alias" "macro"))
- new-form (list 'obsolete fun)))
+ new-form (list 'obsolete fun) nil fun))
new-form)))
(defun macroexp--unfold-lambda (form &optional name)
@@ -278,7 +292,7 @@ is executed without being compiled first."
"attempt to open-code `%s' with too few arguments"
"attempt to open-code `%s' with too many arguments")
name)
- form)
+ form nil nil arglist)
;; The following leads to infinite recursion when loading a
;; file containing `(defsubst f () (f))', and then trying to
@@ -303,118 +317,171 @@ Only valid during macro-expansion."
"Expand all macros in FORM.
This is an internal version of `macroexpand-all'.
Assumes the caller has bound `macroexpand-all-environment'."
- (if (eq (car-safe form) 'backquote-list*)
- ;; Special-case `backquote-list*', as it is normally a macro that
- ;; generates exceedingly deep expansions from relatively shallow input
- ;; forms. We just process it `in reverse' -- first we expand all the
- ;; arguments, _then_ we expand the top-level definition.
- (macroexpand (macroexp--all-forms form 1)
- macroexpand-all-environment)
- ;; Normal form; get its expansion, and then expand arguments.
- (setq form (macroexp-macroexpand form macroexpand-all-environment))
- ;; FIXME: It'd be nice to use `byte-optimize--pcase' here, but when
- ;; I tried it, it broke the bootstrap :-(
- (pcase form
- (`(cond . ,clauses)
- (macroexp--cons 'cond (macroexp--all-clauses clauses) form))
- (`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
- (macroexp--cons
- 'condition-case
- (macroexp--cons err
- (macroexp--cons (macroexp--expand-all body)
- (macroexp--all-clauses handlers 1)
- (cddr form))
- (cdr form))
- form))
- (`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_)
- (push name macroexp--dynvars)
- (macroexp--all-forms form 2))
- (`(function ,(and f `(lambda . ,_)))
- (let ((macroexp--dynvars macroexp--dynvars))
- (macroexp--cons 'function
- (macroexp--cons (macroexp--all-forms f 2)
- nil
- (cdr form))
- form)))
- (`(,(or 'function 'quote) . ,_) form)
- (`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body)
- pcase--dontcare))
- (let ((macroexp--dynvars macroexp--dynvars))
- (macroexp--cons
- fun
- (macroexp--cons
- (macroexp--all-clauses bindings 1)
- (if (null body)
- (macroexp-unprogn
- (macroexp-warn-and-return
- (format "Empty %s body" fun)
- nil nil 'compile-only))
- (macroexp--all-forms body))
- (cdr form))
- form)))
- (`(,(and fun `(lambda . ,_)) . ,args)
- ;; Embedded lambda in function position.
- ;; If the byte-optimizer is loaded, try to unfold this,
- ;; i.e. rewrite it to (let (<args>) <body>). We'd do it in the optimizer
- ;; anyway, but doing it here (i.e. earlier) can sometimes avoid the
- ;; creation of a closure, thus resulting in much better code.
- (let ((newform (macroexp--unfold-lambda form)))
- (if (eq newform form)
- ;; Unfolding failed for some reason, avoid infinite recursion.
- (macroexp--cons (macroexp--all-forms fun 2)
- (macroexp--all-forms args)
- form)
- (macroexp--expand-all newform))))
-
- (`(funcall . ,(or `(,exp . ,args) pcase--dontcare))
- (let ((eexp (macroexp--expand-all exp))
- (eargs (macroexp--all-forms args)))
- ;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
- ;; has a compiler-macro, or to unfold it.
- (pcase eexp
- (`#',f (macroexp--expand-all `(,f . ,eargs)))
- (_ `(funcall ,eexp . ,eargs)))))
- (`(,func . ,_)
- (let ((handler (function-get func 'compiler-macro))
- (funargs (function-get func 'funarg-positions)))
- ;; Check functions quoted with ' rather than with #'
- (dolist (funarg funargs)
- (let ((arg (nth funarg form)))
- (when (and (eq 'quote (car-safe arg))
- (eq 'lambda (car-safe (cadr arg))))
- (setcar (nthcdr funarg form)
- (macroexp-warn-and-return
- (format "%S quoted with ' rather than with #'"
- (let ((f (cadr arg)))
- (if (symbolp f) f `(lambda ,(nth 1 f) ...))))
- arg)))))
- ;; Macro expand compiler macros. This cannot be delayed to
- ;; byte-optimize-form because the output of the compiler-macro can
- ;; use macros.
- (if (null handler)
- ;; No compiler macro. We just expand each argument (for
- ;; setq/setq-default this works alright because the variable names
- ;; are symbols).
- (macroexp--all-forms form 1)
- ;; If the handler is not loaded yet, try (auto)loading the
- ;; function itself, which may in turn load the handler.
- (unless (functionp handler)
- (with-demoted-errors "macroexp--expand-all: %S"
- (autoload-do-load (indirect-function func) func)))
- (let ((newform (macroexp--compiler-macro handler form)))
- (if (eq form newform)
- ;; The compiler macro did not find anything to do.
- (if (equal form (setq newform (macroexp--all-forms form 1)))
- form
- ;; Maybe after processing the args, some new opportunities
- ;; appeared, so let's try the compiler macro again.
- (setq form (macroexp--compiler-macro handler newform))
- (if (eq newform form)
- newform
- (macroexp--expand-all newform)))
- (macroexp--expand-all newform))))))
-
- (_ form))))
+ (push form byte-compile-form-stack)
+ (prog1
+ (if (eq (car-safe form) 'backquote-list*)
+ ;; Special-case `backquote-list*', as it is normally a macro that
+ ;; generates exceedingly deep expansions from relatively shallow input
+ ;; forms. We just process it `in reverse' -- first we expand all the
+ ;; arguments, _then_ we expand the top-level definition.
+ (macroexpand (macroexp--all-forms form 1)
+ macroexpand-all-environment)
+ ;; Normal form; get its expansion, and then expand arguments.
+ (setq form (macroexp-macroexpand form macroexpand-all-environment))
+ ;; FIXME: It'd be nice to use `byte-optimize--pcase' here, but when
+ ;; I tried it, it broke the bootstrap :-(
+ (let ((fn (car-safe form)))
+ (pcase form
+ (`(cond . ,clauses)
+ (macroexp--cons fn (macroexp--all-clauses clauses) form))
+ (`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
+ (macroexp--cons
+ fn
+ (macroexp--cons err
+ (macroexp--cons (macroexp--expand-all body)
+ (macroexp--all-clauses handlers 1)
+ (cddr form))
+ (cdr form))
+ form))
+ (`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_)
+ (push name macroexp--dynvars)
+ (macroexp--all-forms form 2))
+ (`(function ,(and f `(lambda . ,_)))
+ (let ((macroexp--dynvars macroexp--dynvars))
+ (macroexp--cons fn
+ (macroexp--cons (macroexp--all-forms f 2)
+ nil
+ (cdr form))
+ form)))
+ (`(,(or 'function 'quote) . ,_) form)
+ (`(,(and fun (or 'let 'let*)) . ,(or `(,bindings . ,body)
+ pcase--dontcare))
+ (let ((macroexp--dynvars macroexp--dynvars))
+ (macroexp--cons
+ fun
+ (macroexp--cons
+ (macroexp--all-clauses bindings 1)
+ (if (null body)
+ (macroexp-unprogn
+ (macroexp-warn-and-return
+ (format "Empty %s body" fun)
+ nil nil 'compile-only fun))
+ (macroexp--all-forms body))
+ (cdr form))
+ form)))
+ (`(setq ,(and var (pred symbolp)
+ (pred (not booleanp)) (pred (not keywordp)))
+ ,expr)
+ ;; Fast path for the setq common case.
+ (let ((new-expr (macroexp--expand-all expr)))
+ (if (eq new-expr expr)
+ form
+ `(,fn ,var ,new-expr))))
+ (`(setq . ,args)
+ ;; Normalise to a sequence of (setq SYM EXPR).
+ ;; Malformed code is translated to code that signals an error
+ ;; at run time.
+ (let ((nargs (length args)))
+ (if (/= (logand nargs 1) 0)
+ (macroexp-warn-and-return
+ "odd number of arguments in `setq' form"
+ `(signal 'wrong-number-of-arguments '(setq ,nargs))
+ nil 'compile-only fn)
+ (let ((assignments nil))
+ (while (consp (cdr-safe args))
+ (let* ((var (car args))
+ (expr (cadr args))
+ (new-expr (macroexp--expand-all expr))
+ (assignment
+ (if (and (symbolp var)
+ (not (booleanp var)) (not (keywordp var)))
+ `(,fn ,var ,new-expr)
+ (macroexp-warn-and-return
+ (format-message "attempt to set %s `%s'"
+ (if (symbolp var)
+ "constant"
+ "non-variable")
+ var)
+ (cond
+ ((keywordp var)
+ ;; Accept `(setq :a :a)' for compatibility.
+ `(if (eq ,var ,new-expr)
+ ,var
+ (signal 'setting-constant (list ',var))))
+ ((symbolp var)
+ `(signal 'setting-constant (list ',var)))
+ (t
+ `(signal 'wrong-type-argument
+ (list 'symbolp ',var))))
+ nil 'compile-only var))))
+ (push assignment assignments))
+ (setq args (cddr args)))
+ (cons 'progn (nreverse assignments))))))
+ (`(,(and fun `(lambda . ,_)) . ,args)
+ ;; Embedded lambda in function position.
+ ;; If the byte-optimizer is loaded, try to unfold this,
+ ;; i.e. rewrite it to (let (<args>) <body>). We'd do it in the optimizer
+ ;; anyway, but doing it here (i.e. earlier) can sometimes avoid the
+ ;; creation of a closure, thus resulting in much better code.
+ (let ((newform (macroexp--unfold-lambda form)))
+ (if (eq newform form)
+ ;; Unfolding failed for some reason, avoid infinite recursion.
+ (macroexp--cons (macroexp--all-forms fun 2)
+ (macroexp--all-forms args)
+ form)
+ (macroexp--expand-all newform))))
+ (`(funcall ,exp . ,args)
+ (let ((eexp (macroexp--expand-all exp))
+ (eargs (macroexp--all-forms args)))
+ ;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
+ ;; has a compiler-macro, or to unfold it.
+ (pcase eexp
+ ((and `#',f
+ (guard (not (or (special-form-p f) (macrop f))))) ;; bug#46636
+ (macroexp--expand-all `(,f . ,eargs)))
+ (_ `(funcall ,eexp . ,eargs)))))
+ (`(funcall . ,_) form) ;bug#53227
+ (`(,func . ,_)
+ (let ((handler (function-get func 'compiler-macro))
+ (funargs (function-get func 'funarg-positions)))
+ ;; Check functions quoted with ' rather than with #'
+ (dolist (funarg funargs)
+ (let ((arg (nth funarg form)))
+ (when (and (eq 'quote (car-safe arg))
+ (eq 'lambda (car-safe (cadr arg))))
+ (setcar (nthcdr funarg form)
+ (macroexp-warn-and-return
+ (format "%S quoted with ' rather than with #'"
+ (let ((f (cadr arg)))
+ (if (symbolp f) f `(lambda ,(nth 1 f) ...))))
+ arg nil nil (cadr arg))))))
+ ;; Macro expand compiler macros. This cannot be delayed to
+ ;; byte-optimize-form because the output of the compiler-macro can
+ ;; use macros.
+ (if (null handler)
+ ;; No compiler macro. We just expand each argument (for
+ ;; setq/setq-default this works alright because the variable names
+ ;; are symbols).
+ (macroexp--all-forms form 1)
+ ;; If the handler is not loaded yet, try (auto)loading the
+ ;; function itself, which may in turn load the handler.
+ (unless (functionp handler)
+ (with-demoted-errors "macroexp--expand-all: %S"
+ (autoload-do-load (indirect-function func) func)))
+ (let ((newform (macroexp--compiler-macro handler form)))
+ (if (eq form newform)
+ ;; The compiler macro did not find anything to do.
+ (if (equal form (setq newform (macroexp--all-forms form 1)))
+ form
+ ;; Maybe after processing the args, some new opportunities
+ ;; appeared, so let's try the compiler macro again.
+ (setq form (macroexp--compiler-macro handler newform))
+ (if (eq newform form)
+ newform
+ (macroexp--expand-all newform)))
+ (macroexp--expand-all newform))))))
+ (_ form))))
+ (pop byte-compile-form-stack)))
;; Record which arguments expect functions, so we can warn when those
;; are accidentally quoted with ' rather than with #'
@@ -549,12 +616,20 @@ cases where EXP is a constant."
(defmacro macroexp-let2* (test bindings &rest body)
"Multiple binding version of `macroexp-let2'.
-BINDINGS is a list of elements of the form (SYM EXP). Each EXP
-can refer to symbols specified earlier in the binding list."
+BINDINGS is a list of elements of the form (SYM EXP) or just SYM,
+which then stands for (SYM SYM).
+Each EXP can refer to symbols specified earlier in the binding list.
+
+TEST has to be a symbol, and if it is nil it can be omitted."
(declare (indent 2) (debug (sexp (&rest (sexp form)) body)))
+ (when (consp test) ;; `test' was omitted.
+ (push bindings body)
+ (setq bindings test)
+ (setq test nil))
(pcase-exhaustive bindings
('nil (macroexp-progn body))
- (`((,var ,exp) . ,tl)
+ (`(,(or `(,var ,exp) (and (pred symbolp) var (let exp var)))
+ . ,tl)
`(macroexp-let2 ,test ,var ,exp
(macroexp-let2* ,test ,tl ,@body)))))
@@ -704,38 +779,40 @@ test of free variables in the following ways:
(defun internal-macroexpand-for-load (form full-p)
;; Called from the eager-macroexpansion in readevalloop.
- (cond
- ;; Don't repeat the same warning for every top-level element.
- ((eq 'skip (car macroexp--pending-eager-loads)) form)
- ;; If we detect a cycle, skip macro-expansion for now, and output a warning
- ;; with a trimmed backtrace.
- ((and load-file-name (member load-file-name macroexp--pending-eager-loads))
- (let* ((bt (delq nil
- (mapcar #'macroexp--trim-backtrace-frame
- (macroexp--backtrace))))
- (elem `(load ,(file-name-nondirectory load-file-name)))
- (tail (member elem (cdr (member elem bt)))))
- (if tail (setcdr tail (list '…)))
- (if (eq (car-safe (car bt)) 'macroexpand-all) (setq bt (cdr bt)))
- (if macroexp--debug-eager
- (debug 'eager-macroexp-cycle)
- (message "Warning: Eager macro-expansion skipped due to cycle:\n %s"
+ (let ((symbols-with-pos-enabled t)
+ (print-symbols-bare t))
+ (cond
+ ;; Don't repeat the same warning for every top-level element.
+ ((eq 'skip (car macroexp--pending-eager-loads)) form)
+ ;; If we detect a cycle, skip macro-expansion for now, and output a warning
+ ;; with a trimmed backtrace.
+ ((and load-file-name (member load-file-name macroexp--pending-eager-loads))
+ (let* ((bt (delq nil
+ (mapcar #'macroexp--trim-backtrace-frame
+ (macroexp--backtrace))))
+ (elem `(load ,(file-name-nondirectory load-file-name)))
+ (tail (member elem (cdr (member elem bt)))))
+ (if tail (setcdr tail (list '…)))
+ (if (eq (car-safe (car bt)) 'macroexpand-all) (setq bt (cdr bt)))
+ (if macroexp--debug-eager
+ (debug 'eager-macroexp-cycle)
+ (error "Eager macro-expansion skipped due to cycle:\n %s"
(mapconcat #'prin1-to-string (nreverse bt) " => ")))
- (push 'skip macroexp--pending-eager-loads)
- form))
- (t
- (condition-case err
- (let ((macroexp--pending-eager-loads
- (cons load-file-name macroexp--pending-eager-loads)))
- (if full-p
- (macroexpand--all-toplevel form)
- (macroexpand form)))
- (error
- ;; Hopefully this shouldn't happen thanks to the cycle detection,
- ;; but in case it does happen, let's catch the error and give the
- ;; code a chance to macro-expand later.
- (message "Eager macro-expansion failure: %S" err)
- form)))))
+ (push 'skip macroexp--pending-eager-loads)
+ form))
+ (t
+ (condition-case err
+ (let ((macroexp--pending-eager-loads
+ (cons load-file-name macroexp--pending-eager-loads)))
+ (if full-p
+ (macroexpand--all-toplevel form)
+ (macroexpand form)))
+ (error
+ ;; Hopefully this shouldn't happen thanks to the cycle detection,
+ ;; but in case it does happen, let's catch the error and give the
+ ;; code a chance to macro-expand later.
+ (error "Eager macro-expansion failure: %S" err)
+ form))))))
;; ¡¡¡ Big Ugly Hack !!!
;; src/bootstrap-emacs is mostly used to compile .el files, so it needs
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index b3e7fca4781..c47025f8846 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -278,11 +278,17 @@ Type \\`SPC' or \\`y' to %s the current %s;
;; For backward compatibility check if short y/n answers are preferred.
(defcustom read-answer-short 'auto
- "If non-nil, `read-answer' accepts single-character answers.
+ "If non-nil, the `read-answer' function accepts single-character answers.
If t, accept short (single key-press) answers to the question.
If nil, require long answers. If `auto', accept short answers if
`use-short-answers' is non-nil, or the function cell of `yes-or-no-p'
-is set to `y-or-n-p'."
+is set to `y-or-n-p'.
+
+Note that this variable does not affect calls to the more
+commonly-used `yes-or-no-p' function; it only affects calls to
+the `read-answer' function. To control whether `yes-or-no-p'
+requires a long or a short answer, see the `use-short-answers'
+variable."
:type '(choice (const :tag "Accept short answers" t)
(const :tag "Require long answer" nil)
(const :tag "Guess preference" auto))
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index dea5b34991a..8c67d7c7a25 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -175,7 +175,17 @@ MAP can be an alist, plist, hash-table, or array."
(cl-defgeneric map-delete (map key)
"Delete KEY in-place from MAP and return MAP.
-Keys not present in MAP are ignored.")
+Keys not present in MAP are ignored.
+
+Note that if MAP is a list (either alist or plist), and you're
+deleting the final element in the list, the list isn't actually
+destructively modified (but the return value will reflect the
+deletion). So if you're using this method on a list, you have to
+say
+
+ (setq map (map-delete map key))
+
+for this to work reliably.")
(cl-defmethod map-delete ((map list) key)
;; FIXME: Signal map-not-inplace i.s.o returning a different list?
@@ -540,7 +550,7 @@ TYPE is a list whose car is `hash-table' and cdr a list of
keyword-args forwarded to `make-hash-table'.
Example:
- (map-into '((1 . 3)) '(hash-table :test eql))"
+ (map-into \\='((1 . 3)) \\='(hash-table :test eql))"
(map--into-hash map (cdr type)))
(defun map--make-pcase-bindings (args)
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
index 6cb4cb02e0c..56b1ea6ed48 100644
--- a/lisp/emacs-lisp/memory-report.el
+++ b/lisp/emacs-lisp/memory-report.el
@@ -183,6 +183,10 @@ by counted more than once."
(cl-defgeneric memory-report--object-size-1 (_counted _value)
0)
+;; This shouldn't happen, but there's some leakage.
+(cl-defmethod memory-report--object-size-1 (_ (_value symbol-with-pos))
+ (memory-report--size 'symbol))
+
(cl-defmethod memory-report--object-size-1 (_ (value symbol))
;; Don't count global symbols -- makes sizes of lists of symbols too
;; heavy.
diff --git a/lisp/emacs-lisp/multisession.el b/lisp/emacs-lisp/multisession.el
index e6a2424c518..d6f1ab98faa 100644
--- a/lisp/emacs-lisp/multisession.el
+++ b/lisp/emacs-lisp/multisession.el
@@ -218,10 +218,9 @@ DOC should be a doc string, and ARGS are keywords as applicable to
(let ((print-length nil)
(print-circle t)
(print-level nil))
- (prin1-to-string value))))
- (condition-case nil
- (ignore (read-from-string pvalue))
- (error (error "Unable to store unreadable value: %s" pvalue)))
+ (readablep value))))
+ (when (and value (not pvalue))
+ (error "Unable to store unreadable value: %s" value))
(sqlite-execute
multisession--db
"insert into multisession(package, key, sequence, value) values(?, ?, 1, ?) on conflict(package, key) do update set sequence = sequence + 1, value = ?"
@@ -434,10 +433,16 @@ storage method to list."
multisession-edit-mode)
(unless id
(error "No value on the current line"))
- (let* ((object (make-multisession
- :package (car id)
- :key (cdr id)
- :storage multisession-storage))
+ (let* ((object (or
+ ;; If the multisession variable already exists, use
+ ;; it (so that we update it).
+ (and (intern-soft (cdr id))
+ (bound-and-true-p (intern (cdr id))))
+ ;; Create a new object.
+ (make-multisession
+ :package (car id)
+ :key (cdr id)
+ :storage multisession-storage)))
(value (multisession-value object)))
(setf (multisession-value object)
(car (read-from-string
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 77e140dda19..2d5a1b5e77b 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -42,55 +42,61 @@
;; as this one), so we have to do it by hand!
(push (purecopy '(nadvice 1 0)) package--builtin-versions)
+(oclosure-define (advice
+ (:predicate advice--p)
+ (:copier advice--cons (cdr))
+ (:copier advice--copy (car cdr how props)))
+ car cdr how props)
+
+(eval-when-compile
+ (defmacro advice--make-how-alist (&rest args)
+ `(list
+ ,@(mapcar
+ (lambda (arg)
+ (pcase-let ((`(,how . ,body) arg))
+ `(list ,how
+ (oclosure-lambda (advice (how ,how)) (&rest r)
+ ,@body)
+ ,(replace-regexp-in-string
+ "\\<car\\>" "FUNCTION"
+ (replace-regexp-in-string
+ "\\<cdr\\>" "OLDFUN"
+ (format "%S" `(lambda (&rest r) ,@body))
+ t t)
+ t t))))
+ args))))
+
;;;; Lightweight advice/hook
-(defvar advice--where-alist
- '((:around "\300\301\302\003#\207" 5)
- (:before "\300\301\002\"\210\300\302\002\"\207" 4)
- (:after "\300\302\002\"\300\301\003\"\210\207" 5)
- (:override "\300\301\002\"\207" 4)
- (:after-until "\300\302\002\"\206\013\000\300\301\002\"\207" 4)
- (:after-while "\300\302\002\"\205\013\000\300\301\002\"\207" 4)
- (:before-until "\300\301\002\"\206\013\000\300\302\002\"\207" 4)
- (:before-while "\300\301\002\"\205\013\000\300\302\002\"\207" 4)
- (:filter-args "\300\302\301\003!\"\207" 5)
- (:filter-return "\301\300\302\003\"!\207" 5))
+(defvar advice--how-alist
+ (advice--make-how-alist
+ (:around (apply car cdr r))
+ (:before (apply car r) (apply cdr r))
+ (:after (prog1 (apply cdr r) (apply car r)))
+ (:override (apply car r))
+ (:after-until (or (apply cdr r) (apply car r)))
+ (:after-while (and (apply cdr r) (apply car r)))
+ (:before-until (or (apply car r) (apply cdr r)))
+ (:before-while (and (apply car r) (apply cdr r)))
+ (:filter-args (apply cdr (funcall car r)))
+ (:filter-return (funcall car (apply cdr r))))
"List of descriptions of how to add a function.
-Each element has the form (WHERE BYTECODE STACK) where:
- WHERE is a keyword indicating where the function is added.
- BYTECODE is the corresponding byte-code that will be used.
- STACK is the amount of stack space needed by the byte-code.")
-
-(defvar advice--bytecodes (mapcar #'cadr advice--where-alist))
-
-(defun advice--p (object)
- (and (byte-code-function-p object)
- (eq 128 (aref object 0))
- (memq (length object) '(5 6))
- (memq (aref object 1) advice--bytecodes)
- (eq #'apply (aref (aref object 2) 0))))
-
-(defsubst advice--car (f) (aref (aref f 2) 1))
-(defsubst advice--cdr (f) (aref (aref f 2) 2))
-(defsubst advice--props (f) (aref (aref f 2) 3))
+Each element has the form (HOW OCL DOC) where HOW is a keyword,
+OCL is a \"prototype\" function of type `advice', and
+DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.")
(defun advice--cd*r (f)
(while (advice--p f)
(setq f (advice--cdr f)))
f)
-(defun advice--where (f)
- (let ((bytecode (aref f 1))
- (where nil))
- (dolist (elem advice--where-alist)
- (if (eq bytecode (cadr elem)) (setq where (car elem))))
- where))
+(define-obsolete-function-alias 'advice--where #'advice--how "29.1")
(defun advice--make-single-doc (flist function macrop)
- (let ((where (advice--where flist)))
+ (let ((how (advice--how flist)))
(concat
(format "This %s has %s advice: "
(if macrop "macro" "function")
- where)
+ how)
(let ((fun (advice--car flist)))
(if (symbolp fun) (format-message "`%S'." fun)
(let* ((name (cdr (assq 'name (advice--props flist))))
@@ -180,33 +186,41 @@ Each element has the form (WHERE BYTECODE STACK) where:
`(funcall ',fspec ',(cadr ifm))
(cadr (or iff ifm)))))
-(defun advice--make-1 (byte-code stack-depth function main props)
- "Build a function value that adds FUNCTION to MAIN."
- (let ((adv-sig (gethash main advertised-signature-table))
- (advice
- (apply #'make-byte-code 128 byte-code
- (vector #'apply function main props) stack-depth nil
- (and (or (commandp function) (commandp main))
- (list (advice--make-interactive-form
- function main))))))
- (when adv-sig (puthash advice adv-sig advertised-signature-table))
- advice))
-
-(defun advice--make (where function main props)
- "Build a function value that adds FUNCTION to MAIN at WHERE.
-WHERE is a symbol to select an entry in `advice--where-alist'."
+
+(cl-defmethod oclosure-interactive-form ((ad advice) &optional _)
+ (let ((car (advice--car ad))
+ (cdr (advice--cdr ad)))
+ (when (or (commandp car) (commandp cdr))
+ `(interactive ,(advice--make-interactive-form car cdr)))))
+
+(cl-defmethod cl-print-object ((object advice) stream)
+ (cl-assert (advice--p object))
+ (princ "#f(advice " stream)
+ (cl-print-object (advice--car object) stream)
+ (princ " " stream)
+ (princ (advice--how object) stream)
+ (princ " " stream)
+ (cl-print-object (advice--cdr object) stream)
+ (let ((props (advice--props object)))
+ (when props
+ (princ " " stream)
+ (cl-print-object props stream)))
+ (princ ")" stream))
+
+(defun advice--make (how function main props)
+ "Build a function value that adds FUNCTION to MAIN at HOW.
+HOW is a symbol to select an entry in `advice--how-alist'."
(let ((fd (or (cdr (assq 'depth props)) 0))
(md (if (advice--p main)
(or (cdr (assq 'depth (advice--props main))) 0))))
(if (and md (> fd md))
;; `function' should go deeper.
- (let ((rest (advice--make where function (advice--cdr main) props)))
- (advice--make-1 (aref main 1) (aref main 3)
- (advice--car main) rest (advice--props main)))
- (let ((desc (assq where advice--where-alist)))
- (unless desc (error "Unknown add-function location `%S'" where))
- (advice--make-1 (nth 1 desc) (nth 2 desc)
- function main props)))))
+ (let ((rest (advice--make how function (advice--cdr main) props)))
+ (advice--cons main rest))
+ (let ((proto (assq how advice--how-alist)))
+ (unless proto (error "Unknown add-function location `%S'" how))
+ (advice--copy (cadr proto)
+ function main how props)))))
(defun advice--member-p (function use-name definition)
(let ((found nil))
@@ -232,8 +246,7 @@ WHERE is a symbol to select an entry in `advice--where-alist'."
(if val (car val)
(let ((nrest (advice--tweak rest tweaker)))
(if (eq rest nrest) flist
- (advice--make-1 (aref flist 1) (aref flist 3)
- first nrest props))))))))
+ (advice--cons flist nrest))))))))
;;;###autoload
(defun advice--remove-function (flist function)
@@ -273,11 +286,34 @@ different, but `function-equal' will hopefully ignore those differences.")
((symbolp place) `(default-value ',place))
(t place))))
+(defun nadvice--make-docstring (sym)
+ (let* ((main (documentation (symbol-function sym) 'raw))
+ (ud (help-split-fundoc main 'pcase))
+ (doc (or (cdr ud) main))
+ (col1width (apply #'max (mapcar (lambda (x)
+ (string-width (symbol-name (car x))))
+ advice--how-alist)))
+ (table (mapconcat (lambda (x)
+ (format (format " %%-%ds %%s" col1width)
+ (car x) (nth 2 x)))
+ advice--how-alist "\n"))
+ (table (if global-prettify-symbols-mode
+ (replace-regexp-in-string "(lambda\\>" "(λ" table t t)
+ table))
+ (combined-doc
+ (if (not (string-match "<<>>" doc))
+ doc
+ (replace-match table t t doc))))
+ (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))
+
+(put 'add-function 'function-documentation
+ '(nadvice--make-docstring 'add-function))
+
;;;###autoload
-(defmacro add-function (where place function &optional props)
+(defmacro add-function (how place function &optional props)
;; TODO:
- ;; - maybe let `where' specify some kind of predicate and use it
- ;; to implement things like mode-local or eieio-defmethod.
+ ;; - maybe let `how' specify some kind of predicate and use it
+ ;; to implement things like mode-local or cl-defmethod.
;; Of course, that only makes sense if the predicates of all advices can
;; be combined and made more efficient.
;; :before is like a normal add-hook on a normal hook.
@@ -285,20 +321,11 @@ different, but `function-equal' will hopefully ignore those differences.")
;; :before-until is like add-hook on run-hook-with-args-until-success.
;; Same with :after-* but for (add-hook ... 'append).
"Add a piece of advice on the function stored at PLACE.
-FUNCTION describes the code to add. WHERE describes where to add it.
-WHERE can be explained by showing the resulting new function, as the
+FUNCTION describes the code to add. HOW describes how to add it.
+HOW can be explained by showing the resulting new function, as the
result of combining FUNCTION and the previous value of PLACE, which we
call OLDFUN here:
-`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
-`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
-`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
-`:override' (lambda (&rest r) (apply FUNCTION r))
-`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
-`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
-`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
-`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
-`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
-`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
+<<>>
If FUNCTION was already added, do nothing.
PROPS is an alist of additional properties, among which the following have
a special meaning:
@@ -325,14 +352,14 @@ is also interactive. There are 3 cases:
(declare
;;(indent 2)
(debug (form [&or symbolp ("local" form) ("var" sexp) gv-place]
- form &optional form)))
- `(advice--add-function ,where (gv-ref ,(advice--normalize-place place))
+ form &optional form)))
+ `(advice--add-function ,how (gv-ref ,(advice--normalize-place place))
,function ,props))
(declare-function comp-subr-trampoline-install "comp")
;;;###autoload
-(defun advice--add-function (where ref function props)
+(defun advice--add-function (how ref function props)
(when (and (featurep 'native-compile)
(subr-primitive-p (gv-deref ref)))
(let ((subr-name (intern (subr-name (gv-deref ref)))))
@@ -357,7 +384,7 @@ is also interactive. There are 3 cases:
(advice--remove-function (gv-deref ref)
(or name (advice--car a)))))
(setf (gv-deref ref)
- (advice--make where function (gv-deref ref) props))))
+ (advice--make how function (gv-deref ref) props))))
;;;###autoload
(defmacro remove-function (place function)
@@ -455,11 +482,16 @@ of the piece of advice."
(put symbol 'advice--pending (advice--subst-main oldadv nil)))
(funcall fsetfun symbol newdef))))
+(put 'advice-add 'function-documentation
+ '(nadvice--make-docstring 'advice-add))
+
;;;###autoload
-(defun advice-add (symbol where function &optional props)
+(defun advice-add (symbol how function &optional props)
"Like `add-function' but for the function named SYMBOL.
Contrary to `add-function', this will properly handle the cases where SYMBOL
-is defined as a macro, alias, command, ..."
+is defined as a macro, alias, command, ...
+HOW can be one of:
+<<>>"
;; TODO:
;; - record the advice location, to display in describe-function.
;; - change all defadvice in lisp/**/*.el.
@@ -467,21 +499,21 @@ is defined as a macro, alias, command, ..."
(let* ((f (symbol-function symbol))
(nf (advice--normalize symbol f)))
(unless (eq f nf) (fset symbol nf))
- (add-function where (cond
- ((eq (car-safe nf) 'macro) (cdr nf))
- ;; Reasons to delay installation of the advice:
- ;; - If the function is not yet defined, installing
- ;; the advice would affect `fboundp'ness.
- ;; - the symbol-function slot of an autoloaded
- ;; function is not itself a function value.
- ;; - `autoload' does nothing if the function is
- ;; not an autoload or undefined.
- ((or (not nf) (autoloadp nf))
- (get symbol 'advice--pending))
- (t (symbol-function symbol)))
+ (add-function how (cond
+ ((eq (car-safe nf) 'macro) (cdr nf))
+ ;; Reasons to delay installation of the advice:
+ ;; - If the function is not yet defined, installing
+ ;; the advice would affect `fboundp'ness.
+ ;; - the symbol-function slot of an autoloaded
+ ;; function is not itself a function value.
+ ;; - `autoload' does nothing if the function is
+ ;; not an autoload or undefined.
+ ((or (not nf) (autoloadp nf))
+ (get symbol 'advice--pending))
+ (t (symbol-function symbol)))
function props)
- ;; FIXME: We could use a defmethod on `function-docstring' instead,
- ;; except when (or (not nf) (autoloadp nf))!
+ ;; FIXME: We could use a defmethod on `function-documentation' instead,
+ ;; except when (autoloadp nf)!
(put symbol 'function-documentation `(advice--make-docstring ',symbol))
(add-function :around (get symbol 'defalias-fset-function)
#'advice--defalias-fset))
@@ -517,12 +549,12 @@ See `advice-add' and `add-function' for explanation on the
arguments. Note if NAME is nil the advice is anonymous;
otherwise it is named `SYMBOL@NAME'.
-\(fn SYMBOL (WHERE LAMBDA-LIST &optional NAME DEPTH) &rest BODY)"
+\(fn SYMBOL (HOW LAMBDA-LIST &optional NAME DEPTH) &rest BODY)"
(declare (indent 2) (doc-string 3) (debug (sexp sexp def-body)))
(or (listp args) (signal 'wrong-type-argument (list 'listp args)))
(or (<= 2 (length args) 4)
(signal 'wrong-number-of-arguments (list 2 4 (length args))))
- (let* ((where (nth 0 args))
+ (let* ((how (nth 0 args))
(lambda-list (nth 1 args))
(name (nth 2 args))
(depth (nth 3 args))
@@ -532,7 +564,7 @@ otherwise it is named `SYMBOL@NAME'.
(intern (format "%s@%s" symbol name)))
(t (error "Unrecognized name spec `%S'" name)))))
`(prog1 ,@(and (symbolp advice) `((defun ,advice ,lambda-list ,@body)))
- (advice-add ',symbol ,where #',advice ,@(and props `(',props))))))
+ (advice-add ',symbol ,how #',advice ,@(and props `(',props))))))
(defun advice-mapc (fun symbol)
"Apply FUN to every advice function in SYMBOL.
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el
new file mode 100644
index 00000000000..9775e8cc656
--- /dev/null
+++ b/lisp/emacs-lisp/oclosure.el
@@ -0,0 +1,562 @@
+;;; oclosure.el --- Open Closures -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; An OClosure is an object that combines the properties of records
+;; with those of a function. More specifically it is a function extended
+;; with a notion of type (e.g. for defmethod dispatch) as well as the
+;; ability to have some fields that are accessible from the outside.
+
+;; See "Open closures", ELS'2022 (https://zenodo.org/record/6228797).
+
+;; Here are some cases of "callable objects" where OClosures have found use:
+;; - nadvice.el (the original motivation)
+;; - kmacros (for cl-print and for `kmacro-extract-lambda')
+;; - cl-generic: turn `cl--generic-isnot-nnm-p' into a mere type test
+;; (by putting the no-next-methods into their own class).
+;; - Slot accessor functions, where the type-dispatch can be used to
+;; dynamically compute the docstring, and also to pretty print them.
+;; - `save-some-buffers-function'
+;; Here are other cases of "callable objects" where OClosures could be used:
+;; - Use the type to distinguish macros from functions.
+;; - Use a `name' and `depth' property from the function passed to
+;; `add-function' (or `add-hook') instead of passing it via "props".
+;; - iterators (generator.el), thunks (thunk.el), streams (stream.el).
+;; - PEG rules: they're currently just functions, but they should carry
+;; their original (macro-expanded) definition (and should be printed
+;; differently from functions)!
+;; - auto-generate docstrings for cl-defstruct slot accessors instead of
+;; storing them in the accessor itself?
+;; - SRFI-17's `setter'.
+;; - coercion wrappers, as in "Threesomes, with and without blame"
+;; https://dl.acm.org/doi/10.1145/1706299.1706342, or
+;; "On the Runtime Complexity of Type-Directed Unboxing"
+;; http://sv.c.titech.ac.jp/minamide/papers.html
+;; - An efficient `negate' operation such that
+;; (negate (negate f)) returns just `f' and (negate #'<) returns #'>=.
+;; - Autoloads (tho currently our bytecode functions (and hence OClosures)
+;; are too fat for that).
+
+;; Related constructs:
+;; - `funcallable-standard-object' (FSO) in Common-Lisp. These are different
+;; from OClosures in that they involve an additional indirection to get
+;; to the actual code, and that they offer the possibility of
+;; changing (via mutation) the code associated with
+;; an FSO. Also the FSO's function can't directly access the FSO's
+;; other fields, contrary to the case with OClosures where those are directly
+;; available as local variables.
+;; - Function objects in Javascript.
+;; - Function objects in Python.
+;; - Callable/Applicable classes in OO languages, i.e. classes with
+;; a single method called `apply' or `call'. The most obvious
+;; difference with OClosures (beside the fact that Callable can be
+;; extended with additional methods) is that all instances of
+;; a given Callable class have to use the same method, whereas every
+;; OClosure object comes with its own code, so two OClosure objects of the
+;; same type can have different code. Of course, you can get the
+;; same result by turning every `oclosure-lambda' into its own class
+;; declaration creating an ad-hoc subclass of the specified type.
+;; In this sense, OClosures are just a generalization of `lambda' which brings
+;; some of the extra feature of Callable objects.
+;; - Apply hooks and "entities" in MIT Scheme
+;; https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref/Application-Hooks.html
+;; Apply hooks are basically the same as Common-Lisp's FSOs, and "entities"
+;; are a variant of it where the inner function gets the FSO itself as
+;; additional argument (a kind of "self" arg), thus making it easier
+;; for the code to get data from the object's extra info, tho still
+;; not as easy as with OClosures.
+;; - "entities" in Lisp Machine Lisp (LML)
+;; https://hanshuebner.github.io/lmman/fd-clo.xml
+;; These are arguably identical to OClosures, modulo the fact that LML doesn't
+;; have lexically-scoped closures and uses a form of closures based on
+;; capturing (and reinstating) dynamically scoped bindings instead.
+
+;; Naming: OClosures were originally named FunCallableRecords (FCR), but
+;; that name suggested these were fundamentally records that happened
+;; to be called, whereas OClosures are really just closures that happen
+;; to enjoy some characteristics of records.
+;; The "O" comes from "Open" because OClosures aren't completely opaque
+;; (for that same reason, an alternative name suggested at the time was
+;; "disclosures").
+;; The "O" can also be understood to mean "Object" since you have notions
+;; of inheritance, and the ability to associate methods with particular
+;; OClosure types, just as is the case for OO classes.
+
+;;; Code:
+
+;; TODO:
+;; - `oclosure-(cl-)defun', `oclosure-(cl-)defsubst', `oclosure-define-inline'?
+;; - Use accessor in cl-defstruct.
+;; - Add pcase patterns for OClosures.
+;; - anonymous OClosure types.
+;; - copiers for mixins
+;; - class-allocated slots?
+;; - code-allocated slots?
+;; The `where' slot of `advice' would like to be code-allocated, and the
+;; interactive-spec of commands is currently code-allocated but would like
+;; to be instance-allocated. Their scoping rules are a bit odd, so maybe
+;; it's best to avoid them.
+
+(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x)) ;For `named-let'.
+
+(defun oclosure--index-table (slotdescs)
+ (let ((i -1)
+ (it (make-hash-table :test #'eq)))
+ (dolist (desc slotdescs)
+ (let* ((slot (cl--slot-descriptor-name desc)))
+ (cl-incf i)
+ (when (gethash slot it)
+ (error "Duplicate slot name: %S" slot))
+ (setf (gethash slot it) i)))
+ it))
+
+(cl-defstruct (oclosure--class
+ (:constructor nil)
+ (:constructor oclosure--class-make
+ ( name docstring slots parents allparents
+ &aux (index-table (oclosure--index-table slots))))
+ (:include cl--class)
+ (:copier nil))
+ "Metaclass for OClosure classes."
+ (allparents nil :read-only t :type (list-of symbol)))
+
+(setf (cl--find-class 'oclosure)
+ (oclosure--class-make 'oclosure
+ "The root parent of all OClosure classes"
+ nil nil '(oclosure)))
+(defun oclosure--p (oclosure)
+ (not (not (oclosure-type oclosure))))
+
+(cl-deftype oclosure () '(satisfies oclosure--p))
+
+(defun oclosure--slot-mutable-p (slotdesc)
+ (not (alist-get :read-only (cl--slot-descriptor-props slotdesc))))
+
+(defun oclosure--defstruct-make-copiers (copiers slotdescs name)
+ (require 'cl-macs) ;`cl--arglist-args' is not autoloaded.
+ (let* ((mutables '())
+ (slots (mapcar
+ (lambda (desc)
+ (let ((name (cl--slot-descriptor-name desc)))
+ (when (oclosure--slot-mutable-p desc)
+ (push name mutables))
+ name))
+ slotdescs)))
+ (mapcar
+ (lambda (copier)
+ (pcase-let*
+ ((cname (pop copier))
+ (args (or (pop copier) `(&key ,@slots)))
+ (inline (and (eq :inline (car copier)) (pop copier)))
+ (doc (or (pop copier)
+ (format "Copier for objects of type `%s'." name)))
+ (obj (make-symbol "obj"))
+ (absent (make-symbol "absent"))
+ (anames (cl--arglist-args args))
+ (mnames
+ (let ((res '())
+ (tmp args))
+ (while (and tmp
+ (not (memq (car tmp)
+ cl--lambda-list-keywords)))
+ (push (pop tmp) res))
+ res))
+ (index -1)
+ (mutlist '())
+ (argvals
+ (mapcar
+ (lambda (slot)
+ (setq index (1+ index))
+ (let* ((mutable (memq slot mutables))
+ (get `(oclosure--get ,obj ,index ,(not (not mutable)))))
+ (push mutable mutlist)
+ (cond
+ ((not (memq slot anames)) get)
+ ((memq slot mnames) slot)
+ (t
+ `(if (eq ',absent ,slot)
+ ,get
+ ,slot)))))
+ slots)))
+ `(,(if inline 'cl-defsubst 'cl-defun) ,cname
+ (&cl-defs (',absent) ,obj ,@args)
+ ,doc
+ (declare (side-effect-free t))
+ (oclosure--copy ,obj ',(if (remq nil mutlist) (nreverse mutlist))
+ ,@argvals))))
+ copiers)))
+
+
+(defmacro oclosure-define (name &optional docstring &rest slots)
+ "Define a new OClosure type.
+NAME should be a symbol which is the name of the new type.
+It can also be of the form (NAME . PROPS) in which case PROPS
+is a list of additional properties among the following:
+ (:predicate PRED): asks to create a predicate function named PRED.
+ (:parent TYPE): make TYPE (another OClosure type) be a parent of NAME.
+ (:copier COPIER ARGS): asks to create a \"copier\" (i.e. functional update
+ function) named COPIER. It will take an object of type NAME as first
+ argument followed by ARGS. ARGS lists the names of the slots that will
+ be updated with the value of the corresponding argument.
+SLOTS is a list if slot descriptions. Each slot can be a single symbol
+which is the name of the slot, or it can be of the form (SLOT-NAME . SPROPS)
+where SLOT-NAME is then the name of the slot and SPROPS is a property
+list of slot properties. The currently known properties are the following:
+ `:mutable': A non-nil value mean the slot can be mutated.
+ `:type': Specifies the type of the values expected to appear in the slot."
+ (declare (doc-string 2) (indent 1))
+ (unless (or (stringp docstring) (null docstring))
+ (push docstring slots)
+ (setq docstring nil))
+ (let* ((options (when (consp name)
+ (prog1 (copy-sequence (cdr name))
+ (setq name (car name)))))
+ (get-opt (lambda (opt &optional all)
+ (let ((val (assq opt options))
+ tmp)
+ (when val (setq options (delq val options)))
+ (if (not all)
+ (cdr val)
+ (when val
+ (setq val (list (cdr val)))
+ (while (setq tmp (assq opt options))
+ (push (cdr tmp) val)
+ (setq options (delq tmp options)))
+ (nreverse val))))))
+ (predicate (car (funcall get-opt :predicate)))
+ (parent-names (or (funcall get-opt :parent)
+ (funcall get-opt :include)))
+ (copiers (funcall get-opt :copier 'all)))
+ `(progn
+ ,(when options (macroexp-warn-and-return name
+ (format "Ignored options: %S" options)
+ nil))
+ (eval-and-compile
+ (oclosure--define ',name ,docstring ',parent-names ',slots
+ ,@(when predicate `(:predicate ',predicate))))
+ (oclosure--define-functions ,name ,copiers))))
+
+(defun oclosure--build-class (name docstring parent-names slots)
+ (cl-assert (null (cdr parent-names)))
+ (let* ((parent-class (let ((name (or (car parent-names) 'oclosure)))
+ (or (cl--find-class name)
+ (error "Unknown class: %S" name))))
+ (slotdescs
+ (append
+ (oclosure--class-slots parent-class)
+ (mapcar (lambda (field)
+ (if (not (consp field))
+ (cl--make-slot-descriptor field nil nil
+ '((:read-only . t)))
+ (let ((name (pop field))
+ (type nil)
+ (read-only t)
+ (props '()))
+ (while field
+ (pcase (pop field)
+ (:mutable (setq read-only (not (car field))))
+ (:type (setq type (car field)))
+ (p (message "Unknown property: %S" p)
+ (push (cons p (car field)) props)))
+ (setq field (cdr field)))
+ (cl--make-slot-descriptor name nil type
+ `((:read-only . ,read-only)
+ ,@props)))))
+ slots))))
+ (oclosure--class-make name docstring slotdescs
+ (if (cdr parent-names)
+ (oclosure--class-parents parent-class)
+ (list parent-class))
+ (cons name (oclosure--class-allparents
+ parent-class)))))
+
+(defmacro oclosure--define-functions (name copiers)
+ (let* ((class (cl--find-class name))
+ (slotdescs (oclosure--class-slots class)))
+ `(progn
+ ,@(let ((i -1))
+ (mapcar (lambda (desc)
+ (let* ((slot (cl--slot-descriptor-name desc))
+ (mutable (oclosure--slot-mutable-p desc))
+ ;; Always use a double hyphen: if users wants to
+ ;; make it public, they can do so with an alias.
+ (aname (intern (format "%S--%S" name slot))))
+ (cl-incf i)
+ (if (not mutable)
+ `(defalias ',aname
+ ;; We use `oclosure--copy' instead of
+ ;; `oclosure--accessor-copy' here to circumvent
+ ;; bootstrapping problems.
+ (oclosure--copy
+ oclosure--accessor-prototype
+ nil ',name ',slot ,i))
+ (require 'gv) ;For `gv-setter'.
+ `(progn
+ (defalias ',aname
+ (oclosure--accessor-copy
+ oclosure--mut-getter-prototype
+ ',name ',slot ,i))
+ (defalias ',(gv-setter aname)
+ (oclosure--accessor-copy
+ oclosure--mut-setter-prototype
+ ',name ',slot ,i))))))
+ slotdescs))
+ ,@(oclosure--defstruct-make-copiers
+ copiers slotdescs name))))
+
+;;;###autoload
+(defun oclosure--define (name docstring parent-names slots
+ &rest props)
+ (let* ((class (oclosure--build-class name docstring parent-names slots))
+ (pred (lambda (oclosure)
+ (let ((type (oclosure-type oclosure)))
+ (when type
+ (memq name (oclosure--class-allparents
+ (cl--find-class type)))))))
+ (predname (or (plist-get props :predicate)
+ (intern (format "%s--internal-p" name)))))
+ (setf (cl--find-class name) class)
+ (dolist (slot (oclosure--class-slots class))
+ (put (cl--slot-descriptor-name slot) 'slot-name t))
+ (defalias predname pred)
+ (put name 'cl-deftype-satisfies predname)))
+
+(defmacro oclosure--lambda (type bindings mutables args &rest body)
+ "Low level construction of an OClosure object.
+TYPE should be a form returning an OClosure type (a symbol)
+BINDINGS should list all the slots expected by this type, in the proper order.
+MUTABLE is a list of symbols indicating which of the BINDINGS
+should be mutable.
+No checking is performed,"
+ (declare (indent 3) (debug (sexp (&rest (sexp form)) sexp def-body)))
+ ;; FIXME: Fundamentally `oclosure-lambda' should be a special form.
+ ;; We define it here as a macro which expands to something that
+ ;; looks like "normal code" in order to avoid backward compatibility
+ ;; issues with third party macros that do "code walks" and would
+ ;; likely mishandle such a new special form (e.g. `generator.el').
+ ;; But don't be fooled: this macro is tightly bound to `cconv.el'.
+ (pcase-let*
+ ((`(,prebody . ,body) (macroexp-parse-body body))
+ (rovars (mapcar #'car bindings)))
+ (dolist (mutable mutables)
+ (setq rovars (delq mutable rovars)))
+ `(let ,(mapcar (lambda (bind)
+ (if (cdr bind) bind
+ ;; Bind to something that doesn't look
+ ;; like a value to avoid the "Variable
+ ;; ‘foo’ left uninitialized" warning.
+ `(,(car bind) (progn nil))))
+ (reverse bindings))
+ ;; FIXME: Make sure the slotbinds whose value is duplicable aren't
+ ;; just value/variable-propagated by the optimizer (tho I think our
+ ;; optimizer is too naive to be a problem currently).
+ (oclosure--fix-type
+ ;; This `oclosure--fix-type' + `ignore' call is used by the compiler (in
+ ;; `cconv.el') to detect and signal an error in case of
+ ;; store-conversion (i.e. if a variable/slot is mutated).
+ (ignore ,@rovars)
+ (lambda ,args
+ (:documentation ,type)
+ ,@prebody
+ ;; Add dummy code which accesses the field's vars to make sure
+ ;; they're captured in the closure.
+ (if t nil ,@rovars ,@(mapcar (lambda (m) `(setq ,m ,m)) mutables))
+ ,@body)))))
+
+(defmacro oclosure-lambda (type-and-slots args &rest body)
+ "Define anonymous OClosure function.
+TYPE-AND-SLOTS should be of the form (TYPE . SLOTS)
+where TYPE is an OClosure type name (defined by `oclosure-define')
+and SLOTS is a let-style list of bindings for the various slots of TYPE.
+ARGS and BODY are the same as for `lambda'."
+ (declare (indent 2) (debug ((sexp &rest (sexp form)) sexp def-body)))
+ ;; FIXME: Should `oclosure-define' distinguish "optional" from
+ ;; "mandatory" slots, and/or provide default values for slots missing
+ ;; from `fields'?
+ (pcase-let*
+ ((`(,type . ,fields) type-and-slots)
+ (class (or (cl--find-class type)
+ (error "Unknown class: %S" type)))
+ (slots (oclosure--class-slots class))
+ (mutables '())
+ (slotbinds (mapcar (lambda (slot)
+ (let ((name (cl--slot-descriptor-name slot)))
+ (when (oclosure--slot-mutable-p slot)
+ (push name mutables))
+ (list name)))
+ slots))
+ (tempbinds (mapcar
+ (lambda (field)
+ (let* ((name (car field))
+ (bind (assq name slotbinds)))
+ (cond
+ ;; FIXME: Should we also warn about missing slots?
+ ((not bind)
+ (error "Unknown slot: %S" name))
+ ((cdr bind)
+ (error "Duplicate slot: %S" name))
+ (t
+ (let ((temp (gensym "temp")))
+ (setcdr bind (list temp))
+ (cons temp (cdr field)))))))
+ fields)))
+ ;; FIXME: Optimize temps away when they're provided in the right order?
+ `(let ,tempbinds
+ (oclosure--lambda ',type ,slotbinds ,mutables ,args ,@body))))
+
+(defun oclosure--fix-type (_ignore oclosure)
+ "Helper function to implement `oclosure-lambda' via a macro.
+This has 2 uses:
+- For interpreted code, this converts the representation of type information
+ by moving it from the docstring to the environment.
+- For compiled code, this is used as a marker which cconv uses to check that
+ immutable fields are indeed not mutated."
+ (if (byte-code-function-p oclosure)
+ ;; Actually, this should never happen since the `cconv.el' should have
+ ;; optimized away the call to this function.
+ oclosure
+ ;; For byte-coded functions, we store the type as a symbol in the docstring
+ ;; slot. For interpreted functions, there's no specific docstring slot
+ ;; so `Ffunction' turns the symbol into a string.
+ ;; We thus have convert it back into a symbol (via `intern') and then
+ ;; stuff it into the environment part of the closure with a special
+ ;; marker so we can distinguish this entry from actual variables.
+ (cl-assert (eq 'closure (car-safe oclosure)))
+ (let ((typename (nth 3 oclosure))) ;; The "docstring".
+ (cl-assert (stringp typename))
+ (push (cons :type (intern typename))
+ (cadr oclosure))
+ oclosure)))
+
+(defun oclosure--copy (oclosure mutlist &rest args)
+ (if (byte-code-function-p oclosure)
+ (apply #'make-closure oclosure
+ (if (null mutlist)
+ args
+ (mapcar (lambda (arg) (if (pop mutlist) (list arg) arg)) args)))
+ (cl-assert (eq 'closure (car-safe oclosure))
+ nil "oclosure not closure: %S" oclosure)
+ (cl-assert (eq :type (caar (cadr oclosure))))
+ (let ((env (cadr oclosure)))
+ `(closure
+ (,(car env)
+ ,@(named-let loop ((env (cdr env)) (args args))
+ (when args
+ (cons (cons (caar env) (car args))
+ (loop (cdr env) (cdr args)))))
+ ,@(nthcdr (1+ (length args)) env))
+ ,@(nthcdr 2 oclosure)))))
+
+(defun oclosure--get (oclosure index mutable)
+ (if (byte-code-function-p oclosure)
+ (let* ((csts (aref oclosure 2))
+ (v (aref csts index)))
+ (if mutable (car v) v))
+ (cl-assert (eq 'closure (car-safe oclosure)))
+ (cl-assert (eq :type (caar (cadr oclosure))))
+ (cdr (nth (1+ index) (cadr oclosure)))))
+
+(defun oclosure--set (v oclosure index)
+ (if (byte-code-function-p oclosure)
+ (let* ((csts (aref oclosure 2))
+ (cell (aref csts index)))
+ (setcar cell v))
+ (cl-assert (eq 'closure (car-safe oclosure)))
+ (cl-assert (eq :type (caar (cadr oclosure))))
+ (setcdr (nth (1+ index) (cadr oclosure)) v)))
+
+(defun oclosure-type (oclosure)
+ "Return the type of OCLOSURE, or nil if the arg is not a OClosure."
+ (if (byte-code-function-p oclosure)
+ (let ((type (and (> (length oclosure) 4) (aref oclosure 4))))
+ (if (symbolp type) type))
+ (and (eq 'closure (car-safe oclosure))
+ (let* ((env (car-safe (cdr oclosure)))
+ (first-var (car-safe env)))
+ (and (eq :type (car-safe first-var))
+ (cdr first-var))))))
+
+(defconst oclosure--accessor-prototype
+ ;; Use `oclosure--lambda' to circumvent a bootstrapping problem:
+ ;; `oclosure-accessor' is not yet defined at this point but
+ ;; `oclosure--accessor-prototype' is needed when defining `oclosure-accessor'.
+ (oclosure--lambda 'oclosure-accessor ((type) (slot) (index)) nil
+ (oclosure) (oclosure--get oclosure index nil)))
+
+(oclosure-define accessor
+ "OClosure function to access a specific slot of an object."
+ type slot)
+
+(defun oclosure--accessor-cl-print (object stream)
+ (princ "#f(accessor " stream)
+ (prin1 (accessor--type object) stream)
+ (princ "." stream)
+ (prin1 (accessor--slot object) stream)
+ (princ ")" stream))
+
+(defun oclosure--accessor-docstring (f)
+ ;; This would like to be a (cl-defmethod function-documentation ...)
+ ;; but for circularity reason the defmethod is in `simple.el'.
+ (format "Access slot \"%S\" of OBJ of type `%S'.\n\n(fn OBJ)"
+ (accessor--slot f) (accessor--type f)))
+
+(oclosure-define (oclosure-accessor
+ (:parent accessor)
+ (:copier oclosure--accessor-copy (type slot index)))
+ "OClosure function to access a specific slot of an OClosure function."
+ index)
+
+(defun oclosure--slot-index (oclosure slotname)
+ (gethash slotname
+ (oclosure--class-index-table
+ (cl--find-class (oclosure-type oclosure)))))
+
+(defun oclosure--slot-value (oclosure slotname)
+ (let ((class (cl--find-class (oclosure-type oclosure)))
+ (index (oclosure--slot-index oclosure slotname)))
+ (oclosure--get oclosure index
+ (oclosure--slot-mutable-p
+ (nth index (oclosure--class-slots class))))))
+
+(defun oclosure--set-slot-value (oclosure slotname value)
+ (let ((class (cl--find-class (oclosure-type oclosure)))
+ (index (oclosure--slot-index oclosure slotname)))
+ (unless (oclosure--slot-mutable-p
+ (nth index (oclosure--class-slots class)))
+ (signal 'setting-constant (list oclosure slotname)))
+ (oclosure--set value oclosure index)))
+
+(defconst oclosure--mut-getter-prototype
+ (oclosure-lambda (oclosure-accessor (type) (slot) (index)) (oclosure)
+ (oclosure--get oclosure index t)))
+(defconst oclosure--mut-setter-prototype
+ ;; FIXME: The generated docstring is wrong.
+ (oclosure-lambda (oclosure-accessor (type) (slot) (index)) (val oclosure)
+ (oclosure--set val oclosure index)))
+
+;; Ideally, this should be in `files.el', but that file is loaded
+;; before `oclosure.el'.
+(oclosure-define (save-some-buffers-function
+ (:predicate save-some-buffers-function--p)))
+
+
+(provide 'oclosure)
+;;; oclosure.el ends here
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 42979d16755..8d0d5d57a22 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -355,10 +355,10 @@ More specifically the value can be:
This also applies to the \"archive-contents\" file that lists the
contents of the archive."
- :type '(choice (const nil :tag "Never")
- (const allow-unsigned :tag "Allow unsigned")
- (const t :tag "Check always")
- (const all :tag "Check all signatures"))
+ :type '(choice (const :value nil :tag "Never")
+ (const :value allow-unsigned :tag "Allow unsigned")
+ (const :value t :tag "Check always")
+ (const :value all :tag "Check all signatures"))
:risky t
:version "27.1")
@@ -397,7 +397,13 @@ a sane initial value."
:type '(repeat symbol))
(defcustom package-native-compile nil
- "Non-nil means to native compile packages on installation."
+ "Non-nil means to natively compile packages as part of their installation.
+This controls ahead-of-time compilation of packages when they are
+installed. If this option is nil, packages will be natively
+compiled when they are loaded for the first time.
+
+This option does not have any effect if Emacs was not built with
+native compilation support."
:type '(boolean)
:risky t
:version "28.1")
@@ -412,22 +418,22 @@ synchronously."
(defcustom package-name-column-width 30
"Column width for the Package name in the package menu."
- :type 'number
+ :type 'natnum
:version "28.1")
(defcustom package-version-column-width 14
"Column width for the Package version in the package menu."
- :type 'number
+ :type 'natnum
:version "28.1")
(defcustom package-status-column-width 12
"Column width for the Package status in the package menu."
- :type 'number
+ :type 'natnum
:version "28.1")
(defcustom package-archive-column-width 8
"Column width for the Package archive in the package menu."
- :type 'number
+ :type 'natnum
:version "28.1")
@@ -560,9 +566,9 @@ This is the name of the package with its version appended."
"Return file-name extension of package-desc object PKG-DESC.
Depending on the `package-desc-kind' of PKG-DESC, this is one of:
- 'single - \".el\"
- 'tar - \".tar\"
- 'dir - \"\"
+ \\='single - \".el\"
+ \\='tar - \".tar\"
+ \\='dir - \"\"
Signal an error if the kind is none of the above."
(pcase (package-desc-kind pkg-desc)
@@ -997,9 +1003,11 @@ untar into a directory named DIR; otherwise, signal an error."
(defun package-autoload-ensure-default-file (file)
"Make sure that the autoload file FILE exists and if not create it."
+ (declare (obsolete nil "29.1"))
(unless (file-exists-p file)
(require 'autoload)
- (write-region (autoload-rubric file "package" nil) nil file nil 'silent))
+ (let ((coding-system-for-write 'utf-8-emacs-unix))
+ (write-region (autoload-rubric file "package" nil) nil file nil 'silent)))
file)
(defvar autoload-timestamps)
@@ -1014,8 +1022,11 @@ untar into a directory named DIR; otherwise, signal an error."
(autoload-timestamps nil)
(backup-inhibited t)
(version-control 'never))
- (package-autoload-ensure-default-file output-file)
- (make-directory-autoloads pkg-dir output-file)
+ (loaddefs-generate
+ pkg-dir output-file
+ nil
+ "(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))")
(let ((buf (find-buffer-visiting output-file)))
(when buf (kill-buffer buf)))
auto-name))
@@ -1622,7 +1633,9 @@ The variable `package-load-list' controls which packages to load."
(qs (if (file-readable-p elc) elc
(if (file-readable-p package-quickstart-file)
package-quickstart-file))))
- (if qs
+ ;; The quickstart file presumes that it has a blank slate,
+ ;; so don't use it if we already activated some packages.
+ (if (and qs (not (bound-and-true-p package-activated-list)))
;; Skip load-source-file-function which would slow us down by a factor
;; 2 when loading the .el file (this assumes we were careful to
;; save this file so it doesn't need any decoding).
@@ -1847,8 +1860,12 @@ SEEN is used internally to detect infinite recursion."
(error "Need package `%s-%s', but only %s is available"
next-pkg (package-version-join next-version)
found-something))
- (t (error "Package `%s-%s' is unavailable"
- next-pkg (package-version-join next-version)))))
+ (t
+ (if (eq next-pkg 'emacs)
+ (error "This package requires Emacs version %s"
+ (package-version-join next-version))
+ (error "Package `%s-%s' is unavailable"
+ next-pkg (package-version-join next-version))))))
(setq packages
(package-compute-transaction (cons found packages)
(package-desc-reqs found)
@@ -2033,6 +2050,7 @@ if all the in-between dependencies are also in PACKAGE-LIST."
package-alist))))
(setf (package-desc-signed (car pkg-descs)) t))))))))))
+;;;###autoload
(defun package-installed-p (package &optional min-version)
"Return non-nil if PACKAGE, of MIN-VERSION or newer, is installed.
If PACKAGE is a symbol, it is the package name and MIN-VERSION
@@ -2124,6 +2142,61 @@ to install it but still mark it as selected."
(message "Package `%s' installed." name))
(message "`%s' is already installed" name))))
+;;;###autoload
+(defun package-update (name)
+ "Update package NAME if a newer version exists."
+ (interactive
+ (list (completing-read
+ "Update package: " (package--updateable-packages) nil t)))
+ (let ((package (if (symbolp name)
+ name
+ (intern name))))
+ (package-delete (cadr (assq package package-alist)) 'force)
+ (package-install package 'dont-select)))
+
+(defun package--updateable-packages ()
+ ;; Initialize the package system to get the list of package
+ ;; symbols for completion.
+ (package--archives-initialize)
+ (mapcar
+ #'car
+ (seq-filter
+ (lambda (elt)
+ (let ((available
+ (assq (car elt) package-archive-contents)))
+ (and available
+ (version-list-<
+ (package-desc-priority-version (cadr elt))
+ (package-desc-priority-version (cadr available))))))
+ package-alist)))
+
+;;;###autoload
+(defun package-update-all (&optional query)
+ "Refresh package list and upgrade all packages.
+If QUERY, ask the user before updating packages. When called
+interactively, QUERY is always true."
+ (interactive (list (not noninteractive)))
+ (package-refresh-contents)
+ (let ((updateable (package--updateable-packages)))
+ (if (not updateable)
+ (message "No packages to update")
+ (when (and query
+ (not (yes-or-no-p
+ (if (length= updateable 1)
+ "One package to update. Do it? "
+ (format "%s packages to update. Do it?"
+ (length updateable))))))
+ (user-error "Updating aborted"))
+ (mapc #'package-update updateable))))
+
+(defun package--dependencies (pkg)
+ "Return a list of all dependencies PKG has.
+This is done recursively."
+ ;; Can we have circular dependencies? Assume "nope".
+ (when-let* ((desc (cadr (assq pkg package-archive-contents)))
+ (deps (mapcar #'car (package-desc-reqs desc))))
+ (delete-dups (apply #'nconc deps (mapcar #'package--dependencies deps)))))
+
(defun package-strip-rcs-id (str)
"Strip RCS version ID from the version string STR.
If the result looks like a dotted numeric version, return it.
@@ -2350,6 +2423,35 @@ object."
(package-install pkg 'dont-select))
;;;###autoload
+(defun package-recompile (pkg)
+ "Byte-compile package PKG again.
+PKG should be either a symbol, the package name, or a `package-desc'
+object."
+ (interactive (list (intern (completing-read
+ "Recompile package: "
+ (mapcar #'symbol-name
+ (mapcar #'car package-alist))))))
+ (let ((pkg-desc (if (package-desc-p pkg)
+ pkg
+ (cadr (assq pkg package-alist)))))
+ ;; Delete the old .elc files to ensure that we don't inadvertently
+ ;; load them (in case they contain byte code/macros that are now
+ ;; invalid).
+ (dolist (elc (directory-files-recursively
+ (package-desc-dir pkg-desc) "\\.elc\\'"))
+ (delete-file elc))
+ (package--compile pkg-desc)))
+
+;;;###autoload
+(defun package-recompile-all ()
+ "Byte-compile all installed packages.
+This is meant to be used only in the case the byte-compiled files
+are invalid due to changed byte-code, macros or the like."
+ (interactive)
+ (pcase-dolist (`(_ ,pkg-desc) package-alist)
+ (package-recompile pkg-desc)))
+
+;;;###autoload
(defun package-autoremove ()
"Remove packages that are no longer needed.
@@ -2848,7 +2950,13 @@ either a full name or nil, and EMAIL is a valid email address."
(define-derived-mode package-menu-mode tabulated-list-mode "Package Menu"
"Major mode for browsing a list of packages.
-Letters do not insert themselves; instead, they are commands.
+The most useful commands here are:
+
+ `x': Install the package under point if it isn't already installed,
+ and delete it if it's already installed,
+ `i': mark a package for installation, and
+ `d': mark a package for deletion. Use the `x' command to perform the
+ actions on the marked files.
\\<package-menu-mode-map>
\\{package-menu-mode-map}"
:interactive nil
@@ -3412,9 +3520,6 @@ The full list of keys can be viewed with \\[describe-mode]."
(message (mapconcat #'package--prettify-quick-help-key
package--quick-help-keys "\n")))
-(define-obsolete-function-alias
- 'package-menu-view-commentary 'package-menu-describe-package "24.1")
-
(defun package-menu-get-status ()
"Return status text of package at point in Package Menu."
(package--ensure-package-menu-mode)
@@ -3453,7 +3558,7 @@ corresponding to the newer version."
;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC])
(let ((pkg-desc (car entry))
(status (aref (cadr entry) 2)))
- (cond ((member status '("installed" "dependency" "unsigned"))
+ (cond ((member status '("installed" "dependency" "unsigned" "external"))
(push pkg-desc installed))
((member status '("available" "new"))
(setq available (package--append-to-alist pkg-desc available))))))
@@ -3510,17 +3615,34 @@ immediately."
(setq package-menu--mark-upgrades-pending t)
(message "Waiting for refresh to finish...")))
-(defun package-menu--list-to-prompt (packages)
+(defun package-menu--list-to-prompt (packages &optional include-dependencies)
"Return a string listing PACKAGES that's usable in a prompt.
PACKAGES is a list of `package-desc' objects.
Formats the returned string to be usable in a minibuffer
-prompt (see `package-menu--prompt-transaction-p')."
+prompt (see `package-menu--prompt-transaction-p').
+
+If INCLUDE-DEPENDENCIES, also include the number of uninstalled
+dependencies."
;; The case where `package' is empty is handled in
;; `package-menu--prompt-transaction-p' below.
- (format "%d (%s)"
+ (format "%d (%s)%s"
(length packages)
- (mapconcat #'package-desc-full-name packages " ")))
-
+ (mapconcat #'package-desc-full-name packages " ")
+ (let ((deps
+ (seq-remove
+ #'package-installed-p
+ (delete-dups
+ (apply
+ #'nconc
+ (mapcar (lambda (package)
+ (package--dependencies
+ (package-desc-name package)))
+ packages))))))
+ (if (and include-dependencies deps)
+ (if (length= deps 1)
+ (format " plus 1 dependency")
+ (format " plus %d dependencies" (length deps)))
+ ""))))
(defun package-menu--prompt-transaction-p (delete install upgrade)
"Prompt the user about DELETE, INSTALL, and UPGRADE.
@@ -3529,11 +3651,14 @@ Either may be nil, but not all."
(y-or-n-p
(concat
(when delete
- (format "Packages to delete: %s. " (package-menu--list-to-prompt delete)))
+ (format "Packages to delete: %s. "
+ (package-menu--list-to-prompt delete)))
(when install
- (format "Packages to install: %s. " (package-menu--list-to-prompt install)))
+ (format "Packages to install: %s. "
+ (package-menu--list-to-prompt install t)))
(when upgrade
- (format "Packages to upgrade: %s. " (package-menu--list-to-prompt upgrade)))
+ (format "Packages to upgrade: %s. "
+ (package-menu--list-to-prompt upgrade)))
"Proceed? ")))
@@ -3595,8 +3720,13 @@ packages list, respectively."
(defun package-menu-execute (&optional noquery)
"Perform marked Package Menu actions.
Packages marked for installation are downloaded and installed,
-packages marked for deletion are removed,
-and packages marked for upgrading are downloaded and upgraded.
+packages marked for deletion are removed, and packages marked for
+upgrading are downloaded and upgraded.
+
+If no packages are marked, the action taken depends on the state
+of the package under point. If it's not already installed, this
+command will install the package, and if it's installed, it will
+delete the package.
Optional argument NOQUERY non-nil means do not ask the user to confirm."
(interactive nil package-menu-mode)
@@ -3614,8 +3744,20 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm."
((eq cmd ?I)
(push pkg-desc install-list))))
(forward-line)))
+ ;; Nothing marked.
(unless (or delete-list install-list)
- (user-error "No operations specified"))
+ ;; Not on a package line.
+ (unless (tabulated-list-get-id)
+ (user-error "No operations specified"))
+ (let* ((id (tabulated-list-get-id))
+ (status (package-menu-get-status)))
+ (cond
+ ((member status '("installed"))
+ (push id delete-list))
+ ((member status '("available" "avail-obso" "new" "dependency"))
+ (push id install-list))
+ (t (user-error "No default action available for status: %s"
+ status)))))
(let-alist (package-menu--partition-transaction install-list delete-list)
(when (or noquery
(package-menu--prompt-transaction-p .delete .install .upgrade))
@@ -3847,16 +3989,14 @@ packages."
(mapcar #'car package-archives)))
package-menu-mode)
(package--ensure-package-menu-mode)
- (let ((re (if (listp archive)
- (regexp-opt archive)
- archive)))
- (package-menu--filter-by (lambda (pkg-desc)
- (let ((pkg-archive (package-desc-archive pkg-desc)))
- (and pkg-archive
- (string-match-p re pkg-archive))))
- (concat "archive:" (if (listp archive)
- (string-join archive ",")
- archive)))))
+ (let ((archives (ensure-list archive)))
+ (package-menu--filter-by
+ (lambda (pkg-desc)
+ (let ((pkg-archive (package-desc-archive pkg-desc)))
+ (or (null archives)
+ (and pkg-archive
+ (member pkg-archive archives)))))
+ (concat "archive:" (string-join archives ",")))))
(defun package-menu-filter-by-description (description)
"Filter the \"*Packages*\" buffer by DESCRIPTION regexp.
@@ -4176,18 +4316,19 @@ activations need to be changed, such as when `package-load-list' is modified."
(locate-library (package--autoloads-file-name pkg))))
(pfile (prin1-to-string file)))
(insert "(let ((load-true-file-name " pfile ")\
-(load-file-name " pfile "))\n")
+\(load-file-name " pfile "))\n")
(insert-file-contents file)
;; Fixup the special #$ reader form and throw away comments.
(while (re-search-forward "#\\$\\|^;\\(.*\n\\)" nil 'move)
- (unless (nth 8 (syntax-ppss))
+ (unless (ppss-string-terminator (save-match-data (syntax-ppss)))
(replace-match (if (match-end 1) "" pfile) t t)))
(unless (bolp) (insert "\n"))
(insert ")\n")))
(pp `(defvar package-activated-list) (current-buffer))
(pp `(setq package-activated-list
- (append ',(mapcar #'package-desc-name package--quickstart-pkgs)
- package-activated-list))
+ (delete-dups
+ (append ',(mapcar #'package-desc-name package--quickstart-pkgs)
+ package-activated-list)))
(current-buffer))
(let ((info-dirs (butlast Info-directory-list)))
(when info-dirs
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 7a82b416e55..07443dabfef 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -328,7 +328,7 @@ PATTERNS are normal `pcase' patterns, and VALUES are expression.
Evaluation happens sequentially as in `setq' (not in parallel).
-An example: (pcase-setq `((,a) [(,b)]) '((1) [(2)]))
+An example: (pcase-setq \\=`((,a) [(,b)]) \\='((1) [(2)]))
VAL is presumed to match PAT. Failure to match may signal an error or go
undetected, binding variables to arbitrary values, such as nil.
@@ -435,7 +435,7 @@ how many time this CODEGEN is called."
(macroexp-warn-and-return
(format "pcase pattern %S shadowed by previous pcase pattern"
(car case))
- main))))
+ main nil nil (car case)))))
main)))
(defun pcase--expand (exp cases)
@@ -941,7 +941,7 @@ Otherwise, it defers to REST which is a list of branches of the form
(if (eq upat '_) code
(macroexp-warn-and-return
"Pattern t is deprecated. Use `_' instead"
- code))))
+ code nil nil upat))))
((eq upat 'pcase--dontcare) :pcase--dontcare)
((memq (car-safe upat) '(guard pred))
(if (eq (car upat) 'pred) (pcase--mark-used sym))
diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el
index d199716b2c5..a3ff2ecbaa6 100644
--- a/lisp/emacs-lisp/pp.el
+++ b/lisp/emacs-lisp/pp.el
@@ -177,6 +177,10 @@ Also add the value to the front of the list in the variable `values'."
(let ((pt (point)))
(save-excursion
(forward-sexp -1)
+ ;; Make `pp-eval-last-sexp' work the same way `eval-last-sexp'
+ ;; does.
+ (when (looking-at ",@?")
+ (goto-char (match-end 0)))
(read
;; If first line is commented, ignore all leading comments:
(if (save-excursion (beginning-of-line) (looking-at-p "[ \t]*;"))
@@ -246,7 +250,7 @@ Use the `pp-max-width' variable to control the desired line length."
(set-marker (make-marker) (1- (point))))))
(pp--format-list sexp)))
(t
- (princ sexp (current-buffer)))))
+ (prin1 sexp (current-buffer)))))
;; Print some of the smaller integers as characters, perhaps?
(integer
(if (<= ?0 sexp ?z)
@@ -273,7 +277,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)
@@ -375,7 +382,7 @@ Use the `pp-max-width' variable to control the desired line length."
(when (> (current-column) (pp--max-width))
(condition-case ()
(backward-up-list 1)
- (:success (when (looking-back " " 2)
+ (:success (when (and (not (bobp)) (looking-back " " 2))
(insert "\n")))
(error nil)))))))
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 <larsi@gnus.org>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; 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/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el
index 38726ca048e..46b429ce6fe 100644
--- a/lisp/emacs-lisp/re-builder.el
+++ b/lisp/emacs-lisp/re-builder.el
@@ -216,19 +216,17 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
"Buffer to use for the RE Builder.")
;; Define the local "\C-c" keymap
-(defvar reb-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-c" 'reb-toggle-case)
- (define-key map "\C-c\C-q" 'reb-quit)
- (define-key map "\C-c\C-w" 'reb-copy)
- (define-key map "\C-c\C-s" 'reb-next-match)
- (define-key map "\C-c\C-r" 'reb-prev-match)
- (define-key map "\C-c\C-i" 'reb-change-syntax)
- (define-key map "\C-c\C-e" 'reb-enter-subexp-mode)
- (define-key map "\C-c\C-b" 'reb-change-target-buffer)
- (define-key map "\C-c\C-u" 'reb-force-update)
- map)
- "Keymap used by the RE Builder.")
+(defvar-keymap reb-mode-map
+ :doc "Keymap used by the RE Builder."
+ "C-c C-c" #'reb-toggle-case
+ "C-c C-q" #'reb-quit
+ "C-c C-w" #'reb-copy
+ "C-c C-s" #'reb-next-match
+ "C-c C-r" #'reb-prev-match
+ "C-c C-i" #'reb-change-syntax
+ "C-c C-e" #'reb-enter-subexp-mode
+ "C-c C-b" #'reb-change-target-buffer
+ "C-c C-u" #'reb-force-update)
(easy-menu-define reb-mode-menu reb-mode-map
"Menu for the RE Builder."
@@ -263,12 +261,10 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
(setq-local blink-matching-paren nil)
(reb-mode-common))
-(defvar reb-lisp-mode-map
- (let ((map (make-sparse-keymap)))
- ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from
- ;; `emacs-lisp-mode'
- (define-key map "\C-c" (lookup-key reb-mode-map "\C-c"))
- map))
+(defvar-keymap reb-lisp-mode-map
+ ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from
+ ;; `emacs-lisp-mode'
+ "C-c" (keymap-lookup reb-mode-map "C-c"))
(define-derived-mode reb-lisp-mode
emacs-lisp-mode "RE Builder Lisp"
@@ -278,16 +274,22 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
(require 'rx)) ; require rx anyway
(reb-mode-common))
-(defvar reb-subexp-mode-map
- (let ((m (make-keymap)))
- (suppress-keymap m)
- ;; Again share the "\C-c" keymap for the commands
- (define-key m "\C-c" (lookup-key reb-mode-map "\C-c"))
- (define-key m "q" 'reb-quit-subexp-mode)
- (dotimes (digit 10)
- (define-key m (int-to-string digit) 'reb-display-subexp))
- m)
- "Keymap used by the RE Builder for the subexpression mode.")
+(defvar-keymap reb-subexp-mode-map
+ :doc "Keymap used by the RE Builder for the subexpression mode."
+ :full t :suppress t
+ ;; Again share the "\C-c" keymap for the commands
+ "C-c" (keymap-lookup reb-mode-map "C-c")
+ "q" #'reb-quit-subexp-mode
+ "0" #'reb-display-subexp
+ "1" #'reb-display-subexp
+ "2" #'reb-display-subexp
+ "3" #'reb-display-subexp
+ "4" #'reb-display-subexp
+ "5" #'reb-display-subexp
+ "6" #'reb-display-subexp
+ "7" #'reb-display-subexp
+ "8" #'reb-display-subexp
+ "9" #'reb-display-subexp)
(defun reb-mode-common ()
"Setup functions common to functions `reb-mode' and `reb-lisp-mode'."
@@ -323,7 +325,10 @@ Except for Lisp syntax this is the same as `reb-regexp'.")
(reb-lisp-mode))
(t (reb-mode)))
(reb-restart-font-lock)
- (reb-do-update))
+ ;; When using `rx' syntax, the initial syntax () is invalid. But
+ ;; don't signal an error in that case.
+ (ignore-errors
+ (reb-do-update)))
(defun reb-mode-buffer-p ()
"Return non-nil if the current buffer is a RE Builder buffer."
diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el
index e635c7f200c..dae6590b9bc 100644
--- a/lisp/emacs-lisp/rmc.el
+++ b/lisp/emacs-lisp/rmc.el
@@ -23,8 +23,6 @@
;;; Code:
-(require 'seq)
-
(defun rmc--add-key-description (elem)
(let* ((char (car elem))
(name (cadr elem))
@@ -112,14 +110,21 @@
(goto-char start)
(dolist (line (split-string text "\n"))
(end-of-line)
- (if (bolp)
- (insert line "\n")
- (insert line))
+ (if (not (bolp))
+ (insert line)
+ (insert (make-string
+ (max (- (* (mod (1- times) columns)
+ (+ fill-column 4))
+ (current-column))
+ 0)
+ ?\s))
+ (insert line "\n"))
(forward-line 1))))))))
buf))
;;;###autoload
-(defun read-multiple-choice (prompt choices &optional help-string show-help)
+(defun read-multiple-choice (prompt choices &optional help-string show-help
+ long-form)
"Ask user to select an entry from CHOICES, promting with PROMPT.
This function allows to ask the user a multiple-choice question.
@@ -157,14 +162,24 @@ dialogs. Otherwise, the function will always use text-mode dialogs.
The return value is the matching entry from the CHOICES list.
+If LONG-FORM, do a `completing-read' over the NAME elements in
+CHOICES instead.
+
Usage example:
\(read-multiple-choice \"Continue connecting?\"
\\='((?a \"always\")
(?s \"session only\")
(?n \"no\")))"
- (let* ((choices (if show-help choices (append choices '((?? "?")))))
- (altered-names (mapcar #'rmc--add-key-description choices))
+ (if long-form
+ (read-multiple-choice--long-answers prompt choices)
+ (read-multiple-choice--short-answers
+ prompt choices help-string show-help)))
+
+(defun read-multiple-choice--short-answers (prompt choices help-string show-help)
+ (let* ((prompt-choices
+ (if show-help choices (append choices '((?? "?")))))
+ (altered-names (mapcar #'rmc--add-key-description prompt-choices))
(full-prompt
(format
"%s (%s): "
@@ -175,7 +190,7 @@ Usage example:
(save-excursion
(if show-help
(setq buf (rmc--show-help prompt help-string show-help
- choices altered-names)))
+ choices altered-names)))
(while (not tchar)
(message "%s%s"
(if wrong-char
@@ -194,7 +209,7 @@ Usage example:
(lambda (elem)
(cons (capitalize (cadr elem))
(car elem)))
- choices)))
+ prompt-choices)))
(condition-case nil
(let ((cursor-in-echo-area t))
(read-event))
@@ -232,11 +247,22 @@ Usage example:
(when wrong-char
(ding))
(setq buf (rmc--show-help prompt help-string show-help
- choices altered-names))))))
+ choices altered-names))))))
(when (buffer-live-p buf)
(kill-buffer buf))
(assq tchar choices)))
+(defun read-multiple-choice--long-answers (prompt choices)
+ (let ((answer
+ (completing-read
+ (concat prompt " ("
+ (mapconcat #'identity (mapcar #'cadr choices) "/")
+ ") ")
+ (mapcar #'cadr choices) nil t)))
+ (seq-find (lambda (elem)
+ (equal (cadr elem) answer))
+ choices)))
+
(provide 'rmc)
;;; rmc.el ends here
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index aa2486b47ec..18eb168a70a 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -1110,6 +1110,15 @@ can expand to any number of values."
(append rx--builtin-forms rx--builtin-symbols)
"List of built-in rx names. These cannot be redefined by the user.")
+;; Declare Lisp indentation rules for constructs that take 1 or 2
+;; parameters before a body of RX forms.
+;; (`>=' and `=' are omitted because they are more likely to be used
+;; as Lisp functions than RX constructs; `repeat' is a `defcustom' type.)
+(put 'group-n 'lisp-indent-function 1)
+(put 'submatch-n 'lisp-indent-function 1)
+(put '** 'lisp-indent-function 2)
+
+
(defun rx--translate (item)
"Translate the rx-expression ITEM. Return (REGEXP . PRECEDENCE)."
(cond
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index abfe51d32b5..36c17f4cd5e 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -59,8 +59,8 @@
(eval-when-compile (require 'cl-generic))
;; We used to use some sequence functions from cl-lib, but this
-;; dependency was swapped around so that it will be easier to make
-;; seq.el preloaded in the future. See also Bug#39761#26.
+;; dependency was swapped around so that it's easier to make seq.el
+;; preloaded. See also Bug#39761#26.
(defmacro seq-doseq (spec &rest body)
"Loop over a sequence.
@@ -299,6 +299,7 @@ sorted. FUNCTION must be a function of one argument."
TYPE must be one of following symbols: vector, string or list.
\n(fn TYPE SEQUENCE...)"
+ (setq sequences (mapcar #'seq-into-sequence sequences))
(pcase type
('vector (apply #'vconcat sequences))
('string (apply #'concat sequences))
@@ -402,23 +403,23 @@ found or not."
(setq count (+ 1 count))))
count))
-(with-suppressed-warnings ((obsolete seq-contains))
- (cl-defgeneric seq-contains (sequence elt &optional testfn)
- "Return the first element in SEQUENCE that is equal to ELT.
+(cl-defgeneric seq-contains (sequence elt &optional testfn)
+ "Return the first element in SEQUENCE that is equal to ELT.
Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (declare (obsolete seq-contains-p "27.1"))
- (seq-some (lambda (e)
- (when (funcall (or testfn #'equal) elt e)
- e))
- sequence)))
+ (declare (obsolete seq-contains-p "27.1"))
+ (seq-some (lambda (e)
+ (when (funcall (or testfn #'equal) elt e)
+ e))
+ sequence))
(cl-defgeneric seq-contains-p (sequence elt &optional testfn)
"Return non-nil if SEQUENCE contains an element equal to ELT.
Equality is defined by TESTFN if non-nil or by `equal' if nil."
(catch 'seq--break
(seq-doseq (e sequence)
- (when (funcall (or testfn #'equal) e elt)
- (throw 'seq--break t)))
+ (let ((r (funcall (or testfn #'equal) e elt)))
+ (when r
+ (throw 'seq--break r))))
nil))
(cl-defgeneric seq-set-equal-p (sequence1 sequence2 &optional testfn)
@@ -631,5 +632,20 @@ Signal an error if SEQUENCE is empty."
;; we automatically highlight macros.
(add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
+(defun seq-split (sequence length)
+ "Split SEQUENCE into a list of sub-sequences of at most LENGTH.
+All the sub-sequences will be of LENGTH, except the last one,
+which may be shorter."
+ (when (< length 1)
+ (error "Sub-sequence length must be larger than zero"))
+ (let ((result nil)
+ (seq-length (length sequence))
+ (start 0))
+ (while (< start seq-length)
+ (push (seq-subseq sequence start
+ (setq start (min seq-length (+ start length))))
+ result))
+ (nreverse result)))
+
(provide 'seq)
;;; seq.el ends here
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
index 8cd371321ae..2343a9b589f 100644
--- a/lisp/emacs-lisp/shadow.el
+++ b/lisp/emacs-lisp/shadow.el
@@ -177,12 +177,11 @@ See the documentation for `list-load-path-shadows' for further information."
. (1 font-lock-warning-face)))
"Keywords to highlight in `load-path-shadows-mode'.")
-(define-derived-mode load-path-shadows-mode fundamental-mode "LP-Shadows"
+(define-derived-mode load-path-shadows-mode special-mode "LP-Shadows"
"Major mode for `load-path' shadows buffer."
(setq-local font-lock-defaults
'((load-path-shadows-font-lock-keywords)))
- (setq buffer-undo-list t
- buffer-read-only t))
+ (setq buffer-undo-list t))
;; TODO use text-properties instead, a la dired.
(define-button-type 'load-path-shadows-find-file
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 870d34527b0..a2d954cadbb 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -41,41 +41,78 @@
'((t :inherit variable-pitch))
"Face used for a section.")
-(defvar shortdoc--groups nil)
+;;;###autoload
+(progn
+ (defvar shortdoc--groups nil)
-(defmacro define-short-documentation-group (group &rest functions)
- "Add GROUP to the list of defined documentation groups.
+ (defmacro define-short-documentation-group (group &rest functions)
+ "Add GROUP to the list of defined documentation groups.
FUNCTIONS is a list of elements on the form:
- (fun
+ (FUNC
:no-manual BOOL
:args ARGS
- :eval EXAMPLE-FORM
+ :eval EVAL
:no-eval EXAMPLE-FORM
- :no-eval* EXAMPLE-FORM
:no-value EXAMPLE-FORM
+ :no-eval* EXAMPLE-FORM
:result RESULT-FORM
- :result-string RESULT-FORM
+ :result-string RESULT-STRING
:eg-result RESULT-FORM
- :eg-result-string RESULT-FORM)
+ :eg-result-string RESULT-STRING)
-BOOL should be non-nil if the function isn't documented in the
+FUNC is the function being documented.
+
+NO-MANUAL should be non-nil if FUNC isn't documented in the
manual.
-ARGS is optional; the function's signature is displayed if ARGS
-is not present.
+ARGS is optional list of function FUNC's arguments. FUNC's
+signature is displayed automatically if ARGS is not present.
+Specifying ARGS might be useful where you don't want to document
+some of the uncommon arguments a function might have.
+
+While the `:no-manual' and `:args' property can be used for
+any (FUNC ..) form, all of the other properties shown above
+cannot be used simultaneously in such a form.
+
+Here are some common forms with examples of properties that go
+together:
+
+1. Document a form or string, and its evaluated return value.
+ (FUNC
+ :eval EVAL)
+
+If EVAL is a string, it will be inserted as is, and then that
+string will be `read' and evaluated.
+
+2. Document a form or string, but manually document its evaluation
+ result. The provided form will not be evaluated.
-If EVAL isn't a string, it will be printed with `prin1', and then
-evaluated to give a result, which is also printed. If it's a
-string, it'll be inserted as is, then the string will be `read',
-and then evaluated.
+ (FUNC
+ :no-eval EXAMPLE-FORM
+ :result RESULT-FORM) ;Use `:result-string' if value is in string form
+
+Using `:no-value' is the same as using `:no-eval'.
+
+Use `:no-eval*' instead of `:no-eval' where the successful
+execution of the documented form depends on some conditions.
-There can be any number of :example/:result elements."
- (declare (indent defun))
- `(progn
- (setq shortdoc--groups (delq (assq ',group shortdoc--groups)
- shortdoc--groups))
- (push (cons ',group ',functions) shortdoc--groups)))
+3. Document a form or string EXAMPLE-FORM. Also manually
+ document an example result. This result could be unrelated to
+ the documented form.
+
+ (FUNC
+ :no-eval EXAMPLE-FORM
+ :eg-result RESULT-FORM) ;Use `:eg-result-string' if value is in string form
+
+A FUNC form can have any number of `:no-eval' (or `:no-value'),
+`:no-eval*', `:result', `:result-string', `:eg-result' and
+`:eg-result-string' properties."
+ (declare (indent defun))
+ `(progn
+ (setq shortdoc--groups (delq (assq ',group shortdoc--groups)
+ shortdoc--groups))
+ (push (cons ',group ',functions) shortdoc--groups))))
(define-short-documentation-group alist
"Alist Basics"
@@ -223,11 +260,16 @@ There can be any number of :example/:result elements."
:no-manual t
:eval (string-blank-p " \n"))
(string-lessp
- :eval (string-lessp "foo" "bar"))
+ :eval (string-lessp "foo" "bar")
+ :eval (string-lessp "pic4.png" "pic32.png")
+ :eval (string-lessp "1.1" "1 2"))
(string-greaterp
:eval (string-greaterp "foo" "bar"))
(string-version-lessp
- :eval (string-version-lessp "pic4.png" "pic32.png"))
+ :eval (string-version-lessp "pic4.png" "pic32.png")
+ :eval (string-version-lessp "1.1" "1 2"))
+ (string-collate-lessp
+ :eval (string-collate-lessp "1.1" "1 2"))
(string-prefix-p
:eval (string-prefix-p "foo" "foobar"))
(string-suffix-p
@@ -311,6 +353,13 @@ There can be any number of :example/:result elements."
(abbreviate-file-name
:no-eval (abbreviate-file-name "/home/some-user")
:eg-result "~some-user")
+ (file-parent-directory
+ :eval (file-parent-directory "/foo/bar")
+ :eval (file-parent-directory "~")
+ :eval (file-parent-directory "/tmp/")
+ :eval (file-parent-directory "foo/bar")
+ :eval (file-parent-directory "foo")
+ :eval (file-parent-directory "/"))
"Quoted File Names"
(file-name-quote
:args (name)
@@ -426,7 +475,9 @@ There can be any number of :example/:result elements."
:no-eval* (directory-files-and-attributes "/tmp/foo"))
(file-expand-wildcards
:no-eval (file-expand-wildcards "/tmp/*.png")
- :eg-result ("/tmp/foo.png" "/tmp/zot.png"))
+ :eg-result ("/tmp/foo.png" "/tmp/zot.png")
+ :no-eval (file-expand-wildcards "/*/foo.png")
+ :eg-result ("/tmp/foo.png" "/var/foo.png"))
(locate-dominating-file
:no-eval (locate-dominating-file "foo.png" "/tmp/foo/bar/zot")
:eg-result "/tmp/foo.png")
@@ -647,11 +698,6 @@ There can be any number of :example/:result elements."
(plist-put
:no-eval (setq plist (plist-put plist 'd 4))
:eq-result (a 1 b 2 c 3 d 4))
- (lax-plist-get
- :eval (lax-plist-get '("a" 1 "b" 2 "c" 3) "b"))
- (lax-plist-put
- :no-eval (setq plist (lax-plist-put plist "d" 4))
- :eq-result '("a" 1 "b" 2 "c" 3 "d" 4))
(plist-member
:eval (plist-member '(a 1 b 2 c 3) 'b))
"Data About Lists"
@@ -850,6 +896,8 @@ There can be any number of :example/:result elements."
:eval (seq-subseq '(a b c d e) 2 4))
(seq-take
:eval (seq-take '(a b c d e) 3))
+ (seq-split
+ :eval (seq-split [0 1 2 3 5] 2))
(seq-take-while
:eval (seq-take-while #'cl-evenp [2 4 9 6 5]))
(seq-uniq
@@ -1261,16 +1309,20 @@ There can be any number of :example/:result elements."
:eval (keymap-lookup (current-global-map) "C-x x g")))
;;;###autoload
-(defun shortdoc-display-group (group &optional function)
+(defun shortdoc-display-group (group &optional function same-window)
"Pop to a buffer with short documentation summary for functions in GROUP.
-If FUNCTION is non-nil, place point on the entry for FUNCTION (if any)."
+If FUNCTION is non-nil, place point on the entry for FUNCTION (if any).
+If SAME-WINDOW, don't pop to a new window."
(interactive (list (completing-read "Show summary for functions in: "
(mapcar #'car shortdoc--groups))))
(when (stringp group)
(setq group (intern group)))
(unless (assq group shortdoc--groups)
(error "No such documentation group %s" group))
- (pop-to-buffer (format "*Shortdoc %s*" group))
+ (funcall (if same-window
+ #'pop-to-buffer-same-window
+ #'pop-to-buffer)
+ (format "*Shortdoc %s*" group))
(let ((inhibit-read-only t)
(prev nil))
(erase-buffer)
@@ -1299,6 +1351,9 @@ If FUNCTION is non-nil, place point on the entry for FUNCTION (if any)."
(text-property-search-forward 'shortdoc-function function t)
(beginning-of-line)))
+;;;###autoload
+(defalias 'shortdoc #'shortdoc-display-group)
+
(defun shortdoc--display-function (data)
(let ((function (pop data))
(start-section (point))
@@ -1312,15 +1367,15 @@ If FUNCTION is non-nil, place point on the entry for FUNCTION (if any)."
'action (lambda (_)
(describe-function function))
'follow-link t
- 'help-echo (purecopy "mouse-1, RET: describe function"))
+ 'help-echo "mouse-1, RET: describe function")
(insert-text-button
(symbol-name function)
'face 'button
'action (lambda (_)
(info-lookup-symbol function 'emacs-lisp-mode))
'follow-link t
- 'help-echo (purecopy "mouse-1, RET: show \
-function's documentation in the Info manual")))
+ 'help-echo "mouse-1, RET: show \
+function's documentation in the Info manual"))
(setq arglist-start (point))
(insert ")\n")
;; Doc string.
@@ -1405,11 +1460,14 @@ function's documentation in the Info manual")))
If GROUP doesn't exist, it will be created.
If SECTION doesn't exist, it will be added.
+ELEM is a Lisp form. See `define-short-documentation-group' for
+details.
+
Example:
(shortdoc-add-function
- 'file \"Predicates\"
- '(file-locked-p :no-eval (file-locked-p \"/tmp\")))"
+ \\='file \"Predicates\"
+ \\='(file-locked-p :no-eval (file-locked-p \"/tmp\")))"
(let ((glist (assq group shortdoc--groups)))
(unless glist
(setq glist (list group))
diff --git a/lisp/emacs-lisp/shorthands.el b/lisp/emacs-lisp/shorthands.el
index a9e4343715c..ffd3856db6c 100644
--- a/lisp/emacs-lisp/shorthands.el
+++ b/lisp/emacs-lisp/shorthands.el
@@ -61,8 +61,7 @@
(defun shorthands-font-lock-shorthands (limit)
(when read-symbol-shorthands
(while (re-search-forward
- (eval-when-compile
- (concat "\\_<\\(" lisp-mode-symbol-regexp "\\)\\_>"))
+ (concat "\\_<\\(" (rx lisp-mode-symbol) "\\)\\_>")
limit t)
(let* ((existing (get-text-property (match-beginning 1) 'face))
(probe (and (not (memq existing '(font-lock-comment-face
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index b2283e66e4f..61d52026b38 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -1301,9 +1301,9 @@ Only meaningful when called from within `smie-rules-function'."
(let ((afterpos (save-excursion
(let ((tok (funcall smie-forward-token-function)))
(unless tok
- (with-demoted-errors
- (error "smie-rule-separator: Can't skip token %s"
- smie--token))))
+ (funcall (if debug-on-error #'error #'message)
+ "smie-rule-separator: Can't skip token %s"
+ smie--token)))
(skip-chars-forward " ")
(unless (eolp) (point)))))
(or (and afterpos
@@ -1820,7 +1820,7 @@ to which that point should be aligned, if we were to reindent it.")
"Indent current line using the SMIE indentation engine."
(interactive)
(let* ((savep (point))
- (indent (or (with-demoted-errors
+ (indent (or (with-demoted-errors "SMIE Error: %S"
(save-excursion
(forward-line 0)
(skip-chars-forward " \t")
@@ -1846,7 +1846,9 @@ to which that point should be aligned, if we were to reindent it.")
(move-to-column fc)
(syntax-ppss))))
(while
- (and (with-demoted-errors
+ ;; We silence the error completely since errors are "normal" in
+ ;; some cases and an error message would be annoying (bug#19342).
+ (and (ignore-error scan-error
(save-excursion
(let ((end (point))
(bsf nil) ;Best-so-far.
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 43e0fc4c9dd..5159e8784a5 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -81,131 +81,21 @@ Note how the single `-' got converted into a list before
threading."
(declare (indent 0) (debug thread-first))
`(internal--thread-argument nil ,@forms))
-
-(defsubst internal--listify (elt)
- "Wrap ELT in a list if it is not one.
-If ELT is of the form ((EXPR)), listify (EXPR) with a dummy symbol."
- (cond
- ((symbolp elt) (list elt elt))
- ((null (cdr elt))
- (list (make-symbol "s") (car elt)))
- (t elt)))
-
-(defsubst internal--check-binding (binding)
- "Check BINDING is properly formed."
- (when (> (length binding) 2)
- (signal
- 'error
- (cons "`let' bindings can have only one value-form" binding)))
- binding)
-
-(defsubst internal--build-binding-value-form (binding prev-var)
- "Build the conditional value form for BINDING using PREV-VAR."
- (let ((var (car binding)))
- `(,var (and ,prev-var ,(cadr binding)))))
-
-(defun internal--build-binding (binding prev-var)
- "Check and build a single BINDING with PREV-VAR."
- (thread-first
- binding
- internal--listify
- internal--check-binding
- (internal--build-binding-value-form prev-var)))
-
-(defun internal--build-bindings (bindings)
- "Check and build conditional value forms for BINDINGS."
- (let ((prev-var t))
- (mapcar (lambda (binding)
- (let ((binding (internal--build-binding binding prev-var)))
- (setq prev-var (car binding))
- binding))
- bindings)))
-
-(defmacro if-let* (varlist then &rest else)
- "Bind variables according to VARLIST and evaluate THEN or ELSE.
-This is like `if-let' but doesn't handle a VARLIST of the form
-\(SYMBOL SOMETHING) specially."
- (declare (indent 2)
- (debug ((&rest [&or symbolp (symbolp form) (form)])
- body)))
- (if varlist
- `(let* ,(setq varlist (internal--build-bindings varlist))
- (if ,(caar (last varlist))
- ,then
- ,@else))
- `(let* () ,then)))
-
-(defmacro when-let* (varlist &rest body)
- "Bind variables according to VARLIST and conditionally evaluate BODY.
-This is like `when-let' but doesn't handle a VARLIST of the form
-\(SYMBOL SOMETHING) specially."
- (declare (indent 1) (debug if-let*))
- (list 'if-let* varlist (macroexp-progn body)))
-
-(defmacro and-let* (varlist &rest body)
- "Bind variables according to VARLIST and conditionally evaluate BODY.
-Like `when-let*', except if BODY is empty and all the bindings
-are non-nil, then the result is non-nil."
- (declare (indent 1) (debug if-let*))
- (let (res)
- (if varlist
- `(let* ,(setq varlist (internal--build-bindings varlist))
- (when ,(setq res (caar (last varlist)))
- ,@(or body `(,res))))
- `(let* () ,@(or body '(t))))))
-
-;;;###autoload
-(defmacro if-let (spec then &rest else)
- "Bind variables according to SPEC and evaluate THEN or ELSE.
-Evaluate each binding in turn, as in `let*', stopping if a
-binding value is nil. If all are non-nil return the value of
-THEN, otherwise the last form in ELSE.
-
-Each element of SPEC is a list (SYMBOL VALUEFORM) that binds
-SYMBOL to the value of VALUEFORM. An element can additionally be
-of the form (VALUEFORM), which is evaluated and checked for nil;
-i.e. SYMBOL can be omitted if only the test result is of
-interest. It can also be of the form SYMBOL, then the binding of
-SYMBOL is checked for nil.
-
-As a special case, interprets a SPEC of the form \(SYMBOL SOMETHING)
-like \((SYMBOL SOMETHING)). This exists for backward compatibility
-with an old syntax that accepted only one binding."
- (declare (indent 2)
- (debug ([&or (symbolp form) ; must be first, Bug#48489
- (&rest [&or symbolp (symbolp form) (form)])]
- body)))
- (when (and (<= (length spec) 2)
- (not (listp (car spec))))
- ;; Adjust the single binding case
- (setq spec (list spec)))
- (list 'if-let* spec then (macroexp-progn else)))
-
-;;;###autoload
-(defmacro when-let (spec &rest body)
- "Bind variables according to SPEC and conditionally evaluate BODY.
-Evaluate each binding in turn, stopping if a binding value is nil.
-If all are non-nil, return the value of the last form in BODY.
-
-The variable list SPEC is the same as in `if-let'."
- (declare (indent 1) (debug if-let))
- (list 'if-let spec (macroexp-progn body)))
-
(defsubst hash-table-empty-p (hash-table)
"Check whether HASH-TABLE is empty (has 0 elements)."
(zerop (hash-table-count hash-table)))
(defsubst hash-table-keys (hash-table)
"Return a list of keys in HASH-TABLE."
- (cl-loop for k being the hash-keys of hash-table collect k))
+ (let ((keys nil))
+ (maphash (lambda (k _) (push k keys)) hash-table)
+ keys))
(defsubst hash-table-values (hash-table)
"Return a list of values in HASH-TABLE."
- (cl-loop for v being the hash-values of hash-table collect v))
-
-(defsubst string-empty-p (string)
- "Check whether STRING is empty."
- (string= string ""))
+ (let ((values nil))
+ (maphash (lambda (_ v) (push v values)) hash-table)
+ values))
(defsubst string-join (strings &optional separator)
"Join all STRINGS using SEPARATOR.
@@ -277,9 +167,13 @@ non-nil, return the last LENGTH characters instead.
If CODING-SYSTEM is non-nil, STRING will be encoded before
limiting, and LENGTH is interpreted as the number of bytes to
limit the string to. The result will be a unibyte string that is
-shorter than LENGTH, but will not contain \"partial\" characters,
-even if CODING-SYSTEM encodes characters with several bytes per
-character.
+shorter than LENGTH, but will not contain \"partial\"
+characters (or glyphs), even if CODING-SYSTEM encodes characters
+with several bytes per character. If the coding system specifies
+prefix like the byte order mark (aka \"BOM\") or a shift-in sequence,
+their bytes will be normally counted as part of LENGTH. This is
+the case, for instance, with `utf-16'. If this isn't desired, use a
+coding system that doesn't specify a BOM, like `utf-16le' or `utf-16be'.
When shortening strings for display purposes,
`truncate-string-to-width' is almost always a better alternative
@@ -287,45 +181,60 @@ than this function."
(unless (natnump length)
(signal 'wrong-type-argument (list 'natnump length)))
(if coding-system
- (let ((result nil)
- (result-length 0)
- (index (if end (1- (length string)) 0)))
- ;; FIXME: This implementation, which uses encode-coding-char
- ;; to encode the string one character at a time, is in general
- ;; incorrect: coding-systems that produce prefix or suffix
- ;; bytes, such as ISO-2022-based or UTF-8/16 with BOM, will
- ;; produce those bytes for each character, instead of just
- ;; once for the entire string. encode-coding-char attempts to
- ;; remove those extra bytes at least in some situations, but
- ;; it cannot do that in all cases. And in any case, producing
- ;; what is supposed to be a UTF-16 or ISO-2022-CN encoded
- ;; string which lacks the BOM bytes at the beginning and the
- ;; charset designation sequences at the head and tail of the
- ;; result will definitely surprise the callers in some cases.
- (while (let ((encoded (encode-coding-char
- (aref string index) coding-system)))
- (and (<= (+ (length encoded) result-length) length)
- (progn
- (push encoded result)
- (cl-incf result-length (length encoded))
- (setq index (if end (1- index)
- (1+ index))))
- (if end (> index -1)
- (< index (length string)))))
- ;; No body.
- )
- (apply #'concat (if end result (nreverse result))))
+ ;; The previous implementation here tried to encode char by
+ ;; char, and then adding up the length of the encoded octets,
+ ;; but that's not reliably in the presence of BOM marks and
+ ;; ISO-2022-CN which may add charset designations at the
+ ;; start/end of each encoded char (which we don't want). So
+ ;; iterate (with a binary search) instead to find the desired
+ ;; length.
+ (let* ((glyphs (string-glyph-split string))
+ (nglyphs (length glyphs))
+ (too-long (1+ nglyphs))
+ (stop (max (/ nglyphs 2) 1))
+ (gap stop)
+ candidate encoded found candidate-stop)
+ ;; We're returning the end of the string.
+ (when end
+ (setq glyphs (nreverse glyphs)))
+ (while (and (not found)
+ (< stop too-long))
+ (setq encoded
+ (encode-coding-string (string-join (seq-take glyphs stop))
+ coding-system))
+ (cond
+ ((= (length encoded) length)
+ (setq found encoded
+ candidate-stop stop))
+ ;; Too long; try shortening.
+ ((> (length encoded) length)
+ (setq too-long stop
+ stop (max (- stop gap) 1)))
+ ;; Too short; try lengthening.
+ (t
+ (setq candidate encoded
+ candidate-stop stop)
+ (setq stop
+ (if (>= stop nglyphs)
+ too-long
+ (min (+ stop gap) nglyphs)))))
+ (setq gap (max (/ gap 2) 1)))
+ (cond
+ ((not (or found candidate))
+ "")
+ ;; We're returning the end, so redo the encoding.
+ (end
+ (encode-coding-string
+ (string-join (nreverse (seq-take glyphs candidate-stop)))
+ coding-system))
+ (t
+ (or found candidate))))
+ ;; Char-based version.
(cond
((<= (length string) length) string)
(end (substring string (- (length string) length)))
(t (substring string 0 length)))))
-;;;###autoload
-(defun string-lines (string &optional omit-nulls)
- "Split STRING into a list of lines.
-If OMIT-NULLS, empty lines will be removed from the results."
- (split-string string "\n" omit-nulls))
-
(defun string-pad (string length &optional padding start)
"Pad STRING to LENGTH using PADDING.
If PADDING is nil, the space character is used. If not nil, it
@@ -402,51 +311,17 @@ as the new values of the bound variables in the recursive invocation."
(cl-labels ((,name ,fargs . ,body)) #',name)
. ,aargs)))
-(defmacro with-memoization (place &rest code)
- "Return the value of CODE and stash it in PLACE.
-If PLACE's value is non-nil, then don't bother evaluating CODE
-and return the value found in PLACE instead."
- (declare (indent 1) (debug (gv-place body)))
- (gv-letplace (getter setter) place
- `(or ,getter
- ,(macroexp-let2 nil val (macroexp-progn code)
- `(progn
- ,(funcall setter val)
- ,val)))))
-
-;;;###autoload
-(defun ensure-empty-lines (&optional lines)
- "Ensure that there are LINES number of empty lines before point.
-If LINES is nil or omitted, ensure that there is a single empty
-line before point.
-
-If called interactively, LINES is given by the prefix argument.
-
-If there are more than LINES empty lines before point, the number
-of empty lines is reduced to LINES.
-
-If point is not at the beginning of a line, a newline character
-is inserted before adjusting the number of empty lines."
- (interactive "p")
- (unless (bolp)
- (insert "\n"))
- (let ((lines (or lines 1))
- (start (save-excursion
- (if (re-search-backward "[^\n]" nil t)
- (+ (point) 2)
- (point-min)))))
- (cond
- ((> (- (point) start) lines)
- (delete-region (point) (- (point) (- (point) start lines))))
- ((< (- (point) start) lines)
- (insert (make-string (- lines (- (point) start)) ?\n))))))
-
;;;###autoload
(defun string-pixel-width (string)
"Return the width of STRING in pixels."
- (with-temp-buffer
- (insert string)
- (car (buffer-text-pixel-size nil nil t))))
+ (if (zerop (length string))
+ 0
+ ;; Keeping a work buffer around is more efficient than creating a
+ ;; new temporary buffer.
+ (with-current-buffer (get-buffer-create " *string-pixel-width*")
+ (delete-region (point-min) (point-max))
+ (insert string)
+ (car (buffer-text-pixel-size nil nil t)))))
;;;###autoload
(defun string-glyph-split (string)
@@ -511,6 +386,85 @@ this defaults to the current buffer."
(put-text-property sub-start sub-end 'display disp)))
(setq sub-start sub-end))))
+;;;###autoload
+(defun read-process-name (prompt)
+ "Query the user for a process and return the process object."
+ ;; Currently supports only the PROCESS argument.
+ ;; Must either return a list containing a process, or signal an error.
+ ;; (Returning `nil' would mean the current buffer's process.)
+ (unless (fboundp 'process-list)
+ (error "Asynchronous subprocesses are not supported on this system"))
+ ;; Local function to return cons of a complete-able name, and the
+ ;; associated process object, for use with `completing-read'.
+ (cl-flet ((procitem
+ (p) (when (process-live-p p)
+ (let ((pid (process-id p))
+ (procname (process-name p))
+ (procbuf (process-buffer p)))
+ (and (eq (process-type p) 'real)
+ (cons (if procbuf
+ (format "%s (%s) in buffer %s"
+ procname pid
+ (buffer-name procbuf))
+ (format "%s (%s)" procname pid))
+ p))))))
+ ;; Perform `completing-read' for a process.
+ (let* ((currproc (get-buffer-process (current-buffer)))
+ (proclist (or (process-list)
+ (error "No processes found")))
+ (collection (delq nil (mapcar #'procitem proclist)))
+ (selection (completing-read
+ (format-prompt prompt
+ (and currproc
+ (eq (process-type currproc) 'real)
+ (procitem currproc)))
+ collection nil :require-match nil nil
+ (car (seq-find (lambda (proc)
+ (eq currproc (cdr proc)))
+ collection))))
+ (process (and selection
+ (cdr (assoc selection collection)))))
+ (unless process
+ (error "No process selected"))
+ process)))
+
+(defmacro with-buffer-unmodified-if-unchanged (&rest body)
+ "Like `progn', but change buffer-modified status only if buffer text changes.
+If the buffer was unmodified before execution of BODY, and
+buffer text after execution of BODY is identical to what it was
+before, ensure that buffer is still marked unmodified afterwards.
+For example, the following won't change the buffer's modification
+status:
+
+ (with-buffer-unmodified-if-unchanged
+ (insert \"a\")
+ (delete-char -1))
+
+Note that only changes in the raw byte sequence of the buffer text,
+as stored in the internal representation, are monitored for the
+purpose of detecting the lack of changes in buffer text. Any other
+changes that are normally perceived as \"buffer modifications\", such
+as changes in text properties, `buffer-file-coding-system', buffer
+multibyteness, etc. -- will not be noticed, and the buffer will still
+be marked unmodified, effectively ignoring those changes."
+ (declare (debug t) (indent 0))
+ (let ((hash (gensym))
+ (buffer (gensym)))
+ `(let ((,hash (and (not (buffer-modified-p))
+ (buffer-hash)))
+ (,buffer (current-buffer)))
+ (prog1
+ (progn
+ ,@body)
+ ;; If we didn't change anything in the buffer (and the buffer
+ ;; was previously unmodified), then flip the modification status
+ ;; back to "unchanged".
+ (when (and ,hash (buffer-live-p ,buffer))
+ (with-current-buffer ,buffer
+ (when (and (buffer-modified-p)
+ (equal ,hash (buffer-hash)))
+ (restore-buffer-modified-p nil))))))))
+
(provide 'subr-x)
;;; subr-x.el ends here
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index 7cc076cd806..e1be3015838 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -124,15 +124,49 @@ When the last position scanned holds the first character of a
otherwise nil. That construct can be a two character comment
delimiter or an Escaped or Char-quoted character."))
-(defun syntax-propertize-wholelines (start end)
- "Extend the region delimited by START and END to whole lines.
+(defvar syntax-wholeline-max 10000
+ "Maximum line length for syntax operations.
+If lines are longer than that, syntax operations will treat them as chunks
+of this size. Misfontification may then occur.
+This is a tradeoff between correctly applying the syntax rules,
+and avoiding major slowdown on pathologically long lines.")
+
+(defun syntax--lbp (&optional arg)
+ "Like `line-beginning-position' but obeying `syntax-wholeline-max'."
+ (let ((pos (point))
+ (res (line-beginning-position arg)))
+ (cond
+ ((< (abs (- pos res)) syntax-wholeline-max) res)
+ ;; For lines that are too long, round to the nearest multiple of
+ ;; `syntax-wholeline-max'. We use rounding rather than just
+ ;; (min res (+ pos syntax-wholeline-max)) so that repeated calls
+ ;; to `syntax-propertize-wholelines' don't keep growing the bounds,
+ ;; i.e. it really behaves like additional line-breaks.
+ ((< res pos)
+ (let ((max syntax-wholeline-max))
+ (max (point-min) (* max (truncate pos max)))))
+ (t
+ (let ((max syntax-wholeline-max))
+ (min (point-max) (* max (ceiling pos max))))))))
+
+(defun syntax-propertize-wholelines (beg end)
+ "Extend the region delimited by BEG and END to whole lines.
This function is useful for
`syntax-propertize-extend-region-functions';
see Info node `(elisp) Syntax Properties'."
- (goto-char start)
- (cons (line-beginning-position)
- (progn (goto-char end)
- (if (bolp) (point) (line-beginning-position 2)))))
+ ;; This let-binding was taken from
+ ;; `font-lock-extend-region-wholelines' where it was used to avoid
+ ;; inf-looping (Bug#21615) but for some reason it was not applied
+ ;; here in syntax.el and was used only for the "beg" side.
+ (let ((inhibit-field-text-motion t))
+ (let ((new-beg (progn (goto-char beg)
+ (if (bolp) beg
+ (syntax--lbp))))
+ (new-end (progn (goto-char end)
+ (if (bolp) end
+ (syntax--lbp 2)))))
+ (unless (and (eql beg new-beg) (eql end new-end))
+ (cons new-beg new-end)))))
(defun syntax-propertize-multiline (beg end)
"Let `syntax-propertize' pay attention to the syntax-multiline property."
@@ -345,10 +379,16 @@ END) suitable for `syntax-propertize-function'."
(defvar-local syntax-ppss-table nil
"Syntax-table to use during `syntax-ppss', if any.")
-(defvar-local syntax-propertize--inhibit-flush nil
- "If non-nil, `syntax-ppss-flush-cache' only flushes the ppss cache.
-Otherwise it flushes both the ppss cache and the properties
-set by `syntax-propertize'")
+(defun syntax-propertize--in-process-p ()
+ "Non-nil if we're inside `syntax-propertize'.
+This is used to avoid infinite recursion as well as to handle cases where
+`syntax-ppss' is called when the final `syntax-table' properties have not
+yet been setup, in which case we may end up putting invalid info into the cache.
+It's also used so that `syntax-ppss-flush-cache' can be used from within
+`syntax-propertize' without ruining the `syntax-table' already set."
+ (eq syntax-propertize--done most-positive-fixnum))
+
+(defvar-local syntax-ppss--updated-cache nil)
(defun syntax-propertize (pos)
"Ensure that syntax-table properties are set until POS (a buffer point)."
@@ -370,21 +410,24 @@ set by `syntax-propertize'")
(with-silent-modifications
(with-syntax-table (or syntax-ppss-table (syntax-table))
(make-local-variable 'syntax-propertize--done) ;Just in case!
+ ;; Make sure we let-bind it only buffer-locally.
+ (make-local-variable 'syntax-ppss--updated-cache)
(let* ((start (max (min syntax-propertize--done (point-max))
(point-min)))
(end (max pos
(min (point-max)
(+ start syntax-propertize-chunk-size))))
(first t)
- (repeat t))
+ (repeat t)
+ (syntax-ppss--updated-cache nil))
(while repeat
(setq repeat nil)
(run-hook-wrapped
'syntax-propertize-extend-region-functions
(lambda (f)
- (let ((new (funcall f start end))
- ;; Avoid recursion!
- (syntax-propertize--done most-positive-fixnum))
+ ;; Bind `syntax-propertize--done' to avoid recursion!
+ (let* ((syntax-propertize--done most-positive-fixnum)
+ (new (funcall f start end)))
(if (or (null new)
(and (>= (car new) start) (<= (cdr new) end)))
nil
@@ -399,20 +442,26 @@ set by `syntax-propertize'")
;; Flush ppss cache between the original value of `start' and that
;; set above by syntax-propertize-extend-region-functions.
(syntax-ppss-flush-cache start)
- ;; Move the limit before calling the function, so the function
- ;; can use syntax-ppss.
+ ;; Move the limit before calling the function, so it's
+ ;; done in case of errors.
(setq syntax-propertize--done end)
;; (message "syntax-propertizing from %s to %s" start end)
(remove-text-properties start end
'(syntax-table nil syntax-multiline nil))
- ;; Make sure we only let-bind it buffer-locally.
- (make-local-variable 'syntax-propertize--inhibit-flush)
- ;; Let-bind `syntax-propertize--done' to avoid infinite recursion!
- (let ((syntax-propertize--done most-positive-fixnum)
- ;; Let `syntax-propertize-function' call
- ;; `syntax-ppss-flush-cache' without worries.
- (syntax-propertize--inhibit-flush t))
- (funcall syntax-propertize-function start end)))))))))
+ ;; Bind `syntax-propertize--done' to avoid recursion!
+ (let ((syntax-propertize--done most-positive-fixnum))
+ (funcall syntax-propertize-function start end)
+ (when syntax-ppss--updated-cache
+ ;; `syntax-ppss' was called and updated the cache while we
+ ;; were propertizing so we need to flush the part of the
+ ;; cache that may have been rendered out-of-date by the new
+ ;; properties.
+ ;; We used to require syntax-propertize-functions to do that
+ ;; manually when applicable, but nowadays the `syntax-ppss'
+ ;; cache can be updated by too many functions, so the author
+ ;; of the syntax-propertize-function may not be aware it
+ ;; can happen.
+ (syntax-ppss-flush-cache start))))))))))
;;; Link syntax-propertize with syntax.c.
@@ -487,10 +536,10 @@ These are valid when the buffer has no restriction.")
(define-obsolete-function-alias 'syntax-ppss-after-change-function
#'syntax-ppss-flush-cache "27.1")
-(defun syntax-ppss-flush-cache (beg &rest ignored)
+(defun syntax-ppss-flush-cache (beg &rest _ignored)
"Flush the cache of `syntax-ppss' starting at position BEG."
;; Set syntax-propertize to refontify anything past beg.
- (unless syntax-propertize--inhibit-flush
+ (unless (syntax-propertize--in-process-p)
(setq syntax-propertize--done (min beg syntax-propertize--done)))
;; Flush invalid cache entries.
(dolist (cell (list syntax-ppss-wide syntax-ppss-narrow))
@@ -517,10 +566,16 @@ These are valid when the buffer has no restriction.")
(setcdr cell cache)))
))
-;;; FIXME: Explain this variable. Currently only its last (5th) slot is used.
-;;; Perhaps the other slots should be removed?
+;; FIXME: Explain this variable. Currently only its last (5th) slot is used.
+;; Perhaps the other slots should be removed?
+;; This variable is only used when `syntax-begin-function' is used and
+;; will hence be removed together with `syntax-begin-function'.
(defvar syntax-ppss-stats
- [(0 . 0) (0 . 0) (0 . 0) (0 . 0) (0 . 0) (2 . 2500)])
+ [(0 . 0) (0 . 0) (0 . 0) (0 . 0) (0 . 0) (2 . 2500)]
+ "Statistics about which case is more/less frequent in `syntax-ppss'.
+The 5th slot drives the heuristic to use `syntax-begin-function'.
+The rest is only useful if you're interested in tweaking the algorithm.")
+
(defun syntax-ppss-stats ()
(mapcar (lambda (x)
(condition-case nil
@@ -545,10 +600,11 @@ These are valid when the buffer has no restriction.")
(defun syntax-ppss (&optional pos)
"Parse-Partial-Sexp State at POS, defaulting to point.
+If POS is given, this function moves point to POS.
+
The returned value is the same as that of `parse-partial-sexp'
run from `point-min' to POS except that values at positions 2 and 6
in the returned list (counting from 0) cannot be relied upon.
-Point is at POS when this function returns.
It is necessary to call `syntax-ppss-flush-cache' explicitly if
this function is called while `before-change-functions' is
@@ -657,6 +713,7 @@ running the hook."
;; populate the cache so we won't need to do it again soon.
(t
(syntax-ppss--update-stats 3 pt-min pos)
+ (setq syntax-ppss--updated-cache t)
;; If `pt-min' is too far, add a few intermediate entries.
(while (> (- pos pt-min) (* 2 syntax-ppss-max-span))
@@ -691,6 +748,7 @@ running the hook."
(push pair ppss-cache)
(setcar ppss-cache pair)))))))))
+ (setq syntax-ppss--updated-cache t)
(setq ppss-last (cons pos ppss))
(setcar cell ppss-last)
(setcdr cell ppss-cache)
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 13f610bd230..9868d8c4ec0 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -216,33 +216,28 @@ If ADVANCE is non-nil, move forward by one line afterwards."
(while (re-search-forward re nil 'noerror)
(tabulated-list-put-tag empty)))))
-(defvar tabulated-list-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map (make-composed-keymap
- button-buffer-map
- special-mode-map))
- (define-key map "n" 'next-line)
- (define-key map "p" 'previous-line)
- (define-key map (kbd "M-<left>") 'tabulated-list-previous-column)
- (define-key map (kbd "M-<right>") 'tabulated-list-next-column)
- (define-key map "S" 'tabulated-list-sort)
- (define-key map "}" 'tabulated-list-widen-current-column)
- (define-key map "{" 'tabulated-list-narrow-current-column)
- (define-key map [follow-link] 'mouse-face)
- (define-key map [mouse-2] 'mouse-select-window)
- map)
- "Local keymap for `tabulated-list-mode' buffers.")
-
-(defvar tabulated-list-sort-button-map
- (let ((map (make-sparse-keymap)))
- (define-key map [header-line mouse-1] 'tabulated-list-col-sort)
- (define-key map [header-line mouse-2] 'tabulated-list-col-sort)
- (define-key map [mouse-1] 'tabulated-list-col-sort)
- (define-key map [mouse-2] 'tabulated-list-col-sort)
- (define-key map "\C-m" 'tabulated-list-sort)
- (define-key map [follow-link] 'mouse-face)
- map)
- "Local keymap for `tabulated-list-mode' sort buttons.")
+(defvar-keymap tabulated-list-mode-map
+ :doc "Local keymap for `tabulated-list-mode' buffers."
+ :parent (make-composed-keymap button-buffer-map
+ special-mode-map)
+ "n" #'next-line
+ "p" #'previous-line
+ "M-<left>" #'tabulated-list-previous-column
+ "M-<right>" #'tabulated-list-next-column
+ "S" #'tabulated-list-sort
+ "}" #'tabulated-list-widen-current-column
+ "{" #'tabulated-list-narrow-current-column
+ "<follow-link>" 'mouse-face
+ "<mouse-2>" #'mouse-select-window)
+
+(defvar-keymap tabulated-list-sort-button-map
+ :doc "Local keymap for `tabulated-list-mode' sort buttons."
+ "<header-line> <mouse-1>" #'tabulated-list-col-sort
+ "<header-line> <mouse-2>" #'tabulated-list-col-sort
+ "<mouse-1>" #'tabulated-list-col-sort
+ "<mouse-2>" #'tabulated-list-col-sort
+ "RET" #'tabulated-list-sort
+ "<follow-link>" 'mouse-face)
(defun tabulated-list-make-glyphless-char-display-table ()
"Make the `glyphless-char-display' table used for text-mode frames.
@@ -264,18 +259,14 @@ variables `tabulated-list-tty-sort-indicator-asc' and
Populated by `tabulated-list-init-header'.")
(defvar tabulated-list--header-overlay nil)
-(defun tabulated-list-line-number-width ()
- "Return the width taken by `display-line-numbers' in the current buffer."
- ;; line-number-display-width returns the value for the selected
- ;; window, which might not be the window in which the current buffer
- ;; is displayed.
- (if (not display-line-numbers)
- 0
- (let ((cbuf-window (get-buffer-window (current-buffer) t)))
- (if (window-live-p cbuf-window)
- (with-selected-window cbuf-window
- (line-number-display-width 'columns))
- 4))))
+(define-obsolete-function-alias 'tabulated-list-line-number-width
+ 'header-line-indent--line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
+ 'header-line-indent--watch-line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
+ 'header-line-indent--watch-line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-window-scroll-function
+ 'header-line-indent--window-scroll-function "29.1")
(defun tabulated-list-init-header ()
"Set up header line for the Tabulated List buffer."
@@ -289,9 +280,9 @@ Populated by `tabulated-list-init-header'.")
(hcols (mapcar #'car tabulated-list-format))
(tabulated-list--near-rows (list hcols hcols))
(cols nil))
- (if display-line-numbers
- (setq x (+ x (tabulated-list-line-number-width))))
- (push (propertize " " 'display `(space :align-to ,x)) cols)
+ (push (propertize " " 'display
+ `(space :align-to (+ header-line-indent-width ,x)))
+ cols)
(dotimes (n len)
(let* ((col (aref tabulated-list-format n))
(not-last-col (< n (1- len)))
@@ -342,20 +333,25 @@ Populated by `tabulated-list-init-header'.")
(when (> shift 0)
(setq cols
(cons (car cols)
- (cons (propertize (make-string shift ?\s)
- 'display
- `(space :align-to ,(+ x shift)))
- (cdr cols))))
+ (cons
+ (propertize
+ (make-string shift ?\s)
+ 'display
+ `(space :align-to
+ (+ header-line-indent-width ,(+ x shift))))
+ (cdr cols))))
(setq x (+ x shift)))))
(if (>= pad-right 0)
- (push (propertize " "
- 'display `(space :align-to ,next-x)
- 'face 'fixed-pitch)
+ (push (propertize
+ " "
+ 'display `(space :align-to
+ (+ header-line-indent-width ,next-x))
+ 'face 'fixed-pitch)
cols))
(setq x next-x)))
(setq cols (apply 'concat (nreverse cols)))
(if tabulated-list-use-header-line
- (setq header-line-format cols)
+ (setq header-line-format (list "" 'header-line-indent cols))
(setq-local tabulated-list--header-string cols))))
(defun tabulated-list-print-fake-header ()
@@ -596,8 +592,7 @@ Return the column number after insertion."
(when not-last-col
(when (> pad-right 0) (insert (make-string pad-right ?\s)))
(insert (propertize
- ;; We need at least one space to align correctly.
- (make-string (- width (min 1 width label-width)) ?\s)
+ (make-string (- width (min width label-width)) ?\s)
'display `(space :align-to ,next-x))))
(put-text-property opoint (point) 'tabulated-list-column-name name)
next-x)))
@@ -732,6 +727,7 @@ Interactively, N is the prefix numeric argument, and defaults to
1."
(interactive "p")
(let ((start (current-column))
+ (entry (tabulated-list-get-entry))
(nb-cols (length tabulated-list-format))
(col-nb 0)
(total-width 0)
@@ -739,14 +735,25 @@ Interactively, N is the prefix numeric argument, and defaults to
col-width)
(while (and (not found)
(< col-nb nb-cols))
- (if (> start
- (setq total-width
- (+ total-width
- (setq col-width
- (cadr (aref tabulated-list-format
- col-nb))))))
+ (if (>= start
+ (setq total-width
+ (+ total-width
+ (max (setq col-width
+ (cadr (aref tabulated-list-format
+ col-nb)))
+ (let ((desc (aref entry col-nb)))
+ (string-width (if (stringp desc)
+ desc
+ (car desc)))))
+ (or (plist-get (nthcdr 3 (aref tabulated-list-format
+ col-nb))
+ :pad-right)
+ 1))))
(setq col-nb (1+ col-nb))
(setq found t)
+ ;; `tabulated-list-format' may be a constant (sharing list
+ ;; structures), so copy it before mutating.
+ (setq tabulated-list-format (copy-tree tabulated-list-format t))
(setf (cadr (aref tabulated-list-format col-nb))
(max 1 (+ col-width n)))
(tabulated-list-print t)
@@ -759,23 +766,6 @@ Interactively, N is the prefix numeric argument, and defaults to
(interactive "p")
(tabulated-list-widen-current-column (- n)))
-(defvar tabulated-list--current-lnum-width nil)
-(defun tabulated-list-watch-line-number-width (_window)
- (if display-line-numbers
- (let ((lnum-width (tabulated-list-line-number-width)))
- (when (not (= tabulated-list--current-lnum-width lnum-width))
- (setq-local tabulated-list--current-lnum-width lnum-width)
- (tabulated-list-init-header)))))
-
-(defun tabulated-list-window-scroll-function (window _start)
- (if display-line-numbers
- (let ((lnum-width
- (with-selected-window window
- (line-number-display-width 'columns))))
- (when (not (= tabulated-list--current-lnum-width lnum-width))
- (setq-local tabulated-list--current-lnum-width lnum-width)
- (tabulated-list-init-header)))))
-
(defun tabulated-list-next-column (&optional arg)
"Go to the start of the next column after point on the current line.
If ARG is provided, move that many columns."
@@ -846,15 +836,7 @@ as the ewoc pretty-printer."
;; Avoid messing up the entries' display just because the first
;; column of the first entry happens to begin with a R2L letter.
(setq bidi-paragraph-direction 'left-to-right)
- ;; This is for if/when they turn on display-line-numbers
- (add-hook 'display-line-numbers-mode-hook #'tabulated-list-revert nil t)
- ;; This is for if/when they customize the line-number face or when
- ;; the line-number width needs to change due to scrolling.
- (setq-local tabulated-list--current-lnum-width 0)
- (add-hook 'pre-redisplay-functions
- #'tabulated-list-watch-line-number-width nil t)
- (add-hook 'window-scroll-functions
- #'tabulated-list-window-scroll-function nil t))
+ (header-line-indent-mode))
(put 'tabulated-list-mode 'mode-class 'special)
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index 33628d8f47f..cd2e388ce42 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -65,7 +65,6 @@
(eval-when-compile (require 'cl-lib))
(require 'edebug)
-(provide 'testcover)
;;;==========================================================================
@@ -677,4 +676,6 @@ The list is 1valued if all of its constituent elements are also 1valued."
(testcover-analyze-coverage (cadr form)))
(t (testcover-analyze-coverage-backquote form))))
+(provide 'testcover)
+
;;; testcover.el ends here
diff --git a/lisp/emacs-lisp/text-property-search.el b/lisp/emacs-lisp/text-property-search.el
index 9f86a28eb64..d11980f4f45 100644
--- a/lisp/emacs-lisp/text-property-search.el
+++ b/lisp/emacs-lisp/text-property-search.el
@@ -47,7 +47,7 @@ match if is not `equal' to VALUE. Furthermore, a nil PREDICATE
means that the match region is ended if the value changes. For
instance, this means that if you loop with
- (while (setq prop (text-property-search-forward 'face))
+ (while (setq prop (text-property-search-forward \\='face))
...)
you will get all distinct regions with non-nil `face' values in
@@ -166,7 +166,6 @@ and if a matching region is found, place point at the start of the region."
(let ((origin (point))
(ended nil)
pos)
- (forward-char -1)
;; Find the previous candidate.
(while (not ended)
(setq pos (previous-single-property-change (point) property))
diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el
index c93a50cabfe..d48698234fc 100644
--- a/lisp/emacs-lisp/timer-list.el
+++ b/lisp/emacs-lisp/timer-list.el
@@ -62,7 +62,7 @@
((numberp repeat)
(propertize
(format "%12s" (format-seconds
- "%dd %hh %mm %z%,1ss" repeat))
+ "%x%dd %hh %mm %z%,1ss" repeat))
'help-echo "Repeat interval"))
((null repeat)
(propertize " -" 'help-echo "Runs once"))
@@ -81,13 +81,12 @@
;; doing. Kids, don't try this at home!
;;;###autoload (put 'list-timers 'disabled "Beware: manually canceling timers can ruin your Emacs session.")
-(defvar timer-list-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "c" 'timer-list-cancel)
- (easy-menu-define nil map ""
- '("Timers"
- ["Cancel" timer-list-cancel t]))
- map))
+(defvar-keymap timer-list-mode-map
+ "c" #'timer-list-cancel
+ :menu
+ '("Timers"
+ ["Cancel" timer-list-cancel t]
+ ["Quit" quit-window]))
(define-derived-mode timer-list-mode tabulated-list-mode "Timer-List"
"Mode for listing and controlling timers."
diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el
index 71eca5a3230..c2f6c162269 100644
--- a/lisp/emacs-lisp/trace.el
+++ b/lisp/emacs-lisp/trace.el
@@ -172,9 +172,10 @@ You can call this function to add internal values in the trace buffer."
LEVEL is the trace level, ARGS is the list of arguments passed to FUNCTION,
and CONTEXT is a string describing the dynamic context (e.g. values of
some global variables)."
- (let ((print-circle t))
+ (let ((print-circle t)
+ (print-escape-newlines t))
(format "%s%s%d -> %S%s\n"
- (mapconcat 'char-to-string (make-string (max 0 (1- level)) ?|) " ")
+ (mapconcat #'char-to-string (make-string (max 0 (1- level)) ?|) " ")
(if (> level 1) " " "")
level
;; FIXME: Make it so we can click the function name to jump to its
@@ -187,7 +188,8 @@ some global variables)."
LEVEL is the trace level, VALUE value returned by FUNCTION,
and CONTEXT is a string describing the dynamic context (e.g. values of
some global variables)."
- (let ((print-circle t))
+ (let ((print-circle t)
+ (print-escape-newlines t))
(format "%s%s%d <- %s: %S%s\n"
(mapconcat 'char-to-string (make-string (1- level) ?|) " ")
(if (> level 1) " " "")
@@ -271,14 +273,14 @@ If `current-prefix-arg' is non-nil, also read a buffer and a \"context\"
(if default (symbol-name default)))))
(when current-prefix-arg
(list
- (read-buffer (format-prompt "Output to buffer" trace-buffer))
+ (read-buffer "Output to buffer" trace-buffer)
(let ((exp
- (let ((minibuffer-completing-symbol t))
- (read-from-minibuffer "Context expression: "
- nil read-expression-map t
- 'read-expression-history))))
+ (read-from-minibuffer "Context expression: "
+ nil read-expression-map t
+ 'read-expression-history)))
(lambda ()
- (let ((print-circle t))
+ (let ((print-circle t)
+ (print-escape-newlines t))
(concat " [" (prin1-to-string (eval exp t)) "]"))))))))
;;;###autoload
diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el
new file mode 100644
index 00000000000..61265c97c28
--- /dev/null
+++ b/lisp/emacs-lisp/vtable.el
@@ -0,0 +1,976 @@
+;;; vtable.el --- Displaying data in tables -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'eieio)
+(require 'text-property-search)
+(require 'mule-util)
+
+(defface vtable
+ '((t :inherit variable-pitch))
+ "Face used (by default) for vtables."
+ :version "29.1"
+ :group 'faces)
+
+(cl-defstruct vtable-column
+ "A vtable column."
+ name
+ width
+ min-width
+ max-width
+ primary
+ align
+ getter
+ formatter
+ displayer
+ -numerical)
+
+(defclass vtable ()
+ ((columns :initarg :columns :accessor vtable-columns)
+ (objects :initarg :objects :accessor vtable-objects)
+ (objects-function :initarg :objects-function
+ :accessor vtable-objects-function)
+ (getter :initarg :getter :accessor vtable-getter)
+ (formatter :initarg :formatter :accessor vtable-formatter)
+ (displayer :initarg :displayer :accessor vtable-displayer)
+ (use-header-line :initarg :use-header-line
+ :accessor vtable-use-header-line)
+ (face :initarg :face :accessor vtable-face)
+ (actions :initarg :actions :accessor vtable-actions)
+ (keymap :initarg :keymap :accessor vtable-keymap)
+ (separator-width :initarg :separator-width :accessor vtable-separator-width)
+ (divider :initarg :divider :accessor vtable-divider :initform nil)
+ (sort-by :initarg :sort-by :accessor vtable-sort-by)
+ (ellipsis :initarg :ellipsis :accessor vtable-ellipsis)
+ (column-colors :initarg :column-colors :accessor vtable-column-colors)
+ (row-colors :initarg :row-colors :accessor vtable-row-colors)
+ (-cached-colors :initform nil)
+ (-cache :initform (make-hash-table :test #'equal))
+ (-cached-keymap :initform nil)
+ (-has-column-spec :initform nil))
+ "An object to hold the data for a table.")
+
+(defvar-keymap vtable-map
+ "S" #'vtable-sort-by-current-column
+ "{" #'vtable-narrow-current-column
+ "}" #'vtable-widen-current-column
+ "g" #'vtable-revert-command
+ "M-<left>" #'vtable-previous-column
+ "M-<right>" #'vtable-next-column)
+
+(defvar-keymap vtable-header-line-map
+ :parent vtable-map
+ "<follow-link>" 'mouse-face
+ "<mouse-2>" #'vtable-header-line-sort)
+
+(cl-defun make-vtable (&key columns objects objects-function
+ getter
+ formatter
+ displayer
+ (use-header-line t)
+ (face 'vtable)
+ actions keymap
+ (separator-width 1)
+ divider
+ divider-width
+ sort-by
+ (ellipsis t)
+ (insert t)
+ row-colors
+ column-colors)
+ "Create and insert a vtable at point.
+The vtable object is returned. If INSERT is nil, the table won't
+be inserted.
+
+See info node `(vtable)Top' for vtable documentation."
+ (when objects-function
+ (setq objects (funcall objects-function)))
+ ;; We'll be altering the list, so create a copy.
+ (setq objects (copy-sequence objects))
+ (let ((table
+ (make-instance
+ 'vtable
+ :objects objects
+ :objects-function objects-function
+ :getter getter
+ :formatter formatter
+ :displayer displayer
+ :use-header-line use-header-line
+ :face face
+ :actions actions
+ :keymap keymap
+ :separator-width separator-width
+ :sort-by sort-by
+ :row-colors row-colors
+ :column-colors column-colors
+ :ellipsis ellipsis)))
+ ;; Store whether the user has specified columns or not.
+ (setf (slot-value table '-has-column-spec) (not (not columns)))
+ ;; Auto-generate the columns.
+ (unless columns
+ (unless objects
+ (error "Can't auto-generate columns; no objects"))
+ (setq columns (make-list (length (car objects)) "")))
+ (setf (vtable-columns table)
+ (mapcar (lambda (column)
+ (cond
+ ;; We just have the name (as a string).
+ ((stringp column)
+ (make-vtable-column :name column))
+ ;; A plist of keywords/values.
+ ((listp column)
+ (apply #'make-vtable-column column))
+ ;; A full `vtable-column' object.
+ (t
+ column)))
+ columns))
+ ;; Compute missing column data.
+ (setf (vtable-columns table) (vtable--compute-columns table))
+ ;; Compute the colors.
+ (when (or row-colors column-colors)
+ (setf (slot-value table '-cached-colors)
+ (vtable--compute-colors row-colors column-colors)))
+ ;; Compute the divider.
+ (when (or divider divider-width)
+ (setf (vtable-divider table)
+ (propertize
+ (or (copy-sequence divider)
+ (propertize
+ " " 'display
+ (list 'space :width
+ (list (vtable--compute-width table divider-width)))))
+ 'mouse-face 'highlight
+ 'keymap
+ (define-keymap
+ "<drag-mouse-1>" #'vtable--drag-resize-column
+ "<down-mouse-1>" #'ignore))))
+ ;; Compute the keymap.
+ (setf (slot-value table '-cached-keymap) (vtable--make-keymap table))
+ (unless sort-by
+ (seq-do-indexed (lambda (column index)
+ (when (vtable-column-primary column)
+ (push (cons index (vtable-column-primary column))
+ (vtable-sort-by table))))
+ (vtable-columns table)))
+ (when insert
+ (vtable-insert table))
+ table))
+
+(defun vtable--compute-colors (row-colors column-colors)
+ (cond
+ ((null column-colors)
+ (mapcar #'vtable--make-color-face row-colors))
+ ((null row-colors)
+ (mapcar #'vtable--make-color-face column-colors))
+ (t
+ (cl-loop for row in row-colors
+ collect (cl-loop for column in column-colors
+ collect (vtable--face-blend
+ (vtable--make-color-face row)
+ (vtable--make-color-face column)))))))
+
+(defun vtable--make-color-face (object)
+ (if (stringp object)
+ (list :background object)
+ object))
+
+(defun vtable--face-blend (face1 face2)
+ (let ((foreground (vtable--face-color face1 face2 #'face-foreground
+ :foreground))
+ (background (vtable--face-color face1 face2 #'face-background
+ :background)))
+ `(,@(and foreground (list :foreground foreground))
+ ,@(and background (list :background background)))))
+
+(defun vtable--face-color (face1 face2 accessor slot)
+ (let ((col1 (if (facep face1)
+ (funcall accessor face1)
+ (plist-get face1 slot)))
+ (col2 (if (facep face2)
+ (funcall accessor face2)
+ (plist-get face2 slot))))
+ (if (and col1 col2)
+ (vtable--color-blend col1 col2)
+ (or col1 col2))))
+
+;;; FIXME: This is probably not the right way to blend two colors, is
+;;; it?
+(defun vtable--color-blend (color1 color2)
+ (cl-destructuring-bind (r g b)
+ (mapcar (lambda (n) (* (/ n 2) 255.0))
+ (cl-mapcar #'+ (color-name-to-rgb color1)
+ (color-name-to-rgb color2)))
+ (format "#%02X%02X%02X" r g b)))
+
+;;; Interface utility functions.
+
+(defun vtable-current-table ()
+ "Return the table under point."
+ (get-text-property (point) 'vtable))
+
+(defun vtable-current-object ()
+ "Return the object under point."
+ (get-text-property (point) 'vtable-object))
+
+(defun vtable-current-column ()
+ "Return the index of the column under point."
+ (get-text-property (point) 'vtable-column))
+
+(defun vtable-beginning-of-table ()
+ "Go to the start of the current table."
+ (if (text-property-search-backward 'vtable (vtable-current-table))
+ (point)
+ (goto-char (point-min))))
+
+(defun vtable-end-of-table ()
+ "Go to the end of the current table."
+ (if (text-property-search-forward 'vtable (vtable-current-table))
+ (point)
+ (goto-char (point-max))))
+
+(defun vtable-goto-object (object)
+ "Go to OBJECT in the current table.
+Return the position of the object if found, and nil if not."
+ (let ((start (point)))
+ (vtable-beginning-of-table)
+ (save-restriction
+ (narrow-to-region (point) (save-excursion (vtable-end-of-table)))
+ (if (text-property-search-forward 'vtable-object object #'eq)
+ (progn
+ (forward-line -1)
+ (point))
+ (goto-char start)
+ nil))))
+
+(defun vtable-goto-table (table)
+ "Go to TABLE in the current buffer.
+If TABLE is found, return the position of the start of the table.
+If it can't be found, return nil and don't move point."
+ (let ((start (point)))
+ (goto-char (point-min))
+ (if-let ((match (text-property-search-forward 'vtable table t)))
+ (goto-char (prop-match-beginning match))
+ (goto-char start)
+ nil)))
+
+(defun vtable-goto-column (column)
+ "Go to COLUMN on the current line."
+ (beginning-of-line)
+ (if-let ((match (text-property-search-forward 'vtable-column column t)))
+ (goto-char (prop-match-beginning match))
+ (end-of-line)))
+
+(defun vtable-update-object (table object old-object)
+ "Replace OLD-OBJECT in TABLE with OBJECT."
+ (let* ((objects (vtable-objects table))
+ (inhibit-read-only t))
+ ;; First replace the object in the object storage.
+ (if (eq old-object (car objects))
+ ;; It's at the head, so replace it there.
+ (setf (vtable-objects table)
+ (cons object (cdr objects)))
+ ;; Otherwise splice into the list.
+ (while (and (cdr objects)
+ (not (eq (cadr objects) old-object)))
+ (setq objects (cdr objects)))
+ (unless objects
+ (error "Can't find the old object"))
+ (setcar (cdr objects) object))
+ ;; Then update the cache...
+ (let* ((line-number (seq-position old-object (car (vtable--cache table))))
+ (line (elt (car (vtable--cache table)) line-number)))
+ (unless line
+ (error "Can't find cached object"))
+ (setcar line object)
+ (setcdr line (vtable--compute-cached-line table object))
+ ;; ... and redisplay the line in question.
+ (save-excursion
+ (vtable-goto-object old-object)
+ (let ((keymap (get-text-property (point) 'keymap))
+ (start (point)))
+ (delete-line)
+ (vtable--insert-line table line line-number
+ (nth 1 (vtable--cache table))
+ (vtable--spacer table))
+ (add-text-properties start (point) (list 'keymap keymap
+ 'vtable table))))
+ ;; We may have inserted a non-numerical value into a previously
+ ;; all-numerical table, so recompute.
+ (vtable--recompute-numerical table (cdr line)))))
+
+(defun vtable-remove-object (table object)
+ "Remove OBJECT from TABLE.
+This will also remove the displayed line."
+ ;; First remove from the objects.
+ (setf (vtable-objects table) (delq object (vtable-objects table)))
+ ;; Then adjust the cache and display.
+ (let ((cache (vtable--cache table))
+ (inhibit-read-only t))
+ (setcar cache (delq (assq object (car cache)) (car cache)))
+ (save-excursion
+ (vtable-goto-table table)
+ (when (vtable-goto-object object)
+ (delete-line)))))
+
+(defun vtable-insert-object (table object &optional after-object)
+ "Insert OBJECT into TABLE after AFTER-OBJECT.
+If AFTER-OBJECT is nil (or doesn't exist in the table), insert
+OBJECT at the end.
+This also updates the displayed table."
+ ;; First insert into the objects.
+ (let (pos)
+ (if (and after-object
+ (setq pos (memq after-object (vtable-objects table))))
+ ;; Splice into list.
+ (setcdr pos (cons object (cdr pos)))
+ ;; Append.
+ (nconc (vtable-objects table) (list object))))
+ ;; Then adjust the cache and display.
+ (save-excursion
+ (vtable-goto-table table)
+ (let* ((cache (vtable--cache table))
+ (inhibit-read-only t)
+ (keymap (get-text-property (point) 'keymap))
+ (elem (and after-object
+ (assq after-object (car cache))))
+ (line (cons object (vtable--compute-cached-line table object))))
+ (if (not elem)
+ ;; Append.
+ (progn
+ (setcar cache (nconc (car cache) (list line)))
+ (vtable-end-of-table))
+ ;; Splice into list.
+ (let ((pos (memq elem (car cache))))
+ (setcdr pos (cons line (cdr pos)))
+ (unless (vtable-goto-object after-object)
+ (vtable-end-of-table))))
+ (let ((start (point)))
+ ;; FIXME: We have to adjust colors in lines below this if we
+ ;; have :row-colors.
+ (vtable--insert-line table line 0
+ (nth 1 cache) (vtable--spacer table))
+ (add-text-properties start (point) (list 'keymap keymap
+ 'vtable table)))
+ ;; We may have inserted a non-numerical value into a previously
+ ;; all-numerical table, so recompute.
+ (vtable--recompute-numerical table (cdr line)))))
+
+(defun vtable-column (table index)
+ "Return the name of the INDEXth column in TABLE."
+ (vtable-column-name (elt (vtable-columns table) index)))
+
+;;; Generating the table.
+
+(defun vtable--get-value (object index column table)
+ "Compute a cell value."
+ (cond
+ ((vtable-column-getter column)
+ (funcall (vtable-column-getter column)
+ object table))
+ ((vtable-getter table)
+ (funcall (vtable-getter table)
+ object index table))
+ ;; No getter functions; standard getters.
+ ((stringp object)
+ object)
+ (t
+ (elt object index))))
+
+(defun vtable--compute-columns (table)
+ (let ((numerical (make-vector (length (vtable-columns table)) t))
+ (columns (vtable-columns table)))
+ ;; First determine whether there are any all-numerical columns.
+ (dolist (object (vtable-objects table))
+ (seq-do-indexed
+ (lambda (_elem index)
+ (unless (numberp (vtable--get-value object index (elt columns index)
+ table))
+ (setf (elt numerical index) nil)))
+ (vtable-columns table)))
+ ;; Then fill in defaults.
+ (seq-map-indexed
+ (lambda (column index)
+ ;; This is used when displaying.
+ (unless (vtable-column-align column)
+ (setf (vtable-column-align column)
+ (if (elt numerical index)
+ 'right
+ 'left)))
+ ;; This is used for sorting.
+ (setf (vtable-column--numerical column)
+ (elt numerical index))
+ column)
+ (vtable-columns table))))
+
+(defun vtable--spacer (table)
+ (vtable--compute-width table (vtable-separator-width table)))
+
+(defun vtable--recompute-cache (table)
+ (let* ((data (vtable--compute-cache table))
+ (widths (vtable--compute-widths table data)))
+ (setf (gethash (vtable--cache-key) (slot-value table '-cache))
+ (list data widths))))
+
+(defun vtable--ensure-cache (table)
+ (or (vtable--cache table)
+ (vtable--recompute-cache table)))
+
+(defun vtable-insert (table)
+ (let* ((spacer (vtable--spacer table))
+ (start (point))
+ (ellipsis (if (vtable-ellipsis table)
+ (propertize (truncate-string-ellipsis)
+ 'face (vtable-face table))
+ ""))
+ (ellipsis-width (string-pixel-width ellipsis))
+ ;; We maintain a cache per screen/window width, so that we render
+ ;; correctly if Emacs is open on two different screens (or the
+ ;; user resizes the frame).
+ (widths (nth 1 (vtable--ensure-cache table))))
+ ;; Don't insert any header or header line if the user hasn't
+ ;; specified the columns.
+ (when (slot-value table '-has-column-spec)
+ (if (vtable-use-header-line table)
+ (vtable--set-header-line table widths spacer)
+ ;; Insert the header line directly into the buffer, and put a
+ ;; keymap to be able to sort the columns there (by clicking on
+ ;; them).
+ (vtable--insert-header-line table widths spacer)
+ (add-text-properties start (point)
+ (list 'keymap vtable-header-line-map
+ 'rear-nonsticky t
+ 'vtable table))
+ (setq start (point))))
+ (vtable--sort table)
+ ;; Insert the data.
+ (let ((line-number 0))
+ (dolist (line (car (vtable--cache table)))
+ (vtable--insert-line table line line-number widths spacer
+ ellipsis ellipsis-width)
+ (setq line-number (1+ line-number))))
+ (add-text-properties start (point)
+ (list 'rear-nonsticky t
+ 'vtable table))
+ (goto-char start)))
+
+(defun vtable--insert-line (table line line-number widths spacer
+ &optional ellipsis ellipsis-width)
+ (let ((start (point))
+ (columns (vtable-columns table))
+ (column-colors
+ (and (vtable-column-colors table)
+ (if (vtable-row-colors table)
+ (elt (slot-value table '-cached-colors)
+ (mod line-number (length (vtable-row-colors table))))
+ (slot-value table '-cached-colors))))
+ (divider (vtable-divider table))
+ (keymap (slot-value table '-cached-keymap)))
+ (seq-do-indexed
+ (lambda (elem index)
+ (let ((value (nth 0 elem))
+ (column (elt columns index))
+ (pre-computed (nth 2 elem)))
+ ;; See if we have any formatters here.
+ (cond
+ ((vtable-column-formatter column)
+ (setq value (funcall (vtable-column-formatter column) value)
+ pre-computed nil))
+ ((vtable-formatter table)
+ (setq value (funcall (vtable-formatter table)
+ value index table)
+ pre-computed nil)))
+ (let ((displayed
+ ;; Allow any displayers to have their say.
+ (cond
+ ((vtable-column-displayer column)
+ (funcall (vtable-column-displayer column)
+ value (elt widths index) table))
+ ((vtable-displayer table)
+ (funcall (vtable-displayer table)
+ value index (elt widths index) table))
+ (pre-computed
+ ;; If we don't have a displayer, use the pre-made
+ ;; (cached) string value.
+ (if (> (nth 1 elem) (elt widths index))
+ (concat
+ (vtable--limit-string
+ pre-computed (- (elt widths index) ellipsis-width))
+ ellipsis)
+ pre-computed))
+ ;; Recompute widths.
+ (t
+ (if (> (string-pixel-width value) (elt widths index))
+ (concat
+ (vtable--limit-string
+ value (- (elt widths index) ellipsis-width))
+ ellipsis)
+ value))))
+ (start (point))
+ ;; Don't insert the separator after the final column.
+ (last (= index (- (length line) 2))))
+ (if (eq (vtable-column-align column) 'left)
+ (progn
+ (insert displayed)
+ (insert (propertize
+ " " 'display
+ (list 'space
+ :width (list
+ (+ (- (elt widths index)
+ (string-pixel-width displayed))
+ (if last 0 spacer)))))))
+ ;; Align to the right.
+ (insert (propertize " " 'display
+ (list 'space
+ :width (list (- (elt widths index)
+ (string-pixel-width
+ displayed)))))
+ displayed)
+ (unless last
+ (insert (propertize " " 'display
+ (list 'space
+ :width (list spacer))))))
+ (put-text-property start (point) 'vtable-column index)
+ (put-text-property start (point) 'keymap keymap)
+ (when column-colors
+ (add-face-text-property
+ start (point)
+ (elt column-colors (mod index (length column-colors)))))
+ (when divider
+ (insert divider)
+ (setq start (point))))))
+ (cdr line))
+ (insert "\n")
+ (put-text-property start (point) 'vtable-object (car line))
+ (unless column-colors
+ (when-let ((row-colors (slot-value table '-cached-colors)))
+ (add-face-text-property
+ start (point)
+ (elt row-colors (mod line-number (length row-colors))))))))
+
+(defun vtable--cache-key ()
+ (cons (frame-terminal) (window-width)))
+
+(defun vtable--cache (table)
+ (gethash (vtable--cache-key) (slot-value table '-cache)))
+
+(defun vtable--clear-cache (table)
+ (setf (gethash (vtable--cache-key) (slot-value table '-cache)) nil))
+
+(defun vtable--sort (table)
+ (pcase-dolist (`(,index . ,direction) (vtable-sort-by table))
+ (let ((cache (vtable--cache table))
+ (numerical (vtable-column--numerical
+ (elt (vtable-columns table) index)))
+ (numcomp (if (eq direction 'descend)
+ #'> #'<))
+ (stringcomp (if (eq direction 'descend)
+ #'string> #'string<)))
+ (setcar cache
+ (sort (car cache)
+ (lambda (e1 e2)
+ (let ((c1 (elt e1 (1+ index)))
+ (c2 (elt e2 (1+ index))))
+ (if numerical
+ (funcall numcomp (car c1) (car c2))
+ (funcall
+ stringcomp
+ (if (stringp (car c1))
+ (car c1)
+ (format "%s" (car c1)))
+ (if (stringp (car c2))
+ (car c2)
+ (format "%s" (car c2))))))))))))
+
+(defun vtable--indicator (table index)
+ (let ((order (car (last (vtable-sort-by table)))))
+ (if (eq index (car order))
+ ;; We're sorting by this column last, so return an indicator.
+ (catch 'found
+ (dolist (candidate (nth (if (eq (cdr order) 'ascend)
+ 1
+ 0)
+ '((?▼ ?v)
+ (?▲ ?^))))
+ (when (char-displayable-p candidate)
+ (throw 'found (string candidate)))))
+ "")))
+
+(defun vtable--insert-header-line (table widths spacer)
+ ;; Insert the header directly into the buffer.
+ (let ((start (point))
+ (divider (vtable-divider table))
+ (cmap (define-keymap
+ "<header-line> <drag-mouse-1>" #'vtable--drag-resize-column
+ "<header-line> <down-mouse-1>" #'ignore))
+ (dmap (define-keymap
+ "<header-line> <drag-mouse-1>"
+ (lambda (e)
+ (interactive "e")
+ (vtable--drag-resize-column e t))
+ "<header-line> <down-mouse-1>" #'ignore)))
+ (seq-do-indexed
+ (lambda (column index)
+ (let* ((name (propertize
+ (vtable-column-name column)
+ 'face (list 'header-line (vtable-face table))
+ 'mouse-face 'header-line-highlight
+ 'keymap cmap))
+ (start (point))
+ (indicator (vtable--indicator table index))
+ (indicator-width (string-pixel-width indicator))
+ (last (= index (1- (length (vtable-columns table)))))
+ displayed)
+ (setq displayed
+ (if (> (string-pixel-width name)
+ (- (elt widths index) indicator-width))
+ (vtable--limit-string
+ name (- (elt widths index) indicator-width))
+ name))
+ (let ((fill-width
+ (+ (- (elt widths index)
+ (string-pixel-width displayed)
+ indicator-width
+ (vtable-separator-width table)
+ ;; We want the indicator to not be quite flush
+ ;; right.
+ (/ (vtable--char-width table) 2.0))
+ (if last 0 spacer))))
+ (if (or (not last)
+ (zerop indicator-width)
+ (< (seq-reduce #'+ widths 0) (window-width nil t)))
+ ;; Normal case.
+ (insert
+ displayed
+ (propertize " " 'display
+ (list 'space :width (list fill-width)))
+ indicator)
+ ;; This is the final column, and we have a sorting
+ ;; indicator, and the table is too wide for the window.
+ (let* ((pre-indicator (string-pixel-width
+ (buffer-substring (point-min) (point))))
+ (pre-fill
+ (- (window-width nil t)
+ pre-indicator
+ (string-pixel-width displayed))))
+ (insert
+ displayed
+ (propertize " " 'display
+ (list 'space :width (list pre-fill)))
+ indicator
+ (propertize " " 'display
+ (list 'space :width
+ (list (- fill-width pre-fill))))))))
+ (when (and divider (not last))
+ (insert (propertize divider 'keymap dmap)))
+ (insert (propertize
+ " " 'display
+ (list 'space :width (list
+ (/ (vtable--char-width table) 2.0)))))
+ (put-text-property start (point) 'vtable-column index)))
+ (vtable-columns table))
+ (insert "\n")
+ (add-face-text-property start (point) 'header-line)))
+
+(defun vtable--drag-resize-column (e &optional next)
+ "Resize the column by dragging.
+If NEXT, do the next column."
+ (interactive "e")
+ (let* ((pos-start (event-start e))
+ (obj (posn-object pos-start)))
+ (with-current-buffer (window-buffer (posn-window pos-start))
+ (let ((column
+ ;; In the header line we have a text property on the
+ ;; divider.
+ (or (get-text-property (if obj (cdr obj)
+ (posn-point pos-start))
+ 'vtable-column
+ (car obj))
+ ;; For reasons of efficiency, we don't have that in
+ ;; the buffer itself, so find the column.
+ (save-excursion
+ (goto-char (posn-point pos-start))
+ (1+
+ (get-text-property
+ (prop-match-beginning
+ (text-property-search-backward 'vtable-column))
+ 'vtable-column)))))
+ (start-x (car (posn-x-y pos-start)))
+ (end-x (car (posn-x-y (event-end e)))))
+ (when (or (> column 0) next)
+ (vtable--alter-column-width (vtable-current-table)
+ (if next
+ column
+ (1- column))
+ (- end-x start-x)))))))
+
+(defun vtable--recompute-numerical (table line)
+ "Recompute numericalness of columns if necessary."
+ (let ((columns (vtable-columns table))
+ (recompute nil))
+ (seq-do-indexed
+ (lambda (elem index)
+ (when (and (vtable-column--numerical (elt columns index))
+ (not (numberp elem)))
+ (setq recompute t)))
+ line)
+ (when recompute
+ (vtable--compute-columns table))))
+
+(defun vtable--set-header-line (table widths spacer)
+ (setq header-line-format
+ (string-replace
+ "%" "%%"
+ (with-temp-buffer
+ (insert " ")
+ (vtable--insert-header-line table widths spacer)
+ ;; Align the header with the (possibly) fringed buffer text.
+ (put-text-property
+ (point-min) (1+ (point-min))
+ 'display '(space :align-to 0))
+ (buffer-substring (point-min) (1- (point-max))))))
+ (vtable-header-mode 1))
+
+(defun vtable--limit-string (string pixels)
+ (while (and (length> string 0)
+ (> (string-pixel-width string) pixels))
+ (setq string (substring string 0 (1- (length string)))))
+ string)
+
+(defun vtable--char-width (table)
+ (string-pixel-width (propertize "x" 'face (vtable-face table))))
+
+(defun vtable--compute-width (table spec)
+ (cond
+ ((numberp spec)
+ (* spec (vtable--char-width table)))
+ ((string-match "\\([0-9.]+\\)ex" spec)
+ (* (string-to-number (match-string 1 spec)) (vtable--char-width table)))
+ ((string-match "\\([0-9.]+\\)px" spec)
+ (string-to-number (match-string 1 spec)))
+ ((string-match "\\([0-9.]+\\)%" spec)
+ (* (string-to-number (match-string 1 spec)) (window-width nil t)))
+ (t
+ (error "Invalid spec: %s" spec))))
+
+(defun vtable--compute-widths (table cache)
+ "Compute the display widths for TABLE."
+ (seq-into
+ (seq-map-indexed
+ (lambda (column index)
+ (let ((width
+ (or
+ ;; Explicit widths.
+ (and (vtable-column-width column)
+ (vtable--compute-width table (vtable-column-width column)))
+ ;; Compute based on the displayed widths of
+ ;; the data.
+ (seq-max (seq-map (lambda (elem)
+ (nth 1 (elt (cdr elem) index)))
+ cache)))))
+ ;; Let min-width/max-width specs have their say.
+ (when-let ((min-width (and (vtable-column-min-width column)
+ (vtable--compute-width
+ table (vtable-column-min-width column)))))
+ (setq width (max width min-width)))
+ (when-let ((max-width (and (vtable-column-max-width column)
+ (vtable--compute-width
+ table (vtable-column-max-width column)))))
+ (setq width (min width max-width)))
+ width))
+ (vtable-columns table))
+ 'vector))
+
+(defun vtable--compute-cache (table)
+ (seq-map
+ (lambda (object)
+ (cons object (vtable--compute-cached-line table object)))
+ (vtable-objects table)))
+
+(defun vtable--compute-cached-line (table object)
+ (seq-map-indexed
+ (lambda (column index)
+ (let* ((value (vtable--get-value object index column table))
+ (string (if (stringp value)
+ (copy-sequence value)
+ (format "%s" value))))
+ (add-face-text-property 0 (length string)
+ (vtable-face table)
+ t string)
+ ;; We stash the computed width and string here -- if there are
+ ;; no formatters/displayers, we'll be using the string, and
+ ;; then won't have to recreate it.
+ (list value (string-pixel-width string) string)))
+ (vtable-columns table)))
+
+(defun vtable--make-keymap (table)
+ (let ((map (if (or (vtable-actions table)
+ (vtable-keymap table))
+ (copy-keymap vtable-map)
+ vtable-map)))
+ (when-let ((actions (vtable-actions table)))
+ (while actions
+ (funcall (lambda (key binding)
+ (keymap-set map key
+ (lambda (object)
+ (interactive (list (vtable-current-object)))
+ (funcall binding object))))
+ (car actions) (cadr actions))
+ (setq actions (cddr actions))))
+ (if (vtable-keymap table)
+ (progn
+ (setf (vtable-keymap table)
+ (copy-keymap (vtable-keymap table)))
+ ;; Respect any previously set parent keymaps.
+ (set-keymap-parent (vtable-keymap table)
+ (if (keymap-parent (vtable-keymap table))
+ (append (ensure-list
+ (vtable-keymap table))
+ (list map))
+ map))
+ (vtable-keymap table))
+ map)))
+
+(defun vtable-revert ()
+ "Regenerate the table under point."
+ (let ((table (vtable-current-table))
+ (object (vtable-current-object))
+ (column (vtable-current-column))
+ (inhibit-read-only t))
+ (unless table
+ (user-error "No table under point"))
+ (delete-region (vtable-beginning-of-table) (vtable-end-of-table))
+ (vtable-insert table)
+ (when object
+ (vtable-goto-object object))
+ (when column
+ (vtable-goto-column column))))
+
+(defun vtable--widths (table)
+ (nth 1 (vtable--ensure-cache table)))
+
+;;; Commands.
+
+(defvar-keymap vtable-header-mode-map
+ "<header-line> <mouse-1>" 'vtable-header-line-sort
+ "<header-line> <mouse-2>" 'vtable-header-line-sort)
+
+(define-minor-mode vtable-header-mode
+ "Minor mode for buffers with vtables with headers."
+ :keymap vtable-header-mode-map)
+
+(defun vtable-narrow-current-column (&optional n)
+ "Narrow the current column by N characters.
+If N isn't given, N defaults to 1.
+
+Interactively, N is the prefix argument."
+ (interactive "p")
+ (let* ((table (vtable-current-table))
+ (column (vtable-current-column)))
+ (unless column
+ (user-error "No column under point"))
+ (vtable--alter-column-width table column
+ (- (* (vtable--char-width table) (or n 1))))))
+
+(defun vtable--alter-column-width (table column delta)
+ (let ((widths (vtable--widths table)))
+ (setf (aref widths column)
+ (max (* (vtable--char-width table) 2)
+ (+ (aref widths column) delta)))
+ ;; Store the width so it'll be respected on a revert.
+ (setf (vtable-column-width (elt (vtable-columns table) column))
+ (format "%dpx" (aref widths column)))
+ (vtable-revert)))
+
+(defun vtable-widen-current-column (&optional n)
+ "Widen the current column by N characters.
+If N isn't given, N defaults to 1.
+
+Interactively, N is the prefix argument."
+ (interactive "p")
+ (vtable-narrow-current-column (- n)))
+
+(defun vtable-previous-column ()
+ "Go to the previous column."
+ (interactive)
+ (vtable-goto-column
+ (max 0 (1- (or (vtable-current-column)
+ (length (vtable--widths (vtable-current-table))))))))
+
+(defun vtable-next-column ()
+ "Go to the next column."
+ (interactive)
+ (when (vtable-current-column)
+ (vtable-goto-column
+ (min (1- (length (vtable--widths (vtable-current-table))))
+ (1+ (vtable-current-column))))))
+
+(defun vtable-revert-command ()
+ "Re-query data and regenerate the table under point."
+ (interactive)
+ (let ((table (vtable-current-table)))
+ (when (vtable-objects-function table)
+ (setf (vtable-objects table) (funcall (vtable-objects-function table))))
+ (vtable--clear-cache table))
+ (vtable-revert))
+
+(defun vtable-sort-by-current-column ()
+ "Sort the table under point by the column under point."
+ (interactive)
+ (unless (vtable-current-column)
+ (user-error "No current column"))
+ (let* ((table (vtable-current-table))
+ (last (car (last (vtable-sort-by table))))
+ (index (vtable-current-column)))
+ ;; First prune any previous appearance of this column.
+ (setf (vtable-sort-by table)
+ (delq (assq index (vtable-sort-by table))
+ (vtable-sort-by table)))
+ ;; Then insert this as the last sort key.
+ (setf (vtable-sort-by table)
+ (append (vtable-sort-by table)
+ (list (cons index
+ (if (eq (car last) index)
+ (if (eq (cdr last) 'ascend)
+ 'descend
+ 'ascend)
+ 'ascend))))))
+ (vtable-revert))
+
+(defun vtable-header-line-sort (e)
+ "Sort a vtable from the header line."
+ (interactive "e")
+ (let* ((pos (event-start e))
+ (obj (posn-object pos)))
+ (with-current-buffer (window-buffer (posn-window pos))
+ (goto-char (point-min))
+ (vtable-goto-column
+ (get-text-property (if obj (cdr obj) (posn-point pos))
+ 'vtable-column
+ (car obj)))
+ (vtable-sort-by-current-column))))
+
+(provide 'vtable)
+
+;;; vtable.el ends here
diff --git a/lisp/emacs-lock.el b/lisp/emacs-lock.el
index 3d2eda99a9c..1818e22a923 100644
--- a/lisp/emacs-lock.el
+++ b/lisp/emacs-lock.el
@@ -88,9 +88,6 @@ The functions get one argument, the first locked buffer found."
:group 'emacs-lock
:version "24.3")
-(define-obsolete-variable-alias 'emacs-lock-from-exiting
- 'emacs-lock-mode "24.1")
-
(defvar-local emacs-lock-mode nil
"If non-nil, the current buffer is locked.
It can be one of the following values:
@@ -247,14 +244,6 @@ some major modes from being locked under some circumstances."
;; continue standard unloading
nil))
-;;; Compatibility
-
-(defun toggle-emacs-lock ()
- "Toggle `emacs-lock-from-exiting' for the current buffer."
- (declare (obsolete emacs-lock-mode "24.1"))
- (interactive)
- (call-interactively 'emacs-lock-mode))
-
(provide 'emacs-lock)
;;; emacs-lock.el ends here
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index e399fd0fbf3..a7f3d5fe14c 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -572,7 +572,7 @@ Only call fct for visible lines if VISIBLE==t.
Set undo boundary if UNDO is non-nil.
Rectangle is padded if PAD = t or numeric and (cua--rectangle-virtual-edges)
Perform auto-tabify after operation if TABIFY is non-nil.
-Mark is kept if keep-clear is 'keep and cleared if keep-clear is 'clear."
+Mark is kept if keep-clear is `keep' and cleared if keep-clear is `clear'."
(declare (indent 4))
(let* ((inhibit-field-text-motion t)
(start (cua--rectangle-top))
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 83944285e91..ddb49609d40 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -1783,7 +1783,7 @@ Undo previous insertion and inserts new."
(do-not-change-default t))
(setq quote-str
(viper-read-string-with-history
- "Quote string"
+ "Quote string: "
nil
'viper-quote-region-history
;; FIXME: Use comment-region.
@@ -1992,17 +1992,24 @@ problems."
#'viper-minibuffer-standard-hook
(if (or (not (listp old)) (eq (car old) 'lambda))
(list old) old))))
- (val ""))
+ (val "")
+ (padding "")
+ temp-msg)
(setq keymap (or keymap minibuffer-local-map)
initial (or initial "")
- viper-initial initial)
+ viper-initial initial
+ temp-msg (if default
+ (format "(default %s) " default)
+ ""))
(setq viper-incomplete-ex-cmd nil)
- (setq val (read-from-minibuffer (format-prompt prompt default)
- nil
- keymap nil history-var default))
- (setq minibuffer-setup-hook nil)
+ (setq val (read-from-minibuffer prompt
+ (concat temp-msg initial val padding)
+ keymap nil history-var))
+ (setq minibuffer-setup-hook nil
+ padding (viper-array-to-string (this-command-keys))
+ temp-msg "")
;; the following tries to be smart about what to put in history
(if (not (string= val (car (symbol-value history-var))))
(push val (symbol-value history-var)))
@@ -3815,7 +3822,7 @@ Null string will repeat previous search."
(let (buffer buffer-name)
(setq buffer-name
(funcall viper-read-buffer-function
- (format-prompt "Kill buffer"
+ (format "Kill buffer (%s): "
(buffer-name (current-buffer)))))
(setq buffer
(if (null buffer-name)
@@ -4157,12 +4164,17 @@ cursor move past the beginning of line."
"Query replace.
If a null string is supplied as the string to be replaced,
the query replace mode will toggle between string replace
-and regexp replace."
+and regexp replace.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time."
(interactive)
(let (str)
(setq str (viper-read-string-with-history
- (if viper-re-query-replace "Query replace regexp"
- "Query replace")
+ (if viper-re-query-replace "Query replace regexp: "
+ "Query replace: ")
nil ; no initial
'viper-replace1-history
(car viper-replace1-history) ; default
@@ -4177,7 +4189,7 @@ and regexp replace."
(query-replace-regexp
str
(viper-read-string-with-history
- (format-message "Query replace regexp `%s' with" str)
+ (format-message "Query replace regexp `%s' with: " str)
nil ; no initial
'viper-replace1-history
(car viper-replace1-history) ; default
@@ -4185,7 +4197,7 @@ and regexp replace."
(query-replace
str
(viper-read-string-with-history
- (format-message "Query replace `%s' with" str)
+ (format-message "Query replace `%s' with: " str)
nil ; no initial
'viper-replace1-history
(car viper-replace1-history) ; default
diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el
index c4eb183ce44..06130afa7da 100644
--- a/lisp/emulation/viper-macs.el
+++ b/lisp/emulation/viper-macs.el
@@ -105,7 +105,8 @@ a key is a symbol, e.g., `a', `\\1', `f2', etc., or a list, e.g.,
#'viper-end-mapping-kbd-macro)
(define-key viper-emacs-intercept-map "\C-x)"
#'viper-end-mapping-kbd-macro)
- (message "Mapping %S in %s state. Type macro definition followed by `C-x )'"
+ (message (substitute-command-keys "Mapping %S in %s state. \
+Type macro definition followed by \\[kmacro-end-macro]")
(viper-display-macro macro-name)
(if ins "Insert" "Vi")))
))
@@ -886,8 +887,9 @@ mistakes in macro names to be passed to this function is to use
(if (get-register reg)
(if (y-or-n-p "Register contains data. Overwrite? ")
()
- (error
- "Macro not saved in register. Can still be invoked via `C-x e'")))
+ (error
+ (substitute-command-keys
+ "Macro not saved in register. Can still be invoked via \\[kmacro-end-and-call-macro]"))))
(set-register reg last-kbd-macro))
(defun viper-register-macro (count)
diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el
index 7581ece2142..1a90cab7674 100644
--- a/lisp/emulation/viper-mous.el
+++ b/lisp/emulation/viper-mous.el
@@ -62,8 +62,8 @@ or a triple-click."
;; time interval in millisecond within which successive clicks are
;; considered related
(defcustom viper-multiclick-timeout (if (viper-window-display-p)
- double-click-time
- 500)
+ (mouse-double-click-time)
+ 500)
"Time interval in milliseconds for mouse clicks to be considered related."
:type 'integer)
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index b1c361145ca..be87d788e92 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -559,10 +559,10 @@ and improving upon much of it.
2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
do not cause Emacs to quit, except at user level 1 (for a novice).
3. ^X^C EXITS EMACS.
- 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat
- undo. Another `u' changes direction.
+ 4. Viper supports multiple undo: \\`u' will undo. Typing \\`.' will repeat
+ undo. Another \\`u' changes direction.
- 6. Emacs Meta key is `C-\\' (in all modes) or `\\ ESC' (in Vi command mode).
+ 6. Emacs Meta key is \\`C-\\' (in all modes) or \\`\\ ESC' (in Vi command mode).
On a window system, the best way is to use the Meta-key on your keyboard.
7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
something funny happens. This would abort the current editing command.
@@ -573,12 +573,12 @@ For more information on Viper:
b. Print Viper manual, found in ./etc/viper.dvi
c. Print the Quick Reference, found in ./etc/viperCard.dvi
-To submit a bug report or to contact the author, type :submitReport in Vi
+To submit a bug report or to contact the author, type \\`:submitReport' in Vi
command mode. To shoo Viper away and return to pure Emacs (horror!), type:
\\[viper-go-away]
-This startup message appears whenever you load Viper, unless you type `y' now."
+This startup message appears whenever you load Viper, unless you type \\`y' now."
))
(goto-char (point-min))
(if (y-or-n-p "Inhibit Viper startup message? ")
diff --git a/lisp/env.el b/lisp/env.el
index a630bf120f8..a35383a13b1 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -225,7 +225,7 @@ VARIABLES is a list of variable settings of the form (VAR VALUE),
where VAR is the name of the variable (a string) and VALUE
is its value (also a string).
-The previous values will be be restored upon exit."
+The previous values will be restored upon exit."
(declare (indent 1) (debug (sexp body)))
(unless (consp variables)
(error "Invalid VARIABLES: %s" variables))
diff --git a/lisp/epa-ks.el b/lisp/epa-ks.el
index 1078c209aeb..f41429f7734 100644
--- a/lisp/epa-ks.el
+++ b/lisp/epa-ks.el
@@ -338,4 +338,6 @@ enough, since keyservers have strict timeout settings."
(forward-line))
keys))
+(provide 'epa-ks)
+
;;; epa-ks.el ends here
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el
index 6170dcb6116..bb34ca72d6b 100644
--- a/lisp/epa-mail.el
+++ b/lisp/epa-mail.el
@@ -30,21 +30,19 @@
;;; Local Mode
-(defvar epa-mail-mode-map
- (let ((keymap (make-sparse-keymap)))
- (define-key keymap "\C-c\C-ed" 'epa-mail-decrypt)
- (define-key keymap "\C-c\C-ev" 'epa-mail-verify)
- (define-key keymap "\C-c\C-es" 'epa-mail-sign)
- (define-key keymap "\C-c\C-ee" 'epa-mail-encrypt)
- (define-key keymap "\C-c\C-ei" 'epa-mail-import-keys)
- (define-key keymap "\C-c\C-eo" 'epa-insert-keys)
- (define-key keymap "\C-c\C-e\C-d" 'epa-mail-decrypt)
- (define-key keymap "\C-c\C-e\C-v" 'epa-mail-verify)
- (define-key keymap "\C-c\C-e\C-s" 'epa-mail-sign)
- (define-key keymap "\C-c\C-e\C-e" 'epa-mail-encrypt)
- (define-key keymap "\C-c\C-e\C-i" 'epa-mail-import-keys)
- (define-key keymap "\C-c\C-e\C-o" 'epa-insert-keys)
- keymap))
+(defvar-keymap epa-mail-mode-map
+ "C-c C-e d" #'epa-mail-decrypt
+ "C-c C-e v" #'epa-mail-verify
+ "C-c C-e s" #'epa-mail-sign
+ "C-c C-e e" #'epa-mail-encrypt
+ "C-c C-e i" #'epa-mail-import-keys
+ "C-c C-e o" #'epa-insert-keys
+ "C-c C-e C-d" #'epa-mail-decrypt
+ "C-c C-e C-v" #'epa-mail-verify
+ "C-c C-e C-s" #'epa-mail-sign
+ "C-c C-e C-e" #'epa-mail-encrypt
+ "C-c C-e C-i" #'epa-mail-import-keys
+ "C-c C-e C-o" #'epa-insert-keys)
(defvar epa-mail-mode-hook nil)
(defvar epa-mail-mode-on-hook nil)
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
index 979f93f693c..8d970bd6b96 100644
--- a/lisp/erc/erc-autoaway.el
+++ b/lisp/erc/erc-autoaway.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcAutoAway
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index d54e92011b5..bc7a7d14dc2 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -4,7 +4,7 @@
;; Filename: erc-backend.el
;; Author: Lawrence Mitchell <wence@gmx.li>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Created: 2004-05-7
;; Keywords: comm, IRC, chat, client, internet
@@ -102,7 +102,6 @@
;; There's a fairly strong mutual dependency between erc.el and erc-backend.el.
;; Luckily, erc.el does not need erc-backend.el for macroexpansion whereas the
;; reverse is true:
-(provide 'erc-backend)
(require 'erc)
;;;; Variables and options
@@ -124,6 +123,14 @@
"Nickname on the current server.
Use `erc-current-nick' to access this.")
+(defvar-local erc-session-user-full-name nil
+ "Real name used for the current session.
+Sent as the last argument to the USER command.")
+
+(defvar-local erc-session-username nil
+ "Username used for the current session.
+Sent as the first argument of the USER command.")
+
;;; Server attributes
(defvar-local erc-server-process nil
@@ -178,21 +185,27 @@ SILENCE=10 - supports the SILENCE command, maximum allowed number of entries
TOPICLEN=160 - maximum allowed topic length
WALLCHOPS - supports sending messages to all operators in a channel")
+(defvar-local erc--isupport-params nil
+ "Hash map of \"ISUPPORT\" params.
+Keys are symbols. Values are lists of zero or more strings with hex
+escapes removed.")
+
;;; Server and connection state
(defvar erc-server-ping-timer-alist nil
"Mapping of server buffers to their specific ping timer.")
(defvar-local erc-server-connected nil
- "Non-nil if the current buffer has been used by ERC to establish
-an IRC connection.
-
-If you wish to determine whether an IRC connection is currently
-active, use the `erc-server-process-alive' function instead.")
+ "Non-nil if the current buffer belongs to an active IRC connection.
+To determine whether an underlying transport is connected, use the
+function `erc-server-process-alive' instead.")
(defvar-local erc-server-reconnect-count 0
"Number of times we have failed to reconnect to the current server.")
+(defvar-local erc--server-last-reconnect-count 0
+ "Snapshot of reconnect count when the connection was established.")
+
(defvar-local erc-server-quitting nil
"Non-nil if the user requests a quit.")
@@ -315,8 +328,7 @@ This will only be consulted if the coding system in
:version "24.1"
:type '(repeat coding-system))
-(defcustom erc-server-coding-system (if (and (fboundp 'coding-system-p)
- (coding-system-p 'undecided)
+(defcustom erc-server-coding-system (if (and (coding-system-p 'undecided)
(coding-system-p 'utf-8))
'(utf-8 . undecided)
nil)
@@ -464,7 +476,7 @@ If POS is out of range, the value is nil."
(defun erc-bounds-of-word-at-point ()
"Return the bounds of word at point, or nil if we're not at a word.
If no `subword-mode' is active, then this is
-\(bounds-of-thing-at-point 'word)."
+\(bounds-of-thing-at-point \\='word)."
(if (or (erc-word-at-arg-p (point))
(erc-word-at-arg-p (1- (point))))
(save-excursion
@@ -536,6 +548,7 @@ TLS (see `erc-session-client-certificate' for more details)."
(error "Connection attempt failed"))
;; Misc server variables
(with-current-buffer buffer
+ (setq erc-server-filter-data nil)
(setq erc-server-process process)
(setq erc-server-quitting nil)
(setq erc-server-reconnecting nil
@@ -585,7 +598,13 @@ Make sure you are in an ERC buffer when running this."
(let ((erc-server-connect-function (or erc-session-connector
#'erc-open-network-stream)))
(erc-open erc-session-server erc-session-port erc-server-current-nick
- erc-session-user-full-name t erc-session-password)))))
+ erc-session-user-full-name t erc-session-password
+ nil nil nil erc-session-client-certificate
+ erc-session-username
+ (erc-networks--id-given erc-networks--id))
+ (unless (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ (cl-assert (not (eq buffer (current-buffer)))))))))
(defun erc-server-delayed-reconnect (buffer)
(if (buffer-live-p buffer)
@@ -696,6 +715,39 @@ Conditionally try to reconnect and take appropriate action."
;; unexpected disconnect
(erc-process-sentinel-2 event buffer))))
+(defun erc--unhide-prompt ()
+ (remove-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert t)
+ (when (and (marker-position erc-insert-marker)
+ (marker-position erc-input-marker))
+ (with-silent-modifications
+ (remove-text-properties erc-insert-marker erc-input-marker
+ '(display nil)))))
+
+(defun erc--unhide-prompt-on-self-insert ()
+ (when (and (eq this-command #'self-insert-command)
+ (or (eobp) (= (point) erc-input-marker)))
+ (erc--unhide-prompt)))
+
+(defun erc--hide-prompt (proc)
+ (erc-with-all-buffers-of-server
+ proc nil ; sorta wish this was indent 2
+ (when (and erc-hide-prompt
+ (or (eq erc-hide-prompt t)
+ ;; FIXME use `erc--target' after bug#48598
+ (memq (if (erc-default-target)
+ (if (erc-channel-p (car erc-default-recipients))
+ 'channel
+ 'query)
+ 'server)
+ erc-hide-prompt))
+ (marker-position erc-insert-marker)
+ (marker-position erc-input-marker)
+ (get-text-property erc-insert-marker 'erc-prompt))
+ (with-silent-modifications
+ (add-text-properties erc-insert-marker (1- erc-input-marker)
+ `(display ,erc-prompt-hidden)))
+ (add-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert 0 t))))
+
(defun erc-process-sentinel (cproc event)
"Sentinel function for ERC process."
(let ((buf (process-buffer cproc)))
@@ -718,11 +770,8 @@ Conditionally try to reconnect and take appropriate action."
(dolist (buf (erc-buffer-filter (lambda () (boundp 'erc-channel-users)) cproc))
(with-current-buffer buf
(setq erc-channel-users (make-hash-table :test 'equal))))
- ;; Remove the prompt
- (goto-char (or (marker-position erc-input-marker) (point-max)))
- (forward-line 0)
- (erc-remove-text-properties-region (point) (point-max))
- (delete-region (point) (point-max))
+ ;; Hide the prompt
+ (erc--hide-prompt cproc)
;; Decide what to do with the buffer
;; Restart if disconnected
(erc-process-sentinel-1 event buf))))))
@@ -773,11 +822,12 @@ Use DISPLAY-FN to show the results."
(erc-split-line text)))
;; From Circe, with modifications
-(defun erc-server-send (string &optional forcep target)
+(defun erc-server-send (string &optional force target)
"Send STRING to the current server.
-If FORCEP is non-nil, no flood protection is done - the string is
-sent directly. This might cause the messages to arrive in a wrong
-order.
+When FORCE is non-nil, bypass flood protection so that STRING is
+sent directly without modifying the queue. When FORCE is the
+symbol `no-penalty', exempt this round from accumulating a
+timeout penalty.
If TARGET is specified, look up encoding information for that
channel in `erc-encoding-coding-alist' or
@@ -793,11 +843,11 @@ protection algorithm."
(if (erc-server-process-alive)
(erc-with-server-buffer
(let ((str (concat string "\r\n")))
- (if forcep
+ (if force
(progn
- (setq erc-server-flood-last-message
- (+ erc-server-flood-penalty
- erc-server-flood-last-message))
+ (unless (eq force 'no-penalty)
+ (cl-incf erc-server-flood-last-message
+ erc-server-flood-penalty))
(erc-log-irc-protocol str 'outbound)
(condition-case nil
(progn
@@ -1192,7 +1242,7 @@ Would expand to:
aliases))
(let* ((hook-name (intern (format "erc-server-%s-functions" name)))
(fn-name (intern (format "erc-server-%s" name)))
- (hook-doc (format-message "\
+ (hook-doc (format "\
%sHook called upon receiving a %%s server response.
Each function is called with two arguments, the process associated
with the response and the parsed response. If the function returns
@@ -1203,7 +1253,7 @@ See also `%s'."
(concat extra-var-doc "\n\n")
"")
fn-name))
- (fn-doc (format-message "\
+ (fn-doc (format "\
%sHandler for a %s server response.
PROC is the server process which returned the response.
PARSED is the actual response as an `erc-response' struct.
@@ -1284,14 +1334,11 @@ add things to `%s' instead."
(let* ((str (cond
;; If I have joined a channel
((erc-current-nick-p nick)
- (setq buffer (erc-open erc-session-server erc-session-port
- nick erc-session-user-full-name
- nil nil
- (list chnl) chnl
- erc-server-process))
- (when buffer
+ (when (setq buffer (erc--open-target chnl))
(set-buffer buffer)
- (erc-add-default-channel chnl)
+ (with-suppressed-warnings
+ ((obsolete erc-add-default-channel))
+ (erc-add-default-channel chnl))
(erc-server-send (format "MODE %s" chnl)))
(erc-with-buffer (chnl proc)
(erc-channel-begin-receiving-names))
@@ -1328,7 +1375,8 @@ add things to `%s' instead."
(erc-with-buffer
(buffer)
(erc-remove-channel-users))
- (erc-delete-default-channel ch buffer)
+ (with-suppressed-warnings ((obsolete erc-delete-default-channel))
+ (erc-delete-default-channel ch buffer))
(erc-update-mode-line buffer))
((string= nick (erc-current-nick))
(erc-display-message
@@ -1376,19 +1424,27 @@ add things to `%s' instead."
;; sent to the correct nick. also add to bufs, since the user will want
;; to see the nick change in the query, and if it's a newly begun query,
;; erc-channel-users won't contain it
- (erc-buffer-filter
- (lambda ()
- (when (equal (erc-default-target) nick)
- (setq erc-default-recipients
- (cons nn (cdr erc-default-recipients)))
- (rename-buffer nn t) ; bug#12002
- (erc-update-mode-line)
- (cl-pushnew (current-buffer) bufs))))
+ ;;
+ ;; Possibly still relevant: bug#12002
+ (when-let ((buf (erc-get-buffer nick erc-server-process))
+ (tgt (erc--target-from-string nn)))
+ (with-current-buffer buf
+ (setq erc-default-recipients (cons nn (cdr erc-default-recipients))
+ erc--target tgt))
+ (with-current-buffer (erc-get-buffer-create erc-session-server
+ erc-session-port nil tgt
+ (erc-networks--id-given
+ erc-networks--id))
+ ;; Current buffer is among bufs
+ (erc-update-mode-line)))
(erc-update-user-nick nick nn host nil nil login)
(cond
((string= nick (erc-current-nick))
(cl-pushnew (erc-server-buffer) bufs)
(erc-set-current-nick nn)
+ ;; Rename session, possibly rename server buf and all targets
+ (when (erc-network)
+ (erc-networks--id-reload erc-networks--id proc parsed))
(erc-update-mode-line)
(setq erc-nick-change-attempt-count 0)
(setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
@@ -1417,7 +1473,8 @@ add things to `%s' instead."
(erc-with-buffer
(buffer)
(erc-remove-channel-users))
- (erc-delete-default-channel chnl buffer)
+ (with-suppressed-warnings ((obsolete erc-delete-default-channel))
+ (erc-delete-default-channel chnl buffer))
(erc-update-mode-line buffer)
(when erc-kill-buffer-on-part
(kill-buffer buffer))))))
@@ -1427,7 +1484,7 @@ add things to `%s' instead."
(let ((pinger (car (erc-response.command-args parsed))))
(erc-log (format "PING: %s" pinger))
;; ping response to the server MUST be forced, or you can lose big
- (erc-server-send (format "PONG :%s" pinger) t)
+ (erc-server-send (format "PONG :%s" pinger) 'no-penalty)
(when erc-verbose-server-ping
(erc-display-message
parsed 'error proc
@@ -1468,8 +1525,16 @@ add things to `%s' instead."
fnick)
(setf (erc-response.contents parsed) msg)
(setq buffer (erc-get-buffer (if privp nick tgt) proc))
+ ;; Even worth checking for empty target here? (invalid anyway)
+ (unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0)))
+ (if (and privp msgp (not (erc-is-message-ctcp-and-not-action-p msg)))
+ (when erc-auto-query
+ (let ((erc-join-buffer erc-auto-query))
+ (setq buffer (erc--open-target nick))))
+ (setq buffer (erc--open-target tgt))))
(when buffer
(with-current-buffer buffer
+ (when privp (erc--unhide-prompt))
;; update the chat partner info. Add to the list if private
;; message. We will accumulate private identities indefinitely
;; at this point.
@@ -1502,13 +1567,7 @@ add things to `%s' instead."
s parsed buffer nick)
(run-hook-with-args-until-success
'erc-echo-notice-hook s parsed buffer nick))
- (erc-display-message parsed nil buffer s)))
- (when (string= cmd "PRIVMSG")
- (erc-auto-query proc parsed))))))
-
-;; FIXME: need clean way of specifying extra hooks in
-;; define-erc-response-handler.
-(add-hook 'erc-server-PRIVMSG-functions #'erc-auto-query)
+ (erc-display-message parsed nil buffer s)))))))
(define-erc-response-handler (QUIT)
"Another user has quit IRC." nil
@@ -1581,6 +1640,70 @@ Then display the welcome message."
?U (nth 3 (erc-response.command-args parsed))
?C (nth 4 (erc-response.command-args parsed)))))
+(defun erc--parse-isupport-value (value)
+ "Return list of unescaped components from an \"ISUPPORT\" VALUE."
+ ;; https://tools.ietf.org/html/draft-brocklesby-irc-isupport-03#section-2
+ ;;
+ ;; > The server SHOULD send "X", not "X="; this is the normalised form.
+ ;;
+ ;; Note: for now, assume the server will only send non-empty values,
+ ;; possibly with printable ASCII escapes. Though in practice, the
+ ;; only two escapes we're likely to see are backslash and space,
+ ;; meaning the pattern is too liberal.
+ (let (case-fold-search)
+ (mapcar
+ (lambda (v)
+ (let ((start 0)
+ m
+ c)
+ (while (and (< start (length v))
+ (string-match "[\\]x[0-9A-F][0-9A-F]" v start))
+ (setq m (substring v (+ 2 (match-beginning 0)) (match-end 0))
+ c (string-to-number m 16))
+ (if (<= ?\ c ?~)
+ (setq v (concat (substring v 0 (match-beginning 0))
+ (string c)
+ (substring v (match-end 0)))
+ start (- (match-end 0) 3))
+ (setq start (match-end 0))))
+ v))
+ (if (if (>= emacs-major-version 28)
+ (string-search "," value)
+ (string-match-p "," value))
+ (split-string value ",")
+ (list value)))))
+
+(defmacro erc--with-memoization (table &rest forms)
+ "Adapter to be migrated to erc-compat."
+ (declare (indent defun))
+ `(cond
+ ((fboundp 'with-memoization)
+ (with-memoization ,table ,@forms)) ; 29.1
+ ((fboundp 'cl--generic-with-memoization)
+ (cl--generic-with-memoization ,table ,@forms))
+ (t ,@forms)))
+
+(defun erc--get-isupport-entry (key &optional single)
+ "Return an item for \"ISUPPORT\" token KEY, a symbol.
+When a lookup fails return nil. Otherwise return a list whose
+CAR is KEY and whose CDR is zero or more strings. With SINGLE,
+just return the first value, if any. The latter is potentially
+ambiguous and only useful for tokens supporting a single
+primitive value."
+ (if-let* ((table (or erc--isupport-params
+ (erc-with-server-buffer erc--isupport-params)))
+ (value (erc--with-memoization (gethash key table)
+ (when-let ((v (assoc (symbol-name key)
+ erc-server-parameters)))
+ (if (cdr v)
+ (erc--parse-isupport-value (cdr v))
+ '--empty--)))))
+ (pcase value
+ ('--empty-- (unless single (list key)))
+ (`(,head . ,_) (if single head (cons key value))))
+ (when table
+ (remhash key table))))
+
(define-erc-response-handler (005)
"Set the variable `erc-server-parameters' and display the received message.
@@ -1592,21 +1715,25 @@ certain commands are accepted and more. See documentation for
A server may send more than one 005 message."
nil
- (let ((line (mapconcat #'identity
- (setf (erc-response.command-args parsed)
- (cdr (erc-response.command-args parsed)))
- " ")))
- (while (erc-response.command-args parsed)
- (let ((section (pop (erc-response.command-args parsed))))
- ;; fill erc-server-parameters
- (when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\([A-Z]+\\)$"
+ (unless erc--isupport-params
+ (setq erc--isupport-params (make-hash-table)))
+ (let* ((args (cdr (erc-response.command-args parsed)))
+ (line (string-join args " ")))
+ (while args
+ (let ((section (pop args))
+ key
+ value
+ negated)
+ (when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\(-\\)?\\([A-Z]+\\)$"
section)
- (add-to-list 'erc-server-parameters
- `(,(or (match-string 1 section)
- (match-string 3 section))
- .
- ,(match-string 2 section))))))
- (erc-display-message parsed 'notice proc line)))
+ (setq key (or (match-string 1 section) (match-string 4 section))
+ value (match-string 2 section)
+ negated (and (match-string 3 section) '-))
+ (setf (alist-get key erc-server-parameters '- 'remove #'equal)
+ (or value negated))
+ (remhash (intern key) erc--isupport-params))))
+ (erc-display-message parsed 'notice proc line)
+ nil))
(define-erc-response-handler (221)
"Display the current user modes." nil
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 680de6d5aab..bccf0e6f1f5 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -3,7 +3,7 @@
;; Copyright (C) 1996-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, irc, button, url, regexp
;; URL: https://www.emacswiki.org/emacs/ErcButton
@@ -71,7 +71,7 @@
"Face used for highlighting buttons in ERC buffers.
A button is a piece of text that you can activate by pressing
-`RET' or `mouse-2' above it. See also `erc-button-keymap'."
+\\`RET' or `mouse-2' above it. See also `erc-button-keymap'."
:type 'face
:group 'erc-faces)
@@ -125,7 +125,7 @@ longer than `erc-fill-column'."
;; a button, it makes no sense to optimize performance by
;; bytecompiling lambdas in this alist. On the other hand, it makes
;; things hard to maintain.
- '(('nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
+ '((nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
(erc-button-url-regexp 0 t browse-url-button-open-url 0)
("<URL: *\\([^<> ]+\\) *>" 0 t browse-url-button-open-url 1)
;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
@@ -158,12 +158,12 @@ REGEXP is the string matching text around the button or a symbol
strings, or an alist with the strings in the car. Note that
entries in lists or alists are considered to be nicks or other
complete words. Therefore they are enclosed in \\< and \\>
- while searching. REGEXP can also be the quoted symbol
- \\='nicknames, which matches the nickname of any user on the
+ while searching. REGEXP can also be the symbol
+ `nicknames', which matches the nickname of any user on the
current server.
BUTTON is the number of the regexp grouping actually matching the
- button. This is ignored if REGEXP is \\='nicknames.
+ button. This is ignored if REGEXP is `nicknames'.
FORM is a Lisp expression which must eval to true for the button to
be added.
@@ -174,17 +174,15 @@ CALLBACK is the function to call when the user push this button.
PAR is a number of a regexp grouping whose text will be passed to
CALLBACK. There can be several PAR arguments. If REGEXP is
- \\='nicknames, these are ignored, and CALLBACK will be called with
+ `nicknames', these are ignored, and CALLBACK will be called with
the nickname matched as the argument."
- :version "24.1" ; remove finger (bug#4443)
+ :version "29.1"
:type '(repeat
(list :tag "Button"
(choice :tag "Matches"
regexp
(variable :tag "Variable containing regexp")
- ;; FIXME It really does mean 'nicknames
- ;; rather than just nicknames.
- (const :tag "Nicknames" 'nicknames))
+ (const :tag "Nicknames" nicknames))
(integer :tag "Number of the regexp section that matches")
(choice :tag "When to buttonize"
(const :tag "Always" t)
@@ -256,7 +254,9 @@ specified by `erc-button-alist'."
regexp)
(erc-button-remove-old-buttons)
(dolist (entry alist)
- (if (equal (car entry) (quote (quote nicknames)))
+ (if (or (eq (car entry) 'nicknames)
+ ;; Old form retained for backward compatibility.
+ (equal (car entry) (quote 'nicknames)))
(erc-button-add-nickname-buttons entry)
(progn
(setq regexp (or (and (stringp (car entry)) (car entry))
diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el
index 7b7773d5e13..c590b45fd21 100644
--- a/lisp/erc/erc-capab.el
+++ b/lisp/erc/erc-capab.el
@@ -2,9 +2,9 @@
;; Copyright (C) 2006-2022 Free Software Foundation, Inc.
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
-; This file is part of GNU Emacs.
+;; 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
@@ -137,7 +137,7 @@ These arguments are sent to this function when called as a hook in
;; could possibly check for '("IRCD" . "dancer") in
;; `erc-server-parameters' instead of looking for a specific name
;; in `erc-server-version'
- (assoc "CAPAB" erc-server-parameters))
+ (erc--get-isupport-entry 'CAPAB))
(erc-log "Sending CAPAB IDENTIFY-MSG and IDENTIFY-CTCP")
(erc-server-send "CAPAB IDENTIFY-MSG")
(erc-server-send "CAPAB IDENTIFY-CTCP")
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index 00addde2753..16cfb15a5ae 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2003, 2005-2022 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ERC
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 9654cab6e57..d0e1848e0eb 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -5,7 +5,7 @@
;; Author: Ben A. Mesander <ben@gnu.ai.mit.edu>
;; Noah Friedman <friedman@prep.ai.mit.edu>
;; Per Persson <pp@sno.pp.se>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; Created: 1994-01-23
@@ -43,7 +43,7 @@
;; /dcc chat nick - Either accept pending chat offer from nick, or offer
;; DCC chat to nick
;; /dcc close type [nick] - Close DCC connection (SEND/GET/CHAT) with nick
-;; /dcc get nick [file] - Accept DCC offer from nick
+;; /dcc get [-t][-s] nick [file] - Accept DCC offer from nick
;; /dcc list - List all DCC offers/connections
;; /dcc send nick file - Offer DCC SEND to nick
@@ -105,7 +105,11 @@ Looks like:
:file - for outgoing sends, the full path to the file. For incoming sends,
the suggested filename or vetted filename
- :size - size of the file, may be nil on incoming DCCs")
+ :size - size of the file, may be nil on incoming DCCs
+
+ :secure - optional item indicating sender support for TLS
+
+ :turbo - optional item indicating sender support for TSEND")
(defun erc-dcc-list-add (type nick peer parent &rest args)
"Add a new entry of type TYPE to `erc-dcc-list' and return it."
@@ -119,12 +123,13 @@ Looks like:
;; more: the entry data from erc-dcc-list for this particular process.
(defvar erc-dcc-connect-function 'erc-dcc-open-network-stream)
-(defun erc-dcc-open-network-stream (procname buffer addr port _entry)
+(defun erc-dcc-open-network-stream (procname buffer addr port entry)
;; FIXME: Time to try activating this again!?
(if nil; (fboundp 'open-network-stream-nowait) ;; this currently crashes
;; cvs emacs
(open-network-stream-nowait procname buffer addr port)
- (open-network-stream procname buffer addr port)))
+ (open-network-stream procname buffer addr port
+ :type (and (plist-get entry :secure) 'tls))))
(erc-define-catalog
'english
@@ -144,13 +149,14 @@ Looks like:
(dcc-get-bytes-received . "DCC: %f: %b bytes received")
(dcc-get-complete
. "DCC: file %f transfer complete (%s bytes in %t seconds)")
+ (dcc-get-failed . "DCC: file %f transfer failed at %s of %v in %t seconds")
(dcc-get-cmd-aborted . "DCC: Aborted getting %f from %n")
(dcc-get-file-too-long
. "DCC: %f: File longer than sender claimed; aborting transfer")
(dcc-get-notfound . "DCC: %n hasn't offered %f for DCC transfer")
- (dcc-list-head . "DCC: From Type Active Size Filename")
- (dcc-list-line . "DCC: -------- ---- ------ -------------- --------")
- (dcc-list-item . "DCC: %-8n %-4t %-6a %-14s %f")
+ (dcc-list-head . "DCC: From Type Active Size Filename")
+ (dcc-list-line . "DCC: -------- ---- ------ ----------------- --------")
+ (dcc-list-item . "DCC: %-8n %-4t %-6a %-17s %f%u")
(dcc-list-end . "DCC: End of list.")
(dcc-malformed . "DCC: error: %n (%u@%h) sent malformed request: %q")
(dcc-privileged-port
@@ -195,7 +201,7 @@ compared with `erc-nick-equal-p' which is IRC case-insensitive."
(erc-extract-nick test)
(erc-extract-nick val)))
;; not a nick
- (eq test val)
+ (equal test val)
(setq cont nil))))
(if cont
(setq result elt)
@@ -385,7 +391,7 @@ the accepted connection."
(defcustom erc-dcc-get-default-directory nil
"Default directory for incoming DCC file transfers.
If this is nil, then the current value of `default-directory' is used."
- :type '(choice (const nil :tag "Default directory") directory))
+ :type '(choice (const :value nil :tag "Default directory") directory))
;;;###autoload
(defun erc-cmd-DCC (cmd &rest args)
@@ -505,8 +511,12 @@ At least one of TYPE and NICK must be provided."
FILE is the filename. If FILE is split into multiple arguments,
re-join the arguments, separated by a space.
PROC is the server process."
- (setq file (and file (mapconcat #'identity file " ")))
- (let* ((elt (erc-dcc-member :nick nick :type 'GET))
+ (let* ((args (seq-group-by (lambda (s) (eq ?- (aref s 0))) (cons nick file)))
+ (flags (prog1 (cdr (assq t args))
+ (setq args (cdr (assq nil args))
+ nick (pop args)
+ file (and args (mapconcat #'identity args " ")))))
+ (elt (erc-dcc-member :nick nick :type 'GET :file file))
(filename (or file (plist-get elt :file) "unknown")))
(if elt
(let* ((file (read-file-name
@@ -526,7 +536,13 @@ PROC is the server process."
'dcc-get-cmd-aborted
?n nick ?f filename)))
(t
- (erc-dcc-get-file elt file proc))))
+ (erc-dcc-get-file elt file proc)))
+ (when (member "-s" flags)
+ (setq erc-dcc-list (cons (plist-put elt :secure t)
+ (delq elt erc-dcc-list))))
+ (when (member "-t" flags)
+ (setq erc-dcc-list (cons (plist-put elt :turbo t)
+ (delq elt erc-dcc-list)))))
(erc-display-message
nil '(notice error) 'active
'dcc-get-notfound ?n nick ?f filename))))
@@ -564,6 +580,7 @@ It lists the current state of `erc-dcc-list' in an easy to read manner."
(process-status (plist-get elt :peer))
"no")
?s (concat size
+ ;; FIXME consider uniquified names, e.g., foo.bin<2>
(if (and (eq 'GET (plist-get elt :type))
(plist-member elt :file)
(buffer-live-p (get-buffer (plist-get elt :file)))
@@ -575,7 +592,12 @@ It lists the current state of `erc-dcc-list' in an easy to read manner."
(format " (%d%%)"
(floor (* 100.0 byte-count)
(plist-get elt :size))))))
- ?f (or (and (plist-member elt :file) (plist-get elt :file)) "")))
+ ?f (or (and (plist-member elt :file) (plist-get elt :file)) "")
+ ?u (if-let* ((flags (concat (and (plist-get elt :turbo) "t")
+ (and (plist-get elt :secure) "s")))
+ ((not (string-empty-p flags))))
+ (concat " (" flags ")")
+ "")))
(erc-display-message
nil 'notice 'active
'dcc-list-end)
@@ -602,6 +624,10 @@ separated by a space."
(defvar erc-dcc-query-handler-alist
'(("SEND" . erc-dcc-handle-ctcp-send)
+ ("TSEND" . erc-dcc-handle-ctcp-send)
+ ("SSEND" . erc-dcc-handle-ctcp-send)
+ ("TSSEND" . erc-dcc-handle-ctcp-send)
+ ("STSEND" . erc-dcc-handle-ctcp-send)
("CHAT" . erc-dcc-handle-ctcp-chat)))
;;;###autoload
@@ -620,12 +646,16 @@ that subcommand."
?q query ?n nick ?u login ?h host))))
(defconst erc-dcc-ctcp-query-send-regexp
- (concat "^DCC SEND \\(?:"
+ (rx bot "DCC " (group-n 6 (: (** 0 2 (any "TS")) "SEND")) " "
;; Following part matches either filename without spaces
;; or filename enclosed in double quotes with any number
;; of escaped double quotes inside.
- "\"\\(\\(?:\\\\\"\\|[^\"\\]\\)+\\)\"\\|\\([^ ]+\\)"
- "\\) \\([0-9]+\\) \\([0-9]+\\) *\\([0-9]*\\)"))
+ (: (or (: ?\" (group-n 1 (+ (or (: ?\\ ?\") (not (any ?\" ?\\))))) ?\")
+ (group-n 2 (+ (not " ")))))
+ (: " " (group-n 3 (+ digit))
+ " " (group-n 4 (+ digit))
+ (* " ") (group-n 5 (* digit)))
+ eot))
(define-inline erc-dcc-unquote-filename (filename)
(inline-quote
@@ -650,12 +680,14 @@ It extracts the information about the dcc request and adds it to
'dcc-request-bogus
?r "SEND" ?n nick ?u login ?h host))
((string-match erc-dcc-ctcp-query-send-regexp query)
- (let ((filename
- (or (match-string 2 query)
- (erc-dcc-unquote-filename (match-string 1 query))))
- (ip (erc-decimal-to-ip (match-string 3 query)))
- (port (match-string 4 query))
- (size (match-string 5 query)))
+ (let* ((filename (or (match-string 2 query)
+ (erc-dcc-unquote-filename (match-string 1 query))))
+ (ip (erc-decimal-to-ip (match-string 3 query)))
+ (port (match-string 4 query))
+ (size (match-string 5 query))
+ (sub (substring (match-string 6 query) 0 -4))
+ (secure (seq-contains-p sub ?S #'eq))
+ (turbo (seq-contains-p sub ?T #'eq)))
;; FIXME: a warning really should also be sent
;; if the ip address != the host the dcc sender is on.
(erc-display-message
@@ -672,7 +704,9 @@ It extracts the information about the dcc request and adds it to
'GET (format "%s!%s@%s" nick login host)
nil proc
:ip ip :port port :file filename
- :size (string-to-number size))
+ :size (string-to-number size)
+ :turbo (and turbo t)
+ :secure (and secure t))
(if (and (eq erc-dcc-send-request 'auto)
(erc-dcc-auto-mask-p (format "\"%s!%s@%s\"" nick login host)))
(erc-dcc-get-file (car erc-dcc-list) filename proc))))
@@ -768,7 +802,7 @@ the matching regexp, or nil if none found."
PROC is the process-object of the DCC connection. Returns the number of
bytes sent."
(let* ((elt (erc-dcc-member :peer proc))
- (confirmed-marker (plist-get elt :sent))
+ (confirmed-marker (plist-get elt :confirmed))
(sent-marker (plist-get elt :sent)))
(with-current-buffer (process-buffer proc)
(when erc-dcc-verbose
@@ -920,8 +954,7 @@ and making the connection."
(inhibit-file-name-operation 'write-region))
(write-region (point) (point) erc-dcc-file-name nil 'nomessage))
- (setq erc-server-process parent-proc
- erc-dcc-entry-data entry)
+ (setq erc-server-process parent-proc)
(setq erc-dcc-byte-count 0)
(setq proc
(funcall erc-dcc-connect-function
@@ -935,8 +968,8 @@ and making the connection."
(set-process-filter proc #'erc-dcc-get-filter)
(set-process-sentinel proc #'erc-dcc-get-sentinel)
- (setq entry (plist-put entry :start-time (erc-current-time)))
- (setq entry (plist-put entry :peer proc)))))
+ (setq erc-dcc-entry-data (plist-put (plist-put entry :peer proc)
+ :start-time (erc-current-time))))))
(defun erc-dcc-append-contents (buffer _file)
"Append the contents of BUFFER to FILE.
@@ -952,6 +985,16 @@ The contents of the BUFFER will then be erased."
(setq erc-dcc-byte-count (+ (buffer-size) erc-dcc-byte-count))
(erase-buffer))))
+;; If people really need this, we can convert it into a proper option.
+
+(defvar erc-dcc--X-send-final-turbo-ack nil
+ "Workaround for maverick turbo senders that only require a final ACK.
+The only known culprit is WeeChat, with its xfer.network.fast_send
+option, which is on by default. Leaving this set to nil and calling
+/DCC GET -t works just fine, but WeeChat sees it as a failure even
+though the file arrives in its entirety. Setting this to t may
+alleviate such problems.")
+
(defun erc-dcc-get-filter (proc str)
"This is the process filter for transfers from other clients to this one.
It reads incoming bytes from the network and stores them in the DCC
@@ -986,31 +1029,43 @@ rather than every 1024 byte block, but nobody seems to care."
'dcc-get-file-too-long
?f (file-name-nondirectory (buffer-name)))
(delete-process proc))
- (t
- (process-send-string
- proc (erc-pack-int received-bytes)))))))
-
+ ;; Some senders want us to hang up. Only observed w. TSEND.
+ ((and (plist-get erc-dcc-entry-data :turbo)
+ (= received-bytes (plist-get erc-dcc-entry-data :size)))
+ (when erc-dcc--X-send-final-turbo-ack
+ (process-send-string proc (erc-pack-int received-bytes)))
+ (delete-process proc))
+ ((not (or (plist-get erc-dcc-entry-data :turbo)
+ (process-get proc :reportingp)))
+ (process-put proc :reportingp t)
+ (process-send-string proc (erc-pack-int received-bytes))
+ (process-put proc :reportingp nil))))))
-(defun erc-dcc-get-sentinel (proc _event)
+(defun erc-dcc-get-sentinel (proc event)
"This is the process sentinel for CTCP DCC SEND connections.
It shuts down the connection and notifies the user that the
transfer is complete."
;; FIXME, we should look at EVENT, and also check size.
+ (unless (member event '("connection broken by remote peer\n"
+ "deleted\n"))
+ (lwarn 'erc :warning "Unexpected sentinel event %S for %s"
+ (string-trim-right event) proc))
(with-current-buffer (process-buffer proc)
(delete-process proc)
(setq erc-dcc-list (delete erc-dcc-entry-data erc-dcc-list))
(unless (= (point-min) (point-max))
(erc-dcc-append-contents (current-buffer) erc-dcc-file-name))
- (erc-display-message
- nil 'notice erc-server-process
- 'dcc-get-complete
- ?f erc-dcc-file-name
- ?s (number-to-string erc-dcc-byte-count)
- ?t (format "%.0f"
- (erc-time-diff (plist-get erc-dcc-entry-data :start-time)
- nil))))
- (kill-buffer (process-buffer proc))
- (delete-process proc))
+ (let ((done (= erc-dcc-byte-count (plist-get erc-dcc-entry-data :size))))
+ (erc-display-message
+ nil (if done 'notice '(notice error)) erc-server-process
+ (if done 'dcc-get-complete 'dcc-get-failed)
+ ?v (plist-get erc-dcc-entry-data :size)
+ ?f erc-dcc-file-name
+ ?s (number-to-string erc-dcc-byte-count)
+ ?t (format "%.0f"
+ (erc-time-diff (plist-get erc-dcc-entry-data :start-time)
+ nil))))
+ (kill-buffer)))
;;; CHAT handling
diff --git a/lisp/erc/erc-desktop-notifications.el b/lisp/erc/erc-desktop-notifications.el
index 8ece765ef0d..1897f53dc16 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
index 8f46a1c8dd1..958783f2394 100644
--- a/lisp/erc/erc-ezbounce.el
+++ b/lisp/erc/erc-ezbounce.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002, 2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index 492830c3e13..140e7fdfc61 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -4,7 +4,7 @@
;; Author: Andreas Fuchs <asf@void.at>
;; Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcFilling
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 9b9f19a0db3..8fef23945d4 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2001-2022 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Most code is taken verbatim from erc.el, see there for the original
;; authors.
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index f1184ff5eb2..417c0b898a7 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002, 2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index eab219f4c1e..5c0a2c1a481 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2003, 2006-2022 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index ea4f44b91c7..64a8f82b2a9 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2001-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; URL: https://www.emacswiki.org/emacs/ErcImenu
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index 175e83f3c90..b4044548e84 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, irc
;; URL: https://www.emacswiki.org/emacs/ErcAutoJoin
@@ -33,8 +33,6 @@
;;; Code:
(require 'erc)
-(require 'auth-source)
-(require 'erc-networks)
(defgroup erc-autojoin nil
"Enable autojoining."
@@ -57,11 +55,16 @@
Every element in the alist has the form (SERVER . CHANNELS).
SERVER is a regexp matching the server, and channels is the list
of channels to join. SERVER can also be a symbol, in which case
-it is matched against the value of `erc-network' instead of
+it's matched against a non-nil `:id' passed to `erc' or `erc-tls'
+when connecting or the value of the current `erc-network' instead of
`erc-server-announced-name' or `erc-session-server' (this can be
useful when connecting to an IRC proxy that relays several
networks under the same server).
+Note that for historical reasons, this option is mutated at runtime,
+which is regrettable but here to stay. Please double check the value
+before saving it to a `custom-file'.
+
If the channel(s) require channel keys for joining, the passwords
are found via auth-source. For instance, if you use ~/.authinfo
as your auth-source backend, then put something like the
@@ -123,33 +126,32 @@ This is called from a timer set up by `erc-autojoin-channels'."
(erc-autojoin-channels server nick))))
(defun erc-autojoin-server-match (candidate)
- "Match the current network or server against CANDIDATE.
-This should be a key from `erc-autojoin-channels-alist'."
- (or (eq candidate (erc-network))
- (and (stringp candidate)
- (string-match-p candidate
- (or erc-server-announced-name
- erc-session-server)))))
+ "Match the current network ID or server against CANDIDATE.
+CANDIDATE is a key from `erc-autojoin-channels-alist'. Return the
+matching entity, either a string or a non-nil symbol (in the case of a
+network or a network ID). Return nil on failure."
+ (if (symbolp candidate)
+ (eq (or (erc-networks--id-given erc-networks--id) (erc-network))
+ candidate)
+ (when (stringp candidate)
+ (string-match-p candidate (or erc-server-announced-name
+ erc-session-server)))))
+
+(defun erc-autojoin--join ()
+ ;; This is called in the server buffer
+ (pcase-dolist (`(,name . ,channels) erc-autojoin-channels-alist)
+ (when-let ((match (erc-autojoin-server-match name)))
+ (dolist (chan channels)
+ (let ((buf (erc-get-buffer chan erc-server-process)))
+ (unless (and buf (with-current-buffer buf
+ (erc--current-buffer-joined-p)))
+ (erc-server-join-channel nil chan)))))))
(defun erc-autojoin-after-ident (_network _nick)
"Autojoin channels in `erc-autojoin-channels-alist'.
This function is run from `erc-nickserv-identified-hook'."
- (if erc--autojoin-timer
- (setq erc--autojoin-timer
- (cancel-timer erc--autojoin-timer)))
(when (eq erc-autojoin-timing 'ident)
- (let ((server (or erc-session-server erc-server-announced-name))
- (joined (mapcar (lambda (buf)
- (with-current-buffer buf (erc-default-target)))
- (erc-channel-list erc-server-process))))
- ;; We may already be in these channels, e.g. because the
- ;; autojoin timer went off.
- (dolist (l erc-autojoin-channels-alist)
- (when (erc-autojoin-server-match (car l))
- (dolist (chan (cdr l))
- (unless (erc-member-ignore-case chan joined)
- (erc-server-join-channel server chan)))))))
- nil)
+ (erc-autojoin--join)))
(defun erc-autojoin-channels (server nick)
"Autojoin channels in `erc-autojoin-channels-alist'."
@@ -162,24 +164,7 @@ This function is run from `erc-nickserv-identified-hook'."
#'erc-autojoin-channels-delayed
server nick (current-buffer))))
;; `erc-autojoin-timing' is `connect':
- (let ((server (or erc-session-server erc-server-announced-name)))
- (dolist (l erc-autojoin-channels-alist)
- (when (erc-autojoin-server-match (car l))
- (dolist (chan (cdr l))
- (let ((buffer
- (car (erc-buffer-filter
- (lambda ()
- (let ((current (erc-default-target)))
- (and (stringp current)
- (erc-autojoin-server-match (car l))
- (string-equal (erc-downcase chan)
- (erc-downcase current)))))))))
- (when (or (not buffer)
- (not (with-current-buffer buffer
- (erc-server-process-alive))))
- (erc-server-join-channel server chan))))))))
- ;; Return nil to avoid stomping on any other hook funcs.
- nil)
+ (erc-autojoin--join)))
(defun erc-autojoin-current-server ()
"Compute the current server for lookup in `erc-autojoin-channels-alist'.
@@ -190,24 +175,29 @@ Respects `erc-autojoin-domain-only'."
(match-string 1 server)
server)))
+(defun erc-autojoin--mutate (proc parsed remove)
+ (when-let* ((nick (car (erc-parse-user (erc-response.sender parsed))))
+ ((erc-current-nick-p nick))
+ (chnl (car (erc-response.command-args parsed)))
+ (elem (or (and (erc--valid-local-channel-p chnl)
+ (regexp-quote erc-server-announced-name))
+ (erc-networks--id-given erc-networks--id)
+ (erc-network)
+ (with-current-buffer (process-buffer proc)
+ (erc-autojoin-current-server))))
+ (test (if (symbolp elem) #'eq #'equal)))
+ (if remove
+ (let ((cs (delete chnl (assoc-default elem erc-autojoin-channels-alist
+ test))))
+ (setf (alist-get elem erc-autojoin-channels-alist nil (null cs) test)
+ cs))
+ (cl-pushnew chnl
+ (alist-get elem erc-autojoin-channels-alist nil nil test)
+ :test #'equal))))
+
(defun erc-autojoin-add (proc parsed)
"Add the channel being joined to `erc-autojoin-channels-alist'."
- (let* ((chnl (erc-response.contents parsed))
- (nick (car (erc-parse-user (erc-response.sender parsed))))
- (server (with-current-buffer (process-buffer proc)
- (erc-autojoin-current-server))))
- (when (erc-current-nick-p nick)
- (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist)
- (assoc server erc-autojoin-channels-alist))))
- (if elem
- (unless (member chnl (cdr elem))
- (setcdr elem (cons chnl (cdr elem))))
- ;; This always keys on server, not network -- user can
- ;; override by simply adding a network to
- ;; `erc-autojoin-channels-alist'
- (setq erc-autojoin-channels-alist
- (cons (list server chnl)
- erc-autojoin-channels-alist))))))
+ (erc-autojoin--mutate proc parsed nil)
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)
@@ -216,18 +206,7 @@ Respects `erc-autojoin-domain-only'."
(defun erc-autojoin-remove (proc parsed)
"Remove the channel being left from `erc-autojoin-channels-alist'."
- (let* ((chnl (car (erc-response.command-args parsed)))
- (nick (car (erc-parse-user (erc-response.sender parsed))))
- (server (with-current-buffer (process-buffer proc)
- (erc-autojoin-current-server))))
- (when (erc-current-nick-p nick)
- (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist)
- (assoc server erc-autojoin-channels-alist))))
- (when elem
- (setcdr elem (delete chnl (cdr elem)))
- (unless (cdr elem)
- (setq erc-autojoin-channels-alist
- (delete elem erc-autojoin-channels-alist)))))))
+ (erc-autojoin--mutate proc parsed 'remove)
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
index 354203aa090..d059caf5a32 100644
--- a/lisp/erc/erc-lang.el
+++ b/lisp/erc/erc-lang.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002, 2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Old-Version: 1.0.0
;; URL: https://www.emacswiki.org/emacs/ErcLang
;; Keywords: comm
@@ -32,10 +32,8 @@
(require 'erc)
-;; FIXME: It's ISO 639-1, not ISO 638. ISO 638 is for paper, board and pulps.
-;; The Lisp variable should be renamed.
-
-(defvar iso-638-languages
+(define-obsolete-variable-alias 'iso-638-languages 'iso-639-1-languages "29.1")
+(defvar iso-639-1-languages
'(("aa" . "Afar")
("ab" . "Abkhazian")
("af" . "Afrikaans")
@@ -197,12 +195,12 @@ Normungsinstitut (ON), Postfach 130, A-1021 Vienna, Austria.")
(defun language (code)
"Return the language name for the ISO CODE."
(interactive (list (completing-read "ISO language code: "
- iso-638-languages)))
- (message "%s" (cdr (assoc code iso-638-languages))))
+ iso-639-1-languages)))
+ (message "%s" (cdr (assoc code iso-639-1-languages))))
(defun erc-cmd-LANG (language)
"Display the language name for the language code given by LANGUAGE."
- (let ((lang (cdr (assoc language iso-638-languages))))
+ (let ((lang (cdr (assoc language iso-639-1-languages))))
(erc-display-message
nil 'notice 'active
(or lang (concat language ": No such domain"))))
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index c7cd0ceba83..5266b680c38 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Old-Version: 0.1
;; URL: https://www.emacswiki.org/emacs/ErcList
;; Keywords: comm
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index 056701d6200..57093d3fc6c 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2003-2022 Free Software Foundation, Inc.
;; Author: Lawrence Mitchell <wence@gmx.li>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcLogging
;; Keywords: comm, IRC, chat, client, Internet, logging
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index aa78590539b..7c9174ff66a 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; URL: https://www.emacswiki.org/emacs/ErcMatch
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
index fd14d8b0ad8..455a7c3cd2f 100644
--- a/lisp/erc/erc-menu.el
+++ b/lisp/erc/erc-menu.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2001-2002, 2004-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, menu
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
index 30bb18344d7..17ed881b12b 100644
--- a/lisp/erc/erc-netsplit.el
+++ b/lisp/erc/erc-netsplit.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 9377e701c39..091b8aa92d7 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002, 2004-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
@@ -731,6 +731,466 @@ MATCHER is used to find a corresponding network to a server while
(defvar-local erc-network nil
"The name of the network you are connected to (a symbol).")
+
+;;;; Identifying session context
+
+;; This section is concerned with identifying and managing the
+;; relationship between an IRC connection and its unique identity on a
+;; given network (as seen by that network's nick-granting system).
+;; This relationship is quasi-permanent and transcends IRC connections
+;; and Emacs sessions. As of mid 2022, only nicknames matter, and
+;; whether a user is authenticated does not directly impact network
+;; identity from a client's perspective. However, ERC must be
+;; equipped to adapt should this ever change. And while a connection
+;; is normally associated with exactly one nick, some networks (or
+;; intermediaries) may allow multiple clients to control the same nick
+;; by combining instance activity into a single logical client. ERC
+;; must be limber enough to handle such situations.
+
+(defvar-local erc-networks--id nil
+ "Server-local instance of its namesake struct.
+Also shared among all target buffers for a given connection. See
+\\[describe-symbol] `erc-networks--id' for more.")
+
+(cl-defstruct erc-networks--id
+ "Persistent identifying info for a network presence.
+
+Here, \"presence\" refers to some local state representing a
+client's existence on a network. Some clients refer to this as a
+\"context\" or a \"net-id\". The management of this state
+involves tracking associated buffers and what they're displaying.
+Since a presence can outlast physical connections and survive
+changes in back-end transports (and even outlive Emacs sessions),
+its identity must be resilient.
+
+Essential to this notion of an enduring existence on a network is
+ensuring recovery from the loss of a server buffer. Thus, any
+useful identifier must be shared among server and target buffers
+to allow for reassociation. Beyond that, it must ideally be
+derivable from the same set of connection parameters. See the
+constructor `erc-networks--id-create' for more info."
+ (ts nil :type float :read-only t :documentation "Creation timestamp.")
+ (symbol nil :type symbol :documentation "ID as a symbol."))
+
+(cl-defstruct (erc-networks--id-fixed
+ (:include erc-networks--id)
+ (:constructor erc-networks--id-fixed-create
+ (given &aux (ts (float-time)) (symbol given)))))
+
+(cl-defstruct (erc-networks--id-qualifying
+ (:include erc-networks--id)
+ (:constructor erc-networks--id-qualifying-create
+ (&aux
+ (ts (float-time))
+ (parts (erc-networks--id-qualifying-init-parts))
+ (symbol (erc-networks--id-qualifying-init-symbol
+ parts))
+ (len 1))))
+ "A session context composed of hierarchical connection parameters.
+Two identifiers are considered equivalent when their non-empty
+`parts' slots compare equal. Related identifiers share a common
+prefix of `parts' taken from connection parameters (given or
+discovered). An identifier's unique `symbol', intended for
+display purposes, is created by concatenating the shortest common
+prefix among its relatives. For example, related presences [b a
+r d o] and [b a z a r] would have symbols b/a/r and b/a/z
+respectively. The separator is given by `erc-networks--id-sep'."
+ (parts nil :type sequence ; a vector of atoms
+ :documentation "Sequence of identifying components.")
+ (len 0 :type integer
+ :documentation "Length of active `parts' interval."))
+
+;; For now, please use this instead of `erc-networks--id-fixed-p'.
+(cl-defgeneric erc-networks--id-given (net-id)
+ "Return the preassigned identifier for a network presence, if any.
+This may have originated from an `:id' arg to entry-point commands
+`erc-tls' or `erc'.")
+
+(cl-defmethod erc-networks--id-given ((_ erc-networks--id))
+ nil)
+
+(cl-defmethod erc-networks--id-given ((nid erc-networks--id-fixed))
+ (erc-networks--id-symbol nid))
+
+(cl-generic-define-context-rewriter erc-obsolete-var (var spec)
+ `((with-suppressed-warnings ((obsolete ,var)) ,var) ,spec))
+
+;; As a catch-all, derive the symbol from the unquoted printed repr.
+(cl-defgeneric erc-networks--id-create (id)
+ "Invoke an appropriate constructor for an `erc-networks--id' object."
+ (erc-networks--id-fixed-create (intern (format "%s" id))))
+
+;; When a given ID is a symbol, trust it unequivocally.
+(cl-defmethod erc-networks--id-create ((id symbol))
+ (erc-networks--id-fixed-create id))
+
+;; Otherwise, use an adaptive name derived from network params.
+(cl-defmethod erc-networks--id-create ((_ null))
+ (erc-networks--id-qualifying-create))
+
+;; But honor an explicitly set `erc-rename-buffers' (compat).
+(cl-defmethod erc-networks--id-create
+ ((_ null) &context (erc-obsolete-var erc-rename-buffers null))
+ (erc-networks--id-fixed-create (intern (buffer-name))))
+
+;; But honor an explicitly set `erc-reuse-buffers' (compat).
+(cl-defmethod erc-networks--id-create
+ ((_ null) &context (erc-obsolete-var erc-reuse-buffers null))
+ (erc-networks--id-fixed-create (intern (buffer-name))))
+
+(cl-defmethod erc-networks--id-create
+ ((_ symbol) &context (erc-obsolete-var erc-reuse-buffers null))
+ (erc-networks--id-fixed-create (intern (buffer-name))))
+
+(cl-defgeneric erc-networks--id-on-connect (net-id)
+ "Update NET-ID `erc-networks--id' after connection params known.
+This is typically during or just after MOTD.")
+
+(cl-defmethod erc-networks--id-on-connect ((_ erc-networks--id))
+ nil)
+
+(cl-defmethod erc-networks--id-on-connect ((id erc-networks--id-qualifying))
+ (erc-networks--id-qualifying-update id (erc-networks--id-qualifying-create)))
+
+(cl-defgeneric erc-networks--id-equal-p (self other)
+ "Return non-nil when two network identities exhibit underlying equality.
+SELF and OTHER are `erc-networks--id' struct instances. This
+should normally be used only for ID recovery or merging, after
+which no two identities should be `equal' (timestamps aside) that
+aren't also `eq'.")
+
+(cl-defmethod erc-networks--id-equal-p ((self erc-networks--id)
+ (other erc-networks--id))
+ (eq self other))
+
+(cl-defmethod erc-networks--id-equal-p ((a erc-networks--id-fixed)
+ (b erc-networks--id-fixed))
+ (or (eq a b) (eq (erc-networks--id-symbol a) (erc-networks--id-symbol b))))
+
+(cl-defmethod erc-networks--id-equal-p ((a erc-networks--id-qualifying)
+ (b erc-networks--id-qualifying))
+ (or (eq a b) (equal (erc-networks--id-qualifying-parts a)
+ (erc-networks--id-qualifying-parts b))))
+
+;; ERASE-ME: if some future extension were to come along offering
+;; additional members, e.g., [Libera.Chat "bob" laptop], it'd likely
+;; be cleaner to create a new struct type descending from
+;; `erc-networks--id-qualifying' than to convert this function into a
+;; generic. However, the latter would be simpler because it'd just
+;; require something like &context (erc-v3-device erc-v3--device-t).
+
+(defun erc-networks--id-qualifying-init-parts ()
+ "Return opaque list of atoms to serve as canonical identifier."
+ (when-let ((network (erc-network))
+ (nick (erc-current-nick)))
+ (vector network (erc-downcase nick))))
+
+(defvar erc-networks--id-sep "/"
+ "Separator for joining `erc-networks--id-qualifying-parts' into a net ID.")
+
+(defun erc-networks--id-qualifying-init-symbol (elts &optional len)
+ "Return symbol appropriate for network context identified by ELTS.
+Use leading interval of length LEN as contributing components.
+Combine them with string separator `erc-networks--id-sep'."
+ (when elts
+ (unless len
+ (setq len 1))
+ (intern (mapconcat (lambda (s) (prin1-to-string s t))
+ (seq-subseq elts 0 len)
+ erc-networks--id-sep))))
+
+(defun erc-networks--id-qualifying-grow-id (nid)
+ "Grow NID by one component or return nil when at capacity."
+ (unless (= (length (erc-networks--id-qualifying-parts nid))
+ (erc-networks--id-qualifying-len nid))
+ (setf (erc-networks--id-symbol nid)
+ (erc-networks--id-qualifying-init-symbol
+ (erc-networks--id-qualifying-parts nid)
+ (cl-incf (erc-networks--id-qualifying-len nid))))))
+
+(defun erc-networks--id-qualifying-reset-id (nid)
+ "Restore NID to its initial state."
+ (setf (erc-networks--id-qualifying-len nid) 1
+ (erc-networks--id-symbol nid)
+ (erc-networks--id-qualifying-init-symbol
+ (erc-networks--id-qualifying-parts nid))))
+
+(defun erc-networks--id-qualifying-prefix-length (nid-a nid-b)
+ "Return length of common initial prefix of NID-A and NID-B.
+Return nil when no such sequence exists (instead of zero)."
+ (when-let* ((a (erc-networks--id-qualifying-parts nid-a))
+ (b (erc-networks--id-qualifying-parts nid-b))
+ (n (min (length a) (length b)))
+ ((> n 0))
+ ((equal (elt a 0) (elt b 0)))
+ (i 1))
+ (while (and (< i n)
+ (equal (elt a i)
+ (elt b i)))
+ (cl-incf i))
+ i))
+
+(defun erc-networks--id-qualifying-update (dest source &rest overrides)
+ "Update DEST from SOURCE in place.
+Copy slots into DEST from SOURCE and recompute ID. Both SOURCE
+and DEST must be `erc-networks--id' objects. OVERRIDES is an
+optional plist of SLOT VAL pairs."
+ (setf (erc-networks--id-qualifying-parts dest)
+ (or (plist-get overrides :parts)
+ (erc-networks--id-qualifying-parts source))
+ (erc-networks--id-qualifying-len dest)
+ (or (plist-get overrides :len)
+ (erc-networks--id-qualifying-len source))
+ (erc-networks--id-symbol dest)
+ (or (plist-get overrides :symbol)
+ (erc-networks--id-qualifying-init-symbol
+ (erc-networks--id-qualifying-parts dest)
+ (erc-networks--id-qualifying-len dest)))))
+
+(cl-defgeneric erc-networks--id-reload (_nid &optional _proc _parsed)
+ "Handle an update to the current network identity.
+If provided, PROC should be the current `erc-server-process' and
+PARSED the current `erc-response'. NID is an `erc-networks--id'
+object."
+ nil)
+
+(cl-defmethod erc-networks--id-reload ((nid erc-networks--id-qualifying)
+ &optional proc parsed)
+ "Refresh identity after an `erc-networks--id-qualifying-parts'update."
+ (erc-networks--id-qualifying-update nid (erc-networks--id-qualifying-create)
+ :len
+ (erc-networks--id-qualifying-len nid))
+ (erc-networks--rename-server-buffer (or proc erc-server-process) parsed)
+ (erc-networks--shrink-ids-and-buffer-names-any)
+ (erc-with-all-buffers-of-server
+ erc-server-process #'erc--default-target
+ (when-let* ((new-name (erc-networks--reconcile-buffer-names erc--target
+ nid))
+ ((not (equal (buffer-name) new-name))))
+ (rename-buffer new-name 'unique))))
+
+(cl-defgeneric erc-networks--id-ensure-comparable (self other)
+ "Take measures to ensure two net identities are in comparable states.")
+
+(cl-defmethod erc-networks--id-ensure-comparable ((_ erc-networks--id)
+ (_ erc-networks--id))
+ nil)
+
+(cl-defmethod erc-networks--id-ensure-comparable
+ ((nid erc-networks--id-qualifying) (other erc-networks--id-qualifying))
+ "Grow NID along with that of the current buffer.
+Rename the current buffer if its NID has grown."
+ (when-let ((n (erc-networks--id-qualifying-prefix-length other nid)))
+ (while (and (<= (erc-networks--id-qualifying-len nid) n)
+ (erc-networks--id-qualifying-grow-id nid)))
+ ;; Grow and rename a visited buffer and all its targets
+ (when (and (> (erc-networks--id-qualifying-len nid)
+ (erc-networks--id-qualifying-len other))
+ (erc-networks--id-qualifying-grow-id other))
+ ;; Rename NID's buffers using current ID
+ (erc-buffer-filter (lambda ()
+ (when (eq erc-networks--id other)
+ (erc-networks--maybe-update-buffer-name)))))))
+
+(defun erc-networks--id-sort-buffers (buffers)
+ "Return a list of target BUFFERS, newest to oldest."
+ (sort buffers
+ (lambda (a b)
+ (> (with-current-buffer a (erc-networks--id-ts erc-networks--id))
+ (with-current-buffer b (erc-networks--id-ts erc-networks--id))))))
+
+
+;;;; Buffer association
+
+(cl-defgeneric erc-networks--shrink-ids-and-buffer-names ()
+ nil) ; concrete default implementation for non-eliding IDs
+
+(defun erc-networks--refresh-buffer-names (identity &optional omit)
+ "Ensure all colliding buffers for network IDENTITY have suffixes.
+Then rename current buffer appropriately. Don't consider buffer OMIT
+when determining collisions."
+ (if (erc-networks--examine-targets identity erc--target
+ #'ignore
+ (lambda ()
+ (unless (or (not omit) (eq (current-buffer) omit))
+ (erc-networks--ensure-unique-target-buffer-name)
+ t)))
+ (erc-networks--ensure-unique-target-buffer-name)
+ (rename-buffer (erc--target-string erc--target) 'unique)))
+
+;; This currently doesn't equalize related identities that may have
+;; become mismatched because that shouldn't happen after a connection
+;; is up (other than for a brief moment while renicking or similar,
+;; when states are inconsistent).
+(defun erc-networks--shrink-ids-and-buffer-names-any (&rest omit)
+ (let (grown)
+ ;; Gather all grown identities.
+ (erc-buffer-filter
+ (lambda ()
+ (when (and erc-networks--id
+ (erc-networks--id-qualifying-p erc-networks--id)
+ (not (memq (current-buffer) omit))
+ (not (memq erc-networks--id grown))
+ (> (erc-networks--id-qualifying-len erc-networks--id) 1))
+ (push erc-networks--id grown))))
+ ;; Check for other identities with shared prefix. If none exists,
+ ;; and an identity is overlong, shrink it.
+ (dolist (nid grown)
+ (let ((skip (not (null omit))))
+ (catch 'found
+ (if (cdr grown)
+ (dolist (other grown)
+ (unless (eq nid other)
+ (setq skip nil)
+ (when (erc-networks--id-qualifying-prefix-length nid other)
+ (throw 'found (setq skip t)))))
+ (setq skip nil)))
+ (unless (or skip (< (erc-networks--id-qualifying-len nid) 2))
+ (erc-networks--id-qualifying-reset-id nid)
+ (erc-buffer-filter
+ (lambda ()
+ (when (and (eq erc-networks--id nid)
+ (not (memq (current-buffer) omit)))
+ (if erc--target
+ (erc-networks--refresh-buffer-names nid omit)
+ (erc-networks--maybe-update-buffer-name))))))))))
+
+(cl-defmethod erc-networks--shrink-ids-and-buffer-names
+ (&context (erc-networks--id erc-networks--id-qualifying))
+ (erc-networks--shrink-ids-and-buffer-names-any (current-buffer)))
+
+(defun erc-networks-rename-surviving-target-buffer ()
+ "Maybe drop qualifying suffix from fellow target-buffer's name.
+But only do so when there's a single survivor with a target
+matching that of the dying buffer."
+ (when-let*
+ (((with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers))
+ (target erc--target)
+ ;; Buffer name includes ID suffix
+ ((not (string= (erc--target-symbol target) ; string= t "t" -> t
+ (erc-downcase (buffer-name)))))
+ (buf (current-buffer))
+ ;; All buffers, not just those belonging to same process
+ (others (erc-buffer-filter
+ (lambda ()
+ (and-let* ((erc--target)
+ ((not (eq buf (current-buffer))))
+ ((eq (erc--target-symbol target)
+ (erc--target-symbol erc--target))))))))
+ ((not (cdr others))))
+ (with-current-buffer (car others)
+ (rename-buffer (erc--target-string target)))))
+
+(defun erc-networks-shrink-ids-and-buffer-names ()
+ "Recompute network IDs and buffer names, ignoring the current buffer.
+Only do so when an IRC connection's context supports qualified
+naming. Do not discriminate based on whether a buffer's
+connection is active."
+ (erc-networks--shrink-ids-and-buffer-names))
+
+(defun erc-networks--examine-targets (identity target on-dupe on-collision)
+ "Visit all ERC target buffers with the same TARGET.
+Call ON-DUPE when a buffer's identity belongs to a network
+IDENTITY or \"should\" after reconciliation. Call ON-COLLISION
+otherwise. Neither function should accept any args. Expect
+TARGET to be an `erc--target' object."
+ (declare (indent 2))
+ (let ((announced erc-server-announced-name))
+ (erc-buffer-filter
+ (lambda ()
+ (when (and erc--target (eq (erc--target-symbol erc--target)
+ (erc--target-symbol target)))
+ (let ((oursp (if (erc--target-channel-local-p target)
+ (equal announced erc-server-announced-name)
+ (erc-networks--id-equal-p identity erc-networks--id))))
+ (funcall (if oursp on-dupe on-collision))))))))
+
+(defconst erc-networks--qualified-sep "@"
+ "Separator used for naming a target buffer.")
+
+(defun erc-networks--construct-target-buffer-name (target)
+ "Return TARGET@suffix."
+ (concat (erc--target-string target)
+ (if (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ erc-networks--qualified-sep "/")
+ (cond
+ ((not (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers))
+ (cadr (split-string
+ (symbol-name (erc-networks--id-symbol erc-networks--id))
+ "/")))
+ ((erc--target-channel-local-p target) erc-server-announced-name)
+ (t (symbol-name (erc-networks--id-symbol erc-networks--id))))))
+
+(defun erc-networks--ensure-unique-target-buffer-name ()
+ (when-let* ((new-name (erc-networks--construct-target-buffer-name
+ erc--target))
+ ((not (equal (buffer-name) new-name))))
+ (rename-buffer new-name 'unique)))
+
+(defun erc-networks--ensure-unique-server-buffer-name ()
+ (when-let* ((new-name (symbol-name (erc-networks--id-symbol
+ erc-networks--id)))
+ ((not (equal (buffer-name) new-name))))
+ (rename-buffer new-name 'unique)))
+
+(defun erc-networks--maybe-update-buffer-name ()
+ "Update current buffer name to reflect display ID if necessary."
+ (if erc--target
+ (erc-networks--ensure-unique-target-buffer-name)
+ (erc-networks--ensure-unique-server-buffer-name)))
+
+(defun erc-networks--reconcile-buffer-names (target nid)
+ "Reserve preferred buffer name for TARGET and network identifier.
+Expect TARGET to be an `erc--target' instance. Guarantee that at
+most one existing buffer has the same `erc-networks--id' and a
+case-mapped target, i.e., `erc--target-symbol'. If other buffers
+with equivalent targets exist, rename them to TARGET@their-NID
+and return TARGET@our-NID. Otherwise return TARGET as a string.
+When multiple buffers for TARGET exist for the current NID,
+rename them with <n> suffixes going from newest to oldest."
+ (let* (existing ; Former selves or unexpected dupes (for now allow > 1)
+ ;; Renamed ERC buffers on other networks matching target
+ (namesakes (erc-networks--examine-targets nid target
+ (lambda () (push (current-buffer) existing) nil)
+ ;; Append network ID as TARGET@NID,
+ ;; possibly qualifying to achieve uniqueness.
+ (lambda ()
+ (unless (erc--target-channel-local-p erc--target)
+ (erc-networks--id-ensure-comparable
+ nid erc-networks--id))
+ (erc-networks--ensure-unique-target-buffer-name)
+ t)))
+ ;; Must follow ^ because NID may have been modified
+ (name (if (or namesakes (not (with-suppressed-warnings
+ ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)))
+ (erc-networks--construct-target-buffer-name target)
+ (erc--target-string target)))
+ placeholder)
+ ;; If we don't exist, claim name temporarily while renaming others
+ (when-let* (namesakes
+ (ex (get-buffer name))
+ ((not (memq ex existing)))
+ (temp-name (generate-new-buffer-name (format "*%s*" name))))
+ (setq existing (remq ex existing))
+ (with-current-buffer ex
+ (rename-buffer temp-name)
+ (setq placeholder (get-buffer-create name))
+ (rename-buffer name 'unique)))
+ (unless (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ (when (string-suffix-p ">" name)
+ (setq name (substring name 0 -3))))
+ (dolist (ex (erc-networks--id-sort-buffers existing))
+ (with-current-buffer ex
+ (rename-buffer name 'unique)))
+ (when placeholder (kill-buffer placeholder))
+ name))
+
+
;; Functions:
;;;###autoload
@@ -739,6 +1199,7 @@ MATCHER is used to find a corresponding network to a server while
Use the server parameter NETWORK if provided, otherwise parse the
server name and search for a match in `erc-networks-alist'."
;; The server made it easy for us and told us the name of the NETWORK
+ (declare (obsolete "maybe see `erc-networks--determine'" "29.1"))
(let ((network-name (cdr (assoc "NETWORK" erc-server-parameters))))
(if network-name
(intern network-name)
@@ -753,7 +1214,7 @@ server name and search for a match in `erc-networks-alist'."
(defun erc-network ()
"Return the value of `erc-network' for the current server."
- (erc-with-server-buffer erc-network))
+ (or erc-network (erc-with-server-buffer erc-network)))
(defun erc-network-name ()
"Return the name of the current network as a string."
@@ -761,23 +1222,242 @@ server name and search for a match in `erc-networks-alist'."
(defun erc-set-network-name (_proc _parsed)
"Set `erc-network' to the value returned by `erc-determine-network'."
+ (declare (obsolete "maybe see `erc-networks--set-name'" "29.1"))
(unless erc-server-connected
- (setq erc-network (erc-determine-network)))
+ (setq erc-network (with-suppressed-warnings
+ ((obsolete erc-determine-network))
+ (erc-determine-network))))
+ nil)
+
+(defconst erc-networks--name-missing-sentinel (gensym "Unknown ")
+ "Value to cover rare case of a literal NETWORK=nil.")
+
+(defun erc-networks--determine ()
+ "Return the name of the network as a symbol.
+Search `erc-networks-alist' for a known entity matching
+`erc-server-announced-name'. If that fails, use the display name
+given by the `RPL_ISUPPORT' NETWORK parameter."
+ (or (cl-loop for (name matcher) in erc-networks-alist
+ when (and matcher (string-match (concat matcher "\\'")
+ erc-server-announced-name))
+ return name)
+ (and-let* ((vanity (erc--get-isupport-entry 'NETWORK 'single))
+ ((intern vanity))))
+ erc-networks--name-missing-sentinel))
+
+(defun erc-networks--set-name (_proc parsed)
+ "Set `erc-network' to the value returned by `erc-networks--determine'.
+Signal an error when the network cannot be determined."
+ ;; Always update (possibly clobber) current value, if any.
+ (let ((name (erc-networks--determine)))
+ (when (eq name erc-networks--name-missing-sentinel)
+ ;; This can happen theoretically, e.g., if you're editing some
+ ;; settings interactively on a proxy service that impersonates IRC
+ ;; but aren't being proxied through to a real network. The
+ ;; service may send a 422 but no NETWORK param (or *any* 005s).
+ (let ((m (concat "Failed to determine network. Please set entry for "
+ erc-server-announced-name " in `erc-network-alist'.")))
+ (erc-display-error-notice parsed m)
+ (erc-error "Failed to determine network"))) ; beep
+ (setq erc-network name))
+ nil)
+
+;; This lives here in this file because all the other "on connect"
+;; MOTD stuff ended up here (but perhaps that needs to change).
+
+(defun erc-networks--ensure-announced (_ parsed)
+ "Set a fallback `erc-server-announced-name' if still unset.
+Copy source (prefix) from MOTD-ish message as a last resort."
+ ;; The 004 handler never ran; see 2004-03-10 Diane Murray in change log
+ (unless erc-server-announced-name
+ (erc-display-error-notice parsed "Failed to determine server name.")
+ (erc-display-error-notice
+ parsed (concat "If this was unexpected, consider reporting it via "
+ (substitute-command-keys "\\[erc-bug]") "."))
+ (setq erc-server-announced-name (erc-response.sender parsed)))
nil)
(defun erc-unset-network-name (_nick _ip _reason)
"Set `erc-network' to nil."
+ (declare (obsolete "`erc-network' is now effectively read-only" "29.1"))
(setq erc-network nil)
nil)
+;; TODO add note in Commentary saying that this module is considered a
+;; core module and that it's as much about buffer naming and network
+;; identity as anything else.
+
+(defun erc-networks--insert-transplanted-content (content)
+ (let ((inhibit-read-only t)
+ (buffer-undo-list t))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (insert-before-markers content)))))
+
+;; This should run whenever a network identity is updated.
+
+(defun erc-networks--reclaim-orphaned-target-buffers (new-proc nid announced)
+ "Visit disowned buffers for same NID and associate with NEW-PROC.
+ANNOUNCED is the server's reported host name."
+ (erc-buffer-filter
+ (lambda ()
+ (when (and erc--target
+ (not erc-server-connected)
+ (erc-networks--id-equal-p erc-networks--id nid)
+ (or (not (erc--target-channel-local-p erc--target))
+ (string= erc-server-announced-name announced)))
+ ;; If a target buffer exists for the current process, kill this
+ ;; stale one after transplanting its content; else reinstate.
+ (if-let ((existing (erc-get-buffer
+ (erc--target-string erc--target) new-proc)))
+ (progn
+ (widen)
+ (let ((content (buffer-substring (point-min)
+ erc-insert-marker)))
+ (kill-buffer) ; allow target-buf renaming hook to run
+ (with-current-buffer existing
+ (erc-networks--ensure-unique-target-buffer-name)
+ (erc-networks--insert-transplanted-content content))))
+ (setq erc-server-process new-proc
+ erc-server-connected t
+ erc-networks--id nid))))))
+
+(defun erc-networks--copy-over-server-buffer-contents (existing name)
+ "Kill off existing server buffer after copying its contents.
+Must be called from the replacement buffer."
+ ;; ERC expects `erc-open' to be idempotent when setting up local
+ ;; vars and other context properties for a new identity. Thus, it's
+ ;; unlikely we'll have to copy anything else over besides text. And
+ ;; no reconciling of user tables, etc. happens during a normal
+ ;; reconnect, so we should be fine just sticking to text. (Right?)
+ (let ((text (with-current-buffer existing
+ ;; This `erc-networks--id' should be
+ ;; `erc-networks--id-equal-p' to caller's network
+ ;; identity and older if not eq.
+ ;;
+ ;; `erc-server-process' should be set but dead
+ ;; and eq `get-buffer-process' unless latter nil
+ (delete-process erc-server-process)
+ (buffer-substring (point-min) erc-insert-marker)))
+ erc-kill-server-hook
+ erc-kill-buffer-hook)
+ (erc-networks--insert-transplanted-content text)
+ (kill-buffer name)))
+
+;; This stands alone for testing purposes
+
+(defun erc-networks--update-server-identity ()
+ "Maybe grow or replace the current network identity.
+If a dupe is found, adopt its identity by overwriting ours.
+Otherwise, take steps to ensure it can effectively be compared to
+ours, now and into the future. Note that target buffers are
+considered as well because server buffers are often killed."
+ (let* ((identity erc-networks--id)
+ (buffer (current-buffer))
+ (f (lambda ()
+ (unless (or (eq (current-buffer) buffer)
+ (eq erc-networks--id identity))
+ (if (erc-networks--id-equal-p identity erc-networks--id)
+ (throw 'buffer erc-networks--id)
+ (erc-networks--id-ensure-comparable identity
+ erc-networks--id)
+ nil))))
+ (found (catch 'buffer (erc-buffer-filter f))))
+ (when found
+ (setq erc-networks--id found))))
+
+;; These steps should only run when initializing a newly connected
+;; server buffer, whereas `erc-networks--rename-server-buffer' can run
+;; mid-session, after an identity's core components have changed.
+
+(defun erc-networks--init-identity (_proc _parsed)
+ "Update identity with real network name."
+ ;; Initialize identity for real now that we know the network
+ (cl-assert erc-network)
+ (unless (erc-networks--id-symbol erc-networks--id) ; unless just reconnected
+ (erc-networks--id-on-connect erc-networks--id))
+ ;; Find duplicate identities or other conflicting ones and act
+ ;; accordingly.
+ (erc-networks--update-server-identity)
+ ;;
+ nil)
+
+(defun erc-networks--rename-server-buffer (new-proc &optional _parsed)
+ "Rename a server buffer based on its network identity.
+Assume that the current buffer is a server buffer, either one
+with a newly established connection whose identity has just been
+fully fleshed out, or an existing one whose identity has just
+been updated. Either way, assume the current identity is ready
+to serve as a canonical identifier.
+
+When a server buffer already exists with the chosen name, copy
+over its contents and kill it. However, when its process is
+still alive, kill off the current buffer. This can happen, for
+example, after a perceived loss in network connectivity turns out
+to be a false alarm. If `erc-reuse-buffers' is nil, let
+`generate-new-buffer-name' do the actual renaming."
+ (cl-assert (eq new-proc erc-server-process))
+ (cl-assert (erc-networks--id-symbol erc-networks--id))
+ ;; Always look for targets to reassociate because original server
+ ;; buffer may have been deleted.
+ (erc-networks--reclaim-orphaned-target-buffers new-proc erc-networks--id
+ erc-server-announced-name)
+ (let* ((name (symbol-name (erc-networks--id-symbol erc-networks--id)))
+ ;; When this ends up being the current buffer, either we have
+ ;; a "given" ID or the buffer was reused on reconnecting.
+ (existing (get-buffer name)))
+ (cond ((or (not existing)
+ (erc-networks--id-given erc-networks--id)
+ (eq existing (current-buffer)))
+ (rename-buffer name))
+ ;; Abort on accidental reconnect or failure to pass :id param for
+ ;; avoidable collisions.
+ ((erc-server-process-alive existing)
+ (kill-local-variable 'erc-network)
+ (delete-process new-proc)
+ (erc-display-error-notice nil (format "Buffer %s still connected"
+ name))
+ (erc-set-active-buffer existing))
+ ;; Copy over old buffer's contents and kill it
+ ((with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ (erc-networks--copy-over-server-buffer-contents existing name)
+ (rename-buffer name))
+ (t (rename-buffer (generate-new-buffer-name name)))))
+ nil)
+
+;; Soju v0.4.0 only sends ISUPPORT on upstream reconnect, so this
+;; doesn't apply. ZNC 1.8.2, however, still sends the entire burst.
+(defconst erc-networks--bouncer-targets '(*status bouncerserv)
+ "Case-mapped symbols matching known bouncer service-bot targets.")
+
+(defun erc-networks-on-MOTD-end (proc parsed)
+ "Call on-connect functions with server PROC and PARSED message.
+This must run before `erc-server-connected' is set."
+ (when erc-server-connected
+ (unless (erc-buffer-filter (lambda ()
+ (and erc--target
+ (memq (erc--target-symbol erc--target)
+ erc-networks--bouncer-targets)))
+ proc)
+ (let ((m (concat "Unexpected state detected. Please report via "
+ (substitute-command-keys "\\[erc-bug]") ".")))
+ (erc-display-error-notice parsed m))))
+
+ ;; For now, retain compatibility with erc-server-NNN-functions.
+ (or (erc-networks--ensure-announced proc parsed)
+ (erc-networks--set-name proc parsed)
+ (erc-networks--init-identity proc parsed)
+ (erc-networks--rename-server-buffer proc parsed)))
+
(define-erc-module networks nil
"Provide data about IRC networks."
- ((add-hook 'erc-server-375-functions #'erc-set-network-name)
- (add-hook 'erc-server-422-functions #'erc-set-network-name)
- (add-hook 'erc-disconnected-hook #'erc-unset-network-name))
- ((remove-hook 'erc-server-375-functions #'erc-set-network-name)
- (remove-hook 'erc-server-422-functions #'erc-set-network-name)
- (remove-hook 'erc-disconnected-hook #'erc-unset-network-name)))
+ ((add-hook 'erc-server-376-functions #'erc-networks-on-MOTD-end)
+ (add-hook 'erc-server-422-functions #'erc-networks-on-MOTD-end))
+ ((remove-hook 'erc-server-376-functions #'erc-networks-on-MOTD-end)
+ (remove-hook 'erc-server-422-functions #'erc-networks-on-MOTD-end)))
(defun erc-ports-list (ports)
"Return a list of PORTS.
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index a3fe04d392c..911a574b17e 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcNotify
;; Keywords: comm
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
index e53178ce63a..087e5a67d07 100644
--- a/lisp/erc/erc-page.el
+++ b/lisp/erc/erc-page.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2002, 2004, 2006-2022 Free Software Foundation, Inc.
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
index 384be500ad7..af8528dbc38 100644
--- a/lisp/erc/erc-pcomplete.el
+++ b/lisp/erc/erc-pcomplete.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Sacha Chua <sacha@free.net.ph>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; URL: https://www.emacswiki.org/emacs/ErcCompletion
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
index ec4bf3ae536..e46862d6a64 100644
--- a/lisp/erc/erc-replace.el
+++ b/lisp/erc/erc-replace.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2001-2022 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcReplace
;; Keywords: comm, IRC, client, Internet
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
index 0f6851a98a3..9dd1fab6403 100644
--- a/lisp/erc/erc-ring.el
+++ b/lisp/erc/erc-ring.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2001-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; URL: https://www.emacswiki.org/emacs/ErcHistory
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index dcd786411f2..fe9cb5b5f17 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcNickserv
;; This file is part of GNU Emacs.
@@ -174,6 +174,18 @@ function `erc-nickserv-get-password'."
:version "28.1"
:type 'boolean)
+(defcustom erc-auth-source-services-function #'erc-auth-source-search
+ "Function to retrieve NickServ password from auth-source.
+Called with a subset of keyword parameters known to
+`auth-source-search' and relevant to authenticating to nickname
+services. In return, ERC expects a string to send as the
+password, or nil, to fall through to the next method, such as
+prompting. See info node `(erc) Connecting' for details."
+ :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
+ :type '(choice (const erc-auth-source-search)
+ (const nil)
+ function))
+
(defcustom erc-nickserv-passwords nil
"Passwords used when identifying to NickServ automatically.
`erc-prompt-for-nickserv-password' must be nil for these
@@ -202,7 +214,7 @@ Example of use:
(const QuakeNet)
(const Rizon)
(const SlashNET)
- (symbol :tag "Network name"))
+ (symbol :tag "Network name or session ID"))
(repeat :tag "Nickname and password"
(cons :tag "Identity"
(string :tag "Nick")
@@ -431,34 +443,20 @@ As soon as some source returns a password, the sequence of
lookups stops and this function returns it (or returns nil if it
is empty). Otherwise, no corresponding password was found, and
it returns nil."
- (let (network server port)
- ;; Fill in local vars, switching to the server buffer once only
- (erc-with-server-buffer
- (setq network erc-network
- server erc-session-server
- port erc-session-port))
- (let ((ret
- (or
- (when erc-nickserv-passwords
- (cdr (assoc nick
- (cl-second (assoc network
- erc-nickserv-passwords)))))
- (when erc-use-auth-source-for-nickserv-password
- (let ((secret (cl-first (auth-source-search
- :max 1 :require '(:secret)
- :host server
- ;; Ensure a string for :port
- :port (format "%s" port)
- :user nick))))
- (when secret
- (let ((passwd (plist-get secret :secret)))
- (if (functionp passwd) (funcall passwd) passwd)))))
- (when erc-prompt-for-nickserv-password
- (read-passwd
- (format "NickServ password for %s on %s (RET to cancel): "
- nick network))))))
- (when (and ret (not (string= ret "")))
- ret))))
+ (when-let*
+ ((nid (erc-networks--id-symbol erc-networks--id))
+ (ret (or (when erc-nickserv-passwords
+ (assoc-default nick
+ (cadr (assq nid erc-nickserv-passwords))))
+ (when (and erc-use-auth-source-for-nickserv-password
+ erc-auth-source-services-function)
+ (funcall erc-auth-source-services-function :user nick))
+ (when erc-prompt-for-nickserv-password
+ (read-passwd
+ (format "NickServ password for %s on %s (RET to cancel): "
+ nick nid)))))
+ ((not (string-empty-p ret))))
+ ret))
(defvar erc-auto-discard-away)
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index 86978f9d794..5cae64572f0 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2002-2003, 2006-2022 Free Software Foundation, Inc.
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcSound
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index ead0d374b18..5b06c21612f 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -4,7 +4,7 @@
;; Author: Mario Lang <mlang@delysid.org>
;; Contributor: Eric M. Ludlam <zappo@gnu.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcSpeedbar
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index d9cfc9bc985..91e6777b7c0 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2005-2022 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, irc
;; URL: https://www.emacswiki.org/emacs/ErcSpelling
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index d74a53bc71e..cdab3241c12 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, timestamp
;; URL: https://www.emacswiki.org/emacs/ErcStamp
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index 39430ee6598..8997be00ae0 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2017, 2020-2022 Free Software Foundation, Inc.
;; Author: Andrew Barbarello
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://github.com/drewbarbs/erc-status-sidebar
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 2196c5411eb..ef9a8c243e9 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2002-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; URL: https://www.emacswiki.org/emacs/ErcChannelTracking
@@ -46,7 +46,7 @@
(defcustom erc-track-enable-keybindings 'ask
"Whether to enable the ERC track keybindings, namely:
-`C-c C-SPC' and `C-c C-@', which both do the same thing.
+\\`C-c C-SPC' and \\`C-c C-@', which both do the same thing.
The default is to check to see whether these keys are used
already: if not, then enable the ERC track minor mode, which
@@ -353,8 +353,6 @@ of `erc-track-shorten-start' characters."
(> (length s) erc-track-shorten-cutoff))
erc-track-shorten-start))
-(defvar erc-default-recipients)
-
(defun erc-all-buffer-names ()
"Return all channel or query buffer names.
Note that we cannot use `erc-channel-list' with a nil argument,
@@ -455,12 +453,12 @@ START is the minimum length of the name used."
;; Play nice with other IRC clients (and Emacs development rules) by
;; making this a minor mode
-(defvar erc-track-minor-mode-map (make-sparse-keymap)
- "Keymap for rcirc track minor mode.")
-
-(define-key erc-track-minor-mode-map (kbd "C-c C-@") #'erc-track-switch-buffer)
-(define-key erc-track-minor-mode-map (kbd "C-c C-SPC")
- #'erc-track-switch-buffer)
+(defvar erc-track-minor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-c C-@") #'erc-track-switch-buffer)
+ (define-key map (kbd "C-c C-SPC") #'erc-track-switch-buffer)
+ map)
+ "Keymap for ERC track minor mode.")
;;;###autoload
(define-minor-mode erc-track-minor-mode
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
index 8a8842bc484..d998718a8fc 100644
--- a/lisp/erc/erc-truncate.el
+++ b/lisp/erc/erc-truncate.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2003-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcTruncation
;; Keywords: IRC, chat, client, Internet, logging
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
index ee2a8c936f7..ca8ff6c080b 100644
--- a/lisp/erc/erc-xdcc.el
+++ b/lisp/erc/erc-xdcc.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2003-2004, 2006-2022 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm
;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 24f47625711..0a16831fba3 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -3,7 +3,7 @@
;; Copyright (C) 1997-2022 Free Software Foundation, Inc.
;; Author: Alexander L. Belikoff (alexander@belikoff.net)
-;; Maintainer: Amin Bandali <bandali@gnu.org>
+;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Contributors: Sergey Berezin (sergey.berezin@cs.cmu.edu),
;; Mario Lang (mlang@delysid.org),
;; Alex Schroeder (alex@gnu.org)
@@ -130,7 +130,29 @@
"Running scripts at startup and with /LOAD."
:group 'erc)
-(require 'erc-backend)
+;; Defined in erc-backend
+(defvar erc--server-last-reconnect-count)
+(defvar erc--server-reconnecting)
+(defvar erc-channel-members-changed-hook)
+(defvar erc-network)
+(defvar erc-networks--id)
+(defvar erc-server-367-functions)
+(defvar erc-server-announced-name)
+(defvar erc-server-connect-function)
+(defvar erc-server-connected)
+(defvar erc-server-current-nick)
+(defvar erc-server-lag)
+(defvar erc-server-last-sent-time)
+(defvar erc-server-process)
+(defvar erc-server-quitting)
+(defvar erc-server-reconnect-count)
+(defvar erc-server-reconnecting)
+(defvar erc-session-client-certificate)
+(defvar erc-session-connector)
+(defvar erc-session-port)
+(defvar erc-session-server)
+(defvar erc-session-user-full-name)
+(defvar erc-session-username)
;; tunable connection and authentication parameters
@@ -190,16 +212,30 @@ parameters and authentication."
:set (lambda (sym val)
(set sym (if (functionp val) (funcall val) val))))
-(defcustom erc-rename-buffers nil
+(defcustom erc-rename-buffers t
"Non-nil means rename buffers with network name, if available."
:version "24.5"
:group 'erc
:type 'boolean)
+;; For the sake of compatibility, an ID will be created on the user's
+;; behalf when `erc-rename-buffers' is nil and one wasn't provided.
+;; The name will simply be that of the buffer, usually SERVER:PORT.
+;; This violates the policy of treating provided IDs as gospel, but
+;; it'll have to do for now.
+
+(make-obsolete-variable 'erc-rename-buffers
+ "old behavior when t now permanent" "29.1")
+
(defvar erc-password nil
- "Password to use when authenticating to an IRC server.
-It is not strictly necessary to provide this, since ERC will
-prompt you for it.")
+ "Password to use when authenticating to an IRC server interactively.
+
+This variable only exists for legacy reasons. It's not customizable and
+is limited to a single server password. Users looking for similar
+functionality should consider auth-source instead. See info
+node `(auth) Top' and info node `(erc) Connecting'.")
+
+(make-obsolete-variable 'erc-password "use auth-source instead" "29.1")
(defcustom erc-user-mode "+i"
;; +i "Invisible". Hides user from global /who and /names.
@@ -210,7 +246,7 @@ prompt you for it.")
(defcustom erc-prompt-for-password t
- "Asks before using the default password, or whether to enter a new one."
+ "Ask for a server password when invoking `erc-tls' interactively."
:group 'erc
:type 'boolean)
@@ -224,13 +260,49 @@ prompt you for it.")
:group 'erc
:type 'boolean)
-(defcustom erc-hide-prompt nil
- "If non-nil, do not display the prompt for commands.
+(defcustom erc-inhibit-multiline-input nil
+ "When non-nil, conditionally disallow input consisting of multiple lines.
+Issue an error when the number of input lines submitted for
+sending exceeds this value. The value t means disallow more
+than 1 line of input."
+ :package-version '(ERC . "5.4.1") ; FIXME match to next release
+ :group 'erc
+ :type '(choice integer boolean))
-\(A command is any input starting with a `/').
+(defcustom erc-ask-about-multiline-input nil
+ "Whether to ask to ignore `erc-inhibit-multiline-input' when tripped."
+ :package-version '(ERC . "5.4.1") ; FIXME match to next release
+ :group 'erc
+ :type 'boolean)
+
+(defcustom erc-prompt-hidden ">"
+ "Text to show in lieu of the prompt when hidden."
+ :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
+ :group 'erc-display
+ :type 'string)
-See also the variables `erc-prompt' and `erc-command-indicator'."
+(defcustom erc-hide-prompt t
+ "If non-nil, hide input prompt upon disconnecting.
+To unhide, type something in the input area. Once revealed, a
+prompt remains unhidden until the next disconnection. Channel
+prompts are unhidden upon rejoining. See
+`erc-unhide-query-prompt' for behavior concerning query prompts."
+ :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
+ :group 'erc-display
+ :type '(choice (const :tag "Always hide prompt" t)
+ (set (const server)
+ (const query)
+ (const channel))))
+
+(defcustom erc-unhide-query-prompt nil
+ "When non-nil, always reveal query prompts upon reconnecting.
+Otherwise, prompts in a connection's query buffers remain hidden
+until the user types in the input area or a new message arrives
+from the target."
+ :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
:group 'erc-display
+ ;; Extensions may one day offer a way to discover whether a target
+ ;; is online. When that happens, this can be expanded accordingly.
:type 'boolean)
;; tunable GUI stuff
@@ -352,18 +424,30 @@ erc-channel-user struct.")
"Hash table of users on the current server.
It associates nicknames with `erc-server-user' struct instances.")
+(defconst erc--casemapping-rfc1459
+ (make-translation-table
+ '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|) (?~ . ?^))
+ (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
+
+(defconst erc--casemapping-rfc1459-strict
+ (make-translation-table
+ '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|))
+ (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
+
(defun erc-downcase (string)
- "Convert STRING to IRC standard conforming downcase."
- (let ((s (downcase string))
- (c '((?\[ . ?\{)
- (?\] . ?\})
- (?\\ . ?\|)
- (?~ . ?^))))
- (save-match-data
- (while (string-match "[]\\[~]" s)
- (aset s (match-beginning 0)
- (cdr (assq (aref s (match-beginning 0)) c)))))
- s))
+ "Return a downcased copy of STRING with properties.
+Use the CASEMAPPING ISUPPORT parameter to determine the style."
+ (let* ((mapping (erc--get-isupport-entry 'CASEMAPPING 'single))
+ (inhibit-read-only t))
+ (if (equal mapping "ascii")
+ (downcase string)
+ (with-temp-buffer
+ (insert string)
+ (translate-region (point-min) (point-max)
+ (if (equal mapping "rfc1459-strict")
+ erc--casemapping-rfc1459-strict
+ erc--casemapping-rfc1459))
+ (buffer-string)))))
(defmacro erc-with-server-buffer (&rest body)
"Execute BODY in the current ERC server buffer.
@@ -1054,6 +1138,29 @@ The struct has three slots:
:type 'hook
:version "27.1")
+;; This is being auditioned for possible exporting (as a custom hook
+;; option). Likewise for (public versions of) `erc--input-split' and
+;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just
+;; run the latter on the input after `erc-pre-send-functions', and
+;; remove this hook and the struct completely. IOW, if you need this,
+;; please say so.
+
+(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls)
+ "Special hook for modifying individual lines in multiline prompt input.
+The functions are called with one argument, an `erc--input-split'
+struct, which they can optionally modify.
+
+The struct has five slots:
+
+ `string': the input string delivered by `erc-pre-send-functions'
+ `insertp': whether to insert the lines into the buffer
+ `sendp': whether the lines should be sent to the IRC server
+ `lines': a list of lines to be sent, each one a `string'
+ `cmdp': whether to interpret input as a command, like /ignore
+
+The `string' field is effectively read-only. When `cmdp' is
+non-nil, all but the first line will be discarded.")
+
(defvar erc-insert-this t
"Insert the text into the target buffer or not.
Functions on `erc-insert-pre-hook' can set this variable to nil
@@ -1338,6 +1445,45 @@ if ARG is omitted or nil.
(put ',enable 'definition-name ',name)
(put ',disable 'definition-name ',name))))
+;; The rationale for favoring inheritance here (nicer dispatch) is
+;; kinda flimsy since there aren't yet any actual methods.
+
+(cl-defstruct erc--target
+ (string "" :type string :documentation "Received name of target.")
+ (symbol nil :type symbol :documentation "Case-mapped name as symbol."))
+
+;; These should probably take on a `joined' field to track joinedness,
+;; which should be toggled by `erc-server-JOIN', `erc-server-PART',
+;; etc. Functions like `erc--current-buffer-joined-p' (bug#48598) may
+;; find it useful.
+
+(cl-defstruct (erc--target-channel (:include erc--target)))
+
+(cl-defstruct (erc--target-channel-local (:include erc--target-channel)))
+
+;; At some point, it may make sense to add a query type with an
+;; account field, which may help support reassociation across
+;; reconnects and nick changes (likely requires v3 extensions).
+
+(defun erc--target-from-string (string)
+ "Construct an `erc--target' variant from STRING."
+ (funcall (if (erc-channel-p string)
+ (if (erc--valid-local-channel-p string)
+ #'make-erc--target-channel-local
+ #'make-erc--target-channel)
+ #'make-erc--target)
+ :string string :symbol (intern (erc-downcase string))))
+
+(defvar-local erc--target nil
+ "Info about a buffer's target, if any.")
+
+;; Temporary internal getter to ease transition to `erc--target'
+;; everywhere. Will be replaced by updated `erc-default-target'.
+(defun erc--default-target ()
+ "Return target string or nil."
+ (when erc--target
+ (erc--target-string erc--target)))
+
(defun erc-once-with-server-event (event f)
"Run function F the next time EVENT occurs in the `current-buffer'.
@@ -1488,6 +1634,7 @@ Defaults to the server buffer."
(setq-local paragraph-start
(concat "\\(" (regexp-quote (erc-prompt)) "\\)"))
(setq-local completion-ignore-case t)
+ (add-hook 'kill-buffer-hook #'erc-kill-buffer-function nil t)
(add-hook 'completion-at-point-functions #'erc-complete-word-at-point nil t))
;; activation
@@ -1521,6 +1668,22 @@ The available choices are:
(const :tag "Use current buffer" buffer)
(const :tag "Use current buffer" t)))
+(defcustom erc-reconnect-display nil
+ "How (and whether) to display a channel buffer upon reconnecting.
+
+This only affects automatic reconnections and is ignored when
+issuing a /reconnect command or reinvoking `erc-tls' with the
+same args (assuming success, of course). See `erc-join-buffer'
+for a description of possible values."
+ :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+ :group 'erc-buffers
+ :type '(choice (const :tag "Use value of `erc-join-buffer'" nil)
+ (const :tag "Split window and select" window)
+ (const :tag "Split window, don't select" window-noselect)
+ (const :tag "New frame" frame)
+ (const :tag "Bury in new buffer" bury)
+ (const :tag "Use current buffer" buffer)))
+
(defcustom erc-frame-alist nil
"Alist of frame parameters for creating erc frames.
A value of nil means to use `default-frame-alist'."
@@ -1552,6 +1715,14 @@ effect when `erc-join-buffer' is set to `frame'."
(erc-channel-p (erc-default-target))))
(t nil)))
+;; For the sake of compatibility, a historical quirk concerning this
+;; option, when nil, has been preserved: all buffers are suffixed with
+;; the original dialed host name, which is usually something like
+;; irc.libera.chat. Collisions are handled by adding a uniquifying
+;; numeric suffix of the form <N>. Note that channel reassociation
+;; behavior involving this option (when nil) was inverted in 28.1 (ERC
+;; 5.4 and 5.4.1). This was regrettable and has since been undone.
+
(defcustom erc-reuse-buffers t
"If nil, create new buffers on joining a channel/query.
If non-nil, a new buffer will only be created when you join
@@ -1561,6 +1732,9 @@ the existing buffers will be reused."
:group 'erc-buffers
:type 'boolean)
+(make-obsolete-variable 'erc-reuse-buffers
+ "old behavior when t now permanent" "29.1")
+
(defun erc-normalize-port (port)
"Normalize the port specification PORT to integer form.
PORT may be an integer, a string or a symbol. If it is a string or a
@@ -1596,55 +1770,61 @@ symbol, it may have these values:
"Check whether ports A and B are equal."
(= (erc-normalize-port a) (erc-normalize-port b)))
-(defun erc-generate-new-buffer-name (server port target)
- "Create a new buffer name based on the arguments."
- (when (numberp port) (setq port (number-to-string port)))
- (let* ((buf-name (or target
- (let ((name (concat server ":" port)))
- (when (> (length name) 1)
- name))
- ;; This fallback should in fact never happen.
- "*erc-server-buffer*"))
- (full-buf-name (concat buf-name "/" server))
- (dup-buf-name (buffer-name (car (erc-channel-list nil))))
- buffer-name)
- ;; Reuse existing buffers, but not if the buffer is a connected server
- ;; buffer and not if its associated with a different server than the
- ;; current ERC buffer.
- ;; If buf-name is taken by a different connection (or by something !erc)
- ;; then see if "buf-name/server" meets the same criteria.
- (if (and dup-buf-name (string-match-p (concat buf-name "/") dup-buf-name))
- (setq buffer-name full-buf-name) ; ERC buffer with full name already exists.
- (dolist (candidate (list buf-name full-buf-name))
- (if (and (not buffer-name)
- erc-reuse-buffers
- (or (not (get-buffer candidate))
- ;; Looking for a server buffer, so there's no target.
- (and (not target)
- (with-current-buffer (get-buffer candidate)
- (and (erc-server-buffer-p)
- (not (erc-server-process-alive)))))
- ;; Channel buffer; check that it's from the right server.
- (and target
- (with-current-buffer (get-buffer candidate)
- (and (string= erc-session-server server)
- (erc-port-equal erc-session-port port))))))
- (setq buffer-name candidate)
- (when (and (not buffer-name) (get-buffer buf-name) erc-reuse-buffers)
- ;; A new buffer will be created with the name buf-name/server, rename
- ;; the existing name-duplicated buffer with the same format as well.
- (with-current-buffer (get-buffer buf-name)
- (when (derived-mode-p 'erc-mode) ; ensure it's an erc buffer
- (rename-buffer
- (concat buf-name "/" (or erc-session-server erc-server-announced-name)))))))))
- ;; If buffer-name is unset, neither candidate worked out for us,
- ;; fallback to the old <N> uniquification method:
- (or buffer-name (generate-new-buffer-name full-buf-name))))
-
-(defun erc-get-buffer-create (server port target)
+(defun erc-generate-new-buffer-name (server port target &optional tgt-info id)
+ "Determine the name of an ERC buffer.
+When TGT-INFO is nil, assume this is a server buffer. If ID is non-nil,
+return ID as a string unless a buffer already exists with a live server
+process, in which case signal an error. When ID is nil, return a
+temporary name based on SERVER and PORT to be replaced with the network
+name when discovered (see `erc-networks--rename-server-buffer'). Allow
+either SERVER or PORT (but not both) to be nil to accommodate oddball
+`erc-server-connect-function's.
+
+When TGT-INFO is non-nil, expect its string field to match the redundant
+param TARGET (retained for compatibility). Whenever possibly, prefer
+returning TGT-INFO's string unmodified. But when a case-insensitive
+collision prevents that, return target@ID when ID is non-nil or
+target@network otherwise after renaming the conflicting buffer in the
+same manner."
+ (when target ; compat
+ (setq tgt-info (erc--target-from-string target)))
+ (if tgt-info
+ (let* ((esid (erc-networks--id-symbol erc-networks--id))
+ (name (if esid
+ (erc-networks--reconcile-buffer-names tgt-info
+ erc-networks--id)
+ (erc--target-string tgt-info))))
+ (if (and esid (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers))
+ name
+ (generate-new-buffer-name name)))
+ (if (and (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ id)
+ (progn
+ (when-let* ((buf (get-buffer (symbol-name id)))
+ ((erc-server-process-alive buf)))
+ (user-error "Session with ID %S already exists" id))
+ (symbol-name id))
+ (generate-new-buffer-name (if (and server port)
+ (if (with-suppressed-warnings
+ ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers)
+ (format "%s:%s" server port)
+ (format "%s:%s/%s" server port server))
+ (or server port))))))
+
+(defun erc-get-buffer-create (server port target &optional tgt-info id)
"Create a new buffer based on the arguments."
- (get-buffer-create (erc-generate-new-buffer-name server port target)))
-
+ (when target ; compat
+ (setq tgt-info (erc--target-from-string target)))
+ (if (and erc--server-reconnecting
+ (not tgt-info)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers))
+ (current-buffer)
+ (get-buffer-create
+ (erc-generate-new-buffer-name server port nil tgt-info id))))
(defun erc-member-ignore-case (string list)
"Return non-nil if STRING is a member of LIST.
@@ -1761,12 +1941,7 @@ nil."
(lambda (bufname)
(let ((buf (if (consp bufname)
(cdr bufname) (get-buffer bufname))))
- (when buf
- (erc--buffer-p buf (lambda () t) proc)
- (with-current-buffer buf
- (and (derived-mode-p 'erc-mode)
- (or (null proc)
- (eq proc erc-server-process))))))))))
+ (and buf (erc--buffer-p buf (lambda () t) proc)))))))
(defun erc-switch-to-buffer (&optional arg)
"Prompt for an ERC buffer to switch to.
When invoked with prefix argument, use all ERC buffers. Without
@@ -1804,12 +1979,24 @@ all channel buffers on all servers."
;; Some local variables
+;; TODO eventually deprecate this variable
+;;
+;; In the ancient, pre-CVS days (prior to June 2001), this list may
+;; have been used for supporting the changing of a buffer's target on
+;; the fly (mid-session). Such usage, which allowed cons cells like
+;; (QUERY . bob) to serve as the list's head, was either never fully
+;; integrated or was partially clobbered prior to the introduction of
+;; version control. But vestiges remain (see `erc-dcc-chat-mode').
+;; And despite appearances, no evidence has emerged that ERC ever
+;; supported one-to-many target buffers. If such a thing was aspired
+;; to, it was never realized.
+;;
+;; New library code should use the `erc--target' struct instead.
+;; Third-party code can continue to use this until a getter for
+;; `erc--target' (or whatever replaces it) is exported.
(defvar-local erc-default-recipients nil
"List of default recipients of the current buffer.")
-(defvar-local erc-session-user-full-name nil
- "Full name of the user on the current server.")
-
(defvar-local erc-channel-user-limit nil
"Limit of users per channel.")
@@ -1950,7 +2137,10 @@ removed from the list will be disabled."
(defun erc-setup-buffer (buffer)
"Consults `erc-join-buffer' to find out how to display `BUFFER'."
- (pcase erc-join-buffer
+ (pcase (if (zerop (erc-with-server-buffer
+ erc--server-last-reconnect-count))
+ erc-join-buffer
+ (or erc-reconnect-display erc-join-buffer))
('window
(if (active-minibuffer-window)
(display-buffer buffer)
@@ -1976,8 +2166,8 @@ removed from the list will be disabled."
(defun erc-open (&optional server port nick full-name
connect passwd tgt-list channel process
- client-certificate)
- "Connect to SERVER on PORT as NICK with FULL-NAME.
+ client-certificate user id)
+ "Connect to SERVER on PORT as NICK with USER and FULL-NAME.
If CONNECT is non-nil, connect to the server. Otherwise assume
already connected and just create a separate buffer for the new
@@ -1993,15 +2183,17 @@ of the client certificate itself to use when connecting over TLS,
or t, which means that `auth-source' will be queried for the
private key and the certificate.
+When non-nil, ID should be a symbol for identifying the connection.
+
Returns the buffer for the given server or channel."
- (let ((server-announced-name (when (and (boundp 'erc-session-server)
- (string= server erc-session-server))
- erc-server-announced-name))
- (connected-p (unless connect erc-server-connected))
- (buffer (erc-get-buffer-create server port channel))
- (old-buffer (current-buffer))
- old-point
- continued-session)
+ (let* ((target (and channel (erc--target-from-string channel)))
+ (buffer (erc-get-buffer-create server port nil target id))
+ (old-buffer (current-buffer))
+ old-point
+ (continued-session (and erc--server-reconnecting
+ (with-suppressed-warnings
+ ((obsolete erc-reuse-buffers))
+ erc-reuse-buffers))))
(when connect (run-hook-with-args 'erc-before-connect server port nick))
(erc-update-modules)
(set-buffer buffer)
@@ -2009,8 +2201,9 @@ Returns the buffer for the given server or channel."
(let ((old-recon-count erc-server-reconnect-count))
(erc-mode)
(setq erc-server-reconnect-count old-recon-count))
- (setq erc-server-announced-name server-announced-name)
- (setq erc-server-connected connected-p)
+ (when (setq erc-server-connected (not connect))
+ (setq erc-server-announced-name
+ (buffer-local-value 'erc-server-announced-name old-buffer)))
;; connection parameters
(setq erc-server-process process)
(setq erc-insert-marker (make-marker))
@@ -2019,7 +2212,7 @@ Returns the buffer for the given server or channel."
;; (the buffer may have existed)
(goto-char (point-max))
(forward-line 0)
- (when (get-text-property (point) 'erc-prompt)
+ (when (or continued-session (get-text-property (point) 'erc-prompt))
(setq continued-session t)
(set-marker erc-input-marker
(or (next-single-property-change (point) 'erc-prompt)
@@ -2030,6 +2223,9 @@ Returns the buffer for the given server or channel."
(set-marker erc-insert-marker (point))
;; stack of default recipients
(setq erc-default-recipients tgt-list)
+ (when target
+ (setq erc--target target
+ erc-network (erc-network)))
(setq erc-server-current-nick nil)
;; Initialize erc-server-users and erc-channel-users
(if connect
@@ -2041,8 +2237,6 @@ Returns the buffer for the given server or channel."
(setq erc-server-users nil)
(setq erc-channel-users
(make-hash-table :test 'equal))))
- ;; clear last incomplete line read
- (setq erc-server-filter-data nil)
(setq erc-channel-topic "")
;; limit on the number of users on the channel (mode +l)
(setq erc-channel-user-limit nil)
@@ -2059,24 +2253,12 @@ Returns the buffer for the given server or channel."
(setq erc-logged-in nil)
;; The local copy of `erc-nick' - the list of nicks to choose
(setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
- ;; password stuff
- (setq erc-session-password
- (or passwd
- (let ((secret
- (plist-get
- (nth 0
- (auth-source-search :host server
- :max 1
- :user nick
- ;; secrets.el wouldn’t accept a number
- :port (if (numberp port) (number-to-string port) port)
- :require '(:secret)))
- :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))))
;; client certificate (only useful if connecting over TLS)
(setq erc-session-client-certificate client-certificate)
+ (setq erc-networks--id (if connect
+ (erc-networks--id-create id)
+ (buffer-local-value 'erc-networks--id
+ old-buffer)))
;; debug output buffer
(setq erc-dbuf
(when erc-log-p
@@ -2086,12 +2268,13 @@ Returns the buffer for the given server or channel."
(goto-char (point-max))
(insert "\n"))
(if continued-session
- (goto-char old-point)
+ (progn (goto-char old-point)
+ (erc--unhide-prompt))
(set-marker erc-insert-marker (point))
(erc-display-prompt)
(goto-char (point-max)))
- (erc-determine-parameters server port nick full-name)
+ (erc-determine-parameters server port nick full-name user passwd)
;; Saving log file on exit
(run-hook-with-args 'erc-connect-pre-hook buffer)
@@ -2189,11 +2372,9 @@ parameters SERVER and NICK."
(setq server user-input)
(setq passwd (if erc-prompt-for-password
- (if (and erc-password
- (y-or-n-p "Use the default password? "))
- erc-password
- (read-passwd "Password: "))
- erc-password))
+ (read-passwd "Server password: ")
+ (with-suppressed-warnings ((obsolete erc-password))
+ erc-password)))
(when (and passwd (string= "" passwd))
(setq passwd nil))
@@ -2212,8 +2393,10 @@ parameters SERVER and NICK."
(cl-defun erc (&key (server (erc-compute-server))
(port (erc-compute-port))
(nick (erc-compute-nick))
+ (user (erc-compute-user))
password
- (full-name (erc-compute-full-name)))
+ (full-name (erc-compute-full-name))
+ id)
"ERC is a powerful, modular, and extensible IRC client.
This function is the main entry point for ERC.
@@ -2223,8 +2406,10 @@ Non-interactively, it takes the keyword arguments
(server (erc-compute-server))
(port (erc-compute-port))
(nick (erc-compute-nick))
+ (user (erc-compute-user))
password
(full-name (erc-compute-full-name))
+ id
That is, if called with
@@ -2232,9 +2417,13 @@ That is, if called with
then the server and full-name will be set to those values,
whereas `erc-compute-port' and `erc-compute-nick' will be invoked
-for the values of the other parameters."
+for the values of the other parameters.
+
+When present, ID should be an opaque object used to identify the
+connection unequivocally. This is rarely needed and not available
+interactively."
(interactive (erc-select-read-args))
- (erc-open server port nick full-name t password))
+ (erc-open server port nick full-name t password nil nil nil nil user id))
;;;###autoload
(defalias 'erc-select #'erc)
@@ -2244,9 +2433,11 @@ for the values of the other parameters."
(cl-defun erc-tls (&key (server (erc-compute-server))
(port (erc-compute-port))
(nick (erc-compute-nick))
+ (user (erc-compute-user))
password
(full-name (erc-compute-full-name))
- client-certificate)
+ client-certificate
+ id)
"ERC is a powerful, modular, and extensible IRC client.
This function is the main entry point for ERC over TLS.
@@ -2260,6 +2451,7 @@ Non-interactively, it takes the keyword arguments
password
(full-name (erc-compute-full-name))
client-certificate
+ id
That is, if called with
@@ -2281,13 +2473,19 @@ Example usage:
(erc-tls :server \"irc.libera.chat\" :port 6697
:client-certificate
- '(\"/home/bandali/my-cert.key\"
- \"/home/bandali/my-cert.crt\"))"
+ \\='(\"/home/bandali/my-cert.key\"
+ \"/home/bandali/my-cert.crt\"))
+
+When present, ID should be an opaque object for identifying the
+connection unequivocally. (In most cases, this would be a string or a
+symbol composed of letters from the Latin alphabet.) This option is
+generally unneeded, however. See info node `(erc) Connecting' for use
+cases. Not available interactively."
(interactive (let ((erc-default-port erc-default-port-tls))
(erc-select-read-args)))
(let ((erc-server-connect-function 'erc-open-tls-stream))
(erc-open server port nick full-name t password
- nil nil nil client-certificate)))
+ nil nil nil client-certificate user id)))
(defun erc-open-tls-stream (name buffer host port &rest parameters)
"Open an TLS stream to an IRC server.
@@ -2343,8 +2541,6 @@ but you won't see it.
WARNING: Do not set this variable directly! Instead, use the
function `erc-toggle-debug-irc-protocol' to toggle its value.")
-(declare-function erc-network-name "erc-networks" ())
-
(defun erc-log-irc-protocol (string &optional outbound)
"Append STRING to the buffer *erc-protocol*.
@@ -2354,15 +2550,20 @@ The buffer is created if it doesn't exist.
If OUTBOUND is non-nil, STRING is being sent to the IRC server and
appears in face `erc-input-face' in the buffer. Lines must already
-contain CRLF endings. Peer is identified by the most precise label
-available at run time, starting with the network name, followed by the
-announced host name, and falling back to the dialed <server>:<port>."
+contain CRLF endings. A peer is identified by the most precise label
+available, starting with the session ID followed by the server-reported
+hostname, and falling back to the dialed <server>:<port> pair.
+
+When capturing logs for multiple peers and sorting them into buckets,
+such inconsistent labeling may pose a problem until the MOTD is
+received. Setting a fixed `erc-networks--id' can serve as a
+workaround."
(when erc-debug-irc-protocol
- (let ((esid (or (and (fboundp 'erc-network)
- (erc-network)
- (erc-network-name))
- erc-server-announced-name
- (format "%s:%s" erc-session-server erc-session-port)))
+ (let ((esid (if-let ((erc-networks--id)
+ (esid (erc-networks--id-symbol erc-networks--id)))
+ (symbol-name esid)
+ (or erc-server-announced-name
+ (format "%s:%s" erc-session-server erc-session-port))))
(ts (when erc-debug-irc-protocol-time-format
(format-time-string erc-debug-irc-protocol-time-format))))
(with-current-buffer (get-buffer-create "*erc-protocol*")
@@ -2763,7 +2964,7 @@ returns non-nil."
(let* ((command (erc-response.command parsed))
(sender (car (erc-parse-user (erc-response.sender parsed))))
(channel (car (erc-response.command-args parsed)))
- (network (or (and (fboundp 'erc-network-name) (erc-network-name))
+ (network (or (and (erc-network) (erc-network-name))
(erc-shorten-server-name
(or erc-server-announced-name
erc-session-server))))
@@ -2829,6 +3030,8 @@ for special purposes (see erc-dcc.el).")
(defun erc-send-input-line (target line &optional force)
"Send LINE to TARGET."
+ (when (string= line "\n")
+ (setq line " \n"))
(erc-message "PRIVMSG" (concat target " " line) force))
(defun erc-get-arglist (fun)
@@ -3186,22 +3389,139 @@ For a list of user commands (/join /part, ...):
(defalias 'erc-cmd-H #'erc-cmd-HELP)
(put 'erc-cmd-HELP 'process-not-needed t)
+(defcustom erc-auth-source-server-function #'erc-auth-source-search
+ "Function to query auth-source for a server password.
+Called with a subset of keyword parameters known to
+`auth-source-search' and relevant to an opening \"PASS\" command,
+if any. In return, ERC expects a string to send as the server
+password, or nil, to skip the \"PASS\" command completely. An
+explicit `:password' argument to entry-point commands `erc' and
+`erc-tls' also inhibits lookup, as does setting this option to
+nil. See info node `(erc) Connecting' for details."
+ :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
+ :group 'erc
+ :type '(choice (const erc-auth-source-search)
+ (const nil)
+ function))
+
+(defcustom erc-auth-source-join-function #'erc-auth-source-search
+ "Function to query auth-source on joining a channel.
+Called with a subset of keyword arguments known to
+`auth-source-search' and relevant to joining a password-protected
+channel. In return, ERC expects a string to use as the channel
+\"key\", or nil to just join the channel normally. Setting the
+option itself to nil tells ERC to always forgo consulting
+auth-source for channel keys. For more information, see info
+node `(erc) Connecting'."
+ :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
+ :group 'erc
+ :type '(choice (const erc-auth-source-search)
+ (const nil)
+ function))
+
+(defun erc--auth-source-determine-params-defaults ()
+ (let* ((net (and-let* ((esid (erc-networks--id-symbol erc-networks--id))
+ ((symbol-name esid)))))
+ (localp (and erc--target (erc--target-channel-local-p erc--target)))
+ (hosts (if localp
+ (list erc-server-announced-name erc-session-server net)
+ (list net erc-server-announced-name erc-session-server)))
+ (ports (list (cl-typecase erc-session-port
+ (integer (number-to-string erc-session-port))
+ (string (and (string= erc-session-port "irc")
+ erc-session-port)) ; or nil
+ (t erc-session-port))
+ "irc")))
+ (list (cons :host (delq nil hosts))
+ (cons :port (delq nil ports))
+ (cons :require '(:secret)))))
+
+(defun erc--auth-source-determine-params-merge (&rest plist)
+ "Return a plist of merged keyword args to pass to `auth-source-search'.
+Combine items in PLIST with others derived from the current connection
+context, but prioritize the former. For keys not present in PLIST,
+favor a network ID over an announced server unless `erc--target' is a
+local channel. And treat the dialed server address as a fallback for
+the announced name in both cases."
+ (let ((defaults (erc--auth-source-determine-params-defaults)))
+ `(,@(cl-loop for (key value) on plist by #'cddr
+ for default = (assq key defaults)
+ do (when default (setq defaults (delq default defaults)))
+ append `(,key ,(delete-dups
+ `(,@(if (consp value) value (list value))
+ ,@(cdr default)))))
+ ,@(cl-loop for (k . v) in defaults append (list k v)))))
+
+(defun erc--auth-source-search (&rest defaults)
+ "Ask auth-source for a secret and return it if found.
+Use DEFAULTS as keyword arguments for querying auth-source and as a
+guide for narrowing results. Return a string if found or nil otherwise.
+The ordering of DEFAULTS influences how results are filtered, as does
+the ordering of the members of any individual composite values. If
+necessary, the former takes priority. For example, if DEFAULTS were to
+contain
+
+ :host (\"foo\" \"bar\") :port (\"123\" \"456\")
+
+the secret from an auth-source entry of host foo and port 456 would be
+chosen over another of host bar and port 123. However, if DEFAULTS
+looked like
+
+ :port (\"123\" \"456\") :host (\"foo\" \"bar\")
+
+the opposite would be true. In both cases, two entries with the same
+host but different ports would result in the one with port 123 getting
+the nod. Much the same would happen for entries sharing only a port:
+the one with host foo would win."
+ (when-let*
+ ((priority (map-keys defaults))
+ (test (lambda (a b)
+ (catch 'done
+ (dolist (key priority)
+ (let* ((d (plist-get defaults key))
+ (defval (if (listp d) d (list d)))
+ ;; featurep 'seq via auth-source > json > map
+ (p (seq-position defval (plist-get a key)))
+ (q (seq-position defval (plist-get b key))))
+ (unless (eql p q)
+ (throw 'done (when p (or (not q) (< p q))))))))))
+ (plist (copy-sequence defaults)))
+ (unless (plist-get plist :max)
+ (setq plist (plist-put plist :max 5000))) ; `auth-source-netrc-parse'
+ (unless (plist-get defaults :require)
+ (setq plist (plist-put plist :require '(:secret))))
+ (when-let* ((sorted (sort (apply #'auth-source-search plist) test))
+ (secret (plist-get (car sorted) :secret)))
+ (if (functionp secret) (funcall secret) secret))))
+
+(defun erc-auth-source-search (&rest plist)
+ "Call `auth-source-search', possibly with keyword params in PLIST."
+ ;; These exist as separate helpers in case folks should find them
+ ;; useful. If that's you, please request that they be exported.
+ (apply #'erc--auth-source-search
+ (apply #'erc--auth-source-determine-params-merge plist)))
+
(defun erc-server-join-channel (server channel &optional secret)
- (let* ((secret (or secret
- (plist-get (nth 0 (auth-source-search
- :max 1
- :host server
- :port "irc"
- :user channel))
- :secret)))
- (password (if (functionp secret)
- (funcall secret)
- secret)))
- (erc-log (format "cmd: JOIN: %s" channel))
- (erc-server-send (concat "JOIN " channel
- (if password
- (concat " " password)
- "")))))
+ "Join CHANNEL, optionally with SECRET.
+Without SECRET, consult auth-source, possibly passing SERVER as the
+`:host' query parameter."
+ (unless (or secret (not erc-auth-source-join-function))
+ (unless server
+ (when (and erc-server-announced-name
+ (erc--valid-local-channel-p channel))
+ (setq server erc-server-announced-name)))
+ (setq secret (apply erc-auth-source-join-function
+ `(,@(and server (list :host server)) :user ,channel))))
+ (erc-log (format "cmd: JOIN: %s" channel))
+ (erc-server-send (concat "JOIN " channel (and secret (concat " " secret)))))
+
+(defun erc--valid-local-channel-p (channel)
+ "Non-nil when channel is server-local on a network that allows them."
+ (and-let* (((eq ?& (aref channel 0)))
+ (chan-types (erc--get-isupport-entry 'CHANTYPES 'single))
+ ((if (>= emacs-major-version 28)
+ (string-search "&" chan-types)
+ (string-match-p "&" chan-types))))))
(defun erc-cmd-JOIN (channel &optional key)
"Join the channel given in CHANNEL, optionally with KEY.
@@ -3215,18 +3535,12 @@ were most recently invited. See also `invitation'."
(setq chnl (erc-ensure-channel-name channel)))
(when chnl
;; Prevent double joining of same channel on same server.
- (let* ((joined-channels
- (mapcar (lambda (chanbuf)
- (with-current-buffer chanbuf (erc-default-target)))
- (erc-channel-list erc-server-process)))
- (server (with-current-buffer (process-buffer erc-server-process)
- (or erc-session-server erc-server-announced-name)))
- (chnl-name (car (erc-member-ignore-case chnl joined-channels))))
- (if chnl-name
- (switch-to-buffer (if (get-buffer chnl-name)
- chnl-name
- (concat chnl-name "/" server)))
- (erc-server-join-channel server chnl key)))))
+ (if-let* ((existing (erc-get-buffer chnl erc-server-process))
+ ((with-current-buffer existing
+ (erc-get-channel-user (erc-current-nick)))))
+ (switch-to-buffer existing)
+ (setq erc--server-last-reconnect-count 0)
+ (erc-server-join-channel nil chnl key))))
t)
(defalias 'erc-cmd-CHANNEL #'erc-cmd-JOIN)
@@ -3528,8 +3842,8 @@ The rest of LINE is the message to send."
(defun erc-cmd-NICK (nick)
"Change current nickname to NICK."
(erc-log (format "cmd: NICK: %s (erc-bad-nick: %S)" nick erc-bad-nick))
- (let ((nicklen (cdr (assoc "NICKLEN" (erc-with-server-buffer
- erc-server-parameters)))))
+ (let ((nicklen (erc-with-server-buffer
+ (erc--get-isupport-entry 'NICKLEN 'single))))
(and nicklen (> (length nick) (string-to-number nicklen))
(erc-display-message
nil 'notice 'active 'nick-too-long
@@ -3617,13 +3931,14 @@ on the value of `erc-query-display'."
;; `kill-buffer'? If it makes sense, re-add it. -- SK @ 2021-11-11
(interactive
(list (read-string "Start a query with: ")))
- (let ((session-buffer (erc-server-buffer))
- (erc-join-buffer erc-query-display))
- (if user
- (erc-query user session-buffer)
+ (unless user
;; currently broken, evil hack to display help anyway
;(erc-delete-query))))
- (signal 'wrong-number-of-arguments ""))))
+ (signal 'wrong-number-of-arguments ""))
+ (let ((erc-join-buffer erc-query-display))
+ (erc-with-server-buffer
+ (erc--open-target user))))
+
(defalias 'erc-cmd-Q #'erc-cmd-QUERY)
(defun erc-quit/part-reason-default ()
@@ -3641,12 +3956,7 @@ If S is non-nil, it will be used as the quit reason."
"Zippy quit message.
If S is non-nil, it will be used as the quit reason."
- (or s
- (if (fboundp 'yow)
- (if (>= emacs-major-version 28)
- (string-replace "\n" "" (yow))
- (replace-regexp-in-string "\n" "" (yow)))
- (erc-quit/part-reason-default))))
+ (or s (erc-quit/part-reason-default)))
(make-obsolete 'erc-quit-reason-zippy "it will be removed." "24.4")
@@ -3670,12 +3980,7 @@ If S is non-nil, it will be used as the part reason."
"Zippy part message.
If S is non-nil, it will be used as the quit reason."
- (or s
- (if (fboundp 'yow)
- (if (>= emacs-major-version 28)
- (string-replace "\n" "" (yow))
- (replace-regexp-in-string "\n" "" (yow)))
- (erc-quit/part-reason-default))))
+ (or s (erc-quit/part-reason-default)))
(make-obsolete 'erc-part-reason-zippy "it will be removed." "24.4")
@@ -3761,12 +4066,16 @@ the message given by REASON."
(setq erc--server-reconnecting t)
(setq erc-server-reconnect-count 0)
(setq process (get-buffer-process (erc-server-buffer)))
- (if process
- (delete-process process)
- (erc-server-reconnect))
- (with-suppressed-warnings ((obsolete erc-server-reconnecting))
- (setq erc-server-reconnecting nil))
- (setq erc--server-reconnecting nil)))
+ (when process
+ (delete-process process))
+ (erc-server-reconnect)
+ (with-suppressed-warnings ((obsolete erc-server-reconnecting)
+ ((obsolete erc-reuse-buffers)))
+ (if erc-reuse-buffers
+ (progn (cl-assert (not erc--server-reconnecting))
+ (cl-assert (not erc-server-reconnecting)))
+ (setq erc--server-reconnecting nil
+ erc-server-reconnecting nil)))))
t)
(put 'erc-cmd-RECONNECT 'process-not-needed t)
@@ -4257,8 +4566,6 @@ This places `point' just after the prompt, or at the beginning of the line."
(defun erc-complete-word-at-point ()
(run-hook-with-args-until-success 'erc-complete-functions))
-(define-obsolete-function-alias 'erc-complete-word #'completion-at-point "24.1")
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; IRC SERVER INPUT HANDLING
@@ -4305,27 +4612,30 @@ See `erc-default-server-hook'."
(nconc erc-server-vectors (list parsed))
nil)
-(defun erc-query (target server)
- "Open a query buffer on TARGET, using SERVER.
+(defun erc--open-target (target)
+ "Open an ERC buffer on TARGET."
+ (erc-open erc-session-server
+ erc-session-port
+ (erc-current-nick)
+ erc-session-user-full-name
+ nil
+ nil
+ (list target)
+ target
+ erc-server-process
+ nil
+ erc-session-username
+ (erc-networks--id-given erc-networks--id)))
+
+(defun erc-query (target server-buffer)
+ "Open a query buffer on TARGET using SERVER-BUFFER.
To change how this query window is displayed, use `let' to bind
`erc-join-buffer' before calling this."
- (unless (and server
- (buffer-live-p server)
- (set-buffer server))
+ (declare (obsolete "bind `erc-cmd-query' and call `erc-cmd-QUERY'" "29.1"))
+ (unless (buffer-live-p server-buffer)
(error "Couldn't switch to server buffer"))
- (let ((buf (erc-open erc-session-server
- erc-session-port
- (erc-current-nick)
- erc-session-user-full-name
- nil
- nil
- (list target)
- target
- erc-server-process)))
- (unless buf
- (error "Couldn't open query window"))
- (erc-update-mode-line)
- buf))
+ (with-current-buffer server-buffer
+ (erc--open-target target)))
(defcustom erc-auto-query 'window-noselect
"If non-nil, create a query buffer each time you receive a private message.
@@ -4344,6 +4654,9 @@ a new window, but not to select it. See the documentation for
(const :tag "Use current buffer" buffer)
(const :tag "Use current buffer" t)))
+;; FIXME either retire this or put it to use or more clearly explain
+;; what it's supposed to do. It's currently only used by the obsolete
+;; function `erc-auto-query'.
(defcustom erc-query-on-unjoined-chan-privmsg t
"If non-nil create query buffer on receiving any PRIVMSG at all.
This includes PRIVMSGs directed to channels. If you are using an IRC
@@ -4404,9 +4717,8 @@ See also `erc-display-error-notice'."
(format "Nickname %s is %s, try another." nick reason))
(setq erc-nick-change-attempt-count (+ erc-nick-change-attempt-count 1))
(let ((newnick (nth 1 erc-default-nicks))
- (nicklen (cdr (assoc "NICKLEN"
- (erc-with-server-buffer
- erc-server-parameters)))))
+ (nicklen (erc-with-server-buffer
+ (erc--get-isupport-entry 'NICKLEN 'single))))
(setq erc-bad-nick t)
;; try to use a different nick
(if erc-default-nicks
@@ -4467,6 +4779,8 @@ and as second argument the event parsed as a vector."
(erc-cmd-QUERY query))
nil))))
+(make-obsolete 'erc-auto-query "try erc-cmd-QUERY instead" "29.1")
+
(defun erc-is-message-ctcp-p (message)
"Check if MESSAGE is a CTCP message or not."
(string-match "^\C-a\\([^\C-a]*\\)\C-a?$" message))
@@ -4723,11 +5037,19 @@ Set user modes and run `erc-after-connect' hook."
(nick (car (erc-response.command-args parsed)))
(buffer (process-buffer proc)))
(setq erc-server-connected t)
- (setq erc-server-reconnect-count 0)
+ (setq erc--server-last-reconnect-count erc-server-reconnect-count
+ erc-server-reconnect-count 0)
(erc-update-mode-line)
(erc-set-initial-user-mode nick buffer)
(erc-server-setup-periodical-ping buffer)
- (run-hook-with-args 'erc-after-connect server nick)))))
+ (run-hook-with-args 'erc-after-connect server nick))))
+
+ (when erc-unhide-query-prompt
+ (erc-with-all-buffers-of-server proc
+ nil ; FIXME use `erc--target' after bug#48598
+ (when (and (erc-default-target)
+ (not (erc-channel-p (car erc-default-recipients))))
+ (erc--unhide-prompt)))))
(defun erc-set-initial-user-mode (nick buffer)
"If `erc-user-mode' is non-nil for NICK, set the user modes.
@@ -5009,8 +5331,7 @@ See also `erc-channel-begin-receiving-names'."
(defun erc-parse-prefix ()
"Return an alist of valid prefix character types and their representations.
Example: (operator) o => @, (voiced) v => +."
- (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer
- erc-server-parameters)))
+ (let ((str (or (erc-with-server-buffer (erc--get-isupport-entry 'PREFIX t))
;; provide a sane default
"(qaohv)~&@%+"))
types chars)
@@ -5550,7 +5871,7 @@ Specifically, return the position of `erc-insert-marker'."
(point-max))
(defvar erc-last-input-time 0
- "Time of last call to `erc-send-current-line'.
+ "Time of last successful call to `erc-send-current-line'.
If that function has never been called, the value is 0.")
(defcustom erc-accidental-paste-threshold-seconds 0.2
@@ -5566,6 +5887,68 @@ submitted line to be intentional."
:version "26.1"
:type '(choice number (other :tag "disabled" nil)))
+(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r)))
+
+(defun erc--blank-in-multiline-input-p (lines)
+ "Detect whether LINES contains a blank line.
+When `erc-send-whitespace-lines' is in effect, return nil if
+LINES is multiline or the first line is non-empty. When
+`erc-send-whitespace-lines' is nil, return non-nil when any line
+is empty or consists of one or more spaces, tabs, or form-feeds."
+ (catch 'return
+ (let ((multilinep (cdr lines)))
+ (dolist (line lines)
+ (when (if erc-send-whitespace-lines
+ (and (string-empty-p line) (not multilinep))
+ (string-match (rx bot (* (in " \t\f")) eot) line))
+ (throw 'return t))))))
+
+(defun erc--check-prompt-input-for-excess-lines (_ lines)
+ "Return non-nil when trying to send too many LINES."
+ (when erc-inhibit-multiline-input
+ ;; Assume `erc--discard-trailing-multiline-nulls' is set to run
+ (let ((reversed (seq-drop-while #'string-empty-p (reverse lines)))
+ (max (if (eq erc-inhibit-multiline-input t)
+ 2
+ erc-inhibit-multiline-input))
+ (seen 0)
+ msg)
+ (while (and (pop reversed) (< (cl-incf seen) max)))
+ (when (= seen max)
+ (setq msg (format "(exceeded by %d)" (1+ (length reversed))))
+ (unless (and erc-ask-about-multiline-input
+ (y-or-n-p (concat "Send input " msg "?")))
+ (concat "Too many lines " msg))))))
+
+(defun erc--check-prompt-input-for-multiline-blanks (_ lines)
+ "Return non-nil when multiline prompt input has blank LINES."
+ (when (erc--blank-in-multiline-input-p lines)
+ (if erc-warn-about-blank-lines
+ "Blank line - ignoring..."
+ 'invalid)))
+
+(defun erc--check-prompt-input-for-point-in-bounds (_ _)
+ "Return non-nil when point is before prompt."
+ (when (< (point) (erc-beg-of-input-line))
+ "Point is not in the input area"))
+
+(defun erc--check-prompt-input-for-running-process (string _)
+ "Return non-nil unless in an active ERC server buffer."
+ (unless (or (erc-server-buffer-live-p)
+ (erc-command-no-process-p string))
+ "ERC: No process running"))
+
+(defvar erc--check-prompt-input-functions
+ '(erc--check-prompt-input-for-point-in-bounds
+ erc--check-prompt-input-for-multiline-blanks
+ erc--check-prompt-input-for-running-process
+ erc--check-prompt-input-for-excess-lines)
+ "Validators for user input typed at prompt.
+Called with latest input string submitted by user and the list of
+lines produced by splitting it. If any member function returns
+non-nil, processing is abandoned and input is left untouched.
+When the returned value is a string, pass it to `erc-error'.")
+
(defun erc-send-current-line ()
"Parse current line and send it to IRC."
(interactive)
@@ -5579,20 +5962,21 @@ submitted line to be intentional."
(eolp))
(expand-abbrev))
(widen)
- (if (< (point) (erc-beg-of-input-line))
- (erc-error "Point is not in the input area")
+ (if-let* ((str (erc-user-input))
+ (msg (run-hook-with-args-until-success
+ 'erc--check-prompt-input-functions str
+ (split-string str erc--input-line-delim-regexp))))
+ (when (stringp msg)
+ (erc-error msg))
(let ((inhibit-read-only t)
- (str (erc-user-input))
(old-buf (current-buffer)))
- (if (and (not (erc-server-buffer-live-p))
- (not (erc-command-no-process-p str)))
- (erc-error "ERC: No process running")
+ (progn ; unprogn this during next major surgery
(erc-set-active-buffer (current-buffer))
;; Kill the input and the prompt
(delete-region (erc-beg-of-input-line)
(erc-end-of-input-line))
(unwind-protect
- (erc-send-input str)
+ (erc-send-input str 'skip-ws-chk)
;; Fix the buffer if the command didn't kill it
(when (buffer-live-p old-buf)
(with-current-buffer old-buf
@@ -5607,8 +5991,8 @@ submitted line to be intentional."
(set-buffer-modified-p buffer-modified))))))
;; Only when last hook has been run...
- (run-hook-with-args 'erc-send-completed-hook str))))
- (setq erc-last-input-time now))
+ (run-hook-with-args 'erc-send-completed-hook str)))
+ (setq erc-last-input-time now)))
(switch-to-buffer "*ERC Accidental Paste Overflow*")
(lwarn 'erc :warning
"You seem to have accidentally pasted some text!"))))
@@ -5625,21 +6009,31 @@ submitted line to be intentional."
(cl-defstruct erc-input
string insertp sendp)
-(defun erc-send-input (input)
+(cl-defstruct (erc--input-split (:include erc-input))
+ lines cmdp)
+
+(defun erc--discard-trailing-multiline-nulls (state)
+ "Ensure last line of STATE's string is non-null.
+But only when `erc-send-whitespace-lines' is non-nil. STATE is
+an `erc--input-split' object."
+ (when (and erc-send-whitespace-lines (erc--input-split-lines state))
+ (let ((reversed (nreverse (erc--input-split-lines state))))
+ (when (string-empty-p (car reversed))
+ (pop reversed)
+ (setf (erc--input-split-cmdp state) nil))
+ (nreverse (seq-drop-while #'string-empty-p reversed)))))
+
+(defun erc-send-input (input &optional skip-ws-chk)
"Treat INPUT as typed in by the user.
It is assumed that the input and the prompt is already deleted.
Return non-nil only if we actually send anything."
;; Handle different kinds of inputs
- (cond
- ;; Ignore empty input
- ((if erc-send-whitespace-lines
- (string= input "")
- (string-match "\\`[ \t\r\f\n]*\\'" input))
- (when erc-warn-about-blank-lines
- (message "Blank line - ignoring...")
- (beep))
- nil)
- (t
+ (if (and (not skip-ws-chk)
+ (erc--check-prompt-input-for-multiline-blanks
+ input (split-string input erc--input-line-delim-regexp)))
+ (when erc-warn-about-blank-lines
+ (message "Blank line - ignoring...") ; compat
+ (beep))
;; This dynamic variable is used by `erc-send-pre-hook'. It's
;; obsolete, and when it's finally removed, this binding should
;; also be removed.
@@ -5659,48 +6053,28 @@ Return non-nil only if we actually send anything."
:insertp erc-insert-this
:sendp erc-send-this))
(run-hook-with-args 'erc-pre-send-functions state)
+ (setq state (make-erc--input-split
+ :string (erc-input-string state)
+ :insertp (erc-input-insertp state)
+ :sendp (erc-input-sendp state)
+ :lines (split-string (erc-input-string state)
+ erc--input-line-delim-regexp)
+ :cmdp (string-match erc-command-regexp
+ (erc-input-string state))))
+ (run-hook-with-args 'erc--pre-send-split-functions state)
(when (and (erc-input-sendp state)
- erc-send-this)
- (let ((string (erc-input-string state)))
- (if (or (if (>= emacs-major-version 28)
- (string-search "\n" string)
- (string-match "\n" string))
- (not (string-match erc-command-regexp string)))
- (mapc
- (lambda (line)
- (mapc
- (lambda (line)
- ;; Insert what has to be inserted for this.
- (when (erc-input-insertp state)
- (erc-display-msg line))
- (erc-process-input-line (concat line "\n")
- (null erc-flood-protect) t))
- (or (and erc-flood-protect (erc-split-line line))
- (list line))))
- (split-string string "\n"))
- (erc-process-input-line (concat string "\n") t nil))
- t))))))
-
-;; (defun erc-display-command (line)
-;; (when erc-insert-this
-;; (let ((insert-position (point)))
-;; (unless erc-hide-prompt
-;; (erc-display-prompt nil nil (erc-command-indicator)
-;; (and (erc-command-indicator)
-;; 'erc-command-indicator-face)))
-;; (let ((beg (point)))
-;; (insert line)
-;; (erc-put-text-property beg (point)
-;; 'font-lock-face 'erc-command-indicator-face)
-;; (insert "\n"))
-;; (when (processp erc-server-process)
-;; (set-marker (process-mark erc-server-process) (point)))
-;; (set-marker erc-insert-marker (point))
-;; (save-excursion
-;; (save-restriction
-;; (narrow-to-region insert-position (point))
-;; (run-hooks 'erc-send-modify-hook)
-;; (run-hooks 'erc-send-post-hook))))))
+ erc-send-this)
+ (let ((lines (erc--input-split-lines state)))
+ (if (and (erc--input-split-cmdp state) (not (cdr lines)))
+ (erc-process-input-line (concat (car lines) "\n") t nil)
+ (dolist (line lines)
+ (dolist (line (or (and erc-flood-protect (erc-split-line line))
+ (list line)))
+ (when (erc-input-insertp state)
+ (erc-display-msg line))
+ (erc-process-input-line (concat line "\n")
+ (null erc-flood-protect) t))))
+ t)))))
(defun erc-display-msg (line)
"Display LINE as a message of the user to the current target at point."
@@ -5792,6 +6166,27 @@ See also `erc-downcase'."
;; default target handling
+(defun erc--current-buffer-joined-p ()
+ "Return whether the current target buffer is joined."
+ ;; This may be a reliable means of detecting subscription status,
+ ;; but it's also roundabout and awkward. Perhaps it's worth
+ ;; discussing adding a joined slot to `erc--target' for this.
+ (cl-assert erc--target)
+ (and (erc--target-channel-p erc--target)
+ (erc-get-channel-user (erc-current-nick)) t))
+
+;; This function happens to return nil in channel buffers previously
+;; parted or those from which a user had been kicked. While this
+;; "works" for detecting whether a channel is currently subscribed to,
+;; new code should consider using
+;;
+;; (erc-get-channel-user (erc-current-nick))
+;;
+;; instead. For retrieving a target regardless of subscription or
+;; connection status, use replacements based on `erc--target'.
+;; (Coming soon.)
+;;
+;; TODO deprecate this
(defun erc-default-target ()
"Return the current default target (as a character string) or nil if none."
(let ((tgt (car erc-default-recipients)))
@@ -5802,12 +6197,14 @@ See also `erc-downcase'."
(defun erc-add-default-channel (channel)
"Add CHANNEL to the default channel list."
+ (declare (obsolete "use `erc-cmd-JOIN' or similar instead" "29.1"))
(let ((chl (downcase channel)))
(setq erc-default-recipients
(cons chl erc-default-recipients))))
(defun erc-delete-default-channel (channel &optional buffer)
"Delete CHANNEL from the default channel list."
+ (declare (obsolete "use `erc-cmd-PART' or similar instead" "29.1"))
(with-current-buffer (if (and buffer
(bufferp buffer))
buffer
@@ -5819,6 +6216,7 @@ See also `erc-downcase'."
"Add QUERY'd NICKNAME to the default channel list.
The previous default target of QUERY type gets removed."
+ (declare (obsolete "use `erc-cmd-QUERY' or similar instead" "29.1"))
(let ((d1 (car erc-default-recipients))
(d2 (cdr erc-default-recipients))
(qt (cons 'QUERY (downcase nickname))))
@@ -5829,7 +6227,7 @@ The previous default target of QUERY type gets removed."
(defun erc-delete-query ()
"Delete the topmost target if it is a QUERY."
-
+ (declare (obsolete "use one query buffer per target instead" "29.1"))
(let ((d1 (car erc-default-recipients))
(d2 (cdr erc-default-recipients)))
(if (and (listp d1)
@@ -6157,20 +6555,20 @@ user input."
erc-session-server
erc-session-user-full-name))
(if erc-session-password
- (erc-server-send (format "PASS %s" erc-session-password))
+ (erc-server-send (concat "PASS :" erc-session-password))
(message "Logging in without password"))
(erc-server-send (format "NICK %s" (erc-current-nick)))
(erc-server-send
(format "USER %s %s %s :%s"
;; hacked - S.B.
- (if erc-anonymous-login erc-email-userid (user-login-name))
+ erc-session-username
"0" "*"
erc-session-user-full-name))
(erc-update-mode-line))
;; connection properties' heuristics
-(defun erc-determine-parameters (&optional server port nick name)
+(defun erc-determine-parameters (&optional server port nick name user passwd)
"Determine the connection and authentication parameters.
Sets the buffer local variables:
@@ -6178,11 +6576,15 @@ Sets the buffer local variables:
- `erc-session-server'
- `erc-session-port'
- `erc-session-user-full-name'
+- `erc-session-username'
+- `erc-session-password'
- `erc-server-current-nick'"
(setq erc-session-connector erc-server-connect-function
erc-session-server (erc-compute-server server)
erc-session-port (or port erc-default-port)
- erc-session-user-full-name (erc-compute-full-name name))
+ erc-session-user-full-name (erc-compute-full-name name)
+ erc-session-username (erc-compute-user user)
+ erc-session-password (erc--compute-server-password passwd nick))
(erc-set-current-nick (erc-compute-nick nick)))
(defun erc-compute-server (&optional server)
@@ -6200,6 +6602,10 @@ non-nil value is found.
(getenv "IRCSERVER")
erc-default-server))
+(defun erc-compute-user (&optional user)
+ "Return a suitable value for the session user name."
+ (or user (if erc-anonymous-login erc-email-userid (user-login-name))))
+
(defun erc-compute-nick (&optional nick)
"Return user's IRC nick.
@@ -6215,6 +6621,12 @@ non-nil value is found.
(getenv "IRCNICK")
(user-login-name)))
+(defun erc--compute-server-password (password nick)
+ "Maybe provide a PASSWORD argument for the IRC \"PASS\" command.
+When `erc-auth-source-server-function' is non-nil, call it with NICK for
+the user field and use whatever it returns as the server password."
+ (or password (and erc-auth-source-server-function
+ (funcall erc-auth-source-server-function :user nick))))
(defun erc-compute-full-name (&optional full-name)
"Return user's full name.
@@ -6499,30 +6911,19 @@ This should be a string with substitution variables recognized by
(defun erc-format-network ()
"Return the name of the network we are currently on."
- (let ((network (and (fboundp 'erc-network-name) (erc-network-name))))
- (if (and network (symbolp network))
- (symbol-name network)
- "")))
+ (erc-network-name))
(defun erc-format-target-and/or-network ()
"Return the network or the current target and network combined.
If the name of the network is not available, then use the
shortened server name instead."
- (let ((network-name (or (and (fboundp 'erc-network-name) (erc-network-name))
- (erc-shorten-server-name
- (or erc-server-announced-name
- erc-session-server)))))
- (when (and network-name (symbolp network-name))
- (setq network-name (symbol-name network-name)))
- (cond ((erc-default-target)
- (concat (erc-string-no-properties (erc-default-target))
- "@" network-name))
- ((and network-name
- (not (get-buffer network-name)))
- (when erc-rename-buffers
- (rename-buffer network-name))
- network-name)
- (t (buffer-name (current-buffer))))))
+ (if-let ((erc--target)
+ (name (if-let ((esid (erc-networks--id-symbol erc-networks--id)))
+ (symbol-name esid)
+ (erc-shorten-server-name (or erc-server-announced-name
+ erc-session-server)))))
+ (concat (erc--target-string erc--target) "@" name)
+ (buffer-name)))
(defun erc-format-away-status ()
"Return a formatted `erc-mode-line-away-status-format' if `erc-away' is non-nil."
@@ -6939,23 +7340,29 @@ See also `format-spec'."
;;; Various hook functions
-;; FIXME: Don't set the hook globally!
-(add-hook 'kill-buffer-hook #'erc-kill-buffer-function)
-
-(defcustom erc-kill-server-hook '(erc-kill-server)
- "Invoked whenever a server buffer is killed via `kill-buffer'."
+(defcustom erc-kill-server-hook '(erc-kill-server
+ erc-networks-shrink-ids-and-buffer-names)
+ "Invoked whenever a live server buffer is killed via `kill-buffer'."
+ :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
:group 'erc-hooks
:type 'hook)
-(defcustom erc-kill-channel-hook '(erc-kill-channel)
+(defcustom erc-kill-channel-hook
+ '(erc-kill-channel
+ erc-networks-shrink-ids-and-buffer-names
+ erc-networks-rename-surviving-target-buffer)
"Invoked whenever a channel-buffer is killed via `kill-buffer'."
+ :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
:group 'erc-hooks
:type 'hook)
-(defcustom erc-kill-buffer-hook nil
- "Hook run whenever a non-server or channel buffer is killed.
+(defcustom erc-kill-buffer-hook
+ '(erc-networks-shrink-ids-and-buffer-names
+ erc-networks-rename-surviving-target-buffer)
+ "Hook run whenever a query buffer is killed.
See also `kill-buffer'."
+ :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
:group 'erc-hooks
:type 'hook)
@@ -7028,6 +7435,7 @@ This function should be on `erc-kill-channel-hook'."
;; Teach url.el how to open irc:// URLs with ERC.
;; To activate, customize `url-irc-function' to `url-irc-erc'.
+;; FIXME change user to nick, and use API to find server buffer
;;;###autoload
(defun erc-handle-irc-url (host port channel user password)
"Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD.
@@ -7049,9 +7457,12 @@ Otherwise, connect to HOST:PORT as USER and /join CHANNEL."
(provide 'erc)
+(require 'erc-backend)
+
;; Deprecated. We might eventually stop requiring the goodies automatically.
;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to
;; avoid a recursive require error when byte-compiling the entire package.
(require 'erc-goodies)
+(require 'erc-networks)
;;; erc.el ends here
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 27b343ad398..448b6787ee7 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -82,7 +82,11 @@ equivalent of `echo' can always be achieved by using `identity'."
It returns a formatted value that should be passed to `eshell-print'
or `eshell-printn' for display."
(if eshell-plain-echo-behavior
- (concat (apply 'eshell-flatten-and-stringify args) "\n")
+ (progn
+ ;; If the output does not end in a newline, do not emit one.
+ (setq eshell-ensure-newline-p nil)
+ (concat (apply #'eshell-flatten-and-stringify args)
+ (when output-newline "\n")))
(let ((value
(cond
((= (length args) 0) "")
@@ -109,18 +113,33 @@ or `eshell-printn' for display."
"Implementation of `echo'. See `eshell-plain-echo-behavior'."
(eshell-eval-using-options
"echo" args
- '((?n nil nil output-newline "terminate with a newline")
- (?h "help" nil nil "output this help screen")
+ '((?n nil (nil) output-newline
+ "do not output the trailing newline")
+ (?N nil (t) output-newline
+ "terminate with a newline")
+ (?E nil nil _disable-escapes
+ "don't interpret backslash escapes (default)")
+ (?h "help" nil nil
+ "output this help screen")
:preserve-args
- :usage "[-n] [object]")
- (eshell-echo args output-newline)))
+ :usage "[OPTION]... [OBJECT]...")
+ (if eshell-plain-echo-behavior
+ (eshell-echo args (if output-newline (car output-newline) t))
+ ;; In Emacs 28.1 and earlier, "-n" was used to add a newline to
+ ;; non-plain echo in Eshell. This caused confusion due to "-n"
+ ;; generally having the opposite meaning for echo. Retain this
+ ;; compatibility for the time being. For more info, see
+ ;; bug#27361.
+ (when (equal output-newline '(nil))
+ (display-warning
+ :warning "To terminate with a newline, you should use -N instead."))
+ (eshell-echo args output-newline))))
(defun eshell/printnl (&rest args)
- "Print out each of the arguments, separated by newlines."
+ "Print out each of the arguments as strings, separated by newlines."
(let ((elems (flatten-tree args)))
- (while elems
- (eshell-printn (eshell-echo (list (car elems))))
- (setq elems (cdr elems)))))
+ (dolist (elem elems)
+ (eshell-printn (eshell-stringify elem)))))
(defun eshell/listify (&rest args)
"Return the argument(s) as a single list."
@@ -136,39 +155,37 @@ or `eshell-printn' for display."
"umask" args
'((?S "symbolic" nil symbolic-p "display umask symbolically")
(?h "help" nil nil "display this usage message")
+ :preserve-args
:usage "[-S] [mode]")
- (if (or (not args) symbolic-p)
- (let ((modstr
- (concat "000"
- (format "%o"
- (logand (lognot (default-file-modes))
- 511)))))
- (setq modstr (substring modstr (- (length modstr) 3)))
- (when symbolic-p
- (let ((mode (default-file-modes)))
- (setq modstr
- (format
- "u=%s,g=%s,o=%s"
- (concat (and (= (logand mode 64) 64) "r")
- (and (= (logand mode 128) 128) "w")
- (and (= (logand mode 256) 256) "x"))
- (concat (and (= (logand mode 8) 8) "r")
- (and (= (logand mode 16) 16) "w")
- (and (= (logand mode 32) 32) "x"))
- (concat (and (= (logand mode 1) 1) "r")
- (and (= (logand mode 2) 2) "w")
- (and (= (logand mode 4) 4) "x"))))))
- (eshell-printn modstr))
- (setcar args (eshell-convert (car args)))
- (if (numberp (car args))
- (set-default-file-modes
- (- 511 (car (read-from-string
- (concat "?\\" (number-to-string (car args)))))))
- (error "Setting umask symbolically is not yet implemented"))
+ (cond
+ (symbolic-p
+ (let ((mode (default-file-modes)))
+ (eshell-printn
+ (format "u=%s,g=%s,o=%s"
+ (concat (and (= (logand mode 64) 64) "r")
+ (and (= (logand mode 128) 128) "w")
+ (and (= (logand mode 256) 256) "x"))
+ (concat (and (= (logand mode 8) 8) "r")
+ (and (= (logand mode 16) 16) "w")
+ (and (= (logand mode 32) 32) "x"))
+ (concat (and (= (logand mode 1) 1) "r")
+ (and (= (logand mode 2) 2) "w")
+ (and (= (logand mode 4) 4) "x"))))))
+ ((not args)
+ (eshell-printn (format "%03o" (logand (lognot (default-file-modes))
+ #o777))))
+ (t
+ (when (stringp (car args))
+ (if (string-match "^[0-7]+$" (car args))
+ (setcar args (string-to-number (car args) 8))
+ (error "Setting umask symbolically is not yet implemented")))
+ (set-default-file-modes (- #o777 (car args)))
(eshell-print
- "Warning: umask changed for all new files created by Emacs.\n"))
+ "Warning: umask changed for all new files created by Emacs.\n")))
nil))
+(put 'eshell/umask 'eshell-no-numeric-conversions t)
+
(provide 'em-basic)
;; Local Variables:
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index c6a51b1793e..822cc941491 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -158,14 +158,6 @@ to writing a completion function."
(eshell-cmpl--custom-variable-docstring 'pcomplete-autolist)
:type (get 'pcomplete-autolist 'custom-type))
-(defcustom eshell-cmpl-suffix-list (list ?/ ?:)
- (eshell-cmpl--custom-variable-docstring 'pcomplete-suffix-list)
- :type (get 'pcomplete-suffix-list 'custom-type)
- :group 'pcomplete)
-;; Only labeled obsolete in 26.1, but all it does it set
-;; pcomplete-suffix-list, which is itself obsolete since 24.1.
-(make-obsolete-variable 'eshell-cmpl-suffix-list nil "24.1")
-
(defcustom eshell-cmpl-recexact nil
(eshell-cmpl--custom-variable-docstring 'pcomplete-recexact)
:type (get 'pcomplete-recexact 'custom-type))
@@ -262,9 +254,6 @@ to writing a completion function."
eshell-cmpl-ignore-case)
(setq-local pcomplete-autolist
eshell-cmpl-autolist)
- (if (boundp 'pcomplete-suffix-list)
- (setq-local pcomplete-suffix-list
- eshell-cmpl-suffix-list))
(setq-local pcomplete-recexact
eshell-cmpl-recexact)
(setq-local pcomplete-man-function
@@ -311,18 +300,24 @@ to writing a completion function."
(describe-prefix-bindings)
(call-interactively 'pcomplete-help)))
+(defun eshell--pcomplete-insert-tab ()
+ (if (not pcomplete-allow-modifications)
+ (throw 'pcompleted nil)
+ (insert-and-inherit "\t")
+ (throw 'pcompleted t)))
+
(defun eshell-complete-parse-arguments ()
"Parse the command line arguments for `pcomplete-argument'."
(when (and eshell-no-completion-during-jobs
- (eshell-interactive-process))
- (insert-and-inherit "\t")
- (throw 'pcompleted t))
+ (eshell-interactive-process-p))
+ (eshell--pcomplete-insert-tab))
(let ((end (point-marker))
(begin (save-excursion (eshell-bol) (point)))
(posns (list t))
args delim)
- (when (memq this-command '(pcomplete-expand
- pcomplete-expand-and-complete))
+ (when (and pcomplete-allow-modifications
+ (memq this-command '(pcomplete-expand
+ pcomplete-expand-and-complete)))
(run-hook-with-args 'eshell-expand-input-functions begin end)
(if (= begin end)
(end-of-line))
@@ -335,14 +330,11 @@ to writing a completion function."
(setq begin (1+ (cadr delim))
args (eshell-parse-arguments begin end)))
((eq (car delim) ?\()
- (eshell-complete-lisp-symbol)
- (throw 'pcompleted t))
+ (throw 'pcompleted (elisp-completion-at-point)))
(t
- (insert-and-inherit "\t")
- (throw 'pcompleted t))))
+ (eshell--pcomplete-insert-tab))))
(when (get-text-property (1- end) 'comment)
- (insert-and-inherit "\t")
- (throw 'pcompleted t))
+ (eshell--pcomplete-insert-tab))
(let ((pos begin))
(while (< pos end)
(if (get-text-property pos 'arg-begin)
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 893cad7b4fb..5396044d8ca 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -313,7 +313,7 @@ With the following piece of advice, you can make this functionality
available in most of Emacs, with the exception of filename completion
in the minibuffer:
- (advice-add 'expand-file-name :around #'my-expand-multiple-dots)
+ (advice-add \\='expand-file-name :around #\\='my-expand-multiple-dots)
(defun my-expand-multiple-dots (orig-fun filename &rest args)
(apply orig-fun (eshell-expand-multiple-dots filename) args))"
(while (string-match "\\(?:\\`\\|/\\)\\.\\.\\(\\.+\\)\\(?:\\'\\|/\\)"
@@ -391,6 +391,10 @@ in the minibuffer:
(unless (equal curdir newdir)
(eshell-add-to-dir-ring curdir))
(let ((result (cd newdir)))
+ ;; If we're in "/" and cd to ".." or the like, make things
+ ;; less confusing by changing "/.." to "/".
+ (when (equal (file-truename result) "/")
+ (setq result (cd "/")))
(and eshell-cd-shows-directory
(eshell-printn result)))
(run-hooks 'eshell-directory-change-hook)
diff --git a/lisp/eshell/em-elecslash.el b/lisp/eshell/em-elecslash.el
new file mode 100644
index 00000000000..091acb9a861
--- /dev/null
+++ b/lisp/eshell/em-elecslash.el
@@ -0,0 +1,120 @@
+;;; em-elecslash.el --- electric forward slashes -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Sean Whitton <spwhitton@spwhitton.name>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Electric forward slash in remote Eshells.
+
+;;; Code:
+
+(require 'tramp)
+(require 'thingatpt)
+(require 'esh-cmd)
+(require 'esh-ext)
+(require 'esh-mode)
+
+;; This makes us an option when customizing `eshell-modules-list'.
+;;;###autoload
+(progn
+(defgroup eshell-elecslash nil
+ "Electric forward slash in remote Eshells.
+
+This module helps with supplying absolute file name arguments to
+remote commands. After enabling it, typing a forward slash as
+the first character of a command line argument will automatically
+insert the Tramp prefix, /method:host:. The automatic insertion
+applies only when `default-directory' is remote and the command
+is a Lisp function.
+
+The result is that in most cases of supplying absolute file name
+arguments to commands you should see the Tramp prefix inserted
+automatically only when that's what you'd reasonably expect.
+This frees you from having to keep track of whether commands are
+Lisp functions or external when typing command line arguments."
+ :tag "Electric forward slash"
+ :group 'eshell-module))
+
+;;; Functions:
+
+(defun eshell-elecslash-initialize () ;Called from `eshell-mode' via intern-soft!
+ "Initialize remote Eshell electric forward slash support."
+ (add-hook 'post-self-insert-hook
+ #'eshell-electric-forward-slash nil t))
+
+(defun eshell-electric-forward-slash ()
+ "Implementation of electric forward slash in remote Eshells.
+
+Initializing the `eshell-elecslash' module adds this function to
+`post-self-insert-hook'. Typing / or ~/ as the first character
+of a command line argument automatically inserts the Tramp prefix
+in the case that `default-directory' is remote and the command is
+a Lisp function. Typing a second forward slash undoes the
+insertion."
+ (when (eq ?/ (char-before))
+ (delete-char -1)
+ (let ((tilde-before (eq ?~ (char-before)))
+ (command (save-excursion
+ (eshell-bol)
+ (skip-syntax-forward " ")
+ (thing-at-point 'sexp))))
+ (if (and (file-remote-p default-directory)
+ ;; We can't formally parse the input. But if there is
+ ;; one of these operators behind us, then looking at
+ ;; the first command would not be sensible. So be
+ ;; conservative: don't insert the Tramp prefix if there
+ ;; are any of these operators behind us.
+ (not (looking-back (regexp-opt '("&&" "|" ";"))
+ eshell-last-output-end))
+ (or (= (point) eshell-last-output-end)
+ (and tilde-before
+ (= (1- (point)) eshell-last-output-end))
+ (and (or tilde-before
+ (eq ?\s (char-syntax (char-before))))
+ (or (eshell-find-alias-function command)
+ (and (fboundp (intern-soft command))
+ (or eshell-prefer-lisp-functions
+ (not (eshell-search-path command))))))))
+ (let ((map (make-sparse-keymap))
+ (start (if tilde-before (1- (point)) (point)))
+ (localname
+ (tramp-file-name-localname
+ (tramp-dissect-file-name default-directory))))
+ (when tilde-before (delete-char -1))
+ (insert
+ (substring default-directory 0
+ (string-search localname default-directory)))
+ (unless tilde-before (insert "/"))
+ ;; Typing a second slash undoes the insertion, for when
+ ;; you really do want to type a local absolute file name.
+ (define-key map "/" (lambda ()
+ (interactive)
+ (delete-region start (point))
+ (insert (if tilde-before "~/" "/"))))
+ (set-transient-map map))
+ (insert "/")))))
+
+(provide 'em-elecslash)
+
+;; Local Variables:
+;; generated-autoload-file: "esh-groups.el"
+;; End:
+
+;;; esh-elecslash.el ends here
diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el
new file mode 100644
index 00000000000..3db1dea5955
--- /dev/null
+++ b/lisp/eshell/em-extpipe.el
@@ -0,0 +1,204 @@
+;;; em-extpipe.el --- external shell pipelines -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Sean Whitton <spwhitton@spwhitton.name>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; When constructing shell pipelines that will move a lot of data, it
+;; is a good idea to bypass Eshell's own pipelining support and use
+;; the operating system shell's instead. This module tries to make
+;; that easy to do.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'esh-arg)
+(require 'esh-cmd)
+(require 'esh-io)
+(require 'esh-util)
+
+(eval-when-compile (require 'files-x))
+
+;;; Functions:
+
+(defun eshell-extpipe-initialize () ;Called from `eshell-mode' via intern-soft!
+ "Initialize external pipelines support."
+ (when (boundp 'eshell-special-chars-outside-quoting)
+ (setq-local
+ eshell-special-chars-outside-quoting
+ (append eshell-special-chars-outside-quoting (list ?\*))))
+ (add-hook 'eshell-parse-argument-hook
+ #'eshell-parse-external-pipeline -20 t)
+ (add-hook 'eshell-pre-rewrite-command-hook
+ #'eshell-rewrite-external-pipeline -20 t))
+
+(defmacro em-extpipe--or-with-catch (&rest disjuncts)
+ "Evaluate DISJUNCTS like `or' but catch `eshell-incomplete'.
+
+If `eshell-incomplete' is thrown during the evaluation of a
+disjunct, that disjunct yields nil."
+ (let ((result (gensym)))
+ `(let (,result)
+ (or ,@(cl-loop for disjunct in disjuncts collect
+ `(if (catch 'eshell-incomplete
+ (ignore (setq ,result ,disjunct)))
+ nil
+ ,result))))))
+
+(defun eshell-parse-external-pipeline ()
+ "Parse a pipeline intended for execution by the external shell.
+
+A sequence of arguments is rewritten to use the operating system
+shell when it contains `*|', `*<' or `*>', where the asterisk is
+preceded by whitespace or located at the start of input.
+
+The command extends to the next `|' character which is not
+preceded by an unescaped asterisk following whitespace, or the
+end of input, except that any Eshell-specific output redirections
+occurring at the end are excluded. Any other `<' or `>'
+appearing before the end of the command are treated as though
+preceded by (whitespace and) an asterisk.
+
+For example,
+
+ foo <bar *| baz >#<buffer quux>
+
+is equivalent to
+
+ sh -c \"foo <bar | baz\" >#<buffer quux>
+
+when `shell-file-name' is `sh' and `shell-command-switch' is
+`-c', but in
+
+ foo >#<buffer quux> *| baz
+
+and
+
+ foo *| baz >#<buffer quux> --some-argument
+
+the Eshell-specific redirect will be passed on to the operating
+system shell, probably leading to undesired results.
+
+This function must appear early in `eshell-parse-argument-hook'
+to ensure that operating system shell syntax is not interpreted
+as though it were Eshell syntax."
+ ;; Our goal is to wrap the external command to protect it from the
+ ;; other members of `eshell-parse-argument-hook'. We must avoid
+ ;; misinterpreting a quoted `*|', `*<' or `*>' as indicating an
+ ;; external pipeline, hence the structure of the loop in `findbeg1'.
+ (cl-flet
+ ((findbeg1 (pat &optional go (bound (point-max)))
+ (let* ((start (point))
+ (result
+ (catch 'found
+ (while (> bound (point))
+ (let* ((found
+ (save-excursion
+ (re-search-forward
+ "\\(?:#?'\\|\"\\|\\\\\\)" bound t)))
+ (next (or (and found (match-beginning 0))
+ bound)))
+ (if (re-search-forward pat next t)
+ (throw 'found (match-beginning 1))
+ (goto-char next)
+ (while (em-extpipe--or-with-catch
+ (eshell-parse-lisp-argument)
+ (eshell-parse-backslash)
+ (eshell-parse-double-quote)
+ (eshell-parse-literal-quote)))
+ ;; Guard against an infinite loop if none of
+ ;; the parsers moved us forward.
+ (unless (or (> (point) next) (eobp))
+ (forward-char 1))))))))
+ (goto-char (if (and result go) (match-end 0) start))
+ result)))
+ (unless (or eshell-current-argument eshell-current-quoted)
+ (let ((beg (point)) end
+ (next-marked (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)"))
+ (next-unmarked
+ (or (findbeg1 "\\(?:\\=\\|[^*]\\|\\S-\\*\\)\\(|\\)")
+ (point-max))))
+ (when (and next-marked (> next-unmarked next-marked)
+ (or (> next-marked (point))
+ (looking-back "\\`\\|\\s-" nil)))
+ ;; Skip to the final segment of the external pipeline.
+ (while (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*|\\)" t))
+ ;; Find output redirections.
+ (while (findbeg1
+ "\\([0-9]?>+&?[0-9]?\\s-*\\S-\\)" t next-unmarked)
+ ;; Is the output redirection Eshell-specific? We have our
+ ;; own logic, rather than calling `eshell-parse-argument',
+ ;; to avoid specifying here all the possible cars of
+ ;; parsed special references -- `get-buffer-create' etc.
+ (forward-char -1)
+ (let ((this-end
+ (save-match-data
+ (cond ((looking-at "#<")
+ (forward-char 1)
+ (1+ (eshell-find-delimiter ?\< ?\>)))
+ ((and (looking-at "/\\S-+")
+ (assoc (match-string 0)
+ eshell-virtual-targets))
+ (match-end 0))))))
+ (cond ((and this-end end)
+ (goto-char this-end))
+ (this-end
+ (goto-char this-end)
+ (setq end (match-beginning 0)))
+ (t
+ (setq end nil)))))
+ ;; We've moved past all Eshell-specific output redirections
+ ;; we could find. If there is only whitespace left, then
+ ;; `end' is right before redirections we should exclude;
+ ;; otherwise, we must include everything.
+ (unless (and end (skip-syntax-forward "\s" next-unmarked)
+ (= next-unmarked (point)))
+ (setq end next-unmarked))
+ (let ((cmd (string-trim
+ (buffer-substring-no-properties beg end))))
+ (goto-char end)
+ ;; We must now drop the asterisks, unless quoted/escaped.
+ (with-temp-buffer
+ (insert cmd)
+ (goto-char (point-min))
+ (cl-loop
+ for next = (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)" t)
+ while next do (forward-char -2) (delete-char 1))
+ (eshell-finish-arg
+ `(eshell-external-pipeline ,(buffer-string))))))))))
+
+(defun eshell-rewrite-external-pipeline (terms)
+ "Rewrite an external pipeline in TERMS as parsed by
+`eshell-parse-external-pipeline', which see."
+ (while terms
+ (when (and (listp (car terms))
+ (eq (caar terms) 'eshell-external-pipeline))
+ (with-connection-local-variables
+ (setcdr terms (cl-list*
+ shell-command-switch (cadar terms) (cdr terms)))
+ (setcar terms shell-file-name)))
+ (setq terms (cdr terms))))
+
+(defsubst eshell-external-pipeline (&rest _args)
+ "Stub to generate an error if a pipeline is not rewritten."
+ (error "Unhandled external pipeline in input text"))
+
+(provide 'em-extpipe)
+;;; esh-extpipe.el ends here
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index 842f27a4920..58b7a83c091 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -183,6 +183,10 @@ interpretation."
(defvar eshell-glob-matches)
(defvar message-shown)
+(defvar eshell-glob-recursive-alist
+ '(("**/" . recurse)
+ ("***/" . recurse-symlink)))
+
(defun eshell-glob-regexp (pattern)
"Convert glob-pattern PATTERN to a regular expression.
The basic syntax is:
@@ -232,8 +236,86 @@ resulting regular expression."
(regexp-quote (substring pattern matched-in-pattern))
"\\'")))
+(defun eshell-glob-convert-1 (glob &optional last)
+ "Convert a GLOB matching a single element of a file name to regexps.
+If LAST is non-nil, this glob is the last element of a file name.
+
+The result is a pair of regexps, the first for file names to
+include, and the second for ones to exclude."
+ (let ((len (length glob)) (index 1) (incl glob) excl)
+ ;; We can't use `directory-file-name' because it strips away text
+ ;; properties in the string.
+ (let ((last (1- (length incl))))
+ (when (eq (aref incl last) ?/)
+ (setq incl (substring incl 0 last))))
+ ;; Split the glob if it contains a negation like x~y.
+ (while (and (eq incl glob)
+ (setq index (string-search "~" glob index)))
+ (if (or (get-text-property index 'escaped glob)
+ (or (= (1+ index) len)))
+ (setq index (1+ index))
+ (setq incl (substring glob 0 index)
+ excl (substring glob (1+ index)))))
+ (setq incl (eshell-glob-regexp incl)
+ excl (and excl (eshell-glob-regexp excl)))
+ ;; Exclude dot files if requested.
+ (if (or eshell-glob-include-dot-files
+ (eq (aref glob 0) ?.))
+ (unless (or eshell-glob-include-dot-dot
+ (not last))
+ (setq excl (if excl
+ (concat "\\(\\`\\.\\.?\\'\\|" excl "\\)")
+ "\\`\\.\\.?\\'")))
+ (setq excl (if excl
+ (concat "\\(\\`\\.\\|" excl "\\)")
+ "\\`\\.")))
+ (cons incl excl)))
+
+(defun eshell-glob-convert (glob)
+ "Convert an Eshell glob-pattern GLOB to regexps.
+The result is a list of three elements:
+
+1. The base directory to search in.
+
+2. A list containing elements of the following forms:
+
+ * Regexp pairs as generated by `eshell-glob-convert-1'.
+
+ * `recurse', indicating that searches should recurse into
+ subdirectories.
+
+ * `recurse-symlink', like `recurse', but also following
+ symlinks.
+
+3. A boolean indicating whether to match directories only."
+ (let ((globs (eshell-split-path glob))
+ (isdir (eq (aref glob (1- (length glob))) ?/))
+ start-dir result last-saw-recursion)
+ (if (and (cdr globs)
+ (file-name-absolute-p (car globs)))
+ (setq start-dir (car globs)
+ globs (cdr globs))
+ (setq start-dir "."))
+ (while globs
+ (if-let ((recurse (cdr (assoc (car globs)
+ eshell-glob-recursive-alist))))
+ (if last-saw-recursion
+ (setcar result recurse)
+ (push recurse result)
+ (setq last-saw-recursion t))
+ (push (eshell-glob-convert-1 (car globs) (null (cdr globs)))
+ result)
+ (setq last-saw-recursion nil))
+ (setq globs (cdr globs)))
+ (list (file-name-as-directory start-dir)
+ (nreverse result)
+ isdir)))
+
(defun eshell-extended-glob (glob)
- "Return a list of files generated from GLOB, perhaps looking for DIRS-ONLY.
+ "Return a list of files matched by GLOB.
+If no files match, signal an error (if `eshell-error-if-no-glob'
+is non-nil), or otherwise return GLOB itself.
+
This function almost fully supports zsh style filename generation
syntax. Things that are not supported are:
@@ -243,20 +325,11 @@ syntax. Things that are not supported are:
foo~x(a|b) (a|b) will be interpreted as a predicate/modifier list
Mainly they are not supported because file matching is done with Emacs
-regular expressions, and these cannot support the above constructs.
-
-If this routine fails, it returns nil. Otherwise, it returns a list
-the form:
-
- (INCLUDE-REGEXP EXCLUDE-REGEXP (PRED-FUNC-LIST) (MOD-FUNC-LIST))"
- (let ((paths (eshell-split-path glob))
+regular expressions, and these cannot support the above constructs."
+ (let ((globs (eshell-glob-convert glob))
eshell-glob-matches message-shown)
(unwind-protect
- (if (and (cdr paths)
- (file-name-absolute-p (car paths)))
- (eshell-glob-entries (file-name-as-directory (car paths))
- (cdr paths))
- (eshell-glob-entries (file-name-as-directory ".") paths))
+ (apply #'eshell-glob-entries globs)
(if message-shown
(message nil)))
(or (and eshell-glob-matches (sort eshell-glob-matches #'string<))
@@ -265,94 +338,60 @@ the form:
glob))))
;; FIXME does this really need to abuse eshell-glob-matches, message-shown?
-(defun eshell-glob-entries (path globs &optional recurse-p)
- "Glob the entries in PATH, possibly recursing if RECURSE-P is non-nil."
+(defun eshell-glob-entries (path globs only-dirs)
+ "Match the entries in PATH against GLOBS.
+GLOBS is a list of globs as converted by `eshell-glob-convert',
+which see.
+
+If ONLY-DIRS is non-nil, only match directories; otherwise, match
+directories and files."
(let* ((entries (ignore-errors
- (file-name-all-completions "" path)))
- (case-fold-search eshell-glob-case-insensitive)
- (glob (car globs))
- (len (length glob))
- dirs rdirs
- incl excl
- name isdir pathname)
- (while (cond
- ((and (= len 3) (equal glob "**/"))
- (setq recurse-p 2
- globs (cdr globs)
- glob (car globs)
- len (length glob)))
- ((and (= len 4) (equal glob "***/"))
- (setq recurse-p 3
- globs (cdr globs)
- glob (car globs)
- len (length glob)))))
- (if (and recurse-p (not glob))
- (error "`**' cannot end a globbing pattern"))
- (let ((index 1))
- (setq incl glob)
- (while (and (eq incl glob)
- (setq index (string-search "~" glob index)))
- (if (or (get-text-property index 'escaped glob)
- (or (= (1+ index) len)))
- (setq index (1+ index))
- (setq incl (substring glob 0 index)
- excl (substring glob (1+ index))))))
- ;; can't use `directory-file-name' because it strips away text
- ;; properties in the string
- (let ((len (1- (length incl))))
- (if (eq (aref incl len) ?/)
- (setq incl (substring incl 0 len)))
- (when excl
- (setq len (1- (length excl)))
- (if (eq (aref excl len) ?/)
- (setq excl (substring excl 0 len)))))
- (setq incl (eshell-glob-regexp incl)
- excl (and excl (eshell-glob-regexp excl)))
- (if (or eshell-glob-include-dot-files
- (eq (aref glob 0) ?.))
- (unless (or eshell-glob-include-dot-dot
- (cdr globs))
- (setq excl (if excl
- (concat "\\(\\`\\.\\.?\\'\\|" excl "\\)")
- "\\`\\.\\.?\\'")))
- (setq excl (if excl
- (concat "\\(\\`\\.\\|" excl "\\)")
- "\\`\\.")))
+ (file-name-all-completions "" path)))
+ (case-fold-search eshell-glob-case-insensitive)
+ glob glob-remainder recurse-p)
+ (if (rassq (car globs) eshell-glob-recursive-alist)
+ (setq recurse-p (car globs)
+ glob (or (cadr globs)
+ (eshell-glob-convert-1 "*" t))
+ glob-remainder (cddr globs))
+ (setq glob (car globs)
+ glob-remainder (cdr globs)))
(when (and recurse-p eshell-glob-show-progress)
(message "Building file list...%d so far: %s"
- (length eshell-glob-matches) path)
+ (length eshell-glob-matches) path)
(setq message-shown t))
- (if (equal path "./") (setq path ""))
- (while entries
- (setq name (car entries)
- len (length name)
- isdir (eq (aref name (1- len)) ?/))
- (if (let ((fname (directory-file-name name)))
- (and (not (and excl (string-match excl fname)))
- (string-match incl fname)))
- (if (cdr globs)
- (if isdir
- (setq dirs (cons (concat path name) dirs)))
- (setq eshell-glob-matches
- (cons (concat path name) eshell-glob-matches))))
- (if (and recurse-p isdir
- (or (> len 3)
- (not (or (and (= len 2) (equal name "./"))
- (and (= len 3) (equal name "../")))))
- (setq pathname (concat path name))
- (not (and (= recurse-p 2)
- (file-symlink-p
- (directory-file-name pathname)))))
- (setq rdirs (cons pathname rdirs)))
- (setq entries (cdr entries)))
- (setq dirs (nreverse dirs)
- rdirs (nreverse rdirs))
- (while dirs
- (eshell-glob-entries (car dirs) (cdr globs))
- (setq dirs (cdr dirs)))
- (while rdirs
- (eshell-glob-entries (car rdirs) globs recurse-p)
- (setq rdirs (cdr rdirs)))))
+ (when (equal path "./") (setq path ""))
+ (let ((incl (car glob))
+ (excl (cdr glob))
+ dirs rdirs)
+ (dolist (name entries)
+ (let* ((len (length name))
+ (isdir (eq (aref name (1- len)) ?/))
+ pathname)
+ (when (let ((fname (directory-file-name name)))
+ (and (not (and excl (string-match excl fname)))
+ (string-match incl fname)))
+ (if glob-remainder
+ (when isdir
+ (push (concat path name) dirs))
+ (when (or (not only-dirs)
+ (and isdir
+ (not (and (eq recurse-p 'recurse)
+ (file-symlink-p
+ (directory-file-name
+ (concat path name)))))))
+ (push (concat path name) eshell-glob-matches))))
+ (when (and recurse-p isdir
+ (not (member name '("./" "../")))
+ (setq pathname (concat path name))
+ (not (and (eq recurse-p 'recurse)
+ (file-symlink-p
+ (directory-file-name pathname)))))
+ (push pathname rdirs))))
+ (dolist (dir (nreverse dirs))
+ (eshell-glob-entries dir glob-remainder only-dirs))
+ (dolist (rdir (nreverse rdirs))
+ (eshell-glob-entries rdir globs only-dirs)))))
(provide 'em-glob)
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index 16abf044899..1877749c5cf 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -104,7 +104,7 @@ in bash, and any other non-nil value mirrors the \"ignoredups\"
value."
:type '(choice (const :tag "Don't ignore anything" nil)
(const :tag "Ignore consecutive duplicates" t)
- (const :tag "Only keep last duplicate" 'erase)))
+ (const :tag "Only keep last duplicate" erase)))
(defcustom eshell-save-history-on-exit t
"Determine if history should be automatically saved.
@@ -341,7 +341,7 @@ unless a different file is specified on the command line.")
(error "No history"))
(let (length file)
(when (and args (string-match "^[0-9]+$" (car args)))
- (setq length (min (eshell-convert (car args))
+ (setq length (min (string-to-number (car args))
(ring-length eshell-history-ring))
args (cdr args)))
(and length
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 846f3d5e290..bebb0d81b5b 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -100,15 +100,14 @@ faster and conserves more memory."
:type 'boolean)
(defface eshell-ls-directory
- '((((class color) (background light)) (:foreground "Blue" :weight bold))
- (((class color) (background dark)) (:foreground "SkyBlue" :weight bold))
- (t (:weight bold)))
- "The face used for highlighting directories.")
+ '((t (:inherit font-lock-function-name-face)))
+ "The face used for highlighting directories."
+ :version "29.1")
(defface eshell-ls-symlink
- '((((class color) (background light)) (:foreground "Dark Cyan" :weight bold))
- (((class color) (background dark)) (:foreground "Cyan" :weight bold)))
- "The face used for highlighting symbolic links.")
+ '((t (:inherit font-lock-keyword-face)))
+ "The face used for highlighting symbolic links."
+ :version "29.1")
(defface eshell-ls-executable
'((((class color) (background light)) (:foreground "ForestGreen" :weight bold))
@@ -801,7 +800,7 @@ to use, and each member of which is the width of that column
(+ 2 (length (car file))))
files))
;; must account for the added space...
- (max-width (+ (window-width) 2))
+ (max-width (+ (window-body-width nil 'remap) 2))
(best-width 0)
col-widths)
@@ -846,7 +845,7 @@ to use, and each member of which is the width of that column
(lambda (file)
(+ 2 (length (car file))))
files))
- (max-width (+ (window-width) 2))
+ (max-width (+ (window-body-width nil 'remap) 2))
col-widths
colw)
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index 216c71f59e4..b4ef154f8c3 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -68,7 +68,7 @@ ordinary strings."
(defcustom eshell-predicate-alist
'((?/ . (eshell-pred-file-type ?d)) ; directories
(?. . (eshell-pred-file-type ?-)) ; regular files
- (?s . (eshell-pred-file-type ?s)) ; sockets
+ (?= . (eshell-pred-file-type ?s)) ; sockets
(?p . (eshell-pred-file-type ?p)) ; named pipes
(?@ . (eshell-pred-file-type ?l)) ; symbolic links
(?% . (eshell-pred-file-type ?%)) ; allow user to specify (c def.)
@@ -88,17 +88,17 @@ ordinary strings."
(if (file-exists-p file)
(= (file-attribute-user-id (file-attributes file))
(user-uid)))))
- ;; (?G . (lambda (file) ; owned by effective gid
- ;; (if (file-exists-p file)
- ;; (= (file-attribute-user-id (file-attributes file))
- ;; (user-uid)))))
+ (?G . (lambda (file) ; owned by effective gid
+ (if (file-exists-p file)
+ (= (file-attribute-group-id (file-attributes file))
+ (group-gid)))))
(?* . (lambda (file)
(and (file-regular-p file)
(not (file-symlink-p file))
(file-executable-p file))))
(?l . (eshell-pred-file-links))
- (?u . (eshell-pred-user-or-group ?u "user" 2 'eshell-user-id))
- (?g . (eshell-pred-user-or-group ?g "group" 3 'eshell-group-id))
+ (?u . (eshell-pred-user-or-group ?u "user" 2 #'eshell-user-id))
+ (?g . (eshell-pred-user-or-group ?g "group" 3 #'eshell-group-id))
(?a . (eshell-pred-file-time ?a "access" 4))
(?m . (eshell-pred-file-time ?m "modification" 5))
(?c . (eshell-pred-file-time ?c "change" 6))
@@ -111,28 +111,23 @@ The format of each entry is
:risky t)
(defcustom eshell-modifier-alist
- '((?E . (lambda (lst)
- (mapcar
- (lambda (str)
- (eshell-stringify
- (car (eshell-parse-argument str))))
- lst)))
+ '((?E . (lambda (lst) (mapcar #'eshell-eval-argument lst)))
(?L . (lambda (lst) (mapcar #'downcase lst)))
(?U . (lambda (lst) (mapcar #'upcase lst)))
(?C . (lambda (lst) (mapcar #'capitalize lst)))
(?h . (lambda (lst) (mapcar #'file-name-directory lst)))
- (?i . (eshell-include-members))
- (?x . (eshell-include-members t))
+ (?i . (eshell-include-members ?i))
+ (?x . (eshell-include-members ?x t))
(?r . (lambda (lst) (mapcar #'file-name-sans-extension lst)))
(?e . (lambda (lst) (mapcar #'file-name-extension lst)))
(?t . (lambda (lst) (mapcar #'file-name-nondirectory lst)))
(?q . (lambda (lst) (mapcar #'eshell-escape-arg lst)))
(?u . (lambda (lst) (seq-uniq lst)))
(?o . (lambda (lst) (sort lst #'string-lessp)))
- (?O . (lambda (lst) (nreverse (sort lst #'string-lessp))))
+ (?O . (lambda (lst) (sort lst #'string-greaterp)))
(?j . (eshell-join-members))
(?S . (eshell-split-members))
- (?R . 'reverse)
+ (?R . #'reverse)
(?g . (progn
(forward-char)
(if (eq (char-before) ?s)
@@ -142,7 +137,7 @@ The format of each entry is
"A list of modifiers than can be applied to an argument expansion.
The format of each entry is
- (CHAR ENTRYWISE-P MODIFIER-FUNC-SEXP)"
+ (CHAR . MODIFIER-FUNC-SEXP)"
:type '(repeat (cons character sexp))
:risky t)
@@ -166,6 +161,7 @@ PERMISSION BITS (for owner/group/world):
OWNERSHIP:
U owned by effective uid
+ G owned by effective gid
u(UID|\\='user\\=') owned by UID/user
g(GID|\\='group\\=') owned by GID/group
@@ -217,12 +213,28 @@ FOR LISTS OF ARGUMENTS:
i/PAT/ exclude all members not matching PAT
x/PAT/ exclude all members matching PAT
- s/pat/match/ substitute PAT with MATCH
- g/pat/match/ substitute PAT with MATCH for all occurrences
+ s/pat/match/ substitute PAT with MATCH
+ gs/pat/match/ substitute PAT with MATCH for all occurrences
EXAMPLES:
*.c(:o) sorted list of .c files")
+(defvar eshell-pred-delimiter-pairs
+ '((?\( . ?\))
+ (?\[ . ?\])
+ (?\< . ?\>)
+ (?\{ . ?\})
+ (?\' . ?\')
+ (?\" . ?\")
+ (?/ . ?/)
+ (?| . ?|))
+ "A list of delimiter pairs that can be used in argument predicates/modifiers.
+Each element is of the form (OPEN . CLOSE), where OPEN and CLOSE
+are characters representing the opening and closing delimiter,
+respectively.")
+
+(defvar eshell-error-if-no-glob) ; Defined in em-glob.el.
+
(defvar-keymap eshell-pred-mode-map
"C-c M-q" #'eshell-display-predicate-help
"C-c M-m" #'eshell-display-modifier-help)
@@ -253,14 +265,19 @@ EXAMPLES:
#'eshell-parse-arg-modifier t t)
(eshell-pred-mode))
-(defun eshell-apply-modifiers (lst predicates modifiers)
- "Apply to list LST a series of PREDICATES and MODIFIERS."
+(defun eshell-apply-modifiers (lst predicates modifiers string-desc)
+ "Apply to list LST a series of PREDICATES and MODIFIERS.
+STRING-DESC is the original string defining these predicates and
+modifiers."
(let (stringified)
(if (stringp lst)
(setq lst (list lst)
stringified t))
(when (listp lst)
- (setq lst (eshell-winnow-list lst nil predicates))
+ (when lst
+ (setq lst (or (eshell-winnow-list lst nil predicates)
+ (when eshell-error-if-no-glob
+ (error "No matches found: (%s)" string-desc)))))
(while modifiers
(setq lst (funcall (car modifiers) lst)
modifiers (cdr modifiers)))
@@ -280,7 +297,8 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
(when (eshell-arg-delimiter (1+ end))
(save-restriction
(narrow-to-region (point) end)
- (let* ((modifiers (eshell-parse-modifiers))
+ (let* ((modifier-string (buffer-string))
+ (modifiers (eshell-parse-modifiers))
(preds (car modifiers))
(mods (cdr modifiers)))
(if (or preds mods)
@@ -292,7 +310,7 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
(list
(lambda (lst)
(eshell-apply-modifiers
- lst preds mods))))))))
+ lst preds mods modifier-string))))))))
(goto-char (1+ end))
(eshell-finish-arg))))))
@@ -360,46 +378,78 @@ resultant list of strings."
(defun eshell-add-pred-func (pred funcs negate follow)
"Add the predicate function PRED to FUNCS."
- (if negate
- (setq pred (lambda (file)
- (not (funcall pred file)))))
- (if follow
- (setq pred (lambda (file)
- (funcall pred (file-truename file)))))
+ (when negate
+ (setq pred (let ((pred pred))
+ (lambda (file) (not (funcall pred file))))))
+ (when follow
+ (setq pred (let ((pred pred))
+ (lambda (file) (funcall pred (file-truename file))))))
(cons pred funcs))
+(defun eshell-get-comparison-modifier-argument (&optional functions)
+ "Starting at point, get the comparison modifier argument, if any.
+These are the -/+ characters, corresponding to `<' and `>',
+respectively. If no comparison modifier is at point, return `='.
+
+FUNCTIONS, if non-nil, is a list of comparison functions,
+specified as (LESS-THAN GREATER-THAN EQUAL-TO)."
+ (let ((functions (or functions (list #'< #'> #'=))))
+ (if (memq (char-after) '(?- ?+))
+ (prog1
+ (if (eq (char-after) ?-) (nth 0 functions) (nth 1 functions))
+ (forward-char))
+ (nth 2 functions))))
+
+(defun eshell-get-numeric-modifier-argument ()
+ "Starting at point, get the numeric modifier argument, if any.
+If a number is found, update point to just after the number."
+ (when (looking-at "[0-9]+")
+ (prog1
+ (string-to-number (match-string 0))
+ (goto-char (match-end 0)))))
+
+(defun eshell-get-delimited-modifier-argument (&optional chained-p)
+ "Starting at point, get the delimited modifier argument, if any.
+If the character after point is a predicate/modifier
+delimiter (see `eshell-pred-delimiter-pairs', read the value of
+the argument and update point to be just after the closing
+delimiter.
+
+If CHAINED-P is true, then another delimited modifier argument
+will immediately follow this one. In this case, when the opening
+and closing delimiters are the same, update point to be just
+before the closing delimiter. This allows modifiers like
+`:s/match/repl' to work as expected."
+ (when-let* ((open (char-after))
+ (close (cdr (assoc open eshell-pred-delimiter-pairs)))
+ (end (eshell-find-delimiter open close nil nil t)))
+ (prog1
+ (replace-regexp-in-string
+ (rx-to-string `(seq "\\" (group (or "\\" ,open ,close)))) "\\1"
+ (buffer-substring-no-properties (1+ (point)) end))
+ (goto-char (if (and chained-p (eq open close))
+ end
+ (1+ end))))))
+
(defun eshell-pred-user-or-group (mod-char mod-type attr-index get-id-func)
"Return a predicate to test whether a file match a given user/group id."
- (let (ugid open close end)
- (if (looking-at "[0-9]+")
- (progn
- (setq ugid (string-to-number (match-string 0)))
- (goto-char (match-end 0)))
- (setq open (char-after))
- (if (setq close (memq open '(?\( ?\[ ?\< ?\{)))
- (setq close (car (last '(?\) ?\] ?\> ?\})
- (length close))))
- (setq close open))
- (forward-char)
- (setq end (eshell-find-delimiter open close))
- (unless end
- (error "Malformed %s name string for modifier `%c'"
- mod-type mod-char))
- (setq ugid
- (funcall get-id-func (buffer-substring (point) end)))
- (goto-char (1+ end)))
+ (let ((ugid (eshell-get-numeric-modifier-argument)))
+ (unless ugid
+ (let ((ugname (or (eshell-get-delimited-modifier-argument)
+ (error "Malformed %s name string for modifier `%c'"
+ mod-type mod-char))))
+ (setq ugid (funcall get-id-func ugname))))
(unless ugid
(error "Unknown %s name specified for modifier `%c'"
mod-type mod-char))
(lambda (file)
- (let ((attrs (file-attributes file)))
- (if attrs
- (= (nth attr-index attrs) ugid))))))
+ (when-let ((attrs (file-attributes file)))
+ (= (nth attr-index attrs) ugid)))))
(defun eshell-pred-file-time (mod-char mod-type attr-index)
"Return a predicate to test whether a file matches a certain time."
(let* ((quantum 86400)
- qual when open close end)
+ qual when)
(when (memq (char-after) '(?M ?w ?h ?m ?s))
(setq quantum (char-after))
(cond
@@ -414,36 +464,21 @@ resultant list of strings."
((eq quantum ?s)
(setq quantum 1)))
(forward-char))
- (when (memq (char-after) '(?+ ?-))
- (setq qual (char-after))
- (forward-char))
- (if (looking-at "[0-9]+")
- (progn
- (setq when (time-since (* (string-to-number (match-string 0))
- quantum)))
- (goto-char (match-end 0)))
- (setq open (char-after))
- (if (setq close (memq open '(?\( ?\[ ?\< ?\{)))
- (setq close (car (last '(?\) ?\] ?\> ?\})
- (length close))))
- (setq close open))
- (forward-char)
- (setq end (eshell-find-delimiter open close))
- (unless end
- (error "Malformed %s time modifier `%c'" mod-type mod-char))
- (let* ((file (buffer-substring (point) end))
- (attrs (file-attributes file)))
- (unless attrs
- (error "Cannot stat file `%s'" file))
- (setq when (nth attr-index attrs)))
- (goto-char (1+ end)))
- (let ((f (cond ((eq qual ?-) #'time-less-p)
- ((eq qual ?+) (lambda (a b) (time-less-p b a)))
- (#'time-equal-p))))
- (lambda (file)
- (let ((attrs (file-attributes file)))
- (if attrs
- (funcall f when (nth attr-index attrs))))))))
+ (setq qual (eshell-get-comparison-modifier-argument
+ (list #'time-less-p
+ (lambda (a b) (time-less-p b a))
+ #'time-equal-p)))
+ (if-let ((number (eshell-get-numeric-modifier-argument)))
+ (setq when (time-since (* number quantum)))
+ (let* ((file (or (eshell-get-delimited-modifier-argument)
+ (error "Malformed %s time modifier `%c'"
+ mod-type mod-char)))
+ (attrs (or (file-attributes file)
+ (error "Cannot stat file `%s'" file))))
+ (setq when (nth attr-index attrs))))
+ (lambda (file)
+ (when-let ((attrs (file-attributes file)))
+ (funcall qual when (nth attr-index attrs))))))
(defun eshell-pred-file-type (type)
"Return a test which tests that the file is of a certain TYPE.
@@ -458,36 +493,23 @@ that `ls -l' will show in the first column of its display."
'(?b ?c)
(list type))))
(lambda (file)
- (let ((attrs (eshell-file-attributes (directory-file-name file))))
- (if attrs
- (memq (aref (file-attribute-modes attrs) 0) set))))))
+ (when-let ((attrs (eshell-file-attributes (directory-file-name file))))
+ (memq (aref (file-attribute-modes attrs) 0) set)))))
(defsubst eshell-pred-file-mode (mode)
"Return a test which tests that MODE pertains to the file."
(lambda (file)
- (let ((modes (file-modes file 'nofollow)))
- (if modes
- (not (zerop (logand mode modes)))))))
+ (when-let ((modes (file-modes file 'nofollow)))
+ (not (zerop (logand mode modes))))))
(defun eshell-pred-file-links ()
"Return a predicate to test whether a file has a given number of links."
- (let (qual amount)
- (when (memq (char-after) '(?- ?+))
- (setq qual (char-after))
- (forward-char))
- (unless (looking-at "[0-9]+")
- (error "Invalid file link count modifier `l'"))
- (setq amount (string-to-number (match-string 0)))
- (goto-char (match-end 0))
- (let ((f (if (eq qual ?-)
- #'<
- (if (eq qual ?+)
- #'>
- #'=))))
- (lambda (file)
- (let ((attrs (eshell-file-attributes file)))
- (if attrs
- (funcall f (file-attribute-link-number attrs) amount)))))))
+ (let ((qual (eshell-get-comparison-modifier-argument))
+ (amount (or (eshell-get-numeric-modifier-argument)
+ (error "Invalid file link count modifier `l'"))))
+ (lambda (file)
+ (when-let ((attrs (eshell-file-attributes file)))
+ (funcall qual (file-attribute-link-number attrs) amount)))))
(defun eshell-pred-file-size ()
"Return a predicate to test whether a file is of a given size."
@@ -502,89 +524,52 @@ that `ls -l' will show in the first column of its display."
((eq qual ?p)
(setq quantum 512)))
(forward-char))
- (when (memq (char-after) '(?- ?+))
- (setq qual (char-after))
- (forward-char))
- (unless (looking-at "[0-9]+")
- (error "Invalid file size modifier `L'"))
- (setq amount (* (string-to-number (match-string 0)) quantum))
- (goto-char (match-end 0))
- (let ((f (if (eq qual ?-)
- #'<
- (if (eq qual ?+)
- #'>
- #'=))))
- (lambda (file)
- (let ((attrs (eshell-file-attributes file)))
- (if attrs
- (funcall f (file-attribute-size attrs) amount)))))))
+ (setq qual (eshell-get-comparison-modifier-argument))
+ (setq amount (* (or (eshell-get-numeric-modifier-argument)
+ (error "Invalid file size modifier `L'"))
+ quantum))
+ (lambda (file)
+ (when-let ((attrs (eshell-file-attributes file)))
+ (funcall qual (file-attribute-size attrs) amount)))))
(defun eshell-pred-substitute (&optional repeat)
"Return a modifier function that will substitute matches."
- (let ((delim (char-after))
- match replace end)
- (forward-char)
- (setq end (eshell-find-delimiter delim delim nil nil t)
- match (buffer-substring-no-properties (point) end))
- (goto-char (1+ end))
- (setq end (eshell-find-delimiter delim delim nil nil t)
- replace (buffer-substring-no-properties (point) end))
- (goto-char (1+ end))
- (if repeat
- (lambda (lst)
- (mapcar
- (lambda (str)
- (let ((i 0))
- (while (setq i (string-match match str i))
- (setq str (replace-match replace t nil str))))
- str)
- lst))
- (lambda (lst)
- (mapcar
- (lambda (str)
- (if (string-match match str)
- (setq str (replace-match replace t nil str))
- (error (concat str ": substitution failed")))
- str)
- lst)))))
-
-(defun eshell-include-members (&optional invert-p)
- "Include only Lisp members matching a regexp."
- (let ((delim (char-after))
- regexp end)
- (forward-char)
- (setq end (eshell-find-delimiter delim delim nil nil t)
- regexp (buffer-substring-no-properties (point) end))
- (goto-char (1+ end))
- (let ((predicates
- (list (if invert-p
- (lambda (elem) (not (string-match regexp elem)))
- (lambda (elem) (string-match regexp elem))))))
- (lambda (lst)
- (eshell-winnow-list lst nil predicates)))))
+ (let* ((match (or (eshell-get-delimited-modifier-argument t)
+ (error "Malformed pattern string for modifier `s'")))
+ (replace (or (eshell-get-delimited-modifier-argument)
+ (error "Malformed replace string for modifier `s'")))
+ (function (if repeat
+ (lambda (str)
+ (replace-regexp-in-string match replace str t))
+ (lambda (str)
+ (if (string-match match str)
+ (replace-match replace t nil str)
+ (error (concat str ": substitution failed")))))))
+ (lambda (lst) (mapcar function lst))))
+
+(defun eshell-include-members (mod-char &optional invert-p)
+ "Include only Lisp members matching a regexp.
+If INVERT-P is non-nil, include only members not matching a regexp."
+ (let* ((regexp (or (eshell-get-delimited-modifier-argument)
+ (error "Malformed pattern string for modifier `%c'"
+ mod-char)))
+ (predicates
+ (list (if invert-p
+ (lambda (elem) (not (string-match regexp elem)))
+ (lambda (elem) (string-match regexp elem))))))
+ (lambda (lst)
+ (eshell-winnow-list lst nil predicates))))
(defun eshell-join-members ()
"Return a modifier function that join matches."
- (let ((delim (char-after))
- str end)
- (if (not (memq delim '(?' ?/)))
- (setq delim " ")
- (forward-char)
- (setq end (eshell-find-delimiter delim delim nil nil t)
- str (buffer-substring-no-properties (point) end))
- (goto-char (1+ end)))
+ (let ((str (or (eshell-get-delimited-modifier-argument)
+ " ")))
(lambda (lst)
(mapconcat #'identity lst str))))
(defun eshell-split-members ()
"Return a modifier function that splits members."
- (let ((delim (char-after))
- sep end)
- (when (memq delim '(?' ?/))
- (forward-char)
- (setq end (eshell-find-delimiter delim delim nil nil t)
- sep (buffer-substring-no-properties (point) end))
- (goto-char (1+ end)))
+ (let ((sep (eshell-get-delimited-modifier-argument)))
(lambda (lst)
(mapcar
(lambda (str)
diff --git a/lisp/eshell/em-rebind.el b/lisp/eshell/em-rebind.el
index f24758d4e34..2b56c9e8444 100644
--- a/lisp/eshell/em-rebind.el
+++ b/lisp/eshell/em-rebind.el
@@ -238,7 +238,7 @@ lock it at that."
Sends an EOF only if point is at the end of the buffer and there is no
input."
(interactive "p")
- (let ((proc (eshell-interactive-process)))
+ (let ((proc (eshell-head-process)))
(if (eobp)
(cond
((/= (point) eshell-last-output-end)
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index e8459513f39..e0bcd8b099f 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -113,27 +113,13 @@ Comments begin with `#'."
(defun eshell/source (&rest args)
"Source a file in a subshell environment."
- (eshell-eval-using-options
- "source" args
- '((?h "help" nil nil "show this usage screen")
- :show-usage
- :usage "FILE [ARGS]
-Invoke the Eshell commands in FILE in a subshell, binding ARGS to $1,
-$2, etc.")
- (eshell-source-file (car args) (cdr args) t)))
+ (eshell-source-file (car args) (cdr args) t))
(put 'eshell/source 'eshell-no-numeric-conversions t)
(defun eshell/. (&rest args)
"Source a file in the current environment."
- (eshell-eval-using-options
- "." args
- '((?h "help" nil nil "show this usage screen")
- :show-usage
- :usage "FILE [ARGS]
-Invoke the Eshell commands in FILE within the current shell
-environment, binding ARGS to $1, $2, etc.")
- (eshell-source-file (car args) (cdr args))))
+ (eshell-source-file (car args) (cdr args)))
(put 'eshell/. 'eshell-no-numeric-conversions t)
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index e34c5ae47ce..a4fa699aa90 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -56,7 +56,7 @@ which commands are considered visual in nature."
:type 'hook)
(defcustom eshell-visual-commands
- '("vi" ; what is going on??
+ '("vi" "vim" ; what is going on??
"screen" "tmux" "top" "htop" ; ok, a valid program...
"less" "more" ; M-x view-file
"lynx" "links" "ncftp" ; eww, ange-ftp
@@ -67,7 +67,7 @@ Commands listed here are run in a term buffer.
See also `eshell-visual-subcommands' and `eshell-visual-options'."
:type '(repeat string)
- :version "27.1")
+ :version "29.1")
(defcustom eshell-visual-subcommands
nil
@@ -186,8 +186,10 @@ allowed."
(set-process-sentinel proc #'eshell-term-sentinel)
(error "Failed to invoke visual command")))
(term-char-mode)
- (if eshell-escape-control-x
- (term-set-escape-char ?\C-x))))
+ (when eshell-escape-control-x
+ ;; Don't drop existing escape char.
+ (let (term-escape-char)
+ (term-set-escape-char ?\C-x)))))
nil)
;; Process sentinels receive two arguments.
@@ -224,7 +226,7 @@ the buffer."
; (defun eshell-term-send-raw-string (chars)
; (goto-char eshell-last-output-end)
-; (process-send-string (eshell-interactive-process) chars))
+; (process-send-string (eshell-head-process) chars))
; (defun eshell-term-send-raw ()
; "Send the last character typed through the terminal-emulator
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index e9018bdb934..aebbc36e71d 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -61,37 +61,33 @@
"Alias \"su\" to call TRAMP.
Uses the system su through TRAMP's su method."
- (setq args (eshell-stringify-list (flatten-tree args)))
- (let ((orig-args (copy-tree args)))
- (eshell-eval-using-options
- "su" args
- '((?h "help" nil nil "show this usage screen")
- (?l "login" nil login "provide a login environment")
- (? nil nil login "provide a login environment")
- :usage "[- | -l | --login] [USER]
+ (eshell-eval-using-options
+ "su" args
+ '((?h "help" nil nil "show this usage screen")
+ (?l "login" nil login "provide a login environment")
+ (? nil nil login "provide a login environment")
+ :usage "[- | -l | --login] [USER]
Become another USER during a login session.")
- (throw 'eshell-replace-command
- (let ((user "root")
- (host (or (file-remote-p default-directory 'host)
- "localhost"))
- (dir (file-local-name (expand-file-name default-directory)))
- (prefix (file-remote-p default-directory)))
- (dolist (arg args)
- (if (string-equal arg "-") (setq login t) (setq user arg)))
- ;; `eshell-eval-using-options' does not handle "-".
- (if (member "-" orig-args) (setq login t))
- (if login (setq dir "~/"))
- (if (and prefix
- (or
- (not (string-equal
- "su" (file-remote-p default-directory 'method)))
- (not (string-equal
- user (file-remote-p default-directory 'user)))))
- (eshell-parse-command
- "cd" (list (format "%s|su:%s@%s:%s"
- (substring prefix 0 -1) user host dir)))
- (eshell-parse-command
- "cd" (list (format "/su:%s@%s:%s" user host dir)))))))))
+ (throw 'eshell-replace-command
+ (let ((user "root")
+ (host (or (file-remote-p default-directory 'host)
+ tramp-default-host))
+ (dir (file-local-name (expand-file-name default-directory)))
+ (prefix (file-remote-p default-directory)))
+ (dolist (arg args)
+ (if (string-equal arg "-") (setq login t) (setq user arg)))
+ (when login (setq dir "~/"))
+ (if (and prefix
+ (or
+ (not (string-equal
+ "su" (file-remote-p default-directory 'method)))
+ (not (string-equal
+ user (file-remote-p default-directory 'user)))))
+ (eshell-parse-command
+ "cd" (list (format "%s|su:%s@%s:%s"
+ (substring prefix 0 -1) user host dir)))
+ (eshell-parse-command
+ "cd" (list (format "/su:%s@%s:%s" user host dir))))))))
(put 'eshell/su 'eshell-no-numeric-conversions t)
@@ -99,41 +95,35 @@ Become another USER during a login session.")
"Alias \"sudo\" to call Tramp.
Uses the system sudo through TRAMP's sudo method."
- (setq args (eshell-stringify-list (flatten-tree args)))
- (let ((orig-args (copy-tree args)))
- (eshell-eval-using-options
- "sudo" args
- '((?h "help" nil nil "show this usage screen")
- (?u "user" t user "execute a command as another USER")
- :show-usage
- :parse-leading-options-only
- :usage "[(-u | --user) USER] COMMAND
+ (eshell-eval-using-options
+ "sudo" args
+ '((?h "help" nil nil "show this usage screen")
+ (?u "user" t user "execute a command as another USER")
+ :show-usage
+ :parse-leading-options-only
+ :usage "[(-u | --user) USER] COMMAND
Execute a COMMAND as the superuser or another USER.")
- (throw 'eshell-external
- (let ((user (or user "root"))
- (host (or (file-remote-p default-directory 'host)
- "localhost"))
- (dir (file-local-name (expand-file-name default-directory)))
- (prefix (file-remote-p default-directory)))
- ;; `eshell-eval-using-options' reads options of COMMAND.
- (while (and (stringp (car orig-args))
- (member (car orig-args) '("-u" "--user")))
- (setq orig-args (cddr orig-args)))
- (let ((default-directory
- (if (and prefix
- (or
- (not
- (string-equal
- "sudo"
- (file-remote-p default-directory 'method)))
- (not
- (string-equal
- user
- (file-remote-p default-directory 'user)))))
- (format "%s|sudo:%s@%s:%s"
- (substring prefix 0 -1) user host dir)
- (format "/sudo:%s@%s:%s" user host dir))))
- (eshell-named-command (car orig-args) (cdr orig-args))))))))
+ (throw 'eshell-external
+ (let* ((user (or user "root"))
+ (host (or (file-remote-p default-directory 'host)
+ tramp-default-host))
+ (dir (file-local-name (expand-file-name default-directory)))
+ (prefix (file-remote-p default-directory))
+ (default-directory
+ (if (and prefix
+ (or
+ (not
+ (string-equal
+ "sudo"
+ (file-remote-p default-directory 'method)))
+ (not
+ (string-equal
+ user
+ (file-remote-p default-directory 'user)))))
+ (format "%s|sudo:%s@%s:%s"
+ (substring prefix 0 -1) user host dir)
+ (format "/sudo:%s@%s:%s" user host dir))))
+ (eshell-named-command (car args) (cdr args))))))
(put 'eshell/sudo 'eshell-no-numeric-conversions t)
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 1a2f2a57e8e..459487f4358 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -180,19 +180,63 @@ treated as a literal character."
(add-text-properties 0 (length string) '(escaped t) string))
string)
+(defun eshell-concat (quoted &rest rest)
+ "Concatenate all the arguments in REST and return the result.
+If QUOTED is nil, the resulting value(s) may be converted to
+numbers (see `eshell-concat-1').
+
+If each argument in REST is a non-list value, the result will be
+a single value, as if (mapconcat #'eshell-stringify REST) had been
+called, possibly converted to a number.
+
+If there is at least one (non-nil) list argument, the result will
+be a list, with \"adjacent\" elements of consecutive arguments
+concatenated as strings (again, possibly converted to numbers).
+For example, concatenating \"a\", (\"b\"), and (\"c\" \"d\")
+would produce (\"abc\" \"d\")."
+ (let (result)
+ (dolist (i rest result)
+ (when i
+ (cond
+ ((null result)
+ (setq result i))
+ ((listp result)
+ (let (curr-head curr-tail)
+ (if (listp i)
+ (setq curr-head (car i)
+ curr-tail (cdr i))
+ (setq curr-head i
+ curr-tail nil))
+ (setq result
+ (append
+ (butlast result 1)
+ (list (eshell-concat-1 quoted (car (last result))
+ curr-head))
+ curr-tail))))
+ ((listp i)
+ (setq result
+ (cons (eshell-concat-1 quoted result (car i))
+ (cdr i))))
+ (t
+ (setq result (eshell-concat-1 quoted result i))))))))
+
+(defun eshell-concat-1 (quoted first second)
+ "Concatenate FIRST and SECOND.
+If QUOTED is nil and either FIRST or SECOND are numbers, try to
+convert the result to a number as well."
+ (let ((result (concat (eshell-stringify first) (eshell-stringify second))))
+ (if (and (not quoted)
+ (or (numberp first) (numberp second)))
+ (eshell-convert-to-number result)
+ result)))
+
(defun eshell-resolve-current-argument ()
"If there are pending modifications to be made, make them now."
(when eshell-current-argument
(when eshell-arg-listified
- (let ((parts eshell-current-argument))
- (while parts
- (unless (stringp (car parts))
- (setcar parts
- (list 'eshell-to-flat-string (car parts))))
- (setq parts (cdr parts)))
- (setq eshell-current-argument
- (list 'eshell-convert
- (append (list 'concat) eshell-current-argument))))
+ (setq eshell-current-argument
+ (append (list 'eshell-concat eshell-current-quoted)
+ eshell-current-argument))
(setq eshell-arg-listified nil))
(while eshell-current-modifiers
(setq eshell-current-argument
@@ -354,6 +398,30 @@ after are both returned."
(list 'eshell-escape-arg arg))))
(goto-char (1+ end)))))))
+(defun eshell-unescape-inner-double-quote (bound)
+ "Unescape escaped characters inside a double-quoted string.
+The string to parse starts at point and ends at BOUND.
+
+If Eshell is currently parsing a quoted string and there are any
+backslash-escaped characters, this will return the unescaped
+string, updating point to BOUND. Otherwise, this returns nil and
+leaves point where it was."
+ (when eshell-current-quoted
+ (let (strings
+ (start (point))
+ (special-char
+ (rx-to-string
+ `(seq "\\" (group (any ,@eshell-special-chars-inside-quoting))))))
+ (while (re-search-forward special-char bound t)
+ (push (concat (buffer-substring start (match-beginning 0))
+ (match-string 1))
+ strings)
+ (setq start (match-end 0)))
+ (when strings
+ (push (buffer-substring start bound) strings)
+ (goto-char bound)
+ (apply #'concat (nreverse strings))))))
+
(defun eshell-parse-special-reference ()
"Parse a special syntax reference, of the form `#<args>'.
@@ -377,7 +445,9 @@ If the form has no `type', the syntax is parsed as if `type' were
(if (eshell-arg-delimiter (1+ end))
(prog1
(list (if buffer-p 'get-buffer-create 'get-process)
- (buffer-substring-no-properties (point) end))
+ (replace-regexp-in-string
+ (rx "\\" (group (or "\\" "<" ">"))) "\\1"
+ (buffer-substring-no-properties (point) end)))
(goto-char (1+ end)))
(ignore (goto-char here)))))))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index a2d7d9431a9..775e4c1057e 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -107,6 +107,7 @@
(require 'esh-module)
(require 'esh-io)
(require 'esh-ext)
+(require 'generator)
(eval-when-compile
(require 'cl-lib)
@@ -255,6 +256,7 @@ the command."
(defcustom eshell-subcommand-bindings
'((eshell-in-subcommand-p t)
+ (eshell-in-pipeline-p nil)
(default-directory default-directory)
(process-environment (eshell-copy-environment)))
"A list of `let' bindings for subcommand environments."
@@ -278,14 +280,33 @@ otherwise t.")
(defvar eshell-in-subcommand-p nil)
(defvar eshell-last-arguments nil)
(defvar eshell-last-command-name nil)
-(defvar eshell-last-async-proc nil
- "When this foreground process completes, resume command evaluation.")
+(defvar eshell-last-async-procs nil
+ "The currently-running foreground process(es).
+When executing a pipeline, this is a cons cell whose CAR is the
+first process (usually reading from stdin) and whose CDR is the
+last process (usually writing to stdout). Otherwise, the CAR and
+CDR are the same process.
+
+When the process in the CDR completes, resume command evaluation.")
;;; Functions:
-(defsubst eshell-interactive-process ()
- "Return currently running command process, if non-Lisp."
- eshell-last-async-proc)
+(defsubst eshell-interactive-process-p ()
+ "Return non-nil if there is a currently running command process."
+ eshell-last-async-procs)
+
+(defsubst eshell-head-process ()
+ "Return the currently running process at the head of any pipeline.
+This only returns external (non-Lisp) processes."
+ (car-safe eshell-last-async-procs))
+
+(defsubst eshell-tail-process ()
+ "Return the currently running process at the tail of any pipeline.
+This only returns external (non-Lisp) processes."
+ (cdr-safe eshell-last-async-procs))
+
+(define-obsolete-function-alias 'eshell-interactive-process
+ 'eshell-tail-process "29.1")
(defun eshell-cmd-initialize () ;Called from `eshell-mode' via intern-soft!
"Initialize the Eshell command processing module."
@@ -294,7 +315,7 @@ otherwise t.")
(setq-local eshell-command-arguments nil)
(setq-local eshell-last-arguments nil)
(setq-local eshell-last-command-name nil)
- (setq-local eshell-last-async-proc nil)
+ (setq-local eshell-last-async-procs nil)
(add-hook 'eshell-kill-hook #'eshell-resume-command nil t)
@@ -305,7 +326,7 @@ otherwise t.")
(add-hook 'eshell-post-command-hook
(lambda ()
(setq eshell-current-command nil
- eshell-last-async-proc nil))
+ eshell-last-async-procs nil))
nil t)
(add-hook 'eshell-parse-argument-hook
@@ -330,6 +351,39 @@ otherwise t.")
(defvar eshell--sep-terms)
+(defmacro eshell-with-temp-command (region &rest body)
+ "Narrow the buffer to REGION and execute the forms in BODY.
+
+REGION is a cons cell (START . END) that specifies the region to
+which to narrow the buffer. REGION can also be a string, in
+which case the macro temporarily inserts it into the buffer at
+point, and narrows the buffer to the inserted string. Before
+executing BODY, point is set to the beginning of the narrowed
+REGION.
+
+The value returned is the last form in BODY."
+ (declare (indent 1))
+ `(let ((reg ,region))
+ (if (stringp reg)
+ ;; Since parsing relies partly on buffer-local state
+ ;; (e.g. that of `eshell-parse-argument-hook'), we need to
+ ;; perform the parsing in the Eshell buffer.
+ (let ((begin (point)) end
+ (inhibit-point-motion-hooks t))
+ (with-silent-modifications
+ (insert reg)
+ (setq end (point))
+ (unwind-protect
+ (save-restriction
+ (narrow-to-region begin end)
+ (goto-char begin)
+ ,@body)
+ (delete-region begin end))))
+ (save-restriction
+ (narrow-to-region (car reg) (cdr reg))
+ (goto-char (car reg))
+ ,@body))))
+
(defun eshell-parse-command (command &optional args toplevel)
"Parse the COMMAND, adding ARGS if given.
COMMAND can either be a string, or a cons cell demarcating a buffer
@@ -341,15 +395,9 @@ hooks should be run before and after the command."
(append
(if (consp command)
(eshell-parse-arguments (car command) (cdr command))
- (let ((here (point))
- (inhibit-point-motion-hooks t))
- (with-silent-modifications
- ;; FIXME: Why not use a temporary buffer and avoid this
- ;; "insert&delete" business? --Stef
- (insert command)
- (prog1
- (eshell-parse-arguments here (point))
- (delete-region here (point))))))
+ (eshell-with-temp-command command
+ (goto-char (point-max))
+ (eshell-parse-arguments (point-min) (point-max))))
args))
(commands
(mapcar
@@ -763,8 +811,7 @@ This macro calls itself recursively, with NOTFIRST non-nil."
(eshell-set-output-handle ,eshell-output-handle
'append nextproc)
(eshell-set-output-handle ,eshell-error-handle
- 'append nextproc)
- (setq tailproc (or tailproc nextproc))))
+ 'append nextproc)))
,(let ((head (car pipeline)))
(if (memq (car head) '(let progn))
(setq head (car (last head))))
@@ -780,7 +827,10 @@ This macro calls itself recursively, with NOTFIRST non-nil."
,(cond ((not notfirst) (quote 'first))
((cdr pipeline) t)
(t (quote 'last)))))
- ,(car pipeline))))))
+ (let ((proc ,(car pipeline)))
+ (set headproc (or proc (symbol-value headproc)))
+ (set tailproc (or (symbol-value tailproc) proc))
+ proc))))))
(defmacro eshell-do-pipelines-synchronously (pipeline)
"Execute the commands in PIPELINE in sequence synchronously.
@@ -812,7 +862,7 @@ This is used on systems where async subprocesses are not supported."
(let ((result ,(car pipeline)))
;; tailproc gets the result of the last successful process in
;; the pipeline.
- (setq tailproc (or result tailproc))
+ (set tailproc (or result (symbol-value tailproc)))
,(if (cdr pipeline)
`(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
result))))
@@ -821,7 +871,11 @@ This is used on systems where async subprocesses are not supported."
(defmacro eshell-execute-pipeline (pipeline)
"Execute the commands in PIPELINE, connecting each to one another."
- `(let ((eshell-in-pipeline-p t) tailproc)
+ `(let ((eshell-in-pipeline-p t)
+ (headproc (make-symbol "headproc"))
+ (tailproc (make-symbol "tailproc")))
+ (set headproc nil)
+ (set tailproc nil)
(progn
,(if (fboundp 'make-process)
`(eshell-do-pipelines ,pipeline)
@@ -831,7 +885,8 @@ This is used on systems where async subprocesses are not supported."
(car (aref eshell-current-handles
,eshell-error-handle)) nil)))
(eshell-do-pipelines-synchronously ,pipeline)))
- (eshell-process-identity tailproc))))
+ (eshell-process-identity (cons (symbol-value headproc)
+ (symbol-value tailproc))))))
(defmacro eshell-as-subcommand (command)
"Execute COMMAND using a temp buffer.
@@ -853,7 +908,8 @@ This avoids the need to use `let*'."
(defmacro eshell-command-to-value (object)
"Run OBJECT synchronously, returning its result as a string.
Returns a string comprising the output from the command."
- `(let ((value (make-symbol "eshell-temp")))
+ `(let ((value (make-symbol "eshell-temp"))
+ (eshell-in-pipeline-p nil))
(eshell-do-command-to-value ,object)))
;;;_* Iterative evaluation
@@ -903,21 +959,63 @@ at the moment are:
"Completion for the `debug' command."
(while (pcomplete-here '("errors" "commands"))))
+(iter-defun eshell--find-subcommands (haystack)
+ "Recursively search for subcommand forms in HAYSTACK.
+This yields the SUBCOMMANDs when found in forms like
+\"(eshell-as-subcommand SUBCOMMAND)\"."
+ (dolist (elem haystack)
+ (cond
+ ((eq (car-safe elem) 'eshell-as-subcommand)
+ (iter-yield (cdr elem)))
+ ((listp elem)
+ (iter-yield-from (eshell--find-subcommands elem))))))
+
+(defun eshell--invoke-command-directly (command)
+ "Determine whether the given COMMAND can be invoked directly.
+COMMAND should be a non-top-level Eshell command in parsed form.
+
+A command can be invoked directly if all of the following are true:
+
+* The command is of the form
+ \"(eshell-trap-errors (eshell-named-command NAME ARGS))\",
+ where ARGS is optional.
+
+* NAME is a string referring to an alias function and isn't a
+ complex command (see `eshell-complex-commands').
+
+* Any subcommands in ARGS can also be invoked directly."
+ (when (and (eq (car command) 'eshell-trap-errors)
+ (eq (car (cadr command)) 'eshell-named-command))
+ (let ((name (cadr (cadr command)))
+ (args (cdr-safe (nth 2 (cadr command)))))
+ (and name (stringp name)
+ (not (member name eshell-complex-commands))
+ (catch 'simple
+ (dolist (pred eshell-complex-commands t)
+ (when (and (functionp pred)
+ (funcall pred name))
+ (throw 'simple nil))))
+ (eshell-find-alias-function name)
+ (catch 'indirect-subcommand
+ (iter-do (subcommand (eshell--find-subcommands args))
+ (unless (eshell--invoke-command-directly subcommand)
+ (throw 'indirect-subcommand nil)))
+ t)))))
+
(defun eshell-invoke-directly (command)
- (let ((base (cadr (nth 2 (nth 2 (cadr command))))) name)
- (if (and (eq (car base) 'eshell-trap-errors)
- (eq (car (cadr base)) 'eshell-named-command))
- (setq name (cadr (cadr base))))
- (and name (stringp name)
- (not (member name eshell-complex-commands))
- (catch 'simple
- (progn
- (dolist (pred eshell-complex-commands)
- (if (and (functionp pred)
- (funcall pred name))
- (throw 'simple nil)))
- t))
- (eshell-find-alias-function name))))
+ "Determine whether the given COMMAND can be invoked directly.
+COMMAND should be a top-level Eshell command in parsed form, as
+produced by `eshell-parse-command'."
+ (let ((base (cadr (nth 2 (nth 2 (cadr command))))))
+ (eshell--invoke-command-directly base)))
+
+(defun eshell-eval-argument (argument)
+ "Evaluate a single Eshell ARGUMENT and return the result."
+ (let* ((form (eshell-with-temp-command argument
+ (eshell-parse-argument)))
+ (result (eshell-do-eval form t)))
+ (cl-assert (eq (car result) 'quote))
+ (cadr result)))
(defun eshell-eval-command (command &optional input)
"Evaluate the given COMMAND iteratively."
@@ -957,24 +1055,24 @@ at the moment are:
(unless (or (not (stringp status))
(string= "stopped" status)
(string-match eshell-reset-signals status))
- (if (eq proc (eshell-interactive-process))
+ (if (eq proc (eshell-tail-process))
(eshell-resume-eval)))))
(defun eshell-resume-eval ()
"Destructively evaluate a form which may need to be deferred."
(eshell-condition-case err
(progn
- (setq eshell-last-async-proc nil)
+ (setq eshell-last-async-procs nil)
(when eshell-current-command
(let* (retval
- (proc (catch 'eshell-defer
+ (procs (catch 'eshell-defer
(ignore
(setq retval
(eshell-do-eval
eshell-current-command))))))
- (if (eshell-processp proc)
- (ignore (setq eshell-last-async-proc proc))
- (cadr retval)))))
+ (if (eshell-process-pair-p procs)
+ (ignore (setq eshell-last-async-procs procs))
+ (cadr retval)))))
(error
(error (error-message-string err)))))
@@ -1137,17 +1235,16 @@ be finished later after the completion of an asynchronous subprocess."
(setcar form (car new-form))
(setcdr form (cdr new-form)))
(eshell-do-eval form synchronous-p))
- (if (and (memq (car form) eshell-deferrable-commands)
- (not eshell-current-subjob-p)
- result
- (eshell-processp result))
- (if synchronous-p
- (eshell/wait result)
+ (if-let (((memq (car form) eshell-deferrable-commands))
+ ((not eshell-current-subjob-p))
+ (procs (eshell-make-process-pair result)))
+ (if synchronous-p
+ (eshell/wait (cdr procs))
(eshell-manipulate "inserting ignore form"
(setcar form 'ignore)
(setcdr form nil))
- (throw 'eshell-defer result))
- (list 'quote result))))))))))))
+ (throw 'eshell-defer procs))
+ (list 'quote result))))))))))))
;; command invocation
@@ -1237,8 +1334,9 @@ or an external command."
(defun eshell-exec-lisp (printer errprint func-or-form args form-p)
"Execute a Lisp FUNC-OR-FORM, maybe passing ARGS.
PRINTER and ERRPRINT are functions to use for printing regular
-messages, and errors. FORM-P should be non-nil if FUNC-OR-FORM
-represent a Lisp form; ARGS will be ignored in that case."
+messages and errors, respectively. FORM-P should be non-nil if
+FUNC-OR-FORM represent a Lisp form; ARGS will be ignored in that
+case."
(eshell-condition-case err
(let ((result
(save-current-buffer
@@ -1261,44 +1359,56 @@ represent a Lisp form; ARGS will be ignored in that case."
(defsubst eshell-apply* (printer errprint func args)
"Call FUNC, with ARGS, trapping errors and return them as output.
PRINTER and ERRPRINT are functions to use for printing regular
-messages, and errors."
+messages and errors, respectively."
(eshell-exec-lisp printer errprint func args nil))
(defsubst eshell-funcall* (printer errprint func &rest args)
- "Call FUNC, with ARGS, trapping errors and return them as output."
+ "Call FUNC, with ARGS, trapping errors and return them as output.
+PRINTER and ERRPRINT are functions to use for printing regular
+messages and errors, respectively."
(eshell-apply* printer errprint func args))
(defsubst eshell-eval* (printer errprint form)
- "Evaluate FORM, trapping errors and returning them."
+ "Evaluate FORM, trapping errors and returning them.
+PRINTER and ERRPRINT are functions to use for printing regular
+messages and errors, respectively."
(eshell-exec-lisp printer errprint form nil t))
(defsubst eshell-apply (func args)
"Call FUNC, with ARGS, trapping errors and return them as output.
-PRINTER and ERRPRINT are functions to use for printing regular
-messages, and errors."
- (eshell-apply* 'eshell-print 'eshell-error func args))
+Print the result using `eshell-print'; if an error occurs, print
+it via `eshell-error'."
+ (eshell-apply* #'eshell-print #'eshell-error func args))
(defsubst eshell-funcall (func &rest args)
- "Call FUNC, with ARGS, trapping errors and return them as output."
+ "Call FUNC, with ARGS, trapping errors and return them as output.
+Print the result using `eshell-print'; if an error occurs, print
+it via `eshell-error'."
(eshell-apply func args))
(defsubst eshell-eval (form)
- "Evaluate FORM, trapping errors and returning them."
- (eshell-eval* 'eshell-print 'eshell-error form))
+ "Evaluate FORM, trapping errors and returning them.
+Print the result using `eshell-print'; if an error occurs, print
+it via `eshell-error'."
+ (eshell-eval* #'eshell-print #'eshell-error form))
(defsubst eshell-applyn (func args)
"Call FUNC, with ARGS, trapping errors and return them as output.
-PRINTER and ERRPRINT are functions to use for printing regular
-messages, and errors."
- (eshell-apply* 'eshell-printn 'eshell-errorn func args))
+Print the result using `eshell-printn'; if an error occurs, print it
+via `eshell-errorn'."
+ (eshell-apply* #'eshell-printn #'eshell-errorn func args))
(defsubst eshell-funcalln (func &rest args)
- "Call FUNC, with ARGS, trapping errors and return them as output."
+ "Call FUNC, with ARGS, trapping errors and return them as output.
+Print the result using `eshell-printn'; if an error occurs, print it
+via `eshell-errorn'."
(eshell-applyn func args))
(defsubst eshell-evaln (form)
- "Evaluate FORM, trapping errors and returning them."
- (eshell-eval* 'eshell-printn 'eshell-errorn form))
+ "Evaluate FORM, trapping errors and returning them.
+Print the result using `eshell-printn'; if an error occurs, print it
+via `eshell-errorn'."
+ (eshell-eval* #'eshell-printn #'eshell-errorn form))
(defvar eshell-last-output-end) ;Defined in esh-mode.el.
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index fc023f23ce2..98902fc6f23 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -163,7 +163,7 @@ by the user on the command line."
(defcustom eshell-explicit-command-char ?*
"If this char occurs before a command name, call it externally.
-That is, although `vi' may be an alias, `\vi' will always call the
+That is, although `vi' may be an alias, `*vi' will always call the
external version."
:type 'character
:group 'eshell-ext)
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index 2e0f312f4a6..c035890ddf0 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -150,6 +150,8 @@ not be added to this variable."
:risky t
:group 'eshell-io)
+(define-error 'eshell-pipe-broken "Pipe broken")
+
;;; Internal Variables:
(defvar eshell-current-handles nil)
@@ -274,8 +276,20 @@ STATUS should be non-nil on successful termination of the output."
;; If we're redirecting to a process (via a pipe, or process
;; redirection), send it EOF so that it knows we're finished.
((eshell-processp target)
- (if (eq (process-status target) 'run)
- (process-send-eof target)))
+ ;; According to POSIX.1-2017, section 11.1.9, sending EOF causes
+ ;; all bytes waiting to be read to be sent to the process
+ ;; immediately. Thus, if there are any bytes waiting, we need to
+ ;; send EOF twice: once to flush the buffer, and a second time to
+ ;; cause the next read() to return a size of 0, indicating
+ ;; end-of-file to the reading process. However, some platforms
+ ;; (e.g. Solaris) actually require sending a *third* EOF. Since
+ ;; sending extra EOFs while the process is running shouldn't break
+ ;; anything, we'll just send the maximum we'd ever need. See
+ ;; bug#56025 for further details.
+ (let ((i 0))
+ (while (and (<= (cl-incf i) 3)
+ (eq (process-status target) 'run))
+ (process-send-eof target))))
;; A plain function redirection needs no additional arguments
;; passed.
@@ -375,8 +389,6 @@ it defaults to `insert'."
(error "Invalid redirection target: %s"
(eshell-stringify target)))))
-(defvar grep-null-device)
-
(defun eshell-set-output-handle (index mode &optional target)
"Set handle INDEX, using MODE, to point to TARGET."
(when target
@@ -483,24 +495,31 @@ Returns what was actually sent, or nil if nothing was sent."
(goto-char target))))))
((eshell-processp target)
- (when (eq (process-status target) 'run)
- (unless (stringp object)
- (setq object (eshell-stringify object)))
- (process-send-string target object)))
+ (unless (stringp object)
+ (setq object (eshell-stringify object)))
+ (condition-case nil
+ (process-send-string target object)
+ ;; If `process-send-string' raises an error, treat it as a broken pipe.
+ (error (signal 'eshell-pipe-broken target))))
((consp target)
(apply (car target) object (cdr target))))
object)
(defun eshell-output-object (object &optional handle-index handles)
- "Insert OBJECT, using HANDLE-INDEX specifically)."
+ "Insert OBJECT, using HANDLE-INDEX specifically.
+If HANDLE-INDEX is nil, output to `eshell-output-handle'.
+HANDLES is the set of file handles to use; if nil, use
+`eshell-current-handles'."
(let ((target (car (aref (or handles eshell-current-handles)
(or handle-index eshell-output-handle)))))
- (if (and target (not (listp target)))
- (eshell-output-object-to-target object target)
- (while target
- (eshell-output-object-to-target object (car target))
- (setq target (cdr target))))))
+ (if (listp target)
+ (while target
+ (eshell-output-object-to-target object (car target))
+ (setq target (cdr target)))
+ (eshell-output-object-to-target object target)
+ ;; Explicitly return nil to match the list case above.
+ nil)))
(provide 'esh-io)
;;; esh-io.el ends here
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 8302eefe1e6..972d4f9df00 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -146,7 +146,7 @@ See variable `eshell-scroll-to-bottom-on-output' and function
Eshell buffers are truncated from the top to be no greater than this
number, if the function `eshell-truncate-buffer' is on
`eshell-output-filter-functions'."
- :type 'integer)
+ :type 'natnum)
(defcustom eshell-output-filter-functions
'(eshell-postoutput-scroll-to-bottom
@@ -361,7 +361,11 @@ and the hook `eshell-exit-hook'."
(unless module-shortname
(error "Invalid Eshell module name: %s" module-fullname))
(unless (featurep (intern module-shortname))
- (load module-shortname))))
+ (condition-case nil
+ (load module-shortname)
+ (error (lwarn 'eshell :error
+ "Unable to load module `%s' (defined in `eshell-modules-list')"
+ module-fullname))))))
(unless (file-exists-p eshell-directory-name)
(eshell-make-private-directory eshell-directory-name t))
@@ -423,13 +427,13 @@ and the hook `eshell-exit-hook'."
(defun eshell-self-insert-command ()
(interactive)
(process-send-string
- (eshell-interactive-process)
+ (eshell-head-process)
(char-to-string (if (symbolp last-command-event)
(get last-command-event 'ascii-character)
last-command-event))))
(defun eshell-intercept-commands ()
- (when (and (eshell-interactive-process)
+ (when (and (eshell-interactive-process-p)
(not (and (integerp last-input-event)
(memq last-input-event '(?\C-x ?\C-c)))))
(let ((possible-events (where-is-internal this-command))
@@ -595,13 +599,13 @@ If NO-NEWLINE is non-nil, the input is sent without an implied final
newline."
(interactive "P")
;; Note that the input string does not include its terminal newline.
- (let ((proc-running-p (and (eshell-interactive-process)
+ (let ((proc-running-p (and (eshell-head-process)
(not queue-p)))
(inhibit-point-motion-hooks t)
(inhibit-modification-hooks t))
(unless (and proc-running-p
(not (eq (process-status
- (eshell-interactive-process))
+ (eshell-head-process))
'run)))
(if (or proc-running-p
(>= (point) eshell-last-output-end))
@@ -627,8 +631,8 @@ newline."
(if (or eshell-send-direct-to-subprocesses
(= eshell-last-input-start eshell-last-input-end))
(unless no-newline
- (process-send-string (eshell-interactive-process) "\n"))
- (process-send-region (eshell-interactive-process)
+ (process-send-string (eshell-head-process) "\n"))
+ (process-send-region (eshell-head-process)
eshell-last-input-start
eshell-last-input-end)))
(if (= eshell-last-output-end (point))
@@ -665,6 +669,16 @@ newline."
(run-hooks 'eshell-post-command-hook)
(insert-and-inherit input)))))))))
+(defun eshell-send-eof-to-process ()
+ "Send EOF to the currently-running \"head\" process."
+ (interactive)
+ (require 'esh-mode)
+ (declare-function eshell-send-input "esh-mode"
+ (&optional use-region queue-p no-newline))
+ (eshell-send-input nil nil t)
+ (when (eshell-head-process)
+ (process-send-eof (eshell-head-process))))
+
(defsubst eshell-kill-new ()
"Add the last input text to the kill ring."
(kill-ring-save eshell-last-input-start eshell-last-input-end))
@@ -924,9 +938,9 @@ Then send it to the process running in the current buffer."
(interactive) ; Don't pass str as argument, to avoid snooping via C-x ESC ESC
(let ((str (read-passwd
(format "%s Password: "
- (process-name (eshell-interactive-process))))))
+ (process-name (eshell-head-process))))))
(if (stringp str)
- (process-send-string (eshell-interactive-process)
+ (process-send-string (eshell-head-process)
(concat str "\n"))
(message "Warning: text will be echoed"))))
@@ -937,7 +951,7 @@ buffer's process if STRING contains a password prompt defined by
`eshell-password-prompt-regexp'.
This function could be in the list `eshell-output-filter-functions'."
- (when (eshell-interactive-process)
+ (when (eshell-interactive-process-p)
(save-excursion
(let ((case-fold-search t))
(goto-char eshell-last-output-block-begin)
@@ -1024,5 +1038,7 @@ This function could be in the list `eshell-output-filter-functions'."
(let ((default-directory (bookmark-prop-get bookmark 'location)))
(eshell)))
+(put 'eshell-bookmark-jump 'bookmark-handler-type "Eshell")
+
(provide 'esh-mode)
;;; esh-mode.el ends here
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index ade151d7cd5..14e91912d11 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -54,6 +54,7 @@ customizing the variable `eshell-modules-list'."
eshell-basic
eshell-cmpl
eshell-dirs
+ eshell-extpipe
eshell-glob
eshell-hist
eshell-ls
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index d96b77ddd37..f52b70fe7a6 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -97,10 +97,10 @@ let-bound variable `args'."
(declare (debug (form form sexp body)))
`(let* ((temp-args
,(if (memq ':preserve-args (cadr options))
- macro-args
+ (list 'copy-tree macro-args)
(list 'eshell-stringify-list
(list 'flatten-tree macro-args))))
- (processed-args (eshell--do-opts ,name ,options temp-args))
+ (processed-args (eshell--do-opts ,name ,options temp-args ,macro-args))
,@(delete-dups
(delq nil (mapcar (lambda (opt)
(and (listp opt) (nth 3 opt)
@@ -117,7 +117,7 @@ let-bound variable `args'."
;; Documented part of the interface; see eshell-eval-using-options.
(defvar eshell--args)
-(defun eshell--do-opts (name options args)
+(defun eshell--do-opts (name options args orig-args)
"Helper function for `eshell-eval-using-options'.
This code doesn't really need to be macro expanded everywhere."
(require 'esh-ext)
@@ -135,7 +135,7 @@ This code doesn't really need to be macro expanded everywhere."
(error "%s" usage-msg))))))
(if ext-command
(throw 'eshell-external
- (eshell-external-command ext-command args))
+ (eshell-external-command ext-command orig-args))
args)))
(defun eshell-show-usage (name options)
@@ -187,49 +187,82 @@ passed to this command, the external version `%s'
will be called instead." extcmd)))))
(throw 'eshell-usage usage)))
-(defun eshell--set-option (name ai opt options opt-vals)
+(defun eshell--split-switch (switch kind)
+ "Split SWITCH into its option name and potential value, if any.
+KIND should be the integer 0 if SWITCH is a short option, or 1 if it's
+a long option."
+ (if (eq kind 0)
+ ;; Short option
+ (cons (aref switch 0)
+ (and (> (length switch) 1) (substring switch 1)))
+ ;; Long option
+ (save-match-data
+ (string-match "\\([^=]*\\)\\(?:=\\(.*\\)\\)?" switch)
+ (cons (match-string 1 switch) (match-string 2 switch)))))
+
+(defun eshell--set-option (name ai opt value options opt-vals)
"Using NAME's remaining args (index AI), set the OPT within OPTIONS.
-If the option consumes an argument for its value, the argument list
-will be modified."
+VALUE is the potential value of the OPT, coming from args like
+\"-fVALUE\" or \"--foo=VALUE\", or nil if no value was supplied. If
+OPT doesn't consume a value, return VALUE unchanged so that it can be
+processed later; otherwise, return nil.
+
+If the OPT consumes an argument for its value and VALUE is nil, the
+argument list will be modified."
(if (not (nth 3 opt))
(eshell-show-usage name options)
- (setcdr (assq (nth 3 opt) opt-vals)
- (if (eq (nth 2 opt) t)
- (if (> ai (length eshell--args))
- (error "%s: missing option argument" name)
- (pop (nthcdr ai eshell--args)))
- (or (nth 2 opt) t)))))
+ (if (eq (nth 2 opt) t)
+ (progn
+ (setcdr (assq (nth 3 opt) opt-vals)
+ (or value
+ (if (> ai (length eshell--args))
+ (error "%s: missing option argument" name)
+ (pop (nthcdr ai eshell--args)))))
+ nil)
+ (setcdr (assq (nth 3 opt) opt-vals)
+ (or (nth 2 opt) t))
+ value)))
(defun eshell--process-option (name switch kind ai options opt-vals)
"For NAME, process SWITCH (of type KIND), from args at index AI.
The SWITCH will be looked up in the set of OPTIONS.
-SWITCH should be either a string or character. KIND should be the
-integer 0 if it's a character, or 1 if it's a string.
-
-The SWITCH is then be matched against OPTIONS. If no matching handler
-is found, and an :external command is defined (and available), it will
-be called; otherwise, an error will be triggered to say that the
-switch is unrecognized."
- (let* ((opts options)
- found)
+SWITCH should be a string starting with the option to process,
+possibly followed by its value, e.g. \"u\" or \"uUSER\". KIND should
+be the integer 0 if it's a short option, or 1 if it's a long option.
+
+The SWITCH is then be matched against OPTIONS. If KIND is 0 and the
+SWITCH matches an option that doesn't take a value, return the
+remaining characters in SWITCH to be processed later as further short
+options.
+
+If no matching handler is found, and an :external command is defined
+(and available), it will be called; otherwise, an error will be
+triggered to say that the switch is unrecognized."
+ (let ((switch (eshell--split-switch switch kind))
+ (opts options)
+ found remaining)
(while opts
(if (and (listp (car opts))
- (nth kind (car opts))
- (equal switch (nth kind (car opts))))
+ (equal (car switch) (nth kind (car opts))))
(progn
- (eshell--set-option name ai (car opts) options opt-vals)
+ (setq remaining (eshell--set-option name ai (car opts)
+ (cdr switch) options opt-vals))
+ (when (and remaining (eq kind 1))
+ (error "%s: option --%s doesn't allow an argument"
+ name (car switch)))
(setq found t opts nil))
(setq opts (cdr opts))))
- (unless found
+ (if found
+ remaining
(let ((extcmd (memq ':external options)))
(when extcmd
- (setq extcmd (eshell-search-path (cadr extcmd)))
- (if extcmd
- (throw 'eshell-ext-command extcmd)
- (error (if (characterp switch) "%s: unrecognized option -%c"
- "%s: unrecognized option --%s")
- name switch)))))))
+ (setq extcmd (eshell-search-path (cadr extcmd))))
+ (if extcmd
+ (throw 'eshell-ext-command extcmd)
+ (error (if (characterp (car switch)) "%s: unrecognized option -%c"
+ "%s: unrecognized option --%s")
+ name (car switch)))))))
(defun eshell--process-args (name args options)
"Process the given ARGS using OPTIONS."
@@ -250,6 +283,9 @@ switch is unrecognized."
(memq :parse-leading-options-only options))))
(setq arg (nth ai eshell--args))
(if (not (and (stringp arg)
+ ;; A string of length 1 can't be an option; (if
+ ;; it's "-", that generally means stdin).
+ (> (length arg) 1)
(string-match "^-\\(-\\)?\\(.*\\)" arg)))
;; Positional argument found, skip
(setq ai (1+ ai)
@@ -262,12 +298,9 @@ switch is unrecognized."
(if (> (length switch) 0)
(eshell--process-option name switch 1 ai options opt-vals)
(setq ai (length eshell--args)))
- (let ((len (length switch))
- (index 0))
- (while (< index len)
- (eshell--process-option name (aref switch index)
- 0 ai options opt-vals)
- (setq index (1+ index))))))))
+ (while (> (length switch) 0)
+ (setq switch (eshell--process-option name switch 0
+ ai options opt-vals)))))))
(nconc (mapcar #'cdr opt-vals) eshell--args)))
(provide 'esh-opt)
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 5ed692fb5a3..70426ccaf2a 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -101,6 +101,9 @@ information, for example."
(defvar eshell-process-list nil
"A list of the current status of subprocesses.")
+(declare-function eshell-send-eof-to-process "esh-mode")
+(declare-function eshell-tail-process "esh-cmd")
+
(defvar-keymap eshell-proc-mode-map
"C-c M-i" #'eshell-insert-process
"C-c C-c" #'eshell-interrupt-process
@@ -117,7 +120,9 @@ Runs `eshell-reset-after-proc' and `eshell-kill-hook', passing arguments
PROC and STATUS to functions on the latter."
;; Was there till 24.1, but it is not optional.
(remove-hook 'eshell-kill-hook #'eshell-reset-after-proc)
- (eshell-reset-after-proc status)
+ ;; Only reset the prompt if this process is running interactively.
+ (when (eq proc (eshell-tail-process))
+ (eshell-reset-after-proc status))
(run-hook-with-args 'eshell-kill-hook proc status))
(define-minor-mode eshell-proc-mode
@@ -384,8 +389,27 @@ output."
(let ((data (nth 3 entry)))
(setcar (nthcdr 3 entry) nil)
(setcar (nthcdr 4 entry) t)
- (eshell-output-object data nil (cadr entry))
- (setcar (nthcdr 4 entry) nil)))))))))
+ (unwind-protect
+ (condition-case nil
+ (eshell-output-object data nil (cadr entry))
+ ;; FIXME: We want to send SIGPIPE to the process
+ ;; here. However, remote processes don't
+ ;; currently support that, and not all systems
+ ;; have SIGPIPE in the first place (e.g. MS
+ ;; Windows). In these cases, just delete the
+ ;; process; this is reasonably close to the
+ ;; right behavior, since the default action for
+ ;; SIGPIPE is to terminate the process. For use
+ ;; cases where SIGPIPE is truly needed, using an
+ ;; external pipe operator (`*|') may work
+ ;; instead (e.g. when working with remote
+ ;; processes).
+ (eshell-pipe-broken
+ (if (or (process-get proc 'remote-pid)
+ (eq system-type 'windows-nt))
+ (delete-process proc)
+ (signal-process proc 'SIGPIPE))))
+ (setcar (nthcdr 4 entry) nil))))))))))
(defun eshell-sentinel (proc string)
"Generic sentinel for command processes. Reports only signals.
@@ -393,7 +417,7 @@ PROC is the process that's exiting. STRING is the exit message."
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(unwind-protect
- (let* ((entry (assq proc eshell-process-list)))
+ (let ((entry (assq proc eshell-process-list)))
; (if (not entry)
; (error "Sentinel called for unowned process `%s'"
; (process-name proc))
@@ -401,8 +425,13 @@ PROC is the process that's exiting. STRING is the exit message."
(unwind-protect
(progn
(unless (string= string "run")
- (unless (string-match "^\\(finished\\|exited\\)" string)
- (eshell-insertion-filter proc string))
+ ;; Write the exit message if the status is
+ ;; abnormal and the process is already writing
+ ;; to the terminal.
+ (when (and (eq proc (eshell-tail-process))
+ (not (string-match "^\\(finished\\|exited\\)"
+ string)))
+ (funcall (process-filter proc) proc string))
(let ((handles (nth 1 entry))
(str (prog1 (nth 3 entry)
(setf (nth 3 entry) nil)))
@@ -414,8 +443,12 @@ PROC is the process that's exiting. STRING is the exit message."
(lambda ()
(if (nth 4 entry)
(run-at-time 0 nil finish-io)
- (when str (eshell-output-object str nil handles))
- (eshell-close-handles status 'nil handles)))))
+ (when str
+ (ignore-error 'eshell-pipe-broken
+ (eshell-output-object
+ str nil handles)))
+ (eshell-close-handles
+ status 'nil handles)))))
(funcall finish-io)))))
(eshell-remove-process-entry entry))))
(eshell-kill-process-function proc string)))))
@@ -542,14 +575,5 @@ See the variable `eshell-kill-processes-on-exit'."
; ;; `eshell-resume-eval'.
; (eshell-kill-process-function nil "continue")))
-(defun eshell-send-eof-to-process ()
- "Send EOF to process."
- (interactive)
- (require 'esh-mode)
- (declare-function eshell-send-input "esh-mode"
- (&optional use-region queue-p no-newline))
- (eshell-send-input nil nil t)
- (eshell-process-interact 'process-send-eof))
-
(provide 'esh-proc)
;;; esh-proc.el ends here
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 0e04dbc7c9f..5144e305121 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -151,67 +151,98 @@ Otherwise, evaluates FORM with no error handling."
(defun eshell-find-delimiter
(open close &optional bound reverse-p backslash-p)
"From point, find the CLOSE delimiter corresponding to OPEN.
-The matching is bounded by BOUND.
-If REVERSE-P is non-nil, process the region backwards.
-If BACKSLASH-P is non-nil, and OPEN and CLOSE are the same character,
-then quoting is done by a backslash, rather than a doubled delimiter."
+The matching is bounded by BOUND. If REVERSE-P is non-nil,
+process the region backwards.
+
+If BACKSLASH-P is non-nil, or OPEN and CLOSE are different
+characters, then a backslash can be used to escape a delimiter
+(or another backslash). Otherwise, the delimiter is escaped by
+doubling it up."
(save-excursion
(let ((depth 1)
(bound (or bound (point-max))))
- (if (if reverse-p
- (eq (char-before) close)
- (eq (char-after) open))
- (forward-char (if reverse-p -1 1)))
+ (when (if reverse-p
+ (eq (char-before) close)
+ (eq (char-after) open))
+ (forward-char (if reverse-p -1 1)))
(while (and (> depth 0)
- (funcall (if reverse-p '> '<) (point) bound))
- (let ((c (if reverse-p (char-before) (char-after))) nc)
+ (funcall (if reverse-p #'> #'<) (point) bound))
+ (let ((c (if reverse-p (char-before) (char-after))))
(cond ((and (not reverse-p)
(or (not (eq open close))
backslash-p)
(eq c ?\\)
- (setq nc (char-after (1+ (point))))
- (or (eq nc open) (eq nc close)))
+ (memq (char-after (1+ (point)))
+ (list open close ?\\)))
(forward-char 1))
((and reverse-p
(or (not (eq open close))
backslash-p)
- (or (eq c open) (eq c close))
- (eq (char-before (1- (point)))
- ?\\))
+ (eq (char-before (1- (point))) ?\\)
+ (memq c (list open close ?\\)))
(forward-char -1))
((eq open close)
- (if (eq c open)
- (if (and (not backslash-p)
- (eq (if reverse-p
- (char-before (1- (point)))
- (char-after (1+ (point)))) open))
- (forward-char (if reverse-p -1 1))
- (setq depth (1- depth)))))
+ (when (eq c open)
+ (if (and (not backslash-p)
+ (eq (if reverse-p
+ (char-before (1- (point)))
+ (char-after (1+ (point))))
+ open))
+ (forward-char (if reverse-p -1 1))
+ (setq depth (1- depth)))))
((= c open)
(setq depth (+ depth (if reverse-p -1 1))))
((= c close)
(setq depth (+ depth (if reverse-p 1 -1))))))
(forward-char (if reverse-p -1 1)))
- (if (= depth 0)
- (if reverse-p (point) (1- (point)))))))
-
-(defun eshell-convert (string)
- "Convert STRING into a more native looking Lisp object."
- (if (not (stringp string))
- string
- (let ((len (length string)))
- (if (= len 0)
- string
- (if (eq (aref string (1- len)) ?\n)
+ (when (= depth 0)
+ (if reverse-p (point) (1- (point)))))))
+
+(defun eshell-convertible-to-number-p (string)
+ "Return non-nil if STRING can be converted to a number.
+If `eshell-convert-numeric-aguments', always return nil."
+ (and eshell-convert-numeric-arguments
+ (string-match
+ (concat "\\`\\s-*" eshell-number-regexp "\\s-*\\'")
+ string)))
+
+(defun eshell-convert-to-number (string)
+ "Try to convert STRING to a number.
+If STRING doesn't look like a number (or
+`eshell-convert-numeric-aguments' is nil), just return STRING
+unchanged."
+ (if (eshell-convertible-to-number-p string)
+ (string-to-number string)
+ string))
+
+(defun eshell-convert (string &optional to-string)
+ "Convert STRING into a more-native Lisp object.
+If TO-STRING is non-nil, always return a single string with
+trailing newlines removed. Otherwise, this behaves as follows:
+
+* Return non-strings as-is.
+
+* Split multiline strings by line.
+
+* If `eshell-convert-numeric-aguments' is non-nil and every line
+ of output looks like a number, convert them to numbers."
+ (cond
+ ((not (stringp string))
+ (if to-string
+ (eshell-stringify string)
+ string))
+ (to-string (string-trim-right string "\n+"))
+ (t (let ((len (length string)))
+ (if (= len 0)
+ string
+ (when (eq (aref string (1- len)) ?\n)
(setq string (substring string 0 (1- len))))
- (if (string-search "\n" string)
- (split-string string "\n")
- (if (and eshell-convert-numeric-arguments
- (string-match
- (concat "\\`\\s-*" eshell-number-regexp
- "\\s-*\\'") string))
- (string-to-number string)
- string))))))
+ (if (string-search "\n" string)
+ (let ((lines (split-string string "\n")))
+ (if (seq-every-p #'eshell-convertible-to-number-p lines)
+ (mapcar #'string-to-number lines)
+ lines))
+ (eshell-convert-to-number string)))))))
(defvar-local eshell-path-env (getenv "PATH")
"Content of $PATH.
@@ -262,6 +293,7 @@ Prepend remote identification of `default-directory', if any."
(defun eshell-to-flat-string (value)
"Make value a string. If separated by newlines change them to spaces."
+ (declare (obsolete nil "29.1"))
(let ((text (eshell-stringify value)))
(if (string-match "\n+\\'" text)
(setq text (replace-match "" t t text)))
@@ -269,16 +301,6 @@ Prepend remote identification of `default-directory', if any."
(setq text (replace-match " " t t text)))
text))
-(defmacro eshell-for (for-var for-list &rest forms)
- "Iterate through a list."
- (declare (obsolete dolist "24.1"))
- (declare (indent 2))
- `(let ((list-iter ,for-list))
- (while list-iter
- (let ((,for-var (car list-iter)))
- ,@forms)
- (setq list-iter (cdr list-iter)))))
-
(define-obsolete-function-alias 'eshell-flatten-list #'flatten-tree "27.1")
(defun eshell-stringify (object)
@@ -589,11 +611,11 @@ list."
The optional argument ID-FORMAT specifies the preferred uid and
gid format. Valid values are `string' and `integer', defaulting to
`integer'. See `file-attributes'."
- (let* ((file (expand-file-name file))
+ (let* ((expanded-file (expand-file-name file))
entry)
- (if (string-equal (file-remote-p file 'method) "ftp")
- (let ((base (file-name-nondirectory file))
- (dir (file-name-directory file)))
+ (if (string-equal (file-remote-p expanded-file 'method) "ftp")
+ (let ((base (file-name-nondirectory expanded-file))
+ (dir (file-name-directory expanded-file)))
(if (string-equal "" base) (setq base "."))
(unless entry
(setq entry (eshell-parse-ange-ls dir))
@@ -609,6 +631,20 @@ gid format. Valid values are `string' and `integer', defaulting to
"If the `processp' function does not exist, PROC is not a process."
(and (fboundp 'processp) (processp proc)))
+(defun eshell-process-pair-p (procs)
+ "Return non-nil if PROCS is a pair of process objects."
+ (and (consp procs)
+ (eshell-processp (car procs))
+ (eshell-processp (cdr procs))))
+
+(defun eshell-make-process-pair (procs)
+ "Make a pair of process objects from PROCS if possible.
+This represents the head and tail of a pipeline of processes,
+where the head and tail may be the same process."
+ (pcase procs
+ ((pred eshell-processp) (cons procs procs))
+ ((pred eshell-process-pair-p) procs)))
+
;; (defun eshell-copy-file
;; (file newname &optional ok-if-already-exists keep-date)
;; "Copy FILE to NEWNAME. See docs for `copy-file'."
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 5c8dacd980e..17add9b6685 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -34,15 +34,11 @@
;;
;; "-" is a valid part of a variable name.
;;
-;; $<MYVAR>-TOO
+;; $\"MYVAR\"-TOO
+;; $'MYVAR'-TOO
;;
;; Only "MYVAR" is part of the variable name in this case.
;;
-;; $#VARIABLE
-;;
-;; Returns the length of the value of VARIABLE. This could also be
-;; done using the `length' Lisp function.
-;;
;; $(lisp)
;;
;; Returns result of Lisp evaluation. Note: Used alone like this, it
@@ -55,38 +51,40 @@
;; Returns the value of an eshell subcommand. See the note above
;; regarding Lisp evaluations.
;;
-;; $ANYVAR[10]
+;; $<command>
;;
-;; Return the 10th element of ANYVAR. If ANYVAR's value is a string,
-;; it will be split in order to make it a list. The splitting will
-;; occur at whitespace.
+;; Evaluates an eshell subcommand, redirecting the output to a
+;; temporary file, and returning the file name.
;;
-;; $ANYVAR[: 10]
+;; $EXPR[10]
;;
-;; As above, except that splitting occurs at the colon now.
+;; Return the 10th element of $EXPR, which can be any dollar
+;; expression. If $EXPR's value is a string, it will be split in
+;; order to make it a list. The splitting will occur at whitespace.
;;
-;; $ANYVAR[: 10 20]
+;; $EXPR[10 20]
;;
-;; As above, but instead of returning just a string, it now returns a
-;; list of two strings. If the result is being interpolated into a
-;; larger string, this list will be flattened into one big string,
-;; with each element separated by a space.
+;; As above, but instead of returning a single element, it now returns a
+;; list of two elements.
;;
-;; $ANYVAR["\\\\" 10]
+;; $EXPR[: 10]
+;;
+;; Like $EXPR[10], except that splitting occurs at the colon now.
+;;
+;; $EXPR["\\\\" 10]
;;
;; Separate on backslash characters. Actually, the first argument --
-;; if it doesn't have the form of a number, or a plain variable name
-;; -- can be any regular expression. So to split on numbers, use
-;; '$ANYVAR["[0-9]+" 10 20]'.
+;; if it doesn't have the form of a number -- can be any regular
+;; expression. So to split on numbers, use '$EXPR["[0-9]+" 10 20]'.
;;
-;; $ANYVAR[hello]
+;; $EXPR[hello]
;;
-;; Calls `assoc' on ANYVAR with 'hello', expecting it to be an alist.
+;; Calls `assoc' on $EXPR with 'hello', expecting it to be an alist.
;;
-;; $#ANYVAR[hello]
+;; $#EXPR
;;
-;; Returns the length of the cdr of the element of ANYVAR who car is
-;; equal to "hello".
+;; Returns the length of the value of $EXPR. This could also be
+;; done using the `length' Lisp function.
;;
;; There are also a few special variables defined by Eshell. '$$' is
;; the value of the last command (t or nil, in the case of an external
@@ -151,8 +149,8 @@ if they are quoted with a backslash."
(defcustom eshell-variable-aliases-list
`(;; for eshell.el
- ("COLUMNS" ,(lambda (_indices) (window-width)) t)
- ("LINES" ,(lambda (_indices) (window-height)) t)
+ ("COLUMNS" ,(lambda (_indices) (window-body-width nil 'remap)) t)
+ ("LINES" ,(lambda (_indices) (window-body-height nil 'remap)) t)
;; for eshell-cmd.el
("_" ,(lambda (indices)
@@ -187,7 +185,7 @@ list of the indices that was used in the reference, and whether the
user is requesting the length of the ultimate element. For example, a
reference of `$NAME[10][20]' would result in the function for alias
`NAME' being called (assuming it were aliased to a function), and the
-arguments passed to this function would be the list '(10 20)', and
+arguments passed to this function would be the list `(10 20)', and
nil.
If the value is a string, return the value for the variable with that
@@ -404,45 +402,63 @@ process any indices that come after the variable reference."
(let* ((get-len (when (eq (char-after) ?#)
(forward-char) t))
value indices)
- (setq value (eshell-parse-variable-ref)
+ (setq value (eshell-parse-variable-ref get-len)
indices (and (not (eobp))
(eq (char-after) ?\[)
(eshell-parse-indices))
;; This is an expression that will be evaluated by `eshell-do-eval',
;; which only support let-binding of dynamically-scoped vars
- value `(let ((indices ',indices)) ,value))
- (if get-len
- `(length ,value)
- value)))
-
-(defun eshell-parse-variable-ref ()
+ value `(let ((indices (eshell-eval-indices ',indices))) ,value))
+ (when get-len
+ (setq value `(length ,value)))
+ (when eshell-current-quoted
+ (setq value `(eshell-stringify ,value)))
+ value))
+
+(defun eshell-parse-variable-ref (&optional modifier-p)
"Eval a variable reference.
Returns a Lisp form which, if evaluated, will return the value of the
variable.
-Possible options are:
+If MODIFIER-P is non-nil, the value of the variable will be
+modified by some function. If MODIFIER-P is nil, the value will be
+used as-is; this allows optimization of some kinds of variable
+references.
+
+Possible variable references are:
NAME an environment or Lisp variable value
- <LONG-NAME> disambiguates the length of the name
+ \"LONG-NAME\" disambiguates the length of the name
+ `LONG-NAME' as above
{COMMAND} result of command is variable's value
- (LISP-FORM) result of Lisp form is variable's value"
+ (LISP-FORM) result of Lisp form is variable's value
+ <COMMAND> write the output of command to a temporary file;
+ result is the file name"
(cond
((eq (char-after) ?{)
(let ((end (eshell-find-delimiter ?\{ ?\})))
(if (not end)
(throw 'eshell-incomplete ?\{)
+ (forward-char)
(prog1
- `(eshell-convert
- (eshell-command-to-value
- (eshell-as-subcommand
- ,(eshell-parse-command (cons (1+ (point)) end)))))
+ `(eshell-apply-indices
+ (eshell-convert
+ (eshell-command-to-value
+ (eshell-as-subcommand
+ ,(let ((subcmd (or (eshell-unescape-inner-double-quote end)
+ (cons (point) end)))
+ (eshell-current-quoted nil))
+ (eshell-parse-command subcmd))))
+ ;; If this is a simple double-quoted form like
+ ;; "${COMMAND}" (i.e. no indices after the subcommand
+ ;; and no `#' modifier before), ensure we convert to a
+ ;; single string. This avoids unnecessary work
+ ;; (e.g. splitting the output by lines) when it would
+ ;; just be joined back together afterwards.
+ ,(when (and (not modifier-p) eshell-current-quoted)
+ '(not indices)))
+ indices ,eshell-current-quoted)
(goto-char (1+ end))))))
- ((memq (char-after) '(?\' ?\"))
- (let ((name (if (eq (char-after) ?\')
- (eshell-parse-literal-quote)
- (eshell-parse-double-quote))))
- (if name
- `(eshell-get-variable ,(eval name) indices))))
((eq (char-after) ?\<)
(let ((end (eshell-find-delimiter ?\< ?\>)))
(if (not end)
@@ -454,27 +470,47 @@ Possible options are:
`(let ((eshell-current-handles
(eshell-create-handles ,temp 'overwrite)))
(progn
- (eshell-as-subcommand ,(eshell-parse-command cmd))
+ (eshell-as-subcommand
+ ,(let ((eshell-current-quoted nil))
+ (eshell-parse-command cmd)))
(ignore
(nconc eshell-this-command-hook
- (list (lambda ()
- (delete-file ,temp)))))
- (quote ,temp)))
+ ;; Quote this lambda; it will be evaluated
+ ;; by `eshell-do-eval', which requires very
+ ;; particular forms in order to work
+ ;; properly. See bug#54190.
+ (list (function (lambda ()
+ (delete-file ,temp))))))
+ (eshell-apply-indices ,temp indices ,eshell-current-quoted)))
(goto-char (1+ end)))))))
((eq (char-after) ?\()
(condition-case nil
- `(eshell-command-to-value
- (eshell-lisp-command
- ',(read (current-buffer))))
+ `(eshell-apply-indices
+ (eshell-command-to-value
+ (eshell-lisp-command
+ ',(read (or (eshell-unescape-inner-double-quote (point-max))
+ (current-buffer)))))
+ indices ,eshell-current-quoted)
(end-of-file
(throw 'eshell-incomplete ?\())))
+ ((looking-at (rx-to-string
+ `(or "'" ,(if eshell-current-quoted "\\\"" "\""))))
+ (eshell-with-temp-command
+ (or (eshell-unescape-inner-double-quote (point-max))
+ (cons (point) (point-max)))
+ (let ((name (if (eq (char-after) ?\')
+ (eshell-parse-literal-quote)
+ (eshell-parse-double-quote))))
+ (when name
+ `(eshell-get-variable ,(eval name) indices ,eshell-current-quoted)))))
((assoc (char-to-string (char-after))
eshell-variable-aliases-list)
(forward-char)
- `(eshell-get-variable ,(char-to-string (char-before)) indices))
+ `(eshell-get-variable ,(char-to-string (char-before)) indices
+ ,eshell-current-quoted))
((looking-at eshell-variable-name-regexp)
(prog1
- `(eshell-get-variable ,(match-string 0) indices)
+ `(eshell-get-variable ,(match-string 0) indices ,eshell-current-quoted)
(goto-char (match-end 0))))
(t
(error "Invalid variable reference"))))
@@ -482,21 +518,33 @@ Possible options are:
(defvar eshell-glob-function)
(defun eshell-parse-indices ()
- "Parse and return a list of list of indices."
+ "Parse and return a list of index-lists.
+
+For example, \"[0 1][2]\" becomes:
+ ((\"0\" \"1\") (\"2\")."
(let (indices)
(while (eq (char-after) ?\[)
(let ((end (eshell-find-delimiter ?\[ ?\])))
(if (not end)
(throw 'eshell-incomplete ?\[)
(forward-char)
- (let (eshell-glob-function)
- (setq indices (cons (eshell-parse-arguments (point) end)
- indices)))
+ (eshell-with-temp-command (or (eshell-unescape-inner-double-quote end)
+ (cons (point) end))
+ (let (eshell-glob-function (eshell-current-quoted nil))
+ (setq indices (cons (eshell-parse-arguments
+ (point-min) (point-max))
+ indices))))
(goto-char (1+ end)))))
(nreverse indices)))
-(defun eshell-get-variable (name &optional indices)
- "Get the value for the variable NAME."
+(defun eshell-eval-indices (indices)
+ "Evaluate INDICES, a list of index-lists generated by `eshell-parse-indices'."
+ (mapcar (lambda (i) (mapcar #'eval i)) indices))
+
+(defun eshell-get-variable (name &optional indices quoted)
+ "Get the value for the variable NAME.
+INDICES is a list of index-lists (see `eshell-parse-indices').
+If QUOTED is non-nil, this was invoked inside double-quotes."
(let* ((alias (assoc name eshell-variable-aliases-list))
(var (if alias
(cadr alias)
@@ -517,9 +565,9 @@ Possible options are:
(symbol-value var))
(t
(error "Unknown variable `%s'" (eshell-stringify var))))
- indices))))
+ indices quoted))))
-(defun eshell-apply-indices (value indices)
+(defun eshell-apply-indices (value indices &optional quoted)
"Apply to VALUE all of the given INDICES, returning the sub-result.
The format of INDICES is:
@@ -528,12 +576,18 @@ The format of INDICES is:
Each member of INDICES represents a level of nesting. If the first
member of a sublist is not an integer or name, and the value it's
-reference is a string, that will be used as the regexp with which is
-to divide the string into sub-parts. The default is whitespace.
+referencing is a string, that will be used as the regexp with which
+is to divide the string into sub-parts. The default is whitespace.
Otherwise, each INT-OR-NAME refers to an element of the list value.
Integers imply a direct index, and names, an associate lookup using
`assoc'.
+If QUOTED is non-nil, this was invoked inside double-quotes.
+This affects the behavior of splitting strings: without quoting,
+the split values are converted to numbers via
+`eshell-convert-to-number' if possible; with quoting, they're
+left as strings.
+
For example, to retrieve the second element of a user's record in
'/etc/passwd', the variable reference would look like:
@@ -541,16 +595,14 @@ For example, to retrieve the second element of a user's record in
(while indices
(let ((refs (car indices)))
(when (stringp value)
- (let (separator)
- (if (not (or (not (stringp (caar indices)))
- (string-match
- (concat "^" eshell-variable-name-regexp "$")
- (caar indices))))
- (setq separator (caar indices)
- refs (cdr refs)))
- (setq value
- (mapcar #'eshell-convert
- (split-string value separator)))))
+ (let (separator (index (caar indices)))
+ (when (and (stringp index)
+ (not (get-text-property 0 'number index)))
+ (setq separator index
+ refs (cdr refs)))
+ (setq value (split-string value separator))
+ (unless quoted
+ (setq value (mapcar #'eshell-convert-to-number value)))))
(cond
((< (length refs) 0)
(error "Invalid array variable index: %s"
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 5c356e89289..2c472a2afad 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -332,9 +332,9 @@ With prefix ARG, insert output into the current buffer at point."
;; make the output as attractive as possible, with no
;; extraneous newlines
(when intr
- (if (eshell-interactive-process)
- (eshell-wait-for-process (eshell-interactive-process)))
- (cl-assert (not (eshell-interactive-process)))
+ (if (eshell-interactive-process-p)
+ (eshell-wait-for-process (eshell-tail-process)))
+ (cl-assert (not (eshell-interactive-process-p)))
(goto-char (point-max))
(while (and (bolp) (not (bobp)))
(delete-char -1)))
diff --git a/lisp/face-remap.el b/lisp/face-remap.el
index 95207959dd3..fd49c81ab3f 100644
--- a/lisp/face-remap.el
+++ b/lisp/face-remap.el
@@ -70,9 +70,28 @@
:foreground :background :stipple :overline :strike-through :box
:font :inherit :fontset :distant-foreground :extend :vector])
+(defun face-remap--copy-face (val)
+ "Return a copy of the `face' property value VAL."
+ ;; A `face' property can be either a face name (a symbol), or a face
+ ;; property list like (:foreground "red" :inherit default),
+ ;; or a list of such things.
+ ;; FIXME: This should probably be shared to some extent with
+ ;; `add-face-text-property'.
+ (if (or (not (listp val)) (keywordp (car val)))
+ val
+ (copy-sequence val)))
+
+(defun face-attrs--make-indirect-safe ()
+ "Deep-copy the buffer's `face-remapping-alist' upon cloning the buffer."
+ (setq-local face-remapping-alist
+ (mapcar #'face-remap--copy-face face-remapping-alist)))
+
+(add-hook 'clone-indirect-buffer-hook #'face-attrs--make-indirect-safe)
+
(defun face-attrs-more-relative-p (attrs1 attrs2)
- "Return true if ATTRS1 contains a greater number of relative
-face-attributes than ATTRS2. A face attribute is considered
+ "Return non-nil if ATTRS1 is \"more relative\" than ATTRS2.
+We define this as meaning that ATTRS1 contains a greater number of
+relative face-attributes than ATTRS2. A face attribute is considered
relative if `face-attribute-relative-p' returns non-nil.
ATTRS1 and ATTRS2 may be any value suitable for a `face' text
@@ -99,7 +118,7 @@ face lists so that more specific faces are located near the end."
"Order ENTRY so that more relative face specs are near the beginning.
The list structure of ENTRY may be destructively modified."
(setq entry (nreverse entry))
- (setcdr entry (sort (cdr entry) 'face-attrs-more-relative-p))
+ (setcdr entry (sort (cdr entry) #'face-attrs-more-relative-p))
(nreverse entry))
;;;###autoload
@@ -188,10 +207,12 @@ If SPECS is empty or a single face `eq' to FACE, call `face-remap-reset-base'
to use the normal definition of FACE as the base remapping; note that
this is different from SPECS containing a single value nil, which means
not to inherit from the global definition of FACE at all."
+ ;; Simplify the specs in the case where it's just a single face (and
+ ;; it's not a list with just a nil).
(while (and (consp specs) (not (null (car specs))) (null (cdr specs)))
(setq specs (car specs)))
(if (or (null specs)
- (and (eq (car specs) face) (null (cdr specs)))) ; default
+ (eq specs face)) ; default
;; Set entry back to default
(face-remap-reset-base face)
;; Set the base remapping
@@ -209,7 +230,8 @@ not to inherit from the global definition of FACE at all."
(defcustom text-scale-mode-step 1.2
"Scale factor used by `text-scale-mode'.
-Each positive or negative step scales the default face height by this amount."
+Each positive or negative step scales the size of the `default'
+face's font by this amount."
:group 'display
:type 'number
:version "23.1")
@@ -314,7 +336,7 @@ the same amount)."
;;;###autoload
(defun text-scale-increase (inc)
- "Increase the height of the default face in the current buffer by INC steps.
+ "Increase the font size of the default face in current buffer by INC steps.
If the new height is other than the default, `text-scale-mode' is enabled.
Each step scales the height of the default face by the variable
@@ -326,14 +348,14 @@ will remove any scaling currently active."
(new-value (if (= inc 0) 0 (+ current-value inc))))
(if (or (> new-value (text-scale-max-amount))
(< new-value (text-scale-min-amount)))
- (user-error "Cannot %s the default face height more than it already is"
+ (user-error "Cannot %s the font size any further"
(if (> inc 0) "increase" "decrease")))
(setq text-scale-mode-amount new-value))
(text-scale-mode (if (zerop text-scale-mode-amount) -1 1)))
;;;###autoload
(defun text-scale-decrease (dec)
- "Decrease the height of the default face in the current buffer by DEC steps.
+ "Decrease the font size of the default face in the current buffer by DEC steps.
See `text-scale-increase' for more details."
(interactive "p")
(text-scale-increase (- dec)))
@@ -344,19 +366,18 @@ See `text-scale-increase' for more details."
;;;###autoload (define-key ctl-x-map [(control ?0)] 'text-scale-adjust)
;;;###autoload
(defun text-scale-adjust (inc)
- "Adjust the height of the default face by INC.
-
+ "Adjust the font size in the current buffer by INC steps.
INC may be passed as a numeric prefix argument.
The actual adjustment made depends on the final component of the
keybinding used to invoke the command, with all modifiers removed:
- +, = Increase the height of the default face by one step
- - Decrease the height of the default face by one step
- 0 Reset the height of the default face to the global default
+ \\`+', \\`=' Increase font size in current buffer by one step
+ \\`-' Decrease font size in current buffer by one step
+ \\`0' Reset the font size to the global default
After adjusting, continue to read input events and further adjust
-the face height as long as the input event read
+the font size as long as the input event read
\(with all modifiers removed) is one of the above characters.
Each step scales the height of the default face by the variable
@@ -368,7 +389,14 @@ This command is a special-purpose wrapper around the
`text-scale-increase' command which makes repetition convenient
even when it is bound in a non-top-level keymap. For binding in
a top-level keymap, `text-scale-increase' or
-`text-scale-decrease' may be more appropriate."
+`text-scale-decrease' may be more appropriate.
+
+Most faces are affected by these font size changes, but not faces
+that have an explicit `:height' setting. The two exceptions to
+this are the `default' and `header-line' faces: they will both be
+scaled even if they have an explicit `:height' setting.
+
+See also the related command `global-text-scale-adjust'."
(interactive "p")
(let ((ev last-command-event)
(echo-keystrokes nil))
@@ -380,15 +408,15 @@ a top-level keymap, `text-scale-increase' or
(?0 0)
(_ inc))))
(text-scale-increase step)
- ;; (unless (zerop step)
- (message "Use +,-,0 for further adjustment")
(set-transient-map
(let ((map (make-sparse-keymap)))
(dolist (mods '(() (control)))
- (dolist (key '(?- ?+ ?= ?0)) ;; = is often unshifted +.
+ (dolist (key '(?+ ?= ?- ?0)) ;; = is often unshifted +.
(define-key map (vector (append mods (list key)))
(lambda () (interactive) (text-scale-adjust (abs inc))))))
- map))))) ;; )
+ map)
+ nil nil
+ "Use %k for further adjustment"))))
(defvar-local text-scale--pinch-start-scale 0
"The text scale at the start of a pinch sequence.")
@@ -400,15 +428,6 @@ a top-level keymap, `text-scale-increase' or
(interactive "e")
(when (not (eq (event-basic-type event) 'pinch))
(error "`text-scale-pinch' bound to bad event type"))
- (let ((evt))
- (catch 'done
- (while t
- (unless (and (setq evt (read-event nil nil 0.01))
- (eq (car evt) 'pinch))
- (throw 'done nil))))
- (when (and (consp evt)
- (eq (car evt) 'pinch))
- (setq event evt)))
(let ((window (posn-window (nth 1 event)))
(scale (nth 4 event))
(dx (nth 2 event))
@@ -424,6 +443,83 @@ a top-level keymap, `text-scale-increase' or
(+ text-scale--pinch-start-scale
(round (log scale text-scale-mode-step)))))))
+(defcustom global-text-scale-adjust-resizes-frames nil
+ "Whether `global-text-scale-adjust' resizes the frames."
+ :type '(choice (const :tag "Off" nil)
+ (const :tag "On" t))
+ :group 'display
+ :version "29.1")
+
+(defcustom global-text-scale-adjust-limits '(10 . 500)
+ "Min/max values for `global-text-scale-adjust'.
+This is a cons cell where the `car' has the minimum font size and
+the `cdr' has the maximum font size, in units of 1/10 pt."
+ :version "29.1"
+ :group 'display
+ :type '(cons (integer :tag "Min")
+ (integer :tag "Max")))
+
+(defvar global-text-scale-adjust--default-height nil)
+
+;;;###autoload (define-key ctl-x-map [(control meta ?+)] 'global-text-scale-adjust)
+;;;###autoload (define-key ctl-x-map [(control meta ?=)] 'global-text-scale-adjust)
+;;;###autoload (define-key ctl-x-map [(control meta ?-)] 'global-text-scale-adjust)
+;;;###autoload (define-key ctl-x-map [(control meta ?0)] 'global-text-scale-adjust)
+;;;###autoload
+(defun global-text-scale-adjust (increment)
+ "Globally adjust the font size by INCREMENT.
+
+Interactively, INCREMENT may be passed as a numeric prefix argument.
+
+The adjustment made depends on the final component of the key binding
+used to invoke the command, with all modifiers removed:
+
+ \\`+', \\`=' Globally increase the height of the default face
+ \\`-' Globally decrease the height of the default face
+ \\`0' Globally reset the height of the default face
+
+After adjusting, further adjust the font size as long as the key,
+with all modifiers removed, is one of the above characters.
+
+Buffer-local face adjustements have higher priority than global
+face adjustments.
+
+The variable `global-text-scale-adjust-resizes-frames' controls
+whether the frames are resized to keep the same number of lines
+and characters per line when the font size is adjusted.
+
+See also the related command `text-scale-adjust'."
+ (interactive "p")
+ (when (display-graphic-p)
+ (unless global-text-scale-adjust--default-height
+ (setq global-text-scale-adjust--default-height
+ (face-attribute 'default :height)))
+ (let* ((key (event-basic-type last-command-event))
+ (echo-keystrokes nil)
+ (cur (face-attribute 'default :height))
+ (inc
+ (pcase key
+ (?- (* (- increment) 5))
+ (?0 (- global-text-scale-adjust--default-height cur))
+ (_ (* increment 5))))
+ (new (+ cur inc)))
+ (when (< (car global-text-scale-adjust-limits)
+ new
+ (cdr global-text-scale-adjust-limits))
+ (let ((frame-inhibit-implied-resize
+ (not global-text-scale-adjust-resizes-frames)))
+ (set-face-attribute 'default nil :height new)))
+ (when (characterp key)
+ (set-transient-map
+ (let ((map (make-sparse-keymap)))
+ (dolist (mod '(() (control meta)))
+ (dolist (key '(?+ ?= ?- ?0))
+ (define-key map (vector (append mod (list key)))
+ 'global-text-scale-adjust)))
+ map)
+ nil nil
+ "Use %k for further adjustment")))))
+
;; ----------------------------------------------------------------
;; buffer-face-mode
diff --git a/lisp/faces.el b/lisp/faces.el
index df099787698..d104fdbc2fc 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -46,7 +46,8 @@ the terminal-initialization file to be loaded."
("vt320" . "vt200")
("vt400" . "vt200")
("vt420" . "vt200")
- ("alacritty" . "xterm"))
+ ("alacritty" . "xterm")
+ ("foot" . "xterm"))
"Alist of terminal type aliases.
Entries are of the form (TYPE . ALIAS), where both elements are strings.
This means to treat a terminal of type TYPE as if it were of type ALIAS."
@@ -448,6 +449,10 @@ of FACE on FRAME."
(defun face-attribute (face attribute &optional frame inherit)
"Return the value of FACE's ATTRIBUTE on FRAME.
+
+See `set-face-attribute' for the list of supported attributes
+and their meanings and allowed values.
+
If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.
@@ -511,6 +516,9 @@ FACES may be either a single face or a list of faces.
(defun face-foreground (face &optional frame inherit)
"Return the foreground color name of FACE, or nil if unspecified.
+On TTY frames, the returned color name can be \"unspecified-fg\",
+which stands for the unknown default foreground color of the display
+where the frame is displayed.
If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.
@@ -532,6 +540,9 @@ merging with the `default' face (which is always completely specified)."
(defun face-background (face &optional frame inherit)
"Return the background color name of FACE, or nil if unspecified.
+On TTY frames, the returned color name can be \"unspecified-bg\",
+which stands for the unknown default background color of the display
+where the frame is displayed.
If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.
@@ -663,7 +674,12 @@ face spec. It is mostly intended for internal use only.
If FRAME is nil, set the attributes for all existing frames, as
well as the default for new frames. If FRAME is t, change the
-default for new frames only.
+default for new frames only. As an exception, to reset the value
+of some attribute to `unspecified' in a way that overrides the
+non-`unspecified' value defined by the face's spec in `defface',
+for new frames, you must explicitly call this function with FRAME
+set to t and the attribute's value set to `unspecified'; just
+using FRAME of nil will not affect new frames in this case.
ARGS must come in pairs ATTRIBUTE VALUE. ATTRIBUTE must be a
valid face attribute name. All attributes can be set to
@@ -693,14 +709,14 @@ a.k.a. `regular'), `semi-expanded' (a.k.a. `demi-expanded'),
`:height'
-VALUE specifies the relative or absolute height of the font. An
-absolute height is an integer, and specifies font height in units
-of 1/10 pt. A relative height is either a floating point number,
-which specifies a scaling factor for the underlying face height;
-or a function that takes a single argument (the underlying face
-height) and returns the new height. Note that for the `default'
-face, you must specify an absolute height (since there is nothing
-for it to be relative to).
+VALUE specifies the relative or absolute font size (height of the
+font). An absolute height is an integer, and specifies font height in
+units of 1/10 pt. A relative height is either a floating point
+number, which specifies a scaling factor for the underlying face
+height; or a function that takes a single argument (the underlying
+face height) and returns the new height. Note that for the `default'
+face, you must specify an absolute height (since there is nothing for
+it to be relative to).
`:weight'
@@ -1065,6 +1081,9 @@ of the default face. Value is FACE."
(defvar crm-separator) ; from crm.el
+(defconst read-face-name-sample-text "SAMPLE"
+ "Text string to display as the sample text for `read-face-name'.")
+
(defun read-face-name (prompt &optional default multiple)
"Read one or more face names, prompting with PROMPT.
PROMPT should not end in a space or a colon.
@@ -1081,54 +1100,72 @@ That is, if DEFAULT is a list and MULTIPLE is nil, the first
element of DEFAULT is returned. If DEFAULT isn't a list, but
MULTIPLE is non-nil, a one-element list containing DEFAULT is
returned. Otherwise, DEFAULT is returned verbatim."
- (unless (listp default)
- (setq default (list default)))
- (when default
- (setq default
- (if multiple
- (mapconcat (lambda (f) (if (symbolp f) (symbol-name f) f))
- default ", ")
- ;; If we only want one, and the default is more than one,
- ;; discard the unwanted ones.
- (setq default (car default))
- (if (symbolp default)
- (symbol-name default)
- default))))
- (when (and default (not multiple))
- (require 'crm)
- ;; For compatibility with `completing-read-multiple' use `crm-separator'
- ;; to define DEFAULT if MULTIPLE is nil.
- (setq default (car (split-string default crm-separator t))))
-
- ;; Older versions of `read-face-name' did not append ": " to the
- ;; prompt, so there are third party libraries that have that in the
- ;; prompt. If so, remove it.
- (setq prompt (replace-regexp-in-string ": ?\\'" "" prompt))
- (let ((prompt (if default
- (format-prompt prompt default)
- (format "%s: " prompt)))
- aliasfaces nonaliasfaces faces)
- ;; Build up the completion tables.
- (mapatoms (lambda (s)
- (if (facep s)
- (if (get s 'face-alias)
- (push (symbol-name s) aliasfaces)
- (push (symbol-name s) nonaliasfaces)))))
- (if multiple
- (progn
- (dolist (face (completing-read-multiple
- prompt
- (completion-table-in-turn nonaliasfaces aliasfaces)
- nil t nil 'face-name-history default))
- ;; Ignore elements that are not faces
- ;; (for example, because DEFAULT was "all faces")
- (if (facep face) (push (intern face) faces)))
- (nreverse faces))
- (let ((face (completing-read
- prompt
- (completion-table-in-turn nonaliasfaces aliasfaces)
- nil t nil 'face-name-history default)))
- (if (facep face) (intern face))))))
+ (let (defaults)
+ (unless (listp default)
+ (setq default (list default)))
+ (when default
+ (setq default
+ (if multiple
+ (mapconcat (lambda (f) (if (symbolp f) (symbol-name f) f))
+ default ", ")
+ ;; If we only want one, and the default is more than one,
+ ;; discard the unwanted ones and use them only in the
+ ;; "future history" retrieved via `M-n M-n ...'.
+ (setq defaults default default (car default))
+ (if (symbolp default)
+ (symbol-name default)
+ default))))
+ (when (and default (not multiple))
+ (require 'crm)
+ ;; For compatibility with `completing-read-multiple' use `crm-separator'
+ ;; to define DEFAULT if MULTIPLE is nil.
+ (setq default (car (split-string default crm-separator t))))
+
+ ;; Older versions of `read-face-name' did not append ": " to the
+ ;; prompt, so there are third party libraries that have that in the
+ ;; prompt. If so, remove it.
+ (setq prompt (replace-regexp-in-string ": ?\\'" "" prompt))
+ (let ((prompt (if default
+ (format-prompt prompt default)
+ (format "%s: " prompt)))
+ (completion-extra-properties
+ '(:affixation-function
+ (lambda (faces)
+ (mapcar
+ (lambda (face)
+ (list face
+ (concat (propertize read-face-name-sample-text
+ 'face face)
+ "\t")
+ ""))
+ faces))))
+ aliasfaces nonaliasfaces faces)
+ ;; Build up the completion tables.
+ (mapatoms (lambda (s)
+ (if (facep s)
+ (if (get s 'face-alias)
+ (push (symbol-name s) aliasfaces)
+ (push (symbol-name s) nonaliasfaces)))))
+ (if multiple
+ (progn
+ (dolist (face (completing-read-multiple
+ prompt
+ (completion-table-in-turn nonaliasfaces aliasfaces)
+ nil t nil 'face-name-history default))
+ ;; Ignore elements that are not faces
+ ;; (for example, because DEFAULT was "all faces")
+ (if (facep face) (push (if (stringp face)
+ (intern face)
+ face)
+ faces)))
+ (nreverse faces))
+ (let ((face (completing-read
+ prompt
+ (completion-table-in-turn nonaliasfaces aliasfaces)
+ nil t nil 'face-name-history defaults)))
+ (when (facep face) (if (stringp face)
+ (intern face)
+ face)))))))
;; Not defined without X, but behind window-system test.
(defvar x-bitmap-file-path)
@@ -1176,8 +1213,9 @@ an integer value."
(:height
'integerp)
(:stipple
- (and (memq (window-system frame) '(x ns pgtk)) ; No stipple on w32 or haiku
- (mapcar #'list
+ (and (memq (window-system frame) '(x ns pgtk haiku)) ; No stipple on w32
+ (mapcar (lambda (item)
+ (cons item item))
(apply #'nconc
(mapcar (lambda (dir)
(and (file-readable-p dir)
@@ -1722,7 +1760,15 @@ The following sources are applied in this order:
(and tail (face-spec-set-2 face frame
(list :extend (cadr tail))))))
(setq face-attrs (face-spec-choose (get face 'face-override-spec) frame))
- (face-spec-set-2 face frame face-attrs)))
+ (face-spec-set-2 face frame face-attrs)
+ (when (and (fboundp 'set-frame-parameter) ; This isn't available
+ ; during loadup.
+ (eq face 'scroll-bar))
+ ;; Set the `scroll-bar-foreground' and `scroll-bar-background'
+ ;; frame parameters, because the face is handled by setting
+ ;; those two parameters. (bug#13476)
+ (set-frame-parameter frame 'scroll-bar-foreground (face-foreground face))
+ (set-frame-parameter frame 'scroll-bar-background (face-background face)))))
(defun face-spec-set-2 (face frame face-attrs)
"Set the face attributes of FACE on FRAME according to FACE-ATTRS.
@@ -1828,8 +1874,8 @@ on which one provides better contrast with COLOR."
"#ffffff" "black"))
(defconst color-luminance-dark-limit 0.325
- "The relative luminance below which a color is considered 'dark'.
-A 'dark' color in this sense provides better contrast with white
+ "The relative luminance below which a color is considered \"dark\".
+A \"dark\" color in this sense provides better contrast with white
than with black; see `color-dark-p'.
This value was determined experimentally.")
@@ -2057,11 +2103,17 @@ unnamed faces (e.g, `foreground-color')."
(face-attribute 'default attribute))))
(defun foreground-color-at-point ()
- "Return the foreground color of the character after point."
+ "Return the foreground color of the character after point.
+On TTY frames, the returned color name can be \"unspecified-fg\",
+which stands for the unknown default foreground color of the
+display where the frame is displayed."
(faces--attribute-at-point :foreground 'foreground-color))
(defun background-color-at-point ()
- "Return the background color of the character after point."
+ "Return the background color of the character after point.
+On TTY frames, the returned color name can be \"unspecified-bg\",
+which stands for the unknown default background color of the
+display where the frame is displayed."
(faces--attribute-at-point :background 'background-color))
@@ -2627,8 +2679,9 @@ non-nil."
:background "grey75" :foreground "black")
(t
:inverse-video t))
- "Face for the mode lines (for the selected window) as well as header lines.
-See `mode-line-display' for the face used on mode lines."
+ "Face for the mode lines as well as header lines.
+See `mode-line-active' and `mode-line-inactive' for the faces
+used on mode lines."
:version "21.1"
:group 'mode-line-faces
:group 'basic-faces)
@@ -2805,11 +2858,9 @@ used to display the prompt text."
:group 'frames
:group 'basic-faces)
-(defface scroll-bar
- '((((background light)) :foreground "black")
- (((background dark)) :foreground "white"))
+(defface scroll-bar '((t nil))
"Basic face for the scroll bar colors under X."
- :version "28.1"
+ :version "21.1"
:group 'frames
:group 'basic-faces)
@@ -2844,7 +2895,10 @@ Note: Other faces cannot inherit from the cursor face."
'((default
:box (:line-width 1 :style released-button)
:foreground "black")
- (((type x w32 ns haiku pgtk) (class color))
+ (((type haiku))
+ :foreground "B_MENU_ITEM_TEXT_COLOR"
+ :background "B_MENU_BACKGROUND_COLOR")
+ (((type x w32 ns pgtk) (class color))
:background "grey75")
(((type x) (class mono))
:background "grey"))
diff --git a/lisp/ffap.el b/lisp/ffap.el
index f9220817a71..9de0dd40d16 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1,6 +1,6 @@
;;; ffap.el --- find file (or url) at point -*- lexical-binding: t -*-
-;; Copyright (C) 1995-1997, 2000-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2022 Free Software Foundation, Inc.
;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -68,8 +68,8 @@
;; If you do not like these bindings, modify the variable
;; `ffap-bindings', or write your own.
;;
-;; If you use ange-ftp, browse-url, complete, efs, or w3, it is best
-;; to load or autoload them before ffap. If you use ff-paths, load it
+;; If you use ange-ftp, browse-url, complete, efs, it is best to load
+;; or autoload them before ffap. If you use ff-paths, load it
;; afterwards. Try apropos {C-h a ffap RET} to get a list of the many
;; option variables. In particular, if ffap is slow, try these:
;;
@@ -79,7 +79,7 @@
;; (setq ffap-shell-prompt-regexp nil) ; disable shell prompt stripping
;; (setq ffap-gopher-regexp nil) ; disable gopher bookmark matching
;;
-;; ffap uses `browse-url' (if found, else `w3-fetch') to fetch URL's.
+;; ffap uses `browse-url' to fetch URLs.
;; For a hairier `ffap-url-fetcher', try ffap-url.el (same ftp site).
;; Also, you can add `ffap-menu-rescan' to various hooks to fontify
;; the file and URL references within a buffer.
@@ -97,7 +97,6 @@
;; * break long menus into multiple panes (like imenu?)
;; * notice node in "(dired)Virtual Dired" (quotes, parentheses, whitespace)
;; * notice "machine.dom blah blah blah dir/file" (how?)
-;; * as w3 becomes standard, rewrite to rely more on its functions
;; * regexp options for ffap-string-at-point, like font-lock (MCOOK)
;; * v19: could replace `ffap-locate-file' with a quieter `locate-library'
;; * handle "$(VAR)" in Makefiles
@@ -282,7 +281,7 @@ For a fancy alternative, get `ffap-url.el'."
:risky t)
(defcustom ffap-next-regexp
- ;; If you want ffap-next to find URL's only, try this:
+ ;; If you want ffap-next to find URLs only, try this:
;; (and ffap-url-regexp (string-match "\\\\`" ffap-url-regexp)
;; (concat "\\<" (substring ffap-url-regexp 2))))
;;
@@ -315,7 +314,7 @@ disable ffap most of the time."
;;; Find Next Thing in buffer (`ffap-next'):
;;
-;; Original ffap-next-url (URL's only) from RPECK 30 Mar 1995. Since
+;; Original ffap-next-url (URLs only) from RPECK 30 Mar 1995. Since
;; then, broke it up into ffap-next-guess (noninteractive) and
;; ffap-next (a command). It now work on files as well as url's.
@@ -363,7 +362,7 @@ Actual search is done by the function `ffap-next-guess'."
(sit-for 0) ; display point movement
(find-file-at-point (ffap-prompter guess)))
(goto-char pt) ; restore point
- (message "No %sfiles or URL's found"
+ (message "No %sfiles or URLs found"
(if wrap "" "more ")))))
(defun ffap-next-url (&optional back wrap)
@@ -377,6 +376,12 @@ Actual search is done by the function `ffap-next-guess'."
;;; Machines (`ffap-machine-p'):
+(defun ffap-accept-or-reject-p (symbol)
+ "Return non-nil if SYMBOL is `accept' or `reject'.
+Otherwise, return nil. This is intended for use as the
+predicate in the `:safe' property of user options."
+ (memq symbol '(accept reject)))
+
;; I cannot decide a "best" strategy here, so these are variables. In
;; particular, if `Pinging...' is broken or takes too long on your
;; machine, try setting these all to accept or reject.
@@ -385,16 +390,21 @@ Actual search is done by the function `ffap-next-guess'."
Value should be a symbol, one of `ping', `accept', and `reject'."
:type '(choice (const ping)
(const accept)
- (const reject))
+ (const reject))
+ :safe #'ffap-accept-or-reject-p
:group 'ffap)
-(defcustom ffap-machine-p-known 'ping ; `accept' for higher speed
+
+(defcustom ffap-machine-p-known 'accept
"What `ffap-machine-p' does with hostnames that have a known domain.
Value should be a symbol, one of `ping', `accept', and `reject'.
See `mail-extr.el' for the known domains."
:type '(choice (const ping)
(const accept)
- (const reject))
- :group 'ffap)
+ (const reject))
+ :safe #'ffap-accept-or-reject-p
+ :group 'ffap
+ :version "29.1")
+
(defcustom ffap-machine-p-unknown 'reject
"What `ffap-machine-p' does with hostnames that have an unknown domain.
Value should be a symbol, one of `ping', `accept', and `reject'.
@@ -402,6 +412,7 @@ See `mail-extr.el' for the known domains."
:type '(choice (const ping)
(const accept)
(const reject))
+ :safe #'ffap-accept-or-reject-p
:group 'ffap)
(defun ffap-what-domain (domain)
@@ -544,6 +555,7 @@ The optional NOMODIFY argument suppresses the extra search."
(string-match ffap-rfs-regexp filename)
filename)))
+;;;###autoload
(defun ffap-machine-at-point ()
"Return machine name at point if it exists, or nil."
(let ((mach (ffap-string-at-point 'machine)))
@@ -1229,13 +1241,13 @@ If the region is active, return a string from the region.
If the point is in a comment, ensure that the returned string does not
contain the comment start characters (especially for major modes that
-have '//' as comment start characters).
+have \"//\" as comment start characters).
Set the variables `ffap-string-at-point' and
`ffap-string-at-point-region'.
When the region is active and larger than `ffap-max-region-length',
-return an empty string, and set `ffap-string-at-point-region' to '(1 1)."
+return an empty string, and set `ffap-string-at-point-region' to `(1 1)'."
(let* (dir-separator
(args
(cdr
@@ -1326,29 +1338,25 @@ Assumes the buffer has not changed."
;; Older: (apply 'copy-region-as-kill ffap-string-at-point-region)
(message "Copied to kill ring: %s" str))))
-;; External.
-(declare-function w3-view-this-url "ext:w3" (&optional no-show))
-
+;;;###autoload
(defun ffap-url-at-point ()
"Return URL from around point if it exists, or nil.
Sets the variable `ffap-string-at-point-region' to the bounds of URL, if any."
(when ffap-url-regexp
- (or (and (eq major-mode 'w3-mode) ; In a w3 buffer button?
- (w3-view-this-url t))
- (let ((thing-at-point-beginning-of-url-regexp ffap-url-regexp)
- (thing-at-point-default-mail-uri-scheme ffap-foo-at-bar-prefix)
- val)
- (setq val (thing-at-point-url-at-point ffap-lax-url
- (if (use-region-p)
- (cons (region-beginning)
- (region-end)))))
- (if val
- (let ((bounds (thing-at-point-bounds-of-url-at-point
- ffap-lax-url)))
- (setq ffap-string-at-point-region
- (list (car bounds) (cdr bounds)))))
- val))))
+ (let ((thing-at-point-beginning-of-url-regexp ffap-url-regexp)
+ (thing-at-point-default-mail-uri-scheme ffap-foo-at-bar-prefix)
+ val)
+ (setq val (thing-at-point-url-at-point ffap-lax-url
+ (if (use-region-p)
+ (cons (region-beginning)
+ (region-end)))))
+ (if val
+ (let ((bounds (thing-at-point-bounds-of-url-at-point
+ ffap-lax-url)))
+ (setq ffap-string-at-point-region
+ (list (car bounds) (cdr bounds)))))
+ val)))
(defvar ffap-gopher-regexp
"\\<\\(Type\\|Name\\|Path\\|Host\\|Port\\) *= *"
@@ -1449,10 +1457,13 @@ which may actually result in an URL rather than a filename."
(ffap-file-exists-string (substring name 0 (match-beginning 0)))))
;; If it contains a colon, get rid of it (and return if exists)
((and (string-match path-separator name)
- (setq name (ffap-string-at-point 'nocolon))
- (> (length name) 0)
- (ffap-file-exists-string name)))
- ;; File does not exist, try the alist:
+ (let ((this-name (ffap-string-at-point 'nocolon)))
+ ;; But don't interpret the first part if ":/bin" as
+ ;; the empty string.
+ (when (> (length this-name) 0)
+ (setq name this-name)
+ (ffap-file-exists-string name)))))
+ ;; File does not exist, try the alist:
((let ((alist ffap-alist) tem try case-fold-search)
(while (and alist (not try))
(setq tem (car alist) alist (cdr alist))
@@ -1486,12 +1497,7 @@ which may actually result in an URL rather than a filename."
((and (eq major-mode 'internal-ange-ftp-mode)
(string-match "^\\*ftp \\(.*\\)@\\(.*\\)\\*$"
(buffer-name)))
- (concat "/" (substring (buffer-name) 5 -1) ":"))
- ;; This is too often a bad idea:
- ;;((and (eq major-mode 'w3-mode)
- ;; (stringp url-current-server))
- ;; (host-to-ange-path url-current-server))
- )))
+ (concat "/" (substring (buffer-name) 5 -1) ":")))))
(and remote-dir
(or
(and (string-match "\\`\\(/?~?ftp\\)/" name)
@@ -1865,7 +1871,7 @@ Return value:
;;; ffap-other-*, ffap-read-only-*, ffap-alternate-* commands:
;; There could be a real `ffap-noselect' function, but we would need
-;; at least two new user variables, and there is no w3-fetch-noselect.
+;; at least two new user variables.
;; So instead, we just fake it with a slow save-window-excursion.
(defun ffap-other-window (filename)
diff --git a/lisp/files-x.el b/lisp/files-x.el
index e86ba8f8d04..da1e44e2504 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -81,8 +81,7 @@ Intended to be used in the `interactive' spec of
(let ((default (format "%S"
(cond ((eq variable 'unibyte) t)
((boundp variable)
- (symbol-value variable)))))
- (minibuffer-completing-symbol t))
+ (symbol-value variable))))))
(read-from-minibuffer (format "Add %s with value: " variable)
nil read-expression-map t
'set-variable-value-history
@@ -502,24 +501,26 @@ from the MODE alist ignoring the input argument VALUE."
((and (symbolp (car b)) (stringp (car a))) nil)
(t (string< (car a) (car b)))))))
(current-buffer))
+ (when (eobp) (insert "\n"))
(goto-char (point-min))
(indent-sexp))))
(defun dir-locals-to-string (variables)
"Output alists of VARIABLES to string in dotted pair notation syntax."
- (format "(%s)" (mapconcat
- (lambda (mode-variables)
- (format "(%S . %s)"
- (car mode-variables)
- (format "(%s)" (mapconcat
- (lambda (variable-value)
- (format "(%S . %s)"
- (car variable-value)
- (string-trim-right
- (pp-to-string
- (cdr variable-value)))))
- (cdr mode-variables) "\n"))))
- variables "\n")))
+ (format "(%s)"
+ (mapconcat
+ (lambda (mode-variables)
+ (format "(%S . %s)"
+ (car mode-variables)
+ (format "(%s)" (mapconcat
+ (lambda (variable-value)
+ (format "(%S . %s)"
+ (car variable-value)
+ (string-trim-right
+ (pp-to-string
+ (cdr variable-value)))))
+ (cdr mode-variables) "\n"))))
+ variables "\n")))
;;;###autoload
(defun add-dir-local-variable (mode variable value)
@@ -579,15 +580,22 @@ changed by the user.")
(setq ignored-local-variables
(cons 'connection-local-variables-alist ignored-local-variables))
-(defvar connection-local-profile-alist nil
+(defcustom connection-local-profile-alist nil
"Alist mapping connection profiles to variable lists.
Each element in this list has the form (PROFILE VARIABLES).
PROFILE is the name of a connection profile (a symbol).
VARIABLES is a list that declares connection-local variables for
PROFILE. An element in VARIABLES is an alist whose elements are
-of the form (VAR . VALUE).")
-
-(defvar connection-local-criteria-alist nil
+of the form (VAR . VALUE)."
+ :type '(repeat (cons (symbol :tag "Profile")
+ (repeat :tag "Variables"
+ (cons (symbol :tag "Variable")
+ (sexp :tag "Value")))))
+ :group 'files
+ :group 'tramp
+ :version "29.1")
+
+(defcustom connection-local-criteria-alist nil
"Alist mapping connection criteria to connection profiles.
Each element in this list has the form (CRITERIA PROFILES).
CRITERIA is a plist identifying a connection and the application
@@ -596,7 +604,19 @@ using this connection. Property names might be `:application',
`:application' is a symbol, all other property values are
strings. All properties are optional; if CRITERIA is nil, it
always applies.
-PROFILES is a list of connection profiles (symbols).")
+PROFILES is a list of connection profiles (symbols)."
+ :type '(repeat (cons (plist :tag "Criteria"
+ ;; Give the most common options as checkboxes.
+ :options (((const :format "%v " :application)
+ symbol)
+ ((const :format "%v " :protocol) string)
+ ((const :format "%v " :user) string)
+ ((const :format "%v " :machine) string)))
+ (repeat :tag "Profiles"
+ (symbol :tag "Profile"))))
+ :group 'files
+ :group 'tramp
+ :version "29.1")
(defsubst connection-local-normalize-criteria (criteria)
"Normalize plist CRITERIA according to properties.
@@ -649,7 +669,9 @@ variables for a connection profile are defined using
(setcdr slot (delete-dups (append (cdr slot) profiles)))
(setq connection-local-criteria-alist
(cons (cons criteria (delete-dups profiles))
- connection-local-criteria-alist)))))
+ connection-local-criteria-alist))))
+ (customize-set-variable
+ 'connection-local-criteria-alist connection-local-criteria-alist))
(defsubst connection-local-get-profile-variables (profile)
"Return the connection-local variable list for PROFILE."
@@ -668,7 +690,9 @@ connection profile using `connection-local-set-profiles'. Then
variables are set in the server's process buffer according to the
VARIABLES list of the connection profile. The list is processed
in order."
- (setf (alist-get profile connection-local-profile-alist) variables))
+ (setf (alist-get profile connection-local-profile-alist) variables)
+ (customize-set-variable
+ 'connection-local-profile-alist connection-local-profile-alist))
(defun hack-connection-local-variables (criteria)
"Read connection-local variables according to CRITERIA.
@@ -699,36 +723,46 @@ will not be changed."
(copy-tree connection-local-variables-alist)))
(hack-local-variables-apply)))
+(defvar connection-local-default-application 'tramp
+ "Default application in connection-local functions, a symbol.
+This variable must not be changed globally.")
+
(defsubst connection-local-criteria-for-default-directory (&optional application)
"Return a connection-local criteria, which represents `default-directory'.
-If APPLICATION is nil, the symbol `tramp' is used."
+If APPLICATION is nil, `connection-local-default-application' is used."
(when (file-remote-p default-directory)
- `(:application ,(or application 'tramp)
- :protocol ,(file-remote-p default-directory 'method)
- :user ,(file-remote-p default-directory 'user)
- :machine ,(file-remote-p default-directory 'host))))
+ `(:application ,(or application connection-local-default-application)
+ :protocol ,(file-remote-p default-directory 'method)
+ :user ,(file-remote-p default-directory 'user)
+ :machine ,(file-remote-p default-directory 'host))))
;;;###autoload
(defmacro with-connection-local-variables (&rest body)
"Apply connection-local variables according to `default-directory'.
Execute BODY, and unwind connection-local variables."
(declare (debug t))
- `(if (file-remote-p default-directory)
- (let ((enable-connection-local-variables t)
- (old-buffer-local-variables (buffer-local-variables))
- connection-local-variables-alist)
- (hack-connection-local-variables-apply
- (connection-local-criteria-for-default-directory))
- (unwind-protect
- (progn ,@body)
- ;; Cleanup.
- (dolist (variable connection-local-variables-alist)
- (let ((elt (assq (car variable) old-buffer-local-variables)))
- (if elt
- (set (make-local-variable (car elt)) (cdr elt))
- (kill-local-variable (car variable)))))))
- ;; No connection-local variables to apply.
- ,@body))
+ `(with-connection-local-variables-1 (lambda () ,@body)))
+
+;;;###autoload
+(defun with-connection-local-variables-1 (body-fun)
+ "Apply connection-local variables according to `default-directory'.
+Call BODY-FUN with no args, and then unwind connection-local variables."
+ (if (file-remote-p default-directory)
+ (let ((enable-connection-local-variables t)
+ (old-buffer-local-variables (buffer-local-variables))
+ connection-local-variables-alist)
+ (hack-connection-local-variables-apply
+ (connection-local-criteria-for-default-directory))
+ (unwind-protect
+ (funcall body-fun)
+ ;; Cleanup.
+ (dolist (variable connection-local-variables-alist)
+ (let ((elt (assq (car variable) old-buffer-local-variables)))
+ (if elt
+ (set (make-local-variable (car elt)) (cdr elt))
+ (kill-local-variable (car variable)))))))
+ ;; No connection-local variables to apply.
+ (funcall body-fun)))
;;;###autoload
(defun path-separator ()
diff --git a/lisp/files.el b/lisp/files.el
index a11786fca2c..b99ccf66d8a 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -304,19 +304,17 @@ When nil, make them for files that have some already.
The value `never' means do not make them."
:type '(choice (const :tag "Never" never)
(const :tag "If existing" nil)
- (other :tag "Always" t))
+ (other :tag "Always" t))
+ :safe #'version-control-safe-local-p
:group 'backup)
(defun version-control-safe-local-p (x)
"Return whether X is safe as local value for `version-control'."
(or (booleanp x) (equal x 'never)))
-(put 'version-control 'safe-local-variable
- #'version-control-safe-local-p)
-
(defcustom dired-kept-versions 2
"When cleaning directory, number of versions to keep."
- :type 'integer
+ :type 'natnum
:group 'backup
:group 'dired)
@@ -330,16 +328,16 @@ If nil, ask confirmation. Any other value prevents any trimming."
(defcustom kept-old-versions 2
"Number of oldest versions to keep when a new numbered backup is made."
- :type 'integer
+ :type 'natnum
+ :safe #'natnump
:group 'backup)
-(put 'kept-old-versions 'safe-local-variable 'integerp)
(defcustom kept-new-versions 2
"Number of newest versions to keep when a new numbered backup is made.
Includes the new backup. Must be greater than 0."
- :type 'integer
+ :type 'natnum
+ :safe #'natnump
:group 'backup)
-(put 'kept-new-versions 'safe-local-variable 'integerp)
(defcustom require-final-newline nil
"Whether to add a newline automatically at the end of the file.
@@ -443,18 +441,60 @@ idle for `auto-save-visited-interval' seconds."
(when auto-save--timer
(timer-set-idle-time auto-save--timer value :repeat))))
+(defcustom auto-save-visited-predicate nil
+ "Predicate function for `auto-save-visited-mode'.
+
+If non-nil, the value should be a function of no arguments; it
+will be called once in each file-visiting buffer when the time
+comes to auto-save. A buffer will be saved only if the predicate
+function returns a non-nil value.
+
+For example, you could add this to your Init file to only save
+files that are both in Org mode and in a particular directory:
+
+ (setq auto-save-visited-predicate
+ (lambda () (and (eq major-mode \\='org-mode)
+ (string-match \"^/home/skangas/org/\"
+ buffer-file-name))))
+
+If the value of this variable is not a function, it is ignored.
+This is the same as having a predicate that always returns
+non-nil."
+ :group 'auto-save
+ :type '(choice :tag "Function:"
+ (const :tag "No extra predicate" :value nil)
+ (function :tag "Predicate function" :value always))
+ :risky t
+ :version "29.1")
+
+(defcustom remote-file-name-inhibit-auto-save-visited nil
+ "When nil, `auto-save-visited-mode' will auto-save remote files.
+Any other value means that it will not."
+ :group 'auto-save
+ :type 'boolean
+ :version "29.1")
+
(define-minor-mode auto-save-visited-mode
- "Toggle automatic saving to file-visiting buffers on or off.
+ "Toggle automatic saving of file-visiting buffers to their files.
+
+When this mode is enabled, file-visiting buffers are automatically
+saved to their files. This is in contrast to `auto-save-mode', which
+auto-saves those buffers to a separate file, leaving the original
+file intact. See Info node `Saving' for details of the save process.
-Unlike `auto-save-mode', this mode will auto-save buffer contents
-to the visited files directly and will also run all save-related
-hooks. See Info node `Saving' for details of the save process.
+The user option `auto-save-visited-interval' controls how often to
+auto-save a buffer into its visited file.
+
+You can use `auto-save-visited-predicate' to control which
+buffers are saved.
You can also set the buffer-local value of the variable
`auto-save-visited-mode' to nil. A buffer where the buffer-local
value of this variable is nil is ignored for the purpose of
`auto-save-visited-mode', even if `auto-save-visited-mode' is
-enabled."
+enabled.
+
+For more details, see Info node `(emacs) Auto Save Files'."
:group 'auto-save
:global t
(when auto-save--timer (cancel-timer auto-save--timer))
@@ -467,7 +507,11 @@ enabled."
(and buffer-file-name
auto-save-visited-mode
(not (and buffer-auto-save-file-name
- auto-save-visited-file-name))))))))
+ auto-save-visited-file-name))
+ (or (not (file-remote-p buffer-file-name))
+ (not remote-file-name-inhibit-auto-save-visited))
+ (or (not (functionp auto-save-visited-predicate))
+ (funcall auto-save-visited-predicate))))))))
;; The 'set' part is so we don't get a warning for using this variable
;; above, while still catching code that _sets_ the variable to get
@@ -483,12 +527,16 @@ If `silently', don't ask the user before saving."
(defcustom lock-file-name-transforms nil
"Transforms to apply to buffer file name before making a lock file name.
-This has the same syntax as
-`auto-save-file-name-transforms' (which see), but instead of
-applying to auto-save file names, it's applied to lock file names.
+This has the same syntax as `auto-save-file-name-transforms',
+but applies to lock file names instead of auto-save file names.
+
+By default, Emacs puts each lock file into the same directory as the
+file it locks, prepending \".#\" to the base file name.
-By default, a lock file is put into the same directory as the
-file it's locking, and it has the same name, but with \".#\" prepended."
+Note that changing this could break lock file functionality, e.g.:
+if different users access the same file, using different lock file settings;
+if accessing files on a shared file system from different hosts,
+using a transform that puts the lock files on a local file system."
:group 'files
:type '(repeat (list (regexp :tag "Regexp")
(string :tag "Replacement")
@@ -983,10 +1031,7 @@ one or more of those symbols."
(logior (if (memq 'executable predicate) 1 0)
(if (memq 'writable predicate) 2 0)
(if (memq 'readable predicate) 4 0))))
- (let ((file (locate-file-internal filename path suffixes predicate)))
- (if (and file (string-match "\\.eln\\'" file))
- (gethash (file-name-nondirectory file) comp-eln-to-el-h)
- file)))
+ (locate-file-internal filename path suffixes predicate))
(defun locate-file-completion-table (dirs suffixes string pred action)
"Do completion for file names passed to `locate-file'."
@@ -1114,10 +1159,17 @@ directory if it does not exist."
(if (file-directory-p user-emacs-directory)
(or (file-accessible-directory-p user-emacs-directory)
(setq errtype "access"))
- (with-file-modes ?\700
- (condition-case nil
- (make-directory user-emacs-directory t)
- (error (setq errtype "create")))))
+ ;; We don't want to create HOME if it doesn't exist.
+ (if (and (not (file-exists-p "~"))
+ (string-prefix-p
+ (expand-file-name "~")
+ (expand-file-name user-emacs-directory)))
+ (setq errtype "create")
+ ;; Create `user-emacs-directory'.
+ (with-file-modes ?\700
+ (condition-case nil
+ (make-directory user-emacs-directory t)
+ (error (setq errtype "create"))))))
(when (and errtype
user-emacs-directory-warning
(not (get 'user-emacs-directory-warning 'this-session)))
@@ -1242,8 +1294,8 @@ Tip: You can use this expansion of remote identifier components
(defcustom remote-file-name-inhibit-cache 10
"Whether to use the remote file-name cache for read access.
-When nil, never expire cached values (caution)
-When t, never use the cache (safe, but may be slow)
+When nil, never expire cached values (caution).
+When t, never use the cache (safe, but may be slow).
A number means use cached values for that amount of seconds since caching.
The attributes of remote files are cached for better performance.
@@ -1489,8 +1541,13 @@ in all cases, since that is the standard symbol for byte."
(if (string= prefix "") "" "i")
(or unit "B"))
(concat prefix unit))))
- (format (if (and (>= (mod file-size 1.0) 0.05)
+ ;; Mimic what GNU "ls -lh" does:
+ ;; If the formatted size will have just one digit before the decimal...
+ (format (if (and (< file-size 10)
+ ;; ...and its fractional part is not too small...
+ (>= (mod file-size 1.0) 0.05)
(< (mod file-size 1.0) 0.95))
+ ;; ...then emit one digit after the decimal.
"%.1f%s%s"
"%.0f%s%s")
file-size
@@ -1727,19 +1784,18 @@ rather than FUN itself, to `minibuffer-setup-hook'."
(defun find-file (filename &optional wildcards)
"Edit file FILENAME.
-Switch to a buffer visiting file FILENAME,
-creating one if none already exists.
+\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none
+already exists.
Interactively, the default if you just type RET is the current directory,
but the visited file name is available through the minibuffer history:
type \\[next-history-element] to pull it into the minibuffer.
-The first time \\[next-history-element] is used after Emacs prompts for
-the file name, the result is affected by `file-name-at-point-functions',
-which by default try to guess the file name by looking at point in the
-current buffer. Customize the value of `file-name-at-point-functions'
-or set it to nil, if you want only the visited file name and the
-current directory to be available on first \\[next-history-element]
-request.
+The first time \\[next-history-element] is used after Emacs prompts for the file name,
+the result is affected by `file-name-at-point-functions', which by
+default try to guess the file name by looking at point in the current
+buffer. Customize the value of `file-name-at-point-functions' or set
+it to nil, if you want only the visited file name and the current
+directory to be available on first \\[next-history-element] request.
You can visit files on remote machines by specifying something
like /ssh:SOME_REMOTE_MACHINE:FILE for the file name. You can
@@ -1752,7 +1808,7 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp,
expand wildcards (if any) and visit multiple files. You can
suppress wildcard expansion by setting `find-file-wildcards' to nil.
-To visit a file without any kind of conversion and without
+\\<global-map>To visit a file without any kind of conversion and without
automatically choosing a major mode, use \\[find-file-literally]."
(interactive
(find-file-read-args "Find file: "
@@ -1768,6 +1824,7 @@ automatically choosing a major mode, use \\[find-file-literally]."
Like \\[find-file] (which see), but creates a new window or reuses
an existing one. See the function `display-buffer'.
+\\<minibuffer-local-map>\
Interactively, the default if you just type RET is the current directory,
but the visited file name is available through the minibuffer history:
type \\[next-history-element] to pull it into the minibuffer.
@@ -1800,6 +1857,7 @@ expand wildcards (if any) and visit multiple files."
Like \\[find-file] (which see), but creates a new frame or reuses
an existing one. See the function `display-buffer'.
+\\<minibuffer-local-map>\
Interactively, the default if you just type RET is the current directory,
but the visited file name is available through the minibuffer history:
type \\[next-history-element] to pull it into the minibuffer.
@@ -2095,8 +2153,11 @@ started Emacs, set `abbreviated-home-dir' to nil so it will be recalculated)."
"Return the buffer visiting file FILENAME (a string).
This is like `get-file-buffer', except that it checks for any buffer
visiting the same file, possibly under a different name.
+
If PREDICATE is non-nil, only buffers satisfying it are eligible,
-and others are ignored.
+and others are ignored. PREDICATE is called with the buffer as
+the only argument, but not with the buffer as the current buffer.
+
If there is no such live buffer, return nil."
(let ((predicate (or predicate #'identity))
(truename (abbreviate-file-name (file-truename filename))))
@@ -2317,7 +2378,16 @@ the various files."
(attributes (file-attributes truename))
(number (nthcdr 10 attributes))
;; Find any buffer for a file that has same truename.
- (other (and (not buf) (find-buffer-visiting filename))))
+ (other (and (not buf)
+ (find-buffer-visiting
+ filename
+ ;; We want to filter out buffers that we've
+ ;; visited via symlinks and the like, where
+ ;; the symlink no longer exists.
+ (lambda (buffer)
+ (let ((file (buffer-local-value
+ 'buffer-file-name buffer)))
+ (and file (file-exists-p file))))))))
;; Let user know if there is a buffer with the same truename.
(if other
(progn
@@ -2753,8 +2823,7 @@ since only a single case-insensitive search through the alist is made."
(defvar auto-mode-alist
;; Note: The entries for the modes defined in cc-mode.el (c-mode,
;; c++-mode, java-mode and more) are added through autoload
- ;; directives in that file. That way is discouraged since it
- ;; spreads out the definition of the initial value.
+ ;; directives in that file.
(mapcar
(lambda (elt)
(cons (purecopy (car elt)) (cdr elt)))
@@ -2779,6 +2848,9 @@ since only a single case-insensitive search through the alist is made."
;; .dir-locals.el is not really Elisp. Could use the
;; `dir-locals-file' constant if it weren't defined below.
("\\.dir-locals\\(?:-2\\)?\\.el\\'" . lisp-data-mode)
+ ("\\.eld\\'" . lisp-data-mode)
+ ;; FIXME: The lisp-data-mode files below should use the `.eld' extension
+ ;; (or a -*- mode cookie) so we don't need ad-hoc entries here.
("eww-bookmarks\\'" . lisp-data-mode)
("tramp\\'" . lisp-data-mode)
("/archive-contents\\'" . lisp-data-mode)
@@ -2925,7 +2997,7 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|CBR\\|7Z\\|SQUASHFS\\)\\'" .
("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode)
("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MS-DOS
("\\.[eE]?[pP][sS]\\'" . ps-mode)
- ("\\.\\(?:PDF\\|DVI\\|OD[FGPST]\\|DOCX\\|XLSX?\\|PPTX?\\|pdf\\|djvu\\|dvi\\|od[fgpst]\\|docx\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe)
+ ("\\.\\(?:PDF\\|EPUB\\|CBZ\\|FB2\\|O?XPS\\|DVI\\|OD[FGPST]\\|DOCX\\|XLSX?\\|PPTX?\\|pdf\\|epub\\|cbz\\|fb2\\|o?xps\\|djvu\\|dvi\\|od[fgpst]\\|docx\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe)
("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode)
("BROWSE\\'" . ebrowse-tree-mode)
@@ -3052,8 +3124,7 @@ and `magic-mode-alist', which determines modes based on file contents.")
(defvar interpreter-mode-alist
;; Note: The entries for the modes defined in cc-mode.el (awk-mode
;; and pike-mode) are added through autoload directives in that
- ;; file. That way is discouraged since it spreads out the
- ;; definition of the initial value.
+ ;; file.
(mapcar
(lambda (l)
(cons (purecopy (car l)) (cdr l)))
@@ -3091,9 +3162,6 @@ major mode MODE.
See also `auto-mode-alist'.")
-(define-obsolete-variable-alias 'inhibit-first-line-modes-regexps
- 'inhibit-file-local-variables-regexps "24.1")
-
;; TODO really this should be a list of modes (eg tar-mode), not regexps,
;; because we are duplicating info from auto-mode-alist.
;; TODO many elements of this list are also in auto-coding-alist.
@@ -3114,9 +3182,6 @@ member files with their own local variable sections, which are
not appropriate for the containing file.
The function `inhibit-local-variables-p' uses this.")
-(define-obsolete-variable-alias 'inhibit-first-line-modes-suffixes
- 'inhibit-local-variables-suffixes "24.1")
-
(defvar inhibit-local-variables-suffixes nil
"List of regexps matching suffixes to remove from file names.
The function `inhibit-local-variables-p' uses this: when checking
@@ -3245,6 +3310,7 @@ extra checks should be done."
(let ((case-fold-search t))
(assoc-default name alist 'string-match))))))
(if (and mode
+ (not (functionp mode))
(consp mode)
(cadr mode))
(setq mode (car mode)
@@ -3637,7 +3703,7 @@ DIR-NAME is the name of the associated directory. Otherwise it is nil."
(cond
(unsafe-vars
(insert "The local variables list in " name
- "\ncontains values that may not be safe (*)"
+ "\nor .dir-locals.el contains values that may not be safe (*)"
(if risky-vars
", and variables that are risky (**)."
".")))
@@ -3736,8 +3802,8 @@ return as the symbol specifying the mode."
(while (not (or (and (eq handle-mode t) result)
(>= (point) end)))
(unless (looking-at hack-local-variable-regexp)
- (message "Malformed mode-line: %S"
- (buffer-substring-no-properties (point) end))
+ (message "Malformed mode-line: %S in buffer %S"
+ (buffer-substring-no-properties (point) end) (buffer-name))
(throw 'malformed-line nil))
(goto-char (match-end 0))
;; There used to be a downcase here,
@@ -3894,8 +3960,8 @@ inhibited."
(with-demoted-errors "Directory-local variables error: %s"
;; Note this is a no-op if enable-local-variables is nil.
(hack-dir-local-variables))
- (let ((result (append (hack-local-variables--find-variables)
- (hack-local-variables-prop-line))))
+ (let ((result (append (hack-local-variables--find-variables handle-mode)
+ (hack-local-variables-prop-line handle-mode))))
(if (and enable-local-variables
(not (inhibit-local-variables-p)))
(progn
@@ -3964,22 +4030,21 @@ major-mode."
;; Discard the prefix.
(if (looking-at prefix)
(delete-region (point) (match-end 0))
- (error "Local variables entry is missing the prefix"))
+ (user-error "Local variables entry is missing the prefix"))
(end-of-line)
;; Discard the suffix.
(if (looking-back suffix (line-beginning-position))
(delete-region (match-beginning 0) (point))
- (error "Local variables entry is missing the suffix"))
+ (user-error "Local variables entry is missing the suffix"))
(forward-line 1))
(goto-char (point-min))
- (while (not (or (eobp)
- (and (eq handle-mode t) result)))
+ (while (not (eobp))
;; Find the variable name;
(unless (looking-at hack-local-variable-regexp)
- (error "Malformed local variable line: %S"
- (buffer-substring-no-properties
- (point) (line-end-position))))
+ (user-error "Malformed local variable line: %S"
+ (buffer-substring-no-properties
+ (point) (line-end-position))))
(goto-char (match-end 1))
(let* ((str (match-string 1))
(var (intern str))
@@ -4000,7 +4065,8 @@ major-mode."
(not (string-match
"-minor\\'"
(setq val2 (downcase (symbol-name val)))))
- (setq result (intern (concat val2 "-mode"))))
+ ;; Allow several mode: elements.
+ (push (intern (concat val2 "-mode")) result))
(cond ((eq var 'coding))
((eq var 'lexical-binding)
(unless hack-local-variables--warned-lexical
@@ -4024,7 +4090,10 @@ major-mode."
val)
result))))))
(forward-line 1)))))))
- result))
+ (if (eq handle-mode t)
+ ;; Return the final mode: setting that's defined.
+ (car (seq-filter #'fboundp result))
+ result)))
(defun hack-local-variables-apply ()
"Apply the elements of `file-local-variables-alist'.
@@ -4058,7 +4127,8 @@ It is safe if any of these conditions are met:
(and (functionp safep)
;; If the function signals an error, that means it
;; can't assure us that the value is safe.
- (with-demoted-errors (funcall safep val))))))
+ (with-demoted-errors "Local variable error: %S"
+ (funcall safep val))))))
(defun risky-local-variable-p (sym &optional _ignored)
"Non-nil if SYM could be dangerous as a file-local variable.
@@ -4083,11 +4153,8 @@ It is dangerous if either of these conditions are met:
(defun hack-one-local-variable-quotep (exp)
(and (consp exp) (eq (car exp) 'quote) (consp (cdr exp))))
-(defun hack-one-local-variable-constantp (exp)
- (or (and (not (symbolp exp)) (not (consp exp)))
- (memq exp '(t nil))
- (keywordp exp)
- (hack-one-local-variable-quotep exp)))
+(define-obsolete-function-alias 'hack-one-local-variable-constantp
+ #'macroexp-const-p "29.1")
(defun hack-one-local-variable-eval-safep (exp)
"Return non-nil if it is safe to eval EXP when it is found in a file."
@@ -4125,7 +4192,7 @@ It is dangerous if either of these conditions are met:
(cond ((eq prop t)
(let ((ok t))
(dolist (arg (cdr exp))
- (unless (hack-one-local-variable-constantp arg)
+ (unless (macroexp-const-p arg)
(setq ok nil)))
ok))
((functionp prop)
@@ -4475,7 +4542,7 @@ Return the new class name, which is a symbol named DIR."
(with-demoted-errors "Error reading dir-locals: %S"
(dolist (file files)
(let ((file-time (file-attribute-modification-time
- (file-attributes file))))
+ (file-attributes (file-chase-links file)))))
(if (time-less-p latest file-time)
(setq latest file-time)))
(with-temp-buffer
@@ -4795,6 +4862,26 @@ Interactively, confirmation is required unless you supply a prefix argument."
;; It's likely that the VC status at the new location is different from
;; the one at the old location.
(vc-refresh-state)))
+
+(defun rename-visited-file (new-location)
+ "Rename the file visited by the current buffer to NEW-LOCATION.
+This command also sets the visited file name. If the buffer
+isn't visiting any file, that's all it does.
+
+Interactively, this prompts for NEW-LOCATION."
+ (interactive
+ (list (if buffer-file-name
+ (read-file-name "Rename visited file to: ")
+ (read-file-name "Set visited file name: "
+ default-directory
+ (expand-file-name
+ (file-name-nondirectory (buffer-name))
+ default-directory)))))
+ (when (and buffer-file-name
+ (file-exists-p buffer-file-name))
+ (rename-file buffer-file-name new-location))
+ (set-visited-file-name new-location nil t))
+
(defun file-extended-attributes (filename)
"Return an alist of extended attributes of file FILENAME.
@@ -4937,7 +5024,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
nil)))
;; If set-file-extended-attributes fails, fall back on set-file-modes.
(unless (and extended-attributes
- (with-demoted-errors
+ (with-demoted-errors "Error setting attributes: %S"
(set-file-extended-attributes to-name extended-attributes)))
(and modes
(set-file-modes to-name (logand modes #o1777) nofollow-flag)))))
@@ -5088,10 +5175,32 @@ On most systems, this will be true:
;; If there's nothing left to peel off, we're at the root and
;; we can stop.
(when (and dir (equal dir filename))
- (push "" components)
+ (push (if (equal dir "") ""
+ ;; On Windows, the first component might be "c:" or
+ ;; the like.
+ (substring dir 0 -1))
+ components)
(setq filename nil))))
components))
+(defun file-parent-directory (filename)
+ "Return the directory name of the parent directory of FILENAME.
+If FILENAME is at the root of the filesystem, return nil.
+If FILENAME is relative, it is interpreted to be relative
+to `default-directory', and the result will also be relative."
+ (let* ((expanded-filename (expand-file-name filename))
+ (parent (file-name-directory (directory-file-name expanded-filename))))
+ (cond
+ ;; filename is at top-level, therefore no parent
+ ((or (null parent)
+ (file-equal-p parent expanded-filename))
+ nil)
+ ;; filename is relative, return relative parent
+ ((not (file-name-absolute-p filename))
+ (file-relative-name parent))
+ (t
+ parent))))
+
(defcustom make-backup-file-name-function
#'make-backup-file-name--default-function
"A function that `make-backup-file-name' uses to create backup file names.
@@ -5343,7 +5452,14 @@ on a DOS/Windows machine, it returns FILENAME in expanded form."
(let ((fremote (file-remote-p filename))
(dremote (file-remote-p directory))
(fold-case (or (file-name-case-insensitive-p filename)
- read-file-name-completion-ignore-case)))
+ ;; During bootstrap, it can happen that
+ ;; `read-file-name-completion-ignore-case' is
+ ;; not defined yet.
+ ;; FIXME: `read-file-name-completion-ignore-case' is
+ ;; a user-config which we shouldn't trust to reflect
+ ;; the actual file system's semantics.
+ (and (boundp 'read-file-name-completion-ignore-case)
+ read-file-name-completion-ignore-case))))
(if ;; Conditions for separate trees
(or
;; Test for different filesystems on DOS/Windows
@@ -5558,7 +5674,8 @@ Before and after saving the buffer, this function runs
(goto-char (point-max))
(insert ?\n))))
;; Don't let errors prevent saving the buffer.
- (with-demoted-errors (run-hooks 'before-save-hook))
+ (with-demoted-errors "Before-save hook error: %S"
+ (run-hooks 'before-save-hook))
;; Give `write-contents-functions' a chance to
;; short-circuit the whole process.
(unless (run-hook-with-args-until-success 'write-contents-functions)
@@ -5606,7 +5723,7 @@ Before and after saving the buffer, this function runs
(condition-case ()
(progn
(unless
- (with-demoted-errors
+ (with-demoted-errors "Error setting file modes: %S"
(set-file-modes buffer-file-name (car setmodes)))
(set-file-extended-attributes buffer-file-name
(nth 1 setmodes))))
@@ -5694,11 +5811,14 @@ Before and after saving the buffer, this function runs
(signal (car err) (cdr err))))
;; Since we have created an entirely new file,
;; make sure it gets the right permission bits set.
- (setq setmodes (or setmodes
- (list (or (file-modes buffer-file-name)
- (logand ?\666 (default-file-modes)))
- (file-extended-attributes buffer-file-name)
- buffer-file-name)))
+ (setq setmodes
+ (or setmodes
+ (list (or (file-modes buffer-file-name)
+ (logand ?\666 (default-file-modes)))
+ (with-demoted-errors
+ "Error getting extended attributes: %s"
+ (file-extended-attributes buffer-file-name))
+ buffer-file-name)))
;; We succeeded in writing the temp file,
;; so rename it.
(rename-file tempname
@@ -5715,13 +5835,16 @@ Before and after saving the buffer, this function runs
;; (setmodes is set) because that says we're superseding.
(cond ((and tempsetmodes (not setmodes))
;; Change the mode back, after writing.
- (setq setmodes (list (file-modes buffer-file-name)
- (file-extended-attributes buffer-file-name)
- buffer-file-name))
+ (setq setmodes
+ (list (file-modes buffer-file-name)
+ (with-demoted-errors
+ "Error getting extended attributes: %s"
+ (file-extended-attributes buffer-file-name))
+ buffer-file-name))
;; If set-file-extended-attributes fails, fall back on
;; set-file-modes.
(unless
- (with-demoted-errors
+ (with-demoted-errors "Error setting attributes: %s"
(set-file-extended-attributes buffer-file-name
(nth 1 setmodes)))
(set-file-modes buffer-file-name
@@ -5799,7 +5922,7 @@ to return a predicate used to check buffers."
;; FIXME nil should not be a valid option, let alone the default,
;; eg so that add-function can be used.
:type '(choice (const :tag "Default" nil)
- (function :tag "Only in subdirs of root"
+ (function :tag "Only in subdirs of current project"
save-some-buffers-root)
(function :tag "Custom function"))
:version "26.1")
@@ -5816,6 +5939,41 @@ of the directory that was default during command invocation."
(lambda () (file-in-directory-p default-directory root))))
(put 'save-some-buffers-root 'save-some-buffers-function t)
+(defun files--buffers-needing-to-be-saved (pred)
+ "Return a list of buffers to save according to PRED.
+See `save-some-buffers' for PRED values."
+ (let ((buffers
+ (mapcar (lambda (buffer)
+ (if
+ ;; Note that killing some buffers may kill others via
+ ;; hooks (e.g. Rmail and its viewing buffer).
+ (and (buffer-live-p buffer)
+ (buffer-modified-p buffer)
+ (not (buffer-base-buffer buffer))
+ (or
+ (buffer-file-name buffer)
+ (with-current-buffer buffer
+ (or (eq buffer-offer-save 'always)
+ (and pred buffer-offer-save
+ (> (buffer-size) 0)))))
+ (or (not (functionp pred))
+ (with-current-buffer buffer
+ (funcall pred))))
+ buffer))
+ (buffer-list))))
+ (delq nil buffers)))
+
+(defvar save-some-buffers-functions nil
+ "Functions to be run by `save-some-buffers' after saving the buffers.
+The functions can be called in two \"modes\", depending on the
+first argument. If the first argument is `query', then the
+function should return non-nil if there is something to be
+saved (but it should not actually save anything).
+
+If the first argument is something else, then the function should
+save according to the value of the second argument, which is the
+ARG argument from `save-some-buffers'.")
+
(defun save-some-buffers (&optional arg pred)
"Save some modified file-visiting buffers. Asks user about each one.
You can answer \\`y' or \\`SPC' to save, \\`n' or \\`DEL' not to save, \\`C-r'
@@ -5835,27 +5993,31 @@ all with no questions.
Optional second argument PRED determines which buffers are considered:
If PRED is nil, all the file-visiting buffers are considered.
If PRED is t, then certain non-file buffers will also be considered.
-If PRED is a zero-argument function, it indicates for each buffer whether
-to consider it or not when called with that buffer current.
+If PRED is a function, it is called with no argument in each buffer and
+should return non-nil if that buffer should be considered.
PRED defaults to the value of `save-some-buffers-default-predicate'.
See `save-some-buffers-action-alist' if you want to
-change the additional actions you can take on files."
+change the additional actions you can take on files.
+
+The functions in `save-some-buffers-functions' will be called
+after saving the buffers."
(interactive "P")
(unless pred
- (setq pred save-some-buffers-default-predicate))
- ;; Allow `pred' to be a function that returns a predicate
- ;; with lexical bindings in its original environment (bug#46374).
- (when (and (symbolp pred) (get pred 'save-some-buffers-function))
- (let ((pred-fun (and (functionp pred) (funcall pred))))
- (when (functionp pred-fun)
- (setq pred pred-fun))))
+ (setq pred
+ ;; Allow `pred' to be a function that returns a predicate
+ ;; with lexical bindings in its original environment (bug#46374).
+ (if (and (symbolp save-some-buffers-default-predicate)
+ (get save-some-buffers-default-predicate
+ 'save-some-buffers-function))
+ (funcall save-some-buffers-default-predicate)
+ save-some-buffers-default-predicate)))
(let* ((switched-buffer nil)
(save-some-buffers--switch-window-callback
(lambda (buffer)
(setq switched-buffer buffer)))
queried autosaved-buffers
- files-done abbrevs-done)
+ files-done inhibit-message)
(unwind-protect
(save-window-excursion
(dolist (buffer (buffer-list))
@@ -5871,64 +6033,42 @@ change the additional actions you can take on files."
(setq files-done
(map-y-or-n-p
(lambda (buffer)
- ;; Note that killing some buffers may kill others via
- ;; hooks (e.g. Rmail and its viewing buffer).
- (and (buffer-live-p buffer)
- (buffer-modified-p buffer)
- (not (buffer-base-buffer buffer))
- (or
- (buffer-file-name buffer)
- (with-current-buffer buffer
- (or (eq buffer-offer-save 'always)
- (and pred buffer-offer-save
- (> (buffer-size) 0)))))
- (or (not (functionp pred))
- (with-current-buffer buffer (funcall pred)))
- (if arg
- t
- (setq queried t)
- (if (buffer-file-name buffer)
- (if (or
- (equal (buffer-name buffer)
- (file-name-nondirectory
- (buffer-file-name buffer)))
- (string-match
- (concat "\\<"
- (regexp-quote
- (file-name-nondirectory
- (buffer-file-name buffer)))
- "<[^>]*>\\'")
- (buffer-name buffer)))
- ;; The buffer name is similar to the
- ;; file name.
- (format "Save file %s? "
- (buffer-file-name buffer))
- ;; The buffer and file names are
- ;; dissimilar; display both.
- (format "Save file %s (buffer %s)? "
- (buffer-file-name buffer)
- (buffer-name buffer)))
- ;; No file name
- (format "Save buffer %s? " (buffer-name buffer))))))
+ (if arg
+ t
+ (setq queried t)
+ (if (buffer-file-name buffer)
+ (if (or
+ (equal (buffer-name buffer)
+ (file-name-nondirectory
+ (buffer-file-name buffer)))
+ (string-match
+ (concat "\\<"
+ (regexp-quote
+ (file-name-nondirectory
+ (buffer-file-name buffer)))
+ "<[^>]*>\\'")
+ (buffer-name buffer)))
+ ;; The buffer name is similar to the file
+ ;; name.
+ (format "Save file %s? "
+ (buffer-file-name buffer))
+ ;; The buffer and file names are dissimilar;
+ ;; display both.
+ (format "Save file %s (buffer %s)? "
+ (buffer-file-name buffer)
+ (buffer-name buffer)))
+ ;; No file name.
+ (format "Save buffer %s? " (buffer-name buffer)))))
(lambda (buffer)
(with-current-buffer buffer
(save-buffer)))
- (buffer-list)
+ (files--buffers-needing-to-be-saved pred)
'("buffer" "buffers" "save")
save-some-buffers-action-alist))
- ;; Maybe to save abbrevs, and record whether
- ;; we either saved them or asked to.
- (and save-abbrevs abbrevs-changed
- (progn
- (if (or arg
- (eq save-abbrevs 'silently)
- (y-or-n-p (format "Save abbrevs in %s? "
- abbrev-file-name)))
- (write-abbrev-file nil))
- ;; Don't keep bothering user if he says no.
- (setq abbrevs-changed nil)
- (setq abbrevs-done t)))
- (or queried (> files-done 0) abbrevs-done
+ ;; Allow other things to be saved at this time, like abbrevs.
+ (dolist (func save-some-buffers-functions)
+ (setq inhibit-message (or (funcall func nil arg) inhibit-message)))
+ (or queried (> files-done 0) inhibit-message
(cond
((null autosaved-buffers)
(when (called-interactively-p 'any)
@@ -7169,16 +7309,25 @@ by `sh' are supported."
:type 'string
:group 'dired)
-(defun file-expand-wildcards (pattern &optional full)
- "Expand wildcard pattern PATTERN.
-This returns a list of file names that match the pattern.
-Files are sorted in `string<' order.
+(defun file-expand-wildcards (pattern &optional full regexp)
+ "Expand (a.k.a. \"glob\") file-name wildcard pattern PATTERN.
+This returns a list of file names that match PATTERN.
+The returned list of file names is sorted in the `string<' order.
+
+PATTERN is, by default, a \"glob\"/wildcard string, e.g.,
+\"/tmp/*.png\" or \"/*/*/foo.png\", but can also be a regular
+expression if the optional REGEXP parameter is non-nil. In any
+case, the matches are applied per sub-directory, so a match can't
+span a parent/sub directory, which means that a regexp bit can't
+contain the \"/\" character.
-If PATTERN is written as an absolute file name,
-the values are absolute also.
+The returned list of file names is sorted in the `string<' order.
+
+If PATTERN is written as an absolute file name, the expansions in
+the returned list are also absolute.
If PATTERN is written as a relative file name, it is interpreted
-relative to the current default directory, `default-directory'.
+relative to the current `default-directory'.
The file names returned are normally also relative to the current
default directory. However, if FULL is non-nil, they are absolute."
(save-match-data
@@ -7190,7 +7339,8 @@ default directory. However, if FULL is non-nil, they are absolute."
(dirs (if (and dirpart
(string-match "[[*?]" (file-local-name dirpart)))
(mapcar 'file-name-as-directory
- (file-expand-wildcards (directory-file-name dirpart)))
+ (file-expand-wildcards
+ (directory-file-name dirpart) nil regexp))
(list dirpart)))
contents)
(dolist (dir dirs)
@@ -7203,8 +7353,13 @@ default directory. However, if FULL is non-nil, they are absolute."
(unless (string-match "\\`\\.\\.?\\'"
(file-name-nondirectory name))
name))
- (directory-files (or dir ".") full
- (wildcard-to-regexp nondir))))))
+ (directory-files
+ (or dir ".") full
+ (if regexp
+ ;; We're matching each file name
+ ;; element separately.
+ (concat "\\`" nondir "\\'")
+ (wildcard-to-regexp nondir)))))))
(setq contents
(nconc
(if (and dir (not full))
@@ -7214,6 +7369,96 @@ default directory. However, if FULL is non-nil, they are absolute."
contents)))))
contents)))
+(defcustom find-sibling-rules nil
+ "Rules for finding \"sibling\" files.
+This is used by the `find-sibling-file' command.
+
+This variable is a list of (MATCH EXPANSION...) elements.
+
+MATCH is a regular expression that should match a file name that
+has a sibling. It can contain sub-expressions that will be used
+in EXPANSIONS.
+
+EXPANSION is a string that matches file names. For instance, to
+define \".h\" files as siblings of any \".c\", you could say:
+
+ (\"\\\\([^/]+\\\\)\\\\.c\\\\\\='\" \"\\\\1.h\")
+
+MATCH and EXPANSION can also be fuller paths. For instance, if
+you want to define other versions of a project as being sibling
+files, you could say something like:
+
+ (\"src/emacs/[^/]+/\\\\(.*\\\\)\\\\\\='\" \"src/emacs/.*/\\\\1\\\\\\='\")
+
+In this example, if you're in src/emacs/emacs-27/lisp/abbrev.el,
+and you an src/emacs/emacs-28/lisp/abbrev.el file exists, it's
+now defined as a sibling."
+ :type 'sexp
+ :version "29.1")
+
+(defun find-sibling-file (file)
+ "Visit a \"sibling\" file of FILE.
+When called interactively, FILE is the currently visited file.
+
+The \"sibling\" file is defined by the `find-sibling-rules' variable."
+ (interactive (progn
+ (unless buffer-file-name
+ (user-error "Not visiting a file"))
+ (list buffer-file-name)))
+ (unless find-sibling-rules
+ (user-error "The `find-sibling-rules' variable has not been configured"))
+ (let ((siblings (find-sibling-file-search (expand-file-name file)
+ find-sibling-rules)))
+ (cond
+ ((null siblings)
+ (user-error "Couldn't find any sibling files"))
+ ((length= siblings 1)
+ (find-file (car siblings)))
+ (t
+ (let ((relatives (mapcar (lambda (sibling)
+ (file-relative-name
+ sibling (file-name-directory file)))
+ siblings)))
+ (find-file
+ (completing-read (format-prompt "Find file" (car relatives))
+ relatives nil t nil nil (car relatives))))))))
+
+(defun find-sibling-file-search (file &optional rules)
+ "Return a list of FILE's \"siblings\"
+RULES should be a list on the form defined by `find-sibling-rules' (which
+see), and if nil, defaults to `find-sibling-rules'."
+ (let ((results nil))
+ (pcase-dolist (`(,match . ,expansions) (or rules find-sibling-rules))
+ ;; Go through the list and find matches.
+ (when (string-match match file)
+ (let ((match-data (match-data)))
+ (dolist (expansion expansions)
+ (let ((start 0))
+ ;; Expand \\1 forms in the expansions.
+ (while (string-match "\\\\\\([&0-9]+\\)" expansion start)
+ (let ((index (string-to-number (match-string 1 expansion))))
+ (setq start (match-end 0)
+ expansion
+ (replace-match
+ (substring file
+ (elt match-data (* index 2))
+ (elt match-data (1+ (* index 2))))
+ t t expansion)))))
+ ;; Then see which files we have that are matching. (And
+ ;; expand from the end of the file's match, since we might
+ ;; be doing a relative match.)
+ (let ((default-directory (substring file 0 (car match-data))))
+ ;; Keep the first matches first.
+ (setq results
+ (nconc
+ results
+ (mapcar #'expand-file-name
+ (file-expand-wildcards expansion nil t)))))))))
+ ;; Delete the file itself (in case it matched), and remove
+ ;; duplicates, in case we have several expansions and some match
+ ;; the same subsets of files.
+ (delete file (delete-dups results))))
+
;; Let Tramp know that `file-expand-wildcards' does not need an advice.
(provide 'files '(remote-wildcards))
@@ -7228,12 +7473,11 @@ and `list-directory-verbose-switches'."
(list (read-file-name
(if pfx "List directory (verbose): "
"List directory (brief): ")
- nil default-directory t
- nil
+ nil default-directory
(lambda (file)
(or (file-directory-p file)
(insert-directory-wildcard-in-dir-p
- (expand-file-name file)))))
+ (file-name-as-directory (expand-file-name file))))))
pfx)))
(let ((switches (if verbose list-directory-verbose-switches
list-directory-brief-switches))
@@ -7252,9 +7496,9 @@ and `list-directory-verbose-switches'."
;; Finishing with-output-to-temp-buffer seems to clobber default-directory.
(with-current-buffer buffer
(setq default-directory
- (if (file-directory-p dirname)
+ (if (file-accessible-directory-p dirname)
(file-name-as-directory dirname)
- (file-name-directory dirname))))))
+ (file-name-directory (directory-file-name dirname)))))))
(defun shell-quote-wildcard-pattern (pattern)
"Quote characters special to the shell in PATTERN, leave wildcards alone.
@@ -7305,7 +7549,9 @@ need to be passed verbatim to shell commands."
(defvar insert-directory-program (purecopy "ls")
- "Absolute or relative name of the `ls' program used by `insert-directory'.")
+ "Absolute or relative name of the `ls'-like program.
+This is used by `insert-directory' and `dired-insert-directory'
+\(thus, also by `dired').")
(defcustom directory-free-space-program (purecopy "df")
"Program to get the amount of free space on a file system.
@@ -7740,18 +7986,34 @@ prompt the user before killing them."
:group 'convenience
:version "26.1")
-(defun save-buffers-kill-emacs (&optional arg)
+(defun save-buffers-kill-emacs (&optional arg restart)
"Offer to save each buffer, then kill this Emacs process.
With prefix ARG, silently save all file-visiting buffers without asking.
If there are active processes where `process-query-on-exit-flag'
returns non-nil and `confirm-kill-processes' is non-nil,
asks whether processes should be killed.
+
Runs the members of `kill-emacs-query-functions' in turn and stops
-if any returns nil. If `confirm-kill-emacs' is non-nil, calls it."
+if any returns nil. If `confirm-kill-emacs' is non-nil, calls it.
+
+If RESTART, restart Emacs after killing the current Emacs process."
(interactive "P")
;; Don't use save-some-buffers-default-predicate, because we want
;; to ask about all the buffers before killing Emacs.
- (save-some-buffers arg t)
+ (when (or (files--buffers-needing-to-be-saved t)
+ (catch 'need-save
+ (dolist (func save-some-buffers-functions)
+ (when (funcall func 'query)
+ (throw 'need-save t)))))
+ (if (use-dialog-box-p)
+ (pcase (x-popup-dialog
+ t `("Unsaved Buffers"
+ ("Close Without Saving" . no-save)
+ ("Save All" . save-all)
+ ("Cancel" . cancel)))
+ ('cancel (user-error "Exit cancelled"))
+ ('save-all (save-some-buffers t)))
+ (save-some-buffers arg t)))
(let ((confirm confirm-kill-emacs))
(and
(or (not (memq t (mapcar (lambda (buf)
@@ -7792,7 +8054,7 @@ if any returns nil. If `confirm-kill-emacs' is non-nil, calls it."
(run-hook-with-args-until-failure 'kill-emacs-query-functions)
(or (null confirm)
(funcall confirm "Really exit Emacs? "))
- (kill-emacs))))
+ (kill-emacs nil restart))))
(defun save-buffers-kill-terminal (&optional arg)
"Offer to save each buffer, then kill the current connection.
@@ -7807,6 +8069,16 @@ only these files will be asked to be saved."
(if (frame-parameter nil 'client)
(server-save-buffers-kill-terminal arg)
(save-buffers-kill-emacs arg)))
+
+(defun restart-emacs ()
+ "Kill the current Emacs process and start a new one.
+This goes through the same shutdown procedure as
+`save-buffers-kill-emacs', but instead of killing Emacs and
+exiting, it re-executes Emacs (using the same command line
+arguments as the running Emacs)."
+ (interactive)
+ (save-buffers-kill-emacs nil t))
+
;; We use /: as a prefix to "quote" a file name
;; so that magic file name handlers will not apply to it.
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 0bc44ecd912..b1829793f11 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -208,7 +208,7 @@ COND-FN takes one argument: the current element."
(defun filesets-reset-fileset (&optional fileset no-cache)
"Reset the cached values for one or all filesets."
(setq filesets-submenus (if fileset
- (lax-plist-put filesets-submenus fileset nil)
+ (plist-put filesets-submenus fileset nil #'equal)
nil))
(setq filesets-has-changed-flag t)
(setq filesets-update-cache-file-flag (or filesets-update-cache-file-flag
@@ -414,12 +414,12 @@ time to time or if the fileset cache causes troubles."
Set this value to 0 to turn menu splitting off. BTW, parts of submenus
will not be rewrapped if their length exceeds this value."
:set #'filesets-set-default
- :type 'integer)
+ :type 'natnum)
(defcustom filesets-max-entry-length 50
"Truncate names of split submenus to this length."
:set #'filesets-set-default
- :type 'integer)
+ :type 'natnum)
(defcustom filesets-browse-dir-function #'dired
"A function or command used for browsing directories.
@@ -518,7 +518,7 @@ i.e. how deep the menu should be. Try something like
and it should become clear what this option is about. In any case,
including directory trees to the menu can take a lot of memory."
:set #'filesets-set-default
- :type 'integer)
+ :type 'natnum)
(defcustom filesets-commands
'(("Isearch"
@@ -1027,7 +1027,7 @@ defined in `filesets-ingroup-patterns'."
(defcustom filesets-query-user-limit 15
"Query the user before opening a fileset with that many files."
:set #'filesets-set-default
- :type 'integer)
+ :type 'natnum)
(defun filesets-filter-dir-names (lst &optional negative)
@@ -1761,7 +1761,7 @@ Use LOOKUP-NAME for deducing the save-function, if provided."
(defun filesets-add-buffer (&optional name buffer)
"Add BUFFER (or current buffer) to the fileset called NAME.
-User will be queried, if no fileset name is provided."
+If no fileset name is provided, prompt for NAME."
(interactive)
(let* ((buffer (or buffer
(current-buffer)))
@@ -1796,8 +1796,8 @@ User will be queried, if no fileset name is provided."
(message "Filesets: Can't add `%s' to fileset `%s'" this name)))))))
(defun filesets-remove-buffer (&optional name buffer)
- "Remove BUFFER (or current buffer) to fileset NAME.
-User will be queried, if no fileset name is provided."
+ "Remove BUFFER (or current buffer) from the fileset called NAME.
+If no fileset name is provided, prompt for NAME."
(interactive)
(let* ((buffer (or buffer
(current-buffer)))
@@ -1999,7 +1999,7 @@ LOOKUP-NAME is used as lookup name for retrieving fileset specific settings."
(defun filesets-ingroup-cache-get (master)
"Access to `filesets-ingroup-cache'."
- (lax-plist-get filesets-ingroup-cache master))
+ (plist-get filesets-ingroup-cache master #'equal))
(defun filesets-ingroup-cache-put (master file)
"Access to `filesets-ingroup-cache'."
@@ -2008,7 +2008,7 @@ LOOKUP-NAME is used as lookup name for retrieving fileset specific settings."
(cons file (filesets-ingroup-cache-get emaster))
nil)))
(setq filesets-ingroup-cache
- (lax-plist-put filesets-ingroup-cache emaster this))))
+ (plist-put filesets-ingroup-cache emaster this #'equal))))
(defun filesets-ingroup-collect-files (fs &optional remdupl-flag master depth)
"Helper function for `filesets-ingroup-collect'. Collect file names."
@@ -2305,12 +2305,12 @@ bottom up, set `filesets-submenus' to nil, first.)"
((null data))
(let* ((this (car data))
(name (filesets-data-get-name this))
- (cached (lax-plist-get filesets-submenus name))
+ (cached (plist-get filesets-submenus name #'equal))
(submenu (or cached
(filesets-build-submenu count name this))))
(unless cached
(setq filesets-submenus
- (lax-plist-put filesets-submenus name submenu)))
+ (plist-put filesets-submenus name submenu #'equal)))
(unless (filesets-entry-get-dormant-flag this)
(setq filesets-menu-cache
(append filesets-menu-cache (list submenu))))))
diff --git a/lisp/find-dired.el b/lisp/find-dired.el
index c67138a8006..2f3f6b689aa 100644
--- a/lisp/find-dired.el
+++ b/lisp/find-dired.el
@@ -154,6 +154,9 @@ output of `find' (one file per line) when this function is called."
;; History of find-args values entered in the minibuffer.
(defvar find-args-history nil)
+(defvar find-command-history nil
+ "History of commands passed interactively to `find-dired-with-command'.")
+
(defvar dired-sort-inhibit)
;;;###autoload
@@ -171,6 +174,38 @@ it finishes, type \\[kill-find]."
(interactive (list (read-directory-name "Run find in directory: " nil "" t)
(read-string "Run find (with args): " find-args
'(find-args-history . 1))))
+ (setq find-args args ; save for next interactive call
+ args (concat find-program " . "
+ (if (string= args "")
+ ""
+ (concat
+ (shell-quote-argument "(")
+ " " args " "
+ (shell-quote-argument ")")
+ " "))
+ (find-dired--escaped-ls-option)))
+ (find-dired-with-command dir args))
+
+;;;###autoload
+(defun find-dired-with-command (dir command)
+ "Run `find' and go into Dired mode on a buffer of the output.
+The user-supplied COMMAND is run after changing into DIR and should look like
+
+ find . GLOBALARGS \\( ARGS \\) -ls
+
+The car of the variable `find-ls-option' specifies what to
+use in place of \"-ls\" as the starting input.
+
+Collect output in the \"*Find*\" buffer. To kill the job before
+it finishes, type \\[kill-find]."
+ (interactive
+ (list (read-directory-name "Run find in directory: " nil "" t)
+ (read-string "Run find command: "
+ (cons (concat find-program
+ " . \\( \\) "
+ (find-dired--escaped-ls-option))
+ (+ 1 (length find-program) (length " . \\( ")))
+ find-command-history)))
(let ((dired-buffers dired-buffers))
;; Expand DIR ("" means default-directory), and make sure it has a
;; trailing slash.
@@ -199,25 +234,9 @@ it finishes, type \\[kill-find]."
(kill-all-local-variables)
(setq buffer-read-only nil)
(erase-buffer)
- (setq default-directory dir
- find-args args ; save for next interactive call
- args (concat find-program " . "
- (if (string= args "")
- ""
- (concat
- (shell-quote-argument "(")
- " " args " "
- (shell-quote-argument ")")
- " "))
- (if (string-match "\\`\\(.*\\) {} \\(\\\\;\\|\\+\\)\\'"
- (car find-ls-option))
- (format "%s %s %s"
- (match-string 1 (car find-ls-option))
- (shell-quote-argument "{}")
- find-exec-terminator)
- (car find-ls-option))))
+ (setq default-directory dir)
;; Start the find process.
- (shell-command (concat args "&") (current-buffer))
+ (shell-command (concat command "&") (current-buffer))
(dired-mode dir (cdr find-ls-option))
(let ((map (make-sparse-keymap)))
(set-keymap-parent map (current-local-map))
@@ -226,7 +245,7 @@ it finishes, type \\[kill-find]."
(setq-local dired-sort-inhibit t)
(setq-local revert-buffer-function
(lambda (_ignore-auto _noconfirm)
- (find-dired dir find-args)))
+ (find-dired-with-command dir command)))
;; Set subdir-alist so that Tree Dired will work:
(if (fboundp 'dired-simple-subdir-alist)
;; will work even with nested dired format (dired-nstd.el,v 1.15
@@ -234,17 +253,19 @@ it finishes, type \\[kill-find]."
(dired-simple-subdir-alist)
;; else we have an ancient tree dired (or classic dired, where
;; this does no harm)
- (setq-local dired-subdir-alist
- (list (cons default-directory (point-min-marker)))))
+ (setq dired-subdir-alist
+ (list (cons default-directory (point-min-marker)))))
(setq-local dired-subdir-switches find-ls-subdir-switches)
(setq buffer-read-only nil)
;; Subdir headlerline must come first because the first marker in
;; subdir-alist points there.
(insert " " dir ":\n")
+ (when dired-make-directory-clickable
+ (dired--make-directory-clickable))
;; Make second line a ``find'' line in analogy to the ``total'' or
;; ``wildcard'' line.
(let ((point (point)))
- (insert " " args "\n")
+ (insert " " command "\n")
(dired-insert-set-properties point (point)))
(setq buffer-read-only t)
(let ((proc (get-buffer-process (current-buffer))))
@@ -254,6 +275,16 @@ it finishes, type \\[kill-find]."
(move-marker (process-mark proc) (point) (current-buffer)))
(setq mode-line-process '(":%s"))))
+(defun find-dired--escaped-ls-option ()
+ "Return the car of `find-ls-option' escaped for a shell command."
+ (if (string-match "\\`\\(.*\\) {} \\(\\\\;\\|\\+\\)\\'"
+ (car find-ls-option))
+ (format "%s %s %s"
+ (match-string 1 (car find-ls-option))
+ (shell-quote-argument "{}")
+ find-exec-terminator)
+ (car find-ls-option)))
+
(defun kill-find ()
"Kill the `find' process running in the current buffer."
(interactive)
@@ -323,11 +354,7 @@ specifies what to use in place of \"-ls\" as the final argument."
(save-restriction
(widen)
(let ((buffer-read-only nil)
- (beg (point-max))
- (l-opt (and (consp find-ls-option)
- (string-match "l" (cdr find-ls-option))))
- (ls-regexp (concat "^ +[^ \t\r\n]+\\( +[^ \t\r\n]+\\) +"
- "[^ \t\r\n]+ +[^ \t\r\n]+\\( +[^[:space:]]+\\)")))
+ (beg (point-max)))
(goto-char beg)
(insert string)
(goto-char beg)
@@ -342,18 +369,6 @@ specifies what to use in place of \"-ls\" as the final argument."
(goto-char (- beg 3)) ; no error if < 0
(while (search-forward " ./" nil t)
(delete-region (point) (- (point) 2)))
- ;; Pad the number of links and file size. This is a
- ;; quick and dirty way of getting the columns to line up
- ;; most of the time, but it's not foolproof.
- (when l-opt
- (goto-char beg)
- (goto-char (line-beginning-position))
- (while (re-search-forward ls-regexp nil t)
- (replace-match (format "%4s" (match-string 1))
- nil nil nil 1)
- (replace-match (format "%9s" (match-string 2))
- nil nil nil 2)
- (forward-line 1)))
;; Find all the complete lines in the unprocessed
;; output and process it to add text properties.
(goto-char (point-max))
diff --git a/lisp/find-lisp.el b/lisp/find-lisp.el
index d4d899aced7..0a712c0b811 100644
--- a/lisp/find-lisp.el
+++ b/lisp/find-lisp.el
@@ -231,8 +231,8 @@ It is a function which takes two arguments, the directory and its parent."
(dired-simple-subdir-alist)
;; else we have an ancient tree dired (or classic dired, where
;; this does no harm)
- (setq-local dired-subdir-alist
- (list (cons default-directory (point-min-marker)))))
+ (setq dired-subdir-alist
+ (list (cons default-directory (point-min-marker)))))
(find-lisp-insert-directory
dir file-predicate directory-predicate 'ignore)
(goto-char (point-min))
diff --git a/lisp/finder.el b/lisp/finder.el
index 5a6fe451928..73072c0cd48 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -1,7 +1,6 @@
;;; finder.el --- topic & keyword-based code finder -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 1997-1999, 2001-2022 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1992-2022 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
;; Created: 16 Jun 1992
@@ -76,20 +75,18 @@
"Association list of the standard \"Keywords:\" headers.
Each element has the form (KEYWORD . DESCRIPTION).")
-(defvar finder-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map " " 'finder-select)
- (define-key map "f" 'finder-select)
- (define-key map [follow-link] 'mouse-face)
- (define-key map [mouse-2] 'finder-mouse-select)
- (define-key map "\C-m" 'finder-select)
- (define-key map "?" 'finder-summary)
- (define-key map "n" 'next-line)
- (define-key map "p" 'previous-line)
- (define-key map "q" 'finder-exit)
- (define-key map "d" 'finder-list-keywords)
- map)
- "Keymap used in `finder-mode'.")
+(defvar-keymap finder-mode-map
+ :doc "Keymap used in `finder-mode'."
+ "SPC" #'finder-select
+ "f" #'finder-select
+ "<follow-link>" 'mouse-face
+ "<mouse-2>" #'finder-mouse-select
+ "C-m" #'finder-select
+ "?" #'finder-summary
+ "n" #'next-line
+ "p" #'previous-line
+ "q" #'finder-exit
+ "d" #'finder-list-keywords)
(easy-menu-define finder-mode-menu finder-mode-map
"Menu for `finder-mode'."
@@ -130,8 +127,6 @@ Keywords and package names both should be symbols.")
cus-load\\|finder-inf\\|esh-groups\\|subdirs\\|leim-list\\)\\.el$\\)"
"Regexp matching file names not to scan for keywords.")
-(autoload 'autoload-rubric "autoload")
-
(defconst finder--builtins-descriptions
;; I have no idea whether these are supposed to be capitalized
;; and/or end in a full-stop. Existing file headers are inconsistent,
@@ -267,9 +262,9 @@ from; the default is `load-path'."
(find-file-noselect generated-finder-keywords-file)
(setq buffer-undo-list t)
(erase-buffer)
- (insert (autoload-rubric generated-finder-keywords-file
- "keyword-to-package mapping" t))
- (search-backward " ")
+ (generate-lisp-file-heading
+ generated-finder-keywords-file 'finder-compile-keywords
+ :title "keyword-to-package mapping")
;; FIXME: Now that we have package--builtin-versions, package--builtins is
;; only needed to get the list of unversioned packages and to get the
;; summary description of each package.
@@ -283,6 +278,7 @@ from; the default is `load-path'."
(insert "(setq finder-keywords-hash\n ")
(prin1 finder-keywords-hash (current-buffer))
(insert ")\n")
+ (generate-lisp-file-trailer generated-finder-keywords-file)
(basic-save-buffer)))
(defun finder-compile-keywords-make-dist ()
@@ -367,7 +363,7 @@ not `finder-known-keywords'."
"Display FILE's commentary section.
FILE should be in a form suitable for passing to `locate-library'."
;; FIXME: Merge this function into `describe-package', which is
- ;; strictly better as it has links to URL's and is in a proper help
+ ;; strictly better as it has links to URLs and is in a proper help
;; buffer with navigation forward and backward, etc.
(interactive
(list
@@ -454,7 +450,8 @@ Quit the window and kill all Finder-related buffers."
(defun finder-unload-function ()
"Unload the Finder library."
- (with-demoted-errors (unload-feature 'finder-inf t))
+ (with-demoted-errors "Error unloading finder: %S"
+ (unload-feature 'finder-inf t))
;; continue standard unloading
nil)
diff --git a/lisp/foldout.el b/lisp/foldout.el
index 4b192a7b6aa..e00fb40e3ca 100644
--- a/lisp/foldout.el
+++ b/lisp/foldout.el
@@ -473,7 +473,7 @@ What happens depends on the number of mouse clicks:-
"Swallow intervening mouse events so we only get the final click-count.
Signal an error if the final event isn't the same type as the first one."
(let ((initial-event-type (event-basic-type event)))
- (while (null (sit-for (/ double-click-time 1000.0) 'nodisplay))
+ (while (null (sit-for (/ (mouse-double-click-time) 1000.0) 'nodisplay))
(setq event (read--potential-mouse-event)))
(or (eq initial-event-type (event-basic-type event))
(error "")))
diff --git a/lisp/follow.el b/lisp/follow.el
index 6c721899d45..adf1c1b762d 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -1552,7 +1552,7 @@ non-first windows in Follow mode."
(declare-function scroll-bar-drag "scroll-bar" (event))
(declare-function scroll-bar-scroll-up "scroll-bar" (event))
(declare-function scroll-bar-scroll-down "scroll-bar" (event))
-(declare-function mwheel-scroll "mwheel" (event))
+(declare-function mwheel-scroll "mwheel" (event &optional arg))
(defun follow-scroll-bar-toolkit-scroll (event)
(interactive "e")
diff --git a/lisp/font-core.el b/lisp/font-core.el
index 2b75309ff3f..db07aa011c4 100644
--- a/lisp/font-core.el
+++ b/lisp/font-core.el
@@ -105,8 +105,7 @@ example, put in your ~/.emacs:
Where major modes support different levels of fontification, you
can use the variable `font-lock-maximum-decoration' to specify
which level you generally prefer. When you turn Font Lock mode
-on/off the buffer is fontified/defontified, though fontification
-occurs only if the buffer is less than `font-lock-maximum-size'.
+on/off the buffer is fontified/defontified.
To add your own highlighting for some major mode, and modify the
highlighting selected automatically via the variable
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 083bfb8626b..181a7dc90ef 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -47,9 +47,9 @@
;;
;; Fontification for a particular mode may be available in a number of levels
;; of decoration. The higher the level, the more decoration, but the more time
-;; it takes to fontify. See the variable `font-lock-maximum-decoration', and
-;; also the variable `font-lock-maximum-size'. Support modes for Font Lock
-;; mode can be used to speed up Font Lock mode. See `font-lock-support-mode'.
+;; it takes to fontify. See the variable `font-lock-maximum-decoration'.
+;; Support modes for Font Lock mode can be used to speed up Font Lock
+;; mode. See `font-lock-support-mode'.
;;;; How Font Lock mode fontifies:
@@ -208,6 +208,7 @@
(require 'syntax)
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
;; Define core `font-lock' group.
(defgroup font-lock '((jit-lock custom-group))
@@ -227,32 +228,6 @@
;; User variables.
-(defcustom font-lock-maximum-size 256000
- "Maximum buffer size for unsupported buffer fontification.
-When `font-lock-support-mode' is nil, only buffers smaller than
-this are fontified. This variable has no effect if a Font Lock
-support mode (usually `jit-lock-mode') is enabled.
-
-If nil, means size is irrelevant.
-If a list, each element should be a cons pair of the form (MAJOR-MODE . SIZE),
-where MAJOR-MODE is a symbol or t (meaning the default). For example:
- ((c-mode . 256000) (c++-mode . 256000) (rmail-mode . 1048576))
-means that the maximum size is 250K for buffers in C or C++ modes, one megabyte
-for buffers in Rmail mode, and size is irrelevant otherwise."
- :type '(choice (const :tag "none" nil)
- (integer :tag "size")
- (repeat :menu-tag "mode specific" :tag "mode specific"
- :value ((t . nil))
- (cons :tag "Instance"
- (radio :tag "Mode"
- (const :tag "all" t)
- (symbol :tag "name"))
- (radio :tag "Size"
- (const :tag "none" nil)
- (integer :tag "size")))))
- :group 'font-lock)
-(make-obsolete-variable 'font-lock-maximum-size nil "24.1")
-
(defcustom font-lock-maximum-decoration t
"Maximum decoration level for fontification.
If nil, use the default decoration (typically the minimum available).
@@ -279,6 +254,47 @@ decoration for buffers in C++ mode, and level 1 decoration otherwise."
(integer :tag "level" 1)))))
:group 'font-lock)
+(defcustom font-lock-ignore nil
+ "Rules to selectively disable fontifications due to `font-lock-keywords'.
+If non-nil, the value should be a list of condition sets of the form
+
+ (SYMBOL CONDITION ...)
+
+where:
+
+ - SYMBOL is a symbol, usually a major or minor mode. The subsequent
+ CONDITIONs apply if SYMBOL is bound as variable and its value is non-nil.
+ If SYMBOL is a symbol of a mode, that means the buffer has that mode
+ enabled (for major modes, it means the buffer's major mode is derived
+ from SYMBOL's mode).
+
+ - Each CONDITION can be one of the following:
+ - A symbol, typically a face. It matches any element of
+ `font-lock-keywords' that references the symbol. The symbol is
+ interpreted as a glob pattern; in particular, `*' matches
+ everything, `?' matches any single character, and `[abcd]'
+ matches one character from the set.
+ - A string. It matches any element of `font-lock-keywords' whose
+ MATCHER is a regexp that matches the string. This can be used to
+ disable fontification of a particular programming keyword.
+ - A form (pred FUNCTION). It matches an element of `font-lock-keywords'
+ if FUNCTION, when called with the element as the argument, returns
+ non-nil.
+ - A form (not CONDITION). It matches if CONDITION doesn't.
+ - A form (and CONDITION ...). It matches if all the provided
+ CONDITIONs match.
+ - A form (or CONDITION ...). It matches if at least one of the
+ provided CONDITIONs matches.
+ - A form (except CONDITIONs ...). This can be used only at top level
+ or inside an `or' clause. It undoes the effect of previous
+ matching CONDITIONs on the same level.
+
+In each buffer, fontifications due to the elements of `font-lock-keywords'
+that match at least one applicable CONDITION are disabled."
+ :type '(alist :key-type symbol :value-type sexp)
+ :group 'font-lock
+ :version "29.1")
+
(defcustom font-lock-verbose nil
"If non-nil, means show status messages for buffer fontification.
If a number, only buffers greater than this size have fontification messages."
@@ -349,7 +365,7 @@ This can be an \"!\" or the \"n\" in \"ifndef\".")
;; Fontification variables:
(defvar font-lock-keywords nil
- "A list of the keywords to highlight.
+ "A list of keywords and corresponding font-lock highlighting rules.
There are two kinds of values: user-level, and compiled.
A user-level keywords list is what a major mode or the user would
@@ -374,10 +390,10 @@ point, and set `match-data' appropriately if it succeeds; like
`re-search-forward' would). MATCHER regexps can be generated via
the function `regexp-opt'.
-FORM is an expression, whose value should be a keyword element,
-evaluated when the keyword is (first) used in a buffer. This
-feature can be used to provide a keyword that can only be
-generated when Font Lock mode is actually turned on.
+FORM is an expression, whose value should be a keyword element
+of one of the above forms, evaluated when the keyword is (first)
+used in a buffer. This feature can be used to provide a keyword
+that can only be generated when Font Lock mode is actually turned on.
HIGHLIGHT should be either MATCH-HIGHLIGHT or MATCH-ANCHORED.
@@ -653,15 +669,9 @@ be enabled."
;; The first fontification after turning the mode on. This must
;; only be called after the mode hooks have been run.
(when (and font-lock-mode
- (font-lock-specified-p t))
- (let ((max-size (font-lock-value-in-major-mode font-lock-maximum-size)))
- (cond (font-lock-fontified
- nil)
- ((or (null max-size) (> max-size (buffer-size)))
- (with-no-warnings (font-lock-fontify-buffer)))
- (font-lock-verbose
- (message "Fontifying %s...buffer size greater than font-lock-maximum-size"
- (buffer-name)))))))
+ (font-lock-specified-p t)
+ (not font-lock-fontified))
+ (with-no-warnings (font-lock-fontify-buffer))))
(defun font-lock-mode-internal (arg)
;; Turn on Font Lock mode.
@@ -1203,28 +1213,26 @@ Put first the functions more likely to cause a change and cheaper to compute.")
(setq font-lock-beg (or (previous-single-property-change
font-lock-beg 'font-lock-multiline)
(point-min))))
- ;;
- (when (get-text-property font-lock-end 'font-lock-multiline)
- (setq changed t)
- (setq font-lock-end (or (text-property-any font-lock-end (point-max)
- 'font-lock-multiline nil)
- (point-max))))
+ ;; If `font-lock-multiline' starts at `font-lock-end', do not
+ ;; extend the region.
+ (let ((before-end (max (point-min) (1- font-lock-end)))
+ (new-end nil))
+ (when (get-text-property before-end 'font-lock-multiline)
+ (setq new-end (or (text-property-any before-end (point-max)
+ 'font-lock-multiline nil)
+ (point-max)))
+ (when (/= new-end font-lock-end)
+ (setq changed t)
+ (setq font-lock-end new-end))))
changed))
(defun font-lock-extend-region-wholelines ()
"Move fontification boundaries to beginning of lines."
- (let ((changed nil))
- (goto-char font-lock-beg)
- (unless (bolp)
- (setq changed t font-lock-beg
- (let ((inhibit-field-text-motion t))
- (line-beginning-position))))
- (goto-char font-lock-end)
- (unless (bolp)
- (unless (eq font-lock-end
- (setq font-lock-end (line-beginning-position 2)))
- (setq changed t)))
- changed))
+ (let ((new (syntax-propertize-wholelines font-lock-beg font-lock-end)))
+ (when new
+ (setq font-lock-beg (car new))
+ (setq font-lock-end (cdr new))
+ t)))
(defun font-lock-default-fontify-region (beg end loudly)
"Fontify the text between BEG and END.
@@ -1518,7 +1526,7 @@ see `font-lock-syntactic-keywords'."
(or (nth 3 highlight)
(error "No match %d in highlight %S" match highlight))
(when (and (consp value) (not (numberp (car value))))
- (setq value (eval value)))
+ (setq value (eval value t)))
(when (stringp value) (setq value (string-to-syntax value)))
;; Flush the syntax-cache. I believe this is not necessary for
;; font-lock's use of syntax-ppss, but I'm not 100% sure and it can
@@ -1542,7 +1550,7 @@ KEYWORDS should be of the form MATCH-ANCHORED, see `font-lock-keywords',
LIMIT can be modified by the value of its PRE-MATCH-FORM."
(let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights
;; Evaluate PRE-MATCH-FORM.
- (pre-match-value (eval (nth 1 keywords))))
+ (pre-match-value (eval (nth 1 keywords) t)))
;; Set LIMIT to value of PRE-MATCH-FORM or the end of line.
(if (and (numberp pre-match-value) (> pre-match-value (point)))
(setq limit pre-match-value)
@@ -1558,7 +1566,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM."
(font-lock-apply-syntactic-highlight (car highlights))
(setq highlights (cdr highlights)))))
;; Evaluate POST-MATCH-FORM.
- (eval (nth 2 keywords))))
+ (eval (nth 2 keywords) t)))
(defun font-lock-fontify-syntactic-keywords-region (start end)
"Fontify according to `font-lock-syntactic-keywords' between START and END.
@@ -1671,7 +1679,7 @@ HIGHLIGHT should be of the form MATCH-HIGHLIGHT, see `font-lock-keywords'."
;; No match but we might not signal an error.
(or (nth 3 highlight)
(error "No match %d in highlight %S" match highlight))
- (let ((val (eval (nth 1 highlight))))
+ (let ((val (eval (nth 1 highlight) t)))
(when (eq (car-safe val) 'face)
(add-text-properties start end (cddr val))
(setq val (cadr val)))
@@ -1706,7 +1714,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM."
(let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights
(lead-start (match-beginning 0))
;; Evaluate PRE-MATCH-FORM.
- (pre-match-value (eval (nth 1 keywords))))
+ (pre-match-value (eval (nth 1 keywords) t)))
;; Set LIMIT to value of PRE-MATCH-FORM or the end of line.
(if (not (and (numberp pre-match-value) (> pre-match-value (point))))
(setq limit (line-end-position))
@@ -1731,7 +1739,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM."
(font-lock-apply-highlight (car highlights))
(setq highlights (cdr highlights)))))
;; Evaluate POST-MATCH-FORM.
- (eval (nth 2 keywords))))
+ (eval (nth 2 keywords) t)))
(defun font-lock-fontify-keywords-region (start end &optional loudly)
"Fontify according to `font-lock-keywords' between START and END.
@@ -1810,9 +1818,8 @@ If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for
(error "Font-lock trying to use keywords before setting them up"))
(if (eq (car-safe keywords) t)
keywords
- (setq keywords
- (cons t (cons keywords
- (mapcar #'font-lock-compile-keyword keywords))))
+ (let ((compiled (mapcar #'font-lock-compile-keyword keywords)))
+ (setq keywords `(t ,keywords ,@(font-lock--filter-keywords compiled))))
(if (and (not syntactic-keywords)
(let ((beg-function (with-no-warnings syntax-begin-function)))
(or (eq beg-function #'beginning-of-defun)
@@ -1838,7 +1845,7 @@ If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for
(cond ((or (functionp keyword) (nlistp keyword)) ; MATCHER
(list keyword '(0 font-lock-keyword-face)))
((eq (car keyword) 'eval) ; (eval . FORM)
- (font-lock-compile-keyword (eval (cdr keyword))))
+ (font-lock-compile-keyword (eval (cdr keyword) t)))
((eq (car-safe (cdr keyword)) 'quote) ; (MATCHER . 'FORM)
;; If FORM is a FACENAME then quote it. Otherwise ignore the quote.
(if (symbolp (nth 2 keyword))
@@ -1859,7 +1866,7 @@ If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for
keywords
(font-lock-eval-keywords (if (fboundp keywords)
(funcall keywords)
- (eval keywords)))))
+ (eval keywords t)))))
(defun font-lock-value-in-major-mode (values)
"If VALUES is a list, use `major-mode' as a key and return the `assq' value.
@@ -1883,6 +1890,50 @@ A LEVEL of nil is equal to a LEVEL of 0, a LEVEL of t is equal to
(t
(car keywords))))
+(defun font-lock--match-keyword (rule keyword)
+ "Return non-nil if font-lock KEYWORD matches RULE.
+See `font-lock-ignore' for the possible rules."
+ (pcase-exhaustive rule
+ ('* t)
+ ((pred symbolp)
+ (let ((regexp (when (string-match-p "[*?]" (symbol-name rule))
+ (wildcard-to-regexp (symbol-name rule)))))
+ (named-let search ((obj keyword))
+ (cond
+ ((consp obj) (or (search (car obj)) (search (cdr obj))))
+ ((not regexp) (eq rule obj))
+ ((symbolp obj) (string-match-p regexp (symbol-name obj)))))))
+ ((pred stringp) (when (stringp (car keyword))
+ (string-match-p (concat "\\`\\(?:" (car keyword) "\\)")
+ rule)))
+ (`(or . ,rules) (let ((match nil))
+ (while rules
+ (pcase-exhaustive (pop rules)
+ (`(except ,rule)
+ (when match
+ (setq match (not (font-lock--match-keyword rule keyword)))))
+ (rule
+ (unless match
+ (setq match (font-lock--match-keyword rule keyword))))))
+ match))
+ (`(not ,rule) (not (font-lock--match-keyword rule keyword)))
+ (`(and . ,rules) (seq-every-p (lambda (rule)
+ (font-lock--match-keyword rule keyword))
+ rules))
+ (`(pred ,fun) (funcall fun keyword))))
+
+(defun font-lock--filter-keywords (keywords)
+ "Filter a list of KEYWORDS using `font-lock-ignore'."
+ (if-let ((rules (mapcan (pcase-lambda (`(,mode . ,rules))
+ (when (or (and (boundp mode) mode)
+ (derived-mode-p mode))
+ (copy-sequence rules)))
+ font-lock-ignore)))
+ (seq-filter (lambda (keyword) (not (font-lock--match-keyword
+ `(or ,@rules) keyword)))
+ keywords)
+ keywords))
+
(defun font-lock-refresh-defaults ()
"Restart fontification in current buffer after recomputing from defaults.
Recompute fontification variables using `font-lock-defaults' and
@@ -1906,8 +1957,9 @@ preserve `hi-lock-mode' highlighting patterns."
Sets various variables using `font-lock-defaults' and
`font-lock-maximum-decoration'."
;; Set fontification defaults if not previously set for correct major mode.
- (unless (and font-lock-set-defaults
- (eq font-lock-major-mode major-mode))
+ (when (or (not font-lock-set-defaults)
+ (not font-lock-major-mode)
+ (not (derived-mode-p font-lock-major-mode)))
(setq font-lock-major-mode major-mode)
(setq font-lock-set-defaults t)
(let* ((defaults font-lock-defaults)
@@ -2277,7 +2329,7 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
;; e.g. assembler code and GNU linker script in Linux kernel.
;; `cpp-font-lock-keywords' is handy for modes for the files.
;;
-;; Here we cannot use `regexp-opt' because because regex-opt is not preloaded
+;; Here we cannot use `regexp-opt' because regex-opt is not preloaded
;; while font-lock.el is preloaded to emacs. So values pre-calculated with
;; regexp-opt are used here.
diff --git a/lisp/forms.el b/lisp/forms.el
index 8bfeaad1c1a..fdc44b5214f 100644
--- a/lisp/forms.el
+++ b/lisp/forms.el
@@ -2009,7 +2009,7 @@ It returns the highest number.
Usage: (setq forms-number-of-fields
(forms-enumerate
- '(field1 field2 field2 ...)))"
+ \\='(field1 field2 field2 ...)))"
(let ((the-index 0))
(while the-fields
diff --git a/lisp/frame.el b/lisp/frame.el
index 62b73f3157b..9476cb0ec46 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -702,7 +702,9 @@ Return nil if we don't know how to interpret DISPLAY."
The optional argument PARAMETERS specifies additional frame parameters."
(interactive (if (fboundp 'x-display-list)
(list (completing-read "Make frame on display: "
- (x-display-list)))
+ (x-display-list) nil
+ nil (car (x-display-list))
+ nil (car (x-display-list))))
(user-error "This Emacs build does not support X displays")))
(make-frame (cons (cons 'display display) parameters)))
@@ -798,8 +800,9 @@ also select the new frame."
(windows (unless no-windows
(window-state-get (frame-root-window frame))))
(default-frame-alist
- (seq-remove (lambda (elem) (eq (car elem) 'name))
- (frame-parameters frame)))
+ (seq-remove (lambda (elem)
+ (memq (car elem) frame-internal-parameters))
+ (frame-parameters frame)))
(new-frame (make-frame)))
(when windows
(window-state-put windows (frame-root-window new-frame) 'safe))
@@ -882,7 +885,6 @@ the new frame according to its own rules."
(error "Don't know how to interpret display %S"
display)))
(t window-system)))
- (oldframe (selected-frame))
(params parameters)
frame child-frame)
@@ -900,8 +902,12 @@ the new frame according to its own rules."
(dolist (p default-frame-alist)
(unless (assq (car p) params)
(push p params)))
-
-;; (setq frame-size-history '(1000))
+ ;; Add parameters from `frame-inherited-parameters' unless they are
+ ;; overridden by explicit parameters.
+ (dolist (param frame-inherited-parameters)
+ (unless (assq param parameters)
+ (let ((val (frame-parameter nil param)))
+ (when val (push (cons param val) params)))))
(when (eq (cdr (or (assq 'minibuffer params) '(minibuffer . t)))
'child-frame)
@@ -934,12 +940,6 @@ the new frame according to its own rules."
frame 'minibuffer (frame-root-window child-frame))))
(normal-erase-is-backspace-setup-frame frame)
- ;; Inherit original frame's parameters unless they are overridden
- ;; by explicit parameters.
- (dolist (param frame-inherited-parameters)
- (unless (assq param parameters)
- (let ((val (frame-parameter oldframe param)))
- (when val (set-frame-parameter frame param val)))))
;; We can run `window-configuration-change-hook' for this frame now.
(frame-after-make-frame frame t)
@@ -1589,6 +1589,11 @@ acquires focus to be automatically raised.
Note that this minor mode controls Emacs's own auto-raise
feature. Window managers that switch focus on mouse movement
often have their own auto-raise feature."
+ ;; This isn't really a global minor mode; rather, it's local to the
+ ;; selected frame, but declaring it as global prevents a misleading
+ ;; "Auto-Raise mode enabled in current buffer" message from being
+ ;; displayed when it is turned on.
+ :global t
:variable (frame-parameter nil 'auto-raise)
(if (frame-parameter nil 'auto-raise)
(raise-frame)))
@@ -1722,7 +1727,7 @@ to the selected frame.
Storing information about resize operations is off by default.
If you set the variable `frame-size-history' like this
-(setq frame-size-history '(100))
+(setq frame-size-history \\='(100))
then Emacs will save information about the next 100 significant
operations affecting any frame's size in that variable. This
@@ -1988,7 +1993,8 @@ workarea attribute."
(declare-function x-frame-list-z-order "xfns.c" (&optional display))
(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
(declare-function ns-frame-list-z-order "nsfns.m" (&optional display))
-(declare-function pgtk-frame-list-z-order "pgtkfns.c" (&optional display))
+;; TODO: implement this on PGTK.
+;; (declare-function pgtk-frame-list-z-order "pgtkfns.c" (&optional display))
(declare-function haiku-frame-list-z-order "haikufns.c" (&optional display))
(defun frame-list-z-order (&optional display)
@@ -2011,7 +2017,9 @@ Return nil if DISPLAY contains no Emacs frame."
((eq frame-type 'ns)
(ns-frame-list-z-order display))
((eq frame-type 'pgtk)
- (pgtk-frame-list-z-order display))
+ ;; This is currently not supported on PGTK.
+ ;; (pgtk-frame-list-z-order display)
+ nil)
((eq frame-type 'haiku)
(haiku-frame-list-z-order display)))))
@@ -2141,6 +2149,17 @@ frame's display)."
(defalias 'display-multi-frame-p #'display-graphic-p)
(defalias 'display-multi-font-p #'display-graphic-p)
+(defcustom tty-select-active-regions nil
+ "If non-nil, update PRIMARY window-system selection on text-mode frames.
+On a text-mode terminal that supports setSelection command, if
+this variable is non-nil, Emacs will set the PRIMARY selection
+from the active region, according to `select-active-regions'.
+This is currently supported only on xterm."
+ :group 'frames
+ :group 'killing
+ :version "29.1"
+ :type 'boolean)
+
(defun display-selections-p (&optional display)
"Return non-nil if DISPLAY supports selections.
A selection is a way to transfer text or other data between programs
@@ -2156,6 +2175,9 @@ frame's display)."
(not (null dos-windows-version))))
((memq frame-type '(x w32 ns pgtk))
t)
+ ((and tty-select-active-regions
+ (terminal-parameter nil 'xterm--set-selection))
+ t)
(t
nil))))
@@ -2368,6 +2390,8 @@ If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(&optional terminal))
(declare-function pgtk-display-monitor-attributes-list "pgtkfns.c"
(&optional terminal))
+(declare-function haiku-display-monitor-attributes-list "haikufns.c"
+ (&optional terminal))
(defun display-monitor-attributes-list (&optional display)
"Return a list of physical monitor attributes on DISPLAY.
@@ -2419,6 +2443,8 @@ monitors."
(ns-display-monitor-attributes-list display))
((eq frame-type 'pgtk)
(pgtk-display-monitor-attributes-list display))
+ ((eq frame-type 'haiku)
+ (haiku-display-monitor-attributes-list display))
(t
(let ((geometry (list 0 0 (display-pixel-width display)
(display-pixel-height display))))
@@ -2428,6 +2454,70 @@ monitors."
,(display-mm-height display)))
(frames . ,(frames-on-display-list display)))))))))
+(declare-function x-device-class "term/x-win.el" (name))
+(declare-function pgtk-device-class "term/pgtk-win.el" (name))
+
+(defun device-class (frame name)
+ "Return the class of the device NAME for an event generated on FRAME.
+NAME is a string that can be the value of `last-event-device', or
+nil. FRAME is a window system frame, typically the value of
+`last-event-frame' when `last-event-device' was set. On some
+window systems, it can also be a display name or a terminal.
+
+The class of a device is one of the following symbols:
+
+ `core-keyboard' means the device is a keyboard-like device, but
+ any other characteristics are unknown.
+
+ `core-pointer' means the device is a pointing device, but any
+ other characteristics are unknown.
+
+ `mouse' means the device is a computer mouse.
+
+ `trackpoint' means the device is a joystick or trackpoint.
+
+ `eraser' means the device is an eraser, which is typically the
+ other end of a stylus on a graphics tablet.
+
+ `pen' means the device is a stylus or some other similar
+ device.
+
+ `puck' means the device is a device similar to a mouse, but
+ reports absolute coordinates.
+
+ `power-button' means the device is a power button, volume
+ button, or some similar control.
+
+ `keyboard' means the device is a keyboard.
+
+ `touchscreen' means the device is a touchscreen.
+
+ `pad' means the device is a collection of buttons and rings and
+ strips commonly found in drawing tablets.
+
+ `touchpad' means the device is an indirect touch device, such
+ as a touchpad.
+
+ `piano' means the device is a piano, or some other kind of
+ musical instrument.
+
+ `test' means the device is used by the XTEST extension to
+ report input.
+
+It can also be nil, which means the class of the device could not
+be determined. Individual window systems may also return other
+symbols."
+ (let ((frame-type (framep-on-display frame)))
+ (cond ((eq frame-type 'x)
+ (x-device-class name))
+ ((eq frame-type 'pgtk)
+ (pgtk-device-class name))
+ (t (cond
+ ((string= name "Virtual core pointer")
+ 'core-pointer)
+ ((string= name "Virtual core keyboard")
+ 'core-keyboard))))))
+
;;;; Frame geometry values
@@ -2529,6 +2619,77 @@ deleting them."
(if iconify (iconify-frame this) (delete-frame this)))
(setq this next))))
+(defvar undelete-frame--deleted-frames nil
+ "Internal variable used by `undelete-frame--save-deleted-frame'.")
+
+(defun undelete-frame--save-deleted-frame (frame)
+ "Save the configuration of frames deleted with `delete-frame'.
+Only the 16 most recently deleted frames are saved."
+ (when (and after-init-time (frame-live-p frame))
+ (setq undelete-frame--deleted-frames
+ (cons
+ (list
+ (display-graphic-p)
+ (seq-remove
+ (lambda (elem)
+ (or (memq (car elem) frame-internal-parameters)
+ ;; When the daemon is started from a graphical
+ ;; environment, TTY frames have a 'display' parameter set
+ ;; to the value of $DISPLAY (see the note in
+ ;; `server--on-display-p'). Do not store that parameter
+ ;; in the frame data, otherwise `undelete-frame' attempts
+ ;; to restore a graphical frame.
+ (and (eq (car elem) 'display) (not (display-graphic-p)))))
+ (frame-parameters frame))
+ (window-state-get (frame-root-window frame)))
+ undelete-frame--deleted-frames))
+ (if (> (length undelete-frame--deleted-frames) 16)
+ (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--save-deleted-frame -75)
+ (remove-hook 'delete-frame-functions
+ #'undelete-frame--save-deleted-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 16, 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)))
+ (frame-data (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 frame-data)
+ (user-error "No deleted frame with number %d" number)
+ (if (not (eq graphic (nth 0 frame-data)))
+ (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 frame-data undelete-frame--deleted-frames))
+ (let* ((default-frame-alist (nth 1 frame-data))
+ (frame (make-frame)))
+ (window-state-put (nth 2 frame-data) (frame-root-window frame) 'safe)
+ (select-frame-set-input-focus frame)
+ frame))))))))
;;; Window dividers.
(defgroup window-divider nil
@@ -2680,7 +2841,7 @@ Values smaller than 0.2 sec are treated as 0.2 sec."
"How many times to blink before using a solid cursor on NS, X, and MS-Windows.
Use 0 or negative value to blink forever."
:version "24.4"
- :type 'integer
+ :type 'natnum
:group 'cursor)
(defvar blink-cursor-blinks-done 1
@@ -2820,6 +2981,12 @@ If the frame is in fullscreen state, don't change its state, but
set the frame's `fullscreen-restore' parameter to `maximized', so
the frame will be maximized after disabling fullscreen state.
+If you wish to hide the title bar when the frame is maximized, you
+can add something like the following to your init file:
+
+ (add-hook \\='window-size-change-functions
+ #\\='frame-hide-title-bar-when-maximized)
+
Note that with some window managers you may have to set
`frame-resize-pixelwise' to non-nil in order to make a frame
appear truly maximized. In addition, you may have to set
@@ -2873,6 +3040,7 @@ See also `toggle-frame-maximized'."
(define-key ctl-x-5-map "o" #'other-frame)
(define-key ctl-x-5-map "5" #'other-frame-prefix)
(define-key ctl-x-5-map "c" #'clone-frame)
+(define-key ctl-x-5-map "u" #'undelete-frame)
(define-key global-map [f11] #'toggle-frame-fullscreen)
(define-key global-map [(meta f10)] #'toggle-frame-maximized)
(define-key esc-map [f10] #'toggle-frame-maximized)
@@ -2934,6 +3102,13 @@ Offer NUMBER as default value, if it is a natural number."
bidi-display-reordering
bidi-inhibit-bpa))
+(defun frame-hide-title-bar-when-maximized (frame)
+ "Hide the title bar if FRAME is maximized.
+If FRAME isn't maximized, show the title bar."
+ (set-frame-parameter
+ frame 'undecorated
+ (eq (alist-get 'fullscreen (frame-parameters frame)) 'maximized)))
+
(provide 'frame)
;;; frame.el ends here
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 10714af1fa5..a589f7b5d96 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -436,10 +436,11 @@ Properties can be set with
;;;###autoload
(defvar frameset-session-filter-alist
- '((name . :never)
- (left . frameset-filter-iconified)
- (minibuffer . frameset-filter-minibuffer)
- (top . frameset-filter-iconified))
+ (append
+ '((left . frameset-filter-iconified)
+ (minibuffer . frameset-filter-minibuffer)
+ (top . frameset-filter-iconified))
+ (mapcar (lambda (p) (cons p :never)) frame-internal-parameters))
"Minimum set of parameters to filter for live (on-session) framesets.
DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
@@ -447,6 +448,7 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
(defvar frameset-persistent-filter-alist
(append
'((background-color . frameset-filter-sanitize-color)
+ (bottom . frameset-filter-shelve-param)
(buffer-list . :never)
(buffer-predicate . :never)
(buried-buffer-list . :never)
@@ -463,19 +465,23 @@ DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
(frameset--text-pixel-height . :save)
(frameset--text-pixel-width . :save)
(fullscreen . frameset-filter-shelve-param)
+ (GUI:bottom . frameset-filter-unshelve-param)
(GUI:font . frameset-filter-unshelve-param)
(GUI:fullscreen . frameset-filter-unshelve-param)
(GUI:height . frameset-filter-unshelve-param)
+ (GUI:left . frameset-filter-unshelve-param)
+ (GUI:right . frameset-filter-unshelve-param)
+ (GUI:top . frameset-filter-unshelve-param)
(GUI:width . frameset-filter-unshelve-param)
(height . frameset-filter-shelve-param)
- (outer-window-id . :never)
+ (left . frameset-filter-shelve-param)
(parent-frame . :never)
- (parent-id . :never)
(mouse-wheel-frame . :never)
+ (right . frameset-filter-shelve-param)
+ (top . frameset-filter-shelve-param)
(tty . frameset-filter-tty-to-GUI)
(tty-type . frameset-filter-tty-to-GUI)
(width . frameset-filter-shelve-param)
- (window-id . :never)
(window-system . :never))
frameset-session-filter-alist)
"Parameters to filter for persistent framesets.
@@ -1012,13 +1018,15 @@ not be changed once the frame has been created. Internal use only."
(cl-loop for param in '(left top width height border-width minibuffer)
when (assq param parameters) collect it))
-(defun frameset--restore-frame (parameters window-state filters force-onscreen)
+(defun frameset--restore-frame (parameters window-state filters force-onscreen
+ &optional dx dy)
"Set up and return a frame according to its saved state.
That means either reusing an existing frame or creating one anew.
PARAMETERS is the frame's parameter alist; WINDOW-STATE is its window state.
For the meaning of FILTERS and FORCE-ONSCREEN, see `frameset-restore'.
Internal use only."
(let* ((fullscreen (cdr (assq 'fullscreen parameters)))
+ (tty-to-GUI (frameset-switch-to-gui-p parameters))
(filtered-cfg (frameset-filter-params parameters filters nil))
(display (cdr (assq 'display filtered-cfg))) ;; post-filtering
alt-cfg frame)
@@ -1095,6 +1103,14 @@ Internal use only."
(not (eq (frame-parameter frame 'visibility) 'icon)))
(frameset-move-onscreen frame force-onscreen))
+ ;; Frames saved on TTY shall be all considered visible when
+ ;; restoring on GUI display. Also, offset each new such frame
+ ;; relative to the previous one, to make it more visible.
+ (when tty-to-GUI
+ (push '(visibility . t) alt-cfg)
+ (when (and (numberp dx) (numberp dy))
+ (push (cons 'left (+ (frame-parameter frame 'left) dx)) alt-cfg)
+ (push (cons 'top (+ (frame-parameter frame 'top) dy)) alt-cfg)))
;; Let's give the finishing touches (visibility, maximization).
(when alt-cfg (modify-frame-parameters frame alt-cfg))
;; Now restore window state.
@@ -1218,7 +1234,9 @@ All keyword parameters default to nil."
((pred functionp)
(cl-remove-if-not reuse-frames frames))
(_
- (error "Invalid arg :reuse-frames %s" reuse-frames)))))
+ (error "Invalid arg :reuse-frames %s" reuse-frames))))
+ (dx 0)
+ (dy 0))
;; Mark existing frames in the map; candidates to reuse are marked as :ignored;
;; they will be reassigned later, if chosen.
@@ -1291,11 +1309,21 @@ All keyword parameters default to nil."
(setq mb-window nil)))
(when mb-window
(push (cons 'minibuffer mb-window) frame-cfg))))))
+ ;; Apply small offsets to each frame that came from
+ ;; a TTY-saved desktop, so that they don't obscure
+ ;; each other, but only if we don't have real frame
+ ;; position info from a GUI session in some,
+ ;; possibly distant, past.
+ (when (and (frameset-switch-to-gui-p frame-cfg)
+ (null (cdr (assq 'GUI:top frame-cfg)))
+ (null (cdr (assq 'GUI:left frame-cfg))))
+ (setq dx (+ dx 20)
+ dy (+ dy 10)))
;; OK, we're ready at last to create (or reuse) a frame and
;; restore the window config.
(setq frame (frameset--restore-frame frame-cfg window-cfg
(or filters frameset-filter-alist)
- force-onscreen))
+ force-onscreen dx dy))
;; Now reset any duplicate frameset--id
(when (and duplicate (not (eq frame duplicate)))
(set-frame-parameter duplicate 'frameset--id nil))
diff --git a/lisp/fringe.el b/lisp/fringe.el
index 8c833f02429..657a73772d5 100644
--- a/lisp/fringe.el
+++ b/lisp/fringe.el
@@ -244,10 +244,18 @@ When used in a Lisp program, MODE should be one of these:
nil (meaning the default width).
- a single integer, which specifies the pixel widths of both
fringes.
+
This command may round up the left and right width specifications
to ensure that their sum is a multiple of the character width of
a frame. It never rounds up a fringe width of 0.
+Note that removing a right or left fringe (by setting the width
+to zero) makes Emacs reserve one column of the window body to
+display a line continuation marker. (This happens for both the
+left and right fringe, since Emacs can display both left-to-right
+and right-to-left text.) You can use `window-max-chars-per-line'
+to check the effective width.
+
Fringe widths set by `set-window-fringes' override the default
fringe widths set by this command. This command applies to all
frames that exist and frames to be created in the future. If you
@@ -306,7 +314,7 @@ BITMAP is a symbol identifying the new fringe bitmap.
BITS is either a string or a vector of integers.
HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
-Optional fifth arg ALIGN may be one of ‘top’, ‘center’, or ‘bottom’,
+Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
indicating the positioning of the bitmap relative to the rows where it
is used; the default is to center the bitmap. Fifth arg may also be a
list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
diff --git a/lisp/generic-x.el b/lisp/generic-x.el
index ecfa8aab845..2c9d1b316e1 100644
--- a/lisp/generic-x.el
+++ b/lisp/generic-x.el
@@ -1847,4 +1847,8 @@ like an INI file. You can add this hook to `find-file-hook'."
(provide 'generic-x)
+;; Local Variables:
+;; autoload-compute-prefixes: nil
+;; End:
+
;;; generic-x.el ends here
diff --git a/lisp/gnus/deuglify.el b/lisp/gnus/deuglify.el
index d2edfdf09f4..732c6062b8b 100644
--- a/lisp/gnus/deuglify.el
+++ b/lisp/gnus/deuglify.el
@@ -439,6 +439,7 @@ If NODISPLAY is non-nil, don't redisplay the article buffer."
(unless nodisplay (gnus-outlook-display-article-buffer))
attrib-start))
+;;;###autoload
(defun gnus-article-outlook-rearrange-citation (&optional nodisplay)
"Repair broken citations.
If NODISPLAY is non-nil, don't redisplay the article buffer."
diff --git a/lisp/gnus/gmm-utils.el b/lisp/gnus/gmm-utils.el
index 697ce01343a..fc18d8a1c51 100644
--- a/lisp/gnus/gmm-utils.el
+++ b/lisp/gnus/gmm-utils.el
@@ -134,47 +134,8 @@ ARGS are passed to `message'."
(const :tag "No map")
(plist :inline t :tag "Properties"))))
-(define-widget 'gmm-tool-bar-zap-list 'lazy
- "Tool bar zap list."
- :tag "Tool bar zap list"
- :type '(choice (const :tag "Zap all" t)
- (const :tag "Keep all" nil)
- (list
- ;; :value
- ;; Work around (bug in customize?), see
- ;; <news:v9is48jrj1.fsf@marauder.physik.uni-ulm.de>
- ;; (new-file open-file dired kill-buffer write-file
- ;; print-buffer customize help)
- (set :inline t
- (const new-file)
- (const open-file)
- (const dired)
- (const kill-buffer)
- (const save-buffer)
- (const write-file)
- (const undo)
- (const cut)
- (const copy)
- (const paste)
- (const search-forward)
- (const print-buffer)
- (const customize)
- (const help))
- (repeat :inline t
- :tag "Other"
- (symbol :tag "Icon item")))))
-
-(defcustom gmm-tool-bar-style
- (if (and (boundp 'tool-bar-mode)
- tool-bar-mode
- (not (memq (display-visual-class)
- (list 'static-gray 'gray-scale
- 'static-color 'pseudo-color))))
- 'gnome
- 'retro)
- "Preferred tool bar style."
- :type '(choice (const :tag "GNOME style" gnome)
- (const :tag "Retro look" retro)))
+(defvar gmm-tool-bar-style 'gnome)
+(make-obsolete-variable 'gmm-tool-bar-style nil "29.1")
(defvar tool-bar-map)
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 f26ab6ab4c7..4b68a54ce81 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")
@@ -742,7 +743,7 @@ Each element is a regular expression."
"Face used for highlighting buttons in the article buffer.
An article button is a piece of text that you can activate by pressing
-`RET' or `mouse-2' above it."
+\\`RET' or `mouse-2' above it."
:type 'face
:group 'gnus-article-buttons)
@@ -1090,9 +1091,9 @@ positive (negative), move point forward (backwards) this many
parts. When nil, redisplay article."
:version "23.1" ;; No Gnus
:group 'gnus-article-mime
- :type '(choice (const nil :tag "Redisplay article.")
- (const 1 :tag "Next part.")
- (const 0 :tag "Current part.")
+ :type '(choice (const :value nil :tag "Redisplay article")
+ (const :value 1 :tag "Next part")
+ (const :value 0 :tag "Current part")
integer))
;;;
@@ -1159,13 +1160,15 @@ predicate. See Info node `(gnus)Customizing Articles'."
:link '(custom-manual "(gnus)Customizing Articles")
:type gnus-article-treat-head-custom)
-(defcustom gnus-treat-emphasize 50000
+(defcustom gnus-treat-emphasize '(and 50000
+ (not (typep "text/html")))
"Emphasize text.
Valid values are nil, t, `head', `first', `last', an integer or a
predicate. See Info node `(gnus)Customizing Articles'."
:group 'gnus-article-treat
:link '(custom-manual "(gnus)Customizing Articles")
- :type gnus-article-treat-custom)
+ :type gnus-article-treat-custom
+ :version "29.1")
(put 'gnus-treat-emphasize 'highlight t)
(defcustom gnus-treat-strip-cr nil
@@ -1392,6 +1395,15 @@ predicate. See Info node `(gnus)Customizing Articles'."
:link '(custom-manual "(gnus)Customizing Articles")
:type gnus-article-treat-custom)
+(defcustom gnus-treat-suspicious-headers 'head
+ "Mark headers that are suspicious.
+Valid values are nil, t, `head', `first', `last', an integer or a
+predicate. See Info node `(gnus)Customizing Articles'."
+ :version "29.1"
+ :group 'gnus-article-treat
+ :link '(custom-manual "(gnus)Customizing Articles")
+ :type gnus-article-treat-custom)
+
(defcustom gnus-treat-fold-newsgroups 'head
"Fold the Newsgroups and Followup-To headers.
Valid values are nil, t, `head', `first', `last', an integer or a
@@ -1709,6 +1721,7 @@ regexp."
(gnus-treat-unfold-headers gnus-article-treat-unfold-headers)
(gnus-treat-fold-newsgroups gnus-article-treat-fold-newsgroups)
(gnus-treat-fold-headers gnus-article-treat-fold-headers)
+ (gnus-treat-suspicious-headers gnus-article-treat-suspicious-headers)
(gnus-treat-buttonize-head gnus-article-add-buttons-to-head)
(gnus-treat-display-smileys gnus-treat-smiley)
(gnus-treat-capitalize-sentences gnus-article-capitalize-sentences)
@@ -2233,6 +2246,20 @@ unfolded."
(pixel-fill-region (point) (point-max) (pixel-fill-width)))
(goto-char (point-max))))))
+(defun gnus-article-treat-suspicious-headers ()
+ "Mark suspicious headers."
+ (interactive nil gnus-article-mode gnus-summary-mode)
+ (gnus-with-article-headers
+ (let (match)
+ (while (setq match (text-property-search-forward 'textsec-suspicious))
+ (add-text-properties (prop-match-beginning match)
+ (prop-match-end match)
+ (list 'help-echo (prop-match-value match)
+ 'face 'textsec-suspicious))
+ (overlay-put (make-overlay (prop-match-end match)
+ (prop-match-end match))
+ 'after-string "⚠️")))))
+
(defun gnus-treat-smiley ()
"Toggle display of textual emoticons (\"smileys\") as small graphical icons."
(interactive nil gnus-article-mode gnus-summary-mode)
@@ -2299,9 +2326,7 @@ This only works if the article in question is HTML."
(goto-char (point-max))))))
(defcustom gnus-article-truncate-lines (default-value 'truncate-lines)
- "Value of `truncate-lines' in Gnus Article buffer.
-Valid values are nil, t, `head', `first', `last', an integer or a
-predicate. See Info node `(gnus)Customizing Articles'."
+ "Value of `truncate-lines' in Gnus Article buffer."
:version "23.1" ;; No Gnus
:group 'gnus-article
;; :link '(custom-manual "(gnus)Customizing Articles")
@@ -2609,17 +2634,37 @@ If PROMPT (the prefix), prompt for a coding system to use."
(forward-line -1))
(setq end (point))
(while (not (bobp))
- (while (progn
- (forward-line -1)
- (and (not (bobp))
- (memq (char-after) '(?\t ? )))))
- (setq start (point))
- (if (looking-at "\
+ (let (addresses)
+ (while (progn
+ (forward-line -1)
+ (and (not (bobp))
+ (memq (char-after) '(?\t ? )))))
+ (setq start (point))
+ (save-restriction
+ (narrow-to-region start end)
+ (if (looking-at "\
\\(?:Resent-\\)?\\(?:From\\|Cc\\|To\\|Bcc\\|\\(?:In-\\)?Reply-To\\|Sender\
\\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\):")
- (funcall gnus-decode-address-function start end)
- (funcall gnus-decode-header-function start end))
- (goto-char (setq end start)))))
+ (progn
+ (setq addresses (buffer-string))
+ (funcall gnus-decode-address-function (point-min) (point-max)))
+ (funcall gnus-decode-header-function (point-min) (point-max))))
+ (when addresses
+ (article--check-suspicious-addresses addresses))
+ (goto-char (point-max))
+ (goto-char (setq end start))))))
+
+(defun article--check-suspicious-addresses (addresses)
+ (setq addresses (replace-regexp-in-string "\\`[^:]+:[ \t\n]*" "" addresses))
+ (dolist (header (mail-header-parse-addresses addresses t))
+ (when-let* ((address (car (ignore-errors
+ (mail-header-parse-address header))))
+ (warning (and (string-match "@" address)
+ (textsec-suspicious-p address 'email-address))))
+ (goto-char (point-min))
+ (while (search-forward address nil t)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'textsec-suspicious warning)))))
(defun article-decode-group-name ()
"Decode group names in Newsgroups, Followup-To and Xref headers."
@@ -7017,7 +7062,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-cus.el b/lisp/gnus/gnus-cus.el
index f8714a95d40..ddd939794dd 100644
--- a/lisp/gnus/gnus-cus.el
+++ b/lisp/gnus/gnus-cus.el
@@ -273,7 +273,7 @@ DOC is a documentation string for the parameter.")
gnus-agent-cat-predicate)
(agent-score
(choice :tag "Score File" :value nil
- (const file :tag "Use group's score files")
+ (const :value file :tag "Use group's score files")
(repeat (list (string :format "%v" :tag "File name"))))
"Which score files to use when using score to select articles to fetch.
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-eform.el b/lisp/gnus/gnus-eform.el
index 300532de286..96f515119dc 100644
--- a/lisp/gnus/gnus-eform.el
+++ b/lisp/gnus/gnus-eform.el
@@ -92,7 +92,7 @@ The optional LAYOUT overrides the `edit-form' window layout."
(insert ";;; ")
(forward-line 1))
(insert (substitute-command-keys
- ";; Type `C-c C-c' after you've finished editing.\n"))
+ ";; Type \\`C-c C-c' after you've finished editing.\n"))
(insert "\n")
(let ((p (point)))
(gnus-pp form)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index ab874dd0608..04d19e29a3a 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)
@@ -982,66 +983,36 @@ simple manner."
(gnus-run-hooks 'gnus-group-menu-hook)))
-
(defvar gnus-group-tool-bar-map nil)
-(defun gnus-group-tool-bar-update (&optional symbol value)
- "Update group buffer toolbar.
-Setter function for custom variables."
- (when symbol
- (set-default symbol value))
- ;; (setq-default gnus-group-tool-bar-map nil)
- ;; (use-local-map gnus-group-mode-map)
- (when (gnus-alive-p)
- (with-current-buffer gnus-group-buffer
- (gnus-group-make-tool-bar t))))
-
-(defcustom gnus-group-tool-bar (if (eq gmm-tool-bar-style 'gnome)
- 'gnus-group-tool-bar-gnome
- 'gnus-group-tool-bar-retro)
- "Specifies the Gnus group tool bar.
-
-It can be either a list or a symbol referring to a list. See
-`gmm-tool-bar-from-list' for the format of the list. The
-default key map is `gnus-group-mode-map'.
-
-Pre-defined symbols include `gnus-group-tool-bar-gnome' and
-`gnus-group-tool-bar-retro'."
- :type '(choice (const :tag "GNOME style" gnus-group-tool-bar-gnome)
- (const :tag "Retro look" gnus-group-tool-bar-retro)
- (repeat :tag "User defined list" gmm-tool-bar-item)
- (symbol))
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-group-tool-bar-update
- :group 'gnus-group)
-
-(defcustom gnus-group-tool-bar-gnome
+(defcustom gnus-group-tool-bar
'((gnus-group-post-news "mail/compose")
;; Some useful agent icons? I don't use the agent so agent users should
;; suggest useful commands:
- (gnus-agent-toggle-plugged "unplugged" t
- :help "Gnus is currently unplugged. Click to work online."
- :visible (and gnus-agent (not gnus-plugged)))
- (gnus-agent-toggle-plugged "plugged" t
- :help "Gnus is currently plugged. Click to work offline."
- :visible (and gnus-agent gnus-plugged))
- ;; FIXME: gnus-agent-toggle-plugged (in gnus-agent-group-make-menu-bar)
- ;; should have a better help text.
- (gnus-group-send-queue "mail/outbox" t
- :visible (and gnus-agent gnus-plugged)
- :help "Send articles from the queue group")
- (gnus-group-get-new-news "mail/inbox" nil
- :visible (or (not gnus-agent)
- gnus-plugged))
- ;; FIXME: gnus-*-read-group should have a better help text.
- (gnus-topic-read-group "open" nil
- :visible (and (boundp 'gnus-topic-mode)
- gnus-topic-mode))
- (gnus-group-read-group "open" nil
- :visible (not (and (boundp 'gnus-topic-mode)
- gnus-topic-mode)))
- ;; (gnus-group-find-new-groups "???" nil)
+ (gnus-agent-toggle-plugged
+ "unplugged" t
+ :help "Gnus is currently unplugged. Click to work online."
+ :visible (and gnus-agent (not gnus-plugged)))
+ (gnus-agent-toggle-plugged
+ "plugged" t
+ :help "Gnus is currently plugged. Click to work offline."
+ :visible (and gnus-agent gnus-plugged))
+ (gnus-group-send-queue
+ "mail/outbox" t
+ :visible (and gnus-agent gnus-plugged)
+ :help "Send articles from the queue group")
+ (gnus-group-get-new-news
+ "mail/inbox" nil
+ :visible (or (not gnus-agent)
+ gnus-plugged))
+ (gnus-topic-read-group
+ "open" nil
+ :visible (and (boundp 'gnus-topic-mode)
+ gnus-topic-mode))
+ (gnus-group-read-group
+ "open" nil
+ :visible (not (and (boundp 'gnus-topic-mode)
+ gnus-topic-mode)))
(gnus-group-save-newsrc "save")
(gnus-group-describe-group "describe")
(gnus-group-toggle-subscription-at-point "gnus/toggle-subscription")
@@ -1050,44 +1021,22 @@ Pre-defined symbols include `gnus-group-tool-bar-gnome' and
(gnus-group-exit "exit")
(gmm-customize-mode "preferences" t :help "Edit mode preferences")
(gnus-info-find-node "help"))
- "List of functions for the group tool bar (GNOME style).
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-group-tool-bar-update
- :group 'gnus-group)
+ "Specifies the Gnus group tool bar.
-(defcustom gnus-group-tool-bar-retro
- '((gnus-group-get-new-news "gnus/get-news")
- (gnus-group-get-new-news-this-group "gnus/gnntg")
- (gnus-group-catchup-current "gnus/catchup")
- (gnus-group-describe-group "gnus/describe-group")
- (gnus-group-subscribe "gnus/subscribe" t
- :help "Subscribe to the current group")
- (gnus-group-unsubscribe "gnus/unsubscribe" t
- :help "Unsubscribe from the current group")
- (gnus-group-exit "gnus/exit-gnus" gnus-group-mode-map))
- "List of functions for the group tool bar (retro look).
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-group-tool-bar-update
+It can be either a list or a symbol referring to a list. See
+`gmm-tool-bar-from-list' for the format of the list. The
+default key map is `gnus-group-mode-map'."
+ :type '(choice (repeat :tag "User defined list" gmm-tool-bar-item)
+ (symbol))
+ :version "29.1"
:group 'gnus-group)
-(defcustom gnus-group-tool-bar-zap-list t
- "List of icon items from the global tool bar.
-These items are not displayed in the Gnus group mode tool bar.
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type 'gmm-tool-bar-zap-list
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-group-tool-bar-update
- :group 'gnus-group)
+(defvar gnus-group-tool-bar-gnome nil)
+(make-obsolete-variable 'gnus-group-tool-bar-gnome nil "29.1")
+(defvar gnus-group-tool-bar-retro nil)
+(make-obsolete-variable 'gnus-group-tool-bar-retro nil "29.1")
+(defvar gnus-group-tool-bar-zap-list t)
+(make-obsolete-variable 'gnus-group-tool-bar-zap-list nil "29.1")
(defvar image-load-path)
(defvar tool-bar-map)
@@ -1482,9 +1431,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 +1591,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 +2014,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 +2781,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)))
@@ -3134,9 +3083,9 @@ If SOLID (the prefix), create a solid group."
(if (derived-mode-p 'gnus-summary-mode) 'summary 'group))))))
(defvar nnrss-group-alist)
-(eval-when-compile
- (defun nnrss-discover-feed (_arg))
- (defun nnrss-save-server-data (_arg)))
+(declare-function nnrss-discover-feed "nnrss" (url))
+(declare-function nnrss-save-server-data "nnrss" (server))
+
(defun gnus-group-make-rss-group (&optional url)
"Given a URL, discover if there is an RSS feed.
If there is, use Gnus to create an nnrss group"
@@ -3225,7 +3174,11 @@ non-nil SPECS arg must be an alist with `search-query-spec' and
(if (gnus-server-server-name)
(list (list (gnus-server-server-name)))
(seq-group-by
- (lambda (elt) (gnus-group-server elt))
+ (lambda (elt)
+ (if (gnus-group-native-p elt)
+ (gnus-group-server elt)
+ (gnus-method-to-server
+ (gnus-find-method-for-group elt))))
(or gnus-group-marked
(if (gnus-group-group-name)
(list (gnus-group-group-name))
@@ -3276,7 +3229,11 @@ non-nil SPECS arg must be an alist with `search-query-spec' and
(if (gnus-server-server-name)
(list (list (gnus-server-server-name)))
(seq-group-by
- (lambda (elt) (gnus-group-server elt))
+ (lambda (elt)
+ (if (gnus-group-native-p elt)
+ (gnus-group-server elt)
+ (gnus-method-to-server
+ (gnus-find-method-for-group elt))))
(or gnus-group-marked
(if (gnus-group-group-name)
(list (gnus-group-group-name))
@@ -3755,15 +3712,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 +3752,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 +4628,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-html.el b/lisp/gnus/gnus-html.el
index 45f1e6099ea..87f3ee63623 100644
--- a/lisp/gnus/gnus-html.el
+++ b/lisp/gnus/gnus-html.el
@@ -40,14 +40,11 @@
(require 'help-fns)
(require 'url-queue)
-(defcustom gnus-html-image-cache-ttl (days-to-time 7)
- "Time used to determine if we should use images from the cache."
- :version "24.1"
+(defcustom gnus-html-image-cache-ttl (time-convert (days-to-time 7) 'integer)
+ "Number of seconds used to determine if we should use images from the cache."
+ :version "29.1"
:group 'gnus-art
- ;; FIXME hardly the friendliest type. The allowed value is actually
- ;; any time value, but we are assuming no-one cares about USEC and
- ;; PSEC here. It would be better to eg make it a number of minutes.
- :type '(list integer integer))
+ :type 'number)
(defcustom gnus-html-image-automatic-caching t
"Whether automatically cache retrieve images."
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
index 754a1d91cb5..1bffdf3513a 100644
--- a/lisp/gnus/gnus-icalendar.el
+++ b/lisp/gnus/gnus-icalendar.el
@@ -830,11 +830,12 @@ These will be used to retrieve the RSVP information from ical events."
(defmacro gnus-icalendar-with-decoded-handle (handle &rest body)
"Execute BODY in buffer containing the decoded contents of HANDLE."
(let ((charset (make-symbol "charset")))
- `(let ((,charset (cdr (assoc 'charset (mm-handle-type ,handle)))))
+ `(let ((,charset (downcase
+ (or (cdr (assoc 'charset (mm-handle-type ,handle)))
+ "utf-8"))))
(with-temp-buffer
(mm-insert-part ,handle)
- (when (and ,charset (string= (downcase ,charset) "utf-8"))
- (decode-coding-region (point-min) (point-max) 'utf-8))
+ (decode-coding-region (point-min) (point-max) (intern ,charset))
,@body))))
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-logic.el b/lisp/gnus/gnus-logic.el
index 3fb2ed3c626..c1b559ba6f4 100644
--- a/lisp/gnus/gnus-logic.el
+++ b/lisp/gnus/gnus-logic.el
@@ -224,8 +224,8 @@
(goto-char (point-min))
(prog1
(funcall search-func match nil t)
- (widen)))
- (when handles (mm-destroy-parts handles))))))
+ (widen)
+ (when handles (mm-destroy-parts handles))))))))
(provide 'gnus-logic)
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index f38f6f4ee2b..3fc5ce2408a 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -52,24 +52,6 @@ method to use when posting."
(const current)
(sexp :tag "Methods" ,gnus-select-method)))
-(defcustom gnus-outgoing-message-group nil
- "All outgoing messages will be put in this group.
-If you want to store all your outgoing mail and articles in the group
-\"nnml:archive\", you set this variable to that value. This variable
-can also be a list of group names.
-
-If you want to have greater control over what group to put each
-message in, you can set this variable to a function that checks the
-current newsgroup name and then returns a suitable group name (or list
-of names)."
- :group 'gnus-message
- :type '(choice (const nil)
- (function)
- (string :tag "Group")
- (repeat :tag "List of groups" (string :tag "Group"))))
-
-(make-obsolete-variable 'gnus-outgoing-message-group 'gnus-message-archive-group "24.1")
-
(defcustom gnus-mailing-list-groups nil
"If non-nil a regexp matching groups that are really mailing lists.
This is useful when you're reading a mailing list that has been
@@ -215,30 +197,6 @@ use this option with care."
:parameter-document "\
List of charsets that are permitted to be unencoded.")
-(defcustom gnus-debug-files
- '("gnus.el" "gnus-sum.el" "gnus-group.el"
- "gnus-art.el" "gnus-start.el" "gnus-async.el"
- "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el"
- "gnus-agent.el" "gnus-cache.el" "gnus-srvr.el"
- "mm-util.el" "mm-decode.el" "nnmail.el" "message.el")
- "Files whose variables will be reported in `gnus-bug'."
- :version "22.1"
- :group 'gnus-message
- :type '(repeat file))
-
-(make-obsolete-variable 'gnus-debug-files "it is no longer used." "24.1")
-
-(defcustom gnus-debug-exclude-variables
- '(mm-mime-mule-charset-alist
- nnmail-split-fancy message-minibuffer-local-map)
- "Variables that should not be reported in `gnus-bug'."
- :version "22.1"
- :group 'gnus-message
- :type '(repeat variable))
-
-(make-obsolete-variable
- 'gnus-debug-exclude-variables "it is no longer used." "24.1")
-
(defcustom gnus-discouraged-post-methods
'(nndraft nnml nnimap nnmaildir nnmh nnfolder nndir)
"A list of back ends that are not used in \"real\" newsgroups.
@@ -1571,8 +1529,9 @@ this is a reply."
(when gcc
(message-remove-header "gcc")
(widen)
- (setq groups (message-unquote-tokens
- (message-tokenize-header gcc ",\n\t")))
+ (setq groups (mapcar #'string-trim
+ (message-unquote-tokens
+ (message-tokenize-header gcc))))
;; Copy the article over to some group(s).
(while (setq group (pop groups))
(setq method (gnus-inews-group-method group))
@@ -1593,9 +1552,10 @@ this is a reply."
(nnheader-set-temp-buffer " *acc*")
(setq message-options (with-current-buffer cur message-options))
(insert-buffer-substring cur)
+ (restore-buffer-modified-p nil)
(run-hooks 'gnus-gcc-pre-body-encode-hook)
;; Avoid re-doing things like GPG-encoding secret parts.
- (if (not encoded-cache)
+ (if (or (buffer-modified-p) (not encoded-cache))
(message-encode-message-body)
(erase-buffer)
(insert encoded-cache))
@@ -1663,7 +1623,7 @@ this is a reply."
(defun gnus-inews-insert-gcc (&optional group)
"Insert the Gcc to say where the article is to be archived."
(let* ((group (or group gnus-newsgroup-name))
- (var (or gnus-outgoing-message-group gnus-message-archive-group))
+ (var gnus-message-archive-group)
(gcc-self-val
(and group (not (gnus-virtual-group-p group))
(gnus-group-find-parameter group 'gcc-self t)))
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index da3ff473725..2b9d7fac1db 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."
@@ -38,10 +36,10 @@ If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
(car list))
(make-obsolete 'gnus-last-element "use `car' of `last' instead." "27.1")
-(define-obsolete-function-alias 'gnus-copy-sequence 'copy-tree "27.1")
+(define-obsolete-function-alias 'gnus-copy-sequence #'copy-tree "27.1")
-;;; We could be using `seq-difference' here, but it's much slower
-;;; on these data sets. See bug#50877.
+;; We could be using `seq-difference' here, but it's much slower
+;; on these data sets. See bug#50877.
(defun gnus-set-difference (list1 list2)
"Return a list of elements of LIST1 that do not appear in LIST2."
(let ((hash2 (make-hash-table :test 'eq))
@@ -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,60 +159,11 @@ 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)
+(defalias 'gnus-set-sorted-intersection #'gnus-sorted-nintersection)
;;;###autoload
(defun gnus-sorted-nintersection (list1 list2)
@@ -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)))))))
-
-(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)))
+ (if always-list
+ (range-compress-list numbers)
+ (range-denormalize (range-compress-list numbers))))
-(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)))
+(defalias 'gnus-uncompress-sequence #'gnus-uncompress-range)
+(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 #'range-list-difference)
+
+(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-registry.el b/lisp/gnus/gnus-registry.el
index 0c281a997f8..ceeb1848542 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -163,7 +163,9 @@ nnmairix groups are specifically excluded because they are ephemeral."
:type 'boolean
:version "28.1")
-(defvar gnus-registry-enabled nil)
+(make-obsolete-variable
+ 'gnus-registry-enabled
+ "Check for non-nil value of `gnus-registry-db'" "29.1")
(defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning.
@@ -355,8 +357,12 @@ This is not required after changing `gnus-registry-cache-file'."
"Load the registry from the cache file."
(interactive)
(let ((file gnus-registry-cache-file))
+ (gnus-message 5 "Initializing the registry")
(condition-case nil
- (gnus-registry-read file)
+ (progn
+ (gnus-registry-read file)
+ (gnus-registry-install-hooks)
+ (gnus-registry-install-shortcuts))
(file-error
;; Fix previous mis-naming of the registry file.
(let ((old-file-name
@@ -846,9 +852,9 @@ Overrides existing keywords with FORCE set non-nil."
(defun gnus-registry-register-message-ids ()
"Register the Message-ID of every article in the group."
- (unless (or (gnus-parameter-registry-ignore gnus-newsgroup-name)
- (null gnus-registry-register-all)
- (null (eieio-object-p gnus-registry-db)))
+ (unless (or (null gnus-registry-db)
+ (null gnus-registry-register-all)
+ (gnus-parameter-registry-ignore gnus-newsgroup-name))
(dolist (article gnus-newsgroup-articles)
(let* ((id (gnus-registry-fetch-message-id-fast article))
(groups (gnus-registry-get-id-key id 'group)))
@@ -949,13 +955,12 @@ FUNCTION should take two parameters, a mark symbol and the cell value."
(defun gnus-registry-install-shortcuts ()
"Install the keyboard shortcuts and menus for the registry.
Uses `gnus-registry-marks' to find what shortcuts to install."
- (let (keys-plist)
- (setq gnus-registry-misc-menus nil)
- (gnus-registry-do-marks
- :char
- (lambda (mark data)
- (let ((function-format
- (format "gnus-registry-%%s-article-%s-mark" mark)))
+ (setq gnus-registry-misc-menus nil)
+ (gnus-registry-do-marks
+ :char
+ (lambda (mark data)
+ (let ((function-format
+ (format "gnus-registry-%%s-article-%s-mark" mark)))
;;; The following generates these functions:
;;; (defun gnus-registry-set-article-Important-mark (&rest articles)
@@ -967,48 +972,43 @@ Uses `gnus-registry-marks' to find what shortcuts to install."
;;; (interactive (gnus-summary-work-articles current-prefix-arg))
;;; (gnus-registry-set-article-mark-internal 'Important articles t t))
- (dolist (remove '(t nil))
- (let* ((variant-name (if remove "remove" "set"))
- (function-name
- (intern (format function-format variant-name)))
- (shortcut (format "%c" (if remove (upcase data) data))))
- (defalias function-name
- (lambda (&rest articles)
- (:documentation
- (format
- "%s the %s mark over process-marked ARTICLES."
- (upcase-initials variant-name)
- mark))
- (interactive
- (gnus-summary-work-articles current-prefix-arg))
- (gnus-registry--set/remove-mark mark remove articles)))
- (push function-name keys-plist)
- (push shortcut keys-plist)
- (push (vector (format "%s %s"
- (upcase-initials variant-name)
- (symbol-name mark))
- function-name t)
- gnus-registry-misc-menus)
- (gnus-message 9 "Defined mark handling function %s"
- function-name))))))
- (define-key gnus-summary-mark-map "M"
- (apply #'define-keymap :prefix 'gnus-summary-mark-map
- keys-plist))
- (add-hook 'gnus-summary-menu-hook
- (lambda ()
- (easy-menu-add-item
- gnus-summary-misc-menu
- nil
- (cons "Registry Marks" gnus-registry-misc-menus))))))
-
-(define-obsolete-function-alias 'gnus-registry-user-format-function-M
- #'gnus-registry-article-marks-to-chars "24.1")
+ (dolist (remove '(t nil))
+ (let* ((variant-name (if remove "remove" "set"))
+ (function-name
+ (intern (format function-format variant-name)))
+ (shortcut (format "%c" (if remove (upcase data) data))))
+ (defalias function-name
+ (lambda (&rest articles)
+ (:documentation
+ (format
+ "%s the %s mark over process-marked ARTICLES."
+ (upcase-initials variant-name)
+ mark))
+ (interactive
+ (gnus-summary-work-articles current-prefix-arg))
+ (gnus-registry--set/remove-mark mark remove articles)))
+ (keymap-set gnus-summary-mark-map
+ (concat "M " shortcut)
+ function-name)
+ (push (vector (format "%s %s"
+ (upcase-initials variant-name)
+ (symbol-name mark))
+ function-name t)
+ gnus-registry-misc-menus)
+ (gnus-message 9 "Defined mark handling function %s"
+ function-name))))))
+ (add-hook 'gnus-summary-menu-hook
+ (lambda ()
+ (easy-menu-add-item
+ gnus-summary-misc-menu
+ nil
+ (cons "Registry Marks" gnus-registry-misc-menus)))))
;; use like this:
;; (defalias 'gnus-user-format-function-M #'gnus-registry-article-marks-to-chars)
(defun gnus-registry-article-marks-to-chars (headers)
"Show the marks for an article by the :char property."
- (if gnus-registry-enabled
+ (if gnus-registry-db
(let* ((id (mail-header-message-id headers))
(marks (when id (gnus-registry-get-id-key id 'mark))))
(concat (delq nil
@@ -1024,7 +1024,7 @@ Uses `gnus-registry-marks' to find what shortcuts to install."
;; (defalias 'gnus-user-format-function-M #'gnus-registry-article-marks-to-names)
(defun gnus-registry-article-marks-to-names (headers)
"Show the marks for an article by name."
- (if gnus-registry-enabled
+ (if gnus-registry-db
(let* ((id (mail-header-message-id headers))
(marks (when id (gnus-registry-get-id-key id 'mark))))
(mapconcat #'symbol-name marks ","))
@@ -1183,16 +1183,12 @@ non-nil."
(defun gnus-registry-initialize ()
"Initialize the Gnus registry."
(interactive)
- (gnus-message 5 "Initializing the registry")
- (gnus-registry-install-hooks)
- (gnus-registry-install-shortcuts)
(if (gnus-alive-p)
(gnus-registry-load)
(add-hook 'gnus-read-newsrc-el-hook #'gnus-registry-load)))
(defun gnus-registry-install-hooks ()
"Install the registry hooks."
- (setq gnus-registry-enabled t)
(add-hook 'gnus-summary-article-move-hook #'gnus-registry-action)
(add-hook 'gnus-summary-article-delete-hook #'gnus-registry-action)
(add-hook 'gnus-summary-article-expire-hook #'gnus-registry-action)
@@ -1212,17 +1208,16 @@ non-nil."
(remove-hook 'gnus-save-newsrc-hook #'gnus-registry-save)
(remove-hook 'gnus-read-newsrc-el-hook #'gnus-registry-load)
- (remove-hook 'gnus-summary-prepare-hook #'gnus-registry-register-message-ids)
- (setq gnus-registry-enabled nil))
+ (remove-hook 'gnus-summary-prepare-hook #'gnus-registry-register-message-ids))
-(add-hook 'gnus-registry-unload-hook #'gnus-registry-unload-hook)
+(add-hook 'gnus-registry-unload-hook #'gnus-registry-clear)
(defun gnus-registry-install-p ()
"Return non-nil if the registry is enabled (and maybe enable it first).
If the registry is not already enabled, then if `gnus-registry-install'
is `ask', ask the user; or if `gnus-registry-install' is non-nil, enable it."
(interactive)
- (unless gnus-registry-enabled
+ (unless gnus-registry-db
(when (if (eq gnus-registry-install 'ask)
(gnus-y-or-n-p
(concat "Enable the Gnus registry? "
@@ -1230,7 +1225,7 @@ is `ask', ask the user; or if `gnus-registry-install' is non-nil, enable it."
"to get rid of this query permanently. "))
gnus-registry-install)
(gnus-registry-initialize)))
- gnus-registry-enabled)
+ (null (null gnus-registry-db)))
;; largely based on nnselect-warp-to-article
(defun gnus-try-warping-via-registry ()
diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el
index 3189655c8ad..4ef2ebf1dd7 100644
--- a/lisp/gnus/gnus-salt.el
+++ b/lisp/gnus/gnus-salt.el
@@ -133,9 +133,7 @@ It accepts the same format specs that `gnus-summary-line-format' does."
(defun gnus-pick-start-reading (&optional catch-up)
"Start reading the picked articles.
If given a prefix, mark all unpicked articles as read."
- (interactive "P")
- (declare (completion (lambda (s b)
- (completion-minor-mode-active-p s b 'gnus-pick-mode))))
+ (interactive "P" gnus-pick-mode)
(if gnus-newsgroup-processable
(progn
(gnus-summary-limit-to-articles nil)
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index bf88abae76c..369df81d9bd 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -167,10 +167,9 @@ Instead, use this:
This variable can also be set per-server."
:type '(repeat string))
-(defcustom gnus-search-swish++-remove-prefix (concat (getenv "HOME") "/Mail/")
+(defcustom gnus-search-swish++-remove-prefix (expand-file-name "Mail/" "~")
"The prefix to remove from each file name returned by swish++
-in order to get a group name (albeit with / instead of .). This is a
-regular expression.
+in order to get a group name (albeit with / instead of .).
This variable can also be set per-server."
:type 'regexp)
@@ -204,10 +203,9 @@ This variable can also be set per-server."
:type '(repeat string)
:version "28.1")
-(defcustom gnus-search-swish-e-remove-prefix (concat (getenv "HOME") "/Mail/")
+(defcustom gnus-search-swish-e-remove-prefix (expand-file-name "Mail/" "~")
"The prefix to remove from each file name returned by swish-e
-in order to get a group name (albeit with / instead of .). This is a
-regular expression.
+in order to get a group name (albeit with / instead of .).
This variable can also be set per-server."
:type 'regexp
@@ -252,7 +250,7 @@ This variable can also be set per-server."
:type '(repeat string)
:version "28.1")
-(defcustom gnus-search-namazu-remove-prefix (concat (getenv "HOME") "/Mail/")
+(defcustom gnus-search-namazu-remove-prefix (expand-file-name "Mail/" "~")
"The prefix to remove from each file name returned by Namazu
in order to get a group name (albeit with / instead of .).
@@ -296,10 +294,9 @@ This variable can also be set per-server."
:type '(repeat string)
:version "28.1")
-(defcustom gnus-search-notmuch-remove-prefix (concat (getenv "HOME") "/Mail/")
+(defcustom gnus-search-notmuch-remove-prefix (expand-file-name "Mail/" "~")
"The prefix to remove from each file name returned by notmuch
-in order to get a group name (albeit with / instead of .). This is a
-regular expression.
+in order to get a group name (albeit with / instead of .).
This variable can also be set per-server."
:type 'regexp
@@ -339,10 +336,9 @@ This variable can also be set per-server."
:version "28.1"
:type '(repeat string))
-(defcustom gnus-search-mairix-remove-prefix (concat (getenv "HOME") "/Mail/")
+(defcustom gnus-search-mairix-remove-prefix (expand-file-name "Mail/" "~")
"The prefix to remove from each file name returned by mairix
-in order to get a group name (albeit with / instead of .). This is a
-regular expression.
+in order to get a group name (albeit with / instead of .).
This variable can also be set per-server."
:version "28.1"
@@ -353,6 +349,41 @@ This variable can also be set per-server."
:version "28.1"
:type 'boolean)
+(defcustom gnus-search-mu-program "mu"
+ "Name of the mu search executable.
+This can also be set per-server."
+ :version "29.1"
+ :type 'string)
+
+(defcustom gnus-search-mu-switches nil
+ "A list of strings, to be given as additional arguments to mu.
+Note that this should be a list. I.e., do NOT use the following:
+ (setq gnus-search-mu-switches \"-u -r\")
+Instead, use this:
+ (setq gnus-search-mu-switches \\='(\"-u\" \"-r\"))
+This can also be set per-server."
+ :version "29.1"
+ :type '(repeat string))
+
+(defcustom gnus-search-mu-remove-prefix (expand-file-name "~/Mail/")
+ "A prefix to remove from the mu results to get a group name.
+Usually this will be set to the path to your mail directory. This
+can also be set per-server."
+ :version "29.1"
+ :type 'directory)
+
+(defcustom gnus-search-mu-config-directory (expand-file-name "~/.cache/mu")
+ "Configuration directory for mu.
+This can also be set per-server."
+ :version "29.1"
+ :type 'file)
+
+(defcustom gnus-search-mu-raw-queries-p nil
+ "If t, all mu engines will only accept raw search query strings.
+This can also be set per-server."
+ :version "29.1"
+ :type 'boolean)
+
;; Options for search language parsing.
(defcustom gnus-search-expandable-keys
@@ -762,6 +793,9 @@ the files in ARTLIST by that search key.")
(generate-new-buffer " *gnus-search-")))
(cl-call-next-method engine slots))
+(defclass gnus-search-nnselect (gnus-search-engine)
+ nil)
+
(defclass gnus-search-imap (gnus-search-engine)
((literal-plus
:initarg :literal-plus
@@ -823,7 +857,7 @@ quirks.")
:documentation "Location of the config file, if any.")
(remove-prefix
:initarg :remove-prefix
- :initform (concat (getenv "HOME") "/Mail/")
+ :initform (expand-file-name "Mail/" "~")
:type string
:documentation
"The path to the directory where the indexed mails are
@@ -904,16 +938,30 @@ quirks.")
(raw-queries-p
:initform (symbol-value 'gnus-search-notmuch-raw-queries-p))))
+(defclass gnus-search-mu (gnus-search-indexed)
+ ((program
+ :initform (symbol-value 'gnus-search-mu-program))
+ (remove-prefix
+ :initform (symbol-value 'gnus-search-mu-remove-prefix))
+ (switches
+ :initform (symbol-value 'gnus-search-mu-switches))
+ (config-directory
+ :initform (symbol-value 'gnus-search-mu-config-directory))
+ (raw-queries-p
+ :initform (symbol-value 'gnus-search-mu-raw-queries-p))))
+
(define-obsolete-variable-alias 'nnir-method-default-engines
'gnus-search-default-engines "28.1")
-(defcustom gnus-search-default-engines '((nnimap . gnus-search-imap))
+(defcustom gnus-search-default-engines '((nnimap . gnus-search-imap)
+ (nnselect . gnus-search-nnselect))
"Alist of default search engines keyed by server method."
:version "26.1"
:type `(repeat (cons (choice (const nnimap) (const nntp) (const nnspool)
(const nneething) (const nndir) (const nnmbox)
(const nnml) (const nnmh) (const nndraft)
- (const nnfolder) (const nnmaildir))
+ (const nnfolder) (const nnmaildir)
+ (const nnselect))
(choice
,@(mapcar
(lambda (el) (list 'const (intern (car el))))
@@ -1010,6 +1058,33 @@ Responsible for handling and, or, and parenthetical expressions.")
unseen all old new or not)
"Known IMAP search keys.")
+(autoload 'nnselect-categorize "nnselect")
+(autoload 'nnselect-get-artlist "nnselect" nil nil 'macro)
+(autoload 'ids-by-group "nnselect")
+;; nnselect interface
+(cl-defmethod gnus-search-run-search ((_engine gnus-search-nnselect)
+ _srv query-spec groups)
+ (let ((artlist []))
+ (dolist (group groups)
+ (let* ((gnus-newsgroup-selection (nnselect-get-artlist group))
+ (group-spec
+ (nnselect-categorize
+ (mapcar 'car
+ (ids-by-group
+ (number-sequence 1
+ (length gnus-newsgroup-selection))))
+ (lambda (x)
+ (gnus-group-server x)))))
+ (setq artlist
+ (vconcat artlist
+ (seq-intersection
+ gnus-newsgroup-selection
+ (gnus-search-run-query
+ (list (cons 'search-query-spec query-spec)
+ (cons 'search-group-spec group-spec))))))))
+ artlist))
+
+
;; imap interface
(cl-defmethod gnus-search-run-search ((engine gnus-search-imap)
srv query groups)
@@ -1262,7 +1337,11 @@ elements are present."
(cl-defmethod gnus-search-imap-handle-string ((engine gnus-search-imap)
(str string))
(with-slots (literal-plus) engine
- (if (multibyte-string-p str)
+ ;; TODO: Figure out how Exchange IMAP servers actually work. They
+ ;; do not accept any CHARSET but US-ASCII, but they do report
+ ;; Literal+ capability. So what do we do? Will quoted strings
+ ;; always work?
+ (if (string-match-p "[^[:ascii:]]" str)
;; If LITERAL+ is available, use it and encode string as
;; UTF-8.
(if literal-plus
@@ -1318,16 +1397,14 @@ This method is common to all indexed search engines.
Returns a list of [group article score] vectors."
- (save-excursion
- (let* ((qstring (gnus-search-make-query-string engine query))
- (program (slot-value engine 'program))
- (buffer (slot-value engine 'proc-buffer))
- (cp-list (gnus-search-indexed-search-command
- engine qstring query groups))
- proc exitstatus)
- (set-buffer buffer)
+ (let* ((qstring (gnus-search-make-query-string engine query))
+ (program (slot-value engine 'program))
+ (buffer (slot-value engine 'proc-buffer))
+ (cp-list (gnus-search-indexed-search-command
+ engine qstring query groups))
+ proc exitstatus)
+ (with-current-buffer buffer
(erase-buffer)
-
(if groups
(gnus-message 7 "Doing %s query on %s..." program groups)
(gnus-message 7 "Doing %s query..." program))
@@ -1346,7 +1423,7 @@ Returns a list of [group article score] vectors."
;; wants it.
(when (> gnus-verbose 6)
(display-buffer buffer))
- nil))))
+ nil))))
(cl-defmethod gnus-search-indexed-parse-output ((engine gnus-search-indexed)
server query &optional groups)
@@ -1367,18 +1444,27 @@ Returns a list of [group article score] vectors."
(when (and f-name
(file-readable-p f-name)
(null (file-directory-p f-name)))
- (setq group
- (replace-regexp-in-string
- "[/\\]" "."
- (replace-regexp-in-string
- "/?\\(cur\\|new\\|tmp\\)?/\\'" ""
+ ;; `expand-file-name' canoncalizes the file name,
+ ;; specifically collapsing multiple consecutive directory
+ ;; separators.
+ (setq f-name (expand-file-name f-name)
+ group
+ (delete
+ "" ; forward slash at root leaves an empty string
+ (file-name-split
(replace-regexp-in-string
- "\\`\\." ""
- (string-remove-prefix
+ "\\`\\." "" ; why do we do this?
+ (string-remove-prefix
prefix (file-name-directory f-name))
- nil t)
- nil t)
- nil t))
+ nil t)))
+ ;; Turn file name segments into a Gnus group name.
+ group (mapconcat
+ #'identity
+ (if (member (car (last group))
+ '("new" "tmp" "cur"))
+ (nbutlast group)
+ group)
+ "."))
(setq article (file-name-nondirectory f-name)
article
;; TODO: Provide a cleaner way of producing final
@@ -1600,19 +1686,26 @@ Namazu provides a little more information, for instance a score."
(cp-list (gnus-search-indexed-search-command
engine qstring query groups))
thread-ids proc)
- (set-buffer proc-buffer)
- (erase-buffer)
- (setq proc (apply #'start-process (format "search-%s" server)
- proc-buffer program cp-list))
- (while (process-live-p proc)
- (accept-process-output proc))
- (while (re-search-forward "^thread:\\([^ ]+\\)" (point-max) t)
- (push (match-string 1) thread-ids))
+ (with-current-buffer proc-buffer
+ (erase-buffer)
+ (setq proc (apply #'start-process (format "search-%s" server)
+ proc-buffer program cp-list))
+ (while (process-live-p proc)
+ (accept-process-output proc))
+ (goto-char (point-min))
+ (while (re-search-forward
+ "^thread:\\([^[:space:]\n]+\\)"
+ (point-max) t)
+ (cl-pushnew (match-string 1) thread-ids :test #'equal)))
(cl-call-next-method
engine server
- ;; Completely replace the query with our new thread-based one.
- (mapconcat (lambda (thrd) (concat "thread:" thrd))
- thread-ids " or ")
+ ;; If we found threads, completely replace the query with
+ ;; our new thread-based one.
+ (if thread-ids
+ `((query . ,(mapconcat (lambda (thrd)
+ (concat "thread:" thrd))
+ thread-ids " or ")))
+ query)
nil)))
(cl-call-next-method engine server query groups)))
@@ -1625,16 +1718,16 @@ Namazu provides a little more information, for instance a score."
(let ((limit (alist-get 'limit query))
(thread (alist-get 'thread query)))
(with-slots (switches config-file) engine
- `(,(format "--config=%s" config-file)
- "search"
- ,(if thread
- "--output=threads"
- "--output=files")
- "--duplicate=1" ; I have found this necessary, I don't know why.
- ,@switches
- ,(if limit (format "--limit=%d" limit) "")
- ,qstring
- ))))
+ (append
+ (list (format "--config=%s" config-file)
+ "search"
+ (if thread
+ "--output=threads"
+ "--output=files"))
+ (unless thread '("--duplicate=1"))
+ (when limit (list (format "--limit=%d" limit)))
+ switches
+ (list qstring)))))
;;; Mairix interface
@@ -1807,6 +1900,101 @@ Assume \"size\" key is equal to \"larger\"."
(when (alist-get 'thread query) (list "-t"))
(list qstring))))
+;;; Mu interface
+
+(cl-defmethod gnus-search-transform-expression ((engine gnus-search-mu)
+ (expr list))
+ (cl-case (car expr)
+ (recipient (setf (car expr) 'recip))
+ (address (setf (car expr) 'contact))
+ (id (setf (car expr) 'msgid))
+ (attachment (setf (car expr) 'file)))
+ (cl-flet ()
+ (cond
+ ((consp (car expr))
+ (format "(%s)" (gnus-search-transform engine expr)))
+ ;; Explicitly leave out 'date as gnus-search will encode it
+ ;; first; it is handled later
+ ((memq (car expr) '(cc c bcc h from f to t subject s body b
+ maildir m msgid i prio p flag g d
+ size z embed e file j mime y tag x
+ list v))
+ (format "%s:%s" (car expr)
+ (if (string-match "\\`\\*" (cdr expr))
+ (replace-match "" nil nil (cdr expr))
+ (cdr expr))))
+ ((eq (car expr) 'mark)
+ (format "flag:%s" (gnus-search-mu-handle-flag (cdr expr))))
+ ((eq (car expr) 'date)
+ (format "date:%s" (gnus-search-mu-handle-date (cdr expr))))
+ ((eq (car expr) 'before)
+ (format "date:..%s" (gnus-search-mu-handle-date (cdr expr))))
+ ((eq (car expr) 'since)
+ (format "date:%s.." (gnus-search-mu-handle-date (cdr expr))))
+ (t (ignore-errors (cl-call-next-method))))))
+
+(defun gnus-search-mu-handle-date (date)
+ (if (stringp date)
+ date
+ (pcase date
+ (`(nil ,m nil)
+ (nth (1- m) gnus-english-month-names))
+ (`(nil nil ,y)
+ (number-to-string y))
+ ;; mu prefers ISO date YYYY-MM-DD HH:MM:SS
+ (`(,d ,m nil)
+ (let* ((ct (decode-time))
+ (cm (decoded-time-month ct))
+ (cy (decoded-time-year ct))
+ (y (if (> cm m)
+ cy
+ (1- cy))))
+ (format "%d-%02d-%02d" y m d)))
+ (`(nil ,m ,y)
+ (format "%d-%02d" y m))
+ (`(,d ,m ,y)
+ (format "%d-%02d-%02d" y m d)))))
+
+(defun gnus-search-mu-handle-flag (flag)
+ ;; Only change what doesn't match
+ (cond ((string= flag "flag")
+ "flagged")
+ ((string= flag "read")
+ "seen")
+ (t
+ flag)))
+
+(cl-defmethod gnus-search-indexed-extract ((_engine gnus-search-mu))
+ (prog1
+ (let ((bol (line-beginning-position))
+ (eol (line-end-position)))
+ (list (buffer-substring-no-properties bol eol)
+ 100))
+ (move-beginning-of-line 2)))
+
+(cl-defmethod gnus-search-indexed-search-command ((engine gnus-search-mu)
+ (qstring string)
+ query &optional groups)
+ (let ((limit (alist-get 'limit query))
+ (thread (alist-get 'thread query)))
+ (with-slots (switches config-directory) engine
+ `("find" ; command must come first
+ "--nocolor" ; mu will always give coloured output otherwise
+ ,(format "--muhome=%s" config-directory)
+ ,@switches
+ ,(if thread "-r" "")
+ ,(if limit (format "--maxnum=%d" limit) "")
+ ,qstring
+ ,@(if groups
+ `("and" "("
+ ,@(nbutlast (mapcan (lambda (x)
+ (list (concat "maildir:/" x) "or"))
+ groups))
+ ")")
+ "")
+ "--format=plain"
+ "--fields=l"))))
+
;;; Find-grep interface
(cl-defmethod gnus-search-transform-expression ((_engine gnus-search-find-grep)
@@ -1941,9 +2129,9 @@ Assume \"size\" key is equal to \"larger\"."
(defun gnus-search-prepare-query (query-spec)
"Accept a search query in raw format, and prepare it.
QUERY-SPEC is an alist produced by functions such as
-`gnus-group-make-search-group', and contains at least a 'query
+`gnus-group-make-search-group', and contains at least a `query'
key, and possibly some meta keys. This function extracts any
-additional meta keys from the 'query string, and parses the
+additional meta keys from the `query' string, and parses the
remaining string, then adds all that to the top-level spec."
(let ((query (alist-get 'query query-spec))
val)
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 252e6e22299..7b5721fafbb 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -329,10 +329,10 @@ with the subscription method in this variable."
"If non-nil, Gnus will offer to subscribe hierarchically.
When a new hierarchy appears, Gnus will ask the user:
-'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
+Descend hierarchy alt.binaries? ([y]nsq):
-If the user pressed `d', Gnus will descend the hierarchy, `y' will
-subscribe to all newsgroups in the hierarchy and `s' will skip this
+If the user pressed `y', Gnus will descend the hierarchy, `s' will
+subscribe to all newsgroups in the hierarchy and `n' will skip this
hierarchy in its entirety."
:group 'gnus-group-new
:type 'boolean)
@@ -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))
@@ -2869,12 +2867,6 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'."
(princ "(setq gnus-newsrc-file-version ")
(princ (gnus-prin1-to-string gnus-version))
(princ ")\n"))
- ;; Sort `gnus-newsrc-alist' according to order in
- ;; `gnus-group-list'.
- (setq gnus-newsrc-alist
- (mapcar (lambda (g)
- (nth 1 (gethash g gnus-newsrc-hashtb)))
- (delete "dummy.group" gnus-group-list)))
(let* ((print-quoted t)
(print-escape-multibyte nil)
(print-escape-nonascii t)
@@ -2893,17 +2885,20 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'."
;; Remove the `gnus-killed-list' from the list of variables
;; to be saved, if required.
(delq 'gnus-killed-list (copy-sequence gnus-variable-list)))))
- ;; Encode group names in `gnus-newsrc-alist' and
- ;; `gnus-topic-alist' in order to keep newsrc.eld files
- ;; compatible with older versions of Gnus. At some point,
- ;; if/when a new version of Gnus is released, stop doing
- ;; this and move the corresponding decode in
- ;; `gnus-read-newsrc-el-file' into a conversion routine.
+ ;; Sort `gnus-newsrc-alist' according to order in
+ ;; `gnus-group-list'. Encode group names in
+ ;; `gnus-newsrc-alist' and `gnus-topic-alist' in order to
+ ;; keep newsrc.eld files compatible with older versions of
+ ;; Gnus. At some point, if/when a new version of Gnus is
+ ;; released, stop doing this and move the corresponding
+ ;; decode in `gnus-read-newsrc-el-file' into a conversion
+ ;; routine.
(gnus-newsrc-alist
- (mapcar (lambda (info)
- (cons (encode-coding-string (car info) 'utf-8-emacs)
- (cdr info)))
- gnus-newsrc-alist))
+ (mapcar (lambda (group)
+ (cons (encode-coding-string group 'utf-8-emacs)
+ (cdadr (gethash group
+ gnus-newsrc-hashtb))))
+ (remove "dummy.group" gnus-group-list)))
(gnus-topic-alist
(when (memq 'gnus-topic-alist variables)
(mapcar (lambda (elt)
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index d3e476b5d64..7f96e16c8ae 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -97,7 +97,7 @@ See `gnus-group-goto-unread'."
:type 'boolean)
(defcustom gnus-summary-stop-at-end-of-message nil
- "If non-nil, don't select the next message when using `SPC'."
+ "If non-nil, don't select the next message when using \\`SPC'."
:link '(custom-manual "(gnus)Group Maneuvering")
:group 'gnus-summary-maneuvering
:version "24.1"
@@ -264,8 +264,8 @@ This variable will only be used if the value of
(defcustom gnus-summary-goto-unread nil
"If t, many commands will go to the next unread article.
This applies to marking commands as well as other commands that
-\"naturally\" select the next article, like, for instance, `SPC' at
-the end of an article.
+\"naturally\" select the next article, like, for instance, \\`SPC'
+at the end of an article.
If nil, the marking commands do NOT go to the next unread article
\(they go to the next article instead). If `never', commands that
@@ -2887,45 +2887,11 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs))))
(defvar gnus-summary-tool-bar-map nil)
-;; Note: The :set function in the `gnus-summary-tool-bar*' variables will only
-;; affect _new_ message buffers. We might add a function that walks thru all
-;; summary-mode buffers and force the update.
-(defun gnus-summary-tool-bar-update (&optional symbol value)
- "Update summary mode toolbar.
-Setter function for custom variables."
- (setq-default gnus-summary-tool-bar-map nil)
- (when symbol
- ;; When used as ":set" function:
- (set-default symbol value))
- (when (gnus-buffer-live-p gnus-summary-buffer)
- (with-current-buffer gnus-summary-buffer
- (gnus-summary-make-tool-bar))))
-
-(defcustom gnus-summary-tool-bar (if (eq gmm-tool-bar-style 'gnome)
- 'gnus-summary-tool-bar-gnome
- 'gnus-summary-tool-bar-retro)
- "Specifies the Gnus summary tool bar.
-
-It can be either a list or a symbol referring to a list. See
-`gmm-tool-bar-from-list' for the format of the list. The
-default key map is `gnus-summary-mode-map'.
-
-Pre-defined symbols include `gnus-summary-tool-bar-gnome' and
-`gnus-summary-tool-bar-retro'."
- :type '(choice (const :tag "GNOME style" gnus-summary-tool-bar-gnome)
- (const :tag "Retro look" gnus-summary-tool-bar-retro)
- (repeat :tag "User defined list" gmm-tool-bar-item)
- (symbol))
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-summary-tool-bar-update
- :group 'gnus-summary)
-
-(defcustom gnus-summary-tool-bar-gnome
+(defcustom gnus-summary-tool-bar
'((gnus-summary-post-news "mail/compose" nil)
- (gnus-summary-insert-new-articles "mail/inbox" nil
- :visible (or (not gnus-agent)
- gnus-plugged))
+ (gnus-summary-insert-new-articles
+ "mail/inbox" nil
+ :visible (or (not gnus-agent) gnus-plugged))
(gnus-summary-reply-with-original "mail/reply")
(gnus-summary-reply "mail/reply" nil :visible nil)
(gnus-summary-followup-with-original "mail/reply-all")
@@ -2935,17 +2901,10 @@ Pre-defined symbols include `gnus-summary-tool-bar-gnome' and
(gnus-summary-search-article-forward "search" nil :visible nil)
(gnus-summary-print-article "print")
(gnus-summary-tick-article-forward "flag-followup" nil :visible nil)
- ;; Some new commands that may need more suitable icons:
(gnus-summary-save-newsrc "save" nil :visible nil)
- ;; (gnus-summary-show-article "stock_message-display" nil :visible nil)
(gnus-summary-prev-article "left-arrow")
(gnus-summary-next-article "right-arrow")
(gnus-summary-next-page "next-page")
- ;; (gnus-summary-enter-digest-group "right_arrow" nil :visible nil)
- ;;
- ;; Maybe some sort-by-... could be added:
- ;; (gnus-summary-sort-by-author "sort-a-z" nil :visible nil)
- ;; (gnus-summary-sort-by-date "sort-1-9" nil :visible nil)
(gnus-summary-mark-as-expirable
"delete" nil
:visible (gnus-check-backend-function 'request-expire-articles
@@ -2959,64 +2918,25 @@ Pre-defined symbols include `gnus-summary-tool-bar-gnome' and
"mail/not-spam" nil
:visible (and (fboundp 'spam-group-spam-contents-p)
(spam-group-spam-contents-p gnus-newsgroup-name)))
- ;;
(gnus-summary-exit "exit")
(gmm-customize-mode "preferences" t :help "Edit mode preferences")
(gnus-info-find-node "help"))
- "List of functions for the summary tool bar (GNOME style).
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-summary-tool-bar-update
- :group 'gnus-summary)
+ "Specifies the Gnus summary tool bar.
-(defcustom gnus-summary-tool-bar-retro
- '((gnus-summary-prev-unread-article "gnus/prev-ur")
- (gnus-summary-next-unread-article "gnus/next-ur")
- (gnus-summary-post-news "gnus/post")
- (gnus-summary-followup-with-original "gnus/fuwo")
- (gnus-summary-followup "gnus/followup")
- (gnus-summary-reply-with-original "gnus/reply-wo")
- (gnus-summary-reply "gnus/reply")
- (gnus-summary-caesar-message "gnus/rot13")
- (gnus-uu-decode-uu "gnus/uu-decode")
- (gnus-summary-save-article-file "gnus/save-aif")
- (gnus-summary-save-article "gnus/save-art")
- (gnus-uu-post-news "gnus/uu-post")
- (gnus-summary-catchup "gnus/catchup")
- (gnus-summary-catchup-and-exit "gnus/cu-exit")
- (gnus-summary-exit "gnus/exit-summ")
- ;; Some new command that may need more suitable icons:
- (gnus-summary-print-article "gnus/print" nil :visible nil)
- (gnus-summary-mark-as-expirable "gnus/close" nil :visible nil)
- (gnus-summary-save-newsrc "gnus/save" nil :visible nil)
- ;; (gnus-summary-enter-digest-group "gnus/right_arrow" nil :visible nil)
- (gnus-summary-search-article-forward "gnus/search" nil :visible nil)
- ;; (gnus-summary-insert-new-articles "gnus/paste" nil :visible nil)
- ;; (gnus-summary-toggle-threads "gnus/open" nil :visible nil)
- ;;
- (gnus-info-find-node "gnus/help" nil :visible nil))
- "List of functions for the summary tool bar (retro look).
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-summary-tool-bar-update
+It can be either a list or a symbol referring to a list. See
+`gmm-tool-bar-from-list' for the format of the list. The
+default key map is `gnus-summary-mode-map'."
+ :type '(choice (repeat :tag "User defined list" gmm-tool-bar-item)
+ (symbol))
+ :version "29.1"
:group 'gnus-summary)
-(defcustom gnus-summary-tool-bar-zap-list t
- "List of icon items from the global tool bar.
-These items are not displayed in the Gnus summary mode tool bar.
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type 'gmm-tool-bar-zap-list
- :version "23.1" ;; No Gnus
- :initialize 'custom-initialize-default
- :set 'gnus-summary-tool-bar-update
- :group 'gnus-summary)
+(defvar gnus-summary-tool-bar-gnome nil)
+(make-obsolete-variable 'gnus-summary-tool-bar-gnome nil "29.1")
+(defvar gnus-summary-tool-bar-retro nil)
+(make-obsolete-variable 'gnus-summary-tool-bar-retro nil "29.1")
+(defvar gnus-summary-tool-bar-zap-list t)
+(make-obsolete-variable 'gnus-summary-tool-bar-zap-list nil "29.1")
(defvar image-load-path)
(defvar tool-bar-map)
@@ -5755,7 +5675,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 +5848,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 +5863,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 +5960,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 +5998,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 +6097,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 +6109,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 +6305,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 +6886,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 +7048,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)
@@ -8665,7 +8583,7 @@ these articles."
(when matching-subject
(gnus-summary-limit-include-matching-articles
"subject"
- matching-subject)
+ (regexp-quote matching-subject))
;; Each of the previous two limit calls push a limit onto
;; the limit stack. Presumably we want to think of the
;; thread and its associated subject matches as a single
@@ -9447,6 +9365,16 @@ The 1st element is the button named by `gnus-collect-urls-primary-text'."
(push primary urls))
(delete-dups urls)))
+(defun gnus-collect-urls-from-article ()
+ "Select the article and return the list of URLs in it.
+See `gnus-collect-urls'."
+ (gnus-summary-select-article)
+ (gnus-with-article-buffer
+ (article-goto-body)
+ ;; Back up a char, in case body starts with a button.
+ (backward-char)
+ (gnus-collect-urls)))
+
(defun gnus-shorten-url (url max)
"Return an excerpt from URL not exceeding MAX characters."
(if (<= (length url) max)
@@ -9462,33 +9390,27 @@ The 1st element is the button named by `gnus-collect-urls-primary-text'."
"Scan the current article body for links, and offer to browse them.
Links are opened using `browse-url' unless a prefix argument is
-given: Then `browse-url-secondary-browser-function' is used instead.
+given: then `browse-url-secondary-browser-function' is used instead.
If only one link is found, browse that directly, otherwise use
completion to select a link. The first link marked in the
article text with `gnus-collect-urls-primary-text' is the
default."
(interactive "P" gnus-summary-mode)
- (let (urls target)
- (gnus-summary-select-article)
- (gnus-with-article-buffer
- (article-goto-body)
- ;; Back up a char, in case body starts with a button.
- (backward-char)
- (setq urls (gnus-collect-urls))
- (setq target
- (cond ((= (length urls) 1)
- (car urls))
- ((> (length urls) 1)
- (completing-read
- (format-prompt "URL to browse"
- (gnus-shorten-url (car urls) 40))
- urls nil t nil nil (car urls)))))
- (if target
- (if external
- (funcall browse-url-secondary-browser-function target)
- (browse-url target))
- (message "No URLs found.")))))
+ (let* ((urls (gnus-collect-urls-from-article))
+ (target
+ (cond ((= (length urls) 1)
+ (car urls))
+ ((> (length urls) 1)
+ (completing-read
+ (format-prompt "URL to browse"
+ (gnus-shorten-url (car urls) 40))
+ urls nil t nil nil (car urls))))))
+ (if target
+ (if external
+ (funcall browse-url-secondary-browser-function target)
+ (browse-url target))
+ (message "No URLs found."))))
(defun gnus-summary-isearch-article (&optional regexp-p)
"Do incremental search forward on the current article.
@@ -10241,8 +10163,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 +10447,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
@@ -11898,7 +11820,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 +11835,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)))
@@ -12871,8 +12796,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))
@@ -13130,10 +13055,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)
@@ -13150,9 +13075,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))
@@ -13187,7 +13112,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)
@@ -13277,6 +13202,8 @@ BOOKMARK is a bookmark name or a bookmark record."
(buffer . ,(current-buffer))
. ,(bookmark-get-bookmark-record bookmark)))))
+(put 'gnus-summary-bookmark-jump 'bookmark-handler-type "Gnus")
+
(gnus-summary-make-all-marking-commands)
(provide 'gnus-sum)
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index c079d889d98..fa942bee8e8 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -650,6 +650,7 @@ articles in the topic and its subtopics."
(let* ((visible (if visiblep "" "..."))
(level level)
(name name)
+ (entries entries)
(indentation (make-string (* gnus-topic-indent-level level) ? ))
(total-number-of-articles unread)
(number-of-groups (length entries))
@@ -677,7 +678,7 @@ articles in the topic and its subtopics."
(defun gnus-topic-update-topics-containing-group (group)
"Update all topics that have GROUP as a member."
- (when (and (eq major-mode 'gnus-topic-mode)
+ (when (and (derived-mode-p 'gnus-group-mode)
gnus-topic-mode)
(save-excursion
(let ((alist gnus-topic-alist))
@@ -693,7 +694,7 @@ articles in the topic and its subtopics."
(defun gnus-topic-update-topic ()
"Update all parent topics to the current group."
- (when (and (eq major-mode 'gnus-topic-mode)
+ (when (and (derived-mode-p 'gnus-group-mode)
gnus-topic-mode)
(let ((group (gnus-group-group-name))
(m (point-marker))
@@ -747,8 +748,8 @@ articles in the topic and its subtopics."
(car type) (car gnus-group-list-mode)
(cdr gnus-group-list-mode)))
(all-groups (gnus-topic-find-groups
- (car type) (car gnus-group-list-mode)
- (cdr gnus-group-list-mode) nil t))
+ (car type) (car gnus-group-list-mode)
+ (cdr gnus-group-list-mode) nil t))
entry)
(while children
(cl-incf unread (gnus-topic-unread (caar (pop children)))))
@@ -787,8 +788,8 @@ articles in the topic and its subtopics."
(car type) (car gnus-group-list-mode)
(cdr gnus-group-list-mode)))
(all-groups (gnus-topic-find-groups
- (car type) (car gnus-group-list-mode)
- (cdr gnus-group-list-mode) t))
+ (car type) (car gnus-group-list-mode)
+ (cdr gnus-group-list-mode) nil t))
(parent (gnus-topic-parent-topic topic-name))
(all-entries entries)
(unread 0)
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 6150781fecc..218a4d242b2 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -562,7 +562,7 @@ If N, return the Nth ancestor instead."
buffer))
(define-obsolete-function-alias 'gnus-buffer-exists-p
- 'gnus-buffer-live-p "27.1")
+ #'gnus-buffer-live-p "27.1")
(defun gnus-horizontal-recenter ()
"Recenter the current buffer horizontally."
@@ -680,7 +680,7 @@ yield \"nnimap:yxa\"."
(defun gnus-turn-off-edit-menu (type)
"Turn off edit menu in `gnus-TYPE-mode-map'."
(define-key (symbol-value (intern (format "gnus-%s-mode-map" type)))
- [menu-bar edit] 'undefined))
+ [menu-bar edit] #'undefined))
(defvar print-string-length)
@@ -954,9 +954,9 @@ ARG is passed to the first function."
(with-current-buffer gnus-group-buffer
(eq major-mode 'gnus-group-mode))))
-(define-obsolete-function-alias 'gnus-remove-if 'seq-remove "27.1")
+(define-obsolete-function-alias 'gnus-remove-if #'seq-remove "27.1")
-(define-obsolete-function-alias 'gnus-remove-if-not 'seq-filter "27.1")
+(define-obsolete-function-alias 'gnus-remove-if-not #'seq-filter "27.1")
(defun gnus-grep-in-list (word list)
"Find if a WORD matches any regular expression in the given LIST."
@@ -1091,9 +1091,10 @@ ARG is passed to the first function."
(defun gnus-byte-compile (form)
"Byte-compile FORM if `gnus-use-byte-compile' is non-nil."
(if gnus-use-byte-compile
- (let ((byte-compile-warnings '(unresolved callargs redefine)))
+ (let ((byte-compile-warnings '(unresolved callargs redefine))
+ (lexical-binding t))
(byte-compile form))
- form))
+ (eval form t)))
(defun gnus-remassoc (key alist)
"Delete by side effect any elements of LIST whose car is `equal' to KEY.
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 0daecf7df54..7eea08f1744 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -662,12 +662,11 @@ be used directly.")
(gnus-prune-buffers)
(cl-pushnew (current-buffer) gnus-buffers))
-(defmacro gnus-kill-buffer (buffer)
+(defun gnus-kill-buffer (buffer)
"Kill BUFFER and remove from the list of Gnus buffers."
- `(let ((buf ,buffer))
- (when (gnus-buffer-live-p buf)
- (kill-buffer buf)
- (gnus-prune-buffers))))
+ (when (gnus-buffer-live-p buffer)
+ (kill-buffer buffer)
+ (gnus-prune-buffers)))
(defun gnus-buffers ()
"Return a list of live Gnus buffers."
@@ -1131,16 +1130,6 @@ you could set this variable:
:group 'gnus-server
:type '(repeat gnus-select-method))
-(defcustom gnus-local-domain nil
- "Local domain name without a host name.
-The DOMAINNAME environment variable is used instead if it is defined.
-If the function `system-name' returns the full Internet name, there is
-no need to set this variable."
- :group 'gnus-message
- :type '(choice (const :tag "default" nil)
- string))
-(make-obsolete-variable 'gnus-local-domain nil "24.1")
-
;; Customization variables
(defcustom gnus-refer-article-method 'current
@@ -1592,7 +1581,7 @@ posting an article."
"Alist of group regexps and its initial input of the number of articles."
:variable-group gnus-group-parameter
:parameter-type '(choice :tag "Initial Input for Large Newsgroup"
- (const :tag "All" 'all)
+ (const :tag "All" all)
(integer))
:parameter-document "\
@@ -2264,12 +2253,12 @@ a string, be sure to use a valid format, see RFC 2616."
:version "22.1"
:group 'gnus-message
:type '(choice (list (set :inline t
- (const gnus :tag "Gnus version")
- (const emacs :tag "Emacs version")
+ (const :value gnus :tag "Gnus version")
+ (const :value emacs :tag "Emacs version")
(choice :tag "system"
- (const type :tag "system type")
- (const config :tag "system configuration"))
- (const codename :tag "Emacs codename")))
+ (const :value type :tag "system type")
+ (const :value config :tag "system configuration"))
+ (const :value codename :tag "Emacs codename")))
(string)))
;; Convert old (< 2005-01-10) symbol type values:
@@ -2317,11 +2306,6 @@ automatically cache the article in the agent cache."
(defvar gnus-server-method-cache nil)
(defvar gnus-extended-servers nil)
-;; The carpal mode has been removed, but define the variable for
-;; backwards compatibility.
-(defvar gnus-carpal nil)
-(make-obsolete-variable 'gnus-carpal nil "24.1")
-
(defvar gnus-agent-fetching nil
"Whether Gnus agent is in fetching mode.")
@@ -2529,7 +2513,8 @@ are always t.")
("nnmail" nnmail-split-fancy nnmail-article-group)
("nnvirtual" nnvirtual-catchup-group nnvirtual-convert-headers)
("gnus-xmas" gnus-xmas-splash)
- ("score-mode" :interactive t gnus-score-mode gnus-score-edit-all-score)
+ ("score-mode" :interactive t gnus-score-mode)
+ ("gnus-score" :interactive t gnus-score-edit-all-score)
("gnus-mh" gnus-summary-save-article-folder
gnus-Folder-save-name gnus-folder-save-name)
("gnus-mh" :interactive (gnus-summary-mode) gnus-summary-save-in-folder)
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index d2f5b9a97e2..320bc9c3b0e 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)
@@ -412,7 +413,7 @@ the `mail-source-keyword-map' variable."
(let* ((type (pop source))
(defaults (cdr (assq type mail-source-keyword-map)))
(search '(:max 1))
- found default value keyword user-auth pass-auth) ;; auth-info
+ found default keyword user-auth pass-auth) ;; auth-info
;; append to the search the useful info from the source and the defaults:
;; user, host, and port
@@ -439,22 +440,22 @@ the `mail-source-keyword-map' variable."
;; for each default :SYMBOL, set SYMBOL to the plist value for :SYMBOL
;; using `mail-source-value' to evaluate the plist value
(set (mail-source-strip-keyword (setq keyword (car default)))
- ;; note the following reasons for this structure:
+ ;; Note the following reasons for this structure:
;; 1) the auth-sources user and password override everything
;; 2) it avoids macros, so it's cleaner
;; 3) it falls through to the mail-sources and then default values
(cond
((and
- (eq keyword :user)
- (setq user-auth
- (plist-get
- ;; cache the search result in `found'
- (or found
- (setq found (nth 0 (apply #'auth-source-search
- search))))
- :user)))
+ (eq keyword :user)
+ (setq user-auth
+ (plist-get
+ ;; cache the search result in `found'
+ (or found
+ (setq found (nth 0 (apply #'auth-source-search
+ search))))
+ :user)))
user-auth)
- ((and
+ ((and ; cf. 'auth-source-pick-first-password'
(eq keyword :password)
(setq pass-auth
(plist-get
@@ -467,9 +468,8 @@ the `mail-source-keyword-map' variable."
(if (functionp pass-auth)
(setq pass-auth (funcall pass-auth))
pass-auth))
- (t (if (setq value (plist-get source keyword))
- (mail-source-value value)
- (mail-source-value (cadr default)))))))))
+ (t (mail-source-value (or (plist-get source keyword)
+ (cadr default)))))))))
(eval-and-compile
(defun mail-source-bind-common-1 ()
@@ -1048,8 +1048,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'.")
@@ -1067,9 +1065,7 @@ This only works when `display-time' is enabled."
(let ((from (format "%s:%s:%s" server user port))
(found 0)
(buf (generate-new-buffer " *imap source*"))
- (mail-source-string (format "imap:%s:%s" server mailbox))
- (imap-shell-program (or (list program) imap-shell-program))
- remove)
+ (imap-shell-program (or (list program) imap-shell-program)))
(if (and (imap-open server port stream authentication buf)
(imap-authenticate
user (or (cdr (assoc from mail-source-password-cache))
@@ -1078,8 +1074,10 @@ This only works when `display-time' is enabled."
(let ((mailbox-list (if (listp mailbox) mailbox (list mailbox))))
(dolist (mailbox mailbox-list)
(when (imap-mailbox-select mailbox nil buf)
- (let ((coding-system-for-write mail-source-imap-file-coding-system)
- str)
+ (let ((coding-system-for-write
+ mail-source-imap-file-coding-system)
+ (mail-source-string (format "imap:%s:%s" server mailbox))
+ str remove)
(message "Fetching from %s..." mailbox)
(with-temp-file mail-source-crash-box
;; Avoid converting 8-bit chars from inserted strings to
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 8f11e538c5a..7c2b24c6eee 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -50,6 +50,7 @@
(require 'subr-x)
(require 'yank-media)
(require 'mailcap)
+(require 'sendmail)
(autoload 'mailclient-send-it "mailclient")
@@ -716,7 +717,7 @@ The function accepts 1 parameter which is the matched prefix."
(defvar sendmail-program)
(cond ((executable-find sendmail-program)
#'message-send-mail-with-sendmail)
- ((bound-and-true-p 'smtpmail-default-smtp-server)
+ ((bound-and-true-p smtpmail-default-smtp-server)
#'message-smtpmail-send-it)
(t
#'message-send-mail-with-mailclient)))
@@ -1410,7 +1411,7 @@ text and it replaces `self-insert-command' with the other command, e.g.
(file-name-as-directory (expand-file-name "drafts" message-directory))
"~/")
"Directory where Message auto-saves buffers if Gnus isn't running.
-If nil, Message won't auto-save."
+If nil, Message won't auto-save, whether or not Gnus is running."
:group 'message-buffers
:link '(custom-manual "(message)Various Message Variables")
:type '(choice directory (const :tag "Don't auto-save" nil)))
@@ -1467,11 +1468,11 @@ candidates:
(memq feature message-shoot-gnksa-feet)))
(defcustom message-hidden-headers '("^References:" "^Face:" "^X-Face:"
- "^X-Draft-From:")
+ "^X-Draft-From:" "^In-Reply-To:")
"Regexp of headers to be hidden when composing new messages.
This can also be a list of regexps to match headers. Or a list
starting with `not' and followed by regexps."
- :version "22.1"
+ :version "29.1"
:group 'message
:link '(custom-manual "(message)Message Headers")
:type '(choice
@@ -3179,8 +3180,7 @@ Like `text-mode', but with these additional commands:
(mail-abbrevs-setup))
((message-mail-alias-type-p 'ecomplete)
(ecomplete-setup)))
- ;; FIXME: merge the completion tables from ecomplete/bbdb/...?
- ;;(add-hook 'completion-at-point-functions #'message-ecomplete-capf nil t)
+ (add-hook 'completion-at-point-functions #'eudc-capf-complete -1 t)
(add-hook 'completion-at-point-functions #'message-completion-function nil t)
(unless buffer-file-name
(message-set-auto-save-file-name))
@@ -4357,7 +4357,11 @@ it is left unchanged."
(defun message-update-smtp-method-header ()
"Insert an X-Message-SMTP-Method header according to `message-server-alist'."
(unless (message-fetch-field "X-Message-SMTP-Method")
- (let ((from (cadr (mail-extract-address-components (message-fetch-field "From"))))
+ (let ((from (cadr (mail-extract-address-components
+ (save-restriction
+ (widen)
+ (message-narrow-to-headers-or-head)
+ (message-fetch-field "From")))))
method)
(catch 'exit
(dolist (server message-server-alist)
@@ -4901,7 +4905,18 @@ If you always want Gnus to send messages in one piece, set
(message-generate-headers '(Lines)))
;; Remove some headers.
(message-remove-header message-ignored-mail-headers t)
- (mail-encode-encoded-word-buffer))
+ (mail-encode-encoded-word-buffer)
+ ;; Then check for suspicious addresses.
+ (dolist (hdr '("To" "Cc" "Bcc"))
+ (let ((addr (message-fetch-field hdr)))
+ (when (stringp addr)
+ (dolist (address (mail-header-parse-addresses addr t))
+ (when-let ((warning (textsec-suspicious-p
+ address 'email-address-header)))
+ (unless (y-or-n-p
+ (format "Suspicious address: %s; send anyway?"
+ warning))
+ (user-error "Suspicious address %s" address))))))))
(goto-char (point-max))
;; require one newline at the end.
(or (= (preceding-char) ?\n)
@@ -6866,13 +6881,14 @@ are not included."
(or (bolp) (insert ?\n)))
(insert (concat mail-header-separator "\n"))
(forward-line -1)
- ;; If a crash happens while replying, the auto-save file would *not* have a
- ;; `References:' header if `message-generate-headers-first' was nil.
- ;; Therefore, always generate it first.
+ ;; If a crash happens while replying, the auto-save file would *not*
+ ;; have a `References:' header if `message-generate-headers-first'
+ ;; was nil. Therefore, always generate it first. (And why not
+ ;; include the `In-Reply-To' header as well.)
(let ((message-generate-headers-first
(if (eq message-generate-headers-first t)
t
- (append message-generate-headers-first '(References)))))
+ (append message-generate-headers-first '(References In-Reply-To)))))
(when (message-news-p)
(when message-default-news-headers
(insert message-default-news-headers)
@@ -7002,7 +7018,15 @@ is a function used to switch to and display the mail buffer."
;; https://lists.gnu.org/r/emacs-devel/2011-01/msg00337.html
;; We need to convert any string input, eg from rmail-start-mail.
(dolist (h other-headers other-headers)
- (if (stringp (car h)) (setcar h (intern (capitalize (car h)))))))
+ (when (stringp (car h))
+ (setcar h (intern (capitalize (car h)))))
+ ;; Firefox sends us In-Reply-To headers that are Message-IDs
+ ;; without <> around them. Fix that.
+ (when (and (eq (car h) 'In-Reply-To)
+ ;; Looks like a Message-ID.
+ (string-match-p "\\`[^ @]+@[^ @]+\\'" (cdr h))
+ (not (string-match-p "\\`<.*>\\'" (cdr h))))
+ (setcdr h (concat "<" (cdr h) ">")))))
yank-action send-actions continue switch-function
return-action))))
@@ -8001,7 +8025,18 @@ is for the internal use."
(select-safe-coding-system-function nil)
message-required-mail-headers
message-generate-hashcash
- rfc2047-encode-encoded-words)
+ rfc2047-encode-encoded-words
+ ;; If `message-sendmail-envelope-from' is `header' then
+ ;; the envelope-from will be the original sender's
+ ;; address, not the resender's. But when resending, the
+ ;; envelope-from should be the resender's address. Defuse
+ ;; that particular case.
+ (message-sendmail-envelope-from
+ (and (not (and (eq message-sendmail-envelope-from
+ 'obey-mail-envelope-from)
+ (eq mail-envelope-from 'header)))
+ (not (eq message-sendmail-envelope-from 'header))
+ message-sendmail-envelope-from)))
(message-send-mail))
(when gcc
(message-goto-eoh)
@@ -8140,39 +8175,7 @@ which specify the range to operate on."
;; Support for toolbar
(defvar tool-bar-mode)
-;; Note: The :set function in the `message-tool-bar*' variables will only
-;; affect _new_ message buffers. We might add a function that walks thru all
-;; message-mode buffers and force the update.
-(defun message-tool-bar-update (&optional symbol value)
- "Update message mode toolbar.
-Setter function for custom variables."
- (setq-default message-tool-bar-map nil)
- (when symbol
- ;; When used as ":set" function:
- (set-default symbol value)))
-
-(defcustom message-tool-bar (if (eq gmm-tool-bar-style 'gnome)
- 'message-tool-bar-gnome
- 'message-tool-bar-retro)
- "Specifies the message mode tool bar.
-
-It can be either a list or a symbol referring to a list. See
-`gmm-tool-bar-from-list' for the format of the list. The
-default key map is `message-mode-map'.
-
-Pre-defined symbols include `message-tool-bar-gnome' and
-`message-tool-bar-retro'."
- :type '(repeat gmm-tool-bar-list-item)
- :type '(choice (const :tag "GNOME style" message-tool-bar-gnome)
- (const :tag "Retro look" message-tool-bar-retro)
- (repeat :tag "User defined list" gmm-tool-bar-item)
- (symbol))
- :version "23.1" ;; No Gnus
- :initialize #'custom-initialize-default
- :set #'message-tool-bar-update
- :group 'message)
-
-(defcustom message-tool-bar-gnome
+(defcustom message-tool-bar
'((ispell-message "spell" nil
:vert-only t
:visible (not flyspell-mode))
@@ -8188,47 +8191,23 @@ Pre-defined symbols include `message-tool-bar-gnome' and
(message-insert-importance-high "important" nil :visible nil)
(message-insert-importance-low "unimportant" nil :visible nil)
(message-insert-disposition-notification-to "receipt" nil :visible nil))
- "List of items for the message tool bar (GNOME style).
-
-See `gmm-tool-bar-from-list' for details on the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize #'custom-initialize-default
- :set #'message-tool-bar-update
- :group 'message)
+ "Specifies the message mode tool bar.
-(defcustom message-tool-bar-retro
- '(;; Old Emacs 21 icon for consistency.
- (message-send-and-exit "mail/send")
- (message-kill-buffer "close")
- (message-dont-send "cancel")
- (mml-attach-file "attach" mml-mode-map)
- (ispell-message "spell")
- (mml-preview "preview" mml-mode-map)
- (message-insert-importance-high "gnus/important")
- (message-insert-importance-low "gnus/unimportant")
- (message-insert-disposition-notification-to "gnus/receipt"))
- "List of items for the message tool bar (retro style).
-
-See `gmm-tool-bar-from-list' for details on the format of the list."
- :type '(repeat gmm-tool-bar-item)
- :version "23.1" ;; No Gnus
- :initialize #'custom-initialize-default
- :set #'message-tool-bar-update
+It can be either a list or a symbol referring to a list. See
+`gmm-tool-bar-from-list' for the format of the list. The
+default key map is `message-mode-map'."
+ :type '(repeat gmm-tool-bar-list-item)
+ :type '(choice (repeat :tag "User defined list" gmm-tool-bar-item)
+ (symbol))
+ :version "29.1"
:group 'message)
-(defcustom message-tool-bar-zap-list
- '(new-file open-file dired kill-buffer write-file
- print-buffer customize help)
- "List of icon items from the global tool bar.
-These items are not displayed on the message mode tool bar.
-
-See `gmm-tool-bar-from-list' for the format of the list."
- :type 'gmm-tool-bar-zap-list
- :version "23.1" ;; No Gnus
- :initialize #'custom-initialize-default
- :set #'message-tool-bar-update
- :group 'message)
+(defvar message-tool-bar-gnome nil)
+(make-obsolete-variable 'message-tool-bar-gnome nil "29.1")
+(defvar message-tool-bar-retro nil)
+(make-obsolete-variable 'message-tool-bar-gnome nil "29.1")
+(defvar message-tool-bar-zap-list t)
+(make-obsolete-variable 'message-tool-bar-zap-list nil "29.1")
(defvar image-load-path)
(declare-function image-load-path-for-library "image"
@@ -8250,17 +8229,23 @@ When FORCE, rebuild the tool bar."
'message-mode-map))))
message-tool-bar-map)
-;;; Group name completion.
+;;; Group name and email address completion.
(defcustom message-newgroups-header-regexp
"^\\(Newsgroups\\|Followup-To\\|Posted-To\\|Gcc\\):"
- "Regexp that match headers that lists groups."
+ "Regexp matching headers that list groups."
:group 'message
:type 'regexp)
+(defcustom message-email-recipient-header-regexp
+ "^\\([^ :]*-\\)?\\(To\\|B?Cc\\|From\\|Reply-to\\|Mail-Followup-To\\|Mail-Copies-To\\):"
+ "Regexp matching headers that list email addresses."
+ :version "29.1"
+ :type 'regexp)
+
(defcustom message-completion-alist
`((,message-newgroups-header-regexp . ,#'message-expand-group)
- ("^\\([^ :]*-\\)?\\(To\\|B?Cc\\|From\\):" . ,#'message-expand-name))
+ (,message-email-recipient-header-regexp . ,#'message-expand-name))
"Alist of (RE . FUN). Use FUN for completion on header lines matching RE.
FUN should be a function that obeys the same rules as those
of `completion-at-point-functions'."
@@ -8354,7 +8339,11 @@ regular text mode tabbing command."
(defcustom message-expand-name-standard-ui nil
"If non-nil, use the standard completion UI in `message-expand-name'.
-E.g. this means it will obey `completion-styles' and other such settings."
+E.g. this means it will obey `completion-styles' and other such settings.
+
+If this variable is non-nil and `message-mail-alias-type' is
+`ecomplete', `message-self-insert-commands' should probably be
+set to nil."
:version "27.1"
:type 'boolean)
@@ -8383,7 +8372,8 @@ E.g. this means it will obey `completion-styles' and other such settings."
(t
(expand-abbrev))))
-(add-to-list 'completion-category-defaults '(email (styles substring)))
+(add-to-list 'completion-category-defaults '(email (styles substring
+ partial-completion)))
(defun message--bbdb-query-with-words (words)
;; FIXME: This (or something like this) should live on the BBDB side.
@@ -8606,26 +8596,23 @@ From headers in the original article."
message-hidden-headers))
(inhibit-point-motion-hooks t)
(inhibit-modification-hooks t)
- (end-of-headers (point-min)))
+ end-of-headers)
(when regexps
(save-excursion
(save-restriction
(message-narrow-to-headers)
+ (setq end-of-headers (point-min-marker))
(goto-char (point-min))
(while (not (eobp))
(if (not (message-hide-header-p regexps))
(message-next-header)
- (let ((begin (point))
- header header-len)
+ (let ((begin (point)))
(message-next-header)
- (setq header (buffer-substring begin (point))
- header-len (- (point) begin))
- (delete-region begin (point))
- (goto-char end-of-headers)
- (insert header)
- (setq end-of-headers
- (+ end-of-headers header-len))))))))
- (narrow-to-region end-of-headers (point-max))))
+ (let ((header (delete-and-extract-region begin (point))))
+ (save-excursion
+ (goto-char end-of-headers)
+ (insert-before-markers header))))))))
+ (narrow-to-region end-of-headers (point-max)))))
(defun message-hide-header-p (regexps)
(let ((result nil)
@@ -8974,7 +8961,7 @@ used to take the screenshot."
This is meant to be used for MIME handlers: Setting the handler
for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
will then start up Emacs ready to compose mail. For emacsclient use
- emacsclient -e '(message-mailto \"%u\")'"
+ emacsclient -e \\='(message-mailto \"%u\")'"
(interactive)
;; <a href="mailto:someone@example.com?subject=This%20is%20the%20subject&cc=someone_else@example.com&body=This%20is%20the%20body">Send email</a>
(message-mail)
diff --git a/lisp/gnus/mm-bodies.el b/lisp/gnus/mm-bodies.el
index 956449dac14..9045966df5a 100644
--- a/lisp/gnus/mm-bodies.el
+++ b/lisp/gnus/mm-bodies.el
@@ -191,19 +191,21 @@ If TYPE is `text/plain' CRLF->LF translation may occur."
((eq encoding 'base64)
(base64-decode-region
(point-min)
- ;; Some mailers insert whitespace
- ;; junk at the end which
- ;; base64-decode-region dislikes.
- ;; Also remove possible junk which could
- ;; have been added by mailing list software.
(save-excursion
+ ;; Some mailers insert whitespace junk at the end which
+ ;; base64-decode-region dislikes.
(goto-char (point-min))
(while (re-search-forward "^[\t ]*\r?\n" nil t)
(delete-region (match-beginning 0) (match-end 0)))
+ ;; Also ignore junk which could have been added by
+ ;; mailing list software by finding the final line with
+ ;; base64 text.
(goto-char (point-max))
- (when (re-search-backward "^[\t ]*[A-Za-z0-9+/]+=*[\t ]*$"
- nil t)
- (forward-line))
+ (beginning-of-line)
+ (while (and (not (mm-base64-line-p))
+ (not (bobp)))
+ (forward-line -1))
+ (forward-line 1)
(point))))
((memq encoding '(nil 7bit 8bit binary))
;; Do nothing.
@@ -236,6 +238,20 @@ If TYPE is `text/plain' CRLF->LF translation may occur."
(while (search-forward "\r\n" nil t)
(replace-match "\n" t t)))))
+(defun mm-base64-line-p ()
+ "Say whether the current line is base64."
+ ;; This is coded in this way to avoid using regexps that may
+ ;; overflow -- a base64 line may be megabytes long.
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (and (looking-at "[A-Za-z0-9+/]\\{3\\}")
+ (progn
+ (skip-chars-forward "A-Za-z0-9+/")
+ (skip-chars-forward "=")
+ (skip-chars-forward " \t")
+ (eolp)))))
+
(defun mm-decode-body (charset &optional encoding type)
"Decode the current article that has been encoded with ENCODING to CHARSET.
ENCODING is a MIME content transfer encoding.
diff --git a/lisp/gnus/mm-encode.el b/lisp/gnus/mm-encode.el
index ead3bae219d..39b1ad1f3b9 100644
--- a/lisp/gnus/mm-encode.el
+++ b/lisp/gnus/mm-encode.el
@@ -99,7 +99,7 @@ This variable should never be set directly, but bound before a call to
;;;###autoload
(define-obsolete-function-alias 'mm-default-file-encoding
- #'mm-default-file-type "future") ;Old bad name.
+ #'mm-default-file-type "28.1") ;Old bad name.
;;;###autoload
(defun mm-default-file-type (file)
"Return a default content type for FILE."
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el
index 31cf92e6172..727e3abfffc 100644
--- a/lisp/gnus/mm-util.el
+++ b/lisp/gnus/mm-util.el
@@ -315,8 +315,7 @@ Valid elements include:
"ISO-8859-15 exchangeable coding systems and inconvertible characters.")
(defvar mm-iso-8859-x-to-15-table
- (and (fboundp 'coding-system-p)
- (mm-coding-system-p 'iso-8859-15)
+ (and (mm-coding-system-p 'iso-8859-15)
(mapcar
(lambda (cs)
(if (mm-coding-system-p (car cs))
diff --git a/lisp/gnus/mm-uu.el b/lisp/gnus/mm-uu.el
index 9fe41f67866..8646998deb9 100644
--- a/lisp/gnus/mm-uu.el
+++ b/lisp/gnus/mm-uu.el
@@ -214,7 +214,7 @@ This can be either \"inline\" or \"attachment\".")
"$"
,#'mm-uu-org-src-code-block-extract))
"A list of specifications for non-MIME attachments.
-Each element consist of a `mm-uu-entry'.
+Each element consists of a `mm-uu-entry'.
The functions in the last 3 slots of this type can make use of the following
dynamically-scoped variables:
`file-name', `start-point', and `end-point'.
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index b110750c098..57ce36a9442 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -504,8 +504,6 @@ If MODE is not set, try to find mode automatically."
(setq coding-system (mm-find-buffer-file-coding-system)))
(setq text (buffer-string))))
(with-temp-buffer
- (buffer-disable-undo)
- (mm-enable-multibyte)
(insert (cond ((eq charset 'gnus-decoded)
(with-current-buffer (mm-handle-buffer handle)
(buffer-string)))
@@ -521,17 +519,17 @@ If MODE is not set, try to find mode automatically."
;; setting now, but it seems harmless and potentially still useful.
(setq-local font-lock-mode-hook nil)
(setq buffer-file-name (mm-handle-filename handle))
- (with-demoted-errors
- (if mode
- (save-window-excursion
- ;; According to Katsumi Yamaoka <yamaoka@jpl.org>, org-mode
- ;; requires the buffer to be temporarily displayed here, but
- ;; I could not reproduce this problem. Furthermore, if
- ;; there's such a problem, we should fix org-mode rather than
- ;; use switch-to-buffer which can have undesirable
- ;; side-effects!
- ;;(switch-to-buffer (current-buffer))
- (funcall mode))
+ (with-demoted-errors "Error setting mode: %S"
+ (if mode
+ (save-window-excursion
+ ;; According to Katsumi Yamaoka <yamaoka@jpl.org>, org-mode
+ ;; requires the buffer to be temporarily displayed here, but
+ ;; I could not reproduce this problem. Furthermore, if
+ ;; there's such a problem, we should fix org-mode rather than
+ ;; use switch-to-buffer which can have undesirable
+ ;; side-effects!
+ ;;(switch-to-buffer (current-buffer))
+ (funcall mode))
(let ((auto-mode-alist
(delq (rassq 'doc-view-mode-maybe auto-mode-alist)
(copy-sequence auto-mode-alist))))
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 5a526025061..093e582ea7a 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -500,7 +500,8 @@ type detected."
(when (and (consp (car cont))
(= (length cont) 1)
content-type)
- (setcdr (assq 'type (cdr (car cont))) content-type))
+ (when-let ((spec (assq 'type (cdr (car cont)))))
+ (setcdr spec content-type)))
(when (fboundp 'libxml-parse-html-region)
(setq cont (mapcar #'mml-expand-all-html-into-multipart-related cont)))
(prog1
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 ab4243e867f..746109f26fa 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -40,6 +40,7 @@
(autoload 'auth-source-forget+ "auth-source")
(autoload 'auth-source-search "auth-source")
+(autoload 'auth-info-password "auth-source")
(nnoo-declare nnimap)
@@ -94,9 +95,6 @@ Uses the same syntax as `nnmail-split-methods'.")
(defvoo nnimap-unsplittable-articles '(%Deleted %Seen)
"Articles with the flags in the list will not be considered when splitting.")
-(make-obsolete-variable 'nnimap-split-rule "see `nnimap-split-methods'."
- "24.1")
-
(defvoo nnimap-authenticator nil
"How nnimap authenticate itself to the server.
Possible choices are nil (use default methods), `anonymous',
@@ -232,20 +230,30 @@ during splitting, which may be slow."
params)
(format "%s" (nreverse params))))
+(defvar nnimap--max-retrieve-headers 200)
+
(deffoo nnimap-retrieve-headers (articles &optional group server _fetch-old)
(with-current-buffer nntp-server-buffer
(erase-buffer)
(when (nnimap-change-group group server)
(with-current-buffer (nnimap-buffer)
(erase-buffer)
- (nnimap-wait-for-response
- (nnimap-send-command
- "UID FETCH %s %s"
- (nnimap-article-ranges (gnus-compress-sequence articles))
- (nnimap-header-parameters))
- t)
+ ;; If we have a lot of ranges, split them up to avoid
+ ;; generating too-long lines. (The limit is 8192 octects,
+ ;; and this should guarantee that it's (much) shorter than
+ ;; that.) We don't stream the requests, since the server
+ ;; may respond to the requests out-of-order:
+ ;; https://datatracker.ietf.org/doc/html/rfc3501#section-5.5
+ (dolist (ranges (seq-split (gnus-compress-sequence articles t)
+ nnimap--max-retrieve-headers))
+ (nnimap-wait-for-response
+ (nnimap-send-command
+ "UID FETCH %s %s"
+ (nnimap-article-ranges ranges)
+ (nnimap-header-parameters))
+ t))
(unless (process-live-p (get-buffer-process (current-buffer)))
- (error "Server closed connection"))
+ (error "IMAP server %S closed connection" nnimap-address))
(nnimap-transform-headers)
(nnheader-remove-cr-followed-by-lf))
(insert-buffer-substring
@@ -407,10 +415,7 @@ during splitting, which may be slow."
:create t))))
(if found
(list (plist-get found :user)
- (let ((secret (plist-get found :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))
+ (auth-info-password found)
(plist-get found :save-function))
nil)))
@@ -1662,13 +1667,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))
@@ -1693,7 +1698,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)))
@@ -1704,15 +1709,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
@@ -1735,10 +1740,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)))
@@ -1752,9 +1756,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))))
@@ -1764,7 +1768,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)))
@@ -2244,7 +2248,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/nnmail.el b/lisp/gnus/nnmail.el
index c71627f83a4..bde0de98924 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1937,9 +1937,7 @@ If TIME is nil, then return the cutoff time for oldness instead."
(and (string-match (cadr regexp-target-pair) to)
(let ((mail-dont-reply-to-names
(message-dont-reply-to-names)))
- (equal (if (fboundp 'rmail-dont-reply-to)
- (rmail-dont-reply-to from)
- (mail-dont-reply-to from)) "")))))
+ (equal (mail-dont-reply-to from) "")))))
(setq target (format-time-string (caddr regexp-target-pair) date)))
((and (not (equal header 'to-from))
(string-match (cadr regexp-target-pair)
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..8c811b0c6c0 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -333,7 +333,7 @@ this might lead to problems, especially when used with marks propagation."
(defvar nnmairix-widget-other
'(threads flags)
"Other editable mairix commands when using customization widgets.
-Currently there are 'threads and 'flags.")
+Currently there are `threads' and `flags'.")
(defvar nnmairix-interactive-query-parameters
'((?f "from" "f" "From") (?t "to" "t" "To") (?c "to" "tc" "To or Cc")
@@ -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/nnnil.el b/lisp/gnus/nnnil.el
index 36a8bc4581b..092b53298a2 100644
--- a/lisp/gnus/nnnil.el
+++ b/lisp/gnus/nnnil.el
@@ -40,7 +40,7 @@
(defun nnnil-open-server (_server &optional _definitions)
t)
-(defun nnnil-close-server (&optional _server)
+(defun nnnil-close-server (&optional _server _defs)
t)
(defun nnnil-request-close ()
diff --git a/lisp/gnus/nnregistry.el b/lisp/gnus/nnregistry.el
index d042981ca98..4a799acad98 100644
--- a/lisp/gnus/nnregistry.el
+++ b/lisp/gnus/nnregistry.el
@@ -36,7 +36,7 @@
(nnoo-declare nnregistry)
(deffoo nnregistry-server-opened (_server)
- gnus-registry-enabled)
+ gnus-registry-db)
(deffoo nnregistry-close-server (_server &optional _defs)
t)
@@ -45,7 +45,7 @@
nil)
(deffoo nnregistry-open-server (_server &optional _defs)
- gnus-registry-enabled)
+ gnus-registry-db)
(defvar nnregistry-within-nnregistry nil)
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index 4ca53f108f1..f740af3b6d1 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -756,8 +756,7 @@ Export subscriptions to a buffer in OPML Format."
(insert " </body>\n"
"</opml>\n"))
(pop-to-buffer "*OPML Export*")
- (when (fboundp 'sgml-mode)
- (sgml-mode)))
+ (sgml-mode))
(defun nnrss-generate-download-script ()
"Generate a download script in the current buffer.
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index 9d744ea411e..9b8333a7c6c 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -47,7 +47,8 @@
;;; Setup:
(require 'gnus-art)
-(require 'gnus-search)
+(autoload 'gnus-search-run-query "gnus-search")
+(autoload 'gnus-search-server-to-engine "gnus-search")
(eval-when-compile (require 'cl-lib))
@@ -79,33 +80,37 @@
;;; Helper routines.
(defun nnselect-compress-artlist (artlist)
"Compress ARTLIST."
- (let (selection)
- (pcase-dolist (`(,artgroup . ,arts)
- (nnselect-categorize artlist #'nnselect-artitem-group))
- (let (list)
- (pcase-dolist (`(,rsv . ,articles)
- (nnselect-categorize
- arts #'nnselect-artitem-rsv #'nnselect-artitem-number))
- (push (cons rsv (gnus-compress-sequence (sort articles #'<)))
- list))
- (push (cons artgroup list) selection)))
- selection))
+ (if (consp artlist)
+ artlist
+ (let (selection)
+ (pcase-dolist (`(,artgroup . ,arts)
+ (nnselect-categorize artlist #'nnselect-artitem-group))
+ (let (list)
+ (pcase-dolist (`(,rsv . ,articles)
+ (nnselect-categorize
+ arts #'nnselect-artitem-rsv #'nnselect-artitem-number))
+ (push (cons rsv (gnus-compress-sequence (sort articles #'<)))
+ list))
+ (push (cons artgroup list) selection)))
+ selection)))
(defun nnselect-uncompress-artlist (artlist)
"Uncompress ARTLIST."
(if (vectorp artlist)
artlist
(let (selection)
- (pcase-dolist (`(,artgroup (,artrsv . ,artseq)) artlist)
- (setq selection
- (vconcat
- (cl-map 'vector
- (lambda (art)
- (vector artgroup art artrsv))
- (gnus-uncompress-sequence artseq)) selection)))
+ (pcase-dolist (`(,artgroup . ,list) artlist)
+ (pcase-dolist (`(,artrsv . ,artseq) list)
+ (setq selection
+ (vconcat
+ (cl-map 'vector
+ (lambda (art)
+ (vector artgroup art artrsv))
+ (gnus-uncompress-sequence artseq)) selection))))
selection)))
(make-obsolete 'nnselect-group-server 'gnus-group-server "28.1")
+(make-obsolete 'nnselect-run 'nnselect-generate-artlist "29.1")
;; Data type article list.
@@ -207,7 +212,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
@@ -227,11 +232,6 @@ as `(keyfunc member)' and the corresponding element is just
`(gnus-group-prefixed-name
(gnus-group-short-name ,group) '(nnselect "nnselect")))
-(defmacro nnselect-get-artlist (group)
- "Retrieve the list of articles for GROUP."
- `(when (gnus-nnselect-group-p ,group)
- (nnselect-uncompress-artlist
- (gnus-group-get-parameter ,group 'nnselect-artlist t))))
(defmacro nnselect-add-novitem (novitem)
"Add NOVITEM to the list of headers."
@@ -252,16 +252,78 @@ as `(keyfunc member)' and the corresponding element is just
(define-obsolete-variable-alias 'nnir-retrieve-headers-override-function
'nnselect-retrieve-headers-override-function "28.1")
+(defcustom nnselect-allow-ephemeral-expiry nil
+ "If non-nil, articles in ephemeral nnselect groups are subject to expiry."
+ :version "29.1"
+ :type 'boolean)
+
(defcustom nnselect-retrieve-headers-override-function nil
"A function that retrieves article headers for ARTICLES from GROUP.
The retrieved headers should populate the `nntp-server-buffer'.
-Returns either the retrieved header format 'nov or 'headers.
+Returns either the retrieved header format `nov' or `headers'.
If this variable is nil, or if the provided function returns nil,
`gnus-retrieve-headers' will be called instead."
:version "28.1"
:type '(repeat function))
+(defun nnselect-generate-artlist (group &optional specs)
+ "Generate the artlist for GROUP using SPECS.
+SPECS should be an alist including an `nnselect-function' and an
+`nnselect-args'. The former applied to the latter should create
+the artlist. If SPECS is nil retrieve the specs from the group
+parameters."
+ (let* ((specs
+ (or specs (gnus-group-get-parameter group 'nnselect-specs t)))
+ (function (alist-get 'nnselect-function specs))
+ (args (alist-get 'nnselect-args specs)))
+ (condition-case-unless-debug err
+ (funcall function args)
+ ;; Don't swallow gnus-search errors; the user should be made
+ ;; aware of them.
+ (gnus-search-error
+ (signal (car err) (cdr err)))
+ (error
+ (gnus-error
+ 3
+ "nnselect-generate-artlist: %s on %s gave error %s" function args err)
+ []))))
+
+(defmacro nnselect-get-artlist (group)
+ "Get the list of articles for GROUP.
+If the group parameter `nnselect-get-artlist-override-function' is
+non-nil call this function with argument GROUP to get the
+artlist; if the group parameter `nnselect-always-regenerate' is
+non-nil, regenerate the artlist; otherwise retrieve the artlist
+directly from the group parameters."
+ `(when (gnus-nnselect-group-p ,group)
+ (let ((override (gnus-group-get-parameter
+ ,group
+ 'nnselect-get-artlist-override-function)))
+ (cond
+ (override (funcall override ,group))
+ ((gnus-group-get-parameter ,group 'nnselect-always-regenerate)
+ (nnselect-generate-artlist ,group))
+ (t
+ (nnselect-uncompress-artlist
+ (gnus-group-get-parameter ,group 'nnselect-artlist t)))))))
+
+(defmacro nnselect-store-artlist (group artlist)
+ "Store the ARTLIST for GROUP.
+If the group parameter `nnselect-store-artlist-override-function'
+is non-nil call this function on GROUP and ARTLIST; if the group
+parameter `nnselect-always-regenerate' is non-nil don't store the
+artlist; otherwise store the ARTLIST in the group parameters."
+ `(let ((override (gnus-group-get-parameter
+ ,group
+ 'nnselect-store-artlist-override-function)))
+ (cond
+ (override (funcall override ,group ,artlist))
+ ((gnus-group-get-parameter ,group 'nnselect-always-regenerate) t)
+ (t
+ (gnus-group-set-parameter ,group 'nnselect-artlist
+ (nnselect-compress-artlist ,artlist))))))
+
;; Gnus backend interface functions.
(deffoo nnselect-open-server (server &optional definitions)
@@ -287,11 +349,8 @@ If this variable is nil, or if the provided function returns nil,
;; Check for cached select result or run the selection and cache
;; the result.
(unless nnselect-artlist
- (gnus-group-set-parameter
- group 'nnselect-artlist
- (nnselect-compress-artlist (setq nnselect-artlist
- (nnselect-run
- (gnus-group-get-parameter group 'nnselect-specs t)))))
+ (nnselect-store-artlist group
+ (setq nnselect-artlist (nnselect-generate-artlist group)))
(nnselect-request-update-info
group (or info (gnus-get-info group))))
(if (zerop (setq length (nnselect-artlist-length nnselect-artlist)))
@@ -329,6 +388,7 @@ If this variable is nil, or if the provided function returns nil,
(gnus-group-find-parameter artgroup
'gnus-fetch-old-headers t))
fetch-old)))
+ (gnus-request-group artgroup)
(erase-buffer)
(pcase (setq gnus-headers-retrieved-by
(or
@@ -453,24 +513,26 @@ If this variable is nil, or if the provided function returns nil,
:test #'equal :count 1)))))
(deffoo nnselect-request-expire-articles
- (articles _group &optional _server force)
- (if force
- (let (not-expired)
- (pcase-dolist (`(,artgroup . ,artids) (ids-by-group articles))
- (let ((artlist (sort (mapcar #'cdr artids) #'<)))
- (unless (gnus-check-backend-function 'request-expire-articles
- artgroup)
- (error "Group %s does not support article expiration" artgroup))
- (unless (gnus-check-server (gnus-find-method-for-group artgroup))
- (error "Couldn't open server for group %s" artgroup))
- (push (mapcar (lambda (art)
- (car (rassq art artids)))
- (let ((nnimap-expunge 'immediately))
- (gnus-request-expire-articles
- artlist artgroup force)))
- not-expired)))
- (sort (delq nil not-expired) #'<))
- articles))
+ (articles group &optional _server force)
+ (let ((nnimap-expunge 'immediately) not-deleted)
+ (if (and (not force)
+ (not nnselect-allow-ephemeral-expiry)
+ (gnus-ephemeral-group-p (nnselect-add-prefix group)))
+ articles
+ (pcase-dolist (`(,artgroup . ,artids) (ids-by-group articles))
+ (let ((artlist (sort (mapcar #'cdr artids) #'<)))
+ (unless
+ (gnus-check-backend-function 'request-expire-articles artgroup)
+ (error "Group %s does not support article expiration" artgroup))
+ (unless (gnus-check-server (gnus-find-method-for-group artgroup))
+ (error "Couldn't open server for group %s" artgroup))
+ (setq not-deleted
+ (append
+ (mapcar (lambda (art) (car (rassq art artids)))
+ (gnus-request-expire-articles artlist artgroup
+ force))
+ not-deleted))))
+ (sort (delq nil not-deleted) #'<))))
(deffoo nnselect-warp-to-article ()
@@ -528,68 +590,65 @@ If this variable is nil, or if the provided function returns nil,
(deffoo nnselect-request-update-info (group info &optional _server)
(let* ((group (nnselect-add-prefix group))
- (gnus-newsgroup-selection
- (or gnus-newsgroup-selection (nnselect-get-artlist group)))
- newmarks)
+ (gnus-newsgroup-selection
+ (or gnus-newsgroup-selection (nnselect-get-artlist group)))
+ newmarks)
(gnus-info-set-marks info nil)
(setf (gnus-info-read info) nil)
(pcase-dolist (`(,artgroup . ,nartids)
- (ids-by-group
- (number-sequence 1 (nnselect-artlist-length
- gnus-newsgroup-selection))))
+ (ids-by-group
+ (number-sequence 1 (nnselect-artlist-length
+ gnus-newsgroup-selection))))
(let* ((gnus-newsgroup-active nil)
- (artids (cl-sort nartids #'< :key 'car))
- (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)))))
+ (idmap (make-hash-table :test 'eql))
+ (gactive (sort (mapcar 'cdr nartids) '<))
+ (group-info (gnus-get-info artgroup))
+ (marks (gnus-info-marks group-info)))
+ (pcase-dolist (`(,val . ,key) nartids)
+ (puthash key val idmap))
(setf (gnus-info-read info)
- (gnus-add-to-range
- (gnus-info-read info)
- (delq nil (mapcar
- (lambda (art)
- (unless (memq (cdr art) unread) (car art)))
- artids))))
- (pcase-dolist (`(,type . ,mark-list) marks)
- (let ((mark-type (gnus-article-mark-to-type type)) new)
- (when
- (setq new
- (delq nil
- (cond
- ((eq mark-type 'tuple)
- (mapcar
- (lambda (id)
- (let (mark)
- (when
- (setq mark (assq (cdr id) mark-list))
- (cons (car id) (cdr mark)))))
- artids))
- (t
- (setq mark-list
- (gnus-uncompress-range mark-list))
- (mapcar
- (lambda (id)
- (when (memq (cdr id) mark-list)
- (car id))) artids)))))
- (let ((previous (alist-get type newmarks)))
- (if previous
- (nconc previous new)
- (push (cons type new) newmarks))))))))
+ (range-add-list
+ (gnus-info-read info)
+ (sort (mapcar (lambda (art) (gethash art idmap))
+ (gnus-sorted-intersection
+ gactive
+ (range-uncompress (gnus-info-read group-info))))
+ '<)))
+ (pcase-dolist (`(,type . ,mark-list) marks)
+ (let ((mark-type (gnus-article-mark-to-type type)) new)
+ (when
+ (setq new
+ (if (not mark-list) nil
+ (cond
+ ((eq mark-type 'tuple)
+ (delq nil
+ (mapcar
+ (lambda (mark)
+ (let ((id (gethash (car mark) idmap)))
+ (when id (cons id (cdr mark)))))
+ mark-list)))
+ (t
+ (mapcar (lambda (art) (gethash art idmap))
+ (gnus-sorted-intersection
+ gactive (range-uncompress mark-list)))))))
+ (let ((previous (alist-get type newmarks)))
+ (if previous
+ (nconc previous new)
+ (push (cons type new) newmarks))))))))
;; Clean up the marks: compress lists;
(pcase-dolist (`(,type . ,mark-list) newmarks)
(let ((mark-type (gnus-article-mark-to-type type)))
- (unless (eq mark-type 'tuple)
- (setf (alist-get type newmarks)
- (gnus-compress-sequence mark-list)))))
+ (unless (eq mark-type 'tuple)
+ (setf (alist-get type newmarks)
+ (gnus-compress-sequence (sort mark-list '<))))))
;; and ensure an unexist key.
(unless (assq 'unexist newmarks)
(push (cons 'unexist nil) newmarks))
(gnus-info-set-marks info newmarks)
(gnus-set-active group (cons 1 (nnselect-artlist-length
- gnus-newsgroup-selection)))))
+ gnus-newsgroup-selection)))))
(deffoo nnselect-request-thread (header &optional group server)
@@ -644,8 +703,15 @@ If this variable is nil, or if the provided function returns nil,
(lambda (article)
(if
(setq seq
- (cl-position article
- gnus-newsgroup-selection :test 'equal))
+ (cl-position
+ article
+ gnus-newsgroup-selection
+ :test
+ (lambda (x y)
+ (and (equal (nnselect-artitem-group x)
+ (nnselect-artitem-group y))
+ (eql (nnselect-artitem-number x)
+ (nnselect-artitem-number y))))))
(push (1+ seq) old-arts)
(setq gnus-newsgroup-selection
(vconcat gnus-newsgroup-selection (vector article)))
@@ -656,10 +722,7 @@ If this variable is nil, or if the provided function returns nil,
(append (sort old-arts #'<)
(number-sequence first last))
nil t))
- (gnus-group-set-parameter
- group
- 'nnselect-artlist
- (nnselect-compress-artlist gnus-newsgroup-selection))
+ (nnselect-store-artlist group gnus-newsgroup-selection)
(when (>= last first)
(let (new-marks)
(pcase-dolist (`(,artgroup . ,artids)
@@ -706,6 +769,7 @@ If this variable is nil, or if the provided function returns nil,
(message "Creating nnselect group %s" group)
(let* ((group (gnus-group-prefixed-name group '(nnselect "nnselect")))
(specs (assq 'nnselect-specs args))
+ (otherargs (assq-delete-all 'nnselect-specs args))
(function-spec
(or (alist-get 'nnselect-function specs)
(intern (completing-read "Function: " obarray #'functionp))))
@@ -715,10 +779,12 @@ If this variable is nil, or if the provided function returns nil,
(nnselect-specs (list (cons 'nnselect-function function-spec)
(cons 'nnselect-args args-spec))))
(gnus-group-set-parameter group 'nnselect-specs nnselect-specs)
- (gnus-group-set-parameter
- group 'nnselect-artlist
- (nnselect-compress-artlist (or (alist-get 'nnselect-artlist args)
- (nnselect-run nnselect-specs))))
+ (dolist (arg otherargs)
+ (gnus-group-set-parameter group (car arg) (cdr arg)))
+ (nnselect-store-artlist
+ group
+ (or (alist-get 'nnselect-artlist args)
+ (nnselect-generate-artlist group nnselect-specs)))
(nnselect-request-update-info group (gnus-get-info group)))
t)
@@ -743,20 +809,17 @@ If this variable is nil, or if the provided function returns nil,
(deffoo nnselect-request-scan (group _method)
(when (and group
- (gnus-group-get-parameter (nnselect-add-prefix group)
+ (gnus-group-find-parameter (nnselect-add-prefix group)
'nnselect-rescan t))
(nnselect-request-group-scan group)))
(deffoo nnselect-request-group-scan (group &optional _server _info)
(let* ((group (nnselect-add-prefix group))
- (artlist (nnselect-run
- (gnus-group-get-parameter group 'nnselect-specs t))))
+ (artlist (nnselect-generate-artlist group)))
(gnus-set-active group (cons 1 (nnselect-artlist-length
artlist)))
- (gnus-group-set-parameter
- group 'nnselect-artlist
- (nnselect-compress-artlist artlist))))
+ (nnselect-store-artlist group artlist)))
;; Add any undefined required backend functions
@@ -771,20 +834,6 @@ If this variable is nil, or if the provided function returns nil,
(eq 'nnselect (car gnus-command-method))))
-(defun nnselect-run (specs)
- "Apply nnselect-function to nnselect-args from SPECS.
-Return an article list."
- (let ((func (alist-get 'nnselect-function specs))
- (args (alist-get 'nnselect-args specs)))
- (condition-case-unless-debug err
- (funcall func args)
- ;; Don't swallow gnus-search errors; the user should be made
- ;; aware of them.
- (gnus-search-error
- (signal (car err) (cdr err)))
- (error (gnus-error 3 "nnselect-run: %s on %s gave error %s" func args err)
- []))))
-
(defun nnselect-search-thread (header)
"Make an nnselect group containing the thread with article HEADER.
The current server will be searched. If the registry is
@@ -863,19 +912,19 @@ article came from is also searched."
;; When the backend can store marks we collect any
;; changes. Unlike a normal group the mark lists only
;; include marks for articles we retrieved.
- (when (and (gnus-check-backend-function
- 'request-set-mark artgroup)
- (not (gnus-article-unpropagatable-p type)))
- (let* ((old (gnus-list-range-intersection
+ (when (and (gnus-check-backend-function
+ 'request-set-mark gnus-newsgroup-name)
+ (not (gnus-article-unpropagatable-p type)))
+ (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))))
@@ -902,26 +951,29 @@ article came from is also searched."
(setq list (cdr all))))
;; now merge with the original list and sort just to
;; make sure
- (setq list
- (sort (map-merge
- 'alist list
- (alist-get type (gnus-info-marks group-info)))
- (lambda (elt1 elt2)
- (< (car elt1) (car elt2))))))
+ (setq
+ list (sort
+ (map-merge
+ 'alist list
+ (delq nil
+ (mapcar
+ (lambda (x) (unless (memq (car x) artlist) x))
+ (alist-get type (gnus-info-marks group-info)))))
+ 'car-less-than-car)))
(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,16 +996,20 @@ 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)) #'<))))
(gnus-get-unread-articles-in-group
- group-info (gnus-active artgroup) t)
- (gnus-group-update-group artgroup t t)))))))
-
+ group-info (gnus-active artgroup) t))
+ (gnus-group-update-group
+ artgroup t
+ (equal group-info
+ (setq group-info (copy-sequence (gnus-get-info artgroup))
+ group-info
+ (delq (gnus-info-params group-info) group-info)))))))))
(declare-function gnus-registry-get-id-key "gnus-registry" (id key))
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 990bb4426f4..f047c832931 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -36,6 +36,7 @@
(eval-when-compile (require 'cl-lib))
(autoload 'auth-source-search "auth-source")
+(autoload 'auth-info-password "auth-source")
(defgroup nntp nil
"NNTP access for Gnus."
@@ -305,7 +306,7 @@ backend doesn't catch this error.")
(nntp-record-command string))
(process-send-string process (concat string nntp-end-of-line))
(or (memq (process-status process) '(open run))
- (nntp-report "Server closed connection")))
+ (nntp-report "NNTP server %S closed connection" nntp-address)))
(defun nntp-record-command (string)
"Record the command STRING."
@@ -368,7 +369,7 @@ retried once before actually displaying the error report."
(nntp-snarf-error-message)
nil))
((not (memq (process-status process) '(open run)))
- (nntp-report "Server closed connection"))
+ (nntp-report "NNTP server %S closed connection" nntp-address))
(t
(goto-char (point-max))
(let ((limit (point-min))
@@ -1175,10 +1176,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
"563" "nntps" "snews"))))
(auth-user (plist-get auth-info :user))
(auth-force (plist-get auth-info :force))
- (auth-passwd (plist-get auth-info :secret))
- (auth-passwd (if (functionp auth-passwd)
- (funcall auth-passwd)
- auth-passwd))
+ (auth-passwd (auth-info-password auth-info))
(force (or (netrc-get alist "force")
nntp-authinfo-force
auth-force))
@@ -1227,6 +1225,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
(generate-new-buffer
(format " *server %s %s %s*"
nntp-address nntp-port-number buffer))
+ (gnus-add-buffer)
(mm-disable-multibyte)
(setq-local after-change-functions nil
nntp-process-wait-for nil
@@ -1433,7 +1432,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
;; be the process's former output buffer (i.e. now killed)
(or (and process
(memq (process-status process) '(open run)))
- (nntp-report "Server closed connection")))))
+ (nntp-report "NNTP server %S closed connection" nntp-address)))))
(defun nntp-accept-response ()
"Wait for output from the process that outputs to BUFFER."
@@ -1452,7 +1451,7 @@ If SEND-IF-FORCE, only send authinfo to the server if the
(when group
(let ((entry (nntp-find-connection-entry nntp-server-buffer)))
(cond ((not entry)
- (nntp-report "Server closed connection"))
+ (nntp-report "NNTP server %S closed connection" nntp-address))
((not (equal group (caddr entry)))
(with-current-buffer (process-buffer (car entry))
(erase-buffer)
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index 7478a2dd0af..ae4265de7fb 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -114,14 +114,9 @@ It is computed from the marks of individual component groups.")
(gnus-check-server
(gnus-find-method-for-group cgroup) t)
(gnus-request-group cgroup t)
- (setq prefix (gnus-group-real-prefix cgroup))
- ;; FIX FIX FIX we want to check the cache!
- ;; This is probably evil if people have set
- ;; gnus-use-cache to nil themselves, but I
- ;; have no way of finding the true value of it.
- (let ((gnus-use-cache t))
- (setq result (gnus-retrieve-headers
- articles cgroup nil))))
+ (setq prefix (gnus-group-real-prefix cgroup)
+ result (gnus-retrieve-headers
+ articles cgroup nil)))
(set-buffer nntp-server-buffer)
;; If we got HEAD headers, we convert them into NOV
;; headers. This is slow, inefficient and, come to think
@@ -365,7 +360,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/lisp/gnus/smime.el b/lisp/gnus/smime.el
index ac1e0810417..87b5551d31c 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -119,7 +119,7 @@
;;; Code:
(require 'dig)
-
+(require 'gnutls)
(require 'password-cache)
(eval-when-compile (require 'cl-lib))
@@ -149,10 +149,11 @@ certificate."
:type '(choice (const :tag "none" nil)
directory))
-(defcustom smime-CA-file nil
- "Files containing certificates for CAs you trust.
-File should contain certificates in PEM format."
- :version "22.1"
+(defcustom smime-CA-file (car (gnutls-trustfiles))
+ "File containing certificates for CAs you trust.
+The file should contain certificates in PEM format. By default,
+this is initialized from the `gnutls-trusfiles' variable."
+ :version "29.1"
:type '(choice (const :tag "none" nil)
file))
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index b0d258d67a5..084eb3d7745 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -189,7 +189,7 @@ When using `spam-stat-process-spam-directory' or
been touched in this many days will be considered. Without
this filter, re-training spam-stat with several thousand messages
will start to take a very long time."
- :type 'number)
+ :type 'integer)
(defvar spam-stat-last-saved-at nil
"Time stamp of last change of spam-stat-file on this run")
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index 297576288bb..5af29c0a246 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -852,7 +852,7 @@ The value nil means that the check does not yield a decision, and
so, that further checks are needed. The value t means that the
message is definitely not spam, and that further spam checks
should be inhibited. Otherwise, a mailgroup name or the symbol
-'spam (depending on `spam-split-symbolic-return') is returned where
+`spam' (depending on `spam-split-symbolic-return') is returned where
the mail should go, and further checks are also inhibited. The
usual mailgroup name is the value of `spam-split-group', meaning
that the message is definitely a spam."
diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el
index c5a9a93482c..1a6d374db09 100644
--- a/lisp/help-at-pt.el
+++ b/lisp/help-at-pt.el
@@ -81,25 +81,37 @@ If this produces no string either, return nil."
(echo (help-at-pt-string)))
(if (and kbd (not (eq kbd t))) kbd echo)))
+(declare-function widget-describe "wid-edit" (&optional widget-or-pos))
+(declare-function widget-at "wid-edit" (&optional pos))
+
;;;###autoload
-(defun display-local-help (&optional arg)
+(defun display-local-help (&optional inhibit-warning describe-button)
"Display local help in the echo area.
-This displays a short help message, namely the string produced by
-the `kbd-help' property at point. If `kbd-help' does not produce
-a string, but the `help-echo' property does, then that string is
-printed instead.
+This command, by default, displays a short help message, namely
+the string produced by the `kbd-help' property at point. If
+`kbd-help' does not produce a string, but the `help-echo'
+property does, then that string is printed instead.
The string is passed through `substitute-command-keys' before it
is displayed.
-A numeric argument ARG prevents display of a message in case
-there is no help. While ARG can be used interactively, it is
-mainly meant for use from Lisp."
- (interactive "P")
+If INHIBIT-WARNING is non-nil, this prevents display of a message
+in case there is no help.
+
+If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and
+there's a button/widget at point, pop a buffer describing that
+button/widget instead."
+ (interactive (list nil current-prefix-arg))
(let ((help (help-at-pt-kbd-string)))
- (if help
- (message "%s" (substitute-command-keys help))
- (if (not arg) (message "No local help at point")))))
+ (cond
+ ((and describe-button (button-at (point)))
+ (button-describe))
+ ((and describe-button (widget-at (point)))
+ (widget-describe))
+ (help
+ (message "%s" (substitute-command-keys help)))
+ ((not inhibit-warning)
+ (message "No local help at point")))))
(defvar help-at-pt-timer nil
"Non-nil means that a timer is set that checks for local help.
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index d408efeeb9e..fbd40158701 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -33,6 +33,7 @@
;;; Code:
(require 'cl-lib)
+(require 'seq)
(require 'help-mode)
(require 'radix-tree)
(eval-when-compile (require 'subr-x)) ;For when-let.
@@ -132,6 +133,19 @@ with the current prefix. The files are chosen according to
:group 'help
:version "26.3")
+(defcustom help-enable-variable-value-editing nil
+ "If non-nil, allow editing values in *Help* buffers.
+
+To edit the value of a variable, use \\[describe-variable] to
+display a \"*Help*\" buffer, move point after the text
+\"Its value is\" and type \\`e'.
+
+Values that aren't readable by the Emacs Lisp reader can't be
+edited even if this option is enabled."
+ :type 'boolean
+ :group 'help
+ :version "29.1")
+
(defcustom help-enable-symbol-autoload nil
"Perform autoload if docs are missing from autoload objects."
:type 'boolean
@@ -395,7 +409,7 @@ if the variable `help-downcase-arguments' is non-nil."
;; `describe-face' (instead of `describe-simplify-lib-file-name').
;;;###autoload
-(defun find-lisp-object-file-name (object type)
+(defun find-lisp-object-file-name (object type &optional also-c-source)
"Guess the file that defined the Lisp object OBJECT, of type TYPE.
OBJECT should be a symbol associated with a function, variable, or face;
alternatively, it can be a function definition.
@@ -406,8 +420,13 @@ If TYPE is not a symbol, search for a function definition.
The return value is the absolute name of a readable file where OBJECT is
defined. If several such files exist, preference is given to a file
found via `load-path'. The return value can also be `C-source', which
-means that OBJECT is a function or variable defined in C. If no
-suitable file is found, return nil."
+means that OBJECT is a function or variable defined in C, but
+it's currently unknown where. If no suitable file is found,
+return nil.
+
+If ALSO-C-SOURCE is non-nil, instead of returning `C-source',
+this function will attempt to locate the definition of OBJECT in
+the C sources, too."
(let* ((autoloaded (autoloadp type))
(file-name (or (and autoloaded (nth 1 type))
(symbol-file
@@ -444,14 +463,18 @@ suitable file is found, return nil."
(cond
((and (not file-name) (subrp type))
;; A built-in function. The form is from `describe-function-1'.
- (if (get-buffer " *DOC*")
+ (if (or (get-buffer " *DOC*")
+ (and also-c-source
+ (get-buffer-create " *DOC*")))
(help-C-file-name type 'subr)
'C-source))
((and (not file-name) (symbolp object)
(eq type 'defvar)
(integerp (get object 'variable-documentation)))
;; A variable defined in C. The form is from `describe-variable'.
- (if (get-buffer " *DOC*")
+ (if (or (get-buffer " *DOC*")
+ (and also-c-source
+ (get-buffer-create " *DOC*")))
(help-C-file-name object 'var)
'C-source))
((not (stringp file-name))
@@ -496,9 +519,16 @@ suitable file is found, return nil."
(let ((pt2 (with-current-buffer standard-output (point)))
(remapped (command-remapping function)))
(unless (memq remapped '(ignore undefined))
- (let ((keys (where-is-internal
- (or remapped function) overriding-local-map nil nil))
- non-modified-keys)
+ (let* ((all-keys (where-is-internal
+ (or remapped function) overriding-local-map nil nil))
+ (seps (seq-group-by
+ (lambda (key)
+ (and (vectorp key)
+ (eq (elt key 0) 'menu-bar)))
+ all-keys))
+ (keys (cdr (assq nil seps)))
+ (menus (cdr (assq t seps)))
+ non-modified-keys)
(if (and (eq function 'self-insert-command)
(vectorp (car-safe keys))
(consp (aref (car keys) 0)))
@@ -522,29 +552,85 @@ suitable file is found, return nil."
;; don't mention them one by one.
(if (< (length non-modified-keys) 10)
(with-current-buffer standard-output
- (insert (mapconcat #'help--key-description-fontified
- keys ", ")))
+ (help-fns--insert-bindings keys))
(dolist (key non-modified-keys)
(setq keys (delq key keys)))
(if keys
(with-current-buffer standard-output
- (insert (mapconcat #'help--key-description-fontified
- keys ", "))
+ (help-fns--insert-bindings keys)
(insert ", and many ordinary text characters"))
- (princ "many ordinary text characters"))))
+ (princ "many ordinary text characters."))))
(when (or remapped keys non-modified-keys)
(princ ".")
- (terpri)))))
+ (terpri)))
- (with-current-buffer standard-output
- (fill-region-as-paragraph pt2 (point))
- (unless (looking-back "\n\n" (- (point) 2))
- (terpri))))))
+ (with-current-buffer standard-output
+ (fill-region-as-paragraph pt2 (point))
+ (unless (bolp)
+ (insert "\n"))
+ (when menus
+ (let ((start (point)))
+ (help-fns--insert-menu-bindings
+ menus
+ (concat "It can " (and keys "also ")
+ "be invoked from the menu: "))
+ (fill-region-as-paragraph start (point))))
+ (ensure-empty-lines)))))))
+
+(defun help-fns--insert-bindings (keys)
+ (seq-do-indexed (lambda (key i)
+ (insert
+ (cond ((zerop i) "")
+ ((= i (1- (length keys))) " and ")
+ (t ", ")))
+ (insert (help--key-description-fontified key)))
+ keys))
+
+(defun help-fns--insert-menu-bindings (menus heading)
+ (seq-do-indexed
+ (lambda (menu i)
+ (insert
+ (cond ((zerop i) "")
+ ((= i (1- (length menus))) " and ")
+ (t ", ")))
+ (let ((map (lookup-key global-map (seq-take menu 1)))
+ (start (point)))
+ (seq-do-indexed
+ (lambda (entry level)
+ (when (symbolp map)
+ (setq map (symbol-function map)))
+ (when-let ((elem (assq entry (cdr map))))
+ (when heading
+ (insert heading)
+ (setq heading nil start (point)))
+ (when (> level 0)
+ (insert
+ (if (char-displayable-p ?→)
+ " → "
+ " => ")))
+ (if (eq (nth 1 elem) 'menu-item)
+ (progn
+ (insert (nth 2 elem))
+ (setq map (cadddr elem)))
+ (insert (nth 1 elem))
+ (setq map (cddr elem)))))
+ (cdr (seq-into menu 'list)))
+ (put-text-property start (point) 'face 'help-key-binding)))
+ menus))
(defun help-fns--compiler-macro (function)
- (let ((handler (function-get function 'compiler-macro)))
+ (pcase-dolist (`(,type . ,handler)
+ (list (cons "compiler macro"
+ (function-get function 'compiler-macro))
+ (cons (substitute-command-keys "`byte-compile' property")
+ (function-get function 'byte-compile))
+ (cons "byte-code optimizer"
+ (function-get function 'byte-optimizer))))
(when handler
- (insert " This function has a compiler macro")
+ (if (bolp)
+ (insert " This function has a ")
+ (insert " and a "))
+ (insert type)
(if (symbolp handler)
(progn
(insert (format-message " `%s'" handler))
@@ -559,8 +645,17 @@ suitable file is found, return nil."
(save-excursion
(re-search-backward (substitute-command-keys "`\\([^`']+\\)'")
nil t)
- (help-xref-button 1 'help-function-cmacro function lib)))))
- (insert ".\n"))))
+ (help-xref-button 1 'help-function-cmacro function lib)))))))
+ (unless (bolp)
+ (insert ". See "
+ (buttonize "the manual"
+ (lambda (_) (info "(elisp)Advice and Byte Code")))
+ " for details.\n")
+ (save-restriction
+ (let ((fill-prefix " "))
+ (narrow-to-region (line-beginning-position -1) (point))
+ (fill-region (point-min) (point-max)))
+ (goto-char (point-max)))))
(defun help-fns--signature (function doc real-def real-function buffer)
"Insert usage at point and return docstring. With highlighting."
@@ -630,19 +725,22 @@ suitable file is found, return nil."
;; Ignore lambda constructs, keyboard macros, etc.
(let* ((obsolete (and (symbolp function)
(get function 'byte-obsolete-info)))
- (use (car obsolete)))
+ (use (car obsolete))
+ (start (point)))
(when obsolete
- (insert " This "
+ (insert "This "
(if (eq (car-safe (symbol-function function)) 'macro)
"macro"
"function")
" is obsolete")
(when (nth 2 obsolete)
(insert (format " since %s" (nth 2 obsolete))))
- (insert (cond ((stringp use) (concat ";\n " use))
- (use (format-message ";\n use `%s' instead." use))
+ (insert (cond ((stringp use) (concat "; " use))
+ (use (format-message "; use `%s' instead." use))
(t "."))
- "\n"))))
+ "\n")
+ (fill-region-as-paragraph start (point))
+ (ensure-empty-lines))))
(add-hook 'help-fns-describe-function-functions
#'help-fns--globalized-minor-mode)
@@ -653,19 +751,9 @@ suitable file is found, return nil."
(terpri)))
;; We could use `symbol-file' but this is a wee bit more efficient.
-(defun help-fns--autoloaded-p (function file)
- "Return non-nil if FUNCTION has previously been autoloaded.
-FILE is the file where FUNCTION was probably defined."
- (let* ((file (file-name-sans-extension (file-truename file)))
- (load-hist load-history)
- (target (cons t function))
- found)
- (while (and load-hist (not found))
- (and (stringp (caar load-hist))
- (equal (file-name-sans-extension (caar load-hist)) file)
- (setq found (member target (cdar load-hist))))
- (setq load-hist (cdr load-hist)))
- found))
+(defun help-fns--autoloaded-p (function)
+ "Return non-nil if FUNCTION has previously been autoloaded."
+ (seq-some #'autoloadp (get function 'function-history)))
(defun help-fns--interactive-only (function)
"Insert some help blurb if FUNCTION should only be used interactively."
@@ -719,21 +807,23 @@ FILE is the file where FUNCTION was probably defined."
(erase-buffer)
(insert-file-contents f)
(goto-char (point-min))
- (search-forward "\n*")
- (while (re-search-forward re nil t)
- (let ((pos (match-beginning 0)))
- (save-excursion
- ;; Almost all entries are of the form "* ... in Emacs NN.MM."
- ;; but there are also a few in the form "* Emacs NN.MM is a bug
- ;; fix release ...".
- (if (not (re-search-backward "^\\* .* Emacs \\([0-9.]+[0-9]\\)"
- nil t))
- (message "Ref found in non-versioned section in %S"
- (file-name-nondirectory f))
- (let ((version (match-string 1)))
- (when (or (null first) (version< version first))
- (setq place (list f pos))
- (setq first version)))))))))
+ ;; Failed git merges can leave empty files that look like NEWS
+ ;; in etc. Don't error here.
+ (when (search-forward "\n*" nil t)
+ (while (re-search-forward re nil t)
+ (let ((pos (match-beginning 0)))
+ (save-excursion
+ ;; Almost all entries are of the form "* ... in Emacs NN.MM."
+ ;; but there are also a few in the form "* Emacs NN.MM is a bug
+ ;; fix release ...".
+ (if (not (re-search-backward "^\\* .* Emacs \\([0-9.]+[0-9]\\)"
+ nil t))
+ (message "Ref found in non-versioned section in %S"
+ (file-name-nondirectory f))
+ (let ((version (match-string 1)))
+ (when (or (null first) (version< version first))
+ (setq place (list f pos))
+ (setq first version))))))))))
(when first
(make-text-button first nil 'type 'help-news 'help-args place))))
@@ -775,9 +865,10 @@ FILE is the file where FUNCTION was probably defined."
(insert-text-button
(symbol-name group)
'action (lambda (_)
- (shortdoc-display-group group object))
+ (shortdoc-display-group group object
+ help-window-keep-selected))
'follow-link t
- 'help-echo (purecopy "mouse-1, RET: show documentation group")))
+ 'help-echo "mouse-1, RET: show documentation group"))
groups)
(insert (if (= (length groups) 1)
" group.\n"
@@ -829,11 +920,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
(symbol-name function)))))))
(real-def (cond
((and aliased (not (subrp def)))
- (let ((f real-function))
- (while (and (fboundp f)
- (symbolp (symbol-function f)))
- (setq f (symbol-function f)))
- f))
+ (car (function-alias-p real-function t)))
((subrp def) (intern (subr-name def)))
(t def))))
@@ -852,13 +939,13 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
"Print a line describing FUNCTION to `standard-output'."
(pcase-let* ((`(,_real-function ,def ,aliased ,real-def)
(help-fns--analyze-function function))
- (file-name (find-lisp-object-file-name function (if aliased 'defun
- def)))
+ (file-name (find-lisp-object-file-name
+ function (if aliased 'defun def)))
(beg (if (and (or (byte-code-function-p def)
(keymapp def)
(memq (car-safe def) '(macro lambda closure)))
(stringp file-name)
- (help-fns--autoloaded-p function file-name))
+ (help-fns--autoloaded-p function))
(concat
"an autoloaded " (if (commandp def)
"interactive "))
@@ -947,12 +1034,20 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
;;;###autoload
(defun describe-function-1 (function)
- (let ((pt1 (with-current-buffer (help-buffer) (point))))
+ (let ((pt1 (with-current-buffer standard-output (point))))
(help-fns-function-description-header function)
- (with-current-buffer (help-buffer)
- (fill-region-as-paragraph (save-excursion (goto-char pt1) (forward-line 0) (point))
- (point))))
- (terpri)(terpri)
+ (with-current-buffer standard-output
+ (let ((inhibit-read-only t))
+ (fill-region-as-paragraph
+ (save-excursion
+ (goto-char pt1)
+ (forward-line 0)
+ (point))
+ (point)
+ nil t)
+ (ensure-empty-lines))))
+
+ (help-fns--obsolete function)
(pcase-let* ((`(,real-function ,def ,_aliased ,real-def)
(help-fns--analyze-function function))
@@ -961,8 +1056,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
;; for invalid functions i.s.o. signaling an error.
(documentation function t)
;; E.g. an alias for a not yet defined function.
- ((invalid-function void-function) nil)))
- (key-bindings-buffer (current-buffer)))
+ ((invalid-function void-function) nil))))
;; If the function is autoloaded, and its docstring has
;; key substitution constructs, load the library.
@@ -979,7 +1073,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
(help-fns--signature
function doc-raw
(if (subrp def) (indirect-function real-def) real-def)
- real-function key-bindings-buffer)
+ real-function describe-function-orig-buffer)
;; E.g. an alias for a not yet defined function.
((invalid-function void-function) doc-raw))))
(help-fns--ensure-empty-line)
@@ -993,10 +1087,9 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
(set-buffer-file-coding-system 'utf-8)))))
;; Add defaults to `help-fns-describe-function-functions'.
-(add-hook 'help-fns-describe-function-functions #'help-fns--obsolete)
(add-hook 'help-fns-describe-function-functions #'help-fns--interactive-only)
(add-hook 'help-fns-describe-function-functions #'help-fns--parent-mode)
-(add-hook 'help-fns-describe-function-functions #'help-fns--compiler-macro)
+(add-hook 'help-fns-describe-function-functions #'help-fns--compiler-macro 100)
;; Variables
@@ -1140,24 +1233,28 @@ it is displayed along with the global value."
(let ((rep
(let ((print-quoted t)
(print-circle t))
- (cl-prin1-to-string val))))
- (if (and (symbolp val) (not (booleanp val)))
+ (cl-prin1-to-string val))))
+ (if (and (symbolp val) (not (booleanp val)))
(format-message "`%s'" rep)
- rep))))
+ rep)))
+ (start (point)))
(if (< (+ (length print-rep) (point) (- line-beg)) 68)
(insert " " print-rep)
(terpri)
(let ((buf (current-buffer)))
(with-temp-buffer
- (lisp-mode-variables nil)
+ (lisp-data-mode)
(set-syntax-table emacs-lisp-mode-syntax-table)
(insert print-rep)
(pp-buffer)
+ (font-lock-ensure)
(let ((pp-buffer (current-buffer)))
(with-current-buffer buf
(insert-buffer-substring pp-buffer)))))
;; Remove trailing newline.
(and (= (char-before) ?\n) (delete-char -1)))
+ (help-fns--editable-variable start (point)
+ variable val buffer)
(let* ((sv (get variable 'standard-value))
(origval (and (consp sv)
(condition-case nil
@@ -1177,6 +1274,8 @@ it is displayed along with the global value."
(save-restriction
(narrow-to-region from (point))
(save-excursion (pp-buffer)))
+ (help-fns--editable-variable from (point)
+ variable origval buffer)
(if (< (point) (+ from 20))
(delete-region (1- from) from)))))))
(terpri)
@@ -1209,7 +1308,9 @@ it is displayed along with the global value."
;; See previous comment for this function.
;; (help-xref-on-pp from (point))
(if (< (point) (+ from 20))
- (delete-region (1- from) from)))))))
+ (delete-region (1- from) from))
+ (help-fns--editable-variable
+ from (point) variable global-val buffer))))))
(terpri))
;; If the value is large, move it to the end.
@@ -1241,6 +1342,7 @@ it is displayed along with the global value."
alias 'variable-documentation))))
(with-current-buffer standard-output
+ (help-fns--var-obsolete variable)
(insert (or doc "Not documented as a variable.")))
;; Output the indented administrative bits.
@@ -1259,6 +1361,73 @@ it is displayed along with the global value."
;; Return the text we displayed.
(buffer-string))))))))
+(defun help-fns--editable-variable (start end variable value buffer)
+ (when (and (readablep value)
+ help-enable-variable-value-editing)
+ (add-text-properties
+ start end
+ (list 'help-echo "`e' to edit the value"
+ 'help-fns--edit-variable (list variable value buffer
+ (current-buffer))
+ 'keymap (define-keymap
+ :parent button-map
+ "e" #'help-fns-edit-variable)))))
+
+(defvar help-fns--edit-variable)
+
+(put 'help-fns-edit-variable 'disabled t)
+(defun help-fns-edit-variable ()
+ "Edit the variable under point."
+ (declare (completion ignore))
+ (interactive)
+ (let ((var (get-text-property (point) 'help-fns--edit-variable)))
+ (unless var
+ (error "No variable under point"))
+ (pop-to-buffer-same-window (format "*edit %s*" (nth 0 var)))
+ (prin1 (nth 1 var) (current-buffer))
+ (pp-buffer)
+ (goto-char (point-min))
+ (help-fns--edit-value-mode)
+ (insert (format ";; Edit the `%s' variable.\n" (nth 0 var))
+ (substitute-command-keys
+ ";; `\\[help-fns-edit-mode-done]' to update the value and exit; \
+`\\[help-fns-edit-mode-cancel]' to cancel.\n\n"))
+ (setq-local help-fns--edit-variable var)))
+
+(defvar-keymap help-fns--edit-value-mode-map
+ "C-c C-c" #'help-fns-edit-mode-done
+ "C-c C-k" #'help-fns-edit-mode-cancel)
+
+(define-derived-mode help-fns--edit-value-mode emacs-lisp-mode "Elisp"
+ :interactive nil)
+
+(defun help-fns-edit-mode-done (&optional kill)
+ "Update the value of the variable being edited and kill the edit buffer.
+If KILL (the prefix), don't update the value, but just kill the
+current buffer."
+ (interactive "P" help-fns--edit-value-mode)
+ (unless help-fns--edit-variable
+ (error "Invalid buffer"))
+ (goto-char (point-min))
+ (cl-destructuring-bind (variable _ buffer help-buffer)
+ help-fns--edit-variable
+ (unless (buffer-live-p buffer)
+ (error "Original buffer is gone; can't update"))
+ (unless kill
+ (let ((value (read (current-buffer))))
+ (with-current-buffer buffer
+ (set variable value))))
+ (kill-buffer (current-buffer))
+ (when (buffer-live-p help-buffer)
+ (with-current-buffer help-buffer
+ (revert-buffer)))))
+
+(defun help-fns-edit-mode-cancel ()
+ "Kill the edit buffer and cancel editing of the value.
+This cancels value editing without updating the value."
+ (interactive nil help-fns--edit-value-mode)
+ (help-fns-edit-mode-done t))
+
(defun help-fns--run-describe-functions (functions &rest args)
(with-current-buffer standard-output
(unless (bolp)
@@ -1375,19 +1544,21 @@ variable.\n")))
(princ watchpoints)
(terpri))))
-(add-hook 'help-fns-describe-variable-functions #'help-fns--var-obsolete)
(defun help-fns--var-obsolete (variable)
(let* ((obsolete (get variable 'byte-obsolete-variable))
- (use (car obsolete)))
+ (use (car obsolete))
+ (start (point)))
(when obsolete
- (princ " This variable is obsolete")
+ (insert "This variable is obsolete")
(if (nth 2 obsolete)
- (princ (format " since %s" (nth 2 obsolete))))
- (princ (cond ((stringp use) (concat ";\n " use))
- (use (format-message ";\n use `%s' instead."
- (car obsolete)))
- (t ".")))
- (terpri))))
+ (insert (format " since %s" (nth 2 obsolete))))
+ (insert (cond ((stringp use) (concat "; " use))
+ (use (format-message "; use `%s' instead."
+ (car obsolete)))
+ (t "."))
+ "\n")
+ (fill-region-as-paragraph start (point))
+ (ensure-empty-lines))))
(add-hook 'help-fns-describe-variable-functions #'help-fns--var-alias)
(defun help-fns--var-alias (variable)
@@ -1752,8 +1923,8 @@ variable with value KEYMAP."
The heuristic to determine which keymap is most likely to be
relevant to a user follows this order:
-1. 'keymap' text property at point
-2. 'local-map' text property at point
+1. `keymap' text property at point
+2. `local-map' text property at point
3. the `current-local-map'
This is used to set the default value for the interactive prompt
@@ -1772,7 +1943,10 @@ in `describe-keymap'. See also `Searching the Active Keymaps'."
When called interactively, prompt for a variable that has a
keymap value."
(interactive
- (let* ((km (help-fns--most-relevant-active-keymap))
+ (let* ((sym (symbol-at-point))
+ (km (or (and (keymapp (ignore-errors (symbol-value sym)))
+ sym)
+ (help-fns--most-relevant-active-keymap)))
(val (completing-read
(format-prompt "Keymap" km)
obarray
@@ -1851,107 +2025,96 @@ whose documentation describes the minor mode.
If called from Lisp with a non-nil BUFFER argument, display
documentation for the major and minor modes of that buffer."
(interactive "@")
- (let ((help-buffer-under-preparation t))
- (unless buffer (setq buffer (current-buffer)))
+ (unless buffer
+ (setq buffer (current-buffer)))
+ (let ((help-buffer-under-preparation t)
+ (local-minors (buffer-local-value 'local-minor-modes buffer)))
(help-setup-xref (list #'describe-mode buffer)
(called-interactively-p 'interactive))
;; For the sake of help-do-xref and help-xref-go-back,
;; don't switch buffers before calling `help-buffer'.
(with-help-window (help-buffer)
- (with-current-buffer buffer
- (let (minors)
- ;; Older packages do not register in minor-mode-list but only in
- ;; minor-mode-alist.
- (dolist (x minor-mode-alist)
- (setq x (car x))
- (unless (memq x minor-mode-list)
- (push x minor-mode-list)))
- ;; Find enabled minor mode we will want to mention.
- (dolist (mode minor-mode-list)
- ;; Document a minor mode if it is listed in minor-mode-alist,
- ;; non-nil, and has a function definition.
- (let ((fmode (or (get mode :minor-mode-function) mode)))
- (and (boundp mode) (symbol-value mode)
- (fboundp fmode)
- (let ((pretty-minor-mode
- (if (string-match "\\(\\(-minor\\)?-mode\\)?\\'"
- (symbol-name fmode))
- (capitalize
- (substring (symbol-name fmode)
- 0 (match-beginning 0)))
- fmode)))
- (push (list fmode pretty-minor-mode
- (format-mode-line (assq mode minor-mode-alist)))
- minors)))))
- ;; Narrowing is not a minor mode, but its indicator is part of
- ;; mode-line-modes.
- (when (buffer-narrowed-p)
- (push '(narrow-to-region "Narrow" " Narrow") minors))
- (setq minors
- (sort minors
- (lambda (a b) (string-lessp (cadr a) (cadr b)))))
- (when minors
- (princ "Enabled minor modes:\n")
- (make-local-variable 'help-button-cache)
- (with-current-buffer standard-output
- (dolist (mode minors)
- (let ((mode-function (nth 0 mode))
- (pretty-minor-mode (nth 1 mode))
- (indicator (nth 2 mode)))
- (save-excursion
- (goto-char (point-max))
- (princ "\n\f\n")
- (push (point-marker) help-button-cache)
- ;; Document the minor modes fully.
- (insert-text-button
- pretty-minor-mode 'type 'help-function
- 'help-args (list mode-function)
- 'button '(t))
- (princ (format " minor mode (%s):\n"
- (if (zerop (length indicator))
- "no indicator"
- (format "indicator%s"
- indicator))))
- (princ (help-split-fundoc (documentation mode-function)
- nil 'doc)))
- (insert-button pretty-minor-mode
- 'action (car help-button-cache)
- 'follow-link t
- 'help-echo "mouse-2, RET: show full information")
- (newline)))
- (forward-line -1)
- (fill-paragraph nil)
- (forward-line 1))
-
- (princ "\n(Information about these minor modes follows the major mode info.)\n\n"))
- ;; Document the major mode.
- (let ((mode mode-name))
- (with-current-buffer standard-output
- (let ((start (point)))
- (insert (format-mode-line mode nil nil buffer))
- (add-text-properties start (point) '(face bold)))))
- (princ " mode")
- (let* ((mode major-mode)
- (file-name (find-lisp-object-file-name mode nil)))
- (if (not file-name)
- (setq help-mode--current-data (list :symbol mode))
- (princ (format-message " defined in `%s'"
- (help-fns-short-filename file-name)))
- ;; Make a hyperlink to the library.
- (with-current-buffer standard-output
- (save-excursion
- (re-search-backward (substitute-command-keys "`\\([^`']+\\)'")
- nil t)
- (setq help-mode--current-data (list :symbol mode
- :file file-name))
- (help-xref-button 1 'help-function-def mode file-name)))))
- (let ((fundoc (help-split-fundoc (documentation major-mode) nil 'doc)))
- (with-current-buffer standard-output
- (insert ":\n")
- (insert fundoc)
- (insert (help-fns--list-local-commands))))))))
- ;; For the sake of IELM and maybe others
- nil)
+ (with-current-buffer (help-buffer)
+ ;; Add the local minor modes at the start.
+ (when local-minors
+ (insert (format "Minor mode%s enabled in this buffer:"
+ (if (length> local-minors 1)
+ "s" "")))
+ (describe-mode--minor-modes local-minors))
+
+ ;; Document the major mode.
+ (let ((major (buffer-local-value 'major-mode buffer)))
+ (insert "The major mode is "
+ (buttonize
+ (propertize (format-mode-line
+ (buffer-local-value 'mode-name buffer)
+ nil nil buffer)
+ 'face 'bold)
+ (lambda (_)
+ (describe-function major))))
+ (insert " mode")
+ (when-let ((file-name (find-lisp-object-file-name major nil)))
+ (insert (format " defined in %s:\n\n"
+ (buttonize
+ (help-fns-short-filename file-name)
+ (lambda (_)
+ (help-function-def--button-function
+ major file-name))))))
+ (insert (help-split-fundoc (documentation major) nil 'doc)
+ (with-current-buffer buffer
+ (help-fns--list-local-commands)))
+ (ensure-empty-lines 1)
+
+ ;; Insert the global minor modes after the major mode.
+ (when global-minor-modes
+ (insert (format "Global minor mode%s enabled:"
+ (if (length> global-minor-modes 1)
+ "s" "")))
+ (describe-mode--minor-modes global-minor-modes)
+ (when (re-search-forward "^\f")
+ (beginning-of-line)
+ (ensure-empty-lines 1)))
+ ;; For the sake of IELM and maybe others
+ nil)))))
+
+(defun describe-mode--minor-modes (modes)
+ (dolist (mode (seq-sort #'string< modes))
+ (let ((pretty-minor-mode
+ (capitalize
+ (replace-regexp-in-string
+ "\\(\\(-minor\\)?-mode\\)?\\'" ""
+ (symbol-name mode)))))
+ (insert
+ " "
+ (buttonize
+ pretty-minor-mode
+ (lambda (mode)
+ (goto-char (point-min))
+ (text-property-search-forward
+ 'help-minor-mode mode t)
+ (beginning-of-line))
+ mode))
+ (save-excursion
+ (goto-char (point-max))
+ (insert "\n\n\f\n")
+ ;; Document the minor modes fully.
+ (insert (buttonize
+ (propertize pretty-minor-mode 'help-minor-mode mode)
+ (lambda (mode)
+ (describe-function mode))
+ mode))
+ (let ((indicator
+ (format-mode-line (assq mode minor-mode-alist))))
+ (insert (format " minor mode (%s):\n"
+ (if (zerop (length indicator))
+ "no indicator"
+ (format "indicator%s"
+ indicator)))))
+ (insert (help-split-fundoc (documentation mode) nil 'doc)))))
+ (forward-line -1)
+ (fill-paragraph nil)
+ (forward-paragraph 1)
+ (ensure-empty-lines 1))
(defun help-fns--list-local-commands ()
(let ((functions nil))
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 894b2a50aa7..8b5e48edad1 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -31,24 +31,23 @@
(require 'cl-lib)
-(defvar help-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map (make-composed-keymap button-buffer-map
- special-mode-map))
- (define-key map "n" 'help-goto-next-page)
- (define-key map "p" 'help-goto-previous-page)
- (define-key map "l" 'help-go-back)
- (define-key map "r" 'help-go-forward)
- (define-key map "\C-c\C-b" 'help-go-back)
- (define-key map "\C-c\C-f" 'help-go-forward)
- (define-key map [XF86Back] 'help-go-back)
- (define-key map [XF86Forward] 'help-go-forward)
- (define-key map "\C-c\C-c" 'help-follow-symbol)
- (define-key map "s" 'help-view-source)
- (define-key map "i" 'help-goto-info)
- (define-key map "c" 'help-customize)
- map)
- "Keymap for Help mode.")
+(defvar-keymap help-mode-map
+ :doc "Keymap for Help mode."
+ :parent (make-composed-keymap button-buffer-map
+ special-mode-map)
+ "n" #'help-goto-next-page
+ "p" #'help-goto-previous-page
+ "l" #'help-go-back
+ "r" #'help-go-forward
+ "C-c C-b" #'help-go-back
+ "C-c C-f" #'help-go-forward
+ "<XF86Back>" #'help-go-back
+ "<XF86Forward>" #'help-go-forward
+ "C-c C-c" #'help-follow-symbol
+ "s" #'help-view-source
+ "I" #'help-goto-lispref-info
+ "i" #'help-goto-info
+ "c" #'help-customize)
(easy-menu-define help-mode-menu help-mode-map
"Menu for Help mode."
@@ -267,7 +266,9 @@ The format is (FUNCTION ARGS...).")
(let* ((location
(find-function-search-for-symbol fun type file))
(position (cdr location)))
- (pop-to-buffer (car location))
+ (if help-window-keep-selected
+ (pop-to-buffer-same-window (car location))
+ (pop-to-buffer (car location)))
(run-hooks 'find-function-after-hook)
(if position
(progn
@@ -293,7 +294,10 @@ The format is (FUNCTION ARGS...).")
(setq file (locate-library file t))
(if (and file (file-readable-p file))
(progn
- (pop-to-buffer (find-file-noselect file))
+ (if help-window-keep-selected
+ (pop-to-buffer-same-window
+ (find-file-noselect file))
+ (pop-to-buffer (find-file-noselect file)))
(widen)
(goto-char (point-min))
(if (re-search-forward
@@ -312,7 +316,9 @@ The format is (FUNCTION ARGS...).")
(setq file (help-C-file-name var 'var)))
(let* ((location (find-variable-noselect var file))
(position (cdr location)))
- (pop-to-buffer (car location))
+ (if help-window-keep-selected
+ (pop-to-buffer-same-window (car location))
+ (pop-to-buffer (car location)))
(run-hooks 'find-function-after-hook)
(if position
(progn
@@ -333,7 +339,9 @@ The format is (FUNCTION ARGS...).")
(let* ((location
(find-function-search-for-symbol fun 'defface file))
(position (cdr location)))
- (pop-to-buffer (car location))
+ (if help-window-keep-selected
+ (pop-to-buffer-same-window (car location))
+ (pop-to-buffer (car location)))
(if position
(progn
;; Widen the buffer if necessary to go to this position.
@@ -375,7 +383,9 @@ The format is (FUNCTION ARGS...).")
:supertype 'help-xref
'help-function
(lambda (file pos)
- (view-buffer-other-window (find-file-noselect file))
+ (if help-window-keep-selected
+ (view-buffer (find-file-noselect file))
+ (view-buffer-other-window (find-file-noselect file)))
(goto-char pos))
'help-echo (purecopy "mouse-2, RET: show corresponding NEWS announcement"))
@@ -392,7 +402,8 @@ The format is (FUNCTION ARGS...).")
;;;###autoload
(define-derived-mode help-mode special-mode "Help"
"Major mode for viewing help text and navigating references in it.
-Entry to this mode runs the normal hook `help-mode-hook'.
+Also see the `help-enable-variable-value-editing' variable.
+
Commands:
\\{help-mode-map}"
(setq-local revert-buffer-function
@@ -402,17 +413,21 @@ Commands:
help-mode-tool-bar-map)
(setq-local help-mode--current-data nil)
(setq-local bookmark-make-record-function
- #'help-bookmark-make-record))
+ #'help-bookmark-make-record)
+ (unless search-default-mode
+ (isearch-fold-quotes-mode)))
;;;###autoload
(defun help-mode-setup ()
"Enter Help mode in the current buffer."
+ (declare (obsolete nil "29.1"))
(help-mode)
(setq buffer-read-only nil))
;;;###autoload
(defun help-mode-finish ()
"Finalize Help mode setup in current buffer."
+ (declare (obsolete nil "29.1"))
(when (derived-mode-p 'help-mode)
(setq buffer-read-only t)
(help-make-xrefs (current-buffer))))
@@ -437,6 +452,7 @@ Commands:
"\\(symbol\\|program\\|property\\)\\|" ; Don't link
"\\(source \\(?:code \\)?\\(?:of\\|for\\)\\)\\)"
"[ \t\n]+\\)?"
+ "\\(\\\\\\+\\)?"
"['`‘]\\(\\(?:\\sw\\|\\s_\\)+\\|`\\)['’]"))
"Regexp matching doc string references to symbols.
@@ -497,17 +513,16 @@ restore it properly when going back."
;;;###autoload
(defun help-buffer ()
"Return the name of a buffer for inserting help.
-If `help-xref-following' is non-nil, this is the name of the
-current buffer. Signal an error if this buffer is not derived
-from `help-mode'.
+If `help-xref-following' is non-nil and the current buffer is
+derived from `help-mode', this is the name of the current buffer.
+
Otherwise, return \"*Help*\", creating a buffer with that name if
it does not already exist."
- (buffer-name ;for with-output-to-temp-buffer
- (if (not help-xref-following)
- (get-buffer-create "*Help*")
- (unless (derived-mode-p 'help-mode)
- (error "Current buffer is not in Help mode"))
- (current-buffer))))
+ (buffer-name ;for with-output-to-temp-buffer
+ (if (and help-xref-following
+ (derived-mode-p 'help-mode))
+ (current-buffer)
+ (get-buffer-create "*Help*"))))
(defvar describe-symbol-backends
`((nil ,#'fboundp ,(lambda (s _b _f) (describe-function s)))
@@ -526,6 +541,12 @@ Each element has the form (NAME TESTFUN DESCFUN) where:
and a frame), inserts the description of that symbol in the current buffer
and returns that text as well.")
+(defcustom help-clean-buttons nil
+ "If non-nil, remove quotes around link buttons."
+ :version "29.1"
+ :type 'boolean
+ :group 'help)
+
;;;###autoload
(defun help-make-xrefs (&optional buffer)
"Parse and hyperlink documentation cross-references in the given BUFFER.
@@ -613,27 +634,28 @@ that."
;; Quoted symbols
(save-excursion
(while (re-search-forward help-xref-symbol-regexp nil t)
- (let* ((data (match-string 8))
- (sym (intern-soft data)))
- (if sym
- (cond
- ((match-string 3) ; `variable' &c
- (and (or (boundp sym) ; `variable' doesn't ensure
+ (when-let ((sym (intern-soft (match-string 9))))
+ (if (match-string 8)
+ (delete-region (match-beginning 8)
+ (match-end 8))
+ (cond
+ ((match-string 3) ; `variable' &c
+ (and (or (boundp sym) ; `variable' doesn't ensure
; it's actually bound
- (get sym 'variable-documentation))
- (help-xref-button 8 'help-variable sym)))
- ((match-string 4) ; `function' &c
- (and (fboundp sym) ; similarly
- (help-xref-button 8 'help-function sym)))
- ((match-string 5) ; `face'
- (and (facep sym)
- (help-xref-button 8 'help-face sym)))
- ((match-string 6)) ; nothing for `symbol'
- ((match-string 7)
- (help-xref-button 8 'help-function-def sym))
- ((cl-some (lambda (x) (funcall (nth 1 x) sym))
- describe-symbol-backends)
- (help-xref-button 8 'help-symbol sym)))))))
+ (get sym 'variable-documentation))
+ (help-xref-button 9 'help-variable sym)))
+ ((match-string 4) ; `function' &c
+ (and (fboundp sym) ; similarly
+ (help-xref-button 9 'help-function sym)))
+ ((match-string 5) ; `face'
+ (and (facep sym)
+ (help-xref-button 9 'help-face sym)))
+ ((match-string 6)) ; nothing for `symbol'
+ ((match-string 7)
+ (help-xref-button 9 'help-function-def sym))
+ ((cl-some (lambda (x) (funcall (nth 1 x) sym))
+ describe-symbol-backends)
+ (help-xref-button 9 'help-symbol sym)))))))
;; An obvious case of a key substitution:
(save-excursion
(while (re-search-forward
@@ -673,12 +695,26 @@ that."
MATCH-NUMBER is the subexpression of interest in the last matched
regexp. TYPE is the type of button to use. Any remaining arguments are
passed to the button's help-function when it is invoked.
-See `help-make-xrefs'."
+See `help-make-xrefs'.
+
+This function removes quotes surrounding the match if the
+variable `help-clean-buttons' is non-nil."
;; Don't mung properties we've added specially in some instances.
- (unless (button-at (match-beginning match-number))
- (make-text-button (match-beginning match-number)
- (match-end match-number)
- 'type type 'help-args args)))
+ (let ((beg (match-beginning match-number))
+ (end (match-end match-number)))
+ (unless (button-at beg)
+ (make-text-button beg end 'type type 'help-args args)
+ (when (and help-clean-buttons
+ (> beg (point-min))
+ (save-excursion
+ (goto-char (1- beg))
+ (looking-at "['`‘]"))
+ (< end (point-max))
+ (save-excursion
+ (goto-char end)
+ (looking-at "['’]")))
+ (delete-region end (1+ end))
+ (delete-region (1- beg) beg)))))
;;;###autoload
(defun help-insert-xref-button (string type &rest args)
@@ -817,7 +853,16 @@ The help buffers are divided into \"pages\" by the ^L character."
(unless help-mode--current-data
(error "No symbol to look up in the current buffer"))
(info-lookup-symbol (plist-get help-mode--current-data :symbol)
- 'emacs-lisp-mode))
+ 'emacs-lisp-mode
+ help-window-keep-selected))
+
+(defun help-goto-lispref-info ()
+ "View the Emacs Lisp manual *info* node of the current help item."
+ (interactive nil help-mode)
+ (unless help-mode--current-data
+ (error "No symbol to look up in the current buffer"))
+ (info-lookup-symbol (plist-get help-mode--current-data :symbol)
+ 'emacs-lisp-only))
(defun help-customize ()
"Customize variable or face whose doc string is shown in the current buffer."
@@ -927,6 +972,7 @@ BOOKMARK is a bookmark name or a bookmark record."
(pop-to-buffer "*Help*")
(goto-char position)))
+(put 'help-bookmark-jump 'bookmark-handler-type "Help")
(provide 'help-mode)
diff --git a/lisp/help.el b/lisp/help.el
index b142cce845c..d7ee1a84a43 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -392,16 +392,23 @@ If that doesn't give a function, return nil."
The prefix described consists of all but the last event
of the key sequence that ran this command."
(interactive)
- (let ((key (this-command-keys)))
- (describe-bindings
- (if (stringp key)
- (substring key 0 (1- (length key)))
- (let ((prefix (make-vector (1- (length key)) nil))
- (i 0))
- (while (< i (length prefix))
- (aset prefix i (aref key i))
- (setq i (1+ i)))
- prefix)))))
+ (let* ((key (this-command-keys))
+ (prefix
+ (if (stringp key)
+ (substring key 0 (1- (length key)))
+ (let ((prefix (make-vector (1- (length key)) nil))
+ (i 0))
+ (while (< i (length prefix))
+ (aset prefix i (aref key i))
+ (setq i (1+ i)))
+ prefix))))
+ (describe-bindings prefix)
+ (with-current-buffer (help-buffer)
+ (when (< (buffer-size) 10)
+ (let ((inhibit-read-only t))
+ (insert (format "No commands with a binding that start with %s."
+ (help--key-description-fontified prefix))))))))
+
;; Make C-h after a prefix, when not specifically bound,
;; run describe-prefix-bindings.
(setq prefix-help-command 'describe-prefix-bindings)
@@ -453,8 +460,8 @@ With argument, display info only for the selected version."
((< vn 18) "NEWS.1-17")
(t (format "NEWS.%d" vn))))
res)
- (view-file (expand-file-name file data-directory))
- (widen)
+ (find-file (expand-file-name file data-directory))
+ (emacs-news-view-mode)
(goto-char (point-min))
(when (stringp version)
(when (re-search-forward
@@ -621,7 +628,7 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
(enable-recursive-minibuffers t)
val)
(setq val (completing-read (format-prompt "Where is command" fn)
- obarray 'commandp t nil nil
+ obarray #'commandp t nil nil
(and fn (symbol-name fn))))
(list (unless (equal val "") (intern val))
current-prefix-arg)))
@@ -650,15 +657,21 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
(if insert
(if (> (length keys) 0)
(if remapped
- (format "%s (%s) (remapped from %s)"
- keys remapped symbol)
- (format "%s (%s)" keys symbol))
+ (format "%s, remapped to %s (%s)"
+ symbol remapped keys)
+ (format "%s (%s)" symbol keys))
(format "M-x %s RET" symbol))
(if (> (length keys) 0)
(if remapped
- (format "%s is remapped to %s which is on %s"
- symbol remapped keys)
- (format "%s is on %s" symbol keys))
+ (if (eq symbol (symbol-function definition))
+ (format
+ "%s, which is remapped to %s, which is on %s"
+ symbol remapped keys)
+ (format "%s is remapped to %s, which is on %s"
+ symbol remapped keys))
+ (if (eq symbol (symbol-function definition))
+ (format "%s, which is on %s" symbol keys)
+ (format "%s is on %s" symbol keys)))
;; If this is the command the user asked about,
;; and it is not on any key, say so.
;; For other symbols, its aliases, say nothing
@@ -667,7 +680,9 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
(format "%s is not on any key" symbol)))))
(when string
(unless (eq symbol definition)
- (princ ";\n its alias "))
+ (if (eq definition (symbol-function symbol))
+ (princ ";\n its alias ")
+ (princ ";\n it's an alias for ")))
(princ string)))))
nil)
@@ -859,7 +874,7 @@ with `mouse-movement' events."
(memq 'down last-modifiers)
;; After a click, see if a double click is on the way.
(and (memq 'click last-modifiers)
- (not (sit-for (/ double-click-time 1000.0) t))))
+ (not (sit-for (/ (mouse-double-click-time) 1000.0) t))))
(let* ((seq (read-key-sequence "\
Describe the following key, mouse click, or menu item: "
nil nil 'can-return-switch-frame))
@@ -888,6 +903,9 @@ Describe the following key, mouse click, or menu item: "
(setq yank-menu (copy-sequence saved-yank-menu))
(fset 'yank-menu (cons 'keymap yank-menu))))))
+;; Defined in help-fns.el.
+(defvar describe-function-orig-buffer)
+
(defun describe-key (&optional key-list buffer up-event)
"Display documentation of the function invoked by KEY-LIST.
KEY-LIST can be any kind of a key sequence; it can include keyboard events,
@@ -899,6 +917,12 @@ While reading KEY-LIST interactively, this command temporarily enables
menu items or tool-bar buttons that are disabled to allow getting help
on them.
+Interactively, this command can't describe prefix commands, but
+will always wait for the user to type the complete key sequence.
+For instance, entering \"C-x\" will wait until the command has
+been completed, but `M-: (describe-key (kbd \"C-x\")) RET' will
+tell you what this prefix command is bound to.
+
BUFFER is the buffer in which to lookup those keys; it defaults to the
current buffer."
(declare (advertised-calling-convention (key-list &optional buffer) "27.1"))
@@ -912,6 +936,7 @@ current buffer."
(setq buffer nil))
(let* ((help-buffer-under-preparation t)
(buf (or buffer (current-buffer)))
+ (describe-function-orig-buffer buf)
(on-link
(mapcar (lambda (kr)
(let ((raw (cdr kr)))
@@ -945,16 +970,16 @@ current buffer."
(with-help-window (help-buffer)
(when (> (length info-list) 1)
;; FIXME: Make this into clickable hyperlinks.
- (princ "There were several key-sequences:\n\n")
- (princ (mapconcat (lambda (info)
- (pcase-let ((`(,_seq ,brief-desc ,_defn ,_locus)
- info))
- (concat " " brief-desc)))
- info-list
- "\n"))
+ (insert "There were several key-sequences:\n\n")
+ (insert (mapconcat (lambda (info)
+ (pcase-let ((`(,_seq ,brief-desc ,_defn ,_locus)
+ info))
+ (concat " " brief-desc)))
+ info-list
+ "\n"))
(when (delq nil on-link)
- (princ "\n\nThose are influenced by `mouse-1-click-follows-link'"))
- (princ "\n\nThey're all described below."))
+ (insert "\n\nThose are influenced by `mouse-1-click-follows-link'"))
+ (insert "\n\nThey're all described below."))
(pcase-dolist (`(,_seq ,brief-desc ,defn ,locus)
info-list)
(when defn
@@ -962,10 +987,10 @@ current buffer."
(with-current-buffer standard-output
(insert "\n\n" (make-separator-line) "\n")))
- (princ brief-desc)
+ (insert brief-desc)
(when locus
- (princ (format " (found in %s)" locus)))
- (princ ", which is ")
+ (insert (format " (found in %s)" locus)))
+ (insert ", which is ")
(describe-function-1 defn)))))))
(defun search-forward-help-for-help ()
@@ -1076,7 +1101,7 @@ strings done by `substitute-command-keys'."
:version "29.1"
:group 'help)
-(defun substitute-command-keys (string &optional no-face)
+(defun substitute-command-keys (string &optional no-face include-menus)
"Substitute key descriptions for command names in STRING.
Each substring of the form \\\\=[COMMAND] is replaced by either a
keystroke sequence that invokes COMMAND, or \"M-x COMMAND\" if COMMAND
@@ -1086,18 +1111,20 @@ unless the optional argument NO-FACE is non-nil.
Each substring of the form \\\\=`KEYBINDING' will be replaced by
KEYBINDING and use the `help-key-binding' face.
-Each substring of the form \\\\={MAPVAR} is replaced by a summary of
-the value of MAPVAR as a keymap. This summary is similar to the one
-produced by ‘describe-bindings’. The summary ends in two newlines
-(used by the helper function ‘help-make-xrefs’ to find the end of the
-summary).
+Each substring of the form \\\\={MAPVAR} is replaced by a summary
+of the value of MAPVAR as a keymap. This summary is similar to
+the one produced by `describe-bindings'. This will normally
+exclude menu bindings, but if the optional INCLUDE-MENUS argument
+is non-nil, also include menu bindings. The summary ends in two
+newlines (used by the helper function `help-make-xrefs' to find
+the end of the summary).
Each substring of the form \\\\=<MAPVAR> specifies the use of MAPVAR
as the keymap for future \\\\=[COMMAND] substrings.
Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
is replaced by right quote. Left and right quote characters are
-specified by ‘text-quoting-style’.
+specified by `text-quoting-style'.
\\\\== quotes the following character and is discarded; thus, \\\\==\\\\== puts \\\\==
into the output, \\\\==\\[ puts \\[ into the output, and \\\\==\\=` puts \\=` into the
@@ -1138,24 +1165,24 @@ Otherwise, return a new string."
(delete-char 2)
(ignore-errors
(forward-char 1)))
+ ;; 1C. \`f' is replaced with a fontified f.
((and (= (following-char) ?`)
(save-excursion
(prog1 (search-forward "'" nil t)
- (setq end-point (- (point) 2)))))
- (goto-char orig-point)
- (delete-char 2)
- (goto-char (1- end-point))
- (delete-char 1)
- ;; (backward-char 1)
- (let ((k (buffer-substring-no-properties orig-point (point))))
- (cond ((= (length k) 0)
- (error "Empty key sequence in substitution"))
- ((not (key-valid-p k))
- (error "Invalid key sequence in substitution: `%s'" k))))
- (add-text-properties orig-point (point)
- '( face help-key-binding
- font-lock-face help-key-binding)))
- ;; 1C. \[foo] is replaced with the keybinding.
+ (setq end-point (1- (point))))))
+ (let ((k (buffer-substring-no-properties (+ orig-point 2)
+ end-point)))
+ (when (or (key-valid-p k)
+ (string-match-p "\\`M-x " k))
+ (goto-char orig-point)
+ (delete-char 2)
+ (goto-char (- end-point 2)) ; nb. take deletion into account
+ (delete-char 1)
+ (unless no-face
+ (add-text-properties orig-point (point)
+ '( face help-key-binding
+ font-lock-face help-key-binding))))))
+ ;; 1D. \[foo] is replaced with the keybinding.
((and (= (following-char) ?\[)
(save-excursion
(prog1 (search-forward "]" nil t)
@@ -1199,7 +1226,7 @@ Otherwise, return a new string."
(help-mode--add-function-link key fun)
key)
key)))))))
- ;; 1D. \{foo} is replaced with a summary of the keymap
+ ;; 1E. \{foo} is replaced with a summary of the keymap
;; (symbol-value foo).
;; \<foo> just sets the keymap used for \[cmd].
((and (or (and (= (following-char) ?{)
@@ -1239,9 +1266,11 @@ Otherwise, return a new string."
(t
;; Get the list of active keymaps that precede this one.
;; If this one's not active, get nil.
- (let ((earlier-maps (cdr (memq this-keymap (reverse active-maps)))))
+ (let ((earlier-maps
+ (cdr (memq this-keymap (reverse active-maps)))))
(describe-map-tree this-keymap t (nreverse earlier-maps)
- nil nil t nil nil t))))))))
+ nil nil (not include-menus)
+ nil nil t))))))))
;; 2. Handle quotes.
((and (eq (text-quoting-style) 'curve)
(or (and (= (following-char) ?\`)
@@ -1259,7 +1288,8 @@ Otherwise, return a new string."
(defvar help--keymaps-seen nil)
(defun describe-map-tree (startmap &optional partial shadow prefix title
- no-menu transl always-title mention-shadow)
+ no-menu transl always-title mention-shadow
+ buffer)
"Insert a description of the key bindings in STARTMAP.
This is followed by the key bindings of all maps reachable
through STARTMAP.
@@ -1285,7 +1315,10 @@ maps to look through.
If MENTION-SHADOW is non-nil, then when something is shadowed by
SHADOW, don't omit it; instead, mention it but say it is
-shadowed."
+shadowed.
+
+If BUFFER, lookup keys while in that buffer. This only affects
+things like :filters for menu bindings."
(let* ((amaps (accessible-keymaps startmap prefix))
(orig-maps (if no-menu
(progn
@@ -1326,7 +1359,8 @@ shadowed."
(setq sub-shadows (cons (cdr (car tail)) sub-shadows)))
(setq tail (cdr tail))))
(describe-map (cdr elt) elt-prefix transl partial
- sub-shadows no-menu mention-shadow)))
+ sub-shadows no-menu mention-shadow
+ buffer)))
(setq maps (cdr maps)))
;; Print title...
(when (and print-title
@@ -1374,7 +1408,8 @@ Return nil if the key sequence is too long."
((keymapp definition)
(insert "Prefix Command\n"))
((byte-code-function-p definition)
- (insert "[%s]\n" (buttonize "byte-code" #'disassemble definition)))
+ (insert (format "[%s]\n"
+ (buttonize "byte-code" #'disassemble definition))))
((and (consp definition)
(memq (car definition) '(closure lambda)))
(insert (format "[%s]\n"
@@ -1403,13 +1438,13 @@ Return nil if the key sequence is too long."
(t nil))))
(defun describe-map (map &optional prefix transl partial shadow
- nomenu mention-shadow)
+ nomenu mention-shadow buffer)
"Describe the contents of keymap MAP.
Assume that this keymap itself is reached by the sequence of
prefix keys PREFIX (a string or vector).
-TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
-`describe-map-tree'."
+TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW and BUFFER are as
+in `describe-map-tree'."
;; Converted from describe_map in keymap.c.
(let* ((suppress (and partial 'suppress-keymap))
(map (keymap-canonicalize map))
@@ -1460,7 +1495,10 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
((and mention-shadow (not (eq tem definition)))
(setq this-shadowed t))
(t nil))))
- (eq definition (lookup-key tail (vector event) t))
+ (eq definition (if buffer
+ (with-current-buffer buffer
+ (lookup-key tail (vector event) t))
+ (lookup-key tail (vector event) t)))
(push (list event definition this-shadowed) vect))))
((eq (car tail) 'keymap)
;; The same keymap might be in the structure twice, if
@@ -1479,10 +1517,11 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
;; Now output them in sorted order.
(while vect
(let* ((elem (car vect))
- (start (car elem))
- (definition (cadr elem))
- (shadowed (caddr elem))
- (end start))
+ (start (nth 0 elem))
+ (definition (nth 1 elem))
+ (shadowed (nth 2 elem))
+ (end start)
+ remapped)
;; Find consecutive chars that are identically defined.
(when (fixnump start)
(while (and (cdr vect)
@@ -1506,7 +1545,19 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
;; Now START .. END is the range to describe next.
;; Insert the string to describe the event START.
(setq line-start (point))
- (insert (help--key-description-fontified (vector start) prefix))
+ ;; If we're in a <remap> section of the output, then also
+ ;; display the bindings of the keys that we've remapped from.
+ ;; This enables the user to actually see what keys to tap to
+ ;; execute the remapped commands.
+ (if (setq remapped
+ (and (equal prefix [remap])
+ (not (eq definition 'self-insert-command))
+ (car (where-is-internal definition))))
+ (insert (help--key-description-fontified
+ (vector (elt remapped (1- (length remapped))))
+ (seq-into (butlast (seq-into remapped 'list))
+ 'vector)))
+ (insert (help--key-description-fontified (vector start) prefix)))
(when (not (eq start end))
(insert " .. " (help--key-description-fontified (vector end)
prefix)))
@@ -1520,9 +1571,15 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
;; Print a description of the definition of this character.
;; elt_describer will take care of spacing out far enough for
;; alignment purposes.
- (when shadowed
+ (when (or shadowed remapped)
(goto-char (max (1- (point)) (point-min)))
- (insert "\n (this binding is currently shadowed)")
+ (when shadowed
+ (insert "\n (this binding is currently shadowed)"))
+ (when remapped
+ (insert (format
+ "\n (Remapped via %s)"
+ (help--key-description-fontified
+ (vector start) prefix))))
(goto-char (min (1+ (point)) (point-max))))))
;; Next item in list.
(setq vect (cdr vect)))
@@ -1779,13 +1836,25 @@ the help window appears on another frame, it may get selected and
its frame get input focus even if this option is nil.
This option has effect if and only if the help window was created
-by `with-help-window'."
+by `with-help-window'.
+
+Also see `help-window-keep-selected'."
:type '(choice (const :tag "never (nil)" nil)
(const :tag "other" other)
(const :tag "always (t)" t))
:group 'help
:version "23.1")
+(defcustom help-window-keep-selected nil
+ "If non-nil, navigation commands in the *Help* buffer will reuse the window.
+If nil, many commands in the *Help* buffer, like \\<help-mode-map>\\[help-view-source] and \\[help-goto-info], will
+pop to a different window to display the results.
+
+Also see `help-window-select'."
+ :type 'boolean
+ :group 'help
+ :version "29.1")
+
(define-obsolete-variable-alias 'help-enable-auto-load
'help-enable-autoload "27.1")
@@ -1899,40 +1968,41 @@ Return VALUE."
;; Return VALUE.
value))
-;; `with-help-window' is a wrapper for `with-temp-buffer-window'
-;; providing the following additional twists:
-
-;; (1) It puts the buffer in `help-mode' (via `help-mode-setup') and
-;; adds cross references (via `help-mode-finish').
-
-;; (2) It issues a message telling how to scroll and quit the help
-;; window (via `help-window-setup').
-
-;; (3) An option (customizable via `help-window-select') to select the
-;; help window automatically.
-
-;; (4) A marker (`help-window-point-marker') to move point in the help
-;; window to an arbitrary buffer position.
(defmacro with-help-window (buffer-or-name &rest body)
"Evaluate BODY, send output to BUFFER-OR-NAME and show in a help window.
-This construct is like `with-temp-buffer-window' but unlike that
-puts the buffer specified by BUFFER-OR-NAME in `help-mode' and
-displays a message about how to delete the help window when it's no
-longer needed. The help window will be selected if
-`help-window-select' is non-nil.
-Most of this is done by `help-window-setup', which see."
+The return value from BODY will be returned.
+
+The help window will be selected if `help-window-select' is
+non-nil.
+
+The `temp-buffer-window-setup-hook' hook is called."
(declare (indent 1) (debug t))
- `(progn
- ;; Make `help-window-point-marker' point nowhere. The only place
- ;; where this should be set to a buffer position is within BODY.
- (set-marker help-window-point-marker nil)
- (let ((temp-buffer-window-setup-hook
- (cons 'help-mode-setup temp-buffer-window-setup-hook))
- (temp-buffer-window-show-hook
- (cons 'help-mode-finish temp-buffer-window-show-hook)))
- (setq help-window-old-frame (selected-frame))
- (with-temp-buffer-window
- ,buffer-or-name nil 'help-window-setup (progn ,@body)))))
+ `(help--window-setup ,buffer-or-name (lambda () ,@body)))
+
+(defun help--window-setup (buffer callback)
+ ;; Make `help-window-point-marker' point nowhere. The only place
+ ;; where this should be set to a buffer position is within BODY.
+ (set-marker help-window-point-marker nil)
+ (with-current-buffer (get-buffer-create buffer)
+ (unless (derived-mode-p 'help-mode)
+ (help-mode))
+ (setq buffer-read-only t
+ buffer-file-name nil)
+ (setq-local help-mode--current-data nil)
+ (buffer-disable-undo)
+ (let ((inhibit-read-only t)
+ (inhibit-modification-hooks t))
+ (erase-buffer)
+ (delete-all-overlays)
+ (prog1
+ (let ((standard-output (current-buffer)))
+ (prog1
+ (funcall callback)
+ (run-hooks 'temp-buffer-window-setup-hook)))
+ (help-make-xrefs (current-buffer))
+ ;; This must be done after the buffer has been completely
+ ;; generated, since `temp-buffer-resize-mode' may be enabled.
+ (help-window-setup (temp-buffer-window-show (current-buffer)))))))
;; Called from C, on encountering `help-char' when reading a char.
;; Don't print to *Help*; that would clobber Help history.
@@ -2016,7 +2086,7 @@ the same names as used in the original source code, when possible."
(if (and (symbolp def) (fboundp def)) (setq def (indirect-function def)))
;; Advice wrappers have "catch all" args, so fetch the actual underlying
;; function to find the real arguments.
- (while (advice--p def) (setq def (advice--cdr def)))
+ (setq def (advice--cd*r def))
;; If definition is a macro, find the function inside it.
(if (eq (car-safe def) 'macro) (setq def (cdr def)))
(cond
@@ -2069,7 +2139,7 @@ the same names as used in the original source code, when possible."
((symbolp arg)
(let ((name (symbol-name arg)))
(cond
- ((string-match "\\`&" name) arg)
+ ((string-match "\\`&" name) (bare-symbol arg))
((string-match "\\`_." name)
(intern (upcase (substring name 1))))
(t (intern (upcase name))))))
@@ -2132,7 +2202,10 @@ the suggested string to use instead. See
confusables ", ")
string))))
-(defun help-command-error-confusable-suggestions (data _context _signal)
+(defun help-command-error-confusable-suggestions (data context signal)
+ ;; Delegate most of the work to the original default value of
+ ;; `command-error-function' implemented in C.
+ (command-error-default-function data context signal)
(pcase data
(`(void-variable ,var)
(let ((suggestions (help-uni-confusable-suggestions
@@ -2141,8 +2214,12 @@ the suggested string to use instead. See
(princ (concat "\n " suggestions) t))))
(_ nil)))
-(add-function :after command-error-function
- #'help-command-error-confusable-suggestions)
+(when (eq command-error-function #'command-error-default-function)
+ ;; Override the default set in the C code.
+ ;; This is not done using `add-function' so as to loosen the bootstrap
+ ;; dependencies.
+ (setq command-error-function
+ #'help-command-error-confusable-suggestions))
(define-obsolete-function-alias 'help-for-help-internal #'help-for-help "28.1")
diff --git a/lisp/hfy-cmap.el b/lisp/hfy-cmap.el
index 258502bfe70..c08359696d5 100644
--- a/lisp/hfy-cmap.el
+++ b/lisp/hfy-cmap.el
@@ -859,8 +859,4 @@ Loads the variable `hfy-rgb-txt-color-map', which is used by
(provide 'hfy-cmap)
-;; Local Variables:
-;; generated-autoload-file: "htmlfontify-loaddefs.el"
-;; End:
-
;;; hfy-cmap.el ends here
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index fbd698e234a..b56f26d5297 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -69,12 +69,12 @@
;; You might also want to bind the hi-lock commands to more
;; finger-friendly sequences:
-;; (define-key hi-lock-map "\C-z\C-h" 'highlight-lines-matching-regexp)
-;; (define-key hi-lock-map "\C-zi" 'hi-lock-find-patterns)
-;; (define-key hi-lock-map "\C-zh" 'highlight-regexp)
-;; (define-key hi-lock-map "\C-zp" 'highlight-phrase)
-;; (define-key hi-lock-map "\C-zr" 'unhighlight-regexp)
-;; (define-key hi-lock-map "\C-zb" 'hi-lock-write-interactive-patterns))
+;; (keymap-set hi-lock-map "C-z C-h" 'highlight-lines-matching-regexp)
+;; (keymap-set hi-lock-map "C-z i" 'hi-lock-find-patterns)
+;; (keymap-set hi-lock-map "C-z h" 'highlight-regexp)
+;; (keymap-set hi-lock-map "C-z p" 'highlight-phrase)
+;; (keymap-set hi-lock-map "C-z r" 'unhighlight-regexp)
+;; (keymap-set hi-lock-map "C-z b" 'hi-lock-write-interactive-patterns))
;; See the documentation for hi-lock-mode `C-h f hi-lock-mode' for
;; additional instructions.
@@ -97,7 +97,7 @@
When a file is visited and hi-lock mode is on, patterns starting
up to this limit are added to font-lock's patterns. See documentation
of functions `hi-lock-mode' and `hi-lock-find-patterns'."
- :type 'integer
+ :type 'natnum
:group 'hi-lock)
(defcustom hi-lock-highlight-range 2000000
@@ -107,7 +107,7 @@ such as the buffer created by `list-colors-display'. In those buffers
hi-lock patterns will only be applied over a range of
`hi-lock-highlight-range' characters. If font-lock is active then
highlighting will be applied throughout the buffer."
- :type 'integer
+ :type 'natnum
:group 'hi-lock)
(defcustom hi-lock-exclude-modes
@@ -235,10 +235,12 @@ by cycling through the faces in `hi-lock-face-defaults'."
"Human-readable lighters for `hi-lock-interactive-patterns'.")
(put 'hi-lock-interactive-lighters 'permanent-local t)
-(defvar hi-lock-face-defaults
+(defcustom hi-lock-face-defaults
'("hi-yellow" "hi-pink" "hi-green" "hi-blue" "hi-salmon" "hi-aquamarine"
"hi-black-b" "hi-blue-b" "hi-red-b" "hi-green-b" "hi-black-hb")
- "Default faces for hi-lock interactive functions.")
+ "Default face names for hi-lock interactive functions."
+ :type '(repeat string)
+ :version "29.1")
(defvar hi-lock-file-patterns-prefix "Hi-lock"
"String used to identify hi-lock patterns at the start of files.")
@@ -274,17 +276,16 @@ a library is being loaded.")
["Patterns from Buffer" hi-lock-find-patterns
:help "Use patterns (if any) near top of buffer."]))
-(defvar hi-lock-map
- (let ((map (make-sparse-keymap "Hi Lock")))
- (define-key map "\C-xwi" 'hi-lock-find-patterns)
- (define-key map "\C-xwl" 'highlight-lines-matching-regexp)
- (define-key map "\C-xwp" 'highlight-phrase)
- (define-key map "\C-xwh" 'highlight-regexp)
- (define-key map "\C-xw." 'highlight-symbol-at-point)
- (define-key map "\C-xwr" 'unhighlight-regexp)
- (define-key map "\C-xwb" 'hi-lock-write-interactive-patterns)
- map)
- "Key map for hi-lock.")
+(defvar-keymap hi-lock-map
+ :doc "Keymap for `hi-lock-mode'."
+ :name "Hi Lock"
+ "C-x w i" #'hi-lock-find-patterns
+ "C-x w l" #'highlight-lines-matching-regexp
+ "C-x w p" #'highlight-phrase
+ "C-x w h" #'highlight-regexp
+ "C-x w ." #'highlight-symbol-at-point
+ "C-x w r" #'unhighlight-regexp
+ "C-x w b" #'hi-lock-write-interactive-patterns)
;; Visible Functions
@@ -723,21 +724,32 @@ with completion and history."
(when hi-lock-interactive-patterns
(face-name (hi-lock-keyword->face
(car hi-lock-interactive-patterns)))))
- (defaults (append hi-lock--unused-faces
- (cdr (member last-used-face hi-lock-face-defaults))
- hi-lock-face-defaults))
+ (defaults (seq-uniq
+ (append hi-lock--unused-faces
+ (cdr (member last-used-face hi-lock-face-defaults))
+ hi-lock-face-defaults)
+ #'equal))
face)
- (if (and hi-lock-auto-select-face (not current-prefix-arg))
+ (if (and hi-lock-auto-select-face (not current-prefix-arg))
(setq face (or (pop hi-lock--unused-faces) (car defaults)))
- (setq face (completing-read
- (format-prompt "Highlight using face" (car defaults))
- obarray 'facep t nil 'face-name-history defaults))
+ (setq face (symbol-name (read-face-name "Highlight using face" defaults)))
;; Update list of un-used faces.
(setq hi-lock--unused-faces (remove face hi-lock--unused-faces))
;; Grow the list of defaults.
(add-to-list 'hi-lock-face-defaults face t))
(intern face)))
+(defvar hi-lock-use-overlays nil
+ "Whether to always use overlays instead of font-lock rules.
+When font-lock-mode is enabled and the buffer specifies font-lock rules,
+highlighting is performed by adding new font-lock rules to the existing ones,
+so when new matching strings are added, they are highlighted by font-lock.
+Otherwise, overlays are used, but new highlighting overlays are not added
+when new matching strings are inserted to the buffer.
+However, sometimes overlays are still preferable even in buffers
+where font-lock is enabled, when hi-lock overlays take precedence
+over other overlays in the same buffer.")
+
(defun hi-lock-set-pattern (regexp face &optional subexp lighter case-fold spaces-regexp)
"Highlight SUBEXP of REGEXP with face FACE.
If omitted or nil, SUBEXP defaults to zero, i.e. the entire
@@ -759,7 +771,8 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search."
(add-to-list 'hi-lock--unused-faces (face-name face))
(push pattern hi-lock-interactive-patterns)
(push (cons (or lighter regexp) pattern) hi-lock-interactive-lighters)
- (if (and font-lock-mode (font-lock-specified-p major-mode))
+ (if (and font-lock-mode (font-lock-specified-p major-mode)
+ (not hi-lock-use-overlays))
(progn
(font-lock-add-keywords nil (list pattern) t)
(font-lock-flush))
@@ -781,6 +794,8 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search."
(match-end subexp))))
(overlay-put overlay 'hi-lock-overlay t)
(overlay-put overlay 'hi-lock-overlay-regexp (or lighter regexp))
+ ;; Use priority higher than default used by e.g. diff-refine.
+ (overlay-put overlay 'priority 1)
(overlay-put overlay 'face face))
(goto-char (match-end 0)))
(when no-matches
@@ -854,6 +869,27 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search."
;; continue standard unloading
nil)
+;;; Mouse support
+(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
+ (mouse-set-point event)
+ (highlight-symbol-at-point)))
+
+;;;###autoload
+(defun hi-lock-context-menu (menu click)
+ "Populate MENU with a menu item to highlight symbol at CLICK."
+ (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)
;;; hi-lock.el ends here
diff --git a/lisp/hilit-chg.el b/lisp/hilit-chg.el
index 10e2512e9d9..4832dd9023a 100644
--- a/lisp/hilit-chg.el
+++ b/lisp/hilit-chg.el
@@ -669,7 +669,7 @@ This removes all saved change information."
;;;###autoload
(defun highlight-changes-rotate-faces ()
- "Rotate the faces if in Highlight Changes mode and the changes are visible.
+ "\"Age\" changes if in Highlight Changes mode and the changes are visible.
Current changes are displayed in the face described by the first element
of `highlight-changes-face-list', one level older changes are shown in
diff --git a/lisp/hl-line.el b/lisp/hl-line.el
index 8e60ddf6b07..e5ca6819f0d 100644
--- a/lisp/hl-line.el
+++ b/lisp/hl-line.el
@@ -102,7 +102,16 @@ This variable has no effect in Global Highlight Line mode.
For that, use `global-hl-line-sticky-flag'."
:type 'boolean
:version "22.1"
- :group 'hl-line)
+ :group 'hl-line
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (when (featurep 'hl-line)
+ (unless value
+ (let ((selected (window-buffer (selected-window))))
+ (dolist (buffer (buffer-list))
+ (unless (eq buffer selected)
+ (with-current-buffer buffer
+ (hl-line-unhighlight)))))))))
(defcustom global-hl-line-sticky-flag nil
"Non-nil means the Global HL-Line mode highlight appears in all windows.
@@ -125,8 +134,11 @@ This variable is expected to be made buffer-local by modes.")
(defvar hl-line-overlay-buffer nil
"Most recently visited buffer in which Hl-Line mode is enabled.")
-(defvar hl-line-overlay-priority -50
- "Priority used on the overlay used by hl-line.")
+(defcustom hl-line-overlay-priority -50
+ "Priority used on the overlay used by hl-line."
+ :type 'integer
+ :version "28.1"
+ :group 'hl-line)
;;;###autoload
(define-minor-mode hl-line-mode
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 9ea27f24653..dbcc152c15d 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -81,8 +81,6 @@
(eval-when-compile (require 'cl-lib))
(require 'cus-edit)
-(require 'htmlfontify-loaddefs)
-
(defconst htmlfontify-version 0.21)
(defconst hfy-meta-tags
@@ -364,7 +362,7 @@ the etags output on stdout.
Two canned commands are provided - they drive Emacs's etags and
exuberant-ctags' etags respectively."
:tag "etags-command"
- :type (let ((clist (list '(string))))
+ :type (let ((clist (list '(string) '(const :tag "None" nil))))
(dolist (C hfy-etags-cmd-alist)
(push (list 'const :tag (car C) (cdr C)) clist))
(cons 'choice clist)))
@@ -1157,14 +1155,6 @@ The default handler is `hfy-face-to-css-default'.
See also `hfy-face-to-style'.")
-(defalias 'hfy-prop-invisible-p
- (if (fboundp 'invisible-p) #'invisible-p
- (lambda (prop)
- "Is text property PROP an active invisibility property?"
- (or (and (eq buffer-invisibility-spec t) prop)
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec))))))
-
(defun hfy-find-invisible-ranges ()
"Return a list of (start-point . end-point) cons cells of invisible regions."
(save-excursion
@@ -1254,8 +1244,8 @@ return a `defface' style list of face properties instead of a face symbol."
(when face-name (setq base-face face-name))
(dolist (P overlay-data)
(let ((iprops (cadr (memq 'invisible P)))) ;FIXME: plist-get?
- ;;(message "(hfy-prop-invisible-p %S)" iprops)
- (when (and iprops (hfy-prop-invisible-p iprops))
+ ;;(message "(invisible-p %S)" iprops)
+ (when (and iprops (invisible-p iprops))
(setq extra-props
(cons :invisible (cons t extra-props))) ))
(let ((fprops (cadr (or (memq 'face P)
@@ -2409,6 +2399,8 @@ You may also want to set `hfy-page-header' and `hfy-page-footer'."
(declare (obsolete seq-intersection "28.1"))
(nreverse (seq-intersection set-a set-b #'eq)))
+(define-obsolete-function-alias 'hfy-prop-invisible-p #'invisible-p "29.1")
+
(provide 'htmlfontify)
;;; htmlfontify.el ends here
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index 30b494f5733..822ecbdd99d 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1211,7 +1211,9 @@ Interactively, prompt for NAME, and use the current filters."
(let ((type (assq (car qualifier) ibuffer-filtering-alist)))
(unless qualifier
(error "Ibuffer: Bad qualifier %s" qualifier))
- (concat " [" (cadr type) ": " (format "%s]" (cdr qualifier)))))))
+ (if (cdr qualifier)
+ (format " [%s: %s]" (cadr type) (cdr qualifier))
+ (format " [%s]" (cadr type)))))))
(defun ibuffer-list-buffer-modes (&optional include-parents)
"Create a completion table of buffer modes currently in use.
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 5d2dd479455..51b206d7c48 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -321,10 +321,15 @@ bound to the current value of the filter.
(when (cdr qualifier) ; Compose individual filters with `or'.
(setq ,filter `(or ,@(mapcar (lambda (m) (cons ',name m)) qualifier))))))
(if (null (ibuffer-push-filter ,filter))
- (message ,(format "Filter by %s already applied: %%s" description)
- ,qualifier-str)
- (message ,(format "Filter by %s added: %%s" description)
- ,qualifier-str)
+ (if ,qualifier-str
+ (message ,(format "Filter by %s already applied: %%s"
+ description)
+ ,qualifier-str)
+ (message ,(format "Filter by %s already applied" description)))
+ (if ,qualifier-str
+ (message ,(format "Filter by %s added: %%s" description)
+ ,qualifier-str)
+ (message ,(format "Filter by %s added" description)))
(ibuffer-update nil t))))
(push (list ',name ,description
(lambda (buf qualifier)
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 7cfa428e9bc..742d21d0b0f 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -34,7 +34,7 @@
;; you might be interested in replacing the default `list-buffers' key
;; binding by adding the following to your init file:
;;
-;; (global-set-key (kbd "C-x C-b") 'ibuffer)
+;; (keymap-global-set "C-x C-b" 'ibuffer)
;;
;; See also the various customization options, not least the
;; documentation for `ibuffer-formats'.
@@ -364,173 +364,170 @@ directory, like `default-directory'."
(regexp :tag "From")
(regexp :tag "To"))))
-(defvar ibuffer--filter-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "RET") 'ibuffer-filter-by-mode)
- (define-key map (kbd "SPC") 'ibuffer-filter-chosen-by-completion)
- (define-key map (kbd "m") 'ibuffer-filter-by-used-mode)
- (define-key map (kbd "M") 'ibuffer-filter-by-derived-mode)
- (define-key map (kbd "n") 'ibuffer-filter-by-name)
- (define-key map (kbd "E") 'ibuffer-filter-by-process)
- (define-key map (kbd "*") 'ibuffer-filter-by-starred-name)
- (define-key map (kbd "f") 'ibuffer-filter-by-filename)
- (define-key map (kbd "F") 'ibuffer-filter-by-directory)
- (define-key map (kbd "b") 'ibuffer-filter-by-basename)
- (define-key map (kbd ".") 'ibuffer-filter-by-file-extension)
- (define-key map (kbd "<") 'ibuffer-filter-by-size-lt)
- (define-key map (kbd ">") 'ibuffer-filter-by-size-gt)
- (define-key map (kbd "i") 'ibuffer-filter-by-modified)
- (define-key map (kbd "v") 'ibuffer-filter-by-visiting-file)
- (define-key map (kbd "c") 'ibuffer-filter-by-content)
- (define-key map (kbd "e") 'ibuffer-filter-by-predicate)
-
- (define-key map (kbd "r") 'ibuffer-switch-to-saved-filters)
- (define-key map (kbd "a") 'ibuffer-add-saved-filters)
- (define-key map (kbd "x") 'ibuffer-delete-saved-filters)
- (define-key map (kbd "d") 'ibuffer-decompose-filter)
- (define-key map (kbd "s") 'ibuffer-save-filters)
- (define-key map (kbd "p") 'ibuffer-pop-filter)
- (define-key map (kbd "<up>") 'ibuffer-pop-filter)
- (define-key map (kbd "!") 'ibuffer-negate-filter)
- (define-key map (kbd "t") 'ibuffer-exchange-filters)
- (define-key map (kbd "TAB") 'ibuffer-exchange-filters)
- (define-key map (kbd "o") 'ibuffer-or-filter)
- (define-key map (kbd "|") 'ibuffer-or-filter)
- (define-key map (kbd "&") 'ibuffer-and-filter)
- (define-key map (kbd "g") 'ibuffer-filters-to-filter-group)
- (define-key map (kbd "P") 'ibuffer-pop-filter-group)
- (define-key map (kbd "S-<up>") 'ibuffer-pop-filter-group)
- (define-key map (kbd "D") 'ibuffer-decompose-filter-group)
- (define-key map (kbd "/") 'ibuffer-filter-disable)
-
- (define-key map (kbd "S") 'ibuffer-save-filter-groups)
- (define-key map (kbd "R") 'ibuffer-switch-to-saved-filter-groups)
- (define-key map (kbd "X") 'ibuffer-delete-saved-filter-groups)
- (define-key map (kbd "\\") 'ibuffer-clear-filter-groups)
- map))
-
-(defvar ibuffer-mode-map
- (let ((map (make-keymap)))
- (define-key map (kbd "0") 'digit-argument)
- (define-key map (kbd "1") 'digit-argument)
- (define-key map (kbd "2") 'digit-argument)
- (define-key map (kbd "3") 'digit-argument)
- (define-key map (kbd "4") 'digit-argument)
- (define-key map (kbd "5") 'digit-argument)
- (define-key map (kbd "6") 'digit-argument)
- (define-key map (kbd "7") 'digit-argument)
- (define-key map (kbd "8") 'digit-argument)
- (define-key map (kbd "9") 'digit-argument)
-
- (define-key map (kbd "m") 'ibuffer-mark-forward)
- (define-key map (kbd "t") 'ibuffer-toggle-marks)
- (define-key map (kbd "u") 'ibuffer-unmark-forward)
- (define-key map (kbd "=") 'ibuffer-diff-with-file)
- (define-key map (kbd "j") 'ibuffer-jump-to-buffer)
- (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer)
- (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch)
- (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp)
- (define-key map (kbd "M-s a C-o") 'ibuffer-do-occur)
- (define-key map (kbd "DEL") 'ibuffer-unmark-backward)
- (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
- (define-key map (kbd "* *") 'ibuffer-unmark-all)
- (define-key map (kbd "* c") 'ibuffer-change-marks)
- (define-key map (kbd "U") 'ibuffer-unmark-all-marks)
- (define-key map (kbd "* M") 'ibuffer-mark-by-mode)
- (define-key map (kbd "* m") 'ibuffer-mark-modified-buffers)
- (define-key map (kbd "* u") 'ibuffer-mark-unsaved-buffers)
- (define-key map (kbd "* s") 'ibuffer-mark-special-buffers)
- (define-key map (kbd "* r") 'ibuffer-mark-read-only-buffers)
- (define-key map (kbd "* /") 'ibuffer-mark-dired-buffers)
- (define-key map (kbd "* e") 'ibuffer-mark-dissociated-buffers)
- (define-key map (kbd "* h") 'ibuffer-mark-help-buffers)
- (define-key map (kbd "* z") 'ibuffer-mark-compressed-file-buffers)
- (define-key map (kbd ".") 'ibuffer-mark-old-buffers)
-
- (define-key map (kbd "d") 'ibuffer-mark-for-delete)
- (define-key map (kbd "C-d") 'ibuffer-mark-for-delete-backwards)
- (define-key map (kbd "k") 'ibuffer-mark-for-delete)
- (define-key map (kbd "x") 'ibuffer-do-kill-on-deletion-marks)
-
- ;; immediate operations
- (define-key map (kbd "n") 'ibuffer-forward-line)
- (define-key map (kbd "SPC") 'forward-line)
- (define-key map (kbd "p") 'ibuffer-backward-line)
- (define-key map (kbd "M-}") 'ibuffer-forward-next-marked)
- (define-key map (kbd "M-{") 'ibuffer-backwards-next-marked)
- (define-key map (kbd "l") 'ibuffer-redisplay)
- (define-key map (kbd "g") 'ibuffer-update)
- (define-key map "`" 'ibuffer-switch-format)
- (define-key map "-" 'ibuffer-add-to-tmp-hide)
- (define-key map "+" 'ibuffer-add-to-tmp-show)
- (define-key map "b" 'ibuffer-bury-buffer)
- (define-key map (kbd ",") 'ibuffer-toggle-sorting-mode)
- (define-key map (kbd "s i") 'ibuffer-invert-sorting)
- (define-key map (kbd "s a") 'ibuffer-do-sort-by-alphabetic)
- (define-key map (kbd "s v") 'ibuffer-do-sort-by-recency)
- (define-key map (kbd "s s") 'ibuffer-do-sort-by-size)
- (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process)
- (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode)
-
- (define-key map (kbd "M-n") 'ibuffer-forward-filter-group)
- (define-key map "\t" 'ibuffer-forward-filter-group)
- (define-key map (kbd "M-p") 'ibuffer-backward-filter-group)
- (define-key map [backtab] 'ibuffer-backward-filter-group)
- (define-key map (kbd "M-j") 'ibuffer-jump-to-filter-group)
- (define-key map (kbd "C-k") 'ibuffer-kill-line)
- (define-key map (kbd "C-y") 'ibuffer-yank)
-
- (define-key map (kbd "% n") 'ibuffer-mark-by-name-regexp)
- (define-key map (kbd "% m") 'ibuffer-mark-by-mode-regexp)
- (define-key map (kbd "% f") 'ibuffer-mark-by-file-name-regexp)
- (define-key map (kbd "% g") 'ibuffer-mark-by-content-regexp)
- (define-key map (kbd "% L") 'ibuffer-mark-by-locked)
-
- (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)
-
- (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe)
- (define-key map (kbd "!") 'ibuffer-do-shell-command-file)
- (define-key map (kbd "~") 'ibuffer-do-toggle-modified)
- ;; marked operations
- (define-key map (kbd "A") 'ibuffer-do-view)
- (define-key map (kbd "D") 'ibuffer-do-delete)
- (define-key map (kbd "E") 'ibuffer-do-eval)
- (define-key map (kbd "F") 'ibuffer-do-shell-command-file)
- (define-key map (kbd "I") 'ibuffer-do-query-replace-regexp)
- (define-key map (kbd "H") 'ibuffer-do-view-other-frame)
- (define-key map (kbd "N") 'ibuffer-do-shell-command-pipe-replace)
- (define-key map (kbd "M") 'ibuffer-do-toggle-modified)
- (define-key map (kbd "O") 'ibuffer-do-occur)
- (define-key map (kbd "P") 'ibuffer-do-print)
- (define-key map (kbd "Q") 'ibuffer-do-query-replace)
- (define-key map (kbd "R") 'ibuffer-do-rename-uniquely)
- (define-key map (kbd "S") 'ibuffer-do-save)
- (define-key map (kbd "T") 'ibuffer-do-toggle-read-only)
- (define-key map (kbd "L") 'ibuffer-do-toggle-lock)
- (define-key map (kbd "r") 'ibuffer-do-replace-regexp)
- (define-key map (kbd "V") 'ibuffer-do-revert)
- (define-key map (kbd "W") 'ibuffer-do-view-and-eval)
- (define-key map (kbd "X") 'ibuffer-do-shell-command-pipe)
-
- (define-key map (kbd "k") 'ibuffer-do-kill-lines)
- (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)
- (define-key map (kbd "B") 'ibuffer-copy-buffername-as-kill)
-
- (define-key map (kbd "RET") 'ibuffer-visit-buffer)
- (define-key map (kbd "e") 'ibuffer-visit-buffer)
- (define-key map (kbd "f") 'ibuffer-visit-buffer)
- (define-key map (kbd "C-x C-f") 'ibuffer-find-file)
- (define-key map (kbd "o") 'ibuffer-visit-buffer-other-window)
- (define-key map (kbd "C-o") 'ibuffer-visit-buffer-other-window-noselect)
- (define-key map (kbd "M-o") 'ibuffer-visit-buffer-1-window)
- (define-key map (kbd "v") 'ibuffer-do-view)
- (define-key map (kbd "C-x v") 'ibuffer-do-view-horizontally)
- (define-key map (kbd "C-c C-a") 'ibuffer-auto-mode)
- (define-key map (kbd "C-x 4 RET") 'ibuffer-visit-buffer-other-window)
- (define-key map (kbd "C-x 5 RET") 'ibuffer-visit-buffer-other-frame)
-
- (define-key map (kbd "/") ibuffer--filter-map)
- map))
+(defvar-keymap ibuffer--filter-map
+ "RET" #'ibuffer-filter-by-mode
+ "SPC" #'ibuffer-filter-chosen-by-completion
+ "m" #'ibuffer-filter-by-used-mode
+ "M" #'ibuffer-filter-by-derived-mode
+ "n" #'ibuffer-filter-by-name
+ "E" #'ibuffer-filter-by-process
+ "*" #'ibuffer-filter-by-starred-name
+ "f" #'ibuffer-filter-by-filename
+ "F" #'ibuffer-filter-by-directory
+ "b" #'ibuffer-filter-by-basename
+ "." #'ibuffer-filter-by-file-extension
+ "<" #'ibuffer-filter-by-size-lt
+ ">" #'ibuffer-filter-by-size-gt
+ "i" #'ibuffer-filter-by-modified
+ "v" #'ibuffer-filter-by-visiting-file
+ "c" #'ibuffer-filter-by-content
+ "e" #'ibuffer-filter-by-predicate
+
+ "r" #'ibuffer-switch-to-saved-filters
+ "a" #'ibuffer-add-saved-filters
+ "x" #'ibuffer-delete-saved-filters
+ "d" #'ibuffer-decompose-filter
+ "s" #'ibuffer-save-filters
+ "p" #'ibuffer-pop-filter
+ "<up>" #'ibuffer-pop-filter
+ "!" #'ibuffer-negate-filter
+ "t" #'ibuffer-exchange-filters
+ "TAB" #'ibuffer-exchange-filters
+ "o" #'ibuffer-or-filter
+ "|" #'ibuffer-or-filter
+ "&" #'ibuffer-and-filter
+ "g" #'ibuffer-filters-to-filter-group
+ "P" #'ibuffer-pop-filter-group
+ "S-<up>" #'ibuffer-pop-filter-group
+ "D" #'ibuffer-decompose-filter-group
+ "/" #'ibuffer-filter-disable
+
+ "S" #'ibuffer-save-filter-groups
+ "R" #'ibuffer-switch-to-saved-filter-groups
+ "X" #'ibuffer-delete-saved-filter-groups
+ "\\" #'ibuffer-clear-filter-groups)
+
+(defvar-keymap ibuffer-mode-map
+ :full t
+ "0" #'digit-argument
+ "1" #'digit-argument
+ "2" #'digit-argument
+ "3" #'digit-argument
+ "4" #'digit-argument
+ "5" #'digit-argument
+ "6" #'digit-argument
+ "7" #'digit-argument
+ "8" #'digit-argument
+ "9" #'digit-argument
+
+ "m" #'ibuffer-mark-forward
+ "t" #'ibuffer-toggle-marks
+ "u" #'ibuffer-unmark-forward
+ "=" #'ibuffer-diff-with-file
+ "j" #'ibuffer-jump-to-buffer
+ "M-g" #'ibuffer-jump-to-buffer
+ "M-s a C-s" #'ibuffer-do-isearch
+ "M-s a C-M-s" #'ibuffer-do-isearch-regexp
+ "M-s a C-o" #'ibuffer-do-occur
+ "DEL" #'ibuffer-unmark-backward
+ "M-DEL" #'ibuffer-unmark-all
+ "* *" #'ibuffer-unmark-all
+ "* c" #'ibuffer-change-marks
+ "U" #'ibuffer-unmark-all-marks
+ "* M" #'ibuffer-mark-by-mode
+ "* m" #'ibuffer-mark-modified-buffers
+ "* u" #'ibuffer-mark-unsaved-buffers
+ "* s" #'ibuffer-mark-special-buffers
+ "* r" #'ibuffer-mark-read-only-buffers
+ "* /" #'ibuffer-mark-dired-buffers
+ "* e" #'ibuffer-mark-dissociated-buffers
+ "* h" #'ibuffer-mark-help-buffers
+ "* z" #'ibuffer-mark-compressed-file-buffers
+ "." #'ibuffer-mark-old-buffers
+
+ "d" #'ibuffer-mark-for-delete
+ "C-d" #'ibuffer-mark-for-delete-backwards
+ "k" #'ibuffer-mark-for-delete
+ "x" #'ibuffer-do-kill-on-deletion-marks
+
+ ;; immediate operations
+ "n" #'ibuffer-forward-line
+ "SPC" #'forward-line
+ "p" #'ibuffer-backward-line
+ "M-}" #'ibuffer-forward-next-marked
+ "M-{" #'ibuffer-backwards-next-marked
+ "l" #'ibuffer-redisplay
+ "g" #'ibuffer-update
+ "`" #'ibuffer-switch-format
+ "-" #'ibuffer-add-to-tmp-hide
+ "+" #'ibuffer-add-to-tmp-show
+ "b" #'ibuffer-bury-buffer
+ "," #'ibuffer-toggle-sorting-mode
+ "s i" #'ibuffer-invert-sorting
+ "s a" #'ibuffer-do-sort-by-alphabetic
+ "s v" #'ibuffer-do-sort-by-recency
+ "s s" #'ibuffer-do-sort-by-size
+ "s f" #'ibuffer-do-sort-by-filename/process
+ "s m" #'ibuffer-do-sort-by-major-mode
+
+ "M-n" #'ibuffer-forward-filter-group
+ "TAB" #'ibuffer-forward-filter-group
+ "M-p" #'ibuffer-backward-filter-group
+ "<backtab>" #'ibuffer-backward-filter-group
+ "M-j" #'ibuffer-jump-to-filter-group
+ "C-k" #'ibuffer-kill-line
+ "C-y" #'ibuffer-yank
+
+ "% n" #'ibuffer-mark-by-name-regexp
+ "% m" #'ibuffer-mark-by-mode-regexp
+ "% f" #'ibuffer-mark-by-file-name-regexp
+ "% g" #'ibuffer-mark-by-content-regexp
+ "% L" #'ibuffer-mark-by-locked
+
+ "C-t" #'ibuffer-visit-tags-table
+
+ "|" #'ibuffer-do-shell-command-pipe
+ "!" #'ibuffer-do-shell-command-file
+ "~" #'ibuffer-do-toggle-modified
+ ;; marked operations
+ "A" #'ibuffer-do-view
+ "D" #'ibuffer-do-delete
+ "E" #'ibuffer-do-eval
+ "F" #'ibuffer-do-shell-command-file
+ "I" #'ibuffer-do-query-replace-regexp
+ "H" #'ibuffer-do-view-other-frame
+ "N" #'ibuffer-do-shell-command-pipe-replace
+ "M" #'ibuffer-do-toggle-modified
+ "O" #'ibuffer-do-occur
+ "P" #'ibuffer-do-print
+ "Q" #'ibuffer-do-query-replace
+ "R" #'ibuffer-do-rename-uniquely
+ "S" #'ibuffer-do-save
+ "T" #'ibuffer-do-toggle-read-only
+ "L" #'ibuffer-do-toggle-lock
+ "r" #'ibuffer-do-replace-regexp
+ "V" #'ibuffer-do-revert
+ "W" #'ibuffer-do-view-and-eval
+ "X" #'ibuffer-do-shell-command-pipe
+
+ "k" #'ibuffer-do-kill-lines
+ "w" #'ibuffer-copy-filename-as-kill
+ "B" #'ibuffer-copy-buffername-as-kill
+
+ "RET" #'ibuffer-visit-buffer
+ "e" #'ibuffer-visit-buffer
+ "f" #'ibuffer-visit-buffer
+ "C-x C-f" #'ibuffer-find-file
+ "o" #'ibuffer-visit-buffer-other-window
+ "C-o" #'ibuffer-visit-buffer-other-window-noselect
+ "M-o" #'ibuffer-visit-buffer-1-window
+ "v" #'ibuffer-do-view
+ "C-x v" #'ibuffer-do-view-horizontally
+ "C-c C-a" #'ibuffer-auto-mode
+ "C-x 4 RET" #'ibuffer-visit-buffer-other-window
+ "C-x 5 RET" #'ibuffer-visit-buffer-other-frame
+
+ "/" ibuffer--filter-map)
(defun ibuffer-mode--groups-menu-definition (&optional is-popup)
"Build the `ibuffer' \"Filter\" menu. Internal."
@@ -758,46 +755,32 @@ directory, like `default-directory'."
["Diff with file" ibuffer-diff-with-file
:help "View the differences between this buffer and its file"]))
-(defvar ibuffer-name-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
- (define-key map [(mouse-2)] 'ibuffer-mouse-visit-buffer)
- (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
- map))
-
-(defvar ibuffer-filename/process-header-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-do-sort-by-filename/process)
- map))
-
-(defvar ibuffer-mode-name-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-2)] 'ibuffer-mouse-filter-by-mode)
- (define-key map (kbd "RET") 'ibuffer-interactive-filter-by-mode)
- map))
-
-(defvar ibuffer-name-header-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-do-sort-by-alphabetic)
- map))
-
-(defvar ibuffer-size-header-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-do-sort-by-size)
- map))
-
-(defvar ibuffer-mode-header-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-do-sort-by-major-mode)
- map))
-
-(defvar ibuffer-mode-filter-group-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark)
- (define-key map [(mouse-2)] 'ibuffer-mouse-toggle-filter-group)
- (define-key map (kbd "RET") 'ibuffer-toggle-filter-group)
- (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu)
- map))
+(defvar-keymap ibuffer-name-map
+ "<mouse-1>" #'ibuffer-mouse-toggle-mark
+ "<mouse-2>" #'ibuffer-mouse-visit-buffer
+ "<down-mouse-3>" #'ibuffer-mouse-popup-menu)
+
+(defvar-keymap ibuffer-filename/process-header-map
+ "<mouse-1>" #'ibuffer-do-sort-by-filename/process)
+
+(defvar-keymap ibuffer-mode-name-map
+ "<mouse-2>" #'ibuffer-mouse-filter-by-mode
+ "RET" #'ibuffer-interactive-filter-by-mode)
+
+(defvar-keymap ibuffer-name-header-map
+ "<mouse-1>" #'ibuffer-do-sort-by-alphabetic)
+
+(defvar-keymap ibuffer-size-header-map
+ "<mouse-1>" #'ibuffer-do-sort-by-size)
+
+(defvar-keymap ibuffer-mode-header-map
+ "<mouse-1>" #'ibuffer-do-sort-by-major-mode)
+
+(defvar-keymap ibuffer-mode-filter-group-map
+ "<mouse-1>" #'ibuffer-mouse-toggle-mark
+ "<mouse-2>" #'ibuffer-mouse-toggle-filter-group
+ "RET" #'ibuffer-toggle-filter-group
+ "<down-mouse-3>" #'ibuffer-mouse-popup-menu)
(defvar ibuffer-did-modification nil)
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 2986aa192c8..9640d98ca84 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -81,7 +81,7 @@ selection process starts again from the user's $HOME.")
This means to show completions even when the current minibuffer contents
is the same as was the initial input after minibuffer activation.
This also means that if you traverse the list of completions with
-commands like `C-.' and just hit RET without typing any
+commands like \\`C-.' and just hit \\`RET' without typing any
characters, the match under point will be chosen instead of the
default."
:type 'boolean
@@ -139,7 +139,9 @@ See `icomplete-delay-completions-threshold'."
:type 'integer)
(defvar icomplete-in-buffer nil
- "If non-nil, also use Icomplete when completing in non-mini buffers.")
+ "If non-nil, also use Icomplete when completing in non-mini buffers.
+This affects commands like `complete-in-region', but not commands
+that use their own completions setup.")
(defcustom icomplete-minibuffer-setup-hook nil
"Icomplete-specific customization of minibuffer setup.
@@ -153,8 +155,7 @@ with other features and packages. For instance:
will constrain Emacs to a maximum minibuffer height of 3 lines when
icompletion is occurring."
- :type 'hook
- :group 'icomplete)
+ :type 'hook)
;;;_* Initialization
@@ -174,11 +175,11 @@ Used to implement the option `icomplete-show-matches-on-no-input'.")
(defvar icomplete-minibuffer-map
(let ((map (make-sparse-keymap)))
- (define-key map [?\M-\t] 'icomplete-force-complete)
- (define-key map [remap minibuffer-complete-and-exit] 'icomplete-ret)
- (define-key map [?\C-j] 'icomplete-force-complete-and-exit)
- (define-key map [?\C-.] 'icomplete-forward-completions)
- (define-key map [?\C-,] 'icomplete-backward-completions)
+ (define-key map [?\M-\t] #'icomplete-force-complete)
+ (define-key map [remap minibuffer-complete-and-exit] #'icomplete-ret)
+ (define-key map [?\C-j] #'icomplete-force-complete-and-exit)
+ (define-key map [?\C-.] #'icomplete-forward-completions)
+ (define-key map [?\C-,] #'icomplete-backward-completions)
map)
"Keymap used by `icomplete-mode' in the minibuffer.")
@@ -394,18 +395,18 @@ if that doesn't produce a completion match."
(defvar icomplete-fido-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-k") 'icomplete-fido-kill)
- (define-key map (kbd "C-d") 'icomplete-fido-delete-char)
- (define-key map (kbd "RET") 'icomplete-fido-ret)
- (define-key map (kbd "C-m") 'icomplete-fido-ret)
- (define-key map (kbd "DEL") 'icomplete-fido-backward-updir)
- (define-key map (kbd "M-j") 'icomplete-fido-exit)
- (define-key map (kbd "C-s") 'icomplete-forward-completions)
- (define-key map (kbd "C-r") 'icomplete-backward-completions)
- (define-key map (kbd "<right>") 'icomplete-forward-completions)
- (define-key map (kbd "<left>") 'icomplete-backward-completions)
- (define-key map (kbd "C-.") 'icomplete-forward-completions)
- (define-key map (kbd "C-,") 'icomplete-backward-completions)
+ (define-key map (kbd "C-k") #'icomplete-fido-kill)
+ (define-key map (kbd "C-d") #'icomplete-fido-delete-char)
+ (define-key map (kbd "RET") #'icomplete-fido-ret)
+ (define-key map (kbd "C-m") #'icomplete-fido-ret)
+ (define-key map (kbd "DEL") #'icomplete-fido-backward-updir)
+ (define-key map (kbd "M-j") #'icomplete-fido-exit)
+ (define-key map (kbd "C-s") #'icomplete-forward-completions)
+ (define-key map (kbd "C-r") #'icomplete-backward-completions)
+ (define-key map (kbd "<right>") #'icomplete-forward-completions)
+ (define-key map (kbd "<left>") #'icomplete-backward-completions)
+ (define-key map (kbd "C-.") #'icomplete-forward-completions)
+ (define-key map (kbd "C-,") #'icomplete-backward-completions)
map)
"Keymap used by `fido-mode' in the minibuffer.")
@@ -431,7 +432,7 @@ if that doesn't produce a completion match."
This global minor mode makes minibuffer completion behave
more like `ido-mode' than regular `icomplete-mode'."
- :global t :group 'icomplete
+ :global t
(remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)
(remove-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup)
(when fido-mode
@@ -457,7 +458,7 @@ You can use the following key bindings to navigate and select
completions:
\\{icomplete-minibuffer-map}"
- :global t :group 'icomplete
+ :global t
(remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)
(remove-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup)
(when icomplete-mode
@@ -532,7 +533,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
(setq icomplete--in-region-buffer nil)
(delete-overlay icomplete-overlay)
(kill-local-variable 'completion-show-inline-help)
- (remove-hook 'post-command-hook 'icomplete-post-command-hook t)
+ (remove-hook 'post-command-hook #'icomplete-post-command-hook t)
(message nil)))
(when (and completion-in-region-mode
icomplete-mode (icomplete-simple-completing-p))
@@ -543,7 +544,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
(unless (memq icomplete-minibuffer-map (cdr tem))
(setcdr tem (make-composed-keymap icomplete-minibuffer-map
(cdr tem)))))
- (add-hook 'post-command-hook 'icomplete-post-command-hook nil t)))
+ (add-hook 'post-command-hook #'icomplete-post-command-hook nil t)))
(defun icomplete--sorted-completions ()
(or completion-all-sorted-completions
@@ -558,7 +559,8 @@ Usually run by inclusion in `minibuffer-setup-hook'."
;; predicates" which may vary depending on specific
;; `completing-read' invocations, described below:
for fn in (cond ((and minibuffer-default
- (stringp minibuffer-default) ; bug#38992
+ (stringp (or (car-safe minibuffer-default)
+ minibuffer-default)) ; bug#38992 bug#55800
(equal (icomplete--field-string) icomplete--initial-input))
;; Here, we have a non-nil string default and
;; no input whatsoever. We want to make sure
@@ -576,7 +578,9 @@ Usually run by inclusion in `minibuffer-setup-hook'."
;; Has "bar" at the top, so RET will select
;; it, as desired.
,(lambda (comp)
- (equal minibuffer-default comp))
+ (equal (or (car-safe minibuffer-default)
+ minibuffer-default)
+ comp))
;; Why do we need this second predicate?
;; Because that'll make things like M-x man
;; RET RET, when invoked with point on the
@@ -591,14 +595,16 @@ Usually run by inclusion in `minibuffer-setup-hook'."
;; select it -- again, as desired.
;;
;; FIXME: it's arguable that this second
- ;; behaviour should be a property of the
+ ;; behavior should be a property of the
;; completion table and not the completion
;; frontend such as we have done
;; here. However, it seems generically
;; useful for a very broad spectrum of
;; cases.
,(lambda (comp)
- (string-prefix-p minibuffer-default comp))))
+ (string-prefix-p (or (car-safe minibuffer-default)
+ minibuffer-default)
+ comp))))
((and fido-mode
(not minibuffer-default)
(eq (icomplete--category) 'file))
@@ -630,12 +636,12 @@ Usually run by inclusion in `minibuffer-setup-hook'."
(defvar icomplete-vertical-mode-minibuffer-map
(let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-n") 'icomplete-forward-completions)
- (define-key map (kbd "C-p") 'icomplete-backward-completions)
- (define-key map (kbd "<down>") 'icomplete-forward-completions)
- (define-key map (kbd "<up>") 'icomplete-backward-completions)
- (define-key map (kbd "M-<") 'icomplete-vertical-goto-first)
- (define-key map (kbd "M->") 'icomplete-vertical-goto-last)
+ (define-key map (kbd "C-n") #'icomplete-forward-completions)
+ (define-key map (kbd "C-p") #'icomplete-backward-completions)
+ (define-key map (kbd "<down>") #'icomplete-forward-completions)
+ (define-key map (kbd "<up>") #'icomplete-backward-completions)
+ (define-key map (kbd "M-<") #'icomplete-vertical-goto-first)
+ (define-key map (kbd "M->") #'icomplete-vertical-goto-last)
map)
"Keymap used by `icomplete-vertical-mode' in the minibuffer.")
@@ -691,7 +697,7 @@ See `icomplete-mode' and `minibuffer-setup-hook'."
(icomplete-simple-completing-p)) ;Shouldn't be necessary.
(let ((saved-point (point)))
(save-excursion
- (goto-char (point-max))
+ (goto-char (icomplete--field-end))
; Insert the match-status information:
(when (and (or icomplete-show-matches-on-no-input
(not (equal (icomplete--field-string)
@@ -1043,7 +1049,7 @@ matches exist."
(push first prospects)))
(concat determ
"{"
- (mapconcat 'identity prospects icomplete-separator)
+ (mapconcat #'identity prospects icomplete-separator)
(concat (and limit (concat icomplete-separator ellipsis))
"}")))
;; Restore the base-size info, since completion-all-sorted-completions
diff --git a/lisp/ido.el b/lisp/ido.el
index 58cec3deb0e..134081d6759 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -554,7 +554,7 @@ See `ido-last-directory-list' and `ido-save-directory-list-file'."
"Maximum number of working directories to record.
This is the list of directories where files have most recently been opened.
See `ido-work-directory-list' and `ido-save-directory-list-file'."
- :type 'integer)
+ :type 'natnum)
(defcustom ido-work-directory-list-ignore-regexps nil
"List of regexps matching directories which should not be recorded.
@@ -978,7 +978,6 @@ The fallback command is passed as an argument to the functions."
(defvar-keymap ido-file-completion-map
:doc "Keymap for Ido file commands."
:parent ido-file-dir-completion-map
- "C-k" #'ido-delete-file-at-head
"C-o" #'ido-copy-current-word
"C-w" #'ido-copy-current-file-name
"M-l" #'ido-toggle-literal)
@@ -2239,8 +2238,7 @@ If cursor is not at the end of the user input, move to end of input."
(t
(add-to-history 'buffer-name-history buf)
(setq buf (get-buffer-create buf))
- (if (fboundp 'set-buffer-major-mode)
- (set-buffer-major-mode buf))
+ (set-buffer-major-mode buf)
(ido-visit-buffer buf method t))))))
(defun ido-record-work-directory (&optional dir)
@@ -3207,12 +3205,18 @@ instead removed from the current item list."
;; File list sorting
(defun ido-file-lessp (a b)
- ;; Simple compare two file names.
+ "Simple compare two file names."
+ (when ido-case-fold
+ (setq a (downcase a)
+ b (downcase b)))
(string-lessp (ido-no-final-slash a) (ido-no-final-slash b)))
(defun ido-file-extension-lessp (a b)
- ;; Compare file names according to ido-file-extensions-order list.
+ "Compare file names according to ido-file-extensions-order list."
+ (when ido-case-fold
+ (setq a (downcase a)
+ b (downcase b)))
(let ((n (compare-strings a 0 nil b 0 nil nil))
lessp p)
(if (eq n t)
@@ -3941,7 +3945,7 @@ If `ido-change-word-sub' cannot be found in WORD, return nil."
;; In the new buffer, go to the first completion.
;; FIXME: Perhaps this should be done in `ido-completion-help'.
(when (bobp)
- (next-completion 1)))))
+ (first-completion)))))
(defun ido-completion-auto-help ()
"Call `ido-completion-help' if `completion-auto-help' is non-nil."
@@ -3978,23 +3982,30 @@ If `ido-change-word-sub' cannot be found in WORD, return nil."
(setq display-it t))
(if (and ido-completion-buffer display-it)
(with-output-to-temp-buffer ido-completion-buffer
- (let ((completion-list (sort
- (cond
- (ido-directory-too-big
- (message "Reading directory...")
- (setq ido-directory-too-big nil
- ido-ignored-list nil
- ido-cur-list (ido-all-completions)
- ido-rescan t)
- (ido-set-matches)
- (or ido-matches ido-cur-list))
- (ido-use-merged-list
- (ido-flatten-merged-list (or ido-matches ido-cur-list)))
- ((or full-list ido-completion-buffer-all-completions)
- (ido-all-completions))
- (t
- (copy-sequence (or ido-matches ido-cur-list))))
- #'ido-file-lessp)))
+ (let* ((comps
+ (cond
+ (ido-directory-too-big
+ (message "Reading directory...")
+ (setq ido-directory-too-big nil
+ ido-ignored-list nil
+ ido-cur-list (ido-all-completions)
+ ido-rescan t)
+ (ido-set-matches)
+ (or ido-matches ido-cur-list))
+ (ido-use-merged-list
+ (ido-flatten-merged-list (or ido-matches ido-cur-list)))
+ ((or full-list ido-completion-buffer-all-completions)
+ (ido-all-completions))
+ (t
+ (copy-sequence (or ido-matches ido-cur-list)))))
+ (completion-list
+ ;; If we have an alist COMPLETIONS, transform to a
+ ;; simple list first.
+ (sort (if (and (consp comps)
+ (consp (car comps)))
+ (mapcar #'car comps)
+ comps)
+ #'ido-file-lessp)))
;;(add-hook 'completion-setup-hook #'completion-setup-function)
(display-completion-list completion-list))))))
diff --git a/lisp/iimage.el b/lisp/iimage.el
index 2fe50d3e3f1..baeb4bb6a7b 100644
--- a/lisp/iimage.el
+++ b/lisp/iimage.el
@@ -76,11 +76,9 @@ Examples of image filename patterns to match:
foo.JPG"
:type '(alist :key-type regexp :value-type integer))
-(defvar iimage-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-l" #'iimage-recenter)
- map)
- "Keymap used in `iimage-mode'.")
+(defvar-keymap iimage-mode-map
+ :doc "Keymap used in `iimage-mode'."
+ "C-l" #'iimage-recenter)
(defun iimage-recenter (&optional arg)
"Re-draw images and recenter."
@@ -89,9 +87,6 @@ Examples of image filename patterns to match:
(iimage-mode-buffer t)
(recenter-top-bottom arg))
-;;;###autoload
-(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "24.1")
-
(defun turn-off-iimage-mode ()
"Unconditionally turn off iimage mode."
(interactive)
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 536f29441ae..9ceaf1bf734 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -609,9 +609,7 @@ See also `image-dired-thumbnail-storage'."
((eq 'use-image-dired-dir image-dired-thumbnail-storage)
(let* ((f (expand-file-name file))
(hash
- ;; SHA1 is slightly faster than MD5, so let's use it.
- ;; (We don't need anything crytographically strong.)
- (sha1 (file-name-as-directory (file-name-directory f)))))
+ (md5 (file-name-as-directory (file-name-directory f)))))
(format "%s%s%s.thumb.%s"
(file-name-as-directory (expand-file-name (image-dired-dir)))
(file-name-base f)
@@ -2263,23 +2261,26 @@ Optionally use old comment from FILE as initial value."
comment)))
;;;###autoload
-(defun image-dired-mark-tagged-files ()
- "Use regexp to mark files with matching tag.
+(defun image-dired-mark-tagged-files (regexp)
+ "Use REGEXP to mark files with matching tag.
A `tag' is a keyword, a piece of meta data, associated with an
image file and stored in image-dired's database file. This command
lets you input a regexp and this will be matched against all tags
on all image files in the database file. The files that have a
matching tag will be marked in the Dired buffer."
- (interactive)
+ (interactive "sMark tagged files (regexp): ")
(image-dired-sane-db-file)
- (let ((tag (read-string "Mark tagged files (regexp): "))
- (hits 0)
+ (let ((hits 0)
files)
(image-dired--with-db-file
- ;; Collect matches
- (while (search-forward-regexp
- (concat "\\(^[^;\n]+\\);.*" tag ".*$") nil t)
- (push (match-string 1) files)))
+ ;; Collect matches
+ (while (search-forward-regexp "\\(^[^;\n]+\\);\\(.*\\)" nil t)
+ (let ((file (match-string 1))
+ (tags (split-string (match-string 2) ";")))
+ (when (seq-find (lambda (tag)
+ (string-match-p regexp tag))
+ tags)
+ (push file files)))))
;; Mark files
(dolist (curr-file files)
;; I tried using `dired-mark-files-regexp' but it was waaaay to
@@ -2355,7 +2356,8 @@ for deletion instead."
(interactive)
(image-dired--with-marked
(image-dired-delete-char)
- (backward-char))
+ (unless (bobp)
+ (backward-char)))
(image-dired--line-up-with-method)
(with-current-buffer (image-dired-associated-dired-buffer)
(dired-do-delete)))
@@ -2793,6 +2795,7 @@ tags to their respective image file. Internal function used by
;; (bookmark-prop-get bookmark 'image-dired-file)
(goto-char (point-min))))
+(put 'image-dired-bookmark-jump 'bookmark-handler-type "Image-Dired")
;;; Obsolete
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 5bee155460f..46c555df278 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -282,10 +282,17 @@ Stop if the top edge of the image is reached."
(defun image-scroll-up (&optional n)
"Scroll image in current window upward by N lines.
Stop if the bottom edge of the image is reached.
-If ARG is omitted or nil, scroll upward by a near full screen.
+
+Interactively, giving this command a numerical prefix will scroll
+up by that many lines (and down by that many lines if the number
+is negative). Without a prefix, scroll up by a full screen.
+If given a \\`C-u -' prefix, scroll a full page down instead.
+
+If N is omitted or nil, scroll upward by a near full screen.
A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll downward.
-If ARG is the atom `-', scroll downward by nearly full screen.
+A negative N means scroll downward.
+
+If N is the atom `-', scroll downward by nearly full screen.
When calling from a program, supply as argument a number, nil, or `-'."
(interactive "P")
(cond ((null n)
@@ -303,10 +310,17 @@ When calling from a program, supply as argument a number, nil, or `-'."
(defun image-scroll-down (&optional n)
"Scroll image in current window downward by N lines.
Stop if the top edge of the image is reached.
-If ARG is omitted or nil, scroll downward by a near full screen.
+
+Interactively, giving this command a numerical prefix will scroll
+down by that many lines (and up by that many lines if the number
+is negative). Without a prefix, scroll down by a full screen.
+If given a \\`C-u -' prefix, scroll a full page up instead.
+
+If N is omitted or nil, scroll downward by a near full screen.
A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll upward.
-If ARG is the atom `-', scroll upward by nearly full screen.
+A negative N means scroll upward.
+
+If N is the atom `-', scroll upward by nearly full screen.
When calling from a program, supply as argument a number, nil, or `-'."
(interactive "P")
(cond ((null n)
@@ -419,39 +433,31 @@ window configuration prior to the last `image-mode-fit-frame'
call."
(interactive (list nil t))
(let* ((buffer (current-buffer))
- (display (image-get-display-property))
- (size (image-display-size display))
(saved (frame-parameter frame 'image-mode-saved-params))
(window-configuration (current-window-configuration frame))
- (width (frame-width frame))
- (height (frame-height frame)))
+ (frame-width (frame-text-width frame))
+ (frame-height (frame-text-height frame)))
(with-selected-frame (or frame (selected-frame))
(if (and toggle saved
- (= (caar saved) width)
- (= (cdar saved) height))
+ (= (caar saved) frame-width)
+ (= (cdar saved) frame-height))
(progn
- (set-frame-width frame (car (nth 1 saved)))
- (set-frame-height frame (cdr (nth 1 saved)))
+ (set-frame-width frame (car (nth 1 saved)) nil t)
+ (set-frame-height frame (cdr (nth 1 saved)) nil t)
(set-window-configuration (nth 2 saved))
(set-frame-parameter frame 'image-mode-saved-params nil))
(delete-other-windows)
(switch-to-buffer buffer t t)
- (let* ((edges (window-inside-edges))
- (inner-width (- (nth 2 edges) (nth 0 edges)))
- (inner-height (- (nth 3 edges) (nth 1 edges))))
- (set-frame-width frame (+ (ceiling (car size))
- width (- inner-width)))
- (set-frame-height frame (+ (ceiling (cdr size))
- height (- inner-height)))
- ;; The frame size after the above `set-frame-*' calls may
- ;; differ from what we specified, due to window manager
- ;; interference. We have to call `frame-width' and
- ;; `frame-height' to get the actual results.
- (set-frame-parameter frame 'image-mode-saved-params
- (list (cons (frame-width)
- (frame-height))
- (cons width height)
- window-configuration)))))))
+ (fit-frame-to-buffer frame)
+ ;; The frame size after the above `set-frame-*' calls may
+ ;; differ from what we specified, due to window manager
+ ;; interference. We have to call `frame-width' and
+ ;; `frame-height' to get the actual results.
+ (set-frame-parameter frame 'image-mode-saved-params
+ (list (cons (frame-text-width frame)
+ (frame-text-height frame))
+ (cons frame-width frame-height)
+ window-configuration))))))
;;; Image Mode setup
@@ -625,6 +631,8 @@ image as text, when opening such images in `image-mode'."
(put 'image-mode 'mode-class 'special)
+(declare-function image-converter-initialize "image-converter.el")
+
;;;###autoload
(defun image-mode ()
"Major mode for image files.
@@ -645,10 +653,17 @@ Key bindings:
;; Bail out early if we have no image data.
(if (zerop (buffer-size))
(funcall (if (called-interactively-p 'any) 'error 'message)
- (if (file-exists-p buffer-file-name)
- "Empty file"
- "(New file)"))
- (image-mode--display)))
+ (if (stringp buffer-file-name)
+ (if (file-exists-p buffer-file-name)
+ "Empty file"
+ "(New file)")
+ "Empty buffer"))
+ (image-mode--display)
+ ;; Ensure that we recognize externally parsed image formats in
+ ;; commands like `n'.
+ (when image-use-external-converter
+ (require 'image-converter)
+ (image-converter-initialize))))
(defun image-mode--display ()
(if (not (image-get-display-property))
@@ -1195,8 +1210,9 @@ replacing the current Image mode buffer."
"Return an alist of type/buffer for all \"parent\" buffers to image FILE.
This is normally a list of Dired buffers, but can also be archive and
tar mode buffers."
- (let ((buffers nil)
- (dir (file-name-directory file)))
+ (let* ((non-essential t) ; Do not block for remote buffers.
+ (buffers nil)
+ (dir (file-name-directory file)))
(cond
((and (boundp 'tar-superior-buffer)
tar-superior-buffer)
@@ -1211,6 +1227,8 @@ tar mode buffers."
(dolist (buffer (buffer-list))
(with-current-buffer buffer
(when (and (derived-mode-p 'dired-mode)
+ (equal (file-remote-p dir)
+ (file-remote-p default-directory))
(equal (file-truename dir)
(file-truename default-directory)))
(push (cons 'dired (current-buffer)) buffers))))
@@ -1541,8 +1559,8 @@ return value is suitable for appending to an image spec."
(defun image-transform-fit-to-height ()
"Fit the current image to the height of the current window."
- (interactive)
(declare (obsolete nil "29.1"))
+ (interactive)
(setq image-transform-resize 'fit-height)
(image-toggle-display-image))
diff --git a/lisp/image.el b/lisp/image.el
index c9165f77814..bdaaec608ef 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -171,18 +171,18 @@ or \"ffmpeg\") is installed."
(define-error 'unknown-image-type "Unknown image type")
-;; Map put into text properties on images.
-(defvar image-map
- (let ((map (make-sparse-keymap)))
- (define-key map "-" 'image-decrease-size)
- (define-key map "+" 'image-increase-size)
- (define-key map [C-wheel-down] 'image-mouse-decrease-size)
- (define-key map [C-mouse-5] 'image-mouse-decrease-size)
- (define-key map [C-wheel-up] 'image-mouse-increase-size)
- (define-key map [C-mouse-4] 'image-mouse-increase-size)
- (define-key map "r" 'image-rotate)
- (define-key map "o" 'image-save)
- map))
+(defvar-keymap image-map
+ :doc "Map put into text properties on images."
+ "-" #'image-decrease-size
+ "+" #'image-increase-size
+ "r" #'image-rotate
+ "o" #'image-save
+ "h" #'image-flip-horizontally
+ "v" #'image-flip-vertically
+ "C-<wheel-down>" #'image-mouse-decrease-size
+ "C-<mouse-5>" #'image-mouse-decrease-size
+ "C-<wheel-up>" #'image-mouse-increase-size
+ "C-<mouse-4>" #'image-mouse-increase-size)
(defun image-load-path-for-library (library image &optional path no-error)
"Return a suitable search path for images used by LIBRARY.
@@ -382,6 +382,7 @@ be determined."
"Determine the type of image file FILE from its name.
Value is a symbol specifying the image type, or nil if type cannot
be determined."
+ (declare (obsolete image-supported-file-p "29.1"))
(let (type first (case-fold-search t))
(catch 'found
(dolist (elem image-type-file-name-regexps first)
@@ -391,6 +392,20 @@ be determined."
;; If nothing seems to be supported, return first type that matched.
(or first (setq first type))))))))
+ ;;;###autoload
+(defun image-supported-file-p (file)
+ "Say whether Emacs has native support for displaying TYPE.
+The value is a symbol specifying the image type, or nil if type
+cannot be determined (or if Emacs doesn't have built-in support
+for the image type)."
+ (let ((case-fold-search t)
+ type)
+ (catch 'found
+ (dolist (elem image-type-file-name-regexps)
+ (when (and (string-match-p (car elem) file)
+ (image-type-available-p (setq type (cdr elem))))
+ (throw 'found type))))))
+
(declare-function image-convert-p "image-converter.el"
(source &optional image-format))
(declare-function image-convert "image-converter.el"
@@ -419,7 +434,7 @@ type if we can't otherwise guess it."
(require 'image-converter)
(image-convert-p source data-p))))
(or (image-type-from-file-header source)
- (image-type-from-file-name source)
+ (image-supported-file-p source)
(and image-use-external-converter
(progn
(require 'image-converter)
@@ -431,15 +446,6 @@ type if we can't otherwise guess it."
(error "Invalid image type `%s'" type))
type)
-
-(if (fboundp 'image-metadata) ; eg not --without-x
- (define-obsolete-function-alias 'image-extension-data
- 'image-metadata "24.1"))
-
-(define-obsolete-variable-alias
- 'image-library-alist
- 'dynamic-library-alist "24.1")
-
;;;###autoload
(defun image-type-available-p (type)
"Return t if image type TYPE is available.
@@ -463,6 +469,7 @@ must be available."
(and auto
(or (eq auto t) (image-type-available-p type)))))
+(defvar image-convert-to-format)
;;;###autoload
(defun create-image (file-or-data &optional type data-p &rest props)
@@ -500,7 +507,7 @@ Image file names that are not absolute are searched for in the
(when (eq type 'image-convert)
(require 'image-converter)
(setq file-or-data (image-convert file-or-data data-format)
- type 'png
+ type (intern image-convert-to-format)
data-p t)))
(when (image-type-available-p type)
(let ((image
@@ -750,13 +757,15 @@ SPECS is a list of image specifications.
Each image specification in SPECS is a property list. The contents of
a specification are image type dependent. All specifications must at
-least contain the properties `:type TYPE' and either `:file FILE' or
-`:data DATA', where TYPE is a symbol specifying the image type,
-e.g. `xbm', FILE is the file to load the image from, and DATA is a
-string containing the actual image data. The specification whose TYPE
-is supported, and FILE exists, is used to construct the image
-specification to be returned. Return nil if no specification is
-satisfied.
+least contain either the property `:file FILE' or `:data DATA',
+where FILE is the file to load the image from, and DATA is a string
+containing the actual image data. If the property `:type TYPE' is
+omitted or nil, try to determine the image type from its first few
+bytes of image data. If that doesn't work, and the property `:file
+FILE' provide a file name, use its file extension as image type.
+If `:type TYPE' is provided, it must match the actual type
+determined for FILE or DATA by `create-image'. Return nil if no
+specification is satisfied.
If CACHE is non-nil, results are cached and returned on subsequent calls.
@@ -771,22 +780,44 @@ Image files should not be larger than specified by `max-image-size'."
(let* ((spec (car specs))
(type (plist-get spec :type))
(data (plist-get spec :data))
- (file (plist-get spec :file))
- found)
- (when (image-type-available-p type)
- (cond ((stringp file)
- (if (setq found (image-search-load-path file))
- (setq image
- (cons 'image (plist-put (copy-sequence spec)
- :file found)))))
- ((not (null data))
- (setq image (cons 'image spec)))))
+ (file (plist-get spec :file)))
+ (cond
+ ((stringp file)
+ (when (setq file (image-search-load-path file))
+ ;; At this point, remove the :type and :file properties.
+ ;; `create-image' will set them depending on image file.
+ (setq image (cons 'image (copy-sequence spec)))
+ (setf (image-property image :type) nil)
+ (setf (image-property image :file) nil)
+ (and (setq image (ignore-errors
+ (apply #'create-image file nil nil
+ (cdr image))))
+ ;; Ensure, if a type has been provided, it is
+ ;; consistent with the type returned by
+ ;; `create-image'. If not, return nil.
+ (not (null type))
+ (not (eq type (image-property image :type)))
+ (setq image nil))))
+ ((not (null data))
+ ;; At this point, remove the :type and :data properties.
+ ;; `create-image' will set them depending on image data.
+ (setq image (cons 'image (copy-sequence spec)))
+ (setf (image-property image :type) nil)
+ (setf (image-property image :data) nil)
+ (and (setq image (ignore-errors
+ (apply #'create-image data nil t
+ (cdr image))))
+ ;; Ensure, if a type has been provided, it is
+ ;; consistent with the type returned by
+ ;; `create-image'. If not, return nil.
+ (not (null type))
+ (not (eq type (image-property image :type)))
+ (setq image nil))))
(setq specs (cdr specs))))
(when cache
(setf (gethash orig-specs find-image--cache) image))
image)))
-
;;;###autoload
(defmacro defimage (symbol specs &optional doc)
"Define SYMBOL as an image, and return SYMBOL.
@@ -894,8 +925,9 @@ Frames are indexed from 0. Optional argument NOCHECK non-nil means
do not check N is within the range of frames present in the image."
(unless nocheck
(if (< n 0) (setq n 0)
- (setq n (min n (1- (car (plist-get (cdr image)
- :animate-multi-frame-data)))))))
+ (setq n (min n (1- (car (or (plist-get (cdr image)
+ :animate-multi-frame-data)
+ (image-multi-frame-p image))))))))
(plist-put (cdr image) :index n)
(force-window-update (plist-get (cdr image) :animate-buffer)))
@@ -1249,6 +1281,22 @@ changing the displayed image size does not affect the saved image."
(write-region (point-min) (point-max)
(read-file-name "Write image to file: ")))))
+(defun image-flip-horizontally ()
+ "Horizontally flip the image under point."
+ (interactive)
+ (let ((image (image--get-image)))
+ (image-flush image)
+ (setf (image-property image :flip)
+ (not (image-property image :flip)))))
+
+(defun image-flip-vertically ()
+ "Vertically flip the image under point."
+ (interactive)
+ (let ((image (image--get-image)))
+ (image-rotate 180)
+ (setf (image-property image :flip)
+ (not (image-property image :flip)))))
+
(provide 'image)
;;; image.el ends here
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 35666b954ca..fd4673dc1b6 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -100,7 +100,10 @@ mirrored or not.")
"Parse FILE (a JPEG file) and return the Exif data, if any.
The return value is a list of Exif items.
-If the data is invalid, an `exif-error' is signaled."
+If the data is invalid, an `exif-error' is signaled.
+
+Also see the `exif-field' convenience function to extract data
+from the return value of this function."
(with-temp-buffer
(set-buffer-multibyte nil)
(insert-file-contents-literally file)
@@ -110,7 +113,10 @@ If the data is invalid, an `exif-error' is signaled."
"Parse BUFFER (which should be a JPEG file) and return the Exif data, if any.
The return value is a list of Exif items.
-If the data is invalid, an `exif-error' is signaled."
+If the data is invalid, an `exif-error' is signaled.
+
+Also see the `exif-field' convenience function to extract data
+from the return value of this function."
(setq buffer (or buffer (current-buffer)))
(with-current-buffer buffer
(if enable-multibyte-characters
diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el
index 78a2df72c4c..8c49c1edf28 100644
--- a/lisp/image/gravatar.el
+++ b/lisp/image/gravatar.el
@@ -45,7 +45,7 @@
"Time to live in seconds for gravatar cache entries.
If a requested gravatar has been cached for longer than this, it
is retrieved anew. The default value is 30 days."
- :type 'integer
+ :type 'natnum
;; Restricted :type to number of seconds.
:version "27.1"
:group 'gravatar)
diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el
index 460ff16adb0..9ce46f01a33 100644
--- a/lisp/image/image-converter.el
+++ b/lisp/image/image-converter.el
@@ -46,6 +46,16 @@ formats that are to be supported: Only the suffixes that map to
:type 'symbol
:version "27.1")
+(defcustom image-convert-to-format "png"
+ "The image format to convert to.
+This should be a string like \"png\" or \"ppm\" or some
+other (preferably lossless) format that Emacs understands
+natively. The converter chosen has to support the format, and if
+not, conversion will fail."
+ :group 'image
+ :version "29.1"
+ :type 'string)
+
(defvar image-converter-regexp nil
"A regexp that matches the file name suffixes that can be converted.")
@@ -58,15 +68,19 @@ formats that are to be supported: Only the suffixes that map to
(imagemagick :command "convert" :probe ("-list" "format")))
"List of supported image converters to try.")
+(defun image-converter-initialize ()
+ "Determine the external image converter to be used.
+This also determines which external formats we can parse."
+ (unless image-converter
+ (image-converter--find-converter)))
+
(defun image-convert-p (source &optional data-p)
"Return `image-convert' if SOURCE is an image that can be converted.
SOURCE can either be a file name or a string containing image
data. In the latter case, DATA-P should be non-nil. If DATA-P
is a string, it should be a MIME format string like
\"image/gif\"."
- ;; Find an installed image converter.
- (unless image-converter
- (image-converter--find-converter))
+ (image-converter-initialize)
;; When image-converter was customized
(when (and image-converter (not image-converter-regexp))
(when-let ((formats (image-converter--probe image-converter)))
@@ -85,22 +99,23 @@ is a string, it should be a MIME format string like
'image-convert))
(defun image-convert (image &optional image-format)
- "Convert IMAGE file to the PNG format.
+ "Convert IMAGE file to an image format Emacs understands.
+This will usually be \"png\", but this is controlled by the
+`image-convert-to-format' user option.
+
IMAGE can either be a file name or image data.
To pass in image data, IMAGE should a string containing the image
data, and IMAGE-FORMAT should be a symbol with a MIME format name
like \"image/webp\". For instance:
- (image-convert data-string 'image/bmp)
+ (image-convert data-string \\='image/bmp)
IMAGE can also be an image object as returned by `create-image'.
-This function converts the image to PNG, and the converted image
-data is returned as a string."
- ;; Find an installed image converter.
- (unless image-converter
- (image-converter--find-converter))
+This function converts the image the preferred format, and the
+converted image data is returned as a string."
+ (image-converter-initialize)
(unless image-converter
(error "No external image converters available"))
(when (and image-format
@@ -120,7 +135,9 @@ data is returned as a string."
(if (listp image)
;; Return an image object that's the same as we were passed,
;; but ignore the :type value.
- (apply #'create-image (buffer-string) 'png t
+ (apply #'create-image (buffer-string)
+ (intern image-convert-to-format)
+ t
(cl-loop for (key val) on (cdr image) by #'cddr
unless (eq key :type)
append (list key val)))
@@ -227,24 +244,29 @@ Only suffixes that map to `image-mode' are returned."
(cadr (split-string (symbol-name image-format) "/"))))
(defun image-converter--convert-magick (type source image-format)
- (let ((command (image-converter--value type :command)))
+ (let ((command (image-converter--value type :command))
+ (coding-system-for-read 'no-conversion))
(unless (zerop (if image-format
;; We have the image data in SOURCE.
(progn
(insert source)
- (apply #'call-process-region (point-min) (point-max)
- (car command) t t nil
- (append
- (cdr command)
- (list (format "%s:-"
- (image-converter--mime-type
- image-format))
- "png:-"))))
+ (let ((coding-system-for-write 'no-conversion))
+ (apply #'call-process-region (point-min) (point-max)
+ (car command) t t nil
+ (append
+ (cdr command)
+ (list (format "%s:-"
+ (image-converter--mime-type
+ image-format))
+ (concat image-convert-to-format
+ ":-"))))))
;; SOURCE is a file name.
(apply #'call-process (car command)
nil t nil
(append (cdr command)
- (list (expand-file-name source) "png:-")))))
+ (list (expand-file-name source)
+ (concat image-convert-to-format
+ ":-"))))))
;; If the command failed, hopefully the buffer contains the
;; error message.
(buffer-string))))
@@ -252,24 +274,27 @@ Only suffixes that map to `image-mode' are returned."
(cl-defmethod image-converter--convert ((type (eql 'ffmpeg)) source
image-format)
"Convert using ffmpeg."
- (let ((command (image-converter--value type :command)))
+ (let ((command (image-converter--value type :command))
+ (coding-system-for-read 'no-conversion))
(unless (zerop (if image-format
(progn
(insert source)
- (apply #'call-process-region
- (point-min) (point-max) (car command)
- t '(t nil) nil
- (append
- (cdr command)
- (list "-i" "-"
- "-c:v" "png"
- "-f" "image2pipe" "-"))))
+ (let ((coding-system-for-write 'no-conversion))
+ (apply #'call-process-region
+ (point-min) (point-max) (car command)
+ t '(t nil) nil
+ (append
+ (cdr command)
+ (list "-i" "-"
+ "-c:v" image-convert-to-format
+ "-f" "image2pipe" "-")))))
(apply #'call-process
(car command)
nil '(t nil) nil
(append (cdr command)
(list "-i" (expand-file-name source)
- "-c:v" "png" "-f" "image2pipe"
+ "-c:v" image-convert-to-format
+ "-f" "image2pipe"
"-")))))
"ffmpeg error when converting")))
diff --git a/lisp/imenu.el b/lisp/imenu.el
index a87860f0065..dcd816cb7a8 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -87,7 +87,7 @@ This might not yet be honored by all index-building functions."
(defcustom imenu-auto-rescan-maxout 600000
"Imenu auto-rescan is disabled in buffers larger than this size (in bytes).
Also see `imenu-max-index-time'."
- :type 'integer
+ :type 'natnum
:version "26.2")
(defcustom imenu-use-popup-menu 'on-mouse
@@ -132,7 +132,7 @@ element should come before the second. The arguments are cons cells;
(defcustom imenu-max-items 25
"Maximum number of elements in a mouse menu for Imenu."
- :type 'integer)
+ :type 'natnum)
(defcustom imenu-space-replacement "."
"The replacement string for spaces in index names.
@@ -464,14 +464,14 @@ Non-nil arguments are in recursive calls."
`(keymap ,title
,@(mapcar
(lambda (item)
- `(,(car item) ,(car item)
+ `(,(intern (car item)) ,(car item)
,@(cond
((imenu--subalist-p item)
(imenu--create-keymap (car item) (cdr item) cmd))
(t
(lambda () (interactive)
(if cmd (funcall cmd item) item))))))
- alist)))
+ (seq-filter #'identity alist))))
(defun imenu--in-alist (str alist)
"Check whether the string STR is contained in multi-level ALIST."
@@ -899,6 +899,13 @@ for more information."
(`(,name . ,pos) (imenu (list name pos imenu-default-goto-function)))
(_ (error "Unknown imenu item: %S" index-item)))))
+(defun imenu-flush-cache ()
+ "Flush the current imenu cache.
+This forces a full rescan of the buffer to recreate the index alist
+next time `imenu' is invoked."
+ (imenu--cleanup)
+ (setq imenu--index-alist nil))
+
(provide 'imenu)
;;; imenu.el ends here
diff --git a/lisp/indent.el b/lisp/indent.el
index 40669b38424..f52b729051d 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 "Only complete 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
@@ -170,7 +171,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))
@@ -182,21 +183,21 @@ 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)
+ (and (eq tab-first-completion 'eol)
(eolp))
- (and (member tab-first-completion
- '(word word-or-paren word-or-paren-or-punct))
- (not (member 2 syn)))
- (and (member tab-first-completion
- '(word-or-paren word-or-paren-or-punct))
- (not (or (member 4 syn)
- (member 5 syn))))
- (and (equal tab-first-completion 'word-or-paren-or-punct)
- (not (member 1 syn)))))
+ (and (memq tab-first-completion
+ '(word word-or-paren word-or-paren-or-punct))
+ (not (eql 2 syn)))
+ (and (memq tab-first-completion
+ '(word-or-paren word-or-paren-or-punct))
+ (not (or (eql 4 syn)
+ (eql 5 syn))))
+ (and (eq tab-first-completion 'word-or-paren-or-punct)
+ (not (eql 1 syn)))))
(completion-at-point))
;; If a prefix argument was given, rigidly indent the following
@@ -239,21 +240,23 @@ Blank lines are ignored."
(current-indentation))))
indent))))
-(defvar indent-rigidly-map
- (let ((map (make-sparse-keymap)))
- (define-key map [left] 'indent-rigidly-left)
- (define-key map [right] 'indent-rigidly-right)
- (define-key map [S-left] 'indent-rigidly-left-to-tab-stop)
- (define-key map [S-right] 'indent-rigidly-right-to-tab-stop)
- map)
- "Transient keymap for adjusting indentation interactively.
-It is activated by calling `indent-rigidly' interactively.")
+(defvar-keymap indent-rigidly-map
+ :doc "Transient keymap for adjusting indentation interactively.
+It is activated by calling `indent-rigidly' interactively."
+ "TAB" #'indent-rigidly-right
+ "<left>" #'indent-rigidly-left
+ "<right>" #'indent-rigidly-right
+ "S-<left>" #'indent-rigidly-left-to-tab-stop
+ "S-<right>" #'indent-rigidly-right-to-tab-stop)
+(put 'indent-rigidly-right :advertised-binding (kbd "<right>"))
(defun indent-rigidly (start end arg &optional interactive)
"Indent all lines starting in the region.
If called interactively with no prefix argument, activate a
transient mode in which the indentation can be adjusted interactively
by typing \\<indent-rigidly-map>\\[indent-rigidly-left], \\[indent-rigidly-right], \\[indent-rigidly-left-to-tab-stop], or \\[indent-rigidly-right-to-tab-stop].
+In addition, \\`TAB' is also bound (and calls `indent-rigidly-right').
+
Typing any other key exits this mode, and this key is then
acted upon as normally. If `transient-mark-mode' is enabled,
exiting also deactivates the mark.
@@ -267,11 +270,8 @@ Negative values of ARG indent backward, so you can remove all
indentation by specifying a large negative ARG."
(interactive "r\nP\np")
(if (and (not arg) interactive)
- (progn
- (message
- (substitute-command-keys
- "Indent region with \\<indent-rigidly-map>\\[indent-rigidly-left], \\[indent-rigidly-right], \\[indent-rigidly-left-to-tab-stop], or \\[indent-rigidly-right-to-tab-stop]."))
- (set-transient-map indent-rigidly-map t #'deactivate-mark))
+ (set-transient-map indent-rigidly-map t #'deactivate-mark
+ "Indent region with %k")
(save-excursion
(goto-char end)
(setq end (point-marker))
diff --git a/lisp/info-look.el b/lisp/info-look.el
index 64f16df4dc3..6c8ef091a08 100644
--- a/lisp/info-look.el
+++ b/lisp/info-look.el
@@ -280,7 +280,7 @@ system."
;;;###autoload (put 'info-lookup-symbol 'info-file "emacs")
;;;###autoload
-(defun info-lookup-symbol (symbol &optional mode)
+(defun info-lookup-symbol (symbol &optional mode same-window)
"Look up and display documentation of SYMBOL in the relevant Info manual.
SYMBOL should be an identifier: a function or method, a macro, a variable,
a data type, a class, etc.
@@ -293,10 +293,13 @@ MODE is the major mode whose Info manuals to search for the documentation
of SYMBOL. It defaults to the current buffer's `major-mode'; if that
mode doesn't have any Info manuals known to Emacs, the command will
prompt for MODE to use, with completion. With prefix arg, the command
-always prompts for MODE."
+always prompts for MODE.
+
+Is SAME-WINDOW, try to reuse the current window instead of
+popping up a new one."
(interactive
(info-lookup-interactive-arguments 'symbol current-prefix-arg))
- (info-lookup 'symbol symbol mode))
+ (info-lookup 'symbol symbol mode same-window))
;;;###autoload (put 'info-lookup-file 'info-file "emacs")
;;;###autoload
@@ -388,7 +391,7 @@ If optional argument QUERY is non-nil, query for the help mode."
spec
mode)))
-(defun info-lookup (topic item mode)
+(defun info-lookup (topic item mode &optional same-window)
"Display the documentation of TOPIC whose name is ITEM, using MODE's manuals.
TOPIC should be any known symbol of a help topic type, such as `file'
or `symbol'. See the documentation of HELP-TOPIC in the doc
@@ -397,7 +400,10 @@ ITEM is the item whose documentation to search: file name if
TOPIC is `file', a symbol if TOPIC is `symbol', etc.
MODE is the `major-mode' whose Info manuals to search for documentation
of ITEM; if it's nil, the function uses `info-lookup-file-name-alist'
-and the current buffer's file name to guess the mode.."
+and the current buffer's file name to guess the mode.
+
+If SAME-WINDOW, reuse the current window. If nil, pop to a
+different window."
(or mode (setq mode (info-lookup-select-mode)))
(setq mode (info-lookup--item-to-mode item mode))
(if-let ((info (info-lookup->mode-value topic mode)))
@@ -423,19 +429,21 @@ and the current buffer's file name to guess the mode.."
(if (not info-lookup-other-window-flag)
(info)
(save-window-excursion (info))
- (let* ((info-window (get-buffer-window "*info*" t))
- (info-frame (and info-window (window-frame info-window))))
- (if (and info-frame
- (not (eq info-frame (selected-frame)))
- (display-multi-frame-p)
- (memq info-frame (frames-on-display-list)))
- ;; *info* is visible in another frame on same display.
- ;; Raise that frame and select the window.
- (progn
- (select-window info-window)
- (raise-frame info-frame))
- ;; In any other case, switch to *info* in another window.
- (switch-to-buffer-other-window "*info*")))))
+ (if same-window
+ (pop-to-buffer-same-window "*info*")
+ (let* ((info-window (get-buffer-window "*info*" t))
+ (info-frame (and info-window (window-frame info-window))))
+ (if (and info-frame
+ (not (eq info-frame (selected-frame)))
+ (display-multi-frame-p)
+ (memq info-frame (frames-on-display-list)))
+ ;; *info* is visible in another frame on same display.
+ ;; Raise that frame and select the window.
+ (progn
+ (select-window info-window)
+ (raise-frame info-frame))
+ ;; In any other case, switch to *info* another window.
+ (switch-to-buffer-other-window "*info*"))))))
(while (and (not found) modes)
(setq doc-spec (info-lookup->doc-spec topic (car modes)))
(while (and (not found) doc-spec)
@@ -1010,6 +1018,13 @@ Return nil if there is nothing appropriate in the buffer near point."
("(cl)Function Index" nil "^ -+ .*: " "\\( \\|$\\)")
("(cl)Variable Index" nil "^ -+ .*: " "\\( \\|$\\)")))
+(info-lookup-maybe-add-help
+ :mode 'emacs-lisp-only
+ :regexp "[^][()`'‘’,\" \t\n]+"
+ :doc-spec '(("(elisp)Index" nil "^ -+ .*: " "\\( \\|$\\)")
+ ("(cl)Function Index" nil "^ -+ .*: " "\\( \\|$\\)")
+ ("(cl)Variable Index" nil "^ -+ .*: " "\\( \\|$\\)")))
+
(mapc
(lambda (elem)
(let* ((prefix (car elem)))
@@ -1067,6 +1082,7 @@ Return nil if there is nothing appropriate in the buffer near point."
("url" "Variable Index" "Function Index")
("vhdl" "(vhdl-mode)Variable Index" "(vhdl-mode)Command Index")
("viper" "Variable Index" "Function Index")
+ ("vtable" "Index")
("widget" "Index")
("wisent" "Index")
("woman" "Variable Index" "Command Index")))
diff --git a/lisp/info.el b/lisp/info.el
index f4f0f9790cd..7fdb893edc5 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -133,8 +133,6 @@ orientation. See `Info-nth-menu-item'.")
:version "22.1"
:type 'boolean)
-;; It's unfortunate that nil means no fontification, as opposed to no limit,
-;; since that differs from font-lock-maximum-size.
(defcustom Info-fontify-maximum-menu-size 400000
"Maximum size of menu to fontify if `font-lock-mode' is non-nil.
Set to nil to disable node fontification; set to t for no limit."
@@ -161,59 +159,8 @@ A header-line does not scroll with the rest of the buffer."
"Face used to highlight matches in an index entry."
:version "24.4")
-;; This is a defcustom largely so that we can get the benefit
-;; of `custom-initialize-delay'. Perhaps it would work to make it a
-;; `defvar' and explicitly give it a `standard-value' property, and
-;; call `custom-initialize-delay' on it.
-;; The value is initialized at startup time, when command-line calls
-;; `custom-reevaluate-setting' on all the defcustoms in
-;; `custom-delayed-init-variables'. This is somewhat sub-optimal, as ideally
-;; this should be done when Info mode is first invoked.
;;;###autoload
-(defcustom Info-default-directory-list
- (let* ((config-dir
- (file-name-as-directory
- ;; Self-contained NS build with info/ in the app-bundle.
- (or (and (featurep 'ns)
- (let ((dir (expand-file-name "../info" data-directory)))
- (if (file-directory-p dir) dir)))
- configure-info-directory)))
- (prefixes
- ;; Directory trees in which to look for info subdirectories
- (prune-directory-list '("/usr/local/" "/usr/" "/opt/")))
- (suffixes
- ;; Subdirectories in each directory tree that may contain info
- ;; directories.
- '("share/" ""))
- (standard-info-dirs
- (apply #'nconc
- (mapcar (lambda (pfx)
- (let ((dirs
- (mapcar (lambda (sfx)
- (concat pfx sfx "info/"))
- suffixes)))
- (prune-directory-list dirs)))
- prefixes)))
- ;; If $(prefix)/share/info is not one of the standard info
- ;; directories, they are probably installing an experimental
- ;; version of Emacs, so make sure that experimental version's Info
- ;; files override the ones in standard directories.
- (dirs
- (if (member config-dir standard-info-dirs)
- ;; FIXME? What is the point of adding it again at the end
- ;; when it is already present earlier in the list?
- (nconc standard-info-dirs (list config-dir))
- (cons config-dir standard-info-dirs))))
- (if (not (eq system-type 'windows-nt))
- dirs
- ;; Include the info directory near where Emacs executable was installed.
- (let* ((instdir (file-name-directory invocation-directory))
- (dir1 (expand-file-name "../info/" instdir))
- (dir2 (expand-file-name "../../../info/" instdir)))
- (cond ((file-exists-p dir1) (append dirs (list dir1)))
- ((file-exists-p dir2) (append dirs (list dir2)))
- (t dirs)))))
-
+(defcustom Info-default-directory-list nil
"Default list of directories to search for Info documentation files.
They are searched in the order they are given in the list.
Therefore, the directory of Info files that come with Emacs
@@ -224,15 +171,12 @@ first in this list.
Once Info is started, the list of directories to search
comes from the variable `Info-directory-list'.
-This variable `Info-default-directory-list' is used as the default
-for initializing `Info-directory-list' when Info is started, unless
-the environment variable INFOPATH is set.
-
-Although this is a customizable variable, that is mainly for technical
-reasons. Normally, you should either set INFOPATH or customize
-`Info-additional-directory-list', rather than changing this variable."
- :initialize #'custom-initialize-delay
- :type '(repeat directory))
+
+This variable is used as the default for initializing
+`Info-directory-list' when Info is started, unless the
+environment variable INFOPATH is set."
+ :type '(repeat directory)
+ :version "29.1")
(defvar Info-directory-list nil
"List of directories to search for Info documentation files.
@@ -314,7 +258,7 @@ This only has an effect if `Info-hide-note-references' is non-nil."
"Depth of breadcrumbs to display.
0 means do not display breadcrumbs."
:version "23.1"
- :type 'integer)
+ :type 'natnum)
(defcustom Info-search-whitespace-regexp "\\s-+"
"If non-nil, regular expression to match a sequence of whitespace chars.
@@ -679,6 +623,51 @@ in `Info-file-supports-index-cookies-list'."
(cdr (assoc file Info-file-supports-index-cookies-list)))
+(defun Info--default-directory-list ()
+ "Compute a directory list suitable for Info."
+ (let* ((config-dir
+ (file-name-as-directory
+ ;; Self-contained NS build with info/ in the app-bundle.
+ (or (and (featurep 'ns)
+ (let ((dir (expand-file-name "../info" data-directory)))
+ (if (file-directory-p dir) dir)))
+ configure-info-directory)))
+ (prefixes
+ ;; Directory trees in which to look for info subdirectories
+ (prune-directory-list '("/usr/local/" "/usr/" "/opt/")))
+ (suffixes
+ ;; Subdirectories in each directory tree that may contain info
+ ;; directories.
+ '("share/" ""))
+ (standard-info-dirs
+ (apply #'nconc
+ (mapcar (lambda (pfx)
+ (let ((dirs
+ (mapcar (lambda (sfx)
+ (concat pfx sfx "info/"))
+ suffixes)))
+ (prune-directory-list dirs)))
+ prefixes)))
+ ;; If $(prefix)/share/info is not one of the standard info
+ ;; directories, they are probably installing an experimental
+ ;; version of Emacs, so make sure that experimental version's Info
+ ;; files override the ones in standard directories.
+ (dirs
+ (if (member config-dir standard-info-dirs)
+ ;; FIXME? What is the point of adding it again at the end
+ ;; when it is already present earlier in the list?
+ (nconc standard-info-dirs (list config-dir))
+ (cons config-dir standard-info-dirs))))
+ (if (not (eq system-type 'windows-nt))
+ dirs
+ ;; Include the info directory near where Emacs executable was installed.
+ (let* ((instdir (file-name-directory invocation-directory))
+ (dir1 (expand-file-name "../info/" instdir))
+ (dir2 (expand-file-name "../../../info/" instdir)))
+ (cond ((file-exists-p dir1) (append dirs (list dir1)))
+ ((file-exists-p dir2) (append dirs (list dir2)))
+ (t dirs))))))
+
(defun Info-default-dirs ()
(let ((source (expand-file-name "info/" source-directory))
(sibling (if installation-directory
@@ -701,25 +690,11 @@ in `Info-file-supports-index-cookies-list'."
sibling
;; Uninstalled, builddir == srcdir
source))
- (if (or (member alternative Info-default-directory-list)
- ;; On DOS/NT, we use movable executables always,
- ;; and we must always find the Info dir at run time.
- (if (memq system-type '(ms-dos windows-nt))
- nil
- ;; Use invocation-directory for Info
- ;; only if we used it for exec-directory also.
- (not (string= exec-directory
- (expand-file-name "lib-src/"
- installation-directory))))
- (not (file-exists-p alternative)))
- Info-default-directory-list
- ;; `alternative' contains the Info files that came with this
- ;; version, so we should look there first. `Info-insert-dir'
- ;; currently expects to find `alternative' first on the list.
- (cons alternative
- ;; Don't drop the last part, it might contain non-Emacs stuff.
- ;; (reverse (cdr (reverse
- Info-default-directory-list)))) ;; )))
+ ;; `alternative' contains the Info files that came with this
+ ;; version, so we should look there first. `Info-insert-dir'
+ ;; currently expects to find `alternative' first on the list.
+ (append (cons alternative Info-default-directory-list)
+ (Info--default-directory-list))))
(defun info-initialize ()
"Initialize `Info-directory-list', if that hasn't been done yet."
@@ -930,17 +905,20 @@ find a node."
filename)))
filename))))
-(defun Info-find-node (filename nodename &optional no-going-back strict-case)
+(defun Info-find-node (filename nodename &optional no-going-back strict-case
+ noerror)
"Go to an Info node specified as separate FILENAME and NODENAME.
NO-GOING-BACK is non-nil if recovering from an error in this function;
it says do not attempt further (recursive) error recovery.
This function first looks for a case-sensitive match for NODENAME;
if none is found it then tries a case-insensitive match (unless
-STRICT-CASE is non-nil)."
+STRICT-CASE is non-nil).
+
+If NOERROR, inhibit error messages when we can't find the node."
(info-initialize)
(setq nodename (info--node-canonicalize-whitespace nodename))
- (setq filename (Info-find-file filename))
+ (setq filename (Info-find-file filename noerror))
;; Go into Info buffer.
(or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
;; Record the node we are leaving, if we were in one.
@@ -1845,41 +1823,22 @@ directories to search if FILENAME is not absolute; SUFFIXES is a
list of valid filename suffixes for Info files. See
`try-completion' for a description of the remaining arguments."
(setq suffixes (remove "" suffixes))
- (when (file-name-absolute-p string)
- (setq dirs (list (file-name-directory string))))
(let ((names nil)
- (names-sans-suffix nil)
- (suffix (concat (regexp-opt suffixes t) "\\'"))
- (string-dir (file-name-directory string)))
+ (suffix (concat (regexp-opt suffixes t) "\\'")))
(dolist (dir dirs)
- (unless dir
- (setq dir default-directory))
- (if string-dir (setq dir (expand-file-name string-dir dir)))
(when (file-directory-p dir)
- (dolist (file (file-name-all-completions
- (file-name-nondirectory string) dir))
- ;; If the file name has no suffix or a standard suffix,
- ;; include it.
- (and (or (null (file-name-extension file))
- (string-match suffix file))
- ;; But exclude subfiles of split Info files.
- (not (string-match "-[0-9]+\\'" file))
- ;; And exclude backup files.
- (not (string-match "~\\'" file))
- (push (if string-dir (concat string-dir file) file) names))
- ;; If the file name ends in a standard suffix,
- ;; add the unsuffixed name as a completion option.
- (when (string-match suffix file)
- (setq file (substring file 0 (match-beginning 0)))
- (push (if string-dir (concat string-dir file) file)
- names-sans-suffix)))))
- ;; If there is just one file, don't duplicate it with suffixes,
- ;; so `Info-read-node-name-1' will be able to complete a single
- ;; candidate and to add the terminating ")".
- (if (and (= (length names) 1) (= (length names-sans-suffix) 1))
- (setq names names-sans-suffix)
- (setq names (append names-sans-suffix names)))
- (complete-with-action action names string pred)))
+ (dolist (file (directory-files dir))
+ ;; If the file name has a standard suffix,
+ ;; include it (without the suffix).
+ (when (and (string-match suffix file)
+ ;; But exclude subfiles of split Info files.
+ (not (string-match "\\.info-[0-9]+" file))
+ ;; And exclude backup files.
+ (not (string-match "~\\'" file)))
+ (push (substring file 0 (match-beginning 0))
+ names)))))
+ (complete-with-action action (delete-dups (nreverse names))
+ string pred)))
(defun Info-read-node-name-1 (string predicate code)
"Internal function used by `Info-read-node-name'.
@@ -2247,7 +2206,7 @@ and is not in the header line or a tag table."
(let ((backward (< found beg-found)))
(not
(or
- (and (not search-invisible)
+ (and (not (eq search-invisible t))
(if backward
(or (text-property-not-all found beg-found 'invisible nil)
(text-property-not-all found beg-found 'display nil))
@@ -2638,7 +2597,8 @@ new buffer."
(if (eq alt-default t) (setq alt-default str))
;; Don't add this string if it's a duplicate.
(or (assoc-string str completions t)
- (push str completions))))
+ (push str completions)))
+ (setq completions (nreverse completions)))
;; If no good default was found, try an alternate.
(or default
(setq default alt-default))
@@ -3655,13 +3615,16 @@ MATCHES is a list of index matches found by `Info-apropos-matches'.")
(format " (line %s)" (nth 3 entry))
"")))))))))
-(defun Info-apropos-matches (string)
+(defun Info-apropos-matches (string &optional regexp)
"Collect STRING matches from all known Info files on your system.
+If REGEXP, use regexp matching instead of literal matching.
Return a list of matches where each element is in the format
\((FILENAME INDEXTEXT NODENAME LINENUMBER))."
(unless (string= string "")
(let ((pattern (format "\n\\* +\\([^\n]*\\(%s\\)[^\n]*\\):[ \t]+\\([^\n]+\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
- (regexp-quote string)))
+ (if regexp
+ string
+ (regexp-quote string))))
(ohist Info-history)
(ohist-list Info-history-list)
(current-node Info-current-node)
@@ -3686,9 +3649,9 @@ Return a list of matches where each element is in the format
(dolist (manual (nreverse manuals))
(message "Searching %s" manual)
(condition-case err
- (if (setq nodes (Info-index-nodes (Info-find-file manual)))
+ (if (setq nodes (Info-index-nodes (Info-find-file manual t)))
(save-excursion
- (Info-find-node manual (car nodes))
+ (Info-find-node manual (car nodes) nil nil t)
(while
(progn
(goto-char (point-min))
@@ -3715,19 +3678,22 @@ Return a list of matches where each element is in the format
(or (nreverse matches) t))))
;;;###autoload
-(defun info-apropos (string)
- "Grovel indices of all known Info files on your system for STRING.
-Build a menu of the possible matches."
- (interactive "sIndex apropos: ")
+(defun info-apropos (string &optional regexp)
+ "Search indices of all known Info files on your system for STRING.
+If REGEXP (interactively, the prefix), use a regexp match.
+
+Display a menu of the possible matches."
+ (interactive "sIndex apropos: \nP")
(if (equal string "")
(Info-find-node Info-apropos-file "Top")
- (let* ((nodes Info-apropos-nodes) nodename)
+ (let ((nodes Info-apropos-nodes)
+ nodename)
(while (and nodes (not (equal string (nth 1 (car nodes)))))
(setq nodes (cdr nodes)))
(if nodes
- (Info-find-node Info-apropos-file (car (car nodes)))
+ (Info-find-node Info-apropos-file (car (car nodes)) nil nil t)
(setq nodename (format "Index for ‘%s’" string))
- (push (list nodename string (Info-apropos-matches string))
+ (push (list nodename string (Info-apropos-matches string regexp))
Info-apropos-nodes)
(Info-find-node Info-apropos-file nodename)))))
@@ -4268,7 +4234,7 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
(Info-history-menu e "Back in history" Info-history 'Info-history-back))
(defun Info-history-forward-menu (e)
- "Pop up the menu with a list of Info nodes visited with ‘Info-history-back’."
+ "Pop up the menu with a list of Info nodes visited with `Info-history-back'."
(interactive "e" Info-mode)
(Info-history-menu e "Forward in history" Info-history-forward 'Info-history-forward))
@@ -4318,7 +4284,8 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
(substring str (match-end 0))))
(setq i (1+ i)))
(setq items
- (cons str items))))
+ (cons str items)))
+ (setq items (nreverse items)))
(while (and items (< number 9))
(setq current (car items)
items (cdr items)
@@ -4521,7 +4488,9 @@ Advanced commands:
(setq-local revert-buffer-function #'Info-revert-buffer-function)
(setq-local font-lock-defaults '(Info-mode-font-lock-keywords t t))
(Info-set-mode-line)
- (setq-local bookmark-make-record-function #'Info-bookmark-make-record))
+ (setq-local bookmark-make-record-function #'Info-bookmark-make-record)
+ (unless search-default-mode
+ (isearch-fold-quotes-mode)))
;; When an Info buffer is killed, make sure the associated tags buffer
;; is killed too.
@@ -4693,7 +4662,7 @@ the variable `Info-file-list-for-emacs'."
(defvar Info-link-keymap
(let ((keymap (make-sparse-keymap)))
(define-key keymap [header-line down-mouse-1] 'mouse-drag-header-line)
- (define-key keymap [header-line mouse-1] 'mouse-select-window)
+ (define-key keymap [header-line mouse-1] 'Info-mouse-follow-link)
(define-key keymap [header-line mouse-2] 'Info-mouse-follow-link)
(define-key keymap [mouse-2] 'Info-mouse-follow-link)
(define-key keymap [follow-link] 'mouse-face)
@@ -5449,6 +5418,7 @@ type returned by `Info-bookmark-make-record', which see."
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk)))))
+(put 'Info-bookmark-jump 'bookmark-handler-type "Info")
;;;###autoload
(defun info-display-manual (manual)
@@ -5462,7 +5432,8 @@ completion alternatives to currently visited manuals."
(progn
(info-initialize)
(completing-read "Manual name: "
- (info--manual-names current-prefix-arg)
+ (info--filter-manual-names
+ (info--manual-names current-prefix-arg))
nil t))))
(let ((blist (buffer-list))
(manual-re (concat "\\(/\\|\\`\\)" manual "\\(\\.\\|\\'\\)"))
@@ -5490,6 +5461,22 @@ completion alternatives to currently visited manuals."
(info (Info-find-file manual)
(generate-new-buffer-name "*info*")))))
+(defun info--filter-manual-names (names)
+ (cl-flet ((strip (name)
+ (replace-regexp-in-string "\\([-.]info\\)?\\(\\.gz\\)?\\'"
+ "" name)))
+ (seq-uniq (sort (seq-filter
+ (lambda (name)
+ (and (not (string-match-p "info-[0-9]" name))
+ (not (member name '("./" "../" "ChangeLog"
+ "NEWS" "README")))))
+ names)
+ ;; We prefer the shorter names ("foo" over "foo.gz").
+ (lambda (s1 s2)
+ (< (length s1) (length s2))))
+ (lambda (s1 s2)
+ (equal (strip s1) (strip s2))))))
+
(defun info--manual-names (visited-only)
(let (names)
(dolist (buffer (buffer-list))
diff --git a/lisp/informat.el b/lisp/informat.el
index e7595fa541a..c126ab5b1a1 100644
--- a/lisp/informat.el
+++ b/lisp/informat.el
@@ -158,7 +158,7 @@
;;;###autoload
(defcustom Info-split-threshold 262144
"The number of characters by which `Info-split' splits an info file."
- :type 'integer
+ :type 'natnum
:version "23.1"
:group 'texinfo)
diff --git a/lisp/international/ccl.el b/lisp/international/ccl.el
index 9188e3d6ae4..c7d883276db 100644
--- a/lisp/international/ccl.el
+++ b/lisp/international/ccl.el
@@ -577,7 +577,7 @@ Return register which holds a value of the expression."
(ccl-check-register expr cmd)))
(defun ccl-compile-branch-blocks (code rrr blocks)
- "Compile BLOCKs of BRANCH statement. CODE is 'branch or 'read-branch.
+ "Compile BLOCKs of BRANCH statement. CODE is `branch' or `read-branch'.
REG is a register which holds a value of EXPRESSION part. BLOCKs
is a list of CCL-BLOCKs."
(let ((branches (length blocks))
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index 080e7898c47..ca28222c815 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -303,7 +303,8 @@ with L, LRE, or LRO Unicode bidi character type.")
(setq charsets (cdr charsets))))
(modify-category-entry '(#x600 . #x6ff) ?b)
(modify-category-entry '(#x870 . #x8ff) ?b)
-(modify-category-entry '(#xfb50 . #xfdff) ?b)
+(modify-category-entry '(#xfb50 . #xfdcf) ?b)
+(modify-category-entry '(#xfdf0 . #xfdff) ?b)
(modify-category-entry '(#xfe70 . #xfefe) ?b)
;; Cyrillic character set (ISO-8859-5)
@@ -1440,6 +1441,10 @@ Setup `char-width-table' appropriate for non-CJK language environment."
(set-char-table-range char-script-table range 'tibetan))
'tibetan)
+;; Fix some exceptions that blocks.awk/Blocks.txt couldn't get right.
+(set-char-table-range char-script-table '(#x2ea . #x2eb) 'bopomofo)
+(set-char-table-range char-script-table #xab65 'greek)
+
;;; Setting unicode-category-table.
@@ -1522,8 +1527,11 @@ Setup `char-width-table' appropriate for non-CJK language environment."
;; We can't use the \N{name} things here, because this file is used
;; too early in the build process.
-(defvar glyphless--bidi-control-characters
- '(#x202a ; ?\N{left-to-right embedding}
+(defvar bidi-control-characters
+ '(#x200e ; ?\N{left-to-right mark}
+ #x200f ; ?\N{right-to-left mark}
+ #x061c ; ?\N{arabic letter mark}
+ #x202a ; ?\N{left-to-right embedding}
#x202b ; ?\N{right-to-left embedding}
#x202d ; ?\N{left-to-right override}
#x202e ; ?\N{right-to-left override}
@@ -1531,7 +1539,14 @@ Setup `char-width-table' appropriate for non-CJK language environment."
#x2067 ; ?\N{right-to-left isolate}
#x2068 ; ?\N{first strong isolate}
#x202c ; ?\N{pop directional formatting}
- #x2069)) ; ?\N{pop directional isolate})
+ #x2069) ; ?\N{pop directional isolate}
+ "List of bidirectional control characters.")
+
+(defun bidi-string-strip-control-characters (string)
+ "Strip bidi control characters from STRING and return the result."
+ (apply #'string (seq-filter (lambda (char)
+ (not (memq char bidi-control-characters)))
+ string)))
(defun update-glyphless-char-display (&optional variable value)
"Make the setting of `glyphless-char-display-control' take effect.
@@ -1578,8 +1593,7 @@ option `glyphless-char-display'."
(or (aref char-acronym-table from)
"UNK")))
(when (or (eq target 'format-control)
- (memq from
- glyphless--bidi-control-characters))
+ (memq from bidi-control-characters))
(set-char-table-range glyphless-char-display
from this-method)))
(setq from (1+ from))))))
diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el
index 264a1f09dc2..4f4d4f48320 100644
--- a/lisp/international/emoji.el
+++ b/lisp/international/emoji.el
@@ -31,6 +31,7 @@
(require 'cl-extra)
(require 'transient)
(require 'multisession)
+(require 'generate-lisp-file)
(defgroup emoji nil
"Inserting Emojis."
@@ -55,6 +56,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)
@@ -64,18 +73,13 @@
(defvar emoji--insert-buffer)
;;;###autoload
-(defun emoji-insert (&optional text)
- "Choose and insert an emoji glyph.
-If TEXT (interactively, the prefix argument), choose the emoji
-by typing its Unicode Standard name (with completion), instead
-of selecting from emoji display."
- (interactive "*P")
+(defun emoji-insert ()
+ "Choose and insert an emoji glyph."
+ (interactive "*")
(emoji--init)
- (if text
- (emoji--choose-emoji)
- (unless (fboundp 'emoji--command-Emoji)
- (emoji--define-transient))
- (funcall (intern "emoji--command-Emoji"))))
+ (unless (fboundp 'emoji--command-Emoji)
+ (emoji--define-transient))
+ (funcall (intern "emoji--command-Emoji")))
;;;###autoload
(defun emoji-recent ()
@@ -90,8 +94,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))
@@ -406,8 +411,8 @@ the name is not known."
(dolist (glyph glyphs)
(remhash glyph emoji--derived)))
(with-temp-buffer
- (insert ";; Generated file -- do not edit. -*- lexical-binding:t -*-
-;; Copyright © 1991-2021 Unicode, Inc.
+ (generate-lisp-file-heading file 'emoji--generate-file)
+ (insert ";; Copyright © 1991-2021 Unicode, Inc.
;; Generated from Unicode data files by emoji.el.
;; The source for this file is found in the admin/unidata/emoji-test.txt
;; file in the Emacs sources. The Unicode data files are used under the
@@ -417,18 +422,7 @@ the name is not known."
(insert (format "(defconst %s '" var))
(pp (symbol-value var) (current-buffer))
(insert (format "\n) ;; End %s\n\n" var)))
- (insert ";; Local" " Variables:
-;; coding: utf-8
-;; version-control: never
-;; no-byte-"
- ;; Obfuscate to not inhibit compilation of this file, too.
- "compile: t
-;; no-update-autoloads: t
-;; End:
-
-\(provide 'emoji-labels)
-
-\;;; emoji-labels.el ends here\n")
+ (generate-lisp-file-trailer file)
(write-region (point-min) (point-max) file)))
(defun emoji--base-name (name derivations)
@@ -647,29 +641,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.
@@ -683,6 +695,39 @@ We prefer the earliest unique letter."
(emoji--define-transient
(cons "Choose Emoji" (cons glyph derived))))))))))
+(defvar-keymap emoji-zoom-map
+ "+" #'emoji-zoom-increase
+ "-" #'emoji-zoom-decrease)
+
+;;;###autoload
+(defun emoji-zoom-increase (&optional factor)
+ "Increase the size of the character under point.
+FACTOR is the multiplication factor for the size."
+ (interactive)
+ (set-transient-map emoji-zoom-map t nil "Zoom with %k")
+ (let* ((factor (or factor 1.1))
+ (old (get-text-property (point) 'face))
+ (height (or (and (consp old)
+ (plist-get old :height))
+ 1.0))
+ (inhibit-read-only t))
+ (with-silent-modifications
+ (if (consp old)
+ (add-text-properties
+ (point) (1+ (point))
+ (list 'face (plist-put (copy-sequence old) :height (* height factor))
+ 'rear-nonsticky t))
+ (add-face-text-property (point) (1+ (point))
+ (list :height (* height factor)))
+ (put-text-property (point) (1+ (point))
+ 'rear-nonsticky t)))))
+
+;;;###autoload
+(defun emoji-zoom-decrease ()
+ "Decrease the size of the character under point."
+ (interactive)
+ (emoji-zoom-increase 0.9))
+
(provide 'emoji)
;;; emoji.el ends here
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index a2e0838a427..8d34aa99c39 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -182,8 +182,21 @@
(canadian-aboriginal #x14C0)
(ogham #x168F)
(runic #x16A0)
+ (tagalog #x1700)
+ (hanunoo #x1720)
+ (buhid #x1740)
+ (tagbanwa #x1760)
(khmer #x1780)
(mongolian #x1826)
+ (limbu #x1901 #x1920 #x1936)
+ (buginese #x1A00 #x1A1E)
+ (balinese #x1B13 #x1B35 #x1B5E)
+ (sundanese #x1B8A #x1BAB #x1CC4)
+ (batak #x1BC2 #x1BE7 #x1BFF)
+ (lepcha #x1C00 #x1C24 #x1C40)
+ (tai-le #x1950)
+ (tai-lue #x1980)
+ (tai-tham #x1A20 #x1A55 #x1A61 #x1A80)
(symbol . [#x201C #x2200 #x2500])
(braille #x2800)
(ideographic-description #x2FF0)
@@ -193,9 +206,12 @@
(kanbun #x319D)
(han #x5B57)
(yi #xA288)
- (javanese #xA980)
+ (syloti-nagri #xA807 #xA823 #xA82C)
+ (rejang #xA930 #xA947 #xA95F)
+ (javanese #xA98F #xA9B4 #xA9CA)
(cham #xAA00)
(tai-viet #xAA80)
+ (meetei-mayek #xABC0 #xABE3 #xAAE0 #xAAF6)
(hangul #xAC00)
(linear-b #x10000)
(aegean-number #x10100)
@@ -223,22 +239,24 @@
(lydian #x10920)
(kharoshthi #x10A00)
(manichaean #x10AC0)
- (hanifi-rohingya #x10D00)
+ (hanifi-rohingya #x10D00 #x10D24 #x10D39)
(yezidi #x10E80)
(old-sogdian #x10F00)
(sogdian #x10F30)
(chorasmian #x10FB0)
(elymaic #x10FE0)
(old-uyghur #x10F70)
+ (brahmi #x11013 #x11045 #x11052 #x11065)
+ (kaithi #x1108D #x110B0 #x110BD)
(mahajani #x11150)
- (sinhala-archaic-number #x111E1)
+ (sharada #x11191 #x111B3 #x111CD)
(khojki #x11200)
(khudawadi #x112B0)
- (grantha #x11305)
+ (grantha #x11315 #x1133E #x11374)
(newa #x11400)
- (tirhuta #x11481)
- (siddham #x11580)
- (modi #x11600)
+ (tirhuta #x11481 #x1148F #x114D0)
+ (siddham #x1158E #x115AF #x115D4)
+ (modi #x1160E #x11630 #x11655)
(takri #x11680)
(dogra #x11800)
(warang-citi #x118A1)
@@ -251,9 +269,8 @@
(marchen #x11C72)
(masaram-gondi #x11D00)
(gunjala-gondi #x11D60)
- (makasar #x11EE0)
+ (makasar #x11EE0 #x11EF7)
(cuneiform #x12000)
- (cuneiform-numbers-and-punctuation #x12400)
(cypro-minoan #x12F90)
(egyptian #x13000)
(mro #x16A40)
@@ -262,7 +279,6 @@
(pahawh-hmong #x16B11)
(medefaidrin #x16E40)
(tangut #x17000)
- (tangut-components #x18800)
(khitan-small-script #x18B00)
(nushu #x1B170)
(duployan-shorthand #x1BC20)
@@ -285,7 +301,7 @@
(defvar otf-script-alist)
-;; The below was synchronized with the latest Oct 8, 2020 version of
+;; The below was synchronized with the latest Sep 12, 2021 version of
;; https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
(setq otf-script-alist
'((adlm . adlam)
@@ -318,6 +334,7 @@
(copt . coptic)
(xsux . cuneiform)
(cprt . cypriot)
+ (cpmn . cypro-minoan)
(cyrl . cyrillic)
(dsrt . deseret)
(deva . devanagari)
@@ -341,7 +358,7 @@
(gur2 . gurmukhi)
(hani . han)
(hang . hangul)
- (jamo . hangul)
+ (jamo . hangul) ; Not recommended; use 'hang' instead.
(rohg . hanifi-rohingya)
(hano . hanunoo)
(hatr . hatran)
@@ -364,8 +381,8 @@
(latn . latin)
(lepc . lepcha)
(limb . limbu)
- (lina . linear_a)
- (linb . linear_b)
+ (lina . linear-a)
+ (linb . linear-b)
(lisu . lisu)
(lyci . lycian)
(lydi . lydian)
@@ -391,6 +408,7 @@
(musc . musical-symbol)
(mym2 . burmese)
(mymr . burmese)
+ (nand . nandinagari)
(nbat . nabataean)
(newa . newa)
(nko\ . nko)
@@ -405,6 +423,7 @@
(sogo . old-sogdian)
(sarb . old-south-arabian)
(orkh . old-turkic)
+ (ougr . old-uyghur)
(orya . oriya)
(ory2 . oriya)
(osge . osage)
@@ -430,17 +449,18 @@
(sora . sora-sompeng)
(soyo . soyombo)
(sund . sundanese)
- (sylo . syloti_nagri)
+ (sylo . syloti-nagri)
(syrc . syriac)
(tglg . tagalog)
(tagb . tagbanwa)
- (tale . tai_le)
+ (tale . tai-le)
(talu . tai-lue)
(lana . tai-tham)
(tavt . tai-viet)
(takr . takri)
(taml . tamil)
(tml2 . tamil)
+ (tnsa . tangsa)
(tang . tangut)
(telu . telugu)
(tel2 . telugu)
@@ -449,7 +469,9 @@
(tibt . tibetan)
(tfng . tifinagh)
(tirh . tirhuta)
+ (toto . toto)
(ugar . ugaritic)
+ (vith . vithkuqi)
(vai\ . vai)
(wcho . wancho)
(wara . warang-citi)
@@ -738,11 +760,24 @@
cham
ogham
runic
+ tagalog
+ hanunoo
+ buhid
+ tagbanwa
+ limbu
+ buginese
+ balinese
+ sundanese
+ batak
+ lepcha
symbol
braille
yi
+ syloti-nagri
+ rejang
javanese
tai-viet
+ meetei-mayek
aegean-number
ancient-greek-number
ancient-symbol
@@ -760,15 +795,22 @@
cypriot-syllabary
phoenician
lydian
+ hanifi-rohingya
yezidi
kharoshthi
manichaean
chorasmian
elymaic
old-uyghur
+ brahmi
+ kaithi
+ sharada
+ grantha
+ tirhuta
+ siddham
+ modi
makasar
dives-akuru
- cuneiform-numbers-and-punctuation
cuneiform
egyptian
tangsa
@@ -783,6 +825,7 @@
counting-rod-numeral
toto
adlam
+ tai-tham
mahjong-tile
domino-tile
emoji))
@@ -935,6 +978,13 @@
(set-fontset-font "fontset-default" 'emoji
'("Noto Color Emoji" . "iso10646-1") nil 'prepend)
+ ;; This supports the display of Tamil Supplement characters. As
+ ;; these characters are pretty simple and do not need reordering,
+ ;; ligatures, vowel signs, virama etc., neither tml2 nor other OTF
+ ;; features are needed here.
+ (set-fontset-font "fontset-default" '(#x11FC0 . #x11FFF)
+ '("Noto Sans Tamil Supplement" . "iso10646-1") nil 'append)
+
;; Append CJK fonts for characters other than han, kana, cjk-misc.
;; Append fonts for scripts whose name is also a charset name.
(let* ((data (build-default-fontset-data))
@@ -1137,7 +1187,7 @@ Internal use only. Should be called at startup time."
(defconst xlfd-regexp-pointsize-subnum 6) ; POINT_SIZE
(defconst xlfd-regexp-resx-subnum 7) ; RESOLUTION_X
(defconst xlfd-regexp-resy-subnum 8) ; RESOLUTION_Y
-(defconst xlfd-regexp-spacing-subnum 8) ; SPACING
+(defconst xlfd-regexp-spacing-subnum 9) ; SPACING
(defconst xlfd-regexp-avgwidth-subnum 10) ; AVERAGE_WIDTH
(defconst xlfd-regexp-registry-subnum 11) ; REGISTRY and ENCODING
diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el
index 10f8ce6efbd..90fdc06b1e4 100644
--- a/lisp/international/iso-transl.el
+++ b/lisp/international/iso-transl.el
@@ -112,8 +112,12 @@
(",," . [?¸])
(",A" . [?Ą])
(",C" . [?Ç])
+ (",N" . [?Ņ])
+ (",S" . [?Ş])
(",a" . [?ą])
(",c" . [?ç])
+ (",n" . [?ņ])
+ (",s" . [?ş])
("*-" . [?­])
("-" . [?­])
("*." . [?·])
@@ -134,7 +138,23 @@
("*<" . [?«])
("<" . [?«])
("*=" . [?¯])
- ("=" . [?¯])
+ ("==" . [?¯])
+ ("=A" . [?Ā])
+ ("=a" . [?ā])
+ ("=E" . [?Ē])
+ ("=e" . [?ē])
+ ("=/E" . [?Ǣ])
+ ("=/e" . [?ǣ])
+ ("=G" . [?Ḡ])
+ ("=g" . [?ḡ])
+ ("=I" . [?Ī])
+ ("=i" . [?ī])
+ ("=O" . [?Ō])
+ ("=o" . [?ō])
+ ("=U" . [?Ū])
+ ("=u" . [?ū])
+ ("=Y" . [?Ȳ])
+ ("=y" . [?ȳ])
("*>" . [?»])
(">" . [?»])
("*?" . [?¿])
@@ -149,11 +169,34 @@
("R" . [?®])
("*S" . [?§])
("S" . [?§])
+ ("*T" . [?™])
+ ("T" . [?™])
("*Y" . [?¥])
("Y" . [?¥])
+ ("^0" . [?⁰])
("^1" . [?¹])
("^2" . [?²])
("^3" . [?³])
+ ("^4" . [?⁴])
+ ("^5" . [?⁵])
+ ("^6" . [?⁶])
+ ("^7" . [?⁷])
+ ("^8" . [?⁸])
+ ("^9" . [?⁹])
+ ("^+" . [?⁺])
+ ("^-" . [?⁻])
+ ("_0" . [?₀])
+ ("_1" . [?₁])
+ ("_2" . [?₂])
+ ("_3" . [?₃])
+ ("_4" . [?₄])
+ ("_5" . [?₅])
+ ("_6" . [?₆])
+ ("_7" . [?₇])
+ ("_8" . [?₈])
+ ("_9" . [?₉])
+ ("_+" . [?₊])
+ ("_-" . [?₋])
("^A" . [?Â])
("^E" . [?Ê])
("^I" . [?Î])
@@ -164,6 +207,30 @@
("^i" . [?î])
("^o" . [?ô])
("^u" . [?û])
+ ("^^A" . [?Ǎ])
+ ("^^C" . [?Č])
+ ("^^E" . [?Ě])
+ ("^^G" . [?Ǧ])
+ ("^^I" . [?Ǐ])
+ ("^^K" . [?Ǩ])
+ ("^^N" . [?Ň])
+ ("^^O" . [?Ǒ])
+ ("^^R" . [?Ř])
+ ("^^S" . [?Š])
+ ("^^U" . [?Ǔ])
+ ("^^Z" . [?Ž])
+ ("^^a" . [?ǎ])
+ ("^^c" . [?č])
+ ("^^e" . [?ě])
+ ("^^g" . [?ǧ])
+ ("^^i" . [?ǐ])
+ ("^^k" . [?ǩ])
+ ("^^n" . [?ň])
+ ("^^o" . [?ǒ])
+ ("^^r" . [?ř])
+ ("^^s" . [?š])
+ ("^^u" . [?ǔ])
+ ("^^z" . [?ž])
("_a" . [?ª])
("_o" . [?º])
("`A" . [?À])
@@ -182,10 +249,10 @@
("o" . [?°])
("Oe" . [?œ])
("OE" . [?Œ])
- ("*u" . [?µ])
- ("u" . [?µ])
- ("*m" . [?µ])
- ("m" . [?µ])
+ ("*u" . [?μ])
+ ("u" . [?μ])
+ ("*m" . [?μ])
+ ("m" . [?μ])
("*x" . [?×])
("x" . [?×])
("*|" . [?¦])
@@ -308,12 +375,12 @@ sequence VECTOR. (VECTOR is normally one character long.)")
(defun iso-transl-set-language (lang)
"Set shorter key bindings for some characters relevant for LANG.
-This affects the `C-x 8' prefix.
+This affects the \\`C-x 8' prefix.
Note that only a few languages are supported, and for more
rigorous support it is recommended to use an input method
instead. Also note that many of these characters can be input
-with the regular `C-x 8' map without having to specify a language
+with the regular \\`C-x 8' map without having to specify a language
here."
(interactive (list (let ((completion-ignore-case t))
(completing-read "Set which language? "
diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el
index 704f1a1ae62..ec68d8c8046 100644
--- a/lisp/international/ja-dic-cnv.el
+++ b/lisp/international/ja-dic-cnv.el
@@ -44,6 +44,8 @@
;;; Code:
+(require 'generate-lisp-file)
+
;; Name of a file to generate from SKK dictionary.
(defvar ja-dic-filename "ja-dic.el")
@@ -295,7 +297,7 @@
(setq skkdic-okuri-nasi-entries-count (length skkdic-okuri-nasi-entries))
(progress-reporter-done progress))))
-(defun skkdic-convert-okuri-nasi (skkbuf buf)
+(defun skkdic-convert-okuri-nasi (skkbuf buf &optional no-reduction)
(with-current-buffer buf
(insert ";; Setting okuri-nasi entries.\n"
"(skkdic-set-okuri-nasi\n")
@@ -311,7 +313,9 @@
(setq count (1+ count))
(progress-reporter-update progress count)
(if (setq candidates
- (skkdic-reduced-candidates skkbuf kana candidates))
+ (if no-reduction
+ candidates
+ (skkdic-reduced-candidates skkbuf kana candidates)))
(progn
(insert "\"" kana)
(while candidates
@@ -322,10 +326,11 @@
(progress-reporter-done progress))
(insert ")\n\n")))
-(defun skkdic-convert (filename &optional dirname)
+(defun skkdic-convert (filename &optional dirname no-reduction)
"Generate Emacs Lisp file from Japanese dictionary file FILENAME.
The format of the dictionary file should be the same as SKK dictionaries.
-Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)."
+Saves the output as `ja-dic-filename', in directory DIRNAME (if specified).
+If NO-REDUCTION is non-nil, do not reduce the dictionary vocabulary."
(interactive "FSKK dictionary file: ")
(let* ((skkbuf (get-buffer-create " *skkdic-unannotated*"))
(buf (get-buffer-create "*skkdic-work*")))
@@ -335,18 +340,15 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)."
(insert-file-contents (expand-file-name filename)))
(re-search-forward "^[^;]")
(while (re-search-forward ";[^\n/]*/" nil t)
- (replace-match "/")))
+ (replace-match "/" t t)))
;; Setup and generate the header part of working buffer.
(with-current-buffer buf
(erase-buffer)
(buffer-disable-undo)
- (insert ";;; ja-dic.el --- dictionary for Japanese input method"
- " -*- lexical-binding:t -*-\n"
- ";;\tGenerated by the command `skkdic-convert'\n"
- ";;\tOriginal SKK dictionary file: "
+ (generate-lisp-file-heading ja-dic-filename 'skkdic-convert :code nil)
+ (insert ";; Original SKK dictionary file: "
(file-relative-name (expand-file-name filename) dirname)
"\n\n"
- ";; This file is part of GNU Emacs.\n\n"
";;; Start of the header of the original SKK dictionary.\n\n")
(set-buffer skkbuf)
(goto-char 1)
@@ -389,18 +391,12 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)."
(skkdic-collect-okuri-nasi)
;; Convert okuri-nasi general entries.
- (skkdic-convert-okuri-nasi skkbuf buf)
+ (skkdic-convert-okuri-nasi skkbuf buf no-reduction)
;; Postfix
(with-current-buffer buf
(goto-char (point-max))
- (insert ";;\n(provide 'ja-dic)\n\n"
- ";; Local Variables:\n"
- ";; version-control: never\n"
- ";; no-update-autoloads: t\n"
- ";; coding: utf-8\n"
- ";; End:\n\n"
- ";;; ja-dic.el ends here\n")))
+ (generate-lisp-file-trailer ja-dic-filename :compile t)))
;; Save the working buffer.
(set-buffer buf)
@@ -427,15 +423,21 @@ To get complete usage, invoke:
(message "To convert SKK-JISYO.L into skkdic.el:")
(message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert SKK-JISYO.L")
(message "To convert SKK-JISYO.L into DIR/ja-dic.el:")
- (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L"))
- (let (targetdir filename)
+ (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L")
+ (message "To convert SKK-JISYO.L into skkdic.el without reducing dictionary vocabulary:")
+ (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert --no-reduction SKK-JISYO.L"))
+ (let (targetdir filename no-reduction)
(if (string= (car command-line-args-left) "-dir")
(progn
(setq command-line-args-left (cdr command-line-args-left))
(setq targetdir (expand-file-name (car command-line-args-left)))
(setq command-line-args-left (cdr command-line-args-left))))
+ (if (string= (car command-line-args-left) "--no-reduction")
+ (progn
+ (setq no-reduction t)
+ (setq command-line-args-left (cdr command-line-args-left))))
(setq filename (expand-file-name (car command-line-args-left)))
- (skkdic-convert filename targetdir)))
+ (skkdic-convert filename targetdir no-reduction)))
(kill-emacs 0))
diff --git a/lisp/international/latin1-disp.el b/lisp/international/latin1-disp.el
index c8ff93aeb21..7054077fb02 100644
--- a/lisp/international/latin1-disp.el
+++ b/lisp/international/latin1-disp.el
@@ -1,4 +1,4 @@
-;;; latin1-disp.el --- display tables for other ISO 8859 on Latin-1 terminals -*- lexical-binding: t; -*-
+;;; latin1-disp.el --- display tables for non-ASCII on Latin-1 terminals -*- lexical-binding: t; -*-
;; Copyright (C) 2000-2022 Free Software Foundation, Inc.
@@ -22,18 +22,23 @@
;;; Commentary:
-;; This package sets up display of ISO 8859-n for n>1 by substituting
-;; Latin-1 characters and sequences of them for characters which can't
-;; be displayed, either because we're on a tty or because we don't
-;; have the relevant window system fonts available. For instance,
-;; Latin-9 is very similar to Latin-1, so we can display most Latin-9
-;; characters using the Latin-1 characters at the same code point and
-;; fall back on more-or-less mnemonic ASCII sequences for the rest.
+;; This package sets up display of many non-ASCII characters by
+;; substituting ASCII and Latin-1 characters and sequences of them for
+;; characters which can't be displayed, either because we're on a tty
+;; or because we don't have the relevant window system fonts
+;; available. For instance, Latin-9 is very similar to Latin-1, so we
+;; can display most Latin-9 characters using the Latin-1 characters at
+;; the same code point and fall back on more-or-less mnemonic ASCII
+;; sequences for the rest.
;; For the Latin charsets the ASCII sequences are mostly consistent
;; with the Quail prefix input sequences. Latin-4 uses the Quail
;; postfix sequences since a prefix method isn't defined for Latin-4.
+;; Non-Latin non-ASCII characters are generally displayed as ASCII
+;; strings remotely reminiscent of the original characters, as best as
+;; possible. See `latin1-display-ucs-per-lynx'.
+
;; [A different approach is taken in the DOS display tables in
;; term/internal.el, and the relevant ASCII sequences from there are
;; available as an alternative; see `latin1-display-mnemonic'. Only
@@ -759,2426 +764,2425 @@ turn it off and display Unicode characters literally. The display
isn't changed if the display can render Unicode characters."
(interactive "p")
(if (> arg 0)
- (unless (char-displayable-p #x101) ; a with macron
- ;; It doesn't look as though we have a Unicode font.
- (let ((latin1-display-format "%s"))
- (mapc
- (lambda (l)
- (apply 'latin1-display-char l))
- ;; Table derived by running Lynx on a suitable list of
- ;; characters in a utf-8 file, except for some added by
- ;; hand at the end.
- '((?\Ā "A")
- (?\ā "a")
- (?\Ă "A")
- (?\ă "a")
- (?\Ą "A")
- (?\ą "a")
- (?\Ć "C")
- (?\ć "c")
- (?\Ĉ "C")
- (?\ĉ "c")
- (?\Ċ "C")
- (?\ċ "c")
- (?\Č "C")
- (?\č "c")
- (?\Ď "D")
- (?\ď "d")
- (?\Đ "Ð")
- (?\đ "d/")
- (?\Ē "E")
- (?\ē "e")
- (?\Ĕ "E")
- (?\ĕ "e")
- (?\Ė "E")
- (?\ė "e")
- (?\Ę "E")
- (?\ę "e")
- (?\Ě "E")
- (?\ě "e")
- (?\Ĝ "G")
- (?\ĝ "g")
- (?\Ğ "G")
- (?\ğ "g")
- (?\Ġ "G")
- (?\ġ "g")
- (?\Ģ "G")
- (?\ģ "g")
- (?\Ĥ "H")
- (?\ĥ "h")
- (?\Ħ "H/")
- (?\ħ "H")
- (?\Ĩ "I")
- (?\ĩ "i")
- (?\Ī "I")
- (?\ī "i")
- (?\Ĭ "I")
- (?\ĭ "i")
- (?\Į "I")
- (?\į "i")
- (?\İ "I")
- (?\ı "i")
- (?\IJ "IJ")
- (?\ij "ij")
- (?\Ĵ "J")
- (?\ĵ "j")
- (?\Ķ "K")
- (?\ķ "k")
- (?\ĸ "kk")
- (?\Ĺ "L")
- (?\ĺ "l")
- (?\Ļ "L")
- (?\ļ "l")
- (?\Ľ "L")
- (?\ľ "l")
- (?\Ŀ "L.")
- (?\ŀ "l.")
- (?\Ł "L/")
- (?\ł "l/")
- (?\Ń "N")
- (?\ń "n")
- (?\Ņ "N")
- (?\ņ "n")
- (?\Ň "N")
- (?\ň "n")
- (?\ʼn "'n")
- (?\Ŋ "NG")
- (?\ŋ "N")
- (?\Ō "O")
- (?\ō "o")
- (?\Ŏ "O")
- (?\ŏ "o")
- (?\Ő "O\"")
- (?\ő "o\"")
- (?\Π"OE")
- (?\œ "oe")
- (?\Ŕ "R")
- (?\ŕ "r")
- (?\Ŗ "R")
- (?\ŗ "r")
- (?\Ř "R")
- (?\ř "r")
- (?\Ś "S")
- (?\ś "s")
- (?\Ŝ "S")
- (?\ŝ "s")
- (?\Ş "S")
- (?\ş "s")
- (?\Š "S")
- (?\š "s")
- (?\Ţ "T")
- (?\ţ "t")
- (?\Ť "T")
- (?\ť "t")
- (?\Ŧ "T/")
- (?\ŧ "t/")
- (?\Ũ "U")
- (?\ũ "u")
- (?\Ū "U")
- (?\ū "u")
- (?\Ŭ "U")
- (?\ŭ "u")
- (?\Ů "U")
- (?\ů "u")
- (?\Ű "U\"")
- (?\ű "u\"")
- (?\Ų "U")
- (?\ų "u")
- (?\Ŵ "W")
- (?\ŵ "w")
- (?\Ŷ "Y")
- (?\ŷ "y")
- (?\Ÿ "Y")
- (?\Ź "Z")
- (?\ź "z")
- (?\Ż "Z")
- (?\ż "z")
- (?\Ž "Z")
- (?\ž "z")
- (?\ſ "s1")
- (?\Ƈ "C2")
- (?\ƈ "c2")
- (?\Ƒ "F2")
- (?\ƒ " f")
- (?\Ƙ "K2")
- (?\ƙ "k2")
- (?\Ơ "O9")
- (?\ơ "o9")
- (?\Ƣ "OI")
- (?\ƣ "oi")
- (?\Ʀ "yr")
- (?\Ư "U9")
- (?\ư "u9")
- (?\Ƶ "Z/")
- (?\ƶ "z/")
- (?\Ʒ "ED")
- (?\Ǎ "A")
- (?\ǎ "a")
- (?\Ǐ "I")
- (?\ǐ "i")
- (?\Ǒ "O")
- (?\ǒ "o")
- (?\Ǔ "U")
- (?\ǔ "u")
- (?\Ǖ "U:-")
- (?\ǖ "u:-")
- (?\Ǘ "U:'")
- (?\ǘ "u:'")
- (?\Ǚ "U:<")
- (?\ǚ "u:<")
- (?\Ǜ "U:!")
- (?\ǜ "u:!")
- (?\Ǟ "A1")
- (?\ǟ "a1")
- (?\Ǡ "A7")
- (?\ǡ "a7")
- (?\Ǣ "A3")
- (?\ǣ "a3")
- (?\Ǥ "G/")
- (?\ǥ "g/")
- (?\Ǧ "G")
- (?\ǧ "g")
- (?\Ǩ "K")
- (?\ǩ "k")
- (?\Ǫ "O")
- (?\ǫ "o")
- (?\Ǭ "O1")
- (?\ǭ "o1")
- (?\Ǯ "EZ")
- (?\ǯ "ez")
- (?\ǰ "j")
- (?\Ǵ "G")
- (?\ǵ "g")
- (?\Ǻ "AA'")
- (?\ǻ "aa'")
- (?\Ǽ "AE'")
- (?\ǽ "ae'")
- (?\Ǿ "O/'")
- (?\ǿ "o/'")
- (?\Ȁ "A!!")
- (?\ȁ "a!!")
- (?\Ȃ "A)")
- (?\ȃ "a)")
- (?\Ȅ "E!!")
- (?\ȅ "e!!")
- (?\Ȇ "E)")
- (?\ȇ "e)")
- (?\Ȉ "I!!")
- (?\ȉ "i!!")
- (?\Ȋ "I)")
- (?\ȋ "i)")
- (?\Ȍ "O!!")
- (?\ȍ "o!!")
- (?\Ȏ "O)")
- (?\ȏ "o)")
- (?\Ȑ "R!!")
- (?\ȑ "r!!")
- (?\Ȓ "R)")
- (?\ȓ "r)")
- (?\Ȕ "U!!")
- (?\ȕ "u!!")
- (?\Ȗ "U)")
- (?\ȗ "u)")
- (?\ȝ "Z")
- (?\ɑ "A")
- (?\ɒ "A.")
- (?\ɓ "b`")
- (?\ɔ "O")
- (?\ɖ "d.")
- (?\ɗ "d`")
- (?\ɘ "@<umd>")
- (?\ə "@")
- (?\ɚ "R")
- (?\ɛ "E")
- (?\ɜ "V\"")
- (?\ɝ "R<umd>")
- (?\ɞ "O\"")
- (?\ɟ "J")
- (?\ɠ "g`")
- (?\ɡ "g")
- (?\ɢ "G")
- (?\ɣ "Q")
- (?\ɤ "o-")
- (?\ɥ "j<rnd>")
- (?\ɦ "h<?>")
- (?\ɨ "i\"")
- (?\ɩ "I")
- (?\ɪ "I")
- (?\ɫ "L")
- (?\ɬ "L")
- (?\ɭ "l.")
- (?\ɮ "z<lat>")
- (?\ɯ "u-")
- (?\ɰ "j<vel>")
- (?\ɱ "M")
- (?\ɳ "n.")
- (?\ɴ "n\"")
- (?\ɵ "@.")
- (?\ɶ "&.")
- (?\ɷ "U")
- (?\ɹ "r")
- (?\ɺ "*<lat>")
- (?\ɻ "r.")
- (?\ɽ "*.")
- (?\ɾ "*")
- (?\ʀ "R")
- (?\ʁ "g\"")
- (?\ʂ "s.")
- (?\ʃ "S")
- (?\ʄ "J`")
- (?\ʇ "t!")
- (?\ʈ "t.")
- (?\ʉ "u\"")
- (?\ʊ "U")
- (?\ʋ "r<lbd>")
- (?\ʌ "V")
- (?\ʍ "w<vls>")
- (?\ʎ "l^")
- (?\ʏ "I.")
- (?\ʐ "z.")
- (?\ʒ "Z")
- (?\ʔ "?")
- (?\ʕ "H<vcd>")
- (?\ʖ "l!")
- (?\ʗ "c!")
- (?\ʘ "p!")
- (?\ʙ "b<trl>")
- (?\ʛ "G`")
- (?\ʝ "j")
- (?\ʞ "k!")
- (?\ʟ "L")
- (?\ʠ "q`")
- (?\ʤ "d3")
- (?\ʦ "ts")
- (?\ʧ "tS")
- (?\ʰ "<h>")
- (?\ʱ "<?>")
- (?\ʲ ";")
- (?\ʳ "<r>")
- (?\ʷ "<w>")
- (?\ʻ ";S")
- (?\ʼ "`")
- (?\ˆ "^")
- (?\ˇ "'<")
- (?\ˈ "|")
- (?\ˉ "1-")
- (?\ˋ "1!")
- (?\ː ":")
- (?\ˑ ":\\")
- (?\˖ "+")
- (?\˗ "-")
- (?\˘ "'(")
- (?\˙ "'.")
- (?\˚ "'0")
- (?\˛ "';")
- (?\˜ "~")
- (?\˝ "'\"")
- (?\˥ "_T")
- (?\˦ "_H")
- (?\˧ "_M")
- (?\˨ "_L")
- (?\˩ "_B")
- (?\ˬ "_v")
- (?\ˮ "''")
- (?\̀ "`")
- (?\́ "'")
- (?\̂ "^")
- (?\̃ "~")
- (?\̄ "¯")
- (?\̇ "·")
- (?\̈ "¨")
- (?\̊ "°")
- (?\̋ "''")
- (?\̍ "|")
- (?\̎ "||")
- (?\̏ "``")
- (?\̡ ";")
- (?\̢ ".")
- (?\̣ ".")
- (?\̤ "<?>")
- (?\̥ "<o>")
- (?\̦ ",")
- (?\̧ "¸")
- (?\̩ "-")
- (?\̪ "[")
- (?\̫ "<w>")
- (?\̴ "~")
- (?\̷ "/")
- (?\̸ "/")
- (?\̀ "`")
- (?\́ "'")
- (?\͂ "~")
- (?\̈́ "'%")
- (?\ͅ "j3")
- (?\͇ "=")
- (?\͠ "~~")
- (?\ʹ "'")
- (?\͵ ",")
- (?\ͺ "j3")
- (?\; "?%")
- (?\΄ "'*")
- (?\΅ "'%")
- (?\Ά "A'")
- (?\· "·")
- (?\Έ "E'")
- (?\Ή "Y%")
- (?\Ί "I'")
- (?\Ό "O'")
- (?\Ύ "U%")
- (?\Ώ "W%")
- (?\ΐ "i3")
- (?\Α "A")
- (?\Β "B")
- (?\Γ "G")
- (?\Δ "D")
- (?\Ε "E")
- (?\Ζ "Z")
- (?\Η "Y")
- (?\Θ "TH")
- (?\Ι "I")
- (?\Κ "K")
- (?\Λ "L")
- (?\Μ "M")
- (?\Ν "N")
- (?\Ξ "C")
- (?\Ο "O")
- (?\Π "P")
- (?\Ρ "R")
- (?\Σ "S")
- (?\Τ "T")
- (?\Υ "U")
- (?\Φ "F")
- (?\Χ "X")
- (?\Ψ "Q")
- (?\Ω "W*")
- (?\Ϊ "J")
- (?\Ϋ "V*")
- (?\ά "a'")
- (?\έ "e'")
- (?\ή "y%")
- (?\ί "i'")
- (?\ΰ "u3")
- (?\α "a")
- (?\β "b")
- (?\γ "g")
- (?\δ "d")
- (?\ε "e")
- (?\ζ "z")
- (?\η "y")
- (?\θ "th")
- (?\ι "i")
- (?\κ "k")
- (?\λ "l")
- (?\μ "µ")
- (?\ν "n")
- (?\ξ "c")
- (?\ο "o")
- (?\π "p")
- (?\ρ "r")
- (?\ς "*s")
- (?\σ "s")
- (?\τ "t")
- (?\υ "u")
- (?\φ "f")
- (?\χ "x")
- (?\ψ "q")
- (?\ω "w")
- (?\ϊ "j")
- (?\ϋ "v*")
- (?\ό "o'")
- (?\ύ "u%")
- (?\ώ "w%")
- (?\ϐ "beta ")
- (?\ϑ "theta ")
- (?\ϒ "upsi ")
- (?\ϕ "phi ")
- (?\ϖ "pi ")
- (?\ϗ "k.")
- (?\Ϛ "T3")
- (?\ϛ "t3")
- (?\Ϝ "M3")
- (?\ϝ "m3")
- (?\Ϟ "K3")
- (?\ϟ "k3")
- (?\Ϡ "P3")
- (?\ϡ "p3")
- (?\ϰ "kappa ")
- (?\ϱ "rho ")
- (?\ϳ "J")
- (?\ϴ "'%")
- (?\ϵ "j3")
- (?\Ё "IO")
- (?\Ђ "D%")
- (?\Ѓ "G%")
- (?\Є "IE")
- (?\Ѕ "DS")
- (?\І "II")
- (?\Ї "YI")
- (?\Ј "J%")
- (?\Љ "LJ")
- (?\Њ "NJ")
- (?\Ћ "Ts")
- (?\Ќ "KJ")
- (?\Ў "V%")
- (?\Џ "DZ")
- (?\А "A")
- (?\Б "B")
- (?\В "V")
- (?\Г "G")
- (?\Д "D")
- (?\Е "E")
- (?\Ж "ZH")
- (?\З "Z")
- (?\И "I")
- (?\Й "J")
- (?\К "K")
- (?\Л "L")
- (?\М "M")
- (?\Н "N")
- (?\О "O")
- (?\П "P")
- (?\Р "R")
- (?\С "S")
- (?\Т "T")
- (?\У "U")
- (?\Ф "F")
- (?\Х "H")
- (?\Ц "C")
- (?\Ч "CH")
- (?\Ш "SH")
- (?\Щ "SCH")
- (?\Ъ "\"")
- (?\Ы "Y")
- (?\Ь "'")
- (?\Э "`E")
- (?\Ю "YU")
- (?\Я "YA")
- (?\а "a")
- (?\б "b")
- (?\в "v")
- (?\г "g")
- (?\д "d")
- (?\е "e")
- (?\ж "zh")
- (?\з "z")
- (?\и "i")
- (?\й "j")
- (?\к "k")
- (?\л "l")
- (?\м "m")
- (?\н "n")
- (?\о "o")
- (?\п "p")
- (?\р "r")
- (?\с "s")
- (?\т "t")
- (?\у "u")
- (?\ф "f")
- (?\х "h")
- (?\ц "c")
- (?\ч "ch")
- (?\ш "sh")
- (?\щ "sch")
- (?\ъ "\"")
- (?\ы "y")
- (?\ь "'")
- (?\э "`e")
- (?\ю "yu")
- (?\я "ya")
- (?\ё "io")
- (?\ђ "d%")
- (?\ѓ "g%")
- (?\є "ie")
- (?\ѕ "ds")
- (?\і "ii")
- (?\ї "yi")
- (?\ј "j%")
- (?\љ "lj")
- (?\њ "nj")
- (?\ћ "ts")
- (?\ќ "kj")
- (?\ў "v%")
- (?\џ "dz")
- (?\Ѣ "Y3")
- (?\ѣ "y3")
- (?\Ѫ "O3")
- (?\ѫ "o3")
- (?\Ѳ "F3")
- (?\ѳ "f3")
- (?\Ѵ "V3")
- (?\ѵ "v3")
- (?\Ҁ "C3")
- (?\ҁ "c3")
- (?\Ґ "G3")
- (?\ґ "g3")
- (?\Ӕ "AE")
- (?\ӕ "ae")
- (?\ִ "i")
- (?\ַ "a")
- (?\ָ "o")
- (?\ּ "u")
- (?\ֿ "h")
- (?\ׂ ":")
- (?\א "#")
- (?\ב "B+")
- (?\ג "G+")
- (?\ד "D+")
- (?\ה "H+")
- (?\ו "W+")
- (?\ז "Z+")
- (?\ח "X+")
- (?\ט "Tj")
- (?\י "J+")
- (?\ך "K%")
- (?\כ "K+")
- (?\ל "L+")
- (?\ם "M%")
- (?\מ "M+")
- (?\ן "N%")
- (?\נ "N+")
- (?\ס "S+")
- (?\ע "E+")
- (?\ף "P%")
- (?\פ "P+")
- (?\ץ "Zj")
- (?\צ "ZJ")
- (?\ק "Q+")
- (?\ר "R+")
- (?\ש "Sh")
- (?\ת "T+")
- (?\װ "v")
- (?\ױ "oy")
- (?\ײ "ey")
- (?\، ",+")
- (?\؛ ";+")
- (?\؟ "?+")
- (?\ء "H'")
- (?\آ "aM")
- (?\أ "aH")
- (?\ؤ "wH")
- (?\إ "ah")
- (?\ئ "yH")
- (?\ا "a+")
- (?\ب "b+")
- (?\ة "tm")
- (?\ت "t+")
- (?\ث "tk")
- (?\ج "g+")
- (?\ح "hk")
- (?\خ "x+")
- (?\د "d+")
- (?\ذ "dk")
- (?\ر "r+")
- (?\ز "z+")
- (?\س "s+")
- (?\ش "sn")
- (?\ص "c+")
- (?\ض "dd")
- (?\ط "tj")
- (?\ظ "zH")
- (?\ع "e+")
- (?\غ "i+")
- (?\ـ "++")
- (?\ف "f+")
- (?\ق "q+")
- (?\ك "k+")
- (?\ل "l+")
- (?\م "m+")
- (?\ن "n+")
- (?\ه "h+")
- (?\و "w+")
- (?\ى "j+")
- (?\ي "y+")
- (?\ً ":+")
- (?\ٌ "\"+")
- (?\ٍ "=+")
- (?\َ "/+")
- (?\ُ "'+")
- (?\ِ "1+")
- (?\ّ "3+")
- (?\ْ "0+")
- (?\٠ "0a")
- (?\١ "1a")
- (?\٢ "2a")
- (?\٣ "3a")
- (?\٤ "4a")
- (?\٥ "5a")
- (?\٦ "6a")
- (?\٧ "7a")
- (?\٨ "8a")
- (?\٩ "9a")
- (?\ٰ "aS")
- (?\پ "p+")
- (?\ځ "hH")
- (?\چ "tc")
- (?\ژ "zj")
- (?\ڤ "v+")
- (?\گ "gf")
- (?\۰ "0a")
- (?\۱ "1a")
- (?\۲ "2a")
- (?\۳ "3a")
- (?\۴ "4a")
- (?\۵ "5a")
- (?\۶ "6a")
- (?\۷ "7a")
- (?\۸ "8a")
- (?\۹ "9a")
- (?\ሀ "he")
- (?\ሁ "hu")
- (?\ሂ "hi")
- (?\ሃ "ha")
- (?\ሄ "hE")
- (?\ህ "h")
- (?\ሆ "ho")
- (?\ለ "le")
- (?\ሉ "lu")
- (?\ሊ "li")
- (?\ላ "la")
- (?\ሌ "lE")
- (?\ል "l")
- (?\ሎ "lo")
- (?\ሏ "lWa")
- (?\ሐ "He")
- (?\ሑ "Hu")
- (?\ሒ "Hi")
- (?\ሓ "Ha")
- (?\ሔ "HE")
- (?\ሕ "H")
- (?\ሖ "Ho")
- (?\ሗ "HWa")
- (?\መ "me")
- (?\ሙ "mu")
- (?\ሚ "mi")
- (?\ማ "ma")
- (?\ሜ "mE")
- (?\ም "m")
- (?\ሞ "mo")
- (?\ሟ "mWa")
- (?\ሠ "`se")
- (?\ሡ "`su")
- (?\ሢ "`si")
- (?\ሣ "`sa")
- (?\ሤ "`sE")
- (?\ሥ "`s")
- (?\ሦ "`so")
- (?\ሧ "`sWa")
- (?\ረ "re")
- (?\ሩ "ru")
- (?\ሪ "ri")
- (?\ራ "ra")
- (?\ሬ "rE")
- (?\ር "r")
- (?\ሮ "ro")
- (?\ሯ "rWa")
- (?\ሰ "se")
- (?\ሱ "su")
- (?\ሲ "si")
- (?\ሳ "sa")
- (?\ሴ "sE")
- (?\ስ "s")
- (?\ሶ "so")
- (?\ሷ "sWa")
- (?\ሸ "xe")
- (?\ሹ "xu")
- (?\ሺ "xi")
- (?\ሻ "xa")
- (?\ሼ "xE")
- (?\ሽ "xa")
- (?\ሾ "xo")
- (?\ሿ "xWa")
- (?\ቀ "qe")
- (?\ቁ "qu")
- (?\ቂ "qi")
- (?\ቃ "qa")
- (?\ቄ "qE")
- (?\ቅ "q")
- (?\ቆ "qo")
- (?\ቈ "qWe")
- (?\ቊ "qWi")
- (?\ቋ "qWa")
- (?\ቌ "qWE")
- (?\ቍ "qW")
- (?\ቐ "Qe")
- (?\ቑ "Qu")
- (?\ቒ "Qi")
- (?\ቓ "Qa")
- (?\ቔ "QE")
- (?\ቕ "Q")
- (?\ቖ "Qo")
- (?\ቘ "QWe")
- (?\ቚ "QWi")
- (?\ቛ "QWa")
- (?\ቜ "QWE")
- (?\ቝ "QW")
- (?\በ "be")
- (?\ቡ "bu")
- (?\ቢ "bi")
- (?\ባ "ba")
- (?\ቤ "bE")
- (?\ብ "b")
- (?\ቦ "bo")
- (?\ቧ "bWa")
- (?\ቨ "ve")
- (?\ቩ "vu")
- (?\ቪ "vi")
- (?\ቫ "va")
- (?\ቬ "vE")
- (?\ቭ "v")
- (?\ቮ "vo")
- (?\ቯ "vWa")
- (?\ተ "te")
- (?\ቱ "tu")
- (?\ቲ "ti")
- (?\ታ "ta")
- (?\ቴ "tE")
- (?\ት "t")
- (?\ቶ "to")
- (?\ቷ "tWa")
- (?\ቸ "ce")
- (?\ቹ "cu")
- (?\ቺ "ci")
- (?\ቻ "ca")
- (?\ቼ "cE")
- (?\ች "c")
- (?\ቾ "co")
- (?\ቿ "cWa")
- (?\ኀ "`he")
- (?\ኁ "`hu")
- (?\ኂ "`hi")
- (?\ኃ "`ha")
- (?\ኄ "`hE")
- (?\ኅ "`h")
- (?\ኆ "`ho")
- (?\ኈ "hWe")
- (?\ኊ "hWi")
- (?\ኋ "hWa")
- (?\ኌ "hWE")
- (?\ኍ "hW")
- (?\ነ "na")
- (?\ኑ "nu")
- (?\ኒ "ni")
- (?\ና "na")
- (?\ኔ "nE")
- (?\ን "n")
- (?\ኖ "no")
- (?\ኗ "nWa")
- (?\ኘ "Ne")
- (?\ኙ "Nu")
- (?\ኚ "Ni")
- (?\ኛ "Na")
- (?\ኜ "NE")
- (?\ኝ "N")
- (?\ኞ "No")
- (?\ኟ "NWa")
- (?\አ "e")
- (?\ኡ "u")
- (?\ኢ "i")
- (?\ኣ "a")
- (?\ኤ "E")
- (?\እ "I")
- (?\ኦ "o")
- (?\ኧ "e3")
- (?\ከ "ke")
- (?\ኩ "ku")
- (?\ኪ "ki")
- (?\ካ "ka")
- (?\ኬ "kE")
- (?\ክ "k")
- (?\ኮ "ko")
- (?\ኰ "kWe")
- (?\ኲ "kWi")
- (?\ኳ "kWa")
- (?\ኴ "kWE")
- (?\ኵ "kW")
- (?\ኸ "Ke")
- (?\ኹ "Ku")
- (?\ኺ "Ki")
- (?\ኻ "Ka")
- (?\ኼ "KE")
- (?\ኽ "K")
- (?\ኾ "Ko")
- (?\ዀ "KWe")
- (?\ዂ "KWi")
- (?\ዃ "KWa")
- (?\ዄ "KWE")
- (?\ዅ "KW")
- (?\ወ "we")
- (?\ዉ "wu")
- (?\ዊ "wi")
- (?\ዋ "wa")
- (?\ዌ "wE")
- (?\ው "w")
- (?\ዎ "wo")
- (?\ዐ "`e")
- (?\ዑ "`u")
- (?\ዒ "`i")
- (?\ዓ "`a")
- (?\ዔ "`E")
- (?\ዕ "`I")
- (?\ዖ "`o")
- (?\ዘ "ze")
- (?\ዙ "zu")
- (?\ዚ "zi")
- (?\ዛ "za")
- (?\ዜ "zE")
- (?\ዝ "z")
- (?\ዞ "zo")
- (?\ዟ "zWa")
- (?\ዠ "Ze")
- (?\ዡ "Zu")
- (?\ዢ "Zi")
- (?\ዣ "Za")
- (?\ዤ "ZE")
- (?\ዥ "Z")
- (?\ዦ "Zo")
- (?\ዧ "ZWa")
- (?\የ "ye")
- (?\ዩ "yu")
- (?\ዪ "yi")
- (?\ያ "ya")
- (?\ዬ "yE")
- (?\ይ "y")
- (?\ዮ "yo")
- (?\ዯ "yWa")
- (?\ደ "de")
- (?\ዱ "du")
- (?\ዲ "di")
- (?\ዳ "da")
- (?\ዴ "dE")
- (?\ድ "d")
- (?\ዶ "do")
- (?\ዷ "dWa")
- (?\ዸ "De")
- (?\ዹ "Du")
- (?\ዺ "Di")
- (?\ዻ "Da")
- (?\ዼ "DE")
- (?\ዽ "D")
- (?\ዾ "Do")
- (?\ዿ "DWa")
- (?\ጀ "je")
- (?\ጁ "ju")
- (?\ጂ "ji")
- (?\ጃ "ja")
- (?\ጄ "jE")
- (?\ጅ "j")
- (?\ጆ "jo")
- (?\ጇ "jWa")
- (?\ገ "ga")
- (?\ጉ "gu")
- (?\ጊ "gi")
- (?\ጋ "ga")
- (?\ጌ "gE")
- (?\ግ "g")
- (?\ጎ "go")
- (?\ጐ "gWu")
- (?\ጒ "gWi")
- (?\ጓ "gWa")
- (?\ጔ "gWE")
- (?\ጕ "gW")
- (?\ጘ "Ge")
- (?\ጙ "Gu")
- (?\ጚ "Gi")
- (?\ጛ "Ga")
- (?\ጜ "GE")
- (?\ጝ "G")
- (?\ጞ "Go")
- (?\ጟ "GWa")
- (?\ጠ "Te")
- (?\ጡ "Tu")
- (?\ጢ "Ti")
- (?\ጣ "Ta")
- (?\ጤ "TE")
- (?\ጥ "T")
- (?\ጦ "To")
- (?\ጧ "TWa")
- (?\ጨ "Ce")
- (?\ጩ "Ca")
- (?\ጪ "Cu")
- (?\ጫ "Ca")
- (?\ጬ "CE")
- (?\ጭ "C")
- (?\ጮ "Co")
- (?\ጯ "CWa")
- (?\ጰ "Pe")
- (?\ጱ "Pu")
- (?\ጲ "Pi")
- (?\ጳ "Pa")
- (?\ጴ "PE")
- (?\ጵ "P")
- (?\ጶ "Po")
- (?\ጷ "PWa")
- (?\ጸ "SWe")
- (?\ጹ "SWu")
- (?\ጺ "SWi")
- (?\ጻ "SWa")
- (?\ጼ "SWE")
- (?\ጽ "SW")
- (?\ጾ "SWo")
- (?\ጿ "SWa")
- (?\ፀ "`Sa")
- (?\ፁ "`Su")
- (?\ፂ "`Si")
- (?\ፃ "`Sa")
- (?\ፄ "`SE")
- (?\ፅ "`S")
- (?\ፆ "`So")
- (?\ፈ "fa")
- (?\ፉ "fu")
- (?\ፊ "fi")
- (?\ፋ "fa")
- (?\ፌ "fE")
- (?\ፍ "o")
- (?\ፎ "fo")
- (?\ፏ "fWa")
- (?\ፐ "pe")
- (?\ፑ "pu")
- (?\ፒ "pi")
- (?\ፓ "pa")
- (?\ፔ "pE")
- (?\ፕ "p")
- (?\ፖ "po")
- (?\ፗ "pWa")
- (?\ፘ "mYa")
- (?\ፙ "rYa")
- (?\ፚ "fYa")
- (?\፠ " ")
- (?\፡ ":")
- (?\። "::")
- (?\፣ ",")
- (?\፤ ";")
- (?\፥ "-:")
- (?\፦ ":-")
- (?\፧ "`?")
- (?\፨ ":|:")
- (?\፩ "`1")
- (?\፪ "`2")
- (?\፫ "`3")
- (?\፬ "`4")
- (?\፭ "`5")
- (?\፮ "`6")
- (?\፯ "`7")
- (?\፰ "`8")
- (?\፱ "`9")
- (?\፲ "`10")
- (?\፳ "`20")
- (?\፴ "`30")
- (?\፵ "`40")
- (?\፶ "`50")
- (?\፷ "`60")
- (?\፸ "`70")
- (?\፹ "`80")
- (?\፺ "`90")
- (?\፻ "`100")
- (?\፼ "`10000")
- (?\Ḁ "A-0")
- (?\ḁ "a-0")
- (?\Ḃ "B.")
- (?\ḃ "b.")
- (?\Ḅ "B-.")
- (?\ḅ "b-.")
- (?\Ḇ "B_")
- (?\ḇ "b_")
- (?\Ḉ "C,'")
- (?\ḉ "c,'")
- (?\Ḋ "D.")
- (?\ḋ "d.")
- (?\Ḍ "D-.")
- (?\ḍ "d-.")
- (?\Ḏ "D_")
- (?\ḏ "d_")
- (?\Ḑ "D,")
- (?\ḑ "d,")
- (?\Ḓ "D->")
- (?\ḓ "d->")
- (?\Ḕ "E-!")
- (?\ḕ "e-!")
- (?\Ḗ "E-'")
- (?\ḗ "e-'")
- (?\Ḙ "E->")
- (?\ḙ "e->")
- (?\Ḛ "E-?")
- (?\ḛ "e-?")
- (?\Ḝ "E,(")
- (?\ḝ "e,(")
- (?\Ḟ "F.")
- (?\ḟ "f.")
- (?\Ḡ "G-")
- (?\ḡ "g-")
- (?\Ḣ "H.")
- (?\ḣ "h.")
- (?\Ḥ "H-.")
- (?\ḥ "h-.")
- (?\Ḧ "H:")
- (?\ḧ "h:")
- (?\Ḩ "H,")
- (?\ḩ "h,")
- (?\Ḫ "H-(")
- (?\ḫ "h-(")
- (?\Ḭ "I-?")
- (?\ḭ "i-?")
- (?\Ḯ "I:'")
- (?\ḯ "i:'")
- (?\Ḱ "K'")
- (?\ḱ "k'")
- (?\Ḳ "K-.")
- (?\ḳ "k-.")
- (?\Ḵ "K_")
- (?\ḵ "k_")
- (?\Ḷ "L-.")
- (?\ḷ "l-.")
- (?\Ḹ "L--.")
- (?\ḹ "l--.")
- (?\Ḻ "L_")
- (?\ḻ "l_")
- (?\Ḽ "L->")
- (?\ḽ "l->")
- (?\Ḿ "M'")
- (?\ḿ "m'")
- (?\Ṁ "M.")
- (?\ṁ "m.")
- (?\Ṃ "M-.")
- (?\ṃ "m-.")
- (?\Ṅ "N.")
- (?\ṅ "n.")
- (?\Ṇ "N-.")
- (?\ṇ "n-.")
- (?\Ṉ "N_")
- (?\ṉ "n_")
- (?\Ṋ "N->")
- (?\ṋ "n->")
- (?\Ṍ "O?'")
- (?\ṍ "o?'")
- (?\Ṏ "O?:")
- (?\ṏ "o?:")
- (?\Ṑ "O-!")
- (?\ṑ "o-!")
- (?\Ṓ "O-'")
- (?\ṓ "o-'")
- (?\Ṕ "P'")
- (?\ṕ "p'")
- (?\Ṗ "P.")
- (?\ṗ "p.")
- (?\Ṙ "R.")
- (?\ṙ "r.")
- (?\Ṛ "R-.")
- (?\ṛ "r-.")
- (?\Ṝ "R--.")
- (?\ṝ "r--.")
- (?\Ṟ "R_")
- (?\ṟ "r_")
- (?\Ṡ "S.")
- (?\ṡ "s.")
- (?\Ṣ "S-.")
- (?\ṣ "s-.")
- (?\Ṥ "S'.")
- (?\ṥ "s'.")
- (?\Ṧ "S<.")
- (?\ṧ "s<.")
- (?\Ṩ "S.-.")
- (?\ṩ "s.-.")
- (?\Ṫ "T.")
- (?\ṫ "t.")
- (?\Ṭ "T-.")
- (?\ṭ "t-.")
- (?\Ṯ "T_")
- (?\ṯ "t_")
- (?\Ṱ "T->")
- (?\ṱ "t->")
- (?\Ṳ "U--:")
- (?\ṳ "u--:")
- (?\Ṵ "U-?")
- (?\ṵ "u-?")
- (?\Ṷ "U->")
- (?\ṷ "u->")
- (?\Ṹ "U?'")
- (?\ṹ "u?'")
- (?\Ṻ "U-:")
- (?\ṻ "u-:")
- (?\Ṽ "V?")
- (?\ṽ "v?")
- (?\Ṿ "V-.")
- (?\ṿ "v-.")
- (?\Ẁ "W!")
- (?\ẁ "w!")
- (?\Ẃ "W'")
- (?\ẃ "w'")
- (?\Ẅ "W:")
- (?\ẅ "w:")
- (?\Ẇ "W.")
- (?\ẇ "w.")
- (?\Ẉ "W-.")
- (?\ẉ "w-.")
- (?\Ẋ "X.")
- (?\ẋ "x.")
- (?\Ẍ "X:")
- (?\ẍ "x:")
- (?\Ẏ "Y.")
- (?\ẏ "y.")
- (?\Ẑ "Z>")
- (?\ẑ "z>")
- (?\Ẓ "Z-.")
- (?\ẓ "z-.")
- (?\Ẕ "Z_")
- (?\ẕ "z_")
- (?\ẖ "h_")
- (?\ẗ "t:")
- (?\ẘ "w0")
- (?\ẙ "y0")
- (?\Ạ "A-.")
- (?\ạ "a-.")
- (?\Ả "A2")
- (?\ả "a2")
- (?\Ấ "A>'")
- (?\ấ "a>'")
- (?\Ầ "A>!")
- (?\ầ "a>!")
- (?\Ẩ "A>2")
- (?\ẩ "a>2")
- (?\Ẫ "A>?")
- (?\ẫ "a>?")
- (?\Ậ "A>-.")
- (?\ậ "a>-.")
- (?\Ắ "A('")
- (?\ắ "a('")
- (?\Ằ "A(!")
- (?\ằ "a(!")
- (?\Ẳ "A(2")
- (?\ẳ "a(2")
- (?\Ẵ "A(?")
- (?\ẵ "a(?")
- (?\Ặ "A(-.")
- (?\ặ "a(-.")
- (?\Ẹ "E-.")
- (?\ẹ "e-.")
- (?\Ẻ "E2")
- (?\ẻ "e2")
- (?\Ẽ "E?")
- (?\ẽ "e?")
- (?\Ế "E>'")
- (?\ế "e>'")
- (?\Ề "E>!")
- (?\ề "e>!")
- (?\Ể "E>2")
- (?\ể "e>2")
- (?\Ễ "E>?")
- (?\ễ "e>?")
- (?\Ệ "E>-.")
- (?\ệ "e>-.")
- (?\Ỉ "I2")
- (?\ỉ "i2")
- (?\Ị "I-.")
- (?\ị "i-.")
- (?\Ọ "O-.")
- (?\ọ "o-.")
- (?\Ỏ "O2")
- (?\ỏ "o2")
- (?\Ố "O>'")
- (?\ố "o>'")
- (?\Ồ "O>!")
- (?\ồ "o>!")
- (?\Ổ "O>2")
- (?\ổ "o>2")
- (?\Ỗ "O>?")
- (?\ỗ "o>?")
- (?\Ộ "O>-.")
- (?\ộ "o>-.")
- (?\Ớ "O9'")
- (?\ớ "o9'")
- (?\Ờ "O9!")
- (?\ờ "o9!")
- (?\Ở "O92")
- (?\ở "o92")
- (?\Ỡ "O9?")
- (?\ỡ "o9?")
- (?\Ợ "O9-.")
- (?\ợ "o9-.")
- (?\Ụ "U-.")
- (?\ụ "u-.")
- (?\Ủ "U2")
- (?\ủ "u2")
- (?\Ứ "U9'")
- (?\ứ "u9'")
- (?\Ừ "U9!")
- (?\ừ "u9!")
- (?\Ử "U92")
- (?\ử "u92")
- (?\Ữ "U9?")
- (?\ữ "u9?")
- (?\Ự "U9-.")
- (?\ự "u9-.")
- (?\Ỳ "Y!")
- (?\ỳ "y!")
- (?\Ỵ "Y-.")
- (?\ỵ "y-.")
- (?\Ỷ "Y2")
- (?\ỷ "y2")
- (?\Ỹ "Y?")
- (?\ỹ "y?")
- (?\ἀ "a")
- (?\ἁ "ha")
- (?\ἂ "`a")
- (?\ἃ "h`a")
- (?\ἄ "a'")
- (?\ἅ "ha'")
- (?\ἆ "a~")
- (?\ἇ "ha~")
- (?\Ἀ "A")
- (?\Ἁ "hA")
- (?\Ἂ "`A")
- (?\Ἃ "h`A")
- (?\Ἄ "A'")
- (?\Ἅ "hA'")
- (?\Ἆ "A~")
- (?\Ἇ "hA~")
- (?\ἑ "he")
- (?\Ἑ "hE")
- (?\ἱ "hi")
- (?\Ἱ "hI")
- (?\ὁ "ho")
- (?\Ὁ "hO")
- (?\ὑ "hu")
- (?\Ὑ "hU")
- (?\᾿ ",,")
- (?\῀ "?*")
- (?\῁ "?:")
- (?\῍ ",!")
- (?\῎ ",'")
- (?\῏ "?,")
- (?\῝ ";!")
- (?\῞ ";'")
- (?\῟ "?;")
- (?\ῥ "rh")
- (?\Ῥ "Rh")
- (?\῭ "!:")
- (?\` "!*")
- (?\῾ ";;")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\  " ")
- (?\‐ "-")
- (?\‑ "-")
- (?\– "-")
- (?\— "--")
- (?\― "-")
- (?\‖ "||")
- (?\‗ "=2")
- (?\‘ "`")
- (?\’ "'")
- (?\‚ "'")
- (?\‛ "'")
- (?\“ "\"")
- (?\” "\"")
- (?\„ "\"")
- (?\‟ "\"")
- (?\† "/-")
- (?\‡ "/=")
- (?\• " o ")
- (?\․ ".")
- (?\‥ "..")
- (?\… "...")
- (?\‧ "·")
- (?\‰ " 0/00")
- (?\′ "'")
- (?\″ "''")
- (?\‴ "'''")
- (?\‵ "`")
- (?\‶ "``")
- (?\‷ "```")
- (?\‸ "Ca")
- (?\‹ "<")
- (?\› ">")
- (?\※ ":X")
- (?\‼ "!!")
- (?\‾ "'-")
- (?\⁃ "-")
- (?\⁄ "/")
- (?\⁈ "?!")
- (?\⁉ "!?")
- (?\⁰ "^0")
- (?\⁴ "^4")
- (?\⁵ "^5")
- (?\⁶ "^6")
- (?\⁷ "^7")
- (?\⁸ "^8")
- (?\⁹ "^9")
- (?\⁺ "^+")
- (?\⁻ "^-")
- (?\⁼ "^=")
- (?\⁽ "^(")
- (?\⁾ "^)")
- (?\ⁿ "^n")
- (?\₀ "_0")
- (?\₁ "_1")
- (?\₂ "_2")
- (?\₃ "_3")
- (?\₄ "_4")
- (?\₅ "_5")
- (?\₆ "_6")
- (?\₇ "_7")
- (?\₈ "_8")
- (?\₉ "_9")
- (?\₊ "_+")
- (?\₋ "_-")
- (?\₌ "_=")
- (?\₍ "(")
- (?\₎ ")")
- (?\₣ "Ff")
- (?\₤ "Li")
- (?\₧ "Pt")
- (?\₩ "W=")
- (?\€ "EUR")
- (?\℀ "a/c")
- (?\℁ "a/s")
- (?\℃ "oC")
- (?\℅ "c/o")
- (?\℆ "c/u")
- (?\℉ "oF")
- (?\ℊ "g")
- (?\ℎ "h")
- (?\ℏ "\\hbar")
- (?\ℑ "Im")
- (?\ℓ "l")
- (?\№ "No.")
- (?\℗ "PO")
- (?\℘ "P")
- (?\ℜ "Re")
- (?\℞ "Rx")
- (?\℠ "(SM)")
- (?\℡ "TEL")
- (?\™ "(TM)")
- (?\Ω "Ohm")
- (?\K "K")
- (?\Å "Ang.")
- (?\℮ "est.")
- (?\ℴ "o")
- (?\ℵ "Aleph ")
- (?\ℶ "Bet ")
- (?\ℷ "Gimel ")
- (?\ℸ "Dalet ")
- (?\⅓ " 1/3")
- (?\⅔ " 2/3")
- (?\⅕ " 1/5")
- (?\⅖ " 2/5")
- (?\⅗ " 3/5")
- (?\⅘ " 4/5")
- (?\⅙ " 1/6")
- (?\⅚ " 5/6")
- (?\⅛ " 1/8")
- (?\⅜ " 3/8")
- (?\⅝ " 5/8")
- (?\⅞ " 7/8")
- (?\⅟ " 1/")
- (?\Ⅰ "I")
- (?\Ⅱ "II")
- (?\Ⅲ "III")
- (?\Ⅳ "IV")
- (?\Ⅴ "V")
- (?\Ⅵ "VI")
- (?\Ⅶ "VII")
- (?\Ⅷ "VIII")
- (?\Ⅸ "IX")
- (?\Ⅹ "X")
- (?\Ⅺ "XI")
- (?\Ⅻ "XII")
- (?\Ⅼ "L")
- (?\Ⅽ "C")
- (?\Ⅾ "D")
- (?\Ⅿ "M")
- (?\ⅰ "i")
- (?\ⅱ "ii")
- (?\ⅲ "iii")
- (?\ⅳ "iv")
- (?\ⅴ "v")
- (?\ⅵ "vi")
- (?\ⅶ "vii")
- (?\ⅷ "viii")
- (?\ⅸ "ix")
- (?\ⅹ "x")
- (?\ⅺ "xi")
- (?\ⅻ "xii")
- (?\ⅼ "l")
- (?\ⅽ "c")
- (?\ⅾ "d")
- (?\ⅿ "m")
- (?\ↀ "1000RCD")
- (?\ↁ "5000R")
- (?\ↂ "10000R")
- (?\← "<-")
- (?\↑ "-^")
- (?\→ "->")
- (?\↓ "-v")
- (?\↔ "<->")
- (?\↕ "UD")
- (?\↖ "<!!")
- (?\↗ "//>")
- (?\↘ "!!>")
- (?\↙ "<//")
- (?\↨ "UD-")
- (?\↵ "RET")
- (?\⇀ ">V")
- (?\⇐ "<=")
- (?\⇑ "^^")
- (?\⇒ "=>")
- (?\⇓ "vv")
- (?\⇔ "<=>")
- (?\∀ "FA")
- (?\∂ "\\partial")
- (?\∃ "TE")
- (?\∅ "{}")
- (?\∆ "Delta")
- (?\∇ "Nabla")
- (?\∈ "(-")
- (?\∉ "!(-")
- (?\∊ "(-")
- (?\∋ "-)")
- (?\∌ "!-)")
- (?\∍ "-)")
- (?\∎ " qed")
- (?\∏ "\\prod")
- (?\∑ "\\sum")
- (?\− " -")
- (?\∓ "-/+")
- (?\∔ ".+")
- (?\∕ "/")
- (?\∖ " - ")
- (?\∗ "*")
- (?\∘ " ° ")
- (?\∙ "sb")
- (?\√ " SQRT ")
- (?\∛ " ROOT³ ")
- (?\∜ " ROOT4 ")
- (?\∝ "0(")
- (?\∞ "infty")
- (?\∟ "-L")
- (?\∠ "-V")
- (?\∥ "PP")
- (?\∦ " !PP ")
- (?\∧ "AND")
- (?\∨ "OR")
- (?\∩ "(U")
- (?\∪ ")U")
- (?\∫ "\\int ")
- (?\∬ "DI")
- (?\∮ "Io")
- (?\∴ ".:")
- (?\∵ ":.")
- (?\∶ ":R")
- (?\∷ "::")
- (?\∼ "?1")
- (?\∾ "CG")
- (?\≃ "?-")
- (?\≅ "?=")
- (?\≈ "~=")
- (?\≉ " !~= ")
- (?\≌ "=?")
- (?\≓ "HI")
- (?\≔ ":=")
- (?\≕ "=:")
- (?\≠ "!=")
- (?\≡ "=3")
- (?\≢ " !=3 ")
- (?\≤ "=<")
- (?\≥ ">=")
- (?\≦ ".LE.")
- (?\≧ ".GE.")
- (?\≨ ".LT.NOT.EQ.")
- (?\≩ ".GT.NOT.EQ.")
- (?\≪ "<<")
- (?\≫ ">>")
- (?\≮ "!<")
- (?\≯ "!>")
- (?\≶ " <> ")
- (?\≷ " >< ")
- (?\⊂ "(C")
- (?\⊃ ")C")
- (?\⊄ " !(C ")
- (?\⊅ " !)C ")
- (?\⊆ "(_")
- (?\⊇ ")_")
- (?\⊕ "(+)")
- (?\⊖ "(-)")
- (?\⊗ "(×)")
- (?\⊘ "(/)")
- (?\⊙ "(·)")
- (?\⊚ "(°)")
- (?\⊛ "(*)")
- (?\⊜ "(=)")
- (?\⊝ "(-)")
- (?\⊞ "[+]")
- (?\⊟ "[-]")
- (?\⊠ "[×]")
- (?\⊡ "[·]")
- (?\⊥ "-T")
- (?\⊧ " MODELS ")
- (?\⊨ " TRUE ")
- (?\⊩ " FORCES ")
- (?\⊬ " !PROVES ")
- (?\⊭ " NOT TRUE ")
- (?\⊮ " !FORCES ")
- (?\⊲ " NORMAL SUBGROUP OF ")
- (?\⊳ " CONTAINS AS NORMAL SUBGROUP ")
- (?\⊴ " NORMAL SUBGROUP OF OR EQUAL TO ")
- (?\⊵ " CONTAINS AS NORMAL SUBGROUP OR EQUAL TO ")
- (?\⊸ " MULTIMAP ")
- (?\⊺ " INTERCALATE ")
- (?\⊻ " XOR ")
- (?\⊼ " NAND ")
- (?\⋅ " · ")
- (?\⋖ "<.")
- (?\⋗ ">.")
- (?\⋘ "<<<")
- (?\⋙ ">>>")
- (?\⋮ ":3")
- (?\⋯ ".3")
- (?\⌂ "Eh")
- (?\⌇ "~~")
- (?\⌈ "<7")
- (?\⌉ ">7")
- (?\⌊ "7<")
- (?\⌋ "7>")
- (?\⌐ "NI")
- (?\⌒ "(A")
- (?\⌕ "TR")
- (?\⌘ "88")
- (?\⌠ "Iu")
- (?\⌡ "Il")
- (?\⌢ ":(")
- (?\⌣ ":)")
- (?\⌤ "|^|")
- (?\⌧ "[X]")
- (?\〈 "</")
- (?\〉 "/>")
- (?\␣ "Vs")
- (?\⑀ "1h")
- (?\⑁ "3h")
- (?\⑂ "2h")
- (?\⑃ "4h")
- (?\⑆ "1j")
- (?\⑇ "2j")
- (?\⑈ "3j")
- (?\⑉ "4j")
- (?\① "1-o")
- (?\② "2-o")
- (?\③ "3-o")
- (?\④ "4-o")
- (?\⑤ "5-o")
- (?\⑥ "6-o")
- (?\⑦ "7-o")
- (?\⑧ "8-o")
- (?\⑨ "9-o")
- (?\⑩ "10-o")
- (?\⑪ "11-o")
- (?\⑫ "12-o")
- (?\⑬ "13-o")
- (?\⑭ "14-o")
- (?\⑮ "15-o")
- (?\⑯ "16-o")
- (?\⑰ "17-o")
- (?\⑱ "18-o")
- (?\⑲ "19-o")
- (?\⑳ "20-o")
- (?\⑴ "(1)")
- (?\⑵ "(2)")
- (?\⑶ "(3)")
- (?\⑷ "(4)")
- (?\⑸ "(5)")
- (?\⑹ "(6)")
- (?\⑺ "(7)")
- (?\⑻ "(8)")
- (?\⑼ "(9)")
- (?\⑽ "(10)")
- (?\⑾ "(11)")
- (?\⑿ "(12)")
- (?\⒀ "(13)")
- (?\⒁ "(14)")
- (?\⒂ "(15)")
- (?\⒃ "(16)")
- (?\⒄ "(17)")
- (?\⒅ "(18)")
- (?\⒆ "(19)")
- (?\⒇ "(20)")
- (?\⒈ "1.")
- (?\⒉ "2.")
- (?\⒊ "3.")
- (?\⒋ "4.")
- (?\⒌ "5.")
- (?\⒍ "6.")
- (?\⒎ "7.")
- (?\⒏ "8.")
- (?\⒐ "9.")
- (?\⒑ "10.")
- (?\⒒ "11.")
- (?\⒓ "12.")
- (?\⒔ "13.")
- (?\⒕ "14.")
- (?\⒖ "15.")
- (?\⒗ "16.")
- (?\⒘ "17.")
- (?\⒙ "18.")
- (?\⒚ "19.")
- (?\⒛ "20.")
- (?\⒜ "(a)")
- (?\⒝ "(b)")
- (?\⒞ "(c)")
- (?\⒟ "(d)")
- (?\⒠ "(e)")
- (?\⒡ "(f)")
- (?\⒢ "(g)")
- (?\⒣ "(h)")
- (?\⒤ "(i)")
- (?\⒥ "(j)")
- (?\⒦ "(k)")
- (?\⒧ "(l)")
- (?\⒨ "(m)")
- (?\⒩ "(n)")
- (?\⒪ "(o)")
- (?\⒫ "(p)")
- (?\⒬ "(q)")
- (?\⒭ "(r)")
- (?\⒮ "(s)")
- (?\⒯ "(t)")
- (?\⒰ "(u)")
- (?\⒱ "(v)")
- (?\⒲ "(w)")
- (?\⒳ "(x)")
- (?\⒴ "(y)")
- (?\⒵ "(z)")
- (?\Ⓐ "A-o")
- (?\Ⓑ "B-o")
- (?\Ⓒ "C-o")
- (?\Ⓓ "D-o")
- (?\Ⓔ "E-o")
- (?\Ⓕ "F-o")
- (?\Ⓖ "G-o")
- (?\Ⓗ "H-o")
- (?\Ⓘ "I-o")
- (?\Ⓙ "J-o")
- (?\Ⓚ "K-o")
- (?\Ⓛ "L-o")
- (?\Ⓜ "M-o")
- (?\Ⓝ "N-o")
- (?\Ⓞ "O-o")
- (?\Ⓟ "P-o")
- (?\Ⓠ "Q-o")
- (?\Ⓡ "R-o")
- (?\Ⓢ "S-o")
- (?\Ⓣ "T-o")
- (?\Ⓤ "U-o")
- (?\Ⓥ "V-o")
- (?\Ⓦ "W-o")
- (?\Ⓧ "X-o")
- (?\Ⓨ "Y-o")
- (?\Ⓩ "Z-o")
- (?\ⓐ "a-o")
- (?\ⓑ "b-o")
- (?\ⓒ "c-o")
- (?\ⓓ "d-o")
- (?\ⓔ "e-o")
- (?\ⓕ "f-o")
- (?\ⓖ "g-o")
- (?\ⓗ "h-o")
- (?\ⓘ "i-o")
- (?\ⓙ "j-o")
- (?\ⓚ "k-o")
- (?\ⓛ "l-o")
- (?\ⓜ "m-o")
- (?\ⓝ "n-o")
- (?\ⓞ "o-o")
- (?\ⓟ "p-o")
- (?\ⓠ "q-o")
- (?\ⓡ "r-o")
- (?\ⓢ "s-o")
- (?\ⓣ "t-o")
- (?\ⓤ "u-o")
- (?\ⓥ "v-o")
- (?\ⓦ "w-o")
- (?\ⓧ "x-o")
- (?\ⓨ "y-o")
- (?\ⓩ "z-o")
- (?\⓪ "0-o")
- (?\─ "-")
- (?\━ "=")
- (?\│ "|")
- (?\┃ "|")
- (?\┄ "-")
- (?\┅ "=")
- (?\┆ "|")
- (?\┇ "|")
- (?\┈ "-")
- (?\┉ "=")
- (?\┊ "|")
- (?\┋ "|")
- (?\┌ "+")
- (?\┍ "+")
- (?\┎ "+")
- (?\┏ "+")
- (?\┐ "+")
- (?\┑ "+")
- (?\┒ "+")
- (?\┓ "+")
- (?\└ "+")
- (?\┕ "+")
- (?\┖ "+")
- (?\┗ "+")
- (?\┘ "+")
- (?\┙ "+")
- (?\┚ "+")
- (?\┛ "+")
- (?\├ "+")
- (?\┝ "+")
- (?\┞ "+")
- (?\┟ "+")
- (?\┠ "+")
- (?\┡ "+")
- (?\┢ "+")
- (?\┣ "+")
- (?\┤ "+")
- (?\┥ "+")
- (?\┦ "+")
- (?\┧ "+")
- (?\┨ "+")
- (?\┩ "+")
- (?\┪ "+")
- (?\┫ "+")
- (?\┬ "+")
- (?\┭ "+")
- (?\┮ "+")
- (?\┯ "+")
- (?\┰ "+")
- (?\┱ "+")
- (?\┲ "+")
- (?\┳ "+")
- (?\┴ "+")
- (?\┵ "+")
- (?\┶ "+")
- (?\┷ "+")
- (?\┸ "+")
- (?\┹ "+")
- (?\┺ "+")
- (?\┻ "+")
- (?\┼ "+")
- (?\┽ "+")
- (?\┾ "+")
- (?\┿ "+")
- (?\╀ "+")
- (?\╁ "+")
- (?\╂ "+")
- (?\╃ "+")
- (?\╄ "+")
- (?\╅ "+")
- (?\╆ "+")
- (?\╇ "+")
- (?\╈ "+")
- (?\╉ "+")
- (?\╊ "+")
- (?\╋ "+")
- (?\╌ "+")
- (?\╍ "+")
- (?\╎ "+")
- (?\╏ "+")
- (?\═ "+")
- (?\║ "+")
- (?\╒ "+")
- (?\╓ "+")
- (?\╔ "+")
- (?\╕ "+")
- (?\╖ "+")
- (?\╗ "+")
- (?\╘ "+")
- (?\╙ "+")
- (?\╚ "+")
- (?\╛ "+")
- (?\╜ "+")
- (?\╝ "+")
- (?\╞ "+")
- (?\╟ "+")
- (?\╠ "+")
- (?\╡ "+")
- (?\╢ "+")
- (?\╣ "+")
- (?\╤ "+")
- (?\╥ "+")
- (?\╦ "+")
- (?\╧ "+")
- (?\╨ "+")
- (?\╩ "+")
- (?\╪ "+")
- (?\╫ "+")
- (?\╬ "+")
- (?\╱ "/")
- (?\╲ "\\")
- (?\▀ "TB")
- (?\▄ "LB")
- (?\█ "FB")
- (?\▌ "lB")
- (?\▐ "RB")
- (?\░ ".S")
- (?\▒ ":S")
- (?\▓ "?S")
- (?\■ "fS")
- (?\□ "OS")
- (?\▢ "RO")
- (?\▣ "Rr")
- (?\▤ "RF")
- (?\▥ "RY")
- (?\▦ "RH")
- (?\▧ "RZ")
- (?\▨ "RK")
- (?\▩ "RX")
- (?\▪ "sB")
- (?\▬ "SR")
- (?\▭ "Or")
- (?\▲ "^")
- (?\△ "uT")
- (?\▶ "|>")
- (?\▷ "Tr")
- (?\► "|>")
- (?\▼ "v")
- (?\▽ "dT")
- (?\◀ "<|")
- (?\◁ "Tl")
- (?\◄ "<|")
- (?\◆ "Db")
- (?\◇ "Dw")
- (?\◊ "LZ")
- (?\○ "0m")
- (?\◎ "0o")
- (?\● "0M")
- (?\◐ "0L")
- (?\◑ "0R")
- (?\◘ "Sn")
- (?\◙ "Ic")
- (?\◢ "Fd")
- (?\◣ "Bd")
- (?\◯ "Ci")
- (?\★ "*2")
- (?\☆ "*1")
- (?\☎ "TEL")
- (?\☏ "tel")
- (?\☜ "<--")
- (?\☞ "-->")
- (?\☡ "CAUTION ")
- (?\☧ "XP")
- (?\☹ ":-(")
- (?\☺ ":-)")
- (?\☻ "(-:")
- (?\☼ "SU")
- (?\♀ "f.")
- (?\♂ "m.")
- (?\♠ "cS")
- (?\♡ "cH")
- (?\♢ "cD")
- (?\♣ "cC")
- (?\♤ "cS-")
- (?\♥ "cH-")
- (?\♦ "cD-")
- (?\♧ "cC-")
- (?\♩ "Md")
- (?\♪ "M8")
- (?\♫ "M2")
- (?\♬ "M16")
- (?\♭ "b")
- (?\♮ "Mx")
- (?\♯ "#")
- (?\✓ "X")
- (?\✗ "X")
- (?\✠ "-X")
- (?\  " ")
- (?\、 ",_")
- (?\。 "._")
- (?\〃 "+\"")
- (?\〄 "JIS")
- (?\々 "*_")
- (?\〆 ";_")
- (?\〇 "0_")
- (?\《 "<+")
- (?\》 ">+")
- (?\「 "<'")
- (?\」 ">'")
- (?\『 "<\"")
- (?\』 ">\"")
- (?\【 "(\"")
- (?\】 ")\"")
- (?\〒 "=T")
- (?\〓 "=_")
- (?\〔 "('")
- (?\〕 ")'")
- (?\〖 "(I")
- (?\〗 ")I")
- (?\〚 "[[")
- (?\〛 "]]")
- (?\〜 "-?")
- (?\〠 "=T:)")
- (?\〿 " ")
- (?\ぁ "A5")
- (?\あ "a5")
- (?\ぃ "I5")
- (?\い "i5")
- (?\ぅ "U5")
- (?\う "u5")
- (?\ぇ "E5")
- (?\え "e5")
- (?\ぉ "O5")
- (?\お "o5")
- (?\か "ka")
- (?\が "ga")
- (?\き "ki")
- (?\ぎ "gi")
- (?\く "ku")
- (?\ぐ "gu")
- (?\け "ke")
- (?\げ "ge")
- (?\こ "ko")
- (?\ご "go")
- (?\さ "sa")
- (?\ざ "za")
- (?\し "si")
- (?\じ "zi")
- (?\す "su")
- (?\ず "zu")
- (?\せ "se")
- (?\ぜ "ze")
- (?\そ "so")
- (?\ぞ "zo")
- (?\た "ta")
- (?\だ "da")
- (?\ち "ti")
- (?\ぢ "di")
- (?\っ "tU")
- (?\つ "tu")
- (?\づ "du")
- (?\て "te")
- (?\で "de")
- (?\と "to")
- (?\ど "do")
- (?\な "na")
- (?\に "ni")
- (?\ぬ "nu")
- (?\ね "ne")
- (?\の "no")
- (?\は "ha")
- (?\ば "ba")
- (?\ぱ "pa")
- (?\ひ "hi")
- (?\び "bi")
- (?\ぴ "pi")
- (?\ふ "hu")
- (?\ぶ "bu")
- (?\ぷ "pu")
- (?\へ "he")
- (?\べ "be")
- (?\ぺ "pe")
- (?\ほ "ho")
- (?\ぼ "bo")
- (?\ぽ "po")
- (?\ま "ma")
- (?\み "mi")
- (?\む "mu")
- (?\め "me")
- (?\も "mo")
- (?\ゃ "yA")
- (?\や "ya")
- (?\ゅ "yU")
- (?\ゆ "yu")
- (?\ょ "yO")
- (?\よ "yo")
- (?\ら "ra")
- (?\り "ri")
- (?\る "ru")
- (?\れ "re")
- (?\ろ "ro")
- (?\ゎ "wA")
- (?\わ "wa")
- (?\ゐ "wi")
- (?\ゑ "we")
- (?\を "wo")
- (?\ん "n5")
- (?\ゔ "vu")
- (?\゛ "\"5")
- (?\゜ "05")
- (?\ゝ "*5")
- (?\ゞ "+5")
- (?\ァ "a6")
- (?\ア "A6")
- (?\ィ "i6")
- (?\イ "I6")
- (?\ゥ "u6")
- (?\ウ "U6")
- (?\ェ "e6")
- (?\エ "E6")
- (?\ォ "o6")
- (?\オ "O6")
- (?\カ "Ka")
- (?\ガ "Ga")
- (?\キ "Ki")
- (?\ギ "Gi")
- (?\ク "Ku")
- (?\グ "Gu")
- (?\ケ "Ke")
- (?\ゲ "Ge")
- (?\コ "Ko")
- (?\ゴ "Go")
- (?\サ "Sa")
- (?\ザ "Za")
- (?\シ "Si")
- (?\ジ "Zi")
- (?\ス "Su")
- (?\ズ "Zu")
- (?\セ "Se")
- (?\ゼ "Ze")
- (?\ソ "So")
- (?\ゾ "Zo")
- (?\タ "Ta")
- (?\ダ "Da")
- (?\チ "Ti")
- (?\ヂ "Di")
- (?\ッ "TU")
- (?\ツ "Tu")
- (?\ヅ "Du")
- (?\テ "Te")
- (?\デ "De")
- (?\ト "To")
- (?\ド "Do")
- (?\ナ "Na")
- (?\ニ "Ni")
- (?\ヌ "Nu")
- (?\ネ "Ne")
- (?\ノ "No")
- (?\ハ "Ha")
- (?\バ "Ba")
- (?\パ "Pa")
- (?\ヒ "Hi")
- (?\ビ "Bi")
- (?\ピ "Pi")
- (?\フ "Hu")
- (?\ブ "Bu")
- (?\プ "Pu")
- (?\ヘ "He")
- (?\ベ "Be")
- (?\ペ "Pe")
- (?\ホ "Ho")
- (?\ボ "Bo")
- (?\ポ "Po")
- (?\マ "Ma")
- (?\ミ "Mi")
- (?\ム "Mu")
- (?\メ "Me")
- (?\モ "Mo")
- (?\ャ "YA")
- (?\ヤ "Ya")
- (?\ュ "YU")
- (?\ユ "Yu")
- (?\ョ "YO")
- (?\ヨ "Yo")
- (?\ラ "Ra")
- (?\リ "Ri")
- (?\ル "Ru")
- (?\レ "Re")
- (?\ロ "Ro")
- (?\ヮ "WA")
- (?\ワ "Wa")
- (?\ヰ "Wi")
- (?\ヱ "We")
- (?\ヲ "Wo")
- (?\ン "N6")
- (?\ヴ "Vu")
- (?\ヵ "KA")
- (?\ヶ "KE")
- (?\ヷ "Va")
- (?\ヸ "Vi")
- (?\ヹ "Ve")
- (?\ヺ "Vo")
- (?\・ ".6")
- (?\ー "-6")
- (?\ヽ "*6")
- (?\ヾ "+6")
- (?\ㄅ "b4")
- (?\ㄆ "p4")
- (?\ㄇ "m4")
- (?\ㄈ "f4")
- (?\ㄉ "d4")
- (?\ㄊ "t4")
- (?\ㄋ "n4")
- (?\ㄌ "l4")
- (?\ㄍ "g4")
- (?\ㄎ "k4")
- (?\ㄏ "h4")
- (?\ㄐ "j4")
- (?\ㄑ "q4")
- (?\ㄒ "x4")
- (?\ㄓ "zh")
- (?\ㄔ "ch")
- (?\ㄕ "sh")
- (?\ㄖ "r4")
- (?\ㄗ "z4")
- (?\ㄘ "c4")
- (?\ㄙ "s4")
- (?\ㄚ "a4")
- (?\ㄛ "o4")
- (?\ㄜ "e4")
- (?\ㄝ "eh4")
- (?\ㄞ "ai")
- (?\ㄟ "ei")
- (?\ㄠ "au")
- (?\ㄡ "ou")
- (?\ㄢ "an")
- (?\ㄣ "en")
- (?\ㄤ "aN")
- (?\ㄥ "eN")
- (?\ㄦ "er")
- (?\ㄧ "i4")
- (?\ㄨ "u4")
- (?\ㄩ "iu")
- (?\ㄪ "v4")
- (?\ㄫ "nG")
- (?\ㄬ "gn")
- (?\㈜ "(JU)")
- (?\㈠ "1c")
- (?\㈡ "2c")
- (?\㈢ "3c")
- (?\㈣ "4c")
- (?\㈤ "5c")
- (?\㈥ "6c")
- (?\㈦ "7c")
- (?\㈧ "8c")
- (?\㈨ "9c")
- (?\㈩ "10c")
- (?\㉿ "KSC")
- (?\㏂ "am")
- (?\㏘ "pm")
- (?\ff "ff")
- (?\fi "fi")
- (?\fl "fl")
- (?\ffi "ffi")
- (?\ffl "ffl")
- (?\ſt "St")
- (?\st "st")
- (?\ﹽ "3+;")
- (?\ﺂ "aM.")
- (?\ﺄ "aH.")
- (?\ﺈ "ah.")
- (?\ﺍ "a+-")
- (?\ﺎ "a+.")
- (?\ﺏ "b+-")
- (?\ﺐ "b+.")
- (?\ﺑ "b+,")
- (?\ﺒ "b+;")
- (?\ﺓ "tm-")
- (?\ﺔ "tm.")
- (?\ﺕ "t+-")
- (?\ﺖ "t+.")
- (?\ﺗ "t+,")
- (?\ﺘ "t+;")
- (?\ﺙ "tk-")
- (?\ﺚ "tk.")
- (?\ﺛ "tk,")
- (?\ﺜ "tk;")
- (?\ﺝ "g+-")
- (?\ﺞ "g+.")
- (?\ﺟ "g+,")
- (?\ﺠ "g+;")
- (?\ﺡ "hk-")
- (?\ﺢ "hk.")
- (?\ﺣ "hk,")
- (?\ﺤ "hk;")
- (?\ﺥ "x+-")
- (?\ﺦ "x+.")
- (?\ﺧ "x+,")
- (?\ﺨ "x+;")
- (?\ﺩ "d+-")
- (?\ﺪ "d+.")
- (?\ﺫ "dk-")
- (?\ﺬ "dk.")
- (?\ﺭ "r+-")
- (?\ﺮ "r+.")
- (?\ﺯ "z+-")
- (?\ﺰ "z+.")
- (?\ﺱ "s+-")
- (?\ﺲ "s+.")
- (?\ﺳ "s+,")
- (?\ﺴ "s+;")
- (?\ﺵ "sn-")
- (?\ﺶ "sn.")
- (?\ﺷ "sn,")
- (?\ﺸ "sn;")
- (?\ﺹ "c+-")
- (?\ﺺ "c+.")
- (?\ﺻ "c+,")
- (?\ﺼ "c+;")
- (?\ﺽ "dd-")
- (?\ﺾ "dd.")
- (?\ﺿ "dd,")
- (?\ﻀ "dd;")
- (?\ﻁ "tj-")
- (?\ﻂ "tj.")
- (?\ﻃ "tj,")
- (?\ﻄ "tj;")
- (?\ﻅ "zH-")
- (?\ﻆ "zH.")
- (?\ﻇ "zH,")
- (?\ﻈ "zH;")
- (?\ﻉ "e+-")
- (?\ﻊ "e+.")
- (?\ﻋ "e+,")
- (?\ﻌ "e+;")
- (?\ﻍ "i+-")
- (?\ﻎ "i+.")
- (?\ﻏ "i+,")
- (?\ﻐ "i+;")
- (?\ﻑ "f+-")
- (?\ﻒ "f+.")
- (?\ﻓ "f+,")
- (?\ﻔ "f+;")
- (?\ﻕ "q+-")
- (?\ﻖ "q+.")
- (?\ﻗ "q+,")
- (?\ﻘ "q+;")
- (?\ﻙ "k+-")
- (?\ﻚ "k+.")
- (?\ﻛ "k+,")
- (?\ﻜ "k+;")
- (?\ﻝ "l+-")
- (?\ﻞ "l+.")
- (?\ﻟ "l+,")
- (?\ﻠ "l+;")
- (?\ﻡ "m+-")
- (?\ﻢ "m+.")
- (?\ﻣ "m+,")
- (?\ﻤ "m+;")
- (?\ﻥ "n+-")
- (?\ﻦ "n+.")
- (?\ﻧ "n+,")
- (?\ﻨ "n+;")
- (?\ﻩ "h+-")
- (?\ﻪ "h+.")
- (?\ﻫ "h+,")
- (?\ﻬ "h+;")
- (?\ﻭ "w+-")
- (?\ﻮ "w+.")
- (?\ﻯ "j+-")
- (?\ﻰ "j+.")
- (?\ﻱ "y+-")
- (?\ﻲ "y+.")
- (?\ﻳ "y+,")
- (?\ﻴ "y+;")
- (?\ﻵ "lM-")
- (?\ﻶ "lM.")
- (?\ﻷ "lH-")
- (?\ﻸ "lH.")
- (?\ﻹ "lh-")
- (?\ﻺ "lh.")
- (?\ﻻ "la-")
- (?\ﻼ "la.")
- (?\! "!")
- (?\" "\"")
- (?\# "#")
- (?\$ "$")
- (?\% "%")
- (?\& "&")
- (?\' "'")
- (?\( "(")
- (?\) ")")
- (?\* "*")
- (?\+ "+")
- (?\, ",")
- (?\- "-")
- (?\. ".")
- (?\/ "/")
- (?\0 "0")
- (?\1 "1")
- (?\2 "2")
- (?\3 "3")
- (?\4 "4")
- (?\5 "5")
- (?\6 "6")
- (?\7 "7")
- (?\8 "8")
- (?\9 "9")
- (?\: ":")
- (?\; ";")
- (?\< "<")
- (?\= "=")
- (?\> ">")
- (?\? "?")
- (?\@ "@")
- (?\A "A")
- (?\B "B")
- (?\C "C")
- (?\D "D")
- (?\E "E")
- (?\F "F")
- (?\G "G")
- (?\H "H")
- (?\I "I")
- (?\J "J")
- (?\K "K")
- (?\L "L")
- (?\M "M")
- (?\N "N")
- (?\O "O")
- (?\P "P")
- (?\Q "Q")
- (?\R "R")
- (?\S "S")
- (?\T "T")
- (?\U "U")
- (?\V "V")
- (?\W "W")
- (?\X "X")
- (?\Y "Y")
- (?\Z "Z")
- (?\[ "[")
- (?\\ "\\")
- (?\] "]")
- (?\^ "^")
- (?\_ "_")
- (?\` "`")
- (?\a "a")
- (?\b "b")
- (?\c "c")
- (?\d "d")
- (?\e "e")
- (?\f "f")
- (?\g "g")
- (?\h "h")
- (?\i "i")
- (?\j "j")
- (?\k "k")
- (?\l "l")
- (?\m "m")
- (?\n "n")
- (?\o "o")
- (?\p "p")
- (?\q "q")
- (?\r "r")
- (?\s "s")
- (?\t "t")
- (?\u "u")
- (?\v "v")
- (?\w "w")
- (?\x "x")
- (?\y "y")
- (?\z "z")
- (?\{ "{")
- (?\| "|")
- (?\} "}")
- (?\~ "~")
- (?\。 ".")
- (?\「 "\"")
- (?\」 "\"")
- (?\、 ",")
- ;; Not from Lynx
- (? "")
- (?� "?")))))
+ (let ((latin1-display-format "%s"))
+ (mapc
+ (lambda (l)
+ (or (char-displayable-p (car l))
+ (apply 'latin1-display-char l)))
+ ;; Table derived by running Lynx on a suitable list of
+ ;; characters in a utf-8 file, except for some added by
+ ;; hand at the end.
+ '((?\Ā "A")
+ (?\ā "a")
+ (?\Ă "A")
+ (?\ă "a")
+ (?\Ą "A")
+ (?\ą "a")
+ (?\Ć "C")
+ (?\ć "c")
+ (?\Ĉ "C")
+ (?\ĉ "c")
+ (?\Ċ "C")
+ (?\ċ "c")
+ (?\Č "C")
+ (?\č "c")
+ (?\Ď "D")
+ (?\ď "d")
+ (?\Đ "Ð")
+ (?\đ "d/")
+ (?\Ē "E")
+ (?\ē "e")
+ (?\Ĕ "E")
+ (?\ĕ "e")
+ (?\Ė "E")
+ (?\ė "e")
+ (?\Ę "E")
+ (?\ę "e")
+ (?\Ě "E")
+ (?\ě "e")
+ (?\Ĝ "G")
+ (?\ĝ "g")
+ (?\Ğ "G")
+ (?\ğ "g")
+ (?\Ġ "G")
+ (?\ġ "g")
+ (?\Ģ "G")
+ (?\ģ "g")
+ (?\Ĥ "H")
+ (?\ĥ "h")
+ (?\Ħ "H/")
+ (?\ħ "H")
+ (?\Ĩ "I")
+ (?\ĩ "i")
+ (?\Ī "I")
+ (?\ī "i")
+ (?\Ĭ "I")
+ (?\ĭ "i")
+ (?\Į "I")
+ (?\į "i")
+ (?\İ "I")
+ (?\ı "i")
+ (?\IJ "IJ")
+ (?\ij "ij")
+ (?\Ĵ "J")
+ (?\ĵ "j")
+ (?\Ķ "K")
+ (?\ķ "k")
+ (?\ĸ "kk")
+ (?\Ĺ "L")
+ (?\ĺ "l")
+ (?\Ļ "L")
+ (?\ļ "l")
+ (?\Ľ "L")
+ (?\ľ "l")
+ (?\Ŀ "L.")
+ (?\ŀ "l.")
+ (?\Ł "L/")
+ (?\ł "l/")
+ (?\Ń "N")
+ (?\ń "n")
+ (?\Ņ "N")
+ (?\ņ "n")
+ (?\Ň "N")
+ (?\ň "n")
+ (?\ʼn "'n")
+ (?\Ŋ "NG")
+ (?\ŋ "N")
+ (?\Ō "O")
+ (?\ō "o")
+ (?\Ŏ "O")
+ (?\ŏ "o")
+ (?\Ő "O\"")
+ (?\ő "o\"")
+ (?\Π"OE")
+ (?\œ "oe")
+ (?\Ŕ "R")
+ (?\ŕ "r")
+ (?\Ŗ "R")
+ (?\ŗ "r")
+ (?\Ř "R")
+ (?\ř "r")
+ (?\Ś "S")
+ (?\ś "s")
+ (?\Ŝ "S")
+ (?\ŝ "s")
+ (?\Ş "S")
+ (?\ş "s")
+ (?\Š "S")
+ (?\š "s")
+ (?\Ţ "T")
+ (?\ţ "t")
+ (?\Ť "T")
+ (?\ť "t")
+ (?\Ŧ "T/")
+ (?\ŧ "t/")
+ (?\Ũ "U")
+ (?\ũ "u")
+ (?\Ū "U")
+ (?\ū "u")
+ (?\Ŭ "U")
+ (?\ŭ "u")
+ (?\Ů "U")
+ (?\ů "u")
+ (?\Ű "U\"")
+ (?\ű "u\"")
+ (?\Ų "U")
+ (?\ų "u")
+ (?\Ŵ "W")
+ (?\ŵ "w")
+ (?\Ŷ "Y")
+ (?\ŷ "y")
+ (?\Ÿ "Y")
+ (?\Ź "Z")
+ (?\ź "z")
+ (?\Ż "Z")
+ (?\ż "z")
+ (?\Ž "Z")
+ (?\ž "z")
+ (?\ſ "s1")
+ (?\Ƈ "C2")
+ (?\ƈ "c2")
+ (?\Ƒ "F2")
+ (?\ƒ " f")
+ (?\Ƙ "K2")
+ (?\ƙ "k2")
+ (?\Ơ "O9")
+ (?\ơ "o9")
+ (?\Ƣ "OI")
+ (?\ƣ "oi")
+ (?\Ʀ "yr")
+ (?\Ư "U9")
+ (?\ư "u9")
+ (?\Ƶ "Z/")
+ (?\ƶ "z/")
+ (?\Ʒ "ED")
+ (?\Ǎ "A")
+ (?\ǎ "a")
+ (?\Ǐ "I")
+ (?\ǐ "i")
+ (?\Ǒ "O")
+ (?\ǒ "o")
+ (?\Ǔ "U")
+ (?\ǔ "u")
+ (?\Ǖ "U:-")
+ (?\ǖ "u:-")
+ (?\Ǘ "U:'")
+ (?\ǘ "u:'")
+ (?\Ǚ "U:<")
+ (?\ǚ "u:<")
+ (?\Ǜ "U:!")
+ (?\ǜ "u:!")
+ (?\Ǟ "A1")
+ (?\ǟ "a1")
+ (?\Ǡ "A7")
+ (?\ǡ "a7")
+ (?\Ǣ "A3")
+ (?\ǣ "a3")
+ (?\Ǥ "G/")
+ (?\ǥ "g/")
+ (?\Ǧ "G")
+ (?\ǧ "g")
+ (?\Ǩ "K")
+ (?\ǩ "k")
+ (?\Ǫ "O")
+ (?\ǫ "o")
+ (?\Ǭ "O1")
+ (?\ǭ "o1")
+ (?\Ǯ "EZ")
+ (?\ǯ "ez")
+ (?\ǰ "j")
+ (?\Ǵ "G")
+ (?\ǵ "g")
+ (?\Ǻ "AA'")
+ (?\ǻ "aa'")
+ (?\Ǽ "AE'")
+ (?\ǽ "ae'")
+ (?\Ǿ "O/'")
+ (?\ǿ "o/'")
+ (?\Ȁ "A!!")
+ (?\ȁ "a!!")
+ (?\Ȃ "A)")
+ (?\ȃ "a)")
+ (?\Ȅ "E!!")
+ (?\ȅ "e!!")
+ (?\Ȇ "E)")
+ (?\ȇ "e)")
+ (?\Ȉ "I!!")
+ (?\ȉ "i!!")
+ (?\Ȋ "I)")
+ (?\ȋ "i)")
+ (?\Ȍ "O!!")
+ (?\ȍ "o!!")
+ (?\Ȏ "O)")
+ (?\ȏ "o)")
+ (?\Ȑ "R!!")
+ (?\ȑ "r!!")
+ (?\Ȓ "R)")
+ (?\ȓ "r)")
+ (?\Ȕ "U!!")
+ (?\ȕ "u!!")
+ (?\Ȗ "U)")
+ (?\ȗ "u)")
+ (?\ȝ "Z")
+ (?\ɑ "A")
+ (?\ɒ "A.")
+ (?\ɓ "b`")
+ (?\ɔ "O")
+ (?\ɖ "d.")
+ (?\ɗ "d`")
+ (?\ɘ "@<umd>")
+ (?\ə "@")
+ (?\ɚ "R")
+ (?\ɛ "E")
+ (?\ɜ "V\"")
+ (?\ɝ "R<umd>")
+ (?\ɞ "O\"")
+ (?\ɟ "J")
+ (?\ɠ "g`")
+ (?\ɡ "g")
+ (?\ɢ "G")
+ (?\ɣ "Q")
+ (?\ɤ "o-")
+ (?\ɥ "j<rnd>")
+ (?\ɦ "h<?>")
+ (?\ɨ "i\"")
+ (?\ɩ "I")
+ (?\ɪ "I")
+ (?\ɫ "L")
+ (?\ɬ "L")
+ (?\ɭ "l.")
+ (?\ɮ "z<lat>")
+ (?\ɯ "u-")
+ (?\ɰ "j<vel>")
+ (?\ɱ "M")
+ (?\ɳ "n.")
+ (?\ɴ "n\"")
+ (?\ɵ "@.")
+ (?\ɶ "&.")
+ (?\ɷ "U")
+ (?\ɹ "r")
+ (?\ɺ "*<lat>")
+ (?\ɻ "r.")
+ (?\ɽ "*.")
+ (?\ɾ "*")
+ (?\ʀ "R")
+ (?\ʁ "g\"")
+ (?\ʂ "s.")
+ (?\ʃ "S")
+ (?\ʄ "J`")
+ (?\ʇ "t!")
+ (?\ʈ "t.")
+ (?\ʉ "u\"")
+ (?\ʊ "U")
+ (?\ʋ "r<lbd>")
+ (?\ʌ "V")
+ (?\ʍ "w<vls>")
+ (?\ʎ "l^")
+ (?\ʏ "I.")
+ (?\ʐ "z.")
+ (?\ʒ "Z")
+ (?\ʔ "?")
+ (?\ʕ "H<vcd>")
+ (?\ʖ "l!")
+ (?\ʗ "c!")
+ (?\ʘ "p!")
+ (?\ʙ "b<trl>")
+ (?\ʛ "G`")
+ (?\ʝ "j")
+ (?\ʞ "k!")
+ (?\ʟ "L")
+ (?\ʠ "q`")
+ (?\ʤ "d3")
+ (?\ʦ "ts")
+ (?\ʧ "tS")
+ (?\ʰ "<h>")
+ (?\ʱ "<?>")
+ (?\ʲ ";")
+ (?\ʳ "<r>")
+ (?\ʷ "<w>")
+ (?\ʻ ";S")
+ (?\ʼ "`")
+ (?\ˆ "^")
+ (?\ˇ "'<")
+ (?\ˈ "|")
+ (?\ˉ "1-")
+ (?\ˋ "1!")
+ (?\ː ":")
+ (?\ˑ ":\\")
+ (?\˖ "+")
+ (?\˗ "-")
+ (?\˘ "'(")
+ (?\˙ "'.")
+ (?\˚ "'0")
+ (?\˛ "';")
+ (?\˜ "~")
+ (?\˝ "'\"")
+ (?\˥ "_T")
+ (?\˦ "_H")
+ (?\˧ "_M")
+ (?\˨ "_L")
+ (?\˩ "_B")
+ (?\ˬ "_v")
+ (?\ˮ "''")
+ (?\̀ "`")
+ (?\́ "'")
+ (?\̂ "^")
+ (?\̃ "~")
+ (?\̄ "¯")
+ (?\̇ "·")
+ (?\̈ "¨")
+ (?\̊ "°")
+ (?\̋ "''")
+ (?\̍ "|")
+ (?\̎ "||")
+ (?\̏ "``")
+ (?\̡ ";")
+ (?\̢ ".")
+ (?\̣ ".")
+ (?\̤ "<?>")
+ (?\̥ "<o>")
+ (?\̦ ",")
+ (?\̧ "¸")
+ (?\̩ "-")
+ (?\̪ "[")
+ (?\̫ "<w>")
+ (?\̴ "~")
+ (?\̷ "/")
+ (?\̸ "/")
+ (?\̀ "`")
+ (?\́ "'")
+ (?\͂ "~")
+ (?\̈́ "'%")
+ (?\ͅ "j3")
+ (?\͇ "=")
+ (?\͠ "~~")
+ (?\ʹ "'")
+ (?\͵ ",")
+ (?\ͺ "j3")
+ (?\; "?%")
+ (?\΄ "'*")
+ (?\΅ "'%")
+ (?\Ά "A'")
+ (?\· "·")
+ (?\Έ "E'")
+ (?\Ή "Y%")
+ (?\Ί "I'")
+ (?\Ό "O'")
+ (?\Ύ "U%")
+ (?\Ώ "W%")
+ (?\ΐ "i3")
+ (?\Α "A")
+ (?\Β "B")
+ (?\Γ "G")
+ (?\Δ "D")
+ (?\Ε "E")
+ (?\Ζ "Z")
+ (?\Η "Y")
+ (?\Θ "TH")
+ (?\Ι "I")
+ (?\Κ "K")
+ (?\Λ "L")
+ (?\Μ "M")
+ (?\Ν "N")
+ (?\Ξ "C")
+ (?\Ο "O")
+ (?\Π "P")
+ (?\Ρ "R")
+ (?\Σ "S")
+ (?\Τ "T")
+ (?\Υ "U")
+ (?\Φ "F")
+ (?\Χ "X")
+ (?\Ψ "Q")
+ (?\Ω "W*")
+ (?\Ϊ "J")
+ (?\Ϋ "V*")
+ (?\ά "a'")
+ (?\έ "e'")
+ (?\ή "y%")
+ (?\ί "i'")
+ (?\ΰ "u3")
+ (?\α "a")
+ (?\β "b")
+ (?\γ "g")
+ (?\δ "d")
+ (?\ε "e")
+ (?\ζ "z")
+ (?\η "y")
+ (?\θ "th")
+ (?\ι "i")
+ (?\κ "k")
+ (?\λ "l")
+ (?\μ "µ")
+ (?\ν "n")
+ (?\ξ "c")
+ (?\ο "o")
+ (?\π "p")
+ (?\ρ "r")
+ (?\ς "*s")
+ (?\σ "s")
+ (?\τ "t")
+ (?\υ "u")
+ (?\φ "f")
+ (?\χ "x")
+ (?\ψ "q")
+ (?\ω "w")
+ (?\ϊ "j")
+ (?\ϋ "v*")
+ (?\ό "o'")
+ (?\ύ "u%")
+ (?\ώ "w%")
+ (?\ϐ "beta ")
+ (?\ϑ "theta ")
+ (?\ϒ "upsi ")
+ (?\ϕ "phi ")
+ (?\ϖ "pi ")
+ (?\ϗ "k.")
+ (?\Ϛ "T3")
+ (?\ϛ "t3")
+ (?\Ϝ "M3")
+ (?\ϝ "m3")
+ (?\Ϟ "K3")
+ (?\ϟ "k3")
+ (?\Ϡ "P3")
+ (?\ϡ "p3")
+ (?\ϰ "kappa ")
+ (?\ϱ "rho ")
+ (?\ϳ "J")
+ (?\ϴ "'%")
+ (?\ϵ "j3")
+ (?\Ё "IO")
+ (?\Ђ "D%")
+ (?\Ѓ "G%")
+ (?\Є "IE")
+ (?\Ѕ "DS")
+ (?\І "II")
+ (?\Ї "YI")
+ (?\Ј "J%")
+ (?\Љ "LJ")
+ (?\Њ "NJ")
+ (?\Ћ "Ts")
+ (?\Ќ "KJ")
+ (?\Ў "V%")
+ (?\Џ "DZ")
+ (?\А "A")
+ (?\Б "B")
+ (?\В "V")
+ (?\Г "G")
+ (?\Д "D")
+ (?\Е "E")
+ (?\Ж "ZH")
+ (?\З "Z")
+ (?\И "I")
+ (?\Й "J")
+ (?\К "K")
+ (?\Л "L")
+ (?\М "M")
+ (?\Н "N")
+ (?\О "O")
+ (?\П "P")
+ (?\Р "R")
+ (?\С "S")
+ (?\Т "T")
+ (?\У "U")
+ (?\Ф "F")
+ (?\Х "H")
+ (?\Ц "C")
+ (?\Ч "CH")
+ (?\Ш "SH")
+ (?\Щ "SCH")
+ (?\Ъ "\"")
+ (?\Ы "Y")
+ (?\Ь "'")
+ (?\Э "`E")
+ (?\Ю "YU")
+ (?\Я "YA")
+ (?\а "a")
+ (?\б "b")
+ (?\в "v")
+ (?\г "g")
+ (?\д "d")
+ (?\е "e")
+ (?\ж "zh")
+ (?\з "z")
+ (?\и "i")
+ (?\й "j")
+ (?\к "k")
+ (?\л "l")
+ (?\м "m")
+ (?\н "n")
+ (?\о "o")
+ (?\п "p")
+ (?\р "r")
+ (?\с "s")
+ (?\т "t")
+ (?\у "u")
+ (?\ф "f")
+ (?\х "h")
+ (?\ц "c")
+ (?\ч "ch")
+ (?\ш "sh")
+ (?\щ "sch")
+ (?\ъ "\"")
+ (?\ы "y")
+ (?\ь "'")
+ (?\э "`e")
+ (?\ю "yu")
+ (?\я "ya")
+ (?\ё "io")
+ (?\ђ "d%")
+ (?\ѓ "g%")
+ (?\є "ie")
+ (?\ѕ "ds")
+ (?\і "ii")
+ (?\ї "yi")
+ (?\ј "j%")
+ (?\љ "lj")
+ (?\њ "nj")
+ (?\ћ "ts")
+ (?\ќ "kj")
+ (?\ў "v%")
+ (?\џ "dz")
+ (?\Ѣ "Y3")
+ (?\ѣ "y3")
+ (?\Ѫ "O3")
+ (?\ѫ "o3")
+ (?\Ѳ "F3")
+ (?\ѳ "f3")
+ (?\Ѵ "V3")
+ (?\ѵ "v3")
+ (?\Ҁ "C3")
+ (?\ҁ "c3")
+ (?\Ґ "G3")
+ (?\ґ "g3")
+ (?\Ӕ "AE")
+ (?\ӕ "ae")
+ (?\ִ "i")
+ (?\ַ "a")
+ (?\ָ "o")
+ (?\ּ "u")
+ (?\ֿ "h")
+ (?\ׂ ":")
+ (?\א "#")
+ (?\ב "B+")
+ (?\ג "G+")
+ (?\ד "D+")
+ (?\ה "H+")
+ (?\ו "W+")
+ (?\ז "Z+")
+ (?\ח "X+")
+ (?\ט "Tj")
+ (?\י "J+")
+ (?\ך "K%")
+ (?\כ "K+")
+ (?\ל "L+")
+ (?\ם "M%")
+ (?\מ "M+")
+ (?\ן "N%")
+ (?\נ "N+")
+ (?\ס "S+")
+ (?\ע "E+")
+ (?\ף "P%")
+ (?\פ "P+")
+ (?\ץ "Zj")
+ (?\צ "ZJ")
+ (?\ק "Q+")
+ (?\ר "R+")
+ (?\ש "Sh")
+ (?\ת "T+")
+ (?\װ "v")
+ (?\ױ "oy")
+ (?\ײ "ey")
+ (?\، ",+")
+ (?\؛ ";+")
+ (?\؟ "?+")
+ (?\ء "H'")
+ (?\آ "aM")
+ (?\أ "aH")
+ (?\ؤ "wH")
+ (?\إ "ah")
+ (?\ئ "yH")
+ (?\ا "a+")
+ (?\ب "b+")
+ (?\ة "tm")
+ (?\ت "t+")
+ (?\ث "tk")
+ (?\ج "g+")
+ (?\ح "hk")
+ (?\خ "x+")
+ (?\د "d+")
+ (?\ذ "dk")
+ (?\ر "r+")
+ (?\ز "z+")
+ (?\س "s+")
+ (?\ش "sn")
+ (?\ص "c+")
+ (?\ض "dd")
+ (?\ط "tj")
+ (?\ظ "zH")
+ (?\ع "e+")
+ (?\غ "i+")
+ (?\ـ "++")
+ (?\ف "f+")
+ (?\ق "q+")
+ (?\ك "k+")
+ (?\ل "l+")
+ (?\م "m+")
+ (?\ن "n+")
+ (?\ه "h+")
+ (?\و "w+")
+ (?\ى "j+")
+ (?\ي "y+")
+ (?\ً ":+")
+ (?\ٌ "\"+")
+ (?\ٍ "=+")
+ (?\َ "/+")
+ (?\ُ "'+")
+ (?\ِ "1+")
+ (?\ّ "3+")
+ (?\ْ "0+")
+ (?\٠ "0a")
+ (?\١ "1a")
+ (?\٢ "2a")
+ (?\٣ "3a")
+ (?\٤ "4a")
+ (?\٥ "5a")
+ (?\٦ "6a")
+ (?\٧ "7a")
+ (?\٨ "8a")
+ (?\٩ "9a")
+ (?\ٰ "aS")
+ (?\پ "p+")
+ (?\ځ "hH")
+ (?\چ "tc")
+ (?\ژ "zj")
+ (?\ڤ "v+")
+ (?\گ "gf")
+ (?\۰ "0a")
+ (?\۱ "1a")
+ (?\۲ "2a")
+ (?\۳ "3a")
+ (?\۴ "4a")
+ (?\۵ "5a")
+ (?\۶ "6a")
+ (?\۷ "7a")
+ (?\۸ "8a")
+ (?\۹ "9a")
+ (?\ሀ "he")
+ (?\ሁ "hu")
+ (?\ሂ "hi")
+ (?\ሃ "ha")
+ (?\ሄ "hE")
+ (?\ህ "h")
+ (?\ሆ "ho")
+ (?\ለ "le")
+ (?\ሉ "lu")
+ (?\ሊ "li")
+ (?\ላ "la")
+ (?\ሌ "lE")
+ (?\ል "l")
+ (?\ሎ "lo")
+ (?\ሏ "lWa")
+ (?\ሐ "He")
+ (?\ሑ "Hu")
+ (?\ሒ "Hi")
+ (?\ሓ "Ha")
+ (?\ሔ "HE")
+ (?\ሕ "H")
+ (?\ሖ "Ho")
+ (?\ሗ "HWa")
+ (?\መ "me")
+ (?\ሙ "mu")
+ (?\ሚ "mi")
+ (?\ማ "ma")
+ (?\ሜ "mE")
+ (?\ም "m")
+ (?\ሞ "mo")
+ (?\ሟ "mWa")
+ (?\ሠ "`se")
+ (?\ሡ "`su")
+ (?\ሢ "`si")
+ (?\ሣ "`sa")
+ (?\ሤ "`sE")
+ (?\ሥ "`s")
+ (?\ሦ "`so")
+ (?\ሧ "`sWa")
+ (?\ረ "re")
+ (?\ሩ "ru")
+ (?\ሪ "ri")
+ (?\ራ "ra")
+ (?\ሬ "rE")
+ (?\ር "r")
+ (?\ሮ "ro")
+ (?\ሯ "rWa")
+ (?\ሰ "se")
+ (?\ሱ "su")
+ (?\ሲ "si")
+ (?\ሳ "sa")
+ (?\ሴ "sE")
+ (?\ስ "s")
+ (?\ሶ "so")
+ (?\ሷ "sWa")
+ (?\ሸ "xe")
+ (?\ሹ "xu")
+ (?\ሺ "xi")
+ (?\ሻ "xa")
+ (?\ሼ "xE")
+ (?\ሽ "xa")
+ (?\ሾ "xo")
+ (?\ሿ "xWa")
+ (?\ቀ "qe")
+ (?\ቁ "qu")
+ (?\ቂ "qi")
+ (?\ቃ "qa")
+ (?\ቄ "qE")
+ (?\ቅ "q")
+ (?\ቆ "qo")
+ (?\ቈ "qWe")
+ (?\ቊ "qWi")
+ (?\ቋ "qWa")
+ (?\ቌ "qWE")
+ (?\ቍ "qW")
+ (?\ቐ "Qe")
+ (?\ቑ "Qu")
+ (?\ቒ "Qi")
+ (?\ቓ "Qa")
+ (?\ቔ "QE")
+ (?\ቕ "Q")
+ (?\ቖ "Qo")
+ (?\ቘ "QWe")
+ (?\ቚ "QWi")
+ (?\ቛ "QWa")
+ (?\ቜ "QWE")
+ (?\ቝ "QW")
+ (?\በ "be")
+ (?\ቡ "bu")
+ (?\ቢ "bi")
+ (?\ባ "ba")
+ (?\ቤ "bE")
+ (?\ብ "b")
+ (?\ቦ "bo")
+ (?\ቧ "bWa")
+ (?\ቨ "ve")
+ (?\ቩ "vu")
+ (?\ቪ "vi")
+ (?\ቫ "va")
+ (?\ቬ "vE")
+ (?\ቭ "v")
+ (?\ቮ "vo")
+ (?\ቯ "vWa")
+ (?\ተ "te")
+ (?\ቱ "tu")
+ (?\ቲ "ti")
+ (?\ታ "ta")
+ (?\ቴ "tE")
+ (?\ት "t")
+ (?\ቶ "to")
+ (?\ቷ "tWa")
+ (?\ቸ "ce")
+ (?\ቹ "cu")
+ (?\ቺ "ci")
+ (?\ቻ "ca")
+ (?\ቼ "cE")
+ (?\ች "c")
+ (?\ቾ "co")
+ (?\ቿ "cWa")
+ (?\ኀ "`he")
+ (?\ኁ "`hu")
+ (?\ኂ "`hi")
+ (?\ኃ "`ha")
+ (?\ኄ "`hE")
+ (?\ኅ "`h")
+ (?\ኆ "`ho")
+ (?\ኈ "hWe")
+ (?\ኊ "hWi")
+ (?\ኋ "hWa")
+ (?\ኌ "hWE")
+ (?\ኍ "hW")
+ (?\ነ "na")
+ (?\ኑ "nu")
+ (?\ኒ "ni")
+ (?\ና "na")
+ (?\ኔ "nE")
+ (?\ን "n")
+ (?\ኖ "no")
+ (?\ኗ "nWa")
+ (?\ኘ "Ne")
+ (?\ኙ "Nu")
+ (?\ኚ "Ni")
+ (?\ኛ "Na")
+ (?\ኜ "NE")
+ (?\ኝ "N")
+ (?\ኞ "No")
+ (?\ኟ "NWa")
+ (?\አ "e")
+ (?\ኡ "u")
+ (?\ኢ "i")
+ (?\ኣ "a")
+ (?\ኤ "E")
+ (?\እ "I")
+ (?\ኦ "o")
+ (?\ኧ "e3")
+ (?\ከ "ke")
+ (?\ኩ "ku")
+ (?\ኪ "ki")
+ (?\ካ "ka")
+ (?\ኬ "kE")
+ (?\ክ "k")
+ (?\ኮ "ko")
+ (?\ኰ "kWe")
+ (?\ኲ "kWi")
+ (?\ኳ "kWa")
+ (?\ኴ "kWE")
+ (?\ኵ "kW")
+ (?\ኸ "Ke")
+ (?\ኹ "Ku")
+ (?\ኺ "Ki")
+ (?\ኻ "Ka")
+ (?\ኼ "KE")
+ (?\ኽ "K")
+ (?\ኾ "Ko")
+ (?\ዀ "KWe")
+ (?\ዂ "KWi")
+ (?\ዃ "KWa")
+ (?\ዄ "KWE")
+ (?\ዅ "KW")
+ (?\ወ "we")
+ (?\ዉ "wu")
+ (?\ዊ "wi")
+ (?\ዋ "wa")
+ (?\ዌ "wE")
+ (?\ው "w")
+ (?\ዎ "wo")
+ (?\ዐ "`e")
+ (?\ዑ "`u")
+ (?\ዒ "`i")
+ (?\ዓ "`a")
+ (?\ዔ "`E")
+ (?\ዕ "`I")
+ (?\ዖ "`o")
+ (?\ዘ "ze")
+ (?\ዙ "zu")
+ (?\ዚ "zi")
+ (?\ዛ "za")
+ (?\ዜ "zE")
+ (?\ዝ "z")
+ (?\ዞ "zo")
+ (?\ዟ "zWa")
+ (?\ዠ "Ze")
+ (?\ዡ "Zu")
+ (?\ዢ "Zi")
+ (?\ዣ "Za")
+ (?\ዤ "ZE")
+ (?\ዥ "Z")
+ (?\ዦ "Zo")
+ (?\ዧ "ZWa")
+ (?\የ "ye")
+ (?\ዩ "yu")
+ (?\ዪ "yi")
+ (?\ያ "ya")
+ (?\ዬ "yE")
+ (?\ይ "y")
+ (?\ዮ "yo")
+ (?\ዯ "yWa")
+ (?\ደ "de")
+ (?\ዱ "du")
+ (?\ዲ "di")
+ (?\ዳ "da")
+ (?\ዴ "dE")
+ (?\ድ "d")
+ (?\ዶ "do")
+ (?\ዷ "dWa")
+ (?\ዸ "De")
+ (?\ዹ "Du")
+ (?\ዺ "Di")
+ (?\ዻ "Da")
+ (?\ዼ "DE")
+ (?\ዽ "D")
+ (?\ዾ "Do")
+ (?\ዿ "DWa")
+ (?\ጀ "je")
+ (?\ጁ "ju")
+ (?\ጂ "ji")
+ (?\ጃ "ja")
+ (?\ጄ "jE")
+ (?\ጅ "j")
+ (?\ጆ "jo")
+ (?\ጇ "jWa")
+ (?\ገ "ga")
+ (?\ጉ "gu")
+ (?\ጊ "gi")
+ (?\ጋ "ga")
+ (?\ጌ "gE")
+ (?\ግ "g")
+ (?\ጎ "go")
+ (?\ጐ "gWu")
+ (?\ጒ "gWi")
+ (?\ጓ "gWa")
+ (?\ጔ "gWE")
+ (?\ጕ "gW")
+ (?\ጘ "Ge")
+ (?\ጙ "Gu")
+ (?\ጚ "Gi")
+ (?\ጛ "Ga")
+ (?\ጜ "GE")
+ (?\ጝ "G")
+ (?\ጞ "Go")
+ (?\ጟ "GWa")
+ (?\ጠ "Te")
+ (?\ጡ "Tu")
+ (?\ጢ "Ti")
+ (?\ጣ "Ta")
+ (?\ጤ "TE")
+ (?\ጥ "T")
+ (?\ጦ "To")
+ (?\ጧ "TWa")
+ (?\ጨ "Ce")
+ (?\ጩ "Ca")
+ (?\ጪ "Cu")
+ (?\ጫ "Ca")
+ (?\ጬ "CE")
+ (?\ጭ "C")
+ (?\ጮ "Co")
+ (?\ጯ "CWa")
+ (?\ጰ "Pe")
+ (?\ጱ "Pu")
+ (?\ጲ "Pi")
+ (?\ጳ "Pa")
+ (?\ጴ "PE")
+ (?\ጵ "P")
+ (?\ጶ "Po")
+ (?\ጷ "PWa")
+ (?\ጸ "SWe")
+ (?\ጹ "SWu")
+ (?\ጺ "SWi")
+ (?\ጻ "SWa")
+ (?\ጼ "SWE")
+ (?\ጽ "SW")
+ (?\ጾ "SWo")
+ (?\ጿ "SWa")
+ (?\ፀ "`Sa")
+ (?\ፁ "`Su")
+ (?\ፂ "`Si")
+ (?\ፃ "`Sa")
+ (?\ፄ "`SE")
+ (?\ፅ "`S")
+ (?\ፆ "`So")
+ (?\ፈ "fa")
+ (?\ፉ "fu")
+ (?\ፊ "fi")
+ (?\ፋ "fa")
+ (?\ፌ "fE")
+ (?\ፍ "o")
+ (?\ፎ "fo")
+ (?\ፏ "fWa")
+ (?\ፐ "pe")
+ (?\ፑ "pu")
+ (?\ፒ "pi")
+ (?\ፓ "pa")
+ (?\ፔ "pE")
+ (?\ፕ "p")
+ (?\ፖ "po")
+ (?\ፗ "pWa")
+ (?\ፘ "mYa")
+ (?\ፙ "rYa")
+ (?\ፚ "fYa")
+ (?\፠ " ")
+ (?\፡ ":")
+ (?\። "::")
+ (?\፣ ",")
+ (?\፤ ";")
+ (?\፥ "-:")
+ (?\፦ ":-")
+ (?\፧ "`?")
+ (?\፨ ":|:")
+ (?\፩ "`1")
+ (?\፪ "`2")
+ (?\፫ "`3")
+ (?\፬ "`4")
+ (?\፭ "`5")
+ (?\፮ "`6")
+ (?\፯ "`7")
+ (?\፰ "`8")
+ (?\፱ "`9")
+ (?\፲ "`10")
+ (?\፳ "`20")
+ (?\፴ "`30")
+ (?\፵ "`40")
+ (?\፶ "`50")
+ (?\፷ "`60")
+ (?\፸ "`70")
+ (?\፹ "`80")
+ (?\፺ "`90")
+ (?\፻ "`100")
+ (?\፼ "`10000")
+ (?\Ḁ "A-0")
+ (?\ḁ "a-0")
+ (?\Ḃ "B.")
+ (?\ḃ "b.")
+ (?\Ḅ "B-.")
+ (?\ḅ "b-.")
+ (?\Ḇ "B_")
+ (?\ḇ "b_")
+ (?\Ḉ "C,'")
+ (?\ḉ "c,'")
+ (?\Ḋ "D.")
+ (?\ḋ "d.")
+ (?\Ḍ "D-.")
+ (?\ḍ "d-.")
+ (?\Ḏ "D_")
+ (?\ḏ "d_")
+ (?\Ḑ "D,")
+ (?\ḑ "d,")
+ (?\Ḓ "D->")
+ (?\ḓ "d->")
+ (?\Ḕ "E-!")
+ (?\ḕ "e-!")
+ (?\Ḗ "E-'")
+ (?\ḗ "e-'")
+ (?\Ḙ "E->")
+ (?\ḙ "e->")
+ (?\Ḛ "E-?")
+ (?\ḛ "e-?")
+ (?\Ḝ "E,(")
+ (?\ḝ "e,(")
+ (?\Ḟ "F.")
+ (?\ḟ "f.")
+ (?\Ḡ "G-")
+ (?\ḡ "g-")
+ (?\Ḣ "H.")
+ (?\ḣ "h.")
+ (?\Ḥ "H-.")
+ (?\ḥ "h-.")
+ (?\Ḧ "H:")
+ (?\ḧ "h:")
+ (?\Ḩ "H,")
+ (?\ḩ "h,")
+ (?\Ḫ "H-(")
+ (?\ḫ "h-(")
+ (?\Ḭ "I-?")
+ (?\ḭ "i-?")
+ (?\Ḯ "I:'")
+ (?\ḯ "i:'")
+ (?\Ḱ "K'")
+ (?\ḱ "k'")
+ (?\Ḳ "K-.")
+ (?\ḳ "k-.")
+ (?\Ḵ "K_")
+ (?\ḵ "k_")
+ (?\Ḷ "L-.")
+ (?\ḷ "l-.")
+ (?\Ḹ "L--.")
+ (?\ḹ "l--.")
+ (?\Ḻ "L_")
+ (?\ḻ "l_")
+ (?\Ḽ "L->")
+ (?\ḽ "l->")
+ (?\Ḿ "M'")
+ (?\ḿ "m'")
+ (?\Ṁ "M.")
+ (?\ṁ "m.")
+ (?\Ṃ "M-.")
+ (?\ṃ "m-.")
+ (?\Ṅ "N.")
+ (?\ṅ "n.")
+ (?\Ṇ "N-.")
+ (?\ṇ "n-.")
+ (?\Ṉ "N_")
+ (?\ṉ "n_")
+ (?\Ṋ "N->")
+ (?\ṋ "n->")
+ (?\Ṍ "O?'")
+ (?\ṍ "o?'")
+ (?\Ṏ "O?:")
+ (?\ṏ "o?:")
+ (?\Ṑ "O-!")
+ (?\ṑ "o-!")
+ (?\Ṓ "O-'")
+ (?\ṓ "o-'")
+ (?\Ṕ "P'")
+ (?\ṕ "p'")
+ (?\Ṗ "P.")
+ (?\ṗ "p.")
+ (?\Ṙ "R.")
+ (?\ṙ "r.")
+ (?\Ṛ "R-.")
+ (?\ṛ "r-.")
+ (?\Ṝ "R--.")
+ (?\ṝ "r--.")
+ (?\Ṟ "R_")
+ (?\ṟ "r_")
+ (?\Ṡ "S.")
+ (?\ṡ "s.")
+ (?\Ṣ "S-.")
+ (?\ṣ "s-.")
+ (?\Ṥ "S'.")
+ (?\ṥ "s'.")
+ (?\Ṧ "S<.")
+ (?\ṧ "s<.")
+ (?\Ṩ "S.-.")
+ (?\ṩ "s.-.")
+ (?\Ṫ "T.")
+ (?\ṫ "t.")
+ (?\Ṭ "T-.")
+ (?\ṭ "t-.")
+ (?\Ṯ "T_")
+ (?\ṯ "t_")
+ (?\Ṱ "T->")
+ (?\ṱ "t->")
+ (?\Ṳ "U--:")
+ (?\ṳ "u--:")
+ (?\Ṵ "U-?")
+ (?\ṵ "u-?")
+ (?\Ṷ "U->")
+ (?\ṷ "u->")
+ (?\Ṹ "U?'")
+ (?\ṹ "u?'")
+ (?\Ṻ "U-:")
+ (?\ṻ "u-:")
+ (?\Ṽ "V?")
+ (?\ṽ "v?")
+ (?\Ṿ "V-.")
+ (?\ṿ "v-.")
+ (?\Ẁ "W!")
+ (?\ẁ "w!")
+ (?\Ẃ "W'")
+ (?\ẃ "w'")
+ (?\Ẅ "W:")
+ (?\ẅ "w:")
+ (?\Ẇ "W.")
+ (?\ẇ "w.")
+ (?\Ẉ "W-.")
+ (?\ẉ "w-.")
+ (?\Ẋ "X.")
+ (?\ẋ "x.")
+ (?\Ẍ "X:")
+ (?\ẍ "x:")
+ (?\Ẏ "Y.")
+ (?\ẏ "y.")
+ (?\Ẑ "Z>")
+ (?\ẑ "z>")
+ (?\Ẓ "Z-.")
+ (?\ẓ "z-.")
+ (?\Ẕ "Z_")
+ (?\ẕ "z_")
+ (?\ẖ "h_")
+ (?\ẗ "t:")
+ (?\ẘ "w0")
+ (?\ẙ "y0")
+ (?\Ạ "A-.")
+ (?\ạ "a-.")
+ (?\Ả "A2")
+ (?\ả "a2")
+ (?\Ấ "A>'")
+ (?\ấ "a>'")
+ (?\Ầ "A>!")
+ (?\ầ "a>!")
+ (?\Ẩ "A>2")
+ (?\ẩ "a>2")
+ (?\Ẫ "A>?")
+ (?\ẫ "a>?")
+ (?\Ậ "A>-.")
+ (?\ậ "a>-.")
+ (?\Ắ "A('")
+ (?\ắ "a('")
+ (?\Ằ "A(!")
+ (?\ằ "a(!")
+ (?\Ẳ "A(2")
+ (?\ẳ "a(2")
+ (?\Ẵ "A(?")
+ (?\ẵ "a(?")
+ (?\Ặ "A(-.")
+ (?\ặ "a(-.")
+ (?\Ẹ "E-.")
+ (?\ẹ "e-.")
+ (?\Ẻ "E2")
+ (?\ẻ "e2")
+ (?\Ẽ "E?")
+ (?\ẽ "e?")
+ (?\Ế "E>'")
+ (?\ế "e>'")
+ (?\Ề "E>!")
+ (?\ề "e>!")
+ (?\Ể "E>2")
+ (?\ể "e>2")
+ (?\Ễ "E>?")
+ (?\ễ "e>?")
+ (?\Ệ "E>-.")
+ (?\ệ "e>-.")
+ (?\Ỉ "I2")
+ (?\ỉ "i2")
+ (?\Ị "I-.")
+ (?\ị "i-.")
+ (?\Ọ "O-.")
+ (?\ọ "o-.")
+ (?\Ỏ "O2")
+ (?\ỏ "o2")
+ (?\Ố "O>'")
+ (?\ố "o>'")
+ (?\Ồ "O>!")
+ (?\ồ "o>!")
+ (?\Ổ "O>2")
+ (?\ổ "o>2")
+ (?\Ỗ "O>?")
+ (?\ỗ "o>?")
+ (?\Ộ "O>-.")
+ (?\ộ "o>-.")
+ (?\Ớ "O9'")
+ (?\ớ "o9'")
+ (?\Ờ "O9!")
+ (?\ờ "o9!")
+ (?\Ở "O92")
+ (?\ở "o92")
+ (?\Ỡ "O9?")
+ (?\ỡ "o9?")
+ (?\Ợ "O9-.")
+ (?\ợ "o9-.")
+ (?\Ụ "U-.")
+ (?\ụ "u-.")
+ (?\Ủ "U2")
+ (?\ủ "u2")
+ (?\Ứ "U9'")
+ (?\ứ "u9'")
+ (?\Ừ "U9!")
+ (?\ừ "u9!")
+ (?\Ử "U92")
+ (?\ử "u92")
+ (?\Ữ "U9?")
+ (?\ữ "u9?")
+ (?\Ự "U9-.")
+ (?\ự "u9-.")
+ (?\Ỳ "Y!")
+ (?\ỳ "y!")
+ (?\Ỵ "Y-.")
+ (?\ỵ "y-.")
+ (?\Ỷ "Y2")
+ (?\ỷ "y2")
+ (?\Ỹ "Y?")
+ (?\ỹ "y?")
+ (?\ἀ "a")
+ (?\ἁ "ha")
+ (?\ἂ "`a")
+ (?\ἃ "h`a")
+ (?\ἄ "a'")
+ (?\ἅ "ha'")
+ (?\ἆ "a~")
+ (?\ἇ "ha~")
+ (?\Ἀ "A")
+ (?\Ἁ "hA")
+ (?\Ἂ "`A")
+ (?\Ἃ "h`A")
+ (?\Ἄ "A'")
+ (?\Ἅ "hA'")
+ (?\Ἆ "A~")
+ (?\Ἇ "hA~")
+ (?\ἑ "he")
+ (?\Ἑ "hE")
+ (?\ἱ "hi")
+ (?\Ἱ "hI")
+ (?\ὁ "ho")
+ (?\Ὁ "hO")
+ (?\ὑ "hu")
+ (?\Ὑ "hU")
+ (?\᾿ ",,")
+ (?\῀ "?*")
+ (?\῁ "?:")
+ (?\῍ ",!")
+ (?\῎ ",'")
+ (?\῏ "?,")
+ (?\῝ ";!")
+ (?\῞ ";'")
+ (?\῟ "?;")
+ (?\ῥ "rh")
+ (?\Ῥ "Rh")
+ (?\῭ "!:")
+ (?\` "!*")
+ (?\῾ ";;")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\  " ")
+ (?\‐ "-")
+ (?\‑ "-")
+ (?\– "-")
+ (?\— "--")
+ (?\― "-")
+ (?\‖ "||")
+ (?\‗ "=2")
+ (?\‘ "`")
+ (?\’ "'")
+ (?\‚ "'")
+ (?\‛ "'")
+ (?\“ "\"")
+ (?\” "\"")
+ (?\„ "\"")
+ (?\‟ "\"")
+ (?\† "/-")
+ (?\‡ "/=")
+ (?\• " o ")
+ (?\․ ".")
+ (?\‥ "..")
+ (?\… "...")
+ (?\‧ "·")
+ (?\‰ " 0/00")
+ (?\′ "'")
+ (?\″ "''")
+ (?\‴ "'''")
+ (?\‵ "`")
+ (?\‶ "``")
+ (?\‷ "```")
+ (?\‸ "Ca")
+ (?\‹ "<")
+ (?\› ">")
+ (?\※ ":X")
+ (?\‼ "!!")
+ (?\‾ "'-")
+ (?\⁃ "-")
+ (?\⁄ "/")
+ (?\⁈ "?!")
+ (?\⁉ "!?")
+ (?\⁰ "^0")
+ (?\⁴ "^4")
+ (?\⁵ "^5")
+ (?\⁶ "^6")
+ (?\⁷ "^7")
+ (?\⁸ "^8")
+ (?\⁹ "^9")
+ (?\⁺ "^+")
+ (?\⁻ "^-")
+ (?\⁼ "^=")
+ (?\⁽ "^(")
+ (?\⁾ "^)")
+ (?\ⁿ "^n")
+ (?\₀ "_0")
+ (?\₁ "_1")
+ (?\₂ "_2")
+ (?\₃ "_3")
+ (?\₄ "_4")
+ (?\₅ "_5")
+ (?\₆ "_6")
+ (?\₇ "_7")
+ (?\₈ "_8")
+ (?\₉ "_9")
+ (?\₊ "_+")
+ (?\₋ "_-")
+ (?\₌ "_=")
+ (?\₍ "(")
+ (?\₎ ")")
+ (?\₣ "Ff")
+ (?\₤ "Li")
+ (?\₧ "Pt")
+ (?\₩ "W=")
+ (?\€ "EUR")
+ (?\℀ "a/c")
+ (?\℁ "a/s")
+ (?\℃ "oC")
+ (?\℅ "c/o")
+ (?\℆ "c/u")
+ (?\℉ "oF")
+ (?\ℊ "g")
+ (?\ℎ "h")
+ (?\ℏ "\\hbar")
+ (?\ℑ "Im")
+ (?\ℓ "l")
+ (?\№ "No.")
+ (?\℗ "PO")
+ (?\℘ "P")
+ (?\ℜ "Re")
+ (?\℞ "Rx")
+ (?\℠ "(SM)")
+ (?\℡ "TEL")
+ (?\™ "(TM)")
+ (?\Ω "Ohm")
+ (?\K "K")
+ (?\Å "Ang.")
+ (?\℮ "est.")
+ (?\ℴ "o")
+ (?\ℵ "Aleph ")
+ (?\ℶ "Bet ")
+ (?\ℷ "Gimel ")
+ (?\ℸ "Dalet ")
+ (?\⅓ " 1/3")
+ (?\⅔ " 2/3")
+ (?\⅕ " 1/5")
+ (?\⅖ " 2/5")
+ (?\⅗ " 3/5")
+ (?\⅘ " 4/5")
+ (?\⅙ " 1/6")
+ (?\⅚ " 5/6")
+ (?\⅛ " 1/8")
+ (?\⅜ " 3/8")
+ (?\⅝ " 5/8")
+ (?\⅞ " 7/8")
+ (?\⅟ " 1/")
+ (?\Ⅰ "I")
+ (?\Ⅱ "II")
+ (?\Ⅲ "III")
+ (?\Ⅳ "IV")
+ (?\Ⅴ "V")
+ (?\Ⅵ "VI")
+ (?\Ⅶ "VII")
+ (?\Ⅷ "VIII")
+ (?\Ⅸ "IX")
+ (?\Ⅹ "X")
+ (?\Ⅺ "XI")
+ (?\Ⅻ "XII")
+ (?\Ⅼ "L")
+ (?\Ⅽ "C")
+ (?\Ⅾ "D")
+ (?\Ⅿ "M")
+ (?\ⅰ "i")
+ (?\ⅱ "ii")
+ (?\ⅲ "iii")
+ (?\ⅳ "iv")
+ (?\ⅴ "v")
+ (?\ⅵ "vi")
+ (?\ⅶ "vii")
+ (?\ⅷ "viii")
+ (?\ⅸ "ix")
+ (?\ⅹ "x")
+ (?\ⅺ "xi")
+ (?\ⅻ "xii")
+ (?\ⅼ "l")
+ (?\ⅽ "c")
+ (?\ⅾ "d")
+ (?\ⅿ "m")
+ (?\ↀ "1000RCD")
+ (?\ↁ "5000R")
+ (?\ↂ "10000R")
+ (?\← "<-")
+ (?\↑ "-^")
+ (?\→ "->")
+ (?\↓ "-v")
+ (?\↔ "<->")
+ (?\↕ "UD")
+ (?\↖ "<!!")
+ (?\↗ "//>")
+ (?\↘ "!!>")
+ (?\↙ "<//")
+ (?\↨ "UD-")
+ (?\↵ "RET")
+ (?\⇀ ">V")
+ (?\⇐ "<=")
+ (?\⇑ "^^")
+ (?\⇒ "=>")
+ (?\⇓ "vv")
+ (?\⇔ "<=>")
+ (?\∀ "FA")
+ (?\∂ "\\partial")
+ (?\∃ "TE")
+ (?\∅ "{}")
+ (?\∆ "Delta")
+ (?\∇ "Nabla")
+ (?\∈ "(-")
+ (?\∉ "!(-")
+ (?\∊ "(-")
+ (?\∋ "-)")
+ (?\∌ "!-)")
+ (?\∍ "-)")
+ (?\∎ " qed")
+ (?\∏ "\\prod")
+ (?\∑ "\\sum")
+ (?\− " -")
+ (?\∓ "-/+")
+ (?\∔ ".+")
+ (?\∕ "/")
+ (?\∖ " - ")
+ (?\∗ "*")
+ (?\∘ " ° ")
+ (?\∙ "sb")
+ (?\√ " SQRT ")
+ (?\∛ " ROOT³ ")
+ (?\∜ " ROOT4 ")
+ (?\∝ "0(")
+ (?\∞ "infty")
+ (?\∟ "-L")
+ (?\∠ "-V")
+ (?\∥ "PP")
+ (?\∦ " !PP ")
+ (?\∧ "AND")
+ (?\∨ "OR")
+ (?\∩ "(U")
+ (?\∪ ")U")
+ (?\∫ "\\int ")
+ (?\∬ "DI")
+ (?\∮ "Io")
+ (?\∴ ".:")
+ (?\∵ ":.")
+ (?\∶ ":R")
+ (?\∷ "::")
+ (?\∼ "?1")
+ (?\∾ "CG")
+ (?\≃ "?-")
+ (?\≅ "?=")
+ (?\≈ "~=")
+ (?\≉ " !~= ")
+ (?\≌ "=?")
+ (?\≓ "HI")
+ (?\≔ ":=")
+ (?\≕ "=:")
+ (?\≠ "!=")
+ (?\≡ "=3")
+ (?\≢ " !=3 ")
+ (?\≤ "=<")
+ (?\≥ ">=")
+ (?\≦ ".LE.")
+ (?\≧ ".GE.")
+ (?\≨ ".LT.NOT.EQ.")
+ (?\≩ ".GT.NOT.EQ.")
+ (?\≪ "<<")
+ (?\≫ ">>")
+ (?\≮ "!<")
+ (?\≯ "!>")
+ (?\≶ " <> ")
+ (?\≷ " >< ")
+ (?\⊂ "(C")
+ (?\⊃ ")C")
+ (?\⊄ " !(C ")
+ (?\⊅ " !)C ")
+ (?\⊆ "(_")
+ (?\⊇ ")_")
+ (?\⊕ "(+)")
+ (?\⊖ "(-)")
+ (?\⊗ "(×)")
+ (?\⊘ "(/)")
+ (?\⊙ "(·)")
+ (?\⊚ "(°)")
+ (?\⊛ "(*)")
+ (?\⊜ "(=)")
+ (?\⊝ "(-)")
+ (?\⊞ "[+]")
+ (?\⊟ "[-]")
+ (?\⊠ "[×]")
+ (?\⊡ "[·]")
+ (?\⊥ "-T")
+ (?\⊧ " MODELS ")
+ (?\⊨ " TRUE ")
+ (?\⊩ " FORCES ")
+ (?\⊬ " !PROVES ")
+ (?\⊭ " NOT TRUE ")
+ (?\⊮ " !FORCES ")
+ (?\⊲ " NORMAL SUBGROUP OF ")
+ (?\⊳ " CONTAINS AS NORMAL SUBGROUP ")
+ (?\⊴ " NORMAL SUBGROUP OF OR EQUAL TO ")
+ (?\⊵ " CONTAINS AS NORMAL SUBGROUP OR EQUAL TO ")
+ (?\⊸ " MULTIMAP ")
+ (?\⊺ " INTERCALATE ")
+ (?\⊻ " XOR ")
+ (?\⊼ " NAND ")
+ (?\⋅ " · ")
+ (?\⋖ "<.")
+ (?\⋗ ">.")
+ (?\⋘ "<<<")
+ (?\⋙ ">>>")
+ (?\⋮ ":3")
+ (?\⋯ ".3")
+ (?\⌂ "Eh")
+ (?\⌇ "~~")
+ (?\⌈ "<7")
+ (?\⌉ ">7")
+ (?\⌊ "7<")
+ (?\⌋ "7>")
+ (?\⌐ "NI")
+ (?\⌒ "(A")
+ (?\⌕ "TR")
+ (?\⌘ "88")
+ (?\⌠ "Iu")
+ (?\⌡ "Il")
+ (?\⌢ ":(")
+ (?\⌣ ":)")
+ (?\⌤ "|^|")
+ (?\⌧ "[X]")
+ (?\〈 "</")
+ (?\〉 "/>")
+ (?\␣ "Vs")
+ (?\⑀ "1h")
+ (?\⑁ "3h")
+ (?\⑂ "2h")
+ (?\⑃ "4h")
+ (?\⑆ "1j")
+ (?\⑇ "2j")
+ (?\⑈ "3j")
+ (?\⑉ "4j")
+ (?\① "1-o")
+ (?\② "2-o")
+ (?\③ "3-o")
+ (?\④ "4-o")
+ (?\⑤ "5-o")
+ (?\⑥ "6-o")
+ (?\⑦ "7-o")
+ (?\⑧ "8-o")
+ (?\⑨ "9-o")
+ (?\⑩ "10-o")
+ (?\⑪ "11-o")
+ (?\⑫ "12-o")
+ (?\⑬ "13-o")
+ (?\⑭ "14-o")
+ (?\⑮ "15-o")
+ (?\⑯ "16-o")
+ (?\⑰ "17-o")
+ (?\⑱ "18-o")
+ (?\⑲ "19-o")
+ (?\⑳ "20-o")
+ (?\⑴ "(1)")
+ (?\⑵ "(2)")
+ (?\⑶ "(3)")
+ (?\⑷ "(4)")
+ (?\⑸ "(5)")
+ (?\⑹ "(6)")
+ (?\⑺ "(7)")
+ (?\⑻ "(8)")
+ (?\⑼ "(9)")
+ (?\⑽ "(10)")
+ (?\⑾ "(11)")
+ (?\⑿ "(12)")
+ (?\⒀ "(13)")
+ (?\⒁ "(14)")
+ (?\⒂ "(15)")
+ (?\⒃ "(16)")
+ (?\⒄ "(17)")
+ (?\⒅ "(18)")
+ (?\⒆ "(19)")
+ (?\⒇ "(20)")
+ (?\⒈ "1.")
+ (?\⒉ "2.")
+ (?\⒊ "3.")
+ (?\⒋ "4.")
+ (?\⒌ "5.")
+ (?\⒍ "6.")
+ (?\⒎ "7.")
+ (?\⒏ "8.")
+ (?\⒐ "9.")
+ (?\⒑ "10.")
+ (?\⒒ "11.")
+ (?\⒓ "12.")
+ (?\⒔ "13.")
+ (?\⒕ "14.")
+ (?\⒖ "15.")
+ (?\⒗ "16.")
+ (?\⒘ "17.")
+ (?\⒙ "18.")
+ (?\⒚ "19.")
+ (?\⒛ "20.")
+ (?\⒜ "(a)")
+ (?\⒝ "(b)")
+ (?\⒞ "(c)")
+ (?\⒟ "(d)")
+ (?\⒠ "(e)")
+ (?\⒡ "(f)")
+ (?\⒢ "(g)")
+ (?\⒣ "(h)")
+ (?\⒤ "(i)")
+ (?\⒥ "(j)")
+ (?\⒦ "(k)")
+ (?\⒧ "(l)")
+ (?\⒨ "(m)")
+ (?\⒩ "(n)")
+ (?\⒪ "(o)")
+ (?\⒫ "(p)")
+ (?\⒬ "(q)")
+ (?\⒭ "(r)")
+ (?\⒮ "(s)")
+ (?\⒯ "(t)")
+ (?\⒰ "(u)")
+ (?\⒱ "(v)")
+ (?\⒲ "(w)")
+ (?\⒳ "(x)")
+ (?\⒴ "(y)")
+ (?\⒵ "(z)")
+ (?\Ⓐ "A-o")
+ (?\Ⓑ "B-o")
+ (?\Ⓒ "C-o")
+ (?\Ⓓ "D-o")
+ (?\Ⓔ "E-o")
+ (?\Ⓕ "F-o")
+ (?\Ⓖ "G-o")
+ (?\Ⓗ "H-o")
+ (?\Ⓘ "I-o")
+ (?\Ⓙ "J-o")
+ (?\Ⓚ "K-o")
+ (?\Ⓛ "L-o")
+ (?\Ⓜ "M-o")
+ (?\Ⓝ "N-o")
+ (?\Ⓞ "O-o")
+ (?\Ⓟ "P-o")
+ (?\Ⓠ "Q-o")
+ (?\Ⓡ "R-o")
+ (?\Ⓢ "S-o")
+ (?\Ⓣ "T-o")
+ (?\Ⓤ "U-o")
+ (?\Ⓥ "V-o")
+ (?\Ⓦ "W-o")
+ (?\Ⓧ "X-o")
+ (?\Ⓨ "Y-o")
+ (?\Ⓩ "Z-o")
+ (?\ⓐ "a-o")
+ (?\ⓑ "b-o")
+ (?\ⓒ "c-o")
+ (?\ⓓ "d-o")
+ (?\ⓔ "e-o")
+ (?\ⓕ "f-o")
+ (?\ⓖ "g-o")
+ (?\ⓗ "h-o")
+ (?\ⓘ "i-o")
+ (?\ⓙ "j-o")
+ (?\ⓚ "k-o")
+ (?\ⓛ "l-o")
+ (?\ⓜ "m-o")
+ (?\ⓝ "n-o")
+ (?\ⓞ "o-o")
+ (?\ⓟ "p-o")
+ (?\ⓠ "q-o")
+ (?\ⓡ "r-o")
+ (?\ⓢ "s-o")
+ (?\ⓣ "t-o")
+ (?\ⓤ "u-o")
+ (?\ⓥ "v-o")
+ (?\ⓦ "w-o")
+ (?\ⓧ "x-o")
+ (?\ⓨ "y-o")
+ (?\ⓩ "z-o")
+ (?\⓪ "0-o")
+ (?\─ "-")
+ (?\━ "=")
+ (?\│ "|")
+ (?\┃ "|")
+ (?\┄ "-")
+ (?\┅ "=")
+ (?\┆ "|")
+ (?\┇ "|")
+ (?\┈ "-")
+ (?\┉ "=")
+ (?\┊ "|")
+ (?\┋ "|")
+ (?\┌ "+")
+ (?\┍ "+")
+ (?\┎ "+")
+ (?\┏ "+")
+ (?\┐ "+")
+ (?\┑ "+")
+ (?\┒ "+")
+ (?\┓ "+")
+ (?\└ "+")
+ (?\┕ "+")
+ (?\┖ "+")
+ (?\┗ "+")
+ (?\┘ "+")
+ (?\┙ "+")
+ (?\┚ "+")
+ (?\┛ "+")
+ (?\├ "+")
+ (?\┝ "+")
+ (?\┞ "+")
+ (?\┟ "+")
+ (?\┠ "+")
+ (?\┡ "+")
+ (?\┢ "+")
+ (?\┣ "+")
+ (?\┤ "+")
+ (?\┥ "+")
+ (?\┦ "+")
+ (?\┧ "+")
+ (?\┨ "+")
+ (?\┩ "+")
+ (?\┪ "+")
+ (?\┫ "+")
+ (?\┬ "+")
+ (?\┭ "+")
+ (?\┮ "+")
+ (?\┯ "+")
+ (?\┰ "+")
+ (?\┱ "+")
+ (?\┲ "+")
+ (?\┳ "+")
+ (?\┴ "+")
+ (?\┵ "+")
+ (?\┶ "+")
+ (?\┷ "+")
+ (?\┸ "+")
+ (?\┹ "+")
+ (?\┺ "+")
+ (?\┻ "+")
+ (?\┼ "+")
+ (?\┽ "+")
+ (?\┾ "+")
+ (?\┿ "+")
+ (?\╀ "+")
+ (?\╁ "+")
+ (?\╂ "+")
+ (?\╃ "+")
+ (?\╄ "+")
+ (?\╅ "+")
+ (?\╆ "+")
+ (?\╇ "+")
+ (?\╈ "+")
+ (?\╉ "+")
+ (?\╊ "+")
+ (?\╋ "+")
+ (?\╌ "+")
+ (?\╍ "+")
+ (?\╎ "+")
+ (?\╏ "+")
+ (?\═ "+")
+ (?\║ "+")
+ (?\╒ "+")
+ (?\╓ "+")
+ (?\╔ "+")
+ (?\╕ "+")
+ (?\╖ "+")
+ (?\╗ "+")
+ (?\╘ "+")
+ (?\╙ "+")
+ (?\╚ "+")
+ (?\╛ "+")
+ (?\╜ "+")
+ (?\╝ "+")
+ (?\╞ "+")
+ (?\╟ "+")
+ (?\╠ "+")
+ (?\╡ "+")
+ (?\╢ "+")
+ (?\╣ "+")
+ (?\╤ "+")
+ (?\╥ "+")
+ (?\╦ "+")
+ (?\╧ "+")
+ (?\╨ "+")
+ (?\╩ "+")
+ (?\╪ "+")
+ (?\╫ "+")
+ (?\╬ "+")
+ (?\╱ "/")
+ (?\╲ "\\")
+ (?\▀ "TB")
+ (?\▄ "LB")
+ (?\█ "FB")
+ (?\▌ "lB")
+ (?\▐ "RB")
+ (?\░ ".S")
+ (?\▒ ":S")
+ (?\▓ "?S")
+ (?\■ "fS")
+ (?\□ "OS")
+ (?\▢ "RO")
+ (?\▣ "Rr")
+ (?\▤ "RF")
+ (?\▥ "RY")
+ (?\▦ "RH")
+ (?\▧ "RZ")
+ (?\▨ "RK")
+ (?\▩ "RX")
+ (?\▪ "sB")
+ (?\▬ "SR")
+ (?\▭ "Or")
+ (?\▲ "^")
+ (?\△ "uT")
+ (?\▶ "|>")
+ (?\▷ "Tr")
+ (?\► "|>")
+ (?\▼ "v")
+ (?\▽ "dT")
+ (?\◀ "<|")
+ (?\◁ "Tl")
+ (?\◄ "<|")
+ (?\◆ "Db")
+ (?\◇ "Dw")
+ (?\◊ "LZ")
+ (?\○ "0m")
+ (?\◎ "0o")
+ (?\● "0M")
+ (?\◐ "0L")
+ (?\◑ "0R")
+ (?\◘ "Sn")
+ (?\◙ "Ic")
+ (?\◢ "Fd")
+ (?\◣ "Bd")
+ (?\◯ "Ci")
+ (?\★ "*2")
+ (?\☆ "*1")
+ (?\☎ "TEL")
+ (?\☏ "tel")
+ (?\☜ "<--")
+ (?\☞ "-->")
+ (?\☡ "CAUTION ")
+ (?\☧ "XP")
+ (?\☹ ":-(")
+ (?\☺ ":-)")
+ (?\☻ "(-:")
+ (?\☼ "SU")
+ (?\♀ "f.")
+ (?\♂ "m.")
+ (?\♠ "cS")
+ (?\♡ "cH")
+ (?\♢ "cD")
+ (?\♣ "cC")
+ (?\♤ "cS-")
+ (?\♥ "cH-")
+ (?\♦ "cD-")
+ (?\♧ "cC-")
+ (?\♩ "Md")
+ (?\♪ "M8")
+ (?\♫ "M2")
+ (?\♬ "M16")
+ (?\♭ "b")
+ (?\♮ "Mx")
+ (?\♯ "#")
+ (?\✓ "X")
+ (?\✗ "X")
+ (?\✠ "-X")
+ (?\  " ")
+ (?\、 ",_")
+ (?\。 "._")
+ (?\〃 "+\"")
+ (?\〄 "JIS")
+ (?\々 "*_")
+ (?\〆 ";_")
+ (?\〇 "0_")
+ (?\《 "<+")
+ (?\》 ">+")
+ (?\「 "<'")
+ (?\」 ">'")
+ (?\『 "<\"")
+ (?\』 ">\"")
+ (?\【 "(\"")
+ (?\】 ")\"")
+ (?\〒 "=T")
+ (?\〓 "=_")
+ (?\〔 "('")
+ (?\〕 ")'")
+ (?\〖 "(I")
+ (?\〗 ")I")
+ (?\〚 "[[")
+ (?\〛 "]]")
+ (?\〜 "-?")
+ (?\〠 "=T:)")
+ (?\〿 " ")
+ (?\ぁ "A5")
+ (?\あ "a5")
+ (?\ぃ "I5")
+ (?\い "i5")
+ (?\ぅ "U5")
+ (?\う "u5")
+ (?\ぇ "E5")
+ (?\え "e5")
+ (?\ぉ "O5")
+ (?\お "o5")
+ (?\か "ka")
+ (?\が "ga")
+ (?\き "ki")
+ (?\ぎ "gi")
+ (?\く "ku")
+ (?\ぐ "gu")
+ (?\け "ke")
+ (?\げ "ge")
+ (?\こ "ko")
+ (?\ご "go")
+ (?\さ "sa")
+ (?\ざ "za")
+ (?\し "si")
+ (?\じ "zi")
+ (?\す "su")
+ (?\ず "zu")
+ (?\せ "se")
+ (?\ぜ "ze")
+ (?\そ "so")
+ (?\ぞ "zo")
+ (?\た "ta")
+ (?\だ "da")
+ (?\ち "ti")
+ (?\ぢ "di")
+ (?\っ "tU")
+ (?\つ "tu")
+ (?\づ "du")
+ (?\て "te")
+ (?\で "de")
+ (?\と "to")
+ (?\ど "do")
+ (?\な "na")
+ (?\に "ni")
+ (?\ぬ "nu")
+ (?\ね "ne")
+ (?\の "no")
+ (?\は "ha")
+ (?\ば "ba")
+ (?\ぱ "pa")
+ (?\ひ "hi")
+ (?\び "bi")
+ (?\ぴ "pi")
+ (?\ふ "hu")
+ (?\ぶ "bu")
+ (?\ぷ "pu")
+ (?\へ "he")
+ (?\べ "be")
+ (?\ぺ "pe")
+ (?\ほ "ho")
+ (?\ぼ "bo")
+ (?\ぽ "po")
+ (?\ま "ma")
+ (?\み "mi")
+ (?\む "mu")
+ (?\め "me")
+ (?\も "mo")
+ (?\ゃ "yA")
+ (?\や "ya")
+ (?\ゅ "yU")
+ (?\ゆ "yu")
+ (?\ょ "yO")
+ (?\よ "yo")
+ (?\ら "ra")
+ (?\り "ri")
+ (?\る "ru")
+ (?\れ "re")
+ (?\ろ "ro")
+ (?\ゎ "wA")
+ (?\わ "wa")
+ (?\ゐ "wi")
+ (?\ゑ "we")
+ (?\を "wo")
+ (?\ん "n5")
+ (?\ゔ "vu")
+ (?\゛ "\"5")
+ (?\゜ "05")
+ (?\ゝ "*5")
+ (?\ゞ "+5")
+ (?\ァ "a6")
+ (?\ア "A6")
+ (?\ィ "i6")
+ (?\イ "I6")
+ (?\ゥ "u6")
+ (?\ウ "U6")
+ (?\ェ "e6")
+ (?\エ "E6")
+ (?\ォ "o6")
+ (?\オ "O6")
+ (?\カ "Ka")
+ (?\ガ "Ga")
+ (?\キ "Ki")
+ (?\ギ "Gi")
+ (?\ク "Ku")
+ (?\グ "Gu")
+ (?\ケ "Ke")
+ (?\ゲ "Ge")
+ (?\コ "Ko")
+ (?\ゴ "Go")
+ (?\サ "Sa")
+ (?\ザ "Za")
+ (?\シ "Si")
+ (?\ジ "Zi")
+ (?\ス "Su")
+ (?\ズ "Zu")
+ (?\セ "Se")
+ (?\ゼ "Ze")
+ (?\ソ "So")
+ (?\ゾ "Zo")
+ (?\タ "Ta")
+ (?\ダ "Da")
+ (?\チ "Ti")
+ (?\ヂ "Di")
+ (?\ッ "TU")
+ (?\ツ "Tu")
+ (?\ヅ "Du")
+ (?\テ "Te")
+ (?\デ "De")
+ (?\ト "To")
+ (?\ド "Do")
+ (?\ナ "Na")
+ (?\ニ "Ni")
+ (?\ヌ "Nu")
+ (?\ネ "Ne")
+ (?\ノ "No")
+ (?\ハ "Ha")
+ (?\バ "Ba")
+ (?\パ "Pa")
+ (?\ヒ "Hi")
+ (?\ビ "Bi")
+ (?\ピ "Pi")
+ (?\フ "Hu")
+ (?\ブ "Bu")
+ (?\プ "Pu")
+ (?\ヘ "He")
+ (?\ベ "Be")
+ (?\ペ "Pe")
+ (?\ホ "Ho")
+ (?\ボ "Bo")
+ (?\ポ "Po")
+ (?\マ "Ma")
+ (?\ミ "Mi")
+ (?\ム "Mu")
+ (?\メ "Me")
+ (?\モ "Mo")
+ (?\ャ "YA")
+ (?\ヤ "Ya")
+ (?\ュ "YU")
+ (?\ユ "Yu")
+ (?\ョ "YO")
+ (?\ヨ "Yo")
+ (?\ラ "Ra")
+ (?\リ "Ri")
+ (?\ル "Ru")
+ (?\レ "Re")
+ (?\ロ "Ro")
+ (?\ヮ "WA")
+ (?\ワ "Wa")
+ (?\ヰ "Wi")
+ (?\ヱ "We")
+ (?\ヲ "Wo")
+ (?\ン "N6")
+ (?\ヴ "Vu")
+ (?\ヵ "KA")
+ (?\ヶ "KE")
+ (?\ヷ "Va")
+ (?\ヸ "Vi")
+ (?\ヹ "Ve")
+ (?\ヺ "Vo")
+ (?\・ ".6")
+ (?\ー "-6")
+ (?\ヽ "*6")
+ (?\ヾ "+6")
+ (?\ㄅ "b4")
+ (?\ㄆ "p4")
+ (?\ㄇ "m4")
+ (?\ㄈ "f4")
+ (?\ㄉ "d4")
+ (?\ㄊ "t4")
+ (?\ㄋ "n4")
+ (?\ㄌ "l4")
+ (?\ㄍ "g4")
+ (?\ㄎ "k4")
+ (?\ㄏ "h4")
+ (?\ㄐ "j4")
+ (?\ㄑ "q4")
+ (?\ㄒ "x4")
+ (?\ㄓ "zh")
+ (?\ㄔ "ch")
+ (?\ㄕ "sh")
+ (?\ㄖ "r4")
+ (?\ㄗ "z4")
+ (?\ㄘ "c4")
+ (?\ㄙ "s4")
+ (?\ㄚ "a4")
+ (?\ㄛ "o4")
+ (?\ㄜ "e4")
+ (?\ㄝ "eh4")
+ (?\ㄞ "ai")
+ (?\ㄟ "ei")
+ (?\ㄠ "au")
+ (?\ㄡ "ou")
+ (?\ㄢ "an")
+ (?\ㄣ "en")
+ (?\ㄤ "aN")
+ (?\ㄥ "eN")
+ (?\ㄦ "er")
+ (?\ㄧ "i4")
+ (?\ㄨ "u4")
+ (?\ㄩ "iu")
+ (?\ㄪ "v4")
+ (?\ㄫ "nG")
+ (?\ㄬ "gn")
+ (?\㈜ "(JU)")
+ (?\㈠ "1c")
+ (?\㈡ "2c")
+ (?\㈢ "3c")
+ (?\㈣ "4c")
+ (?\㈤ "5c")
+ (?\㈥ "6c")
+ (?\㈦ "7c")
+ (?\㈧ "8c")
+ (?\㈨ "9c")
+ (?\㈩ "10c")
+ (?\㉿ "KSC")
+ (?\㏂ "am")
+ (?\㏘ "pm")
+ (?\ff "ff")
+ (?\fi "fi")
+ (?\fl "fl")
+ (?\ffi "ffi")
+ (?\ffl "ffl")
+ (?\ſt "St")
+ (?\st "st")
+ (?\ﹽ "3+;")
+ (?\ﺂ "aM.")
+ (?\ﺄ "aH.")
+ (?\ﺈ "ah.")
+ (?\ﺍ "a+-")
+ (?\ﺎ "a+.")
+ (?\ﺏ "b+-")
+ (?\ﺐ "b+.")
+ (?\ﺑ "b+,")
+ (?\ﺒ "b+;")
+ (?\ﺓ "tm-")
+ (?\ﺔ "tm.")
+ (?\ﺕ "t+-")
+ (?\ﺖ "t+.")
+ (?\ﺗ "t+,")
+ (?\ﺘ "t+;")
+ (?\ﺙ "tk-")
+ (?\ﺚ "tk.")
+ (?\ﺛ "tk,")
+ (?\ﺜ "tk;")
+ (?\ﺝ "g+-")
+ (?\ﺞ "g+.")
+ (?\ﺟ "g+,")
+ (?\ﺠ "g+;")
+ (?\ﺡ "hk-")
+ (?\ﺢ "hk.")
+ (?\ﺣ "hk,")
+ (?\ﺤ "hk;")
+ (?\ﺥ "x+-")
+ (?\ﺦ "x+.")
+ (?\ﺧ "x+,")
+ (?\ﺨ "x+;")
+ (?\ﺩ "d+-")
+ (?\ﺪ "d+.")
+ (?\ﺫ "dk-")
+ (?\ﺬ "dk.")
+ (?\ﺭ "r+-")
+ (?\ﺮ "r+.")
+ (?\ﺯ "z+-")
+ (?\ﺰ "z+.")
+ (?\ﺱ "s+-")
+ (?\ﺲ "s+.")
+ (?\ﺳ "s+,")
+ (?\ﺴ "s+;")
+ (?\ﺵ "sn-")
+ (?\ﺶ "sn.")
+ (?\ﺷ "sn,")
+ (?\ﺸ "sn;")
+ (?\ﺹ "c+-")
+ (?\ﺺ "c+.")
+ (?\ﺻ "c+,")
+ (?\ﺼ "c+;")
+ (?\ﺽ "dd-")
+ (?\ﺾ "dd.")
+ (?\ﺿ "dd,")
+ (?\ﻀ "dd;")
+ (?\ﻁ "tj-")
+ (?\ﻂ "tj.")
+ (?\ﻃ "tj,")
+ (?\ﻄ "tj;")
+ (?\ﻅ "zH-")
+ (?\ﻆ "zH.")
+ (?\ﻇ "zH,")
+ (?\ﻈ "zH;")
+ (?\ﻉ "e+-")
+ (?\ﻊ "e+.")
+ (?\ﻋ "e+,")
+ (?\ﻌ "e+;")
+ (?\ﻍ "i+-")
+ (?\ﻎ "i+.")
+ (?\ﻏ "i+,")
+ (?\ﻐ "i+;")
+ (?\ﻑ "f+-")
+ (?\ﻒ "f+.")
+ (?\ﻓ "f+,")
+ (?\ﻔ "f+;")
+ (?\ﻕ "q+-")
+ (?\ﻖ "q+.")
+ (?\ﻗ "q+,")
+ (?\ﻘ "q+;")
+ (?\ﻙ "k+-")
+ (?\ﻚ "k+.")
+ (?\ﻛ "k+,")
+ (?\ﻜ "k+;")
+ (?\ﻝ "l+-")
+ (?\ﻞ "l+.")
+ (?\ﻟ "l+,")
+ (?\ﻠ "l+;")
+ (?\ﻡ "m+-")
+ (?\ﻢ "m+.")
+ (?\ﻣ "m+,")
+ (?\ﻤ "m+;")
+ (?\ﻥ "n+-")
+ (?\ﻦ "n+.")
+ (?\ﻧ "n+,")
+ (?\ﻨ "n+;")
+ (?\ﻩ "h+-")
+ (?\ﻪ "h+.")
+ (?\ﻫ "h+,")
+ (?\ﻬ "h+;")
+ (?\ﻭ "w+-")
+ (?\ﻮ "w+.")
+ (?\ﻯ "j+-")
+ (?\ﻰ "j+.")
+ (?\ﻱ "y+-")
+ (?\ﻲ "y+.")
+ (?\ﻳ "y+,")
+ (?\ﻴ "y+;")
+ (?\ﻵ "lM-")
+ (?\ﻶ "lM.")
+ (?\ﻷ "lH-")
+ (?\ﻸ "lH.")
+ (?\ﻹ "lh-")
+ (?\ﻺ "lh.")
+ (?\ﻻ "la-")
+ (?\ﻼ "la.")
+ (?\! "!")
+ (?\" "\"")
+ (?\# "#")
+ (?\$ "$")
+ (?\% "%")
+ (?\& "&")
+ (?\' "'")
+ (?\( "(")
+ (?\) ")")
+ (?\* "*")
+ (?\+ "+")
+ (?\, ",")
+ (?\- "-")
+ (?\. ".")
+ (?\/ "/")
+ (?\0 "0")
+ (?\1 "1")
+ (?\2 "2")
+ (?\3 "3")
+ (?\4 "4")
+ (?\5 "5")
+ (?\6 "6")
+ (?\7 "7")
+ (?\8 "8")
+ (?\9 "9")
+ (?\: ":")
+ (?\; ";")
+ (?\< "<")
+ (?\= "=")
+ (?\> ">")
+ (?\? "?")
+ (?\@ "@")
+ (?\A "A")
+ (?\B "B")
+ (?\C "C")
+ (?\D "D")
+ (?\E "E")
+ (?\F "F")
+ (?\G "G")
+ (?\H "H")
+ (?\I "I")
+ (?\J "J")
+ (?\K "K")
+ (?\L "L")
+ (?\M "M")
+ (?\N "N")
+ (?\O "O")
+ (?\P "P")
+ (?\Q "Q")
+ (?\R "R")
+ (?\S "S")
+ (?\T "T")
+ (?\U "U")
+ (?\V "V")
+ (?\W "W")
+ (?\X "X")
+ (?\Y "Y")
+ (?\Z "Z")
+ (?\[ "[")
+ (?\\ "\\")
+ (?\] "]")
+ (?\^ "^")
+ (?\_ "_")
+ (?\` "`")
+ (?\a "a")
+ (?\b "b")
+ (?\c "c")
+ (?\d "d")
+ (?\e "e")
+ (?\f "f")
+ (?\g "g")
+ (?\h "h")
+ (?\i "i")
+ (?\j "j")
+ (?\k "k")
+ (?\l "l")
+ (?\m "m")
+ (?\n "n")
+ (?\o "o")
+ (?\p "p")
+ (?\q "q")
+ (?\r "r")
+ (?\s "s")
+ (?\t "t")
+ (?\u "u")
+ (?\v "v")
+ (?\w "w")
+ (?\x "x")
+ (?\y "y")
+ (?\z "z")
+ (?\{ "{")
+ (?\| "|")
+ (?\} "}")
+ (?\~ "~")
+ (?\。 ".")
+ (?\「 "\"")
+ (?\」 "\"")
+ (?\、 ",")
+ ;; Not from Lynx
+ (? "")
+ (?� "?"))))
(aset standard-display-table
(make-char 'mule-unicode-0100-24ff) nil)
(aset standard-display-table
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 27defef6480..48c8d2b0818 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -3257,7 +3257,9 @@ as names, not numbers."
"s" #'emoji-search
"d" #'emoji-describe
"r" #'emoji-recent
- "l" #'emoji-list))
+ "l" #'emoji-list
+ "+" #'emoji-zoom-increase
+ "-" #'emoji-zoom-decrease))
(defface confusingly-reordered
'((((supports :underline (:style wave)))
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 0758359e154..ab74c2cffd9 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -298,13 +298,21 @@ attribute."
(defvar hack-read-symbol-shorthands-function nil
"Holds function to compute `read-symbol-shorthands'.")
-(defun load-with-code-conversion (fullname file &optional noerror nomessage)
+(defun load-with-code-conversion (fullname file &optional noerror nomessage
+ eval-function)
"Execute a file of Lisp code named FILE whose absolute name is FULLNAME.
The file contents are decoded before evaluation if necessary.
-If optional third arg NOERROR is non-nil,
- report no error if FILE doesn't exist.
-Print messages at start and end of loading unless
- optional fourth arg NOMESSAGE is non-nil.
+
+If optional third arg NOERROR is non-nil, report no error if FILE
+doesn't exist.
+
+Print messages at start and end of loading unless optional fourth
+arg NOMESSAGE is non-nil.
+
+If EVAL-FUNCTION, call that instead of calling `eval-buffer'
+directly. It is called with two parameters: The buffer object
+and the file name.
+
Return t if file exists."
(if (null (file-readable-p fullname))
(and (null noerror)
@@ -353,10 +361,13 @@ Return t if file exists."
;; Have the original buffer current while we eval,
;; but consider shorthands of the eval'ed one.
(let ((read-symbol-shorthands shorthands))
- (eval-buffer buffer nil
- ;; This is compatible with what `load' does.
- (if dump-mode file fullname)
- nil t)))
+ (if eval-function
+ (funcall eval-function buffer
+ (if dump-mode file fullname))
+ (eval-buffer buffer nil
+ ;; This is compatible with what `load' does.
+ (if dump-mode file fullname)
+ nil t))))
(let (kill-buffer-hook kill-buffer-query-functions)
(kill-buffer buffer)))
(do-after-load-evaluation fullname)
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 14d4c383b23..529cf97215e 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -412,8 +412,8 @@ If it is nil, the current key is shown.
DOCSTRING is the documentation string of this package. The command
`describe-input-method' shows this string while replacing the form
-\\=\\<VAR> in the string by the value of VAR. That value should be a
-string. For instance, the form \\=\\<quail-translation-docstring> is
+\\=\\=\\=\\<VAR> in the string by the value of VAR. That value should be a
+string. For instance, the form \\=\\=\\=\\<quail-translation-docstring> is
replaced by a description about how to select a translation from a
list of candidates.
diff --git a/lisp/international/textsec-check.el b/lisp/international/textsec-check.el
new file mode 100644
index 00000000000..567ef73feb2
--- /dev/null
+++ b/lisp/international/textsec-check.el
@@ -0,0 +1,78 @@
+;;; textsec-check.el --- Check for suspicious texts -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(defgroup textsec nil
+ "Suspicious text identification."
+ :group 'security
+ :version "29.1")
+
+(defcustom textsec-check t
+ "If non-nil, perform some security-related checks on text objects.
+If nil, these checks are disabled."
+ :type 'boolean
+ :version "29.1")
+
+(defface textsec-suspicious
+ '((t (:weight bold :background "red")))
+ "Face used to highlight suspicious strings.")
+
+;;;###autoload
+(defun textsec-suspicious-p (object type)
+ "Say whether OBJECT is suspicious for use as TYPE.
+If OBJECT is suspicious, return a string explaining the reason
+for considering it suspicious, otherwise return nil.
+
+Available values of TYPE and corresponding OBJECTs are:
+
+ `url' -- a URL; OBJECT should be a URL string.
+
+ `link' -- an HTML link; OBJECT should be a cons cell
+ of the form (URL . LINK-TEXT).
+
+ `domain' -- a Web domain; OBJECT should be a string.
+
+ `local-address' -- the local part of an email address; OBJECT
+ should be a string.
+ `name' -- the \"display name\" part of an email address;
+ OBJECT should be a string.
+
+`email-address' -- a full email address; OBJECT should be a string.
+
+ `email-address-header' -- a raw email address header in RFC 2822 format;
+ OBJECT should be a string.
+
+If the user option `textsec-check' is nil, these checks are
+disabled, and this function always returns nil."
+ (if (not textsec-check)
+ nil
+ (require 'textsec)
+ (let ((func (intern (format "textsec-%s-suspicious-p" type))))
+ (unless (fboundp func)
+ (error "%s is not a valid function" func))
+ (funcall func object))))
+
+(provide 'textsec-check)
+
+;;; textsec-check.el ends here
diff --git a/lisp/international/textsec.el b/lisp/international/textsec.el
new file mode 100644
index 00000000000..82eba1b5d51
--- /dev/null
+++ b/lisp/international/textsec.el
@@ -0,0 +1,467 @@
+;;; textsec.el --- Functions for handling homoglyphs and the like -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'uni-confusable)
+(require 'ucs-normalize)
+(require 'idna-mapping)
+(require 'puny)
+(require 'mail-parse)
+(require 'url)
+
+(defvar textsec--char-scripts nil)
+
+(eval-and-compile
+ (defun textsec--create-script-table (data)
+ "Create the textsec--char-scripts char table."
+ (setq textsec--char-scripts (make-char-table nil))
+ (dolist (scripts data)
+ (dolist (range (cadr scripts))
+ (set-char-table-range textsec--char-scripts
+ range (car scripts)))))
+ (require 'uni-scripts))
+
+(defun textsec-scripts (string)
+ "Return a list of Unicode scripts used in STRING.
+The scripts returned by this function use the Unicode Script property
+as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (seq-map (lambda (char)
+ (elt textsec--char-scripts char))
+ string))
+
+(defun textsec-single-script-p (string)
+ "Return non-nil if STRING is all in a single Unicode script.
+
+Note that the concept of \"single script\" used by this function
+isn't obvious -- some mixtures of scripts count as a \"single
+script\". See
+
+ https://www.unicode.org/reports/tr39/#Mixed_Script_Detection
+
+for details. The Unicode scripts are as defined by the
+Unicode Standard Annex 24 (UAX#24)."
+ (let ((scripts (mapcar
+ (lambda (s)
+ (append s
+ ;; Some scripts used in East Asia are
+ ;; commonly used across borders, so we add
+ ;; those.
+ (mapcan (lambda (script)
+ (copy-sequence
+ (textsec--augment-script script)))
+ s)))
+ (textsec-scripts string))))
+ (catch 'empty
+ (cl-loop for s1 in scripts
+ do (cl-loop for s2 in scripts
+ ;; Common/inherited chars can be used in
+ ;; text with all scripts.
+ when (and (not (memq 'common s1))
+ (not (memq 'common s2))
+ (not (memq 'inherited s1))
+ (not (memq 'inherited s2))
+ (not (seq-intersection s1 s2)))
+ do (throw 'empty nil)))
+ t)))
+
+(defun textsec--augment-script (script)
+ (cond
+ ((eq script 'han)
+ '(hangul japan korea))
+ ((or (eq script 'hiragana)
+ (eq script 'katakana))
+ '(japan))
+ ((or (eq script 'hangul)
+ (eq script 'bopomofo))
+ '(korea))))
+
+(defun textsec-covering-scripts (string)
+ "Return a minimal list of scripts used in STRING.
+Note that a string may have several different minimal cover sets.
+The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (let* ((scripts (textsec-scripts string))
+ (set (car scripts)))
+ (dolist (s scripts)
+ (setq set (seq-union set (seq-difference s set))))
+ (sort (delq 'common (delq 'inherited set)) #'string<)))
+
+(defun textsec-restriction-level (string)
+ "Say what restriction level STRING qualifies for.
+Levels are (in decreasing order of restrictiveness) `ascii-only',
+`single-script', `highly-restrictive', `moderately-restrictive',
+`minimally-restrictive' and `unrestricted'."
+ (let ((scripts (textsec-covering-scripts string)))
+ (cond
+ ((string-match "\\`[[:ascii:]]+\\'" string)
+ 'ascii-only)
+ ((textsec-single-script-p string)
+ 'single-script)
+ ((or (null (seq-difference scripts '(latin han hiragana katakana)))
+ (null (seq-difference scripts '(latin han bopomofo)))
+ (null (seq-difference scripts '(latin han hangul))))
+ 'highly-restrictive)
+ ((and (= (length scripts) 2)
+ (memq 'latin scripts)
+ ;; This list comes from
+ ;; https://www.unicode.org/reports/tr31/#Table_Recommended_Scripts
+ ;; (but without latin, cyrillic and greek).
+ (seq-intersection scripts
+ '(arabic
+ armenian
+ bengali
+ bopomofo
+ devanagari
+ ethiopic
+ georgian
+ gujarati
+ gurmukhi
+ hangul
+ han
+ hebrew
+ hiragana
+ katakana
+ kannada
+ khmer
+ lao
+ malayalam
+ myanmar
+ oriya
+ sinhala
+ tamil
+ telugu
+ thaana
+ thai
+ tibetan)))
+ ;; The string is covered by Latin and any one other Recommended
+ ;; script, except Cyrillic, Greek.
+ 'moderately-retrictive)
+ ;; Fixme `minimally-restrictive' -- needs well-formedness criteria
+ ;; and Identifier Profile.
+ (t
+ 'unrestricted))))
+
+(defun textsec-mixed-numbers-p (string)
+ "Return non-nil if STRING includes numbers from different decimal systems."
+ (>
+ (length
+ (seq-uniq
+ (mapcar
+ (lambda (char)
+ ;; Compare zeros in the respective decimal systems.
+ (- char (get-char-code-property char 'numeric-value)))
+ (seq-filter (lambda (char)
+ ;; We're selecting the characters that
+ ;; have a numeric property.
+ (eq (get-char-code-property char 'general-category)
+ 'Nd))
+ string))))
+ 1))
+
+(defun textsec-ascii-confusable-p (string)
+ "Return non-nil if non-ASCII STRING can be confused with ASCII on display."
+ (and (not (eq (textsec-restriction-level string) 'ascii-only))
+ (eq (textsec-restriction-level (textsec-unconfuse-string string))
+ 'ascii-only)))
+
+(defun textsec-unconfuse-string (string)
+ "Return a de-confused version of STRING.
+This algorithm is described in:
+
+ https://www.unicode.org/reports/tr39/#Confusable_Detection"
+ (ucs-normalize-NFD-string
+ (apply #'concat
+ (seq-map (lambda (char)
+ (or (gethash char uni-confusable-table)
+ (string char)))
+ (ucs-normalize-NFD-string string)))))
+
+(defun textsec-resolved-script-set (string)
+ "Return the resolved script set for STRING.
+This is the minimal covering script set for STRING, but is nil is
+STRING isn't a single script string.
+The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (and (textsec-single-script-p string)
+ (textsec-covering-scripts string)))
+
+(defun textsec-single-script-confusable-p (string1 string2)
+ "Say whether STRING1 and STRING2 are single-script confusables.
+The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (and (equal (textsec-unconfuse-string string1)
+ (textsec-unconfuse-string string2))
+ ;; And they have to have at least one resolved script in
+ ;; common.
+ (seq-intersection (textsec-resolved-script-set string1)
+ (textsec-resolved-script-set string2))))
+
+(defun textsec-mixed-script-confusable-p (string1 string2)
+ "Say whether STRING1 and STRING2 are mixed-script confusables.
+The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (and (equal (textsec-unconfuse-string string1)
+ (textsec-unconfuse-string string2))
+ ;; And they have no resolved scripts in common.
+ (null (seq-intersection (textsec-resolved-script-set string1)
+ (textsec-resolved-script-set string2)))))
+
+(defun textsec-whole-script-confusable-p (string1 string2)
+ "Say whether STRING1 and STRING2 are whole-script confusables.
+The scripts are as defined by the Unicode Standard Annex 24 (UAX#24)."
+ (and (textsec-mixed-script-confusable-p string1 string2)
+ (textsec-single-script-p string1)
+ (textsec-single-script-p string2)))
+
+(defun textsec--ipvx-address-p (domain)
+ "Return non-nil if DOMAIN is an ipv4 or ipv6 address."
+ ;; This is a very relaxed pattern for IPv4 or IPv6 addresses. The
+ ;; assumption is that any malformed address accepted by this rule
+ ;; will be rejected by the actual address parser eventually.
+ (let ((case-fold-search t))
+ (rx-let ((ipv4 (** 1 4
+ (** 1 3 (in "0-9"))
+ (? ".")))
+ (ipv6 (: (** 1 7
+ (** 0 4 (in "0-9a-f"))
+ ":")
+ (** 0 4 (in "0-9a-f"))
+ (? ":" ipv4))))
+ (string-match-p (rx bos (or ipv4 ipv6 (: "[" ipv6 "]")) eos) domain))))
+
+(defun textsec-domain-suspicious-p (domain)
+ "Say whether DOMAIN's name looks suspicious.
+Return nil if it isn't suspicious. If it is, return a string explaining
+the potential problem.
+
+Domain names are considered suspicious if they use characters
+that can look similar to other characters when displayed, or
+use characters that are not allowed by Unicode's IDNA mapping,
+or use certain other unusual mixtures of characters."
+ (catch 'found
+ ;; Plain domains aren't suspicious.
+ (when (textsec--ipvx-address-p domain)
+ (throw 'found nil))
+ (seq-do
+ (lambda (char)
+ (when (eq (elt idna-mapping-table char) t)
+ (throw 'found
+ (format "Disallowed character%s (#x%x, %s)"
+ (if (eq (get-char-code-property char 'general-category)
+ 'Cf)
+ ""
+ (concat ": " (string char)))
+ char
+ (get-char-code-property char 'name)))))
+ domain)
+ ;; Does IDNA allow it?
+ (unless (puny-highly-restrictive-domain-p domain)
+ (throw
+ 'found
+ (format "`%s' mixes characters from different scripts in suspicious ways"
+ domain)))
+ ;; Check whether any segment of the domain name is confusable with
+ ;; an ASCII-only segment.
+ (dolist (elem (split-string domain "\\."))
+ (when (textsec-ascii-confusable-p elem)
+ (throw 'found (format "`%s' is confusable with ASCII" elem))))
+ nil))
+
+(defun textsec-local-address-suspicious-p (local)
+ "Say whether LOCAL part of an email address looks suspicious.
+LOCAL is the bit before \"@\" in an email address.
+
+If it isn't suspicious, return nil. If it is, return a string explaining
+the potential problem.
+
+Email addresses are considered suspicious if they use characters
+that can look similar to other characters when displayed, or use
+certain other unusual mixtures of characters."
+ (cond
+ ((not (equal local (ucs-normalize-NFKC-string local)))
+ (format "`%s' is not in normalized format `%s'"
+ local (ucs-normalize-NFKC-string local)))
+ ((textsec-mixed-numbers-p local)
+ (format "`%s' contains numbers from different number systems" local))
+ ((eq (textsec-restriction-level local) 'unrestricted)
+ (format "`%s' isn't restrictive enough" local))
+ ((string-match-p "\\`\\.\\|\\.\\'\\|\\.\\." local)
+ (format "`%s' contains invalid dots" local))))
+
+(defun textsec-bidi-controls-suspicious-p (string)
+ "Return non-nil of STRING uses bidi controls in suspicious ways.
+If STRING doesn't include any suspicious uses of bidirectional
+formatting control characters, return nil. Otherwise, return the
+index of the first character in STRING affected by such suspicious
+use of bidi controls. If the returned value is beyond the length
+of STRING, it means any text following STRING on display might be
+affected by bidi controls in STRING."
+ (with-temp-buffer
+ ;; We add a string that's representative of some text that could
+ ;; follow STRING, with the purpose of detecting residual bidi
+ ;; state at end of STRING which could then affect the following
+ ;; text.
+ (insert string "a1א:!")
+ (let ((pos (bidi-find-overridden-directionality 1 (point-max) nil)))
+ (and (fixnump pos)
+ (1- pos)))))
+
+(defun textsec-name-suspicious-p (name)
+ "Say whether NAME looks suspicious.
+NAME is (for instance) the free-text display name part of an
+email address.
+
+If it isn't suspicious, return nil. If it is, return a string
+explaining the potential problem.
+
+Names are considered suspicious if they use characters that can
+look similar to other characters when displayed, or use certain
+other unusual mixtures of characters."
+ (cond
+ ((not (equal name (ucs-normalize-NFC-string name)))
+ (format "`%s' is not in normalized format `%s'"
+ name (ucs-normalize-NFC-string name)))
+ ((and (seq-find (lambda (char)
+ (and (member char bidi-control-characters)
+ (not (member char
+ '( ?\N{left-to-right mark}
+ ?\N{right-to-left mark}
+ ?\N{arabic letter mark})))))
+ name)
+ ;; We have bidirectional formatting characters, but check
+ ;; whether they affect any other characters in suspicious
+ ;; ways. If not, NAME is not suspicious.
+ (fixnump (textsec-bidi-controls-suspicious-p name)))
+ (format "`%s' contains suspicious uses of bidirectional control characters"
+ name))
+ ((textsec-suspicious-nonspacing-p name))))
+
+(defun textsec-suspicious-nonspacing-p (string)
+ "Say whether STRING uses nonspacing characters in suspicious ways.
+If it doesn't, return nil. If it does, return a string explaining
+the potential problem.
+
+Use of nonspacing characters is considered suspicious if there are
+two or more consecutive identical nonspacing characters, or too many
+consecutive nonspacing characters."
+ (let ((prev nil)
+ (nonspace-count 0))
+ (catch 'found
+ (seq-do
+ (lambda (char)
+ (let ((nonspacing
+ (memq (get-char-code-property char 'general-category)
+ '(Mn Me))))
+ (when (and nonspacing
+ (equal char prev))
+ (throw 'found "Two identical consecutive nonspacing characters"))
+ (setq nonspace-count (if nonspacing
+ (1+ nonspace-count)
+ 0))
+ (when (> nonspace-count 4)
+ (throw 'found
+ "Too many consecutive nonspacing characters"))
+ (setq prev char)))
+ string)
+ nil)))
+
+(defun textsec-email-address-suspicious-p (address)
+ "Say whether EMAIL address looks suspicious.
+If it isn't, return nil. If it is, return a string explaining the
+potential problem.
+
+An email address is considered suspicious if either of its two
+parts -- the local address name or the domain -- are found to be
+suspicious by, respectively, `textsec-local-address-suspicious-p'
+and `textsec-domain-suspicious-p'."
+ (pcase-let ((`(,local ,domain) (split-string address "@")))
+ (or
+ (textsec-domain-suspicious-p domain)
+ (textsec-local-address-suspicious-p local))))
+
+(defun textsec-email-address-header-suspicious-p (email)
+ "Say whether EMAIL looks suspicious.
+If it isn't, return nil. If it is, return a string explaining the
+potential problem.
+
+Note that EMAIL has to be a valid email specification according
+to RFC2047bis -- strings that can't be parsed will be flagged as
+suspicious.
+
+An email specification is considered suspicious if either of its
+two parts -- the address or the name -- are found to be
+suspicious by, respectively, `textsec-email-address-suspicious-p'
+and `textsec-name-suspicious-p'."
+ (catch 'end
+ (pcase-let ((`(,address . ,name)
+ (condition-case nil
+ (mail-header-parse-address email t)
+ (error (throw 'end "Email address can't be parsed.")))))
+ (or
+ (textsec-email-address-suspicious-p address)
+ (and name (textsec-name-suspicious-p name))))))
+
+(defun textsec-url-suspicious-p (url)
+ "Say whether URL looks suspicious.
+If it isn't, return nil. If it is, return a string explaining the
+potential problem."
+ (let ((parsed (url-generic-parse-url url)))
+ ;; The URL may not have a domain.
+ (and (url-host parsed)
+ (textsec-domain-suspicious-p (url-host parsed)))))
+
+(defun textsec-link-suspicious-p (link)
+ "Say whether LINK is suspicious.
+LINK should be a cons cell where the first element is the URL,
+and the second element is the link text.
+
+This function will return non-nil if it seems like the link text
+is misleading about where the URL takes you. This is typical
+when the link text looks like an URL itself, but doesn't lead to
+the same domain as the URL."
+ (let* ((url (car link))
+ (text (string-trim (cdr link))))
+ (catch 'found
+ (let ((udomain (url-host (url-generic-parse-url url)))
+ (tdomain (url-host (url-generic-parse-url text))))
+ (cond
+ ((and udomain
+ tdomain
+ (not (equal udomain tdomain))
+ ;; One may be a sub-domain of the other, but don't allow too
+ ;; short domains.
+ (not (or (and (string-suffix-p udomain tdomain)
+ (url-domsuf-cookie-allowed-p udomain))
+ (and (string-suffix-p tdomain udomain)
+ (url-domsuf-cookie-allowed-p tdomain)))))
+ (throw 'found
+ (format "Text `%s' doesn't point to link URL `%s'"
+ text url)))
+ ((and tdomain
+ (textsec-domain-suspicious-p tdomain))
+ (throw 'found
+ (format "Domain `%s' in the link text is suspicious"
+ (bidi-string-strip-control-characters
+ tdomain)))))))))
+
+(provide 'textsec)
+
+;;; textsec.el ends here
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index a3b62667915..2a91e7cb5ec 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -62,6 +62,7 @@
;;; Code:
(require 'quail)
+(require 'generate-lisp-file)
;; List of values of key "ENCODE:" and the corresponding Emacs
;; coding-system and language environment name.
@@ -269,13 +270,10 @@ SPC, 6, 3, 4, or 7 specifying a tone (SPC:陰平, 6:陽平, 3:上聲, 4:去聲,
(tit-moveleft ",<")
(tit-keyprompt nil))
- (princ (format ";;; %s -*- lexical-binding:t -*-\n"
- (file-name-nondirectory filename)))
+ (generate-lisp-file-heading filename 'titdic-convert :code nil)
(princ ";; Quail package `")
(princ package)
(princ "\n")
- (princ (substitute-command-keys
- ";; Generated by the command `titdic-convert'\n"))
(princ ";;\tOriginal TIT dictionary file: ")
(princ (file-name-nondirectory filename))
(princ "\n\n")
@@ -521,11 +519,8 @@ the generated Quail package is saved."
;; Process the body part
(tit-process-body)
-
- (princ ";; Local Variables:\n")
- (princ ";; version-control: never\n")
- (princ ";; no-update-autoloads: t\n")
- (princ ";; End:\n"))))))
+ (generate-lisp-file-trailer
+ filename :inhibit-provide t :compile t :coding nil))))))
;;;###autoload
(defun batch-titdic-convert (&optional force)
@@ -1135,11 +1130,8 @@ the generated Quail package is saved."
;; Explicitly set eol format to `unix'.
(setq coding-system-for-write 'utf-8-unix)
(with-temp-file (expand-file-name quailfile dirname)
- (insert (format ";;; %s -*- lexical-binding:t -*-\n"
- (file-name-nondirectory quailfile)))
+ (generate-lisp-file-heading quailfile 'miscdic-convert)
(insert (format-message ";; Quail package `%s'\n" name))
- (insert (format-message
- ";; Generated by the command `miscdic-convert'\n"))
(insert ";; Source dictionary file: " dicfile "\n")
(insert ";; Copyright notice of the source file\n")
(insert ";;------------------------------------------------------\n")
@@ -1161,11 +1153,8 @@ the generated Quail package is saved."
(let ((dicbuf (current-buffer)))
(with-current-buffer dstbuf
(funcall converter dicbuf)))))
- (insert ";; Local Variables:\n"
- ";; version-control: never\n"
- ";; no-update-autoloads: t\n"
- ";; End:\n\n"
- ";;; " quailfile " ends here\n")))
+ (generate-lisp-file-trailer
+ quailfile :inhibit-provide t :compile t :coding nil)))
(setq tail (cdr tail)))))
(defun batch-miscdic-convert ()
@@ -1228,7 +1217,4 @@ The library is named pinyin.el, and contains the constant
(insert "(provide 'pinyin)\n"))
(kill-emacs 0)))
-;; Prevent "Local Variables" above confusing Emacs.
-
-
;;; titdic-cnv.el ends here
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 7593a0ec980..8f480a87d94 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -54,6 +54,7 @@
;;; Code:
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
;; Some additional options and constants.
@@ -430,13 +431,13 @@ and doesn't remove full-buffer highlighting after a search."
(defface lazy-highlight
'((((class color) (min-colors 88) (background light))
- (:background "paleturquoise"))
+ (:background "paleturquoise" :distant-foreground "black"))
(((class color) (min-colors 88) (background dark))
- (:background "paleturquoise4"))
+ (:background "paleturquoise4" :distant-foreground "white"))
(((class color) (min-colors 16))
- (:background "turquoise3"))
+ (:background "turquoise3" :distant-foreground "white"))
(((class color) (min-colors 8))
- (:background "turquoise3"))
+ (:background "turquoise3" :distant-foreground "white"))
(t (:underline t)))
"Face for lazy highlighting of matches other than the current one."
:group 'lazy-highlight
@@ -465,6 +466,12 @@ and doesn't remove full-buffer highlighting after a search."
:group 'lazy-count
:version "27.1")
+(defvar lazy-count-invisible-format " (invisible %s)"
+ "Format of the number of invisible matches for the prompt.
+When invisible matches exist, their number is appended
+after the total number of matches. Display nothing when
+this variable is nil.")
+
;; Define isearch help map.
@@ -668,6 +675,7 @@ This is like `describe-bindings', but displays only Isearch keys."
;; The key translations defined in the C-x 8 prefix should add
;; characters to the search string. See iso-transl.el.
(define-key map "\C-x8\r" 'isearch-char-by-name)
+ (define-key map "\C-x8e\r" 'isearch-emoji-by-name)
map)
"Keymap for `isearch-mode'.")
@@ -758,6 +766,8 @@ This is like `describe-bindings', but displays only Isearch keys."
:help "Search for literal char"]
["Search for char by name" isearch-char-by-name
:help "Search for character by name"]
+ ["Search for Emoji by name" isearch-emoji-by-name
+ :help "Search for Emoji by its Unicode name"]
"---"
["Toggle input method" isearch-toggle-input-method
:help "Toggle input method for search"]
@@ -865,14 +875,16 @@ This variable is set and changed during isearch. To change the
default behavior used for searches, see `search-default-mode'
instead.")
-(defvar isearch-lax-whitespace t
+(defcustom isearch-lax-whitespace t
"If non-nil, a space will match a sequence of whitespace chars.
When you enter a space or spaces in ordinary incremental search, it
will match any sequence matched by the regexp defined by the variable
`search-whitespace-regexp'. If the value is nil, each space you type
matches literally, against one space. You can toggle the value of this
variable by the command `isearch-toggle-lax-whitespace', usually bound to
-`M-s SPC' during isearch.")
+`M-s SPC' during isearch."
+ :type 'boolean
+ :version "25.1")
(defvar isearch-regexp-lax-whitespace nil
"If non-nil, a space will match a sequence of whitespace chars.
@@ -1097,7 +1109,7 @@ In incremental searches, a space or spaces normally matches any
whitespace defined by the variable `search-whitespace-regexp'.
To search for a literal space and nothing else, enter C-q SPC.
To toggle whitespace matching, use `isearch-toggle-lax-whitespace',
-usually bound to `M-s SPC' during isearch.
+usually bound to \\`M-s SPC' during isearch.
This command does not support character folding."
(interactive "P\np")
(isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
@@ -1271,6 +1283,7 @@ used to set the value of `isearch-regexp-function'."
isearch-lazy-count-current nil
isearch-lazy-count-total nil
+ isearch-lazy-count-invisible nil
;; Save the original value of `minibuffer-message-timeout', and
;; set it to nil so that isearch's messages don't get timed out.
@@ -1810,17 +1823,19 @@ The following additional command keys are active while editing.
;; Search string might have meta information on text properties.
(minibuffer-allow-text-properties t))
(setq isearch-new-string
- (read-from-minibuffer
- (isearch-message-prefix nil isearch-nonincremental)
- (cons isearch-string (1+ (or (isearch-fail-pos)
- (length isearch-string))))
- minibuffer-local-isearch-map nil
- (if isearch-regexp
- (cons 'regexp-search-ring
- (1+ (or regexp-search-ring-yank-pointer -1)))
- (cons 'search-ring
- (1+ (or search-ring-yank-pointer -1))))
- nil t)
+ (minibuffer-with-setup-hook
+ (minibuffer-lazy-highlight-setup)
+ (read-from-minibuffer
+ (isearch-message-prefix nil isearch-nonincremental)
+ (cons isearch-string (1+ (or (isearch-fail-pos)
+ (length isearch-string))))
+ minibuffer-local-isearch-map nil
+ (if isearch-regexp
+ (cons 'regexp-search-ring
+ (1+ (or regexp-search-ring-yank-pointer -1)))
+ (cons 'search-ring
+ (1+ (or search-ring-yank-pointer -1))))
+ nil t))
isearch-new-message
(mapconcat 'isearch-text-char-description
isearch-new-string "")))))
@@ -2324,7 +2339,12 @@ arg means replace backward. Note that using the prefix arg
is possible only when `isearch-allow-scroll' is non-nil or
`isearch-allow-prefix' is non-nil, and it doesn't always provide the
correct matches for `query-replace', so the preferred way to run word
-replacements from Isearch is `M-s w ... M-%'."
+replacements from Isearch is `M-s w ... M-%'.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time."
(interactive
(list current-prefix-arg))
(barf-if-buffer-read-only)
@@ -2378,7 +2398,12 @@ replacements from Isearch is `M-s w ... M-%'."
(defun isearch-query-replace-regexp (&optional arg)
"Start `query-replace-regexp' with string to replace from last search string.
-See `isearch-query-replace' for more information."
+See `isearch-query-replace' for more information.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time."
(interactive
(list current-prefix-arg))
(isearch-query-replace arg t))
@@ -2504,11 +2529,12 @@ If no input items have been entered yet, just beep."
(if (null (cdr isearch-cmds))
(ding)
(isearch-pop-state))
- ;; When going back to the hidden match, reopen it.
- (when (and (eq search-invisible 'open) isearch-hide-immediately
- isearch-other-end)
- (isearch-range-invisible (min (point) isearch-other-end)
- (max (point) isearch-other-end)))
+ ;; When going back to the hidden match, reopen it and close other overlays.
+ (when (and (eq search-invisible 'open) isearch-hide-immediately)
+ (if isearch-other-end
+ (isearch-range-invisible (min (point) isearch-other-end)
+ (max (point) isearch-other-end))
+ (isearch-close-unnecessary-overlays (point) (point))))
(isearch-update))
(defun isearch-del-char (&optional arg)
@@ -2624,9 +2650,10 @@ is bound to outside of Isearch."
;; Key search depends on mode (bug#47755)
(isearch-mode nil))
(key-binding (this-command-keys-vector) t))))
- (if (and (window-minibuffer-p w)
- (not (minibuffer-window-active-p w))) ; in echo area
- (isearch-yank-x-selection)
+ (if (or mouse-yank-at-point
+ (and (window-minibuffer-p w)
+ (not (minibuffer-window-active-p w)))) ; in echo area
+ (isearch-yank-x-selection)
(when (functionp binding)
(call-interactively binding)))))
@@ -2665,7 +2692,7 @@ or it might return the position of the end of the line."
(interactive "p")
(if (eobp)
(insert
- (with-current-buffer (cadr (buffer-list))
+ (with-minibuffer-selected-window
(buffer-substring-no-properties
(point) (progn (forward-char arg) (point)))))
(forward-char arg)))
@@ -2747,6 +2774,24 @@ With argument, add COUNT copies of the character."
(mapconcat 'isearch-text-char-description
string ""))))))))
+(defun isearch-emoji-by-name (&optional count)
+ "Read an Emoji name and add it to the search string COUNT times.
+COUNT (interactively, the prefix argument) defaults to 1.
+The command accepts Unicode names like \"smiling face\" or
+\"heart with arrow\", and completion is available."
+ (interactive "p")
+ (with-isearch-suspended
+ (let ((emoji (with-temp-buffer
+ (emoji-search)
+ (if (and (integerp count) (> count 1))
+ (apply 'concat (make-list count (buffer-string)))
+ (buffer-string)))))
+ (when emoji
+ (setq isearch-new-string (concat isearch-string emoji)
+ isearch-new-message (concat isearch-message
+ (mapconcat 'isearch-text-char-description
+ emoji "")))))))
+
(defun isearch-search-and-update ()
"Do the search and update the display."
(when (or isearch-success
@@ -2913,6 +2958,7 @@ to the barrier."
(put 'scroll-other-window-down 'isearch-scroll t)
(put 'beginning-of-buffer-other-window 'isearch-scroll t)
(put 'end-of-buffer-other-window 'isearch-scroll t)
+(put 'recenter-other-window 'isearch-scroll t)
;; Commands which change the window layout
(put 'delete-other-windows 'isearch-scroll t)
@@ -2927,6 +2973,9 @@ to the barrier."
(put 'mouse-drag-mode-line 'isearch-scroll t)
(put 'mouse-drag-vertical-line 'isearch-scroll t)
+;; For context menu with isearch submenu
+(put 'context-menu-open 'isearch-scroll t)
+
;; Aliases for split-window-*
(put 'split-window-vertically 'isearch-scroll t)
(put 'split-window-horizontally 'isearch-scroll t)
@@ -3430,11 +3479,13 @@ the word mode."
(if (and (not isearch-success) (not isearch-case-fold-search))
"case-sensitive ")
(let ((prefix ""))
- (advice-function-mapc
- (lambda (_ props)
- (let ((np (cdr (assq 'isearch-message-prefix props))))
- (if np (setq prefix (concat np prefix)))))
- isearch-filter-predicate)
+ (dolist (advice-function (list isearch-filter-predicate
+ isearch-search-fun-function))
+ (advice-function-mapc
+ (lambda (_ props)
+ (let ((np (cdr (assq 'isearch-message-prefix props))))
+ (if np (setq prefix (concat np prefix)))))
+ advice-function))
prefix)
(isearch--describe-regexp-mode isearch-regexp-function)
(cond
@@ -3485,7 +3536,12 @@ isearch-message-suffix prompt. Otherwise, for isearch-message-prefix."
(- isearch-lazy-count-total
isearch-lazy-count-current
-1)))
- (or isearch-lazy-count-total "?"))
+ (if (and isearch-lazy-count-invisible
+ lazy-count-invisible-format)
+ (concat (format "%s" (or isearch-lazy-count-total "?"))
+ (format lazy-count-invisible-format
+ isearch-lazy-count-invisible))
+ (or isearch-lazy-count-total "?")))
"")))
@@ -3713,11 +3769,11 @@ Optional third argument, if t, means if fail just return nil (no error).
;; Verify if the current match is outside of each element of
;; `isearch-opened-overlays', if so close that overlay.
-(defun isearch-close-unnecessary-overlays (begin end)
+(defun isearch-close-unnecessary-overlays (beg end)
(let ((overlays isearch-opened-overlays))
(setq isearch-opened-overlays nil)
(dolist (ov overlays)
- (if (isearch-intersects-p begin end (overlay-start ov) (overlay-end ov))
+ (if (isearch-intersects-p beg end (overlay-start ov) (overlay-end ov))
(push ov isearch-opened-overlays)
(let ((fct-temp (overlay-get ov 'isearch-open-invisible-temporary)))
(if fct-temp
@@ -3736,10 +3792,11 @@ Optional third argument, if t, means if fail just return nil (no error).
(save-excursion
(goto-char beg)
(let (;; can-be-opened keeps track if we can open some overlays.
- (can-be-opened (eq search-invisible 'open))
+ (can-be-opened (memq search-invisible '(open can-be-opened)))
;; the list of overlays that could be opened
(crt-overlays nil))
- (when (and can-be-opened isearch-hide-immediately)
+ (when (and can-be-opened isearch-hide-immediately
+ (not (eq search-invisible 'can-be-opened)))
(isearch-close-unnecessary-overlays beg end))
;; If the following character is currently invisible,
;; skip all characters with that same `invisible' property value.
@@ -3778,9 +3835,10 @@ Optional third argument, if t, means if fail just return nil (no error).
(if (>= (point) end)
(if (and can-be-opened (consp crt-overlays))
(progn
- (setq isearch-opened-overlays
- (append isearch-opened-overlays crt-overlays))
- (mapc 'isearch-open-overlay-temporary crt-overlays)
+ (unless (eq search-invisible 'can-be-opened)
+ (setq isearch-opened-overlays
+ (append isearch-opened-overlays crt-overlays))
+ (mapc 'isearch-open-overlay-temporary crt-overlays))
nil)
(setq isearch-hidden t)))))))
@@ -3964,7 +4022,10 @@ since they have special meaning in a regexp."
(defvar isearch-lazy-highlight-error nil)
(defvar isearch-lazy-count-current nil)
(defvar isearch-lazy-count-total nil)
+(defvar isearch-lazy-count-invisible nil)
(defvar isearch-lazy-count-hash (make-hash-table))
+(defvar lazy-count-update-hook nil
+ "Hook run after new lazy count results are computed.")
(defun lazy-highlight-cleanup (&optional force procrastinate)
"Stop lazy highlighting and remove extra highlighting from current buffer.
@@ -4023,7 +4084,7 @@ by other Emacs features."
isearch-lazy-highlight-window-end))))))
;; something important did indeed change
(lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer
- (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
+ (when isearch-lazy-count
(when (or (equal isearch-string "")
;; Check if this place was reached by a condition above
;; other than changed window boundaries (that shouldn't
@@ -4040,9 +4101,13 @@ by other Emacs features."
;; Reset old counter before going to count new numbers
(clrhash isearch-lazy-count-hash)
(setq isearch-lazy-count-current nil
- isearch-lazy-count-total nil)
+ isearch-lazy-count-total nil
+ isearch-lazy-count-invisible nil)
;; Delay updating the message if possible, to avoid flicker
- (when (string-equal isearch-string "") (isearch-message))))
+ (when (string-equal isearch-string "")
+ (when (and isearch-mode (null isearch-message-function))
+ (isearch-message))
+ (run-hooks 'lazy-count-update-hook))))
(setq isearch-lazy-highlight-window-start-changed nil)
(setq isearch-lazy-highlight-window-end-changed nil)
(setq isearch-lazy-highlight-error isearch-error)
@@ -4095,13 +4160,15 @@ by other Emacs features."
'isearch-lazy-highlight-start))))
;; Update the current match number only in isearch-mode and
;; unless isearch-mode is used specially with isearch-message-function
- (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
+ (when isearch-lazy-count
;; Update isearch-lazy-count-current only when it was already set
;; at the end of isearch-lazy-highlight-buffer-update
(when isearch-lazy-count-current
(setq isearch-lazy-count-current
(gethash (point) isearch-lazy-count-hash 0))
- (isearch-message))))
+ (when (and isearch-mode (null isearch-message-function))
+ (isearch-message))
+ (run-hooks 'lazy-count-update-hook))))
(defun isearch-lazy-highlight-search (string bound)
"Search ahead for the next or previous match, for lazy highlighting.
@@ -4115,10 +4182,10 @@ Attempt to do the search exactly the way the pending Isearch would."
(isearch-regexp-lax-whitespace
isearch-lazy-highlight-regexp-lax-whitespace)
(isearch-forward isearch-lazy-highlight-forward)
- ;; Don't match invisible text unless it can be opened
- ;; or when counting matches and user can visit hidden matches
- (search-invisible (or (eq search-invisible 'open)
- (and isearch-lazy-count search-invisible)))
+ ;; Count all invisible matches, but highlight only
+ ;; matches that can be opened by visiting them later
+ (search-invisible (or (not (null isearch-lazy-count))
+ 'can-be-opened))
(retry t)
(success nil))
;; Use a loop like in `isearch-search'.
@@ -4135,15 +4202,20 @@ Attempt to do the search exactly the way the pending Isearch would."
(error nil)))
(defun isearch-lazy-highlight-match (mb me)
- (let ((ov (make-overlay mb me)))
- (push ov isearch-lazy-highlight-overlays)
- ;; 1000 is higher than ediff's 100+,
- ;; but lower than isearch main overlay's 1001
- (overlay-put ov 'priority 1000)
- (overlay-put ov 'face 'lazy-highlight)
- (unless (or (eq isearch-lazy-highlight 'all-windows)
- isearch-lazy-highlight-buffer)
- (overlay-put ov 'window (selected-window)))))
+ (when (or (not isearch-lazy-count)
+ ;; Recheck the match that possibly was intended
+ ;; for counting only, but not for highlighting
+ (let ((search-invisible 'can-be-opened))
+ (funcall isearch-filter-predicate mb me)))
+ (let ((ov (make-overlay mb me)))
+ (push ov isearch-lazy-highlight-overlays)
+ ;; 1000 is higher than ediff's 100+,
+ ;; but lower than isearch main overlay's 1001
+ (overlay-put ov 'priority 1000)
+ (overlay-put ov 'face 'lazy-highlight)
+ (unless (or (eq isearch-lazy-highlight 'all-windows)
+ isearch-lazy-highlight-buffer)
+ (overlay-put ov 'window (selected-window))))))
(defun isearch-lazy-highlight-start ()
"Start a new lazy-highlight updating loop."
@@ -4277,11 +4349,22 @@ Attempt to do the search exactly the way the pending Isearch would."
(setq found nil)
(forward-char -1)))
(when isearch-lazy-count
- (setq isearch-lazy-count-total
- (1+ (or isearch-lazy-count-total 0)))
- (puthash (if isearch-lazy-highlight-forward me mb)
- isearch-lazy-count-total
- isearch-lazy-count-hash))
+ ;; Count as invisible when can't open overlay,
+ ;; but don't leave search-invisible with the
+ ;; value `open' since then lazy-highlight
+ ;; will open all overlays with matches.
+ (if (not (let ((search-invisible
+ (if (eq search-invisible 'open)
+ 'can-be-opened
+ search-invisible)))
+ (funcall isearch-filter-predicate mb me)))
+ (setq isearch-lazy-count-invisible
+ (1+ (or isearch-lazy-count-invisible 0)))
+ (setq isearch-lazy-count-total
+ (1+ (or isearch-lazy-count-total 0)))
+ (puthash (if isearch-lazy-highlight-forward me mb)
+ isearch-lazy-count-total
+ isearch-lazy-count-hash)))
;; Don't highlight the match when this loop is used
;; only to count matches or when matches were already
;; highlighted within the current window boundaries
@@ -4302,16 +4385,223 @@ Attempt to do the search exactly the way the pending Isearch would."
(setq looping nil
nomore t))))
(if nomore
- (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
+ (when isearch-lazy-count
(unless isearch-lazy-count-total
(setq isearch-lazy-count-total 0))
(setq isearch-lazy-count-current
(gethash opoint isearch-lazy-count-hash 0))
- (isearch-message))
+ (when (and isearch-mode (null isearch-message-function))
+ (isearch-message)))
(setq isearch-lazy-highlight-timer
(run-at-time lazy-highlight-interval nil
- 'isearch-lazy-highlight-buffer-update)))))))))
+ 'isearch-lazy-highlight-buffer-update)))))
+ (when (and nomore isearch-lazy-count)
+ (run-hooks 'lazy-count-update-hook))))))
+
+
+;; Reading from minibuffer with lazy highlight and match count
+
+(defcustom minibuffer-lazy-count-format "%s "
+ "Format of the total number of matches for the prompt prefix."
+ :type '(choice (const :tag "Don't display a count" nil)
+ (string :tag "Display match count" "%s "))
+ :group 'lazy-count
+ :version "29.1")
+
+(cl-defun minibuffer-lazy-highlight-setup
+ (&key (highlight isearch-lazy-highlight)
+ (cleanup lazy-highlight-cleanup)
+ (transform #'identity)
+ (filter nil)
+ (regexp isearch-regexp)
+ (regexp-function isearch-regexp-function)
+ (case-fold isearch-case-fold-search)
+ (lax-whitespace (if regexp
+ isearch-regexp-lax-whitespace
+ isearch-lax-whitespace)))
+ "Set up minibuffer for lazy highlight of matches in the original window.
+
+This function return a closure intended to be added to
+`minibuffer-setup-hook'. It accepts the following keyword
+arguments, all of which have a default based on the current
+isearch settings.
+
+HIGHLIGHT: Whether to perform lazy highlight.
+CLEANUP: Whether to clean up the lazy highlight when the minibuffer
+exits.
+TRANSFORM: A function taking one argument, the minibuffer contents,
+and returning the `isearch-string' to use for lazy highlighting.
+FILTER: A function to add to `isearch-filter-predicate'.
+REGEXP: The value of `isearch-regexp' to use for lazy highlighting.
+REGEXP-FUNCTION: The value of `isearch-regexp-function' to use for
+lazy highlighting.
+CASE-FOLD: The value of `isearch-case-fold' to use for lazy
+highlighting.
+LAX-WHITESPACE: The value of `isearch-lax-whitespace' and
+`isearch-regexp-lax-whitespace' to use for lazy highlighting."
+ (if (not highlight)
+ #'ignore
+ (let ((unwind (make-symbol "minibuffer-lazy-highlight--unwind"))
+ (after-change (make-symbol "minibuffer-lazy-highlight--after-change"))
+ (display-count (make-symbol "minibuffer-lazy-highlight--display-count"))
+ (buffer (current-buffer))
+ overlay)
+ (fset unwind
+ (lambda ()
+ (when filter
+ (with-current-buffer buffer
+ (remove-function (local 'isearch-filter-predicate) filter)))
+ (remove-hook 'lazy-count-update-hook display-count)
+ (when overlay (delete-overlay overlay))
+ (remove-hook 'after-change-functions after-change t)
+ (remove-hook 'minibuffer-exit-hook unwind t)
+ (let ((lazy-highlight-cleanup cleanup))
+ (lazy-highlight-cleanup))))
+ (fset after-change
+ (lambda (_beg _end _len)
+ (let ((inhibit-redisplay t) ;; Avoid cursor flickering
+ (string (minibuffer-contents)))
+ (with-minibuffer-selected-window
+ (let* ((isearch-forward t)
+ (isearch-regexp regexp)
+ (isearch-regexp-function regexp-function)
+ (isearch-case-fold-search case-fold)
+ (isearch-lax-whitespace lax-whitespace)
+ (isearch-regexp-lax-whitespace lax-whitespace)
+ (isearch-string (funcall transform string)))
+ (isearch-lazy-highlight-new-loop))))))
+ (fset display-count
+ (lambda ()
+ (overlay-put overlay 'before-string
+ (and isearch-lazy-count-total
+ (not isearch-error)
+ (format minibuffer-lazy-count-format
+ isearch-lazy-count-total)))))
+ (lambda ()
+ (add-hook 'minibuffer-exit-hook unwind nil t)
+ (add-hook 'after-change-functions after-change nil t)
+ (when minibuffer-lazy-count-format
+ (setq overlay (make-overlay (point-min) (point-min) (current-buffer) t))
+ (add-hook 'lazy-count-update-hook display-count))
+ (when filter
+ (with-current-buffer buffer
+ (add-function :after-while (local 'isearch-filter-predicate) filter)))
+ (funcall after-change nil nil nil)))))
+
+(defun isearch-search-fun-in-noncontiguous-region (search-fun bounds)
+ "Return the function that searches inside noncontiguous regions.
+A noncontiguous region is defined by the argument BOUNDS that
+is a list of cons cells of the form (START . END)."
+ (apply-partially
+ #'search-within-boundaries
+ search-fun
+ (lambda (pos)
+ (seq-some (lambda (b) (if isearch-forward
+ (and (>= pos (car b)) (< pos (cdr b)))
+ (and (> pos (car b)) (<= pos (cdr b)))))
+ bounds))
+ (lambda (pos)
+ (let ((bounds (flatten-list bounds))
+ found)
+ (unless isearch-forward
+ (setq bounds (nreverse bounds)))
+ (while (and bounds (not found))
+ (if (if isearch-forward (< pos (car bounds)) (> pos (car bounds)))
+ (setq found (car bounds))
+ (setq bounds (cdr bounds))))
+ found))))
+
+(defun isearch-search-fun-in-text-property (search-fun property)
+ "Return the function to search inside text that has the specified PROPERTY.
+The function will limit the search for matches only inside text which has
+this property in the current buffer.
+The argument SEARCH-FUN provides the function to search text, and
+defaults to the value of `isearch-search-fun-default' when nil."
+ (apply-partially
+ #'search-within-boundaries
+ search-fun
+ (lambda (pos) (get-text-property (if isearch-forward pos
+ (max (1- pos) (point-min)))
+ property))
+ (lambda (pos) (if isearch-forward
+ (next-single-property-change pos property)
+ (previous-single-property-change pos property)))))
+
+(defun search-within-boundaries ( search-fun get-fun next-fun
+ string &optional bound noerror count)
+ (let* ((old (point))
+ ;; Check if point is already on the property.
+ (beg (when (funcall get-fun old) old))
+ end found (i 0)
+ (subregexp
+ (and isearch-regexp
+ (save-match-data
+ (catch 'subregexp
+ (while (string-match "\\^\\|\\$" string i)
+ (setq i (match-end 0))
+ (when (subregexp-context-p string (match-beginning 0))
+ ;; The ^/$ is not inside a char-range or escaped.
+ (throw 'subregexp t))))))))
+ ;; Otherwise, try to search for the next property.
+ (unless beg
+ (setq beg (funcall next-fun old))
+ (when beg (goto-char beg)))
+ ;; Non-nil `beg' means there are more properties.
+ (while (and beg (not found))
+ ;; Search for the end of the current property.
+ (setq end (funcall next-fun beg))
+ ;; Handle ^/$ specially by matching in a temporary buffer.
+ (if subregexp
+ (let* ((prop-beg
+ (if (or (if isearch-forward (bobp) (eobp))
+ (null (funcall get-fun
+ (+ (point)
+ (if isearch-forward -1 1)))))
+ ;; Already at the beginning of the field.
+ beg
+ ;; Get the real beginning of the field when
+ ;; the search was started in the middle.
+ (let ((isearch-forward (not isearch-forward)))
+ ;; Search in the reverse direction.
+ (funcall next-fun beg))))
+ (substring (buffer-substring prop-beg end))
+ (offset (if isearch-forward prop-beg end))
+ match-data)
+ (with-temp-buffer
+ (insert substring)
+ (goto-char (- beg offset -1))
+ ;; Apply ^/$ regexp on the whole extracted substring.
+ (setq found (funcall
+ (or search-fun (isearch-search-fun-default))
+ string (and bound (max (point-min)
+ (min (point-max)
+ (- bound offset -1))))
+ noerror count))
+ ;; Adjust match data as if it's matched in original buffer.
+ (when found
+ (setq found (+ found offset -1)
+ match-data (mapcar (lambda (m) (+ m offset -1))
+ (match-data)))))
+ (when found (goto-char found))
+ (when match-data (set-match-data
+ (mapcar (lambda (m) (copy-marker m))
+ match-data))))
+ (setq found (funcall
+ (or search-fun (isearch-search-fun-default))
+ string (if bound (if isearch-forward
+ (min bound end)
+ (max bound end))
+ end)
+ noerror count)))
+ ;; Get the next text property.
+ (unless found
+ (setq beg (funcall next-fun end))
+ (when beg (goto-char beg))))
+ (unless found (goto-char old))
+ found))
+
+
(defun isearch-resume (string regexp word forward message case-fold)
"Resume an incremental search.
STRING is the string or regexp searched for.
@@ -4327,6 +4617,23 @@ CASE-FOLD non-nil means the search was case-insensitive."
(isearch-search)
(isearch-update))
+
+(defvar isearch-fold-quotes-mode--state)
+(define-minor-mode isearch-fold-quotes-mode
+ "Minor mode to aid searching for \\=` characters in help modes."
+ :lighter ""
+ (if isearch-fold-quotes-mode
+ (setq-local isearch-fold-quotes-mode--state
+ (buffer-local-set-state
+ search-default-mode
+ (lambda (string &optional _lax)
+ (thread-last
+ (regexp-quote string)
+ (replace-regexp-in-string "`" "[`‘]")
+ (replace-regexp-in-string "'" "['’]")
+ (replace-regexp-in-string "\"" "[\"“”]")))))
+ (buffer-local-restore-state isearch-fold-quotes-mode--state)))
+
(provide 'isearch)
;;; isearch.el ends here
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 20c12024745..be26ca55f0d 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -51,7 +51,7 @@ This variable controls both `display-time' and stealth fontification.
The optimum value is a little over the typical number of buffer
characters which fit in a typical window."
- :type 'integer)
+ :type 'natnum)
(defcustom jit-lock-stealth-time nil
@@ -217,6 +217,11 @@ If the system load rises above `jit-lock-stealth-load' percent, stealth
fontification is suspended. Stealth fontification intensity is controlled via
the variable `jit-lock-stealth-nice'.
+`jit-lock-mode' is not a regular minor mode, and it doesn't
+follow the regular conventions to switch the functionality on or
+off. Instead, an ARG of nil will switch it off, and non-nil will
+switch it on.
+
If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(setq jit-lock-mode arg)
(cond
@@ -237,20 +242,20 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(when (and jit-lock-stealth-time (null jit-lock-stealth-timer))
(setq jit-lock-stealth-timer
(run-with-idle-timer jit-lock-stealth-time t
- 'jit-lock-stealth-fontify)))
+ #'jit-lock-stealth-fontify)))
;; Create, but do not activate, the idle timer for repeated
;; stealth fontification.
(when (and jit-lock-stealth-time (null jit-lock-stealth-repeat-timer))
(setq jit-lock-stealth-repeat-timer (timer-create))
(timer-set-function jit-lock-stealth-repeat-timer
- 'jit-lock-stealth-fontify '(t)))
+ #'jit-lock-stealth-fontify '(t)))
;; Init deferred fontification timer.
(when (and jit-lock-defer-time (null jit-lock-defer-timer))
(setq jit-lock-defer-timer
(run-with-idle-timer jit-lock-defer-time t
- 'jit-lock-deferred-fontify)))
+ #'jit-lock-deferred-fontify)))
;; Initialize contextual fontification if requested.
(when (eq jit-lock-contextually t)
@@ -260,13 +265,13 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(lambda ()
(unless jit-lock--antiblink-grace-timer
(jit-lock-context-fontify))))))
- (add-hook 'post-command-hook 'jit-lock--antiblink-post-command nil t)
+ (add-hook 'post-command-hook #'jit-lock--antiblink-post-command nil t)
(setq jit-lock-context-unfontify-pos
(or jit-lock-context-unfontify-pos (point-max))))
;; Setup our hooks.
- (add-hook 'after-change-functions 'jit-lock-after-change nil t)
- (add-hook 'fontification-functions 'jit-lock-function nil t))
+ (add-hook 'after-change-functions #'jit-lock-after-change nil t)
+ (add-hook 'fontification-functions #'jit-lock-function nil t))
;; Turn Just-in-time Lock mode off.
(t
@@ -289,8 +294,9 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'."
(setq jit-lock-defer-timer nil)))
;; Remove hooks.
- (remove-hook 'after-change-functions 'jit-lock-after-change t)
- (remove-hook 'fontification-functions 'jit-lock-function))))
+ (remove-hook 'post-command-hook #'jit-lock--antiblink-post-command t)
+ (remove-hook 'after-change-functions #'jit-lock-after-change t)
+ (remove-hook 'fontification-functions #'jit-lock-function))))
(define-minor-mode jit-lock-debug-mode
"Minor mode to help debug code run from jit-lock.
@@ -702,8 +708,8 @@ will take place when text is fontified stealthily."
(min jit-lock-context-unfontify-pos jit-lock-start))))))
(defun jit-lock--antiblink-post-command ()
- (let* ((new-l-b-p (copy-marker (line-beginning-position)))
- (l-b-p-2 (line-beginning-position 2))
+ (let* ((new-l-b-p (copy-marker (syntax--lbp)))
+ (l-b-p-2 (syntax--lbp 2))
(same-line
(and jit-lock-antiblink-grace
(not (= new-l-b-p l-b-p-2))
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 84d0ef9179b..b84e9b74b1f 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -4,7 +4,7 @@
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: processes, languages, extensions
-;; Version: 1.0.14
+;; Version: 1.0.15
;; Package-Requires: ((emacs "25.2"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -698,7 +698,9 @@ TIMEOUT is nil)."
(defun jsonrpc--debug (server format &rest args)
"Debug message for SERVER with FORMAT and ARGS."
(jsonrpc--log-event
- server (if (stringp format)`(:message ,(format format args)) format)))
+ server (if (stringp format)
+ `(:message ,(apply #'format format args))
+ format)))
(defun jsonrpc--warn (format &rest args)
"Warning message with FORMAT and ARGS."
diff --git a/lisp/keymap.el b/lisp/keymap.el
index 3e9189fba45..ad7d4fbbba1 100644
--- a/lisp/keymap.el
+++ b/lisp/keymap.el
@@ -241,13 +241,13 @@ See `kbd' for a descripion of KEYS."
(setq bits (+ bits
(cdr
(assq (aref word 0)
- '((?A . ?\A-\^@) (?C . ?\C-\^@)
- (?H . ?\H-\^@) (?M . ?\M-\^@)
- (?s . ?\s-\^@) (?S . ?\S-\^@))))))
+ '((?A . ?\A-\0) (?C . ?\C-\0)
+ (?H . ?\H-\0) (?M . ?\M-\0)
+ (?s . ?\s-\0) (?S . ?\S-\0))))))
(setq prefix (+ prefix 2))
(setq word (substring word 2)))
(when (string-match "^\\^.$" word)
- (setq bits (+ bits ?\C-\^@))
+ (setq bits (+ bits ?\C-\0))
(setq prefix (1+ prefix))
(setq word (substring word 1)))
(let ((found (assoc word '(("NUL" . "\0") ("RET" . "\r")
@@ -262,37 +262,26 @@ See `kbd' for a descripion of KEYS."
(setq word (vector n))))
(cond ((= bits 0)
(setq key word))
- ((and (= bits ?\M-\^@) (stringp word)
+ ((and (= bits ?\M-\0) (stringp word)
(string-match "^-?[0-9]+$" word))
(setq key (mapcar (lambda (x) (+ x bits))
(append word nil))))
((/= (length word) 1)
(error "%s must prefix a single character, not %s"
(substring orig-word 0 prefix) word))
- ((and (/= (logand bits ?\C-\^@) 0) (stringp word)
+ ((and (/= (logand bits ?\C-\0) 0) (stringp word)
;; We used to accept . and ? here,
;; but . is simply wrong,
;; and C-? is not used (we use DEL instead).
(string-match "[@-_a-z]" word))
- (setq key (list (+ bits (- ?\C-\^@)
+ (setq key (list (+ bits (- ?\C-\0)
(logand (aref word 0) 31)))))
(t
(setq key (list (+ bits (aref word 0)))))))))
(when key
(dolist (_ (number-sequence 1 times))
(setq res (vconcat res key))))))
- (if (and (>= (length res) 4)
- (eq (aref res 0) ?\C-x)
- (eq (aref res 1) ?\()
- (eq (aref res (- (length res) 2)) ?\C-x)
- (eq (aref res (- (length res) 1)) ?\)))
- (apply #'vector (let ((lres (append res nil)))
- ;; Remove the first and last two elements.
- (setq lres (cdr (cdr lres)))
- (nreverse lres)
- (setq lres (cdr (cdr lres)))
- (nreverse lres)))
- res))))
+ res)))
(defun key-valid-p (keys)
"Say whether KEYS is a valid key.
@@ -306,10 +295,10 @@ number of characters have a special shorthand syntax.
Here's some example key sequences.
- \"f\" (the key 'f')
- \"S o m\" (a three key sequence of the keys 'S', 'o' and 'm')
- \"C-c o\" (a two key sequence of the keys 'c' with the control modifier
- and then the key 'o')
+ \"f\" (the key `f')
+ \"S o m\" (a three key sequence of the keys `S', `o' and `m')
+ \"C-c o\" (a two key sequence of the keys `c' with the control modifier
+ and then the key `o')
\"H-<left>\" (the key named \"left\" with the hyper modifier)
\"M-RET\" (the \"return\" key with a meta modifier)
\"C-M-<space>\" (the \"space\" key with both the control and meta modifiers)
@@ -325,38 +314,38 @@ which is
Alt-Control-Hyper-Meta-Shift-super"
(declare (pure t) (side-effect-free t))
- (and
- (stringp keys)
- (string-match-p "\\`[^ ]+\\( [^ ]+\\)*\\'" keys)
- (save-match-data
- (catch 'exit
- (let ((prefixes
- "\\(A-\\)?\\(C-\\)?\\(H-\\)?\\(M-\\)?\\(S-\\)?\\(s-\\)?")
- (case-fold-search nil))
- (dolist (key (split-string keys " "))
- ;; Every key might have these modifiers, and they should be
- ;; in this order.
- (when (string-match (concat "\\`" prefixes) key)
- (setq key (substring key (match-end 0))))
- (unless (or (and (= (length key) 1)
- ;; Don't accept control characters as keys.
- (not (< (aref key 0) ?\s))
- ;; Don't accept Meta'd characters as keys.
- (or (multibyte-string-p key)
- (not (<= 127 (aref key 0) 255))))
- (and (string-match-p "\\`<[-_A-Za-z0-9]+>\\'" key)
- ;; Don't allow <M-C-down>.
- (= (progn
- (string-match
- (concat "\\`<" prefixes) key)
- (match-end 0))
- 1))
- (string-match-p
- "\\`\\(NUL\\|RET\\|TAB\\|LFD\\|ESC\\|SPC\\|DEL\\)\\'"
- key))
- ;; Invalid.
- (throw 'exit nil)))
- t)))))
+ (let ((case-fold-search nil))
+ (and
+ (stringp keys)
+ (string-match-p "\\`[^ ]+\\( [^ ]+\\)*\\'" keys)
+ (save-match-data
+ (catch 'exit
+ (let ((prefixes
+ "\\(A-\\)?\\(C-\\)?\\(H-\\)?\\(M-\\)?\\(S-\\)?\\(s-\\)?"))
+ (dolist (key (split-string keys " "))
+ ;; Every key might have these modifiers, and they should be
+ ;; in this order.
+ (when (string-match (concat "\\`" prefixes) key)
+ (setq key (substring key (match-end 0))))
+ (unless (or (and (= (length key) 1)
+ ;; Don't accept control characters as keys.
+ (not (< (aref key 0) ?\s))
+ ;; Don't accept Meta'd characters as keys.
+ (or (multibyte-string-p key)
+ (not (<= 127 (aref key 0) 255))))
+ (and (string-match-p "\\`<[-_A-Za-z0-9]+>\\'" key)
+ ;; Don't allow <M-C-down>.
+ (= (progn
+ (string-match
+ (concat "\\`<" prefixes) key)
+ (match-end 0))
+ 1))
+ (string-match-p
+ "\\`\\(NUL\\|RET\\|TAB\\|LFD\\|ESC\\|SPC\\|DEL\\)\\'"
+ key))
+ ;; Invalid.
+ (throw 'exit nil)))
+ t))))))
(defun key-translate (from to)
"Translate character FROM to TO on the current terminal.
@@ -462,18 +451,19 @@ If MESSAGE (and interactively), message the result."
(keywordp (car args))
(not (eq (car args) :menu)))
(unless (memq (car args) '(:full :keymap :parent :suppress :name :prefix))
- (byte-compile-warn "Invalid keyword: %s" (car args)))
+ (byte-compile-warn-x (car args) "Invalid keyword: %s" (car args)))
(setq args (cdr args))
(when (null args)
- (byte-compile-warn "Uneven number of keywords in %S" form))
+ (byte-compile-warn-x form "Uneven number of keywords in %S" form))
(setq args (cdr args)))
;; Bindings.
(while args
- (let ((key (pop args)))
+ (let* ((wargs args)
+ (key (pop args)))
(when (and (stringp key) (not (key-valid-p key)))
- (byte-compile-warn "Invalid `kbd' syntax: %S" key)))
+ (byte-compile-warn-x wargs "Invalid `kbd' syntax: %S" key)))
(when (null args)
- (byte-compile-warn "Uneven number of key bindings in %S" form))
+ (byte-compile-warn-x form "Uneven number of key bindings in %S" form))
(setq args (cdr args)))
form)
@@ -585,6 +575,11 @@ as the variable documentation string.
(define-keymap ,@(nreverse opts) ,@defs)
,@(and doc (list doc)))))
+(defun make-non-key-event (symbol)
+ "Mark SYMBOL as an event that shouldn't be returned from `where-is'."
+ (put symbol 'non-key-event t)
+ symbol)
+
(provide 'keymap)
;;; keymap.el ends here
diff --git a/lisp/kmacro.el b/lisp/kmacro.el
index 9bbaaa666da..92118ad1433 100644
--- a/lisp/kmacro.el
+++ b/lisp/kmacro.el
@@ -129,7 +129,7 @@ Set to nil if no mouse binding is desired."
(defcustom kmacro-ring-max 8
"Maximum number of keyboard macros to save in macro ring."
- :type 'integer)
+ :type 'natnum)
(defcustom kmacro-execute-before-append t
@@ -164,43 +164,41 @@ macro to be executed before appending to it."
;; Keymap
-(defvar kmacro-keymap
- (let ((map (make-sparse-keymap)))
- ;; Start, end, execute macros
- (define-key map "s" #'kmacro-start-macro)
- (define-key map "\C-s" #'kmacro-start-macro)
- (define-key map "\C-k" #'kmacro-end-or-call-macro-repeat)
- (define-key map "r" #'apply-macro-to-region-lines)
- (define-key map "q" #'kbd-macro-query) ;; Like C-x q
- (define-key map "d" #'kdb-macro-redisplay)
-
- ;; macro ring
- (define-key map "\C-n" #'kmacro-cycle-ring-next)
- (define-key map "\C-p" #'kmacro-cycle-ring-previous)
- (define-key map "\C-v" #'kmacro-view-macro-repeat)
- (define-key map "\C-d" #'kmacro-delete-ring-head)
- (define-key map "\C-t" #'kmacro-swap-ring)
- (define-key map "\C-l" #'kmacro-call-ring-2nd-repeat)
-
- ;; macro counter
- (define-key map "\C-f" #'kmacro-set-format)
- (define-key map "\C-c" #'kmacro-set-counter)
- (define-key map "\C-i" #'kmacro-insert-counter)
- (define-key map "\C-a" #'kmacro-add-counter)
-
- ;; macro editing
- (define-key map "\C-e" #'kmacro-edit-macro-repeat)
- (define-key map "\r" #'kmacro-edit-macro)
- (define-key map "e" #'edit-kbd-macro)
- (define-key map "l" #'kmacro-edit-lossage)
- (define-key map " " #'kmacro-step-edit-macro)
-
- ;; naming and binding
- (define-key map "b" #'kmacro-bind-to-key)
- (define-key map "n" #'kmacro-name-last-macro)
- (define-key map "x" #'kmacro-to-register)
- map)
- "Keymap for keyboard macro commands.")
+(defvar-keymap kmacro-keymap
+ :doc "Keymap for keyboard macro commands."
+ ;; Start, end, execute macros
+ "s" #'kmacro-start-macro
+ "C-s" #'kmacro-start-macro
+ "C-k" #'kmacro-end-or-call-macro-repeat
+ "r" #'apply-macro-to-region-lines
+ "q" #'kbd-macro-query ;; Like C-x q
+ "d" #'kmacro-redisplay
+
+ ;; macro ring
+ "C-n" #'kmacro-cycle-ring-next
+ "C-p" #'kmacro-cycle-ring-previous
+ "C-v" #'kmacro-view-macro-repeat
+ "C-d" #'kmacro-delete-ring-head
+ "C-t" #'kmacro-swap-ring
+ "C-l" #'kmacro-call-ring-2nd-repeat
+
+ ;; macro counter
+ "C-f" #'kmacro-set-format
+ "C-c" #'kmacro-set-counter
+ "C-i" #'kmacro-insert-counter
+ "C-a" #'kmacro-add-counter
+
+ ;; macro editing
+ "C-e" #'kmacro-edit-macro-repeat
+ "RET" #'kmacro-edit-macro
+ "e" #'edit-kbd-macro
+ "l" #'kmacro-edit-lossage
+ "SPC" #'kmacro-step-edit-macro
+
+ ;; naming and binding
+ "b" #'kmacro-bind-to-key
+ "n" #'kmacro-name-last-macro
+ "x" #'kmacro-to-register)
(defalias 'kmacro-keymap kmacro-keymap)
;;; Provide some binding for startup:
@@ -362,9 +360,13 @@ information."
;;; Keyboard macro ring
+(oclosure-define kmacro
+ "Keyboard macro."
+ keys (counter :mutable t) format)
+
(defvar kmacro-ring nil
"The keyboard macro ring.
-Each element is a list (MACRO COUNTER FORMAT). Actually, the head of
+Each element is a `kmacro'. Actually, the head of
the macro ring (when defining or executing) is not stored in the ring;
instead it is available in the variables `last-kbd-macro', `kmacro-counter',
and `kmacro-counter-format'.")
@@ -378,20 +380,23 @@ and `kmacro-counter-format'.")
(defun kmacro-ring-head ()
"Return pseudo head element in macro ring."
(and last-kbd-macro
- (list last-kbd-macro kmacro-counter kmacro-counter-format-start)))
+ (kmacro last-kbd-macro kmacro-counter kmacro-counter-format-start)))
(defun kmacro-push-ring (&optional elt)
"Push ELT or current macro onto `kmacro-ring'."
(when (setq elt (or elt (kmacro-ring-head)))
+ (when (consp elt)
+ (message "Converting obsolete list form of kmacro: %S" elt)
+ (setq elt (apply #'kmacro elt)))
(let ((history-delete-duplicates nil))
(add-to-history 'kmacro-ring elt kmacro-ring-max))))
(defun kmacro-split-ring-element (elt)
- (setq last-kbd-macro (car elt)
- kmacro-counter (nth 1 elt)
- kmacro-counter-format-start (nth 2 elt)))
+ (setq last-kbd-macro (kmacro--keys elt)
+ kmacro-counter (kmacro--counter elt)
+ kmacro-counter-format-start (kmacro--format elt)))
(defun kmacro-pop-ring1 (&optional raw)
@@ -481,21 +486,16 @@ Optional arg EMPTY is message to print if no macros are defined."
;;;###autoload
-(defun kmacro-exec-ring-item (item arg)
+(define-obsolete-function-alias 'kmacro-exec-ring-item #'funcall "29.1"
"Execute item ITEM from the macro ring.
-ARG is the number of times to execute the item."
- ;; Use counter and format specific to the macro on the ring!
- (let ((kmacro-counter (nth 1 item))
- (kmacro-counter-format-start (nth 2 item)))
- (execute-kbd-macro (car item) arg #'kmacro-loop-setup-function)
- (setcar (cdr item) kmacro-counter)))
+ARG is the number of times to execute the item.")
(defun kmacro-call-ring-2nd (arg)
"Execute second keyboard macro in macro ring."
(interactive "P")
(unless (kmacro-ring-empty-p)
- (kmacro-exec-ring-item (car kmacro-ring) arg)))
+ (funcall (car kmacro-ring) arg)))
(defun kmacro-call-ring-2nd-repeat (arg)
@@ -515,7 +515,7 @@ without repeating the prefix."
"Display the second macro in the keyboard macro ring."
(interactive)
(unless (kmacro-ring-empty-p)
- (kmacro-display (car (car kmacro-ring)) nil "2nd macro")))
+ (kmacro-display (kmacro--keys (car kmacro-ring)) nil "2nd macro")))
(defun kmacro-cycle-ring-next (&optional _arg)
@@ -611,8 +611,7 @@ Use \\[kmacro-bind-to-key] to bind it to a key sequence."
(let ((append (and arg (listp arg))))
(unless append
(if last-kbd-macro
- (kmacro-push-ring
- (list last-kbd-macro kmacro-counter kmacro-counter-format-start)))
+ (kmacro-push-ring))
(setq kmacro-counter (or (if arg (prefix-numeric-value arg))
kmacro-initial-counter-value
0)
@@ -748,9 +747,9 @@ With \\[universal-argument], call second macro in macro ring."
(if kmacro-call-repeat-key
(kmacro-call-macro arg no-repeat t)
(kmacro-end-macro arg)))
- ((and (eq this-command 'kmacro-view-macro) ;; We are in repeat mode!
+ ((and (eq this-command #'kmacro-view-macro) ;; We are in repeat mode!
kmacro-view-last-item)
- (kmacro-exec-ring-item (car kmacro-view-last-item) arg))
+ (funcall (car kmacro-view-last-item) arg))
((and arg (listp arg))
(kmacro-call-ring-2nd 1))
(t
@@ -812,46 +811,72 @@ If kbd macro currently being defined end it before activating it."
;; executing the macro later on (but that's controversial...)
;;;###autoload
+(defun kmacro (keys &optional counter format)
+ "Create a `kmacro' for macro bound to symbol or key.
+KEYS should be a vector or a string that obeys `key-valid-p'."
+ (oclosure-lambda (kmacro (keys (if (stringp keys) (key-parse keys) keys))
+ (counter (or counter 0))
+ (format (or format "%d")))
+ (&optional arg)
+ ;; Use counter and format specific to the macro on the ring!
+ (let ((kmacro-counter counter)
+ (kmacro-counter-format-start format))
+ (execute-kbd-macro keys arg #'kmacro-loop-setup-function)
+ (setq counter kmacro-counter))))
+
+(cl-defmethod oclosure-interactive-form ((_ kmacro)) '(interactive "p"))
+
+;;;###autoload
(defun kmacro-lambda-form (mac &optional counter format)
- "Create lambda form for macro bound to symbol or key."
;; Apparently, there are two different ways this is called:
;; either `counter' and `format' are both provided and `mac' is a vector,
;; or only `mac' is provided, as a list (MAC COUNTER FORMAT).
;; The first is used from `insert-kbd-macro' and `edmacro-finish-edit',
;; while the second is used from within this file.
- (let ((mac (if counter (list mac counter format) mac)))
- ;; FIXME: This should be a "funcallable struct"!
- (lambda (&optional arg)
- "Keyboard macro."
- ;; We put an "unused prompt" as a special marker so
- ;; `kmacro-extract-lambda' can see it's "one of us".
- (interactive "pkmacro")
- (if (eq arg 'kmacro--extract-lambda)
- (cons 'kmacro--extract-lambda mac)
- (kmacro-exec-ring-item mac arg)))))
+ (declare (obsolete kmacro "29.1"))
+ (if (kmacro-p mac) mac
+ (when (and (null counter) (consp mac))
+ (setq format (nth 2 mac))
+ (setq counter (nth 1 mac))
+ (setq mac (nth 0 mac)))
+ (when (stringp mac)
+ ;; `kmacro' interprets a string according to `key-parse'.
+ (require 'macros)
+ (declare-function macro--string-to-vector "macros")
+ (setq mac (macro--string-to-vector mac)))
+ (kmacro mac counter format)))
(defun kmacro-extract-lambda (mac)
"Extract kmacro from a kmacro lambda form."
- (let ((mac (cond
- ((eq (car-safe mac) 'lambda)
- (let ((e (assoc 'kmacro-exec-ring-item mac)))
- (car-safe (cdr-safe (car-safe (cdr-safe e))))))
- ((and (functionp mac)
- (equal (interactive-form mac) '(interactive "pkmacro")))
- (let ((r (funcall mac 'kmacro--extract-lambda)))
- (and (eq (car-safe r) 'kmacro--extract-lambda) (cdr r)))))))
- (and (consp mac)
- (= (length mac) 3)
- (arrayp (car mac))
- mac)))
-
-(defalias 'kmacro-p #'kmacro-extract-lambda
- "Return non-nil if MAC is a kmacro keyboard macro.")
+ (declare (obsolete nil "29.1"))
+ (when (kmacro-p mac)
+ (list (kmacro--keys mac)
+ (kmacro--counter mac)
+ (kmacro--format mac))))
+
+(defun kmacro-p (x)
+ "Return non-nil if MAC is a kmacro keyboard macro."
+ (cl-typep x 'kmacro))
+
+(cl-defmethod cl-print-object ((object kmacro) stream)
+ (princ "#f(kmacro " stream)
+ (require 'macros)
+ (declare-function macros--insert-vector-macro "macros" (definition))
+ (let ((vecdef (kmacro--keys object))
+ (counter (kmacro--counter object))
+ (format (kmacro--format object)))
+ (prin1 (key-description vecdef) stream)
+ (unless (and (equal counter 0) (equal format "%d"))
+ (princ " " stream)
+ (prin1 counter stream)
+ (princ " " stream)
+ (prin1 format stream))
+ (princ ")" stream)))
(defun kmacro-bind-to-key (_arg)
"When not defining or executing a macro, offer to bind last macro to a key.
-The key sequences `C-x C-k 0' through `C-x C-k 9' and `C-x C-k A'
-through `C-x C-k Z' are reserved for user bindings, and to bind to
+The key sequences \\`C-x C-k 0' through \\`C-x C-k 9' and \\`C-x C-k A'
+through \\`C-x C-k Z' are reserved for user bindings, and to bind to
one of these sequences, just enter the digit or letter, rather than
the whole sequence.
@@ -884,16 +909,15 @@ The ARG parameter is unused."
(yes-or-no-p (format "%s runs command %S. Bind anyway? "
(format-kbd-macro key-seq)
cmd))))
- (define-key global-map key-seq
- (kmacro-lambda-form (kmacro-ring-head)))
+ (define-key global-map key-seq (kmacro-ring-head))
(message "Keyboard macro bound to %s" (format-kbd-macro key-seq))))))
(defun kmacro-keyboard-macro-p (symbol)
"Return non-nil if SYMBOL is the name of some sort of keyboard macro."
(let ((f (symbol-function symbol)))
(when f
- (or (stringp f)
- (vectorp f)
+ (or (stringp f) ;FIXME: Really deprecated.
+ (vectorp f) ;FIXME: Deprecated.
(kmacro-p f)))))
(defun kmacro-name-last-macro (symbol)
@@ -910,9 +934,7 @@ Such a \"function\" cannot be called from Lisp, but it is a valid editor command
symbol))
(if (string-equal symbol "")
(error "No command name given"))
- ;; FIXME: Use plain old `last-kbd-macro' for kmacros where it doesn't
- ;; make a difference?
- (fset symbol (kmacro-lambda-form (kmacro-ring-head)))
+ (fset symbol (kmacro-ring-head))
;; This used to be used to detect when a symbol corresponds to a kmacro.
;; Nowadays it's unused because we used `kmacro-p' instead to see if the
;; symbol's function definition matches that of a kmacro, which is more
@@ -930,7 +952,7 @@ Such a \"function\" cannot be called from Lisp, but it is a valid editor command
(cl-defmethod register-val-describe ((data kmacro-register) _verbose)
(princ (format "a keyboard macro:\n %s"
- (format-kbd-macro (kmacro-register-macro data)))))
+ (key-description (kmacro-register-macro data)))))
(cl-defmethod register-val-insert ((data kmacro-register))
(insert (format-kbd-macro (kmacro-register-macro data))))
@@ -953,7 +975,7 @@ The ARG parameter is unused."
(interactive)
(cond
((or (kmacro-ring-empty-p)
- (not (eq last-command 'kmacro-view-macro)))
+ (not (eq last-command #'kmacro-view-macro)))
(setq kmacro-view-last-item nil))
((null kmacro-view-last-item)
(setq kmacro-view-last-item kmacro-ring
@@ -963,10 +985,10 @@ The ARG parameter is unused."
kmacro-view-item-no (1+ kmacro-view-item-no)))
(t
(setq kmacro-view-last-item nil)))
- (setq this-command 'kmacro-view-macro
+ (setq this-command #'kmacro-view-macro
last-command this-command) ;; in case we repeat
(kmacro-display (if kmacro-view-last-item
- (car (car kmacro-view-last-item))
+ (kmacro--keys (car kmacro-view-last-item))
last-kbd-macro)
nil
(if kmacro-view-last-item
@@ -980,7 +1002,7 @@ The ARG parameter is unused."
"Display the last keyboard macro.
If repeated, it shows previous elements in the macro ring.
To execute the displayed macro ring item without changing the macro ring,
-just enter C-k.
+just enter \\`C-k'.
This is like `kmacro-view-macro', but allows repeating macro commands
without repeating the prefix."
(interactive)
@@ -1025,34 +1047,30 @@ without repeating the prefix."
(defvar kmacro-step-edit-help) ;; kmacro step edit help enabled
(defvar kmacro-step-edit-num-input-keys) ;; to ignore duplicate pre-command hook
-(defvar kmacro-step-edit-map
- (let ((map (make-sparse-keymap)))
- ;; query-replace-map answers include: `act', `skip', `act-and-show',
- ;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
- ;; `automatic', `backup', `exit-prefix', and `help'.")
- ;; Also: `quit', `edit-replacement'
-
- (set-keymap-parent map query-replace-map)
-
- (define-key map "\t" 'act-repeat)
- (define-key map [tab] 'act-repeat)
- (define-key map "\C-k" 'skip-rest)
- (define-key map "c" 'automatic)
- (define-key map "f" 'skip-keep)
- (define-key map "q" 'quit)
- (define-key map "d" 'skip)
- (define-key map "\C-d" 'skip)
- (define-key map "i" 'insert)
- (define-key map "I" 'insert-1)
- (define-key map "r" 'replace)
- (define-key map "R" 'replace-1)
- (define-key map "a" 'append)
- (define-key map "A" 'append-end)
- map)
- "Keymap that defines the responses to questions in `kmacro-step-edit-macro'.
+(defvar-keymap kmacro-step-edit-map
+ :doc "Keymap that defines the responses to questions in `kmacro-step-edit-macro'.
This keymap is an extension to the `query-replace-map', allowing the
following additional answers: `insert', `insert-1', `replace', `replace-1',
-`append', `append-end', `act-repeat', `skip-end', `skip-keep'.")
+`append', `append-end', `act-repeat', `skip-end', `skip-keep'."
+ ;; query-replace-map answers include: `act', `skip', `act-and-show',
+ ;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
+ ;; `automatic', `backup', `exit-prefix', and `help'.")
+ ;; Also: `quit', `edit-replacement'
+ :parent query-replace-map
+ "TAB" 'act-repeat
+ "<tab>" 'act-repeat
+ "C-k" 'skip-rest
+ "c" 'automatic
+ "f" 'skip-keep
+ "q" 'quit
+ "d" 'skip
+ "C-d" 'skip
+ "i" 'insert
+ "I" 'insert-1
+ "r" 'replace
+ "R" 'replace-1
+ "a" 'append
+ "A" 'append-end)
(defun kmacro-step-edit-prompt (macro index)
;; Show step-edit prompt
@@ -1068,21 +1086,27 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
(concat
(format "Macro: %s%s%s%s%s\n"
(format-kbd-macro kmacro-step-edit-new-macro 1)
- (if (and kmacro-step-edit-new-macro (> (length kmacro-step-edit-new-macro) 0)) " " "")
+ (if (and kmacro-step-edit-new-macro
+ (> (length kmacro-step-edit-new-macro) 0))
+ " " "")
(propertize (if keys (format-kbd-macro keys)
- (if kmacro-step-edit-appending "<APPEND>" "<INSERT>")) 'face 'region)
+ (if kmacro-step-edit-appending
+ "<APPEND>" "<INSERT>"))
+ 'face 'region)
(if future " " "")
(if future (format-kbd-macro future) ""))
(cond
((minibufferp)
(format "%s\n%s\n"
(propertize "\
- minibuffer " 'face 'header-line)
+ minibuffer "
+ 'face 'header-line)
(buffer-substring (point-min) (point-max))))
(curmsg
(format "%s\n%s\n"
(propertize "\
- echo area " 'face 'header-line)
+ echo area "
+ 'face 'header-line)
curmsg))
(t ""))
(if keys
@@ -1113,7 +1137,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
;; Handle commands which reads additional input using read-char.
(cond
- ((and (eq this-command 'quoted-insert)
+ ((and (eq this-command #'quoted-insert)
(not (eq kmacro-step-edit-action t)))
;; Find the actual end of this key sequence.
;; Must be able to backtrack in case we actually execute it.
@@ -1133,7 +1157,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
(cond
((eq kmacro-step-edit-action t) ;; Reentry for actual command @ end of prefix arg.
(cond
- ((eq this-command 'quoted-insert)
+ ((eq this-command #'quoted-insert)
(clear-this-command-keys) ;; recent-keys actually
(let (unread-command-events)
(quoted-insert (prefix-numeric-value current-prefix-arg))
@@ -1177,7 +1201,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
((eq act 'skip)
nil)
((eq act 'skip-keep)
- (setq this-command 'ignore)
+ (setq this-command #'ignore)
t)
((eq act 'skip-rest)
(setq kmacro-step-edit-active 'ignore)
@@ -1227,7 +1251,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
(if restore-index
(setq executing-kbd-macro-index restore-index)))
(t
- (setq this-command 'ignore)))
+ (setq this-command #'ignore)))
(setq kmacro-step-edit-key-index next-index)))
(defun kmacro-step-edit-insert ()
@@ -1271,7 +1295,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
(setq next-index kmacro-step-edit-key-index)
t)
(t nil))
- (setq this-command 'ignore)
+ (setq this-command #'ignore)
(setq this-command cmd)
(if (memq this-command '(self-insert-command digit-argument))
(setq last-command-event (aref keys (1- (length keys)))))
@@ -1284,7 +1308,7 @@ following additional answers: `insert', `insert-1', `replace', `replace-1',
(when kmacro-step-edit-active
(cond
((eq kmacro-step-edit-active 'ignore)
- (setq this-command 'ignore))
+ (setq this-command #'ignore))
((eq kmacro-step-edit-active 'append-end)
(if (= executing-kbd-macro-index (length executing-kbd-macro))
(setq executing-kbd-macro (vconcat executing-kbd-macro [nil])
@@ -1344,12 +1368,12 @@ To customize possible responses, change the \"bindings\" in
(kmacro-push-ring)
(setq last-kbd-macro kmacro-step-edit-new-macro))))
-(defun kdb-macro-redisplay ()
- "Force redisplay during kbd macro execution."
+(defun kmacro-redisplay ()
+ "Force redisplay during keyboard macro execution."
(interactive)
(or executing-kbd-macro
defining-kbd-macro
- (user-error "Not defining or executing kbd macro"))
+ (user-error "Not defining or executing keyboard macro"))
(when executing-kbd-macro
(let ((executing-kbd-macro nil))
(redisplay))))
diff --git a/lisp/language/greek.el b/lisp/language/greek.el
index 58f4fe6fc49..920cf67d871 100644
--- a/lisp/language/greek.el
+++ b/lisp/language/greek.el
@@ -79,7 +79,9 @@
(coding-priority greek-iso-8bit)
(nonascii-translation . iso-8859-7)
(input-method . "greek")
- (documentation . t)))
+ (documentation . "Support for Greek ISO-8859-7 using the greek input method.")
+ (sample-text . "Greek (ελληνικά) Γειά σας")
+ (tutorial . "TUTORIAL.el_GR")))
(provide 'greek)
diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el
index 8b1c3d69ae5..27facaa858f 100644
--- a/lisp/language/ind-util.el
+++ b/lisp/language/ind-util.el
@@ -267,11 +267,34 @@
?த nil nil nil ?ந ?ன ;; DENTALS
?ப nil nil nil ?ம ;; LABIALS
?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS
- nil ?ஷ ?ஸ ?ஹ ;; SIBILANTS
+ ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS
nil nil nil nil nil nil nil nil ;; NUKTAS
- "ஜ்ஞ" "க்ஷ")
+ "ஜ்ஞ" "க்ஷ" "க்‌ஷ")
(;; Misc Symbols
- nil ?ஂ ?ஃ nil ?் nil nil)
+ nil ?ஂ ?ஃ nil ?் ?ௐ nil)
+ (;; Digits
+ nil nil nil nil nil nil nil nil nil nil)
+ (;; Inscript-extra (4) (#, $, ^, *, ])
+ "்ர" "ர்" "த்ர" nil nil)))
+
+(defvar indian-tml-base-digits-table
+ '(
+ (;; VOWELS
+ (?அ nil) (?ஆ ?ா) (?இ ?ி) (?ஈ ?ீ) (?உ ?ு) (?ஊ ?ூ)
+ nil nil nil (?ஏ ?ே) (?எ ?ெ) (?ஐ ?ை)
+ nil (?ஓ ?ோ) (?ஒ ?ொ) (?ஔ ?ௌ) nil nil)
+ (;; CONSONANTS
+ ?க nil nil nil ?ங ;; GUTTRULS
+ ?ச nil ?ஜ nil ?ஞ ;; PALATALS
+ ?ட nil nil nil ?ண ;; CEREBRALS
+ ?த nil nil nil ?ந ?ன ;; DENTALS
+ ?ப nil nil nil ?ம ;; LABIALS
+ ?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS
+ ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS
+ nil nil nil nil nil nil nil nil ;; NUKTAS
+ "ஜ்ஞ" "க்ஷ" "க்‌ஷ")
+ (;; Misc Symbols
+ nil ?ஂ ?ஃ nil ?் ?ௐ nil)
(;; Digits
?௦ ?௧ ?௨ ?௩ ?௪ ?௫ ?௬ ?௭ ?௮ ?௯)
(;; Inscript-extra (4) (#, $, ^, *, ])
@@ -292,8 +315,8 @@
'(;; for encode/decode
(;; vowels -- 18
"a" ("aa" "A") "i" ("ii" "I") "u" ("uu" "U")
- ("RRi" "R^i") ("LLi" "L^i") (".c" "e.c") "E" "e" "ai"
- "o.c" "O" "o" "au" ("RRI" "R^I") ("LLI" "L^I"))
+ ("RRi" "R^i" "RRu" "R^u") ("LLi" "L^i") (".c" "e.c") "E" "e" "ai"
+ "o.c" "O" "o" "au" ("RRI" "R^I" "RRU" "R^U") ("LLI" "L^I"))
(;; consonants -- 40
"k" "kh" "g" "gh" ("~N" "N^")
"ch" ("Ch" "chh") "j" "jh" ("~n" "JN")
@@ -557,6 +580,10 @@
(defvar indian-tml-itrans-v5-hash
(indian-make-hash indian-tml-base-table
indian-itrans-v5-table-for-tamil))
+
+(defvar indian-tml-itrans-digits-v5-hash
+ (indian-make-hash indian-tml-base-digits-table
+ indian-itrans-v5-table-for-tamil))
)
(defmacro indian-translate-region (from to hashtable encode-p)
diff --git a/lisp/language/indian.el b/lisp/language/indian.el
index 614d0767e72..2887d410adf 100644
--- a/lisp/language/indian.el
+++ b/lisp/language/indian.el
@@ -45,8 +45,9 @@
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "devanagari-aiba")
+ (sample-text . "Devanagari (देवनागरी) नमस्ते / नमस्कार")
(documentation . "\
-Such languages using Devanagari script as Hindi and Marathi
+Such languages using Devanagari script as Hindi, Marathi and Nepali
are supported in this language environment."))
'("Indian"))
@@ -55,16 +56,18 @@ are supported in this language environment."))
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "bengali-itrans")
+ (sample-text . "Bengali (বাংলা) নমস্কার")
(documentation . "\
Such languages using Bengali script as Bengali and Assamese
are supported in this language environment."))
'("Indian"))
(set-language-info-alist
- "Punjabi" '((charset unicode)
+ "Gurmukhi" '((charset unicode)
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "punjabi-itrans")
+ (sample-text . "Gurmukhi (ਗੁਰਮੁਖੀ) ਸਤ ਸ੍ਰੀ ਅਕਾਲ")
(documentation . "\
North Indian language Punjabi is supported in this language environment."))
'("Indian"))
@@ -74,17 +77,31 @@ North Indian language Punjabi is supported in this language environment."))
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "gujarati-itrans")
+ (sample-text . "Gujarati (ગુજરાતી) નમસ્તે")
(documentation . "\
North Indian language Gujarati is supported in this language environment."))
'("Indian"))
(set-language-info-alist
+ "Odia" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "odia")
+ (sample-text . "Odia (ଓଡ଼ିଆ) ନମସ୍କାର")
+ (documentation . "\
+Such languages using the Odia script as Odia, Khonti, and Santali
+are supported in this language environment. (This language
+environment was formerly known as \"Oriya\")."))
+ '("Indian"))
+
+(set-language-info-alist
"Oriya" '((charset unicode)
- (coding-system utf-8)
- (coding-priority utf-8)
- (input-method . "oriya-itrans")
- (documentation . "\
-Such languages using Oriya script as Oriya, Khonti, and Santali
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "odia")
+ (sample-text . "Odia (ଓଡ଼ିଆ) ନମସ୍କାର")
+ (documentation . "\
+Such languages using the Odia script as Odia, Khonti, and Santali
are supported in this language environment."))
'("Indian"))
@@ -93,6 +110,7 @@ are supported in this language environment."))
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "tamil-itrans")
+ (sample-text . "Tamil (தமிழ்) வணக்கம்")
(documentation . "\
South Indian Language Tamil is supported in this language environment."))
'("Indian"))
@@ -102,6 +120,7 @@ South Indian Language Tamil is supported in this language environment."))
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "telugu-itrans")
+ (sample-text . "Telugu (తెలుగు) నమస్కారం")
(documentation . "\
South Indian Language Telugu is supported in this language environment."))
'("Indian"))
@@ -113,7 +132,7 @@ South Indian Language Telugu is supported in this language environment."))
(input-method . "kannada-itrans")
(sample-text . "Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ")
(documentation . "\
-Kannada language and script is supported in this language
+Kannada language and script are supported in this language
environment."))
'("Indian"))
@@ -122,10 +141,131 @@ environment."))
(coding-system utf-8)
(coding-priority utf-8)
(input-method . "malayalam-itrans")
+ (sample-text . "Malayalam (മലയാളം) നമസ്കാരം")
(documentation . "\
South Indian language Malayalam is supported in this language environment."))
'("Indian"))
+(set-language-info-alist
+ "Brahmi" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "brahmi")
+ (sample-text . "Brahmi (𑀩𑁆𑀭𑀸𑀳𑁆𑀫𑀻) 𑀦𑀫𑀲𑁆𑀢𑁂")
+ (documentation . "\
+The ancient Brahmi script is supported in this language environment."))
+ '("Indian")) ; Should we have an "Old" category?
+
+(set-language-info-alist
+ "Kaithi" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "kaithi")
+ (sample-text . "Kaithi (𑂍𑂶𑂟𑂲) 𑂩𑂰𑂧𑂩𑂰𑂧")
+ (documentation . "\
+Languages such as Awadhi, Bhojpuri, Magahi and Maithili
+which used the Kaithi script are supported in this language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Tirhuta" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "tirhuta")
+ (sample-text . "Tirhuta (𑒞𑒱𑒩𑒯𑒳𑒞𑒰) 𑒣𑓂𑒩𑒢𑒰𑒧 / 𑒮𑒲𑒞𑒰𑒩𑒰𑒧")
+ (documentation . "\
+Maithili language and its script Tirhuta are supported in this
+language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Sharada" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "sharada")
+ (sample-text . "Sharada (𑆯𑆳𑆫𑆢𑆳) 𑆤𑆩𑆱𑇀𑆑𑆳𑆫")
+ (documentation . "\
+Kashmiri language and its script Sharada are supported in this
+language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Siddham" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "siddham")
+ (sample-text . "Siddham (𑖭𑖰𑖟𑖿𑖠𑖽) 𑖡𑖦𑖭𑖿𑖝𑖸")
+ (documentation . "\
+Sanskrit language and one of its script Siddham are supported
+in this language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Syloti Nagri" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "syloti-nagri")
+ (sample-text . "Syloti Nagri (ꠍꠤꠟꠐꠤ ꠘꠣꠉꠞꠤ) ꠀꠌ꠆ꠍꠣꠟꠣꠝꠥ ꠀꠟꠣꠁꠇꠥꠝ / ꠘꠝꠡ꠆ꠇꠣꠞ")
+ (documentation . "\
+Sylheti language and its script Syloti Nagri are supported
+in this language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Modi" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "modi")
+ (sample-text . "Modi (𑘦𑘻𑘚𑘲) 𑘡𑘦𑘭𑘿𑘎𑘰𑘨")
+ (documentation . "\
+Marathi language and one of its script Modi are supported
+in this language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Limbu" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "limbu")
+ (sample-text . "Limbu (ᤕᤠᤰᤌᤢᤱ ᤐᤠᤴ) ᤛᤣᤘᤠᤖᤥ")
+ (documentation . "\
+Limbu language and its script are supported in this
+language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Grantha" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "grantha")
+ (sample-text . "Grantha (𑌗𑍍𑌰𑌨𑍍𑌥) 𑌨𑌮𑌸𑍍𑌤𑍇 / 𑌨𑌮𑌸𑍍𑌕𑌾𑌰𑌃")
+ (documentation . "\
+Languages such as Sanskrit and Manipravalam, when they use the
+Grantha script, are supported in this language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Lepcha" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "lepcha")
+ (sample-text . "Lepcha (ᰛᰩᰵᰛᰧᰵᰶ) ᰂᰦᰕᰥᰬ")
+ (documentation . "\
+Lepcha language and its script are supported in this
+language environment."))
+ '("Indian"))
+
+(set-language-info-alist
+ "Meetei Mayek" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "meetei-mayek")
+ (sample-text . "Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ")
+ (documentation . "\
+Meetei language and its script Meetei Mayek are supported in this
+language environment."))
+ '("Indian"))
+
;; Replace mnemonic characters in REGEXP according to TABLE. TABLE is
;; an alist of (MNEMONIC-STRING . REPLACEMENT-STRING).
@@ -147,6 +287,8 @@ South Indian language Malayalam is supported in this language environment."))
("H" . "\u094D") ; HALANT
("s" . "[\u0951\u0952]") ; stress sign
("t" . "[\u0953\u0954]") ; accent
+ ("1" . "\u0967") ; numeral 1
+ ("3" . "\u0969") ; numeral 3
("N" . "\u200C") ; ZWNJ
("J" . "\u200D") ; ZWJ
("X" . "[\u0900-\u097F]")))) ; all coverage
@@ -158,6 +300,8 @@ South Indian language Malayalam is supported in this language environment."))
"Cn?\\(?:J?HJ?Cn?\\)*\\(?:H[NJ]?\\|v*n?a?s?t?A?\\)\\|"
;; special consonant form, or
"JHR\\|"
+ ;; vedic accents with numerals, or
+ "1ss?\\|3ss\\|s3ss\\|"
;; any other singleton characters
"X")
table))
@@ -168,14 +312,15 @@ South Indian language Malayalam is supported in this language environment."))
'(("a" . "\u0981") ; SIGN CANDRABINDU
("A" . "[\u0982\u0983]") ; SIGN ANUSVARA .. VISARGA
("V" . "[\u0985-\u0994\u09E0\u09E1]") ; independent vowel
- ("C" . "[\u0995-\u09B9\u09DC-\u09DF\u09F1]") ; consonant
+ ("C" . "[\u0995-\u09B9\u09DC-\u09DF\u09F0\u09F1]") ; consonant
("B" . "[\u09AC\u09AF\u09B0\u09F0]") ; BA, YA, RA
("R" . "[\u09B0\u09F0]") ; RA
("n" . "\u09BC") ; NUKTA
("v" . "[\u09BE-\u09CC\u09D7\u09E2\u09E3]") ; vowel sign
("H" . "\u09CD") ; HALANT
("T" . "\u09CE") ; KHANDA TA
- ("N" . "\u200C") ; ZWNJ
+ ("S" . "\u09FE") ; SANDHI MARK
+ ("N" . "\u200C") ; ZWNJ
("J" . "\u200D") ; ZWJ
("X" . "[\u0980-\u09FF]")))) ; all coverage
(indian-compose-regexp
@@ -183,7 +328,7 @@ South Indian language Malayalam is supported in this language environment."))
;; syllables with an independent vowel, or
"\\(?:RH\\)?Vn?\\(?:J?HB\\)?v*n?a?A?\\|"
;; consonant-based syllables, or
- "Cn?\\(?:J?HJ?Cn?\\)*\\(?:H[NJ]?\\|v*[NJ]?v?a?A?\\)\\|"
+ "Cn?\\(?:J?HJ?Cn?\\)*\\(?:H[NJ]?\\|v*[NJ]?v?a?A?S?\\)\\|"
;; another syllables with an independent vowel, or
"\\(?:RH\\)?T\\|"
;; special consonant form, or
@@ -250,7 +395,7 @@ South Indian language Malayalam is supported in this language environment."))
'(("a" . "\u0B01") ; SIGN CANDRABINDU
("A" . "[\u0B02\u0B03]") ; SIGN ANUSVARA .. VISARGA
("V" . "[\u0B05-\u0B14\u0B60\u0B61]") ; independent vowel
- ("C" . "[\u0B15-\u0B39\u0B5C\u0B5D\u0B71]") ; consonant
+ ("C" . "[\u0B15-\u0B39\u0B5C\u0B5D\u0B5F\u0B71]") ; consonant
("B" . "[\u0B15-\u0B17\u0B1B-\u0B1D\u0B1F-\u0B21\u0B23\u0B24\u0B27-\u0B30\u0B32-\u0B35\u0B38\u0B39]") ; consonant with below form
("R" . "\u0B30") ; RA
("n" . "\u0B3C") ; NUKTA
@@ -354,14 +499,14 @@ South Indian language Malayalam is supported in this language environment."))
("X" . "[\u0D00-\u0D7F]")))) ; all coverage
(indian-compose-regexp
(concat
+ ;; any sequence of 2 or more Malayalam characters, or
+ "XX+\\|"
;; consonant-based syllables, or
"C\\(?:J?HJ?C\\)*\\(?:H[NJ]?\\|v?A?\\)\\|"
;; syllables with an independent vowel, or
"V\\(?:J?HY\\)?v*?A?\\|"
- ;; special consonant form, or
- "JHY\\|"
- ;; any other singleton characters
- "X")
+ ;; special consonant form
+ "JHY")
table))
"Regexp matching a composable sequence of Malayalam characters.")
@@ -384,6 +529,263 @@ South Indian language Malayalam is supported in this language environment."))
(list (vector (cdr slot) 0 #'font-shape-gstring))))))
char-script-table))
-(provide 'indian)
+;; Brahmi composition rules
+(let ((consonant "[\U00011013-\U00011034]")
+ (non-consonant "[^\U00011013-\U00011034\U00011046\U0001107F]")
+ (vowel "[\U00011038-\U00011045]")
+ (numeral "[\U00011052-\U00011065]")
+ (multiplier "[\U00011064\U00011065]")
+ (virama "\U00011046")
+ (number-joiner "\U0001107F"))
+ (set-char-table-range composition-function-table
+ '(#x11046 . #x11046)
+ (list (vector
+ ;; Consonant conjuncts
+ (concat consonant "\\(?:" virama consonant "\\)+"
+ vowel "?")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowelless consonants
+ (concat consonant virama non-consonant)
+ 1 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#x1107F . #x1107F)
+ (list (vector
+ ;; Additive-multiplicative numerals
+ (concat multiplier number-joiner numeral)
+ 1 'font-shape-gstring))))
+
+;; Kaithi composition rules
+(let ((consonant "[\x1108D-\x110AF]")
+ (nukta "\x110BA")
+ (independent-vowel "[\x11083-\x1108C]")
+ (vowel "[\x1108D-\x110C2]")
+ (nasal "[\x11080\x11081]")
+ (virama "\x110B9")
+ (number-sign "\x110BD")
+ (number-sign-above "\x110CD")
+ (numerals "[\x966-\x96F]+")
+ (zwj "\x200D"))
+ (set-char-table-range composition-function-table
+ '(#x110B0 . #x110BA)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant nukta "?\\(?:" virama zwj "?" consonant
+ nukta "?\\)*\\(?:" virama zwj "?\\|" vowel "*" nukta
+ "?" nasal "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowel based syllables
+ (concat independent-vowel nukta "?" virama "?" vowel "?")
+ 1 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#x110BD . #x110BD)
+ (list (vector
+ ;; Number sign
+ (concat number-sign numerals)
+ 0 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#x110CD . #x110CD)
+ (list (vector
+ ;; Number sign above
+ (concat number-sign-above numerals)
+ 0 'font-shape-gstring))))
+
+;; Tirhuta composition rules
+(let ((consonant "[\x1148F-\x114AF]")
+ (nukta "\x114C3")
+ (independent-vowel "[\x11481-\x1148E]")
+ (vowel "[\x114B0-\x114BE]")
+ (nasal "[\x114BF\x114C0]")
+ (virama "\x114C2"))
+ (set-char-table-range composition-function-table
+ '(#x114B0 . #x114C3)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant nukta "?\\(?:" virama consonant nukta
+ "?\\)*\\(?:" virama "\\|" vowel "*" nukta "?"
+ nasal "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowel based syllables
+ (concat independent-vowel nukta "?" virama "?" vowel "?" nasal "?")
+ 1 'font-shape-gstring))))
+
+;; Sharada composition rules
+(let ((consonant "[\x11191-\x111B2]")
+ (nukta "\x111CA")
+ (independent-vowel "[\x11183-\x11190]")
+ (vowel "[\x111B3-\x111BF\x111CE]")
+ (vowel-modifier "\x111CB")
+ (extra-short-vowel-mark "\x111CC")
+ (nasal "[\x11181\x11180\x111CF]")
+ (virama "\x111C0")
+ (fricatives "[\x111C2\x111C3]")
+ (sandhi-mark "\x111C9")
+ (misc "[\x111C4-\x111C8\x111CD]"))
+ (set-char-table-range composition-function-table
+ '(#x111B3 . #x111CE)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant nukta "?" vowel-modifier "?\\(?:" virama
+ consonant nukta "?" vowel-modifier "?\\)*\\(?:" virama
+ "\\|" vowel "*" nukta "?" nasal "?" extra-short-vowel-mark
+ "?" vowel-modifier "?" sandhi-mark "?+" misc "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowel based syllables
+ (concat independent-vowel nukta "?" vowel-modifier "?" virama "?"
+ vowel "?" extra-short-vowel-mark "?" sandhi-mark "?"
+ fricatives "?" misc "?")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Fricatives with Consonants
+ (concat fricatives "?" consonant vowel "?")
+ 0 'font-shape-gstring))))
+
+;; Siddham composition rules
+(let ((consonant "[\x1158E-\x115AE]")
+ (nukta "\x115C0")
+ (independent-vowel "[\x11580-\x1158D\x115D8-\x115DB]")
+ (vowel "[\x115AF-\x115BB\x115DC\x115DD]")
+ (nasal "[\x115BC\x115BD]")
+ (visarga "\x115BE")
+ (virama "\x115BF"))
+ (set-char-table-range composition-function-table
+ '(#x115AF . #x115C0)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant nukta "?" "\\(?:" virama consonant nukta
+ "?\\)*\\(?:" virama "\\|" vowel "*" nukta "?" nasal
+ "?" visarga "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel nukta "?" virama "?" vowel "?"
+ nasal "?" visarga "?")
+ 1 'font-shape-gstring))))
+
+;; Syloti Nagri composition rules
+(let ((consonant "[\xA807-\xA80A\xA80C-\xA822]")
+ (vowel "[\xA802\xA823-\xA827]")
+ (nasal "[\xA80B]")
+ (virama "\xA806")
+ (alternate-virama "\xA82C"))
+ (set-char-table-range composition-function-table
+ '(#xA806 . #xA806)
+ (list (vector
+ ;; Consonant conjunct based syllables
+ (concat consonant "\\(?:" virama consonant "\\)+"
+ vowel "?" nasal "?")
+ 1 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#xA823 . #xA827)
+ (list (vector
+ ;; Non Consonant conjunct based syllables
+ (concat consonant vowel nasal "?")
+ 1 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#xA82C . #xA82C)
+ (list (vector
+ ;; Consonant with the alternate virama
+ (concat consonant "\\(?:" alternate-virama consonant "\\)+"
+ vowel "?" nasal "?")
+ 1 'font-shape-gstring))))
+
+;; Modi composition rules
+(let ((consonant "[\x1160E-\x1162F]")
+ (independent-vowel "[\x11600-\x1160D]")
+ (vowel "[\x11630-\x1163C]")
+ (nasal "\x1163D")
+ (visarga "\x1163E")
+ (virama "\x1163F")
+ (ardhacandra "\x11640"))
+ (set-char-table-range composition-function-table
+ '(#x11630 . #x11640)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant "\\(?:" virama consonant "\\)*\\(?:"
+ virama "\\|" vowel "*" ardhacandra "?" nasal
+ "?" visarga "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel virama "?" vowel "?" ardhacandra
+ nasal "?" visarga "?")
+ 1 'font-shape-gstring))))
+
+;; Limbu composition rules
+(let ((consonant "[\x1900-\x191E]")
+ (vowel "[\x1920-\x1928]")
+ (subjoined-letter "[\x1929-\x192B]")
+ (small-letter "[\x1930-\x1938]")
+ (other-signs "[\x1939\x193A]")
+ (sa-i "\x193B"))
+ (set-char-table-range composition-function-table
+ '(#x1920 . #x193B)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant sa-i "?" subjoined-letter "?" small-letter
+ "?" vowel "?" other-signs "?")
+ 1 'font-shape-gstring))))
+
+;; Grantha composition rules
+(let ((consonant "[\x11315-\x11339]")
+ (nukta "\x1133C")
+ (independent-vowel "[\x11305-\x11314\x11360\x11361]")
+ (vowel "[\x1133E-\x1134C\x11357\x11362\x11363]")
+ (nasal "[\x11300-\x11302]")
+ (bindu "\x1133B")
+ (visarga "\x11303")
+ (virama "\x1134D")
+ (avagraha "\x1133D")
+ (modifier-above "[\x11366-\x11374]"))
+ (set-char-table-range composition-function-table
+ '(#x1133B . #x1134D)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant nukta "?" "\\(?:" virama consonant nukta
+ "?\\)*\\(?:" virama "\\|" vowel "*" nukta "?" nasal
+ "?" bindu "?" visarga "?" modifier-above "?"
+ avagraha "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel nukta "?" virama "?" vowel "?"
+ nasal "?" bindu "?" visarga "?" modifier-above
+ "?" avagraha "?")
+ 1 'font-shape-gstring))))
+
+;; Lepcha composition rules
+(let ((consonant "[\x1C00-\x1C23\x1C4D-\x1C4F]")
+ (vowel "[\x1C26-\x1C2C]")
+ (subjoined-letter "[\x1C24\x1C25]")
+ (consonant-sign "[\x1C2D-\x1C35]")
+ (other-signs "[\x1C36\x1C37]"))
+ (set-char-table-range composition-function-table
+ '(#x1C24 . #x1C37)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant other-signs "?" vowel "?"
+ consonant-sign "?" subjoined-letter "?"
+ other-signs "?")
+ 1 'font-shape-gstring))))
+
+;; Meetei Mayek composition rules
+(let ((akshara "[\xABC0-\xABE2\xAAE0-\xAAEA]")
+ (vowel "[\xABE3-\xABE9\xAAEB-\xAAEC]")
+ (nasal "\xABEA")
+ (visarga "\xAAF5")
+ (virama "[\xABED\xAAF6]")
+ (heavy-tone "\x11640"))
+ (set-char-table-range composition-function-table
+ '(#xABE3 . #xABED)
+ (list (vector
+ ;; Consonant based syllables
+ (concat akshara "\\(?:" virama akshara "\\)*\\(?:"
+ virama "\\|" vowel "*" nasal "?" visarga "?"
+ heavy-tone "?\\)")
+ 1 'font-shape-gstring))))
+(provide 'indian)
;;; indian.el ends here
diff --git a/lisp/language/indonesian.el b/lisp/language/indonesian.el
new file mode 100644
index 00000000000..699f8192543
--- /dev/null
+++ b/lisp/language/indonesian.el
@@ -0,0 +1,197 @@
+;;; indonesian.el --- Indonesian languages support -*- coding: utf-8; lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
+;; Keywords: multilingual, input method, i18n, Indonesia
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains definitions of Indonesia language environments, and
+;; setups for displaying the scripts used there.
+
+;;; Code:
+
+(set-language-info-alist
+ "Balinese" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "balinese")
+ (sample-text . "Balinese (ᬅᬓ᭄ᬱᬭᬩᬮᬶ) ᬒᬁᬲ᭄ᬯᬲ᭄ᬢ᭄ᬬᬲ᭄ᬢᬸ")
+ (documentation . "\
+Balinese language and its script are supported in this language environment.")))
+
+(set-language-info-alist
+ "Javanese" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "javanese")
+ (sample-text . "Javanese (ꦲꦏ꧀ꦱꦫꦗꦮ) ꦲꦭꦺꦴ")
+ (documentation . "\
+Javanese language and its script are supported in this language environment.")))
+
+(set-language-info-alist
+ "Sundanese" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "sundanese")
+ (sample-text . "Sundanese (ᮃᮊ᮪ᮞᮛᮞᮥᮔ᮪ᮓ) ᮞᮙ᮪ᮕᮥᮛᮞᮥᮔ᮪")
+ (documentation . "\
+Sundanese language and its script are supported in this language environment.")))
+
+(set-language-info-alist
+ "Batak" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "batak")
+ (sample-text . "Batak (ᯘᯮᯒᯗ᯲ᯅᯗᯂ᯲) ᯂᯬᯒᯘ᯲ / ᯔᯧᯐᯬᯀᯱᯐᯬᯀᯱ")
+ (documentation . "\
+Languages that use the Batak script, such as Karo, Toba, Pakpak, Mandailing
+and Simalungun, are supported in this language environment.")))
+
+(set-language-info-alist
+ "Rejang" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "rejang")
+ (sample-text . "Rejang (ꥆꤰ꥓ꤼꤽ ꤽꥍꤺꥏ) ꤸꥉꥐꤺꥉꥂꥎ")
+ (documentation . "\
+Rejang language and its script are supported in this language environment.")))
+
+(set-language-info-alist
+ "Makasar" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "makasar")
+ (sample-text . "Makasar (𑻪𑻢𑻪𑻢) 𑻦𑻤𑻵𑻱")
+ (documentation . "\
+Makassarese language and its script Makasar are supported in this language environment.")))
+
+(set-language-info-alist
+ "Buginese" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "lontara")
+ (sample-text . "Buginese (ᨒᨚᨈᨑ) ᨖᨒᨚ")
+ (documentation . "\
+Buginese language and its script Lontara are supported in this language environment.")))
+
+;; Balinese composition rules
+(let ((consonant "[\x1B13-\x1B33\x1B45-\x1B4B]")
+ (independent-vowel "[\x1B05-\x1B12]")
+ (rerekan "\x1B34")
+ (vowel "[\x1B35-\x1B43]")
+ (modifier-above "[\x1B00-\x1B04]")
+ (adeg-adeg "\x1B44")
+ (musical-symbol "[\x1B6B-\x1B73]"))
+ (set-char-table-range composition-function-table
+ '(#x1B34 . #x1B44)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant rerekan "?\\(?:" adeg-adeg consonant
+ rerekan "?\\)*\\(?:" adeg-adeg "\\|" vowel "*" rerekan
+ "?" modifier-above "?" musical-symbol "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel rerekan "?" adeg-adeg "?"
+ vowel "?" modifier-above "?" musical-symbol "?")
+ 1 'font-shape-gstring))))
+
+;; Javanese composition rules
+(let ((consonant "[\xA98F-\xA9B2]")
+ (independent-vowel "[\xA984-\xA98E]")
+ (telu "\xA9B3")
+ (vowel "[\xA9B4-\xA9BC]")
+ (dependant-consonant "[\xA9BD-\xA9BF]")
+ (modifier-above "[\xA980-\xA983]")
+ (pangkon "\xA9C0"))
+ (set-char-table-range composition-function-table
+ '(#xA9B3 . #xA9C0)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant telu "?\\(?:" pangkon consonant
+ telu "?\\)*\\(?:" pangkon "\\|" vowel "*" telu
+ "?" modifier-above "?" dependant-consonant "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel telu "?" pangkon "?"
+ vowel "?" modifier-above "?" dependant-consonant "?")
+ 1 'font-shape-gstring))))
+
+;; Sundanese composition rules
+(let ((consonant "[\x1B8A-\x1BA0\x1BAE\x1BAF\x1BBB-\x1BBF]")
+ (independent-vowel "[\x1B83-\x1B89]")
+ (vowel "[\x1BA4-\x1BA9]")
+ (dependant-consonant "[\x1BA1-\x1BA3\x1BAC-\x1BAD]")
+ (modifier-above "[\x1B80-\x1B82]")
+ (virama "[\x1BAA\x1BAB]"))
+ (set-char-table-range composition-function-table
+ '(#x1BA1 . #x1BAD)
+ (list (vector
+ ;; Consonant based syllables
+ (concat consonant "\\(?:" virama consonant
+ "\\)*\\(?:" virama "\\|" vowel "*"
+ modifier-above "?" dependant-consonant "?\\)")
+ 1 'font-shape-gstring)
+ (vector
+ ;; Vowels based syllables
+ (concat independent-vowel virama "?"
+ vowel "?" modifier-above "?" dependant-consonant "?")
+ 1 'font-shape-gstring))))
+
+;; Batak composition rules
+(let ((akshara "[\x1BC0-\x1BE5]")
+ (vowel "[\x1BE7-\x1BEF]")
+ (dependant-consonant "[\x1BF0\x1BF1]")
+ (modifier-above "\x1BE6")
+ (virama "[\x1BF2\x1BF3]"))
+ (set-char-table-range composition-function-table
+ '(#x1BE6 . #x1BF3)
+ (list (vector
+ ;; Akshara based syllables
+ (concat akshara virama "?" vowel "*" modifier-above
+ "?" dependant-consonant "?")
+ 1 'font-shape-gstring))))
+
+;; Rejang composition rules
+(let ((akshara "[\xA930-\xA946]")
+ (vowel "[\xA947-\xA94E]")
+ (dependant-consonant "[\xA94F\xA952]")
+ (virama "\xA953"))
+ (set-char-table-range composition-function-table
+ '(#xA947 . #xA953)
+ (list (vector
+ ;; Akshara based syllables
+ (concat akshara virama "?" vowel "*"
+ dependant-consonant "?")
+ 1 'font-shape-gstring))))
+
+;; Makasar composition rules
+(let ((akshara "[\x11EE0-\x11EF2]")
+ (vowel "[\x11EF3-\x11EF6]"))
+ (set-char-table-range composition-function-table
+ '(#x11EF3 . #x11EF6)
+ (list (vector
+ ;; Akshara based syllables
+ (concat akshara vowel "*")
+ 1 'font-shape-gstring))))
+
+(provide 'indonesian)
+;;; indonesian.el ends here
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index c8a4821abf7..1e915c2f838 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -1,5 +1,6 @@
;;; misc-lang.el --- support for miscellaneous languages (characters) -*- lexical-binding: t; -*-
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -212,6 +213,59 @@ thin (i.e. 1-dot width) space."
(list (vector "[\U00013000-\U0001342E]+"
0 #'font-shape-gstring))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Hanifi Rohingya
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(set-language-info-alist
+ "Hanifi Rohingya" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "hanifi-rohingya")
+ (sample-text . "Hanifi Rohingya (𐴌𐴟𐴇𐴥𐴝𐴚𐴒𐴙𐴝 𐴇𐴝𐴕𐴞𐴉𐴞 𐴓𐴠𐴑𐴤𐴝) 𐴀𐴝𐴏𐴓𐴝𐴀𐴡𐴤𐴛𐴝𐴓𐴝𐴙𐴑𐴟𐴔")
+ (documentation . "\
+Rohingya language and its script Hanifi Rohingya are supported
+in this language environment.")))
+
+;; Hanifi Rohingya composition rules
+(set-char-table-range
+ composition-function-table
+ '(#x10D1D . #x10D27)
+ (list (vector
+ "[\x10D00-\x10D27]+"
+ 1 'font-shape-gstring)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Kharoṣṭhī
+;; Author: Stefan Baums <baums@gandhari.org>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(set-language-info-alist
+ "Kharoshthi" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "kharoshthi")
+ (sample-text . "Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁")
+ (documentation . "\
+Language environment for Gāndhārī, Sanskrit, and other languages
+using the Kharoṣṭhī script.")))
+
+(let ((consonant "[\U00010A00\U00010A10-\U00010A35]")
+ (vowel "[\U00010A01-\U00010A06]")
+ (virama "\U00010A3F")
+ (modifier "[\U00010A0C-\U00010A0F\U00010A38-\U00010A3A]"))
+ (set-char-table-range composition-function-table
+ '(#x10A3F . #x10A3F)
+ (list
+ (vector
+ (concat consonant
+ "\\(?:" virama consonant "\\)*"
+ modifier "*"
+ virama "?"
+ vowel "*"
+ modifier "*")
+ 1 'font-shape-gstring))))
+
(provide 'misc-lang)
;;; misc-lang.el ends here
diff --git a/lisp/language/philippine.el b/lisp/language/philippine.el
new file mode 100644
index 00000000000..e52ad6912cd
--- /dev/null
+++ b/lisp/language/philippine.el
@@ -0,0 +1,96 @@
+;;; philippine.el --- Philippine languages support -*- coding: utf-8; lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
+;; Keywords: multilingual, input method, i18n, Philippines
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains definitions of Philippine language environments, and
+;; setups for displaying the scripts used there.
+
+;;; Code:
+
+(set-language-info-alist
+ "Tagalog" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "tagalog")
+ (sample-text . "Tagalog (ᜊᜌ᜔ᜊᜌᜒᜈ᜔) ᜃᜓᜋᜓᜐ᜔ᜆ")
+ (documentation . "\
+Tagalog language using the Baybayin script is supported in
+this language environment.")))
+
+(set-language-info-alist
+ "Hanunoo" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "hanunoo")
+ (sample-text . "Hanunoo (ᜱᜨᜳᜨᜳᜢ) ᜫᜬᜧ᜴ ᜣᜭᜯᜥ᜴ ᜰᜲᜭᜥ᜴")
+ (documentation . "\
+Philippine Language Hanunoo is supported in this language environment.")))
+
+(set-language-info-alist
+ "Buhid" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "buhid")
+ (documentation . "\
+Philippine Language Buhid is supported in this language environment.")))
+
+(set-language-info-alist
+ "Tagbanwa" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (input-method . "tagbanwa")
+ (sample-text . "Tagbanwa (ᝦᝪᝯ) ᝫᝩᝬᝥ ᝣᝮᝧᝯ")
+ (documentation . "\
+Philippine Languages Tagbanwa are supported in this language environment.")))
+
+;; Tagalog composition rules
+(let ((akshara "[\x1700-\x1711\x171F]")
+ (vowel "[\x1712\x1713]")
+ (virama "\x1714")
+ (pamudpod "\x1715"))
+ (set-char-table-range composition-function-table
+ '(#x1714 . #x1714)
+ (list (vector
+ ;; Akshara virama syllables
+ (concat akshara virama vowel "?")
+ 1 'font-shape-gstring)))
+ (set-char-table-range composition-function-table
+ '(#x1715 . #x1715)
+ (list (vector
+ ;; Akshara pamudpod syllables
+ (concat akshara pamudpod vowel "?")
+ 1 'font-shape-gstring))))
+
+;; Hanunoo composition rules
+(let ((akshara "[\x1720-\x1731]")
+ (vowel "[\x1732\x1733]")
+ (pamudpod "\x1734"))
+ (set-char-table-range composition-function-table
+ '(#x1734 . #x1734)
+ (list (vector
+ ;; Akshara pamudpod syllables
+ (concat akshara pamudpod vowel "?")
+ 1 'font-shape-gstring))))
+
+(provide 'philippine)
+;;; philippine.el ends here
diff --git a/lisp/language/thai-util.el b/lisp/language/thai-util.el
index d11daf0f839..6c004e9495c 100644
--- a/lisp/language/thai-util.el
+++ b/lisp/language/thai-util.el
@@ -244,15 +244,13 @@ positions (integers or markers) specifying the region."
;; Thai-word-mode requires functions in the feature `thai-word'.
(require 'thai-word)
-(defvar thai-word-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [remap forward-word] 'thai-forward-word)
- (define-key map [remap backward-word] 'thai-backward-word)
- (define-key map [remap kill-word] 'thai-kill-word)
- (define-key map [remap backward-kill-word] 'thai-backward-kill-word)
- (define-key map [remap transpose-words] 'thai-transpose-words)
- map)
- "Keymap for `thai-word-mode'.")
+(defvar-keymap thai-word-mode-map
+ :doc "Keymap for `thai-word-mode'."
+ "<remap> <forward-word>" #'thai-forward-word
+ "<remap> <backward-word>" #'thai-backward-word
+ "<remap> <kill-word>" #'thai-kill-word
+ "<remap> <backward-kill-word>" #'thai-backward-kill-word
+ "<remap> <transpose-words>" #'thai-transpose-words)
(define-minor-mode thai-word-mode
"Minor mode to make word-oriented commands aware of Thai words.
diff --git a/lisp/language/thai.el b/lisp/language/thai.el
index 6a6289a44c7..60f5f9d2a38 100644
--- a/lisp/language/thai.el
+++ b/lisp/language/thai.el
@@ -82,6 +82,43 @@ This is the same as `thai-tis620' with the addition of no-break-space."
(aset composition-function-table (aref chars i) elt)))
(aset composition-function-table ?ำ '(["[ก-ฯ]." 1 thai-composition-function]))
+;; Tai-Tham
+
+(set-language-info-alist
+ "Northern Thai" '((charset unicode)
+ (coding-system utf-8)
+ (coding-priority utf-8)
+ (sample-text .
+ "Northern Thai (ᨣᩣᩴᨾᩮᩬᩥᨦ / ᨽᩣᩈᩣᩃ᩶ᩣ᩠ᨶᨶᩣ) ᩈ᩠ᩅᩢᩔ᩠ᨯᩦᨣᩕᩢ᩠ᨸ")
+ (documentation . t)))
+
+;; From Richard Wordingham <richard.wordingham@ntlworld.com>:
+(defvar tai-tham-composable-pattern
+ (let ((table
+ ;; C is letters, independent vowels, digits, punctuation and symbols.
+ '(("C" . "[\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA0-\u1AAD]")
+ ("M" . ; Marks, CGJ, ZWNJ, ZWJ
+ "[\u0324\u034F\u0E49\u0E4A\u0E4B\u1A55-\u1A57\u1A59-\u1A5E\u1A61-\u1A7C\u1A7F\u200C\200D]")
+ ("H" . "\u1A60") ; Sakot
+ ("S" . ; Marks commuting with sakot
+ "[\u0E49-\u0E4B\u0EC9\u0ECB\u1A75-\u1A7C]")
+ ("N" . "\u1A58"))) ; mai kang lai
+ (basic-syllable "C\\(N*\\(M\\|HS*C\\)\\)*")
+ (regexp "X\\(N\\(X\\)?\\)*H?")) ; where X is basic syllable
+ (let ((case-fold-search nil))
+ (setq regexp (replace-regexp-in-string "X" basic-syllable regexp t t))
+ (dolist (elt table)
+ (setq regexp (replace-regexp-in-string (car elt) (cdr elt)
+ regexp t t))))
+ regexp))
+
+(let ((elt (list (vector tai-tham-composable-pattern 0 'font-shape-gstring)
+ )))
+ (set-char-table-range composition-function-table '(#x1A20 . #x1A54) elt)
+ (set-char-table-range composition-function-table '(#x1A80 . #x1A89) elt)
+ (set-char-table-range composition-function-table '(#x1A90 . #x1A99) elt)
+ (set-char-table-range composition-function-table '(#x1AA0 . #x1AAD) elt))
+
(provide 'thai)
;;; thai.el ends here
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 6d5b0d84e6b..98dad181f40 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -1,10 +1,17 @@
-;;; loaddefs.el --- automatically extracted autoloads -*- lexical-binding: t -*-
-;; This file will be copied to ldefs-boot.el and checked in periodically.
-;;
+;;; loaddefs.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Commentary:
+
+;; This file will be copied to ldefs-boot.el and checked in
+;; periodically.
+
;;; Code:
+
-;;;### (autoloads nil "5x5" "play/5x5.el" (0 0 0 0))
;;; Generated autoloads from play/5x5.el
(autoload '5x5 "5x5" "\
@@ -31,21 +38,16 @@ Rotate left Calc Solutions \\[5x5-solve-rotate-left]
Rotate right Calc Solutions \\[5x5-solve-rotate-right]
Quit current game \\[5x5-quit-game]
-\(fn &optional SIZE)" t nil)
-
+(fn &optional SIZE)" t nil)
(autoload '5x5-crack-randomly "5x5" "\
Attempt to crack 5x5 using random solutions." t nil)
-
(autoload '5x5-crack-mutating-current "5x5" "\
Attempt to crack 5x5 by mutating the current solution." t nil)
-
(autoload '5x5-crack-mutating-best "5x5" "\
Attempt to crack 5x5 by mutating the best solution." t nil)
-
(autoload '5x5-crack-xor-mutate "5x5" "\
Attempt to crack 5x5 by xoring the current and best solution.
Mutate the result." t nil)
-
(autoload '5x5-crack "5x5" "\
Attempt to find a solution for 5x5.
@@ -54,50 +56,39 @@ two parameters, the first will be a grid vector array that is the current
solution and the second will be the best solution so far. The function
should return a grid vector array that is the new solution.
-\(fn BREEDER)" t nil)
-
+(fn BREEDER)" t nil)
(register-definition-prefixes "5x5" '("5x5-"))
-;;;***
-;;;### (autoloads nil "add-log" "vc/add-log.el" (0 0 0 0))
;;; Generated autoloads from vc/add-log.el
(put 'change-log-default-name 'safe-local-variable #'string-or-null-p)
-
(defvar add-log-current-defun-function nil "\
If non-nil, function to guess name of surrounding function.
It is called by `add-log-current-defun' with no argument, and
should return the function's name as a string, or nil if point is
outside a function.")
-
(custom-autoload 'add-log-current-defun-function "add-log" t)
-
(defvar add-log-full-name nil "\
Full name of user, for inclusion in ChangeLog daily headers.
This defaults to the value returned by the function `user-full-name'.")
-
(custom-autoload 'add-log-full-name "add-log" t)
-
(defvar add-log-mailing-address nil "\
Email addresses of user, for inclusion in ChangeLog headers.
This defaults to the value of `user-mail-address'. In addition to
being a simple string, this value can also be a list. All elements
will be recognized as referring to the same user; when creating a new
ChangeLog entry, one element will be chosen at random.")
-
(custom-autoload 'add-log-mailing-address "add-log" t)
-
(autoload 'prompt-for-change-log-name "add-log" "\
Prompt for a change log name." nil nil)
-
(autoload 'find-change-log "add-log" "\
Find a change log file for \\[add-change-log-entry] and return the name.
Optional arg FILE-NAME specifies the file to use.
If FILE-NAME is nil, use the value of `change-log-default-name'.
If `change-log-default-name' is nil, behave as though it were \"ChangeLog\"
-\(or whatever we use on this operating system).
+(or whatever we use on this operating system).
If `change-log-default-name' contains a leading directory component, then
simply find it in the current directory. Otherwise, search in the current
@@ -111,8 +102,7 @@ Once a file is found, `change-log-default-name' is set locally in the
current buffer to the complete file name.
Optional arg BUFFER-FILE overrides `buffer-file-name'.
-\(fn &optional FILE-NAME BUFFER-FILE)" nil nil)
-
+(fn &optional FILE-NAME BUFFER-FILE)" nil nil)
(autoload 'add-change-log-entry "add-log" "\
Find ChangeLog buffer, add an entry for today and an item for this file.
Optional arg WHOAMI (interactive prefix) non-nil means prompt for
@@ -148,15 +138,13 @@ notices.
Today's date is calculated according to `add-log-time-zone-rule' if
non-nil, otherwise in local time.
-\(fn &optional WHOAMI CHANGELOG-FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil)
-
+(fn &optional WHOAMI CHANGELOG-FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil)
(autoload 'add-change-log-entry-other-window "add-log" "\
Find change log file in other window and add entry and item.
This is just like `add-change-log-entry' except that it displays
the change log file in another window.
-\(fn &optional WHOAMI FILE-NAME)" t nil)
-
+(fn &optional WHOAMI FILE-NAME)" t nil)
(autoload 'change-log-mode "add-log" "\
Major mode for editing change logs; like Indented Text mode.
Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
@@ -166,8 +154,7 @@ Runs `change-log-mode-hook'.
\\{change-log-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'add-log-current-defun "add-log" "\
Return name of function definition point is in, or nil.
@@ -181,7 +168,6 @@ identifiers followed by `:' or `='. See variables
`add-log-current-defun-function'.
Has a preference of looking backwards." nil nil)
-
(autoload 'change-log-merge "add-log" "\
Merge the contents of change log file OTHER-LOG with this buffer.
Both must be found in Change Log mode (since the merging depends on
@@ -191,13 +177,10 @@ or a buffer.
Entries are inserted in chronological order. Both the current and
old-style time formats for entries are supported.
-\(fn OTHER-LOG)" t nil)
-
+(fn OTHER-LOG)" t nil)
(register-definition-prefixes "add-log" '("add-log-" "change-log-"))
-;;;***
-;;;### (autoloads nil "advice" "emacs-lisp/advice.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/advice.el
(defvar ad-redefinition-action 'warn "\
@@ -210,9 +193,7 @@ old original, or keep it and raise an error. The values `accept', `discard',
`error' or `warn' govern what will be done. `warn' is just like `accept' but
it additionally prints a warning message. All other values will be
interpreted as `error'.")
-
(custom-autoload 'ad-redefinition-action "advice" t)
-
(defvar ad-default-compilation-action 'maybe "\
Defines whether to compile advised definitions during activation.
A value of `always' will result in unconditional compilation, `never' will
@@ -221,19 +202,15 @@ loaded, and `like-original' will compile if the original definition of the
advised function is compiled or a built-in function. Every other value will
be interpreted as `maybe'. This variable will only be considered if the
COMPILE argument of `ad-activate' was supplied as nil.")
-
(custom-autoload 'ad-default-compilation-action "advice" t)
-
(autoload 'ad-enable-advice "advice" "\
Enables the advice of FUNCTION with CLASS and NAME.
-\(fn FUNCTION CLASS NAME)" t nil)
-
+(fn FUNCTION CLASS NAME)" t nil)
(autoload 'ad-disable-advice "advice" "\
Disable the advice of FUNCTION with CLASS and NAME.
-\(fn FUNCTION CLASS NAME)" t nil)
-
+(fn FUNCTION CLASS NAME)" t nil)
(autoload 'ad-add-advice "advice" "\
Add a piece of ADVICE to FUNCTION's list of advices in CLASS.
@@ -257,8 +234,7 @@ If FUNCTION was not advised already, its advice info will be
initialized. Redefining a piece of advice whose name is part of
the cache-id will clear the cache.
-\(fn FUNCTION ADVICE CLASS POSITION)" nil nil)
-
+(fn FUNCTION ADVICE CLASS POSITION)" nil nil)
(autoload 'ad-activate "advice" "\
Activate all the advice information of an advised FUNCTION.
If FUNCTION has a proper original definition then an advised
@@ -276,8 +252,7 @@ an advised function that has actual pieces of advice but none of them are
enabled is equivalent to a call to `ad-deactivate'. The current advised
definition will always be cached for later usage.
-\(fn FUNCTION &optional COMPILE)" t nil)
-
+(fn FUNCTION &optional COMPILE)" t nil)
(autoload 'defadvice "advice" "\
Define a piece of advice for FUNCTION (a symbol).
The syntax of `defadvice' is as follows:
@@ -324,17 +299,12 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
[DOCSTRING] [INTERACTIVE-FORM]
BODY...)
-\(fn FUNCTION ARGS &rest BODY)" nil t)
-
-(function-put 'defadvice 'doc-string-elt '3)
-
-(function-put 'defadvice 'lisp-indent-function '2)
-
+(fn FUNCTION ARGS &rest BODY)" nil t)
+(function-put 'defadvice 'doc-string-elt 3)
+(function-put 'defadvice 'lisp-indent-function 2)
(register-definition-prefixes "advice" '("ad-"))
-;;;***
-;;;### (autoloads nil "align" "align.el" (0 0 0 0))
;;; Generated autoloads from align.el
(autoload 'align "align" "\
@@ -343,8 +313,8 @@ Interactively, BEG and END are the mark/point of the current region.
Many modes define specific alignment rules, and some of these
rules in some modes react to the current prefix argument. For
-instance, in `text-mode', `M-x align' will align into columns
-based on space delimiters, while `C-u - M-x align' will align
+instance, in `text-mode', \\`M-x align' will align into columns
+based on space delimiters, while \\`C-u -' \\`M-x align' will align
into columns based on the \"$\" character. See the
`align-rules-list' variable definition for the specific rules.
@@ -365,8 +335,7 @@ default rule lists defined in `align-rules-list' and
`align-exclude-rules-list'. See `align-rules-list' for more details
on the format of these lists.
-\(fn BEG END &optional SEPARATE RULES EXCLUDE-RULES)" t nil)
-
+(fn BEG END &optional SEPARATE RULES EXCLUDE-RULES)" t nil)
(autoload 'align-regexp "align" "\
Align the current region using an ad-hoc rule read from the minibuffer.
BEG and END mark the limits of the region. Interactively, this function
@@ -409,8 +378,7 @@ The non-interactive form of the previous example would look something like:
This function is a nothing more than a small wrapper that helps you
construct a rule to pass to `align-region', which does the real work.
-\(fn BEG END REGEXP &optional GROUP SPACING REPEAT)" t nil)
-
+(fn BEG END REGEXP &optional GROUP SPACING REPEAT)" t nil)
(autoload 'align-entire "align" "\
Align the selected region as if it were one alignment section.
BEG and END mark the extent of the region. If RULES or EXCLUDE-RULES
@@ -418,8 +386,7 @@ is set to a list of rules (see `align-rules-list'), it can be used to
override the default alignment rules that would have been used to
align that section.
-\(fn BEG END &optional RULES EXCLUDE-RULES)" t nil)
-
+(fn BEG END &optional RULES EXCLUDE-RULES)" t nil)
(autoload 'align-current "align" "\
Call `align' on the current alignment section.
This function assumes you want to align only the current section, and
@@ -428,8 +395,7 @@ EXCLUDE-RULES is set to a list of rules (see `align-rules-list'), it
can be used to override the default alignment rules that would have
been used to align that section.
-\(fn &optional RULES EXCLUDE-RULES)" t nil)
-
+(fn &optional RULES EXCLUDE-RULES)" t nil)
(autoload 'align-highlight-rule "align" "\
Highlight the whitespace which a given rule would have modified.
BEG and END mark the extent of the region. TITLE identifies the rule
@@ -438,31 +404,25 @@ list of rules (see `align-rules-list'), it can be used to override the
default alignment rules that would have been used to identify the text
to be colored.
-\(fn BEG END TITLE &optional RULES EXCLUDE-RULES)" t nil)
-
+(fn BEG END TITLE &optional RULES EXCLUDE-RULES)" t nil)
(autoload 'align-unhighlight-rule "align" "\
Remove any highlighting that was added by `align-highlight-rule'." t nil)
-
(autoload 'align-newline-and-indent "align" "\
A replacement function for `newline-and-indent', aligning as it goes.
The alignment is done by calling `align' on the region that was
indented." t nil)
-
(register-definition-prefixes "align" '("align-"))
-;;;***
-;;;### (autoloads nil "allout" "allout.el" (0 0 0 0))
;;; Generated autoloads from allout.el
-(push (purecopy '(allout 2 3)) package--builtin-versions)
+(push (purecopy '(allout 2 3)) package--builtin-versions)
(autoload 'allout-auto-activation-helper "allout" "\
Institute `allout-auto-activation'.
Intended to be used as the `allout-auto-activation' :set function.
-\(fn VAR VALUE)" nil nil)
-
+(fn VAR VALUE)" nil nil)
(autoload 'allout-setup "allout" "\
Do fundamental Emacs session for allout auto-activation.
@@ -471,7 +431,6 @@ Establishes allout processing as part of visiting a file if
The proper way to use this is through customizing the setting of
`allout-auto-activation'." nil nil)
-
(defvar allout-auto-activation nil "\
Configure allout outline mode auto-activation.
@@ -490,57 +449,26 @@ With value \"activate\", only auto-mode-activation is enabled.
Auto-layout is not.
With value nil, inhibit any automatic allout-mode activation.")
-
(custom-autoload 'allout-auto-activation "allout" nil)
-
(put 'allout-use-hanging-indents 'safe-local-variable #'booleanp)
-
(put 'allout-reindent-bodies 'safe-local-variable (lambda (x) (memq x '(nil t text force))))
-
(put 'allout-show-bodies 'safe-local-variable #'booleanp)
-
(put 'allout-header-prefix 'safe-local-variable #'stringp)
-
(put 'allout-primary-bullet 'safe-local-variable #'stringp)
-
(put 'allout-plain-bullets-string 'safe-local-variable #'stringp)
-
(put 'allout-distinctive-bullets-string 'safe-local-variable #'stringp)
-
(put 'allout-use-mode-specific-leader 'safe-local-variable (lambda (x) (or (memq x '(t nil allout-mode-leaders comment-start)) (stringp x))))
-
(put 'allout-old-style-prefixes 'safe-local-variable #'booleanp)
-
(put 'allout-stylish-prefixes 'safe-local-variable #'booleanp)
-
(put 'allout-numbered-bullet 'safe-local-variable #'string-or-null-p)
-
(put 'allout-file-xref-bullet 'safe-local-variable #'string-or-null-p)
-
(put 'allout-presentation-padding 'safe-local-variable #'integerp)
-
(put 'allout-layout 'safe-local-variable (lambda (x) (or (numberp x) (listp x) (memq x '(: * + -)))))
-
(autoload 'allout-mode-p "allout" "\
Return t if `allout-mode' is active in current buffer." nil t)
-
(autoload 'allout-mode "allout" "\
Toggle Allout outline mode.
-This is a minor mode. If called interactively, toggle the `Allout
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `allout-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
\\<allout-mode-map-value>
Allout outline mode is a minor mode that provides extensive
outline oriented formatting and manipulation. It enables
@@ -688,7 +616,7 @@ When the text cursor is positioned directly on the bullet character of
a topic, regular characters (a to z) invoke the commands of the
corresponding allout-mode keymap control chars. For example, \"f\"
would invoke the command typically bound to \"C-c<space>C-f\"
-\(\\[allout-forward-current-level] `allout-forward-current-level').
+(\\[allout-forward-current-level] `allout-forward-current-level').
Thus, by positioning the cursor on a topic bullet, you can
execute the outline navigation and manipulation commands with a
@@ -701,7 +629,7 @@ replaced with one that makes it easy to get to the hot-spot. If you
repeat it immediately it cycles (if `allout-beginning-of-line-cycles'
is set) to the beginning of the item and then, if you hit it again
immediately, to the hot-spot. Similarly, `allout-beginning-of-current-entry'
-\(\\[allout-beginning-of-current-entry]) moves to the hot-spot when the cursor is already located
+(\\[allout-beginning-of-current-entry]) moves to the hot-spot when the cursor is already located
at the beginning of the current entry.
Extending Allout
@@ -801,34 +729,41 @@ CONCEALED:
CLOSED: A TOPIC whose immediate OFFSPRING and body-text is CONCEALED.
OPEN: A TOPIC that is not CLOSED, though its OFFSPRING or BODY may be.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Allout mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-(defalias 'outlinify-sticky #'outlineify-sticky)
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `allout-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
+(defalias 'outlinify-sticky #'outlineify-sticky)
(autoload 'outlineify-sticky "allout" "\
Activate outline mode and establish file var so it is started subsequently.
See `allout-layout' and customization of `allout-auto-activation'
for details on preparing Emacs for automatic allout activation.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "allout" '("allout-"))
-;;;***
-;;;### (autoloads nil "allout-widgets" "allout-widgets.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from allout-widgets.el
-(push (purecopy '(allout-widgets 1 0)) package--builtin-versions)
+(push (purecopy '(allout-widgets 1 0)) package--builtin-versions)
(autoload 'allout-widgets-setup "allout-widgets" "\
Commission or decommission allout-widgets-mode along with allout-mode.
Meant to be used by customization of `allout-widgets-auto-activation'.
-\(fn VARNAME VALUE)" nil nil)
-
+(fn VARNAME VALUE)" nil nil)
(defvar allout-widgets-auto-activation nil "\
Activate to enable allout icon graphics wherever allout mode is active.
@@ -843,28 +778,11 @@ explicitly invoke `allout-widgets-mode' in allout buffers where
you want allout widgets operation.
See `allout-widgets-mode' for allout widgets mode features.")
-
(custom-autoload 'allout-widgets-auto-activation "allout-widgets" nil)
-
(put 'allout-widgets-mode-inhibit 'safe-local-variable #'booleanp)
-
(autoload 'allout-widgets-mode "allout-widgets" "\
Toggle Allout Widgets mode.
-This is a minor mode. If called interactively, toggle the
-`Allout-Widgets mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `allout-widgets-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Allout Widgets mode is an extension of Allout mode that provides
graphical decoration of outline structure. It is meant to
operate along with `allout-mode', via `allout-mode-hook'.
@@ -883,17 +801,32 @@ The bullet-icon and guide line graphics provide keybindings and mouse
bindings for easy outline navigation and exposure control, extending
outline hot-spot navigation (see `allout-mode').
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Allout-Widgets mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `allout-widgets-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "allout-widgets" '("allout-"))
-;;;***
-;;;### (autoloads nil "ange-ftp" "net/ange-ftp.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/analyze.el
+
+(register-definition-prefixes "semantic/analyze" '("semantic-a"))
+
+
;;; Generated autoloads from net/ange-ftp.el
(defalias 'ange-ftp-re-read-dir 'ange-ftp-reread-dir)
-
(autoload 'ange-ftp-reread-dir "ange-ftp" "\
Reread remote directory DIR to update the directory cache.
The implementation of remote FTP file names caches directory contents
@@ -901,18 +834,14 @@ for speed. Therefore, when new remote files are created, Emacs
may not know they exist. You can use this command to reread a specific
directory, so that Emacs will know its current contents.
-\(fn &optional DIR)" t nil)
-
+(fn &optional DIR)" t nil)
(autoload 'ange-ftp-hook-function "ange-ftp" "\
-\(fn OPERATION &rest ARGS)" nil nil)
-
+(fn OPERATION &rest ARGS)" nil nil)
(register-definition-prefixes "ange-ftp" '("ange-ftp-" "ftp-error" "internal-ange-ftp-mode"))
-;;;***
-;;;### (autoloads nil "animate" "play/animate.el" (0 0 0 0))
;;; Generated autoloads from play/animate.el
(autoload 'animate-string "animate" "\
@@ -923,8 +852,7 @@ passing through `animate-n-steps' positions before the final ones.
If HPOS is nil (or omitted), center the string horizontally
in the current window.
-\(fn STRING VPOS &optional HPOS)" nil nil)
-
+(fn STRING VPOS &optional HPOS)" nil nil)
(autoload 'animate-sequence "animate" "\
Display animation strings from LIST-OF-STRING with buffer *Animation*.
Strings will be separated from each other by SPACE lines.
@@ -932,27 +860,22 @@ Strings will be separated from each other by SPACE lines.
animation in the buffer named by variable's value, creating the
buffer if one does not exist.
-\(fn LIST-OF-STRINGS SPACE)" nil nil)
-
+(fn LIST-OF-STRINGS SPACE)" nil nil)
(autoload 'animate-birthday-present "animate" "\
Return a birthday present in the buffer *Birthday-Present*.
When optional arg NAME is non-nil or called-interactively, prompt for
NAME of birthday present receiver and return a birthday present in
the buffer *Birthday-Present-for-Name*.
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(register-definition-prefixes "animate" '("animat"))
-;;;***
-;;;### (autoloads nil "ansi-color" "ansi-color.el" (0 0 0 0))
;;; Generated autoloads from ansi-color.el
-(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions)
+(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions)
(autoload 'ansi-color-for-comint-mode-on "ansi-color" "\
Set `ansi-color-for-comint-mode' to t." t nil)
-
(autoload 'ansi-color-process-output "ansi-color" "\
Maybe translate SGR control sequences of comint output into text properties.
@@ -966,22 +889,17 @@ The comint output is assumed to lie between the marker
This is a good function to put in `comint-output-filter-functions'.
-\(fn IGNORED)" nil nil)
-
+(fn IGNORED)" nil nil)
(autoload 'ansi-color-compilation-filter "ansi-color" "\
Maybe translate SGR control sequences into text properties.
This function depends on the `ansi-color-for-compilation-mode'
variable, and is meant to be used in `compilation-filter-hook'." nil nil)
-
(register-definition-prefixes "ansi-color" '("ansi-color-"))
-;;;***
-;;;### (autoloads nil "antlr-mode" "progmodes/antlr-mode.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/antlr-mode.el
-(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions)
+(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions)
(autoload 'antlr-show-makefile-rules "antlr-mode" "\
Show Makefile rules for all grammar files in the current directory.
If the `major-mode' of the current buffer has the value `makefile-mode',
@@ -998,21 +916,16 @@ If the file for a super-grammar cannot be determined, special file names
are used according to variable `antlr-unknown-file-formats' and a
commentary with value `antlr-help-unknown-file-text' is added. The
*Help* buffer always starts with the text in `antlr-help-rules-intro'." t nil)
-
(autoload 'antlr-mode "antlr-mode" "\
Major mode for editing ANTLR grammar files.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'antlr-set-tabs "antlr-mode" "\
Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'.
Used in `antlr-mode'. Also a useful function in `java-mode-hook'." nil nil)
-
(register-definition-prefixes "antlr-mode" '("antlr-"))
-;;;***
-;;;### (autoloads nil "appt" "calendar/appt.el" (0 0 0 0))
;;; Generated autoloads from calendar/appt.el
(autoload 'appt-add "appt" "\
@@ -1022,20 +935,16 @@ Optional argument WARNTIME is an integer (or string) giving the number
of minutes before the appointment at which to start warning.
The default is `appt-message-warning-time'.
-\(fn TIME MSG &optional WARNTIME)" t nil)
-
+(fn TIME MSG &optional WARNTIME)" t nil)
(autoload 'appt-activate "appt" "\
Toggle checking of appointments.
With optional numeric argument ARG, turn appointment checking on if
ARG is positive, otherwise off.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "appt" '("appt-"))
-;;;***
-;;;### (autoloads nil "apropos" "apropos.el" (0 0 0 0))
;;; Generated autoloads from apropos.el
(autoload 'apropos-read-pattern "apropos" "\
@@ -1046,8 +955,7 @@ literally, or a string which is used as a regexp to search for.
SUBJECT is a string that is included in the prompt to identify what
kind of objects to search.
-\(fn SUBJECT)" nil nil)
-
+(fn SUBJECT)" nil nil)
(autoload 'apropos-user-option "apropos" "\
Show user options that match PATTERN.
PATTERN can be a word, a list of words (separated by spaces),
@@ -1058,16 +966,14 @@ search for matches for any two (or more) of those words.
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show
variables, not just user options.
-\(fn PATTERN &optional DO-ALL)" t nil)
-
+(fn PATTERN &optional DO-ALL)" t nil)
(autoload 'apropos-variable "apropos" "\
Show variables that match PATTERN.
With the optional argument DO-NOT-ALL non-nil (or when called
interactively with the prefix \\[universal-argument]), show user
options only, i.e. behave like `apropos-user-option'.
-\(fn PATTERN &optional DO-NOT-ALL)" t nil)
-
+(fn PATTERN &optional DO-NOT-ALL)" t nil)
(autoload 'apropos-local-variable "apropos" "\
Show buffer-local variables that match PATTERN.
Optional arg BUFFER (default: current buffer) is the buffer to check.
@@ -1075,8 +981,7 @@ Optional arg BUFFER (default: current buffer) is the buffer to check.
The output includes variables that are not yet set in BUFFER, but that
will be buffer-local when set.
-\(fn PATTERN &optional BUFFER)" t nil)
-
+(fn PATTERN &optional BUFFER)" t nil)
(autoload 'apropos-function "apropos" "\
Show functions that match PATTERN.
@@ -1088,10 +993,8 @@ search for matches for any two (or more) of those words.
This is the same as running `apropos-command' with a \\[universal-argument] prefix,
or a non-nil `apropos-do-all' argument.
-\(fn PATTERN)" t nil)
-
+(fn PATTERN)" t nil)
(defalias 'command-apropos #'apropos-command)
-
(autoload 'apropos-command "apropos" "\
Show commands (interactively callable functions) that match PATTERN.
PATTERN can be a word, a list of words (separated by spaces),
@@ -1108,13 +1011,11 @@ satisfy the predicate VAR-PREDICATE.
When called from a Lisp program, a string PATTERN is used as a regexp,
while a list of strings is used as a word list.
-\(fn PATTERN &optional DO-ALL VAR-PREDICATE)" t nil)
-
+(fn PATTERN &optional DO-ALL VAR-PREDICATE)" t nil)
(autoload 'apropos-documentation-property "apropos" "\
Like (documentation-property SYMBOL PROPERTY RAW) but handle errors.
-\(fn SYMBOL PROPERTY RAW)" nil nil)
-
+(fn SYMBOL PROPERTY RAW)" nil nil)
(autoload 'apropos "apropos" "\
Show all meaningful Lisp symbols whose names match PATTERN.
Symbols are shown if they are defined as functions, variables, or
@@ -1130,16 +1031,17 @@ consider all symbols (if they match PATTERN).
Return list of symbols and documentation found.
-\(fn PATTERN &optional DO-ALL)" t nil)
+The *Apropos* window will be selected if `help-window-select' is
+non-nil.
+(fn PATTERN &optional DO-ALL)" t nil)
(autoload 'apropos-library "apropos" "\
List the variables and functions defined by library FILE.
FILE should be one of the libraries currently loaded and should
thus be found in `load-history'. If `apropos-do-all' is non-nil,
the output includes key-bindings of commands.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'apropos-value "apropos" "\
Show all symbols whose value's printed representation matches PATTERN.
PATTERN can be a word, a list of words (separated by spaces),
@@ -1153,15 +1055,13 @@ names and values of properties.
Returns list of symbols and values found.
-\(fn PATTERN &optional DO-ALL)" t nil)
-
+(fn PATTERN &optional DO-ALL)" t nil)
(autoload 'apropos-local-value "apropos" "\
Show buffer-local variables whose values match PATTERN.
This is like `apropos-value', but only for buffer-local variables.
Optional arg BUFFER (default: current buffer) is the buffer to check.
-\(fn PATTERN &optional BUFFER)" t nil)
-
+(fn PATTERN &optional BUFFER)" t nil)
(autoload 'apropos-documentation "apropos" "\
Show symbols whose documentation contains matches for PATTERN.
PATTERN can be a word, a list of words (separated by spaces),
@@ -1176,13 +1076,10 @@ documentation strings.
Returns list of symbols and documentation found.
-\(fn PATTERN &optional DO-ALL)" t nil)
-
+(fn PATTERN &optional DO-ALL)" t nil)
(register-definition-prefixes "apropos" '("apropos-"))
-;;;***
-;;;### (autoloads nil "arc-mode" "arc-mode.el" (0 0 0 0))
;;; Generated autoloads from arc-mode.el
(autoload 'archive-mode "arc-mode" "\
@@ -1198,13 +1095,15 @@ archive.
\\{archive-mode-map}
-\(fn &optional FORCE)" nil nil)
-
+(fn &optional FORCE)" nil nil)
(register-definition-prefixes "arc-mode" '("arc"))
-;;;***
-;;;### (autoloads nil "array" "array.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/args.el
+
+(register-definition-prefixes "srecode/args" '("srecode-"))
+
+
;;; Generated autoloads from array.el
(autoload 'array-mode "array" "\
@@ -1274,32 +1173,15 @@ take a numeric prefix argument):
Entering array mode calls the function `array-mode-hook'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "array" '("array-" "current-line" "limit-index" "move-to-column-untabify" "untabify-backward"))
-;;;***
-;;;### (autoloads nil "artist" "textmodes/artist.el" (0 0 0 0))
;;; Generated autoloads from textmodes/artist.el
(autoload 'artist-mode "artist" "\
Toggle Artist mode.
-This is a minor mode. If called interactively, toggle the `Artist
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `artist-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Artist lets you draw lines, squares, rectangles and poly-lines,
ellipses and circles with your mouse and/or keyboard.
@@ -1466,25 +1348,25 @@ Variables
This is a brief overview of the different variables. For more info,
see the documentation for the variables (type \\[describe-variable] <variable> RET).
- artist-rubber-banding Interactively do rubber-banding or not
- artist-first-char What to set at first/second point...
- artist-second-char ...when not rubber-banding
- artist-interface-with-rect If cut/copy/paste should interface with rect
- artist-arrows The arrows to use when drawing arrows
- artist-aspect-ratio Character height-to-width for squares
- artist-trim-line-endings Trimming of line endings
- artist-flood-fill-right-border Right border when flood-filling
- artist-flood-fill-show-incrementally Update display while filling
- artist-pointer-shape Pointer shape to use while drawing
- artist-ellipse-left-char Character to use for narrow ellipses
- artist-ellipse-right-char Character to use for narrow ellipses
- artist-borderless-shapes If shapes should have borders
- artist-picture-compatibility Whether or not to be picture mode compatible
- artist-vaporize-fuzziness Tolerance when recognizing lines
- artist-spray-interval Seconds between repeated sprayings
- artist-spray-radius Size of the spray-area
- artist-spray-chars The spray-\"color\"
- artist-spray-new-chars Initial spray-\"color\"
+ `artist-rubber-banding' Interactively do rubber-banding or not
+ `artist-first-char' What to set at first/second point...
+ `artist-second-char' ...when not rubber-banding
+ `artist-interface-with-rect' Should cut/copy/paste interface with rect
+ `artist-arrows' The arrows to use when drawing arrows
+ `artist-aspect-ratio' Character height-to-width for squares
+ `artist-trim-line-endings' Trimming of line endings
+ `artist-flood-fill-right-border' Right border when flood-filling
+ `artist-flood-fill-show-incrementally' Update display while filling
+ `artist-pointer-shape' Pointer shape to use while drawing
+ `artist-ellipse-left-char' Character to use for narrow ellipses
+ `artist-ellipse-right-char' Character to use for narrow ellipses
+ `artist-borderless-shapes' If shapes should have borders
+ `artist-picture-compatibility' Picture mode compatibility on or off
+ `artist-vaporize-fuzziness' Tolerance when recognizing lines
+ `artist-spray-interval' Seconds between repeated sprayings
+ `artist-spray-radius' Size of the spray-area
+ `artist-spray-chars' The spray-\"color\"
+ `artist-spray-new-char' Initial spray-\"color\"
Hooks
@@ -1495,13 +1377,24 @@ Keymap summary
\\{artist-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Artist mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `artist-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "artist" '("artist-"))
-;;;***
-;;;### (autoloads nil "asm-mode" "progmodes/asm-mode.el" (0 0 0 0))
;;; Generated autoloads from progmodes/asm-mode.el
(autoload 'asm-mode "asm-mode" "\
@@ -1524,21 +1417,16 @@ Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization.
Special commands:
\\{asm-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "asm-mode" '("asm-"))
-;;;***
-;;;### (autoloads nil "auth-source" "auth-source.el" (0 0 0 0))
;;; Generated autoloads from auth-source.el
(defvar auth-source-cache-expiry 7200 "\
How many seconds passwords are cached, or nil to disable expiring.
Overrides `password-cache-expiry' through a let-binding.")
-
(custom-autoload 'auth-source-cache-expiry "auth-source" t)
-
(autoload 'authinfo-mode "auth-source" "\
Mode for editing .authinfo/.netrc files.
@@ -1548,20 +1436,15 @@ point is moved into the passwords (see `authinfo-hide-elements').
\\{authinfo-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "auth-source" '("auth"))
-;;;***
-;;;### (autoloads nil "auth-source-pass" "auth-source-pass.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from auth-source-pass.el
-(push (purecopy '(auth-source-pass 5 0 0)) package--builtin-versions)
+(push (purecopy '(auth-source-pass 5 0 0)) package--builtin-versions)
(autoload 'auth-source-pass-enable "auth-source-pass" "\
Enable auth-source-password-store." nil nil)
-
(autoload 'auth-source-pass-get "auth-source-pass" "\
Return the value associated to KEY in the password-store entry ENTRY.
@@ -1575,112 +1458,41 @@ secret
key1: value1
key2: value2
-\(fn KEY ENTRY)" nil nil)
-
+(fn KEY ENTRY)" nil nil)
(register-definition-prefixes "auth-source-pass" '("auth-source-pass-"))
-;;;***
-;;;### (autoloads nil "autoarg" "autoarg.el" (0 0 0 0))
-;;; Generated autoloads from autoarg.el
-
-(defvar autoarg-mode nil "\
-Non-nil if Autoarg mode is enabled.
-See the `autoarg-mode' command
-for a description of this minor mode.")
-
-(custom-autoload 'autoarg-mode "autoarg" nil)
-
-(autoload 'autoarg-mode "autoarg" "\
-Toggle Autoarg mode, a global minor mode.
-
-\\<autoarg-mode-map>
-In Autoarg mode, digits are bound to `digit-argument', i.e. they
-supply prefix arguments as C-DIGIT and M-DIGIT normally do.
-Furthermore, C-DIGIT inserts DIGIT.
-\\[autoarg-terminate] terminates the prefix sequence and inserts
-the digits of the autoarg sequence into the buffer.
-Without a numeric prefix arg, the normal binding of \\[autoarg-terminate]
-is invoked, i.e. what it would be with Autoarg mode off.
-
-For example:
-`6 9 \\[autoarg-terminate]' inserts `69' into the buffer, as does `C-6 C-9'.
-`6 9 a' inserts 69 `a's into the buffer.
-`6 9 \\[autoarg-terminate] \\[autoarg-terminate]' inserts `69' into the buffer and
-then invokes the normal binding of \\[autoarg-terminate].
-`\\[universal-argument] \\[autoarg-terminate]' invokes the normal binding of \\[autoarg-terminate] four times.
-
-\\{autoarg-mode-map}
-
-\(fn &optional ARG)" t nil)
-
-(defvar autoarg-kp-mode nil "\
-Non-nil if Autoarg-Kp mode is enabled.
-See the `autoarg-kp-mode' command
-for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `autoarg-kp-mode'.")
-
-(custom-autoload 'autoarg-kp-mode "autoarg" nil)
-
-(autoload 'autoarg-kp-mode "autoarg" "\
-Toggle Autoarg-KP mode, a global minor mode.
-
-This is a minor mode. If called interactively, toggle the `Autoarg-Kp
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='autoarg-kp-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\\<autoarg-kp-mode-map>
-This is similar to `autoarg-mode' but rebinds the keypad keys
-`kp-1' etc. to supply digit arguments.
-
-\\{autoarg-kp-mode-map}
-
-\(fn &optional ARG)" t nil)
+;;; Generated autoloads from cedet/ede/auto.el
-(register-definition-prefixes "autoarg" '("autoarg-"))
+(register-definition-prefixes "ede/auto" '("ede-"))
-;;;***
-;;;### (autoloads nil "autoconf" "progmodes/autoconf.el" (0 0 0 0))
;;; Generated autoloads from progmodes/autoconf.el
(autoload 'autoconf-mode "autoconf" "\
Major mode for editing Autoconf configure.ac files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "autoconf" '("autoconf-"))
-;;;***
-;;;### (autoloads nil "autoinsert" "autoinsert.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/autoconf-edit.el
+
+(register-definition-prefixes "ede/autoconf-edit" '("autoconf-"))
+
+
;;; Generated autoloads from autoinsert.el
(autoload 'auto-insert "autoinsert" "\
Insert default contents into new files if variable `auto-insert' is non-nil.
Matches the visited file name against the elements of `auto-insert-alist'." t nil)
-
(autoload 'define-auto-insert "autoinsert" "\
Associate CONDITION with (additional) ACTION in `auto-insert-alist'.
Optional AFTER means to insert action after all existing actions for CONDITION,
or if CONDITION had no actions, after all other CONDITIONs.
-\(fn CONDITION ACTION &optional AFTER)" nil nil)
-
+(fn CONDITION ACTION &optional AFTER)" nil nil)
(function-put 'define-auto-insert 'lisp-indent-function 'defun)
-
(defvar auto-insert-mode nil "\
Non-nil if Auto-Insert mode is enabled.
See the `auto-insert-mode' command
@@ -1688,45 +1500,34 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `auto-insert-mode'.")
-
(custom-autoload 'auto-insert-mode "autoinsert" nil)
-
(autoload 'auto-insert-mode "autoinsert" "\
Toggle Auto-insert mode, a global minor mode.
-This is a minor mode. If called interactively, toggle the
-`Auto-Insert mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+When Auto-insert mode is enabled, when new files are created you can
+insert a template for the file depending on the mode of the buffer.
+
+This is a global minor mode. If called interactively, toggle the
+`Auto-Insert mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='auto-insert-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When Auto-insert mode is enabled, when new files are created you can
-insert a template for the file depending on the mode of the buffer.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "autoinsert" '("auto-insert"))
-;;;***
-;;;### (autoloads nil "autoload" "emacs-lisp/autoload.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/autoload.el
-(put 'generated-autoload-file 'safe-local-variable 'stringp)
-
-(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
-
(put 'autoload-ensure-writable 'risky-local-variable t)
-
(autoload 'update-file-autoloads "autoload" "\
Update the autoloads for FILE.
If prefix arg SAVE-AFTER is non-nil, save the buffer too.
@@ -1739,8 +1540,7 @@ existing value of `generated-autoload-file'.
Return FILE if there was no autoload cookie in it, else nil.
-\(fn FILE &optional SAVE-AFTER OUTFILE)" t nil)
-
+(fn FILE &optional SAVE-AFTER OUTFILE)" t nil)
(autoload 'update-directory-autoloads "autoload" "\
Update autoload definitions for Lisp files in the directories DIRS.
In an interactive call, you must give one argument, the name of a
@@ -1756,10 +1556,8 @@ value of `generated-autoload-file'. If any Lisp file binds
`generated-autoload-file' as a file-local variable, write its
autoloads into the specified file instead.
-\(fn &rest DIRS)" t nil)
-
-(make-obsolete 'update-directory-autoloads 'make-directory-autoloads '"28.1")
-
+(fn &rest DIRS)" t nil)
+(make-obsolete 'update-directory-autoloads 'make-directory-autoloads "28.1")
(autoload 'make-directory-autoloads "autoload" "\
Update autoload definitions for Lisp files in the directories DIRS.
DIR can be either a single directory or a list of
@@ -1772,38 +1570,20 @@ its autoloads into the specified file instead.
The function does NOT recursively descend into subdirectories of the
directory or directories specified.
-\(fn DIR OUTPUT-FILE)" t nil)
-
+(fn DIR OUTPUT-FILE)" t nil)
(autoload 'batch-update-autoloads "autoload" "\
Update loaddefs.el autoloads in batch mode.
Calls `update-directory-autoloads' on the command line arguments.
Definitions are written to `generated-autoload-file' (which
should be non-nil)." nil nil)
+(register-definition-prefixes "autoload" '("autoload-" "batch-update-autoloads--summary" "generate-" "make-autoload" "no-update-autoloads"))
-(register-definition-prefixes "autoload" '("autoload-" "batch-update-autoloads--summary" "generate" "make-autoload" "no-update-autoloads"))
-
-;;;***
-;;;### (autoloads nil "autorevert" "autorevert.el" (0 0 0 0))
;;; Generated autoloads from autorevert.el
(autoload 'auto-revert-mode "autorevert" "\
Toggle reverting buffer when the file changes (Auto-Revert Mode).
-This is a minor mode. If called interactively, toggle the
-`Auto-Revert mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `auto-revert-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Auto-Revert Mode is a minor mode that affects only the current
buffer. When enabled, it reverts the buffer when the file on
disk changes.
@@ -1819,31 +1599,29 @@ Use `global-auto-revert-mode' to automatically revert all buffers.
Use `auto-revert-tail-mode' if you know that the file will only grow
without being changed in the part that is already in the buffer.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Auto-Revert mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `auto-revert-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'turn-on-auto-revert-mode "autorevert" "\
Turn on Auto-Revert Mode.
This function is designed to be added to hooks, for example:
(add-hook \\='c-mode-hook #\\='turn-on-auto-revert-mode)" nil nil)
-
(autoload 'auto-revert-tail-mode "autorevert" "\
Toggle reverting tail of buffer when the file grows.
-This is a minor mode. If called interactively, toggle the
-`Auto-Revert-Tail mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `auto-revert-tail-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Auto-Revert Tail Mode is enabled, the tail of the file is
constantly followed, as with the shell command `tail -f'. This
means that whenever the file grows on disk (presumably because
@@ -1859,14 +1637,27 @@ suppressed by setting `auto-revert-verbose' to nil.
Use `auto-revert-mode' for changes other than appends!
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Auto-Revert-Tail mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `auto-revert-tail-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'turn-on-auto-revert-tail-mode "autorevert" "\
Turn on Auto-Revert Tail Mode.
This function is designed to be added to hooks, for example:
(add-hook \\='my-logfile-mode-hook #\\='turn-on-auto-revert-tail-mode)" nil nil)
-
(defvar global-auto-revert-mode nil "\
Non-nil if Global Auto-Revert mode is enabled.
See the `global-auto-revert-mode' command
@@ -1874,26 +1665,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-auto-revert-mode'.")
-
(custom-autoload 'global-auto-revert-mode "autorevert" nil)
-
(autoload 'global-auto-revert-mode "autorevert" "\
Toggle Global Auto-Revert Mode.
-This is a minor mode. If called interactively, toggle the `Global
-Auto-Revert mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-auto-revert-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Global Auto-Revert Mode is a global minor mode that reverts any
buffer associated with a file when the file changes on disk. Use
`auto-revert-mode' to revert a particular buffer.
@@ -1911,21 +1686,30 @@ This function calls the hook `global-auto-revert-mode-hook'.
It displays the text that `global-auto-revert-mode-text'
specifies in the mode line.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Global Auto-Revert mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='global-auto-revert-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "autorevert" '("auto-revert-" "global-auto-revert-"))
-;;;***
-;;;### (autoloads nil "avl-tree" "emacs-lisp/avl-tree.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/avl-tree.el
(register-definition-prefixes "avl-tree" '("avl-tree-"))
-;;;***
-;;;### (autoloads nil "avoid" "avoid.el" (0 0 0 0))
;;; Generated autoloads from avoid.el
(defvar mouse-avoidance-mode nil "\
@@ -1933,9 +1717,7 @@ Activate Mouse Avoidance mode.
See function `mouse-avoidance-mode' for possible values.
Setting this variable directly does not take effect;
use either \\[customize] or \\[mouse-avoidance-mode].")
-
(custom-autoload 'mouse-avoidance-mode "avoid" nil)
-
(autoload 'mouse-avoidance-mode "avoid" "\
Set Mouse Avoidance mode to MODE.
MODE should be one of the symbols `banish', `exile', `jump', `animate',
@@ -1955,34 +1737,31 @@ Effects of the different modes:
* cat-and-mouse: Same as `animate'.
* proteus: As `animate', but changes the shape of the mouse pointer too.
-\(See `mouse-avoidance-threshold' for definition of \"too close\",
+(See `mouse-avoidance-threshold' for definition of \"too close\",
and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for
definition of \"random distance\".)
-\(fn &optional MODE)" t nil)
-
+(fn &optional MODE)" t nil)
(register-definition-prefixes "avoid" '("mouse-avoidance-"))
-;;;***
-;;;### (autoloads nil "backtrace" "emacs-lisp/backtrace.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/backtrace.el
-(push (purecopy '(backtrace 1 0)) package--builtin-versions)
+(push (purecopy '(backtrace 1 0)) package--builtin-versions)
(autoload 'backtrace "backtrace" "\
Print a trace of Lisp function calls currently active.
Output stream used is value of `standard-output'." nil nil)
-
(register-definition-prefixes "backtrace" '("backtrace-"))
-;;;***
-;;;### (autoloads nil "bat-mode" "progmodes/bat-mode.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/base.el
+
+(register-definition-prefixes "ede/base" '("ede-"))
+
+
;;; Generated autoloads from progmodes/bat-mode.el
(add-to-list 'auto-mode-alist '("\\.\\(bat\\|cmd\\)\\'" . bat-mode))
-
(autoload 'bat-mode "bat-mode" "\
Major mode for editing DOS/Windows batch files.
Start a new script from `bat-template'. Read help pages for DOS commands
@@ -1991,21 +1770,17 @@ Run script using `bat-run' and `bat-run-args'.
\\{bat-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "bat-mode" '("bat-"))
-;;;***
-;;;### (autoloads nil "battery" "battery.el" (0 0 0 0))
;;; Generated autoloads from battery.el
- (put 'battery-mode-line-string 'risky-local-variable t)
+ (put 'battery-mode-line-string 'risky-local-variable t)
(autoload 'battery "battery" "\
Display battery status information in the echo area.
The text being displayed in the echo area is controlled by the variables
`battery-echo-area-format' and `battery-status-function'." t nil)
-
(defvar display-battery-mode nil "\
Non-nil if Display-Battery mode is enabled.
See the `display-battery-mode' command
@@ -2013,39 +1788,37 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `display-battery-mode'.")
-
(custom-autoload 'display-battery-mode "battery" nil)
-
(autoload 'display-battery-mode "battery" "\
Toggle battery status display in mode line (Display Battery mode).
-This is a minor mode. If called interactively, toggle the
+The text displayed in the mode line is controlled by
+`battery-mode-line-format' and `battery-status-function'.
+The mode line is be updated every `battery-update-interval'
+seconds.
+
+The function which updates the mode-line display will call the
+functions in `battery-update-functions', which can be used to
+trigger actions based on battery-related events.
+
+This is a global minor mode. If called interactively, toggle the
`Display-Battery mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='display-battery-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-The text displayed in the mode line is controlled by
-`battery-mode-line-format' and `battery-status-function'.
-The mode line is be updated every `battery-update-interval'
-seconds.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-(register-definition-prefixes "battery" '("battery-"))
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "battery" '("battery-" "my-"))
-;;;***
-;;;### (autoloads nil "benchmark" "emacs-lisp/benchmark.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/benchmark.el
(autoload 'benchmark-call "benchmark" "\
@@ -2060,8 +1833,7 @@ specifies a minimum number of seconds that the benchmark execution
should take. In that case the return value is prepended with the
number of repetitions actually used.
-\(fn FUNC &optional REPETITIONS)" nil nil)
-
+(fn FUNC &optional REPETITIONS)" nil nil)
(autoload 'benchmark-run "benchmark" "\
Time execution of FORMS.
If REPETITIONS is supplied as a number, run FORMS that many times,
@@ -2071,20 +1843,16 @@ Return a list of the total elapsed time for execution, the number of
garbage collections that ran, and the time taken by garbage collection.
See also `benchmark-run-compiled'.
-\(fn &optional REPETITIONS &rest FORMS)" nil t)
-
-(function-put 'benchmark-run 'lisp-indent-function '1)
-
+(fn &optional REPETITIONS &rest FORMS)" nil t)
+(function-put 'benchmark-run 'lisp-indent-function 1)
(autoload 'benchmark-run-compiled "benchmark" "\
Time execution of compiled version of FORMS.
This is like `benchmark-run', but what is timed is a funcall of the
byte code obtained by wrapping FORMS in a `lambda' and compiling the
result. The overhead of the `lambda's is accounted for.
-\(fn &optional REPETITIONS &rest FORMS)" nil t)
-
-(function-put 'benchmark-run-compiled 'lisp-indent-function '1)
-
+(fn &optional REPETITIONS &rest FORMS)" nil t)
+(function-put 'benchmark-run-compiled 'lisp-indent-function 1)
(autoload 'benchmark "benchmark" "\
Print the time taken for REPETITIONS executions of FORM.
Interactively, REPETITIONS is taken from the prefix arg, and
@@ -2094,28 +1862,21 @@ For non-interactive use see also `benchmark-run' and
FORM can also be a function in which case we measure the time it takes
to call it without any argument.
-\(fn REPETITIONS FORM)" t nil)
-
+(fn REPETITIONS FORM)" t nil)
(autoload 'benchmark-progn "benchmark" "\
Evaluate BODY and message the time taken.
The return value is the value of the final form in BODY.
-\(fn &rest BODY)" nil t)
-
-(function-put 'benchmark-progn 'lisp-indent-function '0)
-
+(fn &rest BODY)" nil t)
+(function-put 'benchmark-progn 'lisp-indent-function 0)
(register-definition-prefixes "benchmark" '("benchmark-"))
-;;;***
-;;;### (autoloads nil "bib-mode" "textmodes/bib-mode.el" (0 0 0 0))
;;; Generated autoloads from textmodes/bib-mode.el
(register-definition-prefixes "bib-mode" '("addbib" "bib-" "mark-bib" "return-key-bib" "unread-bib"))
-;;;***
-;;;### (autoloads nil "bibtex" "textmodes/bibtex.el" (0 0 0 0))
;;; Generated autoloads from textmodes/bibtex.el
(autoload 'bibtex-initialize "bibtex" "\
@@ -2132,8 +1893,7 @@ When called interactively, FORCE is t, CURRENT is t if current buffer
visits a file using `bibtex-mode', and SELECT is t if current buffer
does not use `bibtex-mode'.
-\(fn &optional CURRENT FORCE SELECT)" t nil)
-
+(fn &optional CURRENT FORCE SELECT)" t nil)
(autoload 'bibtex-mode "bibtex" "\
Major mode for editing BibTeX files.
@@ -2187,8 +1947,7 @@ if that value is non-nil.
\\{bibtex-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'bibtex-search-entry "bibtex" "\
Move point to the beginning of BibTeX entry named KEY.
Return position of entry if KEY is found or nil if not found.
@@ -2202,59 +1961,44 @@ Also, GLOBAL is t if the current mode is not `bibtex-mode'
or `bibtex-search-entry-globally' is non-nil.
A prefix arg negates the value of `bibtex-search-entry-globally'.
-\(fn KEY &optional GLOBAL START DISPLAY)" t nil)
-
+(fn KEY &optional GLOBAL START DISPLAY)" t nil)
(register-definition-prefixes "bibtex" '("bibtex-"))
-;;;***
-;;;### (autoloads nil "bibtex-style" "textmodes/bibtex-style.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from textmodes/bibtex-style.el
(autoload 'bibtex-style-mode "bibtex-style" "\
Major mode for editing BibTeX style files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "bibtex-style" '("bibtex-style-"))
-;;;***
-;;;### (autoloads nil "bindat" "emacs-lisp/bindat.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/bindat.el
(register-definition-prefixes "bindat" '("bindat-"))
-;;;***
-;;;### (autoloads nil "binhex" "mail/binhex.el" (0 0 0 0))
;;; Generated autoloads from mail/binhex.el
(defconst binhex-begin-line "^:...............................................................$" "\
Regular expression matching the start of a BinHex encoded region.")
-
(autoload 'binhex-decode-region-internal "binhex" "\
Binhex decode region between START and END without using an external program.
If HEADER-ONLY is non-nil only decode header and return filename.
-\(fn START END &optional HEADER-ONLY)" t nil)
-
+(fn START END &optional HEADER-ONLY)" t nil)
(autoload 'binhex-decode-region-external "binhex" "\
Binhex decode region between START and END using external decoder.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'binhex-decode-region "binhex" "\
Binhex decode region between START and END.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(register-definition-prefixes "binhex" '("binhex-"))
-;;;***
-;;;### (autoloads nil "blackbox" "play/blackbox.el" (0 0 0 0))
;;; Generated autoloads from play/blackbox.el
(autoload 'blackbox "blackbox" "\
@@ -2369,22 +2113,23 @@ H * * * O - - - - - - - - - - - - - - - - - - - -
Be sure to compare the second example of a hit with the first example of
a reflection.
-\(fn NUM)" t nil)
-
+(fn NUM)" t nil)
(register-definition-prefixes "blackbox" '("bb-" "blackbox-"))
-;;;***
-;;;### (autoloads nil "bookmark" "bookmark.el" (0 0 0 0))
;;; Generated autoloads from bookmark.el
- (define-key ctl-x-r-map "b" 'bookmark-jump)
- (define-key ctl-x-r-map "m" 'bookmark-set)
- (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite)
- (define-key ctl-x-r-map "l" 'bookmark-bmenu-list)
-(defvar-keymap bookmark-map :doc "Keymap containing bindings to bookmark functions.\nIt is not bound to any key by default: to bind it\nso that you have a bookmark prefix, just use `global-set-key' and bind a\nkey of your choice to variable `bookmark-map'. All interactive bookmark\nfunctions have a binding in this keymap." "x" #'bookmark-set "m" #'bookmark-set "M" #'bookmark-set-no-overwrite "j" #'bookmark-jump "g" #'bookmark-jump "o" #'bookmark-jump-other-window "5" #'bookmark-jump-other-frame "i" #'bookmark-insert "e" #'edit-bookmarks "f" #'bookmark-insert-location "r" #'bookmark-rename "d" #'bookmark-delete "D" #'bookmark-delete-all "l" #'bookmark-load "w" #'bookmark-write "s" #'bookmark-save)
+ (keymap-set ctl-x-r-map "b" #'bookmark-jump)
+ (keymap-set ctl-x-r-map "m" #'bookmark-set)
+ (keymap-set ctl-x-r-map "M" #'bookmark-set-no-overwrite)
+ (keymap-set ctl-x-r-map "l" #'bookmark-bmenu-list)
+(defvar-keymap bookmark-map :doc "\
+Keymap containing bindings to bookmark functions.
+It is not bound to any key by default: to bind it
+so that you have a bookmark prefix, just use `global-set-key' and bind a
+key of your choice to variable `bookmark-map'. All interactive bookmark
+functions have a binding in this keymap." "x" #'bookmark-set "m" #'bookmark-set "M" #'bookmark-set-no-overwrite "j" #'bookmark-jump "g" #'bookmark-jump "o" #'bookmark-jump-other-window "5" #'bookmark-jump-other-frame "i" #'bookmark-insert "e" #'edit-bookmarks "f" #'bookmark-insert-location "r" #'bookmark-rename "d" #'bookmark-delete "D" #'bookmark-delete-all "l" #'bookmark-load "w" #'bookmark-write "s" #'bookmark-save)
(fset 'bookmark-map bookmark-map)
-
(autoload 'bookmark-set "bookmark" "\
Set a bookmark named NAME at the current location.
If NAME is nil, then prompt the user.
@@ -2410,8 +2155,7 @@ Use \\[bookmark-delete] to remove bookmarks (you give it a name and
it removes only the first instance of a bookmark with that name from
the list of bookmarks.)
-\(fn &optional NAME NO-OVERWRITE)" t nil)
-
+(fn &optional NAME NO-OVERWRITE)" t nil)
(autoload 'bookmark-set-no-overwrite "bookmark" "\
Set a bookmark named NAME at the current location.
If NAME is nil, then prompt the user.
@@ -2440,8 +2184,7 @@ Use \\[bookmark-delete] to remove bookmarks (you give it a name and
it removes only the first instance of a bookmark with that name from
the list of bookmarks.)
-\(fn &optional NAME PUSH-BOOKMARK)" t nil)
-
+(fn &optional NAME PUSH-BOOKMARK)" t nil)
(autoload 'bookmark-jump "bookmark" "\
Jump to bookmark BOOKMARK (a point in some file).
You may have a problem using this function if the value of variable
@@ -2461,18 +2204,15 @@ If DISPLAY-FUNC is non-nil, it is a function to invoke to display the
bookmark. It defaults to `pop-to-buffer-same-window'. A typical value for
DISPLAY-FUNC would be `switch-to-buffer-other-window'.
-\(fn BOOKMARK &optional DISPLAY-FUNC)" t nil)
-
+(fn BOOKMARK &optional DISPLAY-FUNC)" t nil)
(autoload 'bookmark-jump-other-window "bookmark" "\
Jump to BOOKMARK in another window. See `bookmark-jump' for more.
-\(fn BOOKMARK)" t nil)
-
+(fn BOOKMARK)" t nil)
(autoload 'bookmark-jump-other-frame "bookmark" "\
Jump to BOOKMARK in another frame. See `bookmark-jump' for more.
-\(fn BOOKMARK)" t nil)
-
+(fn BOOKMARK)" t nil)
(autoload 'bookmark-relocate "bookmark" "\
Relocate BOOKMARK-NAME to another file, reading file name with minibuffer.
@@ -2480,18 +2220,15 @@ This makes an already existing bookmark point to that file, instead of
the one it used to point at. Useful when a file has been renamed
after a bookmark was set in it.
-\(fn BOOKMARK-NAME)" t nil)
-
+(fn BOOKMARK-NAME)" t nil)
(autoload 'bookmark-insert-location "bookmark" "\
Insert the name of the file associated with BOOKMARK-NAME.
Optional second arg NO-HISTORY means don't record this in the
minibuffer history list `bookmark-history'.
-\(fn BOOKMARK-NAME &optional NO-HISTORY)" t nil)
-
+(fn BOOKMARK-NAME &optional NO-HISTORY)" t nil)
(defalias 'bookmark-locate 'bookmark-insert-location)
-
(autoload 'bookmark-rename "bookmark" "\
Change the name of OLD-NAME bookmark to NEW-NAME name.
If called from keyboard, prompt for OLD-NAME and NEW-NAME.
@@ -2505,8 +2242,7 @@ While you are entering the new name, consecutive \\<bookmark-minibuffer-read-nam
consecutive words from the text of the buffer into the new bookmark
name.
-\(fn OLD-NAME &optional NEW-NAME)" t nil)
-
+(fn OLD-NAME &optional NEW-NAME)" t nil)
(autoload 'bookmark-insert "bookmark" "\
Insert the text of the file pointed to by bookmark BOOKMARK-NAME.
BOOKMARK-NAME is a bookmark name (a string), not a bookmark record.
@@ -2516,8 +2252,7 @@ You may have a problem using this function if the value of variable
bookmarks. See help on function `bookmark-load' for more about
this.
-\(fn BOOKMARK-NAME)" t nil)
-
+(fn BOOKMARK-NAME)" t nil)
(autoload 'bookmark-delete "bookmark" "\
Delete BOOKMARK-NAME from the bookmark list.
@@ -2528,20 +2263,16 @@ one most recently used in this file, if any).
Optional second arg BATCH means don't update the bookmark list buffer,
probably because we were called from there.
-\(fn BOOKMARK-NAME &optional BATCH)" t nil)
-
+(fn BOOKMARK-NAME &optional BATCH)" t nil)
(autoload 'bookmark-delete-all "bookmark" "\
Permanently delete all bookmarks.
If optional argument NO-CONFIRM is non-nil, don't ask for
confirmation.
-\(fn &optional NO-CONFIRM)" t nil)
-
+(fn &optional NO-CONFIRM)" t nil)
(autoload 'bookmark-write "bookmark" "\
Write bookmarks to a file (reading the file name with the minibuffer)." t nil)
-
(function-put 'bookmark-write 'interactive-only 'bookmark-save)
-
(autoload 'bookmark-save "bookmark" "\
Save currently defined bookmarks in FILE.
FILE defaults to `bookmark-default-file'.
@@ -2555,8 +2286,7 @@ When you want to load in the bookmarks from a file, use
for a file, defaulting to the file defined by variable
`bookmark-default-file'.
-\(fn &optional PARG FILE MAKE-DEFAULT)" t nil)
-
+(fn &optional PARG FILE MAKE-DEFAULT)" t nil)
(autoload 'bookmark-load "bookmark" "\
Load bookmarks from FILE (which must be in bookmark format).
Appends loaded bookmarks to the front of the list of bookmarks.
@@ -2576,34 +2306,29 @@ If you load a file containing bookmarks with the same names as
bookmarks already present in your Emacs, the new bookmarks will get
unique numeric suffixes \"<2>\", \"<3>\", etc.
-\(fn FILE &optional OVERWRITE NO-MSG DEFAULT)" t nil)
-
+(fn FILE &optional OVERWRITE NO-MSG DEFAULT)" t nil)
(autoload 'bookmark-bmenu-get-buffer "bookmark" "\
Return the Bookmark List, building it if it doesn't exists.
Don't affect the buffer ring order." nil nil)
-
(autoload 'bookmark-bmenu-list "bookmark" "\
Display a list of existing bookmarks.
The list is displayed in a buffer named `*Bookmark List*'.
The leftmost column displays a D if the bookmark is flagged for
deletion, or > if it is flagged for displaying." t nil)
-
(defalias 'list-bookmarks 'bookmark-bmenu-list)
-
(defalias 'edit-bookmarks 'bookmark-bmenu-list)
-
(autoload 'bookmark-bmenu-search "bookmark" "\
Incremental search of bookmarks, hiding the non-matches as we go." '(bookmark-bmenu-mode) nil)
-
(defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark functions"))) (bindings--define-key map [load] '(menu-item "Load a Bookmark File..." bookmark-load :help "Load bookmarks from a bookmark file)")) (bindings--define-key map [write] '(menu-item "Save Bookmarks As..." bookmark-write :help "Write bookmarks to a file (reading the file name with the minibuffer)")) (bindings--define-key map [save] '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")) (bindings--define-key map [edit] '(menu-item "Edit Bookmark List" bookmark-bmenu-list :help "Display a list of existing bookmarks")) (bindings--define-key map [delete] '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete a bookmark from the bookmark list")) (bindings--define-key map [delete-all] '(menu-item "Delete all Bookmarks..." bookmark-delete-all :help "Delete all bookmarks from the bookmark list")) (bindings--define-key map [rename] '(menu-item "Rename Bookmark..." bookmark-rename :help "Change the name of a bookmark")) (bindings--define-key map [locate] '(menu-item "Insert Location..." bookmark-locate :help "Insert the name of the file associated with a bookmark")) (bindings--define-key map [insert] '(menu-item "Insert Contents..." bookmark-insert :help "Insert the text of the file pointed to by a bookmark")) (bindings--define-key map [set] '(menu-item "Set Bookmark..." bookmark-set :help "Set a bookmark named inside a file.")) (bindings--define-key map [jump] '(menu-item "Jump to Bookmark..." bookmark-jump :help "Jump to a bookmark (a point in some file)")) map))
-
(defalias 'menu-bar-bookmark-map menu-bar-bookmark-map)
-
(register-definition-prefixes "bookmark" '("bookmark-" "with-buffer-modified-unmodified"))
-;;;***
-;;;### (autoloads nil "browse-url" "net/browse-url.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/bovine.el
+
+(register-definition-prefixes "semantic/bovine" '("semantic-"))
+
+
;;; Generated autoloads from net/browse-url.el
(defvar browse-url-browser-function 'browse-url-default-browser "\
@@ -2613,16 +2338,13 @@ This is used by the `browse-url-at-point', `browse-url-at-mouse', and
Also see `browse-url-secondary-browser-function' and
`browse-url-handlers'.")
-
(custom-autoload 'browse-url-browser-function "browse-url" t)
-
(defvar browse-url-default-handlers '(("\\`mailto:" . browse-url--mailto) ("\\`man:" . browse-url--man) (browse-url--non-html-file-url-p . browse-url-emacs)) "\
Like `browse-url-handlers' but populated by Emacs and packages.
Emacs and external packages capable of browsing certain URLs
should place their entries in this alist rather than
`browse-url-handlers' which is reserved for the user.")
-
(autoload 'browse-url-select-handler "browse-url" "\
Return a handler of suitable for browsing URL.
This searches `browse-url-handlers', and
@@ -2637,8 +2359,7 @@ Currently, it also consults `browse-url-browser-function' first
if it is set to an alist, although this usage is deprecated since
Emacs 28.1 and will be removed in a future release.
-\(fn URL &optional KIND)" nil nil)
-
+(fn URL &optional KIND)" nil nil)
(autoload 'browse-url-of-file "browse-url" "\
Use a web browser to display FILE.
Display the current buffer's file if FILE is nil or if called
@@ -2646,8 +2367,7 @@ interactively. Turn the filename into a URL with function
`browse-url-file-url'. Pass the URL to a browser using the
`browse-url' function then run `browse-url-of-file-hook'.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(autoload 'browse-url-of-buffer "browse-url" "\
Use a web browser to display BUFFER.
See `browse-url' for details.
@@ -2656,17 +2376,14 @@ Display the current buffer if BUFFER is nil. Display only the
currently visible part of BUFFER (from a temporary file) if buffer is
narrowed.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'browse-url-of-dired-file "browse-url" "\
In Dired, ask a WWW browser to display the file named on this line." t nil)
-
(autoload 'browse-url-of-region "browse-url" "\
Use a web browser to display the current region.
See `browse-url' for details.
-\(fn MIN MAX)" t nil)
-
+(fn MIN MAX)" t nil)
(autoload 'browse-url "browse-url" "\
Open URL using a configurable method.
This will typically (by default) open URL with an external web
@@ -2688,16 +2405,14 @@ significance of ARGS (most of the functions ignore it).
If ARGS are omitted, the default is to pass
`browse-url-new-window-flag' as ARGS.
-\(fn URL &rest ARGS)" t nil)
-
+(fn URL &rest ARGS)" t nil)
(autoload 'browse-url-at-point "browse-url" "\
Open URL at point using a configurable method.
See `browse-url' for details.
Optional prefix argument ARG non-nil inverts the value of the option
`browse-url-new-window-flag'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'browse-url-with-browser-kind "browse-url" "\
Browse URL with a browser of the given browser KIND.
KIND is either `internal' or `external'.
@@ -2705,8 +2420,7 @@ KIND is either `internal' or `external'.
When called interactively, the default browser kind is the
opposite of the browser kind of `browse-url-browser-function'.
-\(fn KIND URL &optional ARG)" t nil)
-
+(fn KIND URL &optional ARG)" t nil)
(autoload 'browse-url-at-mouse "browse-url" "\
Use a web browser to load a URL clicked with the mouse.
See `browse-url' for details.
@@ -2714,15 +2428,13 @@ See `browse-url' for details.
The URL is the one around or before the position of the mouse
click but point is not changed.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'browse-url-xdg-open "browse-url" "\
Pass the specified URL to the \"xdg-open\" command.
xdg-open is a desktop utility that calls your preferred web browser.
The optional argument IGNORED is not used.
-\(fn URL &optional IGNORED)" t nil)
-
+(fn URL &optional IGNORED)" t nil)
(autoload 'browse-url-mozilla "browse-url" "\
Ask the Mozilla WWW browser to load URL.
Default to the URL around or before point. The strings in variable
@@ -2740,8 +2452,7 @@ new tab in an existing window instead.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-firefox "browse-url" "\
Ask the Firefox WWW browser to load URL.
Defaults to the URL around or before point. Passes the strings
@@ -2758,8 +2469,7 @@ is loaded in a new tab in an existing window instead.
Non-interactively, this uses the optional second argument NEW-WINDOW
instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-chromium "browse-url" "\
Ask the Chromium WWW browser to load URL.
Default to the URL around or before point. The strings in
@@ -2767,22 +2477,24 @@ variable `browse-url-chromium-arguments' are also passed to
Chromium.
The optional argument NEW-WINDOW is not used.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-webpositive "browse-url" "\
Ask the WebPositive WWW browser to load URL.
Default to the URL around or before point.
The optional argument NEW-WINDOW is not used.
-\(fn URL &optional NEW-WINDOW)" t nil)
+(fn URL &optional NEW-WINDOW)" t nil)
+(autoload 'browse-url-default-haiku-browser "browse-url" "\
+Browse URL with the system default browser.
+Default to the URL around or before point.
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-emacs "browse-url" "\
Ask Emacs to load URL into a buffer and show it in another window.
Optional argument SAME-WINDOW non-nil means show the URL in the
currently selected window instead.
-\(fn URL &optional SAME-WINDOW)" t nil)
-
+(fn URL &optional SAME-WINDOW)" t nil)
(autoload 'browse-url-gnome-moz "browse-url" "\
Ask Mozilla to load URL via the GNOME program `gnome-moz-remote'.
Default to the URL around or before point. The strings in variable
@@ -2796,10 +2508,8 @@ effect of `browse-url-new-window-flag'.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
-(make-obsolete 'browse-url-gnome-moz 'nil '"25.1")
-
+(fn URL &optional NEW-WINDOW)" t nil)
+(make-obsolete 'browse-url-gnome-moz 'nil "25.1")
(autoload 'browse-url-conkeror "browse-url" "\
Ask the Conkeror WWW browser to load URL.
Default to the URL around or before point. Also pass the strings
@@ -2818,10 +2528,8 @@ new window, load it in a new buffer in an existing window instead.
When called non-interactively, use optional second argument
NEW-WINDOW instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
-(make-obsolete 'browse-url-conkeror 'nil '"28.1")
-
+(fn URL &optional NEW-WINDOW)" t nil)
+(make-obsolete 'browse-url-conkeror 'nil "28.1")
(autoload 'browse-url-w3 "browse-url" "\
Ask the w3 WWW browser to load URL.
Default to the URL around or before point.
@@ -2833,17 +2541,14 @@ prefix argument reverses the effect of `browse-url-new-window-flag'.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-w3-gnudoit "browse-url" "\
Ask another Emacs running gnuserv to load the URL using the W3 browser.
The `browse-url-gnudoit-program' program is used with options given by
`browse-url-gnudoit-args'. Default to the URL around or before point.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
-(make-obsolete 'browse-url-w3-gnudoit 'nil '"25.1")
-
+(fn URL &optional NEW-WINDOW)" t nil)
+(make-obsolete 'browse-url-w3-gnudoit 'nil "25.1")
(autoload 'browse-url-text-xterm "browse-url" "\
Ask a text browser to load URL.
URL defaults to the URL around or before point.
@@ -2852,8 +2557,7 @@ in an Xterm window using the Xterm program named by `browse-url-xterm-program'
with possible additional arguments `browse-url-xterm-args'.
The optional argument NEW-WINDOW is not used.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-text-emacs "browse-url" "\
Ask a text browser to load URL.
URL defaults to the URL around or before point.
@@ -2868,8 +2572,7 @@ reverses the effect of `browse-url-new-window-flag'.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-BUFFER)" t nil)
-
+(fn URL &optional NEW-BUFFER)" t nil)
(autoload 'browse-url-mail "browse-url" "\
Open a new mail message buffer within Emacs for the RFC 2368 URL.
Default to using the mailto: URL around or before point as the
@@ -2885,8 +2588,7 @@ non-nil interactive prefix argument reverses the effect of
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-generic "browse-url" "\
Ask the WWW browser defined by `browse-url-generic-program' to load URL.
Default to the URL around or before point. A fresh copy of the
@@ -2894,15 +2596,13 @@ browser is started up in a new process with possible additional arguments
`browse-url-generic-args'. This is appropriate for browsers which
don't offer a form of remote control.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-kde "browse-url" "\
Ask the KDE WWW browser to load URL.
Default to the URL around or before point.
The optional argument NEW-WINDOW is not used.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-elinks "browse-url" "\
Ask the Elinks WWW browser to load URL.
Default to the URL around the point.
@@ -2913,42 +2613,34 @@ none yet running, a newly started instance.
The Elinks command will be prepended by the program+arguments
from `browse-url-elinks-wrapper'.
-\(fn URL &optional NEW-WINDOW)" t nil)
-
+(fn URL &optional NEW-WINDOW)" t nil)
(autoload 'browse-url-button-open "browse-url" "\
Follow the link under point using `browse-url'.
If EXTERNAL (the prefix if used interactively), open with the
external browser instead of the default one.
-\(fn &optional EXTERNAL MOUSE-EVENT)" t nil)
-
+(fn &optional EXTERNAL MOUSE-EVENT)" t nil)
(autoload 'browse-url-button-open-url "browse-url" "\
Open URL using `browse-url'.
If `current-prefix-arg' is non-nil, use
`browse-url-secondary-browser-function' instead.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "browse-url" '("browse-url-"))
-;;;***
-;;;### (autoloads nil "bs" "bs.el" (0 0 0 0))
;;; Generated autoloads from bs.el
(autoload 'bs-cycle-next "bs" "\
Select next buffer defined by buffer cycling.
The buffers taking part in buffer cycling are defined
by buffer configuration `bs-cycle-configuration-name'." t nil)
-
(autoload 'bs-cycle-previous "bs" "\
Select previous buffer defined by buffer cycling.
The buffers taking part in buffer cycling are defined
by buffer configuration `bs-cycle-configuration-name'." t nil)
-
(autoload 'bs-customize "bs" "\
Customization of group bs for Buffer Selection Menu." t nil)
-
(autoload 'bs-show "bs" "\
Make a menu of buffers so you can manipulate buffers or the buffer list.
\\<bs-mode-map>
@@ -2963,13 +2655,10 @@ With prefix argument ARG show a different buffer list. Function
`bs--configuration-name-for-prefix-arg' determine accordingly
name of buffer configuration.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "bs" '("bs-"))
-;;;***
-;;;### (autoloads nil "bubbles" "play/bubbles.el" (0 0 0 0))
;;; Generated autoloads from play/bubbles.el
(autoload 'bubbles "bubbles" "\
@@ -2985,84 +2674,69 @@ columns on its right towards the left.
\\[bubbles-set-game-medium] sets the difficulty to medium.
\\[bubbles-set-game-difficult] sets the difficulty to difficult.
\\[bubbles-set-game-hard] sets the difficulty to hard." t nil)
-
(register-definition-prefixes "bubbles" '("bubbles-"))
-;;;***
-;;;### (autoloads nil "bug-reference" "progmodes/bug-reference.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from progmodes/bug-reference.el
(put 'bug-reference-url-format 'safe-local-variable (lambda (s) (or (stringp s) (and (symbolp s) (get s 'bug-reference-url-format)))))
-
(put 'bug-reference-bug-regexp 'safe-local-variable 'stringp)
-
(autoload 'bug-reference-mode "bug-reference" "\
Toggle hyperlinking bug references in the buffer (Bug Reference mode).
This is a minor mode. If called interactively, toggle the
-`Bug-Reference mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+`Bug-Reference mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `bug-reference-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'bug-reference-prog-mode "bug-reference" "\
Like `bug-reference-mode', but only buttonize in comments and strings.
This is a minor mode. If called interactively, toggle the
-`Bug-Reference-Prog mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Bug-Reference-Prog mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `bug-reference-prog-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "bug-reference" '("bug-reference-"))
-;;;***
-;;;### (autoloads nil "byte-opt" "emacs-lisp/byte-opt.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/byte-opt.el
(register-definition-prefixes "byte-opt" '("byte-" "disassemble-offset"))
-;;;***
-;;;### (autoloads nil "bytecomp" "emacs-lisp/bytecomp.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/bytecomp.el
+
(put 'byte-compile-dynamic 'safe-local-variable 'booleanp)
(put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp)
(put 'byte-compile-dynamic-docstrings 'safe-local-variable 'booleanp)
(put 'byte-compile-error-on-warn 'safe-local-variable 'booleanp)
-
(put 'byte-compile-warnings 'safe-local-variable (lambda (v) (or (symbolp v) (null (delq nil (mapcar (lambda (x) (not (symbolp x))) v))))))
-
(autoload 'byte-compile-warning-enabled-p "bytecomp" "\
Return non-nil if WARNING is enabled, according to `byte-compile-warnings'.
-\(fn WARNING &optional SYMBOL)" nil nil)
-
+(fn WARNING &optional SYMBOL)" nil nil)
(autoload 'byte-compile-disable-warning "bytecomp" "\
Change `byte-compile-warnings' to disable WARNING.
If `byte-compile-warnings' is t, set it to `(not WARNING)'.
@@ -3070,8 +2744,7 @@ Otherwise, if the first element is `not', add WARNING, else remove it.
Normally you should let-bind `byte-compile-warnings' before calling this,
else the global value will be modified.
-\(fn WARNING)" nil nil)
-
+(fn WARNING)" nil nil)
(autoload 'byte-compile-enable-warning "bytecomp" "\
Change `byte-compile-warnings' to enable WARNING.
If `byte-compile-warnings' is t, do nothing. Otherwise, if the
@@ -3079,14 +2752,12 @@ first element is `not', remove WARNING, else add it.
Normally you should let-bind `byte-compile-warnings' before calling this,
else the global value will be modified.
-\(fn WARNING)" nil nil)
-
+(fn WARNING)" nil nil)
(autoload 'byte-force-recompile "bytecomp" "\
Recompile every `.el' file in DIRECTORY that already has a `.elc' file.
Files in subdirectories of DIRECTORY are processed also.
-\(fn DIRECTORY)" t nil)
-
+(fn DIRECTORY)" t nil)
(autoload 'byte-recompile-directory "bytecomp" "\
Recompile every `.el' file in DIRECTORY that needs recompilation.
This happens when a `.elc' file exists but is older than the `.el' file.
@@ -3106,34 +2777,32 @@ This command will normally not follow symlinks when compiling
files. If FOLLOW-SYMLINKS is non-nil, symlinked `.el' files will
also be compiled.
-\(fn DIRECTORY &optional ARG FORCE FOLLOW-SYMLINKS)" t nil)
+(fn DIRECTORY &optional ARG FORCE FOLLOW-SYMLINKS)" t nil)
(put 'no-byte-compile 'safe-local-variable 'booleanp)
-
(autoload 'byte-compile-file "bytecomp" "\
Compile a file of Lisp code named FILENAME into a file of byte code.
The output file's name is generated by passing FILENAME to the
function `byte-compile-dest-file' (which see).
The value is non-nil if there were no errors, nil if errors.
+If the file sets the file variable `no-byte-compile', it is not
+compiled, any existing output file is removed, and the return
+value is `no-byte-compile'.
See also `emacs-lisp-byte-compile-and-load'.
-\(fn FILENAME &optional LOAD)" t nil)
-
+(fn FILENAME &optional LOAD)" t nil)
(set-advertised-calling-convention 'byte-compile-file '(filename) '"28.1")
-
(autoload 'compile-defun "bytecomp" "\
Compile and evaluate the current top-level form.
Print the result in the echo area.
With argument ARG, insert value in current buffer after the form.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'byte-compile "bytecomp" "\
If FORM is a symbol, byte-compile its function definition.
If FORM is a lambda or a macro, byte-compile it as a function.
-\(fn FORM)" nil nil)
-
+(fn FORM)" nil nil)
(autoload 'display-call-tree "bytecomp" "\
Display a call graph of a specified file.
This lists which functions have been called, what functions called
@@ -3143,19 +2812,17 @@ all functions called by those functions.
The call graph does not include macros, inline functions, or
primitives that the byte-code interpreter knows about directly
-\(`eq', `cons', etc.).
+(`eq', `cons', etc.).
The call tree also lists those functions which are not known to be called
-\(that is, to which no calls have been compiled), and which cannot be
+(that is, to which no calls have been compiled), and which cannot be
invoked interactively.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'batch-byte-compile-if-not-done "bytecomp" "\
Like `byte-compile-file' but doesn't recompile if already up to date.
Use this from the command line, with `-batch';
it won't work in an interactive Emacs." nil nil)
-
(autoload 'batch-byte-compile "bytecomp" "\
Run `byte-compile-file' on the files remaining on the command line.
Use this from the command line, with `-batch';
@@ -3172,8 +2839,7 @@ For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\".
If NOFORCE is non-nil, don't recompile a file that seems to be
already up-to-date.
-\(fn &optional NOFORCE)" nil nil)
-
+(fn &optional NOFORCE)" nil nil)
(autoload 'batch-byte-recompile-directory "bytecomp" "\
Run `byte-recompile-directory' on the dirs remaining on the command line.
Must be used only with `-batch', and kills Emacs on completion.
@@ -3183,61 +2849,44 @@ Optional argument ARG is passed as second argument ARG to
`byte-recompile-directory'; see there for its possible values
and corresponding effects.
-\(fn &optional ARG)" nil nil)
-
+(fn &optional ARG)" nil nil)
(register-definition-prefixes "bytecomp" '("batch-byte-compile-file" "byte" "displaying-byte-compile-warnings" "emacs-lisp-" "no-byte-compile"))
-;;;***
-;;;### (autoloads nil "cal-bahai" "calendar/cal-bahai.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from cedet/semantic/bovine/c.el
+
+(register-definition-prefixes "semantic/bovine/c" '("c-mode" "semantic"))
+
+
;;; Generated autoloads from calendar/cal-bahai.el
(register-definition-prefixes "cal-bahai" '("calendar-bahai-" "diary-bahai-" "holiday-bahai"))
-;;;***
-;;;### (autoloads nil "cal-china" "calendar/cal-china.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/cal-china.el
(put 'calendar-chinese-time-zone 'risky-local-variable t)
-
(register-definition-prefixes "cal-china" '("calendar-chinese-" "diary-chinese-" "holiday-chinese"))
-;;;***
-;;;### (autoloads nil "cal-coptic" "calendar/cal-coptic.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/cal-coptic.el
(register-definition-prefixes "cal-coptic" '("calendar-" "diary-"))
-;;;***
-;;;### (autoloads nil "cal-dst" "calendar/cal-dst.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-dst.el
(put 'calendar-daylight-savings-starts 'risky-local-variable t)
-
(put 'calendar-daylight-savings-ends 'risky-local-variable t)
-
(put 'calendar-current-time-zone-cache 'risky-local-variable t)
-
(register-definition-prefixes "cal-dst" '("calendar-" "dst-"))
-;;;***
-;;;### (autoloads nil "cal-french" "calendar/cal-french.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/cal-french.el
(register-definition-prefixes "cal-french" '("calendar-french-" "diary-french-date"))
-;;;***
-;;;### (autoloads nil "cal-hebrew" "calendar/cal-hebrew.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/cal-hebrew.el
(autoload 'calendar-hebrew-list-yahrzeits "cal-hebrew" "\
@@ -3245,164 +2894,124 @@ List Yahrzeit dates for *Gregorian* DEATH-DATE from START-YEAR to END-YEAR.
When called interactively from the calendar window, the date of death is taken
from the cursor position.
-\(fn DEATH-DATE START-YEAR END-YEAR)" t nil)
-
+(fn DEATH-DATE START-YEAR END-YEAR)" t nil)
(register-definition-prefixes "cal-hebrew" '("calendar-hebrew-" "diary-hebrew-" "holiday-hebrew"))
-;;;***
-;;;### (autoloads nil "cal-html" "calendar/cal-html.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-html.el
(register-definition-prefixes "cal-html" '("cal-html-"))
-;;;***
-;;;### (autoloads nil "cal-islam" "calendar/cal-islam.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/cal-islam.el
(register-definition-prefixes "cal-islam" '("calendar-islamic-" "diary-islamic-" "holiday-islamic"))
-;;;***
-;;;### (autoloads nil "cal-iso" "calendar/cal-iso.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-iso.el
(register-definition-prefixes "cal-iso" '("calendar-iso-" "diary-iso-date"))
-;;;***
-;;;### (autoloads nil "cal-julian" "calendar/cal-julian.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/cal-julian.el
(register-definition-prefixes "cal-julian" '("calendar-" "diary-" "holiday-julian"))
-;;;***
-;;;### (autoloads nil "cal-mayan" "calendar/cal-mayan.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/cal-mayan.el
(register-definition-prefixes "cal-mayan" '("calendar-mayan-" "diary-mayan-date"))
-;;;***
-;;;### (autoloads nil "cal-menu" "calendar/cal-menu.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-menu.el
(register-definition-prefixes "cal-menu" '("cal"))
-;;;***
-;;;### (autoloads nil "cal-move" "calendar/cal-move.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-move.el
(register-definition-prefixes "cal-move" '("calendar-"))
-;;;***
-;;;### (autoloads nil "cal-persia" "calendar/cal-persia.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/cal-persia.el
(register-definition-prefixes "cal-persia" '("calendar-persian-" "diary-persian-date"))
-;;;***
-;;;### (autoloads nil "cal-tex" "calendar/cal-tex.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-tex.el
(register-definition-prefixes "cal-tex" '("cal-tex-"))
-;;;***
-;;;### (autoloads nil "cal-x" "calendar/cal-x.el" (0 0 0 0))
;;; Generated autoloads from calendar/cal-x.el
(register-definition-prefixes "cal-x" '("calendar-" "diary-frame"))
-;;;***
-;;;### (autoloads nil "calc" "calc/calc.el" (0 0 0 0))
;;; Generated autoloads from calc/calc.el
- (define-key ctl-x-map "*" 'calc-dispatch)
+ (define-key ctl-x-map "*" 'calc-dispatch)
(autoload 'calc-dispatch "calc" "\
Invoke the GNU Emacs Calculator. See \\[calc-dispatch-help] for details.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'calc "calc" "\
The Emacs Calculator. Full documentation is listed under `calc-mode'.
-\(fn &optional ARG FULL-DISPLAY INTERACTIVE)" t nil)
-
+(fn &optional ARG FULL-DISPLAY INTERACTIVE)" t nil)
(autoload 'full-calc "calc" "\
Invoke the Calculator and give it a full-sized window.
-\(fn &optional INTERACTIVE)" t nil)
-
+(fn &optional INTERACTIVE)" t nil)
(autoload 'quick-calc "calc" "\
Do a quick calculation in the minibuffer without invoking full Calculator.
With prefix argument INSERT, insert the result in the current
buffer. Otherwise, the result is copied into the kill ring.
-\(fn &optional INSERT)" t nil)
-
+(fn &optional INSERT)" t nil)
(autoload 'calc-eval "calc" "\
Do a quick calculation and return the result as a string.
Return value will either be the formatted result in string form,
or a list containing a character position and an error message in string form.
-\(fn STR &optional SEPARATOR &rest ARGS)" nil nil)
-
+(fn STR &optional SEPARATOR &rest ARGS)" nil nil)
(autoload 'calc-keypad "calc" "\
Invoke the Calculator in \"visual keypad\" mode.
This is most useful in the X window system.
In this mode, click on the Calc \"buttons\" using the left mouse button.
Or, position the cursor manually and do \\[calc-keypad-press].
-\(fn &optional INTERACTIVE)" t nil)
-
+(fn &optional INTERACTIVE)" t nil)
(autoload 'full-calc-keypad "calc" "\
Invoke the Calculator in full-screen \"visual keypad\" mode.
See calc-keypad for details.
-\(fn &optional INTERACTIVE)" t nil)
-
+(fn &optional INTERACTIVE)" t nil)
(autoload 'calc-grab-region "calc" "\
Parse the region as a vector of numbers and push it on the Calculator stack.
-\(fn TOP BOT ARG)" t nil)
-
+(fn TOP BOT ARG)" t nil)
(autoload 'calc-grab-rectangle "calc" "\
Parse a rectangle as a matrix of numbers and push it on the Calculator stack.
-\(fn TOP BOT ARG)" t nil)
-
+(fn TOP BOT ARG)" t nil)
(autoload 'calc-grab-sum-down "calc" "\
Parse a rectangle as a matrix of numbers and sum its columns.
-\(fn TOP BOT ARG)" t nil)
-
+(fn TOP BOT ARG)" t nil)
(autoload 'calc-grab-sum-across "calc" "\
Parse a rectangle as a matrix of numbers and sum its rows.
-\(fn TOP BOT ARG)" t nil)
-
+(fn TOP BOT ARG)" t nil)
(autoload 'calc-embedded "calc" "\
Start Calc Embedded mode on the formula surrounding point.
-\(fn ARG &optional END OBEG OEND)" t nil)
-
+(fn ARG &optional END OBEG OEND)" t nil)
(autoload 'calc-embedded-activate "calc" "\
Scan the current editing buffer for all embedded := and => formulas.
Also looks for the equivalent TeX words, \\gets and \\evalto.
-\(fn &optional ARG CBUF)" t nil)
-
+(fn &optional ARG CBUF)" t nil)
(autoload 'defmath "calc" "\
Define Calc function.
@@ -3415,299 +3024,234 @@ actual Lisp function name.
See Info node `(calc)Defining Functions'.
-\(fn FUNC ARGS &rest BODY)" nil t)
-
-(function-put 'defmath 'doc-string-elt '3)
-
+(fn FUNC ARGS &rest BODY)" nil t)
+(function-put 'defmath 'doc-string-elt 3)
(function-put 'defmath 'lisp-indent-function 'defun)
-
(register-definition-prefixes "calc" '("calc" "defcalcmodevar" "inexact-result" "math-" "var-"))
-;;;***
-;;;### (autoloads nil "calc-alg" "calc/calc-alg.el" (0 0 0 0))
+;;; Generated autoloads from calc/calc-aent.el
+
+(register-definition-prefixes "calc-aent" '("calc" "math-"))
+
+
;;; Generated autoloads from calc/calc-alg.el
(register-definition-prefixes "calc-alg" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-arith" "calc/calc-arith.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-arith.el
(register-definition-prefixes "calc-arith" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-bin" "calc/calc-bin.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-bin.el
(register-definition-prefixes "calc-bin" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-comb" "calc/calc-comb.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-comb.el
(register-definition-prefixes "calc-comb" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-cplx" "calc/calc-cplx.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-cplx.el
(register-definition-prefixes "calc-cplx" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-ext" "calc/calc-ext.el" (0 0 0 0))
+;;; Generated autoloads from calc/calc-embed.el
+
+(register-definition-prefixes "calc-embed" '("calc-"))
+
+
;;; Generated autoloads from calc/calc-ext.el
(register-definition-prefixes "calc-ext" '("calc" "math-" "var-"))
-;;;***
-;;;### (autoloads nil "calc-fin" "calc/calc-fin.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-fin.el
(register-definition-prefixes "calc-fin" '("calc" "math-c"))
-;;;***
-;;;### (autoloads nil "calc-forms" "calc/calc-forms.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-forms.el
(register-definition-prefixes "calc-forms" '("calc" "math-" "var-TimeZone"))
-;;;***
-;;;### (autoloads nil "calc-frac" "calc/calc-frac.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-frac.el
(register-definition-prefixes "calc-frac" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-funcs" "calc/calc-funcs.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-funcs.el
(register-definition-prefixes "calc-funcs" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-graph" "calc/calc-graph.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-graph.el
(register-definition-prefixes "calc-graph" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-help" "calc/calc-help.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-help.el
(register-definition-prefixes "calc-help" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-incom" "calc/calc-incom.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-incom.el
(register-definition-prefixes "calc-incom" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-keypd" "calc/calc-keypd.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-keypd.el
(register-definition-prefixes "calc-keypd" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-lang" "calc/calc-lang.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-lang.el
(register-definition-prefixes "calc-lang" '("calc-" "math-"))
-;;;***
-;;;### (autoloads nil "calc-macs" "calc/calc-macs.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-macs.el
(register-definition-prefixes "calc-macs" '("Math-" "calc-" "math-"))
-;;;***
-;;;### (autoloads nil "calc-map" "calc/calc-map.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-map.el
(register-definition-prefixes "calc-map" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-math" "calc/calc-math.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-math.el
(register-definition-prefixes "calc-math" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-menu" "calc/calc-menu.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-menu.el
(register-definition-prefixes "calc-menu" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-mode" "calc/calc-mode.el" (0 0 0 0))
+;;; Generated autoloads from calc/calc-misc.el
+
+(register-definition-prefixes "calc-misc" '("math-iipow"))
+
+
;;; Generated autoloads from calc/calc-mode.el
(register-definition-prefixes "calc-mode" '("calc-" "math-get-modes-vec"))
-;;;***
-;;;### (autoloads nil "calc-mtx" "calc/calc-mtx.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-mtx.el
(register-definition-prefixes "calc-mtx" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-nlfit" "calc/calc-nlfit.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-nlfit.el
(register-definition-prefixes "calc-nlfit" '("calc-fit-" "math-nlfit-"))
-;;;***
-;;;### (autoloads nil "calc-poly" "calc/calc-poly.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-poly.el
(register-definition-prefixes "calc-poly" '("calcFunc-" "math-"))
-;;;***
-;;;### (autoloads nil "calc-prog" "calc/calc-prog.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-prog.el
(register-definition-prefixes "calc-prog" '("calc" "math-" "var-q"))
-;;;***
-;;;### (autoloads nil "calc-rewr" "calc/calc-rewr.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-rewr.el
(register-definition-prefixes "calc-rewr" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-rules" "calc/calc-rules.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-rules.el
(register-definition-prefixes "calc-rules" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-sel" "calc/calc-sel.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-sel.el
(register-definition-prefixes "calc-sel" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-stat" "calc/calc-stat.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-stat.el
(register-definition-prefixes "calc-stat" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-store" "calc/calc-store.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-store.el
(register-definition-prefixes "calc-store" '("calc"))
-;;;***
-;;;### (autoloads nil "calc-stuff" "calc/calc-stuff.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-stuff.el
(register-definition-prefixes "calc-stuff" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-trail" "calc/calc-trail.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-trail.el
(register-definition-prefixes "calc-trail" '("calc-trail-"))
-;;;***
-;;;### (autoloads nil "calc-undo" "calc/calc-undo.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-undo.el
(autoload 'calc-undo "calc-undo" "\
-\(fn N)" t nil)
-
+(fn N)" t nil)
(register-definition-prefixes "calc-undo" '("calc-"))
-;;;***
-;;;### (autoloads nil "calc-units" "calc/calc-units.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-units.el
(register-definition-prefixes "calc-units" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calc-vec" "calc/calc-vec.el" (0 0 0 0))
;;; Generated autoloads from calc/calc-vec.el
(register-definition-prefixes "calc-vec" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calcalg2" "calc/calcalg2.el" (0 0 0 0))
+;;; Generated autoloads from calc/calc-yank.el
+
+(register-definition-prefixes "calc-yank" '("calc-" "math-number-regexp"))
+
+
;;; Generated autoloads from calc/calcalg2.el
(register-definition-prefixes "calcalg2" '("calc" "math-" "var-IntegLimit"))
-;;;***
-;;;### (autoloads nil "calcalg3" "calc/calcalg3.el" (0 0 0 0))
;;; Generated autoloads from calc/calcalg3.el
(register-definition-prefixes "calcalg3" '("calc" "math-"))
-;;;***
-;;;### (autoloads nil "calccomp" "calc/calccomp.el" (0 0 0 0))
;;; Generated autoloads from calc/calccomp.el
(register-definition-prefixes "calccomp" '("calcFunc-c" "math-"))
-;;;***
-;;;### (autoloads nil "calcsel2" "calc/calcsel2.el" (0 0 0 0))
;;; Generated autoloads from calc/calcsel2.el
(register-definition-prefixes "calcsel2" '("calc-"))
-;;;***
-;;;### (autoloads nil "calculator" "calculator.el" (0 0 0 0))
;;; Generated autoloads from calculator.el
(autoload 'calculator "calculator" "\
Run the Emacs calculator.
See the documentation for `calculator-mode' for more information." t nil)
-
(register-definition-prefixes "calculator" '("calculator-"))
-;;;***
-;;;### (autoloads nil "calendar" "calendar/calendar.el" (0 0 0 0))
;;; Generated autoloads from calendar/calendar.el
(autoload 'calendar "calendar" "\
@@ -3745,94 +3289,68 @@ Runs the following hooks:
This function is suitable for execution in an init file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "calendar" '("calendar-" "diary-" "holiday-buffer" "lunar-phases-buffer" "solar-sunrises-buffer"))
-;;;***
-;;;### (autoloads nil "canlock" "gnus/canlock.el" (0 0 0 0))
;;; Generated autoloads from gnus/canlock.el
(autoload 'canlock-insert-header "canlock" "\
Insert a Cancel-Key and/or a Cancel-Lock header if possible.
-\(fn &optional ID-FOR-KEY ID-FOR-LOCK PASSWORD)" nil nil)
-
+(fn &optional ID-FOR-KEY ID-FOR-LOCK PASSWORD)" nil nil)
(autoload 'canlock-verify "canlock" "\
Verify Cancel-Lock or Cancel-Key in BUFFER.
If BUFFER is nil, the current buffer is assumed. Signal an error if
it fails.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(register-definition-prefixes "canlock" '("canlock-"))
-;;;***
-;;;### (autoloads nil "cc-align" "progmodes/cc-align.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-align.el
(register-definition-prefixes "cc-align" '("c-"))
-;;;***
-;;;### (autoloads nil "cc-awk" "progmodes/cc-awk.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-awk.el
(register-definition-prefixes "cc-awk" '("awk-" "c-awk-"))
-;;;***
-;;;### (autoloads nil "cc-bytecomp" "progmodes/cc-bytecomp.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from progmodes/cc-bytecomp.el
(register-definition-prefixes "cc-bytecomp" '("cc-"))
-;;;***
-;;;### (autoloads nil "cc-cmds" "progmodes/cc-cmds.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-cmds.el
(register-definition-prefixes "cc-cmds" '("c-"))
-;;;***
-;;;### (autoloads nil "cc-defs" "progmodes/cc-defs.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-defs.el
(register-definition-prefixes "cc-defs" '("c-" "cc-bytecomp-compiling-or-loading"))
-;;;***
-;;;### (autoloads nil "cc-engine" "progmodes/cc-engine.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/cc-engine.el
(autoload 'c-guess-basic-syntax "cc-engine" "\
Return the syntactic context of the current line." nil nil)
-
(register-definition-prefixes "cc-engine" '("c-"))
-;;;***
-;;;### (autoloads nil "cc-fonts" "progmodes/cc-fonts.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-fonts.el
(register-definition-prefixes "cc-fonts" '("autodoc-" "c++-font-lock-keywords" "c-" "doxygen-font-lock-" "gtkdoc-font-lock-" "idl-font-lock-keywords" "java" "objc-font-lock-keywords" "pike-font-lock-keywords"))
-;;;***
-;;;### (autoloads nil "cc-guess" "progmodes/cc-guess.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-guess.el
(defvar c-guess-guessed-offsets-alist nil "\
Currently guessed offsets-alist.")
-
(defvar c-guess-guessed-basic-offset nil "\
Currently guessed basic-offset.")
-
(autoload 'c-guess "cc-guess" "\
Guess the style in the region up to `c-guess-region-max', and install it.
@@ -3842,8 +3360,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
-\(fn &optional ACCUMULATE)" t nil)
-
+(fn &optional ACCUMULATE)" t nil)
(autoload 'c-guess-no-install "cc-guess" "\
Guess the style in the region up to `c-guess-region-max'; don't install it.
@@ -3851,8 +3368,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
-\(fn &optional ACCUMULATE)" t nil)
-
+(fn &optional ACCUMULATE)" t nil)
(autoload 'c-guess-buffer "cc-guess" "\
Guess the style on the whole current buffer, and install it.
@@ -3862,8 +3378,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
-\(fn &optional ACCUMULATE)" t nil)
-
+(fn &optional ACCUMULATE)" t nil)
(autoload 'c-guess-buffer-no-install "cc-guess" "\
Guess the style on the whole current buffer; don't install it.
@@ -3871,8 +3386,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
-\(fn &optional ACCUMULATE)" t nil)
-
+(fn &optional ACCUMULATE)" t nil)
(autoload 'c-guess-region "cc-guess" "\
Guess the style on the region and install it.
@@ -3882,8 +3396,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is
non-nil) then the previous guess is extended, otherwise a new guess is
made from scratch.
-\(fn START END &optional ACCUMULATE)" t nil)
-
+(fn START END &optional ACCUMULATE)" t nil)
(autoload 'c-guess-region-no-install "cc-guess" "\
Guess the style on the region; don't install it.
@@ -3907,41 +3420,33 @@ guess is made from scratch.
Note that the larger the region to guess in, the slower the guessing.
So you can limit the region with `c-guess-region-max'.
-\(fn START END &optional ACCUMULATE)" t nil)
-
+(fn START END &optional ACCUMULATE)" t nil)
(autoload 'c-guess-install "cc-guess" "\
Install the latest guessed style into the current buffer.
-\(This guessed style is a combination of `c-guess-guessed-basic-offset',
+(This guessed style is a combination of `c-guess-guessed-basic-offset',
`c-guess-guessed-offsets-alist' and `c-offsets-alist'.)
The style is entered into CC Mode's style system by
`c-add-style'. Its name is either STYLE-NAME, or a name based on
the absolute file name of the file if STYLE-NAME is nil.
-\(fn &optional STYLE-NAME)" t nil)
-
+(fn &optional STYLE-NAME)" t nil)
(register-definition-prefixes "cc-guess" '("c-guess-"))
-;;;***
-;;;### (autoloads nil "cc-langs" "progmodes/cc-langs.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-langs.el
(register-definition-prefixes "cc-langs" '("c-"))
-;;;***
-;;;### (autoloads nil "cc-menus" "progmodes/cc-menus.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-menus.el
(register-definition-prefixes "cc-menus" '("cc-imenu-"))
-;;;***
-;;;### (autoloads nil "cc-mode" "progmodes/cc-mode.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-mode.el
-(push (purecopy '(cc-mode 5 33 1)) package--builtin-versions)
+(push (purecopy '(cc-mode 5 33 1)) package--builtin-versions)
(autoload 'c-initialize-cc-mode "cc-mode" "\
Initialize CC Mode for use in the current buffer.
If the optional NEW-STYLE-INIT is nil or left out then all necessary
@@ -3950,7 +3455,7 @@ only some basic setup is done, and a call to `c-init-language-vars' or
`c-init-language-vars-for' is necessary too (which gives more
control). See \"cc-mode.el\" for more info.
-\(fn &optional NEW-STYLE-INIT)" nil nil)
+(fn &optional NEW-STYLE-INIT)" nil nil)
(add-to-list 'auto-mode-alist '("\\.\\(cc\\|hh\\)\\'" . c++-mode))
(add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode))
(add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode))
@@ -3960,7 +3465,6 @@ control). See \"cc-mode.el\" for more info.
(add-to-list 'auto-mode-alist '("\\.lex\\'" . c-mode))
(add-to-list 'auto-mode-alist '("\\.i\\'" . c-mode))
(add-to-list 'auto-mode-alist '("\\.ii\\'" . c++-mode))
-
(autoload 'c-mode "cc-mode" "\
Major mode for editing C code.
@@ -3977,8 +3481,7 @@ initialization, then `c-mode-hook'.
Key bindings:
\\{c-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'c-or-c++-mode "cc-mode" "\
Analyze buffer and enable either C or C++ mode.
@@ -3990,7 +3493,6 @@ should be used.
This function attempts to use file contents to determine whether
the code is C or C++ and based on that chooses whether to enable
`c-mode' or `c++-mode'." t nil)
-
(autoload 'c++-mode "cc-mode" "\
Major mode for editing C++ code.
To submit a problem report, enter `\\[c-submit-bug-report]' from a
@@ -4007,9 +3509,8 @@ initialization, then `c++-mode-hook'.
Key bindings:
\\{c++-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode))
-
(autoload 'objc-mode "cc-mode" "\
Major mode for editing Objective C code.
To submit a problem report, enter `\\[c-submit-bug-report]' from an
@@ -4026,9 +3527,8 @@ initialization, then `objc-mode-hook'.
Key bindings:
\\{objc-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode))
-
(autoload 'java-mode "cc-mode" "\
Major mode for editing Java code.
To submit a problem report, enter `\\[c-submit-bug-report]' from a
@@ -4045,9 +3545,8 @@ initialization, then `java-mode-hook'.
Key bindings:
\\{java-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode))
-
(autoload 'idl-mode "cc-mode" "\
Major mode for editing CORBA's IDL, PSDL and CIDL code.
To submit a problem report, enter `\\[c-submit-bug-report]' from an
@@ -4064,10 +3563,9 @@ initialization, then `idl-mode-hook'.
Key bindings:
\\{idl-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode))
(add-to-list 'interpreter-mode-alist '("pike" . pike-mode))
-
(autoload 'pike-mode "cc-mode" "\
Major mode for editing Pike code.
To submit a problem report, enter `\\[c-submit-bug-report]' from a
@@ -4084,13 +3582,12 @@ initialization, then `pike-mode-hook'.
Key bindings:
\\{pike-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode))
(add-to-list 'interpreter-mode-alist '("awk" . awk-mode))
(add-to-list 'interpreter-mode-alist '("mawk" . awk-mode))
(add-to-list 'interpreter-mode-alist '("nawk" . awk-mode))
(add-to-list 'interpreter-mode-alist '("gawk" . awk-mode))
-
(autoload 'awk-mode "cc-mode" "\
Major mode for editing AWK code.
To submit a problem report, enter `\\[c-submit-bug-report]' from an
@@ -4106,14 +3603,10 @@ initialization, then `awk-mode-hook'.
Key bindings:
\\{awk-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "cc-mode" '("awk-mode-map" "c++-mode-" "c-" "idl-mode-" "java-mode-" "objc-mode-" "pike-mode-"))
-;;;***
-;;;### (autoloads nil "cc-styles" "progmodes/cc-styles.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/cc-styles.el
(autoload 'c-set-style "cc-styles" "\
@@ -4139,8 +3632,7 @@ calls c-set-style internally in this way whilst initializing a buffer; if
c-set-style is called like this from anywhere else, it will usually behave as
a null operation.
-\(fn STYLENAME &optional DONT-OVERRIDE)" t nil)
-
+(fn STYLENAME &optional DONT-OVERRIDE)" t nil)
(autoload 'c-add-style "cc-styles" "\
Add a style to `c-style-alist', or update an existing one.
STYLE is a string identifying the style to add or update. DESCRIPTION
@@ -4152,43 +3644,35 @@ See the variable `c-style-alist' for the semantics of BASESTYLE,
VARIABLE and VALUE. This function also sets the current style to
STYLE using `c-set-style' if the optional SET-P flag is non-nil.
-\(fn STYLE DESCRIPTION &optional SET-P)" t nil)
-
+(fn STYLE DESCRIPTION &optional SET-P)" t nil)
(autoload 'c-set-offset "cc-styles" "\
Change the value of a syntactic element symbol in `c-offsets-alist'.
SYMBOL is the syntactic element symbol to change and OFFSET is the new
offset for that syntactic element. The optional argument is not used
and exists only for compatibility reasons.
-\(fn SYMBOL OFFSET &optional IGNORED)" t nil)
-
+(fn SYMBOL OFFSET &optional IGNORED)" t nil)
(register-definition-prefixes "cc-styles" '("c-" "cc-choose-style-for-mode"))
-;;;***
-;;;### (autoloads nil "cc-vars" "progmodes/cc-vars.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cc-vars.el
+
(put 'c-basic-offset 'safe-local-variable 'integerp)
(put 'c-backslash-column 'safe-local-variable 'integerp)
(put 'c-file-style 'safe-local-variable 'string-or-null-p)
-
(register-definition-prefixes "cc-vars" '("awk-mode-hook" "c++-" "c-" "defcustom-c-stylevar" "idl-" "java-" "objc-" "pike-"))
-;;;***
-;;;### (autoloads nil "ccl" "international/ccl.el" (0 0 0 0))
;;; Generated autoloads from international/ccl.el
(autoload 'ccl-compile "ccl" "\
Return the compiled code of CCL-PROGRAM as a vector of integers.
-\(fn CCL-PROGRAM)" nil nil)
-
+(fn CCL-PROGRAM)" nil nil)
(autoload 'ccl-dump "ccl" "\
Disassemble compiled CCL-code CODE.
-\(fn CODE)" nil nil)
-
+(fn CODE)" nil nil)
(autoload 'declare-ccl-program "ccl" "\
Declare NAME as a name of CCL program.
@@ -4200,8 +3684,7 @@ execution.
Optional arg VECTOR is a compiled CCL code of the CCL program.
-\(fn NAME &optional VECTOR)" nil t)
-
+(fn NAME &optional VECTOR)" nil t)
(autoload 'define-ccl-program "ccl" "\
Set NAME the compiled code of CCL-PROGRAM.
@@ -4446,12 +3929,9 @@ MAP-IDs := MAP-ID ...
MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET
MAP-ID := integer
-\(fn NAME CCL-PROGRAM &optional DOC)" nil t)
-
-(function-put 'define-ccl-program 'doc-string-elt '3)
-
+(fn NAME CCL-PROGRAM &optional DOC)" nil t)
+(function-put 'define-ccl-program 'doc-string-elt 3)
(function-put 'define-ccl-program 'lisp-indent-function 'defun)
-
(autoload 'check-ccl-program "ccl" "\
Check validity of CCL-PROGRAM.
If CCL-PROGRAM is a symbol denoting a CCL program, return
@@ -4459,87 +3939,63 @@ CCL-PROGRAM, else return nil.
If CCL-PROGRAM is a vector and optional arg NAME (symbol) is supplied,
register CCL-PROGRAM by name NAME, and return NAME.
-\(fn CCL-PROGRAM &optional NAME)" nil t)
-
+(fn CCL-PROGRAM &optional NAME)" nil t)
(autoload 'ccl-execute-with-args "ccl" "\
Execute CCL-PROGRAM with registers initialized by the remaining args.
The return value is a vector of resulting CCL registers.
See the documentation of `define-ccl-program' for the detail of CCL program.
-\(fn CCL-PROG &rest ARGS)" nil nil)
-
+(fn CCL-PROG &rest ARGS)" nil nil)
(register-definition-prefixes "ccl" '("ccl-"))
-;;;***
-;;;### (autoloads nil "cconv" "emacs-lisp/cconv.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/cconv.el
(autoload 'cconv-closure-convert "cconv" "\
Main entry point for closure conversion.
--- FORM is a piece of Elisp code after macroexpansion.
--- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST
+FORM is a piece of Elisp code after macroexpansion.
Returns a form where all lambdas don't have any free variables.
-\(fn FORM)" nil nil)
-
+(fn FORM)" nil nil)
(register-definition-prefixes "cconv" '("cconv-"))
-;;;***
-;;;### (autoloads nil "cdl" "cdl.el" (0 0 0 0))
;;; Generated autoloads from cdl.el
(register-definition-prefixes "cdl" '("cdl-"))
-;;;***
-;;;### (autoloads nil "cedet" "cedet/cedet.el" (0 0 0 0))
;;; Generated autoloads from cedet/cedet.el
-(push (purecopy '(cedet 2 0)) package--builtin-versions)
+(push (purecopy '(cedet 2 0)) package--builtin-versions)
(register-definition-prefixes "cedet" '("cedet-"))
-;;;***
-;;;### (autoloads nil "cedet-cscope" "cedet/cedet-cscope.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from cedet/cedet-cscope.el
(register-definition-prefixes "cedet-cscope" '("cedet-cscope-"))
-;;;***
-;;;### (autoloads nil "cedet-files" "cedet/cedet-files.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from cedet/cedet-files.el
(register-definition-prefixes "cedet-files" '("cedet-"))
-;;;***
-;;;### (autoloads nil "cedet-global" "cedet/cedet-global.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from cedet/cedet-global.el
(register-definition-prefixes "cedet-global" '("cedet-g"))
-;;;***
-;;;### (autoloads nil "cedet-idutils" "cedet/cedet-idutils.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from cedet/cedet-idutils.el
(register-definition-prefixes "cedet-idutils" '("cedet-idutils-"))
-;;;***
-;;;### (autoloads nil "cfengine" "progmodes/cfengine.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cfengine.el
-(push (purecopy '(cfengine 1 4)) package--builtin-versions)
+(push (purecopy '(cfengine 1 4)) package--builtin-versions)
(autoload 'cfengine3-mode "cfengine" "\
Major mode for editing CFEngine3 input.
There are no special keybindings by default.
@@ -4547,8 +4003,7 @@ There are no special keybindings by default.
Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves
to the action header.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'cfengine2-mode "cfengine" "\
Major mode for editing CFEngine2 input.
There are no special keybindings by default.
@@ -4556,16 +4011,12 @@ There are no special keybindings by default.
Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves
to the action header.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'cfengine-auto-mode "cfengine" "\
Choose `cfengine2-mode' or `cfengine3-mode' by buffer contents." t nil)
-
(register-definition-prefixes "cfengine" '("cfengine"))
-;;;***
-;;;### (autoloads nil "char-fold" "char-fold.el" (0 0 0 0))
;;; Generated autoloads from char-fold.el
(autoload 'char-fold-to-regexp "char-fold" "\
@@ -4586,42 +4037,37 @@ just return the result of calling `regexp-quote' on STRING.
FROM is for internal use. It specifies an index in the STRING
from which to start.
-\(fn STRING &optional LAX FROM)" nil nil)
-
+(fn STRING &optional LAX FROM)" nil nil)
(register-definition-prefixes "char-fold" '("char-fold-"))
-;;;***
-;;;### (autoloads nil "chart" "emacs-lisp/chart.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/chart.el
(register-definition-prefixes "chart" '("chart"))
-;;;***
-;;;### (autoloads nil "check-declare" "emacs-lisp/check-declare.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/chart.el
+
+(register-definition-prefixes "semantic/chart" '("semantic-chart-"))
+
+
;;; Generated autoloads from emacs-lisp/check-declare.el
(autoload 'check-declare-file "check-declare" "\
Check veracity of all `declare-function' statements in FILE.
See `check-declare-directory' for more information.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'check-declare-directory "check-declare" "\
Check veracity of all `declare-function' statements under directory ROOT.
Returns non-nil if any false statements are found.
-\(fn ROOT)" t nil)
-
+(fn ROOT)" t nil)
(register-definition-prefixes "check-declare" '("check-declare-"))
-;;;***
-;;;### (autoloads nil "checkdoc" "emacs-lisp/checkdoc.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/checkdoc.el
+
(put 'checkdoc-force-docstrings-flag 'safe-local-variable #'booleanp)
(put 'checkdoc-force-history-flag 'safe-local-variable #'booleanp)
(put 'checkdoc-permit-comma-termination-flag 'safe-local-variable #'booleanp)
@@ -4630,19 +4076,16 @@ Returns non-nil if any false statements are found.
(put 'checkdoc-arguments-in-order-flag 'safe-local-variable #'booleanp)
(put 'checkdoc-verb-check-experimental-flag 'safe-local-variable #'booleanp)
(put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p)
-
(autoload 'checkdoc-list-of-strings-p "checkdoc" "\
Return t when OBJ is a list of strings.
-\(fn OBJ)" nil nil)
+(fn OBJ)" nil nil)
(put 'checkdoc-proper-noun-regexp 'safe-local-variable 'stringp)
(put 'checkdoc-common-verbs-regexp 'safe-local-variable 'stringp)
-
(autoload 'checkdoc "checkdoc" "\
Interactively check the entire buffer for style errors.
The current status of the check will be displayed in a buffer which
the users will view as each check is completed." '(emacs-lisp-mode) nil)
-
(autoload 'checkdoc-interactive "checkdoc" "\
Interactively check the current buffer for doc string errors.
Prefix argument START-HERE will start the checking from the current
@@ -4652,8 +4095,7 @@ errors. Does not check for comment or space warnings.
Optional argument SHOWSTATUS indicates that we should update the
checkdoc status window instead of the usual behavior.
-\(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil)
-
+(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-message-interactive "checkdoc" "\
Interactively check the current buffer for message string errors.
Prefix argument START-HERE will start the checking from the current
@@ -4663,27 +4105,23 @@ errors. Does not check for comment or space warnings.
Optional argument SHOWSTATUS indicates that we should update the
checkdoc status window instead of the usual behavior.
-\(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil)
-
+(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-eval-current-buffer "checkdoc" "\
Evaluate and check documentation for the current buffer.
Evaluation is done first because good documentation for something that
doesn't work is just not useful. Comments, doc strings, and rogue
spacing are all verified." t nil)
-
(autoload 'checkdoc-current-buffer "checkdoc" "\
Check current buffer for document, comment, error style, and rogue spaces.
With a prefix argument (in Lisp, the argument TAKE-NOTES),
store all errors found in a warnings buffer,
otherwise stop after the first error.
-\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-file "checkdoc" "\
Check FILE for document, comment, error style, and rogue spaces.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'checkdoc-start "checkdoc" "\
Start scanning the current buffer for documentation string style errors.
Only documentation strings are checked.
@@ -4691,23 +4129,20 @@ Use `checkdoc-continue' to continue checking if an error cannot be fixed.
Prefix argument TAKE-NOTES means to collect all the warning messages into
a separate buffer.
-\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-continue "checkdoc" "\
Find the next doc string in the current buffer which has a style error.
Prefix argument TAKE-NOTES means to continue through the whole
buffer and save warnings in a separate buffer.
-\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-comments "checkdoc" "\
Find missing comment sections in the current Emacs Lisp file.
Prefix argument TAKE-NOTES non-nil means to save warnings in a
separate buffer. Otherwise print a message. This returns the error
if there is one.
-\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-rogue-spaces "checkdoc" "\
Find extra spaces at the end of lines in the current file.
Prefix argument TAKE-NOTES non-nil means to save warnings in a
@@ -4715,20 +4150,17 @@ separate buffer. Otherwise print a message. This returns the error
if there is one.
Optional argument INTERACT permits more interactive fixing.
-\(fn &optional TAKE-NOTES INTERACT)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES INTERACT)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-message-text "checkdoc" "\
Scan the buffer for occurrences of the error function, and verify text.
Optional argument TAKE-NOTES causes all errors to be logged.
-\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
-
+(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil)
(autoload 'checkdoc-eval-defun "checkdoc" "\
Evaluate the current form with `eval-defun' and check its documentation.
Evaluation is done first so the form will be read before the
documentation is checked. If there is a documentation error, then the display
of what was evaluated will be overwritten by the diagnostic message." t nil)
-
(autoload 'checkdoc-defun "checkdoc" "\
Examine the doc string of the function or variable under point.
Call `error' if the doc string has problems. If NO-ERROR is
@@ -4736,130 +4168,106 @@ non-nil, then do not call error, but call `message' instead.
If the doc string passes the test, then check the function for rogue white
space at the end of each line.
-\(fn &optional NO-ERROR)" t nil)
-
+(fn &optional NO-ERROR)" t nil)
(autoload 'checkdoc-dired "checkdoc" "\
In Dired, run `checkdoc' on marked files.
Skip anything that doesn't have the Emacs Lisp library file
extension (\".el\").
When called from Lisp, FILES is a list of filenames.
-\(fn FILES)" '(dired-mode) nil)
-
+(fn FILES)" '(dired-mode) nil)
(autoload 'checkdoc-ispell "checkdoc" "\
Check the style and spelling of everything interactively.
Calls `checkdoc' with spell-checking turned on.
Prefix argument is the same as for `checkdoc'." t nil)
-
(autoload 'checkdoc-ispell-current-buffer "checkdoc" "\
Check the style and spelling of the current buffer.
Calls `checkdoc-current-buffer' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-current-buffer'." t nil)
-
(autoload 'checkdoc-ispell-interactive "checkdoc" "\
Check the style and spelling of the current buffer interactively.
Calls `checkdoc-interactive' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-interactive'." t nil)
-
(autoload 'checkdoc-ispell-message-interactive "checkdoc" "\
Check the style and spelling of message text interactively.
Calls `checkdoc-message-interactive' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-message-interactive'." t nil)
-
(autoload 'checkdoc-ispell-message-text "checkdoc" "\
Check the style and spelling of message text interactively.
Calls `checkdoc-message-text' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-message-text'." t nil)
-
(autoload 'checkdoc-ispell-start "checkdoc" "\
Check the style and spelling of the current buffer.
Calls `checkdoc-start' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-start'." t nil)
-
(autoload 'checkdoc-ispell-continue "checkdoc" "\
Check the style and spelling of the current buffer after point.
Calls `checkdoc-continue' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-continue'." t nil)
-
(autoload 'checkdoc-ispell-comments "checkdoc" "\
Check the style and spelling of the current buffer's comments.
Calls `checkdoc-comments' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-comments'." t nil)
-
(autoload 'checkdoc-ispell-defun "checkdoc" "\
Check the style and spelling of the current defun with Ispell.
Calls `checkdoc-defun' with spell-checking turned on.
Prefix argument is the same as for `checkdoc-defun'." t nil)
-
(autoload 'checkdoc-minor-mode "checkdoc" "\
Toggle automatic docstring checking (Checkdoc minor mode).
-This is a minor mode. If called interactively, toggle the `Checkdoc
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `checkdoc-minor-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
In Checkdoc minor mode, the usual bindings for `eval-defun' which is
bound to \\<checkdoc-minor-mode-map>\\[checkdoc-eval-defun] and `checkdoc-eval-current-buffer' are overridden to include
checking of documentation strings.
\\{checkdoc-minor-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Checkdoc minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `checkdoc-minor-mode'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'checkdoc-package-keywords "checkdoc" "\
Find package keywords that aren't in `finder-known-keywords'." t nil)
-
(register-definition-prefixes "checkdoc" '("checkdoc-"))
-;;;***
-;;;### (autoloads nil "china-util" "language/china-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/china-util.el
(autoload 'decode-hz-region "china-util" "\
Decode HZ/ZW encoded text in the current region.
Return the length of resulting text.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'decode-hz-buffer "china-util" "\
Decode HZ/ZW encoded text in the current buffer." t nil)
-
(autoload 'encode-hz-region "china-util" "\
Encode the text in the current region to HZ.
Return the length of resulting text.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'encode-hz-buffer "china-util" "\
Encode the text in the current buffer to HZ." t nil)
-
(autoload 'post-read-decode-hz "china-util" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'pre-write-encode-hz "china-util" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(register-definition-prefixes "china-util" '("decode-hz-line-continuation" "hz-" "hz/zw-start-gb" "iso2022-" "zw-start-gb"))
-;;;***
-;;;### (autoloads nil "chistory" "chistory.el" (0 0 0 0))
;;; Generated autoloads from chistory.el
(autoload 'repeat-matching-complex-command "chistory" "\
@@ -4869,8 +4277,7 @@ a form for evaluation. If PATTERN is empty (or nil), every form in the
command history is offered. The form is placed in the minibuffer for
editing and the result is evaluated.
-\(fn &optional PATTERN)" t nil)
-
+(fn &optional PATTERN)" t nil)
(autoload 'list-command-history "chistory" "\
List history of commands that used the minibuffer.
The number of commands listed is controlled by `list-command-history-max'.
@@ -4878,26 +4285,26 @@ Calls value of `list-command-history-filter' (if non-nil) on each history
element to judge if that element should be excluded from the list.
The buffer is left in Command History mode." t nil)
-
(autoload 'command-history "chistory" "\
Examine commands from variable `command-history' in a buffer.
The number of commands listed is controlled by `list-command-history-max'.
The command history is filtered by `list-command-history-filter' if non-nil.
-Use \\<command-history-map>\\[command-history-repeat] to repeat the command on the current line.
+Use \\<command-history-mode-map>\\[command-history-repeat] to repeat the command on the current line.
Otherwise much like Emacs-Lisp Mode except that there is no self-insertion
and digits provide prefix arguments. Tab does not indent.
-\\{command-history-map}
+\\{command-history-mode-map}
This command always recompiles the Command History listing
and runs the normal hook `command-history-hook'." t nil)
-
(register-definition-prefixes "chistory" '("command-history-" "default-command-history-filter" "list-command-history-"))
-;;;***
-;;;### (autoloads nil "cl-font-lock" "progmodes/cl-font-lock.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from emacs-lisp/cl-extra.el
+
+(register-definition-prefixes "cl-extra" '("cl-"))
+
+
;;; Generated autoloads from progmodes/cl-font-lock.el
(defvar cl-font-lock-built-in-mode nil "\
@@ -4907,38 +4314,32 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `cl-font-lock-built-in-mode'.")
-
(custom-autoload 'cl-font-lock-built-in-mode "cl-font-lock" nil)
-
(autoload 'cl-font-lock-built-in-mode "cl-font-lock" "\
Highlight built-in functions, variables, and types in `lisp-mode'.
-This is a minor mode. If called interactively, toggle the
+This is a global minor mode. If called interactively, toggle the
`Cl-Font-Lock-Built-In mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='cl-font-lock-built-in-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "cl-font-lock" '("cl-font-lock-"))
-;;;***
-;;;### (autoloads nil "cl-generic" "emacs-lisp/cl-generic.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/cl-generic.el
-(push (purecopy '(cl-generic 1 0)) package--builtin-versions)
+(push (purecopy '(cl-generic 1 0)) package--builtin-versions)
(autoload 'cl-defgeneric "cl-generic" "\
Create a generic function NAME.
DOC-STRING is the base documentation for this class. A generic
@@ -4952,17 +4353,13 @@ OPTIONS-AND-METHODS currently understands:
- (:method [QUALIFIERS...] ARGS &rest BODY)
DEFAULT-BODY, if present, is used as the body of a default method.
-\(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil t)
-
-(function-put 'cl-defgeneric 'lisp-indent-function '2)
-
-(function-put 'cl-defgeneric 'doc-string-elt '3)
-
+(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil t)
+(function-put 'cl-defgeneric 'lisp-indent-function 2)
+(function-put 'cl-defgeneric 'doc-string-elt 3)
(autoload 'cl-generic-define "cl-generic" "\
-\(fn NAME ARGS OPTIONS)" nil nil)
-
+(fn NAME ARGS OPTIONS)" nil nil)
(autoload 'cl-defmethod "cl-generic" "\
Define a new method for generic function NAME.
This defines an implementation of NAME to use for invocations
@@ -4993,7 +4390,7 @@ the method is combined with other methods, including:
:around - Method will be called around everything else
The absence of QUALIFIER means this is a \"primary\" method.
The set of acceptable qualifiers and their meaning is defined
-\(and can be extended) by the methods of `cl-generic-combine-methods'.
+(and can be extended) by the methods of `cl-generic-combine-methods'.
ARGS can also include so-called context specializers, introduced by
`&context' (which should appear right after the mandatory arguments,
@@ -5002,30 +4399,22 @@ EXPR is an Elisp expression whose value should match TYPE for the
method to be applicable.
The set of acceptable TYPEs (also called \"specializers\") is defined
-\(and can be extended) by the various methods of `cl-generic-generalizers'.
-
-\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t)
+(and can be extended) by the various methods of `cl-generic-generalizers'.
+(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t)
(function-put 'cl-defmethod 'doc-string-elt 'cl--defmethod-doc-pos)
-
(function-put 'cl-defmethod 'lisp-indent-function 'defun)
-
(autoload 'cl-generic-define-method "cl-generic" "\
-\(fn NAME QUALIFIERS ARGS USES-CNM FUNCTION)" nil nil)
-
+(fn NAME QUALIFIERS ARGS CALL-CON FUNCTION)" nil nil)
(autoload 'cl-find-method "cl-generic" "\
-\(fn GENERIC QUALIFIERS SPECIALIZERS)" nil nil)
-
+(fn GENERIC QUALIFIERS SPECIALIZERS)" nil nil)
(register-definition-prefixes "cl-generic" '("cl-"))
-;;;***
-;;;### (autoloads nil "cl-indent" "emacs-lisp/cl-indent.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/cl-indent.el
(autoload 'common-lisp-indent-function "cl-indent" "\
@@ -5093,7 +4482,7 @@ property are:
specifies how to indent the associated argument.
For example, the function `case' has an indent property
-\(4 &rest (&whole 2 &rest 1)), meaning:
+(4 &rest (&whole 2 &rest 1)), meaning:
* indent the first argument by 4.
* arguments after the first should be lists, and there may be any number
of them. The first list element has an offset of 2, all the rest
@@ -5104,18 +4493,15 @@ If the current mode is actually `emacs-lisp-mode', look for a
at `common-lisp-indent-function' and, if set, use its value
instead.
-\(fn INDENT-POINT STATE)" nil nil)
-
+(fn INDENT-POINT STATE)" nil nil)
(register-definition-prefixes "cl-indent" '("common-lisp-" "lisp-"))
-;;;***
-;;;### (autoloads nil "cl-lib" "emacs-lisp/cl-lib.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/cl-lib.el
-(push (purecopy '(cl-lib 1 0)) package--builtin-versions)
-
-(define-obsolete-variable-alias 'custom-print-functions 'cl-custom-print-functions "24.3")
+(push (purecopy '(cl-lib 1 0)) package--builtin-versions)
+(define-obsolete-variable-alias 'custom-print-functions 'cl-custom-print-functions "\
+24.3")
(defvar cl-custom-print-functions nil "\
This is a list of functions that format user objects for printing.
Each function is called in turn with three arguments: the object, the
@@ -5125,14 +4511,15 @@ printer proceeds to the next function on the list.
This variable is not used at present, but it is defined in hopes that
a future Emacs interpreter will be able to use it.")
-
(autoload 'cl-incf "cl-lib" "\
Increment PLACE by X (1 by default).
PLACE may be a symbol, or any generalized variable allowed by `setf'.
The return value is the incremented value of PLACE.
-\(fn PLACE &optional X)" nil t)
+If X is specified, it should be an expression that should
+evaluate to a number.
+(fn PLACE &optional X)" nil t)
(defvar cl-old-struct-compat-mode nil "\
Non-nil if Cl-Old-Struct-Compat mode is enabled.
See the `cl-old-struct-compat-mode' command
@@ -5140,55 +4527,54 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `cl-old-struct-compat-mode'.")
-
(custom-autoload 'cl-old-struct-compat-mode "cl-lib" nil)
-
(autoload 'cl-old-struct-compat-mode "cl-lib" "\
Enable backward compatibility with old-style structs.
+
This can be needed when using code byte-compiled using the old
macro-expansion of `cl-defstruct' that used vectors objects instead
of record objects.
-This is a minor mode. If called interactively, toggle the
-`Cl-Old-Struct-Compat mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Cl-Old-Struct-Compat mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='cl-old-struct-compat-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "cl-lib" '("cl-"))
-;;;***
-;;;### (autoloads nil "cl-print" "emacs-lisp/cl-print.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from emacs-lisp/cl-macs.el
+
+(register-definition-prefixes "cl-macs" '("cl-" "foo" "function-form"))
+
+
;;; Generated autoloads from emacs-lisp/cl-print.el
-(push (purecopy '(cl-print 1 0)) package--builtin-versions)
+(push (purecopy '(cl-print 1 0)) package--builtin-versions)
(autoload 'cl-print-object "cl-print" "\
Dispatcher to print OBJECT on STREAM according to its type.
You can add methods to it to customize the output.
But if you just want to print something, don't call this directly:
call other entry points instead, such as `cl-prin1'.
-\(fn OBJECT STREAM)" nil nil)
-
+(fn OBJECT STREAM)" nil nil)
(autoload 'cl-print-expand-ellipsis "cl-print" "\
Print the expansion of an ellipsis to STREAM.
VALUE should be the value of the `cl-print-ellipsis' text property
which was attached to the ellipsis by `cl-prin1'.
-\(fn VALUE STREAM)" nil nil)
-
+(fn VALUE STREAM)" nil nil)
(autoload 'cl-prin1 "cl-print" "\
Print OBJECT on STREAM according to its type.
Output is further controlled by the variables
@@ -5196,13 +4582,11 @@ Output is further controlled by the variables
variables for the standard printing functions. See Info
node `(elisp)Output Variables'.
-\(fn OBJECT &optional STREAM)" nil nil)
-
+(fn OBJECT &optional STREAM)" nil nil)
(autoload 'cl-prin1-to-string "cl-print" "\
Return a string containing the `cl-prin1'-printed representation of OBJECT.
-\(fn OBJECT)" nil nil)
-
+(fn OBJECT)" nil nil)
(autoload 'cl-print-to-string-with-limit "cl-print" "\
Return a string containing a printed representation of VALUE.
Attempt to get the length of the returned string under LIMIT
@@ -5219,13 +4603,15 @@ this function with `cl-prin1-expand-ellipsis' to expand an
ellipsis, abbreviating the expansion to stay within a size
limit.
-\(fn PRINT-FUNCTION VALUE LIMIT)" nil nil)
-
+(fn PRINT-FUNCTION VALUE LIMIT)" nil nil)
(register-definition-prefixes "cl-print" '("cl-print-" "help-byte-code"))
-;;;***
-;;;### (autoloads nil "cmacexp" "progmodes/cmacexp.el" (0 0 0 0))
+;;; Generated autoloads from emacs-lisp/cl-seq.el
+
+(register-definition-prefixes "cl-seq" '("cl--"))
+
+
;;; Generated autoloads from progmodes/cmacexp.el
(autoload 'c-macro-expand "cmacexp" "\
@@ -5241,13 +4627,10 @@ otherwise use `c-macro-cppflags'.
Noninteractive args are START, END, SUBST.
For use inside Lisp programs, see also `c-macro-expansion'.
-\(fn START END SUBST)" t nil)
-
+(fn START END SUBST)" t nil)
(register-definition-prefixes "cmacexp" '("c-macro-"))
-;;;***
-;;;### (autoloads nil "cmuscheme" "cmuscheme.el" (0 0 0 0))
;;; Generated autoloads from cmuscheme.el
(autoload 'run-scheme "cmuscheme" "\
@@ -5261,15 +4644,12 @@ Note that this may lose due to a timing error if the Scheme processor
discards input when it starts up.
Runs the hook `inferior-scheme-mode-hook' (after the `comint-mode-hook'
is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)
-
-\(fn CMD)" t nil)
+(Type \\[describe-mode] in the process buffer for a list of commands.)
+(fn CMD)" t nil)
(register-definition-prefixes "cmuscheme" '("cmuscheme-load-hook" "inferior-scheme-" "scheme-" "switch-to-scheme"))
-;;;***
-;;;### (autoloads nil "color" "color.el" (0 0 0 0))
;;; Generated autoloads from color.el
(autoload 'color-name-to-rgb "color" "\
@@ -5277,6 +4657,10 @@ Convert COLOR string to a list of normalized RGB components.
COLOR should be a color name (e.g. \"white\") or an RGB triplet
string (e.g. \"#ffff1122eecc\").
+COLOR can also be the symbol `unspecified' or one of the strings
+\"unspecified-fg\" or \"unspecified-bg\", in which case the
+return value is nil.
+
Normally the return value is a list of three floating-point
numbers, (RED GREEN BLUE), each between 0.0 and 1.0 inclusive.
@@ -5284,13 +4668,10 @@ Optional argument FRAME specifies the frame where the color is to be
displayed. If FRAME is omitted or nil, use the selected frame.
If FRAME cannot display COLOR, return nil.
-\(fn COLOR &optional FRAME)" nil nil)
-
+(fn COLOR &optional FRAME)" nil nil)
(register-definition-prefixes "color" '("color-"))
-;;;***
-;;;### (autoloads nil "comint" "comint.el" (0 0 0 0))
;;; Generated autoloads from comint.el
(defvar comint-output-filter-functions '(ansi-color-process-output comint-postoutput-scroll-to-bottom comint-watch-for-password-prompt) "\
@@ -5305,7 +4686,6 @@ See also `comint-preoutput-filter-functions'.
You can use `add-hook' to add functions to this list
either globally or locally.")
-
(autoload 'make-comint-in-buffer "comint" "\
Make a Comint process NAME in BUFFER, running PROGRAM.
If BUFFER is nil, it defaults to NAME surrounded by `*'s.
@@ -5325,8 +4705,7 @@ If PROGRAM is a string, any more args are arguments to PROGRAM.
Return the (possibly newly created) process buffer.
-\(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
-
+(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
(autoload 'make-comint "comint" "\
Make a Comint process NAME in a buffer, running PROGRAM.
The name of the buffer is made by surrounding NAME with `*'s.
@@ -5341,8 +4720,7 @@ If PROGRAM is a string, any more args are arguments to PROGRAM.
Returns the (possibly newly created) process buffer.
-\(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
-
+(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
(autoload 'comint-run "comint" "\
Run PROGRAM in a Comint buffer and switch to that buffer.
@@ -5355,79 +4733,66 @@ hooks on this symbol are run in the buffer.
See `make-comint' and `comint-exec'.
-\(fn PROGRAM &optional SWITCHES)" t nil)
-
+(fn PROGRAM &optional SWITCHES)" t nil)
(function-put 'comint-run 'interactive-only 'make-comint)
-
(defvar comint-file-name-prefix (purecopy "") "\
Prefix prepended to absolute file names taken from process input.
This is used by Comint's and shell's completion functions, and by shell's
directory tracking functions.")
-
(autoload 'comint-redirect-send-command "comint" "\
Send COMMAND to process in current buffer, with output to OUTPUT-BUFFER.
With prefix arg ECHO, echo output in process buffer.
If NO-DISPLAY is non-nil, do not show the output buffer.
-\(fn COMMAND OUTPUT-BUFFER ECHO &optional NO-DISPLAY)" t nil)
-
+(fn COMMAND OUTPUT-BUFFER ECHO &optional NO-DISPLAY)" t nil)
(autoload 'comint-redirect-send-command-to-process "comint" "\
Send COMMAND to PROCESS, with output to OUTPUT-BUFFER.
With prefix arg, echo output in process buffer.
If NO-DISPLAY is non-nil, do not show the output buffer.
-\(fn COMMAND OUTPUT-BUFFER PROCESS ECHO &optional NO-DISPLAY)" t nil)
-
+(fn COMMAND OUTPUT-BUFFER PROCESS ECHO &optional NO-DISPLAY)" t nil)
(autoload 'comint-redirect-results-list "comint" "\
Send COMMAND to current process.
Return a list of expressions in the output which match REGEXP.
REGEXP-GROUP is the regular expression group in REGEXP to use.
-\(fn COMMAND REGEXP REGEXP-GROUP)" nil nil)
-
+(fn COMMAND REGEXP REGEXP-GROUP)" nil nil)
(autoload 'comint-redirect-results-list-from-process "comint" "\
Send COMMAND to PROCESS.
Return a list of expressions in the output which match REGEXP.
REGEXP-GROUP is the regular expression group in REGEXP to use.
-\(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil)
-
+(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil)
(register-definition-prefixes "comint" '("comint-"))
-;;;***
-;;;### (autoloads nil "comp" "emacs-lisp/comp.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/comp.el
-(put 'no-native-compile 'safe-local-variable 'booleanp)
+(put 'no-native-compile 'safe-local-variable 'booleanp)
(autoload 'comp-subr-trampoline-install "comp" "\
Make SUBR-NAME effectively advice-able when called from native code.
-\(fn SUBR-NAME)" nil nil)
-
+(fn SUBR-NAME)" nil nil)
(autoload 'comp-c-func-name "comp" "\
Given NAME, return a name suitable for the native code.
Add PREFIX in front of it. If FIRST is not nil, pick the first
available name ignoring compilation context and potential name
clashes.
-\(fn NAME PREFIX &optional FIRST)" nil nil)
-
+(fn NAME PREFIX &optional FIRST)" nil nil)
(autoload 'comp-clean-up-stale-eln "comp" "\
Remove all FILE*.eln* files found in `native-comp-eln-load-path'.
The files to be removed are those produced from the original source
filename (including FILE).
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'comp-lookup-eln "comp" "\
Given a Lisp source FILENAME return the corresponding .eln file if found.
Search happens in `native-comp-eln-load-path'.
-\(fn FILENAME)" nil nil)
-
+(fn FILENAME)" nil nil)
(autoload 'native-compile "comp" "\
Compile FUNCTION-OR-FILE into native code.
This is the synchronous entry-point for the Emacs Lisp native
@@ -5440,8 +4805,7 @@ If FUNCTION-OR-FILE is a filename, return the filename of the
compiled object. If FUNCTION-OR-FILE is a function symbol or a
form, return the compiled function.
-\(fn FUNCTION-OR-FILE &optional OUTPUT)" nil nil)
-
+(fn FUNCTION-OR-FILE &optional OUTPUT)" nil nil)
(autoload 'batch-native-compile "comp" "\
Perform batch native compilation of remaining command-line arguments.
@@ -5453,16 +4817,14 @@ as part of building the source tarball, in which case the .eln file
will be placed under the native-lisp/ directory (actually, in the
last directory in `native-comp-eln-load-path').
-\(fn &optional FOR-TARBALL)" nil nil)
-
+(fn &optional FOR-TARBALL)" nil nil)
(autoload 'batch-byte+native-compile "comp" "\
Like `batch-native-compile', but used for bootstrap.
Generate .elc files in addition to the .eln files.
Force the produced .eln to be outputted in the eln system
directory (the last entry in `native-comp-eln-load-path') unless
`native-compile-target-directory' is non-nil. If the environment
-variable 'NATIVE_DISABLED' is set, only byte compile." nil nil)
-
+variable \"NATIVE_DISABLED\" is set, only byte compile." nil nil)
(autoload 'native-compile-async "comp" "\
Compile FILES asynchronously.
FILES is one file or a list of filenames or directories.
@@ -5482,21 +4844,20 @@ a function -- A function selecting files with matching names.
The variable `native-comp-async-jobs-number' specifies the number
of (commands) to run simultaneously.
-\(fn FILES &optional RECURSIVELY LOAD SELECTOR)" nil nil)
-
+(fn FILES &optional RECURSIVELY LOAD SELECTOR)" nil nil)
(register-definition-prefixes "comp" '("comp-" "make-comp-edge" "native-" "no-native-compile"))
-;;;***
-;;;### (autoloads nil "comp-cstr" "emacs-lisp/comp-cstr.el" (0 0
-;;;;;; 0 0))
+;;; Generated autoloads from cedet/semantic/wisent/comp.el
+
+(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+
+
;;; Generated autoloads from emacs-lisp/comp-cstr.el
(register-definition-prefixes "comp-cstr" '("comp-" "with-comp-cstr-accessors"))
-;;;***
-;;;### (autoloads nil "compare-w" "vc/compare-w.el" (0 0 0 0))
;;; Generated autoloads from vc/compare-w.el
(autoload 'compare-windows "compare-w" "\
@@ -5528,70 +4889,52 @@ on first call it advances points to the next difference,
on second call it synchronizes points by skipping the difference,
on third call it again advances points to the next difference and so on.
-\(fn IGNORE-WHITESPACE)" t nil)
-
+(fn IGNORE-WHITESPACE)" t nil)
(register-definition-prefixes "compare-w" '("compare-"))
-;;;***
-;;;### (autoloads nil "compface" "image/compface.el" (0 0 0 0))
;;; Generated autoloads from image/compface.el
(register-definition-prefixes "compface" '("uncompface"))
-;;;***
-;;;### (autoloads nil "compile" "progmodes/compile.el" (0 0 0 0))
;;; Generated autoloads from progmodes/compile.el
(defvar compilation-mode-hook nil "\
List of hook functions run by `compilation-mode'.")
-
(custom-autoload 'compilation-mode-hook "compile" t)
-
(defvar compilation-start-hook nil "\
Hook run after starting a new compilation process.
The hook is run with one argument, the new process.")
-
(custom-autoload 'compilation-start-hook "compile" t)
-
(defvar compilation-window-height nil "\
Number of lines in a compilation window.
If nil, use Emacs default.")
-
(custom-autoload 'compilation-window-height "compile" t)
-
(defvar compilation-process-setup-function #'ignore "\
Function to call to customize the compilation process.
This function is called immediately before the compilation process is
started. It can be used to set any variables or functions that are used
while processing the output of the compilation process.")
-
(defvar compilation-buffer-name-function #'compilation--default-buffer-name "\
Function to compute the name of a compilation buffer.
The function receives one argument, the name of the major mode of the
compilation buffer. It should return a string.
By default, it returns `(concat \"*\" (downcase name-of-mode) \"*\")'.")
-
(defvar compilation-finish-functions nil "\
Functions to call when a compilation process finishes.
Each function is called with two arguments: the compilation buffer,
and a string describing how the process finished.")
(put 'compilation-directory 'safe-local-variable 'stringp)
-
(defvar compilation-ask-about-save t "\
Non-nil means \\[compile] asks which buffers to save before compiling.
Otherwise, it saves all modified buffers without asking.")
-
(custom-autoload 'compilation-ask-about-save "compile" t)
-
(defvar compilation-search-path '(nil) "\
List of directories to search for source files named in error messages.
Elements should be directory names, not file names of directories.
The value nil as an element means to try the default directory.")
-
(custom-autoload 'compilation-search-path "compile" t)
-
(defvar compile-command (purecopy "make -k ") "\
Last shell command used to do a compilation; default for next compilation.
@@ -5609,17 +4952,13 @@ You might also use mode hooks to specify it in certain modes, like this:
(file-name-sans-extension buffer-file-name))))))))
It's often useful to leave a space at the end of the value.")
-
(custom-autoload 'compile-command "compile" t)
(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (or (not (boundp 'compilation-read-command)) compilation-read-command))))
-
(defvar compilation-disable-input nil "\
If non-nil, send end-of-file as compilation process input.
This only affects platforms that support asynchronous processes (see
`start-process'); synchronous compilation processes never accept input.")
-
(custom-autoload 'compilation-disable-input "compile" t)
-
(autoload 'compile "compile" "\
Compile the program including the current buffer. Default: run `make'.
Runs COMMAND, a shell command, in a separate process asynchronously
@@ -5649,8 +4988,7 @@ The name used for the buffer is actually whatever is returned by
the function in `compilation-buffer-name-function', so you can set that
to a function that generates a unique name.
-\(fn COMMAND &optional COMINT)" t nil)
-
+(fn COMMAND &optional COMINT)" t nil)
(autoload 'compilation-start "compile" "\
Run compilation command COMMAND (low level interface).
If COMMAND starts with a cd command, that becomes the `default-directory'.
@@ -5668,10 +5006,15 @@ If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight
the matching section of the visited source line; the default is to use the
global value of `compilation-highlight-regexp'.
-Returns the compilation buffer created.
+If CONTINUE is non-nil, the buffer won't be emptied before
+compilation is started. This can be useful if you wish to
+combine the output from several compilation commands in the same
+buffer. The new output will be at the end of the buffer, and
+point is not changed.
-\(fn COMMAND &optional MODE NAME-FUNCTION HIGHLIGHT-REGEXP)" nil nil)
+Returns the compilation buffer created.
+(fn COMMAND &optional MODE NAME-FUNCTION HIGHLIGHT-REGEXP CONTINUE)" nil nil)
(autoload 'compilation-mode "compile" "\
Major mode for compilation log buffers.
\\<compilation-mode-map>To visit the source for a line-numbered error,
@@ -5682,69 +5025,78 @@ Runs `compilation-mode-hook' with `run-mode-hooks' (which see).
\\{compilation-mode-map}
-\(fn &optional NAME-OF-MODE)" t nil)
-
+(fn &optional NAME-OF-MODE)" t nil)
(put 'define-compilation-mode 'doc-string-elt 3)
-
(autoload 'compilation-shell-minor-mode "compile" "\
Toggle Compilation Shell minor mode.
+When Compilation Shell minor mode is enabled, all the
+error-parsing commands of the Compilation major mode are
+available but bound to keys that don't collide with Shell mode.
+See `compilation-mode'.
+
This is a minor mode. If called interactively, toggle the
`Compilation-Shell minor mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `compilation-shell-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When Compilation Shell minor mode is enabled, all the
-error-parsing commands of the Compilation major mode are
-available but bound to keys that don't collide with Shell mode.
-See `compilation-mode'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'compilation-minor-mode "compile" "\
Toggle Compilation minor mode.
+When Compilation minor mode is enabled, all the error-parsing
+commands of Compilation major mode are available. See
+`compilation-mode'.
+
This is a minor mode. If called interactively, toggle the
-`Compilation minor mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Compilation minor mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `compilation-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When Compilation minor mode is enabled, all the error-parsing
-commands of Compilation major mode are available. See
-`compilation-mode'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'compilation-next-error-function "compile" "\
Advance to the next error message and visit the file where the error was.
This is the value of `next-error-function' in Compilation buffers.
-\(fn N &optional RESET)" t nil)
-
+(fn N &optional RESET)" t nil)
(register-definition-prefixes "compile" '("compil" "define-compilation-mode" "kill-compilation" "recompile"))
-;;;***
-;;;### (autoloads nil "completion" "completion.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/compile.el
+
+(register-definition-prefixes "srecode/compile" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/semantic/analyze/complete.el
+
+(register-definition-prefixes "semantic/analyze/complete" '("semantic-analyze-"))
+
+
+;;; Generated autoloads from cedet/semantic/complete.el
+
+(register-definition-prefixes "semantic/complete" '("semantic-"))
+
+
;;; Generated autoloads from completion.el
(defvar dynamic-completion-mode nil "\
@@ -5754,34 +5106,29 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `dynamic-completion-mode'.")
-
(custom-autoload 'dynamic-completion-mode "completion" nil)
-
(autoload 'dynamic-completion-mode "completion" "\
Toggle dynamic word-completion on or off.
-This is a minor mode. If called interactively, toggle the
-`Dynamic-Completion mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Dynamic-Completion mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='dynamic-completion-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "completion" '("*c-def-regexp*" "*lisp-def-regexp*" "accept-completion" "add-" "cdabbrev-" "check-completion-length" "clear-all-completions" "cmpl-" "complet" "current-completion-source" "delete-completion" "enable-completion" "find-" "inside-locate-completion-entry" "interactive-completion-string-reader" "kill-" "list-all-completions" "load-completions-from-file" "make-c" "next-cdabbrev" "num-cmpl-sources" "reset-cdabbrev" "save" "set-c" "symbol-" "use-completion-"))
-;;;***
-;;;### (autoloads nil "conf-mode" "textmodes/conf-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from textmodes/conf-mode.el
(autoload 'conf-mode "conf-mode" "\
@@ -5815,14 +5162,12 @@ See also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode',
\\{conf-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-unix-mode "conf-mode" "\
Conf Mode starter for Unix style Conf files.
Comments start with `#'. For details see `conf-mode'.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-windows-mode "conf-mode" "\
Conf Mode starter for Windows style Conf files.
Comments start with `;'.
@@ -5830,15 +5175,14 @@ For details see `conf-mode'. Example:
; Conf mode font-locks this right on Windows and with \\[conf-windows-mode]
-\[ExtShellFolderViews]
+[ExtShellFolderViews]
Default={5984FFE0-28D4-11CF-AE66-08002B2E1262}
{5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262}
-\[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
+[{5984FFE0-28D4-11CF-AE66-08002B2E1262}]
PersistMoniker=file://Folder.htt
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-javaprop-mode "conf-mode" "\
Conf Mode starter for Java properties files.
Comments start with `#' but are also recognized with `//' or
@@ -5856,8 +5200,7 @@ x.1 =
x.2.y.1.z.1 =
x.2.y.1.z.2.zz =
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-space-mode "conf-mode" "\
Conf Mode starter for space separated conf files.
\"Assignments\" are with ` '. Keywords before the parameters are
@@ -5881,14 +5224,12 @@ class desktop
add /dev/audio desktop
add /dev/mixer desktop
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-space-keywords "conf-mode" "\
Enter Conf Space mode using regexp KEYWORDS to match the keywords.
See `conf-space-mode'.
-\(fn KEYWORDS)" t nil)
-
+(fn KEYWORDS)" t nil)
(autoload 'conf-colon-mode "conf-mode" "\
Conf Mode starter for Colon files.
\"Assignments\" are with `:'.
@@ -5899,8 +5240,7 @@ For details see `conf-mode'. Example:
<Multi_key> <exclam> <exclam> : \"\\241\" exclamdown
<Multi_key> <c> <slash> : \"\\242\" cent
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-ppd-mode "conf-mode" "\
Conf Mode starter for Adobe/CUPS PPD files.
Comments start with `*%' and \"assignments\" are with `:'.
@@ -5911,8 +5251,7 @@ For details see `conf-mode'. Example:
*DefaultTransfer: Null
*Transfer Null.Inverse: \"{ 1 exch sub }\"
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-xdefaults-mode "conf-mode" "\
Conf Mode starter for Xdefaults files.
Comments start with `!' and \"assignments\" are with `:'.
@@ -5923,8 +5262,7 @@ For details see `conf-mode'. Example:
*background: gray99
*foreground: black
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-toml-mode "conf-mode" "\
Conf Mode starter for TOML files.
Comments start with `#' and \"assignments\" are with `='.
@@ -5932,11 +5270,10 @@ For details see `conf-mode'. Example:
# Conf mode font-locks this right with \\[conf-toml-mode]
-\[entry]
+[entry]
value = \"some string\"
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'conf-desktop-mode "conf-mode" "\
Conf Mode started for freedesktop.org Desktop files.
Comments start with `#' and \"assignments\" are with `='.
@@ -5949,13 +5286,15 @@ For details see `conf-mode'.
Exec=gimp-2.8 %U
Terminal=false
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "conf-mode" '("conf-"))
-;;;***
-;;;### (autoloads nil "cookie1" "play/cookie1.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/config.el
+
+(register-definition-prefixes "ede/config" '("ede-"))
+
+
;;; Generated autoloads from play/cookie1.el
(autoload 'cookie "cookie1" "\
@@ -5965,33 +5304,27 @@ of load, ENDMSG at the end.
Interactively, PHRASE-FILE defaults to `cookie-file', unless that
is nil or a prefix argument is used.
-\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" t nil)
-
+(fn PHRASE-FILE &optional STARTMSG ENDMSG)" t nil)
(autoload 'cookie-insert "cookie1" "\
Insert random phrases from PHRASE-FILE; COUNT of them.
When the phrase file is read in, display STARTMSG at the beginning
of load, ENDMSG at the end.
-\(fn PHRASE-FILE &optional COUNT STARTMSG ENDMSG)" nil nil)
-
+(fn PHRASE-FILE &optional COUNT STARTMSG ENDMSG)" nil nil)
(autoload 'cookie-snarf "cookie1" "\
Read the PHRASE-FILE, return it as a vector of strings.
Emit STARTMSG and ENDMSG before and after. Cache the result; second
and subsequent calls on the same file won't go to disk.
-\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" nil nil)
-
+(fn PHRASE-FILE &optional STARTMSG ENDMSG)" nil nil)
(register-definition-prefixes "cookie1" '("cookie"))
-;;;***
-;;;### (autoloads nil "copyright" "emacs-lisp/copyright.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/copyright.el
+
(put 'copyright-at-end-flag 'safe-local-variable 'booleanp)
(put 'copyright-names-regexp 'safe-local-variable 'stringp)
(put 'copyright-year-ranges 'safe-local-variable 'booleanp)
-
(autoload 'copyright-update "copyright" "\
Update copyright notice to indicate the current year.
With prefix ARG, replace the years in the notice rather than adding
@@ -6001,32 +5334,26 @@ following the copyright are updated as well.
If non-nil, INTERACTIVEP tells the function to behave as when it's called
interactively.
-\(fn &optional ARG INTERACTIVEP)" t nil)
-
+(fn &optional ARG INTERACTIVEP)" t nil)
(autoload 'copyright-fix-years "copyright" "\
Convert 2 digit years to 4 digit years.
Uses heuristic: year >= 50 means 19xx, < 50 means 20xx.
If `copyright-year-ranges' (which see) is non-nil, also
independently replaces consecutive years with a range." t nil)
-
(autoload 'copyright "copyright" "\
Insert a copyright by $ORGANIZATION notice at cursor.
-\(fn &optional STR ARG)" t nil)
-
+(fn &optional STR ARG)" t nil)
(autoload 'copyright-update-directory "copyright" "\
Update copyright notice for all files in DIRECTORY matching MATCH.
If FIX is non-nil, run `copyright-fix-years' instead.
-\(fn DIRECTORY MATCH &optional FIX)" t nil)
-
+(fn DIRECTORY MATCH &optional FIX)" t nil)
(register-definition-prefixes "copyright" '("copyright-"))
-;;;***
-;;;### (autoloads nil "cperl-mode" "progmodes/cperl-mode.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/cperl-mode.el
+
(put 'cperl-indent-level 'safe-local-variable 'integerp)
(put 'cperl-brace-offset 'safe-local-variable 'integerp)
(put 'cperl-continued-brace-offset 'safe-local-variable 'integerp)
@@ -6034,7 +5361,7 @@ If FIX is non-nil, run `copyright-fix-years' instead.
(put 'cperl-continued-statement-offset 'safe-local-variable 'integerp)
(put 'cperl-extra-newline-before-brace 'safe-local-variable 'booleanp)
(put 'cperl-merge-trailing-else 'safe-local-variable 'booleanp)
-
+(put 'cperl-file-style 'safe-local-variable 'stringp)
(autoload 'cperl-mode "cperl-mode" "\
Major mode for editing Perl code.
Expression and list commands understand all C brackets.
@@ -6104,10 +5431,10 @@ into
\\{cperl-mode-map}
Setting the variable `cperl-font-lock' to t switches on `font-lock-mode'
-\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
+(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
on electric space between $ and {, `cperl-electric-parens-string' is
the string that contains parentheses that should be electric in CPerl
-\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
+(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
setting `cperl-electric-keywords' enables electric expansion of
control structures in CPerl. `cperl-electric-linefeed' governs which
one of two linefeed behavior is preferable. You can enable all these
@@ -6122,7 +5449,7 @@ If your site has perl5 documentation in info format, you can use commands
These keys run commands `cperl-info-on-current-command' and
`cperl-info-on-command', which one is which is controlled by variable
`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
-\(in turn affected by `cperl-hairy').
+(in turn affected by `cperl-hairy').
Even if you have no info-format documentation, short one-liner-style
help is available on \\[cperl-get-help], and one can run perldoc or
@@ -6185,9 +5512,11 @@ Settings for classic indent-styles: K&R BSD=C++ GNU PBP PerlStyle=Whitesmith
`cperl-continued-statement-offset' 5 4 2 4 4
CPerl knows several indentation styles, and may bulk set the
-corresponding variables. Use \\[cperl-set-style] to do this. Use
-\\[cperl-set-style-back] to restore the memorized preexisting values
-\(both available from menu). See examples in `cperl-style-examples'.
+corresponding variables. Use \\[cperl-set-style] to do this or
+set the `cperl-file-style' user option. Use
+\\[cperl-set-style-back] to restore the memorized preexisting
+values (both available from menu). See examples in
+`cperl-style-examples'.
Part of the indentation style is how different parts of if/elsif/else
statements are broken into lines; in CPerl, this is reflected on how
@@ -6208,21 +5537,16 @@ DO NOT FORGET to read micro-docs (available from `Perl' menu)
or as help on variables `cperl-tips', `cperl-problems',
`cperl-praise', `cperl-speed'.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'cperl-perldoc "cperl-mode" "\
Run `perldoc' on WORD.
-\(fn WORD)" t nil)
-
+(fn WORD)" t nil)
(autoload 'cperl-perldoc-at-point "cperl-mode" "\
Run a `perldoc' on the word around point." t nil)
-
(register-definition-prefixes "cperl-mode" '("cperl-" "pod2man-program"))
-;;;***
-;;;### (autoloads nil "cpp" "progmodes/cpp.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cpp.el
(autoload 'cpp-highlight-buffer "cpp" "\
@@ -6231,16 +5555,22 @@ This command pops up a buffer which you should edit to specify
what kind of highlighting to use, and the criteria for highlighting.
A prefix arg suppresses display of that buffer.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'cpp-parse-edit "cpp" "\
Edit display information for cpp conditionals." t nil)
-
(register-definition-prefixes "cpp" '("cpp-"))
-;;;***
-;;;### (autoloads nil "crm" "emacs-lisp/crm.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/cpp.el
+
+(register-definition-prefixes "srecode/cpp" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/ede/cpp-root.el
+
+(register-definition-prefixes "ede/cpp-root" '("ede-cpp-root-"))
+
+
;;; Generated autoloads from emacs-lisp/crm.el
(autoload 'completing-read-multiple "crm" "\
@@ -6262,13 +5592,15 @@ contents of the minibuffer are \"alice,bob,eve\" and point is between
This function returns a list of the strings that were read,
with empty strings removed.
-\(fn PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil)
-
+(fn PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil)
(register-definition-prefixes "crm" '("crm-"))
-;;;***
-;;;### (autoloads nil "css-mode" "textmodes/css-mode.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/symref/cscope.el
+
+(register-definition-prefixes "semantic/symref/cscope" '("semantic-symref-cscope--line-re"))
+
+
;;; Generated autoloads from textmodes/css-mode.el
(autoload 'css-mode "css-mode" "\
@@ -6292,14 +5624,12 @@ be used to fill comments.
\\{css-mode-map}
-\(fn)" t nil)
+(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode))
-
(autoload 'scss-mode "css-mode" "\
Major mode to edit \"Sassy CSS\" files.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'css-lookup-symbol "css-mode" "\
Display the CSS documentation for SYMBOL, as found on MDN.
When this command is used interactively, it picks a default
@@ -6307,13 +5637,20 @@ symbol based on the CSS text before point -- either an @-keyword,
a property name, a pseudo-class, or a pseudo-element, depending
on what is seen near point.
-\(fn SYMBOL)" t nil)
-
+(fn SYMBOL)" t nil)
(register-definition-prefixes "css-mode" '("css-" "scss-"))
-;;;***
-;;;### (autoloads nil "cua-base" "emulation/cua-base.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/ctxt.el
+
+(register-definition-prefixes "srecode/ctxt" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/semantic/ctxt.el
+
+(register-definition-prefixes "semantic/ctxt" '("semantic-"))
+
+
;;; Generated autoloads from emulation/cua-base.el
(defvar cua-mode nil "\
@@ -6323,26 +5660,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `cua-mode'.")
-
(custom-autoload 'cua-mode "cua-base" nil)
-
(autoload 'cua-mode "cua-base" "\
Toggle Common User Access style editing (CUA mode).
-This is a minor mode. If called interactively, toggle the `Cua mode'
-mode. If the prefix argument is positive, enable the mode, and if it
-is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='cua-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
CUA mode is a global minor mode. When enabled, typed text
replaces the active selection, and you can use C-z, C-x, C-c, and
C-v to undo, cut, copy, and paste in addition to the normal Emacs
@@ -6361,81 +5682,87 @@ You can customize `cua-enable-cua-keys' to completely disable the
CUA bindings, or `cua-prefix-override-inhibit-delay' to change
the prefix fallback behavior.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Cua mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='cua-mode)'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'cua-selection-mode "cua-base" "\
Enable CUA selection mode without the C-z/C-x/C-c/C-v bindings.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "cua-base" '("cua-"))
-;;;***
-;;;### (autoloads nil "cua-gmrk" "emulation/cua-gmrk.el" (0 0 0 0))
;;; Generated autoloads from emulation/cua-gmrk.el
(register-definition-prefixes "cua-gmrk" '("cua-"))
-;;;***
-;;;### (autoloads nil "cua-rect" "emulation/cua-rect.el" (0 0 0 0))
;;; Generated autoloads from emulation/cua-rect.el
(autoload 'cua-rectangle-mark-mode "cua-rect" "\
Toggle the region as rectangular.
+
Activates the region if needed. Only lasts until the region is deactivated.
This is a minor mode. If called interactively, toggle the
-`Cua-Rectangle-Mark mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Cua-Rectangle-Mark mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `cua-rectangle-mark-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "cua-rect" '("cua-"))
-;;;***
-;;;### (autoloads nil "cursor-sensor" "emacs-lisp/cursor-sensor.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from emacs-lisp/cursor-sensor.el
(defvar cursor-sensor-inhibit nil "\
When non-nil, suspend `cursor-sensor-mode' and `cursor-intangible-mode'.
By convention, this is a list of symbols where each symbol stands for the
\"cause\" of the suspension.")
-
(autoload 'cursor-intangible-mode "cursor-sensor" "\
Keep cursor outside of any `cursor-intangible' text property.
This is a minor mode. If called interactively, toggle the
-`Cursor-Intangible mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Cursor-Intangible mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `cursor-intangible-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'cursor-sensor-mode "cursor-sensor" "\
Handle the `cursor-sensor-functions' text property.
+
This property should hold a list of functions which react to the motion
of the cursor. They're called with three arguments (WINDOW OLDPOS DIR)
where WINDOW is the affected window, OLDPOS is the last known position of
@@ -6443,50 +5770,39 @@ the cursor and DIR can be `entered' or `left' depending on whether the cursor
is entering the area covered by the text-property property or leaving it.
This is a minor mode. If called interactively, toggle the
-`Cursor-Sensor mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+`Cursor-Sensor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `cursor-sensor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "cursor-sensor" '("cursor-sensor-"))
-;;;***
-;;;### (autoloads nil "cus-dep" "cus-dep.el" (0 0 0 0))
;;; Generated autoloads from cus-dep.el
(register-definition-prefixes "cus-dep" '("custom-" "generated-custom-dependencies-file"))
-;;;***
-;;;### (autoloads nil "cus-edit" "cus-edit.el" (0 0 0 0))
;;; Generated autoloads from cus-edit.el
(defvar custom-browse-sort-alphabetically nil "\
If non-nil, sort customization group alphabetically in `custom-browse'.")
-
(custom-autoload 'custom-browse-sort-alphabetically "cus-edit" t)
-
(defvar custom-buffer-sort-alphabetically t "\
Whether to sort customization groups alphabetically in Custom buffer.")
-
(custom-autoload 'custom-buffer-sort-alphabetically "cus-edit" t)
-
(defvar custom-menu-sort-alphabetically nil "\
If non-nil, sort each customization group alphabetically in menus.")
-
(custom-autoload 'custom-menu-sort-alphabetically "cus-edit" t)
-
(autoload 'customize-set-value "cus-edit" "\
Set VARIABLE to VALUE, and return VALUE. VALUE is a Lisp object.
@@ -6498,8 +5814,7 @@ If VARIABLE has a `custom-type' property, it must be a widget and the
If given a prefix (or a COMMENT argument), also prompt for a comment.
-\(fn VARIABLE VALUE &optional COMMENT)" t nil)
-
+(fn VARIABLE VALUE &optional COMMENT)" t nil)
(autoload 'customize-set-variable "cus-edit" "\
Set the default for VARIABLE to VALUE, and return VALUE.
VALUE is a Lisp object.
@@ -6515,8 +5830,18 @@ If VARIABLE has a `custom-type' property, it must be a widget and the
If given a prefix (or a COMMENT argument), also prompt for a comment.
-\(fn VARIABLE VALUE &optional COMMENT)" t nil)
+(fn VARIABLE VALUE &optional COMMENT)" t nil)
+(autoload 'setopt "cus-edit" "\
+Set VARIABLE/VALUE pairs, and return the final VALUE.
+This is like `setq', but is meant for user options instead of
+plain variables. This means that `setopt' will execute any
+`custom-set' form associated with VARIABLE.
+
+(fn [VARIABLE VALUE]...)" nil t)
+(autoload 'setopt--set "cus-edit" "\
+
+(fn VARIABLE VALUE)" nil nil)
(autoload 'customize-save-variable "cus-edit" "\
Set the default for VARIABLE to VALUE, and save it for future sessions.
Return VALUE.
@@ -6532,8 +5857,7 @@ If VARIABLE has a `custom-type' property, it must be a widget and the
If given a prefix (or a COMMENT argument), also prompt for a comment.
-\(fn VARIABLE VALUE &optional COMMENT)" t nil)
-
+(fn VARIABLE VALUE &optional COMMENT)" t nil)
(autoload 'customize-push-and-save "cus-edit" "\
Add ELTS to LIST-VAR and save for future sessions, safely.
ELTS should be a list. This function adds each entry to the
@@ -6543,48 +5867,39 @@ If Emacs is initialized, call `customize-save-variable' to save
the resulting list value now. Otherwise, add an entry to
`after-init-hook' to save it after initialization.
-\(fn LIST-VAR ELTS)" nil nil)
-
+(fn LIST-VAR ELTS)" nil nil)
(autoload 'customize "cus-edit" "\
Select a customization buffer which you can use to set user options.
User options are structured into \"groups\".
Initially the top-level group `Emacs' and its immediate subgroups
are shown; the contents of those subgroups are initially hidden." t nil)
-
(autoload 'customize-mode "cus-edit" "\
Customize options related to a major or minor mode.
By default the current major mode is used. With a prefix
argument or if the current major mode has no known group, prompt
for the MODE to customize.
-\(fn MODE)" t nil)
-
+(fn MODE)" t nil)
(autoload 'customize-group "cus-edit" "\
Customize GROUP, which must be a customization group.
If OTHER-WINDOW is non-nil, display in another window.
-\(fn &optional GROUP OTHER-WINDOW)" t nil)
-
+(fn &optional GROUP OTHER-WINDOW)" t nil)
(autoload 'customize-group-other-window "cus-edit" "\
Customize GROUP, which must be a customization group, in another window.
-\(fn &optional GROUP)" t nil)
-
+(fn &optional GROUP)" t nil)
(defalias 'customize-variable 'customize-option)
-
(autoload 'customize-option "cus-edit" "\
Customize SYMBOL, which must be a user option.
-\(fn SYMBOL)" t nil)
-
+(fn SYMBOL)" t nil)
(defalias 'customize-variable-other-window 'customize-option-other-window)
-
(autoload 'customize-option-other-window "cus-edit" "\
Customize SYMBOL, which must be a user option.
Show the buffer in another window, but don't select it.
-\(fn SYMBOL)" t nil)
-
+(fn SYMBOL)" t nil)
(defvar customize-package-emacs-version-alist nil "\
Alist mapping versions of a package to Emacs versions.
We use this for packages that have their own names, but are released
@@ -6615,9 +5930,7 @@ The value of PACKAGE needs to be unique and it needs to match the
PACKAGE value appearing in the :package-version keyword. Since
the user might see the value in an error message, a good choice is
the official name of the package, such as MH-E or Gnus.")
-
(define-obsolete-function-alias 'customize-changed-options #'customize-changed "28.1")
-
(autoload 'customize-changed "cus-edit" "\
Customize all settings whose meanings have changed in Emacs itself.
This includes new user options and faces, and new customization
@@ -6628,8 +5941,7 @@ release.
With argument SINCE-VERSION (a string), customize all settings
that were added or redefined since that version.
-\(fn &optional SINCE-VERSION)" t nil)
-
+(fn &optional SINCE-VERSION)" t nil)
(autoload 'customize-face "cus-edit" "\
Customize FACE, which should be a face name or nil.
If FACE is nil, customize all faces. If FACE is actually a
@@ -6640,8 +5952,7 @@ If OTHER-WINDOW is non-nil, display in another window.
Interactively, when point is on text which has a face specified,
suggest to customize that face, if it's customizable.
-\(fn &optional FACE OTHER-WINDOW)" t nil)
-
+(fn &optional FACE OTHER-WINDOW)" t nil)
(autoload 'customize-face-other-window "cus-edit" "\
Show customization buffer for face FACE in other window.
If FACE is actually a face-alias, customize the face it is aliased to.
@@ -6649,17 +5960,13 @@ If FACE is actually a face-alias, customize the face it is aliased to.
Interactively, when point is on text which has a face specified,
suggest to customize that face, if it's customizable.
-\(fn &optional FACE)" t nil)
-
+(fn &optional FACE)" t nil)
(autoload 'customize-unsaved "cus-edit" "\
Customize all options and faces set in this session but not saved." t nil)
-
(autoload 'customize-rogue "cus-edit" "\
Customize all user variables modified outside customize." t nil)
-
(autoload 'customize-saved "cus-edit" "\
Customize all saved options and faces." t nil)
-
(autoload 'customize-apropos "cus-edit" "\
Customize loaded options, faces and groups matching PATTERN.
PATTERN can be a word, a list of words (separated by spaces),
@@ -6671,28 +5978,23 @@ If TYPE is `options', include only options.
If TYPE is `faces', include only faces.
If TYPE is `groups', include only groups.
-\(fn PATTERN &optional TYPE)" t nil)
-
+(fn PATTERN &optional TYPE)" t nil)
(autoload 'customize-apropos-options "cus-edit" "\
Customize all loaded customizable options matching REGEXP.
-\(fn REGEXP &optional IGNORED)" t nil)
-
+(fn REGEXP &optional IGNORED)" t nil)
(autoload 'customize-apropos-faces "cus-edit" "\
Customize all loaded faces matching REGEXP.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'customize-apropos-groups "cus-edit" "\
Customize all loaded groups matching REGEXP.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'custom-prompt-customize-unsaved-options "cus-edit" "\
Prompt user to customize any unsaved customization options.
-Return non-nil if user chooses to customize, for use in
+Return nil if user chooses to customize, for use in
`kill-emacs-query-functions'." nil nil)
-
(autoload 'custom-buffer-create "cus-edit" "\
Create a buffer containing OPTIONS.
Optional NAME is the name of the buffer.
@@ -6701,8 +6003,7 @@ SYMBOL is a customization option, and WIDGET is a widget for editing
that option.
DESCRIPTION is unused.
-\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil)
-
+(fn OPTIONS &optional NAME DESCRIPTION)" nil nil)
(autoload 'custom-buffer-create-other-window "cus-edit" "\
Create a buffer containing OPTIONS, and display it in another window.
The result includes selecting that window.
@@ -6712,13 +6013,11 @@ SYMBOL is a customization option, and WIDGET is a widget for editing
that option.
DESCRIPTION is unused.
-\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil)
-
+(fn OPTIONS &optional NAME DESCRIPTION)" nil nil)
(autoload 'customize-browse "cus-edit" "\
Create a tree browser for the customize hierarchy.
-\(fn &optional GROUP)" t nil)
-
+(fn &optional GROUP)" t nil)
(defvar custom-file nil "\
File used for storing customization information.
The default is nil, which means to use your init file
@@ -6729,8 +6028,8 @@ You can set this option through Custom, if you carefully read the
last paragraph below. However, usually it is simpler to write
something like the following in your init file:
-\(setq custom-file \"~/.config/emacs-custom.el\")
-\(load custom-file)
+(setq custom-file \"~/.config/emacs-custom.el\")
+(load custom-file)
Note that both lines are necessary: the first line tells Custom to
save all customizations in this file, but does not load it.
@@ -6751,34 +6050,26 @@ want. You also have to put something like (load \"CUSTOM-FILE\")
in your init file, where CUSTOM-FILE is the actual name of the
file. Otherwise, Emacs will not load the file when it starts up,
and hence will not set `custom-file' to that file either.")
-
(custom-autoload 'custom-file "cus-edit" t)
-
(autoload 'custom-save-all "cus-edit" "\
Save all customizations in `custom-file'." nil nil)
-
(autoload 'customize-save-customized "cus-edit" "\
Save all user options which have been set in this session." t nil)
-
(autoload 'custom-menu-create "cus-edit" "\
Create menu for customization group SYMBOL.
The menu is in a format applicable to `easy-menu-define'.
-\(fn SYMBOL)" nil nil)
-
+(fn SYMBOL)" nil nil)
(autoload 'customize-menu-create "cus-edit" "\
Return a customize menu for customization group SYMBOL.
If optional NAME is given, use that as the name of the menu.
Otherwise the menu will be named `Customize'.
The format is suitable for use with `easy-menu-define'.
-\(fn SYMBOL &optional NAME)" nil nil)
-
+(fn SYMBOL &optional NAME)" nil nil)
(register-definition-prefixes "cus-edit" '("Custom-" "cus" "widget-"))
-;;;***
-;;;### (autoloads nil "cus-theme" "cus-theme.el" (0 0 0 0))
;;; Generated autoloads from cus-theme.el
(autoload 'customize-create-theme "cus-theme" "\
@@ -6790,73 +6081,66 @@ from the Custom save file.
BUFFER, if non-nil, should be a buffer to use; the default is
named *Custom Theme*.
-\(fn &optional THEME BUFFER)" t nil)
-
+(fn &optional THEME BUFFER)" t nil)
(autoload 'custom-theme-visit-theme "cus-theme" "\
Set up a Custom buffer to edit custom theme THEME.
-\(fn THEME)" t nil)
-
+(fn THEME)" t nil)
(autoload 'describe-theme "cus-theme" "\
Display a description of the Custom theme THEME (a symbol).
-\(fn THEME)" t nil)
-
+(fn THEME)" t nil)
(autoload 'customize-themes "cus-theme" "\
Display a selectable list of Custom themes.
When called from Lisp, BUFFER should be the buffer to use; if
omitted, a buffer named *Custom Themes* is used.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(register-definition-prefixes "cus-theme" '("custom-" "describe-theme-1"))
-;;;***
-;;;### (autoloads nil "cvs-status" "vc/cvs-status.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/custom.el
+
+(register-definition-prefixes "ede/custom" '("ede-" "eieio-ede-old-variables"))
+
+
;;; Generated autoloads from vc/cvs-status.el
(autoload 'cvs-status-mode "cvs-status" "\
Mode used for cvs status output.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "cvs-status" '("cvs-"))
-;;;***
-;;;### (autoloads nil "cwarn" "progmodes/cwarn.el" (0 0 0 0))
;;; Generated autoloads from progmodes/cwarn.el
(autoload 'cwarn-mode "cwarn" "\
Minor mode that highlights suspicious C and C++ constructions.
-This is a minor mode. If called interactively, toggle the `Cwarn
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `cwarn-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Suspicious constructs are highlighted using `font-lock-warning-face'.
Note, in addition to enabling this minor mode, the major mode must
be included in the variable `cwarn-configuration'. By default C and
C++ modes are included.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the `Cwarn
+mode' mode. If the prefix argument is positive, enable the mode,
+and if it is zero or negative, disable the mode.
-(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1")
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
-(put 'global-cwarn-mode 'globalized-minor-mode t)
+To check whether the minor mode is enabled in the current buffer,
+evaluate `cwarn-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
+(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1")
+(put 'global-cwarn-mode 'globalized-minor-mode t)
(defvar global-cwarn-mode nil "\
Non-nil if Global Cwarn mode is enabled.
See the `global-cwarn-mode' command
@@ -6864,9 +6148,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-cwarn-mode'.")
-
(custom-autoload 'global-cwarn-mode "cwarn" nil)
-
(autoload 'global-cwarn-mode "cwarn" "\
Toggle Cwarn mode in all buffers.
With prefix ARG, enable Global Cwarn mode if ARG is positive;
@@ -6881,26 +6163,20 @@ Cwarn mode is enabled in all buffers where
See `cwarn-mode' for more information on Cwarn mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "cwarn" '("cwarn-" "turn-on-cwarn-mode-if-enabled"))
-;;;***
-;;;### (autoloads nil "cyril-util" "language/cyril-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/cyril-util.el
(autoload 'cyrillic-encode-koi8-r-char "cyril-util" "\
Return KOI8-R external character code of CHAR if appropriate.
-\(fn CHAR)" nil nil)
-
+(fn CHAR)" nil nil)
(autoload 'cyrillic-encode-alternativnyj-char "cyril-util" "\
Return ALTERNATIVNYJ external character code of CHAR if appropriate.
-\(fn CHAR)" nil nil)
-
+(fn CHAR)" nil nil)
(autoload 'standard-display-cyrillic-translit "cyril-util" "\
Display a Cyrillic buffer using a transliteration.
For readability, the table is slightly
@@ -6912,19 +6188,16 @@ Possible values are listed in `cyrillic-language-alist'.
If the argument is t, we use the default cyrillic transliteration.
If the argument is nil, we return the display table to its standard state.
-\(fn &optional CYRILLIC-LANGUAGE)" t nil)
-
+(fn &optional CYRILLIC-LANGUAGE)" t nil)
(register-definition-prefixes "cyril-util" '("cyrillic-language-alist"))
-;;;***
-;;;### (autoloads nil "dabbrev" "dabbrev.el" (0 0 0 0))
;;; Generated autoloads from dabbrev.el
+
(put 'dabbrev-case-fold-search 'risky-local-variable t)
(put 'dabbrev-case-replace 'risky-local-variable t)
(define-key esc-map "/" 'dabbrev-expand)
(define-key esc-map [?\C-/] 'dabbrev-completion)
-
(autoload 'dabbrev-completion "dabbrev" "\
Completion on current word.
Like \\[dabbrev-expand] but finds all expansions in the current buffer
@@ -6937,8 +6210,7 @@ completions.
If the prefix argument is 16 (which comes from \\[universal-argument] \\[universal-argument]),
then it searches *all* buffers.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'dabbrev-expand "dabbrev" "\
Expand previous word \"dynamically\".
@@ -6963,25 +6235,74 @@ direction of search to backward if set non-nil.
See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion].
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "dabbrev" '("dabbrev-"))
-;;;***
-;;;### (autoloads nil "data-debug" "cedet/data-debug.el" (0 0 0 0))
;;; Generated autoloads from cedet/data-debug.el
(autoload 'data-debug-new-buffer "data-debug" "\
Create a new data-debug buffer with NAME.
-\(fn NAME)" nil nil)
-
+(fn NAME)" nil nil)
(register-definition-prefixes "data-debug" '("data-debug-"))
-;;;***
-;;;### (autoloads nil "dbus" "net/dbus.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/db.el
+
+(register-definition-prefixes "semantic/db" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-debug.el
+
+(register-definition-prefixes "semantic/db-debug" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-ebrowse.el
+
+(register-definition-prefixes "semantic/db-ebrowse" '("c++-mode" "semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-el.el
+
+(register-definition-prefixes "semantic/db-el" '("emacs-lisp-mode" "semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-file.el
+
+(register-definition-prefixes "semantic/db-file" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-find.el
+
+(register-definition-prefixes "semantic/db-find" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-global.el
+
+(register-definition-prefixes "semantic/db-global" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-javascript.el
+
+(register-definition-prefixes "semantic/db-javascript" '("javascript-mode" "semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-mode.el
+
+(register-definition-prefixes "semantic/db-mode" '("semanticdb-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-ref.el
+
+(register-definition-prefixes "semantic/db-ref" '("semanticdb-ref-"))
+
+
+;;; Generated autoloads from cedet/semantic/db-typecache.el
+
+(register-definition-prefixes "semantic/db-typecache" '("semanticdb-"))
+
+
;;; Generated autoloads from net/dbus.el
(autoload 'dbus-handle-event "dbus" "\
@@ -6990,22 +6311,17 @@ EVENT is a D-Bus event, see `dbus-check-event'. HANDLER, being
part of the event, is called with arguments ARGS (without type information).
If the HANDLER returns a `dbus-error', it is propagated as return message.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(function-put 'dbus-handle-event 'completion-predicate #'ignore)
-
(autoload 'dbus-monitor "dbus" "\
Invoke `dbus-register-monitor' interactively, and switch to the buffer.
BUS is either a Lisp keyword, `:system' or `:session', or a
string denoting the bus address. The value nil defaults to `:session'.
-\(fn &optional BUS)" t nil)
-
+(fn &optional BUS)" t nil)
(register-definition-prefixes "dbus" '("dbus-"))
-;;;***
-;;;### (autoloads nil "dcl-mode" "progmodes/dcl-mode.el" (0 0 0 0))
;;; Generated autoloads from progmodes/dcl-mode.el
(autoload 'dcl-mode "dcl-mode" "\
@@ -7126,17 +6442,13 @@ $
There is some minimal font-lock support (see vars
`dcl-font-lock-defaults' and `dcl-font-lock-keywords').
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "dcl-mode" '("dcl-"))
-;;;***
-;;;### (autoloads nil "debug" "emacs-lisp/debug.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/debug.el
(setq debugger 'debug)
-
(autoload 'debug "debug" "\
Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger.
Arguments are mainly for use when this is called from the internals
@@ -7149,8 +6461,7 @@ first will be printed into the backtrace buffer.
If `inhibit-redisplay' is non-nil when this function is called,
the debugger will not be entered.
-\(fn &rest ARGS)" t nil)
-
+(fn &rest ARGS)" t nil)
(autoload 'debug-on-entry "debug" "\
Request FUNCTION to invoke debugger each time it is called.
@@ -7166,16 +6477,14 @@ primitive functions only works when that function is called from Lisp.
Use \\[cancel-debug-on-entry] to cancel the effect of this command.
Redefining FUNCTION also cancels it.
-\(fn FUNCTION)" t nil)
-
+(fn FUNCTION)" t nil)
(autoload 'cancel-debug-on-entry "debug" "\
Undo effect of \\[debug-on-entry] on FUNCTION.
If FUNCTION is nil, cancel `debug-on-entry' for all functions.
When called interactively, prompt for FUNCTION in the minibuffer.
To specify a nil argument interactively, exit with an empty minibuffer.
-\(fn &optional FUNCTION)" t nil)
-
+(fn &optional FUNCTION)" t nil)
(autoload 'debug-on-variable-change "debug" "\
Trigger a debugger invocation when VARIABLE is changed.
@@ -7194,30 +6503,38 @@ Use \\[cancel-debug-on-variable-change] to cancel the effect of
this command. Uninterning VARIABLE or making it an alias of
another symbol also cancels it.
-\(fn VARIABLE)" t nil)
-
+(fn VARIABLE)" t nil)
(defalias 'debug-watch #'debug-on-variable-change)
-
(autoload 'cancel-debug-on-variable-change "debug" "\
Undo effect of \\[debug-on-variable-change] on VARIABLE.
If VARIABLE is nil, cancel `debug-on-variable-change' for all variables.
When called interactively, prompt for VARIABLE in the minibuffer.
To specify a nil argument interactively, exit with an empty minibuffer.
-\(fn &optional VARIABLE)" t nil)
-
+(fn &optional VARIABLE)" t nil)
(defalias 'cancel-debug-watch #'cancel-debug-on-variable-change)
-
(register-definition-prefixes "debug" '("debug" "inhibit-debug-on-entry"))
-;;;***
-;;;### (autoloads nil "decipher" "play/decipher.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/bovine/debug.el
+
+(register-definition-prefixes "semantic/bovine/debug" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/analyze/debug.el
+
+(register-definition-prefixes "semantic/analyze/debug" '("semantic-analyze"))
+
+
+;;; Generated autoloads from cedet/semantic/debug.el
+
+(register-definition-prefixes "semantic/debug" '("semantic-debug-"))
+
+
;;; Generated autoloads from play/decipher.el
(autoload 'decipher "decipher" "\
Format a buffer of ciphertext for cryptanalysis and enter Decipher mode." t nil)
-
(autoload 'decipher-mode "decipher" "\
Major mode for decrypting monoalphabetic substitution ciphers.
Lower-case letters enter plaintext.
@@ -7234,18 +6551,19 @@ The most useful commands are:
\\[decipher-make-checkpoint] Save the current cipher alphabet (checkpoint)
\\[decipher-restore-checkpoint] Restore a saved cipher alphabet (checkpoint)
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "decipher" '("decipher-"))
-;;;***
-;;;### (autoloads nil "delim-col" "delim-col.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/decorate.el
+
+(register-definition-prefixes "semantic/decorate" '("semantic-"))
+
+
;;; Generated autoloads from delim-col.el
(autoload 'delimit-columns-customize "delim-col" "\
Customize the `columns' group." t nil)
-
(autoload 'delimit-columns-region "delim-col" "\
Prettify all columns in a text region.
@@ -7269,8 +6587,7 @@ See the `delimit-columns-str-before',
`delimit-columns-extra' variables for customization of the
look.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'delimit-columns-rectangle "delim-col" "\
Prettify all columns in a text rectangle.
@@ -7278,17 +6595,13 @@ See `delimit-columns-region' for what this entails.
START and END delimit the corners of the text rectangle.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(register-definition-prefixes "delim-col" '("delimit-columns-"))
-;;;***
-;;;### (autoloads nil "delsel" "delsel.el" (0 0 0 0))
;;; Generated autoloads from delsel.el
(defalias 'pending-delete-mode 'delete-selection-mode)
-
(defvar delete-selection-mode nil "\
Non-nil if Delete-Selection mode is enabled.
See the `delete-selection-mode' command
@@ -7296,26 +6609,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `delete-selection-mode'.")
-
(custom-autoload 'delete-selection-mode "delsel" nil)
-
(autoload 'delete-selection-mode "delsel" "\
Toggle Delete Selection mode.
-This is a minor mode. If called interactively, toggle the
-`Delete-Selection mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='delete-selection-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Delete Selection mode is enabled, typed text replaces the selection
if the selection is active. Otherwise, typed text is just inserted at
point regardless of any selection.
@@ -7323,20 +6620,36 @@ point regardless of any selection.
See `delete-selection-helper' and `delete-selection-pre-hook' for
information on adapting behavior of commands in Delete Selection mode.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Delete-Selection mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='delete-selection-mode)'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'delete-active-region "delsel" "\
Delete the active region.
If KILLP is non-nil, or if called interactively with a prefix argument,
the active region is killed instead of deleted.
-\(fn &optional KILLP)" t nil)
-
+(fn &optional KILLP)" t nil)
(register-definition-prefixes "delsel" '("del" "minibuffer-keyboard-quit"))
-;;;***
-;;;### (autoloads nil "derived" "emacs-lisp/derived.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/dep.el
+
+(register-definition-prefixes "semantic/dep" '("defcustom-mode-local-semantic-dependency-system-include-path" "semantic-"))
+
+
;;; Generated autoloads from emacs-lisp/derived.el
(autoload 'define-derived-mode "derived" "\
@@ -7398,25 +6711,19 @@ the hook will be named `foo-mode-hook'.
See Info node `(elisp)Derived Modes' for more details.
-\(fn CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)" nil t)
-
-(function-put 'define-derived-mode 'doc-string-elt '4)
-
+(fn CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)" nil t)
+(function-put 'define-derived-mode 'doc-string-elt 4)
(function-put 'define-derived-mode 'lisp-indent-function 'defun)
-
(autoload 'derived-mode-init-mode-variables "derived" "\
Initialize variables for a new MODE.
Right now, if they don't already exist, set up a blank keymap, an
empty syntax table, and an empty abbrev table -- these will be merged
the first time the mode is used.
-\(fn MODE)" nil nil)
-
+(fn MODE)" nil nil)
(register-definition-prefixes "derived" '("derived-mode-"))
-;;;***
-;;;### (autoloads nil "descr-text" "descr-text.el" (0 0 0 0))
;;; Generated autoloads from descr-text.el
(autoload 'describe-text-properties "descr-text" "\
@@ -7427,8 +6734,7 @@ If optional second argument OUTPUT-BUFFER is non-nil,
insert the output into that buffer, and don't initialize or clear it
otherwise.
-\(fn POS &optional OUTPUT-BUFFER BUFFER)" t nil)
-
+(fn POS &optional OUTPUT-BUFFER BUFFER)" t nil)
(autoload 'describe-char "descr-text" "\
Describe position POS (interactively, point) and the char after POS.
POS is taken to be in BUFFER, or the current buffer if BUFFER is nil.
@@ -7455,8 +6761,7 @@ The character information includes:
Unicode Data Base;
and widgets, buttons, overlays, and text properties relevant to POS.
-\(fn POS &optional BUFFER)" t nil)
-
+(fn POS &optional BUFFER)" t nil)
(autoload 'describe-char-eldoc "descr-text" "\
Return a description of character at point for use by ElDoc mode.
@@ -7470,13 +6775,10 @@ minibuffer window for width limit.
This function can be used as a value of
`eldoc-documentation-functions' variable.
-\(fn CALLBACK &rest _)" nil nil)
-
+(fn CALLBACK &rest _)" nil nil)
(register-definition-prefixes "descr-text" '("describe-"))
-;;;***
-;;;### (autoloads nil "desktop" "desktop.el" (0 0 0 0))
;;; Generated autoloads from desktop.el
(defvar desktop-save-mode nil "\
@@ -7486,26 +6788,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `desktop-save-mode'.")
-
(custom-autoload 'desktop-save-mode "desktop" nil)
-
(autoload 'desktop-save-mode "desktop" "\
Toggle desktop saving (Desktop Save mode).
-This is a minor mode. If called interactively, toggle the
-`Desktop-Save mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='desktop-save-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Desktop Save mode is enabled, the state of Emacs is saved from
one session to another. In particular, Emacs will save the desktop when
it exits (this may prompt you; see the option `desktop-save'). The next
@@ -7521,15 +6807,26 @@ To see all the options you can set, browse the `desktop' customization group.
For further details, see info node `(emacs)Saving Emacs Sessions'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Desktop-Save mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='desktop-save-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar desktop-locals-to-save '(desktop-locals-to-save truncate-lines case-fold-search case-replace fill-column overwrite-mode change-log-default-name line-number-mode column-number-mode size-indication-mode buffer-file-coding-system buffer-display-time indent-tabs-mode tab-width indicate-buffer-boundaries indicate-empty-lines show-trailing-whitespace) "\
List of local variables to save for each buffer.
The variables are saved only when they really are local. Conventional minor
modes are restored automatically; they should not be listed here.")
-
(custom-autoload 'desktop-locals-to-save "desktop" t)
-
(defvar-local desktop-save-buffer nil "\
When non-nil, save buffer status in desktop file.
@@ -7543,7 +6840,6 @@ When file names are returned, they should be formatted using the call
Later, when `desktop-read' evaluates the desktop file, auxiliary information
is passed as the argument DESKTOP-BUFFER-MISC to functions in
`desktop-buffer-mode-handlers'.")
-
(defvar desktop-buffer-mode-handlers nil "\
Alist of major mode specific functions to restore a desktop buffer.
Functions listed are called by `desktop-create-buffer' when `desktop-read'
@@ -7582,9 +6878,7 @@ code like
The major mode function must either be autoloaded, or of the form
\"foobar-mode\" and defined in library \"foobar\", so that desktop
can guess how to load the mode's definition.")
-
(put 'desktop-buffer-mode-handlers 'risky-local-variable t)
-
(defvar desktop-minor-mode-handlers nil "\
Alist of functions to restore non-standard minor modes.
Functions are called by `desktop-create-buffer' to restore minor modes.
@@ -7628,9 +6922,7 @@ The minor mode function must either be autoloaded, or of the form
can guess how to load the mode's definition.
See also `desktop-minor-mode-table'.")
-
(put 'desktop-minor-mode-handlers 'risky-local-variable t)
-
(autoload 'desktop-clear "desktop" "\
Empty the Desktop.
This kills all buffers except for internal ones and those with names matched by
@@ -7639,7 +6931,6 @@ Furthermore, it clears the variables listed in `desktop-globals-to-clear'.
When called interactively and `desktop-restore-frames' is non-nil, it also
deletes all frames except the selected one (and its minibuffer frame,
if different)." t nil)
-
(autoload 'desktop-save "desktop" "\
Save the state of Emacs in a desktop file in directory DIRNAME.
Optional argument RELEASE non-nil says we're done with this
@@ -7675,12 +6966,10 @@ In a non-interactive call, VERSION can be given as an integer, either
206 or 208, to specify the format version in which to save the file,
no questions asked.
-\(fn DIRNAME &optional RELEASE ONLY-IF-CHANGED VERSION)" t nil)
-
+(fn DIRNAME &optional RELEASE ONLY-IF-CHANGED VERSION)" t nil)
(autoload 'desktop-remove "desktop" "\
Delete desktop file in `desktop-dirname'.
This function also sets `desktop-dirname' to nil." t nil)
-
(autoload 'desktop-read "desktop" "\
Read and process the desktop file in directory DIRNAME.
Look for a desktop file in DIRNAME, or if DIRNAME is omitted, look in
@@ -7691,27 +6980,26 @@ Interactively, with prefix arg \\[universal-argument], ask for DIRNAME.
This function is a no-op when Emacs is running in batch mode.
It returns t if a desktop file was loaded, nil otherwise.
-\(fn DIRNAME)" t nil)
-
+(fn DIRNAME)" t nil)
(autoload 'desktop-change-dir "desktop" "\
Change to desktop saved in DIRNAME.
Kill the desktop as specified by variables `desktop-save-mode' and
`desktop-save', then clear the desktop and load the desktop file in
directory DIRNAME.
-\(fn DIRNAME)" t nil)
-
+(fn DIRNAME)" t nil)
(autoload 'desktop-save-in-desktop-dir "desktop" "\
Save the desktop in directory `desktop-dirname'." t nil)
-
(autoload 'desktop-revert "desktop" "\
Revert to the last loaded desktop." t nil)
-
(register-definition-prefixes "desktop" '("desktop-"))
-;;;***
-;;;### (autoloads nil "deuglify" "gnus/deuglify.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/detect.el
+
+(register-definition-prefixes "ede/detect" '("ede-"))
+
+
;;; Generated autoloads from gnus/deuglify.el
(autoload 'gnus-article-outlook-unwrap-lines "deuglify" "\
@@ -7721,38 +7009,34 @@ You can control what lines will be unwrapped by frobbing
indicating the minimum and maximum length of an unwrapped citation line. If
NODISPLAY is non-nil, don't redisplay the article buffer.
-\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
-
+(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
(autoload 'gnus-article-outlook-repair-attribution "deuglify" "\
Repair a broken attribution line.
If NODISPLAY is non-nil, don't redisplay the article buffer.
-\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
+(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
+(autoload 'gnus-article-outlook-rearrange-citation "deuglify" "\
+Repair broken citations.
+If NODISPLAY is non-nil, don't redisplay the article buffer.
+(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
(autoload 'gnus-outlook-deuglify-article "deuglify" "\
Full deuglify of broken Outlook (Express) articles.
Treat \"smartquotes\", unwrap lines, repair attribution and
rearrange citation. If NODISPLAY is non-nil, don't redisplay the
article buffer.
-\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
-
+(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil)
(autoload 'gnus-article-outlook-deuglify-article "deuglify" "\
Deuglify broken Outlook (Express) articles and redisplay." '(gnus-article-mode gnus-summary-mode) nil)
+(register-definition-prefixes "deuglify" '("gnus-outlook-"))
-(register-definition-prefixes "deuglify" '("gnus-"))
-
-;;;***
-;;;### (autoloads nil "dframe" "dframe.el" (0 0 0 0))
;;; Generated autoloads from dframe.el
(register-definition-prefixes "dframe" '("dframe-"))
-;;;***
-;;;### (autoloads nil "diary-lib" "calendar/diary-lib.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/diary-lib.el
(autoload 'diary "diary-lib" "\
@@ -7761,8 +7045,7 @@ If no argument is provided, the number of days of diary entries is governed
by the variable `diary-number-of-entries'. A value of ARG less than 1
does nothing. This function is suitable for execution in an init file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'diary-mail-entries "diary-lib" "\
Send a mail message showing diary entries for next NDAYS days.
If no prefix argument is given, NDAYS is set to `diary-mail-days'.
@@ -7776,27 +7059,23 @@ ensure that all relevant variables are set.
#!/usr/bin/emacs -script
;; diary-rem.el - run the Emacs diary-reminder
-\(setq diary-mail-days 3
+(setq diary-mail-days 3
diary-file \"/path/to/diary.file\"
calendar-date-style \\='european
diary-mail-addr \"user@host.name\")
-\(diary-mail-entries)
+(diary-mail-entries)
# diary-rem.el ends here
-\(fn &optional NDAYS)" t nil)
-
+(fn &optional NDAYS)" t nil)
(autoload 'diary-mode "diary-lib" "\
Major mode for editing the diary file.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "diary-lib" '("calendar-mark-" "diary-"))
-;;;***
-;;;### (autoloads nil "dictionary" "net/dictionary.el" (0 0 0 0))
;;; Generated autoloads from net/dictionary.el
(autoload 'dictionary-mode "dictionary" "\
@@ -7818,35 +7097,28 @@ This is a quick reference to this mode describing the default key bindings:
* \\[dictionary-select-strategy] select the default search strategy
* RET or <mouse-2> visit that link" nil nil)
-
(autoload 'dictionary "dictionary" "\
Create a new dictionary buffer and install `dictionary-mode'." t nil)
-
(autoload 'dictionary-search "dictionary" "\
Search the WORD in DICTIONARY if given or in all if nil.
It presents the selection or word at point as default input and
allows editing it.
-\(fn WORD &optional DICTIONARY)" t nil)
-
+(fn WORD &optional DICTIONARY)" t nil)
(autoload 'dictionary-lookup-definition "dictionary" "\
Unconditionally lookup the word at point." t nil)
-
(autoload 'dictionary-match-words "dictionary" "\
Search PATTERN in current default dictionary using default strategy.
-\(fn &optional PATTERN &rest IGNORED)" t nil)
-
+(fn &optional PATTERN &rest IGNORED)" t nil)
(autoload 'dictionary-mouse-popup-matching-words "dictionary" "\
Display entries matching the word at the cursor retrieved using EVENT.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'dictionary-popup-matching-words "dictionary" "\
Display entries matching WORD or the current word if not given.
-\(fn &optional WORD)" t nil)
-
+(fn &optional WORD)" t nil)
(autoload 'dictionary-tooltip-mode "dictionary" "\
Display tooltips for the current word.
@@ -7854,8 +7126,7 @@ This function can be used to enable or disable the tooltip mode
for the current buffer (based on ARG). If global-tooltip-mode is
active it will overwrite that mode for the current buffer.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'global-dictionary-tooltip-mode "dictionary" "\
Enable/disable `dictionary-tooltip-mode' for all buffers.
@@ -7865,29 +7136,27 @@ It can be overwritten for each buffer using `dictionary-tooltip-mode'.
Note: (global-dictionary-tooltip-mode 0) will not disable the mode
any buffer where (dictionary-tooltip-mode 1) has been called.
-\(fn &optional ARG)" t nil)
-
-(autoload 'context-menu-dictionary "dictionary" "\
+(fn &optional ARG)" t nil)
+(autoload 'dictionary-context-menu "dictionary" "\
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
the word at mouse click.
-\(fn MENU CLICK)" nil nil)
-
+(fn MENU CLICK)" nil nil)
(register-definition-prefixes "dictionary" '("dictionary-" "global-dictionary-tooltip-mode"))
-;;;***
-;;;### (autoloads nil "dictionary-connection" "net/dictionary-connection.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/dictionary.el
+
+(register-definition-prefixes "srecode/dictionary" '("srecode-"))
+
+
;;; Generated autoloads from net/dictionary-connection.el
(register-definition-prefixes "dictionary-connection" '("dictionary-connection-"))
-;;;***
-;;;### (autoloads nil "diff" "vc/diff.el" (0 0 0 0))
;;; Generated autoloads from vc/diff.el
(defvar diff-switches (purecopy "-u") "\
@@ -7897,14 +7166,10 @@ This variable is also used in the `vc-diff' command (and related
commands) if the backend-specific diff switch variable isn't
set (`vc-git-diff-switches' for git, for instance), and
`vc-diff-switches' isn't set.")
-
(custom-autoload 'diff-switches "diff" t)
-
(defvar diff-command (purecopy "diff") "\
The command to use to run diff.")
-
(custom-autoload 'diff-command "diff" t)
-
(autoload 'diff "diff" "\
Find and display the differences between OLD and NEW files.
When called interactively, read NEW, then OLD, using the
@@ -7919,8 +7184,7 @@ command.
Non-interactively, OLD and NEW may each be a file or a buffer.
-\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
-
+(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
(autoload 'diff-backup "diff" "\
Diff this file with its backup file or vice versa.
Uses the latest backup, if there are several numerical backups.
@@ -7928,19 +7192,16 @@ If this file is a backup, diff it with its original.
The backup file is the first file given to `diff'.
With prefix arg SWITCHES, prompt for diff switches.
-\(fn FILE &optional SWITCHES)" t nil)
-
+(fn FILE &optional SWITCHES)" t nil)
(autoload 'diff-latest-backup-file "diff" "\
Return the latest existing backup of file FN, or nil.
-\(fn FN)" nil nil)
-
+(fn FN)" nil nil)
(autoload 'diff-buffer-with-file "diff" "\
View the differences between BUFFER and its associated file.
This requires the external program `diff' to be in your `exec-path'.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'diff-buffers "diff" "\
Find and display the differences between OLD and NEW buffers.
@@ -7956,13 +7217,12 @@ diff command.
OLD and NEW may each be a buffer or a buffer name.
-\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
+Also see the `diff-entire-buffers' variable.
+(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
(register-definition-prefixes "diff" '("diff-"))
-;;;***
-;;;### (autoloads nil "diff-mode" "vc/diff-mode.el" (0 0 0 0))
;;; Generated autoloads from vc/diff-mode.el
(autoload 'diff-mode "diff-mode" "\
@@ -7980,34 +7240,30 @@ a diff with \\[diff-reverse-direction].
\\{diff-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'diff-minor-mode "diff-mode" "\
Toggle Diff minor mode.
-This is a minor mode. If called interactively, toggle the `Diff minor
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+\\{diff-minor-mode-map}
+
+This is a minor mode. If called interactively, toggle the `Diff
+minor mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `diff-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\\{diff-minor-mode-map}
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "diff-mode" '("diff-"))
-;;;***
-;;;### (autoloads nil "dig" "net/dig.el" (0 0 0 0))
;;; Generated autoloads from net/dig.el
(autoload 'dig "dig" "\
@@ -8016,13 +7272,15 @@ See `dig-invoke' for an explanation for the parameters.
When called interactively, DOMAIN is prompted for. If given a prefix,
also prompt for the QUERY-TYPE parameter.
-\(fn DOMAIN &optional QUERY-TYPE QUERY-CLASS QUERY-OPTION DIG-OPTION SERVER)" t nil)
-
+(fn DOMAIN &optional QUERY-TYPE QUERY-CLASS QUERY-OPTION DIG-OPTION SERVER)" t nil)
(register-definition-prefixes "dig" '("dig-" "query-dig"))
-;;;***
-;;;### (autoloads nil "dired" "dired.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/dired.el
+
+(register-definition-prefixes "ede/dired" '("ede-dired-"))
+
+
;;; Generated autoloads from dired.el
(defvar dired-listing-switches (purecopy "-al") "\
@@ -8042,20 +7300,20 @@ each option.
On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
some of the `ls' switches are not supported; see the doc string of
`insert-directory' in `ls-lisp.el' for more details.")
-
(custom-autoload 'dired-listing-switches "dired" t)
-
-(defvar dired-directory nil "\
+(defvar-local dired-directory nil "\
The directory name or wildcard spec that this Dired directory lists.
Local to each Dired buffer. May be a list, in which case the car is the
directory name and the cdr is the list of files to mention.
The directory name must be absolute, but need not be fully expanded.")
(define-key ctl-x-map "d" 'dired)
-
(autoload 'dired "dired" "\
\"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it.
-Optional second argument SWITCHES specifies the `ls' options used.
-\(Interactively, use a prefix argument to be able to specify SWITCHES.)
+Optional second argument SWITCHES specifies the options to be used
+when invoking `insert-directory-program', usually `ls', which produces
+the listing of the directory files and their attributes.
+Interactively, a prefix argument will cause the command to prompt
+for SWITCHES.
If DIRNAME is a string, Dired displays a list of files in DIRNAME (which
may also have shell wildcards appended to select certain files).
@@ -8072,31 +7330,26 @@ Type \\[describe-mode] after entering Dired for more info.
If DIRNAME is already in a Dired buffer, that buffer is used without refresh.
-\(fn DIRNAME &optional SWITCHES)" t nil)
+(fn DIRNAME &optional SWITCHES)" t nil)
(define-key ctl-x-4-map "d" 'dired-other-window)
-
(autoload 'dired-other-window "dired" "\
\"Edit\" directory DIRNAME. Like `dired' but select in another window.
-\(fn DIRNAME &optional SWITCHES)" t nil)
+(fn DIRNAME &optional SWITCHES)" t nil)
(define-key ctl-x-5-map "d" 'dired-other-frame)
-
(autoload 'dired-other-frame "dired" "\
\"Edit\" directory DIRNAME. Like `dired' but make a new frame.
-\(fn DIRNAME &optional SWITCHES)" t nil)
+(fn DIRNAME &optional SWITCHES)" t nil)
(define-key tab-prefix-map "d" 'dired-other-tab)
-
(autoload 'dired-other-tab "dired" "\
\"Edit\" directory DIRNAME. Like `dired' but make a new tab.
-\(fn DIRNAME &optional SWITCHES)" t nil)
-
+(fn DIRNAME &optional SWITCHES)" t nil)
(autoload 'dired-noselect "dired" "\
Like `dired' but return the Dired buffer as value, do not select it.
-\(fn DIR-OR-LIST &optional SWITCHES)" nil nil)
-
+(fn DIR-OR-LIST &optional SWITCHES)" nil nil)
(autoload 'dired-mode "dired" "\
Mode for \"editing\" directory listings.
In Dired, you are \"editing\" a list of the files in a directory and
@@ -8129,7 +7382,7 @@ Type \\[dired-do-copy] to Copy files.
Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches.
Type \\[revert-buffer] to read all currently expanded directories aGain.
This retains all marks and hides subdirs again that were hidden before.
-Use `SPC' and `DEL' to move down and up by lines.
+Use \\`SPC' and \\`DEL' to move down and up by lines.
If Dired ever gets confused, you can either type \\[revert-buffer] to read the
directories again, type \\[dired-do-redisplay] to relist the file at point or the marked files or a
@@ -8147,9 +7400,8 @@ This mode runs the following hooks:
Keybindings:
\\{dired-mode-map}
-\(fn &optional DIRNAME SWITCHES)" nil nil)
+(fn &optional DIRNAME SWITCHES)" nil nil)
(put 'dired-find-alternate-file 'disabled t)
-
(autoload 'dired-jump "dired" "\
Jump to Dired buffer corresponding to current buffer.
If in a buffer visiting a file, Dired that file's directory and
@@ -8166,36 +7418,28 @@ When OTHER-WINDOW is non-nil, jump to Dired buffer in other window.
When FILE-NAME is non-nil, jump to its line in Dired.
Interactively with prefix argument, read FILE-NAME.
-\(fn &optional OTHER-WINDOW FILE-NAME)" t nil)
-
+(fn &optional OTHER-WINDOW FILE-NAME)" t nil)
(autoload 'dired-jump-other-window "dired" "\
Like \\[dired-jump] (`dired-jump') but in other window.
-\(fn &optional FILE-NAME)" t nil)
-
+(fn &optional FILE-NAME)" t nil)
(register-definition-prefixes "dired" '("dired-"))
-;;;***
-;;;### (autoloads nil "dirtrack" "dirtrack.el" (0 0 0 0))
-;;; Generated autoloads from dirtrack.el
+;;; Generated autoloads from dired-aux.el
-(autoload 'dirtrack-mode "dirtrack" "\
-Toggle directory tracking in shell buffers (Dirtrack mode).
+(register-definition-prefixes "dired-aux" '("dired-" "minibuffer-default-add-dired-shell-commands"))
-This is a minor mode. If called interactively, toggle the `Dirtrack
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+
+;;; Generated autoloads from dired-x.el
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+(register-definition-prefixes "dired-x" '("dired-" "virtual-dired"))
-To check whether the minor mode is enabled in the current buffer,
-evaluate `dirtrack-mode'.
+
+;;; Generated autoloads from dirtrack.el
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+(autoload 'dirtrack-mode "dirtrack" "\
+Toggle directory tracking in shell buffers (Dirtrack mode).
This method requires that your shell prompt contain the current
working directory at all times, and that you set the variable
@@ -8205,8 +7449,21 @@ This is an alternative to `shell-dirtrack-mode', which works by
tracking `cd' and similar commands which change the shell working
directory.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Dirtrack mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `dirtrack-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'dirtrack "dirtrack" "\
Determine the current directory from the process output for a prompt.
This filter function is used by `dirtrack-mode'. It looks for
@@ -8214,58 +7471,47 @@ the prompt specified by `dirtrack-list', and calls
`shell-process-cd' if the directory seems to have changed away
from `default-directory'.
-\(fn INPUT)" nil nil)
-
+(fn INPUT)" nil nil)
(register-definition-prefixes "dirtrack" '("dirtrack-"))
-;;;***
-;;;### (autoloads nil "disass" "emacs-lisp/disass.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/disass.el
(autoload 'disassemble "disass" "\
Print disassembled code for OBJECT in (optional) BUFFER.
OBJECT can be a symbol defined as a function, or a function itself
-\(a lambda expression or a compiled-function object).
+(a lambda expression or a compiled-function object).
If OBJECT is not already compiled, we compile it, but do not
redefine OBJECT if it is a symbol.
-\(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t nil)
-
+(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t nil)
(register-definition-prefixes "disass" '("disassemble-"))
-;;;***
-;;;### (autoloads nil "disp-table" "disp-table.el" (0 0 0 0))
;;; Generated autoloads from disp-table.el
(autoload 'make-display-table "disp-table" "\
Return a new, empty display table." nil nil)
-
(autoload 'display-table-slot "disp-table" "\
Return the value of the extra slot in DISPLAY-TABLE named SLOT.
SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol).
Valid symbols are `truncation', `wrap', `escape', `control',
`selective-display', and `vertical-border'.
-\(fn DISPLAY-TABLE SLOT)" nil nil)
-
+(fn DISPLAY-TABLE SLOT)" nil nil)
(autoload 'set-display-table-slot "disp-table" "\
Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE.
SLOT may be a number from 0 to 5 inclusive, or a name (symbol).
Valid symbols are `truncation', `wrap', `escape', `control',
`selective-display', and `vertical-border'.
-\(fn DISPLAY-TABLE SLOT VALUE)" nil nil)
-
+(fn DISPLAY-TABLE SLOT VALUE)" nil nil)
(autoload 'describe-display-table "disp-table" "\
Describe the display table DT in a help buffer.
-\(fn DT)" nil nil)
-
+(fn DT)" nil nil)
(autoload 'describe-current-display-table "disp-table" "\
Describe the display table in use in the selected window and buffer." t nil)
-
(autoload 'standard-display-8bit "disp-table" "\
Display characters representing raw bytes in the range L to H literally.
@@ -8279,57 +7525,47 @@ byte.
Note that ASCII printable characters (SPC to TILDA) are displayed
in the default way after this call.
-\(fn L H)" nil nil)
-
+(fn L H)" nil nil)
(autoload 'standard-display-default "disp-table" "\
Display characters in the range L to H using the default notation.
-\(fn L H)" nil nil)
-
+(fn L H)" nil nil)
(autoload 'standard-display-ascii "disp-table" "\
Display character C using printable string S.
-\(fn C S)" nil nil)
-
+(fn C S)" nil nil)
(autoload 'standard-display-g1 "disp-table" "\
Display character C as character SC in the g1 character set.
This function assumes that your terminal uses the SO/SI characters;
it is meaningless for a graphical frame.
-\(fn C SC)" nil nil)
-
+(fn C SC)" nil nil)
(autoload 'standard-display-graphic "disp-table" "\
Display character C as character GC in graphics character set.
This function assumes VT100-compatible escapes; it is meaningless
for a graphical frame.
-\(fn C GC)" nil nil)
-
+(fn C GC)" nil nil)
(autoload 'standard-display-underline "disp-table" "\
Display character C as character UC plus underlining.
-\(fn C UC)" nil nil)
-
+(fn C UC)" nil nil)
(autoload 'create-glyph "disp-table" "\
Allocate a glyph code to display by sending STRING to the terminal.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'make-glyph-code "disp-table" "\
Return a glyph code representing char CHAR with face FACE.
-\(fn CHAR &optional FACE)" nil nil)
-
+(fn CHAR &optional FACE)" nil nil)
(autoload 'glyph-char "disp-table" "\
Return the character of glyph code GLYPH.
-\(fn GLYPH)" nil nil)
-
+(fn GLYPH)" nil nil)
(autoload 'glyph-face "disp-table" "\
Return the face of glyph code GLYPH, or nil if glyph has default face.
-\(fn GLYPH)" nil nil)
-
+(fn GLYPH)" nil nil)
(autoload 'standard-display-european "disp-table" "\
Semi-obsolete way to toggle display of ISO 8859 European characters.
@@ -8349,34 +7585,16 @@ from Lisp code also selects Latin-1 as the language environment.
This provides increased compatibility for users who call this function
in `.emacs'.
-\(fn ARG)" nil nil)
-
+(fn ARG)" nil nil)
(register-definition-prefixes "disp-table" '("display-table-print-array"))
-;;;***
-;;;### (autoloads nil "display-fill-column-indicator" "display-fill-column-indicator.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from display-fill-column-indicator.el
(autoload 'display-fill-column-indicator-mode "display-fill-column-indicator" "\
Toggle display of `fill-column' indicator.
-This uses `display-fill-column-indicator' internally.
-
-This is a minor mode. If called interactively, toggle the
-`Display-Fill-Column-Indicator mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-To check whether the minor mode is enabled in the current buffer,
-evaluate `display-fill-column-indicator-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+This uses `display-fill-column-indicator' internally.
To change the position of the column displayed by default
customize `display-fill-column-indicator-column'. You can change the
@@ -8385,10 +7603,23 @@ The globalized version is `global-display-fill-column-indicator-mode',
which see.
See Info node `Displaying Boundaries' for details.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Display-Fill-Column-Indicator mode' mode. If the prefix
+argument is positive, enable the mode, and if it is zero or
+negative, disable the mode.
-(put 'global-display-fill-column-indicator-mode 'globalized-minor-mode t)
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `display-fill-column-indicator-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
+(put 'global-display-fill-column-indicator-mode 'globalized-minor-mode t)
(defvar global-display-fill-column-indicator-mode nil "\
Non-nil if Global Display-Fill-Column-Indicator mode is enabled.
See the `global-display-fill-column-indicator-mode' command
@@ -8396,9 +7627,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-display-fill-column-indicator-mode'.")
-
(custom-autoload 'global-display-fill-column-indicator-mode "display-fill-column-indicator" nil)
-
(autoload 'global-display-fill-column-indicator-mode "display-fill-column-indicator" "\
Toggle Display-Fill-Column-Indicator mode in all buffers.
With prefix ARG, enable Global Display-Fill-Column-Indicator mode if
@@ -8417,8 +7646,7 @@ Display-Fill-Column-Indicator mode.
`global-display-fill-column-indicator-modes' is used to control which
modes this minor mode is used in.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(defvar global-display-fill-column-indicator-modes '((not special-mode) t) "\
Which major modes `display-fill-column-indicator-mode' is switched on in.
This variable can be either t (all major modes), nil (no major modes),
@@ -8432,43 +7660,38 @@ modes derived from `message-mode' or `mail-mode', but do use in other
modes derived from `text-mode'\". An element with value t means \"use\"
and nil means \"don't use\". There's an implicit nil at the end of the
list.")
-
(custom-autoload 'global-display-fill-column-indicator-modes "display-fill-column-indicator" t)
-
(register-definition-prefixes "display-fill-column-indicator" '("display-fill-column-indicator--turn-on"))
-;;;***
-;;;### (autoloads nil "display-line-numbers" "display-line-numbers.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from display-line-numbers.el
(autoload 'display-line-numbers-mode "display-line-numbers" "\
Toggle display of line numbers in the buffer.
+
This uses `display-line-numbers' internally.
+To change the type of line numbers displayed by default,
+customize `display-line-numbers-type'. To change the type while
+the mode is on, set `display-line-numbers' directly.
+
This is a minor mode. If called interactively, toggle the
-`Display-Line-Numbers mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Display-Line-Numbers mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `display-line-numbers-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-To change the type of line numbers displayed by default,
-customize `display-line-numbers-type'. To change the type while
-the mode is on, set `display-line-numbers' directly.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(put 'global-display-line-numbers-mode 'globalized-minor-mode t)
-
(defvar global-display-line-numbers-mode nil "\
Non-nil if Global Display-Line-Numbers mode is enabled.
See the `global-display-line-numbers-mode' command
@@ -8476,9 +7699,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-display-line-numbers-mode'.")
-
(custom-autoload 'global-display-line-numbers-mode "display-line-numbers" nil)
-
(autoload 'global-display-line-numbers-mode "display-line-numbers" "\
Toggle Display-Line-Numbers mode in all buffers.
With prefix ARG, enable Global Display-Line-Numbers mode if ARG is
@@ -8494,13 +7715,57 @@ Display-Line-Numbers mode is enabled in all buffers where
See `display-line-numbers-mode' for more information on
Display-Line-Numbers mode.
-\(fn &optional ARG)" t nil)
+(fn &optional ARG)" t nil)
+(defvar header-line-indent "" "\
+String to indent at the start if the header line.
+This is used in `header-line-indent-mode', and buffers that have
+this switched on should have a `header-line-format' that look like:
+
+ (\"\" header-line-indent THE-REST...)
+
+Also see `header-line-indent-width'.")
+(defvar header-line-indent-width 0 "\
+The width of the current line numbers displayed.
+This is updated when `header-line-indent-mode' is switched on.
+
+Also see `header-line-indent'.")
+(autoload 'header-line-indent-mode "display-line-numbers" "\
+Mode to indent the header line in `display-line-numbers-mode' buffers.
+
+This means that the header line will be kept indented so that it
+has blank space that's as wide as the displayed line numbers in
+the buffer.
+
+Buffers that have this switched on should have a
+`header-line-format' that look like:
+
+ (\"\" header-line-indent THE-REST...)
+
+The `header-line-indent-width' variable is also kept updated, and
+has the width of `header-line-format'. This can be used, for
+instance, in `:align-to' specs, like:
+
+ (space :align-to (+ header-line-indent-width 10))
+
+This is a minor mode. If called interactively, toggle the
+`Header-Line-Indent mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `header-line-indent-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-(register-definition-prefixes "display-line-numbers" '("display-line-numbers-"))
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "display-line-numbers" '("display-line-numbers-" "header-line-indent--"))
-;;;***
-;;;### (autoloads nil "dissociate" "play/dissociate.el" (0 0 0 0))
;;; Generated autoloads from play/dissociate.el
(autoload 'dissociated-press "dissociate" "\
@@ -8512,11 +7777,9 @@ If ARG is positive, require ARG chars of continuity.
If ARG is negative, require -ARG words of continuity.
Default is 2.
-\(fn &optional ARG)" t nil)
+(fn &optional ARG)" t nil)
-;;;***
-;;;### (autoloads nil "dnd" "dnd.el" (0 0 0 0))
;;; Generated autoloads from dnd.el
(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://") . dnd-open-file) (,(purecopy "^file:") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)) "\
@@ -8531,14 +7794,10 @@ is a pair of (REGEXP . FUNCTION), those regexps are tried for a match.
If no match is found, the URL is inserted as text by calling `dnd-insert-text'.
The function shall return the action done (move, copy, link or private)
if some action was made, or nil if the URL is ignored.")
-
(custom-autoload 'dnd-protocol-alist "dnd" t)
-
(register-definition-prefixes "dnd" '("dnd-"))
-;;;***
-;;;### (autoloads nil "dns" "net/dns.el" (0 0 0 0))
;;; Generated autoloads from net/dns.el
(autoload 'dns-query "dns" "\
@@ -8546,18 +7805,15 @@ Query a DNS server for NAME of TYPE.
If FULL, return the entire record returned.
If REVERSE, look up an IP address.
-\(fn NAME &optional TYPE FULL REVERSE)" nil nil)
-
+(fn NAME &optional TYPE FULL REVERSE)" nil nil)
(register-definition-prefixes "dns" '("dns-"))
-;;;***
-;;;### (autoloads nil "dns-mode" "textmodes/dns-mode.el" (0 0 0 0))
;;; Generated autoloads from textmodes/dns-mode.el
(autoload 'dns-mode "dns-mode" "\
Major mode for viewing and editing DNS master files.
-This mode is inherited from text mode. It add syntax
+This mode is derived from text mode. It adds syntax
highlighting, and some commands for handling DNS master files.
Its keymap inherits from `text-mode' and it has the same
variables for customizing indentation. It has its own abbrev
@@ -8565,26 +7821,26 @@ table and its own syntax table.
Turning on DNS mode runs `dns-mode-hook'.
-\(fn)" t nil)
+(fn)" t nil)
(defalias 'zone-mode 'dns-mode)
-
(autoload 'dns-mode-soa-increment-serial "dns-mode" "\
Locate SOA record and increment the serial field." t nil)
-
(register-definition-prefixes "dns-mode" '("dns-mode-"))
-;;;***
-;;;### (autoloads nil "doc-view" "doc-view.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/doc.el
+
+(register-definition-prefixes "semantic/doc" '("semantic-doc"))
+
+
;;; Generated autoloads from doc-view.el
(autoload 'doc-view-mode-p "doc-view" "\
Return non-nil if document type TYPE is available for `doc-view'.
-Document types are symbols like `dvi', `ps', `pdf', or `odf' (any
-OpenDocument format).
-
-\(fn TYPE)" nil nil)
+Document types are symbols like `dvi', `ps', `pdf', `epub',
+`cbz', `fb2', `xps', `oxps', or`odf' (any OpenDocument format).
+(fn TYPE)" nil nil)
(autoload 'doc-view-mode "doc-view" "\
Major mode in DocView buffers.
@@ -8594,133 +7850,110 @@ and DVI files (as PNG images) in Emacs buffers.
You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to
toggle between displaying the document or editing it as text.
\\{doc-view-mode-map}" t nil)
-
(autoload 'doc-view-mode-maybe "doc-view" "\
Switch to `doc-view-mode' if possible.
If the required external tools are not available, then fallback
to the next best mode." nil nil)
-
(autoload 'doc-view-minor-mode "doc-view" "\
Toggle displaying buffer via Doc View (Doc View minor mode).
-This is a minor mode. If called interactively, toggle the `Doc-View
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
+See the command `doc-view-mode' for more information on this mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+This is a minor mode. If called interactively, toggle the
+`Doc-View minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `doc-view-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-See the command `doc-view-mode' for more information on this mode.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'doc-view-bookmark-jump "doc-view" "\
-\(fn BMK)" nil nil)
-
+(fn BMK)" nil nil)
(register-definition-prefixes "doc-view" '("doc-view-"))
-;;;***
-;;;### (autoloads nil "doctor" "play/doctor.el" (0 0 0 0))
;;; Generated autoloads from play/doctor.el
(autoload 'doctor "doctor" "\
Switch to *doctor* buffer and start giving psychotherapy." t nil)
-
(register-definition-prefixes "doctor" '("doc" "make-doctor-variables"))
-;;;***
-;;;### (autoloads nil "dom" "dom.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/document.el
+
+(register-definition-prefixes "srecode/document" '("srecode-document-"))
+
+
;;; Generated autoloads from dom.el
(register-definition-prefixes "dom" '("dom-"))
-;;;***
-;;;### (autoloads nil "dos-fns" "dos-fns.el" (0 0 0 0))
;;; Generated autoloads from dos-fns.el
(register-definition-prefixes "dos-fns" '("dos"))
-;;;***
-;;;### (autoloads nil "dos-vars" "dos-vars.el" (0 0 0 0))
;;; Generated autoloads from dos-vars.el
(register-definition-prefixes "dos-vars" '("dos-codepage-setup-hook" "msdos-shells"))
-;;;***
-;;;### (autoloads nil "dos-w32" "dos-w32.el" (0 0 0 0))
;;; Generated autoloads from dos-w32.el
(register-definition-prefixes "dos-w32" '("file-name-buffer-file-type-alist" "find-" "w32-"))
-;;;***
-;;;### (autoloads nil "double" "double.el" (0 0 0 0))
;;; Generated autoloads from double.el
(autoload 'double-mode "double" "\
Toggle special insertion on double keypresses (Double mode).
-This is a minor mode. If called interactively, toggle the `Double
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+When Double mode is enabled, some keys will insert different
+strings when pressed twice. See `double-map' for details.
+
+This is a minor mode. If called interactively, toggle the
+`Double mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `double-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When Double mode is enabled, some keys will insert different
-strings when pressed twice. See `double-map' for details.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "double" '("double-"))
-;;;***
-;;;### (autoloads nil "dunnet" "play/dunnet.el" (0 0 0 0))
;;; Generated autoloads from play/dunnet.el
(autoload 'dunnet "dunnet" "\
Switch to *dungeon* buffer and start game." t nil)
-
(register-definition-prefixes "dunnet" '("dun" "obj-special"))
-;;;***
-;;;### (autoloads nil "dynamic-setting" "dynamic-setting.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from dynamic-setting.el
(register-definition-prefixes "dynamic-setting" '("dynamic-setting-handle-config-changed-event" "font-setting-change-default-font"))
-;;;***
-;;;### (autoloads nil "easy-mmode" "emacs-lisp/easy-mmode.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/easy-mmode.el
(defalias 'easy-mmode-define-minor-mode #'define-minor-mode)
-
(autoload 'define-minor-mode "easy-mmode" "\
Define a new minor mode MODE.
This defines the toggle command MODE and (by default) a control variable
@@ -8792,16 +8025,11 @@ For backward compatibility with the Emacs<21 calling convention,
the keywords can also be preceded by the obsolete triplet
INIT-VALUE LIGHTER KEYMAP.
-\(fn MODE DOC [KEYWORD VAL ... &rest BODY])" nil t)
-
-(function-put 'define-minor-mode 'doc-string-elt '2)
-
+(fn MODE DOC [KEYWORD VAL ... &rest BODY])" nil t)
+(function-put 'define-minor-mode 'doc-string-elt 2)
(function-put 'define-minor-mode 'lisp-indent-function 'defun)
-
(defalias 'easy-mmode-define-global-mode #'define-globalized-minor-mode)
-
(defalias 'define-global-minor-mode #'define-globalized-minor-mode)
-
(autoload 'define-globalized-minor-mode "easy-mmode" "\
Make a global mode GLOBAL-MODE corresponding to buffer-local minor MODE.
TURN-ON is a function that will be called with no args in every buffer
@@ -8831,12 +8059,9 @@ When a major mode is initialized, MODE is actually turned on just
after running the major mode's hook. However, MODE is not turned
on if the hook has explicitly disabled it.
-\(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" nil t)
-
-(function-put 'define-globalized-minor-mode 'doc-string-elt '2)
-
+(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" nil t)
+(function-put 'define-globalized-minor-mode 'doc-string-elt 2)
(function-put 'define-globalized-minor-mode 'lisp-indent-function 'defun)
-
(autoload 'easy-mmode-define-keymap "easy-mmode" "\
Return a keymap built from bindings BS.
BS must be a list of (KEY . BINDING) where
@@ -8854,85 +8079,67 @@ Valid keywords and arguments are:
:suppress Non-nil to call `suppress-keymap' on keymap,
`nodigits' to suppress digits as prefix arguments.
-\(fn BS &optional NAME M ARGS)" nil nil)
-
+(fn BS &optional NAME M ARGS)" nil nil)
(autoload 'easy-mmode-defmap "easy-mmode" "\
Define a constant M whose value is the result of `easy-mmode-define-keymap'.
The M, BS, and ARGS arguments are as per that function. DOC is
the constant's documentation.
-\(fn M BS DOC &rest ARGS)" nil t)
-
-(function-put 'easy-mmode-defmap 'lisp-indent-function '1)
+This macro is deprecated; use `defvar-keymap' instead.
+(fn M BS DOC &rest ARGS)" nil t)
+(function-put 'easy-mmode-defmap 'doc-string-elt 3)
+(function-put 'easy-mmode-defmap 'lisp-indent-function 1)
(autoload 'easy-mmode-defsyntax "easy-mmode" "\
Define variable ST as a syntax-table.
CSS contains a list of syntax specifications of the form (CHAR . SYNTAX).
-\(fn ST CSS DOC &rest ARGS)" nil t)
-
-(function-put 'easy-mmode-defsyntax 'lisp-indent-function '1)
-
+(fn ST CSS DOC &rest ARGS)" nil t)
+(function-put 'easy-mmode-defsyntax 'doc-string-elt 3)
+(function-put 'easy-mmode-defsyntax 'lisp-indent-function 1)
(register-definition-prefixes "easy-mmode" '("easy-mmode-"))
-;;;***
-;;;### (autoloads nil "ebnf-abn" "progmodes/ebnf-abn.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-abn.el
(register-definition-prefixes "ebnf-abn" '("ebnf-abn-"))
-;;;***
-;;;### (autoloads nil "ebnf-bnf" "progmodes/ebnf-bnf.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-bnf.el
(register-definition-prefixes "ebnf-bnf" '("ebnf-"))
-;;;***
-;;;### (autoloads nil "ebnf-dtd" "progmodes/ebnf-dtd.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-dtd.el
(register-definition-prefixes "ebnf-dtd" '("ebnf-dtd-"))
-;;;***
-;;;### (autoloads nil "ebnf-ebx" "progmodes/ebnf-ebx.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-ebx.el
(register-definition-prefixes "ebnf-ebx" '("ebnf-ebx-"))
-;;;***
-;;;### (autoloads nil "ebnf-iso" "progmodes/ebnf-iso.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-iso.el
(register-definition-prefixes "ebnf-iso" '("ebnf-"))
-;;;***
-;;;### (autoloads nil "ebnf-otz" "progmodes/ebnf-otz.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-otz.el
(register-definition-prefixes "ebnf-otz" '("ebnf-"))
-;;;***
-;;;### (autoloads nil "ebnf-yac" "progmodes/ebnf-yac.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf-yac.el
(register-definition-prefixes "ebnf-yac" '("ebnf-yac-"))
-;;;***
-;;;### (autoloads nil "ebnf2ps" "progmodes/ebnf2ps.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebnf2ps.el
-(push (purecopy '(ebnf2ps 4 4)) package--builtin-versions)
+(push (purecopy '(ebnf2ps 4 4)) package--builtin-versions)
(autoload 'ebnf-customize "ebnf2ps" "\
Customization for ebnf group." t nil)
-
(autoload 'ebnf-print-directory "ebnf2ps" "\
Generate and print a PostScript syntactic chart image of DIRECTORY.
@@ -8943,8 +8150,7 @@ processed.
See also `ebnf-print-buffer'.
-\(fn &optional DIRECTORY)" t nil)
-
+(fn &optional DIRECTORY)" t nil)
(autoload 'ebnf-print-file "ebnf2ps" "\
Generate and print a PostScript syntactic chart image of the file FILE.
@@ -8953,8 +8159,7 @@ killed after process termination.
See also `ebnf-print-buffer'.
-\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
-
+(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
(autoload 'ebnf-print-buffer "ebnf2ps" "\
Generate and print a PostScript syntactic chart image of the buffer.
@@ -8967,14 +8172,12 @@ is nil, send the image to the printer. If FILENAME is a string, save
the PostScript image in a file with that name. If FILENAME is a
number, prompt the user for the name of the file to save in.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'ebnf-print-region "ebnf2ps" "\
Generate and print a PostScript syntactic chart image of the region.
Like `ebnf-print-buffer', but prints just the current region.
-\(fn FROM TO &optional FILENAME)" t nil)
-
+(fn FROM TO &optional FILENAME)" t nil)
(autoload 'ebnf-spool-directory "ebnf2ps" "\
Generate and spool a PostScript syntactic chart image of DIRECTORY.
@@ -8985,8 +8188,7 @@ processed.
See also `ebnf-spool-buffer'.
-\(fn &optional DIRECTORY)" t nil)
-
+(fn &optional DIRECTORY)" t nil)
(autoload 'ebnf-spool-file "ebnf2ps" "\
Generate and spool a PostScript syntactic chart image of the file FILE.
@@ -8995,23 +8197,20 @@ killed after process termination.
See also `ebnf-spool-buffer'.
-\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
-
+(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
(autoload 'ebnf-spool-buffer "ebnf2ps" "\
Generate and spool a PostScript syntactic chart image of the buffer.
Like `ebnf-print-buffer' except that the PostScript image is saved in a
local buffer to be sent to the printer later.
Use the command `ebnf-despool' to send the spooled images to the printer." t nil)
-
(autoload 'ebnf-spool-region "ebnf2ps" "\
Generate a PostScript syntactic chart image of the region and spool locally.
Like `ebnf-spool-buffer', but spools just the current region.
Use the command `ebnf-despool' to send the spooled images to the printer.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'ebnf-eps-directory "ebnf2ps" "\
Generate EPS files from EBNF files in DIRECTORY.
@@ -9022,8 +8221,7 @@ processed.
See also `ebnf-eps-buffer'.
-\(fn &optional DIRECTORY)" t nil)
-
+(fn &optional DIRECTORY)" t nil)
(autoload 'ebnf-eps-file "ebnf2ps" "\
Generate an EPS file from EBNF file FILE.
@@ -9032,8 +8230,7 @@ killed after EPS generation.
See also `ebnf-eps-buffer'.
-\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
-
+(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
(autoload 'ebnf-eps-buffer "ebnf2ps" "\
Generate a PostScript syntactic chart image of the buffer in an EPS file.
@@ -9053,7 +8250,6 @@ The EPS file name has the following form:
WARNING: This function does *NOT* ask any confirmation to override existing
files." t nil)
-
(autoload 'ebnf-eps-region "ebnf2ps" "\
Generate a PostScript syntactic chart image of the region in an EPS file.
@@ -9074,10 +8270,8 @@ The EPS file name has the following form:
WARNING: This function does *NOT* ask any confirmation to override existing
files.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(defalias 'ebnf-despool #'ps-despool)
-
(autoload 'ebnf-syntax-directory "ebnf2ps" "\
Do a syntactic analysis of the files in DIRECTORY.
@@ -9088,8 +8282,7 @@ are processed.
See also `ebnf-syntax-buffer'.
-\(fn &optional DIRECTORY)" t nil)
-
+(fn &optional DIRECTORY)" t nil)
(autoload 'ebnf-syntax-file "ebnf2ps" "\
Do a syntactic analysis of the named FILE.
@@ -9098,47 +8291,39 @@ killed after syntax checking.
See also `ebnf-syntax-buffer'.
-\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
-
+(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil)
(autoload 'ebnf-syntax-buffer "ebnf2ps" "\
Do a syntactic analysis of the current buffer." t nil)
-
(autoload 'ebnf-syntax-region "ebnf2ps" "\
Do a syntactic analysis of a region.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'ebnf-setup "ebnf2ps" "\
Return the current ebnf2ps setup." nil nil)
-
(autoload 'ebnf-find-style "ebnf2ps" "\
Return style definition if NAME is already defined; otherwise, return nil.
See `ebnf-style-database' documentation.
-\(fn NAME)" t nil)
-
+(fn NAME)" t nil)
(autoload 'ebnf-insert-style "ebnf2ps" "\
Insert a new style NAME with inheritance INHERITS and values VALUES.
See `ebnf-style-database' documentation.
-\(fn NAME INHERITS &rest VALUES)" t nil)
-
+(fn NAME INHERITS &rest VALUES)" t nil)
(autoload 'ebnf-delete-style "ebnf2ps" "\
Delete style NAME.
See `ebnf-style-database' documentation.
-\(fn NAME)" t nil)
-
+(fn NAME)" t nil)
(autoload 'ebnf-merge-style "ebnf2ps" "\
Merge values of style NAME with style VALUES.
See `ebnf-style-database' documentation.
-\(fn NAME &rest VALUES)" t nil)
-
+(fn NAME &rest VALUES)" t nil)
(autoload 'ebnf-apply-style "ebnf2ps" "\
Set STYLE as the current style.
@@ -9146,8 +8331,7 @@ Returns the old style symbol.
See `ebnf-style-database' documentation.
-\(fn STYLE)" t nil)
-
+(fn STYLE)" t nil)
(autoload 'ebnf-reset-style "ebnf2ps" "\
Reset current style.
@@ -9155,8 +8339,7 @@ Returns the old style symbol.
See `ebnf-style-database' documentation.
-\(fn &optional STYLE)" t nil)
-
+(fn &optional STYLE)" t nil)
(autoload 'ebnf-push-style "ebnf2ps" "\
Push the current style onto a stack and set STYLE as the current style.
@@ -9166,8 +8349,7 @@ See also `ebnf-pop-style'.
See `ebnf-style-database' documentation.
-\(fn &optional STYLE)" t nil)
-
+(fn &optional STYLE)" t nil)
(autoload 'ebnf-pop-style "ebnf2ps" "\
Pop a style from the stack of pushed styles and set it as the current style.
@@ -9176,12 +8358,9 @@ Returns the old style symbol.
See also `ebnf-push-style'.
See `ebnf-style-database' documentation." t nil)
-
(register-definition-prefixes "ebnf2ps" '("ebnf-"))
-;;;***
-;;;### (autoloads nil "ebrowse" "progmodes/ebrowse.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ebrowse.el
(autoload 'ebrowse-tree-mode "ebrowse" "\
@@ -9189,79 +8368,67 @@ Major mode for Ebrowse class tree buffers.
Each line corresponds to a class in a class tree.
Letters do not insert themselves, they are commands.
File operations in the tree buffer work on class tree data structures.
-E.g.\\[save-buffer] writes the tree to the file it was loaded from.
+E.g. \\[save-buffer] writes the tree to the file it was loaded from.
Tree mode key bindings:
\\{ebrowse-tree-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'ebrowse-electric-choose-tree "ebrowse" "\
Return a buffer containing a tree or nil if no tree found or canceled." t nil)
-
(autoload 'ebrowse-member-mode "ebrowse" "\
Major mode for Ebrowse member buffers.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'ebrowse-tags-view-declaration "ebrowse" "\
View declaration of member at point." t nil)
-
(autoload 'ebrowse-tags-find-declaration "ebrowse" "\
Find declaration of member at point." t nil)
-
(autoload 'ebrowse-tags-view-definition "ebrowse" "\
View definition of member at point." t nil)
-
(autoload 'ebrowse-tags-find-definition "ebrowse" "\
Find definition of member at point." t nil)
-
(autoload 'ebrowse-tags-find-declaration-other-window "ebrowse" "\
Find declaration of member at point in other window." t nil)
-
(autoload 'ebrowse-tags-view-definition-other-window "ebrowse" "\
View definition of member at point in other window." t nil)
-
(autoload 'ebrowse-tags-find-definition-other-window "ebrowse" "\
Find definition of member at point in other window." t nil)
-
(autoload 'ebrowse-tags-find-declaration-other-frame "ebrowse" "\
Find definition of member at point in other frame." t nil)
-
(autoload 'ebrowse-tags-view-definition-other-frame "ebrowse" "\
View definition of member at point in other frame." t nil)
-
(autoload 'ebrowse-tags-find-definition-other-frame "ebrowse" "\
Find definition of member at point in other frame." t nil)
-
(autoload 'ebrowse-tags-complete-symbol "ebrowse" "\
Perform completion on the C++ symbol preceding point.
A second call of this function without changing point inserts the next match.
A call with prefix PREFIX reads the symbol to insert from the minibuffer with
completion.
-\(fn PREFIX)" t nil)
-
+(fn PREFIX)" '("P") nil)
(autoload 'ebrowse-tags-loop-continue "ebrowse" "\
Repeat last operation on files in tree.
FIRST-TIME non-nil means this is not a repetition, but the first time.
TREE-BUFFER if indirectly specifies which files to loop over.
-\(fn &optional FIRST-TIME TREE-BUFFER)" t nil)
-
+(fn &optional FIRST-TIME TREE-BUFFER)" t nil)
(autoload 'ebrowse-tags-search "ebrowse" "\
Search for REGEXP in all files in a tree.
If marked classes exist, process marked classes, only.
If regular expression is nil, repeat last search.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'ebrowse-tags-query-replace "ebrowse" "\
Query replace FROM with TO in all files of a class tree.
With prefix arg, process files of marked classes only.
-\(fn FROM TO)" t nil)
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+(fn FROM TO)" t nil)
(autoload 'ebrowse-tags-search-member-use "ebrowse" "\
Search for call sites of a member.
If FIX-NAME is specified, search uses of that member.
@@ -9269,41 +8436,32 @@ Otherwise, read a member name from the minibuffer.
Searches in all files mentioned in a class tree for something that
looks like a function call to the member.
-\(fn &optional FIX-NAME)" t nil)
-
+(fn &optional FIX-NAME)" t nil)
(autoload 'ebrowse-back-in-position-stack "ebrowse" "\
Move backward in the position stack.
Prefix arg ARG says how much.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'ebrowse-forward-in-position-stack "ebrowse" "\
Move forward in the position stack.
Prefix arg ARG says how much.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'ebrowse-electric-position-menu "ebrowse" "\
List positions in the position stack in an electric buffer." t nil)
-
(autoload 'ebrowse-save-tree "ebrowse" "\
Save current tree in same file it was loaded from." t nil)
-
(autoload 'ebrowse-save-tree-as "ebrowse" "\
Write the current tree data structure to a file.
Read the file name from the minibuffer if interactive.
Otherwise, FILE-NAME specifies the file to save the tree in.
-\(fn &optional FILE-NAME)" t nil)
-
+(fn &optional FILE-NAME)" t nil)
(autoload 'ebrowse-statistics "ebrowse" "\
Display statistics for a class tree." t nil)
-
(register-definition-prefixes "ebrowse" '("ebrowse-" "electric-buffer-menu-mode-hook"))
-;;;***
-;;;### (autoloads nil "ebuff-menu" "ebuff-menu.el" (0 0 0 0))
;;; Generated autoloads from ebuff-menu.el
(autoload 'electric-buffer-list "ebuff-menu" "\
@@ -9332,39 +8490,30 @@ Run hooks in `electric-buffer-menu-mode-hook' on entry.
\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done.
\\[Buffer-menu-backup-unmark] -- back up a line and remove marks.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "ebuff-menu" '("Electric-buffer-menu-" "electric-buffer-"))
-;;;***
-;;;### (autoloads nil "echistory" "echistory.el" (0 0 0 0))
;;; Generated autoloads from echistory.el
(autoload 'Electric-command-history-redo-expression "echistory" "\
Edit current history line in minibuffer and execute result.
With prefix arg NOCONFIRM, execute current line as-is without editing.
-\(fn &optional NOCONFIRM)" t nil)
-
+(fn &optional NOCONFIRM)" t nil)
(register-definition-prefixes "echistory" '("Electric-history-" "electric-"))
-;;;***
-;;;### (autoloads nil "ecomplete" "ecomplete.el" (0 0 0 0))
;;; Generated autoloads from ecomplete.el
(autoload 'ecomplete-setup "ecomplete" "\
Read the .ecompleterc file." nil nil)
-
(register-definition-prefixes "ecomplete" '("ecomplete-"))
-;;;***
-;;;### (autoloads nil "ede" "cedet/ede.el" (0 0 0 0))
;;; Generated autoloads from cedet/ede.el
-(push (purecopy '(ede 1 2)) package--builtin-versions)
+(push (purecopy '(ede 1 2)) package--builtin-versions)
(defvar global-ede-mode nil "\
Non-nil if Global Ede mode is enabled.
See the `global-ede-mode' command
@@ -9372,197 +8521,36 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-ede-mode'.")
-
(custom-autoload 'global-ede-mode "ede" nil)
-
(autoload 'global-ede-mode "ede" "\
Toggle global EDE (Emacs Development Environment) mode.
-This is a minor mode. If called interactively, toggle the `Global Ede
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-ede-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
This global minor mode enables `ede-minor-mode' in all buffers in
an EDE controlled project.
-\(fn &optional ARG)" t nil)
-
-(register-definition-prefixes "ede" '("ede" "global-ede-mode-map" "project-try-ede"))
-
-;;;***
-
-;;;### (autoloads nil "ede/auto" "cedet/ede/auto.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/auto.el
-
-(register-definition-prefixes "ede/auto" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/autoconf-edit" "cedet/ede/autoconf-edit.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/autoconf-edit.el
-
-(register-definition-prefixes "ede/autoconf-edit" '("autoconf-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/detect" "cedet/ede/detect.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/detect.el
-
-(register-definition-prefixes "ede/detect" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/makefile-edit" "cedet/ede/makefile-edit.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/makefile-edit.el
-
-(register-definition-prefixes "ede/makefile-edit" '("makefile-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/pconf" "cedet/ede/pconf.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/pconf.el
-
-(register-definition-prefixes "ede/pconf" '("ede-pconf-create-file-query"))
-
-;;;***
-
-;;;### (autoloads nil "ede/pmake" "cedet/ede/pmake.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/pmake.el
-
-(register-definition-prefixes "ede/pmake" '("ede-pmake-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj" "cedet/ede/proj.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/proj.el
-
-(register-definition-prefixes "ede/proj" '("ede-proj-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-archive" "cedet/ede/proj-archive.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-archive.el
-
-(register-definition-prefixes "ede/proj-archive" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-aux" "cedet/ede/proj-aux.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from cedet/ede/proj-aux.el
-
-(register-definition-prefixes "ede/proj-aux" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-comp" "cedet/ede/proj-comp.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-comp.el
-
-(register-definition-prefixes "ede/proj-comp" '("ede-" "proj-comp-insert-variable-once"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-elisp" "cedet/ede/proj-elisp.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-elisp.el
-
-(register-definition-prefixes "ede/proj-elisp" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-info" "cedet/ede/proj-info.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-info.el
-
-(register-definition-prefixes "ede/proj-info" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-misc" "cedet/ede/proj-misc.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-misc.el
-
-(register-definition-prefixes "ede/proj-misc" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-obj" "cedet/ede/proj-obj.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from cedet/ede/proj-obj.el
-
-(register-definition-prefixes "ede/proj-obj" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-prog" "cedet/ede/proj-prog.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-prog.el
-
-(register-definition-prefixes "ede/proj-prog" '("ede-proj-target-makefile-program"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-scheme" "cedet/ede/proj-scheme.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-scheme.el
-
-(register-definition-prefixes "ede/proj-scheme" '("ede-proj-target-scheme"))
-
-;;;***
-
-;;;### (autoloads nil "ede/proj-shared" "cedet/ede/proj-shared.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/proj-shared.el
-
-(register-definition-prefixes "ede/proj-shared" '("ede-"))
-
-;;;***
-
-;;;### (autoloads nil "ede/project-am" "cedet/ede/project-am.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/ede/project-am.el
-
-(register-definition-prefixes "ede/project-am" '("project-am-"))
+This is a global minor mode. If called interactively, toggle the
+`Global Ede mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-;;;***
-
-;;;### (autoloads nil "ede/simple" "cedet/ede/simple.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/simple.el
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
-(register-definition-prefixes "ede/simple" '("ede-simple-"))
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='global-ede-mode)'.
-;;;***
-
-;;;### (autoloads nil "ede/source" "cedet/ede/source.el" (0 0 0 0))
-;;; Generated autoloads from cedet/ede/source.el
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-(register-definition-prefixes "ede/source" '("ede-source"))
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "ede" '("ede" "global-ede-mode-map" "project-try-ede"))
-;;;***
-;;;### (autoloads nil "ede/srecode" "cedet/ede/srecode.el" (0 0 0
-;;;;;; 0))
-;;; Generated autoloads from cedet/ede/srecode.el
+;;; Generated autoloads from cedet/semantic/ede-grammar.el
-(register-definition-prefixes "ede/srecode" '("ede-srecode-"))
+(register-definition-prefixes "semantic/ede-grammar" '("semantic-ede-"))
-;;;***
-;;;### (autoloads nil "edebug" "emacs-lisp/edebug.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/edebug.el
(defvar edebug-all-defs nil "\
@@ -9573,27 +8561,24 @@ This applies to `eval-defun', `eval-region', `eval-buffer', and
You can use the command `edebug-all-defs' to toggle the value of this
variable. You may wish to make it local to each buffer with
-\(make-local-variable \\='edebug-all-defs) in your
-`emacs-lisp-mode-hook'.")
+(make-local-variable \\='edebug-all-defs) in your
+`emacs-lisp-mode-hook'.
+Note that this user option has no effect unless the edebug
+package has been loaded.")
(custom-autoload 'edebug-all-defs "edebug" t)
-
(defvar edebug-all-forms nil "\
Non-nil means evaluation of all forms will instrument for Edebug.
This doesn't apply to loading or evaluations in the minibuffer.
Use the command `edebug-all-forms' to toggle the value of this option.")
-
(custom-autoload 'edebug-all-forms "edebug" t)
-
(autoload 'edebug-basic-spec "edebug" "\
Return t if SPEC uses only extant spec symbols.
An extant spec symbol is a symbol that is not a function and has a
`edebug-form-spec' property.
-\(fn SPEC)" nil nil)
-
+(fn SPEC)" nil nil)
(defalias 'edebug-defun 'edebug-eval-top-level-form)
-
(autoload 'edebug-eval-top-level-form "edebug" "\
Evaluate the top level form point is in, stepping through with Edebug.
This is like `eval-defun' except that it steps the code for Edebug
@@ -9609,53 +8594,42 @@ instrumented for Edebug.
If the current defun is actually a call to `defvar' or `defcustom',
evaluating it this way resets the variable using its initial value
expression even if the variable already has some other value.
-\(Normally `defvar' and `defcustom' do not alter the value if there
+(Normally `defvar' and `defcustom' do not alter the value if there
already is one.)" t nil)
-
(autoload 'edebug-all-defs "edebug" "\
Toggle edebugging of all definitions." t nil)
-
(autoload 'edebug-all-forms "edebug" "\
Toggle edebugging of all forms." t nil)
-
(register-definition-prefixes "edebug" '("arglist" "backquote-form" "def-declarations" "edebug" "function-form" "interactive" "lambda-" "name" "nested-backquote-form"))
-;;;***
-;;;### (autoloads nil "ediff" "vc/ediff.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff.el
-(push (purecopy '(ediff 2 81 6)) package--builtin-versions)
+(push (purecopy '(ediff 2 81 6)) package--builtin-versions)
(autoload 'ediff-files "ediff" "\
Run Ediff on a pair of files, FILE-A and FILE-B.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn FILE-A FILE-B &optional STARTUP-HOOKS)" t nil)
-
+(fn FILE-A FILE-B &optional STARTUP-HOOKS)" t nil)
(autoload 'ediff-files3 "ediff" "\
Run Ediff on three files, FILE-A, FILE-B, and FILE-C.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil)
-
+(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil)
(defalias 'ediff3 #'ediff-files3)
-
(defalias 'ediff #'ediff-files)
-
(autoload 'ediff-current-file "ediff" "\
Start ediff between current buffer and its file on disk.
This command can be used instead of `revert-buffer'. If there is
nothing to revert then this command fails." t nil)
-
(autoload 'ediff-backup "ediff" "\
Run Ediff on FILE and its backup file.
Uses the latest backup, if there are several numerical backups.
If this file is a backup, `ediff' it with its original.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'ediff-buffers "ediff" "\
Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B.
STARTUP-HOOKS is a list of functions that Emacs calls without
@@ -9666,10 +8640,8 @@ symbol describing the Ediff job type; it defaults to
`ediff-last-dir-C', `ediff-buffers3', `ediff-merge-buffers', or
`ediff-merge-buffers-with-ancestor'.
-\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil)
-
+(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil)
(defalias 'ebuffers #'ediff-buffers)
-
(autoload 'ediff-buffers3 "ediff" "\
Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C.
STARTUP-HOOKS is a list of functions that Emacs calls without
@@ -9680,10 +8652,8 @@ symbol describing the Ediff job type; it defaults to
`ediff-last-dir-C', `ediff-buffers', `ediff-merge-buffers', or
`ediff-merge-buffers-with-ancestor'.
-\(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil)
-
+(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil)
(defalias 'ebuffers3 #'ediff-buffers3)
-
(autoload 'ediff-directories "ediff" "\
Run Ediff on directories DIR1 and DIR2, comparing files.
Consider only files that have the same name in both directories.
@@ -9691,19 +8661,15 @@ Consider only files that have the same name in both directories.
REGEXP is nil or a regular expression; only file names that match
the regexp are considered.
-\(fn DIR1 DIR2 REGEXP)" t nil)
-
+(fn DIR1 DIR2 REGEXP)" t nil)
(defalias 'edirs #'ediff-directories)
-
(autoload 'ediff-directory-revisions "ediff" "\
Run Ediff on a directory, DIR1, comparing its files with their revisions.
The second argument, REGEXP, is a regular expression that filters the file
names. Only the files that are under revision control are taken into account.
-\(fn DIR1 REGEXP)" t nil)
-
+(fn DIR1 REGEXP)" t nil)
(defalias 'edir-revisions #'ediff-directory-revisions)
-
(autoload 'ediff-directories3 "ediff" "\
Run Ediff on directories DIR1, DIR2, and DIR3, comparing files.
Consider only files that have the same name in all three directories.
@@ -9711,20 +8677,16 @@ Consider only files that have the same name in all three directories.
REGEXP is nil or a regular expression; only file names that match
the regexp are considered.
-\(fn DIR1 DIR2 DIR3 REGEXP)" t nil)
-
+(fn DIR1 DIR2 DIR3 REGEXP)" t nil)
(defalias 'edirs3 #'ediff-directories3)
-
(autoload 'ediff-merge-directories "ediff" "\
Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
the same name in both. The third argument, REGEXP, is nil or a regular
expression; only file names that match the regexp are considered.
MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
-\(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
-
+(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
(defalias 'edirs-merge #'ediff-merge-directories)
-
(autoload 'ediff-merge-directories-with-ancestor "ediff" "\
Merge files in DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors.
Ediff merges files that have identical names in DIR1, DIR2. If a pair of files
@@ -9733,30 +8695,24 @@ without ancestor. The fourth argument, REGEXP, is nil or a regular expression;
only file names that match the regexp are considered.
MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
-\(fn DIR1 DIR2 ANCESTOR-DIR REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
-
+(fn DIR1 DIR2 ANCESTOR-DIR REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
(autoload 'ediff-merge-directory-revisions "ediff" "\
Run Ediff on a directory, DIR1, merging its files with their revisions.
The second argument, REGEXP, is a regular expression that filters the file
names. Only the files that are under revision control are taken into account.
MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
-\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
-
+(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
(defalias 'edir-merge-revisions #'ediff-merge-directory-revisions)
-
(autoload 'ediff-merge-directory-revisions-with-ancestor "ediff" "\
Run Ediff on DIR1 and merge its files with their revisions and ancestors.
The second argument, REGEXP, is a regular expression that filters the file
names. Only the files that are under revision control are taken into account.
MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
-\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
-
+(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil)
(defalias 'edir-merge-revisions-with-ancestor 'ediff-merge-directory-revisions-with-ancestor)
-
(defalias 'edirs-merge-with-ancestor 'ediff-merge-directories-with-ancestor)
-
(autoload 'ediff-windows-wordwise "ediff" "\
Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
This compares the portions of text visible in each of the two windows.
@@ -9767,8 +8723,7 @@ If WIND-B is nil, use window next to WIND-A.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil)
-
+(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil)
(autoload 'ediff-windows-linewise "ediff" "\
Compare WIND-A and WIND-B, which are selected by clicking, linewise.
This compares the portions of text visible in each of the two windows.
@@ -9779,8 +8734,7 @@ If WIND-B is nil, use window next to WIND-A.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil)
-
+(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil)
(autoload 'ediff-regions-wordwise "ediff" "\
Run Ediff on a pair of regions in specified buffers.
BUFFER-A and BUFFER-B are the buffers to be compared.
@@ -9790,8 +8744,7 @@ use `ediff-regions-linewise' instead.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil)
-
+(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil)
(autoload 'ediff-regions-linewise "ediff" "\
Run Ediff on a pair of regions in specified buffers.
BUFFER-A and BUFFER-B are the buffers to be compared.
@@ -9802,10 +8755,8 @@ lines. For small regions, use `ediff-regions-wordwise'.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil)
-
+(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil)
(defalias 'ediff-merge 'ediff-merge-files)
-
(autoload 'ediff-merge-files "ediff" "\
Merge two files without ancestor.
FILE-A and FILE-B are the names of the files to be merged.
@@ -9813,8 +8764,7 @@ STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers. MERGE-BUFFER-FILE
is the name of the file to be associated with the merge buffer..
-\(fn FILE-A FILE-B &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
-
+(fn FILE-A FILE-B &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
(autoload 'ediff-merge-files-with-ancestor "ediff" "\
Merge two files with ancestor.
FILE-A and FILE-B are the names of the files to be merged, and
@@ -9823,10 +8773,8 @@ a list of functions that Emacs calls without arguments after
setting up the Ediff buffers. MERGE-BUFFER-FILE is the name of
the file to be associated with the merge buffer.
-\(fn FILE-A FILE-B FILE-ANCESTOR &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
-
+(fn FILE-A FILE-B FILE-ANCESTOR &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
(defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor)
-
(autoload 'ediff-merge-buffers "ediff" "\
Merge buffers without ancestor.
BUFFER-A and BUFFER-B are the buffers to be merged.
@@ -9839,8 +8787,7 @@ symbol describing the Ediff job type; it defaults to
`ediff-merge-buffers-with-ancestor'. MERGE-BUFFER-FILE is the
name of the file to be associated with the merge buffer.
-\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil)
-
+(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil)
(autoload 'ediff-merge-buffers-with-ancestor "ediff" "\
Merge buffers with ancestor.
BUFFER-A and BUFFER-B are the buffers to be merged, and
@@ -9853,8 +8800,7 @@ also be one of `ediff-merge-files-with-ancestor',
`ediff-buffers3', or `ediff-merge-buffers'. MERGE-BUFFER-FILE is
the name of the file to be associated with the merge buffer.
-\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil)
-
+(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil)
(autoload 'ediff-merge-revisions "ediff" "\
Run Ediff by merging two revisions of a file.
The file is the optional FILE argument or the file visited by the
@@ -9863,8 +8809,7 @@ calls without arguments after setting up the Ediff buffers.
MERGE-BUFFER-FILE is the name of the file to be associated with
the merge buffer.
-\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
-
+(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
(autoload 'ediff-merge-revisions-with-ancestor "ediff" "\
Run Ediff by merging two revisions of a file with a common ancestor.
The file is the optional FILE argument or the file visited by the
@@ -9873,8 +8818,7 @@ calls without arguments after setting up the Ediff buffers.
MERGE-BUFFER-FILE is the name of the file to be associated with
the merge buffer.
-\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
-
+(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil)
(autoload 'ediff-patch-file "ediff" "\
Query for a file name, and then run Ediff by patching that file.
If optional PATCH-BUF is given, use the patch in that buffer
@@ -9882,8 +8826,7 @@ and don't ask the user.
If prefix argument ARG, then: if even argument, assume that the
patch is in a buffer. If odd -- assume it is in a file.
-\(fn &optional ARG PATCH-BUF)" t nil)
-
+(fn &optional ARG PATCH-BUF)" t nil)
(autoload 'ediff-patch-buffer "ediff" "\
Run Ediff by patching the buffer specified at prompt.
Without the optional prefix ARG, asks if the patch is in some buffer and
@@ -9893,12 +8836,9 @@ With ARG=2, assumes the patch is in a buffer and prompts for the buffer.
PATCH-BUF is an optional argument, which specifies the buffer that contains the
patch. If not given, the user is prompted according to the prefix argument.
-\(fn &optional ARG PATCH-BUF)" t nil)
-
+(fn &optional ARG PATCH-BUF)" t nil)
(defalias 'epatch 'ediff-patch-file)
-
(defalias 'epatch-buffer 'ediff-patch-buffer)
-
(autoload 'ediff-revision "ediff" "\
Run Ediff by comparing versions of a file.
The file is an optional FILE argument or the file entered at the prompt.
@@ -9907,153 +8847,118 @@ Uses `vc.el' or `rcs.el' depending on `ediff-version-control-package'.
STARTUP-HOOKS is a list of functions that Emacs calls without
arguments after setting up the Ediff buffers.
-\(fn &optional FILE STARTUP-HOOKS)" t nil)
-
+(fn &optional FILE STARTUP-HOOKS)" t nil)
(defalias 'erevision 'ediff-revision)
-
(autoload 'ediff-version "ediff" "\
Return string describing the version of Ediff.
When called interactively, displays the version." t nil)
-
(autoload 'ediff-documentation "ediff" "\
Display Ediff's manual.
With optional NODE, goes to that node.
-\(fn &optional NODE)" t nil)
-
+(fn &optional NODE)" t nil)
(autoload 'ediff-files-command "ediff" "\
Call `ediff-files' with the next two command line arguments." nil nil)
-
(autoload 'ediff3-files-command "ediff" "\
Call `ediff3-files' with the next three command line arguments." nil nil)
-
(autoload 'ediff-merge-command "ediff" "\
Call `ediff-merge-files' with the next two command line arguments." nil nil)
-
(autoload 'ediff-merge-with-ancestor-command "ediff" "\
Call `ediff-merge-files-with-ancestor' with next three command line arguments." nil nil)
-
(autoload 'ediff-directories-command "ediff" "\
Call `ediff-directories' with the next three command line arguments." nil nil)
-
(autoload 'ediff-directories3-command "ediff" "\
Call `ediff-directories3' with the next four command line arguments." nil nil)
-
(autoload 'ediff-merge-directories-command "ediff" "\
Call `ediff-merge-directories' with the next three command line arguments." nil nil)
-
(autoload 'ediff-merge-directories-with-ancestor-command "ediff" "\
Call `ediff-merge-directories-with-ancestor' with the next four command line
arguments." nil nil)
-
(register-definition-prefixes "ediff" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-diff" "vc/ediff-diff.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-diff.el
(register-definition-prefixes "ediff-diff" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-help" "vc/ediff-help.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-help.el
(autoload 'ediff-customize "ediff-help" nil t nil)
-
(register-definition-prefixes "ediff-help" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-init" "vc/ediff-init.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-init.el
(register-definition-prefixes "ediff-init" '("ediff-" "stipple-pixmap"))
-;;;***
-;;;### (autoloads nil "ediff-merg" "vc/ediff-merg.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-merg.el
(register-definition-prefixes "ediff-merg" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-mult" "vc/ediff-mult.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-mult.el
(autoload 'ediff-show-registry "ediff-mult" "\
Display Ediff's registry." t nil)
-
(defalias 'eregistry #'ediff-show-registry)
-
(register-definition-prefixes "ediff-mult" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-ptch" "vc/ediff-ptch.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-ptch.el
(register-definition-prefixes "ediff-ptch" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-util" "vc/ediff-util.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-util.el
(autoload 'ediff-toggle-multiframe "ediff-util" "\
Switch from multiframe display to single-frame display and back.
To change the default, set the variable `ediff-window-setup-function',
which see." t nil)
-
(autoload 'ediff-toggle-use-toolbar "ediff-util" "\
Enable or disable Ediff toolbar.
Works only in versions of Emacs that support toolbars.
To change the default, set the variable `ediff-use-toolbar-p', which see." t nil)
-
(register-definition-prefixes "ediff-util" '("ediff-"))
-;;;***
-;;;### (autoloads nil "ediff-vers" "vc/ediff-vers.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-vers.el
(register-definition-prefixes "ediff-vers" '("ediff-" "rcs-ediff-view-revision"))
-;;;***
-;;;### (autoloads nil "ediff-wind" "vc/ediff-wind.el" (0 0 0 0))
;;; Generated autoloads from vc/ediff-wind.el
(register-definition-prefixes "ediff-wind" '("ediff-"))
-;;;***
-;;;### (autoloads nil "edmacro" "edmacro.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/edit.el
+
+(register-definition-prefixes "semantic/edit" '("semantic-"))
+
+
;;; Generated autoloads from edmacro.el
(autoload 'edit-kbd-macro "edmacro" "\
Edit a keyboard macro.
At the prompt, type any key sequence which is bound to a keyboard macro.
-Or, type `\\[kmacro-end-and-call-macro]' or RET to edit the last
+Or, type `\\[kmacro-end-and-call-macro]' or \\`RET' to edit the last
keyboard macro, `\\[view-lossage]' to edit the last 300
keystrokes as a keyboard macro, or `\\[execute-extended-command]'
to edit a macro by its command name.
With a prefix argument, format the macro in a more concise way.
-\(fn KEYS &optional PREFIX FINISH-HOOK STORE-HOOK)" t nil)
-
+(fn KEYS &optional PREFIX FINISH-HOOK STORE-HOOK)" t nil)
(autoload 'edit-last-kbd-macro "edmacro" "\
Edit the most recently defined keyboard macro.
-\(fn &optional PREFIX)" t nil)
-
+(fn &optional PREFIX)" t nil)
(autoload 'edit-named-kbd-macro "edmacro" "\
Edit a keyboard macro which has been given a name by `name-last-kbd-macro'.
-\(fn &optional PREFIX)" t nil)
-
+(fn &optional PREFIX)" t nil)
(autoload 'read-kbd-macro "edmacro" "\
Read the region as a keyboard macro definition.
The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
@@ -10066,8 +8971,7 @@ the result is returned rather than being installed as the current macro.
The result will be a string if possible, otherwise an event vector.
Second argument NEED-VECTOR means to return an event vector always.
-\(fn START &optional END)" t nil)
-
+(fn START &optional END)" t nil)
(autoload 'format-kbd-macro "edmacro" "\
Return the keyboard macro MACRO as a human-readable string.
This string is suitable for passing to `read-kbd-macro'.
@@ -10075,13 +8979,10 @@ Second argument VERBOSE means to put one command per line with comments.
If VERBOSE is `1', put everything on one line. If VERBOSE is omitted
or nil, use a compact 80-column format.
-\(fn &optional MACRO VERBOSE)" nil nil)
-
+(fn &optional MACRO VERBOSE)" nil nil)
(register-definition-prefixes "edmacro" '("edmacro-"))
-;;;***
-;;;### (autoloads nil "edt" "emulation/edt.el" (0 0 0 0))
;;; Generated autoloads from emulation/edt.el
(autoload 'edt-set-scroll-margins "edt" "\
@@ -10089,47 +8990,32 @@ Set scroll margins.
Argument TOP is the top margin in number of lines or percent of window.
Argument BOTTOM is the bottom margin in number of lines or percent of window.
-\(fn TOP BOTTOM)" t nil)
-
+(fn TOP BOTTOM)" t nil)
(autoload 'edt-emulation-on "edt" "\
Turn on EDT Emulation." t nil)
-
(register-definition-prefixes "edt" '("edt-"))
-;;;***
-;;;### (autoloads nil "edt-lk201" "emulation/edt-lk201.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emulation/edt-lk201.el
(register-definition-prefixes "edt-lk201" '("*EDT-keys*"))
-;;;***
-;;;### (autoloads nil "edt-mapper" "emulation/edt-mapper.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/edt-mapper.el
(register-definition-prefixes "edt-mapper" '("edt-"))
-;;;***
-;;;### (autoloads nil "edt-pc" "emulation/edt-pc.el" (0 0 0 0))
;;; Generated autoloads from emulation/edt-pc.el
(register-definition-prefixes "edt-pc" '("*EDT-keys*"))
-;;;***
-;;;### (autoloads nil "edt-vt100" "emulation/edt-vt100.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emulation/edt-vt100.el
(register-definition-prefixes "edt-vt100" '("edt-set-term-width-"))
-;;;***
-;;;### (autoloads nil "ehelp" "ehelp.el" (0 0 0 0))
;;; Generated autoloads from ehelp.el
(autoload 'with-electric-help "ehelp" "\
@@ -10156,38 +9042,28 @@ When the user exits (with `electric-help-exit', or otherwise), the help
buffer's window disappears (i.e., we use `save-window-excursion'), and
BUFFER is put back into its original major mode.
-\(fn THUNK &optional BUFFER NOERASE MINHEIGHT)" nil nil)
-
+(fn THUNK &optional BUFFER NOERASE MINHEIGHT)" nil nil)
(autoload 'electric-helpify "ehelp" "\
-\(fn FUN &optional NAME)" nil nil)
-
+(fn FUN &optional NAME)" nil nil)
(register-definition-prefixes "ehelp" '("ehelp-" "electric-"))
-;;;***
-;;;### (autoloads nil "eieio" "emacs-lisp/eieio.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/eieio.el
-(push (purecopy '(eieio 1 4)) package--builtin-versions)
+(push (purecopy '(eieio 1 4)) package--builtin-versions)
(register-definition-prefixes "eieio" '("child-of-class-p" "defclass" "eieio-" "find-class" "obj" "oref" "oset" "same-class-p" "set-slot-value" "slot-" "with-slots"))
-;;;***
-;;;### (autoloads nil "eieio-base" "emacs-lisp/eieio-base.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/eieio-base.el
(register-definition-prefixes "eieio-base" '("eieio-"))
-;;;***
-;;;### (autoloads nil "eieio-core" "emacs-lisp/eieio-core.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/eieio-core.el
-(push (purecopy '(eieio-core 1 4)) package--builtin-versions)
+(push (purecopy '(eieio-core 1 4)) package--builtin-versions)
(autoload 'eieio-defclass-autoload "eieio-core" "\
Create autoload symbols for the EIEIO class CNAME.
SUPERCLASSES are the superclasses that CNAME inherits from.
@@ -10196,35 +9072,45 @@ This function creates a mock-class for CNAME and adds it into
SUPERCLASSES as children.
It creates an autoload function for CNAME's constructor.
-\(fn CNAME SUPERCLASSES FILENAME DOC)" nil nil)
-
+(fn CNAME SUPERCLASSES FILENAME DOC)" nil nil)
(register-definition-prefixes "eieio-core" '("class-" "eieio-" "inconsistent-class-hierarchy" "invalid-slot-" "unbound-slot"))
-;;;***
-;;;### (autoloads nil "eieio-datadebug" "emacs-lisp/eieio-datadebug.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from emacs-lisp/eieio-custom.el
+
+(register-definition-prefixes "eieio-custom" '("eieio-"))
+
+
;;; Generated autoloads from emacs-lisp/eieio-datadebug.el
(register-definition-prefixes "eieio-datadebug" '("data-debug-insert-object-"))
-;;;***
-;;;### (autoloads nil "eieio-speedbar" "emacs-lisp/eieio-speedbar.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from emacs-lisp/eieio-opt.el
+
+(register-definition-prefixes "eieio-opt" '("eieio-"))
+
+
;;; Generated autoloads from emacs-lisp/eieio-speedbar.el
(register-definition-prefixes "eieio-speedbar" '("eieio-speedbar"))
-;;;***
-;;;### (autoloads nil "eldoc" "emacs-lisp/eldoc.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/el.el
+
+(register-definition-prefixes "srecode/el" '("srecode-semantic-apply-tag-to-dict"))
+
+
+;;; Generated autoloads from cedet/semantic/bovine/el.el
+
+(register-definition-prefixes "semantic/bovine/el" '("emacs-lisp-mode" "semantic-"))
+
+
;;; Generated autoloads from emacs-lisp/eldoc.el
-(push (purecopy '(eldoc 1 11 0)) package--builtin-versions)
-;;;***
+(push (purecopy '(eldoc 1 12 0)) package--builtin-versions)
+
-;;;### (autoloads nil "elec-pair" "elec-pair.el" (0 0 0 0))
;;; Generated autoloads from elec-pair.el
(defvar electric-pair-mode nil "\
@@ -10234,26 +9120,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `electric-pair-mode'.")
-
(custom-autoload 'electric-pair-mode "elec-pair" nil)
-
(autoload 'electric-pair-mode "elec-pair" "\
Toggle automatic parens pairing (Electric Pair mode).
-This is a minor mode. If called interactively, toggle the
-`Electric-Pair mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='electric-pair-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Electric Pair mode is a global minor mode. When enabled, typing
an open parenthesis automatically inserts the corresponding
closing parenthesis, and vice versa. (Likewise for brackets, etc.).
@@ -10262,35 +9132,70 @@ inserted around the region instead.
To toggle the mode in a single buffer, use `electric-pair-local-mode'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Electric-Pair mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='electric-pair-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'electric-pair-local-mode "elec-pair" "\
Toggle `electric-pair-mode' only in this buffer.
This is a minor mode. If called interactively, toggle the
-`Electric-Pair-Local mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Electric-Pair-Local mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(buffer-local-value \\='electric-pair-mode
-\(current-buffer))'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+(current-buffer))'.
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "elec-pair" '("electric-pair-"))
-;;;***
-;;;### (autoloads nil "elide-head" "elide-head.el" (0 0 0 0))
;;; Generated autoloads from elide-head.el
+(autoload 'elide-head-mode "elide-head" "\
+Toggle eliding (hiding) header material in the current buffer.
+
+When Elide Header mode is enabled, headers are hidden according
+to `elide-head-headers-to-hide'.
+
+This is suitable as an entry on `find-file-hook' or appropriate
+mode hooks.
+
+This is a minor mode. If called interactively, toggle the
+`Elide-Head mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `elide-head-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'elide-head "elide-head" "\
Hide header material in buffer according to `elide-head-headers-to-hide'.
@@ -10299,81 +9204,171 @@ an elided material again.
This is suitable as an entry on `find-file-hook' or appropriate mode hooks.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
+(make-obsolete 'elide-head 'elide-head-mode "29.1")
(register-definition-prefixes "elide-head" '("elide-head-"))
-;;;***
-;;;### (autoloads nil "elint" "emacs-lisp/elint.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/elint.el
(autoload 'elint-file "elint" "\
Lint the file FILE.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'elint-directory "elint" "\
Lint all the .el files in DIRECTORY.
A complicated directory may require a lot of memory.
-\(fn DIRECTORY)" t nil)
-
+(fn DIRECTORY)" t nil)
(autoload 'elint-current-buffer "elint" "\
Lint the current buffer.
If necessary, this first calls `elint-initialize'." t nil)
-
(autoload 'elint-defun "elint" "\
Lint the function at point.
If necessary, this first calls `elint-initialize'." t nil)
-
(autoload 'elint-initialize "elint" "\
Initialize elint.
If elint is already initialized, this does nothing, unless
optional prefix argument REINIT is non-nil.
-\(fn &optional REINIT)" t nil)
-
+(fn &optional REINIT)" t nil)
(register-definition-prefixes "elint" '("elint-"))
-;;;***
-;;;### (autoloads nil "elp" "emacs-lisp/elp.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/elp.el
(autoload 'elp-instrument-function "elp" "\
Instrument FUNSYM for profiling.
FUNSYM must be a symbol of a defined function.
-\(fn FUNSYM)" t nil)
-
+(fn FUNSYM)" t nil)
(autoload 'elp-instrument-list "elp" "\
Instrument, for profiling, all functions in `elp-function-list'.
Use optional LIST if provided instead.
If called interactively, prompt for LIST in the minibuffer;
type \"nil\" to use `elp-function-list'.
-\(fn &optional LIST)" t nil)
-
+(fn &optional LIST)" t nil)
(autoload 'elp-instrument-package "elp" "\
Instrument for profiling, all functions which start with PREFIX.
For example, to instrument all ELP functions, do the following:
\\[elp-instrument-package] RET elp- RET
-\(fn PREFIX)" t nil)
+Note that only functions that are currently loaded will be
+instrumented. If you run this function, and then later load
+further functions that start with PREFIX, they will not be
+instrumented automatically.
+(fn PREFIX)" t nil)
(autoload 'elp-results "elp" "\
Display current profiling results.
If `elp-reset-after-results' is non-nil, then current profiling
information for all instrumented functions is reset after results are
displayed." t nil)
-
(register-definition-prefixes "elp" '("elp-"))
-;;;***
-;;;### (autoloads nil "emacs-lock" "emacs-lock.el" (0 0 0 0))
+;;; Generated autoloads from eshell/em-alias.el
+
+(register-definition-prefixes "em-alias" '("eshell" "pcomplete/eshell-mode/alias"))
+
+
+;;; Generated autoloads from eshell/em-banner.el
+
+(register-definition-prefixes "em-banner" '("eshell-banner-"))
+
+
+;;; Generated autoloads from eshell/em-basic.el
+
+(register-definition-prefixes "em-basic" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-cmpl.el
+
+(register-definition-prefixes "em-cmpl" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-dirs.el
+
+(register-definition-prefixes "em-dirs" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-elecslash.el
+
+(register-definition-prefixes "em-elecslash" '("eshell-elec"))
+
+
+;;; Generated autoloads from eshell/em-extpipe.el
+
+(register-definition-prefixes "em-extpipe" '("em-extpipe--or-with-catch" "eshell-"))
+
+
+;;; Generated autoloads from eshell/em-glob.el
+
+(register-definition-prefixes "em-glob" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-hist.el
+
+(register-definition-prefixes "em-hist" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-ls.el
+
+(register-definition-prefixes "em-ls" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-pred.el
+
+(register-definition-prefixes "em-pred" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-prompt.el
+
+(register-definition-prefixes "em-prompt" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-rebind.el
+
+(register-definition-prefixes "em-rebind" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-script.el
+
+(register-definition-prefixes "em-script" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-smart.el
+
+(register-definition-prefixes "em-smart" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-term.el
+
+(register-definition-prefixes "em-term" '("eshell-"))
+
+
+;;; Generated autoloads from eshell/em-tramp.el
+
+(register-definition-prefixes "em-tramp" '("eshell"))
+
+
+;;; Generated autoloads from eshell/em-unix.el
+
+(register-definition-prefixes "em-unix" '("eshell" "nil-blank-string"))
+
+
+;;; Generated autoloads from eshell/em-xtra.el
+
+(register-definition-prefixes "em-xtra" '("eshell/"))
+
+
+;;; Generated autoloads from cedet/ede/emacs.el
+
+(register-definition-prefixes "ede/emacs" '("ede-emacs-"))
+
+
;;; Generated autoloads from emacs-lock.el
(autoload 'emacs-lock-mode "emacs-lock" "\
@@ -10397,13 +9392,23 @@ Other values are interpreted as usual.
See also `emacs-lock-unlockable-modes', which exempts buffers under
some major modes from being locked under some circumstances.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "emacs-lock" '("emacs-lock-" "toggle-emacs-lock"))
-;;;***
-;;;### (autoloads nil "emacsbug" "mail/emacsbug.el" (0 0 0 0))
+;;; Generated autoloads from textmodes/emacs-news-mode.el
+
+(autoload 'emacs-news-mode "emacs-news-mode" "\
+Major mode for editing the Emacs NEWS file.
+
+(fn)" t nil)
+(autoload 'emacs-news-view-mode "emacs-news-mode" "\
+Major mode for viewing the Emacs NEWS file.
+
+(fn)" t nil)
+(register-definition-prefixes "emacs-news-mode" '("emacs-news-"))
+
+
;;; Generated autoloads from mail/emacsbug.el
(autoload 'report-emacs-bug "emacsbug" "\
@@ -10414,103 +9419,77 @@ Already submitted bugs can be found in the Emacs bug tracker:
https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;max-bugs=100;base-order=1;bug-rev=1
-\(fn TOPIC &optional UNUSED)" t nil)
-
+(fn TOPIC &optional UNUSED)" t nil)
(set-advertised-calling-convention 'report-emacs-bug '(topic) '"24.5")
-
(autoload 'submit-emacs-patch "emacsbug" "\
Send an Emacs patch to the Emacs maintainers.
Interactively, you will be prompted for SUBJECT and a patch FILE
name (which will be attached to the mail). You will end up in a
Message buffer where you can explain more about the patch.
-\(fn SUBJECT FILE)" t nil)
-
+(fn SUBJECT FILE)" t nil)
(register-definition-prefixes "emacsbug" '("emacs-bug--system-description" "report-emacs-bug-"))
-;;;***
-;;;### (autoloads nil "emerge" "vc/emerge.el" (0 0 0 0))
;;; Generated autoloads from vc/emerge.el
(autoload 'emerge-files "emerge" "\
Run Emerge on two files FILE-A and FILE-B.
-\(fn ARG FILE-A FILE-B FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn ARG FILE-A FILE-B FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-files-with-ancestor "emerge" "\
Run Emerge on two files, giving another file as the ancestor.
-\(fn ARG FILE-A FILE-B FILE-ANCESTOR FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn ARG FILE-A FILE-B FILE-ANCESTOR FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-buffers "emerge" "\
Run Emerge on two buffers BUFFER-A and BUFFER-B.
-\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-buffers-with-ancestor "emerge" "\
Run Emerge on two buffers, giving another buffer as the ancestor.
-\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-files-command "emerge" nil nil nil)
-
(autoload 'emerge-files-with-ancestor-command "emerge" nil nil nil)
-
(autoload 'emerge-files-remote "emerge" "\
-\(fn FILE-A FILE-B FILE-OUT)" nil nil)
-
+(fn FILE-A FILE-B FILE-OUT)" nil nil)
(autoload 'emerge-files-with-ancestor-remote "emerge" "\
-\(fn FILE-A FILE-B FILE-ANC FILE-OUT)" nil nil)
-
+(fn FILE-A FILE-B FILE-ANC FILE-OUT)" nil nil)
(autoload 'emerge-revisions "emerge" "\
Emerge two RCS revisions of a file.
-\(fn ARG FILE REVISION-A REVISION-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn ARG FILE REVISION-A REVISION-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-revisions-with-ancestor "emerge" "\
Emerge two RCS revisions of a file, with another revision as ancestor.
-\(fn ARG FILE REVISION-A REVISION-B ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
-
+(fn ARG FILE REVISION-A REVISION-B ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil)
(autoload 'emerge-merge-directories "emerge" "\
-\(fn A-DIR B-DIR ANCESTOR-DIR OUTPUT-DIR)" t nil)
-
+(fn A-DIR B-DIR ANCESTOR-DIR OUTPUT-DIR)" t nil)
(register-definition-prefixes "emerge" '("emerge-"))
-;;;***
-;;;### (autoloads nil "emoji" "international/emoji.el" (0 0 0 0))
;;; Generated autoloads from international/emoji.el
(autoload 'emoji-insert "emoji" "\
-Choose and insert an emoji glyph.
-If TEXT (interactively, the prefix argument), choose the emoji
-by typing its Unicode Standard name (with completion), instead
-of selecting from emoji display.
-
-\(fn &optional TEXT)" t nil)
-
+Choose and insert an emoji glyph." t nil)
(autoload 'emoji-recent "emoji" "\
Choose and insert one of the recently-used emoji glyphs." t nil)
-
(autoload 'emoji-search "emoji" "\
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." t nil)
-
+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." t nil)
(autoload 'emoji-list "emoji" "\
List emojis and insert the one that's selected.
Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture.
The glyph will be inserted into the buffer that was current
when the command was invoked." t nil)
-
(autoload 'emoji-describe "emoji" "\
Display the name of the grapheme cluster composed from GLYPH.
GLYPH should be a string of one or more characters which together
@@ -10520,34 +9499,25 @@ could also be any character, not just emoji).
If called from Lisp, return the name as a string; return nil if
the name is not known.
-\(fn GLYPH &optional INTERACTIVE)" t nil)
+(fn GLYPH &optional INTERACTIVE)" t nil)
+(autoload 'emoji-zoom-increase "emoji" "\
+Increase the size of the character under point.
+FACTOR is the multiplication factor for the size.
+(fn &optional FACTOR)" t nil)
+(autoload 'emoji-zoom-decrease "emoji" "\
+Decrease the size of the character under point." t nil)
(register-definition-prefixes "emoji" '("emoji-"))
-;;;***
-;;;### (autoloads nil "enriched" "textmodes/enriched.el" (0 0 0 0))
;;; Generated autoloads from textmodes/enriched.el
(autoload 'enriched-mode "enriched" "\
Minor mode for editing text/enriched files.
+
These are files with embedded formatting information in the MIME standard
text/enriched format.
-This is a minor mode. If called interactively, toggle the `Enriched
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `enriched-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Turning the mode on or off runs `enriched-mode-hook'.
More information about Enriched mode is available in the file
@@ -10557,35 +9527,42 @@ Commands:
\\{enriched-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Enriched mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-(autoload 'enriched-encode "enriched" "\
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `enriched-mode'.
-\(fn FROM TO ORIG-BUF)" nil nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
+(autoload 'enriched-encode "enriched" "\
-(autoload 'enriched-decode "enriched" "\
+(fn FROM TO ORIG-BUF)" nil nil)
+(autoload 'enriched-decode "enriched" "\
-\(fn FROM TO)" nil nil)
+(fn FROM TO)" nil nil)
(register-definition-prefixes "enriched" '("enriched-"))
-;;;***
-;;;### (autoloads nil "epa" "epa.el" (0 0 0 0))
;;; Generated autoloads from epa.el
(autoload 'epa-list-keys "epa" "\
List all keys matched with NAME from the public keyring.
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(autoload 'epa-list-secret-keys "epa" "\
List all keys matched with NAME from the private keyring.
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(autoload 'epa-select-keys "epa" "\
Display a user's keyring and ask him to select keys.
CONTEXT is an `epg-context'.
@@ -10594,29 +9571,24 @@ NAMES is a list of strings to be matched with keys. If it is nil, all
the keys are listed.
If SECRET is non-nil, list secret keys instead of public keys.
-\(fn CONTEXT PROMPT &optional NAMES SECRET)" nil nil)
-
+(fn CONTEXT PROMPT &optional NAMES SECRET)" nil nil)
(autoload 'epa-decrypt-file "epa" "\
Decrypt DECRYPT-FILE into PLAIN-FILE.
If you do not specify PLAIN-FILE, this functions prompts for the value to use.
-\(fn DECRYPT-FILE &optional PLAIN-FILE)" t nil)
-
+(fn DECRYPT-FILE &optional PLAIN-FILE)" t nil)
(autoload 'epa-verify-file "epa" "\
Verify FILE.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'epa-sign-file "epa" "\
Sign FILE by SIGNERS keys selected.
-\(fn FILE SIGNERS MODE)" t nil)
-
+(fn FILE SIGNERS MODE)" t nil)
(autoload 'epa-encrypt-file "epa" "\
Encrypt FILE for RECIPIENTS.
-\(fn FILE RECIPIENTS)" t nil)
-
+(fn FILE RECIPIENTS)" t nil)
(autoload 'epa-decrypt-region "epa" "\
Decrypt the current region between START and END.
@@ -10635,23 +9607,20 @@ should consider using the string based counterpart
For example:
-\(let ((context (epg-make-context \\='OpenPGP)))
+(let ((context (epg-make-context \\='OpenPGP)))
(decode-coding-string
(epg-decrypt-string context (buffer-substring start end))
\\='utf-8))
-\(fn START END &optional MAKE-BUFFER-FUNCTION)" t nil)
-
+(fn START END &optional MAKE-BUFFER-FUNCTION)" t nil)
(autoload 'epa-decrypt-armor-in-region "epa" "\
Decrypt OpenPGP armors in the current region between START and END.
Don't use this command in Lisp programs!
See the reason described in the `epa-decrypt-region' documentation.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(function-put 'epa-decrypt-armor-in-region 'interactive-only 't)
-
(autoload 'epa-verify-region "epa" "\
Verify the current region between START and END.
@@ -10665,25 +9634,21 @@ should consider using the string based counterpart
For example:
-\(let ((context (epg-make-context \\='OpenPGP)))
+(let ((context (epg-make-context \\='OpenPGP)))
(decode-coding-string
(epg-verify-string context (buffer-substring start end))
\\='utf-8))
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(function-put 'epa-verify-region 'interactive-only 't)
-
(autoload 'epa-verify-cleartext-in-region "epa" "\
Verify OpenPGP cleartext signed messages in current region from START to END.
Don't use this command in Lisp programs!
See the reason described in the `epa-verify-region' documentation.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(function-put 'epa-verify-cleartext-in-region 'interactive-only 't)
-
(autoload 'epa-sign-region "epa" "\
Sign the current region between START and END by SIGNERS keys selected.
@@ -10696,15 +9661,13 @@ based counterpart `epg-sign-file' instead.
For example:
-\(let ((context (epg-make-context \\='OpenPGP)))
+(let ((context (epg-make-context \\='OpenPGP)))
(epg-sign-string
context
(encode-coding-string (buffer-substring start end) \\='utf-8)))
-\(fn START END SIGNERS MODE)" t nil)
-
+(fn START END SIGNERS MODE)" t nil)
(function-put 'epa-sign-region 'interactive-only 't)
-
(autoload 'epa-encrypt-region "epa" "\
Encrypt the current region between START and END for RECIPIENTS.
@@ -10717,84 +9680,64 @@ file based counterpart `epg-encrypt-file' instead.
For example:
-\(let ((context (epg-make-context \\='OpenPGP)))
+(let ((context (epg-make-context \\='OpenPGP)))
(epg-encrypt-string
context
(encode-coding-string (buffer-substring start end) \\='utf-8)
nil))
-\(fn START END RECIPIENTS SIGN SIGNERS)" t nil)
-
+(fn START END RECIPIENTS SIGN SIGNERS)" t nil)
(function-put 'epa-encrypt-region 'interactive-only 't)
-
(autoload 'epa-delete-keys "epa" "\
Delete selected KEYS.
-\(fn KEYS &optional ALLOW-SECRET)" t nil)
-
+(fn KEYS &optional ALLOW-SECRET)" t nil)
(autoload 'epa-import-keys "epa" "\
Import keys from FILE.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'epa-import-keys-region "epa" "\
Import keys from the region.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'epa-import-armor-in-region "epa" "\
Import keys in the OpenPGP armor format in the current region from START to END.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'epa-export-keys "epa" "\
Export selected KEYS to FILE.
-\(fn KEYS FILE)" t nil)
-
+(fn KEYS FILE)" t nil)
(autoload 'epa-insert-keys "epa" "\
Insert selected KEYS after the point.
-\(fn KEYS)" t nil)
-
+(fn KEYS)" t nil)
(register-definition-prefixes "epa" '("epa-"))
-;;;***
-;;;### (autoloads nil "epa-dired" "epa-dired.el" (0 0 0 0))
;;; Generated autoloads from epa-dired.el
(autoload 'epa-dired-do-decrypt "epa-dired" "\
Decrypt marked files." t nil)
-
(autoload 'epa-dired-do-verify "epa-dired" "\
Verify marked files." t nil)
-
(autoload 'epa-dired-do-sign "epa-dired" "\
Sign marked files." t nil)
-
(autoload 'epa-dired-do-encrypt "epa-dired" "\
Encrypt marked files." t nil)
-;;;***
-;;;### (autoloads nil "epa-file" "epa-file.el" (0 0 0 0))
;;; Generated autoloads from epa-file.el
(autoload 'epa-file-handler "epa-file" "\
-\(fn OPERATION &rest ARGS)" nil nil)
-
+(fn OPERATION &rest ARGS)" nil nil)
(autoload 'epa-file-enable "epa-file" nil t nil)
-
(autoload 'epa-file-disable "epa-file" nil t nil)
-
(register-definition-prefixes "epa-file" '("epa-"))
-;;;***
-;;;### (autoloads nil "epa-ks" "epa-ks.el" (0 0 0 0))
;;; Generated autoloads from epa-ks.el
(autoload 'epa-search-keys "epa-ks" "\
@@ -10808,46 +9751,38 @@ exact matches.
Note that the request may fail if the query is not specific
enough, since keyservers have strict timeout settings.
-\(fn QUERY EXACT)" t nil)
-
+(fn QUERY EXACT)" t nil)
(register-definition-prefixes "epa-ks" '("epa-k"))
-;;;***
-;;;### (autoloads nil "epa-mail" "epa-mail.el" (0 0 0 0))
;;; Generated autoloads from epa-mail.el
(autoload 'epa-mail-mode "epa-mail" "\
A minor-mode for composing encrypted/clearsigned mails.
-This is a minor mode. If called interactively, toggle the `epa-mail
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a minor mode. If called interactively, toggle the
+`epa-mail mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `epa-mail-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'epa-mail-decrypt "epa-mail" "\
Decrypt OpenPGP armors in the current buffer.
The buffer is expected to contain a mail message." t nil)
-
(function-put 'epa-mail-decrypt 'interactive-only 't)
-
(autoload 'epa-mail-verify "epa-mail" "\
Verify OpenPGP cleartext signed messages in the current buffer.
The buffer is expected to contain a mail message." t nil)
-
(function-put 'epa-mail-verify 'interactive-only 't)
-
(autoload 'epa-mail-sign "epa-mail" "\
Sign the current buffer.
The buffer is expected to contain a mail message, and signing is
@@ -10855,10 +9790,8 @@ performed with your default key.
With prefix argument, asks you to select interactively the key to
use from your key ring.
-\(fn START END SIGNERS MODE)" t nil)
-
+(fn START END SIGNERS MODE)" t nil)
(function-put 'epa-mail-sign 'interactive-only 't)
-
(autoload 'epa-mail-encrypt "epa-mail" "\
Encrypt the outgoing mail message in the current buffer.
Takes the recipients from the text in the header in the buffer
@@ -10872,14 +9805,11 @@ or nil meaning use the defaults.
SIGNERS is a list of keys to sign the message with.
-\(fn &optional RECIPIENTS SIGNERS)" t nil)
-
+(fn &optional RECIPIENTS SIGNERS)" t nil)
(autoload 'epa-mail-import-keys "epa-mail" "\
Import keys in the OpenPGP armor format in the current buffer.
The buffer is expected to contain a mail message." t nil)
-
(function-put 'epa-mail-import-keys 'interactive-only 't)
-
(defvar epa-global-mail-mode nil "\
Non-nil if Epa-Global-Mail mode is enabled.
See the `epa-global-mail-mode' command
@@ -10887,46 +9817,38 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `epa-global-mail-mode'.")
-
(custom-autoload 'epa-global-mail-mode "epa-mail" nil)
-
(autoload 'epa-global-mail-mode "epa-mail" "\
Minor mode to hook EasyPG into Mail mode.
-This is a minor mode. If called interactively, toggle the
+This is a global minor mode. If called interactively, toggle the
`Epa-Global-Mail mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='epa-global-mail-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "epa-mail" '("epa-mail-"))
-;;;***
-;;;### (autoloads nil "epg" "epg.el" (0 0 0 0))
;;; Generated autoloads from epg.el
-(push (purecopy '(epg 1 0 0)) package--builtin-versions)
+(push (purecopy '(epg 1 0 0)) package--builtin-versions)
(autoload 'epg-make-context "epg" "\
Return a context object.
-\(fn &optional PROTOCOL ARMOR TEXTMODE INCLUDE-CERTS CIPHER-ALGORITHM DIGEST-ALGORITHM COMPRESS-ALGORITHM)" nil nil)
-
+(fn &optional PROTOCOL ARMOR TEXTMODE INCLUDE-CERTS CIPHER-ALGORITHM DIGEST-ALGORITHM COMPRESS-ALGORITHM)" nil nil)
(register-definition-prefixes "epg" '("epg-"))
-;;;***
-;;;### (autoloads nil "epg-config" "epg-config.el" (0 0 0 0))
;;; Generated autoloads from epg-config.el
(autoload 'epg-find-configuration "epg-config" "\
@@ -10940,13 +9862,10 @@ Then it walks through PROGRAM-ALIST or
Otherwise, it tries the programs listed in the entry until the
version requirement is met.
-\(fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil)
-
+(fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil)
(autoload 'epg-configuration "epg-config" "\
Return a list of internal configuration parameters of `epg-gpg-program'." nil nil)
-
-(make-obsolete 'epg-configuration 'epg-find-configuration '"25.1")
-
+(make-obsolete 'epg-configuration 'epg-find-configuration "25.1")
(autoload 'epg-check-configuration "epg-config" "\
Verify that a sufficient version of GnuPG is installed.
CONFIG should be a `epg-configuration' object (a plist).
@@ -10955,24 +9874,19 @@ REQ-VERSIONS should be a list with elements of the form (MIN
semi-open range of acceptable versions. REQ-VERSIONS may also be
a single minimum version string.
-\(fn CONFIG &optional REQ-VERSIONS)" nil nil)
-
+(fn CONFIG &optional REQ-VERSIONS)" nil nil)
(autoload 'epg-expand-group "epg-config" "\
Look at CONFIG and try to expand GROUP.
-\(fn CONFIG GROUP)" nil nil)
-
+(fn CONFIG GROUP)" nil nil)
(register-definition-prefixes "epg-config" '("epg-"))
-;;;***
-;;;### (autoloads nil "erc" "erc/erc.el" (0 0 0 0))
;;; Generated autoloads from erc/erc.el
-(push (purecopy '(erc 5 4 1)) package--builtin-versions)
+(push (purecopy '(erc 5 4 1)) package--builtin-versions)
(autoload 'erc-select-read-args "erc" "\
Prompt the user for values of nick, server, port, and password." nil nil)
-
(autoload 'erc "erc" "\
ERC is a powerful, modular, and extensible IRC client.
This function is the main entry point for ERC.
@@ -10983,8 +9897,10 @@ Non-interactively, it takes the keyword arguments
(server (erc-compute-server))
(port (erc-compute-port))
(nick (erc-compute-nick))
+ (user (erc-compute-user))
password
(full-name (erc-compute-full-name))
+ id
That is, if called with
@@ -10994,10 +9910,12 @@ then the server and full-name will be set to those values,
whereas `erc-compute-port' and `erc-compute-nick' will be invoked
for the values of the other parameters.
-\(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" t nil)
+When present, ID should be an opaque object used to identify the
+connection unequivocally. This is rarely needed and not available
+interactively.
+(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) ID)" '((erc-select-read-args)) nil)
(defalias 'erc-select #'erc)
-
(autoload 'erc-tls "erc" "\
ERC is a powerful, modular, and extensible IRC client.
This function is the main entry point for ERC over TLS.
@@ -11012,6 +9930,7 @@ Non-interactively, it takes the keyword arguments
password
(full-name (erc-compute-full-name))
client-certificate
+ id
That is, if called with
@@ -11033,67 +9952,207 @@ Example usage:
(erc-tls :server \"irc.libera.chat\" :port 6697
:client-certificate
- '(\"/home/bandali/my-cert.key\"
+ \\='(\"/home/bandali/my-cert.key\"
\"/home/bandali/my-cert.crt\"))
-\(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE)" t nil)
+When present, ID should be an opaque object for identifying the
+connection unequivocally. (In most cases, this would be a string or a
+symbol composed of letters from the Latin alphabet.) This option is
+generally unneeded, however. See info node `(erc) Connecting' for use
+cases. Not available interactively.
+(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE ID)" '((let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))) nil)
(autoload 'erc-handle-irc-url "erc" "\
Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD.
If ERC is already connected to HOST:PORT, simply /join CHANNEL.
Otherwise, connect to HOST:PORT as USER and /join CHANNEL.
-\(fn HOST PORT CHANNEL USER PASSWORD)" nil nil)
-
+(fn HOST PORT CHANNEL USER PASSWORD)" nil nil)
(register-definition-prefixes "erc" '("define-erc-module" "erc-"))
-;;;***
-;;;### (autoloads nil "erc-backend" "erc/erc-backend.el" (0 0 0 0))
+;;; Generated autoloads from erc/erc-autoaway.el
+
+(register-definition-prefixes "erc-autoaway" '("erc-auto"))
+
+
;;; Generated autoloads from erc/erc-backend.el
(register-definition-prefixes "erc-backend" '("erc-"))
-;;;***
-;;;### (autoloads nil "erc-goodies" "erc/erc-goodies.el" (0 0 0 0))
+;;; Generated autoloads from erc/erc-button.el
+
+(register-definition-prefixes "erc-button" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-capab.el
+
+(register-definition-prefixes "erc-capab" '("erc-capab-identify-"))
+
+
+;;; Generated autoloads from erc/erc-compat.el
+
+(register-definition-prefixes "erc-compat" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-dcc.el
+
+(register-definition-prefixes "erc-dcc" '("erc-" "pcomplete/erc-mode/"))
+
+
+;;; Generated autoloads from erc/erc-desktop-notifications.el
+
+(register-definition-prefixes "erc-desktop-notifications" '("erc-notifications-"))
+
+
+;;; Generated autoloads from erc/erc-ezbounce.el
+
+(register-definition-prefixes "erc-ezbounce" '("erc-ezb-"))
+
+
+;;; Generated autoloads from erc/erc-fill.el
+
+(register-definition-prefixes "erc-fill" '("erc-"))
+
+
;;; Generated autoloads from erc/erc-goodies.el
(register-definition-prefixes "erc-goodies" '("erc-"))
-;;;***
-;;;### (autoloads nil "erc-ibuffer" "erc/erc-ibuffer.el" (0 0 0 0))
;;; Generated autoloads from erc/erc-ibuffer.el
(register-definition-prefixes "erc-ibuffer" '("erc-"))
-;;;***
-;;;### (autoloads nil "erc-lang" "erc/erc-lang.el" (0 0 0 0))
+;;; Generated autoloads from erc/erc-identd.el
+
+(register-definition-prefixes "erc-identd" '("erc-identd-"))
+
+
+;;; Generated autoloads from erc/erc-imenu.el
+
+(register-definition-prefixes "erc-imenu" '("erc-unfill-notice"))
+
+
+;;; Generated autoloads from erc/erc-join.el
+
+(register-definition-prefixes "erc-join" '("erc-"))
+
+
;;; Generated autoloads from erc/erc-lang.el
-(register-definition-prefixes "erc-lang" '("erc-cmd-LANG" "iso-638-languages" "language"))
+(register-definition-prefixes "erc-lang" '("erc-cmd-LANG" "iso-639-1-languages" "language"))
+
+
+;;; Generated autoloads from erc/erc-list.el
+
+(register-definition-prefixes "erc-list" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-log.el
+
+(register-definition-prefixes "erc-log" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-match.el
+
+(register-definition-prefixes "erc-match" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-menu.el
+
+(register-definition-prefixes "erc-menu" '("erc-menu-"))
+
+
+;;; Generated autoloads from erc/erc-netsplit.el
+
+(register-definition-prefixes "erc-netsplit" '("erc-"))
-;;;***
-;;;### (autoloads nil "erc-networks" "erc/erc-networks.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from erc/erc-networks.el
(autoload 'erc-determine-network "erc-networks" "\
Return the name of the network or \"Unknown\" as a symbol.
Use the server parameter NETWORK if provided, otherwise parse the
server name and search for a match in `erc-networks-alist'." nil nil)
-
+(make-obsolete 'erc-determine-network '"maybe see `erc-networks--determine'" "29.1")
(autoload 'erc-server-select "erc-networks" "\
Interactively select a server to connect to using `erc-server-alist'." t nil)
-
(register-definition-prefixes "erc-networks" '("erc-"))
-;;;***
-;;;### (autoloads nil "ert" "emacs-lisp/ert.el" (0 0 0 0))
+;;; Generated autoloads from erc/erc-notify.el
+
+(register-definition-prefixes "erc-notify" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-page.el
+
+(register-definition-prefixes "erc-page" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-pcomplete.el
+
+(register-definition-prefixes "erc-pcomplete" '("erc-pcomplet" "pcomplete"))
+
+
+;;; Generated autoloads from erc/erc-replace.el
+
+(register-definition-prefixes "erc-replace" '("erc-replace-"))
+
+
+;;; Generated autoloads from erc/erc-ring.el
+
+(register-definition-prefixes "erc-ring" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-services.el
+
+(register-definition-prefixes "erc-services" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-sound.el
+
+(register-definition-prefixes "erc-sound" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-speedbar.el
+
+(register-definition-prefixes "erc-speedbar" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-spelling.el
+
+(register-definition-prefixes "erc-spelling" '("erc-spelling-"))
+
+
+;;; Generated autoloads from erc/erc-stamp.el
+
+(register-definition-prefixes "erc-stamp" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-status-sidebar.el
+
+(register-definition-prefixes "erc-status-sidebar" '("erc-status-sidebar-"))
+
+
+;;; Generated autoloads from erc/erc-track.el
+
+(register-definition-prefixes "erc-track" '("erc-"))
+
+
+;;; Generated autoloads from erc/erc-truncate.el
+
+(register-definition-prefixes "erc-truncate" '("erc-max-buffer-size"))
+
+
+;;; Generated autoloads from erc/erc-xdcc.el
+
+(register-definition-prefixes "erc-xdcc" '("erc-"))
+
+
;;; Generated autoloads from emacs-lisp/ert.el
(autoload 'ert-deftest "ert" "\
@@ -11118,12 +10177,7 @@ it has to be wrapped in `(eval (quote ...))'.
If NAME is already defined as a test and Emacs is running
in batch mode, an error is signalled.
-\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil t)
-
-(function-put 'ert-deftest 'doc-string-elt '3)
-
-(function-put 'ert-deftest 'lisp-indent-function '2)
-
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil 'macro)
(autoload 'ert-run-tests-batch "ert" "\
Run the tests specified by SELECTOR, printing results to the terminal.
@@ -11134,8 +10188,7 @@ ert-run-tests-batch-and-exit\" useful.
Returns the stats object.
-\(fn &optional SELECTOR)" nil nil)
-
+(fn &optional SELECTOR)" nil nil)
(autoload 'ert-run-tests-batch-and-exit "ert" "\
Like `ert-run-tests-batch', but exits Emacs when done.
@@ -11144,38 +10197,28 @@ on unexpected results, or 2 if the tool detected an error outside
of the tests (e.g. invalid SELECTOR or bug in the code that runs
the tests).
-\(fn &optional SELECTOR)" nil nil)
-
+(fn &optional SELECTOR)" nil nil)
(autoload 'ert-run-tests-interactively "ert" "\
Run the tests specified by SELECTOR and display the results in a buffer.
SELECTOR works as described in `ert-select-tests'.
-\(fn SELECTOR)" t nil)
-
+(fn SELECTOR)" t nil)
(defalias 'ert #'ert-run-tests-interactively)
-
(autoload 'ert-describe-test "ert" "\
Display the documentation for TEST-OR-TEST-NAME (a symbol or ert-test).
-\(fn TEST-OR-TEST-NAME)" t nil)
-
+(fn TEST-OR-TEST-NAME)" t nil)
(register-definition-prefixes "ert" '("ert-"))
-;;;***
-;;;### (autoloads nil "ert-x" "emacs-lisp/ert-x.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/ert-x.el
(autoload 'ert-kill-all-test-buffers "ert-x" "\
Kill all test buffers that are still live." t nil)
-
(register-definition-prefixes "ert-x" '("ert-"))
-;;;***
-;;;### (autoloads nil "erts-mode" "progmodes/erts-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/erts-mode.el
(autoload 'erts-mode "erts-mode" "\
@@ -11184,97 +10227,71 @@ This mode mainly provides some font locking.
\\{erts-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "erts-mode" '("erts-"))
-;;;***
-;;;### (autoloads nil "esh-arg" "eshell/esh-arg.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-arg.el
(register-definition-prefixes "esh-arg" '("eshell-"))
-;;;***
-;;;### (autoloads nil "esh-cmd" "eshell/esh-cmd.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-cmd.el
(register-definition-prefixes "esh-cmd" '("eshell" "pcomplete/eshell-mode/eshell-debug"))
-;;;***
-;;;### (autoloads nil "esh-ext" "eshell/esh-ext.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-ext.el
(register-definition-prefixes "esh-ext" '("eshell"))
-;;;***
-;;;### (autoloads nil "esh-io" "eshell/esh-io.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-io.el
(register-definition-prefixes "esh-io" '("eshell-"))
-;;;***
-;;;### (autoloads nil "esh-mode" "eshell/esh-mode.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-mode.el
(autoload 'eshell-mode "esh-mode" "\
Emacs shell interactive mode.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'eshell-bookmark-jump "esh-mode" "\
Default bookmark handler for Eshell buffers.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "esh-mode" '("eshell"))
-;;;***
-;;;### (autoloads nil "esh-module" "eshell/esh-module.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from eshell/esh-module.el
(register-definition-prefixes "esh-module" '("eshell-"))
-;;;***
-;;;### (autoloads nil "esh-opt" "eshell/esh-opt.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-opt.el
(register-definition-prefixes "esh-opt" '("eshell-"))
-;;;***
-;;;### (autoloads nil "esh-proc" "eshell/esh-proc.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-proc.el
(register-definition-prefixes "esh-proc" '("eshell"))
-;;;***
-;;;### (autoloads nil "esh-util" "eshell/esh-util.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-util.el
(register-definition-prefixes "esh-util" '("eshell-"))
-;;;***
-;;;### (autoloads nil "esh-var" "eshell/esh-var.el" (0 0 0 0))
;;; Generated autoloads from eshell/esh-var.el
(register-definition-prefixes "esh-var" '("eshell" "pcomplete/eshell-mode/"))
-;;;***
-;;;### (autoloads nil "eshell" "eshell/eshell.el" (0 0 0 0))
;;; Generated autoloads from eshell/eshell.el
-(push (purecopy '(eshell 2 4 2)) package--builtin-versions)
+(push (purecopy '(eshell 2 4 2)) package--builtin-versions)
(autoload 'eshell "eshell" "\
Create an interactive Eshell buffer.
Start a new Eshell session, or switch to an already active
@@ -11292,14 +10309,12 @@ value of `eshell-buffer-name', which see.
Eshell is a shell-like command interpreter. For more
information on Eshell, see Info node `(eshell)Top'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'eshell-command "eshell" "\
Execute the Eshell command string COMMAND.
With prefix ARG, insert output into the current buffer at point.
-\(fn &optional COMMAND ARG)" t nil)
-
+(fn &optional COMMAND ARG)" t nil)
(autoload 'eshell-command-result "eshell" "\
Execute the given Eshell COMMAND, and return the result.
The result might be any Lisp object.
@@ -11307,13 +10322,10 @@ If STATUS-VAR is a symbol, it will be set to the exit status of the
command. This is the only way to determine whether the value returned
corresponding to a successful execution.
-\(fn COMMAND &optional STATUS-VAR)" nil nil)
-
+(fn COMMAND &optional STATUS-VAR)" nil nil)
(register-definition-prefixes "eshell" '("eshell-"))
-;;;***
-;;;### (autoloads nil "etags" "progmodes/etags.el" (0 0 0 0))
;;; Generated autoloads from progmodes/etags.el
(defvar tags-file-name nil "\
@@ -11324,59 +10336,44 @@ setting the value of this variable, whether buffer-local or global.
Use the `etags' program to make a tags table file.")
(put 'tags-file-name 'variable-interactive (purecopy "fVisit tags table: "))
(put 'tags-file-name 'safe-local-variable 'stringp)
-
(defvar tags-case-fold-search 'default "\
Whether tags operations should be case-sensitive.
A value of t means case-insensitive, a value of nil means case-sensitive.
Any other value means use the setting of `case-fold-search'.")
-
(custom-autoload 'tags-case-fold-search "etags" t)
-
(put 'tags-case-fold-search 'safe-local-variable 'symbolp)
-
(defvar tags-table-list nil "\
List of file names of tags tables to search.
An element that is a directory means the file \"TAGS\" in that directory.
To switch to a new list of tags tables, setting this variable is sufficient.
If you set this variable, do not also set `tags-file-name'.
Use the `etags' program to make a tags table file.")
-
(custom-autoload 'tags-table-list "etags" t)
-
(defvar tags-compression-info-list (purecopy '("" ".Z" ".bz2" ".gz" ".xz" ".tgz")) "\
List of extensions tried by etags when `auto-compression-mode' is on.
An empty string means search the non-compressed file.")
-
(custom-autoload 'tags-compression-info-list "etags" t)
-
(defvar tags-add-tables 'ask-user "\
Control whether to add a new tags table to the current list.
t means do; nil means don't (always start a new list).
Any other value means ask the user whether to add a new tags table
to the current list (as opposed to starting a new list).")
-
(custom-autoload 'tags-add-tables "etags" t)
-
(defvar find-tag-hook nil "\
Hook to be run by \\[find-tag] after finding a tag. See `run-hooks'.
The value in the buffer in which \\[find-tag] is done is used,
not the value in the buffer \\[find-tag] goes to.")
-
(custom-autoload 'find-tag-hook "etags" t)
-
(defvar find-tag-default-function nil "\
A function of no arguments used by \\[find-tag] to pick a default tag.
If nil, and the symbol that is the value of `major-mode'
has a `find-tag-default-function' property (see `put'), that is used.
Otherwise, `find-tag-default' is used.")
-
(custom-autoload 'find-tag-default-function "etags" t)
-
(autoload 'tags-table-mode "etags" "\
Major mode for tags table file buffers.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'visit-tags-table "etags" "\
Tell tags commands to use tags table file FILE.
FILE should be the name of a file created with the `etags' program.
@@ -11389,8 +10386,7 @@ When you find a tag with \\[find-tag], the buffer it finds the tag
in is given a local value of this variable which is the name of the tags
file the tag was in.
-\(fn FILE &optional LOCAL)" t nil)
-
+(fn FILE &optional LOCAL)" t nil)
(autoload 'visit-tags-table-buffer "etags" "\
Select the buffer containing the current tags table.
Optional arg CONT specifies which tags table to visit.
@@ -11404,21 +10400,18 @@ Optional second arg CBUF, if non-nil, specifies the initial buffer,
which is important if that buffer has a local value of `tags-file-name'.
Returns t if it visits a tags table, or nil if there are no more in the list.
-\(fn &optional CONT CBUF)" nil nil)
-
+(fn &optional CONT CBUF)" nil nil)
(autoload 'tags-table-files "etags" "\
Return a list of files in the current tags table.
Assumes the tags table is the current buffer. The file names are returned
as they appeared in the `etags' command that created the table, usually
without directory names." nil nil)
-
(autoload 'tags-lazy-completion-table "etags" nil nil nil)
(defun tags-completion-at-point-function ()
(if (or tags-table-list tags-file-name)
(progn
(load "etags")
(tags-completion-at-point-function))))
-
(autoload 'find-tag-noselect "etags" "\
Find tag (in current tags table) whose name contains TAGNAME.
Returns the buffer containing the tag's definition and moves its point there,
@@ -11439,8 +10432,7 @@ Contrast this with the ring of marks gone to by the command.
See documentation of variable `tags-file-name'.
-\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
-
+(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
(autoload 'find-tag "etags" "\
Find tag (in current tags table) whose name contains TAGNAME.
Select the buffer containing the tag's definition, and move point there.
@@ -11460,10 +10452,8 @@ Contrast this with the ring of marks gone to by the command.
See documentation of variable `tags-file-name'.
-\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
-
-(make-obsolete 'find-tag 'xref-find-definitions '"25.1")
-
+(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
+(make-obsolete 'find-tag 'xref-find-definitions "25.1")
(autoload 'find-tag-other-window "etags" "\
Find tag (in current tags table) whose name contains TAGNAME.
Select the buffer containing the tag's definition in another window, and
@@ -11484,10 +10474,8 @@ Contrast this with the ring of marks gone to by the command.
See documentation of variable `tags-file-name'.
-\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
-
-(make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window '"25.1")
-
+(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil)
+(make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window "25.1")
(autoload 'find-tag-other-frame "etags" "\
Find tag (in current tags table) whose name contains TAGNAME.
Select the buffer containing the tag's definition in another frame, and
@@ -11508,10 +10496,8 @@ Contrast this with the ring of marks gone to by the command.
See documentation of variable `tags-file-name'.
-\(fn TAGNAME &optional NEXT-P)" t nil)
-
-(make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame '"25.1")
-
+(fn TAGNAME &optional NEXT-P)" t nil)
+(make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame "25.1")
(autoload 'find-tag-regexp "etags" "\
Find tag (in current tags table) whose name matches REGEXP.
Select the buffer containing the tag's definition and move point there.
@@ -11530,14 +10516,10 @@ Contrast this with the ring of marks gone to by the command.
See documentation of variable `tags-file-name'.
-\(fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil)
-
-(make-obsolete 'find-tag-regexp 'xref-find-apropos '"25.1")
-
+(fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil)
+(make-obsolete 'find-tag-regexp 'xref-find-apropos "25.1")
(defalias 'pop-tag-mark 'xref-go-back)
-
(defalias 'next-file 'tags-next-file)
-
(autoload 'tags-next-file "etags" "\
Select next file among files in current tags table.
@@ -11551,17 +10533,14 @@ Non-nil second argument NOVISIT means use a temporary buffer
Value is nil if the file was already visited;
if the file was newly read in, the value is the filename.
-\(fn &optional INITIALIZE NOVISIT)" t nil)
-
+(fn &optional INITIALIZE NOVISIT)" t nil)
(autoload 'tags-loop-continue "etags" "\
Continue last \\[tags-search] or \\[tags-query-replace] command.
Used noninteractively with non-nil argument to begin such a command (the
argument is passed to `next-file', which see).
-\(fn &optional FIRST-TIME)" t nil)
-
-(make-obsolete 'tags-loop-continue 'fileloop-continue '"27.1")
-
+(fn &optional FIRST-TIME)" t nil)
+(make-obsolete 'tags-loop-continue 'fileloop-continue "27.1")
(autoload 'tags-search "etags" "\
Search through all files listed in tags table for match for REGEXP.
Stops when a match is found.
@@ -11572,19 +10551,22 @@ files to search. The search will be restricted to these files.
Also see the documentation of the `tags-file-name' variable.
-\(fn REGEXP &optional FILES)" t nil)
-
+(fn REGEXP &optional FILES)" t nil)
(autoload 'tags-query-replace "etags" "\
Do `query-replace-regexp' of FROM with TO on all files listed in tags table.
Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
with the command \\[fileloop-continue].
-For non-interactive use, superseded by `fileloop-initialize-replace'.
-\(fn FROM TO &optional DELIMITED FILES)" t nil)
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
-(set-advertised-calling-convention 'tags-query-replace '(from to &optional delimited) '"27.1")
+For non-interactive use, this is superseded by `fileloop-initialize-replace'.
+(fn FROM TO &optional DELIMITED FILES)" t nil)
+(set-advertised-calling-convention 'tags-query-replace '(from to &optional delimited) '"27.1")
(autoload 'list-tags "etags" "\
Display list of tags in file FILE.
This searches only the first table in the list, and no included
@@ -11593,52 +10575,38 @@ usually without a directory specification. If called
interactively, FILE defaults to the file name of the current
buffer.
-\(fn FILE &optional NEXT-MATCH)" t nil)
-
+(fn FILE &optional NEXT-MATCH)" t nil)
(autoload 'tags-apropos "etags" "\
Display list of all tags in tags table REGEXP matches.
-\(fn REGEXP)" t nil)
-
-(make-obsolete 'tags-apropos 'xref-find-apropos '"25.1")
-
+(fn REGEXP)" t nil)
+(make-obsolete 'tags-apropos 'xref-find-apropos "25.1")
(autoload 'select-tags-table "etags" "\
Select a tags table file from a menu of those you have already used.
The list of tags tables to select from is stored in `tags-table-set-list';
see the doc of that variable if you want to add names to the list." t nil)
-
(autoload 'complete-tag "etags" "\
Perform tags completion on the text around point.
Completes to the set of names listed in the current tags table.
The string to complete is chosen in the same way as the default
for \\[find-tag] (which see)." t nil)
-
(autoload 'etags--xref-backend "etags" nil nil nil)
-
(register-definition-prefixes "etags" '("default-tags-table-function" "etags-" "file-of-tag" "find-tag-" "goto-tag-location-function" "initialize-new-tags-table" "last-tag" "list-tags-function" "select-tags-table-" "snarf-tag-function" "tag" "verify-tags-table-function"))
-;;;***
-;;;### (autoloads nil "etc-authors-mode" "textmodes/etc-authors-mode.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from textmodes/etc-authors-mode.el
(autoload 'etc-authors-mode "etc-authors-mode" "\
Major mode for viewing \"etc/AUTHORS\" from the Emacs distribution.
Provides some basic font locking and not much else.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "etc-authors-mode" '("etc-authors-"))
-;;;***
-;;;### (autoloads nil "ethio-util" "language/ethio-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/ethio-util.el
(autoload 'setup-ethiopic-environment-internal "ethio-util" nil nil nil)
-
(autoload 'ethio-sera-to-fidel-buffer "ethio-util" "\
Convert the current buffer from SERA to FIDEL.
@@ -11655,8 +10623,7 @@ even if the buffer is read-only.
See also the descriptions of the variables
`ethio-use-colon-for-colon' and `ethio-use-three-dot-question'.
-\(fn &optional SECONDARY FORCE)" t nil)
-
+(fn &optional SECONDARY FORCE)" t nil)
(autoload 'ethio-sera-to-fidel-region "ethio-util" "\
Convert the characters in region from SERA to FIDEL.
@@ -11673,15 +10640,13 @@ conversion even if the buffer is read-only.
See also the descriptions of the variables
`ethio-use-colon-for-colon' and `ethio-use-three-dot-question'.
-\(fn BEGIN END &optional SECONDARY FORCE)" t nil)
-
+(fn BEGIN END &optional SECONDARY FORCE)" t nil)
(autoload 'ethio-sera-to-fidel-marker "ethio-util" "\
Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
Assume that each region begins with `ethio-primary-language'.
The markers \"<sera>\" and \"</sera>\" themselves are not deleted.
-\(fn &optional FORCE)" t nil)
-
+(fn &optional FORCE)" t nil)
(autoload 'ethio-fidel-to-sera-buffer "ethio-util" "\
Replace all the FIDEL characters in the current buffer to the SERA format.
The variable `ethio-primary-language' specifies the primary
@@ -11698,8 +10663,7 @@ See also the descriptions of the variables
`ethio-use-colon-for-colon', `ethio-use-three-dot-question',
`ethio-quote-vowel-always' and `ethio-numeric-reduction'.
-\(fn &optional SECONDARY FORCE)" t nil)
-
+(fn &optional SECONDARY FORCE)" t nil)
(autoload 'ethio-fidel-to-sera-region "ethio-util" "\
Replace all the FIDEL characters in the region to the SERA format.
@@ -11717,17 +10681,14 @@ See also the descriptions of the variables
`ethio-use-colon-for-colon', `ethio-use-three-dot-question',
`ethio-quote-vowel-always' and `ethio-numeric-reduction'.
-\(fn BEGIN END &optional SECONDARY FORCE)" t nil)
-
+(fn BEGIN END &optional SECONDARY FORCE)" t nil)
(autoload 'ethio-fidel-to-sera-marker "ethio-util" "\
Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
The markers \"<sera>\" and \"</sera>\" themselves are not deleted.
-\(fn &optional FORCE)" t nil)
-
+(fn &optional FORCE)" t nil)
(autoload 'ethio-modify-vowel "ethio-util" "\
Modify the vowel of the FIDEL that is under the cursor." t nil)
-
(autoload 'ethio-replace-space "ethio-util" "\
Replace ASCII spaces with Ethiopic word separators in the region.
@@ -11741,19 +10702,15 @@ If CH = 3, with the Ethiopic colon-like word separator.
The 2nd and 3rd arguments BEGIN and END specify the region.
-\(fn CH BEGIN END)" t nil)
-
+(fn CH BEGIN END)" t nil)
(autoload 'ethio-input-special-character "ethio-util" "\
This function is deprecated.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'ethio-fidel-to-tex-buffer "ethio-util" "\
Convert each fidel characters in the current buffer into a fidel-tex command." t nil)
-
(autoload 'ethio-tex-to-fidel-buffer "ethio-util" "\
Convert fidel-tex commands in the current buffer into fidel chars." t nil)
-
(autoload 'ethio-fidel-to-java-buffer "ethio-util" "\
Convert Ethiopic characters into the Java escape sequences.
@@ -11762,32 +10719,29 @@ character's codepoint (in hex) in Unicode.
If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
Otherwise, [0-9A-F]." nil nil)
-
(autoload 'ethio-java-to-fidel-buffer "ethio-util" "\
Convert the Java escape sequences into corresponding Ethiopic characters." nil nil)
-
(autoload 'ethio-find-file "ethio-util" "\
Transliterate file content into Ethiopic depending on filename suffix." nil nil)
-
(autoload 'ethio-write-file "ethio-util" "\
Transliterate Ethiopic characters in ASCII depending on the file extension." nil nil)
-
(autoload 'ethio-insert-ethio-space "ethio-util" "\
Insert the Ethiopic word delimiter (the colon-like character).
With ARG, insert that many delimiters.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'ethio-composition-function "ethio-util" "\
-\(fn POS TO FONT-OBJECT STRING DIRECTION)" nil nil)
-
+(fn POS TO FONT-OBJECT STRING DIRECTION)" nil nil)
(register-definition-prefixes "ethio-util" '("ethio-" "exit-ethiopic-environment"))
-;;;***
-;;;### (autoloads nil "eudc" "net/eudc.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/ethiopic.el
+
+(register-definition-prefixes "quail/ethiopic" '("ethio-select-a-translation"))
+
+
;;; Generated autoloads from net/eudc.el
(autoload 'eudc-set-server "eudc" "\
@@ -11795,20 +10749,25 @@ Set the directory server to SERVER using PROTOCOL.
Unless NO-SAVE is non-nil, the server is saved as the default
server for future sessions.
-\(fn SERVER PROTOCOL &optional NO-SAVE)" t nil)
-
+(fn SERVER PROTOCOL &optional NO-SAVE)" t nil)
(autoload 'eudc-get-email "eudc" "\
Get the email field of NAME from the directory server.
If ERROR is non-nil, report an error if there is none.
-\(fn NAME &optional ERROR)" t nil)
-
+(fn NAME &optional ERROR)" t nil)
(autoload 'eudc-get-phone "eudc" "\
Get the phone field of NAME from the directory server.
If ERROR is non-nil, report an error if there is none.
-\(fn NAME &optional ERROR)" t nil)
+(fn NAME &optional ERROR)" t nil)
+(autoload 'eudc-expand-try-all "eudc" "\
+Wrap `eudc-expand-inline' with a prefix argument.
+If TRY-ALL-SERVERS -- the prefix argument when called
+interactively -- is non-nil, collect results from all servers.
+If TRY-ALL-SERVERS is nil, do not try subsequent servers after
+one server returns any match.
+(fn &optional TRY-ALL-SERVERS)" t nil)
(autoload 'eudc-expand-inline "eudc" "\
Query the directory server, and expand the query string before point.
The query string consists of the buffer substring from the point back to
@@ -11817,143 +10776,142 @@ The variable `eudc-inline-query-format' controls how to associate the
individual inline query words with directory attribute names.
After querying the server for the given string, the expansion specified by
`eudc-inline-expansion-format' is inserted in the buffer at point.
-If REPLACE is non-nil, then this expansion replaces the name in the buffer.
-`eudc-expansion-overwrites-query' being non-nil inverts the meaning of REPLACE.
+If SAVE-QUERY-AS-KILL is non-nil, then save the pre-expansion
+text to the kill ring. `eudc-expansion-save-query-as-kill' being
+non-nil inverts the meaning of SAVE-QUERY-AS-KILL.
Multiple servers can be tried with the same query until one finds a match,
-see `eudc-inline-expansion-servers'.
+see `eudc-inline-expansion-servers'. If TRY-ALL-SERVERS is
+non-nil, collect results from all servers.
-\(fn &optional REPLACE)" t nil)
+(fn &optional SAVE-QUERY-AS-KILL TRY-ALL-SERVERS)" t nil)
+(autoload 'eudc-format-inline-expansion-result "eudc" "\
+Format a query result according to `eudc-inline-expansion-format'.
+(fn RES QUERY-ATTRS)" nil nil)
(autoload 'eudc-query-with-words "eudc" "\
Query the directory server, and return the matching responses.
The variable `eudc-inline-query-format' controls how to associate the
individual QUERY-WORDS with directory attribute names.
After querying the server for the given string, the expansion
specified by `eudc-inline-expansion-format' is applied to the
-matches before returning them.inserted in the buffer at point.
+matches before returning them.
Multiple servers can be tried with the same query until one finds a match,
-see `eudc-inline-expansion-servers'.
-
-\(fn QUERY-WORDS)" nil nil)
+see `eudc-inline-expansion-servers'. When TRY-ALL-SERVERS is non-nil,
+keep collecting results from subsequent servers after the first match.
+(fn QUERY-WORDS &optional TRY-ALL-SERVERS)" nil nil)
(autoload 'eudc-query-form "eudc" "\
Display a form to query the directory server.
If given a non-nil argument GET-FIELDS-FROM-SERVER, the function first
queries the server for the existing fields and displays a corresponding form.
-\(fn &optional GET-FIELDS-FROM-SERVER)" t nil)
-
+(fn &optional GET-FIELDS-FROM-SERVER)" t nil)
(autoload 'eudc-load-eudc "eudc" "\
Load the Emacs Unified Directory Client.
This does nothing except loading eudc by autoload side-effect." t nil)
-
(defvar eudc-tools-menu (let ((map (make-sparse-keymap "Directory Servers"))) (define-key map [phone] `(menu-item ,(purecopy "Get Phone") eudc-get-phone :help ,(purecopy "Get the phone field of name from the directory server"))) (define-key map [email] `(menu-item ,(purecopy "Get Email") eudc-get-email :help ,(purecopy "Get the email field of NAME from the directory server"))) (define-key map [separator-eudc-email] menu-bar-separator) (define-key map [expand-inline] `(menu-item ,(purecopy "Expand Inline Query") eudc-expand-inline :help ,(purecopy "Query the directory server, and expand the query string before point"))) (define-key map [query] `(menu-item ,(purecopy "Query with Form") eudc-query-form :help ,(purecopy "Display a form to query the directory server"))) (define-key map [separator-eudc-query] menu-bar-separator) (define-key map [new] `(menu-item ,(purecopy "New Server") eudc-set-server :help ,(purecopy "Set the directory server to SERVER using PROTOCOL"))) (define-key map [load] `(menu-item ,(purecopy "Load Hotlist of Servers") eudc-load-eudc :help ,(purecopy "Load the Emacs Unified Directory Client"))) map))
-
(fset 'eudc-tools-menu (symbol-value 'eudc-tools-menu))
-
(register-definition-prefixes "eudc" '("eudc-"))
-;;;***
-;;;### (autoloads nil "eudc-bob" "net/eudc-bob.el" (0 0 0 0))
;;; Generated autoloads from net/eudc-bob.el
(autoload 'eudc-display-generic-binary "eudc-bob" "\
Display a button for unidentified binary DATA.
-\(fn DATA)" nil nil)
-
+(fn DATA)" nil nil)
(autoload 'eudc-display-url "eudc-bob" "\
Display URL and make it clickable.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'eudc-display-mail "eudc-bob" "\
Display e-mail address and make it clickable.
-\(fn MAIL)" nil nil)
-
+(fn MAIL)" nil nil)
(autoload 'eudc-display-sound "eudc-bob" "\
Display a button to play the sound DATA.
-\(fn DATA)" nil nil)
-
+(fn DATA)" nil nil)
(autoload 'eudc-display-jpeg-inline "eudc-bob" "\
Display the JPEG DATA inline at point if possible.
-\(fn DATA)" nil nil)
-
+(fn DATA)" nil nil)
(autoload 'eudc-display-jpeg-as-button "eudc-bob" "\
Display a button for the JPEG DATA.
-\(fn DATA)" nil nil)
-
+(fn DATA)" nil nil)
(register-definition-prefixes "eudc-bob" '("eudc-bob-"))
-;;;***
-;;;### (autoloads nil "eudc-export" "net/eudc-export.el" (0 0 0 0))
+;;; Generated autoloads from net/eudc-capf.el
+
+(autoload 'eudc-capf-complete "eudc-capf" "\
+Email address completion function for `completion-at-point-functions'.
+
+This function checks whether the current major mode is one of the
+modes listed in `eudc-capf-modes', and whether point is on a line
+with a message header listing email recipients, that is, a line
+whose beginning matches `message-email-recipient-header-regexp',
+and, if the check succeeds, searches for records matching the
+words before point.
+
+The return value is either nil when no match is found, or a
+completion table as required for functions listed in
+`completion-at-point-functions'." nil nil)
+(autoload 'eudc-capf-message-expand-name "eudc-capf" "\
+Email address completion function for `message-completion-alist'.
+
+When this function is added to `message-completion-alist',
+replacing any existing entry for `message-expand-name' there,
+with an appropriate regular expression such as for example
+`message-email-recipient-header-regexp', then EUDC will be
+queried for email addresses, and the results delivered to
+`completion-at-point'." nil nil)
+(register-definition-prefixes "eudc-capf" '("eudc-capf-modes"))
+
+
;;; Generated autoloads from net/eudc-export.el
(autoload 'eudc-insert-record-at-point-into-bbdb "eudc-export" "\
Insert record at point into the BBDB database.
This function can only be called from a directory query result buffer." t nil)
-
(autoload 'eudc-try-bbdb-insert "eudc-export" "\
Call `eudc-insert-record-at-point-into-bbdb' if on a record." t nil)
-
(register-definition-prefixes "eudc-export" '("eudc-"))
-;;;***
-;;;### (autoloads nil "eudc-hotlist" "net/eudc-hotlist.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/eudc-hotlist.el
(autoload 'eudc-edit-hotlist "eudc-hotlist" "\
Edit the hotlist of directory servers in a specialized buffer." t nil)
-
(register-definition-prefixes "eudc-hotlist" '("eudc-hotlist-"))
-;;;***
-;;;### (autoloads nil "eudc-vars" "net/eudc-vars.el" (0 0 0 0))
;;; Generated autoloads from net/eudc-vars.el
(register-definition-prefixes "eudc-vars" '("eudc-"))
-;;;***
-;;;### (autoloads nil "eudcb-bbdb" "net/eudcb-bbdb.el" (0 0 0 0))
;;; Generated autoloads from net/eudcb-bbdb.el
(register-definition-prefixes "eudcb-bbdb" '("eudc-bbdb-"))
-;;;***
-;;;### (autoloads nil "eudcb-ldap" "net/eudcb-ldap.el" (0 0 0 0))
;;; Generated autoloads from net/eudcb-ldap.el
(register-definition-prefixes "eudcb-ldap" '("eudc-"))
-;;;***
-;;;### (autoloads nil "eudcb-mab" "net/eudcb-mab.el" (0 0 0 0))
;;; Generated autoloads from net/eudcb-mab.el
(register-definition-prefixes "eudcb-mab" '("eudc-"))
-;;;***
-;;;### (autoloads nil "eudcb-macos-contacts" "net/eudcb-macos-contacts.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from net/eudcb-macos-contacts.el
(register-definition-prefixes "eudcb-macos-contacts" '("eudc-macos-contacts-"))
-;;;***
-;;;### (autoloads nil "ewoc" "emacs-lisp/ewoc.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/ewoc.el
(autoload 'ewoc-create "ewoc" "\
@@ -11975,13 +10933,10 @@ Normally, a newline is automatically inserted after the header,
the footer and every node's printed representation. Optional
fourth arg NOSEP non-nil inhibits this.
-\(fn PRETTY-PRINTER &optional HEADER FOOTER NOSEP)" nil nil)
-
+(fn PRETTY-PRINTER &optional HEADER FOOTER NOSEP)" nil nil)
(register-definition-prefixes "ewoc" '("ewoc-"))
-;;;***
-;;;### (autoloads nil "eww" "net/eww.el" (0 0 0 0))
;;; Generated autoloads from net/eww.el
(defvar eww-suggest-uris '(eww-links-at-point thing-at-point-url-at-point eww-current-url) "\
@@ -11989,9 +10944,7 @@ List of functions called to form the list of default URIs for `eww'.
Each of the elements is a function returning either a string or a list
of strings. The results will be joined into a single list with
duplicate entries (if any) removed.")
-
(custom-autoload 'eww-suggest-uris "eww" t)
-
(autoload 'eww-browse "eww" "\
Function to be run to parse command line URLs.
This is meant to be used for MIME handlers or command line use.
@@ -12005,7 +10958,6 @@ This can also be used on the command line directly:
emacs -f eww-browse https://gnu.org
will start Emacs and browse the GNU web site." t nil)
-
(autoload 'eww "eww" "\
Fetch URL and render the page.
If the input doesn't look like an URL or a domain name, the
@@ -12018,28 +10970,24 @@ If BUFFER, the data to be rendered is in that buffer. In that
case, this function doesn't actually fetch URL. BUFFER will be
killed after rendering.
-\(fn URL &optional NEW-BUFFER BUFFER)" t nil)
+(fn URL &optional NEW-BUFFER BUFFER)" t nil)
(defalias 'browse-web 'eww)
-
(autoload 'eww-open-file "eww" "\
Render FILE using EWW.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'eww-search-words "eww" "\
Search the web for the text in the region.
If region is active (and not whitespace), search the web for
the text between region beginning and end. Else, prompt the
user for a search string. See the variable `eww-search-prefix'
for the search engine used." t nil)
-
(autoload 'eww-mode "eww" "\
Mode for browsing the web.
\\{eww-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'eww-browse-url "eww" "\
Ask the EWW browser to load URL.
@@ -12055,38 +11003,30 @@ in the tab-bar on an existing frame. See more options in
Non-interactively, this uses the optional second argument NEW-WINDOW
instead of `browse-url-new-window-flag'.
-\(fn URL &optional NEW-WINDOW)" nil nil)
-
+(fn URL &optional NEW-WINDOW)" nil nil)
(autoload 'eww-list-bookmarks "eww" "\
Display the bookmarks." t nil)
-
(autoload 'eww-bookmark-jump "eww" "\
Default bookmark handler for EWW buffers.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "eww" '("erc--download-directory" "eww-"))
-;;;***
-;;;### (autoloads nil "executable" "progmodes/executable.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/executable.el
(autoload 'executable-command-find-posix-p "executable" "\
Check if PROGRAM handles arguments Posix-style.
If PROGRAM is non-nil, use that instead of \"find\".
-\(fn &optional PROGRAM)" nil nil)
-
+(fn &optional PROGRAM)" nil nil)
(autoload 'executable-interpret "executable" "\
Run script with user-specified args, and collect output in a buffer.
While script runs asynchronously, you can use the \\[next-error]
command to find the next error. The buffer is also in `comint-mode' and
`compilation-shell-minor-mode', so that you can answer any prompts.
-\(fn COMMAND)" t nil)
-
+(fn COMMAND)" t nil)
(autoload 'executable-set-magic "executable" "\
Set this buffer's interpreter to INTERPRETER with optional ARGUMENT.
The variables `executable-magicless-file-regexp', `executable-prefix-env',
@@ -12094,25 +11034,19 @@ The variables `executable-magicless-file-regexp', `executable-prefix-env',
when and how magic numbers are inserted or replaced and scripts made
executable.
-\(fn INTERPRETER &optional ARGUMENT NO-QUERY-FLAG INSERT-FLAG)" t nil)
-
+(fn INTERPRETER &optional ARGUMENT NO-QUERY-FLAG INSERT-FLAG)" t nil)
(autoload 'executable-make-buffer-file-executable-if-script-p "executable" "\
Make file executable according to umask if not already executable.
If file already has any execute bits set at all, do not change existing
file modes." nil nil)
-
(register-definition-prefixes "executable" '("executable-"))
-;;;***
-;;;### (autoloads nil "exif" "image/exif.el" (0 0 0 0))
;;; Generated autoloads from image/exif.el
(register-definition-prefixes "exif" '("exif-"))
-;;;***
-;;;### (autoloads nil "expand" "expand.el" (0 0 0 0))
;;; Generated autoloads from expand.el
(autoload 'expand-add-abbrevs "expand" "\
@@ -12137,34 +11071,36 @@ cyclically with the functions `expand-jump-to-previous-slot' and
If ARG is omitted, point is placed at the end of the expanded text.
-\(fn TABLE ABBREVS)" nil nil)
-
+(fn TABLE ABBREVS)" nil nil)
(autoload 'expand-abbrev-hook "expand" "\
Abbrev hook used to do the expansion job of expand abbrevs.
See `expand-add-abbrevs'. Value is non-nil if expansion was done." nil nil)
-
(autoload 'expand-jump-to-previous-slot "expand" "\
Move the cursor to the previous slot in the last abbrev expansion.
This is used only in conjunction with `expand-add-abbrevs'." t nil)
-
(autoload 'expand-jump-to-next-slot "expand" "\
Move the cursor to the next slot in the last abbrev expansion.
This is used only in conjunction with `expand-add-abbrevs'." t nil)
(define-key abbrev-map "p" 'expand-jump-to-previous-slot)
(define-key abbrev-map "n" 'expand-jump-to-next-slot)
-
(register-definition-prefixes "expand" '("expand-"))
-;;;***
-;;;### (autoloads nil "ezimage" "ezimage.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/expandproto.el
+
+(register-definition-prefixes "srecode/expandproto" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/srecode/extract.el
+
+(register-definition-prefixes "srecode/extract" '("srecode-extract"))
+
+
;;; Generated autoloads from ezimage.el
(register-definition-prefixes "ezimage" '("defezimage" "ezimage-"))
-;;;***
-;;;### (autoloads nil "f90" "progmodes/f90.el" (0 0 0 0))
;;; Generated autoloads from progmodes/f90.el
(autoload 'f90-mode "f90" "\
@@ -12227,13 +11163,10 @@ Variables controlling indentation style and extra features:
Turning on F90 mode calls the value of the variable `f90-mode-hook'
with no args, if that value is non-nil.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "f90" '("f90-"))
-;;;***
-;;;### (autoloads nil "face-remap" "face-remap.el" (0 0 0 0))
;;; Generated autoloads from face-remap.el
(autoload 'face-remap-add-relative "face-remap" "\
@@ -12258,15 +11191,13 @@ attributes.
The base (lowest priority) remapping may be set to something
other than the normal definition of FACE via `face-remap-set-base'.
-\(fn FACE &rest SPECS)" nil nil)
-
+(fn FACE &rest SPECS)" nil nil)
(autoload 'face-remap-reset-base "face-remap" "\
Set the base remapping of FACE to the normal definition of FACE.
This causes the remappings specified by `face-remap-add-relative'
to apply on top of the normal definition of FACE.
-\(fn FACE)" nil nil)
-
+(fn FACE)" nil nil)
(autoload 'face-remap-set-base "face-remap" "\
Set the base remapping of FACE in the current buffer to SPECS.
This causes the remappings specified by `face-remap-add-relative'
@@ -12281,8 +11212,7 @@ to use the normal definition of FACE as the base remapping; note that
this is different from SPECS containing a single value nil, which means
not to inherit from the global definition of FACE at all.
-\(fn FACE &rest SPECS)" nil nil)
-
+(fn FACE &rest SPECS)" nil nil)
(autoload 'text-scale-set "face-remap" "\
Set the scale factor of the default face in the current buffer to LEVEL.
If LEVEL is non-zero, `text-scale-mode' is enabled, otherwise it is disabled.
@@ -12292,10 +11222,9 @@ Each step scales the height of the default face by the variable
`text-scale-mode-step' (a negative number decreases the height by
the same amount).
-\(fn LEVEL)" t nil)
-
+(fn LEVEL)" t nil)
(autoload 'text-scale-increase "face-remap" "\
-Increase the height of the default face in the current buffer by INC steps.
+Increase the font size of the default face in current buffer by INC steps.
If the new height is other than the default, `text-scale-mode' is enabled.
Each step scales the height of the default face by the variable
@@ -12303,33 +11232,30 @@ Each step scales the height of the default face by the variable
height by the same amount). As a special case, an argument of 0
will remove any scaling currently active.
-\(fn INC)" t nil)
-
+(fn INC)" t nil)
(autoload 'text-scale-decrease "face-remap" "\
-Decrease the height of the default face in the current buffer by DEC steps.
+Decrease the font size of the default face in the current buffer by DEC steps.
See `text-scale-increase' for more details.
-\(fn DEC)" t nil)
+(fn DEC)" t nil)
(define-key ctl-x-map [(control ?+)] 'text-scale-adjust)
(define-key ctl-x-map [(control ?-)] 'text-scale-adjust)
(define-key ctl-x-map [(control ?=)] 'text-scale-adjust)
(define-key ctl-x-map [(control ?0)] 'text-scale-adjust)
-
(autoload 'text-scale-adjust "face-remap" "\
-Adjust the height of the default face by INC.
-
+Adjust the font size in the current buffer by INC steps.
INC may be passed as a numeric prefix argument.
The actual adjustment made depends on the final component of the
keybinding used to invoke the command, with all modifiers removed:
- +, = Increase the height of the default face by one step
- - Decrease the height of the default face by one step
- 0 Reset the height of the default face to the global default
+ \\`+', \\`=' Increase font size in current buffer by one step
+ \\`-' Decrease font size in current buffer by one step
+ \\`0' Reset the font size to the global default
After adjusting, continue to read input events and further adjust
-the face height as long as the input event read
-\(with all modifiers removed) is one of the above characters.
+the font size as long as the input event read
+(with all modifiers removed) is one of the above characters.
Each step scales the height of the default face by the variable
`text-scale-mode-step' (a negative number of steps decreases the
@@ -12342,36 +11268,69 @@ even when it is bound in a non-top-level keymap. For binding in
a top-level keymap, `text-scale-increase' or
`text-scale-decrease' may be more appropriate.
-\(fn INC)" t nil)
- (define-key global-map [pinch] 'text-scale-pinch)
+Most faces are affected by these font size changes, but not faces
+that have an explicit `:height' setting. The two exceptions to
+this are the `default' and `header-line' faces: they will both be
+scaled even if they have an explicit `:height' setting.
+
+See also the related command `global-text-scale-adjust'.
+(fn INC)" t nil)
+ (define-key global-map [pinch] 'text-scale-pinch)
(autoload 'text-scale-pinch "face-remap" "\
Adjust the height of the default face by the scale in the pinch event EVENT.
-\(fn EVENT)" t nil)
+(fn EVENT)" t nil)
+ (define-key ctl-x-map [(control meta ?+)] 'global-text-scale-adjust)
+ (define-key ctl-x-map [(control meta ?=)] 'global-text-scale-adjust)
+ (define-key ctl-x-map [(control meta ?-)] 'global-text-scale-adjust)
+ (define-key ctl-x-map [(control meta ?0)] 'global-text-scale-adjust)
+(autoload 'global-text-scale-adjust "face-remap" "\
+Globally adjust the font size by INCREMENT.
+
+Interactively, INCREMENT may be passed as a numeric prefix argument.
+The adjustment made depends on the final component of the key binding
+used to invoke the command, with all modifiers removed:
+
+ \\`+', \\`=' Globally increase the height of the default face
+ \\`-' Globally decrease the height of the default face
+ \\`0' Globally reset the height of the default face
+
+After adjusting, further adjust the font size as long as the key,
+with all modifiers removed, is one of the above characters.
+
+Buffer-local face adjustements have higher priority than global
+face adjustments.
+
+The variable `global-text-scale-adjust-resizes-frames' controls
+whether the frames are resized to keep the same number of lines
+and characters per line when the font size is adjusted.
+
+See also the related command `text-scale-adjust'.
+
+(fn INCREMENT)" t nil)
(autoload 'buffer-face-mode "face-remap" "\
Minor mode for a buffer-specific default face.
+When enabled, the face specified by the variable
+`buffer-face-mode-face' is used to display the buffer text.
+
This is a minor mode. If called interactively, toggle the
-`Buffer-Face mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+`Buffer-Face mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `buffer-face-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When enabled, the face specified by the variable
-`buffer-face-mode-face' is used to display the buffer text.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'buffer-face-set "face-remap" "\
Enable `buffer-face-mode', using face specs SPECS.
Each argument in SPECS should be a face, i.e. either a face name
@@ -12383,8 +11342,7 @@ one face is listed, that specifies an aggregate face, like in a
This function makes the variable `buffer-face-mode-face' buffer
local, and sets it to FACE.
-\(fn &rest SPECS)" t nil)
-
+(fn &rest SPECS)" t nil)
(autoload 'buffer-face-toggle "face-remap" "\
Toggle `buffer-face-mode', using face specs SPECS.
Each argument in SPECS should be a face, i.e. either a face name
@@ -12400,25 +11358,20 @@ face, then is left enabled, but the face changed to reflect SPECS.
This function will make the variable `buffer-face-mode-face'
buffer local, and set it to SPECS.
-\(fn &rest SPECS)" t nil)
-
+(fn &rest SPECS)" t nil)
(autoload 'variable-pitch-mode "face-remap" "\
Variable-pitch default-face mode.
An interface to `buffer-face-mode' which uses the `variable-pitch' face.
Besides the choice of face, it is the same as `buffer-face-mode'.
-\(fn &optional ARG)" t nil)
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "face-remap" '("buffer-face-mode-" "face-" "global-text-scale-adjust-" "internal-lisp-face-attributes" "text-scale-"))
-(register-definition-prefixes "face-remap" '("buffer-face-mode-" "face-" "internal-lisp-face-attributes" "text-scale-"))
-
-;;;***
-;;;### (autoloads nil "facemenu" "facemenu.el" (0 0 0 0))
;;; Generated autoloads from facemenu.el
- (autoload 'facemenu-menu "facemenu" nil nil 'keymap)
+ (autoload 'facemenu-menu "facemenu" nil nil 'keymap)
(define-key global-map [C-down-mouse-2] 'facemenu-menu)
-
(autoload 'list-colors-display "facemenu" "\
Display names of defined colors, and show what they look like.
If the optional argument LIST is non-nil, it should be a list of
@@ -12434,19 +11387,15 @@ If the optional argument CALLBACK is non-nil, it should be a
function to call each time the user types RET or clicks on a
color. The function should accept a single argument, the color name.
-\(fn &optional LIST BUFFER-NAME CALLBACK)" t nil)
-
+(fn &optional LIST BUFFER-NAME CALLBACK)" t nil)
(register-definition-prefixes "facemenu" '("facemenu-" "list-colors-"))
-;;;***
-;;;### (autoloads nil "faceup" "emacs-lisp/faceup.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/faceup.el
-(push (purecopy '(faceup 0 0 6)) package--builtin-versions)
+(push (purecopy '(faceup 0 0 6)) package--builtin-versions)
(autoload 'faceup-view-buffer "faceup" "\
Display the faceup representation of the current buffer." t nil)
-
(autoload 'faceup-write-file "faceup" "\
Save the faceup representation of the current buffer to the file FILE-NAME.
@@ -12457,57 +11406,52 @@ If optional second arg CONFIRM is non-nil, this function
asks for confirmation before overwriting an existing file.
Interactively, confirmation is required unless you supply a prefix argument.
-\(fn &optional FILE-NAME CONFIRM)" t nil)
-
+(fn &optional FILE-NAME CONFIRM)" t nil)
(autoload 'faceup-render-view-buffer "faceup" "\
Convert BUFFER containing Faceup markup to a new buffer and display it.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'faceup-clean-buffer "faceup" "\
Remove faceup markup from buffer." t nil)
-
(autoload 'faceup-defexplainer "faceup" "\
Define an Ert explainer function for FUNCTION.
FUNCTION must return an explanation when the test fails and
`faceup-test-explain' is set.
-\(fn FUNCTION)" nil t)
-
+(fn FUNCTION)" nil t)
(register-definition-prefixes "faceup" '("faceup-"))
-;;;***
-;;;### (autoloads nil "feedmail" "mail/feedmail.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/analyze/fcn.el
+
+(register-definition-prefixes "semantic/analyze/fcn" '("semantic-analyze-"))
+
+
;;; Generated autoloads from mail/feedmail.el
-(push (purecopy '(feedmail 11)) package--builtin-versions)
+(push (purecopy '(feedmail 11)) package--builtin-versions)
(autoload 'feedmail-send-it "feedmail" "\
Send the current mail buffer using the Feedmail package.
This is a suitable value for `send-mail-function'. It can be used
with various lower-level mechanisms to provide features such as queueing." nil nil)
-
(autoload 'feedmail-run-the-queue-no-prompts "feedmail" "\
Like `feedmail-run-the-queue', but suppress confirmation prompts.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'feedmail-run-the-queue-global-prompt "feedmail" "\
Like `feedmail-run-the-queue', but with a global confirmation prompt.
This is generally most useful if run non-interactively, since you can
bail out with an appropriate answer to the global confirmation prompt.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'feedmail-run-the-queue "feedmail" "\
Visit each message in the feedmail queue directory and send it out.
Return value is a list of three things: number of messages sent, number of
messages skipped, and number of non-message things in the queue (commonly
backup file names and the like).
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'feedmail-queue-reminder "feedmail" "\
Perform some kind of reminder activity about queued and draft messages.
Called with an optional symbol argument which says what kind of event
@@ -12527,20 +11471,15 @@ expected to perform the reminder activity. You can supply your own reminder
functions by redefining `feedmail-queue-reminder-alist'. If you don't want any
reminders, you can set `feedmail-queue-reminder-alist' to nil.
-\(fn &optional WHAT-EVENT)" t nil)
-
+(fn &optional WHAT-EVENT)" t nil)
(register-definition-prefixes "feedmail" '("feedmail-"))
-;;;***
-;;;### (autoloads nil "ffap" "ffap.el" (0 0 0 0))
;;; Generated autoloads from ffap.el
(defvar ffap-file-finder 'find-file "\
The command called by `find-file-at-point' to find a file.")
-
(custom-autoload 'ffap-file-finder "ffap" t)
-
(autoload 'ffap-next "ffap" "\
Search buffer for next file or URL, and run ffap.
Optional argument BACK says to search backwards.
@@ -12549,8 +11488,7 @@ Interactively: use a single prefix \\[universal-argument] to search backwards,
double prefix to wrap forward, triple to wrap backwards.
Actual search is done by the function `ffap-next-guess'.
-\(fn &optional BACK WRAP)" t nil)
-
+(fn &optional BACK WRAP)" t nil)
(autoload 'find-file-at-point "ffap" "\
Find FILENAME, guessing a default from text around point.
If `ffap-url-regexp' is not nil, the FILENAME may also be an URL.
@@ -12561,10 +11499,8 @@ See also the variables `ffap-dired-wildcards', `ffap-newfile-prompt',
`ffap-file-name-with-spaces', and the functions `ffap-file-at-point'
and `ffap-url-at-point'.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(defalias 'ffap 'find-file-at-point)
-
(autoload 'ffap-menu "ffap" "\
Put up a menu of files and URLs mentioned in this buffer.
Then set mark, jump to choice, and try to fetch it. The menu is
@@ -12572,8 +11508,7 @@ cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'.
The optional RESCAN argument (a prefix, interactively) forces
a rebuild. Searches with `ffap-menu-regexp'.
-\(fn &optional RESCAN)" t nil)
-
+(fn &optional RESCAN)" t nil)
(autoload 'ffap-at-mouse "ffap" "\
Find file or URL guessed from text around mouse click.
Interactively, calls `ffap-at-mouse-fallback' if no guess is found.
@@ -12582,26 +11517,25 @@ Return value:
* if the fallback is called, return whatever it returns
* otherwise, nil
-\(fn E)" t nil)
-
+(fn E)" t nil)
(autoload 'dired-at-point "ffap" "\
Start Dired, defaulting to file at point. See `ffap'.
If `dired-at-point-require-prefix' is set, the prefix meaning is reversed.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'ffap-guess-file-name-at-point "ffap" "\
Try to get a file name at point.
This hook is intended to be put in `file-name-at-point-functions'." nil nil)
-
(autoload 'ffap-bindings "ffap" "\
Evaluate the forms in variable `ffap-bindings'." t nil)
-
(register-definition-prefixes "ffap" '("dired-at-point-" "ffap-" "find-file-literally-at-point"))
-;;;***
-;;;### (autoloads nil "filecache" "filecache.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/fields.el
+
+(register-definition-prefixes "srecode/fields" '("srecode-"))
+
+
;;; Generated autoloads from filecache.el
(autoload 'file-cache-add-directory "filecache" "\
@@ -12609,8 +11543,7 @@ Add all files in DIRECTORY to the file cache.
If called from Lisp with a non-nil REGEXP argument is non-nil,
only add files whose names match REGEXP.
-\(fn DIRECTORY &optional REGEXP)" t nil)
-
+(fn DIRECTORY &optional REGEXP)" t nil)
(autoload 'file-cache-add-directory-list "filecache" "\
Add DIRECTORIES (a list of directory names) to the file cache.
If called interactively, read the directory names one by one.
@@ -12618,25 +11551,21 @@ If the optional REGEXP argument is non-nil, only files which match it
will be added to the cache. Note that the REGEXP is applied to the
files in each directory, not to the directory list itself.
-\(fn DIRECTORIES &optional REGEXP)" t nil)
-
+(fn DIRECTORIES &optional REGEXP)" t nil)
(autoload 'file-cache-add-file "filecache" "\
Add FILE to the file cache.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'file-cache-add-directory-using-find "filecache" "\
Use the `find' command to add files to the file cache.
Find is run in DIRECTORY.
-\(fn DIRECTORY)" t nil)
-
+(fn DIRECTORY)" t nil)
(autoload 'file-cache-add-directory-using-locate "filecache" "\
Use the `locate' command to add files to the file cache.
STRING is passed as an argument to the locate command.
-\(fn STRING)" t nil)
-
+(fn STRING)" t nil)
(autoload 'file-cache-add-directory-recursively "filecache" "\
Add DIR and any subdirectories to the file-cache.
This function does not use any external programs.
@@ -12644,23 +11573,19 @@ If the optional REGEXP argument is non-nil, only files which match it
will be added to the cache. Note that the REGEXP is applied to the
files in each directory, not to the directory list itself.
-\(fn DIR &optional REGEXP)" t nil)
-
+(fn DIR &optional REGEXP)" t nil)
(autoload 'file-cache-minibuffer-complete "filecache" "\
Complete a filename in the minibuffer using a preloaded cache.
Filecache does two kinds of substitution: it completes on names in
the cache, and, once it has found a unique name, it cycles through
the directories that the name is available in. With a prefix argument,
the name is considered already unique; only the second substitution
-\(directories) is done.
-
-\(fn ARG)" t nil)
+(directories) is done.
+(fn ARG)" t nil)
(register-definition-prefixes "filecache" '("file-cache-"))
-;;;***
-;;;### (autoloads nil "fileloop" "fileloop.el" (0 0 0 0))
;;; Generated autoloads from fileloop.el
(autoload 'fileloop-initialize "fileloop" "\
@@ -12674,13 +11599,11 @@ to perform the operation on the current file buffer and when done
should return non-nil to mean that we should immediately continue
operating on the next file and nil otherwise.
-\(fn FILES SCAN-FUNCTION OPERATE-FUNCTION)" nil nil)
-
+(fn FILES SCAN-FUNCTION OPERATE-FUNCTION)" nil nil)
(autoload 'fileloop-initialize-search "fileloop" "\
-\(fn REGEXP FILES CASE-FOLD)" nil nil)
-
+(fn REGEXP FILES CASE-FOLD)" nil nil)
(autoload 'fileloop-initialize-replace "fileloop" "\
Initialize a new round of query&replace on several files.
FROM is a regexp and TO is the replacement to use.
@@ -12694,13 +11617,10 @@ CASE-FOLD can be t, nil, or `default':
`case-fold-search' instead.
DELIMITED if non-nil means replace only word-delimited matches.
-\(fn FROM TO FILES CASE-FOLD &optional DELIMITED)" nil nil)
-
+(fn FROM TO FILES CASE-FOLD &optional DELIMITED)" nil nil)
(register-definition-prefixes "fileloop" '("fileloop-"))
-;;;***
-;;;### (autoloads nil "filenotify" "filenotify.el" (0 0 0 0))
;;; Generated autoloads from filenotify.el
(autoload 'file-notify-handle-event "filenotify" "\
@@ -12708,15 +11628,16 @@ Handle a file system monitoring event, coming from backends.
If OBJECT is a filewatch event, call its callback.
Otherwise, signal a `file-notify-error'.
-\(fn OBJECT)" t nil)
-
+(fn OBJECT)" t nil)
(function-put 'file-notify-handle-event 'completion-predicate #'ignore)
-
(register-definition-prefixes "filenotify" '("file-notify-"))
-;;;***
-;;;### (autoloads nil "files-x" "files-x.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/files.el
+
+(register-definition-prefixes "ede/files" '("ede-"))
+
+
;;; Generated autoloads from files-x.el
(autoload 'add-file-local-variable "files-x" "\
@@ -12730,13 +11651,11 @@ If there is no Local Variables list in the current file buffer
then this function adds the first line containing the string
`Local Variables:' and the last line containing the string `End:'.
-\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil)
-
+(fn VARIABLE VALUE &optional INTERACTIVE)" t nil)
(autoload 'delete-file-local-variable "files-x" "\
Delete all settings of file-local VARIABLE from the Local Variables list.
-\(fn VARIABLE &optional INTERACTIVE)" t nil)
-
+(fn VARIABLE &optional INTERACTIVE)" t nil)
(autoload 'add-file-local-variable-prop-line "files-x" "\
Add file-local VARIABLE with its VALUE to the -*- line.
@@ -12747,35 +11666,27 @@ the -*- line.
If there is no -*- line at the beginning of the current file buffer
then this function adds it.
-\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil)
-
+(fn VARIABLE VALUE &optional INTERACTIVE)" t nil)
(autoload 'delete-file-local-variable-prop-line "files-x" "\
Delete all settings of file-local VARIABLE from the -*- line.
-\(fn VARIABLE &optional INTERACTIVE)" t nil)
-
+(fn VARIABLE &optional INTERACTIVE)" t nil)
(autoload 'add-dir-local-variable "files-x" "\
Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el.
-\(fn MODE VARIABLE VALUE)" t nil)
-
+(fn MODE VARIABLE VALUE)" t nil)
(autoload 'delete-dir-local-variable "files-x" "\
Delete all MODE settings of file-local VARIABLE from .dir-locals.el.
-\(fn MODE VARIABLE)" t nil)
-
+(fn MODE VARIABLE)" t nil)
(autoload 'copy-file-locals-to-dir-locals "files-x" "\
Copy file-local variables to .dir-locals.el." t nil)
-
(autoload 'copy-dir-locals-to-file-locals "files-x" "\
Copy directory-local variables to the Local Variables list." t nil)
-
(autoload 'copy-dir-locals-to-file-locals-prop-line "files-x" "\
Copy directory-local variables to the -*- line." t nil)
-
(defvar enable-connection-local-variables t "\
Non-nil means enable use of connection-local variables.")
-
(autoload 'connection-local-set-profiles "files-x" "\
Add PROFILES for CRITERIA.
CRITERIA is a plist identifying a connection and the application
@@ -12788,8 +11699,7 @@ PROFILES are applied to the corresponding process buffer. The
variables for a connection profile are defined using
`connection-local-set-profile-variables'.
-\(fn CRITERIA &rest PROFILES)" nil nil)
-
+(fn CRITERIA &rest PROFILES)" nil nil)
(autoload 'connection-local-set-profile-variables "files-x" "\
Map the symbol PROFILE to a list of variable settings.
VARIABLES is a list that declares connection-local variables for
@@ -12803,51 +11713,66 @@ variables are set in the server's process buffer according to the
VARIABLES list of the connection profile. The list is processed
in order.
-\(fn PROFILE VARIABLES)" nil nil)
-
+(fn PROFILE VARIABLES)" nil nil)
(autoload 'hack-connection-local-variables-apply "files-x" "\
Apply connection-local variables identified by CRITERIA.
Other local variables, like file-local and dir-local variables,
will not be changed.
-\(fn CRITERIA)" nil nil)
-
+(fn CRITERIA)" nil nil)
(autoload 'with-connection-local-variables "files-x" "\
Apply connection-local variables according to `default-directory'.
Execute BODY, and unwind connection-local variables.
-\(fn &rest BODY)" nil t)
+(fn &rest BODY)" nil t)
+(autoload 'with-connection-local-variables-1 "files-x" "\
+Apply connection-local variables according to `default-directory'.
+Call BODY-FUN with no args, and then unwind connection-local variables.
+(fn BODY-FUN)" nil nil)
(autoload 'path-separator "files-x" "\
The connection-local value of `path-separator'." nil nil)
-
(autoload 'null-device "files-x" "\
The connection-local value of `null-device'." nil nil)
-
(register-definition-prefixes "files-x" '("connection-local-" "dir-locals-to-string" "hack-connection-local-variables" "modify-" "read-file-local-variable"))
-;;;***
-;;;### (autoloads nil "filesets" "filesets.el" (0 0 0 0))
;;; Generated autoloads from filesets.el
(autoload 'filesets-init "filesets" "\
Filesets initialization.
Set up hooks, load the cache file -- if existing -- and build the menu." nil nil)
-
(register-definition-prefixes "filesets" '("filesets-"))
-;;;***
-;;;### (autoloads nil "find-cmd" "find-cmd.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/symref/filter.el
+
+(register-definition-prefixes "semantic/symref/filter" '("semantic-symref-"))
+
+
+;;; Generated autoloads from cedet/srecode/filters.el
+
+(register-definition-prefixes "srecode/filters" '("srecode-comment-prefix"))
+
+
+;;; Generated autoloads from cedet/srecode/find.el
+
+(register-definition-prefixes "srecode/find" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/semantic/find.el
+
+(register-definition-prefixes "semantic/find" '("semantic-"))
+
+
;;; Generated autoloads from find-cmd.el
-(push (purecopy '(find-cmd 0 6)) package--builtin-versions)
+(push (purecopy '(find-cmd 0 6)) package--builtin-versions)
(autoload 'find-cmd "find-cmd" "\
Initiate the building of a find command.
For example:
-\(find-cmd \\='(prune (name \".svn\" \".git\" \".CVS\"))
+(find-cmd \\='(prune (name \".svn\" \".git\" \".CVS\"))
\\='(and (or (name \"*.pl\" \"*.pm\" \"*.t\")
(mtime \"+1\"))
(fstype \"nfs\" \"ufs\"))))
@@ -12855,13 +11780,10 @@ For example:
`default-directory' is used as the initial search path. The
result is a string that should be ready for the command line.
-\(fn &rest SUBFINDS)" nil nil)
-
+(fn &rest SUBFINDS)" nil nil)
(register-definition-prefixes "find-cmd" '("find-"))
-;;;***
-;;;### (autoloads nil "find-dired" "find-dired.el" (0 0 0 0))
;;; Generated autoloads from find-dired.el
(autoload 'find-dired "find-dired" "\
@@ -12876,8 +11798,20 @@ use in place of \"-ls\" as the final argument.
Collect output in the \"*Find*\" buffer. To kill the job before
it finishes, type \\[kill-find].
-\(fn DIR ARGS)" t nil)
+(fn DIR ARGS)" t nil)
+(autoload 'find-dired-with-command "find-dired" "\
+Run `find' and go into Dired mode on a buffer of the output.
+The user-supplied COMMAND is run after changing into DIR and should look like
+
+ find . GLOBALARGS \\( ARGS \\) -ls
+
+The car of the variable `find-ls-option' specifies what to
+use in place of \"-ls\" as the starting input.
+
+Collect output in the \"*Find*\" buffer. To kill the job before
+it finishes, type \\[kill-find].
+(fn DIR COMMAND)" t nil)
(autoload 'find-name-dired "find-dired" "\
Search DIR recursively for files matching the globbing PATTERN,
and run Dired on those files.
@@ -12888,8 +11822,7 @@ The default command run (after changing into DIR) is
See `find-name-arg' to customize the arguments.
-\(fn DIR PATTERN)" t nil)
-
+(fn DIR PATTERN)" t nil)
(autoload 'find-grep-dired "find-dired" "\
Find files in DIR that contain matches for REGEXP and start Dired on output.
The command run (after changing into DIR) is
@@ -12900,13 +11833,10 @@ The command run (after changing into DIR) is
where the first string in the value of the variable `find-ls-option'
specifies what to use in place of \"-ls\" as the final argument.
-\(fn DIR REGEXP)" t nil)
-
+(fn DIR REGEXP)" t nil)
(register-definition-prefixes "find-dired" '("find-" "kill-find" "lookfor-dired"))
-;;;***
-;;;### (autoloads nil "find-file" "find-file.el" (0 0 0 0))
;;; Generated autoloads from find-file.el
(defvar ff-special-constructs `((,(purecopy "^#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]") \, (lambda nil (match-string 2)))) "\
@@ -12916,19 +11846,15 @@ If REGEXP matches the current line (from the beginning of the line),
`ff-treat-as-special' calls function EXTRACT with no args.
If EXTRACT returns nil, keep trying. Otherwise, return the
filename that EXTRACT returned.")
-
(custom-autoload 'ff-special-constructs "find-file" t)
-
(autoload 'ff-get-other-file "find-file" "\
Find the header or source file corresponding to this file.
See also the documentation for `ff-find-other-file'.
If optional IN-OTHER-WINDOW is non-nil, find the file in another window.
-\(fn &optional IN-OTHER-WINDOW)" t nil)
-
+(fn &optional IN-OTHER-WINDOW)" t nil)
(defalias 'ff-find-related-file #'ff-find-other-file)
-
(autoload 'ff-find-other-file "find-file" "\
Find the header or source file corresponding to this file.
Being on a `#include' line pulls in that file.
@@ -12986,23 +11912,16 @@ Variables of interest include:
- `ff-file-created-hook'
List of functions to be called if the other file has been created.
-\(fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE EVENT)" t nil)
-
+(fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE EVENT)" t nil)
(define-obsolete-function-alias 'ff-mouse-find-other-file #'ff-find-other-file "28.1")
-
(define-obsolete-function-alias 'ff-mouse-find-other-file-other-window #'ff-find-other-file-other-window "28.1")
-
(autoload 'ff-find-other-file-other-window "find-file" "\
Visit the file you point at in another window.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(register-definition-prefixes "find-file" '("cc-" "ff-" "modula2-other-file-alist"))
-;;;***
-;;;### (autoloads nil "find-func" "emacs-lisp/find-func.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/find-func.el
(autoload 'find-library "find-func" "\
@@ -13013,29 +11932,28 @@ Interactively, prompt for LIBRARY using the one at or near point.
This function searches `find-library-source-path' if non-nil, and
`load-path' otherwise.
-\(fn LIBRARY)" t nil)
+See the `find-library-include-other-files' user option for
+customizing the candidate completions.
+(fn LIBRARY)" t nil)
(autoload 'read-library-name "find-func" "\
Read and return a library name, defaulting to the one near point.
A library name is the filename of an Emacs Lisp library located
in a directory under `load-path' (or `find-library-source-path',
if non-nil)." nil nil)
-
(autoload 'find-library-other-window "find-func" "\
Find the Emacs Lisp source of LIBRARY in another window.
See `find-library' for more details.
-\(fn LIBRARY)" t nil)
-
+(fn LIBRARY)" t nil)
(autoload 'find-library-other-frame "find-func" "\
Find the Emacs Lisp source of LIBRARY in another frame.
See `find-library' for more details.
-\(fn LIBRARY)" t nil)
-
+(fn LIBRARY)" t nil)
(autoload 'find-function-search-for-symbol "find-func" "\
Search for SYMBOL's definition of type TYPE in LIBRARY.
Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
@@ -13046,8 +11964,7 @@ Otherwise, TYPE specifies the kind of definition,
and it is interpreted via `find-function-regexp-alist'.
The search is done in the source for library LIBRARY.
-\(fn SYMBOL TYPE LIBRARY)" nil nil)
-
+(fn SYMBOL TYPE LIBRARY)" nil nil)
(autoload 'find-function-noselect "find-func" "\
Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
@@ -13060,8 +11977,7 @@ If FUNCTION is a built-in function, this function normally
attempts to find it in the Emacs C sources; however, if LISP-ONLY
is non-nil, signal an error instead.
-\(fn FUNCTION &optional LISP-ONLY)" nil nil)
-
+(fn FUNCTION &optional LISP-ONLY)" nil nil)
(autoload 'find-function "find-func" "\
Find the definition of the FUNCTION near point.
@@ -13072,22 +11988,19 @@ Set mark before moving, if the buffer already existed.
See also `find-function-recenter-line' and `find-function-after-hook'.
-\(fn FUNCTION)" t nil)
-
+(fn FUNCTION)" t nil)
(autoload 'find-function-other-window "find-func" "\
Find, in another window, the definition of FUNCTION near point.
See `find-function' for more details.
-\(fn FUNCTION)" t nil)
-
+(fn FUNCTION)" t nil)
(autoload 'find-function-other-frame "find-func" "\
Find, in another frame, the definition of FUNCTION near point.
See `find-function' for more details.
-\(fn FUNCTION)" t nil)
-
+(fn FUNCTION)" t nil)
(autoload 'find-variable-noselect "find-func" "\
Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
@@ -13095,8 +12008,7 @@ Finds the library containing the definition of VARIABLE in a buffer and
the point of the definition. The buffer is not selected.
If the variable's definition can't be found in the buffer, return (BUFFER).
-\(fn VARIABLE &optional FILE)" nil nil)
-
+(fn VARIABLE &optional FILE)" nil nil)
(autoload 'find-variable "find-func" "\
Find the definition of the VARIABLE at or before point.
@@ -13108,22 +12020,19 @@ Set mark before moving, if the buffer already existed.
See also `find-function-recenter-line' and `find-function-after-hook'.
-\(fn VARIABLE)" t nil)
-
+(fn VARIABLE)" t nil)
(autoload 'find-variable-other-window "find-func" "\
Find, in another window, the definition of VARIABLE near point.
See `find-variable' for more details.
-\(fn VARIABLE)" t nil)
-
+(fn VARIABLE)" t nil)
(autoload 'find-variable-other-frame "find-func" "\
Find, in another frame, the definition of VARIABLE near point.
See `find-variable' for more details.
-\(fn VARIABLE)" t nil)
-
+(fn VARIABLE)" t nil)
(autoload 'find-definition-noselect "find-func" "\
Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
If the definition can't be found in the buffer, return (BUFFER).
@@ -13131,8 +12040,7 @@ TYPE says what type of definition: nil for a function, `defvar' for a
variable, `defface' for a face. This function does not switch to the
buffer nor display it.
-\(fn SYMBOL TYPE &optional FILE)" nil nil)
-
+(fn SYMBOL TYPE &optional FILE)" nil nil)
(autoload 'find-face-definition "find-func" "\
Find the definition of FACE. FACE defaults to the name near point.
@@ -13144,81 +12052,62 @@ Set mark before moving, if the buffer already existed.
See also `find-function-recenter-line' and `find-function-after-hook'.
-\(fn FACE)" t nil)
-
+(fn FACE)" t nil)
(autoload 'find-function-on-key "find-func" "\
Find the function that KEY invokes. KEY is a string.
Set mark before moving, if the buffer already existed.
-\(fn KEY)" t nil)
-
+(fn KEY)" t nil)
(autoload 'find-function-on-key-other-window "find-func" "\
Find, in the other window, the function that KEY invokes.
See `find-function-on-key'.
-\(fn KEY)" t nil)
-
+(fn KEY)" t nil)
(autoload 'find-function-on-key-other-frame "find-func" "\
Find, in the other frame, the function that KEY invokes.
See `find-function-on-key'.
-\(fn KEY)" t nil)
-
+(fn KEY)" t nil)
(autoload 'find-function-at-point "find-func" "\
Find directly the function at point in the other window." t nil)
-
(autoload 'find-variable-at-point "find-func" "\
Find directly the variable at point in the other window." t nil)
-
(autoload 'find-function-setup-keys "find-func" "\
Define some key bindings for the `find-function' family of functions." nil nil)
+(register-definition-prefixes "find-func" '("find-" "read-library-name--find-files"))
-(register-definition-prefixes "find-func" '("find-"))
-
-;;;***
-;;;### (autoloads nil "find-lisp" "find-lisp.el" (0 0 0 0))
;;; Generated autoloads from find-lisp.el
(autoload 'find-lisp-find-dired "find-lisp" "\
Find files in DIR, matching REGEXP.
-\(fn DIR REGEXP)" t nil)
-
+(fn DIR REGEXP)" t nil)
(autoload 'find-lisp-find-dired-subdirectories "find-lisp" "\
Find all subdirectories of DIR.
-\(fn DIR)" t nil)
-
+(fn DIR)" t nil)
(autoload 'find-lisp-find-dired-filter "find-lisp" "\
Change the filter on a `find-lisp-find-dired' buffer to REGEXP.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(register-definition-prefixes "find-lisp" '("find-lisp-"))
-;;;***
-;;;### (autoloads nil "finder" "finder.el" (0 0 0 0))
;;; Generated autoloads from finder.el
(autoload 'finder-list-keywords "finder" "\
Display descriptions of the keywords in the Finder buffer." t nil)
-
(autoload 'finder-commentary "finder" "\
Display FILE's commentary section.
FILE should be in a form suitable for passing to `locate-library'.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'finder-by-keyword "finder" "\
Find packages matching a given keyword." t nil)
-
(register-definition-prefixes "finder" '("finder-" "generated-finder-keywords-file"))
-;;;***
-;;;### (autoloads nil "flow-ctrl" "flow-ctrl.el" (0 0 0 0))
;;; Generated autoloads from flow-ctrl.el
(autoload 'enable-flow-control "flow-ctrl" "\
@@ -13226,8 +12115,7 @@ Toggle flow control handling.
When handling is enabled, user can type C-s as C-\\, and C-q as C-^.
With arg, enable flow control mode if arg is positive, otherwise disable.
-\(fn &optional ARGUMENT)" t nil)
-
+(fn &optional ARGUMENT)" t nil)
(autoload 'enable-flow-control-on "flow-ctrl" "\
Enable flow control if using one of a specified set of terminal types.
Use `(enable-flow-control-on \"vt100\" \"h19\")' to enable flow control
@@ -13235,20 +12123,16 @@ on VT-100 and H19 terminals. When flow control is enabled,
you must type C-\\ to get the effect of a C-s, and type C-^
to get the effect of a C-q.
-\(fn &rest LOSING-TERMINAL-TYPES)" nil nil)
-
+(fn &rest LOSING-TERMINAL-TYPES)" nil nil)
(register-definition-prefixes "flow-ctrl" '("flow-control-c-"))
-;;;***
-;;;### (autoloads nil "flow-fill" "mail/flow-fill.el" (0 0 0 0))
;;; Generated autoloads from mail/flow-fill.el
(autoload 'fill-flowed-encode "flow-fill" "\
-\(fn &optional BUFFER)" nil nil)
-
+(fn &optional BUFFER)" nil nil)
(autoload 'fill-flowed "flow-fill" "\
Apply RFC2646 decoding to BUFFER.
If BUFFER is nil, default to the current buffer.
@@ -13256,16 +12140,13 @@ If BUFFER is nil, default to the current buffer.
If DELETE-SPACE, delete RFC2646 spaces padding at the end of
lines.
-\(fn &optional BUFFER DELETE-SPACE)" nil nil)
-
+(fn &optional BUFFER DELETE-SPACE)" nil nil)
(register-definition-prefixes "flow-fill" '("fill-flowed-"))
-;;;***
-;;;### (autoloads nil "flymake" "progmodes/flymake.el" (0 0 0 0))
;;; Generated autoloads from progmodes/flymake.el
-(push (purecopy '(flymake 1 2 1)) package--builtin-versions)
+(push (purecopy '(flymake 1 2 2)) package--builtin-versions)
(autoload 'flymake-log "flymake" "\
Log, at level LEVEL, the message MSG formatted with ARGS.
LEVEL is passed to `display-warning', which is used to display
@@ -13273,8 +12154,7 @@ the warning. If this form is included in a file,
the generated warning contains an indication of the file that
generated it.
-\(fn LEVEL MSG &rest ARGS)" nil t)
-
+(fn LEVEL MSG &rest ARGS)" nil t)
(autoload 'flymake-make-diagnostic "flymake" "\
Make a Flymake diagnostic for LOCUS's region from BEG to END.
LOCUS is a buffer object or a string designating a file name.
@@ -13296,8 +12176,7 @@ created diagnostic, overriding the default properties and any
properties listed in the `flymake-overlay-control' property of
the diagnostic's type symbol.
-\(fn LOCUS BEG END TYPE TEXT &optional DATA OVERLAY-PROPERTIES)" nil nil)
-
+(fn LOCUS BEG END TYPE TEXT &optional DATA OVERLAY-PROPERTIES)" nil nil)
(autoload 'flymake-diagnostics "flymake" "\
Get Flymake diagnostics in region determined by BEG and END.
@@ -13305,32 +12184,16 @@ If neither BEG or END is supplied, use whole accessible buffer,
otherwise if BEG is non-nil and END is nil, consider only
diagnostics at BEG.
-\(fn &optional BEG END)" nil nil)
-
+(fn &optional BEG END)" nil nil)
(autoload 'flymake-diag-region "flymake" "\
Compute BUFFER's region (BEG . END) corresponding to LINE and COL.
If COL is nil, return a region just for LINE. Return nil if the
region is invalid. This function saves match data.
-\(fn BUFFER LINE &optional COL)" nil nil)
-
+(fn BUFFER LINE &optional COL)" nil nil)
(autoload 'flymake-mode "flymake" "\
Toggle Flymake mode on or off.
-This is a minor mode. If called interactively, toggle the `Flymake
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `flymake-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Flymake is an Emacs minor mode for on-the-fly syntax checking.
Flymake collects diagnostic information from multiple sources,
called backends, and visually annotates the buffer with the
@@ -13345,6 +12208,13 @@ The commands `flymake-goto-next-error' and
`flymake-goto-prev-error' can be used to navigate among Flymake
diagnostics annotated in the buffer.
+By default, `flymake-mode' doesn't override the \\[next-error] command, but
+if you're using Flymake a lot (and don't use the regular compilation
+mechanisms that often), it can be useful to put something like
+the following in your init file:
+
+ (setq next-error-function \\='flymake-goto-next-error)
+
The visual appearance of each type of diagnostic can be changed
by setting properties `flymake-overlay-control', `flymake-bitmap'
and `flymake-severity' on the symbols of diagnostic types (like
@@ -13361,20 +12231,28 @@ suitable for the current buffer. The commands
`flymake-reporting-backends' summarize the situation, as does the
special *Flymake log* buffer.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Flymake mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `flymake-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'flymake-mode-on "flymake" "\
Turn Flymake mode on." nil nil)
-
(autoload 'flymake-mode-off "flymake" "\
Turn Flymake mode off." nil nil)
-
(register-definition-prefixes "flymake" '("flymake-"))
-;;;***
-;;;### (autoloads nil "flymake-cc" "progmodes/flymake-cc.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/flymake-cc.el
(autoload 'flymake-cc "flymake-cc" "\
@@ -13383,49 +12261,31 @@ This backend uses `flymake-cc-command' (which see) to launch a
process that is passed the current buffer's contents via stdin.
REPORT-FN is Flymake's callback.
-\(fn REPORT-FN &rest ARGS)" nil nil)
-
+(fn REPORT-FN &rest ARGS)" nil nil)
(register-definition-prefixes "flymake-cc" '("flymake-cc-"))
-;;;***
-;;;### (autoloads nil "flymake-proc" "progmodes/flymake-proc.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from progmodes/flymake-proc.el
-(push (purecopy '(flymake-proc 1 0)) package--builtin-versions)
+(push (purecopy '(flymake-proc 1 0)) package--builtin-versions)
(register-definition-prefixes "flymake-proc" '("flymake-proc-"))
-;;;***
-;;;### (autoloads nil "flyspell" "textmodes/flyspell.el" (0 0 0 0))
;;; Generated autoloads from textmodes/flyspell.el
(autoload 'flyspell-prog-mode "flyspell" "\
Turn on `flyspell-mode' for comments and strings." t nil)
(defvar flyspell-mode nil "Non-nil if Flyspell mode is enabled.")
-
(autoload 'flyspell-mode "flyspell" "\
Toggle on-the-fly spell checking (Flyspell mode).
-This is a minor mode. If called interactively, toggle the `Flyspell
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `flyspell-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Flyspell mode is a buffer-local minor mode. When enabled, it
spawns a single Ispell process and checks each word. The default
flyspell behavior is to highlight incorrect words.
+This mode is geared toward text modes. In buffers that contain
+code, `flyspell-prog-mode' is usually a better choice.
+
Bindings:
\\[ispell-word]: correct words (using Ispell).
\\[flyspell-auto-correct-word]: automatically correct word.
@@ -13442,72 +12302,60 @@ invoking `ispell-change-dictionary'.
Consider using the `ispell-parser' to check your text. For instance
consider adding:
-\(add-hook \\='tex-mode-hook (lambda () (setq ispell-parser \\='tex)))
+(add-hook \\='tex-mode-hook (lambda () (setq ispell-parser \\='tex)))
in your init file.
\\[flyspell-region] checks all words inside a region.
\\[flyspell-buffer] checks the whole buffer.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Flyspell mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `flyspell-mode'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'turn-on-flyspell "flyspell" "\
Unconditionally turn on Flyspell mode." nil nil)
-
(autoload 'turn-off-flyspell "flyspell" "\
Unconditionally turn off Flyspell mode." nil nil)
-
(autoload 'flyspell-mode-off "flyspell" "\
Turn Flyspell mode off." nil nil)
-
(autoload 'flyspell-region "flyspell" "\
Flyspell text between BEG and END.
Make sure `flyspell-mode' is turned on if you want the highlight
of a misspelled word removed when you've corrected it.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'flyspell-buffer "flyspell" "\
Flyspell whole buffer." t nil)
-
(register-definition-prefixes "flyspell" '("flyspell-" "mail-mode-flyspell-verify" "make-flyspell-overlay" "sgml-mode-flyspell-verify" "tex"))
-;;;***
-;;;### (autoloads nil "foldout" "foldout.el" (0 0 0 0))
;;; Generated autoloads from foldout.el
-(push (purecopy '(foldout 1 10)) package--builtin-versions)
+(push (purecopy '(foldout 1 10)) package--builtin-versions)
(register-definition-prefixes "foldout" '("foldout-"))
-;;;***
-;;;### (autoloads nil "follow" "follow.el" (0 0 0 0))
;;; Generated autoloads from follow.el
(autoload 'turn-on-follow-mode "follow" "\
Turn on Follow mode. Please see the function `follow-mode'." nil nil)
-
(autoload 'turn-off-follow-mode "follow" "\
Turn off Follow mode. Please see the function `follow-mode'." nil nil)
-
(autoload 'follow-mode "follow" "\
Toggle Follow mode.
-This is a minor mode. If called interactively, toggle the `Follow
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `follow-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Follow mode is a minor mode that combines windows into one tall
virtual window. This is accomplished by two main techniques:
@@ -13537,8 +12385,21 @@ This command runs the normal hook `follow-mode-hook'.
Keys specific to Follow mode:
\\{follow-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Follow mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `follow-mode'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'follow-scroll-up-window "follow" "\
Scroll text in a Follow mode window up by that window's size.
The other windows in the window chain will scroll synchronously.
@@ -13551,8 +12412,7 @@ Negative ARG means scroll downward.
Works like `scroll-up' when not in Follow mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'follow-scroll-down-window "follow" "\
Scroll text in a Follow mode window down by that window's size.
The other windows in the window chain will scroll synchronously.
@@ -13565,8 +12425,7 @@ Negative ARG means scroll upward.
Works like `scroll-down' when not in Follow mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'follow-scroll-up "follow" "\
Scroll text in a Follow mode window chain up.
@@ -13578,8 +12437,7 @@ Negative ARG means scroll downward.
Works like `scroll-up' when not in Follow mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'follow-scroll-down "follow" "\
Scroll text in a Follow mode window chain down.
@@ -13591,8 +12449,7 @@ Negative ARG means scroll upward.
Works like `scroll-down' when not in Follow mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'follow-delete-other-windows-and-split "follow" "\
Create two side by side windows and enter Follow mode.
@@ -13601,58 +12458,54 @@ in the selected window. All other windows, in the current
frame, are deleted and the selected window is split in two
side-by-side windows. Follow mode is activated, hence the
two windows always will display two successive pages.
-\(If one window is moved, the other one will follow.)
+(If one window is moved, the other one will follow.)
If ARG is positive, the leftmost window is selected. If negative,
the rightmost is selected. If ARG is nil, the leftmost window is
selected if the original window is the first one in the frame.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "follow" '("follow-"))
-;;;***
-;;;### (autoloads nil "fontset" "international/fontset.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from international/fontset.el
-(register-definition-prefixes "fontset" '("charset-script-alist" "create-" "fontset-" "generate-fontset-menu" "set" "standard-fontset-spec" "x-" "xlfd-"))
+(register-definition-prefixes "fontset" '("build-default-fontset-data" "charset-script-alist" "create-" "fontset-" "generate-fontset-menu" "set" "standard-fontset-spec" "x-" "xlfd-"))
-;;;***
-;;;### (autoloads nil "footnote" "mail/footnote.el" (0 0 0 0))
;;; Generated autoloads from mail/footnote.el
(autoload 'footnote-mode "footnote" "\
Toggle Footnote mode.
-This is a minor mode. If called interactively, toggle the `Footnote
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+Footnote mode is a buffer-local minor mode. If enabled, it
+provides footnote support for `message-mode'. To get started,
+play around with the following keys:
+\\{footnote-minor-mode-map}
+
+This is a minor mode. If called interactively, toggle the
+`Footnote mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `footnote-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-Footnote mode is a buffer-local minor mode. If enabled, it
-provides footnote support for `message-mode'. To get started,
-play around with the following keys:
-\\{footnote-minor-mode-map}
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "footnote" '("footnote-"))
-\(fn &optional ARG)" t nil)
+
+;;; Generated autoloads from cedet/semantic/format.el
-(register-definition-prefixes "footnote" '("footnote-"))
+(register-definition-prefixes "semantic/format" '("semantic-"))
-;;;***
-;;;### (autoloads nil "format-spec" "format-spec.el" (0 0 0 0))
;;; Generated autoloads from format-spec.el
(autoload 'format-spec "format-spec" "\
@@ -13703,13 +12556,10 @@ any occurrences of \"%%\" in FORMAT verbatim in the result.
If SPLIT, instead of returning a single string, a list of strings
is returned, where each format spec is its own element.
-\(fn FORMAT SPECIFICATION &optional IGNORE-MISSING SPLIT)" nil nil)
-
+(fn FORMAT SPECIFICATION &optional IGNORE-MISSING SPLIT)" nil nil)
(register-definition-prefixes "format-spec" '("format-spec-"))
-;;;***
-;;;### (autoloads nil "forms" "forms.el" (0 0 0 0))
;;; Generated autoloads from forms.el
(autoload 'forms-mode "forms" "\
@@ -13731,23 +12581,18 @@ Commands: Equivalent keys in read-only mode:
C-c C-s forms-search-forward s
C-c C-x forms-exit x
-\(fn &optional PRIMARY)" t nil)
-
+(fn &optional PRIMARY)" t nil)
(autoload 'forms-find-file "forms" "\
Visit a file in Forms mode.
-\(fn FN)" t nil)
-
+(fn FN)" t nil)
(autoload 'forms-find-file-other-window "forms" "\
Visit a file in Forms mode in other window.
-\(fn FN)" t nil)
-
+(fn FN)" t nil)
(register-definition-prefixes "forms" '("forms-"))
-;;;***
-;;;### (autoloads nil "fortran" "progmodes/fortran.el" (0 0 0 0))
;;; Generated autoloads from progmodes/fortran.el
(autoload 'fortran-mode "fortran" "\
@@ -13820,13 +12665,10 @@ Variables controlling indentation style and extra features:
Turning on Fortran mode calls the value of the variable `fortran-mode-hook'
with no args, if that value is non-nil.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "fortran" '("fortran-"))
-;;;***
-;;;### (autoloads nil "fortune" "play/fortune.el" (0 0 0 0))
;;; Generated autoloads from play/fortune.el
(autoload 'fortune-add-fortune "fortune" "\
@@ -13835,24 +12677,21 @@ Add STRING to a fortune file FILE.
Interactively, if called with a prefix argument,
read the file name to use. Otherwise use the value of `fortune-file'.
-\(fn STRING FILE)" t nil)
-
+(fn STRING FILE)" t nil)
(autoload 'fortune-from-region "fortune" "\
Append the current region to a local fortune-like data file.
Interactively, if called with a prefix argument,
read the file name to use. Otherwise use the value of `fortune-file'.
-\(fn BEG END FILE)" t nil)
-
+(fn BEG END FILE)" t nil)
(autoload 'fortune-compile "fortune" "\
Compile fortune file.
If called with a prefix asks for the FILE to compile, otherwise uses
the value of `fortune-file'. This currently cannot handle directories.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(autoload 'fortune-to-signature "fortune" "\
Create signature from output of the fortune program.
@@ -13861,15 +12700,13 @@ otherwise uses the value of `fortune-file'. If you want to have fortune
choose from a set of files in a directory, call interactively with prefix
and choose the directory as the fortune-file.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(autoload 'fortune-message "fortune" "\
Display a fortune cookie to the mini-buffer.
If called with a prefix, it has the same behavior as `fortune'.
Optional FILE is a fortune file from which a cookie will be selected.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(autoload 'fortune "fortune" "\
Display a fortune cookie.
If called with a prefix asks for the FILE to choose the fortune from,
@@ -13877,23 +12714,18 @@ otherwise uses the value of `fortune-file'. If you want to have fortune
choose from a set of files in a directory, call interactively with prefix
and choose the directory as the fortune-file.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(register-definition-prefixes "fortune" '("fortune-"))
-;;;***
-;;;### (autoloads nil "frameset" "frameset.el" (0 0 0 0))
;;; Generated autoloads from frameset.el
-(defvar frameset-session-filter-alist '((name . :never) (left . frameset-filter-iconified) (minibuffer . frameset-filter-minibuffer) (top . frameset-filter-iconified)) "\
+(defvar frameset-session-filter-alist (append '((left . frameset-filter-iconified) (minibuffer . frameset-filter-minibuffer) (top . frameset-filter-iconified)) (mapcar (lambda (p) (cons p :never)) frame-internal-parameters)) "\
Minimum set of parameters to filter for live (on-session) framesets.
DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
-
-(defvar frameset-persistent-filter-alist (append '((background-color . frameset-filter-sanitize-color) (buffer-list . :never) (buffer-predicate . :never) (buried-buffer-list . :never) (client . :never) (delete-before . :never) (font . frameset-filter-font-param) (font-backend . :never) (foreground-color . frameset-filter-sanitize-color) (frameset--text-pixel-height . :save) (frameset--text-pixel-width . :save) (fullscreen . frameset-filter-shelve-param) (GUI:font . frameset-filter-unshelve-param) (GUI:fullscreen . frameset-filter-unshelve-param) (GUI:height . frameset-filter-unshelve-param) (GUI:width . frameset-filter-unshelve-param) (height . frameset-filter-shelve-param) (outer-window-id . :never) (parent-frame . :never) (parent-id . :never) (mouse-wheel-frame . :never) (tty . frameset-filter-tty-to-GUI) (tty-type . frameset-filter-tty-to-GUI) (width . frameset-filter-shelve-param) (window-id . :never) (window-system . :never)) frameset-session-filter-alist) "\
+(defvar frameset-persistent-filter-alist (append '((background-color . frameset-filter-sanitize-color) (bottom . frameset-filter-shelve-param) (buffer-list . :never) (buffer-predicate . :never) (buried-buffer-list . :never) (client . :never) (delete-before . :never) (font . frameset-filter-font-param) (font-backend . :never) (foreground-color . frameset-filter-sanitize-color) (frameset--text-pixel-height . :save) (frameset--text-pixel-width . :save) (fullscreen . frameset-filter-shelve-param) (GUI:bottom . frameset-filter-unshelve-param) (GUI:font . frameset-filter-unshelve-param) (GUI:fullscreen . frameset-filter-unshelve-param) (GUI:height . frameset-filter-unshelve-param) (GUI:left . frameset-filter-unshelve-param) (GUI:right . frameset-filter-unshelve-param) (GUI:top . frameset-filter-unshelve-param) (GUI:width . frameset-filter-unshelve-param) (height . frameset-filter-shelve-param) (left . frameset-filter-shelve-param) (parent-frame . :never) (mouse-wheel-frame . :never) (right . frameset-filter-shelve-param) (top . frameset-filter-shelve-param) (tty . frameset-filter-tty-to-GUI) (tty-type . frameset-filter-tty-to-GUI) (width . frameset-filter-shelve-param) (window-system . :never)) frameset-session-filter-alist) "\
Parameters to filter for persistent framesets.
DO NOT MODIFY. See `frameset-filter-alist' for a full description.")
-
(defvar frameset-filter-alist frameset-persistent-filter-alist "\
Alist of frame parameters and filtering functions.
@@ -13949,7 +12781,6 @@ It must return:
Frame parameters not on this alist are passed intact, as if they were
defined with ACTION = nil.")
-
(autoload 'frameset-frame-id "frameset" "\
Return the frame id of FRAME, if it has one; else, return nil.
A frame id is a string that uniquely identifies a frame.
@@ -13958,20 +12789,17 @@ invocations, and once assigned is never changed unless the same
frame is duplicated (via `frameset-restore'), in which case the
newest frame keeps the id and the old frame's is set to nil.
-\(fn FRAME)" nil nil)
-
+(fn FRAME)" nil nil)
(autoload 'frameset-frame-id-equal-p "frameset" "\
Return non-nil if FRAME's id matches ID.
-\(fn FRAME ID)" nil nil)
-
+(fn FRAME ID)" nil nil)
(autoload 'frameset-frame-with-id "frameset" "\
Return the live frame with id ID, if exists; else nil.
If FRAME-LIST is a list of frames, check these frames only.
If nil, check all live frames.
-\(fn ID &optional FRAME-LIST)" nil nil)
-
+(fn ID &optional FRAME-LIST)" nil nil)
(autoload 'frameset-save "frameset" "\
Return a frameset for FRAME-LIST, a list of frames.
Dead frames and non-frame objects are silently removed from the list.
@@ -13984,8 +12812,7 @@ PREDICATE is a predicate function, which must return non-nil for frames that
should be saved; if PREDICATE is nil, all frames from FRAME-LIST are saved.
PROPERTIES is a user-defined property list to add to the frameset.
-\(fn FRAME-LIST &key APP NAME DESCRIPTION FILTERS PREDICATE PROPERTIES)" nil nil)
-
+(fn FRAME-LIST &key APP NAME DESCRIPTION FILTERS PREDICATE PROPERTIES)" nil nil)
(autoload 'frameset-restore "frameset" "\
Restore a FRAMESET into the current display(s).
@@ -14045,8 +12872,7 @@ restoration, including those that have been reused or created anew.
All keyword parameters default to nil.
-\(fn FRAMESET &key PREDICATE FILTERS REUSE-FRAMES FORCE-DISPLAY FORCE-ONSCREEN CLEANUP-FRAMES)" nil nil)
-
+(fn FRAMESET &key PREDICATE FILTERS REUSE-FRAMES FORCE-DISPLAY FORCE-ONSCREEN CLEANUP-FRAMES)" nil nil)
(autoload 'frameset-to-register "frameset" "\
Store the current frameset in register REGISTER.
Use \\[jump-to-register] to restore the frameset.
@@ -14054,69 +12880,78 @@ Argument is a character, naming the register.
Interactively, reads the register using `register-read-with-preview'.
-\(fn REGISTER)" t nil)
-
+(fn REGISTER)" t nil)
(register-definition-prefixes "frameset" '("frameset-"))
-;;;***
-;;;### (autoloads nil "fringe" "fringe.el" (0 0 0 0))
;;; Generated autoloads from fringe.el
-(unless (fboundp 'define-fringe-bitmap) (defun define-fringe-bitmap (_bitmap _bits &optional _height _width _align) "Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.\nBITMAP is a symbol identifying the new fringe bitmap.\nBITS is either a string or a vector of integers.\nHEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.\nWIDTH must be an integer between 1 and 16, or nil which defaults to 8.\nOptional fifth arg ALIGN may be one of ‘top’, ‘center’, or ‘bottom’,\nindicating the positioning of the bitmap relative to the rows where it\nis used; the default is to center the bitmap. Fifth arg may also be a\nlist (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap\nshould be repeated.\nIf BITMAP already exists, the existing definition is replaced."))
-
+(unless (fboundp 'define-fringe-bitmap) (defun define-fringe-bitmap (_bitmap _bits &optional _height _width _align) "Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
+BITMAP is a symbol identifying the new fringe bitmap.
+BITS is either a string or a vector of integers.
+HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
+WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
+Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
+indicating the positioning of the bitmap relative to the rows where it
+is used; the default is to center the bitmap. Fifth arg may also be a
+list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
+should be repeated.
+If BITMAP already exists, the existing definition is replaced."))
(register-definition-prefixes "fringe" '("fringe-" "set-fringe-"))
-;;;***
-;;;### (autoloads nil "gamegrid" "play/gamegrid.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/fw.el
+
+(register-definition-prefixes "semantic/fw" '("semantic"))
+
+
;;; Generated autoloads from play/gamegrid.el
(register-definition-prefixes "gamegrid" '("gamegrid-"))
-;;;***
-;;;### (autoloads nil "gametree" "play/gametree.el" (0 0 0 0))
;;; Generated autoloads from play/gametree.el
(register-definition-prefixes "gametree" '("gametree-"))
-;;;***
-;;;### (autoloads nil "gdb-mi" "progmodes/gdb-mi.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/bovine/gcc.el
+
+(register-definition-prefixes "semantic/bovine/gcc" '("semantic-"))
+
+
;;; Generated autoloads from progmodes/gdb-mi.el
(defvar gdb-enable-debug nil "\
Non-nil if Gdb-Enable-Debug mode is enabled.
See the `gdb-enable-debug' command
for a description of this minor mode.")
-
(custom-autoload 'gdb-enable-debug "gdb-mi" nil)
-
(autoload 'gdb-enable-debug "gdb-mi" "\
Toggle logging of transaction between Emacs and Gdb.
+
The log is stored in `gdb-debug-log' as an alist with elements
whose cons is send, send-item or recv and whose cdr is the string
being transferred. This list may grow up to a size of
`gdb-debug-log-max' after which the oldest element (at the end of
the list) is deleted every time a new one is added (at the front).
-This is a minor mode. If called interactively, toggle the
-`Gdb-Enable-Debug mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Gdb-Enable-Debug mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='gdb-enable-debug)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'gdb "gdb-mi" "\
Run gdb passing it COMMAND-LINE as arguments.
@@ -14175,28 +13010,21 @@ detailed description of this mode.
| | D gdb-delete-breakpoint |
+-----------------------------------+----------------------------------+
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(register-definition-prefixes "gdb-mi" '("breakpoint" "def-gdb-" "gdb" "gud-" "hollow-right-triangle" "nil"))
-;;;***
-;;;### (autoloads nil "generator" "emacs-lisp/generator.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/generator.el
(register-definition-prefixes "generator" '("cps-" "iter-"))
-;;;***
-;;;### (autoloads nil "generic" "emacs-lisp/generic.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/generic.el
(defvar generic-mode-list nil "\
A list of mode names for `generic-mode'.
Do not add entries to this list directly; use `define-generic-mode'
instead (which see).")
-
(autoload 'define-generic-mode "generic" "\
Create a new generic mode MODE.
@@ -14235,17 +13063,13 @@ mode hook `MODE-hook'.
See the file generic-x.el for some examples of `define-generic-mode'.
-\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t)
-
-(function-put 'define-generic-mode 'lisp-indent-function '1)
-
-(function-put 'define-generic-mode 'doc-string-elt '7)
-
+(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t)
+(function-put 'define-generic-mode 'lisp-indent-function 1)
+(function-put 'define-generic-mode 'doc-string-elt 7)
(autoload 'generic-mode-internal "generic" "\
Go into the generic mode MODE.
-\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST FUNCTION-LIST)" nil nil)
-
+(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST FUNCTION-LIST)" nil nil)
(autoload 'generic-mode "generic" "\
Enter generic mode MODE.
@@ -14256,8 +13080,7 @@ own mode, but have comment characters, keywords, and the like.)
To define a generic-mode, use the function `define-generic-mode'.
Some generic modes are defined in `generic-x.el'.
-\(fn MODE)" t nil)
-
+(fn MODE)" t nil)
(autoload 'generic-make-keywords-list "generic" "\
Return a `font-lock-keywords' construct that highlights KEYWORD-LIST.
KEYWORD-LIST is a list of keyword strings that should be
@@ -14267,88 +13090,86 @@ PREFIX and SUFFIX. Then it returns a construct based on this
regular expression that can be used as an element of
`font-lock-keywords'.
-\(fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil)
+(fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil)
+(make-obsolete 'generic-make-keywords-list 'regexp-opt "24.4")
+(register-definition-prefixes "generic" '("generic-"))
-(make-obsolete 'generic-make-keywords-list 'regexp-opt '"24.4")
+
+;;; Generated autoloads from cedet/ede/generic.el
-(register-definition-prefixes "generic" '("generic-"))
+(register-definition-prefixes "ede/generic" '("ede-generic-"))
-;;;***
-;;;### (autoloads nil "generic-x" "generic-x.el" (0 0 0 0))
-;;; Generated autoloads from generic-x.el
+;;; Generated autoloads from cedet/srecode/getset.el
-(register-definition-prefixes "generic-x" '("default-generic-mode" "generic-"))
+(register-definition-prefixes "srecode/getset" '("srecode-"))
-;;;***
-;;;### (autoloads nil "glasses" "progmodes/glasses.el" (0 0 0 0))
;;; Generated autoloads from progmodes/glasses.el
(autoload 'glasses-mode "glasses" "\
Minor mode for making identifiers likeThis readable.
-This is a minor mode. If called interactively, toggle the `Glasses
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+When this mode is active, it tries to add virtual
+separators (like underscores) at places they belong to.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+This is a minor mode. If called interactively, toggle the
+`Glasses mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `glasses-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-When this mode is active, it tries to add virtual
-separators (like underscores) at places they belong to.
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "glasses" '("glasses-"))
-\(fn &optional ARG)" t nil)
+
+;;; Generated autoloads from cedet/semantic/symref/global.el
-(register-definition-prefixes "glasses" '("glasses-"))
+(register-definition-prefixes "semantic/symref/global" '("semantic-symref-global--line-re"))
-;;;***
-;;;### (autoloads nil "glyphless-mode" "textmodes/glyphless-mode.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from textmodes/glyphless-mode.el
(autoload 'glyphless-display-mode "glyphless-mode" "\
Minor mode for displaying glyphless characters in the current buffer.
+
If enabled, all glyphless characters will be displayed as boxes
that display their acronyms.
This is a minor mode. If called interactively, toggle the
-`Glyphless-Display mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Glyphless-Display mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `glyphless-display-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "glyphless-mode" '("glyphless-mode-"))
-;;;***
-;;;### (autoloads nil "gmm-utils" "gnus/gmm-utils.el" (0 0 0 0))
;;; Generated autoloads from gnus/gmm-utils.el
(autoload 'gmm-regexp-concat "gmm-utils" "\
Potentially concat a list of regexps into a single one.
The concatenation is done with logical ORs.
-\(fn REGEXP)" nil nil)
-
+(fn REGEXP)" nil nil)
(autoload 'gmm-message "gmm-utils" "\
If LEVEL is lower than `gmm-verbose' print ARGS using `message'.
@@ -14359,19 +13180,16 @@ Guideline for numbers:
7 - not very important messages on stuff
9 - messages inside loops.
-\(fn LEVEL &rest ARGS)" nil nil)
-
+(fn LEVEL &rest ARGS)" nil nil)
(autoload 'gmm-error "gmm-utils" "\
Beep an error if LEVEL is equal to or less than `gmm-verbose'.
ARGS are passed to `message'.
-\(fn LEVEL &rest ARGS)" nil nil)
-
+(fn LEVEL &rest ARGS)" nil nil)
(autoload 'gmm-widget-p "gmm-utils" "\
Non-nil if SYMBOL is a widget.
-\(fn SYMBOL)" nil nil)
-
+(fn SYMBOL)" nil nil)
(autoload 'gmm-tool-bar-from-list "gmm-utils" "\
Make a tool bar from ICON-LIST.
@@ -14390,27 +13208,22 @@ runs the command find-file\", then use `new-file' in ZAP-LIST.
DEFAULT-MAP specifies the default key map for ICON-LIST.
-\(fn ICON-LIST ZAP-LIST DEFAULT-MAP)" nil nil)
-
+(fn ICON-LIST ZAP-LIST DEFAULT-MAP)" nil nil)
(register-definition-prefixes "gmm-utils" '("defun-gmm" "gmm-"))
-;;;***
-;;;### (autoloads nil "gnus" "gnus/gnus.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus.el
+
(push (purecopy '(gnus 5 13)) package--builtin-versions)
(custom-autoload 'gnus-select-method "gnus")
-
(autoload 'gnus-child-no-server "gnus" "\
Read network news as a child, without connecting to the local server.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-slave-no-server "gnus" "\
Read network news as a child, without connecting to the local server.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-no-server "gnus" "\
Read network news.
If ARG is a positive number, Gnus will use that as the startup level.
@@ -14420,18 +13233,15 @@ an NNTP server to use.
As opposed to `gnus', this command will not connect to the local
server.
-\(fn &optional ARG CHILD)" t nil)
-
+(fn &optional ARG CHILD)" t nil)
(autoload 'gnus-child "gnus" "\
Read news as a child.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-slave "gnus" "\
Read news as a child.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-other-frame "gnus" "\
Pop up a frame to read news.
This will call one of the Gnus commands which is specified by the user
@@ -14443,39 +13253,31 @@ such as \"unix:0\" to specify where to pop up a frame. If DISPLAY is
omitted or the function `make-frame-on-display' is not available, the
current display is used.
-\(fn &optional ARG DISPLAY)" t nil)
-
+(fn &optional ARG DISPLAY)" t nil)
(autoload 'gnus "gnus" "\
Read network news.
If ARG is non-nil and a positive number, Gnus will use that as the
startup level. If ARG is non-nil and not a positive number, Gnus will
prompt the user for the name of an NNTP server to use.
-\(fn &optional ARG DONT-CONNECT CHILD)" t nil)
-
+(fn &optional ARG DONT-CONNECT CHILD)" t nil)
(register-definition-prefixes "gnus" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-agent" "gnus/gnus-agent.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-agent.el
(autoload 'gnus-unplugged "gnus-agent" "\
Start Gnus unplugged." t nil)
-
(autoload 'gnus-plugged "gnus-agent" "\
Start Gnus plugged." t nil)
-
(autoload 'gnus-child-unplugged "gnus-agent" "\
Read news as a child unplugged.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-slave-unplugged "gnus-agent" "\
Read news as a child unplugged.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'gnus-agentize "gnus-agent" "\
Allow Gnus to be an offline newsreader.
@@ -14486,10 +13288,8 @@ customize `gnus-agent' to nil.
This will modify the `gnus-setup-news-hook', and
`message-send-mail-real-function' variables, and install the Gnus agent
minor mode in all Gnus buffers." t nil)
-
(autoload 'gnus-agent-possibly-save-gcc "gnus-agent" "\
Save GCC if Gnus is unplugged." nil nil)
-
(autoload 'gnus-agent-rename-group "gnus-agent" "\
Rename fully-qualified OLD-GROUP as NEW-GROUP.
Always updates the agent, even when disabled, as the old agent
@@ -14497,8 +13297,7 @@ files would corrupt gnus when the agent was next enabled.
Depends upon the caller to determine whether group renaming is
supported.
-\(fn OLD-GROUP NEW-GROUP)" nil nil)
-
+(fn OLD-GROUP NEW-GROUP)" nil nil)
(autoload 'gnus-agent-delete-group "gnus-agent" "\
Delete fully-qualified GROUP.
Always updates the agent, even when disabled, as the old agent
@@ -14506,87 +13305,65 @@ files would corrupt gnus when the agent was next enabled.
Depends upon the caller to determine whether group deletion is
supported.
-\(fn GROUP)" nil nil)
-
+(fn GROUP)" nil nil)
(autoload 'gnus-agent-get-undownloaded-list "gnus-agent" "\
Construct list of articles that have not been downloaded." nil nil)
-
(autoload 'gnus-agent-possibly-alter-active "gnus-agent" "\
Possibly expand a group's active range to include articles
downloaded into the agent.
-\(fn GROUP ACTIVE &optional INFO)" nil nil)
-
+(fn GROUP ACTIVE &optional INFO)" nil nil)
(autoload 'gnus-agent-find-parameter "gnus-agent" "\
Search for GROUPs SYMBOL in the group's parameters, the group's
topic parameters, the group's category, or the customizable
variables. Returns the first non-nil value found.
-\(fn GROUP SYMBOL)" nil nil)
-
+(fn GROUP SYMBOL)" nil nil)
(autoload 'gnus-agent-batch-fetch "gnus-agent" "\
Start Gnus and fetch session." t nil)
-
(autoload 'gnus-agent-batch "gnus-agent" "\
Start Gnus, send queue and fetch session." t nil)
-
(autoload 'gnus-agent-regenerate "gnus-agent" "\
Regenerate all agent covered files.
CLEAN is obsolete and ignored.
-\(fn &optional CLEAN REREAD)" t nil)
-
+(fn &optional CLEAN REREAD)" t nil)
(register-definition-prefixes "gnus-agent" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-art" "gnus/gnus-art.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-art.el
(autoload 'gnus-article-prepare-display "gnus-art" "\
Make the current buffer look like a nice article." nil nil)
-
(register-definition-prefixes "gnus-art" '(":keymap" "article-" "gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-async" "gnus/gnus-async.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-async.el
(register-definition-prefixes "gnus-async" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-bcklg" "gnus/gnus-bcklg.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-bcklg.el
(register-definition-prefixes "gnus-bcklg" '("gnus-backlog-"))
-;;;***
-;;;### (autoloads nil "gnus-bookmark" "gnus/gnus-bookmark.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from gnus/gnus-bookmark.el
(autoload 'gnus-bookmark-set "gnus-bookmark" "\
Set a bookmark for this article." '(gnus-article-mode gnus-summary-mode) nil)
-
(autoload 'gnus-bookmark-jump "gnus-bookmark" "\
Jump to a Gnus bookmark (BMK-NAME).
-\(fn &optional BMK-NAME)" t nil)
-
+(fn &optional BMK-NAME)" t nil)
(autoload 'gnus-bookmark-bmenu-list "gnus-bookmark" "\
Display a list of existing Gnus bookmarks.
The list is displayed in a buffer named `*Gnus Bookmark List*'.
The leftmost column displays a D if the bookmark is flagged for
deletion, or > if it is flagged for displaying." t nil)
-
(register-definition-prefixes "gnus-bookmark" '("gnus-bookmark-"))
-;;;***
-;;;### (autoloads nil "gnus-cache" "gnus/gnus-cache.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-cache.el
(autoload 'gnus-jog-cache "gnus-cache" "\
@@ -14594,17 +13371,14 @@ Go through all groups and put the articles into the cache.
Usage:
$ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" t nil)
-
(autoload 'gnus-cache-generate-active "gnus-cache" "\
Generate the cache active file.
-\(fn &optional DIRECTORY)" t nil)
-
+(fn &optional DIRECTORY)" t nil)
(autoload 'gnus-cache-generate-nov-databases "gnus-cache" "\
Generate NOV files recursively starting in DIR.
-\(fn DIR)" t nil)
-
+(fn DIR)" t nil)
(autoload 'gnus-cache-rename-group "gnus-cache" "\
Rename OLD-GROUP as NEW-GROUP.
Always updates the cache, even when disabled, as the old cache
@@ -14612,8 +13386,7 @@ files would corrupt Gnus when the cache was next enabled. It
depends on the caller to determine whether group renaming is
supported.
-\(fn OLD-GROUP NEW-GROUP)" nil nil)
-
+(fn OLD-GROUP NEW-GROUP)" nil nil)
(autoload 'gnus-cache-delete-group "gnus-cache" "\
Delete GROUP from the cache.
Always updates the cache, even when disabled, as the old cache
@@ -14621,41 +13394,30 @@ files would corrupt gnus when the cache was next enabled.
Depends upon the caller to determine whether group deletion is
supported.
-\(fn GROUP)" nil nil)
-
+(fn GROUP)" nil nil)
(register-definition-prefixes "gnus-cache" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-cite" "gnus/gnus-cite.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-cite.el
(register-definition-prefixes "gnus-cite" '("gnus-" "turn-o"))
-;;;***
-;;;### (autoloads nil "gnus-cloud" "gnus/gnus-cloud.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-cloud.el
(register-definition-prefixes "gnus-cloud" '("gnus-cloud-"))
-;;;***
-;;;### (autoloads nil "gnus-cus" "gnus/gnus-cus.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-cus.el
(register-definition-prefixes "gnus-cus" '("category-fields" "gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-dbus" "gnus/gnus-dbus.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-dbus.el
(register-definition-prefixes "gnus-dbus" '("gnus-dbus-"))
-;;;***
-;;;### (autoloads nil "gnus-delay" "gnus/gnus-delay.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-delay.el
(autoload 'gnus-delay-article "gnus-delay" "\
@@ -14675,11 +13437,9 @@ The value of `message-draft-headers' determines which headers are
generated when the article is delayed. Remaining headers are
generated when the article is sent.
-\(fn DELAY)" '(message-mode) nil)
-
+(fn DELAY)" '(message-mode) nil)
(autoload 'gnus-delay-send-queue "gnus-delay" "\
Send all the delayed messages that are due now." t nil)
-
(autoload 'gnus-delay-initialize "gnus-delay" "\
Initialize the gnus-delay package.
This sets up a key binding in `message-mode' to delay a message.
@@ -14688,151 +13448,115 @@ This tells Gnus to look for delayed messages after getting new news.
The optional arg NO-KEYMAP is ignored.
Checking delayed messages is skipped if optional arg NO-CHECK is non-nil.
-\(fn &optional NO-KEYMAP NO-CHECK)" nil nil)
-
+(fn &optional NO-KEYMAP NO-CHECK)" nil nil)
(register-definition-prefixes "gnus-delay" '("gnus-delay-"))
-;;;***
-;;;### (autoloads nil "gnus-demon" "gnus/gnus-demon.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-demon.el
(register-definition-prefixes "gnus-demon" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-diary" "gnus/gnus-diary.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-diary.el
(autoload 'gnus-user-format-function-d "gnus-diary" "\
-\(fn HEADER)" nil nil)
-
+(fn HEADER)" nil nil)
(autoload 'gnus-user-format-function-D "gnus-diary" "\
-\(fn HEADER)" nil nil)
-
+(fn HEADER)" nil nil)
(register-definition-prefixes "gnus-diary" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-dired" "gnus/gnus-dired.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-dired.el
(autoload 'turn-on-gnus-dired-mode "gnus-dired" "\
Convenience method to turn on `gnus-dired-mode'." t nil)
-
(register-definition-prefixes "gnus-dired" '("gnus-dired-"))
-;;;***
-;;;### (autoloads nil "gnus-draft" "gnus/gnus-draft.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-draft.el
(autoload 'gnus-draft-reminder "gnus-draft" "\
Reminder user if there are unsent drafts." t nil)
-
(register-definition-prefixes "gnus-draft" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-dup" "gnus/gnus-dup.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-dup.el
(register-definition-prefixes "gnus-dup" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-eform" "gnus/gnus-eform.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-eform.el
(register-definition-prefixes "gnus-eform" '("gnus-edit-form"))
-;;;***
-;;;### (autoloads nil "gnus-fun" "gnus/gnus-fun.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-fun.el
(autoload 'gnus--random-face-with-type "gnus-fun" "\
Return file from DIR with extension EXT.
Omit matches of OMIT, and process them by FUN.
-\(fn DIR EXT OMIT FUN)" nil nil)
-
+(fn DIR EXT OMIT FUN)" nil nil)
(autoload 'message-goto-eoh "message" nil t)
-
(autoload 'gnus-random-x-face "gnus-fun" "\
Return X-Face header data chosen randomly from `gnus-x-face-directory'.
Files matching `gnus-x-face-omit-files' are not considered." t nil)
-
(autoload 'gnus-insert-random-x-face-header "gnus-fun" "\
Insert a random X-Face header from `gnus-x-face-directory'." t nil)
-
(autoload 'gnus-x-face-from-file "gnus-fun" "\
Insert an X-Face header based on an image FILE.
Depending on `gnus-convert-image-to-x-face-command' it may accept
different input formats.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'gnus-face-from-file "gnus-fun" "\
Return a Face header based on an image FILE.
Depending on `gnus-convert-image-to-face-command' it may accept
different input formats.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'gnus-convert-face-to-png "gnus-fun" "\
Convert FACE (which is base64-encoded) to a PNG.
The PNG is returned as a string.
-\(fn FACE)" nil nil)
-
+(fn FACE)" nil nil)
(autoload 'gnus-convert-png-to-face "gnus-fun" "\
Convert FILE to a Face.
FILE should be a PNG file that's 48x48 and smaller than or equal to
726 bytes.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'gnus-random-face "gnus-fun" "\
Return randomly chosen Face from `gnus-face-directory'.
Files matching `gnus-face-omit-files' are not considered." t nil)
-
(autoload 'gnus-insert-random-face-header "gnus-fun" "\
Insert a random Face header from `gnus-face-directory'." nil nil)
-
(register-definition-prefixes "gnus-fun" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-gravatar" "gnus/gnus-gravatar.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from gnus/gnus-gravatar.el
(autoload 'gnus-treat-from-gravatar "gnus-gravatar" "\
Display gravatar in the From header.
If gravatar is already displayed, remove it.
-\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
-
+(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
(autoload 'gnus-treat-mail-gravatar "gnus-gravatar" "\
Display gravatars in the Cc and To headers.
If gravatars are already displayed, remove them.
-\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
-
+(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil)
(register-definition-prefixes "gnus-gravatar" '("gnus-gravatar-"))
-;;;***
-;;;### (autoloads nil "gnus-group" "gnus/gnus-group.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-group.el
(autoload 'gnus-fetch-group "gnus-group" "\
@@ -14840,125 +13564,98 @@ Start Gnus if necessary and enter GROUP.
If ARTICLES, display those articles.
Returns whether the fetching was successful or not.
-\(fn GROUP &optional ARTICLES)" t nil)
-
+(fn GROUP &optional ARTICLES)" t nil)
(autoload 'gnus-fetch-group-other-frame "gnus-group" "\
Pop up a frame and enter GROUP.
-\(fn GROUP)" t nil)
-
+(fn GROUP)" t nil)
(autoload 'gnus-read-ephemeral-emacs-bug-group "gnus-group" "\
Browse Emacs bug reports with IDS in an ephemeral group.
The arguments have the same meaning as those of
`gnus-read-ephemeral-bug-group', which see.
-\(fn IDS &optional WINDOW-CONF)" t nil)
-
+(fn IDS &optional WINDOW-CONF)" t nil)
(register-definition-prefixes "gnus-group" '(":keymap" "gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-html" "gnus/gnus-html.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-html.el
(autoload 'gnus-article-html "gnus-html" "\
-\(fn &optional HANDLE)" nil nil)
-
+(fn &optional HANDLE)" nil nil)
(autoload 'gnus-html-prefetch-images "gnus-html" "\
-\(fn SUMMARY)" nil nil)
-
+(fn SUMMARY)" nil nil)
(register-definition-prefixes "gnus-html" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-icalendar" "gnus/gnus-icalendar.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from gnus/gnus-icalendar.el
(autoload 'gnus-icalendar-mm-inline "gnus-icalendar" "\
-\(fn HANDLE)" nil nil)
-
+(fn HANDLE)" nil nil)
(register-definition-prefixes "gnus-icalendar" '("gnus-icalendar"))
-;;;***
-;;;### (autoloads nil "gnus-int" "gnus/gnus-int.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-int.el
(register-definition-prefixes "gnus-int" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-kill" "gnus/gnus-kill.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-kill.el
(defalias 'gnus-batch-kill 'gnus-batch-score)
-
(autoload 'gnus-batch-score "gnus-kill" "\
Run batched scoring.
Usage: emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score" t nil)
-
(register-definition-prefixes "gnus-kill" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-logic" "gnus/gnus-logic.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-logic.el
(register-definition-prefixes "gnus-logic" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-mh" "gnus/gnus-mh.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-mh.el
(register-definition-prefixes "gnus-mh" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-ml" "gnus/gnus-ml.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-ml.el
(autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil nil nil)
-
(autoload 'gnus-mailing-list-insinuate "gnus-ml" "\
Setup group parameters from List-Post header.
If FORCE is non-nil, replace the old ones.
-\(fn &optional FORCE)" t nil)
-
+(fn &optional FORCE)" t nil)
(autoload 'gnus-mailing-list-mode "gnus-ml" "\
Minor mode for providing mailing-list commands.
+\\{gnus-mailing-list-mode-map}
+
This is a minor mode. If called interactively, toggle the
-`Gnus-Mailing-List mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Gnus-Mailing-List mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `gnus-mailing-list-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\\{gnus-mailing-list-mode-map}
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "gnus-ml" '("gnus-mailing-list-"))
-;;;***
-;;;### (autoloads nil "gnus-mlspl" "gnus/gnus-mlspl.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-mlspl.el
(autoload 'gnus-group-split-setup "gnus-mlspl" "\
@@ -14983,8 +13680,7 @@ elaborate fancy splits may also be useful to split mail that doesn't
match any of the group-specified splitting rules. See
`gnus-group-split-fancy' for details.
-\(fn &optional AUTO-UPDATE CATCH-ALL)" t nil)
-
+(fn &optional AUTO-UPDATE CATCH-ALL)" t nil)
(autoload 'gnus-group-split-update "gnus-mlspl" "\
Computes `nnmail-split-fancy' from group params and CATCH-ALL.
It does this by calling (gnus-group-split-fancy nil nil CATCH-ALL).
@@ -14992,19 +13688,17 @@ It does this by calling (gnus-group-split-fancy nil nil CATCH-ALL).
If CATCH-ALL is nil, `gnus-group-split-default-catch-all-group' is used
instead. This variable is set by `gnus-group-split-setup'.
-\(fn &optional CATCH-ALL)" t nil)
-
+(fn &optional CATCH-ALL)" t nil)
(autoload 'gnus-group-split "gnus-mlspl" "\
Use information from group parameters in order to split mail.
See `gnus-group-split-fancy' for more information.
`gnus-group-split' is a valid value for `nnmail-split-methods'." nil nil)
-
(autoload 'gnus-group-split-fancy "gnus-mlspl" "\
Uses information from group parameters in order to split mail.
It can be embedded into `nnmail-split-fancy' lists with the SPLIT
-\(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL)
+(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL)
GROUPS may be a regular expression or a list of group names, that will
be used to select candidate groups. If it is omitted or nil, all
@@ -15033,31 +13727,28 @@ as the last element of a `|' SPLIT.
For example, given the following group parameters:
nnml:mail.bar:
-\((to-address . \"bar@femail.com\")
+((to-address . \"bar@femail.com\")
(split-regexp . \".*@femail\\\\.com\"))
nnml:mail.foo:
-\((to-list . \"foo@nowhere.gov\")
+((to-list . \"foo@nowhere.gov\")
(extra-aliases \"foo@localhost\" \"foo-redist@home\")
(split-exclude \"bugs-foo\" \"rambling-foo\")
(admin-address . \"foo-request@nowhere.gov\"))
nnml:mail.others:
-\((split-spec . catch-all))
+((split-spec . catch-all))
Calling (gnus-group-split-fancy nil nil \"mail.others\") returns:
-\(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\"
+(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\"
\"mail.bar\")
(any \"\\\\(foo@nowhere\\\\.gov\\\\|foo@localhost\\\\|foo-redist@home\\\\)\"
- \"bugs-foo\" - \"rambling-foo\" \"mail.foo\"))
\"mail.others\")
-\(fn &optional GROUPS NO-CROSSPOST CATCH-ALL)" nil nil)
-
+(fn &optional GROUPS NO-CROSSPOST CATCH-ALL)" nil nil)
(register-definition-prefixes "gnus-mlspl" '("gnus-group-split-"))
-;;;***
-;;;### (autoloads nil "gnus-msg" "gnus/gnus-msg.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-msg.el
(autoload 'gnus-msg-mail "gnus-msg" "\
@@ -15067,26 +13758,19 @@ Gcc: header for archiving purposes.
If Gnus isn't running, a plain `message-mail' setup is used
instead.
-\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-ACTION YANK-ACTION SEND-ACTIONS RETURN-ACTION)" t nil)
-
+(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-ACTION YANK-ACTION SEND-ACTIONS RETURN-ACTION)" t nil)
(autoload 'gnus-button-mailto "gnus-msg" "\
Mail to ADDRESS.
-\(fn ADDRESS)" nil nil)
-
+(fn ADDRESS)" nil nil)
(autoload 'gnus-button-reply "gnus-msg" "\
Like `message-reply'.
-\(fn &optional TO-ADDRESS WIDE)" t nil)
-
+(fn &optional TO-ADDRESS WIDE)" t nil)
(define-mail-user-agent 'gnus-user-agent 'gnus-msg-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook)
-
(register-definition-prefixes "gnus-msg" '(":prefix" "gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-notifications" "gnus/gnus-notifications.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from gnus/gnus-notifications.el
(autoload 'gnus-notifications "gnus-notifications" "\
@@ -15097,31 +13781,23 @@ notification using `notifications-notify' for it.
This is typically a function to add in
`gnus-after-getting-new-news-hook'" nil nil)
-
(register-definition-prefixes "gnus-notifications" '("gnus-notifications-"))
-;;;***
-;;;### (autoloads nil "gnus-picon" "gnus/gnus-picon.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-picon.el
(autoload 'gnus-treat-from-picon "gnus-picon" "\
Display picons in the From header.
If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil)
-
(autoload 'gnus-treat-mail-picon "gnus-picon" "\
Display picons in the Cc and To headers.
If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil)
-
(autoload 'gnus-treat-newsgroups-picon "gnus-picon" "\
Display picons in the Newsgroups and Followup-To headers.
If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil)
-
(register-definition-prefixes "gnus-picon" '("gnus-picon-"))
-;;;***
-;;;### (autoloads nil "gnus-range" "gnus/gnus-range.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-range.el
(autoload 'gnus-sorted-difference "gnus-range" "\
@@ -15129,238 +13805,172 @@ Return a list of elements of LIST1 that do not appear in LIST2.
Both lists have to be sorted over <.
The tail of LIST1 is not copied.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-sorted-ndifference "gnus-range" "\
Return a list of elements of LIST1 that do not appear in LIST2.
Both lists have to be sorted over <.
LIST1 is modified.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-sorted-complement "gnus-range" "\
Return a list of elements that are in LIST1 or LIST2 but not both.
Both lists have to be sorted over <.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-intersection "gnus-range" "\
-\(fn LIST1 LIST2)" nil nil)
-
-(make-obsolete 'gnus-intersection 'seq-intersection '"28.1")
-
+(fn LIST1 LIST2)" nil nil)
+(make-obsolete 'gnus-intersection 'seq-intersection "28.1")
(autoload 'gnus-sorted-intersection "gnus-range" "\
Return intersection of LIST1 and LIST2.
LIST1 and LIST2 have to be sorted over <.
-\(fn LIST1 LIST2)" nil nil)
-
-(autoload 'gnus-sorted-range-intersection "gnus-range" "\
-Return intersection of RANGE1 and RANGE2.
-RANGE1 and RANGE2 have to be sorted over <.
-
-\(fn RANGE1 RANGE2)" nil nil)
-
-(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection)
-
+(fn LIST1 LIST2)" nil nil)
+(defalias 'gnus-set-sorted-intersection #'gnus-sorted-nintersection)
(autoload 'gnus-sorted-nintersection "gnus-range" "\
Return intersection of LIST1 and LIST2 by modifying cdr pointers of LIST1.
LIST1 and LIST2 have to be sorted over <.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-sorted-union "gnus-range" "\
Return union of LIST1 and LIST2.
LIST1 and LIST2 have to be sorted over <.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-sorted-nunion "gnus-range" "\
Return union of LIST1 and LIST2 by modifying cdr pointers of LIST1.
LIST1 and LIST2 have to be sorted over <.
-\(fn LIST1 LIST2)" nil nil)
-
+(fn LIST1 LIST2)" nil nil)
(autoload 'gnus-add-to-sorted-list "gnus-range" "\
Add NUM into sorted LIST by side effect.
-\(fn LIST NUM)" nil nil)
-
+(fn LIST NUM)" nil nil)
(register-definition-prefixes "gnus-range" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-registry" "gnus/gnus-registry.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from gnus/gnus-registry.el
(autoload 'gnus-registry-initialize "gnus-registry" "\
Initialize the Gnus registry." t nil)
-
(register-definition-prefixes "gnus-registry" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-rfc1843" "gnus/gnus-rfc1843.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from gnus/gnus-rfc1843.el
(register-definition-prefixes "gnus-rfc1843" '("rfc1843-"))
-;;;***
-;;;### (autoloads nil "gnus-rmail" "gnus/gnus-rmail.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-rmail.el
(register-definition-prefixes "gnus-rmail" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-salt" "gnus/gnus-salt.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-salt.el
(register-definition-prefixes "gnus-salt" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-score" "gnus/gnus-score.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-score.el
(register-definition-prefixes "gnus-score" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-search" "gnus/gnus-search.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from gnus/gnus-search.el
(register-definition-prefixes "gnus-search" '("gnus-search-"))
-;;;***
-;;;### (autoloads nil "gnus-sieve" "gnus/gnus-sieve.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-sieve.el
(autoload 'gnus-sieve-update "gnus-sieve" "\
Update the Sieve script in gnus-sieve-file, by replacing the region
between gnus-sieve-region-start and gnus-sieve-region-end with
-\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost), then
+(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost), then
execute gnus-sieve-update-shell-command.
See the documentation for these variables and functions for details." t nil)
-
(autoload 'gnus-sieve-generate "gnus-sieve" "\
Generate the Sieve script in gnus-sieve-file, by replacing the region
between gnus-sieve-region-start and gnus-sieve-region-end with
-\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost).
+(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost).
See the documentation for these variables and functions for details." t nil)
-
(autoload 'gnus-sieve-article-add-rule "gnus-sieve" nil '(gnus-article-mode gnus-summary-mode) nil)
-
(register-definition-prefixes "gnus-sieve" '("gnus-sieve-"))
-;;;***
-;;;### (autoloads nil "gnus-spec" "gnus/gnus-spec.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-spec.el
(autoload 'gnus-update-format "gnus-spec" "\
Update the format specification near point.
-\(fn VAR)" t nil)
-
+(fn VAR)" t nil)
(register-definition-prefixes "gnus-spec" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-srvr" "gnus/gnus-srvr.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-srvr.el
(register-definition-prefixes "gnus-srvr" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-start" "gnus/gnus-start.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-start.el
(autoload 'gnus-declare-backend "gnus-start" "\
Declare back end NAME with ABILITIES as a Gnus back end.
-\(fn NAME &rest ABILITIES)" nil nil)
-
+(fn NAME &rest ABILITIES)" nil nil)
(register-definition-prefixes "gnus-start" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-sum" "gnus/gnus-sum.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-sum.el
(autoload 'gnus-summary-bookmark-jump "gnus-sum" "\
Handler function for record returned by `gnus-summary-bookmark-make-record'.
BOOKMARK is a bookmark name or a bookmark record.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "gnus-sum" '(":keymap" "gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-topic" "gnus/gnus-topic.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-topic.el
(register-definition-prefixes "gnus-topic" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-undo" "gnus/gnus-undo.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-undo.el
(register-definition-prefixes "gnus-undo" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-util" "gnus/gnus-util.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-util.el
(register-definition-prefixes "gnus-util" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-uu" "gnus/gnus-uu.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-uu.el
(register-definition-prefixes "gnus-uu" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-vm" "gnus/gnus-vm.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-vm.el
(register-definition-prefixes "gnus-vm" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnus-win" "gnus/gnus-win.el" (0 0 0 0))
;;; Generated autoloads from gnus/gnus-win.el
(autoload 'gnus-add-configuration "gnus-win" "\
Add the window configuration CONF to `gnus-buffer-configuration'.
-\(fn CONF)" nil nil)
-
+(fn CONF)" nil nil)
(register-definition-prefixes "gnus-win" '("gnus-"))
-;;;***
-;;;### (autoloads nil "gnutls" "net/gnutls.el" (0 0 0 0))
;;; Generated autoloads from net/gnutls.el
(register-definition-prefixes "gnutls" '("gnutls-" "open-gnutls-stream"))
-;;;***
-;;;### (autoloads nil "gomoku" "play/gomoku.el" (0 0 0 0))
;;; Generated autoloads from play/gomoku.el
(autoload 'gomoku "gomoku" "\
@@ -15382,13 +13992,10 @@ Gomoku game, and ought to be upgraded to use the full modern rules.
Use \\[describe-mode] for more info.
-\(fn &optional N M)" t nil)
-
+(fn &optional N M)" t nil)
(register-definition-prefixes "gomoku" '("gomoku-"))
-;;;***
-;;;### (autoloads nil "goto-addr" "net/goto-addr.el" (0 0 0 0))
;;; Generated autoloads from net/goto-addr.el
(autoload 'goto-address-at-point "goto-addr" "\
@@ -15397,8 +14004,7 @@ Send mail to address at point. See documentation for
`goto-address-find-address-at-point'. If no address is found
there, then load the URL at or before point.
-\(fn &optional EVENT)" t nil)
-
+(fn &optional EVENT)" t nil)
(autoload 'goto-address "goto-addr" "\
Sets up goto-address functionality in the current buffer.
Allows user to use mouse/keyboard command to click to go to a URL
@@ -15409,28 +14015,25 @@ only on URLs and e-mail addresses.
Also fontifies the buffer appropriately (see `goto-address-fontify-p' and
`goto-address-highlight-p' for more information)." t nil)
(put 'goto-address 'safe-local-eval-function t)
-
(autoload 'goto-address-mode "goto-addr" "\
Minor mode to buttonize URLs and e-mail addresses in the current buffer.
This is a minor mode. If called interactively, toggle the
-`Goto-Address mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+`Goto-Address mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `goto-address-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(put 'global-goto-address-mode 'globalized-minor-mode t)
-
(defvar global-goto-address-mode nil "\
Non-nil if Global Goto-Address mode is enabled.
See the `global-goto-address-mode' command
@@ -15438,9 +14041,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-goto-address-mode'.")
-
(custom-autoload 'global-goto-address-mode "goto-addr" nil)
-
(autoload 'global-goto-address-mode "goto-addr" "\
Toggle Goto-Address mode in all buffers.
With prefix ARG, enable Global Goto-Address mode if ARG is positive;
@@ -15455,32 +14056,52 @@ Goto-Address mode is enabled in all buffers where
See `goto-address-mode' for more information on Goto-Address mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'goto-address-prog-mode "goto-addr" "\
Like `goto-address-mode', but only for comments and strings.
This is a minor mode. If called interactively, toggle the
-`Goto-Address-Prog mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Goto-Address-Prog mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `goto-address-prog-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "goto-addr" '("goto-addr"))
-;;;***
-;;;### (autoloads nil "gravatar" "image/gravatar.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/wisent/grammar.el
+
+(autoload 'wisent-grammar-mode "semantic/wisent/grammar" "\
+Major mode for editing Wisent grammars.
+
+(fn)" t nil)
+(register-definition-prefixes "semantic/wisent/grammar" '("semantic-grammar-" "wisent-"))
+
+
+;;; Generated autoloads from cedet/semantic/bovine/grammar.el
+
+(autoload 'bovine-grammar-mode "semantic/bovine/grammar" "\
+Major mode for editing Bovine grammars.
+
+(fn)" t nil)
+(register-definition-prefixes "semantic/bovine/grammar" '("bovine-" "semantic-grammar-"))
+
+
+;;; Generated autoloads from cedet/semantic/grammar.el
+
+(register-definition-prefixes "semantic/grammar" '("semantic-"))
+
+
;;; Generated autoloads from image/gravatar.el
(autoload 'gravatar-retrieve "gravatar" "\
@@ -15489,27 +14110,21 @@ When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS),
where GRAVATAR is either an image descriptor, or the symbol
`error' if the retrieval failed.
-\(fn MAIL-ADDRESS CALLBACK &optional CBARGS)" nil nil)
-
+(fn MAIL-ADDRESS CALLBACK &optional CBARGS)" nil nil)
(autoload 'gravatar-retrieve-synchronously "gravatar" "\
Synchronously retrieve a gravatar for MAIL-ADDRESS.
Value is either an image descriptor, or the symbol `error' if the
retrieval failed.
-\(fn MAIL-ADDRESS)" nil nil)
-
+(fn MAIL-ADDRESS)" nil nil)
(register-definition-prefixes "gravatar" '("gravatar-"))
-;;;***
-;;;### (autoloads nil "grep" "progmodes/grep.el" (0 0 0 0))
;;; Generated autoloads from progmodes/grep.el
(defvar grep-window-height nil "\
Number of lines in a grep window. If nil, use `compilation-window-height'.")
-
(custom-autoload 'grep-window-height "grep" t)
-
(defvar grep-command nil "\
The default grep command for \\[grep].
If the grep program used supports an option to always include file names
@@ -15519,9 +14134,7 @@ include it when specifying `grep-command'.
In interactive usage, the actual value of this variable is set up
by `grep-compute-defaults'; to change the default value, use
\\[customize] or call the function `grep-apply-setting'.")
-
(custom-autoload 'grep-command "grep" nil)
-
(defvar grep-find-command nil "\
The default find command for \\[grep-find].
In interactive usage, the actual value of this variable is set up
@@ -15532,32 +14145,24 @@ This variable can either be a string, or a cons of the
form (COMMAND . POSITION). In the latter case, COMMAND will be
used as the default command, and point will be placed at POSITION
for easier editing.")
-
(custom-autoload 'grep-find-command "grep" nil)
-
(defvar grep-setup-hook nil "\
List of hook functions run by `grep-process-setup' (see `run-hooks').")
-
(custom-autoload 'grep-setup-hook "grep" t)
-
(defconst grep-regexp-alist `((,(concat "^\\(?:" "\\(?1:[^\0\n]+\\)\\(?3:\0\\)\\(?2:[0-9]+\\):" "\\|" "\\(?1:" "\\(?:[a-zA-Z]:\\)?" "[^\n:]+?[^\n/:]\\):[\11 ]*\\(?2:[1-9][0-9]*\\)[\11 ]*:" "\\)") 1 2 (,(lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face))) (when mbeg (- mbeg beg))))) \, (lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg 1)))))) nil nil (3 '(face nil display ":"))) ("^Binary file \\(.+\\) matches" 1 nil nil 0 1)) "\
Regexp used to match grep hits.
See `compilation-error-regexp-alist' for format details.")
-
(defvar grep-program (purecopy "grep") "\
The default grep program for `grep-command' and `grep-find-command'.
This variable's value takes effect when `grep-compute-defaults' is called.")
-
(defvar find-program (purecopy "find") "\
The default find program.
This is used by commands like `grep-find-command', `find-dired'
and others.")
-
(defvar xargs-program (purecopy "xargs") "\
The default xargs program for `grep-find-command'.
See `grep-find-use-xargs'.
This variable's value takes effect when `grep-compute-defaults' is called.")
-
(defvar grep-find-use-xargs nil "\
How to invoke find and grep.
If `exec', use `find -exec {} ;'.
@@ -15567,31 +14172,24 @@ If `gnu-sort', use `find -print0', `sort -z' and `xargs -0'.
Any other value means to use `find -print' and `xargs'.
This variable's value takes effect when `grep-compute-defaults' is called.")
-
(custom-autoload 'grep-find-use-xargs "grep" nil)
-
(defvar grep-history nil "\
History list for grep.")
-
(defvar grep-find-history nil "\
History list for `grep-find'.")
-
(autoload 'grep-process-setup "grep" "\
Setup compilation variables and buffer for `grep'.
Set up `compilation-exit-message-function' and run `grep-setup-hook'." nil nil)
-
(autoload 'grep-compute-defaults "grep" "\
Compute the defaults for the `grep' command.
The value depends on `grep-command', `grep-template',
`grep-use-null-device', `grep-find-command', `grep-find-template',
-`grep-use-null-filename-separator', `grep-find-use-xargs' and
-`grep-highlight-matches'." nil nil)
-
+`grep-use-null-filename-separator', `grep-find-use-xargs',
+`grep-highlight-matches', and `grep-quoting-style'." nil nil)
(autoload 'grep-mode "grep" "\
Sets `grep-last-buffer' and `compilation-window-height'.
-\(fn)" nil nil)
-
+(fn)" nil nil)
(autoload 'grep "grep" "\
Run Grep with user-specified COMMAND-ARGS.
The output from the command goes to the \"*grep*\" buffer.
@@ -15614,8 +14212,7 @@ tag the cursor is over, substituting it into the last Grep command
in the Grep command history (or into `grep-command' if that history
list is empty).
-\(fn COMMAND-ARGS)" t nil)
-
+(fn COMMAND-ARGS)" t nil)
(autoload 'grep-find "grep" "\
Run grep via find, with user-specified args COMMAND-ARGS.
Collect output in the \"*grep*\" buffer.
@@ -15625,10 +14222,8 @@ to find the text that grep hits refer to.
This command uses a special history list for its arguments, so you can
easily repeat a find command.
-\(fn COMMAND-ARGS)" t nil)
-
-(defalias 'find-grep 'grep-find)
-
+(fn COMMAND-ARGS)" t nil)
+(defalias 'find-grep #'grep-find)
(autoload 'lgrep "grep" "\
Run grep, searching for REGEXP in FILES in directory DIR.
The search is limited to file names matching shell pattern FILES.
@@ -15650,8 +14245,7 @@ This command shares argument histories with \\[rgrep] and \\[grep].
If CONFIRM is non-nil, the user will be given an opportunity to edit the
command before it's run.
-\(fn REGEXP &optional FILES DIR CONFIRM)" t nil)
-
+(fn REGEXP &optional FILES DIR CONFIRM)" t nil)
(autoload 'rgrep "grep" "\
Recursively grep for REGEXP in FILES in directory tree rooted at DIR.
The search is limited to file names matching shell pattern FILES.
@@ -15677,8 +14271,11 @@ to specify a command to run.
If CONFIRM is non-nil, the user will be given an opportunity to edit the
command before it's run.
-\(fn REGEXP &optional FILES DIR CONFIRM)" t nil)
+Interactively, the user can use the \\`M-c' command while entering
+the regexp to indicate whether the grep should be case sensitive
+or not.
+(fn REGEXP &optional FILES DIR CONFIRM)" t nil)
(autoload 'zrgrep "grep" "\
Recursively grep for REGEXP in gzipped FILES in tree rooted at DIR.
Like `rgrep' but uses `zgrep' for `grep-program', sets the default
@@ -15687,22 +14284,21 @@ file name to `*.gz', and sets `grep-highlight-matches' to `always'.
If CONFIRM is non-nil, the user will be given an opportunity to edit the
command before it's run.
-\(fn REGEXP &optional FILES DIR CONFIRM TEMPLATE)" t nil)
+(fn REGEXP &optional FILES DIR CONFIRM TEMPLATE)" t nil)
+(defalias 'rzgrep #'zrgrep)
+(register-definition-prefixes "grep" '("grep-" "kill-grep" "rgrep-"))
-(defalias 'rzgrep 'zrgrep)
+
+;;; Generated autoloads from cedet/semantic/symref/grep.el
-(register-definition-prefixes "grep" '("grep-" "kill-grep" "rgrep-"))
+(register-definition-prefixes "semantic/symref/grep" '("semantic-symref-"))
-;;;***
-;;;### (autoloads nil "gssapi" "gnus/gssapi.el" (0 0 0 0))
;;; Generated autoloads from gnus/gssapi.el
(register-definition-prefixes "gssapi" '("gssapi-program" "open-gssapi-stream"))
-;;;***
-;;;### (autoloads nil "gud" "progmodes/gud.el" (0 0 0 0))
;;; Generated autoloads from progmodes/gud.el
(autoload 'gud-gdb "gud" "\
@@ -15716,22 +14312,19 @@ will run in *gud-PID*, otherwise it will run in *gud*; in these
cases the initial working directory is the `default-directory' of
the buffer in which this command was invoked.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'sdb "gud" "\
Run sdb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'dbx "gud" "\
Run dbx on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'xdb "gud" "\
Run xdb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
@@ -15740,8 +14333,7 @@ and source-file directory for your debugger.
You can set the variable `gud-xdb-directories' to a list of program source
directories if your program contains sources from more than one directory.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'perldb "gud" "\
Debug a perl program with gud.
Interactively, this will prompt you for a command line.
@@ -15752,8 +14344,7 @@ Noninteractively, COMMAND-LINE should be on the form
The directory containing the perl program becomes the initial
working directory and source-file directory for your debugger.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'pdb "gud" "\
Run COMMAND-LINE in the `*gud-FILE*' buffer to debug Python programs.
@@ -15765,15 +14356,13 @@ If called interactively, the command line will be prompted for.
The directory containing this file becomes the initial working
directory and source-file directory for your debugger.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'guiler "gud" "\
Run guiler on program FILE in buffer `*gud-FILE*'.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'jdb "gud" "\
Run jdb with command line COMMAND-LINE in a buffer.
The buffer is named \"*gud*\" if no initial class is given or
@@ -15788,13 +14377,11 @@ original source file access method.
For general information about commands available to control jdb from
gud, see `gud-mode'.
-\(fn COMMAND-LINE)" t nil)
-
+(fn COMMAND-LINE)" t nil)
(autoload 'gdb-script-mode "gud" "\
Major mode for editing GDB scripts.
-\(fn)" t nil)
-
+(fn)" t nil)
(defvar gud-tooltip-mode nil "\
Non-nil if Gud-Tooltip mode is enabled.
See the `gud-tooltip-mode' command
@@ -15802,33 +14389,28 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `gud-tooltip-mode'.")
-
(custom-autoload 'gud-tooltip-mode "gud" nil)
-
(autoload 'gud-tooltip-mode "gud" "\
Toggle the display of GUD tooltips.
-This is a minor mode. If called interactively, toggle the
-`Gud-Tooltip mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Gud-Tooltip mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='gud-tooltip-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "gud" '("gdb-" "gud-"))
-;;;***
-;;;### (autoloads nil "gv" "emacs-lisp/gv.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/gv.el
(autoload 'gv-get "gv" "\
@@ -15841,8 +14423,7 @@ with a (not necessarily copyable) Elisp expression that returns the value to
set it to.
DO must return an Elisp expression.
-\(fn PLACE DO)" nil nil)
-
+(fn PLACE DO)" nil nil)
(autoload 'gv-letplace "gv" "\
Build the code manipulating the generalized variable PLACE.
GETTER will be bound to a copyable expression that returns the value
@@ -15854,35 +14435,25 @@ and SETTER.
The returned value will then be an Elisp expression that first evaluates
all the parts of PLACE that can be evaluated and then runs E.
-\(fn (GETTER SETTER) PLACE &rest BODY)" nil t)
-
-(function-put 'gv-letplace 'lisp-indent-function '2)
-
+(fn (GETTER SETTER) PLACE &rest BODY)" nil t)
+(function-put 'gv-letplace 'lisp-indent-function 2)
(autoload 'gv-define-expander "gv" "\
Use HANDLER to handle NAME as a generalized var.
NAME is a symbol: the name of a function, macro, or special form.
HANDLER is a function which takes an argument DO followed by the same
arguments as NAME. DO is a function as defined in `gv-get'.
-\(fn NAME HANDLER)" nil t)
-
-(function-put 'gv-define-expander 'lisp-indent-function '1)
-
+(fn NAME HANDLER)" nil t)
+(function-put 'gv-define-expander 'lisp-indent-function 1)
(autoload 'gv--defun-declaration "gv" "\
-\(fn SYMBOL NAME ARGS HANDLER &optional FIX)" nil nil)
-
+(fn SYMBOL NAME ARGS HANDLER &optional FIX)" nil nil)
(defsubst gv--expander-defun-declaration (&rest args) (apply #'gv--defun-declaration 'gv-expander args))
-
(defsubst gv--setter-defun-declaration (&rest args) (apply #'gv--defun-declaration 'gv-setter args))
-
(or (assq 'gv-expander defun-declarations-alist) (let ((x (list 'gv-expander #'gv--expander-defun-declaration))) (push x macro-declarations-alist) (push x defun-declarations-alist)))
-
(or (assq 'gv-setter defun-declarations-alist) (push (list 'gv-setter #'gv--setter-defun-declaration) defun-declarations-alist))
-
(let ((spec (get 'compiler-macro 'edebug-declaration-spec))) (put 'gv-expander 'edebug-declaration-spec spec) (put 'gv-setter 'edebug-declaration-spec spec))
-
(autoload 'gv-define-setter "gv" "\
Define a setter method for generalized variable NAME.
This macro is an easy-to-use substitute for `gv-define-expander' that works
@@ -15895,10 +14466,8 @@ which can do arbitrary things, whereas the other arguments are all guaranteed
to be pure and copyable. Example use:
(gv-define-setter aref (v a i) \\=`(aset ,a ,i ,v))
-\(fn NAME ARGLIST &rest BODY)" nil t)
-
-(function-put 'gv-define-setter 'lisp-indent-function '2)
-
+(fn NAME ARGLIST &rest BODY)" nil t)
+(function-put 'gv-define-setter 'lisp-indent-function 2)
(autoload 'gv-define-simple-setter "gv" "\
Define a simple setter method for generalized variable NAME.
This macro is an easy-to-use substitute for `gv-define-expander' that works
@@ -15912,8 +14481,7 @@ instead the assignment is turned into something equivalent to
temp)
so as to preserve the semantics of `setf'.
-\(fn NAME SETTER &optional FIX-RETURN)" nil t)
-
+(fn NAME SETTER &optional FIX-RETURN)" nil t)
(autoload 'setf "gv" "\
Set each PLACE to the value of its VAL.
This is a generalized version of `setq'; the PLACEs may be symbolic
@@ -15921,10 +14489,8 @@ references such as (car x) or (aref x i), as well as plain symbols.
For example, (setf (cadr x) y) is equivalent to (setcar (cdr x) y).
The return value is the last VAL in the list.
-\(fn PLACE VAL PLACE VAL ...)" nil t)
-
+(fn PLACE VAL PLACE VAL ...)" nil t)
(def-edebug-elem-spec 'gv-place '(form))
-
(autoload 'gv-ref "gv" "\
Return a reference to PLACE.
This is like the `&' operator of the C language.
@@ -15932,13 +14498,10 @@ Note: this only works reliably with lexical binding mode, except for very
simple PLACEs such as (symbol-function \\='foo) which will also work in dynamic
binding mode.
-\(fn PLACE)" nil t)
-
+(fn PLACE)" nil t)
(register-definition-prefixes "gv" '("gv-"))
-;;;***
-;;;### (autoloads nil "handwrite" "play/handwrite.el" (0 0 0 0))
;;; Generated autoloads from play/handwrite.el
(autoload 'handwrite "handwrite" "\
@@ -15950,89 +14513,81 @@ Variables: `handwrite-linespace' (default 12)
`handwrite-fontsize' (default 11)
`handwrite-numlines' (default 60)
`handwrite-pagenumbering' (default nil)" t nil)
-
(register-definition-prefixes "handwrite" '("handwrite-" "menu-bar-handwrite-map"))
-;;;***
-;;;### (autoloads nil "hanja-util" "language/hanja-util.el" (0 0
-;;;;;; 0 0))
+;;; Generated autoloads from leim/quail/hangul.el
+
+(autoload 'hangul-input-method-activate "quail/hangul" "\
+Activate Hangul input method INPUT-METHOD.
+FUNC is a function to handle input key.
+HELP-TEXT is a text set in `hangul-input-method-help-text'.
+
+(fn INPUT-METHOD FUNC HELP-TEXT &rest ARGS)" nil nil)
+(register-definition-prefixes "quail/hangul" '("alphabetp" "hangul" "notzerop"))
+
+
;;; Generated autoloads from language/hanja-util.el
(register-definition-prefixes "hanja-util" '("han"))
-;;;***
-;;;### (autoloads nil "hanoi" "play/hanoi.el" (0 0 0 0))
;;; Generated autoloads from play/hanoi.el
(autoload 'hanoi "hanoi" "\
Towers of Hanoi diversion. Use NRINGS rings.
-\(fn NRINGS)" t nil)
-
+(fn NRINGS)" t nil)
(autoload 'hanoi-unix "hanoi" "\
Towers of Hanoi, UNIX doomsday version.
Displays 32-ring towers that have been progressing at one move per
second since 1970-01-01 00:00:00 GMT.
Repent before ring 31 moves." t nil)
-
(autoload 'hanoi-unix-64 "hanoi" "\
Like `hanoi-unix', but pretend to have a 64-bit clock.
This is, necessarily (as of Emacs 20.3), a crock. When the
`current-time' interface is made s2G-compliant, hanoi.el will need
to be updated." t nil)
-
(register-definition-prefixes "hanoi" '("hanoi-"))
-;;;***
-;;;### (autoloads nil "hashcash" "mail/hashcash.el" (0 0 0 0))
;;; Generated autoloads from mail/hashcash.el
(autoload 'hashcash-insert-payment "hashcash" "\
Insert X-Payment and X-Hashcash headers with a payment for ARG.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'hashcash-insert-payment-async "hashcash" "\
Insert X-Payment and X-Hashcash headers with a payment for ARG
Only start calculation. Results are inserted when ready.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'hashcash-verify-payment "hashcash" "\
Verify a hashcash payment.
-\(fn TOKEN &optional RESOURCE AMOUNT)" nil nil)
-
+(fn TOKEN &optional RESOURCE AMOUNT)" nil nil)
(autoload 'mail-add-payment "hashcash" "\
Add X-Payment: and X-Hashcash: headers with a hashcash payment
for each recipient address. Prefix arg sets default payment temporarily.
Set ASYNC to t to start asynchronous calculation. (See
`mail-add-payment-async').
-\(fn &optional ARG ASYNC)" t nil)
-
+(fn &optional ARG ASYNC)" t nil)
(autoload 'mail-add-payment-async "hashcash" "\
Add X-Payment: and X-Hashcash: headers with a hashcash payment
for each recipient address. Prefix arg sets default payment temporarily.
Calculation is asynchronous.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'mail-check-payment "hashcash" "\
Look for a valid X-Payment: or X-Hashcash: header.
Prefix arg sets default accept amount temporarily.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "hashcash" '("hashcash-"))
-;;;***
-;;;### (autoloads nil "help-at-pt" "help-at-pt.el" (0 0 0 0))
;;; Generated autoloads from help-at-pt.el
(autoload 'help-at-pt-string "help-at-pt" "\
@@ -16043,38 +14598,36 @@ If KBD is non-nil, `kbd-help' is used instead, and any
`help-echo' property is ignored. In this case, the return value
can also be t, if that is the value of the `kbd-help' property.
-\(fn &optional KBD)" nil nil)
-
+(fn &optional KBD)" nil nil)
(autoload 'help-at-pt-kbd-string "help-at-pt" "\
Return the keyboard help string at point.
If the `kbd-help' text or overlay property at point produces a
string, return it. Otherwise, use the `help-echo' property.
If this produces no string either, return nil." nil nil)
-
(autoload 'display-local-help "help-at-pt" "\
Display local help in the echo area.
-This displays a short help message, namely the string produced by
-the `kbd-help' property at point. If `kbd-help' does not produce
-a string, but the `help-echo' property does, then that string is
-printed instead.
+This command, by default, displays a short help message, namely
+the string produced by the `kbd-help' property at point. If
+`kbd-help' does not produce a string, but the `help-echo'
+property does, then that string is printed instead.
The string is passed through `substitute-command-keys' before it
is displayed.
-A numeric argument ARG prevents display of a message in case
-there is no help. While ARG can be used interactively, it is
-mainly meant for use from Lisp.
+If INHIBIT-WARNING is non-nil, this prevents display of a message
+in case there is no help.
-\(fn &optional ARG)" t nil)
+If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and
+there's a button/widget at point, pop a buffer describing that
+button/widget instead.
+(fn &optional INHIBIT-WARNING DESCRIBE-BUTTON)" t nil)
(autoload 'help-at-pt-cancel-timer "help-at-pt" "\
Cancel any timer set by `help-at-pt-set-timer'.
This disables `help-at-pt-display-when-idle'." t nil)
-
(autoload 'help-at-pt-set-timer "help-at-pt" "\
Enable `help-at-pt-display-when-idle'.
This is done by setting a timer, if none is currently active." t nil)
-
(defvar help-at-pt-display-when-idle 'never "\
Automatically show local help on point-over.
If the value is t, the string obtained from any `kbd-help' or
@@ -16105,9 +14658,7 @@ enabling buffer local values. It sets the actual value to nil.
Thus, Custom distinguishes between a nil value and other values
that disable the feature, which Custom identifies with `never'.
The default is `never'.")
-
(custom-autoload 'help-at-pt-display-when-idle "help-at-pt" nil)
-
(autoload 'scan-buf-move-to-region "help-at-pt" "\
Go to the start of the next region with non-nil PROP property.
Then run HOOK, which should be a quoted symbol that is a normal
@@ -16125,8 +14676,7 @@ do not run HOOK. If there are not enough regions to move over,
an error results and the number of available regions is mentioned
in the error message. Point is not moved and HOOK is not run.
-\(fn PROP &optional ARG HOOK)" nil nil)
-
+(fn PROP &optional ARG HOOK)" nil nil)
(autoload 'scan-buf-next-region "help-at-pt" "\
Go to the start of the next region with non-nil help-echo.
Print the help found there using `display-local-help'. Adjacent
@@ -16147,8 +14697,7 @@ help-echo region without any local help being available. This is
because `help-echo' can be a function evaluating to nil. This
rarely happens in practice.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'scan-buf-previous-region "help-at-pt" "\
Go to the start of the previous region with non-nil help-echo.
Print the help found there using `display-local-help'. Adjacent
@@ -16156,13 +14705,10 @@ areas with different non-nil help-echo properties are considered
different regions. With numeric argument ARG, behaves like
`scan-buf-next-region' with argument -ARG.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "help-at-pt" '("help-at-pt-" "scan-buf-move-hook"))
-;;;***
-;;;### (autoloads nil "help-fns" "help-fns.el" (0 0 0 0))
;;; Generated autoloads from help-fns.el
(autoload 'describe-function "help-fns" "\
@@ -16172,21 +14718,18 @@ When called from Lisp, FUNCTION may also be a function object.
See the `help-enable-symbol-autoload' variable for special
handling of autoloaded functions.
-\(fn FUNCTION)" t nil)
-
+(fn FUNCTION)" t nil)
(autoload 'describe-command "help-fns" "\
Display the full documentation of COMMAND (a symbol).
When called from Lisp, COMMAND may also be a function object.
-\(fn COMMAND)" t nil)
-
+(fn COMMAND)" t nil)
(autoload 'help-C-file-name "help-fns" "\
Return the name of the C file where SUBR-OR-VAR is defined.
KIND should be `var' for a variable or `subr' for a subroutine.
If we can't find the file name, nil is returned.
-\(fn SUBR-OR-VAR KIND)" nil nil)
-
+(fn SUBR-OR-VAR KIND)" nil nil)
(autoload 'find-lisp-object-file-name "help-fns" "\
Guess the file that defined the Lisp object OBJECT, of type TYPE.
OBJECT should be a symbol associated with a function, variable, or face;
@@ -16198,32 +14741,33 @@ If TYPE is not a symbol, search for a function definition.
The return value is the absolute name of a readable file where OBJECT is
defined. If several such files exist, preference is given to a file
found via `load-path'. The return value can also be `C-source', which
-means that OBJECT is a function or variable defined in C. If no
-suitable file is found, return nil.
+means that OBJECT is a function or variable defined in C, but
+it's currently unknown where. If no suitable file is found,
+return nil.
-\(fn OBJECT TYPE)" nil nil)
+If ALSO-C-SOURCE is non-nil, instead of returning `C-source',
+this function will attempt to locate the definition of OBJECT in
+the C sources, too.
+(fn OBJECT TYPE &optional ALSO-C-SOURCE)" nil nil)
(autoload 'describe-function-1 "help-fns" "\
-\(fn FUNCTION)" nil nil)
-
+(fn FUNCTION)" nil nil)
(autoload 'variable-at-point "help-fns" "\
Return the bound variable symbol found at or before point.
Return 0 if there is no such symbol.
If ANY-SYMBOL is non-nil, don't insist the symbol be bound.
-\(fn &optional ANY-SYMBOL)" nil nil)
-
+(fn &optional ANY-SYMBOL)" nil nil)
(autoload 'describe-variable "help-fns" "\
Display the full documentation of VARIABLE (a symbol).
Returns the documentation as a string, also.
If VARIABLE has a buffer-local value in BUFFER or FRAME
-\(default to the current buffer and current frame),
+(default to the current buffer and current frame),
it is displayed along with the global value.
-\(fn VARIABLE &optional BUFFER FRAME)" t nil)
-
+(fn VARIABLE &optional BUFFER FRAME)" t nil)
(autoload 'describe-face "help-fns" "\
Display the properties of face FACE on FRAME.
Interactively, FACE defaults to the faces of the character after point
@@ -16233,8 +14777,7 @@ If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.
-\(fn FACE &optional FRAME)" t nil)
-
+(fn FACE &optional FRAME)" t nil)
(autoload 'describe-symbol "help-fns" "\
Display the full documentation of SYMBOL.
Will show the info of SYMBOL as a function, variable, and/or face.
@@ -16242,30 +14785,26 @@ Optional arguments BUFFER and FRAME specify for which buffer and
frame to show the information about SYMBOL; they default to the
current buffer and the selected frame, respectively.
-\(fn SYMBOL &optional BUFFER FRAME)" t nil)
-
+(fn SYMBOL &optional BUFFER FRAME)" t nil)
(autoload 'describe-syntax "help-fns" "\
Describe the syntax specifications in the syntax table of BUFFER.
The descriptions are inserted in a help buffer, which is then displayed.
BUFFER defaults to the current buffer.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'describe-categories "help-fns" "\
Describe the category specifications in the current category table.
The descriptions are inserted in a buffer, which is then displayed.
If BUFFER is non-nil, then describe BUFFER's category table instead.
BUFFER should be a buffer or a buffer name.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'describe-keymap "help-fns" "\
Describe key bindings in KEYMAP.
When called interactively, prompt for a variable that has a
keymap value.
-\(fn KEYMAP)" t nil)
-
+(fn KEYMAP)" t nil)
(autoload 'describe-mode "help-fns" "\
Display documentation of current major mode and minor modes.
A brief summary of the minor modes comes first, followed by the
@@ -16279,8 +14818,7 @@ whose documentation describes the minor mode.
If called from Lisp with a non-nil BUFFER argument, display
documentation for the major and minor modes of that buffer.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'describe-widget "help-fns" "\
Display a buffer with information about a widget.
You can use this command to describe buttons (e.g., the links in a *Help*
@@ -16294,23 +14832,18 @@ When called from Lisp, POS may be a buffer position or a mouse position list.
Calls each function of the list `describe-widget-functions' in turn, until
one of them returns non-nil.
-\(fn &optional POS)" t nil)
-
+(fn &optional POS)" t nil)
(autoload 'doc-file-to-man "help-fns" "\
Produce an nroff buffer containing the doc-strings from the DOC file.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'doc-file-to-info "help-fns" "\
Produce a texinfo buffer with sorted doc-strings from the DOC file.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(register-definition-prefixes "help-fns" '("describe-" "help-" "keymap-name-history"))
-;;;***
-;;;### (autoloads nil "help-macro" "help-macro.el" (0 0 0 0))
;;; Generated autoloads from help-macro.el
(defvar three-step-help nil "\
@@ -16319,35 +14852,30 @@ The three steps are simple prompt, prompt with all options, and
window listing and describing the options.
A value of nil means skip the middle step, so that \\[help-command] \\[help-command]
gives the window that lists the options.")
-
(custom-autoload 'three-step-help "help-macro" t)
-
(register-definition-prefixes "help-macro" '("make-help-screen"))
-;;;***
-;;;### (autoloads nil "help-mode" "help-mode.el" (0 0 0 0))
;;; Generated autoloads from help-mode.el
(autoload 'help-mode--add-function-link "help-mode" "\
-\(fn STR FUN)" nil nil)
-
+(fn STR FUN)" nil nil)
(autoload 'help-mode "help-mode" "\
Major mode for viewing help text and navigating references in it.
-Entry to this mode runs the normal hook `help-mode-hook'.
+Also see the `help-enable-variable-value-editing' variable.
+
Commands:
\\{help-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'help-mode-setup "help-mode" "\
Enter Help mode in the current buffer." nil nil)
-
+(make-obsolete 'help-mode-setup 'nil "29.1")
(autoload 'help-mode-finish "help-mode" "\
Finalize Help mode setup in current buffer." nil nil)
-
+(make-obsolete 'help-mode-finish 'nil "29.1")
(autoload 'help-setup-xref "help-mode" "\
Invoked from commands using the \"*Help*\" buffer to install some xref info.
@@ -16360,16 +14888,14 @@ This should be called very early, before the output buffer is cleared,
because we want to record the \"previous\" position of point so we can
restore it properly when going back.
-\(fn ITEM INTERACTIVE-P)" nil nil)
-
+(fn ITEM INTERACTIVE-P)" nil nil)
(autoload 'help-buffer "help-mode" "\
Return the name of a buffer for inserting help.
-If `help-xref-following' is non-nil, this is the name of the
-current buffer. Signal an error if this buffer is not derived
-from `help-mode'.
+If `help-xref-following' is non-nil and the current buffer is
+derived from `help-mode', this is the name of the current buffer.
+
Otherwise, return \"*Help*\", creating a buffer with that name if
it does not already exist." nil nil)
-
(autoload 'help-make-xrefs "help-mode" "\
Parse and hyperlink documentation cross-references in the given BUFFER.
@@ -16384,15 +14910,14 @@ preceded by the word `variable' or `option'.
If the variable `help-xref-mule-regexp' is non-nil, find also
cross-reference information related to multilingual environment
-\(e.g., coding-systems). This variable is also used to disambiguate
+(e.g., coding-systems). This variable is also used to disambiguate
the type of reference as the same way as `help-xref-symbol-regexp'.
A special reference `back' is made to return back through a stack of
help buffers. Variable `help-back-label' specifies the text for
that.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'help-xref-button "help-mode" "\
Make a hyperlink for cross-reference text previously matched.
MATCH-NUMBER is the subexpression of interest in the last matched
@@ -16400,55 +14925,45 @@ regexp. TYPE is the type of button to use. Any remaining arguments are
passed to the button's help-function when it is invoked.
See `help-make-xrefs'.
-\(fn MATCH-NUMBER TYPE &rest ARGS)" nil nil)
+This function removes quotes surrounding the match if the
+variable `help-clean-buttons' is non-nil.
+(fn MATCH-NUMBER TYPE &rest ARGS)" nil nil)
(autoload 'help-insert-xref-button "help-mode" "\
Insert STRING and make a hyperlink from cross-reference text on it.
TYPE is the type of button to use. Any remaining arguments are passed
to the button's help-function when it is invoked.
See `help-make-xrefs'.
-\(fn STRING TYPE &rest ARGS)" nil nil)
-
+(fn STRING TYPE &rest ARGS)" nil nil)
(autoload 'help-xref-on-pp "help-mode" "\
Add xrefs for symbols in `pp's output between FROM and TO.
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "25.1")
-
(autoload 'help-bookmark-jump "help-mode" "\
Jump to `help-mode' bookmark BOOKMARK.
Handler function for record returned by `help-bookmark-make-record'.
BOOKMARK is a bookmark name or a bookmark record.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "help-mode" '("describe-symbol-backends" "help-"))
-;;;***
-;;;### (autoloads nil "helper" "emacs-lisp/helper.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/helper.el
(autoload 'Helper-describe-bindings "helper" "\
Describe local key bindings of current mode." t nil)
-
(autoload 'Helper-help "helper" "\
Provide help for current mode." t nil)
-
(register-definition-prefixes "helper" '("Helper-"))
-;;;***
-;;;### (autoloads nil "hex-util" "hex-util.el" (0 0 0 0))
;;; Generated autoloads from hex-util.el
(register-definition-prefixes "hex-util" '("decode-hex-string" "encode-hex-string"))
-;;;***
-;;;### (autoloads nil "hexl" "hexl.el" (0 0 0 0))
;;; Generated autoloads from hexl.el
(autoload 'hexl-mode "hexl" "\
@@ -16533,43 +15048,40 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode.
\\[describe-bindings] for advanced commands.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'hexl-find-file "hexl" "\
Edit file FILENAME as a binary file in hex dump format.
Switch to a buffer visiting file FILENAME, creating one if none exists,
and edit the file in `hexl-mode'. The buffer's coding-system will be
no-conversion, unlike if you visit it normally and then invoke `hexl-mode'.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'hexlify-buffer "hexl" "\
Convert a binary buffer to hexl format.
This discards the buffer's undo information." t nil)
-
(register-definition-prefixes "hexl" '("dehexlify-buffer" "hexl-"))
-;;;***
-;;;### (autoloads nil "hi-lock" "hi-lock.el" (0 0 0 0))
-;;; Generated autoloads from hi-lock.el
+;;; Generated autoloads from hfy-cmap.el
-(autoload 'hi-lock-mode "hi-lock" "\
-Toggle selective highlighting of patterns (Hi Lock mode).
+(autoload 'htmlfontify-load-rgb-file "hfy-cmap" "\
+Load an X11 style rgb.txt FILE.
+Search `hfy-rgb-load-path' if FILE is not specified.
+Loads the variable `hfy-rgb-txt-color-map', which is used by
+`hfy-fallback-color-values'.
-This is a minor mode. If called interactively, toggle the `Hi-Lock
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+(fn &optional FILE)" t nil)
+(autoload 'hfy-fallback-color-values "hfy-cmap" "\
+Use a fallback method for obtaining the rgb values for a color.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+(fn COLOR-STRING)" nil nil)
+(register-definition-prefixes "hfy-cmap" '("hfy-" "htmlfontify-unload-rgb-file"))
-To check whether the minor mode is enabled in the current buffer,
-evaluate `hi-lock-mode'.
+
+;;; Generated autoloads from hi-lock.el
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+(autoload 'hi-lock-mode "hi-lock" "\
+Toggle selective highlighting of patterns (Hi Lock mode).
Hi Lock mode is automatically enabled when you invoke any of the
highlighting commands listed below, such as \\[highlight-regexp].
@@ -16631,10 +15143,22 @@ position (number of characters into buffer)
Hi-lock: end is found. A mode is excluded if it's in the list
`hi-lock-exclude-modes'.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Hi-Lock mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
-(put 'global-hi-lock-mode 'globalized-minor-mode t)
+To check whether the minor mode is enabled in the current buffer,
+evaluate `hi-lock-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
+(put 'global-hi-lock-mode 'globalized-minor-mode t)
(defvar global-hi-lock-mode nil "\
Non-nil if Global Hi-Lock mode is enabled.
See the `global-hi-lock-mode' command
@@ -16642,9 +15166,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-hi-lock-mode'.")
-
(custom-autoload 'global-hi-lock-mode "hi-lock" nil)
-
(autoload 'global-hi-lock-mode "hi-lock" "\
Toggle Hi-Lock mode in all buffers.
With prefix ARG, enable Global Hi-Lock mode if ARG is positive;
@@ -16659,10 +15181,8 @@ Hi-Lock mode is enabled in all buffers where
See `hi-lock-mode' for more information on Hi-Lock mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(defalias 'highlight-lines-matching-regexp 'hi-lock-line-face-buffer)
-
(autoload 'hi-lock-line-face-buffer "hi-lock" "\
Highlight all lines that match REGEXP using FACE.
The lines that match REGEXP will be displayed by merging
@@ -16679,10 +15199,8 @@ Use Font lock mode, if enabled, to highlight REGEXP. Otherwise,
use overlays for highlighting. If overlays are used, the
highlighting will not update as you type.
-\(fn REGEXP &optional FACE)" t nil)
-
+(fn REGEXP &optional FACE)" t nil)
(defalias 'highlight-regexp 'hi-lock-face-buffer)
-
(autoload 'hi-lock-face-buffer "hi-lock" "\
Set face of each match of REGEXP to FACE.
Interactively, prompt for REGEXP using `read-regexp', then FACE.
@@ -16704,10 +15222,8 @@ is considered \"enabled\" in a buffer if its `major-mode'
causes `font-lock-specified-p' to return non-nil, which means
the major mode specifies support for Font Lock.
-\(fn REGEXP &optional FACE SUBEXP LIGHTER)" t nil)
-
+(fn REGEXP &optional FACE SUBEXP LIGHTER)" t nil)
(defalias 'highlight-phrase 'hi-lock-face-phrase-buffer)
-
(autoload 'hi-lock-face-phrase-buffer "hi-lock" "\
Set face of each match of phrase REGEXP to FACE.
Interactively, prompt for REGEXP using `read-regexp', then FACE.
@@ -16724,10 +15240,8 @@ is considered \"enabled\" in a buffer if its `major-mode'
causes `font-lock-specified-p' to return non-nil, which means
the major mode specifies support for Font Lock.
-\(fn REGEXP &optional FACE)" t nil)
-
+(fn REGEXP &optional FACE)" t nil)
(defalias 'highlight-symbol-at-point 'hi-lock-face-symbol-at-point)
-
(autoload 'hi-lock-face-symbol-at-point "hi-lock" "\
Highlight each instance of the symbol at point.
Uses the next face from `hi-lock-face-defaults' without prompting,
@@ -16742,9 +15256,7 @@ in which case the highlighting will not update as you type. The Font
Lock mode is considered \"enabled\" in a buffer if its `major-mode'
causes `font-lock-specified-p' to return non-nil, which means
the major mode specifies support for Font Lock." t nil)
-
(defalias 'unhighlight-regexp 'hi-lock-unface-buffer)
-
(autoload 'hi-lock-unface-buffer "hi-lock" "\
Remove highlighting of each match to REGEXP set by hi-lock.
Interactively, prompt for REGEXP, accepting only regexps
@@ -16752,42 +15264,27 @@ previously inserted by hi-lock interactive functions.
If REGEXP is t (or if \\[universal-argument] was specified interactively),
then remove all hi-lock highlighting.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'hi-lock-write-interactive-patterns "hi-lock" "\
Write interactively added patterns, if any, into buffer at point.
Interactively added patterns are those normally specified using
`highlight-regexp' and `highlight-lines-matching-regexp'; they can
be found in variable `hi-lock-interactive-patterns'." t nil)
-
(autoload 'hi-lock-find-patterns "hi-lock" "\
Add patterns from the current buffer to the list of hi-lock patterns." t nil)
+(autoload 'hi-lock-context-menu "hi-lock" "\
+Populate MENU with a menu item to highlight symbol at CLICK.
-(register-definition-prefixes "hi-lock" '("hi-lock-" "turn-on-hi-lock-if-enabled"))
+(fn MENU CLICK)" nil nil)
+(register-definition-prefixes "hi-lock" '("hi-lock-" "highlight-symbol-at-mouse" "turn-on-hi-lock-if-enabled"))
-;;;***
-;;;### (autoloads nil "hideif" "progmodes/hideif.el" (0 0 0 0))
;;; Generated autoloads from progmodes/hideif.el
(autoload 'hide-ifdef-mode "hideif" "\
Toggle features to hide/show #ifdef blocks (Hide-Ifdef mode).
-This is a minor mode. If called interactively, toggle the `Hide-Ifdef
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `hide-ifdef-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Hide-Ifdef mode is a buffer-local minor mode for use with C and
C-like major modes. When enabled, code within #ifdef constructs
that the C preprocessor would eliminate may be hidden from view.
@@ -16822,13 +15319,24 @@ Several variables affect how the hiding is done:
\\{hide-ifdef-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Hide-Ifdef mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `hide-ifdef-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "hideif" '("backward-ifdef" "down-ifdef" "forward-ifdef" "hide-ifdef" "hif-" "intern-safe" "next-ifdef" "previous-ifdef" "show-ifdef" "up-ifdef"))
-;;;***
-;;;### (autoloads nil "hideshow" "progmodes/hideshow.el" (0 0 0 0))
;;; Generated autoloads from progmodes/hideshow.el
(defvar hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil))) "\
@@ -16858,24 +15366,9 @@ use of ADJUST-BEG-FUNC.
If any of the elements is left nil or omitted, hideshow tries to guess
appropriate values. The regexps should not contain leading or trailing
whitespace. Case does not matter.")
-
(autoload 'hs-minor-mode "hideshow" "\
Minor mode to selectively hide/show code and comment blocks.
-This is a minor mode. If called interactively, toggle the `hs minor
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `hs-minor-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When hideshow minor mode is on, the menu bar is augmented with hideshow
commands and the hideshow commands are enabled.
The value (hs . t) is added to `buffer-invisibility-spec'.
@@ -16892,43 +15385,36 @@ Lastly, the normal hook `hs-minor-mode-hook' is run using `run-hooks'.
Key bindings:
\\{hs-minor-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the `hs
+minor mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `hs-minor-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'turn-off-hideshow "hideshow" "\
Unconditionally turn off `hs-minor-mode'." nil nil)
-
(register-definition-prefixes "hideshow" '("hs-"))
-;;;***
-;;;### (autoloads nil "hierarchy" "emacs-lisp/hierarchy.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/hierarchy.el
(register-definition-prefixes "hierarchy" '("hierarchy-"))
-;;;***
-;;;### (autoloads nil "hilit-chg" "hilit-chg.el" (0 0 0 0))
;;; Generated autoloads from hilit-chg.el
(autoload 'highlight-changes-mode "hilit-chg" "\
Toggle highlighting changes in this buffer (Highlight Changes mode).
-This is a minor mode. If called interactively, toggle the
-`Highlight-Changes mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `highlight-changes-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Highlight Changes is enabled, changes are marked with a text
property. Normally they are displayed in a distinctive face, but
command \\[highlight-changes-visible-mode] can be used to toggle
@@ -16944,25 +15430,24 @@ through various faces.
buffer with the contents of a file
\\[highlight-compare-buffers] highlights differences between two buffers.
-\(fn &optional ARG)" t nil)
-
-(autoload 'highlight-changes-visible-mode "hilit-chg" "\
-Toggle visibility of highlighting due to Highlight Changes mode.
-
This is a minor mode. If called interactively, toggle the
-`Highlight-Changes-Visible mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
+`Highlight-Changes mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
-evaluate `highlight-changes-visible-mode'.
+evaluate `highlight-changes-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+(fn &optional ARG)" t nil)
+(autoload 'highlight-changes-visible-mode "hilit-chg" "\
+Toggle visibility of highlighting due to Highlight Changes mode.
Highlight Changes Visible mode only has an effect when Highlight
Changes mode is on. When enabled, the changed text is displayed
@@ -16973,22 +15458,33 @@ The default value can be customized with variable
This command does not itself set Highlight Changes mode.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Highlight-Changes-Visible mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `highlight-changes-visible-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'highlight-changes-remove-highlight "hilit-chg" "\
Remove the change face from the region between BEG and END.
This allows you to manually remove highlighting from uninteresting changes.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'highlight-changes-next-change "hilit-chg" "\
Move to the beginning of the next change, if in Highlight Changes mode." t nil)
-
(autoload 'highlight-changes-previous-change "hilit-chg" "\
Move to the beginning of the previous change, if in Highlight Changes mode." t nil)
-
(autoload 'highlight-changes-rotate-faces "hilit-chg" "\
-Rotate the faces if in Highlight Changes mode and the changes are visible.
+\"Age\" changes if in Highlight Changes mode and the changes are visible.
Current changes are displayed in the face described by the first element
of `highlight-changes-face-list', one level older changes are shown in
@@ -17000,7 +15496,6 @@ this function to `write-file-functions' as a buffer-local value. To do
this, eval the following in the buffer to be saved:
(add-hook \\='write-file-functions \\='highlight-changes-rotate-faces nil t)" t nil)
-
(autoload 'highlight-compare-buffers "hilit-chg" "\
Compare two buffers and highlight the differences.
@@ -17016,8 +15511,7 @@ If a buffer is read-only, differences will be highlighted but no property
changes are made, so \\[highlight-changes-next-change] and
\\[highlight-changes-previous-change] will not work.
-\(fn BUF-A BUF-B)" t nil)
-
+(fn BUF-A BUF-B)" t nil)
(autoload 'highlight-compare-with-file "hilit-chg" "\
Compare this buffer with a file, and highlight differences.
@@ -17032,10 +15526,8 @@ If the buffer is read-only, differences will be highlighted but no property
changes are made, so \\[highlight-changes-next-change] and
\\[highlight-changes-previous-change] will not work.
-\(fn FILE-B)" t nil)
-
+(fn FILE-B)" t nil)
(put 'global-highlight-changes-mode 'globalized-minor-mode t)
-
(defvar global-highlight-changes-mode nil "\
Non-nil if Global Highlight-Changes mode is enabled.
See the `global-highlight-changes-mode' command
@@ -17043,9 +15535,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-highlight-changes-mode'.")
-
(custom-autoload 'global-highlight-changes-mode "hilit-chg" nil)
-
(autoload 'global-highlight-changes-mode "hilit-chg" "\
Toggle Highlight-Changes mode in all buffers.
With prefix ARG, enable Global Highlight-Changes mode if ARG is
@@ -17061,22 +15551,17 @@ Highlight-Changes mode is enabled in all buffers where
See `highlight-changes-mode' for more information on Highlight-Changes
mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "hilit-chg" '("highlight-" "hilit-chg-"))
-;;;***
-;;;### (autoloads nil "hippie-exp" "hippie-exp.el" (0 0 0 0))
;;; Generated autoloads from hippie-exp.el
(defvar hippie-expand-try-functions-list '(try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol) "\
The list of expansion functions tried in order by `hippie-expand'.
To change the behavior of `hippie-expand', remove, change the order of,
or insert functions in this list.")
-
(custom-autoload 'hippie-expand-try-functions-list "hippie-exp" t)
-
(autoload 'hippie-expand "hippie-exp" "\
Try to expand text before point, using multiple methods.
The expansion functions in `hippie-expand-try-functions-list' are
@@ -17087,39 +15572,21 @@ With a positive numeric argument, jumps directly to the ARG next
function in this list. With a negative argument or just \\[universal-argument],
undoes the expansion.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'make-hippie-expand-function "hippie-exp" "\
Construct a function similar to `hippie-expand'.
Make it use the expansion functions in TRY-LIST. An optional second
argument VERBOSE non-nil makes the function verbose.
-\(fn TRY-LIST &optional VERBOSE)" nil nil)
-
+(fn TRY-LIST &optional VERBOSE)" nil nil)
(register-definition-prefixes "hippie-exp" '("he-" "hippie-expand-" "try-"))
-;;;***
-;;;### (autoloads nil "hl-line" "hl-line.el" (0 0 0 0))
;;; Generated autoloads from hl-line.el
(autoload 'hl-line-mode "hl-line" "\
Toggle highlighting of the current line (Hl-Line mode).
-This is a minor mode. If called interactively, toggle the `Hl-Line
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `hl-line-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Hl-Line mode is a buffer-local minor mode. If
`hl-line-sticky-flag' is non-nil, Hl-Line mode highlights the
line about the buffer's point in all windows. Caveat: the
@@ -17130,8 +15597,21 @@ non-selected window. Hl-Line mode uses the function
When `hl-line-sticky-flag' is nil, Hl-Line mode highlights the
line about point in the selected window only.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Hl-Line mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `hl-line-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(defvar global-hl-line-mode nil "\
Non-nil if Global Hl-Line mode is enabled.
See the `global-hl-line-mode' command
@@ -17139,26 +15619,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-hl-line-mode'.")
-
(custom-autoload 'global-hl-line-mode "hl-line" nil)
-
(autoload 'global-hl-line-mode "hl-line" "\
Toggle line highlighting in all buffers (Global Hl-Line mode).
-This is a minor mode. If called interactively, toggle the `Global
-Hl-Line mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-hl-line-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
If `global-hl-line-sticky-flag' is non-nil, Global Hl-Line mode
highlights the line about the current buffer's point in all live
windows.
@@ -17166,110 +15630,88 @@ windows.
Global-Hl-Line mode uses the function `global-hl-line-highlight'
on `post-command-hook'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Global Hl-Line mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='global-hl-line-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "hl-line" '("global-hl-line-" "hl-line-"))
-;;;***
-;;;### (autoloads nil "hmac-def" "net/hmac-def.el" (0 0 0 0))
;;; Generated autoloads from net/hmac-def.el
(register-definition-prefixes "hmac-def" '("define-hmac-function"))
-;;;***
-;;;### (autoloads nil "hmac-md5" "net/hmac-md5.el" (0 0 0 0))
;;; Generated autoloads from net/hmac-md5.el
(register-definition-prefixes "hmac-md5" '("hmac-md5" "md5-binary"))
-;;;***
-;;;### (autoloads nil "holidays" "calendar/holidays.el" (0 0 0 0))
;;; Generated autoloads from calendar/holidays.el
(defvar holiday-general-holidays (mapcar 'purecopy '((holiday-fixed 1 1 "New Year's Day") (holiday-float 1 1 3 "Martin Luther King Day") (holiday-fixed 2 2 "Groundhog Day") (holiday-fixed 2 14 "Valentine's Day") (holiday-float 2 1 3 "President's Day") (holiday-fixed 3 17 "St. Patrick's Day") (holiday-fixed 4 1 "April Fools' Day") (holiday-float 5 0 2 "Mother's Day") (holiday-float 5 1 -1 "Memorial Day") (holiday-fixed 6 14 "Flag Day") (holiday-float 6 0 3 "Father's Day") (holiday-fixed 7 4 "Independence Day") (holiday-float 9 1 1 "Labor Day") (holiday-float 10 1 2 "Columbus Day") (holiday-fixed 10 31 "Halloween") (holiday-fixed 11 11 "Veteran's Day") (holiday-float 11 4 4 "Thanksgiving"))) "\
General holidays. Default value is for the United States.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-general-holidays "holidays" t)
-
(put 'holiday-general-holidays 'risky-local-variable t)
-
(defvar holiday-oriental-holidays (mapcar 'purecopy '((holiday-chinese-new-year) (if calendar-chinese-all-holidays-flag (append (holiday-chinese 1 15 "Lantern Festival") (holiday-chinese-qingming) (holiday-chinese 5 5 "Dragon Boat Festival") (holiday-chinese 7 7 "Double Seventh Festival") (holiday-chinese 8 15 "Mid-Autumn Festival") (holiday-chinese 9 9 "Double Ninth Festival") (holiday-chinese-winter-solstice))))) "\
Oriental holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-oriental-holidays "holidays" t)
-
(put 'holiday-oriental-holidays 'risky-local-variable t)
-
(defvar holiday-local-holidays nil "\
Local holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-local-holidays "holidays" t)
-
(put 'holiday-local-holidays 'risky-local-variable t)
-
(defvar holiday-other-holidays nil "\
User defined holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-other-holidays "holidays" t)
-
(put 'holiday-other-holidays 'risky-local-variable t)
-
(defvar holiday-hebrew-holidays (mapcar 'purecopy '((holiday-hebrew-passover) (holiday-hebrew-rosh-hashanah) (holiday-hebrew-hanukkah) (if calendar-hebrew-all-holidays-flag (append (holiday-hebrew-tisha-b-av) (holiday-hebrew-misc))))) "\
Jewish holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-hebrew-holidays "holidays" t)
-
(put 'holiday-hebrew-holidays 'risky-local-variable t)
-
(defvar holiday-christian-holidays (mapcar 'purecopy '((holiday-easter-etc) (holiday-fixed 12 25 "Christmas") (if calendar-christian-all-holidays-flag (append (holiday-fixed 1 6 "Epiphany") (holiday-julian 12 25 "Christmas (Julian calendar)") (holiday-greek-orthodox-easter) (holiday-fixed 8 15 "Assumption") (holiday-advent 0 "Advent"))))) "\
Christian holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-christian-holidays "holidays" t)
-
(put 'holiday-christian-holidays 'risky-local-variable t)
-
(defvar holiday-islamic-holidays (mapcar 'purecopy '((holiday-islamic-new-year) (holiday-islamic 9 1 "Ramadan Begins") (if calendar-islamic-all-holidays-flag (append (holiday-islamic 1 10 "Ashura") (holiday-islamic 3 12 "Mulad-al-Nabi") (holiday-islamic 7 26 "Shab-e-Mi'raj") (holiday-islamic 8 15 "Shab-e-Bara't") (holiday-islamic 9 27 "Shab-e Qadr") (holiday-islamic 10 1 "Id-al-Fitr") (holiday-islamic 12 10 "Id-al-Adha"))))) "\
Islamic holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-islamic-holidays "holidays" t)
-
(put 'holiday-islamic-holidays 'risky-local-variable t)
-
(defvar holiday-bahai-holidays (mapcar 'purecopy '((holiday-bahai-new-year) (holiday-bahai-ridvan) (holiday-fixed 5 23 "Declaration of the Báb") (holiday-fixed 5 29 "Ascension of Bahá’u’lláh") (holiday-fixed 7 9 "Martyrdom of the Báb") (holiday-fixed 10 20 "Birth of the Báb") (holiday-fixed 11 12 "Birth of Bahá’u’lláh") (if calendar-bahai-all-holidays-flag (append (holiday-fixed 11 26 "Day of the Covenant") (holiday-fixed 11 28 "Ascension of `Abdu’l-Bahá"))))) "\
Bahá’í holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-bahai-holidays "holidays" t)
-
(put 'holiday-bahai-holidays 'risky-local-variable t)
-
(defvar holiday-solar-holidays (mapcar 'purecopy '((solar-equinoxes-solstices) (holiday-sexp calendar-daylight-savings-starts (format "Daylight Saving Time Begins %s" (solar-time-string (/ calendar-daylight-savings-starts-time (float 60)) calendar-standard-time-zone-name))) (holiday-sexp calendar-daylight-savings-ends (format "Daylight Saving Time Ends %s" (solar-time-string (/ calendar-daylight-savings-ends-time (float 60)) calendar-daylight-time-zone-name))))) "\
Sun-related holidays.
See the documentation for `calendar-holidays' for details.")
-
(custom-autoload 'holiday-solar-holidays "holidays" t)
-
(put 'holiday-solar-holidays 'risky-local-variable t)
-
(put 'calendar-holidays 'risky-local-variable t)
-
(autoload 'holidays "holidays" "\
Display the holidays for last month, this month, and next month.
If called with an optional prefix argument ARG, prompts for month and year.
This function is suitable for execution in an init file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'list-holidays "holidays" "\
Display holidays for years Y1 to Y2 (inclusive).
Y2 defaults to Y1. The optional list of holidays L defaults to
@@ -17290,18 +15732,24 @@ of a holiday list.
The optional LABEL is used to label the buffer created.
-\(fn Y1 &optional Y2 L LABEL)" t nil)
+The list of holiday lists is computed by the
+`holiday-available-holiday-lists' and you can alter the results
+by redefining that function, or use `add-function' to add
+values.
+(fn Y1 &optional Y2 L LABEL)" t nil)
(defalias 'holiday-list 'list-holidays)
-
(register-definition-prefixes "holidays" '("calendar-" "holiday-"))
-;;;***
-;;;### (autoloads nil "htmlfontify" "htmlfontify.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/html.el
+
+(register-definition-prefixes "semantic/html" '("semantic-"))
+
+
;;; Generated autoloads from htmlfontify.el
-(push (purecopy '(htmlfontify 0 21)) package--builtin-versions)
+(push (purecopy '(htmlfontify 0 21)) package--builtin-versions)
(autoload 'htmlfontify-buffer "htmlfontify" "\
Create a new buffer, named for the current buffer + a .html extension,
containing an inline CSS-stylesheet and formatted CSS-markup HTML
@@ -17320,21 +15768,32 @@ If the SRCDIR and FILE arguments are set, lookup etags derived
entries in the `hfy-tags-cache' and add HTML anchors and
hyperlinks as appropriate.
-\(fn &optional SRCDIR FILE)" t nil)
-
+(fn &optional SRCDIR FILE)" t nil)
(autoload 'htmlfontify-copy-and-link-dir "htmlfontify" "\
Trawl SRCDIR and write fontified-and-hyperlinked output in DSTDIR.
F-EXT and L-EXT specify values for `hfy-extn' and `hfy-link-extn'.
You may also want to set `hfy-page-header' and `hfy-page-footer'.
-\(fn SRCDIR DSTDIR &optional F-EXT L-EXT)" t nil)
-
+(fn SRCDIR DSTDIR &optional F-EXT L-EXT)" t nil)
(register-definition-prefixes "htmlfontify" '("hfy-" "htmlfontify-"))
-;;;***
-;;;### (autoloads nil "ibuf-macs" "ibuf-macs.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/ia.el
+
+(register-definition-prefixes "semantic/ia" '("semantic-ia-"))
+
+
+;;; Generated autoloads from cedet/semantic/ia-sb.el
+
+(register-definition-prefixes "semantic/ia-sb" '("semantic-ia-s"))
+
+
+;;; Generated autoloads from ibuf-ext.el
+
+(register-definition-prefixes "ibuf-ext" '("ibuffer-"))
+
+
;;; Generated autoloads from ibuf-macs.el
(autoload 'define-ibuffer-column "ibuf-macs" "\
@@ -17360,10 +15819,7 @@ inlined into the compiled format versions. This means that if you
change its definition, you should explicitly call
`ibuffer-recompile-formats'.
-\(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil t)
-
-(function-put 'define-ibuffer-column 'lisp-indent-function 'defun)
-
+(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-sorter "ibuf-macs" "\
Define a method of sorting named NAME.
DOCUMENTATION is the documentation of the function, which will be called
@@ -17374,12 +15830,7 @@ For sorting, the forms in BODY will be evaluated with `a' bound to one
buffer object, and `b' bound to another. BODY should return a non-nil
value if and only if `a' is \"less than\" `b'.
-\(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil t)
-
-(function-put 'define-ibuffer-sorter 'lisp-indent-function '1)
-
-(function-put 'define-ibuffer-sorter 'doc-string-elt '2)
-
+(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-op "ibuf-macs" "\
Generate a function which operates on a buffer.
OP becomes the name of the function; if it doesn't begin with
@@ -17418,12 +15869,7 @@ BODY define the operation; they are forms to evaluate per each
marked buffer. BODY is evaluated with `buf' bound to the
buffer object.
-\(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil t)
-
-(function-put 'define-ibuffer-op 'lisp-indent-function '2)
-
-(function-put 'define-ibuffer-op 'doc-string-elt '3)
-
+(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-filter "ibuf-macs" "\
Define a filter named NAME.
DOCUMENTATION is the documentation of the function.
@@ -17438,17 +15884,10 @@ not a particular buffer should be displayed or not. The forms in BODY
will be evaluated with BUF bound to the buffer object, and QUALIFIER
bound to the current value of the filter.
-\(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil t)
-
-(function-put 'define-ibuffer-filter 'lisp-indent-function '2)
-
-(function-put 'define-ibuffer-filter 'doc-string-elt '2)
-
+(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil 'macro)
(register-definition-prefixes "ibuf-macs" '("ibuffer-"))
-;;;***
-;;;### (autoloads nil "ibuffer" "ibuffer.el" (0 0 0 0))
;;; Generated autoloads from ibuffer.el
(autoload 'ibuffer-list-buffers "ibuffer" "\
@@ -17456,15 +15895,13 @@ Display a list of buffers, in another window.
If optional argument FILES-ONLY is non-nil, then add a filter for
buffers which are visiting a file.
-\(fn &optional FILES-ONLY)" t nil)
-
+(fn &optional FILES-ONLY)" t nil)
(autoload 'ibuffer-other-window "ibuffer" "\
Like `ibuffer', but displayed in another window by default.
If optional argument FILES-ONLY is non-nil, then add a filter for
buffers which are visiting a file.
-\(fn &optional FILES-ONLY)" t nil)
-
+(fn &optional FILES-ONLY)" t nil)
(autoload 'ibuffer "ibuffer" "\
Begin using Ibuffer to edit a list of buffers.
Type \\<ibuffer-mode-map>\\[describe-mode] after entering ibuffer for more information.
@@ -17483,20 +15920,15 @@ FORMATS is the value to use for `ibuffer-formats'.
If specified, then the variable `ibuffer-formats' will have
that value locally in this buffer.
-\(fn &optional OTHER-WINDOW-P NAME QUALIFIERS NOSELECT SHRINK FILTER-GROUPS FORMATS)" t nil)
-
+(fn &optional OTHER-WINDOW-P NAME QUALIFIERS NOSELECT SHRINK FILTER-GROUPS FORMATS)" t nil)
(autoload 'ibuffer-jump "ibuffer" "\
Call Ibuffer and set point at the line listing the current buffer.
If optional arg OTHER-WINDOW is non-nil, then use another window.
-\(fn &optional OTHER-WINDOW)" t nil)
-
+(fn &optional OTHER-WINDOW)" t nil)
(register-definition-prefixes "ibuffer" '("filename" "ibuffer-" "locked" "mark" "mod" "name" "process" "read-only" "recency" "size"))
-;;;***
-;;;### (autoloads nil "icalendar" "calendar/icalendar.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/icalendar.el
(autoload 'icalendar-export-file "icalendar" "\
@@ -17504,8 +15936,7 @@ Export diary file to iCalendar format.
All diary entries in the file DIARY-FILENAME are converted to iCalendar
format. The result is appended to the file ICAL-FILENAME.
-\(fn DIARY-FILENAME ICAL-FILENAME)" t nil)
-
+(fn DIARY-FILENAME ICAL-FILENAME)" t nil)
(autoload 'icalendar-export-region "icalendar" "\
Export region in diary file to iCalendar format.
All diary entries in the region from MIN to MAX in the current buffer are
@@ -17515,8 +15946,7 @@ This function attempts to return t if something goes wrong. In this
case an error string which describes all the errors and problems is
written into the buffer `*icalendar-errors*'.
-\(fn MIN MAX ICAL-FILENAME)" t nil)
-
+(fn MIN MAX ICAL-FILENAME)" t nil)
(autoload 'icalendar-import-file "icalendar" "\
Import an iCalendar file and append to a diary file.
Argument ICAL-FILENAME output iCalendar file.
@@ -17524,8 +15954,7 @@ Argument DIARY-FILENAME input `diary-file'.
Optional argument NON-MARKING determines whether events are created as
non-marking or not.
-\(fn ICAL-FILENAME DIARY-FILENAME &optional NON-MARKING)" t nil)
-
+(fn ICAL-FILENAME DIARY-FILENAME &optional NON-MARKING)" t nil)
(autoload 'icalendar-import-buffer "icalendar" "\
Extract iCalendar events from current buffer.
@@ -17544,13 +15973,10 @@ Return code t means that importing worked well, return code nil
means that an error has occurred. Error messages will be in the
buffer `*icalendar-errors*'.
-\(fn &optional DIARY-FILENAME DO-NOT-ASK NON-MARKING)" t nil)
-
+(fn &optional DIARY-FILENAME DO-NOT-ASK NON-MARKING)" t nil)
(register-definition-prefixes "icalendar" '("icalendar-"))
-;;;***
-;;;### (autoloads nil "icomplete" "icomplete.el" (0 0 0 0))
;;; Generated autoloads from icomplete.el
(defvar fido-mode nil "\
@@ -17560,31 +15986,28 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `fido-mode'.")
-
(custom-autoload 'fido-mode "icomplete" nil)
-
(autoload 'fido-mode "icomplete" "\
An enhanced `icomplete-mode' that emulates `ido-mode'.
-This is a minor mode. If called interactively, toggle the `Fido mode'
-mode. If the prefix argument is positive, enable the mode, and if it
-is zero or negative, disable the mode.
+This global minor mode makes minibuffer completion behave
+more like `ido-mode' than regular `icomplete-mode'.
+
+This is a global minor mode. If called interactively, toggle the
+`Fido mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='fido-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-This global minor mode makes minibuffer completion behave
-more like `ido-mode' than regular `icomplete-mode'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar icomplete-mode nil "\
Non-nil if Icomplete mode is enabled.
See the `icomplete-mode' command
@@ -17592,26 +16015,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `icomplete-mode'.")
-
(custom-autoload 'icomplete-mode "icomplete" nil)
-
(autoload 'icomplete-mode "icomplete" "\
Toggle incremental minibuffer completion (Icomplete mode).
-This is a minor mode. If called interactively, toggle the `Icomplete
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='icomplete-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When this global minor mode is enabled, typing in the minibuffer
continuously displays a list of possible completions that match
the string you have typed. See `icomplete-completions' for a
@@ -17625,8 +16032,21 @@ completions:
\\{icomplete-minibuffer-map}
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Icomplete mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='icomplete-mode)'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(defvar icomplete-vertical-mode nil "\
Non-nil if Icomplete-Vertical mode is enabled.
See the `icomplete-vertical-mode' command
@@ -17634,34 +16054,32 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `icomplete-vertical-mode'.")
-
(custom-autoload 'icomplete-vertical-mode "icomplete" nil)
-
(autoload 'icomplete-vertical-mode "icomplete" "\
Toggle vertical candidate display in `icomplete-mode' or `fido-mode'.
-This is a minor mode. If called interactively, toggle the
-`Icomplete-Vertical mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='icomplete-vertical-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
If none of these modes are on, turn on `icomplete-mode'.
As many completion candidates as possible are displayed, depending on
the value of `max-mini-window-height', and the way the mini-window is
resized depends on `resize-mini-windows'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Icomplete-Vertical mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='icomplete-vertical-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar fido-vertical-mode nil "\
Non-nil if Fido-Vertical mode is enabled.
See the `fido-vertical-mode' command
@@ -17669,39 +16087,35 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `fido-vertical-mode'.")
-
(custom-autoload 'fido-vertical-mode "icomplete" nil)
-
(autoload 'fido-vertical-mode "icomplete" "\
Toggle vertical candidate display in `fido-mode'.
+
When turning on, if non-vertical `fido-mode' is off, turn it on.
If it's on, just add the vertical display.
-This is a minor mode. If called interactively, toggle the
-`Fido-Vertical mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Fido-Vertical mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='fido-vertical-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-\(fn &optional ARG)" t nil)
+(fn &optional ARG)" t nil)
(when (locate-library "obsolete/iswitchb")
(autoload 'iswitchb-mode "iswitchb" "Toggle Iswitchb mode." t)
(make-obsolete 'iswitchb-mode
"use `icomplete-mode' or `ido-mode' instead." "24.4"))
-
(register-definition-prefixes "icomplete" '("icomplete-"))
-;;;***
-;;;### (autoloads nil "icon" "progmodes/icon.el" (0 0 0 0))
;;; Generated autoloads from progmodes/icon.el
(autoload 'icon-mode "icon" "\
@@ -17737,30 +16151,25 @@ Variables controlling indentation style:
Turning on Icon mode calls the value of the variable `icon-mode-hook'
with no args, if that value is non-nil.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "icon" '("beginning-of-icon-defun" "calculate-icon-indent" "electric-icon-brace" "end-of-icon-defun" "icon-" "indent-icon-exp" "mark-icon-function"))
-;;;***
-;;;### (autoloads nil "idlw-complete-structtag" "progmodes/idlw-complete-structtag.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/idle.el
+
+(register-definition-prefixes "semantic/idle" '("define-semantic-idle-service" "global-semantic-idle-summary-mode" "semantic-"))
+
+
;;; Generated autoloads from progmodes/idlw-complete-structtag.el
(register-definition-prefixes "idlw-complete-structtag" '("idlwave-"))
-;;;***
-;;;### (autoloads nil "idlw-help" "progmodes/idlw-help.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/idlw-help.el
(register-definition-prefixes "idlw-help" '("idlwave-"))
-;;;***
-;;;### (autoloads nil "idlw-shell" "progmodes/idlw-shell.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/idlw-shell.el
(autoload 'idlwave-shell "idlw-shell" "\
@@ -17779,26 +16188,20 @@ The buffer is put in `idlwave-shell-mode', providing commands for sending
input and controlling the IDL job. See help on `idlwave-shell-mode'.
See also the variable `idlwave-shell-prompt-pattern'.
-\(Type \\[describe-mode] in the shell buffer for a list of commands.)
-
-\(fn &optional ARG)" t nil)
+(Type \\[describe-mode] in the shell buffer for a list of commands.)
+(fn &optional ARG)" t nil)
(register-definition-prefixes "idlw-shell" '("idlwave-"))
-;;;***
-;;;### (autoloads nil "idlw-toolbar" "progmodes/idlw-toolbar.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from progmodes/idlw-toolbar.el
-(register-definition-prefixes "idlw-toolbar" '("idlwave-toolbar-"))
+(register-definition-prefixes "idlw-toolbar" '("idlwave-toolbar"))
-;;;***
-;;;### (autoloads nil "idlwave" "progmodes/idlwave.el" (0 0 0 0))
;;; Generated autoloads from progmodes/idlwave.el
-(push (purecopy '(idlwave 6 1 22)) package--builtin-versions)
+(push (purecopy '(idlwave 6 1 22)) package--builtin-versions)
(autoload 'idlwave-mode "idlwave" "\
Major mode for editing IDL source files (version 6.1_em22).
@@ -17919,13 +16322,10 @@ The main features of this mode are
\\{idlwave-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "idlwave" '("idlwave-"))
-;;;***
-;;;### (autoloads nil "ido" "ido.el" (0 0 0 0))
;;; Generated autoloads from ido.el
(defvar ido-mode nil "\
@@ -17939,9 +16339,7 @@ The following values are possible:
Setting this variable directly does not take effect;
use either \\[customize] or the function `ido-mode'.")
-
(custom-autoload 'ido-mode "ido" nil)
-
(autoload 'ido-mode "ido" "\
Toggle Ido mode on or off.
With ARG, turn Ido mode on if arg is positive, off otherwise.
@@ -17952,8 +16350,7 @@ However, if ARG arg equals `files', remap only commands for files, or
if it equals `buffers', remap only commands for buffer switching.
This function also adds a hook to the minibuffer.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'ido-switch-buffer "ido" "\
Switch to another buffer.
The buffer is displayed according to `ido-default-buffer-method' -- the
@@ -17986,12 +16383,10 @@ RET Select the buffer at the front of the list of matches.
\\[ido-enter-find-file] Drop into `ido-find-file'.
\\[ido-kill-buffer-at-head] Kill buffer at head of buffer list.
\\[ido-toggle-ignore] Toggle ignoring buffers listed in `ido-ignore-buffers'." t nil)
-
(autoload 'ido-switch-buffer-other-window "ido" "\
Switch to another buffer and show it in another window.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'." t nil)
-
(autoload 'ido-display-buffer "ido" "\
Display a buffer in another window but don't select it.
@@ -18002,33 +16397,27 @@ window.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'.
-\(fn &optional ACTION)" t nil)
-
+(fn &optional ACTION)" t nil)
(autoload 'ido-display-buffer-other-frame "ido" "\
Display a buffer preferably in another frame.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'." t nil)
-
(autoload 'ido-kill-buffer "ido" "\
Kill a buffer.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'." t nil)
-
(autoload 'ido-insert-buffer "ido" "\
Insert contents of a buffer in current buffer after point.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'." t nil)
-
(autoload 'ido-switch-buffer-other-frame "ido" "\
Switch to another buffer and show it in another frame.
The buffer name is selected interactively by typing a substring.
For details of keybindings, see `ido-switch-buffer'." t nil)
-
(autoload 'ido-find-file-in-dir "ido" "\
Switch to another file starting from DIR.
-\(fn DIR)" t nil)
-
+(fn DIR)" t nil)
(autoload 'ido-find-file "ido" "\
Edit file with name obtained via minibuffer.
The file is displayed according to `ido-default-file-method' -- the
@@ -18072,72 +16461,58 @@ RET Select the file at the front of the list of matches.
\\[ido-completion-help] Show list of matching files in separate window.
\\[ido-toggle-ignore] Toggle ignoring files listed in `ido-ignore-files'.
\\[ido-reread-directory] Reread the current directory." t nil)
-
(autoload 'ido-find-file-other-window "ido" "\
Switch to another file and show it in another window.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-alternate-file "ido" "\
Find another file, select its buffer, kill previous buffer.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-alternate-file-other-window "ido" "\
Find file as a replacement for the file in the next window.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-file-read-only "ido" "\
Edit file read-only with name obtained via minibuffer.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-file-read-only-other-window "ido" "\
Edit file read-only in other window with name obtained via minibuffer.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-file-read-only-other-frame "ido" "\
Edit file read-only in other frame with name obtained via minibuffer.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-display-file "ido" "\
Display a file in another window but don't select it.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-find-file-other-frame "ido" "\
Switch to another file and show it in another frame.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-write-file "ido" "\
Write current buffer to a file.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-insert-file "ido" "\
Insert contents of file in current buffer.
The file name is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-dired "ido" "\
Call `dired' the Ido way.
The directory is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-dired-other-window "ido" "\
\"Edit\" a directory. Like `ido-dired' but select in another window.
The directory is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-dired-other-frame "ido" "\
\"Edit\" a directory. Like `ido-dired' but make a new frame.
The directory is selected interactively by typing a substring.
For details of keybindings, see `ido-find-file'." t nil)
-
(autoload 'ido-read-buffer "ido" "\
Ido replacement for the built-in `read-buffer'.
Return the name of a buffer selected.
@@ -18147,22 +16522,19 @@ If REQUIRE-MATCH is non-nil, an existing buffer must be selected.
Optional arg PREDICATE if non-nil is a function limiting the
buffers that can be considered.
-\(fn PROMPT &optional DEFAULT REQUIRE-MATCH PREDICATE)" nil nil)
-
+(fn PROMPT &optional DEFAULT REQUIRE-MATCH PREDICATE)" nil nil)
(autoload 'ido-read-file-name "ido" "\
Ido replacement for the built-in `read-file-name'.
Read file name, prompting with PROMPT and completing in directory DIR.
See `read-file-name' for additional parameters.
-\(fn PROMPT &optional DIR DEFAULT-FILENAME MUSTMATCH INITIAL PREDICATE)" nil nil)
-
+(fn PROMPT &optional DIR DEFAULT-FILENAME MUSTMATCH INITIAL PREDICATE)" nil nil)
(autoload 'ido-read-directory-name "ido" "\
Ido replacement for the built-in `read-directory-name'.
Read directory name, prompting with PROMPT and completing in directory DIR.
See `read-directory-name' for additional parameters.
-\(fn PROMPT &optional DIR DEFAULT-DIRNAME MUSTMATCH INITIAL)" nil nil)
-
+(fn PROMPT &optional DIR DEFAULT-DIRNAME MUSTMATCH INITIAL)" nil nil)
(autoload 'ido-completing-read "ido" "\
Ido replacement for the built-in `completing-read'.
Read a string in the minibuffer with Ido-style completion.
@@ -18179,13 +16551,15 @@ If INITIAL-INPUT is non-nil, insert it in the minibuffer initially,
HIST, if non-nil, specifies a history list.
DEF, if non-nil, is the default value.
-\(fn PROMPT CHOICES &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil)
-
+(fn PROMPT CHOICES &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil)
(register-definition-prefixes "ido" '("ido-"))
-;;;***
-;;;### (autoloads nil "ielm" "ielm.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/symref/idutils.el
+
+(register-definition-prefixes "semantic/symref/idutils" '("semantic-symref-idutils--line-re"))
+
+
;;; Generated autoloads from ielm.el
(autoload 'ielm "ielm" "\
@@ -18194,50 +16568,44 @@ Switches to the buffer named BUF-NAME if provided (`*ielm*' by default),
or creates it if it does not exist.
See `inferior-emacs-lisp-mode' for details.
-\(fn &optional BUF-NAME)" t nil)
-
+(fn &optional BUF-NAME)" t nil)
(register-definition-prefixes "ielm" '("ielm-" "inferior-emacs-lisp-mode"))
-;;;***
-;;;### (autoloads nil "ietf-drums" "mail/ietf-drums.el" (0 0 0 0))
;;; Generated autoloads from mail/ietf-drums.el
(register-definition-prefixes "ietf-drums" '("ietf-drums-"))
-;;;***
-;;;### (autoloads nil "iimage" "iimage.el" (0 0 0 0))
+;;; Generated autoloads from mail/ietf-drums-date.el
+
+(register-definition-prefixes "ietf-drums-date" '("date-parse-error" "ietf-drums-"))
+
+
;;; Generated autoloads from iimage.el
(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "24.1")
-
(autoload 'iimage-mode "iimage" "\
Toggle Iimage mode on or off.
-This is a minor mode. If called interactively, toggle the `Iimage
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a minor mode. If called interactively, toggle the
+`Iimage mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `iimage-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\\{iimage-mode-map}
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "iimage" '("iimage-" "turn-off-iimage-mode"))
-;;;***
-;;;### (autoloads nil "image" "image.el" (0 0 0 0))
;;; Generated autoloads from image.el
(autoload 'image-type-from-data "image" "\
@@ -18245,27 +16613,24 @@ Determine the image type from image data DATA.
Value is a symbol specifying the image type or nil if type cannot
be determined.
-\(fn DATA)" nil nil)
-
+(fn DATA)" nil nil)
(autoload 'image-type-from-buffer "image" "\
Determine the image type from data in the current buffer.
Value is a symbol specifying the image type or nil if type cannot
be determined." nil nil)
-
(autoload 'image-type-from-file-header "image" "\
Determine the type of image file FILE from its first few bytes.
Value is a symbol specifying the image type, or nil if type cannot
be determined.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'image-type-from-file-name "image" "\
Determine the type of image file FILE from its name.
Value is a symbol specifying the image type, or nil if type cannot
be determined.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
+(make-obsolete 'image-type-from-file-name 'image-supported-file-p "29.1")
(autoload 'image-type "image" "\
Determine and return image type.
SOURCE is an image file name or image data.
@@ -18279,14 +16644,12 @@ data. If DATA-P is a symbol with a name on the format
`image/jpeg', that may be used as a hint to determine the image
type if we can't otherwise guess it.
-\(fn SOURCE &optional TYPE DATA-P)" nil nil)
-
+(fn SOURCE &optional TYPE DATA-P)" nil nil)
(autoload 'image-type-available-p "image" "\
Return t if image type TYPE is available.
Image types are symbols like `xbm' or `jpeg'.
-\(fn TYPE)" nil nil)
-
+(fn TYPE)" nil nil)
(autoload 'image-type-auto-detected-p "image" "\
Return t if the current buffer contains an auto-detectable image.
This function is intended to be used from `magic-fallback-mode-alist'.
@@ -18296,7 +16659,6 @@ its beginning matches an image type in `image-type-header-regexps',
and that image type is present in `image-type-auto-detectable' with a
non-nil value. If that value is non-nil, but not t, then the image type
must be available." nil nil)
-
(autoload 'create-image "image" "\
Create an image.
FILE-OR-DATA is an image file name or image data.
@@ -18322,8 +16684,7 @@ Image file names that are not absolute are searched for in the
\"images\" sub-directory of `data-directory' and
`x-bitmap-file-path' (in that order).
-\(fn FILE-OR-DATA &optional TYPE DATA-P &rest PROPS)" nil nil)
-
+(fn FILE-OR-DATA &optional TYPE DATA-P &rest PROPS)" nil nil)
(autoload 'put-image "image" "\
Put image IMAGE in front of POS in the current buffer.
IMAGE must be an image created with `create-image' or `defimage'.
@@ -18337,8 +16698,7 @@ display it in the text area, a value of `left-margin' means
display it in the left marginal area, a value of `right-margin'
means display it in the right marginal area.
-\(fn IMAGE POS &optional STRING AREA)" nil nil)
-
+(fn IMAGE POS &optional STRING AREA)" nil nil)
(autoload 'insert-image "image" "\
Insert IMAGE into current buffer at point.
IMAGE is displayed by inserting STRING into the current buffer
@@ -18362,8 +16722,7 @@ Normally `isearch' is able to search for STRING in the buffer
even if it's hidden behind a displayed image. If INHIBIT-ISEARCH
is non-nil, this is inhibited.
-\(fn IMAGE &optional STRING AREA SLICE INHIBIT-ISEARCH)" nil nil)
-
+(fn IMAGE &optional STRING AREA SLICE INHIBIT-ISEARCH)" nil nil)
(autoload 'insert-sliced-image "image" "\
Insert IMAGE into current buffer at point.
IMAGE is displayed by inserting STRING into the current buffer
@@ -18375,15 +16734,13 @@ display it in the left marginal area, a value of `right-margin'
means display it in the right marginal area.
The image is automatically split into ROWS x COLS slices.
-\(fn IMAGE &optional STRING AREA ROWS COLS)" nil nil)
-
+(fn IMAGE &optional STRING AREA ROWS COLS)" nil nil)
(autoload 'remove-images "image" "\
Remove images between START and END in BUFFER.
Remove only images that were put in BUFFER with calls to `put-image'.
BUFFER nil or omitted means use the current buffer.
-\(fn START END &optional BUFFER)" nil nil)
-
+(fn START END &optional BUFFER)" nil nil)
(autoload 'find-image "image" "\
Find an image, choosing one of a list of image specifications.
@@ -18391,13 +16748,15 @@ SPECS is a list of image specifications.
Each image specification in SPECS is a property list. The contents of
a specification are image type dependent. All specifications must at
-least contain the properties `:type TYPE' and either `:file FILE' or
-`:data DATA', where TYPE is a symbol specifying the image type,
-e.g. `xbm', FILE is the file to load the image from, and DATA is a
-string containing the actual image data. The specification whose TYPE
-is supported, and FILE exists, is used to construct the image
-specification to be returned. Return nil if no specification is
-satisfied.
+least contain either the property `:file FILE' or `:data DATA',
+where FILE is the file to load the image from, and DATA is a string
+containing the actual image data. If the property `:type TYPE' is
+omitted or nil, try to determine the image type from its first few
+bytes of image data. If that doesn't work, and the property `:file
+FILE' provide a file name, use its file extension as image type.
+If `:type TYPE' is provided, it must match the actual type
+determined for FILE or DATA by `create-image'. Return nil if no
+specification is satisfied.
If CACHE is non-nil, results are cached and returned on subsequent calls.
@@ -18405,8 +16764,7 @@ The image is looked for in `image-load-path'.
Image files should not be larger than specified by `max-image-size'.
-\(fn SPECS &optional CACHE)" nil nil)
-
+(fn SPECS &optional CACHE)" nil nil)
(autoload 'defimage "image" "\
Define SYMBOL as an image, and return SYMBOL.
@@ -18427,12 +16785,9 @@ Example:
(defimage test-image ((:type xpm :file \"~/test1.xpm\")
(:type xbm :file \"~/test1.xbm\")))
-\(fn SYMBOL SPECS &optional DOC)" nil t)
-
-(function-put 'defimage 'doc-string-elt '3)
-
+(fn SYMBOL SPECS &optional DOC)" nil t)
+(function-put 'defimage 'doc-string-elt 3)
(function-put 'defimage 'lisp-indent-function 'defun)
-
(autoload 'imagemagick-register-types "image" "\
Register file types that can be handled by ImageMagick.
This function is called at startup, after loading the init file.
@@ -18444,26 +16799,19 @@ Emacs visits them in Image mode. They are also added to
recognizes these files as having image type `imagemagick'.
If Emacs is compiled without ImageMagick support, this does nothing." nil nil)
-
(autoload 'image-at-point-p "image" "\
Return non-nil if there is an image at point." nil nil)
-
(register-definition-prefixes "image" '("find-image--cache" "image" "unknown-image-type"))
-;;;***
-;;;### (autoloads nil "image-converter" "image/image-converter.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from image/image-converter.el
(register-definition-prefixes "image-converter" '("image-convert"))
-;;;***
-;;;### (autoloads nil "image-dired" "image-dired.el" (0 0 0 0))
;;; Generated autoloads from image-dired.el
-(push (purecopy '(image-dired 0 4 11)) package--builtin-versions)
+(push (purecopy '(image-dired 0 4 11)) package--builtin-versions)
(autoload 'image-dired-dired-toggle-marked-thumbs "image-dired" "\
Toggle thumbnails in front of file names in the Dired buffer.
If no marked file could be found, insert or hide thumbnails on the
@@ -18471,8 +16819,7 @@ current line. ARG, if non-nil, specifies the files to use instead
of the marked files. If ARG is an integer, use the next ARG (or
previous -ARG, if ARG<0) files.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'image-dired-dired-with-window-configuration "image-dired" "\
Open directory DIR and create a default window configuration.
@@ -18491,8 +16838,7 @@ If called with prefix argument ARG, skip splitting of windows.
The current window configuration is saved and can be restored by
calling `image-dired-restore-window-configuration'.
-\(fn DIR &optional ARG)" t nil)
-
+(fn DIR &optional ARG)" t nil)
(autoload 'image-dired-display-thumbs "image-dired" "\
Display thumbnails of all marked files, in `image-dired-thumbnail-buffer'.
If a thumbnail image does not exist for a file, it is created on the
@@ -18514,8 +16860,7 @@ used or not. If non-nil, use `display-buffer' instead of
`image-dired-previous-line-and-display' where we do not want the
thumbnail buffer to be selected.
-\(fn &optional ARG APPEND DO-NOT-POP)" t nil)
-
+(fn &optional ARG APPEND DO-NOT-POP)" t nil)
(autoload 'image-dired-show-all-from-dir "image-dired" "\
Make a thumbnail buffer for all images in DIR and display it.
Any file matching `image-file-name-regexp' is considered an image
@@ -18526,91 +16871,77 @@ If the number of image files in DIR exceeds
before creating the thumbnail buffer. If that variable is nil,
never ask for confirmation.
-\(fn DIR)" t nil)
-
+(fn DIR)" t nil)
(defalias 'image-dired 'image-dired-show-all-from-dir)
-
(autoload 'image-dired-tag-files "image-dired" "\
Tag marked file(s) in Dired. With prefix ARG, tag file at point.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'image-dired-delete-tag "image-dired" "\
Remove tag for selected file(s).
With prefix argument ARG, remove tag from file at point.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'image-dired-jump-thumbnail-buffer "image-dired" "\
Jump to thumbnail buffer." t nil)
-
(autoload 'image-dired-minor-mode "image-dired" "\
Setup easy-to-use keybindings for the commands to be used in Dired mode.
+
Note that n, p and <down> and <up> will be hijacked and bound to
`image-dired-dired-next-line' and `image-dired-dired-previous-line'.
This is a minor mode. If called interactively, toggle the
-`Image-Dired minor mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Image-Dired minor mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `image-dired-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'image-dired-display-thumbs-append "image-dired" "\
Append thumbnails to `image-dired-thumbnail-buffer'." t nil)
-
(autoload 'image-dired-display-thumb "image-dired" "\
Shorthand for `image-dired-display-thumbs' with prefix argument." t nil)
-
(autoload 'image-dired-dired-display-external "image-dired" "\
Display file at point using an external viewer." t nil)
-
(autoload 'image-dired-dired-display-image "image-dired" "\
Display current image file.
See documentation for `image-dired-display-image' for more information.
With prefix argument ARG, display image in its original size.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'image-dired-dired-comment-files "image-dired" "\
Add comment to current or marked files in Dired." t nil)
-
(autoload 'image-dired-mark-tagged-files "image-dired" "\
-Use regexp to mark files with matching tag.
+Use REGEXP to mark files with matching tag.
A `tag' is a keyword, a piece of meta data, associated with an
image file and stored in image-dired's database file. This command
lets you input a regexp and this will be matched against all tags
on all image files in the database file. The files that have a
-matching tag will be marked in the Dired buffer." t nil)
+matching tag will be marked in the Dired buffer.
+(fn REGEXP)" t nil)
(autoload 'image-dired-dired-edit-comment-and-tags "image-dired" "\
Edit comment and tags of current or marked image files.
Edit comment and tags for all marked image files in an
easy-to-use form." t nil)
-
(autoload 'image-dired-bookmark-jump "image-dired" "\
Default bookmark handler for Image-Dired buffers.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(define-obsolete-function-alias 'tumme #'image-dired "24.4")
-
(define-obsolete-function-alias 'image-dired-setup-dired-keybindings #'image-dired-minor-mode "26.1")
-
(register-definition-prefixes "image-dired" '("image-dired-"))
-;;;***
-;;;### (autoloads nil "image-file" "image-file.el" (0 0 0 0))
;;; Generated autoloads from image-file.el
(defvar image-file-name-extensions (purecopy '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm" "svg" "webp")) "\
@@ -18622,9 +16953,7 @@ See `auto-image-file-mode'; if `auto-image-file-mode' is enabled,
setting this variable directly does not take effect unless
`auto-image-file-mode' is re-enabled; this happens automatically when
the variable is set using \\[customize].")
-
(custom-autoload 'image-file-name-extensions "image-file" nil)
-
(defvar image-file-name-regexps nil "\
List of regexps matching image-file filenames.
Filenames matching one of these regexps are considered image files,
@@ -18634,20 +16963,16 @@ See function `auto-image-file-mode'; if `auto-image-file-mode' is
enabled, setting this variable directly does not take effect unless
`auto-image-file-mode' is re-enabled; this happens automatically when
the variable is set using \\[customize].")
-
(custom-autoload 'image-file-name-regexps "image-file" nil)
-
(autoload 'image-file-name-regexp "image-file" "\
Return a regular expression matching image-file filenames." nil nil)
-
(autoload 'insert-image-file "image-file" "\
Insert the image file FILE into the current buffer.
Optional arguments VISIT, BEG, END, and REPLACE are interpreted
as for the command `insert-file-contents'. Return list of
absolute file name and number of characters inserted.
-\(fn FILE &optional VISIT BEG END REPLACE)" nil nil)
-
+(fn FILE &optional VISIT BEG END REPLACE)" nil nil)
(defvar auto-image-file-mode nil "\
Non-nil if Auto-Image-File mode is enabled.
See the `auto-image-file-mode' command
@@ -18655,37 +16980,32 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `auto-image-file-mode'.")
-
(custom-autoload 'auto-image-file-mode "image-file" nil)
-
(autoload 'auto-image-file-mode "image-file" "\
Toggle visiting of image files as images (Auto Image File mode).
-This is a minor mode. If called interactively, toggle the
+An image file is one whose name has an extension in
+`image-file-name-extensions', or matches a regexp in
+`image-file-name-regexps'.
+
+This is a global minor mode. If called interactively, toggle the
`Auto-Image-File mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='auto-image-file-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-An image file is one whose name has an extension in
-`image-file-name-extensions', or matches a regexp in
-`image-file-name-regexps'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "image-file" '("image-file-"))
-;;;***
-;;;### (autoloads nil "image-mode" "image-mode.el" (0 0 0 0))
;;; Generated autoloads from image-mode.el
(autoload 'image-mode "image-mode" "\
@@ -18695,52 +17015,49 @@ as an image and display as text or hex.
Key bindings:
\\{image-mode-map}" t nil)
-
(autoload 'image-minor-mode "image-mode" "\
Toggle Image minor mode in this buffer.
+Image minor mode provides the key \\<image-mode-map>\\[image-toggle-display],
+to switch back to `image-mode' and display an image file as the
+actual image.
+
This is a minor mode. If called interactively, toggle the `Image
minor mode' mode. If the prefix argument is positive, enable the
mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `image-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Image minor mode provides the key \\<image-mode-map>\\[image-toggle-display],
-to switch back to `image-mode' and display an image file as the
-actual image.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'image-mode-to-text "image-mode" "\
Set a non-image mode as major mode in combination with image minor mode.
A non-mage major mode found from `auto-mode-alist' or fundamental mode
displays an image file as text." nil nil)
-
(autoload 'image-bookmark-jump "image-mode" "\
-\(fn BMK)" nil nil)
-
+(fn BMK)" nil nil)
(register-definition-prefixes "image-mode" '("image-"))
-;;;***
-;;;### (autoloads nil "imap" "net/imap.el" (0 0 0 0))
;;; Generated autoloads from net/imap.el
(register-definition-prefixes "imap" '("imap-"))
-;;;***
-;;;### (autoloads nil "imenu" "imenu.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/imenu.el
+
+(register-definition-prefixes "semantic/imenu" '("semantic-"))
+
+
;;; Generated autoloads from imenu.el
(defvar imenu-sort-function nil "\
@@ -18756,10 +17073,8 @@ Set it to `imenu--sort-by-name' if you want alphabetic sorting.
The function should take two arguments and return t if the first
element should come before the second. The arguments are cons cells;
-\(NAME . POSITION). Look at `imenu--sort-by-name' for an example.")
-
+(NAME . POSITION). Look at `imenu--sort-by-name' for an example.")
(custom-autoload 'imenu-sort-function "imenu" t)
-
(defvar-local imenu-generic-expression nil "\
List of definition matchers for creating an Imenu index.
Each element of this list should have the form
@@ -18795,7 +17110,6 @@ used by `fortran-mode' with `imenu-syntax-alist' set locally so that
characters which normally have \"symbol\" syntax are considered to have
\"word\" syntax during matching.")
(put 'imenu-generic-expression 'risky-local-variable t)
-
(defvar-local imenu-create-index-function 'imenu-default-create-index-function "\
The function to use for creating an index alist of the current buffer.
@@ -18804,7 +17118,6 @@ an index alist of the current buffer. The function is
called within a `save-excursion'.
See `imenu--index-alist' for the format of the buffer index alist.")
-
(defvar-local imenu-prev-index-position-function 'beginning-of-defun "\
Function for finding the next index position.
@@ -18815,14 +17128,12 @@ file.
The function should leave point at the place to be connected to the
index and it should return nil when it doesn't find another index.")
-
(defvar-local imenu-extract-index-name-function nil "\
Function for extracting the index item name, given a position.
This function is called after `imenu-prev-index-position-function'
finds a position for an index item, with point at that position.
It should return the name for that index item.")
-
(defvar-local imenu-name-lookup-function nil "\
Function to compare string with index item.
@@ -18833,12 +17144,10 @@ If nil, comparison is done with `string='.
Set this to some other function for more advanced comparisons,
such as \"begins with\" or \"name matches and number of
arguments match\".")
-
(defvar-local imenu-default-goto-function 'imenu-default-goto-function "\
The default function called when selecting an Imenu item.
The function in this variable is called when selecting a normal index-item.")
(put 'imenu--index-alist 'risky-local-variable t)
-
(defvar-local imenu-syntax-alist nil "\
Alist of syntax table modifiers to use while in `imenu--generic-function'.
@@ -18849,70 +17158,66 @@ a string, all the characters in the string get the specified syntax.
This is typically used to give word syntax to characters which
normally have symbol syntax to simplify `imenu-expression'
and speed-up matching.")
-
(defvar-local imenu-case-fold-search t "\
Defines whether `imenu--generic-function' should fold case when matching.
This variable should be set (only) by initialization code
for modes which use `imenu--generic-function'. If it is not set, but
`font-lock-defaults' is set, then font-lock's setting is used.")
-
(autoload 'imenu-add-to-menubar "imenu" "\
Add an `imenu' entry to the menu bar for the current buffer.
NAME is a string used to name the menu bar item.
See the command `imenu' for more information.
-\(fn NAME)" t nil)
-
+(fn NAME)" t nil)
(autoload 'imenu-add-menubar-index "imenu" "\
Add an Imenu \"Index\" entry on the menu bar for the current buffer.
A trivial interface to `imenu-add-to-menubar' suitable for use in a hook." t nil)
-
(autoload 'imenu "imenu" "\
Jump to a place in the buffer chosen using a buffer menu or mouse menu.
INDEX-ITEM specifies the position. See `imenu-choose-buffer-index'
for more information.
-\(fn INDEX-ITEM)" t nil)
-
+(fn INDEX-ITEM)" t nil)
(register-definition-prefixes "imenu" '("imenu-"))
-;;;***
-;;;### (autoloads nil "ind-util" "language/ind-util.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/decorate/include.el
+
+(register-definition-prefixes "semantic/decorate/include" '("semantic-decoration-"))
+
+
;;; Generated autoloads from language/ind-util.el
(autoload 'indian-compose-region "ind-util" "\
Compose the region according to `composition-function-table'.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'indian-compose-string "ind-util" "\
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'in-is13194-post-read-conversion "ind-util" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'in-is13194-pre-write-conversion "ind-util" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(autoload 'indian-2-column-to-ucs-region "ind-util" "\
Convert old Emacs Devanagari characters to UCS.
-\(fn FROM TO)" t nil)
+(fn FROM TO)" t nil)
+(register-definition-prefixes "ind-util" '("combinatorial" "indian-" "is13194-"))
-(register-definition-prefixes "ind-util" '("indian-" "is13194-"))
+
+;;; Generated autoloads from leim/quail/indian.el
+
+(register-definition-prefixes "quail/indian" '("indian-mlm-mozhi-u" "inscript-" "quail-"))
-;;;***
-;;;### (autoloads nil "inf-lisp" "progmodes/inf-lisp.el" (0 0 0 0))
;;; Generated autoloads from progmodes/inf-lisp.el
(autoload 'inferior-lisp "inf-lisp" "\
@@ -18927,20 +17232,16 @@ of `inferior-lisp-program'). Runs the hooks from
If any parts of the command name contains spaces, they should be
quoted using shell quote syntax.
-\(Type \\[describe-mode] in the process buffer for a list of commands.)
-
-\(fn CMD)" t nil)
+(Type \\[describe-mode] in the process buffer for a list of commands.)
+(fn CMD)" t nil)
(defalias 'run-lisp 'inferior-lisp)
-
(register-definition-prefixes "inf-lisp" '("inferior-lisp-" "lisp-" "switch-to-lisp"))
-;;;***
-;;;### (autoloads nil "info" "info.el" (0 0 0 0))
;;; Generated autoloads from info.el
-(defcustom Info-default-directory-list (let* ((config-dir (file-name-as-directory (or (and (featurep 'ns) (let ((dir (expand-file-name "../info" data-directory))) (if (file-directory-p dir) dir))) configure-info-directory))) (prefixes (prune-directory-list '("/usr/local/" "/usr/" "/opt/"))) (suffixes '("share/" "")) (standard-info-dirs (apply #'nconc (mapcar (lambda (pfx) (let ((dirs (mapcar (lambda (sfx) (concat pfx sfx "info/")) suffixes))) (prune-directory-list dirs))) prefixes))) (dirs (if (member config-dir standard-info-dirs) (nconc standard-info-dirs (list config-dir)) (cons config-dir standard-info-dirs)))) (if (not (eq system-type 'windows-nt)) dirs (let* ((instdir (file-name-directory invocation-directory)) (dir1 (expand-file-name "../info/" instdir)) (dir2 (expand-file-name "../../../info/" instdir))) (cond ((file-exists-p dir1) (append dirs (list dir1))) ((file-exists-p dir2) (append dirs (list dir2))) (t dirs))))) "\
+(defvar Info-default-directory-list nil "\
Default list of directories to search for Info documentation files.
They are searched in the order they are given in the list.
Therefore, the directory of Info files that come with Emacs
@@ -18951,22 +17252,16 @@ first in this list.
Once Info is started, the list of directories to search
comes from the variable `Info-directory-list'.
-This variable `Info-default-directory-list' is used as the default
-for initializing `Info-directory-list' when Info is started, unless
-the environment variable INFOPATH is set.
-
-Although this is a customizable variable, that is mainly for technical
-reasons. Normally, you should either set INFOPATH or customize
-`Info-additional-directory-list', rather than changing this variable." :initialize #'custom-initialize-delay :type '(repeat directory))
+This variable is used as the default for initializing
+`Info-directory-list' when Info is started, unless the
+environment variable INFOPATH is set.")
(custom-autoload 'Info-default-directory-list "info" t)
-
(autoload 'info-other-window "info" "\
Like `info' but show the Info buffer in another window.
-\(fn &optional FILE-OR-NODE BUFFER)" t nil)
+(fn &optional FILE-OR-NODE BUFFER)" t nil)
(put 'info 'info-file (purecopy "emacs"))
-
(autoload 'info "info" "\
Enter Info, the documentation browser.
Optional argument FILE-OR-NODE specifies the file to examine;
@@ -18989,29 +17284,23 @@ in all the directories in that path.
See a list of available Info commands in `Info-mode'.
-\(fn &optional FILE-OR-NODE BUFFER)" t nil)
-
+(fn &optional FILE-OR-NODE BUFFER)" t nil)
(autoload 'info-emacs-manual "info" "\
Display the Emacs manual in Info mode." t nil)
-
(autoload 'info-emacs-bug "info" "\
Display the \"Reporting Bugs\" section of the Emacs manual in Info mode." t nil)
-
(autoload 'info-standalone "info" "\
Run Emacs as a standalone Info reader.
Usage: emacs -f info-standalone [filename]
In standalone mode, \\<Info-mode-map>\\[quit-window] exits Emacs itself." nil nil)
-
(autoload 'Info-on-current-buffer "info" "\
Use Info mode to browse the current Info buffer.
With a prefix arg, this queries for the node name to visit first;
otherwise, that defaults to `Top'.
-\(fn &optional NODENAME)" t nil)
-
+(fn &optional NODENAME)" t nil)
(autoload 'Info-directory "info" "\
Go to the Info directory node." t nil)
-
(autoload 'Info-index "info" "\
Look up a string TOPIC in the index for this manual and go to that entry.
If there are no exact matches to the specified topic, this chooses
@@ -19019,22 +17308,21 @@ the first match which is a case-insensitive substring of a topic.
Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches.
Give an empty topic name to go to the Index node itself.
-\(fn TOPIC)" t nil)
-
+(fn TOPIC)" t nil)
(autoload 'info-apropos "info" "\
-Grovel indices of all known Info files on your system for STRING.
-Build a menu of the possible matches.
+Search indices of all known Info files on your system for STRING.
+If REGEXP (interactively, the prefix), use a regexp match.
-\(fn STRING)" t nil)
+Display a menu of the possible matches.
+(fn STRING &optional REGEXP)" t nil)
(autoload 'info-finder "info" "\
Display descriptions of the keywords in the Finder virtual manual.
In interactive use, a prefix argument directs this command to read
a list of keywords separated by comma. After that, it displays a node
with a list of packages that contain all specified keywords.
-\(fn &optional KEYWORDS)" t nil)
-
+(fn &optional KEYWORDS)" t nil)
(autoload 'Info-mode "info" "\
Info mode provides commands for browsing through the Info documentation tree.
Documentation in Info is divided into \"nodes\", each of which discusses
@@ -19098,9 +17386,8 @@ Advanced commands:
\\[universal-argument] \\[info] Move to new Info file with completion.
\\[universal-argument] N \\[info] Select Info buffer with prefix number in the name *info*<N>.
-\(fn)" t nil)
+(fn)" t nil)
(put 'Info-goto-emacs-command-node 'info-file (purecopy "emacs"))
-
(autoload 'Info-goto-emacs-command-node "info" "\
Go to the Info node in the Emacs manual for command COMMAND.
The command is found by looking up in Emacs manual's indices
@@ -19108,9 +17395,8 @@ or in another manual found via COMMAND's `info-file' property or
the variable `Info-file-list-for-emacs'.
COMMAND must be a symbol or string.
-\(fn COMMAND)" t nil)
+(fn COMMAND)" t nil)
(put 'Info-goto-emacs-key-command-node 'info-file (purecopy "emacs"))
-
(autoload 'Info-goto-emacs-key-command-node "info" "\
Go to the node in the Emacs manual which describes the command bound to KEY.
KEY is a string.
@@ -19119,18 +17405,15 @@ The command is found by looking up in Emacs manual's indices
or in another manual found via COMMAND's `info-file' property or
the variable `Info-file-list-for-emacs'.
-\(fn KEY)" t nil)
-
+(fn KEY)" t nil)
(autoload 'Info-speedbar-browser "info" "\
Initialize speedbar to display an Info node browser.
This will add a speedbar major display mode." t nil)
-
(autoload 'Info-bookmark-jump "info" "\
This implements the `handler' function interface for the record
type returned by `Info-bookmark-make-record', which see.
-\(fn BMK)" nil nil)
-
+(fn BMK)" nil nil)
(autoload 'info-display-manual "info" "\
Display an Info buffer displaying MANUAL.
If there is an existing Info buffer for MANUAL, display it.
@@ -19138,13 +17421,10 @@ Otherwise, visit the manual in a new Info buffer. In interactive
use, a prefix argument directs this command to limit the
completion alternatives to currently visited manuals.
-\(fn MANUAL)" t nil)
-
+(fn MANUAL)" t nil)
(register-definition-prefixes "info" '("Info-" "info-"))
-;;;***
-;;;### (autoloads nil "info-look" "info-look.el" (0 0 0 0))
;;; Generated autoloads from info-look.el
(autoload 'info-lookup-reset "info-look" "\
@@ -19153,48 +17433,56 @@ This command is useful if the user wants to start at the beginning without
quitting Emacs, for example, after some Info documents were updated on the
system." t nil)
(put 'info-lookup-symbol 'info-file "emacs")
-
(autoload 'info-lookup-symbol "info-look" "\
-Display the definition of SYMBOL, as found in the relevant manual.
-When this command is called interactively, it reads SYMBOL from the
-minibuffer. In the minibuffer, use \\<minibuffer-local-completion-map>\\[next-history-element] to yank the default argument
-value into the minibuffer so you can edit it. The default symbol is the
-one found at point.
+Look up and display documentation of SYMBOL in the relevant Info manual.
+SYMBOL should be an identifier: a function or method, a macro, a variable,
+a data type, a class, etc.
-With prefix arg MODE a query for the symbol help mode is offered.
+Interactively, prompt for SYMBOL; you can use \\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer
+to yank the default argument value into the minibuffer so you can edit it.
+The default symbol is the one found at point.
-\(fn SYMBOL &optional MODE)" t nil)
- (put 'info-lookup-file 'info-file "emacs")
+MODE is the major mode whose Info manuals to search for the documentation
+of SYMBOL. It defaults to the current buffer's `major-mode'; if that
+mode doesn't have any Info manuals known to Emacs, the command will
+prompt for MODE to use, with completion. With prefix arg, the command
+always prompts for MODE.
+Is SAME-WINDOW, try to reuse the current window instead of
+popping up a new one.
+
+(fn SYMBOL &optional MODE SAME-WINDOW)" t nil)
+ (put 'info-lookup-file 'info-file "emacs")
(autoload 'info-lookup-file "info-look" "\
-Display the documentation of a file.
-When this command is called interactively, it reads FILE from the minibuffer.
-In the minibuffer, use \\<minibuffer-local-completion-map>\\[next-history-element] to yank the default file name
-into the minibuffer so you can edit it.
-The default file name is the one found at point.
+Look up and display documentation of FILE in the relevant Info manual.
+FILE should be the name of a file; a notable example is a standard header
+file that is part of the C or C++ standard library.
-With prefix arg MODE a query for the file help mode is offered.
+Interactively, prompt for FILE; you can use \\<minibuffer-local-completion-map>\\[next-history-element] in the minibuffer
+to yank the default argument value into the minibuffer so you can edit it.
+The default file name is the one found at point.
-\(fn FILE &optional MODE)" t nil)
+MODE is the major mode whose Info manuals to search for the documentation
+of FILE. It defaults to the current buffer's `major-mode'; if that
+mode doesn't have any Info manuals known to Emacs, the command will
+prompt for MODE to use, with completion. With prefix arg, the command
+always prompts for MODE.
+(fn FILE &optional MODE)" t nil)
(autoload 'info-complete-symbol "info-look" "\
Perform completion on symbol preceding point.
-\(fn &optional MODE)" t nil)
-
+(fn &optional MODE)" t nil)
(autoload 'info-complete-file "info-look" "\
Perform completion on file preceding point.
-\(fn &optional MODE)" t nil)
-
+(fn &optional MODE)" t nil)
(register-definition-prefixes "info-look" '("info-"))
-;;;***
-;;;### (autoloads nil "info-xref" "info-xref.el" (0 0 0 0))
;;; Generated autoloads from info-xref.el
-(push (purecopy '(info-xref 3)) package--builtin-versions)
+(push (purecopy '(info-xref 3)) package--builtin-versions)
(autoload 'info-xref-check "info-xref" "\
Check external references in FILENAME, an info document.
Interactively from an `Info-mode' or `texinfo-mode' buffer the
@@ -19221,8 +17509,7 @@ not external references, which makes it rather easy for mistakes
to creep in or node name changes to go unnoticed.
`Info-validate' doesn't check external references either.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'info-xref-check-all "info-xref" "\
Check external references in all info documents in the info path.
`Info-directory-list' and `Info-additional-directory-list' are
@@ -19235,7 +17522,6 @@ particular the Emacs manuals normally don't. If you have a
source code directory in `Info-directory-list' then a lot of
extraneous files might be read. This will be time consuming but
should be harmless." t nil)
-
(autoload 'info-xref-check-all-custom "info-xref" "\
Check info references in all customize groups and variables.
Info references can be in `custom-manual' or `info-link' entries
@@ -19244,7 +17530,6 @@ of the `custom-links' for a variable.
Any `custom-load' autoloads in variables are loaded in order to
get full link information. This will be a lot of Lisp packages
and can take a long time." t nil)
-
(autoload 'info-xref-docstrings "info-xref" "\
Check docstring info node references in source files.
The given files are searched for docstring hyperlinks like
@@ -19266,25 +17551,19 @@ and links can be in the file commentary or elsewhere too. Even
.elc files can usually be checked successfully if you don't have
the sources handy.
-\(fn FILENAME-LIST)" t nil)
-
+(fn FILENAME-LIST)" t nil)
(register-definition-prefixes "info-xref" '("info-xref-"))
-;;;***
-;;;### (autoloads nil "informat" "informat.el" (0 0 0 0))
;;; Generated autoloads from informat.el
(autoload 'Info-tagify "informat" "\
Create or update Info file tag table in current buffer or in a region.
-\(fn &optional INPUT-BUFFER-NAME)" t nil)
-
+(fn &optional INPUT-BUFFER-NAME)" t nil)
(defvar Info-split-threshold 262144 "\
The number of characters by which `Info-split' splits an info file.")
-
(custom-autoload 'Info-split-threshold "informat" t)
-
(autoload 'Info-split "informat" "\
Split an info file into an indirect file plus bounded-size subfiles.
Each subfile will be up to the number of characters that
@@ -19298,22 +17577,17 @@ The subfiles are written in the same directory the original file is
in, with names generated by appending `-' and a number to the original
file name. The indirect file still functions as an Info file, but it
contains just the tag table and a directory of subfiles." t nil)
-
(autoload 'Info-validate "informat" "\
Check current buffer for validity as an Info file.
Check that every node pointer points to an existing node." t nil)
-
(autoload 'batch-info-validate "informat" "\
Run `Info-validate' on the files remaining on the command line.
Must be used only with -batch, and kills Emacs on completion.
Each file will be processed even if an error occurred previously.
For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\"" nil nil)
-
(register-definition-prefixes "informat" '("Info-validate-"))
-;;;***
-;;;### (autoloads nil "inline" "emacs-lisp/inline.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/inline.el
(autoload 'define-inline "inline" "\
@@ -19322,62 +17596,53 @@ Define an inline function NAME with arguments ARGS and body in BODY.
This is like `defmacro', but has several advantages.
See Info node `(elisp)Defining Functions' for more details.
-\(fn NAME ARGS &rest BODY)" nil t)
-
+(fn NAME ARGS &rest BODY)" nil t)
(function-put 'define-inline 'lisp-indent-function 'defun)
+(function-put 'define-inline 'doc-string-elt 3)
+(register-definition-prefixes "inline" '("inline-"))
-(function-put 'define-inline 'doc-string-elt '3)
+
+;;; Generated autoloads from cedet/srecode/insert.el
-(register-definition-prefixes "inline" '("inline-"))
+(register-definition-prefixes "srecode/insert" '("srecode-"))
+
+
+;;; Generated autoloads from leim/quail/ipa.el
+
+(register-definition-prefixes "quail/ipa" '("ipa-x-sampa-"))
-;;;***
-;;;### (autoloads nil "isearch-x" "international/isearch-x.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from international/isearch-x.el
(autoload 'isearch-toggle-specified-input-method "isearch-x" "\
Select an input method and turn it on in interactive search." t nil)
-
(autoload 'isearch-toggle-input-method "isearch-x" "\
Toggle input method in interactive search." t nil)
-
(autoload 'isearch-transient-input-method "isearch-x" "\
Activate transient input method in interactive search." t nil)
-
(autoload 'isearch-process-search-multibyte-characters "isearch-x" "\
-\(fn LAST-CHAR &optional COUNT)" nil nil)
-
+(fn LAST-CHAR &optional COUNT)" nil nil)
(register-definition-prefixes "isearch-x" '("isearch-"))
-;;;***
-;;;### (autoloads nil "isearchb" "isearchb.el" (0 0 0 0))
;;; Generated autoloads from isearchb.el
-(push (purecopy '(isearchb 1 5)) package--builtin-versions)
+(push (purecopy '(isearchb 1 5)) package--builtin-versions)
(autoload 'isearchb-activate "isearchb" "\
Active isearchb mode for subsequent alphanumeric keystrokes.
Executing this command again will terminate the search; or, if
the search has not yet begun, will toggle to the last buffer
accessed via isearchb." t nil)
-
(register-definition-prefixes "isearchb" '("isearchb"))
-;;;***
-;;;### (autoloads nil "iso-ascii" "international/iso-ascii.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from international/iso-ascii.el
(register-definition-prefixes "iso-ascii" '("iso-ascii-"))
-;;;***
-;;;### (autoloads nil "iso-cvt" "international/iso-cvt.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from international/iso-cvt.el
(autoload 'iso-spanish "iso-cvt" "\
@@ -19386,112 +17651,90 @@ Translate the region between FROM and TO using the table
`iso-spanish-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-german "iso-cvt" "\
Translate net conventions for German to ISO 8859-1.
Translate the region FROM and TO using the table
`iso-german-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-iso2tex "iso-cvt" "\
Translate ISO 8859-1 characters to TeX sequences.
Translate the region between FROM and TO using the table
`iso-iso2tex-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-tex2iso "iso-cvt" "\
Translate TeX sequences to ISO 8859-1 characters.
Translate the region between FROM and TO using the table
`iso-tex2iso-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-gtex2iso "iso-cvt" "\
Translate German TeX sequences to ISO 8859-1 characters.
Translate the region between FROM and TO using the table
`iso-gtex2iso-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-iso2gtex "iso-cvt" "\
Translate ISO 8859-1 characters to German TeX sequences.
Translate the region between FROM and TO using the table
`iso-iso2gtex-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-iso2duden "iso-cvt" "\
Translate ISO 8859-1 characters to Duden sequences.
Translate the region between FROM and TO using the table
`iso-iso2duden-trans-tab'.
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-iso2sgml "iso-cvt" "\
Translate ISO 8859-1 characters in the region to SGML entities.
Use entities from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\".
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-sgml2iso "iso-cvt" "\
Translate SGML entities in the region to ISO 8859-1 characters.
Use entities from \"ISO 8879:1986//ENTITIES Added Latin 1//EN\".
Optional arg BUFFER is ignored (for use in `format-alist').
-\(fn FROM TO &optional BUFFER)" t nil)
-
+(fn FROM TO &optional BUFFER)" t nil)
(autoload 'iso-cvt-read-only "iso-cvt" "\
Warn that format is read-only.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'iso-cvt-write-only "iso-cvt" "\
Warn that format is write-only.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'iso-cvt-define-menu "iso-cvt" "\
Add submenus to the File menu, to convert to and from various formats." t nil)
-
(register-definition-prefixes "iso-cvt" '("iso-"))
-;;;***
-;;;### (autoloads nil "iso8601" "calendar/iso8601.el" (0 0 0 0))
;;; Generated autoloads from calendar/iso8601.el
(register-definition-prefixes "iso8601" '("iso8601-"))
-;;;***
-;;;### (autoloads nil "ispell" "textmodes/ispell.el" (0 0 0 0))
;;; Generated autoloads from textmodes/ispell.el
(put 'ispell-check-comments 'safe-local-variable (lambda (a) (memq a '(nil t exclusive))))
-
(defvar ispell-personal-dictionary nil "\
File name of your personal spelling dictionary, or nil.
If nil, the default personal dictionary for your spelling checker is used.")
-
(custom-autoload 'ispell-personal-dictionary "ispell" t)
-
(put 'ispell-local-dictionary 'safe-local-variable 'string-or-null-p)
-
(defconst ispell-menu-map (let ((map (make-sparse-keymap "Spell"))) (define-key map [ispell-change-dictionary] `(menu-item ,(purecopy "Change Dictionary...") ispell-change-dictionary :help ,(purecopy "Supply explicit dictionary file name"))) (define-key map [ispell-kill-ispell] `(menu-item ,(purecopy "Kill Process") (lambda nil (interactive) (ispell-kill-ispell nil 'clear)) :enable (and (boundp 'ispell-process) ispell-process (eq (ispell-process-status) 'run)) :help ,(purecopy "Terminate Ispell subprocess"))) (define-key map [ispell-pdict-save] `(menu-item ,(purecopy "Save Dictionary") (lambda nil (interactive) (ispell-pdict-save t t)) :help ,(purecopy "Save personal dictionary"))) (define-key map [ispell-customize] `(menu-item ,(purecopy "Customize...") (lambda nil (interactive) (customize-group 'ispell)) :help ,(purecopy "Customize spell checking options"))) (define-key map [ispell-help] `(menu-item ,(purecopy "Help") (lambda nil (interactive) (describe-function 'ispell-help)) :help ,(purecopy "Show standard Ispell keybindings and commands"))) (define-key map [flyspell-mode] `(menu-item ,(purecopy "Automatic spell checking (Flyspell)") flyspell-mode :help ,(purecopy "Check spelling while you edit the text") :button (:toggle bound-and-true-p flyspell-mode))) (define-key map [ispell-complete-word] `(menu-item ,(purecopy "Complete Word") ispell-complete-word :help ,(purecopy "Complete word at cursor using dictionary"))) (define-key map [ispell-complete-word-interior-frag] `(menu-item ,(purecopy "Complete Word Fragment") ispell-complete-word-interior-frag :help ,(purecopy "Complete word fragment at cursor"))) (define-key map [ispell-continue] `(menu-item ,(purecopy "Continue Spell-Checking") ispell-continue :enable (and (boundp 'ispell-region-end) (marker-position ispell-region-end) (equal (marker-buffer ispell-region-end) (current-buffer))) :help ,(purecopy "Continue spell checking last region"))) (define-key map [ispell-word] `(menu-item ,(purecopy "Spell-Check Word") ispell-word :help ,(purecopy "Spell-check word at cursor"))) (define-key map [ispell-comments-and-strings] `(menu-item ,(purecopy "Spell-Check Comments") ispell-comments-and-strings :help ,(purecopy "Spell-check only comments and strings"))) (define-key map [ispell-region] `(menu-item ,(purecopy "Spell-Check Region") ispell-region :enable mark-active :help ,(purecopy "Spell-check text in marked region"))) (define-key map [ispell-message] `(menu-item ,(purecopy "Spell-Check Message") ispell-message :visible (eq major-mode 'mail-mode) :help ,(purecopy "Skip headers and included message text"))) (define-key map [ispell-buffer] `(menu-item ,(purecopy "Spell-Check Buffer") ispell-buffer :help ,(purecopy "Check spelling of selected buffer"))) map) "\
Key map for ispell menu.")
-
(fset 'ispell-menu-map (symbol-value 'ispell-menu-map))
-
(defvar ispell-skip-region-alist `((ispell-words-keyword forward-line) (ispell-dictionary-keyword forward-line) (ispell-pdict-keyword forward-line) (ispell-parsing-keyword forward-line) (,(purecopy "^---*BEGIN PGP [A-Z ]*--*") \, (purecopy "^---*END PGP [A-Z ]*--*")) (,(purecopy "^begin [0-9][0-9][0-9] [^ \11]+$") \, (purecopy "\nend\n")) (,(purecopy "^%!PS-Adobe-[123].0") \, (purecopy "\n%%EOF\n")) (,(purecopy "^---* \\(Start of \\)?[Ff]orwarded [Mm]essage") \, (purecopy "^---* End of [Ff]orwarded [Mm]essage"))) "\
Alist expressing beginning and end of regions not to spell check.
The alist key must be a regular expression.
@@ -19500,15 +17743,13 @@ Valid forms include:
(KEY . REGEXP) - skip to the end of REGEXP. REGEXP may be string or symbol.
(KEY REGEXP) - skip to end of REGEXP. REGEXP must be a string.
(KEY FUNCTION ARGS) - FUNCTION called with ARGS returns end of region.")
-
-(defvar ispell-tex-skip-alists (purecopy '((("\\\\addcontentsline" ispell-tex-arg-end 2) ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end) ("\\\\\\([aA]lph\\|arabic\\)" ispell-tex-arg-end) ("\\\\cref" ispell-tex-arg-end) ("\\\\bibliographystyle" ispell-tex-arg-end) ("\\\\makebox" ispell-tex-arg-end 0) ("\\\\e?psfig" ispell-tex-arg-end) ("\\\\document\\(class\\|style\\)" . "\\\\begin[ \11\n]*{[ \11\n]*document[ \11\n]*}")) (("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0) ("list" ispell-tex-arg-end 2) ("program" . "\\\\end[ \11\n]*{[ \11\n]*program[ \11\n]*}") ("verbatim\\*?" . "\\\\end[ \11\n]*{[ \11\n]*verbatim\\*?[ \11\n]*}")))) "\
+(defvar ispell-tex-skip-alists (purecopy '((("\\\\addcontentsline" ispell-tex-arg-end 2) ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end) ("\\\\\\([aA]lph\\|arabic\\)" ispell-tex-arg-end) ("\\\\cref" ispell-tex-arg-end) ("\\\\bibliographystyle" ispell-tex-arg-end) ("\\\\makebox" ispell-tex-arg-end 0) ("\\\\e?psfig" ispell-tex-arg-end) ("\\\\document\\(class\\|style\\)" . "\\\\begin[ \11\n]*{document}")) (("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0) ("list" ispell-tex-arg-end 2) ("program" . "\\\\end[ \11]*{program}") ("verbatim\\*?" . "\\\\end[ \11]*{verbatim\\*?}")))) "\
Lists of regions to be skipped in TeX mode.
First list is used raw.
Second list has key placed inside \\begin{}.
Delete or add any regions you want to be automatically selected
for skipping in latex mode.")
-
(defconst ispell-html-skip-alists '(("<[cC][oO][dD][eE]\\>[^>]*>" "</[cC][oO][dD][eE]*>") ("<[sS][cC][rR][iI][pP][tT]\\>[^>]*>" "</[sS][cC][rR][iI][pP][tT]>") ("<[aA][pP][pP][lL][eE][tT]\\>[^>]*>" "</[aA][pP][pP][lL][eE][tT]>") ("<[vV][eE][rR][bB]\\>[^>]*>" "<[vV][eE][rR][bB]\\>[^>]*>") ("<[tT][tT]/" "/") ("<[^ \11\n>]" ">") ("&[^ \11\n;]" "[; \11\n]")) "\
Lists of start and end keys to skip in HTML buffers.
Same format as `ispell-skip-region-alist'.
@@ -19516,7 +17757,6 @@ Note - substrings of other matches must come last
(e.g. \"<[tT][tT]/\" and \"<[^ \\t\\n>]\").")
(put 'ispell-local-pdict 'safe-local-variable 'stringp)
(define-key esc-map "$" 'ispell-word)
-
(autoload 'ispell-word "ispell" "\
Check spelling of word under or before the cursor.
If the word is not found in dictionary, display possible corrections
@@ -19524,7 +17764,7 @@ in a window allowing you to choose one.
If optional argument FOLLOWING is non-nil or if `ispell-following-word'
is non-nil when called interactively, then the following word
-\(rather than preceding) is checked when the cursor is not over a word.
+(rather than preceding) is checked when the cursor is not over a word.
When the optional argument QUIETLY is non-nil or `ispell-quietly' is non-nil
when called interactively, non-corrective messages are suppressed.
@@ -19544,17 +17784,15 @@ Return values:
nil word is correct or spelling is accepted.
0 word is inserted into buffer-local definitions.
\"word\" word corrected from word list.
-\(\"word\" arg) word is hand entered.
+(\"word\" arg) word is hand entered.
quit spell session exited.
-\(fn &optional FOLLOWING QUIETLY CONTINUE REGION)" t nil)
-
+(fn &optional FOLLOWING QUIETLY CONTINUE REGION)" t nil)
(autoload 'ispell-pdict-save "ispell" "\
Check to see if the personal dictionary has been modified.
If so, ask if it needs to be saved.
-\(fn &optional NO-QUERY FORCE-SAVE)" t nil)
-
+(fn &optional NO-QUERY FORCE-SAVE)" t nil)
(autoload 'ispell-help "ispell" "\
Display a list of the options available when a misspelling is encountered.
@@ -19578,14 +17816,12 @@ Selections are:
\\`C-l' Redraw screen.
\\`C-r' Recursive edit.
\\`C-z' Suspend Emacs or iconify frame." nil nil)
-
(autoload 'ispell-kill-ispell "ispell" "\
Kill current Ispell process (so that you may start a fresh one).
With NO-ERROR, just return non-nil if there was no Ispell running.
With CLEAR, buffer session localwords are cleaned.
-\(fn &optional NO-ERROR CLEAR)" t nil)
-
+(fn &optional NO-ERROR CLEAR)" t nil)
(autoload 'ispell-change-dictionary "ispell" "\
Change to dictionary DICT for Ispell.
With a prefix arg, set it \"globally\", for all buffers.
@@ -19593,15 +17829,15 @@ Without a prefix arg, set it \"locally\", just for this buffer.
By just answering RET you can find out what the current dictionary is.
-\(fn DICT &optional ARG)" t nil)
-
+(fn DICT &optional ARG)" t nil)
(autoload 'ispell-region "ispell" "\
Interactively check a region for spelling errors.
+Leave the mark at the last misspelled word that the user was queried about.
+
Return nil if spell session was terminated, otherwise returns shift offset
amount for last line processed.
-\(fn REG-START REG-END &optional RECHECKP SHIFT)" t nil)
-
+(fn REG-START REG-END &optional RECHECKP SHIFT)" t nil)
(autoload 'ispell-comments-and-strings "ispell" "\
Check comments and strings in the current buffer for spelling errors.
If called interactively with an active region, check only comments and
@@ -19609,23 +17845,19 @@ strings in the region.
When called from Lisp, START and END buffer positions can be provided
to limit the check.
-\(fn &optional START END)" t nil)
-
+(fn &optional START END)" t nil)
(autoload 'ispell-comment-or-string-at-point "ispell" "\
Check the comment or string containing point for spelling errors." t nil)
-
(autoload 'ispell-buffer "ispell" "\
-Check the current buffer for spelling errors interactively." t nil)
-
+Check the current buffer for spelling errors interactively.
+Leave the mark at the last misspelled word that the user was queried about." t nil)
(autoload 'ispell-buffer-with-debug "ispell" "\
`ispell-buffer' with some output sent to `ispell-debug-buffer'.
If APPEND is non-nil, don't erase previous debugging output.
-\(fn &optional APPEND)" t nil)
-
+(fn &optional APPEND)" t nil)
(autoload 'ispell-continue "ispell" "\
Continue a halted spelling session beginning with the current word." t nil)
-
(autoload 'ispell-complete-word "ispell" "\
Try to complete the word before or at point.
If optional INTERIOR-FRAG is non-nil, then the word may be a character
@@ -19633,11 +17865,9 @@ sequence inside of a word.
Standard ispell choices are then available.
-\(fn &optional INTERIOR-FRAG)" t nil)
-
+(fn &optional INTERIOR-FRAG)" t nil)
(autoload 'ispell-complete-word-interior-frag "ispell" "\
Completes word matching character sequence inside a word." t nil)
-
(autoload 'ispell "ispell" "\
Interactively check a region or buffer for spelling errors.
If `transient-mark-mode' is on, and a region is active, spell-check
@@ -19647,24 +17877,9 @@ Ispell dictionaries are not distributed with Emacs. If you are
looking for a dictionary, please see the distribution of the GNU ispell
program, or do an Internet search; there are various dictionaries
available on the net." t nil)
-
(autoload 'ispell-minor-mode "ispell" "\
Toggle last-word spell checking (Ispell minor mode).
-This is a minor mode. If called interactively, toggle the `ISpell
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `ispell-minor-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Ispell minor mode is a buffer-local minor mode. When enabled,
typing SPC or RET warns you if the previous word is incorrectly
spelled.
@@ -19676,8 +17891,21 @@ SPC.
For spell-checking \"on the fly\", not just after typing SPC or
RET, use `flyspell-mode'.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`ISpell minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `ispell-minor-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'ispell-message "ispell" "\
Check the spelling of a mail message or news post.
Don't check spelling of message headers except the Subject field.
@@ -19697,136 +17925,128 @@ in your init file:
You can bind this to the key C-c i in GNUS or mail by adding to
`news-reply-mode-hook' or `mail-mode-hook' the following lambda expression:
(lambda () (local-set-key \"\\C-ci\" \\='ispell-message))" t nil)
-
(register-definition-prefixes "ispell" '("check-ispell-version" "ispell-"))
-;;;***
-;;;### (autoloads nil "ja-dic-cnv" "international/ja-dic-cnv.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from international/ja-dic-cnv.el
(register-definition-prefixes "ja-dic-cnv" '("batch-skkdic-convert" "ja-dic-filename" "skkdic-"))
-;;;***
-;;;### (autoloads nil "ja-dic-utl" "international/ja-dic-utl.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from international/ja-dic-utl.el
(register-definition-prefixes "ja-dic-utl" '("skkdic-"))
-;;;***
-;;;### (autoloads nil "japan-util" "language/japan-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/japan-util.el
(autoload 'setup-japanese-environment-internal "japan-util" nil nil nil)
-
(autoload 'japanese-katakana "japan-util" "\
Convert argument to Katakana and return that.
The argument may be a character or string. The result has the same type.
The argument object is not altered--the value is a copy.
Optional argument HANKAKU t means to convert to `hankaku' Katakana
-\(`japanese-jisx0201-kana'), in which case return value
+(`japanese-jisx0201-kana'), in which case return value
may be a string even if OBJ is a character if two Katakanas are
necessary to represent OBJ.
-\(fn OBJ &optional HANKAKU)" nil nil)
-
+(fn OBJ &optional HANKAKU)" nil nil)
(autoload 'japanese-hiragana "japan-util" "\
Convert argument to Hiragana and return that.
The argument may be a character or string. The result has the same type.
The argument object is not altered--the value is a copy.
-\(fn OBJ)" nil nil)
-
+(fn OBJ)" nil nil)
(autoload 'japanese-hankaku "japan-util" "\
Convert argument to `hankaku' and return that.
The argument may be a character or string. The result has the same type.
The argument object is not altered--the value is a copy.
Optional argument ASCII-ONLY non-nil means to return only ASCII character.
-\(fn OBJ &optional ASCII-ONLY)" nil nil)
-
+(fn OBJ &optional ASCII-ONLY)" nil nil)
(autoload 'japanese-zenkaku "japan-util" "\
Convert argument to `zenkaku' and return that.
The argument may be a character or string. The result has the same type.
The argument object is not altered--the value is a copy.
-\(fn OBJ)" nil nil)
-
+(fn OBJ)" nil nil)
(autoload 'japanese-katakana-region "japan-util" "\
Convert Japanese `hiragana' chars in the region to `katakana' chars.
Optional argument HANKAKU t means to convert to `hankaku katakana' character
of which charset is `japanese-jisx0201-kana'.
-\(fn FROM TO &optional HANKAKU)" t nil)
-
+(fn FROM TO &optional HANKAKU)" t nil)
(autoload 'japanese-hiragana-region "japan-util" "\
Convert Japanese `katakana' chars in the region to `hiragana' chars.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'japanese-hankaku-region "japan-util" "\
Convert Japanese `zenkaku' chars in the region to `hankaku' chars.
`Zenkaku' chars belong to `japanese-jisx0208'
`Hankaku' chars belong to `ascii' or `japanese-jisx0201-kana'.
Optional argument ASCII-ONLY non-nil means to convert only to ASCII char.
-\(fn FROM TO &optional ASCII-ONLY)" t nil)
-
+(fn FROM TO &optional ASCII-ONLY)" t nil)
(autoload 'japanese-zenkaku-region "japan-util" "\
Convert hankaku' chars in the region to Japanese `zenkaku' chars.
`Zenkaku' chars belong to `japanese-jisx0208'
`Hankaku' chars belong to `ascii' or `japanese-jisx0201-kana'.
Optional argument KATAKANA-ONLY non-nil means to convert only KATAKANA char.
-\(fn FROM TO &optional KATAKANA-ONLY)" t nil)
-
+(fn FROM TO &optional KATAKANA-ONLY)" t nil)
(autoload 'read-hiragana-string "japan-util" "\
Read a Hiragana string from the minibuffer, prompting with string PROMPT.
If non-nil, second arg INITIAL-INPUT is a string to insert before reading.
-\(fn PROMPT &optional INITIAL-INPUT)" nil nil)
-
+(fn PROMPT &optional INITIAL-INPUT)" nil nil)
(register-definition-prefixes "japan-util" '("japanese-"))
-;;;***
-;;;### (autoloads nil "jka-compr" "jka-compr.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/japanese.el
+
+(register-definition-prefixes "quail/japanese" '("quail-japanese-"))
+
+
+;;; Generated autoloads from cedet/semantic/java.el
+
+(register-definition-prefixes "semantic/java" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/wisent/java-tags.el
+
+(register-definition-prefixes "semantic/wisent/java-tags" '("semantic-" "wisent-java-parse-error"))
+
+
+;;; Generated autoloads from cedet/semantic/wisent/javascript.el
+
+(register-definition-prefixes "semantic/wisent/javascript" '("semantic-" "wisent-javascript-jv-expand-tag"))
+
+
;;; Generated autoloads from jka-compr.el
(defvar jka-compr-inhibit nil "\
Non-nil means inhibit automatic uncompression temporarily.
Lisp programs can bind this to t to do that.
It is not recommended to set this variable permanently to anything but nil.")
-
(autoload 'jka-compr-handler "jka-compr" "\
-\(fn OPERATION &rest ARGS)" nil nil)
-
+(fn OPERATION &rest ARGS)" nil nil)
(autoload 'jka-compr-uninstall "jka-compr" "\
Uninstall jka-compr.
This removes the entries in `file-name-handler-alist' and `auto-mode-alist'
and `inhibit-local-variables-suffixes' that were added
by `jka-compr-install'." nil nil)
-
(register-definition-prefixes "jka-compr" '("compression-error" "jka-compr-"))
-;;;***
-;;;### (autoloads nil "js" "progmodes/js.el" (0 0 0 0))
;;; Generated autoloads from progmodes/js.el
-(push (purecopy '(js 9)) package--builtin-versions)
+(push (purecopy '(js 9)) package--builtin-versions)
(autoload 'js-mode "js" "\
Major mode for editing JavaScript.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'js-jsx-mode "js" "\
Major mode for editing JavaScript+JSX.
@@ -19840,69 +18060,51 @@ could set `js-jsx-syntax' to t in your init file, or in a
`js-jsx-enable' in `js-mode-hook'. You may be better served by
one of the aforementioned options instead of using this mode.
-\(fn)" t nil)
+(fn)" t nil)
(defalias 'javascript-mode 'js-mode)
-
(dolist (name (list "node" "nodejs" "gjs" "rhino")) (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'js-mode)))
-
(register-definition-prefixes "js" '("js-"))
-;;;***
-;;;### (autoloads nil "json" "json.el" (0 0 0 0))
;;; Generated autoloads from json.el
-(push (purecopy '(json 1 5)) package--builtin-versions)
+(push (purecopy '(json 1 5)) package--builtin-versions)
(register-definition-prefixes "json" '("json-"))
-;;;***
-;;;### (autoloads nil "jsonrpc" "jsonrpc.el" (0 0 0 0))
;;; Generated autoloads from jsonrpc.el
-(push (purecopy '(jsonrpc 1 0 14)) package--builtin-versions)
+(push (purecopy '(jsonrpc 1 0 15)) package--builtin-versions)
(register-definition-prefixes "jsonrpc" '("jsonrpc-"))
-;;;***
-;;;### (autoloads nil "kermit" "kermit.el" (0 0 0 0))
;;; Generated autoloads from kermit.el
(register-definition-prefixes "kermit" '("kermit-"))
-;;;***
-;;;### (autoloads nil "keypad" "emulation/keypad.el" (0 0 0 0))
;;; Generated autoloads from emulation/keypad.el
(defvar keypad-setup nil "\
Specifies the keypad setup for unshifted keypad keys when NumLock is off.
When selecting the plain numeric keypad setup, the character returned by the
decimal key must be specified.")
-
(custom-autoload 'keypad-setup "keypad" nil)
-
(defvar keypad-numlock-setup nil "\
Specifies the keypad setup for unshifted keypad keys when NumLock is on.
When selecting the plain numeric keypad setup, the character returned by the
decimal key must be specified.")
-
(custom-autoload 'keypad-numlock-setup "keypad" nil)
-
(defvar keypad-shifted-setup nil "\
Specifies the keypad setup for shifted keypad keys when NumLock is off.
When selecting the plain numeric keypad setup, the character returned by the
decimal key must be specified.")
-
(custom-autoload 'keypad-shifted-setup "keypad" nil)
-
(defvar keypad-numlock-shifted-setup nil "\
Specifies the keypad setup for shifted keypad keys when NumLock is off.
When selecting the plain numeric keypad setup, the character returned by the
decimal key must be specified.")
-
(custom-autoload 'keypad-numlock-shifted-setup "keypad" nil)
-
(autoload 'keypad-setup "keypad" "\
Set keypad bindings in `function-key-map' according to SETUP.
If optional second argument NUMLOCK is non-nil, the NumLock On bindings
@@ -19923,12 +18125,9 @@ keys are bound.
If SETUP is `numeric' and the optional fourth argument DECIMAL is non-nil,
the decimal key on the keypad is mapped to DECIMAL instead of `.'
-\(fn SETUP &optional NUMLOCK SHIFT DECIMAL)" nil nil)
+(fn SETUP &optional NUMLOCK SHIFT DECIMAL)" nil nil)
-;;;***
-;;;### (autoloads nil "kinsoku" "international/kinsoku.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from international/kinsoku.el
(autoload 'kinsoku "kinsoku" "\
@@ -19945,13 +18144,10 @@ shorter.
in one place, and is used for the text processing described above in
the context of text formatting.
-\(fn LINEBEG)" nil nil)
-
+(fn LINEBEG)" nil nil)
(register-definition-prefixes "kinsoku" '("kinsoku-"))
-;;;***
-;;;### (autoloads nil "kkc" "international/kkc.el" (0 0 0 0))
;;; Generated autoloads from international/kkc.el
(defvar kkc-after-update-conversion-functions nil "\
@@ -19960,7 +18156,6 @@ With this input method, a user can select a proper conversion from
candidate list. Each time he changes the selection, functions in this
list are called with two arguments; starting and ending buffer
positions that contains the current selection.")
-
(autoload 'kkc-region "kkc" "\
Convert Kana string in the current region to Kanji-Kana mixed string.
Users can select a desirable conversion interactively.
@@ -19969,14 +18164,12 @@ positions FROM and TO (integers or markers) specifying the target region.
When it returns, the point is at the tail of the selected conversion,
and the return value is the length of the conversion.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(register-definition-prefixes "kkc" '("kkc-"))
-;;;***
-;;;### (autoloads nil "kmacro" "kmacro.el" (0 0 0 0))
;;; Generated autoloads from kmacro.el
+
(global-set-key "\C-x(" #'kmacro-start-macro)
(global-set-key "\C-x)" #'kmacro-end-macro)
(global-set-key "\C-xe" #'kmacro-end-and-call-macro)
@@ -19984,13 +18177,8 @@ and the return value is the length of the conversion.
(global-set-key [f4] #'kmacro-end-or-call-macro)
(global-set-key "\C-x\C-k" #'kmacro-keymap)
(autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap)
-
-(autoload 'kmacro-exec-ring-item "kmacro" "\
-Execute item ITEM from the macro ring.
-ARG is the number of times to execute the item.
-
-\(fn ITEM ARG)" nil nil)
-
+(define-obsolete-function-alias 'kmacro-exec-ring-item #'funcall "29.1" "Execute item ITEM from the macro ring.
+ARG is the number of times to execute the item.")
(autoload 'kmacro-start-macro "kmacro" "\
Record subsequent keyboard input, defining a keyboard macro.
The commands are recorded even as they are executed.
@@ -20014,8 +18202,7 @@ Use \\[kmacro-name-last-macro] to give it a name that will remain valid even
after another macro is defined.
Use \\[kmacro-bind-to-key] to bind it to a key sequence.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'kmacro-end-macro "kmacro" "\
Finish defining a keyboard macro.
The definition was started by \\[kmacro-start-macro].
@@ -20027,8 +18214,7 @@ With numeric arg, repeat macro now that many times,
counting the definition just completed as the first repetition.
An argument of zero means repeat until error.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'kmacro-call-macro "kmacro" "\
Call the keyboard MACRO that you defined with \\[kmacro-start-macro].
A prefix argument serves as a repeat count. Zero means repeat until error.
@@ -20042,8 +18228,7 @@ for details on how to adjust or disable this behavior.
To give a macro a name so you can call it even after defining others,
use \\[kmacro-name-last-macro].
-\(fn ARG &optional NO-REPEAT END-MACRO MACRO)" t nil)
-
+(fn ARG &optional NO-REPEAT END-MACRO MACRO)" t nil)
(autoload 'kmacro-start-macro-or-insert-counter "kmacro" "\
Record subsequent keyboard input, defining a keyboard macro.
The commands are recorded even as they are executed.
@@ -20065,15 +18250,13 @@ The macro counter can be set directly via \\[kmacro-set-counter] and \\[kmacro-a
The format of the inserted value of the counter can be controlled
via \\[kmacro-set-format].
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'kmacro-end-or-call-macro "kmacro" "\
End kbd macro if currently being defined; else call last kbd macro.
With numeric prefix ARG, repeat macro that many times.
With \\[universal-argument], call second macro in macro ring.
-\(fn ARG &optional NO-REPEAT)" t nil)
-
+(fn ARG &optional NO-REPEAT)" t nil)
(autoload 'kmacro-end-and-call-macro "kmacro" "\
Call last keyboard macro, ending it first if currently being defined.
With numeric prefix ARG, repeat macro that many times.
@@ -20082,45 +18265,45 @@ Zero argument means repeat until there is an error.
To give a macro a name, so you can call it even after defining other
macros, use \\[kmacro-name-last-macro].
-\(fn ARG &optional NO-REPEAT)" t nil)
-
+(fn ARG &optional NO-REPEAT)" t nil)
(autoload 'kmacro-end-call-mouse "kmacro" "\
Move point to the position clicked with the mouse and call last kbd macro.
If kbd macro currently being defined end it before activating it.
-\(fn EVENT)" t nil)
+(fn EVENT)" t nil)
+(autoload 'kmacro "kmacro" "\
+Create a `kmacro' for macro bound to symbol or key.
+KEYS should be a vector or a string that obeys `key-valid-p'.
+(fn KEYS &optional COUNTER FORMAT)" nil nil)
(autoload 'kmacro-lambda-form "kmacro" "\
-Create lambda form for macro bound to symbol or key.
-\(fn MAC &optional COUNTER FORMAT)" nil nil)
-(register-definition-prefixes "kmacro" '("kdb-macro-redisplay" "kmacro-"))
+(fn MAC &optional COUNTER FORMAT)" nil nil)
+(make-obsolete 'kmacro-lambda-form 'kmacro "29.1")
+(register-definition-prefixes "kmacro" '("kmacro-"))
-;;;***
-;;;### (autoloads nil "korea-util" "language/korea-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/korea-util.el
(defvar default-korean-keyboard (purecopy (if (string-search "3" (or (getenv "HANGUL_KEYBOARD_TYPE") "")) "3" "")) "\
The kind of Korean keyboard for Korean (Hangul) input method.
\"\" for 2, \"3\" for 3, and \"3f\" for 3f.")
-
(autoload 'setup-korean-environment-internal "korea-util" nil nil nil)
-
(register-definition-prefixes "korea-util" '("exit-korean-environment" "isearch-" "korean-key-bindings" "quail-hangul-switch-" "toggle-korean-input-method"))
-;;;***
-;;;### (autoloads nil "lao-util" "language/lao-util.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/lao.el
+
+(register-definition-prefixes "quail/lao" '("lao-" "quail-lao-update-translation"))
+
+
;;; Generated autoloads from language/lao-util.el
(autoload 'lao-compose-string "lao-util" "\
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'lao-transcribe-single-roman-syllable-to-lao "lao-util" "\
Transcribe a Romanized Lao syllable in the region FROM and TO to Lao string.
Only the first syllable is transcribed.
@@ -20131,63 +18314,48 @@ LAO-STRING is the Lao character transcription of it.
Optional 3rd arg STR, if non-nil, is a string to search for Roman Lao
syllable. In that case, FROM and TO are indexes to STR.
-\(fn FROM TO &optional STR)" nil nil)
-
+(fn FROM TO &optional STR)" nil nil)
(autoload 'lao-transcribe-roman-to-lao-string "lao-util" "\
Transcribe Romanized Lao string STR to Lao character string.
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'lao-composition-function "lao-util" "\
-\(fn GSTRING DIRECTION)" nil nil)
-
+(fn GSTRING DIRECTION)" nil nil)
(autoload 'lao-compose-region "lao-util" "\
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(register-definition-prefixes "lao-util" '("lao-"))
-;;;***
-;;;### (autoloads nil "latexenc" "international/latexenc.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from international/latexenc.el
(defvar latex-inputenc-coding-alist (purecopy '(("ansinew" . windows-1252) ("applemac" . mac-roman) ("ascii" . us-ascii) ("cp1250" . windows-1250) ("cp1252" . windows-1252) ("cp1257" . cp1257) ("cp437de" . cp437) ("cp437" . cp437) ("cp850" . cp850) ("cp852" . cp852) ("cp858" . cp858) ("cp865" . cp865) ("latin1" . iso-8859-1) ("latin2" . iso-8859-2) ("latin3" . iso-8859-3) ("latin4" . iso-8859-4) ("latin5" . iso-8859-9) ("latin9" . iso-8859-15) ("latin10" . iso-8859-16) ("next" . next) ("utf8" . utf-8) ("utf8x" . utf-8))) "\
Mapping from LaTeX encodings in \"inputenc.sty\" to Emacs coding systems.
LaTeX encodings are specified with \"\\usepackage[encoding]{inputenc}\".
Used by the function `latexenc-find-file-coding-system'.")
-
(custom-autoload 'latex-inputenc-coding-alist "latexenc" t)
-
(autoload 'latexenc-inputenc-to-coding-system "latexenc" "\
Return the corresponding coding-system for the specified input encoding.
Return nil if no matching coding system can be found.
-\(fn INPUTENC)" nil nil)
-
+(fn INPUTENC)" nil nil)
(autoload 'latexenc-coding-system-to-inputenc "latexenc" "\
Return the corresponding input encoding for the specified coding system.
Return nil if no matching input encoding can be found.
-\(fn CS)" nil nil)
-
+(fn CS)" nil nil)
(autoload 'latexenc-find-file-coding-system "latexenc" "\
Determine the coding system of a LaTeX file if it uses \"inputenc.sty\".
The mapping from LaTeX's \"inputenc.sty\" encoding names to Emacs
coding system names is determined from `latex-inputenc-coding-alist'.
-\(fn ARG-LIST)" nil nil)
-
+(fn ARG-LIST)" nil nil)
(register-definition-prefixes "latexenc" '("latexenc-dont-use-"))
-;;;***
-;;;### (autoloads nil "latin1-disp" "international/latin1-disp.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from international/latin1-disp.el
(defvar latin1-display nil "\
@@ -20204,9 +18372,7 @@ charsets if you don't have a Unicode font with which to display them.
Setting this variable directly does not take effect;
use either \\[customize] or the function `latin1-display'.")
-
(custom-autoload 'latin1-display "latin1-disp" nil)
-
(autoload 'latin1-display "latin1-disp" "\
Set up Latin-1/ASCII display for the arguments character SETS.
See option `latin1-display' for the method. The members of the list
@@ -20214,8 +18380,7 @@ must be in `latin1-display-sets'. With no arguments, reset the
display for all of `latin1-display-sets'. See also
`latin1-display-setup'.
-\(fn &rest SETS)" nil nil)
-
+(fn &rest SETS)" nil nil)
(defvar latin1-display-ucs-per-lynx nil "\
Set up Latin-1/ASCII display for Unicode characters.
This uses the transliterations of the Lynx browser. The display isn't
@@ -20223,70 +18388,48 @@ changed if the display can render Unicode characters.
Setting this variable directly does not take effect;
use either \\[customize] or the function `latin1-display'.")
-
(custom-autoload 'latin1-display-ucs-per-lynx "latin1-disp" nil)
-
(register-definition-prefixes "latin1-disp" '("latin1-display-"))
-;;;***
-;;;### (autoloads nil "ld-script" "progmodes/ld-script.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/ld-script.el
(autoload 'ld-script-mode "ld-script" "\
A major mode to edit GNU ld script files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "ld-script" '("ld-script-"))
-;;;***
-;;;### (autoloads nil "ldap" "net/ldap.el" (0 0 0 0))
;;; Generated autoloads from net/ldap.el
(register-definition-prefixes "ldap" '("ldap-"))
-;;;***
-;;;### (autoloads nil "legacy-gnus-agent" "gnus/legacy-gnus-agent.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from gnus/legacy-gnus-agent.el
(register-definition-prefixes "legacy-gnus-agent" '("gnus-agent-"))
-;;;***
-;;;### (autoloads nil "less-css-mode" "textmodes/less-css-mode.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from textmodes/less-css-mode.el
(put 'less-css-compile-at-save 'safe-local-variable #'booleanp)
-
(put 'less-css-lessc-options 'safe-local-variable t)
-
(put 'less-css-output-directory 'safe-local-variable #'stringp)
-
(put 'less-css-input-file-name 'safe-local-variable #'stringp)
(add-to-list 'auto-mode-alist '("\\.less\\'" . less-css-mode))
-
(autoload 'less-css-mode "less-css-mode" "\
Major mode for editing Less files (http://lesscss.org/).
Special commands:
\\{less-css-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "less-css-mode" '("less-css-"))
-;;;***
-;;;### (autoloads nil "let-alist" "emacs-lisp/let-alist.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/let-alist.el
-(push (purecopy '(let-alist 1 0 6)) package--builtin-versions)
+(push (purecopy '(let-alist 1 0 6)) package--builtin-versions)
(autoload 'let-alist "let-alist" "\
Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
Dotted symbol is any symbol starting with a `.'. Only those present
@@ -20316,15 +18459,21 @@ the variables of the outer one. You can, however, access alists
inside the original alist by using dots inside the symbol, as
displayed in the example above.
-\(fn ALIST &rest BODY)" nil t)
+(fn ALIST &rest BODY)" nil t)
+(function-put 'let-alist 'lisp-indent-function 1)
+(register-definition-prefixes "let-alist" '("let-alist--"))
-(function-put 'let-alist 'lisp-indent-function '1)
+
+;;; Generated autoloads from cedet/semantic/lex.el
-(register-definition-prefixes "let-alist" '("let-alist--"))
+(register-definition-prefixes "semantic/lex" '("define-lex" "semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/lex-spp.el
+
+(register-definition-prefixes "semantic/lex-spp" '("define-lex-spp-" "semantic-lex-"))
-;;;***
-;;;### (autoloads nil "life" "play/life.el" (0 0 0 0))
;;; Generated autoloads from play/life.el
(autoload 'life "life" "\
@@ -20337,38 +18486,37 @@ generations (the default is `life-step-time').
When called from Lisp, optional argument STEP-TIME is the time to
sleep in seconds.
-\(fn &optional STEP-TIME)" t nil)
-
+(fn &optional STEP-TIME)" t nil)
(register-definition-prefixes "life" '("life-"))
-;;;***
-;;;### (autoloads nil "linum" "linum.el" (0 0 0 0))
;;; Generated autoloads from linum.el
(autoload 'linum-mode "linum" "\
Toggle display of line numbers in the left margin (Linum mode).
+This mode has been largely replaced by `display-line-numbers-mode'
+(which is much faster and has fewer interaction problems with other
+modes).
+
+Linum mode is a buffer-local minor mode.
+
This is a minor mode. If called interactively, toggle the `Linum
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+mode' mode. If the prefix argument is positive, enable the mode,
+and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `linum-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Linum mode is a buffer-local minor mode.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(put 'global-linum-mode 'globalized-minor-mode t)
-
(defvar global-linum-mode nil "\
Non-nil if Global Linum mode is enabled.
See the `global-linum-mode' command
@@ -20376,9 +18524,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-linum-mode'.")
-
(custom-autoload 'global-linum-mode "linum" nil)
-
(autoload 'global-linum-mode "linum" "\
Toggle Linum mode in all buffers.
With prefix ARG, enable Global Linum mode if ARG is positive;
@@ -20392,21 +18538,59 @@ Linum mode is enabled in all buffers where `linum-on' would do it.
See `linum-mode' for more information on Linum mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "linum" '("linum-"))
-;;;***
-;;;### (autoloads nil "lisp-mnt" "emacs-lisp/lisp-mnt.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from cedet/ede/linux.el
+
+(register-definition-prefixes "ede/linux" '("ede-linux-" "project-linux-"))
+
+
;;; Generated autoloads from emacs-lisp/lisp-mnt.el
(register-definition-prefixes "lisp-mnt" '("lm-"))
-;;;***
-;;;### (autoloads nil "loadhist" "loadhist.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/symref/list.el
+
+(register-definition-prefixes "semantic/symref/list" '("semantic-symref-"))
+
+
+;;; Generated autoloads from emacs-lisp/loaddefs-gen.el
+
+(put 'generated-autoload-file 'safe-local-variable 'stringp)
+(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
+(autoload 'loaddefs-generate "loaddefs-gen" "\
+Generate loaddefs files for Lisp files in the directories DIRS.
+DIR can be either a single directory or a list of directories.
+
+The autoloads will be written to OUTPUT-FILE. If any Lisp file
+binds `generated-autoload-file' as a file-local variable, write
+its autoloads into the specified file instead.
+
+The function does NOT recursively descend into subdirectories of the
+directory or directories specified.
+
+If EXTRA-DATA, include this string at the start of the generated
+file. This will also force generation of OUTPUT-FILE even if
+there are no autoloads to put into the file.
+
+If INCLUDE-PACKAGE-VERSION, include package version data.
+
+If GENERATE-FULL, don't update, but regenerate all the loaddefs files.
+
+(fn DIR OUTPUT-FILE &optional EXCLUDED-FILES EXTRA-DATA INCLUDE-PACKAGE-VERSION GENERATE-FULL)" nil nil)
+(autoload 'loaddefs-generate-batch "loaddefs-gen" "\
+Generate loaddefs.el files in batch mode.
+This scans for ;;;###autoload forms and related things.
+
+The first element on the command line should be the (main)
+loaddefs.el output file, and the rest are the directories to
+use." nil nil)
+(register-definition-prefixes "loaddefs-gen" '("autoload-" "generated-autoload-" "loaddefs-generate--"))
+
+
;;; Generated autoloads from loadhist.el
(autoload 'unload-feature "loadhist" "\
@@ -20432,21 +18616,21 @@ definitions in the variable `unload-function-defs-list' and could
remove symbols from it in the event that the package has done
something strange, such as redefining an Emacs function.
-\(fn FEATURE &optional FORCE)" t nil)
-
+(fn FEATURE &optional FORCE)" t nil)
(register-definition-prefixes "loadhist" '("feature-" "file-" "loadhist-" "read-feature" "unload-"))
-;;;***
-;;;### (autoloads nil "locate" "locate.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/locate.el
+
+(register-definition-prefixes "ede/locate" '("ede-locate-"))
+
+
;;; Generated autoloads from locate.el
(defvar locate-ls-subdir-switches (purecopy "-al") "\
`ls' switches for inserting subdirectories in `*Locate*' buffers.
This should contain the \"-l\" switch, but not the \"-F\" or \"-b\" switches.")
-
(custom-autoload 'locate-ls-subdir-switches "locate" t)
-
(autoload 'locate "locate" "\
Run the program `locate', putting results in `*Locate*' buffer.
Pass it SEARCH-STRING as argument. Interactively, prompt for SEARCH-STRING.
@@ -20469,8 +18653,7 @@ the docstring of that function for its meaning.
After preparing the results buffer, this runs `dired-mode-hook' and
then `locate-post-command-hook'.
-\(fn SEARCH-STRING &optional FILTER ARG)" t nil)
-
+(fn SEARCH-STRING &optional FILTER ARG)" t nil)
(autoload 'locate-with-filter "locate" "\
Run the executable program `locate' with a filter.
This function is similar to the function `locate', which see.
@@ -20486,13 +18669,10 @@ ARG is the interactive prefix arg, which has the same effect as in `locate'.
When called from Lisp, this function is identical with `locate',
except that FILTER is not optional.
-\(fn SEARCH-STRING FILTER &optional ARG)" t nil)
-
+(fn SEARCH-STRING FILTER &optional ARG)" t nil)
(register-definition-prefixes "locate" '("locate-"))
-;;;***
-;;;### (autoloads nil "log-edit" "vc/log-edit.el" (0 0 0 0))
;;; Generated autoloads from vc/log-edit.el
(autoload 'log-edit "log-edit" "\
@@ -20519,36 +18699,63 @@ If BUFFER is non-nil, `log-edit' will switch to that buffer, use it
to edit the log message and go back to the current buffer when
done. Otherwise, this function will use the current buffer.
-\(fn CALLBACK &optional SETUP PARAMS BUFFER MODE &rest IGNORE)" nil nil)
-
+(fn CALLBACK &optional SETUP PARAMS BUFFER MODE &rest IGNORE)" nil nil)
(register-definition-prefixes "log-edit" '("log-edit-"))
-;;;***
-;;;### (autoloads nil "log-view" "vc/log-view.el" (0 0 0 0))
;;; Generated autoloads from vc/log-view.el
(autoload 'log-view-mode "log-view" "\
Major mode for browsing CVS log output.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "log-view" '("log-view-"))
-;;;***
-;;;### (autoloads nil "lpr" "lpr.el" (0 0 0 0))
+;;; Generated autoloads from longlines.el
+
+(autoload 'longlines-mode "longlines" "\
+Toggle Long Lines mode in this buffer.
+
+When Long Lines mode is enabled, long lines are wrapped if they
+extend beyond `fill-column'. The soft newlines used for line
+wrapping will not show up when the text is yanked or saved to
+disk.
+
+If the variable `longlines-auto-wrap' is non-nil, lines are
+automatically wrapped whenever the buffer is changed. You can
+always call `fill-paragraph' to fill individual paragraphs.
+
+If the variable `longlines-show-hard-newlines' is non-nil, hard
+newlines are indicated with a symbol.
+
+This is a minor mode. If called interactively, toggle the
+`Longlines mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `longlines-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "longlines" '("longlines-"))
+
+
;;; Generated autoloads from lpr.el
(defvar lpr-windows-system (memq system-type '(ms-dos windows-nt)) "\
Non-nil if running on MS-DOS or MS Windows.")
-
(defvar lpr-lp-system (memq system-type '(usg-unix-v hpux)) "\
Non-nil if running on a system type that uses the \"lp\" command.")
-
(defvar printer-name (and (eq system-type 'ms-dos) "PRN") "\
The name of a local printer to which data is sent for printing.
-\(Note that PostScript files are sent to `ps-printer-name', which see.)
+(Note that PostScript files are sent to `ps-printer-name', which see.)
On Unix-like systems, a string value should be a name understood by
lpr's -P option; otherwise the value should be nil.
@@ -20560,17 +18767,13 @@ printers, or \"COM1\" to \"COM4\" or \"AUX\" for serial printers, or
\"//hostname/printer\" for a shared network printer. You can also set
it to the name of a file, in which case the output gets appended to that
file. If you want to discard the printed output, set this to \"NUL\".")
-
(custom-autoload 'printer-name "lpr" t)
-
(defvar lpr-switches nil "\
List of strings to pass as extra options for the printer program.
It is recommended to set `printer-name' instead of including an explicit
switch on this list.
See `lpr-command'.")
-
(custom-autoload 'lpr-switches "lpr" t)
-
(defvar lpr-command (purecopy (cond (lpr-windows-system "") (lpr-lp-system "lp") (t "lpr"))) "\
Name of program for printing a file.
@@ -20581,14 +18784,11 @@ Windows NT and Novell Netware respectively) are handled specially, using
`printer-name' as the destination for output; any other program is
treated like `lpr' except that an explicit filename is given as the last
argument.")
-
(custom-autoload 'lpr-command "lpr" t)
-
(autoload 'lpr-buffer "lpr" "\
Print buffer contents without pagination or page headers.
See the variables `lpr-switches' and `lpr-command'
for customization of the printer command." t nil)
-
(autoload 'print-buffer "lpr" "\
Paginate and print buffer contents.
@@ -20602,14 +18802,12 @@ in the print command itself; we expect them to request pagination.
See the variables `lpr-switches' and `lpr-command'
for further customization of the printer command." t nil)
-
(autoload 'lpr-region "lpr" "\
Print region contents without pagination or page headers.
See the variables `lpr-switches' and `lpr-command'
for customization of the printer command.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'print-region "lpr" "\
Paginate and print the region contents.
@@ -20624,26 +18822,24 @@ in the print command itself; we expect them to request pagination.
See the variables `lpr-switches' and `lpr-command'
for further customization of the printer command.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(register-definition-prefixes "lpr" '("lpr-" "print"))
-;;;***
-;;;### (autoloads nil "ls-lisp" "ls-lisp.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/lrt.el
+
+(register-definition-prefixes "quail/lrt" '("quail-lrt-update-translation"))
+
+
;;; Generated autoloads from ls-lisp.el
(defvar ls-lisp-support-shell-wildcards t "\
Non-nil means ls-lisp treats file patterns as shell wildcards.
Otherwise they are treated as Emacs regexps (for backward compatibility).")
-
(custom-autoload 'ls-lisp-support-shell-wildcards "ls-lisp" t)
-
(register-definition-prefixes "ls-lisp" '("ls-lisp-"))
-;;;***
-;;;### (autoloads nil "lunar" "calendar/lunar.el" (0 0 0 0))
;;; Generated autoloads from calendar/lunar.el
(autoload 'lunar-phases "lunar" "\
@@ -20651,34 +18847,27 @@ Display the quarters of the moon for last month, this month, and next month.
If called with an optional prefix argument ARG, prompts for month and year.
This function is suitable for execution in an init file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "lunar" '("calendar-lunar-phases" "diary-lunar-phases" "eclipse-check" "lunar-"))
-;;;***
-;;;### (autoloads nil "m4-mode" "progmodes/m4-mode.el" (0 0 0 0))
;;; Generated autoloads from progmodes/m4-mode.el
(autoload 'm4-mode "m4-mode" "\
A major mode to edit m4 macro files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "m4-mode" '("m4-"))
-;;;***
-;;;### (autoloads nil "macros" "macros.el" (0 0 0 0))
;;; Generated autoloads from macros.el
(defalias 'name-last-kbd-macro #'kmacro-name-last-macro)
-
(autoload 'insert-kbd-macro "macros" "\
Insert in buffer the definition of kbd macro MACRONAME, as Lisp code.
MACRONAME should be a symbol.
Optional second arg KEYS means also record the keys it is on
-\(this is the prefix argument, when calling interactively).
+(this is the prefix argument, when calling interactively).
This Lisp code will, when executed, define the kbd macro with the same
definition it has now. If you say to record the keys, the Lisp code
@@ -20689,8 +18878,7 @@ bindings.
To save a kbd macro, visit a file of Lisp code such as your `~/.emacs',
use this command, and then save the file.
-\(fn MACRONAME &optional KEYS)" t nil)
-
+(fn MACRONAME &optional KEYS)" t nil)
(autoload 'kbd-macro-query "macros" "\
Query user during kbd macro execution.
@@ -20709,8 +18897,7 @@ Your options are: \\<query-replace-map>
\\[recenter] Redisplay the screen, then ask again.
\\[edit] Enter recursive edit; ask again when you exit from that.
-\(fn FLAG)" t nil)
-
+(fn FLAG)" t nil)
(autoload 'apply-macro-to-region-lines "macros" "\
Apply last keyboard macro to all lines in the region.
For each line that begins in the region, move to the beginning of
@@ -20752,14 +18939,11 @@ and write a macro to massage a word into a table entry:
and then select the region of un-tablified names and use
`\\[apply-macro-to-region-lines]' to build the table from the names.
-\(fn TOP BOTTOM &optional MACRO)" t nil)
+(fn TOP BOTTOM &optional MACRO)" t nil)
(define-key ctl-x-map "q" 'kbd-macro-query)
+(register-definition-prefixes "macros" '("macro"))
-(register-definition-prefixes "macros" '("macros--insert-vector-macro"))
-
-;;;***
-;;;### (autoloads nil "mail-extr" "mail/mail-extr.el" (0 0 0 0))
;;; Generated autoloads from mail/mail-extr.el
(autoload 'mail-extract-address-components "mail-extr" "\
@@ -20777,8 +18961,8 @@ each recipient. If ALL is nil, then if ADDRESS contains more than
one recipients, all but the first is ignored.
ADDRESS may be a string or a buffer. If it is a buffer, the visible
-\(narrowed) portion of the buffer will be interpreted as the address.
-\(This feature exists so that the clever caller might be able to avoid
+(narrowed) portion of the buffer will be interpreted as the address.
+(This feature exists so that the clever caller might be able to avoid
consing a string.)
This function is primarily meant for when you're displaying the
@@ -20790,73 +18974,53 @@ non-display use, you should probably use
than `mail-header-parse-address', but does less post-processing
to the results.
-\(fn ADDRESS &optional ALL)" nil nil)
-
+(fn ADDRESS &optional ALL)" nil nil)
(autoload 'what-domain "mail-extr" "\
Convert mail domain DOMAIN to the country it corresponds to.
-\(fn DOMAIN)" t nil)
-
+(fn DOMAIN)" t nil)
(register-definition-prefixes "mail-extr" '("mail-extr-"))
-;;;***
-;;;### (autoloads nil "mail-hist" "mail/mail-hist.el" (0 0 0 0))
;;; Generated autoloads from mail/mail-hist.el
(autoload 'mail-hist-define-keys "mail-hist" "\
Define keys for accessing mail header history. For use in hooks." nil nil)
-
(autoload 'mail-hist-enable "mail-hist" nil nil nil)
-
(defvar mail-hist-keep-history t "\
Non-nil means keep a history for headers and text of outgoing mail.")
-
(custom-autoload 'mail-hist-keep-history "mail-hist" t)
-
(autoload 'mail-hist-put-headers-into-history "mail-hist" "\
Put headers and contents of this message into mail header history.
Each header has its own independent history, as does the body of the
message.
This function normally would be called when the message is sent." nil nil)
-
(register-definition-prefixes "mail-hist" '("mail-hist-"))
-;;;***
-;;;### (autoloads nil "mail-parse" "mail/mail-parse.el" (0 0 0 0))
;;; Generated autoloads from mail/mail-parse.el
(register-definition-prefixes "mail-parse" '("mail-"))
-;;;***
-;;;### (autoloads nil "mail-prsvr" "mail/mail-prsvr.el" (0 0 0 0))
;;; Generated autoloads from mail/mail-prsvr.el
(register-definition-prefixes "mail-prsvr" '("mail-parse-"))
-;;;***
-;;;### (autoloads nil "mail-source" "gnus/mail-source.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from gnus/mail-source.el
(register-definition-prefixes "mail-source" '("mail-source"))
-;;;***
-;;;### (autoloads nil "mail-utils" "mail/mail-utils.el" (0 0 0 0))
;;; Generated autoloads from mail/mail-utils.el
(defvar mail-use-rfc822 nil "\
If non-nil, use a full, hairy RFC 822 (or later) parser on mail addresses.
Otherwise, (the default) use a smaller, somewhat faster, and
often correct parser.")
-
(custom-autoload 'mail-use-rfc822 "mail-utils" t)
-
(defvar mail-dont-reply-to-names nil "\
Regexp specifying addresses to prune from a reply message.
If this is nil, it is set the first time you compose a reply, to
@@ -20864,14 +19028,11 @@ a value which excludes your own email address.
Matching addresses are excluded from the Cc field in replies, and
also the To field, unless this would leave an empty To field.")
-
(custom-autoload 'mail-dont-reply-to-names "mail-utils" t)
-
(autoload 'mail-file-babyl-p "mail-utils" "\
Return non-nil if FILE is a Babyl file.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'mail-quote-printable "mail-utils" "\
Convert a string to the \"quoted printable\" Q encoding if necessary.
If the string contains only ASCII characters and no troublesome ones,
@@ -20880,22 +19041,19 @@ we return it unconverted.
If the optional argument WRAPPER is non-nil,
we add the wrapper characters =?ISO-8859-1?Q?....?=.
-\(fn STRING &optional WRAPPER)" nil nil)
-
+(fn STRING &optional WRAPPER)" nil nil)
(autoload 'mail-quote-printable-region "mail-utils" "\
Convert the region to the \"quoted printable\" Q encoding.
If the optional argument WRAPPER is non-nil,
we add the wrapper characters =?ISO-8859-1?Q?....?=.
-\(fn BEG END &optional WRAPPER)" t nil)
-
+(fn BEG END &optional WRAPPER)" t nil)
(autoload 'mail-unquote-printable "mail-utils" "\
Undo the \"quoted printable\" encoding.
If the optional argument WRAPPER is non-nil,
we expect to find and remove the wrapper characters =?ISO-8859-1?Q?....?=.
-\(fn STRING &optional WRAPPER)" nil nil)
-
+(fn STRING &optional WRAPPER)" nil nil)
(autoload 'mail-unquote-printable-region "mail-utils" "\
Undo the \"quoted printable\" encoding in buffer from BEG to END.
If the optional argument WRAPPER is non-nil,
@@ -20907,8 +19065,7 @@ If UNIBYTE is non-nil, insert converted characters as unibyte.
That is useful if you are going to character code decoding afterward,
as Rmail does.
-\(fn BEG END &optional WRAPPER NOERROR UNIBYTE)" t nil)
-
+(fn BEG END &optional WRAPPER NOERROR UNIBYTE)" t nil)
(autoload 'mail-fetch-field "mail-utils" "\
Return the value of the header field whose type is FIELD-NAME.
If second arg LAST is non-nil, use the last field of type FIELD-NAME.
@@ -20919,13 +19076,10 @@ included in the result.
The buffer should be narrowed to just the header, else false
matches may be returned from the message body.
-\(fn FIELD-NAME &optional LAST ALL LIST DELETE)" nil nil)
-
+(fn FIELD-NAME &optional LAST ALL LIST DELETE)" nil nil)
(register-definition-prefixes "mail-utils" '("mail-"))
-;;;***
-;;;### (autoloads nil "mailabbrev" "mail/mailabbrev.el" (0 0 0 0))
;;; Generated autoloads from mail/mailabbrev.el
(defvar mail-abbrevs-mode nil "\
@@ -20935,42 +19089,37 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `mail-abbrevs-mode'.")
-
(custom-autoload 'mail-abbrevs-mode "mailabbrev" nil)
-
(autoload 'mail-abbrevs-mode "mailabbrev" "\
Toggle abbrev expansion of mail aliases (Mail Abbrevs mode).
-This is a minor mode. If called interactively, toggle the
-`Mail-Abbrevs mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='mail-abbrevs-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Mail Abbrevs mode is a global minor mode. When enabled,
abbrev-like expansion is performed when editing certain mail
headers (those specified by `mail-abbrev-mode-regexp'), based on
the entries in your `mail-personal-alias-file'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Mail-Abbrevs mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='mail-abbrevs-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'mail-abbrevs-setup "mailabbrev" "\
Initialize use of the `mailabbrev' package." nil nil)
-
(autoload 'build-mail-abbrevs "mailabbrev" "\
Read mail aliases from personal mail alias file and set `mail-abbrevs'.
By default this is the file specified by `mail-personal-alias-file'.
-\(fn &optional FILE RECURSIVEP)" nil nil)
-
+(fn &optional FILE RECURSIVEP)" nil nil)
(autoload 'define-mail-abbrev "mailabbrev" "\
Define NAME as a mail alias abbrev that translates to DEFINITION.
If DEFINITION contains multiple addresses, separate them with commas.
@@ -20980,13 +19129,10 @@ from a mailrc file. In that case, addresses are separated with
spaces and addresses with embedded spaces are surrounded by
double-quotes.
-\(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil)
-
+(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil)
(register-definition-prefixes "mailabbrev" '("mail-" "merge-mail-abbrevs" "rebuild-mail-abbrevs"))
-;;;***
-;;;### (autoloads nil "mailalias" "mail/mailalias.el" (0 0 0 0))
;;; Generated autoloads from mail/mailalias.el
(defvar mail-complete-style 'angles "\
@@ -20997,9 +19143,7 @@ If `parens', they look like:
king@grassland.com (Elvis Parsley)
If `angles', they look like:
Elvis Parsley <king@grassland.com>")
-
(custom-autoload 'mail-complete-style "mailalias" t)
-
(autoload 'expand-mail-aliases "mailalias" "\
Expand all mail aliases in suitable header fields found between BEG and END.
If interactive, expand in header fields.
@@ -21009,8 +19153,7 @@ their `Resent-' variants.
Optional second arg EXCLUDE may be a regular expression defining text to be
removed from alias expansions.
-\(fn BEG END &optional EXCLUDE)" t nil)
-
+(fn BEG END &optional EXCLUDE)" t nil)
(autoload 'define-mail-alias "mailalias" "\
Define NAME as a mail alias that translates to DEFINITION.
This means that sending a message to NAME will actually send to DEFINITION.
@@ -21020,58 +19163,44 @@ If FROM-MAILRC-FILE is non-nil, then addresses in DEFINITION
can be separated by spaces; an address can contain spaces
if it is quoted with double-quotes.
-\(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil)
-
+(fn NAME DEFINITION &optional FROM-MAILRC-FILE)" t nil)
(autoload 'mail-completion-at-point-function "mailalias" "\
Compute completion data for mail aliases.
For use on `completion-at-point-functions'." nil nil)
-
(autoload 'mail-complete "mailalias" "\
Perform completion on header field or word preceding point.
Completable headers are according to `mail-complete-alist'. If none matches
current header, calls `mail-complete-function' and passes prefix ARG if any.
-\(fn ARG)" t nil)
-
-(make-obsolete 'mail-complete 'mail-completion-at-point-function '"24.1")
-
+(fn ARG)" t nil)
+(make-obsolete 'mail-complete 'mail-completion-at-point-function "24.1")
(register-definition-prefixes "mailalias" '("build-mail-aliases" "mail-"))
-;;;***
-;;;### (autoloads nil "mailcap" "net/mailcap.el" (0 0 0 0))
;;; Generated autoloads from net/mailcap.el
(autoload 'mailcap-mime-type-to-extension "mailcap" "\
Return a file name extension based on a MIME-TYPE.
For instance, `image/png' will result in `png'.
-\(fn MIME-TYPE)" nil nil)
-
+(fn MIME-TYPE)" nil nil)
(register-definition-prefixes "mailcap" '("mailcap-"))
-;;;***
-;;;### (autoloads nil "mailclient" "mail/mailclient.el" (0 0 0 0))
;;; Generated autoloads from mail/mailclient.el
(autoload 'mailclient-send-it "mailclient" "\
Pass current buffer on to the system's mail client.
Suitable value for `send-mail-function'.
The mail client is taken to be the handler of mailto URLs." nil nil)
-
(register-definition-prefixes "mailclient" '("mailclient-"))
-;;;***
-;;;### (autoloads nil "mailheader" "mail/mailheader.el" (0 0 0 0))
;;; Generated autoloads from mail/mailheader.el
(register-definition-prefixes "mailheader" '("mail-header"))
-;;;***
-;;;### (autoloads nil "mairix" "net/mairix.el" (0 0 0 0))
;;; Generated autoloads from net/mairix.el
(autoload 'mairix-search "mairix" "\
@@ -21079,51 +19208,49 @@ Call Mairix with SEARCH.
If THREADS is non-nil, also display whole threads of found
messages. Results will be put into the default search file.
-\(fn SEARCH THREADS)" t nil)
-
+(fn SEARCH THREADS)" t nil)
(autoload 'mairix-use-saved-search "mairix" "\
Use a saved search for querying Mairix." t nil)
-
(autoload 'mairix-edit-saved-searches-customize "mairix" "\
Edit the list of saved searches in a customization buffer." t nil)
-
(autoload 'mairix-search-from-this-article "mairix" "\
Search messages from sender of the current article.
This is effectively a shortcut for calling `mairix-search' with
f:current_from. If prefix THREADS is non-nil, include whole
threads.
-\(fn THREADS)" t nil)
-
+(fn THREADS)" t nil)
(autoload 'mairix-search-thread-this-article "mairix" "\
Search thread for the current article.
This is effectively a shortcut for calling `mairix-search'
with m:msgid of the current article and enabled threads." t nil)
-
(autoload 'mairix-widget-search-based-on-article "mairix" "\
Create mairix query based on current article using widgets." t nil)
-
(autoload 'mairix-edit-saved-searches "mairix" "\
Edit current mairix searches." t nil)
-
(autoload 'mairix-widget-search "mairix" "\
Create mairix query interactively using graphical widgets.
MVALUES may contain values from current article.
-\(fn &optional MVALUES)" t nil)
-
+(fn &optional MVALUES)" t nil)
(autoload 'mairix-update-database "mairix" "\
Call mairix for updating the database for SERVERS.
Mairix will be called asynchronously unless
`mairix-synchronous-update' is t. Mairix will be called with
`mairix-update-options'." t nil)
-
(register-definition-prefixes "mairix" '("mairix-"))
-;;;***
-;;;### (autoloads nil "make-mode" "progmodes/make-mode.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from cedet/semantic/bovine/make.el
+
+(register-definition-prefixes "semantic/bovine/make" '("makefile-mode" "semantic-"))
+
+
+;;; Generated autoloads from cedet/ede/make.el
+
+(register-definition-prefixes "ede/make" '("ede-"))
+
+
;;; Generated autoloads from progmodes/make-mode.el
(autoload 'makefile-mode "make-mode" "\
@@ -21211,53 +19338,51 @@ Makefile mode can be configured by modifying the following variables:
on one of those in the minibuffer whenever you enter a `.'.
at the beginning of a line in Makefile mode.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'makefile-automake-mode "make-mode" "\
An adapted `makefile-mode' that knows about automake.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'makefile-gmake-mode "make-mode" "\
An adapted `makefile-mode' that knows about gmake.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'makefile-makepp-mode "make-mode" "\
An adapted `makefile-mode' that knows about makepp.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'makefile-bsdmake-mode "make-mode" "\
An adapted `makefile-mode' that knows about BSD make.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'makefile-imake-mode "make-mode" "\
An adapted `makefile-mode' that knows about imake.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "make-mode" '("makefile-"))
-;;;***
-;;;### (autoloads nil "makesum" "makesum.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/makefile-edit.el
+
+(register-definition-prefixes "ede/makefile-edit" '("makefile-"))
+
+
+;;; Generated autoloads from textmodes/makeinfo.el
+
+(register-definition-prefixes "makeinfo" '("makeinfo-"))
+
+
;;; Generated autoloads from makesum.el
(autoload 'make-command-summary "makesum" "\
Make a summary of current key bindings in the buffer *Summary*.
Previous contents of that buffer are killed first." t nil)
-
(register-definition-prefixes "makesum" '("double-column"))
-;;;***
-;;;### (autoloads nil "man" "man.el" (0 0 0 0))
;;; Generated autoloads from man.el
(defalias 'manual-entry 'man)
-
(autoload 'man "man" "\
Get a Un*x manual page and put it in a buffer.
This command is the top-level command in the man package.
@@ -21299,50 +19424,38 @@ Note that in some cases you will need to use \\[quoted-insert] to quote the
SPC character in the above examples, because this command attempts
to auto-complete your input based on the installed manual pages.
-\(fn MAN-ARGS)" t nil)
-
+(fn MAN-ARGS)" t nil)
(autoload 'man-follow "man" "\
Get a Un*x manual page of the item under point and put it in a buffer.
-\(fn MAN-ARGS)" '(man-common) nil)
-
+(fn MAN-ARGS)" '(man-common) nil)
(autoload 'Man-bookmark-jump "man" "\
Default bookmark handler for Man buffers.
-\(fn BOOKMARK)" nil nil)
+(fn BOOKMARK)" nil nil)
+(autoload 'Man-context-menu "man" "\
+Populate MENU with commands that open a man page at point.
+(fn MENU CLICK)" nil nil)
(register-definition-prefixes "man" '("Man-" "man"))
-;;;***
-;;;### (autoloads nil "map" "emacs-lisp/map.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/map.el
-(push (purecopy '(map 3 2 1)) package--builtin-versions)
+(push (purecopy '(map 3 2 1)) package--builtin-versions)
(register-definition-prefixes "map" '("map-"))
-;;;***
-;;;### (autoloads nil "master" "master.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/map.el
+
+(register-definition-prefixes "srecode/map" '("srecode-"))
+
+
;;; Generated autoloads from master.el
(autoload 'master-mode "master" "\
Toggle Master mode.
-This is a minor mode. If called interactively, toggle the `Master
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `master-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Master mode is enabled, you can scroll the slave buffer
using the following commands:
@@ -21352,13 +19465,24 @@ The slave buffer is stored in the buffer-local variable `master-of'.
You can set this variable using `master-set-slave'. You can show
yourself the value of `master-of' by calling `master-show-slave'.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Master mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `master-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "master" '("master-"))
-;;;***
-;;;### (autoloads nil "mb-depth" "mb-depth.el" (0 0 0 0))
;;; Generated autoloads from mb-depth.el
(defvar minibuffer-depth-indicate-mode nil "\
@@ -21368,47 +19492,39 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `minibuffer-depth-indicate-mode'.")
-
(custom-autoload 'minibuffer-depth-indicate-mode "mb-depth" nil)
-
(autoload 'minibuffer-depth-indicate-mode "mb-depth" "\
Toggle Minibuffer Depth Indication mode.
-This is a minor mode. If called interactively, toggle the
+Minibuffer Depth Indication mode is a global minor mode. When
+enabled, any recursive use of the minibuffer will show the
+recursion depth in the minibuffer prompt. This is only useful if
+`enable-recursive-minibuffers' is non-nil.
+
+This is a global minor mode. If called interactively, toggle the
`Minibuffer-Depth-Indicate mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='minibuffer-depth-indicate-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Minibuffer Depth Indication mode is a global minor mode. When
-enabled, any recursive use of the minibuffer will show the
-recursion depth in the minibuffer prompt. This is only useful if
-`enable-recursive-minibuffers' is non-nil.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "mb-depth" '("minibuffer-depth-"))
-;;;***
-;;;### (autoloads nil "md4" "md4.el" (0 0 0 0))
;;; Generated autoloads from md4.el
(register-definition-prefixes "md4" '("md4"))
-;;;***
-;;;### (autoloads nil "memory-report" "emacs-lisp/memory-report.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from emacs-lisp/memory-report.el
(autoload 'memory-report "memory-report" "\
@@ -21417,197 +19533,156 @@ Generate a report of how Emacs is using memory.
This report is approximate, and will commonly over-count memory
usage by variables, because shared data structures will usually
by counted more than once." t nil)
-
(register-definition-prefixes "memory-report" '("memory-report-"))
-;;;***
-;;;### (autoloads nil "message" "gnus/message.el" (0 0 0 0))
;;; Generated autoloads from gnus/message.el
(define-mail-user-agent 'message-user-agent 'message-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook)
-
(autoload 'message-mode "message" "\
Major mode for editing mail and news to be sent.
Like `text-mode', but with these additional commands:
\\{message-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'message-mail "message" "\
Start editing a mail message to be sent.
OTHER-HEADERS is an alist of header/value pairs. CONTINUE says whether
to continue editing a message already being composed. SWITCH-FUNCTION
is a function used to switch to and display the mail buffer.
-\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest _)" t nil)
-
+(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest _)" t nil)
(autoload 'message-news "message" "\
Start editing a news article to be sent.
-\(fn &optional NEWSGROUPS SUBJECT)" t nil)
-
+(fn &optional NEWSGROUPS SUBJECT)" t nil)
(autoload 'message-reply "message" "\
Start editing a reply to the article in the current buffer.
-\(fn &optional TO-ADDRESS WIDE SWITCH-FUNCTION)" t nil)
-
+(fn &optional TO-ADDRESS WIDE SWITCH-FUNCTION)" t nil)
(autoload 'message-wide-reply "message" "\
Make a \"wide\" reply to the message in the current buffer.
-\(fn &optional TO-ADDRESS)" t nil)
-
+(fn &optional TO-ADDRESS)" t nil)
(autoload 'message-followup "message" "\
Follow up to the message in the current buffer.
If TO-NEWSGROUPS, use that as the new Newsgroups line.
-\(fn &optional TO-NEWSGROUPS)" t nil)
-
+(fn &optional TO-NEWSGROUPS)" t nil)
(autoload 'message-cancel-news "message" "\
Cancel an article you posted.
If ARG, allow editing of the cancellation message.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'message-supersede "message" "\
Start composing a message to supersede the current message.
This is done simply by taking the old article and adding a Supersedes
header line with the old Message-ID." t nil)
-
(autoload 'message-recover "message" "\
Reread contents of current buffer from its last auto-save file." t nil)
-
(autoload 'message-forward "message" "\
Forward the current message via mail.
Optional NEWS will use news to forward instead of mail.
Optional DIGEST will use digest to forward.
-\(fn &optional NEWS DIGEST)" t nil)
-
+(fn &optional NEWS DIGEST)" t nil)
(autoload 'message-forward-make-body "message" "\
-\(fn FORWARD-BUFFER &optional DIGEST)" nil nil)
-
+(fn FORWARD-BUFFER &optional DIGEST)" nil nil)
(autoload 'message-forward-rmail-make-body "message" "\
-\(fn FORWARD-BUFFER)" nil nil)
-
+(fn FORWARD-BUFFER)" nil nil)
(autoload 'message-insinuate-rmail "message" "\
Let RMAIL use message to forward." t nil)
-
(autoload 'message-resend "message" "\
Resend the current article to ADDRESS.
-\(fn ADDRESS)" t nil)
-
+(fn ADDRESS)" t nil)
(autoload 'message-bounce "message" "\
Re-mail the current message.
This only makes sense if the current message is a bounce message that
contains some mail you have written which has been bounced back to
you." t nil)
-
(autoload 'message-mail-other-window "message" "\
Like `message-mail' command, but display mail buffer in another window.
-\(fn &optional TO SUBJECT)" t nil)
-
+(fn &optional TO SUBJECT)" t nil)
(autoload 'message-mail-other-frame "message" "\
Like `message-mail' command, but display mail buffer in another frame.
-\(fn &optional TO SUBJECT)" t nil)
-
+(fn &optional TO SUBJECT)" t nil)
(autoload 'message-news-other-window "message" "\
Start editing a news article to be sent.
-\(fn &optional NEWSGROUPS SUBJECT)" t nil)
-
+(fn &optional NEWSGROUPS SUBJECT)" t nil)
(autoload 'message-news-other-frame "message" "\
Start editing a news article to be sent.
-\(fn &optional NEWSGROUPS SUBJECT)" t nil)
-
+(fn &optional NEWSGROUPS SUBJECT)" t nil)
(autoload 'message-bold-region "message" "\
Bold all nonblank characters in the region.
Works by overstriking characters.
Called from program, takes two arguments START and END
which specify the range to operate on.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'message-unbold-region "message" "\
Remove all boldness (overstruck characters) in the region.
Called from program, takes two arguments START and END
which specify the range to operate on.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'message-mailto "message" "\
Command to parse command line mailto: links.
This is meant to be used for MIME handlers: Setting the handler
for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
will then start up Emacs ready to compose mail. For emacsclient use
- emacsclient -e '(message-mailto \"%u\")'
-
-\(fn &optional URL)" t nil)
+ emacsclient -e \\='(message-mailto \"%u\")'
+(fn &optional URL)" t nil)
(register-definition-prefixes "message" '("message-"))
-;;;***
-;;;### (autoloads nil "meta-mode" "progmodes/meta-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/meta-mode.el
-(push (purecopy '(meta-mode 1 0)) package--builtin-versions)
+(push (purecopy '(meta-mode 1 0)) package--builtin-versions)
(autoload 'metafont-mode "meta-mode" "\
Major mode for editing Metafont sources.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'metapost-mode "meta-mode" "\
Major mode for editing MetaPost sources.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "meta-mode" '("font-lock-match-meta-declaration-item-and-skip-to-next" "meta"))
-;;;***
-;;;### (autoloads nil "mh-acros" "mh-e/mh-acros.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-acros.el
(register-definition-prefixes "mh-acros" '("defmacro-mh" "defun-mh" "mh-" "with-mh-folder-updating"))
-;;;***
-;;;### (autoloads nil "mh-alias" "mh-e/mh-alias.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-alias.el
(register-definition-prefixes "mh-alias" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-buffers" "mh-e/mh-buffers.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-buffers.el
(register-definition-prefixes "mh-buffers" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-comp" "mh-e/mh-comp.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-comp.el
(autoload 'mh-smail "mh-comp" "\
Compose a message with the MH mail system.
See `mh-send' for more details on composing mail." t nil)
-
(autoload 'mh-smail-other-window "mh-comp" "\
Compose a message with the MH mail system in other window.
See `mh-send' for more details on composing mail." t nil)
-
(autoload 'mh-smail-batch "mh-comp" "\
Compose a message with the MH mail system.
@@ -21621,10 +19696,8 @@ SUBJECT, and OTHER-HEADERS. Additional arguments are IGNORED.
This function remains for Emacs 21 compatibility. New
applications should use `mh-user-agent-compose'.
-\(fn &optional TO SUBJECT OTHER-HEADERS &rest IGNORED)" nil nil)
-
+(fn &optional TO SUBJECT OTHER-HEADERS &rest IGNORED)" nil nil)
(define-mail-user-agent 'mh-e-user-agent 'mh-user-agent-compose 'mh-send-letter 'mh-fully-kill-draft 'mh-before-send-letter-hook)
-
(autoload 'mh-user-agent-compose "mh-comp" "\
Set up mail composition draft with the MH mail system.
This is the `mail-user-agent' entry point to MH-E. This function
@@ -21641,8 +19714,7 @@ are strings.
Any additional arguments are IGNORED.
-\(fn &optional TO SUBJECT OTHER-HEADERS &rest IGNORED)" nil nil)
-
+(fn &optional TO SUBJECT OTHER-HEADERS &rest IGNORED)" nil nil)
(autoload 'mh-send-letter "mh-comp" "\
Save draft and send message.
@@ -21668,8 +19740,7 @@ use `mh-send-prog' to tell MH-E the name.
The hook `mh-annotate-msg-hook' is run after annotating the
message and scan line.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'mh-fully-kill-draft "mh-comp" "\
Quit editing and delete draft message.
@@ -21677,36 +19748,25 @@ If for some reason you are not happy with the draft, you can use
this command to kill the draft buffer and delete the draft
message. Use the command \\[kill-buffer] if you don't want to
delete the draft message." t nil)
-
(register-definition-prefixes "mh-comp" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-compat" "mh-e/mh-compat.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-compat.el
(register-definition-prefixes "mh-compat" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-e" "mh-e/mh-e.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-e.el
-(push (purecopy '(mh-e 8 6 -4)) package--builtin-versions)
+(push (purecopy '(mh-e 8 6 -4)) package--builtin-versions)
(put 'mh-progs 'risky-local-variable t)
-
(put 'mh-lib 'risky-local-variable t)
-
(put 'mh-lib-progs 'risky-local-variable t)
-
(autoload 'mh-version "mh-e" "\
Display version information about MH-E and the MH mail handling system." t nil)
-
(register-definition-prefixes "mh-e" '("defcustom-mh" "defface-mh" "defgroup-mh" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-folder" "mh-e/mh-folder.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-folder.el
(autoload 'mh-rmail "mh-folder" "\
@@ -21716,8 +19776,7 @@ Scan an MH folder if ARG is non-nil.
This function is an entry point to MH-E, the Emacs interface to
the MH mail system.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'mh-nmail "mh-folder" "\
Check for new mail in inbox folder.
Scan an MH folder if ARG is non-nil.
@@ -21725,8 +19784,7 @@ Scan an MH folder if ARG is non-nil.
This function is an entry point to MH-E, the Emacs interface to
the MH mail system.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'mh-folder-mode "mh-folder" "\
Major MH-E mode for \"editing\" an MH folder scan listing.\\<mh-folder-mode-map>
@@ -21783,135 +19841,95 @@ perform the operation on all messages in that region.
\\{mh-folder-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "mh-folder" '(":keymap" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-funcs" "mh-e/mh-funcs.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-funcs.el
(register-definition-prefixes "mh-funcs" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-identity" "mh-e/mh-identity.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from mh-e/mh-identity.el
(register-definition-prefixes "mh-identity" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-inc" "mh-e/mh-inc.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-inc.el
(register-definition-prefixes "mh-inc" '("mh-inc-spool-"))
-;;;***
-;;;### (autoloads nil "mh-junk" "mh-e/mh-junk.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-junk.el
(register-definition-prefixes "mh-junk" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-letter" "mh-e/mh-letter.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-letter.el
(register-definition-prefixes "mh-letter" '(":keymap" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-limit" "mh-e/mh-limit.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-limit.el
(register-definition-prefixes "mh-limit" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-mime" "mh-e/mh-mime.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-mime.el
(register-definition-prefixes "mh-mime" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-print" "mh-e/mh-print.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-print.el
(register-definition-prefixes "mh-print" '("mh-p"))
-;;;***
-;;;### (autoloads nil "mh-scan" "mh-e/mh-scan.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-scan.el
(register-definition-prefixes "mh-scan" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-search" "mh-e/mh-search.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-search.el
(register-definition-prefixes "mh-search" '(":keymap" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-seq" "mh-e/mh-seq.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-seq.el
(register-definition-prefixes "mh-seq" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-show" "mh-e/mh-show.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-show.el
(register-definition-prefixes "mh-show" '(":keymap" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-speed" "mh-e/mh-speed.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-speed.el
(register-definition-prefixes "mh-speed" '(":keymap" "mh-"))
-;;;***
-;;;### (autoloads nil "mh-thread" "mh-e/mh-thread.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-thread.el
(register-definition-prefixes "mh-thread" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-tool-bar" "mh-e/mh-tool-bar.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from mh-e/mh-tool-bar.el
(register-definition-prefixes "mh-tool-bar" '("mh-tool-bar-"))
-;;;***
-;;;### (autoloads nil "mh-utils" "mh-e/mh-utils.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-utils.el
(register-definition-prefixes "mh-utils" '("mh-"))
-;;;***
-;;;### (autoloads nil "mh-xface" "mh-e/mh-xface.el" (0 0 0 0))
;;; Generated autoloads from mh-e/mh-xface.el
(register-definition-prefixes "mh-xface" '("mh-"))
-;;;***
-;;;### (autoloads nil "mhtml-mode" "textmodes/mhtml-mode.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from textmodes/mhtml-mode.el
(autoload 'mhtml-mode "mhtml-mode" "\
@@ -21921,13 +19939,10 @@ Code inside a <script> element is indented using the rules from
`js-mode'; and code inside a <style> element is indented using
the rules from `css-mode'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "mhtml-mode" '("mhtml-"))
-;;;***
-;;;### (autoloads nil "midnight" "midnight.el" (0 0 0 0))
;;; Generated autoloads from midnight.el
(defvar midnight-mode nil "\
@@ -21937,28 +19952,25 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `midnight-mode'.")
-
(custom-autoload 'midnight-mode "midnight" nil)
-
(autoload 'midnight-mode "midnight" "\
Non-nil means run `midnight-hook' at midnight.
-This is a minor mode. If called interactively, toggle the `Midnight
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Midnight mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='midnight-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'clean-buffer-list "midnight" "\
Kill old buffers that have not been displayed recently.
The relevant variables are `clean-buffer-list-delay-general',
@@ -21970,19 +19982,15 @@ While processing buffers, this procedure displays messages containing
the current date/time, buffer name, how many seconds ago it was
displayed (can be nil if the buffer was never displayed) and its
lifetime, i.e., its \"age\" when it will be purged." t nil)
-
(autoload 'midnight-delay-set "midnight" "\
Modify `midnight-timer' according to `midnight-delay'.
Sets the first argument SYMB (which must be symbol `midnight-delay')
to its second argument TM.
-\(fn SYMB TM)" nil nil)
-
+(fn SYMB TM)" nil nil)
(register-definition-prefixes "midnight" '("clean-buffer-list-" "midnight-"))
-;;;***
-;;;### (autoloads nil "minibuf-eldef" "minibuf-eldef.el" (0 0 0 0))
;;; Generated autoloads from minibuf-eldef.el
(defvar minibuffer-electric-default-mode nil "\
@@ -21992,27 +20000,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `minibuffer-electric-default-mode'.")
-
(custom-autoload 'minibuffer-electric-default-mode "minibuf-eldef" nil)
-
(autoload 'minibuffer-electric-default-mode "minibuf-eldef" "\
Toggle Minibuffer Electric Default mode.
-This is a minor mode. If called interactively, toggle the
-`Minibuffer-Electric-Default mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='minibuffer-electric-default-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Minibuffer Electric Default mode is a global minor mode. When
enabled, minibuffer prompts that show a default value only show
the default when it's applicable -- that is, when hitting RET
@@ -22020,13 +20011,25 @@ would yield the default value. If the user modifies the input
such that hitting RET would enter a non-default value, the prompt
is modified to remove the default indication.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Minibuffer-Electric-Default mode' mode. If the prefix argument
+is positive, enable the mode, and if it is zero or negative,
+disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='minibuffer-electric-default-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "minibuf-eldef" '("minibuf"))
-;;;***
-;;;### (autoloads nil "misc" "misc.el" (0 0 0 0))
;;; Generated autoloads from misc.el
(autoload 'copy-from-above-command "misc" "\
@@ -22035,39 +20038,43 @@ Copy ARG characters, but not past the end of that line.
If no argument given, copy the entire rest of the line.
The characters copied are inserted in the buffer before point.
-\(fn &optional ARG)" t nil)
+Also see the `duplicate-line' command.
+
+(fn &optional ARG)" t nil)
+(autoload 'duplicate-line "misc" "\
+Duplicate the current line N times.
+Interactively, N is the prefix numeric argument, and defaults to 1.
+Also see the `copy-from-above-command' command.
+(fn &optional N)" t nil)
(autoload 'zap-up-to-char "misc" "\
Kill up to, but not including ARGth occurrence of CHAR.
+When run interactively, the argument INTERACTIVE is non-nil.
Case is ignored if `case-fold-search' is non-nil in the current buffer.
Goes backward if ARG is negative; error if CHAR not found.
Ignores CHAR at point.
+If called interactively, do a case sensitive search if CHAR
+is an upper-case character.
-\(fn ARG CHAR)" t nil)
-
+(fn ARG CHAR &optional INTERACTIVE)" t nil)
(autoload 'mark-beginning-of-buffer "misc" "\
Set mark at the beginning of the buffer." t nil)
-
(autoload 'mark-end-of-buffer "misc" "\
Set mark at the end of the buffer." t nil)
-
(autoload 'upcase-char "misc" "\
Uppercasify ARG chars starting from point. Point doesn't move.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'forward-to-word "misc" "\
Move forward until encountering the beginning of a word.
With argument, do this that many times.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'backward-to-word "misc" "\
Move backward until encountering the end of a word.
With argument, do this that many times.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'butterfly "misc" "\
Use butterflies to flip the desired bit on the drive platter.
Open hands and let the delicate wings flap once. The disturbance
@@ -22075,28 +20082,24 @@ ripples outward, changing the flow of the eddy currents in the
upper atmosphere. These cause momentary pockets of higher-pressure
air to form, which act as lenses that deflect incoming cosmic rays,
focusing them to strike the drive platter and flip the desired bit.
-You can type `M-x butterfly C-M-c' to run it. This is a permuted
+You can type \\`M-x butterfly C-M-c' to run it. This is a permuted
variation of `C-x M-c M-butterfly' from url `https://xkcd.com/378/'." t nil)
-
(autoload 'list-dynamic-libraries "misc" "\
Display a list of all dynamic libraries known to Emacs.
-\(These are the libraries listed in `dynamic-library-alist'.)
+(These are the libraries listed in `dynamic-library-alist'.)
If optional argument LOADED-ONLY-P (interactively, prefix arg)
is non-nil, only libraries already loaded are listed.
Optional argument BUFFER specifies a buffer to use, instead of
\"*Dynamic Libraries*\".
The return value is always nil.
-\(fn &optional LOADED-ONLY-P BUFFER)" t nil)
-
+(fn &optional LOADED-ONLY-P BUFFER)" t nil)
(register-definition-prefixes "misc" '("list-dynamic-libraries--"))
-;;;***
-;;;### (autoloads nil "misearch" "misearch.el" (0 0 0 0))
;;; Generated autoloads from misearch.el
- (add-hook 'isearch-mode-hook 'multi-isearch-setup)
+ (add-hook 'isearch-mode-hook 'multi-isearch-setup)
(defvar multi-isearch-next-buffer-function nil "\
Function to call to get the next buffer to search.
@@ -22118,30 +20121,23 @@ should return the previous buffer to search.
If the second argument of this function WRAP is non-nil, then it
should return the first buffer in the series; and for the backward
search, it should return the last buffer in the series.")
-
(defvar multi-isearch-next-buffer-current-function nil "\
The currently active function to get the next buffer to search.
Initialized from `multi-isearch-next-buffer-function' when
Isearch starts.")
-
(defvar multi-isearch-current-buffer nil "\
The buffer where the search is currently searching.
The value is nil when the search still is in the initial buffer.")
-
(defvar multi-isearch-buffer-list nil "\
Sequence of buffers visited by multiple buffers Isearch.
This is nil if Isearch is not currently searching more than one buffer.")
-
(defvar multi-isearch-file-list nil "\
Sequence of files visited by multiple file buffers Isearch.")
-
(autoload 'multi-isearch-setup "misearch" "\
Set up isearch to search multiple buffers.
Intended to be added to `isearch-mode-hook'." nil nil)
-
(autoload 'multi-isearch-switch-buffer "misearch" "\
Switch to the next buffer in multi-buffer search." nil nil)
-
(autoload 'multi-isearch-buffers "misearch" "\
Start multi-buffer Isearch on a list of BUFFERS.
This list can contain live buffers or their names.
@@ -22149,8 +20145,7 @@ Interactively read buffer names to search, one by one, ended with RET.
With a prefix argument, ask for a regexp, and search in buffers
whose names match the specified regexp.
-\(fn BUFFERS)" t nil)
-
+(fn BUFFERS)" t nil)
(autoload 'multi-isearch-buffers-regexp "misearch" "\
Start multi-buffer regexp Isearch on a list of BUFFERS.
This list can contain live buffers or their names.
@@ -22158,8 +20153,7 @@ Interactively read buffer names to search, one by one, ended with RET.
With a prefix argument, ask for a regexp, and search in buffers
whose names match the specified regexp.
-\(fn BUFFERS)" t nil)
-
+(fn BUFFERS)" t nil)
(autoload 'multi-isearch-files "misearch" "\
Start multi-buffer Isearch on a list of FILES.
Relative file names in this list are expanded to absolute
@@ -22168,8 +20162,7 @@ Interactively read file names to search, one by one, ended with RET.
With a prefix argument, ask for a wildcard, and search in file buffers
whose file names match the specified wildcard.
-\(fn FILES)" t nil)
-
+(fn FILES)" t nil)
(autoload 'multi-isearch-files-regexp "misearch" "\
Start multi-buffer regexp Isearch on a list of FILES.
Relative file names in this list are expanded to absolute
@@ -22178,82 +20171,61 @@ Interactively read file names to search, one by one, ended with RET.
With a prefix argument, ask for a wildcard, and search in file buffers
whose file names match the specified wildcard.
-\(fn FILES)" t nil)
-
+(fn FILES)" t nil)
(register-definition-prefixes "misearch" '("misearch-unload-function" "multi-isearch-"))
-;;;***
-;;;### (autoloads nil "mixal-mode" "progmodes/mixal-mode.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/mixal-mode.el
-(push (purecopy '(mixal-mode 0 4)) package--builtin-versions)
+(push (purecopy '(mixal-mode 0 4)) package--builtin-versions)
(autoload 'mixal-mode "mixal-mode" "\
Major mode for the mixal asm language.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "mixal-mode" '("mixal-"))
-;;;***
-;;;### (autoloads nil "mm-archive" "gnus/mm-archive.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-archive.el
(register-definition-prefixes "mm-archive" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-bodies" "gnus/mm-bodies.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-bodies.el
(register-definition-prefixes "mm-bodies" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-decode" "gnus/mm-decode.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-decode.el
(register-definition-prefixes "mm-decode" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-encode" "gnus/mm-encode.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-encode.el
-(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "future")
-
+(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "28.1")
(autoload 'mm-default-file-type "mm-encode" "\
Return a default content type for FILE.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(register-definition-prefixes "mm-encode" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-extern" "gnus/mm-extern.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-extern.el
(autoload 'mm-extern-cache-contents "mm-extern" "\
Put the external-body part of HANDLE into its cache.
-\(fn HANDLE)" nil nil)
-
+(fn HANDLE)" nil nil)
(autoload 'mm-inline-external-body "mm-extern" "\
Show the external-body part of HANDLE.
This function replaces the buffer of HANDLE with a buffer contains
the entire message.
If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing.
-\(fn HANDLE &optional NO-DISPLAY)" nil nil)
-
+(fn HANDLE &optional NO-DISPLAY)" nil nil)
(register-definition-prefixes "mm-extern" '("mm-extern-"))
-;;;***
-;;;### (autoloads nil "mm-partial" "gnus/mm-partial.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-partial.el
(autoload 'mm-inline-partial "mm-partial" "\
@@ -22262,38 +20234,29 @@ This function replaces the buffer of HANDLE with a buffer contains
the entire message.
If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing.
-\(fn HANDLE &optional NO-DISPLAY)" nil nil)
-
+(fn HANDLE &optional NO-DISPLAY)" nil nil)
(register-definition-prefixes "mm-partial" '("mm-partial-find-parts"))
-;;;***
-;;;### (autoloads nil "mm-url" "gnus/mm-url.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-url.el
(autoload 'mm-url-insert-file-contents "mm-url" "\
Insert file contents of URL.
If `mm-url-use-external' is non-nil, use `mm-url-program'.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'mm-url-insert-file-contents-external "mm-url" "\
Insert file contents of URL using `mm-url-program'.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "mm-url" '("mm-url-"))
-;;;***
-;;;### (autoloads nil "mm-util" "gnus/mm-util.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-util.el
(register-definition-prefixes "mm-util" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-uu" "gnus/mm-uu.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-uu.el
(autoload 'mm-uu-dissect "mm-uu" "\
@@ -22302,31 +20265,24 @@ The optional NOHEADER means there's no header in the buffer.
MIME-TYPE specifies a MIME type and parameters, which defaults to the
value of `mm-uu-text-plain-type'.
-\(fn &optional NOHEADER MIME-TYPE)" nil nil)
-
+(fn &optional NOHEADER MIME-TYPE)" nil nil)
(autoload 'mm-uu-dissect-text-parts "mm-uu" "\
Dissect text parts and put uu handles into HANDLE.
Assume text has been decoded if DECODED is non-nil.
-\(fn HANDLE &optional DECODED)" nil nil)
-
+(fn HANDLE &optional DECODED)" nil nil)
(register-definition-prefixes "mm-uu" '("mm-"))
-;;;***
-;;;### (autoloads nil "mm-view" "gnus/mm-view.el" (0 0 0 0))
;;; Generated autoloads from gnus/mm-view.el
(register-definition-prefixes "mm-view" '("mm-"))
-;;;***
-;;;### (autoloads nil "mml" "gnus/mml.el" (0 0 0 0))
;;; Generated autoloads from gnus/mml.el
(autoload 'mml-to-mime "mml" "\
Translate the current buffer from MML to MIME." nil nil)
-
(autoload 'mml-attach-file "mml" "\
Attach a file to the outgoing MIME message.
The file is not inserted or encoded until you send the message with
@@ -22346,96 +20302,82 @@ If given a prefix interactively, no prompting will be done for
the TYPE, DESCRIPTION or DISPOSITION values. Instead defaults
will be computed and used.
-\(fn FILE &optional TYPE DESCRIPTION DISPOSITION)" t nil)
-
+(fn FILE &optional TYPE DESCRIPTION DISPOSITION)" t nil)
(register-definition-prefixes "mml" '("mime-to-mml" "mml-"))
-;;;***
-;;;### (autoloads nil "mml-sec" "gnus/mml-sec.el" (0 0 0 0))
;;; Generated autoloads from gnus/mml-sec.el
(register-definition-prefixes "mml-sec" '("mml-"))
-;;;***
-;;;### (autoloads nil "mml-smime" "gnus/mml-smime.el" (0 0 0 0))
;;; Generated autoloads from gnus/mml-smime.el
(register-definition-prefixes "mml-smime" '("mml-smime-"))
-;;;***
-;;;### (autoloads nil "mml1991" "gnus/mml1991.el" (0 0 0 0))
;;; Generated autoloads from gnus/mml1991.el
(autoload 'mml1991-encrypt "mml1991" "\
-\(fn CONT &optional SIGN)" nil nil)
-
+(fn CONT &optional SIGN)" nil nil)
(autoload 'mml1991-sign "mml1991" "\
-\(fn CONT)" nil nil)
-
+(fn CONT)" nil nil)
(register-definition-prefixes "mml1991" '("mml1991-"))
-;;;***
-;;;### (autoloads nil "mml2015" "gnus/mml2015.el" (0 0 0 0))
;;; Generated autoloads from gnus/mml2015.el
(autoload 'mml2015-decrypt "mml2015" "\
-\(fn HANDLE CTL)" nil nil)
-
+(fn HANDLE CTL)" nil nil)
(autoload 'mml2015-decrypt-test "mml2015" "\
-\(fn HANDLE CTL)" nil nil)
-
+(fn HANDLE CTL)" nil nil)
(autoload 'mml2015-verify "mml2015" "\
-\(fn HANDLE CTL)" nil nil)
-
+(fn HANDLE CTL)" nil nil)
(autoload 'mml2015-verify-test "mml2015" "\
-\(fn HANDLE CTL)" nil nil)
-
+(fn HANDLE CTL)" nil nil)
(autoload 'mml2015-encrypt "mml2015" "\
-\(fn CONT &optional SIGN)" nil nil)
-
+(fn CONT &optional SIGN)" nil nil)
(autoload 'mml2015-sign "mml2015" "\
-\(fn CONT)" nil nil)
-
+(fn CONT)" nil nil)
(autoload 'mml2015-self-encrypt "mml2015" nil nil nil)
-
(register-definition-prefixes "mml2015" '("mml2015-"))
-;;;***
-;;;### (autoloads nil "mode-local" "cedet/mode-local.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/mode.el
+
+(register-definition-prefixes "srecode/mode" '("srecode-"))
+
+
+;;; Generated autoloads from cedet/semantic/decorate/mode.el
+
+(register-definition-prefixes "semantic/decorate/mode" '("define-semantic-decoration-style" "semantic-"))
+
+
;;; Generated autoloads from cedet/mode-local.el
(put 'define-overloadable-function 'doc-string-elt 3)
-
(register-definition-prefixes "mode-local" '("def" "describe-mode-local-bindings" "fetch-overload" "get-mode-local-parent" "make-obsolete-overload" "mode-local-" "setq-mode-local" "with-mode-local" "xref-mode-local-"))
-;;;***
-;;;### (autoloads nil "modula2" "progmodes/modula2.el" (0 0 0 0))
;;; Generated autoloads from progmodes/modula2.el
(defalias 'modula-2-mode 'm2-mode)
-
(autoload 'm2-mode "modula2" "\
This is a mode intended to support program development in Modula-2.
All control constructs of Modula-2 can be reached by typing C-c
@@ -22460,47 +20402,37 @@ followed by the first character of the construct.
`m2-compile-command' holds the command to compile a Modula-2 program.
`m2-link-command' holds the command to link a Modula-2 program.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "modula2" '("m2-" "m3-font-lock-keywords"))
-;;;***
-;;;### (autoloads nil "morse" "play/morse.el" (0 0 0 0))
;;; Generated autoloads from play/morse.el
(autoload 'morse-region "morse" "\
-Convert all text in a given region to morse code.
-
-\(fn BEG END)" t nil)
+Convert plain text in region to Morse code.
+See <https://en.wikipedia.org/wiki/Morse_code>.
+(fn BEG END)" t nil)
(autoload 'unmorse-region "morse" "\
-Convert morse coded text in region to ordinary ASCII text.
-
-\(fn BEG END)" t nil)
+Convert Morse coded text in region to plain text.
+(fn BEG END)" t nil)
(autoload 'nato-region "morse" "\
-Convert all text in a given region to NATO phonetic alphabet.
-
-\(fn BEG END)" t nil)
+Convert plain text in region to NATO spelling alphabet.
+(fn BEG END)" t nil)
(autoload 'denato-region "morse" "\
-Convert NATO phonetic alphabet in region to ordinary ASCII text.
-
-\(fn BEG END)" t nil)
+Convert NATO spelling alphabet text in region to plain text.
+(fn BEG END)" t nil)
(register-definition-prefixes "morse" '("morse-code" "nato-alphabet"))
-;;;***
-;;;### (autoloads nil "mouse-copy" "mouse-copy.el" (0 0 0 0))
;;; Generated autoloads from mouse-copy.el
(register-definition-prefixes "mouse-copy" '("mouse-"))
-;;;***
-;;;### (autoloads nil "mouse-drag" "mouse-drag.el" (0 0 0 0))
;;; Generated autoloads from mouse-drag.el
(autoload 'mouse-drag-throw "mouse-drag" "\
@@ -22525,8 +20457,7 @@ hemisphere you're in.)
To test this function, evaluate:
(global-set-key [down-mouse-2] \\='mouse-drag-throw)
-\(fn START-EVENT)" t nil)
-
+(fn START-EVENT)" t nil)
(autoload 'mouse-drag-drag "mouse-drag" "\
\"Drag\" the page according to a mouse drag.
@@ -22543,33 +20474,29 @@ middle button in Tk text widgets.
To test this function, evaluate:
(global-set-key [down-mouse-2] \\='mouse-drag-drag)
-\(fn START-EVENT)" t nil)
-
+(fn START-EVENT)" t nil)
(register-definition-prefixes "mouse-drag" '("mouse-"))
-;;;***
-;;;### (autoloads nil "mpc" "mpc.el" (0 0 0 0))
;;; Generated autoloads from mpc.el
(autoload 'mpc "mpc" "\
Main entry point for MPC." t nil)
-
(register-definition-prefixes "mpc" '("mpc-" "tag-browser-tagtypes"))
-;;;***
-;;;### (autoloads nil "mpuz" "play/mpuz.el" (0 0 0 0))
;;; Generated autoloads from play/mpuz.el
(autoload 'mpuz "mpuz" "\
Multiplication puzzle with GNU Emacs." t nil)
-
(register-definition-prefixes "mpuz" '("mpuz-"))
-;;;***
-;;;### (autoloads nil "msb" "msb.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/mru-bookmark.el
+
+(register-definition-prefixes "semantic/mru-bookmark" '("global-semantic-mru-bookmark-mode" "semantic-"))
+
+
;;; Generated autoloads from msb.el
(defvar msb-mode nil "\
@@ -22579,50 +20506,41 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `msb-mode'.")
-
(custom-autoload 'msb-mode "msb" nil)
-
(autoload 'msb-mode "msb" "\
Toggle Msb mode.
-This is a minor mode. If called interactively, toggle the `Msb mode'
-mode. If the prefix argument is positive, enable the mode, and if it
-is zero or negative, disable the mode.
+This mode overrides the binding(s) of `mouse-buffer-menu' to provide a
+different buffer menu using the function `msb'.
+
+This is a global minor mode. If called interactively, toggle the
+`Msb mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='msb-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-This mode overrides the binding(s) of `mouse-buffer-menu' to provide a
-different buffer menu using the function `msb'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "msb" '("mouse-select-buffer" "msb"))
-;;;***
-;;;### (autoloads nil "mspools" "mail/mspools.el" (0 0 0 0))
;;; Generated autoloads from mail/mspools.el
(autoload 'mspools-show "mspools" "\
Show the list of non-empty spool files in the *spools* buffer.
Buffer is not displayed if SHOW is non-nil.
-\(fn &optional NOSHOW)" t nil)
-
+(fn &optional NOSHOW)" t nil)
(register-definition-prefixes "mspools" '("mspools-"))
-;;;***
-;;;### (autoloads nil "mule-diag" "international/mule-diag.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from international/mule-diag.el
(autoload 'list-character-sets "mule-diag" "\
@@ -22637,8 +20555,7 @@ ISO-2022-based coding systems.
With prefix ARG, the output format gets more cryptic,
but still shows the full information.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'read-charset "mule-diag" "\
Read a character set from the minibuffer, prompting with string PROMPT.
It must be an Emacs character set listed in the variable `charset-list'.
@@ -22649,23 +20566,19 @@ INITIAL-INPUT, if non-nil, is a string inserted in the minibuffer initially.
See the documentation of the function `completing-read' for the detailed
meanings of these arguments.
-\(fn PROMPT &optional DEFAULT-VALUE INITIAL-INPUT)" nil nil)
-
+(fn PROMPT &optional DEFAULT-VALUE INITIAL-INPUT)" nil nil)
(autoload 'list-charset-chars "mule-diag" "\
Display a list of characters in character set CHARSET.
-\(fn CHARSET)" t nil)
-
+(fn CHARSET)" t nil)
(autoload 'describe-character-set "mule-diag" "\
Display information about built-in character set CHARSET.
-\(fn CHARSET)" t nil)
-
+(fn CHARSET)" t nil)
(autoload 'describe-coding-system "mule-diag" "\
Display information about CODING-SYSTEM.
-\(fn CODING-SYSTEM)" t nil)
-
+(fn CODING-SYSTEM)" t nil)
(autoload 'describe-current-coding-system-briefly "mule-diag" "\
Display coding systems currently used in a brief format in echo area.
@@ -22688,10 +20601,8 @@ in place of `..':
eol-type of `default-process-coding-system' for read
`default-process-coding-system' for write
eol-type of `default-process-coding-system'" t nil)
-
(autoload 'describe-current-coding-system "mule-diag" "\
Display coding systems currently used, in detail." t nil)
-
(autoload 'list-coding-systems "mule-diag" "\
Display a list of all coding systems.
This shows the mnemonic letter, name, and description of each coding system.
@@ -22699,33 +20610,27 @@ This shows the mnemonic letter, name, and description of each coding system.
With prefix ARG, the output format gets more cryptic,
but still contains full information about each coding system.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'list-coding-categories "mule-diag" "\
Display a list of all coding categories." nil nil)
-
(autoload 'describe-font "mule-diag" "\
Display information about a font whose name is FONTNAME.
-\(fn FONTNAME)" t nil)
-
+(fn FONTNAME)" t nil)
(autoload 'describe-fontset "mule-diag" "\
Display information about FONTSET.
This shows which font is used for which character(s).
-\(fn FONTSET)" t nil)
-
+(fn FONTSET)" t nil)
(autoload 'list-fontsets "mule-diag" "\
Display a list of all fontsets.
This shows the name, size, and style of each fontset.
With prefix arg, also list the fonts contained in each fontset;
see the function `describe-fontset' for the format of the list.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'list-input-methods "mule-diag" "\
Display information about all input methods." t nil)
-
(autoload 'mule-diag "mule-diag" "\
Display diagnosis of the multilingual environment (Mule).
@@ -22733,27 +20638,21 @@ This shows various information related to the current multilingual
environment, including lists of input methods, coding systems,
character sets, and fontsets (if Emacs is running under a window
system which uses fontsets)." t nil)
-
(autoload 'font-show-log "mule-diag" "\
Show log of font listing and opening.
Prefix arg LIMIT says how many fonts to show for each listing.
The default is 20. If LIMIT is negative, do not limit the listing.
-\(fn &optional LIMIT)" t nil)
-
+(fn &optional LIMIT)" t nil)
(register-definition-prefixes "mule-diag" '("charset-history" "describe-font-internal" "insert-section" "list-" "mule--kbd-at" "print-" "sort-listed-character-sets"))
-;;;***
-;;;### (autoloads nil "mule-util" "international/mule-util.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from international/mule-util.el
(autoload 'store-substring "mule-util" "\
Embed OBJ (string or character) at index IDX of STRING.
-\(fn STRING IDX OBJ)" nil nil)
-
+(fn STRING IDX OBJ)" nil nil)
(autoload 'truncate-string-to-width "mule-util" "\
Truncate string STR to end at column END-COLUMN.
The optional 3rd arg START-COLUMN, if non-nil, specifies the starting
@@ -22787,19 +20686,17 @@ If ELLIPSIS-TEXT-PROPERTY is non-nil, a too-long string will not
be truncated, but instead the elided parts will be covered by a
`display' text property showing the ellipsis.
-\(fn STR END-COLUMN &optional START-COLUMN PADDING ELLIPSIS ELLIPSIS-TEXT-PROPERTY)" nil nil)
-
+(fn STR END-COLUMN &optional START-COLUMN PADDING ELLIPSIS ELLIPSIS-TEXT-PROPERTY)" nil nil)
(defsubst nested-alist-p (obj) "\
Return t if OBJ is a nested alist.
Nested alist is a list of the form (ENTRY . BRANCHES), where ENTRY is
any Lisp object, and BRANCHES is a list of cons cells of the form
-\(KEY-ELEMENT . NESTED-ALIST).
+(KEY-ELEMENT . NESTED-ALIST).
You can use a nested alist to store any Lisp object (ENTRY) for a key
sequence KEYSEQ, where KEYSEQ is a sequence of KEY-ELEMENT. KEYSEQ
can be a string, a vector, or a list." (and obj (listp obj) (listp (cdr obj))))
-
(autoload 'set-nested-alist "mule-util" "\
Set ENTRY for KEYSEQ in a nested alist ALIST.
Optional 4th arg LEN non-nil means the first LEN elements in KEYSEQ
@@ -22808,8 +20705,7 @@ Optional 5th argument BRANCHES if non-nil is branches for a keyseq
longer than KEYSEQ.
See the documentation of `nested-alist-p' for more detail.
-\(fn KEYSEQ ENTRY ALIST &optional LEN BRANCHES)" nil nil)
-
+(fn KEYSEQ ENTRY ALIST &optional LEN BRANCHES)" nil nil)
(autoload 'lookup-nested-alist "mule-util" "\
Look up key sequence KEYSEQ in nested alist ALIST. Return the definition.
Optional 3rd argument LEN specifies the length of KEYSEQ.
@@ -22822,45 +20718,37 @@ If ALIST is not deep enough for KEYSEQ, return number which is
Optional 5th argument NIL-FOR-TOO-LONG non-nil means return nil
even if ALIST is not deep enough.
-\(fn KEYSEQ ALIST &optional LEN START NIL-FOR-TOO-LONG)" nil nil)
-
+(fn KEYSEQ ALIST &optional LEN START NIL-FOR-TOO-LONG)" nil nil)
(autoload 'coding-system-post-read-conversion "mule-util" "\
Return the value of CODING-SYSTEM's `post-read-conversion' property.
-\(fn CODING-SYSTEM)" nil nil)
-
+(fn CODING-SYSTEM)" nil nil)
(autoload 'coding-system-pre-write-conversion "mule-util" "\
Return the value of CODING-SYSTEM's `pre-write-conversion' property.
-\(fn CODING-SYSTEM)" nil nil)
-
+(fn CODING-SYSTEM)" nil nil)
(autoload 'coding-system-translation-table-for-decode "mule-util" "\
Return the value of CODING-SYSTEM's `decode-translation-table' property.
-\(fn CODING-SYSTEM)" nil nil)
-
+(fn CODING-SYSTEM)" nil nil)
(autoload 'coding-system-translation-table-for-encode "mule-util" "\
Return the value of CODING-SYSTEM's `encode-translation-table' property.
-\(fn CODING-SYSTEM)" nil nil)
-
+(fn CODING-SYSTEM)" nil nil)
(autoload 'with-coding-priority "mule-util" "\
Execute BODY like `progn' with CODING-SYSTEMS at the front of priority list.
CODING-SYSTEMS is a list of coding systems. See `set-coding-system-priority'.
This affects the implicit sorting of lists of coding systems returned by
operations such as `find-coding-systems-region'.
-\(fn CODING-SYSTEMS &rest BODY)" nil t)
-
-(function-put 'with-coding-priority 'lisp-indent-function '1)
-
+(fn CODING-SYSTEMS &rest BODY)" nil t)
+(function-put 'with-coding-priority 'lisp-indent-function 1)
(autoload 'detect-coding-with-language-environment "mule-util" "\
Detect a coding system for the text between FROM and TO with LANG-ENV.
The detection takes into account the coding system priorities for the
language environment LANG-ENV.
-\(fn FROM TO LANG-ENV)" nil nil)
-
+(fn FROM TO LANG-ENV)" nil nil)
(autoload 'filepos-to-bufferpos "mule-util" "\
Try to return the buffer position corresponding to a particular file position.
The file position is given as a (0-based) BYTE count.
@@ -22875,8 +20763,7 @@ QUALITY can be:
EOL format is not yet decided.)
nil, in which case we may return nil rather than an approximation.
-\(fn BYTE &optional QUALITY CODING-SYSTEM)" nil nil)
-
+(fn BYTE &optional QUALITY CODING-SYSTEM)" nil nil)
(autoload 'bufferpos-to-filepos "mule-util" "\
Try to return the file byte corresponding to a particular buffer POSITION.
Value is the file position given as a (0-based) byte count.
@@ -22891,14 +20778,10 @@ QUALITY can be:
EOL format is not yet decided.)
nil, in which case we may return nil rather than an approximation.
-\(fn POSITION &optional QUALITY CODING-SYSTEM)" nil nil)
-
+(fn POSITION &optional QUALITY CODING-SYSTEM)" nil nil)
(register-definition-prefixes "mule-util" '("filepos-to-bufferpos--dos" "truncate-string-ellipsis"))
-;;;***
-;;;### (autoloads nil "multisession" "emacs-lisp/multisession.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from emacs-lisp/multisession.el
(autoload 'define-multisession-variable "multisession" "\
@@ -22906,22 +20789,17 @@ Make NAME into a multisession variable initialized from INITIAL-VALUE.
DOC should be a doc string, and ARGS are keywords as applicable to
`make-multisession'.
-\(fn NAME INITIAL-VALUE &optional DOC &rest ARGS)" nil t)
-
+(fn NAME INITIAL-VALUE &optional DOC &rest ARGS)" nil t)
(function-put 'define-multisession-variable 'lisp-indent-function 'defun)
-
(autoload 'list-multisession-values "multisession" "\
List all values in the \"multisession\" database.
If CHOOSE-STORAGE (interactively, the prefix), query for the
storage method to list.
-\(fn &optional CHOOSE-STORAGE)" t nil)
-
+(fn &optional CHOOSE-STORAGE)" t nil)
(register-definition-prefixes "multisession" '("multisession-"))
-;;;***
-;;;### (autoloads nil "mwheel" "mwheel.el" (0 0 0 0))
;;; Generated autoloads from mwheel.el
(defvar mouse-wheel-mode t "\
@@ -22931,62 +20809,50 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `mouse-wheel-mode'.")
-
(custom-autoload 'mouse-wheel-mode "mwheel" nil)
-
(autoload 'mouse-wheel-mode "mwheel" "\
Toggle mouse wheel support (Mouse Wheel mode).
-This is a minor mode. If called interactively, toggle the
-`Mouse-Wheel mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Mouse-Wheel mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='mouse-wheel-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "mwheel" '("mouse-wheel-" "mwheel-"))
-;;;***
-;;;### (autoloads nil "net-utils" "net/net-utils.el" (0 0 0 0))
;;; Generated autoloads from net/net-utils.el
(autoload 'ifconfig "net-utils" "\
Run `ifconfig-program' and display diagnostic output." t nil)
-
(autoload 'iwconfig "net-utils" "\
Run `iwconfig-program' and display diagnostic output." t nil)
-
(autoload 'netstat "net-utils" "\
Run `netstat-program' and display diagnostic output." t nil)
-
(autoload 'arp "net-utils" "\
Run `arp-program' and display diagnostic output." t nil)
-
(autoload 'route "net-utils" "\
Run `route-program' and display diagnostic output." t nil)
-
(autoload 'traceroute "net-utils" "\
Run `traceroute-program' for TARGET.
-\(fn TARGET)" t nil)
-
+(fn TARGET)" t nil)
(autoload 'ping "net-utils" "\
Ping HOST.
If your system's ping continues until interrupted, you can try setting
`ping-program-options'.
-\(fn HOST)" t nil)
-
+(fn HOST)" t nil)
(autoload 'nslookup-host "net-utils" "\
Look up the DNS information for HOST (name or IP address).
Optional argument NAME-SERVER says which server to use for
@@ -22999,8 +20865,7 @@ See also: `nslookup-host-ipv4', `nslookup-host-ipv6' for
non-interactive versions of this function more suitable for use
in Lisp code.
-\(fn HOST &optional NAME-SERVER)" t nil)
-
+(fn HOST &optional NAME-SERVER)" t nil)
(autoload 'nslookup-host-ipv4 "net-utils" "\
Return the IPv4 address for HOST (name or IP address).
Optional argument NAME-SERVER says which server to use for DNS
@@ -23012,8 +20877,7 @@ vector of octets.
This command uses `nslookup-program' to look up DNS records.
-\(fn HOST &optional NAME-SERVER FORMAT)" nil nil)
-
+(fn HOST &optional NAME-SERVER FORMAT)" nil nil)
(autoload 'nslookup-host-ipv6 "net-utils" "\
Return the IPv6 address for HOST (name or IP address).
Optional argument NAME-SERVER says which server to use for DNS
@@ -23025,11 +20889,9 @@ vector of hextets.
This command uses `nslookup-program' to look up DNS records.
-\(fn HOST &optional NAME-SERVER FORMAT)" nil nil)
-
+(fn HOST &optional NAME-SERVER FORMAT)" nil nil)
(autoload 'nslookup "net-utils" "\
Run `nslookup-program'." t nil)
-
(autoload 'dns-lookup-host "net-utils" "\
Look up the DNS information for HOST (name or IP address).
Optional argument NAME-SERVER says which server to use for
@@ -23038,8 +20900,7 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument.
This command uses `dns-lookup-program' for looking up the DNS information.
-\(fn HOST &optional NAME-SERVER)" t nil)
-
+(fn HOST &optional NAME-SERVER)" t nil)
(autoload 'run-dig "net-utils" "\
Look up DNS information for HOST (name or IP address).
Optional argument NAME-SERVER says which server to use for
@@ -23048,46 +20909,37 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument.
This command uses `dig-program' for looking up the DNS information.
-\(fn HOST &optional NAME-SERVER)" t nil)
-
+(fn HOST &optional NAME-SERVER)" t nil)
(autoload 'ftp "net-utils" "\
Run `ftp-program' to connect to HOST.
-\(fn HOST)" t nil)
-
+(fn HOST)" t nil)
(autoload 'finger "net-utils" "\
Finger USER on HOST.
This command uses `finger-X.500-host-regexps'
and `network-connection-service-alist', which see.
-\(fn USER HOST)" t nil)
-
+(fn USER HOST)" t nil)
(autoload 'whois "net-utils" "\
Send SEARCH-STRING to server defined by the `whois-server-name' variable.
If `whois-guess-server' is non-nil, then try to deduce the correct server
from SEARCH-STRING. With argument, prompt for whois server.
The port is deduced from `network-connection-service-alist'.
-\(fn ARG SEARCH-STRING)" t nil)
-
+(fn ARG SEARCH-STRING)" t nil)
(autoload 'whois-reverse-lookup "net-utils" nil t nil)
-
(autoload 'network-connection-to-service "net-utils" "\
Open a network connection to SERVICE on HOST.
This command uses `network-connection-service-alist', which see.
-\(fn HOST SERVICE)" t nil)
-
+(fn HOST SERVICE)" t nil)
(autoload 'network-connection "net-utils" "\
Open a network connection to HOST on PORT.
-\(fn HOST PORT)" t nil)
-
+(fn HOST PORT)" t nil)
(register-definition-prefixes "net-utils" '("arp-program" "dig-program" "dns-lookup-program" "finger-X.500-host-regexps" "ftp-" "ifconfig-program" "ipconfig" "iwconfig-program" "net" "nslookup-" "ping-program" "route-program" "run-network-program" "smbclient" "traceroute-program" "whois-"))
-;;;***
-;;;### (autoloads nil "netrc" "net/netrc.el" (0 0 0 0))
;;; Generated autoloads from net/netrc.el
(autoload 'netrc-credentials "netrc" "\
@@ -23095,14 +20947,10 @@ Return a user name/password pair.
Port specifications will be prioritized in the order they are
listed in the PORTS list.
-\(fn MACHINE &rest PORTS)" nil nil)
-
+(fn MACHINE &rest PORTS)" nil nil)
(register-definition-prefixes "netrc" '("netrc-"))
-;;;***
-;;;### (autoloads nil "network-stream" "net/network-stream.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from net/network-stream.el
(autoload 'open-network-stream "network-stream" "\
@@ -23211,23 +21059,17 @@ type (either `gnutls-x509pki' or `gnutls-anon'), and the
remaining elements should be a keyword list accepted by
gnutls-boot (as returned by `gnutls-boot-parameters').
-\(fn NAME BUFFER HOST SERVICE &rest PARAMETERS)" nil nil)
-
+(fn NAME BUFFER HOST SERVICE &rest PARAMETERS)" nil nil)
(define-obsolete-function-alias 'open-protocol-stream #'open-network-stream "26.1")
-
(register-definition-prefixes "network-stream" '("network-stream-"))
-;;;***
-;;;### (autoloads nil "newst-backend" "net/newst-backend.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from net/newst-backend.el
(autoload 'newsticker-running-p "newst-backend" "\
Check whether newsticker is running.
Return t if newsticker is running, nil otherwise. Newsticker is
considered to be running if the newsticker timer list is not empty." nil nil)
-
(autoload 'newsticker-start "newst-backend" "\
Start the newsticker.
Start the timers for display and retrieval. If the newsticker, i.e. the
@@ -23235,36 +21077,24 @@ timers, are running already a warning message is printed unless
DO-NOT-COMPLAIN-IF-RUNNING is not nil.
Run `newsticker-start-hook' if newsticker was not running already.
-\(fn &optional DO-NOT-COMPLAIN-IF-RUNNING)" t nil)
-
+(fn &optional DO-NOT-COMPLAIN-IF-RUNNING)" t nil)
(register-definition-prefixes "newst-backend" '("newsticker-"))
-;;;***
-;;;### (autoloads nil "newst-plainview" "net/newst-plainview.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from net/newst-plainview.el
(autoload 'newsticker-plainview "newst-plainview" "\
Start newsticker plainview." t nil)
-
(register-definition-prefixes "newst-plainview" '("newsticker-"))
-;;;***
-;;;### (autoloads nil "newst-reader" "net/newst-reader.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/newst-reader.el
(autoload 'newsticker-show-news "newst-reader" "\
Start reading news. You may want to bind this to a key." t nil)
-
(register-definition-prefixes "newst-reader" '("newsticker-"))
-;;;***
-;;;### (autoloads nil "newst-ticker" "net/newst-ticker.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/newst-ticker.el
(autoload 'newsticker-ticker-running-p "newst-ticker" "\
@@ -23272,68 +21102,49 @@ Check whether newsticker's actual ticker is running.
Return t if ticker is running, nil otherwise. Newsticker is
considered to be running if the newsticker timer list is not
empty." nil nil)
-
(autoload 'newsticker-start-ticker "newst-ticker" "\
Start newsticker's ticker (but not the news retrieval).
Start display timer for the actual ticker if wanted and not
running already." t nil)
-
(register-definition-prefixes "newst-ticker" '("newsticker-"))
-;;;***
-;;;### (autoloads nil "newst-treeview" "net/newst-treeview.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from net/newst-treeview.el
(autoload 'newsticker-treeview "newst-treeview" "\
Start newsticker treeview." t nil)
-
(register-definition-prefixes "newst-treeview" '("newsticker-"))
-;;;***
-;;;### (autoloads nil "newsticker" "net/newsticker.el" (0 0 0 0))
;;; Generated autoloads from net/newsticker.el
(register-definition-prefixes "newsticker" '("newsticker-version"))
-;;;***
-;;;### (autoloads nil "nnagent" "gnus/nnagent.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnagent.el
(register-definition-prefixes "nnagent" '("nnagent-"))
-;;;***
-;;;### (autoloads nil "nnbabyl" "gnus/nnbabyl.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnbabyl.el
(register-definition-prefixes "nnbabyl" '("nnbabyl-"))
-;;;***
-;;;### (autoloads nil "nndiary" "gnus/nndiary.el" (0 0 0 0))
;;; Generated autoloads from gnus/nndiary.el
(autoload 'nndiary-generate-nov-databases "nndiary" "\
Generate NOV databases in all nndiary directories.
-\(fn &optional SERVER)" t nil)
-
+(fn &optional SERVER)" t nil)
(register-definition-prefixes "nndiary" '("nndiary-"))
-;;;***
-;;;### (autoloads nil "nndir" "gnus/nndir.el" (0 0 0 0))
;;; Generated autoloads from gnus/nndir.el
(register-definition-prefixes "nndir" '("nndir-"))
-;;;***
-;;;### (autoloads nil "nndoc" "gnus/nndoc.el" (0 0 0 0))
;;; Generated autoloads from gnus/nndoc.el
(autoload 'nndoc-add-type "nndoc" "\
@@ -23343,209 +21154,153 @@ as the last checked definition, if t or `first', add as the
first definition, and if any other symbol, add after that
symbol in the alist.
-\(fn DEFINITION &optional POSITION)" nil nil)
-
+(fn DEFINITION &optional POSITION)" nil nil)
(register-definition-prefixes "nndoc" '("nndoc-"))
-;;;***
-;;;### (autoloads nil "nndraft" "gnus/nndraft.el" (0 0 0 0))
;;; Generated autoloads from gnus/nndraft.el
(register-definition-prefixes "nndraft" '("nndraft-"))
-;;;***
-;;;### (autoloads nil "nneething" "gnus/nneething.el" (0 0 0 0))
;;; Generated autoloads from gnus/nneething.el
(register-definition-prefixes "nneething" '("nneething-"))
-;;;***
-;;;### (autoloads nil "nnfolder" "gnus/nnfolder.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnfolder.el
(autoload 'nnfolder-generate-active-file "nnfolder" "\
Look for mbox folders in the nnfolder directory and make them into groups.
This command does not work if you use short group names." t nil)
-
(register-definition-prefixes "nnfolder" '("nnfolder-"))
-;;;***
-;;;### (autoloads nil "nngateway" "gnus/nngateway.el" (0 0 0 0))
;;; Generated autoloads from gnus/nngateway.el
(register-definition-prefixes "nngateway" '("nngateway-"))
-;;;***
-;;;### (autoloads nil "nnheader" "gnus/nnheader.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnheader.el
(register-definition-prefixes "nnheader" '("gnus-" "mail-header-" "make-mail-header" "nnheader-" "nntp-"))
-;;;***
-;;;### (autoloads nil "nnimap" "gnus/nnimap.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnimap.el
(register-definition-prefixes "nnimap" '("nnimap-"))
-;;;***
-;;;### (autoloads nil "nnmail" "gnus/nnmail.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnmail.el
(register-definition-prefixes "nnmail" '("nnmail-"))
-;;;***
-;;;### (autoloads nil "nnmaildir" "gnus/nnmaildir.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnmaildir.el
(register-definition-prefixes "nnmaildir" '("nnmaildir-"))
-;;;***
-;;;### (autoloads nil "nnmairix" "gnus/nnmairix.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnmairix.el
(register-definition-prefixes "nnmairix" '("nnmairix-"))
-;;;***
-;;;### (autoloads nil "nnmbox" "gnus/nnmbox.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnmbox.el
(register-definition-prefixes "nnmbox" '("nnmbox-"))
-;;;***
-;;;### (autoloads nil "nnmh" "gnus/nnmh.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnmh.el
(register-definition-prefixes "nnmh" '("nnmh-"))
-;;;***
-;;;### (autoloads nil "nnml" "gnus/nnml.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnml.el
(autoload 'nnml-generate-nov-databases "nnml" "\
Generate NOV databases in all nnml directories.
-\(fn &optional SERVER)" t nil)
-
+(fn &optional SERVER)" t nil)
(register-definition-prefixes "nnml" '("nnml-"))
-;;;***
-;;;### (autoloads nil "nnnil" "gnus/nnnil.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnnil.el
(register-definition-prefixes "nnnil" '("nnnil-"))
-;;;***
-;;;### (autoloads nil "nnoo" "gnus/nnoo.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnoo.el
(register-definition-prefixes "nnoo" '("deffoo" "defvoo" "nnoo-" "noo--defalias"))
-;;;***
-;;;### (autoloads nil "nnregistry" "gnus/nnregistry.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnregistry.el
(register-definition-prefixes "nnregistry" '("nnregistry-"))
-;;;***
-;;;### (autoloads nil "nnrss" "gnus/nnrss.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnrss.el
(register-definition-prefixes "nnrss" '("nnrss-"))
-;;;***
-;;;### (autoloads nil "nnselect" "gnus/nnselect.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnselect.el
(register-definition-prefixes "nnselect" '("gnus-" "ids-by-group" "nnselect-" "numbers-by-group"))
-;;;***
-;;;### (autoloads nil "nnspool" "gnus/nnspool.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnspool.el
(register-definition-prefixes "nnspool" '("news-inews-program" "nnspool-"))
-;;;***
-;;;### (autoloads nil "nntp" "gnus/nntp.el" (0 0 0 0))
;;; Generated autoloads from gnus/nntp.el
(register-definition-prefixes "nntp" '("nntp-"))
-;;;***
-;;;### (autoloads nil "nnvirtual" "gnus/nnvirtual.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnvirtual.el
(register-definition-prefixes "nnvirtual" '("nnvirtual-"))
-;;;***
-;;;### (autoloads nil "nnweb" "gnus/nnweb.el" (0 0 0 0))
;;; Generated autoloads from gnus/nnweb.el
(register-definition-prefixes "nnweb" '("nnweb-"))
-;;;***
-;;;### (autoloads nil "notifications" "notifications.el" (0 0 0 0))
;;; Generated autoloads from notifications.el
(register-definition-prefixes "notifications" '("notifications-"))
-;;;***
-;;;### (autoloads nil "novice" "novice.el" (0 0 0 0))
;;; Generated autoloads from novice.el
(defvar disabled-command-function 'disabled-command-function "\
Function to call to handle disabled commands.
If nil, the feature is disabled, i.e., all commands work normally.")
-
(autoload 'disabled-command-function "novice" "\
-\(fn &optional CMD KEYS)" nil nil)
-
+(fn &optional CMD KEYS)" nil nil)
(autoload 'enable-command "novice" "\
Allow COMMAND to be executed without special confirmation from now on.
COMMAND must be a symbol.
This command alters the user's .emacs file so that this will apply
to future sessions.
-\(fn COMMAND)" t nil)
-
+(fn COMMAND)" t nil)
(autoload 'disable-command "novice" "\
Require special confirmation to execute COMMAND from now on.
COMMAND must be a symbol.
This command alters your init file so that this choice applies to
future sessions.
-\(fn COMMAND)" t nil)
-
+(fn COMMAND)" t nil)
(register-definition-prefixes "novice" '("en/disable-command"))
-;;;***
-;;;### (autoloads nil "nroff-mode" "textmodes/nroff-mode.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from textmodes/nroff-mode.el
(autoload 'nroff-mode "nroff-mode" "\
@@ -23555,42 +21310,31 @@ Turning on Nroff mode runs `text-mode-hook', then `nroff-mode-hook'.
Also, try `nroff-electric-mode', for automatically inserting
closing requests for requests that are used in matched pairs.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "nroff-mode" '("nroff-"))
-;;;***
-;;;### (autoloads nil "nsm" "net/nsm.el" (0 0 0 0))
;;; Generated autoloads from net/nsm.el
(register-definition-prefixes "nsm" '("network-security-" "nsm-"))
-;;;***
-;;;### (autoloads nil "ntlm" "net/ntlm.el" (0 0 0 0))
;;; Generated autoloads from net/ntlm.el
-(push (purecopy '(ntlm 2 1 0)) package--builtin-versions)
+(push (purecopy '(ntlm 2 1 0)) package--builtin-versions)
(register-definition-prefixes "ntlm" '("ntlm-"))
-;;;***
-;;;### (autoloads nil "nxml-enc" "nxml/nxml-enc.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-enc.el
(register-definition-prefixes "nxml-enc" '("nxml-"))
-;;;***
-;;;### (autoloads nil "nxml-maint" "nxml/nxml-maint.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-maint.el
(register-definition-prefixes "nxml-maint" '("nxml-insert-target-repertoire-glyph-set"))
-;;;***
-;;;### (autoloads nil "nxml-mode" "nxml/nxml-mode.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-mode.el
(autoload 'nxml-mode "nxml-mode" "\
@@ -23645,359 +21389,271 @@ to nil. For more details, see the function `nxml-forward-balanced-item'.
Many aspects this mode can be customized using
\\[customize-group] nxml RET.
-\(fn)" t nil)
+(fn)" t nil)
(defalias 'xml-mode 'nxml-mode)
-
(register-definition-prefixes "nxml-mode" '("nxml-"))
-;;;***
-;;;### (autoloads nil "nxml-ns" "nxml/nxml-ns.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-ns.el
(register-definition-prefixes "nxml-ns" '("nxml-ns-"))
-;;;***
-;;;### (autoloads nil "nxml-outln" "nxml/nxml-outln.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-outln.el
(register-definition-prefixes "nxml-outln" '("nxml-"))
-;;;***
-;;;### (autoloads nil "nxml-parse" "nxml/nxml-parse.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-parse.el
(register-definition-prefixes "nxml-parse" '("nxml-"))
-;;;***
-;;;### (autoloads nil "nxml-rap" "nxml/nxml-rap.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-rap.el
(register-definition-prefixes "nxml-rap" '("nxml-"))
-;;;***
-;;;### (autoloads nil "nxml-util" "nxml/nxml-util.el" (0 0 0 0))
;;; Generated autoloads from nxml/nxml-util.el
(register-definition-prefixes "nxml-util" '("nxml-"))
-;;;***
-;;;### (autoloads nil "ob-C" "org/ob-C.el" (0 0 0 0))
;;; Generated autoloads from org/ob-C.el
(register-definition-prefixes "ob-C" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-R" "org/ob-R.el" (0 0 0 0))
;;; Generated autoloads from org/ob-R.el
(register-definition-prefixes "ob-R" '("ob-" "org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-awk" "org/ob-awk.el" (0 0 0 0))
;;; Generated autoloads from org/ob-awk.el
(register-definition-prefixes "ob-awk" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-calc" "org/ob-calc.el" (0 0 0 0))
;;; Generated autoloads from org/ob-calc.el
(register-definition-prefixes "ob-calc" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-clojure" "org/ob-clojure.el" (0 0 0 0))
;;; Generated autoloads from org/ob-clojure.el
(register-definition-prefixes "ob-clojure" '("ob-clojure-" "org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-comint" "org/ob-comint.el" (0 0 0 0))
;;; Generated autoloads from org/ob-comint.el
(register-definition-prefixes "ob-comint" '("org-babel-comint-"))
-;;;***
-;;;### (autoloads nil "ob-css" "org/ob-css.el" (0 0 0 0))
+;;; Generated autoloads from org/ob-core.el
+
+(register-definition-prefixes "ob-core" '("org-"))
+
+
;;; Generated autoloads from org/ob-css.el
(register-definition-prefixes "ob-css" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-ditaa" "org/ob-ditaa.el" (0 0 0 0))
;;; Generated autoloads from org/ob-ditaa.el
(register-definition-prefixes "ob-ditaa" '("org-"))
-;;;***
-;;;### (autoloads nil "ob-dot" "org/ob-dot.el" (0 0 0 0))
;;; Generated autoloads from org/ob-dot.el
(register-definition-prefixes "ob-dot" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-emacs-lisp" "org/ob-emacs-lisp.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from org/ob-emacs-lisp.el
(register-definition-prefixes "ob-emacs-lisp" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-eshell" "org/ob-eshell.el" (0 0 0 0))
;;; Generated autoloads from org/ob-eshell.el
(register-definition-prefixes "ob-eshell" '("ob-eshell-session-live-p" "org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-eval" "org/ob-eval.el" (0 0 0 0))
;;; Generated autoloads from org/ob-eval.el
(register-definition-prefixes "ob-eval" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-exp" "org/ob-exp.el" (0 0 0 0))
;;; Generated autoloads from org/ob-exp.el
(register-definition-prefixes "ob-exp" '("org-"))
-;;;***
-;;;### (autoloads nil "ob-forth" "org/ob-forth.el" (0 0 0 0))
;;; Generated autoloads from org/ob-forth.el
(register-definition-prefixes "ob-forth" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-fortran" "org/ob-fortran.el" (0 0 0 0))
;;; Generated autoloads from org/ob-fortran.el
(register-definition-prefixes "ob-fortran" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-gnuplot" "org/ob-gnuplot.el" (0 0 0 0))
;;; Generated autoloads from org/ob-gnuplot.el
(register-definition-prefixes "ob-gnuplot" '("*org-babel-gnuplot-" "org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-groovy" "org/ob-groovy.el" (0 0 0 0))
;;; Generated autoloads from org/ob-groovy.el
(register-definition-prefixes "ob-groovy" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-haskell" "org/ob-haskell.el" (0 0 0 0))
;;; Generated autoloads from org/ob-haskell.el
(register-definition-prefixes "ob-haskell" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-java" "org/ob-java.el" (0 0 0 0))
;;; Generated autoloads from org/ob-java.el
(register-definition-prefixes "ob-java" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-js" "org/ob-js.el" (0 0 0 0))
;;; Generated autoloads from org/ob-js.el
(register-definition-prefixes "ob-js" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-julia" "org/ob-julia.el" (0 0 0 0))
;;; Generated autoloads from org/ob-julia.el
(register-definition-prefixes "ob-julia" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-latex" "org/ob-latex.el" (0 0 0 0))
;;; Generated autoloads from org/ob-latex.el
(register-definition-prefixes "ob-latex" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-lilypond" "org/ob-lilypond.el" (0 0 0 0))
;;; Generated autoloads from org/ob-lilypond.el
(register-definition-prefixes "ob-lilypond" '("lilypond-mode" "ob-lilypond-header-args" "org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-lisp" "org/ob-lisp.el" (0 0 0 0))
;;; Generated autoloads from org/ob-lisp.el
(register-definition-prefixes "ob-lisp" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-lua" "org/ob-lua.el" (0 0 0 0))
+;;; Generated autoloads from org/ob-lob.el
+
+(register-definition-prefixes "ob-lob" '("org-babel-"))
+
+
;;; Generated autoloads from org/ob-lua.el
(register-definition-prefixes "ob-lua" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-makefile" "org/ob-makefile.el" (0 0 0 0))
;;; Generated autoloads from org/ob-makefile.el
(register-definition-prefixes "ob-makefile" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-maxima" "org/ob-maxima.el" (0 0 0 0))
;;; Generated autoloads from org/ob-maxima.el
(register-definition-prefixes "ob-maxima" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-ocaml" "org/ob-ocaml.el" (0 0 0 0))
;;; Generated autoloads from org/ob-ocaml.el
(register-definition-prefixes "ob-ocaml" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-octave" "org/ob-octave.el" (0 0 0 0))
;;; Generated autoloads from org/ob-octave.el
(register-definition-prefixes "ob-octave" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-org" "org/ob-org.el" (0 0 0 0))
;;; Generated autoloads from org/ob-org.el
(register-definition-prefixes "ob-org" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-perl" "org/ob-perl.el" (0 0 0 0))
;;; Generated autoloads from org/ob-perl.el
(register-definition-prefixes "ob-perl" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-plantuml" "org/ob-plantuml.el" (0 0 0 0))
;;; Generated autoloads from org/ob-plantuml.el
(register-definition-prefixes "ob-plantuml" '("org-"))
-;;;***
-;;;### (autoloads nil "ob-processing" "org/ob-processing.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from org/ob-processing.el
(register-definition-prefixes "ob-processing" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-python" "org/ob-python.el" (0 0 0 0))
;;; Generated autoloads from org/ob-python.el
(register-definition-prefixes "ob-python" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-ref" "org/ob-ref.el" (0 0 0 0))
;;; Generated autoloads from org/ob-ref.el
(register-definition-prefixes "ob-ref" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-ruby" "org/ob-ruby.el" (0 0 0 0))
;;; Generated autoloads from org/ob-ruby.el
(register-definition-prefixes "ob-ruby" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-sass" "org/ob-sass.el" (0 0 0 0))
;;; Generated autoloads from org/ob-sass.el
(register-definition-prefixes "ob-sass" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-scheme" "org/ob-scheme.el" (0 0 0 0))
;;; Generated autoloads from org/ob-scheme.el
(register-definition-prefixes "ob-scheme" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-screen" "org/ob-screen.el" (0 0 0 0))
;;; Generated autoloads from org/ob-screen.el
(register-definition-prefixes "ob-screen" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-sed" "org/ob-sed.el" (0 0 0 0))
;;; Generated autoloads from org/ob-sed.el
(register-definition-prefixes "ob-sed" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-shell" "org/ob-shell.el" (0 0 0 0))
;;; Generated autoloads from org/ob-shell.el
(register-definition-prefixes "ob-shell" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-sql" "org/ob-sql.el" (0 0 0 0))
;;; Generated autoloads from org/ob-sql.el
(register-definition-prefixes "ob-sql" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-sqlite" "org/ob-sqlite.el" (0 0 0 0))
;;; Generated autoloads from org/ob-sqlite.el
(register-definition-prefixes "ob-sqlite" '("org-babel-"))
-;;;***
-;;;### (autoloads nil "ob-table" "org/ob-table.el" (0 0 0 0))
;;; Generated autoloads from org/ob-table.el
(register-definition-prefixes "ob-table" '("org-"))
-;;;***
-;;;### (autoloads nil "oc" "org/oc.el" (0 0 0 0))
+;;; Generated autoloads from org/ob-tangle.el
+
+(register-definition-prefixes "ob-tangle" '("org-babel-"))
+
+
;;; Generated autoloads from org/oc.el
(autoload 'org-cite-insert "oc" "\
@@ -24005,47 +21661,35 @@ Insert a citation at point.
Insertion is done according to the processor set in `org-cite-insert-processor'.
ARG is the prefix argument received when calling interactively the function.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "oc" '("org-cite-"))
-;;;***
-;;;### (autoloads nil "oc-basic" "org/oc-basic.el" (0 0 0 0))
;;; Generated autoloads from org/oc-basic.el
(register-definition-prefixes "oc-basic" '("org-cite-basic-"))
-;;;***
-;;;### (autoloads nil "oc-biblatex" "org/oc-biblatex.el" (0 0 0 0))
;;; Generated autoloads from org/oc-biblatex.el
(register-definition-prefixes "oc-biblatex" '("org-cite-biblatex-"))
-;;;***
-;;;### (autoloads nil "oc-csl" "org/oc-csl.el" (0 0 0 0))
;;; Generated autoloads from org/oc-csl.el
(register-definition-prefixes "oc-csl" '("org-cite-csl-"))
-;;;***
-;;;### (autoloads nil "oc-natbib" "org/oc-natbib.el" (0 0 0 0))
;;; Generated autoloads from org/oc-natbib.el
(register-definition-prefixes "oc-natbib" '("org-cite-natbib-"))
-;;;***
-;;;### (autoloads nil "octave" "progmodes/octave.el" (0 0 0 0))
;;; Generated autoloads from progmodes/octave.el
- (add-to-list 'auto-mode-alist '("\\.m\\'" . octave-maybe-mode))
+ (add-to-list 'auto-mode-alist '("\\.m\\'" . octave-maybe-mode))
(autoload 'octave-maybe-mode "octave" "\
Select `octave-mode' if the current buffer seems to hold Octave code." nil nil)
-
(autoload 'octave-mode "octave" "\
Major mode for editing Octave code.
@@ -24059,8 +21703,7 @@ See Info node `(octave-mode) Using Octave Mode' for more details.
Key bindings:
\\{octave-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'inferior-octave "octave" "\
Run an inferior Octave process, I/O via `inferior-octave-buffer'.
This buffer is put in Inferior Octave mode. See `inferior-octave-mode'.
@@ -24074,103 +21717,89 @@ Additional commands to be executed on startup can be provided either in
the file specified by `inferior-octave-startup-file' or by the default
startup file, `~/.emacs-octave'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(defalias 'run-octave 'inferior-octave)
-
(register-definition-prefixes "octave" '("inferior-octave-" "octave-"))
-;;;***
-;;;### (autoloads nil "ogonek" "international/ogonek.el" (0 0 0 0))
;;; Generated autoloads from international/ogonek.el
(register-definition-prefixes "ogonek" '("ogonek-"))
-;;;***
-;;;### (autoloads nil "ol-bibtex" "org/ol-bibtex.el" (0 0 0 0))
+;;; Generated autoloads from org/ol.el
+
+(register-definition-prefixes "ol" '("org-"))
+
+
+;;; Generated autoloads from org/ol-bbdb.el
+
+(register-definition-prefixes "ol-bbdb" '("org-bbdb-"))
+
+
;;; Generated autoloads from org/ol-bibtex.el
(register-definition-prefixes "ol-bibtex" '("org-"))
-;;;***
-;;;### (autoloads nil "ol-docview" "org/ol-docview.el" (0 0 0 0))
;;; Generated autoloads from org/ol-docview.el
(register-definition-prefixes "ol-docview" '("org-docview-"))
-;;;***
-;;;### (autoloads nil "ol-doi" "org/ol-doi.el" (0 0 0 0))
;;; Generated autoloads from org/ol-doi.el
(register-definition-prefixes "ol-doi" '("org-link-doi-"))
-;;;***
-;;;### (autoloads nil "ol-eshell" "org/ol-eshell.el" (0 0 0 0))
;;; Generated autoloads from org/ol-eshell.el
(register-definition-prefixes "ol-eshell" '("org-eshell-"))
-;;;***
-;;;### (autoloads nil "ol-eww" "org/ol-eww.el" (0 0 0 0))
;;; Generated autoloads from org/ol-eww.el
(register-definition-prefixes "ol-eww" '("org-eww-"))
-;;;***
-;;;### (autoloads nil "ol-gnus" "org/ol-gnus.el" (0 0 0 0))
;;; Generated autoloads from org/ol-gnus.el
(register-definition-prefixes "ol-gnus" '("org-gnus-"))
-;;;***
-;;;### (autoloads nil "ol-info" "org/ol-info.el" (0 0 0 0))
;;; Generated autoloads from org/ol-info.el
(register-definition-prefixes "ol-info" '("org-info-"))
-;;;***
-;;;### (autoloads nil "ol-man" "org/ol-man.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-irc.el
+
+(register-definition-prefixes "ol-irc" '("org-irc-"))
+
+
;;; Generated autoloads from org/ol-man.el
(register-definition-prefixes "ol-man" '("org-man-"))
-;;;***
-;;;### (autoloads nil "ol-mhe" "org/ol-mhe.el" (0 0 0 0))
;;; Generated autoloads from org/ol-mhe.el
(register-definition-prefixes "ol-mhe" '("org-mhe-"))
-;;;***
-;;;### (autoloads nil "ol-rmail" "org/ol-rmail.el" (0 0 0 0))
;;; Generated autoloads from org/ol-rmail.el
(register-definition-prefixes "ol-rmail" '("org-rmail-"))
-;;;***
-;;;### (autoloads nil "ol-w3m" "org/ol-w3m.el" (0 0 0 0))
;;; Generated autoloads from org/ol-w3m.el
(register-definition-prefixes "ol-w3m" '("org-w3m-"))
-;;;***
-;;;### (autoloads nil "opascal" "progmodes/opascal.el" (0 0 0 0))
;;; Generated autoloads from progmodes/opascal.el
(define-obsolete-function-alias 'delphi-mode #'opascal-mode "24.4")
-
(autoload 'opascal-mode "opascal" "\
Major mode for editing OPascal code.
\\<opascal-mode-map>
@@ -24198,21 +21827,17 @@ Coloring:
`opascal-keyword-face' (default `font-lock-keyword-face')
Face used to color OPascal keywords.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "opascal" '("opascal-"))
-;;;***
-;;;### (autoloads nil "org" "org/org.el" (0 0 0 0))
;;; Generated autoloads from org/org.el
-(push (purecopy '(org 9 5 2)) package--builtin-versions)
+(push (purecopy '(org 9 5 4)) package--builtin-versions)
(autoload 'org-babel-do-load-languages "org" "\
Load the languages defined in `org-babel-load-languages'.
-\(fn SYM VALUE)" nil nil)
-
+(fn SYM VALUE)" nil nil)
(autoload 'org-babel-load-file "org" "\
Load Emacs Lisp source code blocks in the Org FILE.
This function exports the source code using `org-babel-tangle'
@@ -24220,8 +21845,7 @@ and then loads the resulting file using `load-file'. With
optional prefix argument COMPILE, the tangled Emacs Lisp file is
byte-compiled before it is loaded.
-\(fn FILE &optional COMPILE)" t nil)
-
+(fn FILE &optional COMPILE)" t nil)
(autoload 'org-version "org" "\
Show the Org version.
Interactively, or when MESSAGE is non-nil, show it in echo area.
@@ -24229,16 +21853,13 @@ With prefix argument, or when HERE is non-nil, insert it at point.
In non-interactive uses, a reduced version string is output unless
FULL is given.
-\(fn &optional HERE FULL MESSAGE)" t nil)
-
+(fn &optional HERE FULL MESSAGE)" t nil)
(autoload 'org-load-modules-maybe "org" "\
Load all extensions listed in `org-modules'.
-\(fn &optional FORCE)" nil nil)
-
+(fn &optional FORCE)" nil nil)
(autoload 'org-clock-persistence-insinuate "org" "\
Set up hooks for clock persistence." nil nil)
-
(autoload 'org-mode "org" "\
Outline-based notes management and organizer, alias
\"Carsten's outline-mode for keeping track of everything.\"
@@ -24258,8 +21879,7 @@ The following commands are available:
\\{org-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'org-cycle "org" "\
TAB-action and visibility cycling for Org mode.
@@ -24310,23 +21930,20 @@ there is no headline there, and if the variable `org-cycle-global-at-bob'
is non-nil, this function acts as if called with prefix argument (`\\[universal-argument] TAB',
same as `S-TAB') also when called without prefix argument.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'org-global-cycle "org" "\
Cycle the global visibility. For details see `org-cycle'.
With `\\[universal-argument]' prefix ARG, switch to startup visibility.
With a numeric prefix, show all headlines up to that level.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'org-run-like-in-org-mode "org" "\
Run a command, pretending that the current buffer is in Org mode.
This will temporarily bind local variables that are typically bound in
Org mode to the values they have in Org mode, and then interactively
call CMD.
-\(fn CMD)" nil nil)
-
+(fn CMD)" nil nil)
(autoload 'org-open-file "org" "\
Open the file at PATH.
First, this expands any special file name abbreviations. Then the
@@ -24349,8 +21966,7 @@ link, please customize `org-link-frame-setup'.
If the file does not exist, throw an error.
-\(fn PATH &optional IN-EMACS LINE SEARCH)" nil nil)
-
+(fn PATH &optional IN-EMACS LINE SEARCH)" nil nil)
(autoload 'org-open-at-point-global "org" "\
Follow a link or a time-stamp like Org mode does.
Also follow links and emails as seen by `thing-at-point'.
@@ -24358,7 +21974,6 @@ This command can be called in any mode to follow an external
link or a time-stamp that has Org mode syntax. Its behavior
is undefined when called on internal links like fuzzy links.
Raise a user error when there is nothing to follow." t nil)
-
(autoload 'org-offer-links-in-entry "org" "\
Offer links in the current entry and return the selected link.
If there is only one link, return it.
@@ -24366,8 +21981,7 @@ If NTH is an integer, return the NTH link found.
If ZERO is a string, check also this string for a link, and if
there is one, return it.
-\(fn BUFFER MARKER &optional NTH ZERO)" nil nil)
-
+(fn BUFFER MARKER &optional NTH ZERO)" nil nil)
(autoload 'org-switchb "org" "\
Switch between Org buffers.
@@ -24375,13 +21989,11 @@ With `\\[universal-argument]' prefix, restrict available buffers to files.
With `\\[universal-argument] \\[universal-argument]' prefix, restrict available buffers to agenda files.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'org-cycle-agenda-files "org" "\
Cycle through the files in `org-agenda-files'.
If the current buffer visits an agenda file, find the next one in the list.
If the current buffer does not, find the first agenda file." t nil)
-
(autoload 'org-submit-bug-report "org" "\
Submit a bug report on Org via mail.
@@ -24390,28 +22002,22 @@ Don't hesitate to report any problems or inaccurate documentation.
If you don't have setup sending mail from (X)Emacs, please copy the
output buffer into your mail program, as it gives us important
information about your Org version and configuration." t nil)
-
(autoload 'org-reload "org" "\
Reload all Org Lisp files.
With prefix arg UNCOMPILED, load the uncompiled versions.
-\(fn &optional UNCOMPILED)" t nil)
-
+(fn &optional UNCOMPILED)" t nil)
(autoload 'org-customize "org" "\
Call the customize function with org as argument." t nil)
-
(register-definition-prefixes "org" '("org-" "turn-on-org-cdlatex"))
-;;;***
-;;;### (autoloads nil "org-agenda" "org/org-agenda.el" (0 0 0 0))
;;; Generated autoloads from org/org-agenda.el
(autoload 'org-toggle-sticky-agenda "org-agenda" "\
Toggle `org-agenda-sticky'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'org-agenda "org-agenda" "\
Dispatch agenda commands to collect entries to the agenda buffer.
Prompts for a command to execute. Any prefix arg will be passed
@@ -24442,12 +22048,11 @@ searches can be pre-defined in this way.
If the current buffer is in Org mode and visiting a file, you can also
first press `<' once to indicate that the agenda should be temporarily
-\(until the next use of `\\[org-agenda]') restricted to the current file.
+(until the next use of `\\[org-agenda]') restricted to the current file.
Pressing `<' twice means to restrict to the current subtree or region
-\(if active).
-
-\(fn &optional ARG KEYS RESTRICTION)" t nil)
+(if active).
+(fn &optional ARG KEYS RESTRICTION)" t nil)
(autoload 'org-batch-agenda "org-agenda" "\
Run an agenda command in batch mode and send the result to STDOUT.
If CMD-KEY is a string of length 1, it is used as a key in
@@ -24456,8 +22061,7 @@ longer string it is used as a tags/todo match string.
Parameters are alternating variable names and values that will be bound
before running the agenda command.
-\(fn CMD-KEY &rest PARAMETERS)" nil t)
-
+(fn CMD-KEY &rest PARAMETERS)" nil t)
(autoload 'org-batch-agenda-csv "org-agenda" "\
Run an agenda command in batch mode and send the result to STDOUT.
If CMD-KEY is a string of length 1, it is used as a key in
@@ -24493,18 +22097,15 @@ priority-l The priority letter if any was given
priority-n The computed numerical priority
agenda-day The day in the agenda where this is listed
-\(fn CMD-KEY &rest PARAMETERS)" nil t)
-
+(fn CMD-KEY &rest PARAMETERS)" nil t)
(autoload 'org-store-agenda-views "org-agenda" "\
Store agenda views.
-\(fn &rest PARAMETERS)" t nil)
-
+(fn &rest PARAMETERS)" t nil)
(autoload 'org-batch-store-agenda-views "org-agenda" "\
Run all custom agenda commands that have a file argument.
-\(fn &rest PARAMETERS)" nil t)
-
+(fn &rest PARAMETERS)" nil t)
(autoload 'org-agenda-list "org-agenda" "\
Produce a daily/weekly view from all files in variable `org-agenda-files'.
The view will be for the current day or week, but from the overview buffer
@@ -24520,8 +22121,7 @@ given in `org-agenda-start-on-weekday'.
When WITH-HOUR is non-nil, only include scheduled and deadline
items if they have an hour specification like [h]h:mm.
-\(fn &optional ARG START-DAY SPAN WITH-HOUR)" t nil)
-
+(fn &optional ARG START-DAY SPAN WITH-HOUR)" t nil)
(autoload 'org-search-view "org-agenda" "\
Show all entries that contain a phrase or words or regular expressions.
@@ -24567,31 +22167,27 @@ This command searches the agenda files, and in addition the files
listed in `org-agenda-text-search-extra-files' unless a restriction lock
is active.
-\(fn &optional TODO-ONLY STRING EDIT-AT)" t nil)
-
+(fn &optional TODO-ONLY STRING EDIT-AT)" t nil)
(autoload 'org-todo-list "org-agenda" "\
-Show all (not done) TODO entries from all agenda file in a single list.
+Show all (not done) TODO entries from all agenda files in a single list.
The prefix arg can be used to select a specific TODO keyword and limit
the list to these. When using `\\[universal-argument]', you will be prompted
for a keyword. A numeric prefix directly selects the Nth keyword in
`org-todo-keywords-1'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'org-tags-view "org-agenda" "\
Show all headlines for all `org-agenda-files' matching a TAGS criterion.
The prefix arg TODO-ONLY limits the search to TODO entries.
-\(fn &optional TODO-ONLY MATCH)" t nil)
-
+(fn &optional TODO-ONLY MATCH)" t nil)
(autoload 'org-agenda-list-stuck-projects "org-agenda" "\
Create agenda view for projects that are stuck.
Stuck projects are project that have no next actions. For the definitions
of what a project is and how to check if it stuck, customize the variable
`org-stuck-projects'.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'org-diary "org-agenda" "\
Return diary information from org files.
This function can be used in a \"sexp\" diary entry in the Emacs calendar.
@@ -24619,28 +22215,24 @@ The function expects the lisp variables `entry' and `date' to be provided
by the caller, because this is how the calendar works. Don't use this
function from a program - use `org-agenda-get-day-entries' instead.
-\(fn &rest ARGS)" nil nil)
-
+(fn &rest ARGS)" nil nil)
(autoload 'org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item "org-agenda" "\
Do we have a reason to ignore this TODO entry because it has a time stamp?
-\(fn &optional END)" nil nil)
-
+(fn &optional END)" nil nil)
(autoload 'org-agenda-set-restriction-lock "org-agenda" "\
Set restriction lock for agenda to current subtree or file.
When in a restricted subtree, remove it.
The restriction will span over the entire file if TYPE is `file',
-or if type is '(4), or if the cursor is before the first headline
+or if type is \\='(4), or if the cursor is before the first headline
in the file. Otherwise, only apply the restriction to the current
subtree.
-\(fn &optional TYPE)" t nil)
-
+(fn &optional TYPE)" t nil)
(autoload 'org-calendar-goto-agenda "org-agenda" "\
Compute the Org agenda for the calendar date displayed at the cursor.
This is a command that has to be installed in `calendar-mode-map'." t nil)
-
(autoload 'org-agenda-to-appt "org-agenda" "\
Activate appointments found in `org-agenda-files'.
@@ -24667,35 +22259,38 @@ belonging to the \"Work\" category.
ARGS are symbols indicating what kind of entries to consider.
By default `org-agenda-to-appt' will use :deadline*, :scheduled*
-\(i.e., deadlines and scheduled items with a hh:mm specification)
+(i.e., deadlines and scheduled items with a hh:mm specification)
and :timestamp entries. See the docstring of `org-diary' for
details and examples.
If an entry has a APPT_WARNTIME property, its value will be used
to override `appt-message-warning-time'.
-\(fn &optional REFRESH FILTER &rest ARGS)" t nil)
-
+(fn &optional REFRESH FILTER &rest ARGS)" t nil)
(register-definition-prefixes "org-agenda" '("org-"))
-;;;***
-;;;### (autoloads nil "org-attach-git" "org/org-attach-git.el" (0
-;;;;;; 0 0 0))
+;;; Generated autoloads from org/org-archive.el
+
+(register-definition-prefixes "org-archive" '("org-a"))
+
+
+;;; Generated autoloads from org/org-attach.el
+
+(register-definition-prefixes "org-attach" '("org-attach-"))
+
+
;;; Generated autoloads from org/org-attach-git.el
(register-definition-prefixes "org-attach-git" '("org-attach-git-"))
-;;;***
-;;;### (autoloads nil "org-capture" "org/org-capture.el" (0 0 0 0))
;;; Generated autoloads from org/org-capture.el
(autoload 'org-capture-string "org-capture" "\
Capture STRING with the template selected by KEYS.
-\(fn STRING &optional KEYS)" t nil)
-
+(fn STRING &optional KEYS)" t nil)
(autoload 'org-capture "org-capture" "\
Capture something.
\\<org-capture-mode-map>
@@ -24725,137 +22320,202 @@ agenda will use the date at point as the default date. Then, a
`C-1' prefix will tell the capture process to use the HH:MM time
of the day at point (if any) or the current HH:MM time.
-\(fn &optional GOTO KEYS)" t nil)
-
+(fn &optional GOTO KEYS)" t nil)
(autoload 'org-capture-import-remember-templates "org-capture" "\
Set `org-capture-templates' to be similar to `org-remember-templates'." t nil)
-
(register-definition-prefixes "org-capture" '("org-capture-"))
-;;;***
-;;;### (autoloads nil "org-crypt" "org/org-crypt.el" (0 0 0 0))
+;;; Generated autoloads from org/org-clock.el
+
+(register-definition-prefixes "org-clock" '("org-"))
+
+
+;;; Generated autoloads from org/org-colview.el
+
+(register-definition-prefixes "org-colview" '("org-"))
+
+
+;;; Generated autoloads from org/org-compat.el
+
+(register-definition-prefixes "org-compat" '("org-"))
+
+
;;; Generated autoloads from org/org-crypt.el
(autoload 'org-encrypt-entry "org-crypt" "\
Encrypt the content of the current headline." t nil)
-
(autoload 'org-decrypt-entry "org-crypt" "\
Decrypt the content of the current headline." t nil)
-
(autoload 'org-encrypt-entries "org-crypt" "\
Encrypt all top-level entries in the current buffer." t nil)
-
(autoload 'org-decrypt-entries "org-crypt" "\
Decrypt all entries in the current buffer." t nil)
-
(autoload 'org-crypt-use-before-save-magic "org-crypt" "\
Add a hook to automatically encrypt entries before a file is saved to disk." nil nil)
-
(register-definition-prefixes "org-crypt" '("org-"))
-;;;***
-;;;### (autoloads nil "org-ctags" "org/org-ctags.el" (0 0 0 0))
;;; Generated autoloads from org/org-ctags.el
(register-definition-prefixes "org-ctags" '("org-ctags-"))
-;;;***
-;;;### (autoloads nil "org-entities" "org/org-entities.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from org/org-datetree.el
+
+(register-definition-prefixes "org-datetree" '("org-datetree-"))
+
+
+;;; Generated autoloads from org/org-duration.el
+
+(register-definition-prefixes "org-duration" '("org-duration-"))
+
+
+;;; Generated autoloads from org/org-element.el
+
+(register-definition-prefixes "org-element" '("org-element-"))
+
+
;;; Generated autoloads from org/org-entities.el
(register-definition-prefixes "org-entities" '("org-entit"))
-;;;***
-;;;### (autoloads nil "org-faces" "org/org-faces.el" (0 0 0 0))
;;; Generated autoloads from org/org-faces.el
(register-definition-prefixes "org-faces" '("org-"))
-;;;***
-;;;### (autoloads nil "org-habit" "org/org-habit.el" (0 0 0 0))
+;;; Generated autoloads from org/org-feed.el
+
+(register-definition-prefixes "org-feed" '("org-feed-"))
+
+
+;;; Generated autoloads from org/org-footnote.el
+
+(register-definition-prefixes "org-footnote" '("org-footnote-"))
+
+
+;;; Generated autoloads from org/org-goto.el
+
+(register-definition-prefixes "org-goto" '("org-goto-"))
+
+
;;; Generated autoloads from org/org-habit.el
(register-definition-prefixes "org-habit" '("org-"))
-;;;***
-;;;### (autoloads nil "org-inlinetask" "org/org-inlinetask.el" (0
-;;;;;; 0 0 0))
+;;; Generated autoloads from org/org-id.el
+
+(register-definition-prefixes "org-id" '("org-id-"))
+
+
+;;; Generated autoloads from org/org-indent.el
+
+(register-definition-prefixes "org-indent" '("org-indent-"))
+
+
;;; Generated autoloads from org/org-inlinetask.el
(register-definition-prefixes "org-inlinetask" '("org-inlinetask-"))
-;;;***
-;;;### (autoloads nil "org-macro" "org/org-macro.el" (0 0 0 0))
+;;; Generated autoloads from org/org-keys.el
+
+(register-definition-prefixes "org-keys" '("org-"))
+
+
+;;; Generated autoloads from org/org-lint.el
+
+(register-definition-prefixes "org-lint" '("org-lint-"))
+
+
+;;; Generated autoloads from org/org-list.el
+
+(register-definition-prefixes "org-list" '("org-"))
+
+
;;; Generated autoloads from org/org-macro.el
(register-definition-prefixes "org-macro" '("org-macro-"))
-;;;***
-;;;### (autoloads nil "org-mouse" "org/org-mouse.el" (0 0 0 0))
+;;; Generated autoloads from org/org-macs.el
+
+(register-definition-prefixes "org-macs" '("org-"))
+
+
+;;; Generated autoloads from org/org-mobile.el
+
+(register-definition-prefixes "org-mobile" '("org-mobile-"))
+
+
;;; Generated autoloads from org/org-mouse.el
(register-definition-prefixes "org-mouse" '("org-mouse-"))
-;;;***
-;;;### (autoloads nil "org-pcomplete" "org/org-pcomplete.el" (0 0
-;;;;;; 0 0))
+;;; Generated autoloads from org/org-num.el
+
+(register-definition-prefixes "org-num" '("org-num-"))
+
+
;;; Generated autoloads from org/org-pcomplete.el
(register-definition-prefixes "org-pcomplete" '("org-" "pcomplete/org-mode/"))
-;;;***
-;;;### (autoloads nil "org-protocol" "org/org-protocol.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from org/org-plot.el
+
+(register-definition-prefixes "org-plot" '("org-"))
+
+
;;; Generated autoloads from org/org-protocol.el
(register-definition-prefixes "org-protocol" '("org-protocol-"))
-;;;***
-;;;### (autoloads nil "org-src" "org/org-src.el" (0 0 0 0))
+;;; Generated autoloads from org/org-refile.el
+
+(register-definition-prefixes "org-refile" '("org-"))
+
+
;;; Generated autoloads from org/org-src.el
(register-definition-prefixes "org-src" '("org-"))
-;;;***
-;;;### (autoloads nil "org-tempo" "org/org-tempo.el" (0 0 0 0))
+;;; Generated autoloads from org/org-table.el
+
+(register-definition-prefixes "org-table" '("org"))
+
+
;;; Generated autoloads from org/org-tempo.el
(register-definition-prefixes "org-tempo" '("org-tempo-"))
-;;;***
-;;;### (autoloads nil "org-version" "org/org-version.el" (0 0 0 0))
+;;; Generated autoloads from org/org-timer.el
+
+(register-definition-prefixes "org-timer" '("org-timer-"))
+
+
;;; Generated autoloads from org/org-version.el
(autoload 'org-release "org-version" "\
The release version of Org.
Inserted by installing Org mode or when a release is made." nil nil)
-
(autoload 'org-git-version "org-version" "\
The Git version of Org mode.
Inserted by installing Org or when a release is made." nil nil)
-;;;***
-;;;### (autoloads nil "outline" "outline.el" (0 0 0 0))
;;; Generated autoloads from outline.el
+
(put 'outline-regexp 'safe-local-variable 'stringp)
(put 'outline-heading-end-regexp 'safe-local-variable 'stringp)
(put 'outline-level 'risky-local-variable t)
-
(autoload 'outline-mode "outline" "\
Set major mode for editing outlines with selective display.
Headings are lines which start with asterisks: one for major headings,
@@ -24879,35 +22539,55 @@ beginning of the line. The longer the match, the deeper the level.
Turning on outline mode calls the value of `text-mode-hook' and then of
`outline-mode-hook', if they are non-nil.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'outline-minor-mode "outline" "\
Toggle Outline minor mode.
-This is a minor mode. If called interactively, toggle the `Outline
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
+See the command `outline-mode' for more information on this mode.
+
+This is a minor mode. If called interactively, toggle the
+`Outline minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `outline-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-See the command `outline-mode' for more information on this mode.
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "outline" '("outline-"))
+
+
+;;; Generated autoloads from org/ox.el
-\(fn &optional ARG)" t nil)
+(register-definition-prefixes "ox" '("org-export-"))
-(register-definition-prefixes "outline" '("outline-"))
+
+;;; Generated autoloads from org/ox-ascii.el
+
+(register-definition-prefixes "ox-ascii" '("org-ascii-"))
+
+
+;;; Generated autoloads from org/ox-beamer.el
+
+(register-definition-prefixes "ox-beamer" '("org-beamer-"))
+
+
+;;; Generated autoloads from org/ox-html.el
+
+(register-definition-prefixes "ox-html" '("org-html-"))
+
+
+;;; Generated autoloads from org/ox-icalendar.el
+
+(register-definition-prefixes "ox-icalendar" '("org-icalendar-"))
-;;;***
-;;;### (autoloads nil "ox-koma-letter" "org/ox-koma-letter.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from org/ox-koma-letter.el
(autoload 'org-koma-letter-export-as-latex "ox-koma-letter" "\
@@ -24940,8 +22620,7 @@ Export is done in a buffer named \"*Org KOMA-LETTER Export*\". It
will be displayed if `org-export-show-temporary-export-buffer' is
non-nil.
-\(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
-
+(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
(autoload 'org-koma-letter-export-to-latex "ox-koma-letter" "\
Export current buffer as a KOMA Scrlttr2 letter (tex).
@@ -24973,8 +22652,7 @@ directory.
Return output file's name.
-\(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
-
+(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
(autoload 'org-koma-letter-export-to-pdf "ox-koma-letter" "\
Export current buffer as a KOMA Scrlttr2 letter (pdf).
@@ -25003,23 +22681,48 @@ file-local settings.
Return PDF file's name.
-\(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
-
+(fn &optional ASYNC SUBTREEP VISIBLE-ONLY BODY-ONLY EXT-PLIST)" t nil)
(register-definition-prefixes "ox-koma-letter" '("org-koma-letter-"))
-;;;***
-;;;### (autoloads nil "ox-man" "org/ox-man.el" (0 0 0 0))
+;;; Generated autoloads from org/ox-latex.el
+
+(register-definition-prefixes "ox-latex" '("org-latex-"))
+
+
;;; Generated autoloads from org/ox-man.el
(register-definition-prefixes "ox-man" '("org-man-"))
-;;;***
-;;;### (autoloads nil "package" "emacs-lisp/package.el" (0 0 0 0))
+;;; Generated autoloads from org/ox-md.el
+
+(register-definition-prefixes "ox-md" '("org-md-"))
+
+
+;;; Generated autoloads from org/ox-odt.el
+
+(register-definition-prefixes "ox-odt" '("org-odt-"))
+
+
+;;; Generated autoloads from org/ox-org.el
+
+(register-definition-prefixes "ox-org" '("org-org-"))
+
+
+;;; Generated autoloads from org/ox-publish.el
+
+(register-definition-prefixes "ox-publish" '("org-publish-"))
+
+
+;;; Generated autoloads from org/ox-texinfo.el
+
+(register-definition-prefixes "ox-texinfo" '("org-texinfo-"))
+
+
;;; Generated autoloads from emacs-lisp/package.el
-(push (purecopy '(package 1 1 0)) package--builtin-versions)
+(push (purecopy '(package 1 1 0)) package--builtin-versions)
(defvar package-enable-at-startup t "\
Whether to make installed packages available when Emacs starts.
If non-nil, packages are made available before reading the init
@@ -25032,29 +22735,22 @@ with \"-q\").
Even if the value is nil, you can type \\[package-initialize] to
make installed packages available at any time, or you can
call (package-activate-all) in your init-file.")
-
(custom-autoload 'package-enable-at-startup "package" t)
-
(defcustom package-user-dir (locate-user-emacs-file "elpa") "\
Directory containing the user's Emacs Lisp packages.
The directory name should be absolute.
Apart from this directory, Emacs also looks for system-wide
packages in `package-directory-list'." :type 'directory :initialize #'custom-initialize-delay :risky t :version "24.1")
-
(custom-autoload 'package-user-dir "package" t)
-
(defcustom package-directory-list (let (result) (dolist (f load-path) (and (stringp f) (equal (file-name-nondirectory f) "site-lisp") (push (expand-file-name "elpa" f) result))) (nreverse result)) "\
List of additional directories containing Emacs Lisp packages.
Each directory name should be absolute.
These directories contain packages intended for system-wide; in
contrast, `package-user-dir' contains packages for personal use." :type '(repeat directory) :initialize #'custom-initialize-delay :risky t :version "24.1")
-
(custom-autoload 'package-directory-list "package" t)
-
(defvar package--activated nil "\
Non-nil if `package-activate-all' has been run.")
-
(autoload 'package-initialize "package" "\
Load Emacs Lisp packages, and activate them.
The variable `package-load-list' controls which packages to load.
@@ -25071,17 +22767,14 @@ superfluous call to `package-initialize' from your init-file. If
you have code which must run before `package-initialize', put
that code in the early init-file.
-\(fn &optional NO-ACTIVATE)" t nil)
-
+(fn &optional NO-ACTIVATE)" t nil)
(defun package-activate-all nil "\
Activate all installed packages.
-The variable `package-load-list' controls which packages to load." (setq package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if (file-readable-p elc) elc (if (file-readable-p package-quickstart-file) package-quickstart-file)))) (if qs (let ((load-source-file-function nil)) (unless (boundp 'package-activated-list) (setq package-activated-list nil)) (load qs nil 'nomessage)) (require 'package) (package--activate-all))))
-
+The variable `package-load-list' controls which packages to load." (setq package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if (file-readable-p elc) elc (if (file-readable-p package-quickstart-file) package-quickstart-file)))) (if (and qs (not (bound-and-true-p package-activated-list))) (let ((load-source-file-function nil)) (unless (boundp 'package-activated-list) (setq package-activated-list nil)) (load qs nil 'nomessage)) (require 'package) (package--activate-all))))
(autoload 'package-import-keyring "package" "\
Import keys from FILE.
-\(fn &optional FILE)" t nil)
-
+(fn &optional FILE)" t nil)
(autoload 'package-refresh-contents "package" "\
Download descriptions of all configured ELPA packages.
For each archive configured in the variable `package-archives',
@@ -25090,8 +22783,15 @@ and make them available for download.
Optional argument ASYNC specifies whether to perform the
downloads in the background.
-\(fn &optional ASYNC)" t nil)
+(fn &optional ASYNC)" t nil)
+(autoload 'package-installed-p "package" "\
+Return non-nil if PACKAGE, of MIN-VERSION or newer, is installed.
+If PACKAGE is a symbol, it is the package name and MIN-VERSION
+should be a version list.
+If PACKAGE is a `package-desc' object, MIN-VERSION is ignored.
+
+(fn PACKAGE &optional MIN-VERSION)" nil nil)
(autoload 'package-install "package" "\
Install the package PKG.
PKG can be a `package-desc' or a symbol naming one of the
@@ -25108,8 +22808,17 @@ non-nil, install the package but do not add it to
If PKG is a `package-desc' and it is already installed, don't try
to install it but still mark it as selected.
-\(fn PKG &optional DONT-SELECT)" t nil)
+(fn PKG &optional DONT-SELECT)" t nil)
+(autoload 'package-update "package" "\
+Update package NAME if a newer version exists.
+
+(fn NAME)" t nil)
+(autoload 'package-update-all "package" "\
+Refresh package list and upgrade all packages.
+If QUERY, ask the user before updating packages. When called
+interactively, QUERY is always true.
+(fn &optional QUERY)" t nil)
(autoload 'package-install-from-buffer "package" "\
Install a package from the current buffer.
The current buffer is assumed to be a single .el or .tar file or
@@ -25121,41 +22830,45 @@ description file is not mandatory, in which case the information
is derived from the main .el file in the directory.
Downloads and installs required packages as needed." t nil)
-
(autoload 'package-install-file "package" "\
Install a package from FILE.
The file can either be a tar file, an Emacs Lisp file, or a
directory.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'package-install-selected-packages "package" "\
Ensure packages in `package-selected-packages' are installed.
If some packages are not installed, propose to install them.
If optional argument NOCONFIRM is non-nil, don't ask for
confirmation to install packages.
-\(fn &optional NOCONFIRM)" t nil)
-
+(fn &optional NOCONFIRM)" t nil)
(autoload 'package-reinstall "package" "\
Reinstall package PKG.
PKG should be either a symbol, the package name, or a `package-desc'
object.
-\(fn PKG)" t nil)
+(fn PKG)" t nil)
+(autoload 'package-recompile "package" "\
+Byte-compile package PKG again.
+PKG should be either a symbol, the package name, or a `package-desc'
+object.
+(fn PKG)" t nil)
+(autoload 'package-recompile-all "package" "\
+Byte-compile all installed packages.
+This is meant to be used only in the case the byte-compiled files
+are invalid due to changed byte-code, macros or the like." t nil)
(autoload 'package-autoremove "package" "\
Remove packages that are no longer needed.
Packages that are no more needed by other packages in
`package-selected-packages' and their dependencies
will be deleted." t nil)
-
(autoload 'describe-package "package" "\
Display the full documentation of PACKAGE (a symbol).
-\(fn PACKAGE)" t nil)
-
+(fn PACKAGE)" t nil)
(autoload 'list-packages "package" "\
Display a list of packages.
This first fetches the updated list of packages before
@@ -25164,10 +22877,8 @@ The list is displayed in a buffer named `*Packages*', and
includes the package's version, availability status, and a
short description.
-\(fn &optional NO-FETCH)" t nil)
-
+(fn &optional NO-FETCH)" t nil)
(defalias 'package-list-packages 'list-packages)
-
(autoload 'package-get-version "package" "\
Return the version number of the package in which this is used.
Assumes it is used from an Elisp file placed inside the top-level directory
@@ -25175,20 +22886,13 @@ of an installed ELPA package.
The return value is a string (or nil in case we can't find it).
It works in more cases if the call is in the file which contains
the `Version:' header." nil nil)
-
(function-put 'package-get-version 'pure 't)
-
(defcustom package-quickstart-file (locate-user-emacs-file "package-quickstart.el") "\
Location of the file used to speed up activation of packages at startup." :type 'file :initialize #'custom-initialize-delay :version "27.1")
-
(custom-autoload 'package-quickstart-file "package" t)
-
(register-definition-prefixes "package" '("bad-signature" "define-package" "describe-package-1" "package-"))
-;;;***
-;;;### (autoloads nil "package-x" "emacs-lisp/package-x.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/package-x.el
(autoload 'package-upload-file "package-x" "\
@@ -25201,27 +22905,21 @@ contents list with this information.
If `package-archive-upload-base' does not specify a valid upload
destination, prompt for one. If the directory does not exist, it
is created. The directory need not have any initial contents
-\(i.e., you can use this command to populate an initially empty
+(i.e., you can use this command to populate an initially empty
archive).
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(register-definition-prefixes "package-x" '("package-"))
-;;;***
-;;;### (autoloads nil "page-ext" "textmodes/page-ext.el" (0 0 0 0))
;;; Generated autoloads from textmodes/page-ext.el
(register-definition-prefixes "page-ext" '("pages-"))
-;;;***
-;;;### (autoloads nil "parse-time" "calendar/parse-time.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from calendar/parse-time.el
-(put 'parse-time-rules 'risky-local-variable t)
+(put 'parse-time-rules 'risky-local-variable t)
(autoload 'parse-time-string "parse-time" "\
Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\",
@@ -25233,13 +22931,10 @@ The values returned are identical to those of `decode-time', but
any unknown values other than DST are returned as nil, and an
unknown DST value is returned as -1.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(register-definition-prefixes "parse-time" '("parse-"))
-;;;***
-;;;### (autoloads nil "pascal" "progmodes/pascal.el" (0 0 0 0))
;;; Generated autoloads from progmodes/pascal.el
(autoload 'pascal-mode "pascal" "\
@@ -25284,37 +22979,26 @@ Variables controlling indentation/edit style:
See also the user variables `pascal-type-keywords', `pascal-start-keywords' and
`pascal-separator-keywords'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "pascal" '("electric-pascal-" "pascal-"))
-;;;***
-;;;### (autoloads nil "password-cache" "password-cache.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from password-cache.el
(defvar password-cache t "\
Whether to cache passwords.")
-
(custom-autoload 'password-cache "password-cache" t)
-
(defvar password-cache-expiry 16 "\
How many seconds passwords are cached, or nil to disable expiring.
Whether passwords are cached at all is controlled by `password-cache'.")
-
(custom-autoload 'password-cache-expiry "password-cache" t)
-
(autoload 'password-in-cache-p "password-cache" "\
Check if KEY is in the cache.
-\(fn KEY)" nil nil)
-
+(fn KEY)" nil nil)
(register-definition-prefixes "password-cache" '("password-"))
-;;;***
-;;;### (autoloads nil "pcase" "emacs-lisp/pcase.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/pcase.el
(autoload 'pcase "pcase" "\
@@ -25357,14 +23041,10 @@ Additional patterns can be defined using `pcase-defmacro'.
See Info node `(elisp) Pattern-Matching Conditional' in the
Emacs Lisp manual for more information and examples.
-\(fn EXP &rest CASES)" nil t)
-
-(function-put 'pcase 'lisp-indent-function '1)
-
+(fn EXP &rest CASES)" nil t)
+(function-put 'pcase 'lisp-indent-function 1)
(put 'pcase 'function-documentation '(pcase--make-docstring))
-
(autoload 'pcase--make-docstring "pcase" nil nil nil)
-
(autoload 'pcase-exhaustive "pcase" "\
The exhaustive version of `pcase' (which see).
If EXP fails to match any of the patterns in CASES, an error is
@@ -25373,22 +23053,17 @@ signaled.
In contrast, `pcase' will return nil if there is no match, but
not signal an error.
-\(fn EXP &rest CASES)" nil t)
-
-(function-put 'pcase-exhaustive 'lisp-indent-function '1)
-
+(fn EXP &rest CASES)" nil t)
+(function-put 'pcase-exhaustive 'lisp-indent-function 1)
(autoload 'pcase-lambda "pcase" "\
Like `lambda' but allow each argument to be a pattern.
I.e. accepts the usual &optional and &rest keywords, but every
formal argument can be any pattern accepted by `pcase' (a mere
variable name being but a special case of it).
-\(fn LAMBDA-LIST &rest BODY)" nil t)
-
-(function-put 'pcase-lambda 'doc-string-elt '2)
-
+(fn LAMBDA-LIST &rest BODY)" nil t)
+(function-put 'pcase-lambda 'doc-string-elt 2)
(function-put 'pcase-lambda 'lisp-indent-function 'defun)
-
(autoload 'pcase-let* "pcase" "\
Like `let*', but supports destructuring BINDINGS using `pcase' patterns.
As with `pcase-let', BINDINGS are of the form (PATTERN EXP), but the
@@ -25399,10 +23074,8 @@ Each EXP should match (i.e. be of compatible structure) to its
respective PATTERN; a mismatch may signal an error or may go
undetected, binding variables to arbitrary values, such as nil.
-\(fn BINDINGS &rest BODY)" nil t)
-
-(function-put 'pcase-let* 'lisp-indent-function '1)
-
+(fn BINDINGS &rest BODY)" nil t)
+(function-put 'pcase-let* 'lisp-indent-function 1)
(autoload 'pcase-let "pcase" "\
Like `let', but supports destructuring BINDINGS using `pcase' patterns.
BODY should be a list of expressions, and BINDINGS should be a list of
@@ -25415,10 +23088,8 @@ Each EXP should match (i.e. be of compatible structure) to its
respective PATTERN; a mismatch may signal an error or may go
undetected, binding variables to arbitrary values, such as nil.
-\(fn BINDINGS &rest BODY)" nil t)
-
-(function-put 'pcase-let 'lisp-indent-function '1)
-
+(fn BINDINGS &rest BODY)" nil t)
+(function-put 'pcase-let 'lisp-indent-function 1)
(autoload 'pcase-dolist "pcase" "\
Eval BODY once for each set of bindings defined by PATTERN and LIST elements.
PATTERN should be a `pcase' pattern describing the structure of
@@ -25430,23 +23101,20 @@ then evaluates BODY with these bindings in effect. The
destructuring bindings of variables in PATTERN to the subfields
of the elements of LIST is performed as if by `pcase-let'.
-\(fn (PATTERN LIST) BODY...)" nil t)
-
-(function-put 'pcase-dolist 'lisp-indent-function '1)
-
+(fn (PATTERN LIST) BODY...)" nil t)
+(function-put 'pcase-dolist 'lisp-indent-function 1)
(autoload 'pcase-setq "pcase" "\
Assign values to variables by destructuring with `pcase'.
PATTERNS are normal `pcase' patterns, and VALUES are expression.
Evaluation happens sequentially as in `setq' (not in parallel).
-An example: (pcase-setq `((,a) [(,b)]) '((1) [(2)]))
+An example: (pcase-setq \\=`((,a) [(,b)]) \\='((1) [(2)]))
VAL is presumed to match PAT. Failure to match may signal an error or go
undetected, binding variables to arbitrary values, such as nil.
-\(fn PATTERNS VALUE PATTERN VALUES ...)" nil t)
-
+(fn PATTERNS VALUE PATTERN VALUES ...)" nil t)
(autoload 'pcase-defmacro "pcase" "\
Define a new kind of pcase PATTERN, by macro expansion.
Patterns of the form (NAME ...) will be expanded according
@@ -25455,146 +23123,99 @@ to this macro.
By convention, DOC should use \"EXPVAL\" to stand
for the result of evaluating EXP (first arg to `pcase').
-\(fn NAME ARGS [DOC] &rest BODY...)" nil t)
-
-(function-put 'pcase-defmacro 'lisp-indent-function '2)
-
-(function-put 'pcase-defmacro 'doc-string-elt '3)
-
+(fn NAME ARGS [DOC] &rest BODY...)" nil t)
+(function-put 'pcase-defmacro 'lisp-indent-function 2)
+(function-put 'pcase-defmacro 'doc-string-elt 3)
(register-definition-prefixes "pcase" '("pcase-"))
-;;;***
-;;;### (autoloads nil "pcmpl-cvs" "pcmpl-cvs.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-cvs.el
(autoload 'pcomplete/cvs "pcmpl-cvs" "\
Completion rules for the `cvs' command." nil nil)
-
(register-definition-prefixes "pcmpl-cvs" '("pcmpl-cvs-"))
-;;;***
-;;;### (autoloads nil "pcmpl-gnu" "pcmpl-gnu.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-gnu.el
(autoload 'pcomplete/gzip "pcmpl-gnu" "\
Completion for `gzip'." nil nil)
-
(autoload 'pcomplete/bzip2 "pcmpl-gnu" "\
Completion for `bzip2'." nil nil)
-
(autoload 'pcomplete/make "pcmpl-gnu" "\
Completion for GNU `make'." nil nil)
-
(autoload 'pcomplete/tar "pcmpl-gnu" "\
Completion for the GNU tar utility." nil nil)
-
(autoload 'pcomplete/find "pcmpl-gnu" "\
Completion for the GNU find utility." nil nil)
-
(defalias 'pcomplete/gdb 'pcomplete/xargs)
+(register-definition-prefixes "pcmpl-gnu" '("pcmpl-gnu-" "pcomplete/find"))
-(register-definition-prefixes "pcmpl-gnu" '("pcmpl-gnu-"))
-
-;;;***
-;;;### (autoloads nil "pcmpl-linux" "pcmpl-linux.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-linux.el
(autoload 'pcomplete/kill "pcmpl-linux" "\
Completion for GNU/Linux `kill', using /proc filesystem." nil nil)
-
(autoload 'pcomplete/umount "pcmpl-linux" "\
Completion for GNU/Linux `umount'." nil nil)
-
(autoload 'pcomplete/mount "pcmpl-linux" "\
Completion for GNU/Linux `mount'." nil nil)
-
(register-definition-prefixes "pcmpl-linux" '("pcmpl-linux-" "pcomplete-pare-list"))
-;;;***
-;;;### (autoloads nil "pcmpl-rpm" "pcmpl-rpm.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-rpm.el
(autoload 'pcomplete/rpm "pcmpl-rpm" "\
Completion for the `rpm' command." nil nil)
-
(register-definition-prefixes "pcmpl-rpm" '("pcmpl-rpm-"))
-;;;***
-;;;### (autoloads nil "pcmpl-unix" "pcmpl-unix.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-unix.el
(autoload 'pcomplete/cd "pcmpl-unix" "\
Completion for `cd'." nil nil)
-
(defalias 'pcomplete/pushd 'pcomplete/cd)
-
(autoload 'pcomplete/rmdir "pcmpl-unix" "\
Completion for `rmdir'." nil nil)
-
(autoload 'pcomplete/rm "pcmpl-unix" "\
Completion for `rm'." nil nil)
-
(autoload 'pcomplete/xargs "pcmpl-unix" "\
Completion for `xargs'." nil nil)
-
(defalias 'pcomplete/time 'pcomplete/xargs)
-
(autoload 'pcomplete/which "pcmpl-unix" "\
Completion for `which'." nil nil)
-
(autoload 'pcomplete/chown "pcmpl-unix" "\
Completion for the `chown' command." nil nil)
-
(autoload 'pcomplete/chgrp "pcmpl-unix" "\
Completion for the `chgrp' command." nil nil)
-
(autoload 'pcomplete/ssh "pcmpl-unix" "\
Completion rules for the `ssh' command." nil nil)
-
(autoload 'pcomplete/scp "pcmpl-unix" "\
Completion rules for the `scp' command.
Includes files as well as host names followed by a colon." nil nil)
-
(autoload 'pcomplete/telnet "pcmpl-unix" nil nil nil)
-
(autoload 'pcomplete/rsh "pcmpl-unix" "\
Complete `rsh', which, after the user and hostname, is like xargs." nil nil)
-
(register-definition-prefixes "pcmpl-unix" '("pcmpl-" "pcomplete/"))
-;;;***
-;;;### (autoloads nil "pcmpl-x" "pcmpl-x.el" (0 0 0 0))
;;; Generated autoloads from pcmpl-x.el
(autoload 'pcomplete/tlmgr "pcmpl-x" "\
Completion for the `tlmgr' command." nil nil)
-
(autoload 'pcomplete/ack "pcmpl-x" "\
Completion for the `ack' command.
Start an argument with `-' to complete short options and `--' for
long options." nil nil)
-
(defalias 'pcomplete/ack-grep 'pcomplete/ack)
-
(autoload 'pcomplete/ag "pcmpl-x" "\
Completion for the `ag' command." nil nil)
-
(autoload 'pcomplete/bcc32 "pcmpl-x" "\
Completion function for Borland's C++ compiler." nil nil)
-
(defalias 'pcomplete/bcc 'pcomplete/bcc32)
-
(register-definition-prefixes "pcmpl-x" '("pcmpl-x-"))
-;;;***
-;;;### (autoloads nil "pcomplete" "pcomplete.el" (0 0 0 0))
;;; Generated autoloads from pcomplete.el
(autoload 'pcomplete "pcomplete" "\
@@ -25602,48 +23223,40 @@ Support extensible programmable completion.
To use this function, just bind the TAB key to it, or add it to your
completion functions list (it should occur fairly early in the list).
-\(fn &optional INTERACTIVELY)" t nil)
-
-(make-obsolete 'pcomplete '"use completion-at-point and pcomplete-completions-at-point" '"27.1")
-
+(fn &optional INTERACTIVELY)" t nil)
+(make-obsolete 'pcomplete '"use completion-at-point and pcomplete-completions-at-point" "27.1")
(autoload 'pcomplete-reverse "pcomplete" "\
If cycling completion is in use, cycle backwards." t nil)
-
(autoload 'pcomplete-expand-and-complete "pcomplete" "\
Expand the textual value of the current argument.
This will modify the current buffer." t nil)
-
(autoload 'pcomplete-continue "pcomplete" "\
Complete without reference to any cycling completions." t nil)
-
(autoload 'pcomplete-expand "pcomplete" "\
Expand the textual value of the current argument.
This will modify the current buffer." t nil)
-
(autoload 'pcomplete-help "pcomplete" "\
Display any help information relative to the current argument." t nil)
-
-(make-obsolete 'pcomplete-help '"use completion-help-at-point and pcomplete-completions-at-point" '"27.1")
-
+(make-obsolete 'pcomplete-help '"use completion-help-at-point and pcomplete-completions-at-point" "27.1")
(autoload 'pcomplete-list "pcomplete" "\
Show the list of possible completions for the current argument." t nil)
-
(autoload 'pcomplete-comint-setup "pcomplete" "\
Setup a comint buffer to use pcomplete.
COMPLETEF-SYM should be the symbol where the
dynamic-complete-functions are kept. For comint mode itself,
this is `comint-dynamic-complete-functions'.
-\(fn COMPLETEF-SYM)" nil nil)
-
+(fn COMPLETEF-SYM)" nil nil)
(autoload 'pcomplete-shell-setup "pcomplete" "\
Setup `shell-mode' to use pcomplete." nil nil)
-
(register-definition-prefixes "pcomplete" '("pcomplete-"))
-;;;***
-;;;### (autoloads nil "pcvs" "vc/pcvs.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/pconf.el
+
+(register-definition-prefixes "ede/pconf" '("ede-pconf-create-file-query"))
+
+
;;; Generated autoloads from vc/pcvs.el
(autoload 'cvs-checkout "pcvs" "\
@@ -25653,8 +23266,7 @@ and run `cvs-mode' on it.
With a prefix argument, prompt for cvs FLAGS to use.
-\(fn MODULES DIR FLAGS &optional ROOT)" t nil)
-
+(fn MODULES DIR FLAGS &optional ROOT)" t nil)
(autoload 'cvs-quickdir "pcvs" "\
Open a *cvs* buffer on DIR without running cvs.
With a prefix argument, prompt for a directory to use.
@@ -25663,8 +23275,7 @@ A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]),
Optional argument NOSHOW if non-nil means not to display the buffer.
FLAGS is ignored.
-\(fn DIR &optional FLAGS NOSHOW)" t nil)
-
+(fn DIR &optional FLAGS NOSHOW)" t nil)
(autoload 'cvs-examine "pcvs" "\
Run a `cvs -n update' in the specified DIRECTORY.
That is, check what needs to be done, but don't change the disc.
@@ -25674,8 +23285,7 @@ A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]),
prevents reuse of an existing *cvs* buffer.
Optional argument NOSHOW if non-nil means not to display the buffer.
-\(fn DIRECTORY FLAGS &optional NOSHOW)" t nil)
-
+(fn DIRECTORY FLAGS &optional NOSHOW)" t nil)
(autoload 'cvs-update "pcvs" "\
Run a `cvs update' in the current working DIRECTORY.
Feed the output to a *cvs* buffer and run `cvs-mode' on it.
@@ -25685,8 +23295,7 @@ A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]),
The prefix is also passed to `cvs-flags-query' to select the FLAGS
passed to cvs.
-\(fn DIRECTORY FLAGS)" t nil)
-
+(fn DIRECTORY FLAGS)" t nil)
(autoload 'cvs-status "pcvs" "\
Run a `cvs status' in the current working DIRECTORY.
Feed the output to a *cvs* buffer and run `cvs-mode' on it.
@@ -25695,80 +23304,61 @@ A prefix arg >8 (ex: \\[universal-argument] \\[universal-argument]),
prevents reuse of an existing *cvs* buffer.
Optional argument NOSHOW if non-nil means not to display the buffer.
-\(fn DIRECTORY FLAGS &optional NOSHOW)" t nil)
-
+(fn DIRECTORY FLAGS &optional NOSHOW)" t nil)
(defvar cvs-dired-action 'cvs-quickdir "\
The action to be performed when opening a CVS directory.
Sensible values are `cvs-examine', `cvs-status' and `cvs-quickdir'.")
-
(custom-autoload 'cvs-dired-action "pcvs" t)
-
(defvar cvs-dired-use-hook '(4) "\
Whether or not opening a CVS directory should run PCL-CVS.
A value of nil means never do it.
`always' means to always do it unless a prefix argument is given to the
command that prompted the opening of the directory.
Anything else means to do it only if the prefix arg is equal to this value.")
-
(custom-autoload 'cvs-dired-use-hook "pcvs" t)
-
(defun cvs-dired-noselect (dir) "\
Run `cvs-examine' if DIR is a CVS administrative directory.
The exact behavior is determined also by `cvs-dired-use-hook'." (when (stringp dir) (setq dir (directory-file-name dir)) (when (and (string= "CVS" (file-name-nondirectory dir)) (file-readable-p (expand-file-name "Entries" dir)) cvs-dired-use-hook (if (eq cvs-dired-use-hook 'always) (not current-prefix-arg) (equal current-prefix-arg cvs-dired-use-hook))) (save-excursion (funcall cvs-dired-action (file-name-directory dir) t t)))))
-
(register-definition-prefixes "pcvs" '("cvs-" "defun-cvs-mode"))
-;;;***
-;;;### (autoloads nil "pcvs-defs" "vc/pcvs-defs.el" (0 0 0 0))
;;; Generated autoloads from vc/pcvs-defs.el
(defvar cvs-global-menu (let ((m (make-sparse-keymap "PCL-CVS"))) (define-key m [status] `(menu-item ,(purecopy "Directory Status") cvs-status :help ,(purecopy "A more verbose status of a workarea"))) (define-key m [checkout] `(menu-item ,(purecopy "Checkout Module") cvs-checkout :help ,(purecopy "Check out a module from the repository"))) (define-key m [update] `(menu-item ,(purecopy "Update Directory") cvs-update :help ,(purecopy "Fetch updates from the repository"))) (define-key m [examine] `(menu-item ,(purecopy "Examine Directory") cvs-examine :help ,(purecopy "Examine the current state of a workarea"))) (fset 'cvs-global-menu m)) "\
Global menu used by PCL-CVS.")
-
(register-definition-prefixes "pcvs-defs" '("cvs-"))
-;;;***
-;;;### (autoloads nil "pcvs-info" "vc/pcvs-info.el" (0 0 0 0))
;;; Generated autoloads from vc/pcvs-info.el
(register-definition-prefixes "pcvs-info" '("cvs-"))
-;;;***
-;;;### (autoloads nil "pcvs-parse" "vc/pcvs-parse.el" (0 0 0 0))
;;; Generated autoloads from vc/pcvs-parse.el
(register-definition-prefixes "pcvs-parse" '("cvs-"))
-;;;***
-;;;### (autoloads nil "pcvs-util" "vc/pcvs-util.el" (0 0 0 0))
;;; Generated autoloads from vc/pcvs-util.el
(register-definition-prefixes "pcvs-util" '("cvs-"))
-;;;***
-;;;### (autoloads nil "perl-mode" "progmodes/perl-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/perl-mode.el
+
(put 'perl-indent-level 'safe-local-variable 'integerp)
(put 'perl-continued-statement-offset 'safe-local-variable 'integerp)
(put 'perl-continued-brace-offset 'safe-local-variable 'integerp)
(put 'perl-brace-offset 'safe-local-variable 'integerp)
(put 'perl-brace-imaginary-offset 'safe-local-variable 'integerp)
(put 'perl-label-offset 'safe-local-variable 'integerp)
-
(autoload 'perl-flymake "perl-mode" "\
Perl backend for Flymake.
Launch `perl-flymake-command' (which see) and pass to its
standard input the contents of the current buffer. The output of
this command is analyzed for error and warning messages.
-\(fn REPORT-FN &rest ARGS)" nil nil)
-
+(fn REPORT-FN &rest ARGS)" nil nil)
(autoload 'perl-mode "perl-mode" "\
Major mode for editing Perl code.
Expression and list commands understand all Perl brackets.
@@ -25817,13 +23407,15 @@ Various indentation styles: K&R BSD BLK GNU LW
Turning on Perl mode runs the normal hook `perl-mode-hook'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "perl-mode" '("indent-perl-exp" "mark-perl-function" "perl-"))
-;;;***
-;;;### (autoloads nil "picture" "textmodes/picture.el" (0 0 0 0))
+;;; Generated autoloads from pgtk-dnd.el
+
+(register-definition-prefixes "pgtk-dnd" '("pgtk-dnd-"))
+
+
;;; Generated autoloads from textmodes/picture.el
(autoload 'picture-mode "picture" "\
@@ -25896,29 +23488,20 @@ Entry to this mode calls the value of `picture-mode-hook' if non-nil.
Note that Picture mode commands will work outside of Picture mode, but
they are not by default assigned to keys." t nil)
-
(defalias 'edit-picture 'picture-mode)
-
(register-definition-prefixes "picture" '("picture-"))
-;;;***
-;;;### (autoloads nil "pinyin" "language/pinyin.el" (0 0 0 0))
;;; Generated autoloads from language/pinyin.el
(register-definition-prefixes "pinyin" '("pinyin-character-map"))
-;;;***
-;;;### (autoloads nil "pixel-fill" "textmodes/pixel-fill.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from textmodes/pixel-fill.el
(register-definition-prefixes "pixel-fill" '("pixel-fill-"))
-;;;***
-;;;### (autoloads nil "pixel-scroll" "pixel-scroll.el" (0 0 0 0))
;;; Generated autoloads from pixel-scroll.el
(defvar pixel-scroll-mode nil "\
@@ -25928,28 +23511,25 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `pixel-scroll-mode'.")
-
(custom-autoload 'pixel-scroll-mode "pixel-scroll" nil)
-
(autoload 'pixel-scroll-mode "pixel-scroll" "\
A minor mode to scroll text pixel-by-pixel.
-This is a minor mode. If called interactively, toggle the
-`Pixel-Scroll mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Pixel-Scroll mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='pixel-scroll-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar pixel-scroll-precision-mode nil "\
Non-nil if Pixel-Scroll-Precision mode is enabled.
See the `pixel-scroll-precision-mode' command
@@ -25957,66 +23537,60 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `pixel-scroll-precision-mode'.")
-
(custom-autoload 'pixel-scroll-precision-mode "pixel-scroll" nil)
-
(autoload 'pixel-scroll-precision-mode "pixel-scroll" "\
Toggle pixel scrolling.
+
When enabled, this minor mode allows to scroll the display
precisely, according to the turning of the mouse wheel.
-This is a minor mode. If called interactively, toggle the
+This is a global minor mode. If called interactively, toggle the
`Pixel-Scroll-Precision mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable the
-mode.
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='pixel-scroll-precision-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "pixel-scroll" '("pixel-"))
-;;;***
-;;;### (autoloads nil "plstore" "plstore.el" (0 0 0 0))
;;; Generated autoloads from plstore.el
(autoload 'plstore-open "plstore" "\
Create a plstore instance associated with FILE.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'plstore-mode "plstore" "\
Major mode for editing PLSTORE files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "plstore" '("plstore-"))
-;;;***
-;;;### (autoloads nil "po" "textmodes/po.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/pmake.el
+
+(register-definition-prefixes "ede/pmake" '("ede-pmake-"))
+
+
;;; Generated autoloads from textmodes/po.el
(autoload 'po-find-file-coding-system "po" "\
Return a (DECODING . ENCODING) pair, according to PO file's charset.
Called through `file-coding-system-alist', before the file is visited for real.
-\(fn ARG-LIST)" nil nil)
-
+(fn ARG-LIST)" nil nil)
(register-definition-prefixes "po" '("po-"))
-;;;***
-;;;### (autoloads nil "pong" "play/pong.el" (0 0 0 0))
;;; Generated autoloads from play/pong.el
(autoload 'pong "pong" "\
@@ -26027,25 +23601,19 @@ Move left and right bats and try to bounce the ball to your opponent.
pong-mode keybindings:\\<pong-mode-map>
\\{pong-mode-map}" t nil)
-
(register-definition-prefixes "pong" '("pong-"))
-;;;***
-;;;### (autoloads nil "pop3" "net/pop3.el" (0 0 0 0))
;;; Generated autoloads from net/pop3.el
(autoload 'pop3-movemail "pop3" "\
Transfer contents of a maildrop to the specified FILE.
Use streaming commands.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(register-definition-prefixes "pop3" '("pop3-"))
-;;;***
-;;;### (autoloads nil "pp" "emacs-lisp/pp.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/pp.el
(autoload 'pp-to-string "pp" "\
@@ -26053,11 +23621,9 @@ Return a string containing the pretty-printed representation of OBJECT.
OBJECT can be any Lisp object. Quoting characters are used as needed
to make output that `read' can handle, whenever this is possible.
-\(fn OBJECT)" nil nil)
-
+(fn OBJECT)" nil nil)
(autoload 'pp-buffer "pp" "\
Prettify the current buffer with printed representation of a Lisp object." t nil)
-
(autoload 'pp "pp" "\
Output the pretty-printed representation of OBJECT, any Lisp object.
Quoting characters are printed as needed to make output that `read'
@@ -26071,8 +23637,7 @@ and vectors. Bind `pp-use-max-width' to a non-nil value to do so.
Output stream is STREAM, or value of `standard-output' (which see).
-\(fn OBJECT &optional STREAM)" nil nil)
-
+(fn OBJECT &optional STREAM)" nil nil)
(autoload 'pp-display-expression "pp" "\
Prettify and display EXPRESSION in an appropriate way, depending on length.
If LISP, format with `pp-emacs-lisp-code'; use `pp' otherwise.
@@ -26080,47 +23645,39 @@ If LISP, format with `pp-emacs-lisp-code'; use `pp' otherwise.
If a temporary buffer is needed for representation, it will be named
after OUT-BUFFER-NAME.
-\(fn EXPRESSION OUT-BUFFER-NAME &optional LISP)" nil nil)
-
+(fn EXPRESSION OUT-BUFFER-NAME &optional LISP)" nil nil)
(autoload 'pp-eval-expression "pp" "\
Evaluate EXPRESSION and pretty-print its value.
Also add the value to the front of the list in the variable `values'.
-\(fn EXPRESSION)" t nil)
-
+(fn EXPRESSION)" t nil)
(autoload 'pp-macroexpand-expression "pp" "\
Macroexpand EXPRESSION and pretty-print its value.
-\(fn EXPRESSION)" t nil)
-
+(fn EXPRESSION)" t nil)
(autoload 'pp-eval-last-sexp "pp" "\
Run `pp-eval-expression' on sexp before point.
With ARG, pretty-print output into current buffer.
Ignores leading comment characters.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'pp-macroexpand-last-sexp "pp" "\
Run `pp-macroexpand-expression' on sexp before point.
With ARG, pretty-print output into current buffer.
Ignores leading comment characters.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'pp-emacs-lisp-code "pp" "\
Insert SEXP into the current buffer, formatted as Emacs Lisp code.
Use the `pp-max-width' variable to control the desired line length.
-\(fn SEXP)" nil nil)
-
+(fn SEXP)" nil nil)
(register-definition-prefixes "pp" '("pp-"))
-;;;***
-;;;### (autoloads nil "printing" "printing.el" (0 0 0 0))
;;; Generated autoloads from printing.el
-(push (purecopy '(printing 6 9 3)) package--builtin-versions)
+(push (purecopy '(printing 6 9 3)) package--builtin-versions)
(autoload 'pr-interface "printing" "\
Activate the printing interface buffer.
@@ -26128,8 +23685,7 @@ If BUFFER is nil, the current buffer is used for printing.
For more information, type \\[pr-interface-help].
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload 'pr-ps-directory-preview "printing" "\
Preview directory using ghostview.
@@ -26147,8 +23703,7 @@ file name.
See also documentation for `pr-list-directory'.
-\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
-
+(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
(autoload 'pr-ps-directory-using-ghostscript "printing" "\
Print directory using PostScript through ghostscript.
@@ -26166,8 +23721,7 @@ file name.
See also documentation for `pr-list-directory'.
-\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
-
+(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
(autoload 'pr-ps-directory-print "printing" "\
Print directory using PostScript printer.
@@ -26185,8 +23739,7 @@ file name.
See also documentation for `pr-list-directory'.
-\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
-
+(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
(autoload 'pr-ps-directory-ps-print "printing" "\
Print directory using PostScript printer or through ghostscript.
@@ -26206,8 +23759,7 @@ file name.
See also documentation for `pr-list-directory'.
-\(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
-
+(fn N-UP DIR FILE-REGEXP &optional FILENAME)" t nil)
(autoload 'pr-ps-buffer-preview "printing" "\
Preview buffer using ghostview.
@@ -26220,8 +23772,7 @@ argument FILENAME is treated as follows: if it's nil, save the image in a
temporary file. If FILENAME is a string, save the PostScript image in a file
with that name. If FILENAME is t, prompts for a file name.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-buffer-using-ghostscript "printing" "\
Print buffer using PostScript through ghostscript.
@@ -26234,8 +23785,7 @@ argument FILENAME is treated as follows: if it's nil, send the image to the
printer. If FILENAME is a string, save the PostScript image in a file with
that name. If FILENAME is t, prompts for a file name.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-buffer-print "printing" "\
Print buffer using PostScript printer.
@@ -26248,8 +23798,7 @@ argument FILENAME is treated as follows: if it's nil, send the image to the
printer. If FILENAME is a string, save the PostScript image in a file with
that name. If FILENAME is t, prompts for a file name.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-buffer-ps-print "printing" "\
Print buffer using PostScript printer or through ghostscript.
@@ -26264,64 +23813,55 @@ argument FILENAME is treated as follows: if it's nil, send the image to the
printer. If FILENAME is a string, save the PostScript image in a file with
that name. If FILENAME is t, prompts for a file name.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-region-preview "printing" "\
Preview region using ghostview.
See also `pr-ps-buffer-preview'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-region-using-ghostscript "printing" "\
Print region using PostScript through ghostscript.
See also `pr-ps-buffer-using-ghostscript'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-region-print "printing" "\
Print region using PostScript printer.
See also `pr-ps-buffer-print'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-region-ps-print "printing" "\
Print region using PostScript printer or through ghostscript.
See also `pr-ps-buffer-ps-print'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-mode-preview "printing" "\
Preview major mode using ghostview.
See also `pr-ps-buffer-preview'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-mode-using-ghostscript "printing" "\
Print major mode using PostScript through ghostscript.
See also `pr-ps-buffer-using-ghostscript'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-mode-print "printing" "\
Print major mode using PostScript printer.
See also `pr-ps-buffer-print'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-ps-mode-ps-print "printing" "\
Print major mode using PostScript or through ghostscript.
See also `pr-ps-buffer-ps-print'.
-\(fn N-UP &optional FILENAME)" t nil)
-
+(fn N-UP &optional FILENAME)" t nil)
(autoload 'pr-printify-directory "printing" "\
Replace nonprinting characters in directory with printable representations.
The printable representations use ^ (for ASCII control characters) or hex.
@@ -26335,18 +23875,15 @@ prompts for FILE(name)-REGEXP.
See also documentation for `pr-list-directory'.
-\(fn &optional DIR FILE-REGEXP)" t nil)
-
+(fn &optional DIR FILE-REGEXP)" t nil)
(autoload 'pr-printify-buffer "printing" "\
Replace nonprinting characters in buffer with printable representations.
The printable representations use ^ (for ASCII control characters) or hex.
The characters tab, linefeed, space, return and formfeed are not affected." t nil)
-
(autoload 'pr-printify-region "printing" "\
Replace nonprinting characters in region with printable representations.
The printable representations use ^ (for ASCII control characters) or hex.
The characters tab, linefeed, space, return and formfeed are not affected." t nil)
-
(autoload 'pr-txt-directory "printing" "\
Print directory using text printer.
@@ -26358,17 +23895,13 @@ prompts for FILE(name)-REGEXP.
See also documentation for `pr-list-directory'.
-\(fn &optional DIR FILE-REGEXP)" t nil)
-
+(fn &optional DIR FILE-REGEXP)" t nil)
(autoload 'pr-txt-buffer "printing" "\
Print buffer using text printer." t nil)
-
(autoload 'pr-txt-region "printing" "\
Print region using text printer." t nil)
-
(autoload 'pr-txt-mode "printing" "\
Print major mode using text printer." t nil)
-
(autoload 'pr-despool-preview "printing" "\
Preview spooled PostScript.
@@ -26380,8 +23913,7 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
save the image in a temporary file. If FILENAME is a string, save the
PostScript image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'pr-despool-using-ghostscript "printing" "\
Print spooled PostScript using ghostscript.
@@ -26393,8 +23925,7 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
send the image to the printer. If FILENAME is a string, save the PostScript
image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'pr-despool-print "printing" "\
Send the spooled PostScript to the printer.
@@ -26406,8 +23937,7 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
send the image to the printer. If FILENAME is a string, save the PostScript
image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'pr-despool-ps-print "printing" "\
Send the spooled PostScript to the printer or use ghostscript to print it.
@@ -26419,33 +23949,27 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
send the image to the printer. If FILENAME is a string, save the PostScript
image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'pr-ps-file-preview "printing" "\
Preview PostScript file FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'pr-ps-file-up-preview "printing" "\
Preview PostScript file FILENAME.
-\(fn N-UP IFILENAME &optional OFILENAME)" t nil)
-
+(fn N-UP IFILENAME &optional OFILENAME)" t nil)
(autoload 'pr-ps-file-using-ghostscript "printing" "\
Print PostScript file FILENAME using ghostscript.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'pr-ps-file-print "printing" "\
Print PostScript file FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'pr-ps-file-ps-print "printing" "\
Send PostScript file FILENAME to printer or use ghostscript to print it.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'pr-ps-file-up-ps-print "printing" "\
Process a PostScript file IFILENAME and send it to printer.
@@ -26462,11 +23986,9 @@ nil, send the image to the printer. If OFILENAME is a string, save the
PostScript image in a file with that name. If OFILENAME is t, prompts for a
file name.
-\(fn N-UP IFILENAME &optional OFILENAME)" t nil)
-
+(fn N-UP IFILENAME &optional OFILENAME)" t nil)
(autoload 'pr-toggle-file-duplex "printing" "\
Toggle duplex for PostScript file." t nil)
-
(autoload 'pr-toggle-file-tumble "printing" "\
Toggle tumble for PostScript file.
@@ -26474,22 +23996,16 @@ If tumble is off, produces a printing suitable for binding on the left or
right.
If tumble is on, produces a printing suitable for binding at the top or
bottom." t nil)
-
(autoload 'pr-toggle-file-landscape "printing" "\
Toggle landscape for PostScript file." t nil)
-
(autoload 'pr-toggle-ghostscript "printing" "\
Toggle printing using ghostscript." t nil)
-
(autoload 'pr-toggle-faces "printing" "\
Toggle printing with faces." t nil)
-
(autoload 'pr-toggle-spool "printing" "\
Toggle spooling." t nil)
-
(autoload 'pr-toggle-duplex "printing" "\
Toggle duplex." t nil)
-
(autoload 'pr-toggle-tumble "printing" "\
Toggle tumble.
@@ -26497,73 +24013,54 @@ If tumble is off, produces a printing suitable for binding on the left or
right.
If tumble is on, produces a printing suitable for binding at the top or
bottom." t nil)
-
(autoload 'pr-toggle-landscape "printing" "\
Toggle landscape." t nil)
-
(autoload 'pr-toggle-upside-down "printing" "\
Toggle upside-down." t nil)
-
(autoload 'pr-toggle-line "printing" "\
Toggle line number." t nil)
-
(autoload 'pr-toggle-zebra "printing" "\
Toggle zebra stripes." t nil)
-
(autoload 'pr-toggle-header "printing" "\
Toggle printing header." t nil)
-
(autoload 'pr-toggle-header-frame "printing" "\
Toggle printing header frame." t nil)
-
(autoload 'pr-toggle-lock "printing" "\
Toggle menu lock." t nil)
-
(autoload 'pr-toggle-region "printing" "\
Toggle whether the region is automagically detected." t nil)
-
(autoload 'pr-toggle-mode "printing" "\
Toggle auto mode." t nil)
-
(autoload 'pr-customize "printing" "\
Customization of the `printing' group.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'lpr-customize "printing" "\
Customization of the `lpr' group.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'pr-help "printing" "\
Help for the printing package.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'pr-ps-name "printing" "\
Interactively select a PostScript printer." t nil)
-
(autoload 'pr-txt-name "printing" "\
Interactively select a text printer." t nil)
-
(autoload 'pr-ps-utility "printing" "\
Interactively select a PostScript utility." t nil)
-
(autoload 'pr-show-ps-setup "printing" "\
Show current ps-print settings.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'pr-show-pr-setup "printing" "\
Show current printing settings.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'pr-show-lpr-setup "printing" "\
Show current lpr settings.
-\(fn &rest IGNORE)" t nil)
-
+(fn &rest IGNORE)" t nil)
(autoload 'pr-ps-fast-fire "printing" "\
Fast fire function for PostScript printing.
@@ -26625,8 +24122,7 @@ zero and the argument SELECT is treated as follows:
Note that this command always behaves as if `pr-auto-region' and `pr-auto-mode'
are both set to t.
-\(fn N-UP &optional SELECT)" t nil)
-
+(fn N-UP &optional SELECT)" t nil)
(autoload 'pr-txt-fast-fire "printing" "\
Fast fire function for text printing.
@@ -26651,33 +24147,31 @@ Noninteractively, the argument SELECT-PRINTER is treated as follows:
Note that this command always behaves as if `pr-auto-region' and `pr-auto-mode'
are both set to t.
-\(fn &optional SELECT-PRINTER)" t nil)
-
+(fn &optional SELECT-PRINTER)" t nil)
(register-definition-prefixes "printing" '("lpr-setup" "pr-"))
-;;;***
-;;;### (autoloads nil "proced" "proced.el" (0 0 0 0))
;;; Generated autoloads from proced.el
(autoload 'proced "proced" "\
Generate a listing of UNIX system processes.
\\<proced-mode-map>
-If invoked with optional ARG, do not select the window displaying
-the process information.
+If invoked with optional non-negative ARG, do not select the
+window displaying the process information.
+
+If `proced-show-remote-processes' is non-nil or the command is
+invoked with a negative ARG `\\[universal-argument] \\[negative-argument]', and `default-directory'
+points to a remote host, the system processes of that host are shown.
This function runs the normal hook `proced-post-display-hook'.
See `proced-mode' for a description of features available in
Proced buffers.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "proced" '("proced-"))
-;;;***
-;;;### (autoloads nil "profiler" "profiler.el" (0 0 0 0))
;;; Generated autoloads from profiler.el
(autoload 'profiler-start "profiler" "\
@@ -26690,31 +24184,80 @@ If MODE is `mem' or `cpu+mem', start profiler that samples CPU
if SIGPROF is not supported, or is unreliable, or is not sampling
at a high enough frequency.
-\(fn MODE)" t nil)
-
+(fn MODE)" t nil)
(autoload 'profiler-find-profile "profiler" "\
Open profile FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'profiler-find-profile-other-window "profiler" "\
Open profile FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'profiler-find-profile-other-frame "profiler" "\
Open profile FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(register-definition-prefixes "profiler" '("profiler-"))
-;;;***
-;;;### (autoloads nil "project" "progmodes/project.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/proj.el
+
+(register-definition-prefixes "ede/proj" '("ede-proj-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-archive.el
+
+(register-definition-prefixes "ede/proj-archive" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-aux.el
+
+(register-definition-prefixes "ede/proj-aux" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-comp.el
+
+(register-definition-prefixes "ede/proj-comp" '("ede-" "proj-comp-insert-variable-once"))
+
+
+;;; Generated autoloads from cedet/ede/proj-elisp.el
+
+(register-definition-prefixes "ede/proj-elisp" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-info.el
+
+(register-definition-prefixes "ede/proj-info" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-misc.el
+
+(register-definition-prefixes "ede/proj-misc" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-obj.el
+
+(register-definition-prefixes "ede/proj-obj" '("ede-"))
+
+
+;;; Generated autoloads from cedet/ede/proj-prog.el
+
+(register-definition-prefixes "ede/proj-prog" '("ede-proj-target-makefile-program"))
+
+
+;;; Generated autoloads from cedet/ede/proj-scheme.el
+
+(register-definition-prefixes "ede/proj-scheme" '("ede-proj-target-scheme"))
+
+
+;;; Generated autoloads from cedet/ede/proj-shared.el
+
+(register-definition-prefixes "ede/proj-shared" '("ede-"))
+
+
;;; Generated autoloads from progmodes/project.el
-(push (purecopy '(project 0 8 1)) package--builtin-versions)
+(push (purecopy '(project 0 8 1)) package--builtin-versions)
(autoload 'project-current "project" "\
Return the project instance in DIRECTORY, defaulting to `default-directory'.
@@ -26732,12 +24275,10 @@ ignored (per `project-ignores').
See the doc string of `project-find-functions' for the general form
of the project instance object.
-\(fn &optional MAYBE-PROMPT DIRECTORY)" nil nil)
-
+(fn &optional MAYBE-PROMPT DIRECTORY)" nil nil)
(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map "!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) (define-key map "f" 'project-find-file) (define-key map "F" 'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) (define-key map "s" 'project-shell) (define-key map "d" 'project-find-dir) (define-key map "D" 'project-dired) (define-key map "v" 'project-vc-dir) (define-key map "c" 'project-compile) (define-key map "e" 'project-eshell) (define-key map "k" 'project-kill-buffers) (define-key map "p" 'project-switch-project) (define-key map "g" 'project-find-regexp) (define-key map "G" 'project-or-external-find-regexp) (define-key map "r" 'project-query-replace-regexp) (define-key map "x" 'project-execute-extended-command) map) "\
Keymap for project commands.")
(define-key ctl-x-map "p" project-prefix-map)
-
(autoload 'project-other-window-command "project" "\
Run project command, displaying resultant buffer in another window.
@@ -26746,7 +24287,6 @@ The following commands are available:
\\{project-prefix-map}
\\{project-other-window-map}" t nil)
(define-key ctl-x-4-map "p" #'project-other-window-command)
-
(autoload 'project-other-frame-command "project" "\
Run project command, displaying resultant buffer in another frame.
@@ -26755,16 +24295,13 @@ The following commands are available:
\\{project-prefix-map}
\\{project-other-frame-map}" t nil)
(define-key ctl-x-5-map "p" #'project-other-frame-command)
-
(autoload 'project-other-tab-command "project" "\
Run project command, displaying resultant buffer in a new tab.
The following commands are available:
\\{project-prefix-map}" t nil)
-
(when (bound-and-true-p tab-prefix-map) (define-key tab-prefix-map "p" #'project-other-tab-command))
-
(autoload 'project-find-regexp "project" "\
Find all matches for REGEXP in the current project's roots.
With \\[universal-argument] prefix, you can specify the directory
@@ -26774,15 +24311,13 @@ e.g. entering `ch' is equivalent to `*.[ch]'. As whitespace
triggers completion when entering a pattern, including it
requires quoting, e.g. `\\[quoted-insert]<space>'.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'project-or-external-find-regexp "project" "\
Find all matches for REGEXP in the project roots or external roots.
With \\[universal-argument] prefix, you can specify the file name
pattern to search for.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'project-find-file "project" "\
Visit a file (with completion) in the current project.
@@ -26793,8 +24328,7 @@ If INCLUDE-ALL is non-nil, or with prefix argument when called
interactively, include all files under the project root, except
for VCS directories listed in `vc-directory-exclusion-list'.
-\(fn &optional INCLUDE-ALL)" t nil)
-
+(fn &optional INCLUDE-ALL)" t nil)
(autoload 'project-or-external-find-file "project" "\
Visit a file (with completion) in the current project or external roots.
@@ -26805,62 +24339,52 @@ If INCLUDE-ALL is non-nil, or with prefix argument when called
interactively, include all files under the project root, except
for VCS directories listed in `vc-directory-exclusion-list'.
-\(fn &optional INCLUDE-ALL)" t nil)
-
+(fn &optional INCLUDE-ALL)" t nil)
(autoload 'project-find-dir "project" "\
Start Dired in a directory inside the current project." t nil)
-
(autoload 'project-dired "project" "\
Start Dired in the current project's root." t nil)
-
(autoload 'project-vc-dir "project" "\
Run VC-Dir in the current project's root." t nil)
-
(autoload 'project-shell "project" "\
Start an inferior shell in the current project's root directory.
If a buffer already exists for running a shell in the project's root,
switch to it. Otherwise, create a new shell buffer.
With \\[universal-argument] prefix arg, create a new inferior shell buffer even
if one already exists." t nil)
-
(autoload 'project-eshell "project" "\
Start Eshell in the current project's root directory.
If a buffer already exists for running Eshell in the project's root,
switch to it. Otherwise, create a new Eshell buffer.
With \\[universal-argument] prefix arg, create a new Eshell buffer even
if one already exists." t nil)
-
(autoload 'project-async-shell-command "project" "\
Run `async-shell-command' in the current project's root directory." t nil)
-
(function-put 'project-async-shell-command 'interactive-only 'async-shell-command)
-
(autoload 'project-shell-command "project" "\
Run `shell-command' in the current project's root directory." t nil)
-
(function-put 'project-shell-command 'interactive-only 'shell-command)
-
(autoload 'project-search "project" "\
Search for REGEXP in all the files of the project.
Stops when a match is found.
To continue searching for the next match, use the
command \\[fileloop-continue].
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'project-query-replace-regexp "project" "\
Query-replace REGEXP in all the files of the project.
Stops when a match is found and prompts for whether to replace it.
+At that prompt, the user must type a character saying what to do
+with the match. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
If you exit the `query-replace', you can later continue the
`query-replace' loop using the command \\[fileloop-continue].
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'project-compile "project" "\
Run `compile' in the project root." t nil)
-
(function-put 'project-compile 'interactive-only 'compile)
-
(autoload 'project-switch-to-buffer "project" "\
Display buffer BUFFER-OR-NAME in the selected window.
When called interactively, prompts for a buffer belonging to the
@@ -26868,8 +24392,7 @@ current project. Two buffers belong to the same project if their
project instances, as reported by `project-current' in each
buffer, are identical.
-\(fn BUFFER-OR-NAME)" t nil)
-
+(fn BUFFER-OR-NAME)" t nil)
(autoload 'project-display-buffer "project" "\
Display BUFFER-OR-NAME in some window, without selecting it.
When called interactively, prompts for a buffer belonging to the
@@ -26880,8 +24403,7 @@ buffer, are identical.
This function uses `display-buffer' as a subroutine, which see
for how it is determined where the buffer will be displayed.
-\(fn BUFFER-OR-NAME)" t nil)
-
+(fn BUFFER-OR-NAME)" t nil)
(autoload 'project-display-buffer-other-frame "project" "\
Display BUFFER-OR-NAME preferably in another frame.
When called interactively, prompts for a buffer belonging to the
@@ -26893,8 +24415,7 @@ This function uses `display-buffer-other-frame' as a subroutine,
which see for how it is determined where the buffer will be
displayed.
-\(fn BUFFER-OR-NAME)" t nil)
-
+(fn BUFFER-OR-NAME)" t nil)
(autoload 'project-kill-buffers "project" "\
Kill the buffers belonging to the current project.
Two buffers belong to the same project if their project
@@ -26905,30 +24426,26 @@ is non-nil, the command will not ask the user for confirmation.
NO-CONFIRM is always nil when the command is invoked
interactively.
-\(fn &optional NO-CONFIRM)" t nil)
+Also see the `project-kill-buffers-display-buffer-list' variable.
+(fn &optional NO-CONFIRM)" t nil)
(autoload 'project-remember-project "project" "\
Add project PR to the front of the project list.
Save the result in `project-list-file' if the list of projects
has changed, and NO-WRITE is nil.
-\(fn PR &optional NO-WRITE)" nil nil)
-
+(fn PR &optional NO-WRITE)" nil nil)
(autoload 'project-forget-project "project" "\
Remove directory PROJECT-ROOT from the project list.
PROJECT-ROOT is the root directory of a known project listed in
the project list.
-\(fn PROJECT-ROOT)" t nil)
-
+(fn PROJECT-ROOT)" t nil)
(autoload 'project-known-project-roots "project" "\
Return the list of root directories of all known projects." nil nil)
-
(autoload 'project-execute-extended-command "project" "\
Execute an extended command in project root." t nil)
-
(function-put 'project-execute-extended-command 'interactive-only 'command-execute)
-
(autoload 'project-switch-project "project" "\
\"Switch\" to another project by running an Emacs command.
The available commands are presented as a dispatch menu
@@ -26937,13 +24454,15 @@ made from `project-switch-commands'.
When called in a program, it will use the project corresponding
to directory DIR.
-\(fn DIR)" t nil)
-
+(fn DIR)" t nil)
(register-definition-prefixes "project" '("project-"))
-;;;***
-;;;### (autoloads nil "prolog" "progmodes/prolog.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/project-am.el
+
+(register-definition-prefixes "ede/project-am" '("project-am-"))
+
+
;;; Generated autoloads from progmodes/prolog.el
(autoload 'prolog-mode "prolog" "\
@@ -26960,48 +24479,37 @@ To find out what version of Prolog mode you are running, enter
Commands:
\\{prolog-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'mercury-mode "prolog" "\
Major mode for editing Mercury programs.
Actually this is just customized `prolog-mode'.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'run-prolog "prolog" "\
Run an inferior Prolog process, input and output via buffer *prolog*.
With prefix argument ARG, restart the Prolog process if running before.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "prolog" '("mercury-mode-map" "prolog-"))
-;;;***
-;;;### (autoloads nil "ps-bdf" "ps-bdf.el" (0 0 0 0))
;;; Generated autoloads from ps-bdf.el
(defvar bdf-directory-list (if (memq system-type '(ms-dos windows-nt)) (list (expand-file-name "fonts/bdf" installation-directory)) '("/usr/local/share/emacs/fonts/bdf")) "\
List of directories to search for `BDF' font files.
The default value is (\"/usr/local/share/emacs/fonts/bdf\").")
-
(custom-autoload 'bdf-directory-list "ps-bdf" t)
-
(register-definition-prefixes "ps-bdf" '("bdf-"))
-;;;***
-;;;### (autoloads nil "ps-def" "ps-def.el" (0 0 0 0))
;;; Generated autoloads from ps-def.el
(register-definition-prefixes "ps-def" '("ps-"))
-;;;***
-;;;### (autoloads nil "ps-mode" "progmodes/ps-mode.el" (0 0 0 0))
;;; Generated autoloads from progmodes/ps-mode.el
-(push (purecopy '(ps-mode 1 1 9)) package--builtin-versions)
+(push (purecopy '(ps-mode 1 1 9)) package--builtin-versions)
(autoload 'ps-mode "ps-mode" "\
Major mode for editing PostScript with GNU Emacs.
@@ -27040,29 +24548,27 @@ point to the corresponding spot in the PostScript window, if input
to the interpreter was sent from that window.
Typing \\<ps-run-mode-map>\\[ps-run-goto-error] when the cursor is at the number has the same effect.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "ps-mode" '("ps-"))
-;;;***
-;;;### (autoloads nil "ps-print" "ps-print.el" (0 0 0 0))
+;;; Generated autoloads from ps-mule.el
+
+(register-definition-prefixes "ps-mule" '("ps-mule-"))
+
+
;;; Generated autoloads from ps-print.el
-(push (purecopy '(ps-print 7 3 5)) package--builtin-versions)
+(push (purecopy '(ps-print 7 3 5)) package--builtin-versions)
(defvar ps-page-dimensions-database (purecopy (list (list 'a4 (/ (* 72 21.0) 2.54) (/ (* 72 29.7) 2.54) "A4") (list 'a3 (/ (* 72 29.7) 2.54) (/ (* 72 42.0) 2.54) "A3") (list 'letter (* 72 8.5) (* 72 11.0) "Letter") (list 'legal (* 72 8.5) (* 72 14.0) "Legal") (list 'letter-small (* 72 7.68) (* 72 10.16) "LetterSmall") (list 'tabloid (* 72 11.0) (* 72 17.0) "Tabloid") (list 'ledger (* 72 17.0) (* 72 11.0) "Ledger") (list 'statement (* 72 5.5) (* 72 8.5) "Statement") (list 'executive (* 72 7.5) (* 72 10.0) "Executive") (list 'a4small (* 72 7.47) (* 72 10.85) "A4Small") (list 'b4 (* 72 10.125) (* 72 14.33) "B4") (list 'b5 (* 72 7.16) (* 72 10.125) "B5") '(addresslarge 236.0 99.0 "AddressLarge") '(addresssmall 236.0 68.0 "AddressSmall") '(cuthanging13 90.0 222.0 "CutHanging13") '(cuthanging15 90.0 114.0 "CutHanging15") '(diskette 181.0 136.0 "Diskette") '(eurofilefolder 139.0 112.0 "EuropeanFilefolder") '(eurofoldernarrow 526.0 107.0 "EuroFolderNarrow") '(eurofolderwide 526.0 136.0 "EuroFolderWide") '(euronamebadge 189.0 108.0 "EuroNameBadge") '(euronamebadgelarge 223.0 136.0 "EuroNameBadgeLarge") '(filefolder 230.0 37.0 "FileFolder") '(jewelry 76.0 136.0 "Jewelry") '(mediabadge 180.0 136.0 "MediaBadge") '(multipurpose 126.0 68.0 "MultiPurpose") '(retaillabel 90.0 104.0 "RetailLabel") '(shipping 271.0 136.0 "Shipping") '(slide35mm 26.0 104.0 "Slide35mm") '(spine8mm 187.0 26.0 "Spine8mm") '(topcoated 425.19685 136.0 "TopCoatedPaper") '(topcoatedpaper 396.0 136.0 "TopcoatedPaper150") '(vhsface 205.0 127.0 "VHSFace") '(vhsspine 400.0 50.0 "VHSSpine") '(zipdisk 156.0 136.0 "ZipDisk"))) "\
List associating a symbolic paper type to its width, height and doc media.
See `ps-paper-type'.")
-
(custom-autoload 'ps-page-dimensions-database "ps-print" t)
-
(defvar ps-paper-type 'letter "\
Specify the size of paper to format for.
Should be one of the paper types defined in `ps-page-dimensions-database', for
example `letter', `legal' or `a4'.")
-
(custom-autoload 'ps-paper-type "ps-print" t)
-
(defvar ps-print-color-p (fboundp 'x-color-values) "\
Specify how buffer's text color is printed.
@@ -27076,12 +24582,9 @@ Valid values are:
See also `ps-black-white-faces'.
Any other value is treated as t.")
-
(custom-autoload 'ps-print-color-p "ps-print" t)
-
(autoload 'ps-print-customize "ps-print" "\
Customization of ps-print group." t nil)
-
(autoload 'ps-print-buffer "ps-print" "\
Generate and print a PostScript image of the buffer.
@@ -27093,37 +24596,32 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
send the image to the printer. If FILENAME is a string, save the PostScript
image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'ps-print-buffer-with-faces "ps-print" "\
Generate and print a PostScript image of the buffer.
Like `ps-print-buffer', but includes font, color, and underline information in
the generated image. This command works only if you are using a window system,
so it has a way to determine color values.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'ps-print-region "ps-print" "\
Generate and print a PostScript image of the region.
Like `ps-print-buffer', but prints just the current region.
-\(fn FROM TO &optional FILENAME)" t nil)
-
+(fn FROM TO &optional FILENAME)" t nil)
(autoload 'ps-print-region-with-faces "ps-print" "\
Generate and print a PostScript image of the region.
Like `ps-print-region', but includes font, color, and underline information in
the generated image. This command works only if you are using a window system,
so it has a way to determine color values.
-\(fn FROM TO &optional FILENAME)" t nil)
-
+(fn FROM TO &optional FILENAME)" t nil)
(autoload 'ps-spool-buffer "ps-print" "\
Generate and spool a PostScript image of the buffer.
Like `ps-print-buffer' except that the PostScript image is saved in a local
buffer to be sent to the printer later.
Use the command `ps-despool' to send the spooled images to the printer." t nil)
-
(autoload 'ps-spool-buffer-with-faces "ps-print" "\
Generate and spool a PostScript image of the buffer.
Like the command `ps-spool-buffer', but includes font, color, and underline
@@ -27131,15 +24629,13 @@ information in the generated image. This command works only if you are using
a window system, so it has a way to determine color values.
Use the command `ps-despool' to send the spooled images to the printer." t nil)
-
(autoload 'ps-spool-region "ps-print" "\
Generate a PostScript image of the region and spool locally.
Like `ps-spool-buffer', but spools just the current region.
Use the command `ps-despool' to send the spooled images to the printer.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'ps-spool-region-with-faces "ps-print" "\
Generate a PostScript image of the region and spool locally.
Like `ps-spool-region', but includes font, color, and underline information in
@@ -27148,8 +24644,7 @@ so it has a way to determine color values.
Use the command `ps-despool' to send the spooled images to the printer.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'ps-despool "ps-print" "\
Send the spooled PostScript to the printer.
@@ -27161,29 +24656,24 @@ Noninteractively, the argument FILENAME is treated as follows: if it is nil,
send the image to the printer. If FILENAME is a string, save the PostScript
image in a file with that name.
-\(fn &optional FILENAME)" t nil)
-
+(fn &optional FILENAME)" t nil)
(autoload 'ps-line-lengths "ps-print" "\
Display the correspondence between a line length and a font size.
Done using the current ps-print setup.
Try: pr -t file | awk \\='{printf \"%3d %s
\", length($0), $0}\\=' | sort -r | head" t nil)
-
(autoload 'ps-nb-pages-buffer "ps-print" "\
Display number of pages to print this buffer, for various font heights.
The table depends on the current ps-print setup.
-\(fn NB-LINES)" t nil)
-
+(fn NB-LINES)" t nil)
(autoload 'ps-nb-pages-region "ps-print" "\
Display number of pages to print the region, for various font heights.
The table depends on the current ps-print setup.
-\(fn NB-LINES)" t nil)
-
+(fn NB-LINES)" t nil)
(autoload 'ps-setup "ps-print" "\
Return the current PostScript-generation setup." nil nil)
-
(autoload 'ps-extend-face-list "ps-print" "\
Extend face in ALIST-SYM.
@@ -27197,8 +24687,7 @@ The elements in FACE-EXTENSION-LIST are like those for `ps-extend-face'.
See `ps-extend-face' for documentation.
-\(fn FACE-EXTENSION-LIST &optional MERGE-P ALIST-SYM)" nil nil)
-
+(fn FACE-EXTENSION-LIST &optional MERGE-P ALIST-SYM)" nil nil)
(autoload 'ps-extend-face "ps-print" "\
Extend face in ALIST-SYM.
@@ -27229,56 +24718,43 @@ EXTENSION is one of the following symbols:
If EXTENSION is any other symbol, it is ignored.
-\(fn FACE-EXTENSION &optional MERGE-P ALIST-SYM)" nil nil)
-
+(fn FACE-EXTENSION &optional MERGE-P ALIST-SYM)" nil nil)
(register-definition-prefixes "ps-print" '("ps-"))
-;;;***
-;;;### (autoloads nil "ps-samp" "ps-samp.el" (0 0 0 0))
;;; Generated autoloads from ps-samp.el
(register-definition-prefixes "ps-samp" '("ps-"))
-;;;***
-;;;### (autoloads nil "pulse" "cedet/pulse.el" (0 0 0 0))
;;; Generated autoloads from cedet/pulse.el
-(push (purecopy '(pulse 1 0)) package--builtin-versions)
+(push (purecopy '(pulse 1 0)) package--builtin-versions)
(autoload 'pulse-momentary-highlight-one-line "pulse" "\
Highlight the line around POINT, unhighlighting before next command.
If POINT is nil or missing, the current point is used instead.
Optional argument FACE specifies the face to do the highlighting.
-\(fn &optional POINT FACE)" nil nil)
-
+(fn &optional POINT FACE)" nil nil)
(autoload 'pulse-momentary-highlight-region "pulse" "\
Highlight between START and END, unhighlighting before next command.
Optional argument FACE specifies the face to do the highlighting.
-\(fn START END &optional FACE)" nil nil)
-
+(fn START END &optional FACE)" nil nil)
(register-definition-prefixes "pulse" '("pulse-"))
-;;;***
-;;;### (autoloads nil "puny" "net/puny.el" (0 0 0 0))
;;; Generated autoloads from net/puny.el
(register-definition-prefixes "puny" '("puny-"))
-;;;***
-;;;### (autoloads nil "python" "progmodes/python.el" (0 0 0 0))
;;; Generated autoloads from progmodes/python.el
-(push (purecopy '(python 0 28)) package--builtin-versions)
+(push (purecopy '(python 0 28)) package--builtin-versions)
(add-to-list 'auto-mode-alist (cons (purecopy "\\.py[iw]?\\'") 'python-mode))
-
(add-to-list 'interpreter-mode-alist (cons (purecopy "python[0-9.]*") 'python-mode))
-
(autoload 'run-python "python" "\
Run an inferior Python process.
@@ -27297,20 +24773,21 @@ Runs the hook `inferior-python-mode-hook' after
`comint-mode-hook' is run. (Type \\[describe-mode] in the
process buffer for a list of commands.)
-\(fn &optional CMD DEDICATED SHOW)" t nil)
-
+(fn &optional CMD DEDICATED SHOW)" t nil)
(autoload 'python-mode "python" "\
Major mode for editing Python files.
\\{python-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "python" '("inferior-python-mode" "python-" "run-python-internal"))
-;;;***
-;;;### (autoloads nil "qp" "mail/qp.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/wisent/python.el
+
+(register-definition-prefixes "semantic/wisent/python" '("semantic-" "wisent-python-"))
+
+
;;; Generated autoloads from mail/qp.el
(autoload 'quoted-printable-decode-region "qp" "\
@@ -27325,18 +24802,14 @@ The CODING-SYSTEM argument is a historical hangover and is deprecated.
QP encodes raw bytes and should be decoded into raw bytes. Decoding
them into characters should be done separately.
-\(fn FROM TO &optional CODING-SYSTEM)" t nil)
-
+(fn FROM TO &optional CODING-SYSTEM)" t nil)
(register-definition-prefixes "qp" '("quoted-printable-"))
-;;;***
-;;;### (autoloads nil "quail" "international/quail.el" (0 0 0 0))
;;; Generated autoloads from international/quail.el
(autoload 'quail-title "quail" "\
Return the title of the current Quail package." nil nil)
-
(autoload 'quail-use-package "quail" "\
Start using Quail package PACKAGE-NAME.
The remaining arguments are LIBRARIES to be loaded before using the package.
@@ -27344,8 +24817,7 @@ The remaining arguments are LIBRARIES to be loaded before using the package.
This activates input method defined by PACKAGE-NAME by running
`quail-activate', which see.
-\(fn PACKAGE-NAME &rest LIBRARIES)" nil nil)
-
+(fn PACKAGE-NAME &rest LIBRARIES)" nil nil)
(autoload 'quail-define-package "quail" "\
Define NAME as a new Quail package for input LANGUAGE.
TITLE is a string to be displayed at mode-line to indicate this package.
@@ -27364,8 +24836,8 @@ If it is nil, the current key is shown.
DOCSTRING is the documentation string of this package. The command
`describe-input-method' shows this string while replacing the form
-\\=\\<VAR> in the string by the value of VAR. That value should be a
-string. For instance, the form \\=\\<quail-translation-docstring> is
+\\=\\=\\=\\<VAR> in the string by the value of VAR. That value should be a
+string. For instance, the form \\=\\=\\=\\<quail-translation-docstring> is
replaced by a description about how to select a translation from a
list of candidates.
@@ -27426,8 +24898,7 @@ If SIMPLE is non-nil, then we do not alter the meanings of
commands such as \\[forward-char], \\[backward-char], \\[next-line], \\[previous-line] and \\[indent-for-tab-command]; they are treated as
non-Quail commands.
-\(fn NAME LANGUAGE TITLE &optional GUIDANCE DOCSTRING TRANSLATION-KEYS FORGET-LAST-SELECTION DETERMINISTIC KBD-TRANSLATE SHOW-LAYOUT CREATE-DECODE-MAP MAXIMUM-SHORTEST OVERLAY-PLIST UPDATE-TRANSLATION-FUNCTION CONVERSION-KEYS SIMPLE)" nil nil)
-
+(fn NAME LANGUAGE TITLE &optional GUIDANCE DOCSTRING TRANSLATION-KEYS FORGET-LAST-SELECTION DETERMINISTIC KBD-TRANSLATE SHOW-LAYOUT CREATE-DECODE-MAP MAXIMUM-SHORTEST OVERLAY-PLIST UPDATE-TRANSLATION-FUNCTION CONVERSION-KEYS SIMPLE)" nil nil)
(autoload 'quail-set-keyboard-layout "quail" "\
Set the current keyboard layout to the same as keyboard KBD-TYPE.
@@ -27437,16 +24908,14 @@ standard layout defined in `quail-keyboard-layout-standard'. This
function tells Quail system the layout of your keyboard so that what
you type is correctly handled.
-\(fn KBD-TYPE)" t nil)
-
+(fn KBD-TYPE)" t nil)
(autoload 'quail-show-keyboard-layout "quail" "\
Show the physical layout of the keyboard type KEYBOARD-TYPE.
The variable `quail-keyboard-layout-type' holds the currently selected
keyboard type.
-\(fn &optional KEYBOARD-TYPE)" t nil)
-
+(fn &optional KEYBOARD-TYPE)" t nil)
(autoload 'quail-define-rules "quail" "\
Define translation rules of the current Quail package.
Each argument is a list of KEY and TRANSLATION.
@@ -27480,8 +24949,7 @@ the following annotation types are supported.
no-decode-map --- the value non-nil means that decoding map is not
generated for the following translations.
-\(fn &rest RULES)" nil t)
-
+(fn &rest RULES)" nil t)
(autoload 'quail-install-map "quail" "\
Install the Quail map MAP in the current Quail package.
@@ -27490,8 +24958,7 @@ which to install MAP.
The installed map can be referred by the function `quail-map'.
-\(fn MAP &optional NAME)" nil nil)
-
+(fn MAP &optional NAME)" nil nil)
(autoload 'quail-install-decode-map "quail" "\
Install the Quail decode map DECODE-MAP in the current Quail package.
@@ -27500,8 +24967,7 @@ which to install MAP.
The installed decode map can be referred by the function `quail-decode-map'.
-\(fn DECODE-MAP &optional NAME)" nil nil)
-
+(fn DECODE-MAP &optional NAME)" nil nil)
(autoload 'quail-defrule "quail" "\
Add one translation rule, KEY to TRANSLATION, in the current Quail package.
KEY is a string meaning a sequence of keystrokes to be translated.
@@ -27527,8 +24993,7 @@ current Quail package.
Optional 4th argument APPEND, if non-nil, appends TRANSLATION
to the current translations for KEY instead of replacing them.
-\(fn KEY TRANSLATION &optional NAME APPEND)" nil nil)
-
+(fn KEY TRANSLATION &optional NAME APPEND)" nil nil)
(autoload 'quail-defrule-internal "quail" "\
Define KEY as TRANS in a Quail map MAP.
@@ -27540,8 +25005,7 @@ Optional 5th arg DECODE-MAP is a Quail decode map.
Optional 6th arg PROPS is a property list annotating TRANS. See the
function `quail-define-rules' for the detail.
-\(fn KEY TRANS MAP &optional APPEND DECODE-MAP PROPS)" nil nil)
-
+(fn KEY TRANS MAP &optional APPEND DECODE-MAP PROPS)" nil nil)
(autoload 'quail-update-leim-list-file "quail" "\
Update entries for Quail packages in `LEIM' list file in directory DIRNAME.
DIRNAME is a directory containing Emacs input methods;
@@ -27555,120 +25019,10 @@ When called from a program, the remaining arguments are additional
directory names to search for Quail packages under `quail' subdirectory
of each directory.
-\(fn DIRNAME &rest DIRNAMES)" t nil)
-
+(fn DIRNAME &rest DIRNAMES)" t nil)
(register-definition-prefixes "quail" '("quail-"))
-;;;***
-
-;;;### (autoloads nil "quail/ethiopic" "leim/quail/ethiopic.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from leim/quail/ethiopic.el
-
-(register-definition-prefixes "quail/ethiopic" '("ethio-select-a-translation"))
-
-;;;***
-;;;### (autoloads nil "quail/hangul" "leim/quail/hangul.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from leim/quail/hangul.el
-
-(autoload 'hangul-input-method-activate "quail/hangul" "\
-Activate Hangul input method INPUT-METHOD.
-FUNC is a function to handle input key.
-HELP-TEXT is a text set in `hangul-input-method-help-text'.
-
-\(fn INPUT-METHOD FUNC HELP-TEXT &rest ARGS)" nil nil)
-
-(register-definition-prefixes "quail/hangul" '("alphabetp" "hangul" "notzerop"))
-
-;;;***
-
-;;;### (autoloads nil "quail/indian" "leim/quail/indian.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from leim/quail/indian.el
-
-(register-definition-prefixes "quail/indian" '("indian-mlm-mozhi-u" "inscript-" "quail-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/ipa" "leim/quail/ipa.el" (0 0 0 0))
-;;; Generated autoloads from leim/quail/ipa.el
-
-(register-definition-prefixes "quail/ipa" '("ipa-x-sampa-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/japanese" "leim/quail/japanese.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from leim/quail/japanese.el
-
-(register-definition-prefixes "quail/japanese" '("quail-japanese-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/lao" "leim/quail/lao.el" (0 0 0 0))
-;;; Generated autoloads from leim/quail/lao.el
-
-(register-definition-prefixes "quail/lao" '("lao-" "quail-lao-update-translation"))
-
-;;;***
-
-;;;### (autoloads nil "quail/lrt" "leim/quail/lrt.el" (0 0 0 0))
-;;; Generated autoloads from leim/quail/lrt.el
-
-(register-definition-prefixes "quail/lrt" '("quail-lrt-update-translation"))
-
-;;;***
-
-;;;### (autoloads nil "quail/sisheng" "leim/quail/sisheng.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from leim/quail/sisheng.el
-
-(register-definition-prefixes "quail/sisheng" '("quail-make-sisheng-rules" "sisheng-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/thai" "leim/quail/thai.el" (0 0 0 0))
-;;; Generated autoloads from leim/quail/thai.el
-
-(register-definition-prefixes "quail/thai" '("thai-generate-quail-map"))
-
-;;;***
-
-;;;### (autoloads nil "quail/tibetan" "leim/quail/tibetan.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from leim/quail/tibetan.el
-
-(register-definition-prefixes "quail/tibetan" '("quail-tib" "tibetan-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/uni-input" "leim/quail/uni-input.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from leim/quail/uni-input.el
-
-(autoload 'ucs-input-activate "quail/uni-input" "\
-Activate UCS input method.
-With ARG, activate UCS input method if and only if ARG is positive.
-
-While this input method is active, the variable
-`input-method-function' is bound to the function `ucs-input-method'.
-
-\(fn &optional ARG)" nil nil)
-
-(register-definition-prefixes "quail/uni-input" '("ucs-input-"))
-
-;;;***
-
-;;;### (autoloads nil "quail/viqr" "leim/quail/viqr.el" (0 0 0 0))
-;;; Generated autoloads from leim/quail/viqr.el
-
-(register-definition-prefixes "quail/viqr" '("viet-quail-define-rules"))
-
-;;;***
-
-;;;### (autoloads nil "quickurl" "net/quickurl.el" (0 0 0 0))
;;; Generated autoloads from net/quickurl.el
(defconst quickurl-reread-hook-postfix "\n;; Local Variables:\n;; eval: (progn (require 'quickurl) (add-hook 'write-file-functions (lambda () (quickurl-read) nil) nil t))\n;; End:\n" "\
@@ -27681,7 +25035,6 @@ To make use of this do something like:
(setq quickurl-postfix quickurl-reread-hook-postfix)
in your init file (after loading/requiring quickurl).")
-
(autoload 'quickurl "quickurl" "\
Insert a URL based on LOOKUP.
@@ -27689,21 +25042,18 @@ If not supplied LOOKUP is taken to be the word at point in the current
buffer, this default action can be modified via
`quickurl-grab-lookup-function'.
-\(fn &optional LOOKUP)" t nil)
-
+(fn &optional LOOKUP)" t nil)
(autoload 'quickurl-ask "quickurl" "\
Insert a URL, with `completing-read' prompt, based on LOOKUP.
-\(fn LOOKUP)" t nil)
-
+(fn LOOKUP)" t nil)
(autoload 'quickurl-add-url "quickurl" "\
Allow the user to interactively add a new URL associated with WORD.
See `quickurl-grab-url' for details on how the default word/URL combination
is decided.
-\(fn WORD URL COMMENT)" t nil)
-
+(fn WORD URL COMMENT)" t nil)
(autoload 'quickurl-browse-url "quickurl" "\
Browse the URL associated with LOOKUP.
@@ -27711,16 +25061,13 @@ If not supplied LOOKUP is taken to be the word at point in the
current buffer, this default action can be modified via
`quickurl-grab-lookup-function'.
-\(fn &optional LOOKUP)" t nil)
-
+(fn &optional LOOKUP)" t nil)
(autoload 'quickurl-browse-url-ask "quickurl" "\
Browse the URL, with `completing-read' prompt, associated with LOOKUP.
-\(fn LOOKUP)" t nil)
-
+(fn LOOKUP)" t nil)
(autoload 'quickurl-edit-urls "quickurl" "\
Pull `quickurl-url-file' into a buffer for hand editing." t nil)
-
(autoload 'quickurl-list-mode "quickurl" "\
A mode for browsing the quickurl URL list.
@@ -27728,24 +25075,22 @@ The key bindings for `quickurl-list-mode' are:
\\{quickurl-list-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'quickurl-list "quickurl" "\
Display `quickurl-list' as a formatted list using `quickurl-list-mode'." t nil)
-
(register-definition-prefixes "quickurl" '("quickurl-"))
-;;;***
-;;;### (autoloads nil "radix-tree" "emacs-lisp/radix-tree.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/radix-tree.el
(register-definition-prefixes "radix-tree" '("radix-tree-"))
-;;;***
-;;;### (autoloads nil "rcirc" "net/rcirc.el" (0 0 0 0))
+;;; Generated autoloads from emacs-lisp/range.el
+
+(register-definition-prefixes "range" '("range-"))
+
+
;;; Generated autoloads from net/rcirc.el
(autoload 'rcirc "rcirc" "\
@@ -27755,10 +25100,8 @@ Do not connect to a server if it is already connected.
If ARG is non-nil, instead prompt for connection parameters.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(defalias 'irc 'rcirc)
-
(autoload 'rcirc-connect "rcirc" "\
Connect to SERVER.
The arguments PORT, NICK, USER-NAME, FULL-NAME, PASSWORD,
@@ -27766,8 +25109,7 @@ ENCRYPTION, CERTFP, SERVER-ALIAS are interpreted as in
`rcirc-server-alist'. STARTUP-CHANNELS is a list of channels
that are joined after authentication.
-\(fn SERVER &optional PORT NICK USER-NAME FULL-NAME STARTUP-CHANNELS PASSWORD ENCRYPTION CERTFP SERVER-ALIAS)" nil nil)
-
+(fn SERVER &optional PORT NICK USER-NAME FULL-NAME STARTUP-CHANNELS PASSWORD ENCRYPTION CERTFP SERVER-ALIAS)" nil nil)
(defvar rcirc-track-minor-mode nil "\
Non-nil if Rcirc-Track minor mode is enabled.
See the `rcirc-track-minor-mode' command
@@ -27775,38 +25117,32 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `rcirc-track-minor-mode'.")
-
(custom-autoload 'rcirc-track-minor-mode "rcirc" nil)
-
(autoload 'rcirc-track-minor-mode "rcirc" "\
Global minor mode for tracking activity in rcirc buffers.
-This is a minor mode. If called interactively, toggle the
-`Rcirc-Track minor mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Rcirc-Track minor mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='rcirc-track-minor-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "rcirc" '("rcirc-" "with-rcirc-"))
-;;;***
-;;;### (autoloads nil "re-builder" "emacs-lisp/re-builder.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/re-builder.el
(defalias 'regexp-builder 're-builder)
-
(autoload 're-builder "re-builder" "\
Construct a regexp interactively.
This command makes the current buffer the \"target\" buffer of
@@ -27820,14 +25156,17 @@ Case-sensitivity can be toggled with \\[reb-toggle-case]. The
regexp builder supports three different forms of input which can
be set with \\[reb-change-syntax]. More options and details are
provided in the Commentary section of this library." t nil)
-
(register-definition-prefixes "re-builder" '("re-builder-unload-function" "reb-"))
-;;;***
-;;;### (autoloads nil "recentf" "recentf.el" (0 0 0 0))
;;; Generated autoloads from recentf.el
+(autoload 'recentf-open "recentf" "\
+Prompt for FILE in `recentf-list' and visit it.
+Enable `recentf-mode' if it isn't already.
+
+(fn FILE)" t nil)
+(defalias 'recentf 'recentf-open)
(defvar recentf-mode nil "\
Non-nil if Recentf mode is enabled.
See the `recentf-mode' command
@@ -27835,25 +25174,16 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `recentf-mode'.")
-
(custom-autoload 'recentf-mode "recentf" nil)
-
(autoload 'recentf-mode "recentf" "\
-Toggle \"Open Recent\" menu (Recentf mode).
-
-This is a minor mode. If called interactively, toggle the `Recentf
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+Toggle keeping track of opened files (Recentf mode).
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='recentf-mode)'.
+This mode maintains a list of recently opened files and makes it
+easy to visit them. The recent files list is automatically saved
+across Emacs sessions.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+You can use `recentf-open' or `recentf-open-files' to visit
+files.
When Recentf mode is enabled, a \"Open Recent\" submenu is
displayed in the \"File\" menu, containing a list of files that
@@ -27864,15 +25194,26 @@ to a file, and killing a buffer is counted as \"operating\" on
the file. If instead you want to prioritize files that appear in
buffers you switch to a lot, you can say something like the following:
- (add-hook 'buffer-list-update-hook 'recentf-track-opened-file)
+ (add-hook \\='buffer-list-update-hook #\\='recentf-track-opened-file)
+
+This is a global minor mode. If called interactively, toggle the
+`Recentf mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='recentf-mode)'.
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "recentf" '("recentf-"))
-;;;***
-;;;### (autoloads nil "rect" "rect.el" (0 0 0 0))
;;; Generated autoloads from rect.el
(autoload 'delete-rectangle "rect" "\
@@ -27885,8 +25226,7 @@ When called from a program the rectangle's corners are START and END.
With a prefix (or a FILL) argument, also fill lines where nothing has
to be deleted.
-\(fn START END &optional FILL)" t nil)
-
+(fn START END &optional FILL)" t nil)
(autoload 'delete-extract-rectangle "rect" "\
Delete the contents of the rectangle with corners at START and END.
Return it as a list of strings, one for each line of the rectangle.
@@ -27895,14 +25235,12 @@ When called from a program the rectangle's corners are START and END.
With an optional FILL argument, also fill lines where nothing has to be
deleted.
-\(fn START END &optional FILL)" nil nil)
-
+(fn START END &optional FILL)" nil nil)
(autoload 'extract-rectangle "rect" "\
Return the contents of the rectangle with corners at START and END.
Return it as a list of strings, one for each line of the rectangle.
-\(fn START END)" nil nil)
-
+(fn START END)" nil nil)
(autoload 'kill-rectangle "rect" "\
Delete the region-rectangle and save it as the last killed one.
@@ -27915,19 +25253,16 @@ deleted.
If the buffer is read-only, Emacs will beep and refrain from deleting
the rectangle, but put it in `killed-rectangle' anyway. This means that
you can use this command to copy text from a read-only buffer.
-\(If the variable `kill-read-only-ok' is non-nil, then this won't
+(If the variable `kill-read-only-ok' is non-nil, then this won't
even beep.)
-\(fn START END &optional FILL)" t nil)
-
+(fn START END &optional FILL)" t nil)
(autoload 'copy-rectangle-as-kill "rect" "\
Copy the region-rectangle and save it as the last killed one.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'yank-rectangle "rect" "\
Yank the last killed rectangle with upper left corner at point." t nil)
-
(autoload 'insert-rectangle "rect" "\
Insert text of RECTANGLE with upper left corner at point.
RECTANGLE's first line is inserted at point, its second
@@ -27936,8 +25271,7 @@ RECTANGLE should be a list of strings.
After this command, the mark is at the upper left corner
and point is at the lower right corner.
-\(fn RECTANGLE)" nil nil)
-
+(fn RECTANGLE)" nil nil)
(autoload 'open-rectangle "rect" "\
Blank out the region-rectangle, shifting text right.
@@ -27948,10 +25282,8 @@ When called from a program the rectangle's corners are START and END.
With a prefix (or a FILL) argument, fill with blanks even if there is
no text on the right side of the rectangle.
-\(fn START END &optional FILL)" t nil)
-
+(fn START END &optional FILL)" t nil)
(defalias 'close-rectangle 'delete-whitespace-rectangle)
-
(autoload 'delete-whitespace-rectangle "rect" "\
Delete all whitespace following a specified column in each line.
The left edge of the rectangle specifies the position in each line
@@ -27961,8 +25293,7 @@ rectangle, all contiguous whitespace starting at that column is deleted.
When called from a program the rectangle's corners are START and END.
With a prefix (or a FILL) argument, also fill too short lines.
-\(fn START END &optional FILL)" t nil)
-
+(fn START END &optional FILL)" t nil)
(autoload 'string-rectangle "rect" "\
Replace rectangle contents with STRING on each line.
The length of STRING need not be the same as the rectangle width.
@@ -27973,10 +25304,8 @@ the minibuffer.
Called from a program, takes three args; START, END and STRING.
-\(fn START END STRING)" t nil)
-
+(fn START END STRING)" t nil)
(defalias 'replace-rectangle 'string-rectangle)
-
(autoload 'string-insert-rectangle "rect" "\
Insert STRING on each line of region-rectangle, shifting text right.
@@ -27984,8 +25313,7 @@ When called from a program, the rectangle's corners are START and END.
The left edge of the rectangle specifies the column for insertion.
This command does not delete or overwrite any existing text.
-\(fn START END STRING)" t nil)
-
+(fn START END STRING)" t nil)
(autoload 'clear-rectangle "rect" "\
Blank out the region-rectangle.
The text previously in the region is overwritten with blanks.
@@ -27994,8 +25322,7 @@ When called from a program the rectangle's corners are START and END.
With a prefix (or a FILL) argument, also fill with blanks the parts of the
rectangle which were empty.
-\(fn START END &optional FILL)" t nil)
-
+(fn START END &optional FILL)" t nil)
(autoload 'rectangle-number-lines "rect" "\
Insert numbers in front of the region-rectangle.
@@ -28004,68 +25331,46 @@ counting. FORMAT, if non-nil, should be a format string to pass
to `format' along with the line count. When called interactively
with a prefix argument, prompt for START-AT and FORMAT.
-\(fn START END START-AT &optional FORMAT)" t nil)
-
+(fn START END START-AT &optional FORMAT)" t nil)
(autoload 'rectangle-mark-mode "rect" "\
Toggle the region as rectangular.
+Activates the region if it's inactive and Transient Mark mode is
+on. Only lasts until the region is next deactivated.
+
This is a minor mode. If called interactively, toggle the
`Rectangle-Mark mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `rectangle-mark-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Activates the region if it's inactive and Transient Mark mode is
-on. Only lasts until the region is next deactivated.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "rect" '("apply-on-rectangle" "clear-rectangle-line" "delete-" "extract-rectangle-" "killed-rectangle" "ope" "rectangle-" "spaces-string" "string-rectangle-"))
-;;;***
-;;;### (autoloads nil "refbib" "textmodes/refbib.el" (0 0 0 0))
;;; Generated autoloads from textmodes/refbib.el
(register-definition-prefixes "refbib" '("r2b-"))
-;;;***
-;;;### (autoloads nil "refer" "textmodes/refer.el" (0 0 0 0))
;;; Generated autoloads from textmodes/refer.el
(register-definition-prefixes "refer" '("refer-"))
-;;;***
-;;;### (autoloads nil "refill" "textmodes/refill.el" (0 0 0 0))
;;; Generated autoloads from textmodes/refill.el
(autoload 'refill-mode "refill" "\
Toggle automatic refilling (Refill mode).
-This is a minor mode. If called interactively, toggle the `Refill
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `refill-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Refill mode is a buffer-local minor mode. When enabled, the
current paragraph is refilled as you edit. Self-inserting
characters only cause refilling if they would cause
@@ -28073,39 +25378,40 @@ auto-filling.
For true \"word wrap\" behavior, use `visual-line-mode' instead.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Refill mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `refill-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "refill" '("refill-"))
-;;;***
-;;;### (autoloads nil "reftex" "textmodes/reftex.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/analyze/refs.el
+
+(register-definition-prefixes "semantic/analyze/refs" '("semantic-"))
+
+
;;; Generated autoloads from textmodes/reftex.el
+
(autoload 'reftex-citation "reftex-cite" nil t)
(autoload 'reftex-all-document-files "reftex-parse")
(autoload 'reftex-isearch-minor-mode "reftex-global" nil t)
(autoload 'reftex-index-phrases-mode "reftex-index" nil t)
-
(autoload 'turn-on-reftex "reftex" "\
Turn on RefTeX mode." nil nil)
-
(autoload 'reftex-mode "reftex" "\
Minor mode with distinct support for \\label, \\ref and \\cite in LaTeX.
-This is a minor mode. If called interactively, toggle the `Reftex
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `reftex-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
\\<reftex-mode-map>A Table of Contents of the entire (multifile) document with browsing
capabilities is available with `\\[reftex-toc]'.
@@ -28134,30 +25440,81 @@ on the menu bar.
------------------------------------------------------------------------------
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Reftex mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `reftex-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'reftex-reset-scanning-information "reftex" "\
Reset the symbols containing information from buffer scanning.
This enforces rescanning the buffer on next use." nil nil)
-
(register-definition-prefixes "reftex" '("reftex-"))
-;;;***
-;;;### (autoloads nil "reftex-vars" "textmodes/reftex-vars.el" (0
-;;;;;; 0 0 0))
+;;; Generated autoloads from textmodes/reftex-auc.el
+
+(register-definition-prefixes "reftex-auc" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-cite.el
+
+(register-definition-prefixes "reftex-cite" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-dcr.el
+
+(register-definition-prefixes "reftex-dcr" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-global.el
+
+(register-definition-prefixes "reftex-global" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-index.el
+
+(register-definition-prefixes "reftex-index" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-parse.el
+
+(register-definition-prefixes "reftex-parse" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-ref.el
+
+(register-definition-prefixes "reftex-ref" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-sel.el
+
+(register-definition-prefixes "reftex-sel" '("reftex-"))
+
+
+;;; Generated autoloads from textmodes/reftex-toc.el
+
+(register-definition-prefixes "reftex-toc" '("reftex-"))
+
+
;;; Generated autoloads from textmodes/reftex-vars.el
+
(put 'reftex-vref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x))))
(put 'reftex-fref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x))))
(put 'reftex-level-indent 'safe-local-variable 'integerp)
(put 'reftex-guess-label-type 'safe-local-variable (lambda (x) (memq x '(nil t))))
-
(register-definition-prefixes "reftex-vars" '("reftex-"))
-;;;***
-;;;### (autoloads nil "regexp-opt" "emacs-lisp/regexp-opt.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/regexp-opt.el
(autoload 'regexp-opt "regexp-opt" "\
@@ -28207,34 +25564,26 @@ usually more efficient than that of a simplified version:
(mapconcat \\='regexp-quote strings \"\\\\|\")
(cdr parens))))
-\(fn STRINGS &optional PAREN)" nil nil)
-
+(fn STRINGS &optional PAREN)" nil nil)
(autoload 'regexp-opt-depth "regexp-opt" "\
Return the depth of REGEXP.
This means the number of non-shy regexp grouping constructs
-\(parenthesized expressions) in REGEXP.
-
-\(fn REGEXP)" nil nil)
+(parenthesized expressions) in REGEXP.
+(fn REGEXP)" nil nil)
(register-definition-prefixes "regexp-opt" '("regexp-opt-"))
-;;;***
-;;;### (autoloads nil "regi" "emacs-lisp/regi.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/regi.el
(register-definition-prefixes "regi" '("regi-"))
-;;;***
-;;;### (autoloads nil "registry" "registry.el" (0 0 0 0))
;;; Generated autoloads from registry.el
(register-definition-prefixes "registry" '("registry-"))
-;;;***
-;;;### (autoloads nil "remember" "textmodes/remember.el" (0 0 0 0))
;;; Generated autoloads from textmodes/remember.el
(autoload 'remember "remember" "\
@@ -28244,20 +25593,16 @@ or nil to bring up a blank `remember-buffer'.
With a prefix or a visible region, use the region as INITIAL.
-\(fn &optional INITIAL)" t nil)
-
+(fn &optional INITIAL)" t nil)
(autoload 'remember-other-frame "remember" "\
Call `remember' in another frame.
-\(fn &optional INITIAL)" t nil)
-
+(fn &optional INITIAL)" t nil)
(autoload 'remember-clipboard "remember" "\
Remember the contents of the current clipboard.
Most useful for remembering things from other applications." t nil)
-
(autoload 'remember-diary-extract-entries "remember" "\
Extract diary entries from the region based on `remember-diary-regexp'." nil nil)
-
(autoload 'remember-notes "remember" "\
Return the notes buffer, creating it if needed, and maybe switch to it.
This buffer is for notes that you want to preserve across Emacs sessions.
@@ -28279,13 +25624,10 @@ Set `initial-buffer-choice' to `remember-notes' to visit your notes buffer
when Emacs starts. Set `remember-notes-buffer-name' to \"*scratch*\"
to turn the *scratch* buffer into your notes buffer.
-\(fn &optional SWITCH-TO)" t nil)
-
+(fn &optional SWITCH-TO)" t nil)
(register-definition-prefixes "remember" '("remember-"))
-;;;***
-;;;### (autoloads nil "repeat" "repeat.el" (0 0 0 0))
;;; Generated autoloads from repeat.el
(autoload 'repeat "repeat" "\
@@ -28303,13 +25645,11 @@ sequence. This behavior can be modified by the global variable
\"most recently executed command\" shall be read as \"most
recently executed command not bound to an input event\".
-\(fn REPEAT-ARG)" t nil)
-
+(fn REPEAT-ARG)" t nil)
(defvar repeat-map nil "\
The value of the repeating transient map for the next command.
A command called from the map can set it again to the same map when
the map can't be set on the command symbol property `repeat-map'.")
-
(defvar repeat-mode nil "\
Non-nil if Repeat mode is enabled.
See the `repeat-mode' command
@@ -28317,36 +25657,32 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `repeat-mode'.")
-
(custom-autoload 'repeat-mode "repeat" nil)
-
(autoload 'repeat-mode "repeat" "\
Toggle Repeat mode.
+
When Repeat mode is enabled, and the command symbol has the property named
`repeat-map', this map is activated temporarily for the next command.
See `describe-repeat-maps' for a list of all repeatable commands.
-This is a minor mode. If called interactively, toggle the `Repeat
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Repeat mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='repeat-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "repeat" '("describe-repeat-maps" "repeat-"))
-;;;***
-;;;### (autoloads nil "reporter" "mail/reporter.el" (0 0 0 0))
;;; Generated autoloads from mail/reporter.el
(autoload 'reporter-submit-bug-report "reporter" "\
@@ -28370,16 +25706,13 @@ is non-nil.
This function does not send a message; it uses the given information
to initialize a message, which the user can then edit and finally send
-\(or decline to send). The variable `mail-user-agent' controls which
+(or decline to send). The variable `mail-user-agent' controls which
mail-sending package is used for editing and sending the message.
-\(fn ADDRESS PKGNAME VARLIST &optional PRE-HOOKS POST-HOOKS SALUTATION)" nil nil)
-
+(fn ADDRESS PKGNAME VARLIST &optional PRE-HOOKS POST-HOOKS SALUTATION)" nil nil)
(register-definition-prefixes "reporter" '("reporter-"))
-;;;***
-;;;### (autoloads nil "reposition" "reposition.el" (0 0 0 0))
;;; Generated autoloads from reposition.el
(autoload 'reposition-window "reposition" "\
@@ -28403,39 +25736,35 @@ first comment line visible (if point is in a comment).
If INTERACTIVE is non-nil, as it is interactively,
report errors as appropriate for this kind of usage.
-\(fn &optional ARG INTERACTIVE)" t nil)
-
+(fn &optional ARG INTERACTIVE)" t nil)
(register-definition-prefixes "reposition" '("repos-count-screen-lines"))
-;;;***
-;;;### (autoloads nil "reveal" "reveal.el" (0 0 0 0))
;;; Generated autoloads from reveal.el
(autoload 'reveal-mode "reveal" "\
Toggle uncloaking of invisible text near point (Reveal mode).
-This is a minor mode. If called interactively, toggle the `Reveal
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `reveal-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Reveal mode is a buffer-local minor mode. When enabled, it
reveals invisible text around point.
Also see the `reveal-auto-hide' variable.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Reveal mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `reveal-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar global-reveal-mode nil "\
Non-nil if Global Reveal mode is enabled.
See the `global-reveal-mode' command
@@ -28443,101 +25772,78 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-reveal-mode'.")
-
(custom-autoload 'global-reveal-mode "reveal" nil)
-
(autoload 'global-reveal-mode "reveal" "\
Toggle Reveal mode in all buffers (Global Reveal mode).
+
Reveal mode renders invisible text around point visible again.
-This is a minor mode. If called interactively, toggle the `Global
-Reveal mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Global Reveal mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='global-reveal-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "reveal" '("reveal-"))
-;;;***
-;;;### (autoloads nil "rfc1843" "international/rfc1843.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from international/rfc1843.el
(register-definition-prefixes "rfc1843" '("rfc1843-"))
-;;;***
-;;;### (autoloads nil "rfc2045" "mail/rfc2045.el" (0 0 0 0))
;;; Generated autoloads from mail/rfc2045.el
(register-definition-prefixes "rfc2045" '("rfc2045-encode-string"))
-;;;***
-;;;### (autoloads nil "rfc2047" "mail/rfc2047.el" (0 0 0 0))
;;; Generated autoloads from mail/rfc2047.el
(register-definition-prefixes "rfc2047" '("rfc2047-"))
-;;;***
-;;;### (autoloads nil "rfc2104" "net/rfc2104.el" (0 0 0 0))
;;; Generated autoloads from net/rfc2104.el
(register-definition-prefixes "rfc2104" '("rfc2104-"))
-;;;***
-;;;### (autoloads nil "rfc2231" "mail/rfc2231.el" (0 0 0 0))
;;; Generated autoloads from mail/rfc2231.el
(register-definition-prefixes "rfc2231" '("rfc2231-"))
-;;;***
-;;;### (autoloads nil "rfc6068" "mail/rfc6068.el" (0 0 0 0))
;;; Generated autoloads from mail/rfc6068.el
(register-definition-prefixes "rfc6068" '("rfc6068-"))
-;;;***
-;;;### (autoloads nil "rfc822" "mail/rfc822.el" (0 0 0 0))
;;; Generated autoloads from mail/rfc822.el
(register-definition-prefixes "rfc822" '("rfc822-"))
-;;;***
-;;;### (autoloads nil "ring" "emacs-lisp/ring.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/ring.el
(autoload 'ring-p "ring" "\
Return t if X is a ring; nil otherwise.
-\(fn X)" nil nil)
-
+(fn X)" nil nil)
(autoload 'make-ring "ring" "\
Make a ring that can contain SIZE elements.
-\(fn SIZE)" nil nil)
-
+(fn SIZE)" nil nil)
(register-definition-prefixes "ring" '("ring-"))
-;;;***
-;;;### (autoloads nil "rlogin" "net/rlogin.el" (0 0 0 0))
;;; Generated autoloads from net/rlogin.el
(autoload 'rlogin "rlogin" "\
@@ -28548,7 +25854,7 @@ other arguments for `rlogin'.
Input is sent line-at-a-time to the remote connection.
Communication with the remote host is recorded in a buffer `*rlogin-HOST*'
-\(or `*rlogin-USER@HOST*' if the remote username differs).
+(or `*rlogin-USER@HOST*' if the remote username differs).
If a prefix argument is given and the buffer `*rlogin-HOST*' already exists,
a new buffer with a different connection will be made.
@@ -28577,32 +25883,24 @@ If you wish to change directory tracking styles during a session, use the
function `rlogin-directory-tracking-mode' rather than simply setting the
variable.
-\(fn INPUT-ARGS &optional BUFFER)" t nil)
-
+(fn INPUT-ARGS &optional BUFFER)" t nil)
(register-definition-prefixes "rlogin" '("rlogin-"))
-;;;***
-;;;### (autoloads nil "rmail" "mail/rmail.el" (0 0 0 0))
;;; Generated autoloads from mail/rmail.el
(defvar rmail-file-name (purecopy "~/RMAIL") "\
Name of user's primary mail file.")
-
(custom-autoload 'rmail-file-name "rmail" t)
-
(defcustom rmail-spool-directory (purecopy (cond ((file-exists-p "/var/mail") "/var/mail/") ((file-exists-p "/var/spool/mail") "/var/spool/mail/") ((memq system-type '(hpux usg-unix-v)) "/usr/mail/") (t "/usr/spool/mail/"))) "\
Name of directory used by system mailer for delivering new mail.
Its name should end with a slash." :initialize #'custom-initialize-delay :type 'directory :group 'rmail)
-
(custom-autoload 'rmail-spool-directory "rmail" t)
-
(autoload 'rmail-movemail-variant-p "rmail" "\
Return t if the current movemail variant is any of VARIANTS.
Currently known variants are `emacs' and `mailutils'.
-\(fn &rest VARIANTS)" nil nil)
-
+(fn &rest VARIANTS)" nil nil)
(defvar rmail-user-mail-address-regexp nil "\
Regexp matching user mail addresses.
If non-nil, this variable is used to identify the correspondent
@@ -28616,80 +25914,59 @@ sent by you under different user names.
Then it should be a regexp matching your mail addresses.
Setting this variable has an effect only before reading a mail.")
-
(custom-autoload 'rmail-user-mail-address-regexp "rmail" t)
-
-(define-obsolete-variable-alias 'rmail-dont-reply-to-names 'mail-dont-reply-to-names "24.1")
-
+(define-obsolete-variable-alias 'rmail-dont-reply-to-names 'mail-dont-reply-to-names "\
+24.1")
(defvar rmail-default-dont-reply-to-names nil "\
Regexp specifying part of the default value of `mail-dont-reply-to-names'.
This is used when the user does not set `mail-dont-reply-to-names'
explicitly.")
-
-(make-obsolete-variable 'rmail-default-dont-reply-to-names 'mail-dont-reply-to-names "24.1")
-
+(make-obsolete-variable 'rmail-default-dont-reply-to-names 'mail-dont-reply-to-names "\
+24.1")
(defvar rmail-ignored-headers (purecopy (concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:" "\\|^status:\\|^received:\\|^x400-originator:\\|^x400-recipients:" "\\|^x400-received:\\|^x400-mts-identifier:\\|^x400-content-type:" "\\|^\\(resent-\\|\\)message-id:\\|^summary-line:\\|^resent-date:" "\\|^nntp-posting-host:\\|^path:\\|^x-char.*:\\|^x-face:\\|^face:" "\\|^x-mailer:\\|^delivered-to:\\|^lines:" "\\|^content-transfer-encoding:\\|^x-coding-system:" "\\|^return-path:\\|^errors-to:\\|^return-receipt-to:" "\\|^precedence:\\|^mime-version:" "\\|^list-owner:\\|^list-help:\\|^list-post:\\|^list-subscribe:" "\\|^list-id:\\|^list-unsubscribe:\\|^list-archive:" "\\|^content-length:\\|^nntp-posting-date:\\|^user-agent" "\\|^importance:\\|^envelope-to:\\|^delivery-date\\|^openpgp:" "\\|^mbox-line:\\|^cancel-lock:" "\\|^DomainKey-Signature:\\|^dkim-signature:" "\\|^ARC-.*:" "\\|^Received-SPF:" "\\|^Authentication-Results:" "\\|^resent-face:\\|^resent-x.*:\\|^resent-organization:\\|^resent-openpgp:" "\\|^x-.*:")) "\
Regexp to match header fields that Rmail should normally hide.
-\(See also `rmail-nonignored-headers', which overrides this regexp.)
+(See also `rmail-nonignored-headers', which overrides this regexp.)
This variable is used for reformatting the message header,
which normally happens once for each message,
when you view the message for the first time in Rmail.
To make a change in this variable take effect
for a message that you have already viewed,
go to that message and type \\[rmail-toggle-header] twice.")
-
(custom-autoload 'rmail-ignored-headers "rmail" t)
-
(defvar rmail-displayed-headers nil "\
Regexp to match Header fields that Rmail should display.
If nil, display all header fields except those matched by
`rmail-ignored-headers'.")
-
(custom-autoload 'rmail-displayed-headers "rmail" t)
-
(defvar rmail-retry-ignored-headers (purecopy "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:\\|message-id:") "\
Headers that should be stripped when retrying a failed message.")
-
(custom-autoload 'rmail-retry-ignored-headers "rmail" t)
-
(defvar rmail-highlighted-headers (purecopy "^From:\\|^Subject:") "\
Regexp to match Header fields that Rmail should normally highlight.
A value of nil means don't highlight. Uses the face `rmail-highlight'.")
-
(custom-autoload 'rmail-highlighted-headers "rmail" t)
-
(defvar rmail-primary-inbox-list nil "\
List of files that are inboxes for your primary mail file `rmail-file-name'.
If this is nil, uses the environment variable MAIL. If that is
unset, uses a file named by the function `user-login-name' in the
directory `rmail-spool-directory' (whose value depends on the
operating system). For example, \"/var/mail/USER\".")
-
(custom-autoload 'rmail-primary-inbox-list "rmail" t)
-
(defvar rmail-secondary-file-directory (purecopy "~/") "\
Directory for additional secondary Rmail files.")
-
(custom-autoload 'rmail-secondary-file-directory "rmail" t)
-
(defvar rmail-secondary-file-regexp (purecopy "\\.xmail\\'") "\
Regexp for which files are secondary Rmail files.")
-
(custom-autoload 'rmail-secondary-file-regexp "rmail" t)
-
(defvar rmail-mode-hook nil "\
List of functions to call when Rmail is invoked.")
-
(defvar rmail-show-message-hook nil "\
List of functions to call when Rmail displays a message.")
-
(custom-autoload 'rmail-show-message-hook "rmail" t)
-
(defvar rmail-file-coding-system nil "\
Coding system used in RMAIL file.
This is set to nil by default.")
-
(defvar rmail-insert-mime-forwarded-message-function nil "\
Function to insert a message in MIME format so it can be forwarded.
This function is called if `rmail-enable-mime' and
@@ -28697,7 +25974,6 @@ This function is called if `rmail-enable-mime' and
It is called with one argument FORWARD-BUFFER, which is a
buffer containing the message to forward. The current buffer
is the outgoing mail buffer.")
-
(autoload 'rmail "rmail" "\
Read and edit incoming mail.
Moves messages into file named by `rmail-file-name' and edits that
@@ -28711,8 +25987,7 @@ have a chance to specify a file name with the minibuffer.
If `rmail-display-summary' is non-nil, make a summary for this RMAIL file.
-\(fn &optional FILE-NAME-ARG)" t nil)
-
+(fn &optional FILE-NAME-ARG)" t nil)
(autoload 'rmail-mode "rmail" "\
Rmail Mode is used by \\<rmail-mode-map>\\[rmail] for editing Rmail files.
All normal editing commands are turned off.
@@ -28763,40 +26038,29 @@ Instead, these commands are available:
\\[rmail-summary-by-regexp] Summarize only messages with particular regexp(s).
\\[rmail-summary-by-topic] Summarize only messages with subject line regexp(s).
\\[rmail-toggle-header] Toggle display of complete header." t nil)
-
(autoload 'rmail-input "rmail" "\
Run Rmail on file FILENAME.
-\(fn FILENAME)" t nil)
-
+(fn FILENAME)" t nil)
(autoload 'rmail-set-remote-password "rmail" "\
Set PASSWORD to be used for retrieving mail from a POP or IMAP server.
-\(fn PASSWORD)" t nil)
-
+(fn PASSWORD)" t nil)
(register-definition-prefixes "rmail" '("mail-" "rmail-"))
-;;;***
-;;;### (autoloads nil "rmail-spam-filter" "mail/rmail-spam-filter.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from mail/rmail-spam-filter.el
(register-definition-prefixes "rmail-spam-filter" '("rmail-" "rsf-"))
-;;;***
-;;;### (autoloads nil "rmailedit" "mail/rmailedit.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailedit.el
(autoload 'rmail-edit-current-message "rmailedit" "\
Edit the contents of this message." t nil)
-
(register-definition-prefixes "rmailedit" '("rmail-"))
-;;;***
-;;;### (autoloads nil "rmailkwd" "mail/rmailkwd.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailkwd.el
(autoload 'rmail-add-label "rmailkwd" "\
@@ -28804,44 +26068,37 @@ Add LABEL to labels associated with current RMAIL message.
Completes (see `rmail-read-label') over known labels when reading.
LABEL may be a symbol or string. Only one label is allowed.
-\(fn LABEL)" t nil)
-
+(fn LABEL)" t nil)
(autoload 'rmail-kill-label "rmailkwd" "\
Remove LABEL from labels associated with current RMAIL message.
Completes (see `rmail-read-label') over known labels when reading.
LABEL may be a symbol or string. Only one label is allowed.
-\(fn LABEL)" t nil)
-
+(fn LABEL)" t nil)
(autoload 'rmail-read-label "rmailkwd" "\
Read a label with completion, prompting with PROMPT.
Completions are chosen from `rmail-label-obarray'. The default
is `rmail-last-label', if that is non-nil. Updates `rmail-last-label'
according to the choice made, and returns a symbol.
-\(fn PROMPT)" nil nil)
-
+(fn PROMPT)" nil nil)
(autoload 'rmail-previous-labeled-message "rmailkwd" "\
Show previous message with one of the labels LABELS.
LABELS should be a comma-separated list of label names.
If LABELS is empty, the last set of labels specified is used.
With prefix argument N moves backward N messages with these labels.
-\(fn N LABELS)" t nil)
-
+(fn N LABELS)" t nil)
(autoload 'rmail-next-labeled-message "rmailkwd" "\
Show next message with one of the labels LABELS.
LABELS should be a comma-separated list of label names.
If LABELS is empty, the last set of labels specified is used.
With prefix argument N moves forward N messages with these labels.
-\(fn N LABELS)" t nil)
-
+(fn N LABELS)" t nil)
(register-definition-prefixes "rmailkwd" '("rmail-"))
-;;;***
-;;;### (autoloads nil "rmailmm" "mail/rmailmm.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailmm.el
(autoload 'rmail-mime "rmailmm" "\
@@ -28863,13 +26120,10 @@ By default, this displays text and multipart messages, and offers to
download attachments as specified by `rmail-mime-attachment-dirs-alist'.
The arguments ARG and STATE have no effect in this case.
-\(fn &optional ARG STATE)" t nil)
-
+(fn &optional ARG STATE)" t nil)
(register-definition-prefixes "rmailmm" '("rmail-"))
-;;;***
-;;;### (autoloads nil "rmailmsc" "mail/rmailmsc.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailmsc.el
(autoload 'set-rmail-inbox-list "rmailmsc" "\
@@ -28879,14 +26133,12 @@ If FILE-NAME is empty, remove any existing inbox list.
This applies only to the current session.
-\(fn FILE-NAME)" t nil)
+(fn FILE-NAME)" t nil)
-;;;***
-;;;### (autoloads nil "rmailout" "mail/rmailout.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailout.el
-(put 'rmail-output-file-alist 'risky-local-variable t)
+(put 'rmail-output-file-alist 'risky-local-variable t)
(autoload 'rmail-output "rmailout" "\
Append this message to mail file FILE-NAME.
Writes mbox format, unless FILE-NAME exists and is Babyl format, in which
@@ -28922,8 +26174,7 @@ message (if writing a file directly).
Set the optional fourth argument NOT-RMAIL non-nil if you call this
from a non-Rmail buffer. In this case, COUNT is ignored.
-\(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil)
-
+(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil)
(autoload 'rmail-output-as-seen "rmailout" "\
Append this message to mbox file named FILE-NAME.
The details are as for `rmail-output', except that:
@@ -28935,8 +26186,7 @@ Note that if NOT-RMAIL is non-nil, there is no difference between this
function and `rmail-output'. This argument may be removed in future,
so you should call `rmail-output' directly in that case.
-\(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil)
-
+(fn FILE-NAME &optional COUNT NOATTRIBUTE NOT-RMAIL)" t nil)
(autoload 'rmail-output-body-to-file "rmailout" "\
Write this message body to the file FILE-NAME.
Interactively, the default file name comes from either the message
@@ -28949,42 +26199,35 @@ Note that this overwrites FILE-NAME (after confirmation), rather
than appending to it. Deletes the message after writing if
`rmail-delete-after-output' is non-nil.
-\(fn FILE-NAME)" t nil)
-
+(fn FILE-NAME)" t nil)
(register-definition-prefixes "rmailout" '("rmail-"))
-;;;***
-;;;### (autoloads nil "rmailsort" "mail/rmailsort.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailsort.el
(autoload 'rmail-sort-by-date "rmailsort" "\
Sort messages of current Rmail buffer by \"Date\" header.
If prefix argument REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-subject "rmailsort" "\
Sort messages of current Rmail buffer by \"Subject\" header.
Ignores any \"Re: \" prefix. If prefix argument REVERSE is
non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-author "rmailsort" "\
Sort messages of current Rmail buffer by author.
This uses either the \"From\" or \"Sender\" header, downcased.
If prefix argument REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-recipient "rmailsort" "\
Sort messages of current Rmail buffer by recipient.
This uses either the \"To\" or \"Apparently-To\" header, downcased.
If prefix argument REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-correspondent "rmailsort" "\
Sort messages of current Rmail buffer by other correspondent.
This uses either the \"From\", \"Sender\", \"To\", or
@@ -28992,14 +26235,12 @@ This uses either the \"From\", \"Sender\", \"To\", or
excluded by `mail-dont-reply-to-names'. If prefix argument
REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-lines "rmailsort" "\
Sort messages of current Rmail buffer by the number of lines.
If prefix argument REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE)" t nil)
-
+(fn REVERSE)" t nil)
(autoload 'rmail-sort-by-labels "rmailsort" "\
Sort messages of current Rmail buffer by labels.
LABELS is a comma-separated list of labels. The order of these
@@ -29008,24 +26249,19 @@ label come first, messages with the second label come second, and
so on. Messages that have none of these labels come last.
If prefix argument REVERSE is non-nil, sorts in reverse order.
-\(fn REVERSE LABELS)" t nil)
-
+(fn REVERSE LABELS)" t nil)
(register-definition-prefixes "rmailsort" '("rmail-"))
-;;;***
-;;;### (autoloads nil "rmailsum" "mail/rmailsum.el" (0 0 0 0))
;;; Generated autoloads from mail/rmailsum.el
(autoload 'rmail-summary "rmailsum" "\
Display a summary of all messages, one line per message." t nil)
-
(autoload 'rmail-summary-by-labels "rmailsum" "\
Display a summary of all messages with one or more LABELS.
LABELS should be a string containing the desired labels, separated by commas.
-\(fn LABELS)" t nil)
-
+(fn LABELS)" t nil)
(autoload 'rmail-summary-by-recipients "rmailsum" "\
Display a summary of all messages with the given RECIPIENTS.
Normally checks the To, From and Cc fields of headers;
@@ -29033,190 +26269,94 @@ but if PRIMARY-ONLY is non-nil (prefix arg given),
only look in the To and From fields.
RECIPIENTS is a regular expression.
-\(fn RECIPIENTS &optional PRIMARY-ONLY)" t nil)
-
+(fn RECIPIENTS &optional PRIMARY-ONLY)" t nil)
(autoload 'rmail-summary-by-regexp "rmailsum" "\
Display a summary of all messages according to regexp REGEXP.
If the regular expression is found in the header of the message
-\(including in the date and other lines, as well as the subject line),
+(including in the date and other lines, as well as the subject line),
Emacs will list the message in the summary.
-\(fn REGEXP)" t nil)
-
+(fn REGEXP)" t nil)
(autoload 'rmail-summary-by-topic "rmailsum" "\
Display a summary of all messages with the given SUBJECT.
Normally checks just the Subject field of headers; but with prefix
argument WHOLE-MESSAGE is non-nil, looks in the whole message.
SUBJECT is a regular expression.
-\(fn SUBJECT &optional WHOLE-MESSAGE)" t nil)
-
+(fn SUBJECT &optional WHOLE-MESSAGE)" t nil)
(autoload 'rmail-summary-by-senders "rmailsum" "\
Display a summary of all messages whose \"From\" field matches SENDERS.
SENDERS is a regular expression. The default for SENDERS matches the
sender of the current message.
-\(fn SENDERS)" t nil)
-
+(fn SENDERS)" t nil)
(register-definition-prefixes "rmailsum" '("rmail-"))
-;;;***
-
-;;;### (autoloads nil "rmc" "emacs-lisp/rmc.el" (0 0 0 0))
-;;; Generated autoloads from emacs-lisp/rmc.el
-
-(autoload 'read-multiple-choice "rmc" "\
-Ask user to select an entry from CHOICES, promting with PROMPT.
-This function allows to ask the user a multiple-choice question.
-
-CHOICES should be a list of the form (KEY NAME [DESCRIPTION]).
-KEY is a character the user should type to select the entry.
-NAME is a short name for the entry to be displayed while prompting
-\(if there's no room, it might be shortened).
-DESCRIPTION is an optional longer description of the entry; it will
-be displayed in a help buffer if the user requests more help. This
-help description has a fixed format in columns. For greater
-flexibility, instead of passing a DESCRIPTION, the caller can pass
-the optional argument HELP-STRING. This argument is a string that
-should contain a more detailed description of all of the possible
-choices. `read-multiple-choice' will display that description in a
-help buffer if the user requests that.
-If optional argument SHOW-HELP is non-nil, show the help screen
-immediately, before any user input. If SHOW-HELP is a string,
-use it as the name of the help buffer.
-
-This function translates user input into responses by consulting
-the bindings in `query-replace-map'; see the documentation of
-that variable for more information. The relevant bindings for the
-purposes of this function are `recenter', `scroll-up', `scroll-down',
-and `edit'.
-If the user types the `recenter', `scroll-up', or `scroll-down'
-responses, the function performs the requested window recentering or
-scrolling, and then asks the question again. If the user enters `edit',
-the function starts a recursive edit. When the user exit the recursive
-edit, the multiple-choice prompt gains focus again.
-
-When `use-dialog-box' is t (the default), and the command using this
-function was invoked via the mouse, this function pops up a GUI dialog
-to collect the user input, but only if Emacs is capable of using GUI
-dialogs. Otherwise, the function will always use text-mode dialogs.
-
-The return value is the matching entry from the CHOICES list.
-
-Usage example:
-
-\(read-multiple-choice \"Continue connecting?\"
- \\='((?a \"always\")
- (?s \"session only\")
- (?n \"no\")))
-
-\(fn PROMPT CHOICES &optional HELP-STRING SHOW-HELP)" nil nil)
-
-(register-definition-prefixes "rmc" '("rmc--"))
-
-;;;***
-
-;;;### (autoloads nil "rng-cmpct" "nxml/rng-cmpct.el" (0 0 0 0))
+
;;; Generated autoloads from nxml/rng-cmpct.el
(autoload 'rng-c-load-schema "rng-cmpct" "\
Load a schema in RELAX NG compact syntax from FILENAME.
Return a pattern.
-\(fn FILENAME)" nil nil)
-
+(fn FILENAME)" nil nil)
(register-definition-prefixes "rng-cmpct" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-dt" "nxml/rng-dt.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-dt.el
(register-definition-prefixes "rng-dt" '("rng-dt-"))
-;;;***
-;;;### (autoloads nil "rng-loc" "nxml/rng-loc.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-loc.el
(register-definition-prefixes "rng-loc" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-maint" "nxml/rng-maint.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-maint.el
(register-definition-prefixes "rng-maint" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-match" "nxml/rng-match.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-match.el
(register-definition-prefixes "rng-match" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-nxml" "nxml/rng-nxml.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-nxml.el
(autoload 'rng-nxml-mode-init "rng-nxml" "\
Initialize `nxml-mode' to take advantage of `rng-validate-mode'.
This is typically called from `nxml-mode-hook'.
Validation will be enabled if `rng-nxml-auto-validate-flag' is non-nil." t nil)
-
(register-definition-prefixes "rng-nxml" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-parse" "nxml/rng-parse.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-parse.el
(register-definition-prefixes "rng-parse" '("rng-parse-"))
-;;;***
-;;;### (autoloads nil "rng-pttrn" "nxml/rng-pttrn.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-pttrn.el
(register-definition-prefixes "rng-pttrn" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-uri" "nxml/rng-uri.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-uri.el
(register-definition-prefixes "rng-uri" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-util" "nxml/rng-util.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-util.el
(register-definition-prefixes "rng-util" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-valid" "nxml/rng-valid.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-valid.el
(autoload 'rng-validate-mode "rng-valid" "\
Minor mode performing continual validation against a RELAX NG schema.
-This is a minor mode. If called interactively, toggle the
-`Rng-Validate mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `rng-validate-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Checks whether the buffer is a well-formed XML 1.0 document,
conforming to the XML Namespaces Recommendation and valid against a
RELAX NG schema. The mode-line indicates whether it is or not. Any
@@ -29237,17 +26377,27 @@ conventionally have a suffix of `.rnc'). The variable
`rng-schema-locating-files' specifies files containing rules
to use for finding the schema.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Rng-Validate mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `rng-validate-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "rng-valid" '("rng-"))
-;;;***
-;;;### (autoloads nil "rng-xsd" "nxml/rng-xsd.el" (0 0 0 0))
;;; Generated autoloads from nxml/rng-xsd.el
-(put 'http://www\.w3\.org/2001/XMLSchema-datatypes 'rng-dt-compile #'rng-xsd-compile)
-
+(put 'http://www.w3.org/2001/XMLSchema-datatypes 'rng-dt-compile #'rng-xsd-compile)
(autoload 'rng-xsd-compile "rng-xsd" "\
Provide W3C XML Schema as a RELAX NG datatypes library.
NAME is a symbol giving the local name of the datatype. PARAMS is a
@@ -29266,13 +26416,10 @@ The object returned can be any convenient non-nil value, provided
that, if two strings represent the same value, the returned objects
must be equal.
-\(fn NAME PARAMS)" nil nil)
-
+(fn NAME PARAMS)" nil nil)
(register-definition-prefixes "rng-xsd" '("rng-xsd-" "xsd-duration-reference-dates"))
-;;;***
-;;;### (autoloads nil "robin" "international/robin.el" (0 0 0 0))
;;; Generated autoloads from international/robin.el
(autoload 'robin-define-package "robin" "\
@@ -29286,8 +26433,7 @@ OUTPUT is either a character or a string. RULES are not evaluated.
If there already exists a robin package whose name is NAME, the new
one replaces the old one.
-\(fn NAME DOCSTRING &rest RULES)" nil t)
-
+(fn NAME DOCSTRING &rest RULES)" nil t)
(autoload 'robin-modify-package "robin" "\
Change a rule in an already defined robin package.
@@ -29295,18 +26441,14 @@ NAME is the string specifying a robin package.
INPUT is a string that specifies the input pattern.
OUTPUT is either a character or a string to be generated.
-\(fn NAME INPUT OUTPUT)" nil nil)
-
+(fn NAME INPUT OUTPUT)" nil nil)
(autoload 'robin-use-package "robin" "\
Start using robin package NAME, which is a string.
-\(fn NAME)" nil nil)
-
+(fn NAME)" nil nil)
(register-definition-prefixes "robin" '("robin-"))
-;;;***
-;;;### (autoloads nil "rot13" "rot13.el" (0 0 0 0))
;;; Generated autoloads from rot13.el
(autoload 'rot13 "rot13" "\
@@ -29315,18 +26457,15 @@ If OBJECT is a buffer, encrypt the region between START and END.
If OBJECT is a string, encrypt it in its entirety, ignoring START
and END, and return the encrypted string.
-\(fn OBJECT &optional START END)" nil nil)
-
+(fn OBJECT &optional START END)" nil nil)
(autoload 'rot13-string "rot13" "\
Return ROT13 encryption of STRING.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'rot13-region "rot13" "\
ROT13 encrypt the region between START and END in current buffer.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'rot13-other-window "rot13" "\
Display current buffer in ROT13 in another window.
The text itself is not modified, only the way it is displayed is affected.
@@ -29336,18 +26475,14 @@ is not deleted, any buffer displayed in it will become instantly encoded
in ROT13.
See also `toggle-rot13-mode'." t nil)
-
(autoload 'toggle-rot13-mode "rot13" "\
Toggle the use of ROT13 encoding for the current window." t nil)
-
(register-definition-prefixes "rot13" '("rot13-"))
-;;;***
-;;;### (autoloads nil "rst" "textmodes/rst.el" (0 0 0 0))
;;; Generated autoloads from textmodes/rst.el
- (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
+ (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
(autoload 'rst-mode "rst" "\
Major mode for editing reStructuredText documents.
\\<rst-mode-map>
@@ -29358,91 +26493,75 @@ highlighting.
\\{rst-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'rst-minor-mode "rst" "\
Toggle ReST minor mode.
-This is a minor mode. If called interactively, toggle the `Rst minor
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+When ReST minor mode is enabled, the ReST mode keybindings
+are installed on top of the major mode bindings. Use this
+for modes derived from Text mode, like Mail mode.
+
+This is a minor mode. If called interactively, toggle the `Rst
+minor mode' mode. If the prefix argument is positive, enable the
+mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `rst-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When ReST minor mode is enabled, the ReST mode keybindings
-are installed on top of the major mode bindings. Use this
-for modes derived from Text mode, like Mail mode.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "rst" '("rst-"))
-;;;***
-;;;### (autoloads nil "rtree" "rtree.el" (0 0 0 0))
;;; Generated autoloads from rtree.el
(register-definition-prefixes "rtree" '("rtree-"))
-;;;***
-;;;### (autoloads nil "ruby-mode" "progmodes/ruby-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/ruby-mode.el
-(push (purecopy '(ruby-mode 1 2)) package--builtin-versions)
+(push (purecopy '(ruby-mode 1 2)) package--builtin-versions)
(autoload 'ruby-mode "ruby-mode" "\
Major mode for editing Ruby code.
-\(fn)" t nil)
-
+(fn)" t nil)
(add-to-list 'auto-mode-alist (cons (purecopy (concat "\\(?:\\.\\(?:" "rbw?\\|ru\\|rake\\|thor" "\\|jbuilder\\|rabl\\|gemspec\\|podspec" "\\)" "\\|/" "\\(?:Gem\\|Rake\\|Cap\\|Thor" "\\|Puppet\\|Berks\\|Brew" "\\|Vagrant\\|Guard\\|Pod\\)file" "\\)\\'")) 'ruby-mode))
-
(dolist (name (list "ruby" "rbx" "jruby" "ruby1.9" "ruby1.8")) (add-to-list 'interpreter-mode-alist (cons (purecopy name) 'ruby-mode)))
-
(register-definition-prefixes "ruby-mode" '("ruby-"))
-;;;***
-;;;### (autoloads nil "ruler-mode" "ruler-mode.el" (0 0 0 0))
;;; Generated autoloads from ruler-mode.el
(defvar-local ruler-mode nil "\
Non-nil if Ruler mode is enabled.
Use the command `ruler-mode' to change this variable.")
-
(autoload 'ruler-mode "ruler-mode" "\
Toggle display of ruler in header line (Ruler mode).
This is a minor mode. If called interactively, toggle the `Ruler
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+mode' mode. If the prefix argument is positive, enable the mode,
+and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `ruler-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "ruler-mode" '("ruler-"))
-;;;***
-;;;### (autoloads nil "rx" "emacs-lisp/rx.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/rx.el
(autoload 'rx-to-string "rx" "\
@@ -29454,8 +26573,7 @@ group.
For extending the `rx' notation in FORM, use `rx-define' or `rx-let-eval'.
-\(fn FORM &optional NO-GROUP)" nil nil)
-
+(fn FORM &optional NO-GROUP)" nil nil)
(autoload 'rx "rx" "\
Translate regular expressions REGEXPS in sexp form to a regexp string.
Each argument is one of the forms below; RX is a subform, and RX... stands
@@ -29465,34 +26583,34 @@ See `rx-to-string' for the corresponding function.
STRING Match a literal string.
CHAR Match a literal character.
-\(seq RX...) Match the RXs in sequence. Alias: :, sequence, and.
-\(or RX...) Match one of the RXs. Alias: |.
-
-\(zero-or-more RX...) Match RXs zero or more times. Alias: 0+.
-\(one-or-more RX...) Match RXs one or more times. Alias: 1+.
-\(zero-or-one RX...) Match RXs or the empty string. Alias: opt, optional.
-\(* RX...) Match RXs zero or more times; greedy.
-\(+ RX...) Match RXs one or more times; greedy.
-\(? RX...) Match RXs or the empty string; greedy.
-\(*? RX...) Match RXs zero or more times; non-greedy.
-\(+? RX...) Match RXs one or more times; non-greedy.
-\(?? RX...) Match RXs or the empty string; non-greedy.
-\(= N RX...) Match RXs exactly N times.
-\(>= N RX...) Match RXs N or more times.
-\(** N M RX...) Match RXs N to M times. Alias: repeat.
-\(minimal-match RX) Match RX, with zero-or-more, one-or-more, zero-or-one
+(seq RX...) Match the RXs in sequence. Alias: :, sequence, and.
+(or RX...) Match one of the RXs. Alias: |.
+
+(zero-or-more RX...) Match RXs zero or more times. Alias: 0+.
+(one-or-more RX...) Match RXs one or more times. Alias: 1+.
+(zero-or-one RX...) Match RXs or the empty string. Alias: opt, optional.
+(* RX...) Match RXs zero or more times; greedy.
+(+ RX...) Match RXs one or more times; greedy.
+(? RX...) Match RXs or the empty string; greedy.
+(*? RX...) Match RXs zero or more times; non-greedy.
+(+? RX...) Match RXs one or more times; non-greedy.
+(?? RX...) Match RXs or the empty string; non-greedy.
+(= N RX...) Match RXs exactly N times.
+(>= N RX...) Match RXs N or more times.
+(** N M RX...) Match RXs N to M times. Alias: repeat.
+(minimal-match RX) Match RX, with zero-or-more, one-or-more, zero-or-one
and aliases using non-greedy matching.
-\(maximal-match RX) Match RX, with zero-or-more, one-or-more, zero-or-one
+(maximal-match RX) Match RX, with zero-or-more, one-or-more, zero-or-one
and aliases using greedy matching, which is the default.
-\(any SET...) Match a character from one of the SETs. Each SET is a
+(any SET...) Match a character from one of the SETs. Each SET is a
character, a string, a range as string \"A-Z\" or cons
(?A . ?Z), or a character class (see below). Alias: in, char.
-\(not CHARSPEC) Match one character not matched by CHARSPEC. CHARSPEC
+(not CHARSPEC) Match one character not matched by CHARSPEC. CHARSPEC
can be a character, single-char string, (any ...), (or ...),
(intersection ...), (syntax ...), (category ...),
or a character class.
-\(intersection CHARSET...) Match all CHARSETs.
+(intersection CHARSET...) Match all CHARSETs.
CHARSET is (any...), (not...), (or...) or (intersection...),
a character or a single-char string.
not-newline Match any character except a newline. Alias: nonl.
@@ -29517,13 +26635,13 @@ CHARCLASS Match a character from a character class. One of:
ascii ASCII characters (codes 0-127).
nonascii Non-ASCII characters (but not raw bytes).
-\(syntax SYNTAX) Match a character with syntax SYNTAX, being one of:
+(syntax SYNTAX) Match a character with syntax SYNTAX, being one of:
whitespace, punctuation, word, symbol, open-parenthesis,
close-parenthesis, expression-prefix, string-quote,
paired-delimiter, escape, character-quote, comment-start,
comment-end, string-delimiter, comment-delimiter
-\(category CAT) Match a character in category CAT, being one of:
+(category CAT) Match a character in category CAT, being one of:
space-for-indent, base, consonant, base-vowel,
upper-diacritical-mark, lower-diacritical-mark, tone-mark, symbol,
digit, vowel-modifying-diacritical-mark, vowel-sign,
@@ -29552,24 +26670,23 @@ Zero-width assertions: these all match the empty string in specific places.
symbol-start At the beginning of a symbol.
symbol-end At the end of a symbol.
-\(group RX...) Match RXs and define a capture group. Alias: submatch.
-\(group-n N RX...) Match RXs and define capture group N. Alias: submatch-n.
-\(backref N) Match the text that capture group N matched.
+(group RX...) Match RXs and define a capture group. Alias: submatch.
+(group-n N RX...) Match RXs and define capture group N. Alias: submatch-n.
+(backref N) Match the text that capture group N matched.
-\(literal EXPR) Match the literal string from evaluating EXPR at run time.
-\(regexp EXPR) Match the string regexp from evaluating EXPR at run time.
-\(eval EXPR) Match the rx sexp from evaluating EXPR at macro-expansion
+(literal EXPR) Match the literal string from evaluating EXPR at run time.
+(regexp EXPR) Match the string regexp from evaluating EXPR at run time.
+(eval EXPR) Match the rx sexp from evaluating EXPR at macro-expansion
(compile) time.
Additional constructs can be defined using `rx-define' and `rx-let',
which see.
-\(fn REGEXPS...)" nil t)
-
+(fn REGEXPS...)" nil t)
(autoload 'rx-let-eval "rx" "\
Evaluate BODY with local BINDINGS for `rx-to-string'.
BINDINGS, after evaluation, is a list of definitions each on the form
-\(NAME [(ARGS...)] RX), in effect for calls to `rx-to-string'
+(NAME [(ARGS...)] RX), in effect for calls to `rx-to-string'
in BODY.
For bindings without an ARGS list, NAME is defined as an alias
@@ -29585,14 +26702,12 @@ For extensions when using the `rx' macro, use `rx-let'.
To make global rx extensions, use `rx-define'.
For more details, see Info node `(elisp) Extending Rx'.
-\(fn BINDINGS BODY...)" nil t)
-
-(function-put 'rx-let-eval 'lisp-indent-function '1)
-
+(fn BINDINGS BODY...)" nil t)
+(function-put 'rx-let-eval 'lisp-indent-function 1)
(autoload 'rx-let "rx" "\
Evaluate BODY with local BINDINGS for `rx'.
BINDINGS is an unevaluated list of bindings each on the form
-\(NAME [(ARGS...)] RX).
+(NAME [(ARGS...)] RX).
They are bound lexically and are available in `rx' expressions in
BODY only.
@@ -29609,10 +26724,8 @@ For local extensions to `rx-to-string', use `rx-let-eval'.
To make global rx extensions, use `rx-define'.
For more details, see Info node `(elisp) Extending Rx'.
-\(fn BINDINGS BODY...)" nil t)
-
-(function-put 'rx-let 'lisp-indent-function '1)
-
+(fn BINDINGS BODY...)" nil t)
+(function-put 'rx-let 'lisp-indent-function 1)
(autoload 'rx-define "rx" "\
Define NAME as a global `rx' definition.
If the ARGS list is omitted, define NAME as an alias for the `rx'
@@ -29629,65 +26742,58 @@ To make local rx extensions, use `rx-let' for `rx',
`rx-let-eval' for `rx-to-string'.
For more details, see Info node `(elisp) Extending Rx'.
-\(fn NAME [(ARGS...)] RX)" nil t)
-
+(fn NAME [(ARGS...)] RX)" nil t)
(function-put 'rx-define 'lisp-indent-function 'defun)
-
-(eval-and-compile (defun rx--pcase-macroexpander (&rest regexps) "A pattern that matches strings against `rx' REGEXPS in sexp form.\nREGEXPS are interpreted as in `rx'. The pattern matches any\nstring that is a match for REGEXPS, as if by `string-match'.\n\nIn addition to the usual `rx' syntax, REGEXPS can contain the\nfollowing constructs:\n\n (let REF RX...) binds the symbol REF to a submatch that matches\n the regular expressions RX. REF is bound in\n CODE to the string of the submatch or nil, but\n can also be used in `backref'.\n (backref REF) matches whatever the submatch REF matched.\n REF can be a number, as usual, or a name\n introduced by a previous (let REF ...)\n construct." (let* ((rx--pcase-vars nil) (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps))))) `(and (pred stringp) ,(pcase (length rx--pcase-vars) (0 `(pred (string-match ,regexp))) (1 `(app (lambda (s) (if (string-match ,regexp s) (match-string 1 s) 0)) (and ,(car rx--pcase-vars) (pred (not numberp))))) (nvars `(app (lambda (s) (and (string-match ,regexp s) ,(rx--reduce-right (lambda (a b) `(cons ,a ,b)) (mapcar (lambda (i) `(match-string ,i s)) (number-sequence 1 nvars))))) ,(list '\` (rx--reduce-right #'cons (mapcar (lambda (name) (list '\, name)) (reverse rx--pcase-vars)))))))))))
-
+(eval-and-compile (defun rx--pcase-macroexpander (&rest regexps) "A pattern that matches strings against `rx' REGEXPS in sexp form.
+REGEXPS are interpreted as in `rx'. The pattern matches any
+string that is a match for REGEXPS, as if by `string-match'.
+
+In addition to the usual `rx' syntax, REGEXPS can contain the
+following constructs:
+
+ (let REF RX...) binds the symbol REF to a submatch that matches
+ the regular expressions RX. REF is bound in
+ CODE to the string of the submatch or nil, but
+ can also be used in `backref'.
+ (backref REF) matches whatever the submatch REF matched.
+ REF can be a number, as usual, or a name
+ introduced by a previous (let REF ...)
+ construct." (let* ((rx--pcase-vars nil) (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps))))) `(and (pred stringp) ,(pcase (length rx--pcase-vars) (0 `(pred (string-match ,regexp))) (1 `(app (lambda (s) (if (string-match ,regexp s) (match-string 1 s) 0)) (and ,(car rx--pcase-vars) (pred (not numberp))))) (nvars `(app (lambda (s) (and (string-match ,regexp s) ,(rx--reduce-right (lambda (a b) `(cons ,a ,b)) (mapcar (lambda (i) `(match-string ,i s)) (number-sequence 1 nvars))))) ,(list '\` (rx--reduce-right #'cons (mapcar (lambda (name) (list '\, name)) (reverse rx--pcase-vars)))))))))))
(define-symbol-prop 'rx--pcase-macroexpander 'edebug-form-spec 'nil)
-
(define-symbol-prop 'rx 'pcase-macroexpander #'rx--pcase-macroexpander)
-
(register-definition-prefixes "rx" '("rx-"))
-;;;***
-;;;### (autoloads nil "sasl" "net/sasl.el" (0 0 0 0))
;;; Generated autoloads from net/sasl.el
(register-definition-prefixes "sasl" '("sasl-"))
-;;;***
-;;;### (autoloads nil "sasl-cram" "net/sasl-cram.el" (0 0 0 0))
;;; Generated autoloads from net/sasl-cram.el
(register-definition-prefixes "sasl-cram" '("sasl-cram-md5-"))
-;;;***
-;;;### (autoloads nil "sasl-digest" "net/sasl-digest.el" (0 0 0 0))
;;; Generated autoloads from net/sasl-digest.el
(register-definition-prefixes "sasl-digest" '("sasl-digest-md5-"))
-;;;***
-;;;### (autoloads nil "sasl-ntlm" "net/sasl-ntlm.el" (0 0 0 0))
;;; Generated autoloads from net/sasl-ntlm.el
(register-definition-prefixes "sasl-ntlm" '("sasl-ntlm-"))
-;;;***
-;;;### (autoloads nil "sasl-scram-rfc" "net/sasl-scram-rfc.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from net/sasl-scram-rfc.el
(register-definition-prefixes "sasl-scram-rfc" '("sasl-scram-"))
-;;;***
-;;;### (autoloads nil "sasl-scram-sha256" "net/sasl-scram-sha256.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from net/sasl-scram-sha256.el
(register-definition-prefixes "sasl-scram-sha256" '("sasl-scram-sha"))
-;;;***
-;;;### (autoloads nil "savehist" "savehist.el" (0 0 0 0))
;;; Generated autoloads from savehist.el
(defvar savehist-mode nil "\
@@ -29697,26 +26803,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `savehist-mode'.")
-
(custom-autoload 'savehist-mode "savehist" nil)
-
(autoload 'savehist-mode "savehist" "\
Toggle saving of minibuffer history (Savehist mode).
-This is a minor mode. If called interactively, toggle the `Savehist
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='savehist-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Savehist mode is enabled, minibuffer history is saved
to `savehist-file' periodically and when exiting Emacs. When
Savehist mode is enabled for the first time in an Emacs session,
@@ -29743,13 +26833,24 @@ This mode should normally be turned on from your Emacs init file.
Calling it at any other time replaces your current minibuffer
histories, which is probably undesirable.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Savehist mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='savehist-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "savehist" '("savehist-"))
-;;;***
-;;;### (autoloads nil "saveplace" "saveplace.el" (0 0 0 0))
;;; Generated autoloads from saveplace.el
(defvar save-place-mode nil "\
@@ -29759,62 +26860,64 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `save-place-mode'.")
-
(custom-autoload 'save-place-mode "saveplace" nil)
-
(autoload 'save-place-mode "saveplace" "\
Non-nil means automatically save place in each file.
+
This means when you visit a file, point goes to the last place
where it was when you previously visited the same file.
-This is a minor mode. If called interactively, toggle the `Save-Place
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a global minor mode. If called interactively, toggle the
+`Save-Place mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='save-place-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'save-place-local-mode "saveplace" "\
Toggle whether to save your place in this file between sessions.
+
If this mode is enabled, point is recorded when you kill the buffer
or exit Emacs. Visiting this file again will go to that position,
even in a later Emacs session.
+To save places automatically in all files, put this in your init
+file:
+
+(save-place-mode 1)
+
This is a minor mode. If called interactively, toggle the
-`Save-Place-Local mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Save-Place-Local mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `save-place-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-To save places automatically in all files, put this in your init
-file:
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-\(save-place-mode 1)
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "saveplace" '("load-save-place-alist-from-file" "save-place"))
-\(fn &optional ARG)" t nil)
+
+;;; Generated autoloads from cedet/semantic/sb.el
-(register-definition-prefixes "saveplace" '("load-save-place-alist-from-file" "save-place"))
+(register-definition-prefixes "semantic/sb" '("semantic-sb-"))
-;;;***
-;;;### (autoloads nil "scheme" "progmodes/scheme.el" (0 0 0 0))
;;; Generated autoloads from progmodes/scheme.el
(autoload 'scheme-mode "scheme" "\
@@ -29835,8 +26938,7 @@ Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{scheme-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'dsssl-mode "scheme" "\
Major mode for editing DSSSL code.
Editing commands are similar to those of `lisp-mode'.
@@ -29849,13 +26951,20 @@ Entering this mode runs the hooks `scheme-mode-hook' and then
`dsssl-mode-hook' and inserts the value of `dsssl-sgml-declaration' if
that variable's value is a string.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "scheme" '("dsssl-" "scheme-"))
-;;;***
-;;;### (autoloads nil "score-mode" "gnus/score-mode.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/bovine/scm.el
+
+(register-definition-prefixes "semantic/bovine/scm" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/scope.el
+
+(register-definition-prefixes "semantic/scope" '("semantic-"))
+
+
;;; Generated autoloads from gnus/score-mode.el
(autoload 'gnus-score-mode "score-mode" "\
@@ -29864,13 +26973,10 @@ This mode is an extended emacs-lisp mode.
\\{gnus-score-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "score-mode" '("gnus-score-" "score-mode-"))
-;;;***
-;;;### (autoloads nil "scroll-all" "scroll-all.el" (0 0 0 0))
;;; Generated autoloads from scroll-all.el
(defvar scroll-all-mode nil "\
@@ -29880,89 +26986,82 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `scroll-all-mode'.")
-
(custom-autoload 'scroll-all-mode "scroll-all" nil)
-
(autoload 'scroll-all-mode "scroll-all" "\
Toggle shared scrolling in same-frame windows (Scroll-All mode).
-This is a minor mode. If called interactively, toggle the `Scroll-All
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+When Scroll-All mode is enabled, scrolling commands invoked in
+one window apply to all visible windows in the same frame.
+
+This is a global minor mode. If called interactively, toggle the
+`Scroll-All mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='scroll-all-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-When Scroll-All mode is enabled, scrolling commands invoked in
-one window apply to all visible windows in the same frame.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "scroll-all" '("scroll-all-"))
-;;;***
-;;;### (autoloads nil "scroll-bar" "scroll-bar.el" (0 0 0 0))
;;; Generated autoloads from scroll-bar.el
(register-definition-prefixes "scroll-bar" '("get-scroll-bar-mode" "horizontal-scroll-bar" "previous-scroll-bar-mode" "scroll-bar-" "set-scroll-bar-mode" "toggle-"))
-;;;***
-;;;### (autoloads nil "scroll-lock" "scroll-lock.el" (0 0 0 0))
;;; Generated autoloads from scroll-lock.el
(autoload 'scroll-lock-mode "scroll-lock" "\
Buffer-local minor mode for pager-like scrolling.
-This is a minor mode. If called interactively, toggle the
-`Scroll-Lock mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `scroll-lock-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When enabled, keys that normally move point by line or paragraph
will scroll the buffer by the respective amount of lines instead
and point will be kept vertically fixed relative to window
boundaries during scrolling.
-Note that the default key binding to Scroll_Lock will not work on
+Note that the default key binding to `scroll' will not work on
MS-Windows systems if `w32-scroll-lock-modifier' is non-nil.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Scroll-Lock mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `scroll-lock-mode'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "scroll-lock" '("scroll-lock-"))
-;;;***
-;;;### (autoloads nil "secrets" "net/secrets.el" (0 0 0 0))
;;; Generated autoloads from net/secrets.el
+
(when (featurep 'dbusbind)
(autoload 'secrets-show-secrets "secrets" nil t))
-
(register-definition-prefixes "secrets" '("secrets-"))
-;;;***
-;;;### (autoloads nil "semantic" "cedet/semantic.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/semantic.el
+
+(register-definition-prefixes "srecode/semantic" '("srecode-semantic-"))
+
+
;;; Generated autoloads from cedet/semantic.el
-(push (purecopy '(semantic 2 2)) package--builtin-versions)
+(push (purecopy '(semantic 2 2)) package--builtin-versions)
(defvar semantic-default-submodes '(global-semantic-idle-scheduler-mode global-semanticdb-minor-mode) "\
List of auxiliary Semantic minor modes enabled by `semantic-mode'.
The possible elements of this list include the following:
@@ -29985,9 +27084,7 @@ The following modes are more targeted at people who want to see
`global-semantic-show-unmatched-syntax-mode' - Highlight unmatched lexical
syntax tokens.
`global-semantic-show-parser-state-mode' - Display the parser cache state.")
-
(custom-autoload 'semantic-default-submodes "semantic" t)
-
(defvar semantic-mode nil "\
Non-nil if Semantic mode is enabled.
See the `semantic-mode' command
@@ -29995,26 +27092,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `semantic-mode'.")
-
(custom-autoload 'semantic-mode "semantic" nil)
-
(autoload 'semantic-mode "semantic" "\
Toggle parser features (Semantic mode).
-This is a minor mode. If called interactively, toggle the `Semantic
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='semantic-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
In Semantic mode, Emacs parses the buffers you visit for their
semantic content. This information is used by a variety of
auxiliary minor modes, listed in `semantic-default-submodes';
@@ -30023,199 +27104,29 @@ Semantic mode.
\\{semantic-mode-map}
-\(fn &optional ARG)" t nil)
-
-(register-definition-prefixes "semantic" '("bovinate" "semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/analyze/debug" "cedet/semantic/analyze/debug.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/analyze/debug.el
-
-(register-definition-prefixes "semantic/analyze/debug" '("semantic-analyze"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/analyze/fcn" "cedet/semantic/analyze/fcn.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/analyze/fcn.el
-
-(register-definition-prefixes "semantic/analyze/fcn" '("semantic-analyze-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/bovine/debug" "cedet/semantic/bovine/debug.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/bovine/debug.el
-
-(register-definition-prefixes "semantic/bovine/debug" '("semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/bovine/grammar" "cedet/semantic/bovine/grammar.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/bovine/grammar.el
-
-(autoload 'bovine-grammar-mode "semantic/bovine/grammar" "\
-Major mode for editing Bovine grammars.
-
-\(fn)" t nil)
-
-(register-definition-prefixes "semantic/bovine/grammar" '("bovine-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/chart" "cedet/semantic/chart.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/chart.el
-
-(register-definition-prefixes "semantic/chart" '("semantic-chart-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/db-debug" "cedet/semantic/db-debug.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/db-debug.el
-
-(register-definition-prefixes "semantic/db-debug" '("semanticdb-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/db-ebrowse" "cedet/semantic/db-ebrowse.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/db-ebrowse.el
-
-(register-definition-prefixes "semantic/db-ebrowse" '("c++-mode" "semanticdb-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/db-el" "cedet/semantic/db-el.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/db-el.el
-
-(register-definition-prefixes "semantic/db-el" '("emacs-lisp-mode" "semanticdb-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/db-javascript" "cedet/semantic/db-javascript.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/db-javascript.el
-
-(register-definition-prefixes "semantic/db-javascript" '("javascript-mode" "semanticdb-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/db-ref" "cedet/semantic/db-ref.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/db-ref.el
-
-(register-definition-prefixes "semantic/db-ref" '("semanticdb-ref-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/decorate" "cedet/semantic/decorate.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/decorate.el
-
-(register-definition-prefixes "semantic/decorate" '("semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/ede-grammar" "cedet/semantic/ede-grammar.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/ede-grammar.el
-
-(register-definition-prefixes "semantic/ede-grammar" '("semantic-ede-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/fw" "cedet/semantic/fw.el" (0 0 0
-;;;;;; 0))
-;;; Generated autoloads from cedet/semantic/fw.el
-
-(register-definition-prefixes "semantic/fw" '("semantic"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/grammar" "cedet/semantic/grammar.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/grammar.el
-
-(register-definition-prefixes "semantic/grammar" '("semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/java" "cedet/semantic/java.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/semantic/java.el
-
-(register-definition-prefixes "semantic/java" '("semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/sb" "cedet/semantic/sb.el" (0 0 0
-;;;;;; 0))
-;;; Generated autoloads from cedet/semantic/sb.el
-
-(register-definition-prefixes "semantic/sb" '("semantic-sb-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/symref/filter" "cedet/semantic/symref/filter.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/symref/filter.el
-
-(register-definition-prefixes "semantic/symref/filter" '("semantic-symref-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/util" "cedet/semantic/util.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/semantic/util.el
-
-(register-definition-prefixes "semantic/util" '("semantic-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/wisent" "cedet/semantic/wisent.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/wisent.el
-
-(register-definition-prefixes "semantic/wisent" '("define-wisent-lexer" "wisent-"))
-
-;;;***
-
-;;;### (autoloads nil "semantic/wisent/comp" "cedet/semantic/wisent/comp.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/wisent/comp.el
-
-(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+This is a global minor mode. If called interactively, toggle the
+`Semantic mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-;;;***
-
-;;;### (autoloads nil "semantic/wisent/grammar" "cedet/semantic/wisent/grammar.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/wisent/grammar.el
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
-(autoload 'wisent-grammar-mode "semantic/wisent/grammar" "\
-Major mode for editing Wisent grammars.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='semantic-mode)'.
-\(fn)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-(register-definition-prefixes "semantic/wisent/grammar" '("wisent-"))
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "semantic" '("bovinate" "semantic-"))
-;;;***
-;;;### (autoloads nil "semantic/wisent/wisent" "cedet/semantic/wisent/wisent.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/wisent/wisent.el
+;;; Generated autoloads from cedet/semantic/senator.el
-(register-definition-prefixes "semantic/wisent/wisent" '("$action" "$nterm" "$region" "wisent-"))
+(register-definition-prefixes "semantic/senator" '("semantic-up-reference" "senator-"))
-;;;***
-;;;### (autoloads nil "sendmail" "mail/sendmail.el" (0 0 0 0))
;;; Generated autoloads from mail/sendmail.el
(defvar mail-from-style 'angles "\
@@ -30230,9 +27141,7 @@ If `angles', they look like:
Otherwise, most addresses look like `angles', but they look like
`parens' if `angles' would need quoting and `parens' would not.")
-
(custom-autoload 'mail-from-style "sendmail" t)
-
(defvar mail-specify-envelope-from nil "\
If non-nil, specify the envelope-from address when sending mail.
The value used to specify it is whatever is found in
@@ -30242,24 +27151,18 @@ On most systems, specifying the envelope-from address is a
privileged operation. This variable affects sendmail and
smtpmail -- if you use feedmail to send mail, see instead the
variable `feedmail-deduce-envelope-from'.")
-
(custom-autoload 'mail-specify-envelope-from "sendmail" t)
-
(defvar mail-self-blind nil "\
Non-nil means insert Bcc to self in messages to be sent.
This is done when the message is initialized,
so you can remove or alter the Bcc field to override the default.
If you are using `message-mode' to compose messages, customize the
variable `message-default-mail-headers' instead.")
-
(custom-autoload 'mail-self-blind "sendmail" t)
-
(defvar mail-interactive t "\
Non-nil means when sending a message wait for and display errors.
Otherwise, let mailer send back a message to report errors.")
-
(custom-autoload 'mail-interactive "sendmail" t)
-
(defvar send-mail-function (if (and (boundp 'smtpmail-smtp-server) smtpmail-smtp-server) #'smtpmail-send-it #'sendmail-query-once) "\
Function to call to send the current buffer as mail.
The headers should be delimited by a line which is
@@ -30267,65 +27170,48 @@ not a valid RFC 822 (or later) header or continuation line,
that matches the variable `mail-header-separator'.
This is used by the default mail-sending commands. See also
`message-send-mail-function' for use with the Message package.")
-
(custom-autoload 'send-mail-function "sendmail" t)
-
(defvar mail-header-separator (purecopy "--text follows this line--") "\
Line used to separate headers from text in messages being composed.")
-
(custom-autoload 'mail-header-separator "sendmail" t)
-
(defvar mail-archive-file-name nil "\
Name of file to write all outgoing messages in, or nil for none.
This is normally an mbox file, but for backwards compatibility may also
be a Babyl file.
If you are using `message-mode' to compose messages, customize the
variable `message-default-mail-headers' instead.")
-
(custom-autoload 'mail-archive-file-name "sendmail" t)
-
(defvar mail-default-reply-to nil "\
Address to insert as default Reply-To field of outgoing messages.
If nil, it will be initialized from the REPLYTO environment variable
when you first send mail.
If you are using `message-mode' to compose messages, customize the
variable `message-default-mail-headers' instead.")
-
(custom-autoload 'mail-default-reply-to "sendmail" t)
-
(defvar mail-personal-alias-file (purecopy "~/.mailrc") "\
If non-nil, the name of the user's personal mail alias file.
This file typically should be in same format as the `.mailrc' file used by
the `Mail' or `mailx' program.
This file need not actually exist.")
-
(custom-autoload 'mail-personal-alias-file "sendmail" t)
-
(defvar mail-setup-hook nil "\
Normal hook, run each time a new outgoing message is initialized.")
-
(custom-autoload 'mail-setup-hook "sendmail" t)
-
(defvar mail-aliases t "\
Alist of mail address aliases,
or t meaning should be initialized from your mail aliases file.
-\(The file's name is normally `~/.mailrc', but `mail-personal-alias-file'
+(The file's name is normally `~/.mailrc', but `mail-personal-alias-file'
can specify a different file name.)
The alias definitions in the file have this form:
alias ALIAS MEANING")
-
(defvar mail-yank-prefix "> " "\
Prefix insert on lines of yanked message being replied to.
If this is nil, use indentation, as specified by `mail-indentation-spaces'.")
-
(custom-autoload 'mail-yank-prefix "sendmail" t)
-
(defvar mail-indentation-spaces 3 "\
Number of spaces to insert at the beginning of each cited line.
Used by `mail-yank-original' via `mail-indent-citation'.")
-
(custom-autoload 'mail-indentation-spaces "sendmail" t)
-
(defvar mail-citation-hook nil "\
Hook for modifying a citation just inserted in the mail buffer.
Each hook function can find the citation between (point) and (mark t),
@@ -30336,17 +27222,13 @@ in the cited portion of the message.
If this hook is entirely empty (nil), a default action is taken
instead of no action.")
-
(custom-autoload 'mail-citation-hook "sendmail" t)
-
(defvar mail-citation-prefix-regexp (purecopy "\\([ \11]*\\(\\w\\|[_.]\\)+>+\\|[ \11]*[>|]\\)+") "\
Regular expression to match a citation prefix plus whitespace.
It should match whatever sort of citation prefixes you want to handle,
with whitespace before and after; it should also match just whitespace.
The default value matches citations like `foo-bar>' plus whitespace.")
-
(custom-autoload 'mail-citation-prefix-regexp "sendmail" t)
-
(defvar mail-signature t "\
Text inserted at end of mail buffer when a message is initialized.
If nil, no signature is inserted.
@@ -30356,43 +27238,32 @@ If a string, that string is inserted.
which is the standard way to delimit a signature in a message.)
Otherwise, it should be an expression; it is evaluated
and should insert whatever you want to insert.")
-
(custom-autoload 'mail-signature "sendmail" t)
-
(defvar mail-signature-file (purecopy "~/.signature") "\
File containing the text inserted at end of mail buffer.")
-
(custom-autoload 'mail-signature-file "sendmail" t)
-
(defvar mail-default-directory (purecopy "~/") "\
Value of `default-directory' for Mail mode buffers.
This directory is used for auto-save files of Mail mode buffers.
Note that Message mode does not use this variable; it auto-saves
in `message-auto-save-directory'.")
-
(custom-autoload 'mail-default-directory "sendmail" t)
-
(defvar mail-default-headers nil "\
A string containing header lines, to be inserted in outgoing messages.
It can contain newlines, and should end in one. It is inserted
before you edit the message, so you can edit or delete the lines.
If you are using `message-mode' to compose messages, customize the
variable `message-default-mail-headers' instead.")
-
(custom-autoload 'mail-default-headers "sendmail" t)
-
(autoload 'sendmail-query-once "sendmail" "\
Query for `send-mail-function' and send mail with it.
This also saves the value of `send-mail-function' via Customize." nil nil)
-
(define-mail-user-agent 'sendmail-user-agent #'sendmail-user-agent-compose #'mail-send-and-exit)
-
(autoload 'sendmail-user-agent-compose "sendmail" "\
-\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest IGNORED)" nil nil)
-
+(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-FUNCTION YANK-ACTION SEND-ACTIONS RETURN-ACTION &rest IGNORED)" nil nil)
(autoload 'mail-mode "sendmail" "\
Major mode for editing mail to be sent.
Like Text Mode but with these additional commands:
@@ -30415,22 +27286,18 @@ Here are commands that move to a header field (and create it if there isn't):
Turning on Mail mode runs the normal hooks `text-mode-hook' and
`mail-mode-hook' (in that order).
-\(fn)" t nil)
-
+(fn)" t nil)
(defvar mail-mailing-lists nil "\
List of mailing list addresses the user is subscribed to.
The variable is used to trigger insertion of the \"Mail-Followup-To\"
header when sending a message to a mailing list.")
-
(custom-autoload 'mail-mailing-lists "sendmail" t)
-
(defvar sendmail-coding-system nil "\
Coding system for encoding the outgoing mail.
This has higher priority than the default `buffer-file-coding-system'
and `default-sendmail-coding-system',
but lower priority than the local value of `buffer-file-coding-system'.
See also the function `select-message-coding-system'.")
-
(defvar default-sendmail-coding-system 'utf-8 "\
Default coding system for encoding the outgoing mail.
This variable is used only when `sendmail-coding-system' is nil.
@@ -30440,7 +27307,6 @@ User should not set this variable manually,
instead use `sendmail-coding-system' to get a constant encoding
of outgoing mails regardless of the current language environment.
See also the function `select-message-coding-system'.")
-
(autoload 'mail "sendmail" "\
Edit a message to be sent. Prefix arg means resume editing (don't erase).
When this function returns, the buffer `*mail*' is selected.
@@ -30489,154 +27355,28 @@ The seventh argument ACTIONS is a list of actions to take
when the message is sent, we apply FUNCTION to ARGS.
This is how Rmail arranges to mark messages `answered'.
-\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER ACTIONS RETURN-ACTION)" t nil)
-
+(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER ACTIONS RETURN-ACTION)" t nil)
(autoload 'mail-other-window "sendmail" "\
Like `mail' command, but display mail buffer in another window.
-\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil)
-
+(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil)
(autoload 'mail-other-frame "sendmail" "\
Like `mail' command, but display mail buffer in another frame.
-\(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil)
-
+(fn &optional NOERASE TO SUBJECT IN-REPLY-TO CC REPLYBUFFER SENDACTIONS)" t nil)
(register-definition-prefixes "sendmail" '("mail-" "sendmail-"))
-;;;***
-;;;### (autoloads nil "seq" "emacs-lisp/seq.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/seq.el
-(push (purecopy '(seq 2 23)) package--builtin-versions)
-
-(autoload 'seq-subseq "seq" "\
-Return the sequence of elements of SEQUENCE from START to END.
-END is exclusive.
-
-If END is omitted, it defaults to the length of the sequence. If
-START or END is negative, it counts from the end. Signal an
-error if START or END are outside of the sequence (i.e too large
-if positive or too small if negative).
-
-\(fn SEQUENCE START &optional END)" nil nil)
-
-(autoload 'seq-take "seq" "\
-Take the first N elements of SEQUENCE and return the result.
-The result is a sequence of the same type as SEQUENCE.
-
-If N is a negative integer or zero, an empty sequence is
-returned.
-
-\(fn SEQUENCE N)" nil nil)
-
-(autoload 'seq-sort-by "seq" "\
-Sort SEQUENCE using PRED as a comparison function.
-Elements of SEQUENCE are transformed by FUNCTION before being
-sorted. FUNCTION must be a function of one argument.
-
-\(fn FUNCTION PRED SEQUENCE)" nil nil)
-
-(autoload 'seq-filter "seq" "\
-Return a list of all elements for which (PRED element) is non-nil in SEQUENCE.
-
-\(fn PRED SEQUENCE)" nil nil)
-
-(autoload 'seq-remove "seq" "\
-Return a list of all the elements for which (PRED element) is nil in SEQUENCE.
-
-\(fn PRED SEQUENCE)" nil nil)
-
-(autoload 'seq-reduce "seq" "\
-Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
-
-Return the result of calling FUNCTION with INITIAL-VALUE and the
-first element of SEQUENCE, then calling FUNCTION with that result
-and the second element of SEQUENCE, then with that result and the
-third element of SEQUENCE, etc. FUNCTION will be called with
-INITIAL-VALUE (and then the accumulated value) as the first
-argument, and the elements from SEQUENCE as the second argument.
-
-If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called.
-\(fn FUNCTION SEQUENCE INITIAL-VALUE)" nil nil)
-
-(autoload 'seq-every-p "seq" "\
-Return non-nil if (PRED element) is non-nil for all elements of SEQUENCE.
-
-\(fn PRED SEQUENCE)" nil nil)
-
-(autoload 'seq-some "seq" "\
-Return non-nil if PRED is satisfied for at least one element of SEQUENCE.
-If so, return the first non-nil value returned by PRED.
-
-\(fn PRED SEQUENCE)" nil nil)
-
-(autoload 'seq-find "seq" "\
-Return the first element for which (PRED element) is non-nil in SEQUENCE.
-If no element is found, return DEFAULT.
-
-Note that `seq-find' has an ambiguity if the found element is
-identical to DEFAULT, as it cannot be known if an element was
-found or not.
-
-\(fn PRED SEQUENCE &optional DEFAULT)" nil nil)
-
-(autoload 'seq-position "seq" "\
-Return the index of the first element in SEQUENCE that is equal to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil.
-
-\(fn SEQUENCE ELT &optional TESTFN)" nil nil)
-
-(autoload 'seq-uniq "seq" "\
-Return a list of the elements of SEQUENCE with duplicates removed.
-TESTFN is used to compare elements, or `equal' if TESTFN is nil.
-
-\(fn SEQUENCE &optional TESTFN)" nil nil)
-
-(autoload 'seq-union "seq" "\
-Return a list of all elements that appear in either SEQUENCE1 or SEQUENCE2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil.
-
-\(fn SEQUENCE1 SEQUENCE2 &optional TESTFN)" nil nil)
-
-(autoload 'seq-intersection "seq" "\
-Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil.
-
-\(fn SEQUENCE1 SEQUENCE2 &optional TESTFN)" nil nil)
-
-(autoload 'seq-group-by "seq" "\
-Apply FUNCTION to each element of SEQUENCE.
-Separate the elements of SEQUENCE into an alist using the results as
-keys. Keys are compared using `equal'.
-
-\(fn FUNCTION SEQUENCE)" nil nil)
-
-(autoload 'seq-max "seq" "\
-Return the largest element of SEQUENCE.
-SEQUENCE must be a sequence of numbers or markers.
-
-\(fn SEQUENCE)" nil nil)
-
-(autoload 'seq-random-elt "seq" "\
-Return a random element from SEQUENCE.
-Signal an error if SEQUENCE is empty.
-
-\(fn SEQUENCE)" nil nil)
-
-(register-definition-prefixes "seq" '("seq-"))
+(push (purecopy '(seq 2 23)) package--builtin-versions)
-;;;***
-;;;### (autoloads nil "server" "server.el" (0 0 0 0))
;;; Generated autoloads from server.el
(put 'server-host 'risky-local-variable t)
-
(put 'server-port 'risky-local-variable t)
-
(put 'server-auth-dir 'risky-local-variable t)
-
(autoload 'server-start "server" "\
Allow this Emacs process to be a server for client processes.
This starts a server communications subprocess through which client
@@ -30657,15 +27397,13 @@ To force-start a server, do \\[server-force-delete] and then
To check from a Lisp program whether a server is running, use
the `server-process' variable.
-\(fn &optional LEAVE-DEAD INHIBIT-PROMPT)" t nil)
-
+(fn &optional LEAVE-DEAD INHIBIT-PROMPT)" t nil)
(autoload 'server-force-delete "server" "\
Unconditionally delete connection file for server NAME.
If server is running, it is first stopped.
NAME defaults to `server-name'. With argument, ask for NAME.
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(defvar server-mode nil "\
Non-nil if Server mode is enabled.
See the `server-mode' command
@@ -30673,32 +27411,29 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `server-mode'.")
-
(custom-autoload 'server-mode "server" nil)
-
(autoload 'server-mode "server" "\
Toggle Server mode.
-This is a minor mode. If called interactively, toggle the `Server
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+Server mode runs a process that accepts commands from the
+`emacsclient' program. See Info node `Emacs server' and
+`server-start' for details.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+This is a global minor mode. If called interactively, toggle the
+`Server mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='server-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Server mode runs a process that accepts commands from the
-`emacsclient' program. See Info node `Emacs server' and
-`server-start' for details.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'server-save-buffers-kill-terminal "server" "\
Offer to save each buffer, then kill the current client.
With ARG non-nil, silently save all file-visiting buffers, then kill.
@@ -30706,8 +27441,7 @@ With ARG non-nil, silently save all file-visiting buffers, then kill.
If emacsclient was started with a list of filenames to edit, then
only these files will be asked to be saved.
-\(fn ARG)" nil nil)
-
+(fn ARG)" nil nil)
(autoload 'server-stop-automatically "server" "\
Automatically stop server as specified by ARG.
@@ -30729,13 +27463,10 @@ Any other value of ARG will cause this function to signal an error.
This function is meant to be called from the user init file.
-\(fn ARG)" nil nil)
-
+(fn ARG)" nil nil)
(register-definition-prefixes "server" '("server-"))
-;;;***
-;;;### (autoloads nil "ses" "ses.el" (0 0 0 0))
;;; Generated autoloads from ses.el
(autoload 'ses-mode "ses" "\
@@ -30752,7 +27483,7 @@ contents of another cell. For example, you can sum a range of
cells with `(+ A1 A2 A3)'. There are specialized functions like
`ses+' (addition for ranges with empty cells), `ses-average' (for
performing calculations on cells), and `ses-range' and `ses-select'
-\(for extracting ranges of cells).
+(for extracting ranges of cells).
Each cell also has a print function that controls how it is
displayed.
@@ -30774,13 +27505,9 @@ part):
These are active only in the minibuffer, when entering or editing a
formula:
\\{ses-mode-edit-map}" t nil)
-
(register-definition-prefixes "ses" '("ses"))
-;;;***
-;;;### (autoloads nil "sgml-mode" "textmodes/sgml-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from textmodes/sgml-mode.el
(autoload 'sgml-mode "sgml-mode" "\
@@ -30802,8 +27529,7 @@ Do \\[describe-variable] sgml- SPC to see available variables.
Do \\[describe-key] on the following bindings to discover what they do.
\\{sgml-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'html-mode "sgml-mode" "\
Major mode based on SGML mode for editing HTML documents.
This allows inserting skeleton constructs used in hypertext documents with
@@ -30842,17 +27568,13 @@ To work around that, do:
\\{html-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "sgml-mode" '("html-" "sgml-"))
-;;;***
-;;;### (autoloads nil "sh-script" "progmodes/sh-script.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/sh-script.el
-(put 'sh-shell 'safe-local-variable 'symbolp)
+(put 'sh-shell 'safe-local-variable 'symbolp)
(autoload 'sh-mode "sh-script" "\
Major mode for editing shell scripts.
This mode works for many shells, since they all have roughly the same syntax,
@@ -30905,15 +27627,11 @@ indicate what shell it is use `sh-alias-alist' to translate.
If your shell gives error messages with line numbers, you can use \\[executable-interpret]
with your script for an edit-interpret-debug cycle.
-\(fn)" t nil)
-
+(fn)" t nil)
(defalias 'shell-script-mode 'sh-mode)
-
(register-definition-prefixes "sh-script" '("sh-"))
-;;;***
-;;;### (autoloads nil "shadow" "emacs-lisp/shadow.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/shadow.el
(autoload 'list-load-path-shadows "shadow" "\
@@ -30931,11 +27649,11 @@ the earlier.
For example, suppose `load-path' is set to
-\(\"/usr/share/emacs/site-lisp\" \"/usr/share/emacs/24.3/lisp\")
+(\"/usr/share/emacs/site-lisp\" \"/usr/share/emacs/24.3/lisp\")
and that each of these directories contains a file called XXX.el. Then
XXX.el in the site-lisp directory is referred to by all of:
-\(require \\='XXX), (autoload .... \"XXX\"), (load-library \"XXX\") etc.
+(require \\='XXX), (autoload .... \"XXX\"), (load-library \"XXX\") etc.
The first XXX.el file prevents Emacs from seeing the second (unless
the second is loaded explicitly via `load-file').
@@ -30951,20 +27669,17 @@ Emacs version).
This function performs these checks and flags all possible
shadowings. Because a .el file may exist without a corresponding .elc
-\(or vice-versa), these suffixes are essentially ignored. A file
+(or vice-versa), these suffixes are essentially ignored. A file
XXX.elc in an early directory (that does not contain XXX.el) is
considered to shadow a later file XXX.el, and vice-versa.
Shadowings are located by calling the (non-interactive) companion
function, `load-path-shadows-find'.
-\(fn &optional STRINGP)" t nil)
-
+(fn &optional STRINGP)" t nil)
(register-definition-prefixes "shadow" '("load-path-shadows-"))
-;;;***
-;;;### (autoloads nil "shadowfile" "shadowfile.el" (0 0 0 0))
;;; Generated autoloads from shadowfile.el
(autoload 'shadow-define-cluster "shadowfile" "\
@@ -30975,14 +27690,12 @@ defined by a name, the network address of a primary host (the one we copy
files to), and a regular expression that matches the hostnames of all the
sites in the cluster.
-\(fn NAME)" t nil)
-
+(fn NAME)" t nil)
(autoload 'shadow-define-literal-group "shadowfile" "\
Declare a single file to be shared between sites.
It may have different filenames on each site. When this file is edited, the
new version will be copied to each of the other locations. Sites can be
specific hostnames, or names of clusters (see `shadow-define-cluster')." t nil)
-
(autoload 'shadow-define-regexp-group "shadowfile" "\
Make each of a group of files be shared between hosts.
Prompts for regular expression; files matching this are shared between a list
@@ -30990,15 +27703,16 @@ of sites, which are also prompted for. The filenames must be identical on all
hosts (if they aren't, use `shadow-define-literal-group' instead of this
function). Each site can be either a hostname or the name of a cluster (see
`shadow-define-cluster')." t nil)
-
(autoload 'shadow-initialize "shadowfile" "\
Set up file shadowing." t nil)
-
(register-definition-prefixes "shadowfile" '("shadow"))
-;;;***
-;;;### (autoloads nil "shell" "shell.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/shell.el
+
+(register-definition-prefixes "ede/shell" '("ede-shell-run-command"))
+
+
;;; Generated autoloads from shell.el
(defvar shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe") "\
@@ -31007,16 +27721,13 @@ don't handle the backslash as a quote character. For shells that
match this regexp, Emacs will write out the command history when the
shell finishes, and won't remove backslashes when it unquotes shell
arguments.")
-
(custom-autoload 'shell-dumb-shell-regexp "shell" t)
-
(autoload 'split-string-shell-command "shell" "\
Split STRING (a shell command) into a list of strings.
General shell syntax, like single and double quoting, as well as
backslash quoting, is respected.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'shell "shell" "\
Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*').
Interactively, a prefix arg means to prompt for BUFFER.
@@ -31028,6 +27739,8 @@ If BUFFER exists and shell process is running, just switch to BUFFER.
Program used comes from variable `explicit-shell-file-name',
or (if that is nil) from the ESHELL environment variable,
or (if that is nil) from `shell-file-name'.
+Non-interactively, it can also be specified via the FILE-NAME arg.
+
If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
it is given as initial input (but this may be lost, due to a timing
error, if the shell discards input when it starts up).
@@ -31049,103 +27762,149 @@ Otherwise, one argument `-i' is passed to the shell.
Make the shell buffer the current buffer, and return it.
-\(Type \\[describe-mode] in the shell buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the shell buffer for a list of commands.)
+(fn &optional BUFFER FILE-NAME)" t nil)
(register-definition-prefixes "shell" '("dirs" "explicit-" "shell-"))
-;;;***
-;;;### (autoloads nil "shortdoc" "emacs-lisp/shortdoc.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/shortdoc.el
+(defvar shortdoc--groups nil)
+(defmacro define-short-documentation-group (group &rest functions) "\
+Add GROUP to the list of defined documentation groups.
+FUNCTIONS is a list of elements on the form:
+
+ (FUNC
+ :no-manual BOOL
+ :args ARGS
+ :eval EVAL
+ :no-eval EXAMPLE-FORM
+ :no-value EXAMPLE-FORM
+ :no-eval* EXAMPLE-FORM
+ :result RESULT-FORM
+ :result-string RESULT-STRING
+ :eg-result RESULT-FORM
+ :eg-result-string RESULT-STRING)
+
+FUNC is the function being documented.
+
+NO-MANUAL should be non-nil if FUNC isn't documented in the
+manual.
+
+ARGS is optional list of function FUNC's arguments. FUNC's
+signature is displayed automatically if ARGS is not present.
+Specifying ARGS might be useful where you don't want to document
+some of the uncommon arguments a function might have.
+
+While the `:no-manual' and `:args' property can be used for
+any (FUNC ..) form, all of the other properties shown above
+cannot be used simultaneously in such a form.
+
+Here are some common forms with examples of properties that go
+together:
+
+1. Document a form or string, and its evaluated return value.
+ (FUNC
+ :eval EVAL)
+
+If EVAL is a string, it will be inserted as is, and then that
+string will be `read' and evaluated.
+
+2. Document a form or string, but manually document its evaluation
+ result. The provided form will not be evaluated.
+
+ (FUNC
+ :no-eval EXAMPLE-FORM
+ :result RESULT-FORM) ;Use `:result-string' if value is in string form
+
+Using `:no-value' is the same as using `:no-eval'.
+
+Use `:no-eval*' instead of `:no-eval' where the successful
+execution of the documented form depends on some conditions.
+
+3. Document a form or string EXAMPLE-FORM. Also manually
+ document an example result. This result could be unrelated to
+ the documented form.
+
+ (FUNC
+ :no-eval EXAMPLE-FORM
+ :eg-result RESULT-FORM) ;Use `:eg-result-string' if value is in string form
+
+A FUNC form can have any number of `:no-eval' (or `:no-value'),
+`:no-eval*', `:result', `:result-string', `:eg-result' and
+`:eg-result-string' properties." (declare (indent defun)) `(progn (setq shortdoc--groups (delq (assq ',group shortdoc--groups) shortdoc--groups)) (push (cons ',group ',functions) shortdoc--groups)))
(autoload 'shortdoc-display-group "shortdoc" "\
Pop to a buffer with short documentation summary for functions in GROUP.
If FUNCTION is non-nil, place point on the entry for FUNCTION (if any).
+If SAME-WINDOW, don't pop to a new window.
-\(fn GROUP &optional FUNCTION)" t nil)
+(fn GROUP &optional FUNCTION SAME-WINDOW)" t nil)
+(defalias 'shortdoc #'shortdoc-display-group)
+(register-definition-prefixes "shortdoc" '("alist" "buffer" "file" "hash-table" "keymaps" "list" "number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" "text-properties" "vector"))
-(register-definition-prefixes "shortdoc" '("alist" "buffer" "define-short-documentation-group" "file" "hash-table" "keymaps" "list" "number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" "text-properties" "vector"))
-
-;;;***
-;;;### (autoloads nil "shr" "net/shr.el" (0 0 0 0))
;;; Generated autoloads from net/shr.el
(autoload 'shr-render-region "shr" "\
Display the HTML rendering of the region between BEGIN and END.
-\(fn BEGIN END &optional BUFFER)" t nil)
-
+(fn BEGIN END &optional BUFFER)" t nil)
(autoload 'shr-insert-document "shr" "\
Render the parsed document DOM into the current buffer.
DOM should be a parse tree as generated by
`libxml-parse-html-region' or similar.
-\(fn DOM)" nil nil)
-
+(fn DOM)" nil nil)
(register-definition-prefixes "shr" '("shr-"))
-;;;***
-;;;### (autoloads nil "shr-color" "net/shr-color.el" (0 0 0 0))
;;; Generated autoloads from net/shr-color.el
(register-definition-prefixes "shr-color" '("shr-color-"))
-;;;***
-;;;### (autoloads nil "sieve" "net/sieve.el" (0 0 0 0))
;;; Generated autoloads from net/sieve.el
(autoload 'sieve-manage "sieve" "\
-\(fn SERVER &optional PORT)" t nil)
-
+(fn SERVER &optional PORT)" t nil)
(autoload 'sieve-upload "sieve" "\
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(autoload 'sieve-upload-and-bury "sieve" "\
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(autoload 'sieve-upload-and-kill "sieve" "\
-\(fn &optional NAME)" t nil)
-
+(fn &optional NAME)" t nil)
(register-definition-prefixes "sieve" '("sieve-"))
-;;;***
-;;;### (autoloads nil "sieve-manage" "net/sieve-manage.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/sieve-manage.el
(register-definition-prefixes "sieve-manage" '("sieve-"))
-;;;***
-;;;### (autoloads nil "sieve-mode" "net/sieve-mode.el" (0 0 0 0))
;;; Generated autoloads from net/sieve-mode.el
(autoload 'sieve-mode "sieve-mode" "\
Major mode for editing Sieve code.
Turning on Sieve mode runs `sieve-mode-hook'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "sieve-mode" '("sieve-"))
-;;;***
-;;;### (autoloads nil "simula" "progmodes/simula.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/simple.el
+
+(register-definition-prefixes "ede/simple" '("ede-simple-"))
+
+
;;; Generated autoloads from progmodes/simula.el
(autoload 'simula-mode "simula" "\
@@ -31186,29 +27945,27 @@ Variables controlling indentation style:
Turning on SIMULA mode calls the value of the variable simula-mode-hook
with no arguments, if that value is non-nil.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "simula" '("simula-"))
-;;;***
-;;;### (autoloads nil "skeleton" "skeleton.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/sisheng.el
+
+(register-definition-prefixes "quail/sisheng" '("quail-make-sisheng-rules" "sisheng-"))
+
+
;;; Generated autoloads from skeleton.el
(defvar skeleton-filter-function 'identity "\
Function for transforming a skeleton proxy's aliases' variable value.")
-
(autoload 'define-skeleton "skeleton" "\
Define a user-configurable COMMAND that enters a statement skeleton.
DOCUMENTATION is that of the command.
SKELETON is as defined under `skeleton-insert'.
-\(fn COMMAND DOCUMENTATION &rest SKELETON)" nil t)
-
-(function-put 'define-skeleton 'doc-string-elt '2)
-
+(fn COMMAND DOCUMENTATION &rest SKELETON)" nil t)
+(function-put 'define-skeleton 'doc-string-elt 2)
(function-put 'define-skeleton 'lisp-indent-function 'defun)
-
(autoload 'skeleton-proxy-new "skeleton" "\
Insert SKELETON.
Prefix ARG allows wrapping around words or regions (see `skeleton-insert').
@@ -31220,13 +27977,12 @@ This command can also be an abbrev expansion (3rd and 4th columns in
Optional second argument STR may also be a string which will be the value
of `str' whereas the skeleton's interactor is then ignored.
-\(fn SKELETON &optional STR ARG)" nil nil)
-
+(fn SKELETON &optional STR ARG)" nil nil)
(autoload 'skeleton-insert "skeleton" "\
Insert the complex statement skeleton SKELETON describes very concisely.
With optional second argument REGIONS, wrap first interesting point
-\(`_') in skeleton around next REGIONS words, if REGIONS is positive.
+(`_') in skeleton around next REGIONS words, if REGIONS is positive.
If REGIONS is negative, wrap REGIONS preceding interregions into first
REGIONS interesting positions (successive `_'s) in skeleton.
@@ -31293,8 +28049,7 @@ available:
input initial input (string or cons with index) while reading str
v1, v2 local variables for memorizing anything you want
-\(fn SKELETON &optional REGIONS STR)" nil nil)
-
+(fn SKELETON &optional REGIONS STR)" nil nil)
(autoload 'skeleton-pair-insert-maybe "skeleton" "\
Insert the character you type ARG times.
@@ -31310,13 +28065,10 @@ the defaults are used. These are (), [], {}, <> and (grave
accent, apostrophe) for the paired ones, and the same character
twice for the others.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "skeleton" '("skeleton-"))
-;;;***
-;;;### (autoloads nil "smerge-mode" "vc/smerge-mode.el" (0 0 0 0))
;;; Generated autoloads from vc/smerge-mode.el
(autoload 'smerge-refine-regions "smerge-mode" "\
@@ -31334,92 +28086,74 @@ If non-nil, PREPROC is called with no argument in a buffer that contains
a copy of a region, just before preparing it to for `diff'. It can be
used to replace chars to try and eliminate some spurious differences.
-\(fn BEG1 END1 BEG2 END2 PROPS-C &optional PREPROC PROPS-R PROPS-A)" nil nil)
-
+(fn BEG1 END1 BEG2 END2 PROPS-C &optional PREPROC PROPS-R PROPS-A)" nil nil)
(autoload 'smerge-ediff "smerge-mode" "\
Invoke ediff to resolve the conflicts.
NAME-UPPER, NAME-LOWER, and NAME-BASE, if non-nil, are used for the
buffer names.
-\(fn &optional NAME-UPPER NAME-LOWER NAME-BASE)" t nil)
-
+(fn &optional NAME-UPPER NAME-LOWER NAME-BASE)" t nil)
(autoload 'smerge-mode "smerge-mode" "\
Minor mode to simplify editing output from the diff3 program.
-This is a minor mode. If called interactively, toggle the `SMerge
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+\\{smerge-mode-map}
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+This is a minor mode. If called interactively, toggle the
+`SMerge mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `smerge-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\\{smerge-mode-map}
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'smerge-start-session "smerge-mode" "\
Turn on `smerge-mode' and move point to first conflict marker.
If no conflict maker is found, turn off `smerge-mode'.
-\(fn &optional INTERACTIVELY)" t nil)
-
+(fn &optional INTERACTIVELY)" t nil)
(register-definition-prefixes "smerge-mode" '("smerge-"))
-;;;***
-;;;### (autoloads nil "smie" "emacs-lisp/smie.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/smie.el
(register-definition-prefixes "smie" '("smie-"))
-;;;***
-;;;### (autoloads nil "smiley" "gnus/smiley.el" (0 0 0 0))
;;; Generated autoloads from gnus/smiley.el
(autoload 'smiley-region "smiley" "\
Replace in the region `smiley-regexp-alist' matches with corresponding images.
A list of images is returned.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'smiley-buffer "smiley" "\
Run `smiley-region' at the BUFFER, specified in the argument or
interactively. If there's no argument, do it at the current buffer.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(register-definition-prefixes "smiley" '("gnus-smiley-file-types" "smiley-"))
-;;;***
-;;;### (autoloads nil "smime" "gnus/smime.el" (0 0 0 0))
;;; Generated autoloads from gnus/smime.el
(register-definition-prefixes "smime" '("smime"))
-;;;***
-;;;### (autoloads nil "smtpmail" "mail/smtpmail.el" (0 0 0 0))
;;; Generated autoloads from mail/smtpmail.el
(autoload 'smtpmail-send-it "smtpmail" nil nil nil)
-
(autoload 'smtpmail-send-queued-mail "smtpmail" "\
Send mail that was queued as a result of setting `smtpmail-queue-mail'." t nil)
-
(register-definition-prefixes "smtpmail" '("smtpmail-"))
-;;;***
-;;;### (autoloads nil "snake" "play/snake.el" (0 0 0 0))
;;; Generated autoloads from play/snake.el
(autoload 'snake "snake" "\
@@ -31437,12 +28171,9 @@ Snake mode keybindings:
\\[snake-move-right] Makes the snake move right
\\[snake-move-up] Makes the snake move up
\\[snake-move-down] Makes the snake move down" t nil)
-
(register-definition-prefixes "snake" '("snake-"))
-;;;***
-;;;### (autoloads nil "snmp-mode" "net/snmp-mode.el" (0 0 0 0))
;;; Generated autoloads from net/snmp-mode.el
(autoload 'snmp-mode "snmp-mode" "\
@@ -31454,7 +28185,6 @@ Delete converts tabs to spaces as it moves back.
\\{snmp-mode-map}
Turning on `snmp-mode' runs the hooks in `snmp-common-mode-hook', then
`snmp-mode-hook'." t nil)
-
(autoload 'snmpv2-mode "snmp-mode" "\
Major mode for editing SNMPv2 MIBs.
Expression and list commands understand all C brackets.
@@ -31464,46 +28194,40 @@ Delete converts tabs to spaces as it moves back.
\\{snmp-mode-map}
Turning on `snmp-mode' runs the hooks in `snmp-common-mode-hook',
then `snmpv2-mode-hook'." t nil)
-
(register-definition-prefixes "snmp-mode" '("snmp"))
-;;;***
-;;;### (autoloads nil "so-long" "so-long.el" (0 0 0 0))
;;; Generated autoloads from so-long.el
-(push (purecopy '(so-long 1 1 2)) package--builtin-versions)
+(push (purecopy '(so-long 1 1 2)) package--builtin-versions)
(autoload 'so-long-commentary "so-long" "\
View the `so-long' library's documentation in `outline-mode'." t nil)
-
(autoload 'so-long-customize "so-long" "\
Open the customization group `so-long'." t nil)
-
(autoload 'so-long-minor-mode "so-long" "\
This is the minor mode equivalent of `so-long-mode'.
-This is a minor mode. If called interactively, toggle the `So-Long
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `so-long-minor-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Any active minor modes listed in `so-long-minor-modes' are disabled for the
current buffer, and buffer-local values are assigned to variables in accordance
with `so-long-variable-overrides'.
This minor mode is a standard `so-long-action' option.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`So-Long minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `so-long-minor-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'so-long-mode "so-long" "\
This major mode is the default `so-long-action' option.
@@ -31529,10 +28253,9 @@ values), despite potential performance issues, type \\[so-long-revert].
Use \\[so-long-commentary] for more information.
Use \\[so-long-customize] to open the customization group `so-long' to
-configure the behaviour.
-
-\(fn)" t nil)
+configure the behavior.
+(fn)" t nil)
(autoload 'so-long "so-long" "\
Invoke `so-long-action' and run `so-long-hook'.
@@ -31548,13 +28271,11 @@ With a prefix argument, select the action to use interactively.
If an action was already active in the buffer, it will be reverted before
invoking the new action.
-\(fn &optional ACTION)" t nil)
-
+(fn &optional ACTION)" t nil)
(autoload 'so-long-enable "so-long" "\
Enable the `so-long' library's functionality.
Equivalent to calling (global-so-long-mode 1)" t nil)
-
(defvar global-so-long-mode nil "\
Non-nil if Global So-Long mode is enabled.
See the `global-so-long-mode' command
@@ -31562,26 +28283,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-so-long-mode'.")
-
(custom-autoload 'global-so-long-mode "so-long" nil)
-
(autoload 'global-so-long-mode "so-long" "\
Toggle automated performance mitigations for files with long lines.
-This is a minor mode. If called interactively, toggle the `Global
-So-Long mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-so-long-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Many Emacs modes struggle with buffers which contain excessively long lines,
and may consequently cause unacceptable performance issues.
@@ -31595,38 +28300,42 @@ When such files are detected by `so-long-predicate', we invoke the selected
Use \\[so-long-commentary] for more information.
Use \\[so-long-customize] to open the customization group `so-long' to
-configure the behaviour.
+configure the behavior.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Global So-Long mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='global-so-long-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(register-definition-prefixes "so-long" '("so-long-" "turn-o"))
-;;;***
-;;;### (autoloads nil "soap-client" "net/soap-client.el" (0 0 0 0))
;;; Generated autoloads from net/soap-client.el
-(push (purecopy '(soap-client 3 2 0)) package--builtin-versions)
+(push (purecopy '(soap-client 3 2 1)) package--builtin-versions)
(register-definition-prefixes "soap-client" '("soap-"))
-;;;***
-;;;### (autoloads nil "soap-inspect" "net/soap-inspect.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/soap-inspect.el
(register-definition-prefixes "soap-inspect" '("soap-"))
-;;;***
-;;;### (autoloads nil "socks" "net/socks.el" (0 0 0 0))
;;; Generated autoloads from net/socks.el
(register-definition-prefixes "socks" '("socks-"))
-;;;***
-;;;### (autoloads nil "solar" "calendar/solar.el" (0 0 0 0))
;;; Generated autoloads from calendar/solar.el
(autoload 'sunrise-sunset "solar" "\
@@ -31637,13 +28346,10 @@ longitude, latitude, time zone, and date, and always use standard time.
This function is suitable for execution in an init file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "solar" '("calendar-" "diary-sunrise-sunset" "solar-"))
-;;;***
-;;;### (autoloads nil "solitaire" "play/solitaire.el" (0 0 0 0))
;;; Generated autoloads from play/solitaire.el
(autoload 'solitaire "solitaire" "\
@@ -31655,7 +28361,7 @@ Move around the board using the cursor keys.
Move stones using \\[solitaire-move] followed by a direction key.
Undo moves using \\[solitaire-undo].
Check for possible moves using \\[solitaire-do-check].
-\(The variable `solitaire-auto-eval' controls whether to automatically
+(The variable `solitaire-auto-eval' controls whether to automatically
check after each move or undo.)
What is Solitaire?
@@ -31714,16 +28420,18 @@ Pick your favorite shortcuts:
\\{solitaire-mode-map}
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(register-definition-prefixes "solitaire" '("solitaire-"))
-;;;***
-;;;### (autoloads nil "sort" "sort.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/sort.el
+
+(register-definition-prefixes "semantic/sort" '("semantic-"))
+
+
;;; Generated autoloads from sort.el
-(put 'sort-fold-case 'safe-local-variable 'booleanp)
+(put 'sort-fold-case 'safe-local-variable 'booleanp)
(autoload 'sort-subr "sort" "\
General text sorting routine to divide buffer into records and sort them.
@@ -31768,8 +28476,7 @@ the keys are numbers, with `compare-buffer-substrings' if the
keys are cons cells (the car and cdr of each cons cell are taken
as start and end positions), and with `string<' otherwise.
-\(fn REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN PREDICATE)" nil nil)
-
+(fn REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN PREDICATE)" nil nil)
(autoload 'sort-lines "sort" "\
Sort lines in region alphabetically; REVERSE non-nil means descending order.
Interactively, REVERSE is the prefix argument, and BEG and END are the region.
@@ -31778,8 +28485,7 @@ REVERSE (non-nil means reverse order), BEG and END (region to sort).
The variable `sort-fold-case' determines whether alphabetic case affects
the sort order.
-\(fn REVERSE BEG END)" t nil)
-
+(fn REVERSE BEG END)" t nil)
(autoload 'sort-paragraphs "sort" "\
Sort paragraphs in region alphabetically; argument means descending order.
Called from a program, there are three arguments:
@@ -31787,8 +28493,7 @@ REVERSE (non-nil means reverse order), BEG and END (region to sort).
The variable `sort-fold-case' determines whether alphabetic case affects
the sort order.
-\(fn REVERSE BEG END)" t nil)
-
+(fn REVERSE BEG END)" t nil)
(autoload 'sort-pages "sort" "\
Sort pages in region alphabetically; argument means descending order.
Called from a program, there are three arguments:
@@ -31796,9 +28501,8 @@ REVERSE (non-nil means reverse order), BEG and END (region to sort).
The variable `sort-fold-case' determines whether alphabetic case affects
the sort order.
-\(fn REVERSE BEG END)" t nil)
+(fn REVERSE BEG END)" t nil)
(put 'sort-numeric-base 'safe-local-variable 'integerp)
-
(autoload 'sort-numeric-fields "sort" "\
Sort lines in region numerically by the ARGth field of each line.
Fields are separated by whitespace and numbered from 1 up.
@@ -31809,8 +28513,7 @@ With a negative arg, sorts by the ARGth field counted from the right.
Called from a program, there are three arguments:
FIELD, BEG and END. BEG and END specify region to sort.
-\(fn FIELD BEG END)" t nil)
-
+(fn FIELD BEG END)" t nil)
(autoload 'sort-fields "sort" "\
Sort lines in region lexicographically by the ARGth field of each line.
Fields are separated by whitespace and numbered from 1 up.
@@ -31820,8 +28523,7 @@ FIELD, BEG and END. BEG and END specify region to sort.
The variable `sort-fold-case' determines whether alphabetic case affects
the sort order.
-\(fn FIELD BEG END)" t nil)
-
+(fn FIELD BEG END)" t nil)
(autoload 'sort-regexp-fields "sort" "\
Sort the text in the region lexicographically.
If called interactively, prompt for two regular expressions,
@@ -31848,8 +28550,7 @@ For example: to sort lines in the region by the first word on each line
starting with the letter \"f\",
RECORD-REGEXP would be \"^.*$\" and KEY would be \"\\\\=\\<f\\\\w*\\\\>\"
-\(fn REVERSE RECORD-REGEXP KEY-REGEXP BEG END)" t nil)
-
+(fn REVERSE RECORD-REGEXP KEY-REGEXP BEG END)" t nil)
(autoload 'sort-columns "sort" "\
Sort lines in region alphabetically by a certain range of columns.
For the purpose of this command, the region BEG...END includes
@@ -31865,8 +28566,7 @@ and it doesn't know how to handle that. Also, when possible,
it uses the `sort' utility program, which doesn't understand tabs.
Use \\[untabify] to convert tabs to spaces before sorting.
-\(fn REVERSE &optional BEG END)" t nil)
-
+(fn REVERSE &optional BEG END)" t nil)
(autoload 'reverse-region "sort" "\
Reverse the order of lines in a region.
When called from Lisp, takes two point or marker arguments, BEG and END.
@@ -31875,8 +28575,7 @@ to be reversed is the line starting after BEG.
If END is not at the end of a line, the last line to be reversed
is the one that ends before END.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'delete-duplicate-lines "sort" "\
Delete all but one copy of any identical lines in the region.
Non-interactively, arguments BEG and END delimit the region.
@@ -31896,20 +28595,20 @@ If the argument KEEP-BLANKS is non-nil (interactively, with a
Returns the number of deleted lines. Interactively, or if INTERACTIVE
is non-nil, it also prints a message describing the number of deletions.
-\(fn BEG END &optional REVERSE ADJACENT KEEP-BLANKS INTERACTIVE)" t nil)
-
+(fn BEG END &optional REVERSE ADJACENT KEEP-BLANKS INTERACTIVE)" t nil)
(register-definition-prefixes "sort" '("sort-"))
-;;;***
-;;;### (autoloads nil "soundex" "soundex.el" (0 0 0 0))
;;; Generated autoloads from soundex.el
(register-definition-prefixes "soundex" '("soundex"))
-;;;***
-;;;### (autoloads nil "spam" "gnus/spam.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/source.el
+
+(register-definition-prefixes "ede/source" '("ede-source"))
+
+
;;; Generated autoloads from gnus/spam.el
(autoload 'spam-initialize "spam" "\
@@ -31919,14 +28618,10 @@ can call `spam-initialize' before you set spam-use-* variables on
explicitly, and matters only if you need the extra headers
installed through `spam-necessary-extra-headers'.
-\(fn &rest SYMBOLS)" t nil)
-
+(fn &rest SYMBOLS)" t nil)
(register-definition-prefixes "spam" '(":keymap" "spam-"))
-;;;***
-;;;### (autoloads nil "spam-report" "gnus/spam-report.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from gnus/spam-report.el
(autoload 'spam-report-process-queue "spam-report" "\
@@ -31936,55 +28631,48 @@ If FILE is given, use it instead of `spam-report-requests-file'.
If KEEP is t, leave old requests in the file. If KEEP is the
symbol `ask', query before flushing the queue file.
-\(fn &optional FILE KEEP)" t nil)
-
+(fn &optional FILE KEEP)" t nil)
(autoload 'spam-report-url-ping-mm-url "spam-report" "\
Ping a host through HTTP, addressing a specific GET resource.
Use the external program specified in `mm-url-program' to connect
to server.
-\(fn HOST REPORT)" nil nil)
-
+(fn HOST REPORT)" nil nil)
(autoload 'spam-report-url-to-file "spam-report" "\
Collect spam report requests in `spam-report-requests-file'.
Customize `spam-report-url-ping-function' to use this function.
-\(fn HOST REPORT)" nil nil)
-
+(fn HOST REPORT)" nil nil)
(autoload 'spam-report-agentize "spam-report" "\
Add spam-report support to the Agent.
Spam reports will be queued with \\[spam-report-url-to-file] when
the Agent is unplugged, and will be submitted in a batch when the
Agent is plugged." t nil)
-
(autoload 'spam-report-deagentize "spam-report" "\
Remove spam-report support from the Agent.
Spam reports will be queued with the method used when
\\[spam-report-agentize] was run." t nil)
-
(register-definition-prefixes "spam-report" '("spam-report-"))
-;;;***
-;;;### (autoloads nil "spam-stat" "gnus/spam-stat.el" (0 0 0 0))
;;; Generated autoloads from gnus/spam-stat.el
(register-definition-prefixes "spam-stat" '("spam-stat" "with-spam-stat-max-buffer-size"))
-;;;***
-;;;### (autoloads nil "spam-wash" "gnus/spam-wash.el" (0 0 0 0))
;;; Generated autoloads from gnus/spam-wash.el
(register-definition-prefixes "spam-wash" '("spam-"))
-;;;***
-;;;### (autoloads nil "speedbar" "speedbar.el" (0 0 0 0))
+;;; Generated autoloads from cedet/ede/speedbar.el
+
+(register-definition-prefixes "ede/speedbar" '("ede-"))
+
+
;;; Generated autoloads from speedbar.el
(defalias 'speedbar 'speedbar-frame-mode)
-
(autoload 'speedbar-frame-mode "speedbar" "\
Enable or disable speedbar. Positive ARG means turn on, negative turn off.
A nil ARG means toggle. Once the speedbar frame is activated, a buffer in
@@ -31993,34 +28681,26 @@ supported at a time.
`speedbar-before-popup-hook' is called before popping up the speedbar frame.
`speedbar-before-delete-hook' is called before the frame is deleted.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'speedbar-get-focus "speedbar" "\
Change frame focus to or from the speedbar frame.
If the selected frame is not speedbar, then speedbar frame is
selected. If the speedbar frame is active, then select the attached frame." t nil)
-
(register-definition-prefixes "speedbar" '("speedbar-"))
-;;;***
-;;;### (autoloads nil "spook" "play/spook.el" (0 0 0 0))
;;; Generated autoloads from play/spook.el
(autoload 'spook "spook" "\
Add that special touch of class to your outgoing mail." t nil)
-
(autoload 'snarf-spooks "spook" "\
Return a vector containing the lines from `spook-phrases-file'." nil nil)
-
(register-definition-prefixes "spook" '("spook-phrase"))
-;;;***
-;;;### (autoloads nil "sql" "progmodes/sql.el" (0 0 0 0))
;;; Generated autoloads from progmodes/sql.el
-(push (purecopy '(sql 3 6)) package--builtin-versions)
+(push (purecopy '(sql 3 6)) package--builtin-versions)
(autoload 'sql-add-product-keywords "sql" "\
Add highlighting KEYWORDS for SQL PRODUCT.
@@ -32040,8 +28720,7 @@ For example:
adds a fontification pattern to fontify identifiers ending in
`_t' as data types.
-\(fn PRODUCT KEYWORDS &optional APPEND)" nil nil)
-
+(fn PRODUCT KEYWORDS &optional APPEND)" nil nil)
(autoload 'sql-mode "sql" "\
Major mode to edit SQL.
@@ -32066,12 +28745,11 @@ Note that SQL doesn't have an escape character unless you specify
one. If you specify backslash as escape character in SQL, you
must tell Emacs. Here's how to do that in your init file:
-\(add-hook \\='sql-mode-hook
+(add-hook \\='sql-mode-hook
(lambda ()
(modify-syntax-entry ?\\\\ \"\\\\\" sql-mode-syntax-table)))
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'sql-connect "sql" "\
Connect to an interactive session using CONNECTION settings.
@@ -32081,8 +28759,7 @@ their settings.
The user will not be prompted for any login parameters if a value
is specified in the connection settings.
-\(fn CONNECTION &optional BUF-NAME)" t nil)
-
+(fn CONNECTION &optional BUF-NAME)" t nil)
(autoload 'sql-product-interactive "sql" "\
Run PRODUCT interpreter as an inferior process.
@@ -32094,10 +28771,9 @@ To specify the SQL product, prefix the call with
the call to \\[sql-product-interactive] with
\\[universal-argument] \\[universal-argument].
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional PRODUCT NEW-NAME)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional PRODUCT NEW-NAME)" t nil)
(autoload 'sql-oracle "sql" "\
Run sqlplus by Oracle as an inferior process.
@@ -32125,10 +28801,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-sybase "sql" "\
Run isql by Sybase as an inferior process.
@@ -32156,10 +28831,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-informix "sql" "\
Run dbaccess by Informix as an inferior process.
@@ -32185,10 +28859,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-sqlite "sql" "\
Run sqlite as an inferior process.
@@ -32218,10 +28891,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-mysql "sql" "\
Run mysql by TcX as an inferior process.
@@ -32251,10 +28923,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-mariadb "sql" "\
Run mysql by MariaDB as an inferior process.
@@ -32284,10 +28955,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-solid "sql" "\
Run solsql by Solid as an inferior process.
@@ -32314,10 +28984,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-ingres "sql" "\
Run sql by Ingres as an inferior process.
@@ -32343,10 +29012,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-ms "sql" "\
Run osql by Microsoft as an inferior process.
@@ -32374,10 +29042,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-postgres "sql" "\
Run psql by Postgres as an inferior process.
@@ -32407,12 +29074,11 @@ The default comes from `process-coding-system-alist' and
your might try undecided-dos as a coding system. If this doesn't help,
Try to set `comint-output-filter-functions' like this:
-\(add-hook \\='comint-output-filter-functions #\\='comint-strip-ctrl-m \\='append)
-
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(add-hook \\='comint-output-filter-functions #\\='comint-strip-ctrl-m \\='append)
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-interbase "sql" "\
Run isql by Interbase as an inferior process.
@@ -32439,10 +29105,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-db2 "sql" "\
Run db2 by IBM as an inferior process.
@@ -32473,10 +29138,9 @@ in the SQL buffer, after you start the process.
The default comes from `process-coding-system-alist' and
`default-process-coding-system'.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-linter "sql" "\
Run inl by RELEX as an inferior process.
@@ -32504,134 +29168,83 @@ before \\[sql-linter]. Once session has started,
\\[sql-rename-buffer] can be called separately to rename the
buffer.
-\(Type \\[describe-mode] in the SQL buffer for a list of commands.)
-
-\(fn &optional BUFFER)" t nil)
+(Type \\[describe-mode] in the SQL buffer for a list of commands.)
+(fn &optional BUFFER)" t nil)
(autoload 'sql-vertica "sql" "\
Run vsql as an inferior process.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(register-definition-prefixes "sql" '("sql-"))
-;;;***
-;;;### (autoloads nil "sqlite" "sqlite.el" (0 0 0 0))
;;; Generated autoloads from sqlite.el
(register-definition-prefixes "sqlite" '("with-sqlite-transaction"))
-;;;***
-;;;### (autoloads nil "sqlite-mode" "sqlite-mode.el" (0 0 0 0))
;;; Generated autoloads from sqlite-mode.el
(autoload 'sqlite-mode-open-file "sqlite-mode" "\
Browse the contents of an sqlite file.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(register-definition-prefixes "sqlite-mode" '("sqlite-"))
-;;;***
-
-;;;### (autoloads nil "srecode" "cedet/srecode.el" (0 0 0 0))
-;;; Generated autoloads from cedet/srecode.el
-(push (purecopy '(srecode 1 2)) package--builtin-versions)
-
-(register-definition-prefixes "srecode" '("srecode-version"))
-
-;;;***
-
-;;;### (autoloads nil "srecode/args" "cedet/srecode/args.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from cedet/srecode/args.el
-
-(register-definition-prefixes "srecode/args" '("srecode-"))
-
-;;;***
-
-;;;### (autoloads nil "srecode/ctxt" "cedet/srecode/ctxt.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from cedet/srecode/ctxt.el
-
-(register-definition-prefixes "srecode/ctxt" '("srecode-"))
-
-;;;***
-
-;;;### (autoloads nil "srecode/dictionary" "cedet/srecode/dictionary.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/srecode/dictionary.el
-
-(register-definition-prefixes "srecode/dictionary" '("srecode-"))
-
-;;;***
-;;;### (autoloads nil "srecode/extract" "cedet/srecode/extract.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/srecode/extract.el
-
-(register-definition-prefixes "srecode/extract" '("srecode-extract"))
-
-;;;***
-
-;;;### (autoloads nil "srecode/fields" "cedet/srecode/fields.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/srecode/fields.el
-
-(register-definition-prefixes "srecode/fields" '("srecode-"))
-
-;;;***
-
-;;;### (autoloads nil "srecode/filters" "cedet/srecode/filters.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/srecode/filters.el
+;;; Generated autoloads from cedet/ede/srecode.el
-(register-definition-prefixes "srecode/filters" '("srecode-comment-prefix"))
+(register-definition-prefixes "ede/srecode" '("ede-srecode-"))
-;;;***
-;;;### (autoloads nil "srecode/find" "cedet/srecode/find.el" (0 0
-;;;;;; 0 0))
-;;; Generated autoloads from cedet/srecode/find.el
+;;; Generated autoloads from cedet/srecode.el
-(register-definition-prefixes "srecode/find" '("srecode-"))
+(push (purecopy '(srecode 1 2)) package--builtin-versions)
+(register-definition-prefixes "srecode" '("srecode-version"))
-;;;***
-;;;### (autoloads nil "srecode/semantic" "cedet/srecode/semantic.el"
-;;;;;; (0 0 0 0))
-;;; Generated autoloads from cedet/srecode/semantic.el
+;;; Generated autoloads from cedet/srecode/srt.el
-(register-definition-prefixes "srecode/semantic" '("srecode-semantic-"))
+(register-definition-prefixes "srecode/srt" '("srecode-read-"))
-;;;***
-;;;### (autoloads nil "srecode/srt-mode" "cedet/srecode/srt-mode.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from cedet/srecode/srt-mode.el
(autoload 'srecode-template-mode "srecode/srt-mode" "\
Major-mode for writing SRecode macros.
-\(fn)" t nil)
-
+(fn)" t nil)
(defalias 'srt-mode #'srecode-template-mode)
-
(register-definition-prefixes "srecode/srt-mode" '("semantic-" "srecode-"))
-;;;***
-;;;### (autoloads nil "srecode/table" "cedet/srecode/table.el" (0
-;;;;;; 0 0 0))
-;;; Generated autoloads from cedet/srecode/table.el
+;;; Generated autoloads from textmodes/string-edit.el
-(register-definition-prefixes "srecode/table" '("object-sort-list" "srecode-"))
+(autoload 'string-edit "string-edit" "\
+Switch to a new buffer to edit STRING.
+When the user finishes editing (with \\<string-edit-mode-map>\\[string-edit-done]), SUCCESS-CALLBACK
+is called with the resulting string.
+
+If the user aborts (with \\<string-edit-mode-map>\\[string-edit-abort]), ABORT-CALLBACK (if any) is
+called with no parameters.
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If PROMPT is nil, no help text
+will be inserted.
+
+(fn PROMPT STRING SUCCESS-CALLBACK &key ABORT-CALLBACK)" nil nil)
+(autoload 'read-string-from-buffer "string-edit" "\
+Switch to a new buffer to edit STRING in a recursive edit.
+The user finishes editing with \\<string-edit-mode-map>\\[string-edit-done], or aborts with \\<string-edit-mode-map>\\[string-edit-abort]).
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If nil, no prompt will be
+inserted in the buffer.
+
+(fn PROMPT STRING)" nil nil)
+(register-definition-prefixes "string-edit" '("string-edit-"))
-;;;***
-;;;### (autoloads nil "strokes" "strokes.el" (0 0 0 0))
;;; Generated autoloads from strokes.el
(autoload 'strokes-global-set-stroke "strokes" "\
@@ -32643,8 +29256,7 @@ documentation for the `strokes-define-stroke' function.
See also `strokes-global-set-stroke-string'.
-\(fn STROKE COMMAND)" t nil)
-
+(fn STROKE COMMAND)" t nil)
(autoload 'strokes-read-stroke "strokes" "\
Read a simple stroke (interactively) and return the stroke.
Optional PROMPT in minibuffer displays before and during stroke reading.
@@ -32653,8 +29265,7 @@ entered in the strokes buffer if the variable
`strokes-use-strokes-buffer' is non-nil.
Optional EVENT is acceptable as the starting event of the stroke.
-\(fn &optional PROMPT EVENT)" nil nil)
-
+(fn &optional PROMPT EVENT)" nil nil)
(autoload 'strokes-read-complex-stroke "strokes" "\
Read a complex stroke (interactively) and return the stroke.
Optional PROMPT in minibuffer displays before and during stroke reading.
@@ -32663,39 +29274,32 @@ is implemented by allowing the user to paint with button 1 or button 2 and
then complete the stroke with button 3.
Optional EVENT is acceptable as the starting event of the stroke.
-\(fn &optional PROMPT EVENT)" nil nil)
-
+(fn &optional PROMPT EVENT)" nil nil)
(autoload 'strokes-do-stroke "strokes" "\
Read a simple stroke from the user and then execute its command.
This must be bound to a mouse event.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'strokes-do-complex-stroke "strokes" "\
Read a complex stroke from the user and then execute its command.
This must be bound to a mouse event.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'strokes-describe-stroke "strokes" "\
Displays the command which STROKE maps to, reading STROKE interactively.
-\(fn STROKE)" t nil)
-
+(fn STROKE)" t nil)
(autoload 'strokes-help "strokes" "\
Get instruction on using the Strokes package." t nil)
-
(autoload 'strokes-load-user-strokes "strokes" "\
Load user-defined strokes from file named by `strokes-file'." t nil)
-
(autoload 'strokes-list-strokes "strokes" "\
Pop up a buffer containing an alphabetical listing of strokes in STROKES-MAP.
With CHRONOLOGICAL prefix arg (\\[universal-argument]) list strokes chronologically
by command name.
If STROKES-MAP is not given, `strokes-global-map' will be used instead.
-\(fn &optional CHRONOLOGICAL STROKES-MAP)" t nil)
-
+(fn &optional CHRONOLOGICAL STROKES-MAP)" t nil)
(defvar strokes-mode nil "\
Non-nil if Strokes mode is enabled.
See the `strokes-mode' command
@@ -32703,26 +29307,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `strokes-mode'.")
-
(custom-autoload 'strokes-mode "strokes" nil)
-
(autoload 'strokes-mode "strokes" "\
Toggle Strokes mode, a global minor mode.
-This is a minor mode. If called interactively, toggle the `Strokes
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='strokes-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
\\<strokes-mode-map>
Strokes are pictographic mouse gestures which invoke commands.
Strokes are invoked with \\[strokes-do-stroke]. You can define
@@ -32736,120 +29324,68 @@ Encode/decode your strokes with \\[strokes-encode-buffer],
\\{strokes-mode-map}
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Strokes mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='strokes-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'strokes-decode-buffer "strokes" "\
Decode stroke strings in BUFFER and display their corresponding glyphs.
Optional BUFFER defaults to the current buffer.
Optional FORCE non-nil will ignore the buffer's read-only status.
-\(fn &optional BUFFER FORCE)" t nil)
-
+(fn &optional BUFFER FORCE)" t nil)
(autoload 'strokes-compose-complex-stroke "strokes" "\
Read a complex stroke and insert its glyph into the current buffer." t nil)
-
(register-definition-prefixes "strokes" '("strokes-"))
-;;;***
-;;;### (autoloads nil "studly" "play/studly.el" (0 0 0 0))
;;; Generated autoloads from play/studly.el
(autoload 'studlify-region "studly" "\
Studlify-case the region.
-\(fn BEGIN END)" t nil)
-
+(fn BEGIN END)" t nil)
(autoload 'studlify-word "studly" "\
Studlify-case the current word, or COUNT words if given an argument.
-\(fn COUNT)" t nil)
-
+(fn COUNT)" t nil)
(autoload 'studlify-buffer "studly" "\
Studlify-case the current buffer." t nil)
-;;;***
-;;;### (autoloads nil "subr-x" "emacs-lisp/subr-x.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/subr-x.el
-(autoload 'if-let "subr-x" "\
-Bind variables according to SPEC and evaluate THEN or ELSE.
-Evaluate each binding in turn, as in `let*', stopping if a
-binding value is nil. If all are non-nil return the value of
-THEN, otherwise the last form in ELSE.
-
-Each element of SPEC is a list (SYMBOL VALUEFORM) that binds
-SYMBOL to the value of VALUEFORM. An element can additionally be
-of the form (VALUEFORM), which is evaluated and checked for nil;
-i.e. SYMBOL can be omitted if only the test result is of
-interest. It can also be of the form SYMBOL, then the binding of
-SYMBOL is checked for nil.
-
-As a special case, interprets a SPEC of the form (SYMBOL SOMETHING)
-like ((SYMBOL SOMETHING)). This exists for backward compatibility
-with an old syntax that accepted only one binding.
-
-\(fn SPEC THEN &rest ELSE)" nil t)
-
-(function-put 'if-let 'lisp-indent-function '2)
-
-(autoload 'when-let "subr-x" "\
-Bind variables according to SPEC and conditionally evaluate BODY.
-Evaluate each binding in turn, stopping if a binding value is nil.
-If all are non-nil, return the value of the last form in BODY.
-
-The variable list SPEC is the same as in `if-let'.
-
-\(fn SPEC &rest BODY)" nil t)
-
-(function-put 'when-let 'lisp-indent-function '1)
-
(autoload 'string-truncate-left "subr-x" "\
Truncate STRING to LENGTH, replacing initial surplus with \"...\".
-\(fn STRING LENGTH)" nil nil)
-
+(fn STRING LENGTH)" nil nil)
(autoload 'string-clean-whitespace "subr-x" "\
Clean up whitespace in STRING.
All sequences of whitespaces in STRING are collapsed into a
single space character, and leading/trailing whitespace is
removed.
-\(fn STRING)" nil nil)
-
-(autoload 'string-lines "subr-x" "\
-Split STRING into a list of lines.
-If OMIT-NULLS, empty lines will be removed from the results.
-
-\(fn STRING &optional OMIT-NULLS)" nil nil)
-
-(autoload 'ensure-empty-lines "subr-x" "\
-Ensure that there are LINES number of empty lines before point.
-If LINES is nil or omitted, ensure that there is a single empty
-line before point.
-
-If called interactively, LINES is given by the prefix argument.
-
-If there are more than LINES empty lines before point, the number
-of empty lines is reduced to LINES.
-
-If point is not at the beginning of a line, a newline character
-is inserted before adjusting the number of empty lines.
-
-\(fn &optional LINES)" t nil)
-
+(fn STRING)" nil nil)
(autoload 'string-pixel-width "subr-x" "\
Return the width of STRING in pixels.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'string-glyph-split "subr-x" "\
Split STRING into a list of strings representing separate glyphs.
This takes into account combining characters and grapheme clusters.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'add-display-text-property "subr-x" "\
Add display property PROP with VALUE to the text from START to END.
If any text in the region has a non-nil `display' property, those
@@ -32858,34 +29394,20 @@ properties are retained.
If OBJECT is non-nil, it should be a string or a buffer. If nil,
this defaults to the current buffer.
-\(fn START END PROP VALUE &optional OBJECT)" nil nil)
+(fn START END PROP VALUE &optional OBJECT)" nil nil)
+(autoload 'read-process-name "subr-x" "\
+Query the user for a process and return the process object.
-(register-definition-prefixes "subr-x" '("and-let*" "hash-table-" "if-let*" "internal--" "named-let" "replace-region-contents" "string-" "thread-" "when-let*" "with-memoization"))
+(fn PROMPT)" nil nil)
+(register-definition-prefixes "subr-x" '("hash-table-" "internal--thread-argument" "named-let" "replace-region-contents" "string-" "thread-" "with-buffer-unmodified-if-unchanged"))
-;;;***
-;;;### (autoloads nil "subword" "progmodes/subword.el" (0 0 0 0))
;;; Generated autoloads from progmodes/subword.el
(define-obsolete-function-alias 'capitalized-words-mode 'subword-mode "25.1")
-
(autoload 'subword-mode "subword" "\
Toggle subword movement and editing (Subword mode).
-This is a minor mode. If called interactively, toggle the `Subword
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `subword-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Subword mode is a buffer-local minor mode. Enabling it changes
the definition of a word so that word-based commands stop inside
symbols with mixed uppercase and lowercase letters,
@@ -32904,10 +29426,22 @@ called a `subword'. Here are some examples:
This mode changes the definition of a word so that word commands
treat nomenclature boundaries as word boundaries.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Subword mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
-(put 'global-subword-mode 'globalized-minor-mode t)
+To check whether the minor mode is enabled in the current buffer,
+evaluate `subword-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
+(put 'global-subword-mode 'globalized-minor-mode t)
(defvar global-subword-mode nil "\
Non-nil if Global Subword mode is enabled.
See the `global-subword-mode' command
@@ -32915,9 +29449,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-subword-mode'.")
-
(custom-autoload 'global-subword-mode "subword" nil)
-
(autoload 'global-subword-mode "subword" "\
Toggle Subword mode in all buffers.
With prefix ARG, enable Global Subword mode if ARG is positive;
@@ -32928,40 +29460,37 @@ Enable the mode if ARG is nil, omitted, or is a positive number.
Disable the mode if ARG is a negative number.
Subword mode is enabled in all buffers where `(lambda nil
-\(subword-mode 1))' would do it.
+(subword-mode 1))' would do it.
See `subword-mode' for more information on Subword mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'superword-mode "subword" "\
Toggle superword movement and editing (Superword mode).
-This is a minor mode. If called interactively, toggle the `Superword
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `superword-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Superword mode is a buffer-local minor mode. Enabling it changes
-the definition of words such that symbols characters are treated
-as parts of words: e.g., in `superword-mode',
+the definition of words such that characters which have symbol
+syntax are treated as parts of words: e.g., in `superword-mode',
\"this_is_a_symbol\" counts as one word.
\\{superword-mode-map}
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Superword mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-(put 'global-superword-mode 'globalized-minor-mode t)
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `superword-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
+(put 'global-superword-mode 'globalized-minor-mode t)
(defvar global-superword-mode nil "\
Non-nil if Global Superword mode is enabled.
See the `global-superword-mode' command
@@ -32969,9 +29498,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-superword-mode'.")
-
(custom-autoload 'global-superword-mode "subword" nil)
-
(autoload 'global-superword-mode "subword" "\
Toggle Superword mode in all buffers.
With prefix ARG, enable Global Superword mode if ARG is positive;
@@ -32982,17 +29509,14 @@ Enable the mode if ARG is nil, omitted, or is a positive number.
Disable the mode if ARG is a negative number.
Superword mode is enabled in all buffers where `(lambda nil
-\(superword-mode 1))' would do it.
+(superword-mode 1))' would do it.
See `superword-mode' for more information on Superword mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "subword" '("subword-" "superword-mode-map"))
-;;;***
-;;;### (autoloads nil "supercite" "mail/supercite.el" (0 0 0 0))
;;; Generated autoloads from mail/supercite.el
(autoload 'sc-cite-original "supercite" "\
@@ -33019,20 +29543,20 @@ original message but it does require a few things:
The region need not be active (and typically isn't when this
function is called). Also, the hook `sc-pre-hook' is run before,
and `sc-post-hook' is run after the guts of this function." nil nil)
-
(register-definition-prefixes "supercite" '("sc-"))
-;;;***
-;;;### (autoloads nil "svg" "svg.el" (0 0 0 0))
;;; Generated autoloads from svg.el
-(push (purecopy '(svg 1 1)) package--builtin-versions)
+(push (purecopy '(svg 1 1)) package--builtin-versions)
(register-definition-prefixes "svg" '("svg-"))
-;;;***
-;;;### (autoloads nil "t-mouse" "t-mouse.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/symref.el
+
+(register-definition-prefixes "semantic/symref" '("semantic-symref-"))
+
+
;;; Generated autoloads from t-mouse.el
(defvar gpm-mouse-mode t "\
@@ -33042,26 +29566,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `gpm-mouse-mode'.")
-
(custom-autoload 'gpm-mouse-mode "t-mouse" nil)
-
(autoload 'gpm-mouse-mode "t-mouse" "\
Toggle mouse support in GNU/Linux consoles (GPM Mouse mode).
-This is a minor mode. If called interactively, toggle the `Gpm-Mouse
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='gpm-mouse-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
This allows the use of the mouse when operating on a GNU/Linux console,
in the same way as you can use the mouse under X11.
It relies on the `gpm' daemon being activated.
@@ -33070,38 +29578,46 @@ Note that when `gpm-mouse-mode' is enabled, you cannot use the
mouse to transfer text between Emacs and other programs which use
GPM. This is due to limitations in GPM and the Linux kernel.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Gpm-Mouse mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='gpm-mouse-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "t-mouse" '("gpm-mouse-"))
-;;;***
-;;;### (autoloads nil "tab-line" "tab-line.el" (0 0 0 0))
;;; Generated autoloads from tab-line.el
(autoload 'tab-line-mode "tab-line" "\
Toggle display of tab line in the windows displaying the current buffer.
-This is a minor mode. If called interactively, toggle the `Tab-Line
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+This is a minor mode. If called interactively, toggle the
+`Tab-Line mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `tab-line-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar-local tab-line-exclude nil)
-
(put 'global-tab-line-mode 'globalized-minor-mode t)
-
(defvar global-tab-line-mode nil "\
Non-nil if Global Tab-Line mode is enabled.
See the `global-tab-line-mode' command
@@ -33109,9 +29625,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-tab-line-mode'.")
-
(custom-autoload 'global-tab-line-mode "tab-line" nil)
-
(autoload 'global-tab-line-mode "tab-line" "\
Toggle Tab-Line mode in all buffers.
With prefix ARG, enable Global Tab-Line mode if ARG is positive;
@@ -33126,13 +29640,10 @@ would do it.
See `tab-line-mode' for more information on Tab-Line mode.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "tab-line" '("tab-line-"))
-;;;***
-;;;### (autoloads nil "tabify" "tabify.el" (0 0 0 0))
;;; Generated autoloads from tabify.el
(autoload 'untabify "tabify" "\
@@ -33144,8 +29655,7 @@ Called non-interactively, the region is specified by arguments
START and END, rather than by the position of point and mark.
The variable `tab-width' controls the spacing of tab stops.
-\(fn START END &optional ARG)" t nil)
-
+(fn START END &optional ARG)" t nil)
(autoload 'tabify "tabify" "\
Convert multiple spaces in region to tabs when possible.
A group of spaces is partially replaced by tabs
@@ -33157,17 +29667,15 @@ Called non-interactively, the region is specified by arguments
START and END, rather than by the position of point and mark.
The variable `tab-width' controls the spacing of tab stops.
-\(fn START END &optional ARG)" t nil)
-
+(fn START END &optional ARG)" t nil)
(register-definition-prefixes "tabify" '("tabify-regexp"))
-;;;***
-;;;### (autoloads nil "table" "textmodes/table.el" (0 0 0 0))
;;; Generated autoloads from textmodes/table.el
(autoload 'table-fixed-width-mode "table" "\
Cell width is fixed when this is non-nil.
+
Normally it should be nil for allowing automatic cell width expansion
that widens a cell when it is necessary. When non-nil, typing in a
cell does not automatically expand the cell width. A word that is too
@@ -33177,21 +29685,21 @@ variable's value can be toggled by \\[table-fixed-width-mode] at
run-time.
This is a minor mode. If called interactively, toggle the
-`Table-Fixed-Width mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
+`Table-Fixed-Width mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `table-fixed-width-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'table-insert "table" "\
Insert an editable text table.
Insert a table of specified number of COLUMNS and ROWS. Optional
@@ -33313,8 +29821,7 @@ Inside a table cell has a special keymap.
\\{table-cell-map}
-\(fn COLUMNS ROWS &optional CELL-WIDTH CELL-HEIGHT)" t nil)
-
+(fn COLUMNS ROWS &optional CELL-WIDTH CELL-HEIGHT)" t nil)
(autoload 'table-insert-row "table" "\
Insert N table row(s).
When point is in a table the newly inserted row(s) are placed above
@@ -33322,8 +29829,7 @@ the current row. When point is outside of the table it must be below
the table within the table width range, then the newly created row(s)
are appended at the bottom of the table.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-insert-column "table" "\
Insert N table column(s).
When point is in a table the newly inserted column(s) are placed left
@@ -33331,14 +29837,12 @@ of the current column. When point is outside of the table it must be
right side of the table within the table height range, then the newly
created column(s) are appended at the right of the table.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-insert-row-column "table" "\
Insert row(s) or column(s).
See `table-insert-row' and `table-insert-column'.
-\(fn ROW-COLUMN N)" t nil)
-
+(fn ROW-COLUMN N)" t nil)
(autoload 'table-recognize "table" "\
Recognize all tables within the current buffer and activate them.
Scans the entire buffer and recognizes valid table cells. If the
@@ -33346,10 +29850,8 @@ optional numeric prefix argument ARG is negative the tables in the
buffer become inactive, meaning the tables become plain text and loses
all the table specific features.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'table-unrecognize "table" nil t nil)
-
(autoload 'table-recognize-region "table" "\
Recognize all tables within region.
BEG and END specify the region to work on. If the optional numeric
@@ -33357,23 +29859,19 @@ prefix argument ARG is negative the tables in the region become
inactive, meaning the tables become plain text and lose all the table
specific features.
-\(fn BEG END &optional ARG)" t nil)
-
+(fn BEG END &optional ARG)" t nil)
(autoload 'table-unrecognize-region "table" "\
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'table-recognize-table "table" "\
Recognize a table at point.
If the optional numeric prefix argument ARG is negative the table
becomes inactive, meaning the table becomes plain text and loses all
the table specific features.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'table-unrecognize-table "table" nil t nil)
-
(autoload 'table-recognize-cell "table" "\
Recognize a table cell that contains current point.
Probe the cell dimension and prepare the cell information. The
@@ -33382,10 +29880,8 @@ must not be specified. When the optional numeric prefix argument ARG
is negative the cell becomes inactive, meaning that the cell becomes
plain text and loses all the table specific features.
-\(fn &optional FORCE NO-COPY ARG)" t nil)
-
+(fn &optional FORCE NO-COPY ARG)" t nil)
(autoload 'table-unrecognize-cell "table" nil t nil)
-
(autoload 'table-heighten-cell "table" "\
Heighten the current cell by N lines by expanding the cell vertically.
Heightening is done by adding blank lines at the bottom of the current
@@ -33394,8 +29890,7 @@ heightened in order to keep the rectangular table structure. The
optional argument NO-COPY is internal use only and must not be
specified.
-\(fn N &optional NO-COPY NO-UPDATE)" t nil)
-
+(fn N &optional NO-COPY NO-UPDATE)" t nil)
(autoload 'table-shorten-cell "table" "\
Shorten the current cell by N lines by shrinking the cell vertically.
Shortening is done by removing blank lines from the bottom of the cell
@@ -33405,22 +29900,19 @@ is applicable to all the cells aligned horizontally with the current
one because they are also shortened in order to keep the rectangular
table structure.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-widen-cell "table" "\
Widen the current cell by N columns and expand the cell horizontally.
Some other cells in the same table are widen as well to keep the
table's rectangle structure.
-\(fn N &optional NO-COPY NO-UPDATE)" t nil)
-
+(fn N &optional NO-COPY NO-UPDATE)" t nil)
(autoload 'table-narrow-cell "table" "\
Narrow the current cell by N columns and shrink the cell horizontally.
Some other cells in the same table are narrowed as well to keep the
table's rectangle structure.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-forward-cell "table" "\
Move point forward to the beginning of the next cell.
With argument ARG, do it ARG times;
@@ -33460,43 +29952,36 @@ You can actually try how it works in this buffer. Press
| |6 | | | |6 | | +--+--+--+--+ +--+--+--+--+ +--+-----+--+
+--+--+--+ +--+--+--+
-\(fn &optional ARG NO-RECOGNIZE UNRECOGNIZE)" t nil)
-
+(fn &optional ARG NO-RECOGNIZE UNRECOGNIZE)" t nil)
(autoload 'table-backward-cell "table" "\
Move backward to the beginning of the previous cell.
With argument ARG, do it ARG times;
a negative argument ARG = -N means move forward N cells.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'table-span-cell "table" "\
Span current cell into adjacent cell in DIRECTION.
DIRECTION is one of symbols; right, left, above or below.
-\(fn DIRECTION)" t nil)
-
+(fn DIRECTION)" t nil)
(autoload 'table-split-cell-vertically "table" "\
Split current cell vertically.
Creates a cell above and a cell below the current point location." t nil)
-
(autoload 'table-split-cell-horizontally "table" "\
Split current cell horizontally.
Creates a cell on the left and a cell on the right of the current
point location." t nil)
-
(autoload 'table-split-cell "table" "\
Split current cell in ORIENTATION.
ORIENTATION is a symbol either horizontally or vertically.
-\(fn ORIENTATION)" t nil)
-
+(fn ORIENTATION)" t nil)
(autoload 'table-justify "table" "\
Justify contents of a cell, a row of cells or a column of cells.
WHAT is a symbol `cell', `row' or `column'. JUSTIFY is a symbol
`left', `center', `right', `top', `middle', `bottom' or `none'.
-\(fn WHAT JUSTIFY)" t nil)
-
+(fn WHAT JUSTIFY)" t nil)
(autoload 'table-justify-cell "table" "\
Justify cell contents.
JUSTIFY is a symbol `left', `center' or `right' for horizontal, or `top',
@@ -33504,22 +29989,19 @@ JUSTIFY is a symbol `left', `center' or `right' for horizontal, or `top',
non-nil the justify operation is limited to the current paragraph,
otherwise the entire cell contents is justified.
-\(fn JUSTIFY &optional PARAGRAPH)" t nil)
-
+(fn JUSTIFY &optional PARAGRAPH)" t nil)
(autoload 'table-justify-row "table" "\
Justify cells of a row.
JUSTIFY is a symbol `left', `center' or `right' for horizontal,
or `top', `middle', `bottom' or `none' for vertical.
-\(fn JUSTIFY)" t nil)
-
+(fn JUSTIFY)" t nil)
(autoload 'table-justify-column "table" "\
Justify cells of a column.
JUSTIFY is a symbol `left', `center' or `right' for horizontal,
or `top', `middle', `bottom' or `none' for vertical.
-\(fn JUSTIFY)" t nil)
-
+(fn JUSTIFY)" t nil)
(autoload 'table-query-dimension "table" "\
Return the dimension of the current cell and the current table.
The result is a list (cw ch tw th c r cells) where cw is the cell
@@ -33532,8 +30014,7 @@ the number tends to be larger than it appears for the tables with
non-uniform cell structure (heavily spanned and split). When optional
WHERE is provided the cell and table at that location is reported.
-\(fn &optional WHERE)" t nil)
-
+(fn &optional WHERE)" t nil)
(autoload 'table-generate-source "table" "\
Generate source of the current table in the specified language.
LANGUAGE is a symbol that specifies the language to describe the
@@ -33561,8 +30042,7 @@ CALS (DocBook DTD):
URL `https://www.oasis-open.org/html/a502.htm'
URL `https://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
-\(fn LANGUAGE &optional DEST-BUFFER CAPTION)" t nil)
-
+(fn LANGUAGE &optional DEST-BUFFER CAPTION)" t nil)
(autoload 'table-insert-sequence "table" "\
Travel cells forward while inserting a specified sequence string in each cell.
STR is the base string from which the sequence starts. When STR is an
@@ -33598,24 +30078,21 @@ Example:
(table-forward-cell 1)
(table-insert-sequence \"64\" 0 1 2 \\='left))
-\(fn STR N INCREMENT INTERVAL JUSTIFY)" t nil)
-
+(fn STR N INCREMENT INTERVAL JUSTIFY)" t nil)
(autoload 'table-delete-row "table" "\
Delete N row(s) of cells.
Delete N rows of cells from current row. The current row is the row
contains the current cell where point is located. Each row must
consists from cells of same height.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-delete-column "table" "\
Delete N column(s) of cells.
Delete N columns of cells from current column. The current column is
the column contains the current cell where point is located. Each
column must consists from cells of same width.
-\(fn N)" t nil)
-
+(fn N)" t nil)
(autoload 'table-capture "table" "\
Convert plain text into a table by capturing the text in the region.
Create a table with the text in region as cell contents. BEG and END
@@ -33727,41 +30204,56 @@ By applying `table-release', which does the opposite process, the
contents become once again plain text. `table-release' works as
companion command to `table-capture' this way.
-\(fn BEG END &optional COL-DELIM-REGEXP ROW-DELIM-REGEXP JUSTIFY MIN-CELL-WIDTH COLUMNS)" t nil)
-
+(fn BEG END &optional COL-DELIM-REGEXP ROW-DELIM-REGEXP JUSTIFY MIN-CELL-WIDTH COLUMNS)" t nil)
(autoload 'table-release "table" "\
Convert a table into plain text by removing the frame from a table.
Remove the frame from a table and deactivate the table. This command
converts a table into plain text without frames. It is a companion to
`table-capture' which does the opposite process." t nil)
-
(register-definition-prefixes "table" '("*table--" "table-"))
-;;;***
-;;;### (autoloads nil "tabulated-list" "emacs-lisp/tabulated-list.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/table.el
+
+(register-definition-prefixes "srecode/table" '("object-sort-list" "srecode-"))
+
+
;;; Generated autoloads from emacs-lisp/tabulated-list.el
+
(push (purecopy '(tabulated-list 1 0)) package--builtin-versions)
-;;;***
-;;;### (autoloads nil "talk" "talk.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/tag.el
+
+(register-definition-prefixes "semantic/tag" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/tag-file.el
+
+(register-definition-prefixes "semantic/tag-file" '("semantic-prototype-file"))
+
+
+;;; Generated autoloads from cedet/semantic/tag-ls.el
+
+(register-definition-prefixes "semantic/tag-ls" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/semantic/tag-write.el
+
+(register-definition-prefixes "semantic/tag-write" '("semantic-tag-write-"))
+
+
;;; Generated autoloads from talk.el
(autoload 'talk-connect "talk" "\
Connect to display DISPLAY for the Emacs talk group.
-\(fn DISPLAY)" t nil)
-
+(fn DISPLAY)" t nil)
(autoload 'talk "talk" "\
Connect to the Emacs talk group from the current X display or tty frame." t nil)
-
(register-definition-prefixes "talk" '("talk-"))
-;;;***
-;;;### (autoloads nil "tar-mode" "tar-mode.el" (0 0 0 0))
;;; Generated autoloads from tar-mode.el
(autoload 'tar-mode "tar-mode" "\
@@ -33780,13 +30272,10 @@ inside of a tar archive without extracting it and re-archiving it.
See also: variables `tar-update-datestamp' and `tar-anal-blocksize'.
\\{tar-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "tar-mode" '("tar-"))
-;;;***
-;;;### (autoloads nil "tcl" "progmodes/tcl.el" (0 0 0 0))
;;; Generated autoloads from progmodes/tcl.el
(autoload 'tcl-mode "tcl" "\
@@ -33817,34 +30306,26 @@ Turning on Tcl mode runs `tcl-mode-hook'. Read the documentation for
`tcl-mode-hook' to see what kinds of interesting hook functions
already exist.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'inferior-tcl "tcl" "\
Run inferior Tcl process.
Prefix arg means enter program name interactively.
See documentation for function `inferior-tcl-mode' for more information.
-\(fn CMD)" t nil)
-
+(fn CMD)" t nil)
(autoload 'tcl-help-on-word "tcl" "\
Get help on Tcl command. Default is word at point.
Prefix argument means invert sense of `tcl-use-smart-word-finder'.
-\(fn COMMAND &optional ARG)" t nil)
-
+(fn COMMAND &optional ARG)" t nil)
(register-definition-prefixes "tcl" '("inferior-tcl-" "run-tcl" "switch-to-tcl" "tcl-"))
-;;;***
-;;;### (autoloads nil "tcover-ses" "emacs-lisp/tcover-ses.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/tcover-ses.el
(register-definition-prefixes "tcover-ses" '("ses-exercise"))
-;;;***
-;;;### (autoloads nil "telnet" "net/telnet.el" (0 0 0 0))
;;; Generated autoloads from net/telnet.el
(autoload 'telnet "telnet" "\
@@ -33858,27 +30339,26 @@ is controlled by the contents of the global variable `telnet-host-properties',
falling back on the value of the global variable `telnet-program'.
Normally input is edited in Emacs and sent a line at a time.
-\(fn HOST &optional PORT)" t nil)
-
+(fn HOST &optional PORT)" t nil)
(autoload 'rsh "telnet" "\
Open a network login connection to host named HOST (a string).
Communication with HOST is recorded in a buffer `*rsh-HOST*'.
Normally input is edited in Emacs and sent a line at a time.
-\(fn HOST)" t nil)
-
+(fn HOST)" t nil)
(register-definition-prefixes "telnet" '("send-process-next-char" "telnet-"))
-;;;***
-;;;### (autoloads nil "tempo" "tempo.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/template.el
+
+(register-definition-prefixes "srecode/template" '("semantic-tag-components"))
+
+
;;; Generated autoloads from tempo.el
(register-definition-prefixes "tempo" '("tempo-"))
-;;;***
-;;;### (autoloads nil "term" "term.el" (0 0 0 0))
;;; Generated autoloads from term.el
(autoload 'make-term "term" "\
@@ -33888,8 +30368,7 @@ If there is already a running process in that buffer, it is not restarted.
Optional third arg STARTFILE is the name of a file to send the contents of to
the process. Any more args are arguments to PROGRAM.
-\(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
-
+(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil)
(autoload 'term "term" "\
Start a terminal-emulator in a new buffer.
The buffer is in Term mode; see `term-mode' for the
@@ -33897,15 +30376,13 @@ commands to use in that buffer.
\\<term-raw-map>Type \\[switch-to-buffer] to switch to another buffer.
-\(fn PROGRAM)" t nil)
-
+(fn PROGRAM)" t nil)
(autoload 'ansi-term "term" "\
Start a terminal-emulator in a new buffer.
This is almost the same as `term' apart from always creating a new buffer,
-and `C-x' being marked as a `term-escape-char'.
-
-\(fn PROGRAM &optional NEW-BUFFER-NAME)" t nil)
+and \\`C-x' being marked as a `term-escape-char'.
+(fn PROGRAM &optional NEW-BUFFER-NAME)" t nil)
(autoload 'serial-term "term" "\
Start a terminal-emulator for a serial port in a new buffer.
PORT is the path or name of the serial port. For example, this
@@ -33925,30 +30402,22 @@ use in that buffer.
\\<term-raw-map>Type \\[switch-to-buffer] to switch to another buffer.
-\(fn PORT SPEED &optional LINE-MODE)" t nil)
-
+(fn PORT SPEED &optional LINE-MODE)" t nil)
(register-definition-prefixes "term" '("ansi-term-color-vector" "serial-" "term-"))
-;;;***
-;;;### (autoloads nil "testcover" "emacs-lisp/testcover.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emacs-lisp/testcover.el
(autoload 'testcover-start "testcover" "\
Use Edebug to instrument for coverage all macros and functions in FILENAME.
If BYTE-COMPILE is non-nil, byte compile each function after instrumenting.
-\(fn FILENAME &optional BYTE-COMPILE)" t nil)
-
+(fn FILENAME &optional BYTE-COMPILE)" t nil)
(autoload 'testcover-this-defun "testcover" "\
Start coverage on function under point." t nil)
-
(register-definition-prefixes "testcover" '("testcover-"))
-;;;***
-;;;### (autoloads nil "tetris" "play/tetris.el" (0 0 0 0))
;;; Generated autoloads from play/tetris.el
(autoload 'tetris "tetris" "\
@@ -33967,103 +30436,74 @@ as to form complete rows.
\\[tetris-rotate-prev] Rotate the shape clockwise
\\[tetris-rotate-next] Rotate the shape anticlockwise
\\[tetris-move-bottom] Drop the shape to the bottom of the playing area" t nil)
-
(register-definition-prefixes "tetris" '("tetris-"))
-;;;***
-;;;### (autoloads nil "tex-mode" "textmodes/tex-mode.el" (0 0 0 0))
;;; Generated autoloads from textmodes/tex-mode.el
(defvar tex-shell-file-name nil "\
If non-nil, the shell file name to run in the subshell used to run TeX.")
-
(custom-autoload 'tex-shell-file-name "tex-mode" t)
-
(defvar tex-directory (purecopy ".") "\
Directory in which temporary files are written.
You can make this `/tmp' if your TEXINPUTS has no relative directories in it
and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
`\\input' commands with relative directories.")
-
(custom-autoload 'tex-directory "tex-mode" t)
-
(defvar tex-first-line-header-regexp nil "\
Regexp for matching a first line which `tex-region' should include.
If this is non-nil, it should be a regular expression string;
if it matches the first line of the file,
`tex-region' always includes the first line in the TeX run.")
-
(custom-autoload 'tex-first-line-header-regexp "tex-mode" t)
-
(defvar tex-main-file nil "\
The main TeX source file which includes this buffer's file.
The command `tex-file' runs TeX on the file specified by `tex-main-file'
if the variable is non-nil.")
-
(custom-autoload 'tex-main-file "tex-mode" t)
-
(defvar tex-offer-save t "\
If non-nil, ask about saving modified buffers before \\[tex-file] is run.")
-
(custom-autoload 'tex-offer-save "tex-mode" t)
-
(defvar tex-run-command (purecopy "tex") "\
Command used to run TeX subjob.
TeX Mode sets `tex-command' to this string.
See the documentation of that variable.")
-
(custom-autoload 'tex-run-command "tex-mode" t)
-
(defvar latex-run-command (purecopy "latex") "\
Command used to run LaTeX subjob.
LaTeX Mode sets `tex-command' to this string.
See the documentation of that variable.")
-
(custom-autoload 'latex-run-command "tex-mode" t)
-
(defvar slitex-run-command (purecopy "slitex") "\
Command used to run SliTeX subjob.
SliTeX Mode sets `tex-command' to this string.
See the documentation of that variable.")
-
(custom-autoload 'slitex-run-command "tex-mode" t)
-
(defvar tex-start-options (purecopy "") "\
TeX options to use when starting TeX.
These immediately precede the commands in `tex-start-commands'
and the input file name, with no separating space and are not shell-quoted.
If nil, TeX runs with no options. See the documentation of `tex-command'.")
-
(custom-autoload 'tex-start-options "tex-mode" t)
-
(defvar tex-start-commands (purecopy "\\nonstopmode\\input") "\
TeX commands to use when starting TeX.
They are shell-quoted and precede the input file name, with a separating space.
If nil, no commands are used. See the documentation of `tex-command'.")
-
(custom-autoload 'tex-start-commands "tex-mode" t)
-
(defvar latex-block-names nil "\
User defined LaTeX block names.
Combined with `latex-standard-block-names' for minibuffer completion.")
-
(custom-autoload 'latex-block-names "tex-mode" t)
-
(defvar tex-bibtex-command (purecopy "bibtex") "\
Command used by `tex-bibtex-file' to gather bibliographic data.
If this string contains an asterisk (`*'), that is replaced by the file name;
otherwise, the file name, preceded by blank, is added at the end.")
-
(custom-autoload 'tex-bibtex-command "tex-mode" t)
-
(defvar tex-dvi-print-command (purecopy "lpr -d") "\
Command used by \\[tex-print] to print a .dvi file.
If this string contains an asterisk (`*'), that is replaced by the file name;
otherwise, the file name, preceded by blank, is added at the end.")
-
(custom-autoload 'tex-dvi-print-command "tex-mode" t)
-
(defvar tex-alt-dvi-print-command (purecopy "lpr -d") "\
Command used by \\[tex-print] with a prefix arg to print a .dvi file.
If this string contains an asterisk (`*'), that is replaced by the file name;
@@ -34078,9 +30518,7 @@ for example,
would tell \\[tex-print] with a prefix argument to ask you which printer to
use.")
-
(custom-autoload 'tex-alt-dvi-print-command "tex-mode" t)
-
(defvar tex-dvi-view-command `(cond ((eq window-system 'x) ,(purecopy "xdvi")) ((eq window-system 'w32) ,(purecopy "yap")) (t ,(purecopy "dvi2tty * | cat -s"))) "\
Command used by \\[tex-view] to display a `.dvi' file.
If it is a string, that specifies the command directly.
@@ -34088,33 +30526,23 @@ If this string contains an asterisk (`*'), that is replaced by the file name;
otherwise, the file name, preceded by a space, is added at the end.
If the value is a form, it is evaluated to get the command to use.")
-
(custom-autoload 'tex-dvi-view-command "tex-mode" t)
-
(defvar tex-show-queue-command (purecopy "lpq") "\
Command used by \\[tex-show-print-queue] to show the print queue.
Should show the queue(s) that \\[tex-print] puts jobs on.")
-
(custom-autoload 'tex-show-queue-command "tex-mode" t)
-
(defvar tex-default-mode #'latex-mode "\
Mode to enter for a new file that might be either TeX or LaTeX.
This variable is used when it can't be determined whether the file
is plain TeX or LaTeX or what because the file contains no commands.
Normally set to either `plain-tex-mode' or `latex-mode'.")
-
(custom-autoload 'tex-default-mode "tex-mode" t)
-
(defvar tex-open-quote (purecopy "``") "\
String inserted by typing \\[tex-insert-quote] to open a quotation.")
-
(custom-autoload 'tex-open-quote "tex-mode" t)
-
(defvar tex-close-quote (purecopy "''") "\
String inserted by typing \\[tex-insert-quote] to close a quotation.")
-
(custom-autoload 'tex-close-quote "tex-mode" t)
-
(autoload 'tex-mode "tex-mode" "\
Major mode for editing files of input for TeX, LaTeX, or SliTeX.
This is the shared parent mode of several submodes.
@@ -34124,14 +30552,10 @@ this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',
such as if there are no commands in the file, the value of `tex-default-mode'
says which mode to use.
-\(fn)" t nil)
-
+(fn)" t nil)
(defalias 'TeX-mode #'tex-mode)
-
(defalias 'plain-TeX-mode #'plain-tex-mode)
-
(defalias 'LaTeX-mode #'latex-mode)
-
(autoload 'plain-tex-mode "tex-mode" "\
Major mode for editing files of input for plain TeX.
Makes $ and } display the characters they match.
@@ -34173,8 +30597,7 @@ Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
special subshell is initiated, the hook `tex-shell-hook' is run.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'latex-mode "tex-mode" "\
Major mode for editing files of input for LaTeX.
Makes $ and } display the characters they match.
@@ -34216,8 +30639,7 @@ Entering Latex mode runs the hook `text-mode-hook', then
`tex-mode-hook', and finally `latex-mode-hook'. When the special
subshell is initiated, `tex-shell-hook' is run.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'slitex-mode "tex-mode" "\
Major mode for editing files of input for SliTeX.
Makes $ and } display the characters they match.
@@ -34260,20 +30682,25 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
`slitex-mode-hook'. When the special subshell is initiated, the hook
`tex-shell-hook' is run.
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'tex-start-shell "tex-mode" nil nil nil)
-
(autoload 'doctex-mode "tex-mode" "\
Major mode to edit DocTeX files.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "tex-mode" '("doctex-font-lock-" "latex-" "plain-tex-mode-map" "tex-"))
-;;;***
-;;;### (autoloads nil "texinfmt" "textmodes/texinfmt.el" (0 0 0 0))
+;;; Generated autoloads from cedet/srecode/texi.el
+
+(register-definition-prefixes "srecode/texi" '("semantic-insert-foreign-tag" "srecode-texi-"))
+
+
+;;; Generated autoloads from cedet/semantic/texi.el
+
+(register-definition-prefixes "semantic/texi" '("semantic-"))
+
+
;;; Generated autoloads from textmodes/texinfmt.el
(autoload 'texinfo-format-buffer "texinfmt" "\
@@ -34285,16 +30712,14 @@ Non-nil argument (prefix, if interactive) means don't make tag table
and don't split the file if large. You can use `Info-tagify' and
`Info-split' to do these manually.
-\(fn &optional NOSPLIT)" t nil)
-
+(fn &optional NOSPLIT)" t nil)
(autoload 'texinfo-format-region "texinfmt" "\
Convert the current region of the Texinfo file to Info format.
This lets you see what that part of the file will look like in Info.
The command is bound to \\[texinfo-format-region]. The text that is
converted to Info is stored in a temporary buffer.
-\(fn REGION-BEGINNING REGION-END)" t nil)
-
+(fn REGION-BEGINNING REGION-END)" t nil)
(autoload 'texi2info "texinfmt" "\
Convert the current buffer (written in Texinfo code) into an Info file.
The Info file output is generated in a buffer visiting the Info file
@@ -34308,25 +30733,18 @@ Texinfo source buffer is not changed.
Non-nil argument (prefix, if interactive) means don't split the file
if large. You can use `Info-split' to do this manually.
-\(fn &optional NOSPLIT)" t nil)
-
+(fn &optional NOSPLIT)" t nil)
(register-definition-prefixes "texinfmt" '("batch-texinfo-format" "texinf"))
-;;;***
-;;;### (autoloads nil "texinfo" "textmodes/texinfo.el" (0 0 0 0))
;;; Generated autoloads from textmodes/texinfo.el
(defvar texinfo-open-quote (purecopy "``") "\
String inserted by typing \\[texinfo-insert-quote] to open a quotation.")
-
(custom-autoload 'texinfo-open-quote "texinfo" t)
-
(defvar texinfo-close-quote (purecopy "''") "\
String inserted by typing \\[texinfo-insert-quote] to close a quotation.")
-
(custom-autoload 'texinfo-close-quote "texinfo" t)
-
(autoload 'texinfo-mode "texinfo" "\
Major mode for editing Texinfo files.
@@ -34394,22 +30812,63 @@ be the first node in the file.
Entering Texinfo mode calls the value of `text-mode-hook', and then the
value of `texinfo-mode-hook'.
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "texinfo" '("texinfo-"))
-;;;***
-;;;### (autoloads nil "text-property-search" "emacs-lisp/text-property-search.el"
-;;;;;; (0 0 0 0))
+;;; Generated autoloads from textmodes/texnfo-upd.el
+
+(register-definition-prefixes "texnfo-upd" '("texinfo-"))
+
+
;;; Generated autoloads from emacs-lisp/text-property-search.el
(register-definition-prefixes "text-property-search" '("text-property-"))
-;;;***
-;;;### (autoloads nil "thai-util" "language/thai-util.el" (0 0 0
-;;;;;; 0))
+;;; Generated autoloads from international/textsec.el
+
+(register-definition-prefixes "textsec" '("textsec-"))
+
+
+;;; Generated autoloads from international/textsec-check.el
+
+(autoload 'textsec-suspicious-p "textsec-check" "\
+Say whether OBJECT is suspicious for use as TYPE.
+If OBJECT is suspicious, return a string explaining the reason
+for considering it suspicious, otherwise return nil.
+
+Available values of TYPE and corresponding OBJECTs are:
+
+ `url' -- a URL; OBJECT should be a URL string.
+
+ `link' -- an HTML link; OBJECT should be a cons cell
+ of the form (URL . LINK-TEXT).
+
+ `domain' -- a Web domain; OBJECT should be a string.
+
+ `local-address' -- the local part of an email address; OBJECT
+ should be a string.
+ `name' -- the \"display name\" part of an email address;
+ OBJECT should be a string.
+
+`email-address' -- a full email address; OBJECT should be a string.
+
+ `email-address-header' -- a raw email address header in RFC 2822 format;
+ OBJECT should be a string.
+
+If the user option `textsec-check' is nil, these checks are
+disabled, and this function always returns nil.
+
+(fn OBJECT TYPE)" nil nil)
+(register-definition-prefixes "textsec-check" '("textsec-check"))
+
+
+;;; Generated autoloads from leim/quail/thai.el
+
+(register-definition-prefixes "quail/thai" '("thai-generate-quail-map"))
+
+
;;; Generated autoloads from language/thai-util.el
(autoload 'thai-compose-region "thai-util" "\
@@ -34417,49 +30876,39 @@ Compose Thai characters in the region.
When called from a program, expects two arguments,
positions (integers or markers) specifying the region.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'thai-compose-string "thai-util" "\
Compose Thai characters in STRING and return the resulting string.
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'thai-compose-buffer "thai-util" "\
Compose Thai characters in the current buffer." t nil)
-
(autoload 'thai-composition-function "thai-util" "\
-\(fn GSTRING DIRECTION)" nil nil)
-
+(fn GSTRING DIRECTION)" nil nil)
(register-definition-prefixes "thai-util" '("exit-thai-language-environment-internal" "setup-thai-language-environment-internal" "thai-"))
-;;;***
-;;;### (autoloads nil "thai-word" "language/thai-word.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from language/thai-word.el
(register-definition-prefixes "thai-word" '("thai-"))
-;;;***
-;;;### (autoloads nil "thingatpt" "thingatpt.el" (0 0 0 0))
;;; Generated autoloads from thingatpt.el
(autoload 'forward-thing "thingatpt" "\
Move forward to the end of the Nth next THING.
THING should be a symbol specifying a type of syntactic entity.
-Possibilities include `symbol', `list', `sexp', `defun',
+Possibilities include `symbol', `list', `sexp', `defun', `number',
`filename', `url', `email', `uuid', `word', `sentence', `whitespace',
`line', and `page'.
-\(fn THING &optional N)" nil nil)
-
+(fn THING &optional N)" nil nil)
(autoload 'bounds-of-thing-at-point "thingatpt" "\
Determine the start and end buffer locations for the THING at point.
THING should be a symbol specifying a type of syntactic entity.
-Possibilities include `symbol', `list', `sexp', `defun',
+Possibilities include `symbol', `list', `sexp', `defun', `number',
`filename', `url', `email', `uuid', `word', `sentence', `whitespace',
`line', and `page'.
@@ -34469,8 +30918,7 @@ valid THING.
Return a cons cell (START . END) giving the start and end
positions of the thing found.
-\(fn THING)" nil nil)
-
+(fn THING)" nil nil)
(autoload 'thing-at-point "thingatpt" "\
Return the THING at point.
THING should be a symbol specifying a type of syntactic entity.
@@ -34484,45 +30932,36 @@ strip text properties from the return value.
See the file `thingatpt.el' for documentation on how to define
a symbol as a valid THING.
-\(fn THING &optional NO-PROPERTIES)" nil nil)
-
+(fn THING &optional NO-PROPERTIES)" nil nil)
(autoload 'bounds-of-thing-at-mouse "thingatpt" "\
Determine start and end locations for THING at mouse click given by EVENT.
Like `bounds-of-thing-at-point', but tries to use the position in EVENT
where the mouse button is clicked to find the thing nearby.
-\(fn EVENT THING)" nil nil)
-
+(fn EVENT THING)" nil nil)
(autoload 'thing-at-mouse "thingatpt" "\
Return the THING at mouse click specified by EVENT.
Like `thing-at-point', but tries to use the position in EVENT
where the mouse button is clicked to find the thing nearby.
-\(fn EVENT THING &optional NO-PROPERTIES)" nil nil)
-
+(fn EVENT THING &optional NO-PROPERTIES)" nil nil)
(autoload 'sexp-at-point "thingatpt" "\
Return the sexp at point, or nil if none is found." nil nil)
-
(autoload 'symbol-at-point "thingatpt" "\
Return the symbol at point, or nil if none is found." nil nil)
-
(autoload 'number-at-point "thingatpt" "\
Return the number at point, or nil if none is found.
Decimal numbers like \"14\" or \"-14.5\", as well as hex numbers
like \"0xBEEF09\" or \"#xBEEF09\", are recognized." nil nil)
-
(autoload 'list-at-point "thingatpt" "\
Return the Lisp list at point, or nil if none is found.
If IGNORE-COMMENT-OR-STRING is non-nil comments and strings are
treated as white space.
-\(fn &optional IGNORE-COMMENT-OR-STRING)" nil nil)
-
+(fn &optional IGNORE-COMMENT-OR-STRING)" nil nil)
(register-definition-prefixes "thingatpt" '("beginning-of-thing" "define-thing-chars" "end-of-thing" "filename" "form-at-point" "in-string-p" "sentence-at-point" "thing-at-point-" "word-at-point"))
-;;;***
-;;;### (autoloads nil "thread" "thread.el" (0 0 0 0))
;;; Generated autoloads from thread.el
(autoload 'thread-handle-event "thread" "\
@@ -34530,132 +30969,108 @@ Handle thread events, propagated by `thread-signal'.
An EVENT has the format
(thread-event THREAD ERROR-SYMBOL DATA)
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'list-threads "thread" "\
Display a list of threads." t nil)
(put 'list-threads 'disabled "Beware: manually canceling threads can ruin your Emacs session.")
-
(register-definition-prefixes "thread" '("thread-list-"))
-;;;***
-;;;### (autoloads nil "thumbs" "thumbs.el" (0 0 0 0))
;;; Generated autoloads from thumbs.el
(autoload 'thumbs-find-thumb "thumbs" "\
Display the thumbnail for IMG.
-\(fn IMG)" t nil)
-
+(fn IMG)" t nil)
(autoload 'thumbs-show-from-dir "thumbs" "\
Make a preview buffer for all images in DIR.
Optional argument REG to select file matching a regexp,
and SAME-WINDOW to show thumbs in the same window.
-\(fn DIR &optional REG SAME-WINDOW)" t nil)
-
+(fn DIR &optional REG SAME-WINDOW)" t nil)
(autoload 'thumbs-dired-show-marked "thumbs" "\
In dired, make a thumbs buffer with marked files." t nil)
-
(autoload 'thumbs-dired-show "thumbs" "\
In dired, make a thumbs buffer with all files in current directory." t nil)
-
(defalias 'thumbs 'thumbs-show-from-dir)
-
(autoload 'thumbs-dired-setroot "thumbs" "\
In dired, call the setroot program on the image at point." t nil)
-
(register-definition-prefixes "thumbs" '("thumbs-"))
-;;;***
-;;;### (autoloads nil "thunk" "emacs-lisp/thunk.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/thunk.el
-(push (purecopy '(thunk 1 0)) package--builtin-versions)
+(push (purecopy '(thunk 1 0)) package--builtin-versions)
(register-definition-prefixes "thunk" '("thunk-"))
-;;;***
-;;;### (autoloads nil "tibet-util" "language/tibet-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from language/tibet-util.el
(autoload 'tibetan-char-p "tibet-util" "\
Check if char CH is Tibetan character.
Returns non-nil if CH is Tibetan. Otherwise, returns nil.
-\(fn CH)" nil nil)
-
+(fn CH)" nil nil)
(autoload 'tibetan-tibetan-to-transcription "tibet-util" "\
Transcribe Tibetan string STR and return the corresponding Roman string.
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'tibetan-transcription-to-tibetan "tibet-util" "\
Convert Tibetan Roman string STR to Tibetan character string.
The returned string has no composition information.
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'tibetan-compose-string "tibet-util" "\
Compose Tibetan string STR.
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'tibetan-compose-region "tibet-util" "\
Compose Tibetan text the region BEG and END.
-\(fn BEG END)" t nil)
-
+(fn BEG END)" t nil)
(autoload 'tibetan-decompose-region "tibet-util" "\
Decompose Tibetan text in the region FROM and TO.
This is different from `decompose-region' because precomposed
Tibetan characters are decomposed into normal Tibetan character
sequences.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'tibetan-decompose-string "tibet-util" "\
Decompose Tibetan string STR.
This is different from `decompose-string' because precomposed
Tibetan characters are decomposed into normal Tibetan character
sequences.
-\(fn STR)" nil nil)
-
+(fn STR)" nil nil)
(autoload 'tibetan-decompose-buffer "tibet-util" "\
Decomposes Tibetan characters in the buffer into their components.
See also the documentation of the function `tibetan-decompose-region'." t nil)
-
(autoload 'tibetan-compose-buffer "tibet-util" "\
Composes Tibetan character components in the buffer.
See also docstring of the function `tibetan-compose-region'." t nil)
-
(autoload 'tibetan-post-read-conversion "tibet-util" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'tibetan-pre-write-conversion "tibet-util" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(autoload 'tibetan-pre-write-canonicalize-for-unicode "tibet-util" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(register-definition-prefixes "tibet-util" '("tibetan-"))
-;;;***
-;;;### (autoloads nil "tildify" "textmodes/tildify.el" (0 0 0 0))
+;;; Generated autoloads from leim/quail/tibetan.el
+
+(register-definition-prefixes "quail/tibetan" '("quail-tib" "tibetan-"))
+
+
;;; Generated autoloads from textmodes/tildify.el
-(push (purecopy '(tildify 4 6 1)) package--builtin-versions)
+(push (purecopy '(tildify 4 6 1)) package--builtin-versions)
(autoload 'tildify-region "tildify" "\
Add hard spaces in the region between BEG and END.
See variables `tildify-pattern', `tildify-space-string', and
@@ -34665,8 +31080,7 @@ This function performs no refilling of the changed text.
If DONT-ASK is set, or called interactively with prefix argument, user
won't be prompted for confirmation of each substitution.
-\(fn BEG END &optional DONT-ASK)" t nil)
-
+(fn BEG END &optional DONT-ASK)" t nil)
(autoload 'tildify-buffer "tildify" "\
Add hard spaces in the current buffer.
See variables `tildify-pattern', `tildify-space-string', and
@@ -34676,8 +31090,7 @@ This function performs no refilling of the changed text.
If DONT-ASK is set, or called interactively with prefix argument, user
won't be prompted for confirmation of each substitution.
-\(fn &optional DONT-ASK)" t nil)
-
+(fn &optional DONT-ASK)" t nil)
(autoload 'tildify-space "tildify" "\
Convert space before point into a hard space if the context is right.
@@ -34699,24 +31112,9 @@ Otherwise, if
remove the hard space and leave only the space character.
This function is meant to be used as a `post-self-insert-hook'." t nil)
-
(autoload 'tildify-mode "tildify" "\
Adds electric behavior to space character.
-This is a minor mode. If called interactively, toggle the `Tildify
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `tildify-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When space is inserted into a buffer in a position where hard space is required
instead (determined by `tildify-space-pattern' and `tildify-space-predicates'),
that space character is replaced by a hard space specified by
@@ -34726,28 +31124,36 @@ When `tildify-mode' is enabled, if `tildify-string-alist' specifies a hard space
representation for current major mode, the `tildify-space-string' buffer-local
variable will be set to the representation.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Tildify mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `tildify-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "tildify" '("tildify-"))
-;;;***
-;;;### (autoloads nil "time" "time.el" (0 0 0 0))
;;; Generated autoloads from time.el
(defvar display-time-day-and-date nil "\
Non-nil means \\[display-time] should display day and date as well as time.")
-
(custom-autoload 'display-time-day-and-date "time" t)
(put 'display-time-string 'risky-local-variable t)
-
(autoload 'display-time "time" "\
Enable display of time, load level, and mail flag in mode lines.
This display updates automatically every minute.
If `display-time-day-and-date' is non-nil, the current day and date
are displayed as well.
This runs the normal hook `display-time-hook' after each update." t nil)
-
(defvar display-time-mode nil "\
Non-nil if Display-Time mode is enabled.
See the `display-time-mode' command
@@ -34755,41 +31161,36 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `display-time-mode'.")
-
(custom-autoload 'display-time-mode "time" nil)
-
(autoload 'display-time-mode "time" "\
Toggle display of time, load level, and mail flag in mode lines.
-This is a minor mode. If called interactively, toggle the
-`Display-Time mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='display-time-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When Display Time mode is enabled, it updates every minute (you
can control the number of seconds between updates by customizing
`display-time-interval'). If `display-time-day-and-date' is
non-nil, the current day and date are displayed as well. This
runs the normal hook `display-time-hook' after each update.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Display-Time mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-(define-obsolete-function-alias 'display-time-world #'world-clock "28.1")
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='display-time-mode)'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
+(define-obsolete-function-alias 'display-time-world #'world-clock "28.1")
(autoload 'world-clock "time" "\
Display a world clock buffer with times in various time zones.
The variable `world-clock-list' specifies which time zones to use.
To turn off the world time display, go to the window and type `\\[quit-window]'." t nil)
-
(autoload 'emacs-uptime "time" "\
Return a string giving the uptime of this instance of Emacs.
FORMAT is a string to format the result, using `format-seconds'.
@@ -34797,21 +31198,16 @@ For example, the Unix uptime command format is \"%D, %z%2h:%.2m\".
If the optional argument HERE is non-nil, insert string at
point.
-\(fn &optional FORMAT HERE)" t nil)
-
+(fn &optional FORMAT HERE)" t nil)
(autoload 'emacs-init-time "time" "\
Return a string giving the duration of the Emacs initialization.
FORMAT is a string to format the result, using `format'. If nil,
the default format \"%f seconds\" is used.
-\(fn &optional FORMAT)" t nil)
-
+(fn &optional FORMAT)" t nil)
(register-definition-prefixes "time" '("display-time-" "legacy-style-world-list" "time--display-world-list" "world-clock-" "zoneinfo-style-world-list"))
-;;;***
-;;;### (autoloads nil "time-date" "calendar/time-date.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/time-date.el
(autoload 'date-to-time "time-date" "\
@@ -34819,61 +31215,49 @@ Parse a string DATE that represents a date-time and return a time value.
DATE should be in one of the forms recognized by `parse-time-string'.
If DATE lacks timezone information, GMT is assumed.
-\(fn DATE)" nil nil)
-
+(fn DATE)" nil nil)
(defalias 'time-to-seconds 'float-time)
-
(defalias 'seconds-to-time 'time-convert)
-
(autoload 'days-to-time "time-date" "\
Convert DAYS into a time value.
-\(fn DAYS)" nil nil)
-
+(fn DAYS)" nil nil)
(autoload 'time-since "time-date" "\
Return the time elapsed since TIME.
TIME should be either a time value or a date-time string.
-\(fn TIME)" nil nil)
-
+(fn TIME)" nil nil)
(define-obsolete-function-alias 'subtract-time 'time-subtract "26.1")
-
(autoload 'date-to-day "time-date" "\
Return the absolute date of DATE, a date-time string.
The absolute date is the number of days elapsed since the imaginary
Gregorian date Sunday, December 31, 1 BC.
-\(fn DATE)" nil nil)
-
+(fn DATE)" nil nil)
(autoload 'days-between "time-date" "\
Return the number of days between DATE1 and DATE2.
DATE1 and DATE2 should be date-time strings.
-\(fn DATE1 DATE2)" nil nil)
-
+(fn DATE1 DATE2)" nil nil)
(autoload 'date-leap-year-p "time-date" "\
Return t if YEAR is a leap year.
-\(fn YEAR)" nil nil)
-
+(fn YEAR)" nil nil)
(autoload 'time-to-day-in-year "time-date" "\
Return the day number within the year corresponding to TIME.
-\(fn TIME)" nil nil)
-
+(fn TIME)" nil nil)
(autoload 'time-to-days "time-date" "\
The absolute date corresponding to TIME, a time value.
The absolute date is the number of days elapsed since the imaginary
Gregorian date Sunday, December 31, 1 BC.
-\(fn TIME)" nil nil)
-
+(fn TIME)" nil nil)
(autoload 'safe-date-to-time "time-date" "\
Parse a string DATE that represents a date-time and return a time value.
If DATE is malformed, return a time value of zeros.
-\(fn DATE)" nil nil)
-
+(fn DATE)" nil nil)
(autoload 'format-seconds "time-date" "\
Use format control STRING to format the number SECONDS.
The valid format specifiers are:
@@ -34900,34 +31284,33 @@ The \"%z\" specifier does not print anything. When it is used, specifiers
must be given in order of decreasing size. To the left of \"%z\", nothing
is output until the first non-zero unit is encountered.
-\(fn STRING SECONDS)" nil nil)
+The \"%x\" specifier does not print anything. When it is used,
+specifiers must be given in order of decreasing size. To the
+right of \"%x\", trailing zero units are not output.
+(fn STRING SECONDS)" nil nil)
(autoload 'seconds-to-string "time-date" "\
Convert the time interval in seconds to a short string.
-\(fn DELAY)" nil nil)
-
+(fn DELAY)" nil nil)
(register-definition-prefixes "time-date" '("date-" "decoded-time-" "encode-time-value" "seconds-to-string" "time-" "with-decoded-time-value"))
-;;;***
-;;;### (autoloads nil "time-stamp" "time-stamp.el" (0 0 0 0))
;;; Generated autoloads from time-stamp.el
+
(put 'time-stamp-format 'safe-local-variable 'stringp)
(put 'time-stamp-time-zone 'safe-local-variable 'time-stamp-zone-type-p)
-
(autoload 'time-stamp-zone-type-p "time-stamp" "\
Return non-nil if ZONE is of the correct type for a timezone rule.
Valid ZONE values are described in the documentation of `format-time-string'.
-\(fn ZONE)" nil nil)
+(fn ZONE)" nil nil)
(put 'time-stamp-line-limit 'safe-local-variable 'integerp)
(put 'time-stamp-start 'safe-local-variable 'stringp)
(put 'time-stamp-end 'safe-local-variable 'stringp)
(put 'time-stamp-inserts-lines 'safe-local-variable 'symbolp)
(put 'time-stamp-count 'safe-local-variable 'integerp)
(put 'time-stamp-pattern 'safe-local-variable 'stringp)
-
(autoload 'time-stamp "time-stamp" "\
Update any time stamp string(s) in the buffer.
This function looks for a time stamp template and updates it with
@@ -34960,19 +31343,14 @@ You can set `time-stamp-pattern' in a file's local variables list
to customize the information in the time stamp and where it is written.
The time stamp is updated only if `time-stamp-active' is non-nil." t nil)
-
(autoload 'time-stamp-toggle-active "time-stamp" "\
Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
With ARG, turn time stamping on if and only if ARG is positive.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(register-definition-prefixes "time-stamp" '("time-stamp-"))
-;;;***
-;;;### (autoloads nil "timeclock" "calendar/timeclock.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/timeclock.el
(defvar timeclock-mode-line-display nil "\
@@ -34982,9 +31360,7 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `timeclock-mode-line-display'.")
-
(custom-autoload 'timeclock-mode-line-display "timeclock" nil)
-
(autoload 'timeclock-mode-line-display "timeclock" "\
Toggle display of the amount of time left today in the mode line.
If `timeclock-use-display-time' is non-nil (the default), then
@@ -34998,13 +31374,12 @@ display (non-nil means on).
If using a customized `timeclock-workday' value, this should be
set before switching this mode on.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'timeclock-in "timeclock" "\
Clock in, recording the current time moment in the timelog.
With a numeric prefix ARG, record the fact that today has only that
many hours in it to be worked. If ARG is a non-numeric prefix argument
-\(non-nil, but not a number), 0 is assumed (working on a holiday or
+(non-nil, but not a number), 0 is assumed (working on a holiday or
weekend). *If not called interactively, ARG should be the number of
_seconds_ worked today*. This feature only has effect the first time
this function is called within a day.
@@ -35014,8 +31389,7 @@ FIND-PROJECT is non-nil -- or the user calls `timeclock-in'
interactively -- call the function `timeclock-get-project-function' to
discover the name of the project.
-\(fn &optional ARG PROJECT FIND-PROJECT)" t nil)
-
+(fn &optional ARG PROJECT FIND-PROJECT)" t nil)
(autoload 'timeclock-out "timeclock" "\
Clock out, recording the current time moment in the timelog.
If a prefix ARG is given, the user has completed the project that was
@@ -35026,16 +31400,14 @@ FIND-REASON is non-nil -- or the user calls `timeclock-out'
interactively -- call the function `timeclock-get-reason-function' to
discover the reason.
-\(fn &optional ARG REASON FIND-REASON)" t nil)
-
+(fn &optional ARG REASON FIND-REASON)" t nil)
(autoload 'timeclock-status-string "timeclock" "\
Report the overall timeclock status at the present moment.
If SHOW-SECONDS is non-nil, display second resolution.
If TODAY-ONLY is non-nil, the display will be relative only to time
worked today, ignoring the time worked on previous days.
-\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
-
+(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
(autoload 'timeclock-change "timeclock" "\
Change to working on a different project.
This clocks out of the current project, then clocks in on a new one.
@@ -35043,16 +31415,13 @@ With a prefix ARG, consider the previous project as finished at the
time of changeover. PROJECT is the name of the last project you were
working on.
-\(fn &optional ARG PROJECT)" t nil)
-
+(fn &optional ARG PROJECT)" t nil)
(autoload 'timeclock-query-out "timeclock" "\
Ask the user whether to clock out.
This is a useful function for adding to `kill-emacs-query-functions'." nil nil)
-
(autoload 'timeclock-reread-log "timeclock" "\
Re-read the timeclock, to account for external changes.
Returns the new value of `timeclock-discrepancy'." t nil)
-
(autoload 'timeclock-workday-remaining-string "timeclock" "\
Return a string representing the amount of time left today.
Display second resolution if SHOW-SECONDS is non-nil. If TODAY-ONLY
@@ -35060,15 +31429,13 @@ is non-nil, the display will be relative only to time worked today.
See `timeclock-relative' for more information about the meaning of
\"relative to today\".
-\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
-
+(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
(autoload 'timeclock-workday-elapsed-string "timeclock" "\
Return a string representing the amount of time worked today.
Display seconds resolution if SHOW-SECONDS is non-nil. If RELATIVE is
non-nil, the amount returned will be relative to past time worked.
-\(fn &optional SHOW-SECONDS)" t nil)
-
+(fn &optional SHOW-SECONDS)" t nil)
(autoload 'timeclock-when-to-leave-string "timeclock" "\
Return a string representing the end of today's workday.
This string is relative to the value of `timeclock-workday'. If
@@ -35076,35 +31443,25 @@ SHOW-SECONDS is non-nil, the value printed/returned will include
seconds. If TODAY-ONLY is non-nil, the value returned will be
relative only to the time worked today, and not to past time.
-\(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
-
+(fn &optional SHOW-SECONDS TODAY-ONLY)" t nil)
(register-definition-prefixes "timeclock" '("timeclock-"))
-;;;***
-;;;### (autoloads nil "timer-list" "emacs-lisp/timer-list.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from emacs-lisp/timer-list.el
(autoload 'list-timers "timer-list" "\
List all timers in a buffer.
-\(fn &optional IGNORE-AUTO NONCONFIRM)" t nil)
+(fn &optional IGNORE-AUTO NONCONFIRM)" t nil)
(put 'list-timers 'disabled "Beware: manually canceling timers can ruin your Emacs session.")
-
(register-definition-prefixes "timer-list" '("timer-list-"))
-;;;***
-;;;### (autoloads nil "timezone" "timezone.el" (0 0 0 0))
;;; Generated autoloads from timezone.el
(register-definition-prefixes "timezone" '("timezone-"))
-;;;***
-;;;### (autoloads nil "titdic-cnv" "international/titdic-cnv.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from international/titdic-cnv.el
(autoload 'titdic-convert "titdic-cnv" "\
@@ -35112,8 +31469,7 @@ Convert a TIT dictionary of FILENAME into a Quail package.
Optional argument DIRNAME if specified is the directory name under which
the generated Quail package is saved.
-\(fn FILENAME &optional DIRNAME)" t nil)
-
+(fn FILENAME &optional DIRNAME)" t nil)
(autoload 'batch-titdic-convert "titdic-cnv" "\
Run `titdic-convert' on the files remaining on the command line.
Use this from the command line, with `-batch';
@@ -35122,16 +31478,13 @@ For example, invoke \"emacs -batch -f batch-titdic-convert XXX.tit\" to
generate Quail package file \"xxx.el\" from TIT dictionary file \"XXX.tit\".
To get complete usage, invoke \"emacs -batch -f batch-titdic-convert -h\".
-\(fn &optional FORCE)" nil nil)
-
+(fn &optional FORCE)" nil nil)
(register-definition-prefixes "titdic-cnv" '("batch-miscdic-convert" "ctlau-" "miscdic-convert" "pinyin-convert" "py-converter" "quail-" "quick-" "tit-" "tsang-" "ziranma-converter"))
-;;;***
-;;;### (autoloads nil "tmm" "tmm.el" (0 0 0 0))
;;; Generated autoloads from tmm.el
- (define-key global-map "\M-`" 'tmm-menubar)
+ (define-key global-map "\M-`" 'tmm-menubar)
(autoload 'tmm-menubar "tmm" "\
Text-mode emulation of looking and choosing from a menubar.
See the documentation for `tmm-prompt'.
@@ -35142,16 +31495,14 @@ Note that \\[menu-bar-open] by default drops down TTY menus; if you want it
to invoke `tmm-menubar' instead, customize the variable
`tty-menu-open-use-tmm' to a non-nil value.
-\(fn &optional X-POSITION)" t nil)
-
+(fn &optional X-POSITION)" t nil)
(autoload 'tmm-menubar-mouse "tmm" "\
Text-mode emulation of looking and choosing from a menubar.
This command is used when you click the mouse in the menubar
on a console which has no window system but does have a mouse.
See the documentation for `tmm-prompt'.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'tmm-prompt "tmm" "\
Text-mode emulation of calling the bindings in keymap.
Creates a text-mode menu of possible choices. You can access the elements
@@ -35167,14 +31518,10 @@ Its value should be an event that has a binding in MENU.
NO-EXECUTE, if non-nil, means to return the command the user selects
instead of executing it.
-\(fn MENU &optional IN-POPUP DEFAULT-ITEM NO-EXECUTE)" nil nil)
-
+(fn MENU &optional IN-POPUP DEFAULT-ITEM NO-EXECUTE)" nil nil)
(register-definition-prefixes "tmm" '("tmm-"))
-;;;***
-;;;### (autoloads nil "todo-mode" "calendar/todo-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from calendar/todo-mode.el
(autoload 'todo-show "todo-mode" "\
@@ -35214,42 +31561,35 @@ by default. The done items are hidden, but typing
items. With non-nil user option `todo-show-with-done' both todo
and done items are always shown on visiting a category.
-\(fn &optional SOLICIT-FILE INTERACTIVE)" t nil)
-
+(fn &optional SOLICIT-FILE INTERACTIVE)" t nil)
(autoload 'todo-mode "todo-mode" "\
Major mode for displaying, navigating and editing todo lists.
\\{todo-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'todo-archive-mode "todo-mode" "\
Major mode for archived todo categories.
\\{todo-archive-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(autoload 'todo-filtered-items-mode "todo-mode" "\
Mode for displaying and reprioritizing top priority Todo.
\\{todo-filtered-items-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "todo-mode" '("todo-"))
-;;;***
-;;;### (autoloads nil "tool-bar" "tool-bar.el" (0 0 0 0))
;;; Generated autoloads from tool-bar.el
(autoload 'toggle-tool-bar-mode-from-frame "tool-bar" "\
Toggle tool bar on or off, based on the status of the current frame.
See `tool-bar-mode' for more information.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'tool-bar-add-item "tool-bar" "\
Add an item to the tool bar.
ICON names the image, DEF is the key definition and KEY is a symbol
@@ -35265,8 +31605,7 @@ ICON.xbm, using `find-image'.
Use this function only to make bindings in the global value of `tool-bar-map'.
To define items in any other map, use `tool-bar-local-item'.
-\(fn ICON DEF KEY &rest PROPS)" nil nil)
-
+(fn ICON DEF KEY &rest PROPS)" nil nil)
(autoload 'tool-bar-local-item "tool-bar" "\
Add an item to the tool bar in map MAP.
ICON names the image, DEF is the key definition and KEY is a symbol
@@ -35279,8 +31618,7 @@ function will first try to use low-color/ICON.xpm if `display-color-cells'
is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
ICON.xbm, using `find-image'.
-\(fn ICON DEF KEY MAP &rest PROPS)" nil nil)
-
+(fn ICON DEF KEY MAP &rest PROPS)" nil nil)
(autoload 'tool-bar-add-item-from-menu "tool-bar" "\
Define tool bar binding for COMMAND in keymap MAP using the given ICON.
This makes a binding for COMMAND in `tool-bar-map', copying its
@@ -35294,8 +31632,7 @@ MAP must contain appropriate binding for `[menu-bar]' which holds a keymap.
Use this function only to make bindings in the global value of `tool-bar-map'.
To define items in any other map, use `tool-bar-local-item-from-menu'.
-\(fn COMMAND ICON &optional MAP &rest PROPS)" nil nil)
-
+(fn COMMAND ICON &optional MAP &rest PROPS)" nil nil)
(autoload 'tool-bar-local-item-from-menu "tool-bar" "\
Define local tool bar binding for COMMAND using the given ICON.
This makes a binding for COMMAND in IN-MAP, copying its binding from
@@ -35307,20 +31644,15 @@ properties to add to the binding.
FROM-MAP must contain appropriate binding for `[menu-bar]' which
holds a keymap.
-\(fn COMMAND ICON IN-MAP &optional FROM-MAP &rest PROPS)" nil nil)
-
-(register-definition-prefixes "tool-bar" '("tool-bar-"))
+(fn COMMAND ICON IN-MAP &optional FROM-MAP &rest PROPS)" nil nil)
+(register-definition-prefixes "tool-bar" '("toggle-tool-bar-mode-from-frame" "tool-bar-"))
-;;;***
-;;;### (autoloads nil "tooltip" "tooltip.el" (0 0 0 0))
;;; Generated autoloads from tooltip.el
(register-definition-prefixes "tooltip" '("tooltip-"))
-;;;***
-;;;### (autoloads nil "tq" "emacs-lisp/tq.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/tq.el
(autoload 'tq-create "tq" "\
@@ -35329,26 +31661,20 @@ PROCESS should be a subprocess capable of sending and receiving
streams of bytes. It may be a local process, or it may be connected
to a tcp server on another machine.
-\(fn PROCESS)" nil nil)
-
+(fn PROCESS)" nil nil)
(register-definition-prefixes "tq" '("tq-"))
-;;;***
-;;;### (autoloads nil "trace" "emacs-lisp/trace.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/trace.el
(defvar trace-buffer "*trace-output*" "\
Trace output will by default go to that buffer.")
-
(custom-autoload 'trace-buffer "trace" t)
-
(autoload 'trace-values "trace" "\
Helper function to get internal values.
You can call this function to add internal values in the trace buffer.
-\(fn &rest VALUES)" nil nil)
-
+(fn &rest VALUES)" nil nil)
(autoload 'trace-function-foreground "trace" "\
Trace calls to function FUNCTION.
With a prefix argument, also prompt for the trace buffer (default
@@ -35369,220 +31695,155 @@ stuff - use `trace-function-background' instead.
To stop tracing a function, use `untrace-function' or `untrace-all'.
-\(fn FUNCTION &optional BUFFER CONTEXT)" t nil)
-
+(fn FUNCTION &optional BUFFER CONTEXT)" t nil)
(autoload 'trace-function-background "trace" "\
Trace calls to function FUNCTION, quietly.
This is like `trace-function-foreground', but without popping up
the output buffer or changing the window configuration.
-\(fn FUNCTION &optional BUFFER CONTEXT)" t nil)
-
+(fn FUNCTION &optional BUFFER CONTEXT)" t nil)
(defalias 'trace-function 'trace-function-foreground)
-
(register-definition-prefixes "trace" '("inhibit-trace" "trace-" "untrace-"))
-;;;***
-;;;### (autoloads nil "tramp" "net/tramp.el" (0 0 0 0))
;;; Generated autoloads from net/tramp.el
+
(when (featurep 'tramp-compat)
(load "tramp-compat" 'noerror 'nomessage))
-
(defvar tramp-mode t "\
Whether Tramp is enabled.
If it is set to nil, all remote file names are used literally.")
-
(custom-autoload 'tramp-mode "tramp" t)
-
(defconst tramp-initial-file-name-regexp "\\`/[^/:]+:[^/:]*:" "\
Value for `tramp-file-name-regexp' for autoload.
It must match the initial `tramp-syntax' settings.")
-
(defvar tramp-file-name-regexp tramp-initial-file-name-regexp "\
Regular expression matching file names handled by Tramp.
This regexp should match Tramp file names but no other file
names. When calling `tramp-register-file-name-handlers', the
initial value is overwritten by the car of `tramp-file-name-structure'.")
-
(defvar tramp-ignored-file-name-regexp nil "\
Regular expression matching file names that are not under Tramp's control.")
-
(custom-autoload 'tramp-ignored-file-name-regexp "tramp" t)
-
(defconst tramp-autoload-file-name-regexp (concat "\\`/" (if (memq system-type '(cygwin windows-nt)) "\\(-\\|[^/|:]\\{2,\\}\\)" "[^/|:]+") ":") "\
Regular expression matching file names handled by Tramp autoload.
It must match the initial `tramp-syntax' settings. It should not
match file names at root of the underlying local file system,
like \"/sys\" or \"/C:\".")
-
(defun tramp-autoload-file-name-handler (operation &rest args) "\
Load Tramp file name handler, and perform OPERATION." (tramp-unload-file-name-handlers) (when tramp-mode (let ((default-directory temporary-file-directory)) (when (bound-and-true-p tramp-archive-autoload) (load "tramp-archive" 'noerror 'nomessage)) (load "tramp" 'noerror 'nomessage))) (apply operation args))
-
(defun tramp-register-autoload-file-name-handlers nil "\
-Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp #'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 'safe-magic t))
+Add Tramp file name handlers to `file-name-handler-alist' during autoload." (unless (rassq #'tramp-file-name-handler file-name-handler-alist) (add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp #'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 'safe-magic t)))
(tramp-register-autoload-file-name-handlers)
-
(defun tramp-unload-file-name-handlers nil "\
Unload Tramp file name handlers from `file-name-handler-alist'." (dolist (fnh file-name-handler-alist) (when (and (symbolp (cdr fnh)) (string-prefix-p "tramp-" (symbol-name (cdr fnh)))) (setq file-name-handler-alist (delq fnh file-name-handler-alist)))))
-
(defun tramp-unload-tramp nil "\
Discard Tramp from loading remote files." (interactive) (ignore-errors (unload-feature 'tramp 'force)))
-
(register-definition-prefixes "tramp" '("tramp-" "with-"))
-;;;***
-;;;### (autoloads nil "tramp-adb" "net/tramp-adb.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-adb.el
(register-definition-prefixes "tramp-adb" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-archive" "net/tramp-archive.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from net/tramp-archive.el
(defvar tramp-archive-enabled (featurep 'dbusbind) "\
Non-nil when file archive support is available.")
-
-(defconst tramp-archive-suffixes '("7z" "apk" "ar" "cab" "CAB" "cpio" "crate" "deb" "depot" "exe" "iso" "jar" "lzh" "LZH" "msu" "MSU" "mtree" "odb" "odf" "odg" "odp" "ods" "odt" "pax" "rar" "rpm" "shar" "tar" "tbz" "tgz" "tlz" "txz" "tzst" "warc" "xar" "xpi" "xps" "zip" "ZIP") "\
+(defconst tramp-archive-suffixes '("7z" "apk" "ar" "cab" "CAB" "cpio" "crate" "deb" "depot" "epub" "exe" "iso" "jar" "lzh" "LZH" "msu" "MSU" "mtree" "odb" "odf" "odg" "odp" "ods" "odt" "pax" "rar" "rpm" "shar" "tar" "tbz" "tgz" "tlz" "txz" "tzst" "warc" "xar" "xpi" "xps" "zip" "ZIP") "\
List of suffixes which indicate a file archive.
It must be supported by libarchive(3).")
-
(defconst tramp-archive-compression-suffixes '("bz2" "gz" "lrz" "lz" "lz4" "lzma" "lzo" "uu" "xz" "Z" "zst") "\
List of suffixes which indicate a compressed file.
It must be supported by libarchive(3).")
-
(defmacro tramp-archive-autoload-file-name-regexp nil "\
Regular expression matching archive file names." '(concat "\\`" "\\(" ".+" "\\." (regexp-opt tramp-archive-suffixes) "\\(?:" "\\." (regexp-opt tramp-archive-compression-suffixes) "\\)*" "\\)" "\\(" "/" ".*" "\\)" "\\'"))
-
(defun tramp-archive-autoload-file-name-handler (operation &rest args) "\
-Load Tramp archive file name handler, and perform OPERATION." (defvar tramp-archive-autoload) (when tramp-archive-enabled (let ((default-directory temporary-file-directory) (tramp-archive-autoload t)) (apply #'tramp-autoload-file-name-handler operation args))))
-
+Load Tramp archive file name handler, and perform OPERATION." (defvar tramp-archive-autoload) (let ((default-directory temporary-file-directory) (tramp-archive-autoload tramp-archive-enabled)) (apply #'tramp-autoload-file-name-handler operation args)))
(defun tramp-register-archive-file-name-handler nil "\
-Add archive file name handler to `file-name-handler-alist'." (when tramp-archive-enabled (add-to-list 'file-name-handler-alist (cons (tramp-archive-autoload-file-name-regexp) #'tramp-archive-autoload-file-name-handler)) (put #'tramp-archive-autoload-file-name-handler 'safe-magic t)))
-
+Add archive file name handler to `file-name-handler-alist'." (when (and tramp-archive-enabled (not (rassq #'tramp-archive-file-name-handler file-name-handler-alist))) (add-to-list 'file-name-handler-alist (cons (tramp-archive-autoload-file-name-regexp) #'tramp-archive-autoload-file-name-handler)) (put #'tramp-archive-autoload-file-name-handler 'safe-magic t)))
(add-hook 'after-init-hook #'tramp-register-archive-file-name-handler)
-
(add-hook 'tramp-archive-unload-hook (lambda nil (remove-hook 'after-init-hook #'tramp-register-archive-file-name-handler)))
-
(register-definition-prefixes "tramp-archive" '("tramp-" "with-parsed-tramp-archive-file-name"))
-;;;***
-;;;### (autoloads nil "tramp-cache" "net/tramp-cache.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-cache.el
(register-definition-prefixes "tramp-cache" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-cmds" "net/tramp-cmds.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-cmds.el
(register-definition-prefixes "tramp-cmds" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-compat" "net/tramp-compat.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/tramp-compat.el
(register-definition-prefixes "tramp-compat" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-crypt" "net/tramp-crypt.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-crypt.el
(register-definition-prefixes "tramp-crypt" '("tramp-crypt-"))
-;;;***
-;;;### (autoloads nil "tramp-ftp" "net/tramp-ftp.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-ftp.el
(register-definition-prefixes "tramp-ftp" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-fuse" "net/tramp-fuse.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-fuse.el
(register-definition-prefixes "tramp-fuse" '("tramp-fuse-"))
-;;;***
-;;;### (autoloads nil "tramp-gvfs" "net/tramp-gvfs.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-gvfs.el
(register-definition-prefixes "tramp-gvfs" '("tramp-" "with-tramp-dbus-"))
-;;;***
-;;;### (autoloads nil "tramp-integration" "net/tramp-integration.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from net/tramp-integration.el
(register-definition-prefixes "tramp-integration" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-rclone" "net/tramp-rclone.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from net/tramp-rclone.el
(register-definition-prefixes "tramp-rclone" '("tramp-rclone-"))
-;;;***
-;;;### (autoloads nil "tramp-sh" "net/tramp-sh.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-sh.el
(register-definition-prefixes "tramp-sh" '("tramp-"))
-;;;***
-;;;### (autoloads nil "tramp-smb" "net/tramp-smb.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-smb.el
(register-definition-prefixes "tramp-smb" '("tramp-smb-"))
-;;;***
-;;;### (autoloads nil "tramp-sshfs" "net/tramp-sshfs.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-sshfs.el
(register-definition-prefixes "tramp-sshfs" '("tramp-sshfs-"))
-;;;***
-;;;### (autoloads nil "tramp-sudoedit" "net/tramp-sudoedit.el" (0
-;;;;;; 0 0 0))
;;; Generated autoloads from net/tramp-sudoedit.el
(register-definition-prefixes "tramp-sudoedit" '("tramp-sudoedit-"))
-;;;***
-;;;### (autoloads nil "tramp-uu" "net/tramp-uu.el" (0 0 0 0))
;;; Generated autoloads from net/tramp-uu.el
(register-definition-prefixes "tramp-uu" '("tramp-uu"))
-;;;***
-;;;### (autoloads nil "trampver" "net/trampver.el" (0 0 0 0))
;;; Generated autoloads from net/trampver.el
-(push (purecopy '(tramp 2 6 0 -1)) package--builtin-versions)
+(push (purecopy '(tramp 2 6 0 -1)) package--builtin-versions)
(register-definition-prefixes "trampver" '("tramp-"))
-;;;***
-;;;### (autoloads nil "transient" "transient.el" (0 0 0 0))
;;; Generated autoloads from transient.el
(autoload 'transient-insert-suffix "transient" "\
@@ -35595,10 +31856,8 @@ LOC is a command, a key vector, a key description (a string
(whose last element may also be a command or key).
See info node `(transient)Modifying Existing Transients'.
-\(fn PREFIX LOC SUFFIX)" nil nil)
-
+(fn PREFIX LOC SUFFIX)" nil nil)
(function-put 'transient-insert-suffix 'lisp-indent-function 'defun)
-
(autoload 'transient-append-suffix "transient" "\
Insert a SUFFIX into PREFIX after LOC.
PREFIX is a prefix command, a symbol.
@@ -35609,10 +31868,8 @@ LOC is a command, a key vector, a key description (a string
(whose last element may also be a command or key).
See info node `(transient)Modifying Existing Transients'.
-\(fn PREFIX LOC SUFFIX)" nil nil)
-
+(fn PREFIX LOC SUFFIX)" nil nil)
(function-put 'transient-append-suffix 'lisp-indent-function 'defun)
-
(autoload 'transient-replace-suffix "transient" "\
Replace the suffix at LOC in PREFIX with SUFFIX.
PREFIX is a prefix command, a symbol.
@@ -35623,10 +31880,8 @@ LOC is a command, a key vector, a key description (a string
(whose last element may also be a command or key).
See info node `(transient)Modifying Existing Transients'.
-\(fn PREFIX LOC SUFFIX)" nil nil)
-
+(fn PREFIX LOC SUFFIX)" nil nil)
(function-put 'transient-replace-suffix 'lisp-indent-function 'defun)
-
(autoload 'transient-remove-suffix "transient" "\
Remove the suffix or group at LOC in PREFIX.
PREFIX is a prefix command, a symbol.
@@ -35635,22 +31890,16 @@ LOC is a command, a key vector, a key description (a string
(whose last element may also be a command or key).
See info node `(transient)Modifying Existing Transients'.
-\(fn PREFIX LOC)" nil nil)
-
+(fn PREFIX LOC)" nil nil)
(function-put 'transient-remove-suffix 'lisp-indent-function 'defun)
-
(register-definition-prefixes "transient" '("magit--fit-window-to-buffer" "transient-"))
-;;;***
-;;;### (autoloads nil "tree-widget" "tree-widget.el" (0 0 0 0))
;;; Generated autoloads from tree-widget.el
(register-definition-prefixes "tree-widget" '("tree-widget-"))
-;;;***
-;;;### (autoloads nil "tutorial" "tutorial.el" (0 0 0 0))
;;; Generated autoloads from tutorial.el
(autoload 'help-with-tutorial "tutorial" "\
@@ -35670,31 +31919,24 @@ When the tutorial buffer is killed the content and the point
position in the buffer is saved so that the tutorial may be
resumed later.
-\(fn &optional ARG DONT-ASK-FOR-REVERT)" t nil)
-
+(fn &optional ARG DONT-ASK-FOR-REVERT)" t nil)
(register-definition-prefixes "tutorial" '("get-lang-string" "lang-strings" "tutorial--"))
-;;;***
-;;;### (autoloads nil "tv-util" "language/tv-util.el" (0 0 0 0))
;;; Generated autoloads from language/tv-util.el
(autoload 'tai-viet-composition-function "tv-util" "\
-\(fn FROM TO FONT-OBJECT STRING DIRECTION)" nil nil)
-
+(fn FROM TO FONT-OBJECT STRING DIRECTION)" nil nil)
(register-definition-prefixes "tv-util" '("tai-viet-"))
-;;;***
-;;;### (autoloads nil "two-column" "textmodes/two-column.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from textmodes/two-column.el
+
(autoload '2C-command "two-column" () t 'keymap)
(global-set-key "\C-x6" #'2C-command)
(global-set-key [f2] #'2C-command)
-
(autoload '2C-two-columns "two-column" "\
Split current window vertically for two-column editing.
\\<global-map>When called the first time, associates a buffer with the current
@@ -35703,17 +31945,15 @@ for details.). It runs `2C-other-buffer-hook' in the new buffer.
When called again, restores the screen layout with the current buffer
first and the associated buffer to its right.
-\(fn &optional BUFFER)" t nil)
-
+(fn &optional BUFFER)" t nil)
(autoload '2C-associate-buffer "two-column" "\
Associate another BUFFER with this one in two-column minor mode.
Can also be used to associate a just previously visited file, by
accepting the proposed default buffer.
-\(See \\[describe-mode] .)
-
-\(fn BUFFER)" t nil)
+(See \\[describe-mode] .)
+(fn BUFFER)" t nil)
(autoload '2C-split "two-column" "\
Split a two-column text at point, into two buffers in two-column minor mode.
Point becomes the local value of `2C-window-width'. Only lines that
@@ -35730,15 +31970,12 @@ First column's text sSs Second column's text
/ \\
5 character Separator You type M-5 \\[2C-split] with the point here.
-\(See \\[describe-mode] .)
-
-\(fn ARG)" t nil)
+(See \\[describe-mode] .)
+(fn ARG)" t nil)
(register-definition-prefixes "two-column" '("2C-"))
-;;;***
-;;;### (autoloads nil "type-break" "type-break.el" (0 0 0 0))
;;; Generated autoloads from type-break.el
(defvar type-break-mode nil "\
@@ -35748,26 +31985,11 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `type-break-mode'.")
-
(custom-autoload 'type-break-mode "type-break" nil)
-
(autoload 'type-break-mode "type-break" "\
Enable or disable typing-break mode.
-This is a minor mode, but it is global to all buffers by default.
-
-This is a minor mode. If called interactively, toggle the `Type-Break
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='type-break-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+This is a minor mode, but it is global to all buffers by default.
When this mode is enabled, the user is encouraged to take typing breaks at
appropriate intervals; either after a specified amount of time or when the
@@ -35836,8 +32058,21 @@ across Emacs sessions. This provides recovery of the break status between
sessions and after a crash. Manual changes to the file may result in
problems.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Type-Break mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='type-break-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'type-break "type-break" "\
Take a typing break.
@@ -35846,12 +32081,10 @@ During the break, a demo selected from the functions listed in
After the typing break is finished, the next break is scheduled
as per the function `type-break-schedule'." t nil)
-
(autoload 'type-break-statistics "type-break" "\
Print statistics about typing breaks in a temporary buffer.
This includes the last time a typing break was taken, when the next one is
scheduled, the keystroke thresholds and the current keystroke count, etc." t nil)
-
(autoload 'type-break-guesstimate-keystroke-threshold "type-break" "\
Guess values for the minimum/maximum keystroke threshold for typing breaks.
@@ -35874,29 +32107,10 @@ fraction of the maximum threshold to which to set the minimum threshold.
FRAC should be the inverse of the fractional value; for example, a value of
2 would mean to use one half, a value of 4 would mean to use one quarter, etc.
-\(fn WPM &optional WORDLEN FRAC)" t nil)
-
+(fn WPM &optional WORDLEN FRAC)" t nil)
(register-definition-prefixes "type-break" '("timep" "type-break-"))
-;;;***
-
-;;;### (autoloads nil "uce" "mail/uce.el" (0 0 0 0))
-;;; Generated autoloads from mail/uce.el
-
-(autoload 'uce-reply-to-uce "uce" "\
-Compose a reply to unsolicited commercial email (UCE).
-Sets up a reply buffer addressed to: the sender, his postmaster,
-his abuse@ address, and the postmaster of the mail relay used.
-You might need to set `uce-mail-reader' before using this.
-
-\(fn &optional IGNORED)" t nil)
-
-(register-definition-prefixes "uce" '("uce-"))
-
-;;;***
-;;;### (autoloads nil "ucs-normalize" "international/ucs-normalize.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from international/ucs-normalize.el
(autoload 'string-glyph-compose "ucs-normalize" "\
@@ -35908,8 +32122,7 @@ For instance:
(string-glyph-compose \"Å\") => \"Å\"
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'string-glyph-decompose "ucs-normalize" "\
Decompose STRING according to the Unicode NFD.
This returns a new string that is the canonical decomposition of STRING,
@@ -35917,14 +32130,10 @@ a.k.a. the \"Unicode Normalization Form D\" of STRING. For instance:
(ucs-normalize-NFD-string \"Å\") => \"Å\"
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(register-definition-prefixes "ucs-normalize" '("ucs-normalize-" "utf-8-hfs"))
-;;;***
-;;;### (autoloads nil "underline" "textmodes/underline.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from textmodes/underline.el
(autoload 'underline-region "underline" "\
@@ -35933,18 +32142,33 @@ Works by overstriking underscores.
Called from program, takes two arguments START and END
which specify the range to operate on.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'ununderline-region "underline" "\
Remove all underlining (overstruck underscores) in the region.
Called from program, takes two arguments START and END
which specify the range to operate on.
-\(fn START END)" t nil)
+(fn START END)" t nil)
+
+
+;;; Generated autoloads from mail/undigest.el
+
+(register-definition-prefixes "undigest" '("rmail-"))
+
+
+;;; Generated autoloads from leim/quail/uni-input.el
+
+(autoload 'ucs-input-activate "quail/uni-input" "\
+Activate UCS input method.
+With ARG, activate UCS input method if and only if ARG is positive.
+
+While this input method is active, the variable
+`input-method-function' is bound to the function `ucs-input-method'.
+
+(fn &optional ARG)" nil nil)
+(register-definition-prefixes "quail/uni-input" '("ucs-input-"))
-;;;***
-;;;### (autoloads nil "unrmail" "mail/unrmail.el" (0 0 0 0))
;;; Generated autoloads from mail/unrmail.el
(autoload 'batch-unrmail "unrmail" "\
@@ -35953,18 +32177,14 @@ Specify the input Rmail Babyl file names as command line arguments.
For each Rmail file, the corresponding output file name
is made by adding `.mail' at the end.
For example, invoke `emacs -batch -f batch-unrmail RMAIL'." nil nil)
-
(autoload 'unrmail "unrmail" "\
Convert old-style Rmail Babyl file FILE to mbox format file TO-FILE.
The variable `unrmail-mbox-format' controls which mbox format to use.
-\(fn FILE TO-FILE)" t nil)
-
+(fn FILE TO-FILE)" t nil)
(register-definition-prefixes "unrmail" '("unrmail-mbox-format"))
-;;;***
-;;;### (autoloads nil "unsafep" "emacs-lisp/unsafep.el" (0 0 0 0))
;;; Generated autoloads from emacs-lisp/unsafep.el
(autoload 'unsafep "unsafep" "\
@@ -35972,13 +32192,10 @@ Return nil if evaluating FORM couldn't possibly do any harm.
Otherwise result is a reason why FORM is unsafe.
VARS is a list of symbols with local bindings like `unsafep-vars'.
-\(fn FORM &optional VARS)" nil nil)
-
+(fn FORM &optional VARS)" nil nil)
(register-definition-prefixes "unsafep" '("safe-functions" "unsafep-"))
-;;;***
-;;;### (autoloads nil "url" "url/url.el" (0 0 0 0))
;;; Generated autoloads from url/url.el
(autoload 'url-retrieve "url" "\
@@ -35994,9 +32211,9 @@ STATUS is a plist representing what happened during the request,
with most recent events first, or an empty list if no events have
occurred. Each pair is one of:
-\(:redirect REDIRECTED-TO) - the request was redirected to this URL.
+(:redirect REDIRECTED-TO) - the request was redirected to this URL.
-\(:error (error type . DATA)) - an error occurred. TYPE is a
+(:error (error type . DATA)) - an error occurred. TYPE is a
symbol that says something about where the error occurred, and
DATA is a list (possibly nil) that describes the error further.
@@ -36015,8 +32232,7 @@ the server.
If URL is a multibyte string, it will be encoded as utf-8 and
URL-encoded before it's used.
-\(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil)
-
+(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil)
(autoload 'url-retrieve-synchronously "url" "\
Retrieve URL synchronously.
Return the buffer containing the data, or nil if there are no data
@@ -36028,20 +32244,15 @@ If INHIBIT-COOKIES is non-nil, refuse to store cookies. If
TIMEOUT is passed, it should be a number that says (in seconds)
how long to wait for a response before giving up.
-\(fn URL &optional SILENT INHIBIT-COOKIES TIMEOUT)" nil nil)
-
+(fn URL &optional SILENT INHIBIT-COOKIES TIMEOUT)" nil nil)
(register-definition-prefixes "url" '("url-"))
-;;;***
-;;;### (autoloads nil "url-about" "url/url-about.el" (0 0 0 0))
;;; Generated autoloads from url/url-about.el
(register-definition-prefixes "url-about" '("url-"))
-;;;***
-;;;### (autoloads nil "url-auth" "url/url-auth.el" (0 0 0 0))
;;; Generated autoloads from url/url-auth.el
(autoload 'url-get-authentication "url-auth" "\
@@ -36063,8 +32274,7 @@ TYPE is the type of authentication to be returned. This is either a string
PROMPT is boolean - specifies whether to ask the user for a username/password
if one cannot be found in the cache
-\(fn URL REALM TYPE PROMPT &optional ARGS)" nil nil)
-
+(fn URL REALM TYPE PROMPT &optional ARGS)" nil nil)
(autoload 'url-register-auth-scheme "url-auth" "\
Register an HTTP authentication method.
@@ -36077,63 +32287,49 @@ RATING a rating between 1 and 10 of the strength of the authentication.
This is used when asking for the best authentication for a specific
URL. The item with the highest rating is returned.
-\(fn TYPE &optional FUNCTION RATING)" nil nil)
-
+(fn TYPE &optional FUNCTION RATING)" nil nil)
(register-definition-prefixes "url-auth" '("url-"))
-;;;***
-;;;### (autoloads nil "url-cache" "url/url-cache.el" (0 0 0 0))
;;; Generated autoloads from url/url-cache.el
(autoload 'url-store-in-cache "url-cache" "\
Store buffer BUFF in the cache.
-\(fn &optional BUFF)" nil nil)
-
+(fn &optional BUFF)" nil nil)
(autoload 'url-is-cached "url-cache" "\
Return non-nil if the URL is cached.
The actual return value is the last modification time of the cache file.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-cache-extract "url-cache" "\
Extract FNAM from the local disk cache.
-\(fn FNAM)" nil nil)
-
+(fn FNAM)" nil nil)
(register-definition-prefixes "url-cache" '("url-"))
-;;;***
-;;;### (autoloads nil "url-cid" "url/url-cid.el" (0 0 0 0))
;;; Generated autoloads from url/url-cid.el
(autoload 'url-cid "url-cid" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-cid" '("url-cid-gnus"))
-;;;***
-;;;### (autoloads nil "url-cookie" "url/url-cookie.el" (0 0 0 0))
;;; Generated autoloads from url/url-cookie.el
(register-definition-prefixes "url-cookie" '("url-cookie"))
-;;;***
-;;;### (autoloads nil "url-dav" "url/url-dav.el" (0 0 0 0))
;;; Generated autoloads from url/url-dav.el
(autoload 'url-dav-supported-p "url-dav" "\
Return WebDAV protocol version supported by URL.
Returns nil if WebDAV is not supported.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-dav-request "url-dav" "\
Perform WebDAV operation METHOD on URL. Return the parsed responses.
Automatically creates an XML request body if TAG is non-nil.
@@ -36150,72 +32346,54 @@ NAMESPACES is an assoc list of (NAMESPACE . EXPANSION), and these are
added to the <TAG> element. The DAV=DAV: namespace is automatically
added to this list, so most requests can just pass in nil.
-\(fn URL METHOD TAG BODY &optional DEPTH HEADERS NAMESPACES)" nil nil)
-
+(fn URL METHOD TAG BODY &optional DEPTH HEADERS NAMESPACES)" nil nil)
(autoload 'url-dav-vc-registered "url-dav" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-dav" '("url-dav-"))
-;;;***
-;;;### (autoloads nil "url-dired" "url/url-dired.el" (0 0 0 0))
;;; Generated autoloads from url/url-dired.el
(register-definition-prefixes "url-dired" '("url-"))
-;;;***
-;;;### (autoloads nil "url-domsuf" "url/url-domsuf.el" (0 0 0 0))
;;; Generated autoloads from url/url-domsuf.el
(register-definition-prefixes "url-domsuf" '("url-domsuf-"))
-;;;***
-;;;### (autoloads nil "url-expand" "url/url-expand.el" (0 0 0 0))
;;; Generated autoloads from url/url-expand.el
(register-definition-prefixes "url-expand" '("url-"))
-;;;***
-;;;### (autoloads nil "url-file" "url/url-file.el" (0 0 0 0))
;;; Generated autoloads from url/url-file.el
(autoload 'url-file "url-file" "\
Handle file: and ftp: URLs.
-\(fn URL CALLBACK CBARGS)" nil nil)
+(fn URL CALLBACK CBARGS)" nil nil)
+(register-definition-prefixes "url-file" '("url-"))
-(register-definition-prefixes "url-file" '("url-file-"))
-
-;;;***
-;;;### (autoloads nil "url-ftp" "url/url-ftp.el" (0 0 0 0))
;;; Generated autoloads from url/url-ftp.el
(register-definition-prefixes "url-ftp" '("url-ftp"))
-;;;***
-;;;### (autoloads nil "url-future" "url/url-future.el" (0 0 0 0))
;;; Generated autoloads from url/url-future.el
(register-definition-prefixes "url-future" '("url-future-"))
-;;;***
-;;;### (autoloads nil "url-gw" "url/url-gw.el" (0 0 0 0))
;;; Generated autoloads from url/url-gw.el
(autoload 'url-gateway-nslookup-host "url-gw" "\
Attempt to resolve the given HOST using nslookup if possible.
-\(fn HOST)" t nil)
-
+(fn HOST)" t nil)
(autoload 'url-open-stream "url-gw" "\
Open a stream to HOST, possibly via a gateway.
Args per `open-network-stream'.
@@ -36225,14 +32403,10 @@ Might do a non-blocking connection; use `process-status' to check.
Optional arg GATEWAY-METHOD specifies the gateway to be used,
overriding the value of `url-gateway-method'.
-\(fn NAME BUFFER HOST SERVICE &optional GATEWAY-METHOD)" nil nil)
-
+(fn NAME BUFFER HOST SERVICE &optional GATEWAY-METHOD)" nil nil)
(register-definition-prefixes "url-gw" '("url-"))
-;;;***
-;;;### (autoloads nil "url-handlers" "url/url-handlers.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from url/url-handlers.el
(defvar url-handler-mode nil "\
@@ -36242,43 +32416,40 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `url-handler-mode'.")
-
(custom-autoload 'url-handler-mode "url-handlers" nil)
-
(autoload 'url-handler-mode "url-handlers" "\
Handle URLs as if they were file names throughout Emacs.
+
After switching on this minor mode, Emacs file primitives handle
URLs. For instance:
-This is a minor mode. If called interactively, toggle the
-`Url-Handler mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='url-handler-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
(file-exists-p \"https://www.gnu.org/\")
=> t
and `C-x C-f https://www.gnu.org/ RET' will give you the HTML at
that URL in a buffer.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Url-Handler mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='url-handler-mode)'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'url-file-handler "url-handlers" "\
Function called from the `file-name-handler-alist' routines.
OPERATION is what needs to be done (`file-exists-p', etc.).
ARGS are the arguments that would have been passed to OPERATION.
-\(fn OPERATION &rest ARGS)" nil nil)
-
+(fn OPERATION &rest ARGS)" nil nil)
(autoload 'url-copy-file "url-handlers" "\
Copy URL to NEWNAME. Both arguments must be strings.
Signal a `file-already-exists' error if file NEWNAME already
@@ -36286,72 +32457,56 @@ exists, unless a third argument OK-IF-ALREADY-EXISTS is supplied
and non-nil. An integer as third argument means request
confirmation if NEWNAME already exists.
-\(fn URL NEWNAME &optional OK-IF-ALREADY-EXISTS &rest IGNORED)" nil nil)
-
+(fn URL NEWNAME &optional OK-IF-ALREADY-EXISTS &rest IGNORED)" nil nil)
(autoload 'url-file-local-copy "url-handlers" "\
Copy URL into a temporary file on this machine.
Returns the name of the local copy, or nil, if FILE is directly
accessible.
-\(fn URL &rest IGNORED)" nil nil)
-
+(fn URL &rest IGNORED)" nil nil)
(autoload 'url-insert-buffer-contents "url-handlers" "\
Insert the contents of BUFFER into current buffer.
This is like `url-insert', but also decodes the current buffer as
if it had been inserted from a file named URL.
-\(fn BUFFER URL &optional VISIT BEG END REPLACE)" nil nil)
-
+(fn BUFFER URL &optional VISIT BEG END REPLACE)" nil nil)
(autoload 'url-insert-file-contents "url-handlers" "\
-\(fn URL &optional VISIT BEG END REPLACE)" nil nil)
-
+(fn URL &optional VISIT BEG END REPLACE)" nil nil)
(register-definition-prefixes "url-handlers" '("url-"))
-;;;***
-;;;### (autoloads nil "url-history" "url/url-history.el" (0 0 0 0))
;;; Generated autoloads from url/url-history.el
(register-definition-prefixes "url-history" '("url-"))
-;;;***
-;;;### (autoloads nil "url-http" "url/url-http.el" (0 0 0 0))
;;; Generated autoloads from url/url-http.el
- (autoload 'url-default-expander "url-expand")
+ (autoload 'url-default-expander "url-expand")
(defalias 'url-https-expand-file-name 'url-default-expander)
(autoload 'url-https "url-http")
(autoload 'url-https-file-exists-p "url-http")
(autoload 'url-https-file-readable-p "url-http")
(autoload 'url-https-file-attributes "url-http")
-
(register-definition-prefixes "url-http" '("url-h"))
-;;;***
-;;;### (autoloads nil "url-imap" "url/url-imap.el" (0 0 0 0))
;;; Generated autoloads from url/url-imap.el
(register-definition-prefixes "url-imap" '("url-imap"))
-;;;***
-;;;### (autoloads nil "url-irc" "url/url-irc.el" (0 0 0 0))
;;; Generated autoloads from url/url-irc.el
(autoload 'url-irc "url-irc" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-irc" '("url-irc-"))
-;;;***
-;;;### (autoloads nil "url-ldap" "url/url-ldap.el" (0 0 0 0))
;;; Generated autoloads from url/url-ldap.el
(autoload 'url-ldap "url-ldap" "\
@@ -36360,101 +32515,76 @@ The return value is a buffer displaying the search results in HTML.
URL can be a URL string, or a URL record of the type returned by
`url-generic-parse-url'.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-ldap" '("url-ldap-"))
-;;;***
-;;;### (autoloads nil "url-mailto" "url/url-mailto.el" (0 0 0 0))
;;; Generated autoloads from url/url-mailto.el
(autoload 'url-mail "url-mailto" "\
-\(fn &rest ARGS)" t nil)
-
+(fn &rest ARGS)" t nil)
(autoload 'url-mailto "url-mailto" "\
Handle the mailto: URL syntax.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-mailto" '("url-mail-goto-field"))
-;;;***
-;;;### (autoloads nil "url-methods" "url/url-methods.el" (0 0 0 0))
;;; Generated autoloads from url/url-methods.el
(register-definition-prefixes "url-methods" '("url-scheme-"))
-;;;***
-;;;### (autoloads nil "url-misc" "url/url-misc.el" (0 0 0 0))
;;; Generated autoloads from url/url-misc.el
(autoload 'url-man "url-misc" "\
Fetch a Unix manual page URL.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-info "url-misc" "\
Fetch a GNU Info URL.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-generic-emulator-loader "url-misc" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(defalias 'url-rlogin 'url-generic-emulator-loader)
-
(defalias 'url-telnet 'url-generic-emulator-loader)
-
(defalias 'url-tn3270 'url-generic-emulator-loader)
-
(autoload 'url-data "url-misc" "\
Fetch a data URL (RFC 2397).
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-misc" '("url-do-terminal-emulator"))
-;;;***
-;;;### (autoloads nil "url-news" "url/url-news.el" (0 0 0 0))
;;; Generated autoloads from url/url-news.el
(autoload 'url-news "url-news" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-snews "url-news" "\
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-news" '("url-news-"))
-;;;***
-;;;### (autoloads nil "url-nfs" "url/url-nfs.el" (0 0 0 0))
;;; Generated autoloads from url/url-nfs.el
(register-definition-prefixes "url-nfs" '("url-nfs"))
-;;;***
-;;;### (autoloads nil "url-parse" "url/url-parse.el" (0 0 0 0))
;;; Generated autoloads from url/url-parse.el
(autoload 'url-recreate-url "url-parse" "\
Recreate a URL string from the parsed URLOBJ.
-\(fn URLOBJ)" nil nil)
-
+(fn URLOBJ)" nil nil)
(autoload 'url-generic-parse-url "url-parse" "\
Return an URL-struct of the parts of URL.
The CL-style struct contains the following fields:
@@ -36494,30 +32624,22 @@ parses to
ATTRIBUTES = nil
FULLNESS = t
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-parse" '("url-"))
-;;;***
-;;;### (autoloads nil "url-privacy" "url/url-privacy.el" (0 0 0 0))
;;; Generated autoloads from url/url-privacy.el
(autoload 'url-setup-privacy-info "url-privacy" "\
Setup variables that expose info about you and your system." t nil)
-
(register-definition-prefixes "url-privacy" '("url-device-type"))
-;;;***
-;;;### (autoloads nil "url-proxy" "url/url-proxy.el" (0 0 0 0))
;;; Generated autoloads from url/url-proxy.el
(register-definition-prefixes "url-proxy" '("url-"))
-;;;***
-;;;### (autoloads nil "url-queue" "url/url-queue.el" (0 0 0 0))
;;; Generated autoloads from url/url-queue.el
(autoload 'url-queue-retrieve "url-queue" "\
@@ -36527,33 +32649,25 @@ but with limits on the degree of parallelism. The variable
`url-queue-parallel-processes' sets the number of concurrent processes.
The variable `url-queue-timeout' sets a timeout.
-\(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil)
-
+(fn URL CALLBACK &optional CBARGS SILENT INHIBIT-COOKIES)" nil nil)
(register-definition-prefixes "url-queue" '("url-queue"))
-;;;***
-;;;### (autoloads nil "url-tramp" "url/url-tramp.el" (0 0 0 0))
;;; Generated autoloads from url/url-tramp.el
(defvar url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet") "\
List of URL protocols for which the work is handled by Tramp.
They must also be covered by `url-handler-regexp'.")
-
(custom-autoload 'url-tramp-protocols "url-tramp" t)
-
(autoload 'url-tramp-file-handler "url-tramp" "\
Function called from the `file-name-handler-alist' routines.
OPERATION is what needs to be done. ARGS are the arguments that
would have been passed to OPERATION.
-\(fn OPERATION &rest ARGS)" nil nil)
-
+(fn OPERATION &rest ARGS)" nil nil)
(register-definition-prefixes "url-tramp" '("url-tramp-convert-"))
-;;;***
-;;;### (autoloads nil "url-util" "url/url-util.el" (0 0 0 0))
;;; Generated autoloads from url/url-util.el
(defvar url-debug nil "\
@@ -36563,19 +32677,15 @@ Debug messages are logged to the *URL-DEBUG* buffer.
If t, all messages will be logged.
If a number, all messages will be logged, as well shown via `message'.
If a list, it is a list of the types of messages to be logged.")
-
(custom-autoload 'url-debug "url-util" t)
-
(autoload 'url-debug "url-util" "\
-\(fn TAG &rest ARGS)" nil nil)
-
+(fn TAG &rest ARGS)" nil nil)
(autoload 'url-parse-args "url-util" "\
-\(fn STR &optional NODOWNCASE)" nil nil)
-
+(fn STR &optional NODOWNCASE)" nil nil)
(autoload 'url-insert-entities-in-string "url-util" "\
Convert HTML markup-start characters to entity references in STRING.
Also replaces the \" character, so that the result may be safely used as
@@ -36586,62 +32696,50 @@ conversion. Replaces these characters as follows:
> ==> &gt;
\" ==> &quot;
-\(fn STRING)" nil nil)
-
+(fn STRING)" nil nil)
(autoload 'url-normalize-url "url-util" "\
Return a \"normalized\" version of URL.
Strips out default port numbers, etc.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-lazy-message "url-util" "\
Just like `message', but is a no-op if called more than once a second.
Will not do anything if `url-show-status' is nil.
-\(fn &rest ARGS)" nil nil)
-
+(fn &rest ARGS)" nil nil)
(autoload 'url-get-normalized-date "url-util" "\
Return a date string that most HTTP servers can understand.
-\(fn &optional SPECIFIED-TIME)" nil nil)
-
+(fn &optional SPECIFIED-TIME)" nil nil)
(autoload 'url-eat-trailing-space "url-util" "\
Remove spaces/tabs at the end of a string.
-\(fn X)" nil nil)
-
+(fn X)" nil nil)
(autoload 'url-strip-leading-spaces "url-util" "\
Remove spaces at the front of a string.
-\(fn X)" nil nil)
-
+(fn X)" nil nil)
(autoload 'url-display-percentage "url-util" "\
-\(fn FMT PERC &rest ARGS)" nil nil)
-
+(fn FMT PERC &rest ARGS)" nil nil)
(autoload 'url-percentage "url-util" "\
-\(fn X Y)" nil nil)
-
+(fn X Y)" nil nil)
(defalias 'url-basepath 'url-file-directory)
-
(autoload 'url-file-directory "url-util" "\
Return the directory part of FILE, for a URL.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'url-file-nondirectory "url-util" "\
Return the nondirectory part of FILE, for a URL.
-\(fn FILE)" nil nil)
-
+(fn FILE)" nil nil)
(autoload 'url-parse-query-string "url-util" "\
-\(fn QUERY &optional DOWNCASE ALLOW-NEWLINES)" nil nil)
-
+(fn QUERY &optional DOWNCASE ALLOW-NEWLINES)" nil nil)
(autoload 'url-build-query-string "url-util" "\
Build a query-string.
@@ -36652,7 +32750,7 @@ Given a QUERY in the form:
(key4)
(key5 \"\"))
-\(This is the same format as produced by `url-parse-query-string')
+(This is the same format as produced by `url-parse-query-string')
This will return a string
\"key1=val1&key2=val2&key3=val1&key3=val2&key4&key5\". Keys may
@@ -36664,8 +32762,7 @@ When SEMICOLONS is given, the separator will be \";\".
When KEEP-EMPTY is given, empty values will show as \"key=\"
instead of just \"key\" as in the example above.
-\(fn QUERY &optional SEMICOLONS KEEP-EMPTY)" nil nil)
-
+(fn QUERY &optional SEMICOLONS KEEP-EMPTY)" nil nil)
(autoload 'url-unhex-string "url-util" "\
Decode %XX sequences in a percent-encoded URL.
If optional second argument ALLOW-NEWLINES is non-nil, then allow the
@@ -36675,8 +32772,7 @@ forbidden in URL encoding.
The resulting string in general requires decoding using an
appropriate coding-system; see `decode-coding-string'.
-\(fn STR &optional ALLOW-NEWLINES)" nil nil)
-
+(fn STR &optional ALLOW-NEWLINES)" nil nil)
(autoload 'url-hexify-string "url-util" "\
URI-encode STRING and return the result.
If STRING is multibyte, it is first converted to a utf-8 byte
@@ -36690,8 +32786,7 @@ allowed characters. Otherwise, ALLOWED-CHARS should be either a
list of allowed chars, or a vector whose Nth element is non-nil
if character N is allowed.
-\(fn STRING &optional ALLOWED-CHARS)" nil nil)
-
+(fn STRING &optional ALLOWED-CHARS)" nil nil)
(autoload 'url-encode-url "url-util" "\
Return a properly URI-encoded version of URL.
This function also performs URI normalization, e.g. converting
@@ -36699,21 +32794,18 @@ the scheme to lowercase if it is uppercase. Apart from
normalization, if URL is already URI-encoded, this function
should return it unchanged.
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(autoload 'url-file-extension "url-util" "\
Return the filename extension of FNAME.
If optional argument X is t, then return the basename
of the file with the extension stripped off.
-\(fn FNAME &optional X)" nil nil)
-
+(fn FNAME &optional X)" nil nil)
(autoload 'url-truncate-url-for-viewing "url-util" "\
Return a shortened version of URL that is WIDTH characters wide or less.
WIDTH defaults to the current frame width.
-\(fn URL &optional WIDTH)" nil nil)
-
+(fn URL &optional WIDTH)" nil nil)
(autoload 'url-view-url "url-util" "\
View the current document's URL.
Optional argument NO-SHOW means just return the URL, don't show it in
@@ -36721,8 +32813,7 @@ the minibuffer.
This uses `url-current-object', set locally to the buffer.
-\(fn &optional NO-SHOW)" t nil)
-
+(fn &optional NO-SHOW)" t nil)
(autoload 'url-domain "url-util" "\
Return the domain of the host of the URL.
Return nil if this can't be determined.
@@ -36730,24 +32821,18 @@ Return nil if this can't be determined.
For instance, this function will return \"fsf.co.uk\" if the host in URL
is \"www.fsf.co.uk\".
-\(fn URL)" nil nil)
-
+(fn URL)" nil nil)
(register-definition-prefixes "url-util" '("url-"))
-;;;***
-;;;### (autoloads nil "url-vars" "url/url-vars.el" (0 0 0 0))
;;; Generated autoloads from url/url-vars.el
(register-definition-prefixes "url-vars" '("url-"))
-;;;***
-;;;### (autoloads nil "userlock" "userlock.el" (0 0 0 0))
;;; Generated autoloads from userlock.el
(put 'create-lockfiles 'safe-local-variable 'booleanp)
-
(autoload 'ask-user-about-lock "userlock" "\
Ask user what to do when he wants to edit FILE but it is locked by OPPONENT.
This function has a choice of three things to do:
@@ -36758,13 +32843,11 @@ This function has a choice of three things to do:
You can redefine this function to choose among those three alternatives
in any way you like.
-\(fn FILE OPPONENT)" nil nil)
-
+(fn FILE OPPONENT)" nil nil)
(autoload 'userlock--ask-user-about-supersession-threat "userlock" "\
-\(fn FILENAME)" nil nil)
-
+(fn FILENAME)" nil nil)
(autoload 'ask-user-about-supersession-threat "userlock" "\
Ask a user who is about to modify an obsolete buffer what to do.
This function has two choices: it can return, in which case the modification
@@ -36774,57 +32857,59 @@ in which case the proposed buffer modification will not be made.
You can rewrite this to use any criterion you like to choose which one to do.
The buffer in question is current when this function is called.
-\(fn FILENAME)" nil nil)
-
+(fn FILENAME)" nil nil)
(autoload 'userlock--handle-unlock-error "userlock" "\
Report an ERROR that occurred while unlocking a file.
-\(fn ERROR)" nil nil)
-
+(fn ERROR)" nil nil)
(register-definition-prefixes "userlock" '("ask-user-about-" "file-" "userlock--check-content-unchanged"))
-;;;***
-;;;### (autoloads nil "utf-7" "international/utf-7.el" (0 0 0 0))
;;; Generated autoloads from international/utf-7.el
(autoload 'utf-7-post-read-conversion "utf-7" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'utf-7-imap-post-read-conversion "utf-7" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'utf-7-pre-write-conversion "utf-7" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(autoload 'utf-7-imap-pre-write-conversion "utf-7" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(register-definition-prefixes "utf-7" '("utf-7-"))
-;;;***
-;;;### (autoloads nil "utf7" "international/utf7.el" (0 0 0 0))
;;; Generated autoloads from international/utf7.el
(autoload 'utf7-encode "utf7" "\
Encode UTF-7 STRING. Use IMAP modification if FOR-IMAP is non-nil.
-\(fn STRING &optional FOR-IMAP)" nil nil)
-
+(fn STRING &optional FOR-IMAP)" nil nil)
(register-definition-prefixes "utf7" '("utf7-"))
-;;;***
-;;;### (autoloads nil "uudecode" "mail/uudecode.el" (0 0 0 0))
+;;; Generated autoloads from cedet/semantic/util.el
+
+(register-definition-prefixes "semantic/util" '("semantic-"))
+
+
+;;; Generated autoloads from cedet/ede/util.el
+
+(register-definition-prefixes "ede/util" '("ede-make-buffer-writable"))
+
+
+;;; Generated autoloads from cedet/semantic/util-modes.el
+
+(register-definition-prefixes "semantic/util-modes" '("semantic-"))
+
+
;;; Generated autoloads from mail/uudecode.el
(autoload 'uudecode-decode-region-external "uudecode" "\
@@ -36832,45 +32917,34 @@ Uudecode region between START and END using external program.
If FILE-NAME is non-nil, save the result to FILE-NAME. The program
used is specified by `uudecode-decoder-program'.
-\(fn START END &optional FILE-NAME)" t nil)
-
+(fn START END &optional FILE-NAME)" t nil)
(autoload 'uudecode-decode-region-internal "uudecode" "\
Uudecode region between START and END without using an external program.
If FILE-NAME is non-nil, save the result to FILE-NAME.
-\(fn START END &optional FILE-NAME)" t nil)
-
+(fn START END &optional FILE-NAME)" t nil)
(autoload 'uudecode-decode-region "uudecode" "\
Uudecode region between START and END.
If FILE-NAME is non-nil, save the result to FILE-NAME.
-\(fn START END &optional FILE-NAME)" nil nil)
-
+(fn START END &optional FILE-NAME)" nil nil)
(register-definition-prefixes "uudecode" '("uudecode-"))
-;;;***
-;;;### (autoloads nil "vc" "vc/vc.el" (0 0 0 0))
;;; Generated autoloads from vc/vc.el
(defvar vc-checkout-hook nil "\
Normal hook (list of functions) run after checking out a file.
See `run-hooks'.")
-
(custom-autoload 'vc-checkout-hook "vc" t)
-
(defvar vc-checkin-hook nil "\
Normal hook (list of functions) run after commit or file checkin.
See also `log-edit-done-hook'.")
-
(custom-autoload 'vc-checkin-hook "vc" t)
-
(defvar vc-before-checkin-hook nil "\
Normal hook (list of functions) run before a commit or a file checkin.
See `run-hooks'.")
-
(custom-autoload 'vc-before-checkin-hook "vc" t)
-
(autoload 'vc-responsible-backend "vc" "\
Return the name of a backend system that is responsible for FILE.
@@ -36886,8 +32960,7 @@ be reported.
If NO-ERROR is nil, signal an error that no VC backend is
responsible for the given file.
-\(fn FILE &optional NO-ERROR)" nil nil)
-
+(fn FILE &optional NO-ERROR)" nil nil)
(autoload 'vc-next-action "vc" "\
Do the next logical version control operation on the current fileset.
This requires that all files in the current VC fileset be in the
@@ -36915,8 +32988,7 @@ When using this command to register a new file (or files), it
will automatically deduce which VC repository to register it
with, using the most specific one.
-\(fn VERBOSE)" t nil)
-
+(fn VERBOSE)" t nil)
(autoload 'vc-register "vc" "\
Register into a version control system.
If VC-FILESET is given, register the files in that fileset.
@@ -36930,8 +33002,7 @@ directory are already registered under that backend) will be used to
register the file. If no backend declares itself responsible, the
first backend that could register the file is used.
-\(fn &optional VC-FILESET COMMENT)" t nil)
-
+(fn &optional VC-FILESET COMMENT)" t nil)
(autoload 'vc-ignore "vc" "\
Ignore FILE under the VCS of DIRECTORY.
@@ -36946,8 +33017,7 @@ When called interactively, prompt for a FILE to ignore, unless a
prefix argument is given, in which case prompt for a file FILE to
remove from the list of ignored files.
-\(fn FILE &optional DIRECTORY REMOVE)" t nil)
-
+(fn FILE &optional DIRECTORY REMOVE)" t nil)
(autoload 'vc-version-diff "vc" "\
Report diffs between revisions REV1 and REV2 in the repository history.
This compares two revisions of the current fileset.
@@ -36956,13 +33026,11 @@ of the last commit.
If REV2 is nil, it defaults to the work tree, i.e. the current
state of each file in the fileset.
-\(fn FILES REV1 REV2)" t nil)
-
+(fn FILES REV1 REV2)" t nil)
(autoload 'vc-root-version-diff "vc" "\
Report diffs between REV1 and REV2 revisions of the whole tree.
-\(fn FILES REV1 REV2)" t nil)
-
+(fn FILES REV1 REV2)" t nil)
(autoload 'vc-diff "vc" "\
Display diffs between file revisions.
Normally this compares the currently selected fileset with their
@@ -36972,14 +33040,12 @@ designators specifying which revisions to compare.
The optional argument NOT-URGENT non-nil means it is ok to say no to
saving the buffer.
-\(fn &optional HISTORIC NOT-URGENT)" t nil)
-
+(fn &optional HISTORIC NOT-URGENT)" t nil)
(autoload 'vc-diff-mergebase "vc" "\
Report diffs between the merge base of REV1 and REV2 revisions.
The merge base is a common ancestor between REV1 and REV2 revisions.
-\(fn FILES REV1 REV2)" t nil)
-
+(fn FILES REV1 REV2)" t nil)
(autoload 'vc-version-ediff "vc" "\
Show differences between REV1 and REV2 of FILES using ediff.
This compares two revisions of the files in FILES. Currently,
@@ -36990,8 +33056,7 @@ of the last commit.
If REV2 is nil, it defaults to the work tree, i.e. the current
state of each file in FILES.
-\(fn FILES REV1 REV2)" t nil)
-
+(fn FILES REV1 REV2)" t nil)
(autoload 'vc-ediff "vc" "\
Display diffs between file revisions using ediff.
Normally this compares the currently selected fileset with their
@@ -37001,8 +33066,7 @@ designators specifying which revisions to compare.
The optional argument NOT-URGENT non-nil means it is ok to say no to
saving the buffer.
-\(fn HISTORIC &optional NOT-URGENT)" t nil)
-
+(fn HISTORIC &optional NOT-URGENT)" t nil)
(autoload 'vc-root-diff "vc" "\
Display diffs between VC-controlled whole tree revisions.
Normally, this compares the tree corresponding to the current
@@ -37013,24 +33077,20 @@ designators specifying which revisions to compare.
The optional argument NOT-URGENT non-nil means it is ok to say no to
saving the buffer.
-\(fn HISTORIC &optional NOT-URGENT)" t nil)
-
+(fn HISTORIC &optional NOT-URGENT)" t nil)
(autoload 'vc-root-dir "vc" "\
Return the root directory for the current VC tree.
Return nil if the root directory cannot be identified." nil nil)
-
(autoload 'vc-revision-other-window "vc" "\
Visit revision REV of the current file in another window.
If the current file is named `F', the revision is named `F.~REV~'.
If `F.~REV~' already exists, use it instead of checking it out again.
-\(fn REV)" t nil)
-
+(fn REV)" t nil)
(autoload 'vc-insert-headers "vc" "\
Insert headers into a file for use with a version control system.
Headers desired are inserted at point, and are pulled from
the variable `vc-BACKEND-header'." t nil)
-
(autoload 'vc-merge "vc" "\
Perform a version control merge operation.
You must be visiting a version controlled file, or in a `vc-dir' buffer.
@@ -37044,17 +33104,13 @@ two revisions to merge from in the minibuffer. If the first
revision is a branch number, then merge all changes from that
branch. If the first revision is empty, merge the most recent
changes from the current branch." t nil)
-
(autoload 'vc-message-unresolved-conflicts "vc" "\
Display a message indicating unresolved conflicts in FILENAME.
-\(fn FILENAME)" nil nil)
-
+(fn FILENAME)" nil nil)
(defalias 'vc-resolve-conflicts 'smerge-ediff)
-
(autoload 'vc-find-conflicted-file "vc" "\
Visit the next conflicted file in the current project." t nil)
-
(autoload 'vc-create-tag "vc" "\
Descending recursively from DIR, make a tag called NAME.
For each registered file, the working revision becomes part of
@@ -37062,8 +33118,7 @@ the named configuration. If the prefix argument BRANCHP is
given, the tag is made as a new branch and the files are
checked out in that new branch.
-\(fn DIR NAME BRANCHP)" t nil)
-
+(fn DIR NAME BRANCHP)" t nil)
(autoload 'vc-retrieve-tag "vc" "\
For each file in or below DIR, retrieve their tagged version NAME.
NAME can name a branch, in which case this command will switch to the
@@ -37076,8 +33131,7 @@ locked files at or below DIR (but if NAME is empty, locked files are
allowed and simply skipped).
This function runs the hook `vc-retrieve-tag-hook' when finished.
-\(fn DIR NAME)" t nil)
-
+(fn DIR NAME)" t nil)
(autoload 'vc-print-log "vc" "\
List the change log of the current fileset in a window.
If WORKING-REVISION is non-nil, leave point at that revision.
@@ -37087,8 +33141,7 @@ number of revisions to show; the default is `vc-log-show-limit'.
When called interactively with a prefix argument, prompt for
WORKING-REVISION and LIMIT.
-\(fn &optional WORKING-REVISION LIMIT)" t nil)
-
+(fn &optional WORKING-REVISION LIMIT)" t nil)
(autoload 'vc-print-root-log "vc" "\
List the revision history for the current VC controlled tree in a window.
If LIMIT is non-nil, it should be a number specifying the maximum
@@ -37099,25 +33152,21 @@ A special case is when the prefix argument is 1: in this case
the command asks for the ID of a revision, and shows that revision
with its diffs (if the underlying VCS supports that).
-\(fn &optional LIMIT REVISION)" t nil)
-
+(fn &optional LIMIT REVISION)" t nil)
(autoload 'vc-print-branch-log "vc" "\
Show the change log for BRANCH root in a window.
-\(fn BRANCH)" t nil)
-
+(fn BRANCH)" t nil)
(autoload 'vc-log-incoming "vc" "\
Show log of changes that will be received with pull from REMOTE-LOCATION.
When called interactively with a prefix argument, prompt for REMOTE-LOCATION.
-\(fn &optional REMOTE-LOCATION)" t nil)
-
+(fn &optional REMOTE-LOCATION)" t nil)
(autoload 'vc-log-outgoing "vc" "\
Show log of changes that will be sent with a push operation to REMOTE-LOCATION.
When called interactively with a prefix argument, prompt for REMOTE-LOCATION.
-\(fn &optional REMOTE-LOCATION)" t nil)
-
+(fn &optional REMOTE-LOCATION)" t nil)
(autoload 'vc-log-search "vc" "\
Search the log of changes for PATTERN.
@@ -37129,27 +33178,23 @@ Display all entries that match log messages in long format.
With a prefix argument, ask for a command to run that will output
log entries.
-\(fn PATTERN)" t nil)
-
+(fn PATTERN)" t nil)
(autoload 'vc-log-mergebase "vc" "\
Show a log of changes between the merge base of REV1 and REV2 revisions.
The merge base is a common ancestor between REV1 and REV2 revisions.
-\(fn FILES REV1 REV2)" t nil)
-
+(fn FILES REV1 REV2)" t nil)
(autoload 'vc-region-history "vc" "\
Show the history of the region between FROM and TO.
If called interactively, show the history between point and
mark.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'vc-revert "vc" "\
Revert working copies of the selected fileset to their repository contents.
This asks for confirmation if the buffer contents are not identical
to the working revision (except for keyword expansion)." t nil)
-
(autoload 'vc-pull "vc" "\
Update the current fileset or branch.
You must be visiting a version controlled file, or in a `vc-dir' buffer.
@@ -37164,10 +33209,8 @@ file, this simply replaces the work file with the latest revision
on its branch. If the file contains changes, any changes in the
tip revision are merged into the working file.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(defalias 'vc-update 'vc-pull)
-
(autoload 'vc-push "vc" "\
Push the current branch.
You must be visiting a version controlled file, or in a `vc-dir' buffer.
@@ -37179,8 +33222,7 @@ VCS command to run.
On a non-distributed version control system, this signals an error.
It also signals an error in a Bazaar bound branch.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'vc-switch-backend "vc" "\
Make BACKEND the current version control system for FILE.
FILE must already be registered in BACKEND. The change is not
@@ -37189,36 +33231,31 @@ VC's perspective on FILE, it does not register or unregister it.
By default, this command cycles through the registered backends.
To get a prompt, use a prefix argument.
-\(fn FILE BACKEND)" t nil)
-
-(make-obsolete 'vc-switch-backend 'nil '"28.1")
-
+(fn FILE BACKEND)" t nil)
+(make-obsolete 'vc-switch-backend 'nil "28.1")
(autoload 'vc-transfer-file "vc" "\
Transfer FILE to another version control system NEW-BACKEND.
If NEW-BACKEND has a higher precedence than FILE's current backend
-\(i.e. it comes earlier in `vc-handled-backends'), then register FILE in
+(i.e. it comes earlier in `vc-handled-backends'), then register FILE in
NEW-BACKEND, using the revision number from the current backend as the
base level. If NEW-BACKEND has a lower precedence than the current
backend, then commit all changes that were made under the current
backend to NEW-BACKEND, and unregister FILE from the current backend.
-\(If FILE is not yet registered under NEW-BACKEND, register it.)
-
-\(fn FILE NEW-BACKEND)" nil nil)
+(If FILE is not yet registered under NEW-BACKEND, register it.)
+(fn FILE NEW-BACKEND)" nil nil)
(autoload 'vc-delete-file "vc" "\
Delete file and mark it as such in the version control system.
If called interactively, read FILE, defaulting to the current
buffer's file name if it's under version control.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'vc-rename-file "vc" "\
Rename file OLD to NEW in both work area and repository.
If called interactively, read OLD and NEW, defaulting OLD to the
current buffer's file name if it's under version control.
-\(fn OLD NEW)" t nil)
-
+(fn OLD NEW)" t nil)
(autoload 'vc-update-change-log "vc" "\
Find change log file and add entries from recent version control logs.
Normally, find log entries for all registered files in the default
@@ -37233,13 +33270,10 @@ log for the default directory, which may not be appropriate.
From a program, any ARGS are assumed to be filenames for which
log entries should be gathered.
-\(fn &rest ARGS)" t nil)
-
+(fn &rest ARGS)" t nil)
(register-definition-prefixes "vc" '("vc-" "with-vc-properties"))
-;;;***
-;;;### (autoloads nil "vc-annotate" "vc/vc-annotate.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-annotate.el
(autoload 'vc-annotate "vc-annotate" "\
@@ -37255,7 +33289,7 @@ everything that is older than that is shown in blue.
With a prefix argument, this command asks two questions in the
minibuffer. First, you may enter a revision number REV; then the buffer
displays and annotates that revision instead of the working revision
-\(type RET in the minibuffer to leave that default unchanged). Then,
+(type RET in the minibuffer to leave that default unchanged). Then,
you are prompted for the time span in days which the color range
should cover. For example, a time span of 20 days means that changes
over the past 20 days are shown in red to blue, according to their
@@ -37274,18 +33308,14 @@ mode-specific menu. `vc-annotate-color-map' and
`vc-annotate-background-mode' specifies whether the color map
should be applied to the background or to the foreground.
-\(fn FILE REV &optional DISPLAY-MODE BUF MOVE-POINT-TO VC-BK)" t nil)
-
+(fn FILE REV &optional DISPLAY-MODE BUF MOVE-POINT-TO VC-BK)" t nil)
(register-definition-prefixes "vc-annotate" '("vc-"))
-;;;***
-;;;### (autoloads nil "vc-bzr" "vc/vc-bzr.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-bzr.el
(defconst vc-bzr-admin-dirname ".bzr" "\
Name of the directory containing Bzr repository status files.")
-
(defconst vc-bzr-admin-checkout-format-file (concat vc-bzr-admin-dirname "/checkout/format") "\
Name of the format file in a .bzr directory.")
(defun vc-bzr-registered (file)
@@ -37293,39 +33323,31 @@ Name of the format file in a .bzr directory.")
(progn
(load "vc-bzr" nil t)
(vc-bzr-registered file))))
-
(register-definition-prefixes "vc-bzr" '("vc-bzr-"))
-;;;***
-;;;### (autoloads nil "vc-cvs" "vc/vc-cvs.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-cvs.el
+
(defun vc-cvs-registered (f)
"Return non-nil if file F is registered with CVS."
(when (file-readable-p (expand-file-name
- "CVS/Entries" (file-name-directory f)))
+ "CVS/Entries" (file-name-directory f)))
(load "vc-cvs" nil t)
(vc-cvs-registered f)))
-
(register-definition-prefixes "vc-cvs" '("vc-cvs-"))
-;;;***
-;;;### (autoloads nil "vc-dav" "vc/vc-dav.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-dav.el
(register-definition-prefixes "vc-dav" '("vc-dav-"))
-;;;***
-;;;### (autoloads nil "vc-dir" "vc/vc-dir.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-dir.el
(autoload 'vc-dir-root "vc-dir" "\
Run `vc-dir' in the repository root directory without prompt.
If the default directory of the current buffer is
not under version control, prompt for a directory." t nil)
-
(autoload 'vc-dir "vc-dir" "\
Show the VC status for \"interesting\" files in and below DIR.
This allows you to mark files and perform VC operations on them.
@@ -37343,21 +33365,16 @@ These are the commands available for use in the file status buffer:
\\{vc-dir-mode-map}
-\(fn DIR &optional BACKEND)" t nil)
-
+(fn DIR &optional BACKEND)" t nil)
(autoload 'vc-dir-bookmark-jump "vc-dir" "\
Provide the `bookmark-jump' behavior for a `vc-dir' buffer.
This implements the `handler' function interface for the record
type returned by `vc-dir-bookmark-make-record'.
-\(fn BMK)" nil nil)
-
+(fn BMK)" nil nil)
(register-definition-prefixes "vc-dir" '("vc-"))
-;;;***
-;;;### (autoloads nil "vc-dispatcher" "vc/vc-dispatcher.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from vc/vc-dispatcher.el
(autoload 'vc-do-command "vc-dispatcher" "\
@@ -37376,115 +33393,73 @@ that is inserted into the command line before the filename.
Return the return value of the slave command in the synchronous
case, and the process object in the asynchronous case.
-\(fn BUFFER OKSTATUS COMMAND FILE-OR-LIST &rest FLAGS)" nil nil)
-
+(fn BUFFER OKSTATUS COMMAND FILE-OR-LIST &rest FLAGS)" nil nil)
(register-definition-prefixes "vc-dispatcher" '("vc-"))
-;;;***
-;;;### (autoloads nil "vc-filewise" "vc/vc-filewise.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-filewise.el
(register-definition-prefixes "vc-filewise" '("vc-"))
-;;;***
-;;;### (autoloads nil "vc-git" "vc/vc-git.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-git.el
+
(defun vc-git-registered (file)
"Return non-nil if FILE is registered with git."
(if (vc-find-root file ".git") ; Short cut.
(progn
(load "vc-git" nil t)
(vc-git-registered file))))
-
(register-definition-prefixes "vc-git" '("vc-"))
-;;;***
-;;;### (autoloads nil "vc-hg" "vc/vc-hg.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-hg.el
+
(defun vc-hg-registered (file)
"Return non-nil if FILE is registered with hg."
(if (vc-find-root file ".hg") ; short cut
(progn
(load "vc-hg" nil t)
(vc-hg-registered file))))
-
(register-definition-prefixes "vc-hg" '("vc-hg-"))
-;;;***
-;;;### (autoloads nil "vc-mtn" "vc/vc-mtn.el" (0 0 0 0))
-;;; Generated autoloads from vc/vc-mtn.el
-
-(defconst vc-mtn-admin-dir "_MTN" "\
-Name of the monotone directory.")
-
-(defconst vc-mtn-admin-format (concat vc-mtn-admin-dir "/format") "\
-Name of the monotone directory's format file.")
- (defun vc-mtn-registered (file)
- (if (vc-find-root file vc-mtn-admin-format)
- (progn
- (load "vc-mtn" nil t)
- (vc-mtn-registered file))))
-
-(register-definition-prefixes "vc-mtn" '("vc-mtn-"))
-
-;;;***
-
-;;;### (autoloads nil "vc-rcs" "vc/vc-rcs.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-rcs.el
(defvar vc-rcs-master-templates (purecopy '("%sRCS/%s,v" "%s%s,v" "%sRCS/%s")) "\
Where to look for RCS master files.
For a description of possible values, see `vc-check-master-templates'.")
-
(custom-autoload 'vc-rcs-master-templates "vc-rcs" t)
-
(defun vc-rcs-registered (f) (vc-default-registered 'RCS f))
-
(register-definition-prefixes "vc-rcs" '("vc-r"))
-;;;***
-;;;### (autoloads nil "vc-sccs" "vc/vc-sccs.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-sccs.el
(defvar vc-sccs-master-templates (purecopy '("%sSCCS/s.%s" "%ss.%s" vc-sccs-search-project-dir)) "\
Where to look for SCCS master files.
For a description of possible values, see `vc-check-master-templates'.")
-
(custom-autoload 'vc-sccs-master-templates "vc-sccs" t)
-
(defun vc-sccs-registered (f) (vc-default-registered 'SCCS f))
-
(defun vc-sccs-search-project-dir (_dirname basename) "\
Return the name of a master file in the SCCS project directory.
Does not check whether the file exists but returns nil if it does not
find any project directory." (let ((project-dir (getenv "PROJECTDIR")) dirs dir) (when project-dir (if (file-name-absolute-p project-dir) (setq dirs '("SCCS" "")) (setq dirs '("src/SCCS" "src" "source/SCCS" "source")) (setq project-dir (expand-file-name (concat "~" project-dir)))) (while (and (not dir) dirs) (setq dir (expand-file-name (car dirs) project-dir)) (unless (file-directory-p dir) (setq dir nil) (setq dirs (cdr dirs)))) (and dir (expand-file-name (concat "s." basename) dir)))))
-
(register-definition-prefixes "vc-sccs" '("vc-sccs-"))
-;;;***
-;;;### (autoloads nil "vc-src" "vc/vc-src.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-src.el
(defvar vc-src-master-templates (purecopy '("%s.src/%s,v")) "\
Where to look for SRC master files.
For a description of possible values, see `vc-check-master-templates'.")
-
(custom-autoload 'vc-src-master-templates "vc-src" t)
-
(defun vc-src-registered (f) (vc-default-registered 'src f))
-
(register-definition-prefixes "vc-src" '("vc-src-"))
-;;;***
-;;;### (autoloads nil "vc-svn" "vc/vc-svn.el" (0 0 0 0))
;;; Generated autoloads from vc/vc-svn.el
+
(defun vc-svn-registered (f)
(let ((admin-dir (cond ((and (eq system-type 'windows-nt)
(getenv "SVN_ASP_DOT_NET_HACK"))
@@ -37493,24 +33468,18 @@ For a description of possible values, see `vc-check-master-templates'.")
(when (vc-find-root f admin-dir)
(load "vc-svn" nil t)
(vc-svn-registered f))))
-
(register-definition-prefixes "vc-svn" '("vc-svn-"))
-;;;***
-;;;### (autoloads nil "vcursor" "vcursor.el" (0 0 0 0))
;;; Generated autoloads from vcursor.el
(register-definition-prefixes "vcursor" '("vcursor-"))
-;;;***
-;;;### (autoloads nil "vera-mode" "progmodes/vera-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/vera-mode.el
+
(push (purecopy '(vera-mode 2 28)) package--builtin-versions)
(add-to-list 'auto-mode-alist (cons (purecopy "\\.vr[hi]?\\'") 'vera-mode))
-
(autoload 'vera-mode "vera-mode" "\
Major mode for editing Vera code.
@@ -37560,17 +33529,13 @@ Key bindings:
\\{vera-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "vera-mode" '("vera-"))
-;;;***
-;;;### (autoloads nil "verilog-mode" "progmodes/verilog-mode.el"
-;;;;;; (0 0 0 0))
;;; Generated autoloads from progmodes/verilog-mode.el
-(push (purecopy '(verilog-mode 2021 10 14 127365406)) package--builtin-versions)
+(push (purecopy '(verilog-mode 2021 10 14 127365406)) package--builtin-versions)
(autoload 'verilog-mode "verilog-mode" "\
Major mode for editing Verilog code.
\\<verilog-mode-map>
@@ -37706,14 +33671,10 @@ Key bindings specific to `verilog-mode-map' are:
\\{verilog-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "verilog-mode" '("electric-verilog-" "verilog-" "vl-"))
-;;;***
-;;;### (autoloads nil "vhdl-mode" "progmodes/vhdl-mode.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from progmodes/vhdl-mode.el
(autoload 'vhdl-mode "vhdl-mode" "\
@@ -38263,74 +34224,57 @@ Key bindings:
\\{vhdl-mode-map}
-\(fn)" t nil)
-
+(fn)" t nil)
(register-definition-prefixes "vhdl-mode" '("vhdl-"))
-;;;***
-;;;### (autoloads nil "viet-util" "language/viet-util.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from language/viet-util.el
(autoload 'viet-encode-viscii-char "viet-util" "\
Return VISCII character code of CHAR if appropriate.
-\(fn CHAR)" nil nil)
-
+(fn CHAR)" nil nil)
(autoload 'viet-decode-viqr-region "viet-util" "\
Convert `VIQR' mnemonics of the current region to Vietnamese characters.
When called from a program, expects two arguments,
positions (integers or markers) specifying the stretch of the region.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'viet-decode-viqr-buffer "viet-util" "\
Convert `VIQR' mnemonics of the current buffer to Vietnamese characters." t nil)
-
(autoload 'viet-encode-viqr-region "viet-util" "\
Convert Vietnamese characters of the current region to `VIQR' mnemonics.
When called from a program, expects two arguments,
positions (integers or markers) specifying the stretch of the region.
-\(fn FROM TO)" t nil)
-
+(fn FROM TO)" t nil)
(autoload 'viet-encode-viqr-buffer "viet-util" "\
Convert Vietnamese characters of the current buffer to `VIQR' mnemonics." t nil)
-
(autoload 'viqr-post-read-conversion "viet-util" "\
-\(fn LEN)" nil nil)
-
+(fn LEN)" nil nil)
(autoload 'viqr-pre-write-conversion "viet-util" "\
-\(fn FROM TO)" nil nil)
-
+(fn FROM TO)" nil nil)
(register-definition-prefixes "viet-util" '("viet-viqr-alist" "viqr-regexp"))
-;;;***
-;;;### (autoloads nil "view" "view.el" (0 0 0 0))
;;; Generated autoloads from view.el
(defvar view-remove-frame-by-deleting t "\
Determine how View mode removes a frame no longer needed.
If nil, make an icon of the frame. If non-nil, delete the frame.")
-
(custom-autoload 'view-remove-frame-by-deleting "view" t)
-
(defvar-local view-mode nil "\
Non-nil if View mode is enabled.
Don't change this variable directly, you must change it by one of the
functions that enable or disable view mode.")
-
(autoload 'kill-buffer-if-not-modified "view" "\
Like `kill-buffer', but does nothing if buffer BUF is modified.
-\(fn BUF)" nil nil)
-
+(fn BUF)" nil nil)
(autoload 'view-file "view" "\
View FILE in View mode, returning to previous buffer when done.
Emacs commands editing the buffer contents are not available; instead, a
@@ -38341,8 +34285,7 @@ For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'view-file-other-window "view" "\
View FILE in View mode in another window.
When done, return that window to its previous buffer, and kill the
@@ -38356,8 +34299,7 @@ For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'view-file-other-frame "view" "\
View FILE in View mode in another frame.
When done, kill the buffer visiting FILE if unmodified and if it wasn't
@@ -38372,8 +34314,7 @@ For a list of all View commands, type H or h while viewing.
This command runs the normal hook `view-mode-hook'.
-\(fn FILE)" t nil)
-
+(fn FILE)" t nil)
(autoload 'view-buffer "view" "\
View BUFFER in View mode, returning to previous buffer when done.
Emacs commands editing the buffer contents are not available; instead, a
@@ -38397,8 +34338,7 @@ This function does not enable View mode if the buffer's major mode
has a `special' mode-class, because such modes usually have their
own View-like bindings.
-\(fn BUFFER &optional EXIT-ACTION)" t nil)
-
+(fn BUFFER &optional EXIT-ACTION)" t nil)
(autoload 'view-buffer-other-window "view" "\
View BUFFER in View mode in another window.
Emacs commands editing the buffer contents are not available;
@@ -38419,8 +34359,7 @@ This function does not enable View mode if the buffer's major mode
has a `special' mode-class, because such modes usually have their
own View-like bindings.
-\(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil)
-
+(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil)
(autoload 'view-buffer-other-frame "view" "\
View BUFFER in View mode in another frame.
Emacs commands editing the buffer contents are not available;
@@ -38441,25 +34380,10 @@ This function does not enable View mode if the buffer's major mode
has a `special' mode-class, because such modes usually have their
own View-like bindings.
-\(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil)
-
+(fn BUFFER &optional NOT-RETURN EXIT-ACTION)" t nil)
(autoload 'view-mode "view" "\
Toggle View mode, a minor mode for viewing text but not editing it.
-This is a minor mode. If called interactively, toggle the `View mode'
-mode. If the prefix argument is positive, enable the mode, and if it
-is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `view-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
When View mode is enabled, commands that do not change the buffer
contents are available as usual. Kill commands save text but
do not delete it from the buffer. Most other commands beep and
@@ -38537,8 +34461,21 @@ then \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] will return to th
Entry to view-mode runs the normal hook `view-mode-hook'.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the `View
+mode' mode. If the prefix argument is positive, enable the mode,
+and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+To check whether the minor mode is enabled in the current buffer,
+evaluate `view-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'view-return-to-alist-update "view" "\
Update `view-return-to-alist' of buffer BUFFER.
Remove from `view-return-to-alist' all entries referencing dead
@@ -38549,10 +34486,8 @@ function `view-mode-exit'. If `view-return-to-alist' contains an
entry for the selected window, purge that entry from
`view-return-to-alist' before adding ITEM.
-\(fn BUFFER &optional ITEM)" nil nil)
-
-(make-obsolete 'view-return-to-alist-update '"this function has no effect." '"24.1")
-
+(fn BUFFER &optional ITEM)" nil nil)
+(make-obsolete 'view-return-to-alist-update '"this function has no effect." "24.1")
(autoload 'view-mode-enter "view" "\
Enter View mode and set up exit from view mode depending on optional arguments.
Optional argument QUIT-RESTORE if non-nil must specify a valid
@@ -38568,115 +34503,78 @@ For a list of all View commands, type H or h while viewing.
This function runs the normal hook `view-mode-hook'.
-\(fn &optional QUIT-RESTORE EXIT-ACTION)" nil nil)
-
+(fn &optional QUIT-RESTORE EXIT-ACTION)" nil nil)
(autoload 'View-exit-and-edit "view" "\
Exit View mode and make the current buffer editable." t nil)
-
(register-definition-prefixes "view" '("View-" "view-"))
-;;;***
-;;;### (autoloads nil "viper" "emulation/viper.el" (0 0 0 0))
;;; Generated autoloads from emulation/viper.el
-(push (purecopy '(viper 3 14 1)) package--builtin-versions)
+(push (purecopy '(viper 3 14 1)) package--builtin-versions)
(autoload 'toggle-viper-mode "viper" "\
Toggle Viper on/off.
If Viper is enabled, turn it off. Otherwise, turn it on." t nil)
-
(autoload 'viper-mode "viper" "\
Turn on Viper emulation of Vi in Emacs. See Info node `(viper)Top'." t nil)
-
(register-definition-prefixes "viper" '("set-viper-state-in-major-mode" "this-major-mode-requires-vi-state" "viper-"))
-;;;***
-;;;### (autoloads nil "viper-cmd" "emulation/viper-cmd.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emulation/viper-cmd.el
(register-definition-prefixes "viper-cmd" '("viper-"))
-;;;***
-;;;### (autoloads nil "viper-ex" "emulation/viper-ex.el" (0 0 0 0))
;;; Generated autoloads from emulation/viper-ex.el
(register-definition-prefixes "viper-ex" '("ex-" "viper-"))
-;;;***
-;;;### (autoloads nil "viper-init" "emulation/viper-init.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/viper-init.el
(register-definition-prefixes "viper-init" '("viper-"))
-;;;***
-;;;### (autoloads nil "viper-keym" "emulation/viper-keym.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/viper-keym.el
(register-definition-prefixes "viper-keym" '("ex-read-filename-map" "viper-"))
-;;;***
-;;;### (autoloads nil "viper-macs" "emulation/viper-macs.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/viper-macs.el
(register-definition-prefixes "viper-macs" '("ex-" "viper-"))
-;;;***
-;;;### (autoloads nil "viper-mous" "emulation/viper-mous.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/viper-mous.el
(register-definition-prefixes "viper-mous" '("viper-"))
-;;;***
-;;;### (autoloads nil "viper-util" "emulation/viper-util.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from emulation/viper-util.el
(register-definition-prefixes "viper-util" '("viper"))
-;;;***
-;;;### (autoloads nil "vt-control" "vt-control.el" (0 0 0 0))
-;;; Generated autoloads from vt-control.el
+;;; Generated autoloads from leim/quail/viqr.el
-(register-definition-prefixes "vt-control" '("vt-"))
+(register-definition-prefixes "quail/viqr" '("viet-quail-define-rules"))
-;;;***
-;;;### (autoloads nil "vt100-led" "vt100-led.el" (0 0 0 0))
-;;; Generated autoloads from vt100-led.el
+;;; Generated autoloads from emacs-lisp/vtable.el
-(register-definition-prefixes "vt100-led" '("led-"))
+(register-definition-prefixes "vtable" '("vtable"))
-;;;***
-;;;### (autoloads nil "w32-fns" "w32-fns.el" (0 0 0 0))
;;; Generated autoloads from w32-fns.el
(register-definition-prefixes "w32-fns" '("w32-"))
-;;;***
-;;;### (autoloads nil "w32-vars" "w32-vars.el" (0 0 0 0))
;;; Generated autoloads from w32-vars.el
(register-definition-prefixes "w32-vars" '("w32-"))
-;;;***
-;;;### (autoloads nil "warnings" "emacs-lisp/warnings.el" (0 0 0
-;;;;;; 0))
;;; Generated autoloads from emacs-lisp/warnings.el
(defvar warning-prefix-function nil "\
@@ -38687,7 +34585,6 @@ and should return the entry that should actually be used.
The warnings buffer is current when this function is called
and the function can insert text in it. This text becomes
the beginning of the warning.")
-
(defvar warning-series nil "\
Non-nil means treat multiple `display-warning' calls as a series.
A marker indicates a position in the warnings buffer
@@ -38696,24 +34593,21 @@ additional warnings in the same buffer should not move point.
If t, the next warning begins a series (and stores a marker here).
A symbol with a function definition is like t, except
also call that function before the next warning.")
-
(defvar warning-fill-prefix nil "\
Non-nil means fill each warning text using this string as `fill-prefix'.")
-
(defvar warning-type-format (purecopy " (%s)") "\
Format for displaying the warning type in the warning message.
The result of formatting the type this way gets included in the
message under the control of the string in `warning-levels'.")
-
(autoload 'display-warning "warnings" "\
Display a warning message, MESSAGE.
TYPE is the warning type: either a custom group name (a symbol),
or a list of symbols whose first element is a custom group name.
-\(The rest of the symbols represent subcategories, for warning purposes
+(The rest of the symbols represent subcategories, for warning purposes
only, and you can use whatever symbols you like.)
LEVEL should be either :debug, :warning, :error, or :emergency
-\(but see `warning-minimum-level' and `warning-minimum-log-level').
+(but see `warning-minimum-level' and `warning-minimum-log-level').
Default is :warning.
:emergency -- a problem that will seriously impair Emacs operation soon
@@ -38738,8 +34632,7 @@ disable automatic display of the warning or disable the warning
entirely by setting `warning-suppress-types' or
`warning-suppress-log-types' on their behalf.
-\(fn TYPE MESSAGE &optional LEVEL BUFFER-NAME)" nil nil)
-
+(fn TYPE MESSAGE &optional LEVEL BUFFER-NAME)" nil nil)
(autoload 'lwarn "warnings" "\
Display a warning message made from (format-message MESSAGE ARGS...).
\\<special-mode-map>
@@ -38748,11 +34641,11 @@ this is equivalent to `display-warning'.
TYPE is the warning type: either a custom group name (a symbol),
or a list of symbols whose first element is a custom group name.
-\(The rest of the symbols represent subcategories and
+(The rest of the symbols represent subcategories and
can be whatever you like.)
LEVEL should be either :debug, :warning, :error, or :emergency
-\(but see `warning-minimum-level' and `warning-minimum-log-level').
+(but see `warning-minimum-level' and `warning-minimum-log-level').
:emergency -- a problem that will seriously impair Emacs operation soon
if you do not attend to it promptly.
@@ -38760,21 +34653,17 @@ LEVEL should be either :debug, :warning, :error, or :emergency
:warning -- suspicious data or circumstances.
:debug -- info for debugging only.
-\(fn TYPE LEVEL MESSAGE &rest ARGS)" nil nil)
-
+(fn TYPE LEVEL MESSAGE &rest ARGS)" nil nil)
(autoload 'warn "warnings" "\
Display a warning message made from (format-message MESSAGE ARGS...).
Aside from generating the message with `format-message',
this is equivalent to `display-warning', using
`emacs' as the type and `:warning' as the level.
-\(fn MESSAGE &rest ARGS)" nil nil)
-
+(fn MESSAGE &rest ARGS)" nil nil)
(register-definition-prefixes "warnings" '("warning-"))
-;;;***
-;;;### (autoloads nil "wdired" "wdired.el" (0 0 0 0))
;;; Generated autoloads from wdired.el
(autoload 'wdired-change-to-wdired-mode "wdired" "\
@@ -38786,12 +34675,9 @@ files. After typing \\[wdired-finish-edit], Emacs modifies the files and
directories to reflect your edits.
See `wdired-mode'." t nil)
-
(register-definition-prefixes "wdired" '("wdired-"))
-;;;***
-;;;### (autoloads nil "webjump" "net/webjump.el" (0 0 0 0))
;;; Generated autoloads from net/webjump.el
(autoload 'webjump "webjump" "\
@@ -38802,19 +34688,14 @@ hotlist.
Please submit bug reports and other feedback to the author, Neil W. Van Dyke
<nwv@acm.org>." t nil)
-
(register-definition-prefixes "webjump" '("webjump-"))
-;;;***
-;;;### (autoloads nil "which-func" "progmodes/which-func.el" (0 0
-;;;;;; 0 0))
;;; Generated autoloads from progmodes/which-func.el
+
(put 'which-func-format 'risky-local-variable t)
(put 'which-func-current 'risky-local-variable t)
-
(define-obsolete-function-alias 'which-func-mode 'which-function-mode "24.1")
-
(defvar which-function-mode nil "\
Non-nil if Which-Function mode is enabled.
See the `which-function-mode' command
@@ -38822,81 +34703,61 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `which-function-mode'.")
-
(custom-autoload 'which-function-mode "which-func" nil)
-
(autoload 'which-function-mode "which-func" "\
Toggle mode line display of current function (Which Function mode).
-This is a minor mode. If called interactively, toggle the
+Which Function mode is a global minor mode. When enabled, the
+current function name is continuously displayed in the mode line,
+in certain major modes.
+
+This is a global minor mode. If called interactively, toggle the
`Which-Function mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='which-function-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-Which Function mode is a global minor mode. When enabled, the
-current function name is continuously displayed in the mode line,
-in certain major modes.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "which-func" '("which-func"))
-;;;***
-;;;### (autoloads nil "whitespace" "whitespace.el" (0 0 0 0))
;;; Generated autoloads from whitespace.el
-(push (purecopy '(whitespace 13 2 2)) package--builtin-versions)
+(push (purecopy '(whitespace 13 2 2)) package--builtin-versions)
(autoload 'whitespace-mode "whitespace" "\
Toggle whitespace visualization (Whitespace mode).
-This is a minor mode. If called interactively, toggle the `Whitespace
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `whitespace-mode'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
See also `whitespace-style', `whitespace-newline' and
`whitespace-display-mappings'.
This mode uses a number of faces to visualize the whitespace; see
the customization group `whitespace' for details.
-\(fn &optional ARG)" t nil)
-
-(autoload 'whitespace-newline-mode "whitespace" "\
-Toggle newline visualization (Whitespace Newline mode).
-
This is a minor mode. If called interactively, toggle the
-`Whitespace-Newline mode' mode. If the prefix argument is positive,
+`Whitespace mode' mode. If the prefix argument is positive,
enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
-evaluate `whitespace-newline-mode'.
+evaluate `whitespace-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+(fn &optional ARG)" t nil)
+(autoload 'whitespace-newline-mode "whitespace" "\
+Toggle newline visualization (Whitespace Newline mode).
Use `whitespace-newline-mode' only for NEWLINE visualization
exclusively. For other visualizations, including NEWLINE
@@ -38905,8 +34766,22 @@ use `whitespace-mode'.
See also `whitespace-newline' and `whitespace-display-mappings'.
-\(fn &optional ARG)" t nil)
+This is a minor mode. If called interactively, toggle the
+`Whitespace-Newline mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `whitespace-newline-mode'.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(defvar global-whitespace-mode nil "\
Non-nil if Global Whitespace mode is enabled.
See the `global-whitespace-mode' command
@@ -38914,31 +34789,29 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-whitespace-mode'.")
-
(custom-autoload 'global-whitespace-mode "whitespace" nil)
-
(autoload 'global-whitespace-mode "whitespace" "\
Toggle whitespace visualization globally (Global Whitespace mode).
-This is a minor mode. If called interactively, toggle the `Global
-Whitespace mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
+See also `whitespace-style', `whitespace-newline' and
+`whitespace-display-mappings'.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+This is a global minor mode. If called interactively, toggle the
+`Global Whitespace mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='global-whitespace-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-See also `whitespace-style', `whitespace-newline' and
-`whitespace-display-mappings'.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(defvar global-whitespace-newline-mode nil "\
Non-nil if Global Whitespace-Newline mode is enabled.
See the `global-whitespace-newline-mode' command
@@ -38946,26 +34819,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `global-whitespace-newline-mode'.")
-
(custom-autoload 'global-whitespace-newline-mode "whitespace" nil)
-
(autoload 'global-whitespace-newline-mode "whitespace" "\
Toggle global newline visualization (Global Whitespace Newline mode).
-This is a minor mode. If called interactively, toggle the `Global
-Whitespace-Newline mode' mode. If the prefix argument is positive,
-enable the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-whitespace-newline-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Use `global-whitespace-newline-mode' only for NEWLINE
visualization exclusively. For other visualizations, including
NEWLINE visualization together with (HARD) SPACEs and/or TABs,
@@ -38973,8 +34830,22 @@ please use `global-whitespace-mode'.
See also `whitespace-newline' and `whitespace-display-mappings'.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Global Whitespace-Newline mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='global-whitespace-newline-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(autoload 'whitespace-toggle-options "whitespace" "\
Toggle local `whitespace-mode' options.
@@ -39045,8 +34916,7 @@ The valid symbols are:
See `whitespace-style' and `indent-tabs-mode' for documentation.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'global-whitespace-toggle-options "whitespace" "\
Toggle global `whitespace-mode' options.
@@ -39066,6 +34936,7 @@ Interactively, it accepts one of the following chars:
r toggle trailing blanks visualization
l toggle \"long lines\" visualization
L toggle \"long lines\" tail visualization
+ C-l toggle \"long lines\" one character visualization
n toggle NEWLINE visualization
e toggle empty line at bob and/or eob visualization
C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
@@ -39096,6 +34967,7 @@ The valid symbols are:
trailing toggle trailing blanks visualization
lines toggle \"long lines\" visualization
lines-tail toggle \"long lines\" tail visualization
+ lines-char toggle \"long lines\" one character visualization
newline toggle NEWLINE visualization
empty toggle empty line at bob and/or eob visualization
indentation toggle indentation SPACEs visualization
@@ -39117,8 +34989,7 @@ The valid symbols are:
See `whitespace-style' and `indent-tabs-mode' for documentation.
-\(fn ARG)" t nil)
-
+(fn ARG)" t nil)
(autoload 'whitespace-cleanup "whitespace" "\
Cleanup some blank problems in all buffer or at region.
@@ -39171,7 +35042,6 @@ The problems cleaned up are:
See `whitespace-style', `indent-tabs-mode' and `tab-width' for
documentation." t nil)
-
(autoload 'whitespace-cleanup-region "whitespace" "\
Cleanup some blank problems at region.
@@ -39212,15 +35082,13 @@ The problems cleaned up are:
See `whitespace-style', `indent-tabs-mode' and `tab-width' for
documentation.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'whitespace-report "whitespace" "\
Report some whitespace problems in buffer.
Perform `whitespace-report-region' on the current buffer.
-\(fn &optional FORCE REPORT-IF-BOGUS)" t nil)
-
+(fn &optional FORCE REPORT-IF-BOGUS)" t nil)
(autoload 'whitespace-report-region "whitespace" "\
Report some whitespace problems in a region.
@@ -39258,96 +35126,83 @@ See `whitespace-style' for documentation.
See also `whitespace-cleanup' and `whitespace-cleanup-region' for
cleaning up these problems.
-\(fn START END &optional FORCE REPORT-IF-BOGUS)" t nil)
-
+(fn START END &optional FORCE REPORT-IF-BOGUS)" t nil)
(register-definition-prefixes "whitespace" '("whitespace-"))
-;;;***
-;;;### (autoloads nil "wid-browse" "wid-browse.el" (0 0 0 0))
;;; Generated autoloads from wid-browse.el
(autoload 'widget-browse-at "wid-browse" "\
Browse the widget under point.
-\(fn POS)" t nil)
-
+(fn POS)" t nil)
(autoload 'widget-browse "wid-browse" "\
Create a widget browser for WIDGET.
-\(fn WIDGET)" t nil)
-
+(fn WIDGET)" t nil)
(autoload 'widget-browse-other-window "wid-browse" "\
Show widget browser for WIDGET in other window.
-\(fn &optional WIDGET)" t nil)
-
+(fn &optional WIDGET)" t nil)
(autoload 'widget-minor-mode "wid-browse" "\
Minor mode for traversing widgets.
-This is a minor mode. If called interactively, toggle the `Widget
-minor mode' mode. If the prefix argument is positive, enable the
-mode, and if it is zero or negative, disable the mode.
+This is a minor mode. If called interactively, toggle the
+`Widget minor mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `widget-minor-mode'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
-\(fn &optional ARG)" t nil)
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "wid-browse" '("widget-"))
-;;;***
-;;;### (autoloads nil "wid-edit" "wid-edit.el" (0 0 0 0))
;;; Generated autoloads from wid-edit.el
(autoload 'widgetp "wid-edit" "\
Return non-nil if WIDGET is a widget.
-\(fn WIDGET)" nil nil)
-
+(fn WIDGET)" nil nil)
(autoload 'widget-prompt-value "wid-edit" "\
Prompt for a value matching WIDGET, using PROMPT.
The current value is assumed to be VALUE, unless UNBOUND is non-nil.
-\(fn WIDGET PROMPT &optional VALUE UNBOUND)" nil nil)
-
+(fn WIDGET PROMPT &optional VALUE UNBOUND)" nil nil)
(autoload 'widget-create "wid-edit" "\
Create widget of TYPE.
The optional ARGS are additional keyword arguments.
-\(fn TYPE &rest ARGS)" nil nil)
-
+(fn TYPE &rest ARGS)" nil nil)
(autoload 'widget-delete "wid-edit" "\
Delete WIDGET.
-\(fn WIDGET)" nil nil)
+(fn WIDGET)" nil nil)
+(autoload 'widget-convert "wid-edit" "\
+Convert TYPE to a widget without inserting it in the buffer.
+The optional ARGS are additional keyword arguments.
+(fn TYPE &rest ARGS)" nil nil)
(autoload 'widget-insert "wid-edit" "\
Call `insert' with ARGS even if surrounding text is read only.
-\(fn &rest ARGS)" nil nil)
-
+(fn &rest ARGS)" nil nil)
(defvar widget-keymap (let ((map (make-sparse-keymap))) (define-key map "\11" 'widget-forward) (define-key map "\33\11" 'widget-backward) (define-key map [(shift tab)] 'widget-backward) (put 'widget-backward :advertised-binding [(shift tab)]) (define-key map [backtab] 'widget-backward) (define-key map [down-mouse-2] 'widget-button-click) (define-key map [down-mouse-1] 'widget-button-click) (define-key map [(control 109)] 'widget-button-press) map) "\
Keymap containing useful binding for buffers containing widgets.
Recommended as a parent keymap for modes using widgets.
Note that such modes will need to require wid-edit.")
-
(autoload 'widget-setup "wid-edit" "\
Setup current buffer so editing string widgets works." nil nil)
-
(register-definition-prefixes "wid-edit" '("widget-"))
-;;;***
-;;;### (autoloads nil "windmove" "windmove.el" (0 0 0 0))
;;; Generated autoloads from windmove.el
(autoload 'windmove-left "windmove" "\
@@ -39355,12 +35210,11 @@ Select the window to the left of the current one.
With no prefix argument, or with prefix argument equal to zero,
\"left\" is relative to the position of point in the window; otherwise
it is relative to the top edge (for positive ARG) or the bottom edge
-\(for negative ARG) of the current window.
+(for negative ARG) of the current window.
If no window is at the desired location, an error is signaled
unless `windmove-create-window' is non-nil and a new window is created.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-up "windmove" "\
Select the window above the current one.
With no prefix argument, or with prefix argument equal to zero, \"up\"
@@ -39370,8 +35224,7 @@ negative ARG) of the current window.
If no window is at the desired location, an error is signaled
unless `windmove-create-window' is non-nil and a new window is created.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-right "windmove" "\
Select the window to the right of the current one.
With no prefix argument, or with prefix argument equal to zero,
@@ -39381,19 +35234,40 @@ bottom edge (for negative ARG) of the current window.
If no window is at the desired location, an error is signaled
unless `windmove-create-window' is non-nil and a new window is created.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-down "windmove" "\
Select the window below the current one.
With no prefix argument, or with prefix argument equal to zero,
\"down\" is relative to the position of point in the window; otherwise
it is relative to the left edge (for positive ARG) or the right edge
-\(for negative ARG) of the current window.
+(for negative ARG) of the current window.
If no window is at the desired location, an error is signaled
unless `windmove-create-window' is non-nil and a new window is created.
-\(fn &optional ARG)" t nil)
+(fn &optional ARG)" t nil)
+(defvar windmove-mode t "\
+Non-nil if Windmove mode is enabled.
+See the `windmove-mode' command
+for a description of this minor mode.")
+(custom-autoload 'windmove-mode "windmove" nil)
+(autoload 'windmove-mode "windmove" "\
+Global minor mode for default windmove commands.
+
+This is a global minor mode. If called interactively, toggle the
+`Windmove mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='windmove-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
(autoload 'windmove-default-keybindings "windmove" "\
Set up keybindings for `windmove'.
Keybindings are of the form MODIFIERS-{left,right,up,down},
@@ -39402,51 +35276,43 @@ If MODIFIERS is `none', the keybindings will be directly bound to
the arrow keys.
Default value of MODIFIERS is `shift'.
-\(fn &optional MODIFIERS)" t nil)
-
+(fn &optional MODIFIERS)" t nil)
(autoload 'windmove-display-left "windmove" "\
Display the next buffer in window to the left of the current one.
See the logic of the prefix ARG and `windmove-display-no-select'
in `windmove-display-in-direction'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-up "windmove" "\
Display the next buffer in window above the current one.
See the logic of the prefix ARG and `windmove-display-no-select'
in `windmove-display-in-direction'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-right "windmove" "\
Display the next buffer in window to the right of the current one.
See the logic of the prefix ARG and `windmove-display-no-select'
in `windmove-display-in-direction'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-down "windmove" "\
Display the next buffer in window below the current one.
See the logic of the prefix ARG and `windmove-display-no-select'
in `windmove-display-in-direction'.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-same-window "windmove" "\
Display the next buffer in the same window.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-new-frame "windmove" "\
Display the next buffer in a new frame.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-new-tab "windmove" "\
Display the next buffer in a new tab.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-display-default-keybindings "windmove" "\
Set up keybindings for directional buffer display.
Keys are bound to commands that display the next buffer in the specified
@@ -39456,36 +35322,31 @@ If MODIFIERS is `none', the keybindings will be directly bound to
the arrow keys.
Default value of MODIFIERS is `shift-meta'.
-\(fn &optional MODIFIERS)" t nil)
-
+(fn &optional MODIFIERS)" t nil)
(autoload 'windmove-delete-left "windmove" "\
Delete the window to the left of the current one.
If prefix ARG is \\[universal-argument], delete the selected window and
select the window that was to the left of the current one.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-delete-up "windmove" "\
Delete the window above the current one.
If prefix ARG is \\[universal-argument], delete the selected window and
select the window that was above the current one.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-delete-right "windmove" "\
Delete the window to the right of the current one.
If prefix ARG is \\[universal-argument], delete the selected window and
select the window that was to the right of the current one.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-delete-down "windmove" "\
Delete the window below the current one.
If prefix ARG is \\[universal-argument], delete the selected window and
select the window that was below the current one.
-\(fn &optional ARG)" t nil)
-
+(fn &optional ARG)" t nil)
(autoload 'windmove-delete-default-keybindings "windmove" "\
Set up keybindings for directional window deletion.
Keys are bound to commands that delete windows in the specified
@@ -39496,20 +35357,15 @@ If PREFIX is `none', no prefix is used. If MODIFIERS is `none',
the keybindings are directly bound to the arrow keys.
Default value of PREFIX is \\`C-x' and MODIFIERS is `shift'.
-\(fn &optional PREFIX MODIFIERS)" t nil)
-
+(fn &optional PREFIX MODIFIERS)" t nil)
(autoload 'windmove-swap-states-left "windmove" "\
Swap the states with the window on the left from the current one." t nil)
-
(autoload 'windmove-swap-states-up "windmove" "\
Swap the states with the window above from the current one." t nil)
-
(autoload 'windmove-swap-states-down "windmove" "\
Swap the states with the window below from the current one." t nil)
-
(autoload 'windmove-swap-states-right "windmove" "\
Swap the states with the window on the right from the current one." t nil)
-
(autoload 'windmove-swap-states-default-keybindings "windmove" "\
Set up keybindings for directional window swap states.
Keys are bound to commands that swap the states of the selected window
@@ -39520,13 +35376,10 @@ If MODIFIERS is `none', the keybindings will be directly bound to the
arrow keys.
Default value of MODIFIERS is `shift-super'.
-\(fn &optional MODIFIERS)" t nil)
-
+(fn &optional MODIFIERS)" t nil)
(register-definition-prefixes "windmove" '("windmove-"))
-;;;***
-;;;### (autoloads nil "winner" "winner.el" (0 0 0 0))
;;; Generated autoloads from winner.el
(defvar winner-mode nil "\
@@ -39536,50 +35389,53 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `winner-mode'.")
-
(custom-autoload 'winner-mode "winner" nil)
-
(autoload 'winner-mode "winner" "\
Toggle Winner mode on or off.
-This is a minor mode. If called interactively, toggle the `Winner
-mode' mode. If the prefix argument is positive, enable the mode, and
-if it is zero or negative, disable the mode.
+Winner mode is a global minor mode that records the changes in
+the window configuration (i.e. how the frames are partitioned
+into windows) so that the changes can be \"undone\" using the
+command `winner-undo'. By default this one is bound to the key
+sequence \\`C-c <left>'. If you change your mind (while undoing),
+you can press \\`C-c <right>' (calling `winner-redo').
+
+This is a global minor mode. If called interactively, toggle the
+`Winner mode' mode. If the prefix argument is positive, enable
+the mode, and if it is zero or negative, disable the mode.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate `(default-value \\='winner-mode)'.
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
-Winner mode is a global minor mode that records the changes in
-the window configuration (i.e. how the frames are partitioned
-into windows) so that the changes can be \"undone\" using the
-command `winner-undo'. By default this one is bound to the key
-sequence `C-c <left>'. If you change your mind (while undoing),
-you can press `C-c <right>' (calling `winner-redo').
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "winner" '("winner-"))
-\(fn &optional ARG)" t nil)
+
+;;; Generated autoloads from cedet/semantic/wisent/wisent.el
-(register-definition-prefixes "winner" '("winner-"))
+(register-definition-prefixes "semantic/wisent/wisent" '("$action" "$nterm" "$region" "wisent-"))
+
+
+;;; Generated autoloads from cedet/semantic/wisent.el
+
+(register-definition-prefixes "semantic/wisent" '("define-wisent-lexer" "wisent-"))
-;;;***
-;;;### (autoloads nil "woman" "woman.el" (0 0 0 0))
;;; Generated autoloads from woman.el
(defvar woman-locale nil "\
String specifying a manual page locale, or nil.
If a manual page is available in the specified locale
-\(e.g. \"sv_SE.ISO8859-1\"), it will be offered in preference to the
+(e.g. \"sv_SE.ISO8859-1\"), it will be offered in preference to the
default version. Normally, `set-locale-environment' sets this at startup.")
-
(custom-autoload 'woman-locale "woman" t)
-
(autoload 'woman "woman" "\
Browse UN*X man page for TOPIC (Without using external Man program).
The major browsing mode used is essentially the standard Man mode.
@@ -39592,11 +35448,9 @@ updated (e.g. to re-interpret the current directory).
Used non-interactively, arguments are optional: if given then TOPIC
should be a topic string and non-nil RE-CACHE forces re-caching.
-\(fn &optional TOPIC RE-CACHE)" t nil)
-
+(fn &optional TOPIC RE-CACHE)" t nil)
(autoload 'woman-dired-find-file "woman" "\
In dired, run the WoMan man-page browser on this file." t nil)
-
(autoload 'woman-find-file "woman" "\
Find, decode and browse a specific UN*X man-page source file FILE-NAME.
Use existing buffer if possible; reformat only if prefix arg given.
@@ -39606,32 +35460,75 @@ No external programs are used, except that `gunzip' will be used to
decompress the file if appropriate. See the documentation for the
`woman' command for further details.
-\(fn FILE-NAME &optional REFORMAT)" t nil)
-
+(fn FILE-NAME &optional REFORMAT)" t nil)
(autoload 'woman-bookmark-jump "woman" "\
Default bookmark handler for Woman buffers.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "woman" '("WoMan-" "menu-bar-manuals-menu" "set-woman-file-regexp" "woman"))
-;;;***
-;;;### (autoloads nil "x-dnd" "x-dnd.el" (0 0 0 0))
+;;; Generated autoloads from textmodes/word-wrap-mode.el
+
+(autoload 'word-wrap-whitespace-mode "word-wrap-mode" "\
+Allow `word-wrap' to fold on all breaking whitespace characters.
+
+The characters to break on are defined by `word-wrap-whitespace-characters'.
+
+This is a minor mode. If called interactively, toggle the
+`Word-Wrap-Whitespace mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `word-wrap-whitespace-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t nil)
+(put 'global-word-wrap-whitespace-mode 'globalized-minor-mode t)
+(defvar global-word-wrap-whitespace-mode nil "\
+Non-nil if Global Word-Wrap-Whitespace mode is enabled.
+See the `global-word-wrap-whitespace-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `global-word-wrap-whitespace-mode'.")
+(custom-autoload 'global-word-wrap-whitespace-mode "word-wrap-mode" nil)
+(autoload 'global-word-wrap-whitespace-mode "word-wrap-mode" "\
+Toggle Word-Wrap-Whitespace mode in all buffers.
+With prefix ARG, enable Global Word-Wrap-Whitespace mode if ARG is
+positive; otherwise, disable it.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.
+Enable the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+Word-Wrap-Whitespace mode is enabled in all buffers where
+`word-wrap-whitespace-mode' would do it.
+
+See `word-wrap-whitespace-mode' for more information on
+Word-Wrap-Whitespace mode.
+
+(fn &optional ARG)" t nil)
+(register-definition-prefixes "word-wrap-mode" '("word-wrap-whitespace-characters"))
+
+
;;; Generated autoloads from x-dnd.el
(register-definition-prefixes "x-dnd" '("x-dnd-"))
-;;;***
-;;;### (autoloads nil "xdg" "xdg.el" (0 0 0 0))
;;; Generated autoloads from xdg.el
(register-definition-prefixes "xdg" '("xdg-"))
-;;;***
-;;;### (autoloads nil "xml" "xml.el" (0 0 0 0))
;;; Generated autoloads from xml.el
(autoload 'xml-parse-file "xml" "\
@@ -39655,8 +35552,7 @@ Both features can be combined by providing a cons cell
(symbol-qnames . ALIST).
-\(fn FILE &optional PARSE-DTD PARSE-NS)" nil nil)
-
+(fn FILE &optional PARSE-DTD PARSE-NS)" nil nil)
(autoload 'xml-parse-region "xml" "\
Parse the region from BEG to END in BUFFER.
Return the XML parse tree, or raise an error if the region does
@@ -39683,19 +35579,15 @@ Both features can be combined by providing a cons cell
(symbol-qnames . ALIST).
-\(fn &optional BEG END BUFFER PARSE-DTD PARSE-NS)" nil nil)
-
+(fn &optional BEG END BUFFER PARSE-DTD PARSE-NS)" nil nil)
(autoload 'xml-remove-comments "xml" "\
Remove XML/HTML comments in the region between BEG and END.
All text between the <!-- ... --> markers will be removed.
-\(fn BEG END)" nil nil)
-
+(fn BEG END)" nil nil)
(register-definition-prefixes "xml" '("xml-"))
-;;;***
-;;;### (autoloads nil "xmltok" "nxml/xmltok.el" (0 0 0 0))
;;; Generated autoloads from nxml/xmltok.el
(autoload 'xmltok-get-declared-encoding-position "xmltok" "\
@@ -39709,33 +35601,30 @@ If there is XML that is not well-formed that looks like an XML
declaration, return nil. Otherwise, return t.
If LIMIT is non-nil, then do not consider characters beyond LIMIT.
-\(fn &optional LIMIT)" nil nil)
-
+(fn &optional LIMIT)" nil nil)
(register-definition-prefixes "xmltok" '("xmltok-"))
-;;;***
-;;;### (autoloads nil "xref" "progmodes/xref.el" (0 0 0 0))
;;; Generated autoloads from progmodes/xref.el
-(push (purecopy '(xref 1 3 2)) package--builtin-versions)
+(push (purecopy '(xref 1 4 1)) package--builtin-versions)
(autoload 'xref-find-backend "xref" nil nil nil)
-
(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "29.1")
-
(autoload 'xref-go-back "xref" "\
Go back to the previous position in xref history.
To undo, use \\[xref-go-forward]." t nil)
-
(autoload 'xref-go-forward "xref" "\
Got to the point where a previous \\[xref-go-back] was invoked." t nil)
-
(autoload 'xref-marker-stack-empty-p "xref" "\
Whether the xref back-history is empty." nil nil)
-
(autoload 'xref-forward-history-empty-p "xref" "\
Whether the xref forward-history is empty." nil nil)
+(autoload 'xref-show-xrefs "xref" "\
+Display some Xref values produced by FETCHER using DISPLAY-ACTION.
+The meanings of both arguments are the same as documented in
+`xref-show-xrefs-function'.
+(fn FETCHER DISPLAY-ACTION)" nil nil)
(autoload 'xref-find-definitions "xref" "\
Find the definition of the identifier at point.
With prefix argument or when there's no identifier at point,
@@ -39748,18 +35637,15 @@ buffer where the user can select from the list.
Use \\[xref-go-back] to return back to where you invoked this command.
-\(fn IDENTIFIER)" t nil)
-
+(fn IDENTIFIER)" t nil)
(autoload 'xref-find-definitions-other-window "xref" "\
Like `xref-find-definitions' but switch to the other window.
-\(fn IDENTIFIER)" t nil)
-
+(fn IDENTIFIER)" t nil)
(autoload 'xref-find-definitions-other-frame "xref" "\
Like `xref-find-definitions' but switch to the other frame.
-\(fn IDENTIFIER)" t nil)
-
+(fn IDENTIFIER)" t nil)
(autoload 'xref-find-references "xref" "\
Find references to the identifier at point.
This command might prompt for the identifier as needed, perhaps
@@ -39768,27 +35654,24 @@ With prefix argument, or if `xref-prompt-for-identifier' is t,
always prompt for the identifier. If `xref-prompt-for-identifier'
is nil, prompt only if there's no usable symbol at point.
-\(fn IDENTIFIER)" t nil)
-
+(fn IDENTIFIER)" t nil)
(autoload 'xref-find-definitions-at-mouse "xref" "\
Find the definition of identifier at or around mouse click.
This command is intended to be bound to a mouse event.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'xref-find-references-at-mouse "xref" "\
Find references to the identifier at or around mouse click.
This command is intended to be bound to a mouse event.
-\(fn EVENT)" t nil)
-
+(fn EVENT)" t nil)
(autoload 'xref-find-apropos "xref" "\
Find all meaningful symbols that match PATTERN.
The argument has the same meaning as in `apropos'.
See `tags-apropos-additional-actions' for how to augment the
output of this command when the backend is etags.
-\(fn PATTERN)" t nil)
+(fn PATTERN)" t nil)
(define-key esc-map "." #'xref-find-definitions)
(define-key esc-map "," #'xref-go-back)
(define-key esc-map [?\C-,] #'xref-go-forward)
@@ -39796,7 +35679,6 @@ output of this command when the backend is etags.
(define-key esc-map [?\C-.] #'xref-find-apropos)
(define-key ctl-x-4-map "." #'xref-find-definitions-other-window)
(define-key ctl-x-5-map "." #'xref-find-definitions-other-frame)
-
(autoload 'xref-references-in-directory "xref" "\
Find all references to SYMBOL in directory DIR.
Return a list of xref values.
@@ -39805,8 +35687,7 @@ This function uses the Semantic Symbol Reference API, see
`semantic-symref-tool-alist' for details on which tools are used,
and when.
-\(fn SYMBOL DIR)" nil nil)
-
+(fn SYMBOL DIR)" nil nil)
(autoload 'xref-matches-in-directory "xref" "\
Find all matches for REGEXP in directory DIR.
Return a list of xref values.
@@ -39814,8 +35695,7 @@ Only files matching some of FILES and none of IGNORES are searched.
FILES is a string with glob patterns separated by spaces.
IGNORES is a list of glob patterns for files to ignore.
-\(fn REGEXP FILES DIR IGNORES)" nil nil)
-
+(fn REGEXP FILES DIR IGNORES)" nil nil)
(autoload 'xref-matches-in-files "xref" "\
Find all matches for REGEXP in FILES.
Return a list of xref values.
@@ -39824,27 +35704,20 @@ FILES must be a list of absolute file names.
See `xref-search-program' and `xref-search-program-alist' for how
to control which program to use when looking for matches.
-\(fn REGEXP FILES)" nil nil)
-
+(fn REGEXP FILES)" nil nil)
(register-definition-prefixes "xref" '("xref-"))
-;;;***
-;;;### (autoloads nil "xscheme" "progmodes/xscheme.el" (0 0 0 0))
;;; Generated autoloads from progmodes/xscheme.el
(register-definition-prefixes "xscheme" '("default-xscheme-runlight" "exit-scheme-interaction-mode" "global-set-scheme-interaction-buffer" "local-" "reset-scheme" "run-scheme" "scheme-" "start-scheme" "verify-xscheme-buffer" "xscheme-"))
-;;;***
-;;;### (autoloads nil "xsd-regexp" "nxml/xsd-regexp.el" (0 0 0 0))
;;; Generated autoloads from nxml/xsd-regexp.el
(register-definition-prefixes "xsd-regexp" '("xsdre-"))
-;;;***
-;;;### (autoloads nil "xt-mouse" "xt-mouse.el" (0 0 0 0))
;;; Generated autoloads from xt-mouse.el
(defvar xterm-mouse-mode nil "\
@@ -39854,26 +35727,10 @@ for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `xterm-mouse-mode'.")
-
(custom-autoload 'xterm-mouse-mode "xt-mouse" nil)
-
(autoload 'xterm-mouse-mode "xt-mouse" "\
Toggle XTerm mouse mode.
-This is a minor mode. If called interactively, toggle the
-`Xterm-Mouse mode' mode. If the prefix argument is positive, enable
-the mode, and if it is zero or negative, disable the mode.
-
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable the
-mode if ARG is nil, omitted, or is a positive number. Disable the
-mode if ARG is a negative number.
-
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='xterm-mouse-mode)'.
-
-The mode's hook is called both when the mode is enabled and when it is
-disabled.
-
Turn it on to use Emacs mouse commands, and off to use xterm mouse commands.
This works in terminal emulators compatible with xterm. It only
works for simple uses of the mouse. Basically, only non-modified
@@ -39881,13 +35738,24 @@ single clicks are supported. When turned on, the normal xterm
mouse functionality for such clicks is still available by holding
down the SHIFT key while pressing the mouse button.
-\(fn &optional ARG)" t nil)
+This is a global minor mode. If called interactively, toggle the
+`Xterm-Mouse mode' mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='xterm-mouse-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+(fn &optional ARG)" t nil)
(register-definition-prefixes "xt-mouse" '("turn-o" "xt-mouse-epoch" "xterm-mouse-"))
-;;;***
-;;;### (autoloads nil "xwidget" "xwidget.el" (0 0 0 0))
;;; Generated autoloads from xwidget.el
(autoload 'xwidget-webkit-browse-url "xwidget" "\
@@ -39895,20 +35763,16 @@ Ask xwidget-webkit to browse URL.
NEW-SESSION specifies whether to create a new xwidget-webkit session.
Interactively, URL defaults to the string looking like a url around point.
-\(fn URL &optional NEW-SESSION)" t nil)
-
+(fn URL &optional NEW-SESSION)" t nil)
(autoload 'xwidget-webkit-bookmark-jump-handler "xwidget" "\
Jump to the web page bookmarked by the bookmark record BOOKMARK.
If `xwidget-webkit-bookmark-jump-new-session' is non-nil, create
a new xwidget-webkit session, otherwise use an existing session.
-\(fn BOOKMARK)" nil nil)
-
+(fn BOOKMARK)" nil nil)
(register-definition-prefixes "xwidget" '("xwidget-"))
-;;;***
-;;;### (autoloads nil "yank-media" "yank-media.el" (0 0 0 0))
;;; Generated autoloads from yank-media.el
(autoload 'yank-media "yank-media" "\
@@ -39919,7 +35783,6 @@ the `yank-media-handler' mechanism.
Also see `yank-media-types' for a command that lets you explore
all the different selection types." t nil)
-
(autoload 'yank-media-handler "yank-media" "\
Register HANDLER for dealing with `yank-media' actions for TYPES.
TYPES should be a MIME media type symbol, a regexp, or a list
@@ -39929,171 +35792,41 @@ HANDLER is a function that will be called with two arguments: The
MIME type (a symbol on the form `image/png') and the selection
data (a string).
-\(fn TYPES HANDLER)" nil nil)
-
+(fn TYPES HANDLER)" nil nil)
(register-definition-prefixes "yank-media" '("yank-media-"))
-;;;***
-;;;### (autoloads nil "yenc" "mail/yenc.el" (0 0 0 0))
;;; Generated autoloads from mail/yenc.el
(autoload 'yenc-decode-region "yenc" "\
Yenc decode region between START and END using an internal decoder.
-\(fn START END)" t nil)
-
+(fn START END)" t nil)
(autoload 'yenc-extract-filename "yenc" "\
Extract file name from an yenc header." nil nil)
-
(register-definition-prefixes "yenc" '("yenc-"))
-;;;***
-;;;### (autoloads nil "zeroconf" "net/zeroconf.el" (0 0 0 0))
;;; Generated autoloads from net/zeroconf.el
(register-definition-prefixes "zeroconf" '("zeroconf-"))
-;;;***
-;;;### (autoloads nil "zone" "play/zone.el" (0 0 0 0))
;;; Generated autoloads from play/zone.el
(autoload 'zone "zone" "\
Zone out, completely." t nil)
-
(register-definition-prefixes "zone" '("zone-"))
-
-;;;***
-
-;;;### (autoloads nil nil ("abbrev.el" "bindings.el" "buff-menu.el"
-;;;;;; "button.el" "calc/calc-aent.el" "calc/calc-embed.el" "calc/calc-misc.el"
-;;;;;; "calc/calc-yank.el" "case-table.el" "cedet/ede/base.el" "cedet/ede/config.el"
-;;;;;; "cedet/ede/cpp-root.el" "cedet/ede/custom.el" "cedet/ede/dired.el"
-;;;;;; "cedet/ede/emacs.el" "cedet/ede/files.el" "cedet/ede/generic.el"
-;;;;;; "cedet/ede/linux.el" "cedet/ede/locate.el" "cedet/ede/make.el"
-;;;;;; "cedet/ede/shell.el" "cedet/ede/speedbar.el" "cedet/ede/system.el"
-;;;;;; "cedet/ede/util.el" "cedet/semantic/analyze.el" "cedet/semantic/analyze/complete.el"
-;;;;;; "cedet/semantic/analyze/refs.el" "cedet/semantic/bovine.el"
-;;;;;; "cedet/semantic/bovine/c-by.el" "cedet/semantic/bovine/c.el"
-;;;;;; "cedet/semantic/bovine/el.el" "cedet/semantic/bovine/gcc.el"
-;;;;;; "cedet/semantic/bovine/make-by.el" "cedet/semantic/bovine/make.el"
-;;;;;; "cedet/semantic/bovine/scm-by.el" "cedet/semantic/bovine/scm.el"
-;;;;;; "cedet/semantic/complete.el" "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el"
-;;;;;; "cedet/semantic/db-find.el" "cedet/semantic/db-global.el"
-;;;;;; "cedet/semantic/db-mode.el" "cedet/semantic/db-typecache.el"
-;;;;;; "cedet/semantic/db.el" "cedet/semantic/debug.el" "cedet/semantic/decorate/include.el"
-;;;;;; "cedet/semantic/decorate/mode.el" "cedet/semantic/dep.el"
-;;;;;; "cedet/semantic/doc.el" "cedet/semantic/edit.el" "cedet/semantic/find.el"
-;;;;;; "cedet/semantic/format.el" "cedet/semantic/grammar-wy.el"
-;;;;;; "cedet/semantic/grm-wy-boot.el" "cedet/semantic/html.el"
-;;;;;; "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" "cedet/semantic/idle.el"
-;;;;;; "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" "cedet/semantic/lex.el"
-;;;;;; "cedet/semantic/mru-bookmark.el" "cedet/semantic/scope.el"
-;;;;;; "cedet/semantic/senator.el" "cedet/semantic/sort.el" "cedet/semantic/symref.el"
-;;;;;; "cedet/semantic/symref/cscope.el" "cedet/semantic/symref/global.el"
-;;;;;; "cedet/semantic/symref/grep.el" "cedet/semantic/symref/idutils.el"
-;;;;;; "cedet/semantic/symref/list.el" "cedet/semantic/tag-file.el"
-;;;;;; "cedet/semantic/tag-ls.el" "cedet/semantic/tag-write.el"
-;;;;;; "cedet/semantic/tag.el" "cedet/semantic/texi.el" "cedet/semantic/util-modes.el"
-;;;;;; "cedet/semantic/wisent/java-tags.el" "cedet/semantic/wisent/javascript.el"
-;;;;;; "cedet/semantic/wisent/javat-wy.el" "cedet/semantic/wisent/js-wy.el"
-;;;;;; "cedet/semantic/wisent/python-wy.el" "cedet/semantic/wisent/python.el"
-;;;;;; "cedet/srecode/compile.el" "cedet/srecode/cpp.el" "cedet/srecode/document.el"
-;;;;;; "cedet/srecode/el.el" "cedet/srecode/expandproto.el" "cedet/srecode/getset.el"
-;;;;;; "cedet/srecode/insert.el" "cedet/srecode/java.el" "cedet/srecode/map.el"
-;;;;;; "cedet/srecode/mode.el" "cedet/srecode/srt-wy.el" "cedet/srecode/srt.el"
-;;;;;; "cedet/srecode/template.el" "cedet/srecode/texi.el" "composite.el"
-;;;;;; "cus-face.el" "cus-start.el" "custom.el" "dired-aux.el" "dired-x.el"
-;;;;;; "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el"
-;;;;;; "emacs-lisp/cl-extra.el" "emacs-lisp/cl-macs.el" "emacs-lisp/cl-preloaded.el"
-;;;;;; "emacs-lisp/cl-seq.el" "emacs-lisp/easymenu.el" "emacs-lisp/eieio-custom.el"
-;;;;;; "emacs-lisp/eieio-opt.el" "emacs-lisp/float-sup.el" "emacs-lisp/lisp-mode.el"
-;;;;;; "emacs-lisp/lisp.el" "emacs-lisp/macroexp.el" "emacs-lisp/map-ynp.el"
-;;;;;; "emacs-lisp/nadvice.el" "emacs-lisp/shorthands.el" "emacs-lisp/syntax.el"
-;;;;;; "emacs-lisp/timer.el" "env.el" "epa-hook.el" "erc/erc-autoaway.el"
-;;;;;; "erc/erc-button.el" "erc/erc-capab.el" "erc/erc-compat.el"
-;;;;;; "erc/erc-dcc.el" "erc/erc-desktop-notifications.el" "erc/erc-ezbounce.el"
-;;;;;; "erc/erc-fill.el" "erc/erc-identd.el" "erc/erc-imenu.el"
-;;;;;; "erc/erc-join.el" "erc/erc-list.el" "erc/erc-log.el" "erc/erc-match.el"
-;;;;;; "erc/erc-menu.el" "erc/erc-netsplit.el" "erc/erc-notify.el"
-;;;;;; "erc/erc-page.el" "erc/erc-pcomplete.el" "erc/erc-replace.el"
-;;;;;; "erc/erc-ring.el" "erc/erc-services.el" "erc/erc-sound.el"
-;;;;;; "erc/erc-speedbar.el" "erc/erc-spelling.el" "erc/erc-stamp.el"
-;;;;;; "erc/erc-status-sidebar.el" "erc/erc-track.el" "erc/erc-truncate.el"
-;;;;;; "erc/erc-xdcc.el" "eshell/em-alias.el" "eshell/em-banner.el"
-;;;;;; "eshell/em-basic.el" "eshell/em-cmpl.el" "eshell/em-dirs.el"
-;;;;;; "eshell/em-glob.el" "eshell/em-hist.el" "eshell/em-ls.el"
-;;;;;; "eshell/em-pred.el" "eshell/em-prompt.el" "eshell/em-rebind.el"
-;;;;;; "eshell/em-script.el" "eshell/em-smart.el" "eshell/em-term.el"
-;;;;;; "eshell/em-tramp.el" "eshell/em-unix.el" "eshell/em-xtra.el"
-;;;;;; "faces.el" "files.el" "font-core.el" "font-lock.el" "format.el"
-;;;;;; "frame.el" "help.el" "hfy-cmap.el" "ibuf-ext.el" "indent.el"
-;;;;;; "international/characters.el" "international/charscript.el"
-;;;;;; "international/cp51932.el" "international/emoji-zwj.el" "international/eucjp-ms.el"
-;;;;;; "international/iso-transl.el" "international/mule-cmds.el"
-;;;;;; "international/mule-conf.el" "international/mule.el" "isearch.el"
-;;;;;; "jit-lock.el" "jka-cmpr-hook.el" "keymap.el" "language/burmese.el"
-;;;;;; "language/cham.el" "language/chinese.el" "language/cyrillic.el"
-;;;;;; "language/czech.el" "language/english.el" "language/ethiopic.el"
-;;;;;; "language/european.el" "language/georgian.el" "language/greek.el"
-;;;;;; "language/hebrew.el" "language/indian.el" "language/japanese.el"
-;;;;;; "language/khmer.el" "language/korean.el" "language/lao.el"
-;;;;;; "language/misc-lang.el" "language/romanian.el" "language/sinhala.el"
-;;;;;; "language/slovak.el" "language/tai-viet.el" "language/thai.el"
-;;;;;; "language/tibetan.el" "language/utf-8-lang.el" "language/vietnamese.el"
-;;;;;; "ldefs-boot.el" "leim/ja-dic/ja-dic.el" "leim/leim-list.el"
-;;;;;; "leim/quail/4Corner.el" "leim/quail/ARRAY30.el" "leim/quail/CCDOSPY.el"
-;;;;;; "leim/quail/CTLau-b5.el" "leim/quail/CTLau.el" "leim/quail/ECDICT.el"
-;;;;;; "leim/quail/ETZY.el" "leim/quail/PY-b5.el" "leim/quail/PY.el"
-;;;;;; "leim/quail/Punct-b5.el" "leim/quail/Punct.el" "leim/quail/QJ-b5.el"
-;;;;;; "leim/quail/QJ.el" "leim/quail/SW.el" "leim/quail/TONEPY.el"
-;;;;;; "leim/quail/ZIRANMA.el" "leim/quail/ZOZY.el" "leim/quail/arabic.el"
-;;;;;; "leim/quail/cham.el" "leim/quail/compose.el" "leim/quail/croatian.el"
-;;;;;; "leim/quail/cyril-jis.el" "leim/quail/cyrillic.el" "leim/quail/czech.el"
-;;;;;; "leim/quail/georgian.el" "leim/quail/greek.el" "leim/quail/hanja-jis.el"
-;;;;;; "leim/quail/hanja.el" "leim/quail/hanja3.el" "leim/quail/hebrew.el"
-;;;;;; "leim/quail/ipa-praat.el" "leim/quail/latin-alt.el" "leim/quail/latin-ltx.el"
-;;;;;; "leim/quail/latin-post.el" "leim/quail/latin-pre.el" "leim/quail/persian.el"
-;;;;;; "leim/quail/programmer-dvorak.el" "leim/quail/py-punct.el"
-;;;;;; "leim/quail/pypunct-b5.el" "leim/quail/quick-b5.el" "leim/quail/quick-cns.el"
-;;;;;; "leim/quail/rfc1345.el" "leim/quail/sami.el" "leim/quail/sgml-input.el"
-;;;;;; "leim/quail/slovak.el" "leim/quail/symbol-ksc.el" "leim/quail/tamil-dvorak.el"
-;;;;;; "leim/quail/tsang-b5.el" "leim/quail/tsang-cns.el" "leim/quail/vntelex.el"
-;;;;;; "leim/quail/vnvni.el" "leim/quail/welsh.el" "loadup.el" "mail/blessmail.el"
-;;;;;; "mail/undigest.el" "menu-bar.el" "mh-e/mh-gnus.el" "minibuffer.el"
-;;;;;; "mouse.el" "newcomment.el" "obarray.el" "org/ob-core.el"
-;;;;;; "org/ob-lob.el" "org/ob-matlab.el" "org/ob-tangle.el" "org/ob.el"
-;;;;;; "org/ol-bbdb.el" "org/ol-irc.el" "org/ol.el" "org/org-archive.el"
-;;;;;; "org/org-attach.el" "org/org-clock.el" "org/org-colview.el"
-;;;;;; "org/org-compat.el" "org/org-datetree.el" "org/org-duration.el"
-;;;;;; "org/org-element.el" "org/org-feed.el" "org/org-footnote.el"
-;;;;;; "org/org-goto.el" "org/org-id.el" "org/org-indent.el" "org/org-install.el"
-;;;;;; "org/org-keys.el" "org/org-lint.el" "org/org-list.el" "org/org-macs.el"
-;;;;;; "org/org-mobile.el" "org/org-num.el" "org/org-plot.el" "org/org-refile.el"
-;;;;;; "org/org-table.el" "org/org-timer.el" "org/ox-ascii.el" "org/ox-beamer.el"
-;;;;;; "org/ox-html.el" "org/ox-icalendar.el" "org/ox-latex.el"
-;;;;;; "org/ox-md.el" "org/ox-odt.el" "org/ox-org.el" "org/ox-publish.el"
-;;;;;; "org/ox-texinfo.el" "org/ox.el" "paren.el" "progmodes/elisp-mode.el"
-;;;;;; "progmodes/prog-mode.el" "ps-mule.el" "register.el" "replace.el"
-;;;;;; "rfn-eshadow.el" "select.el" "simple.el" "startup.el" "subdirs.el"
-;;;;;; "subr.el" "tab-bar.el" "textmodes/fill.el" "textmodes/makeinfo.el"
-;;;;;; "textmodes/page.el" "textmodes/paragraphs.el" "textmodes/reftex-auc.el"
-;;;;;; "textmodes/reftex-cite.el" "textmodes/reftex-dcr.el" "textmodes/reftex-global.el"
-;;;;;; "textmodes/reftex-index.el" "textmodes/reftex-parse.el" "textmodes/reftex-ref.el"
-;;;;;; "textmodes/reftex-sel.el" "textmodes/reftex-toc.el" "textmodes/texnfo-upd.el"
-;;;;;; "textmodes/text-mode.el" "uniquify.el" "vc/ediff-hook.el"
-;;;;;; "vc/vc-hooks.el" "version.el" "widget.el" "window.el") (0
-;;;;;; 0 0 0))
-
-;;;***
+;;; End of scraped data
+
(provide 'loaddefs)
+
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
-;; coding: utf-8
+;; coding: utf-8-emacs-unix
;; End:
+
;;; loaddefs.el ends here
diff --git a/lisp/leim/quail/compose.el b/lisp/leim/quail/compose.el
index 2aa8ae78fe7..60c73d7dff8 100644
--- a/lisp/leim/quail/compose.el
+++ b/lisp/leim/quail/compose.el
@@ -464,9 +464,9 @@ Examples:
("2^" ?²)
("^3" ?³)
("3^" ?³)
- ("mu" ?µ)
- ("/u" ?µ)
- ("u/" ?µ)
+ ("mu" ?μ)
+ ("/u" ?μ)
+ ("u/" ?μ)
("^1" ?¹)
("1^" ?¹)
("^_o" ?º)
diff --git a/lisp/leim/quail/emoji.el b/lisp/leim/quail/emoji.el
new file mode 100644
index 00000000000..f9d3e170be5
--- /dev/null
+++ b/lisp/leim/quail/emoji.el
@@ -0,0 +1,2003 @@
+;;; emoji.el --- Quail package for emoji character composition -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Juri Linkov <juri@linkov.net>
+;; Keywords: multilingual, input method, i18n
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This input method supports the same key sequences as the names
+;; defined by the `C-x 8 e s' completions in emoji.el. Also it adds
+;; more emoji that enclosed in double colons.
+
+;; You can enable this input method transiently with `C-u C-x \ emoji RET'.
+;; Then typing `C-x \' will enable this input method temporarily, and
+;; after typing a key sequence it will be disabled. So typing
+;; e.g. `C-x \ : )' will insert the smiling character, and disable
+;; this input method automatically afterwards.
+
+;;; Code:
+
+(require 'quail)
+
+(quail-define-package
+ "emoji" "UTF-8" "🙂" t
+ "Emoji input method for inserting emoji characters.
+Examples:
+ slightly smiling face -> 🙂
+ :slightly_smiling_face: -> 🙂
+ :-) -> 🙂"
+ '(("\t" . quail-completion))
+ t nil nil nil nil nil nil nil nil t)
+
+(eval-when-compile
+ (require 'emoji)
+ (emoji--init)
+ (defmacro emoji--define-rules ()
+ `(quail-define-rules
+ ,@(let ((rules nil))
+ (maphash (lambda (from to)
+ (push (list from (if (stringp to)
+ (vector to)
+ to))
+ rules))
+ emoji--all-bases)
+ (append
+ rules
+ '((":hash:" ["#️⃣"])
+ (":keycap_star:" ["*️⃣"])
+ (":zero:" ["0️⃣"])
+ (":one:" ["1️⃣"])
+ (":two:" ["2️⃣"])
+ (":three:" ["3️⃣"])
+ (":four:" ["4️⃣"])
+ (":five:" ["5️⃣"])
+ (":six:" ["6️⃣"])
+ (":seven:" ["7️⃣"])
+ (":eight:" ["8️⃣"])
+ (":nine:" ["9️⃣"])
+ (":copyright:" ["©️"])
+ (":registered:" ["®️"])
+ (":mahjong:" ["🀄"])
+ (":black_joker:" ["🃏"])
+ (":a:" ["🅰️"])
+ (":b:" ["🅱️"])
+ (":o2:" ["🅾️"])
+ (":parking:" ["🅿️"])
+ (":ab:" ["🆎"])
+ (":cl:" ["🆑"])
+ (":cool:" ["🆒"])
+ (":free:" ["🆓"])
+ (":id:" ["🆔"])
+ (":new:" ["🆕"])
+ (":ng:" ["🆖"])
+ (":ok:" ["🆗"])
+ (":sos:" ["🆘"])
+ (":up:" ["🆙"])
+ (":vs:" ["🆚"])
+ (":flag-ac:" ["🇦🇨"])
+ (":flag-ad:" ["🇦🇩"])
+ (":flag-ae:" ["🇦🇪"])
+ (":flag-af:" ["🇦🇫"])
+ (":flag-ag:" ["🇦🇬"])
+ (":flag-ai:" ["🇦🇮"])
+ (":flag-al:" ["🇦🇱"])
+ (":flag-am:" ["🇦🇲"])
+ (":flag-ao:" ["🇦🇴"])
+ (":flag-aq:" ["🇦🇶"])
+ (":flag-ar:" ["🇦🇷"])
+ (":flag-as:" ["🇦🇸"])
+ (":flag-at:" ["🇦🇹"])
+ (":flag-au:" ["🇦🇺"])
+ (":flag-aw:" ["🇦🇼"])
+ (":flag-ax:" ["🇦🇽"])
+ (":flag-az:" ["🇦🇿"])
+ (":flag-ba:" ["🇧🇦"])
+ (":flag-bb:" ["🇧🇧"])
+ (":flag-bd:" ["🇧🇩"])
+ (":flag-be:" ["🇧🇪"])
+ (":flag-bf:" ["🇧🇫"])
+ (":flag-bg:" ["🇧🇬"])
+ (":flag-bh:" ["🇧🇭"])
+ (":flag-bi:" ["🇧🇮"])
+ (":flag-bj:" ["🇧🇯"])
+ (":flag-bl:" ["🇧🇱"])
+ (":flag-bm:" ["🇧🇲"])
+ (":flag-bn:" ["🇧🇳"])
+ (":flag-bo:" ["🇧🇴"])
+ (":flag-bq:" ["🇧🇶"])
+ (":flag-br:" ["🇧🇷"])
+ (":flag-bs:" ["🇧🇸"])
+ (":flag-bt:" ["🇧🇹"])
+ (":flag-bv:" ["🇧🇻"])
+ (":flag-bw:" ["🇧🇼"])
+ (":flag-by:" ["🇧🇾"])
+ (":flag-bz:" ["🇧🇿"])
+ (":flag-ca:" ["🇨🇦"])
+ (":flag-cc:" ["🇨🇨"])
+ (":flag-cd:" ["🇨🇩"])
+ (":flag-cf:" ["🇨🇫"])
+ (":flag-cg:" ["🇨🇬"])
+ (":flag-ch:" ["🇨🇭"])
+ (":flag-ci:" ["🇨🇮"])
+ (":flag-ck:" ["🇨🇰"])
+ (":flag-cl:" ["🇨🇱"])
+ (":flag-cm:" ["🇨🇲"])
+ (":cn:" ["🇨🇳"])
+ (":flag-cn:" ["🇨🇳"])
+ (":flag-co:" ["🇨🇴"])
+ (":flag-cp:" ["🇨🇵"])
+ (":flag-cr:" ["🇨🇷"])
+ (":flag-cu:" ["🇨🇺"])
+ (":flag-cv:" ["🇨🇻"])
+ (":flag-cw:" ["🇨🇼"])
+ (":flag-cx:" ["🇨🇽"])
+ (":flag-cy:" ["🇨🇾"])
+ (":flag-cz:" ["🇨🇿"])
+ (":de:" ["🇩🇪"])
+ (":flag-de:" ["🇩🇪"])
+ (":flag-dg:" ["🇩🇬"])
+ (":flag-dj:" ["🇩🇯"])
+ (":flag-dk:" ["🇩🇰"])
+ (":flag-dm:" ["🇩🇲"])
+ (":flag-do:" ["🇩🇴"])
+ (":flag-dz:" ["🇩🇿"])
+ (":flag-ea:" ["🇪🇦"])
+ (":flag-ec:" ["🇪🇨"])
+ (":flag-ee:" ["🇪🇪"])
+ (":flag-eg:" ["🇪🇬"])
+ (":flag-eh:" ["🇪🇭"])
+ (":flag-er:" ["🇪🇷"])
+ (":es:" ["🇪🇸"])
+ (":flag-es:" ["🇪🇸"])
+ (":flag-et:" ["🇪🇹"])
+ (":flag-eu:" ["🇪🇺"])
+ (":flag-fi:" ["🇫🇮"])
+ (":flag-fj:" ["🇫🇯"])
+ (":flag-fk:" ["🇫🇰"])
+ (":flag-fm:" ["🇫🇲"])
+ (":flag-fo:" ["🇫🇴"])
+ (":fr:" ["🇫🇷"])
+ (":flag-fr:" ["🇫🇷"])
+ (":flag-ga:" ["🇬🇦"])
+ (":gb:" ["🇬🇧"])
+ (":uk:" ["🇬🇧"])
+ (":flag-gb:" ["🇬🇧"])
+ (":flag-gd:" ["🇬🇩"])
+ (":flag-ge:" ["🇬🇪"])
+ (":flag-gf:" ["🇬🇫"])
+ (":flag-gg:" ["🇬🇬"])
+ (":flag-gh:" ["🇬🇭"])
+ (":flag-gi:" ["🇬🇮"])
+ (":flag-gl:" ["🇬🇱"])
+ (":flag-gm:" ["🇬🇲"])
+ (":flag-gn:" ["🇬🇳"])
+ (":flag-gp:" ["🇬🇵"])
+ (":flag-gq:" ["🇬🇶"])
+ (":flag-gr:" ["🇬🇷"])
+ (":flag-gs:" ["🇬🇸"])
+ (":flag-gt:" ["🇬🇹"])
+ (":flag-gu:" ["🇬🇺"])
+ (":flag-gw:" ["🇬🇼"])
+ (":flag-gy:" ["🇬🇾"])
+ (":flag-hk:" ["🇭🇰"])
+ (":flag-hm:" ["🇭🇲"])
+ (":flag-hn:" ["🇭🇳"])
+ (":flag-hr:" ["🇭🇷"])
+ (":flag-ht:" ["🇭🇹"])
+ (":flag-hu:" ["🇭🇺"])
+ (":flag-ic:" ["🇮🇨"])
+ (":flag-id:" ["🇮🇩"])
+ (":flag-ie:" ["🇮🇪"])
+ (":flag-il:" ["🇮🇱"])
+ (":flag-im:" ["🇮🇲"])
+ (":flag-in:" ["🇮🇳"])
+ (":flag-io:" ["🇮🇴"])
+ (":flag-iq:" ["🇮🇶"])
+ (":flag-ir:" ["🇮🇷"])
+ (":flag-is:" ["🇮🇸"])
+ (":it:" ["🇮🇹"])
+ (":flag-it:" ["🇮🇹"])
+ (":flag-je:" ["🇯🇪"])
+ (":flag-jm:" ["🇯🇲"])
+ (":flag-jo:" ["🇯🇴"])
+ (":jp:" ["🇯🇵"])
+ (":flag-jp:" ["🇯🇵"])
+ (":flag-ke:" ["🇰🇪"])
+ (":flag-kg:" ["🇰🇬"])
+ (":flag-kh:" ["🇰🇭"])
+ (":flag-ki:" ["🇰🇮"])
+ (":flag-km:" ["🇰🇲"])
+ (":flag-kn:" ["🇰🇳"])
+ (":flag-kp:" ["🇰🇵"])
+ (":kr:" ["🇰🇷"])
+ (":flag-kr:" ["🇰🇷"])
+ (":flag-kw:" ["🇰🇼"])
+ (":flag-ky:" ["🇰🇾"])
+ (":flag-kz:" ["🇰🇿"])
+ (":flag-la:" ["🇱🇦"])
+ (":flag-lb:" ["🇱🇧"])
+ (":flag-lc:" ["🇱🇨"])
+ (":flag-li:" ["🇱🇮"])
+ (":flag-lk:" ["🇱🇰"])
+ (":flag-lr:" ["🇱🇷"])
+ (":flag-ls:" ["🇱🇸"])
+ (":flag-lt:" ["🇱🇹"])
+ (":flag-lu:" ["🇱🇺"])
+ (":flag-lv:" ["🇱🇻"])
+ (":flag-ly:" ["🇱🇾"])
+ (":flag-ma:" ["🇲🇦"])
+ (":flag-mc:" ["🇲🇨"])
+ (":flag-md:" ["🇲🇩"])
+ (":flag-me:" ["🇲🇪"])
+ (":flag-mf:" ["🇲🇫"])
+ (":flag-mg:" ["🇲🇬"])
+ (":flag-mh:" ["🇲🇭"])
+ (":flag-mk:" ["🇲🇰"])
+ (":flag-ml:" ["🇲🇱"])
+ (":flag-mm:" ["🇲🇲"])
+ (":flag-mn:" ["🇲🇳"])
+ (":flag-mo:" ["🇲🇴"])
+ (":flag-mp:" ["🇲🇵"])
+ (":flag-mq:" ["🇲🇶"])
+ (":flag-mr:" ["🇲🇷"])
+ (":flag-ms:" ["🇲🇸"])
+ (":flag-mt:" ["🇲🇹"])
+ (":flag-mu:" ["🇲🇺"])
+ (":flag-mv:" ["🇲🇻"])
+ (":flag-mw:" ["🇲🇼"])
+ (":flag-mx:" ["🇲🇽"])
+ (":flag-my:" ["🇲🇾"])
+ (":flag-mz:" ["🇲🇿"])
+ (":flag-na:" ["🇳🇦"])
+ (":flag-nc:" ["🇳🇨"])
+ (":flag-ne:" ["🇳🇪"])
+ (":flag-nf:" ["🇳🇫"])
+ (":flag-ng:" ["🇳🇬"])
+ (":flag-ni:" ["🇳🇮"])
+ (":flag-nl:" ["🇳🇱"])
+ (":flag-no:" ["🇳🇴"])
+ (":flag-np:" ["🇳🇵"])
+ (":flag-nr:" ["🇳🇷"])
+ (":flag-nu:" ["🇳🇺"])
+ (":flag-nz:" ["🇳🇿"])
+ (":flag-om:" ["🇴🇲"])
+ (":flag-pa:" ["🇵🇦"])
+ (":flag-pe:" ["🇵🇪"])
+ (":flag-pf:" ["🇵🇫"])
+ (":flag-pg:" ["🇵🇬"])
+ (":flag-ph:" ["🇵🇭"])
+ (":flag-pk:" ["🇵🇰"])
+ (":flag-pl:" ["🇵🇱"])
+ (":flag-pm:" ["🇵🇲"])
+ (":flag-pn:" ["🇵🇳"])
+ (":flag-pr:" ["🇵🇷"])
+ (":flag-ps:" ["🇵🇸"])
+ (":flag-pt:" ["🇵🇹"])
+ (":flag-pw:" ["🇵🇼"])
+ (":flag-py:" ["🇵🇾"])
+ (":flag-qa:" ["🇶🇦"])
+ (":flag-re:" ["🇷🇪"])
+ (":flag-ro:" ["🇷🇴"])
+ (":flag-rs:" ["🇷🇸"])
+ (":ru:" ["🇷🇺"])
+ (":flag-ru:" ["🇷🇺"])
+ (":flag-rw:" ["🇷🇼"])
+ (":flag-sa:" ["🇸🇦"])
+ (":flag-sb:" ["🇸🇧"])
+ (":flag-sc:" ["🇸🇨"])
+ (":flag-sd:" ["🇸🇩"])
+ (":flag-se:" ["🇸🇪"])
+ (":flag-sg:" ["🇸🇬"])
+ (":flag-sh:" ["🇸🇭"])
+ (":flag-si:" ["🇸🇮"])
+ (":flag-sj:" ["🇸🇯"])
+ (":flag-sk:" ["🇸🇰"])
+ (":flag-sl:" ["🇸🇱"])
+ (":flag-sm:" ["🇸🇲"])
+ (":flag-sn:" ["🇸🇳"])
+ (":flag-so:" ["🇸🇴"])
+ (":flag-sr:" ["🇸🇷"])
+ (":flag-ss:" ["🇸🇸"])
+ (":flag-st:" ["🇸🇹"])
+ (":flag-sv:" ["🇸🇻"])
+ (":flag-sx:" ["🇸🇽"])
+ (":flag-sy:" ["🇸🇾"])
+ (":flag-sz:" ["🇸🇿"])
+ (":flag-ta:" ["🇹🇦"])
+ (":flag-tc:" ["🇹🇨"])
+ (":flag-td:" ["🇹🇩"])
+ (":flag-tf:" ["🇹🇫"])
+ (":flag-tg:" ["🇹🇬"])
+ (":flag-th:" ["🇹🇭"])
+ (":flag-tj:" ["🇹🇯"])
+ (":flag-tk:" ["🇹🇰"])
+ (":flag-tl:" ["🇹🇱"])
+ (":flag-tm:" ["🇹🇲"])
+ (":flag-tn:" ["🇹🇳"])
+ (":flag-to:" ["🇹🇴"])
+ (":flag-tr:" ["🇹🇷"])
+ (":flag-tt:" ["🇹🇹"])
+ (":flag-tv:" ["🇹🇻"])
+ (":flag-tw:" ["🇹🇼"])
+ (":flag-tz:" ["🇹🇿"])
+ (":flag-ua:" ["🇺🇦"])
+ (":flag-ug:" ["🇺🇬"])
+ (":flag-um:" ["🇺🇲"])
+ (":flag-un:" ["🇺🇳"])
+ (":us:" ["🇺🇸"])
+ (":flag-us:" ["🇺🇸"])
+ (":flag-uy:" ["🇺🇾"])
+ (":flag-uz:" ["🇺🇿"])
+ (":flag-va:" ["🇻🇦"])
+ (":flag-vc:" ["🇻🇨"])
+ (":flag-ve:" ["🇻🇪"])
+ (":flag-vg:" ["🇻🇬"])
+ (":flag-vi:" ["🇻🇮"])
+ (":flag-vn:" ["🇻🇳"])
+ (":flag-vu:" ["🇻🇺"])
+ (":flag-wf:" ["🇼🇫"])
+ (":flag-ws:" ["🇼🇸"])
+ (":flag-xk:" ["🇽🇰"])
+ (":flag-ye:" ["🇾🇪"])
+ (":flag-yt:" ["🇾🇹"])
+ (":flag-za:" ["🇿🇦"])
+ (":flag-zm:" ["🇿🇲"])
+ (":flag-zw:" ["🇿🇼"])
+ (":koko:" ["🈁"])
+ (":sa:" ["🈂️"])
+ (":u7121:" ["🈚"])
+ (":u6307:" ["🈯"])
+ (":u7981:" ["🈲"])
+ (":u7a7a:" ["🈳"])
+ (":u5408:" ["🈴"])
+ (":u6e80:" ["🈵"])
+ (":u6709:" ["🈶"])
+ (":u6708:" ["🈷️"])
+ (":u7533:" ["🈸"])
+ (":u5272:" ["🈹"])
+ (":u55b6:" ["🈺"])
+ (":ideograph_advantage:" ["🉐"])
+ (":accept:" ["🉑"])
+ (":cyclone:" ["🌀"])
+ (":foggy:" ["🌁"])
+ (":closed_umbrella:" ["🌂"])
+ (":night_with_stars:" ["🌃"])
+ (":sunrise_over_mountains:" ["🌄"])
+ (":sunrise:" ["🌅"])
+ (":city_sunset:" ["🌆"])
+ (":city_sunrise:" ["🌇"])
+ (":rainbow:" ["🌈"])
+ (":bridge_at_night:" ["🌉"])
+ (":ocean:" ["🌊"])
+ (":volcano:" ["🌋"])
+ (":milky_way:" ["🌌"])
+ (":earth_africa:" ["🌍"])
+ (":earth_americas:" ["🌎"])
+ (":earth_asia:" ["🌏"])
+ (":globe_with_meridians:" ["🌐"])
+ (":new_moon:" ["🌑"])
+ (":waxing_crescent_moon:" ["🌒"])
+ (":first_quarter_moon:" ["🌓"])
+ (":moon:" ["🌔"])
+ (":waxing_gibbous_moon:" ["🌔"])
+ (":full_moon:" ["🌕"])
+ (":waning_gibbous_moon:" ["🌖"])
+ (":last_quarter_moon:" ["🌗"])
+ (":waning_crescent_moon:" ["🌘"])
+ (":crescent_moon:" ["🌙"])
+ (":new_moon_with_face:" ["🌚"])
+ (":first_quarter_moon_with_face:" ["🌛"])
+ (":last_quarter_moon_with_face:" ["🌜"])
+ (":full_moon_with_face:" ["🌝"])
+ (":sun_with_face:" ["🌞"])
+ (":star2:" ["🌟"])
+ (":stars:" ["🌠"])
+ (":thermometer:" ["🌡️"])
+ (":mostly_sunny:" ["🌤️"])
+ (":sun_small_cloud:" ["🌤️"])
+ (":barely_sunny:" ["🌥️"])
+ (":sun_behind_cloud:" ["🌥️"])
+ (":partly_sunny_rain:" ["🌦️"])
+ (":sun_behind_rain_cloud:" ["🌦️"])
+ (":rain_cloud:" ["🌧️"])
+ (":snow_cloud:" ["🌨️"])
+ (":lightning:" ["🌩️"])
+ (":lightning_cloud:" ["🌩️"])
+ (":tornado:" ["🌪️"])
+ (":tornado_cloud:" ["🌪️"])
+ (":fog:" ["🌫️"])
+ (":wind_blowing_face:" ["🌬️"])
+ (":hotdog:" ["🌭"])
+ (":taco:" ["🌮"])
+ (":burrito:" ["🌯"])
+ (":chestnut:" ["🌰"])
+ (":seedling:" ["🌱"])
+ (":evergreen_tree:" ["🌲"])
+ (":deciduous_tree:" ["🌳"])
+ (":palm_tree:" ["🌴"])
+ (":cactus:" ["🌵"])
+ (":hot_pepper:" ["🌶️"])
+ (":tulip:" ["🌷"])
+ (":cherry_blossom:" ["🌸"])
+ (":rose:" ["🌹"])
+ (":hibiscus:" ["🌺"])
+ (":sunflower:" ["🌻"])
+ (":blossom:" ["🌼"])
+ (":corn:" ["🌽"])
+ (":ear_of_rice:" ["🌾"])
+ (":herb:" ["🌿"])
+ (":four_leaf_clover:" ["🍀"])
+ (":maple_leaf:" ["🍁"])
+ (":fallen_leaf:" ["🍂"])
+ (":leaves:" ["🍃"])
+ (":mushroom:" ["🍄"])
+ (":tomato:" ["🍅"])
+ (":eggplant:" ["🍆"])
+ (":grapes:" ["🍇"])
+ (":melon:" ["🍈"])
+ (":watermelon:" ["🍉"])
+ (":tangerine:" ["🍊"])
+ (":lemon:" ["🍋"])
+ (":banana:" ["🍌"])
+ (":pineapple:" ["🍍"])
+ (":apple:" ["🍎"])
+ (":green_apple:" ["🍏"])
+ (":pear:" ["🍐"])
+ (":peach:" ["🍑"])
+ (":cherries:" ["🍒"])
+ (":strawberry:" ["🍓"])
+ (":hamburger:" ["🍔"])
+ (":pizza:" ["🍕"])
+ (":meat_on_bone:" ["🍖"])
+ (":poultry_leg:" ["🍗"])
+ (":rice_cracker:" ["🍘"])
+ (":rice_ball:" ["🍙"])
+ (":rice:" ["🍚"])
+ (":curry:" ["🍛"])
+ (":ramen:" ["🍜"])
+ (":spaghetti:" ["🍝"])
+ (":bread:" ["🍞"])
+ (":fries:" ["🍟"])
+ (":sweet_potato:" ["🍠"])
+ (":dango:" ["🍡"])
+ (":oden:" ["🍢"])
+ (":sushi:" ["🍣"])
+ (":fried_shrimp:" ["🍤"])
+ (":fish_cake:" ["🍥"])
+ (":icecream:" ["🍦"])
+ (":shaved_ice:" ["🍧"])
+ (":ice_cream:" ["🍨"])
+ (":doughnut:" ["🍩"])
+ (":cookie:" ["🍪"])
+ (":chocolate_bar:" ["🍫"])
+ (":candy:" ["🍬"])
+ (":lollipop:" ["🍭"])
+ (":custard:" ["🍮"])
+ (":honey_pot:" ["🍯"])
+ (":cake:" ["🍰"])
+ (":bento:" ["🍱"])
+ (":stew:" ["🍲"])
+ (":fried_egg:" ["🍳"])
+ (":cooking:" ["🍳"])
+ (":fork_and_knife:" ["🍴"])
+ (":tea:" ["🍵"])
+ (":sake:" ["🍶"])
+ (":wine_glass:" ["🍷"])
+ (":cocktail:" ["🍸"])
+ (":tropical_drink:" ["🍹"])
+ (":beer:" ["🍺"])
+ (":beers:" ["🍻"])
+ (":baby_bottle:" ["🍼"])
+ (":knife_fork_plate:" ["🍽️"])
+ (":champagne:" ["🍾"])
+ (":popcorn:" ["🍿"])
+ (":ribbon:" ["🎀"])
+ (":gift:" ["🎁"])
+ (":birthday:" ["🎂"])
+ (":jack_o_lantern:" ["🎃"])
+ (":christmas_tree:" ["🎄"])
+ (":santa:" ["🎅"])
+ (":fireworks:" ["🎆"])
+ (":sparkler:" ["🎇"])
+ (":balloon:" ["🎈"])
+ (":tada:" ["🎉"])
+ (":confetti_ball:" ["🎊"])
+ (":tanabata_tree:" ["🎋"])
+ (":crossed_flags:" ["🎌"])
+ (":bamboo:" ["🎍"])
+ (":dolls:" ["🎎"])
+ (":flags:" ["🎏"])
+ (":wind_chime:" ["🎐"])
+ (":rice_scene:" ["🎑"])
+ (":school_satchel:" ["🎒"])
+ (":mortar_board:" ["🎓"])
+ (":medal:" ["🎖️"])
+ (":reminder_ribbon:" ["🎗️"])
+ (":studio_microphone:" ["🎙️"])
+ (":level_slider:" ["🎚️"])
+ (":control_knobs:" ["🎛️"])
+ (":film_frames:" ["🎞️"])
+ (":admission_tickets:" ["🎟️"])
+ (":carousel_horse:" ["🎠"])
+ (":ferris_wheel:" ["🎡"])
+ (":roller_coaster:" ["🎢"])
+ (":fishing_pole_and_fish:" ["🎣"])
+ (":microphone:" ["🎤"])
+ (":movie_camera:" ["🎥"])
+ (":cinema:" ["🎦"])
+ (":headphones:" ["🎧"])
+ (":art:" ["🎨"])
+ (":tophat:" ["🎩"])
+ (":circus_tent:" ["🎪"])
+ (":ticket:" ["🎫"])
+ (":clapper:" ["🎬"])
+ (":performing_arts:" ["🎭"])
+ (":video_game:" ["🎮"])
+ (":dart:" ["🎯"])
+ (":slot_machine:" ["🎰"])
+ (":8ball:" ["🎱"])
+ (":game_die:" ["🎲"])
+ (":bowling:" ["🎳"])
+ (":flower_playing_cards:" ["🎴"])
+ (":musical_note:" ["🎵"])
+ (":notes:" ["🎶"])
+ (":saxophone:" ["🎷"])
+ (":guitar:" ["🎸"])
+ (":musical_keyboard:" ["🎹"])
+ (":trumpet:" ["🎺"])
+ (":violin:" ["🎻"])
+ (":musical_score:" ["🎼"])
+ (":running_shirt_with_sash:" ["🎽"])
+ (":tennis:" ["🎾"])
+ (":ski:" ["🎿"])
+ (":basketball:" ["🏀"])
+ (":checkered_flag:" ["🏁"])
+ (":snowboarder:" ["🏂"])
+ (":woman-running:" ["🏃‍♀️"])
+ (":man-running:" ["🏃‍♂️"])
+ (":runner:" ["🏃"])
+ (":running:" ["🏃"])
+ (":woman-surfing:" ["🏄‍♀️"])
+ (":man-surfing:" ["🏄‍♂️"])
+ (":surfer:" ["🏄"])
+ (":sports_medal:" ["🏅"])
+ (":trophy:" ["🏆"])
+ (":horse_racing:" ["🏇"])
+ (":football:" ["🏈"])
+ (":rugby_football:" ["🏉"])
+ (":woman-swimming:" ["🏊‍♀️"])
+ (":man-swimming:" ["🏊‍♂️"])
+ (":swimmer:" ["🏊"])
+ (":woman-lifting-weights:" ["🏋️‍♀️"])
+ (":man-lifting-weights:" ["🏋️‍♂️"])
+ (":weight_lifter:" ["🏋️"])
+ (":woman-golfing:" ["🏌️‍♀️"])
+ (":man-golfing:" ["🏌️‍♂️"])
+ (":golfer:" ["🏌️"])
+ (":racing_motorcycle:" ["🏍️"])
+ (":racing_car:" ["🏎️"])
+ (":cricket_bat_and_ball:" ["🏏"])
+ (":volleyball:" ["🏐"])
+ (":field_hockey_stick_and_ball:" ["🏑"])
+ (":ice_hockey_stick_and_puck:" ["🏒"])
+ (":table_tennis_paddle_and_ball:" ["🏓"])
+ (":snow_capped_mountain:" ["🏔️"])
+ (":camping:" ["🏕️"])
+ (":beach_with_umbrella:" ["🏖️"])
+ (":building_construction:" ["🏗️"])
+ (":house_buildings:" ["🏘️"])
+ (":cityscape:" ["🏙️"])
+ (":derelict_house_building:" ["🏚️"])
+ (":classical_building:" ["🏛️"])
+ (":desert:" ["🏜️"])
+ (":desert_island:" ["🏝️"])
+ (":national_park:" ["🏞️"])
+ (":stadium:" ["🏟️"])
+ (":house:" ["🏠"])
+ (":house_with_garden:" ["🏡"])
+ (":office:" ["🏢"])
+ (":post_office:" ["🏣"])
+ (":european_post_office:" ["🏤"])
+ (":hospital:" ["🏥"])
+ (":bank:" ["🏦"])
+ (":atm:" ["🏧"])
+ (":hotel:" ["🏨"])
+ (":love_hotel:" ["🏩"])
+ (":convenience_store:" ["🏪"])
+ (":school:" ["🏫"])
+ (":department_store:" ["🏬"])
+ (":factory:" ["🏭"])
+ (":izakaya_lantern:" ["🏮"])
+ (":lantern:" ["🏮"])
+ (":japanese_castle:" ["🏯"])
+ (":european_castle:" ["🏰"])
+ (":rainbow-flag:" ["🏳️‍🌈"])
+ (":transgender_flag:" ["🏳️‍⚧️"])
+ (":waving_white_flag:" ["🏳️"])
+ (":pirate_flag:" ["🏴‍☠️"])
+ (":flag-england:" ["🏴󠁧󠁢󠁥󠁮󠁧󠁿"])
+ (":flag-scotland:" ["🏴󠁧󠁢󠁳󠁣󠁴󠁿"])
+ (":flag-wales:" ["🏴󠁧󠁢󠁷󠁬󠁳󠁿"])
+ (":waving_black_flag:" ["🏴"])
+ (":rosette:" ["🏵️"])
+ (":label:" ["🏷️"])
+ (":badminton_racquet_and_shuttlecock:" ["🏸"])
+ (":bow_and_arrow:" ["🏹"])
+ (":amphora:" ["🏺"])
+ (":skin-tone-2:" ["🏻"])
+ (":skin-tone-3:" ["🏼"])
+ (":skin-tone-4:" ["🏽"])
+ (":skin-tone-5:" ["🏾"])
+ (":skin-tone-6:" ["🏿"])
+ (":rat:" ["🐀"])
+ (":mouse2:" ["🐁"])
+ (":ox:" ["🐂"])
+ (":water_buffalo:" ["🐃"])
+ (":cow2:" ["🐄"])
+ (":tiger2:" ["🐅"])
+ (":leopard:" ["🐆"])
+ (":rabbit2:" ["🐇"])
+ (":black_cat:" ["🐈‍⬛"])
+ (":cat2:" ["🐈"])
+ (":dragon:" ["🐉"])
+ (":crocodile:" ["🐊"])
+ (":whale2:" ["🐋"])
+ (":snail:" ["🐌"])
+ (":snake:" ["🐍"])
+ (":racehorse:" ["🐎"])
+ (":ram:" ["🐏"])
+ (":goat:" ["🐐"])
+ (":sheep:" ["🐑"])
+ (":monkey:" ["🐒"])
+ (":rooster:" ["🐓"])
+ (":chicken:" ["🐔"])
+ (":service_dog:" ["🐕‍🦺"])
+ (":dog2:" ["🐕"])
+ (":pig2:" ["🐖"])
+ (":boar:" ["🐗"])
+ (":elephant:" ["🐘"])
+ (":octopus:" ["🐙"])
+ (":shell:" ["🐚"])
+ (":bug:" ["🐛"])
+ (":ant:" ["🐜"])
+ (":bee:" ["🐝"])
+ (":honeybee:" ["🐝"])
+ (":ladybug:" ["🐞"])
+ (":lady_beetle:" ["🐞"])
+ (":fish:" ["🐟"])
+ (":tropical_fish:" ["🐠"])
+ (":blowfish:" ["🐡"])
+ (":turtle:" ["🐢"])
+ (":hatching_chick:" ["🐣"])
+ (":baby_chick:" ["🐤"])
+ (":hatched_chick:" ["🐥"])
+ (":bird:" ["🐦"])
+ (":penguin:" ["🐧"])
+ (":koala:" ["🐨"])
+ (":poodle:" ["🐩"])
+ (":dromedary_camel:" ["🐪"])
+ (":camel:" ["🐫"])
+ (":dolphin:" ["🐬"])
+ (":flipper:" ["🐬"])
+ (":mouse:" ["🐭"])
+ (":cow:" ["🐮"])
+ (":tiger:" ["🐯"])
+ (":rabbit:" ["🐰"])
+ (":cat:" ["🐱"])
+ (":dragon_face:" ["🐲"])
+ (":whale:" ["🐳"])
+ (":horse:" ["🐴"])
+ (":monkey_face:" ["🐵"])
+ (":o)" ["🐵"])
+ (":dog:" ["🐶"])
+ (":pig:" ["🐷"])
+ (":frog:" ["🐸"])
+ (":hamster:" ["🐹"])
+ (":wolf:" ["🐺"])
+ (":polar_bear:" ["🐻‍❄️"])
+ (":bear:" ["🐻"])
+ (":panda_face:" ["🐼"])
+ (":pig_nose:" ["🐽"])
+ (":feet:" ["🐾"])
+ (":paw_prints:" ["🐾"])
+ (":chipmunk:" ["🐿️"])
+ (":eyes:" ["👀"])
+ (":eye-in-speech-bubble:" ["👁️‍🗨️"])
+ (":eye:" ["👁️"])
+ (":ear:" ["👂"])
+ (":nose:" ["👃"])
+ (":lips:" ["👄"])
+ (":tongue:" ["👅"])
+ (":point_up_2:" ["👆"])
+ (":point_down:" ["👇"])
+ (":point_left:" ["👈"])
+ (":point_right:" ["👉"])
+ (":facepunch:" ["👊"])
+ (":punch:" ["👊"])
+ (":wave:" ["👋"])
+ (":ok_hand:" ["👌"])
+ (":+1:" ["👍"])
+ (":thumbsup:" ["👍"])
+ (":-1:" ["👎"])
+ (":thumbsdown:" ["👎"])
+ (":clap:" ["👏"])
+ (":open_hands:" ["👐"])
+ (":crown:" ["👑"])
+ (":womans_hat:" ["👒"])
+ (":eyeglasses:" ["👓"])
+ (":necktie:" ["👔"])
+ (":shirt:" ["👕"])
+ (":tshirt:" ["👕"])
+ (":jeans:" ["👖"])
+ (":dress:" ["👗"])
+ (":kimono:" ["👘"])
+ (":bikini:" ["👙"])
+ (":womans_clothes:" ["👚"])
+ (":purse:" ["👛"])
+ (":handbag:" ["👜"])
+ (":pouch:" ["👝"])
+ (":mans_shoe:" ["👞"])
+ (":shoe:" ["👞"])
+ (":athletic_shoe:" ["👟"])
+ (":high_heel:" ["👠"])
+ (":sandal:" ["👡"])
+ (":boot:" ["👢"])
+ (":footprints:" ["👣"])
+ (":bust_in_silhouette:" ["👤"])
+ (":busts_in_silhouette:" ["👥"])
+ (":boy:" ["👦"])
+ (":girl:" ["👧"])
+ (":male-farmer:" ["👨‍🌾"])
+ (":male-cook:" ["👨‍🍳"])
+ (":man_feeding_baby:" ["👨‍🍼"])
+ (":male-student:" ["👨‍🎓"])
+ (":male-singer:" ["👨‍🎤"])
+ (":male-artist:" ["👨‍🎨"])
+ (":male-teacher:" ["👨‍🏫"])
+ (":male-factory-worker:" ["👨‍🏭"])
+ (":man-boy-boy:" ["👨‍👦‍👦"])
+ (":man-boy:" ["👨‍👦"])
+ (":man-girl-boy:" ["👨‍👧‍👦"])
+ (":man-girl-girl:" ["👨‍👧‍👧"])
+ (":man-girl:" ["👨‍👧"])
+ (":man-man-boy:" ["👨‍👨‍👦"])
+ (":man-man-boy-boy:" ["👨‍👨‍👦‍👦"])
+ (":man-man-girl:" ["👨‍👨‍👧"])
+ (":man-man-girl-boy:" ["👨‍👨‍👧‍👦"])
+ (":man-man-girl-girl:" ["👨‍👨‍👧‍👧"])
+ (":man-woman-boy:" ["👨‍👩‍👦"])
+ (":man-woman-boy-boy:" ["👨‍👩‍👦‍👦"])
+ (":man-woman-girl:" ["👨‍👩‍👧"])
+ (":man-woman-girl-boy:" ["👨‍👩‍👧‍👦"])
+ (":man-woman-girl-girl:" ["👨‍👩‍👧‍👧"])
+ (":male-technologist:" ["👨‍💻"])
+ (":male-office-worker:" ["👨‍💼"])
+ (":male-mechanic:" ["👨‍🔧"])
+ (":male-scientist:" ["👨‍🔬"])
+ (":male-astronaut:" ["👨‍🚀"])
+ (":male-firefighter:" ["👨‍🚒"])
+ (":man_with_probing_cane:" ["👨‍🦯"])
+ (":red_haired_man:" ["👨‍🦰"])
+ (":curly_haired_man:" ["👨‍🦱"])
+ (":bald_man:" ["👨‍🦲"])
+ (":white_haired_man:" ["👨‍🦳"])
+ (":man_in_motorized_wheelchair:" ["👨‍🦼"])
+ (":man_in_manual_wheelchair:" ["👨‍🦽"])
+ (":male-doctor:" ["👨‍⚕️"])
+ (":male-judge:" ["👨‍⚖️"])
+ (":male-pilot:" ["👨‍✈️"])
+ (":man-heart-man:" ["👨‍❤️‍👨"])
+ (":man-kiss-man:" ["👨‍❤️‍💋‍👨"])
+ (":man:" ["👨"])
+ (":female-farmer:" ["👩‍🌾"])
+ (":female-cook:" ["👩‍🍳"])
+ (":woman_feeding_baby:" ["👩‍🍼"])
+ (":female-student:" ["👩‍🎓"])
+ (":female-singer:" ["👩‍🎤"])
+ (":female-artist:" ["👩‍🎨"])
+ (":female-teacher:" ["👩‍🏫"])
+ (":female-factory-worker:" ["👩‍🏭"])
+ (":woman-boy-boy:" ["👩‍👦‍👦"])
+ (":woman-boy:" ["👩‍👦"])
+ (":woman-girl-boy:" ["👩‍👧‍👦"])
+ (":woman-girl-girl:" ["👩‍👧‍👧"])
+ (":woman-girl:" ["👩‍👧"])
+ (":woman-woman-boy:" ["👩‍👩‍👦"])
+ (":woman-woman-boy-boy:" ["👩‍👩‍👦‍👦"])
+ (":woman-woman-girl:" ["👩‍👩‍👧"])
+ (":woman-woman-girl-boy:" ["👩‍👩‍👧‍👦"])
+ (":woman-woman-girl-girl:" ["👩‍👩‍👧‍👧"])
+ (":female-technologist:" ["👩‍💻"])
+ (":female-office-worker:" ["👩‍💼"])
+ (":female-mechanic:" ["👩‍🔧"])
+ (":female-scientist:" ["👩‍🔬"])
+ (":female-astronaut:" ["👩‍🚀"])
+ (":female-firefighter:" ["👩‍🚒"])
+ (":woman_with_probing_cane:" ["👩‍🦯"])
+ (":red_haired_woman:" ["👩‍🦰"])
+ (":curly_haired_woman:" ["👩‍🦱"])
+ (":bald_woman:" ["👩‍🦲"])
+ (":white_haired_woman:" ["👩‍🦳"])
+ (":woman_in_motorized_wheelchair:" ["👩‍🦼"])
+ (":woman_in_manual_wheelchair:" ["👩‍🦽"])
+ (":female-doctor:" ["👩‍⚕️"])
+ (":female-judge:" ["👩‍⚖️"])
+ (":female-pilot:" ["👩‍✈️"])
+ (":woman-heart-man:" ["👩‍❤️‍👨"])
+ (":woman-heart-woman:" ["👩‍❤️‍👩"])
+ (":woman-kiss-man:" ["👩‍❤️‍💋‍👨"])
+ (":woman-kiss-woman:" ["👩‍❤️‍💋‍👩"])
+ (":woman:" ["👩"])
+ (":family:" ["👪"])
+ (":man_and_woman_holding_hands:" ["👫"])
+ (":woman_and_man_holding_hands:" ["👫"])
+ (":couple:" ["👫"])
+ (":two_men_holding_hands:" ["👬"])
+ (":men_holding_hands:" ["👬"])
+ (":two_women_holding_hands:" ["👭"])
+ (":women_holding_hands:" ["👭"])
+ (":female-police-officer:" ["👮‍♀️"])
+ (":male-police-officer:" ["👮‍♂️"])
+ (":cop:" ["👮"])
+ (":women-with-bunny-ears-partying:" ["👯‍♀️"])
+ (":woman-with-bunny-ears-partying:" ["👯‍♀️"])
+ (":men-with-bunny-ears-partying:" ["👯‍♂️"])
+ (":man-with-bunny-ears-partying:" ["👯‍♂️"])
+ (":dancers:" ["👯"])
+ (":woman_with_veil:" ["👰‍♀️"])
+ (":man_with_veil:" ["👰‍♂️"])
+ (":bride_with_veil:" ["👰"])
+ (":blond-haired-woman:" ["👱‍♀️"])
+ (":blond-haired-man:" ["👱‍♂️"])
+ (":person_with_blond_hair:" ["👱"])
+ (":man_with_gua_pi_mao:" ["👲"])
+ (":woman-wearing-turban:" ["👳‍♀️"])
+ (":man-wearing-turban:" ["👳‍♂️"])
+ (":man_with_turban:" ["👳"])
+ (":older_man:" ["👴"])
+ (":older_woman:" ["👵"])
+ (":baby:" ["👶"])
+ (":female-construction-worker:" ["👷‍♀️"])
+ (":male-construction-worker:" ["👷‍♂️"])
+ (":construction_worker:" ["👷"])
+ (":princess:" ["👸"])
+ (":japanese_ogre:" ["👹"])
+ (":japanese_goblin:" ["👺"])
+ (":ghost:" ["👻"])
+ (":angel:" ["👼"])
+ (":alien:" ["👽"])
+ (":space_invader:" ["👾"])
+ (":imp:" ["👿"])
+ (":skull:" ["💀"])
+ (":woman-tipping-hand:" ["💁‍♀️"])
+ (":man-tipping-hand:" ["💁‍♂️"])
+ (":information_desk_person:" ["💁"])
+ (":female-guard:" ["💂‍♀️"])
+ (":male-guard:" ["💂‍♂️"])
+ (":guardsman:" ["💂"])
+ (":dancer:" ["💃"])
+ (":lipstick:" ["💄"])
+ (":nail_care:" ["💅"])
+ (":woman-getting-massage:" ["💆‍♀️"])
+ (":man-getting-massage:" ["💆‍♂️"])
+ (":massage:" ["💆"])
+ (":woman-getting-haircut:" ["💇‍♀️"])
+ (":man-getting-haircut:" ["💇‍♂️"])
+ (":haircut:" ["💇"])
+ (":barber:" ["💈"])
+ (":syringe:" ["💉"])
+ (":pill:" ["💊"])
+ (":kiss:" ["💋"])
+ (":love_letter:" ["💌"])
+ (":ring:" ["💍"])
+ (":gem:" ["💎"])
+ (":couplekiss:" ["💏"])
+ (":bouquet:" ["💐"])
+ (":couple_with_heart:" ["💑"])
+ (":wedding:" ["💒"])
+ (":heartbeat:" ["💓"])
+ (":broken_heart:" ["💔"])
+ ("</3" ["💔"])
+ (":two_hearts:" ["💕"])
+ (":sparkling_heart:" ["💖"])
+ (":heartpulse:" ["💗"])
+ (":cupid:" ["💘"])
+ (":blue_heart:" ["💙"])
+ ("<3" ["💙"])
+ (":green_heart:" ["💚"])
+ ("<3" ["💚"])
+ (":yellow_heart:" ["💛"])
+ ("<3" ["💛"])
+ (":purple_heart:" ["💜"])
+ ("<3" ["💜"])
+ (":gift_heart:" ["💝"])
+ (":revolving_hearts:" ["💞"])
+ (":heart_decoration:" ["💟"])
+ (":diamond_shape_with_a_dot_inside:" ["💠"])
+ (":bulb:" ["💡"])
+ (":anger:" ["💢"])
+ (":bomb:" ["💣"])
+ (":zzz:" ["💤"])
+ (":boom:" ["💥"])
+ (":collision:" ["💥"])
+ (":sweat_drops:" ["💦"])
+ (":droplet:" ["💧"])
+ (":dash:" ["💨"])
+ (":hankey:" ["💩"])
+ (":poop:" ["💩"])
+ (":shit:" ["💩"])
+ (":muscle:" ["💪"])
+ (":dizzy:" ["💫"])
+ (":speech_balloon:" ["💬"])
+ (":thought_balloon:" ["💭"])
+ (":white_flower:" ["💮"])
+ (":100:" ["💯"])
+ (":moneybag:" ["💰"])
+ (":currency_exchange:" ["💱"])
+ (":heavy_dollar_sign:" ["💲"])
+ (":credit_card:" ["💳"])
+ (":yen:" ["💴"])
+ (":dollar:" ["💵"])
+ (":euro:" ["💶"])
+ (":pound:" ["💷"])
+ (":money_with_wings:" ["💸"])
+ (":chart:" ["💹"])
+ (":seat:" ["💺"])
+ (":computer:" ["💻"])
+ (":briefcase:" ["💼"])
+ (":minidisc:" ["💽"])
+ (":floppy_disk:" ["💾"])
+ (":cd:" ["💿"])
+ (":dvd:" ["📀"])
+ (":file_folder:" ["📁"])
+ (":open_file_folder:" ["📂"])
+ (":page_with_curl:" ["📃"])
+ (":page_facing_up:" ["📄"])
+ (":date:" ["📅"])
+ (":calendar:" ["📆"])
+ (":card_index:" ["📇"])
+ (":chart_with_upwards_trend:" ["📈"])
+ (":chart_with_downwards_trend:" ["📉"])
+ (":bar_chart:" ["📊"])
+ (":clipboard:" ["📋"])
+ (":pushpin:" ["📌"])
+ (":round_pushpin:" ["📍"])
+ (":paperclip:" ["📎"])
+ (":straight_ruler:" ["📏"])
+ (":triangular_ruler:" ["📐"])
+ (":bookmark_tabs:" ["📑"])
+ (":ledger:" ["📒"])
+ (":notebook:" ["📓"])
+ (":notebook_with_decorative_cover:" ["📔"])
+ (":closed_book:" ["📕"])
+ (":book:" ["📖"])
+ (":open_book:" ["📖"])
+ (":green_book:" ["📗"])
+ (":blue_book:" ["📘"])
+ (":orange_book:" ["📙"])
+ (":books:" ["📚"])
+ (":name_badge:" ["📛"])
+ (":scroll:" ["📜"])
+ (":memo:" ["📝"])
+ (":pencil:" ["📝"])
+ (":telephone_receiver:" ["📞"])
+ (":pager:" ["📟"])
+ (":fax:" ["📠"])
+ (":satellite_antenna:" ["📡"])
+ (":loudspeaker:" ["📢"])
+ (":mega:" ["📣"])
+ (":outbox_tray:" ["📤"])
+ (":inbox_tray:" ["📥"])
+ (":package:" ["📦"])
+ (":e-mail:" ["📧"])
+ (":incoming_envelope:" ["📨"])
+ (":envelope_with_arrow:" ["📩"])
+ (":mailbox_closed:" ["📪"])
+ (":mailbox:" ["📫"])
+ (":mailbox_with_mail:" ["📬"])
+ (":mailbox_with_no_mail:" ["📭"])
+ (":postbox:" ["📮"])
+ (":postal_horn:" ["📯"])
+ (":newspaper:" ["📰"])
+ (":iphone:" ["📱"])
+ (":calling:" ["📲"])
+ (":vibration_mode:" ["📳"])
+ (":mobile_phone_off:" ["📴"])
+ (":no_mobile_phones:" ["📵"])
+ (":signal_strength:" ["📶"])
+ (":camera:" ["📷"])
+ (":camera_with_flash:" ["📸"])
+ (":video_camera:" ["📹"])
+ (":tv:" ["📺"])
+ (":radio:" ["📻"])
+ (":vhs:" ["📼"])
+ (":film_projector:" ["📽️"])
+ (":prayer_beads:" ["📿"])
+ (":twisted_rightwards_arrows:" ["🔀"])
+ (":repeat:" ["🔁"])
+ (":repeat_one:" ["🔂"])
+ (":arrows_clockwise:" ["🔃"])
+ (":arrows_counterclockwise:" ["🔄"])
+ (":low_brightness:" ["🔅"])
+ (":high_brightness:" ["🔆"])
+ (":mute:" ["🔇"])
+ (":speaker:" ["🔈"])
+ (":sound:" ["🔉"])
+ (":loud_sound:" ["🔊"])
+ (":battery:" ["🔋"])
+ (":electric_plug:" ["🔌"])
+ (":mag:" ["🔍"])
+ (":mag_right:" ["🔎"])
+ (":lock_with_ink_pen:" ["🔏"])
+ (":closed_lock_with_key:" ["🔐"])
+ (":key:" ["🔑"])
+ (":lock:" ["🔒"])
+ (":unlock:" ["🔓"])
+ (":bell:" ["🔔"])
+ (":no_bell:" ["🔕"])
+ (":bookmark:" ["🔖"])
+ (":link:" ["🔗"])
+ (":radio_button:" ["🔘"])
+ (":back:" ["🔙"])
+ (":end:" ["🔚"])
+ (":on:" ["🔛"])
+ (":soon:" ["🔜"])
+ (":top:" ["🔝"])
+ (":underage:" ["🔞"])
+ (":keycap_ten:" ["🔟"])
+ (":capital_abcd:" ["🔠"])
+ (":abcd:" ["🔡"])
+ (":1234:" ["🔢"])
+ (":symbols:" ["🔣"])
+ (":abc:" ["🔤"])
+ (":fire:" ["🔥"])
+ (":flashlight:" ["🔦"])
+ (":wrench:" ["🔧"])
+ (":hammer:" ["🔨"])
+ (":nut_and_bolt:" ["🔩"])
+ (":hocho:" ["🔪"])
+ (":knife:" ["🔪"])
+ (":gun:" ["🔫"])
+ (":microscope:" ["🔬"])
+ (":telescope:" ["🔭"])
+ (":crystal_ball:" ["🔮"])
+ (":six_pointed_star:" ["🔯"])
+ (":beginner:" ["🔰"])
+ (":trident:" ["🔱"])
+ (":black_square_button:" ["🔲"])
+ (":white_square_button:" ["🔳"])
+ (":red_circle:" ["🔴"])
+ (":large_blue_circle:" ["🔵"])
+ (":large_orange_diamond:" ["🔶"])
+ (":large_blue_diamond:" ["🔷"])
+ (":small_orange_diamond:" ["🔸"])
+ (":small_blue_diamond:" ["🔹"])
+ (":small_red_triangle:" ["🔺"])
+ (":small_red_triangle_down:" ["🔻"])
+ (":arrow_up_small:" ["🔼"])
+ (":arrow_down_small:" ["🔽"])
+ (":om_symbol:" ["🕉️"])
+ (":dove_of_peace:" ["🕊️"])
+ (":kaaba:" ["🕋"])
+ (":mosque:" ["🕌"])
+ (":synagogue:" ["🕍"])
+ (":menorah_with_nine_branches:" ["🕎"])
+ (":clock1:" ["🕐"])
+ (":clock2:" ["🕑"])
+ (":clock3:" ["🕒"])
+ (":clock4:" ["🕓"])
+ (":clock5:" ["🕔"])
+ (":clock6:" ["🕕"])
+ (":clock7:" ["🕖"])
+ (":clock8:" ["🕗"])
+ (":clock9:" ["🕘"])
+ (":clock10:" ["🕙"])
+ (":clock11:" ["🕚"])
+ (":clock12:" ["🕛"])
+ (":clock130:" ["🕜"])
+ (":clock230:" ["🕝"])
+ (":clock330:" ["🕞"])
+ (":clock430:" ["🕟"])
+ (":clock530:" ["🕠"])
+ (":clock630:" ["🕡"])
+ (":clock730:" ["🕢"])
+ (":clock830:" ["🕣"])
+ (":clock930:" ["🕤"])
+ (":clock1030:" ["🕥"])
+ (":clock1130:" ["🕦"])
+ (":clock1230:" ["🕧"])
+ (":candle:" ["🕯️"])
+ (":mantelpiece_clock:" ["🕰️"])
+ (":hole:" ["🕳️"])
+ (":man_in_business_suit_levitating:" ["🕴️"])
+ (":female-detective:" ["🕵️‍♀️"])
+ (":male-detective:" ["🕵️‍♂️"])
+ (":sleuth_or_spy:" ["🕵️"])
+ (":dark_sunglasses:" ["🕶️"])
+ (":spider:" ["🕷️"])
+ (":spider_web:" ["🕸️"])
+ (":joystick:" ["🕹️"])
+ (":man_dancing:" ["🕺"])
+ (":linked_paperclips:" ["🖇️"])
+ (":lower_left_ballpoint_pen:" ["🖊️"])
+ (":lower_left_fountain_pen:" ["🖋️"])
+ (":lower_left_paintbrush:" ["🖌️"])
+ (":lower_left_crayon:" ["🖍️"])
+ (":raised_hand_with_fingers_splayed:" ["🖐️"])
+ (":middle_finger:" ["🖕"])
+ (":reversed_hand_with_middle_finger_extended:" ["🖕"])
+ (":spock-hand:" ["🖖"])
+ (":black_heart:" ["🖤"])
+ (":desktop_computer:" ["🖥️"])
+ (":printer:" ["🖨️"])
+ (":three_button_mouse:" ["🖱️"])
+ (":trackball:" ["🖲️"])
+ (":frame_with_picture:" ["🖼️"])
+ (":card_index_dividers:" ["🗂️"])
+ (":card_file_box:" ["🗃️"])
+ (":file_cabinet:" ["🗄️"])
+ (":wastebasket:" ["🗑️"])
+ (":spiral_note_pad:" ["🗒️"])
+ (":spiral_calendar_pad:" ["🗓️"])
+ (":compression:" ["🗜️"])
+ (":old_key:" ["🗝️"])
+ (":rolled_up_newspaper:" ["🗞️"])
+ (":dagger_knife:" ["🗡️"])
+ (":speaking_head_in_silhouette:" ["🗣️"])
+ (":left_speech_bubble:" ["🗨️"])
+ (":right_anger_bubble:" ["🗯️"])
+ (":ballot_box_with_ballot:" ["🗳️"])
+ (":world_map:" ["🗺️"])
+ (":mount_fuji:" ["🗻"])
+ (":tokyo_tower:" ["🗼"])
+ (":statue_of_liberty:" ["🗽"])
+ (":japan:" ["🗾"])
+ (":moyai:" ["🗿"])
+ (":grinning:" ["😀"])
+ (":D" ["😀"])
+ (":grin:" ["😁"])
+ (":joy:" ["😂"])
+ (":smiley:" ["😃"])
+ (":)" ["😃"])
+ ("=)" ["😃"])
+ ("=-)" ["😃"])
+ (":smile:" ["😄"])
+ (":)" ["😄"])
+ ("C:" ["😄"])
+ ("c:" ["😄"])
+ (":D" ["😄"])
+ (":-D" ["😄"])
+ (":sweat_smile:" ["😅"])
+ (":laughing:" ["😆"])
+ (":satisfied:" ["😆"])
+ (":>" ["😆"])
+ (":->" ["😆"])
+ (":innocent:" ["😇"])
+ (":smiling_imp:" ["😈"])
+ (":wink:" ["😉"])
+ (";)" ["😉"])
+ (";-)" ["😉"])
+ (":blush:" ["😊"])
+ (":)" ["😊"])
+ (":yum:" ["😋"])
+ (":relieved:" ["😌"])
+ (":heart_eyes:" ["😍"])
+ (":sunglasses:" ["😎"])
+ ("8)" ["😎"])
+ (":smirk:" ["😏"])
+ (":neutral_face:" ["😐"])
+ (":|" ["😐"])
+ (":-|" ["😐"])
+ (":expressionless:" ["😑"])
+ (":unamused:" ["😒"])
+ (":(" ["😒"])
+ (":sweat:" ["😓"])
+ (":pensive:" ["😔"])
+ (":confused:" ["😕"])
+ (":\\" ["😕"])
+ (":-\\" ["😕"])
+ (":/" ["😕"])
+ (":-/" ["😕"])
+ (":confounded:" ["😖"])
+ (":kissing:" ["😗"])
+ (":kissing_heart:" ["😘"])
+ (":*" ["😘"])
+ (":-*" ["😘"])
+ (":kissing_smiling_eyes:" ["😙"])
+ (":kissing_closed_eyes:" ["😚"])
+ (":stuck_out_tongue:" ["😛"])
+ (":p" ["😛"])
+ (":-p" ["😛"])
+ (":P" ["😛"])
+ (":-P" ["😛"])
+ (":b" ["😛"])
+ (":-b" ["😛"])
+ (":stuck_out_tongue_winking_eye:" ["😜"])
+ (";p" ["😜"])
+ (";-p" ["😜"])
+ (";b" ["😜"])
+ (";-b" ["😜"])
+ (";P" ["😜"])
+ (";-P" ["😜"])
+ (":stuck_out_tongue_closed_eyes:" ["😝"])
+ (":disappointed:" ["😞"])
+ (":(" ["😞"])
+ ("):" ["😞"])
+ (":-(" ["😞"])
+ (":worried:" ["😟"])
+ (":angry:" ["😠"])
+ (">:(" ["😠"])
+ (">:-(" ["😠"])
+ (":rage:" ["😡"])
+ (":cry:" ["😢"])
+ (":'(" ["😢"])
+ (":persevere:" ["😣"])
+ (":triumph:" ["😤"])
+ (":disappointed_relieved:" ["😥"])
+ (":frowning:" ["😦"])
+ (":anguished:" ["😧"])
+ ("D:" ["😧"])
+ (":fearful:" ["😨"])
+ (":weary:" ["😩"])
+ (":sleepy:" ["😪"])
+ (":tired_face:" ["😫"])
+ (":grimacing:" ["😬"])
+ (":sob:" ["😭"])
+ (":'(" ["😭"])
+ (":face_exhaling:" ["😮‍💨"])
+ (":open_mouth:" ["😮"])
+ (":o" ["😮"])
+ (":-o" ["😮"])
+ (":O" ["😮"])
+ (":-O" ["😮"])
+ (":hushed:" ["😯"])
+ (":cold_sweat:" ["😰"])
+ (":scream:" ["😱"])
+ (":astonished:" ["😲"])
+ (":flushed:" ["😳"])
+ (":sleeping:" ["😴"])
+ (":face_with_spiral_eyes:" ["😵‍💫"])
+ (":dizzy_face:" ["😵"])
+ (":face_in_clouds:" ["😶‍🌫️"])
+ (":no_mouth:" ["😶"])
+ (":mask:" ["😷"])
+ (":smile_cat:" ["😸"])
+ (":joy_cat:" ["😹"])
+ (":smiley_cat:" ["😺"])
+ (":heart_eyes_cat:" ["😻"])
+ (":smirk_cat:" ["😼"])
+ (":kissing_cat:" ["😽"])
+ (":pouting_cat:" ["😾"])
+ (":crying_cat_face:" ["😿"])
+ (":scream_cat:" ["🙀"])
+ (":slightly_frowning_face:" ["🙁"])
+ (":slightly_smiling_face:" ["🙂"])
+ (":)" ["🙂"])
+ ("(:" ["🙂"])
+ (":-)" ["🙂"])
+ (":upside_down_face:" ["🙃"])
+ (":face_with_rolling_eyes:" ["🙄"])
+ (":woman-gesturing-no:" ["🙅‍♀️"])
+ (":man-gesturing-no:" ["🙅‍♂️"])
+ (":no_good:" ["🙅"])
+ (":woman-gesturing-ok:" ["🙆‍♀️"])
+ (":man-gesturing-ok:" ["🙆‍♂️"])
+ (":ok_woman:" ["🙆"])
+ (":woman-bowing:" ["🙇‍♀️"])
+ (":man-bowing:" ["🙇‍♂️"])
+ (":bow:" ["🙇"])
+ (":see_no_evil:" ["🙈"])
+ (":hear_no_evil:" ["🙉"])
+ (":speak_no_evil:" ["🙊"])
+ (":woman-raising-hand:" ["🙋‍♀️"])
+ (":man-raising-hand:" ["🙋‍♂️"])
+ (":raising_hand:" ["🙋"])
+ (":raised_hands:" ["🙌"])
+ (":woman-frowning:" ["🙍‍♀️"])
+ (":man-frowning:" ["🙍‍♂️"])
+ (":person_frowning:" ["🙍"])
+ (":woman-pouting:" ["🙎‍♀️"])
+ (":man-pouting:" ["🙎‍♂️"])
+ (":person_with_pouting_face:" ["🙎"])
+ (":pray:" ["🙏"])
+ (":rocket:" ["🚀"])
+ (":helicopter:" ["🚁"])
+ (":steam_locomotive:" ["🚂"])
+ (":railway_car:" ["🚃"])
+ (":bullettrain_side:" ["🚄"])
+ (":bullettrain_front:" ["🚅"])
+ (":train2:" ["🚆"])
+ (":metro:" ["🚇"])
+ (":light_rail:" ["🚈"])
+ (":station:" ["🚉"])
+ (":tram:" ["🚊"])
+ (":train:" ["🚋"])
+ (":bus:" ["🚌"])
+ (":oncoming_bus:" ["🚍"])
+ (":trolleybus:" ["🚎"])
+ (":busstop:" ["🚏"])
+ (":minibus:" ["🚐"])
+ (":ambulance:" ["🚑"])
+ (":fire_engine:" ["🚒"])
+ (":police_car:" ["🚓"])
+ (":oncoming_police_car:" ["🚔"])
+ (":taxi:" ["🚕"])
+ (":oncoming_taxi:" ["🚖"])
+ (":car:" ["🚗"])
+ (":red_car:" ["🚗"])
+ (":oncoming_automobile:" ["🚘"])
+ (":blue_car:" ["🚙"])
+ (":truck:" ["🚚"])
+ (":articulated_lorry:" ["🚛"])
+ (":tractor:" ["🚜"])
+ (":monorail:" ["🚝"])
+ (":mountain_railway:" ["🚞"])
+ (":suspension_railway:" ["🚟"])
+ (":mountain_cableway:" ["🚠"])
+ (":aerial_tramway:" ["🚡"])
+ (":ship:" ["🚢"])
+ (":woman-rowing-boat:" ["🚣‍♀️"])
+ (":man-rowing-boat:" ["🚣‍♂️"])
+ (":rowboat:" ["🚣"])
+ (":speedboat:" ["🚤"])
+ (":traffic_light:" ["🚥"])
+ (":vertical_traffic_light:" ["🚦"])
+ (":construction:" ["🚧"])
+ (":rotating_light:" ["🚨"])
+ (":triangular_flag_on_post:" ["🚩"])
+ (":door:" ["🚪"])
+ (":no_entry_sign:" ["🚫"])
+ (":smoking:" ["🚬"])
+ (":no_smoking:" ["🚭"])
+ (":put_litter_in_its_place:" ["🚮"])
+ (":do_not_litter:" ["🚯"])
+ (":potable_water:" ["🚰"])
+ (":non-potable_water:" ["🚱"])
+ (":bike:" ["🚲"])
+ (":no_bicycles:" ["🚳"])
+ (":woman-biking:" ["🚴‍♀️"])
+ (":man-biking:" ["🚴‍♂️"])
+ (":bicyclist:" ["🚴"])
+ (":woman-mountain-biking:" ["🚵‍♀️"])
+ (":man-mountain-biking:" ["🚵‍♂️"])
+ (":mountain_bicyclist:" ["🚵"])
+ (":woman-walking:" ["🚶‍♀️"])
+ (":man-walking:" ["🚶‍♂️"])
+ (":walking:" ["🚶"])
+ (":no_pedestrians:" ["🚷"])
+ (":children_crossing:" ["🚸"])
+ (":mens:" ["🚹"])
+ (":womens:" ["🚺"])
+ (":restroom:" ["🚻"])
+ (":baby_symbol:" ["🚼"])
+ (":toilet:" ["🚽"])
+ (":wc:" ["🚾"])
+ (":shower:" ["🚿"])
+ (":bath:" ["🛀"])
+ (":bathtub:" ["🛁"])
+ (":passport_control:" ["🛂"])
+ (":customs:" ["🛃"])
+ (":baggage_claim:" ["🛄"])
+ (":left_luggage:" ["🛅"])
+ (":couch_and_lamp:" ["🛋️"])
+ (":sleeping_accommodation:" ["🛌"])
+ (":shopping_bags:" ["🛍️"])
+ (":bellhop_bell:" ["🛎️"])
+ (":bed:" ["🛏️"])
+ (":place_of_worship:" ["🛐"])
+ (":octagonal_sign:" ["🛑"])
+ (":shopping_trolley:" ["🛒"])
+ (":hindu_temple:" ["🛕"])
+ (":hut:" ["🛖"])
+ (":elevator:" ["🛗"])
+ (":hammer_and_wrench:" ["🛠️"])
+ (":shield:" ["🛡️"])
+ (":oil_drum:" ["🛢️"])
+ (":motorway:" ["🛣️"])
+ (":railway_track:" ["🛤️"])
+ (":motor_boat:" ["🛥️"])
+ (":small_airplane:" ["🛩️"])
+ (":airplane_departure:" ["🛫"])
+ (":airplane_arriving:" ["🛬"])
+ (":satellite:" ["🛰️"])
+ (":passenger_ship:" ["🛳️"])
+ (":scooter:" ["🛴"])
+ (":motor_scooter:" ["🛵"])
+ (":canoe:" ["🛶"])
+ (":sled:" ["🛷"])
+ (":flying_saucer:" ["🛸"])
+ (":skateboard:" ["🛹"])
+ (":auto_rickshaw:" ["🛺"])
+ (":pickup_truck:" ["🛻"])
+ (":roller_skate:" ["🛼"])
+ (":large_orange_circle:" ["🟠"])
+ (":large_yellow_circle:" ["🟡"])
+ (":large_green_circle:" ["🟢"])
+ (":large_purple_circle:" ["🟣"])
+ (":large_brown_circle:" ["🟤"])
+ (":large_red_square:" ["🟥"])
+ (":large_blue_square:" ["🟦"])
+ (":large_orange_square:" ["🟧"])
+ (":large_yellow_square:" ["🟨"])
+ (":large_green_square:" ["🟩"])
+ (":large_purple_square:" ["🟪"])
+ (":large_brown_square:" ["🟫"])
+ (":pinched_fingers:" ["🤌"])
+ (":white_heart:" ["🤍"])
+ (":brown_heart:" ["🤎"])
+ (":pinching_hand:" ["🤏"])
+ (":zipper_mouth_face:" ["🤐"])
+ (":money_mouth_face:" ["🤑"])
+ (":face_with_thermometer:" ["🤒"])
+ (":nerd_face:" ["🤓"])
+ (":thinking_face:" ["🤔"])
+ (":face_with_head_bandage:" ["🤕"])
+ (":robot_face:" ["🤖"])
+ (":hugging_face:" ["🤗"])
+ (":the_horns:" ["🤘"])
+ (":sign_of_the_horns:" ["🤘"])
+ (":call_me_hand:" ["🤙"])
+ (":raised_back_of_hand:" ["🤚"])
+ (":left-facing_fist:" ["🤛"])
+ (":right-facing_fist:" ["🤜"])
+ (":handshake:" ["🤝"])
+ (":crossed_fingers:" ["🤞"])
+ (":hand_with_index_and_middle_fingers_crossed:" ["🤞"])
+ (":i_love_you_hand_sign:" ["🤟"])
+ (":face_with_cowboy_hat:" ["🤠"])
+ (":clown_face:" ["🤡"])
+ (":nauseated_face:" ["🤢"])
+ (":rolling_on_the_floor_laughing:" ["🤣"])
+ (":drooling_face:" ["🤤"])
+ (":lying_face:" ["🤥"])
+ (":woman-facepalming:" ["🤦‍♀️"])
+ (":man-facepalming:" ["🤦‍♂️"])
+ (":face_palm:" ["🤦"])
+ (":sneezing_face:" ["🤧"])
+ (":face_with_raised_eyebrow:" ["🤨"])
+ (":face_with_one_eyebrow_raised:" ["🤨"])
+ (":star-struck:" ["🤩"])
+ (":grinning_face_with_star_eyes:" ["🤩"])
+ (":zany_face:" ["🤪"])
+ (":grinning_face_with_one_large_and_one_small_eye:" ["🤪"])
+ (":shushing_face:" ["🤫"])
+ (":face_with_finger_covering_closed_lips:" ["🤫"])
+ (":face_with_symbols_on_mouth:" ["🤬"])
+ (":serious_face_with_symbols_covering_mouth:" ["🤬"])
+ (":face_with_hand_over_mouth:" ["🤭"])
+ (":smiling_face_with_smiling_eyes_and_hand_covering_mouth:" ["🤭"])
+ (":face_vomiting:" ["🤮"])
+ (":face_with_open_mouth_vomiting:" ["🤮"])
+ (":exploding_head:" ["🤯"])
+ (":shocked_face_with_exploding_head:" ["🤯"])
+ (":pregnant_woman:" ["🤰"])
+ (":breast-feeding:" ["🤱"])
+ (":palms_up_together:" ["🤲"])
+ (":selfie:" ["🤳"])
+ (":prince:" ["🤴"])
+ (":woman_in_tuxedo:" ["🤵‍♀️"])
+ (":man_in_tuxedo:" ["🤵‍♂️"])
+ (":person_in_tuxedo:" ["🤵"])
+ (":mrs_claus:" ["🤶"])
+ (":mother_christmas:" ["🤶"])
+ (":woman-shrugging:" ["🤷‍♀️"])
+ (":man-shrugging:" ["🤷‍♂️"])
+ (":shrug:" ["🤷"])
+ (":woman-cartwheeling:" ["🤸‍♀️"])
+ (":man-cartwheeling:" ["🤸‍♂️"])
+ (":person_doing_cartwheel:" ["🤸"])
+ (":woman-juggling:" ["🤹‍♀️"])
+ (":man-juggling:" ["🤹‍♂️"])
+ (":juggling:" ["🤹"])
+ (":fencer:" ["🤺"])
+ (":woman-wrestling:" ["🤼‍♀️"])
+ (":man-wrestling:" ["🤼‍♂️"])
+ (":wrestlers:" ["🤼"])
+ (":woman-playing-water-polo:" ["🤽‍♀️"])
+ (":man-playing-water-polo:" ["🤽‍♂️"])
+ (":water_polo:" ["🤽"])
+ (":woman-playing-handball:" ["🤾‍♀️"])
+ (":man-playing-handball:" ["🤾‍♂️"])
+ (":handball:" ["🤾"])
+ (":diving_mask:" ["🤿"])
+ (":wilted_flower:" ["🥀"])
+ (":drum_with_drumsticks:" ["🥁"])
+ (":clinking_glasses:" ["🥂"])
+ (":tumbler_glass:" ["🥃"])
+ (":spoon:" ["🥄"])
+ (":goal_net:" ["🥅"])
+ (":first_place_medal:" ["🥇"])
+ (":second_place_medal:" ["🥈"])
+ (":third_place_medal:" ["🥉"])
+ (":boxing_glove:" ["🥊"])
+ (":martial_arts_uniform:" ["🥋"])
+ (":curling_stone:" ["🥌"])
+ (":lacrosse:" ["🥍"])
+ (":softball:" ["🥎"])
+ (":flying_disc:" ["🥏"])
+ (":croissant:" ["🥐"])
+ (":avocado:" ["🥑"])
+ (":cucumber:" ["🥒"])
+ (":bacon:" ["🥓"])
+ (":potato:" ["🥔"])
+ (":carrot:" ["🥕"])
+ (":baguette_bread:" ["🥖"])
+ (":green_salad:" ["🥗"])
+ (":shallow_pan_of_food:" ["🥘"])
+ (":stuffed_flatbread:" ["🥙"])
+ (":egg:" ["🥚"])
+ (":glass_of_milk:" ["🥛"])
+ (":peanuts:" ["🥜"])
+ (":kiwifruit:" ["🥝"])
+ (":pancakes:" ["🥞"])
+ (":dumpling:" ["🥟"])
+ (":fortune_cookie:" ["🥠"])
+ (":takeout_box:" ["🥡"])
+ (":chopsticks:" ["🥢"])
+ (":bowl_with_spoon:" ["🥣"])
+ (":cup_with_straw:" ["🥤"])
+ (":coconut:" ["🥥"])
+ (":broccoli:" ["🥦"])
+ (":pie:" ["🥧"])
+ (":pretzel:" ["🥨"])
+ (":cut_of_meat:" ["🥩"])
+ (":sandwich:" ["🥪"])
+ (":canned_food:" ["🥫"])
+ (":leafy_green:" ["🥬"])
+ (":mango:" ["🥭"])
+ (":moon_cake:" ["🥮"])
+ (":bagel:" ["🥯"])
+ (":smiling_face_with_3_hearts:" ["🥰"])
+ (":yawning_face:" ["🥱"])
+ (":smiling_face_with_tear:" ["🥲"])
+ (":partying_face:" ["🥳"])
+ (":woozy_face:" ["🥴"])
+ (":hot_face:" ["🥵"])
+ (":cold_face:" ["🥶"])
+ (":ninja:" ["🥷"])
+ (":disguised_face:" ["🥸"])
+ (":pleading_face:" ["🥺"])
+ (":sari:" ["🥻"])
+ (":lab_coat:" ["🥼"])
+ (":goggles:" ["🥽"])
+ (":hiking_boot:" ["🥾"])
+ (":womans_flat_shoe:" ["🥿"])
+ (":crab:" ["🦀"])
+ (":lion_face:" ["🦁"])
+ (":scorpion:" ["🦂"])
+ (":turkey:" ["🦃"])
+ (":unicorn_face:" ["🦄"])
+ (":eagle:" ["🦅"])
+ (":duck:" ["🦆"])
+ (":bat:" ["🦇"])
+ (":shark:" ["🦈"])
+ (":owl:" ["🦉"])
+ (":fox_face:" ["🦊"])
+ (":butterfly:" ["🦋"])
+ (":deer:" ["🦌"])
+ (":gorilla:" ["🦍"])
+ (":lizard:" ["🦎"])
+ (":rhinoceros:" ["🦏"])
+ (":shrimp:" ["🦐"])
+ (":squid:" ["🦑"])
+ (":giraffe_face:" ["🦒"])
+ (":zebra_face:" ["🦓"])
+ (":hedgehog:" ["🦔"])
+ (":sauropod:" ["🦕"])
+ (":t-rex:" ["🦖"])
+ (":cricket:" ["🦗"])
+ (":kangaroo:" ["🦘"])
+ (":llama:" ["🦙"])
+ (":peacock:" ["🦚"])
+ (":hippopotamus:" ["🦛"])
+ (":parrot:" ["🦜"])
+ (":raccoon:" ["🦝"])
+ (":lobster:" ["🦞"])
+ (":mosquito:" ["🦟"])
+ (":microbe:" ["🦠"])
+ (":badger:" ["🦡"])
+ (":swan:" ["🦢"])
+ (":mammoth:" ["🦣"])
+ (":dodo:" ["🦤"])
+ (":sloth:" ["🦥"])
+ (":otter:" ["🦦"])
+ (":orangutan:" ["🦧"])
+ (":skunk:" ["🦨"])
+ (":flamingo:" ["🦩"])
+ (":oyster:" ["🦪"])
+ (":beaver:" ["🦫"])
+ (":bison:" ["🦬"])
+ (":seal:" ["🦭"])
+ (":guide_dog:" ["🦮"])
+ (":probing_cane:" ["🦯"])
+ (":bone:" ["🦴"])
+ (":leg:" ["🦵"])
+ (":foot:" ["🦶"])
+ (":tooth:" ["🦷"])
+ (":female_superhero:" ["🦸‍♀️"])
+ (":male_superhero:" ["🦸‍♂️"])
+ (":superhero:" ["🦸"])
+ (":female_supervillain:" ["🦹‍♀️"])
+ (":male_supervillain:" ["🦹‍♂️"])
+ (":supervillain:" ["🦹"])
+ (":safety_vest:" ["🦺"])
+ (":ear_with_hearing_aid:" ["🦻"])
+ (":motorized_wheelchair:" ["🦼"])
+ (":manual_wheelchair:" ["🦽"])
+ (":mechanical_arm:" ["🦾"])
+ (":mechanical_leg:" ["🦿"])
+ (":cheese_wedge:" ["🧀"])
+ (":cupcake:" ["🧁"])
+ (":salt:" ["🧂"])
+ (":beverage_box:" ["🧃"])
+ (":garlic:" ["🧄"])
+ (":onion:" ["🧅"])
+ (":falafel:" ["🧆"])
+ (":waffle:" ["🧇"])
+ (":butter:" ["🧈"])
+ (":mate_drink:" ["🧉"])
+ (":ice_cube:" ["🧊"])
+ (":bubble_tea:" ["🧋"])
+ (":woman_standing:" ["🧍‍♀️"])
+ (":man_standing:" ["🧍‍♂️"])
+ (":standing_person:" ["🧍"])
+ (":woman_kneeling:" ["🧎‍♀️"])
+ (":man_kneeling:" ["🧎‍♂️"])
+ (":kneeling_person:" ["🧎"])
+ (":deaf_woman:" ["🧏‍♀️"])
+ (":deaf_man:" ["🧏‍♂️"])
+ (":deaf_person:" ["🧏"])
+ (":face_with_monocle:" ["🧐"])
+ (":farmer:" ["🧑‍🌾"])
+ (":cook:" ["🧑‍🍳"])
+ (":person_feeding_baby:" ["🧑‍🍼"])
+ (":mx_claus:" ["🧑‍🎄"])
+ (":student:" ["🧑‍🎓"])
+ (":singer:" ["🧑‍🎤"])
+ (":artist:" ["🧑‍🎨"])
+ (":teacher:" ["🧑‍🏫"])
+ (":factory_worker:" ["🧑‍🏭"])
+ (":technologist:" ["🧑‍💻"])
+ (":office_worker:" ["🧑‍💼"])
+ (":mechanic:" ["🧑‍🔧"])
+ (":scientist:" ["🧑‍🔬"])
+ (":astronaut:" ["🧑‍🚀"])
+ (":firefighter:" ["🧑‍🚒"])
+ (":people_holding_hands:" ["🧑‍🤝‍🧑"])
+ (":person_with_probing_cane:" ["🧑‍🦯"])
+ (":red_haired_person:" ["🧑‍🦰"])
+ (":curly_haired_person:" ["🧑‍🦱"])
+ (":bald_person:" ["🧑‍🦲"])
+ (":white_haired_person:" ["🧑‍🦳"])
+ (":person_in_motorized_wheelchair:" ["🧑‍🦼"])
+ (":person_in_manual_wheelchair:" ["🧑‍🦽"])
+ (":health_worker:" ["🧑‍⚕️"])
+ (":judge:" ["🧑‍⚖️"])
+ (":pilot:" ["🧑‍✈️"])
+ (":adult:" ["🧑"])
+ (":child:" ["🧒"])
+ (":older_adult:" ["🧓"])
+ (":woman_with_beard:" ["🧔‍♀️"])
+ (":man_with_beard:" ["🧔‍♂️"])
+ (":bearded_person:" ["🧔"])
+ (":person_with_headscarf:" ["🧕"])
+ (":woman_in_steamy_room:" ["🧖‍♀️"])
+ (":man_in_steamy_room:" ["🧖‍♂️"])
+ (":person_in_steamy_room:" ["🧖"])
+ (":woman_climbing:" ["🧗‍♀️"])
+ (":man_climbing:" ["🧗‍♂️"])
+ (":person_climbing:" ["🧗"])
+ (":woman_in_lotus_position:" ["🧘‍♀️"])
+ (":man_in_lotus_position:" ["🧘‍♂️"])
+ (":person_in_lotus_position:" ["🧘"])
+ (":female_mage:" ["🧙‍♀️"])
+ (":male_mage:" ["🧙‍♂️"])
+ (":mage:" ["🧙"])
+ (":female_fairy:" ["🧚‍♀️"])
+ (":male_fairy:" ["🧚‍♂️"])
+ (":fairy:" ["🧚"])
+ (":female_vampire:" ["🧛‍♀️"])
+ (":male_vampire:" ["🧛‍♂️"])
+ (":vampire:" ["🧛"])
+ (":mermaid:" ["🧜‍♀️"])
+ (":merman:" ["🧜‍♂️"])
+ (":merperson:" ["🧜"])
+ (":female_elf:" ["🧝‍♀️"])
+ (":male_elf:" ["🧝‍♂️"])
+ (":elf:" ["🧝"])
+ (":female_genie:" ["🧞‍♀️"])
+ (":male_genie:" ["🧞‍♂️"])
+ (":genie:" ["🧞"])
+ (":female_zombie:" ["🧟‍♀️"])
+ (":male_zombie:" ["🧟‍♂️"])
+ (":zombie:" ["🧟"])
+ (":brain:" ["🧠"])
+ (":orange_heart:" ["🧡"])
+ (":billed_cap:" ["🧢"])
+ (":scarf:" ["🧣"])
+ (":gloves:" ["🧤"])
+ (":coat:" ["🧥"])
+ (":socks:" ["🧦"])
+ (":red_envelope:" ["🧧"])
+ (":firecracker:" ["🧨"])
+ (":jigsaw:" ["🧩"])
+ (":test_tube:" ["🧪"])
+ (":petri_dish:" ["🧫"])
+ (":dna:" ["🧬"])
+ (":compass:" ["🧭"])
+ (":abacus:" ["🧮"])
+ (":fire_extinguisher:" ["🧯"])
+ (":toolbox:" ["🧰"])
+ (":bricks:" ["🧱"])
+ (":magnet:" ["🧲"])
+ (":luggage:" ["🧳"])
+ (":lotion_bottle:" ["🧴"])
+ (":thread:" ["🧵"])
+ (":yarn:" ["🧶"])
+ (":safety_pin:" ["🧷"])
+ (":teddy_bear:" ["🧸"])
+ (":broom:" ["🧹"])
+ (":basket:" ["🧺"])
+ (":roll_of_paper:" ["🧻"])
+ (":soap:" ["🧼"])
+ (":sponge:" ["🧽"])
+ (":receipt:" ["🧾"])
+ (":nazar_amulet:" ["🧿"])
+ (":ballet_shoes:" ["🩰"])
+ (":one-piece_swimsuit:" ["🩱"])
+ (":briefs:" ["🩲"])
+ (":shorts:" ["🩳"])
+ (":thong_sandal:" ["🩴"])
+ (":drop_of_blood:" ["🩸"])
+ (":adhesive_bandage:" ["🩹"])
+ (":stethoscope:" ["🩺"])
+ (":yo-yo:" ["🪀"])
+ (":kite:" ["🪁"])
+ (":parachute:" ["🪂"])
+ (":boomerang:" ["🪃"])
+ (":magic_wand:" ["🪄"])
+ (":pinata:" ["🪅"])
+ (":nesting_dolls:" ["🪆"])
+ (":ringed_planet:" ["🪐"])
+ (":chair:" ["🪑"])
+ (":razor:" ["🪒"])
+ (":axe:" ["🪓"])
+ (":diya_lamp:" ["🪔"])
+ (":banjo:" ["🪕"])
+ (":military_helmet:" ["🪖"])
+ (":accordion:" ["🪗"])
+ (":long_drum:" ["🪘"])
+ (":coin:" ["🪙"])
+ (":carpentry_saw:" ["🪚"])
+ (":screwdriver:" ["🪛"])
+ (":ladder:" ["🪜"])
+ (":hook:" ["🪝"])
+ (":mirror:" ["🪞"])
+ (":window:" ["🪟"])
+ (":plunger:" ["🪠"])
+ (":sewing_needle:" ["🪡"])
+ (":knot:" ["🪢"])
+ (":bucket:" ["🪣"])
+ (":mouse_trap:" ["🪤"])
+ (":toothbrush:" ["🪥"])
+ (":headstone:" ["🪦"])
+ (":placard:" ["🪧"])
+ (":rock:" ["🪨"])
+ (":fly:" ["🪰"])
+ (":worm:" ["🪱"])
+ (":beetle:" ["🪲"])
+ (":cockroach:" ["🪳"])
+ (":potted_plant:" ["🪴"])
+ (":wood:" ["🪵"])
+ (":feather:" ["🪶"])
+ (":anatomical_heart:" ["🫀"])
+ (":lungs:" ["🫁"])
+ (":people_hugging:" ["🫂"])
+ (":blueberries:" ["🫐"])
+ (":bell_pepper:" ["🫑"])
+ (":olive:" ["🫒"])
+ (":flatbread:" ["🫓"])
+ (":tamale:" ["🫔"])
+ (":fondue:" ["🫕"])
+ (":teapot:" ["🫖"])
+ (":bangbang:" ["‼️"])
+ (":interrobang:" ["⁉️"])
+ (":tm:" ["™️"])
+ (":information_source:" ["ℹ️"])
+ (":left_right_arrow:" ["↔️"])
+ (":arrow_up_down:" ["↕️"])
+ (":arrow_upper_left:" ["↖️"])
+ (":arrow_upper_right:" ["↗️"])
+ (":arrow_lower_right:" ["↘️"])
+ (":arrow_lower_left:" ["↙️"])
+ (":leftwards_arrow_with_hook:" ["↩️"])
+ (":arrow_right_hook:" ["↪️"])
+ (":watch:" ["⌚"])
+ (":hourglass:" ["⌛"])
+ (":keyboard:" ["⌨️"])
+ (":eject:" ["⏏️"])
+ (":fast_forward:" ["⏩"])
+ (":rewind:" ["⏪"])
+ (":arrow_double_up:" ["⏫"])
+ (":arrow_double_down:" ["⏬"])
+ (":black_right_pointing_double_triangle_with_vertical_bar:" ["⏭️"])
+ (":black_left_pointing_double_triangle_with_vertical_bar:" ["⏮️"])
+ (":black_right_pointing_triangle_with_double_vertical_bar:" ["⏯️"])
+ (":alarm_clock:" ["⏰"])
+ (":stopwatch:" ["⏱️"])
+ (":timer_clock:" ["⏲️"])
+ (":hourglass_flowing_sand:" ["⏳"])
+ (":double_vertical_bar:" ["⏸️"])
+ (":black_square_for_stop:" ["⏹️"])
+ (":black_circle_for_record:" ["⏺️"])
+ (":m:" ["Ⓜ️"])
+ (":black_small_square:" ["▪️"])
+ (":white_small_square:" ["▫️"])
+ (":arrow_forward:" ["▶️"])
+ (":arrow_backward:" ["◀️"])
+ (":white_medium_square:" ["◻️"])
+ (":black_medium_square:" ["◼️"])
+ (":white_medium_small_square:" ["◽"])
+ (":black_medium_small_square:" ["◾"])
+ (":sunny:" ["☀️"])
+ (":cloud:" ["☁️"])
+ (":umbrella:" ["☂️"])
+ (":snowman:" ["☃️"])
+ (":comet:" ["☄️"])
+ (":phone:" ["☎️"])
+ (":telephone:" ["☎️"])
+ (":ballot_box_with_check:" ["☑️"])
+ (":umbrella_with_rain_drops:" ["☔"])
+ (":coffee:" ["☕"])
+ (":shamrock:" ["☘️"])
+ (":point_up:" ["☝️"])
+ (":skull_and_crossbones:" ["☠️"])
+ (":radioactive_sign:" ["☢️"])
+ (":biohazard_sign:" ["☣️"])
+ (":orthodox_cross:" ["☦️"])
+ (":star_and_crescent:" ["☪️"])
+ (":peace_symbol:" ["☮️"])
+ (":yin_yang:" ["☯️"])
+ (":wheel_of_dharma:" ["☸️"])
+ (":white_frowning_face:" ["☹️"])
+ (":relaxed:" ["☺️"])
+ (":female_sign:" ["♀️"])
+ (":male_sign:" ["♂️"])
+ (":aries:" ["♈"])
+ (":taurus:" ["♉"])
+ (":gemini:" ["♊"])
+ (":cancer:" ["♋"])
+ (":leo:" ["♌"])
+ (":virgo:" ["♍"])
+ (":libra:" ["♎"])
+ (":scorpius:" ["♏"])
+ (":sagittarius:" ["♐"])
+ (":capricorn:" ["♑"])
+ (":aquarius:" ["♒"])
+ (":pisces:" ["♓"])
+ (":chess_pawn:" ["♟️"])
+ (":spades:" ["♠️"])
+ (":clubs:" ["♣️"])
+ (":hearts:" ["♥️"])
+ (":diamonds:" ["♦️"])
+ (":hotsprings:" ["♨️"])
+ (":recycle:" ["♻️"])
+ (":infinity:" ["♾️"])
+ (":wheelchair:" ["♿"])
+ (":hammer_and_pick:" ["⚒️"])
+ (":anchor:" ["⚓"])
+ (":crossed_swords:" ["⚔️"])
+ (":medical_symbol:" ["⚕️"])
+ (":staff_of_aesculapius:" ["⚕️"])
+ (":scales:" ["⚖️"])
+ (":alembic:" ["⚗️"])
+ (":gear:" ["⚙️"])
+ (":atom_symbol:" ["⚛️"])
+ (":fleur_de_lis:" ["⚜️"])
+ (":warning:" ["⚠️"])
+ (":zap:" ["⚡"])
+ (":transgender_symbol:" ["⚧️"])
+ (":white_circle:" ["⚪"])
+ (":black_circle:" ["⚫"])
+ (":coffin:" ["⚰️"])
+ (":funeral_urn:" ["⚱️"])
+ (":soccer:" ["⚽"])
+ (":baseball:" ["⚾"])
+ (":snowman_without_snow:" ["⛄"])
+ (":partly_sunny:" ["⛅"])
+ (":thunder_cloud_and_rain:" ["⛈️"])
+ (":ophiuchus:" ["⛎"])
+ (":pick:" ["⛏️"])
+ (":helmet_with_white_cross:" ["⛑️"])
+ (":chains:" ["⛓️"])
+ (":no_entry:" ["⛔"])
+ (":shinto_shrine:" ["⛩️"])
+ (":church:" ["⛪"])
+ (":mountain:" ["⛰️"])
+ (":umbrella_on_ground:" ["⛱️"])
+ (":fountain:" ["⛲"])
+ (":golf:" ["⛳"])
+ (":ferry:" ["⛴️"])
+ (":boat:" ["⛵"])
+ (":sailboat:" ["⛵"])
+ (":skier:" ["⛷️"])
+ (":ice_skate:" ["⛸️"])
+ (":woman-bouncing-ball:" ["⛹️‍♀️"])
+ (":man-bouncing-ball:" ["⛹️‍♂️"])
+ (":person_with_ball:" ["⛹️"])
+ (":tent:" ["⛺"])
+ (":fuelpump:" ["⛽"])
+ (":scissors:" ["✂️"])
+ (":white_check_mark:" ["✅"])
+ (":airplane:" ["✈️"])
+ (":email:" ["✉️"])
+ (":envelope:" ["✉️"])
+ (":fist:" ["✊"])
+ (":hand:" ["✋"])
+ (":raised_hand:" ["✋"])
+ (":v:" ["✌️"])
+ (":writing_hand:" ["✍️"])
+ (":pencil2:" ["✏️"])
+ (":black_nib:" ["✒️"])
+ (":heavy_check_mark:" ["✔️"])
+ (":heavy_multiplication_x:" ["✖️"])
+ (":latin_cross:" ["✝️"])
+ (":star_of_david:" ["✡️"])
+ (":sparkles:" ["✨"])
+ (":eight_spoked_asterisk:" ["✳️"])
+ (":eight_pointed_black_star:" ["✴️"])
+ (":snowflake:" ["❄️"])
+ (":sparkle:" ["❇️"])
+ (":x:" ["❌"])
+ (":negative_squared_cross_mark:" ["❎"])
+ (":question:" ["❓"])
+ (":grey_question:" ["❔"])
+ (":grey_exclamation:" ["❕"])
+ (":exclamation:" ["❗"])
+ (":heavy_exclamation_mark:" ["❗"])
+ (":heavy_heart_exclamation_mark_ornament:" ["❣️"])
+ (":heart_on_fire:" ["❤️‍🔥"])
+ (":mending_heart:" ["❤️‍🩹"])
+ (":heart:" ["❤️"])
+ ("<3" ["❤️"])
+ (":heavy_plus_sign:" ["➕"])
+ (":heavy_minus_sign:" ["➖"])
+ (":heavy_division_sign:" ["➗"])
+ (":arrow_right:" ["➡️"])
+ (":curly_loop:" ["➰"])
+ (":loop:" ["➿"])
+ (":arrow_heading_up:" ["⤴️"])
+ (":arrow_heading_down:" ["⤵️"])
+ (":arrow_left:" ["⬅️"])
+ (":arrow_up:" ["⬆️"])
+ (":arrow_down:" ["⬇️"])
+ (":black_large_square:" ["⬛"])
+ (":white_large_square:" ["⬜"])
+ (":star:" ["⭐"])
+ (":o:" ["⭕"])
+ (":wavy_dash:" ["〰️"])
+ (":part_alternation_mark:" ["〽️"])
+ (":congratulations:" ["㊗️"])
+ (":secret:" ["㊙️"])))))))
+
+(emoji--define-rules)
+
+(provide 'emoji)
+;;; emoji.el ends here
diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el
index 23204c0cd3e..04e95b0737b 100644
--- a/lisp/leim/quail/indian.el
+++ b/lisp/leim/quail/indian.el
@@ -171,7 +171,7 @@
clm)
(with-temp-buffer
(insert "\n")
- (insert " +")
+ (insert "----+")
(insert-char ?- 74)
(insert "\n |")
(setq clm 6)
@@ -244,19 +244,27 @@
(insert "\n")
(buffer-string))))
-(defvar quail-tamil-itrans-various-signs-and-digits-table
+(defun quail-tamil-itrans-compute-signs-table (digitp)
+ "Compute the signs table for the tamil-itrans input method.
+If DIGITP is non-nil, include the digits translation as well."
(let ((various '((?ஃ . "H") ("ஸ்ரீ" . "srii") (?ௐ)))
(digits "௦௧௨௩௪௫௬௭௮௯")
(width 6) clm)
(with-temp-buffer
- (insert "\n" (make-string 18 ?-) "+" (make-string 60 ?-) "\n")
+ (insert "\n" (make-string 18 ?-) "+")
+ (when digitp (insert (make-string 60 ?-)))
+ (insert "\n")
(insert
(propertize "\t" 'display '(space :align-to 5)) "various"
- (propertize "\t" 'display '(space :align-to 18)) "|"
- (propertize "\t" 'display '(space :align-to 45)) "digits")
-
- (insert "\n" (make-string 18 ?-) "+" (make-string 60 ?-) "\n")
- (setq clm 0 )
+ (propertize "\t" 'display '(space :align-to 18)) "|")
+ (when digitp
+ (insert
+ (propertize "\t" 'display '(space :align-to 45)) "digits"))
+ (insert "\n" (make-string 18 ?-) "+")
+ (when digitp
+ (insert (make-string 60 ?-)))
+ (insert "\n")
+ (setq clm 0)
(dotimes (i (length various))
(insert (propertize "\t" 'display (list 'space :align-to clm))
@@ -264,10 +272,11 @@
(setq clm (+ clm width)))
(insert (propertize "\t" 'display '(space :align-to 18)) "|")
(setq clm 20)
- (dotimes (i 10)
- (insert (propertize "\t" 'display (list 'space :align-to clm))
- (aref digits i))
- (setq clm (+ clm width)))
+ (when digitp
+ (dotimes (i 10)
+ (insert (propertize "\t" 'display (list 'space :align-to clm))
+ (aref digits i))
+ (setq clm (+ clm width))))
(insert "\n")
(setq clm 0)
(dotimes (i (length various))
@@ -276,13 +285,22 @@
(setq clm (+ clm width)))
(insert (propertize "\t" 'display '(space :align-to 18)) "|")
(setq clm 20)
- (dotimes (i 10)
- (insert (propertize "\t" 'display (list 'space :align-to clm))
- (format "%d" i))
- (setq clm (+ clm width)))
- (insert "\n" (make-string 18 ?-) "+" (make-string 60 ?-) "\n")
+ (when digitp
+ (dotimes (i 10)
+ (insert (propertize "\t" 'display (list 'space :align-to clm))
+ (format "%d" i))
+ (setq clm (+ clm width))))
+ (insert "\n" (make-string 18 ?-) "+")
+ (when digitp
+ (insert (make-string 60 ?-) "\n"))
(buffer-string))))
+(defvar quail-tamil-itrans-various-signs-and-digits-table
+ (quail-tamil-itrans-compute-signs-table t))
+
+(defvar quail-tamil-itrans-various-signs-table
+ (quail-tamil-itrans-compute-signs-table nil))
+
(if nil
(quail-define-package "tamil-itrans" "Tamil" "TmlIT" t "Tamil ITRANS"))
(quail-define-indian-trans-package
@@ -293,16 +311,39 @@ You can input characters using the following mapping tables.
Example: To enter வணக்கம், type vaNakkam.
### Basic syllables (consonants + vowels) ###
-\\<quail-tamil-itrans-syllable-table>
+\\=\\<quail-tamil-itrans-syllable-table>
+
+### Miscellaneous (various signs) ###
+\\=\\<quail-tamil-itrans-various-signs-table>
+
+### Others (numerics + symbols) ###
+
+Characters below have no ITRANS method associated with them.
+Their descriptions are included for easy reference.
+\\=\\<quail-tamil-itrans-numerics-and-symbols-table>
+
+Full key sequences are listed below:")
+
+(if nil
+ (quail-define-package "tamil-itrans-digits" "Tamil" "TmlITD" t "Tamil ITRANS with digits"))
+(quail-define-indian-trans-package
+ indian-tml-itrans-digits-v5-hash "tamil-itrans-digits" "Tamil" "TmlITD"
+ "Tamil transliteration by ITRANS method with Tamil digits support.
+
+You can input characters using the following mapping tables.
+ Example: To enter வணக்கம், type vaNakkam.
+
+### Basic syllables (consonants + vowels) ###
+\\=\\<quail-tamil-itrans-syllable-table>
### Miscellaneous (various signs + digits) ###
-\\<quail-tamil-itrans-various-signs-and-digits-table>
+\\=\\<quail-tamil-itrans-various-signs-and-digits-table>
### Others (numerics + symbols) ###
Characters below have no ITRANS method associated with them.
Their descriptions are included for easy reference.
-\\<quail-tamil-itrans-numerics-and-symbols-table>
+\\=\\<quail-tamil-itrans-numerics-and-symbols-table>
Full key sequences are listed below:")
@@ -479,6 +520,13 @@ Full key sequences are listed below:")
"tamil-inscript" "Tamil" "TmlIS"
"Tamil keyboard Inscript.")
+(if nil
+ (quail-define-package "tamil-inscript-digits" "Tamil" "TmlISD" t "Tamil keyboard Inscript with digits."))
+(quail-define-inscript-package
+ indian-tml-base-digits-table inscript-tml-keytable
+ "tamil-inscript-digits" "Tamil" "TmlISD"
+ "Tamil keyboard Inscript with Tamil digits support.")
+
;; Probhat Input Method
(quail-define-package
"bengali-probhat" "Bengali" "BngPB" t
@@ -633,7 +681,7 @@ Full key sequences are listed below:")
(quail-define-package "malayalam-mozhi" "Malayalam" "MlmMI" t
"Malayalam transliteration by Mozhi method."
nil nil t nil nil nil t nil
- #'indian-mlm-mozhi-update-translation)
+ #'indian-mlm-mozhi-update-translation nil t)
(maphash
(lambda (key val)
@@ -648,4 +696,1271 @@ Full key sequences are listed below:")
(quail-defrule "|" ?‌)
(quail-defrule "||" ?​)
+(quail-define-package
+ "brahmi" "Brahmi" "𑀲" t "Brahmi phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("``" ?₹)
+ ("1" ?𑁧)
+ ("`1" ?1)
+ ("`!" ?𑁒)
+ ("2" ?𑁨)
+ ("`2" ?2)
+ ("`@" ?𑁓)
+ ("3" ?𑁩)
+ ("`3" ?3)
+ ("`#" ?𑁔)
+ ("4" ?𑁪)
+ ("`4" ?4)
+ ("`$" ?𑁕)
+ ("5" ?𑁫)
+ ("`5" ?5)
+ ("`%" ?𑁖)
+ ("6" ?𑁬)
+ ("`6" ?6)
+ ("`^" ?𑁗)
+ ("7" ?𑁭)
+ ("`7" ?7)
+ ("`&" ?𑁘)
+ ("8" ?𑁮)
+ ("`8" ?8)
+ ("`*" ?𑁙)
+ ("9" ?𑁯)
+ ("`9" ?9)
+ ("`(" ?𑁚)
+ ("0" ?𑁦)
+ ("`0" ?0)
+ ("`)" ?𑁛)
+ ("`-" ?𑁜)
+ ("`_" ?𑁝)
+ ("`=" ?𑁞)
+ ("`+" ?𑁟)
+ ("`\\" ?𑁇)
+ ("`|" ?𑁈)
+ ("`" ?𑀝)
+ ("q" ?𑀝)
+ ("Q" ?𑀞)
+ ("`q" ?𑀃)
+ ("`Q" ?𑁠)
+ ("w" ?𑀟)
+ ("W" ?𑀠)
+ ("`w" ?𑀄)
+ ("`W" ?𑁡)
+ ("e" ?𑁂)
+ ("E" ?𑁃)
+ ("`e" ?𑀏)
+ ("`E" ?𑀐)
+ ("r" ?𑀭)
+ ("R" ?𑀾)
+ ("`r" ?𑀋)
+ ("`R" ?𑀶)
+ ("t" ?𑀢)
+ ("T" ?𑀣)
+ ("`t" ?𑁢)
+ ("y" ?𑀬)
+ ("Y" ?𑁣)
+ ("`y" ?𑁤)
+ ("`Y" ?𑁥)
+ ("u" ?𑀼)
+ ("U" ?𑀽)
+ ("`u" ?𑀉)
+ ("`U" ?𑀊)
+ ("i" ?𑀺)
+ ("I" ?𑀻)
+ ("`i" ?𑀇)
+ ("`I" ?𑀈)
+ ("o" ?𑁄)
+ ("O" ?𑁅)
+ ("`o" ?𑀑)
+ ("`O" ?𑀒)
+ ("p" ?𑀧)
+ ("P" ?𑀨)
+ ("`p" ?𑁳)
+ ("`P" ?𑁱)
+ ("`[" ?𑁴)
+ ("`{" ?𑁲)
+ ("a" ?𑀸)
+ ("A" ?𑀆)
+ ("`a" ?𑀅)
+ ("`A" ?𑀹)
+ ("s" ?𑀲)
+ ("S" ?𑀰)
+ ("`s" ?𑀱)
+ ("d" ?𑀤)
+ ("D" ?𑀥)
+ ("`d" ?𑀶)
+ ("f" ?𑁆)
+ ("F" ?𑀿)
+ ("`f" ?𑀌)
+ ("`F" ?𑁰)
+ ("g" ?𑀕)
+ ("G" ?𑀖)
+ ("h" ?𑀳)
+ ("H" ?𑀂)
+ ("j" ?𑀚)
+ ("J" ?𑀛)
+ ("k" ?𑀓)
+ ("K" ?𑀔)
+ ("l" ?𑀮)
+ ("L" ?𑀴)
+ ("`l" ?𑀵)
+ ("`L" ?𑁵)
+ ("z" ?𑁀)
+ ("Z" ?𑀍)
+ ("`z" ?𑁁)
+ ("`Z" ?𑀎)
+ ("x" ?𑁉)
+ ("X" ?𑁊)
+ ("`x" ?𑁋)
+ ("`X" ?𑁌)
+ ("c" ?𑀘)
+ ("C" ?𑀙)
+ ("`c" #x200C) ; ZWNJ
+ ("`C" #x200D) ; ZWJ
+ ("v" ?𑀯)
+ ("V" ?𑀷)
+ ("b" ?𑀩)
+ ("B" ?𑀪)
+ ("n" ?𑀦)
+ ("N" ?𑀡)
+ ("`n" ?𑀗)
+ ("`N" ?𑀜)
+ ("m" ?𑀫)
+ ("M" ?𑀁)
+ ("`m" ?𑀀)
+ ("<" ?𑁍)
+ ("`/" ?𑁿)
+ )
+
+(quail-define-package
+ "kaithi" "Kaithi" "𑂍𑂶" t "Kaithi phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?१)
+("`1" ?1)
+("2" ?२)
+("`2" ?2)
+("3" ?३)
+("`3" ?3)
+("4" ?४)
+("`4" ?4)
+("5" ?५)
+("`5" ?5)
+("6" ?६)
+("`6" ?6)
+("7" ?७)
+("`7" ?7)
+("8" ?८)
+("`8" ?8)
+("9" ?९)
+("`9" ?9)
+("0" ?०)
+("`0" ?0)
+("`)" ?𑂻)
+("`\\" ?𑃀)
+("`|" ?𑃁)
+("`" ?𑂗)
+("q" ?𑂗)
+("Q" ?𑂘)
+("w" ?𑂙)
+("W" ?𑂛)
+("`w" ?𑂚)
+("`W" ?𑂜)
+("e" ?𑂵)
+("E" ?𑂶)
+("`e" ?𑂉)
+("`E" ?𑂊)
+("r" ?𑂩)
+("R" ?𑃂)
+("t" ?𑂞)
+("T" ?𑂟)
+("y" ?𑂨)
+("Y" ?⸱)
+("u" ?𑂳)
+("U" ?𑂴)
+("`u" ?𑂇)
+("`U" ?𑂈)
+("i" ?𑂱)
+("I" ?𑂲)
+("`i" ?𑂅)
+("`I" ?𑂆)
+("o" ?𑂷)
+("O" ?𑂸)
+("`o" ?𑂋)
+("`O" ?𑂌)
+("p" ?𑂣)
+("P" ?𑂤)
+("a" ?𑂰)
+("A" ?𑂄)
+("`a" ?𑂃)
+("s" ?𑂮)
+("S" ?𑂬)
+("d" ?𑂠)
+("D" ?𑂡)
+("`d" ?𑂼)
+("`D" #x110BD) ; Kaithi Number Sign
+("f" ?𑂹)
+("F" #x110CD) ; Kaithi Number Sign Above
+("`f" ?𑂾)
+("`F" ?𑂿)
+("g" ?𑂏)
+("G" ?𑂐)
+("h" ?𑂯)
+("H" ?𑂂)
+("j" ?𑂔)
+("J" ?𑂕)
+("k" ?𑂍)
+("K" ?𑂎)
+("l" ?𑂪)
+("z" ?𑂖)
+("Z" ?𑂑)
+("x" ?𑂭)
+("X" ?𑂺)
+("c" ?𑂒)
+("C" ?𑂓)
+("`c" #x200C) ; ZWNJ
+("`C" #x200D) ; ZWJ
+("v" ?𑂫)
+("b" ?𑂥)
+("B" ?𑂦)
+("n" ?𑂢)
+("N" ?𑂝)
+("m" ?𑂧)
+("M" ?𑂁)
+("`m" ?𑂀)
+)
+
+(quail-define-package
+ "tirhuta" "Tirhuta" "𑒞𑒱" t "Tirhuta phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?𑓑)
+("`1" ?1)
+("2" ?𑓒)
+("`2" ?2)
+("3" ?𑓓)
+("`3" ?3)
+("4" ?𑓔)
+("`4" ?4)
+("5" ?𑓕)
+("`5" ?5)
+("6" ?𑓖)
+("`6" ?6)
+("7" ?𑓗)
+("`7" ?7)
+("8" ?𑓘)
+("`8" ?8)
+("9" ?𑓙)
+("`9" ?9)
+("0" ?𑓐)
+("`0" ?0)
+("`)" ?𑓆)
+("`\\" ?।)
+("`|" ?॥)
+("`" ?𑒙)
+("q" ?𑒙)
+("Q" ?𑒚)
+("w" ?𑒛)
+("W" ?𑒜)
+("e" ?𑒺)
+("E" ?𑒹)
+("`e" ?𑒋)
+("r" ?𑒩)
+("R" ?𑒵)
+("`r" ?𑒇)
+("t" ?𑒞)
+("T" ?𑒟)
+("y" ?𑒨)
+("Y" ?𑒻)
+("`y" ?𑒌)
+("u" ?𑒳)
+("U" ?𑒴)
+("`u" ?𑒅)
+("`U" ?𑒆)
+("i" ?𑒱)
+("I" ?𑒲)
+("`i" ?𑒃)
+("`I" ?𑒄)
+("o" ?𑒽)
+("O" ?𑒼)
+("`o" ?𑒍)
+("p" ?𑒣)
+("P" ?𑒤)
+("a" ?𑒰)
+("A" ?𑒂)
+("`a" ?𑒁)
+("s" ?𑒮)
+("S" ?𑒬)
+("d" ?𑒠)
+("D" ?𑒡)
+("f" ?𑓂)
+("F" ?𑒶)
+("`f" ?𑒈)
+("g" ?𑒑)
+("G" ?𑒒)
+("h" ?𑒯)
+("H" ?𑓁)
+("j" ?𑒖)
+("J" ?𑒗)
+("k" ?𑒏)
+("K" ?𑒐)
+("l" ?𑒪)
+("L" ?𑒷)
+("`l" ?𑒉)
+("z" ?𑒘)
+("Z" ?𑒓)
+("`z" ?𑒸)
+("`Z" ?𑒊)
+("x" ?𑒭)
+("X" ?𑓃)
+("c" ?𑒔)
+("C" ?𑒕)
+("`c" #x200C) ; ZWNJ
+("v" ?𑒫)
+("V" ?𑒾)
+("`v" ?𑒎)
+("b" ?𑒥)
+("B" ?𑒦)
+("`b" ?𑒀)
+("`B" ?𑓄)
+("n" ?𑒢)
+("N" ?𑒝)
+("`n" ?𑓇)
+("`N" ?𑓅)
+("m" ?𑒧)
+("M" ?𑓀)
+("`m" ?𑒿)
+)
+
+(quail-define-package
+ "sharada" "Sharada" "𑆯𑆳" t "Sharada phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?𑇑)
+("`1" ?1)
+("2" ?𑇒)
+("`2" ?2)
+("3" ?𑇓)
+("`3" ?3)
+("4" ?𑇔)
+("`4" ?4)
+("5" ?𑇕)
+("`5" ?5)
+("6" ?𑇖)
+("`6" ?6)
+("7" ?𑇗)
+("`7" ?7)
+("8" ?𑇘)
+("`8" ?8)
+("9" ?𑇙)
+("`9" ?9)
+("0" ?𑇐)
+("`0" ?0)
+("`)" ?𑇇)
+("`\\" ?𑇅)
+("`|" ?𑇆)
+("`" ?𑆛)
+("q" ?𑆛)
+("Q" ?𑆜)
+("`q" ?𑇈)
+("`Q" ?𑇉)
+("w" ?𑆝)
+("W" ?𑆞)
+("`w" ?𑇋)
+("`W" ?𑇍)
+("e" ?𑆼)
+("E" ?𑆽)
+("`e" ?𑆍)
+("`E" ?𑆎)
+("r" ?𑆫)
+("R" ?𑆸)
+("`r" ?𑆉)
+("`R" ?𑇎)
+("t" ?𑆠)
+("T" ?𑆡)
+("y" ?𑆪)
+("u" ?𑆶)
+("U" ?𑆷)
+("`u" ?𑆇)
+("`U" ?𑆈)
+("i" ?𑆴)
+("I" ?𑆵)
+("`i" ?𑆅)
+("`I" ?𑆆)
+("o" ?𑆾)
+("O" ?𑆿)
+("`o" ?𑆏)
+("`O" ?𑆐)
+("p" ?𑆥)
+("P" ?𑆦)
+("`p" ?𑇃)
+("a" ?𑆳)
+("A" ?𑆄)
+("`a" ?𑆃)
+("s" ?𑆱)
+("S" ?𑆯)
+("d" ?𑆢)
+("D" ?𑆣)
+("`d" ?𑇚)
+("`D" ?𑇛)
+("f" ?𑇀)
+("F" ?𑆹)
+("`f" ?𑆊)
+("`F" ?𑇌)
+("g" ?𑆓)
+("G" ?𑆔)
+("`g" ?𑇜)
+("`G" ?𑇝)
+("h" ?𑆲)
+("H" ?𑆂)
+("`h" ?𑇞)
+("`H" ?𑇟)
+("j" ?𑆘)
+("J" ?𑆙)
+("`j" ?᳘)
+("`J" ?᳕)
+("k" ?𑆑)
+("K" ?𑆒)
+("`k" ?𑇂)
+("l" ?𑆬)
+("L" ?𑆭)
+("`l" ?𑆺)
+("`L" ?𑆋)
+("z" ?𑆚)
+("Z" ?𑆕)
+("`z" ?𑆻)
+("`Z" ?𑆌)
+("x" ?𑆰)
+("X" ?𑇊)
+("c" ?𑆖)
+("C" ?𑆗)
+("`c" #x200C) ; ZWNJ
+("v" ?𑆮)
+("b" ?𑆧)
+("B" ?𑆨)
+("n" ?𑆤)
+("N" ?𑆟)
+("`n" ?𑇄)
+("`N" ?𑇁)
+("m" ?𑆩)
+("M" ?𑆁)
+("`m" ?𑆀)
+("`M" ?𑇏)
+)
+
+(quail-define-package
+ "siddham" "Sharada" "𑖭𑖰" t "Siddham phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("`1" ?𑗊)
+("`!" ?𑗔)
+("`2" ?𑗋)
+("`@" ?𑗕)
+("`3" ?𑗌)
+("`#" ?𑗖)
+("`4" ?𑗍)
+("`$" ?𑗗)
+("`5" ?𑗎)
+("`%" ?𑗅)
+("`6" ?𑗏)
+("`^" ?𑗆)
+("`7" ?𑗐)
+("`&" ?𑗇)
+("`8" ?𑗑)
+("`*" ?𑗈)
+("`9" ?𑗒)
+("`(" ?𑗉)
+("`0" ?𑗓)
+("`)" ?𑗄)
+("`\\" ?𑗂)
+("`|" ?𑗃)
+("`" ?𑖘)
+("q" ?𑖘)
+("Q" ?𑖙)
+("`q" ?𑗘)
+("`Q" ?𑗙)
+("w" ?𑖚)
+("W" ?𑖛)
+("`w" ?𑗚)
+("`W" ?𑗛)
+("e" ?𑖸)
+("E" ?𑖹)
+("`e" ?𑖊)
+("`E" ?𑖋)
+("r" ?𑖨)
+("R" ?𑖴)
+("`r" ?𑖆)
+("t" ?𑖝)
+("T" ?𑖞)
+("`t" ?𑗜)
+("`T" ?𑗝)
+("y" ?𑖧)
+("u" ?𑖲)
+("U" ?𑖳)
+("`u" ?𑖄)
+("`U" ?𑖅)
+("i" ?𑖰)
+("I" ?𑖱)
+("`i" ?𑖂)
+("`I" ?𑖃)
+("o" ?𑖺)
+("O" ?𑖻)
+("`o" ?𑖌)
+("`O" ?𑖍)
+("p" ?𑖢)
+("P" ?𑖣)
+("a" ?𑖯)
+("A" ?𑖁)
+("`a" ?𑖀)
+("s" ?𑖭)
+("S" ?𑖫)
+("d" ?𑖟)
+("D" ?𑖠)
+("`d" ?𑗁)
+("f" ?𑖿)
+("F" ?𑖵)
+("`f" ?𑖇)
+("g" ?𑖐)
+("G" ?𑖑)
+("h" ?𑖮)
+("H" ?𑖾)
+("j" ?𑖕)
+("J" ?𑖖)
+("k" ?𑖎)
+("K" ?𑖏)
+("l" ?𑖩)
+("L" ?𑖈)
+("`l" ?𑖉)
+("z" ?𑖗)
+("Z" ?𑖒)
+("x" ?𑖬)
+("X" ?𑗀)
+("c" ?𑖓)
+("C" ?𑖔)
+("`c" #x200C) ; ZWNJ
+("v" ?𑖪)
+("b" ?𑖤)
+("B" ?𑖥)
+("n" ?𑖡)
+("N" ?𑖜)
+("m" ?𑖦)
+("M" ?𑖽)
+("`m" ?𑖼)
+)
+
+
+(quail-define-package
+ "syloti-nagri" "Syloti Nagri" "ꠍꠤ" t "Syloti Nagri phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("`~" ?৳)
+("1" ?১)
+("`1" ?1)
+("2" ?২)
+("`2" ?2)
+("3" ?৩)
+("`3" ?3)
+("4" ?৪)
+("`4" ?4)
+("5" ?৫)
+("`5" ?5)
+("6" ?৬)
+("`6" ?6)
+("7" ?৭)
+("`7" ?7)
+("8" ?৮)
+("`8" ?8)
+("9" ?৯)
+("`9" ?9)
+("0" ?০)
+("`0" ?0)
+("`\\" ?𑇅)
+("`|" ?𑇆)
+("`" ?ꠐ)
+("q" ?ꠐ)
+("Q" ?ꠑ)
+("`q" ?꠨)
+("`Q" ?꠩)
+("w" ?ꠒ)
+("W" ?ꠓ)
+("`w" ?꠪)
+("`W" ?꠫)
+("e" ?ꠦ)
+("E" ?ꠄ)
+("r" ?ꠞ)
+("R" ?ꠠ)
+("t" ?ꠔ)
+("T" ?ꠕ)
+("y" ?ꠂ)
+("u" ?ꠥ)
+("U" ?ꠃ)
+("i" ?ꠤ)
+("I" ?ꠁ)
+("o" ?ꠧ)
+("O" ?ꠅ)
+("p" ?ꠙ)
+("P" ?ꠚ)
+("a" ?ꠣ)
+("A" ?ꠀ)
+("s" ?ꠡ)
+("d" ?ꠖ)
+("D" ?ꠗ)
+("f" ?꠆)
+("F" ?꠬)
+("g" ?ꠉ)
+("G" ?ꠊ)
+("h" ?ꠢ)
+("j" ?ꠎ)
+("J" ?ꠏ)
+("k" ?ꠇ)
+("K" ?ꠈ)
+("l" ?ꠟ)
+("c" ?ꠌ)
+("C" ?ꠍ)
+("`c" #x200C) ; ZWNJ
+("b" ?ꠛ)
+("B" ?ꠜ)
+("n" ?ꠘ)
+("m" ?ꠝ)
+("M" ?ꠋ)
+)
+
+(quail-define-package
+ "modi" "Modi" "𑘦𑘻" t "Modi phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?𑙑)
+("`1" ?1)
+("2" ?𑙒)
+("`2" ?2)
+("3" ?𑙓)
+("`3" ?3)
+("4" ?𑙔)
+("`4" ?4)
+("5" ?𑙕)
+("`5" ?5)
+("6" ?𑙖)
+("`6" ?6)
+("7" ?𑙗)
+("`7" ?7)
+("8" ?𑙘)
+("`8" ?8)
+("9" ?𑙙)
+("`9" ?9)
+("0" ?𑙐)
+("`0" ?0)
+("`)" ?𑙃)
+("`\\" ?𑙁)
+("`|" ?𑙂)
+("`" ?𑘘)
+("q" ?𑘘)
+("Q" ?𑘙)
+("`q" ?𑙄)
+("w" ?𑘚)
+("W" ?𑘛)
+("e" ?𑘹)
+("E" ?𑘺)
+("`e" ?𑘊)
+("`E" ?𑘋)
+("r" ?𑘨)
+("R" ?𑘵)
+("`r" ?𑘆)
+("t" ?𑘝)
+("T" ?𑘞)
+("y" ?𑘧)
+("u" ?𑘳)
+("U" ?𑘴)
+("`u" ?𑘄)
+("`U" ?𑘅)
+("i" ?𑘱)
+("I" ?𑘲)
+("`i" ?𑘂)
+("`I" ?𑘃)
+("o" ?𑘻)
+("O" ?𑘼)
+("`o" ?𑘌)
+("`O" ?𑘍)
+("p" ?𑘢)
+("P" ?𑘣)
+("a" ?𑘰)
+("A" ?𑘁)
+("`a" ?𑘀)
+("s" ?𑘭)
+("S" ?𑘫)
+("d" ?𑘟)
+("D" ?𑘠)
+("f" ?𑘿)
+("F" ?𑘶)
+("`f" ?𑘇)
+("g" ?𑘐)
+("G" ?𑘑)
+("h" ?𑘮)
+("H" ?𑘾)
+("j" ?𑘕)
+("J" ?𑘖)
+("k" ?𑘎)
+("K" ?𑘏)
+("l" ?𑘩)
+("L" ?𑘯)
+("`l" ?𑘷)
+("`L" ?𑘈)
+("z" ?𑘗)
+("Z" ?𑘒)
+("`z" ?𑘸)
+("`Z" ?𑘉)
+("x" ?𑘬)
+("X" ?𑙀)
+("c" ?𑘓)
+("C" ?𑘔)
+("`c" #x200C) ; ZWNJ
+("v" ?𑘪)
+("b" ?𑘤)
+("B" ?𑘥)
+("n" ?𑘡)
+("N" ?𑘜)
+("m" ?𑘦)
+("M" ?𑘽)
+)
+
+(quail-define-package
+ "odia" "Odia" "ଓ" t "Odia phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?୧)
+("`1" ?1)
+("`!" ?୲)
+("2" ?୨)
+("`2" ?2)
+("`@" ?୳)
+("3" ?୩)
+("`3" ?3)
+("`#" ?୴)
+("4" ?୪)
+("`4" ?4)
+("`$" ?୵)
+("5" ?୫)
+("`5" ?5)
+("`%" ?୶)
+("6" ?୬)
+("`6" ?6)
+("`^" ?୷)
+("7" ?୭)
+("`7" ?7)
+("8" ?୮)
+("`8" ?8)
+("9" ?୯)
+("`9" ?9)
+("0" ?୦)
+("`0" ?0)
+("`\\" ?।)
+("`|" ?॥)
+("`" ?ଟ)
+("q" ?ଟ)
+("Q" ?ଠ)
+("`q" ?୰)
+("`Q" ?୕)
+("w" ?ଡ)
+("W" ?ଢ)
+("`w" ?ଡ଼)
+("`W" ?ଢ଼)
+("e" ?େ)
+("E" ?ୈ)
+("`e" ?ଏ)
+("`E" ?ଐ)
+("r" ?ର)
+("R" ?ୃ)
+("`r" ?ଋ)
+("t" ?ତ)
+("T" ?ଥ)
+("`t" ?ୖ)
+("`T" ?ୗ)
+("y" ?ଯ)
+("Y" ?ୟ)
+("u" ?ୁ)
+("U" ?ୂ)
+("`u" ?ଉ)
+("`U" ?ଊ)
+("i" ?ି)
+("I" ?ୀ)
+("`i" ?ଇ)
+("`I" ?ଈ)
+("o" ?ୋ)
+("O" ?ୌ)
+("`o" ?ଓ)
+("`O" ?ଔ)
+("p" ?ପ)
+("P" ?ଫ)
+("a" ?ା)
+("A" ?ଆ)
+("`a" ?ଅ)
+("s" ?ସ)
+("S" ?ଶ)
+("d" ?ଦ)
+("D" ?ଧ)
+("f" ?୍)
+("F" ?ୄ)
+("`f" ?ୠ)
+("g" ?ଗ)
+("G" ?ଘ)
+("h" ?ହ)
+("H" ?ଃ)
+("j" ?ଜ)
+("J" ?ଝ)
+("k" ?କ)
+("K" ?ଖ)
+("l" ?ଲ)
+("L" ?ଳ)
+("`l" ?ୢ)
+("`L" ?ଌ)
+("z" ?ଞ)
+("Z" ?ଙ)
+("`z" ?ୣ)
+("`Z" ?ୡ)
+("x" ?ଷ)
+("X" ?଼)
+("c" ?ଚ)
+("C" ?ଛ)
+("`c" #x200C) ; ZWNJ
+("`C" #x200D) ; ZWJ
+("v" ?ଵ)
+("V" ?ୱ)
+("b" ?ବ)
+("B" ?ଭ)
+("n" ?ନ)
+("N" ?ଣ)
+("m" ?ମ)
+("M" ?ଂ)
+("`m" ?ଁ)
+("`M" ?ଽ)
+)
+
+(quail-define-package
+ "limbu" "Limbu" "ᤕ" t "Limbu phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+("``" ?₹)
+("1" ?᥇)
+("`1" ?1)
+("`!" ?᥄)
+("2" ?᥈)
+("`2" ?2)
+("3" ?᥉)
+("`3" ?3)
+("4" ?᥊)
+("`4" ?4)
+("5" ?᥋)
+("`5" ?5)
+("6" ?᥌)
+("`6" ?6)
+("7" ?᥍)
+("`7" ?7)
+("8" ?᥎)
+("`8" ?8)
+("9" ?᥏)
+("`9" ?9)
+("0" ?᥆)
+("`0" ?0)
+("`\\" ?।)
+("`|" ?॥)
+("`" ?ᤘ)
+("q" ?ᤧ)
+("Q" ?ᤨ)
+("`q" ?᥀)
+("w" ?ᤘ)
+("W" ?ᤫ)
+("e" ?ᤣ)
+("E" ?ᤤ)
+("r" ?ᤖ)
+("R" ?ᤷ)
+("`r" ?ᤪ)
+("t" ?ᤋ)
+("T" ?ᤌ)
+("`t" ?ᤳ)
+("`T" ?ᤞ)
+("y" ?ᤕ)
+("Y" ?ᤩ)
+("u" ?ᤢ)
+("i" ?ᤡ)
+("o" ?ᤥ)
+("O" ?ᤦ)
+("p" ?ᤐ)
+("P" ?ᤑ)
+("`p" ?ᤵ)
+("a" ?ᤠ)
+("A" ?ᤀ)
+("s" ?ᤛ)
+("S" ?ᤙ)
+("d" ?ᤍ)
+("D" ?ᤎ)
+("f" ?᤻)
+("g" ?ᤃ)
+("G" ?ᤄ)
+("`g" ?ᤝ)
+("h" ?ᤜ)
+("j" ?ᤈ)
+("J" ?ᤉ)
+("k" ?ᤁ)
+("K" ?ᤂ)
+("`k" ?ᤰ)
+("l" ?ᤗ)
+("L" ?ᤸ)
+("z" ?ᤊ)
+("Z" ?ᤅ)
+("x" ?ᤚ)
+("X" ?᤹)
+("c" ?ᤆ)
+("C" ?ᤇ)
+("`c" #x200C) ; ZWNJ
+("v" ?᤺)
+("b" ?ᤒ)
+("B" ?ᤓ)
+("n" ?ᤏ)
+("N" ?ᤴ)
+("m" ?ᤔ)
+("M" ?ᤱ)
+("`m" ?ᤲ)
+("`?" ?᥅)
+)
+
+(quail-define-package
+ "grantha" "Grantha" "𑌗𑍍𑌰" t "Grantha phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("``" ?₹)
+ ("1" ?௧)
+ ("`1" ?1)
+ ("`!" ?𑍧)
+ ("2" ?௨)
+ ("`2" ?2)
+ ("`@" ?𑍨)
+ ("3" ?௩)
+ ("`3" ?3)
+ ("`#" ?𑍩)
+ ("4" ?௪)
+ ("`4" ?4)
+ ("`$" ?𑍪)
+ ("5" ?௫)
+ ("`5" ?5)
+ ("`%" ?𑍫)
+ ("6" ?௬)
+ ("`6" ?6)
+ ("`^" ?𑍬)
+ ("7" ?௭)
+ ("`7" ?7)
+ ("8" ?௮)
+ ("`8" ?8)
+ ("9" ?௯)
+ ("`9" ?9)
+ ("0" ?௦)
+ ("`0" ?0)
+ ("q" ?𑌟)
+ ("Q" ?𑌠)
+ ("`q" ?𑍐)
+ ("`Q" ?𑍝)
+ ("w" ?𑌡)
+ ("W" ?𑌢)
+ ("`w" ?𑍞)
+ ("`W" ?𑍟)
+ ("e" ?𑍇)
+ ("E" ?𑍈)
+ ("`e" ?𑌏)
+ ("`E" ?𑌐)
+ ("r" ?𑌰)
+ ("R" ?𑍃)
+ ("`r" ?𑌋)
+ ("t" ?𑌤)
+ ("T" ?𑌥)
+ ("`t" ?𑍗)
+ ("y" ?𑌯)
+ ("u" ?𑍁)
+ ("U" ?𑍂)
+ ("`u" ?𑌉)
+ ("`U" ?𑌊)
+ ("i" ?𑌿)
+ ("I" ?𑍀)
+ ("`i" ?𑌇)
+ ("`I" ?𑌈)
+ ("o" ?𑍋)
+ ("O" ?𑍌)
+ ("`o" ?𑌓)
+ ("`O" ?𑌔)
+ ("p" ?𑌪)
+ ("P" ?𑌫)
+ ("`p" ?𑍴)
+ ("a" ?𑌾)
+ ("A" ?𑌆)
+ ("`a" ?𑌅)
+ ("`A" ?𑍰)
+ ("s" ?𑌸)
+ ("S" ?𑌶)
+ ("d" ?𑌦)
+ ("D" ?𑌧)
+ ("f" ?𑍍)
+ ("F" ?𑍄)
+ ("`f" ?𑍠)
+ ("g" ?𑌗)
+ ("G" ?𑌘)
+ ("h" ?𑌹)
+ ("H" ?𑌃)
+ ("j" ?𑌜)
+ ("J" ?𑌝)
+ ("k" ?𑌕)
+ ("K" ?𑌖)
+ ("`k" ?𑍱)
+ ("l" ?𑌲)
+ ("L" ?𑌳)
+ ("`l" ?𑍢)
+ ("`L" ?𑌌)
+ ("z" ?𑌞)
+ ("Z" ?𑌙)
+ ("`z" ?𑍣)
+ ("`Z" ?𑍡)
+ ("x" ?𑌷)
+ ("X" ?𑌼)
+ ("`x" ?𑌻)
+ ("c" ?𑌚)
+ ("C" ?𑌛)
+ ("`c" #x200C) ; ZWNJ
+ ("v" ?𑌵)
+ ("V" ?𑌽)
+ ("`v" ?𑍳)
+ ("b" ?𑌬)
+ ("B" ?𑌭)
+ ("n" ?𑌨)
+ ("N" ?𑌣)
+ ("`n" ?𑍲)
+ ("m" ?𑌮)
+ ("M" ?𑌂)
+ ("`m" ?𑌁)
+ ("`M" ?𑌀))
+
+(quail-define-package
+ "lepcha" "Lepcha" "ᰛᰩᰵ" t "Lepcha phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("``" ?₹)
+ ("1" ?᱁)
+ ("`1" ?1)
+ ("2" ?᱂)
+ ("`2" ?2)
+ ("3" ?᱃)
+ ("`3" ?3)
+ ("4" ?᱄)
+ ("`4" ?4)
+ ("5" ?᱅)
+ ("`5" ?5)
+ ("6" ?᱆)
+ ("`6" ?6)
+ ("7" ?᱇)
+ ("`7" ?7)
+ ("8" ?᱈)
+ ("`8" ?8)
+ ("9" ?᱉)
+ ("`9" ?9)
+ ("0" ?᱀)
+ ("`0" ?0)
+ ("`\\" ?᰻)
+ ("`|" ?᰼)
+ ("`" ?ᱍ)
+ ("q" ?ᱍ)
+ ("Q" ?ᱎ)
+ ("`q" ?᰽)
+ ("`Q" ?᰾)
+ ("w" ?ᰢ)
+ ("W" ?ᱏ)
+ ("`w" ?᰿)
+ ("e" ?ᰬ)
+ ("r" ?ᰛ)
+ ("R" ?ᰥ)
+ ("`r" ?ᰲ)
+ ("t" ?ᰊ)
+ ("T" ?ᰋ)
+ ("`t" ?ᰳ)
+ ("y" ?ᰚ)
+ ("Y" ?ᰤ)
+ ("u" ?ᰪ)
+ ("U" ?ᰫ)
+ ("i" ?ᰧ)
+ ("o" ?ᰨ)
+ ("O" ?ᰩ)
+ ("p" ?ᰎ)
+ ("P" ?ᰏ)
+ ("`p" ?ᰐ)
+ ("`P" ?ᰱ)
+ ("a" ?ᰦ)
+ ("A" ?ᰣ)
+ ("s" ?ᰠ)
+ ("S" ?ᰡ)
+ ("d" ?ᰌ)
+ ("f" ?ᰑ)
+ ("F" ?ᰒ)
+ ("g" ?ᰃ)
+ ("G" ?ᰄ)
+ ("h" ?ᰝ)
+ ("H" ?ᰞ)
+ ("j" ?ᰈ)
+ ("k" ?ᰀ)
+ ("K" ?ᰁ)
+ ("`k" ?ᰂ)
+ ("`K" ?ᰭ)
+ ("l" ?ᰜ)
+ ("L" ?ᰯ)
+ ("z" ?ᰉ)
+ ("Z" ?ᰅ)
+ ("`z" ?ᰴ)
+ ("`Z" ?ᰵ)
+ ("x" ?ᰶ)
+ ("X" ?᰷)
+ ("c" ?ᰆ)
+ ("C" ?ᰇ)
+ ("`c" #x200C) ; ZWNJ
+ ("v" ?ᰟ)
+ ("b" ?ᰓ)
+ ("B" ?ᰔ)
+ ("n" ?ᰍ)
+ ("N" ?ᰰ)
+ ("m" ?ᰕ)
+ ("M" ?ᰖ)
+ ("`m" ?ᰮ))
+
+(quail-define-package
+ "meetei-mayek" "Meetei Mayek" "ꯃꯤ" t "Meetei Mayek phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("``" ?₹)
+ ("1" ?꯱)
+ ("`1" ?1)
+ ("2" ?꯲)
+ ("`2" ?2)
+ ("3" ?꯳)
+ ("`3" ?3)
+ ("4" ?꯴)
+ ("`4" ?4)
+ ("5" ?꯵)
+ ("`5" ?5)
+ ("6" ?꯶)
+ ("`6" ?6)
+ ("7" ?꯷)
+ ("`7" ?7)
+ ("8" ?꯸)
+ ("`8" ?8)
+ ("9" ?꯹)
+ ("`9" ?9)
+ ("0" ?꯰)
+ ("`0" ?0)
+ ("`\\" ?꫰)
+ ("`|" ?꯫)
+ ("`" ?ꫤ)
+ ("q" ?ꫤ)
+ ("Q" ?ꫥ)
+ ("w" ?ꯋ)
+ ("W" ?ꫦ)
+ ("`w" ?ꫧ)
+ ("e" ?ꯦ)
+ ("E" ?ꯩ)
+ ("`e" ?ꫠ)
+ ("r" ?ꯔ)
+ ("t" ?ꯇ)
+ ("T" ?ꯊ)
+ ("`t" ?ꯠ)
+ ("y" ?ꯌ)
+ ("u" ?ꯨ)
+ ("U" ?ꯎ)
+ ("`u" ?ꫬ)
+ ("i" ?ꯤ)
+ ("I" ?ꯏ)
+ ("`i" ?ꯢ)
+ ("`I" ?ꫫ)
+ ("o" ?ꯣ)
+ ("O" ?ꯧ)
+ ("`o" ?ꫡ)
+ ("`O" ?ꫮ)
+ ("p" ?ꯄ)
+ ("P" ?ꯐ)
+ ("`p" ?ꯞ)
+ ("a" ?ꯥ)
+ ("A" ?ꯑ)
+ ("`a" ?ꫭ)
+ ("`A" ?ꫯ)
+ ("s" ?ꯁ)
+ ("S" ?ꫩ)
+ ("`s" ?ꫪ)
+ ("d" ?ꯗ)
+ ("D" ?ꯙ)
+ ("f" ?꯭)
+ ("F" ?꫶)
+ ("g" ?ꯒ)
+ ("G" ?ꯘ)
+ ("h" ?ꯍ)
+ ("H" ?ꫵ)
+ ("j" ?ꯖ)
+ ("J" ?ꯓ)
+ ("k" ?ꯀ)
+ ("K" ?ꯈ)
+ ("`k" ?ꯛ)
+ ("l" ?ꯂ)
+ ("L" ?ꯜ)
+ ("z" ?ꯉ)
+ ("Z" ?ꯡ)
+ ("`z" ?ꫣ)
+ ("x" ?ꯪ)
+ ("c" ?ꯆ)
+ ("C" ?ꫢ)
+ ("v" ?꯬)
+ ("V" ?ꫳ)
+ ("`v" ?ꫴ)
+ ("b" ?ꯕ)
+ ("B" ?ꯚ)
+ ("n" ?ꯅ)
+ ("N" ?ꯟ)
+ ("`n" ?ꫨ)
+ ("m" ?ꯃ)
+ ("M" ?ꯝ)
+ ("`m" ?ꫲ)
+ ("`?" ?꫱))
+
+(provide 'indian)
;;; indian.el ends here
diff --git a/lisp/leim/quail/indonesian.el b/lisp/leim/quail/indonesian.el
new file mode 100644
index 00000000000..8d0d158076a
--- /dev/null
+++ b/lisp/leim/quail/indonesian.el
@@ -0,0 +1,557 @@
+;;; indonesian.el --- Quail package for inputting Indonesian characters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
+;; Keywords: multilingual, input method, i18n, Indonesia
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Input methods for Indonesian languages.
+
+;;; Code:
+
+(require 'quail)
+
+;; This input method supports languages like Buginese, Balinese, Sundanese and
+;; Javanese.
+
+(quail-define-package
+ "balinese" "Balinese" "ᬩ" t "Balinese phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("1" ?᭑)
+ ("`1" ?1)
+ ("`!" ?᭫)
+ ("2" ?᭒)
+ ("`2" ?2)
+ ("`@" ?᭬)
+ ("3" ?᭓)
+ ("`3" ?3)
+ ("`#" ?᭭)
+ ("4" ?᭔)
+ ("`4" ?4)
+ ("`$" ?᭮)
+ ("5" ?᭕)
+ ("`5" ?5)
+ ("`%" ?᭯)
+ ("6" ?᭖)
+ ("`6" ?6)
+ ("`^" ?᭰)
+ ("7" ?᭗)
+ ("`7" ?7)
+ ("`&" ?᭱)
+ ("8" ?᭘)
+ ("`8" ?8)
+ ("`*" ?᭲)
+ ("9" ?᭙)
+ ("`9" ?9)
+ ("`(" ?᭳)
+ ("0" ?᭐)
+ ("`0" ?0)
+ ("`)" ?᭼)
+ ("`\\" ?᭞)
+ ("`|" ?᭟)
+ ("`" ?ᬝ)
+ ("q" ?ᬝ)
+ ("Q" ?ᬞ)
+ ("`q" ?᭚)
+ ("`Q" ?᭽)
+ ("w" ?ᬟ)
+ ("W" ?ᬠ)
+ ("`w" ?᭛)
+ ("`W" ?᭾)
+ ("e" ?ᬾ)
+ ("E" ?ᬿ)
+ ("`e" ?ᬏ)
+ ("`E" ?ᬐ)
+ ("r" ?ᬭ)
+ ("R" ?ᬃ)
+ ("`r" ?ᬺ)
+ ("`R" ?ᬋ)
+ ("t" ?ᬢ)
+ ("T" ?ᬣ)
+ ("`t" ?᭜)
+ ("`T" ?᭝)
+ ("y" ?ᬬ)
+ ("Y" ?ᭂ)
+ ("`y" ?ᭃ)
+ ("`Y" ?᭴)
+ ("u" ?ᬸ)
+ ("U" ?ᬹ)
+ ("`u" ?ᬉ)
+ ("`U" ?ᬊ)
+ ("i" ?ᬶ)
+ ("I" ?ᬷ)
+ ("`i" ?ᬇ)
+ ("`I" ?ᬈ)
+ ("o" ?ᭀ)
+ ("O" ?ᭁ)
+ ("`o" ?ᬑ)
+ ("`O" ?ᬒ)
+ ("p" ?ᬧ)
+ ("P" ?ᬨ)
+ ("`p" ?ᭈ)
+ ("`P" ?᭠)
+ ("a" ?ᬵ)
+ ("A" ?ᬆ)
+ ("`a" ?ᬅ)
+ ("`A" ?᭵)
+ ("s" ?ᬲ)
+ ("S" ?ᬰ)
+ ("`s" ?᭡)
+ ("`S" ?᭢)
+ ("d" ?ᬤ)
+ ("D" ?ᬥ)
+ ("`d" ?᭣)
+ ("`D" ?᭤)
+ ("f" ?᭄)
+ ("F" ?ᬻ)
+ ("`f" ?ᬌ)
+ ("`F" ?᭶)
+ ("g" ?ᬕ)
+ ("G" ?ᬖ)
+ ("`g" ?᭥)
+ ("`G" ?᭦)
+ ("h" ?ᬳ)
+ ("H" ?ᬄ)
+ ("`h" ?᭧)
+ ("`H" ?᭨)
+ ("j" ?ᬚ)
+ ("J" ?ᬛ)
+ ("`j" ?ᭌ)
+ ("`J" ?᭩)
+ ("k" ?ᬓ)
+ ("K" ?ᬔ)
+ ("`k" ?ᭅ)
+ ("`K" ?ᭆ)
+ ("l" ?ᬮ)
+ ("L" ?ᬼ)
+ ("`l" ?ᬍ)
+ ("`L" ?᭪)
+ ("z" ?ᭊ)
+ ("Z" ?ᬽ)
+ ("`z" ?ᬎ)
+ ("`Z" ?᭷)
+ ("x" ?ᬱ)
+ ("X" ?᬴)
+ ("`x" ?᭸)
+ ("c" ?ᬘ)
+ ("C" ?ᬙ)
+ ("`c" #x200C) ; ZWNJ
+ ("v" ?ᬯ)
+ ("V" ?ᭉ)
+ ("`v" ?᭹)
+ ("`V" ?᭺)
+ ("b" ?ᬩ)
+ ("B" ?ᬪ)
+ ("`b" ?᭻)
+ ("n" ?ᬦ)
+ ("N" ?ᬡ)
+ ("`n" ?ᬗ)
+ ("`N" ?ᬜ)
+ ("m" ?ᬫ)
+ ("M" ?ᬂ)
+ ("`m" ?ᬁ)
+ ("`M" ?ᬀ))
+
+(quail-define-package
+ "javanese" "Javanese" "ꦗ" t "Javanese phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("1" ?꧑)
+ ("`1" ?1)
+ ("`!" ?꧁)
+ ("2" ?꧒)
+ ("`2" ?2)
+ ("`@" ?꧂)
+ ("3" ?꧓)
+ ("`3" ?3)
+ ("`#" ?꧃)
+ ("4" ?꧔)
+ ("`4" ?4)
+ ("`$" ?꧄)
+ ("5" ?꧕)
+ ("`5" ?5)
+ ("`%" ?꧅)
+ ("6" ?꧖)
+ ("`6" ?6)
+ ("`^" ?꧆)
+ ("7" ?꧗)
+ ("`7" ?7)
+ ("`&" ?꧇)
+ ("8" ?꧘)
+ ("`8" ?8)
+ ("`*" ?꧈)
+ ("9" ?꧙)
+ ("`9" ?9)
+ ("`(" ?꧉)
+ ("0" ?꧐)
+ ("`0" ?0)
+ ("`)" ?꧞)
+ ("`\\" ?꧊)
+ ("`|" ?꧋)
+ ("`" ?ꦛ)
+ ("q" ?ꦛ)
+ ("Q" ?ꦜ)
+ ("`q" ?꧟)
+ ("`Q" ?ꧏ)
+ ("w" ?ꦝ)
+ ("W" ?ꦞ)
+ ("`w" ?꧌)
+ ("`W" ?꧍)
+ ("e" ?ꦺ)
+ ("E" ?ꦻ)
+ ("`e" ?ꦌ)
+ ("`E" ?ꦍ)
+ ("r" ?ꦫ)
+ ("R" ?ꦬ)
+ ("`r" ?ꦿ)
+ ("`R" ?ꦂ)
+ ("t" ?ꦠ)
+ ("T" ?ꦡ)
+ ("`t" ?ꦼ)
+ ("y" ?ꦪ)
+ ("Y" ?ꦾ)
+ ("u" ?ꦸ)
+ ("U" ?ꦹ)
+ ("`u" ?ꦈ)
+ ("`U" ?ꦅ)
+ ("i" ?ꦶ)
+ ("I" ?ꦷ)
+ ("`i" ?ꦆ)
+ ("`I" ?ꦇ)
+ ("o" ?ꦎ)
+ ("p" ?ꦥ)
+ ("P" ?ꦦ)
+ ("`p" ?ꦉ)
+ ("a" ?ꦴ)
+ ("A" ?ꦄ)
+ ("`a" ?ꦵ)
+ ("s" ?ꦱ)
+ ("S" ?ꦯ)
+ ("d" ?ꦢ)
+ ("D" ?ꦣ)
+ ("f" ?꧀)
+ ("F" ?ꦽ)
+ ("`f" ?ꦉ)
+ ("g" ?ꦒ)
+ ("G" ?ꦓ)
+ ("h" ?ꦲ)
+ ("H" ?ꦃ)
+ ("j" ?ꦗ)
+ ("J" ?ꦙ)
+ ("`j" ?ꦘ)
+ ("k" ?ꦏ)
+ ("K" ?ꦑ)
+ ("`k" ?ꦐ)
+ ("l" ?ꦭ)
+ ("L" ?ꦊ)
+ ("`l" ?ꦋ)
+ ("z" ?ꦚ)
+ ("Z" ?ꦔ)
+ ("x" ?ꦰ)
+ ("X" ?꦳)
+ ("c" ?ꦕ)
+ ("C" ?ꦖ)
+ ("`c" #x200C) ; ZWNJ
+ ("v" ?ꦮ)
+ ("V" ?ᭉ)
+ ("b" ?ꦧ)
+ ("B" ?ꦨ)
+ ("n" ?ꦤ)
+ ("N" ?ꦟ)
+ ("m" ?ꦩ)
+ ("M" ?ꦁ)
+ ("`m" ?ꦀ))
+
+(quail-define-package
+ "sundanese" "Sundanese" "ᮞᮥ" t "Sundanese phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("1" ?᮱)
+ ("`1" ?1)
+ ("`!" ?᳀)
+ ("2" ?᮲)
+ ("`2" ?2)
+ ("`@" ?᳁)
+ ("3" ?᮳)
+ ("`3" ?3)
+ ("`#" ?᳂)
+ ("4" ?᮴)
+ ("`4" ?4)
+ ("`$" ?᳃)
+ ("5" ?᮵)
+ ("`5" ?5)
+ ("6" ?᮶)
+ ("`6" ?6)
+ ("7" ?᮷)
+ ("`7" ?7)
+ ("8" ?᮸)
+ ("`8" ?8)
+ ("9" ?᮹)
+ ("`9" ?9)
+ ("0" ?᮰)
+ ("`0" ?0)
+ ("`" ?ᮒ)
+ ("q" ?ᮋ)
+ ("w" ?ᮝ)
+ ("W" ?ᮭ)
+ ("e" ?ᮨ)
+ ("E" ?ᮩ)
+ ("`e" ?ᮈ)
+ ("`E" ?ᮉ)
+ ("r" ?ᮛ)
+ ("R" ?ᮢ)
+ ("`r" ?ᮁ)
+ ("`R" ?ᮻ)
+ ("t" ?ᮒ)
+ ("y" ?ᮚ)
+ ("Y" ?ᮡ)
+ ("u" ?ᮥ)
+ ("U" ?ᮅ)
+ ("i" ?ᮤ)
+ ("I" ?ᮄ)
+ ("o" ?ᮧ)
+ ("O" ?ᮇ)
+ ("p" ?ᮕ)
+ ("P" ?ᮖ)
+ ("a" ?ᮃ)
+ ("A" ?ᮦ)
+ ("`a" ?ᮆ)
+ ("s" ?ᮞ)
+ ("S" ?ᮯ)
+ ("d" ?ᮓ)
+ ("D" ?᳆)
+ ("f" ?᮪)
+ ("F" ?᮫)
+ ("g" ?ᮌ)
+ ("h" ?ᮠ)
+ ("H" ?ᮂ)
+ ("j" ?ᮏ)
+ ("k" ?ᮊ)
+ ("K" ?ᮮ)
+ ("`k" ?ᮾ)
+ ("`K" ?᳅)
+ ("l" ?ᮜ)
+ ("L" ?ᮣ)
+ ("`l" ?ᮼ)
+ ("`L" ?᳄)
+ ("z" ?ᮐ)
+ ("x" ?ᮟ)
+ ("c" ?ᮎ)
+ ("`c" #x200C) ; ZWNJ
+ ("b" ?ᮘ)
+ ("B" ?ᮽ)
+ ("`b" ?ᮺ)
+ ("`B" ?᳇)
+ ("n" ?ᮔ)
+ ("N" ?ᮍ)
+ ("`n" ?ᮑ)
+ ("m" ?ᮙ)
+ ("M" ?ᮀ)
+ ("`m" ?ᮿ)
+ ("`M" ?ᮬ))
+
+(quail-define-package
+ "batak" "Batak" "ᯅ" t "Batak phonetic input method,
+ used by languages such as Karo, Toba, Pakpak, Mandailing
+ and Simalungun.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?᯼)
+ ("Q" ?᯽)
+ ("w" ?ᯋ)
+ ("W" ?ᯌ)
+ ("`w" ?ᯍ)
+ ("e" ?ᯧ)
+ ("E" ?ᯨ)
+ ("`e" ?ᯩ)
+ ("r" ?ᯒ)
+ ("R" ?ᯓ)
+ ("t" ?ᯖ)
+ ("T" ?ᯗ)
+ ("y" ?ᯛ)
+ ("Y" ?ᯜ)
+ ("u" ?ᯮ)
+ ("U" ?ᯥ)
+ ("`u" ?ᯯ)
+ ("i" ?ᯪ)
+ ("I" ?ᯫ)
+ ("`i" ?ᯤ)
+ ("o" ?ᯬ)
+ ("O" ?ᯭ)
+ ("p" ?ᯇ)
+ ("P" ?ᯈ)
+ ("a" ?ᯀ)
+ ("A" ?ᯁ)
+ ("s" ?ᯘ)
+ ("S" ?ᯙ)
+ ("`s" ?ᯚ)
+ ("d" ?ᯑ)
+ ("f" ?᯲)
+ ("F" ?᯳)
+ ("g" ?ᯎ)
+ ("G" ?ᯏ)
+ ("h" ?ᯂ)
+ ("H" ?ᯃ)
+ ("`h" ?ᯄ)
+ ("`H" ?ᯱ)
+ ("j" ?ᯐ)
+ ("k" ?᯦)
+ ("l" ?ᯞ)
+ ("L" ?ᯟ)
+ ("z" ?ᯝ)
+ ("Z" ?ᯰ)
+ ("x" ?ᯠ)
+ ("c" ?ᯡ)
+ ("v" ?᯾)
+ ("V" ?᯿)
+ ("b" ?ᯅ)
+ ("B" ?ᯆ)
+ ("n" ?ᯉ)
+ ("N" ?ᯊ)
+ ("`n" ?ᯢ)
+ ("m" ?ᯔ)
+ ("M" ?ᯕ)
+ ("`m" ?ᯣ))
+
+(quail-define-package
+ "rejang" "Rejang" "ꤽꥍ" nil "Rejang phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?꥟)
+ ("w" ?ꥀ)
+ ("e" ?ꥉ)
+ ("E" ?ꥊ)
+ ("r" ?ꤽ)
+ ("R" ?ꥑ)
+ ("t" ?ꤳ)
+ ("y" ?ꤿ)
+ ("u" ?ꥈ)
+ ("U" ?ꥍ)
+ ("i" ?ꥇ)
+ ("o" ?ꥋ)
+ ("O" ?ꥌ)
+ ("p" ?ꤶ)
+ ("a" ?ꥆ)
+ ("A" ?ꥎ)
+ ("s" ?ꤼ)
+ ("d" ?ꤴ)
+ ("D" ?ꥄ)
+ ("f" ?꥓)
+ ("F" ?ꥃ)
+ ("g" ?ꤱ)
+ ("h" ?ꥁ)
+ ("H" ?ꥒ)
+ ("j" ?ꤺ)
+ ("k" ?ꤰ)
+ ("l" ?ꤾ)
+ ("z" ?ꤲ)
+ ("Z" ?ꥏ)
+ ("x" ?ꤻ)
+ ("X" ?ꥅ)
+ ("c" ?ꤹ)
+ ("b" ?ꤷ)
+ ("n" ?ꤵ)
+ ("N" ?ꥐ)
+ ("m" ?ꤸ)
+ ("M" ?ꥂ))
+
+(quail-define-package
+ "makasar" "Makasar" "𑻪" nil "Makasar phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?𑻷)
+ ("Q" ?𑻸)
+ ("e" ?𑻵)
+ ("r" ?𑻭)
+ ("t" ?𑻦)
+ ("y" ?𑻬)
+ ("u" ?𑻴)
+ ("i" ?𑻳)
+ ("o" ?𑻶)
+ ("p" ?𑻣)
+ ("a" ?𑻱)
+ ("s" ?𑻰)
+ ("d" ?𑻧)
+ ("g" ?𑻡)
+ ("j" ?𑻪)
+ ("k" ?𑻠)
+ ("l" ?𑻮)
+ ("z" ?𑻢)
+ ("Z" ?𑻲)
+ ("x" ?𑻫)
+ ("c" ?𑻩)
+ ("v" ?𑻯)
+ ("b" ?𑻤)
+ ("n" ?𑻨)
+ ("m" ?𑻥))
+
+(quail-define-package
+ "lontara" "Lontara" "ᨒ" nil "Lontara phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?᨞)
+ ("Q" ?᨟)
+ ("e" ?ᨙ)
+ ("E" ?ᨛ)
+ ("r" ?ᨑ)
+ ("t" ?ᨈ)
+ ("y" ?ᨐ)
+ ("u" ?ᨘ)
+ ("i" ?ᨗ)
+ ("o" ?ᨚ)
+ ("p" ?ᨄ)
+ ("a" ?ᨕ)
+ ("s" ?ᨔ)
+ ("d" ?ᨉ)
+ ("g" ?ᨁ)
+ ("h" ?ᨖ)
+ ("j" ?ᨍ)
+ ("k" ?ᨀ)
+ ("l" ?ᨒ)
+ ("z" ?ᨂ)
+ ("Z" ?ᨃ)
+ ("x" ?ᨎ)
+ ("X" ?ᨏ)
+ ("c" ?ᨌ)
+ ("v" ?ᨓ)
+ ("b" ?ᨅ)
+ ("n" ?ᨊ)
+ ("N" ?ᨋ)
+ ("m" ?ᨆ)
+ ("M" ?ᨇ))
+
+(provide 'indonesian)
+;;; indonesian.el ends here
diff --git a/lisp/leim/quail/ipa.el b/lisp/leim/quail/ipa.el
index 1eb2255f6ce..773dc31f9b7 100644
--- a/lisp/leim/quail/ipa.el
+++ b/lisp/leim/quail/ipa.el
@@ -269,7 +269,7 @@ QUAIL-KEYMAP is a cons that satisfies `quail-map-p'; TO-PREPEND is a
string."
(when (consp quail-keymap) (setq quail-keymap (cdr quail-keymap)))
(if (or (integerp quail-keymap)
- (and (fboundp 'characterp) (characterp quail-keymap)))
+ (characterp quail-keymap))
(setq quail-keymap (list (string quail-keymap)))
(if (stringp quail-keymap)
(setq quail-keymap (list quail-keymap))
diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el
index acb3ef8ede9..76ddf3c2746 100644
--- a/lisp/leim/quail/latin-post.el
+++ b/lisp/leim/quail/latin-post.el
@@ -2239,6 +2239,7 @@ of characters from a single Latin-N charset.
tilde | ~ | a~ -> ã
cedilla | , | c, -> ç
ogonek | , | a, -> ą
+ macron | - | a- -> ā g- -> ḡ e/- -> ǣ -- -> ¯
breve | ~ | a~ -> ă
caron | ~ | c~ -> č
dbl. acute | : | o: -> ő
@@ -2246,14 +2247,45 @@ of characters from a single Latin-N charset.
dot | . | z. -> ż
stroke | / | d/ -> đ
nordic | / | d/ -> ð t/ -> þ a/ -> å e/ -> æ o/ -> ø
+ symbols | ^ | r^ -> ® t^ -> ™
+ super | ^ | 0^ -> ⁰ 1^ -> ¹ +^ -> ⁺ -^ -> ⁻
+ subscript | _ | 0_ -> ₀ 1_ -> ₁ +_ -> ₊ -_ -> ₋
others | / | s/ -> ß ?/ -> ¿ !/ -> ¡ // -> ° o/ -> œ
+ | / | 2/ -> ½ 3/ -> ¾ 4/ -> ?¼
| various | << -> « >> -> » o_ -> º a_ -> ª
Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
" nil t nil nil nil nil nil nil nil nil t)
-;; Fixme: ¦ § ¨ © ¬ ­ ® ¯ ± ² ³ ´ µ ¶ · ¸ ¹ ¼ ½ ¾ × ÷
+;; Fixme: ¦ § ¨ © ¬ ± ´ µ ¶ · ¸ × ÷
(quail-define-rules
+ ("2/" ?½)
+ ("3/" ?¾)
+ ("4/" ?¼)
+ ("0^" ?⁰)
+ ("1^" ?¹)
+ ("2^" ?²)
+ ("3^" ?³)
+ ("4^" ?⁴)
+ ("5^" ?⁵)
+ ("6^" ?⁶)
+ ("7^" ?⁷)
+ ("8^" ?⁸)
+ ("9^" ?⁹)
+ ("+^" ?⁺)
+ ("-^" ?⁻)
+ ("0_" ?₀)
+ ("1_" ?₁)
+ ("2_" ?₂)
+ ("3_" ?₃)
+ ("4_" ?₄)
+ ("5_" ?₅)
+ ("6_" ?₆)
+ ("7_" ?₇)
+ ("8_" ?₈)
+ ("9_" ?₉)
+ ("+_" ?₊)
+ ("-_" ?₋)
(" _" ? )
("!/" ?¡)
("//" ?°)
@@ -2284,11 +2316,13 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("E-" ?Ē)
("E." ?Ė)
("E/" ?Æ)
+ ("E/-" ?Ǣ)
("E\"" ?Ë)
("E^" ?Ê)
("E`" ?È)
("E~" ?Ě)
("G," ?Ģ)
+ ("G-" ?Ḡ)
("G." ?Ġ)
("G^" ?Ĝ)
("G~" ?Ğ)
@@ -2374,12 +2408,14 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("e-" ?ē)
("e." ?ė)
("e/" ?æ)
+ ("e/-" ?ǣ)
("e\"" ?ë)
("e^" ?ê)
("e`" ?è)
("e~" ?ě)
("e=" ?€)
("g," ?ģ)
+ ("g-" ?ḡ)
("g." ?ġ)
("g^" ?ĝ)
("g~" ?ğ)
@@ -2417,6 +2453,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("o~" ?õ)
("r'" ?ŕ)
("r," ?ŗ)
+ ("r^" ?®)
("r~" ?ř)
("s'" ?ś)
("s," ?ş)
@@ -2426,6 +2463,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("t," ?ţ)
("t/" ?þ)
("t/" ?ŧ)
+ ("t^" ?™)
("t~" ?ť)
("u'" ?ú)
("u," ?ų)
@@ -2442,7 +2480,35 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("z'" ?ź)
("z." ?ż)
("z~" ?ž)
-
+ ("--" ?¯)
+
+ ("2//" ["2/"])
+ ("3//" ["3/"])
+ ("4//" ["4/"])
+ ("0^^" ["0^"])
+ ("1^^" ["1^"])
+ ("2^^" ["2^"])
+ ("3^^" ["3^"])
+ ("4^^" ["4^"])
+ ("5^^" ["5^"])
+ ("6^^" ["6^"])
+ ("7^^" ["7^"])
+ ("8^^" ["8^"])
+ ("9^^" ["9^"])
+ ("+^^" ["+^"])
+ ("-^^" ["-^"])
+ ("0__" ["0_"])
+ ("1__" ["1_"])
+ ("2__" ["2_"])
+ ("3__" ["3_"])
+ ("4__" ["4_"])
+ ("5__" ["5_"])
+ ("6__" ["6_"])
+ ("7__" ["7_"])
+ ("8__" ["8_"])
+ ("9__" ["9_"])
+ ("+__" ["+_"])
+ ("-__" ["-_"])
(" __" [" _"])
("!//" ["!/"])
("///" ["//"])
@@ -2470,11 +2536,13 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("E--" ["E-"])
("E.." ["E."])
("E//" ["E/"])
+ ("E/--" ["E/-"])
("E\"\"" ["E\""])
("E^^" ["E^"])
("E``" ["E`"])
("E~~" ["E~"])
("G,," ["G,"])
+ ("G--" ["G-"])
("G.." ["G."])
("G^^" ["G^"])
("G~~" ["G~"])
@@ -2553,12 +2621,14 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("e--" ["e-"])
("e.." ["e."])
("e//" ["e/"])
+ ("e/--" ["e/-"])
("e\"\"" ["e\""])
("e^^" ["e^"])
("e``" ["e`"])
("e==" ["e="])
("e~~" ["e~"])
("g,," ["g,"])
+ ("g--" ["g-"])
("g.." ["g."])
("g^^" ["g^"])
("g~~" ["g~"])
@@ -2617,6 +2687,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\='
("z''" ["z'"])
("z.." ["z."])
("z~~" ["z~"])
+ ("---" ["--"])
)
;; Derived from Slovenian.kmap from Yudit
diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el
index b6a26e0b2c5..48e0ce9efc9 100644
--- a/lisp/leim/quail/latin-pre.el
+++ b/lisp/leim/quail/latin-pre.el
@@ -1104,14 +1104,32 @@ of characters from a single Latin-N charset.
cedilla | , ~ | ,c -> ç ~c -> ç
caron | ~ | ~c -> č ~g -> ğ
breve | ~ | ~a -> ă
+ macron | - | -a -> ā -/e -> ǣ -- -> ¯
dot above | / . | /g -> ġ .g -> ġ
misc | \" ~ / | \"s -> ß ~d -> ð ~t -> þ /a -> å /e -> æ /o -> ø
symbol | ~ | ~> -> » ~< -> « ~! -> ¡ ~? -> ¿ ~~ -> ¸
symbol | _ / | _o -> º _a -> ª // -> ° /\\ -> × _y -> ¥
- symbol | ^ | ^r -> ® ^c -> © ^1 -> ¹ ^2 -> ² ^3 -> ³
+ symbol | ^ | ^r -> ® ^t -> ™ ^c -> © ^1 -> ¹ ^2 -> ² ^3 -> ³
" nil t nil nil nil nil nil nil nil nil t)
(quail-define-rules
+ ("--" ?¯)
+ ("-A" ?Ā)
+ ("-a" ?ā)
+ ("-E" ?Ē)
+ ("-e" ?ē)
+ ("-/E" ?Ǣ)
+ ("-/e" ?ǣ)
+ ("-G" ?Ḡ)
+ ("-g" ?ḡ)
+ ("-I" ?Ī)
+ ("-i" ?ī)
+ ("-O" ?Ō)
+ ("-o" ?ō)
+ ("-U" ?Ū)
+ ("-u" ?ū)
+ ("-Y" ?Ȳ)
+ ("-y" ?ȳ)
("' " ?')
("''" ?´)
("'A" ?Á)
@@ -1197,9 +1215,16 @@ of characters from a single Latin-N charset.
("\"w" ?ẅ)
("\"y" ?ÿ)
("^ " ?^)
+ ("^0" ?⁰)
("^1" ?¹)
("^2" ?²)
("^3" ?³)
+ ("^4" ?⁴)
+ ("^5" ?⁵)
+ ("^6" ?⁶)
+ ("^7" ?⁷)
+ ("^8" ?⁸)
+ ("^9" ?⁹)
("^A" ?Â)
("^C" ?Ĉ)
("^E" ?Ê)
@@ -1224,9 +1249,24 @@ of characters from a single Latin-N charset.
("^o" ?ô)
("^r" ?®)
("^s" ?ŝ)
+ ("^t" ?™)
("^u" ?û)
("^w" ?ŵ)
("^y" ?ŷ)
+ ("^+" ?⁺)
+ ("^-" ?⁻)
+ ("_0" ?₀)
+ ("_1" ?₁)
+ ("_2" ?₂)
+ ("_3" ?₃)
+ ("_4" ?₄)
+ ("_5" ?₅)
+ ("_6" ?₆)
+ ("_7" ?₇)
+ ("_8" ?₈)
+ ("_9" ?₉)
+ ("_++" ?₊)
+ ("_-" ?₋)
("_+" ?±)
("_:" ?÷)
("_a" ?ª)
diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el
new file mode 100644
index 00000000000..0c4a0d4ce40
--- /dev/null
+++ b/lisp/leim/quail/misc-lang.el
@@ -0,0 +1,1184 @@
+;;; misc-lang.el --- Quail package for inputting Miscellaneous characters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
+;; Keywords: multilingual, input method, i18n, Miscellaneous
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Input methods for Miscellaneous languages.
+
+;;; Code:
+
+(require 'quail)
+
+(quail-define-package
+ "hanifi-rohingya" "Hanifi Rohingya" "𐴌𐴟" t "Hanifi Rohingya phonetic input method.
+
+ `\\=`' is used to switch levels instead of Alt-Gr.
+" nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("1" ?𐴱)
+ ("`1" ?1)
+ ("2" ?𐴲)
+ ("`2" ?2)
+ ("3" ?𐴳)
+ ("`3" ?3)
+ ("4" ?𐴴)
+ ("`4" ?4)
+ ("5" ?𐴵)
+ ("`5" ?5)
+ ("6" ?𐴶)
+ ("`6" ?6)
+ ("7" ?𐴷)
+ ("`7" ?7)
+ ("8" ?𐴸)
+ ("`8" ?8)
+ ("9" ?𐴹)
+ ("`9" ?9)
+ ("0" ?𐴰)
+ ("`0" ?0)
+ ("q" ?𐴄)
+ ("w" ?𐴋)
+ ("W" ?𐴍)
+ ("e" ?𐴠)
+ ("E" ?𐴤)
+ ("r" ?𐴌)
+ ("R" ?𐴥)
+ ("t" ?𐴃)
+ ("T" ?𐴦)
+ ("y" ?𐴘)
+ ("Y" ?𐴙)
+ ("u" ?𐴟)
+ ("U" ?𐴧)
+ ("i" ?𐴞)
+ ("o" ?𐴡)
+ ("p" ?𐴂)
+ ("a" ?𐴀)
+ ("A" ?𐴝)
+ ("s" ?𐴏)
+ ("S" ?𐴐)
+ ("d" ?𐴊)
+ ("f" ?𐴉)
+ ("F" ?𐴢)
+ ("g" ?𐴒)
+ ("h" ?𐴇)
+ ("j" ?𐴅)
+ ("k" ?𐴑)
+ ("K" ?𐴈)
+ ("l" ?𐴓)
+ ("z" ?𐴎)
+ ("c" ?𐴆)
+ ("C" #x200C) ; ZWNJ
+ ("v" ?𐴖)
+ ("V" ?𐴗)
+ ("`v" ?𐴜)
+ ("b" ?𐴁)
+ ("n" ?𐴕)
+ ("N" ?𐴚)
+ ("`n" ?𐴛)
+ ("`N" ?𐴣)
+ ("m" ?𐴔))
+
+;; The Kharoṣṭhī input method is based on the Kyoto-Harvard input
+;; conventions for Sanskrit, extended for Kharoṣṭhī special characters.
+;; Author: Stefan Baums <baums@gandhari.org>.
+(quail-define-package
+ "kharoshthi" "Kharoshthi" "𐨑" nil
+ "Kharoṣṭhī input method." nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("a" ["𐨀"])
+ ("i" ["𐨀𐨁"])
+ ("u" ["𐨀𐨂"])
+ ("R" ["𐨀𐨃"])
+ ("e" ["𐨀𐨅"])
+ ("o" ["𐨀𐨆"])
+
+ ("k" ["𐨐𐨿"])
+ ("ka" ["𐨐"])
+ ("ki" ["𐨐𐨁"])
+ ("ku" ["𐨐𐨂"])
+ ("kR" ["𐨐𐨃"])
+ ("ke" ["𐨐𐨅"])
+ ("ko" ["𐨐𐨆"])
+ ("k_" ["𐨐𐨹𐨿"])
+ ("k_a" ["𐨐𐨹"])
+ ("k_i" ["𐨐𐨹𐨁"])
+ ("k_u" ["𐨐𐨹𐨂"])
+ ("k_R" ["𐨐𐨹𐨃"])
+ ("k_e" ["𐨐𐨹𐨅"])
+ ("k_o" ["𐨐𐨹𐨆"])
+ ("k=" ["𐨐𐨿𐨸"])
+ ("k=a" ["𐨐𐨸"])
+ ("k=i" ["𐨐𐨸𐨁"])
+ ("k=u" ["𐨐𐨸𐨂"])
+ ("k=R" ["𐨐𐨸𐨃"])
+ ("k=e" ["𐨐𐨸𐨅"])
+ ("k=o" ["𐨐𐨸𐨆"])
+ ("k_=" ["𐨐𐨹𐨿𐨸"])
+ ("k_=a" ["𐨐𐨹𐨸"])
+ ("k_=i" ["𐨐𐨹𐨸𐨁"])
+ ("k_=u" ["𐨐𐨹𐨸𐨂"])
+ ("k_=R" ["𐨐𐨹𐨸𐨃"])
+ ("k_=e" ["𐨐𐨹𐨸𐨅"])
+ ("k_=o" ["𐨐𐨹𐨸𐨆"])
+
+ ("kh" ["𐨑𐨿"])
+ ("kha" ["𐨑"])
+ ("khi" ["𐨑𐨁"])
+ ("khu" ["𐨑𐨂"])
+ ("khR" ["𐨑𐨃"])
+ ("khe" ["𐨑𐨅"])
+ ("kho" ["𐨑𐨆"])
+ ("kh_" ["𐨑𐨹𐨿"])
+ ("kh_a" ["𐨑𐨹"])
+ ("kh_i" ["𐨑𐨹𐨁"])
+ ("kh_u" ["𐨑𐨹𐨂"])
+ ("kh_R" ["𐨑𐨹𐨃"])
+ ("kh_e" ["𐨑𐨹𐨅"])
+ ("kh_o" ["𐨑𐨹𐨆"])
+ ("kh=" ["𐨑𐨿𐨸"])
+ ("kh=a" ["𐨑𐨸"])
+ ("kh=i" ["𐨑𐨸𐨁"])
+ ("kh=u" ["𐨑𐨸𐨂"])
+ ("kh=R" ["𐨑𐨸𐨃"])
+ ("kh=e" ["𐨑𐨸𐨅"])
+ ("kh=o" ["𐨑𐨸𐨆"])
+ ("kh_=" ["𐨑𐨹𐨿𐨸"])
+ ("kh_=a" ["𐨑𐨹𐨸"])
+ ("kh_=i" ["𐨑𐨹𐨸𐨁"])
+ ("kh_=u" ["𐨑𐨹𐨸𐨂"])
+ ("kh_=R" ["𐨑𐨹𐨸𐨃"])
+ ("kh_=e" ["𐨑𐨹𐨸𐨅"])
+ ("kh_=o" ["𐨑𐨹𐨸𐨆"])
+
+ ("g" ["𐨒𐨿"])
+ ("ga" ["𐨒"])
+ ("gi" ["𐨒𐨁"])
+ ("gu" ["𐨒𐨂"])
+ ("gR" ["𐨒𐨃"])
+ ("ge" ["𐨒𐨅"])
+ ("go" ["𐨒𐨆"])
+ ("g_" ["𐨒𐨹𐨿"])
+ ("g_a" ["𐨒𐨹"])
+ ("g_i" ["𐨒𐨹𐨁"])
+ ("g_u" ["𐨒𐨹𐨂"])
+ ("g_R" ["𐨒𐨹𐨃"])
+ ("g_e" ["𐨒𐨹𐨅"])
+ ("g_o" ["𐨒𐨹𐨆"])
+ ("g=" ["𐨒𐨿𐨸"])
+ ("g=a" ["𐨒𐨸"])
+ ("g=i" ["𐨒𐨸𐨁"])
+ ("g=u" ["𐨒𐨸𐨂"])
+ ("g=R" ["𐨒𐨸𐨃"])
+ ("g=e" ["𐨒𐨸𐨅"])
+ ("g=o" ["𐨒𐨸𐨆"])
+ ("g_=" ["𐨒𐨹𐨿𐨸"])
+ ("g_=a" ["𐨒𐨹𐨸"])
+ ("g_=i" ["𐨒𐨹𐨸𐨁"])
+ ("g_=u" ["𐨒𐨹𐨸𐨂"])
+ ("g_=R" ["𐨒𐨹𐨸𐨃"])
+ ("g_=e" ["𐨒𐨹𐨸𐨅"])
+ ("g_=o" ["𐨒𐨹𐨸𐨆"])
+
+ ("gh" ["𐨓𐨿"])
+ ("gha" ["𐨓"])
+ ("ghi" ["𐨓𐨁"])
+ ("ghu" ["𐨓𐨂"])
+ ("ghR" ["𐨓𐨃"])
+ ("ghe" ["𐨓𐨅"])
+ ("gho" ["𐨓𐨆"])
+ ("gh_" ["𐨓𐨹𐨿"])
+ ("gh_a" ["𐨓𐨹"])
+ ("gh_i" ["𐨓𐨹𐨁"])
+ ("gh_u" ["𐨓𐨹𐨂"])
+ ("gh_R" ["𐨓𐨹𐨃"])
+ ("gh_e" ["𐨓𐨹𐨅"])
+ ("gh_o" ["𐨓𐨹𐨆"])
+ ("gh=" ["𐨓𐨿𐨸"])
+ ("gh=a" ["𐨓𐨸"])
+ ("gh=i" ["𐨓𐨸𐨁"])
+ ("gh=u" ["𐨓𐨸𐨂"])
+ ("gh=R" ["𐨓𐨸𐨃"])
+ ("gh=e" ["𐨓𐨸𐨅"])
+ ("gh=o" ["𐨓𐨸𐨆"])
+ ("gh_=" ["𐨓𐨹𐨿𐨸"])
+ ("gh_=a" ["𐨓𐨹𐨸"])
+ ("gh_=i" ["𐨓𐨹𐨸𐨁"])
+ ("gh_=u" ["𐨓𐨹𐨸𐨂"])
+ ("gh_=R" ["𐨓𐨹𐨸𐨃"])
+ ("gh_=e" ["𐨓𐨹𐨸𐨅"])
+ ("gh_=o" ["𐨓𐨹𐨸𐨆"])
+
+ ("c" ["𐨕𐨿"])
+ ("ca" ["𐨕"])
+ ("ci" ["𐨕𐨁"])
+ ("cu" ["𐨕𐨂"])
+ ("cR" ["𐨕𐨃"])
+ ("ce" ["𐨕𐨅"])
+ ("co" ["𐨕𐨆"])
+ ("c_" ["𐨕𐨹𐨿"])
+ ("c_a" ["𐨕𐨹"])
+ ("c_i" ["𐨕𐨹𐨁"])
+ ("c_u" ["𐨕𐨹𐨂"])
+ ("c_R" ["𐨕𐨹𐨃"])
+ ("c_e" ["𐨕𐨹𐨅"])
+ ("c_o" ["𐨕𐨹𐨆"])
+ ("c=" ["𐨕𐨿𐨸"])
+ ("c=a" ["𐨕𐨸"])
+ ("c=i" ["𐨕𐨸𐨁"])
+ ("c=u" ["𐨕𐨸𐨂"])
+ ("c=R" ["𐨕𐨸𐨃"])
+ ("c=e" ["𐨕𐨸𐨅"])
+ ("c=o" ["𐨕𐨸𐨆"])
+ ("c_=" ["𐨕𐨹𐨿𐨸"])
+ ("c_=a" ["𐨕𐨹𐨸"])
+ ("c_=i" ["𐨕𐨹𐨸𐨁"])
+ ("c_=u" ["𐨕𐨹𐨸𐨂"])
+ ("c_=R" ["𐨕𐨹𐨸𐨃"])
+ ("c_=e" ["𐨕𐨹𐨸𐨅"])
+ ("c_=o" ["𐨕𐨹𐨸𐨆"])
+
+ ("ch" ["𐨖𐨿"])
+ ("cha" ["𐨖"])
+ ("chi" ["𐨖𐨁"])
+ ("chu" ["𐨖𐨂"])
+ ("chR" ["𐨖𐨃"])
+ ("che" ["𐨖𐨅"])
+ ("cho" ["𐨖𐨆"])
+ ("ch_" ["𐨖𐨹𐨿"])
+ ("ch_a" ["𐨖𐨹"])
+ ("ch_i" ["𐨖𐨹𐨁"])
+ ("ch_u" ["𐨖𐨹𐨂"])
+ ("ch_R" ["𐨖𐨹𐨃"])
+ ("ch_e" ["𐨖𐨹𐨅"])
+ ("ch_o" ["𐨖𐨹𐨆"])
+ ("ch=" ["𐨖𐨿𐨸"])
+ ("ch=a" ["𐨖𐨸"])
+ ("ch=i" ["𐨖𐨸𐨁"])
+ ("ch=u" ["𐨖𐨸𐨂"])
+ ("ch=R" ["𐨖𐨸𐨃"])
+ ("ch=e" ["𐨖𐨸𐨅"])
+ ("ch=o" ["𐨖𐨸𐨆"])
+ ("ch_=" ["𐨖𐨹𐨿𐨸"])
+ ("ch_=a" ["𐨖𐨹𐨸"])
+ ("ch_=i" ["𐨖𐨹𐨸𐨁"])
+ ("ch_=u" ["𐨖𐨹𐨸𐨂"])
+ ("ch_=R" ["𐨖𐨹𐨸𐨃"])
+ ("ch_=e" ["𐨖𐨹𐨸𐨅"])
+ ("ch_=o" ["𐨖𐨹𐨸𐨆"])
+
+ ("j" ["𐨗𐨿"])
+ ("ja" ["𐨗"])
+ ("ji" ["𐨗𐨁"])
+ ("ju" ["𐨗𐨂"])
+ ("jR" ["𐨗𐨃"])
+ ("je" ["𐨗𐨅"])
+ ("jo" ["𐨗𐨆"])
+ ("j_" ["𐨗𐨹𐨿"])
+ ("j_a" ["𐨗𐨹"])
+ ("j_i" ["𐨗𐨹𐨁"])
+ ("j_u" ["𐨗𐨹𐨂"])
+ ("j_R" ["𐨗𐨹𐨃"])
+ ("j_e" ["𐨗𐨹𐨅"])
+ ("j_o" ["𐨗𐨹𐨆"])
+ ("j=" ["𐨗𐨿𐨸"])
+ ("j=a" ["𐨗𐨸"])
+ ("j=i" ["𐨗𐨸𐨁"])
+ ("j=u" ["𐨗𐨸𐨂"])
+ ("j=R" ["𐨗𐨸𐨃"])
+ ("j=e" ["𐨗𐨸𐨅"])
+ ("j=o" ["𐨗𐨸𐨆"])
+ ("j_=" ["𐨗𐨹𐨿𐨸"])
+ ("j_=a" ["𐨗𐨹𐨸"])
+ ("j_=i" ["𐨗𐨹𐨸𐨁"])
+ ("j_=u" ["𐨗𐨹𐨸𐨂"])
+ ("j_=R" ["𐨗𐨹𐨸𐨃"])
+ ("j_=e" ["𐨗𐨹𐨸𐨅"])
+ ("j_=o" ["𐨗𐨹𐨸𐨆"])
+
+ ("jh" ["𐨰𐨿"])
+ ("jha" ["𐨰"])
+ ("jhi" ["𐨰𐨁"])
+ ("jhu" ["𐨰𐨂"])
+ ("jhR" ["𐨰𐨃"])
+ ("jhe" ["𐨰𐨅"])
+ ("jho" ["𐨰𐨆"])
+ ("jh_" ["𐨰𐨹𐨿"])
+ ("jh_a" ["𐨰𐨹"])
+ ("jh_i" ["𐨰𐨹𐨁"])
+ ("jh_u" ["𐨰𐨹𐨂"])
+ ("jh_R" ["𐨰𐨹𐨃"])
+ ("jh_e" ["𐨰𐨹𐨅"])
+ ("jh_o" ["𐨰𐨹𐨆"])
+ ("jh=" ["𐨰𐨿𐨸"])
+ ("jh=a" ["𐨰𐨸"])
+ ("jh=i" ["𐨰𐨸𐨁"])
+ ("jh=u" ["𐨰𐨸𐨂"])
+ ("jh=R" ["𐨰𐨸𐨃"])
+ ("jh=e" ["𐨰𐨸𐨅"])
+ ("jh=o" ["𐨰𐨸𐨆"])
+ ("jh_=" ["𐨰𐨹𐨿𐨸"])
+ ("jh_=a" ["𐨰𐨹𐨸"])
+ ("jh_=i" ["𐨰𐨹𐨸𐨁"])
+ ("jh_=u" ["𐨰𐨹𐨸𐨂"])
+ ("jh_=R" ["𐨰𐨹𐨸𐨃"])
+ ("jh_=e" ["𐨰𐨹𐨸𐨅"])
+ ("jh_=o" ["𐨰𐨹𐨸𐨆"])
+
+ ("J" ["𐨙𐨿"])
+ ("Ja" ["𐨙"])
+ ("Ji" ["𐨙𐨁"])
+ ("Ju" ["𐨙𐨂"])
+ ("JR" ["𐨙𐨃"])
+ ("Je" ["𐨙𐨅"])
+ ("Jo" ["𐨙𐨆"])
+ ("J_" ["𐨙𐨹𐨿"])
+ ("J_a" ["𐨙𐨹"])
+ ("J_i" ["𐨙𐨹𐨁"])
+ ("J_u" ["𐨙𐨹𐨂"])
+ ("J_R" ["𐨙𐨹𐨃"])
+ ("J_e" ["𐨙𐨹𐨅"])
+ ("J_o" ["𐨙𐨹𐨆"])
+ ("J=" ["𐨙𐨿𐨸"])
+ ("J=a" ["𐨙𐨸"])
+ ("J=i" ["𐨙𐨸𐨁"])
+ ("J=u" ["𐨙𐨸𐨂"])
+ ("J=R" ["𐨙𐨸𐨃"])
+ ("J=e" ["𐨙𐨸𐨅"])
+ ("J=o" ["𐨙𐨸𐨆"])
+ ("J_=" ["𐨙𐨹𐨿𐨸"])
+ ("J_=a" ["𐨙𐨹𐨸"])
+ ("J_=i" ["𐨙𐨹𐨸𐨁"])
+ ("J_=u" ["𐨙𐨹𐨸𐨂"])
+ ("J_=R" ["𐨙𐨹𐨸𐨃"])
+ ("J_=e" ["𐨙𐨹𐨸𐨅"])
+ ("J_=o" ["𐨙𐨹𐨸𐨆"])
+
+ ("T" ["𐨚𐨿"])
+ ("Ta" ["𐨚"])
+ ("Ti" ["𐨚𐨁"])
+ ("Tu" ["𐨚𐨂"])
+ ("TR" ["𐨚𐨃"])
+ ("Te" ["𐨚𐨅"])
+ ("To" ["𐨚𐨆"])
+ ("T_" ["𐨚𐨹𐨿"])
+ ("T_a" ["𐨚𐨹"])
+ ("T_i" ["𐨚𐨹𐨁"])
+ ("T_u" ["𐨚𐨹𐨂"])
+ ("T_R" ["𐨚𐨹𐨃"])
+ ("T_e" ["𐨚𐨹𐨅"])
+ ("T_o" ["𐨚𐨹𐨆"])
+ ("T=" ["𐨚𐨿𐨸"])
+ ("T=a" ["𐨚𐨸"])
+ ("T=i" ["𐨚𐨸𐨁"])
+ ("T=u" ["𐨚𐨸𐨂"])
+ ("T=R" ["𐨚𐨸𐨃"])
+ ("T=e" ["𐨚𐨸𐨅"])
+ ("T=o" ["𐨚𐨸𐨆"])
+ ("T_=" ["𐨚𐨹𐨿𐨸"])
+ ("T_=a" ["𐨚𐨹𐨸"])
+ ("T_=i" ["𐨚𐨹𐨸𐨁"])
+ ("T_=u" ["𐨚𐨹𐨸𐨂"])
+ ("T_=R" ["𐨚𐨹𐨸𐨃"])
+ ("T_=e" ["𐨚𐨹𐨸𐨅"])
+ ("T_=o" ["𐨚𐨹𐨸𐨆"])
+
+ ("Th" ["𐨛𐨿"])
+ ("Tha" ["𐨛"])
+ ("Thi" ["𐨛𐨁"])
+ ("Thu" ["𐨛𐨂"])
+ ("ThR" ["𐨛𐨃"])
+ ("The" ["𐨛𐨅"])
+ ("Tho" ["𐨛𐨆"])
+ ("Th_" ["𐨛𐨹𐨿"])
+ ("Th_a" ["𐨛𐨹"])
+ ("Th_i" ["𐨛𐨹𐨁"])
+ ("Th_u" ["𐨛𐨹𐨂"])
+ ("Th_R" ["𐨛𐨹𐨃"])
+ ("Th_e" ["𐨛𐨹𐨅"])
+ ("Th_o" ["𐨛𐨹𐨆"])
+ ("Th=" ["𐨛𐨿𐨸"])
+ ("Th=a" ["𐨛𐨸"])
+ ("Th=i" ["𐨛𐨸𐨁"])
+ ("Th=u" ["𐨛𐨸𐨂"])
+ ("Th=R" ["𐨛𐨸𐨃"])
+ ("Th=e" ["𐨛𐨸𐨅"])
+ ("Th=o" ["𐨛𐨸𐨆"])
+ ("Th_=" ["𐨛𐨹𐨿𐨸"])
+ ("Th_=a" ["𐨛𐨹𐨸"])
+ ("Th_=i" ["𐨛𐨹𐨸𐨁"])
+ ("Th_=u" ["𐨛𐨹𐨸𐨂"])
+ ("Th_=R" ["𐨛𐨹𐨸𐨃"])
+ ("Th_=e" ["𐨛𐨹𐨸𐨅"])
+ ("Th_=o" ["𐨛𐨹𐨸𐨆"])
+
+ ("D" ["𐨜𐨿"])
+ ("Da" ["𐨜"])
+ ("Di" ["𐨜𐨁"])
+ ("Du" ["𐨜𐨂"])
+ ("DR" ["𐨜𐨃"])
+ ("De" ["𐨜𐨅"])
+ ("Do" ["𐨜𐨆"])
+ ("D_" ["𐨜𐨹𐨿"])
+ ("D_a" ["𐨜𐨹"])
+ ("D_i" ["𐨜𐨹𐨁"])
+ ("D_u" ["𐨜𐨹𐨂"])
+ ("D_R" ["𐨜𐨹𐨃"])
+ ("D_e" ["𐨜𐨹𐨅"])
+ ("D_o" ["𐨜𐨹𐨆"])
+ ("D=" ["𐨜𐨿𐨸"])
+ ("D=a" ["𐨜𐨸"])
+ ("D=i" ["𐨜𐨸𐨁"])
+ ("D=u" ["𐨜𐨸𐨂"])
+ ("D=R" ["𐨜𐨸𐨃"])
+ ("D=e" ["𐨜𐨸𐨅"])
+ ("D=o" ["𐨜𐨸𐨆"])
+ ("D_=" ["𐨜𐨹𐨿𐨸"])
+ ("D_=a" ["𐨜𐨹𐨸"])
+ ("D_=i" ["𐨜𐨹𐨸𐨁"])
+ ("D_=u" ["𐨜𐨹𐨸𐨂"])
+ ("D_=R" ["𐨜𐨹𐨸𐨃"])
+ ("D_=e" ["𐨜𐨹𐨸𐨅"])
+ ("D_=o" ["𐨜𐨹𐨸𐨆"])
+
+ ("Dh" ["𐨝𐨿"])
+ ("Dha" ["𐨝"])
+ ("Dhi" ["𐨝𐨁"])
+ ("Dhu" ["𐨝𐨂"])
+ ("DhR" ["𐨝𐨃"])
+ ("Dhe" ["𐨝𐨅"])
+ ("Dho" ["𐨝𐨆"])
+ ("Dh_" ["𐨝𐨹𐨿"])
+ ("Dh_a" ["𐨝𐨹"])
+ ("Dh_i" ["𐨝𐨹𐨁"])
+ ("Dh_u" ["𐨝𐨹𐨂"])
+ ("Dh_R" ["𐨝𐨹𐨃"])
+ ("Dh_e" ["𐨝𐨹𐨅"])
+ ("Dh_o" ["𐨝𐨹𐨆"])
+ ("Dh=" ["𐨝𐨿𐨸"])
+ ("Dh=a" ["𐨝𐨸"])
+ ("Dh=i" ["𐨝𐨸𐨁"])
+ ("Dh=u" ["𐨝𐨸𐨂"])
+ ("Dh=R" ["𐨝𐨸𐨃"])
+ ("Dh=e" ["𐨝𐨸𐨅"])
+ ("Dh=o" ["𐨝𐨸𐨆"])
+ ("Dh_=" ["𐨝𐨹𐨿𐨸"])
+ ("Dh_=a" ["𐨝𐨹𐨸"])
+ ("Dh_=i" ["𐨝𐨹𐨸𐨁"])
+ ("Dh_=u" ["𐨝𐨹𐨸𐨂"])
+ ("Dh_=R" ["𐨝𐨹𐨸𐨃"])
+ ("Dh_=e" ["𐨝𐨹𐨸𐨅"])
+ ("Dh_=o" ["𐨝𐨹𐨸𐨆"])
+
+ ("N" ["𐨞𐨿"])
+ ("Na" ["𐨞"])
+ ("Ni" ["𐨞𐨁"])
+ ("Nu" ["𐨞𐨂"])
+ ("NR" ["𐨞𐨃"])
+ ("Ne" ["𐨞𐨅"])
+ ("No" ["𐨞𐨆"])
+ ("N_" ["𐨞𐨹𐨿"])
+ ("N_a" ["𐨞𐨹"])
+ ("N_i" ["𐨞𐨹𐨁"])
+ ("N_u" ["𐨞𐨹𐨂"])
+ ("N_R" ["𐨞𐨹𐨃"])
+ ("N_e" ["𐨞𐨹𐨅"])
+ ("N_o" ["𐨞𐨹𐨆"])
+ ("N=" ["𐨞𐨿𐨸"])
+ ("N=a" ["𐨞𐨸"])
+ ("N=i" ["𐨞𐨸𐨁"])
+ ("N=u" ["𐨞𐨸𐨂"])
+ ("N=R" ["𐨞𐨸𐨃"])
+ ("N=e" ["𐨞𐨸𐨅"])
+ ("N=o" ["𐨞𐨸𐨆"])
+ ("N_=" ["𐨞𐨹𐨿𐨸"])
+ ("N_=a" ["𐨞𐨹𐨸"])
+ ("N_=i" ["𐨞𐨹𐨸𐨁"])
+ ("N_=u" ["𐨞𐨹𐨸𐨂"])
+ ("N_=R" ["𐨞𐨹𐨸𐨃"])
+ ("N_=e" ["𐨞𐨹𐨸𐨅"])
+ ("N_=o" ["𐨞𐨹𐨸𐨆"])
+
+ ("t" ["𐨟𐨿"])
+ ("ta" ["𐨟"])
+ ("ti" ["𐨟𐨁"])
+ ("tu" ["𐨟𐨂"])
+ ("tR" ["𐨟𐨃"])
+ ("te" ["𐨟𐨅"])
+ ("to" ["𐨟𐨆"])
+ ("t_" ["𐨟𐨹𐨿"])
+ ("t_a" ["𐨟𐨹"])
+ ("t_i" ["𐨟𐨹𐨁"])
+ ("t_u" ["𐨟𐨹𐨂"])
+ ("t_R" ["𐨟𐨹𐨃"])
+ ("t_e" ["𐨟𐨹𐨅"])
+ ("t_o" ["𐨟𐨹𐨆"])
+ ("t=" ["𐨟𐨿𐨸"])
+ ("t=a" ["𐨟𐨸"])
+ ("t=i" ["𐨟𐨸𐨁"])
+ ("t=u" ["𐨟𐨸𐨂"])
+ ("t=R" ["𐨟𐨸𐨃"])
+ ("t=e" ["𐨟𐨸𐨅"])
+ ("t=o" ["𐨟𐨸𐨆"])
+ ("t_=" ["𐨟𐨹𐨿𐨸"])
+ ("t_=a" ["𐨟𐨹𐨸"])
+ ("t_=i" ["𐨟𐨹𐨸𐨁"])
+ ("t_=u" ["𐨟𐨹𐨸𐨂"])
+ ("t_=R" ["𐨟𐨹𐨸𐨃"])
+ ("t_=e" ["𐨟𐨹𐨸𐨅"])
+ ("t_=o" ["𐨟𐨹𐨸𐨆"])
+
+ ("th" ["𐨠𐨿"])
+ ("tha" ["𐨠"])
+ ("thi" ["𐨠𐨁"])
+ ("thu" ["𐨠𐨂"])
+ ("thR" ["𐨠𐨃"])
+ ("the" ["𐨠𐨅"])
+ ("tho" ["𐨠𐨆"])
+ ("th_" ["𐨠𐨹𐨿"])
+ ("th_a" ["𐨠𐨹"])
+ ("th_i" ["𐨠𐨹𐨁"])
+ ("th_u" ["𐨠𐨹𐨂"])
+ ("th_R" ["𐨠𐨹𐨃"])
+ ("th_e" ["𐨠𐨹𐨅"])
+ ("th_o" ["𐨠𐨹𐨆"])
+ ("th=" ["𐨠𐨿𐨸"])
+ ("th=a" ["𐨠𐨸"])
+ ("th=i" ["𐨠𐨸𐨁"])
+ ("th=u" ["𐨠𐨸𐨂"])
+ ("th=R" ["𐨠𐨸𐨃"])
+ ("th=e" ["𐨠𐨸𐨅"])
+ ("th=o" ["𐨠𐨸𐨆"])
+ ("th_=" ["𐨠𐨹𐨿𐨸"])
+ ("th_=a" ["𐨠𐨹𐨸"])
+ ("th_=i" ["𐨠𐨹𐨸𐨁"])
+ ("th_=u" ["𐨠𐨹𐨸𐨂"])
+ ("th_=R" ["𐨠𐨹𐨸𐨃"])
+ ("th_=e" ["𐨠𐨹𐨸𐨅"])
+ ("th_=o" ["𐨠𐨹𐨸𐨆"])
+
+ ("d" ["𐨡𐨿"])
+ ("da" ["𐨡"])
+ ("di" ["𐨡𐨁"])
+ ("du" ["𐨡𐨂"])
+ ("dR" ["𐨡𐨃"])
+ ("de" ["𐨡𐨅"])
+ ("do" ["𐨡𐨆"])
+ ("d_" ["𐨡𐨹𐨿"])
+ ("d_a" ["𐨡𐨹"])
+ ("d_i" ["𐨡𐨹𐨁"])
+ ("d_u" ["𐨡𐨹𐨂"])
+ ("d_R" ["𐨡𐨹𐨃"])
+ ("d_e" ["𐨡𐨹𐨅"])
+ ("d_o" ["𐨡𐨹𐨆"])
+ ("d=" ["𐨡𐨿𐨸"])
+ ("d=a" ["𐨡𐨸"])
+ ("d=i" ["𐨡𐨸𐨁"])
+ ("d=u" ["𐨡𐨸𐨂"])
+ ("d=R" ["𐨡𐨸𐨃"])
+ ("d=e" ["𐨡𐨸𐨅"])
+ ("d=o" ["𐨡𐨸𐨆"])
+ ("d_=" ["𐨡𐨹𐨿𐨸"])
+ ("d_=a" ["𐨡𐨹𐨸"])
+ ("d_=i" ["𐨡𐨹𐨸𐨁"])
+ ("d_=u" ["𐨡𐨹𐨸𐨂"])
+ ("d_=R" ["𐨡𐨹𐨸𐨃"])
+ ("d_=e" ["𐨡𐨹𐨸𐨅"])
+ ("d_=o" ["𐨡𐨹𐨸𐨆"])
+
+ ("dh" ["𐨢𐨿"])
+ ("dha" ["𐨢"])
+ ("dhi" ["𐨢𐨁"])
+ ("dhu" ["𐨢𐨂"])
+ ("dhR" ["𐨢𐨃"])
+ ("dhe" ["𐨢𐨅"])
+ ("dho" ["𐨢𐨆"])
+ ("dh_" ["𐨢𐨹𐨿"])
+ ("dh_a" ["𐨢𐨹"])
+ ("dh_i" ["𐨢𐨹𐨁"])
+ ("dh_u" ["𐨢𐨹𐨂"])
+ ("dh_R" ["𐨢𐨹𐨃"])
+ ("dh_e" ["𐨢𐨹𐨅"])
+ ("dh_o" ["𐨢𐨹𐨆"])
+ ("dh=" ["𐨢𐨿𐨸"])
+ ("dh=a" ["𐨢𐨸"])
+ ("dh=i" ["𐨢𐨸𐨁"])
+ ("dh=u" ["𐨢𐨸𐨂"])
+ ("dh=R" ["𐨢𐨸𐨃"])
+ ("dh=e" ["𐨢𐨸𐨅"])
+ ("dh=o" ["𐨢𐨸𐨆"])
+ ("dh_=" ["𐨢𐨹𐨿𐨸"])
+ ("dh_=a" ["𐨢𐨹𐨸"])
+ ("dh_=i" ["𐨢𐨹𐨸𐨁"])
+ ("dh_=u" ["𐨢𐨹𐨸𐨂"])
+ ("dh_=R" ["𐨢𐨹𐨸𐨃"])
+ ("dh_=e" ["𐨢𐨹𐨸𐨅"])
+ ("dh_=o" ["𐨢𐨹𐨸𐨆"])
+
+ ("n" ["𐨣𐨿"])
+ ("na" ["𐨣"])
+ ("ni" ["𐨣𐨁"])
+ ("nu" ["𐨣𐨂"])
+ ("nR" ["𐨣𐨃"])
+ ("ne" ["𐨣𐨅"])
+ ("no" ["𐨣𐨆"])
+ ("n_" ["𐨣𐨹𐨿"])
+ ("n_a" ["𐨣𐨹"])
+ ("n_i" ["𐨣𐨹𐨁"])
+ ("n_u" ["𐨣𐨹𐨂"])
+ ("n_R" ["𐨣𐨹𐨃"])
+ ("n_e" ["𐨣𐨹𐨅"])
+ ("n_o" ["𐨣𐨹𐨆"])
+ ("n=" ["𐨣𐨿𐨸"])
+ ("n=a" ["𐨣𐨸"])
+ ("n=i" ["𐨣𐨸𐨁"])
+ ("n=u" ["𐨣𐨸𐨂"])
+ ("n=R" ["𐨣𐨸𐨃"])
+ ("n=e" ["𐨣𐨸𐨅"])
+ ("n=o" ["𐨣𐨸𐨆"])
+ ("n_=" ["𐨣𐨹𐨿𐨸"])
+ ("n_=a" ["𐨣𐨹𐨸"])
+ ("n_=i" ["𐨣𐨹𐨸𐨁"])
+ ("n_=u" ["𐨣𐨹𐨸𐨂"])
+ ("n_=R" ["𐨣𐨹𐨸𐨃"])
+ ("n_=e" ["𐨣𐨹𐨸𐨅"])
+ ("n_=o" ["𐨣𐨹𐨸𐨆"])
+
+ ("p" ["𐨤𐨿"])
+ ("pa" ["𐨤"])
+ ("pi" ["𐨤𐨁"])
+ ("pu" ["𐨤𐨂"])
+ ("pR" ["𐨤𐨃"])
+ ("pe" ["𐨤𐨅"])
+ ("po" ["𐨤𐨆"])
+ ("p_" ["𐨤𐨹𐨿"])
+ ("p_a" ["𐨤𐨹"])
+ ("p_i" ["𐨤𐨹𐨁"])
+ ("p_u" ["𐨤𐨹𐨂"])
+ ("p_R" ["𐨤𐨹𐨃"])
+ ("p_e" ["𐨤𐨹𐨅"])
+ ("p_o" ["𐨤𐨹𐨆"])
+ ("p=" ["𐨤𐨿𐨸"])
+ ("p=a" ["𐨤𐨸"])
+ ("p=i" ["𐨤𐨸𐨁"])
+ ("p=u" ["𐨤𐨸𐨂"])
+ ("p=R" ["𐨤𐨸𐨃"])
+ ("p=e" ["𐨤𐨸𐨅"])
+ ("p=o" ["𐨤𐨸𐨆"])
+ ("p_=" ["𐨤𐨹𐨿𐨸"])
+ ("p_=a" ["𐨤𐨹𐨸"])
+ ("p_=i" ["𐨤𐨹𐨸𐨁"])
+ ("p_=u" ["𐨤𐨹𐨸𐨂"])
+ ("p_=R" ["𐨤𐨹𐨸𐨃"])
+ ("p_=e" ["𐨤𐨹𐨸𐨅"])
+ ("p_=o" ["𐨤𐨹𐨸𐨆"])
+
+ ("ph" ["𐨥𐨿"])
+ ("pha" ["𐨥"])
+ ("phi" ["𐨥𐨁"])
+ ("phu" ["𐨥𐨂"])
+ ("phR" ["𐨥𐨃"])
+ ("phe" ["𐨥𐨅"])
+ ("pho" ["𐨥𐨆"])
+ ("ph_" ["𐨥𐨹𐨿"])
+ ("ph_a" ["𐨥𐨹"])
+ ("ph_i" ["𐨥𐨹𐨁"])
+ ("ph_u" ["𐨥𐨹𐨂"])
+ ("ph_R" ["𐨥𐨹𐨃"])
+ ("ph_e" ["𐨥𐨹𐨅"])
+ ("ph_o" ["𐨥𐨹𐨆"])
+ ("ph=" ["𐨥𐨿𐨸"])
+ ("ph=a" ["𐨥𐨸"])
+ ("ph=i" ["𐨥𐨸𐨁"])
+ ("ph=u" ["𐨥𐨸𐨂"])
+ ("ph=R" ["𐨥𐨸𐨃"])
+ ("ph=e" ["𐨥𐨸𐨅"])
+ ("ph=o" ["𐨥𐨸𐨆"])
+ ("ph_=" ["𐨥𐨹𐨿𐨸"])
+ ("ph_=a" ["𐨥𐨹𐨸"])
+ ("ph_=i" ["𐨥𐨹𐨸𐨁"])
+ ("ph_=u" ["𐨥𐨹𐨸𐨂"])
+ ("ph_=R" ["𐨥𐨹𐨸𐨃"])
+ ("ph_=e" ["𐨥𐨹𐨸𐨅"])
+ ("ph_=o" ["𐨥𐨹𐨸𐨆"])
+
+ ("b" ["𐨦𐨿"])
+ ("ba" ["𐨦"])
+ ("bi" ["𐨦𐨁"])
+ ("bu" ["𐨦𐨂"])
+ ("bR" ["𐨦𐨃"])
+ ("be" ["𐨦𐨅"])
+ ("bo" ["𐨦𐨆"])
+ ("b_" ["𐨦𐨹𐨿"])
+ ("b_a" ["𐨦𐨹"])
+ ("b_i" ["𐨦𐨹𐨁"])
+ ("b_u" ["𐨦𐨹𐨂"])
+ ("b_R" ["𐨦𐨹𐨃"])
+ ("b_e" ["𐨦𐨹𐨅"])
+ ("b_o" ["𐨦𐨹𐨆"])
+ ("b=" ["𐨦𐨿𐨸"])
+ ("b=a" ["𐨦𐨸"])
+ ("b=i" ["𐨦𐨸𐨁"])
+ ("b=u" ["𐨦𐨸𐨂"])
+ ("b=R" ["𐨦𐨸𐨃"])
+ ("b=e" ["𐨦𐨸𐨅"])
+ ("b=o" ["𐨦𐨸𐨆"])
+ ("b_=" ["𐨦𐨹𐨿𐨸"])
+ ("b_=a" ["𐨦𐨹𐨸"])
+ ("b_=i" ["𐨦𐨹𐨸𐨁"])
+ ("b_=u" ["𐨦𐨹𐨸𐨂"])
+ ("b_=R" ["𐨦𐨹𐨸𐨃"])
+ ("b_=e" ["𐨦𐨹𐨸𐨅"])
+ ("b_=o" ["𐨦𐨹𐨸𐨆"])
+
+ ("bh" ["𐨧𐨿"])
+ ("bha" ["𐨧"])
+ ("bhi" ["𐨧𐨁"])
+ ("bhu" ["𐨧𐨂"])
+ ("bhR" ["𐨧𐨃"])
+ ("bhe" ["𐨧𐨅"])
+ ("bho" ["𐨧𐨆"])
+ ("bh_" ["𐨧𐨹𐨿"])
+ ("bh_a" ["𐨧𐨹"])
+ ("bh_i" ["𐨧𐨹𐨁"])
+ ("bh_u" ["𐨧𐨹𐨂"])
+ ("bh_R" ["𐨧𐨹𐨃"])
+ ("bh_e" ["𐨧𐨹𐨅"])
+ ("bh_o" ["𐨧𐨹𐨆"])
+ ("bh=" ["𐨧𐨿𐨸"])
+ ("bh=a" ["𐨧𐨸"])
+ ("bh=i" ["𐨧𐨸𐨁"])
+ ("bh=u" ["𐨧𐨸𐨂"])
+ ("bh=R" ["𐨧𐨸𐨃"])
+ ("bh=e" ["𐨧𐨸𐨅"])
+ ("bh=o" ["𐨧𐨸𐨆"])
+ ("bh_=" ["𐨧𐨹𐨿𐨸"])
+ ("bh_=a" ["𐨧𐨹𐨸"])
+ ("bh_=i" ["𐨧𐨹𐨸𐨁"])
+ ("bh_=u" ["𐨧𐨹𐨸𐨂"])
+ ("bh_=R" ["𐨧𐨹𐨸𐨃"])
+ ("bh_=e" ["𐨧𐨹𐨸𐨅"])
+ ("bh_=o" ["𐨧𐨹𐨸𐨆"])
+
+ ("m" ["𐨨𐨿"])
+ ("ma" ["𐨨"])
+ ("mi" ["𐨨𐨁"])
+ ("mu" ["𐨨𐨂"])
+ ("mR" ["𐨨𐨃"])
+ ("me" ["𐨨𐨅"])
+ ("mo" ["𐨨𐨆"])
+ ("m_" ["𐨨𐨹𐨿"])
+ ("m_a" ["𐨨𐨹"])
+ ("m_i" ["𐨨𐨹𐨁"])
+ ("m_u" ["𐨨𐨹𐨂"])
+ ("m_R" ["𐨨𐨹𐨃"])
+ ("m_e" ["𐨨𐨹𐨅"])
+ ("m_o" ["𐨨𐨹𐨆"])
+ ("m=" ["𐨨𐨿𐨸"])
+ ("m=a" ["𐨨𐨸"])
+ ("m=i" ["𐨨𐨸𐨁"])
+ ("m=u" ["𐨨𐨸𐨂"])
+ ("m=R" ["𐨨𐨸𐨃"])
+ ("m=e" ["𐨨𐨸𐨅"])
+ ("m=o" ["𐨨𐨸𐨆"])
+ ("m_=" ["𐨨𐨹𐨿𐨸"])
+ ("m_=a" ["𐨨𐨹𐨸"])
+ ("m_=i" ["𐨨𐨹𐨸𐨁"])
+ ("m_=u" ["𐨨𐨹𐨸𐨂"])
+ ("m_=R" ["𐨨𐨹𐨸𐨃"])
+ ("m_=e" ["𐨨𐨹𐨸𐨅"])
+ ("m_=o" ["𐨨𐨹𐨸𐨆"])
+
+ ("y" ["𐨩𐨿"])
+ ("ya" ["𐨩"])
+ ("yi" ["𐨩𐨁"])
+ ("yu" ["𐨩𐨂"])
+ ("yR" ["𐨩𐨃"])
+ ("ye" ["𐨩𐨅"])
+ ("yo" ["𐨩𐨆"])
+ ("y_" ["𐨩𐨹𐨿"])
+ ("y_a" ["𐨩𐨹"])
+ ("y_i" ["𐨩𐨹𐨁"])
+ ("y_u" ["𐨩𐨹𐨂"])
+ ("y_R" ["𐨩𐨹𐨃"])
+ ("y_e" ["𐨩𐨹𐨅"])
+ ("y_o" ["𐨩𐨹𐨆"])
+ ("y=" ["𐨩𐨿𐨸"])
+ ("y=a" ["𐨩𐨸"])
+ ("y=i" ["𐨩𐨸𐨁"])
+ ("y=u" ["𐨩𐨸𐨂"])
+ ("y=R" ["𐨩𐨸𐨃"])
+ ("y=e" ["𐨩𐨸𐨅"])
+ ("y=o" ["𐨩𐨸𐨆"])
+ ("y_=" ["𐨩𐨹𐨿𐨸"])
+ ("y_=a" ["𐨩𐨹𐨸"])
+ ("y_=i" ["𐨩𐨹𐨸𐨁"])
+ ("y_=u" ["𐨩𐨹𐨸𐨂"])
+ ("y_=R" ["𐨩𐨹𐨸𐨃"])
+ ("y_=e" ["𐨩𐨹𐨸𐨅"])
+ ("y_=o" ["𐨩𐨹𐨸𐨆"])
+
+ ("r" ["𐨪𐨿"])
+ ("ra" ["𐨪"])
+ ("ri" ["𐨪𐨁"])
+ ("ru" ["𐨪𐨂"])
+ ("rR" ["𐨪𐨃"])
+ ("re" ["𐨪𐨅"])
+ ("ro" ["𐨪𐨆"])
+ ("r_" ["𐨪𐨹𐨿"])
+ ("r_a" ["𐨪𐨹"])
+ ("r_i" ["𐨪𐨹𐨁"])
+ ("r_u" ["𐨪𐨹𐨂"])
+ ("r_R" ["𐨪𐨹𐨃"])
+ ("r_e" ["𐨪𐨹𐨅"])
+ ("r_o" ["𐨪𐨹𐨆"])
+ ("r=" ["𐨪𐨿𐨸"])
+ ("r=a" ["𐨪𐨸"])
+ ("r=i" ["𐨪𐨸𐨁"])
+ ("r=u" ["𐨪𐨸𐨂"])
+ ("r=R" ["𐨪𐨸𐨃"])
+ ("r=e" ["𐨪𐨸𐨅"])
+ ("r=o" ["𐨪𐨸𐨆"])
+ ("r_=" ["𐨪𐨹𐨿𐨸"])
+ ("r_=a" ["𐨪𐨹𐨸"])
+ ("r_=i" ["𐨪𐨹𐨸𐨁"])
+ ("r_=u" ["𐨪𐨹𐨸𐨂"])
+ ("r_=R" ["𐨪𐨹𐨸𐨃"])
+ ("r_=e" ["𐨪𐨹𐨸𐨅"])
+ ("r_=o" ["𐨪𐨹𐨸𐨆"])
+
+ ("l" ["𐨫𐨿"])
+ ("la" ["𐨫"])
+ ("li" ["𐨫𐨁"])
+ ("lu" ["𐨫𐨂"])
+ ("lR" ["𐨫𐨃"])
+ ("le" ["𐨫𐨅"])
+ ("lo" ["𐨫𐨆"])
+ ("l_" ["𐨫𐨹𐨿"])
+ ("l_a" ["𐨫𐨹"])
+ ("l_i" ["𐨫𐨹𐨁"])
+ ("l_u" ["𐨫𐨹𐨂"])
+ ("l_R" ["𐨫𐨹𐨃"])
+ ("l_e" ["𐨫𐨹𐨅"])
+ ("l_o" ["𐨫𐨹𐨆"])
+ ("l=" ["𐨫𐨿𐨸"])
+ ("l=a" ["𐨫𐨸"])
+ ("l=i" ["𐨫𐨸𐨁"])
+ ("l=u" ["𐨫𐨸𐨂"])
+ ("l=R" ["𐨫𐨸𐨃"])
+ ("l=e" ["𐨫𐨸𐨅"])
+ ("l=o" ["𐨫𐨸𐨆"])
+ ("l_=" ["𐨫𐨹𐨿𐨸"])
+ ("l_=a" ["𐨫𐨹𐨸"])
+ ("l_=i" ["𐨫𐨹𐨸𐨁"])
+ ("l_=u" ["𐨫𐨹𐨸𐨂"])
+ ("l_=R" ["𐨫𐨹𐨸𐨃"])
+ ("l_=e" ["𐨫𐨹𐨸𐨅"])
+ ("l_=o" ["𐨫𐨹𐨸𐨆"])
+
+ ("v" ["𐨬𐨿"])
+ ("va" ["𐨬"])
+ ("vi" ["𐨬𐨁"])
+ ("vu" ["𐨬𐨂"])
+ ("vR" ["𐨬𐨃"])
+ ("ve" ["𐨬𐨅"])
+ ("vo" ["𐨬𐨆"])
+ ("v_" ["𐨬𐨹𐨿"])
+ ("v_a" ["𐨬𐨹"])
+ ("v_i" ["𐨬𐨹𐨁"])
+ ("v_u" ["𐨬𐨹𐨂"])
+ ("v_R" ["𐨬𐨹𐨃"])
+ ("v_e" ["𐨬𐨹𐨅"])
+ ("v_o" ["𐨬𐨹𐨆"])
+ ("v=" ["𐨬𐨿𐨸"])
+ ("v=a" ["𐨬𐨸"])
+ ("v=i" ["𐨬𐨸𐨁"])
+ ("v=u" ["𐨬𐨸𐨂"])
+ ("v=R" ["𐨬𐨸𐨃"])
+ ("v=e" ["𐨬𐨸𐨅"])
+ ("v=o" ["𐨬𐨸𐨆"])
+ ("v_=" ["𐨬𐨹𐨿𐨸"])
+ ("v_=a" ["𐨬𐨹𐨸"])
+ ("v_=i" ["𐨬𐨹𐨸𐨁"])
+ ("v_=u" ["𐨬𐨹𐨸𐨂"])
+ ("v_=R" ["𐨬𐨹𐨸𐨃"])
+ ("v_=e" ["𐨬𐨹𐨸𐨅"])
+ ("v_=o" ["𐨬𐨹𐨸𐨆"])
+
+ ("z" ["𐨭𐨿"])
+ ("za" ["𐨭"])
+ ("zi" ["𐨭𐨁"])
+ ("zu" ["𐨭𐨂"])
+ ("z" ["𐨭𐨃"])
+ ("ze" ["𐨭𐨅"])
+ ("zo" ["𐨭𐨆"])
+ ("z_" ["𐨭𐨹𐨿"])
+ ("z_a" ["𐨭𐨹"])
+ ("z_i" ["𐨭𐨹𐨁"])
+ ("z_u" ["𐨭𐨹𐨂"])
+ ("z_R" ["𐨭𐨹𐨃"])
+ ("z_e" ["𐨭𐨹𐨅"])
+ ("z_o" ["𐨭𐨹𐨆"])
+ ("z=" ["𐨭𐨿𐨸"])
+ ("z=a" ["𐨭𐨸"])
+ ("z=i" ["𐨭𐨸𐨁"])
+ ("z=u" ["𐨭𐨸𐨂"])
+ ("z=R" ["𐨭𐨸𐨃"])
+ ("z=e" ["𐨭𐨸𐨅"])
+ ("z=o" ["𐨭𐨸𐨆"])
+ ("z_=" ["𐨭𐨹𐨿𐨸"])
+ ("z_=a" ["𐨭𐨹𐨸"])
+ ("z_=i" ["𐨭𐨹𐨸𐨁"])
+ ("z_=u" ["𐨭𐨹𐨸𐨂"])
+ ("z_=R" ["𐨭𐨹𐨸𐨃"])
+ ("z_=e" ["𐨭𐨹𐨸𐨅"])
+ ("z_=o" ["𐨭𐨹𐨸𐨆"])
+
+ ("S" ["𐨮𐨿"])
+ ("Sa" ["𐨮"])
+ ("Si" ["𐨮𐨁"])
+ ("Su" ["𐨮𐨂"])
+ ("SR" ["𐨮𐨃"])
+ ("Se" ["𐨮𐨅"])
+ ("So" ["𐨮𐨆"])
+ ("S_" ["𐨮𐨹𐨿"])
+ ("S_a" ["𐨮𐨹"])
+ ("S_i" ["𐨮𐨹𐨁"])
+ ("S_u" ["𐨮𐨹𐨂"])
+ ("S_R" ["𐨮𐨹𐨃"])
+ ("S_e" ["𐨮𐨹𐨅"])
+ ("S_o" ["𐨮𐨹𐨆"])
+ ("S=" ["𐨮𐨿𐨸"])
+ ("S=a" ["𐨮𐨸"])
+ ("S=i" ["𐨮𐨸𐨁"])
+ ("S=u" ["𐨮𐨸𐨂"])
+ ("S=R" ["𐨮𐨸𐨃"])
+ ("S=e" ["𐨮𐨸𐨅"])
+ ("S=o" ["𐨮𐨸𐨆"])
+ ("S_=" ["𐨮𐨹𐨿𐨸"])
+ ("S_=a" ["𐨮𐨹𐨸"])
+ ("S_=i" ["𐨮𐨹𐨸𐨁"])
+ ("S_=u" ["𐨮𐨹𐨸𐨂"])
+ ("S_=R" ["𐨮𐨹𐨸𐨃"])
+ ("S_=e" ["𐨮𐨹𐨸𐨅"])
+ ("S_=o" ["𐨮𐨹𐨸𐨆"])
+
+ ("s" ["𐨯𐨿"])
+ ("sa" ["𐨯"])
+ ("si" ["𐨯𐨁"])
+ ("su" ["𐨯𐨂"])
+ ("sR" ["𐨯𐨃"])
+ ("se" ["𐨯𐨅"])
+ ("so" ["𐨯𐨆"])
+ ("s_" ["𐨯𐨹𐨿"])
+ ("s_a" ["𐨯𐨹"])
+ ("s_i" ["𐨯𐨹𐨁"])
+ ("s_u" ["𐨯𐨹𐨂"])
+ ("s_R" ["𐨯𐨹𐨃"])
+ ("s_e" ["𐨯𐨹𐨅"])
+ ("s_o" ["𐨯𐨹𐨆"])
+ ("s=" ["𐨯𐨿𐨸"])
+ ("s=a" ["𐨯𐨸"])
+ ("s=i" ["𐨯𐨸𐨁"])
+ ("s=u" ["𐨯𐨸𐨂"])
+ ("s=R" ["𐨯𐨸𐨃"])
+ ("s=e" ["𐨯𐨸𐨅"])
+ ("s=o" ["𐨯𐨸𐨆"])
+ ("s_=" ["𐨯𐨹𐨿𐨸"])
+ ("s_=a" ["𐨯𐨹𐨸"])
+ ("s_=i" ["𐨯𐨹𐨸𐨁"])
+ ("s_=u" ["𐨯𐨹𐨸𐨂"])
+ ("s_=R" ["𐨯𐨹𐨸𐨃"])
+ ("s_=e" ["𐨯𐨹𐨸𐨅"])
+ ("s_=o" ["𐨯𐨹𐨸𐨆"])
+
+ ("h" ["𐨱𐨿"])
+ ("ha" ["𐨱"])
+ ("hi" ["𐨱𐨁"])
+ ("hu" ["𐨱𐨂"])
+ ("hR" ["𐨱𐨃"])
+ ("he" ["𐨱𐨅"])
+ ("ho" ["𐨱𐨆"])
+ ("h_" ["𐨱𐨹𐨿"])
+ ("h_a" ["𐨱𐨹"])
+ ("h_i" ["𐨱𐨹𐨁"])
+ ("h_u" ["𐨱𐨹𐨂"])
+ ("h_R" ["𐨱𐨹𐨃"])
+ ("h_e" ["𐨱𐨹𐨅"])
+ ("h_o" ["𐨱𐨹𐨆"])
+ ("h=" ["𐨱𐨿𐨸"])
+ ("h=a" ["𐨱𐨸"])
+ ("h=i" ["𐨱𐨸𐨁"])
+ ("h=u" ["𐨱𐨸𐨂"])
+ ("h=R" ["𐨱𐨸𐨃"])
+ ("h=e" ["𐨱𐨸𐨅"])
+ ("h=o" ["𐨱𐨸𐨆"])
+ ("h_=" ["𐨱𐨹𐨿𐨸"])
+ ("h_=a" ["𐨱𐨹𐨸"])
+ ("h_=i" ["𐨱𐨹𐨸𐨁"])
+ ("h_=u" ["𐨱𐨹𐨸𐨂"])
+ ("h_=R" ["𐨱𐨹𐨸𐨃"])
+ ("h_=e" ["𐨱𐨹𐨸𐨅"])
+ ("h_=o" ["𐨱𐨹𐨸𐨆"])
+
+ ("k'" ["𐨲𐨿"])
+ ("k'a" ["𐨲"])
+ ("k'i" ["𐨲𐨁"])
+ ("k'u" ["𐨲𐨂"])
+ ("k'R" ["𐨲𐨃"])
+ ("k'e" ["𐨲𐨅"])
+ ("k'o" ["𐨲𐨆"])
+ ("k'_" ["𐨲𐨹𐨿"])
+ ("k'_a" ["𐨲𐨹"])
+ ("k'_i" ["𐨲𐨹𐨁"])
+ ("k'_u" ["𐨲𐨹𐨂"])
+ ("k'_R" ["𐨲𐨹𐨃"])
+ ("k'_e" ["𐨲𐨹𐨅"])
+ ("k'_o" ["𐨲𐨹𐨆"])
+ ("k'=" ["𐨲𐨿𐨸"])
+ ("k'=a" ["𐨲𐨸"])
+ ("k'=i" ["𐨲𐨸𐨁"])
+ ("k'=u" ["𐨲𐨸𐨂"])
+ ("k'=R" ["𐨲𐨸𐨃"])
+ ("k'=e" ["𐨲𐨸𐨅"])
+ ("k'=o" ["𐨲𐨸𐨆"])
+ ("k'_=" ["𐨲𐨹𐨿𐨸"])
+ ("k'_=a" ["𐨲𐨹𐨸"])
+ ("k'_=i" ["𐨲𐨹𐨸𐨁"])
+ ("k'_=u" ["𐨲𐨹𐨸𐨂"])
+ ("k'_=R" ["𐨲𐨹𐨸𐨃"])
+ ("k'_=e" ["𐨲𐨹𐨸𐨅"])
+ ("k'_=o" ["𐨲𐨹𐨸𐨆"])
+
+ ("T'" ["𐨴𐨿"])
+ ("T'a" ["𐨴"])
+ ("T'i" ["𐨴𐨁"])
+ ("T'u" ["𐨴𐨂"])
+ ("T'R" ["𐨴𐨃"])
+ ("T'e" ["𐨴𐨅"])
+ ("T'o" ["𐨴𐨆"])
+ ("T'_" ["𐨴𐨹𐨿"])
+ ("T'_a" ["𐨴𐨹"])
+ ("T'_i" ["𐨴𐨹𐨁"])
+ ("T'_u" ["𐨴𐨹𐨂"])
+ ("T'_R" ["𐨴𐨹𐨃"])
+ ("T'_e" ["𐨴𐨹𐨅"])
+ ("T'_o" ["𐨴𐨹𐨆"])
+ ("T'=" ["𐨴𐨿𐨸"])
+ ("T'=a" ["𐨴𐨸"])
+ ("T'=i" ["𐨴𐨸𐨁"])
+ ("T'=u" ["𐨴𐨸𐨂"])
+ ("T'=R" ["𐨴𐨸𐨃"])
+ ("T'=e" ["𐨴𐨸𐨅"])
+ ("T'=o" ["𐨴𐨸𐨆"])
+ ("T'_=" ["𐨴𐨹𐨿𐨸"])
+ ("T'_=a" ["𐨴𐨹𐨸"])
+ ("T'_=i" ["𐨴𐨹𐨸𐨁"])
+ ("T'_=u" ["𐨴𐨹𐨸𐨂"])
+ ("T'_=R" ["𐨴𐨹𐨸𐨃"])
+ ("T'_=e" ["𐨴𐨹𐨸𐨅"])
+ ("T'_=o" ["𐨴𐨹𐨸𐨆"])
+
+ ("Th'" ["𐨳𐨿"])
+ ("Th'a" ["𐨳"])
+ ("Th'i" ["𐨳𐨁"])
+ ("Th'u" ["𐨳𐨂"])
+ ("Th'R" ["𐨳𐨃"])
+ ("Th'e" ["𐨳𐨅"])
+ ("Th'o" ["𐨳𐨆"])
+ ("Th'_" ["𐨳𐨹𐨿"])
+ ("Th'_a" ["𐨳𐨹"])
+ ("Th'_i" ["𐨳𐨹𐨁"])
+ ("Th'_u" ["𐨳𐨹𐨂"])
+ ("Th'_R" ["𐨳𐨹𐨃"])
+ ("Th'_e" ["𐨳𐨹𐨅"])
+ ("Th'_o" ["𐨳𐨹𐨆"])
+ ("Th'=" ["𐨳𐨿𐨸"])
+ ("Th'=a" ["𐨳𐨸"])
+ ("Th'=i" ["𐨳𐨸𐨁"])
+ ("Th'=u" ["𐨳𐨸𐨂"])
+ ("Th'=R" ["𐨳𐨸𐨃"])
+ ("Th'=e" ["𐨳𐨸𐨅"])
+ ("Th'=o" ["𐨳𐨸𐨆"])
+ ("Th'_=" ["𐨳𐨹𐨿𐨸"])
+ ("Th'_=a" ["𐨳𐨹𐨸"])
+ ("Th'_=i" ["𐨳𐨹𐨸𐨁"])
+ ("Th'_=u" ["𐨳𐨹𐨸𐨂"])
+ ("Th'_=R" ["𐨳𐨹𐨸𐨃"])
+ ("Th'_=e" ["𐨳𐨹𐨸𐨅"])
+ ("Th'_=o" ["𐨳𐨹𐨸𐨆"])
+
+ ("vh" ["𐨵𐨿"])
+ ("vha" ["𐨵"])
+ ("vhi" ["𐨵𐨁"])
+ ("vhu" ["𐨵𐨂"])
+ ("vhR" ["𐨵𐨃"])
+ ("vhe" ["𐨵𐨅"])
+ ("vho" ["𐨵𐨆"])
+ ("vh_" ["𐨵𐨹𐨿"])
+ ("vh_a" ["𐨵𐨹"])
+ ("vh_i" ["𐨵𐨹𐨁"])
+ ("vh_u" ["𐨵𐨹𐨂"])
+ ("vh_R" ["𐨵𐨹𐨃"])
+ ("vh_e" ["𐨵𐨹𐨅"])
+ ("vh_o" ["𐨵𐨹𐨆"])
+ ("vh=" ["𐨵𐨿𐨸"])
+ ("vh=a" ["𐨵𐨸"])
+ ("vh=i" ["𐨵𐨸𐨁"])
+ ("vh=u" ["𐨵𐨸𐨂"])
+ ("vh=R" ["𐨵𐨸𐨃"])
+ ("vh=e" ["𐨵𐨸𐨅"])
+ ("vh=o" ["𐨵𐨸𐨆"])
+ ("vh_=" ["𐨵𐨹𐨿𐨸"])
+ ("vh_=a" ["𐨵𐨹𐨸"])
+ ("vh_=i" ["𐨵𐨹𐨸𐨁"])
+ ("vh_=u" ["𐨵𐨹𐨸𐨂"])
+ ("vh_=R" ["𐨵𐨹𐨸𐨃"])
+ ("vh_=e" ["𐨵𐨹𐨸𐨅"])
+ ("vh_=o" ["𐨵𐨹𐨸𐨆"])
+
+ ("M" ?𐨎)
+ ("H" ?𐨏)
+ ("\\" ?𐨌)
+ (";;" ?𐨍)
+
+ ("1" ?𐩀)
+ ("2" ?𐩁)
+ ("3" ?𐩂)
+ ("4" ?𐩃)
+ ("10" ?𐩄)
+ ("20" ?𐩅)
+ ("100" ?𐩆)
+ ("1000" ?𐩇)
+
+ (".." ?𐩐)
+ (".o" ?𐩑)
+ (".O" ?𐩒)
+ (".E" ?𐩓)
+ (".X" ?𐩔)
+ (".L" ?𐩕)
+ (".|" ?𐩖)
+ (".||" ?𐩗)
+ (".=" ?𐩘))
+
+(provide 'misc-lang)
+;;; misc-lang.el ends here
diff --git a/lisp/leim/quail/persian.el b/lisp/leim/quail/persian.el
index 61428c94f0d..07d006c2a48 100644
--- a/lisp/leim/quail/persian.el
+++ b/lisp/leim/quail/persian.el
@@ -23,7 +23,7 @@
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
-;;
+
;; This file contains a collection of input methods for
;; Persian languages (Farsi, Urdu, Pashto/Afghanic, ...)
;;
@@ -402,7 +402,7 @@
;;;;;;;;;;; isiri-6219 Table 6 -- جدول ۶ - حروِفِ عربی
("F" ?إ)
- ("D" ?\u0671) ;; (ucs-insert #x0671)ٱ named: حرفِ الفِ وصل
+ ("D" ?\u0671) ;; (insert-char #x0671)ٱ named: حرفِ الفِ وصل
("K" ?ك) ;; Arabic kaf
("Th" ?ة) ;; ta marbuteh
("Y" ?ي)
@@ -421,40 +421,40 @@
("8" ?۸)
("9" ?۹)
- ("\\/" ?\u066B) ;; (ucs-insert #x066B)٫ named: ممیزِ فارسی
- ("\\," ?\u066C) ;; (ucs-insert #x066C)٬ named: جداکننده‌ی هزارهای فارسی
- ("%" ?\u066A) ;; (ucs-insert #x066A)٪ named: درصدِ فارسی
- ("+" ?\u002B) ;; (ucs-insert #x002B)+ named: علامتِ به‌اضافه
- ("-" ?\u2212) ;; (ucs-insert #x2212)− named: علامتِ منها
- ("\\*" ?\u00D7) ;; (ucs-insert #x00D7)× named: علامتِ ضرب
- ("\\-" ?\u00F7) ;; (ucs-insert #x00F7)÷ named: علامتِ تقسیم
- ("<" ?\u003C) ;; (ucs-insert #x003C)< named: علامتِ کوچکتر
- ("=" ?\u003D) ;; (ucs-insert #x003D)= named: علامتِ مساوی
- (">" ?\u003E) ;; (ucs-insert #x003E)> named: علامتِ بزرگتر
+ ("\\/" ?\u066B) ;; (insert-char #x066B)٫ named: ممیزِ فارسی
+ ("\\," ?\u066C) ;; (insert-char #x066C)٬ named: جداکننده‌ی هزارهای فارسی
+ ("%" ?\u066A) ;; (insert-char #x066A)٪ named: درصدِ فارسی
+ ("+" ?\u002B) ;; (insert-char #x002B)+ named: علامتِ به‌اضافه
+ ("-" ?\u2212) ;; (insert-char #x2212)− named: علامتِ منها
+ ("\\*" ?\u00D7) ;; (insert-char #x00D7)× named: علامتِ ضرب
+ ("\\-" ?\u00F7) ;; (insert-char #x00F7)÷ named: علامتِ تقسیم
+ ("<" ?\u003C) ;; (insert-char #x003C)< named: علامتِ کوچکتر
+ ("=" ?\u003D) ;; (insert-char #x003D)= named: علامتِ مساوی
+ (">" ?\u003E) ;; (insert-char #x003E)> named: علامتِ بزرگتر
;;;;;;;;;;; isiri-6219 Table 2 -- جدول ۲ - علائم نقطه گذاریِ مشترک
;;; Space
("." ?.) ;;
- (":" ?\u003A) ;; (ucs-insert #x003A): named:
- ("!" ?\u0021) ;; (ucs-insert #x0021)! named:
- ("\\." ?\u2026) ;; (ucs-insert #x2026)… named:
- ("\\-" ?\u2010) ;; (ucs-insert #x2010)‐ named:
- ("-" ?\u002D) ;; (ucs-insert #x002D)- named:
+ (":" ?\u003A) ;; (insert-char #x003A): named:
+ ("!" ?\u0021) ;; (insert-char #x0021)! named:
+ ("\\." ?\u2026) ;; (insert-char #x2026)… named:
+ ("\\-" ?\u2010) ;; (insert-char #x2010)‐ named:
+ ("-" ?\u002D) ;; (insert-char #x002D)- named:
("|" ?|)
;;("\\\\" ?\)
("//" ?/)
- ("*" ?\u002A) ;; (ucs-insert #x002A)* named:
- ("(" ?\u0028) ;; (ucs-insert #x0028)( named:
- (")" ?\u0029) ;; (ucs-insert #x0029)) named:
- ("[" ?\u005B) ;; (ucs-insert #x005B)[ named:
- ("[" ?\u005D) ;; (ucs-insert #x005D)] named:
- ("{" ?\u007B) ;; (ucs-insert #x007B){ named:
- ("}" ?\u007D) ;; (ucs-insert #x007D)} named:
- ("\\<" ?\u00AB) ;; (ucs-insert #x00AB)« named:
- ("\\>" ?\u00BB) ;; (ucs-insert #x00BB)» named:
- ("N" ?\u00AB) ;; (ucs-insert #x00AB)« named:
- ("M" ?\u00BB) ;; (ucs-insert #x00BB)» named:
+ ("*" ?\u002A) ;; (insert-char #x002A)* named:
+ ("(" ?\u0028) ;; (insert-char #x0028)( named:
+ (")" ?\u0029) ;; (insert-char #x0029)) named:
+ ("[" ?\u005B) ;; (insert-char #x005B)[ named:
+ ("[" ?\u005D) ;; (insert-char #x005D)] named:
+ ("{" ?\u007B) ;; (insert-char #x007B){ named:
+ ("}" ?\u007D) ;; (insert-char #x007D)} named:
+ ("\\<" ?\u00AB) ;; (insert-char #x00AB)« named:
+ ("\\>" ?\u00BB) ;; (insert-char #x00BB)» named:
+ ("N" ?\u00AB) ;; (insert-char #x00AB)« named:
+ ("M" ?\u00BB) ;; (insert-char #x00BB)» named:
;;;;;;;;;;; isiri-6219 Table 3 -- جدول ۳ - علائم نقطه گذاریِ فارسی
("," ?،) ;; farsi
@@ -466,20 +466,20 @@
;;;;;;;;;;; isiri-6219 Table 1 -- جدول ۱ - نویسه‌های کنترلی
;; LF
;; CR
- ("&zwnj;" ?\u200C) ;; (ucs-insert #x200C)‌ named: فاصله‌ی مجازی
+ ("&zwnj;" ?\u200C) ;; (insert-char #x200C)‌ named: فاصله‌ی مجازی
("/" ?\u200C) ;;
- ("&zwj;" ?\u200D) ;; (ucs-insert #x200D)‍ named: اتصالِ مجازی
+ ("&zwj;" ?\u200D) ;; (insert-char #x200D)‍ named: اتصالِ مجازی
("J" ?\u200D) ;;
- ("&lrm;" ?\u200E) ;; (ucs-insert #x200E)‎ named: نشانه‌ی چپ‌به‌راست
- ("&rlm;" ?\u200F) ;; (ucs-insert #x200F)‏ named: نشانه‌ی راست‌به‌چپ
- ("&ls;" ?\u2028) ;; (ucs-insert #x2028)
 named: جداکننده‌ی سطرها
- ("&ps;" ?\u2028) ;; (ucs-insert #x2029)
 named: جداکننده‌ی بندها
- ("&lre;" ?\u202A) ;; (ucs-insert #x202A)‪ named: زیرمتنِ چپ‌به‌راست
- ("&rle;" ?\u202B) ;; (ucs-insert #x202B) named: زیرمتنِ راست‌به‌چپ
- ("&pdf;" ?\u202C) ;; (ucs-insert #x202C) named: پایانِ زیرمتن
- ("&lro;" ?\u202D) ;; (ucs-insert #x202D) named: زیرمتنِ اکیداً چپ‌به‌راست
- ("&rlo;" ?\u202D) ;; (ucs-insert #x202E) named: زیرمتنِ اکیداً راست‌به‌چپ
- ("&bom;" ?\uFEFF) ;; (ucs-insert #xFEFF) named: نشانه‌ی ترتیبِ بایت‌ها
+ ("&lrm;" ?\u200E) ;; (insert-char #x200E)‎ named: نشانه‌ی چپ‌به‌راست
+ ("&rlm;" ?\u200F) ;; (insert-char #x200F)‏ named: نشانه‌ی راست‌به‌چپ
+ ("&ls;" ?\u2028) ;; (insert-char #x2028)
 named: جداکننده‌ی سطرها
+ ("&ps;" ?\u2028) ;; (insert-char #x2029)
 named: جداکننده‌ی بندها
+ ("&lre;" ?\u202A) ;; (insert-char #x202A)‪ named: زیرمتنِ چپ‌به‌راست
+ ("&rle;" ?\u202B) ;; (insert-char #x202B) named: زیرمتنِ راست‌به‌چپ
+ ("&pdf;" ?\u202C) ;; (insert-char #x202C) named: پایانِ زیرمتن
+ ("&lro;" ?\u202D) ;; (insert-char #x202D) named: زیرمتنِ اکیداً چپ‌به‌راست
+ ("&rlo;" ?\u202D) ;; (insert-char #x202E) named: زیرمتنِ اکیداً راست‌به‌چپ
+ ("&bom;" ?\uFEFF) ;; (insert-char #xFEFF) named: نشانه‌ی ترتیبِ بایت‌ها
;;;;;;;;;;; isiri-6219 Table 7 -- جدول ۷ - نشانه‌هایِ فارسی
@@ -491,14 +491,14 @@
("O" ?ٌ) ;; دو پيش فارسى -- تنوين رفع
("~" ?ّ) ;; tashdid ;; تشديد فارسى
("@" ?ْ) ;; ساکن فارسى
- ("U" ?\u0653) ;; (ucs-insert #x0653)ٓ named: مدِ فارسی
+ ("U" ?\u0653) ;; (insert-char #x0653)ٓ named: مدِ فارسی
("`" ?ٔ) ;; همزه فارسى بالا
- ("C" ?\u0655) ;; (ucs-insert #x0655)ٕ named: همزه فارسى پایین
- ("$" ?\u0670) ;; (ucs-insert #x0670)ٰ named: الفِ مقصوره‌ی فارسی
+ ("C" ?\u0655) ;; (insert-char #x0655)ٕ named: همزه فارسى پایین
+ ("$" ?\u0670) ;; (insert-char #x0670)ٰ named: الفِ مقصوره‌ی فارسی
;;;;;;;;;;; isiri-6219 Table 8 - Forbidden Characters -- جدول ۸ - نویسه‌هایِ ممنوع
-;; ;; he ye (ucs-insert 1728) (ucs-insert #x06c0) kills emacs-24.0.90
+;; ;; he ye (insert-char 1728) (insert-char #x06c0) kills emacs-24.0.90
;; arabic digits 0-9
@@ -508,7 +508,7 @@
("\\~" ?~)
("\\@" ?@)
("\\#" ?#)
- ("\\$" ?\uFDFC) ;; (ucs-insert #xFDFC)﷼ named:
+ ("\\$" ?\uFDFC) ;; (insert-char #xFDFC)﷼ named:
("\\^" ?^)
("\\1" ?1)
("\\2" ?2)
diff --git a/lisp/leim/quail/philippine.el b/lisp/leim/quail/philippine.el
new file mode 100644
index 00000000000..9afbdc354e3
--- /dev/null
+++ b/lisp/leim/quail/philippine.el
@@ -0,0 +1,152 @@
+;;; philippine.el --- Quail package for inputting Philippine characters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
+;; Keywords: multilingual, input method, i18n, Philippines
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Input methods for Philippine languages.
+
+;;; Code:
+
+(require 'quail)
+
+;; This input method supports languages like Tagalog, Hanunoo, Buhid and
+;; Tagbanwa, using the Baybayin script.
+(quail-define-package
+ "tagalog" "Tagalog" "ᜊ" nil "Tagalog phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?₱)
+ ("w" ?ᜏ)
+ ("r" ?ᜍ)
+ ("R" ?ᜟ)
+ ("t" ?ᜆ)
+ ("y" ?ᜌ)
+ ("u" ?ᜓ)
+ ("U" ?ᜂ)
+ ("i" ?ᜒ)
+ ("I" ?ᜁ)
+ ("p" ?ᜉ)
+ ("a" ?ᜀ)
+ ("s" ?ᜐ)
+ ("d" ?ᜇ)
+ ("f" ?᜔)
+ ("g" ?ᜄ)
+ ("h" ?ᜑ)
+ ("j" ?᜵)
+ ("J" ?᜶)
+ ("k" ?ᜃ)
+ ("l" ?ᜎ)
+ ("v" ?᜕)
+ ("b" ?ᜊ)
+ ("n" ?ᜈ)
+ ("N" ?ᜅ)
+ ("m" ?ᜋ))
+
+(quail-define-package
+ "hanunoo" "Hanunoo" "ᜱ" nil "Hanunoo phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?₱)
+ ("w" ?ᜯ)
+ ("r" ?ᜭ)
+ ("t" ?ᜦ)
+ ("y" ?ᜬ)
+ ("u" ?ᜳ)
+ ("U" ?ᜢ)
+ ("i" ?ᜲ)
+ ("I" ?ᜡ)
+ ("p" ?ᜩ)
+ ("a" ?ᜠ)
+ ("s" ?ᜰ)
+ ("d" ?ᜧ)
+ ("f" ?᜴)
+ ("g" ?ᜤ)
+ ("h" ?ᜱ)
+ ("j" ?᜵)
+ ("J" ?᜶)
+ ("k" ?ᜣ)
+ ("l" ?ᜮ)
+ ("b" ?ᜪ)
+ ("n" ?ᜨ)
+ ("N" ?ᜥ)
+ ("m" ?ᜫ))
+
+(quail-define-package
+ "buhid" "Buhid" "ᝊᝓ" nil "Buhid phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?₱)
+ ("w" ?ᝏ)
+ ("r" ?ᝍ)
+ ("t" ?ᝆ)
+ ("y" ?ᝌ)
+ ("u" ?ᝓ)
+ ("U" ?ᝂ)
+ ("i" ?ᝒ)
+ ("I" ?ᝁ)
+ ("p" ?ᝉ)
+ ("a" ?ᝀ)
+ ("s" ?ᝐ)
+ ("d" ?ᝇ)
+ ("g" ?ᝄ)
+ ("h" ?ᝑ)
+ ("j" ?᜵)
+ ("J" ?᜶)
+ ("k" ?ᝃ)
+ ("l" ?ᝎ)
+ ("b" ?ᝊ)
+ ("n" ?ᝈ)
+ ("N" ?ᝅ)
+ ("m" ?ᝋ))
+
+(quail-define-package
+ "tagbanwa" "Tagbanwa" "ᝦ" nil "Tagbanwa phonetic input method."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?₱)
+ ("w" ?ᝯ)
+ ("t" ?ᝦ)
+ ("y" ?ᝬ)
+ ("u" ?ᝳ)
+ ("U" ?ᝢ)
+ ("i" ?ᝲ)
+ ("I" ?ᝡ)
+ ("p" ?ᝩ)
+ ("a" ?ᝠ)
+ ("s" ?ᝰ)
+ ("d" ?ᝧ)
+ ("g" ?ᝤ)
+ ("j" ?᜵)
+ ("J" ?᜶)
+ ("k" ?ᝣ)
+ ("l" ?ᝮ)
+ ("b" ?ᝪ)
+ ("n" ?ᝨ)
+ ("N" ?ᝥ)
+ ("m" ?ᝫ))
+
+(provide 'philippine)
+;;; philippine.el ends here
diff --git a/lisp/leim/quail/symbol-ksc.el b/lisp/leim/quail/symbol-ksc.el
index 042465697a1..d440058902a 100644
--- a/lisp/leim/quail/symbol-ksc.el
+++ b/lisp/leim/quail/symbol-ksc.el
@@ -39,7 +39,7 @@
"한글심벌입력표:
【(】괄호열기【arrow】화살【sex】♂♀【index】첨자 【accent】악센트
【)】괄호닫기【music】음악【dot】점 【quote】따옴표【xtext】§※¶¡¿
- 【Unit】℃Å¢℉【math】수학기호【pic】상형문자【line】선문자
+ 【Unit】℃Å¢℉【math】수학기호【pic】상형문자【line】선문자
【unit】단위 【frac】분수 【textline】­―∥\∼
【wn】㈜【ks】㉿【No】№【㏇】㏇ 【dag】† 【ddag】‡【percent】‰
【am】㏂【pm】㏘【™】™【Tel】℡【won】₩ 【yen】¥ 【pound】£
@@ -65,7 +65,7 @@
("dot" "·‥…¨ː")
("quote" "、。〃‘’“”°′″´˝")
("textline" "­―∥\∼")
- ("Unit" "℃Å¢℉")
+ ("Unit" "℃Å¢℉")
("sex" "♂♀")
("accent" "~ˇ˘˚˙¸˛")
("percent" "‰")
diff --git a/lisp/linum.el b/lisp/linum.el
index e121618b69f..d491da52066 100644
--- a/lisp/linum.el
+++ b/lisp/linum.el
@@ -74,6 +74,9 @@ and you have to scroll or press \\[recenter-top-bottom] to update the numbers."
;;;###autoload
(define-minor-mode linum-mode
"Toggle display of line numbers in the left margin (Linum mode).
+This mode has been largely replaced by `display-line-numbers-mode'
+(which is much faster and has fewer interaction problems with other
+modes).
Linum mode is a buffer-local minor mode."
:lighter "" ; for desktop.el
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index 48058f40535..39481ab0684 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -157,38 +157,35 @@ documentation of `unload-feature' for details.")
;; mode, or proposed is not nil and not major-mode, and so we use it.
(funcall (or proposed 'fundamental-mode)))))))
+(defvar loadhist-unload-filename nil)
+
(cl-defgeneric loadhist-unload-element (x)
- "Unload an element from the `load-history'."
+ "Unload an element from the `load-history'.
+The variable `loadhist-unload-filename' holds the name of the file we're
+unloading."
(message "Unexpected element %S in load-history" x))
-;; In `load-history', the definition of a previously autoloaded
-;; function is represented by 2 entries: (t . SYMBOL) comes before
-;; (defun . SYMBOL) and says we should restore SYMBOL's autoload when
-;; we undefine it.
-;; So we use this auxiliary variable to keep track of the last (t . SYMBOL)
-;; that occurred.
-(defvar loadhist--restore-autoload nil
- "If non-nil, is a symbol for which to try to restore a previous autoload.")
-
-(cl-defmethod loadhist-unload-element ((x (head t)))
- (setq loadhist--restore-autoload (cdr x)))
-
-(defun loadhist--unload-function (x)
- (let ((fun (cdr x)))
- (when (fboundp fun)
- (when (fboundp 'ad-unadvise)
- (ad-unadvise fun))
- (let ((aload (get fun 'autoload)))
- (defalias fun
- (if (and aload (eq fun loadhist--restore-autoload))
- (cons 'autoload aload)
- nil)))))
- (setq loadhist--restore-autoload nil))
-
(cl-defmethod loadhist-unload-element ((x (head defun)))
- (loadhist--unload-function x))
-(cl-defmethod loadhist-unload-element ((x (head autoload)))
- (loadhist--unload-function x))
+ (let* ((fun (cdr x))
+ (hist (get fun 'function-history)))
+ (cond
+ ((null hist)
+ (defalias fun nil)
+ ;; Override the change that `defalias' just recorded.
+ (put fun 'function-history nil))
+ ((equal (car hist) loadhist-unload-filename)
+ (defalias fun (cadr hist))
+ ;; Set the history afterwards, to override the change that
+ ;; `defalias' records otherwise.
+ (put fun 'function-history (cddr hist)))
+ (t
+ ;; Unloading a file whose definition is "inactive" (i.e. has been
+ ;; overridden by another file): just remove it from the history,
+ ;; so future unloading of that other file has a chance to DTRT.
+ (let* ((tmp (plist-member hist loadhist-unload-filename))
+ (pos (- (length hist) (length tmp))))
+ (cl-assert (> pos 1))
+ (setcdr (nthcdr (- pos 2) hist) (cdr tmp)))))))
(cl-defmethod loadhist-unload-element ((_ (head require))) nil)
(cl-defmethod loadhist-unload-element ((_ (head defface))) nil)
@@ -257,6 +254,7 @@ something strange, such as redefining an Emacs function."
(prin1-to-string dependents) file))))
(let* ((unload-function-defs-list (feature-symbols feature))
(file (pop unload-function-defs-list))
+ (loadhist-unload-filename file)
(name (symbol-name feature))
(unload-hook (intern-soft (concat name "-unload-hook")))
(unload-func (intern-soft (concat name "-unload-function"))))
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 1be73a2090d..21a87dbd77b 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -128,6 +128,7 @@
(set-buffer "*scratch*")
(setq buffer-undo-list t)
+(load "emacs-lisp/debug-early")
(load "emacs-lisp/byte-run")
(load "emacs-lisp/backquote")
(load "subr")
@@ -195,11 +196,10 @@
(setq definition-prefixes new))
(load "button") ;After loaddefs, because of define-minor-mode!
-(load "emacs-lisp/nadvice")
(load "emacs-lisp/cl-preloaded")
+(load "emacs-lisp/oclosure") ;Used by cl-generic
(load "obarray") ;abbrev.el is implemented in terms of obarrays.
(load "abbrev") ;lisp-mode.el and simple.el use define-abbrev-table.
-(load "simple")
(load "help")
@@ -245,11 +245,16 @@
(load "language/khmer")
(load "language/burmese")
(load "language/cham")
+(load "language/philippine")
+(load "language/indonesian")
(load "indent")
(let ((max-specpdl-size (max max-specpdl-size 1800)))
;; A particularly demanding file to load; 1600 does not seem to be enough.
(load "emacs-lisp/cl-generic"))
+(load "simple")
+(load "emacs-lisp/seq")
+(load "emacs-lisp/nadvice")
(load "minibuffer") ;Needs cl-generic (and define-minor-mode).
(load "frame")
(load "startup")
@@ -342,10 +347,8 @@
(load "term/ns-win"))))
(if (featurep 'pgtk)
(progn
+ (load "pgtk-dnd")
(load "term/common-win")
- ;; Don't load ucs-normalize.el unless uni-*.el files were
- ;; already produced, because it needs uni-*.el files that might
- ;; not be built early enough during bootstrap.
(load "term/pgtk-win")))
(if (fboundp 'x-create-frame)
;; Do it after loading term/foo-win.el since the value of the
@@ -394,6 +397,9 @@
(message "Warning: Change in load-path due to site-load will be \
lost after dumping")))
+;; Used by `kill-buffer', for instance.
+(load "emacs-lisp/rmc")
+
;; Make sure default-directory is unibyte when dumping. This is
;; because we cannot decode and encode it correctly (since the locale
;; environment is not, and should not be, set up). default-directory
diff --git a/lisp/locate.el b/lisp/locate.el
index 95b66f275a1..20ef052184e 100644
--- a/lisp/locate.el
+++ b/lisp/locate.el
@@ -238,6 +238,8 @@ that is, with a prefix arg, you get the default behavior."
;; Functions
(defun locate-default-make-command-line (search-string)
+ (unless (executable-find locate-command)
+ (error "Can't find the %s command" locate-command))
(list locate-command search-string))
(defun locate-word-at-point ()
@@ -461,13 +463,11 @@ Specific `locate-mode' commands, such as \\[locate-find-directory],
do not work in subdirectories.
\\{locate-mode-map}"
- ;; Avoid clobbering this variable
- (make-local-variable 'dired-subdir-alist)
(setq default-directory "/"
buffer-read-only t)
(add-to-invisibility-spec '(dired . t))
(dired-alist-add-1 default-directory (point-min-marker))
- (setq-local dired-directory "/")
+ (setq dired-directory "/")
(setq-local dired-subdir-switches locate-ls-subdir-switches)
(setq dired-switches-alist nil)
;; This should support both Unix and Windoze style names
diff --git a/lisp/obsolete/longlines.el b/lisp/longlines.el
index 731f47794c9..6dc2f61ed96 100644
--- a/lisp/obsolete/longlines.el
+++ b/lisp/longlines.el
@@ -6,7 +6,6 @@
;; Alex Schroeder <alex@gnu.org>
;; Chong Yidong <cyd@stupidchicken.com>
;; Maintainer: emacs-devel@gnu.org
-;; Obsolete-since: 24.4
;; Keywords: convenience, wp
;; This file is part of GNU Emacs.
@@ -73,6 +72,10 @@ You can also enable the display temporarily, using the command
This is used when `longlines-show-hard-newlines' is on."
:type 'string)
+(defcustom longlines-breakpoint-chars " ;,|"
+ "A bag of separator chars for longlines."
+ :type 'string)
+
;;; Internal variables
(defvar longlines-wrap-beg nil)
@@ -115,7 +118,6 @@ newlines are indicated with a symbol."
(add-to-list 'buffer-file-format 'longlines)
(add-hook 'change-major-mode-hook #'longlines-mode-off nil t)
(add-hook 'before-revert-hook #'longlines-before-revert-hook nil t)
- (make-local-variable 'buffer-substring-filters)
(make-local-variable 'longlines-auto-wrap)
(set (make-local-variable 'isearch-search-fun-function)
#'longlines-search-function)
@@ -123,7 +125,8 @@ newlines are indicated with a symbol."
#'longlines-search-forward)
(set (make-local-variable 'replace-re-search-function)
#'longlines-re-search-forward)
- (add-to-list 'buffer-substring-filters 'longlines-encode-string)
+ (add-function :filter-return (local 'filter-buffer-substring-function)
+ #'longlines-encode-string)
(when longlines-wrap-follows-window-size
(let ((dw (if (and (integerp longlines-wrap-follows-window-size)
(>= longlines-wrap-follows-window-size 0)
@@ -140,7 +143,7 @@ newlines are indicated with a symbol."
(inhibit-modification-hooks t)
(mod (buffer-modified-p))
buffer-file-name buffer-file-truename)
- ;; Turning off undo is OK since (spaces + newlines) is
+ ;; Turning off undo is OK since (separators + newlines) is
;; conserved, except for a corner case in
;; longlines-wrap-lines that we'll never encounter from here
(save-restriction
@@ -199,7 +202,8 @@ newlines are indicated with a symbol."
(kill-local-variable 'replace-search-function)
(kill-local-variable 'replace-re-search-function)
(kill-local-variable 'require-final-newline)
- (kill-local-variable 'buffer-substring-filters)
+ (remove-function (local 'filter-buffer-substring-function)
+ #'longlines-encode-string)
(kill-local-variable 'use-hard-newlines)))
(defun longlines-mode-off ()
@@ -273,11 +277,8 @@ end of the buffer."
"If the current line needs to be wrapped, wrap it and return nil.
If wrapping is performed, point remains on the line. If the line does
not need to be wrapped, move point to the next line and return t."
- (if (longlines-set-breakpoint)
+ (if (longlines-set-breakpoint fill-column)
(progn (insert-before-markers-and-inherit ?\n)
- (backward-char 1)
- (delete-char -1)
- (forward-char 1)
nil)
(if (longlines-merge-lines-p)
(progn (end-of-line)
@@ -286,58 +287,60 @@ not need to be wrapped, move point to the next line and return t."
;; replace these two newlines by a single space. Unfortunately,
;; this breaks the conservation of (spaces + newlines), so we
;; have to fiddle with longlines-wrap-point.
- (if (or (prog1 (bolp) (forward-char 1)) (eolp))
- (progn
- (delete-char -1)
- (if (> longlines-wrap-point (point))
- (setq longlines-wrap-point
- (1- longlines-wrap-point))))
- (insert-before-markers-and-inherit ?\s)
- (backward-char 1)
- (delete-char -1)
- (forward-char 1))
+ (if (or (prog1 (bolp) (forward-char 1)) (eolp))
+ (progn
+ (delete-char -1)
+ (if (> longlines-wrap-point (point))
+ (setq longlines-wrap-point
+ (1- longlines-wrap-point))))
+ (delete-char -1))
nil)
(forward-line 1)
t)))
-(defun longlines-set-breakpoint ()
+(defun longlines-set-breakpoint (target-column)
"Place point where we should break the current line, and return t.
If the line should not be broken, return nil; point remains on the
line."
- (move-to-column fill-column)
- (if (and (re-search-forward "[^ ]" (line-end-position) 1)
- (> (current-column) fill-column))
- ;; This line is too long. Can we break it?
- (or (longlines-find-break-backward)
- (progn (move-to-column fill-column)
- (longlines-find-break-forward)))))
+ (move-to-column target-column)
+ (let ((non-breakpoint-re (format "[^%s]" longlines-breakpoint-chars)))
+ (if (and (re-search-forward non-breakpoint-re (line-end-position) t 1)
+ (> (current-column) target-column))
+ ;; This line is too long. Can we break it?
+ (or (longlines-find-break-backward)
+ (progn (move-to-column target-column)
+ (longlines-find-break-forward))))))
(defun longlines-find-break-backward ()
"Move point backward to the first available breakpoint and return t.
If no breakpoint is found, return nil."
- (and (search-backward " " (line-beginning-position) 1)
- (save-excursion
- (skip-chars-backward " " (line-beginning-position))
- (null (bolp)))
- (progn (forward-char 1)
- (if (and fill-nobreak-predicate
- (run-hook-with-args-until-success
- 'fill-nobreak-predicate))
- (progn (skip-chars-backward " " (line-beginning-position))
- (longlines-find-break-backward))
- t))))
+ (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars)))
+ (when (and (re-search-backward breakpoint-re (line-beginning-position) t 1)
+ (save-excursion
+ (skip-chars-backward longlines-breakpoint-chars
+ (line-beginning-position))
+ (null (bolp))))
+ (forward-char 1)
+ (if (and fill-nobreak-predicate
+ (run-hook-with-args-until-success 'fill-nobreak-predicate))
+ (progn
+ (skip-chars-backward longlines-breakpoint-chars
+ (line-beginning-position))
+ (longlines-find-break-backward))
+ t))))
(defun longlines-find-break-forward ()
"Move point forward to the first available breakpoint and return t.
If no break point is found, return nil."
- (and (search-forward " " (line-end-position) 1)
- (progn (skip-chars-forward " " (line-end-position))
- (null (eolp)))
- (if (and fill-nobreak-predicate
- (run-hook-with-args-until-success
- 'fill-nobreak-predicate))
- (longlines-find-break-forward)
- t)))
+ (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars)))
+ (and (re-search-forward breakpoint-re (line-end-position) t 1)
+ (progn
+ (skip-chars-forward longlines-breakpoint-chars (line-end-position))
+ (null (eolp)))
+ (if (and fill-nobreak-predicate
+ (run-hook-with-args-until-success 'fill-nobreak-predicate))
+ (longlines-find-break-forward)
+ t))))
(defun longlines-merge-lines-p ()
"Return t if part of the next line can fit onto the current line.
@@ -348,12 +351,7 @@ Otherwise, return nil. Text cannot be moved across hard newlines."
(null (get-text-property (point) 'hard))
(let ((space (- fill-column (current-column))))
(forward-line 1)
- (if (eq (char-after) ? )
- t ; We can always merge some spaces
- (<= (if (search-forward " " (line-end-position) 1)
- (current-column)
- (1+ (current-column)))
- space))))))
+ (longlines-set-breakpoint (max 0 (1- space)))))))
(defun longlines-decode-region (&optional beg end)
"Turn all newlines between BEG and END into hard newlines.
@@ -372,7 +370,7 @@ If BEG and END are nil, the point and mark are used."
(longlines-decode-region (point-min) (point-max)))
(defun longlines-encode-region (beg end &optional _buffer)
- "Replace each soft newline between BEG and END with exactly one space.
+ "Remove each soft newline between BEG and END.
Hard newlines are left intact. The optional argument BUFFER exists for
compatibility with `format-alist', and is ignored."
(save-excursion
@@ -382,23 +380,28 @@ compatibility with `format-alist', and is ignored."
(while (search-forward "\n" reg-max t)
(let ((pos (match-beginning 0)))
(unless (get-text-property pos 'hard)
- (goto-char (1+ pos))
- (insert-and-inherit " ")
- (delete-region pos (1+ pos))
- (remove-text-properties pos (1+ pos) '(hard nil)))))
+ (remove-text-properties pos (1+ pos) '(hard nil))
+ (delete-region pos (1+ pos)))))
(set-buffer-modified-p mod)
end)))
(defun longlines-encode-string (string)
- "Return a copy of STRING with each soft newline replaced by a space.
+ "Return a copy of STRING with each soft newline removed.
Hard newlines are left intact."
- (let* ((str (copy-sequence string))
- (pos (string-search "\n" str)))
- (while pos
- (if (null (get-text-property pos 'hard str))
- (aset str pos ? ))
- (setq pos (string-search "\n" str (1+ pos))))
- str))
+ (let ((start 0)
+ (result nil)
+ pos)
+ (while (setq pos (string-search "\n" string start))
+ (unless (= start pos)
+ (push (substring string start pos) result))
+ (when (get-text-property pos 'hard string)
+ (push (substring string pos (1+ pos)) result))
+ (setq start (1+ pos)))
+ (if (null result)
+ (copy-sequence string)
+ (unless (= start (length string))
+ (push (substring string start) result))
+ (apply #'concat (nreverse result)))))
;;; Auto wrap
diff --git a/lisp/lpr.el b/lisp/lpr.el
index 01617ef912a..88b0607b119 100644
--- a/lisp/lpr.el
+++ b/lisp/lpr.el
@@ -125,7 +125,7 @@ and print the result."
(defcustom print-region-function
(if (memq system-type '(ms-dos windows-nt))
(progn
- (declare-function w32-direct-print-region-function "w32-fns")
+ (declare-function w32-direct-print-region-function "dos-w32")
#'w32-direct-print-region-function)
#'call-process-region)
"Function to call to print the region on a printer.
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index e7118a2a376..6d1f449568a 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -621,14 +621,22 @@ in some standard C libraries does."
(sub2 (substring s2 ni2 e2))
;; "Fraction" is a numerical sequence with leading zeros.
(fr1 (string-match "\\`0+" sub1))
- (fr2 (string-match "\\`0+" sub2)))
+ (efr1 (match-end 0))
+ (fr2 (string-match "\\`0+" sub2))
+ (efr2 (match-end 0)))
(cond
- ((and fr1 fr2) ; two fractions, the shortest wins
- (setq val (- val (- (length sub1) (length sub2)))))
+ ;; Two fractions: the longer one is less than the other,
+ ;; but only if the "common prefix" is all-zeroes,
+ ;; otherwise fall back on numerical comparison.
+ ((and fr1 fr2)
+ (if (or (and (< efr1 (- e1 ni1)) (< efr2 (- e2 ni2))
+ (not (eq (aref sub1 efr1) (aref sub2 efr2))))
+ (= efr1 (- e1 ni1)) (= efr2 (- e2 ni2)))
+ (setq val (- val (- (length sub1) (length sub2))))))
(fr1 ; a fraction is always less than an integral
- (setq val (- ni1)))
+ (setq val (- 0 ni1 1))) ; make sure val is non-zero
(fr2
- (setq val ni2)))
+ (setq val (1+ ni2)))) ; make sure val is non-zero
(if (zerop val) ; fall back on numerical comparison
(setq val (- (string-to-number sub1)
(string-to-number sub2))))
@@ -784,7 +792,7 @@ SWITCHES and TIME-INDEX give the full switch list and time data."
;; In GNU ls, -h affects the size in blocks, displayed
;; by -s, as well.
(if (memq ?h switches)
- (format "%6s "
+ (format "%7s "
(file-size-human-readable
;; We use 1K as "block size", although
;; most Windows volumes use 4KB to 8KB
@@ -881,7 +889,7 @@ All ls time options, namely c, t and u, are handled."
ls-lisp-filesize-f-fmt
ls-lisp-filesize-d-fmt)
file-size)
- (format " %6s" (file-size-human-readable file-size))))
+ (format " %7s" (file-size-human-readable file-size))))
(defun ls-lisp-unload-function ()
"Unload ls-lisp library."
@@ -891,7 +899,7 @@ All ls time options, namely c, t and u, are handled."
nil)
(defun ls-lisp--sanitize-switches (switches)
- "Convert long options of GNU 'ls' to their short form.
+ "Convert long options of GNU \"ls\" to their short form.
Conversion is done only for flags supported by ls-lisp.
Long options not supported by ls-lisp are removed.
Supported options are: A a B C c F G g h i n R r S s t U u v X.
diff --git a/lisp/macros.el b/lisp/macros.el
index 4cb4e98d3fd..0baf3804332 100644
--- a/lisp/macros.el
+++ b/lisp/macros.el
@@ -46,6 +46,16 @@
" ")
?\]))
+(defun macro--string-to-vector (str)
+ "Convert an old-style string key sequence to the vector form."
+ (let ((vec (string-to-vector str)))
+ (unless (multibyte-string-p str)
+ (dotimes (i (length vec))
+ (let ((k (aref vec i)))
+ (when (> k 127)
+ (setf (aref vec i) (+ k ?\M-\C-@ -128))))))
+ vec))
+
;;;###autoload
(defun insert-kbd-macro (macroname &optional keys)
"Insert in buffer the definition of kbd macro MACRONAME, as Lisp code.
@@ -72,70 +82,36 @@ use this command, and then save the file."
(setq macroname 'last-kbd-macro definition last-kbd-macro)
(insert "(setq "))
(setq definition (symbol-function macroname))
- (insert "(fset '"))
+ ;; Prefer `defalias' over `fset' since it additionally keeps
+ ;; track of the file where the users added it, and it interacts
+ ;; better with `advice-add' (and hence things like ELP).
+ (insert "(defalias '"))
(prin1 macroname (current-buffer))
(insert "\n ")
- (if (stringp definition)
- (let ((beg (point)) end)
- (prin1 definition (current-buffer))
- (setq end (point-marker))
- (goto-char beg)
- (while (< (point) end)
- (let ((char (following-char)))
- (cond ((= char 0)
- (delete-region (point) (1+ (point)))
- (insert "\\C-@"))
- ((< char 27)
- (delete-region (point) (1+ (point)))
- (insert "\\C-" (+ 96 char)))
- ((= char ?\C-\\)
- (delete-region (point) (1+ (point)))
- (insert "\\C-\\\\"))
- ((< char 32)
- (delete-region (point) (1+ (point)))
- (insert "\\C-" (+ 64 char)))
- ((< char 127)
- (forward-char 1))
- ((= char 127)
- (delete-region (point) (1+ (point)))
- (insert "\\C-?"))
- ((= char 128)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-@"))
- ((= char (aref "\M-\C-\\" 0))
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-\\\\"))
- ((< char 155)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-" (- char 32)))
- ((< char 160)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-" (- char 64)))
- ((= char (aref "\M-\\" 0))
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\\\"))
- ((< char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-" (- char 128)))
- ((= char 255)
- (delete-region (point) (1+ (point)))
- (insert "\\M-\\C-?"))))))
- (if (vectorp definition)
- (macros--insert-vector-macro definition)
- (pcase (kmacro-extract-lambda definition)
- (`(,vecdef ,counter ,format)
- (insert "(kmacro-lambda-form ")
- (macros--insert-vector-macro vecdef)
- (insert " ")
- (prin1 counter (current-buffer))
- (insert " ")
- (prin1 format (current-buffer))
- (insert ")"))
- (_ (prin1 definition (current-buffer))))))
+ (when (stringp definition)
+ (setq definition (macro--string-to-vector definition)))
+ (if (vectorp definition)
+ (setq definition (kmacro definition)))
+ (if (kmacro-p definition)
+ (let ((vecdef (kmacro--keys definition))
+ (counter (kmacro--counter definition))
+ (format (kmacro--format definition)))
+ (insert "(kmacro ")
+ (prin1 (key-description vecdef) (current-buffer))
+ ;; FIXME: Do we really want to store the counter?
+ (unless (and (equal counter 0) (equal format "%d"))
+ (insert " ")
+ (prin1 counter (current-buffer))
+ (insert " ")
+ (prin1 format (current-buffer)))
+ (insert ")"))
+ ;; FIXME: Shouldn't this signal an error?
+ (prin1 definition (current-buffer)))
(insert ")\n")
(if keys
- (let ((keys (or (where-is-internal (symbol-function macroname)
- '(keymap))
+ (let ((keys (or (and (symbol-function macroname)
+ (where-is-internal (symbol-function macroname)
+ '(keymap)))
(where-is-internal macroname '(keymap)))))
(while keys
(insert "(global-set-key ")
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
index f5559e39f68..d743802eade 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/mail/emacsbug.el
@@ -1,7 +1,6 @@
;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1994, 1997-1998, 2000-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1985-2022 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
@@ -30,6 +29,9 @@
;; to complete the process. Alternatively, compose the bug report in
;; Emacs then paste it into your normal mail client.
+;; `M-x submit-emacs-patch' can be used to send a patch to the Emacs
+;; maintainers.
+
;;; Code:
(require 'sendmail)
@@ -40,9 +42,6 @@
:group 'maint
:group 'mail)
-(define-obsolete-variable-alias 'report-emacs-bug-pretest-address
- 'report-emacs-bug-address "24.1")
-
(defcustom report-emacs-bug-no-confirmation nil
"If non-nil, suppress the confirmations asked for the sake of novice users."
:type 'boolean)
@@ -304,6 +303,9 @@ usually do not have translators for other languages.\n\n")))
(emacs-bug--system-description)
(insert "Configured features:\n" system-configuration-features "\n\n")
(fill-region (line-beginning-position -1) (point))
+ (when (and (featurep 'native-compile)
+ (null (native-comp-available-p)))
+ (insert "(NATIVE_COMP present but libgccjit not available)\n\n"))
(insert "Important settings:\n")
(mapc
(lambda (var)
@@ -345,10 +347,10 @@ usually do not have translators for other languages.\n\n")))
;; This is so the user has to type something in order to send easily.
(use-local-map (nconc (make-sparse-keymap) (current-local-map)))
- (define-key (current-local-map) "\C-c\C-i" #'info-emacs-bug)
+ (keymap-set (current-local-map) "C-c C-i" #'info-emacs-bug)
(if can-insert-mail
- (define-key (current-local-map) "\C-c\M-i"
- #'report-emacs-bug-insert-to-mailer))
+ (keymap-set (current-local-map) "C-c M-i"
+ #'report-emacs-bug-insert-to-mailer))
(setq report-emacs-bug-send-command (get mail-user-agent 'sendfunc)
report-emacs-bug-send-hook (get mail-user-agent 'hookvar))
(if report-emacs-bug-send-command
@@ -357,20 +359,23 @@ usually do not have translators for other languages.\n\n")))
(unless report-emacs-bug-no-explanations
(with-output-to-temp-buffer "*Bug Help*"
(princ "While in the mail buffer:\n\n")
- (if report-emacs-bug-send-command
- (princ (substitute-command-keys
- (format " Type \\[%s] to send the bug report.\n"
- report-emacs-bug-send-command))))
- (princ (substitute-command-keys
- " Type \\[kill-buffer] RET to cancel (don't send it).\n"))
- (if can-insert-mail
- (princ (substitute-command-keys
- " Type \\[report-emacs-bug-insert-to-mailer] to copy text to your preferred mail program.\n")))
- (terpri)
- (princ (substitute-command-keys
- " Type \\[info-emacs-bug] to visit in Info the Emacs Manual section
+ (let ((help
+ (substitute-command-keys
+ (format "%s%s%s%s"
+ (if report-emacs-bug-send-command
+ (format " Type \\[%s] to send the bug report.\n"
+ report-emacs-bug-send-command)
+ "")
+ " Type \\[kill-buffer] \\`RET' to cancel (don't send it).\n"
+ (if can-insert-mail
+ " Type \\[report-emacs-bug-insert-to-mailer] to \
+copy text to your preferred mail program.\n"
+ "")
+ " Type \\[info-emacs-bug] to visit in Info the Emacs Manual section
about when and how to write a bug report, and what
- information you should include to help fix the bug.")))
+ information you should include to help fix the bug."))))
+ (with-current-buffer "*Bug Help*"
+ (insert help))))
(shrink-window-if-larger-than-buffer (get-buffer-window "*Bug Help*")))
;; Make it less likely people will send empty messages.
(if report-emacs-bug-send-hook
@@ -485,15 +490,23 @@ and send the mail again%s."
Interactively, you will be prompted for SUBJECT and a patch FILE
name (which will be attached to the mail). You will end up in a
Message buffer where you can explain more about the patch."
- (interactive "sThis patch is about: \nfPatch file name: ")
+ (interactive
+ (let* ((file (read-file-name "Patch file name: "))
+ (guess (with-temp-buffer
+ (insert-file-contents file)
+ (mail-fetch-field "Subject"))))
+ (list (read-string (format-prompt "This patch is about" guess)
+ nil nil guess)
+ file)))
(switch-to-buffer "*Patch Help*")
(let ((inhibit-read-only t))
(erase-buffer)
(insert "Thank you for considering submitting a patch to the Emacs project.\n\n"
"Please describe what the patch fixes (or, if it's a new feature, what it\n"
- "implements) in the mail buffer below. When done, use the `C-c C-c' command\n"
+ "implements) in the mail buffer below. When done, use the "
+ (substitute-command-keys "\\<message-mode-map>\\[message-send-and-exit] command\n")
"to send the patch as an email to the Emacs issue tracker.\n\n"
- "If this is the first time you've submitted an Emacs patch, please\n"
+ "If this is the first time you're submitting an Emacs patch, please\n"
"read the ")
(insert-text-button
"CONTRIBUTE"
@@ -506,11 +519,13 @@ Message buffer where you can explain more about the patch."
(view-mode 1)
(button-mode 1))
(message-mail-other-window report-emacs-bug-address subject)
+ (message-goto-body)
(insert "\n\n\n")
(emacs-bug--system-description)
(mml-attach-file file "text/patch" nil "attachment")
(message-goto-body)
- (message "Write a description of the patch and use `C-c C-c' to send it")
+ (message "Write a description of the patch and use %s to send it"
+ (substitute-command-keys "\\[message-send-and-exit]"))
(add-hook 'message-send-hook
(lambda ()
(message-goto-body)
diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el
index 32edc292619..af12417f706 100644
--- a/lisp/mail/feedmail.el
+++ b/lisp/mail/feedmail.el
@@ -1317,7 +1317,7 @@ feedmail-queue-buffer-file-name is restored to nil.
Example advice for mail-send:
- (advice-add 'mail-send :around #'my-feedmail-mail-send-advice)
+ (advice-add \\='mail-send :around #\\='my-feedmail-mail-send-advice)
(defun my-feedmail-mail-send-advice (orig-fun &rest args)
(let ((feedmail-queue-buffer-file-name buffer-file-name)
(buffer-file-name nil))
@@ -1619,7 +1619,8 @@ local gurus."
(if (null mail-interactive) '("-oem" "-odb")))))
(declare-function smtpmail-via-smtp "smtpmail"
- (recipient smtpmail-text-buffer &optional ask-for-password))
+ (recipient smtpmail-text-buffer &optional ask-for-password
+ send-attempts))
(defvar smtpmail-smtp-server)
;; provided by jam@austin.asc.slb.com (James A. McLaughlin);
@@ -1742,7 +1743,7 @@ applied to a file after you've just read it from disk: for example, a
feedmail FQM message file from a queue. You could use something like
this:
- (add-to-list 'auto-mode-alist \\='(\"\\\\.fqm\\\\\\='\" . feedmail-vm-mail-mode))"
+ (add-to-list \\='auto-mode-alist \\='(\"\\\\.fqm\\\\\\='\" . feedmail-vm-mail-mode))"
(feedmail-say-debug ">in-> feedmail-vm-mail-mode")
(let ((the-buf (current-buffer)))
(vm-mail)
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el
index a985a212557..29e16c419be 100644
--- a/lisp/mail/footnote.el
+++ b/lisp/mail/footnote.el
@@ -41,11 +41,11 @@
;; + The key sequence 'C-c ! a C-y C-c ! b' should auto-fill the
;; footnote in adaptive fill mode. This does not seem to be a bug in
;; `adaptive-fill' because it behaves that way on all point movements
-;; + Handle footmode mode elegantly in all modes, even if that means refuses to
+;; + Handle footnote mode elegantly in all modes, even if that means refusing to
;; accept the burden. For example, in a programming language mode, footnotes
;; should be commented.
-;; + Manually autofilling the a first footnote should not cause it to
-;; wrap into the footnote section tag
+;; + Manually autofilling the first footnote should not cause it to
+;; wrap into the footnote section tag.
;; + Current solution adds a second newline after the section tag, so it is
;; clearly a separate paragraph. There may be stylistic objections to this.
;; + Footnotes with multiple paragraphs should not have their first
diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el
index b343a017e34..8d274d9cac4 100644
--- a/lisp/mail/hashcash.el
+++ b/lisp/mail/hashcash.el
@@ -57,7 +57,7 @@
"The default number of bits to pay to unknown users.
If this is zero, no payment header will be generated.
See `hashcash-payment-alist'."
- :type 'integer
+ :type 'natnum
:group 'hashcash)
(defcustom hashcash-payment-alist '()
@@ -77,7 +77,7 @@ present, is the string to be hashed; if not present ADDR will be used."
(defcustom hashcash-default-accept-payment 20
"The default minimum number of bits to accept on incoming payments."
- :type 'integer
+ :type 'natnum
:group 'hashcash)
(defcustom hashcash-accept-resources `((,user-mail-address nil))
diff --git a/lisp/mail/ietf-drums-date.el b/lisp/mail/ietf-drums-date.el
new file mode 100644
index 00000000000..ddef7f11b66
--- /dev/null
+++ b/lisp/mail/ietf-drums-date.el
@@ -0,0 +1,274 @@
+;;; ietf-drums-date.el --- parse time/date for ietf-drums.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Bob Rogers <rogers@rgrjr.com>
+;; Keywords: mail, util
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; 'ietf-drums-parse-date-string' parses a time and/or date in a
+;; string and returns a list of values, just like `decode-time', where
+;; unspecified elements in the string are returned as nil (except
+;; unspecified DST is returned as -1). `encode-time' may be applied
+;; on these values to obtain an internal time value.
+
+;; Historically, `parse-time-string' was used for this purpose, but it
+;; was gradually but imperfectly extended to handle other date
+;; formats. 'ietf-drums-parse-date-string' is compatible in that it
+;; uses the same return value format and parses the same email date
+;; formats by default, but can be made stricter if desired.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'parse-time)
+
+(define-error 'date-parse-error "Date/time parse error" 'error)
+
+(defconst ietf-drums-date--slot-names
+ '(second minute hour day month year weekday dst zone)
+ "Names of return value slots, for better error messages
+See the decoded-time defstruct.")
+
+(defconst ietf-drums-date--slot-ranges
+ '((0 60) (0 59) (0 23) (1 31) (1 12) (1 9999))
+ "Numeric slot ranges, for bounds checking.
+Note that RFC5322 explicitly requires that seconds go up to 60,
+to allow for leap seconds (see Mills, D., \"Network Time
+Protocol\", STD 12, RFC 1119, September 1989).")
+
+(defsubst ietf-drums-date--ignore-char-p (char)
+ ;; Ignore whitespace and commas.
+ (memq char '(?\s ?\t ?\r ?\n ?,)))
+
+(defun ietf-drums-date--tokenize-string (string &optional comment-eof)
+ "Turn STRING into tokens, separated only by whitespace and commas.
+Multiple commas are ignored. Pure digit sequences are turned
+into integers. If COMMENT-EOF is true, then a comment as
+defined by RFC5322 (strictly, the CFWS production that also
+accepts comments) is treated as an end-of-file, and no further
+tokens are recognized, otherwise we strip out all comments and
+treat them as whitespace (per RFC822)."
+ (let ((index 0)
+ (end (length string))
+ (list ()))
+ (cl-flet ((skip-ignored ()
+ ;; Skip ignored characters at index (the scan
+ ;; position). Skip RFC822 comments in matched parens,
+ ;; but do not complain about unterminated comments.
+ (let ((char nil)
+ (nest 0))
+ (while (and (< index end)
+ (setq char (aref string index))
+ (or (> nest 0)
+ (ietf-drums-date--ignore-char-p char)
+ (and (not comment-eof) (eql char ?\())))
+ (cl-incf index)
+ ;; FWS bookkeeping.
+ (cond ((and (eq char ?\\)
+ (< (1+ index) end))
+ ;; Move to the next char but don't check
+ ;; it to see if it might be a paren.
+ (cl-incf index))
+ ((eq char ?\() (cl-incf nest))
+ ((eq char ?\)) (cl-decf nest)))))))
+ (skip-ignored) ;; Skip leading whitespace.
+ (while (and (< index end)
+ (not (and comment-eof
+ (eq (aref string index) ?\())))
+ (let* ((start index)
+ (char (aref string index))
+ (all-digits (<= ?0 char ?9)))
+ ;; char is valid; look for more valid characters.
+ (when (and (eq char ?\\)
+ (< (1+ index) end))
+ ;; Escaped character, which might be a "(". If so, we are
+ ;; correct to include it in the token, even though the
+ ;; caller is sure to barf. If not, we violate RFC2?822 by
+ ;; not removing the backslash, but no characters in valid
+ ;; RFC2?822 dates need escaping anyway, so it shouldn't
+ ;; matter that this is not done strictly correctly. --
+ ;; rgr, 24-Dec-21.
+ (cl-incf index))
+ (while (and (< (cl-incf index) end)
+ (setq char (aref string index))
+ (not (or (ietf-drums-date--ignore-char-p char)
+ (eq char ?\())))
+ (unless (<= ?0 char ?9)
+ (setq all-digits nil))
+ (when (and (eq char ?\\)
+ (< (1+ index) end))
+ ;; Escaped character, see above.
+ (cl-incf index)))
+ (push (if all-digits
+ (cl-parse-integer string :start start :end index)
+ (substring string start index))
+ list)
+ (skip-ignored)))
+ (nreverse list))))
+
+(defun ietf-drums-parse-date-string (time-string &optional error no-822)
+ "Parse an RFC5322 or RFC822 date, passed as TIME-STRING.
+The optional ERROR parameter causes syntax errors to be flagged
+by signalling an instance of the date-parse-error condition. The
+optional NO-822 parameter disables the more lax RFC822 syntax,
+which is permitted by default.
+
+The result is a list of (SEC MIN HOUR DAY MON YEAR DOW DST TZ),
+which can be accessed as a decoded-time defstruct (q.v.),
+e.g. `decoded-time-year' to extract the year, and turned into an
+Emacs timestamp by `encode-time'.
+
+The strict syntax for RFC5322 is as follows:
+
+ [ day-of-week \",\" ] day FWS month-name FWS year FWS time [CFWS]
+
+where the \"time\" production is:
+
+ 2DIGIT \":\" 2DIGIT [ \":\" 2DIGIT ] FWS ( \"+\" / \"-\" ) 4DIGIT
+
+and FWS is \"folding white space,\" and CFWS is \"comments and/or
+folding white space\", where comments are included in nesting
+parentheses and are equivalent to white space. RFC822 also
+accepts comments in random places (all of which is handled by
+ietf-drums-date--tokenize-string) and two-digit years. For
+two-digit years, 50 and up are interpreted as 1950 through 1999
+and 00 through 49 as 200 through 2049.
+
+We are somewhat more lax in what we accept (specifically, the
+hours don't have to be two digits, and the TZ and the comma after
+the DOW are optional), but we do insist that the items that are
+present do appear in this order. Unspecified/unrecognized
+elements in the string are returned as nil (except unspecified
+DST is returned as -1)."
+ (let ((tokens (ietf-drums-date--tokenize-string (downcase time-string)
+ no-822))
+ (time (list nil nil nil nil nil nil nil -1 nil)))
+ (cl-labels ((set-matched-slot (slot index token)
+ ;; Assign a slot value from match data if index is
+ ;; non-nil, else from token, signalling an error if
+ ;; enabled and it's out of range.
+ (let ((value (if index
+ (cl-parse-integer (match-string index token))
+ token)))
+ (when error
+ (let ((range (nth slot ietf-drums-date--slot-ranges)))
+ (when (and range
+ (not (<= (car range) value (cadr range))))
+ (signal 'date-parse-error
+ (list "Slot out of range"
+ (nth slot ietf-drums-date--slot-names)
+ token (car range) (cadr range))))))
+ (setf (nth slot time) value)))
+ (set-numeric (slot token)
+ ;; Only assign the slot if the token is a number.
+ (cond ((natnump token)
+ (set-matched-slot slot nil token))
+ (error
+ (signal 'date-parse-error
+ (list "Not a number"
+ (nth slot ietf-drums-date--slot-names)
+ token))))))
+ ;; Check for weekday.
+ (let ((dow (assoc (car tokens) parse-time-weekdays)))
+ (when dow
+ ;; Day of the week.
+ (set-matched-slot 6 nil (cdr dow))
+ (pop tokens)))
+ ;; Day.
+ (set-numeric 3 (pop tokens))
+ ;; Alphabetic month.
+ (let* ((month (pop tokens))
+ (match (assoc month parse-time-months)))
+ (cond (match
+ (set-matched-slot 4 nil (cdr match)))
+ (error
+ (signal 'date-parse-error
+ (list "Expected an alphabetic month" month)))
+ (t
+ (push month tokens))))
+ ;; Year.
+ (let ((year (pop tokens)))
+ ;; Check the year for the right number of digits.
+ (cond ((not (natnump year))
+ (when error
+ (signal 'date-parse-error
+ (list "Expected a year" year)))
+ (push year tokens))
+ ((>= year 1000)
+ (set-numeric 5 year))
+ ((or no-822
+ (>= year 100))
+ (when error
+ (signal 'date-parse-error
+ (list "Four-digit years are required" year)))
+ (push year tokens))
+ ((>= year 50)
+ ;; second half of the 20th century.
+ (set-numeric 5 (+ 1900 year)))
+ (t
+ ;; first half of the 21st century.
+ (set-numeric 5 (+ 2000 year)))))
+ ;; Time.
+ (let ((time (pop tokens)))
+ (cond ((or (null time) (natnump time))
+ (when error
+ (signal 'date-parse-error
+ (list "Expected a time" time)))
+ (push time tokens))
+ ((string-match
+ "^\\([0-9][0-9]?\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$"
+ time)
+ (set-matched-slot 2 1 time)
+ (set-matched-slot 1 2 time)
+ (set-matched-slot 0 3 time))
+ ((string-match "^\\([0-9][0-9]?\\):\\([0-9][0-9]\\)$" time)
+ ;; Time without seconds.
+ (set-matched-slot 2 1 time)
+ (set-matched-slot 1 2 time)
+ (set-matched-slot 0 nil 0))
+ (error
+ (signal 'date-parse-error
+ (list "Expected a time" time)))))
+ ;; Timezone.
+ (let* ((zone (pop tokens))
+ (match (assoc zone parse-time-zoneinfo)))
+ (cond (match
+ (set-matched-slot 8 nil (cadr match))
+ (set-matched-slot 7 nil (caddr match)))
+ ((and (stringp zone)
+ (string-match "^[-+][0-9][0-9][0-9][0-9]$" zone))
+ ;; Numeric time zone.
+ (set-matched-slot
+ 8 nil
+ (* 60
+ (+ (cl-parse-integer zone :start 3 :end 5)
+ (* 60 (cl-parse-integer zone :start 1 :end 3)))
+ (if (= (aref zone 0) ?-) -1 1))))
+ ((and zone error)
+ (signal 'date-parse-error
+ (list "Expected a timezone" zone)))))
+ (when (and tokens error)
+ (signal 'date-parse-error
+ (list "Extra token(s)" (car tokens)))))
+ time))
+
+(provide 'ietf-drums-date)
+
+;;; ietf-drums-date.el ends here
diff --git a/lisp/mail/ietf-drums.el b/lisp/mail/ietf-drums.el
index 4a079591890..d1ad671b160 100644
--- a/lisp/mail/ietf-drums.el
+++ b/lisp/mail/ietf-drums.el
@@ -25,16 +25,6 @@
;; library is based on draft-ietf-drums-msg-fmt-05.txt, released on
;; 1998-08-05.
-;; Pending a real regression self test suite, Simon Josefsson added
-;; various self test expressions snipped from bug reports, and their
-;; expected value, below. I you believe it could be useful, please
-;; add your own test cases, or write a real self test suite, or just
-;; remove this.
-
-;; <m3oekvfd50.fsf@whitebox.m5r.de>
-;; (ietf-drums-parse-address "'foo' <foo@example.com>")
-;; => ("foo@example.com" . "'foo'")
-
;;; Code:
(eval-when-compile (require 'cl-lib))
@@ -75,6 +65,21 @@ backslash and doublequote.")
(modify-syntax-entry ?\' "_" table)
table))
+(defvar ietf-drums-comment-syntax-table
+ (let ((table (copy-syntax-table ietf-drums-syntax-table)))
+ (modify-syntax-entry ?\" "w" table)
+ table)
+ "In comments, DQUOTE is normal and does not start a string.")
+
+(defun ietf-drums--skip-comment ()
+ ;; From just before the start of a comment, go to the end. Returns
+ ;; point. If the comment is unterminated, go to point-max.
+ (condition-case ()
+ (with-syntax-table ietf-drums-comment-syntax-table
+ (forward-sexp 1))
+ (scan-error (goto-char (point-max))))
+ (point))
+
(defun ietf-drums-token-to-list (token)
"Translate TOKEN into a list of characters."
(let ((i 0)
@@ -119,14 +124,7 @@ backslash and doublequote.")
(forward-sexp 1)
(error (goto-char (point-max)))))
((eq c ?\()
- (delete-region
- (point)
- (condition-case nil
- (with-syntax-table (copy-syntax-table ietf-drums-syntax-table)
- (modify-syntax-entry ?\" "w")
- (forward-sexp 1)
- (point))
- (error (point-max)))))
+ (delete-region (point) (ietf-drums--skip-comment)))
(t
(forward-char 1))))
(buffer-string))))
@@ -140,9 +138,11 @@ backslash and doublequote.")
(setq c (char-after))
(cond
((eq c ?\")
- (forward-sexp 1))
+ (condition-case ()
+ (forward-sexp 1)
+ (scan-error (goto-char (point-max)))))
((eq c ?\()
- (forward-sexp 1))
+ (ietf-drums--skip-comment))
((memq c '(?\ ?\t ?\n ?\r))
(delete-char 1))
(t
@@ -150,7 +150,7 @@ backslash and doublequote.")
(buffer-string))))
(defun ietf-drums-get-comment (string)
- "Return the first comment in STRING."
+ "Return the last comment in STRING."
(with-temp-buffer
(ietf-drums-init string)
(let (result c)
@@ -191,6 +191,8 @@ the Content-Transfer-Encoding header of a mail."
"Parse STRING and return a MAILBOX / DISPLAY-NAME pair.
If DECODE, the DISPLAY-NAME will have RFC2047 decoding performed
(that's the \"=?utf...q...=?\") stuff."
+ (when decode
+ (require 'rfc2047))
(with-temp-buffer
(let (display-name mailbox c display-string)
(ietf-drums-init string)
@@ -240,7 +242,7 @@ If DECODE, the DISPLAY-NAME will have RFC2047 decoding performed
(cons
(mapconcat #'identity (nreverse display-name) "")
(ietf-drums-get-comment string)))
- (cons mailbox (if decode
+ (cons mailbox (if (and decode display-string)
(rfc2047-decode-string display-string)
display-string))))))
@@ -292,9 +294,13 @@ a list of address strings."
(replace-match " " t t))
(goto-char (point-min)))
+(declare-function ietf-drums-parse-date-string "ietf-drums-date"
+ (time-string &optional error? no-822?))
+
(defun ietf-drums-parse-date (string)
"Return an Emacs time spec from STRING."
- (encode-time (parse-time-string string)))
+ (require 'ietf-drums-date)
+ (encode-time (ietf-drums-parse-date-string string)))
(defun ietf-drums-narrow-to-header ()
"Narrow to the header section in the current buffer."
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index 50ba04ccc1e..25ce4ea9025 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -1,7 +1,6 @@
;;; mail-extr.el --- extract full name and address from email header -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-1994, 1997, 2001-2022 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1991-2022 Free Software Foundation, Inc.
;; Author: Joe Wells <jbw@cs.bu.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -240,8 +239,7 @@ we will act as though we couldn't find a full name in the address."
;; Matches a leading title that is not part of the name (does not
;; contribute to uniquely identifying the person).
(defcustom mail-extr-full-name-prefixes
- (purecopy
- "\\(Prof\\|D[Rr]\\|Mrs?\\|Rev\\|Rabbi\\|SysOp\\|LCDR\\)\\.?[ \t\n]")
+ "\\(Prof\\|D[Rr]\\|Mrs?\\|Rev\\|Rabbi\\|SysOp\\|LCDR\\)\\.?[ \t\n]"
"Matches prefixes to the full name that identify a person's position.
These are stripped from the full name because they do not contribute to
uniquely identifying the person."
@@ -279,45 +277,42 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; Yes, there are weird people with digits in their names.
;; You will also notice the consideration for the
;; Swedish/Finnish/Norwegian character set.
-(defconst mail-extr-all-letters-but-separators
- (purecopy "][[:alnum:]{|}'~`"))
+(defconst mail-extr-all-letters-but-separators "][[:alnum:]{|}'~`")
;; Any character that can occur in a name in an RFC 822 (or later)
;; address including the separator (hyphen and possibly period) for
;; multipart names.
;; #### should . be in here?
(defconst mail-extr-all-letters
- (purecopy (concat mail-extr-all-letters-but-separators "-")))
+ (concat mail-extr-all-letters-but-separators "-"))
;; Any character that can start a name.
;; Keep this set as minimal as possible.
-(defconst mail-extr-first-letters (purecopy "[:alpha:]"))
+(defconst mail-extr-first-letters "[:alpha:]")
;; Any character that can end a name.
;; Keep this set as minimal as possible.
-(defconst mail-extr-last-letters (purecopy "[:alpha:]`'."))
+(defconst mail-extr-last-letters "[:alpha:]`'.")
(defconst mail-extr-leading-garbage "\\W+")
;; (defconst mail-extr-non-begin-name-chars
-;; (purecopy (concat "^" mail-extr-first-letters)))
+;; (concat "^" mail-extr-first-letters))
;; (defconst mail-extr-non-end-name-chars
-;; (purecopy (concat "^" mail-extr-last-letters)))
+;; (concat "^" mail-extr-last-letters))
;; Matches periods used instead of spaces. Must not match the period
;; following an initial.
(defconst mail-extr-bad-dot-pattern
- (purecopy
- (format "\\([%s][%s]\\)\\.+\\([%s]\\)"
- mail-extr-all-letters
- mail-extr-last-letters
- mail-extr-first-letters)))
+ (format "\\([%s][%s]\\)\\.+\\([%s]\\)"
+ mail-extr-all-letters
+ mail-extr-last-letters
+ mail-extr-first-letters))
;; Matches an embedded or leading nickname that should be removed.
;; (defconst mail-extr-nickname-pattern
-;; (purecopy
-;; (format "\\([ .]\\|\\`\\)[\"'`[(]\\([ .%s]+\\)[]\"')] "
-;; mail-extr-all-letters)))
+;; (format "\\([ .]\\|\\`\\)[\"'`[(]\\([ .%s]+\\)[]\"')] "
+;; mail-extr-all-letters))
;; Matches the occurrence of a generational name suffix, and the last
;; character of the preceding name. This is important because we want to
@@ -325,59 +320,56 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; *** Perhaps this should be a user-customizable variable. However, the
;; *** regular expression is fairly tricky to alter, so maybe not.
(defconst mail-extr-full-name-suffix-pattern
- (purecopy
- (format
- "\\(,? ?\\([JjSs][Rr]\\.?\\|V?I+V?\\)\\)\\([^%s]\\([^%s]\\|\\'\\)\\|\\'\\)"
- mail-extr-all-letters mail-extr-all-letters)))
+ (format
+ "\\(,? ?\\([JjSs][Rr]\\.?\\|V?I+V?\\)\\)\\([^%s]\\([^%s]\\|\\'\\)\\|\\'\\)"
+ mail-extr-all-letters mail-extr-all-letters))
-(defconst mail-extr-roman-numeral-pattern (purecopy "V?I+V?\\b"))
+(defconst mail-extr-roman-numeral-pattern "V?I+V?\\b")
;; Matches a trailing uppercase (with other characters possible) acronym.
;; Must not match a trailing uppercase last name or trailing initial
(defconst mail-extr-weird-acronym-pattern
- (purecopy "\\([A-Z]+[-_/]\\|[A-Z][A-Z][A-Z]?\\b\\)"))
+ "\\([A-Z]+[-_/]\\|[A-Z][A-Z][A-Z]?\\b\\)")
;; Matches a mixed-case or lowercase name (not an initial).
;; #### Match Latin1 lower case letters here too?
;; (defconst mail-extr-mixed-case-name-pattern
-;; (purecopy
-;; (format
-;; "\\b\\([a-z][%s]*[%s]\\|[%s][%s]*[a-z][%s]*[%s]\\|[%s][%s]*[a-z]\\)"
-;; mail-extr-all-letters mail-extr-last-letters
-;; mail-extr-first-letters mail-extr-all-letters mail-extr-all-letters
-;; mail-extr-last-letters mail-extr-first-letters mail-extr-all-letters)))
+;; (format
+;; "\\b\\([a-z][%s]*[%s]\\|[%s][%s]*[a-z][%s]*[%s]\\|[%s][%s]*[a-z]\\)"
+;; mail-extr-all-letters mail-extr-last-letters
+;; mail-extr-first-letters mail-extr-all-letters mail-extr-all-letters
+;; mail-extr-last-letters mail-extr-first-letters mail-extr-all-letters))
;; Matches a trailing alternative address.
;; #### Match Latin1 letters here too?
;; #### Match _ before @ here too?
(defconst mail-extr-alternative-address-pattern
- (purecopy "\\(aka *\\)?[a-zA-Z.]+[!@][a-zA-Z.]"))
+ "\\(aka *\\)?[a-zA-Z.]+[!@][a-zA-Z.]")
;; Matches a variety of trailing comments not including comma-delimited
;; comments.
(defconst mail-extr-trailing-comment-start-pattern
- (purecopy " [-{]\\|--\\|[+@#></;]"))
+ " [-{]\\|--\\|[+@#></;]")
;; Matches a name (not an initial).
;; This doesn't force a word boundary at the end because sometimes a
;; comment is separated by a `-' with no preceding space.
(defconst mail-extr-name-pattern
- (purecopy (format "\\b[%s][%s]*[%s]"
- mail-extr-first-letters
- mail-extr-all-letters
- mail-extr-last-letters)))
+ (format "\\b[%s][%s]*[%s]"
+ mail-extr-first-letters
+ mail-extr-all-letters
+ mail-extr-last-letters))
(defconst mail-extr-initial-pattern
- (purecopy (format "\\b[%s]\\([. ]\\|\\b\\)" mail-extr-first-letters)))
+ (format "\\b[%s]\\([. ]\\|\\b\\)" mail-extr-first-letters))
;; Matches a single name before a comma.
;; (defconst mail-extr-last-name-first-pattern
-;; (purecopy (concat "\\`" mail-extr-name-pattern ",")))
+;; (concat "\\`" mail-extr-name-pattern ","))
;; Matches telephone extensions.
(defconst mail-extr-telephone-extension-pattern
- (purecopy
- "\\(\\([Ee]xt\\|[Tt]ph\\|[Tt]el\\|[Xx]\\)\\.?\\)? *\\+?[0-9][- 0-9]+"))
+ "\\(\\([Ee]xt\\|[Tt]ph\\|[Tt]el\\|[Xx]\\)\\.?\\)? *\\+?[0-9][- 0-9]+")
;; Matches ham radio call signs.
;; Help from: Mat Maessen N2NJZ <maessm@rpi.edu>, Mark Feit
@@ -386,7 +378,7 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; KE9TV KF0NV N1API N3FU N3GZE N3IGS N4KCC N7IKQ N9HHU W4YHF W6ANK WA2SUH
;; WB7VZI N2NJZ NR3G KJ4KK AB4UM AL7NI KH6OH WN3KBT N4TMI W1A N0NZO
(defconst mail-extr-ham-call-sign-pattern
- (purecopy "\\b\\(DX[0-9]+\\|[AKNW][A-Z]?[0-9][A-Z][A-Z]?[A-Z]?\\)"))
+ "\\b\\(DX[0-9]+\\|[AKNW][A-Z]?[0-9][A-Z][A-Z]?[A-Z]?\\)")
;; Possible trailing suffixes: "\\(/\\(KT\\|A[AEG]\\|[R0-9]\\)\\)?"
;; /KT == Temporary Technician (has CSC but not "real" license)
@@ -400,31 +392,29 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; Matches normal single-part name
(defconst mail-extr-normal-name-pattern
- (purecopy (format "\\b[%s][%s]+[%s]"
- mail-extr-first-letters
- mail-extr-all-letters-but-separators
- mail-extr-last-letters)))
+ (format "\\b[%s][%s]+[%s]"
+ mail-extr-first-letters
+ mail-extr-all-letters-but-separators
+ mail-extr-last-letters))
;; Matches a single word name.
;; (defconst mail-extr-one-name-pattern
-;; (purecopy (concat "\\`" mail-extr-normal-name-pattern "\\'")))
+;; (concat "\\`" mail-extr-normal-name-pattern "\\'"))
;; Matches normal two names with missing middle initial
;; The first name is not allowed to have a hyphen because this can cause
;; false matches where the "middle initial" is actually the first letter
;; of the second part of the first name.
(defconst mail-extr-two-name-pattern
- (purecopy
- (concat "\\`\\(" mail-extr-normal-name-pattern
- "\\|" mail-extr-initial-pattern
- "\\) +\\(" mail-extr-name-pattern "\\)\\(,\\|\\'\\)")))
+ (concat "\\`\\(" mail-extr-normal-name-pattern
+ "\\|" mail-extr-initial-pattern
+ "\\) +\\(" mail-extr-name-pattern "\\)\\(,\\|\\'\\)"))
(defconst mail-extr-listserv-list-name-pattern
- (purecopy "Multiple recipients of list \\([-A-Z]+\\)"))
+ "Multiple recipients of list \\([-A-Z]+\\)")
(defconst mail-extr-stupid-vms-date-stamp-pattern
- (purecopy
- "[0-9][0-9]-[JFMASOND][aepuco][nbrylgptvc]-[0-9][0-9][0-9][0-9] [0-9]+ *"))
+ "[0-9][0-9]-[JFMASOND][aepuco][nbrylgptvc]-[0-9][0-9][0-9][0-9] [0-9]+ *")
;;; HZ -- GB (PRC Chinese character encoding) in ASCII embedding protocol
;;
@@ -443,25 +433,23 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; mode from GB back to ASCII. (Note that the escape-from-GB code '~}'
;; ($7E7D) is outside the defined GB range.)
(defconst mail-extr-hz-embedded-gb-encoded-chinese-pattern
- (purecopy "~{\\([^~].\\|~[^}]\\)+~}"))
+ "~{\\([^~].\\|~[^}]\\)+~}")
;; The leading optional lowercase letters are for a bastardized version of
;; the encoding, as is the optional nature of the final slash.
(defconst mail-extr-x400-encoded-address-pattern
- (purecopy "[a-z]?[a-z]?\\(/[A-Za-z]+\\(\\.[A-Za-z]+\\)?=[^/]+\\)+/?\\'"))
+ "[a-z]?[a-z]?\\(/[A-Za-z]+\\(\\.[A-Za-z]+\\)?=[^/]+\\)+/?\\'")
(defconst mail-extr-x400-encoded-address-field-pattern-format
- (purecopy "/%s=\\([^/]+\\)\\(/\\|\\'\\)"))
+ "/%s=\\([^/]+\\)\\(/\\|\\'\\)")
(defconst mail-extr-x400-encoded-address-surname-pattern
;; S stands for Surname (family name).
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Ss]")))
+ (format mail-extr-x400-encoded-address-field-pattern-format "[Ss]"))
(defconst mail-extr-x400-encoded-address-given-name-pattern
;; G stands for Given name.
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Gg]")))
+ (format mail-extr-x400-encoded-address-field-pattern-format "[Gg]"))
(defconst mail-extr-x400-encoded-address-full-name-pattern
;; PN stands for Personal Name. When used it represents the combination
@@ -469,8 +457,7 @@ by translating things like \"foo!bar!baz@host\" into \"baz@bar.UUCP\"."
;; "The one system I used having this field asked it with the prompt
;; `Personal Name'. But they mapped it into G and S on outgoing real
;; X.400 addresses. As they mapped G and S into PN on incoming..."
- (purecopy
- (format mail-extr-x400-encoded-address-field-pattern-format "[Pp][Nn]")))
+ (format mail-extr-x400-encoded-address-field-pattern-format "[Pp][Nn]"))
@@ -716,7 +703,6 @@ to the results."
value-list)
(with-current-buffer (get-buffer-create extraction-buffer)
- (fundamental-mode)
(buffer-disable-undo extraction-buffer)
(set-syntax-table mail-extr-address-syntax-table)
(widen)
@@ -738,7 +724,6 @@ to the results."
(set-text-properties (point-min) (point-max) nil)
(with-current-buffer (get-buffer-create canonicalization-buffer)
- (fundamental-mode)
(buffer-disable-undo canonicalization-buffer)
(setq case-fold-search nil))
diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el
index e02d4218dd2..a13f9de1740 100644
--- a/lisp/mail/mail-hist.el
+++ b/lisp/mail/mail-hist.el
@@ -80,7 +80,7 @@ previous/next input.")
(defcustom mail-hist-history-size (or kill-ring-max 1729)
"The maximum number of elements in a mail field's history.
Oldest elements are dumped first."
- :type 'integer)
+ :type 'natnum)
;;;###autoload
(defcustom mail-hist-keep-history t
diff --git a/lisp/mail/mail-parse.el b/lisp/mail/mail-parse.el
index 23894e59b77..ec719850e2e 100644
--- a/lisp/mail/mail-parse.el
+++ b/lisp/mail/mail-parse.el
@@ -76,7 +76,8 @@
The return value is a list with mail/name pairs."
(delq nil
(mapcar (lambda (elem)
- (or (mail-header-parse-address elem)
+ (or (ignore-errors
+ (mail-header-parse-address elem))
(mail-header-parse-address-lax elem)))
(mail-header-parse-addresses string t))))
diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el
index 952970d07c0..9ea2cc92e94 100644
--- a/lisp/mail/mail-utils.el
+++ b/lisp/mail/mail-utils.el
@@ -239,12 +239,8 @@ comma-separated list, and return the pruned list."
;; Or just set the default directly in the defcustom.
(if (null mail-dont-reply-to-names)
(setq mail-dont-reply-to-names
- ;; `rmail-default-dont-reply-to-names' is obsolete.
- (let ((a (bound-and-true-p rmail-default-dont-reply-to-names))
- (b (if (> (length user-mail-address) 0)
- (concat "\\`" (regexp-quote user-mail-address) "\\'"))))
- (cond ((and a b) (concat a "\\|" b))
- ((or a b))))))
+ (if (> (length user-mail-address) 0)
+ (concat "\\`" (regexp-quote user-mail-address) "\\'"))))
;; Split up DESTINATIONS and match each element separately.
(let ((start-pos 0) (cur-pos 0)
(case-fold-search t))
@@ -281,9 +277,6 @@ comma-separated list, and return the pruned list."
(substring destinations (match-end 0))
destinations))
-;; Legacy name
-(define-obsolete-function-alias 'rmail-dont-reply-to #'mail-dont-reply-to "24.1")
-
;;;###autoload
(defun mail-fetch-field (field-name &optional last all list delete)
diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el
index ba7cf58d383..c97786190c3 100644
--- a/lisp/mail/mailalias.el
+++ b/lisp/mail/mailalias.el
@@ -72,8 +72,7 @@ When t this still needs to be initialized.")
)
"Alist of header field and expression to return alist for completion.
The expression may reference the variable `pattern'
-which will hold the string being completed.
-If not on matching header, `mail-complete-function' gets called instead."
+which will hold the string being completed."
:type 'alist
:group 'mailalias)
(put 'mail-complete-alist 'risky-local-variable t)
@@ -90,13 +89,6 @@ If `angles', they look like:
:type '(choice (const angles) (const parens) (const nil))
:group 'mailalias)
-(defcustom mail-complete-function 'ispell-complete-word
- "Function to call when completing outside `mail-complete-alist'-header."
- :type '(choice function (const nil))
- :group 'mailalias)
-(make-obsolete-variable 'mail-complete-function
- 'completion-at-point-functions "24.1")
-
(defcustom mail-directory-function nil
"Function to get completions from directory service or nil for none.
See `mail-directory-requery'."
@@ -433,25 +425,6 @@ For use on `completion-at-point-functions'."
(let ((pattern prefix)) (eval list-exp))))))
(list beg end table)))))
-;;;###autoload
-(defun mail-complete (arg)
- "Perform completion on header field or word preceding point.
-Completable headers are according to `mail-complete-alist'. If none matches
-current header, calls `mail-complete-function' and passes prefix ARG if any."
- (declare (obsolete mail-completion-at-point-function "24.1"))
- (interactive "P")
- ;; Read the defaults first, if we have not done so.
- (sendmail-sync-aliases)
- (if (eq mail-aliases t)
- (progn
- (setq mail-aliases nil)
- (if (file-exists-p mail-personal-alias-file)
- (build-mail-aliases))))
- (let ((data (mail-completion-at-point-function)))
- (if data
- (apply #'completion-in-region data)
- (funcall mail-complete-function arg))))
-
(defun mail-completion-expand (table)
"Build new completion table that expands aliases.
Completes like TABLE except that if the completion is a valid alias,
diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el
index b3c45100f6d..bb0d646346c 100644
--- a/lisp/mail/rfc2047.el
+++ b/lisp/mail/rfc2047.el
@@ -46,7 +46,7 @@
("Followup-To" . nil)
("Message-ID" . nil)
("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|\\(In-\\)?Reply-To\\|Sender\
-\\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\)" . address-mime)
+\\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\|Disposition-Notification-To\\)" . address-mime)
(t . mime))
"Header/encoding method alist.
The list is traversed sequentially. The keys can either be
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 55921eca685..a970ab2a760 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -315,20 +315,6 @@ Setting this variable has an effect only before reading a mail."
:version "21.1")
;;;###autoload
-(define-obsolete-variable-alias 'rmail-dont-reply-to-names
- 'mail-dont-reply-to-names "24.1")
-
-;; Prior to 24.1, this used to contain "\\`info-".
-;;;###autoload
-(defvar rmail-default-dont-reply-to-names nil
- "Regexp specifying part of the default value of `mail-dont-reply-to-names'.
-This is used when the user does not set `mail-dont-reply-to-names'
-explicitly.")
-;;;###autoload
-(make-obsolete-variable 'rmail-default-dont-reply-to-names
- 'mail-dont-reply-to-names "24.1")
-
-;;;###autoload
(defcustom rmail-ignored-headers
(purecopy
(concat "^via:\\|^mail-from:\\|^origin:\\|^references:\\|^sender:"
@@ -388,7 +374,7 @@ If nil, display all header fields except those matched by
;;;###autoload
(defcustom rmail-retry-ignored-headers (purecopy "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:\\|message-id:")
"Headers that should be stripped when retrying a failed message."
- :type '(choice regexp (const nil :tag "None"))
+ :type '(choice regexp (const :value nil :tag "None"))
:group 'rmail-headers
:version "23.2") ; added x-detected-operating-system, x-spam
@@ -537,7 +523,7 @@ Examples:
;; Note: this is matched with case-fold-search bound to t.
(defcustom rmail-re-abbrevs
"\\(RE\\|رد\\|回复\\|回覆\\|SV\\|Antw\\|VS\\|REF\\|AW\\|ΑΠ\\|ΣΧΕΤ\\|השב\\|Vá\\|R\\|RIF\\|BLS\\|RES\\|Odp\\|YNT\\|ATB\\)"
- "Regexp with localized 'Re:' abbreviations in various languages."
+ "Regexp with localized \"Re:\" abbreviations in various languages."
:version "28.1"
:type 'regexp)
@@ -1465,7 +1451,6 @@ If so restore the actual mbox message collection."
(setq-local font-lock-defaults
'(rmail-font-lock-keywords
t t nil nil
- (font-lock-maximum-size . nil)
(font-lock-dont-widen . t)
(font-lock-inhibit-thing-lock . (lazy-lock-mode fast-lock-mode))))
(setq-local require-final-newline nil)
@@ -3354,12 +3339,12 @@ removing prefixes such as Re:, Fwd: and so on and mailing list
tags such as [tag]."
(let ((subject (or (rmail-get-header "Subject" msgnum) ""))
(regexp "\\`[ \t\n]*\\(\\(\\w\\{1,4\\}\u00a0*[::]\\|\\[[^]]+]\\)[ \t\n]+\\)*"))
+ (setq subject (rfc2047-decode-string subject))
;; Corporate mailing systems sometimes add `[External] :'; if that happened,
;; delete everything up thru there. Empirically, that deletion makes
;; the Subject match the other messages in the thread.
(if (string-match "\\[external][ \t\n]*:" subject)
(setq subject (substring subject (match-end 0))))
- (setq subject (rfc2047-decode-string subject))
(setq subject (replace-regexp-in-string regexp "" subject))
(replace-regexp-in-string "[ \t\n]+" " " subject)))
@@ -4489,10 +4474,7 @@ password."
:max 1 :user user :host host
:require '(:secret)))))
(if found
- (let ((secret (plist-get found :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))
+ (auth-info-password found)
(read-passwd (if imap
"IMAP password: "
"POP password: "))))))
@@ -4595,8 +4577,6 @@ Argument MIME is non-nil if this is a mime message."
armor-end-regexp
(buffer-substring armor-start (- (point-max) after-end)))))
-(declare-function rmail-mime-entity-truncated "rmailmm" (entity))
-
;; Should this have a key-binding, or be in a menu?
;; There doesn't really seem to be an appropriate menu.
;; Eg the edit command is not in a menu either.
diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el
index 76a32724c08..79f421bdcd6 100644
--- a/lisp/mail/rmailmm.el
+++ b/lisp/mail/rmailmm.el
@@ -796,17 +796,14 @@ directly."
((string-match "text/" content-type)
(setq type 'text))
((string-match "image/\\(.*\\)" content-type)
- (setq type (image-type-from-file-name
+ (setq type (image-supported-file-p
(concat "." (match-string 1 content-type))))
- (if (and (boundp 'image-types)
- (memq type image-types)
- (image-type-available-p type))
- (if (and rmail-mime-show-images
- (not (eq rmail-mime-show-images 'button))
- (or (not (numberp rmail-mime-show-images))
- (< size rmail-mime-show-images)))
- (setq to-show t))
- (setq type nil))))
+ (when (and type
+ rmail-mime-show-images
+ (not (eq rmail-mime-show-images 'button))
+ (or (not (numberp rmail-mime-show-images))
+ (< size rmail-mime-show-images)))
+ (setq to-show t))))
(setcar bulk-data size)
(setcdr bulk-data type)
to-show))
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index 59c2e578d32..b23fbc3f600 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -1475,7 +1475,7 @@ argument says to read a file name and use that file as the inbox."
(forward-line -1))
(declare-function rmail-abort-edit "rmailedit" ())
-(declare-function rmail-cease-edit "rmailedit"())
+(declare-function rmail-cease-edit "rmailedit" (&optional abort))
(declare-function rmail-set-label "rmailkwd" (l state &optional n))
(declare-function rmail-output-read-file-name "rmailout" ())
(declare-function mail-send-and-exit "sendmail" (&optional arg))
diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el
index 76c3baf4727..6afadca6bb3 100644
--- a/lisp/mail/sendmail.el
+++ b/lisp/mail/sendmail.el
@@ -430,20 +430,6 @@ support Delivery Status Notification."
(const :tag "Success" success)))
:version "22.1")
-;; Note: could use /usr/ucb/mail instead of sendmail;
-;; options -t, and -v if not interactive.
-(defvar mail-mailer-swallows-blank-line nil
- "Set this non-nil if the system's mailer runs the header and body together.
-The actual value should be an expression to evaluate that returns
-non-nil if the problem will actually occur.
-\(As far as we know, this is not an issue on any system still supported
-by Emacs.)")
-
-(put 'mail-mailer-swallows-blank-line 'risky-local-variable t) ; gets evalled
-(make-obsolete-variable 'mail-mailer-swallows-blank-line
- "no need to set this on any modern system."
- "24.1" 'set)
-
(defvar mail-mode-syntax-table
;; define-derived-mode will make it inherit from text-mode-syntax-table.
(let ((st (make-syntax-table)))
@@ -877,7 +863,7 @@ The variable is used to trigger insertion of the \"Mail-Followup-To\"
header when sending a message to a mailing list."
:type '(repeat string))
-(declare-function mml-to-mime "mml" ())
+(declare-function mm-long-lines-p "mm-bodies" (length))
(defun mail-send ()
"Send the message in the current buffer.
@@ -955,7 +941,11 @@ the user from the mailer."
(error "Invalid header line (maybe a continuation line lacks initial whitespace)"))
(forward-line 1)))
(goto-char opoint)
- (when mail-encode-mml
+ (require 'mml)
+ (when (or mail-encode-mml
+ ;; When we have long lines, we have to MIME encode
+ ;; to get line folding.
+ (mm-long-lines-p 1000))
(mml-to-mime)
(setq mail-encode-mml nil))
(run-hooks 'mail-send-hook)
@@ -1305,8 +1295,6 @@ external program defined by `sendmail-program'."
;; Insert an extra newline if we need it to work around
;; Sun's bug that swallows newlines.
(goto-char (1+ delimline))
- (if (eval mail-mailer-swallows-blank-line)
- (newline))
;; Find and handle any Fcc fields.
(goto-char (point-min))
(if (re-search-forward "^Fcc:" delimline t)
@@ -1491,28 +1479,6 @@ just append to the file, in Babyl format if necessary."
(with-current-buffer buffer
(set-visited-file-modtime)))))))))
-(defun mail-sent-via ()
- "Make a Sent-via header line from each To or Cc header line."
- (declare (obsolete "nobody can remember what it is for." "24.1"))
- (interactive)
- (save-excursion
- ;; put a marker at the end of the header
- (let ((end (copy-marker (mail-header-end)))
- (case-fold-search t))
- (goto-char (point-min))
- ;; search for the To: lines and make Sent-via: lines from them
- ;; search for the next To: line
- (while (re-search-forward "^\\(to\\|cc\\):" end t)
- ;; Grab this line plus all its continuations, sans the `to:'.
- (let ((to-line
- (buffer-substring (point)
- (progn
- (if (re-search-forward "^[^ \t\n]" end t)
- (backward-char 1)
- (goto-char end))
- (point)))))
- ;; Insert a copy, with altered header field name.
- (insert-before-markers "Sent-via:" to-line))))))
(defun mail-to ()
"Move point to end of To field, creating it if necessary."
@@ -1835,8 +1801,6 @@ If the current line has `mail-yank-prefix', insert it on the new line."
(or (bolp) (newline))
(goto-char start))))
-(define-obsolete-function-alias 'mail-attach-file #'mail-insert-file "24.1")
-
(declare-function mml-attach-file "mml"
(file &optional type description disposition))
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index 8ac0cd7e7c0..8cba2b14e14 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -171,7 +171,7 @@ attempt."
"The number of times smtpmail will retry sending when getting transient errors.
These are errors with a code of 4xx from the SMTP server, which
mean \"try again\"."
- :type 'integer
+ :type 'natnum
:version "27.1")
(defcustom smtpmail-store-queue-variables nil
@@ -342,8 +342,6 @@ for `smtpmail-try-auth-method'.")
;; Insert an extra newline if we need it to work around
;; Sun's bug that swallows newlines.
(goto-char (1+ delimline))
- (if (eval mail-mailer-swallows-blank-line t)
- (newline))
;; Find and handle any Fcc fields.
(goto-char (point-min))
(if (re-search-forward "^Fcc:" delimline t)
@@ -554,11 +552,9 @@ for `smtpmail-try-auth-method'.")
:create ask-for-password)))
(mech (or (plist-get auth-info :smtp-auth) (car mechs)))
(user (plist-get auth-info :user))
- (password (plist-get auth-info :secret))
+ (password (auth-info-password auth-info))
(save-function (and ask-for-password
(plist-get auth-info :save-function))))
- (when (functionp password)
- (setq password (funcall password)))
(when (and user
(not password))
;; The user has stored the user name, but not the password, so
@@ -573,9 +569,7 @@ for `smtpmail-try-auth-method'.")
:user smtpmail-smtp-user
:require '(:user :secret)
:create t))
- password (plist-get auth-info :secret)))
- (when (functionp password)
- (setq password (funcall password)))
+ password (auth-info-password auth-info)))
(let ((result (catch 'done
(if (and mech user password)
(smtpmail-try-auth-method process mech user password)
diff --git a/lisp/mail/undigest.el b/lisp/mail/undigest.el
index 03e77a83ce3..c6d29bc4e77 100644
--- a/lisp/mail/undigest.el
+++ b/lisp/mail/undigest.el
@@ -41,7 +41,8 @@ You may need to customize it for local needs."
(defconst rmail-digest-methods
- '(rmail-digest-parse-mime
+ '(rmail-digest-parse-mixed-mime
+ rmail-digest-parse-mime
rmail-digest-parse-rfc1153strict
rmail-digest-parse-rfc1153sloppy
rmail-digest-parse-rfc934)
@@ -52,6 +53,53 @@ A function returns nil if it cannot parse the digest. If it can, it
returns a list of cons pairs containing the start and end positions of
each undigestified message as markers.")
+(defun rmail-content-type-boundary (type)
+ "If Content-type is of type TYPE, return its boundary; otherwise, return nil."
+ (goto-char (point-min))
+ (let ((head-end (save-excursion (search-forward "\n\n" nil t) (point))))
+ (when (re-search-forward
+ (concat "^Content-type: " type ";"
+ "\\s-* boundary=\"?\\([^\";\n]+\\)[\";\n]")
+ head-end t)
+ (match-string 1))))
+
+(defun rmail-digest-parse-mixed-mime ()
+ "Like `rmail-digest-parse-mime', but for multipart/mixed messages."
+ (when-let ((boundary (rmail-content-type-boundary "multipart/mixed")))
+ (let ((global-sep (concat "\n--" boundary))
+ (digest (concat "^Content-type: multipart/digest;"
+ "\\s-* boundary=\"?\\([^\";\n]+\\)[\";\n]"))
+ result)
+ (search-forward global-sep nil t)
+ (while (not (or result (eobp)))
+ ;; For each part, see if it is a multipart/digest.
+ (let* ((limit (save-excursion (search-forward global-sep nil 'move)
+ (point)))
+ (beg (and (re-search-forward digest limit t)
+ (match-beginning 0)))
+ digest-sep)
+ (when (and beg
+ (setq digest-sep (concat "\n--" (match-string 1)))
+ ;; Search for 1st sep.
+ (search-forward digest-sep nil t))
+ ;; Skip body part headers.
+ (search-forward "\n\n" nil t)
+ ;; Push the 1st message.
+ (push (cons (copy-marker beg) (copy-marker (point-marker) t))
+ result)
+ ;; Push the rest of the messages.
+ (let ((start (make-marker))
+ done)
+ (while (and (search-forward digest-sep limit 'move) (not done))
+ (move-marker start (match-beginning 0))
+ (and (looking-at "--$") (setq done t))
+ (search-forward "\n\n")
+ (push (cons (copy-marker start)
+ (copy-marker (point-marker) t))
+ result))))
+ (goto-char limit)))
+ (nreverse result))))
+
(defun rmail-digest-parse-mime ()
(goto-char (point-min))
(when (let ((head-end (progn (search-forward "\n\n" nil t) (point))))
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el
index 8ce5afa9622..9e7194e4a02 100644
--- a/lisp/mail/unrmail.el
+++ b/lisp/mail/unrmail.el
@@ -208,7 +208,7 @@ The variable `unrmail-mbox-format' controls which mbox format to use."
(setq mail-from (or (let ((from (mail-fetch-field "Mail-From")))
;; mail-mbox-from (below) returns a
;; string that ends in a newline, but
- ;; but mail-fetch-field does not, so
+ ;; mail-fetch-field does not, so
;; we append a newline here.
(if from
(format "%s\n" from)))
diff --git a/lisp/man.el b/lisp/man.el
index adf244a11ad..951e0ef9add 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1976,6 +1976,34 @@ Uses `Man-name-local-regexp'."
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))
+(put 'Man-bookmark-jump 'bookmark-handler-type "Man")
+
+;;; Mouse support
+(defun Man-at-mouse (e)
+ "Open man manual at point."
+ (interactive "e")
+ (save-excursion
+ (mouse-set-point e)
+ (man (Man-default-man-entry))))
+
+;;;###autoload
+(defun Man-context-menu (menu click)
+ "Populate MENU with commands that open a man page at point."
+ (save-excursion
+ (mouse-set-point click)
+ (when (save-excursion
+ (skip-syntax-backward "^ ")
+ (and (looking-at
+ "[[:space:]]*\\([[:alnum:]_-]+([[:alnum:]]+)\\)")
+ (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")
+ 'man-separator)))
+ menu)
+
;; Init the man package variables, if not already done.
(Man-init-defvars)
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index e0cf6c588c4..12a0b4d328f 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -96,18 +96,28 @@
(bindings--define-key menu [separator-print]
menu-bar-separator)
- (unless (featurep 'ns)
- (bindings--define-key menu [close-tab]
- '(menu-item "Close Tab" tab-close
- :visible (fboundp 'tab-close)
- :help "Close currently selected tab"))
- (bindings--define-key menu [make-tab]
- '(menu-item "New Tab" tab-new
- :visible (fboundp 'tab-new)
- :help "Open a new tab"))
-
- (bindings--define-key menu [separator-tab]
- menu-bar-separator))
+ (bindings--define-key menu [close-tab]
+ '(menu-item "Close Tab" tab-close
+ :visible (fboundp 'tab-close)
+ :help "Close currently selected tab"))
+ (bindings--define-key menu [make-tab]
+ '(menu-item "New Tab" tab-new
+ :visible (fboundp 'tab-new)
+ :help "Open a new tab"))
+
+ (bindings--define-key menu [separator-tab]
+ menu-bar-separator)
+
+ (bindings--define-key menu [undelete-frame-mode]
+ '(menu-item "Allow Undeleting Frames" undelete-frame-mode
+ :help "Allow frames to be restored after deletion"
+ :button (:toggle . undelete-frame-mode)))
+
+ (bindings--define-key menu [undelete-last-deleted-frame]
+ '(menu-item "Undelete Frame" undelete-frame
+ :enable (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
;; event.
@@ -121,9 +131,9 @@
:visible (fboundp 'make-frame-on-monitor)
:help "Open a new frame on another monitor"))
(bindings--define-key menu [make-frame-on-display]
- '(menu-item "New Frame on Display..." make-frame-on-display
+ '(menu-item "New Frame on Display Server..." make-frame-on-display
:visible (fboundp 'make-frame-on-display)
- :help "Open a new frame on another display"))
+ :help "Open a new frame on a display server"))
(bindings--define-key menu [make-frame]
'(menu-item "New Frame" make-frame-command
:visible (fboundp 'make-frame-command)
@@ -168,17 +178,23 @@
t))
:help "Recover edits from a crashed session"))
(bindings--define-key menu [revert-buffer]
- '(menu-item "Revert Buffer" revert-buffer
- :enable (or (not (eq revert-buffer-function
- 'revert-buffer--default))
- (not (eq
- revert-buffer-insert-file-contents-function
- 'revert-buffer-insert-file-contents--default-function))
- (and buffer-file-number
- (or (buffer-modified-p)
- (not (verify-visited-file-modtime
- (current-buffer))))))
- :help "Re-read current buffer from its file"))
+ '(menu-item
+ "Revert Buffer" revert-buffer
+ :enable
+ (or (not (eq revert-buffer-function
+ 'revert-buffer--default))
+ (not (eq
+ revert-buffer-insert-file-contents-function
+ 'revert-buffer-insert-file-contents--default-function))
+ (and buffer-file-number
+ (or (buffer-modified-p)
+ (not (verify-visited-file-modtime
+ (current-buffer)))
+ ;; Enable if the buffer has a different
+ ;; writeability than the file.
+ (not (eq (not buffer-read-only)
+ (file-writable-p buffer-file-name))))))
+ :help "Re-read current buffer from its file"))
(bindings--define-key menu [write-file]
'(menu-item "Save As..." write-file
:enable (and (menu-bar-menu-frame-live-and-visible-p)
@@ -295,7 +311,7 @@
(isearch-update-ring string t)
(re-search-backward string)))
-;; The Edit->Search->Incremental Search menu
+;; The Edit->Incremental Search menu
(defvar menu-bar-i-search-menu
(let ((menu (make-sparse-keymap "Incremental Search")))
(bindings--define-key menu [isearch-forward-symbol-at-point]
@@ -323,12 +339,6 @@
(defvar menu-bar-search-menu
(let ((menu (make-sparse-keymap "Search")))
-
- (bindings--define-key menu [i-search]
- `(menu-item "Incremental Search" ,menu-bar-i-search-menu))
- (bindings--define-key menu [separator-tag-isearch]
- menu-bar-separator)
-
(bindings--define-key menu [tags-continue]
'(menu-item "Continue Tags Search" fileloop-continue
:enable (and (featurep 'fileloop)
@@ -485,6 +495,9 @@
(bindings--define-key menu [replace]
`(menu-item "Replace" ,menu-bar-replace-menu))
+ (bindings--define-key menu [i-search]
+ `(menu-item "Incremental Search" ,menu-bar-i-search-menu))
+
(bindings--define-key menu [search]
`(menu-item "Search" ,menu-bar-search-menu))
@@ -571,9 +584,6 @@
menu))
-(define-obsolete-function-alias
- 'menu-bar-kill-ring-save 'kill-ring-save "24.1")
-
;; These are alternative definitions for the cut, paste and copy
;; menu items. Use them if your system expects these to use the clipboard.
@@ -590,7 +600,8 @@
"Insert the clipboard contents, or the last stretch of killed text."
(interactive "*")
(let ((select-enable-clipboard t)
- ;; Ensure that we defeat the DWIM login in `gui-selection-value'.
+ ;; Ensure that we defeat the DWIM logic in `gui-selection-value'
+ ;; (i.e., that gui--clipboard-selection-unchanged-p returns nil).
(gui--last-selected-text-clipboard nil))
(yank)))
@@ -735,7 +746,11 @@ by \"Save Options\" in Custom buffers.")
;; interactively, because the purpose is to mark the variable as a
;; candidate for `Save Options', and we do not want to save options that
;; the user has already set explicitly in the init file.
- (when interactively (customize-mark-as-set ',variable)))
+ (when interactively
+ (customize-mark-as-set ',variable))
+ ;; Toggle menu items must make sure that the menu is updated so
+ ;; that toggle marks are drawn in the right state.
+ (force-mode-line-update t))
'(menu-item ,item-name ,command :help ,help
:button (:toggle . (and (default-boundp ',variable)
(default-value ',variable)))
@@ -778,6 +793,7 @@ The selected font will be the default on both the existing and future frames."
(dolist (elt '(scroll-bar-mode
debug-on-quit debug-on-error
;; Somehow this works, when tool-bar and menu-bar don't.
+ desktop-save-mode
tooltip-mode window-divider-mode
save-place-mode uniquify-buffer-name-style fringe-mode
indicate-empty-lines indicate-buffer-boundaries
@@ -2175,12 +2191,12 @@ otherwise it could decide to silently do nothing."
(defcustom yank-menu-length 20
"Text of items in `yank-menu' longer than this will be truncated."
- :type 'integer
+ :type 'natnum
:group 'menu)
(defcustom yank-menu-max-items 60
"Maximum number of entries to display in the `yank-menu'."
- :type 'integer
+ :type 'natnum
:group 'menu
:version "29.1")
@@ -2306,8 +2322,29 @@ Buffers menu is regenerated."
(cdr elt)))
buf)))
-;; Used to cache the menu entries for commands in the Buffers menu
-(defvar menu-bar-buffers-menu-command-entries nil)
+(defvar menu-bar-buffers-menu-command-entries
+ (list '(command-separator "--")
+ (list 'next-buffer
+ 'menu-item
+ "Next Buffer"
+ 'next-buffer
+ :help "Switch to the \"next\" buffer in a cyclic order")
+ (list 'previous-buffer
+ 'menu-item
+ "Previous Buffer"
+ 'previous-buffer
+ :help "Switch to the \"previous\" buffer in a cyclic order")
+ (list 'select-named-buffer
+ 'menu-item
+ "Select Named Buffer..."
+ 'switch-to-buffer
+ :help "Prompt for a buffer name, and select that buffer in the current window")
+ (list 'list-all-buffers
+ 'menu-item
+ "List All Buffers"
+ 'list-buffers
+ :help "Pop up a window listing all Emacs buffers"))
+ "Entries to be included at the end of the \"Buffers\" menu.")
(defvar menu-bar-select-buffer-function 'switch-to-buffer
"Function to select the buffer chosen from the `Buffers' menu-bar menu.
@@ -2332,9 +2369,13 @@ It must accept a buffer as its only required argument.")
(and (lookup-key (current-global-map) [menu-bar buffer])
(or force (frame-or-buffer-changed-p))
(let ((buffers (buffer-list))
- (frames (frame-list))
- buffers-menu)
-
+ frames buffers-menu)
+ ;; Ignore the initial frame if present. It can happen if
+ ;; Emacs was started as a daemon. (bug#53740)
+ (dolist (frame (frame-list))
+ (unless (equal (terminal-name (frame-terminal frame))
+ "initial_terminal")
+ (push frame frames)))
;; Make the menu of buffers proper.
(setq buffers-menu
(let ((i 0)
@@ -2388,35 +2429,7 @@ It must accept a buffer as its only required argument.")
`((frames-separator "--")
(frames menu-item "Frames" ,frames-menu))))))
- ;; Add in some normal commands at the end of the menu. We use
- ;; the copy cached in `menu-bar-buffers-menu-command-entries'
- ;; if it's been set already. Note that we can't use constant
- ;; lists for the menu-entries, because the low-level menu-code
- ;; modifies them.
- (unless menu-bar-buffers-menu-command-entries
- (setq menu-bar-buffers-menu-command-entries
- (list '(command-separator "--")
- (list 'next-buffer
- 'menu-item
- "Next Buffer"
- 'next-buffer
- :help "Switch to the \"next\" buffer in a cyclic order")
- (list 'previous-buffer
- 'menu-item
- "Previous Buffer"
- 'previous-buffer
- :help "Switch to the \"previous\" buffer in a cyclic order")
- (list 'select-named-buffer
- 'menu-item
- "Select Named Buffer..."
- 'switch-to-buffer
- :help "Prompt for a buffer name, and select that buffer in the current window")
- (list 'list-all-buffers
- 'menu-item
- "List All Buffers"
- 'list-buffers
- :help "Pop up a window listing all Emacs buffers"
- ))))
+ ;; Add in some normal commands at the end of the menu.
(setq buffers-menu
(nconc buffers-menu menu-bar-buffers-menu-command-entries))
@@ -2527,7 +2540,7 @@ Use \\[menu-bar-mode] to make the menu bar appear."))))
(put 'menu-bar-mode 'standard-value '(t))
(defun toggle-menu-bar-mode-from-frame (&optional arg)
- "Toggle display of the menu bar of the current frame.
+ "Toggle display of the menu bar.
See `menu-bar-mode' for more information."
(interactive (list (or current-prefix-arg 'toggle)))
(if (eq arg 'toggle)
@@ -2619,8 +2632,11 @@ FROM-MENU-BAR, if non-nil, means we are dropping one of menu-bar's menus."
;; `setup-specified-language-environment', for instance,
;; expects this to be set from a menu keymap.
(setq last-command-event (car (last event)))
- ;; mouse-major-mode-menu was using `command-execute' instead.
- (call-interactively cmd))))
+ (setq from--tty-menu-p nil)
+ ;; Signal use-dialog-box-p this command was invoked from a menu.
+ (let ((from--tty-menu-p t))
+ ;; mouse-major-mode-menu was using `command-execute' instead.
+ (call-interactively cmd)))))
(defun popup-menu-normalize-position (position)
"Convert the POSITION to the form which `popup-menu' expects internally.
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index ef0a76b9a49..f011ea47f80 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -95,9 +95,9 @@ RANGE is read in interactive use."
Remove all of the messages (files) within the current folder, and
then remove the folder (directory) itself.
-Run the abnormal hook `mh-kill-folder-suppress-prompt-hooks'. The
-hook functions are called with no arguments and should return a
-non-nil value to suppress the normal prompt when you remove a
+Run the abnormal hook `mh-kill-folder-suppress-prompt-functions'.
+The hook functions are called with no arguments and should return
+a non-nil value to suppress the normal prompt when you remove a
folder. This is useful for folders that are easily regenerated."
(interactive)
(if (or (run-hook-with-args-until-success
diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el
index a2ea7610139..3e731e22a1f 100644
--- a/lisp/mh-e/mh-limit.el
+++ b/lisp/mh-e/mh-limit.el
@@ -143,7 +143,7 @@ Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
;;; Support Routines
(defun mh-subject-to-sequence (all)
- "Put all following messages with same subject in sequence 'subject.
+ "Put all following messages with same subject in sequence `subject'.
If arg ALL is t, move to beginning of folder buffer to collect all
messages.
If arg ALL is nil, collect only messages from current one on forward.
@@ -161,7 +161,7 @@ Return number of messages put in the sequence:
(mh-subject-to-sequence-unthreaded all)))
(defun mh-subject-to-sequence-threaded (all)
- "Put all messages with the same subject in the 'subject sequence.
+ "Put all messages with the same subject in the `subject' sequence.
This function works when the folder is threaded. In this
situation the subject could get truncated and so the normal
@@ -192,7 +192,7 @@ are taken into account."
It would be desirable to avoid hard-coding this.")
(defun mh-subject-to-sequence-unthreaded (all)
- "Put all following messages with same subject in sequence 'subject.
+ "Put all following messages with same subject in sequence `subject'.
This function only works with an unthreaded folder. If arg ALL is
t, move to beginning of folder buffer to collect all messages. If
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index 98a20b7bb4f..b93f7d8c412 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -1141,15 +1141,7 @@ this ;-)"
"Check if show buffer is small.
This is used to decide if smileys and graphical emphasis should be
displayed."
- (let ((max nil))
- ;; FIXME: font-lock-maximum-size is obsolete.
- (when (and (boundp 'font-lock-maximum-size) font-lock-maximum-size)
- (cond ((numberp font-lock-maximum-size)
- (setq max font-lock-maximum-size))
- ((listp font-lock-maximum-size)
- (setq max (cdr (or (assoc 'mh-show-mode font-lock-maximum-size)
- (assoc t font-lock-maximum-size)))))))
- (or (not (numberp max)) (>= (/ max 8) (buffer-size)))))
+ (>= 64000 (buffer-size)))
@@ -1764,7 +1756,7 @@ initialized. Always use the command `mh-have-file-command'.")
;;;###mh-autoload
(defun mh-have-file-command ()
"Return t if `file' command is on the system.
-'file -i' is used to get MIME type of composition insertion."
+\"file -i\" is used to get MIME type of composition insertion."
(when (eq mh-have-file-command 'undefined)
(setq mh-have-file-command
(and (executable-find "file") ; file command exists
diff --git a/lisp/midnight.el b/lisp/midnight.el
index 3e309a5c881..60d9b565ef0 100644
--- a/lisp/midnight.el
+++ b/lisp/midnight.el
@@ -67,14 +67,14 @@ The autokilling is done by `clean-buffer-list' when it is in `midnight-hook'.
Currently displayed and/or modified (unsaved) buffers, as well as buffers
matching `clean-buffer-list-kill-never-buffer-names' and
`clean-buffer-list-kill-never-regexps' are excluded."
- :type 'integer)
+ :type 'natnum)
(defcustom clean-buffer-list-delay-special 3600
"The number of seconds before some buffers become eligible for autokilling.
Buffers matched by `clean-buffer-list-kill-regexps' and
`clean-buffer-list-kill-buffer-names' are killed if they were last
displayed more than this many seconds ago."
- :type 'integer)
+ :type 'natnum)
(defcustom clean-buffer-list-kill-regexps '("\\`\\*Man ")
"List of regexps saying which buffers will be killed at midnight.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index ab760a42d15..9d2abbd1180 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -864,7 +864,11 @@ Intended to be called via `clear-message-function'."
(setq minibuffer-message-timer nil))
(when (overlayp minibuffer-message-overlay)
(delete-overlay minibuffer-message-overlay)
- (setq minibuffer-message-overlay nil))))
+ (setq minibuffer-message-overlay nil)))
+
+ ;; Return nil telling the caller that the message
+ ;; should be also handled by the caller.
+ nil)
(setq clear-message-function 'clear-minibuffer-message)
@@ -894,11 +898,23 @@ If the current buffer is not a minibuffer, erase its entire contents."
(defcustom completion-auto-help t
"Non-nil means automatically provide help for invalid completion input.
-If the value is t the *Completions* buffer is displayed whenever completion
+If the value is t, the *Completions* buffer is displayed whenever completion
is requested but cannot be done.
If the value is `lazy', the *Completions* buffer is only displayed after
-the second failed attempt to complete."
- :type '(choice (const nil) (const t) (const lazy)))
+the second failed attempt to complete.
+If the value is `always', the *Completions* buffer is always shown
+after a completion attempt, and the list of completions is updated if
+already visible.
+If the value is `visible', the *Completions* buffer is displayed
+whenever completion is requested but cannot be done for the first time,
+but remains visible thereafter, and the list of completions in it is
+updated for subsequent attempts to complete.."
+ :type '(choice (const :tag "Don't show" nil)
+ (const :tag "Show only when cannot complete" t)
+ (const :tag "Show after second failed completion attempt" lazy)
+ (const :tag
+ "Leave visible after first failed completion" visible)
+ (const :tag "Always visible" always)))
(defvar completion-styles-alist
'((emacs21
@@ -985,7 +1001,11 @@ and DOC describes the way this style of completion works.")
The available styles are listed in `completion-styles-alist'.
Note that `completion-category-overrides' may override these
-styles for specific categories, such as files, buffers, etc."
+styles for specific categories, such as files, buffers, etc.
+
+Note that Tramp host name completion (e.g., \"/ssh:ho<TAB>\")
+currently doesn't work if this list doesn't contain at least one
+of `basic', `emacs22' or `emacs21'."
:type completion--styles-type
:version "23.1")
@@ -1004,7 +1024,9 @@ an association list that can specify properties such as:
- `styles': the list of `completion-styles' to use for that category.
- `cycle': the `completion-cycle-threshold' to use for that category.
Categories are symbols such as `buffer' and `file', used when
-completing buffer and file names, respectively.")
+completing buffer and file names, respectively.
+
+Also see `completion-category-overrides'.")
(defcustom completion-category-overrides nil
"List of category-specific user overrides for completion styles.
@@ -1014,7 +1036,9 @@ an association list that can specify properties such as:
- `cycle': the `completion-cycle-threshold' to use for that category.
Categories are symbols such as `buffer' and `file', used when
completing buffer and file names, respectively.
-This overrides the defaults specified in `completion-category-defaults'."
+
+If a property in a category is specified by this variable, it
+overrides the default specified in `completion-category-defaults'."
:version "25.1"
:type `(alist :key-type (choice :tag "Category"
(const buffer)
@@ -1120,6 +1144,7 @@ Moves point to the end of the new text."
;; The properties on `newtext' include things like the
;; `completions-first-difference' face, which we don't want to
;; include upon insertion.
+ (setq newtext (copy-sequence newtext)) ;Don't modify the arg by side-effect.
(if minibuffer-allow-text-properties
;; If we're preserving properties, then just remove the faces
;; and other properties added by the completion machinery.
@@ -1169,6 +1194,18 @@ completion candidates than this number."
:version "24.1"
:type completion--cycling-threshold-type)
+(defcustom completions-sort 'alphabetical
+ "Sort candidates in the *Completions* buffer.
+
+The value can be nil to disable sorting, `alphabetical' for
+alphabetical sorting or a custom sorting function. The sorting
+function takes and returns a list of completion candidate
+strings."
+ :type '(choice (const :tag "No sorting" nil)
+ (const :tag "Alphabetical sorting" alphabetical)
+ (function :tag "Custom function"))
+ :version "29.1")
+
(defcustom completions-group nil
"Enable grouping of completion candidates in the *Completions* buffer.
See also `completions-group-format' and `completions-group-sort'."
@@ -1327,16 +1364,18 @@ when the buffer's text is already an exact match."
(completion--cache-all-sorted-completions beg end comps)
(minibuffer-force-complete beg end))
(completed
- ;; We could also decide to refresh the completions,
- ;; if they're displayed (and assuming there are
- ;; completions left).
- (minibuffer-hide-completions)
- (if exact
- ;; If completion did not put point at end of field,
- ;; it's a sign that completion is not finished.
- (completion--done completion
- (if (< comp-pos (length completion))
- 'exact 'unknown))))
+ (cond
+ ((pcase completion-auto-help
+ ('visible (get-buffer-window "*Completions*" 0))
+ ('always t))
+ (minibuffer-completion-help beg end))
+ (t (minibuffer-hide-completions)
+ (when exact
+ ;; If completion did not put point at end of field,
+ ;; it's a sign that completion is not finished.
+ (completion--done completion
+ (if (< comp-pos (length completion))
+ 'exact 'unknown))))))
;; Show the completion table, if requested.
((not exact)
(if (pcase completion-auto-help
@@ -1380,26 +1419,42 @@ scroll the window of possible completions."
;; and this command is repeated, scroll that window.
((and (window-live-p minibuffer-scroll-window)
(eq t (frame-visible-p (window-frame minibuffer-scroll-window))))
- (let ((window minibuffer-scroll-window)
- (reverse (equal (this-command-keys) [backtab])))
+ (let ((window minibuffer-scroll-window))
(with-current-buffer (window-buffer window)
- (if (pos-visible-in-window-p (if reverse (point-min) (point-max)) window)
- ;; If end or beginning is in view, scroll up to the
- ;; beginning or end respectively.
- (if reverse
- (set-window-point window (point-max))
- (set-window-start window (point-min) nil))
- ;; Else scroll down one screen.
- (with-selected-window window
- (if reverse (scroll-down) (scroll-up))))
- nil)))
+ (cond
+ ;; Here this is possible only when second-tab, but instead of
+ ;; scrolling the completion list window, switch to it below,
+ ;; outside of `with-current-buffer'.
+ ((eq completion-auto-select 'second-tab))
+ ;; Reverse tab
+ ((equal (this-command-keys) [backtab])
+ (if (pos-visible-in-window-p (point-min) window)
+ ;; If beginning is in view, scroll up to the end.
+ (set-window-point window (point-max))
+ ;; Else scroll down one screen.
+ (with-selected-window window (scroll-down))))
+ ;; Normal tab
+ (t
+ (if (pos-visible-in-window-p (point-max) window)
+ ;; If end is in view, scroll up to the end.
+ (set-window-start window (point-min) nil)
+ ;; Else scroll down one screen.
+ (with-selected-window window (scroll-up))))))
+ (when (eq completion-auto-select 'second-tab)
+ (switch-to-completions))
+ nil))
;; If we're cycling, keep on cycling.
((and completion-cycling completion-all-sorted-completions)
(minibuffer-force-complete beg end)
t)
- (t (pcase (completion--do-completion beg end)
- (#b000 nil)
- (_ t)))))
+ (t (prog1 (pcase (completion--do-completion beg end)
+ (#b000 nil)
+ (_ t))
+ (when (and (eq completion-auto-select t)
+ (window-live-p minibuffer-scroll-window)
+ (eq t (frame-visible-p (window-frame minibuffer-scroll-window))))
+ ;; When the completion list window was displayed, select it.
+ (switch-to-completions))))))
(defun completion--cache-all-sorted-completions (beg end comps)
(add-hook 'after-change-functions
@@ -1622,8 +1677,8 @@ DONT-CYCLE tells the function not to setup cycling."
map)))))))))
(defvar minibuffer-confirm-exit-commands
- '(completion-at-point minibuffer-complete
- minibuffer-complete-word PC-complete PC-complete-word)
+ '( completion-at-point minibuffer-complete
+ minibuffer-complete-word)
"List of commands which cause an immediately following
`minibuffer-complete-and-exit' to ask for extra confirmation.")
@@ -1671,52 +1726,57 @@ If `minibuffer-completion-confirm' is `confirm-after-completion',
"Exit from `require-match' minibuffer.
COMPLETION-FUNCTION is called if the current buffer's content does not
appear to be a match."
- (cond
- ;; Allow user to specify null string
+ (cond
+ ;; Allow user to specify null string
((= beg end) (funcall exit-function))
- ((test-completion (buffer-substring beg end)
- minibuffer-completion-table
- minibuffer-completion-predicate)
- ;; FIXME: completion-ignore-case has various slightly
- ;; incompatible meanings. E.g. it can reflect whether the user
- ;; wants completion to pay attention to case, or whether the
- ;; string will be used in a context where case is significant.
- ;; E.g. usually try-completion should obey the first, whereas
- ;; test-completion should obey the second.
- (when completion-ignore-case
- ;; Fixup case of the field, if necessary.
- (let* ((string (buffer-substring beg end))
- (compl (try-completion
- string
- minibuffer-completion-table
- minibuffer-completion-predicate)))
- (when (and (stringp compl) (not (equal string compl))
- ;; If it weren't for this piece of paranoia, I'd replace
- ;; the whole thing with a call to do-completion.
- ;; This is important, e.g. when the current minibuffer's
- ;; content is a directory which only contains a single
- ;; file, so `try-completion' actually completes to
- ;; that file.
- (= (length string) (length compl)))
- (completion--replace beg end compl))))
- (funcall exit-function))
-
- ((memq minibuffer-completion-confirm '(confirm confirm-after-completion))
- ;; The user is permitted to exit with an input that's rejected
- ;; by test-completion, after confirming her choice.
- (if (or (eq last-command this-command)
- ;; For `confirm-after-completion' we only ask for confirmation
- ;; if trying to exit immediately after typing TAB (this
- ;; catches most minibuffer typos).
- (and (eq minibuffer-completion-confirm 'confirm-after-completion)
- (not (memq last-command minibuffer-confirm-exit-commands))))
+ ;; The CONFIRM argument is a predicate.
+ ((and (functionp minibuffer-completion-confirm)
+ (funcall minibuffer-completion-confirm
+ (buffer-substring beg end)))
+ (funcall exit-function))
+ ;; See if we have a completion from the table.
+ ((test-completion (buffer-substring beg end)
+ minibuffer-completion-table
+ minibuffer-completion-predicate)
+ ;; FIXME: completion-ignore-case has various slightly
+ ;; incompatible meanings. E.g. it can reflect whether the user
+ ;; wants completion to pay attention to case, or whether the
+ ;; string will be used in a context where case is significant.
+ ;; E.g. usually try-completion should obey the first, whereas
+ ;; test-completion should obey the second.
+ (when completion-ignore-case
+ ;; Fixup case of the field, if necessary.
+ (let* ((string (buffer-substring beg end))
+ (compl (try-completion
+ string
+ minibuffer-completion-table
+ minibuffer-completion-predicate)))
+ (when (and (stringp compl) (not (equal string compl))
+ ;; If it weren't for this piece of paranoia, I'd replace
+ ;; the whole thing with a call to do-completion.
+ ;; This is important, e.g. when the current minibuffer's
+ ;; content is a directory which only contains a single
+ ;; file, so `try-completion' actually completes to
+ ;; that file.
+ (= (length string) (length compl)))
+ (completion--replace beg end compl))))
+ (funcall exit-function))
+ ;; The user is permitted to exit with an input that's rejected
+ ;; by test-completion, after confirming her choice.
+ ((memq minibuffer-completion-confirm '(confirm confirm-after-completion))
+ (if (or (eq last-command this-command)
+ ;; For `confirm-after-completion' we only ask for confirmation
+ ;; if trying to exit immediately after typing TAB (this
+ ;; catches most minibuffer typos).
+ (and (eq minibuffer-completion-confirm 'confirm-after-completion)
+ (not (memq last-command minibuffer-confirm-exit-commands))))
(funcall exit-function)
- (minibuffer-message "Confirm")
- nil))
+ (minibuffer-message "Confirm")
+ nil))
- (t
- ;; Call do-completion, but ignore errors.
- (funcall completion-function))))
+ (t
+ ;; Call do-completion, but ignore errors.
+ (funcall completion-function))))
(defun completion--try-word-completion (string table predicate point md)
(let ((comp (completion-try-completion string table predicate point md)))
@@ -1826,6 +1886,17 @@ Return nil if there is no valid completion, else t."
This face is only used if the strings used for completions
doesn't already specify a face.")
+(defface completions-highlight
+ '((t :inherit highlight))
+ "Default face for highlighting the current completion candidate."
+ :version "29.1")
+
+(defcustom completions-highlight-face 'completions-highlight
+ "A face name to highlight the current completion candidate.
+If the value is nil, no highlighting is performed."
+ :type '(choice (const nil) face)
+ :version "29.1")
+
(defcustom completions-format 'horizontal
"Define the appearance and sorting of completions.
If the value is `vertical', display completions sorted vertically
@@ -1845,6 +1916,15 @@ completions."
:type 'boolean
:version "28.1")
+(defcustom completions-header-format
+ (propertize "%s possible completions:\n" 'face 'shadow)
+ "Format of completions header.
+It may contain one %s to show the total count of completions.
+When nil, no header is shown."
+ :type '(choice (const :tag "No header" nil)
+ (string :tag "Header format string"))
+ :version "29.1")
+
(defun completion--insert-strings (strings &optional group-fun)
"Insert a list of STRINGS into the current buffer.
The candidate strings are inserted into the buffer depending on the
@@ -1984,7 +2064,8 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(when title
(insert (format completions-group-format title) "\n")))))
(completion--insert str group-fun)
- (insert "\n")))))
+ (insert "\n")))
+ (delete-char -1)))
(defun completion--insert (str group-fun)
(if (not (consp str))
@@ -1996,7 +2077,7 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(funcall group-fun str 'transform)
str))
(point))
- `(mouse-face highlight completion--string ,str))
+ `(mouse-face highlight cursor-face ,completions-highlight-face completion--string ,str))
;; If `str' is a list that has 2 elements,
;; then the second element is a suffix annotation.
;; If `str' has 3 elements, then the second element
@@ -2006,11 +2087,11 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(when prefix
(let ((beg (point))
(end (progn (insert prefix) (point))))
- (put-text-property beg end 'mouse-face nil)))
+ (add-text-properties beg end `(mouse-face nil completion--string ,(car str)))))
(completion--insert (car str) group-fun)
(let ((beg (point))
(end (progn (insert suffix) (point))))
- (put-text-property beg end 'mouse-face nil)
+ (add-text-properties beg end `(mouse-face nil completion--string ,(car str)))
;; Put the predefined face only when suffix
;; is added via annotation-function without prefix,
;; and when the caller doesn't use own face.
@@ -2054,7 +2135,7 @@ and with BASE-SIZE appended as the last element."
(lambda (elem)
(let ((str
;; Don't modify the string itself, but a copy, since the
- ;; the string may be read-only or used for other purposes.
+ ;; string may be read-only or used for other purposes.
;; Furthermore, since `completions' may come from
;; display-completion-list, `elem' may be a list.
(if (consp elem)
@@ -2107,10 +2188,9 @@ candidates."
(with-current-buffer standard-output
(goto-char (point-max))
- (if (null completions)
- (insert "There are no possible completions of what you have typed.")
- (insert "Possible completions are:\n")
- (completion--insert-strings completions group-fun))))
+ (when completions-header-format
+ (insert (format completions-header-format (length completions))))
+ (completion--insert-strings completions group-fun)))
(run-hooks 'completion-setup-hook)
nil)
@@ -2145,25 +2225,6 @@ These include:
`exact' - text is a valid completion but may be further
completed.")
-(defvar completion-annotate-function
- nil
- ;; Note: there's a lot of scope as for when to add annotations and
- ;; what annotations to add. E.g. completing-help.el allowed adding
- ;; the first line of docstrings to M-x completion. But there's
- ;; a tension, since such annotations, while useful at times, can
- ;; actually drown the useful information.
- ;; So completion-annotate-function should be used parsimoniously, or
- ;; else only used upon a user's request (e.g. we could add a command
- ;; to completion-list-mode to add annotations to the current
- ;; completions).
- "Function to add annotations in the *Completions* buffer.
-The function takes a completion and should either return nil, or a string that
-will be displayed next to the completion. The function can access the
-completion table and predicates via `minibuffer-completion-table' and related
-variables.")
-(make-obsolete-variable 'completion-annotate-function
- 'completion-extra-properties "24.1")
-
(defun completion--done (string &optional finished message)
(let* ((exit-fun (plist-get completion-extra-properties :exit-function))
(pre-msg (and exit-fun (current-message))))
@@ -2182,6 +2243,19 @@ variables.")
(equal pre-msg (and exit-fun (current-message))))
(completion--message message))))
+(defcustom completions-max-height nil
+ "Maximum height for *Completions* buffer window."
+ :type '(choice (const nil) natnum)
+ :version "29.1")
+
+(defun completions--fit-window-to-buffer (&optional win &rest _)
+ "Resize *Completions* buffer window."
+ (if temp-buffer-resize-mode
+ (let ((temp-buffer-max-height (or completions-max-height
+ temp-buffer-max-height)))
+ (resize-temp-buffer-window win))
+ (fit-window-to-buffer win completions-max-height)))
+
(defun minibuffer-completion-help (&optional start end)
"Display a list of possible completions of the current minibuffer contents."
(interactive)
@@ -2211,6 +2285,9 @@ variables.")
(let* ((last (last completions))
(base-size (or (cdr last) 0))
(prefix (unless (zerop base-size) (substring string 0 base-size)))
+ (base-prefix (buffer-substring (minibuffer--completion-prompt-end)
+ (+ start base-size)))
+ (base-suffix (buffer-substring (point) (point-max)))
(all-md (completion--metadata (buffer-substring-no-properties
start (point))
base-size md
@@ -2218,8 +2295,7 @@ variables.")
minibuffer-completion-predicate))
(ann-fun (or (completion-metadata-get all-md 'annotation-function)
(plist-get completion-extra-properties
- :annotation-function)
- completion-annotate-function))
+ :annotation-function)))
(aff-fun (or (completion-metadata-get all-md 'affixation-function)
(plist-get completion-extra-properties
:affixation-function)))
@@ -2245,9 +2321,7 @@ variables.")
,(if (eq (selected-window) (minibuffer-window))
'display-buffer-at-bottom
'display-buffer-below-selected))
- ,(if temp-buffer-resize-mode
- '(window-height . resize-temp-buffer-window)
- '(window-height . fit-window-to-buffer))
+ (window-height . completions--fit-window-to-buffer)
,(when temp-buffer-resize-mode
'(preserve-size . (nil . t)))
(body-function
@@ -2264,7 +2338,10 @@ variables.")
;; same, but not always.
(setq completions (if sort-fun
(funcall sort-fun completions)
- (sort completions 'string-lessp)))
+ (pcase completions-sort
+ ('nil completions)
+ ('alphabetical (sort completions #'string-lessp))
+ (_ (funcall completions-sort completions)))))
;; After sorting, group the candidates using the
;; `group-function'.
@@ -2301,20 +2378,28 @@ variables.")
;; completion-all-completions does not give us the
;; necessary information.
end))
+ (setq-local completion-base-affixes
+ (list base-prefix base-suffix))
(setq-local completion-list-insert-choice-function
(let ((ctable minibuffer-completion-table)
(cpred minibuffer-completion-predicate)
(cprops completion-extra-properties))
(lambda (start end choice)
- (unless (or (zerop (length prefix))
- (equal prefix
- (buffer-substring-no-properties
- (max (point-min)
- (- start (length prefix)))
- start)))
- (message "*Completions* out of date"))
- ;; FIXME: Use `md' to do quoting&terminator here.
- (completion--replace start end choice)
+ (if (and (stringp start) (stringp end))
+ (progn
+ (delete-minibuffer-contents)
+ (insert start choice)
+ ;; Keep point after completion before suffix
+ (save-excursion (insert end)))
+ (unless (or (zerop (length prefix))
+ (equal prefix
+ (buffer-substring-no-properties
+ (max (point-min)
+ (- start (length prefix)))
+ start)))
+ (message "*Completions* out of date"))
+ ;; FIXME: Use `md' to do quoting&terminator here.
+ (completion--replace start end choice))
(let* ((minibuffer-completion-table ctable)
(minibuffer-completion-predicate cpred)
(completion-extra-properties cprops)
@@ -2335,6 +2420,7 @@ variables.")
"Get rid of an out-of-date *Completions* buffer."
;; FIXME: We could/should use minibuffer-scroll-window here, but it
;; can also point to the minibuffer-parent-window, so it's a bit tricky.
+ (interactive)
(let ((win (get-buffer-window "*Completions*" 0)))
(if win (with-selected-window win (bury-buffer)))))
@@ -2454,7 +2540,10 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'.
;; FIXME: Only works if completion-in-region-mode was activated via
;; completion-at-point called directly.
"M-?" #'completion-help-at-point
- "TAB" #'completion-at-point)
+ "TAB" #'completion-at-point
+ "M-<up>" #'minibuffer-previous-completion
+ "M-<down>" #'minibuffer-next-completion
+ "M-RET" #'minibuffer-choose-completion)
;; It is difficult to know when to exit completion-in-region-mode (i.e. hide
;; the *Completions*). Here's how previous packages did it:
@@ -2501,6 +2590,7 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'.
(cl-assert completion-in-region-mode-predicate)
(setq completion-in-region-mode--predicate
completion-in-region-mode-predicate)
+ (setq-local minibuffer-completion-auto-choose nil)
(add-hook 'post-command-hook #'completion-in-region--postch)
(push `(completion-in-region-mode . ,completion-in-region-mode-map)
minor-mode-overriding-map-alist)))
@@ -2662,11 +2752,15 @@ The completion method is determined by `completion-at-point-functions'."
"?" #'minibuffer-completion-help
"<prior>" #'switch-to-completions
"M-v" #'switch-to-completions
- "M-g M-c" #'switch-to-completions)
+ "M-g M-c" #'switch-to-completions
+ "M-<up>" #'minibuffer-previous-completion
+ "M-<down>" #'minibuffer-next-completion
+ "M-RET" #'minibuffer-choose-completion)
(defvar-keymap minibuffer-local-must-match-map
:doc "Local keymap for minibuffer input with completion, for exact match."
:parent minibuffer-local-completion-map
+ "M-X" #'execute-extended-command-cycle
"RET" #'minibuffer-complete-and-exit
"C-j" #'minibuffer-complete-and-exit)
@@ -2676,9 +2770,6 @@ Gets combined either with `minibuffer-local-completion-map' or
with `minibuffer-local-must-match-map'."
"SPC" nil)
-(defvar minibuffer-local-filename-must-match-map (make-sparse-keymap))
-(make-obsolete-variable 'minibuffer-local-filename-must-match-map nil "24.1")
-
(defvar-keymap minibuffer-local-ns-map
:doc "Local keymap for the minibuffer when spaces are not allowed."
:parent minibuffer-local-map
@@ -2724,7 +2815,6 @@ not active."
"<down-mouse-1>" #'ignore)
(define-derived-mode minibuffer-inactive-mode nil "InactiveMinibuffer"
- :abbrev-table nil ;abbrev.el is not loaded yet during dump.
;; Note: this major mode is called from minibuf.c.
"Major mode to use in the minibuffer when it is not active.
This is only used when the minibuffer area has no active minibuffer.
@@ -2746,7 +2836,6 @@ For customizing this mode, it is better to use
`minibuffer-setup-hook' and `minibuffer-exit-hook' rather than
the mode hook of this mode."
:syntax-table nil
- :abbrev-table nil
:interactive nil)
;;; Completion tables.
@@ -2913,26 +3002,30 @@ same as `substitute-in-file-name'."
(let* ((ustr (substitute-in-file-name qstr))
(uprefix (substring ustr 0 upos))
qprefix)
- ;; Main assumption: nothing after qpos should affect the text before upos,
- ;; so we can work our way backward from the end of qstr, one character
- ;; at a time.
- ;; Second assumptions: If qpos is far from the end this can be a bit slow,
- ;; so we speed it up by doing a first loop that skips a word at a time.
- ;; This word-sized loop is careful not to cut in the middle of env-vars.
- (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
- (and boundary
- (progn
- (setq qprefix (substring qstr 0 boundary))
+ (if (eq upos (length ustr))
+ ;; Easy and common case. This not only speed things up in a very
+ ;; common case but it also avoids problems in some cases (bug#53053).
+ (cons (length qstr) #'minibuffer-maybe-quote-filename)
+ ;; Main assumption: nothing after qpos should affect the text before upos,
+ ;; so we can work our way backward from the end of qstr, one character
+ ;; at a time.
+ ;; Second assumptions: If qpos is far from the end this can be a bit slow,
+ ;; so we speed it up by doing a first loop that skips a word at a time.
+ ;; This word-sized loop is careful not to cut in the middle of env-vars.
+ (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
+ (and boundary
+ (progn
+ (setq qprefix (substring qstr 0 boundary))
+ (string-prefix-p uprefix
+ (substitute-in-file-name qprefix)))))
+ (setq qstr qprefix))
+ (let ((qpos (length qstr)))
+ (while (and (> qpos 0)
(string-prefix-p uprefix
- (substitute-in-file-name qprefix)))))
- (setq qstr qprefix))
- (let ((qpos (length qstr)))
- (while (and (> qpos 0)
- (string-prefix-p uprefix
- (substitute-in-file-name
- (substring qstr 0 (1- qpos)))))
- (setq qpos (1- qpos)))
- (cons qpos #'minibuffer-maybe-quote-filename))))
+ (substitute-in-file-name
+ (substring qstr 0 (1- qpos)))))
+ (setq qpos (1- qpos)))
+ (cons qpos #'minibuffer-maybe-quote-filename)))))
(defalias 'completion--file-name-table
(completion-table-with-quoting #'completion-file-name-table
@@ -2975,7 +3068,8 @@ such as making the current buffer visit no file in the case of
:type 'boolean)
(defcustom minibuffer-beginning-of-buffer-movement nil
- "Control how the `M-<' command in the minibuffer behaves.
+ "Control how the \\<minibuffer-local-map>\\[minibuffer-beginning-of-buffer] \
+command in the minibuffer behaves.
If non-nil, the command will go to the end of the prompt (if
point is after the end of the prompt). If nil, it will behave
like the `beginning-of-buffer' command."
@@ -3044,10 +3138,16 @@ Fourth arg MUSTMATCH can take the following values:
input, but she needs to confirm her choice if she called
`minibuffer-complete' right before `minibuffer-complete-and-exit'
and the input is not an existing file.
+- a function, which will be called with the input as the
+ argument. If the function returns a non-nil value, the
+ minibuffer is exited with that argument as the value.
- anything else behaves like t except that typing RET does not exit if it
does non-null completion.
-Fifth arg INITIAL specifies text to start with.
+Fifth arg INITIAL specifies text to start with. It will be
+interpreted as the trailing part of DEFAULT-FILENAME, so using a
+full file name for INITIAL will usually lead to surprising
+results.
Sixth arg PREDICATE, if non-nil, should be a function of one
argument; then a file name is considered an acceptable completion
@@ -4007,7 +4107,7 @@ This turns
into
(prefix \"f\" any \"o\" any \"o\" any point)
which is at the core of flex logic. The extra
-'any' is optimized away later on."
+`any' is optimized away later on."
(mapcan (lambda (elem)
(if (stringp elem)
(mapcan (lambda (char)
@@ -4151,6 +4251,7 @@ See `completing-read' for the meaning of the arguments."
;; override bindings in base-keymap.
base-keymap)))
(buffer (current-buffer))
+ (c-i-c completion-ignore-case)
(result
(minibuffer-with-setup-hook
(lambda ()
@@ -4160,7 +4261,9 @@ See `completing-read' for the meaning of the arguments."
(setq-local minibuffer-completion-confirm
(unless (eq require-match t) require-match))
(setq-local minibuffer--require-match require-match)
- (setq-local minibuffer--original-buffer buffer))
+ (setq-local minibuffer--original-buffer buffer)
+ ;; Copy the value from original buffer to the minibuffer.
+ (setq-local completion-ignore-case c-i-c))
(read-from-minibuffer prompt initial-input keymap
nil hist def inherit-input-method))))
(when (and (equal result "") def)
@@ -4245,6 +4348,91 @@ the minibuffer was activated, and execute the forms."
(with-minibuffer-selected-window
(scroll-other-window-down arg)))
+(defmacro with-minibuffer-completions-window (&rest body)
+ "Execute the forms in BODY from the minibuffer in its completions window.
+When used in a minibuffer window, select the window with completions,
+and execute the forms."
+ (declare (indent 0) (debug t))
+ `(let ((window (or (get-buffer-window "*Completions*" 0)
+ ;; Make sure we have a completions window.
+ (progn (minibuffer-completion-help)
+ (get-buffer-window "*Completions*" 0)))))
+ (when window
+ (with-selected-window window
+ ,@body))))
+
+(defcustom minibuffer-completion-auto-choose t
+ "Non-nil means to automatically insert completions to the minibuffer.
+When non-nil, then `minibuffer-next-completion' and
+`minibuffer-previous-completion' will insert the completion
+selected by these commands to the minibuffer."
+ :type 'boolean
+ :version "29.1")
+
+(defun minibuffer-next-completion (&optional n)
+ "Move to the next item in its completions window from the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion to the minibuffer."
+ (interactive "p")
+ (let ((auto-choose minibuffer-completion-auto-choose))
+ (with-minibuffer-completions-window
+ (when completions-highlight-face
+ (setq-local cursor-face-highlight-nonselected-window t))
+ (next-completion (or n 1))
+ (when auto-choose
+ (let ((completion-use-base-affixes t))
+ (choose-completion nil t t))))))
+
+(defun minibuffer-previous-completion (&optional n)
+ "Move to the previous item in its completions window from the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion to the minibuffer."
+ (interactive "p")
+ (minibuffer-next-completion (- (or n 1))))
+
+(defun minibuffer-choose-completion (&optional no-exit no-quit)
+ "Run `choose-completion' from the minibuffer in its completions window.
+With prefix argument NO-EXIT, insert the completion at point to the
+minibuffer, but don't exit the minibuffer. When the prefix argument
+is not provided, then whether to exit the minibuffer depends on the value
+of `completion-no-auto-exit'.
+If NO-QUIT is non-nil, insert the completion at point to the
+minibuffer, but don't quit the completions window."
+ (interactive "P")
+ (with-minibuffer-completions-window
+ (let ((completion-use-base-affixes t))
+ (choose-completion nil no-exit no-quit))))
+
+(defun minibuffer-complete-history ()
+ "Complete the minibuffer history as far as possible.
+Like `minibuffer-complete' but completes on the history items
+instead of the default completion table."
+ (interactive)
+ (let ((completions-sort nil)
+ (history (mapcar (lambda (h)
+ ;; Support e.g. `C-x ESC ESC TAB' as
+ ;; a replacement of `list-command-history'
+ (if (consp h) (format "%S" h) h))
+ (symbol-value minibuffer-history-variable))))
+ (completion-in-region (minibuffer--completion-prompt-end) (point-max)
+ history nil)))
+
+(defun minibuffer-complete-defaults ()
+ "Complete minibuffer defaults as far as possible.
+Like `minibuffer-complete' but completes on the default items
+instead of the completion table."
+ (interactive)
+ (let ((completions-sort nil))
+ (when (and (not minibuffer-default-add-done)
+ (functionp minibuffer-default-add-function))
+ (setq minibuffer-default-add-done t
+ minibuffer-default (funcall minibuffer-default-add-function)))
+ (completion-in-region (minibuffer--completion-prompt-end) (point-max)
+ (ensure-list minibuffer-default) nil)))
+
+(define-key minibuffer-local-map [?\C-x up] 'minibuffer-complete-history)
+(define-key minibuffer-local-map [?\C-x down] 'minibuffer-complete-defaults)
+
(defcustom minibuffer-default-prompt-format " (default %s)"
"Format string used to output \"default\" values.
When prompting for input, there will often be a default value,
diff --git a/lisp/misc.el b/lisp/misc.el
index d85f889ffd3..28c5d6e07f5 100644
--- a/lisp/misc.el
+++ b/lisp/misc.el
@@ -33,7 +33,9 @@
"Copy characters from previous nonblank line, starting just above point.
Copy ARG characters, but not past the end of that line.
If no argument given, copy the entire rest of the line.
-The characters copied are inserted in the buffer before point."
+The characters copied are inserted in the buffer before point.
+
+Also see the `duplicate-line' command."
(interactive "P")
(let ((cc (current-column))
n
@@ -61,18 +63,41 @@ The characters copied are inserted in the buffer before point."
(+ n (point)))))))
(insert string)))
+;;;###autoload
+(defun duplicate-line (&optional n)
+ "Duplicate the current line N times.
+Interactively, N is the prefix numeric argument, and defaults to 1.
+Also see the `copy-from-above-command' command."
+ (interactive "p")
+ (unless n
+ (setq n 1))
+ (let ((line (buffer-substring (line-beginning-position) (line-end-position))))
+ (save-excursion
+ (forward-line 1)
+ (unless (bolp)
+ (insert "\n"))
+ (dotimes (_ n)
+ (insert line "\n")))))
+
;; Variation of `zap-to-char'.
;;;###autoload
-(defun zap-up-to-char (arg char)
+(defun zap-up-to-char (arg char &optional interactive)
"Kill up to, but not including ARGth occurrence of CHAR.
+When run interactively, the argument INTERACTIVE is non-nil.
Case is ignored if `case-fold-search' is non-nil in the current buffer.
Goes backward if ARG is negative; error if CHAR not found.
-Ignores CHAR at point."
+Ignores CHAR at point.
+If called interactively, do a case sensitive search if CHAR
+is an upper-case character."
(interactive (list (prefix-numeric-value current-prefix-arg)
(read-char-from-minibuffer "Zap up to char: "
- nil 'read-char-history)))
- (let ((direction (if (>= arg 0) 1 -1)))
+ nil 'read-char-history)
+ t))
+ (let ((direction (if (>= arg 0) 1 -1))
+ (case-fold-search (if (and interactive (char-uppercase-p char))
+ nil
+ case-fold-search)))
(kill-region (point)
(progn
(forward-char direction)
@@ -126,7 +151,7 @@ ripples outward, changing the flow of the eddy currents in the
upper atmosphere. These cause momentary pockets of higher-pressure
air to form, which act as lenses that deflect incoming cosmic rays,
focusing them to strike the drive platter and flip the desired bit.
-You can type `M-x butterfly C-M-c' to run it. This is a permuted
+You can type \\`M-x butterfly C-M-c' to run it. This is a permuted
variation of `C-x M-c M-butterfly' from url `https://xkcd.com/378/'."
(interactive)
(if (yes-or-no-p "Do you really want to unleash the powers of the butterfly? ")
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 1a76b9a0b66..ddcb51aecf2 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -42,7 +42,9 @@
:group 'editing)
(defcustom mouse-yank-at-point nil
- "If non-nil, mouse yank commands yank at point instead of at click."
+ "If non-nil, mouse yank commands yank at point instead of at click.
+This also allows yanking text into an isearch without moving the
+mouse cursor to the echo area."
:type 'boolean)
(defcustom mouse-drag-copy-region nil
@@ -51,9 +53,17 @@
This affects `mouse-save-then-kill' (\\[mouse-save-then-kill]) in
addition to mouse drags.
+If this variable is `non-empty', only copy to the kill ring if
+the region is non-empty. For instance, if you mouse drag an area
+that is less than a half a character, you'd normally get the
+empty string in your kill ring, but with this value, this short
+mouse drag won't affect the kill ring.
+
This variable applies only to mouse adjustments in Emacs, not
selecting and adjusting regions in other windows."
- :type 'boolean
+ :type '(choice (const :tag "No" nil)
+ (const :tag "Yes" t)
+ (const :tag "Non-empty" non-empty))
:version "24.1")
(defcustom mouse-1-click-follows-link 450
@@ -97,6 +107,25 @@ point at the click position."
:type 'boolean
:version "22.1")
+(defcustom mouse-drag-and-drop-region-scroll-margin nil
+ "If non-nil, the scroll margin inside a window when dragging text.
+If the mouse moves this many lines close to the top or bottom of
+a window while dragging text, then that window will be scrolled
+down and up respectively."
+ :type '(choice (const :tag "Don't scroll during mouse movement")
+ (integer :tag "This many lines from window top or bottom"))
+ :version "29.1")
+
+(defcustom mouse-drag-mode-line-buffer nil
+ "If non-nil, allow dragging files from the mode line.
+When the buffer has an associated file, it can be dragged from
+the buffer name portion of its mode line to other programs.
+
+This option is only supported on X, Haiku and Nextstep (GNUstep
+or macOS)."
+ :type 'boolean
+ :version "29.1")
+
(defvar mouse--last-down nil)
(defun mouse--down-1-maybe-follows-link (&optional _prompt)
@@ -156,6 +185,17 @@ Expects to be bound to `(double-)mouse-1' in `key-translation-map'."
(define-key key-translation-map [double-mouse-1]
#'mouse--click-1-maybe-follows-link)
+(defun mouse-double-click-time ()
+ "Return a number for `double-click-time'.
+In contrast to using the `double-click-time' variable directly,
+which could be set to nil or t, this function is guaranteed to
+always return a positive integer or zero."
+ (let ((ct double-click-time))
+ (cond ((eq ct t) 10000) ; arbitrary number useful for sit-for
+ ((eq ct nil) 0)
+ ((and (numberp ct) (> ct 0)) ct)
+ (t 0))))
+
;; Provide a mode-specific menu on a mouse button.
@@ -298,6 +338,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 hi-lock-context-menu)
+ (function-item occur-context-menu)
+ (function-item Man-context-menu)
+ (function-item dictionary-context-menu)
(function :tag "Custom function")))
:version "28.1")
@@ -317,9 +361,13 @@ At the end, it's possible to modify the final menu by specifying
the function `context-menu-filter-function'."
(let* ((menu (make-sparse-keymap (propertize "Context Menu" 'hide t)))
(click (or click last-input-event))
+ (window (posn-window (event-start click)))
(fun (mouse-posn-property (event-start click)
'context-menu-function)))
+ (unless (eq (selected-window) window)
+ (select-window window))
+
(if (functionp fun)
(setq menu (funcall fun menu click))
(run-hook-wrapped 'context-menu-functions
@@ -607,7 +655,13 @@ This command must be bound to a mouse click."
(interactive "e")
(unless (one-window-p t)
(mouse-minibuffer-check click)
- (delete-window (posn-window (event-start click)))))
+ ;; Only delete the window if the user hasn't moved point out of
+ ;; the mode line before releasing the button.
+ (when (and (eq (posn-area (event-end click))
+ 'mode-line)
+ (eq (posn-window (event-end click))
+ (posn-window (event-start click))))
+ (delete-window (posn-window (event-start click))))))
(defun mouse-select-window (click)
"Select the window clicked on; don't move point."
@@ -633,10 +687,13 @@ This command must be bound to a mouse click."
(switch-to-buffer buf)
(delete-window window)))
-(defun mouse-delete-other-windows ()
+(defun mouse-delete-other-windows (click)
"Delete all windows except the one you click on."
- (interactive "@")
- (delete-other-windows))
+ (interactive "e")
+ (when (and (eq (posn-area (event-end click)) 'mode-line)
+ (eq (posn-window (event-start click))
+ (posn-window (event-end click))))
+ (delete-other-windows (posn-window (event-start click)))))
(defun mouse-split-window-vertically (click)
"Select Emacs window mouse is on, then split it vertically in half.
@@ -824,8 +881,29 @@ frame instead."
(interactive "e")
(let* ((start (event-start start-event))
(window (posn-window start))
- (frame (window-frame window)))
+ (frame (window-frame window))
+ (skip-tracking nil)
+ filename)
+ ;; FIXME: is there a better way of determining if the event
+ ;; started on a buffer name?
+ (when (and mouse-drag-mode-line-buffer
+ (eq (car (posn-string start))
+ (car (with-selected-window window
+ (setq filename (buffer-file-name))
+ mode-line-buffer-identification)))
+ filename
+ (file-exists-p filename))
+ (let ((mouse-fine-grained-tracking nil))
+ (track-mouse
+ (setq track-mouse 'drag-source)
+ (let ((event (read-event)))
+ (if (not (eq (event-basic-type event)
+ 'mouse-movement))
+ (push event unread-command-events)
+ (dnd-begin-file-drag filename frame 'copy t)
+ (setq skip-tracking t))))))
(cond
+ (skip-tracking t)
((not (window-live-p window)))
((or (not (window-at-side-p window 'bottom))
;; Allow resizing the minibuffer window if it's on the
@@ -1122,7 +1200,7 @@ frame with the mouse."
(<= (- right parent-right) snap-width)
snap-x (<= (- last-x snap-x) snap-width))
;; Stay snapped when the mouse moved rightward but
- ;; not more more than `snap-width' pixels from the
+ ;; not more than `snap-width' pixels from the
;; time FRAME snapped.
(setq left (- parent-right native-width)))
(t
@@ -1144,7 +1222,7 @@ frame with the mouse."
(<= (- parent-top top) snap-width)
snap-y (<= (- snap-y last-y) snap-width))
;; Stay snapped when the mouse moved upward but
- ;; not more more than `snap-width' pixels from the
+ ;; not more than `snap-width' pixels from the
;; time FRAME snapped.
(setq top parent-top))
(t
@@ -1166,7 +1244,7 @@ frame with the mouse."
(<= (- bottom parent-bottom) snap-width)
snap-y (<= (- last-y snap-y) snap-width))
;; Stay snapped when the mouse moved downward but
- ;; not more more than `snap-width' pixels from the
+ ;; not more than `snap-width' pixels from the
;; time FRAME snapped.
(setq top (- parent-bottom native-height)))
(t
@@ -1362,11 +1440,16 @@ command alters the kill ring or not."
(if (< end beg)
(setq end (nth 0 range) beg (nth 1 range))
(setq beg (nth 0 range) end (nth 1 range)))))
- (and mouse-drag-copy-region (integerp beg) (integerp end)
+ (when (and mouse-drag-copy-region
+ (integerp beg)
+ (integerp end)
+ (or (not (eq mouse-drag-copy-region 'non-empty))
+ (/= beg end)))
;; Don't set this-command to `kill-region', so a following
;; C-w won't double the text in the kill ring. Ignore
;; `last-command' so we don't append to a preceding kill.
- (let (this-command last-command deactivate-mark)
+ (let ((last-command last-command)
+ this-command deactivate-mark)
(copy-region-as-kill beg end)))
(if (numberp beg) (goto-char beg))
;; On a text terminal, bounce the cursor.
@@ -1469,6 +1552,7 @@ is dragged over to."
(mouse-drag-and-drop-region start-event)
;; Give temporary modes such as isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
+ (ignore-preserving-kill-region)
(mouse-drag-track start-event)))
;; Inhibit the region-confinement when undoing mouse-drag-region
@@ -1678,7 +1762,8 @@ The region will be defined with mark and point."
nil start-point))
((>= mouse-row bottom)
(mouse-scroll-subr start-window (1+ (- mouse-row bottom))
- nil start-point))))))))
+ nil start-point))))))
+ (ignore-preserving-kill-region)))
map)
t (lambda ()
(funcall cleanup)
@@ -2051,7 +2136,9 @@ if `mouse-drag-copy-region' is non-nil)."
(if before-scroll (goto-char before-scroll)))
(exchange-point-and-mark)
(mouse-set-region-1)
- (when mouse-drag-copy-region
+ (when (and mouse-drag-copy-region
+ (or (not (eq mouse-drag-copy-region 'non-empty))
+ (not (/= (mark t) (point)))))
(kill-new (filter-buffer-substring (mark t) (point))))
(setq mouse-save-then-kill-posn click-pt)))))
@@ -2749,18 +2836,72 @@ and selects that window."
(declare-function generate-fontset-menu "fontset" ())
+(defun mouse-generate-font-name-for-menu (entity)
+ "Return a short name for font entity ENTITY.
+The name should be used to describe ENTITY in the case that its
+family is already known, such as in a pane generated by
+`mouse-generate-font-menu'."
+ (let ((weight (font-get entity :weight))
+ (slant (font-get entity :slant))
+ (width (font-get entity :width))
+ (size (font-get entity :size))
+ (adstyle (font-get entity :adstyle))
+ (name ""))
+ (when weight
+ (setq name (concat name (symbol-name weight) " ")))
+ (when (and slant
+ (not (eq slant 'normal)))
+ (setq name (concat name (symbol-name slant) " ")))
+ (when (and width (not (eq width 'normal)))
+ (setq name (concat name (symbol-name width) " ")))
+ (when (and size (not (zerop size)))
+ (setq name (concat name (number-to-string size) " ")))
+ (when adstyle
+ (setq name (concat name (if (symbolp adstyle)
+ (symbol-name adstyle)
+ (number-to-string adstyle))
+ " ")))
+ (string-trim-right name)))
+
+(defun mouse-generate-font-menu ()
+ "Return a list of menu panes for each font family."
+ (let ((families (font-family-list))
+ (panes (list "Font families")))
+ (dolist (family families)
+ (when family
+ (let* ((fonts (list-fonts (font-spec :family family)))
+ (pane (if fonts (list family)
+ (list family (cons family family)))))
+ (when fonts
+ (dolist (font fonts)
+ (setq pane
+ (nconc pane
+ (list (list (or (font-get font :name)
+ (mouse-generate-font-name-for-menu font))
+ (font-xlfd-name font)))))))
+ (setq panes (nconc panes (list pane))))))
+ panes))
+
(defun mouse-select-font ()
"Prompt for a font name, using `x-popup-menu', and return it."
(interactive)
(unless (display-multi-font-p)
(error "Cannot change fonts on this display"))
- (car
- (x-popup-menu
- (if (listp last-nonmenu-event)
- last-nonmenu-event
- (list '(0 0) (selected-window)))
- (append x-fixed-font-alist
- (list (generate-fontset-menu))))))
+ (let ((result (car
+ (x-popup-menu
+ (if (listp last-nonmenu-event)
+ last-nonmenu-event
+ (list '(0 0) (selected-window)))
+ (append x-fixed-font-alist
+ (list (generate-fontset-menu))
+ '(("More Fonts" ("By Family" more))))))))
+ (if (eq result 'more)
+ (car (x-popup-menu
+ (if (listp last-nonmenu-event)
+ last-nonmenu-event
+ (list '(0 0) (selected-window)))
+ (mouse-generate-font-menu)))
+ result)))
(declare-function text-scale-mode "face-remap")
@@ -2774,12 +2915,7 @@ choose a font."
(interactive
(progn (unless (display-multi-font-p)
(error "Cannot change fonts on this display"))
- (x-popup-menu
- (if (listp last-nonmenu-event)
- last-nonmenu-event
- (list '(0 0) (selected-window)))
- ;; Append list of fontsets currently defined.
- (append x-fixed-font-alist (list (generate-fontset-menu))))))
+ (list (mouse-select-font))))
(if fonts
(let (font)
(while fonts
@@ -2917,6 +3053,11 @@ in addition, temporarily highlight the original region with the
:type 'boolean
:version "26.1")
+(defcustom mouse-drag-and-drop-region-cross-program nil
+ "If non-nil, allow dragging text to other programs."
+ :type 'boolean
+ :version "29.1")
+
(defface mouse-drag-and-drop-region '((t :inherit region))
"Face to highlight original text during dragging.
This face is used by `mouse-drag-and-drop-region' to temporarily
@@ -2927,6 +3068,36 @@ highlight the original region when
(declare-function rectangle-dimensions "rect" (start end))
(declare-function rectangle-position-as-coordinates "rect" (position))
(declare-function rectangle-intersect-p "rect" (pos1 size1 pos2 size2))
+(declare-function x-begin-drag "xfns.c")
+
+(defun mouse-drag-and-drop-region-display-tooltip (tooltip)
+ "Display TOOLTIP, a tooltip string, using `x-show-tip'.
+Call `tooltip-show-help-non-mode' instead on non-graphical displays."
+ (if (display-graphic-p)
+ (let ((params (copy-sequence tooltip-frame-parameters))
+ (fg (face-attribute 'tooltip :foreground))
+ (bg (face-attribute 'tooltip :background)))
+ (when (stringp fg)
+ (setf (alist-get 'foreground-color params) fg)
+ (setf (alist-get 'border-color params) fg))
+ (when (stringp bg)
+ (setf (alist-get 'background-color params) bg))
+ ;; Don't time out: this leads to very confusing behavior when
+ ;; Emacs isn't visible, and the only indication that the user
+ ;; is actually dragging something abruptly disappears.
+ (x-show-tip tooltip nil params most-positive-fixnum))
+ (tooltip-show-help-non-mode tooltip)))
+
+(declare-function x-hide-tip "xfns.c")
+(declare-function x-show-tip "xfns.c")
+
+(defun mouse-drag-and-drop-region-hide-tooltip ()
+ "Hide any tooltip currently displayed.
+Call `tooltip-show-help-non-mode' to clear the echo area message
+instead on non-graphical displays."
+ (if (display-graphic-p)
+ (x-hide-tip)
+ (tooltip-show-help-non-mode nil)))
(defun mouse-drag-and-drop-region (event)
"Move text in the region to point where mouse is dragged to.
@@ -2943,6 +3114,7 @@ is copied instead of being cut."
(display-multi-frame-p)
(require 'tooltip))
mouse-drag-and-drop-region-show-tooltip))
+ (mouse-highlight nil)
(start (region-beginning))
(end (region-end))
(point (point))
@@ -2956,6 +3128,17 @@ is copied instead of being cut."
(cdr bounds)))
(region-bounds)))
(region-noncontiguous (region-noncontiguous-p))
+ ;; Otherwise, the mouse periodically moves on top of the
+ ;; tooltip.
+ (mouse-fine-grained-tracking t)
+ (was-tooltip-mode tooltip-mode)
+ ;; System tooltips tend to flicker and in general work
+ ;; incorrectly.
+ (use-system-tooltips nil)
+ ;; Whether or not some text was ``cut'' from Emacs to another
+ ;; program and the cleaanup code should not try modifying the
+ ;; region.
+ drag-was-cross-program
point-to-paste
point-to-paste-read-only
window-to-paste
@@ -2967,255 +3150,384 @@ is copied instead of being cut."
value-selection ; This remains nil when event was "click".
text-tooltip
states
- window-exempt)
-
- ;; STATES stores for each window on this frame its start and point
- ;; positions so we can restore them on all windows but for the one
- ;; where the drop occurs. For inter-frame drags we'll have to do
- ;; this for all windows on all visible frames. In addition we save
- ;; also the cursor type for the window's buffer so we can restore it
- ;; in case we modified it.
- ;; https://lists.gnu.org/r/emacs-devel/2017-12/msg00090.html
- (walk-window-tree
- (lambda (window)
- (setq states
- (cons
- (list
- window
- (copy-marker (window-start window))
- (copy-marker (window-point window))
- (with-current-buffer (window-buffer window)
- cursor-type))
- states))))
-
- (ignore-errors
- (track-mouse
- (setq track-mouse 'dropping)
- ;; When event was "click" instead of "drag", skip loop.
- (while (progn
- (setq event (read-key)) ; read-event or read-key
- (or (mouse-movement-p event)
- ;; Handle `mouse-autoselect-window'.
- (memq (car event) '(select-window switch-frame))))
- ;; Obtain the dragged text in region. When the loop was
- ;; skipped, value-selection remains nil.
- (unless value-selection
- (setq value-selection (funcall region-extract-function nil))
- (when mouse-drag-and-drop-region-show-tooltip
- (let ((text-size mouse-drag-and-drop-region-show-tooltip))
- (setq text-tooltip
- (if (and (integerp text-size)
- (> (length value-selection) text-size))
- (concat
- (substring value-selection 0 (/ text-size 2))
- "\n...\n"
- (substring value-selection (- (/ text-size 2)) -1))
- value-selection))))
-
- ;; Check if selected text is read-only.
- (setq text-from-read-only
- (or text-from-read-only
- (catch 'loop
- (dolist (bound (region-bounds))
- (when (text-property-not-all
- (car bound) (cdr bound) 'read-only nil)
- (throw 'loop t)))))))
-
- (setq window-to-paste (posn-window (event-end event)))
- (setq point-to-paste (posn-point (event-end event)))
- ;; Set nil when target buffer is minibuffer.
- (setq buffer-to-paste (let (buf)
- (when (windowp window-to-paste)
- (setq buf (window-buffer window-to-paste))
- (when (not (minibufferp buf))
- buf))))
- (setq cursor-in-text-area (and window-to-paste
- point-to-paste
- buffer-to-paste))
-
- (when cursor-in-text-area
- ;; Check if point under mouse is read-only.
- (save-window-excursion
- (select-window window-to-paste)
- (setq point-to-paste-read-only
- (or buffer-read-only
- (get-text-property point-to-paste 'read-only))))
-
- ;; Check if "drag but negligible". Operation "drag but
- ;; negligible" is defined as drag-and-drop the text to
- ;; the original region. When modifier is pressed, the
- ;; text will be inserted to inside of the original
- ;; region.
- ;;
- ;; If the region is rectangular, check if the newly inserted
- ;; rectangular text would intersect the already selected
- ;; region. If it would, then set "drag-but-negligible" to t.
- ;; As a special case, allow dragging the region freely anywhere
- ;; to the left, as this will never trigger its contents to be
- ;; inserted into the overlays tracking it.
- (setq drag-but-negligible
- (and (eq (overlay-buffer (car mouse-drag-and-drop-overlays))
- buffer-to-paste)
- (if region-noncontiguous
- (let ((dimensions (rectangle-dimensions start end))
- (start-coordinates
- (rectangle-position-as-coordinates start))
- (point-to-paste-coordinates
- (rectangle-position-as-coordinates
- point-to-paste)))
- (and (rectangle-intersect-p
- start-coordinates dimensions
- point-to-paste-coordinates dimensions)
- (not (< (car point-to-paste-coordinates)
- (car start-coordinates)))))
- (and (<= (overlay-start
- (car mouse-drag-and-drop-overlays))
- point-to-paste)
- (<= point-to-paste
- (overlay-end
- (car mouse-drag-and-drop-overlays))))))))
-
- ;; Show a tooltip.
- (if mouse-drag-and-drop-region-show-tooltip
- (tooltip-show text-tooltip)
- (tooltip-hide))
-
- ;; Show cursor and highlight the original region.
- (when mouse-drag-and-drop-region-show-cursor
- ;; Modify cursor even when point is out of frame.
- (setq cursor-type (cond
- ((not cursor-in-text-area)
- nil)
- ((or point-to-paste-read-only
- drag-but-negligible)
- 'hollow)
- (t
- 'bar)))
- (when cursor-in-text-area
- (dolist (overlay mouse-drag-and-drop-overlays)
- (overlay-put overlay
- 'face 'mouse-drag-and-drop-region))
- (deactivate-mark) ; Maintain region in other window.
- (mouse-set-point event)))))
-
- ;; Hide a tooltip.
- (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide))
-
- ;; Check if modifier was pressed on drop.
- (setq no-modifier-on-drop
- (not (member mouse-drag-and-drop-region (event-modifiers event))))
-
- ;; Check if event was "click".
- (setq clicked (not value-selection))
-
- ;; Restore status on drag to outside of text-area or non-mouse input.
- (when (or (not cursor-in-text-area)
- (not (equal (event-basic-type event) mouse-button)))
- (setq drag-but-negligible t
- no-modifier-on-drop t))
-
- ;; Do not modify any buffers when event is "click",
- ;; "drag but negligible", or "drag to read-only".
- (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ
- (if no-modifier-on-drop
- mouse-drag-and-drop-region-cut-when-buffers-differ
- (not mouse-drag-and-drop-region-cut-when-buffers-differ)))
- (wanna-paste-to-same-buffer (equal buffer-to-paste buffer))
- (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer
- no-modifier-on-drop))
- (wanna-cut-on-other-buffer
- (and (not wanna-paste-to-same-buffer)
- mouse-drag-and-drop-region-cut-when-buffers-differ))
- (cannot-paste (or point-to-paste-read-only
- (when (or wanna-cut-on-same-buffer
- wanna-cut-on-other-buffer)
- text-from-read-only))))
-
- (cond
- ;; Move point within region.
- (clicked
- (deactivate-mark)
- (mouse-set-point event))
- ;; Undo operation. Set back the original text as region.
- ((or (and drag-but-negligible
- no-modifier-on-drop)
- cannot-paste)
- ;; Inform user either source or destination buffer cannot be modified.
- (when (and (not drag-but-negligible)
- cannot-paste)
- (message "Buffer is read-only"))
-
- ;; Select source window back and restore region.
- ;; (set-window-point window point)
- (select-window window)
- (goto-char point)
- (setq deactivate-mark nil)
- (activate-mark)
- (when region-noncontiguous
- (rectangle-mark-mode)))
- ;; Modify buffers.
- (t
- ;; * DESTINATION BUFFER::
- ;; Insert the text to destination buffer under mouse.
- (select-window window-to-paste)
- (setq window-exempt window-to-paste)
- (goto-char point-to-paste)
- (push-mark)
- (insert-for-yank value-selection)
-
- ;; On success, set the text as region on destination buffer.
- (when (not (equal (mark) (point)))
- (setq deactivate-mark nil)
- (activate-mark)
- (when region-noncontiguous
- (rectangle-mark-mode)))
-
- ;; * SOURCE BUFFER::
- ;; Set back the original text as region or delete the original
- ;; text, on source buffer.
- (if wanna-paste-to-same-buffer
- ;; When source buffer and destination buffer are the same,
- ;; remove the original text.
- (when no-modifier-on-drop
- (let (deactivate-mark)
- (dolist (overlay mouse-drag-and-drop-overlays)
- (delete-region (overlay-start overlay)
- (overlay-end overlay)))))
- ;; When source buffer and destination buffer are different,
- ;; keep (set back the original text as region) or remove the
- ;; original text.
- (select-window window) ; Select window with source buffer.
- (goto-char point) ; Move point to the original text on source buffer.
-
- (if mouse-drag-and-drop-region-cut-when-buffers-differ
- ;; Remove the dragged text from source buffer like
- ;; operation `cut'.
- (dolist (overlay mouse-drag-and-drop-overlays)
- (delete-region (overlay-start overlay)
- (overlay-end overlay)))
- ;; Set back the dragged text as region on source buffer
- ;; like operation `copy'.
- (activate-mark))
- (select-window window-to-paste))))))
-
- ;; Clean up.
- (dolist (overlay mouse-drag-and-drop-overlays)
- (delete-overlay overlay))
-
- ;; Restore old states but for the window where the drop
- ;; occurred. Restore cursor types for all windows.
- (dolist (state states)
- (let ((window (car state)))
- (when (and window-exempt
- (not (eq window window-exempt)))
- (set-window-start window (nth 1 state) 'noforce)
- (set-marker (nth 1 state) nil)
- ;; If window is selected, the following automatically sets
- ;; point for that window's buffer.
- (set-window-point window (nth 2 state))
- (set-marker (nth 2 state) nil))
- (with-current-buffer (window-buffer window)
- (setq cursor-type (nth 3 state)))))))
+ window-exempt
+ drag-again-mouse-position)
+
+ (unwind-protect
+ (progn
+ ;; Without this moving onto text with a help-echo will
+ ;; interfere with the tooltip containing dragged text.
+ (tooltip-mode -1)
+ ;; STATES stores for each window on this frame its start and point
+ ;; positions so we can restore them on all windows but for the one
+ ;; where the drop occurs. For inter-frame drags we'll have to do
+ ;; this for all windows on all visible frames. In addition we save
+ ;; also the cursor type for the window's buffer so we can restore it
+ ;; in case we modified it.
+ ;; https://lists.gnu.org/r/emacs-devel/2017-12/msg00090.html
+ (walk-window-tree
+ (lambda (window)
+ (setq states
+ (cons
+ (list
+ window
+ (copy-marker (window-start window))
+ (copy-marker (window-point window))
+ (with-current-buffer (window-buffer window)
+ cursor-type))
+ states))))
+
+ (ignore-errors
+ (catch 'cross-program-drag
+ (track-mouse
+ (setq track-mouse (if mouse-drag-and-drop-region-cross-program
+ ;; When `track-mouse' is `drop', we
+ ;; get events with a posn-window of
+ ;; the grabbed frame even if some
+ ;; window is between that and the
+ ;; pointer. This makes dragging to a
+ ;; window on top of a frame
+ ;; impossible. With this value of
+ ;; `track-mouse', no frame is returned
+ ;; in that particular case, which
+ ;; tells us to initiate interprogram
+ ;; drag-and-drop.
+ 'drag-source
+ 'drop))
+ ;; When event was "click" instead of "drag", skip loop.
+ (while (progn
+ (setq event (read-key)) ; read-event or read-key
+ (or (mouse-movement-p event)
+ ;; Handle `mouse-autoselect-window'.
+ (memq (car event) '(select-window switch-frame))))
+ (catch 'drag-again
+ ;; If the mouse is in the drag scroll margin, scroll
+ ;; either up or down depending on which margin it is in.
+ (when mouse-drag-and-drop-region-scroll-margin
+ (let* ((row (cdr (posn-col-row (event-end event))))
+ (window (when (windowp (posn-window (event-end event)))
+ (posn-window (event-end event))))
+ (text-height (when window
+ (window-text-height window)))
+ ;; Make sure it's possible to scroll both up
+ ;; and down if the margin is too large for the
+ ;; window.
+ (margin (when text-height
+ (min (/ text-height 3)
+ mouse-drag-and-drop-region-scroll-margin))))
+ (when (windowp window)
+ ;; At 2 lines, the window becomes too small for any
+ ;; meaningful scrolling.
+ (unless (<= text-height 2)
+ ;; We could end up at the beginning or end of the
+ ;; buffer.
+ (ignore-errors
+ (cond
+ ;; Inside the bottom scroll margin, scroll up.
+ ((> row (- text-height margin))
+ (with-selected-window window
+ (scroll-up 1)))
+ ;; Inside the top scroll margin, scroll down.
+ ((< row margin)
+ (with-selected-window window
+ (scroll-down 1)))))))))
+
+ ;; Obtain the dragged text in region. When the loop was
+ ;; skipped, value-selection remains nil.
+ (unless value-selection
+ (setq value-selection (funcall region-extract-function nil))
+ (when mouse-drag-and-drop-region-show-tooltip
+ (let ((text-size mouse-drag-and-drop-region-show-tooltip))
+ (setq text-tooltip
+ (if (and (integerp text-size)
+ (> (length value-selection) text-size))
+ (concat
+ (substring value-selection 0 (/ text-size 2))
+ "\n...\n"
+ (substring value-selection (- (/ text-size 2)) -1))
+ value-selection))))
+
+ ;; Check if selected text is read-only.
+ (setq text-from-read-only
+ (or text-from-read-only
+ (catch 'loop
+ (dolist (bound (region-bounds))
+ (when (text-property-not-all
+ (car bound) (cdr bound) 'read-only nil)
+ (throw 'loop t)))))))
+
+ (when (and mouse-drag-and-drop-region-cross-program
+ (display-graphic-p)
+ (fboundp 'x-begin-drag)
+ (or (and (framep (posn-window (event-end event)))
+ (let ((location (posn-x-y (event-end event)))
+ (frame (posn-window (event-end event))))
+ (or (< (car location) 0)
+ (< (cdr location) 0)
+ (> (car location)
+ (frame-pixel-width frame))
+ (> (cdr location)
+ (frame-pixel-height frame)))))
+ (and (or (not drag-again-mouse-position)
+ (let ((mouse-position (mouse-absolute-pixel-position)))
+ (or (< 5 (abs (- (car drag-again-mouse-position)
+ (car mouse-position))))
+ (< 5 (abs (- (cdr drag-again-mouse-position)
+ (cdr mouse-position)))))))
+ (not (posn-window (event-end event))))))
+ (setq drag-again-mouse-position nil)
+ (gui-set-selection 'XdndSelection value-selection)
+ (let ((drag-action-or-frame
+ (condition-case nil
+ (x-begin-drag '("UTF8_STRING" "text/plain"
+ "text/plain;charset=utf-8"
+ "STRING" "TEXT" "COMPOUND_TEXT")
+ (if mouse-drag-and-drop-region-cut-when-buffers-differ
+ 'XdndActionMove
+ 'XdndActionCopy)
+ (posn-window (event-end event)) 'now
+ ;; On platforms where we know
+ ;; `return-frame' doesn't
+ ;; work, allow dropping on
+ ;; the drop frame.
+ (eq window-system 'haiku) t)
+ (quit nil))))
+ (when (framep drag-action-or-frame)
+ ;; With some window managers `x-begin-drag'
+ ;; returns a frame sooner than `mouse-position'
+ ;; will return one, due to over-wide frame windows
+ ;; being drawn by the window manager. To avoid
+ ;; that, we just require the mouse move a few
+ ;; pixels before beginning another cross-program
+ ;; drag.
+ (setq drag-again-mouse-position
+ (mouse-absolute-pixel-position))
+ (throw 'drag-again nil))
+
+ (let ((min-char (point)))
+ (when (eq drag-action-or-frame 'XdndActionMove)
+ ;; Remove the dragged text from source buffer like
+ ;; operation `cut'.
+ (dolist (overlay mouse-drag-and-drop-overlays)
+ (when (< min-char (min (overlay-start overlay)
+ (overlay-end overlay)))
+ (setq min-char (min (overlay-start overlay)
+ (overlay-end overlay))))
+ (delete-region (overlay-start overlay)
+ (overlay-end overlay)))
+ (goto-char min-char)
+ (setq deactivate-mark t)
+ (setq drag-was-cross-program t)))
+
+ (when (eq drag-action-or-frame 'XdndActionCopy)
+ ;; Set back the dragged text as region on source buffer
+ ;; like operation `copy'.
+ (activate-mark)))
+ (throw 'cross-program-drag nil))
+
+ (setq window-to-paste (posn-window (event-end event)))
+ (setq point-to-paste (posn-point (event-end event)))
+ ;; Set nil when target buffer is minibuffer.
+ (setq buffer-to-paste (let (buf)
+ (when (windowp window-to-paste)
+ (setq buf (window-buffer window-to-paste))
+ (when (not (minibufferp buf))
+ buf))))
+ (setq cursor-in-text-area (and window-to-paste
+ point-to-paste
+ buffer-to-paste))
+
+ (when cursor-in-text-area
+ ;; Check if point under mouse is read-only.
+ (save-window-excursion
+ (select-window window-to-paste)
+ (setq point-to-paste-read-only
+ (or buffer-read-only
+ (get-text-property point-to-paste 'read-only))))
+
+ ;; Check if "drag but negligible". Operation "drag but
+ ;; negligible" is defined as drag-and-drop the text to
+ ;; the original region. When modifier is pressed, the
+ ;; text will be inserted to inside of the original
+ ;; region.
+ ;;
+ ;; If the region is rectangular, check if the newly inserted
+ ;; rectangular text would intersect the already selected
+ ;; region. If it would, then set "drag-but-negligible" to t.
+ ;; As a special case, allow dragging the region freely anywhere
+ ;; to the left, as this will never trigger its contents to be
+ ;; inserted into the overlays tracking it.
+ (setq drag-but-negligible
+ (and (eq (overlay-buffer (car mouse-drag-and-drop-overlays))
+ buffer-to-paste)
+ (if region-noncontiguous
+ (let ((dimensions (rectangle-dimensions start end))
+ (start-coordinates
+ (rectangle-position-as-coordinates start))
+ (point-to-paste-coordinates
+ (rectangle-position-as-coordinates
+ point-to-paste)))
+ (and (rectangle-intersect-p
+ start-coordinates dimensions
+ point-to-paste-coordinates dimensions)
+ (not (< (car point-to-paste-coordinates)
+ (car start-coordinates)))))
+ (and (<= (overlay-start
+ (car mouse-drag-and-drop-overlays))
+ point-to-paste)
+ (<= point-to-paste
+ (overlay-end
+ (car mouse-drag-and-drop-overlays))))))))
+
+ ;; Show a tooltip.
+ (if mouse-drag-and-drop-region-show-tooltip
+ ;; Don't use tooltip-show since it has side effects
+ ;; which change the text properties, and
+ ;; `text-tooltip' can potentially be the text which
+ ;; will be pasted.
+ (mouse-drag-and-drop-region-display-tooltip text-tooltip)
+ (mouse-drag-and-drop-region-hide-tooltip))
+
+ ;; Show cursor and highlight the original region.
+ (when mouse-drag-and-drop-region-show-cursor
+ ;; Modify cursor even when point is out of frame.
+ (setq cursor-type (cond
+ ((not cursor-in-text-area)
+ nil)
+ ((or point-to-paste-read-only
+ drag-but-negligible)
+ 'hollow)
+ (t
+ 'bar)))
+ (when cursor-in-text-area
+ (dolist (overlay mouse-drag-and-drop-overlays)
+ (overlay-put overlay
+ 'face 'mouse-drag-and-drop-region))
+ (deactivate-mark) ; Maintain region in other window.
+ (mouse-set-point event)))))))
+
+ ;; Hide a tooltip.
+ (when mouse-drag-and-drop-region-show-tooltip (x-hide-tip))
+
+ ;; Check if modifier was pressed on drop.
+ (setq no-modifier-on-drop
+ (not (member mouse-drag-and-drop-region (event-modifiers event))))
+
+ ;; Check if event was "click".
+ (setq clicked (not value-selection))
+
+ ;; Restore status on drag to outside of text-area or non-mouse input.
+ (when (or (not cursor-in-text-area)
+ (not (equal (event-basic-type event) mouse-button)))
+ (setq drag-but-negligible t
+ no-modifier-on-drop t))
+
+ ;; Do not modify any buffers when event is "click",
+ ;; "drag but negligible", or "drag to read-only".
+ (unless drag-was-cross-program
+ (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ
+ (if no-modifier-on-drop
+ mouse-drag-and-drop-region-cut-when-buffers-differ
+ (not mouse-drag-and-drop-region-cut-when-buffers-differ)))
+ (wanna-paste-to-same-buffer (equal buffer-to-paste buffer))
+ (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer
+ no-modifier-on-drop))
+ (wanna-cut-on-other-buffer
+ (and (not wanna-paste-to-same-buffer)
+ mouse-drag-and-drop-region-cut-when-buffers-differ))
+ (cannot-paste (or point-to-paste-read-only
+ (when (or wanna-cut-on-same-buffer
+ wanna-cut-on-other-buffer)
+ text-from-read-only))))
+
+ (cond
+ ;; Move point within region.
+ (clicked
+ (deactivate-mark)
+ (mouse-set-point event))
+ ;; Undo operation. Set back the original text as region.
+ ((or (and drag-but-negligible
+ no-modifier-on-drop)
+ cannot-paste)
+ ;; Inform user either source or destination buffer cannot be modified.
+ (when (and (not drag-but-negligible)
+ cannot-paste)
+ (message "Buffer is read-only"))
+
+ ;; Select source window back and restore region.
+ ;; (set-window-point window point)
+ (select-window window)
+ (goto-char point)
+ (setq deactivate-mark nil)
+ (activate-mark)
+ (when region-noncontiguous
+ (rectangle-mark-mode)))
+ ;; Modify buffers.
+ (t
+ ;; * DESTINATION BUFFER::
+ ;; Insert the text to destination buffer under mouse.
+ (select-window window-to-paste)
+ (setq window-exempt window-to-paste)
+ (goto-char point-to-paste)
+ (push-mark)
+ (insert-for-yank value-selection)
+
+ ;; On success, set the text as region on destination buffer.
+ (when (not (equal (mark) (point)))
+ (setq deactivate-mark nil)
+ (activate-mark)
+ (when region-noncontiguous
+ (rectangle-mark-mode)))
+
+ ;; * SOURCE BUFFER::
+ ;; Set back the original text as region or delete the original
+ ;; text, on source buffer.
+ (if wanna-paste-to-same-buffer
+ ;; When source buffer and destination buffer are the same,
+ ;; remove the original text.
+ (when no-modifier-on-drop
+ (let (deactivate-mark)
+ (dolist (overlay mouse-drag-and-drop-overlays)
+ (delete-region (overlay-start overlay)
+ (overlay-end overlay)))))
+ ;; When source buffer and destination buffer are different,
+ ;; keep (set back the original text as region) or remove the
+ ;; original text.
+ (select-window window) ; Select window with source buffer.
+ (goto-char point) ; Move point to the original text on source buffer.
+
+ (if mouse-drag-and-drop-region-cut-when-buffers-differ
+ ;; Remove the dragged text from source buffer like
+ ;; operation `cut'.
+ (dolist (overlay mouse-drag-and-drop-overlays)
+ (delete-region (overlay-start overlay)
+ (overlay-end overlay)))
+ ;; Set back the dragged text as region on source buffer
+ ;; like operation `copy'.
+ (activate-mark))
+ (select-window window-to-paste))))))))
+
+ (when was-tooltip-mode
+ (tooltip-mode 1))
+
+ ;; Clean up.
+ (dolist (overlay mouse-drag-and-drop-overlays)
+ (delete-overlay overlay))
+
+ ;; Restore old states but for the window where the drop
+ ;; occurred. Restore cursor types for all windows.
+ (dolist (state states)
+ (let ((window (car state)))
+ (when (and window-exempt
+ (not (eq window window-exempt)))
+ (set-window-start window (nth 1 state) 'noforce)
+ (set-marker (nth 1 state) nil)
+ ;; If window is selected, the following automatically sets
+ ;; point for that window's buffer.
+ (set-window-point window (nth 2 state))
+ (set-marker (nth 2 state) nil))
+ (with-current-buffer (window-buffer window)
+ (setq cursor-type (nth 3 state))))))))
;;; Bindings for mouse commands.
diff --git a/lisp/msb.el b/lisp/msb.el
index 6e1d03ac277..6843df2edcf 100644
--- a/lisp/msb.el
+++ b/lisp/msb.el
@@ -103,7 +103,7 @@
((eq major-mode 'Man-mode)
4090
"Manuals (%d)")
- ((eq major-mode 'w3-mode)
+ ((eq major-mode 'eww-mode)
4020
"WWW (%d)")
((or (memq major-mode
@@ -154,7 +154,7 @@
((eq major-mode 'Man-mode)
5030
"Manuals (%d)")
- ((eq major-mode 'w3-mode)
+ ((eq major-mode 'eww-mode)
5020
"WWW (%d)")
((or (memq major-mode
@@ -299,7 +299,7 @@ If the value is not a number, then the value 10 is used."
(defcustom msb-display-most-recently-used 15
"How many buffers should be in the most-recently-used menu.
No buffers at all if less than 1 or nil (or any non-number)."
- :type 'integer
+ :type 'natnum
:set #'msb-custom-set)
(defcustom msb-most-recently-used-title "Most recently used (%d)"
@@ -353,9 +353,6 @@ This is instead of the groups in `msb-menu-cond'."
:type 'boolean
:set #'msb-custom-set)
-(define-obsolete-variable-alias 'msb-after-load-hooks
- 'msb-after-load-hook "24.1")
-
(defcustom msb-after-load-hook nil
"Hook run after the msb package has been loaded."
:type 'hook
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index 55d3c7a5d82..ba5255fc076 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -1,6 +1,7 @@
;;; mwheel.el --- Mouse wheel support -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2000-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2022 Free Software Foundation, Inc.
+
;; Keywords: mouse
;; Package: emacs
@@ -22,7 +23,7 @@
;;; Commentary:
;; This enables the use of the mouse wheel (or scroll wheel) in Emacs.
-;; Under X11/X.Org, the wheel events are sent as button4/button5
+;; Under X11/X.Org, the wheel events are sent as mouse-4/mouse-5
;; events.
;; Mouse wheel support is already enabled by default on most graphical
@@ -32,7 +33,7 @@
;; Implementation note:
;;
-;; I for one would prefer some way of converting the button4/button5
+;; I for one would prefer some way of converting the mouse-4/mouse-5
;; events into different event types, like 'mwheel-up' or
;; 'mwheel-down', but I cannot find a way to do this very easily (or
;; portably), so for now I just live with it.
@@ -40,6 +41,7 @@
(require 'timer)
(defvar mouse-wheel-mode)
+
(defvar mouse-wheel--installed-bindings-alist nil
"Alist of all installed mouse wheel key bindings.")
@@ -112,7 +114,10 @@ set to the event sent when clicking on the mouse wheel button."
:type 'number)
(defcustom mouse-wheel-scroll-amount
- '(1 ((shift) . hscroll) ((meta) . nil) ((control) . text-scale))
+ '(1 ((shift) . hscroll)
+ ((meta) . nil)
+ ((control meta) . global-text-scale)
+ ((control) . text-scale))
"Amount to scroll windows by when spinning the mouse wheel.
This is an alist mapping the modifier key to the amount to scroll when
the wheel is moved with the modifier key depressed.
@@ -124,12 +129,14 @@ screen. It can also be a floating point number, specifying the fraction of
a full screen to scroll. A near full screen is `next-screen-context-lines'
less than a full screen.
-If AMOUNT is the symbol 'hscroll', this means that with MODIFIER,
+If AMOUNT is the symbol `hscroll', this means that with MODIFIER,
the mouse wheel will scroll horizontally instead of vertically.
-If AMOUNT is the symbol 'text-scale', this means that with
-MODIFIER, the mouse wheel will change the face height instead of
-scrolling."
+If AMOUNT is the symbol `text-scale' or `global-text-scale', this
+means that with MODIFIER, the mouse wheel will change the font size
+instead of scrolling (by adjusting the font height of the default
+face, either locally in the buffer or globally). For more
+information, see `text-scale-adjust' and `global-text-scale-adjust'."
:group 'mouse
:type '(cons
(choice :tag "Normal"
@@ -154,7 +161,8 @@ scrolling."
(integer :tag "Scroll specific # of lines")
(float :tag "Scroll fraction of window")
(const :tag "Scroll horizontally" :value hscroll)
- (const :tag "Change face size" :value text-scale)))))
+ (const :tag "Change buffer face size" :value text-scale)
+ (const :tag "Change global face size" :value global-text-scale)))))
:set 'mouse-wheel-change-button
:version "28.1")
@@ -417,7 +425,8 @@ value of ARG, and the command uses it in subsequent scrolls."
(put 'mwheel-scroll 'scroll-command t)
(defun mouse-wheel-text-scale (event)
- "Increase or decrease the height of the default face according to the EVENT."
+ "Adjust font size of the default face according to EVENT.
+See also `text-scale-adjust'."
(interactive (list last-input-event))
(let ((selected-window (selected-window))
(scroll-window (mouse-wheel--get-scroll-window event))
@@ -432,6 +441,20 @@ value of ARG, and the command uses it in subsequent scrolls."
(text-scale-decrease 1)))
(select-window selected-window))))
+(declare-function global-text-scale-adjust "face-remap.el" (increment))
+(defun mouse-wheel-global-text-scale (event)
+ "Increase or decrease the global font size according to the EVENT.
+This invokes `global-text-scale-adjust', which see."
+ (interactive (list last-input-event))
+ (let ((button (mwheel-event-button event)))
+ (unwind-protect
+ (cond ((memq button (list mouse-wheel-down-event
+ mouse-wheel-down-alternate-event))
+ (global-text-scale-adjust 1))
+ ((memq button (list mouse-wheel-up-event
+ mouse-wheel-up-alternate-event))
+ (global-text-scale-adjust -1))))))
+
(defun mouse-wheel--add-binding (key fun)
"Bind mouse wheel button KEY to function FUN.
Save it for later removal by `mouse-wheel--remove-bindings'."
@@ -484,8 +507,15 @@ an event used for scrolling, such as `mouse-wheel-down-event'."
mouse-wheel-down-alternate-event
mouse-wheel-up-alternate-event))
(when event
- (mouse-wheel--add-binding `[,(list (caar binding) event)]
+ (mouse-wheel--add-binding `[,(append (car binding) (list event))]
'mouse-wheel-text-scale))))
+ ((and (consp binding) (eq (cdr binding) 'global-text-scale))
+ (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event
+ mouse-wheel-down-alternate-event
+ mouse-wheel-up-alternate-event))
+ (when event
+ (mouse-wheel--add-binding `[,(append (car binding) (list event))]
+ 'mouse-wheel-global-text-scale))))
;; Bindings for scrolling.
(t
(dolist (event (list mouse-wheel-down-event mouse-wheel-up-event
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index a6904fc07e9..9937c022d9f 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -2547,13 +2547,16 @@ can parse the output from a DIR listing for a host of type TYPE.")
(defvar ange-ftp-after-parse-ls-hook nil
"Normal hook run after parsing the text of an FTP directory listing.")
+(declare-function ls-lisp--sanitize-switches "ls-lisp" (switches))
+
(defun ange-ftp-ls (file lsargs parse &optional no-error wildcard)
"Return the output of a `DIR' or `ls' command done over FTP.
FILE is the full name of the remote file, LSARGS is any args to pass to the
`ls' command, and PARSE specifies that the output should be parsed and stored
away in the internal cache."
- (while (string-match "^--dired\\s-+" lsargs)
- (setq lsargs (replace-match "" nil t lsargs)))
+ (while (string-match "--" lsargs)
+ (require 'ls-lisp)
+ (setq lsargs (ls-lisp--sanitize-switches lsargs)))
;; If parse is t, we assume that file is a directory. i.e. we only parse
;; full directory listings.
(let* ((ange-ftp-this-file (ange-ftp-expand-file-name file))
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index e4c485eccde..a55aec76bfc 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -1,4 +1,4 @@
-;;; browse-url.el --- pass a URL to a WWW browser -*- lexical-binding: t; -*-
+;;; browse-url.el --- pass a URL to a web browser -*- lexical-binding: t; -*-
;; Copyright (C) 1995-2022 Free Software Foundation, Inc.
@@ -24,24 +24,28 @@
;;; Commentary:
-;; This package provides functions which read a URL (Uniform Resource
-;; Locator) from the minibuffer, defaulting to the URL around point,
-;; and ask a World-Wide Web browser to load it. It can also load the
-;; URL associated with the current buffer. Different browsers use
-;; different methods of remote control so there is one function for
-;; each supported browser. If the chosen browser is not running, it
-;; is started. Currently there is support for the following browsers,
-;; as well as some other obsolete ones:
+;; This package provides functions which read a URL from the
+;; minibuffer, defaulting to the URL around point, and ask a web
+;; browser to load it. It can also load the URL at point, or one
+;; associated with the current buffer. The main functions are:
+
+;; `browse-url' Open URL
+;; `browse-url-at-point' Open URL at point
+;; `browse-url-of-buffer' Use web browser to display buffer
+;; `browse-url-of-file' Use web browser to display file
+
+;; Different browsers use different methods of remote control so there
+;; is one function for each supported browser. If the chosen browser
+;; is not running, it is started. Currently there is support for the
+;; following browsers, as well as some other obsolete ones:
;; Function Browser Earliest version
-;; browse-url-mozilla Mozilla Don't know
;; browse-url-firefox Firefox Don't know (tried with 1.0.1)
;; browse-url-chrome Chrome 47.0.2526.111
;; browse-url-chromium Chromium 3.0
;; browse-url-epiphany GNOME Web (Epiphany) Don't know
;; browse-url-webpositive WebPositive 1.2-alpha (Haiku R1/beta3)
-;; browse-url-w3 w3 0
-;; browse-url-text-* Any text browser 0
+;; browse-url-text-* Any text browser 0
;; browse-url-generic arbitrary
;; browse-url-default-windows-browser MS-Windows browser
;; browse-url-default-macosx-browser macOS browser
@@ -50,14 +54,12 @@
;; browse-url-elinks Elinks Don't know (tried with 0.12.GIT)
;; eww-browse-url Emacs Web Wowser
-;; Browsers can cache Web pages so it may be necessary to tell them to
+;; Browsers can cache web pages so it may be necessary to tell them to
;; reload the current page if it has changed (e.g., if you have edited
;; it). There is currently no perfect automatic solution to this.
-;; This package generalizes function html-previewer-process in Marc
-;; Andreessen's html-mode (LCD modes/html-mode.el.Z). See also the
-;; ffap.el package. The huge hyperbole package also contains similar
-;; functions.
+;; See also the ffap.el package. The huge hyperbole package also
+;; contains similar functions.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Usage
@@ -83,34 +85,34 @@
;; M-x browse-url-of-dired-file RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Customization (~/.emacs)
+;; Customization (Init File)
;; To see what variables are available for customization, type
;; `M-x set-variable browse-url TAB'. Better, use
;; `M-x customize-group browse-url'.
-;; Bind the browse-url commands to keys with the `C-c C-z' prefix
-;; (as used by html-helper-mode):
-;; (global-set-key "\C-c\C-z." 'browse-url-at-point)
-;; (global-set-key "\C-c\C-zb" 'browse-url-of-buffer)
-;; (global-set-key "\C-c\C-zr" 'browse-url-of-region)
-;; (global-set-key "\C-c\C-zu" 'browse-url)
-;; (global-set-key "\C-c\C-zv" 'browse-url-of-file)
+;; Bind the browse-url commands to keys with the `C-c C-z' prefix:
+
+;; (keymap-global-set "C-c C-z ." 'browse-url-at-point)
+;; (keymap-global-set "C-c C-z b" 'browse-url-of-buffer)
+;; (keymap-global-set "C-c C-z r" 'browse-url-of-region)
+;; (keymap-global-set "C-c C-z u" 'browse-url)
+;; (keymap-global-set "C-c C-z v" 'browse-url-of-file)
;; (add-hook 'dired-mode-hook
;; (lambda ()
-;; (local-set-key "\C-c\C-zf" 'browse-url-of-dired-file)))
+;; (keymap-local-set "C-c C-z f" 'browse-url-of-dired-file)))
;; Browse URLs in mail messages under RMAIL by clicking mouse-2:
;; (add-hook 'rmail-mode-hook (lambda () ; rmail-mode startup
-;; (define-key rmail-mode-map [mouse-2] 'browse-url-at-mouse)))
+;; (keymap-set rmail-mode-map [mouse-2] 'browse-url-at-mouse)))
;; Alternatively, add `goto-address' to `rmail-show-message-hook'.
;; Gnus provides a standard feature to activate URLs in article
;; buffers for invocation of browse-url.
-;; Use the Emacs w3 browser when not running under X11:
+;; Use the Emacs Web Wowser (EWW) when not running under X11:
;; (or (eq window-system 'x)
-;; (setq browse-url-browser-function 'browse-url-w3))
+;; (setq browse-url-browser-function #'eww-browse-url))
;; To always save modified buffers before displaying the file in a browser:
;; (setq browse-url-save-file t)
@@ -149,15 +151,14 @@
:group 'comm)
(defvar browse-url--browser-defcustom-type
- '(choice
- (function-item :tag "Emacs W3" :value browse-url-w3)
- (function-item :tag "eww" :value eww-browse-url)
- (function-item :tag "Mozilla" :value browse-url-mozilla)
+ `(choice
+ (function-item :tag "Emacs Web Wowser (EWW)" :value eww-browse-url)
(function-item :tag "Firefox" :value browse-url-firefox)
(function-item :tag "Google Chrome" :value browse-url-chrome)
(function-item :tag "Chromium" :value browse-url-chromium)
(function-item :tag "GNOME Web (Epiphany)" :value browse-url-epiphany)
- (function-item :tag "WebPositive" :value browse-url-webpositive)
+ ,@(when (eq system-type 'haiku)
+ (list '(function-item :tag "WebPositive" :value browse-url-webpositive)))
(function-item :tag "Text browser in an xterm window"
:value browse-url-text-xterm)
(function-item :tag "Text browser in an Emacs window"
@@ -165,11 +166,13 @@
(function-item :tag "KDE" :value browse-url-kde)
(function-item :tag "Elinks" :value browse-url-elinks)
(function-item :tag "Specified by `Browse Url Generic Program'"
- :value browse-url-generic)
- (function-item :tag "Default Windows browser"
- :value browse-url-default-windows-browser)
- (function-item :tag "Default macOS browser"
- :value browse-url-default-macosx-browser)
+ :value browse-url-generic)
+ ,@(when (eq system-type 'windows-nt)
+ (list '(function-item :tag "Default Windows browser"
+ :value browse-url-default-windows-browser)))
+ ,@(when (eq system-type 'darwin)
+ (list '(function-item :tag "Default macOS browser"
+ :value browse-url-default-macosx-browser)))
(function-item :tag "Default browser"
:value browse-url-default-browser)
(function :tag "Your own function")
@@ -247,16 +250,19 @@ be used instead."
(defcustom browse-url-mozilla-program "mozilla"
"The name by which to invoke Mozilla."
:type 'string)
+(make-obsolete-variable 'browse-url-mozilla-program nil "29.1")
(defcustom browse-url-mozilla-arguments nil
"A list of strings to pass to Mozilla as arguments."
:type '(repeat (string :tag "Argument")))
+(make-obsolete-variable 'browse-url-mozilla-arguments nil "29.1")
(defcustom browse-url-mozilla-startup-arguments browse-url-mozilla-arguments
"A list of strings to pass to Mozilla when it starts up.
Defaults to the value of `browse-url-mozilla-arguments' at the time
`browse-url' is loaded."
:type '(repeat (string :tag "Argument")))
+(make-obsolete-variable 'browse-url-mozilla-startup-arguments nil "29.1")
(defun browse-url--find-executable (candidates default)
(while (and candidates (not (executable-find (car candidates))))
@@ -340,6 +346,7 @@ Defaults to the value of `browse-url-epiphany-arguments' at the time
If non-nil, then open the URL in a new tab rather than a new window if
`browse-url-mozilla' is asked to open it in a new window."
:type 'boolean)
+(make-obsolete-variable 'browse-url-mozilla-new-window-is-tab nil "29.1")
(defcustom browse-url-firefox-new-window-is-tab nil
"Whether to open up new windows in a tab or a new window.
@@ -404,7 +411,7 @@ address to an HTTP URL:
(setq browse-url-filename-alist
\\='((\"/webmaster@webserver:/home/www/html/\" .
- \"http://www.acme.co.uk/\")
+ \"https://www.example.org/\")
(\"^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*\" . \"ftp://\\2/\")
(\"^/\\([^:@/]+@\\)?\\([^:/]+\\):/*\" . \"ftp://\\1\\2/\")
(\"^/+\" . \"file:/\")))"
@@ -437,11 +444,13 @@ These might set its size, for instance."
(defcustom browse-url-gnudoit-program "gnudoit"
"The name of the `gnudoit' program used by `browse-url-w3-gnudoit'."
:type 'string)
+(make-obsolete-variable 'browse-url-gnudoit-program nil "29.1")
(defcustom browse-url-gnudoit-args '("-q")
"A list of strings defining options for `browse-url-gnudoit-program'.
These might set the port, for instance."
:type '(repeat (string :tag "Argument")))
+(make-obsolete-variable 'browse-url-gnudoit-args nil "29.1")
(defcustom browse-url-generic-program nil
"The name of the browser program used by `browse-url-generic'."
@@ -635,18 +644,32 @@ CHARS is a regexp that matches a character."
The annoying characters are those that can mislead a web browser
regarding its parameter treatment."
;; FIXME: Is there an actual example of a web browser getting
- ;; confused? (This used to encode commas, but at least Firefox
- ;; handles commas correctly and doesn't accept encoded commas.)
- (browse-url-url-encode-chars url "[\"()$ ]"))
+ ;; confused? (This used to encode commas and dollar signs, but at
+ ;; least Firefox handles commas correctly and doesn't accept those
+ ;; encoded.)
+ (browse-url-url-encode-chars url "[\"() ]"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; URL input
+(defcustom browse-url-default-scheme "http"
+ "URL scheme that `browse-url' (and related commands) will use by default.
+
+For example, when point is on an URL fragment like
+\"www.example.org\", `browse-url' will assume that this is an
+\"http\" URL by default (i.e. \"http://www.example.org\").
+
+Note that if you set this to \"https\", websites that do not yet
+support HTTPS may not load correctly in your web browser. Such
+websites are increasingly rare, but they do still exist."
+ :type 'string
+ :version "29.1")
+
(defun browse-url-url-at-point ()
(or (thing-at-point 'url t)
;; assume that the user is pointing at something like gnu.org/gnu
(let ((f (thing-at-point 'filename t)))
- (and f (concat "http://" f)))))
+ (and f (concat browse-url-default-scheme "://" f)))))
;; Having this as a separate function called by the browser-specific
;; functions allows them to be stand-alone commands, making it easier
@@ -708,16 +731,38 @@ interactively. Turn the filename into a URL with function
(browse-url (browse-url-file-url file))
(run-hooks 'browse-url-of-file-hook))
+(defun browse-url--file-name-coding-system ()
+ (if (equal system-type 'windows-nt)
+ ;; W32 pretends that file names are UTF-8 encoded.
+ 'utf-8
+ (or file-name-coding-system default-file-name-coding-system)))
+
(defun browse-url-file-url (file)
"Return the URL corresponding to FILE.
Use variable `browse-url-filename-alist' to map filenames to URLs."
- (let ((coding (if (equal system-type 'windows-nt)
- ;; W32 pretends that file names are UTF-8 encoded.
- 'utf-8
- (and (or file-name-coding-system
- default-file-name-coding-system)))))
- (if coding (setq file (encode-coding-string file coding))))
- (setq file (browse-url-url-encode-chars file "[*\"()',=;?% ]"))
+ (when-let ((coding (browse-url--file-name-coding-system)))
+ (setq file (encode-coding-string file coding)))
+ (if (and (file-remote-p file)
+ ;; We're applying special rules for FTP URLs for historical
+ ;; reasons.
+ (seq-find (lambda (match)
+ (and (string-match-p (car match) file)
+ (not (string-match "\\`file:" (cdr match)))))
+ browse-url-filename-alist))
+ (setq file (browse-url-url-encode-chars file "[*\"()',=;?% ]"))
+ ;; Encode all other file names properly.
+ (let ((bits (file-name-split file)))
+ (setq file
+ (string-join
+ ;; On Windows, the first bit here might be "c:" or the
+ ;; like, so don't encode the ":" in the first bit.
+ (cons (let ((url-unreserved-chars
+ (if (file-name-absolute-p file)
+ (cons ?: url-unreserved-chars)
+ url-unreserved-chars)))
+ (url-hexify-string (car bits)))
+ (mapcar #'url-hexify-string (cdr bits)))
+ "/"))))
(dolist (map browse-url-filename-alist)
(when (and map (string-match (car map) file))
(setq file (replace-match (cdr map) t nil file))))
@@ -769,7 +814,10 @@ If optional arg TEMP-FILE-NAME is non-nil, delete it instead."
(defun browse-url-of-dired-file ()
"In Dired, ask a WWW browser to display the file named on this line."
(interactive)
- (let ((tem (dired-get-filename t t)))
+ (let ((tem (dired-get-filename t t))
+ ;; Some URL handlers open files in Emacs. We want to always
+ ;; open in a browser, so disable those.
+ (browse-url-default-handlers nil))
(if tem
(browse-url-of-file (expand-file-name tem))
(error "No file on this line"))))
@@ -835,7 +883,11 @@ If ARGS are omitted, the default is to pass
((featurep 'pgtk)
(setq classname (pgtk-backend-display-class))
(if (equal classname "GdkWaylandDisplay")
- (setenv "WAYLAND_DISPLAY" dpy)
+ (progn
+ ;; The `display' frame parameter is probably wrong.
+ ;; See bug#53969 for some context.
+ ;; (setenv "WAYLAND_DISPLAY" dpy)
+ )
(setenv "DISPLAY" dpy)))
(t
(setenv "DISPLAY" dpy)))))
@@ -954,7 +1006,13 @@ non-nil, or the same display as Emacs if different from the current
environment, otherwise just use the current environment."
(let ((display (or browse-url-browser-display (browse-url-emacs-display))))
(if display
- (cons (concat "DISPLAY=" display) process-environment)
+ (cons (concat (if (and (eq window-system 'pgtk)
+ (equal (pgtk-backend-display-class)
+ "GdkWaylandDisplay"))
+ "WAYLAND_DISPLAY="
+ "DISPLAY=")
+ display)
+ process-environment)
process-environment)))
(defun browse-url-emacs-display ()
@@ -984,22 +1042,21 @@ instead of `browse-url-new-window-flag'."
'browse-url-default-windows-browser)
((memq system-type '(darwin))
'browse-url-default-macosx-browser)
+ ((featurep 'haiku)
+ 'browse-url-default-haiku-browser)
((browse-url-can-use-xdg-open) 'browse-url-xdg-open)
;;; ((executable-find browse-url-gnome-moz-program) 'browse-url-gnome-moz)
- ((executable-find browse-url-mozilla-program) 'browse-url-mozilla)
((executable-find browse-url-firefox-program) 'browse-url-firefox)
((executable-find browse-url-chromium-program) 'browse-url-chromium)
((executable-find browse-url-kde-program) 'browse-url-kde)
((executable-find browse-url-chrome-program) 'browse-url-chrome)
((executable-find browse-url-webpositive-program) 'browse-url-webpositive)
((executable-find browse-url-xterm-program) 'browse-url-text-xterm)
- ((locate-library "w3") 'browse-url-w3)
- (t
- (lambda (&rest _ignore) (error "No usable browser found"))))
+ (t #'eww-browse-url))
url args))
(function-put 'browse-url-default-browser 'browse-url-browser-kind
- ;; Well, most probably external if we ignore w3.
+ ;; Well, most probably external if we ignore EWW.
'external)
(defun browse-url-can-use-xdg-open ()
@@ -1040,6 +1097,7 @@ new tab in an existing window instead.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
+ (declare (obsolete nil "29.1"))
(interactive (browse-url-interactive-arg "URL: "))
(setq url (browse-url-encode-url url))
(let* ((process-environment (browse-url-process-environment))
@@ -1066,6 +1124,7 @@ used instead of `browse-url-new-window-flag'."
(defun browse-url-mozilla-sentinel (process url)
"Handle a change to the process communicating with Mozilla."
+ (declare (obsolete nil "29.1"))
(or (eq (process-exit-status process) 0)
(let* ((process-environment (browse-url-process-environment)))
;; Mozilla is not running - start it
@@ -1204,6 +1263,24 @@ The optional argument NEW-WINDOW is not used."
(function-put 'browse-url-webpositive 'browse-url-browser-kind 'external)
+(declare-function haiku-roster-launch "haikuselect.c")
+
+;;;###autoload
+(defun browse-url-default-haiku-browser (url &optional _new-window)
+ "Browse URL with the system default browser.
+Default to the URL around or before point."
+ (interactive (browse-url-interactive-arg "URL: "))
+ (setq url (browse-url-encode-url url))
+ (let* ((scheme (save-match-data
+ (if (string-match "\\(.+\\):/" url)
+ (match-string 1 url)
+ "http")))
+ (mime (concat "application/x-vnd.Be.URL." scheme)))
+ (haiku-roster-launch mime (vector url))))
+
+(function-put 'browse-url-default-haiku-browser
+ 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-emacs (url &optional same-window)
"Ask Emacs to load URL into a buffer and show it in another window.
@@ -1213,10 +1290,12 @@ currently selected window instead."
(require 'url-handlers)
(let ((parsed (url-generic-parse-url url))
(func (if same-window 'find-file 'find-file-other-window)))
- (if (and (equal (url-type parsed) "file")
- (file-directory-p (url-filename parsed)))
- ;; It's a directory; just open it.
- (funcall func (url-filename parsed))
+ (if (equal (url-type parsed) "file")
+ ;; It's a file; just open it.
+ (let ((file (url-unhex-string (url-filename parsed))))
+ (when-let ((coding (browse-url--file-name-coding-system)))
+ (setq file (decode-coding-string file 'utf-8)))
+ (funcall func file))
(let ((file-name-handler-alist
(cons (cons url-handler-regexp 'url-file-handler)
file-name-handler-alist)))
@@ -1307,6 +1386,7 @@ prefix argument reverses the effect of `browse-url-new-window-flag'.
When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
+ (declare (obsolete nil "29.1"))
(interactive (browse-url-interactive-arg "W3 URL: "))
(require 'w3) ; w3-fetch-other-window not autoloaded
(if (browse-url-maybe-new-window new-window)
@@ -1576,13 +1656,11 @@ from `browse-url-elinks-wrapper'."
;;; Adding buttons to a buffer to call `browse-url' when you hit them.
-(defvar browse-url-button-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\r" #'browse-url-button-open)
- (define-key map [mouse-2] #'browse-url-button-open)
- (define-key map "w" #'browse-url-button-copy)
- map)
- "The keymap used for `browse-url' buttons.")
+(defvar-keymap browse-url-button-map
+ :doc "The keymap used for `browse-url' buttons."
+ "RET" #'browse-url-button-open
+ "<mouse-2>" #'browse-url-button-open
+ "w" #'browse-url-button-copy)
(defface browse-url-button
'((t :inherit link))
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index 6a8bf879671..d4d4ed54e90 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -1871,13 +1871,7 @@ name and cdr is the list of properties as returned by
\(dbus-get-all-managed-objects :session \"org.gnome.SettingsDaemon\" \"/\")
- => ((\"/org/gnome/SettingsDaemon/MediaKeys\"
- (\"org.gnome.SettingsDaemon.MediaKeys\")
- (\"org.freedesktop.DBus.Peer\")
- (\"org.freedesktop.DBus.Introspectable\")
- (\"org.freedesktop.DBus.Properties\")
- (\"org.freedesktop.DBus.ObjectManager\"))
- (\"/org/gnome/SettingsDaemon/Power\"
+ => ((\"/org/gnome/SettingsDaemon/Power\"
(\"org.gnome.SettingsDaemon.Power.Keyboard\")
(\"org.gnome.SettingsDaemon.Power.Screen\")
(\"org.gnome.SettingsDaemon.Power\"
diff --git a/lisp/net/dictionary-connection.el b/lisp/net/dictionary-connection.el
index aef3c4efc74..a4afcd6647d 100644
--- a/lisp/net/dictionary-connection.el
+++ b/lisp/net/dictionary-connection.el
@@ -83,10 +83,10 @@ Return a data structure identifying the connection."
"Return the status of the CONNECTION.
Possible return values are the symbols:
nil: argument is not a connection object
- 'none: argument is not connected
- 'up: connection is open and buffer is existing
- 'down: connection is closed
- 'alone: connection is not associated with a buffer"
+ `none': argument is not connected
+ `up': connection is open and buffer is existing
+ `down': connection is closed
+ `alone': connection is not associated with a buffer"
(when (dictionary-connection-p connection)
(let ((process (dictionary-connection-process connection))
(buffer (dictionary-connection-buffer connection)))
diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el
index 507363cc0f8..31cc5035a3e 100644
--- a/lisp/net/dictionary.el
+++ b/lisp/net/dictionary.el
@@ -89,7 +89,7 @@ You can specify here:
This port is probably always 2628 so there should be no need to modify it."
:group 'dictionary
:set #'dictionary-set-server-var
- :type 'number
+ :type 'natnum
:version "28.1")
(defcustom dictionary-identification
@@ -206,7 +206,7 @@ where the current word was found."
"The port of the proxy server, used only when `dictionary-use-http-proxy' is set."
:group 'dictionary-proxy
:set #'dictionary-set-server-var
- :type 'number
+ :type 'natnum
:version "28.1")
(defcustom dictionary-use-single-buffer
@@ -326,26 +326,22 @@ is utf-8"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Global variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar dictionary-mode-map
- (let ((map (make-sparse-keymap)))
- (suppress-keymap map)
- (set-keymap-parent map button-buffer-map)
-
- (define-key map "q" #'dictionary-close)
- (define-key map "h" #'dictionary-help)
- (define-key map "s" #'dictionary-search)
- (define-key map "d" #'dictionary-lookup-definition)
- (define-key map "D" #'dictionary-select-dictionary)
- (define-key map "M" #'dictionary-select-strategy)
- (define-key map "m" #'dictionary-match-words)
- (define-key map "l" #'dictionary-previous)
- (define-key map "n" #'forward-button)
- (define-key map "p" #'backward-button)
- (define-key map " " #'scroll-up-command)
- (define-key map [?\S-\ ] #'scroll-down-command)
- (define-key map (read-kbd-macro "M-SPC") #'scroll-down-command)
- map)
- "Keymap for the dictionary mode.")
+(defvar-keymap dictionary-mode-map
+ :doc "Keymap for the dictionary mode."
+ :suppress t :parent button-buffer-map
+ "q" #'dictionary-close
+ "h" #'dictionary-help
+ "s" #'dictionary-search
+ "d" #'dictionary-lookup-definition
+ "D" #'dictionary-select-dictionary
+ "M" #'dictionary-select-strategy
+ "m" #'dictionary-match-words
+ "l" #'dictionary-previous
+ "n" #'forward-button
+ "p" #'backward-button
+ "SPC" #'scroll-up-command
+ "S-SPC" #'scroll-down-command
+ "M-SPC" #'scroll-down-command)
(defvar dictionary-connection
nil
@@ -759,31 +755,31 @@ of matching words."
(progn
(insert-button "[Back]" :type 'dictionary-button
'callback 'dictionary-restore-state
- 'help-echo (purecopy "Mouse-2 to go backwards in history"))
+ 'help-echo "Mouse-2 to go backwards in history")
(insert " ")
(insert-button "[Search definition]" :type 'dictionary-button
'callback 'dictionary-search
- 'help-echo (purecopy "Mouse-2 to look up a new word"))
+ 'help-echo "Mouse-2 to look up a new word")
(insert " ")
(insert-button "[Matching words]" :type 'dictionary-button
'callback 'dictionary-match-words
- 'help-echo (purecopy "Mouse-2 to find matches for a pattern"))
+ 'help-echo "Mouse-2 to find matches for a pattern")
(insert " ")
(insert-button "[Quit]" :type 'dictionary-button
'callback 'dictionary-close
- 'help-echo (purecopy "Mouse-2 to close this window"))
+ 'help-echo "Mouse-2 to close this window")
(insert "\n ")
(insert-button "[Select dictionary]" :type 'dictionary-button
'callback 'dictionary-select-dictionary
- 'help-echo (purecopy "Mouse-2 to select dictionary for future searches"))
+ 'help-echo "Mouse-2 to select dictionary for future searches")
(insert " ")
(insert-button "[Select match strategy]" :type 'dictionary-button
'callback 'dictionary-select-strategy
- 'help-echo (purecopy "Mouse-2 to select matching algorithm"))
+ 'help-echo "Mouse-2 to select matching algorithm")
(insert "\n\n")))
(setq dictionary-marker (point-marker)))
@@ -932,13 +928,13 @@ If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
(insert-button (concat dictionary ": " translated) :type 'dictionary-link
'callback 'dictionary-set-dictionary
'data (cons dictionary description)
- 'help-echo (purecopy "Mouse-2 to select this dictionary"))
+ 'help-echo "Mouse-2 to select this dictionary")
(unless (dictionary-special-dictionary dictionary)
(insert " ")
(insert-button "(Details)" :type 'dictionary-link
'callback 'dictionary-set-dictionary
'list-data (list (cons dictionary description) t)
- 'help-echo (purecopy "Mouse-2 to get more information")))
+ 'help-echo "Mouse-2 to get more information"))
(insert "\n")))))
(defun dictionary-set-dictionary (param &optional more)
@@ -976,7 +972,7 @@ If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
(insert-button description :type 'dictionary-link
'callback 'dictionary-set-dictionary
'data (cons dictionary description)
- 'help-echo (purecopy "Mouse-2 to select this dictionary"))
+ 'help-echo "Mouse-2 to select this dictionary")
(insert "\n\n")
(setq reply (dictionary-read-answer))
(insert reply)
@@ -1027,7 +1023,7 @@ If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
(insert-button description :type 'dictionary-link
'callback 'dictionary-set-strategy
'data strategy
- 'help-echo (purecopy "Mouse-2 to select this matching algorithm"))
+ 'help-echo "Mouse-2 to select this matching algorithm")
(insert "\n")))))
(defun dictionary-set-strategy (strategy &rest _ignored)
@@ -1128,7 +1124,7 @@ If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
(insert-button word :type 'dictionary-link
'callback 'dictionary-new-search
'data (cons word dictionary)
- 'help-echo (purecopy "Mouse-2 to lookup word"))
+ 'help-echo "Mouse-2 to lookup word")
(insert "\n")) (reverse word-list))
(insert "\n")))
list))
@@ -1376,7 +1372,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
diff --git a/lisp/net/dig.el b/lisp/net/dig.el
index f7f1500454a..d4fad0c61fd 100644
--- a/lisp/net/dig.el
+++ b/lisp/net/dig.el
@@ -44,6 +44,11 @@
"Name of dig (domain information groper) binary."
:type 'file)
+(defcustom dig-program-options nil
+ "Options for the dig program."
+ :type '(repeat string)
+ :version "26.1")
+
(defcustom dig-dns-server nil
"DNS server to query.
If nil, use system defaults."
@@ -59,8 +64,8 @@ If nil, use system defaults."
:type 'sexp)
(defun dig-invoke (domain &optional
- query-type query-class query-option
- dig-option server)
+ query-type query-class query-option
+ dig-option server)
"Call dig with given arguments and return buffer containing output.
DOMAIN is a string with a DNS domain. QUERY-TYPE is an optional
string with a DNS type. QUERY-CLASS is an optional string with a DNS
@@ -79,7 +84,8 @@ and is a commonly available debugging tool."
(push domain cmdline)
(if server (push (concat "@" server) cmdline)
(if dig-dns-server (push (concat "@" dig-dns-server) cmdline)))
- (apply #'call-process dig-program nil buf nil cmdline)
+ (apply #'call-process dig-program nil buf nil
+ (append dig-program-options cmdline))
buf))
(defun dig-extract-rr (domain &optional type class)
@@ -117,11 +123,9 @@ Buffer should contain output generated by `dig-invoke'."
(setq str (replace-match "" nil nil str)))
str))
-(defvar dig-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "g" nil)
- (define-key map "q" #'dig-exit)
- map))
+(defvar-keymap dig-mode-map
+ "g" nil
+ "q" #'dig-exit)
(define-derived-mode dig-mode special-mode "Dig"
"Major mode for displaying dig output."
@@ -132,7 +136,7 @@ Buffer should contain output generated by `dig-invoke'."
(defun dig-exit ()
"Quit dig output buffer."
- (interactive)
+ (interactive nil dig-mode)
(quit-window t))
;;;###autoload
@@ -140,12 +144,23 @@ Buffer should contain output generated by `dig-invoke'."
query-type query-class query-option dig-option server)
"Query addresses of a DOMAIN using dig.
See `dig-invoke' for an explanation for the parameters.
-When called interactively, DOMAIN is prompted for. If given a prefix,
-also prompt for the QUERY-TYPE parameter."
+When called interactively, DOMAIN is prompted for.
+
+If given a \\[universal-argument] prefix, also prompt \
+for the QUERY-TYPE parameter.
+
+If given a \\[universal-argument] \\[universal-argument] \
+prefix, also prompt for the SERVER parameter."
(interactive
- (list (read-string "Host: ")
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Host" default) nil nil default))
(and current-prefix-arg
(read-string "Query type: "))))
+ (when (and (numberp (car current-prefix-arg))
+ (>= (car current-prefix-arg) 16))
+ (let ((serv (read-from-minibuffer "Name server: ")))
+ (when (not (equal serv ""))
+ (setq server serv))))
(pop-to-buffer-same-window
(dig-invoke domain query-type query-class query-option dig-option server))
(goto-char (point-min))
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index 6a2cd13dd03..68a0ccb3a13 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -86,7 +86,7 @@
`("EUDC Image Menu"
["---" nil nil]
["Toggle inline display" eudc-bob-toggle-inline-display
- (eudc-bob-can-display-inline-images)]
+ (display-graphic-p)]
,@(cdr (cdr eudc-bob-generic-menu))))
(defvar eudc-bob-sound-menu
@@ -109,14 +109,6 @@
(setq overlays (cdr overlays)))
value))
-(defun eudc-bob-can-display-inline-images ()
- "Return non-nil if we can display images inline."
- (if (fboundp 'console-type)
- (and (memq (console-type) '(x mswindows))
- (fboundp 'make-glyph))
- (and (fboundp 'display-graphic-p)
- (display-graphic-p))))
-
(defun eudc-bob-make-button (label keymap &optional menu plist)
"Create a button with LABEL.
Attach KEYMAP, MENU and properties from PLIST to a new overlay covering
@@ -124,7 +116,7 @@ LABEL."
(let (overlay
(p (point))
prop val)
- (insert label)
+ (insert (or label ""))
(put-text-property p (point) 'face 'bold)
(setq overlay (make-overlay p (point)))
(overlay-put overlay 'mouse-face 'highlight)
@@ -142,19 +134,7 @@ LABEL."
"Display the JPEG DATA at point.
If INLINE is non-nil, try to inline the image otherwise simply
display a button."
- (cond ((fboundp 'make-glyph)
- (let ((glyph (if (eudc-bob-can-display-inline-images)
- (make-glyph (list (vector 'jpeg :data data)
- [string :data "[JPEG Picture]"])))))
- (eudc-bob-make-button "[JPEG Picture]"
- eudc-bob-image-keymap
- eudc-bob-image-menu
- (list 'glyph glyph
- 'end-glyph (if inline glyph)
- 'duplicable t
- 'invisible inline
- 'object-data data))))
- ((fboundp 'create-image)
+ (cond ((fboundp 'create-image)
(let* ((image (create-image data nil t))
(props (list 'object-data data 'eudc-image image)))
(when (and inline (image-type-available-p 'jpeg))
@@ -167,7 +147,7 @@ display a button."
(defun eudc-bob-toggle-inline-display ()
"Toggle inline display of an image."
(interactive)
- (when (eudc-bob-can-display-inline-images)
+ (when (display-graphic-p)
(let* ((overlays (append (overlays-at (1- (point)))
(overlays-at (point))))
image)
@@ -287,11 +267,13 @@ display a button."
;;;###autoload
(defun eudc-display-jpeg-inline (data)
"Display the JPEG DATA inline at point if possible."
- (eudc-bob-display-jpeg data (eudc-bob-can-display-inline-images)))
+ (eudc-bob-display-jpeg data (display-graphic-p)))
;;;###autoload
(defun eudc-display-jpeg-as-button (data)
"Display a button for the JPEG DATA."
(eudc-bob-display-jpeg data nil))
+(define-obsolete-function-alias 'eudc-bob-can-display-inline-images #'display-graphic-p "29.1")
+
;;; eudc-bob.el ends here
diff --git a/lisp/net/eudc-capf.el b/lisp/net/eudc-capf.el
new file mode 100644
index 00000000000..68cbfd93ffe
--- /dev/null
+++ b/lisp/net/eudc-capf.el
@@ -0,0 +1,133 @@
+;;; eudc-capf.el --- EUDC - completion-at-point bindings -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; Author: Alexander Adolf
+;;
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides functions to deliver email addresses from
+;; EUDC search results to `completion-at-point'.
+;;
+;; Email address completion will likely be desirable only in
+;; situations where designating email recipients plays a role, such
+;; as when composing or replying to email messages, or when posting
+;; to newsgroups, possibly with copies of the post being emailed.
+;; Hence, modes relevant in such contexts, such as for example
+;; `message-mode' and `mail-mode', often at least to some extent
+;; provide infrastructure for different functions to be called when
+;; completing in certain message header fields, or in the body of
+;; the message. In other modes for editing email messages or
+;; newsgroup posts, which do not provide such infrastructure, any
+;; completion function providing email addresses will need to check
+;; whether the completion attempt occurs in an appropriate context
+;; (that is, in a relevant message header field) before providing
+;; completion candidates. Two mechanisms are thus provided by this
+;; library.
+;;
+;; The first mechanism is intended for use by the modes listed in
+;; `eudc-capf-modes', and relies on these modes adding
+;; `eudc-capf-complete' to `completion-at-point-functions', as
+;; would be usually done for any general-purpose completion
+;; function. In this mode of operation, and in order to offer
+;; email addresses only in contexts where the user would expect
+;; them, a check is performed whether point is on a line that is a
+;; message header field suitable for email addresses, such as for
+;; example "To:", "Cc:", etc.
+;;
+;; The second mechanism is intended for when the user modifies
+;; `message-completion-alist' to replace `message-expand-name' with
+;; the function `eudc-capf-message-expand-name'. As a result,
+;; minibuffer completion (`completing-read') for email addresses
+;; would no longer enabled in `message-mode', but
+;; `completion-at-point' (in-buffer completion) only.
+
+;;; Usage:
+
+;; In a major mode, or context where you want email address
+;; completion, you would do something along the lines of:
+;;
+;; (require 'eudc-capf)
+;; (add-hook 'completion-at-point-functions #'eudc-capf-complete -1 t)
+;;
+;; The minus one argument puts it at the front of the list so it is
+;; called first, and the t value for the LOCAL parameter causes the
+;; setting to be buffer local, so as to avoid modifying any global
+;; setting.
+;;
+;; The value of the variable `eudc-capf-modes' indicates which
+;; major modes do such a setup as part of their initialisation
+;; code.
+
+;;; Code:
+
+(require 'eudc)
+
+(defvar message-email-recipient-header-regexp)
+(defvar mail-abbrev-mode-regexp)
+(declare-function mail-abbrev-in-expansion-header-p "mailabbrev" ())
+
+(defconst eudc-capf-modes '(message-mode)
+ "List of modes in which email address completion is to be attempted.")
+
+;; completion functions
+
+;;;###autoload
+(defun eudc-capf-complete ()
+ "Email address completion function for `completion-at-point-functions'.
+
+This function checks whether the current major mode is one of the
+modes listed in `eudc-capf-modes', and whether point is on a line
+with a message header listing email recipients, that is, a line
+whose beginning matches `message-email-recipient-header-regexp',
+and, if the check succeeds, searches for records matching the
+words before point.
+
+The return value is either nil when no match is found, or a
+completion table as required for functions listed in
+`completion-at-point-functions'."
+ (if (and (seq-some #'derived-mode-p eudc-capf-modes)
+ (let ((mail-abbrev-mode-regexp message-email-recipient-header-regexp))
+ (mail-abbrev-in-expansion-header-p)))
+ (eudc-capf-message-expand-name)))
+
+;;;###autoload
+(defun eudc-capf-message-expand-name ()
+ "Email address completion function for `message-completion-alist'.
+
+When this function is added to `message-completion-alist',
+replacing any existing entry for `message-expand-name' there,
+with an appropriate regular expression such as for example
+`message-email-recipient-header-regexp', then EUDC will be
+queried for email addresses, and the results delivered to
+`completion-at-point'."
+ (if (or eudc-server eudc-server-hotlist)
+ (progn
+ (let* ((beg (save-excursion
+ (re-search-backward "\\([:,]\\|^\\)[ \t]*")
+ (match-end 0)))
+ (end (point))
+ (prefix (save-excursion (buffer-substring-no-properties beg end))))
+ (list beg end
+ (completion-table-with-cache
+ (lambda (_)
+ (eudc-query-with-words (split-string prefix "[ \t]+") t))
+ t))))))
+
+(provide 'eudc-capf)
+;;; eudc-capf.el ends here
diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el
index 26afd768051..d70e0cf4f63 100644
--- a/lisp/net/eudc-hotlist.el
+++ b/lisp/net/eudc-hotlist.el
@@ -35,15 +35,13 @@
(defvar eudc-hotlist-menu nil)
(defvar eudc-hotlist-list-beginning nil)
-(defvar eudc-hotlist-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "a" #'eudc-hotlist-add-server)
- (define-key map "d" #'eudc-hotlist-delete-server)
- (define-key map "s" #'eudc-hotlist-select-server)
- (define-key map "t" #'eudc-hotlist-transpose-servers)
- (define-key map "q" #'eudc-hotlist-quit-edit)
- (define-key map "x" #'kill-current-buffer)
- map))
+(defvar-keymap eudc-hotlist-mode-map
+ "a" #'eudc-hotlist-add-server
+ "d" #'eudc-hotlist-delete-server
+ "s" #'eudc-hotlist-select-server
+ "t" #'eudc-hotlist-transpose-servers
+ "q" #'eudc-hotlist-quit-edit
+ "x" #'kill-current-buffer)
(define-derived-mode eudc-hotlist-mode fundamental-mode "EUDC-Servers"
"Major mode used to edit the hotlist of servers.
diff --git a/lisp/net/eudc-vars.el b/lisp/net/eudc-vars.el
index 3122b26cd81..59347ccc89a 100644
--- a/lisp/net/eudc-vars.el
+++ b/lisp/net/eudc-vars.el
@@ -42,7 +42,7 @@ A port number may be specified by appending a colon and a
number to the name of the server. Use `localhost' if the directory
server resides on your computer (BBDB backend).
-To specify multiple servers, customize eudc-server-hotlist
+To specify multiple servers, customize `eudc-server-hotlist'
instead."
:type '(choice (string :tag "Server") (const :tag "None" nil)))
@@ -179,32 +179,63 @@ must be set in a protocol/server-local fashion, see `eudc-server-set' and
(symbol :menu-tag "Other" :tag "Attribute name"))))
:version "25.1")
-;; Default to nil so that the most common use of eudc-expand-inline,
-;; where replace is nil, does not affect the kill ring.
-(defcustom eudc-expansion-overwrites-query nil
- "If non-nil, expanding a query overwrites the query string."
+(define-obsolete-variable-alias
+ 'eudc-expansion-overwrites-query
+ 'eudc-expansion-save-query-as-kill
+ "29.1")
+
+;; Default to nil so that the most common use of `eudc-expand-inline',
+;; where `save-query-as-kill' is nil, does not affect the kill ring.
+(defcustom eudc-expansion-save-query-as-kill nil
+ "If non-nil, expansion saves the query string to the kill ring."
:type 'boolean
:version "25.1")
-(defcustom eudc-inline-expansion-format '("%s %s <%s>" firstname name email)
- "A list specifying the format of the expansion of inline queries.
-This variable controls what `eudc-expand-inline' actually inserts in
-the buffer. First element is a string passed to `format'. Remaining
-elements are symbols indicating attribute names; the corresponding values
-are passed as additional arguments to `format'."
- :type '(list
- (string :tag "Format String")
- (repeat :inline t
- :tag "Attributes"
- (choice
- :tag "Attribute"
- (const :menu-tag "First Name" :tag "First Name" firstname)
- (const :menu-tag "Surname" :tag "Surname" name)
- (const :menu-tag "Email Address" :tag "Email Address" email)
- (const :menu-tag "Phone" :tag "Phone" phone)
- (symbol :menu-tag "Other")
- (symbol :tag "Attribute name"))))
- :version "25.1")
+(defcustom eudc-inline-expansion-format nil
+ "Specify the format of the expansion of inline queries.
+This variable controls what `eudc-expand-inline' actually inserts
+in the buffer. It is either a list, or a function.
+
+When set to a list, the expansion result will be formatted
+according to the first element of the list, a string, which is
+passed as the first argument to `format'. The remaining elements
+of the list are symbols indicating attribute names; the
+corresponding values are passed as additional arguments to
+`format'.
+
+When set to nil, the expansion result will be formatted using
+`eudc-rfc5322-make-address', and the PHRASE part will be
+formatted according to \"firstname name\", quoting the result if
+necessary. No COMMENT will be added in this case.
+
+When set to a function, the expansion result will be formatted
+using `eudc-rfc5322-make-address', and the referenced function is
+used to format the PHRASE, and COMMENT parts, respectively. It
+receives a single argument, which is an alist of
+protocol-specific attributes describing the recipient. To access
+the alist elements using generic EUDC attribute names, such as
+for example name, or email, use `eudc-translate-attribute-list'.
+The function should return a list, which should contain two
+elements. If the first element is a string, it will be used as
+the PHRASE part, quoting it if necessary. If the second element
+is a string, it will be used as the COMMENT part, unless it
+contains characters not allowed in the COMMENT part by RFC 5322,
+in which case the COMMENT part will be omitted."
+ :type '(choice (const :tag "RFC 5322 formatted \"first last <address>\"" nil)
+ (function :tag "RFC 5322 phrase/comment formatting function")
+ (list :tag "Format string (deprecated)"
+ (string :tag "Format String")
+ (repeat :inline t
+ :tag "Attributes"
+ (choice
+ :tag "Attribute"
+ (const :menu-tag "First Name" :tag "First Name" firstname)
+ (const :menu-tag "Surname" :tag "Surname" name)
+ (const :menu-tag "Email Address" :tag "Email Address" email)
+ (const :menu-tag "Phone" :tag "Phone" phone)
+ (symbol :menu-tag "Other")
+ (symbol :tag "Attribute name")))))
+ :version "29.1")
(defcustom eudc-inline-expansion-servers 'server-then-hotlist
"Which servers to contact for the expansion of inline queries.
@@ -252,6 +283,7 @@ If nil, query all servers available from `eudc-inline-expansion-servers'."
(firstname . "First Name")
(cn . "Full Name")
(sn . "Surname")
+ (name . "Surname")
(givenname . "First Name")
(ou . "Unit")
(labeledurl . "URL")
@@ -394,6 +426,15 @@ BBDB fields. SPECs are sexps which are evaluated:
(symbol :tag "BBDB Field")
(sexp :tag "Conversion Spec"))))
+(defcustom eudc-ldap-no-wildcard-attributes
+ '(objectclass objectcategory)
+ "LDAP attributes which are always searched for without wildcard character.
+This is the list of special dictionary-valued attributes, where
+wildcarded search may fail. For example, it fails with
+objectclass in Active Directory servers."
+ :type '(repeat (symbol :tag "Directory attribute")))
+
+
;;}}}
;;{{{ BBDB Custom Group
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index 6831c4ffe3d..9208e40a730 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -48,6 +48,7 @@
(require 'wid-edit)
(require 'cl-lib)
(require 'eudc-vars)
+(eval-when-compile (require 'subr-x))
;;{{{ Internal cooking
@@ -55,16 +56,14 @@
(defvar eudc-form-widget-list nil)
-(defvar eudc-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map widget-keymap)
- (define-key map "q" #'kill-current-buffer)
- (define-key map "x" #'kill-current-buffer)
- (define-key map "f" #'eudc-query-form)
- (define-key map "b" #'eudc-try-bbdb-insert)
- (define-key map "n" #'eudc-move-to-next-record)
- (define-key map "p" #'eudc-move-to-previous-record)
- map))
+(defvar-keymap eudc-mode-map
+ :parent widget-keymap
+ "q" #'kill-current-buffer
+ "x" #'kill-current-buffer
+ "f" #'eudc-query-form
+ "b" #'eudc-try-bbdb-insert
+ "n" #'eudc-move-to-next-record
+ "p" #'eudc-move-to-previous-record)
(defvar mode-popup-menu)
@@ -162,6 +161,75 @@ Value is the new string."
newtext)))
(concat rtn-str (substring str start))))
+
+(defconst eudc-rfc5322-atext-token "[:alpha:][:digit:]!#$%&'*+/=?^_`{|}~-"
+ "Printable US-ASCII characters not including specials. Used for atoms.")
+
+(defconst eudc-rfc5322-wsp-token " \t"
+ "Non-folding white space.")
+
+(defconst eudc-rfc5322-fwsp-token
+ (concat eudc-rfc5322-wsp-token "\n")
+ "Folding white space.")
+
+(defconst eudc-rfc5322-cctext-token "\u005D-\u007E\u002A-\u005B\u0021-\u0027"
+ "Printable US-ASCII characters not including \"(\", \")\", or \"\\\".")
+
+(defun eudc-rfc5322-quote-phrase (string)
+ "Quote STRING if it needs quoting as a phrase in a header."
+ (if (string-match
+ (concat "[^" eudc-rfc5322-wsp-token eudc-rfc5322-atext-token "]")
+ string)
+ (concat "\"" string "\"")
+ string))
+
+(defun eudc-rfc5322-valid-comment-p (string)
+ "Check if STRING can be used as comment in a header."
+ (if (string-match
+ (concat "[^" eudc-rfc5322-cctext-token eudc-rfc5322-fwsp-token "]")
+ string)
+ nil
+ t))
+
+(defun eudc-rfc5322-make-address (address &optional firstname name comment)
+ "Create a valid address specification according to RFC5322.
+RFC5322 address specifications are used in message header fields
+to indicate senders and recipients of messages. They generally
+have one of the forms:
+
+ADDRESS
+ADDRESS (COMMENT)
+PHRASE <ADDRESS>
+PHRASE <ADDRESS> (COMMENT)
+
+The arguments FIRSTNAME and NAME are combined to form PHRASE.
+PHRASE is enclosed in double quotes if necessary.
+
+COMMENT is omitted if it contains any symbols outside the
+permitted set `eudc-rfc5322-cctext-token'."
+ (if (and address
+ (not (string-blank-p address)))
+ (let ((result address)
+ (name-given (and name
+ (not (string-blank-p name))))
+ (firstname-given (and firstname
+ (not (string-blank-p firstname))))
+ (valid-comment-given (and comment
+ (not (string-blank-p comment))
+ (eudc-rfc5322-valid-comment-p comment))))
+ (if (or name-given firstname-given)
+ (let ((phrase (string-trim (concat firstname " " name))))
+ (setq result
+ (concat
+ (eudc-rfc5322-quote-phrase phrase)
+ " <" result ">"))))
+ (if valid-comment-given
+ (setq result
+ (concat result " (" comment ")")))
+ result)
+ ;; nil or empty address, nothing to return
+ nil))
+
;;}}}
;;{{{ Server and Protocol Variable Routines
@@ -298,8 +366,8 @@ accordingly. Otherwise it is set to its EUDC default binding."
;;}}}
-;; Add PROTOCOL to the list of supported protocols
(defun eudc-register-protocol (protocol)
+ "Add PROTOCOL to the list of supported protocols."
(unless (memq protocol eudc-supported-protocols)
(setq eudc-supported-protocols
(cons protocol eudc-supported-protocols))
@@ -313,32 +381,51 @@ accordingly. Otherwise it is set to its EUDC default binding."
(cons protocol eudc-known-protocols))))
-(defun eudc-translate-query (query)
+(defun eudc-translate-query (query &optional reverse)
"Translate attribute names of QUERY.
The translation is done according to
-`eudc-protocol-attributes-translation-alist'."
+`eudc-protocol-attributes-translation-alist'.
+
+When REVERSE is nil or omitted, the attribute names are
+translated from EUDC generic names to protocol-specific
+names. When REVERSE is non-nil, the translation is from
+protocol-specific names back to EUDC generic names."
(if eudc-protocol-attributes-translation-alist
(mapcar (lambda (attribute)
- (let ((trans (assq (car attribute)
- (symbol-value eudc-protocol-attributes-translation-alist))))
+ (let ((trans
+ (if reverse
+ (rassq (car attribute)
+ (symbol-value eudc-protocol-attributes-translation-alist))
+ (assq (car attribute)
+ (symbol-value eudc-protocol-attributes-translation-alist)))))
(if trans
- (cons (cdr trans) (cdr attribute))
+ (cons (if reverse (car trans) (cdr trans))
+ (cdr attribute))
attribute)))
query)
query))
-(defun eudc-translate-attribute-list (list)
+(defun eudc-translate-attribute-list (list &optional reverse)
"Translate a list of attribute names LIST.
The translation is done according to
-`eudc-protocol-attributes-translation-alist'."
+`eudc-protocol-attributes-translation-alist'.
+
+When REVERSE is nil or omitted, the attribute names are
+translated from EUDC generic names to protocol-specific
+names. When REVERSE is non-nil, the translation is from
+protocol-specific names back to EUDC generic names."
(if eudc-protocol-attributes-translation-alist
(let (trans)
(mapcar (lambda (attribute)
- (setq trans (assq attribute
- (symbol-value eudc-protocol-attributes-translation-alist)))
- (if trans
- (cdr trans)
- attribute))
+ (setq trans
+ (if reverse
+ (rassq attribute
+ (symbol-value eudc-protocol-attributes-translation-alist))
+ (assq attribute
+ (symbol-value eudc-protocol-attributes-translation-alist))))
+ (if trans
+ (if reverse (car trans) (cdr trans))
+ attribute))
list))
list))
@@ -651,7 +738,7 @@ server for future sessions."
(defun eudc-get-email (name &optional error)
"Get the email field of NAME from the directory server.
If ERROR is non-nil, report an error if there is none."
- (interactive "sName: \np")
+ (interactive "sSurname: \np")
(or eudc-server
(call-interactively 'eudc-set-server))
(let ((result (eudc-query (list (cons 'name name)) '(email)))
@@ -669,7 +756,7 @@ If ERROR is non-nil, report an error if there is none."
(defun eudc-get-phone (name &optional error)
"Get the phone field of NAME from the directory server.
If ERROR is non-nil, report an error if there is none."
- (interactive "sName: \np")
+ (interactive "sSurname: \np")
(or eudc-server
(call-interactively 'eudc-set-server))
(let ((result (eudc-query (list (cons 'name name)) '(phone)))
@@ -741,9 +828,18 @@ If none try N - 1 and so forth."
(setq n (1- n)))
formats))
+;;;###autoload
+(defun eudc-expand-try-all (&optional try-all-servers)
+ "Wrap `eudc-expand-inline' with a prefix argument.
+If TRY-ALL-SERVERS -- the prefix argument when called
+interactively -- is non-nil, collect results from all servers.
+If TRY-ALL-SERVERS is nil, do not try subsequent servers after
+one server returns any match."
+ (interactive "P")
+ (eudc-expand-inline (not eudc-expansion-save-query-as-kill) try-all-servers))
;;;###autoload
-(defun eudc-expand-inline (&optional replace)
+(defun eudc-expand-inline (&optional save-query-as-kill try-all-servers)
"Query the directory server, and expand the query string before point.
The query string consists of the buffer substring from the point back to
the preceding comma, colon or beginning of line.
@@ -751,10 +847,12 @@ The variable `eudc-inline-query-format' controls how to associate the
individual inline query words with directory attribute names.
After querying the server for the given string, the expansion specified by
`eudc-inline-expansion-format' is inserted in the buffer at point.
-If REPLACE is non-nil, then this expansion replaces the name in the buffer.
-`eudc-expansion-overwrites-query' being non-nil inverts the meaning of REPLACE.
+If SAVE-QUERY-AS-KILL is non-nil, then save the pre-expansion
+text to the kill ring. `eudc-expansion-save-query-as-kill' being
+non-nil inverts the meaning of SAVE-QUERY-AS-KILL.
Multiple servers can be tried with the same query until one finds a match,
-see `eudc-inline-expansion-servers'."
+see `eudc-inline-expansion-servers'. If TRY-ALL-SERVERS is
+non-nil, collect results from all servers."
(interactive)
(let* ((end (point))
(beg (save-excursion
@@ -764,13 +862,13 @@ see `eudc-inline-expansion-servers'."
(point)))
(query-words (split-string (buffer-substring-no-properties beg end)
"[ \t]+"))
- (response-strings (eudc-query-with-words query-words)))
+ (response-strings (eudc-query-with-words query-words try-all-servers)))
(if (null response-strings)
(error "No match")
(if (or
- (and replace (not eudc-expansion-overwrites-query))
- (and (not replace) eudc-expansion-overwrites-query))
+ (and save-query-as-kill (not eudc-expansion-save-query-as-kill))
+ (and (not save-query-as-kill) eudc-expansion-save-query-as-kill))
(kill-ring-save beg end))
(cond
((or (= (length response-strings) 1)
@@ -787,15 +885,65 @@ see `eudc-inline-expansion-servers'."
(error "There is more than one match for the query"))))))
;;;###autoload
-(defun eudc-query-with-words (query-words)
+(defun eudc-format-inline-expansion-result (res query-attrs)
+ "Format a query result according to `eudc-inline-expansion-format'."
+ (cond
+ ;; format string
+ ((consp eudc-inline-expansion-format)
+ (string-trim (apply #'format
+ (car eudc-inline-expansion-format)
+ (mapcar
+ (lambda (field)
+ (or (cdr (assq field res))
+ ""))
+ (eudc-translate-attribute-list
+ (cdr eudc-inline-expansion-format))))))
+
+ ;; formatting function
+ ((functionp eudc-inline-expansion-format)
+ (let ((addr (cdr (assq (nth 2 query-attrs) res)))
+ (ucontent (funcall eudc-inline-expansion-format res)))
+ (if (and ucontent
+ (listp ucontent))
+ (let* ((phrase (car ucontent))
+ (comment (cadr ucontent))
+ (phrase-given
+ (and phrase
+ (stringp phrase)
+ (not (string-blank-p phrase))))
+ (valid-comment-given
+ (and comment
+ (stringp comment)
+ (not (string-blank-p comment))
+ (eudc-rfc5322-valid-comment-p
+ comment))))
+ (eudc-rfc5322-make-address
+ addr nil
+ (if phrase-given phrase nil)
+ (if valid-comment-given comment nil)))
+ (progn
+ (error "Error: the function referenced by \
+`eudc-inline-expansion-format' is expected to return a list.")
+ nil))))
+
+ ;; fallback behaviour (nil function, or non-matching type)
+ (t
+ (let ((fname (cdr (assq (nth 0 query-attrs) res)))
+ (lname (cdr (assq (nth 1 query-attrs) res)))
+ (addr (cdr (assq (nth 2 query-attrs) res))))
+ (eudc-rfc5322-make-address addr fname lname)))))
+
+;;;###autoload
+(defun eudc-query-with-words (query-words &optional try-all-servers)
"Query the directory server, and return the matching responses.
The variable `eudc-inline-query-format' controls how to associate the
individual QUERY-WORDS with directory attribute names.
After querying the server for the given string, the expansion
specified by `eudc-inline-expansion-format' is applied to the
-matches before returning them.inserted in the buffer at point.
+matches before returning them.
Multiple servers can be tried with the same query until one finds a match,
-see `eudc-inline-expansion-servers'."
+see `eudc-inline-expansion-servers'. When TRY-ALL-SERVERS is non-nil,
+keep collecting results from subsequent servers after the first match."
(cond
((eq eudc-inline-expansion-servers 'current-server)
(or eudc-server
@@ -812,6 +960,7 @@ see `eudc-inline-expansion-servers'."
(error "Wrong value for `eudc-inline-expansion-servers': %S"
eudc-inline-expansion-servers)))
(let* (query-formats
+ response-strings
(eudc-former-server eudc-server)
(eudc-former-protocol eudc-protocol)
;; Prepare the list of servers to query
@@ -823,7 +972,7 @@ see `eudc-inline-expansion-servers'."
(if eudc-server
(cons (cons eudc-server eudc-protocol)
(delete (cons eudc-server eudc-protocol)
- (copy-sequence eudc-server-hotlist)))
+ (copy-sequence eudc-server-hotlist)))
eudc-server-hotlist))
((eq eudc-inline-expansion-servers 'current-server)
(list (cons eudc-server eudc-protocol))))))
@@ -833,46 +982,46 @@ see `eudc-inline-expansion-servers'."
(setcdr (nthcdr (1- eudc-max-servers-to-query) servers) nil))
(unwind-protect
- (let ((response
- (catch 'found
- ;; Loop on the servers
- (dolist (server servers)
- (eudc-set-server (car server) (cdr server) t)
-
- ;; Determine which formats apply in the query-format list
- (setq query-formats
- (or
- (eudc-extract-n-word-formats eudc-inline-query-format
- (length query-words))
- (if (null eudc-protocol-has-default-query-attributes)
- '(name))))
-
- ;; Loop on query-formats
- (while query-formats
- (let ((response
- (eudc-query
- (eudc-format-query query-words (car query-formats))
- (eudc-translate-attribute-list
- (cdr eudc-inline-expansion-format)))))
- (if response
- (throw 'found response)))
- (setq query-formats (cdr query-formats))))
- ;; No more servers to try... no match found
- nil))
- (response-strings '()))
-
- ;; Process response through eudc-inline-expansion-format
- (dolist (r response)
- (let ((response-string
- (apply #'format
- (car eudc-inline-expansion-format)
- (mapcar (lambda (field)
- (or (cdr (assq field r))
- ""))
- (eudc-translate-attribute-list
- (cdr eudc-inline-expansion-format))))))
- (if (> (length response-string) 0)
- (push response-string response-strings))))
+ (cl-flet
+ ((run-query
+ (query-formats)
+ (let* ((query-attrs (eudc-translate-attribute-list
+ (if (consp eudc-inline-expansion-format)
+ (cdr eudc-inline-expansion-format)
+ '(firstname name email))))
+ (response
+ (eudc-query
+ (eudc-format-query query-words (car query-formats))
+ query-attrs)))
+ (when response
+ ;; Format response.
+ (dolist (r response)
+ (let ((response-string
+ (eudc-format-inline-expansion-result r query-attrs)))
+ (if response-string
+ (cl-pushnew response-string response-strings
+ :test #'equal))))
+ (when (not try-all-servers)
+ (throw 'found nil))))))
+ (catch 'found
+ ;; Loop on the servers.
+ (dolist (server servers)
+ (eudc-set-server (car server) (cdr server) t)
+
+ ;; Determine which formats apply in the query-format list.
+ (setq query-formats
+ (or
+ (eudc-extract-n-word-formats eudc-inline-query-format
+ (length query-words))
+ (if (null eudc-protocol-has-default-query-attributes)
+ '(name))))
+
+ ;; Loop on query-formats.
+ (while query-formats
+ (run-query query-formats)
+ (setq query-formats (cdr query-formats))))
+ ;; No more servers to try... no match found.
+ nil)
response-strings)
(or (and (equal eudc-server eudc-former-server)
(equal eudc-protocol eudc-former-protocol))
@@ -894,7 +1043,10 @@ queries the server for the existing fields and displays a corresponding form."
pt)
(switch-to-buffer buffer)
(let ((inhibit-read-only t))
+ (remove-hook 'after-change-functions 'widget-after-change t)
+ (delete-all-overlays)
(erase-buffer)
+ (add-hook 'after-change-functions 'widget-after-change nil t)
(kill-all-local-variables)
(make-local-variable 'eudc-form-widget-list)
(widget-insert "Directory Query Form\n")
@@ -1052,6 +1204,8 @@ queries the server for the existing fields and displays a corresponding form."
`(["---" nil nil]
["Query with Form" eudc-query-form
:help "Display a form to query the directory server"]
+ ["Expand Inline Query Trying All Servers" eudc-expand-try-all
+ :help "Query all directory servers and expand the query string before point"]
["Expand Inline Query" eudc-expand-inline
:help "Query the directory server, and expand the query string before point"]
["Insert Record into BBDB" eudc-insert-record-at-point-into-bbdb
@@ -1086,6 +1240,7 @@ queries the server for the existing fields and displays a corresponding form."
:help "Set the directory server to SERVER using PROTOCOL"]))
(defun eudc-menu ()
+ "Return easy menu for EUDC."
(let (command)
(append '("Directory Servers")
(list
@@ -1117,6 +1272,7 @@ queries the server for the existing fields and displays a corresponding form."
eudc-tail-menu)))
(defun eudc-install-menu ()
+ "Install EUDC menu."
(define-key
global-map
[menu-bar tools directory-search]
diff --git a/lisp/net/eudcb-bbdb.el b/lisp/net/eudcb-bbdb.el
index 60a3adbc34f..e71dc238d08 100644
--- a/lisp/net/eudcb-bbdb.el
+++ b/lisp/net/eudcb-bbdb.el
@@ -233,7 +233,7 @@ RETURN-ATTRS is a list of attributes to return, defaulting to
(setq bbdb-attrs (append bbdb-attrs (list (car query-attrs))))
(if (car query-attrs)
;; BEWARE: `bbdb-search' is a macro!
- (setq records (eval `(bbdb-search records ,@bbdb-attrs) t)))
+ (setq records (eval `(bbdb-search (quote ,records) ,@bbdb-attrs) t)))
(setq query-attrs (cdr query-attrs)))
(mapc (lambda (record)
(setq filtered (eudc-filter-duplicate-attributes record))
diff --git a/lisp/net/eudcb-ldap.el b/lisp/net/eudcb-ldap.el
index 365dace961a..1201c84f2d3 100644
--- a/lisp/net/eudcb-ldap.el
+++ b/lisp/net/eudcb-ldap.el
@@ -151,16 +151,20 @@ attribute names are returned. Default to `person'."
(interactive)
(or eudc-server
(call-interactively 'eudc-set-server))
- (let ((ldap-host-parameters-alist
- (list (cons eudc-server
- '(scope subtree sizelimit 1)))))
- (mapcar #'eudc-ldap-cleanup-record-filtering-addresses
- (ldap-search
- (eudc-ldap-format-query-as-rfc1558
- (list (cons "objectclass"
- (or objectclass
- "person"))))
- eudc-server nil t))))
+ (let ((plist (copy-sequence
+ (alist-get eudc-server ldap-host-parameters-alist
+ nil nil #'equal))))
+ (plist-put plist 'scope 'subtree)
+ (plist-put plist 'sizelimit '1)
+ (let ((ldap-host-parameters-alist
+ (list (cons eudc-server plist))))
+ (mapcar #'eudc-ldap-cleanup-record-filtering-addresses
+ (ldap-search
+ (eudc-ldap-format-query-as-rfc1558
+ (list (cons 'objectclass
+ (or objectclass
+ "person"))))
+ eudc-server nil t)))))
(defun eudc-ldap-escape-query-special-chars (string)
"Value is STRING with characters forbidden in LDAP queries escaped."
@@ -178,12 +182,17 @@ attribute names are returned. Default to `person'."
(defun eudc-ldap-format-query-as-rfc1558 (query)
"Format the EUDC QUERY list as a RFC1558 LDAP search filter."
- (let ((formatter (lambda (item &optional wildcard)
- (format "(%s=%s)"
- (car item)
- (concat
- (eudc-ldap-escape-query-special-chars
- (cdr item)) (if wildcard "*" ""))))))
+ (let ((formatter
+ (lambda (item &optional wildcard)
+ (format "(%s=%s)"
+ (car item)
+ (concat
+ (eudc-ldap-escape-query-special-chars
+ (cdr item))
+ (if (and wildcard
+ (not (memq (car item)
+ eudc-ldap-no-wildcard-attributes)))
+ "*" ""))))))
(format "(&%s)"
(concat
(mapconcat formatter (butlast query) "")
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index eaa5c119385..4dbd5de2ef7 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -32,6 +32,7 @@
(require 'thingatpt)
(require 'url)
(require 'url-queue)
+(require 'url-file)
(require 'xdg)
(eval-when-compile (require 'subr-x))
@@ -191,7 +192,7 @@ determine the renaming scheme, as follows:
user-defined function:
(defun my-eww-rename-buffer ()
- (when (eq major-mode 'eww-mode)
+ (when (eq major-mode \\='eww-mode)
(when-let ((string (or (plist-get eww-data :title)
(plist-get eww-data :url))))
(format \"*%s*\" string))))
@@ -310,7 +311,7 @@ parameter, and should return the (possibly) transformed URL."
(defvar eww-accept-content-types
"text/html, text/plain, text/sgml, text/css, application/xhtml+xml, */*;q=0.01"
- "Value used for the HTTP 'Accept' header.")
+ "Value used for the HTTP \"Accept\" header.")
(defvar-keymap eww-link-keymap
:parent shr-map
@@ -362,7 +363,9 @@ new buffer instead of reusing the default EWW buffer.
If BUFFER, the data to be rendered is in that buffer. In that
case, this function doesn't actually fetch URL. BUFFER will be
-killed after rendering."
+killed after rendering.
+
+For more information, see Info node `(eww) Top'."
(interactive
(let ((uris (eww-suggested-uris)))
(list (read-string (format-prompt "Enter URL or keywords"
@@ -487,22 +490,21 @@ killed after rendering."
(defun eww-open-file (file)
"Render FILE using EWW."
(interactive "fFile: ")
- (eww (concat "file://"
- (and (memq system-type '(windows-nt ms-dos))
- "/")
- (expand-file-name file))
- nil
- ;; The file name may be a non-local Tramp file. The URL
- ;; library doesn't understand these file names, so use the
- ;; normal Emacs machinery to load the file.
- (with-current-buffer (generate-new-buffer " *eww file*")
- (set-buffer-multibyte nil)
- (insert "Content-type: " (or (mailcap-extension-to-mime
- (url-file-extension file))
- "application/octet-stream")
- "\n\n")
- (insert-file-contents file)
- (current-buffer))))
+ (let ((url-allow-non-local-files t))
+ (eww (concat "file://"
+ (and (memq system-type '(windows-nt ms-dos))
+ "/")
+ (expand-file-name file)))))
+
+(defun eww--file-buffer (file)
+ (with-current-buffer (generate-new-buffer " *eww file*")
+ (set-buffer-multibyte nil)
+ (insert "Content-type: " (or (mailcap-extension-to-mime
+ (url-file-extension file))
+ "application/octet-stream")
+ "\n\n")
+ (insert-file-contents file)
+ (current-buffer)))
;;;###autoload
(defun eww-search-words ()
@@ -833,7 +835,7 @@ The renaming scheme is performed in accordance with
(when url
(setq url (propertize url 'face 'variable-pitch))
(let* ((parsed (url-generic-parse-url url))
- (host-length (shr-string-pixel-width
+ (host-length (string-pixel-width
(propertize
(format "%s://%s" (url-type parsed)
(url-host parsed))
@@ -842,17 +844,17 @@ The renaming scheme is performed in accordance with
(cond
;; The host bit is wider than the window, so nix
;; the title.
- ((> (+ host-length (shr-string-pixel-width "xxxxx")) width)
+ ((> (+ host-length (string-pixel-width "xxxxx")) width)
(setq title ""))
;; Trim the title.
- ((> (+ (shr-string-pixel-width (concat title "xx"))
+ ((> (+ (string-pixel-width (concat title "xx"))
host-length)
width)
(setq title
(concat
(eww--limit-string-pixelwise
title (- width host-length
- (shr-string-pixel-width
+ (string-pixel-width
(propertize "...: " 'face
'variable-pitch))))
(propertize "..." 'face 'variable-pitch)))))))
@@ -932,9 +934,9 @@ The renaming scheme is performed in accordance with
(defun eww-links-at-point ()
"Return list of URIs, if any, linked at point."
- (remq nil
- (list (get-text-property (point) 'shr-url)
- (get-text-property (point) 'image-url))))
+ (seq-filter #'stringp
+ (list (get-text-property (point) 'shr-url)
+ (get-text-property (point) 'image-url))))
(defun eww-view-source ()
"View the HTML source code of the current page."
@@ -1204,7 +1206,10 @@ instead of `browse-url-new-window-flag'."
(format "*eww-%s*" (url-host (url-generic-parse-url
(eww--dwim-expand-url url))))))
(eww-mode))
- (eww url))
+ (let ((url-allow-non-local-files t))
+ (eww url)))
+
+(function-put 'eww-browse-url 'browse-url-browser-kind 'internal)
(defun eww-back-url ()
"Go to the previously displayed page."
@@ -1291,9 +1296,16 @@ just re-display the HTML already fetched."
(error "No current HTML data")
(eww-display-html 'utf-8 url (plist-get eww-data :dom)
(point) (current-buffer)))
- (let ((url-mime-accept-string eww-accept-content-types))
- (eww-retrieve url #'eww-render
- (list url (point) (current-buffer) encode))))))
+ (let ((parsed (url-generic-parse-url url)))
+ (if (equal (url-type parsed) "file")
+ ;; Use Tramp instead of url.el for files (since url.el
+ ;; doesn't work well with Tramp files).
+ (let ((eww-buffer (current-buffer)))
+ (with-current-buffer (eww--file-buffer (url-filename parsed))
+ (eww-render nil url nil eww-buffer)))
+ (let ((url-mime-accept-string eww-accept-content-types))
+ (eww-retrieve url #'eww-render
+ (list url (point) (current-buffer) encode))))))))
;; Form support.
@@ -1847,7 +1859,7 @@ The browser to used is specified by the
(replace-regexp-in-string ".utm_.*" "" url))
(defun eww--transform-url (url)
- "Appy `eww-url-transformers'."
+ "Apply `eww-url-transformers'."
(when url
(dolist (func eww-url-transformers)
(setq url (funcall func url)))
@@ -2045,7 +2057,9 @@ If CHARSET is nil then use UTF-8."
(defun eww-write-bookmarks ()
(with-temp-file (expand-file-name "eww-bookmarks" eww-bookmarks-directory)
(insert ";; Auto-generated file; don't edit -*- mode: lisp-data -*-\n")
- (pp eww-bookmarks (current-buffer))))
+ (let ((print-length nil)
+ (print-level nil))
+ (pp eww-bookmarks (current-buffer)))))
(defun eww-read-bookmarks (&optional error-out)
"Read bookmarks from `eww-bookmarks'.
@@ -2499,6 +2513,8 @@ Otherwise, the restored buffer will contain a prompt to do so by using
"Default bookmark handler for EWW buffers."
(eww (bookmark-prop-get bookmark 'location)))
+(put 'eww-bookmark-jump 'bookmark-handler-type "EWW")
+
(provide 'eww)
;;; eww.el ends here
diff --git a/lisp/net/ldap.el b/lisp/net/ldap.el
index ce6c270e0bc..0f2943cbb03 100644
--- a/lisp/net/ldap.el
+++ b/lisp/net/ldap.el
@@ -54,7 +54,7 @@ a separator."
Initialized from the LDAP library at build time.
Default value is 389."
:type '(choice (const :tag "Use library default" nil)
- (integer :tag "Port number")))
+ (natnum :tag "Port number")))
(defcustom ldap-default-base nil
"Default base for LDAP searches.
@@ -148,7 +148,7 @@ Valid properties include:
"The name of the ldapsearch command line program."
:type '(string :tag "`ldapsearch' Program"))
-(defcustom ldap-ldapsearch-args '("-LL" "-tt")
+(defcustom ldap-ldapsearch-args '("-LLL" "-tt")
"A list of additional arguments to pass to `ldapsearch'."
:type '(repeat :tag "`ldapsearch' Arguments"
(string :tag "Argument")))
@@ -663,7 +663,7 @@ an alist of attribute/value pairs."
(while (not (memq (process-status proc) '(exit signal)))
(sit-for 0.1))
(let ((status (process-exit-status proc)))
- (when (not (eq status 0))
+ (when (not (memql status '(0 4))) ; 4 = Size limit exceeded
;; Handle invalid credentials exit status specially
;; for ldap-password-read.
(if (eq status 49)
@@ -682,7 +682,7 @@ an alist of attribute/value pairs."
(while (re-search-forward (concat "[\t\n\f]+ \\|"
ldap-ldapsearch-password-prompt-regexp)
nil t)
- (replace-match "" nil nil))
+ (replace-match ""))
(goto-char (point-min))
(if (looking-at "usage")
@@ -691,7 +691,6 @@ an alist of attribute/value pairs."
;; Skip error message when retrieving attribute list
(if (looking-at "Size limit exceeded")
(forward-line 1))
- (if (looking-at "version:") (forward-line 1)) ;bug#12724.
(while (progn
(skip-chars-forward " \t\n")
(not (eobp)))
@@ -699,7 +698,7 @@ an alist of attribute/value pairs."
(forward-line 1)
(while (looking-at "^\\([A-Za-z][-A-Za-z0-9]*\
\\|[0-9]+\\(?:\\.[0-9]+\\)*\\)\\(;[-A-Za-z0-9]+\\)*[=:\t ]+\
-\\(<[\t ]*file://\\)\\(.*\\)$")
+\\(<[\t ]*file://\\)?\\(.*\\)$")
(setq name (match-string 1)
value (match-string 4))
;; Need to handle file:///D:/... as generated by OpenLDAP
@@ -724,7 +723,6 @@ an alist of attribute/value pairs."
(record
(push (nreverse record) result)))
(setq record nil)
- (skip-chars-forward " \t\n")
(message "Parsing results... %d" numres)
(setq numres (1+ numres)))
(message "Parsing results... done")
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index bf3c8edd1e3..8ba7f1bec3d 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
@@ -439,9 +440,10 @@ MAILCAPS if set; otherwise (on Unix) use the path from RFC 1524, plus
("/usr/local/etc/mailcap" system)))))
(when (stringp path)
(setq path (mapcar #'list (split-string path path-separator t))))
- (when (seq-some (lambda (f)
- (file-has-changed-p (car f) 'mail-parse-mailcaps))
- path)
+ (when (or (null mailcap--computed-mime-data)
+ (seq-some (lambda (f)
+ (file-has-changed-p (car f) 'mail-parse-mailcaps))
+ path))
;; Clear out all old data.
(setq mailcap--computed-mime-data nil)
;; Add the Emacs-distributed defaults (which will be used as
@@ -1096,11 +1098,12 @@ For instance, `image/png' will result in `png'."
(mailcap-parse-mimetypes)
(let* ((all-mime-type
;; All unique MIME types from file extensions
- (delete-dups
- (mapcar (lambda (file)
- (mailcap-extension-to-mime
- (file-name-extension file t)))
- files)))
+ (delq nil
+ (delete-dups
+ (mapcar (lambda (file)
+ (mailcap-extension-to-mime
+ (file-name-extension file t)))
+ files))))
(all-mime-info
;; All MIME info lists
(delete-dups
@@ -1174,34 +1177,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)
diff --git a/lisp/net/mairix.el b/lisp/net/mairix.el
index d84763b1626..0b99d2a0b7c 100644
--- a/lisp/net/mairix.el
+++ b/lisp/net/mairix.el
@@ -743,21 +743,20 @@ VALUES may contain values for editable fields from current article."
;;;; Major mode for editing/deleting/saving searches
-(defvar mairix-searches-mode-map
- (let ((map (make-keymap)))
- (define-key map [(return)] 'mairix-select-search)
- (define-key map [(down)] 'mairix-next-search)
- (define-key map [(up)] 'mairix-previous-search)
- (define-key map [(right)] 'mairix-next-search)
- (define-key map [(left)] 'mairix-previous-search)
- (define-key map "\C-p" 'mairix-previous-search)
- (define-key map "\C-n" 'mairix-next-search)
- (define-key map [(q)] 'mairix-select-quit)
- (define-key map [(e)] 'mairix-select-edit)
- (define-key map [(d)] 'mairix-select-delete)
- (define-key map [(s)] 'mairix-select-save)
- map)
- "`mairix-searches-mode' keymap.")
+(defvar-keymap mairix-searches-mode-map
+ :doc "`mairix-searches-mode' keymap."
+ :full t
+ "<return>" #'mairix-select-search
+ "<down>" #'mairix-next-search
+ "<up>" #'mairix-previous-search
+ "<right>" #'mairix-next-search
+ "<left>" #'mairix-previous-search
+ "C-p" #'mairix-previous-search
+ "C-n" #'mairix-next-search
+ "q" #'mairix-select-quit
+ "e" #'mairix-select-edit
+ "d" #'mairix-select-delete
+ "s" #'mairix-select-save)
(defvar mairix-searches-mode-font-lock-keywords
'(("^\\([0-9]+\\)"
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index 411b6ed4132..c7ff175e08e 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -23,11 +23,10 @@
;;; Commentary:
-;;
;; There are three main areas of functionality:
;;
;; * Wrap common network utility programs (ping, traceroute, netstat,
-;; nslookup, arp, route). Note that these wrappers are of the diagnostic
+;; nslookup, arp, route). Note that these wrappers are of the diagnostic
;; functions of these programs only.
;;
;; * Implement some very basic protocols in Emacs Lisp (finger and whois)
@@ -39,7 +38,7 @@
;;; Code:
;; On some systems, programs like ifconfig are not in normal user
-;; path, but rather in /sbin, /usr/sbin, etc (but non-root users can
+;; path, but rather in /sbin, /usr/sbin, etc. (but non-root users can
;; still use them for queries). Actually the trend these
;; days is for /sbin to be a symlink to /usr/sbin, but we still need to
;; search both for older systems.
@@ -176,15 +175,6 @@ This variable is only used if the variable
`comint-use-prompt-regexp' is non-nil."
:type 'regexp)
-(defcustom dig-program "dig"
- "Program to query DNS information."
- :type 'string)
-
-(defcustom dig-program-options nil
- "Options for the dig program."
- :type '(repeat string)
- :version "26.1")
-
(defcustom ftp-program "ftp"
"Program to run to do FTP transfers."
:type 'string)
@@ -280,6 +270,7 @@ This variable is only used if the variable
(define-derived-mode net-utils-mode special-mode "NetworkUtil"
"Major mode for interacting with an external network utility."
+ :interactive nil
(setq-local font-lock-defaults
'((net-utils-font-lock-keywords)))
(setq-local revert-buffer-function #'net-utils--revert-function))
@@ -288,31 +279,6 @@ This variable is only used if the variable
;; Utility functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Simplified versions of some at-point functions from ffap.el.
-;; It's not worth loading all of ffap just for these.
-(defun net-utils-machine-at-point ()
- (let ((pt (point)))
- (buffer-substring-no-properties
- (save-excursion
- (skip-chars-backward "-a-zA-Z0-9.")
- (point))
- (save-excursion
- (skip-chars-forward "-a-zA-Z0-9.")
- (skip-chars-backward "." pt)
- (point)))))
-
-(defun net-utils-url-at-point ()
- (let ((pt (point)))
- (buffer-substring-no-properties
- (save-excursion
- (skip-chars-backward "--:=&?$+@-Z_a-z~#,%")
- (skip-chars-forward "^A-Za-z0-9" pt)
- (point))
- (save-excursion
- (skip-chars-forward "--:=&?$+@-Z_a-z~#,%")
- (skip-chars-backward ":;.,!?" pt)
- (point)))))
-
(defun net-utils-remove-ctrl-m-filter (process output-string)
"Remove trailing control Ms."
(with-current-buffer (process-buffer process)
@@ -464,7 +430,8 @@ This variable is only used if the variable
If your system's ping continues until interrupted, you can try setting
`ping-program-options'."
(interactive
- (list (read-from-minibuffer "Ping host: " (net-utils-machine-at-point))))
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Ping host" default) nil nil default))))
(let ((options
(if ping-program-options
(append ping-program-options (list host))
@@ -497,7 +464,8 @@ See also: `nslookup-host-ipv4', `nslookup-host-ipv6' for
non-interactive versions of this function more suitable for use
in Lisp code."
(interactive
- (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Lookup host" default) nil nil default))
(if current-prefix-arg (read-from-minibuffer "Name server: "))))
(let ((options
(append nslookup-program-options (list host)
@@ -589,14 +557,12 @@ This command uses `nslookup-program' to look up DNS records."
(autoload 'comint-mode "comint" nil t)
-(defvar nslookup-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\t" #'completion-at-point)
- map))
+(defvar-keymap nslookup-mode-map
+ "TAB" #'completion-at-point)
-;; Using a derived mode gives us keymaps, hooks, etc.
(define-derived-mode nslookup-mode comint-mode "Nslookup"
"Major mode for interacting with the nslookup program."
+ :interactive nil
(setq-local font-lock-defaults
'((nslookup-font-lock-keywords)))
(setq comint-prompt-regexp nslookup-prompt-regexp)
@@ -611,7 +577,8 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument.
This command uses `dns-lookup-program' for looking up the DNS information."
(interactive
- (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Lookup host" default) nil nil default))
(if current-prefix-arg (read-from-minibuffer "Name server: "))))
(let ((options
(append dns-lookup-program-options (list host)
@@ -633,20 +600,12 @@ DNS resolution.
Interactively, prompt for NAME-SERVER if invoked with prefix argument.
This command uses `dig-program' for looking up the DNS information."
+ (declare (obsolete dig "29.1"))
(interactive
- (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point))
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Lookup host" default) nil nil default))
(if current-prefix-arg (read-from-minibuffer "Name server: "))))
- (let ((options
- (append dig-program-options (list host)
- (if name-server (list (concat "@" name-server))))))
- (net-utils-run-program
- "Dig"
- (concat "** "
- (mapconcat #'identity
- (list "Dig" host dig-program)
- " ** "))
- dig-program
- options)))
+ (dig host nil nil nil nil name-server))
(autoload 'comint-exec "comint")
(declare-function comint-watch-for-password-prompt "comint" (string))
@@ -656,9 +615,8 @@ This command uses `dig-program' for looking up the DNS information."
(defun ftp (host)
"Run `ftp-program' to connect to HOST."
(interactive
- (list
- (read-from-minibuffer
- "Ftp to Host: " (net-utils-machine-at-point))))
+ (list (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Ftp to Host" default) nil nil default))))
(let ((buf (get-buffer-create (concat "*ftp [" host "]*"))))
(set-buffer buf)
(ftp-mode)
@@ -668,14 +626,12 @@ This command uses `dig-program' for looking up the DNS information."
(list host)))
(pop-to-buffer buf)))
-(defvar ftp-mode-map
- (let ((map (make-sparse-keymap)))
- ;; Occasionally useful
- (define-key map "\t" #'completion-at-point)
- map))
+(defvar-keymap ftp-mode-map
+ "TAB" #'completion-at-point)
(define-derived-mode ftp-mode comint-mode "FTP"
"Major mode for interacting with the ftp program."
+ :interactive nil
(setq comint-prompt-regexp ftp-prompt-regexp)
(setq comint-input-autoexpand t)
;; Only add the password-prompting hook if it's not already in the
@@ -695,8 +651,8 @@ This command uses `dig-program' for looking up the DNS information."
This command uses `smbclient-program' to connect to HOST."
(interactive
(list
- (read-from-minibuffer
- "Connect to Host: " (net-utils-machine-at-point))
+ (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Connect to Host" default) nil nil default))
(read-from-minibuffer "SMB Service: ")))
(let* ((name (format "smbclient [%s\\%s]" host service))
(buf (get-buffer-create (concat "*" name "*")))
@@ -714,8 +670,8 @@ This command uses `smbclient-program' to connect to HOST."
This command uses `smbclient-program' to connect to HOST."
(interactive
(list
- (read-from-minibuffer
- "Connect to Host: " (net-utils-machine-at-point))))
+ (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Connect to Host" default) nil nil default))))
(let ((buf (get-buffer-create (format "*SMB Shares on %s*" host))))
(set-buffer buf)
(smbclient-mode)
@@ -725,6 +681,7 @@ This command uses `smbclient-program' to connect to HOST."
(define-derived-mode smbclient-mode comint-mode "smbclient"
"Major mode for interacting with the smbclient program."
+ :interactive nil
(setq comint-prompt-regexp smbclient-prompt-regexp)
(setq comint-input-autoexpand t)
;; Only add the password-prompting hook if it's not already in the
@@ -813,15 +770,15 @@ and `network-connection-service-alist', which see."
;; uses a string like "pbreton@cs.umb.edu", we won't ask for the
;; host name. If we don't see an "@", we'll prompt for the host.
(interactive
- (let* ((answer (read-from-minibuffer "Finger User: "
- (net-utils-url-at-point)))
+ (let* ((answer (let ((default (ffap-url-at-point)))
+ (read-string (format-prompt "Finger User" default) nil nil default)))
(index (string-match (regexp-quote "@") answer)))
(if index
(list (substring answer 0 index)
(substring answer (1+ index)))
(list answer
- (read-from-minibuffer "At Host: "
- (net-utils-machine-at-point))))))
+ (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "At Host" default) nil nil default))))))
(let* ((user-and-host (concat user "@" host))
(process-name (concat "Finger [" user-and-host "]"))
(regexps finger-X.500-host-regexps)
@@ -940,10 +897,9 @@ The port is deduced from `network-connection-service-alist'."
;;; General Network connection
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Using a derived mode gives us keymaps, hooks, etc.
-(define-derived-mode
- network-connection-mode comint-mode "Network-Connection"
- "Major mode for interacting with the `network-connection' program.")
+(define-derived-mode network-connection-mode comint-mode "Network-Connection"
+ "Major mode for interacting with the `network-connection' program."
+ :interactive nil)
(defun network-connection-mode-setup (host service)
(setq-local network-connection-host host)
@@ -955,7 +911,8 @@ The port is deduced from `network-connection-service-alist'."
This command uses `network-connection-service-alist', which see."
(interactive
(list
- (read-from-minibuffer "Host: " (net-utils-machine-at-point))
+ (let ((default (ffap-machine-at-point)))
+ (read-string (format-prompt "Host" default) nil nil default))
(completing-read "Service: "
(mapcar
(lambda (elt)
@@ -1008,6 +965,9 @@ This command uses `network-connection-service-alist', which see."
(and old-comint-input-ring
(setq comint-input-ring old-comint-input-ring)))))
+(define-obsolete-function-alias 'net-utils-machine-at-point #'ffap-machine-at-point "29.1")
+(define-obsolete-function-alias 'net-utils-url-at-point #'ffap-url-at-point "29.1")
+
(provide 'net-utils)
;;; net-utils.el ends here
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index a62a7bd8b7d..5ae2df769a2 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -40,7 +40,6 @@
;; Silence warnings
(defvar newsticker-groups)
-(defvar w3-mode-map)
(defvar w3m-minor-mode-map)
(defvar newsticker--retrieval-timer-list nil
@@ -1697,11 +1696,11 @@ Checks list of active processes against list of newsticker processes."
;; ======================================================================
(defun newsticker--images-dir ()
"Return directory where feed images are saved."
- (concat newsticker-dir "/images/"))
+ (expand-file-name "images/" newsticker-dir))
(defun newsticker--icons-dir ()
"Return directory where feed icons are saved."
- (concat newsticker-dir "/icons/"))
+ (expand-file-name "icons/" newsticker-dir))
(defun newsticker--image-get (feed-name filename directory url)
"Get image for FEED-NAME by returning FILENAME from DIRECTORY.
@@ -2114,7 +2113,7 @@ FEED is a symbol!"
(defun newsticker--cache-dir ()
"Return directory for saving cache data."
- (concat newsticker-dir "/feeds"))
+ (expand-file-name "feeds/" newsticker-dir))
(defun newsticker--cache-save ()
"Save cache data for all feeds."
@@ -2125,13 +2124,15 @@ FEED is a symbol!"
(defun newsticker--cache-save-feed (feed)
"Save cache data for FEED."
- (let ((dir (concat (newsticker--cache-dir) "/" (symbol-name (car feed)))))
+ (let ((dir (file-name-as-directory
+ (expand-file-name (symbol-name (car feed))
+ (newsticker--cache-dir)))))
(unless (file-directory-p dir)
(make-directory dir t))
(let ((coding-system-for-write 'utf-8))
- (with-temp-file (concat dir "/data")
+ (with-temp-file (expand-file-name "data" dir)
(insert ";; -*- coding: utf-8 -*-\n")
- (insert (prin1-to-string (cdr feed)))))))
+ (prin1 (cdr feed) (current-buffer) t)))))
(defun newsticker--cache-read ()
"Read cache data."
@@ -2141,7 +2142,9 @@ FEED is a symbol!"
(defun newsticker--cache-read-feed (feed-name)
"Read cache data for feed named FEED-NAME."
- (let ((file-name (concat (newsticker--cache-dir) "/" feed-name "/data"))
+ (let ((file-name (expand-file-name
+ "data" (expand-file-name
+ feed-name (newsticker--cache-dir))))
(coding-system-for-read 'utf-8))
(when (file-exists-p file-name)
(with-temp-buffer
@@ -2213,8 +2216,7 @@ Export subscriptions to a buffer in OPML Format."
(newsticker--opml-insert-feed (car f) 4)))
(insert " </body>\n</opml>\n")))
(pop-to-buffer "*OPML Export*")
- (when (fboundp 'sgml-mode)
- (sgml-mode)))
+ (sgml-mode))
(defun newsticker--opml-insert-elt (elt depth)
"Insert an OPML ELT with indentation level DEPTH."
@@ -2334,14 +2336,19 @@ This function just prints out the values of the FEEDNAME and title of the ITEM."
"Download the first image.
If FEEDNAME equals \"imagefeed\" download the first image URL
found in the description=contents of ITEM to the directory
-\"~/tmp/newsticker/FEEDNAME/TITLE\" where TITLE is the title of
-the item."
+`temporary-file-directory'/newsticker/FEEDNAME/TITLE where TITLE
+is the title of the item."
(when (string= feedname "imagefeed")
(let ((title (newsticker--title item))
(desc (newsticker--desc item)))
(when (string-match "<img src=\"\\(http://[^ \"]+\\)\"" desc)
(let ((url (substring desc (match-beginning 1) (match-end 1)))
- (temp-dir (concat "~/tmp/newsticker/" feedname "/" title))
+ (temp-dir (file-name-as-directory
+ (expand-file-name
+ title (expand-file-name
+ feedname (expand-file-name
+ "newsticker"
+ temporary-file-directory)))))
(org-dir default-directory))
(unless (file-directory-p temp-dir)
(make-directory temp-dir t))
@@ -2355,7 +2362,8 @@ the item."
(defun newsticker-download-enclosures (feedname item)
"In all feeds download the enclosed object of the news ITEM.
-The object is saved to the directory \"~/tmp/newsticker/FEEDNAME/TITLE\", which
+The object is saved to the directory
+`temporary-file-directory'/newsticker/FEEDNAME/TITLE, which
is created if it does not exist. TITLE is the title of the news
item. Argument FEEDNAME is ignored.
This function is suited for adding it to `newsticker-new-item-functions'."
@@ -2363,7 +2371,12 @@ This function is suited for adding it to `newsticker-new-item-functions'."
(enclosure (newsticker--enclosure item)))
(when enclosure
(let ((url (cdr (assoc 'url enclosure)))
- (temp-dir (concat "~/tmp/newsticker/" feedname "/" title))
+ (temp-dir (file-name-as-directory
+ (expand-file-name
+ title (expand-file-name
+ feedname (expand-file-name
+ "newsticker"
+ temporary-file-directory)))))
(org-dir default-directory))
(unless (file-directory-p temp-dir)
(make-directory temp-dir t))
diff --git a/lisp/net/newst-plainview.el b/lisp/net/newst-plainview.el
index df574dfa2f4..4eb6f6c695e 100644
--- a/lisp/net/newst-plainview.el
+++ b/lisp/net/newst-plainview.el
@@ -37,7 +37,6 @@
(require 'xml)
;; Silence warnings
-(defvar w3-mode-map)
(defvar w3m-minor-mode-map)
;; ======================================================================
@@ -1232,7 +1231,6 @@ item-retrieval time is added as well."
(newsticker--buffer-do-insert-text item 'desc feed-name-symbol))
(defvar w3m-fill-column)
-(defvar w3-maximum-line-length)
(defun newsticker--buffer-do-insert-text (item type feed-name-symbol)
"Actually insert contents of news item, format it, render it and all that.
@@ -1366,19 +1364,14 @@ FEED-NAME-SYMBOL tells to which feed this item belongs."
"</?[A-Za-z1-6]*\\|&#?[A-Za-z0-9]+;" pos-text-end t)
;; (message "%s" (newsticker--title item))
(let ((w3m-fill-column (if newsticker-use-full-width
- -1 fill-column))
- (w3-maximum-line-length
- (if newsticker-use-full-width nil fill-column)))
+ -1 fill-column)))
(save-excursion
(funcall newsticker-html-renderer pos-text-start
pos-text-end)))
- (cond ((eq newsticker-html-renderer 'w3m-region)
- (add-text-properties pos (point-max)
- (list 'keymap
- w3m-minor-mode-map)))
- ((eq newsticker-html-renderer 'w3-region)
- (add-text-properties pos (point-max)
- (list 'keymap w3-mode-map))))
+ (when (eq newsticker-html-renderer 'w3m-region)
+ (add-text-properties pos (point-max)
+ (list 'keymap
+ w3m-minor-mode-map)))
(setq is-rendered-HTML t)))
(error
(message "Error: HTML rendering failed: %s, %s"
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el
index 7e00ac93e75..4a7f0b8e3ee 100644
--- a/lisp/net/newst-reader.el
+++ b/lisp/net/newst-reader.el
@@ -112,18 +112,18 @@ window is used when filling. See also `newsticker-justification'."
"Function for rendering HTML contents.
If non-nil, newsticker.el will call this function whenever it
finds HTML-like tags in item descriptions.
-Possible functions include `shr-render-region', `w3m-region', `w3-region', and
+Possible functions include `shr-render-region', `w3m-region', and
`newsticker-htmlr-render'.
-Newsticker automatically loads the respective package w3m, w3, or
+Newsticker automatically loads the respective package w3m, or
htmlr if this option is set."
:type '(choice :tag "Function"
(const :tag "None" nil)
(const :tag "SHR" shr-render-region)
- (const :tag "w3" w3-region)
(const :tag "w3m" w3m-region)
(const :tag "htmlr" newsticker-htmlr-render))
:set #'newsticker--set-customvar-formatting
- :group 'newsticker-reader)
+ :group 'newsticker-reader
+ :version "29.1")
(defcustom newsticker-date-format
"(%A, %H:%M)"
@@ -315,8 +315,6 @@ Return the image."
(if newsticker-html-renderer
(cond ((eq newsticker-html-renderer 'w3m-region)
(require 'w3m))
- ((eq newsticker-html-renderer 'w3-region)
- (require 'w3-auto))
((eq newsticker-html-renderer 'newsticker-htmlr-render)
(require 'htmlr))))
(funcall newsticker-frontend))
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 80d9fd1cef2..637f53e6550 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -106,13 +106,13 @@ applies to newsticker only."
(defcustom newsticker-treeview-use-feed-name-from-url-list-in-treeview
t
- "Use the feed names from 'newsticker-url-list' for display in treeview."
+ "Use the feed names from `newsticker-url-list' for display in treeview."
:version "28.1"
:type 'boolean)
(defcustom newsticker-treeview-use-feed-name-from-url-list-in-itemview
t
- "Use feed names from 'newsticker-url-list' in itemview."
+ "Use feed names from `newsticker-url-list' in itemview."
:version "28.1"
:type 'boolean)
@@ -252,7 +252,6 @@ their id stays constant."
(declare-function w3m-toggle-inline-images "ext:w3m" (&optional force no-cache))
(defvar w3m-fill-column)
-(defvar w3-maximum-line-length)
(defun newsticker--treeview-render-text (start end)
"Render text between markers START and END."
@@ -272,17 +271,13 @@ their id stays constant."
"</?[A-Za-z1-6]*\\|&#?[A-Za-z0-9]+;" end t)
;; (message "%s" (newsticker--title item))
(let ((w3m-fill-column (if newsticker-use-full-width
- -1 fill-column))
- (w3-maximum-line-length
- (if newsticker-use-full-width nil fill-column)))
+ -1 fill-column)))
(select-window (newsticker--treeview-item-window))
(save-excursion
(funcall newsticker-html-renderer start end)))
;;(cond ((eq newsticker-html-renderer 'w3m-region)
;; (add-text-properties start end (list 'keymap
;; w3m-minor-mode-map)))
- ;;((eq newsticker-html-renderer 'w3-region)
- ;;(add-text-properties start end (list 'keymap w3-mode-map))))
(if (eq newsticker-html-renderer 'w3m-region)
(w3m-toggle-inline-images t))
t)))
@@ -608,14 +603,10 @@ If CLEAR-BUFFER is non-nil the list buffer is completely erased."
(newsticker--treeview-list-update-faces)
(goto-char (point-min))))
-(defvar newsticker-treeview-list-sort-button-map
- (let ((map (make-sparse-keymap)))
- (define-key map [header-line mouse-1]
- #'newsticker--treeview-list-sort-by-column)
- (define-key map [header-line mouse-2]
- #'newsticker--treeview-list-sort-by-column)
- map)
- "Local keymap for newsticker treeview list window sort buttons.")
+(defvar-keymap newsticker-treeview-list-sort-button-map
+ :doc "Local keymap for newsticker treeview list window sort buttons."
+ "<header-line> <mouse-1>" #'newsticker--treeview-list-sort-by-column
+ "<header-line> <mouse-2>" #'newsticker--treeview-list-sort-by-column)
(defun newsticker--treeview-list-sort-by-column (&optional event)
"Sort the newsticker list window buffer by the column clicked on.
@@ -1257,20 +1248,20 @@ Note: does not update the layout."
"Save treeview group settings."
(interactive)
(let ((coding-system-for-write 'utf-8)
- (buf (find-file-noselect (concat newsticker-dir "/groups"))))
+ (buf (find-file-noselect (expand-file-name "groups" newsticker-dir))))
(when buf
(with-current-buffer buf
(setq buffer-undo-list t)
(erase-buffer)
(insert ";; -*- coding: utf-8 -*-\n")
- (insert (prin1-to-string newsticker-groups))
+ (prin1 newsticker-groups (current-buffer) t)
(save-buffer)
(kill-buffer)))))
(defun newsticker--treeview-load ()
"Load treeview settings."
(let* ((coding-system-for-read 'utf-8)
- (filename (concat newsticker-dir "/groups"))
+ (filename (expand-file-name "groups" newsticker-dir))
(buf (and (file-exists-p filename)
(find-file-noselect filename))))
(when buf
@@ -1283,7 +1274,6 @@ Note: does not update the layout."
(setq newsticker-groups nil)))
(kill-buffer buf))))
-
(defun newsticker-treeview-scroll-item ()
"Scroll current item."
(interactive)
@@ -2013,41 +2003,39 @@ Return t if groups have changed, nil otherwise."
menu)
"Map for newsticker item menu.")
-(defvar newsticker-treeview-mode-map
- (let ((map (make-sparse-keymap 'newsticker-treeview-mode-map)))
- (define-key map " " #'newsticker-treeview-next-page)
- (define-key map "a" #'newsticker-add-url)
- (define-key map "b" #'newsticker-treeview-browse-url-item)
- (define-key map "c" #'newsticker-treeview-customize-current-feed)
- (define-key map "F" #'newsticker-treeview-prev-feed)
- (define-key map "f" #'newsticker-treeview-next-feed)
- (define-key map "g" #'newsticker-treeview-get-news)
- (define-key map "G" #'newsticker-get-all-news)
- (define-key map "i" #'newsticker-treeview-toggle-item-immortal)
- (define-key map "j" #'newsticker-treeview-jump)
- (define-key map "n" #'newsticker-treeview-next-item)
- (define-key map "N" #'newsticker-treeview-next-new-or-immortal-item)
- (define-key map "O" #'newsticker-treeview-mark-list-items-old)
- (define-key map "o" #'newsticker-treeview-mark-item-old)
- (define-key map "p" #'newsticker-treeview-prev-item)
- (define-key map "P" #'newsticker-treeview-prev-new-or-immortal-item)
- (define-key map "q" #'newsticker-treeview-quit)
- (define-key map "S" #'newsticker-treeview-save-item)
- (define-key map "s" #'newsticker-treeview-save)
- (define-key map "u" #'newsticker-treeview-update)
- (define-key map "v" #'newsticker-treeview-browse-url)
- ;;(define-key map "\n" #'newsticker-treeview-scroll-item)
- ;;(define-key map "\C-m" #'newsticker-treeview-scroll-item)
- (define-key map "\M-m" #'newsticker-group-move-feed)
- (define-key map "\M-a" #'newsticker-group-add-group)
- (define-key map "\M-d" #'newsticker-group-delete-group)
- (define-key map "\M-r" #'newsticker-group-rename-group)
- (define-key map [M-down] #'newsticker-group-shift-feed-down)
- (define-key map [M-up] #'newsticker-group-shift-feed-up)
- (define-key map [M-S-down] #'newsticker-group-shift-group-down)
- (define-key map [M-S-up] #'newsticker-group-shift-group-up)
- map)
- "Mode map for newsticker treeview.")
+(defvar-keymap newsticker-treeview-mode-map
+ :doc "Mode map for newsticker treeview."
+ "SPC" #'newsticker-treeview-next-page
+ "a" #'newsticker-add-url
+ "b" #'newsticker-treeview-browse-url-item
+ "c" #'newsticker-treeview-customize-current-feed
+ "F" #'newsticker-treeview-prev-feed
+ "f" #'newsticker-treeview-next-feed
+ "g" #'newsticker-treeview-get-news
+ "G" #'newsticker-get-all-news
+ "i" #'newsticker-treeview-toggle-item-immortal
+ "j" #'newsticker-treeview-jump
+ "n" #'newsticker-treeview-next-item
+ "N" #'newsticker-treeview-next-new-or-immortal-item
+ "O" #'newsticker-treeview-mark-list-items-old
+ "o" #'newsticker-treeview-mark-item-old
+ "p" #'newsticker-treeview-prev-item
+ "P" #'newsticker-treeview-prev-new-or-immortal-item
+ "q" #'newsticker-treeview-quit
+ "S" #'newsticker-treeview-save-item
+ "s" #'newsticker-treeview-save
+ "u" #'newsticker-treeview-update
+ "v" #'newsticker-treeview-browse-url
+ ;;"C-j" #'newsticker-treeview-scroll-item
+ ;;"RET" #'newsticker-treeview-scroll-item
+ "M-m" #'newsticker-group-move-feed
+ "M-a" #'newsticker-group-add-group
+ "M-d" #'newsticker-group-delete-group
+ "M-r" #'newsticker-group-rename-group
+ "M-<down>" #'newsticker-group-shift-feed-down
+ "M-<up>" #'newsticker-group-shift-feed-up
+ "M-S-<down>" #'newsticker-group-shift-group-down
+ "M-S-<up>" #'newsticker-group-shift-group-up)
(define-derived-mode newsticker-treeview-mode fundamental-mode "Newsticker TV"
"Major mode for Newsticker Treeview.
diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el
index 0f6dfb6ad46..de225d76dcc 100644
--- a/lisp/net/pop3.el
+++ b/lisp/net/pop3.el
@@ -59,7 +59,7 @@
(defcustom pop3-port 110
"POP3 port."
:version "22.1" ;; Oort Gnus
- :type 'number
+ :type 'natnum
:group 'pop3)
(defcustom pop3-password-required t
@@ -88,7 +88,7 @@ valid value is `apop'."
The lower the number, the more latency-sensitive the fetching
will be. If your pop3 server doesn't support streaming at all,
set this to 1."
- :type 'number
+ :type 'natnum
:version "24.1"
:group 'pop3)
diff --git a/lisp/net/quickurl.el b/lisp/net/quickurl.el
index 598a7da0712..61cae43a88a 100644
--- a/lisp/net/quickurl.el
+++ b/lisp/net/quickurl.el
@@ -163,19 +163,17 @@ in your init file (after loading/requiring quickurl).")
(defvar quickurl-urls nil
"URL alist for use with `quickurl' and `quickurl-ask'.")
-(defvar quickurl-list-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "a" #'quickurl-list-add-url)
- (define-key map [(control m)] #'quickurl-list-insert-url)
- (define-key map "u" #'quickurl-list-insert-naked-url)
- (define-key map " " #'quickurl-list-insert-with-lookup)
- (define-key map "l" #'quickurl-list-insert-lookup)
- (define-key map "d" #'quickurl-list-insert-with-desc)
- (define-key map [(control g)] #'quickurl-list-quit)
- (define-key map "q" #'quickurl-list-quit)
- (define-key map [mouse-2] #'quickurl-list-mouse-select)
- map)
- "Local keymap for a `quickurl-list-mode' buffer.")
+(defvar-keymap quickurl-list-mode-map
+ :doc "Local keymap for a `quickurl-list-mode' buffer."
+ "a" #'quickurl-list-add-url
+ "RET" #'quickurl-list-insert-url
+ "u" #'quickurl-list-insert-naked-url
+ "SPC" #'quickurl-list-insert-with-lookup
+ "l" #'quickurl-list-insert-lookup
+ "d" #'quickurl-list-insert-with-desc
+ "C-g" #'quickurl-list-quit
+ "q" #'quickurl-list-quit
+ "<mouse-2>" #'quickurl-list-mouse-select)
(defvar quickurl-list-buffer-name "*quickurl-list*"
"Name for the URL listing buffer.")
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 9a1153b3c6a..54d7861f445 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -130,7 +130,7 @@ be displayed instead."
(defcustom rcirc-default-port 6667
"The default port to connect to."
- :type 'integer)
+ :type 'natnum)
(defcustom rcirc-default-nick (user-login-name)
"Your nick."
@@ -267,6 +267,7 @@ The ARGUMENTS for each METHOD symbol are:
Examples:
((\"Libera.Chat\" nickserv \"bob\" \"p455w0rd\")
(\"Libera.Chat\" chanserv \"bob\" \"#bobland\" \"passwd99\")
+ (\"Libera.Chat\" certfp \"/path/to/key\" \"/path/to/cert\")
(\"bitlbee\" bitlbee \"robert\" \"sekrit\")
(\"dal.net\" nickserv \"bob\" \"sekrit\" \"NickServ@services.dal.net\")
(\"quakenet.org\" quakenet \"bobby\" \"sekrit\")
@@ -433,6 +434,20 @@ will be killed."
:version "28.1"
:type 'boolean)
+(defcustom rcirc-cycle-completion-flag nil
+ "Non-nil means to use cycling for completion in rcirc buffers.
+See the Info node `(emacs) Completion Options' for background on
+what cycling completion means."
+ :version "29.1"
+ :set (lambda (sym val)
+ (dolist (buf (match-buffers '(major-mode . rcirc-mode)))
+ (with-current-buffer buf
+ (if val
+ (setq-local completion-cycle-threshold t)
+ (kill-local-variable 'completion-cycle-threshold))))
+ (set-default sym val))
+ :type 'boolean)
+
(defvar-local rcirc-nick nil
"The nickname used for the current connection.")
@@ -560,8 +575,8 @@ If ARG is non-nil, instead prompt for connection parameters."
(auth (auth-source-search :host server
:user user-name
:port port))
- (fn (plist-get (car auth) :secret)))
- (setq password (funcall fn)))
+ (pwd (auth-info-password (car auth))))
+ (setq password pwd))
(when server
(let (connected)
(dolist (p (rcirc-process-list))
@@ -757,18 +772,26 @@ SERVER-PLIST is the property list for the server."
(yes-or-no-p "Encrypt connection?"))
'tls 'plain))
+(defvar rcirc-reconnect-delay)
(defun rcirc-keepalive ()
"Send keep alive pings to active rcirc processes.
Kill processes that have not received a server message since the
last ping."
(if (rcirc-process-list)
(mapc (lambda (process)
- (with-rcirc-process-buffer process
- (when (not rcirc-connecting)
- (rcirc-send-ctcp process
- rcirc-nick
- (format "KEEPALIVE %f"
- (float-time))))))
+ (with-rcirc-process-buffer process
+ (when (not rcirc-connecting)
+ (condition-case nil
+ (rcirc-send-ctcp process
+ rcirc-nick
+ (format "KEEPALIVE %f"
+ (float-time)))
+ (rcirc-closed-connection
+ (if (zerop rcirc-reconnect-delay)
+ (message "rcirc: Connection to %s closed"
+ (process-name process))
+ (rcirc-reconnect process))
+ (message ""))))))
(rcirc-process-list))
;; no processes, clean up timer
(when (timerp rcirc-keepalive-timer)
@@ -1060,17 +1083,18 @@ Note that the messages are stored in reverse order.")
;; expression and `rcirc-process-regexp'.
(error "Malformed tag %S" tag))
(cons (match-string 1 tag)
- (replace-regexp-in-string
- (rx (* ?\\ ?\\) ?\\ (any ?: ?s ?\\ ?r ?n))
- (lambda (rep)
- (concat (substring rep 0 -2)
- (cl-case (aref rep (1- (length rep)))
- (?: ";")
- (?s " ")
- (?\\ "\\\\")
- (?r "\r")
- (?n "\n"))))
- (match-string 2 tag))))
+ (when (match-string 2 tag)
+ (replace-regexp-in-string
+ (rx (* ?\\ ?\\) ?\\ (any ?: ?s ?\\ ?r ?n))
+ (lambda (rep)
+ (concat (substring rep 0 -2)
+ (cl-case (aref rep (1- (length rep)))
+ (?: ";")
+ (?s " ")
+ (?\\ "\\\\")
+ (?r "\r")
+ (?n "\n"))))
+ (match-string 2 tag)))))
(split-string tag-data ";"))))
rcirc-message-tags))
(user (match-string 3 text))
@@ -1122,6 +1146,8 @@ used as the message body."
"Check if PROCESS is open or running."
(memq (process-status process) '(run open)))
+(define-error 'rcirc-closed-connection "Network connection not open")
+
(defun rcirc-send-string (process &rest parts)
"Send PROCESS a PARTS plus a newline.
PARTS may contain a `:' symbol, to designate that the next string
@@ -1139,8 +1165,7 @@ element in PARTS is a list, append it to PARTS."
rcirc-encode-coding-system)
"\n")))
(unless (rcirc--connection-open-p process)
- (error "Network connection to %s is not open"
- (process-name process)))
+ (signal 'rcirc-closed-connection process))
(rcirc-debug process string)
(process-send-string process string)))
@@ -1321,33 +1346,30 @@ The list is updated automatically by `defun-rcirc-command'.")
'set-rcirc-encode-coding-system
"28.1")
-(defvar rcirc-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "RET") 'rcirc-send-input)
- (define-key map (kbd "M-p") 'rcirc-insert-prev-input)
- (define-key map (kbd "M-n") 'rcirc-insert-next-input)
- (define-key map (kbd "TAB") 'completion-at-point)
- (define-key map (kbd "C-c C-b") 'rcirc-browse-url)
- (define-key map (kbd "C-c C-c") 'rcirc-edit-multiline)
- (define-key map (kbd "C-c C-j") 'rcirc-cmd-join)
- (define-key map (kbd "C-c C-k") 'rcirc-cmd-kick)
- (define-key map (kbd "C-c C-l") 'rcirc-toggle-low-priority)
- (define-key map (kbd "C-c C-d") 'rcirc-cmd-mode)
- (define-key map (kbd "C-c C-m") 'rcirc-cmd-msg)
- (define-key map (kbd "C-c C-r") 'rcirc-cmd-nick) ; rename
- (define-key map (kbd "C-c C-o") 'rcirc-omit-mode)
- (define-key map (kbd "C-c C-p") 'rcirc-cmd-part)
- (define-key map (kbd "C-c C-q") 'rcirc-cmd-query)
- (define-key map (kbd "C-c C-t") 'rcirc-cmd-topic)
- (define-key map (kbd "C-c C-n") 'rcirc-cmd-names)
- (define-key map (kbd "C-c C-w") 'rcirc-cmd-whois)
- (define-key map (kbd "C-c C-x") 'rcirc-cmd-quit)
- (define-key map (kbd "C-c TAB") ; C-i
- 'rcirc-toggle-ignore-buffer-activity)
- (define-key map (kbd "C-c C-s") 'rcirc-switch-to-server-buffer)
- (define-key map (kbd "C-c C-a") 'rcirc-jump-to-first-unread-line)
- map)
- "Keymap for rcirc mode.")
+(defvar-keymap rcirc-mode-map
+ :doc "Keymap for rcirc mode."
+ "RET" #'rcirc-send-input
+ "M-p" #'rcirc-insert-prev-input
+ "M-n" #'rcirc-insert-next-input
+ "TAB" #'completion-at-point
+ "C-c C-b" #'rcirc-browse-url
+ "C-c C-c" #'rcirc-edit-multiline
+ "C-c C-j" #'rcirc-cmd-join
+ "C-c C-k" #'rcirc-cmd-kick
+ "C-c C-l" #'rcirc-toggle-low-priority
+ "C-c C-d" #'rcirc-cmd-mode
+ "C-c C-m" #'rcirc-cmd-msg
+ "C-c C-r" #'rcirc-cmd-nick ; rename
+ "C-c C-o" #'rcirc-omit-mode
+ "C-c C-p" #'rcirc-cmd-part
+ "C-c C-q" #'rcirc-cmd-query
+ "C-c C-t" #'rcirc-cmd-topic
+ "C-c C-n" #'rcirc-cmd-names
+ "C-c C-w" #'rcirc-cmd-whois
+ "C-c C-x" #'rcirc-cmd-quit
+ "C-c C-i" #'rcirc-toggle-ignore-buffer-activity
+ "C-c C-s" #'rcirc-switch-to-server-buffer
+ "C-c C-a" #'rcirc-jump-to-first-unread-line)
(defvar-local rcirc-short-buffer-name nil
"Generated abbreviation to use to indicate buffer activity.")
@@ -1434,7 +1456,8 @@ PROCESS is the process object used for communication.
(add-hook 'completion-at-point-functions
'rcirc-completion-at-point nil 'local)
- (setq-local completion-cycle-threshold t)
+ (when rcirc-cycle-completion-flag
+ (setq-local completion-cycle-threshold t))
(run-mode-hooks 'rcirc-mode-hook))
@@ -1683,16 +1706,17 @@ extracted."
(setq rcirc-parent-buffer parent)
(insert text)
(and (> pos 0) (goto-char pos))
- (message "Type C-c C-c to return text to %s, or C-c C-k to cancel" parent))))
-
-(defvar rcirc-multiline-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-c C-c") 'rcirc-multiline-minor-submit)
- (define-key map (kbd "C-x C-s") 'rcirc-multiline-minor-submit)
- (define-key map (kbd "C-c C-k") 'rcirc-multiline-minor-cancel)
- (define-key map (kbd "ESC ESC ESC") 'rcirc-multiline-minor-cancel)
- map)
- "Keymap for multiline mode in rcirc.")
+ (message "Type %s to return text to %s, or %s to cancel"
+ (substitute-command-keys "\\[rcirc-multiline-minor-submit]")
+ parent
+ (substitute-command-keys "\\[rcirc-multiline-minor-cancel]")))))
+
+(defvar-keymap rcirc-multiline-minor-mode-map
+ :doc "Keymap for multiline mode in rcirc."
+ "C-c C-c" #'rcirc-multiline-minor-submit
+ "C-x C-s" #'rcirc-multiline-minor-submit
+ "C-c C-k" #'rcirc-multiline-minor-cancel
+ "ESC ESC ESC" #'rcirc-multiline-minor-cancel)
(define-minor-mode rcirc-multiline-minor-mode
"Minor mode for editing multiple lines in rcirc."
@@ -2240,12 +2264,10 @@ This function does not alter the INPUT string."
(mapconcat rcirc-nick-filter sorted sep)))
;;; activity tracking
-(defvar rcirc-track-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-c C-@") 'rcirc-next-active-buffer)
- (define-key map (kbd "C-c C-SPC") 'rcirc-next-active-buffer)
- map)
- "Keymap for rcirc track minor mode.")
+(defvar-keymap rcirc-track-minor-mode-map
+ :doc "Keymap for rcirc track minor mode."
+ "C-c C-@" #'rcirc-next-active-buffer
+ "C-c C-SPC" #'rcirc-next-active-buffer)
(defcustom rcirc-track-abbrevate-flag t
"Non-nil means `rcirc-track-minor-mode' should abbreviate names."
@@ -2592,15 +2614,22 @@ that, an interactive form can specified."
(defun ,fn-name (,argument &optional process target)
,(concat documentation
"\n\nNote: If PROCESS or TARGET are nil, the values given"
- "\nby `rcirc-buffer-process' and `rcirc-target' will be used.")
- (interactive (list ,interactive-spec))
+ "\nby `rcirc-buffer-process' and `rcirc-target' will be used.")
+ (interactive ,(if (stringp interactive-spec)
+ ;; HACK: Necessary to wrap the result of
+ ;; the interactive spec in a list.
+ `(list (call-interactively
+ (lambda (&rest args)
+ (interactive ,interactive-spec)
+ args)))
+ `(list ,interactive-spec)))
(unless (if (listp ,argument)
(<= ,required (length ,argument) ,total)
(string-match ,regexp ,argument))
(user-error "Malformed input (%s): %S" ',command ,argument))
(push ,(upcase (symbol-name command)) rcirc-pending-requests)
(let ((process (or process (rcirc-buffer-process)))
- (target (or target rcirc-target)))
+ (target (or target rcirc-target)))
(ignore target process)
(let (,@(cl-loop
for i from 0 for arg in (delq '&optional arguments)
@@ -3266,7 +3295,7 @@ PROCESS is the process object for the current connection."
(with-current-buffer chat-buffer
(rcirc-print process sender "NICK" old-nick new-nick)
(setq rcirc-target new-nick)
- (rename-buffer (rcirc-generate-new-buffer-name process new-nick)))
+ (rename-buffer (rcirc-generate-new-buffer-name process new-nick) t))
(setf rcirc-buffer-alist
(cons (cons new-nick chat-buffer)
(delq (assoc-string old-nick rcirc-buffer-alist t)
@@ -3447,7 +3476,7 @@ form \"PARAMETER\" to enable a feature, \"PARAMETER=VALUE\" to
configure a specific option or \"-PARAMETER\" to disable a
previously specified feature. SENDER is passed on to
`rcirc-handler-generic'. PROCESS is the process object for the
-current connection. Note that this is not the behaviour as
+current connection. Note that this is not the behavior as
specified in RFC2812, where 005 stood for RPL_BOUNCE."
(rcirc-handler-generic process "005" sender args text)
(with-rcirc-process-buffer process
diff --git a/lisp/net/rlogin.el b/lisp/net/rlogin.el
index 98b660dcc43..a6d0edae072 100644
--- a/lisp/net/rlogin.el
+++ b/lisp/net/rlogin.el
@@ -1,7 +1,6 @@
;;; rlogin.el --- remote login interface -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1995, 1997-1998, 2001-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1992-2022 Free Software Foundation, Inc.
;; Author: Noah Friedman <friedman@splode.com>
;; Keywords: unix, comm
@@ -118,19 +117,15 @@ this variable is set from that."
:type '(choice (const nil) string)
:group 'rlogin)
-(defvar rlogin-mode-map
- (let ((map (if (consp shell-mode-map)
- (cons 'keymap shell-mode-map)
- (copy-keymap shell-mode-map))))
- (define-key map "\C-c\C-c" 'rlogin-send-Ctrl-C)
- (define-key map "\C-c\C-d" 'rlogin-send-Ctrl-D)
- (define-key map "\C-c\C-z" 'rlogin-send-Ctrl-Z)
- (define-key map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash)
- (define-key map "\C-d" 'rlogin-delchar-or-send-Ctrl-D)
- (define-key map "\C-i" 'rlogin-tab-or-complete)
- map)
- "Keymap for `rlogin-mode'.")
-
+(defvar-keymap rlogin-mode-map
+ :doc "Keymap for `rlogin-mode'."
+ :parent shell-mode-map
+ "C-c C-c" #'rlogin-send-Ctrl-C
+ "C-c C-d" #'rlogin-send-Ctrl-D
+ "C-c C-z" #'rlogin-send-Ctrl-Z
+ "C-c C-\\" #'rlogin-send-Ctrl-backslash
+ "C-d" #'rlogin-delchar-or-send-Ctrl-D
+ "TAB" #'rlogin-tab-or-complete)
(defvar rlogin-history nil)
diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el
index d8341774e47..c4f97a92fb5 100644
--- a/lisp/net/secrets.el
+++ b/lisp/net/secrets.el
@@ -741,14 +741,13 @@ ITEM can also be an object path, which is used if contained in COLLECTION."
;;; Visualization.
-(defvar secrets-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map (make-composed-keymap special-mode-map widget-keymap))
- (define-key map "n" #'next-line)
- (define-key map "p" #'previous-line)
- (define-key map "z" #'kill-current-buffer)
- map)
- "Keymap used in `secrets-mode' buffers.")
+(defvar-keymap secrets-mode-map
+ :doc "Keymap used in `secrets-mode' buffers."
+ :parent (make-composed-keymap special-mode-map
+ widget-keymap)
+ "n" #'next-line
+ "p" #'previous-line
+ "z" #'kill-current-buffer)
(define-derived-mode secrets-mode special-mode "Secrets"
"Major mode for presenting password entries retrieved by Security Service.
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 7363874cf3c..c4f0d3b9404 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -40,6 +40,7 @@
(require 'image)
(require 'puny)
(require 'url-cookie)
+(require 'url-file)
(require 'pixel-fill)
(require 'text-property-search)
@@ -227,6 +228,15 @@ temporarily blinks with this face."
"Face for <h6> elements."
:version "28.1")
+(defface shr-code '((t :inherit fixed-pitch))
+ "Face used for rendering <code> blocks."
+ :version "29.1")
+
+(defface shr-mark
+ '((t :background "yellow" :foreground "black"))
+ "Face used for <mark> elements."
+ :version "29.1")
+
(defcustom shr-inhibit-images nil
"If non-nil, inhibit loading images."
:version "28.1"
@@ -280,11 +290,10 @@ and other things:
"O" #'shr-save-contents
"RET" #'shr-browse-url)
-(defvar shr-image-map
- (let ((map (copy-keymap shr-map)))
- (when (boundp 'image-map)
- (set-keymap-parent map image-map))
- map))
+(defvar-keymap shr-image-map
+ :parent (if (boundp 'image-map)
+ (make-composed-keymap shr-map image-map)
+ shr-map))
;; Public functions and commands.
(declare-function libxml-parse-html-region "xml.c"
@@ -332,6 +341,11 @@ and other things:
0))
(pixel-fill-width)))
+(defmacro shr-string-pixel-width (string)
+ `(if (not shr-use-fonts)
+ (length ,string)
+ (string-pixel-width ,string)))
+
;;;###autoload
(defun shr-insert-document (dom)
"Render the parsed document DOM into the current buffer.
@@ -356,6 +370,7 @@ DOM should be a parse tree as generated by
(shr--window-width)))
(max-specpdl-size max-specpdl-size)
(shr--link-targets nil)
+ (hscroll (window-hscroll))
;; `bidi-display-reordering' is supposed to be only used for
;; debugging purposes, but Shr's naïve filling algorithm
;; cannot cope with the complexity of RTL text in an LTR
@@ -375,17 +390,20 @@ DOM should be a parse tree as generated by
;; below will misbehave, because it silently assumes that it
;; starts with a non-hscrolled window (vertical-motion will move
;; to a wrong place otherwise).
- (set-window-hscroll nil 0)
- (shr-descend dom)
- (shr-fill-lines start (point))
- (shr--remove-blank-lines-at-the-end start (point))
- (shr--set-target-ids shr--link-targets)
+ (unwind-protect
+ (progn
+ (set-window-hscroll nil 0)
+ (shr-descend dom)
+ (shr-fill-lines start (point))
+ (shr--remove-blank-lines-at-the-end start (point))
+ (shr--set-target-ids shr--link-targets))
+ (set-window-hscroll nil hscroll))
(when shr-warning
(message "%s" shr-warning))))
(defun shr--set-target-ids (ids)
;; If the buffer is empty, there's no point in setting targets.
- (unless (zerop (buffer-size))
+ (unless (zerop (- (point-max) (point-min)))
;; We may have several targets in the same place (if you have
;; several <span id='foo'> things after one another). So group
;; them by position.
@@ -630,7 +648,7 @@ size, and full-buffer size."
(t
(shr-generic dom)))
(when-let ((id (dom-attr dom 'id)))
- (push (cons id (point)) shr--link-targets))
+ (push (cons id (set-marker (make-marker) start)) shr--link-targets))
;; If style is set, then this node has set the color.
(when style
(shr-colorize-region
@@ -668,19 +686,6 @@ size, and full-buffer size."
(goto-char (mark))
(shr-pixel-column))))
-(defun shr-string-pixel-width (string)
- (if (not shr-use-fonts)
- (length string)
- ;; Save and restore point across with-temp-buffer, since
- ;; shr-pixel-column uses save-window-excursion, which can reset
- ;; point to 1.
- (let ((pt (point)))
- (prog1
- (with-temp-buffer
- (insert string)
- (shr-pixel-column))
- (goto-char pt)))))
-
(defsubst shr--translate-insertion-chars ()
;; Remove soft hyphens.
(goto-char (point-min))
@@ -877,8 +882,10 @@ size, and full-buffer size."
;; A link to an anchor.
(concat (nth 3 base) url))
(t
- ;; Totally relative.
- (url-expand-file-name url (concat (car base) (cadr base))))))
+ ;; Totally relative. Allow Tramp file names if we're
+ ;; rendering a file:// URL.
+ (let ((url-allow-non-local-files (equal (nth 2 base) "file")))
+ (url-expand-file-name url (concat (car base) (cadr base)))))))
(defun shr-ensure-newline ()
(unless (bobp)
@@ -987,8 +994,7 @@ the mouse click event."
(let ((url (get-text-property (point) 'shr-url)))
(if (not url)
(message "No link under point")
- (url-retrieve (shr-encode-url url)
- #'shr-store-contents (list url directory)))))
+ (url-retrieve url #'shr-store-contents (list url directory)))))
(defun shr-store-contents (status url directory)
(unless (plist-get status :error)
@@ -1147,7 +1153,7 @@ Return a string with image data."
(with-temp-buffer
(set-buffer-multibyte nil)
(when (ignore-errors
- (url-cache-extract (url-cache-create-filename (shr-encode-url url)))
+ (url-cache-extract (url-cache-create-filename url))
t)
(when (re-search-forward "\r?\n\r?\n" nil t)
(shr-parse-image-data)))))
@@ -1245,6 +1251,7 @@ START, and END. Note that START and END should be markers."
(defun shr-encode-url (url)
"Encode URL."
+ (declare (obsolete nil "29.1"))
(browse-url-url-encode-chars url "[)$ ]"))
(autoload 'shr-color-visible "shr-color")
@@ -1319,6 +1326,11 @@ ones, in case fg and bg are nil."
(defun shr-tag-comment (_dom)
)
+;; Introduced in HTML5. For text browsers, functionally similar to a
+;; comment.
+(defun shr-tag-template (_dom)
+ )
+
(defun shr-dom-to-xml (dom &optional charset)
(with-temp-buffer
(shr-dom-print dom)
@@ -1407,13 +1419,21 @@ ones, in case fg and bg are nil."
(shr-fontize-dom dom 'underline))
(defun shr-tag-code (dom)
- (let ((shr-current-font 'fixed-pitch))
+ (let ((shr-current-font 'shr-code))
(shr-generic dom)))
(defun shr-tag-tt (dom)
;; The `tt' tag is deprecated in favor of `code'.
(shr-tag-code dom))
+(defun shr-tag-mark (dom)
+ (when (and (not (bobp))
+ (not (= (char-after (1- (point))) ?\s)))
+ (insert " "))
+ (let ((start (point)))
+ (shr-generic dom)
+ (shr-add-font start (point) 'shr-mark)))
+
(defun shr-tag-ins (cont)
(let* ((start (point))
(color "green")
@@ -1465,9 +1485,20 @@ ones, in case fg and bg are nil."
(shr-generic dom)
(when-let* ((id (and (not (dom-attr dom 'id)) ; Handled by `shr-descend'.
(dom-attr dom 'name)))) ; Obsolete since HTML5.
- (push (cons id (point)) shr--link-targets))
+ (push (cons id (set-marker (make-marker) start)) shr--link-targets))
(when url
- (shr-urlify (or shr-start start) (shr-expand-url url) title))))
+ (shr-urlify (or shr-start start) (shr-expand-url url) title)
+ ;; Check whether the URL is suspicious.
+ (when-let ((warning (or (textsec-suspicious-p
+ (shr-expand-url url) 'url)
+ (textsec-suspicious-p
+ (cons (shr-expand-url url)
+ (buffer-substring (or shr-start start)
+ (point)))
+ 'link))))
+ (add-text-properties (or shr-start start) (point)
+ (list 'face '(shr-link textsec-suspicious)))
+ (insert (propertize "⚠️" 'help-echo warning))))))
(defun shr-tag-abbr (dom)
(let ((title (dom-attr dom 'title))
@@ -1654,13 +1685,13 @@ The preference is a float determined from `shr-prefer-media-type'."
(setq shr-start (point))
(shr-insert alt))
((and (not shr-ignore-cache)
- (url-is-cached (shr-encode-url url)))
+ (url-is-cached url))
(funcall shr-put-image-function (shr-get-image-data url) alt
(list :width width :height height)))
(t
(when (and shr-ignore-cache
- (url-is-cached (shr-encode-url url)))
- (let ((file (url-cache-create-filename (shr-encode-url url))))
+ (url-is-cached url))
+ (let ((file (url-cache-create-filename url)))
(when (file-exists-p file)
(delete-file file))))
(when (image-type-available-p 'svg)
@@ -1669,7 +1700,7 @@ The preference is a float determined from `shr-prefer-media-type'."
(or alt "")))
(insert " ")
(url-queue-retrieve
- (shr-encode-url url) #'shr-image-fetched
+ url #'shr-image-fetched
(list (current-buffer) start (set-marker (make-marker) (point))
(list :width width :height height))
t
diff --git a/lisp/net/sieve-manage.el b/lisp/net/sieve-manage.el
index 468bc90a9d7..a39e35a53a1 100644
--- a/lisp/net/sieve-manage.el
+++ b/lisp/net/sieve-manage.el
@@ -79,6 +79,7 @@
(require 'sasl)
(autoload 'sasl-find-mechanism "sasl")
(autoload 'auth-source-search "auth-source")
+(autoload 'auth-info-password "auth-source")
;; User customizable variables:
@@ -130,7 +131,7 @@ for doing the actual authentication."
(defcustom sieve-manage-default-port "sieve"
"Default port number or service name for managesieve protocol."
- :type '(choice integer string)
+ :type '(choice natnum string)
:version "24.4")
(defcustom sieve-manage-default-stream 'network
@@ -230,10 +231,7 @@ Return the buffer associated with the connection."
:max 1
:create t))
(user-name (or (plist-get (nth 0 auth-info) :user) ""))
- (user-password (or (plist-get (nth 0 auth-info) :secret) ""))
- (user-password (if (functionp user-password)
- (funcall user-password)
- user-password))
+ (user-password (or (auth-info-password (nth 0 auth-info)) ""))
(client (sasl-make-client (sasl-find-mechanism (list mech))
user-name "sieve" sieve-manage-server))
(sasl-read-passphrase
diff --git a/lisp/net/sieve-mode.el b/lisp/net/sieve-mode.el
index 58fd41d8995..f62af03534a 100644
--- a/lisp/net/sieve-mode.el
+++ b/lisp/net/sieve-mode.el
@@ -137,13 +137,11 @@
;; Key map definition
-(defvar sieve-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-l" #'sieve-upload)
- (define-key map "\C-c\C-c" #'sieve-upload-and-kill)
- (define-key map "\C-c\C-m" #'sieve-manage)
- map)
- "Key map used in sieve mode.")
+(defvar-keymap sieve-mode-map
+ :doc "Keymap used in sieve mode."
+ "C-c C-l" #'sieve-upload
+ "C-c C-c" #'sieve-upload-and-kill
+ "C-c RET" #'sieve-manage)
;; Menu
diff --git a/lisp/net/sieve.el b/lisp/net/sieve.el
index 630ea04070b..3a6067ee10b 100644
--- a/lisp/net/sieve.el
+++ b/lisp/net/sieve.el
@@ -106,33 +106,31 @@ require \"fileinto\";
;; FIXME: This is arguably a bug/problem in `easy-menu-define'.
(declare-function sieve-manage-mode-menu "sieve")
-(defvar sieve-manage-mode-map
- (let ((map (make-sparse-keymap)))
- ;; various
- (define-key map "?" #'sieve-help)
- (define-key map "h" #'sieve-help)
- ;; activating
- (define-key map "m" #'sieve-activate)
- (define-key map "u" #'sieve-deactivate)
- (define-key map "\M-\C-?" #'sieve-deactivate-all)
- ;; navigation keys
- (define-key map "\C-p" #'sieve-prev-line)
- (define-key map [up] #'sieve-prev-line)
- (define-key map "\C-n" #'sieve-next-line)
- (define-key map [down] #'sieve-next-line)
- (define-key map " " #'sieve-next-line)
- (define-key map "n" #'sieve-next-line)
- (define-key map "p" #'sieve-prev-line)
- (define-key map "\C-m" #'sieve-edit-script)
- (define-key map "f" #'sieve-edit-script)
- ;; (define-key map "o" #'sieve-edit-script-other-window)
- (define-key map "r" #'sieve-remove)
- (define-key map "q" #'sieve-bury-buffer)
- (define-key map "Q" #'sieve-manage-quit)
- (define-key map [(down-mouse-2)] #'sieve-edit-script)
- (define-key map [(down-mouse-3)] #'sieve-manage-mode-menu)
- map)
- "Keymap for `sieve-manage-mode'.")
+(defvar-keymap sieve-manage-mode-map
+ :doc "Keymap for `sieve-manage-mode'."
+ ;; various
+ "?" #'sieve-help
+ "h" #'sieve-help
+ ;; activating
+ "m" #'sieve-activate
+ "u" #'sieve-deactivate
+ "M-DEL" #'sieve-deactivate-all
+ ;; navigation keys
+ "C-p" #'sieve-prev-line
+ "<up>" #'sieve-prev-line
+ "C-n" #'sieve-next-line
+ "<down>" #'sieve-next-line
+ "SPC" #'sieve-next-line
+ "n" #'sieve-next-line
+ "p" #'sieve-prev-line
+ "RET" #'sieve-edit-script
+ "f" #'sieve-edit-script
+ ;; "o" #'sieve-edit-script-other-window
+ "r" #'sieve-remove
+ "q" #'sieve-bury-buffer
+ "Q" #'sieve-manage-quit
+ "<down-mouse-2>" #'sieve-edit-script
+ "<down-mouse-3>" #'sieve-manage-mode-menu)
(easy-menu-define sieve-manage-mode-menu sieve-manage-mode-map
"Sieve Menu."
diff --git a/lisp/net/snmp-mode.el b/lisp/net/snmp-mode.el
index de84b4f8dd1..394c4a9666d 100644
--- a/lisp/net/snmp-mode.el
+++ b/lisp/net/snmp-mode.el
@@ -248,14 +248,12 @@ This is used during Tempo template completion."
;; Set up our keymap
;;
-(defvar snmp-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\177" 'backward-delete-char-untabify)
- (define-key map "\C-c\C-i" 'tempo-complete-tag)
- (define-key map "\C-c\C-f" 'tempo-forward-mark)
- (define-key map "\C-c\C-b" 'tempo-backward-mark)
- map)
- "Keymap used in SNMP mode.")
+(defvar-keymap snmp-mode-map
+ :doc "Keymap used in SNMP mode."
+ "DEL" #'backward-delete-char-untabify
+ "C-c TAB" #'tempo-complete-tag
+ "C-c C-f" #'tempo-forward-mark
+ "C-c C-b" #'tempo-backward-mark)
;; Set up our syntax table
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index d2092633d89..5e7bdbe6c6a 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -5,12 +5,11 @@
;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
;; Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
;; Created: December, 2009
-;; Version: 3.2.0
+;; Version: 3.2.1
;; Keywords: soap, web-services, comm, hypermedia
;; Package: soap-client
;; URL: https://github.com/alex-hhh/emacs-soap-client
-;; Package-Requires: ((cl-lib "0.6.1"))
-;;FIXME: Put in `Package-Requires:' the Emacs version we expect.
+;; Package-Requires: ((emacs "24.1") (cl-lib "0.6.1"))
;; This file is part of GNU Emacs.
@@ -659,7 +658,7 @@ representing leap seconds."
(if second
(if second-fraction
(let* ((second-fraction-significand
- (string-replace "." "" second-fraction))
+ (replace-regexp-in-string "\\." "" second-fraction))
(hertz
(expt 10 (length second-fraction-significand)))
(ticks (+ (* hertz (string-to-number second))
@@ -1937,7 +1936,7 @@ This is a specialization of `soap-decode-type' for
(e-name (soap-xs-element-name element))
;; Heuristic: guess if we need to decode using local
;; namespaces.
- (use-fq-names (string-search ":" (symbol-name (car node))))
+ (use-fq-names (string-match ":" (symbol-name (car node))))
(children (if e-name
(if use-fq-names
;; Find relevant children
diff --git a/lisp/net/socks.el b/lisp/net/socks.el
index 8df0773e1d2..2ba1c20566f 100644
--- a/lisp/net/socks.el
+++ b/lisp/net/socks.el
@@ -407,11 +407,10 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
(setq version (process-get proc 'socks-server-protocol))
(cond
((equal version 'http)
- (setq request (format (eval-when-compile
- (concat
- "CONNECT %s:%d HTTP/1.0\r\n"
- "User-Agent: Emacs/SOCKS v1.0\r\n"
- "\r\n"))
+ (setq request (format (concat
+ "CONNECT %s:%d HTTP/1.0\r\n"
+ "User-Agent: Emacs/SOCKS v1.0\r\n"
+ "\r\n")
(cond
((equal atype socks-address-type-name) address)
(t
diff --git a/lisp/net/telnet.el b/lisp/net/telnet.el
index 0d54d2220b6..802e7bc0a28 100644
--- a/lisp/net/telnet.el
+++ b/lisp/net/telnet.el
@@ -1,7 +1,6 @@
;;; telnet.el --- run a telnet session from within an Emacs buffer -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1985-2022 Free Software Foundation, Inc.
;; Author: William F. Schelter
;; Maintainer: emacs-devel@gnu.org
@@ -61,14 +60,13 @@ PROGRAM says which program to run, to talk to that machine.
LOGIN-NAME, which is optional, says what to log in as on that machine.")
(defvar telnet-new-line "\r")
-(defvar telnet-mode-map
- (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
- (define-key map "\C-m" #'telnet-send-input)
- ;; (define-key map "\C-j" #'telnet-send-input)
- (define-key map "\C-c\C-q" #'send-process-next-char)
- (define-key map "\C-c\C-c" #'telnet-interrupt-subjob)
- (define-key map "\C-c\C-z" #'telnet-c-z)
- map))
+(defvar-keymap telnet-mode-map
+ :parent comint-mode-map
+ "RET" #'telnet-send-input
+ ;; "C-j" #'telnet-send-input
+ "C-c C-q" #'send-process-next-char
+ "C-c C-c" #'telnet-interrupt-subjob
+ "C-c C-z" #'telnet-c-z)
(defvar telnet-prompt-pattern "^[^#$%>\n]*[#$%>] *")
(defvar telnet-replace-c-g nil)
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index ed73a86ef03..b504ce600d1 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -159,6 +159,7 @@ It is used for TCP/IP devices."
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . tramp-handle-list-system-processes)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -168,6 +169,7 @@ It is used for TCP/IP devices."
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . tramp-adb-handle-make-process)
(make-symbolic-link . tramp-handle-make-symbolic-link)
+ (process-attributes . tramp-handle-process-attributes)
(process-file . tramp-adb-handle-process-file)
(rename-file . tramp-adb-handle-rename-file)
(set-file-acl . ignore)
@@ -179,6 +181,7 @@ It is used for TCP/IP devices."
(start-file-process . tramp-handle-start-file-process)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . ignore)
(tramp-get-remote-gid . ignore)
(tramp-get-remote-uid . ignore)
(tramp-set-file-uid-gid . ignore)
@@ -267,7 +270,7 @@ arguments to pass to the OPERATION."
"Parse `file-attributes' for Tramp files using the ls(1) command."
(with-current-buffer (tramp-get-buffer vec)
(goto-char (point-min))
- (let ((file-properties nil))
+ (let (file-properties)
(while (re-search-forward tramp-adb-ls-toolbox-regexp nil t)
(let* ((mod-string (match-string 1))
(is-dir (eq ?d (aref mod-string 0)))
@@ -545,28 +548,8 @@ Emacs dired can't find files."
(defun tramp-adb-handle-write-region
(start end filename &optional append visit lockname mustbenew)
"Like `write-region' for Tramp files."
- (setq filename (expand-file-name filename)
- lockname (file-truename (or lockname filename)))
- (with-parsed-tramp-file-name filename nil
- (when (and mustbenew (file-exists-p filename)
- (or (eq mustbenew 'excl)
- (not
- (y-or-n-p
- (format "File %s exists; overwrite anyway?" filename)))))
- (tramp-error v 'file-already-exists filename))
-
- (let ((file-locked (eq (file-locked-p lockname) t))
- (curbuf (current-buffer))
- (tmpfile (tramp-compat-make-temp-file filename)))
-
- ;; Lock file.
- (when (and (not (auto-save-file-name-p (file-name-nondirectory filename)))
- (file-remote-p lockname)
- (not file-locked))
- (setq file-locked t)
- ;; `lock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'lock-file lockname))
-
+ (tramp-skeleton-write-region start end filename append visit lockname mustbenew
+ (let ((tmpfile (tramp-compat-make-temp-file filename)))
(when (and append (file-exists-p filename))
(copy-file filename tmpfile 'ok)
(set-file-modes tmpfile (logior (or (file-modes tmpfile) 0) #o0600)))
@@ -579,33 +562,7 @@ Emacs dired can't find files."
(unless (tramp-adb-execute-adb-command
v "push" tmpfile (tramp-compat-file-name-unquote localname))
(tramp-error v 'file-error "Cannot write: `%s'" filename))
- (delete-file tmpfile)))
-
- ;; We must also flush the cache of the directory, because
- ;; `file-attributes' reads the values from there.
- (tramp-flush-file-properties v localname)
-
- (unless (equal curbuf (current-buffer))
- (tramp-error
- v 'file-error
- "Buffer has changed from `%s' to `%s'" curbuf (current-buffer)))
-
- ;; Set file modification time.
- (when (or (eq visit t) (stringp visit))
- (set-visited-file-modtime
- (or (file-attribute-modification-time (file-attributes filename))
- (current-time))))
-
- ;; Unlock file.
- (when file-locked
- ;; `unlock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'unlock-file lockname))
-
- ;; The end.
- (when (and (null noninteractive)
- (or (eq visit t) (string-or-null-p visit)))
- (tramp-message v 0 "Wrote %s" filename))
- (run-hooks 'tramp-handle-write-region-hook))))
+ (delete-file tmpfile))))))
(defun tramp-adb-handle-set-file-modes (filename mode &optional flag)
"Like `set-file-modes' for Tramp files."
@@ -776,7 +733,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(defun tramp-adb-get-signal-strings (vec)
"Strings to return by `process-file' in case of signals."
(with-tramp-connection-property vec "signal-strings"
- (let ((default-directory (tramp-make-tramp-file-name vec 'localname))
+ (let ((default-directory (tramp-make-tramp-file-name vec 'noloc))
;; `shell-file-name' and `shell-command-switch' are needed
;; for Emacs < 27.1, which doesn't support connection-local
;; variables in `shell-command'.
@@ -815,10 +772,10 @@ 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))
+ (setq input (tramp-unquote-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))
@@ -849,7 +806,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(setcar (cdr destination) (expand-file-name (cadr destination)))
(if (tramp-equal-remote default-directory (cadr destination))
;; stderr is on the same remote host.
- (setq stderr (tramp-file-local-name (cadr destination)))
+ (setq stderr (tramp-unquote-file-local-name (cadr destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
@@ -870,7 +827,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 +858,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.
@@ -972,6 +929,7 @@ implementation will be used."
(tramp-make-tramp-temp-file v))))
(remote-tmpstderr
(and tmpstderr (tramp-make-tramp-file-name v tmpstderr)))
+ (orig-command command)
(program (car command))
(args (cdr command))
(command
@@ -984,102 +942,115 @@ implementation will be used."
(or (null program) tramp-process-connection-type))
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
- (i 0))
+ (i 0)
+ p)
+
+ (when (string-match-p "[[:multibyte:]]" command)
+ (tramp-error
+ v 'file-error "Cannot apply multi-byte command `%s'" command))
(while (get-process name1)
;; NAME must be unique as process name.
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
(setq name name1)
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name)
- (tramp-set-connection-property v "process-buffer" buffer)
-
- (with-current-buffer (tramp-get-connection-buffer v)
- (unwind-protect
- ;; We catch this event. Otherwise, `make-process'
- ;; could be called on the local host.
- (save-excursion
- (save-restriction
- ;; Activate narrowing in order to save BUFFER
- ;; contents. Clear also the modification time;
- ;; otherwise we might be interrupted by
- ;; `verify-visited-file-modtime'.
- (let ((buffer-undo-list t)
- (inhibit-read-only t)
- (coding-system-for-write
- (if (symbolp coding) coding (car coding)))
- (coding-system-for-read
- (if (symbolp coding) coding (cdr coding))))
- (clear-visited-file-modtime)
- (narrow-to-region (point-max) (point-max))
- ;; We call `tramp-adb-maybe-open-connection',
- ;; in order to cleanup the prompt afterwards.
- (tramp-adb-maybe-open-connection v)
- (delete-region (point-min) (point-max))
- ;; Send the command.
- (let* ((p (tramp-get-connection-process v)))
- (tramp-adb-send-command v command nil t) ; nooutput
- ;; Set sentinel and filter.
- (when sentinel
- (set-process-sentinel p sentinel))
- (when filter
- (set-process-filter p filter))
- ;; Set query flag and process marker for
- ;; this process. We ignore errors, because
- ;; the process could have finished already.
- (ignore-errors
- (set-process-query-on-exit-flag p (null noquery))
- (set-marker (process-mark p) (point)))
- ;; We must flush them here already;
- ;; otherwise `rename-file', `delete-file' or
- ;; `insert-file-contents' will fail.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")
- ;; Copy tmpstderr file.
- (when (and (stringp stderr)
- (not (tramp-tramp-file-p stderr)))
- (add-function
- :after (process-sentinel p)
- (lambda (_proc _msg)
- (rename-file remote-tmpstderr stderr))))
- ;; Read initial output. Remove the first
- ;; line, which is the command echo.
- (unless (eq filter t)
- (while
- (progn
- (goto-char (point-min))
- (not (re-search-forward "[\n]" nil t)))
- (tramp-accept-process-output p 0))
- (delete-region (point-min) (point)))
- ;; Provide error buffer. This shows only
- ;; initial error messages; messages arriving
- ;; later on will be inserted when the
- ;; process is deleted. The temporary file
- ;; will exist until the process is deleted.
- (when (bufferp stderr)
- (with-current-buffer stderr
- (insert-file-contents-literally
- remote-tmpstderr 'visit))
- ;; Delete tmpstderr file.
- (add-function
- :after (process-sentinel p)
- (lambda (_proc _msg)
- (with-current-buffer stderr
- (insert-file-contents-literally
- remote-tmpstderr 'visit nil nil 'replace))
- (delete-file remote-tmpstderr))))
- ;; Return process.
- p))))
-
- ;; Save exit.
- (if (string-prefix-p tramp-temp-buffer-name (buffer-name))
- (ignore-errors
- (set-process-buffer (tramp-get-connection-process v) nil)
- (kill-buffer (current-buffer)))
- (set-buffer-modified-p bmp))
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")))))))))
+
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name)
+ (tramp-set-connection-property v "process-buffer" buffer)
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (unwind-protect
+ ;; We catch this event. Otherwise,
+ ;; `make-process' could be called on the local
+ ;; host.
+ (save-excursion
+ (save-restriction
+ ;; Activate narrowing in order to save
+ ;; BUFFER contents. Clear also the
+ ;; modification time; otherwise we might be
+ ;; interrupted by `verify-visited-file-modtime'.
+ (let ((buffer-undo-list t)
+ (inhibit-read-only t)
+ (coding-system-for-write
+ (if (symbolp coding) coding (car coding)))
+ (coding-system-for-read
+ (if (symbolp coding) coding (cdr coding))))
+ (clear-visited-file-modtime)
+ (narrow-to-region (point-max) (point-max))
+ ;; We call `tramp-adb-maybe-open-connection',
+ ;; in order to cleanup the prompt afterwards.
+ (tramp-adb-maybe-open-connection v)
+ (delete-region (point-min) (point-max))
+ ;; Send the command.
+ (setq p (tramp-get-connection-process v))
+ (tramp-adb-send-command v command nil t) ; nooutput
+ ;; Set sentinel and filter.
+ (when sentinel
+ (set-process-sentinel p sentinel))
+ (when filter
+ (set-process-filter p filter))
+ (process-put p 'remote-command orig-command)
+ (tramp-set-connection-property
+ p "remote-command" orig-command)
+ ;; Set query flag and process marker for
+ ;; this process. We ignore errors,
+ ;; because the process could have finished
+ ;; already.
+ (ignore-errors
+ (set-process-query-on-exit-flag p (null noquery))
+ (set-marker (process-mark p) (point))
+ ;; We must flush them here already;
+ ;; otherwise `rename-file', `delete-file' or
+ ;; `insert-file-contents' will fail.
+ (tramp-flush-connection-property v "process-name")
+ (tramp-flush-connection-property
+ v "process-buffer")
+ ;; Copy tmpstderr file.
+ (when (and (stringp stderr)
+ (not (tramp-tramp-file-p stderr)))
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (rename-file remote-tmpstderr stderr))))
+ ;; Read initial output. Remove the
+ ;; first line, which is the command
+ ;; echo.
+ (unless (eq filter t)
+ (while
+ (progn
+ (goto-char (point-min))
+ (not (re-search-forward "[\n]" nil t)))
+ (tramp-accept-process-output p 0))
+ (delete-region (point-min) (point)))
+ ;; Provide error buffer. This shows
+ ;; only initial error messages; messages
+ ;; arriving later on will be inserted
+ ;; when the process is deleted. The
+ ;; temporary file will exist until the
+ ;; process is deleted.
+ (when (bufferp stderr)
+ (with-current-buffer stderr
+ (insert-file-contents-literally
+ remote-tmpstderr 'visit))
+ ;; Delete tmpstderr file.
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (with-current-buffer stderr
+ (insert-file-contents-literally
+ remote-tmpstderr 'visit nil nil 'replace))
+ (delete-file remote-tmpstderr))))
+ ;; Return process.
+ p))))
+
+ ;; Save exit.
+ (if (string-prefix-p tramp-temp-buffer-name (buffer-name))
+ (ignore-errors
+ (set-process-buffer p nil)
+ (kill-buffer (current-buffer)))
+ (set-buffer-modified-p bmp))))))))))))
(defun tramp-adb-handle-exec-path ()
"Like `exec-path' for Tramp files."
@@ -1108,9 +1079,9 @@ E.g. a host name \"192.168.1.1#5555\" returns \"192.168.1.1:5555\"
tramp-prefix-port-format ":"
(cond ((member host devices) host)
;; This is the case when the host is connected to the default port.
- ((member (format "%s%s%d" host tramp-prefix-port-format port)
+ ((member (format "%s%s%s" host tramp-prefix-port-format port)
devices)
- (format "%s:%d" host port))
+ (format "%s:%s" host port))
;; An empty host name shall be mapped as well, when there
;; is exactly one entry in `devices'.
((and (zerop (length host)) (= (length devices) 1))
@@ -1264,7 +1235,7 @@ connection if a previous connection has died for some reason."
(if (zerop (length device))
(tramp-error vec 'file-error "Device %s not connected" host))
(with-tramp-progress-reporter vec 3 "Opening adb shell connection"
- (let* ((coding-system-for-read 'utf-8-dos) ;is this correct?
+ (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct?
(process-connection-type tramp-process-connection-type)
(args (if (> (length host) 0)
(list "-s" device "shell")
@@ -1318,8 +1289,7 @@ connection if a previous connection has died for some reason."
"echo \\\"`getprop ro.product.model` "
"`getprop ro.product.version` "
"`getprop ro.build.version.release`\\\""))
- (let ((old-getprop
- (tramp-get-connection-property vec "getprop" nil))
+ (let ((old-getprop (tramp-get-connection-property vec "getprop"))
(new-getprop
(tramp-set-connection-property
vec "getprop"
@@ -1359,10 +1329,47 @@ connection if a previous connection has died for some reason."
'tramp-adb-connection-local-default-shell-profile
tramp-adb-connection-local-default-shell-variables)
+(defconst tramp-adb-connection-local-default-ps-variables
+ '((tramp-process-attributes-ps-args)
+ (tramp-process-attributes-ps-format
+ . ((user . string)
+ (pid . number)
+ (ppid . number)
+ (vsize . number)
+ (rss . number)
+ (wchan . string) ; ??
+ (pc . string) ; ??
+ (state . string)
+ (args . nil))))
+ "Default connection-local ps variables for remote adb connections.")
+
+(connection-local-set-profile-variables
+ 'tramp-adb-connection-local-default-ps-profile
+ tramp-adb-connection-local-default-ps-variables)
+
(with-eval-after-load 'shell
(connection-local-set-profiles
`(:application tramp :protocol ,tramp-adb-method)
- 'tramp-adb-connection-local-default-shell-profile))
+ 'tramp-adb-connection-local-default-shell-profile
+ 'tramp-adb-connection-local-default-ps-profile))
+
+;; `shell-mode' tries to open remote files like "/adb::~/.history".
+;; This fails, because the tilde cannot be expanded. Tell
+;; `tramp-handle-expand-file-name' to tolerate this.
+(defun tramp-adb-tolerate-tilde (orig-fun)
+ "Advice for `shell-mode' to tolerate tilde in remote file names."
+ (let ((tramp-tolerate-tilde
+ (or tramp-tolerate-tilde
+ (equal (file-remote-p default-directory 'method)
+ tramp-adb-method))))
+ (funcall orig-fun)))
+
+(add-function
+ :around (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde)
+(add-hook 'tramp-adb-unload-hook
+ (lambda ()
+ (remove-function
+ (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde)))
(add-hook 'tramp-unload-hook
(lambda ()
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 8a88057d38a..119ac54dd29 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -57,6 +57,7 @@
;; * ".crate" - Cargo (Rust) packages
;; * ".deb" - Debian packages
;; * ".depot" - HP-UX SD depots
+;; * ".epub" - Electronic publications
;; * ".exe" - Self extracting Microsoft Windows EXE files
;; * ".iso" - ISO 9660 images
;; * ".jar" - Java archives
@@ -145,6 +146,7 @@
"crate" ;; Cargo (Rust) packages. Not in libarchive testsuite.
"deb" ;; Debian packages. Not in libarchive testsuite.
"depot" ;; HP-UX SD depot. Not in libarchive testsuite.
+ "epub" ;; Electronic publications. Not in libarchive testsuite.
"exe" ;; Self extracting Microsoft Windows EXE files.
"iso" ;; ISO 9660 images.
"jar" ;; Java archives. Not in libarchive testsuite.
@@ -190,6 +192,8 @@ It must be supported by libarchive(3).")
"\\)" ;; \1
"\\(" "/" ".*" "\\)" "\\'"))) ;; \2
+(put #'tramp-archive-autoload-file-name-regexp 'tramp-autoload t)
+
;; In older Emacsen (prior 27.1), `tramp-archive-autoload-file-name-regexp'
;; is not autoloaded. So we cannot expect it to be known in
;; tramp-loaddefs.el. But it exists, when tramp-archive.el is loaded.
@@ -265,6 +269,7 @@ It must be supported by libarchive(3).")
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-archive-handle-insert-directory)
(insert-file-contents . tramp-archive-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-archive-handle-load)
(lock-file . ignore)
(make-auto-save-file-name . ignore)
@@ -274,6 +279,7 @@ It must be supported by libarchive(3).")
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-archive-handle-not-implemented)
+ (process-attributes . ignore)
(process-file . ignore)
(rename-file . tramp-archive-handle-not-implemented)
(set-file-acl . ignore)
@@ -285,6 +291,7 @@ It must be supported by libarchive(3).")
(start-file-process . tramp-archive-handle-not-implemented)
;; `substitute-in-file-name' performed by default handler.
(temporary-file-directory . tramp-archive-handle-temporary-file-directory)
+ (tramp-get-home-directory . ignore)
(tramp-get-remote-gid . ignore)
(tramp-get-remote-uid . ignore)
(tramp-set-file-uid-gid . ignore)
@@ -302,7 +309,8 @@ Operations not mentioned here will be handled by the default Emacs primitives.")
#'tramp-archive-file-name-p))
(apply #'tramp-file-name-for-operation operation args)))
-(defun tramp-archive-run-real-handler (operation args)
+;;;###tramp-autoload
+(progn (defun tramp-archive-run-real-handler (operation args)
"Invoke normal file name handler for OPERATION.
First arg specifies the OPERATION, second arg ARGS is a list of
arguments to pass to the OPERATION."
@@ -312,7 +320,7 @@ arguments to pass to the OPERATION."
,(and (eq inhibit-file-name-operation operation)
inhibit-file-name-handlers)))
(inhibit-file-name-operation operation))
- (apply operation args)))
+ (apply operation args))))
;;;###tramp-autoload
(defun tramp-archive-file-name-handler (operation &rest args)
@@ -357,24 +365,29 @@ arguments to pass to the OPERATION."
(progn (defun tramp-archive-autoload-file-name-handler (operation &rest args)
"Load Tramp archive file name handler, and perform OPERATION."
(defvar tramp-archive-autoload)
- (when tramp-archive-enabled
- ;; We cannot use `tramp-compat-temporary-file-directory' here due
- ;; to autoload. When installing Tramp's GNU ELPA package, there
- ;; might be an older, incompatible version active. We try to
- ;; overload this.
- (let ((default-directory temporary-file-directory)
- (tramp-archive-autoload t))
- (apply #'tramp-autoload-file-name-handler operation args)))))
+ (let (;; We cannot use `tramp-compat-temporary-file-directory' here
+ ;; due to autoload. When installing Tramp's GNU ELPA package,
+ ;; there might be an older, incompatible version active. We
+ ;; try to overload this.
+ (default-directory temporary-file-directory)
+ (tramp-archive-autoload tramp-archive-enabled))
+ (apply #'tramp-autoload-file-name-handler operation args))))
+
+(put #'tramp-archive-autoload-file-name-handler 'tramp-autoload t)
;;;###autoload
(progn (defun tramp-register-archive-file-name-handler ()
"Add archive file name handler to `file-name-handler-alist'."
- (when tramp-archive-enabled
+ (when (and tramp-archive-enabled
+ (not
+ (rassq #'tramp-archive-file-name-handler file-name-handler-alist)))
(add-to-list 'file-name-handler-alist
(cons (tramp-archive-autoload-file-name-regexp)
#'tramp-archive-autoload-file-name-handler))
(put #'tramp-archive-autoload-file-name-handler 'safe-magic t))))
+(put #'tramp-register-archive-file-name-handler 'tramp-autoload t)
+
;;;###autoload
(progn
(add-hook 'after-init-hook #'tramp-register-archive-file-name-handler)
@@ -457,7 +470,7 @@ name is kept in slot `hop'"
((tramp-archive-file-name-p archive)
(let ((archive
(tramp-make-tramp-file-name
- (tramp-archive-dissect-file-name archive) nil 'noarchive)))
+ (tramp-archive-dissect-file-name archive))))
(setf (tramp-file-name-host vec) (tramp-archive-gvfs-host archive)))
(puthash archive (list vec) tramp-archive-hash))
@@ -560,8 +573,7 @@ offered."
(defun tramp-archive-gvfs-file-name (name)
"Return NAME in GVFS syntax."
- (tramp-make-tramp-file-name
- (tramp-archive-dissect-file-name name) nil 'nohop))
+ (tramp-make-tramp-file-name (tramp-archive-dissect-file-name name)))
;; File name primitives.
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 715b537247f..dbebcad1a84 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -122,14 +122,14 @@ If KEY is `tramp-cache-undefined', don't create anything, and return nil."
(puthash key (make-hash-table :test #'equal) tramp-cache-data)))
(when (tramp-file-name-p key)
(dolist (elt tramp-connection-properties)
- (when (tramp-compat-string-search
+ (when (string-match-p
(or (nth 0 elt) "")
- (tramp-make-tramp-file-name key 'noloc 'nohop))
+ (tramp-make-tramp-file-name key 'noloc))
(tramp-set-connection-property key (nth 1 elt) (nth 2 elt)))))
hash))))
;;;###tramp-autoload
-(defun tramp-get-file-property (key file property default)
+(defun tramp-get-file-property (key file property &optional default)
"Get the PROPERTY of FILE from the cache context of KEY.
Return DEFAULT if not set."
;; Unify localname. Remove hop from `tramp-file-name' structure.
@@ -240,7 +240,7 @@ Return VALUE."
(defun tramp-flush-file-properties (key file)
"Remove all properties of FILE in the cache context of KEY."
(let* ((file (tramp-run-real-handler #'directory-file-name (list file)))
- (truename (tramp-get-file-property key file "file-truename" nil)))
+ (truename (tramp-get-file-property key file "file-truename")))
;; Unify localname. Remove hop from `tramp-file-name' structure.
(setq file (tramp-compat-file-name-unquote file)
key (copy-tramp-file-name key))
@@ -262,7 +262,7 @@ Remove also properties of all files in subdirectories."
(setq directory (tramp-compat-file-name-unquote directory))
(let* ((directory (tramp-run-real-handler
#'directory-file-name (list directory)))
- (truename (tramp-get-file-property key directory "file-truename" nil)))
+ (truename (tramp-get-file-property key directory "file-truename")))
(tramp-message key 8 "%s" directory)
(dolist (key (hash-table-keys tramp-cache-data))
(when (and (tramp-file-name-p key)
@@ -311,7 +311,7 @@ This is suppressed for temporary buffers."
;;; -- Properties --
;;;###tramp-autoload
-(defun tramp-get-connection-property (key property default)
+(defun tramp-get-connection-property (key property &optional default)
"Get the named PROPERTY for the connection.
KEY identifies the connection, it is either a process or a
`tramp-file-name' structure. A special case is nil, which is
@@ -427,7 +427,7 @@ used to cache connection properties of the local machine."
;;;###tramp-autoload
(defun tramp-list-connections ()
- "Return all known `tramp-file-name' structs according to `tramp-cache'."
+ "Return all active `tramp-file-name' structs according to `tramp-cache-data'."
(let ((tramp-verbose 0))
(delq nil (mapcar
(lambda (key)
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index c18ab4972d2..bd2dbf4a1e0 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -51,6 +51,7 @@ SYNTAX can be one of the symbols `default' (default),
(when syntax
(customize-set-variable 'tramp-syntax syntax)))
+;;;###tramp-autoload
(defun tramp-list-tramp-buffers ()
"Return a list of all Tramp connection buffers."
(append
@@ -61,6 +62,7 @@ SYNTAX can be one of the symbols `default' (default),
(all-completions
"*trace tramp" (mapcar #'list (mapcar #'buffer-name (buffer-list))))))
+;;;###tramp-autoload
(defun tramp-list-remote-buffers ()
"Return a list of all buffers with remote `default-directory'."
(delq
@@ -133,7 +135,7 @@ When called interactively, a Tramp connection has to be selected."
(get-buffer (tramp-debug-buffer-name vec)))
(unless keep-debug
(get-buffer (tramp-trace-buffer-name vec)))
- (tramp-get-connection-property vec "process-buffer" nil)))
+ (tramp-get-connection-property vec "process-buffer")))
(when (bufferp buf) (kill-buffer buf)))
;; Flush file cache.
@@ -720,7 +722,7 @@ the debug buffer(s).")
(when (y-or-n-p "Do you want to append the buffer(s)?")
;; OK, let's send. First we delete the buffer list.
- (kill-buffer nil)
+ (kill-buffer)
(switch-to-buffer curbuf)
(goto-char (point-max))
(insert (propertize "\n" 'display "\n\
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 0a45b12a04a..a12e4859ac4 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -31,12 +31,13 @@
(require 'auth-source)
(require 'format-spec)
-(require 'ls-lisp) ;; Due to `tramp-handle-insert-directory'.
+(require 'ls-lisp) ;; Due to `tramp-handle-insert-directory'.
(require 'parse-time)
(require 'shell)
(require 'subr-x)
(declare-function tramp-error "tramp")
+(declare-function tramp-file-name-handler "tramp")
(declare-function tramp-tramp-file-p "tramp")
(defvar tramp-temp-name-prefix)
@@ -133,8 +134,8 @@ NAME is unquoted."
#'exec-path
(lambda ()
"List of directories to search programs to run in remote subprocesses."
- (if-let ((handler (find-file-name-handler default-directory 'exec-path)))
- (funcall handler 'exec-path)
+ (if (tramp-tramp-file-p default-directory)
+ (tramp-file-name-handler 'exec-path)
exec-path))))
;; `time-equal-p' has appeared in Emacs 27.1.
@@ -233,7 +234,7 @@ CONDITION can also be a list of error conditions."
(if (fboundp 'string-replace)
#'string-replace
(lambda (from-string to-string in-string)
- (let ((case-fold-search nil))
+ (let (case-fold-search)
(replace-regexp-in-string
(regexp-quote from-string) to-string in-string t t)))))
@@ -242,7 +243,7 @@ CONDITION can also be a list of error conditions."
(if (fboundp 'string-search)
#'string-search
(lambda (needle haystack &optional start-pos)
- (let ((case-fold-search nil))
+ (let (case-fold-search)
(string-match-p (regexp-quote needle) haystack start-pos)))))
;; Function `make-lock-file-name' is new in Emacs 28.1.
@@ -283,6 +284,16 @@ CONDITION can also be a list of error conditions."
(tramp-error vec tramp-permission-denied file)
(tramp-error vec tramp-permission-denied "Permission denied: %s" file)))
+;; Function `auth-info-password' is new in Emacs 29.1.
+(defalias 'tramp-compat-auth-info-password
+ (if (fboundp 'auth-info-password)
+ #'auth-info-password
+ (lambda (auth-info)
+ (let ((secret (plist-get auth-info :secret)))
+ (while (functionp secret)
+ (setq secret (funcall secret)))
+ secret))))
+
(dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
(put (intern elt) 'tramp-suppress-trace t))
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 36443e09830..6cb1237a0f4 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -39,7 +39,7 @@
;; first time you access a crypted remote directory. It is kept in
;; your user directory "~/.emacs.d/" with the url-encoded directory
;; name as part of the basename, and ".encfs6.xml" as suffix. Do not
-;; loose this file and the corresponding password; otherwise there is
+;; lose this file and the corresponding password; otherwise there is
;; no way to decrypt your crypted files.
;; If the user option `tramp-crypt-save-encfs-config-remote' is
@@ -151,7 +151,7 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
(dolist (dir tramp-crypt-directories)
(and (string-prefix-p
dir (file-name-as-directory (expand-file-name name)))
- (throw 'crypt-file-name-p dir))))))
+ (throw 'crypt-file-name-p dir))))))
;; New handlers should be added here.
@@ -193,9 +193,9 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
;; `file-name-nondirectory' performed by default handler.
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
- (file-notify-add-watch . ignore)
- (file-notify-rm-watch . ignore)
- (file-notify-valid-p . ignore)
+ (file-notify-add-watch . tramp-handle-file-notify-add-watch)
+ (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
+ (file-notify-valid-p . tramp-handle-file-notify-valid-p)
(file-ownership-preserved-p . tramp-crypt-handle-file-ownership-preserved-p)
(file-readable-p . tramp-crypt-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
@@ -208,7 +208,8 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-crypt-handle-insert-directory)
- ;; `insert-file-contents' performed by default handler.
+ (insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-handle-load)
(lock-file . tramp-crypt-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -218,6 +219,7 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-handle-make-symbolic-link)
+ (process-attributes . ignore)
(process-file . ignore)
(rename-file . tramp-crypt-handle-rename-file)
(set-file-acl . ignore)
@@ -229,6 +231,7 @@ If NAME doesn't belong to a crypted remote directory, retun nil."
(start-file-process . ignore)
;; `substitute-in-file-name' performed by default handler.
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ ;; `tramp-get-home-directory' performed by default-handler.
;; `tramp-get-remote-gid' performed by default handler.
;; `tramp-get-remote-uid' performed by default handler.
(tramp-set-file-uid-gid . tramp-crypt-handle-set-file-uid-gid)
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el
index ff8caa570ca..dd7e0f9f342 100644
--- a/lisp/net/tramp-ftp.el
+++ b/lisp/net/tramp-ftp.el
@@ -125,7 +125,7 @@ pass to the OPERATION."
;; "ftp" method is used in the Tramp file name. So we unset
;; those values.
(ange-ftp-ftp-name-arg "")
- (ange-ftp-ftp-name-res nil))
+ ange-ftp-ftp-name-res)
(cond
;; If argument is a symlink, `file-directory-p' and
;; `file-exists-p' call the traversed file recursively. So we
@@ -135,12 +135,21 @@ pass to the OPERATION."
;; completion. We don't use `with-parsed-tramp-file-name',
;; because this returns another user but the one declared in
;; "~/.netrc".
+ ;; For file names which look like Tramp archive files like
+ ;; "/ftp:anonymous@ftp.gnu.org:/gnu/tramp/tramp-2.0.39.tar.gz",
+ ;; we must disable tramp-archive.el, because in
+ ;; `ange-ftp-get-files' this is "normalized" by
+ ;; `file-name-as-directory' with unwelcome side side-effects.
+ ;; This disables the file archive functionality, perhaps we
+ ;; could fix this otherwise. (Bug#56078)
((memq operation '(file-directory-p file-exists-p))
- (if (apply #'ange-ftp-hook-function operation args)
+ (cl-letf (((symbol-function #'tramp-archive-file-name-handler)
+ (lambda (operation &rest args)
+ (tramp-archive-run-real-handler operation args))))
+ (prog1 (apply #'ange-ftp-hook-function operation args)
(let ((v (tramp-dissect-file-name (car args) t)))
(setf (tramp-file-name-method v) tramp-ftp-method)
- (tramp-set-connection-property v "started" t))
- nil))
+ (tramp-set-connection-property v "started" t)))))
;; If the second argument of `copy-file' or `rename-file' is a
;; remote file name but via FTP, ange-ftp doesn't check this.
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index 2a73d5aa02b..2ff106d6023 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -44,6 +44,17 @@
(delete-file (tramp-fuse-local-file-name filename) trash)
(tramp-flush-file-properties v localname)))
+(defvar tramp-fuse-remove-hidden-files nil
+ "Remove hidden files from directory listings.")
+
+(defsubst tramp-fuse-remove-hidden-files (files)
+ "Remove hidden files from FILES."
+ (if tramp-fuse-remove-hidden-files
+ (cl-remove-if
+ (lambda (x) (and (stringp x) (string-match-p "\\.fuse_hidden" x)))
+ files)
+ files))
+
(defun tramp-fuse-handle-directory-files
(directory &optional full match nosort count)
"Like `directory-files' for Tramp files."
@@ -75,7 +86,8 @@
result)))
(setq result (cons item result))))
;; Return result.
- (if nosort result (sort result #'string<))))))
+ (tramp-fuse-remove-hidden-files
+ (if nosort result (sort result #'string<)))))))
(defun tramp-fuse-handle-file-attributes (filename &optional id-format)
"Like `file-attributes' for Tramp files."
@@ -92,20 +104,21 @@
(defun tramp-fuse-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (all-completions
- filename
- (delete-dups
- (append
- (file-name-all-completions
- filename (tramp-fuse-local-file-name directory))
- ;; Some storage systems do not return "." and "..".
- (let (result)
- (dolist (item '(".." ".") result)
- (when (string-prefix-p filename item)
- (catch 'match
- (dolist (elt completion-regexp-list)
- (unless (string-match-p elt item) (throw 'match nil)))
- (setq result (cons (concat item "/") result))))))))))
+ (tramp-fuse-remove-hidden-files
+ (all-completions
+ filename
+ (delete-dups
+ (append
+ (file-name-all-completions
+ filename (tramp-fuse-local-file-name directory))
+ ;; Some storage systems do not return "." and "..".
+ (let (result)
+ (dolist (item '(".." ".") result)
+ (when (string-prefix-p filename item)
+ (catch 'match
+ (dolist (elt completion-regexp-list)
+ (unless (string-match-p elt item) (throw 'match nil)))
+ (setq result (cons (concat item "/") result)))))))))))
;; This function isn't used.
(defun tramp-fuse-handle-insert-directory
@@ -140,7 +153,7 @@
(defun tramp-fuse-mount-point (vec)
"Return local mount point of VEC."
- (or (tramp-get-connection-property vec "mount-point" nil)
+ (or (tramp-get-connection-property vec "mount-point")
(expand-file-name
(concat
tramp-temp-name-prefix
@@ -164,7 +177,7 @@ It has the same meaning as `remote-file-name-inhibit-cache'.")
;; cannot use `with-tramp-file-property', because we don't want to
;; cache a nil result.
(let ((remote-file-name-inhibit-cache tramp-fuse-mount-timeout))
- (or (tramp-get-file-property vec "/" "mounted" nil)
+ (or (tramp-get-file-property vec "/" "mounted")
(let* ((default-directory tramp-compat-temporary-file-directory)
(command (format "mount -t fuse.%s" (tramp-file-name-method vec)))
(mount (shell-command-to-string command)))
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 221ee547a2b..056237fd55c 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -796,6 +796,7 @@ It has been changed in GVFS 1.14.")
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -805,6 +806,7 @@ It has been changed in GVFS 1.14.")
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-handle-make-symbolic-link)
+ (process-attributes . ignore)
(process-file . ignore)
(rename-file . tramp-gvfs-handle-rename-file)
(set-file-acl . ignore)
@@ -816,6 +818,7 @@ It has been changed in GVFS 1.14.")
(start-file-process . ignore)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . tramp-gvfs-handle-get-home-directory)
(tramp-get-remote-gid . tramp-gvfs-handle-get-remote-gid)
(tramp-get-remote-uid . tramp-gvfs-handle-get-remote-uid)
(tramp-set-file-uid-gid . tramp-gvfs-handle-set-file-uid-gid)
@@ -836,6 +839,8 @@ Operations not mentioned here will be handled by the default Emacs primitives.")
(let ((method (tramp-file-name-method vec)))
(and (stringp method) (member method tramp-gvfs-methods)))))
+(defvar tramp-gvfs-dbus-event-vector)
+
;;;###tramp-autoload
(defun tramp-gvfs-file-name-handler (operation &rest args)
"Invoke the GVFS related OPERATION and ARGS.
@@ -843,7 +848,11 @@ First arg specifies the OPERATION, second arg is a list of
arguments to pass to the OPERATION."
(unless tramp-gvfs-enabled
(tramp-user-error nil "Package `tramp-gvfs' not supported"))
- (if-let ((fn (assoc operation tramp-gvfs-file-name-handler-alist)))
+ (if-let ((filename (apply #'tramp-file-name-for-operation operation args))
+ (tramp-gvfs-dbus-event-vector
+ (and (tramp-tramp-file-p filename)
+ (tramp-dissect-file-name filename)))
+ (fn (assoc operation tramp-gvfs-file-name-handler-alist)))
(save-match-data (apply (cdr fn) args))
(tramp-run-real-handler operation args)))
@@ -916,8 +925,6 @@ or `dbus-call-method-asynchronously'."
;; when loading.
(dbus-ignore-errors (tramp-dbus-function ,vec func args))))
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-tramp-dbus-call-method\\>"))
-
(defmacro with-tramp-dbus-get-all-properties
(vec bus service path interface)
"Return all properties of INTERFACE.
@@ -932,12 +939,11 @@ The call will be traced by Tramp with trace level 6."
(tramp-dbus-function
,vec #'dbus-get-all-properties (list ,bus ,service ,path ,interface))))
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-tramp-dbus-get-all-properties\\>"))
-
(defvar tramp-gvfs-dbus-event-vector nil
"Current Tramp file name to be used, as vector.
It is needed when D-Bus signals or errors arrive, because there
-is no information where to trace the message.")
+is no information where to trace the message.
+Globally, the value shall always be nil; it is bound where needed.")
(defun tramp-gvfs-dbus-event-error (event err)
"Called when a D-Bus error message arrives, see `dbus-event-error-functions'."
@@ -1014,7 +1020,7 @@ file names."
;; We cannot copy or rename directly.
((or (and equal-remote
- (tramp-get-connection-property v "direct-copy-failed" nil))
+ (tramp-get-connection-property v "direct-copy-failed"))
(and t1 (not (tramp-gvfs-file-name-p filename)))
(and t2 (not (tramp-gvfs-file-name-p newname))))
(let ((tmpfile (tramp-compat-make-temp-file filename)))
@@ -1051,7 +1057,7 @@ file names."
(if (or (not equal-remote)
(and equal-remote
(tramp-get-connection-property
- v "direct-copy-failed" nil)))
+ v "direct-copy-failed")))
;; Propagate the error.
(with-current-buffer (tramp-get-connection-buffer v)
(goto-char (point-min))
@@ -1139,22 +1145,22 @@ file names."
(setq name (tramp-compat-file-name-concat dir name)))
;; If NAME is not a Tramp file, run the real handler.
(if (not (tramp-tramp-file-p name))
- (tramp-run-real-handler #'expand-file-name (list name nil))
+ (tramp-run-real-handler #'expand-file-name (list name))
;; Dissect NAME.
(with-parsed-tramp-file-name name nil
;; If there is a default location, expand tilde.
- (when (string-match "\\`\\(~\\)\\(/\\|\\'\\)" localname)
- (save-match-data
- (tramp-gvfs-maybe-open-connection
- (make-tramp-file-name
- :method method :user user :domain domain
- :host host :port port :localname "/" :hop hop)))
- (unless (string-empty-p
- (tramp-get-connection-property v "default-location" ""))
- (setq localname
- (replace-match
- (tramp-get-connection-property v "default-location" "~")
- nil t localname 1))))
+ (when (string-match "\\`~\\([^/]*\\)\\(.*\\)\\'" localname)
+ (let ((uname (match-string 1 localname))
+ (fname (match-string 2 localname))
+ hname)
+ (when (zerop (length uname))
+ (setq uname user))
+ (when (setq hname (tramp-get-home-directory v uname))
+ (setq localname (concat hname fname)))))
+ ;; Tilde expansion is not possible.
+ (when (and (not tramp-tolerate-tilde)
+ (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname))
+ (tramp-error v 'file-error "Cannot expand tilde in file `%s'" name))
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "/" localname)))
;; We do not pass "/..".
@@ -1172,7 +1178,7 @@ file names."
;; Do normal `expand-file-name' (this does "/./" and "/../"),
;; unless there are tilde characters in file name.
(tramp-make-tramp-file-name
- v (if (string-match-p "\\`~" localname)
+ v (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
localname
(tramp-run-real-handler #'expand-file-name (list localname)))))))
@@ -1330,32 +1336,29 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(or (cdr (assoc "standard::size" attributes)) "0")))
;; ... file mode flags
(setq res-filemodes
- (let ((n (cdr (assoc "unix::mode" attributes))))
- (if n
- (tramp-file-mode-from-int (string-to-number n))
- (format
- "%s%s%s%s------"
- (if dirp "d" (if res-symlink-target "l" "-"))
- (if (equal (cdr (assoc "access::can-read" attributes))
- "FALSE")
- "-" "r")
- (if (equal (cdr (assoc "access::can-write" attributes))
- "FALSE")
- "-" "w")
- (if (equal (cdr (assoc "access::can-execute" attributes))
- "FALSE")
- "-" "x")))))
+ (if-let ((n (cdr (assoc "unix::mode" attributes))))
+ (tramp-file-mode-from-int (string-to-number n))
+ (format
+ "%s%s%s%s------"
+ (if dirp "d" (if res-symlink-target "l" "-"))
+ (if (equal (cdr (assoc "access::can-read" attributes))
+ "FALSE")
+ "-" "r")
+ (if (equal (cdr (assoc "access::can-write" attributes))
+ "FALSE")
+ "-" "w")
+ (if (equal (cdr (assoc "access::can-execute" attributes))
+ "FALSE")
+ "-" "x"))))
;; ... inode and device
(setq res-inode
- (let ((n (cdr (assoc "unix::inode" attributes))))
- (if n
- (string-to-number n)
- (tramp-get-inode (tramp-dissect-file-name filename)))))
+ (if-let ((n (cdr (assoc "unix::inode" attributes))))
+ (string-to-number n)
+ (tramp-get-inode (tramp-dissect-file-name filename))))
(setq res-device
- (let ((n (cdr (assoc "unix::device" attributes))))
- (if n
- (string-to-number n)
- (tramp-get-device (tramp-dissect-file-name filename)))))
+ (if-let ((n (cdr (assoc "unix::device" attributes))))
+ (string-to-number n)
+ (tramp-get-device (tramp-dissect-file-name filename))))
;; Return data gathered.
(list
@@ -1389,7 +1392,8 @@ If FILE-SYSTEM is non-nil, return file system attributes."
"Like `file-executable-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
(with-tramp-file-property v localname "file-executable-p"
- (tramp-check-cached-permissions v ?x))))
+ (or (tramp-check-cached-permissions v ?x)
+ (tramp-check-cached-permissions v ?s)))))
(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
@@ -1575,8 +1579,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(with-current-buffer (tramp-get-connection-buffer vec)
(goto-char (point-min))
(when (looking-at-p "gio: Operation not supported")
- (tramp-set-connection-property vec key nil)))
- nil))))
+ (tramp-set-connection-property vec key nil)))))))
(defun tramp-gvfs-handle-set-file-modes (filename mode &optional flag)
"Like `set-file-modes' for Tramp files."
@@ -1600,15 +1603,33 @@ If FILE-SYSTEM is non-nil, return file system attributes."
nil
time)))))
+(defun tramp-gvfs-handle-get-home-directory (vec &optional _user)
+ "The remote home directory for connection VEC as local file name.
+If USER is a string, return its home directory instead of the
+user identified by VEC. If there is no user specified in either
+VEC or USER, or if there is no home directory, return nil."
+ (let ((localname (tramp-get-connection-property vec "default-location"))
+ result)
+ (cond
+ ((zerop (length localname))
+ (tramp-get-connection-property (tramp-get-process vec) "share"))
+ ;; Google-drive.
+ ((not (string-prefix-p "/" localname))
+ (dolist (item
+ (tramp-gvfs-get-directory-attributes
+ (tramp-make-tramp-file-name vec "/"))
+ result)
+ (when (string-equal (cdr (assoc "name" item)) localname)
+ (setq result (concat "/" (car item))))))
+ (t localname))))
+
(defun tramp-gvfs-handle-get-remote-uid (vec id-format)
"The uid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
(if (equal id-format 'string)
(tramp-file-name-user vec)
(when-let ((localname
- (tramp-get-connection-property
- (tramp-get-process vec) "share"
- (tramp-get-connection-property vec "default-location" nil))))
+ (tramp-get-connection-property (tramp-get-process vec) "share")))
(file-attribute-user-id
(file-attributes (tramp-make-tramp-file-name vec localname) id-format)))))
@@ -1616,9 +1637,7 @@ ID-FORMAT valid values are `string' and `integer'."
"The gid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
(when-let ((localname
- (tramp-get-connection-property
- (tramp-get-process vec) "share"
- (tramp-get-connection-property vec "default-location" nil))))
+ (tramp-get-connection-property (tramp-get-process vec) "share")))
(file-attribute-group-id
(file-attributes (tramp-make-tramp-file-name vec localname) id-format))))
@@ -1656,7 +1675,7 @@ ID-FORMAT valid values are `string' and `integer'."
(concat (tramp-gvfs-get-remote-prefix v) localname)))
(when (string-equal "mtp" method)
(when-let
- ((media (tramp-get-connection-property v "media-device" nil)))
+ ((media (tramp-get-connection-property v "media-device")))
(setq method (tramp-media-device-method media)
host (tramp-media-device-host media)
port (tramp-media-device-port media))))
@@ -1731,7 +1750,7 @@ a downcased host name only."
(setq domain (read-string "Domain name: ")))
(tramp-message l 6 "%S %S %S %d" message user domain flags)
- (unless (tramp-get-connection-property l "first-password-request" nil)
+ (unless (tramp-get-connection-property l "first-password-request")
(tramp-clear-passwd l))
(setq password (tramp-read-passwd
@@ -1769,22 +1788,26 @@ a downcased host name only."
(list
t ;; handled.
nil ;; no abort of D-Bus.
- (with-tramp-connection-property (tramp-get-process v) message
- ;; In theory, there can be several choices.
- ;; Until now, there is only the question whether
- ;; to accept an unknown host signature or certificate.
- (with-temp-buffer
- ;; Preserve message for `progress-reporter'.
- (with-temp-message ""
- (insert message)
- (goto-char (point-max))
- (if noninteractive
- (message "%s" message)
- (pop-to-buffer (current-buffer)))
- (if (yes-or-no-p
- (buffer-substring
- (line-beginning-position) (point)))
- 0 1)))))
+ ;; Preserve message for `progress-reporter'.
+ (with-temp-message ""
+ (if noninteractive
+ ;; Keep regression tests running.
+ (progn
+ (message "%s" message)
+ 0)
+ (with-tramp-connection-property (tramp-get-process v) message
+ ;; In theory, there can be several choices.
+ ;; Until now, there is only the question
+ ;; whether to accept an unknown host
+ ;; signature or certificate.
+ (with-temp-buffer
+ (insert message)
+ (goto-char (point-max))
+ (pop-to-buffer (current-buffer))
+ (if (yes-or-no-p
+ (buffer-substring
+ (line-beginning-position) (point)))
+ 0 1))))))
;; When QUIT is raised, we shall return this
;; information to D-Bus.
@@ -1849,14 +1872,13 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(when (member method tramp-media-methods)
;; Ensure that media devices are cached.
(tramp-get-media-devices nil)
- (let ((v (tramp-get-connection-property
- (make-tramp-media-device
- :method method :host host :port port)
- "vector" nil)))
- (when v
- (setq method (tramp-file-name-method v)
- host (tramp-file-name-host v)
- port (tramp-file-name-port v)))))
+ (when-let ((v (tramp-get-connection-property
+ (make-tramp-media-device
+ :method method :host host :port port)
+ "vector" nil)))
+ (setq method (tramp-file-name-method v)
+ host (tramp-file-name-host v)
+ port (tramp-file-name-port v))))
(when (member method tramp-gvfs-methods)
(let ((v (make-tramp-file-name
:method method :user user :domain domain
@@ -1894,15 +1916,14 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(defun tramp-gvfs-connection-mounted-p (vec)
"Check, whether the location is already mounted."
(or
- (tramp-get-file-property vec "/" "fuse-mountpoint" nil)
+ (tramp-get-file-property vec "/" "fuse-mountpoint")
(catch 'mounted
(dolist
(elt
(with-tramp-file-property vec "/" "list-mounts"
(with-tramp-dbus-call-method vec t
:session tramp-gvfs-service-daemon tramp-gvfs-path-mounttracker
- tramp-gvfs-interface-mounttracker tramp-gvfs-listmounts))
- nil)
+ tramp-gvfs-interface-mounttracker tramp-gvfs-listmounts)))
;; Jump over the first elements of the mount info. Since there
;; were changes in the entries, we cannot access dedicated
;; elements.
@@ -1951,14 +1972,13 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(when (member method tramp-media-methods)
;; Ensure that media devices are cached.
(tramp-get-media-devices vec)
- (let ((v (tramp-get-connection-property
- (make-tramp-media-device
- :method method :host host :port port)
- "vector" nil)))
- (when v
- (setq method (tramp-file-name-method v)
- host (tramp-file-name-host v)
- port (tramp-file-name-port v)))))
+ (when-let ((v (tramp-get-connection-property
+ (make-tramp-media-device
+ :method method :host host :port port)
+ "vector")))
+ (setq method (tramp-file-name-method v)
+ host (tramp-file-name-host v)
+ port (tramp-file-name-port v))))
(when (and
(string-equal method (tramp-file-name-method vec))
(string-equal user (tramp-file-name-user vec))
@@ -2112,10 +2132,6 @@ connection if a previous connection has died for some reason."
(unless (tramp-connectable-p vec)
(throw 'non-essential 'non-essential))
- ;; We set the file name, in case there are incoming D-Bus signals or
- ;; D-Bus errors.
- (setq tramp-gvfs-dbus-event-vector vec)
-
;; For password handling, we need a process bound to the connection
;; buffer. Therefore, we create a dummy process. Maybe there is a
;; better solution?
@@ -2218,7 +2234,7 @@ connection if a previous connection has died for some reason."
(tramp-error
vec 'file-error
"Timeout reached mounting %s@%s using %s" user host method)))
- (while (not (tramp-get-file-property vec "/" "fuse-mountpoint" nil))
+ (while (not (tramp-get-file-property vec "/" "fuse-mountpoint"))
(read-event nil nil 0.1)))
;; If `tramp-gvfs-handler-askquestion' has returned "No", it
@@ -2246,13 +2262,7 @@ connection if a previous connection has died for some reason."
COMMAND is a command from the gvfs-* utilities. It is replaced
by the corresponding gio tool call if available. `call-process'
is applied, and it returns t if the return code is zero."
- (let* ((locale (tramp-get-local-locale vec))
- (process-environment
- (append
- `(,(format "LANG=%s" locale)
- ,(format "LANGUAGE=%s" locale)
- ,(format "LC_ALL=%s" locale))
- process-environment)))
+ (let ((locale (tramp-get-local-locale vec)))
(when (tramp-gvfs-gio-tool-p vec)
;; Use gio tool.
(setq args (cons (cdr (assoc command tramp-gvfs-gio-mapping))
@@ -2262,7 +2272,14 @@ is applied, and it returns t if the return code is zero."
(with-current-buffer (tramp-get-connection-buffer vec)
(tramp-gvfs-maybe-open-connection vec)
(erase-buffer)
- (or (zerop (apply #'tramp-call-process vec command nil t nil args))
+ (or (zerop
+ (apply
+ #'tramp-call-process vec "env" nil t nil
+ (append `(,(format "LANG=%s" locale)
+ ,(format "LANGUAGE=%s" locale)
+ ,(format "LC_ALL=%s" locale)
+ ,command)
+ args)))
;; Remove information about mounted connection.
(and (tramp-flush-file-properties vec "/") nil)))))
@@ -2355,11 +2372,11 @@ It checks for registered GNOME Online Accounts."
(defun tramp-get-media-device (vec)
"Transform VEC into a `tramp-media-device' structure.
Check, that respective cache values do exist."
- (if-let ((media (tramp-get-connection-property vec "media-device" nil))
- (prop (tramp-get-connection-property media "vector" nil)))
+ (if-let ((media (tramp-get-connection-property vec "media-device"))
+ (prop (tramp-get-connection-property media "vector")))
media
(tramp-get-media-devices vec)
- (tramp-get-connection-property vec "media-device" nil)))
+ (tramp-get-connection-property vec "media-device")))
(defun tramp-get-media-devices (vec)
"Retrieve media devices, and cache them.
@@ -2404,9 +2421,9 @@ It checks for mounted media devices."
(lambda (key)
(and (tramp-media-device-p key)
(string-equal service (tramp-media-device-method key))
- (tramp-get-connection-property key "vector" nil)
+ (tramp-get-connection-property key "vector")
(list nil (tramp-file-name-host
- (tramp-get-connection-property key "vector" nil)))))
+ (tramp-get-connection-property key "vector")))))
(hash-table-keys tramp-cache-data)))
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index 03a2c2457a2..226113d8800 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -39,6 +39,7 @@
(declare-function info-lookup->topic-value "info-look")
(declare-function info-lookup-maybe-add-help "info-look")
(declare-function recentf-cleanup "recentf")
+(declare-function shortdoc-add-function "shortdoc")
(declare-function tramp-dissect-file-name "tramp")
(declare-function tramp-file-name-equal-p "tramp")
(declare-function tramp-tramp-file-p "tramp")
@@ -49,6 +50,7 @@
(defvar info-lookup-alist)
(defvar ivy-completing-read-handlers-alist)
(defvar recentf-exclude)
+(defvar shortdoc--groups)
(defvar tramp-current-connection)
(defvar tramp-postfix-host-format)
(defvar tramp-use-ssh-controlmaster-options)
@@ -106,7 +108,7 @@ been set up by `rfn-eshadow-setup-minibuffer'."
end))
(point-max))
(let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
- (rfn-eshadow-update-overlay-hook nil)
+ rfn-eshadow-update-overlay-hook
file-name-handler-alist)
(move-overlay rfn-eshadow-overlay (point-max) (point-max))
(rfn-eshadow-update-overlay))))))))
@@ -257,6 +259,33 @@ NAME must be equal to `tramp-current-connection'."
(delete (info-lookup->mode-cache 'symbol ',mode)
(info-lookup->topic-cache 'symbol))))))))
+;;; Integration of shortdoc.el:
+
+(with-eval-after-load 'shortdoc
+ (dolist (elem '((file-remote-p
+ :eval (file-remote-p "/ssh:user@host:/tmp/foo")
+ :eval (file-remote-p "/ssh:user@host:/tmp/foo" 'method))
+ (file-local-name
+ :eval (file-local-name "/ssh:user@host:/tmp/foo"))
+ (file-local-copy
+ :no-eval (file-local-copy "/ssh:user@host:/tmp/foo")
+ :eg-result "/tmp/tramp.8ihLbO"
+ :eval (file-local-copy "/tmp/foo"))))
+ (unless (assoc (car elem)
+ (member "Remote Files" (assq 'file shortdoc--groups)))
+ (shortdoc-add-function 'file "Remote Files" elem)))
+
+ (add-hook
+ 'tramp-integration-unload-hook
+ (lambda ()
+ (let ((glist (assq 'file shortdoc--groups)))
+ (while (and (consp glist)
+ (not (and (stringp (cadr glist))
+ (string-equal (cadr glist) "Remote Files"))))
+ (setq glist (cdr glist)))
+ (when (consp glist)
+ (setcdr glist nil))))))
+
;;; Integration of compile.el:
;; Compilation processes use `accept-process-output' such a way that
@@ -271,7 +300,7 @@ NAME must be equal to `tramp-current-connection'."
#'tramp-compile-disable-ssh-controlmaster-options)
(add-hook 'tramp-integration-unload-hook
(lambda ()
- (remove-hook 'compilation-start-hook
+ (remove-hook 'compilation-mode-hook
#'tramp-compile-disable-ssh-controlmaster-options))))
;;; Default connection-local variables for Tramp.
@@ -303,6 +332,220 @@ NAME must be equal to `tramp-current-connection'."
'(:application tramp)
'tramp-connection-local-default-shell-profile))
+;; Tested with FreeBSD 12.2.
+(defconst tramp-bsd-process-attributes-ps-args
+ `("-acxww"
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("pid"
+ "euid"
+ "user"
+ "egid"
+ "egroup"
+ "comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+ ",")
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("state"
+ "ppid"
+ "pgid"
+ "sid"
+ "tty"
+ "tpgid"
+ "minflt"
+ "majflt"
+ "time"
+ "pri"
+ "nice"
+ "vsz"
+ "rss"
+ "etimes"
+ "pcpu"
+ "pmem"
+ "args")
+ ","))
+ "List of arguments for \"ps\".
+See `tramp-process-attributes-ps-args'.")
+
+(defconst tramp-bsd-process-attributes-ps-format
+ '((pid . number)
+ (euid . number)
+ (user . string)
+ (egid . number)
+ (group . string)
+ (comm . 52)
+ (state . string)
+ (ppid . number)
+ (pgrp . number)
+ (sess . number)
+ (ttname . string)
+ (tpgid . number)
+ (minflt . number)
+ (majflt . number)
+ (time . tramp-ps-time)
+ (pri . number)
+ (nice . number)
+ (vsize . number)
+ (rss . number)
+ (etime . number)
+ (pcpu . number)
+ (pmem . number)
+ (args . nil))
+ "Alist of formats for \"ps\".
+See `tramp-process-attributes-ps-format'.")
+
+(defconst tramp-connection-local-bsd-ps-variables
+ `((tramp-process-attributes-ps-args
+ . ,tramp-bsd-process-attributes-ps-args)
+ (tramp-process-attributes-ps-format
+ . ,tramp-bsd-process-attributes-ps-format))
+ "Default connection-local ps variables for remote BSD connections.")
+
+(connection-local-set-profile-variables
+ 'tramp-connection-local-bsd-ps-profile
+ tramp-connection-local-bsd-ps-variables)
+
+;; Tested with BusyBox v1.24.1.
+(defconst tramp-busybox-process-attributes-ps-args
+ `("-o"
+ ,(mapconcat
+ #'identity
+ '("pid"
+ "user"
+ "group"
+ "comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+ ",")
+ "-o" "stat=abcde"
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("ppid"
+ "pgid"
+ "tty"
+ "time"
+ "nice"
+ "etime"
+ "args")
+ ","))
+ "List of arguments for \"ps\".
+See `tramp-process-attributes-ps-args'.")
+
+(defconst tramp-busybox-process-attributes-ps-format
+ '((pid . number)
+ (user . string)
+ (group . string)
+ (comm . 52)
+ (state . 5)
+ (ppid . number)
+ (pgrp . number)
+ (ttname . string)
+ (time . tramp-ps-time)
+ (nice . number)
+ (etime . tramp-ps-time)
+ (args . nil))
+ "Alist of formats for \"ps\".
+See `tramp-process-attributes-ps-format'.")
+
+(defconst tramp-connection-local-busybox-ps-variables
+ `((tramp-process-attributes-ps-args
+ . ,tramp-busybox-process-attributes-ps-args)
+ (tramp-process-attributes-ps-format
+ . ,tramp-busybox-process-attributes-ps-format))
+ "Default connection-local ps variables for remote Busybox connections.")
+
+(connection-local-set-profile-variables
+ 'tramp-connection-local-busybox-ps-profile
+ tramp-connection-local-busybox-ps-variables)
+
+;; Darwin (macOS).
+(defconst tramp-darwin-process-attributes-ps-args
+ `("-acxww"
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("pid"
+ "uid"
+ "user"
+ "gid"
+ "comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+ ",")
+ "-o" "state=abcde"
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("ppid"
+ "pgid"
+ "sess"
+ "tty"
+ "tpgid"
+ "minflt"
+ "majflt"
+ "time"
+ "pri"
+ "nice"
+ "vsz"
+ "rss"
+ "etime"
+ "pcpu"
+ "pmem"
+ "args")
+ ","))
+ "List of arguments for \"ps\".
+See `tramp-process-attributes-ps-args'.")
+
+(defconst tramp-darwin-process-attributes-ps-format
+ '((pid . number)
+ (euid . number)
+ (user . string)
+ (egid . number)
+ (comm . 52)
+ (state . 5)
+ (ppid . number)
+ (pgrp . number)
+ (sess . number)
+ (ttname . string)
+ (tpgid . number)
+ (minflt . number)
+ (majflt . number)
+ (time . tramp-ps-time)
+ (pri . number)
+ (nice . number)
+ (vsize . number)
+ (rss . number)
+ (etime . tramp-ps-time)
+ (pcpu . number)
+ (pmem . number)
+ (args . nil))
+ "Alist of formats for \"ps\".
+See `tramp-process-attributes-ps-format'.")
+
+(defconst tramp-connection-local-darwin-ps-variables
+ `((tramp-process-attributes-ps-args
+ . ,tramp-darwin-process-attributes-ps-args)
+ (tramp-process-attributes-ps-format
+ . ,tramp-darwin-process-attributes-ps-format))
+ "Default connection-local ps variables for remote Darwin connections.")
+
+(connection-local-set-profile-variables
+ 'tramp-connection-local-darwin-ps-profile
+ tramp-connection-local-darwin-ps-variables)
+
+;; Preset default "ps" profile for local hosts, based on system type.
+
+(when-let ((local-profile
+ (cond ((eq system-type 'darwin)
+ 'tramp-connection-local-darwin-ps-profile)
+ ;; ... Add other system types here.
+ )))
+ (connection-local-set-profiles
+ `(:application tramp :machine ,(system-name))
+ local-profile)
+ (connection-local-set-profiles
+ '(:application tramp :machine "localhost")
+ local-profile))
+
(add-hook 'tramp-unload-hook
(lambda () (unload-feature 'tramp-integration 'force)))
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 259e85a04a3..bbc76851318 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -107,9 +107,9 @@
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
- (file-notify-add-watch . ignore)
- (file-notify-rm-watch . ignore)
- (file-notify-valid-p . ignore)
+ (file-notify-add-watch . tramp-handle-file-notify-add-watch)
+ (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
+ (file-notify-valid-p . tramp-handle-file-notify-valid-p)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-rclone-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
@@ -123,6 +123,7 @@
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -132,6 +133,7 @@
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-handle-make-symbolic-link)
+ (process-attributes . ignore)
(process-file . ignore)
(rename-file . tramp-rclone-handle-rename-file)
(set-file-acl . ignore)
@@ -143,6 +145,7 @@
(start-file-process . ignore)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . ignore)
(tramp-get-remote-gid . ignore)
(tramp-get-remote-uid . ignore)
(tramp-set-file-uid-gid . ignore)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 72b1ebb3e06..174fde720e4 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -38,6 +38,7 @@
(declare-function dired-compress-file "dired-aux")
(declare-function dired-remove-file "dired-aux")
(defvar dired-compress-file-suffixes)
+;; Added in Emacs 28.1.
(defvar process-file-return-signal-string)
(defvar vc-handled-backends)
(defvar vc-bzr-program)
@@ -117,7 +118,7 @@ configuration."
"Which ssh Control* arguments to use.
If it is a string, it should have the form
-\"-o ControlMaster=auto -o ControlPath=\\='tramp.%%r@%%h:%%p\\='
+\"-o ControlMaster=auto -o ControlPath=tramp.%%C
-o ControlPersist=no\". Percent characters in the ControlPath
spec must be doubled, because the string is used as format string.
@@ -136,6 +137,21 @@ be auto-detected by Tramp.
The string is used in `tramp-methods'.")
+(defvar tramp-scp-force-scp-protocol nil
+ "Force scp protocol.
+
+It is the string \"-O\" if supported by the local scp (since
+release 8.6), otherwise the string \"\". If it is nil, it will
+be auto-detected by Tramp.
+
+The string is used in `tramp-methods'.")
+
+(defcustom tramp-use-scp-direct-remote-copying nil
+ "Whether to use direct copying between two remote hosts."
+ :group 'tramp
+ :version "29.1"
+ :type 'boolean)
+
;; Initialize `tramp-methods' with the supported methods.
;;;###tramp-autoload
(tramp--with-startup
@@ -172,7 +188,8 @@ The string is used in `tramp-methods'.")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k")
- ("%x") ("-q") ("-r") ("%c")))
+ ("%x") ("%y") ("%z")
+ ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)))
(add-to-list 'tramp-methods
@@ -188,7 +205,8 @@ The string is used in `tramp-methods'.")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k")
- ("%x") ("-q") ("-r") ("%c")))
+ ("%x") ("%y") ("%z")
+ ("-q") ("-r") ("%c")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)))
(add-to-list 'tramp-methods
@@ -294,7 +312,8 @@ The string is used in `tramp-methods'.")
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)
- (tramp-session-timeout 300)))
+ (tramp-session-timeout 300)
+ (tramp-password-previous-hop t)))
(add-to-list 'tramp-methods
`("doas"
(tramp-login-program "doas")
@@ -302,7 +321,8 @@ The string is used in `tramp-methods'.")
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)
- (tramp-session-timeout 300)))
+ (tramp-session-timeout 300)
+ (tramp-password-previous-hop t)))
(add-to-list 'tramp-methods
`("ksu"
(tramp-login-program "ksu")
@@ -996,6 +1016,7 @@ Format specifiers \"%s\" are replaced before the script is used.")
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-sh-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . tramp-handle-list-system-processes)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -1005,6 +1026,7 @@ Format specifiers \"%s\" are replaced before the script is used.")
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . tramp-sh-handle-make-process)
(make-symbolic-link . tramp-sh-handle-make-symbolic-link)
+ (process-attributes . tramp-handle-process-attributes)
(process-file . tramp-sh-handle-process-file)
(rename-file . tramp-sh-handle-rename-file)
(set-file-acl . tramp-sh-handle-set-file-acl)
@@ -1016,6 +1038,7 @@ Format specifiers \"%s\" are replaced before the script is used.")
(start-file-process . tramp-handle-start-file-process)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . tramp-sh-handle-get-home-directory)
(tramp-get-remote-gid . tramp-sh-handle-get-remote-gid)
(tramp-get-remote-uid . tramp-sh-handle-get-remote-uid)
(tramp-set-file-uid-gid . tramp-sh-handle-set-file-uid-gid)
@@ -1123,8 +1146,8 @@ component is used as the target of the symlink."
;; Use Perl implementation.
((and (tramp-get-remote-perl v)
- (tramp-get-connection-property v "perl-file-spec" nil)
- (tramp-get-connection-property v "perl-cwd-realpath" nil))
+ (tramp-get-connection-property v "perl-file-spec")
+ (tramp-get-connection-property v "perl-cwd-realpath"))
(tramp-maybe-send-script
v tramp-perl-file-truename "tramp_perl_file_truename")
(setq result
@@ -1149,8 +1172,7 @@ component is used as the target of the symlink."
(when (file-remote-p result)
(setq result (tramp-compat-file-name-quote result 'top)))
(tramp-message v 4 "True name of `%s' is `%s'" localname result)
- result))
- 'nohop)))))
+ result)))))))
;; Basic functions.
@@ -1163,9 +1185,9 @@ component is used as the target of the symlink."
(with-parsed-tramp-file-name filename nil
(with-tramp-file-property v localname "file-exists-p"
(or (not (null (tramp-get-file-property
- v localname "file-attributes-integer" nil)))
+ v localname "file-attributes-integer")))
(not (null (tramp-get-file-property
- v localname "file-attributes-string" nil)))
+ v localname "file-attributes-string")))
(tramp-send-command-and-check
v
(format
@@ -1194,12 +1216,18 @@ component is used as the target of the symlink."
;; The scripts could fail, for example with huge file size.
(tramp-do-file-attributes-with-ls v localname id-format))))))))
+(defconst tramp-sunos-unames (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
+ "Regexp to determine remote SunOS.")
+
(defun tramp-sh--quoting-style-options (vec)
"Quoting style options to be used for VEC."
(or
(tramp-get-ls-command-with
vec "--quoting-style=literal --show-control-chars")
- (tramp-get-ls-command-with vec "-w")
+ ;; ls on Solaris does not return an error in that case. We've got
+ ;; reports for "SunOS 5.11" so far.
+ (unless (tramp-check-remote-uname vec tramp-sunos-unames)
+ (tramp-get-ls-command-with vec "-w"))
""))
(defun tramp-do-file-attributes-with-ls (vec localname &optional id-format)
@@ -1435,12 +1463,26 @@ of."
v (format
"env TZ=UTC %s %s %s %s"
(tramp-get-remote-touch v)
- (if (tramp-get-connection-property v "touch-t" nil)
+ (if (tramp-get-connection-property v "touch-t")
(format "-t %s" (format-time-string "%Y%m%d%H%M.%S" time t))
"")
(if (eq flag 'nofollow) "-h" "")
(tramp-shell-quote-argument localname)))))))
+(defun tramp-sh-handle-get-home-directory (vec &optional user)
+ "The remote home directory for connection VEC as local file name.
+If USER is a string, return its home directory instead of the
+user identified by VEC. If there is no user specified in either
+VEC or USER, or if there is no home directory, return nil."
+ (when (tramp-send-command-and-check
+ vec (format
+ "echo %s"
+ (tramp-shell-quote-argument
+ (concat "~" (or user (tramp-file-name-user vec))))))
+ (with-current-buffer (tramp-get-buffer vec)
+ (goto-char (point-min))
+ (buffer-substring (point) (point-at-eol)))))
+
(defun tramp-sh-handle-get-remote-uid (vec id-format)
"The uid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
@@ -1579,6 +1621,7 @@ ID-FORMAT valid values are `string' and `integer'."
;; Examine `file-attributes' cache to see if request can be
;; satisfied without remote operation.
(or (tramp-check-cached-permissions v ?x)
+ (tramp-check-cached-permissions v ?s)
(tramp-run-test "-x" filename)))))
(defun tramp-sh-handle-file-readable-p (filename)
@@ -2241,200 +2284,211 @@ the uid and gid from FILENAME."
(op filename newname ok-if-already-exists keep-date)
"Invoke `scp' program to copy.
The method used must be an out-of-band method."
- (let* ((t1 (tramp-tramp-file-p filename))
- (t2 (tramp-tramp-file-p newname))
- (orig-vec (tramp-dissect-file-name (if t1 filename newname)))
+ (let* ((v1 (and (tramp-tramp-file-p filename)
+ (tramp-dissect-file-name filename)))
+ (v2 (and (tramp-tramp-file-p newname)
+ (tramp-dissect-file-name newname)))
+ (v (or v1 v2))
copy-program copy-args copy-env copy-keep-date listener spec
options source target remote-copy-program remote-copy-args p)
- (with-parsed-tramp-file-name (if t1 filename newname) nil
- (if (and t1 t2)
-
- ;; Both are Tramp files. We shall optimize it when the
- ;; methods for FILENAME and NEWNAME are the same.
- (let* ((dir-flag (file-directory-p filename))
- (tmpfile (tramp-compat-make-temp-file localname dir-flag)))
- (if dir-flag
- (setq tmpfile
- (expand-file-name
- (file-name-nondirectory newname) tmpfile)))
- (unwind-protect
- (progn
- (tramp-do-copy-or-rename-file-out-of-band
- op filename tmpfile ok-if-already-exists keep-date)
- (tramp-do-copy-or-rename-file-out-of-band
- 'rename tmpfile newname ok-if-already-exists keep-date))
- ;; Save exit.
- (ignore-errors
- (if dir-flag
- (delete-directory
- (expand-file-name ".." tmpfile) 'recursive)
- (delete-file tmpfile)))))
-
- ;; Check which ones of source and target are Tramp files.
- (setq source (funcall
- (if (and (string-equal method "rsync")
- (file-directory-p filename)
- (not (file-exists-p newname)))
- #'file-name-as-directory
- #'identity)
- (if t1
- (tramp-make-copy-program-file-name v)
- (tramp-compat-file-name-unquote filename)))
- target (if t2
- (tramp-make-copy-program-file-name v)
- (tramp-compat-file-name-unquote newname)))
-
- ;; Check for user. There might be an interactive setting.
- (setq user (or (tramp-file-name-user v)
- (tramp-get-connection-property v "login-as" nil)))
-
- ;; Check for listener port.
- (when (tramp-get-method-parameter v 'tramp-remote-copy-args)
- (setq listener (number-to-string (+ 50000 (random 10000))))
- (while
- (zerop (tramp-call-process v "nc" nil nil nil "-z" host listener))
- (setq listener (number-to-string (+ 50000 (random 10000))))))
-
- ;; Compose copy command.
- (setq options
- (format-spec
- (tramp-ssh-controlmaster-options v)
- (format-spec-make
- ?t (tramp-get-connection-property
- (tramp-get-connection-process v) "temp-file" "")))
- spec (list
- ?h (or host "") ?u (or user "") ?p (or port "")
- ?r listener ?c options ?k (if keep-date " " "")
- ?n (concat "2>" (tramp-get-remote-null-device v))
- ?x (tramp-scp-strict-file-name-checking v))
- copy-program (tramp-get-method-parameter v 'tramp-copy-program)
- copy-keep-date (tramp-get-method-parameter
- v 'tramp-copy-keep-date)
- copy-args
- ;; " " has either been a replacement of "%k" (when
- ;; keep-date argument is non-nil), or a replacement for
- ;; the whole keep-date sublist.
- (delete " " (apply #'tramp-expand-args v 'tramp-copy-args spec))
- ;; `tramp-ssh-controlmaster-options' is a string instead
- ;; of a list. Unflatten it.
- copy-args
- (tramp-compat-flatten-tree
- (mapcar
- (lambda (x) (if (tramp-compat-string-search " " x)
- (split-string x) x))
- copy-args))
- copy-env (apply #'tramp-expand-args v 'tramp-copy-env spec)
- remote-copy-program
- (tramp-get-method-parameter v 'tramp-remote-copy-program)
- remote-copy-args
- (apply #'tramp-expand-args v 'tramp-remote-copy-args spec))
-
- ;; Check for local copy program.
- (unless (executable-find copy-program)
- (tramp-error
- v 'file-error "Cannot find local copy program: %s" copy-program))
-
- ;; Install listener on the remote side. The prompt must be
- ;; consumed later on, when the process does not listen anymore.
- (when remote-copy-program
- (unless (with-tramp-connection-property
- v (concat "remote-copy-program-" remote-copy-program)
- (tramp-find-executable
- v remote-copy-program (tramp-get-remote-path v)))
- (tramp-error
- v 'file-error
- "Cannot find remote listener: %s" remote-copy-program))
- (setq remote-copy-program
- (mapconcat
- #'identity
- (append
- (list remote-copy-program) remote-copy-args
- (list (if t1 (concat "<" source) (concat ">" target)) "&"))
- " "))
- (tramp-send-command v remote-copy-program)
- (with-timeout
- (60 (tramp-error
- v 'file-error
- "Listener process not running on remote host: `%s'"
- remote-copy-program))
- (tramp-send-command v (format "netstat -l | grep -q :%s" listener))
- (while (not (tramp-send-command-and-check v nil))
- (tramp-send-command
- v (format "netstat -l | grep -q :%s" listener)))))
+ (if (and v1 v2 (zerop (length (tramp-scp-direct-remote-copying v1 v2))))
- (with-temp-buffer
+ ;; Both are Tramp files. We cannot use direct remote copying.
+ (let* ((dir-flag (file-directory-p filename))
+ (tmpfile (tramp-compat-make-temp-file
+ (tramp-file-name-localname v1) dir-flag)))
+ (if dir-flag
+ (setq tmpfile
+ (expand-file-name
+ (file-name-nondirectory newname) tmpfile)))
(unwind-protect
- ;; The default directory must be remote.
- (let ((default-directory
- (file-name-directory (if t1 filename newname)))
- (process-environment (copy-sequence process-environment)))
- ;; Set the transfer process properties.
- (tramp-set-connection-property
- v "process-name" (buffer-name (current-buffer)))
- (tramp-set-connection-property
- v "process-buffer" (current-buffer))
- (when copy-env
- (tramp-message
- orig-vec 6 "%s=\"%s\""
- (car copy-env) (string-join (cdr copy-env) " "))
- (setenv (car copy-env) (string-join (cdr copy-env) " ")))
- (setq
- copy-args
- (append
- copy-args
- (if remote-copy-program
- (list (if t1 (concat ">" target) (concat "<" source)))
- (list source target)))
- ;; Use an asynchronous process. By this, password
- ;; can be handled. We don't set a timeout, because
- ;; the copying of large files can last longer than 60
- ;; secs.
- p (let ((default-directory tramp-compat-temporary-file-directory))
- (apply
- #'start-process
- (tramp-get-connection-name v)
- (tramp-get-connection-buffer v)
- copy-program copy-args)))
- (tramp-message orig-vec 6 "%s" (string-join (process-command p) " "))
- (process-put p 'vector orig-vec)
- (process-put p 'adjust-window-size-function #'ignore)
- (set-process-query-on-exit-flag p nil)
+ (progn
+ (tramp-do-copy-or-rename-file-out-of-band
+ op filename tmpfile ok-if-already-exists keep-date)
+ (tramp-do-copy-or-rename-file-out-of-band
+ 'rename tmpfile newname ok-if-already-exists keep-date))
+ ;; Save exit.
+ (ignore-errors
+ (if dir-flag
+ (delete-directory
+ (expand-file-name ".." tmpfile) 'recursive)
+ (delete-file tmpfile)))))
+
+ ;; Check which ones of source and target are Tramp files.
+ (setq source (funcall
+ (if (and (string-equal (tramp-file-name-method v) "rsync")
+ (file-directory-p filename)
+ (not (file-exists-p newname)))
+ #'file-name-as-directory
+ #'identity)
+ (if v1
+ (tramp-make-copy-program-file-name v1)
+ (tramp-compat-file-name-unquote filename)))
+ target (if v2
+ (tramp-make-copy-program-file-name v2)
+ (tramp-compat-file-name-unquote newname)))
+
+ ;; Check for listener port.
+ (when (tramp-get-method-parameter v 'tramp-remote-copy-args)
+ (setq listener (number-to-string (+ 50000 (random 10000))))
+ (while
+ (zerop (tramp-call-process
+ v "nc" nil nil nil "-z" (tramp-file-name-host v) listener))
+ (setq listener (number-to-string (+ 50000 (random 10000))))))
+
+ ;; Compose copy command.
+ (setq options
+ (format-spec
+ (tramp-ssh-controlmaster-options v)
+ (format-spec-make
+ ?t (tramp-get-connection-property
+ (tramp-get-connection-process v) "temp-file" "")))
+ spec (list
+ ;; "%h" and "%u" do not happen in `tramp-copy-args'
+ ;; of `scp', so it is save to use `v'.
+ ?h (or (tramp-file-name-host v) "")
+ ?u (or (tramp-file-name-user v)
+ ;; There might be an interactive setting.
+ (tramp-get-connection-property v "login-as")
+ "")
+ ;; For direct remote copying, the port must be the
+ ;; same for source and target.
+ ?p (or (tramp-file-name-port v) "")
+ ?r listener ?c options ?k (if keep-date " " "")
+ ?n (concat "2>" (tramp-get-remote-null-device v))
+ ?x (tramp-scp-strict-file-name-checking v)
+ ?y (tramp-scp-force-scp-protocol v)
+ ?z (tramp-scp-direct-remote-copying v1 v2))
+ copy-program (tramp-get-method-parameter v 'tramp-copy-program)
+ copy-keep-date (tramp-get-method-parameter
+ v 'tramp-copy-keep-date)
+ copy-args
+ ;; " " has either been a replacement of "%k" (when
+ ;; keep-date argument is non-nil), or a replacement for
+ ;; the whole keep-date sublist.
+ (delete " " (apply #'tramp-expand-args v 'tramp-copy-args spec))
+ ;; `tramp-ssh-controlmaster-options' is a string instead
+ ;; of a list. Unflatten it.
+ copy-args
+ (tramp-compat-flatten-tree
+ (mapcar
+ (lambda (x) (if (tramp-compat-string-search " " x)
+ (split-string x) x))
+ copy-args))
+ copy-env (apply #'tramp-expand-args v 'tramp-copy-env spec)
+ remote-copy-program
+ (tramp-get-method-parameter v 'tramp-remote-copy-program)
+ remote-copy-args
+ (apply #'tramp-expand-args v 'tramp-remote-copy-args spec))
+
+ ;; Check for local copy program.
+ (unless (executable-find copy-program)
+ (tramp-error
+ v 'file-error "Cannot find local copy program: %s" copy-program))
+
+ ;; Install listener on the remote side. The prompt must be
+ ;; consumed later on, when the process does not listen anymore.
+ (when remote-copy-program
+ (unless (with-tramp-connection-property
+ v (concat "remote-copy-program-" remote-copy-program)
+ (tramp-find-executable
+ v remote-copy-program (tramp-get-remote-path v)))
+ (tramp-error
+ v 'file-error
+ "Cannot find remote listener: %s" remote-copy-program))
+ (setq remote-copy-program
+ (mapconcat
+ #'identity
+ (append
+ (list remote-copy-program) remote-copy-args
+ (list (if v1 (concat "<" source) (concat ">" target)) "&"))
+ " "))
+ (tramp-send-command v remote-copy-program)
+ (with-timeout
+ (60 (tramp-error
+ v 'file-error
+ "Listener process not running on remote host: `%s'"
+ remote-copy-program))
+ (tramp-send-command v (format "netstat -l | grep -q :%s" listener))
+ (while (not (tramp-send-command-and-check v nil))
+ (tramp-send-command
+ v (format "netstat -l | grep -q :%s" listener)))))
+
+ (with-temp-buffer
+ (unwind-protect
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ ;; The default directory must be remote.
+ (let ((default-directory
+ (file-name-directory (if v1 filename newname)))
+ (process-environment (copy-sequence process-environment)))
+ ;; Set the transfer process properties.
+ (tramp-set-connection-property
+ v "process-name" (buffer-name (current-buffer)))
+ (tramp-set-connection-property
+ v "process-buffer" (current-buffer))
+ (when copy-env
+ (tramp-message
+ v 6 "%s=\"%s\""
+ (car copy-env) (string-join (cdr copy-env) " "))
+ (setenv (car copy-env) (string-join (cdr copy-env) " ")))
+ (setq
+ copy-args
+ (append
+ copy-args
+ (if remote-copy-program
+ (list (if v1 (concat ">" target) (concat "<" source)))
+ (list source target)))
+ ;; Use an asynchronous process. By this, password
+ ;; can be handled. We don't set a timeout, because
+ ;; the copying of large files can last longer than
+ ;; 60 secs.
+ p (let ((default-directory
+ tramp-compat-temporary-file-directory))
+ (apply
+ #'start-process
+ (tramp-get-connection-name v)
+ (tramp-get-connection-buffer v)
+ copy-program copy-args)))
+ (tramp-message v 6 "%s" (string-join (process-command p) " "))
+ (process-put p 'vector v)
+ (process-put p 'adjust-window-size-function #'ignore)
+ (set-process-query-on-exit-flag p nil)
+
+ ;; We must adapt `tramp-local-end-of-line' for sending
+ ;; the password. Also, we indicate that perhaps several
+ ;; password prompts might appear.
+ (let ((tramp-local-end-of-line tramp-rsh-end-of-line)
+ (tramp-password-prompt-not-unique (and v1 v2)))
+ (tramp-process-actions
+ p v nil tramp-actions-copy-out-of-band)))))
+
+ ;; Clear the remote prompt.
+ (when (and remote-copy-program
+ (not (tramp-send-command-and-check v nil)))
+ ;; Houston, we have a problem! Likely, the listener is
+ ;; still running, so let's clear everything (but the
+ ;; cached password).
+ (tramp-cleanup-connection v 'keep-debug 'keep-password))))
+
+ ;; Handle KEEP-DATE argument.
+ (when (and keep-date (not copy-keep-date))
+ (tramp-compat-set-file-times
+ newname
+ (file-attribute-modification-time (file-attributes filename))
+ (unless ok-if-already-exists 'nofollow)))
+
+ ;; Set the mode.
+ (unless (and keep-date copy-keep-date)
+ (ignore-errors
+ (set-file-modes newname (tramp-default-file-modes filename)))))
- ;; We must adapt `tramp-local-end-of-line' for
- ;; sending the password.
- (let ((tramp-local-end-of-line tramp-rsh-end-of-line))
- (tramp-process-actions
- p v nil tramp-actions-copy-out-of-band)))
-
- ;; Reset the transfer process properties.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")
- ;; Clear the remote prompt.
- (when (and remote-copy-program
- (not (tramp-send-command-and-check v nil)))
- ;; Houston, we have a problem! Likely, the listener is
- ;; still running, so let's clear everything (but the
- ;; cached password).
- (tramp-cleanup-connection v 'keep-debug 'keep-password))))
-
- ;; Handle KEEP-DATE argument.
- (when (and keep-date (not copy-keep-date))
- (tramp-compat-set-file-times
- newname
- (file-attribute-modification-time (file-attributes filename))
- (unless ok-if-already-exists 'nofollow)))
-
- ;; Set the mode.
- (unless (and keep-date copy-keep-date)
- (ignore-errors
- (set-file-modes newname (tramp-default-file-modes filename)))))
-
- ;; If the operation was `rename', delete the original file.
- (unless (eq op 'copy)
- (if (file-regular-p filename)
- (delete-file filename)
- (delete-directory filename 'recursive))))))
+ ;; If the operation was `rename', delete the original file.
+ (unless (eq op 'copy)
+ (if (file-regular-p filename)
+ (delete-file filename)
+ (delete-directory filename 'recursive)))))
(defun tramp-sh-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
@@ -2681,7 +2735,9 @@ The method used must be an out-of-band method."
;; Try to insert the amount of free space.
(goto-char (point-min))
;; First find the line to put it on.
- (when (re-search-forward "^\\([[:space:]]*total\\)" nil t)
+ (when (and (re-search-forward "^\\([[:space:]]*total\\)" nil t)
+ ;; Emacs 29.1 or later.
+ (not (fboundp 'dired--insert-disk-space)))
(when-let ((available (get-free-disk-space ".")))
;; Replace "total" with "total used", to avoid confusion.
(replace-match "\\1 used in directory")
@@ -2715,34 +2771,28 @@ the result will be a local, non-Tramp, file name."
(with-parsed-tramp-file-name name nil
;; If connection is not established yet, run the real handler.
(if (not (tramp-connectable-p v))
- (tramp-run-real-handler #'expand-file-name (list name nil))
+ (tramp-run-real-handler #'expand-file-name (list name))
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "~/" localname)))
;; Tilde expansion if necessary. This needs a shell which
;; groks tilde expansion! The function `tramp-find-shell' is
;; supposed to find such a shell on the remote host. Please
;; tell me about it when this doesn't work on your system.
- (when (string-match "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ (when (string-match "\\`~\\([^/]*\\)\\(.*\\)\\'" localname)
(let ((uname (match-string 1 localname))
- (fname (match-string 2 localname)))
+ (fname (match-string 2 localname))
+ hname)
;; We cannot simply apply "~/", because under sudo "~/" is
;; expanded to the local user home directory but to the
;; root home directory. On the other hand, using always
;; the default user name for tilde expansion is not
;; appropriate either, because ssh and companions might
;; use a user name from the config file.
- (when (and (string-equal uname "~")
+ (when (and (zerop (length uname))
(string-match-p "\\`su\\(do\\)?\\'" method))
- (setq uname (concat uname user)))
- (setq uname
- (with-tramp-connection-property v uname
- (tramp-send-command
- v
- (format "cd %s && pwd" (tramp-shell-quote-argument uname)))
- (with-current-buffer (tramp-get-buffer v)
- (goto-char (point-min))
- (buffer-substring (point) (point-at-eol)))))
- (setq localname (concat uname fname))))
+ (setq uname user))
+ (when (setq hname (tramp-get-home-directory v uname))
+ (setq localname (concat hname fname)))))
;; There might be a double slash, for example when "~/"
;; expands to "/". Remove this.
(while (string-match "//" localname)
@@ -2750,15 +2800,17 @@ the result will be a local, non-Tramp, file name."
;; Do not keep "/..".
(when (string-match-p "^/\\.\\.?$" localname)
(setq localname "/"))
- ;; No tilde characters in file name, do normal
- ;; `expand-file-name' (this does "/./" and "/../").
+ ;; Do normal `expand-file-name' (this does "/./" and "/../"),
+ ;; unless there are tilde characters in file name.
;; `default-directory' is bound, because on Windows there
;; would be problems with UNC shares or Cygwin mounts.
(let ((default-directory tramp-compat-temporary-file-directory))
(tramp-make-tramp-file-name
- v (tramp-drop-volume-letter
- (tramp-run-real-handler
- #'expand-file-name (list localname)))))))))
+ v (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ localname
+ (tramp-drop-volume-letter
+ (tramp-run-real-handler
+ #'expand-file-name (list localname))))))))))
;;; Remote commands:
@@ -2824,6 +2876,7 @@ implementation will be used."
stderr (tramp-make-tramp-temp-name v)))))
(remote-tmpstderr
(and tmpstderr (tramp-make-tramp-file-name v tmpstderr)))
+ (orig-command command)
(program (car command))
(args (cdr command))
;; When PROGRAM matches "*sh", and the first arg is
@@ -2835,8 +2888,10 @@ implementation will be used."
(string-match-p "sh$" program)
(= (length args) 2)
(string-equal "-c" (car args))
- ;; Don't if there is a string.
- (not (string-match-p "'\\|\"" (cadr args)))))
+ ;; Don't if there is a quoted string.
+ (not (string-match-p "'\\|\"" (cadr args)))
+ ;; Check, that /dev/tty is usable.
+ (tramp-get-remote-dev-tty v)))
;; When PROGRAM is nil, we just provide a tty.
(args (if (not heredoc) args
(let ((i 250))
@@ -2852,7 +2907,7 @@ implementation will be used."
;; `shell'. We discard hops, if existing, that's why
;; we cannot use `file-remote-p'.
(prompt (format "PS1=%s %s"
- (tramp-make-tramp-file-name v nil 'nohop)
+ (tramp-make-tramp-file-name v)
tramp-initial-end-of-output))
;; We use as environment the difference to toplevel
;; `process-environment'.
@@ -2921,91 +2976,103 @@ implementation will be used."
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
(setq name name1)
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name)
- (tramp-set-connection-property v "process-buffer" buffer)
- (with-current-buffer (tramp-get-connection-buffer v)
- (unwind-protect
- ;; We catch this event. Otherwise, `make-process'
- ;; could be called on the local host.
- (save-excursion
- (save-restriction
- ;; Activate narrowing in order to save BUFFER
- ;; contents. Clear also the modification time;
- ;; otherwise we might be interrupted by
- ;; `verify-visited-file-modtime'.
- (let ((buffer-undo-list t)
- (inhibit-read-only t)
- (mark (point-max))
- (coding-system-for-write
- (if (symbolp coding) coding (car coding)))
- (coding-system-for-read
- (if (symbolp coding) coding (cdr coding))))
- (clear-visited-file-modtime)
- (narrow-to-region (point-max) (point-max))
- (catch 'suppress
- ;; Set the pid of the remote shell. This is
- ;; needed when sending signals remotely.
- (let ((pid (tramp-send-command-and-read v "echo $$")))
- (setq p (tramp-get-connection-process v))
- (process-put p 'remote-pid pid)
- (tramp-set-connection-property p "remote-pid" pid))
- ;; Disable carriage return to newline
- ;; translation. This does not work on
- ;; macOS, see Bug#50748.
- (when (and (memq connection-type '(nil pipe))
- (not (tramp-check-remote-uname v "Darwin")))
- (tramp-send-command v "stty -icrnl"))
- ;; `tramp-maybe-open-connection' and
- ;; `tramp-send-command-and-read' could have
- ;; trashed the connection buffer. Remove this.
- (widen)
- (delete-region mark (point-max))
- (narrow-to-region (point-max) (point-max))
- ;; Now do it.
- (if command
- ;; Send the command.
- (tramp-send-command v command nil t) ; nooutput
- ;; Check, whether a pty is associated.
- (unless (process-get p 'remote-tty)
- (tramp-error
- v 'file-error
- "pty association is not supported for `%s'"
- name))))
- ;; Set sentinel and filter.
- (when sentinel
- (set-process-sentinel p sentinel))
- (when filter
- (set-process-filter p filter))
- ;; Set query flag and process marker for this
- ;; process. We ignore errors, because the
- ;; process could have finished already.
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name)
+ (tramp-set-connection-property v "process-buffer" buffer)
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (unwind-protect
+ ;; We catch this event. Otherwise,
+ ;; `make-process' could be called on the local
+ ;; host.
+ (save-excursion
+ (save-restriction
+ ;; Activate narrowing in order to save
+ ;; BUFFER contents. Clear also the
+ ;; modification time; otherwise we might be
+ ;; interrupted by `verify-visited-file-modtime'.
+ (let ((buffer-undo-list t)
+ (inhibit-read-only t)
+ (mark (point-max))
+ (coding-system-for-write
+ (if (symbolp coding) coding (car coding)))
+ (coding-system-for-read
+ (if (symbolp coding) coding (cdr coding))))
+ (clear-visited-file-modtime)
+ (narrow-to-region (point-max) (point-max))
+ (catch 'suppress
+ ;; Set the pid of the remote shell. This is
+ ;; needed when sending signals remotely.
+ (let ((pid
+ (tramp-send-command-and-read v "echo $$")))
+ (setq p (tramp-get-connection-process v))
+ (process-put p 'remote-pid pid)
+ (tramp-set-connection-property
+ p "remote-pid" pid))
+ ;; Disable carriage return to newline
+ ;; translation. This does not work on
+ ;; macOS, see Bug#50748.
+ (when (and (memq connection-type '(nil pipe))
+ (not
+ (tramp-check-remote-uname v "Darwin")))
+ (tramp-send-command v "stty -icrnl"))
+ ;; `tramp-maybe-open-connection' and
+ ;; `tramp-send-command-and-read' could have
+ ;; trashed the connection buffer. Remove this.
+ (widen)
+ (delete-region mark (point-max))
+ (narrow-to-region (point-max) (point-max))
+ ;; Now do it.
+ (if command
+ ;; Send the command.
+ (tramp-send-command v command nil t) ; nooutput
+ ;; Check, whether a pty is associated.
+ (unless (process-get p 'remote-tty)
+ (tramp-error
+ v 'file-error
+ "pty association is not supported for `%s'"
+ name))))
+ ;; Set sentinel and filter.
+ (when sentinel
+ (set-process-sentinel p sentinel))
+ (when filter
+ (set-process-filter p filter))
+ (process-put p 'remote-command orig-command)
+ (tramp-set-connection-property
+ p "remote-command" orig-command)
+ ;; Set query flag and process marker for
+ ;; this process. We ignore errors,
+ ;; because the process could have finished
+ ;; already.
+ (ignore-errors
+ (set-process-query-on-exit-flag p (null noquery))
+ (set-marker (process-mark p) (point)))
+ ;; We must flush them here already;
+ ;; otherwise `delete-file' will fail.
+ (tramp-flush-connection-property v "process-name")
+ (tramp-flush-connection-property v "process-buffer")
+ ;; Kill stderr process and delete named pipe.
+ (when (bufferp stderr)
+ (add-function
+ :after (process-sentinel p)
+ (lambda (_proc _msg)
+ (ignore-errors
+ (while (accept-process-output
+ (get-buffer-process stderr) 0 nil t))
+ (delete-process (get-buffer-process stderr)))
+ (ignore-errors
+ (delete-file remote-tmpstderr)))))
+ ;; Return process.
+ p)))
+
+ ;; Save exit.
+ (if (string-prefix-p tramp-temp-buffer-name (buffer-name))
(ignore-errors
- (set-process-query-on-exit-flag p (null noquery))
- (set-marker (process-mark p) (point)))
- ;; Kill stderr process and delete named pipe.
- (when (bufferp stderr)
- (add-function
- :after (process-sentinel p)
- (lambda (_proc _msg)
- (ignore-errors
- (while (accept-process-output
- (get-buffer-process stderr) 0 nil t))
- (delete-process (get-buffer-process stderr)))
- (ignore-errors
- (delete-file remote-tmpstderr)))))
- ;; Return process.
- p)))
-
- ;; Save exit.
- (if (string-prefix-p tramp-temp-buffer-name (buffer-name))
- (ignore-errors
- (set-process-buffer p nil)
- (kill-buffer (current-buffer)))
- (set-buffer-modified-p bmp))
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")))))))))
+ (set-process-buffer p nil)
+ (kill-buffer (current-buffer)))
+ (set-buffer-modified-p bmp))))))))))))
(defun tramp-sh-get-signal-strings (vec)
"Strings to return by `process-file' in case of signals."
@@ -3013,7 +3080,7 @@ implementation will be used."
vec
(concat
"signal-strings-" (tramp-get-method-parameter vec 'tramp-remote-shell))
- (let ((default-directory (tramp-make-tramp-file-name vec 'localname))
+ (let ((default-directory (tramp-make-tramp-file-name vec 'noloc))
process-file-return-signal-string signals res result)
(setq signals
(append
@@ -3098,13 +3165,13 @@ 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))
+ (setq input (tramp-unquote-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))
+ tmpinput (tramp-make-tramp-file-name v input))
(copy-file infile tmpinput t)))
(when input (setq command (format "%s <%s" command input)))
@@ -3132,11 +3199,11 @@ implementation will be used."
(setcar (cdr destination) (expand-file-name (cadr destination)))
(if (tramp-equal-remote default-directory (cadr destination))
;; stderr is on the same remote host.
- (setq stderr (tramp-file-local-name (cadr destination)))
+ (setq stderr (tramp-unquote-file-local-name (cadr destination)))
;; stderr must be copied to remote host. The temporary
;; file must be deleted after execution.
(setq stderr (tramp-make-tramp-temp-file v)
- tmpstderr (tramp-make-tramp-file-name v stderr 'nohop))))
+ tmpstderr (tramp-make-tramp-file-name v stderr))))
;; stderr to be discarded.
((null (cadr destination))
(setq stderr (tramp-get-remote-null-device v)))))
@@ -3153,7 +3220,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 +3252,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.
@@ -3282,251 +3349,197 @@ implementation will be used."
(defun tramp-sh-handle-write-region
(start end filename &optional append visit lockname mustbenew)
"Like `write-region' for Tramp files."
- (setq filename (expand-file-name filename)
- lockname (file-truename (or lockname filename)))
- (with-parsed-tramp-file-name filename nil
- (when (and mustbenew (file-exists-p filename)
- (or (eq mustbenew 'excl)
- (not
- (y-or-n-p
- (format "File %s exists; overwrite anyway?" filename)))))
- (tramp-error v 'file-already-exists filename))
-
- (let ((file-locked (eq (file-locked-p lockname) t))
- (uid (or (file-attribute-user-id (file-attributes filename 'integer))
- (tramp-get-remote-uid v 'integer)))
- (gid (or (file-attribute-group-id (file-attributes filename 'integer))
- (tramp-get-remote-gid v 'integer))))
-
- ;; Lock file.
- (when (and (not (auto-save-file-name-p (file-name-nondirectory filename)))
- (file-remote-p lockname)
- (not file-locked))
- (setq file-locked t)
- ;; `lock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'lock-file lockname))
-
- (if (and (tramp-local-host-p v)
- ;; `file-writable-p' calls `file-expand-file-name'. We
- ;; cannot use `tramp-run-real-handler' therefore.
- (file-writable-p (file-name-directory localname))
- (or (file-directory-p localname)
- (file-writable-p localname)))
- ;; Short track: if we are on the local host, we can run directly.
- (let ((create-lockfiles (not file-locked)))
- (write-region start end localname append 'no-message lockname))
-
- (let* ((modes (tramp-default-file-modes
- filename (and (eq mustbenew 'excl) 'nofollow)))
- ;; We use this to save the value of
- ;; `last-coding-system-used' after writing the tmp
- ;; file. At the end of the function, we set
- ;; `last-coding-system-used' to this saved value. This
- ;; way, any intermediary coding systems used while
- ;; talking to the remote shell or suchlike won't hose
- ;; this variable. This approach was snarfed from
- ;; ange-ftp.el.
- coding-system-used
- ;; Write region into a tmp file. This isn't really
- ;; needed if we use an encoding function, but currently
- ;; we use it always because this makes the logic
- ;; simpler. We must also set `temporary-file-directory',
- ;; because it could point to a remote directory.
- (temporary-file-directory tramp-compat-temporary-file-directory)
- (tmpfile (or tramp-temp-buffer-file-name
- (tramp-compat-make-temp-file filename))))
-
- ;; If `append' is non-nil, we copy the file locally, and let
- ;; the native `write-region' implementation do the job.
- (when (and append (file-exists-p filename))
- (copy-file filename tmpfile 'ok))
-
- ;; We say `no-message' here because we don't want the
- ;; visited file modtime data to be clobbered from the temp
- ;; file. We call `set-visited-file-modtime' ourselves later
- ;; on. We must ensure that `file-coding-system-alist'
- ;; matches `tmpfile'.
- (let ((file-coding-system-alist
- (tramp-find-file-name-coding-system-alist filename tmpfile))
- create-lockfiles)
- (condition-case err
- (write-region start end tmpfile append 'no-message)
- ((error quit)
- (setq tramp-temp-buffer-file-name nil)
- (delete-file tmpfile)
- (signal (car err) (cdr err))))
-
- ;; Now, `last-coding-system-used' has the right value. Remember it.
- (setq coding-system-used last-coding-system-used))
-
- ;; The permissions of the temporary file should be set. If
- ;; FILENAME does not exist (eq modes nil) it has been
- ;; renamed to the backup file. This case `save-buffer'
- ;; handles permissions.
- ;; Ensure that it is still readable.
- (when modes
- (set-file-modes tmpfile (logior (or modes 0) #o0400)))
-
- ;; This is a bit lengthy due to the different methods
- ;; possible for file transfer. First, we check whether the
- ;; method uses an scp program. If so, we call it.
- ;; Otherwise, both encoding and decoding command must be
- ;; specified. However, if the method _also_ specifies an
- ;; encoding function, then that is used for encoding the
- ;; contents of the tmp file.
- (let* ((size (file-attribute-size (file-attributes tmpfile)))
- (rem-dec (tramp-get-inline-coding v "remote-decoding" size))
- (loc-enc (tramp-get-inline-coding v "local-encoding" size)))
- (cond
- ;; `copy-file' handles direct copy and out-of-band methods.
- ((or (tramp-local-host-p v)
- (tramp-method-out-of-band-p v size))
- (if (and (not (stringp start))
- (= (or end (point-max)) (point-max))
- (= (or start (point-min)) (point-min))
- (tramp-get-method-parameter v 'tramp-copy-keep-tmpfile))
- (progn
- (setq tramp-temp-buffer-file-name tmpfile)
- (condition-case err
- ;; We keep the local file for performance
- ;; reasons, useful for "rsync".
- (copy-file tmpfile filename t)
- ((error quit)
- (setq tramp-temp-buffer-file-name nil)
- (delete-file tmpfile)
- (signal (car err) (cdr err)))))
- (setq tramp-temp-buffer-file-name nil)
- ;; Don't rename, in order to keep context in SELinux.
- (unwind-protect
- (copy-file tmpfile filename t)
- (delete-file tmpfile))))
-
- ;; Use inline file transfer.
- (rem-dec
- ;; Encode tmpfile.
+ (tramp-skeleton-write-region start end filename append visit lockname mustbenew
+ (if (and (tramp-local-host-p v)
+ ;; `file-writable-p' calls `file-expand-file-name'. We
+ ;; cannot use `tramp-run-real-handler' therefore.
+ (file-writable-p (file-name-directory localname))
+ (or (file-directory-p localname)
+ (file-writable-p localname)))
+ ;; Short track: if we are on the local host, we can run directly.
+ (let ((create-lockfiles (not file-locked)))
+ (write-region start end localname append 'no-message lockname))
+
+ (let* ((modes (tramp-default-file-modes
+ filename (and (eq mustbenew 'excl) 'nofollow)))
+ ;; We use this to save the value of
+ ;; `last-coding-system-used' after writing the tmp file.
+ ;; At the end of the function, we set
+ ;; `last-coding-system-used' to this saved value. This
+ ;; way, any intermediary coding systems used while
+ ;; talking to the remote shell or suchlike won't hose
+ ;; this variable. This approach was snarfed from
+ ;; ange-ftp.el.
+ coding-system-used
+ ;; Write region into a tmp file. This isn't really
+ ;; needed if we use an encoding function, but currently
+ ;; we use it always because this makes the logic simpler.
+ ;; We must also set `temporary-file-directory', because
+ ;; it could point to a remote directory.
+ (temporary-file-directory
+ tramp-compat-temporary-file-directory)
+ (tmpfile (or tramp-temp-buffer-file-name
+ (tramp-compat-make-temp-file filename))))
+
+ ;; If `append' is non-nil, we copy the file locally, and let
+ ;; the native `write-region' implementation do the job.
+ (when (and append (file-exists-p filename))
+ (copy-file filename tmpfile 'ok))
+
+ ;; We say `no-message' here because we don't want the visited
+ ;; file modtime data to be clobbered from the temp file. We
+ ;; call `set-visited-file-modtime' ourselves later on. We
+ ;; must ensure that `file-coding-system-alist' matches
+ ;; `tmpfile'.
+ (let ((file-coding-system-alist
+ (tramp-find-file-name-coding-system-alist filename tmpfile))
+ create-lockfiles)
+ (condition-case err
+ (write-region start end tmpfile append 'no-message)
+ ((error quit)
+ (setq tramp-temp-buffer-file-name nil)
+ (delete-file tmpfile)
+ (signal (car err) (cdr err))))
+
+ ;; Now, `last-coding-system-used' has the right value.
+ ;; Remember it.
+ (setq coding-system-used last-coding-system-used))
+
+ ;; The permissions of the temporary file should be set. If
+ ;; FILENAME does not exist (eq modes nil) it has been renamed
+ ;; to the backup file. This case `save-buffer' handles
+ ;; permissions. Ensure that it is still readable.
+ (when modes
+ (set-file-modes tmpfile (logior (or modes 0) #o0400)))
+
+ ;; This is a bit lengthy due to the different methods possible
+ ;; for file transfer. First, we check whether the method uses
+ ;; an scp program. If so, we call it. Otherwise, both
+ ;; encoding and decoding command must be specified. However,
+ ;; if the method _also_ specifies an encoding function, then
+ ;; that is used for encoding the contents of the tmp file.
+ (let* ((size (file-attribute-size (file-attributes tmpfile)))
+ (rem-dec (tramp-get-inline-coding v "remote-decoding" size))
+ (loc-enc (tramp-get-inline-coding v "local-encoding" size)))
+ (cond
+ ;; `copy-file' handles direct copy and out-of-band methods.
+ ((or (tramp-local-host-p v)
+ (tramp-method-out-of-band-p v size))
+ (if (and (not (stringp start))
+ (= (or end (point-max)) (point-max))
+ (= (or start (point-min)) (point-min))
+ (tramp-get-method-parameter
+ v 'tramp-copy-keep-tmpfile))
+ (progn
+ (setq tramp-temp-buffer-file-name tmpfile)
+ (condition-case err
+ ;; We keep the local file for performance
+ ;; reasons, useful for "rsync".
+ (copy-file tmpfile filename t)
+ ((error quit)
+ (setq tramp-temp-buffer-file-name nil)
+ (delete-file tmpfile)
+ (signal (car err) (cdr err)))))
+ (setq tramp-temp-buffer-file-name nil)
+ ;; Don't rename, in order to keep context in SELinux.
(unwind-protect
- (with-temp-buffer
- (set-buffer-multibyte nil)
- ;; Use encoding function or command.
- (with-tramp-progress-reporter
- v 3 (format-message
- "Encoding local file `%s' using `%s'"
- tmpfile loc-enc)
- (if (functionp loc-enc)
- ;; The following `let' is a workaround for
- ;; the base64.el that comes with pgnus-0.84.
- ;; If both of the following conditions are
- ;; satisfied, it tries to write to a local
- ;; file in default-directory, but at this
- ;; point, default-directory is remote.
- ;; (`call-process-region' can't write to
- ;; remote files, it seems.) The file in
- ;; question is a tmp file anyway.
- (let ((coding-system-for-read 'binary)
- (default-directory
- tramp-compat-temporary-file-directory))
- (insert-file-contents-literally tmpfile)
- (funcall loc-enc (point-min) (point-max)))
-
- (unless (zerop (tramp-call-local-coding-command
- loc-enc tmpfile t))
- (tramp-error
- v 'file-error
- (concat "Cannot write to `%s', "
- "local encoding command `%s' failed")
- filename loc-enc))))
-
- ;; Send buffer into remote decoding command which
- ;; writes to remote file. Because this happens on
- ;; the remote host, we cannot use the function.
- (with-tramp-progress-reporter
- v 3 (format-message
- "Decoding remote file `%s' using `%s'"
- filename rem-dec)
- (goto-char (point-max))
- (unless (bolp) (newline))
- (tramp-send-command
- v
- (format
- (concat rem-dec " <<'%s'\n%s%s")
- (tramp-shell-quote-argument localname)
- tramp-end-of-heredoc
- (buffer-string)
- tramp-end-of-heredoc))
- (tramp-barf-unless-okay
- v nil
- "Couldn't write region to `%s', decode using `%s' failed"
- filename rem-dec)
- ;; When `file-precious-flag' is set, the region is
- ;; written to a temporary file. Check that the
- ;; checksum is equal to that from the local tmpfile.
- (when file-precious-flag
- (erase-buffer)
- (and
- ;; cksum runs locally, if possible.
- (zerop (tramp-call-process v "cksum" tmpfile t))
- ;; cksum runs remotely.
- (tramp-send-command-and-check
- v
- (format
- "cksum <%s" (tramp-shell-quote-argument localname)))
- ;; ... they are different.
- (not
- (string-equal
- (buffer-string)
- (tramp-get-buffer-string (tramp-get-buffer v))))
- (tramp-error
- v 'file-error
- (concat "Couldn't write region to `%s',"
- " decode using `%s' failed")
- filename rem-dec)))))
+ (copy-file tmpfile filename t)
+ (delete-file tmpfile))))
- ;; Save exit.
- (delete-file tmpfile)))
-
- ;; That's not expected.
- (t
- (tramp-error
- v 'file-error
- (concat "Method `%s' should specify both encoding and "
- "decoding command or an scp program")
- method))))
+ ;; Use inline file transfer.
+ (rem-dec
+ ;; Encode tmpfile.
+ (unwind-protect
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ ;; Use encoding function or command.
+ (with-tramp-progress-reporter
+ v 3 (format-message
+ "Encoding local file `%s' using `%s'"
+ tmpfile loc-enc)
+ (if (functionp loc-enc)
+ ;; The following `let' is a workaround for the
+ ;; base64.el that comes with pgnus-0.84. If
+ ;; both of the following conditions are
+ ;; satisfied, it tries to write to a local
+ ;; file in default-directory, but at this
+ ;; point, default-directory is remote.
+ ;; (`call-process-region' can't write to
+ ;; remote files, it seems.) The file in
+ ;; question is a tmp file anyway.
+ (let ((coding-system-for-read 'binary)
+ (default-directory
+ tramp-compat-temporary-file-directory))
+ (insert-file-contents-literally tmpfile)
+ (funcall loc-enc (point-min) (point-max)))
+
+ (unless (zerop (tramp-call-local-coding-command
+ loc-enc tmpfile t))
+ (tramp-error
+ v 'file-error
+ (concat "Cannot write to `%s', "
+ "local encoding command `%s' failed")
+ filename loc-enc))))
+
+ ;; Send buffer into remote decoding command which
+ ;; writes to remote file. Because this happens on
+ ;; the remote host, we cannot use the function.
+ (with-tramp-progress-reporter
+ v 3 (format-message
+ "Decoding remote file `%s' using `%s'"
+ filename rem-dec)
+ (goto-char (point-max))
+ (unless (bolp) (newline))
+ (tramp-send-command
+ v
+ (format
+ (concat rem-dec " <<'%s'\n%s%s")
+ (tramp-shell-quote-argument localname)
+ tramp-end-of-heredoc
+ (buffer-string)
+ tramp-end-of-heredoc))
+ (tramp-barf-unless-okay
+ v nil
+ "Couldn't write region to `%s', decode using `%s' failed"
+ filename rem-dec)
+ ;; When `file-precious-flag' is set, the region is
+ ;; written to a temporary file. Check that the
+ ;; checksum is equal to that from the local tmpfile.
+ (when file-precious-flag
+ (erase-buffer)
+ (and
+ ;; cksum runs locally, if possible.
+ (zerop (tramp-call-process v "cksum" tmpfile t))
+ ;; cksum runs remotely.
+ (tramp-send-command-and-check
+ v
+ (format
+ "cksum <%s"
+ (tramp-shell-quote-argument localname)))
+ ;; ... they are different.
+ (not
+ (string-equal
+ (buffer-string)
+ (tramp-get-buffer-string (tramp-get-buffer v))))
+ (tramp-error
+ v 'file-error
+ "Couldn't write region to `%s', decode using `%s' failed"
+ filename rem-dec)))))
- ;; Make `last-coding-system-used' have the right value.
- (when coding-system-used
- (setq last-coding-system-used coding-system-used))))
+ ;; Save exit.
+ (delete-file tmpfile)))
- (tramp-flush-file-properties v localname)
+ ;; That's not expected.
+ (t
+ (tramp-error
+ v 'file-error
+ (concat "Method `%s' should specify both encoding and "
+ "decoding command or an scp program")
+ method))))
- ;; We must protect `last-coding-system-used', now we have set it
- ;; to its correct value.
- (let (last-coding-system-used (need-chown t))
- ;; Set file modification time.
- (when (or (eq visit t) (stringp visit))
- (let ((file-attr (file-attributes filename 'integer)))
- (set-visited-file-modtime
- ;; We must pass modtime explicitly, because FILENAME can
- ;; be different from (buffer-file-name), f.e. if
- ;; `file-precious-flag' is set.
- (or (file-attribute-modification-time file-attr)
- (current-time)))
- (when (and (= (file-attribute-user-id file-attr) uid)
- (= (file-attribute-group-id file-attr) gid))
- (setq need-chown nil))))
-
- ;; Set the ownership.
- (when need-chown
- (tramp-set-file-uid-gid filename uid gid))
-
- ;; Unlock file.
- (when file-locked
- ;; `unlock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'unlock-file lockname))
-
- (when (and (null noninteractive)
- (or (eq visit t) (string-or-null-p visit)))
- (tramp-message v 0 "Wrote %s" filename))
- (run-hooks 'tramp-handle-write-region-hook)))))
+ ;; Make `last-coding-system-used' have the right value.
+ (when coding-system-used
+ (setq last-coding-system-used coding-system-used))))))
(defvar tramp-vc-registered-file-names nil
"List used to collect file names, which are checked during `vc-registered'.")
@@ -3650,8 +3663,7 @@ Fall back to normal file name handler if no Tramp handler exists."
(defun tramp-sh-file-name-handler-p (vec)
"Whether VEC uses a method from `tramp-sh-file-name-handler'."
(and (assoc (tramp-file-name-method vec) tramp-methods)
- (eq (tramp-find-foreign-file-name-handler
- (tramp-make-tramp-file-name vec nil 'nohop))
+ (eq (tramp-find-foreign-file-name-handler vec)
'tramp-sh-file-name-handler)))
;; This must be the last entry, because `identity' always matches.
@@ -3964,7 +3976,7 @@ Only send the definition if it has not already been done."
;; We cannot let-bind (tramp-get-connection-process vec) because it
;; might be nil.
(let ((scripts (tramp-get-connection-property
- (tramp-get-connection-process vec) "scripts" nil)))
+ (tramp-get-connection-process vec) "scripts")))
(unless (member name scripts)
(with-tramp-progress-reporter
vec 5 (format-message "Sending script `%s'" name)
@@ -3997,9 +4009,6 @@ Returns the exit code of the `test' program."
switch
(tramp-shell-quote-argument localname)))))
-(defconst tramp-sunos-unames (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
- "Regexp to determine remote SunOS.")
-
(defun tramp-find-executable
(vec progname dirlist &optional ignore-tilde ignore-path)
"Search for PROGNAME in $PATH and all directories mentioned in DIRLIST.
@@ -4105,13 +4114,10 @@ file exists and nonzero exit status otherwise."
;; The algorithm is as follows: we try a list of several commands.
;; For each command, we first run `$cmd /' -- this should return
;; true, as the root directory always exists. And then we run
- ;; `$cmd /this\ file\ does\ not\ exist ', hoping that the file indeed
- ;; does not exist. This should return false. We use the first
- ;; command we find that seems to work.
+ ;; `$cmd /\ this\ file\ does\ not\ exist\ ', hoping that the file
+ ;; indeed does not exist. This should return false. We use the
+ ;; first command we find that seems to work.
;; The list of commands to try is as follows:
- ;; `ls -d' This works on most systems, but NetBSD 1.4
- ;; has a bug: `ls' always returns zero exit
- ;; status, even for files which don't exist.
;; `test -e' Some Bourne shells have a `test' builtin
;; which does not know the `-e' option.
;; `/bin/test -e' For those, the `test' binary on disk normally
@@ -4119,6 +4125,10 @@ file exists and nonzero exit status otherwise."
;; is sometimes `/bin/test' and sometimes it's
;; `/usr/bin/test'.
;; `/usr/bin/test -e' In case `/bin/test' does not exist.
+ ;; `ls -d' This works on most systems, but NetBSD 1.4
+ ;; has a bug: `ls' always returns zero exit
+ ;; status, even for files which don't exist.
+
(unless (or
(ignore-errors
(and (setq result (format "%s -e" (tramp-get-test-command vec)))
@@ -4216,7 +4226,7 @@ file exists and nonzero exit status otherwise."
(defun tramp-find-shell (vec)
"Open a shell on the remote host which groks tilde expansion."
;; If we are in `make-process', we don't need another shell.
- (unless (tramp-get-connection-property vec "process-name" nil)
+ (unless (tramp-get-connection-property vec "process-name")
(with-current-buffer (tramp-get-buffer vec)
(let ((default-shell (tramp-get-method-parameter vec 'tramp-remote-shell))
shell)
@@ -4313,11 +4323,10 @@ process to set up. VEC specifies the connection."
;; connection properties. We start again with
;; `tramp-maybe-open-connection', it will be caught there.
(tramp-message vec 5 "Checking system information")
- (let* ((old-uname (tramp-get-connection-property vec "uname" nil))
+ (let* ((old-uname (tramp-get-connection-property vec "uname"))
(uname
;; If we are in `make-process', we don't need to recompute.
- (if (and old-uname
- (tramp-get-connection-property vec "process-name" nil))
+ (if (and old-uname (tramp-get-connection-property vec "process-name"))
old-uname
(tramp-set-connection-property
vec "uname"
@@ -4765,36 +4774,33 @@ Goes through the list `tramp-inline-compress-commands'."
(t (setq tramp-ssh-controlmaster-options "")
(let ((case-fold-search t))
(ignore-errors
- (when (executable-find "ssh")
- (with-tramp-progress-reporter
- vec 4 "Computing ControlMaster options"
- (with-temp-buffer
- (tramp-call-process vec "ssh" nil t nil "-o" "ControlMaster")
- (goto-char (point-min))
- (when (search-forward-regexp "missing.+argument" nil t)
- (setq tramp-ssh-controlmaster-options
- "-o ControlMaster=auto")))
- (unless (zerop (length tramp-ssh-controlmaster-options))
- (with-temp-buffer
- ;; We use a non-existing IP address, in order to
- ;; avoid useless connections, and DNS timeouts.
- ;; Setting ConnectTimeout is needed since OpenSSH 7.
- (tramp-call-process
- vec "ssh" nil t nil
- "-o" "ConnectTimeout=1" "-o" "ControlPath=%C" "0.0.0.1")
- (goto-char (point-min))
+ (with-tramp-progress-reporter
+ vec 4 "Computing ControlMaster options"
+ ;; We use a non-existing IP address, in order to avoid
+ ;; useless connections, and DNS timeouts.
+ (when (zerop
+ (tramp-call-process
+ vec "ssh" nil nil nil
+ "-G" "-o" "ControlMaster=auto" "0.0.0.1"))
+ (setq tramp-ssh-controlmaster-options
+ "-o ControlMaster=auto")
+ (if (zerop
+ (tramp-call-process
+ vec "ssh" nil nil nil
+ "-G" "-o" "ControlPath=tramp.%C" "0.0.0.1"))
(setq tramp-ssh-controlmaster-options
(concat tramp-ssh-controlmaster-options
- (if (search-forward-regexp "unknown.+key" nil t)
- " -o ControlPath='tramp.%%r@%%h:%%p'"
- " -o ControlPath='tramp.%%C'"))))
- (with-temp-buffer
- (tramp-call-process vec "ssh" nil t nil "-o" "ControlPersist")
- (goto-char (point-min))
- (when (search-forward-regexp "missing.+argument" nil t)
- (setq tramp-ssh-controlmaster-options
- (concat tramp-ssh-controlmaster-options
- " -o ControlPersist=no")))))))))
+ " -o ControlPath=tramp.%%C"))
+ (setq tramp-ssh-controlmaster-options
+ (concat tramp-ssh-controlmaster-options
+ " -o ControlPath=tramp.%%r@%%h:%%p")))
+ (when (zerop
+ (tramp-call-process
+ vec "ssh" nil nil nil
+ "-G" "-o" "ControlPersist=no" "0.0.0.1"))
+ (setq tramp-ssh-controlmaster-options
+ (concat tramp-ssh-controlmaster-options
+ " -o ControlPersist=no")))))))
tramp-ssh-controlmaster-options)))
(defun tramp-scp-strict-file-name-checking (vec)
@@ -4808,7 +4814,7 @@ Goes through the list `tramp-inline-compress-commands'."
((stringp tramp-scp-strict-file-name-checking)
tramp-scp-strict-file-name-checking)
- ;; Determine the options.
+ ;; Determine the option.
(t (setq tramp-scp-strict-file-name-checking "")
(let ((case-fold-search t))
(ignore-errors
@@ -4824,11 +4830,111 @@ Goes through the list `tramp-inline-compress-commands'."
(setq tramp-scp-strict-file-name-checking "-T")))))))
tramp-scp-strict-file-name-checking)))
+(defun tramp-scp-force-scp-protocol (vec)
+ "Return the force scp protocol argument of the local scp."
+ (cond
+ ;; No options to be computed.
+ ((null (assoc "%y" (tramp-get-method-parameter vec 'tramp-copy-args)))
+ "")
+
+ ;; There is already a value to be used.
+ ((stringp tramp-scp-force-scp-protocol)
+ tramp-scp-force-scp-protocol)
+
+ ;; Determine the options.
+ (t (setq tramp-scp-force-scp-protocol "")
+ (let ((case-fold-search t))
+ (ignore-errors
+ (when (executable-find "scp")
+ (with-tramp-progress-reporter
+ vec 4 "Computing force scp protocol argument"
+ (with-temp-buffer
+ (tramp-call-process vec "scp" nil t nil "-O")
+ (goto-char (point-min))
+ (unless
+ (search-forward-regexp
+ "\\(illegal\\|unknown\\) option -- O" nil t)
+ (setq tramp-scp-force-scp-protocol "-O")))))))
+ tramp-scp-force-scp-protocol)))
+
+(defun tramp-scp-direct-remote-copying (vec1 vec2)
+ "Return the direct remote copying argument of the local scp."
+ (cond
+ ((or (not tramp-use-scp-direct-remote-copying) (null vec1) (null vec2)
+ (not (tramp-get-process vec1))
+ (not (equal (tramp-file-name-port vec1) (tramp-file-name-port vec2)))
+ (null (assoc "%z" (tramp-get-method-parameter vec1 'tramp-copy-args)))
+ (null (assoc "%z" (tramp-get-method-parameter vec2 'tramp-copy-args))))
+ "")
+
+ ((let ((case-fold-search t))
+ (and
+ ;; Check, whether "scp" supports "-R" option.
+ (with-tramp-connection-property nil "scp-R"
+ (when (executable-find "scp")
+ (with-temp-buffer
+ (tramp-call-process vec1 "scp" nil t nil "-R")
+ (goto-char (point-min))
+ (not (search-forward-regexp
+ "\\(illegal\\|unknown\\) option -- R" nil 'noerror)))))
+
+ ;; Check, that RemoteCommand is not used.
+ (with-tramp-connection-property
+ (tramp-get-process vec1) "ssh-remote-command"
+ (let ((command `("ssh" "-G" ,(tramp-file-name-host vec1))))
+ (with-temp-buffer
+ (tramp-call-process
+ vec1 tramp-encoding-shell nil t nil
+ tramp-encoding-command-switch
+ (mapconcat #'identity command " "))
+ (goto-char (point-min))
+ (not (search-forward "remotecommand" nil 'noerror)))))
+
+ ;; Check hostkeys.
+ (with-tramp-connection-property
+ (tramp-get-process vec1)
+ (concat "direct-remote-copying-"
+ (tramp-make-tramp-file-name vec2 'noloc))
+ (let ((command
+ (append
+ `("ssh" "-G" ,(tramp-file-name-host vec2) "|"
+ "grep" "-i" "^hostname" "|" "cut" "-d\" \"" "-f2" "|"
+ "ssh-keyscan" "-f" "-")
+ (when (tramp-file-name-port vec2)
+ `("-p" ,(tramp-file-name-port vec2)))))
+ found string)
+ (with-temp-buffer
+ ;; Check hostkey of VEC2, seen from VEC1.
+ (tramp-send-command vec1 (mapconcat #'identity command " "))
+ ;; Check hostkey of VEC2, seen locally.
+ (tramp-call-process
+ vec1 tramp-encoding-shell nil t nil tramp-encoding-command-switch
+ (mapconcat #'identity command " "))
+ (goto-char (point-min))
+ (while (and (not found) (not (eobp)))
+ (setq string
+ (buffer-substring
+ (line-beginning-position) (line-end-position))
+ string
+ (and
+ (string-match "^[^# ]+ \\S-+ \\(\\S-+\\)$" string)
+ (match-string 1 string))
+ found
+ (and string
+ (with-current-buffer (tramp-get-buffer vec1)
+ (goto-char (point-min))
+ (search-forward string nil 'noerror))))
+ (forward-line))
+ found)))))
+ "-R")
+
+ (t "-3")))
+
(defun tramp-timeout-session (vec)
"Close the connection VEC after a session timeout.
If there is just some editing, retry it after 5 seconds."
(if (and (tramp-get-connection-property
- (tramp-get-connection-process vec) "locked" nil)
+ (tramp-get-connection-process vec) "locked")
(tramp-file-name-equal-p vec (car tramp-current-connection)))
(progn
(tramp-message
@@ -4847,13 +4953,14 @@ connection if a previous connection has died for some reason."
(throw 'non-essential 'non-essential))
(let ((p (tramp-get-connection-process vec))
- (process-name (tramp-get-connection-property vec "process-name" nil))
+ (process-name (tramp-get-connection-property vec "process-name"))
(process-environment (copy-sequence process-environment))
(pos (with-current-buffer (tramp-get-connection-buffer vec) (point))))
;; If Tramp opens the same connection within a short time frame,
;; there is a problem. We shall signal this.
(unless (or (process-live-p p)
+ (and (processp p) (not non-essential))
(not (tramp-file-name-equal-p
vec (car tramp-current-connection)))
(time-less-p
@@ -4917,8 +5024,7 @@ connection if a previous connection has died for some reason."
(tramp-error vec 'file-error "`tramp-encoding-shell' not set"))
(let* ((current-host tramp-system-name)
(target-alist (tramp-compute-multi-hops vec))
- ;; Needed for `tramp-get-remote-null-device'.
- (previous-hop nil)
+ (previous-hop tramp-null-hop)
;; We will apply `tramp-ssh-controlmaster-options'
;; only for the first hop.
(options (tramp-ssh-controlmaster-options vec))
@@ -5003,9 +5109,14 @@ connection if a previous connection has died for some reason."
;; Set password prompt vector.
(tramp-set-connection-property
p "password-vector"
- (make-tramp-file-name
- :method l-method :user l-user :domain l-domain
- :host l-host :port l-port))
+ (if (tramp-get-method-parameter
+ hop 'tramp-password-previous-hop)
+ (let ((pv (copy-tramp-file-name previous-hop)))
+ (setf (tramp-file-name-method pv) l-method)
+ pv)
+ (make-tramp-file-name
+ :method l-method :user l-user :domain l-domain
+ :host l-host :port l-port)))
;; Set session timeout.
(when (tramp-get-method-parameter
@@ -5056,9 +5167,9 @@ connection if a previous connection has died for some reason."
previous-hop hop)))
;; Activate session timeout.
- (when (tramp-get-connection-property p "session-timeout" nil)
+ (when (tramp-get-connection-property p "session-timeout")
(run-at-time
- (tramp-get-connection-property p "session-timeout" nil) nil
+ (tramp-get-connection-property p "session-timeout") nil
#'tramp-timeout-session vec))
;; Make initial shell settings.
@@ -5080,7 +5191,7 @@ is meant to be used from `tramp-maybe-open-connection' only. The
function waits for output unless NOOUTPUT is set."
(unless neveropen (tramp-maybe-open-connection vec))
(let ((p (tramp-get-connection-process vec)))
- (when (tramp-get-connection-property p "remote-echo" nil)
+ (when (tramp-get-connection-property p "remote-echo")
;; We mark the command string that it can be erased in the output buffer.
(tramp-set-connection-property p "check-remote-echo" t)
;; If we put `tramp-echo-mark' after a trailing newline (which
@@ -5441,7 +5552,7 @@ Nonexistent directories are removed from spec."
(lambda (x)
(and
(stringp x)
- (file-directory-p (tramp-make-tramp-file-name vec x 'nohop))
+ (file-directory-p (tramp-make-tramp-file-name vec x))
x))
remote-path))))))
@@ -5830,6 +5941,12 @@ This command is returned only if `delete-by-moving-to-trash' is non-nil."
command))
(delete-file tmpfile)))))
+(defun tramp-get-remote-dev-tty (vec)
+ "Check, whether remote /dev/tty is usable."
+ (with-tramp-connection-property vec "dev-tty"
+ (tramp-send-command-and-check
+ vec "echo </dev/tty")))
+
;; Some predefined connection properties.
(defun tramp-get-inline-compress (vec prop size)
"Return the compress command related to PROP.
@@ -5841,7 +5958,7 @@ If no corresponding command is found, nil is returned."
(> size tramp-inline-compress-start-size))
(with-tramp-connection-property (tramp-get-process vec) prop
(tramp-find-inline-compress vec)
- (tramp-get-connection-property (tramp-get-process vec) prop nil))))
+ (tramp-get-connection-property (tramp-get-process vec) prop))))
(defun tramp-get-inline-coding (vec prop size)
"Return the coding command related to PROP.
@@ -5861,7 +5978,7 @@ function cell is returned to be applied on a buffer."
(let ((coding
(with-tramp-connection-property (tramp-get-process vec) prop
(tramp-find-inline-encoding vec)
- (tramp-get-connection-property (tramp-get-process vec) prop nil)))
+ (tramp-get-connection-property (tramp-get-process vec) prop)))
(prop1 (if (tramp-compat-string-search "encoding" prop)
"inline-compress" "inline-decompress"))
compress)
@@ -5977,9 +6094,6 @@ function cell is returned to be applied on a buffer."
;;
;; * Use lsh instead of ssh. (Alfred M. Szmidt)
;;
-;; * Optimize out-of-band copying when both methods are scp-like (not
-;; rsync).
-;;
;; * Keep a second connection open for out-of-band methods like scp or
;; rsync.
;;
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index c5f423fa3f0..b717c4dcc38 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -274,6 +274,7 @@ See `tramp-actions-before-shell' for more info.")
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-smb-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -283,6 +284,7 @@ See `tramp-actions-before-shell' for more info.")
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-smb-handle-make-symbolic-link)
+ (process-attributes . ignore)
(process-file . tramp-smb-handle-process-file)
(rename-file . tramp-smb-handle-rename-file)
(set-file-acl . tramp-smb-handle-set-file-acl)
@@ -294,6 +296,7 @@ See `tramp-actions-before-shell' for more info.")
(start-file-process . tramp-smb-handle-start-file-process)
(substitute-in-file-name . tramp-smb-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . tramp-smb-handle-get-home-directory)
(tramp-get-remote-gid . ignore)
(tramp-get-remote-uid . ignore)
(tramp-set-file-uid-gid . ignore)
@@ -383,14 +386,13 @@ arguments to pass to the OPERATION."
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
(tramp-flush-file-properties v2 v2-localname)
- (unless
- (tramp-smb-send-command
- v1
- (format
- "%s \"%s\" \"%s\""
- (if (tramp-smb-get-cifs-capabilities v1) "link" "hardlink")
- (tramp-smb-get-localname v1)
- (tramp-smb-get-localname v2)))
+ (unless (tramp-smb-send-command
+ v1
+ (format
+ "%s %s %s"
+ (if (tramp-smb-get-cifs-capabilities v1) "link" "hardlink")
+ (tramp-smb-shell-quote-localname v1)
+ (tramp-smb-shell-quote-localname v2)))
(tramp-error
v2 'file-error
"error with add-name-to-file, see buffer `%s' for details"
@@ -517,50 +519,50 @@ arguments to pass to the OPERATION."
"tar qx -")))))
(unwind-protect
- (with-temp-buffer
- ;; Set the transfer process properties.
- (tramp-set-connection-property
- v "process-name" (buffer-name (current-buffer)))
- (tramp-set-connection-property
- v "process-buffer" (current-buffer))
-
- (when t1
- ;; The smbclient tar command creates always
- ;; complete paths. We must emulate the
- ;; directory structure, and symlink to the
- ;; real target.
- (make-directory
- (expand-file-name
- ".." (concat tmpdir localname))
- 'parents)
- (make-symbolic-link
- newname
- (directory-file-name (concat tmpdir localname))))
-
- ;; Use an asynchronous processes. By this,
- ;; password can be handled.
- (let* ((default-directory tmpdir)
- (p (apply
- #'start-process
- (tramp-get-connection-name v)
- (tramp-get-connection-buffer v)
- tramp-smb-program args)))
-
- (tramp-message
- v 6 "%s" (string-join (process-command p) " "))
- (process-put p 'vector v)
- (process-put p 'adjust-window-size-function #'ignore)
- (set-process-query-on-exit-flag p nil)
- (tramp-process-actions
- p v nil tramp-smb-actions-with-tar)
-
- (while (process-live-p p)
- (sleep-for 0.1))
- (tramp-message v 6 "\n%s" (buffer-string))))
-
- ;; Reset the transfer process properties.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ (with-temp-buffer
+ ;; Set the transfer process properties.
+ (tramp-set-connection-property
+ v "process-name" (buffer-name (current-buffer)))
+ (tramp-set-connection-property
+ v "process-buffer" (current-buffer))
+
+ (when t1
+ ;; The smbclient tar command creates
+ ;; always complete paths. We must emulate
+ ;; the directory structure, and symlink to
+ ;; the real target.
+ (make-directory
+ (expand-file-name
+ ".." (concat tmpdir localname))
+ 'parents)
+ (make-symbolic-link
+ newname
+ (directory-file-name (concat tmpdir localname))))
+
+ ;; Use an asynchronous processes. By this,
+ ;; password can be handled.
+ (let* ((default-directory tmpdir)
+ (p (apply
+ #'start-process
+ (tramp-get-connection-name v)
+ (tramp-get-connection-buffer v)
+ tramp-smb-program args)))
+
+ (tramp-message
+ v 6 "%s" (string-join (process-command p) " "))
+ (process-put p 'vector v)
+ (process-put p 'adjust-window-size-function #'ignore)
+ (set-process-query-on-exit-flag p nil)
+ (tramp-process-actions
+ p v nil tramp-smb-actions-with-tar)
+
+ (while (process-live-p p)
+ (sleep-for 0.1))
+ (tramp-message v 6 "\n%s" (buffer-string))))))
+
+ ;; Save exit.
(when t1 (delete-directory tmpdir 'recursive))))
;; Handle KEEP-DATE argument.
@@ -606,7 +608,11 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(if (tramp-tramp-file-p filename) filename newname))
'file-missing filename))
- (if-let ((tmpfile (file-local-copy filename)))
+ ;; `file-local-copy' returns a file name also for a local file
+ ;; with `jka-compr-handler', so we cannot trust its result as
+ ;; indication for a remote file name.
+ (if-let ((tmpfile
+ (and (file-remote-p filename) (file-local-copy filename))))
;; Remote filename.
(condition-case err
(rename-file tmpfile newname ok-if-already-exists)
@@ -634,9 +640,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(tramp-error
v 'file-error "Target `%s' must contain a share name" newname))
(unless (tramp-smb-send-command
- v (format "put \"%s\" \"%s\""
- (tramp-compat-file-name-unquote filename)
- (tramp-smb-get-localname v)))
+ v (format "put %s %s"
+ (tramp-smb-shell-quote-argument filename)
+ (tramp-smb-shell-quote-localname v)))
(tramp-error
v 'file-error "Cannot copy `%s' to `%s'" filename newname)))))
@@ -665,10 +671,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(tramp-flush-directory-properties v localname)
(unless (tramp-smb-send-command
v (format
- "%s \"%s\""
+ "%s %s"
(if (tramp-smb-get-cifs-capabilities v)
"posix_rmdir" "rmdir")
- (tramp-smb-get-localname v)))
+ (tramp-smb-shell-quote-localname v)))
;; Error.
(with-current-buffer (tramp-get-connection-buffer v)
(goto-char (point-min))
@@ -691,9 +697,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(move-file-to-trash filename)
(unless (tramp-smb-send-command
v (format
- "%s \"%s\""
+ "%s %s"
(if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
- (tramp-smb-get-localname v)))
+ (tramp-smb-shell-quote-localname v)))
;; Error.
(with-current-buffer (tramp-get-connection-buffer v)
(goto-char (point-min))
@@ -742,28 +748,33 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(setq name (tramp-compat-file-name-concat dir name)))
;; If NAME is not a Tramp file, run the real handler.
(if (not (tramp-tramp-file-p name))
- (tramp-run-real-handler #'expand-file-name (list name nil))
+ (tramp-run-real-handler #'expand-file-name (list name))
;; Dissect NAME.
(with-parsed-tramp-file-name name nil
- ;; Tilde expansion if necessary. We use the user name as share,
- ;; which is often the case in domains.
- (when (string-match "\\`/?~\\([^/]*\\)" localname)
- (setq localname
- (replace-match
- (if (zerop (length (match-string 1 localname)))
- user
- (match-string 1 localname))
- nil nil localname)))
- ;; Make the file name absolute.
+ ;; Tilde expansion if necessary.
+ (when (string-match "\\`~\\([^/]*\\)\\(.*\\)\\'" localname)
+ (let ((uname (match-string 1 localname))
+ (fname (match-string 2 localname))
+ hname)
+ (when (zerop (length uname))
+ (setq uname user))
+ (when (setq hname (tramp-get-home-directory v uname))
+ (setq localname (concat hname fname)))))
+ ;; Tilde expansion is not possible.
+ (when (and (not tramp-tolerate-tilde)
+ (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname))
+ (tramp-error v 'file-error "Cannot expand tilde in file `%s'" name))
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "/" localname)))
;; Do not keep "/..".
(when (string-match-p "^/\\.\\.?$" localname)
(setq localname "/"))
- ;; No tilde characters in file name, do normal
- ;; `expand-file-name' (this does "/./" and "/../").
+ ;; Do normal `expand-file-name' (this does "/./" and "/../"),
+ ;; unless there are tilde characters in file name.
(tramp-make-tramp-file-name
- v (tramp-run-real-handler #'expand-file-name (list localname))))))
+ v (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ localname
+ (tramp-run-real-handler #'expand-file-name (list localname)))))))
(defun tramp-smb-action-get-acl (proc vec)
"Read ACL data from connection buffer."
@@ -813,33 +824,31 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(concat "2>" (tramp-get-remote-null-device v)))))
(unwind-protect
- (with-temp-buffer
- ;; Set the transfer process properties.
- (tramp-set-connection-property
- v "process-name" (buffer-name (current-buffer)))
- (tramp-set-connection-property
- v "process-buffer" (current-buffer))
-
- ;; Use an asynchronous process. By this, password can
- ;; be handled.
- (let ((p (apply
- #'start-process
- (tramp-get-connection-name v)
- (tramp-get-connection-buffer v)
- tramp-smb-acl-program args)))
-
- (tramp-message
- v 6 "%s" (string-join (process-command p) " "))
- (process-put p 'vector v)
- (process-put p 'adjust-window-size-function #'ignore)
- (set-process-query-on-exit-flag p nil)
- (tramp-process-actions p v nil tramp-smb-actions-get-acl)
- (when (> (point-max) (point-min))
- (substring-no-properties (buffer-string)))))
-
- ;; Reset the transfer process properties.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer"))))))))
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ (with-temp-buffer
+ ;; Set the transfer process properties.
+ (tramp-set-connection-property
+ v "process-name" (buffer-name (current-buffer)))
+ (tramp-set-connection-property
+ v "process-buffer" (current-buffer))
+
+ ;; Use an asynchronous process. By this,
+ ;; password can be handled.
+ (let ((p (apply
+ #'start-process
+ (tramp-get-connection-name v)
+ (tramp-get-connection-buffer v)
+ tramp-smb-acl-program args)))
+
+ (tramp-message
+ v 6 "%s" (string-join (process-command p) " "))
+ (process-put p 'vector v)
+ (process-put p 'adjust-window-size-function #'ignore)
+ (set-process-query-on-exit-flag p nil)
+ (tramp-process-actions p v nil tramp-smb-actions-get-acl)
+ (when (> (point-max) (point-min))
+ (substring-no-properties (buffer-string))))))))))))))
(defun tramp-smb-handle-file-attributes (filename &optional id-format)
"Like `file-attributes' for Tramp files."
@@ -886,7 +895,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
vec 5 "file attributes with stat: %s" (tramp-file-name-localname vec))
(let* (size id link uid gid atime mtime ctime mode inode)
(when (tramp-smb-send-command
- vec (format "stat \"%s\"" (tramp-smb-get-localname vec)))
+ vec (format "stat %s" (tramp-smb-shell-quote-localname vec)))
;; Loop the listing.
(with-current-buffer (tramp-get-connection-buffer vec)
@@ -960,7 +969,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(when (and (stringp id)
(tramp-smb-send-command
vec
- (format "readlink \"%s\"" (tramp-smb-get-localname vec))))
+ (format
+ "readlink %s" (tramp-smb-shell-quote-localname vec))))
(goto-char (point-min))
(and (looking-at ".+ -> \\(.+\\)")
(setq id (match-string 1))))
@@ -979,8 +989,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(with-tramp-progress-reporter
v 3 (format "Fetching %s to tmp file %s" filename tmpfile)
(unless (tramp-smb-send-command
- v (format "get \"%s\" \"%s\""
- (tramp-smb-get-localname v) tmpfile))
+ v (format "get %s %s"
+ (tramp-smb-shell-quote-localname v)
+ (tramp-smb-shell-quote-argument tmpfile)))
;; Oops, an error. We shall cleanup.
(delete-file tmpfile)
(tramp-error
@@ -1013,7 +1024,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(when (tramp-smb-get-share v)
(tramp-message v 5 "file system info: %s" localname)
(tramp-smb-send-command
- v (format "du %s/*" (tramp-smb-get-localname v)))
+ v (format "du %s/*" (tramp-smb-shell-quote-localname v)))
(with-current-buffer (tramp-get-connection-buffer v)
(let (total avail blocksize)
(goto-char (point-min))
@@ -1123,7 +1134,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
;; Insert size information.
(when full-directory-p
(insert
- (if avail
+ (if (and avail
+ ;; Emacs 29.1 or later.
+ (not (fboundp 'dired--insert-disk-space)))
(format "total used in directory %s available %s\n" used avail)
(format "total %s\n" used))))
@@ -1201,18 +1214,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(unless (file-name-absolute-p directory)
(setq directory (expand-file-name directory default-directory)))
(with-parsed-tramp-file-name directory nil
- (let* ((file (tramp-smb-get-localname v)))
- (when (file-directory-p (file-name-directory directory))
- (tramp-smb-send-command
- v
- (if (tramp-smb-get-cifs-capabilities v)
- (format "posix_mkdir \"%s\" %o" file (default-file-modes))
- (format "mkdir \"%s\"" file)))
- ;; We must also flush the cache of the directory, because
- ;; `file-attributes' reads the values from there.
- (tramp-flush-file-properties v localname))
- (unless (file-directory-p directory)
- (tramp-error v 'file-error "Couldn't make directory %s" directory)))))
+ (when (file-directory-p (file-name-directory directory))
+ (tramp-smb-send-command
+ v (if (tramp-smb-get-cifs-capabilities v)
+ (format "posix_mkdir %s %o"
+ (tramp-smb-shell-quote-localname v) (default-file-modes))
+ (format "mkdir %s" (tramp-smb-shell-quote-localname v))))
+ ;; We must also flush the cache of the directory, because
+ ;; `file-attributes' reads the values from there.
+ (tramp-flush-file-properties v localname))
+ (unless (file-directory-p directory)
+ (tramp-error v 'file-error "Couldn't make directory %s" directory))))
(defun tramp-smb-handle-make-symbolic-link
(target linkname &optional ok-if-already-exists)
@@ -1256,11 +1268,10 @@ component is used as the target of the symlink."
;; `file-attributes' reads the values from there.
(tramp-flush-file-properties v localname)
- (unless
- (tramp-smb-send-command
- v (format "symlink \"%s\" \"%s\""
- (tramp-compat-file-name-unquote target)
- (tramp-smb-get-localname v)))
+ (unless (tramp-smb-send-command
+ v (format "symlink %s %s"
+ (tramp-smb-shell-quote-argument target)
+ (tramp-smb-shell-quote-localname v)))
(tramp-error
v 'file-error
"error with make-symbolic-link, see buffer `%s' for details"
@@ -1281,10 +1292,10 @@ 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))
+ (setq input (tramp-unquote-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))
@@ -1329,31 +1340,34 @@ component is used as the target of the symlink."
(setq i (1+ i)
name1 (format "%s<%d>" name i)))
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name1)
- (tramp-set-connection-property
- v "process-buffer"
- (or outbuf (generate-new-buffer tramp-temp-buffer-name)))
-
;; Call it.
(condition-case nil
- (with-current-buffer (tramp-get-connection-buffer v)
- ;; Preserve buffer contents.
- (narrow-to-region (point-max) (point-max))
- (tramp-smb-call-winexe v)
- (when (tramp-smb-get-share v)
- (tramp-smb-send-command
- v (format "cd \"//%s%s\"" host (file-name-directory localname))))
- (tramp-smb-send-command v command)
- ;; Preserve command output.
- (narrow-to-region (point-max) (point-max))
- (let ((p (tramp-get-connection-process v)))
- (tramp-smb-send-command v "exit $lasterrorcode")
- (while (process-live-p p)
- (sleep-for 0.1)
- (setq ret (process-exit-status p))))
- (delete-region (point-min) (point-max))
- (widen))
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name1)
+ (tramp-set-connection-property
+ v "process-buffer"
+ (or outbuf (generate-new-buffer tramp-temp-buffer-name)))
+ (with-current-buffer (tramp-get-connection-buffer v)
+ ;; Preserve buffer contents.
+ (narrow-to-region (point-max) (point-max))
+ (tramp-smb-call-winexe v)
+ (when (tramp-smb-get-share v)
+ (tramp-smb-send-command
+ v (format "cd //%s%s" host
+ (tramp-smb-shell-quote-argument
+ (file-name-directory localname)))))
+ (tramp-smb-send-command v command)
+ ;; Preserve command output.
+ (narrow-to-region (point-max) (point-max))
+ (let ((p (tramp-get-connection-process v)))
+ (tramp-smb-send-command v "exit $lasterrorcode")
+ (while (process-live-p p)
+ (sleep-for 0.1)
+ (setq ret (process-exit-status p))))
+ (delete-region (point-min) (point-max))
+ (widen))))
;; When the user did interrupt, we should do it also. We use
;; return code -1 as marker.
@@ -1368,13 +1382,11 @@ component is used as the target of the symlink."
;; Cleanup. We remove all file cache values for the connection,
;; because the remote process could have changed them.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")
(when tmpinput (delete-file tmpinput))
+ ;; FIXME: Does connection-property "process-buffer" still exist?
(unless outbuf
- (kill-buffer (tramp-get-connection-property v "process-buffer" nil)))
-
- (unless process-file-side-effects
+ (kill-buffer (tramp-get-connection-property v "process-buffer")))
+ (when process-file-side-effects
(tramp-flush-directory-properties v ""))
;; Return exit status.
@@ -1419,9 +1431,9 @@ component is used as the target of the symlink."
v2 'file-error
"Target `%s' must contain a share name" newname))
(unless (tramp-smb-send-command
- v2 (format "rename \"%s\" \"%s\""
- (tramp-smb-get-localname v1)
- (tramp-smb-get-localname v2)))
+ v2 (format "rename %s %s"
+ (tramp-smb-shell-quote-localname v1)
+ (tramp-smb-shell-quote-localname v2)))
(tramp-error v2 'file-error "Cannot rename `%s'" filename))))
;; We must rename via copy.
@@ -1474,42 +1486,44 @@ component is used as the target of the symlink."
"||" "echo" "tramp_exit_status" "1")))
(unwind-protect
- (with-temp-buffer
- ;; Set the transfer process properties.
- (tramp-set-connection-property
- v "process-name" (buffer-name (current-buffer)))
- (tramp-set-connection-property
- v "process-buffer" (current-buffer))
-
- ;; Use an asynchronous process. By this, password can
- ;; be handled.
- (let ((p (apply
- #'start-process
- (tramp-get-connection-name v)
- (tramp-get-connection-buffer v)
- tramp-smb-acl-program args)))
-
- (tramp-message v 6 "%s" (string-join (process-command p) " "))
- (process-put p 'vector v)
- (process-put p 'adjust-window-size-function #'ignore)
- (set-process-query-on-exit-flag p nil)
- (tramp-process-actions p v nil tramp-smb-actions-set-acl)
- ;; This is meant for traces, and returning from the
- ;; function. No error is propagated outside, due to
- ;; the `ignore-errors' closure.
- (unless (tramp-search-regexp "tramp_exit_status [[:digit:]]+")
- (tramp-error
- v 'file-error
- "Couldn't find exit status of `%s'" tramp-smb-acl-program))
- (skip-chars-forward "^ ")
- (when (zerop (read (current-buffer)))
- ;; Success.
- (tramp-set-file-property v localname "file-acl" acl-string)
- t)))
-
- ;; Reset the transfer process properties.
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")))))))
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ (with-temp-buffer
+ ;; Set the transfer process properties.
+ (tramp-set-connection-property
+ v "process-name" (buffer-name (current-buffer)))
+ (tramp-set-connection-property
+ v "process-buffer" (current-buffer))
+
+ ;; Use an asynchronous process. By this, password
+ ;; can be handled.
+ (let ((p (apply
+ #'start-process
+ (tramp-get-connection-name v)
+ (tramp-get-connection-buffer v)
+ tramp-smb-acl-program args)))
+
+ (tramp-message
+ v 6 "%s" (string-join (process-command p) " "))
+ (process-put p 'vector v)
+ (process-put p 'adjust-window-size-function #'ignore)
+ (set-process-query-on-exit-flag p nil)
+ (tramp-process-actions p v nil tramp-smb-actions-set-acl)
+ ;; This is meant for traces, and returning from
+ ;; the function. No error is propagated
+ ;; outside, due to the `ignore-errors' closure.
+ (unless
+ (tramp-search-regexp "tramp_exit_status [[:digit:]]+")
+ (tramp-error
+ v 'file-error
+ "Couldn't find exit status of `%s'"
+ tramp-smb-acl-program))
+ (skip-chars-forward "^ ")
+ (when (zerop (read (current-buffer)))
+ ;; Success.
+ (tramp-set-file-property
+ v localname "file-acl" acl-string)
+ t)))))))))))
(defun tramp-smb-handle-set-file-modes (filename mode &optional flag)
"Like `set-file-modes' for Tramp files."
@@ -1519,7 +1533,8 @@ component is used as the target of the symlink."
(when (tramp-smb-get-cifs-capabilities v)
(tramp-flush-file-properties v localname)
(unless (tramp-smb-send-command
- v (format "chmod \"%s\" %o" (tramp-smb-get-localname v) mode))
+ v
+ (format "chmod %s %o" (tramp-smb-shell-quote-localname v) mode))
(tramp-error
v 'file-error "Error while changing file's mode %s" filename))))))
@@ -1537,41 +1552,50 @@ component is used as the target of the symlink."
(command (string-join (cons program args) " "))
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
- (i 0))
+ (i 0)
+ p)
(unwind-protect
- (save-excursion
- (save-restriction
- (while (get-process name1)
- ;; NAME must be unique as process name.
- (setq i (1+ i)
- name1 (format "%s<%d>" name i)))
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name1)
- (tramp-set-connection-property v "process-buffer" buffer)
- ;; Activate narrowing in order to save BUFFER contents.
- (with-current-buffer (tramp-get-connection-buffer v)
- (let ((buffer-undo-list t))
- (narrow-to-region (point-max) (point-max))
- (tramp-smb-call-winexe v)
- (when (tramp-smb-get-share v)
- (tramp-smb-send-command
- v (format
- "cd \"//%s%s\""
- host (file-name-directory localname))))
- (tramp-message v 6 "(%s); exit" command)
- (tramp-send-string v command)))
- ;; Return value.
- (tramp-get-connection-process v)))
+ (with-tramp-saved-connection-property v "process-name"
+ (with-tramp-saved-connection-property v "process-buffer"
+ (save-excursion
+ (save-restriction
+ (while (get-process name1)
+ ;; NAME must be unique as process name.
+ (setq i (1+ i)
+ name1 (format "%s<%d>" name i)))
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name1)
+ (tramp-set-connection-property v "process-buffer" buffer)
+ ;; Activate narrowing in order to save BUFFER contents.
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (let ((buffer-undo-list t))
+ (narrow-to-region (point-max) (point-max))
+ (tramp-smb-call-winexe v)
+ (when (tramp-smb-get-share v)
+ (tramp-smb-send-command
+ v (format
+ "cd //%s%s"
+ host
+ (tramp-smb-shell-quote-argument
+ (file-name-directory localname)))))
+ (tramp-message v 6 "(%s); exit" command)
+ (tramp-send-string v command)))
+ (setq p (tramp-get-connection-process v))
+ (when program
+ (process-put p 'remote-command (cons program args))
+ (tramp-set-connection-property
+ p "remote-command" (cons program args)))
+ ;; Return value.
+ p))))
;; Save exit.
+ ;; FIXME: Does `tramp-get-connection-buffer' return the proper value?
(with-current-buffer (tramp-get-connection-buffer v)
(if (tramp-compat-string-search tramp-temp-buffer-name (buffer-name))
(progn
(set-process-buffer (tramp-get-connection-process v) nil)
(kill-buffer (current-buffer)))
- (set-buffer-modified-p bmp)))
- (tramp-flush-connection-property v "process-name")
- (tramp-flush-connection-property v "process-buffer")))))
+ (set-buffer-modified-p bmp)))))))
(defun tramp-smb-handle-substitute-in-file-name (filename)
"Like `substitute-in-file-name' for Tramp files.
@@ -1590,31 +1614,20 @@ errors for shares like \"C$/\", which are common in Microsoft Windows."
(tramp-run-real-handler #'substitute-in-file-name (list filename))
(error filename))))
+(defun tramp-smb-handle-get-home-directory (vec &optional user)
+ "The remote home directory for connection VEC as local file name.
+If USER is a string, return its home directory instead of the
+user identified by VEC. If there is no user specified in either
+VEC or USER, or if there is no home directory, return nil."
+ (let ((user (or user (tramp-file-name-user vec))))
+ (unless (zerop (length user))
+ (concat "/" user))))
+
(defun tramp-smb-handle-write-region
(start end filename &optional append visit lockname mustbenew)
"Like `write-region' for Tramp files."
- (setq filename (expand-file-name filename)
- lockname (file-truename (or lockname filename)))
- (with-parsed-tramp-file-name filename nil
- (when (and mustbenew (file-exists-p filename)
- (or (eq mustbenew 'excl)
- (not
- (y-or-n-p
- (format "File %s exists; overwrite anyway?" filename)))))
- (tramp-error v 'file-already-exists filename))
-
- (let ((file-locked (eq (file-locked-p lockname) t))
- (curbuf (current-buffer))
- (tmpfile (tramp-compat-make-temp-file filename)))
-
- ;; Lock file.
- (when (and (not (auto-save-file-name-p (file-name-nondirectory filename)))
- (file-remote-p lockname)
- (not file-locked))
- (setq file-locked t)
- ;; `lock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'lock-file lockname))
-
+ (tramp-skeleton-write-region start end filename append visit lockname mustbenew
+ (let ((tmpfile (tramp-compat-make-temp-file filename)))
(when (and append (file-exists-p filename))
(copy-file filename tmpfile 'ok))
;; We say `no-message' here because we don't want the visited file
@@ -1627,36 +1640,11 @@ errors for shares like \"C$/\", which are common in Microsoft Windows."
v 3 (format "Moving tmp file %s to %s" tmpfile filename)
(unwind-protect
(unless (tramp-smb-send-command
- v (format "put %s \"%s\""
- tmpfile (tramp-smb-get-localname v)))
+ v (format "put %s %s"
+ (tramp-smb-shell-quote-argument tmpfile)
+ (tramp-smb-shell-quote-localname v)))
(tramp-error v 'file-error "Cannot write `%s'" filename))
- (delete-file tmpfile)))
-
- ;; We must also flush the cache of the directory, because
- ;; `file-attributes' reads the values from there.
- (tramp-flush-file-properties v localname)
-
- (unless (equal curbuf (current-buffer))
- (tramp-error
- v 'file-error
- "Buffer has changed from `%s' to `%s'" curbuf (current-buffer)))
-
- ;; Set file modification time.
- (when (or (eq visit t) (stringp visit))
- (set-visited-file-modtime
- (or (file-attribute-modification-time (file-attributes filename))
- (current-time))))
-
- ;; Unlock file.
- (when file-locked
- ;; `unlock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'unlock-file lockname))
-
- ;; The end.
- (when (and (null noninteractive)
- (or (eq visit t) (string-or-null-p visit)))
- (tramp-message v 0 "Wrote %s" filename))
- (run-hooks 'tramp-handle-write-region-hook))))
+ (delete-file tmpfile))))))
;; Internal file name functions.
@@ -1690,9 +1678,8 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"."
(when (string-match "\\(\\$\\$\\)\\(/\\|$\\)" localname)
(setq localname (replace-match "$" nil nil localname 1)))
- ;; A period followed by a space, or trailing periods and spaces,
- ;; are not supported.
- (when (string-match-p "\\. \\|\\.$\\| $" localname)
+ ;; A trailing space is not supported.
+ (when (string-match-p " $" localname)
(tramp-error
vec 'file-error
"Invalid file name %s" (tramp-make-tramp-file-name vec localname)))
@@ -1713,7 +1700,7 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
(setq localname (or localname "/"))
(with-tramp-file-property v localname "file-entries"
(let* ((share (tramp-smb-get-share v))
- (cache (tramp-get-connection-property v "share-cache" nil))
+ (cache (tramp-get-connection-property v "share-cache"))
res entry)
(if (and (not share) cache)
@@ -1723,7 +1710,7 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
;; Read entries.
(if share
(tramp-smb-send-command
- v (format "dir \"%s*\"" (tramp-smb-get-localname v)))
+ v (format "dir %s*" (tramp-smb-shell-quote-localname v)))
;; `tramp-smb-maybe-open-connection' lists also the share names.
(tramp-smb-maybe-open-connection v))
@@ -1927,7 +1914,7 @@ are listed. Result is the list (LOCALNAME MODE SIZE MTIME)."
(if (and (tramp-smb-get-share vec)
(process-live-p (tramp-get-connection-process vec)))
(with-tramp-connection-property (tramp-get-process vec) "stat-capability"
- (tramp-smb-send-command vec "stat \"/\""))))
+ (tramp-smb-send-command vec "stat /"))))
;; Connection functions.
@@ -2042,7 +2029,7 @@ If ARGUMENT is non-nil, use it as argument for
(if (not (zerop (length user))) (concat user "@") "")
host (or share ""))
- (let* ((coding-system-for-read nil)
+ (let* (coding-system-for-read
(process-connection-type tramp-process-connection-type)
(p (let ((default-directory
tramp-compat-temporary-file-directory)
@@ -2187,6 +2174,10 @@ Removes smb prompt. Returns nil if an error message has appeared."
(let ((system-type 'ms-dos))
(tramp-unquote-shell-quote-argument s)))
+(defun tramp-smb-shell-quote-localname (vec)
+ "Call `tramp-smb-shell-quote-argument' on localname of VEC."
+ (tramp-smb-shell-quote-argument (tramp-smb-get-localname vec)))
+
(add-hook 'tramp-unload-hook
(lambda ()
(unload-feature 'tramp-smb 'force)))
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
index 0a5bf2f43b3..d7c918fbc83 100644
--- a/lisp/net/tramp-sshfs.el
+++ b/lisp/net/tramp-sshfs.el
@@ -51,11 +51,14 @@
(add-to-list 'tramp-methods
`(,tramp-sshfs-method
(tramp-mount-args (("-C") ("-p" "%p")
+ ("-o" "dir_cache=no")
+ ("-o" "transform_symlinks")
("-o" "idmap=user,reconnect")))
;; These are for remote processes.
(tramp-login-program "ssh")
- (tramp-login-args (("-q")("-l" "%u") ("-p" "%p")
- ("-e" "none") ("%h") ("%l")))
+ (tramp-login-args (("-q") ("-l" "%u") ("-p" "%p")
+ ("-e" "none") ("-t" "-t")
+ ("%h") ("%l")))
(tramp-direct-async t)
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-remote-shell-login ("-l"))
@@ -107,9 +110,9 @@
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
- (file-notify-add-watch . ignore)
- (file-notify-rm-watch . ignore)
- (file-notify-valid-p . ignore)
+ (file-notify-add-watch . tramp-handle-file-notify-add-watch)
+ (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
+ (file-notify-valid-p . tramp-handle-file-notify-valid-p)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
@@ -118,11 +121,12 @@
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-sshfs-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
- (file-writable-p . tramp-handle-file-writable-p)
+ (file-writable-p . tramp-sshfs-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-handle-insert-directory)
(insert-file-contents . tramp-sshfs-handle-insert-file-contents)
+ (list-system-processes . tramp-handle-list-system-processes)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -132,17 +136,19 @@
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . tramp-handle-make-process)
(make-symbolic-link . tramp-handle-make-symbolic-link)
+ (process-attributes . tramp-handle-process-attributes)
(process-file . tramp-sshfs-handle-process-file)
(rename-file . tramp-sshfs-handle-rename-file)
(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)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . ignore)
(tramp-get-remote-gid . ignore)
(tramp-get-remote-uid . ignore)
(tramp-set-file-uid-gid . ignore)
@@ -219,6 +225,10 @@ arguments to pass to the OPERATION."
;;`file-system-info' exists since Emacs 27.1.
(tramp-compat-funcall 'file-system-info (tramp-fuse-local-file-name filename)))
+(defun tramp-sshfs-handle-file-writable-p (filename)
+ "Like `file-writable-p' for Tramp files."
+ (file-writable-p (tramp-fuse-local-file-name filename)))
+
(defun tramp-sshfs-handle-insert-file-contents
(filename &optional visit beg end replace)
"Like `insert-file-contents' for Tramp files."
@@ -239,16 +249,69 @@ arguments to pass to the OPERATION."
(error "Implementation does not handle immediate return"))
(with-parsed-tramp-file-name (expand-file-name default-directory) nil
- (let ((command
+ (let ((coding-system-for-read 'utf-8-dos) ; Is this correct?
+ (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 stderr tmpstderr outbuf)
+
+ ;; 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-unquote-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))
+ (copy-file infile tmpinput t)))
+ (when input (setq command (format "%s <%s" command input)))
+
+ ;; Determine output.
+ (cond
+ ;; Just a buffer.
+ ((bufferp destination)
+ (setq outbuf destination))
+ ;; A buffer name.
+ ((stringp destination)
+ (setq outbuf (get-buffer-create destination)))
+ ;; (REAL-DESTINATION ERROR-DESTINATION)
+ ((consp destination)
+ ;; output.
+ (cond
+ ((bufferp (car destination))
+ (setq outbuf (car destination)))
+ ((stringp (car destination))
+ (setq outbuf (get-buffer-create (car destination))))
+ ((car destination)
+ (setq outbuf (current-buffer))))
+ ;; stderr.
+ (cond
+ ((stringp (cadr destination))
+ (setcar (cdr destination) (expand-file-name (cadr destination)))
+ (if (tramp-equal-remote default-directory (cadr destination))
+ ;; stderr is on the same remote host.
+ (setq stderr (tramp-unquote-file-local-name (cadr destination)))
+ ;; stderr must be copied to remote host. The temporary
+ ;; file must be deleted after execution.
+ (setq stderr (tramp-make-tramp-temp-file v)
+ tmpstderr (tramp-make-tramp-file-name v stderr))))
+ ;; stderr to be discarded.
+ ((null (cadr destination))
+ (setq stderr (tramp-get-remote-null-device v)))))
+ ;; 't
+ (destination
+ (setq outbuf (current-buffer))))
+ (when stderr (setq command (format "%s 2>%s" command stderr)))
+
(unwind-protect
(apply
#'tramp-call-process
v (tramp-get-method-parameter v 'tramp-login-program)
- infile destination display
+ nil outbuf display
(tramp-expand-args
v 'tramp-login-args
?h (or (tramp-file-name-host v) "")
@@ -256,7 +319,20 @@ arguments to pass to the OPERATION."
?p (or (tramp-file-name-port v) "")
?l command))
- (unless process-file-side-effects
+ ;; Synchronize stderr.
+ (when tmpstderr
+ (tramp-cleanup-connection v 'keep-debug 'keep-password)
+ (tramp-fuse-unmount v))
+
+ ;; Provide error file.
+ (when tmpstderr
+ (rename-file tmpstderr (cadr destination) t))
+
+ ;; 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,44 +361,22 @@ 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."
- (setq filename (expand-file-name filename)
- lockname (file-truename (or lockname filename)))
- (with-parsed-tramp-file-name filename nil
- (when (and mustbenew (file-exists-p filename)
- (or (eq mustbenew 'excl)
- (not
- (y-or-n-p
- (format "File %s exists; overwrite anyway?" filename)))))
- (tramp-error v 'file-already-exists filename))
-
- (let ((file-locked (eq (file-locked-p lockname) t)))
-
- ;; Lock file.
- (when (and (not (auto-save-file-name-p (file-name-nondirectory filename)))
- (file-remote-p lockname)
- (not file-locked))
- (setq file-locked t)
- ;; `lock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'lock-file lockname))
-
- (let (create-lockfiles)
- (write-region
- start end (tramp-fuse-local-file-name filename) append 'nomessage)
- (tramp-flush-file-properties v localname))
-
- ;; Unlock file.
- (when file-locked
- ;; `unlock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'unlock-file lockname))
-
- ;; The end.
- (when (and (null noninteractive)
- (or (eq visit t) (string-or-null-p visit)))
- (tramp-message v 0 "Wrote %s" filename))
- (run-hooks 'tramp-handle-write-region-hook))))
+ (tramp-skeleton-write-region start end filename append visit lockname mustbenew
+ (let (create-lockfiles)
+ (write-region
+ start end (tramp-fuse-local-file-name filename) append 'nomessage))))
;; File name conversions.
@@ -383,6 +437,24 @@ connection if a previous connection has died for some reason."
(with-tramp-connection-property
vec "gid-string" (tramp-get-local-gid 'string)))
+;; `shell-mode' tries to open remote files like "/sshfs:user@host:~/.history".
+;; This fails, because the tilde cannot be expanded. Tell
+;; `tramp-handle-expand-file-name' to tolerate this.
+(defun tramp-sshfs-tolerate-tilde (orig-fun)
+ "Advice for `shell-mode' to tolerate tilde in remote file names."
+ (let ((tramp-tolerate-tilde
+ (or tramp-tolerate-tilde
+ (equal (file-remote-p default-directory 'method)
+ tramp-sshfs-method))))
+ (funcall orig-fun)))
+
+(add-function
+ :around (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde)
+(add-hook 'tramp-sshfs-unload-hook
+ (lambda ()
+ (remove-function
+ (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde)))
+
(add-hook 'tramp-unload-hook
(lambda ()
(unload-feature 'tramp-sshfs 'force)))
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index a68d4b3e365..420a593644f 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -45,7 +45,8 @@
(add-to-list 'tramp-methods
`(,tramp-sudoedit-method
(tramp-sudo-login (("sudo") ("-u" "%u") ("-S") ("-H")
- ("-p" "Password:") ("--")))))
+ ("-p" "Password:") ("--")))
+ (tramp-password-previous-hop t)))
(add-to-list 'tramp-default-user-alist '("\\`sudoedit\\'" nil "root"))
@@ -100,9 +101,9 @@ See `tramp-actions-before-shell' for more info.")
(file-name-nondirectory . tramp-handle-file-name-nondirectory)
;; `file-name-sans-versions' performed by default handler.
(file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
- (file-notify-add-watch . ignore)
- (file-notify-rm-watch . ignore)
- (file-notify-valid-p . ignore)
+ (file-notify-add-watch . tramp-handle-file-notify-add-watch)
+ (file-notify-rm-watch . tramp-handle-file-notify-rm-watch)
+ (file-notify-valid-p . tramp-handle-file-notify-valid-p)
(file-ownership-preserved-p . ignore)
(file-readable-p . tramp-sudoedit-handle-file-readable-p)
(file-regular-p . tramp-handle-file-regular-p)
@@ -116,6 +117,7 @@ See `tramp-actions-before-shell' for more info.")
;; `get-file-buffer' performed by default handler.
(insert-directory . tramp-handle-insert-directory)
(insert-file-contents . tramp-handle-insert-file-contents)
+ (list-system-processes . ignore)
(load . tramp-handle-load)
(lock-file . tramp-handle-lock-file)
(make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -125,6 +127,7 @@ See `tramp-actions-before-shell' for more info.")
(make-nearby-temp-file . tramp-handle-make-nearby-temp-file)
(make-process . ignore)
(make-symbolic-link . tramp-sudoedit-handle-make-symbolic-link)
+ (process-attributes . ignore)
(process-file . ignore)
(rename-file . tramp-sudoedit-handle-rename-file)
(set-file-acl . tramp-sudoedit-handle-set-file-acl)
@@ -136,6 +139,7 @@ See `tramp-actions-before-shell' for more info.")
(start-file-process . ignore)
(substitute-in-file-name . tramp-handle-substitute-in-file-name)
(temporary-file-directory . tramp-handle-temporary-file-directory)
+ (tramp-get-home-directory . tramp-sudoedit-handle-get-home-directory)
(tramp-get-remote-gid . tramp-sudoedit-handle-get-remote-gid)
(tramp-get-remote-uid . tramp-sudoedit-handle-get-remote-uid)
(tramp-set-file-uid-gid . tramp-sudoedit-handle-set-file-uid-gid)
@@ -143,7 +147,7 @@ See `tramp-actions-before-shell' for more info.")
(unlock-file . tramp-handle-unlock-file)
(vc-registered . ignore)
(verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime)
- (write-region . tramp-sudoedit-handle-write-region))
+ (write-region . tramp-handle-write-region))
"Alist of handler functions for Tramp SUDOEDIT method.")
;; It must be a `defsubst' in order to push the whole code into
@@ -168,6 +172,12 @@ arguments to pass to the OPERATION."
(tramp-register-foreign-file-name-handler
#'tramp-sudoedit-file-name-p #'tramp-sudoedit-file-name-handler))
+;; Needed for `tramp-read-passwd'.
+(defconst tramp-sudoedit-null-hop
+ (make-tramp-file-name
+ :method tramp-sudoedit-method :user (user-login-name) :host tramp-system-name)
+"Connection hop which identifies the virtual hop before the first one.")
+
;; File name primitives.
@@ -362,17 +372,23 @@ the result will be a local, non-Tramp, file name."
(setq localname "~"))
(unless (file-name-absolute-p localname)
(setq localname (format "~%s/%s" user localname)))
- (when (string-match "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ (when (string-match "\\`~\\([^/]*\\)\\(.*\\)\\'" localname)
(let ((uname (match-string 1 localname))
- (fname (match-string 2 localname)))
- (when (string-equal uname "~")
- (setq uname (concat uname user)))
- (setq localname (concat uname fname))))
- ;; Do not keep "/..".
- (when (string-match-p "^/\\.\\.?$" localname)
- (setq localname "/"))
+ (fname (match-string 2 localname))
+ hname)
+ (when (zerop (length uname))
+ (setq uname user))
+ (when (setq hname (tramp-get-home-directory v uname))
+ (setq localname (concat hname fname)))))
+ ;; Do not keep "/..".
+ (when (string-match-p "^/\\.\\.?$" localname)
+ (setq localname "/"))
;; Do normal `expand-file-name' (this does "~user/", "/./" and "/../").
- (tramp-make-tramp-file-name v (expand-file-name localname))))
+ (tramp-make-tramp-file-name
+ v (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ localname
+ (tramp-run-real-handler
+ #'expand-file-name (list localname))))))
(defun tramp-sudoedit-remote-acl-p (vec)
"Check, whether ACL is enabled on the remote host."
@@ -572,8 +588,7 @@ the result will be a local, non-Tramp, file name."
(when (file-remote-p result)
(setq result (tramp-compat-file-name-quote result 'top)))
(tramp-message v 4 "True name of `%s' is `%s'" localname result)
- result))
- 'nohop)))))
+ result)))))))
(defun tramp-sudoedit-handle-file-writable-p (filename)
"Like `file-writable-p' for Tramp files."
@@ -693,6 +708,13 @@ component is used as the target of the symlink."
(tramp-flush-file-property v localname "file-selinux-context"))
t)))))
+(defun tramp-sudoedit-handle-get-home-directory (vec &optional user)
+ "The remote home directory for connection VEC as local file name.
+If USER is a string, return its home directory instead of the
+user identified by VEC. If there is no user specified in either
+VEC or USER, or if there is no home directory, return nil."
+ (expand-file-name (concat "~" (or user (tramp-file-name-user vec)))))
+
(defun tramp-sudoedit-handle-get-remote-uid (vec id-format)
"The uid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
@@ -717,38 +739,6 @@ ID-FORMAT valid values are `string' and `integer'."
(or gid (tramp-get-remote-gid v 'integer)))
(tramp-unquote-file-local-name filename))))
-(defun tramp-sudoedit-handle-write-region
- (start end filename &optional append visit lockname mustbenew)
- "Like `write-region' for Tramp files."
- (setq filename (expand-file-name filename))
- (with-parsed-tramp-file-name filename nil
- (let* ((uid (or (file-attribute-user-id (file-attributes filename 'integer))
- (tramp-get-remote-uid v 'integer)))
- (gid (or (file-attribute-group-id (file-attributes filename 'integer))
- (tramp-get-remote-gid v 'integer)))
- (flag (and (eq mustbenew 'excl) 'nofollow))
- (modes (tramp-default-file-modes filename flag))
- (attributes (file-extended-attributes filename)))
- (prog1
- (tramp-handle-write-region
- start end filename append visit lockname mustbenew)
-
- ;; Set the ownership, modes and extended attributes. This is
- ;; not performed in `tramp-handle-write-region'.
- (unless (and (= (file-attribute-user-id
- (file-attributes filename 'integer))
- uid)
- (= (file-attribute-group-id
- (file-attributes filename 'integer))
- gid))
- (tramp-set-file-uid-gid filename uid gid))
- (tramp-compat-set-file-modes filename modes flag)
- ;; We ignore possible errors, because ACL strings could be
- ;; incompatible.
- (when attributes
- (ignore-errors
- (set-file-extended-attributes filename attributes)))))))
-
;; Internal functions.
@@ -826,6 +816,7 @@ in case of error, t otherwise."
(process-put p 'vector vec)
(process-put p 'adjust-window-size-function #'ignore)
(set-process-query-on-exit-flag p nil)
+ (tramp-set-connection-property p "password-vector" tramp-sudoedit-null-hop)
(tramp-process-actions p vec nil tramp-sudoedit-sudo-actions)
(tramp-message vec 6 "%s\n%s" (process-exit-status p) (buffer-string))
(prog1
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index adde443fdd6..37259107147 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -185,7 +185,7 @@ See the variable `tramp-encoding-shell' for more information."
;; Since Emacs 26.1, `system-name' can return nil at build time if
;; Emacs is compiled with "--no-build-details". We do expect it to be
-;; a string. (Bug#44481)
+;; a string. (Bug#44481, Bug#54294)
(defconst tramp-system-name (or (system-name) "")
"The system name Tramp is running locally.")
@@ -238,7 +238,7 @@ pair of the form (KEY VALUE). The following KEYs are defined:
unchanged after expansion (i.e. no host, no user or no port
were specified), that sublist is not used. For e.g.
- '((\"-a\" \"-b\") (\"-l\" \"%u\"))
+ \\='((\"-a\" \"-b\") (\"-l\" \"%u\"))
that means that (\"-l\" \"%u\") is used only if the user was
specified, and it is thus effectively optional.
@@ -255,6 +255,10 @@ pair of the form (KEY VALUE). The following KEYs are defined:
- \"%n\" expands to \"2>/dev/null\".
- \"%x\" is replaced by the `tramp-scp-strict-file-name-checking'
argument if it is supported.
+ - \"%y\" is replaced by the `tramp-scp-force-scp-protocol'
+ argument if it is supported.
+ - \"%z\" is replaced by the `tramp-scp-direct-remote-copying'
+ argument if it is supported.
The existence of `tramp-login-args', combined with the
absence of `tramp-copy-args', is an indication that the
@@ -313,14 +317,20 @@ pair of the form (KEY VALUE). The following KEYs are defined:
* `tramp-connection-timeout'
This is the maximum time to be spent for establishing a connection.
In general, the global default value shall be used, but for
- some methods, like \"su\" or \"sudo\", a shorter timeout
- might be desirable.
+ some methods, like \"doas\", \"su\" or \"sudo\", a shorter
+ timeout might be desirable.
* `tramp-session-timeout'
How long a Tramp connection keeps open before being disconnected.
- This is useful for methods like \"su\" or \"sudo\", which
+ This is useful for methods like \"doas\" or \"sudo\", which
shouldn't run an open connection in the background forever.
+ * `tramp-password-previous-hop'
+ The password for this connection is the same like the
+ password for the previous hop. If there is no previous hop,
+ the password of the local user is applied. This is needed
+ for methods like \"doas\", \"sudo\" or \"sudoedit\".
+
* `tramp-case-insensitive'
Whether the remote file system handles file names case insensitive.
Only a non-nil value counts, the default value nil means to
@@ -495,7 +505,8 @@ interpreted as a regular expression which always matches."
;; either lower case or upper case letters. See
;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=38079#20>.
(defcustom tramp-restricted-shell-hosts-alist
- (when (eq system-type 'windows-nt)
+ (when (and (eq system-type 'windows-nt)
+ (not (string-match-p "sh$" tramp-encoding-shell)))
(list (format "\\`\\(%s\\|%s\\)\\'"
(regexp-quote (downcase tramp-system-name))
(regexp-quote (upcase tramp-system-name)))))
@@ -511,11 +522,12 @@ host runs a restricted shell, it shall be added to this list, too."
(concat
"\\`"
(regexp-opt
- (list "localhost" "localhost6" tramp-system-name "127.0.0.1" "::1") t)
+ `("localhost" "localhost4" "localhost6" ,tramp-system-name "127.0.0.1" "::1")
+ t)
"\\'")
"Host names which are regarded as local host.
If the local host runs a chrooted environment, set this to nil."
- :version "27.1"
+ :version "29.1"
:type '(choice (const :tag "Chrooted environment" nil)
(regexp :tag "Host regexp")))
@@ -1372,7 +1384,8 @@ would require an immediate reread during filename completion, nil
means to use always cached values for the directory contents."
:type '(choice (const nil) (const t) integer))
(make-obsolete-variable
- 'tramp-completion-reread-directory-timeout 'remote-file-name-inhibit-cache "27.2")
+ 'tramp-completion-reread-directory-timeout
+ 'remote-file-name-inhibit-cache "27.2")
;;; Internal Variables:
@@ -1387,6 +1400,11 @@ Will be called once the password has been verified by successful
authentication.")
(put 'tramp-password-save-function 'tramp-suppress-trace t)
+(defvar tramp-password-prompt-not-unique nil
+ "Whether several passwords might be requested.
+This shouldn't be set explicitly. It is let-bound, for example
+during direct remote copying with scp.")
+
(defconst tramp-completion-file-name-handler-alist
'((file-name-all-completions
. tramp-completion-handle-file-name-all-completions)
@@ -1408,7 +1426,10 @@ calling HANDLER.")
;; internal data structure. Convenience functions for internal
;; data structure.
-;; The basic structure for remote file names.
+;; The basic structure for remote file names. We must autoload it in
+;; tramp-loaddefs.el, because some functions, which need it, wouldn't
+;; work otherwise when unloading / reloading Tramp. (Bug#50869)
+;;;###tramp-autoload
(cl-defstruct (tramp-file-name (:type list) :named)
method user domain host port localname hop)
@@ -1420,6 +1441,11 @@ calling HANDLER.")
(put #'tramp-file-name-localname 'tramp-suppress-trace t)
(put #'tramp-file-name-hop 'tramp-suppress-trace t)
+;; Needed for `tramp-read-passwd' and `tramp-get-remote-null-device'.
+(defconst tramp-null-hop
+ (make-tramp-file-name :user (user-login-name) :host tramp-system-name)
+"Connection hop which identifies the virtual hop before the first one.")
+
(defun tramp-file-name-user-domain (vec)
"Return user and domain components of VEC."
(when (or (tramp-file-name-user vec) (tramp-file-name-domain vec))
@@ -1476,7 +1502,7 @@ entry does not exist, return nil."
(replace-regexp-in-string "^tramp-" "" (symbol-name param))))
(if (tramp-connection-property-p vec hash-entry)
;; We use the cached property.
- (tramp-get-connection-property vec hash-entry nil)
+ (tramp-get-connection-property vec hash-entry)
;; Use the static value from `tramp-methods'.
(when-let ((methods-entry
(assoc
@@ -1713,13 +1739,10 @@ See `tramp-dissect-file-name' for details."
"Construct a Tramp file name from ARGS.
ARGS could have two different signatures. The first one is of
-type (VEC &optional LOCALNAME HOP).
+type (VEC &optional LOCALNAME).
If LOCALNAME is nil, the value in VEC is used. If it is a
symbol, a null localname will be used. Otherwise, LOCALNAME is
expected to be a string, which will be used.
-If HOP is nil, the value in VEC is used. If it is a symbol, a
-null hop will be used. Otherwise, HOP is expected to be a
-string, which will be used.
The other signature exists for backward compatibility. It has
the form (METHOD USER DOMAIN HOST PORT LOCALNAME &optional HOP)."
@@ -1735,8 +1758,13 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME &optional HOP)."
hop (tramp-file-name-hop (car args)))
(when (cadr args)
(setq localname (and (stringp (cadr args)) (cadr args))))
- (when (cl-caddr args)
- (setq hop (and (stringp (cl-caddr args)) (cl-caddr args)))))
+ (when hop
+ (setq hop nil)
+ ;; Assure that the hops are in `tramp-default-proxies-alist'.
+ ;; In tramp-archive.el, the slot `hop' is used for the archive
+ ;; file name.
+ (unless (string-equal method "archive")
+ (tramp-add-hops (car args)))))
(t (setq method (nth 0 args)
user (nth 1 args)
@@ -1769,15 +1797,17 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME &optional HOP)."
localname)))
(set-advertised-calling-convention
- #'tramp-make-tramp-file-name '(vec &optional localname hop) "27.1")
+ #'tramp-make-tramp-file-name '(vec &optional localname) "29.1")
(defun tramp-make-tramp-hop-name (vec)
"Construct a Tramp hop name from VEC."
- (replace-regexp-in-string
- tramp-prefix-regexp ""
+ (concat
+ (tramp-file-name-hop vec)
(replace-regexp-in-string
- (concat tramp-postfix-host-regexp "$") tramp-postfix-hop-format
- (tramp-make-tramp-file-name vec 'noloc))))
+ tramp-prefix-regexp ""
+ (replace-regexp-in-string
+ (concat tramp-postfix-host-regexp "$") tramp-postfix-hop-format
+ (tramp-make-tramp-file-name vec 'noloc)))))
(defun tramp-completion-make-tramp-file-name (method user host localname)
"Construct a Tramp file name from METHOD, USER, HOST and LOCALNAME.
@@ -1808,10 +1838,10 @@ Unless DONT-CREATE, the buffer is created when it doesn't exist yet."
;; as indication, whether a connection is active.
(tramp-set-connection-property
vec "process-buffer"
- (tramp-get-connection-property vec "process-buffer" nil))
+ (tramp-get-connection-property vec "process-buffer"))
(setq buffer-undo-list t
default-directory
- (tramp-make-tramp-file-name vec 'noloc 'nohop))
+ (tramp-make-tramp-file-name vec 'noloc))
(current-buffer)))))
(defun tramp-get-connection-buffer (vec &optional dont-create)
@@ -1819,14 +1849,14 @@ Unless DONT-CREATE, the buffer is created when it doesn't exist yet."
Unless DONT-CREATE, the buffer is created when it doesn't exist yet.
In case a second asynchronous communication has been started, it is different
from `tramp-get-buffer'."
- (or (tramp-get-connection-property vec "process-buffer" nil)
+ (or (tramp-get-connection-property vec "process-buffer")
(tramp-get-buffer vec dont-create)))
(defun tramp-get-connection-name (vec)
"Get the connection name to be used for VEC.
In case a second asynchronous communication has been started, it is different
from the default one."
- (or (tramp-get-connection-property vec "process-name" nil)
+ (or (tramp-get-connection-property vec "process-name")
(tramp-buffer-name vec)))
(defun tramp-get-process (vec-or-proc)
@@ -1926,7 +1956,8 @@ The outline level is equal to the verbosity of the Tramp message."
"A predicate for Tramp interactive commands.
They are completed by \"M-x TAB\" only in Tramp debug buffers."
(with-current-buffer buffer
- (string-equal (buffer-substring 1 10) ";; Emacs:")))
+ (string-equal
+ (buffer-substring (point-min) (min (+ (point-min) 10) (point-max))) ";; Emacs:")))
(put #'tramp-debug-buffer-command-completion-p 'tramp-suppress-trace t)
@@ -2120,15 +2151,17 @@ applicable)."
(put #'tramp-message 'tramp-suppress-trace t)
-(defsubst tramp-backtrace (&optional vec-or-proc)
+(defsubst tramp-backtrace (&optional vec-or-proc force)
"Dump a backtrace into the debug buffer.
-If VEC-OR-PROC is nil, the buffer *debug tramp* is used. This
-function is meant for debugging purposes."
- (when (>= tramp-verbose 10)
- (if vec-or-proc
- (tramp-message
- vec-or-proc 10 "\n%s" (with-output-to-string (backtrace)))
- (with-output-to-temp-buffer "*debug tramp*" (backtrace)))))
+If VEC-OR-PROC is nil, the buffer *debug tramp* is used. FORCE
+forces the backtrace even if `tramp-verbose' is less than 10.
+This function is meant for debugging purposes."
+ (let ((tramp-verbose (if force 10 tramp-verbose)))
+ (when (>= tramp-verbose 10)
+ (if vec-or-proc
+ (tramp-message
+ vec-or-proc 10 "\n%s" (with-output-to-string (backtrace)))
+ (with-output-to-temp-buffer "*debug tramp*" (backtrace))))))
(put #'tramp-backtrace 'tramp-suppress-trace t)
@@ -2158,6 +2191,11 @@ FMT-STRING and ARGUMENTS."
(put #'tramp-error 'tramp-suppress-trace t)
+(defvar tramp-error-show-message-timeout 30
+ "Time to show the Tramp buffer in case of an error.
+If it is bound to nil, the buffer is not shown. This is used in
+tramp-tests.el.")
+
(defsubst tramp-error-with-buffer
(buf vec-or-proc signal fmt-string &rest arguments)
"Emit an error, and show BUF.
@@ -2175,6 +2213,7 @@ an input event arrives. The other arguments are passed to `tramp-error'."
(apply #'tramp-error vec-or-proc signal fmt-string arguments)
;; Save exit.
(when (and buf
+ (natnump tramp-error-show-message-timeout)
(not (zerop tramp-verbose))
;; Do not show when flagged from outside.
(not non-essential)
@@ -2188,7 +2227,7 @@ an input event arrives. The other arguments are passed to `tramp-error'."
;; Show buffer.
(pop-to-buffer buf)
(discard-input)
- (sit-for 30)))
+ (sit-for tramp-error-show-message-timeout)))
;; Reset timestamp. It would be wrong after waiting for a while.
(when (tramp-file-name-equal-p vec (car tramp-current-connection))
(setcdr tramp-current-connection (current-time)))))))
@@ -2201,7 +2240,8 @@ an input event arrives. The other arguments are passed to `tramp-error'."
(unwind-protect
(apply #'tramp-error vec-or-proc 'user-error fmt-string arguments)
;; Save exit.
- (when (and (not (zerop tramp-verbose))
+ (when (and (natnump tramp-error-show-message-timeout)
+ (not (zerop tramp-verbose))
;; Do not show when flagged from outside.
(not non-essential)
;; Show only when Emacs has started already.
@@ -2211,7 +2251,7 @@ an input event arrives. The other arguments are passed to `tramp-error'."
;; `tramp-error' does not show messages. So we must do it ourselves.
(apply #'message fmt-string arguments)
(discard-input)
- (sit-for 30)
+ (sit-for tramp-error-show-message-timeout)
;; Reset timestamp. It would be wrong after waiting for a while.
(when
(tramp-file-name-equal-p vec-or-proc (car tramp-current-connection))
@@ -2291,8 +2331,6 @@ If VAR is nil, then we bind `v' to the structure and `method', `user',
(ignore ,@(mapcar #'car bindings))
,@body)))
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
-
(defun tramp-progress-reporter-update (reporter &optional value suffix)
"Report progress of an operation for Tramp."
(let* ((parameters (cdr reporter))
@@ -2315,7 +2353,7 @@ without a visible progress reporter."
;; running, and when there is a minimum level.
(when-let ((pr (and (null tramp-inhibit-progress-reporter)
(<= ,level (min tramp-verbose 3))
- (make-progress-reporter ,message nil nil))))
+ (make-progress-reporter ,message))))
(run-at-time 3 0.1 #'tramp-progress-reporter-update pr))))
(unwind-protect
;; Execute the body.
@@ -2329,9 +2367,6 @@ without a visible progress reporter."
(if tm (cancel-timer tm))
(tramp-message ,vec ,level "%s...%s" ,message cookie)))))
-(font-lock-add-keywords
- 'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>"))
-
(defmacro with-tramp-file-property (vec file property &rest body)
"Check in Tramp cache for PROPERTY, otherwise execute BODY and set cache.
FILE must be a local file name on a connection identified via VEC."
@@ -2348,8 +2383,6 @@ FILE must be a local file name on a connection identified via VEC."
value)
,@body))
-(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-tramp-file-property\\>"))
-
(defmacro with-tramp-connection-property (key property &rest body)
"Check in Tramp for property PROPERTY, otherwise execute BODY and set."
(declare (indent 2) (debug t))
@@ -2363,8 +2396,15 @@ FILE must be a local file name on a connection identified via VEC."
(tramp-set-connection-property ,key ,property value))
value))
-(font-lock-add-keywords
- 'emacs-lisp-mode '("\\<with-tramp-connection-property\\>"))
+(defmacro with-tramp-saved-connection-property (key property &rest body)
+ "Save PROPERTY, run BODY, reset PROPERTY."
+ (declare (indent 2) (debug t))
+ `(let ((value (tramp-get-connection-property
+ ,key ,property tramp-cache-undefined)))
+ (unwind-protect (progn ,@body)
+ (if (eq value tramp-cache-undefined)
+ (tramp-flush-connection-property ,key ,property)
+ (tramp-set-connection-property ,key ,property value)))))
(defun tramp-drop-volume-letter (name)
"Cut off unnecessary drive letter from file NAME.
@@ -2459,7 +2499,7 @@ For definition of that list see `tramp-set-completion-function'."
(defun tramp-default-file-modes (filename &optional flag)
"Return file modes of FILENAME as integer.
-If optional FLAG is ‘nofollow’, do not follow FILENAME if it is a
+If optional FLAG is `nofollow', do not follow FILENAME if it is a
symbolic link. If the file modes of FILENAME cannot be
determined, return the value of `default-file-modes', without
execute permissions."
@@ -2501,6 +2541,7 @@ arguments to pass to the OPERATION."
,(and (eq inhibit-file-name-operation operation)
inhibit-file-name-handlers)))
(inhibit-file-name-operation operation)
+ (args (if (tramp-file-name-p (car args)) (cons nil (cdr args)) args))
signal-hook-function)
(apply operation args)))
@@ -2584,23 +2625,26 @@ Must be handled by the callers."
'(make-nearby-temp-file process-file shell-command
start-file-process temporary-file-directory
;; Emacs 27+ only.
- exec-path make-process))
+ exec-path make-process
+ ;; Emacs 29+ only.
+ list-system-processes process-attributes))
default-directory)
;; PROC.
((member operation '(file-notify-rm-watch file-notify-valid-p))
(when (processp (nth 0 args))
(tramp-get-default-directory (process-buffer (nth 0 args)))))
;; VEC.
- ((member operation '(tramp-get-remote-gid tramp-get-remote-uid))
+ ((member operation
+ '(tramp-get-home-directory
+ tramp-get-remote-gid tramp-get-remote-uid))
(tramp-make-tramp-file-name (nth 0 args)))
;; Unknown file primitive.
(t (error "Unknown file I/O primitive: %s" operation))))
-(defun tramp-find-foreign-file-name-handler (filename &optional _operation)
+(defun tramp-find-foreign-file-name-handler (vec &optional _operation)
"Return foreign file name handler if exists."
- (when (tramp-tramp-file-p filename)
+ (when (tramp-file-name-p vec)
(let ((handler tramp-foreign-file-name-handler-alist)
- (vec (tramp-dissect-file-name filename))
elt func res)
(while handler
(setq elt (car handler)
@@ -2633,7 +2677,7 @@ Fall back to normal file name handler if no Tramp file name handler exists."
(with-parsed-tramp-file-name filename nil
(let ((current-connection tramp-current-connection)
(foreign
- (tramp-find-foreign-file-name-handler filename operation))
+ (tramp-find-foreign-file-name-handler v operation))
(signal-hook-function #'tramp-signal-hook-function)
result)
;; Set `tramp-current-connection'.
@@ -2680,6 +2724,7 @@ Fall back to normal file name handler if no Tramp file name handler exists."
(tramp-message
v 5 "Non-essential received in operation %s"
(cons operation args))
+ (let ((tramp-verbose 10)) (tramp-backtrace v))
(tramp-run-real-handler operation args))
((eq result 'suppress)
(let ((inhibit-message t))
@@ -2732,17 +2777,21 @@ Falls back to normal file name handler if no Tramp file name handler exists."
(load "tramp" 'noerror 'nomessage)))
(apply operation args)))
+(put #'tramp-autoload-file-name-handler 'tramp-autoload t)
+
;; `tramp-autoload-file-name-handler' must be registered before
;; evaluation of site-start and init files, because there might exist
;; remote files already, f.e. files kept via recentf-mode.
;;;###autoload
(progn (defun tramp-register-autoload-file-name-handlers ()
"Add Tramp file name handlers to `file-name-handler-alist' during autoload."
- (add-to-list 'file-name-handler-alist
- (cons tramp-autoload-file-name-regexp
- #'tramp-autoload-file-name-handler))
- (put #'tramp-autoload-file-name-handler 'safe-magic t)))
+ (unless (rassq #'tramp-file-name-handler file-name-handler-alist)
+ (add-to-list 'file-name-handler-alist
+ (cons tramp-autoload-file-name-regexp
+ #'tramp-autoload-file-name-handler))
+ (put #'tramp-autoload-file-name-handler 'safe-magic t))))
+(put #'tramp-register-autoload-file-name-handlers 'tramp-autoload t)
;;;###autoload (tramp-register-autoload-file-name-handlers)
(defun tramp-use-absolute-autoload-file-names ()
@@ -2856,6 +2905,7 @@ whether HANDLER is to be called. Add operations defined in
(string-prefix-p "tramp-" (symbol-name (cdr fnh))))
(setq file-name-handler-alist (delq fnh file-name-handler-alist))))))
+(put #'tramp-unload-file-name-handlers 'tramp-autoload t)
(add-hook 'tramp-unload-hook #'tramp-unload-file-name-handlers)
;;; File name handler functions for completion mode:
@@ -2919,7 +2969,7 @@ not in completion mode."
(m (tramp-find-method method user host))
all-user-hosts)
- (unless localname ;; Nothing to complete.
+ (unless localname ;; Nothing to complete.
(if (or user host)
@@ -3323,6 +3373,129 @@ User is always nil."
(forward-line 1)
result))
+;;; Skeleton macros for file name handler functions.
+
+(defmacro tramp-skeleton-delete-directory (directory recursive trash &rest body)
+ "Skeleton for `tramp-*-handle-delete-directory'.
+BODY is the backend specific code."
+ (declare (indent 3) (debug t))
+ `(with-parsed-tramp-file-name (expand-file-name ,directory) nil
+ (if (and delete-by-moving-to-trash ,trash)
+ ;; Move non-empty dir to trash only if recursive deletion was
+ ;; requested.
+ (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
+ (tramp-error
+ v 'file-error "Directory is not empty, not moving to trash")
+ (move-file-to-trash ,directory))
+ ,@body)
+ (tramp-flush-directory-properties v localname)))
+
+(put #'tramp-skeleton-delete-directory 'tramp-suppress-trace t)
+
+(defmacro tramp-skeleton-write-region
+ (start end filename append visit lockname mustbenew &rest body)
+ "Skeleton for `tramp-*-handle-write-region'.
+BODY is the backend specific code."
+ (declare (indent 7) (debug t))
+ ;; Sometimes, there is another file name handler responsible for
+ ;; VISIT, for example `jka-compr-handler'. We must respect this.
+ ;; See Bug#55166.
+ `(let* ((filename (expand-file-name ,filename))
+ (lockname (file-truename (or ,lockname filename)))
+ (handler (and (stringp ,visit)
+ (let ((inhibit-file-name-handlers
+ `(tramp-file-name-handler
+ tramp-crypt-file-name-handler
+ . inhibit-file-name-handlers))
+ (inhibit-file-name-operation 'write-region))
+ (find-file-name-handler ,visit 'write-region)))))
+ (with-parsed-tramp-file-name filename nil
+ (if handler
+ (progn
+ (tramp-message
+ v 5 "Calling handler `%s' for visiting `%s'" handler ,visit)
+ (funcall
+ handler 'write-region
+ ,start ,end filename ,append ,visit lockname ,mustbenew))
+
+ (when (and ,mustbenew (file-exists-p filename)
+ (or (eq ,mustbenew 'excl)
+ (not
+ (y-or-n-p
+ (format
+ "File %s exists; overwrite anyway?" filename)))))
+ (tramp-error v 'file-already-exists filename))
+
+ (let ((file-locked (eq (file-locked-p lockname) t))
+ (uid (or (file-attribute-user-id
+ (file-attributes filename 'integer))
+ (tramp-get-remote-uid v 'integer)))
+ (gid (or (file-attribute-group-id
+ (file-attributes filename 'integer))
+ (tramp-get-remote-gid v 'integer)))
+ (attributes (file-extended-attributes filename))
+ (curbuf (current-buffer)))
+
+ ;; Lock file.
+ (when (and (not (auto-save-file-name-p
+ (file-name-nondirectory filename)))
+ (file-remote-p lockname)
+ (not file-locked))
+ (setq file-locked t)
+ ;; `lock-file' exists since Emacs 28.1.
+ (tramp-compat-funcall 'lock-file lockname))
+
+ ;; The body.
+ ,@body
+
+ ;; We must also flush the cache of the directory, because
+ ;; `file-attributes' reads the values from there.
+ (tramp-flush-file-properties v localname)
+
+ ;; We must protect `last-coding-system-used', now we have
+ ;; set it to its correct value.
+ (let (last-coding-system-used (need-chown t))
+ ;; Set file modification time.
+ (when (or (eq ,visit t) (stringp ,visit))
+ (when-let ((file-attr (file-attributes filename 'integer)))
+ (set-visited-file-modtime
+ ;; We must pass modtime explicitly, because FILENAME
+ ;; can be different from (buffer-file-name), f.e. if
+ ;; `file-precious-flag' is set.
+ (or (file-attribute-modification-time file-attr)
+ (current-time)))
+ (when (and (= (file-attribute-user-id file-attr) uid)
+ (= (file-attribute-group-id file-attr) gid))
+ (setq need-chown nil))))
+
+ ;; Set the ownership.
+ (when need-chown
+ (tramp-set-file-uid-gid filename uid gid)))
+
+ ;; Set extended attributes. We ignore possible errors,
+ ;; because ACL strings could be incompatible.
+ (when attributes
+ (ignore-errors
+ (set-file-extended-attributes filename attributes)))
+
+ ;; Unlock file.
+ (when file-locked
+ ;; `unlock-file' exists since Emacs 28.1.
+ (tramp-compat-funcall 'unlock-file lockname))
+
+ ;; Sanity check.
+ (unless (equal curbuf (current-buffer))
+ (tramp-error
+ v 'file-error
+ "Buffer has changed from `%s' to `%s'" curbuf (current-buffer)))
+
+ (when (and (null noninteractive)
+ (or (eq ,visit t) (string-or-null-p ,visit)))
+ (tramp-message v 0 "Wrote %s" filename))
+ (run-hooks 'tramp-handle-write-region-hook))))))
+
+(put #'tramp-skeleton-write-region 'tramp-suppress-trace t)
+
;;; Common file name handler functions for different backends:
(defvar tramp-handle-file-local-copy-hook nil
@@ -3331,6 +3504,10 @@ User is always nil."
(defvar tramp-handle-write-region-hook nil
"Normal hook to be run at the end of `tramp-*-handle-write-region'.")
+(defvar tramp-tolerate-tilde nil
+ "Indicator, that not expandable tilde shall be tolerated.
+Let-bind it when necessary.")
+
;; `directory-abbrev-apply' and `directory-abbrev-make-regexp' exists
;; since Emacs 29.1. Since this handler isn't called for older
;; Emacsen, it is save to invoke them via `tramp-compat-funcall'.
@@ -3338,20 +3515,30 @@ User is always nil."
"Like `abbreviate-file-name' for Tramp files."
(let* ((case-fold-search (file-name-case-insensitive-p filename))
(vec (tramp-dissect-file-name filename))
+ (tramp-tolerate-tilde t)
(home-dir
- (with-tramp-connection-property vec "home-directory"
- (tramp-compat-funcall
+ (if (let ((non-essential t)) (tramp-connectable-p vec))
+ ;; If a connection has already been established, get the
+ ;; home directory.
+ (tramp-get-home-directory vec)
+ ;; Otherwise, just use the cached value.
+ (tramp-get-connection-property vec "~"))))
+ (when home-dir
+ (setq home-dir
+ (tramp-compat-funcall
'directory-abbrev-apply
- (expand-file-name (tramp-make-tramp-file-name vec "~"))))))
+ (tramp-make-tramp-file-name vec home-dir))))
;; If any elt of `directory-abbrev-alist' matches this name,
;; abbreviate accordingly.
(setq filename (tramp-compat-funcall 'directory-abbrev-apply filename))
;; Abbreviate home directory.
- (if (string-match
- (tramp-compat-funcall 'directory-abbrev-make-regexp home-dir) filename)
+ (if (and home-dir
+ (string-match
+ (tramp-compat-funcall 'directory-abbrev-make-regexp home-dir)
+ filename))
(tramp-make-tramp-file-name
vec (concat "~" (substring filename (match-beginning 1))))
- filename)))
+ (tramp-make-tramp-file-name (tramp-dissect-file-name filename)))))
(defun tramp-handle-access-file (filename string)
"Like `access-file' for Tramp files."
@@ -3465,23 +3652,37 @@ User is always nil."
(setq name (tramp-compat-file-name-concat dir name)))
;; If NAME is not a Tramp file, run the real handler.
(if (not (tramp-tramp-file-p name))
- (tramp-run-real-handler #'expand-file-name (list name nil))
+ (tramp-run-real-handler #'expand-file-name (list name))
;; Dissect NAME.
(with-parsed-tramp-file-name name nil
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "/" localname)))
+ ;; Expand tilde. Usually, the methods applying this handler do
+ ;; not support tilde expansion. But users could declare a
+ ;; respective connection property. (Bug#53847)
+ (when (string-match "\\`~\\([^/]*\\)\\(.*\\)\\'" localname)
+ (let ((uname (match-string 1 localname))
+ (fname (match-string 2 localname))
+ hname)
+ (when (zerop (length uname))
+ (setq uname user))
+ (when (setq hname (tramp-get-home-directory v uname))
+ (setq localname (concat hname fname)))))
+ ;; Tilde expansion is not possible.
+ (when (and (not tramp-tolerate-tilde)
+ (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname))
+ (tramp-error v 'file-error "Cannot expand tilde in file `%s'" name))
;; Do not keep "/..".
(when (string-match-p "^/\\.\\.?$" localname)
(setq localname "/"))
- ;; Do normal `expand-file-name' (this does "/./" and "/../"),
- ;; unless there are tilde characters in file name.
+ ;; Do normal `expand-file-name' (this does "/./" and "/../").
;; `default-directory' is bound, because on Windows there would
;; be problems with UNC shares or Cygwin mounts.
(let ((default-directory tramp-compat-temporary-file-directory))
(tramp-make-tramp-file-name
- v (if (string-match-p "\\`~" localname)
- localname
- (tramp-drop-volume-letter
+ v (tramp-drop-volume-letter
+ (if (string-match-p "\\`\\(~[^/]*\\)\\(.*\\)\\'" localname)
+ localname
(tramp-run-real-handler #'expand-file-name (list localname)))))))))
(defun tramp-handle-file-accessible-directory-p (filename)
@@ -3678,10 +3879,10 @@ User is always nil."
;; We do not want traces in the debug buffer.
(let ((tramp-verbose (min tramp-verbose 3)))
(when (tramp-tramp-file-p filename)
- (let* ((v (tramp-dissect-file-name filename))
- (p (tramp-get-connection-process v))
+ (let* ((o (tramp-dissect-file-name filename))
+ (p (tramp-get-connection-process o))
(c (and (process-live-p p)
- (tramp-get-connection-property p "connected" nil))))
+ (tramp-get-connection-property p "connected"))))
;; We expand the file name only, if there is already a connection.
(with-parsed-tramp-file-name
(if c (expand-file-name filename) filename) nil
@@ -3693,7 +3894,8 @@ User is always nil."
((eq identification 'user) (tramp-file-name-user-domain v))
((eq identification 'host) (tramp-file-name-host-port v))
((eq identification 'localname) localname)
- ((eq identification 'hop) hop)
+ ;; Hop exists only in original dissected file name.
+ ((eq identification 'hop) (tramp-file-name-hop o))
(t (tramp-make-tramp-file-name v 'noloc)))))))))
(defun tramp-handle-file-selinux-context (_filename)
@@ -3744,8 +3946,7 @@ User is always nil."
(expand-file-name
symlink-target
(file-name-directory v2-localname))))
- v2-localname)
- 'nohop)))
+ v2-localname))))
(when (>= numchase numchase-limit)
(tramp-error
v1 'file-error
@@ -3904,8 +4105,7 @@ User is always nil."
(cond
((stringp remote-copy)
(file-local-copy
- (tramp-make-tramp-file-name
- v remote-copy 'nohop)))
+ (tramp-make-tramp-file-name v remote-copy)))
((stringp tramp-temp-buffer-file-name)
(copy-file
filename tramp-temp-buffer-file-name 'ok)
@@ -3948,11 +4148,162 @@ User is always nil."
(or remote-copy (null tramp-temp-buffer-file-name)))
(delete-file local-copy))
(when (stringp remote-copy)
- (delete-file (tramp-make-tramp-file-name v remote-copy 'nohop))))
+ (delete-file (tramp-make-tramp-file-name v remote-copy))))
;; Result.
(cons filename (cdr result)))))
+(defun tramp-ps-time ()
+ "Read printed time oif \"ps\" in format \"[[DD-]hh:]mm:ss\".
+Return it as number of seconds. Used in `tramp-process-attributes-ps-format'."
+ (search-forward-regexp "\\s-+")
+ (search-forward-regexp
+ (concat
+ "\\(?:" "\\(?:" "\\([0-9]+\\)-" "\\)?"
+ "\\([0-9]+\\):" "\\)?"
+ "\\([0-9]+\\):"
+ ;; Seconds can also be a floating point number.
+ "\\([0-9.]+\\)")
+ (line-end-position) 'noerror)
+ (+ (* 24 60 60 (string-to-number (or (match-string 1) "0")))
+ (* 60 60 (string-to-number (or (match-string 2) "0")))
+ (* 60 (string-to-number (or (match-string 3) "0")))
+ (string-to-number (or (match-string 4) "0"))))
+
+(defconst tramp-process-attributes-ps-args
+ `("-eww"
+ "-o"
+ ,(mapconcat
+ #'identity
+ '("pid"
+ "euid"
+ "euser"
+ "egid"
+ "egroup"
+ "comm:80"
+ "state"
+ "ppid"
+ "pgrp"
+ "sess"
+ "tname"
+ "tpgid"
+ "min_flt"
+ "maj_flt"
+ "times"
+ "pri"
+ "nice"
+ "thcount"
+ "vsize"
+ "rss"
+ "etimes"
+ "pcpu"
+ "pmem"
+ "args")
+ ","))
+ "List of arguments for calling \"ps\".
+See `tramp-get-process-attributes'.
+
+This list is the default value on remote GNU/Linux systems.")
+
+(defconst tramp-process-attributes-ps-format
+ '((pid . number)
+ (euid . number)
+ (user . string)
+ (egid . number)
+ (group . string)
+ (comm . 80)
+ (state . string)
+ (ppid . number)
+ (pgrp . number)
+ (sess . number)
+ (ttname . string)
+ (tpgid . number)
+ (minflt . number)
+ (majflt . number)
+ (time . number)
+ (pri . number)
+ (nice . number)
+ (thcount . number)
+ (vsize . number)
+ (rss . number)
+ (etime . number)
+ (pcpu . number)
+ (pmem . number)
+ (args . nil))
+ "Alist where each element is a cons cell of the form `\(KEY . TYPE)'.
+KEY is a key (symbol) used in `process-attributes'. TYPE is the
+printed result for KEY of the \"ps\" command, it can be `number',
+`string', a number (string of that length), a symbol (a function
+to be applied), or nil (for the last column of the \"ps\" output.
+
+This alist is used to parse the output of calling \"ps\" in
+`tramp-get-process-attributes'.
+
+This alist is the default value on remote GNU/Linux systems.")
+
+(defun tramp-get-process-attributes (vec)
+ "Return all process attributes for connection VEC.
+Parsing the remote \"ps\" output is controlled by
+`tramp-process-attributes-ps-args' and
+`tramp-process-attributes-ps-format'.
+
+It is not guaranteed, that all process attributes as described in
+`process-attributes' are returned. The additional attribute
+`pid' shall be returned always."
+ ;; Since Emacs 27.1.
+ (when (fboundp 'connection-local-criteria-for-default-directory)
+ (with-tramp-file-property vec "/" "process-attributes"
+ (ignore-errors
+ (with-temp-buffer
+ (hack-connection-local-variables-apply
+ (connection-local-criteria-for-default-directory))
+ ;; (pop-to-buffer (current-buffer))
+ (when (zerop
+ (apply
+ #'process-file
+ "ps" nil t nil tramp-process-attributes-ps-args))
+ (let (result res)
+ (goto-char (point-min))
+ (while (not (eobp))
+ ;; (tramp-test-message
+ ;; "%s" (buffer-substring (point) (line-end-position)))
+ (when (save-excursion
+ (search-forward-regexp
+ "[[:digit:]]" (line-end-position) 'noerror))
+ (setq res nil)
+ (dolist (elt tramp-process-attributes-ps-format)
+ (push
+ (cons
+ (car elt)
+ (cond
+ ((eq (cdr elt) 'number) (read (current-buffer)))
+ ((eq (cdr elt) 'string)
+ (search-forward-regexp "\\S-+")
+ (match-string 0))
+ ((numberp (cdr elt))
+ (search-forward-regexp "\\s-+")
+ (search-forward-regexp ".+" (+ (point) (cdr elt)))
+ (string-trim (match-string 0)))
+ ((fboundp (cdr elt))
+ (funcall (cdr elt)))
+ ((null (cdr elt))
+ (search-forward-regexp "\\s-+")
+ (buffer-substring (point) (line-end-position)))
+ (t nil)))
+ res))
+ ;; `nice' could be `-'.
+ (setq res (rassq-delete-all '- res))
+ (push (append res) result))
+ (forward-line))
+ ;; Return result.
+ result)))))))
+
+(defun tramp-handle-list-system-processes ()
+ "Like `list-system-processes' for Tramp files."
+ (let ((v (tramp-dissect-file-name default-directory)))
+ (tramp-flush-file-property v "/" "process-attributes")
+ (mapcar (lambda (x) (cdr (assq 'pid x))) (tramp-get-process-attributes v))))
+
(defun tramp-get-lock-file (file)
"Read lockfile info of FILE.
Return nil when there is no lockfile."
@@ -3988,7 +4339,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(match (string-match tramp-lock-file-info-regexp info)))
(or ; Locked by me.
(and (string-equal (match-string 1 info) (user-login-name))
- (string-equal (match-string 2 info) (system-name))
+ (string-equal (match-string 2 info) tramp-system-name)
(string-equal (match-string 3 info) (tramp-get-lock-pid file)))
; User name.
(match-string 1 info))))
@@ -3999,6 +4350,14 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
;; was visited.
(catch 'dont-lock
(unless (eq (file-locked-p file) t) ;; Locked by me.
+ (when (and buffer-file-truename
+ (not (verify-visited-file-modtime))
+ (file-exists-p file))
+ ;; In filelock.c, `userlock--ask-user-about-supersession-threat'
+ ;; is called, which also checks file contents. This is unwise
+ ;; for remote files.
+ (ask-user-about-supersession-threat file))
+
(when-let ((info (tramp-get-lock-file file))
(match (string-match tramp-lock-file-info-regexp info)))
(unless (ask-user-about-lock
@@ -4011,7 +4370,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
;; USER@HOST.PID[:BOOT_TIME]
(info
(format
- "%s@%s.%s" (user-login-name) (system-name)
+ "%s@%s.%s" (user-login-name) tramp-system-name
(tramp-get-lock-pid file))))
;; Protect against security hole.
@@ -4037,7 +4396,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(make-symbolic-link info lockname 'ok-if-already-exists)
(error
(with-file-modes #o0644
- (write-region info nil lockname)))))))))
+ (write-region info nil lockname nil 'no-message)))))))))
(defun tramp-handle-make-lock-file-name (file)
"Like `make-lock-file-name' for Tramp files."
@@ -4088,15 +4447,10 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(and (tramp-sh-file-name-handler-p vec)
(not (tramp-get-method-parameter vec 'tramp-copy-program))))
-(defun tramp-compute-multi-hops (vec)
- "Expands VEC according to `tramp-default-proxies-alist'."
- (let ((saved-tdpa tramp-default-proxies-alist)
- (target-alist `(,vec))
- (hops (or (tramp-file-name-hop vec) ""))
- (item vec)
- choices proxy)
-
- ;; Ad-hoc proxy definitions.
+(defun tramp-add-hops (vec)
+ "Add ad-hoc proxy definitions to `tramp-default-proxies-alist'."
+ (when-let ((hops (tramp-file-name-hop vec))
+ (item vec))
(dolist (proxy (reverse (split-string hops tramp-postfix-hop-regexp 'omit)))
(let* ((host-port (tramp-file-name-host-port item))
(user-domain (tramp-file-name-user-domain item))
@@ -4113,9 +4467,19 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(add-to-list 'tramp-default-proxies-alist entry)
(setq item (tramp-dissect-file-name proxy))))
;; Save the new value.
- (when (and hops tramp-save-ad-hoc-proxies)
+ (when tramp-save-ad-hoc-proxies
(customize-save-variable
- 'tramp-default-proxies-alist tramp-default-proxies-alist))
+ 'tramp-default-proxies-alist tramp-default-proxies-alist))))
+
+(defun tramp-compute-multi-hops (vec)
+ "Expands VEC according to `tramp-default-proxies-alist'."
+ (let ((saved-tdpa tramp-default-proxies-alist)
+ (target-alist `(,vec))
+ (item vec)
+ choices proxy)
+
+ ;; Ad-hoc proxy definitions.
+ (tramp-add-hops vec)
;; Look for proxy hosts to be passed.
(setq choices tramp-default-proxies-alist)
@@ -4204,7 +4568,7 @@ substitution. SPEC-LIST is a list of char/value pairs used for
(and ;; The method supports it.
(tramp-get-method-parameter v 'tramp-direct-async)
;; It has been indicated.
- (tramp-get-connection-property v "direct-async-process" nil)
+ (tramp-get-connection-property v "direct-async-process")
;; There's no multi-hop.
(or (not (tramp-multi-hop-p v))
(= (length (tramp-compute-multi-hops v)) 1))
@@ -4255,6 +4619,7 @@ substitution. SPEC-LIST is a list of char/value pairs used for
(get-buffer-create buffer)
;; BUFFER can be nil. We use a temporary buffer.
(generate-new-buffer tramp-temp-buffer-name)))
+ (orig-command command)
(env (mapcar
(lambda (elt)
(when (tramp-compat-string-search "=" elt) elt))
@@ -4276,7 +4641,9 @@ substitution. SPEC-LIST is a list of char/value pairs used for
(command (mapconcat #'tramp-shell-quote-argument command " "))
;; Set cwd and environment variables.
(command
- (append `("cd" ,localname "&&" "(" "env") env `(,command ")"))))
+ (append
+ `("cd" ,(tramp-shell-quote-argument localname) "&&" "(" "env")
+ env `(,command ")"))))
;; Check for `tramp-sh-file-name-handler', because something
;; is different between tramp-sh.el, and tramp-adb.el or
@@ -4328,6 +4695,8 @@ substitution. SPEC-LIST is a list of char/value pairs used for
;; t. See Bug#51177.
(when filter
(set-process-filter p filter))
+ (process-put p 'remote-command orig-command)
+ (tramp-set-connection-property p "remote-command" orig-command)
(tramp-message v 6 "%s" (string-join (process-command p) " "))
p))))))
@@ -4341,6 +4710,14 @@ support symbolic links."
(tramp-dissect-file-name (expand-file-name linkname)) 'file-error
"make-symbolic-link not supported"))
+(defun tramp-handle-process-attributes (pid)
+ "Like `process-attributes' for Tramp files."
+ (catch 'result
+ (dolist (elt (tramp-get-process-attributes
+ (tramp-dissect-file-name default-directory)))
+ (when (= (cdr (assq 'pid elt)) pid)
+ (throw 'result elt)))))
+
(defun tramp-handle-shell-command (command &optional output-buffer error-buffer)
"Like `shell-command' for Tramp files."
(let* ((asynchronous (string-match-p "[ \t]*&[ \t]*\\'" command))
@@ -4472,7 +4849,7 @@ support symbolic links."
(prog1
;; Run the process.
- (process-file-shell-command command nil buffer nil)
+ (process-file-shell-command command nil buffer)
;; Insert error messages if they were separated.
(when error-file
(with-current-buffer error-buffer
@@ -4537,10 +4914,7 @@ BUFFER might be a list, in this case STDERR is separated."
;; We must disable cygwin-mount file name
;; handlers and alike.
(tramp-run-real-handler
- #'substitute-in-file-name (list localname))))))))
- ;; "/m:h:~" does not work for completion. We use "/m:h:~/".
- (if (and (stringp localname) (string-equal "~" localname))
- (concat filename "/")
+ #'substitute-in-file-name (list localname)))))))
filename))))
(defconst tramp-time-dont-know '(0 0 0 1000)
@@ -4598,33 +4972,10 @@ of."
(defun tramp-handle-write-region
(start end filename &optional append visit lockname mustbenew)
"Like `write-region' for Tramp files."
- (setq filename (expand-file-name filename)
- lockname (file-truename (or lockname filename)))
- (with-parsed-tramp-file-name filename nil
- (when (and mustbenew (file-exists-p filename)
- (or (eq mustbenew 'excl)
- (not
- (y-or-n-p
- (format "File %s exists; overwrite anyway?" filename)))))
- (tramp-error v 'file-already-exists filename))
-
- (let ((file-locked (eq (file-locked-p lockname) t))
- (tmpfile (tramp-compat-make-temp-file filename))
+ (tramp-skeleton-write-region start end filename append visit lockname mustbenew
+ (let ((tmpfile (tramp-compat-make-temp-file filename))
(modes (tramp-default-file-modes
- filename (and (eq mustbenew 'excl) 'nofollow)))
- (uid (or (file-attribute-user-id (file-attributes filename 'integer))
- (tramp-get-remote-uid v 'integer)))
- (gid (or (file-attribute-group-id (file-attributes filename 'integer))
- (tramp-get-remote-gid v 'integer))))
-
- ;; Lock file.
- (when (and (not (auto-save-file-name-p (file-name-nondirectory filename)))
- (file-remote-p lockname)
- (not file-locked))
- (setq file-locked t)
- ;; `lock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'lock-file lockname))
-
+ filename (and (eq mustbenew 'excl) 'nofollow))))
(when (and append (file-exists-p filename))
(copy-file filename tmpfile 'ok))
;; The permissions of the temporary file should be set. If
@@ -4643,29 +4994,7 @@ of."
(error
(delete-file tmpfile)
(tramp-error
- v 'file-error "Couldn't write region to `%s'" filename)))
-
- (tramp-flush-file-properties v localname)
-
- ;; Set file modification time.
- (when (or (eq visit t) (stringp visit))
- (set-visited-file-modtime
- (or (file-attribute-modification-time (file-attributes filename))
- (current-time))))
-
- ;; Set the ownership.
- (tramp-set-file-uid-gid filename uid gid)
-
- ;; Unlock file.
- (when file-locked
- ;; `unlock-file' exists since Emacs 28.1.
- (tramp-compat-funcall 'unlock-file lockname))
-
- ;; The end.
- (when (and (null noninteractive)
- (or (eq visit t) (string-or-null-p visit)))
- (tramp-message v 0 "Wrote %s" filename))
- (run-hooks 'tramp-handle-write-region-hook))))
+ v 'file-error "Couldn't write region to `%s'" filename))))))
;; This is used in tramp-sh.el and tramp-sudoedit.el.
(defconst tramp-stat-marker "/////"
@@ -4744,7 +5073,8 @@ of."
;; Let's check whether a wrong password has been sent already.
;; Sometimes, the process returns a new password request
;; immediately after rejecting the previous (wrong) one.
- (unless (tramp-get-connection-property vec "first-password-request" nil)
+ (unless (or tramp-password-prompt-not-unique
+ (tramp-get-connection-property vec "first-password-request"))
(tramp-clear-passwd vec))
(goto-char (point-min))
(tramp-check-for-regexp proc tramp-process-action-regexp)
@@ -4752,7 +5082,13 @@ of."
;; We don't call `tramp-send-string' in order to hide the
;; password from the debug buffer and the traces.
(process-send-string
- proc (concat (tramp-read-passwd proc) tramp-local-end-of-line))
+ proc
+ (concat
+ (funcall
+ (if tramp-password-prompt-not-unique
+ #'tramp-read-passwd-without-cache #'tramp-read-passwd)
+ proc)
+ tramp-local-end-of-line))
;; Hide password prompt.
(narrow-to-region (point-max) (point-max))))
t)
@@ -4941,8 +5277,9 @@ performed successfully. Any other value means an error."
(tramp-message vec 6 "\n%s" (buffer-string)))
(if (eq exit 'ok)
(ignore-errors
- (and (functionp tramp-password-save-function)
- (funcall tramp-password-save-function)))
+ (when (functionp tramp-password-save-function)
+ (funcall tramp-password-save-function)
+ (setq tramp-password-save-function nil)))
;; Not successful.
(tramp-clear-passwd vec)
(delete-process proc)
@@ -4981,7 +5318,7 @@ performed successfully. Any other value means an error."
"Lock PROC for other communication, and run BODY.
Mostly useful to protect BODY from being interrupted by timers."
(declare (indent 1) (debug t))
- `(if (tramp-get-connection-property ,proc "locked" nil)
+ `(if (tramp-get-connection-property ,proc "locked")
;; Be kind for older Emacsen.
(if (member 'remote-file-error debug-ignored-errors)
(throw 'non-essential 'non-essential)
@@ -4993,9 +5330,6 @@ Mostly useful to protect BODY from being interrupted by timers."
,@body)
(tramp-flush-connection-property ,proc "locked"))))
-(font-lock-add-keywords
- 'emacs-lisp-mode '("\\<with-tramp-locked-connection\\>"))
-
(defun tramp-accept-process-output (proc &optional timeout)
"Like `accept-process-output' for Tramp processes.
This is needed in order to hide `last-coding-system-used', which is set
@@ -5037,7 +5371,7 @@ Erase echoed commands if exists."
;; Check whether we need to remove echo output. The max length of
;; the echo mark regexp is taken for search. We restrict the
;; search for the second echo mark to PIPE_BUF characters.
- (when (and (tramp-get-connection-property proc "check-remote-echo" nil)
+ (when (and (tramp-get-connection-property proc "check-remote-echo")
(re-search-forward
tramp-echoed-echo-mark-regexp
(+ (point) (* 5 tramp-echo-mark-marker-length)) t))
@@ -5053,7 +5387,7 @@ Erase echoed commands if exists."
(delete-region begin (point))
(goto-char (point-min)))))
- (when (or (not (tramp-get-connection-property proc "check-remote-echo" nil))
+ (when (or (not (tramp-get-connection-property proc "check-remote-echo"))
;; Sometimes, the echo string is suppressed on the remote side.
(not (string-equal
(substring-no-properties
@@ -5115,7 +5449,7 @@ The STRING is expected to use Unix line-endings, but the lines sent to
the remote host use line-endings as defined in the variable
`tramp-rsh-end-of-line'. The communication buffer is erased before sending."
(let* ((p (tramp-get-connection-process vec))
- (chunksize (tramp-get-connection-property p "chunksize" nil)))
+ (chunksize (tramp-get-connection-property p "chunksize")))
(unless p
(tramp-error
vec 'file-error "Can't send string to remote host -- not logged in"))
@@ -5153,7 +5487,7 @@ the remote host use line-endings as defined in the variable
(unless (process-live-p proc)
(let ((vec (process-get proc 'vector))
(buf (process-buffer proc))
- (prompt (tramp-get-connection-property proc "prompt" nil)))
+ (prompt (tramp-get-connection-property proc "prompt")))
(when vec
(tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
(tramp-flush-connection-properties proc)
@@ -5319,8 +5653,10 @@ If FILENAME is remote, a file name handler is called."
(when (and modes (not (zerop (logand modes #o2000))))
(setq gid (file-attribute-group-id (file-attributes dir)))))
- (if-let ((handler (find-file-name-handler filename 'tramp-set-file-uid-gid)))
- (funcall handler #'tramp-set-file-uid-gid filename uid gid)
+ (if (tramp-tramp-file-p filename)
+ (funcall (if (tramp-crypt-file-name-p filename)
+ #'tramp-crypt-file-name-handler #'tramp-file-name-handler)
+ #'tramp-set-file-uid-gid filename uid gid)
;; On W32 systems, "chown" does not work.
(unless (memq system-type '(ms-dos windows-nt))
(let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer)))
@@ -5375,11 +5711,12 @@ VEC is used for tracing."
"Check `file-attributes' caches for VEC.
Return t if according to the cache access type ACCESS is known to
be granted."
- (let ((result nil)
+ (let (result
(offset (cond
((eq ?r access) 1)
((eq ?w access) 2)
- ((eq ?x access) 3))))
+ ((eq ?x access) 3)
+ ((eq ?s access) 3))))
(dolist (suffix '("string" "integer") result)
(setq
result
@@ -5409,40 +5746,45 @@ be granted."
;; User accessible and owned by user.
(and
(eq access (aref (file-attribute-modes file-attr) offset))
- (or (equal remote-uid (file-attribute-user-id file-attr))
+ (or (equal remote-uid unknown-id)
+ (equal remote-uid (file-attribute-user-id file-attr))
(equal unknown-id (file-attribute-user-id file-attr))))
;; Group accessible and owned by user's principal group.
(and
(eq access
(aref (file-attribute-modes file-attr) (+ offset 3)))
- (or (equal remote-gid (file-attribute-group-id file-attr))
+ (or (equal remote-gid unknown-id)
+ (equal remote-gid (file-attribute-group-id file-attr))
(equal unknown-id (file-attribute-group-id file-attr))))))))))))
+(defun tramp-get-home-directory (vec &optional user)
+ "The remote home directory for connection VEC as local file name.
+If USER is a string, return its home directory instead of the
+user identified by VEC. If there is no user specified in either
+VEC or USER, or if there is no home directory, return nil."
+ (and (tramp-file-name-p vec)
+ (with-tramp-connection-property vec (concat "~" user)
+ (tramp-file-name-handler #'tramp-get-home-directory vec user))))
+
(defun tramp-get-remote-uid (vec id-format)
"The uid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
- (with-tramp-connection-property vec (format "uid-%s" id-format)
- (or (when-let
- ((handler
- (find-file-name-handler
- (tramp-make-tramp-file-name vec) 'tramp-get-remote-uid)))
- (funcall handler #'tramp-get-remote-uid vec id-format))
- ;; Ensure there is a valid result.
- (and (equal id-format 'integer) tramp-unknown-id-integer)
- (and (equal id-format 'string) tramp-unknown-id-string))))
+ (or (and (tramp-file-name-p vec)
+ (with-tramp-connection-property vec (format "uid-%s" id-format)
+ (tramp-file-name-handler #'tramp-get-remote-uid vec id-format)))
+ ;; Ensure there is a valid result.
+ (and (equal id-format 'integer) tramp-unknown-id-integer)
+ (and (equal id-format 'string) tramp-unknown-id-string)))
(defun tramp-get-remote-gid (vec id-format)
"The gid of the remote connection VEC, in ID-FORMAT.
ID-FORMAT valid values are `string' and `integer'."
- (with-tramp-connection-property vec (format "gid-%s" id-format)
- (or (when-let
- ((handler
- (find-file-name-handler
- (tramp-make-tramp-file-name vec) 'tramp-get-remote-gid)))
- (funcall handler #'tramp-get-remote-gid vec id-format))
- ;; Ensure there is a valid result.
- (and (equal id-format 'integer) tramp-unknown-id-integer)
- (and (equal id-format 'string) tramp-unknown-id-string))))
+ (or (and (tramp-file-name-p vec)
+ (with-tramp-connection-property vec (format "gid-%s" id-format)
+ (tramp-file-name-handler #'tramp-get-remote-gid vec id-format)))
+ ;; Ensure there is a valid result.
+ (and (equal id-format 'integer) tramp-unknown-id-integer)
+ (and (equal id-format 'string) tramp-unknown-id-string)))
(defun tramp-local-host-p (vec)
"Return t if this points to the local host, nil otherwise.
@@ -5462,8 +5804,7 @@ This handles also chrooted environments, which are not regarded as local."
(null tramp-crypt-enabled)
;; The local temp directory must be writable for the other user.
(file-writable-p
- (tramp-make-tramp-file-name
- vec tramp-compat-temporary-file-directory 'nohop))
+ (tramp-make-tramp-file-name vec tramp-compat-temporary-file-directory))
;; On some systems, chown runs only for root.
(or (zerop (user-uid))
(zerop (tramp-get-remote-uid vec 'integer))))))
@@ -5685,39 +6026,44 @@ verbosity of 6."
"Return t if system process PROCESS-NAME is running for `user-login-name'."
(when (stringp process-name)
(catch 'result
- (dolist (pid (list-system-processes))
- (when-let ((attributes (process-attributes pid))
- (comm (cdr (assoc 'comm attributes))))
- (and (string-equal (cdr (assoc 'user attributes)) (user-login-name))
- ;; The returned command name could be truncated to 15
- ;; characters. Therefore, we cannot check for `string-equal'.
- (string-prefix-p comm process-name)
- (throw 'result t)))))))
+ (let ((default-directory temporary-file-directory))
+ (dolist (pid (list-system-processes))
+ (when-let ((attributes (process-attributes pid))
+ (comm (cdr (assoc 'comm attributes))))
+ (and (string-equal (cdr (assoc 'user attributes)) (user-login-name))
+ ;; The returned command name could be truncated to 15
+ ;; characters. Therefore, we cannot check for `string-equal'.
+ (string-prefix-p comm process-name)
+ (throw 'result t))))))))
;; When calling "emacs -Q", `auth-source-search' won't be called. If
;; you want to debug exactly this case, call "emacs -Q --eval '(setq
;; tramp-cache-read-persistent-data t)'" instead.
(defun tramp-read-passwd (proc &optional prompt)
"Read a password from user (compat function).
-Consults the auth-source package.
-Invokes `password-read' if available, `read-passwd' else."
+Consults the auth-source package."
(let* (;; If `auth-sources' contains "~/.authinfo.gpg", and
;; `exec-path' contains a relative file name like ".", it
;; could happen that the "gpg" command is not found. So we
;; adapt `default-directory'. (Bug#39389, Bug#39489)
(default-directory tramp-compat-temporary-file-directory)
(case-fold-search t)
- (key (tramp-make-tramp-file-name
- ;; In tramp-sh.el, we must use "password-vector" due to
- ;; multi-hop.
- (tramp-get-connection-property
- proc "password-vector" (process-get proc 'vector))
- 'noloc 'nohop))
+ ;; In tramp-sh.el, we must use "password-vector" due to
+ ;; multi-hop.
+ (vec (tramp-get-connection-property
+ proc "password-vector" (process-get proc 'vector)))
+ (key (tramp-make-tramp-file-name vec 'noloc))
+ (method (tramp-file-name-method vec))
+ (user (or (tramp-file-name-user-domain vec)
+ (tramp-get-connection-property key "login-as")))
+ (host (tramp-file-name-host-port vec))
(pw-prompt
(or prompt
(with-current-buffer (process-buffer proc)
(tramp-check-for-regexp proc tramp-password-prompt-regexp)
- (format "%s for %s " (capitalize (match-string 1)) key))))
+ (if (string-match-p "passphrase" (match-string 1))
+ (match-string 0)
+ (format "%s for %s " (capitalize (match-string 1)) key)))))
(auth-source-creation-prompts `((secret . ,pw-prompt)))
;; Use connection-local value.
(auth-sources (buffer-local-value 'auth-sources (process-buffer proc)))
@@ -5726,59 +6072,60 @@ Invokes `password-read' if available, `read-passwd' else."
auth-info auth-passwd)
(unwind-protect
- (with-parsed-tramp-file-name key nil
- (setq tramp-password-save-function nil
- user
- (or user (tramp-get-connection-property key "login-as" nil)))
- (prog1
- (or
- ;; See if auth-sources contains something useful.
- (ignore-errors
- (and (tramp-get-connection-property
- v "first-password-request" nil)
- ;; Try with Tramp's current method.
- (setq auth-info
- (car
- (auth-source-search
- :max 1
- (and user :user)
- (if domain
- (concat
- user tramp-prefix-domain-format domain)
- user)
- :host
- (if port
- (concat
- host tramp-prefix-port-format port)
- host)
- :port method
- :require (cons :secret (and user '(:user)))
- :create t))
- tramp-password-save-function
- (plist-get auth-info :save-function)
- auth-passwd (plist-get auth-info :secret)))
- (while (functionp auth-passwd)
- (setq auth-passwd (funcall auth-passwd)))
- auth-passwd)
-
- ;; Try the password cache.
- (progn
- (setq auth-passwd (password-read pw-prompt key)
- tramp-password-save-function
- (lambda () (password-cache-add key auth-passwd)))
- auth-passwd))
+ ;; We cannot use `with-parsed-tramp-file-name', because it
+ ;; expands the file name.
+ (or
+ (setq tramp-password-save-function nil)
+ ;; See if auth-sources contains something useful.
+ (ignore-errors
+ (and (tramp-get-connection-property vec "first-password-request")
+ ;; Try with Tramp's current method. If there is no
+ ;; user name, `:create' triggers to ask for. We
+ ;; suppress it.
+ (setq auth-info
+ (car
+ (auth-source-search
+ :max 1 :user user :host host :port method
+ :require (cons :secret (and user '(:user)))
+ :create (and user t)))
+ tramp-password-save-function
+ (plist-get auth-info :save-function)
+ auth-passwd
+ (tramp-compat-auth-info-password auth-info))))
+
+ ;; Try the password cache.
+ (progn
+ (setq auth-passwd (password-read pw-prompt key)
+ tramp-password-save-function
+ (lambda () (password-cache-add key auth-passwd)))
+ auth-passwd))
- ;; Workaround. Prior Emacs 28.1, auth-source has saved
- ;; empty passwords. See discussion in Bug#50399.
- (when (zerop (length auth-passwd))
- (setq tramp-password-save-function nil))
- (tramp-set-connection-property v "first-password-request" nil)))
+ ;; Workaround. Prior Emacs 28.1, auth-source has saved empty
+ ;; passwords. See discussion in Bug#50399.
+ (when (zerop (length auth-passwd))
+ (setq tramp-password-save-function nil))
+ (tramp-set-connection-property vec "first-password-request" nil)
;; Reenable the timers.
(with-timeout-unsuspend stimers))))
(put #'tramp-read-passwd 'tramp-suppress-trace t)
+(defun tramp-read-passwd-without-cache (proc &optional prompt)
+ "Read a password from user (compat function)."
+ ;; We suspend the timers while reading the password.
+ (let ((stimers (with-timeout-suspend)))
+ (unwind-protect
+ (password-read
+ (or prompt
+ (with-current-buffer (process-buffer proc)
+ (tramp-check-for-regexp proc tramp-password-prompt-regexp)
+ (match-string 0))))
+ ;; Reenable the timers.
+ (with-timeout-unsuspend stimers))))
+
+(put #'tramp-read-passwd-without-cache 'tramp-suppress-trace t)
+
(defun tramp-clear-passwd (vec)
"Clear password cache for connection related to VEC."
(let ((method (tramp-file-name-method vec))
@@ -5791,7 +6138,7 @@ Invokes `password-read' if available, `read-passwd' else."
(auth-source-forget
`(:max 1 ,(and user-domain :user) ,user-domain
:host ,host-port :port ,method))
- (password-cache-remove (tramp-make-tramp-file-name vec 'noloc 'nohop))))
+ (password-cache-remove (tramp-make-tramp-file-name vec 'noloc))))
(put #'tramp-clear-passwd 'tramp-suppress-trace t)
@@ -5884,32 +6231,54 @@ name of a process or buffer, or nil to default to the current buffer."
(lambda ()
(remove-hook 'interrupt-process-functions #'tramp-interrupt-process)))
+(defun tramp-signal-process (process sigcode &optional remote)
+ "Send PROCESS the signal with code SIGCODE.
+PROCESS may also be a number specifying the process id of the
+process to signal; in this case, the process need not be a child of
+this Emacs.
+If PROCESS is a process object which contains the property
+`remote-pid', or PROCESS is a number and REMOTE is a remote file name,
+PROCESS is interpreted as process on the respective remote host, which
+will be the process to signal.
+SIGCODE may be an integer, or a symbol whose name is a signal name."
+ (let (pid vec)
+ (cond
+ ((processp process)
+ (setq pid (process-get process 'remote-pid)
+ vec (process-get process 'vector)))
+ ((numberp process)
+ (setq pid process
+ vec (and (stringp remote) (tramp-dissect-file-name remote))))
+ (t (signal 'wrong-type-argument (list #'processp process))))
+ (unless (or (numberp sigcode) (symbolp sigcode))
+ (signal 'wrong-type-argument (list #'numberp sigcode)))
+ ;; If it's a Tramp process, send SIGCODE remotely.
+ (when (and pid vec)
+ (tramp-message
+ vec 5 "Send signal %s to process %s with pid %s" sigcode process pid)
+ ;; This is for tramp-sh.el. Other backends do not support this (yet).
+ (if (tramp-compat-funcall
+ 'tramp-send-command-and-check
+ vec (format "\\kill -%s %d" sigcode pid))
+ 0 -1))))
+
+;; `signal-process-functions' exists since Emacs 29.1.
+(when (boundp 'signal-process-functions)
+ (add-hook 'signal-process-functions #'tramp-signal-process)
+ (add-hook
+ 'tramp-unload-hook
+ (lambda ()
+ (remove-hook 'signal-process-functions #'tramp-signal-process))))
+
(defun tramp-get-remote-null-device (vec)
"Return null device on the remote host identified by VEC.
-If VEC is nil, return local null device."
- (if (null vec)
+If VEC is `tramp-null-hop', return local null device."
+ (if (equal vec tramp-null-hop)
null-device
(with-tramp-connection-property vec "null-device"
(let ((default-directory (tramp-make-tramp-file-name vec)))
(tramp-compat-null-device)))))
-(defmacro tramp-skeleton-delete-directory (directory recursive trash &rest body)
- "Skeleton for `tramp-*-handle-delete-directory'.
-BODY is the backend specific code."
- (declare (indent 3) (debug t))
- `(with-parsed-tramp-file-name (expand-file-name ,directory) nil
- (if (and delete-by-moving-to-trash ,trash)
- ;; Move non-empty dir to trash only if recursive deletion was
- ;; requested.
- (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
- (tramp-error
- v 'file-error "Directory is not empty, not moving to trash")
- (move-file-to-trash ,directory))
- ,@body)
- (tramp-flush-directory-properties v localname)))
-
-(put #'tramp-skeleton-delete-directory 'tramp-suppress-trace t)
-
;; Checklist for `tramp-unload-hook'
;; - Unload all `tramp-*' packages
;; - Reset `file-name-handler-alist'
@@ -5924,6 +6293,8 @@ BODY is the backend specific code."
;; Maybe it's not loaded yet.
(ignore-errors (unload-feature 'tramp 'force))))
+(put #'tramp-unload-tramp 'tramp-autoload t)
+
(provide 'tramp)
(run-hooks 'tramp--startup-hook)
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index e3bcd568d72..68fd110ec00 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -52,12 +52,13 @@
;; Suppress message from `emacs-repository-get-branch'. We must
;; also handle out-of-tree builds.
(let ((inhibit-message t)
- (debug-on-error nil)
(dir (or (locate-dominating-file (locate-library "tramp") ".git")
- source-directory)))
+ source-directory))
+ debug-on-error)
;; `emacs-repository-get-branch' has been introduced with Emacs 27.1.
(with-no-warnings
(and (stringp dir) (file-directory-p dir)
+ (executable-find "git")
(emacs-repository-get-branch dir)))))
"The repository branch of the Tramp sources.")
@@ -66,10 +67,11 @@
;; Suppress message from `emacs-repository-get-version'. We must
;; also handle out-of-tree builds.
(let ((inhibit-message t)
- (debug-on-error nil)
(dir (or (locate-dominating-file (locate-library "tramp") ".git")
- source-directory)))
+ source-directory))
+ debug-on-error)
(and (stringp dir) (file-directory-p dir)
+ (executable-find "git")
(emacs-repository-get-version dir))))
"The repository revision of the Tramp sources.")
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 95adf9f90a1..385dd80beba 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -1235,33 +1235,21 @@ changed with `comment-style'."
;; FIXME: maybe we should call uncomment depending on ARG.
(funcall comment-region-function beg end arg)))
-(defun comment-region-default-1 (beg end &optional arg noadjust)
- "Comment region between BEG and END.
-See `comment-region' for ARG. If NOADJUST, do not skip past
-leading/trailing space when determining the region to comment
-out."
+(defun comment-region-default-1 (beg end &optional arg)
(let* ((numarg (prefix-numeric-value arg))
(style (cdr (assoc comment-style comment-styles)))
(lines (nth 2 style))
(block (nth 1 style))
(multi (nth 0 style)))
- (if noadjust
- (when (bolp)
- (setq end (1- end)))
- ;; We use `chars' instead of `syntax' because `\n' might be
- ;; of end-comment syntax rather than of whitespace syntax.
- ;; sanitize BEG and END
- (goto-char beg)
- (skip-chars-forward " \t\n\r")
- (beginning-of-line)
- (setq beg (max beg (point)))
- (goto-char end)
- (skip-chars-backward " \t\n\r")
- (end-of-line)
- (setq end (min end (point)))
- (when (>= beg end)
- (error "Nothing to comment")))
+ ;; We use `chars' instead of `syntax' because `\n' might be
+ ;; of end-comment syntax rather than of whitespace syntax.
+ ;; sanitize BEG and END
+ (goto-char beg) (skip-chars-forward " \t\n\r") (beginning-of-line)
+ (setq beg (max beg (point)))
+ (goto-char end) (skip-chars-backward " \t\n\r") (end-of-line)
+ (setq end (min end (point)))
+ (if (>= beg end) (error "Nothing to comment"))
;; sanitize LINES
(setq lines
diff --git a/lisp/notifications.el b/lisp/notifications.el
index 5ad64ff73b6..b58a1a02116 100644
--- a/lisp/notifications.el
+++ b/lisp/notifications.el
@@ -202,7 +202,7 @@ This function returns a notification id, an integer, which can be
used to manipulate the notification item with
`notifications-close-notification' or the `:replaces-id' argument
of another `notifications-notify' call."
- (with-demoted-errors
+ (with-demoted-errors "Notification error: %S"
(let ((bus (or (plist-get params :bus) :session))
(title (plist-get params :title))
(body (plist-get params :body))
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index b8f6cb5ad36..dfe5c369e2c 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -369,31 +369,29 @@ and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph
corresponding to the referenced character following the character
reference.")
-(defvar nxml-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\M-\C-u" 'nxml-backward-up-element)
- (define-key map "\M-\C-d" 'nxml-down-element)
- (define-key map "\M-\C-n" 'nxml-forward-element)
- (define-key map "\M-\C-p" 'nxml-backward-element)
- (define-key map "\M-{" 'nxml-backward-paragraph)
- (define-key map "\M-}" 'nxml-forward-paragraph)
- (define-key map "\M-h" 'nxml-mark-paragraph)
- (define-key map "\C-c\C-f" 'nxml-finish-element)
- (define-key map "\C-c]" 'nxml-finish-element)
- (define-key map "\C-c/" 'nxml-finish-element)
- (define-key map "\C-c\C-m" 'nxml-split-element)
- (define-key map "\C-c\C-b" 'nxml-balanced-close-start-tag-block)
- (define-key map "\C-c\C-i" 'nxml-balanced-close-start-tag-inline)
- (define-key map "\C-c\C-x" 'nxml-insert-xml-declaration)
- (define-key map "\C-c\C-d" 'nxml-dynamic-markup-word)
- ;; u is for Unicode
- (define-key map "\C-c\C-u" 'nxml-insert-named-char)
- (define-key map "\C-c\C-o" nxml-outline-prefix-map)
- (define-key map [S-mouse-2] 'nxml-mouse-hide-direct-text-content)
- (define-key map "/" 'nxml-electric-slash)
- (define-key map "\M-\t" 'completion-at-point)
- map)
- "Keymap for `nxml-mode'.")
+(defvar-keymap nxml-mode-map
+ :doc "Keymap for `nxml-mode'."
+ "C-M-u" #'nxml-backward-up-element
+ "C-M-d" #'nxml-down-element
+ "C-M-n" #'nxml-forward-element
+ "C-M-p" #'nxml-backward-element
+ "M-{" #'nxml-backward-paragraph
+ "M-}" #'nxml-forward-paragraph
+ "M-h" #'nxml-mark-paragraph
+ "C-c C-f" #'nxml-finish-element
+ "C-c ]" #'nxml-finish-element
+ "C-c /" #'nxml-finish-element
+ "C-c C-m" #'nxml-split-element
+ "C-c C-b" #'nxml-balanced-close-start-tag-block
+ "C-c C-i" #'nxml-balanced-close-start-tag-inline
+ "C-c C-x" #'nxml-insert-xml-declaration
+ "C-c C-d" #'nxml-dynamic-markup-word
+ ;; u is for Unicode
+ "C-c C-u" #'nxml-insert-named-char
+ "C-c C-o" nxml-outline-prefix-map
+ "/" #'nxml-electric-slash
+ "M-TAB" #'completion-at-point
+ "S-<mouse-2>" #'nxml-mouse-hide-direct-text-content)
(defvar nxml-font-lock-keywords
'(nxml-fontify-matcher)
@@ -566,7 +564,8 @@ Many aspects this mode can be customized using
(font-lock-syntactic-face-function
. sgml-font-lock-syntactic-face)))
- (with-demoted-errors (rng-nxml-mode-init)))
+ (with-demoted-errors "RNG NXML error: %S"
+ (rng-nxml-mode-init)))
(defun nxml--buffer-substring-filter (string)
;; The `rng-state' property is huge, so don't copy it to the kill ring.
diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el
index 928338a6af9..1518122a79d 100644
--- a/lisp/nxml/nxml-outln.el
+++ b/lisp/nxml/nxml-outln.el
@@ -129,20 +129,18 @@ See the variable `nxml-section-element-name-regexp' for more details."
(defvar nxml-heading-scan-distance 1000
"Maximum distance from section to scan for heading.")
-(defvar nxml-outline-prefix-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-a" 'nxml-show-all)
- (define-key map "\C-t" 'nxml-hide-all-text-content)
- (define-key map "\C-r" 'nxml-refresh-outline)
- (define-key map "\C-c" 'nxml-hide-direct-text-content)
- (define-key map "\C-e" 'nxml-show-direct-text-content)
- (define-key map "\C-d" 'nxml-hide-subheadings)
- (define-key map "\C-s" 'nxml-show)
- (define-key map "\C-k" 'nxml-show-subheadings)
- (define-key map "\C-l" 'nxml-hide-text-content)
- (define-key map "\C-i" 'nxml-show-direct-subheadings)
- (define-key map "\C-o" 'nxml-hide-other)
- map))
+(defvar-keymap nxml-outline-prefix-map
+ "C-a" #'nxml-show-all
+ "C-t" #'nxml-hide-all-text-content
+ "C-r" #'nxml-refresh-outline
+ "C-c" #'nxml-hide-direct-text-content
+ "C-e" #'nxml-show-direct-text-content
+ "C-d" #'nxml-hide-subheadings
+ "C-s" #'nxml-show
+ "C-k" #'nxml-show-subheadings
+ "C-l" #'nxml-hide-text-content
+ "C-i" #'nxml-show-direct-subheadings
+ "C-o" #'nxml-hide-other)
;;; Commands for changing visibility
@@ -693,11 +691,9 @@ non-transparent child section."
(nxml-highlighted-qname (xmltok-end-tag-qname))
nxml-highlighted-greater-than))))
-(defvar nxml-outline-show-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'nxml-show-direct-text-content)
- (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
- map))
+(defvar-keymap nxml-outline-show-map
+ "RET" #'nxml-show-direct-text-content
+ "<mouse-2>" #'nxml-mouse-show-direct-text-content)
(defvar nxml-outline-show-help "mouse-2: show")
@@ -724,12 +720,10 @@ non-transparent child section."
(put 'nxml-outline-display-heading 'evaporate t)
(put 'nxml-outline-display-heading 'face 'nxml-heading)
-(defvar nxml-outline-hiding-tag-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'nxml-mouse-show-direct-subheadings)
- (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
- (define-key map "\C-m" 'nxml-show-direct-text-content)
- map))
+(defvar-keymap nxml-outline-hiding-tag-map
+ "<mouse-1>" #'nxml-mouse-show-direct-subheadings
+ "<mouse-2>" #'nxml-mouse-show-direct-text-content
+ "RET" #'nxml-show-direct-text-content)
(defvar nxml-outline-hiding-tag-help
"mouse-1: show subheadings, mouse-2: show text content")
@@ -739,12 +733,10 @@ non-transparent child section."
(put 'nxml-outline-display-hiding-tag 'keymap nxml-outline-hiding-tag-map)
(put 'nxml-outline-display-hiding-tag 'help-echo nxml-outline-hiding-tag-help)
-(defvar nxml-outline-showing-tag-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'nxml-mouse-hide-subheadings)
- (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content)
- (define-key map "\C-m" 'nxml-show-direct-text-content)
- map))
+(defvar-keymap nxml-outline-showing-tag-map
+ "<mouse-1>" #'nxml-mouse-hide-subheadings
+ "<mouse-2>" #'nxml-mouse-show-direct-text-content
+ "RET" #'nxml-show-direct-text-content)
(defvar nxml-outline-showing-tag-help
"mouse-1: hide subheadings, mouse-2: show text content")
diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el
index ff9eda3fd2a..56ba4480bfa 100644
--- a/lisp/nxml/nxml-parse.el
+++ b/lisp/nxml/nxml-parse.el
@@ -246,7 +246,7 @@ same way as well-formedness error."
parsed-attributes)))
(setq atts (cdr atts)))
;; We want to end up with the attributes followed by the
- ;; the namespace attributes in the same order as
+ ;; namespace attributes in the same order as
;; xmltok-attributes and xmltok-namespace-attributes respectively.
(when parsed-namespace-attributes
(setq parsed-attributes
diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el
index 56ff3b66c0f..b9c980222e2 100644
--- a/lisp/nxml/rng-valid.el
+++ b/lisp/nxml/rng-valid.el
@@ -110,14 +110,14 @@
(defcustom rng-state-cache-distance 2000
"Distance in characters between each parsing and validation state cache."
- :type 'integer)
+ :type 'natnum)
(defcustom rng-validate-chunk-size 8000
"Number of characters in a RELAX NG validation chunk.
A validation chunk will be the smallest chunk that is at least this
size and ends with a tag. After validating a chunk, validation will
continue only if Emacs is still idle."
- :type 'integer)
+ :type 'natnum)
(defcustom rng-validate-delay 1.5
"Time in seconds that Emacs must be idle before starting a full validation.
diff --git a/lisp/obsolete/abbrevlist.el b/lisp/obsolete/abbrevlist.el
deleted file mode 100644
index ca508a15544..00000000000
--- a/lisp/obsolete/abbrevlist.el
+++ /dev/null
@@ -1,56 +0,0 @@
-;;; abbrevlist.el --- list one abbrev table alphabetically ordered -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1986, 1992, 2001-2022 Free Software Foundation, Inc.
-;; Suggested by a previous version by Gildea.
-
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: abbrev
-;; Package: emacs
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-;;;###autoload
-(defun list-one-abbrev-table (abbrev-table output-buffer)
- "Display alphabetical listing of ABBREV-TABLE in buffer OUTPUT-BUFFER."
- (with-output-to-temp-buffer output-buffer
- (save-excursion
- (let ((abbrev-list nil) (first-column 0))
- (set-buffer standard-output)
- (mapatoms
- (function (lambda (abbrev)
- (setq abbrev-list (cons abbrev abbrev-list))))
- abbrev-table)
- (setq abbrev-list (sort abbrev-list #'string-lessp))
- (while abbrev-list
- (if (> (+ first-column 40) (window-width))
- (progn
- (insert "\n")
- (setq first-column 0)))
- (indent-to first-column)
- (insert (symbol-name (car abbrev-list)))
- (indent-to (+ first-column 8))
- (insert (symbol-value (car abbrev-list)))
- (setq first-column (+ first-column 40))
- (setq abbrev-list (cdr abbrev-list)))))))
-
-(provide 'abbrevlist)
-
-;;; abbrevlist.el ends here
diff --git a/lisp/obsolete/assoc.el b/lisp/obsolete/assoc.el
deleted file mode 100644
index 76fcb4b78b8..00000000000
--- a/lisp/obsolete/assoc.el
+++ /dev/null
@@ -1,140 +0,0 @@
-;;; assoc.el --- insert/delete functions on association lists -*- lexical-binding: t -*-
-
-;; Copyright (C) 1996, 2001-2022 Free Software Foundation, Inc.
-
-;; Author: Barry A. Warsaw <bwarsaw@cen.com>
-;; Keywords: extensions
-;; Obsolete-since: 24.3
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Association list utilities providing insertion, deletion, sorting
-;; fetching off key-value pairs in association lists.
-
-;;; Code:
-
-(defun asort (alist-symbol key)
- "Move a specified key-value pair to the head of an alist.
-The alist is referenced by ALIST-SYMBOL. Key-value pair to move to
-head is one matching KEY. Returns the sorted list and doesn't affect
-the order of any other key-value pair. Side effect sets alist to new
-sorted list."
- (set alist-symbol
- (sort (copy-alist (symbol-value alist-symbol))
- (lambda (a _b) (equal (car a) key)))))
-
-
-(defun aelement (key value)
- "Make a list of a cons cell containing car of KEY and cdr of VALUE.
-The returned list is suitable for concatenating with an existing
-alist, via `nconc'."
- (list (cons key value)))
-
-
-(defun aheadsym (alist)
- "Return the key symbol at the head of ALIST."
- (car (car alist)))
-
-
-(defun anot-head-p (alist key)
- "Find out if a specified key-value pair is not at the head of an alist.
-The alist to check is specified by ALIST and the key-value pair is the
-one matching the supplied KEY. Returns nil if ALIST is nil, or if
-key-value pair is at the head of the alist. Returns t if key-value
-pair is not at the head of alist. ALIST is not altered."
- (not (equal (aheadsym alist) key)))
-
-
-(defun aput (alist-symbol key &optional value)
- "Insert a key-value pair into an alist.
-The alist is referenced by ALIST-SYMBOL. The key-value pair is made
-from KEY and optionally, VALUE. Returns the altered alist.
-
-If the key-value pair referenced by KEY can be found in the alist, and
-VALUE is supplied non-nil, then the value of KEY will be set to VALUE.
-If VALUE is not supplied, or is nil, the key-value pair will not be
-modified, but will be moved to the head of the alist. If the key-value
-pair cannot be found in the alist, it will be inserted into the head
-of the alist (with value nil if VALUE is nil or not supplied)."
- (let ((elem (aelement key value))
- alist)
- (asort alist-symbol key)
- (setq alist (symbol-value alist-symbol))
- (cond ((null alist) (set alist-symbol elem))
- ((anot-head-p alist key) (set alist-symbol (nconc elem alist)))
- (value (setcar alist (car elem)) alist)
- (t alist))))
-
-
-(defun adelete (alist-symbol key)
- "Delete a key-value pair from the alist.
-Alist is referenced by ALIST-SYMBOL and the key-value pair to remove
-is pair matching KEY. Returns the altered alist."
- (asort alist-symbol key)
- (let ((alist (symbol-value alist-symbol)))
- (cond ((null alist) nil)
- ((anot-head-p alist key) alist)
- (t (set alist-symbol (cdr alist))))))
-
-
-(defun aget (alist key &optional keynil-p)
- "Return the value in ALIST that is associated with KEY.
-Optional KEYNIL-P describes what to do if the value associated with
-KEY is nil. If KEYNIL-P is not supplied or is nil, and the value is
-nil, then KEY is returned. If KEYNIL-P is non-nil, then nil would be
-returned.
-
-If no key-value pair matching KEY could be found in ALIST, or ALIST is
-nil then nil is returned. ALIST is not altered."
- (defvar assoc--copy)
- (let ((assoc--copy (copy-alist alist)))
- (cond ((null alist) nil)
- ((progn (asort 'assoc--copy key) ; dynamic binding
- (anot-head-p assoc--copy key)) nil)
- ((cdr (car assoc--copy)))
- (keynil-p nil)
- ((car (car assoc--copy)))
- (t nil))))
-
-
-(defun amake (alist-symbol keylist &optional valuelist)
- "Make an association list.
-The association list is attached to the alist referenced by
-ALIST-SYMBOL. Each element in the KEYLIST becomes a key and is
-associated with the value in VALUELIST with the same index. If
-VALUELIST is not supplied or is nil, then each key in KEYLIST is
-associated with nil.
-
-KEYLIST and VALUELIST should have the same number of elements, but
-this isn't enforced. If VALUELIST is smaller than KEYLIST, remaining
-keys are associated with nil. If VALUELIST is larger than KEYLIST,
-extra values are ignored. Returns the created alist."
- (let ((keycar (car keylist))
- (keycdr (cdr keylist))
- (valcar (car valuelist))
- (valcdr (cdr valuelist)))
- (cond ((null keycdr)
- (aput alist-symbol keycar valcar))
- (t
- (amake alist-symbol keycdr valcdr)
- (aput alist-symbol keycar valcar))))
- (symbol-value alist-symbol))
-
-(provide 'assoc)
-
-;;; assoc.el ends here
diff --git a/lisp/autoarg.el b/lisp/obsolete/autoarg.el
index b0d6abe0207..8d5ded93421 100644
--- a/lisp/autoarg.el
+++ b/lisp/obsolete/autoarg.el
@@ -5,6 +5,7 @@
;; Author: Dave Love <fx@gnu.org>
;; Created: 1998-09-04
;; Keywords: abbrev, emulations
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
diff --git a/lisp/obsolete/complete.el b/lisp/obsolete/complete.el
deleted file mode 100644
index 1b4c39b159d..00000000000
--- a/lisp/obsolete/complete.el
+++ /dev/null
@@ -1,1122 +0,0 @@
-;;; complete.el --- partial completion mechanism plus other goodies -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1990-1993, 1999-2022 Free Software Foundation, Inc.
-
-;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Keywords: abbrev convenience
-;; Obsolete-since: 24.1
-;;
-;; Special thanks to Hallvard Furuseth for his many ideas and contributions.
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Extended completion for the Emacs minibuffer.
-;;
-;; The basic idea is that the command name or other completable text is
-;; divided into words and each word is completed separately, so that
-;; "M-x p-b" expands to "M-x print-buffer". If the entry is ambiguous
-;; each word is completed as much as possible and then the cursor is
-;; left at the first position where typing another letter will resolve
-;; the ambiguity.
-;;
-;; Word separators for this purpose are hyphen, space, and period.
-;; These would most likely occur in command names, Info menu items,
-;; and file names, respectively. But all word separators are treated
-;; alike at all times.
-;;
-;; This completion package replaces the old-style completer's key
-;; bindings for TAB, SPC, RET, and `?'. The old completer is still
-;; available on the Meta versions of those keys. If you set
-;; PC-meta-flag to nil, the old completion keys will be left alone
-;; and the partial completer will use the Meta versions of the keys.
-
-
-;; Usage: M-x partial-completion-mode. During completable minibuffer entry,
-;;
-;; TAB means to do a partial completion;
-;; SPC means to do a partial complete-word;
-;; RET means to do a partial complete-and-exit;
-;; ? means to do a partial completion-help.
-;;
-;; If you set PC-meta-flag to nil, then TAB, SPC, RET, and ? perform
-;; original Emacs completions, and M-TAB etc. do partial completion.
-;; To do this, put the command,
-;;
-;; (setq PC-meta-flag nil)
-;;
-;; in your .emacs file. To load partial completion automatically, put
-;;
-;; (partial-completion-mode t)
-;;
-;; in your .emacs file, too. Things will be faster if you byte-compile
-;; this file when you install it.
-;;
-;; As an extra feature, in cases where RET would not normally
-;; complete (such as `C-x b'), the M-RET key will always do a partial
-;; complete-and-exit. Thus `C-x b f.c RET' will select or create a
-;; buffer called "f.c", but `C-x b f.c M-RET' will select the existing
-;; buffer whose name matches that pattern (perhaps "filing.c").
-;; (PC-meta-flag does not affect this behavior; M-RET used to be
-;; undefined in this situation.)
-;;
-;; The regular M-TAB (lisp-complete-symbol) command also supports
-;; partial completion in this package.
-
-;; In addition, this package includes a feature for accessing include
-;; files. For example, `C-x C-f <sys/time.h> RET' reads the file
-;; /usr/include/sys/time.h. The variable PC-include-file-path is a
-;; list of directories in which to search for include files. Completion
-;; is supported in include file names.
-
-
-;;; Code:
-
-(defgroup partial-completion nil
- "Partial Completion of items."
- :prefix "pc-"
- :group 'minibuffer
- :group 'convenience)
-
-(defcustom PC-first-char 'find-file
- "Control how the first character of a string is to be interpreted.
-If nil, the first character of a string is not taken literally if it is a word
-delimiter, so that \".e\" matches \"*.e*\".
-If t, the first character of a string is always taken literally even if it is a
-word delimiter, so that \".e\" matches \".e*\".
-If non-nil and non-t, the first character is taken literally only for file name
-completion."
- :type '(choice (const :tag "delimiter" nil)
- (const :tag "literal" t)
- (other :tag "find-file" find-file)))
-
-(defcustom PC-meta-flag t
- "If non-nil, TAB means PC completion and M-TAB means normal completion.
-Otherwise, TAB means normal completion and M-TAB means Partial Completion."
- :type 'boolean)
-
-(defcustom PC-word-delimiters "-_. "
- "A string of characters treated as word delimiters for completion.
-Some arcane rules:
-If `]' is in this string, it must come first.
-If `^' is in this string, it must not come first.
-If `-' is in this string, it must come first or right after `]'.
-In other words, if S is this string, then `[S]' must be a valid Emacs regular
-expression (not containing character ranges like `a-z')."
- :type 'string)
-
-(defcustom PC-include-file-path '("/usr/include" "/usr/local/include")
- "A list of directories in which to look for include files.
-If nil, means use the colon-separated path in the variable $INCPATH instead."
- :type '(repeat directory))
-
-(defcustom PC-disable-includes nil
- "If non-nil, include-file support in \\[find-file] is disabled."
- :type 'boolean)
-
-(defvar PC-default-bindings t
- "If non-nil, default partial completion key bindings are suppressed.")
-
-(defvar PC-env-vars-alist nil
- "A list of the environment variable names and values.")
-
-
-(defun PC-bindings (bind)
- (let ((completion-map minibuffer-local-completion-map)
- (must-match-map minibuffer-local-must-match-map))
- (cond ((not bind)
- ;; These bindings are the default bindings. It would be better to
- ;; restore the previous bindings.
- (define-key read-expression-map "\e\t" #'completion-at-point)
-
- (define-key completion-map "\t" #'minibuffer-complete)
- (define-key completion-map " " #'minibuffer-complete-word)
- (define-key completion-map "?" #'minibuffer-completion-help)
-
- (define-key must-match-map "\r" #'minibuffer-complete-and-exit)
- (define-key must-match-map "\n" #'minibuffer-complete-and-exit)
-
- (define-key global-map [remap lisp-complete-symbol] nil))
- (PC-default-bindings
- (define-key read-expression-map "\e\t" #'PC-lisp-complete-symbol)
-
- (define-key completion-map "\t" #'PC-complete)
- (define-key completion-map " " #'PC-complete-word)
- (define-key completion-map "?" #'PC-completion-help)
-
- (define-key completion-map "\e\t" #'PC-complete)
- (define-key completion-map "\e " #'PC-complete-word)
- (define-key completion-map "\e\r" #'PC-force-complete-and-exit)
- (define-key completion-map "\e\n" #'PC-force-complete-and-exit)
- (define-key completion-map "\e?" #'PC-completion-help)
-
- (define-key must-match-map "\r" #'PC-complete-and-exit)
- (define-key must-match-map "\n" #'PC-complete-and-exit)
-
- (define-key must-match-map "\e\r" #'PC-complete-and-exit)
- (define-key must-match-map "\e\n" #'PC-complete-and-exit)
-
- (define-key global-map [remap lisp-complete-symbol] #'PC-lisp-complete-symbol)))))
-
-(defvar PC-do-completion-end nil
- "Internal variable used by `PC-do-completion'.")
-
-(make-variable-buffer-local 'PC-do-completion-end)
-
-(defvar PC-goto-end nil
- "Internal variable set in `PC-do-completion', used in
-`choose-completion-string-functions'.")
-
-(make-variable-buffer-local 'PC-goto-end)
-
-;;;###autoload
-(define-minor-mode partial-completion-mode
- "Toggle Partial Completion mode.
-
-When Partial Completion mode is enabled, TAB (or M-TAB if `PC-meta-flag' is
-nil) is enhanced so that if some string is divided into words and each word is
-delimited by a character in `PC-word-delimiters', partial words are completed
-as much as possible and `*' characters are treated likewise in file names.
-
-For example, M-x p-c-m expands to M-x partial-completion-mode since no other
-command begins with that sequence of characters, and
-\\[find-file] f_b.c TAB might complete to foo_bar.c if that file existed and no
-other file in that directory begins with that sequence of characters.
-
-Unless `PC-disable-includes' is non-nil, the `<...>' sequence is interpreted
-specially in \\[find-file]. For example,
-\\[find-file] <sys/time.h> RET finds the file `/usr/include/sys/time.h'.
-See also the variable `PC-include-file-path'.
-
-Partial Completion mode extends the meaning of `completion-auto-help' (which
-see), so that if it is neither nil nor t, Emacs shows the `*Completions*'
-buffer only on the second attempt to complete. That is, if TAB finds nothing
-to complete, the first TAB just says \"Next char not unique\" and the
-second TAB brings up the `*Completions*' buffer."
- :global t
- ;; Deal with key bindings...
- (PC-bindings partial-completion-mode)
- ;; Deal with include file feature...
- (cond ((not partial-completion-mode)
- (remove-hook 'find-file-not-found-functions
- #'PC-look-for-include-file))
- ((not PC-disable-includes)
- (add-hook 'find-file-not-found-functions #'PC-look-for-include-file)))
- ;; Adjust the completion selection in *Completion* buffers to the way
- ;; we work. The default minibuffer completion code only completes the
- ;; text before point and leaves the text after point alone (new in
- ;; Emacs-22). In contrast we use the whole text and we even sometimes
- ;; move point to a place before EOB, to indicate the first position where
- ;; there's a difference, so when the user uses choose-completion, we have
- ;; to trick choose-completion into replacing the whole minibuffer text
- ;; rather than only the text before point. --Stef
- (funcall
- (if partial-completion-mode #'add-hook #'remove-hook)
- 'choose-completion-string-functions
- (lambda (_choice buffer &rest _)
- ;; When completing M-: (lisp- ) with point before the ), it is
- ;; not appropriate to go to point-max (unlike the filename case).
- (if (and (not PC-goto-end)
- (minibufferp buffer))
- (goto-char (point-max))
- ;; Need a similar hack for the non-minibuffer-case -- gm.
- (when PC-do-completion-end
- (goto-char PC-do-completion-end)
- (setq PC-do-completion-end nil)))
- (setq PC-goto-end nil)
- nil))
- ;; Build the env-completion and mapping table.
- (when (and partial-completion-mode (null PC-env-vars-alist))
- (setq PC-env-vars-alist
- (mapcar (lambda (string)
- (let ((d (string-search "=" string)))
- (cons (concat "$" (substring string 0 d))
- (and d (substring string (1+ d))))))
- process-environment))))
-
-
-(defun PC-complete ()
- "Like minibuffer-complete, but allows \"b--di\"-style abbreviations.
-For example, \"M-x b--di\" would match `byte-recompile-directory', or any
-name which consists of three or more words, the first beginning with \"b\"
-and the third beginning with \"di\".
-
-The pattern \"b--d\" is ambiguous for `byte-recompile-directory' and
-`beginning-of-defun', so this would produce a list of completions
-just like when normal Emacs completions are ambiguous.
-
-Word-delimiters for the purposes of Partial Completion are \"-\", \"_\",
-\".\", and SPC."
- (interactive)
- (if (PC-was-meta-key)
- (minibuffer-complete)
- ;; If the previous command was not this one,
- ;; never scroll, always retry completion.
- (or (eq last-command this-command)
- (setq minibuffer-scroll-window nil))
- (let ((window minibuffer-scroll-window))
- ;; If there's a fresh completion window with a live buffer,
- ;; and this command is repeated, scroll that window.
- (if (and window (window-buffer window)
- (buffer-name (window-buffer window)))
- (with-current-buffer (window-buffer window)
- (if (pos-visible-in-window-p (point-max) window)
- (set-window-start window (point-min) nil)
- (scroll-other-window)))
- (PC-do-completion nil)))))
-
-
-(defun PC-complete-word ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This can be bound to other keys, like `-' and `.', if you wish."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (if (eq last-command-event ? )
- (minibuffer-complete-word)
- (self-insert-command 1))
- (self-insert-command 1)
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-space ()
- "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details.
-This is suitable for binding to other keys which should act just like SPC."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-word)
- (insert " ")
- (if (eobp)
- (PC-do-completion 'word))))
-
-
-(defun PC-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-complete-and-exit)
- (PC-do-complete-and-exit)))
-
-(defun PC-force-complete-and-exit ()
- "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (let ((minibuffer-completion-confirm nil))
- (PC-do-complete-and-exit)))
-
-(defun PC-do-complete-and-exit ()
- (cond
- ((= (point-max) (minibuffer-prompt-end))
- ;; Duplicate the "bug" that Info-menu relies on...
- (exit-minibuffer))
- ((eq minibuffer-completion-confirm 'confirm)
- (if (or (eq last-command this-command)
- (test-completion (field-string)
- minibuffer-completion-table
- minibuffer-completion-predicate))
- (exit-minibuffer)
- (PC-temp-minibuffer-message " [Confirm]")))
- ((eq minibuffer-completion-confirm 'confirm-after-completion)
- ;; Similar to the above, but only if trying to exit immediately
- ;; after typing TAB (this catches most minibuffer typos).
- (if (and (memq last-command minibuffer-confirm-exit-commands)
- (not (test-completion (field-string)
- minibuffer-completion-table
- minibuffer-completion-predicate)))
- (PC-temp-minibuffer-message " [Confirm]")
- (exit-minibuffer)))
- (t
- (let ((flag (PC-do-completion 'exit)))
- (and flag
- (if (or (eq flag 'complete)
- (not minibuffer-completion-confirm))
- (exit-minibuffer)
- (PC-temp-minibuffer-message " [Confirm]")))))))
-
-
-(defun PC-completion-help ()
- "Like `minibuffer-completion-help', but allows \"b--di\"-style abbreviations.
-See `PC-complete' for details."
- (interactive)
- (if (eq (PC-was-meta-key) PC-meta-flag)
- (minibuffer-completion-help)
- (PC-do-completion 'help)))
-
-(defun PC-was-meta-key ()
- (or (/= (length (this-command-keys)) 1)
- (let ((key (aref (this-command-keys) 0)))
- (if (integerp key)
- (>= key 128)
- (not (null (memq 'meta (event-modifiers key))))))))
-
-
-(defvar PC-ignored-extensions 'empty-cache)
-(defvar PC-delims 'empty-cache)
-(defvar PC-ignored-regexp nil)
-(defvar PC-word-failed-flag nil)
-(defvar PC-delim-regex nil)
-(defvar PC-ndelims-regex nil)
-(defvar PC-delims-list nil)
-
-(defvar PC-completion-as-file-name-predicate
- (lambda () minibuffer-completing-file-name)
- "A function testing whether a minibuffer completion now will work filename-style.
-The function takes no arguments, and typically looks at the value
-of `minibuffer-completion-table' and the minibuffer contents.")
-
-;; Returns the sequence of non-delimiter characters that follow regexp in string.
-(defun PC-chunk-after (string regexp)
- (if (not (string-match regexp string))
- (let ((message "String %s didn't match regexp %s"))
- (message message string regexp)
- (error message string regexp)))
- (let ((result (substring string (match-end 0))))
- ;; result may contain multiple chunks
- (if (string-match PC-delim-regex result)
- (setq result (substring result 0 (match-beginning 0))))
- result))
-
-(defun test-completion-ignore-case (str table pred)
- "Like `test-completion', but ignores case when possible."
- ;; Binding completion-ignore-case to nil ensures, for compatibility with
- ;; standard completion, that the return value is exactly one of the
- ;; possibilities. Do this binding only if pred is nil, out of paranoia;
- ;; perhaps it is safe even if pred is non-nil.
- (if pred
- (test-completion str table pred)
- (let ((completion-ignore-case nil))
- (test-completion str table pred))))
-
-;; The following function is an attempt to work around two problems:
-
-;; (1) When complete.el was written, (try-completion "" '(("") (""))) used to
-;; return the value "". With a change from 2002-07-07 it returns t which caused
-;; `PC-lisp-complete-symbol' to fail with a "Wrong type argument: sequencep, t"
-;; error. `PC-try-completion' returns STRING in this case.
-
-;; (2) (try-completion "" '((""))) returned t before the above-mentioned change.
-;; Since `PC-chop-word' operates on the return value of `try-completion' this
-;; case might have provoked a similar error as in (1). `PC-try-completion'
-;; returns "" instead. I don't know whether this is a real problem though.
-
-;; Since `PC-try-completion' is not a guaranteed to fix these bugs reliably, you
-;; should try to look at the following discussions when you encounter problems:
-;; - emacs-pretest-bug ("Partial Completion" starting 2007-02-23),
-;; - emacs-devel ("[address-of-OP: Partial completion]" starting 2007-02-24),
-;; - emacs-devel ("[address-of-OP: EVAL and mouse selection in *Completions*]"
-;; starting 2007-03-05).
-(defun PC-try-completion (string alist &optional predicate)
- "Like `try-completion' but return STRING instead of t."
- (let ((result (try-completion string alist predicate)))
- (if (eq result t) string result)))
-
-(defvar completion-base-size)
-
-;; TODO document MODE magic...
-(defun PC-do-completion (&optional mode beg end goto-end)
- "Internal function to do the work of partial completion.
-Text to be completed lies between BEG and END. Normally when
-replacing text in the minibuffer, this function replaces up to
-point-max (as is appropriate for completing a file name). If
-GOTO-END is non-nil, however, it instead replaces up to END."
- (or beg (setq beg (minibuffer-prompt-end)))
- (or end (setq end (point-max)))
- (let* ((table (if (eq minibuffer-completion-table 'read-file-name-internal)
- 'PC-read-file-name-internal
- minibuffer-completion-table))
- (pred minibuffer-completion-predicate)
- (filename (funcall PC-completion-as-file-name-predicate))
- (dirname nil) ; non-nil only if a filename is being completed
- ;; The following used to be "(dirlength 0)" which caused the erasure of
- ;; the entire buffer text before `point' when inserting a completion
- ;; into a buffer.
- dirlength
- (str (buffer-substring beg end))
- (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str)))
- (ambig nil)
- basestr origstr
- env-on
- regex
- p offset
- abbreviated
- (poss nil)
- helpposs
- (case-fold-search completion-ignore-case))
-
- ;; Check if buffer contents can already be considered complete
- (if (and (eq mode 'exit)
- (test-completion str table pred))
- 'complete
-
- ;; Do substitutions in directory names
- (and filename
- (setq basestr (or (file-name-directory str) ""))
- (setq dirlength (length basestr))
- ;; Do substitutions in directory names
- (setq p (substitute-in-file-name basestr))
- (not (string-equal basestr p))
- (setq str (concat p (file-name-nondirectory str)))
- (progn
- (delete-region beg end)
- (insert str)
- (setq end (+ beg (length str)))))
-
- ;; Prepare various delimiter strings
- (or (equal PC-word-delimiters PC-delims)
- (setq PC-delims PC-word-delimiters
- PC-delim-regex (concat "[" PC-delims "]")
- PC-ndelims-regex (concat "[^" PC-delims "]*")
- PC-delims-list (append PC-delims nil)))
-
- ;; Add wildcards if necessary
- (and filename
- (let ((dir (file-name-directory str))
- (file (file-name-nondirectory str))
- ;; The base dir for file-completion was passed in `predicate'.
- (default-directory (if (stringp pred) (expand-file-name pred)
- default-directory)))
- (while (and (stringp dir) (not (file-directory-p dir)))
- (setq dir (directory-file-name dir))
- (setq file (concat (replace-regexp-in-string
- PC-delim-regex "*\\&"
- (file-name-nondirectory dir))
- "*/" file))
- (setq dir (file-name-directory dir)))
- (setq origstr str str (concat dir file))))
-
- ;; Look for wildcard expansions in directory name
- (and filename
- (string-match "\\*.*/" str)
- (let ((pat str)
- ;; The base dir for file-completion was passed in `predicate'.
- (default-directory (if (stringp pred) (expand-file-name pred)
- default-directory))
- files)
- (setq p (1+ (string-match "/[^/]*\\'" pat)))
- (while (setq p (string-match PC-delim-regex pat p))
- (setq pat (concat (substring pat 0 p)
- "*"
- (substring pat p))
- p (+ p 2)))
- (setq files (file-expand-wildcards (concat pat "*")))
- (if files
- (let ((dir (file-name-directory (car files)))
- (p files))
- (while (and (setq p (cdr p))
- (equal dir (file-name-directory (car p)))))
- (if p
- (setq filename nil table nil
- pred (if (stringp pred) nil pred)
- ambig t)
- (delete-region beg end)
- (setq str (concat dir (file-name-nondirectory str)))
- (insert str)
- (setq end (+ beg (length str)))))
- (if origstr
- ;; If the wildcards were introduced by us, it's
- ;; possible that PC-read-file-name-internal can
- ;; still find matches for the original string
- ;; even if we couldn't, so remove the added
- ;; wildcards.
- (setq str origstr)
- (setq filename nil table nil
- pred (if (stringp pred) nil pred))))))
-
- ;; Strip directory name if appropriate
- (if filename
- (if incname
- (setq basestr (substring str incname)
- dirname (substring str 0 incname))
- (setq basestr (file-name-nondirectory str)
- dirname (file-name-directory str))
- ;; Make sure str is consistent with its directory and basename
- ;; parts. This is important on DOZe'NT systems when str only
- ;; includes a drive letter, like in "d:".
- (setq str (concat dirname basestr)))
- (setq basestr str))
-
- ;; Convert search pattern to a standard regular expression
- (setq regex (regexp-quote basestr)
- offset (if (and (> (length regex) 0)
- (not (eq (aref basestr 0) ?\*))
- (or (eq PC-first-char t)
- (and PC-first-char filename))) 1 0)
- p offset)
- (while (setq p (string-match PC-delim-regex regex p))
- (if (eq (aref regex p) ? )
- (setq regex (concat (substring regex 0 p)
- PC-ndelims-regex
- PC-delim-regex
- (substring regex (1+ p)))
- p (+ p (length PC-ndelims-regex) (length PC-delim-regex)))
- (let ((bump (if (memq (aref regex p)
- '(?$ ?^ ?\. ?* ?+ ?? ?\[ ?\] ?\\))
- -1 0)))
- (setq regex (concat (substring regex 0 (+ p bump))
- PC-ndelims-regex
- (substring regex (+ p bump)))
- p (+ p (length PC-ndelims-regex) 1)))))
- (setq p 0)
- (if filename
- (while (setq p (string-search "\\*" regex p))
- (setq regex (concat (substring regex 0 p)
- "[^/]*"
- (substring regex (+ p 2))))))
- ;;(setq the-regex regex)
- (setq regex (concat "\\`" regex))
-
- (and (> (length basestr) 0)
- (= (aref basestr 0) ?$)
- (setq env-on t
- table PC-env-vars-alist
- pred nil))
-
- ;; Find an initial list of possible completions
- (unless (setq p (string-match (concat PC-delim-regex
- (if filename "\\|\\*" ""))
- str
- (+ (length dirname) offset)))
-
- ;; Minibuffer contains no hyphens -- simple case!
- (setq poss (all-completions (if env-on basestr str)
- table
- pred))
- (unless (or poss (string-equal str ""))
- ;; Try completion as an abbreviation, e.g. "mvb" ->
- ;; "m-v-b" -> "multiple-value-bind", but only for
- ;; non-empty strings.
- (setq origstr str
- abbreviated t)
- (if filename
- (cond
- ;; "alpha" or "/alpha" -> expand whole path.
- ((string-match "^/?\\([A-Za-z0-9]+\\)$" str)
- (setq
- basestr ""
- p nil
- poss (file-expand-wildcards
- (concat "/"
- (mapconcat #'list (match-string 1 str) "*/")
- "*"))
- beg (1- beg)))
- ;; Alphanumeric trailer -> expand trailing file
- ((string-match "^\\(.+/\\)\\([A-Za-z0-9]+\\)$" str)
- (setq regex (concat "\\`"
- (mapconcat #'list
- (match-string 2 str)
- "[A-Za-z0-9]*[^A-Za-z0-9]"))
- p (1+ (length (match-string 1 str))))))
- (setq regex (concat "\\`" (mapconcat (lambda (c)
- (regexp-quote (string c)))
- str "[^-]*-"))
- p 1))))
- (when p
- ;; Use all-completions to do an initial cull. This is a big win,
- ;; since all-completions is written in C!
- (let ((compl (all-completions (if env-on
- (file-name-nondirectory (substring str 0 p))
- (substring str 0 p))
- table
- pred)))
- (setq p compl)
- (when (and compl abbreviated)
- (if filename
- (progn
- (setq p nil)
- (dolist (x compl)
- (when (string-match regex x)
- (push x p)))
- (setq basestr (try-completion "" p)))
- (setq basestr (mapconcat #'list str "-"))
- (delete-region beg end)
- (setq end (+ beg (length basestr)))
- (insert basestr))))
- (while p
- (and (string-match regex (car p))
- (progn
- (set-text-properties 0 (length (car p)) '() (car p))
- (setq poss (cons (car p) poss))))
- (setq p (cdr p))))
-
- ;; If table had duplicates, they can be here.
- (delete-dups poss)
-
- ;; Handle completion-ignored-extensions
- (and filename
- (not (eq mode 'help))
- (let ((p2 poss))
-
- ;; Build a regular expression representing the extensions list
- (or (equal completion-ignored-extensions PC-ignored-extensions)
- (setq PC-ignored-regexp
- (concat "\\("
- (mapconcat
- #'regexp-quote
- (setq PC-ignored-extensions
- completion-ignored-extensions)
- "\\|")
- "\\)\\'")))
-
- ;; Check if there are any without an ignored extension.
- ;; Also ignore `.' and `..'.
- (setq p nil)
- (while p2
- (or (string-match PC-ignored-regexp (car p2))
- (string-match "\\(\\`\\|/\\)[.][.]?/?\\'" (car p2))
- (setq p (cons (car p2) p)))
- (setq p2 (cdr p2)))
-
- ;; If there are "good" names, use them
- (and p (setq poss p))))
-
- ;; Now we have a list of possible completions
-
- (cond
-
- ;; No valid completions found
- ((null poss)
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
- (let ((PC-word-failed-flag t))
- (delete-char -1)
- (PC-do-completion 'word))
- (when abbreviated
- (delete-region beg end)
- (insert origstr))
- (beep)
- (PC-temp-minibuffer-message (if ambig
- " [Ambiguous dir name]"
- (if (eq mode 'help)
- " [No completions]"
- " [No match]")))
- nil))
-
- ;; More than one valid completion found
- ((or (cdr (setq helpposs poss))
- (memq mode '(help word)))
-
- ;; Is the actual string one of the possible completions?
- (setq p (and (not (eq mode 'help)) poss))
- (while (and p
- (not (string-equal (car p) basestr)))
- (setq p (cdr p)))
- (and p (null mode)
- (PC-temp-minibuffer-message " [Complete, but not unique]"))
- (if (and p
- (not (and (null mode)
- (eq this-command last-command))))
- t
-
- ;; If ambiguous, try for a partial completion
- (let ((improved nil)
- prefix
- (pt nil)
- (skip "\\`"))
-
- ;; Check if next few letters are the same in all cases
- (if (and (not (eq mode 'help))
- (setq prefix (PC-try-completion
- (PC-chunk-after basestr skip) poss)))
- (let ((first t) i)
- (if (eq mode 'word)
- (setq prefix (PC-chop-word prefix basestr)))
- (goto-char (+ beg (length dirname)))
- (while (and (progn
- (setq i 0) ; index into prefix string
- (while (< i (length prefix))
- (if (and (< (point) end)
- (or (eq (downcase (aref prefix i))
- (downcase (following-char)))
- (and (looking-at " ")
- (memq (aref prefix i)
- PC-delims-list))))
- ;; replace " " by the actual delimiter
- ;; or input char by prefix char
- (progn
- (delete-char 1)
- (insert (substring prefix i (1+ i))))
- ;; insert a new character
- (progn
- (and filename (looking-at "\\*")
- (progn
- (delete-char 1)
- (setq end (1- end))))
- (setq improved t)
- (insert (substring prefix i (1+ i)))
- (setq end (1+ end))))
- (setq i (1+ i)))
- (or pt (setq pt (point)))
- (looking-at PC-delim-regex))
- (setq skip (concat skip
- (regexp-quote prefix)
- PC-ndelims-regex)
- prefix (PC-try-completion
- (PC-chunk-after
- ;; not basestr, because that does
- ;; not reflect insertions
- (buffer-substring
- (+ beg (length dirname)) end)
- skip)
- (mapcar
- (lambda (x)
- (when (string-match skip x)
- (substring x (match-end 0))))
- poss)))
- (or (> i 0) (> (length prefix) 0))
- (or (not (eq mode 'word))
- (and first (> (length prefix) 0)
- (setq first nil
- prefix (substring prefix 0 1))))))
- (goto-char (if (eq mode 'word) end
- (or pt beg)))))
-
- (if (and (eq mode 'word)
- (not PC-word-failed-flag))
-
- (if improved
-
- ;; We changed it... would it be complete without the space?
- (if (test-completion (buffer-substring
- (field-beginning) (1- end))
- table pred)
- (delete-region (1- end) end)))
-
- (if improved
-
- ;; We changed it... enough to be complete?
- (and (eq mode 'exit)
- (test-completion-ignore-case (field-string) table pred))
-
- ;; If totally ambiguous, display a list of completions
- (if (or (eq completion-auto-help t)
- (and completion-auto-help
- (eq last-command this-command))
- (eq mode 'help))
- (let ((prompt-end (minibuffer-prompt-end)))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (sort helpposs #'string-lessp))
- (setq PC-do-completion-end end
- PC-goto-end goto-end)
- (with-current-buffer standard-output
- ;; Record which part of the buffer we are completing
- ;; so that choosing a completion from the list
- ;; knows how much old text to replace.
- ;; This was briefly nil in the non-dirname case.
- ;; However, if one calls PC-lisp-complete-symbol
- ;; on "(ne-f" with point on the hyphen, PC offers
- ;; all completions starting with "(ne", some of
- ;; which do not match the "-f" part (maybe it
- ;; should not, but it does). In such cases,
- ;; completion gets confused trying to figure out
- ;; how much to replace, so we tell it explicitly
- ;; (ie, the number of chars in the buffer before beg).
- ;;
- ;; Note that choose-completion-string-functions
- ;; plays around with point.
- (with-suppressed-warnings ((obsolete
- completion-base-size))
- (setq completion-base-size
- (if dirname
- dirlength
- (- beg prompt-end)))))))
- (PC-temp-minibuffer-message " [Next char not unique]"))
- ;; Expansion of filenames is not reversible,
- ;; so just keep the prefix.
- (when (and abbreviated filename)
- (delete-region (point) end))
- nil)))))
-
- ;; Only one possible completion
- (t
- (if (and (equal basestr (car poss))
- (not (and env-on filename))
- (not abbreviated))
- (if (null mode)
- (PC-temp-minibuffer-message " [Sole completion]"))
- (delete-region beg end)
- (insert (format "%s"
- (if filename
- (substitute-in-file-name (concat dirname (car poss)))
- (car poss)))))
- t)))))
-
-(defun PC-chop-word (new old)
- (let ((i -1)
- (j -1))
- (while (and (setq i (string-match PC-delim-regex old (1+ i)))
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (if (and j
- (or (not PC-word-failed-flag)
- (setq j (string-match PC-delim-regex new (1+ j)))))
- (substring new 0 (1+ j))
- new)))
-
-(defvar PC-not-minibuffer nil)
-
-(defun PC-temp-minibuffer-message (message)
- "A Lisp version of `temp_minibuffer_message' from minibuf.c."
- (cond (PC-not-minibuffer
- (message "%s" message)
- (sit-for 2)
- (message ""))
- ((fboundp 'temp-minibuffer-message)
- (temp-minibuffer-message message))
- (t
- (let ((point-max (point-max)))
- (save-excursion
- (goto-char point-max)
- (insert message))
- (let ((inhibit-quit t))
- (sit-for 2)
- (delete-region point-max (point-max))
- (when quit-flag
- (setq quit-flag nil
- unread-command-events '(7))))))))
-
-;; Does not need to be buffer-local (?) because only used when one
-;; PC-l-c-s immediately follows another.
-(defvar PC-lisp-complete-end nil
- "Internal variable used by `PC-lisp-complete-symbol'.")
-
-(defun PC-lisp-complete-symbol ()
- "Perform completion on Lisp symbol preceding point.
-That symbol is compared against the symbols that exist
-and any additional characters determined by what is there
-are inserted.
-If the symbol starts just after an open-parenthesis,
-only symbols with function definitions are considered.
-Otherwise, all symbols with function definitions, values
-or properties are considered."
- (interactive)
- (let* ((end
- (save-excursion
- (with-syntax-table lisp-mode-syntax-table
- (skip-syntax-forward "_w")
- (point))))
- (beg (save-excursion
- (with-syntax-table lisp-mode-syntax-table
- (backward-sexp 1)
- (while (= (char-syntax (following-char)) ?\')
- (forward-char 1))
- (point))))
- (minibuffer-completion-table obarray)
- (minibuffer-completion-predicate
- (if (eq (char-after (1- beg)) ?\()
- 'fboundp
- (function (lambda (sym)
- (or (boundp sym) (fboundp sym)
- (symbol-plist sym))))))
- (PC-not-minibuffer t))
- ;; https://lists.gnu.org/r/emacs-devel/2007-03/msg01211.html
- ;;
- ;; This deals with cases like running PC-l-c-s on "M-: (n-f".
- ;; The first call to PC-l-c-s expands this to "(ne-f", and moves
- ;; point to the hyphen [1]. If one calls PC-l-c-s immediately after,
- ;; then without the last-command check, one is offered all
- ;; completions of "(ne", which is presumably not what one wants.
- ;;
- ;; This is arguably (at least, it seems to be the existing intended
- ;; behavior) what one _does_ want if point has been explicitly
- ;; positioned on the hyphen. Note that if PC-do-completion (qv) binds
- ;; completion-base-size to nil, then completion does not replace the
- ;; correct amount of text in such cases.
- ;;
- ;; Neither of these problems occur when using PC for filenames in the
- ;; minibuffer, because in that case PC-do-completion is called without
- ;; an explicit value for END, and so uses (point-max). This is fine for
- ;; a filename, because the end of the filename must be at the end of
- ;; the minibuffer. The same is not true for lisp symbols.
- ;;
- ;; [1] An alternate fix would be to not move point to the hyphen
- ;; in such cases, but that would make the behavior different from
- ;; that for filenames. It seems PC moves point to the site of the
- ;; first difference between the possible completions.
- ;;
- ;; Alternatively alternatively, maybe end should be computed in
- ;; the same way as beg. That would change the behavior though.
- (if (equal last-command 'PC-lisp-complete-symbol)
- (PC-do-completion nil beg PC-lisp-complete-end t)
- (if PC-lisp-complete-end
- (move-marker PC-lisp-complete-end end)
- (setq PC-lisp-complete-end (copy-marker end t)))
- (PC-do-completion nil beg end t))))
-
-(defun PC-complete-as-file-name ()
- "Perform completion on file names preceding point.
- Environment vars are converted to their values."
- (interactive)
- (let* ((end (point))
- (beg (if (re-search-backward "[^\\][ \t\n\"`'][^ \t\n\"`']"
- (point-min) t)
- (+ (point) 2)
- (point-min)))
- (minibuffer-completion-table 'PC-read-file-name-internal)
- (minibuffer-completion-predicate nil)
- (PC-not-minibuffer t))
- (goto-char end)
- (PC-do-completion nil beg end)))
-
-;; Facilities for loading C header files. This is independent from the
-;; main completion code. See also the variable `PC-include-file-path'
-;; at top of this file.
-
-(defun PC-look-for-include-file ()
- (if (string-match "[\"<]\\([^\"<>]*\\)[\">]?$" (buffer-file-name))
- (let ((name (substring (buffer-file-name)
- (match-beginning 1) (match-end 1)))
- (punc (aref (buffer-file-name) (match-beginning 0)))
- (path nil)
- new-buf)
- (kill-buffer (current-buffer))
- (if (equal name "")
- (with-current-buffer (car (buffer-list))
- (save-excursion
- (beginning-of-line)
- (if (looking-at
- "[ \t]*#[ \t]*include[ \t]+[<\"]\\(.+\\)[>\"][ \t]*[\n/]")
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc (char-after (1- (match-beginning 1))))
- ;; Suggested by Frank Siebenlist:
- (if (or (looking-at
- "[ \t]*([ \t]*load[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*load-library[ \t]+\"\\([^\"]+\\)\"")
- (looking-at
- "[ \t]*([ \t]*require[ \t]+'\\([^\t )]+\\)[\t )]"))
- (progn
- (setq name (buffer-substring (match-beginning 1)
- (match-end 1))
- punc ?\<
- path load-path)
- (if (string-match "\\.elc$" name)
- (setq name (substring name 0 -1))
- (or (string-match "\\.el$" name)
- (setq name (concat name ".el")))))
- (error "Not on an #include line"))))))
- (or (string-match "\\.[[:alnum:]]+$" name)
- (setq name (concat name ".h")))
- (if (eq punc ?\<)
- (let ((path (or path (PC-include-file-path))))
- (while (and path
- (not (file-exists-p
- (concat (file-name-as-directory (car path))
- name))))
- (setq path (cdr path)))
- (if path
- (setq name (concat (file-name-as-directory (car path)) name))
- (error "No such include file: <%s>" name)))
- (let ((dir (with-current-buffer (car (buffer-list))
- default-directory)))
- (if (file-exists-p (concat dir name))
- (setq name (concat dir name))
- (error "No such include file: `%s'" name))))
- (setq new-buf (get-file-buffer name))
- (if new-buf
- ;; no need to verify last-modified time for this!
- (set-buffer new-buf)
- (set-buffer (create-file-buffer name))
- (erase-buffer)
- (insert-file-contents name t))
- ;; Returning non-nil with the new buffer current
- ;; is sufficient to tell find-file to use it.
- t)
- nil))
-
-(defun PC-include-file-path ()
- (or PC-include-file-path
- (let ((env (getenv "INCPATH"))
- (path nil)
- pos)
- (or env (error "No include file path specified"))
- (while (setq pos (string-match ":[^:]+$" env))
- (setq path (cons (substring env (1+ pos)) path)
- env (substring env 0 pos)))
- path)))
-
-;; This is adapted from lib-complete.el, by Mike Williams.
-(defun PC-include-file-all-completions (file search-path &optional full)
- "Return all completions for FILE in any directory on SEARCH-PATH.
-If optional third argument FULL is non-nil, returned pathnames should be
-absolute rather than relative to some directory on the SEARCH-PATH."
- (setq search-path
- (mapcar (lambda (dir)
- (if dir (file-name-as-directory dir) default-directory))
- search-path))
- (if (file-name-absolute-p file)
- ;; It's an absolute file name, so don't need search-path
- (progn
- (setq file (expand-file-name file))
- (file-name-all-completions
- (file-name-nondirectory file) (file-name-directory file)))
- (let ((subdir (file-name-directory file))
- (ndfile (file-name-nondirectory file))
- file-lists)
- ;; Append subdirectory part to each element of search-path
- (if subdir
- (setq search-path
- (mapcar (lambda (dir) (concat dir subdir))
- search-path)
- file nil))
- ;; Make list of completions in each directory on search-path
- (while search-path
- (let* ((dir (car search-path))
- (subdir (if full dir subdir)))
- (if (file-directory-p dir)
- (progn
- (setq file-lists
- (cons
- (mapcar (lambda (file) (concat subdir file))
- (file-name-all-completions ndfile
- (car search-path)))
- file-lists))))
- (setq search-path (cdr search-path))))
- ;; Compress out duplicates while building complete list (slloooow!)
- (let ((sorted (sort (apply #'nconc file-lists)
- (lambda (x y) (not (string-lessp x y)))))
- compressed)
- (while sorted
- (if (equal (car sorted) (car compressed)) nil
- (setq compressed (cons (car sorted) compressed)))
- (setq sorted (cdr sorted)))
- compressed))))
-
-(defun PC-read-file-name-internal (string pred action)
- "Extend `read-file-name-internal' to handle include files.
-This is only used by "
- (if (string-match "<\\([^\"<>]*\\)>?\\'" string)
- (let* ((name (match-string 1 string))
- (str2 (substring string (match-beginning 0)))
- (completion-table
- (mapcar (lambda (x)
- (format (if (string-match "/\\'" x) "<%s" "<%s>") x))
- (PC-include-file-all-completions
- name (PC-include-file-path)))))
- (cond
- ((not completion-table) nil)
- ((eq action 'lambda) (test-completion str2 completion-table nil))
- ((eq action nil) (PC-try-completion str2 completion-table nil))
- ((eq action t) (all-completions str2 completion-table nil))))
- (read-file-name-internal string pred action)))
-
-
-(provide 'complete)
-
-;;; complete.el ends here
diff --git a/lisp/obsolete/cust-print.el b/lisp/obsolete/cust-print.el
deleted file mode 100644
index 80ded086545..00000000000
--- a/lisp/obsolete/cust-print.el
+++ /dev/null
@@ -1,674 +0,0 @@
-;;; cust-print.el --- handles print-level and print-circle -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1992, 2001-2022 Free Software Foundation, Inc.
-
-;; Author: Daniel LaLiberte <liberte@holonexus.org>
-;; Adapted-By: ESR
-;; Keywords: extensions
-;; Obsolete-since: 24.3
-
-;; LCD Archive Entry:
-;; cust-print|Daniel LaLiberte|liberte@holonexus.org
-;; |Handle print-level, print-circle and more.
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This package provides a general print handler for prin1 and princ
-;; that supports print-level and print-circle, and by the way,
-;; print-length since the standard routines are being replaced. Also,
-;; to print custom types constructed from lists and vectors, use
-;; custom-print-list and custom-print-vector. See the documentation
-;; strings of these variables for more details.
-
-;; If the results of your expressions contain circular references to
-;; other parts of the same structure, the standard Emacs print
-;; subroutines may fail to print with an untrappable error,
-;; "Apparently circular structure being printed". If you only use cdr
-;; circular lists (where cdrs of lists point back; what is the right
-;; term here?), you can limit the length of printing with
-;; print-length. But car circular lists and circular vectors generate
-;; the above mentioned error in Emacs version 18. Version
-;; 19 supports print-level, but it is often useful to get a better
-;; print representation of circular and shared structures; the print-circle
-;; option may be used to print more concise representations.
-
-;; There are three main ways to use this package. First, you may
-;; replace prin1, princ, and some subroutines that use them by calling
-;; install-custom-print so that any use of these functions in
-;; Lisp code will be affected; you can later reset with
-;; uninstall-custom-print. Second, you may temporarily install
-;; these functions with the macro with-custom-print. Third, you
-;; could call the custom routines directly, thus only affecting the
-;; printing that requires them.
-
-;; Note that subroutines which call print subroutines directly will
-;; not use the custom print functions. In particular, the evaluation
-;; functions like eval-region call the print subroutines directly.
-;; Therefore, if you evaluate (aref circ-list 0), where circ-list is a
-;; circular list rather than an array, aref calls error directly which
-;; will jump to the top level instead of printing the circular list.
-
-;; Uninterned symbols are recognized when print-circle is non-nil,
-;; but they are not printed specially here. Use the cl-packages package
-;; to print according to print-gensym.
-
-;; Obviously the right way to implement this custom-print facility is
-;; in C or with hooks into the standard printer. Please volunteer
-;; since I don't have the time or need. More CL-like printing
-;; capabilities could be added in the future.
-
-;; Implementation design: we want to use the same list and vector
-;; processing algorithm for all versions of prin1 and princ, since how
-;; the processing is done depends on print-length, print-level, and
-;; print-circle. For circle printing, a preprocessing step is
-;; required before the final printing. Thanks to Jamie Zawinski
-;; for motivation and algorithms.
-
-
-;;; Code:
-
-(defgroup cust-print nil
- "Handles print-level and print-circle."
- :prefix "print-"
- :group 'lisp
- :group 'extensions)
-
-;; If using cl-packages:
-
-'(defpackage "cust-print"
- (:nicknames "CP" "custom-print")
- (:use "el")
- (:export
- print-level
- print-circle
-
- custom-print-install
- custom-print-uninstall
- custom-print-installed-p
- with-custom-print
-
- custom-prin1
- custom-princ
- custom-prin1-to-string
- custom-print
- custom-format
- custom-message
- custom-error
-
- custom-printers
- add-custom-printer
- ))
-
-'(in-package cust-print)
-
-;; Emacs 18 doesn't have defalias.
-;; Provide def for byte compiler.
-
-;; Variables:
-;;=========================================================
-
-;;(defvar print-length nil
-;; "*Controls how many elements of a list, at each level, are printed.
-;;This is defined by emacs.")
-
-(defcustom print-level nil
- "Controls how many levels deep a nested data object will print.
-
-If nil, printing proceeds recursively and may lead to
-max-lisp-eval-depth being exceeded or an error may occur:
-`Apparently circular structure being printed.'
-Also see `print-length' and `print-circle'.
-
-If non-nil, components at levels equal to or greater than `print-level'
-are printed simply as `#'. The object to be printed is at level 0,
-and if the object is a list or vector, its top-level components are at
-level 1."
- :type '(choice (const nil) integer))
-
-
-(defcustom print-circle nil
- "Controls the printing of recursive structures.
-
-If nil, printing proceeds recursively and may lead to
-`max-lisp-eval-depth' being exceeded or an error may occur:
-\"Apparently circular structure being printed.\" Also see
-`print-length' and `print-level'.
-
-If non-nil, shared substructures anywhere in the structure are printed
-with `#N=' before the first occurrence (in the order of the print
-representation) and `#N#' in place of each subsequent occurrence,
-where N is a positive decimal integer."
- :type 'boolean)
-
-
-(defcustom custom-print-vectors nil
- "Non-nil if printing of vectors should obey `print-level' and `print-length'."
- :type 'boolean)
-
-
-;; Custom printers
-;;==========================================================
-
-(defvar custom-printers nil
- ;; e.g. '((symbolp . pkg::print-symbol))
- "An alist for custom printing of any type.
-Pairs are of the form (PREDICATE . PRINTER). If PREDICATE is true
-for an object, then PRINTER is called with the object.
-PRINTER should print to `standard-output' using cust-print-original-princ
-if the standard printer is sufficient, or cust-print-prin for complex things.
-The PRINTER should return the object being printed.
-
-Don't modify this variable directly. Use `add-custom-printer' and
-`delete-custom-printer'")
-;; Should cust-print-original-princ and cust-print-prin be exported symbols?
-;; Or should the standard printers functions be replaced by
-;; CP ones in Emacs Lisp so that CP internal functions need not be called?
-
-(defun add-custom-printer (pred printer)
- "Add a pair of PREDICATE and PRINTER to `custom-printers'.
-Any pair that has the same PREDICATE is first removed."
- (setq custom-printers (cons (cons pred printer)
- (delq (assq pred custom-printers)
- custom-printers)))
- ;; Rather than updating here, we could wait until cust-print-top-level is called.
- (cust-print-update-custom-printers))
-
-(defun delete-custom-printer (pred)
- "Delete the custom printer associated with PREDICATE."
- (setq custom-printers (delq (assq pred custom-printers)
- custom-printers))
- (cust-print-update-custom-printers))
-
-
-(defun cust-print-use-custom-printer (_object)
- ;; Default function returns nil.
- nil)
-
-(defun cust-print-update-custom-printers ()
- ;; Modify the definition of cust-print-use-custom-printer
- (defalias 'cust-print-use-custom-printer
- ;; We don't really want to require the byte-compiler.
- ;; (byte-compile
- `(lambda (object)
- (cond
- ,@(mapcar (function
- (lambda (pair)
- `((,(car pair) object)
- (,(cdr pair) object))))
- custom-printers)
- ;; Otherwise return nil.
- (t nil)
- ))
- ;; )
- ))
-
-
-;; Saving and restoring emacs printing routines.
-;;====================================================
-
-(defun cust-print-set-function-cell (symbol-pair)
- (defalias (car symbol-pair)
- (symbol-function (car (cdr symbol-pair)))))
-
-(defun cust-print-original-princ (_object &optional _stream) nil) ; dummy def
-
-;; Save emacs routines.
-(if (not (fboundp 'cust-print-original-prin1))
- (mapc #'cust-print-set-function-cell
- '((cust-print-original-prin1 prin1)
- (cust-print-original-princ princ)
- (cust-print-original-print print)
- (cust-print-original-prin1-to-string prin1-to-string)
- (cust-print-original-format format)
- (cust-print-original-message message)
- (cust-print-original-error error))))
-(declare-function cust-print-original-format "cust-print")
-(declare-function cust-print-original-message "cust-print")
-
-(defun custom-print-install ()
- "Replace print functions with general, customizable, Lisp versions.
-The Emacs subroutines are saved away, and you can reinstall them
-by running `custom-print-uninstall'."
- (interactive)
- (mapc #'cust-print-set-function-cell
- '((prin1 custom-prin1)
- (princ custom-princ)
- (print custom-print)
- (prin1-to-string custom-prin1-to-string)
- (format custom-format)
- (message custom-message)
- (error custom-error)
- ))
- t)
-
-(defun custom-print-uninstall ()
- "Reset print functions to their Emacs subroutines."
- (interactive)
- (mapc #'cust-print-set-function-cell
- '((prin1 cust-print-original-prin1)
- (princ cust-print-original-princ)
- (print cust-print-original-print)
- (prin1-to-string cust-print-original-prin1-to-string)
- (format cust-print-original-format)
- (message cust-print-original-message)
- (error cust-print-original-error)
- ))
- t)
-
-(defalias 'custom-print-funcs-installed-p #'custom-print-installed-p)
-(defun custom-print-installed-p ()
- "Return t if custom-print is currently installed, nil otherwise."
- (eq (symbol-function 'custom-prin1) (symbol-function 'prin1)))
-
-(defmacro with-custom-print (&rest body)
- "Temporarily install the custom print package while executing BODY."
- (declare (debug t))
- `(unwind-protect
- (progn
- (custom-print-install)
- ,@body)
- (custom-print-uninstall)))
-(defalias 'with-custom-print-funcs #'with-custom-print)
-
-
-;; Lisp replacements for prin1 and princ, and for some subrs that use them
-;;===============================================================
-;; - so far only the printing and formatting subrs.
-
-(defun custom-prin1 (object &optional stream)
- "Output the printed representation of OBJECT, any Lisp object.
-Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `prin1'. It
-uses the appropriate printer depending on the values of `print-level'
-and `print-circle' (which see)."
- (cust-print-top-level object stream 'cust-print-original-prin1))
-
-
-(defun custom-princ (object &optional stream)
- "Output the printed representation of OBJECT, any Lisp object.
-No quoting characters are used; no delimiters are printed around
-the contents of strings.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `princ'."
- (cust-print-top-level object stream 'cust-print-original-princ))
-
-
-(defun custom-prin1-to-string (object &optional noescape)
- "Return a string containing the printed representation of OBJECT,
-any Lisp object. Quoting characters are used when needed to make output
-that `read' can handle, whenever this is possible, unless the optional
-second argument NOESCAPE is non-nil.
-
-This is the custom-print replacement for the standard `prin1-to-string'."
- (let ((buf (get-buffer-create " *custom-print-temp*")))
- ;; We must erase the buffer before printing in case an error
- ;; occurred during the last prin1-to-string and we are in debugger.
- (with-current-buffer buf
- (erase-buffer))
- ;; We must be in the current-buffer when the print occurs.
- (if noescape
- (custom-princ object buf)
- (custom-prin1 object buf))
- (with-current-buffer buf
- (buffer-string)
- ;; We could erase the buffer again, but why bother?
- )))
-
-
-(defun custom-print (object &optional stream)
- "Output the printed representation of OBJECT, with newlines around it.
-Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
-Output stream is STREAM, or value of `standard-output' (which see).
-
-This is the custom-print replacement for the standard `print'."
- (cust-print-original-princ "\n" stream)
- (custom-prin1 object stream)
- (cust-print-original-princ "\n" stream))
-
-
-(defun custom-format (fmt &rest args)
- "Format a string out of a control-string and arguments.
-The first argument is a control string. It, and subsequent arguments
-substituted into it, become the value, which is a string.
-It may contain %s or %d or %c to substitute successive following arguments.
-%s means print an argument as a string, %d means print as number in decimal,
-%c means print a number as a single character.
-The argument used by %s must be a string or a symbol;
-the argument used by %d, %b, %o, %x or %c must be a number.
-
-This is the custom-print replacement for the standard `format'. It
-calls the Emacs `format' after first making strings for list,
-vector, or symbol args. The format specification for such args should
-be `%s' in any case, so a string argument will also work. The string
-is generated with `custom-prin1-to-string', which quotes quotable
-characters."
- (apply #'cust-print-original-format fmt
- (mapcar (function (lambda (arg)
- (if (or (listp arg) (vectorp arg) (symbolp arg))
- (custom-prin1-to-string arg)
- arg)))
- args)))
-
-
-(defun custom-message (fmt &rest args)
- "Print a one-line message at the bottom of the screen.
-The first argument is a control string.
-It may contain %s or %d or %c to print successive following arguments.
-%s means print an argument as a string, %d means print as number in decimal,
-%c means print a number as a single character.
-The argument used by %s must be a string or a symbol;
-the argument used by %d or %c must be a number.
-
-This is the custom-print replacement for the standard `message'.
-See `custom-format' for the details."
- ;; It doesn't work to princ the result of custom-format as in:
- ;; (cust-print-original-princ (apply 'custom-format fmt args))
- ;; because the echo area requires special handling
- ;; to avoid duplicating the output.
- ;; cust-print-original-message does it right.
- (apply #'cust-print-original-message fmt
- (mapcar (function (lambda (arg)
- (if (or (listp arg) (vectorp arg) (symbolp arg))
- (custom-prin1-to-string arg)
- arg)))
- args)))
-
-
-(defun custom-error (fmt &rest args)
- "Signal an error, making error message by passing all args to `format'.
-
-This is the custom-print replacement for the standard `error'.
-See `custom-format' for the details."
- (signal 'error (list (apply #'custom-format fmt args))))
-
-
-
-;; Support for custom prin1 and princ
-;;=========================================
-
-;; Defs to quiet byte-compiler.
-(defvar circle-table)
-(defvar cust-print-current-level)
-
-(defun cust-print-original-printer (_object) nil) ; One of the standard printers.
-(defun cust-print-low-level-prin (_object) nil) ; Used internally.
-(defun cust-print-prin (_object) nil) ; Call this to print recursively.
-
-(defun cust-print-top-level (object stream emacs-printer)
- ;; Set up for printing.
- (let ((standard-output (or stream standard-output))
- ;; circle-table will be non-nil if anything is circular.
- (circle-table (and print-circle
- (cust-print-preprocess-circle-tree object)))
- (cust-print-current-level (or print-level -1)))
-
- (defalias 'cust-print-original-printer emacs-printer)
- (defalias 'cust-print-low-level-prin
- (cond
- ((or custom-printers
- circle-table
- print-level ; comment out for version 19
- ;; Emacs doesn't use print-level or print-length
- ;; for vectors, but custom-print can.
- (if custom-print-vectors
- (or print-level print-length)))
- 'cust-print-print-object)
- (t 'cust-print-original-printer)))
- (defalias 'cust-print-prin
- (if circle-table 'cust-print-print-circular 'cust-print-low-level-prin))
-
- (cust-print-prin object)
- object))
-
-
-(defun cust-print-print-object (object)
- ;; Test object type and print accordingly.
- ;; Could be called as either cust-print-low-level-prin or cust-print-prin.
- (cond
- ((null object) (cust-print-original-printer object))
- ((cust-print-use-custom-printer object) object)
- ((consp object) (cust-print-list object))
- ((vectorp object) (cust-print-vector object))
- ;; All other types, just print.
- (t (cust-print-original-printer object))))
-
-
-(defun cust-print-print-circular (object)
- ;; Printer for `prin1' and `princ' that handles circular structures.
- ;; If OBJECT appears multiply, and has not yet been printed,
- ;; prefix with label; if it has been printed, use `#N#' instead.
- ;; Otherwise, print normally.
- (let ((tag (assq object circle-table)))
- (if tag
- (let ((id (cdr tag)))
- (if (> id 0)
- (progn
- ;; Already printed, so just print id.
- (cust-print-original-princ "#")
- (cust-print-original-princ id)
- (cust-print-original-princ "#"))
- ;; Not printed yet, so label with id and print object.
- (setcdr tag (- id)) ; mark it as printed
- (cust-print-original-princ "#")
- (cust-print-original-princ (- id))
- (cust-print-original-princ "=")
- (cust-print-low-level-prin object)
- ))
- ;; Not repeated in structure.
- (cust-print-low-level-prin object))))
-
-
-;;================================================
-;; List and vector processing for print functions.
-
-(defun cust-print-list (list)
- ;; Print a list using print-length, print-level, and print-circle.
- (if (= cust-print-current-level 0)
- (cust-print-original-princ "#")
- (let ((cust-print-current-level (1- cust-print-current-level)))
- (cust-print-original-princ "(")
- (let ((length (or print-length 0)))
-
- ;; Print the first element always (even if length = 0).
- (cust-print-prin (car list))
- (setq list (cdr list))
- (if list (cust-print-original-princ " "))
- (setq length (1- length))
-
- ;; Print the rest of the elements.
- (while (and list (/= 0 length))
- (if (and (listp list)
- (not (assq list circle-table)))
- (progn
- (cust-print-prin (car list))
- (setq list (cdr list)))
-
- ;; cdr is not a list, or it is in circle-table.
- (cust-print-original-princ ". ")
- (cust-print-prin list)
- (setq list nil))
-
- (setq length (1- length))
- (if list (cust-print-original-princ " ")))
-
- (if (and list (= length 0)) (cust-print-original-princ "..."))
- (cust-print-original-princ ")"))))
- list)
-
-
-(defun cust-print-vector (vector)
- ;; Print a vector according to print-length, print-level, and print-circle.
- (if (= cust-print-current-level 0)
- (cust-print-original-princ "#")
- (let ((cust-print-current-level (1- cust-print-current-level))
- (i 0)
- (len (length vector)))
- (cust-print-original-princ "[")
-
- (if print-length
- (setq len (min print-length len)))
- ;; Print the elements
- (while (< i len)
- (cust-print-prin (aref vector i))
- (setq i (1+ i))
- (if (< i (length vector)) (cust-print-original-princ " ")))
-
- (if (< i (length vector)) (cust-print-original-princ "..."))
- (cust-print-original-princ "]")
- ))
- vector)
-
-
-
-;; Circular structure preprocessing
-;;==================================
-
-(defun cust-print-preprocess-circle-tree (object)
- ;; Fill up the table.
- (let (;; Table of tags for each object in an object to be printed.
- ;; A tag is of the form:
- ;; ( <object> <nil-t-or-id-number> )
- ;; The id-number is generated after the entire table has been computed.
- ;; During walk through, the real circle-table lives in the cdr so we
- ;; can use setcdr to add new elements instead of having to setq the
- ;; variable sometimes (poor man's locf).
- (circle-table (list nil)))
- (cust-print-walk-circle-tree object)
-
- ;; Reverse table so it is in the order that the objects will be printed.
- ;; This pass could be avoided if we always added to the end of the
- ;; table with setcdr in walk-circle-tree.
- (setcdr circle-table (nreverse (cdr circle-table)))
-
- ;; Walk through the table, assigning id-numbers to those
- ;; objects which will be printed using #N= syntax. Delete those
- ;; objects which will be printed only once (to speed up assq later).
- (let ((rest circle-table)
- (id -1))
- (while (cdr rest)
- (let ((tag (car (cdr rest))))
- (cond ((cdr tag)
- (setcdr tag id)
- (setq id (1- id))
- (setq rest (cdr rest)))
- ;; Else delete this object.
- (t (setcdr rest (cdr (cdr rest))))))
- ))
- ;; Drop the car.
- (cdr circle-table)
- ))
-
-
-
-(defun cust-print-walk-circle-tree (object)
- (let (read-equivalent-p tag)
- (while object
- (setq read-equivalent-p
- (or (numberp object)
- (and (symbolp object)
- ;; Check if it is uninterned.
- (eq object (intern-soft (symbol-name object)))))
- tag (and (not read-equivalent-p)
- (assq object (cdr circle-table))))
- (cond (tag
- ;; Seen this object already, so note that.
- (setcdr tag t))
-
- ((not read-equivalent-p)
- ;; Add a tag for this object.
- (setcdr circle-table
- (cons (list object)
- (cdr circle-table)))))
- (setq object
- (cond
- (tag ;; No need to descend since we have already.
- nil)
-
- ((consp object)
- ;; Walk the car of the list recursively.
- (cust-print-walk-circle-tree (car object))
- ;; But walk the cdr with the above while loop
- ;; to avoid problems with max-lisp-eval-depth.
- ;; And it should be faster than recursion.
- (cdr object))
-
- ((vectorp object)
- ;; Walk the vector.
- (let ((i (length object))
- (j 0))
- (while (< j i)
- (cust-print-walk-circle-tree (aref object j))
- (setq j (1+ j))))))))))
-
-
-;; Example.
-;;=======================================
-
-'(progn
- (progn
- ;; Create some circular structures.
- (setq circ-sym (let ((x (make-symbol "FOO"))) (list x x)))
- (setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f))
- (setcar (nthcdr 3 circ-list) circ-list)
- (aset (nth 2 circ-list) 2 circ-list)
- (setq dotted-circ-list (list 'a 'b 'c))
- (setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list)
- (setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7))
- (aset circ-vector 5 (make-symbol "-gensym-"))
- (setcar (cdr (aref circ-vector 4)) (aref circ-vector 5))
- nil)
-
- (install-custom-print)
- ;; (setq print-circle t)
-
- (let ((print-circle t))
- (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)")
- (error "Circular object with array printing")))
-
- (let ((print-circle t))
- (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)")
- (error "Circular object with array printing")))
-
- (let* ((print-circle t)
- (x (list 'p 'q))
- (y (list (list 'a 'b) x 'foo x)))
- (setcdr (cdr (cdr (cdr y))) (cdr y))
- (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))"
- )
- (error "Circular list example from CL manual")))
-
- (let ((print-circle nil))
- ;; cl-packages.el is required to print uninterned symbols like #:FOO.
- ;; (require 'cl-packages)
- (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)")
- (error "Uninterned symbols in list")))
- (let ((print-circle t))
- (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)")
- (error "Circular uninterned symbols in list")))
-
- (uninstall-custom-print)
- )
-
-(provide 'cust-print)
-
-;;; cust-print.el ends here
diff --git a/lisp/obsolete/eieio-compat.el b/lisp/obsolete/eieio-compat.el
index 8d8211b8498..2ac75293fcc 100644
--- a/lisp/obsolete/eieio-compat.el
+++ b/lisp/obsolete/eieio-compat.el
@@ -5,6 +5,7 @@
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: OO, lisp
;; Package: eieio
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
@@ -248,21 +249,6 @@ Summary:
nil)
;;;###autoload
-(defun eieio-defmethod (method args)
- "Obsolete work part of an old version of the `defmethod' macro."
- (declare (obsolete cl-defmethod "24.1"))
- (eval `(defmethod ,method ,@args))
- method)
-
-;;;###autoload
-(defun eieio-defgeneric (method doc-string)
- "Obsolete work part of an old version of the `defgeneric' macro."
- (declare (obsolete cl-defgeneric "24.1"))
- (eval `(defgeneric ,method (x) ,@(if doc-string `(,doc-string))))
- ;; Return the method
- 'method)
-
-;;;###autoload
(defun eieio-defclass (cname superclasses slots options)
(declare (obsolete eieio-defclass-internal "25.1"))
(eval `(defclass ,cname ,superclasses ,slots ,@options)))
diff --git a/lisp/obsolete/erc-hecomplete.el b/lisp/obsolete/erc-hecomplete.el
deleted file mode 100644
index 79ccf804409..00000000000
--- a/lisp/obsolete/erc-hecomplete.el
+++ /dev/null
@@ -1,218 +0,0 @@
-;;; erc-hecomplete.el --- Provides Nick name completion for ERC -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2001-2002, 2004, 2006-2022 Free Software Foundation,
-;; Inc.
-
-;; Author: Alex Schroeder <alex@gnu.org>
-;; URL: https://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This file is considered obsolete. It is recommended to use
-;; completion from erc-pcomplete instead.
-
-;; This file is based on hippie-expand, while the new file is based on
-;; pcomplete.
-
-;;; Code:
-
-(require 'erc)
-(require 'erc-match); for erc-pals
-(require 'hippie-exp); for the hippie expand stuff
-
-;;;###autoload (autoload 'erc-hecomplete-mode "erc-hecomplete" nil t)
-(define-erc-module hecomplete nil
- "Complete nick at point."
- ((add-hook 'erc-complete-functions #'erc-hecomplete))
- ((remove-hook 'erc-complete-functions #'erc-hecomplete)))
-
-(defun erc-hecomplete ()
- "Complete nick at point.
-See `erc-try-complete-nick' for more technical info.
-This function is obsolete, use `erc-pcomplete' instead."
- (interactive)
- (let ((hippie-expand-try-functions-list '(erc-try-complete-nick)))
- (hippie-expand nil)))
-
-(defgroup erc-hecomplete nil
- "Nick completion. It is recommended to use `erc-pcomplete' instead."
- :group 'erc)
-
-(defcustom erc-nick-completion 'all
- "Determine how the list of nicks is determined during nick completion.
-See `erc-complete-nick' for information on how to activate this.
-
-pals: Use `erc-pals'.
-all: All channel members.
-
-You may also provide your own function that returns a list of completions.
-One example is `erc-nick-completion-exclude-myself',
-or you may use an arbitrary lisp expression."
- :type '(choice (const :tag "List of pals" pals)
- (const :tag "All channel members" all)
- (const :tag "All channel members except yourself"
- erc-nick-completion-exclude-myself)
- (repeat :tag "List" (string :tag "Nick"))
- function
- sexp))
-
-(defcustom erc-nick-completion-ignore-case t
- "Non-nil means don't consider case significant in nick completion.
-Case will be automatically corrected when non-nil.
-For instance if you type \"dely TAB\" the word completes and changes to
-\"delYsid\"."
- :type 'boolean)
-
-(defun erc-nick-completion-exclude-myself ()
- "Get a list of all the channel members except you.
-
-This function returns a list of all the members in the channel, except
-your own nick. This way if you're named foo and someone is called foobar,
-typing \"f o TAB\" will directly give you foobar. Use this with
-`erc-nick-completion'."
- (remove
- (erc-current-nick)
- (erc-get-channel-nickname-list)))
-
-(defcustom erc-nick-completion-postfix ": "
- "When `erc-complete' is used in the first word after the prompt,
-add this string when a unique expansion was found."
- :type 'string)
-
-(defun erc-command-list ()
- "Return a list of strings of the defined user commands."
- (let ((case-fold-search nil))
- (mapcar (lambda (x)
- (concat "/" (downcase (substring (symbol-name x) 8))))
- (apropos-internal "erc-cmd-[A-Z]+"))))
-
-(defun erc-try-complete-nick (old)
- "Complete nick at point.
-This is a function to put on `hippie-expand-try-functions-list'.
-Then use \\[hippie-expand] to expand nicks.
-The type of completion depends on `erc-nick-completion'."
- (try-complete-erc-nick old (cond ((eq erc-nick-completion 'pals) erc-pals)
- ((eq erc-nick-completion 'all)
- (append
- (erc-get-channel-nickname-list)
- (erc-command-list)))
- ((functionp erc-nick-completion)
- (funcall erc-nick-completion))
- (t erc-nick-completion))))
-
-(defvar try-complete-erc-nick-window-configuration nil
- "The window configuration for `try-complete-erc-nick'.
-When called the first time, a window config is stored here,
-and when completion is done, the window config is restored
-from here. See `try-complete-erc-nick-restore' and
-`try-complete-erc-nick'.")
-
-(defun try-complete-erc-nick-restore ()
- "Restore window configuration."
- (if (not try-complete-erc-nick-window-configuration)
- (when (get-buffer "*Completions*")
- (delete-windows-on "*Completions*"))
- (set-window-configuration
- try-complete-erc-nick-window-configuration)
- (setq try-complete-erc-nick-window-configuration nil)))
-
-(defun try-complete-erc-nick (old completions)
- "Try to complete current word depending on `erc-try-complete-nick'.
-The argument OLD has to be nil the first call of this function, and t
-for subsequent calls (for further possible completions of the same
-string). It returns t if a new completion is found, nil otherwise. The
-second argument COMPLETIONS is a list of completions to use. Actually,
-it is only used when OLD is nil. It will be copied to `he-expand-list'
-on the first call. After that, it is no longer used.
-Window configurations are stored in
-`try-complete-erc-nick-window-configuration'."
- (let (expansion
- final
- (alist (if (consp (car completions))
- completions
- (mapcar (lambda (s)
- (if (and (erc-complete-at-prompt)
- (and (not (= (length s) 0))
- (not (eq (elt s 0) ?/))))
- (list (concat s erc-nick-completion-postfix))
- (list (concat s " "))))
- completions))) ; make alist if required
- (completion-ignore-case erc-nick-completion-ignore-case))
- (he-init-string (he-dabbrev-beg) (point))
- ;; If there is a string to complete, complete it using alist.
- ;; expansion is the possible expansion, or t. If expansion is t
- ;; or if expansion is the "real" thing, we are finished (final is
- ;; t). Take care -- expansion can also be nil!
- (unless (string= he-search-string "")
- (setq expansion (try-completion he-search-string alist)
- final (or (eq t expansion)
- (and expansion
- (eq t (try-completion expansion alist))))))
- (cond ((not expansion)
- ;; There is no expansion at all.
- (try-complete-erc-nick-restore)
- (he-reset-string)
- nil)
- ((eq t expansion)
- ;; The user already has the correct expansion.
- (try-complete-erc-nick-restore)
- (he-reset-string)
- t)
- ((and old (string= expansion he-search-string))
- ;; This is the second time around and nothing changed,
- ;; ie. the user tried to expand something incomplete
- ;; without making a choice -- hitting TAB twice, for
- ;; example.
- (try-complete-erc-nick-restore)
- (he-reset-string)
- nil)
- (final
- ;; The user has found the correct expansion.
- (try-complete-erc-nick-restore)
- (he-substitute-string expansion)
- t)
- (t
- ;; We found something but we are not finished. Show a
- ;; completions buffer. Substitute what we found and return
- ;; t.
- (setq try-complete-erc-nick-window-configuration
- (current-window-configuration))
- (with-output-to-temp-buffer "*Completions*"
- (display-completion-list (all-completions he-search-string alist)))
- (he-substitute-string expansion)
- t))))
-
-(defun erc-at-beginning-of-line-p (point &optional bol-func)
- (save-excursion
- (funcall (or bol-func
- 'erc-bol))
- (equal point (point))))
-
-(defun erc-complete-at-prompt ()
- "Return t if point is directly after `erc-prompt' when doing completion."
- (erc-at-beginning-of-line-p (he-dabbrev-beg)))
-
-(provide 'erc-hecomplete)
-
-;;; erc-hecomplete.el ends here
-;;
-;; Local Variables:
-;; indent-tabs-mode: t
-;; tab-width: 8
-;; End:
diff --git a/lisp/obsolete/gs.el b/lisp/obsolete/gs.el
index 971e7d2640a..7bf324ceecf 100644
--- a/lisp/obsolete/gs.el
+++ b/lisp/obsolete/gs.el
@@ -116,7 +116,7 @@ FILE is the value to substitute for the place-holder `<file>'."
(/ (* 25.4 mm) 72.0)))
(declare-function x-change-window-property "xfns.c"
- (prop value &optional frame type format outer-p))
+ (prop value &optional frame type format outer-p window-id))
(defun gs-set-ghostview-window-prop (frame spec img-width img-height)
"Set the `GHOSTVIEW' window property of FRAME.
diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el
index 6c1be1078ff..6c4c10ca6c2 100644
--- a/lisp/obsolete/info-edit.el
+++ b/lisp/obsolete/info-edit.el
@@ -33,7 +33,6 @@
(make-obsolete-variable 'Info-edit-mode-hook
"editing Info nodes by hand is not recommended." "24.4")
-(define-obsolete-variable-alias 'Info-edit-map 'Info-edit-mode-map "24.1")
(defvar Info-edit-mode-map (let ((map (make-sparse-keymap)))
(set-keymap-parent map text-mode-map)
(define-key map "\C-c\C-c" #'Info-cease-edit)
diff --git a/lisp/obsolete/iswitchb.el b/lisp/obsolete/iswitchb.el
index 2825ea1136c..1929d1994e7 100644
--- a/lisp/obsolete/iswitchb.el
+++ b/lisp/obsolete/iswitchb.el
@@ -1064,8 +1064,7 @@ Return the modified list with the last element prepended to it."
;; then create a new buffer
(progn
(setq newbufcreated (get-buffer-create buf))
- (if (fboundp 'set-buffer-major-mode)
- (set-buffer-major-mode newbufcreated))
+ (set-buffer-major-mode newbufcreated)
(iswitchb-visit-buffer newbufcreated))
;; else won't create new buffer
(message "no buffer matching `%s'" buf))))
diff --git a/lisp/obsolete/mailpost.el b/lisp/obsolete/mailpost.el
deleted file mode 100644
index 5b3a76e2f79..00000000000
--- a/lisp/obsolete/mailpost.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;;; mailpost.el --- RMAIL coupler to /usr/uci/post mailer -*- lexical-binding: t; -*-
-
-;; This is in the public domain
-;; since Delp distributed it in 1986 without a copyright notice.
-
-;; This file is part of GNU Emacs.
-
-;; Author: Gary Delp <delp@huey.Udel.Edu>
-;; Maintainer: emacs-devel@gnu.org
-;; Created: 13 Jan 1986
-;; Keywords: mail
-;; Obsolete-since: 24.3
-
-;;; Commentary:
-
-;; Yet another mail interface. this for the rmail system to provide
-;; the missing sendmail interface on systems without /usr/lib/sendmail,
-;; but with /usr/uci/post.
-
-;;; Code:
-
-(require 'mailalias)
-(require 'sendmail)
-
-;; (setq send-mail-function 'post-mail-send-it)
-
-(defun post-mail-send-it ()
- "The MH -post interface for `rmail-mail' to call.
-To use it, include \"(setq send-mail-function \\='post-mail-send-it)\" in
-site-init."
- (let ((errbuf (if mail-interactive
- (generate-new-buffer " post-mail errors")
- 0))
- temfile
- (tembuf (generate-new-buffer " post-mail temp"))
- (case-fold-search nil)
- delimline
- (mailbuf (current-buffer)))
- (unwind-protect
- (with-current-buffer tembuf
- (erase-buffer)
- (insert-buffer-substring mailbuf)
- (goto-char (point-max))
- ;; require one newline at the end.
- (or (= (preceding-char) ?\n)
- (insert ?\n))
- ;; Change header-delimiter to be what post-mail expects.
- (mail-sendmail-undelimit-header)
- (setq delimline (point-marker))
- (if mail-aliases
- (expand-mail-aliases (point-min) delimline))
- (goto-char (point-min))
- ;; ignore any blank lines in the header
- (while (and (re-search-forward "\n\n\n*" delimline t)
- (< (point) delimline))
- (replace-match "\n"))
- ;; Find and handle any Fcc fields.
- (let ((case-fold-search t))
- (goto-char (point-min))
- (if (re-search-forward "^Fcc:" delimline t)
- (mail-do-fcc delimline))
- ;; If there is a From and no Sender, put it a Sender.
- (goto-char (point-min))
- (and (re-search-forward "^From:" delimline t)
- (not (save-excursion
- (goto-char (point-min))
- (re-search-forward "^Sender:" delimline t)))
- (progn
- (forward-line 1)
- (insert "Sender: " (user-login-name) "\n")))
- ;; don't send out a blank subject line
- (goto-char (point-min))
- (if (re-search-forward "^Subject:[ \t]*\n" delimline t)
- (replace-match ""))
- (if mail-interactive
- (with-current-buffer errbuf
- (erase-buffer))))
- (with-file-modes 384 (setq temfile (make-temp-file ",rpost")))
- (apply #'call-process
- (append (list (if (boundp 'post-mail-program)
- post-mail-program
- "/usr/uci/lib/mh/post")
- nil errbuf nil
- "-nofilter" "-msgid")
- (if mail-interactive '("-watch") '("-nowatch"))
- (list temfile)))
- (if mail-interactive
- (with-current-buffer errbuf
- (goto-char (point-min))
- (while (re-search-forward "\n\n* *" nil t)
- (replace-match "; "))
- (if (not (zerop (buffer-size)))
- (error "Sending...failed to %s"
- (buffer-substring (point-min) (point-max)))))))
- (kill-buffer tembuf)
- (if (bufferp errbuf)
- (switch-to-buffer errbuf)))))
-
-(provide 'mailpost)
-
-;;; mailpost.el ends here
diff --git a/lisp/obsolete/mouse-sel.el b/lisp/obsolete/mouse-sel.el
deleted file mode 100644
index a9d6bfee604..00000000000
--- a/lisp/obsolete/mouse-sel.el
+++ /dev/null
@@ -1,731 +0,0 @@
-;;; mouse-sel.el --- multi-click selection support -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1993-1995, 2001-2022 Free Software Foundation, Inc.
-
-;; Author: Mike Williams <mdub@bigfoot.com>
-;; Keywords: mouse
-;; Obsolete-since: 24.3
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This module provides multi-click mouse support for GNU Emacs versions
-;; 19.18 and later. I've tried to make it behave more like standard X
-;; clients (eg. xterm) than the default Emacs 19 mouse selection handlers.
-;; Basically:
-;;
-;; * Clicking mouse-1 starts (cancels) selection, dragging extends it.
-;;
-;; * Clicking or dragging mouse-3 extends the selection as well.
-;;
-;; * Double-clicking on word constituents selects words.
-;; Double-clicking on symbol constituents selects symbols.
-;; Double-clicking on quotes or parentheses selects sexps.
-;; Double-clicking on whitespace selects whitespace.
-;; Triple-clicking selects lines.
-;; Quad-clicking selects paragraphs.
-;;
-;; * Selecting sets the region & X primary selection, but does NOT affect
-;; the kill-ring. Because the mouse handlers set the primary selection
-;; directly, mouse-sel sets the variables interprogram-cut-function
-;; and interprogram-paste-function to nil.
-;;
-;; * Clicking mouse-2 inserts the contents of the primary selection at
-;; the mouse position (or point, if mouse-yank-at-point is non-nil).
-;;
-;; * Pressing mouse-2 while selecting or extending copies selection
-;; to the kill ring. Pressing mouse-1 or mouse-3 kills it.
-;;
-;; * Double-clicking mouse-3 also kills selection.
-;;
-;; * M-mouse-1, M-mouse-2 & M-mouse-3 work similarly to mouse-1, mouse-2
-;; & mouse-3, but operate on the X secondary selection rather than the
-;; primary selection and region.
-;;
-;; This module requires my thingatpt.el module, which it uses to find the
-;; bounds of words, lines, sexps, etc.
-;;
-;; Thanks to KevinB@bartley.demon.co.uk for his useful input.
-;;
-;;--- Customization -------------------------------------------------------
-;;
-;; * You may want to use none or more of following:
-;;
-;; ;; Enable region highlight
-;; (transient-mark-mode 1)
-;;
-;; ;; But only in the selected window
-;; (setq highlight-nonselected-windows nil)
-;;
-;; ;; Enable pending-delete
-;; (delete-selection-mode 1)
-;;
-;; * You can control the way mouse-sel binds its keys by setting the value
-;; of mouse-sel-default-bindings before loading mouse-sel.
-;;
-;; (a) If mouse-sel-default-bindings = t (the default)
-;;
-;; Mouse sets and insert selection
-;; mouse-1 mouse-select
-;; mouse-2 mouse-insert-selection
-;; mouse-3 mouse-extend
-;;
-;; Selection/kill-ring interaction is disabled
-;; interprogram-cut-function = nil
-;; interprogram-paste-function = nil
-;;
-;; (b) If mouse-sel-default-bindings = 'interprogram-cut-paste
-;;
-;; Mouse sets selection, and pastes from kill-ring
-;; mouse-1 mouse-select
-;; mouse-2 mouse-insert-selection
-;; mouse-3 mouse-extend
-;; In this mode, mouse-insert-selection just calls mouse-yank-at-click.
-;;
-;; Selection/kill-ring interaction is retained
-;; interprogram-cut-function = gui-select-text
-;; interprogram-paste-function = gui-selection-value
-;;
-;; What you lose is the ability to select some text in
-;; delete-selection-mode and yank over the top of it.
-;;
-;; (c) If mouse-sel-default-bindings = nil, no bindings are made.
-;;
-;; * By default, mouse-insert-selection (mouse-2) inserts the selection at
-;; the mouse position. You can tell it to insert at point instead with:
-;;
-;; (setq mouse-yank-at-point t)
-;;
-;; * I like to leave point at the end of the region nearest to where the
-;; mouse was, even though this makes region highlighting mis-leading (the
-;; cursor makes it look like one extra character is selected). You can
-;; disable this behavior with:
-;;
-;; (setq mouse-sel-leave-point-near-mouse nil)
-;;
-;; * By default, mouse-select cycles the click count after 4 clicks. That
-;; is, clicking mouse-1 five times has the same effect as clicking it
-;; once, clicking six times has the same effect as clicking twice, etc.
-;; Disable this behavior with:
-;;
-;; (setq mouse-sel-cycle-clicks nil)
-;;
-;; * The variables mouse-sel-{set,get}-selection-function control how the
-;; selection is handled. Under X Windows, these variables default so
-;; that the X primary selection is used. Under other windowing systems,
-;; alternate functions are used, which simply store the selection value
-;; in a variable.
-
-;;; Code:
-
-(require 'mouse)
-(require 'thingatpt)
-
-;;=== User Variables ======================================================
-
-(defgroup mouse-sel nil
- "Mouse selection enhancement."
- :group 'mouse)
-
-(defcustom mouse-sel-leave-point-near-mouse t
- "Leave point near last mouse position.
-If non-nil, \\[mouse-select] and \\[mouse-extend] will leave point at the end
-of the region nearest to where the mouse last was.
-If nil, point will always be placed at the beginning of the region."
- :type 'boolean)
-
-(defcustom mouse-sel-cycle-clicks t
- "If non-nil, \\[mouse-select] cycles the click-counts after 4 clicks."
- :type 'boolean)
-
-(defcustom mouse-sel-default-bindings t
- "Control mouse bindings."
- :type '(choice (const :tag "none" nil)
- (const :tag "cut and paste" interprogram-cut-paste)
- (other :tag "default bindings" t)))
-
-;;=== Key bindings ========================================================
-
-(defconst mouse-sel-bound-events
- '(;; Primary selection bindings.
- ;;
- ;; Bind keys to `ignore' instead of unsetting them because modes may
- ;; bind `down-mouse-1', for instance, without binding `mouse-1'.
- ;; If we unset `mouse-1', this leads to a bitch_at_user when the
- ;; mouse goes up because no matching binding is found for that.
- ([mouse-1] . ignore)
- ([drag-mouse-1] . ignore)
- ([mouse-3] . ignore)
- ([down-mouse-1] . mouse-select)
- ([down-mouse-3] . mouse-extend)
- ([mouse-2] . mouse-insert-selection)
- ;; Secondary selection bindings.
- ([M-mouse-1] . ignore)
- ([M-drag-mouse-1] . ignore)
- ([M-mouse-3] . ignore)
- ([M-down-mouse-1] . mouse-select-secondary)
- ([M-mouse-2] . mouse-insert-secondary)
- ([M-down-mouse-3] . mouse-extend-secondary))
- "An alist of events that `mouse-sel-mode' binds.")
-
-;;=== User Command ========================================================
-
-(defvar mouse-sel-original-bindings nil)
-
-(defalias 'mouse-sel--ignore #'ignore)
-
-;;;###autoload
-(define-minor-mode mouse-sel-mode
- "Toggle Mouse Sel mode.
-
-Mouse Sel mode is a global minor mode. When enabled, mouse
-selection is enhanced in various ways:
-
-- Double-clicking on symbol constituents selects symbols.
-Double-clicking on quotes or parentheses selects sexps.
-Double-clicking on whitespace selects whitespace.
-Triple-clicking selects lines.
-Quad-clicking selects paragraphs.
-
-- Selecting sets the region & X primary selection, but does NOT affect
-the `kill-ring', nor do the kill-ring functions change the X selection.
-Because the mouse handlers set the primary selection directly,
-mouse-sel sets the variables `interprogram-cut-function' and
-`interprogram-paste-function' to nil.
-
-- Clicking mouse-2 inserts the contents of the primary selection at
-the mouse position (or point, if `mouse-yank-at-point' is non-nil).
-
-- mouse-2 while selecting or extending copies selection to the
-kill ring; mouse-1 or mouse-3 kills it."
- :global t
- (if mouse-sel-mode
- (progn
- ;; If mouse-2 has never been done by the user, initialize the
- ;; `event-kind' property to ensure that `follow-link' clicks
- ;; are interpreted correctly.
- (put 'mouse-2 'event-kind 'mouse-click)
- (add-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook)
- (when mouse-sel-default-bindings
- ;; Save original bindings and replace them with new ones.
- (setq mouse-sel-original-bindings
- (mapcar (lambda (binding)
- (let ((event (car binding)))
- (prog1 (cons event (lookup-key global-map event))
- (global-set-key event (cdr binding)))))
- mouse-sel-bound-events))
- ;; Update interprogram functions.
- (unless (eq mouse-sel-default-bindings 'interprogram-cut-paste)
- (add-function :override interprogram-cut-function
- #'mouse-sel--ignore)
- (add-function :override interprogram-paste-function
- #'mouse-sel--ignore))))
-
- ;; Restore original bindings
- (remove-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook)
- (dolist (binding mouse-sel-original-bindings)
- (global-set-key (car binding) (cdr binding)))
- ;; Restore the old values of these variables,
- ;; only if they were actually saved previously.
- (remove-function interprogram-cut-function #'mouse-sel--ignore)
- (remove-function interprogram-paste-function #'mouse-sel--ignore)))
-
-(make-obsolete 'mouse-sel-mode "use the normal mouse modes" "24.3")
-
-;;=== Internal Variables/Constants ========================================
-
-(defvar mouse-sel-primary-thing nil
- "Type of PRIMARY selection in current buffer.")
-(make-variable-buffer-local 'mouse-sel-primary-thing)
-
-(defvar mouse-sel-secondary-thing nil
- "Type of SECONDARY selection in current buffer.")
-(make-variable-buffer-local 'mouse-sel-secondary-thing)
-
-;; Ensure that secondary overlay is defined
-(unless (overlayp mouse-secondary-overlay)
- (setq mouse-secondary-overlay (make-overlay 1 1))
- (overlay-put mouse-secondary-overlay 'face 'secondary-selection))
-
-(defconst mouse-sel-primary-overlay
- (let ((ol (make-overlay (point-min) (point-min))))
- (delete-overlay ol)
- (overlay-put ol 'face 'region)
- ol)
- "An overlay which records the current primary selection.
-This is used by Mouse Sel mode only.")
-
-(defconst mouse-sel-selection-alist
- '((PRIMARY mouse-sel-primary-overlay mouse-sel-primary-thing)
- (SECONDARY mouse-secondary-overlay mouse-sel-secondary-thing))
- "Alist associating selections with variables.
-Each element is of the form:
-
- (SELECTION-NAME OVERLAY-SYMBOL SELECTION-THING-SYMBOL)
-
-where SELECTION-NAME = name of selection
- OVERLAY-SYMBOL = name of variable containing overlay to use
- SELECTION-THING-SYMBOL = name of variable where the current selection
- type for this selection should be stored.")
-
-(defvar mouse-sel-set-selection-function
- (if (eq mouse-sel-default-bindings 'interprogram-cut-paste)
- 'gui-set-selection
- (lambda (selection value)
- (if (eq selection 'PRIMARY)
- (gui-select-text value)
- (gui-set-selection selection value))))
- "Function to call to set selection.
-Called with two arguments:
-
- SELECTION, the name of the selection concerned, and
- VALUE, the text to store.
-
-This sets the selection, unless `mouse-sel-default-bindings'
-is `interprogram-cut-paste'.")
-
-
-(defvar mouse-sel-get-selection-function
- (lambda (selection)
- (if (eq selection 'PRIMARY)
- (or (gui-selection-value)
- (bound-and-true-p x-last-selected-text-primary)
- gui--last-selected-text-primary)
- (gui-get-selection selection)))
- "Function to call to get the selection.
-Called with one argument:
-
- SELECTION: the name of the selection concerned.")
-
-;;=== Support/access functions ============================================
-
-(defun mouse-sel-determine-selection-thing (nclicks)
- "Determine what `thing' `mouse-sel' should operate on.
-The first argument is NCLICKS, is the number of consecutive
-mouse clicks at the same position.
-
-Double-clicking on word constituents selects words.
-Double-clicking on symbol constituents selects symbols.
-Double-clicking on quotes or parentheses selects sexps.
-Double-clicking on whitespace selects whitespace.
-Triple-clicking selects lines.
-Quad-clicking selects paragraphs.
-
-Feel free to re-define this function to support your own desired
-multi-click semantics."
- (let* ((next-char (char-after (point)))
- (char-syntax (if next-char (char-syntax next-char))))
- (if mouse-sel-cycle-clicks
- (setq nclicks (1+ (% (1- nclicks) 4))))
- (cond
- ((= nclicks 1) nil)
- ((= nclicks 3) 'line)
- ((>= nclicks 4) 'paragraph)
- ((memq char-syntax '(?\( ?\) ?\" ?')) 'sexp)
- ((memq next-char '(?\s ?\t ?\n)) 'whitespace)
- ((eq char-syntax ?_) 'symbol)
- ((eq char-syntax ?w) 'word))))
-
-(defun mouse-sel-set-selection (selection value)
- "Set the specified SELECTION to VALUE."
- (if mouse-sel-set-selection-function
- (funcall mouse-sel-set-selection-function selection value)
- (put 'mouse-sel-internal-selection selection value)))
-
-(defun mouse-sel-get-selection (selection)
- "Get the value of the specified SELECTION."
- (if mouse-sel-get-selection-function
- (funcall mouse-sel-get-selection-function selection)
- (get 'mouse-sel-internal-selection selection)))
-
-(defun mouse-sel-selection-overlay (selection)
- "Return overlay corresponding to SELECTION."
- (let ((symbol (nth 1 (assoc selection mouse-sel-selection-alist))))
- (or symbol (error "No overlay corresponding to %s selection" selection))
- (symbol-value symbol)))
-
-(defun mouse-sel-selection-thing (selection)
- "Return overlay corresponding to SELECTION."
- (let ((symbol (nth 2 (assoc selection mouse-sel-selection-alist))))
- (or symbol (error "No symbol corresponding to %s selection" selection))
- symbol))
-
-(defun mouse-sel-region-to-primary (orig-window)
- "Convert region to PRIMARY overlay and deactivate region.
-Argument ORIG-WINDOW specifies the window the cursor was in when the
-originating command was issued, and is used to determine whether the
-region was visible or not."
- (if transient-mark-mode
- (let ((overlay (mouse-sel-selection-overlay 'PRIMARY)))
- (cond
- ((and mark-active
- (or highlight-nonselected-windows
- (eq orig-window (selected-window))))
- ;; Region was visible, so convert region to overlay
- (move-overlay overlay (region-beginning) (region-end)
- (current-buffer)))
- ((eq orig-window (selected-window))
- ;; Point was visible, so set overlay at point
- (move-overlay overlay (point) (point) (current-buffer)))
- (t
- ;; Nothing was visible, so remove overlay
- (delete-overlay overlay)))
- (setq mark-active nil))))
-
-(defun mouse-sel-primary-to-region (&optional direction)
- "Convert PRIMARY overlay to region.
-Optional argument DIRECTION specifies the mouse drag direction: a value of
-1 indicates that the mouse was dragged left-to-right, otherwise it was
-dragged right-to-left."
- (let* ((overlay (mouse-sel-selection-overlay 'PRIMARY))
- (start (overlay-start overlay))
- (end (overlay-end overlay)))
- (if (eq start end)
- (progn
- (if start (goto-char start))
- (deactivate-mark))
- (if (and mouse-sel-leave-point-near-mouse (eq direction 1))
- (progn
- (goto-char end)
- (push-mark start 'nomsg 'active))
- (goto-char start)
- (push-mark end 'nomsg 'active)))
- (if transient-mark-mode (delete-overlay overlay))))
-
-(defmacro mouse-sel-eval-at-event-end (event &rest forms)
- "Evaluate forms at mouse position.
-Move to the end position of EVENT, execute FORMS, and restore original
-point and window."
- `(let ((posn (event-end ,event)))
- (if posn (mouse-minibuffer-check ,event))
- (if (and posn (not (windowp (posn-window posn))))
- (error "Cursor not in text area of window"))
- (let (orig-window orig-point-marker)
- (setq orig-window (selected-window))
- (if posn (select-window (posn-window posn)))
- (setq orig-point-marker (point-marker))
- (if (and posn (numberp (posn-point posn)))
- (goto-char (posn-point posn)))
- (unwind-protect
- (progn
- ,@forms)
- (goto-char (marker-position orig-point-marker))
- (move-marker orig-point-marker nil)
- (select-window orig-window)))))
-
-(put 'mouse-sel-eval-at-event-end 'lisp-indent-hook 1)
-
-;;=== Select ==============================================================
-
-(defun mouse-select (event)
- "Set region/selection using the mouse.
-
-Click sets point & mark to click position.
-Dragging extends region/selection.
-
-Multi-clicking selects word/lines/paragraphs, as determined by
-'mouse-sel-determine-selection-thing.
-
-Clicking mouse-2 while selecting copies selected text to the kill-ring.
-Clicking mouse-1 or mouse-3 kills the selected text.
-
-This should be bound to a down-mouse event."
- (interactive "@e")
- (let (select)
- (unwind-protect
- (setq select (mouse-select-internal 'PRIMARY event))
- (if (and select (listp select))
- (push (cons 'mouse-2 (cdr event)) unread-command-events)
- (mouse-sel-primary-to-region select)))))
-
-(defun mouse-select-secondary (event)
- "Set secondary selection using the mouse.
-
-Click sets the start of the secondary selection to click position.
-Dragging extends the secondary selection.
-
-Multi-clicking selects word/lines/paragraphs, as determined by
-'mouse-sel-determine-selection-thing.
-
-Clicking mouse-2 while selecting copies selected text to the kill-ring.
-Clicking mouse-1 or mouse-3 kills the selected text.
-
-This should be bound to a down-mouse event."
- (interactive "e")
- (mouse-select-internal 'SECONDARY event))
-
-(defun mouse-select-internal (selection event)
- "Set SELECTION using the mouse, with EVENT as the initial down-event.
-Normally, this returns the direction in which the selection was
-made: a value of 1 indicates that the mouse was dragged
-left-to-right, otherwise it was dragged right-to-left.
-
-However, if `mouse-1-click-follows-link' is non-nil and the
-subsequent mouse events specify following a link, this returns
-the final mouse-event. In that case, the selection is not set."
- (mouse-sel-eval-at-event-end event
- (let ((thing-symbol (mouse-sel-selection-thing selection))
- (overlay (mouse-sel-selection-overlay selection)))
- (set thing-symbol
- (mouse-sel-determine-selection-thing (event-click-count event)))
- (let ((object-bounds (bounds-of-thing-at-point
- (symbol-value thing-symbol))))
- (if object-bounds
- (progn
- (move-overlay overlay
- (car object-bounds) (cdr object-bounds)
- (current-buffer)))
- (move-overlay overlay (point) (point) (current-buffer)))))
- (catch 'follow-link
- (mouse-extend-internal selection event t))))
-
-;;=== Extend ==============================================================
-
-(defun mouse-extend (event)
- "Extend region/selection using the mouse."
- (interactive "e")
- (let ((orig-window (selected-window))
- direction)
- (select-window (posn-window (event-end event)))
- (unwind-protect
- (progn
- (mouse-sel-region-to-primary orig-window)
- (setq direction (mouse-extend-internal 'PRIMARY event)))
- (mouse-sel-primary-to-region direction))))
-
-(defun mouse-extend-secondary (event)
- "Extend secondary selection using the mouse."
- (interactive "e")
- (save-window-excursion
- (mouse-extend-internal 'SECONDARY event)))
-
-(defun mouse-extend-internal (selection &optional initial-event no-process)
- "Extend specified SELECTION using the mouse.
-Track mouse-motion events, adjusting the SELECTION appropriately.
-Optional argument INITIAL-EVENT specifies an initial down-mouse event.
-Optional argument NO-PROCESS means not to process the initial
-event.
-
-See documentation for mouse-select-internal for more details."
- (mouse-sel-eval-at-event-end initial-event
- (let ((orig-cursor-type
- (cdr (assoc 'cursor-type (frame-parameters (selected-frame))))))
- (unwind-protect
-
- (let* ((thing-symbol (mouse-sel-selection-thing selection))
- (overlay (mouse-sel-selection-overlay selection))
- (orig-window (selected-window))
- (top (nth 1 (window-edges orig-window)))
- (bottom (nth 3 (window-edges orig-window)))
- (mark-active nil) ; inhibit normal region highlight
- (echo-keystrokes 0) ; don't echo mouse events
- min max
- direction
- event)
-
- ;; Get current bounds of overlay
- (if (eq (overlay-buffer overlay) (current-buffer))
- (setq min (overlay-start overlay)
- max (overlay-end overlay))
- (setq min (point)
- max min)
- (set thing-symbol nil))
-
-
- ;; Bar cursor
- (if (fboundp 'modify-frame-parameters)
- (modify-frame-parameters (selected-frame)
- '((cursor-type . bar))))
-
- ;; Handle dragging
- (track-mouse
-
- (while (if (and initial-event (not no-process))
- ;; Use initial event
- (prog1
- (setq event initial-event)
- (setq initial-event nil))
- (setq event (read-event))
- (and (consp event)
- (memq (car event) '(mouse-movement switch-frame))))
-
- (let ((selection-thing (symbol-value thing-symbol))
- (end (event-end event)))
-
- (cond
-
- ;; Ignore any movement outside the frame
- ((eq (car-safe event) 'switch-frame) nil)
- ((and (posn-window end)
- (not (eq (let ((posn-w (posn-window end)))
- (if (windowp posn-w)
- (window-frame posn-w)
- posn-w))
- (window-frame orig-window)))) nil)
-
- ;; Different window, same frame
- ((not (eq (posn-window end) orig-window))
- (let ((end-row (cdr (cdr (mouse-position)))))
- (cond
- ((and end-row (not (bobp)) (< end-row top))
- (mouse-scroll-subr orig-window (- end-row top)
- overlay max))
- ((and end-row (not (eobp)) (>= end-row bottom))
- (mouse-scroll-subr orig-window (1+ (- end-row bottom))
- overlay min))
- )))
-
- ;; On the mode line
- ((eq (posn-point end) 'mode-line)
- (mouse-scroll-subr orig-window 1 overlay min))
-
- ;; In original window
- (t (goto-char (posn-point end)))
-
- )
-
- ;; Determine direction of drag
- (cond
- ((and (not direction) (not (eq min max)))
- (setq direction (if (< (point) (/ (+ min max) 2)) -1 1)))
- ((and (not (eq direction -1)) (<= (point) min))
- (setq direction -1))
- ((and (not (eq direction 1)) (>= (point) max))
- (setq direction 1)))
-
- (if (not selection-thing) nil
-
- ;; If dragging forward, goal is next character
- (if (and (eq direction 1) (not (eobp))) (forward-char 1))
-
- ;; Move to start/end of selected thing
- (let ((goal (point)))
- (goto-char (if (eq 1 direction) min max))
- (condition-case nil
- (progn
- (while (> (* direction (- goal (point))) 0)
- (forward-thing selection-thing direction))
- (let ((end (point)))
- (forward-thing selection-thing (- direction))
- (goto-char
- (if (> (* direction (- goal (point))) 0)
- end (point)))))
- (error))))
-
- ;; Move overlay
- (move-overlay overlay
- (if (eq 1 direction) min (point))
- (if (eq -1 direction) max (point))
- (current-buffer))
-
- ))) ; end track-mouse
-
- ;; Detect follow-link events
- (when (mouse-sel-follow-link-p initial-event event)
- (throw 'follow-link event))
-
- ;; Finish up after dragging
- (let ((overlay-start (overlay-start overlay))
- (overlay-end (overlay-end overlay)))
-
- ;; Set selection
- (if (not (eq overlay-start overlay-end))
- (mouse-sel-set-selection
- selection
- (buffer-substring overlay-start overlay-end)))
-
- ;; Handle copy/kill
- (let (this-command)
- (cond
- ((eq (event-basic-type last-input-event) 'mouse-2)
- (copy-region-as-kill overlay-start overlay-end)
- (read-event) (read-event))
- ((and (memq (event-basic-type last-input-event)
- '(mouse-1 mouse-3))
- (memq 'down (event-modifiers last-input-event)))
- (kill-region overlay-start overlay-end)
- (move-overlay overlay overlay-start overlay-start)
- (read-event) (read-event))
- ((and (eq (event-basic-type last-input-event) 'mouse-3)
- (memq 'double (event-modifiers last-input-event)))
- (kill-region overlay-start overlay-end)
- (move-overlay overlay overlay-start overlay-start)))))
-
- direction)
-
- ;; Restore cursor
- (if (fboundp 'modify-frame-parameters)
- (modify-frame-parameters
- (selected-frame) (list (cons 'cursor-type orig-cursor-type))))
-
- ))))
-
-(defun mouse-sel-follow-link-p (initial final)
- "Return t if we should follow a link, given INITIAL and FINAL mouse events.
-See `mouse-1-click-follows-link' for details. Currently, Mouse
-Sel mode does not support using a `double' value to follow links
-using double-clicks."
- (and initial final mouse-1-click-follows-link
- (eq (car initial) 'down-mouse-1)
- (mouse-on-link-p (event-start initial))
- (= (posn-point (event-start initial))
- (posn-point (event-end final)))
- (= (event-click-count initial) 1)
- (or (not (integerp mouse-1-click-follows-link))
- (let ((t0 (posn-timestamp (event-start initial)))
- (t1 (posn-timestamp (event-end final))))
- (and (integerp t0) (integerp t1)
- (if (> mouse-1-click-follows-link 0)
- (<= (- t1 t0) mouse-1-click-follows-link)
- (< (- t0 t1) mouse-1-click-follows-link)))))))
-
-;;=== Paste ===============================================================
-
-(defun mouse-insert-selection (event arg)
- "Insert the contents of the PRIMARY selection at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (interactive "e\nP")
- (if (eq mouse-sel-default-bindings 'interprogram-cut-paste)
- (mouse-yank-at-click event arg)
- (mouse-insert-selection-internal 'PRIMARY event)))
-
-(defun mouse-insert-secondary (event)
- "Insert the contents of the SECONDARY selection at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (interactive "e")
- (mouse-insert-selection-internal 'SECONDARY event))
-
-(defun mouse-insert-selection-internal (selection event)
- "Insert the contents of the named SELECTION at mouse click.
-If `mouse-yank-at-point' is non-nil, insert at point instead."
- (unless mouse-yank-at-point
- (mouse-set-point event))
- (when mouse-sel-get-selection-function
- (push-mark (point) 'nomsg)
- (insert-for-yank
- (or (funcall mouse-sel-get-selection-function selection) ""))))
-
-;;=== Handle loss of selections ===========================================
-
-(defun mouse-sel-lost-selection-hook (selection)
- "Remove the overlay for a lost selection."
- (let ((overlay (mouse-sel-selection-overlay selection)))
- (delete-overlay overlay)))
-
-(provide 'mouse-sel)
-
-;;; mouse-sel.el ends here
diff --git a/lisp/obsolete/old-emacs-lock.el b/lisp/obsolete/old-emacs-lock.el
deleted file mode 100644
index 70123e75375..00000000000
--- a/lisp/obsolete/old-emacs-lock.el
+++ /dev/null
@@ -1,102 +0,0 @@
-;;; old-emacs-lock.el --- prevents you from exiting Emacs if a buffer is locked -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1994, 1997, 2001-2022 Free Software Foundation, Inc.
-
-;; Author: Tom Wurgler <twurgler@goodyear.com>
-;; Created: 12/8/94
-;; Keywords: extensions, processes
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This code sets a buffer-local variable to t if toggle-emacs-lock is run,
-;; then if the user attempts to exit Emacs, the locked buffer name will be
-;; displayed and the exit aborted. This is just a way of protecting
-;; yourself from yourself. For example, if you have a shell running a big
-;; program and exiting Emacs would abort that program, you may want to lock
-;; that buffer, then if you forget about it after a while, you won't
-;; accidentally exit Emacs. To unlock the buffer, just goto the buffer and
-;; run toggle-emacs-lock again.
-
-;;; Code:
-
-(defvar emacs-lock-from-exiting nil
- "Whether Emacs is locked to prevent exiting. See `check-emacs-lock'.")
-(make-variable-buffer-local 'emacs-lock-from-exiting)
-
-(defvar emacs-lock-buffer-locked nil
- "Whether a shell or telnet buffer was locked when its process was killed.")
-(make-variable-buffer-local 'emacs-lock-buffer-locked)
-(put 'emacs-lock-buffer-locked 'permanent-local t)
-
-(defun check-emacs-lock ()
- "Check if variable `emacs-lock-from-exiting' is t for any buffer.
-If any locked buffer is found, signal error and display the buffer's name."
- (save-excursion
- (dolist (buffer (buffer-list))
- (set-buffer buffer)
- (when emacs-lock-from-exiting
- (error "Emacs is locked from exit due to buffer: %s" (buffer-name))))))
-
-(defun toggle-emacs-lock ()
- "Toggle `emacs-lock-from-exiting' for the current buffer.
-See `check-emacs-lock'."
- (interactive)
- (setq emacs-lock-from-exiting (not emacs-lock-from-exiting))
- (if emacs-lock-from-exiting
- (message "Buffer is now locked")
- (message "Buffer is now unlocked")))
-
-(defun emacs-lock-check-buffer-lock ()
- "Check if variable `emacs-lock-from-exiting' is t for a buffer.
-If the buffer is locked, signal error and display its name."
- (when emacs-lock-from-exiting
- (error "Buffer `%s' is locked, can't delete it" (buffer-name))))
-
-; These next defuns make it so if you exit a shell that is locked, the lock
-; is shut off for that shell so you can exit Emacs. Same for telnet.
-; Also, if a shell or a telnet buffer was locked and the process killed,
-; turn the lock back on again if the process is restarted.
-
-(defun emacs-lock-shell-sentinel ()
- (set-process-sentinel
- (get-buffer-process (buffer-name)) (function emacs-lock-clear-sentinel)))
-
-(defun emacs-lock-clear-sentinel (_proc _str)
- (if emacs-lock-from-exiting
- (progn
- (setq emacs-lock-from-exiting nil)
- (setq emacs-lock-buffer-locked t)
- (message "Buffer is now unlocked"))
- (setq emacs-lock-buffer-locked nil)))
-
-(defun emacs-lock-was-buffer-locked ()
- (if emacs-lock-buffer-locked
- (setq emacs-lock-from-exiting t)))
-
-(unless noninteractive
- (add-hook 'kill-emacs-hook #'check-emacs-lock))
-(add-hook 'kill-buffer-hook #'emacs-lock-check-buffer-lock)
-(add-hook 'shell-mode-hook #'emacs-lock-was-buffer-locked)
-(add-hook 'shell-mode-hook #'emacs-lock-shell-sentinel)
-(add-hook 'telnet-mode-hook #'emacs-lock-was-buffer-locked)
-(add-hook 'telnet-mode-hook #'emacs-lock-shell-sentinel)
-
-(provide 'emacs-lock)
-
-;;; old-emacs-lock.el ends here
diff --git a/lisp/obsolete/patcomp.el b/lisp/obsolete/patcomp.el
deleted file mode 100644
index 2c35cb07007..00000000000
--- a/lisp/obsolete/patcomp.el
+++ /dev/null
@@ -1,24 +0,0 @@
-;;; patcomp.el --- used by patch files to update Emacs releases -*- lexical-binding: t; -*-
-
-;; This file is part of GNU Emacs.
-
-;; Obsolete-since: 24.3
-
-;;; Commentary:
-
-;;; Code:
-
-(defun batch-byte-recompile-emacs ()
- "Recompile the Emacs `lisp' directory.
-This is used after installing the patches for a new version."
- (let ((load-path (list (expand-file-name "lisp"))))
- (byte-recompile-directory "lisp")))
-
-(defun batch-byte-compile-emacs ()
- "Compile new files installed in the Emacs `lisp' directory.
-This is used after installing the patches for a new version.
-It uses the command line arguments to specify the files to compile."
- (let ((load-path (list (expand-file-name "lisp"))))
- (batch-byte-compile)))
-
-;;; patcomp.el ends here
diff --git a/lisp/obsolete/pc-mode.el b/lisp/obsolete/pc-mode.el
deleted file mode 100644
index 4c4bfb5b9c7..00000000000
--- a/lisp/obsolete/pc-mode.el
+++ /dev/null
@@ -1,56 +0,0 @@
-;;; pc-mode.el --- emulate certain key bindings used on PCs -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1995, 2001-2022 Free Software Foundation, Inc.
-
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: emulations
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-;;;###autoload
-(defun pc-bindings-mode ()
- "Set up certain key bindings for PC compatibility.
-The keys affected are:
-Delete (and its variants) delete forward instead of backward.
-C-Backspace kills backward a word (as C-Delete normally would).
-M-Backspace does undo.
-Home and End move to beginning and end of line
-C-Home and C-End move to beginning and end of buffer.
-C-Escape does list-buffers."
-
- (interactive)
- (define-key function-key-map [delete] "\C-d")
- (define-key function-key-map [M-delete] [?\M-d])
- (define-key function-key-map [C-delete] [?\M-d])
- (global-set-key [C-M-delete] #'kill-sexp)
- (global-set-key [C-backspace] #'backward-kill-word)
- (global-set-key [M-backspace] #'undo)
-
- (global-set-key [C-escape] #'list-buffers)
-
- (global-set-key [home] #'beginning-of-line)
- (global-set-key [end] #'end-of-line)
- (global-set-key [C-home] #'beginning-of-buffer)
- (global-set-key [C-end] #'end-of-buffer))
-
-(provide 'pc-mode)
-
-;;; pc-mode.el ends here
diff --git a/lisp/obsolete/pc-select.el b/lisp/obsolete/pc-select.el
deleted file mode 100644
index 922358bcd66..00000000000
--- a/lisp/obsolete/pc-select.el
+++ /dev/null
@@ -1,410 +0,0 @@
-;;; pc-select.el --- emulate mark, cut, copy and paste from Motif -*- lexical-binding: t; -*-
-;;; (or MAC GUI or MS-windoze (bah)) look-and-feel
-;;; including key bindings.
-
-;; Copyright (C) 1995-1997, 2000-2022 Free Software Foundation, Inc.
-
-;; Author: Michael Staats <michael@thp.Uni-Duisburg.DE>
-;; Keywords: convenience emulations
-;; Created: 26 Sep 1995
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This package emulates the mark, copy, cut and paste look-and-feel of motif
-;; programs (which is the same as the MAC gui and (sorry for that) MS-Windows).
-;; It modifies the keybindings of the cursor keys and the next, prior,
-;; home and end keys. They will modify mark-active.
-;; You can still get the old behavior of cursor moving with the
-;; control sequences C-f, C-b, etc.
-;; This package uses transient-mark-mode and
-;; delete-selection-mode.
-;;
-;; In addition to that all key-bindings from the pc-mode are
-;; done here too (as suggested by RMS).
-;;
-;; As I found out after I finished the first version, s-region.el tries
-;; to do the same.... But my code is a little more complete and using
-;; delete-selection-mode is very important for the look-and-feel.
-;; Pete Forman <pete.forman@airgun.wg.waii.com> provided some motif
-;; compliant keybindings which I added. I had to modify them a little
-;; to add the -mark and -nomark functionality of cursor moving.
-;;
-;; Credits:
-;; Many thanks to all who made comments.
-;; Thanks to RMS and Ralf Muschall <prm@rz.uni-jena.de> for criticism.
-;; Kevin Cutts <cutts@ukraine.corp.mot.com> added the beginning-of-buffer
-;; and end-of-buffer functions which I modified a little.
-;; David Biesack <sasdjb@unx.sas.com> suggested some more cleanup.
-;; Thanks to Pete Forman <pete.forman@airgun.wg.waii.com>
-;; for additional motif keybindings.
-;; Thanks to jvromans@squirrel.nl (Johan Vromans) for a bug report
-;; concerning setting of this-command.
-;; Dan Nicolaescu <done@ece.arizona.ro> suggested suppressing the
-;; scroll-up/scroll-down error.
-;; Eli Barzilay (eli@cs.bgu.ac.il) suggested the sexps functions and
-;; keybindings.
-;;
-;; Ok, some details about the idea of PC Selection mode:
-;;
-;; o The standard keys for moving around (right, left, up, down, home, end,
-;; prior, next, called "move-keys" from now on) will always de-activate
-;; the mark.
-;; o If you press "Shift" together with the "move-keys", the region
-;; you pass along is activated
-;; o You have the copy, cut and paste functions (as in many other programs)
-;; which will operate on the active region
-;; It was not possible to bind them to C-v, C-x and C-c for obvious
-;; emacs reasons.
-;; They will be bound according to the "old" behavior to S-delete (cut),
-;; S-insert (paste) and C-insert (copy). These keys do the same in many
-;; other programs.
-;;
-
-;;; Code:
-
-;; Customization:
-(defgroup pc-select nil
- "Emulate pc bindings."
- :prefix "pc-select"
- :group 'emulations)
-
-(define-obsolete-variable-alias 'pc-select-override-scroll-error
- 'scroll-error-top-bottom
- "24.1")
-(defcustom pc-select-override-scroll-error t
- "Non-nil means don't generate error on scrolling past edge of buffer.
-This variable applies in PC Selection mode only.
-The scroll commands normally generate an error if you try to scroll
-past the top or bottom of the buffer. This is annoying when selecting
-text with these commands. If you set this variable to non-nil, these
-errors are suppressed."
- :type 'boolean)
-
-(defcustom pc-select-selection-keys-only nil
- "Non-nil means only bind the basic selection keys when started.
-Other keys that emulate pc-behavior will be untouched.
-This gives mostly Emacs-like behavior with only the selection keys enabled."
- :type 'boolean)
-
-(defcustom pc-select-meta-moves-sexps nil
- "Non-nil means move sexp-wise with Meta key, otherwise move word-wise."
- :type 'boolean)
-
-(defcustom pc-selection-mode-hook nil
- "The hook to run when PC Selection mode is toggled."
- :type 'hook)
-
-(defvar pc-select-saved-settings-alist nil
- "The values of the variables before PC Selection mode was toggled on.
-When PC Selection mode is toggled on, it sets quite a few variables
-for its own purposes. This alist holds the original values of the
-variables PC Selection mode had set, so that these variables can be
-restored to their original values when PC Selection mode is toggled off.")
-
-(defvar pc-select-map nil
- "The keymap used as the global map when PC Selection mode is on." )
-
-(defvar pc-select-saved-global-map nil
- "The global map that was in effect when PC Selection mode was toggled on.")
-
-(defvar pc-select-key-bindings-alist nil
- "This alist holds all the key bindings PC Selection mode sets.")
-
-(defvar pc-select-default-key-bindings nil
- "These key bindings always get set by PC Selection mode.")
-
-(defvar pc-select-extra-key-bindings
- ;; The following keybindings are for standard ISO keyboards
- ;; as they are used with IBM compatible PCs, IBM RS/6000,
- ;; MACs, many X-Stations and probably more.
- '(;; Commented out since it's been standard at least since Emacs-21.
- ;;([S-insert] . yank)
- ;;([C-insert] . copy-region-as-kill)
- ;;([S-delete] . kill-region)
-
- ;; The following bindings are useful on Sun Type 3 keyboards
- ;; They implement the Get-Delete-Put (copy-cut-paste)
- ;; functions from sunview on the L6, L8 and L10 keys
- ;; Sam Steingold <sds@gnu.org> says that f16 is copy and f18 is paste.
- ([f16] . copy-region-as-kill)
- ([f18] . yank)
- ([f20] . kill-region)
-
- ;; The following bindings are from Pete Forman.
- ([f6] . other-window) ; KNextPane F6
- ([C-delete] . kill-line) ; KEraseEndLine cDel
- ("\M-\d" . undo) ; KUndo aBS
-
- ;; The following binding is taken from pc-mode.el
- ;; as suggested by RMS.
- ;; I only used the one that is not covered above.
- ([C-M-delete] . kill-sexp)
- ;; Next line proposed by Eli Barzilay
- ([C-escape] . electric-buffer-list))
- "Key bindings to set only if `pc-select-selection-keys-only' is nil.")
-
-(defvar pc-select-meta-moves-sexps-key-bindings
- '((([M-right] . forward-sexp)
- ([M-left] . backward-sexp))
- (([M-right] . forward-word)
- ([M-left] . backward-word)))
- "The list of key bindings controlled by `pc-select-meta-moves-sexp'.
-The bindings in the car of this list get installed if
-`pc-select-meta-moves-sexp' is t, the bindings in the cadr of this
-list get installed otherwise.")
-
-;; This is for tty. We don't turn on normal-erase-is-backspace,
-;; but bind keys as pc-selection-mode did before
-;; normal-erase-is-backspace was invented, to keep us back
-;; compatible.
-(defvar pc-select-tty-key-bindings
- '(([delete] . delete-char) ; KDelete Del
- ([C-backspace] . backward-kill-word))
- "The list of key bindings controlled by `pc-select-selection-keys-only'.
-These key bindings get installed when running in a tty, but only if
-`pc-select-selection-keys-only' is nil.")
-
-(defvar pc-select-old-M-delete-binding nil
- "Holds the old mapping of [M-delete] in the `function-key-map'.
-This variable holds the value associated with [M-delete] in the
-`function-key-map' before PC Selection mode had changed that
-association.")
-
-;;;;
-;; misc
-;;;;
-
-(provide 'pc-select)
-
-(defun pc-select-define-keys (alist keymap)
- "Make KEYMAP have the key bindings specified in ALIST."
- (let ((lst alist))
- (while lst
- (define-key keymap (caar lst) (cdar lst))
- (setq lst (cdr lst)))))
-
-(defun pc-select-restore-keys (alist keymap saved-map)
- "Use ALIST to restore key bindings from SAVED-MAP into KEYMAP.
-Go through all the key bindings in ALIST, and, for each key
-binding, if KEYMAP and ALIST still agree on the key binding,
-restore the previous value of that key binding from SAVED-MAP."
- (let ((lst alist))
- (while lst
- (when (equal (lookup-key keymap (caar lst)) (cdar lst))
- (define-key keymap (caar lst) (lookup-key saved-map (caar lst))))
- (setq lst (cdr lst)))))
-
-(defmacro pc-select-add-to-alist (alist var val)
- "Ensure that ALIST contains the cons cell (VAR . VAL).
-If a cons cell whose car is VAR is already on the ALIST, update the
-cdr of that cell with VAL. Otherwise, make a new cons cell
-\(VAR . VAL), and prepend it onto ALIST."
- (let ((elt (make-symbol "elt")))
- `(let ((,elt (assq ',var ,alist)))
- (if ,elt
- (setcdr ,elt ,val)
- (setq ,alist (cons (cons ',var ,val) ,alist))))))
-
-(defmacro pc-select-save-and-set-var (var newval)
- "Set VAR to NEWVAL; save the old value.
-The old value is saved on the `pc-select-saved-settings-alist'."
- `(when (boundp ',var)
- (pc-select-add-to-alist pc-select-saved-settings-alist ,var ,var)
- (setq ,var ,newval)))
-
-(defmacro pc-select-save-and-set-mode (mode &optional arg mode-var)
- "Call the function MODE; save the old value of the variable MODE.
-MODE is presumed to be a function which turns on a minor mode. First,
-save the value of the variable MODE on `pc-select-saved-settings-alist'.
-Then, if ARG is specified, call MODE with ARG, otherwise call it with
-nil as an argument. If MODE-VAR is specified, save the value of the
-variable MODE-VAR (instead of the value of the variable MODE) on
-`pc-select-saved-settings-alist'."
- (unless mode-var (setq mode-var mode))
- `(when (fboundp ',mode)
- (pc-select-add-to-alist pc-select-saved-settings-alist
- ,mode-var ,mode-var)
- (,mode ,arg)))
-
-(defmacro pc-select-restore-var (var)
- "Restore the previous value of the variable VAR.
-Look up VAR's previous value in `pc-select-saved-settings-alist', and,
-if the value is found, set VAR to that value."
- (let ((elt (make-symbol "elt")))
- `(let ((,elt (assq ',var pc-select-saved-settings-alist)))
- (unless (null ,elt)
- (setq ,var (cdr ,elt))))))
-
-(defmacro pc-select-restore-mode (mode)
- "Restore the previous state (either on or off) of the minor mode MODE.
-Look up the value of the variable MODE on `pc-select-saved-settings-alist'.
-If the value is non-nil, call the function MODE with an argument of
-1, otherwise call it with an argument of -1."
- (let ((elt (make-symbol "elt")))
- `(when (fboundp ',mode)
- (let ((,elt (assq ',mode pc-select-saved-settings-alist)))
- (unless (null ,elt)
- (,mode (if (cdr ,elt) 1 -1)))))))
-
-
-;;;###autoload
-(define-minor-mode pc-selection-mode
- "Change mark behavior to emulate Motif, Mac or MS-Windows cut and paste style.
-
-This mode enables Delete Selection mode and Transient Mark mode.
-
-The arrow keys (and others) are bound to new functions
-which modify the status of the mark.
-
-The ordinary arrow keys disable the mark.
-The shift-arrow keys move, leaving the mark behind.
-
-C-LEFT and C-RIGHT move back or forward one word, disabling the mark.
-S-C-LEFT and S-C-RIGHT move back or forward one word, leaving the mark behind.
-
-M-LEFT and M-RIGHT move back or forward one word or sexp, disabling the mark.
-S-M-LEFT and S-M-RIGHT move back or forward one word or sexp, leaving the mark
-behind. To control whether these keys move word-wise or sexp-wise set the
-variable `pc-select-meta-moves-sexps' after loading pc-select.el but before
-turning PC Selection mode on.
-
-C-DOWN and C-UP move back or forward a paragraph, disabling the mark.
-S-C-DOWN and S-C-UP move back or forward a paragraph, leaving the mark behind.
-
-HOME moves to beginning of line, disabling the mark.
-S-HOME moves to beginning of line, leaving the mark behind.
-With Ctrl or Meta, these keys move to beginning of buffer instead.
-
-END moves to end of line, disabling the mark.
-S-END moves to end of line, leaving the mark behind.
-With Ctrl or Meta, these keys move to end of buffer instead.
-
-PRIOR or PAGE-UP scrolls and disables the mark.
-S-PRIOR or S-PAGE-UP scrolls and leaves the mark behind.
-
-S-DELETE kills the region (`kill-region').
-S-INSERT yanks text from the kill ring (`yank').
-C-INSERT copies the region into the kill ring (`copy-region-as-kill').
-
-In addition, certain other PC bindings are imitated (to avoid this, set
-the variable `pc-select-selection-keys-only' to t after loading pc-select.el
-but before calling PC Selection mode):
-
- F6 other-window
- DELETE delete-char
- C-DELETE kill-line
- M-DELETE kill-word
- C-M-DELETE kill-sexp
- C-BACKSPACE backward-kill-word
- M-BACKSPACE undo"
- ;; FIXME: bring pc-bindings-mode here ?
- :global t
-
- (if pc-selection-mode
- (if (null pc-select-key-bindings-alist)
- (progn
- (setq pc-select-saved-global-map (copy-keymap (current-global-map)))
- (setq pc-select-key-bindings-alist
- (append pc-select-default-key-bindings
- (if pc-select-selection-keys-only
- nil
- pc-select-extra-key-bindings)
- (if pc-select-meta-moves-sexps
- (car pc-select-meta-moves-sexps-key-bindings)
- (cadr pc-select-meta-moves-sexps-key-bindings))
- (if (or pc-select-selection-keys-only
- (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt)))
- nil
- pc-select-tty-key-bindings)))
-
- (pc-select-define-keys pc-select-key-bindings-alist
- (current-global-map))
-
- (unless (or pc-select-selection-keys-only
- (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt)))
- ;; it is not clear that we need the following line
- ;; I hope it doesn't do too much harm to leave it in, though...
- (setq pc-select-old-M-delete-binding
- (lookup-key function-key-map [M-delete]))
- (define-key function-key-map [M-delete] [?\M-d]))
-
- (when (and (not pc-select-selection-keys-only)
- (or (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt)))
- (fboundp 'normal-erase-is-backspace-mode))
- (pc-select-save-and-set-mode normal-erase-is-backspace-mode 1
- normal-erase-is-backspace))
- ;; the original author also had this above:
- ;; (setq-default normal-erase-is-backspace t)
- ;; However, the documentation for the variable says that
- ;; "setting it with setq has no effect", so I'm removing it.
-
- (pc-select-save-and-set-var highlight-nonselected-windows nil)
- (pc-select-save-and-set-var transient-mark-mode t)
- (pc-select-save-and-set-var shift-select-mode t)
- (pc-select-save-and-set-var mark-even-if-inactive t)
- (pc-select-save-and-set-mode delete-selection-mode 1))
- ;;else
- ;; If the user turned on pc-selection-mode a second time
- ;; do not clobber the values of the variables that were
- ;; saved from before pc-selection mode was activated --
- ;; just make sure the values are the way we like them.
- (pc-select-define-keys pc-select-key-bindings-alist
- (current-global-map))
- (unless (or pc-select-selection-keys-only
- (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt)))
- ;; it is not clear that we need the following line
- ;; I hope it doesn't do too much harm to leave it in, though...
- (define-key function-key-map [M-delete] [?\M-d]))
- (when (and (not pc-select-selection-keys-only)
- (or (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt)))
- (fboundp 'normal-erase-is-backspace-mode))
- (normal-erase-is-backspace-mode 1))
- (setq highlight-nonselected-windows nil)
- (transient-mark-mode 1)
- (setq mark-even-if-inactive t)
- (delete-selection-mode 1))
- ;;else
- (when pc-select-key-bindings-alist
- (when (and (not pc-select-selection-keys-only)
- (or (eq window-system 'x)
- (memq system-type '(ms-dos windows-nt))))
- (pc-select-restore-mode normal-erase-is-backspace-mode))
-
- (pc-select-restore-keys
- pc-select-key-bindings-alist (current-global-map)
- pc-select-saved-global-map)
-
- (pc-select-restore-var highlight-nonselected-windows)
- (pc-select-restore-var transient-mark-mode)
- (pc-select-restore-var shift-select-mode)
- (pc-select-restore-var mark-even-if-inactive)
- (pc-select-restore-mode delete-selection-mode)
- (and pc-select-old-M-delete-binding
- (define-key function-key-map [M-delete]
- pc-select-old-M-delete-binding))
- (setq pc-select-key-bindings-alist nil
- pc-select-saved-settings-alist nil))))
-(make-obsolete 'pc-selection-mode 'delete-selection-mode "24.1")
-
-;;; pc-select.el ends here
diff --git a/lisp/obsolete/s-region.el b/lisp/obsolete/s-region.el
deleted file mode 100644
index 9dfc9831f4e..00000000000
--- a/lisp/obsolete/s-region.el
+++ /dev/null
@@ -1,123 +0,0 @@
-;;; s-region.el --- set region using shift key -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1994-1995, 2001-2022 Free Software Foundation, Inc.
-
-;; Author: Morten Welinder <terra@diku.dk>
-;; Keywords: terminals
-;; Favorite-brand-of-beer: None, I hate beer.
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Having loaded this code you can set the region by holding down the
-;; shift key and move the cursor to the other end of the region. The
-;; functionality provided by this code is similar to that provided by
-;; the editors of Borland International's compilers for ms-dos.
-
-;; Currently, s-region-move may be bound only to events that are vectors
-;; of length one and whose last element is a symbol. Also, the functions
-;; that are given this kind of overlay should be (interactive "p")
-;; functions.
-
-;; If the following keys are not already bound then...
-;; C-insert is bound to copy-region-as-kill
-;; S-delete is bound to kill-region
-;; S-insert is bound to yank
-
-;;; Code:
-
-(defvar s-region-overlay (make-overlay 1 1))
-(overlay-put s-region-overlay 'face 'region)
-(overlay-put s-region-overlay 'priority 1000000) ; for hilit19
-
-(defun s-region-unshift (key)
- "Remove shift modifier from last keypress KEY and return that as a key."
- (if (vectorp key)
- (let ((last (aref key (1- (length key)))))
- (if (symbolp last)
- (let* ((keyname (symbol-name last))
- (pos (string-match "S-" keyname)))
- (if pos
- ;; We skip all initial parts of the event assuming that
- ;; those are setting up the prefix argument to the command.
- (vector (intern (concat (substring keyname 0 pos)
- (substring keyname (+ 2 pos)))))
- (error "Non-shifted key: %S" key)))
- (error "Key does not end in a symbol: %S" key)))
- (error "Non-vector key: %S" key)))
-
-(defun s-region-move-p1 (&rest arg)
- "This is an overlay function to point-moving keys that are interactive \"p\"."
- (interactive "p")
- (apply (function s-region-move) arg))
-
-(defun s-region-move-p2 (&rest arg)
- "This is an overlay function to point-moving keys that are interactive \"P\"."
- (interactive "P")
- (apply (function s-region-move) arg))
-
-(defun s-region-move (&rest arg)
- (if (if mark-active (not (equal last-command 's-region-move)) t)
- (set-mark-command nil)
- (message "")) ; delete the "Mark set" message
- (setq this-command 's-region-move)
- (apply (key-binding (s-region-unshift (this-command-keys))) arg)
- (move-overlay s-region-overlay (mark) (point) (current-buffer))
- (sit-for 1)
- (delete-overlay s-region-overlay))
-
-(defun s-region-bind (keylist &optional map)
- "Bind shifted keys in KEYLIST to `s-region-move-p1' or `s-region-move-p2'.
-Each key in KEYLIST is shifted and bound to one of the `s-region-move'
-functions provided it is already bound to some command or other.
-Optional second argument MAP specifies keymap to add binding to, defaulting
-to global keymap."
- (let ((p2 (list 'scroll-up 'scroll-down
- 'beginning-of-buffer 'end-of-buffer)))
- (or map (setq map global-map))
- (while keylist
- (let* ((key (car keylist))
- (binding (key-binding key)))
- (if (commandp binding)
- (define-key
- map
- (vector (intern (concat "S-" (symbol-name (aref key 0)))))
- (cond ((memq binding p2)
- 's-region-move-p2)
- (t 's-region-move-p1)))))
- (setq keylist (cdr keylist)))))
-
-;; Single keys (plus modifiers) only!
-(s-region-bind
- (list [right] [left] [up] [down]
- [C-left] [C-right] [C-up] [C-down]
- [M-left] [M-right] [M-up] [M-down]
- [next] [previous] [home] [end]
- [C-next] [C-previous] [C-home] [C-end]
- [M-next] [M-previous] [M-home] [M-end]))
-
-(or (global-key-binding [C-insert])
- (global-set-key [C-insert] #'copy-region-as-kill))
-(or (global-key-binding [S-delete])
- (global-set-key [S-delete] #'kill-region))
-(or (global-key-binding [S-insert])
- (global-set-key [S-insert] #'yank))
-
-(provide 's-region)
-
-;;; s-region.el ends here
diff --git a/lisp/obsolete/sregex.el b/lisp/obsolete/sregex.el
deleted file mode 100644
index f8722f6129e..00000000000
--- a/lisp/obsolete/sregex.el
+++ /dev/null
@@ -1,605 +0,0 @@
-;;; sregex.el --- symbolic regular expressions -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1997-1998, 2000-2022 Free Software Foundation, Inc.
-
-;; Author: Bob Glickstein <bobg+sregex@zanshin.com>
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: extensions
-;; Obsolete-since: 24.1
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This package allows you to write regular expressions using a
-;; totally new, Lisp-like syntax.
-
-;; A "symbolic regular expression" (sregex for short) is a Lisp form
-;; that, when evaluated, produces the string form of the specified
-;; regular expression. Here's a simple example:
-
-;; (sregexq (or "Bob" "Robert")) => "Bob\\|Robert"
-
-;; As you can see, an sregex is specified by placing one or more
-;; special clauses in a call to `sregexq'. The clause in this case is
-;; the `or' of two strings (not to be confused with the Lisp function
-;; `or'). The list of allowable clauses appears below.
-
-;; With sregex, it is never necessary to "escape" magic characters
-;; that are meant to be taken literally; that happens automatically.
-;; For example:
-
-;; (sregexq "M*A*S*H") => "M\\*A\\*S\\*H"
-
-;; It is also unnecessary to "group" parts of the expression together
-;; to overcome operator precedence; that also happens automatically.
-;; For example:
-
-;; (sregexq (opt (or "Bob" "Robert"))) => "\\(?:Bob\\|Robert\\)?"
-
-;; It *is* possible to group parts of the expression in order to refer
-;; to them with numbered backreferences:
-
-;; (sregexq (group (or "Go" "Run"))
-;; ", Spot, "
-;; (backref 1)) => "\\(Go\\|Run\\), Spot, \\1"
-
-;; `sregexq' is a macro. Each time it is used, it constructs a simple
-;; Lisp expression that then invokes a moderately complex engine to
-;; interpret the sregex and render the string form. Because of this,
-;; I don't recommend sprinkling calls to `sregexq' throughout your
-;; code, the way one normally does with string regexes (which are
-;; cheap to evaluate). Instead, it's wiser to precompute the regexes
-;; you need wherever possible instead of repeatedly constructing the
-;; same ones over and over. Example:
-
-;; (let ((field-regex (sregexq (opt "resent-")
-;; (or "to" "cc" "bcc"))))
-;; ...
-;; (while ...
-;; ...
-;; (re-search-forward field-regex ...)
-;; ...))
-
-;; The arguments to `sregexq' are automatically quoted, but the
-;; flipside of this is that it is not straightforward to include
-;; computed (i.e., non-constant) values in `sregexq' expressions. So
-;; `sregex' is a function that is like `sregexq' but which does not
-;; automatically quote its values. Literal sregex clauses must be
-;; explicitly quoted like so:
-
-;; (sregex '(or "Bob" "Robert")) => "Bob\\|Robert"
-
-;; but computed clauses can be included easily, allowing for the reuse
-;; of common clauses:
-
-;; (let ((dotstar '(0+ any))
-;; (whitespace '(1+ (syntax ?-)))
-;; (digits '(1+ (char (?0 . ?9)))))
-;; (sregex 'bol dotstar ":" whitespace digits)) => "^.*:\\s-+[0-9]+"
-
-;; To use this package in a Lisp program, simply (require 'sregex).
-
-;; Here are the clauses allowed in an `sregex' or `sregexq'
-;; expression:
-
-;; - a string
-;; This stands for the literal string. If it contains
-;; metacharacters, they will be escaped in the resulting regex
-;; (using `regexp-quote').
-
-;; - the symbol `any'
-;; This stands for ".", a regex matching any character except
-;; newline.
-
-;; - the symbol `bol'
-;; Stands for "^", matching the empty string at the beginning of a line
-
-;; - the symbol `eol'
-;; Stands for "$", matching the empty string at the end of a line
-
-;; - (group CLAUSE ...)
-;; Groups the given CLAUSEs using "\\(" and "\\)".
-
-;; - (sequence CLAUSE ...)
-
-;; Groups the given CLAUSEs; may or may not use "\\(?:" and "\\)".
-;; Clauses grouped by `sequence' do not count for purposes of
-;; numbering backreferences. Use `sequence' in situations like
-;; this:
-
-;; (sregexq (or "dog" "cat"
-;; (sequence (opt "sea ") "monkey")))
-;; => "dog\\|cat\\|\\(?:sea \\)?monkey"
-
-;; where a single `or' alternate needs to contain multiple
-;; subclauses.
-
-;; - (backref N)
-;; Matches the same string previously matched by the Nth "group" in
-;; the same sregex. N is a positive integer.
-
-;; - (or CLAUSE ...)
-;; Matches any one of the CLAUSEs by separating them with "\\|".
-
-;; - (0+ CLAUSE ...)
-;; Concatenates the given CLAUSEs and matches zero or more
-;; occurrences by appending "*".
-
-;; - (1+ CLAUSE ...)
-;; Concatenates the given CLAUSEs and matches one or more
-;; occurrences by appending "+".
-
-;; - (opt CLAUSE ...)
-;; Concatenates the given CLAUSEs and matches zero or one occurrence
-;; by appending "?".
-
-;; - (repeat MIN MAX CLAUSE ...)
-;; Concatenates the given CLAUSEs and constructs a regex matching at
-;; least MIN occurrences and at most MAX occurrences. MIN must be a
-;; non-negative integer. MAX must be a non-negative integer greater
-;; than or equal to MIN; or MAX can be nil to mean "infinity."
-
-;; - (char CHAR-CLAUSE ...)
-;; Creates a "character class" matching one character from the given
-;; set. See below for how to construct a CHAR-CLAUSE.
-
-;; - (not-char CHAR-CLAUSE ...)
-;; Creates a "character class" matching any one character not in the
-;; given set. See below for how to construct a CHAR-CLAUSE.
-
-;; - the symbol `bot'
-;; Stands for "\\`", matching the empty string at the beginning of
-;; text (beginning of a string or of a buffer).
-
-;; - the symbol `eot'
-;; Stands for "\\'", matching the empty string at the end of text.
-
-;; - the symbol `point'
-;; Stands for "\\=", matching the empty string at point.
-
-;; - the symbol `word-boundary'
-;; Stands for "\\b", matching the empty string at the beginning or
-;; end of a word.
-
-;; - the symbol `not-word-boundary'
-;; Stands for "\\B", matching the empty string not at the beginning
-;; or end of a word.
-
-;; - the symbol `bow'
-;; Stands for "\\<", matching the empty string at the beginning of a
-;; word.
-
-;; - the symbol `eow'
-;; Stands for "\\>", matching the empty string at the end of a word.
-
-;; - the symbol `wordchar'
-;; Stands for the regex "\\w", matching a word-constituent character
-;; (as determined by the current syntax table)
-
-;; - the symbol `not-wordchar'
-;; Stands for the regex "\\W", matching a non-word-constituent
-;; character.
-
-;; - (syntax CODE)
-;; Stands for the regex "\\sCODE", where CODE is a syntax table code
-;; (a single character). Matches any character with the requested
-;; syntax.
-
-;; - (not-syntax CODE)
-;; Stands for the regex "\\SCODE", where CODE is a syntax table code
-;; (a single character). Matches any character without the
-;; requested syntax.
-
-;; - (regex REGEX)
-;; This is a "trapdoor" for including ordinary regular expression
-;; strings in the result. Some regular expressions are clearer when
-;; written the old way: "[a-z]" vs. (sregexq (char (?a . ?z))), for
-;; instance.
-
-;; Each CHAR-CLAUSE that is passed to (char ...) and (not-char ...)
-;; has one of the following forms:
-
-;; - a character
-;; Adds that character to the set.
-
-;; - a string
-;; Adds all the characters in the string to the set.
-
-;; - A pair (MIN . MAX)
-;; Where MIN and MAX are characters, adds the range of characters
-;; from MIN through MAX to the set.
-
-;;; To do:
-
-;; An earlier version of this package could optionally translate the
-;; symbolic regex into other languages' syntaxes, e.g. Perl. For
-;; instance, with Perl syntax selected, (sregexq (or "ab" "cd")) would
-;; yield "ab|cd" instead of "ab\\|cd". It might be useful to restore
-;; such a facility.
-
-;; - handle multibyte chars in sregex--char-aux
-;; - add support for character classes ([:blank:], ...)
-;; - add support for non-greedy operators *? and +?
-;; - bug: (sregexq (opt (opt ?a))) returns "a??" which is a non-greedy "a?"
-
-;;; Code:
-
-(eval-when-compile (require 'cl-lib))
-
-;; Compatibility code for when we didn't have shy-groups
-(defvar sregex--current-sregex nil)
-(defun sregex-info () nil)
-(defmacro sregex-save-match-data (&rest forms) (cons 'save-match-data forms))
-(defun sregex-replace-match (r &optional f l str subexp _x)
- (replace-match r f l str subexp))
-(defun sregex-match-string (c &optional i _x) (match-string c i))
-(defun sregex-match-string-no-properties (count &optional in-string _sregex)
- (match-string-no-properties count in-string))
-(defun sregex-match-beginning (count &optional _sregex) (match-beginning count))
-(defun sregex-match-end (count &optional _sregex) (match-end count))
-(defun sregex-match-data (&optional _sregex) (match-data))
-(defun sregex-backref-num (n &optional _sregex) n)
-
-
-(defun sregex (&rest exps)
- "Symbolic regular expression interpreter.
-This is exactly like `sregexq' (q.v.) except that it evaluates all its
-arguments, so literal sregex clauses must be quoted. For example:
-
- (sregex \\='(or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\"
-
-An argument-evaluating sregex interpreter lets you reuse sregex
-subexpressions:
-
- (let ((dotstar \\='(0+ any))
- (whitespace \\='(1+ (syntax ?-)))
- (digits \\='(1+ (char (?0 . ?9)))))
- (sregex \\='bol dotstar \":\" whitespace digits)) => \"^.*:\\\\s-+[0-9]+\""
- (sregex--sequence exps nil))
-
-(defmacro sregexq (&rest exps)
- "Symbolic regular expression interpreter.
-This macro allows you to specify a regular expression (regexp) in
-symbolic form, and converts it into the string form required by Emacs's
-regex functions such as `re-search-forward' and `looking-at'. Here is
-a simple example:
-
- (sregexq (or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\"
-
-As you can see, an sregex is specified by placing one or more special
-clauses in a call to `sregexq'. The clause in this case is the `or'
-of two strings (not to be confused with the Lisp function `or'). The
-list of allowable clauses appears below.
-
-With `sregex', it is never necessary to \"escape\" magic characters
-that are meant to be taken literally; that happens automatically.
-For example:
-
- (sregexq \"M*A*S*H\") => \"M\\\\*A\\\\*S\\\\*H\"
-
-It is also unnecessary to \"group\" parts of the expression together
-to overcome operator precedence; that also happens automatically.
-For example:
-
- (sregexq (opt (or \"Bob\" \"Robert\"))) => \"\\\\(Bob\\\\|Robert\\\\)?\"
-
-It *is* possible to group parts of the expression in order to refer
-to them with numbered backreferences:
-
- (sregexq (group (or \"Go\" \"Run\"))
- \", Spot, \"
- (backref 1)) => \"\\\\(Go\\\\|Run\\\\), Spot, \\\\1\"
-
-If `sregexq' needs to introduce its own grouping parentheses, it will
-automatically renumber your backreferences:
-
- (sregexq (opt \"resent-\")
- (group (or \"to\" \"cc\" \"bcc\"))
- \": \"
- (backref 1)) => \"\\\\(resent-\\\\)?\\\\(to\\\\|cc\\\\|bcc\\\\): \\\\2\"
-
-`sregexq' is a macro. Each time it is used, it constructs a simple
-Lisp expression that then invokes a moderately complex engine to
-interpret the sregex and render the string form. Because of this, I
-don't recommend sprinkling calls to `sregexq' throughout your code,
-the way one normally does with string regexes (which are cheap to
-evaluate). Instead, it's wiser to precompute the regexes you need
-wherever possible instead of repeatedly constructing the same ones
-over and over. Example:
-
- (let ((field-regex (sregexq (opt \"resent-\")
- (or \"to\" \"cc\" \"bcc\"))))
- ...
- (while ...
- ...
- (re-search-forward field-regex ...)
- ...))
-
-The arguments to `sregexq' are automatically quoted, but the
-flipside of this is that it is not straightforward to include
-computed (i.e., non-constant) values in `sregexq' expressions. So
-`sregex' is a function that is like `sregexq' but which does not
-automatically quote its values. Literal sregex clauses must be
-explicitly quoted like so:
-
- (sregex \\='(or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\"
-
-but computed clauses can be included easily, allowing for the reuse
-of common clauses:
-
- (let ((dotstar \\='(0+ any))
- (whitespace \\='(1+ (syntax ?-)))
- (digits \\='(1+ (char (?0 . ?9)))))
- (sregex \\='bol dotstar \":\" whitespace digits)) => \"^.*:\\\\s-+[0-9]+\"
-
-Here are the clauses allowed in an `sregex' or `sregexq' expression:
-
-- a string
- This stands for the literal string. If it contains
- metacharacters, they will be escaped in the resulting regex
- (using `regexp-quote').
-
-- the symbol `any'
- This stands for \".\", a regex matching any character except
- newline.
-
-- the symbol `bol'
- Stands for \"^\", matching the empty string at the beginning of a line
-
-- the symbol `eol'
- Stands for \"$\", matching the empty string at the end of a line
-
-- (group CLAUSE ...)
- Groups the given CLAUSEs using \"\\\\(\" and \"\\\\)\".
-
-- (sequence CLAUSE ...)
-
- Groups the given CLAUSEs; may or may not use \"\\\\(\" and \"\\\\)\".
- Clauses grouped by `sequence' do not count for purposes of
- numbering backreferences. Use `sequence' in situations like
- this:
-
- (sregexq (or \"dog\" \"cat\"
- (sequence (opt \"sea \") \"monkey\")))
- => \"dog\\\\|cat\\\\|\\\\(?:sea \\\\)?monkey\"
-
- where a single `or' alternate needs to contain multiple
- subclauses.
-
-- (backref N)
- Matches the same string previously matched by the Nth \"group\" in
- the same sregex. N is a positive integer.
-
-- (or CLAUSE ...)
- Matches any one of the CLAUSEs by separating them with \"\\\\|\".
-
-- (0+ CLAUSE ...)
- Concatenates the given CLAUSEs and matches zero or more
- occurrences by appending \"*\".
-
-- (1+ CLAUSE ...)
- Concatenates the given CLAUSEs and matches one or more
- occurrences by appending \"+\".
-
-- (opt CLAUSE ...)
- Concatenates the given CLAUSEs and matches zero or one occurrence
- by appending \"?\".
-
-- (repeat MIN MAX CLAUSE ...)
- Concatenates the given CLAUSEs and constructs a regex matching at
- least MIN occurrences and at most MAX occurrences. MIN must be a
- non-negative integer. MAX must be a non-negative integer greater
- than or equal to MIN; or MAX can be nil to mean \"infinity.\"
-
-- (char CHAR-CLAUSE ...)
- Creates a \"character class\" matching one character from the given
- set. See below for how to construct a CHAR-CLAUSE.
-
-- (not-char CHAR-CLAUSE ...)
- Creates a \"character class\" matching any one character not in the
- given set. See below for how to construct a CHAR-CLAUSE.
-
-- the symbol `bot'
- Stands for \"\\\\\\=`\", matching the empty string at the beginning of
- text (beginning of a string or of a buffer).
-
-- the symbol `eot'
- Stands for \"\\\\'\", matching the empty string at the end of text.
-
-- the symbol `point'
- Stands for \"\\\\=\\=\", matching the empty string at point.
-
-- the symbol `word-boundary'
- Stands for \"\\\\b\", matching the empty string at the beginning or
- end of a word.
-
-- the symbol `not-word-boundary'
- Stands for \"\\\\B\", matching the empty string not at the beginning
- or end of a word.
-
-- the symbol `bow'
- Stands for \"\\\\=\\<\", matching the empty string at the beginning of a
- word.
-
-- the symbol `eow'
- Stands for \"\\\\=\\>\", matching the empty string at the end of a word.
-
-- the symbol `wordchar'
- Stands for the regex \"\\\\w\", matching a word-constituent character
- (as determined by the current syntax table)
-
-- the symbol `not-wordchar'
- Stands for the regex \"\\\\W\", matching a non-word-constituent
- character.
-
-- (syntax CODE)
- Stands for the regex \"\\\\sCODE\", where CODE is a syntax table code
- (a single character). Matches any character with the requested
- syntax.
-
-- (not-syntax CODE)
- Stands for the regex \"\\\\SCODE\", where CODE is a syntax table code
- (a single character). Matches any character without the
- requested syntax.
-
-- (regex REGEX)
- This is a \"trapdoor\" for including ordinary regular expression
- strings in the result. Some regular expressions are clearer when
- written the old way: \"[a-z]\" vs. (sregexq (char (?a . ?z))), for
- instance.
-
-Each CHAR-CLAUSE that is passed to (char ...) and (not-char ...)
-has one of the following forms:
-
-- a character
- Adds that character to the set.
-
-- a string
- Adds all the characters in the string to the set.
-
-- A pair (MIN . MAX)
- Where MIN and MAX are characters, adds the range of characters
- from MIN through MAX to the set."
- `(apply 'sregex ',exps))
-
-(defun sregex--engine (exp combine)
- (cond
- ((stringp exp)
- (if (and combine
- (eq combine 'suffix)
- (/= (length exp) 1))
- (concat "\\(?:" (regexp-quote exp) "\\)")
- (regexp-quote exp)))
- ((symbolp exp)
- (cl-ecase exp
- (any ".")
- (bol "^")
- (eol "$")
- (wordchar "\\w")
- (not-wordchar "\\W")
- (bot "\\`")
- (eot "\\'")
- (point "\\=")
- (word-boundary "\\b")
- (not-word-boundary "\\B")
- (bow "\\<")
- (eow "\\>")))
- ((consp exp)
- (funcall (intern (concat "sregex--"
- (symbol-name (car exp))))
- (cdr exp)
- combine))
- (t (error "Invalid expression: %s" exp))))
-
-(defun sregex--sequence (exps combine)
- (if (= (length exps) 1) (sregex--engine (car exps) combine)
- (let ((re (mapconcat
- (lambda (e) (sregex--engine e 'concat))
- exps "")))
- (if (eq combine 'suffix)
- (concat "\\(?:" re "\\)")
- re))))
-
-(defun sregex--or (exps combine)
- (if (= (length exps) 1) (sregex--engine (car exps) combine)
- (let ((re (mapconcat
- (lambda (e) (sregex--engine e 'or))
- exps "\\|")))
- (if (not (eq combine 'or))
- (concat "\\(?:" re "\\)")
- re))))
-
-(defun sregex--group (exps _combine) (concat "\\(" (sregex--sequence exps nil) "\\)"))
-
-(defun sregex--backref (exps _combine) (concat "\\" (int-to-string (car exps))))
-(defun sregex--opt (exps _combine) (concat (sregex--sequence exps 'suffix) "?"))
-(defun sregex--0+ (exps _combine) (concat (sregex--sequence exps 'suffix) "*"))
-(defun sregex--1+ (exps _combine) (concat (sregex--sequence exps 'suffix) "+"))
-
-(defun sregex--char (exps _combine) (sregex--char-aux nil exps))
-(defun sregex--not-char (exps _combine) (sregex--char-aux t exps))
-
-(defun sregex--syntax (exps _combine) (format "\\s%c" (car exps)))
-(defun sregex--not-syntax (exps _combine) (format "\\S%c" (car exps)))
-
-(defun sregex--regex (exps combine)
- (if combine (concat "\\(?:" (car exps) "\\)") (car exps)))
-
-(defun sregex--repeat (exps _combine)
- (let* ((min (or (pop exps) 0))
- (minstr (number-to-string min))
- (max (pop exps)))
- (concat (sregex--sequence exps 'suffix)
- (concat "\\{" minstr ","
- (when max (number-to-string max)) "\\}"))))
-
-(defun sregex--char-range (start end)
- (let ((startc (char-to-string start))
- (endc (char-to-string end)))
- (cond
- ((> end (+ start 2)) (concat startc "-" endc))
- ((> end (+ start 1)) (concat startc (char-to-string (1+ start)) endc))
- ((> end start) (concat startc endc))
- (t startc))))
-
-(defun sregex--char-aux (complement args)
- ;; regex-opt does the same, we should join effort.
- (let ((chars (make-bool-vector 256 nil))) ; Yeah, right!
- (dolist (arg args)
- (cond ((integerp arg) (aset chars arg t))
- ((stringp arg) (mapc (lambda (c) (aset chars c t)) arg))
- ((consp arg)
- (let ((start (car arg))
- (end (cdr arg)))
- (when (> start end)
- (let ((tmp start)) (setq start end) (setq end tmp)))
- ;; now start <= end
- (let ((i start))
- (while (<= i end)
- (aset chars i t)
- (setq i (1+ i))))))))
- ;; now chars is a map of the characters in the class
- (let ((caret (aref chars ?^))
- (dash (aref chars ?-))
- (class (if (aref chars ?\]) "]" "")))
- (aset chars ?^ nil)
- (aset chars ?- nil)
- (aset chars ?\] nil)
-
- (let (start end)
- (dotimes (i 256)
- (if (aref chars i)
- (progn
- (unless start (setq start i))
- (setq end i)
- (aset chars i nil))
- (when start
- (setq class (concat class (sregex--char-range start end)))
- (setq start nil))))
- (if start
- (setq class (concat class (sregex--char-range start end)))))
-
- (if (> (length class) 0)
- (setq class (concat class (if caret "^") (if dash "-")))
- (setq class (concat class (if dash "-") (if caret "^"))))
- (if (and (not complement) (= (length class) 1))
- (regexp-quote class)
- (concat "[" (if complement "^") class "]")))))
-
-(provide 'sregex)
-
-;;; sregex.el ends here
diff --git a/lisp/obsolete/starttls.el b/lisp/obsolete/starttls.el
index 6f0685d3dda..2f1f0e9773c 100644
--- a/lisp/obsolete/starttls.el
+++ b/lisp/obsolete/starttls.el
@@ -287,9 +287,6 @@ GnuTLS requires a port number."
starttls-gnutls-program
starttls-program))))
-(define-obsolete-function-alias 'starttls-any-program-available
- #'starttls-available-p "24.1")
-
(provide 'starttls)
;;; starttls.el ends here
diff --git a/lisp/mail/uce.el b/lisp/obsolete/uce.el
index 2672cfca1fb..2cbbf5dc65d 100644
--- a/lisp/mail/uce.el
+++ b/lisp/obsolete/uce.el
@@ -5,6 +5,7 @@
;; Author: stanislav shalunov <shalunov@mccme.ru>
;; Created: 10 Dec 1996
;; Keywords: mail, uce, unsolicited commercial email
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
diff --git a/lisp/vc/vc-mtn.el b/lisp/obsolete/vc-mtn.el
index 20fbf92bb12..cd56b290072 100644
--- a/lisp/vc/vc-mtn.el
+++ b/lisp/obsolete/vc-mtn.el
@@ -5,6 +5,7 @@
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: vc
;; Package: vc
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
diff --git a/lisp/vt-control.el b/lisp/obsolete/vt-control.el
index b80d3505b30..190ccbaa83c 100644
--- a/lisp/vt-control.el
+++ b/lisp/obsolete/vt-control.el
@@ -4,6 +4,7 @@
;; Author: Rob Riepel <riepel@networking.stanford.edu>
;; Keywords: terminals
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
diff --git a/lisp/vt100-led.el b/lisp/obsolete/vt100-led.el
index a6a256a6a74..d741a112aa7 100644
--- a/lisp/vt100-led.el
+++ b/lisp/obsolete/vt100-led.el
@@ -5,6 +5,7 @@
;; Author: Howard Gayle
;; Maintainer: emacs-devel@gnu.org
;; Keywords: hardware
+;; Obsolete-since: 29.1
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el
index 427aba34150..c99d6a8ba71 100644
--- a/lisp/org/ob-comint.el
+++ b/lisp/org/ob-comint.el
@@ -166,7 +166,7 @@ source block, and the name of the temp file.")
(defvar-local org-babel-comint-async-chunk-callback nil
"Callback function to clean Babel async output results before insertion.
Its single argument is a string consisting of output from the
-comint process. It should return a string that will be be passed
+comint process. It should return a string that will be passed
to `org-babel-insert-result'.")
(defvar-local org-babel-comint-async-dangling nil
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 23ef162a7f3..04af84d2e44 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -480,7 +480,7 @@ value. The value can either be a string or a closure that
evaluates to a string. The closure is evaluated when the source
block is being evaluated (e.g. during execution or export), with
point at the source block. It is not possible to use an
-arbitrary function symbol (e.g. 'some-func), since org uses
+arbitrary function symbol (e.g. `some-func'), since org uses
lexical binding. To achieve the same functionality, call the
function within a closure (e.g. (lambda () (some-func))).
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/ob-julia.el b/lisp/org/ob-julia.el
index abddca36134..50a44bcf448 100644
--- a/lisp/org/ob-julia.el
+++ b/lisp/org/ob-julia.el
@@ -250,8 +250,8 @@ end")
(defun org-babel-julia-evaluate-external-process
(body result-type result-params column-names-p)
"Evaluate BODY in external julia process.
-If RESULT-TYPE equals 'output then return standard output as a
-string. If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
(cl-case result-type
(value
@@ -274,8 +274,8 @@ last statement in BODY, as elisp."
(defun org-babel-julia-evaluate-session
(session body result-type result-params column-names-p)
"Evaluate BODY in SESSION.
-If RESULT-TYPE equals 'output then return standard output as a
-string. If RESULT-TYPE equals 'value then return the value of the
+If RESULT-TYPE equals `output' then return standard output as a
+string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
(cl-case result-type
(value
diff --git a/lisp/org/ob-lua.el b/lisp/org/ob-lua.el
index 48de0dbad06..b6e78fb7fd8 100644
--- a/lisp/org/ob-lua.el
+++ b/lisp/org/ob-lua.el
@@ -395,7 +395,7 @@ fd:close()"
(org-babel-lua-table-or-string results)))))
(defun org-babel-lua-read-string (string)
- "Strip 's from around Lua string."
+ "Strip \\=' characters from around Lua string."
(org-unbracket-string "'" "'" string))
(provide 'ob-lua)
diff --git a/lisp/org/ob-table.el b/lisp/org/ob-table.el
index 2f092998d8b..f6729e0ece7 100644
--- a/lisp/org/ob-table.el
+++ b/lisp/org/ob-table.el
@@ -84,7 +84,7 @@ is the equivalent of the following source code block:
#+end_src
NOTE: The quotation marks around the function name,
-'source-block', are optional.
+`source-block', are optional.
NOTE: By default, string variable names are interpreted as
references to source-code blocks, to force interpretation of a
diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el
index cf307aa0cb3..566258eba4a 100644
--- a/lisp/org/ob-tangle.el
+++ b/lisp/org/ob-tangle.el
@@ -43,7 +43,7 @@
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance))
(declare-function outline-previous-heading "outline" ())
-(defvar org-id-link-to-org-use-id nil) ; Dynamically scoped
+(defvar org-id-link-to-org-use-id) ; Dynamically scoped
(defcustom org-babel-tangle-lang-exts
'(("emacs-lisp" . "el")
diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el
index d82406affb2..9ed1b810fab 100644
--- a/lisp/org/oc-basic.el
+++ b/lisp/org/oc-basic.el
@@ -178,21 +178,36 @@ Return a hash table with citation references as keys and fields alist as values.
" and ")))
('issued
;; Date are expressed as an array
- ;; (`date-parts') or a "string (`raw').
- ;; In both cases, extract the year and
- ;; associate it to `year' field, for
- ;; compatibility with BibTeX format.
+ ;; (`date-parts') or a "string (`raw'
+ ;; or `literal'). In both cases,
+ ;; extract the year and associate it
+ ;; to `year' field, for compatibility
+ ;; with BibTeX format.
(let ((date (or (alist-get 'date-parts value)
+ (alist-get 'literal value)
(alist-get 'raw value))))
(cons 'year
(cond
((consp date)
- (caar date))
+ (let ((year (caar date)))
+ (cond
+ ((numberp year) (number-to-string year))
+ ((stringp year) year)
+ (t
+ (error
+ "First element of CSL-JSON date-parts should be a number or string, got %s: %S"
+ (type-of year) year)))))
((stringp date)
- (car (split-string date "-")))
+ (replace-regexp-in-string
+ (rx
+ (minimal-match (zero-or-more anything))
+ (group-n 1 (repeat 4 digit))
+ (zero-or-more anything))
+ (rx (backref 1))
+ date))
(t
(error "Unknown CSL-JSON date format: %S"
- date))))))
+ value))))))
(_
(cons field value))))
item)
@@ -225,6 +240,8 @@ Return a hash table with citation references as keys and fields alist as values.
entries)))
entries))
+(defvar org-cite-basic--file-id-cache nil
+ "Hash table linking files to their hash.")
(defun org-cite-basic--parse-bibliography (&optional info)
"List all entries available in the buffer.
@@ -237,14 +254,19 @@ table where keys are references and values are association lists between fields,
as symbols, and values as strings or nil.
Optional argument INFO is the export state, as a property list."
+ (unless (hash-table-p org-cite-basic--file-id-cache)
+ (setq org-cite-basic--file-id-cache (make-hash-table :test #'equal)))
(if (plist-member info :cite-basic/bibliography)
(plist-get info :cite-basic/bibliography)
(let ((results nil))
(dolist (file (org-cite-list-bibliography-files))
(when (file-readable-p file)
(with-temp-buffer
- (insert-file-contents file)
- (let* ((file-id (cons file (org-buffer-hash)))
+ (when (or (org-file-has-changed-p file)
+ (not (gethash file org-cite-basic--file-id-cache)))
+ (insert-file-contents file)
+ (puthash file (org-buffer-hash) org-cite-basic--file-id-cache))
+ (let* ((file-id (cons file (gethash file org-cite-basic--file-id-cache)))
(entries
(or (cdr (assoc file-id org-cite-basic--bibliography-cache))
(let ((table
@@ -719,19 +741,24 @@ Return nil if there are no bibliography files or no entries."
(t
(clrhash org-cite-basic--completion-cache)
(dolist (key (org-cite-basic--all-keys))
- (let ((completion
- (concat
- (let ((author (org-cite-basic--get-field 'author key nil t)))
- (if author
- (truncate-string-to-width
- (replace-regexp-in-string " and " "; " author)
- org-cite-basic-author-column-end nil ?\s)
- (make-string org-cite-basic-author-column-end ?\s)))
- org-cite-basic-column-separator
- (let ((date (org-cite-basic--get-year key nil 'no-suffix)))
- (format "%4s" (or date "")))
- org-cite-basic-column-separator
- (org-cite-basic--get-field 'title key nil t))))
+ (let* ((entry (org-cite-basic--get-entry
+ key
+ ;; Supply pre-calculated bibliography to avoid
+ ;; performance degradation.
+ (list :cite-basic/bibliography entries)))
+ (completion
+ (concat
+ (let ((author (org-cite-basic--get-field 'author entry nil 'raw)))
+ (if author
+ (truncate-string-to-width
+ (replace-regexp-in-string " and " "; " author)
+ org-cite-basic-author-column-end nil ?\s)
+ (make-string org-cite-basic-author-column-end ?\s)))
+ org-cite-basic-column-separator
+ (let ((date (org-cite-basic--get-year entry nil 'no-suffix)))
+ (format "%4s" (or date "")))
+ org-cite-basic-column-separator
+ (org-cite-basic--get-field 'title entry nil t))))
(puthash completion key org-cite-basic--completion-cache)))
(unless (map-empty-p org-cite-basic--completion-cache) ;no key
(puthash entries t org-cite-basic--completion-cache)
diff --git a/lisp/org/oc-biblatex.el b/lisp/org/oc-biblatex.el
index 3cc157ec937..174725b4244 100644
--- a/lisp/org/oc-biblatex.el
+++ b/lisp/org/oc-biblatex.el
@@ -164,12 +164,7 @@ INFO is the export state, as a property list."
(mapconcat (lambda (r)
(org-cite-biblatex--atomic-arguments (list r) info))
(org-cite-get-references citation)
- "")
- ;; According to BibLaTeX manual, left braces or brackets
- ;; following a multicite command could be parsed as other
- ;; arguments. So we stop any further parsing by inserting
- ;; a \relax unconditionally.
- "\\relax")))
+ ""))))
(defun org-cite-biblatex--command (citation info base &optional multi no-opt)
"Return biblatex command using BASE name for CITATION object.
diff --git a/lisp/org/oc.el b/lisp/org/oc.el
index eb5f519cb64..c4cd0268c7c 100644
--- a/lisp/org/oc.el
+++ b/lisp/org/oc.el
@@ -808,6 +808,8 @@ INFO is the export communication channel, as a property list."
(or (plist-get info :citations)
(letrec ((cites nil)
(tree (plist-get info :parse-tree))
+ (definition-cache (make-hash-table :test #'equal))
+ (definition-list nil)
(find-definition
;; Find definition for standard reference LABEL. At
;; this point, it is impossible to rely on
@@ -816,11 +818,21 @@ INFO is the export communication channel, as a property list."
;; un-processed citation objects. So we use
;; a simplified version of the function above.
(lambda (label)
- (org-element-map tree 'footnote-definition
- (lambda (d)
- (and (equal label (org-element-property :label d))
- (or (org-element-contents d) "")))
- info t)))
+ (or (gethash label definition-cache)
+ (org-element-map
+ (or definition-list
+ (setq definition-list
+ (org-element-map
+ tree
+ 'footnote-definition
+ #'identity info)))
+ 'footnote-definition
+ (lambda (d)
+ (and (equal label (org-element-property :label d))
+ (puthash label
+ (or (org-element-contents d) "")
+ definition-cache)))
+ info t))))
(search-cites
(lambda (data)
(org-element-map data '(citation footnote-reference)
@@ -834,7 +846,8 @@ INFO is the export communication channel, as a property list."
(_
(let ((label (org-element-property :label datum)))
(funcall search-cites
- (funcall find-definition label))))))
+ (funcall find-definition label)))))
+ nil)
info nil 'footnote-definition t))))
(funcall search-cites tree)
(let ((result (nreverse cites)))
diff --git a/lisp/org/ol-bibtex.el b/lisp/org/ol-bibtex.el
index 41443d79595..81b99167b8e 100644
--- a/lisp/org/ol-bibtex.el
+++ b/lisp/org/ol-bibtex.el
@@ -115,7 +115,7 @@
(defvar org-agenda-overriding-header)
(defvar org-agenda-search-view-always-boolean)
-(defvar org-bibtex-description nil) ; dynamically scoped from org.el
+(defvar org-bibtex-description nil)
(defvar org-id-locations)
(defvar org-property-end-re)
(defvar org-special-properties)
@@ -655,7 +655,8 @@ With a prefix arg, query for optional fields."
(defun org-bibtex-read ()
"Read a bibtex entry and save to `org-bibtex-entries'.
-This uses `bibtex-parse-entry'."
+This uses `bibtex-parse-entry'.
+Return the new value of `org-bibtex-entries'."
(interactive)
(let ((keyword (lambda (str) (intern (concat ":" (downcase str)))))
(clean-space (lambda (str) (replace-regexp-in-string
@@ -678,7 +679,8 @@ This uses `bibtex-parse-entry'."
(funcall clean-space (funcall strip-delim (cdr pair)))))
(save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry)))
org-bibtex-entries)
- (unless (car org-bibtex-entries) (pop org-bibtex-entries))))
+ (unless (car org-bibtex-entries) (pop org-bibtex-entries))
+ org-bibtex-entries))
(defun org-bibtex-read-buffer (buffer)
"Read all bibtex entries in BUFFER and save to `org-bibtex-entries'.
diff --git a/lisp/org/ol-doi.el b/lisp/org/ol-doi.el
index 94585e4c3e5..56239f65d43 100644
--- a/lisp/org/ol-doi.el
+++ b/lisp/org/ol-doi.el
@@ -44,7 +44,7 @@ PATH is a the path to search for, as a string."
"Export a \"doi\" type link.
PATH is the DOI name. DESC is the description of the link, or
nil. BACKEND is a symbol representing the backend used for
-export. INFO is a a plist containing the export parameters."
+export. INFO is a plist containing the export parameters."
(let ((uri (concat org-link-doi-server-url path)))
(pcase backend
(`html
diff --git a/lisp/org/ol-eww.el b/lisp/org/ol-eww.el
index 69bf1ba62dd..d1bb5195107 100644
--- a/lisp/org/ol-eww.el
+++ b/lisp/org/ol-eww.el
@@ -115,7 +115,7 @@ keep the structure of the Org file."
(setq transform-start (region-beginning))
(setq transform-end (region-end))
;; Deactivate mark if current mark is activate.
- (when (fboundp 'deactivate-mark) (deactivate-mark)))
+ (deactivate-mark))
(message "Transforming links...")
(save-excursion
(goto-char transform-start)
diff --git a/lisp/org/ol-w3m.el b/lisp/org/ol-w3m.el
index 517329889c6..80d6811a5c5 100644
--- a/lisp/org/ol-w3m.el
+++ b/lisp/org/ol-w3m.el
@@ -72,7 +72,7 @@ so that it can be yanked into an Org buffer with links working correctly."
(setq transform-start (region-beginning))
(setq transform-end (region-end))
;; Deactivate mark if current mark is activate.
- (when (fboundp 'deactivate-mark) (deactivate-mark)))
+ (deactivate-mark))
(message "Transforming links...")
(save-excursion
(goto-char transform-start)
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index 2951c3def1e..a0dad926bc2 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -183,7 +183,7 @@ link.
(defcustom org-link-descriptive t
"Non-nil means Org displays descriptive links.
-E.g. [[https://orgmode.org][Org website]] is be displayed as
+E.g. [[https://orgmode.org][Org website]] is displayed as
\"Org Website\", hiding the link itself and just displaying its
description. When set to nil, Org displays the full links
literally.
@@ -1575,19 +1575,11 @@ non-nil."
(setq link
(format-time-string
(car org-time-stamp-formats)
- (encode-time
+ (apply 'encode-time
(list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
nil nil nil))))
(org-link-store-props :type "calendar" :date cd)))
- ((eq major-mode 'w3-mode)
- (setq cpltxt (if (and (buffer-name)
- (not (string-match "Untitled" (buffer-name))))
- (buffer-name)
- (url-view-url t))
- link (url-view-url t))
- (org-link-store-props :type "w3" :url (url-view-url t)))
-
((eq major-mode 'image-mode)
(setq cpltxt (concat "file:"
(abbreviate-file-name buffer-file-name))
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index fed36ac9b63..a43b083d536 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)
@@ -97,8 +99,8 @@
;; Defined somewhere in this file, but used before definition.
(defvar org-agenda-buffer-name "*Org Agenda*")
-(defvar org-agenda-overriding-header nil)
(defvar org-agenda-title-append nil)
+(defvar org-agenda-overriding-header)
;; (with-no-warnings (defvar entry)) ;; unprefixed, from calendar.el
;; (with-no-warnings (defvar date)) ;; unprefixed, from calendar.el
(defvar original-date) ; dynamically scoped, calendar.el does scope this
@@ -1613,7 +1615,7 @@ alpha-down Sort headlines alphabetically, reversed.
The different possibilities will be tried in sequence, and testing stops
if one comparison returns a \"not-equal\". For example, the default
- '(time-up category-keep priority-down)
+ `(time-up category-keep priority-down)'
means: Pull out all entries having a specified time of day and sort them,
in order to make a time schedule for the current day the first thing in the
agenda listing for the day. Of the entries without a time indication, keep
@@ -2156,7 +2158,7 @@ string that it returns."
(org-remap org-agenda-mode-map 'move-end-of-line 'org-agenda-end-of-line)
(defvar org-agenda-menu) ; defined later in this file.
-(defvar org-agenda-restrict nil) ; defined later in this file.
+(defvar org-agenda-restrict nil)
(defvar org-agenda-follow-mode nil)
(defvar org-agenda-entry-text-mode nil)
(defvar org-agenda-clockreport-mode nil)
@@ -4122,7 +4124,7 @@ dimming them." ;FIXME: The arg isn't used, actually!
If the header at `org-hd-marker' is blocked according to
`org-entry-blocked-p', then if `org-agenda-dim-blocked-tasks' is
-'invisible and the header is not blocked by checkboxes, set the
+`invisible' and the header is not blocked by checkboxes, set the
text property `org-todo-blocked' to `invisible', otherwise set it
to t."
(when (get-text-property 0 'todo-state entry)
@@ -4857,7 +4859,7 @@ Press `\\[org-agenda-manipulate-query-add]', \
;;;###autoload
(defun org-todo-list (&optional arg)
- "Show all (not done) TODO entries from all agenda file in a single list.
+ "Show all (not done) TODO entries from all agenda files in a single list.
The prefix arg can be used to select a specific TODO keyword and limit
the list to these. When using `\\[universal-argument]', you will be prompted
for a keyword. A numeric prefix directly selects the Nth keyword in
@@ -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 (org-at-timestamp-p 'agenda)))
(throw :skip nil))
(org-agenda-skip))
(let* ((pos (match-beginning 0))
@@ -7177,12 +7180,13 @@ The optional argument TYPE tells the agenda type."
(concat
(substring x 0 (match-end 1))
(unless (string= org-agenda-todo-keyword-format "")
- (format org-agenda-todo-keyword-format
- (match-string 2 x)))
- ;; Remove `display' property as the icon could leak
- ;; on the white space.
- (org-add-props " " (org-plist-delete (text-properties-at 0 x)
- 'display))
+ (format org-agenda-todo-keyword-format
+ (match-string 2 x)))
+ (unless (string= org-agenda-todo-keyword-format "")
+ ;; Remove `display' property as the icon could leak
+ ;; on the white space.
+ (org-add-props " " (org-plist-delete (text-properties-at 0 x)
+ 'display)))
(substring x (match-end 3)))))))
x)))
@@ -7285,7 +7289,7 @@ When TYPE is \"scheduled\", \"deadline\", \"timestamp\" or
\"timestamp_ia\", compare within each of these type. When TYPE
is the empty string, compare all timestamps without respect of
their type."
- (let* ((def (and (not org-agenda-sort-notime-is-late) -1))
+ (let* ((def (if org-agenda-sort-notime-is-late 99999999 -1))
(ta (or (and (string-match type (or (get-text-property 1 'type a) ""))
(get-text-property 1 'ts-date a))
def))
@@ -7395,7 +7399,7 @@ Argument ARG is the prefix argument."
When in a restricted subtree, remove it.
The restriction will span over the entire file if TYPE is `file',
-or if type is '(4), or if the cursor is before the first headline
+or if type is \\='(4), or if the cursor is before the first headline
in the file. Otherwise, only apply the restriction to the current
subtree."
(interactive "P")
diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el
index d3c5094b462..2fd9a9c74da 100644
--- a/lisp/org/org-capture.el
+++ b/lisp/org/org-capture.el
@@ -1453,7 +1453,8 @@ Of course, if exact position has been required, just put it there."
(org-with-point-at pos
(when org-capture-bookmark
(let ((bookmark (plist-get org-bookmark-names-plist :last-capture)))
- (when bookmark (with-demoted-errors (bookmark-set bookmark)))))
+ (when bookmark (with-demoted-errors "Bookmark set error: %S"
+ (bookmark-set bookmark)))))
(move-marker org-capture-last-stored-marker (point))))))
(defun org-capture-narrow (beg end)
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index ddae182791e..fdc9818a5a8 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -658,7 +658,6 @@ there is no recent clock to choose from."
(if (< i 10)
(+ i ?0)
(+ i (- ?A 10))) m))
- (if (fboundp 'int-to-char) (setf (car s) (int-to-char (car s))))
(push s sel-list)))
(run-hooks 'org-clock-before-select-task-hook)
(goto-char (point-min))
@@ -1105,7 +1104,7 @@ to be CLOCKED OUT."))))
60))
(keep
(or (and (memq ch '(?k ?K))
- (read-number "Keep how many minutes? " default))
+ (read-number "Keep how many minutes: " default))
(and (memq ch '(?t ?T))
(floor
(/ (float-time
@@ -1113,7 +1112,7 @@ to be CLOCKED OUT."))))
60)))))
(gotback
(and (memq ch '(?g ?G))
- (read-number "Got back how many minutes ago? " default)))
+ (read-number "Got back how many minutes ago: " default)))
(subtractp (memq ch '(?s ?S)))
(barely-started-p (org-time-less-p
(org-time-subtract last-valid (cdr clock))
@@ -1904,11 +1903,11 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes."
((match-end 2)
;; Two time stamps.
(let* ((ts (float-time
- (encode-time
+ (apply #'encode-time
(save-match-data
(org-parse-time-string (match-string 2))))))
(te (float-time
- (encode-time
+ (apply #'encode-time
(org-parse-time-string (match-string 3)))))
(dt (- (if tend (min te tend) te)
(if tstart (max ts tstart) ts))))
@@ -2505,7 +2504,7 @@ the currently selected interval size."
(when step
;; Write many tables, in steps
(unless (or block (and ts te))
- (user-error "Clocktable `:step' can only be used with `:block' or `:tstart, :end'"))
+ (user-error "Clocktable `:step' can only be used with `:block' or `:tstart', `:tend'"))
(org-clocktable-steps params)
(throw 'exit nil))
@@ -3042,9 +3041,9 @@ Otherwise, return nil."
(setq ts (match-string 1)
te (match-string 3))
(setq s (- (float-time
- (encode-time (org-parse-time-string te)))
+ (apply #'encode-time (org-parse-time-string te)))
(float-time
- (encode-time (org-parse-time-string ts))))
+ (apply #'encode-time (org-parse-time-string ts))))
neg (< s 0)
s (abs s)
h (floor (/ s 3600))
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index 371889432d3..829fcbbe3fb 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -782,7 +782,7 @@ around it."
(setq time-after (copy-sequence time))
(setf (nth 3 time-before) (1- (nth 3 time)))
(setf (nth 3 time-after) (1+ (nth 3 time)))
- (mapcar (lambda (x) (format-time-string fmt (encode-time x)))
+ (mapcar (lambda (x) (format-time-string fmt (apply #'encode-time x)))
(list time-before time time-after)))))
(defun org-columns-open-link (&optional arg)
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index cfccc2c0523..3e394fbab1c 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -39,7 +39,7 @@
(declare-function org-calendar-goto-agenda "org-agenda" ())
(declare-function org-align-tags "org" (&optional all))
(declare-function org-at-heading-p "org" (&optional ignored))
-(declare-function org-at-table.el-p "org" ())
+(declare-function org-at-table.el-p "org-table" ())
(declare-function org-element-at-point "org-element" ())
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-lineage "org-element" (blob &optional types with-self))
@@ -72,6 +72,35 @@
(defvar org-table1-hline-regexp)
+;;; Emacs < 29 compatibility
+
+(defvar org-file-has-changed-p--hash-table (make-hash-table :test #'equal)
+ "Internal variable used by `org-file-has-changed-p'.")
+
+(if (fboundp 'file-has-changed-p)
+ (defalias 'org-file-has-changed-p #'file-has-changed-p)
+ (defun org-file-has-changed-p (file &optional tag)
+ "Return non-nil if FILE has changed.
+The size and modification time of FILE are compared to the size
+and modification time of the same FILE during a previous
+invocation of `org-file-has-changed-p'. Thus, the first invocation
+of `org-file-has-changed-p' always returns non-nil when FILE exists.
+The optional argument TAG, which must be a symbol, can be used to
+limit the comparison to invocations with identical tags; it can be
+the symbol of the calling function, for example."
+ (let* ((file (directory-file-name (expand-file-name file)))
+ (remote-file-name-inhibit-cache t)
+ (fileattr (file-attributes file 'integer))
+ (attr (and fileattr
+ (cons (file-attribute-size fileattr)
+ (file-attribute-modification-time fileattr))))
+ (sym (concat (symbol-name tag) "@" file))
+ (cachedattr (gethash sym org-file-has-changed-p--hash-table)))
+ (when (not (equal attr cachedattr))
+ (puthash sym attr org-file-has-changed-p--hash-table)))))
+
+
+
;;; Emacs < 28.1 compatibility
(if (fboundp 'directory-empty-p)
@@ -209,7 +238,7 @@ This is a floating point number if the size is too large for an integer."
(if (fboundp 'string-collate-lessp)
(defalias 'org-string-collate-lessp
'string-collate-lessp)
- (defun org-string-collate-lessp (s1 s2 &rest _)
+ (defun org-string-collate-lessp (s1 s2 &optional _ _)
"Return non-nil if STRING1 is less than STRING2 in lexicographic order.
Case is significant."
(string< s1 s2)))
@@ -1048,9 +1077,9 @@ ELEMENT is the element at point."
(cl-case (org-element-type object)
;; Prevent checks in links due to keybinding conflict with
;; Flyspell.
- ((code entity export-snippet inline-babel-call
- inline-src-block line-break latex-fragment link macro
- statistics-cookie target timestamp verbatim)
+ ((citation citation-reference code entity export-snippet inline-babel-call
+ inline-src-block line-break latex-fragment link macro
+ statistics-cookie target timestamp verbatim)
nil)
(footnote-reference
;; Only in inline footnotes, within the definition.
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index 79527866076..20b5b030392 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -396,31 +396,25 @@ still has an entry since one of its properties (`:title') does.")
"Alist between element types and locations of secondary values.")
(defconst org-element--pair-round-table
- (let ((table (make-syntax-table)))
+ (let ((table (make-char-table 'syntax-table '(2))))
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
- (dolist (char '(?\{ ?\} ?\[ ?\] ?\< ?\>) table)
- (modify-syntax-entry char " " table)))
- "Table used internally to pair only round brackets.
-Other brackets are treated as spaces.")
+ table)
+ "Table used internally to pair only round brackets.")
(defconst org-element--pair-square-table
- (let ((table (make-syntax-table)))
+ (let ((table (make-char-table 'syntax-table '(2))))
(modify-syntax-entry ?\[ "(]" table)
(modify-syntax-entry ?\] ")[" table)
- (dolist (char '(?\{ ?\} ?\( ?\) ?\< ?\>) table)
- (modify-syntax-entry char " " table)))
- "Table used internally to pair only square brackets.
-Other brackets are treated as spaces.")
+ table)
+ "Table used internally to pair only square brackets.")
(defconst org-element--pair-curly-table
- (let ((table (make-syntax-table)))
+ (let ((table (make-char-table 'syntax-table '(2))))
(modify-syntax-entry ?\{ "(}" table)
(modify-syntax-entry ?\} "){" table)
- (dolist (char '(?\[ ?\] ?\( ?\) ?\< ?\>) table)
- (modify-syntax-entry char " " table)))
- "Table used internally to pair only curly brackets.
-Other brackets are treated as spaces.")
+ table)
+ "Table used internally to pair only curly brackets.")
(defun org-element--parse-paired-brackets (char)
"Parse paired brackets at point.
@@ -4397,6 +4391,7 @@ looking into captions:
;; every element it encounters.
(and (not (eq category 'elements))
(setq category 'elements))))))))
+ (--ignore-list (plist-get info :ignore-list))
--acc)
(letrec ((--walk-tree
(lambda (--data)
@@ -4406,7 +4401,7 @@ looking into captions:
(cond
((not --data))
;; Ignored element in an export context.
- ((and info (memq --data (plist-get info :ignore-list))))
+ ((and info (memq --data --ignore-list)))
;; List of elements or objects.
((not --type) (mapc --walk-tree --data))
;; Unconditionally enter parse trees.
diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el
index 1db36bc72ba..d96898372f9 100644
--- a/lisp/org/org-faces.el
+++ b/lisp/org/org-faces.el
@@ -38,8 +38,7 @@
:group 'org-faces)
(defface org-hide
- '((default :inherit fixed-pitch)
- (((background light)) (:foreground "white"))
+ '((((background light)) (:foreground "white"))
(((background dark)) (:foreground "black")))
"Face used to hide leading stars in headlines.
The foreground color of this face should be equal to the background
@@ -202,8 +201,7 @@ set the properties in the `org-column' face. For example, set
:group 'org-faces)
(defface org-date
- '((default :inherit fixed-pitch)
- (((class color) (background light)) (:foreground "Purple" :underline t))
+ '((((class color) (background light)) (:foreground "Purple" :underline t))
(((class color) (background dark)) (:foreground "Cyan" :underline t))
(t (:underline t)))
"Face for date/time stamps."
@@ -379,8 +377,7 @@ changes."
(sexp :tag "Face")))))
(defface org-table ;Copied from `font-lock-function-name-face'
- '((default :inherit fixed-pitch)
- (((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
+ '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
(((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
(((class color) (min-colors 16) (background light)) (:foreground "Blue"))
(((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
@@ -396,8 +393,7 @@ changes."
:group 'org-faces)
(defface org-formula
- '((default :inherit fixed-pitch)
- (((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
+ '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
(((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
(((class color) (min-colors 8) (background light)) (:foreground "red"))
(((class color) (min-colors 8) (background dark)) (:foreground "red"))
@@ -405,12 +401,12 @@ changes."
"Face for formulas."
:group 'org-faces)
-(defface org-code '((t :inherit (fixed-pitch shadow)))
+(defface org-code '((t :inherit shadow))
"Face for fixed-width text like code snippets."
:group 'org-faces
:version "22.1")
-(defface org-meta-line '((t :inherit (fixed-pitch font-lock-comment-face)))
+(defface org-meta-line '((t :inherit font-lock-comment-face))
"Face for meta lines starting with \"#+\"."
:group 'org-faces
:version "22.1")
@@ -437,7 +433,7 @@ This face applies to the #+TITLE:, #+SUBTITLE:, #+AUTHOR:,
#+EMAIL: and #+DATE: keywords."
:group 'org-faces)
-(defface org-block `((t :inherit (fixed-pitch shadow)
+(defface org-block `((t :inherit shadow
,@(and (>= emacs-major-version 27) '(:extend t))))
"Face used for text inside various blocks.
@@ -459,7 +455,7 @@ verse and quote blocks are fontified using the `org-verse' and
"Face used for the line delimiting the end of source blocks."
:group 'org-faces)
-(defface org-verbatim '((t (:inherit (fixed-pitch shadow))))
+(defface org-verbatim '((t (:inherit shadow)))
"Face for fixed-with text like code snippets."
:group 'org-faces
:version "22.1")
diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el
index a5fea08882f..c7b4bde0d28 100644
--- a/lisp/org/org-feed.el
+++ b/lisp/org/org-feed.el
@@ -406,7 +406,7 @@ it can be a list structured like an entry in `org-feed-alist'."
;; Write the new status
;; We do this only now, in case something goes wrong above, so
- ;; that would would end up with a status that does not reflect
+ ;; that would end up with a status that does not reflect
;; which items truly have been handled
(org-feed-write-status inbox-pos drawer status)
diff --git a/lisp/org/org-lint.el b/lisp/org/org-lint.el
index 0894951b654..83c2d08a907 100644
--- a/lisp/org/org-lint.el
+++ b/lisp/org/org-lint.el
@@ -784,8 +784,12 @@ Use \"export %s\" instead"
reports))
(defun org-lint-undefined-footnote-reference (ast)
- (let ((definitions (org-element-map ast 'footnote-definition
- (lambda (f) (org-element-property :label f)))))
+ (let ((definitions
+ (org-element-map ast '(footnote-definition footnote-reference)
+ (lambda (f)
+ (and (or (eq 'footnote-definition (org-element-type f))
+ (eq 'inline (org-element-property :type f)))
+ (org-element-property :label f))))))
(org-element-map ast 'footnote-reference
(lambda (f)
(let ((label (org-element-property :label f)))
diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el
index 0dd8139a977..da309f8c6da 100644
--- a/lisp/org/org-list.el
+++ b/lisp/org/org-list.el
@@ -1442,7 +1442,7 @@ This function returns, destructively, the new list structure."
(save-excursion
(goto-char (org-list-get-last-item item struct prevs))
(point-at-eol)))
- ((string-match-p "\\`[0-9]+\\'" dest)
+ ((and (stringp dest) (string-match-p "\\`[0-9]+\\'" dest))
(let* ((all (org-list-get-all-items item struct prevs))
(len (length all))
(index (mod (string-to-number dest) len)))
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index bb8a95065b3..0921f3aa27c 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -378,7 +378,7 @@ Return value as a string."
(buffer-substring
(point) (line-end-position)))))
(when (cl-some #'identity time)
- (setq date (encode-time time))))))))
+ (setq date (apply #'encode-time time))))))))
(let ((proc (get-buffer-process buf)))
(while (and proc (accept-process-output proc .5 nil t)))))
(kill-buffer buf))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 6f038f026bf..bb0562dde06 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -37,6 +37,7 @@
(declare-function org-mode "org" ())
(declare-function org-show-context "org" (&optional key))
(declare-function org-string-collate-lessp "org-compat" (s1 s2 &optional locale ignore-case))
+(declare-function org-time-convert-to-integer "org-compat" (time))
(defvar org-ts-regexp0)
(defvar ffap-url-regexp)
@@ -257,15 +258,16 @@ ignored in this case."
(defun org-file-newer-than-p (file time)
"Non-nil if FILE is newer than TIME.
-FILE is a filename, as a string, TIME is a list of integers, as
+FILE is a filename, as a string, TIME is a Lisp time value, as
returned by, e.g., `current-time'."
(and (file-exists-p file)
;; Only compare times up to whole seconds as some file-systems
;; (e.g. HFS+) do not retain any finer granularity. As
;; a consequence, make sure we return non-nil when the two
;; times are equal.
- (not (time-less-p (cl-subseq (nth 5 (file-attributes file)) 0 2)
- (cl-subseq time 0 2)))))
+ (not (time-less-p (org-time-convert-to-integer
+ (nth 5 (file-attributes file)))
+ (org-time-convert-to-integer time)))))
(defun org-compile-file (source process ext &optional err-msg log-buf spec)
"Compile a SOURCE file using PROCESS.
@@ -1185,7 +1187,7 @@ nil, just return 0."
((numberp s) s)
((stringp s)
(condition-case nil
- (float-time (encode-time (org-parse-time-string s)))
+ (float-time (apply #'encode-time (org-parse-time-string s)))
(error 0)))
(t 0)))
@@ -1252,7 +1254,7 @@ following special strings: \"<now>\", \"<today>\",
\"<tomorrow>\", and \"<yesterday>\".
Return 0. if S is not recognized as a valid value."
- (let ((today (float-time (encode-time
+ (let ((today (float-time (apply #'encode-time
(append '(0 0 0) (nthcdr 3 (decode-time)))))))
(save-match-data
(cond
diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el
index 8d5be425453..a590ff87f24 100644
--- a/lisp/org/org-mouse.el
+++ b/lisp/org/org-mouse.el
@@ -208,7 +208,7 @@ this function is called. Otherwise, the current major mode menu is used."
(interactive "@e \nP")
(if (and (= (event-click-count event) 1)
(or (not mark-active)
- (sit-for (/ double-click-time 1000.0))))
+ (sit-for (/ (mouse-double-click-time) 1000.0))))
(progn
(select-window (posn-window (event-start event)))
(when (not (org-mouse-mark-active))
@@ -295,7 +295,7 @@ nor a function, elements of KEYWORDS are used directly."
((functionp itemformat) (funcall itemformat keyword))
((stringp itemformat) (format itemformat keyword))
(t keyword))
- (list 'funcall function keyword)
+ `(funcall #',function ,keyword)
:style (cond
((null selected) t)
((functionp selected) 'toggle)
diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el
index bf84c99e042..4507fbe7ddc 100644
--- a/lisp/org/org-plot.el
+++ b/lisp/org/org-plot.el
@@ -280,7 +280,7 @@ When NORMALISE is non-nil, the count is divided by the number of values."
collect (cons n (/ (length m) normaliser)))))
(defun org--plot/prime-factors (value)
- "Return the prime decomposition of VALUE, e.g. for 12, '(3 2 2)."
+ "Return the prime decomposition of VALUE, e.g. for 12, \\='(3 2 2)."
(let ((factors '(1)) (i 1))
(while (/= 1 value)
(setq i (1+ i))
diff --git a/lisp/org/org-refile.el b/lisp/org/org-refile.el
index 8e1ab7439e6..71d00a7a22b 100644
--- a/lisp/org/org-refile.el
+++ b/lisp/org/org-refile.el
@@ -566,18 +566,18 @@ prefix argument (`C-u C-u C-u C-c C-w')."
(let ((bookmark-name (plist-get org-bookmark-names-plist
:last-refile)))
(when bookmark-name
- (with-demoted-errors
- (bookmark-set bookmark-name))))
+ (with-demoted-errors "Bookmark set error: %S"
+ (bookmark-set bookmark-name))))
;; If we are refiling for capture, make sure that the
;; last-capture pointers point here
(when (bound-and-true-p org-capture-is-refiling)
(let ((bookmark-name (plist-get org-bookmark-names-plist
:last-capture-marker)))
(when bookmark-name
- (with-demoted-errors
- (bookmark-set bookmark-name))))
+ (with-demoted-errors "Bookmark set error: %S"
+ (bookmark-set bookmark-name))))
(move-marker org-capture-last-stored-marker (point)))
- (when (fboundp 'deactivate-mark) (deactivate-mark))
+ (deactivate-mark)
(run-hooks 'org-after-refile-insert-hook)))
(unless org-refile-keep
(if regionp
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 58707eae440..c301bc6af1a 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -462,14 +462,14 @@ This may be useful when columns have been shrunk."
(when pos (goto-char pos))
(goto-char (line-beginning-position))
(let ((end (line-end-position)) str)
- (backward-char)
+ (goto-char (1- pos))
(while (progn (forward-char 1) (< (point) end))
(let ((ov (car (overlays-at (point)))))
(if (not ov)
(push (char-to-string (char-after)) str)
(push (overlay-get ov 'display) str)
(goto-char (1- (overlay-end ov))))))
- (format "%s" (mapconcat #'identity (reverse str) "")))))
+ (format "|%s" (mapconcat #'identity (reverse str) "")))))
(defvar-local org-table-header-overlay nil)
(defun org-table-header-set-header ()
@@ -2606,7 +2606,7 @@ location of point."
(format-time-string
(org-time-stamp-format
(string-match-p "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
- (encode-time
+ (apply #'encode-time
(save-match-data (org-parse-time-string ts))))))
form t t))
@@ -5465,7 +5465,7 @@ The table is taken from the parameter TXT, or from the buffer at point."
(nreverse table)))))
(defun org-table-collapse-header (table &optional separator max-header-lines)
- "Collapse the lines before 'hline into a single header.
+ "Collapse the lines before `hline' into a single header.
The given TABLE is a list of lists as returned by `org-table-to-lisp'.
The leading lines before the first `hline' symbol are considered
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 1053bbe22cc..2a500fe5106 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -5,13 +5,13 @@
(defun org-release ()
"The release version of Org.
Inserted by installing Org mode or when a release is made."
- (let ((org-release "9.5.2"))
+ (let ((org-release "9.5.4"))
org-release))
;;;###autoload
(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.4-3-g6dc785"))
org-git-version))
(provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index fba45caabe6..008230500d7 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -9,7 +9,7 @@
;; Homepage: https://orgmode.org
;; Package-Requires: ((emacs "25.1"))
-;; Version: 9.5.2
+;; Version: 9.5.4
;; This file is part of GNU Emacs.
;;
@@ -199,6 +199,7 @@ Stars are put in group 1 and the trimmed body in group 2.")
(declare-function org-update-radio-target-regexp "ol" ())
(defvar org-element-paragraph-separate)
+(defvar org-element--timestamp-regexp)
(defvar org-indent-indentation-per-level)
(defvar org-radio-target-regexp)
(defvar org-target-link-regexp)
@@ -246,7 +247,7 @@ byte-compiled before it is loaded."
(if compile
(progn
(byte-compile-file tangled-file)
- (load tangled-file)
+ (load-file (byte-compile-dest-file tangled-file))
(message "Compiled and loaded %s" tangled-file))
(load-file tangled-file)
(message "Loaded %s" tangled-file))))
@@ -3300,7 +3301,7 @@ Replace format-specifiers in the command as noted below and use
%i: The LaTeX fragment to be converted.
For example, this could be used with LaTeXML as
-\"latexmlc 'literal:%i' --profile=math --preload=siunitx.sty 2>/dev/null\"."
+\"latexmlc \\='literal:%i\\=' --profile=math --preload=siunitx.sty 2>/dev/null\"."
:group 'org-latex
:package-version '(Org . "9.4")
:type '(choice
@@ -12159,7 +12160,7 @@ This works in the agenda, and also in an Org buffer."
(progn
(message "[s]et or [r]emove? ")
(equal (read-char-exclusive) ?r))))
- (when (fboundp 'deactivate-mark) (deactivate-mark))
+ (deactivate-mark)
(let ((agendap (equal major-mode 'org-agenda-mode))
l1 l2 m buf pos newhead (cnt 0))
(goto-char end)
@@ -13986,7 +13987,7 @@ user."
(when (< (nth 2 org-defdecode) org-extend-today-until)
(setf (nth 2 org-defdecode) -1)
(setf (nth 1 org-defdecode) 59)
- (setq org-def (encode-time org-defdecode))
+ (setq org-def (apply #'encode-time org-defdecode))
(setq org-defdecode (decode-time org-def)))
(let* ((timestr (format-time-string
(if org-with-time "%Y-%m-%d %H:%M" "%Y-%m-%d")
@@ -14470,7 +14471,7 @@ The command returns the inserted time stamp."
time (org-fix-decoded-time t1)
str (org-add-props
(format-time-string
- (substring tf 1 -1) (encode-time time))
+ (substring tf 1 -1) (apply 'encode-time time))
nil 'mouse-face 'highlight))
(put-text-property beg end 'display str)))
@@ -14725,7 +14726,7 @@ days in order to avoid rounding problems."
(defun org-time-string-to-time (s)
"Convert timestamp string S into internal time."
- (encode-time (org-parse-time-string s)))
+ (apply #'encode-time (org-parse-time-string s)))
(defun org-time-string-to-seconds (s)
"Convert a timestamp string S into a number of seconds."
@@ -15011,16 +15012,25 @@ value is equivalent to `inactive'.
When at a timestamp, return the position of the point as a symbol
among `bracket', `after', `year', `month', `hour', `minute',
`day' or a number of character from the last know part of the
-time stamp.
+time stamp. If diary sexp timestamps, any point inside the timestamp
+is considered `day' (i.e. only `bracket', `day', and `after' return
+values are possible).
When matching, the match groups are the following:
- group 1: year
- group 2: month
- group 3: day number
- group 4: day name
+ group 1: year, if any
+ group 2: month, if any
+ group 3: day number, if any
+ group 4: day name, if any
group 5: hours, if any
group 6: minutes, if any"
- (let* ((regexp (if extended org-ts-regexp3 org-ts-regexp2))
+ (let* ((regexp
+ (if extended
+ (if (eq extended 'agenda)
+ (rx-to-string
+ `(or (regexp ,org-ts-regexp3)
+ (regexp ,org-element--timestamp-regexp)))
+ org-ts-regexp3)
+ org-ts-regexp2))
(pos (point))
(match?
(let ((boundaries (org-in-regexp regexp)))
@@ -15051,7 +15061,8 @@ When matching, the match groups are the following:
((org-pos-in-match-range pos 8) 'minute)
((or (org-pos-in-match-range pos 4)
(org-pos-in-match-range pos 5)) 'day)
- ((and (> pos (or (match-end 8) (match-end 5)))
+ ((and (or (match-end 8) (match-end 5))
+ (> pos (or (match-end 8) (match-end 5)))
(< pos (match-end 0)))
(- pos (or (match-end 8) (match-end 5))))
(t 'day))))
@@ -15155,7 +15166,7 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like
(setcar time0 (or (car time0) 0))
(setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
(setcar (nthcdr 2 time0) (or (nth 2 time0) 0))
- (setq time (encode-time time0))))
+ (setq time (apply 'encode-time time0))))
;; Insert the new time-stamp, and ensure point stays in the same
;; category as before (i.e. not after the last position in that
;; category).
@@ -17522,11 +17533,11 @@ this numeric value."
(interactive "r")
(let ((result ""))
(while (/= beg end)
- (when (get-char-property beg 'invisible)
- (setq beg (next-single-char-property-change beg 'invisible nil end)))
- (let ((next (next-single-char-property-change beg 'invisible nil end)))
- (setq result (concat result (buffer-substring beg next)))
- (setq beg next)))
+ (if (invisible-p beg)
+ (setq beg (next-single-char-property-change beg 'invisible nil end))
+ (let ((next (next-single-char-property-change beg 'invisible nil end)))
+ (setq result (concat result (buffer-substring beg next)))
+ (setq beg next))))
(setq deactivate-mark t)
(kill-new result)
(message "Visible strings have been copied to the kill ring.")))
@@ -18731,17 +18742,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))
diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el
index 5de0b5d675c..9cf9125aebd 100644
--- a/lisp/org/ox-html.el
+++ b/lisp/org/ox-html.el
@@ -442,7 +442,7 @@ property on the headline itself.")
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
- .org-svg { width: 90%; }
+ .org-svg { }
</style>"
"The default style specification for exported HTML files.
You can use `org-html-head' and `org-html-head-extra' to add to
@@ -2909,7 +2909,7 @@ Starred and \"displaymath\" environments are not numbered."
(defun org-html--unlabel-latex-environment (latex-frag)
"Change environment in LATEX-FRAG string to an unnumbered one.
-For instance, change an 'equation' environment to 'equation*'."
+For instance, change an `equation' environment to `equation*'."
(replace-regexp-in-string
"\\`[ \t]*\\\\begin{\\([^*]+?\\)}"
"\\1*"
diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el
index 636bd0d2ae3..51e2352b4e8 100644
--- a/lisp/org/ox-publish.el
+++ b/lisp/org/ox-publish.el
@@ -839,7 +839,7 @@ in `org-export-options-alist' or in export back-ends. In the
latter case, optional argument BACKEND has to be set to the
back-end where the option is defined, e.g.,
- (org-publish-find-property file :subtitle 'latex)
+ (org-publish-find-property file :subtitle \\='latex)
Return value may be a string or a list, depending on the type of
PROPERTY, i.e. \"behavior\" parameter from `org-export-options-alist'."
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index afea529f640..ae7e41e576b 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -632,7 +632,7 @@ This option can also be set with the SELECT_TAGS keyword."
(defcustom org-export-with-smart-quotes nil
"Non-nil means activate smart quotes during export.
This option can also be set with the OPTIONS keyword,
-e.g., \"':t\".
+e.g., \"\\=':t\".
When setting this to non-nil, you need to take care of
using the correct Babel package when exporting to LaTeX.
@@ -1923,28 +1923,34 @@ Return a string."
(and (not greaterp)
(memq type org-element-recursive-objects)))
(contents
- (mapconcat
- (lambda (element) (org-export-data element info))
- (org-element-contents
- (if (or greaterp objectp) data
- ;; Elements directly containing
- ;; objects must have their indentation
- ;; normalized first.
- (org-element-normalize-contents
- data
- ;; When normalizing first paragraph
- ;; of an item or
- ;; a footnote-definition, ignore
- ;; first line's indentation.
- (and
- (eq type 'paragraph)
- (memq (org-element-type parent)
- '(footnote-definition item))
- (eq (car (org-element-contents parent))
- data)
- (eq (org-element-property :pre-blank parent)
- 0)))))
- "")))
+ (let ((export-buffer (current-buffer)))
+ (with-temp-buffer
+ (dolist (element (org-element-contents
+ (if (or greaterp objectp) data
+ ;; Elements directly containing
+ ;; objects must have their indentation
+ ;; normalized first.
+ (org-element-normalize-contents
+ data
+ ;; When normalizing first paragraph
+ ;; of an item or
+ ;; a footnote-definition, ignore
+ ;; first line's indentation.
+ (and
+ (eq type 'paragraph)
+ (memq (org-element-type parent)
+ '(footnote-definition item))
+ (eq (car (org-element-contents parent))
+ data)
+ (eq (org-element-property :pre-blank parent)
+ 0))))))
+ (insert
+ ;; Use right local variable
+ ;; environment if there are, for
+ ;; example, #+BIND variables.
+ (with-current-buffer export-buffer
+ (org-export-data element info))))
+ (buffer-string)))))
(broken-link-handler
(funcall transcoder data
(if (not greaterp) contents
@@ -2956,11 +2962,12 @@ Return code as a string."
(mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o)))
(append (org-export-get-all-options backend)
org-export-options-alist))))
- tree)
+ tree modified-tick)
;; Update communication channel and get parse tree. Buffer
;; isn't parsed directly. Instead, all buffer modifications
;; and consequent parsing are undertaken in a temporary copy.
(org-export-with-buffer-copy
+ (font-lock-mode -1)
;; Run first hook with current back-end's name as argument.
(run-hook-with-args 'org-export-before-processing-hook
(org-export-backend-name backend))
@@ -2972,6 +2979,7 @@ Return code as a string."
;; potentially invasive changes.
(org-set-regexps-and-options)
(org-update-radio-target-regexp)
+ (setq modified-tick (buffer-chars-modified-tick))
;; Possibly execute Babel code. Re-run a macro expansion
;; specifically for {{{results}}} since inline source blocks
;; may have generated some more. Refresh buffer properties
@@ -2979,8 +2987,10 @@ Return code as a string."
(when org-export-use-babel
(org-babel-exp-process-buffer)
(org-macro-replace-all '(("results" . "$1")) parsed-keywords)
- (org-set-regexps-and-options)
- (org-update-radio-target-regexp))
+ (unless (eq modified-tick (buffer-chars-modified-tick))
+ (org-set-regexps-and-options)
+ (org-update-radio-target-regexp))
+ (setq modified-tick (buffer-chars-modified-tick)))
;; Run last hook with current back-end's name as argument.
;; Update buffer properties and radio targets one last time
;; before parsing.
@@ -2988,8 +2998,10 @@ Return code as a string."
(save-excursion
(run-hook-with-args 'org-export-before-parsing-hook
(org-export-backend-name backend)))
- (org-set-regexps-and-options)
- (org-update-radio-target-regexp)
+ (unless (eq modified-tick (buffer-chars-modified-tick))
+ (org-set-regexps-and-options)
+ (org-update-radio-target-regexp))
+ (setq modified-tick (buffer-chars-modified-tick))
;; Update communication channel with environment.
(setq info
(org-combine-plists
@@ -3748,28 +3760,33 @@ definition can be found, raise an error."
(if (not label) (org-element-contents footnote-reference)
(let ((cache (or (plist-get info :footnote-definition-cache)
(let ((hash (make-hash-table :test #'equal)))
+ ;; Cache all the footnotes in document for
+ ;; later search.
+ (org-element-map (plist-get info :parse-tree)
+ '(footnote-definition footnote-reference)
+ (lambda (f)
+ ;; Skip any standard footnote reference
+ ;; since those cannot contain a
+ ;; definition.
+ (unless (eq (org-element-property :type f) 'standard)
+ (puthash
+ (cons :element (org-element-property :label f))
+ f
+ hash)))
+ info)
(plist-put info :footnote-definition-cache hash)
hash))))
(or
(gethash label cache)
(puthash label
- (org-element-map (plist-get info :parse-tree)
- '(footnote-definition footnote-reference)
- (lambda (f)
- (cond
- ;; Skip any footnote with a different label.
- ;; Also skip any standard footnote reference
- ;; with the same label since those cannot
- ;; contain a definition.
- ((not (equal (org-element-property :label f) label)) nil)
- ((eq (org-element-property :type f) 'standard) nil)
- ((org-element-contents f))
- ;; Even if the contents are empty, we can not
- ;; return nil since that would eventually raise
- ;; the error. Instead, return the equivalent
- ;; empty string.
- (t "")))
- info t)
+ (let ((hashed (gethash (cons :element label) cache)))
+ (when hashed
+ (or (org-element-contents hashed)
+ ;; Even if the contents are empty, we can not
+ ;; return nil since that would eventually raise
+ ;; the error. Instead, return the equivalent
+ ;; empty string.
+ "")))
cache)
(error "Definition not found for footnote %s" label))))))
@@ -4341,17 +4358,27 @@ significant."
(let* ((search-cells (org-export-string-to-search-cell
(org-element-property :path link)))
(link-cache (or (plist-get info :resolve-fuzzy-link-cache)
- (let ((table (make-hash-table :test #'eq)))
+ (let ((table (make-hash-table :test #'equal)))
+ ;; Cache all the element search cells.
+ (org-element-map (plist-get info :parse-tree)
+ (append pseudo-types '(target) org-element-all-elements)
+ (lambda (datum)
+ (dolist (cell (org-export-search-cells datum))
+ (if (gethash cell table)
+ (push datum (gethash cell table))
+ (puthash cell (list datum) table)))))
(plist-put info :resolve-fuzzy-link-cache table)
table)))
(cached (gethash search-cells link-cache 'not-found)))
(if (not (eq cached 'not-found)) cached
(let ((matches
- (org-element-map (plist-get info :parse-tree)
- (append pseudo-types '(target) org-element-all-elements)
- (lambda (datum)
- (and (org-export-match-search-cell-p datum search-cells)
- datum)))))
+ (let (result)
+ (dolist (search-cell search-cells)
+ (setq result
+ (nconc
+ result
+ (gethash search-cell link-cache))))
+ (delq nil result))))
(unless matches
(signal 'org-link-broken (list (org-element-property :path link))))
(puthash
@@ -4378,15 +4405,27 @@ tree or a file name. Assume LINK type is either \"id\" or
\"custom-id\". Throw an error if no match is found."
(let ((id (org-element-property :path link)))
;; First check if id is within the current parse tree.
- (or (org-element-map (plist-get info :parse-tree) 'headline
- (lambda (headline)
- (when (or (equal (org-element-property :ID headline) id)
- (equal (org-element-property :CUSTOM_ID headline) id))
- headline))
- info 'first-match)
- ;; Otherwise, look for external files.
- (cdr (assoc id (plist-get info :id-alist)))
- (signal 'org-link-broken (list id)))))
+ (or (let ((local-ids (or (plist-get info :id-local-cache)
+ (let ((table (make-hash-table :test #'equal)))
+ (org-element-map
+ (plist-get info :parse-tree)
+ 'headline
+ (lambda (headline)
+ (let ((id (org-element-property :ID headline))
+ (custom-id (org-element-property :CUSTOM_ID headline)))
+ (when id
+ (unless (gethash id table)
+ (puthash id headline table)))
+ (when custom-id
+ (unless (gethash custom-id table)
+ (puthash custom-id headline table)))))
+ info)
+ (plist-put info :id-local-cache table)
+ table))))
+ (gethash id local-ids))
+ ;; Otherwise, look for external files.
+ (cdr (assoc id (plist-get info :id-alist)))
+ (signal 'org-link-broken (list id)))))
(defun org-export-resolve-radio-link (link info)
"Return radio-target object referenced as LINK destination.
diff --git a/lisp/outline.el b/lisp/outline.el
index 0304d2334c4..38a37fb74d3 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -1,7 +1,6 @@
;;; outline.el --- outline mode commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986, 1993-1995, 1997, 2000-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1986-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: outlines
@@ -178,15 +177,25 @@ in the file it applies to.")
map))
(defcustom outline-minor-mode-cycle-filter nil
- "Filter out positions on the heading available for cycling."
+ "Control where on a heading the visibility-cycling commands are bound to keys.
+This option controls, in Outline minor mode, where on a heading typing
+the key sequences bound to visibility-cycling commands like `outline-cycle'
+and `outline-cycle-buffer' will invoke those commands. By default, you can
+invoke these commands by typing \\`TAB' and \\`S-TAB' anywhere on a heading line,
+but customizing this option can make those bindings be in effect only at
+specific positions on the heading, like only at the line's beginning or
+line's end. This allows these keys to be bound to their usual commands,
+as determined by the major mode, elsewhere on the heading lines.
+This option is only in effect when `outline-minor-mode-cycle' is non-nil."
:type '(choice (const :tag "Everywhere" nil)
(const :tag "At line beginning" bolp)
(const :tag "Not at line beginning"
(lambda () (not (bolp))))
(const :tag "At line end" eolp)
- (function :tag "Custom filter"))
+ (function :tag "Custom filter function"))
:version "28.1")
+(defvar outline-minor-mode-cycle)
(defun outline-minor-mode-cycle--bind (map key binding &optional filter)
(define-key map key
`(menu-item
@@ -195,8 +204,10 @@ in the file it applies to.")
:filter
,(or filter
(lambda (cmd)
- (when (or (not (functionp outline-minor-mode-cycle-filter))
- (funcall outline-minor-mode-cycle-filter))
+ (when (and outline-minor-mode-cycle
+ (outline-on-heading-p t)
+ (or (not (functionp outline-minor-mode-cycle-filter))
+ (funcall outline-minor-mode-cycle-filter)))
cmd))))))
(defvar outline-minor-mode-cycle-map
@@ -223,14 +234,8 @@ in the file it applies to.")
;; Highlight headings according to the level.
(eval . (list (concat "^\\(?:" outline-regexp "\\).*")
0 '(if outline-minor-mode
- (if outline-minor-mode-cycle
- (if outline-minor-mode-highlight
- (list 'face (outline-font-lock-face)
- 'keymap outline-minor-mode-cycle-map)
- (list 'face nil
- 'keymap outline-minor-mode-cycle-map))
- (if outline-minor-mode-highlight
- (list 'face (outline-font-lock-face))))
+ (if outline-minor-mode-highlight
+ (list 'face (outline-font-lock-face)))
(outline-font-lock-face))
(when outline-minor-mode
(pcase outline-minor-mode-highlight
@@ -315,8 +320,11 @@ data reflects the `outline-regexp'.")
(defvar outline-mode-hook nil
"This hook is run when outline mode starts.")
-(defvar outline-blank-line nil
- "Non-nil means to leave unhidden blank line before heading.")
+(defcustom outline-blank-line nil
+ "Non-nil means to leave an unhidden blank line before headings."
+ :type 'boolean
+ :safe #'booleanp
+ :version "22.1")
;;;###autoload
(define-derived-mode outline-mode text-mode "Outline"
@@ -354,7 +362,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)
@@ -370,28 +379,33 @@ After that, changing the prefix key requires manipulating keymaps."
(set-default sym val)))
(defcustom outline-minor-mode-cycle nil
- "Enable cycling of headings in `outline-minor-mode'.
-When enabled, it puts a keymap with cycling keys on heading lines.
-When point is on a heading line, then typing `TAB' cycles between `hide all',
-`headings only' and `show all' (`outline-cycle'). Typing `S-TAB' on
-a heading line cycles the whole buffer (`outline-cycle-buffer').
-Typing these keys anywhere outside heading lines uses their default bindings."
+ "Enable visibility-cycling commands on headings in `outline-minor-mode'.
+If enabled, typing \\`TAB' on a heading line cycles the visibility
+state of that heading's body between `hide all', `headings only'
+and `show all' (`outline-cycle'), and typing \\`S-TAB' on a heading
+line likewise cycles the visibility state of the whole buffer
+\(`outline-cycle-buffer').
+Typing these keys anywhere outside heading lines invokes their default
+bindings, per the current major mode."
:type 'boolean
:safe #'booleanp
:version "28.1")
(defcustom outline-minor-mode-highlight nil
- "Highlight headings in `outline-minor-mode' using font-lock keywords.
-Non-nil value works well only when outline font-lock keywords
-don't conflict with the major mode's font-lock keywords.
-When t, it puts outline faces only if there are no major mode's faces
-on headings. When `override', it completely overwrites major mode's
-faces with outline faces. When `append', it tries to append outline
-faces to major mode's faces."
- :type '(choice (const :tag "No highlighting" nil)
- (const :tag "Overwrite major mode faces" override)
- (const :tag "Append outline faces to major mode faces" append)
- (const :tag "Highlight separately from major mode faces" t))
+ "Whether to highlight headings in `outline-minor-mode' using font-lock keywords.
+This option controles whether `outline-minor-mode' will use its font-lock
+keywords to highlight headings, which could potentially conflict with
+font-lock faces defined by the major mode. Thus, a non-nil value will
+work well only when there's no such conflict.
+If the value is t, use outline faces only if there are no major mode's
+font-lock faces on headings. When `override', completely overwrite major
+mode's font-lock faces with outline faces. When `append', try to append
+outline font-lock faces to those of major mode."
+ :type '(choice (const :tag "Do not use outline font-lock highlighting" nil)
+ (const :tag "Overwrite major mode font-lock faces" override)
+ (const :tag "Append outline font-lock faces to major mode's"
+ append)
+ (const :tag "Highlight with outline font-lock faces only if major mode doesn't" t))
:safe #'symbolp
:version "28.1")
@@ -410,9 +424,7 @@ faces to major mode's faces."
(not (get-text-property (point) 'face))))
(overlay-put overlay 'face (outline-font-lock-face)))
(when outline-minor-mode-use-buttons
- (outline--insert-open-button))
- (when outline-minor-mode-cycle
- (overlay-put overlay 'keymap outline-minor-mode-cycle-map)))
+ (outline--insert-open-button)))
(goto-char (match-end 0))))))
;;;###autoload
@@ -421,11 +433,13 @@ faces to major mode's faces."
See the command `outline-mode' for more information on this mode."
:lighter " Outl"
- :keymap (list (cons [menu-bar] outline-minor-mode-menu-bar-map)
- (cons outline-minor-mode-prefix outline-mode-prefix-map))
+ :keymap (easy-mmode-define-keymap
+ `(([menu-bar] . ,outline-minor-mode-menu-bar-map)
+ (,outline-minor-mode-prefix . ,outline-mode-prefix-map))
+ :inherit outline-minor-mode-cycle-map)
(if outline-minor-mode
(progn
- (when (or outline-minor-mode-cycle outline-minor-mode-highlight)
+ (when outline-minor-mode-highlight
(if (and global-font-lock-mode (font-lock-specified-p major-mode))
(progn
(font-lock-add-keywords nil outline-font-lock-keywords t)
@@ -437,8 +451,9 @@ 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)))
- (when (or outline-minor-mode-cycle outline-minor-mode-highlight)
+ (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))
(remove-overlays nil nil 'outline-overlay t)
@@ -992,7 +1007,6 @@ If non-nil, EVENT should be a mouse event."
(overlay-put o 'help-echo "Click to hide")
(overlay-put o 'keymap
(define-keymap
- :parent outline-minor-mode-cycle-map
"RET" #'outline-hide-subtree
"<mouse-2>" #'outline-hide-subtree)))))
@@ -1003,7 +1017,6 @@ If non-nil, EVENT should be a mouse event."
(overlay-put o 'help-echo "Click to show")
(overlay-put o 'keymap
(define-keymap
- :parent outline-minor-mode-cycle-map
"RET" #'outline-show-subtree
"<mouse-2>" #'outline-show-subtree)))))
@@ -1308,9 +1321,187 @@ 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 Outline major and
+minor modes are set or when the command
+`outline-apply-default-state' is called interactively.
+
+When nil, no default state is defined and
+`outline-apply-default-state' is a no-op.
+
+If equal to `outline-show-all', all text of buffer is shown.
+
+If equal to `outline-show-only-headings', show only headings,
+whatever their level is.
+
+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 that level.
+
+If equal to a lambda function or function name, this function is
+expected to toggle headings visibility, and will be
+called without arguments 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.
+
+The rules apply if and only if `outline-default-state' is a
+number.
+
+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 cons cell of the form (custom-function . FUNCTION) where
+ FUNCTION is a lambda function or function name which will be
+ called without arguments 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."
+Return either `hide-all', `headings-only', or `show-all'."
(save-excursion
(let (start end ov-list heading-end)
(outline-back-to-heading)
@@ -1343,11 +1534,14 @@ Return either 'hide-all, 'headings-only, or 'show-all."
(save-excursion (outline-end-of-subtree) (point)))))
(defun outline-cycle ()
- "Cycle between `hide all', `headings only' and `show all'.
+ "Cycle visibility state of the current heading line's body.
-`Hide all' means hide all subheadings and their bodies.
-`Headings only' means show sub headings but not their bodies.
-`Show all' means show all subheadings and their bodies."
+This cycles the visibility of the current heading line's subheadings
+and body between `hide all', `headings only' and `show all'.
+
+`Hide all' means hide all the subheadings and their bodies.
+`Headings only' means show the subheadings, but not their bodies.
+`Show all' means show all the subheadings and their bodies."
(interactive)
(condition-case nil
(pcase (outline--cycle-state)
@@ -1369,7 +1563,15 @@ Return either 'hide-all, 'headings-only, or 'show-all."
"Internal variable used for tracking buffer cycle state.")
(defun outline-cycle-buffer ()
- "Cycle the whole buffer like in `outline-cycle'."
+ "Cycle visibility state of the body lines of the whole buffer.
+
+This cycles the visibility of all the subheadings and bodies of all
+the heading lines in the buffer. It cycles them between `hide all',
+`headings only' and `show all'.
+
+`Hide all' means hide all the buffer's subheadings and their bodies.
+`Headings only' means show all the subheadings, but not their bodies.
+`Show all' means show all the buffer's subheadings and their bodies."
(interactive)
(let (has-top-level)
(save-excursion
diff --git a/lisp/paren.el b/lisp/paren.el
index a1f74f2097e..4c268dbf771 100644
--- a/lisp/paren.el
+++ b/lisp/paren.el
@@ -89,11 +89,25 @@ its position."
:type 'boolean)
(defcustom show-paren-context-when-offscreen nil
- "If non-nil, show context in the echo area when the openparen is offscreen.
+ "If non-nil, show context around the opening paren if it is offscreen.
The context is usually the line that contains the openparen,
except if the openparen is on its own line, in which case the
-context includes the previous nonblank line."
- :type 'boolean
+context includes the previous nonblank line.
+
+By default, the context is shown in the echo area.
+
+If set to the symbol `overlay', the context is shown in an
+overlay at the top-left of the window.
+
+If set to the symbol `child-frame', the context is shown in a
+child frame at the top-left of the window. You might want to
+customize the `child-frame-border' face (especially the
+background color) to give the child frame a distinguished border.
+On non-graphical frames, the context is shown in the echo area."
+ :type '(choice (const :tag "Off" nil)
+ (const :tag "In echo area" t)
+ (const :tag "In overlay" overlay)
+ (const :tag "In child-frame" child-frame))
:version "29.1")
(defvar show-paren--idle-timer nil)
@@ -211,6 +225,13 @@ It is the default value of `show-paren-data-function'."
(let* ((temp (show-paren--locate-near-paren))
(dir (car temp))
(outside (cdr temp))
+ ;; If we're inside a comment, then we probably want to blink
+ ;; a matching parentheses in the comment. So don't ignore
+ ;; comments in that case.
+ (parse-sexp-ignore-comments
+ (if (ppss-comment-depth (syntax-ppss))
+ nil
+ parse-sexp-ignore-comments))
pos mismatch here-beg here-end)
;;
;; Find the other end of the sexp.
@@ -260,6 +281,136 @@ It is the default value of `show-paren-data-function'."
(if (= dir 1) pos (1+ pos))
mismatch)))))))
+(defvar show-paren--context-child-frame nil)
+
+(defun show-paren--context-child-frame-redirect-focus ()
+ "Redirect focus from child frame."
+ (redirect-frame-focus
+ show-paren--context-child-frame
+ (frame-parent show-paren--context-child-frame)))
+
+(defun show-paren--context-child-frame-buffer (text)
+ (with-current-buffer
+ (get-buffer-create " *show-paren context*")
+ ;; Redirect focus to parent.
+ (add-hook 'pre-command-hook
+ #'show-paren--delete-context-child-frame
+ nil t)
+ ;; Use an empty keymap.
+ (use-local-map (make-keymap))
+ (dolist (var '((mode-line-format . nil)
+ (header-line-format . nil)
+ (tab-line-format . nil)
+ (tab-bar-format . nil) ;; Emacs 28 tab-bar-format
+ (frame-title-format . "")
+ (truncate-lines . t)
+ (cursor-in-non-selected-windows . nil)
+ (cursor-type . nil)
+ (show-trailing-whitespace . nil)
+ (display-line-numbers . nil)
+ (left-fringe-width . nil)
+ (right-fringe-width . nil)
+ (left-margin-width . 0)
+ (right-margin-width . 0)
+ (fringes-outside-margins . 0)
+ (buffer-read-only . t)))
+ (set (make-local-variable (car var)) (cdr var)))
+ (let ((inhibit-modification-hooks t)
+ (inhibit-read-only t))
+ (erase-buffer)
+ (insert text)
+ (goto-char (point-min)))
+ (current-buffer)))
+
+(defvar show-paren--context-child-frame-parameters
+ `((visibility . nil)
+ (width . 0) (height . 0)
+ (min-width . t) (min-height . t)
+ (no-accept-focus . t)
+ (no-focus-on-map . t)
+ (border-width . 0)
+ (child-frame-border-width . 1)
+ (left-fringe . 0)
+ (right-fringe . 0)
+ (vertical-scroll-bars . nil)
+ (horizontal-scroll-bars . nil)
+ (menu-bar-lines . 0)
+ (tool-bar-lines . 0)
+ (tab-bar-lines . 0)
+ (no-other-frame . t)
+ (no-other-window . t)
+ (no-delete-other-windows . t)
+ (unsplittable . t)
+ (undecorated . t)
+ (cursor-type . nil)
+ (no-special-glyphs . t)
+ (desktop-dont-save . t)))
+
+(defun show-paren--delete-context-child-frame ()
+ (when show-paren--context-child-frame
+ (delete-frame show-paren--context-child-frame)
+ (setq show-paren--context-child-frame nil))
+ (remove-hook 'post-command-hook
+ #'show-paren--delete-context-child-frame))
+
+(defun show-paren--show-context-in-child-frame (text)
+ "Show TEXT in a child-frame at the top-left of the current window."
+ (let ((minibuffer (minibuffer-window (window-frame)))
+ (buffer (show-paren--context-child-frame-buffer text))
+ (x (window-pixel-left))
+ (y (window-pixel-top))
+ (window-min-height 1)
+ (window-min-width 1)
+ after-make-frame-functions)
+ (show-paren--delete-context-child-frame)
+ (setq show-paren--context-child-frame
+ (make-frame
+ `((parent-frame . ,(window-frame))
+ (minibuffer . ,minibuffer)
+ ,@show-paren--context-child-frame-parameters)))
+ (let ((win (frame-root-window show-paren--context-child-frame)))
+ (set-window-buffer win buffer)
+ (set-window-dedicated-p win t)
+ (set-frame-size show-paren--context-child-frame
+ (string-width text)
+ (length (string-lines text)))
+ (set-frame-position show-paren--context-child-frame x y)
+ (make-frame-visible show-paren--context-child-frame)
+ (add-hook 'post-command-hook
+ #'show-paren--delete-context-child-frame))))
+
+(defvar-local show-paren--context-overlay nil)
+
+(defun show-paren--delete-context-overlay ()
+ (when show-paren--context-overlay
+ (delete-overlay show-paren--context-overlay)
+ (setq show-paren--context-overlay nil))
+ (remove-hook 'post-command-hook #'show-paren--delete-overlays
+ 'local))
+
+(defun show-paren--show-context-in-overlay (text)
+ "Show TEXT in an overlay at the top-left of the current window."
+ (setq text (replace-regexp-in-string "\n" " " text))
+ (show-paren--delete-context-overlay)
+ (let* ((beg (window-start))
+ (end (save-excursion
+ (goto-char beg)
+ (line-end-position))))
+ (setq show-paren--context-overlay (make-overlay beg end)))
+ (overlay-put show-paren--context-overlay 'display text)
+ (overlay-put show-paren--context-overlay
+ 'face `(:box
+ ( :line-width (1 . -1)
+ :color ,(face-attribute 'shadow :foreground))))
+ (add-hook 'post-command-hook #'show-paren--delete-context-overlay
+ nil 'local))
+
+;; The last position of point for which `show-paren-function' was
+;; called. We track it in order to C-g away a context overlay or
+;; child-frame without having it pop up again after
+;; `show-paren-delay'.
+(defvar-local show-paren--last-pos nil)
+
(defun show-paren-function ()
"Highlight the parentheses until the next input arrives."
(let ((data (and show-paren-mode (funcall show-paren-data-function))))
@@ -268,7 +419,8 @@ It is the default value of `show-paren-data-function'."
;; If show-paren-mode is nil in this buffer or if not at a paren that
;; has a match, turn off any previous paren highlighting.
(delete-overlay show-paren--overlay)
- (delete-overlay show-paren--overlay-1))
+ (delete-overlay show-paren--overlay-1)
+ (setq show-paren--last-pos (point)))
;; Found something to highlight.
(let* ((here-beg (nth 0 data))
@@ -299,8 +451,8 @@ It is the default value of `show-paren-data-function'."
;; Otherwise, turn off any such highlighting.
(if (or (not here-beg)
(and (not show-paren-highlight-openparen)
- (> here-end (point))
- (<= here-beg (point))
+ (> here-end (point))
+ (<= here-beg (point))
(integerp there-beg)))
(delete-overlay show-paren--overlay-1)
(move-overlay show-paren--overlay-1
@@ -315,24 +467,32 @@ It is the default value of `show-paren-data-function'."
(delete-overlay show-paren--overlay)
(if highlight-expression
(move-overlay show-paren--overlay
- (if (< there-beg here-beg) here-end here-beg)
+ (if (< there-beg here-beg) here-end here-beg)
(if (< there-beg here-beg) there-beg there-end)
(current-buffer))
(move-overlay show-paren--overlay
there-beg there-end (current-buffer)))
- ;; If `show-paren-open-line-when-offscreen' is t and point
- ;; is at a close paren, show the line that contains the
- ;; openparen in the echo area.
+ ;; If `show-paren-context-when-offscreen' is non-nil and
+ ;; point is at a closing paren, show the context around the
+ ;; opening paren.
(let ((openparen (min here-beg there-beg)))
- (if (and show-paren-context-when-offscreen
- (< there-beg here-beg)
- (not (pos-visible-in-window-p openparen)))
- (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)))))
+ (when (and show-paren-context-when-offscreen
+ (not (eql show-paren--last-pos (point)))
+ (< there-beg here-beg)
+ (not (pos-visible-in-window-p openparen)))
+ (let ((context (blink-paren-open-paren-line-string
+ openparen))
+ (message-log-max nil))
+ (cond
+ ((and
+ (eq show-paren-context-when-offscreen 'child-frame)
+ (display-graphic-p))
+ (show-paren--show-context-in-child-frame context))
+ ((eq show-paren-context-when-offscreen 'overlay)
+ (show-paren--show-context-in-overlay context))
+ (show-paren-context-when-offscreen
+ (minibuffer-message "Matches %s" context))))))
+ (setq show-paren--last-pos (point))
;; Always set the overlay face, since it varies.
(overlay-put show-paren--overlay 'priority show-paren-priority)
(overlay-put show-paren--overlay 'face face))))))
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index d0ae9390e31..3c9bf1ec9d2 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -134,7 +134,7 @@ Return the new list."
"Add to TARGETS the list of target names in MAKEFILE and files it includes.
Return the new list."
(with-temp-buffer
- (with-demoted-errors ;Could be a directory or something.
+ (with-demoted-errors "Error inserting makefile: %S"
(insert-file-contents makefile))
(let ((filenames (when pcmpl-gnu-makefile-includes (pcmpl-gnu-make-includes))))
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 289312e0bbc..15b9880df85 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -189,6 +189,16 @@ and how is entirely up to the behavior of the
`pcomplete-parse-arguments-function'."
:type 'boolean)
+(defvar pcomplete-allow-modifications nil
+ "If non-nil, allow effects in `pcomplete-parse-arguments-function'.
+For the `pcomplete' command, it was common for functions in
+`pcomplete-parse-arguments-function' to make modifications to the
+buffer, like expanding variables are such.
+For `completion-at-point-functions', this is not an option any more, so
+this variable is used to tell `pcomplete-parse-arguments-function'
+whether it can do the modifications like it used to, or whether
+it should refrain from doing so.")
+
(defcustom pcomplete-parse-arguments-function
#'pcomplete-parse-buffer-arguments
"A function to call to parse the current line's arguments.
@@ -392,6 +402,9 @@ Same as `pcomplete' but using the standard completion UI."
;; imposing the pcomplete UI over the standard UI.
(catch 'pcompleted
(let* ((pcomplete-stub)
+ (buffer-read-only
+ ;; Make sure the function obeys `pcomplete-allow-modifications'.
+ (if pcomplete-allow-modifications buffer-read-only t))
pcomplete-seen pcomplete-norm-func
pcomplete-args pcomplete-last pcomplete-index
(pcomplete-autolist pcomplete-autolist)
@@ -526,6 +539,7 @@ completion functions list (it should occur fairly early in the list)."
pcomplete-last-completion-raw nil)
(catch 'pcompleted
(let* ((pcomplete-stub)
+ (pcomplete-allow-modifications t)
pcomplete-seen pcomplete-norm-func
pcomplete-args pcomplete-last pcomplete-index
(pcomplete-autolist pcomplete-autolist)
@@ -551,7 +565,8 @@ completion functions list (it should occur fairly early in the list)."
"Expand the textual value of the current argument.
This will modify the current buffer."
(interactive)
- (let ((pcomplete-expand-before-complete t))
+ (let ((pcomplete-expand-before-complete t)
+ (pcomplete-allow-modifications t))
(with-suppressed-warnings ((obsolete pcomplete))
(pcomplete))))
@@ -569,6 +584,7 @@ This will modify the current buffer."
This will modify the current buffer."
(interactive)
(let ((pcomplete-expand-before-complete t)
+ (pcomplete-allow-modifications t)
(pcomplete-expand-only-p t))
(with-suppressed-warnings ((obsolete pcomplete))
(pcomplete))
@@ -786,25 +802,30 @@ this is `comint-dynamic-complete-functions'."
(let ((begin (pcomplete-begin 'last)))
(if (and (listp pcomplete-stub) ;??
(not pcomplete-expand-only-p))
- (let* ((completions pcomplete-stub) ;??
- (common-stub (car completions))
- (c completions)
- (len (length common-stub)))
- (while (and c (> len 0))
- (while (and (> len 0)
- (not (string=
- (substring common-stub 0 len)
- (substring (car c) 0
- (min (length (car c))
- len)))))
- (setq len (1- len)))
- (setq c (cdr c)))
- (setq pcomplete-stub (substring common-stub 0 len)
- pcomplete-autolist t)
- (when (and begin (> len 0) (not pcomplete-show-list))
- (delete-region begin (point))
- (pcomplete-insert-entry "" pcomplete-stub))
- (throw 'pcomplete-completions completions))
+ ;; If `pcomplete-stub' is a list, it means it's a list of
+ ;; completions computed during parsing, e.g. Eshell uses
+ ;; that to turn globs into lists of completions.
+ (if (not pcomplete-allow-modifications)
+ (let ((completions pcomplete-stub))
+ ;; FIXME: The mapping from what's in the buffer to the list
+ ;; of completions can be arbitrary and will often fail to be
+ ;; understood by the completion style. See bug#50470.
+ ;; E.g. `pcomplete-stub' may end up being "~/Down*"
+ ;; while the completions contain entries like
+ ;; "/home/<foo>/Downloads" which will fail to match the
+ ;; "~/Down*" completion pattern since the completion
+ ;; is neither told that it's a file nor a global pattern.
+ (setq pcomplete-stub (buffer-substring begin (point)))
+ (throw 'pcomplete-completions completions))
+ (let* ((completions pcomplete-stub)
+ (common-prefix (try-completion "" completions))
+ (len (length common-prefix)))
+ (setq pcomplete-stub common-prefix
+ pcomplete-autolist t)
+ (when (and begin (> len 0) (not pcomplete-show-list))
+ (delete-region begin (point))
+ (pcomplete-insert-entry "" pcomplete-stub))
+ (throw 'pcomplete-completions completions)))
(when expand-p
(if (stringp pcomplete-stub)
(when begin
diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el
new file mode 100644
index 00000000000..f9532269d62
--- /dev/null
+++ b/lisp/pgtk-dnd.el
@@ -0,0 +1,396 @@
+;;; pgtk-dnd.el --- drag and drop support for GDK -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: window, drag, drop
+;; Package: emacs
+
+;; Significant portions taken from x-dnd.el.
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file provides the receiving side of the GDK drag and drop
+;; mechanism.
+
+;;; Code:
+
+(require 'dnd)
+
+;;; Customizable variables
+(defcustom pgtk-dnd-test-function #'pgtk-dnd-default-test-function
+ "The function drag and drop uses to determine if to accept or reject a drop.
+The function takes three arguments, WINDOW, ACTION and TYPES.
+WINDOW is where the mouse is when the function is called. WINDOW
+may be a frame if the mouse isn't over a real window (i.e. menu
+bar, tool bar or scroll bar). ACTION is the suggested action
+from the drag and drop source, one of the symbols move, copy,
+link or ask. TYPES is a vector of available types for the drop.
+
+Each element of TYPE should either be a string (containing the
+name of the type's X atom), or a symbol, whose name will be used.
+
+The function shall return nil to reject the drop or a cons with
+two values, the wanted action as car and the wanted type as cdr.
+The wanted action can be copy, move, link, ask or private.
+
+The default value for this variable is `pgtk-dnd-default-test-function'."
+ :version "22.1"
+ :type 'symbol
+ :group 'pgtk)
+
+(defcustom pgtk-dnd-types-alist
+ `((,(purecopy "text/uri-list") . pgtk-dnd-handle-uri-list)
+ (,(purecopy "FILE_NAME") . pgtk-dnd-handle-file-name)
+ (,(purecopy "UTF8_STRING") . pgtk-dnd-insert-utf8-text)
+ (,(purecopy "text/plain;charset=UTF-8") . pgtk-dnd-insert-utf8-text)
+ (,(purecopy "text/plain;charset=utf-8") . pgtk-dnd-insert-utf8-text)
+ (,(purecopy "text/plain") . dnd-insert-text)
+ (,(purecopy "COMPOUND_TEXT") . pgtk-dnd-insert-ctext)
+ (,(purecopy "STRING") . dnd-insert-text)
+ (,(purecopy "TEXT") . dnd-insert-text))
+ "Which function to call to handle a drop of that type.
+If the type for the drop is not present, or the function is nil,
+the drop is rejected. The function takes three arguments, WINDOW, ACTION
+and DATA. WINDOW is where the drop occurred, ACTION is the action for
+this drop (copy, move, link, private or ask) as determined by a previous
+call to `pgtk-dnd-test-function'. DATA is the drop data.
+The function shall return the action used (copy, move, link or private)
+if drop is successful, nil if not."
+ :version "22.1"
+ :type 'alist
+ :group 'pgtk)
+
+(defcustom pgtk-dnd-known-types
+ (mapcar 'purecopy '("text/uri-list"
+ "FILE_NAME"
+ "UTF8_STRING"
+ "text/plain;charset=UTF-8"
+ "text/plain;charset=utf-8"
+ "text/plain"
+ "COMPOUND_TEXT"
+ "STRING"
+ "TEXT"))
+ "The types accepted by default for dropped data.
+The types are chosen in the order they appear in the list."
+ :version "22.1"
+ :type '(repeat string)
+ :group 'pgtk)
+
+;; Internal variables
+
+(defvar pgtk-dnd-current-state nil
+ "The current state for a drop.
+This is an alist with one entry for each display. The value for each display
+is a vector that contains the state for drag and drop for that display.
+Elements in the vector are:
+Last buffer drag was in,
+last window drag was in,
+types available for drop,
+the action suggested by the source,
+the type we want for the drop,
+the action we want for the drop,
+any protocol specific data.")
+
+(declare-function pgtk-get-selection-internal "pgtkselect.c")
+(declare-function pgtk-register-dnd-targets "pgtkselect.c")
+
+(defvar pgtk-dnd-empty-state [nil nil nil nil nil nil nil])
+
+(defun pgtk-dnd-init-frame (&optional frame)
+ "Setup drag and drop for FRAME (i.e. create appropriate properties)."
+ (when (eq 'pgtk (window-system frame))
+ (pgtk-register-dnd-targets frame pgtk-dnd-known-types)))
+
+(defun pgtk-dnd-get-state-cons-for-frame (frame-or-window)
+ "Return the entry in `pgtk-dnd-current-state' for a frame or window."
+ (let* ((frame (if (framep frame-or-window) frame-or-window
+ (window-frame frame-or-window)))
+ (display (frame-parameter frame 'display)))
+ (if (not (assoc display pgtk-dnd-current-state))
+ (push (cons display (copy-sequence pgtk-dnd-empty-state))
+ pgtk-dnd-current-state))
+ (assoc display pgtk-dnd-current-state)))
+
+(defun pgtk-dnd-get-state-for-frame (frame-or-window)
+ "Return the state in `pgtk-dnd-current-state' for a frame or window."
+ (cdr (pgtk-dnd-get-state-cons-for-frame frame-or-window)))
+
+(defun pgtk-dnd-default-test-function (_window _action types)
+ "The default test function for drag and drop.
+WINDOW is where the mouse is when this function is called. It may be
+a frame if the mouse is over the menu bar, scroll bar or tool bar.
+ACTION is the suggested action from the source, and TYPES are the
+types the drop data can have. This function only accepts drops with
+types in `pgtk-dnd-known-types'. It always returns the action `copy'."
+ (let ((type (pgtk-dnd-choose-type types)))
+ (when type (cons 'copy type))))
+
+(defun pgtk-dnd-current-type (frame-or-window)
+ "Return the type we want the DND data to be in for the current drop.
+FRAME-OR-WINDOW is the frame or window that the mouse is over."
+ (aref (pgtk-dnd-get-state-for-frame frame-or-window) 4))
+
+(defun pgtk-dnd-forget-drop (frame-or-window)
+ "Remove all state for the last drop.
+FRAME-OR-WINDOW is the frame or window that the mouse is over."
+ (setcdr (pgtk-dnd-get-state-cons-for-frame frame-or-window)
+ (copy-sequence pgtk-dnd-empty-state)))
+
+(defun pgtk-dnd-maybe-call-test-function (window action)
+ "Call `pgtk-dnd-test-function' if something has changed.
+WINDOW is the window the mouse is over. ACTION is the suggested
+action from the source. If nothing has changed, return the last
+action and type we got from `pgtk-dnd-test-function'."
+ (let ((buffer (when (window-live-p window)
+ (window-buffer window)))
+ (current-state (pgtk-dnd-get-state-for-frame window)))
+ (unless (and (equal buffer (aref current-state 0))
+ (equal window (aref current-state 1))
+ (equal action (aref current-state 3)))
+ (save-current-buffer
+ (when buffer (set-buffer buffer))
+ (let* ((action-type (funcall pgtk-dnd-test-function
+ window
+ action
+ (aref current-state 2)))
+ (handler (cdr (assoc (cdr action-type) pgtk-dnd-types-alist))))
+ ;; Ignore action-type if we have no handler.
+ (setq current-state
+ (pgtk-dnd-save-state window
+ action
+ (when handler action-type)))))))
+ (let ((current-state (pgtk-dnd-get-state-for-frame window)))
+ (cons (aref current-state 5)
+ (aref current-state 4))))
+
+(defun pgtk-dnd-save-state (window action action-type &optional types extra-data)
+ "Save the state of the current drag and drop.
+WINDOW is the window the mouse is over. ACTION is the action suggested
+by the source. ACTION-TYPE is the result of calling `pgtk-dnd-test-function'.
+If given, TYPES are the types for the drop data that the source supports.
+EXTRA-DATA is data needed for a specific protocol."
+ (let ((current-state (pgtk-dnd-get-state-for-frame window)))
+ (aset current-state 5 (car action-type))
+ (aset current-state 4 (cdr action-type))
+ (aset current-state 3 action)
+ (when types (aset current-state 2 types))
+ (when extra-data (aset current-state 6 extra-data))
+ (aset current-state 1 window)
+ (aset current-state 0 (and (window-live-p window) (window-buffer window)))
+ (setcdr (pgtk-dnd-get-state-cons-for-frame window) current-state)))
+
+
+(defun pgtk-dnd-handle-moz-url (window action data)
+ "Handle one item of type text/x-moz-url.
+WINDOW is the window where the drop happened. ACTION is ignored.
+DATA is the moz-url, which is formatted as two strings separated by \\r\\n.
+The first string is the URL, the second string is the title of that URL.
+DATA is encoded in utf-16. Decode the URL and call `pgtk-dnd-handle-uri-list'."
+ ;; Mozilla and applications based on it use text/unicode, but it is
+ ;; impossible to tell if it is le or be. Use what the machine Emacs
+ ;; runs on uses. This loses if dropping between machines
+ ;; with different endian-ness, but it is the best we can do.
+ (let* ((coding (if (eq (byteorder) ?B) 'utf-16be 'utf-16le))
+ (string (decode-coding-string data coding))
+ (strings (split-string string "[\r\n]" t))
+ ;; Can one drop more than one moz-url ?? Assume not.
+ (url (car strings)))
+ (pgtk-dnd-handle-uri-list window action url)))
+
+(defun pgtk-dnd-insert-utf8-text (window action text)
+ "Decode the UTF-8 text and insert it at point.
+TEXT is the text as a string, WINDOW is the window where the drop happened."
+ (dnd-insert-text window action (decode-coding-string text 'utf-8)))
+
+(defun pgtk-dnd-insert-utf16-text (window action text)
+ "Decode the UTF-16 text and insert it at point.
+TEXT is the text as a string, WINDOW is the window where the drop happened."
+ ;; See comment in pgtk-dnd-handle-moz-url about coding.
+ (let ((coding (if (eq (byteorder) ?B) 'utf-16be 'utf-16le)))
+ (dnd-insert-text window action (decode-coding-string text coding))))
+
+(defun pgtk-dnd-insert-ctext (window action text)
+ "Decode the compound text and insert it at point.
+TEXT is the text as a string, WINDOW is the window where the drop happened."
+ (dnd-insert-text window action
+ (decode-coding-string text
+ 'compound-text-with-extensions)))
+
+(defun pgtk-dnd-handle-uri-list (window action string)
+ "Split an uri-list into separate URIs and call `dnd-handle-one-url'.
+WINDOW is the window where the drop happened.
+STRING is the uri-list as a string. The URIs are separated by \\r\\n."
+ (let ((uri-list (split-string string "[\0\r\n]" t))
+ retval)
+ (dolist (bf uri-list)
+ ;; If one URL is handled, treat as if the whole drop succeeded.
+ (let ((did-action (dnd-handle-one-url window action bf)))
+ (when did-action (setq retval did-action))))
+ retval))
+
+(defun pgtk-dnd-handle-file-name (window action string)
+ "Convert file names to URLs and call `dnd-handle-one-url'.
+WINDOW is the window where the drop happened.
+STRING is the file names as a string, separated by nulls."
+ (let ((uri-list (split-string string "[\0\r\n]" t))
+ (coding (or file-name-coding-system
+ default-file-name-coding-system))
+ retval)
+ (dolist (bf uri-list)
+ ;; If one URL is handled, treat as if the whole drop succeeded.
+ (if coding (setq bf (encode-coding-string bf coding)))
+ (let* ((file-uri (concat "file://"
+ (mapconcat 'url-hexify-string
+ (split-string bf "/") "/")))
+ (did-action (dnd-handle-one-url window action file-uri)))
+ (when did-action (setq retval did-action))))
+ retval))
+
+
+(defun pgtk-dnd-choose-type (types &optional known-types)
+ "Choose which type we want to receive for the drop.
+TYPES are the types the source of the drop offers, a vector of type names
+as strings or symbols. Select among the types in `pgtk-dnd-known-types' or
+KNOWN-TYPES if given, and return that type name.
+If no suitable type is found, return nil."
+ (let* ((known-list (or known-types pgtk-dnd-known-types))
+ (first-known-type (car known-list))
+ (types-array types)
+ (found (when first-known-type
+ (catch 'done
+ (dotimes (i (length types-array))
+ (let* ((type (aref types-array i))
+ (typename (if (symbolp type)
+ (symbol-name type) type)))
+ (when (equal first-known-type typename)
+ (throw 'done first-known-type))))
+ nil))))
+
+ (if (and (not found) (cdr known-list))
+ (pgtk-dnd-choose-type types (cdr known-list))
+ found)))
+
+(defun pgtk-dnd-drop-data (event frame window data type)
+ "Drop one data item onto a frame.
+EVENT is the client message for the drop, FRAME is the frame the drop
+occurred on. WINDOW is the window of FRAME where the drop happened.
+DATA is the data received from the source, and type is the type for DATA,
+see `pgtk-dnd-types-alist').
+
+Returns the action used (move, copy, link, private) if drop was successful,
+nil if not."
+ (let* ((type-info (assoc type pgtk-dnd-types-alist))
+ (handler (cdr type-info))
+ (state (pgtk-dnd-get-state-for-frame frame))
+ (action (aref state 5))
+ (w (posn-window (event-start event))))
+ (when handler
+ (if (and (window-live-p w)
+ (not (window-minibuffer-p w))
+ (not (window-dedicated-p w)))
+ ;; If dropping in an ordinary window which we could use,
+ ;; let dnd-open-file-other-window specify what to do.
+ (progn
+ (when (and (not mouse-yank-at-point)
+ ;; If dropping on top of the mode line, insert
+ ;; the text at point instead.
+ (posn-point (event-start event)))
+ (goto-char (posn-point (event-start event))))
+ (funcall handler window action data))
+ ;; If we can't display the file here,
+ ;; make a new window for it.
+ (let ((dnd-open-file-other-window t))
+ (select-frame frame)
+ (funcall handler window action data))))))
+
+(defun pgtk-dnd-handle-drag-n-drop-event (event)
+ "Receive drag and drop events (X client messages).
+Currently XDND, Motif and old KDE 1.x protocols are recognized."
+ (interactive "e")
+ (let* ((client-message (car (cdr (cdr event))))
+ (window (posn-window (event-start event)))
+ (frame (if (framep window)
+ window
+ (window-frame window))))
+ (pgtk-dnd-handle-gdk event frame window client-message)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; GDK protocol.
+
+(declare-function pgtk-update-drop-status "pgtkselect.c")
+(declare-function pgtk-drop-finish "pgtkselect.c")
+
+(defun pgtk-dnd-handle-gdk (event frame window client-message)
+ "Handle drag-n-drop EVENT on FRAME.
+WINDOW should be the window the event happened on top of.
+CLIENT-MESSAGE is the detailed description of the drag-and-drop
+message."
+ (cond
+ ;; We can't handle `drag-leave' here, since that signal is also
+ ;; sent right before `drag-drop', and there is no reliable way to
+ ;; distinguish the two.
+ ((eq (car client-message) 'lambda) ; drag-motion
+ (let ((state (pgtk-dnd-get-state-for-frame frame)))
+ (unless (aref state 0) ;; This is actually an entry.
+ (pgtk-dnd-save-state window nil nil
+ (pgtk-get-selection-internal
+ (nth 1 client-message) 'TARGETS)
+ t)
+ (setq state (pgtk-dnd-get-state-for-frame frame)))
+ (let* ((action (nth 3 client-message))
+ (time (nth 2 client-message))
+ (action-type (pgtk-dnd-maybe-call-test-function window
+ action)))
+ ;; Get the selection contents now. GdkWaylandSelection
+ ;; becomes unavailable immediately after `drag-drop' is sent.
+ (let* ((current-type (pgtk-dnd-current-type window))
+ (current-action-type (car-safe (aref state 6))))
+ (when (and current-type
+ (not (equal current-action-type action-type)))
+ (aset state 6 (cons action-type
+ (pgtk-get-selection-internal
+ (nth 1 client-message)
+ (intern current-type))))))
+ (pgtk-update-drop-status (car action-type) time)
+ (dnd-handle-movement (event-start event)))))
+ ((eq (car client-message) 'quote) ; drag-drop
+ (let* ((state (pgtk-dnd-get-state-for-frame frame))
+ (timestamp (nth 2 client-message))
+ (value (and (pgtk-dnd-current-type window)
+ (or (cdr-safe (aref state 6))
+ (pgtk-get-selection-internal
+ (nth 1 client-message)
+ (intern (pgtk-dnd-current-type window))
+ timestamp))))
+ action)
+ (unwind-protect
+ (setq action (when value
+ (condition-case info
+ (pgtk-dnd-drop-data
+ event frame window value
+ (pgtk-dnd-current-type window))
+ (error
+ (message "Error: %s" info)
+ nil))))
+ (pgtk-drop-finish action timestamp (eq action 'move))
+ (pgtk-dnd-forget-drop window))))))
+
+(provide 'pgtk-dnd)
+
+;;; pgtk-dnd.el ends here
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el
index e8b637ba1a1..fc7e680c262 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -32,8 +32,10 @@
;;; Commentary:
-;; This package offers a global minor mode which makes mouse-wheel
-;; scroll a line smoothly.
+;; This file contains two somewhat related features.
+
+;; The first is a global minor mode which makes Emacs try to scroll
+;; each line smoothly.
;;
;; Scrolling a line up by `set-window-vscroll' and that by `scroll-up'
;; give similar display as shown below.
@@ -58,6 +60,25 @@
;; (set-window-vscroll nil vs t) (sit-for 0))
;; (scroll-up 1)
+;; The second is another global minor mode that redefines `wheel-up'
+;; and `wheel-down' to a command that tries to scroll the display
+;; according to the precise movement of a trackpad or mouse.
+
+;; But it operates in a much more intelligent manner than simply
+;; setting the vscroll. It will set window start to the position
+;; closest to the position at the top-left corner of the window if
+;; vscroll were set accordingly, in a smart and fast manner, and only
+;; set vscroll the rest of the way. There is no visible difference,
+;; but it is much faster, and doesn't move the display by a huge
+;; portion if vscroll is reset for some reason.
+
+;; It also tries to move point out of the way, so redisplay will not
+;; recenter the display as it scrolls. This works well almost all of
+;; the time, but is impossible to get right with images larger than
+;; the window they're displayed in. A feature that will allow
+;; redisplay to skip recentering is in the works, and will completely
+;; resolve this problem.
+
;;; Todo:
;;
;; Allowing pixel-level scrolling in Emacs requires a thorough review
@@ -69,6 +90,7 @@
(require 'mwheel)
(require 'subr-x)
(require 'ring)
+(require 'cua-base)
(defvar pixel-wait 0
"Idle time on each step of pixel scroll specified in second.
@@ -108,6 +130,9 @@ is always with pixel resolution.")
(define-key map [vertical-scroll-bar wheel-down] 'pixel-scroll-precision)
(define-key map [vertical-scroll-bar wheel-up] 'pixel-scroll-precision)
(define-key map [vertical-scroll-bar touch-end] 'pixel-scroll-start-momentum)
+ (define-key map [tool-bar wheel-down] 'pixel-scroll-precision)
+ (define-key map [tool-bar wheel-up] 'pixel-scroll-precision)
+ (define-key map [tool-bar touch-end] 'pixel-scroll-start-momentum)
(define-key map [left-margin wheel-down] 'pixel-scroll-precision)
(define-key map [left-margin wheel-up] 'pixel-scroll-precision)
(define-key map [left-margin touch-end] 'pixel-scroll-start-momentum)
@@ -189,6 +214,14 @@ This is only effective when `pixel-scroll-precision-mode' is enabled."
:type 'boolean
:version "29.1")
+(defcustom pixel-scroll-precision-interpolate-mice t
+ "Whether or not to interpolate scrolling from a mouse.
+If non-nil, scrolling from the mouse wheel of an actual mouse (as
+opposed to a touchpad) will cause Emacs to interpolate the scroll."
+ :group 'scrolling
+ :type 'boolean
+ :version "29.1")
+
(defun pixel-scroll-in-rush-p ()
"Return non-nil if next scroll should be non-smooth.
When scrolling request is delivered soon after the previous one,
@@ -514,7 +547,7 @@ the height of the current window."
(beginning-of-visual-line)
(point)))
t)
- (set-window-vscroll nil desired-vscroll t)))
+ (set-window-vscroll nil desired-vscroll t t)))
(defun pixel-scroll-precision-scroll-down (delta)
"Scroll the current window down by DELTA pixels."
@@ -553,7 +586,7 @@ the height of the current window."
(goto-char up-point)))
(let ((current-vscroll (window-vscroll nil t)))
(setq delta (- delta current-vscroll))
- (set-window-vscroll nil 0 t)
+ (set-window-vscroll nil 0 t t)
(when (> delta 0)
(let* ((start (window-start))
(dims (window-text-pixel-size nil (cons start (- delta))
@@ -569,12 +602,13 @@ the height of the current window."
(signal 'beginning-of-buffer nil))
(setq delta (- delta height))))
(when (< delta 0)
- (set-window-vscroll nil (- delta) t)))))
+ (set-window-vscroll nil (- delta) t t)))))
-(defun pixel-scroll-precision-interpolate (delta)
+(defun pixel-scroll-precision-interpolate (delta &optional old-window)
"Interpolate a scroll of DELTA pixels.
-This results in the window being scrolled by DELTA pixels with an
-animation."
+OLD-WINDOW is the window which will be selected when redisplay
+takes place, or nil for the current window. This results in the
+window being scrolled by DELTA pixels with an animation."
(let ((percentage 0)
(total-time pixel-scroll-precision-interpolation-total-time)
(factor pixel-scroll-precision-interpolation-factor)
@@ -592,7 +626,9 @@ animation."
(while-no-input
(unwind-protect
(while (< percentage 1)
- (redisplay t)
+ (with-selected-window (or old-window
+ (selected-window))
+ (redisplay t))
(sleep-for between-scroll)
(setq time-elapsed (+ time-elapsed
(- (float-time) last-time))
@@ -643,28 +679,35 @@ Move the display up or down by the pixel deltas in EVENT to
scroll the display according to the user's turning the mouse
wheel."
(interactive "e")
- (let ((window (mwheel-event-window event)))
+ (let ((window (mwheel-event-window event))
+ (current-window (selected-window)))
+ (when (framep window)
+ (setq window (frame-selected-window window)))
(if (and (nth 4 event))
(let ((delta (round (cdr (nth 4 event)))))
(unless (zerop delta)
(if (> (abs delta) (window-text-height window t))
(mwheel-scroll event nil)
(with-selected-window window
- (if (and pixel-scroll-precision-large-scroll-height
- (> (abs delta)
- pixel-scroll-precision-large-scroll-height)
- (let* ((kin-state (pixel-scroll-kinetic-state))
- (ring (aref kin-state 0))
- (time (aref kin-state 1)))
- (or (null time)
- (> (- (float-time) time) 1.0)
- (and (consp ring)
- (ring-empty-p ring)))))
+ (if (or (and pixel-scroll-precision-interpolate-mice
+ (eq (device-class last-event-frame
+ last-event-device)
+ 'mouse))
+ (and pixel-scroll-precision-large-scroll-height
+ (> (abs delta)
+ pixel-scroll-precision-large-scroll-height)
+ (let* ((kin-state (pixel-scroll-kinetic-state))
+ (ring (aref kin-state 0))
+ (time (aref kin-state 1)))
+ (or (null time)
+ (> (- (float-time) time) 1.0)
+ (and (consp ring)
+ (ring-empty-p ring))))))
(progn
(let ((kin-state (pixel-scroll-kinetic-state)))
(aset kin-state 0 (make-ring 30))
(aset kin-state 1 nil))
- (pixel-scroll-precision-interpolate delta))
+ (pixel-scroll-precision-interpolate delta current-window))
(condition-case nil
(progn
(if (< delta 0)
@@ -678,11 +721,12 @@ wheel."
(message (error-message-string '(end-of-buffer))))))))))
(mwheel-scroll event nil))))
-(defun pixel-scroll-kinetic-state ()
- "Return the kinetic scroll state of the current window.
+(defun pixel-scroll-kinetic-state (&optional window)
+ "Return the kinetic scroll state of WINDOW.
+If WINDOW is nil, return the state of the current window.
It is a vector of the form [ VELOCITY TIME SIGN ]."
- (or (window-parameter nil 'kinetic-state)
- (set-window-parameter nil 'kinetic-state
+ (or (window-parameter window 'kinetic-state)
+ (set-window-parameter window 'kinetic-state
(vector (make-ring 30) nil nil))))
(defun pixel-scroll-accumulate-velocity (delta)
@@ -716,67 +760,70 @@ It is a vector of the form [ VELOCITY TIME SIGN ]."
(when pixel-scroll-precision-use-momentum
(let ((window (mwheel-event-window event))
(state nil))
- (with-selected-window window
- (setq state (pixel-scroll-kinetic-state))
- (when (and (aref state 1)
- (listp (aref state 0)))
- (condition-case nil
- (while-no-input
- (unwind-protect (progn
- (aset state 0 (pixel-scroll-calculate-velocity state))
- (when (> (abs (aref state 0))
- pixel-scroll-precision-momentum-min-velocity)
- (let* ((velocity (aref state 0))
- (original-velocity velocity)
- (time-spent 0))
- (if (> velocity 0)
- (while (and (> velocity 0)
- (<= time-spent
- pixel-scroll-precision-momentum-seconds))
- (when (> (round velocity) 0)
- (pixel-scroll-precision-scroll-up (round velocity)))
- (setq velocity (- velocity
- (/ original-velocity
- (/ pixel-scroll-precision-momentum-seconds
- pixel-scroll-precision-momentum-tick))))
- (redisplay t)
- (sit-for pixel-scroll-precision-momentum-tick)
- (setq time-spent (+ time-spent
- pixel-scroll-precision-momentum-tick))))
- (while (and (< velocity 0)
- (<= time-spent
- pixel-scroll-precision-momentum-seconds))
- (when (> (round (abs velocity)) 0)
+ (when (framep window)
+ (setq window (frame-selected-window window)))
+ (setq state (pixel-scroll-kinetic-state window))
+ (when (and (aref state 1)
+ (listp (aref state 0)))
+ (condition-case nil
+ (while-no-input
+ (unwind-protect (progn
+ (aset state 0 (pixel-scroll-calculate-velocity state))
+ (when (> (abs (aref state 0))
+ pixel-scroll-precision-momentum-min-velocity)
+ (let* ((velocity (aref state 0))
+ (original-velocity velocity)
+ (time-spent 0))
+ (if (> velocity 0)
+ (while (and (> velocity 0)
+ (<= time-spent
+ pixel-scroll-precision-momentum-seconds))
+ (when (> (round velocity) 0)
+ (with-selected-window window
+ (pixel-scroll-precision-scroll-up (round velocity))))
+ (setq velocity (- velocity
+ (/ original-velocity
+ (/ pixel-scroll-precision-momentum-seconds
+ pixel-scroll-precision-momentum-tick))))
+ (redisplay t)
+ (sit-for pixel-scroll-precision-momentum-tick)
+ (setq time-spent (+ time-spent
+ pixel-scroll-precision-momentum-tick))))
+ (while (and (< velocity 0)
+ (<= time-spent
+ pixel-scroll-precision-momentum-seconds))
+ (when (> (round (abs velocity)) 0)
+ (with-selected-window window
(pixel-scroll-precision-scroll-down (round
- (abs velocity))))
- (setq velocity (+ velocity
- (/ (abs original-velocity)
- (/ pixel-scroll-precision-momentum-seconds
- pixel-scroll-precision-momentum-tick))))
- (redisplay t)
- (sit-for pixel-scroll-precision-momentum-tick)
- (setq time-spent (+ time-spent
- pixel-scroll-precision-momentum-tick))))))
- (aset state 0 (make-ring 30))
- (aset state 1 nil)))
- (beginning-of-buffer
- (message (error-message-string '(beginning-of-buffer))))
- (end-of-buffer
- (message (error-message-string '(end-of-buffer))))))))))
+ (abs velocity)))))
+ (setq velocity (+ velocity
+ (/ (abs original-velocity)
+ (/ pixel-scroll-precision-momentum-seconds
+ pixel-scroll-precision-momentum-tick))))
+ (redisplay t)
+ (sit-for pixel-scroll-precision-momentum-tick)
+ (setq time-spent (+ time-spent
+ pixel-scroll-precision-momentum-tick))))))
+ (aset state 0 (make-ring 30))
+ (aset state 1 nil)))
+ (beginning-of-buffer
+ (message (error-message-string '(beginning-of-buffer))))
+ (end-of-buffer
+ (message (error-message-string '(end-of-buffer)))))))))
(defun pixel-scroll-interpolate-down ()
"Interpolate a scroll downwards by one page."
(interactive)
(if pixel-scroll-precision-interpolate-page
(pixel-scroll-precision-interpolate (- (window-text-height nil t)))
- (scroll-up)))
+ (cua-scroll-up)))
(defun pixel-scroll-interpolate-up ()
"Interpolate a scroll upwards by one page."
(interactive)
(if pixel-scroll-precision-interpolate-page
(pixel-scroll-precision-interpolate (window-text-height nil t))
- (scroll-down)))
+ (cua-scroll-down)))
;;;###autoload
(define-minor-mode pixel-scroll-precision-mode
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
index 7f821bf4cf4..bb3369de5fc 100644
--- a/lisp/play/decipher.el
+++ b/lisp/play/decipher.el
@@ -978,13 +978,14 @@ if it can't, it signals an error."
decipher-stats-buffer)
;; Create a new buffer if requested:
(create
- (let ((stats-name (concat "*" (buffer-name) "*")))
+ (let* ((stats-name (concat "*" (buffer-name) "*"))
+ (buf (get-buffer stats-name)))
(setq decipher-stats-buffer
- (if (eq 'decipher-stats-mode
- (buffer-local-value 'major-mode
- (get-buffer stats-name)))
- ;; We just lost track of the statistics buffer:
- (get-buffer stats-name)
+ (if (and (bufferp buf)
+ (eq 'decipher-stats-mode
+ (buffer-local-value 'major-mode buf)))
+ buf
+ ;; We just lost track of the statistics buffer:
(generate-new-buffer stats-name))))
(with-current-buffer decipher-stats-buffer
(decipher-stats-mode))
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
index 07f27374df7..b859176bb47 100644
--- a/lisp/play/dunnet.el
+++ b/lisp/play/dunnet.el
@@ -898,7 +898,7 @@ Regular objects have whole numbers lower than 255.
Objects that cannot be taken but might move and are
described during room description are negative.
Stuff that is described and might change are 255, and are
-handled specially by 'dun-describe-room.")
+handled specially by `dun-describe-room'.")
(defconst dun-room-silents (list nil
(list obj-tree obj-coconut) ;; dead-end
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index 256b4e19ce8..7a850b07ee4 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -343,11 +343,17 @@ format."
(gamegrid-colorize-glyph color))
((listp data)
(find-image data)) ;untested!
- ((vectorp data)
- (gamegrid-make-image-from-vector data)))))
+ ;; Remove when `gamegrid-make-image-from-vector' is removed:
+ ((vectorp data)
+ (lwarn 'gamegrid :warning
+ "Using obsolete XEmacs style \"glyph\"; \
+convert to an Emacs image-spec instead")
+ (with-suppressed-warnings ((obsolete gamegrid-make-image-from-vector))
+ (gamegrid-make-image-from-vector data))))))
(defun gamegrid-make-image-from-vector (vect)
"Convert an XEmacs style \"glyph\" to an image-spec."
+ (declare (obsolete nil "29.1"))
(let ((l (list 'image :type)))
(dotimes (n (length vect))
(setf l (nconc l (list (aref vect n)))))
@@ -452,6 +458,7 @@ format."
;; Adjust the height of the default face to the height of the
;; images. Unlike XEmacs, Emacs doesn't allow making the default
;; face buffer-local; so we do this with an overlay.
+ ;; FIXME: This is not correct. See face-remap.el.
(when (eq gamegrid-display-mode 'glyph)
(overlay-put (make-overlay (point-min) (point-max))
'face gamegrid-face))
diff --git a/lisp/play/handwrite.el b/lisp/play/handwrite.el
index 14624ddce23..68a82f5a9ef 100644
--- a/lisp/play/handwrite.el
+++ b/lisp/play/handwrite.el
@@ -1,6 +1,6 @@
;;; handwrite.el --- turns your emacs buffer into a handwritten document -*- lexical-binding: t -*-
-;; Copyright (C) 1996, 2001-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2022 Free Software Foundation, Inc.
;; Author: Danny Roozendaal (was: <danny@tvs.kun.nl>)
;; Maintainer: emacs-devel@gnu.org
@@ -29,44 +29,42 @@
;;
;; Other functions that may be useful are:
;;
-;; handwrite-10pt: sets the font size to 10 and finds corresponding
-;; values for the line spacing and the number of lines
-;; on a page.
-;; handwrite-11pt: which is similar
-;; handwrite-12pt: which is also similar
-;; handwrite-13pt: which is similar, too
+;; `handwrite-10pt': set the font size to 10 and find corresponding
+;; values for the line spacing and the number of lines
+;; on a page.
+;; `handwrite-11pt': which is similar
+;; `handwrite-12pt': which is also similar
+;; `handwrite-13pt': which is similar, too
;;
-;; handwrite-set-pagenumber: set and unset page numbering
+;; `handwrite-set-pagenumber': set and unset page numbering
;;
;;
;; If you are not satisfied with the type page there are a number of
;; variables you may want to set.
;;
-;; To use this, say "M-x handwrite" or type at your prompt
+;; To use this, say `M-x handwrite' or type at your prompt
;; "emacs -l handwrite.el".
;;
;; I tried to make it `iso_8859_1'-friendly, but there are some exotic
;; characters missing.
;;
;;
-;; Known bugs: -Page feeds do not do their work, but are ignored instead.
-;; -Tabs are not always properly displayed.
-;; -Handwrite may create corrupt PostScript if it encounters
-;; unknown characters.
+;; Known bugs:
+;; - Page feeds do not work, and are ignored instead.
+;; - Tabs are not always properly displayed.
+;; - Handwrite may create corrupt PostScript if it encounters
+;; unknown characters.
;;
;; Thanks to anyone who emailed me suggestions!
;;; Code:
-;; From ps-print.el
-(defvar ps-printer-name)
-(defvar ps-lpr-command)
-(defvar ps-lpr-switches)
+(require 'ps-print)
;; Variables
(defgroup handwrite nil
- "Turns your Emacs buffer into a handwritten document."
+ "Turn your Emacs buffer into a handwritten document."
:prefix "handwrite-"
:group 'games)
@@ -235,20 +233,13 @@ Variables: `handwrite-linespace' (default 12)
(while (search-forward "\f" nil t)
(replace-match "" nil t) )
(untabify textp (point-max)) ; this may result in strange tabs
- (if (y-or-n-p "Send this to the printer? ")
- (progn
- (require 'ps-print)
- (let* ((coding-system-for-write 'raw-text-unix)
- (ps-printer-name (or ps-printer-name
- (and (boundp 'printer-name)
- printer-name)))
- (ps-lpr-switches
- (if (stringp ps-printer-name)
- (list (concat "-P" ps-printer-name)))))
- (apply (or (and (boundp 'ps-print-region-function)
- ps-print-region-function)
- 'call-process-region)
- (point-min) (point-max) ps-lpr-command nil nil nil))))
+ (when (y-or-n-p "Send this to the printer? ")
+ (let* ((coding-system-for-write 'raw-text-unix)
+ (printer-name (or ps-printer-name printer-name))
+ (lpr-printer-switch ps-printer-name-option)
+ (print-region-function ps-print-region-function)
+ (lpr-command ps-lpr-command))
+ (lpr-print-region (point-min) (point-max) ps-lpr-switches nil)))
(message "")
(bury-buffer ())
(switch-to-buffer cur-buf)
@@ -264,8 +255,8 @@ Variables: `handwrite-linespace' (default 12)
(defun handwrite-10pt ()
"Specify 10-point output for `handwrite'.
-This sets `handwrite-fontsize' to 10 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'."
+Set `handwrite-fontsize' to 10 and find correct values for
+`handwrite-linespace' and `handwrite-numlines'."
(interactive)
(setq handwrite-fontsize 10)
(setq handwrite-linespace 11)
@@ -274,8 +265,8 @@ values for `handwrite-linespace' and `handwrite-numlines'."
(defun handwrite-11pt ()
"Specify 11-point output for `handwrite'.
-This sets `handwrite-fontsize' to 11 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'."
+Set `handwrite-fontsize' to 11 and find correct values for
+`handwrite-linespace' and `handwrite-numlines'."
(interactive)
(setq handwrite-fontsize 11)
(setq handwrite-linespace 12)
@@ -284,8 +275,8 @@ values for `handwrite-linespace' and `handwrite-numlines'."
(defun handwrite-12pt ()
"Specify 12-point output for `handwrite'.
-This sets `handwrite-fontsize' to 12 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'."
+Set `handwrite-fontsize' to 12 and find correct values for
+`handwrite-linespace' and `handwrite-numlines'."
(interactive)
(setq handwrite-fontsize 12)
(setq handwrite-linespace 13)
@@ -294,8 +285,8 @@ values for `handwrite-linespace' and `handwrite-numlines'."
(defun handwrite-13pt ()
"Specify 13-point output for `handwrite'.
-This sets `handwrite-fontsize' to 13 and finds correct
-values for `handwrite-linespace' and `handwrite-numlines'."
+Set `handwrite-fontsize' to 13 and find correct values for
+`handwrite-linespace' and `handwrite-numlines'."
(interactive)
(setq handwrite-fontsize 13)
(setq handwrite-linespace 14)
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
index 974e9fbc49c..5b7d343a79e 100644
--- a/lisp/play/morse.el
+++ b/lisp/play/morse.el
@@ -1,6 +1,6 @@
;;; morse.el --- convert text to morse code and back -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2022 Free Software Foundation, Inc.
;; Author: Rick Farnbach <rick_farnbach@MENTORG.COM>
;; Keywords: games
@@ -22,11 +22,11 @@
;;; Commentary:
-;; Converts text to Morse code and back with M-x morse-region and
-;; M-x unmorse-region (though Morse code is no longer official :-().
+;; Convert plain text to Morse code and back with `M-x morse-region' and
+;; `M-x unmorse-region'.
-;; Converts text to NATO phonetic alphabet and back with M-x
-;; nato-region and M-x denato-region.
+;; Convert plain text to NATO spelling alphabet and back with
+;; `M-x nato-region' and `M-x denato-region'.
;;; Code:
@@ -142,14 +142,16 @@
("(" . "Open")
(")" . "Close")
("@" . "At"))
- "NATO phonetic alphabet.
+ "NATO spelling alphabet.
See “International Code of Signals” (INTERCO), United States
Edition, 1969 Edition (Revised 2003) available from National
-Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
+Geospatial-Intelligence Agency at <https://www.nga.mil/>.
+See also <https://en.wikipedia.org/wiki/NATO_phonetic_alphabet>.")
;;;###autoload
(defun morse-region (beg end)
- "Convert all text in a given region to morse code."
+ "Convert plain text in region to Morse code.
+See <https://en.wikipedia.org/wiki/Morse_code>."
(interactive "*r")
(if (integerp end)
(setq end (copy-marker end)))
@@ -172,7 +174,7 @@ Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
;;;###autoload
(defun unmorse-region (beg end)
- "Convert morse coded text in region to ordinary ASCII text."
+ "Convert Morse coded text in region to plain text."
(interactive "*r")
(if (integerp end)
(setq end (copy-marker end)))
@@ -194,7 +196,7 @@ Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
;;;###autoload
(defun nato-region (beg end)
- "Convert all text in a given region to NATO phonetic alphabet."
+ "Convert plain text in region to NATO spelling alphabet."
;; Copied from morse-region. -- ashawley 2009-02-10
(interactive "*r")
(if (integerp end)
@@ -218,7 +220,7 @@ Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
;;;###autoload
(defun denato-region (beg end)
- "Convert NATO phonetic alphabet in region to ordinary ASCII text."
+ "Convert NATO spelling alphabet text in region to plain text."
;; Copied from unmorse-region. -- ashawley 2009-02-10
(interactive "*r")
(if (integerp end)
diff --git a/lisp/play/spook.el b/lisp/play/spook.el
index f2bdba1c2aa..ccff2e75b0a 100644
--- a/lisp/play/spook.el
+++ b/lisp/play/spook.el
@@ -49,7 +49,7 @@
(defcustom spook-phrase-default-count 15
"Default number of phrases to insert."
- :type 'integer)
+ :type 'natnum)
;;;###autoload
(defun spook ()
diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el
index 8ce2453c753..a6bfea81ee1 100644
--- a/lisp/play/tetris.el
+++ b/lisp/play/tetris.el
@@ -95,27 +95,34 @@ If the return value is a number, it is used as the timer period."
(defcustom tetris-buffer-width 30
"Width of used portion of buffer."
- :type 'number)
+ :type 'natnum)
(defcustom tetris-buffer-height 22
"Height of used portion of buffer."
- :type 'number)
+ :type 'natnum)
(defcustom tetris-width 10
"Width of playing area."
- :type 'number)
+ :type 'natnum)
(defcustom tetris-height 20
"Height of playing area."
- :type 'number)
+ :type 'natnum)
(defcustom tetris-top-left-x 3
"X position of top left of playing area."
- :type 'number)
+ :type 'natnum)
(defcustom tetris-top-left-y 1
"Y position of top left of playing area."
- :type 'number)
+ :type 'natnum)
+
+(defcustom tetris-allow-repetitions t
+ "If non-nil, use a random selection for each shape.
+If nil, put the shapes into a bag and select without putting
+back (until empty, when the bag is repopulated."
+ :type 'boolean
+ :version "29.1")
(defvar tetris-next-x (+ (* 2 tetris-top-left-x) tetris-width)
"X position of next shape.")
@@ -233,6 +240,7 @@ each one of its four blocks.")
(defvar-local tetris-pos-x 0)
(defvar-local tetris-pos-y 0)
(defvar-local tetris-paused nil)
+(defvar-local tetris--bag nil)
;; ;;;;;;;;;;;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -341,10 +349,23 @@ each one of its four blocks.")
(let ((period (tetris-get-tick-period)))
(if period (gamegrid-set-timer period))))
+(defun tetris--shuffle (sequence)
+ (cl-loop for i from (length sequence) downto 2
+ do (cl-rotatef (elt sequence (random i))
+ (elt sequence (1- i))))
+ sequence)
+
+(defun tetris--seven-bag ()
+ (when (not tetris--bag)
+ (setq tetris--bag (tetris--shuffle (list 0 1 2 3 4 5 6))))
+ (pop tetris--bag))
+
(defun tetris-new-shape ()
(setq tetris-shape tetris-next-shape)
(setq tetris-rot 0)
- (setq tetris-next-shape (random 7))
+ (setq tetris-next-shape (if tetris-allow-repetitions
+ (random 7)
+ (tetris--seven-bag)))
(setq tetris-pos-x (/ (- tetris-width (tetris-shape-width)) 2))
(setq tetris-pos-y 0)
(if (tetris-test-shape)
diff --git a/lisp/plstore.el b/lisp/plstore.el
index b37d39ce1b1..de3f828016a 100644
--- a/lisp/plstore.el
+++ b/lisp/plstore.el
@@ -107,6 +107,7 @@ symmetric encryption will be used."
:type '(choice (const nil) (repeat :tag "Recipient(s)" string))
:group 'plstore)
+;;;###autoload
(put 'plstore-encrypt-to 'safe-local-variable
(lambda (val)
(or (stringp val)
diff --git a/lisp/proced.el b/lisp/proced.el
index c1d599afc4a..a27638d3679 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -29,10 +29,6 @@
;;
;; To do:
;; - Interactive temporary customizability of flags in `proced-grammar-alist'
-;; - Allow "sudo kill PID", "sudo renice PID"
-;; `proced-send-signal' operates on multiple processes one by one.
-;; With "sudo" we want to execute one "kill" or "renice" command
-;; for all marked processes. Is there a `sudo-call-process'?
;;
;; Thoughts and Ideas
;; - Currently, `process-attributes' returns the list of
@@ -55,12 +51,19 @@
:group 'unix
:prefix "proced-")
+(defcustom proced-show-remote-processes nil
+ "Whether processes of the remote host shall be shown.
+This happens only when `default-directory' is remote."
+ :version "29.1"
+ :type 'boolean)
+
(defcustom proced-signal-function #'signal-process
"Name of signal function.
It can be an elisp function (usually `signal-process') or a string specifying
the external command (usually \"kill\")."
:type '(choice (function :tag "function")
(string :tag "command")))
+(make-obsolete-variable 'proced-signal-function "no longer used." "29.1")
(defcustom proced-renice-command "renice"
"Name of renice command."
@@ -275,8 +278,8 @@ It can also be a list of keys appearing in `proced-grammar-alist'."
;; FIXME: is there a better name for filter `user' that does not coincide
;; with an attribute key?
(defcustom proced-filter-alist
- `((user (user . ,(concat "\\`" (regexp-quote (user-real-login-name)) "\\'")))
- (user-running (user . ,(concat "\\`" (regexp-quote (user-real-login-name)) "\\'"))
+ `((user (user . proced-user-name))
+ (user-running (user . proced-user-name)
(state . "\\`[Rr]\\'"))
(all)
(all-running (state . "\\`[Rr]\\'"))
@@ -366,7 +369,7 @@ May be used to revert the process listing."
;; Internal variables
-(defvar proced-available (not (null (list-system-processes)))
+(defvar proced-available t;(not (null (list-system-processes)))
"Non-nil means Proced is known to work on this system.")
(defvar-local proced-process-alist nil
@@ -565,6 +568,12 @@ Important: the match ends just after the marker.")
:help "Renice Marked Processes"]))
;; helper functions
+(defun proced-user-name (user)
+ "Check the `user' attribute with user name `proced' is running for."
+ (string-equal user (if (file-remote-p default-directory)
+ (file-remote-p default-directory 'user)
+ (user-real-login-name))))
+
(defun proced-marker-regexp ()
"Return regexp matching `proced-marker-char'."
;; `proced-marker-char' must appear in column zero
@@ -626,6 +635,7 @@ Return nil if point is not on a process line."
Type \\[proced] to start a Proced session. In a Proced buffer
type \\<proced-mode-map>\\[proced-mark] to mark a process for later commands.
Type \\[proced-send-signal] to send signals to marked processes.
+Type \\[proced-renice] to renice marked processes.
The initial content of a listing is defined by the variable `proced-filter'
and the variable `proced-format'.
@@ -677,8 +687,13 @@ After displaying or updating a Proced buffer, Proced runs the normal hook
(defun proced (&optional arg)
"Generate a listing of UNIX system processes.
\\<proced-mode-map>
-If invoked with optional ARG, do not select the window displaying
-the process information.
+If invoked with optional non-negative ARG, do not select the
+window displaying the process information.
+
+If `proced-show-remote-processes' is non-nil or the command is
+invoked with a negative ARG `\\[universal-argument] \\[negative-argument]', \
+and `default-directory'
+points to a remote host, the system processes of that host are shown.
This function runs the normal hook `proced-post-display-hook'.
@@ -689,6 +704,11 @@ Proced buffers."
(error "Proced is not available on this system"))
(let ((buffer (get-buffer-create "*Proced*")) new)
(set-buffer buffer)
+ (when (and (file-remote-p default-directory)
+ (not
+ (or proced-show-remote-processes
+ (eq arg '-))))
+ (setq default-directory temporary-file-directory))
(setq new (zerop (buffer-size)))
(when new
(proced-mode)
@@ -1406,7 +1426,7 @@ Replace newline characters by \"^J\" (two characters)."
;; If none of the alternatives is non-nil, the attribute is ignored
;; in the listing.
(let ((standard-attributes
- (car (proced-process-attributes (list (emacs-pid)))))
+ (car (proced-process-attributes (list-system-processes))))
new-format fmi)
(if (and proced-tree-flag
(assq 'ppid standard-attributes))
@@ -1821,7 +1841,8 @@ supported but discouraged. It will be removed in a future version of Emacs."
(dolist (process process-alist)
(condition-case err
(unless (zerop (funcall
- proced-signal-function (car process) signal))
+ proced-signal-function (car process) signal
+ (file-remote-p default-directory)))
(proced-log "%s\n" (cdr process))
(push (cdr process) failures))
(error ; catch errors from failed signals
@@ -1833,7 +1854,7 @@ supported but discouraged. It will be removed in a future version of Emacs."
(dolist (process process-alist)
(with-temp-buffer
(condition-case nil
- (unless (zerop (call-process
+ (unless (zerop (process-file
proced-signal-function nil t nil
signal (number-to-string (car process))))
(proced-log (current-buffer))
@@ -1875,7 +1896,7 @@ the normal hook `proced-after-send-signal-hook'."
(dolist (process process-alist)
(with-temp-buffer
(condition-case nil
- (unless (zerop (call-process
+ (unless (zerop (process-file
proced-renice-command nil t nil
priority (number-to-string (car process))))
(proced-log (current-buffer))
diff --git a/lisp/profiler.el b/lisp/profiler.el
index 94c24c62aa6..8670e5786a4 100644
--- a/lisp/profiler.el
+++ b/lisp/profiler.el
@@ -38,7 +38,7 @@
(defcustom profiler-sampling-interval 1000000
"Default sampling interval in nanoseconds."
- :type 'integer
+ :type 'natnum
:group 'profiler)
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index 4bc6de0c759..d6e2ab8a87a 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -2437,7 +2437,6 @@ the default language."
#'antlr-imenu-create-index-function)
(set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test
(and antlr-imenu-name ; there should be a global variable...
- (fboundp 'imenu-add-to-menubar)
(imenu-add-to-menubar
(if (stringp antlr-imenu-name) antlr-imenu-name "Index")))
(antlr-set-tabs))
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
index 370fb1b80b4..aaf063b5174 100644
--- a/lisp/progmodes/asm-mode.el
+++ b/lisp/progmodes/asm-mode.el
@@ -24,16 +24,16 @@
;;; Commentary:
;; This mode was written by Eric S. Raymond <esr@snark.thyrsus.com>,
-;; inspired by an earlier asm-mode by Martin Neitzel.
+;; inspired by an earlier `asm-mode' by Martin Neitzel.
-;; This major mode is based on prog mode. It defines a private abbrev table
-;; that can be used to save abbrevs for assembler mnemonics. It binds just
-;; five keys:
+;; This major mode is based on `prog-mode'. It defines a private
+;; abbrev table that can be used to save abbrevs for assembler
+;; mnemonics. It binds just five keys:
;;
;; TAB tab to next tab stop
;; : outdent preceding label, tab to tab stop
;; comment char place or move comment
-;; asm-comment-char specifies which character this is;
+;; `asm-comment-char' specifies which character this is;
;; you can use a different character in different
;; Asm mode buffers.
;; C-j, C-m newline and tab to tab stop
@@ -41,9 +41,9 @@
;; Code is indented to the first tab stop level.
;; This mode runs two hooks:
-;; 1) An asm-mode-set-comment-hook before the part of the initialization
-;; depending on asm-comment-char, and
-;; 2) an asm-mode-hook at the end of initialization.
+;; 1) `asm-mode-set-comment-hook' before the part of the initialization
+;; depending on `asm-comment-char', and
+;; 2) `asm-mode-hook' at the end of initialization.
;;; Code:
@@ -68,13 +68,11 @@
"Abbrev table used while in Asm mode.")
(define-abbrev-table 'asm-mode-abbrev-table ())
-(defvar asm-mode-map
- (let ((map (make-sparse-keymap)))
- ;; Note that the comment character isn't set up until asm-mode is called.
- (define-key map ":" 'asm-colon)
- (define-key map "\C-c;" 'comment-region)
- map)
- "Keymap for Asm mode.")
+(defvar-keymap asm-mode-map
+ :doc "Keymap for Asm mode."
+ ;; Note that the comment character isn't set up until asm-mode is called.
+ ":" #'asm-colon
+ "C-c ;" #'comment-region)
(easy-menu-define asm-mode-menu asm-mode-map
"Menu for Asm mode."
@@ -130,7 +128,7 @@ Special commands:
(setq-local tab-always-indent nil)
(run-hooks 'asm-mode-set-comment-hook)
- ;; Make our own local child of asm-mode-map
+ ;; Make our own local child of `asm-mode-map'
;; so we can define our own comment character.
(use-local-map (nconc (make-sparse-keymap) asm-mode-map))
(local-set-key (vector asm-comment-char) #'asm-comment)
diff --git a/lisp/progmodes/bat-mode.el b/lisp/progmodes/bat-mode.el
index 7ef2500e46b..6bac297a298 100644
--- a/lisp/progmodes/bat-mode.el
+++ b/lisp/progmodes/bat-mode.el
@@ -71,8 +71,8 @@
"doskey" "echo" "endlocal" "erase" "fc" "find" "findstr" "format"
"ftype" "label" "md" "mkdir" "more" "move" "net" "path" "pause"
"popd" "prompt" "pushd" "rd" "ren" "rename" "replace" "rmdir" "set"
- "setlocal" "shift" "sort" "subst" "time" "title" "tree" "type"
- "ver" "vol" "xcopy"))
+ "setlocal" "setx" "shift" "sort" "subst" "time" "title" "tree"
+ "type" "ver" "vol" "xcopy"))
(CONTROLFLOW
'("call" "cmd" "defined" "do" "else" "equ" "exist" "exit" "for" "geq"
"goto" "gtr" "if" "in" "leq" "lss" "neq" "not" "start"))
@@ -82,7 +82,7 @@
(2 font-lock-constant-face t))
("^:[^:].*"
. 'bat-label-face)
- ("\\_<\\(defined\\|set\\)\\_>[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"
+ ("\\_<\\(defined\\|set\\|setx\\)\\_>[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"
(2 font-lock-variable-name-face))
("%~\\([0-9]\\)"
(1 font-lock-variable-name-face))
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 06242a4cba8..d3626dbaf01 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -40,12 +40,10 @@
;; Somewhat arbitrary, by analogy with eg goto-address.
:group 'comm)
-(defvar bug-reference-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'bug-reference-push-button)
- (define-key map (kbd "C-c RET") 'bug-reference-push-button)
- map)
- "Keymap used by bug reference buttons.")
+(defvar-keymap bug-reference-map
+ :doc "Keymap used by bug reference buttons."
+ "<mouse-2>" #'bug-reference-push-button
+ "C-c RET" #'bug-reference-push-button)
;; E.g., "https://gcc.gnu.org/PR%s"
(defvar bug-reference-url-format nil
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 8298d5fef04..e14f5b9058f 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -202,6 +202,58 @@ Works with: arglist-cont-nonempty, arglist-close."
(skip-chars-forward " \t"))
(vector (current-column)))))))
+(defun c-lineup-argcont-1 (elem)
+ ;; Move to the start of the current arg and return non-nil, otherwise
+ ;; return nil.
+ (beginning-of-line)
+
+ (when (eq (car elem) 'arglist-cont-nonempty)
+ ;; Our argument list might not be the innermost one. If it
+ ;; isn't, go back to the first position in it. We do this by
+ ;; stepping back over open parens until we get to the open paren
+ ;; of our argument list.
+ (let ((open-paren (c-langelem-2nd-pos c-syntactic-element))
+ (paren-state (c-parse-state)))
+ (while (not (eq (car paren-state) open-paren))
+ (unless (consp (car paren-state)) ;; ignore matched braces
+ (goto-char (car paren-state)))
+ (setq paren-state (cdr paren-state)))))
+
+ (let ((start (point)) c)
+
+ (when (bolp)
+ ;; Previous line ending in a comma means we're the start of an
+ ;; argument. This should quickly catch most cases not for us.
+ ;; This case is only applicable if we're the innermost arglist.
+ (c-backward-syntactic-ws)
+ (setq c (char-before)))
+
+ (unless (eq c ?,)
+ ;; In a gcc asm, ":" on the previous line means the start of an
+ ;; argument. And lines starting with ":" are not for us, don't
+ ;; want them to indent to the preceding operand.
+ (let ((gcc-asm (save-excursion
+ (goto-char start)
+ (c-in-gcc-asm-p))))
+ (unless (and gcc-asm
+ (or (eq c ?:)
+ (save-excursion
+ (goto-char start)
+ (looking-at "[ \t]*:"))))
+
+ (c-lineup-argcont-scan (if gcc-asm ?:))
+ t)))))
+
+(defun c-lineup-argcont-scan (&optional other-match)
+ ;; Find the start of an argument, for `c-lineup-argcont'.
+ (when (zerop (c-backward-token-2 1 t))
+ (let ((c (char-after)))
+ (if (or (eq c ?,) (eq c other-match))
+ (progn
+ (forward-char)
+ (c-forward-syntactic-ws))
+ (c-lineup-argcont-scan other-match)))))
+
;; Contributed by Kevin Ryde <user42@zip.com.au>.
(defun c-lineup-argcont (elem)
"Line up a continued argument.
@@ -217,56 +269,30 @@ but of course only between operand specifications, not in the expressions
for the operands.
Works with: arglist-cont, arglist-cont-nonempty."
-
(save-excursion
- (beginning-of-line)
+ (when (c-lineup-argcont-1 elem)
+ (vector (current-column)))))
- (when (eq (car elem) 'arglist-cont-nonempty)
- ;; Our argument list might not be the innermost one. If it
- ;; isn't, go back to the last position in it. We do this by
- ;; stepping back over open parens until we get to the open paren
- ;; of our argument list.
- (let ((open-paren (c-langelem-2nd-pos c-syntactic-element))
- (paren-state (c-parse-state)))
- (while (not (eq (car paren-state) open-paren))
- (unless (consp (car paren-state)) ;; ignore matched braces
- (goto-char (car paren-state)))
- (setq paren-state (cdr paren-state)))))
-
- (let ((start (point)) c)
-
- (when (bolp)
- ;; Previous line ending in a comma means we're the start of an
- ;; argument. This should quickly catch most cases not for us.
- ;; This case is only applicable if we're the innermost arglist.
- (c-backward-syntactic-ws)
- (setq c (char-before)))
-
- (unless (eq c ?,)
- ;; In a gcc asm, ":" on the previous line means the start of an
- ;; argument. And lines starting with ":" are not for us, don't
- ;; want them to indent to the preceding operand.
- (let ((gcc-asm (save-excursion
- (goto-char start)
- (c-in-gcc-asm-p))))
- (unless (and gcc-asm
- (or (eq c ?:)
- (save-excursion
- (goto-char start)
- (looking-at "[ \t]*:"))))
-
- (c-lineup-argcont-scan (if gcc-asm ?:))
- (vector (current-column))))))))
+(defun c-lineup-argcont-+ (langelem)
+ "Indent an argument continuation `c-basic-offset' in from the first argument.
-(defun c-lineup-argcont-scan (&optional other-match)
- ;; Find the start of an argument, for `c-lineup-argcont'.
- (when (zerop (c-backward-token-2 1 t))
- (let ((c (char-after)))
- (if (or (eq c ?,) (eq c other-match))
- (progn
- (forward-char)
- (c-forward-syntactic-ws))
- (c-lineup-argcont-scan other-match)))))
+This first argument is that on a previous line at the same level of nesting.
+
+foo (xyz, uvw, aaa + bbb + ccc
+ + ddd + eee + fff); <- c-lineup-argcont-+
+ <--> c-basic-offset
+
+Only continuation lines like this are touched, nil being returned
+on lines which are the start of an argument.
+
+Works with: arglist-cont, arglist-cont-nonempty."
+ (save-excursion
+ (when (c-lineup-argcont-1 langelem) ; Check we've got a continued argument...
+ ;; ... but ignore the position found.
+ (goto-char (c-langelem-2nd-pos c-syntactic-element))
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (vector (+ (current-column) c-basic-offset)))))
(defun c-lineup-arglist-intro-after-paren (_langelem)
"Line up a line to just after the open paren of the surrounding paren
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index 188d5a8a837..9ea1557391b 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -56,6 +56,8 @@
;; Silence the byte compiler.
(cc-bytecomp-defvar c-new-BEG)
(cc-bytecomp-defvar c-new-END)
+(cc-bytecomp-defun c-restore-string-fences)
+(cc-bytecomp-defun c-clear-string-fences)
;; Some functions in cc-engine that are used below. There's a cyclic
;; dependency so it can't be required here. (Perhaps some functions
@@ -934,7 +936,7 @@
;; It prepares the buffer for font
;; locking, hence must get called before `font-lock-after-change-function'.
;;
- ;; This function is the AWK value of `c-before-font-lock-function'.
+ ;; This function is the AWK value of `c-before-font-lock-functions'.
;; It does hidden buffer changes.
(c-save-buffer-state ()
(setq c-new-END (c-awk-end-of-change-region beg end old-len))
@@ -1109,29 +1111,30 @@ nor helpful.
Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(interactive "p")
- (or arg (setq arg 1))
- (save-match-data
- (c-save-buffer-state ; ensures the buffer is writable.
- nil
- (let ((found t)) ; Has the most recent regexp search found b-of-defun?
- (if (>= arg 0)
- ;; Go back one defun each time round the following loop. (For +ve arg)
- (while (and found (> arg 0) (not (eq (point) (point-min))))
- ;; Go back one "candidate" each time round the next loop until one
- ;; is genuinely a beginning-of-defun.
- (while (and (setq found (search-backward-regexp
- "^[^#} \t\n\r]" (point-min) 'stop-at-limit))
- (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
- (setq arg (1- arg)))
- ;; The same for a -ve arg.
- (if (not (eq (point) (point-max))) (forward-char 1))
- (while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg.
- (while (and (setq found (search-forward-regexp
- "^[^#} \t\n\r]" (point-max) 'stop-at-limit))
- (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
- (setq arg (1+ arg)))
- (if found (goto-char (match-beginning 0))))
- (eq arg 0)))))
+ (c-with-string-fences
+ (or arg (setq arg 1))
+ (save-match-data
+ (c-save-buffer-state ; ensures the buffer is writable.
+ nil
+ (let ((found t)) ; Has the most recent regexp search found b-of-defun?
+ (if (>= arg 0)
+ ;; Go back one defun each time round the following loop. (For +ve arg)
+ (while (and found (> arg 0) (not (eq (point) (point-min))))
+ ;; Go back one "candidate" each time round the next loop until one
+ ;; is genuinely a beginning-of-defun.
+ (while (and (setq found (search-backward-regexp
+ "^[^#} \t\n\r]" (point-min) 'stop-at-limit))
+ (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
+ (setq arg (1- arg)))
+ ;; The same for a -ve arg.
+ (if (not (eq (point) (point-max))) (forward-char 1))
+ (while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg.
+ (while (and (setq found (search-forward-regexp
+ "^[^#} \t\n\r]" (point-max) 'stop-at-limit))
+ (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
+ (setq arg (1+ arg)))
+ (if found (goto-char (match-beginning 0))))
+ (eq arg 0))))))
(defun c-awk-forward-awk-pattern ()
;; Point is at the start of an AWK pattern (which may be null) or function
@@ -1187,39 +1190,40 @@ no explicit action; see function `c-awk-beginning-of-defun'.
Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(interactive "p")
- (or arg (setq arg 1))
- (save-match-data
- (c-save-buffer-state
- nil
- (let ((start-point (point)) end-point)
- ;; Strategy: (For +ve ARG): If we're not already at a beginning-of-defun,
- ;; move backwards to one.
- ;; Repeat [(i) move forward to end-of-current-defun (see below);
- ;; (ii) If this isn't it, move forward to beginning-of-defun].
- ;; We start counting ARG only when step (i) has passed the original point.
- (when (> arg 0)
- ;; Try to move back to a beginning-of-defun, if not already at one.
- (if (not (c-awk-beginning-of-defun-p))
- (when (not (c-awk-beginning-of-defun 1)) ; No bo-defun before point.
- (goto-char start-point)
- (c-awk-beginning-of-defun -1))) ; if this fails, we're at EOB, tough!
- ;; Now count forward, one defun at a time
- (while (and (not (eobp))
- (c-awk-end-of-defun1)
- (if (> (point) start-point) (setq arg (1- arg)) t)
- (> arg 0)
- (c-awk-beginning-of-defun -1))))
-
- (when (< arg 0)
- (setq end-point start-point)
- (while (and (not (bobp))
- (c-awk-beginning-of-defun 1)
- (if (< (setq end-point (if (bobp) (point)
- (save-excursion (c-awk-end-of-defun1))))
- start-point)
- (setq arg (1+ arg)) t)
- (< arg 0)))
- (goto-char (min start-point end-point)))))))
+ (c-with-string-fences
+ (or arg (setq arg 1))
+ (save-match-data
+ (c-save-buffer-state
+ nil
+ (let ((start-point (point)) end-point)
+ ;; Strategy: (For +ve ARG): If we're not already at a beginning-of-defun,
+ ;; move backwards to one.
+ ;; Repeat [(i) move forward to end-of-current-defun (see below);
+ ;; (ii) If this isn't it, move forward to beginning-of-defun].
+ ;; We start counting ARG only when step (i) has passed the original point.
+ (when (> arg 0)
+ ;; Try to move back to a beginning-of-defun, if not already at one.
+ (if (not (c-awk-beginning-of-defun-p))
+ (when (not (c-awk-beginning-of-defun 1)) ; No bo-defun before point.
+ (goto-char start-point)
+ (c-awk-beginning-of-defun -1))) ; if this fails, we're at EOB, tough!
+ ;; Now count forward, one defun at a time
+ (while (and (not (eobp))
+ (c-awk-end-of-defun1)
+ (if (> (point) start-point) (setq arg (1- arg)) t)
+ (> arg 0)
+ (c-awk-beginning-of-defun -1))))
+
+ (when (< arg 0)
+ (setq end-point start-point)
+ (while (and (not (bobp))
+ (c-awk-beginning-of-defun 1)
+ (if (< (setq end-point (if (bobp) (point)
+ (save-excursion (c-awk-end-of-defun1))))
+ start-point)
+ (setq arg (1+ arg)) t)
+ (< arg 0)))
+ (goto-char (min start-point end-point))))))))
(cc-provide 'cc-awk) ; Changed from 'awk-mode, ACM 2002/5/21
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index e9237bb01e2..82268f49433 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -49,6 +49,8 @@
; which looks at this.
(cc-bytecomp-defun electric-pair-post-self-insert-function)
(cc-bytecomp-defvar c-indent-to-body-directives)
+(cc-bytecomp-defun c-restore-string-fences)
+(cc-bytecomp-defun c-clear-string-fences)
(defvar c-syntactic-context)
;; Indentation / Display syntax functions
@@ -210,35 +212,36 @@ and takes care to set the indentation before calling
"Show syntactic information for current line.
With universal argument, inserts the analysis as a comment on that line."
(interactive "P")
- (let* ((c-parsing-error nil)
- (syntax (if (boundp 'c-syntactic-context)
- ;; Use `c-syntactic-context' in the same way as
- ;; `c-indent-line', to be consistent.
- c-syntactic-context
- (c-save-buffer-state nil
- (c-guess-basic-syntax)))))
- (if (not (consp arg))
- (let (elem pos ols)
- (message "Syntactic analysis: %s" syntax)
- (unwind-protect
- (progn
- (while syntax
- (setq elem (pop syntax))
- (when (setq pos (c-langelem-pos elem))
- (push (c-put-overlay pos (1+ pos)
- 'face 'highlight)
- ols))
- (when (setq pos (c-langelem-2nd-pos elem))
- (push (c-put-overlay pos (1+ pos)
- 'face 'secondary-selection)
- ols)))
- (sit-for 10))
- (while ols
- (c-delete-overlay (pop ols)))))
- (indent-for-comment)
- (insert-and-inherit (format "%s" syntax))
- ))
- (c-keep-region-active))
+ (c-with-string-fences
+ (let* ((c-parsing-error nil)
+ (syntax (if (boundp 'c-syntactic-context)
+ ;; Use `c-syntactic-context' in the same way as
+ ;; `c-indent-line', to be consistent.
+ c-syntactic-context
+ (c-save-buffer-state nil
+ (c-guess-basic-syntax)))))
+ (if (not (consp arg))
+ (let (elem pos ols)
+ (message "Syntactic analysis: %s" syntax)
+ (unwind-protect
+ (progn
+ (while syntax
+ (setq elem (pop syntax))
+ (when (setq pos (c-langelem-pos elem))
+ (push (c-put-overlay pos (1+ pos)
+ 'face 'highlight)
+ ols))
+ (when (setq pos (c-langelem-2nd-pos elem))
+ (push (c-put-overlay pos (1+ pos)
+ 'face 'secondary-selection)
+ ols)))
+ (sit-for 10))
+ (while ols
+ (c-delete-overlay (pop ols)))))
+ (indent-for-comment)
+ (insert-and-inherit (format "%s" syntax))
+ ))
+ (c-keep-region-active)))
(defun c-syntactic-information-on-region (from to)
"Insert a comment with the syntactic analysis on every line in the region."
@@ -414,23 +417,25 @@ argument is supplied, or `c-hungry-delete-key' is nil, or point is
inside a literal then the function in the variable
`c-backspace-function' is called."
(interactive "*P")
- (if (c-save-buffer-state ()
- (or (not c-hungry-delete-key)
- arg
- (c-in-literal)))
- (funcall c-backspace-function (prefix-numeric-value arg))
- (c-hungry-delete-backwards)))
+ (c-with-string-fences
+ (if (c-save-buffer-state ()
+ (or (not c-hungry-delete-key)
+ arg
+ (c-in-literal)))
+ (funcall c-backspace-function (prefix-numeric-value arg))
+ (c-hungry-delete-backwards))))
(defun c-hungry-delete-backwards ()
"Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character.
See also \\[c-hungry-delete-forward]."
(interactive)
- (let ((here (point)))
- (c-skip-ws-backward)
- (if (/= (point) here)
- (delete-region (point) here)
- (funcall c-backspace-function 1))))
+ (c-with-string-fences
+ (let ((here (point)))
+ (c-skip-ws-backward)
+ (if (/= (point) here)
+ (delete-region (point) here)
+ (funcall c-backspace-function 1)))))
(defalias 'c-hungry-backspace 'c-hungry-delete-backwards)
@@ -442,23 +447,26 @@ argument is supplied, or `c-hungry-delete-key' is nil, or point is
inside a literal then the function in the variable `c-delete-function'
is called."
(interactive "*P")
- (if (c-save-buffer-state ()
- (or (not c-hungry-delete-key)
- arg
- (c-in-literal)))
- (funcall c-delete-function (prefix-numeric-value arg))
- (c-hungry-delete-forward)))
+ (c-with-string-fences
+ (if
+ (c-save-buffer-state ()
+ (or (not c-hungry-delete-key)
+ arg
+ (c-in-literal)))
+ (funcall c-delete-function (prefix-numeric-value arg))
+ (c-hungry-delete-forward))))
(defun c-hungry-delete-forward ()
"Delete the following character or all following whitespace
up to the next non-whitespace character.
See also \\[c-hungry-delete-backwards]."
(interactive)
- (let ((here (point)))
- (c-skip-ws-forward)
- (if (/= (point) here)
- (delete-region (point) here)
- (funcall c-delete-function 1))))
+ (c-with-string-fences
+ (let ((here (point)))
+ (c-skip-ws-forward)
+ (if (/= (point) here)
+ (delete-region (point) here)
+ (funcall c-delete-function 1)))))
;; This function is only used in XEmacs.
(defun c-electric-delete (arg)
@@ -519,7 +527,8 @@ function to control that."
(defmacro c--call-post-self-insert-hook-more-safely ()
;; Call post-self-insert-hook, if such exists. See comment for
- ;; `c--call-post-self-insert-hook-more-safely-1'.
+ ;; `c--call-post-self-insert-hook-more-safely-1'. This macro should be
+ ;; invoked OUTSIDE of `c-with-string-fences'.
(if (boundp 'post-self-insert-hook)
'(c--call-post-self-insert-hook-more-safely-1)
'(progn)))
@@ -530,30 +539,30 @@ If `c-electric-flag' is set, handle it specially according to the variable
`c-electric-pound-behavior'. If a numeric ARG is supplied, or if point is
inside a literal or a macro, nothing special happens."
(interactive "*P")
- (if (c-save-buffer-state ()
- (or arg
- (not c-electric-flag)
- (not (memq 'alignleft c-electric-pound-behavior))
- (save-excursion
- (skip-chars-backward " \t")
- (not (bolp)))
- (save-excursion
- (and (= (forward-line -1) 0)
- (progn (end-of-line)
- (eq (char-before) ?\\))))
- (c-in-literal)))
- ;; do nothing special
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
- ;; place the pound character at the left edge
- (let ((pos (- (point-max) (point)))
- (bolp (bolp)))
- (beginning-of-line)
- (delete-horizontal-space)
- (insert (c-last-command-char))
- (and (not bolp)
- (goto-char (- (point-max) pos)))
- ))
+ (c-with-string-fences
+ (if (c-save-buffer-state ()
+ (or arg
+ (not c-electric-flag)
+ (not (memq 'alignleft c-electric-pound-behavior))
+ (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+ (save-excursion
+ (and (= (forward-line -1) 0)
+ (progn (end-of-line)
+ (eq (char-before) ?\\))))
+ (c-in-literal)))
+ ;; do nothing special
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+ ;; place the pound character at the left edge
+ (let ((pos (- (point-max) (point)))
+ (bolp (bolp)))
+ (beginning-of-line)
+ (delete-horizontal-space)
+ (insert (c-last-command-char))
+ (and (not bolp)
+ (goto-char (- (point-max) pos))))))
(c--call-post-self-insert-hook-more-safely))
(defun c-point-syntax ()
@@ -883,25 +892,26 @@ settings of `c-cleanup-list' are done."
(interactive "*P")
(let (safepos literal
- ;; We want to inhibit blinking the paren since this would be
- ;; most disruptive. We'll blink it ourselves later on.
- (old-blink-paren blink-paren-function)
- blink-paren-function case-fold-search
- (at-eol (looking-at "[ \t]*\\\\?$"))
- (active-region (and (fboundp 'use-region-p) (use-region-p)))
- got-pair-} electric-pair-deletion)
-
- (c-save-buffer-state ()
- (setq safepos (c-safe-position (point) (c-parse-state))
- literal (c-in-literal safepos)))
-
- ;; Insert the brace. Note that expand-abbrev might reindent
- ;; the line here if there's a preceding "else" or something.
- (let (post-self-insert-hook) ; the only way to get defined functionality
- ; from `self-insert-command'.
- (self-insert-command (prefix-numeric-value arg)))
-
- ;; Emulate `electric-pair-mode'.
+ ;; We want to inhibit blinking the paren since this would be
+ ;; most disruptive. We'll blink it ourselves later on.
+ (old-blink-paren blink-paren-function)
+ blink-paren-function case-fold-search
+ (at-eol (looking-at "[ \t]*\\\\?$"))
+ (active-region (and (fboundp 'use-region-p) (use-region-p)))
+ got-pair-} electric-pair-deletion)
+
+ (c-with-string-fences
+ (c-save-buffer-state ()
+ (setq safepos (c-safe-position (point) (c-parse-state))
+ literal (c-in-literal safepos)))
+
+ ;; Insert the brace. Note that expand-abbrev might reindent
+ ;; the line here if there's a preceding "else" or something.
+ (let (post-self-insert-hook) ; the only way to get defined functionality
+ ; from `self-insert-command'.
+ (self-insert-command (prefix-numeric-value arg))))
+
+ ;; Emulate `electric-pair-mode', outside of `c-with-string-fences'.
(when (and (boundp 'electric-pair-mode)
electric-pair-mode)
(let ((size (buffer-size))
@@ -912,30 +922,31 @@ settings of `c-cleanup-list' are done."
(eq (char-after) ?}))
electric-pair-deletion (< (buffer-size) size))))
- ;; Perform any required CC Mode electric actions.
- (cond
- ((or literal arg (not c-electric-flag) active-region))
- ((not at-eol)
- (c-indent-line))
- (electric-pair-deletion
- (c-indent-line)
- (c-do-brace-electrics 'ignore nil))
- (t (c-do-brace-electrics nil nil)
- (when got-pair-}
+ (c-with-string-fences
+ ;; Perform any required CC Mode electric actions.
+ (cond
+ ((or literal arg (not c-electric-flag) active-region))
+ ((not at-eol)
+ (c-indent-line))
+ (electric-pair-deletion
+ (c-indent-line)
+ (c-do-brace-electrics 'ignore nil))
+ (t (c-do-brace-electrics nil nil)
+ (when got-pair-}
+ (save-excursion
+ (forward-char)
+ (c-do-brace-electrics 'assume 'ignore))
+ (c-indent-line))))
+
+ ;; blink the paren
+ (and (eq (c-last-command-char) ?\})
+ (not executing-kbd-macro)
+ old-blink-paren
(save-excursion
- (forward-char)
- (c-do-brace-electrics 'assume 'ignore))
- (c-indent-line))))
-
- ;; blink the paren
- (and (eq (c-last-command-char) ?\})
- (not executing-kbd-macro)
- old-blink-paren
- (save-excursion
- (c-save-buffer-state nil
- (c-backward-syntactic-ws safepos))
- (funcall old-blink-paren)))
- (c--call-post-self-insert-hook-more-safely)))
+ (c-save-buffer-state nil
+ (c-backward-syntactic-ws safepos))
+ (funcall old-blink-paren)))))
+ (c--call-post-self-insert-hook-more-safely))
(defun c-electric-slash (arg)
"Insert a slash character.
@@ -956,39 +967,40 @@ If a numeric ARG is supplied, point is inside a literal, or
`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
is inhibited."
(interactive "*P")
- (let ((literal (c-save-buffer-state () (c-in-literal)))
- indentp
- ;; shut this up
- (c-echo-syntactic-information-p nil))
+ (c-with-string-fences
+ (let ((literal (c-save-buffer-state () (c-in-literal)))
+ indentp
+ ;; shut this up
+ (c-echo-syntactic-information-p nil))
- ;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or
- ;; `c-syntactic-indentation' set.
- (when (and (not arg)
- (eq literal 'c)
- (memq 'comment-close-slash c-cleanup-list)
- (eq (c-last-command-char) ?/)
- (looking-at (concat "[ \t]*\\("
- (regexp-quote comment-end) "\\)?$"))
- ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
- (save-excursion
- (save-restriction
- (narrow-to-region (point-min) (point))
- (back-to-indentation)
- (looking-at (concat c-current-comment-prefix "[ \t]*$")))))
- (delete-region (progn (forward-line 0) (point))
- (progn (end-of-line) (point)))
- (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here?
-
- (setq indentp (and (not arg)
- c-syntactic-indentation
- c-electric-flag
- (eq (c-last-command-char) ?/)
- (eq (char-before) (if literal ?* ?/))))
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
- (if indentp
- (indent-according-to-mode))
- (c--call-post-self-insert-hook-more-safely)))
+ ;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or
+ ;; `c-syntactic-indentation' set.
+ (when (and (not arg)
+ (eq literal 'c)
+ (memq 'comment-close-slash c-cleanup-list)
+ (eq (c-last-command-char) ?/)
+ (looking-at (concat "[ \t]*\\("
+ (regexp-quote comment-end) "\\)?$"))
+ ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (point-min) (point))
+ (back-to-indentation)
+ (looking-at (concat c-current-comment-prefix "[ \t]*$")))))
+ (delete-region (progn (forward-line 0) (point))
+ (progn (end-of-line) (point)))
+ (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here?
+
+ (setq indentp (and (not arg)
+ c-syntactic-indentation
+ c-electric-flag
+ (eq (c-last-command-char) ?/)
+ (eq (char-before) (if literal ?* ?/))))
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+ (if indentp
+ (indent-according-to-mode))))
+ (c--call-post-self-insert-hook-more-safely))
(defun c-electric-star (arg)
"Insert a star character.
@@ -999,26 +1011,26 @@ supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
this indentation is inhibited."
(interactive "*P")
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
- ;; if we are in a literal, or if arg is given do not reindent the
- ;; current line, unless this star introduces a comment-only line.
- (if (c-save-buffer-state ()
- (and c-syntactic-indentation
- c-electric-flag
- (not arg)
- (eq (c-in-literal) 'c)
- (eq (char-before) ?*)
- (save-excursion
- (forward-char -1)
- (skip-chars-backward "*")
- (if (eq (char-before) ?/)
- (forward-char -1))
- (skip-chars-backward " \t")
- (bolp))))
- (let (c-echo-syntactic-information-p) ; shut this up
- (indent-according-to-mode))
- )
+ (c-with-string-fences
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+ ;; if we are in a literal, or if arg is given do not reindent the
+ ;; current line, unless this star introduces a comment-only line.
+ (if (c-save-buffer-state ()
+ (and c-syntactic-indentation
+ c-electric-flag
+ (not arg)
+ (eq (c-in-literal) 'c)
+ (eq (char-before) ?*)
+ (save-excursion
+ (forward-char -1)
+ (skip-chars-backward "*")
+ (if (eq (char-before) ?/)
+ (forward-char -1))
+ (skip-chars-backward " \t")
+ (bolp))))
+ (let (c-echo-syntactic-information-p) ; shut this up
+ (indent-according-to-mode))))
(c--call-post-self-insert-hook-more-safely))
(defun c-electric-semi&comma (arg)
@@ -1039,60 +1051,61 @@ reindented unless `c-syntactic-indentation' is nil.
semicolon following a defun might be cleaned up, depending on the
settings of `c-cleanup-list'."
(interactive "*P")
- (let* (lim literal c-syntactic-context
- (here (point))
- ;; shut this up
- (c-echo-syntactic-information-p nil))
-
- (c-save-buffer-state ()
- (setq lim (c-most-enclosing-brace (c-parse-state))
- literal (c-in-literal lim)))
-
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
-
- (if (and c-electric-flag (not literal) (not arg))
- ;; do all cleanups and newline insertions if c-auto-newline is on.
- (if (or (not c-auto-newline)
- (not (looking-at "[ \t]*\\\\?$")))
- (if c-syntactic-indentation
- (c-indent-line))
- ;; clean ups: list-close-comma or defun-close-semi
- (let ((pos (- (point-max) (point))))
- (if (c-save-buffer-state ()
- (and (or (and
- (eq (c-last-command-char) ?,)
- (memq 'list-close-comma c-cleanup-list))
- (and
- (eq (c-last-command-char) ?\;)
- (memq 'defun-close-semi c-cleanup-list)))
- (progn
- (forward-char -1)
- (c-skip-ws-backward)
- (eq (char-before) ?}))
- ;; make sure matching open brace isn't in a comment
- (not (c-in-literal lim))))
- (delete-region (point) here))
- (goto-char (- (point-max) pos)))
- ;; reindent line
- (when c-syntactic-indentation
- (setq c-syntactic-context (c-guess-basic-syntax))
- (c-indent-line c-syntactic-context))
- ;; check to see if a newline should be added
- (let ((criteria c-hanging-semi&comma-criteria)
- answer add-newline-p)
- (while criteria
- (setq answer (funcall (car criteria)))
- ;; only nil value means continue checking
- (if (not answer)
- (setq criteria (cdr criteria))
- (setq criteria nil)
- ;; only 'stop specifically says do not add a newline
- (setq add-newline-p (not (eq answer 'stop)))
- ))
- (if add-newline-p
- (c-newline-and-indent)))))
- (c--call-post-self-insert-hook-more-safely)))
+ (c-with-string-fences
+ (let* (lim literal c-syntactic-context
+ (here (point))
+ ;; shut this up
+ (c-echo-syntactic-information-p nil))
+
+ (c-save-buffer-state ()
+ (setq lim (c-most-enclosing-brace (c-parse-state))
+ literal (c-in-literal lim)))
+
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+
+ (if (and c-electric-flag (not literal) (not arg))
+ ;; do all cleanups and newline insertions if c-auto-newline is on.
+ (if (or (not c-auto-newline)
+ (not (looking-at "[ \t]*\\\\?$")))
+ (if c-syntactic-indentation
+ (c-indent-line))
+ ;; clean ups: list-close-comma or defun-close-semi
+ (let ((pos (- (point-max) (point))))
+ (if (c-save-buffer-state ()
+ (and (or (and
+ (eq (c-last-command-char) ?,)
+ (memq 'list-close-comma c-cleanup-list))
+ (and
+ (eq (c-last-command-char) ?\;)
+ (memq 'defun-close-semi c-cleanup-list)))
+ (progn
+ (forward-char -1)
+ (c-skip-ws-backward)
+ (eq (char-before) ?}))
+ ;; make sure matching open brace isn't in a comment
+ (not (c-in-literal lim))))
+ (delete-region (point) here))
+ (goto-char (- (point-max) pos)))
+ ;; reindent line
+ (when c-syntactic-indentation
+ (setq c-syntactic-context (c-guess-basic-syntax))
+ (c-indent-line c-syntactic-context))
+ ;; check to see if a newline should be added
+ (let ((criteria c-hanging-semi&comma-criteria)
+ answer add-newline-p)
+ (while criteria
+ (setq answer (funcall (car criteria)))
+ ;; only nil value means continue checking
+ (if (not answer)
+ (setq criteria (cdr criteria))
+ (setq criteria nil)
+ ;; only 'stop specifically says do not add a newline
+ (setq add-newline-p (not (eq answer 'stop)))
+ ))
+ (if add-newline-p
+ (c-newline-and-indent)))))))
+ (c--call-post-self-insert-hook-more-safely))
(defun c-electric-colon (arg)
"Insert a colon.
@@ -1113,89 +1126,90 @@ reindented unless `c-syntactic-indentation' is nil.
`c-cleanup-list'."
(interactive "*P")
- (let* ((bod (c-point 'bod))
- (literal (c-save-buffer-state () (c-in-literal bod)))
- newlines is-scope-op
- ;; shut this up
- (c-echo-syntactic-information-p nil))
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
- ;; Any electric action?
- (if (and c-electric-flag (not literal) (not arg))
- ;; Unless we're at EOL, only re-indentation happens.
- (if (not (looking-at "[ \t]*\\\\?$"))
- (if c-syntactic-indentation
- (indent-according-to-mode))
-
- ;; scope-operator clean-up?
- (let ((pos (- (point-max) (point)))
- (here (point)))
- (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12]
- (and c-auto-newline
- (memq 'scope-operator c-cleanup-list)
- (eq (char-before) ?:)
- (progn
- (forward-char -1)
- (c-skip-ws-backward)
- (eq (char-before) ?:))
- (not (c-in-literal))
- (not (eq (char-after (- (point) 2)) ?:))))
- (progn
- (delete-region (point) (1- here))
- (setq is-scope-op t)))
- (goto-char (- (point-max) pos)))
-
- ;; indent the current line if it's done syntactically.
- (if c-syntactic-indentation
- ;; Cannot use the same syntax analysis as we find below,
- ;; since that's made with c-syntactic-indentation-in-macros
- ;; always set to t.
- (indent-according-to-mode))
-
- ;; Calculate where, if anywhere, we want newlines.
- (c-save-buffer-state
- ((c-syntactic-indentation-in-macros t)
- (c-auto-newline-analysis t)
- ;; Turn on syntactic macro analysis to help with auto newlines
- ;; only.
- (syntax (c-guess-basic-syntax))
- (elem syntax))
- ;; Translate substatement-label to label for this operation.
- (while elem
- (if (eq (car (car elem)) 'substatement-label)
- (setcar (car elem) 'label))
- (setq elem (cdr elem)))
- ;; some language elements can only be determined by checking
- ;; the following line. Let's first look for ones that can be
- ;; found when looking on the line with the colon
- (setq newlines
- (and c-auto-newline
- (or (c-lookup-lists '(case-label label access-label)
- syntax c-hanging-colons-alist)
- (c-lookup-lists '(member-init-intro inher-intro)
- (progn
- (insert ?\n)
- (unwind-protect
- (c-guess-basic-syntax)
- (delete-char -1)))
- c-hanging-colons-alist)))))
- ;; does a newline go before the colon? Watch out for already
- ;; non-hung colons. However, we don't unhang them because that
- ;; would be a cleanup (and anti-social).
- (if (and (memq 'before newlines)
- (not is-scope-op)
- (save-excursion
- (skip-chars-backward ": \t")
- (not (bolp))))
- (let ((pos (- (point-max) (point))))
- (forward-char -1)
- (c-newline-and-indent)
- (goto-char (- (point-max) pos))))
- ;; does a newline go after the colon?
- (if (and (memq 'after (cdr-safe newlines))
- (not is-scope-op))
- (c-newline-and-indent))))
- (c--call-post-self-insert-hook-more-safely)))
+ (c-with-string-fences
+ (let* ((bod (c-point 'bod))
+ (literal (c-save-buffer-state () (c-in-literal bod)))
+ newlines is-scope-op
+ ;; shut this up
+ (c-echo-syntactic-information-p nil))
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+ ;; Any electric action?
+ (if (and c-electric-flag (not literal) (not arg))
+ ;; Unless we're at EOL, only re-indentation happens.
+ (if (not (looking-at "[ \t]*\\\\?$"))
+ (if c-syntactic-indentation
+ (indent-according-to-mode))
+
+ ;; scope-operator clean-up?
+ (let ((pos (- (point-max) (point)))
+ (here (point)))
+ (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12]
+ (and c-auto-newline
+ (memq 'scope-operator c-cleanup-list)
+ (eq (char-before) ?:)
+ (progn
+ (forward-char -1)
+ (c-skip-ws-backward)
+ (eq (char-before) ?:))
+ (not (c-in-literal))
+ (not (eq (char-after (- (point) 2)) ?:))))
+ (progn
+ (delete-region (point) (1- here))
+ (setq is-scope-op t)))
+ (goto-char (- (point-max) pos)))
+
+ ;; indent the current line if it's done syntactically.
+ (if c-syntactic-indentation
+ ;; Cannot use the same syntax analysis as we find below,
+ ;; since that's made with c-syntactic-indentation-in-macros
+ ;; always set to t.
+ (indent-according-to-mode))
+
+ ;; Calculate where, if anywhere, we want newlines.
+ (c-save-buffer-state
+ ((c-syntactic-indentation-in-macros t)
+ (c-auto-newline-analysis t)
+ ;; Turn on syntactic macro analysis to help with auto newlines
+ ;; only.
+ (syntax (c-guess-basic-syntax))
+ (elem syntax))
+ ;; Translate substatement-label to label for this operation.
+ (while elem
+ (if (eq (car (car elem)) 'substatement-label)
+ (setcar (car elem) 'label))
+ (setq elem (cdr elem)))
+ ;; some language elements can only be determined by checking
+ ;; the following line. Let's first look for ones that can be
+ ;; found when looking on the line with the colon
+ (setq newlines
+ (and c-auto-newline
+ (or (c-lookup-lists '(case-label label access-label)
+ syntax c-hanging-colons-alist)
+ (c-lookup-lists '(member-init-intro inher-intro)
+ (progn
+ (insert ?\n)
+ (unwind-protect
+ (c-guess-basic-syntax)
+ (delete-char -1)))
+ c-hanging-colons-alist)))))
+ ;; does a newline go before the colon? Watch out for already
+ ;; non-hung colons. However, we don't unhang them because that
+ ;; would be a cleanup (and anti-social).
+ (if (and (memq 'before newlines)
+ (not is-scope-op)
+ (save-excursion
+ (skip-chars-backward ": \t")
+ (not (bolp))))
+ (let ((pos (- (point-max) (point))))
+ (forward-char -1)
+ (c-newline-and-indent)
+ (goto-char (- (point-max) pos))))
+ ;; does a newline go after the colon?
+ (if (and (memq 'after (cdr-safe newlines))
+ (not is-scope-op))
+ (c-newline-and-indent))))))
+ (c--call-post-self-insert-hook-more-safely))
(defun c-electric-lt-gt (arg)
"Insert a \"<\" or \">\" character.
@@ -1209,74 +1223,75 @@ finishes a C++ style stream operator in C++ mode. Exceptions are when a
numeric argument is supplied, or the point is inside a literal."
(interactive "*P")
- (let ((literal (c-save-buffer-state () (c-in-literal)))
- template-delim include-delim
+ (let (template-delim include-delim
(c-echo-syntactic-information-p nil)
final-pos found-delim case-fold-search)
- (let (post-self-insert-hook) ; Disable random functionality.
- (self-insert-command (prefix-numeric-value arg)))
- (setq final-pos (point))
+ (c-with-string-fences
+ (let (post-self-insert-hook) ; Disable random functionality.
+ (self-insert-command (prefix-numeric-value arg)))
+ (setq final-pos (point))
;;;; 2010-01-31: There used to be code here to put a syntax-table text
;;;; property on the new < or > and its mate (if any) when they are template
;;;; parens. This is now done in an after-change function.
- (when (and (not arg) (not literal))
- ;; Have we got a delimiter on a #include directive?
- (beginning-of-line)
- (setq include-delim
- (and
- (looking-at c-cpp-include-key)
- (if (eq (c-last-command-char) ?<)
- (eq (match-end 0) (1- final-pos))
- (goto-char (1- final-pos))
- (skip-chars-backward "^<>" (c-point 'bol))
- (eq (char-before) ?<))))
- (goto-char final-pos)
-
- ;; Indent the line if appropriate.
- (when (and c-electric-flag c-syntactic-indentation c-recognize-<>-arglists)
- (setq found-delim
+ (when (and (not arg)
+ (not (c-save-buffer-state () (c-in-literal))))
+ ;; Have we got a delimiter on a #include directive?
+ (beginning-of-line)
+ (setq include-delim
+ (and
+ (looking-at c-cpp-include-key)
(if (eq (c-last-command-char) ?<)
- ;; If a <, basically see if it's got "template" before it .....
- (or (and (progn
- (backward-char)
- (= (point)
- (progn (c-beginning-of-current-token) (point))))
- (progn
- (c-backward-token-2)
- (looking-at c-opt-<>-sexp-key))
- (setq template-delim t))
- ;; ..... or is a C++ << operator.
- (and (c-major-mode-is 'c++-mode)
- (progn
- (goto-char (1- final-pos))
- (c-beginning-of-current-token)
- (looking-at "<<"))
- (>= (match-end 0) final-pos)))
-
- ;; It's a >. Either a template/generic terminator ...
- (or (and (c-get-char-property (1- final-pos) 'syntax-table)
- (setq template-delim t))
- ;; or a C++ >> operator.
- (and (c-major-mode-is 'c++-mode)
- (progn
- (goto-char (1- final-pos))
- (c-beginning-of-current-token)
- (looking-at ">>"))
- (>= (match-end 0) final-pos)))))
- (goto-char final-pos)
-
- (when found-delim
- (indent-according-to-mode)))
-
- ;; On the off chance that < and > are configured as pairs in
- ;; electric-pair-mode.
- (when (and (boundp 'electric-pair-mode) electric-pair-mode
- (or template-delim include-delim))
- (let (post-self-insert-hook)
- (electric-pair-post-self-insert-function))))
+ (eq (match-end 0) (1- final-pos))
+ (goto-char (1- final-pos))
+ (skip-chars-backward "^<>" (c-point 'bol))
+ (eq (char-before) ?<))))
+ (goto-char final-pos)
+
+ ;; Indent the line if appropriate.
+ (when (and c-electric-flag c-syntactic-indentation c-recognize-<>-arglists)
+ (setq found-delim
+ (if (eq (c-last-command-char) ?<)
+ ;; If a <, basically see if it's got "template" before it .....
+ (or (and (progn
+ (backward-char)
+ (= (point)
+ (progn (c-beginning-of-current-token) (point))))
+ (progn
+ (c-backward-token-2)
+ (looking-at c-opt-<>-sexp-key))
+ (setq template-delim t))
+ ;; ..... or is a C++ << operator.
+ (and (c-major-mode-is 'c++-mode)
+ (progn
+ (goto-char (1- final-pos))
+ (c-beginning-of-current-token)
+ (looking-at "<<"))
+ (>= (match-end 0) final-pos)))
+
+ ;; It's a >. Either a template/generic terminator ...
+ (or (and (c-get-char-property (1- final-pos) 'syntax-table)
+ (setq template-delim t))
+ ;; or a C++ >> operator.
+ (and (c-major-mode-is 'c++-mode)
+ (progn
+ (goto-char (1- final-pos))
+ (c-beginning-of-current-token)
+ (looking-at ">>"))
+ (>= (match-end 0) final-pos)))))
+ (goto-char final-pos)
+
+ (when found-delim
+ (indent-according-to-mode)))))
+
+ ;; On the off chance that < and > are configured as pairs in
+ ;; electric-pair-mode.
+ (when (and (boundp 'electric-pair-mode) electric-pair-mode
+ (or template-delim include-delim))
+ (let (post-self-insert-hook)
+ (electric-pair-post-self-insert-function)))
(when found-delim
(when (and (eq (char-before) ?>)
@@ -1301,12 +1316,13 @@ removed; see the variable `c-cleanup-list'.
Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some
newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
(interactive "*P")
- (let ((literal (c-save-buffer-state () (c-in-literal)))
+ (let ((literal (c-save-buffer-state ()
+ (c-with-string-fences (c-in-literal))))
;; shut this up
(c-echo-syntactic-information-p nil)
case-fold-search)
(let (post-self-insert-hook) ; The only way to get defined functionality
- ; from `self-insert-command'.
+ ; from `self-insert-command'.
(self-insert-command (prefix-numeric-value arg)))
(if (and (not arg) (not literal))
@@ -1315,46 +1331,47 @@ newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
;; afterwards.
(old-blink-paren blink-paren-function)
blink-paren-function)
- (if (and c-syntactic-indentation c-electric-flag)
- (indent-according-to-mode))
-
- ;; If we're at EOL, check for new-line clean-ups.
- (when (and c-electric-flag c-auto-newline
- (looking-at "[ \t]*\\\\?$"))
-
- ;; clean up brace-elseif-brace
- (when
- (and (memq 'brace-elseif-brace c-cleanup-list)
- (eq (c-last-command-char) ?\()
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "else"
- "\\([ \t\n]\\|\\\\\n\\)+"
- "if"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "("
- "\\=")
- nil t)
- (not (c-save-buffer-state () (c-in-literal))))
- (delete-region (match-beginning 0) (match-end 0))
- (insert-and-inherit "} else if ("))
-
- ;; clean up brace-catch-brace
- (when
- (and (memq 'brace-catch-brace c-cleanup-list)
- (eq (c-last-command-char) ?\()
- (re-search-backward
- (concat "}"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "catch"
- "\\([ \t\n]\\|\\\\\n\\)*"
- "("
- "\\=")
- nil t)
- (not (c-save-buffer-state () (c-in-literal))))
- (delete-region (match-beginning 0) (match-end 0))
- (insert-and-inherit "} catch (")))
+ (c-with-string-fences
+ (if (and c-syntactic-indentation c-electric-flag)
+ (indent-according-to-mode))
+
+ ;; If we're at EOL, check for new-line clean-ups.
+ (when (and c-electric-flag c-auto-newline
+ (looking-at "[ \t]*\\\\?$"))
+
+ ;; clean up brace-elseif-brace
+ (when
+ (and (memq 'brace-elseif-brace c-cleanup-list)
+ (eq (c-last-command-char) ?\()
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "else"
+ "\\([ \t\n]\\|\\\\\n\\)+"
+ "if"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "("
+ "\\=")
+ nil t)
+ (not (c-save-buffer-state () (c-in-literal))))
+ (delete-region (match-beginning 0) (match-end 0))
+ (insert-and-inherit "} else if ("))
+
+ ;; clean up brace-catch-brace
+ (when
+ (and (memq 'brace-catch-brace c-cleanup-list)
+ (eq (c-last-command-char) ?\()
+ (re-search-backward
+ (concat "}"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "catch"
+ "\\([ \t\n]\\|\\\\\n\\)*"
+ "("
+ "\\=")
+ nil t)
+ (not (c-save-buffer-state () (c-in-literal))))
+ (delete-region (match-beginning 0) (match-end 0))
+ (insert-and-inherit "} catch ("))))
;; Apply `electric-pair-mode' stuff.
(when (and (boundp 'electric-pair-mode)
@@ -1362,41 +1379,42 @@ newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
(let (post-self-insert-hook)
(electric-pair-post-self-insert-function)))
- ;; Check for clean-ups at function calls. These two DON'T need
- ;; `c-electric-flag' or `c-syntactic-indentation' set.
- ;; Point is currently just after the inserted paren.
- (let (beg (end (1- (point))))
- (cond
-
- ;; space-before-funcall clean-up?
- ((and (memq 'space-before-funcall c-cleanup-list)
- (eq (c-last-command-char) ?\()
- (save-excursion
- (backward-char)
- (skip-chars-backward " \t")
- (setq beg (point))
- (and (c-save-buffer-state () (c-on-identifier))
- ;; Don't add a space into #define FOO()....
- (not (and (c-beginning-of-macro)
- (c-forward-over-cpp-define-id)
- (eq (point) beg))))))
- (save-excursion
- (delete-region beg end)
- (goto-char beg)
- (insert ?\ )))
-
- ;; compact-empty-funcall clean-up?
- ((c-save-buffer-state ()
- (and (memq 'compact-empty-funcall c-cleanup-list)
- (eq (c-last-command-char) ?\))
- (save-excursion
- (c-safe (backward-char 2))
- (when (looking-at "()")
- (setq end (point))
- (skip-chars-backward " \t")
- (setq beg (point))
- (c-on-identifier)))))
- (delete-region beg end))))
+ (c-with-string-fences
+ ;; Check for clean-ups at function calls. These two DON'T need
+ ;; `c-electric-flag' or `c-syntactic-indentation' set.
+ ;; Point is currently just after the inserted paren.
+ (let (beg (end (1- (point))))
+ (cond
+
+ ;; space-before-funcall clean-up?
+ ((and (memq 'space-before-funcall c-cleanup-list)
+ (eq (c-last-command-char) ?\()
+ (save-excursion
+ (backward-char)
+ (skip-chars-backward " \t")
+ (setq beg (point))
+ (and (c-save-buffer-state () (c-on-identifier))
+ ;; Don't add a space into #define FOO()....
+ (not (and (c-beginning-of-macro)
+ (c-forward-over-cpp-define-id)
+ (eq (point) beg))))))
+ (save-excursion
+ (delete-region beg end)
+ (goto-char beg)
+ (insert ?\ )))
+
+ ;; compact-empty-funcall clean-up?
+ ((c-save-buffer-state ()
+ (and (memq 'compact-empty-funcall c-cleanup-list)
+ (eq (c-last-command-char) ?\))
+ (save-excursion
+ (c-safe (backward-char 2))
+ (when (looking-at "()")
+ (setq end (point))
+ (skip-chars-backward " \t")
+ (setq beg (point))
+ (c-on-identifier)))))
+ (delete-region beg end)))))
(and (eq last-input-event ?\))
(not executing-kbd-macro)
old-blink-paren
@@ -1405,8 +1423,8 @@ newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
;; Apply `electric-pair-mode' stuff inside a string or comment.
(when (and (boundp 'electric-pair-mode) electric-pair-mode)
(let (post-self-insert-hook)
- (electric-pair-post-self-insert-function))))
- (c--call-post-self-insert-hook-more-safely)))
+ (electric-pair-post-self-insert-function)))))
+ (c--call-post-self-insert-hook-more-safely))
(defun c-electric-continued-statement ()
"Reindent the current line if appropriate.
@@ -1868,70 +1886,71 @@ defun."
(c-region-is-active-p)
(push-mark))
- (c-save-buffer-state
- (beginning-of-defun-function
- end-of-defun-function
- (paren-state (c-parse-state))
- (orig-point-min (point-min)) (orig-point-max (point-max))
- lim ; Position of { which has been widened to.
- where pos case-fold-search)
-
- (save-restriction
- (if (eq c-defun-tactic 'go-outward)
- (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
- paren-state orig-point-min orig-point-max)))
-
- ;; Move back out of any macro/comment/string we happen to be in.
- (c-beginning-of-macro)
- (setq pos (c-literal-start))
- (if pos (goto-char pos))
-
- (setq where (c-where-wrt-brace-construct))
-
- (if (< arg 0)
- ;; Move forward to the closing brace of a function.
- (progn
- (if (memq where '(at-function-end outwith-function))
- (setq arg (1+ arg)))
- (if (< arg 0)
- (c-while-widening-to-decl-block
- (< (setq arg (- (c-forward-to-nth-EOF-\;-or-} (- arg) where))) 0)))
- (prog1
- ;; Move forward to the next opening brace....
- (when (and (= arg 0)
- (progn
- (c-while-widening-to-decl-block
- (not (c-syntactic-re-search-forward "{" nil 'eob)))
- (eq (char-before) ?{)))
- (backward-char)
- ;; ... and backward to the function header.
- (c-beginning-of-decl-1)
- t)
- (c-keep-region-active)))
-
- ;; Move backward to the opening brace of a function, making successively
- ;; larger portions of the buffer visible as necessary.
- (when (> arg 0)
- (c-while-widening-to-decl-block
- (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
-
- (when (eq arg 0)
- ;; Go backward to this function's header.
- (c-beginning-of-decl-1)
-
- (setq pos (point))
- ;; We're now there, modulo comments and whitespace.
- ;; Try to be line oriented; position point at the closest
- ;; preceding boi that isn't inside a comment, but if we hit
- ;; the previous declaration then we use the current point
- ;; instead.
- (while (and (/= (point) (c-point 'boi))
- (c-backward-single-comment)))
- (if (/= (point) (c-point 'boi))
- (goto-char pos)))
-
- (c-keep-region-active)
- (= arg 0)))))
+ (c-with-string-fences
+ (c-save-buffer-state
+ (beginning-of-defun-function
+ end-of-defun-function
+ (paren-state (c-parse-state))
+ (orig-point-min (point-min)) (orig-point-max (point-max))
+ lim ; Position of { which has been widened to.
+ where pos case-fold-search)
+
+ (save-restriction
+ (if (eq c-defun-tactic 'go-outward)
+ (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
+ paren-state orig-point-min orig-point-max)))
+
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-start))
+ (if pos (goto-char pos))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move forward to the closing brace of a function.
+ (progn
+ (if (memq where '(at-function-end outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (c-while-widening-to-decl-block
+ (< (setq arg (- (c-forward-to-nth-EOF-\;-or-} (- arg) where))) 0)))
+ (prog1
+ ;; Move forward to the next opening brace....
+ (when (and (= arg 0)
+ (progn
+ (c-while-widening-to-decl-block
+ (not (c-syntactic-re-search-forward "{" nil 'eob)))
+ (eq (char-before) ?{)))
+ (backward-char)
+ ;; ... and backward to the function header.
+ (c-beginning-of-decl-1)
+ t)
+ (c-keep-region-active)))
+
+ ;; Move backward to the opening brace of a function, making successively
+ ;; larger portions of the buffer visible as necessary.
+ (when (> arg 0)
+ (c-while-widening-to-decl-block
+ (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
+
+ (when (eq arg 0)
+ ;; Go backward to this function's header.
+ (c-beginning-of-decl-1)
+
+ (setq pos (point))
+ ;; We're now there, modulo comments and whitespace.
+ ;; Try to be line oriented; position point at the closest
+ ;; preceding boi that isn't inside a comment, but if we hit
+ ;; the previous declaration then we use the current point
+ ;; instead.
+ (while (and (/= (point) (c-point 'boi))
+ (c-backward-single-comment)))
+ (if (/= (point) (c-point 'boi))
+ (goto-char pos)))
+
+ (c-keep-region-active)
+ (= arg 0))))))
(defun c-forward-to-nth-EOF-\;-or-} (n where)
;; Skip to the closing brace or semicolon of the Nth function after point.
@@ -1998,65 +2017,66 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
(c-region-is-active-p)
(push-mark))
- (c-save-buffer-state
- (beginning-of-defun-function
- end-of-defun-function
- (paren-state (c-parse-state))
- (orig-point-min (point-min)) (orig-point-max (point-max))
- lim
- where pos case-fold-search)
-
- (save-restriction
- (if (eq c-defun-tactic 'go-outward)
- (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
- paren-state orig-point-min orig-point-max)))
-
- ;; Move back out of any macro/comment/string we happen to be in.
- (c-beginning-of-macro)
- (setq pos (c-literal-start))
- (if pos (goto-char pos))
+ (c-with-string-fences
+ (c-save-buffer-state
+ (beginning-of-defun-function
+ end-of-defun-function
+ (paren-state (c-parse-state))
+ (orig-point-min (point-min)) (orig-point-max (point-max))
+ lim
+ where pos case-fold-search)
+
+ (save-restriction
+ (if (eq c-defun-tactic 'go-outward)
+ (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
+ paren-state orig-point-min orig-point-max)))
+
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-start))
+ (if pos (goto-char pos))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move backwards to the } of a function
+ (progn
+ (if (memq where '(at-header outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (c-while-widening-to-decl-block
+ (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
+ (if (= arg 0)
+ (c-while-widening-to-decl-block
+ (progn (c-syntactic-skip-backward "^}")
+ (not (eq (char-before) ?}))))))
+
+ ;; Move forward to the } of a function
+ (if (> arg 0)
+ (c-while-widening-to-decl-block
+ (> (setq arg (c-forward-to-nth-EOF-\;-or-} arg where)) 0))))
+
+ ;; Do we need to move forward from the brace to the semicolon?
+ (when (eq arg 0)
+ (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
+ (c-syntactic-re-search-forward ";"))
- (setq where (c-where-wrt-brace-construct))
+ (setq pos (point))
+ ;; We're there now, modulo comments and whitespace.
+ ;; Try to be line oriented; position point after the next
+ ;; newline that isn't inside a comment, but if we hit the
+ ;; next declaration then we use the current point instead.
+ (while (and (not (bolp))
+ (not (looking-at "\\s *$"))
+ (c-forward-single-comment)))
+ (cond ((bolp))
+ ((looking-at "\\s *$")
+ (forward-line 1))
+ (t
+ (goto-char pos))))
- (if (< arg 0)
- ;; Move backwards to the } of a function
- (progn
- (if (memq where '(at-header outwith-function))
- (setq arg (1+ arg)))
- (if (< arg 0)
- (c-while-widening-to-decl-block
- (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
- (if (= arg 0)
- (c-while-widening-to-decl-block
- (progn (c-syntactic-skip-backward "^}")
- (not (eq (char-before) ?}))))))
-
- ;; Move forward to the } of a function
- (if (> arg 0)
- (c-while-widening-to-decl-block
- (> (setq arg (c-forward-to-nth-EOF-\;-or-} arg where)) 0))))
-
- ;; Do we need to move forward from the brace to the semicolon?
- (when (eq arg 0)
- (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
- (c-syntactic-re-search-forward ";"))
-
- (setq pos (point))
- ;; We're there now, modulo comments and whitespace.
- ;; Try to be line oriented; position point after the next
- ;; newline that isn't inside a comment, but if we hit the
- ;; next declaration then we use the current point instead.
- (while (and (not (bolp))
- (not (looking-at "\\s *$"))
- (c-forward-single-comment)))
- (cond ((bolp))
- ((looking-at "\\s *$")
- (forward-line 1))
- (t
- (goto-char pos))))
-
- (c-keep-region-active)
- (= arg 0))))
+ (c-keep-region-active)
+ (= arg 0)))))
(defun c-defun-name-1 ()
"Return name of current defun, at current narrowing, or nil if there isn't one.
@@ -2095,13 +2115,12 @@ with a brace block."
(c-forward-syntactic-ws)
(when (eq (char-after) ?\")
(forward-sexp 1)
+ (c-forward-syntactic-ws)
(c-forward-token-2)) ; over the comma and following WS.
- (buffer-substring-no-properties
- (point)
- (progn
- (c-forward-token-2)
- (c-backward-syntactic-ws)
- (point))))
+ (setq pos (point))
+ (and (zerop (c-forward-token-2))
+ (progn (c-backward-syntactic-ws) t)
+ (buffer-substring-no-properties pos (point))))
((and (c-major-mode-is 'objc-mode) (looking-at "[-+]\\s-*(")) ; Objective-C method
;; Move to the beginning of the method name.
@@ -2342,18 +2361,19 @@ with a brace block, at the outermost level of nesting."
"Display the name of the current CC mode defun and the position in it.
With a prefix arg, push the name onto the kill ring too."
(interactive "P")
- (save-restriction
- (widen)
- (c-save-buffer-state ((name-and-limits (c-defun-name-and-limits nil))
- (name (car name-and-limits))
- (limits (cdr name-and-limits))
- (point-bol (c-point 'bol)))
- (when name
- (message "%s. Line %s/%s." name
- (1+ (count-lines (car limits) (max point-bol (car limits))))
- (count-lines (car limits) (cdr limits)))
- (if arg (kill-new name))
- (sit-for 3 t)))))
+ (c-with-string-fences
+ (save-restriction
+ (widen)
+ (c-save-buffer-state ((name-and-limits (c-defun-name-and-limits nil))
+ (name (car name-and-limits))
+ (limits (cdr name-and-limits))
+ (point-bol (c-point 'bol)))
+ (when name
+ (message "%s. Line %s/%s." name
+ (1+ (count-lines (car limits) (max point-bol (car limits))))
+ (count-lines (car limits) (cdr limits)))
+ (if arg (kill-new name))
+ (sit-for 3 t))))))
(put 'c-display-defun-name 'isearch-scroll t)
(defun c-mark-function ()
@@ -2369,34 +2389,35 @@ As opposed to \\[c-beginning-of-defun] and \\[c-end-of-defun], this
function does not require the declaration to contain a brace block."
(interactive)
- (let (decl-limits case-fold-search)
- (c-save-buffer-state nil
- ;; We try to be line oriented, unless there are several
- ;; declarations on the same line.
- (if (looking-at c-syntactic-eol)
- (c-backward-token-2 1 nil (c-point 'bol)))
- (setq decl-limits (c-declaration-limits t)))
-
- (if (not decl-limits)
- (error "Cannot find any declaration")
- (let* ((extend-region-p
- (and (eq this-command 'c-mark-function)
- (eq last-command 'c-mark-function)))
- (push-mark-p (and (eq this-command 'c-mark-function)
- (not extend-region-p)
- (not (c-region-is-active-p)))))
- (if push-mark-p (push-mark))
- (if extend-region-p
- (progn
- (exchange-point-and-mark)
- (setq decl-limits (c-declaration-limits t))
- (when (not decl-limits)
- (exchange-point-and-mark)
- (error "Cannot find any declaration"))
- (goto-char (cdr decl-limits))
- (exchange-point-and-mark))
- (goto-char (car decl-limits))
- (push-mark (cdr decl-limits) nil t))))))
+ (c-with-string-fences
+ (let (decl-limits case-fold-search)
+ (c-save-buffer-state nil
+ ;; We try to be line oriented, unless there are several
+ ;; declarations on the same line.
+ (if (looking-at c-syntactic-eol)
+ (c-backward-token-2 1 nil (c-point 'bol)))
+ (setq decl-limits (c-declaration-limits t)))
+
+ (if (not decl-limits)
+ (error "Cannot find any declaration")
+ (let* ((extend-region-p
+ (and (eq this-command 'c-mark-function)
+ (eq last-command 'c-mark-function)))
+ (push-mark-p (and (eq this-command 'c-mark-function)
+ (not extend-region-p)
+ (not (c-region-is-active-p)))))
+ (if push-mark-p (push-mark))
+ (if extend-region-p
+ (progn
+ (exchange-point-and-mark)
+ (setq decl-limits (c-declaration-limits t))
+ (when (not decl-limits)
+ (exchange-point-and-mark)
+ (error "Cannot find any declaration"))
+ (goto-char (cdr decl-limits))
+ (exchange-point-and-mark))
+ (goto-char (car decl-limits))
+ (push-mark (cdr decl-limits) nil t)))))))
(defun c-cpp-define-name ()
"Return the name of the current CPP macro, or NIL if we're not in one."
@@ -3033,85 +3054,86 @@ be more \"DWIM:ey\"."
nil t))
(if (< count 0)
(c-end-of-statement (- count) lim sentence-flag)
- (c-save-buffer-state
- ((count (or count 1))
- last ; start point for going back ONE chunk. Updated each chunk movement.
- (macro-fence
- (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
- res ; result from sub-function call
- not-bos ; "not beginning-of-statement"
- (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
-
- ;; Go back one statement at each iteration of the following loop.
- (while (and (/= count 0)
- (or (not lim) (> (point) lim)))
- ;; Go back one "chunk" each time round the following loop, stopping
- ;; when we reach a statement boundary, etc.
- (setq last (point))
- (while
- (cond ; Each arm of this cond returns NIL on reaching a desired
- ; statement boundary, non-NIL otherwise.
- ((bobp)
- (setq count 0)
- nil)
-
- (range ; point is within or approaching a literal.
- (cond
- ;; Single line string or sentence-flag is null => skip the
- ;; entire literal.
- ((or (null sentence-flag)
- (c-one-line-string-p range))
- (goto-char (car range))
- (setq range (c-ascertain-preceding-literal))
- ;; N.B. The following is essentially testing for an AWK regexp
- ;; at BOS:
- ;; Was the previous non-ws thing an end of statement?
- (save-excursion
- (if macro-fence
- (c-backward-comments)
- (c-backward-syntactic-ws))
- (not (or (bobp) (c-after-statement-terminator-p)))))
-
- ;; Comment inside a statement or a multi-line string.
- (t (when (setq res ; returns non-nil when we go out of the literal
- (if (eq (c-literal-type range) 'string)
- (c-beginning-of-sentence-in-string range)
- (c-beginning-of-sentence-in-comment range)))
- (setq range (c-ascertain-preceding-literal)))
- res)))
-
- ;; Non-literal code.
- (t (setq res (c-back-over-illiterals macro-fence))
- (setq not-bos ; "not reached beginning-of-statement".
- (or (= (point) last)
- (memq (char-after) '(?\) ?\}))
- (and
- (car res)
- ;; We're at a tentative BOS. The next form goes
- ;; back over WS looking for an end of previous
- ;; statement.
- (not (save-excursion
- (if macro-fence
- (c-backward-comments)
- (c-backward-syntactic-ws))
- (or (bobp) (c-after-statement-terminator-p)))))))
- ;; Are we about to move backwards into or out of a
- ;; preprocessor command? If so, locate its beginning.
- (when (eq (cdr res) 'macro-boundary)
- (save-excursion
- (beginning-of-line)
- (setq macro-fence
- (and (not (bobp))
- (progn (c-skip-ws-backward) (c-beginning-of-macro))
- (point)))))
- ;; Are we about to move backwards into a literal?
- (when (memq (cdr res) '(macro-boundary literal))
- (setq range (c-ascertain-preceding-literal)))
- not-bos))
- (setq last (point)))
-
- (if (/= count 0) (setq count (1- count))))
- (c-keep-region-active))))
+ (c-with-string-fences
+ (c-save-buffer-state
+ ((count (or count 1))
+ last ; start point for going back ONE chunk. Updated each chunk movement.
+ (macro-fence
+ (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
+ res ; result from sub-function call
+ not-bos ; "not beginning-of-statement"
+ (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+ ;; Go back one statement at each iteration of the following loop.
+ (while (and (/= count 0)
+ (or (not lim) (> (point) lim)))
+ ;; Go back one "chunk" each time round the following loop, stopping
+ ;; when we reach a statement boundary, etc.
+ (setq last (point))
+ (while
+ (cond ; Each arm of this cond returns NIL on reaching a desired
+ ; statement boundary, non-NIL otherwise.
+ ((bobp)
+ (setq count 0)
+ nil)
+
+ (range ; point is within or approaching a literal.
+ (cond
+ ;; Single line string or sentence-flag is null => skip the
+ ;; entire literal.
+ ((or (null sentence-flag)
+ (c-one-line-string-p range))
+ (goto-char (car range))
+ (setq range (c-ascertain-preceding-literal))
+ ;; N.B. The following is essentially testing for an AWK regexp
+ ;; at BOS:
+ ;; Was the previous non-ws thing an end of statement?
+ (save-excursion
+ (if macro-fence
+ (c-backward-comments)
+ (c-backward-syntactic-ws))
+ (not (or (bobp) (c-after-statement-terminator-p)))))
+
+ ;; Comment inside a statement or a multi-line string.
+ (t (when (setq res ; returns non-nil when we go out of the literal
+ (if (eq (c-literal-type range) 'string)
+ (c-beginning-of-sentence-in-string range)
+ (c-beginning-of-sentence-in-comment range)))
+ (setq range (c-ascertain-preceding-literal)))
+ res)))
+
+ ;; Non-literal code.
+ (t (setq res (c-back-over-illiterals macro-fence))
+ (setq not-bos ; "not reached beginning-of-statement".
+ (or (= (point) last)
+ (memq (char-after) '(?\) ?\}))
+ (and
+ (car res)
+ ;; We're at a tentative BOS. The next form goes
+ ;; back over WS looking for an end of previous
+ ;; statement.
+ (not (save-excursion
+ (if macro-fence
+ (c-backward-comments)
+ (c-backward-syntactic-ws))
+ (or (bobp) (c-after-statement-terminator-p)))))))
+ ;; Are we about to move backwards into or out of a
+ ;; preprocessor command? If so, locate its beginning.
+ (when (eq (cdr res) 'macro-boundary)
+ (save-excursion
+ (beginning-of-line)
+ (setq macro-fence
+ (and (not (bobp))
+ (progn (c-skip-ws-backward) (c-beginning-of-macro))
+ (point)))))
+ ;; Are we about to move backwards into a literal?
+ (when (memq (cdr res) '(macro-boundary literal))
+ (setq range (c-ascertain-preceding-literal)))
+ not-bos))
+ (setq last (point)))
+
+ (if (/= count 0) (setq count (1- count))))
+ (c-keep-region-active)))))
(defun c-end-of-statement (&optional count lim sentence-flag)
"Go to the end of the innermost C statement.
@@ -3129,78 +3151,79 @@ sentence motion in or near comments and multiline strings."
(setq count (or count 1))
(if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag)
- (c-save-buffer-state
- (here ; start point for going forward ONE statement. Updated each statement.
- (macro-fence
- (save-excursion
- (and (not (eobp)) (c-beginning-of-macro)
- (progn (c-end-of-macro) (point)))))
- res
- (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
-
- ;; Go back/forward one statement at each iteration of the following loop.
- (while (and (/= count 0)
- (or (not lim) (< (point) lim)))
- (setq here (point)) ; ONLY HERE is HERE updated
-
- ;; Go forward one "chunk" each time round the following loop, stopping
- ;; when we reach a statement boundary, etc.
- (while
- (cond ; Each arm of this cond returns NIL on reaching a desired
- ; statement boundary, non-NIL otherwise.
- ((eobp)
- (setq count 0)
- nil)
+ (c-with-string-fences
+ (c-save-buffer-state
+ (here ; start point for going forward ONE statement. Updated each statement.
+ (macro-fence
+ (save-excursion
+ (and (not (eobp)) (c-beginning-of-macro)
+ (progn (c-end-of-macro) (point)))))
+ res
+ (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+ ;; Go back/forward one statement at each iteration of the following loop.
+ (while (and (/= count 0)
+ (or (not lim) (< (point) lim)))
+ (setq here (point)) ; ONLY HERE is HERE updated
+
+ ;; Go forward one "chunk" each time round the following loop, stopping
+ ;; when we reach a statement boundary, etc.
+ (while
+ (cond ; Each arm of this cond returns NIL on reaching a desired
+ ; statement boundary, non-NIL otherwise.
+ ((eobp)
+ (setq count 0)
+ nil)
+
+ (range ; point is within a literal.
+ (cond
+ ;; sentence-flag is null => skip the entire literal.
+ ;; or a Single line string.
+ ((or (null sentence-flag)
+ (c-one-line-string-p range))
+ (goto-char (cdr range))
+ (setq range (c-ascertain-following-literal))
+ ;; Is there a virtual semicolon here (e.g. for AWK)?
+ (not (c-at-vsemi-p)))
+
+ ;; Comment or multi-line string.
+ (t (when (setq res ; gets non-nil when we go out of the literal
+ (if (eq (c-literal-type range) 'string)
+ (c-end-of-sentence-in-string range)
+ (c-end-of-sentence-in-comment range)))
+ (setq range (c-ascertain-following-literal)))
+ ;; If we've just come forward out of a literal, check for
+ ;; vsemi. (N.B. AWK can't have a vsemi after a comment, but
+ ;; some other language may do in the future)
+ (and res
+ (not (c-at-vsemi-p))))))
+
+ ;; Non-literal code.
+ (t (setq res (c-forward-over-illiterals macro-fence
+ (> (point) here)))
+ ;; Are we about to move forward into or out of a
+ ;; preprocessor command?
+ (when (eq (cdr res) 'macro-boundary)
+ (setq macro-fence
+ (save-excursion
+ (if macro-fence
+ (progn
+ (end-of-line)
+ (and (not (eobp))
+ (progn (c-skip-ws-forward)
+ (c-beginning-of-macro))
+ (progn (c-end-of-macro)
+ (point))))
+ (and (not (eobp))
+ (c-beginning-of-macro)
+ (progn (c-end-of-macro) (point)))))))
+ ;; Are we about to move forward into a literal?
+ (when (memq (cdr res) '(macro-boundary literal))
+ (setq range (c-ascertain-following-literal)))
+ (car res))))
- (range ; point is within a literal.
- (cond
- ;; sentence-flag is null => skip the entire literal.
- ;; or a Single line string.
- ((or (null sentence-flag)
- (c-one-line-string-p range))
- (goto-char (cdr range))
- (setq range (c-ascertain-following-literal))
- ;; Is there a virtual semicolon here (e.g. for AWK)?
- (not (c-at-vsemi-p)))
-
- ;; Comment or multi-line string.
- (t (when (setq res ; gets non-nil when we go out of the literal
- (if (eq (c-literal-type range) 'string)
- (c-end-of-sentence-in-string range)
- (c-end-of-sentence-in-comment range)))
- (setq range (c-ascertain-following-literal)))
- ;; If we've just come forward out of a literal, check for
- ;; vsemi. (N.B. AWK can't have a vsemi after a comment, but
- ;; some other language may do in the future)
- (and res
- (not (c-at-vsemi-p))))))
-
- ;; Non-literal code.
- (t (setq res (c-forward-over-illiterals macro-fence
- (> (point) here)))
- ;; Are we about to move forward into or out of a
- ;; preprocessor command?
- (when (eq (cdr res) 'macro-boundary)
- (setq macro-fence
- (save-excursion
- (if macro-fence
- (progn
- (end-of-line)
- (and (not (eobp))
- (progn (c-skip-ws-forward)
- (c-beginning-of-macro))
- (progn (c-end-of-macro)
- (point))))
- (and (not (eobp))
- (c-beginning-of-macro)
- (progn (c-end-of-macro) (point)))))))
- ;; Are we about to move forward into a literal?
- (when (memq (cdr res) '(macro-boundary literal))
- (setq range (c-ascertain-following-literal)))
- (car res))))
-
- (if (/= count 0) (setq count (1- count))))
- (c-keep-region-active))))
+ (if (/= count 0) (setq count (1- count))))
+ (c-keep-region-active)))))
;; set up electric character functions to work with pending-del,
@@ -3539,122 +3562,125 @@ prefix argument is equivalent to -1.
depending on the variable `indent-tabs-mode'."
(interactive "P")
- (let ((indent-function
- (if c-syntactic-indentation
- (symbol-function 'indent-according-to-mode)
- (lambda ()
- (let ((c-macro-start c-macro-start)
- (steps (if (equal arg '(4))
- -1
- (prefix-numeric-value arg))))
- (c-shift-line-indentation (* steps c-basic-offset))
- (when (and c-auto-align-backslashes
- (save-excursion
- (end-of-line)
- (eq (char-before) ?\\))
- (c-query-and-set-macro-start))
- ;; Realign the line continuation backslash if inside a macro.
- (c-backslash-region (point) (point) nil t)))
- ))))
- (if (and c-syntactic-indentation arg)
- ;; If c-syntactic-indentation and got arg, always indent this
- ;; line as C and shift remaining lines of expression the same
- ;; amount.
- (let ((shift-amt (save-excursion
- (back-to-indentation)
- (current-column)))
- beg end)
- (c-indent-line)
- (setq shift-amt (- (save-excursion
- (back-to-indentation)
- (current-column))
- shift-amt))
- (save-excursion
- (if (eq c-tab-always-indent t)
- (beginning-of-line)) ; FIXME!!! What is this here for? ACM 2005/10/31
- (setq beg (point))
- (c-forward-sexp 1)
- (setq end (point))
- (goto-char beg)
- (forward-line 1)
- (setq beg (point)))
- (if (> end beg)
- (indent-code-rigidly beg end shift-amt "#")))
- ;; Else use c-tab-always-indent to determine behavior.
- (cond
- ;; CASE 1: indent when at column zero or in line's indentation,
- ;; otherwise insert a tab
- ((not c-tab-always-indent)
- (if (save-excursion
- (skip-chars-backward " \t")
- (not (bolp)))
- (funcall c-insert-tab-function)
- (funcall indent-function)))
- ;; CASE 2: just indent the line
- ((eq c-tab-always-indent t)
- (funcall indent-function))
- ;; CASE 3: if in a literal, insert a tab, but always indent the
- ;; line
- (t
- (if (c-save-buffer-state () (c-in-literal))
- (funcall c-insert-tab-function))
- (funcall indent-function)
- )))))
+ (c-with-string-fences
+ (let ((indent-function
+ (if c-syntactic-indentation
+ (symbol-function 'indent-according-to-mode)
+ (lambda ()
+ (let ((c-macro-start c-macro-start)
+ (steps (if (equal arg '(4))
+ -1
+ (prefix-numeric-value arg))))
+ (c-shift-line-indentation (* steps c-basic-offset))
+ (when (and c-auto-align-backslashes
+ (save-excursion
+ (end-of-line)
+ (eq (char-before) ?\\))
+ (c-query-and-set-macro-start))
+ ;; Realign the line continuation backslash if inside a macro.
+ (c-backslash-region (point) (point) nil t)))
+ ))))
+ (if (and c-syntactic-indentation arg)
+ ;; If c-syntactic-indentation and got arg, always indent this
+ ;; line as C and shift remaining lines of expression the same
+ ;; amount.
+ (let ((shift-amt (save-excursion
+ (back-to-indentation)
+ (current-column)))
+ beg end)
+ (c-indent-line)
+ (setq shift-amt (- (save-excursion
+ (back-to-indentation)
+ (current-column))
+ shift-amt))
+ (save-excursion
+ (if (eq c-tab-always-indent t)
+ (beginning-of-line)) ; FIXME!!! What is this here for? ACM 2005/10/31
+ (setq beg (point))
+ (c-forward-sexp 1)
+ (setq end (point))
+ (goto-char beg)
+ (forward-line 1)
+ (setq beg (point)))
+ (if (> end beg)
+ (indent-code-rigidly beg end shift-amt "#")))
+ ;; Else use c-tab-always-indent to determine behavior.
+ (cond
+ ;; CASE 1: indent when at column zero or in line's indentation,
+ ;; otherwise insert a tab
+ ((not c-tab-always-indent)
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp)))
+ (funcall c-insert-tab-function)
+ (funcall indent-function)))
+ ;; CASE 2: just indent the line
+ ((eq c-tab-always-indent t)
+ (funcall indent-function))
+ ;; CASE 3: if in a literal, insert a tab, but always indent the
+ ;; line
+ (t
+ (if (c-save-buffer-state () (c-in-literal))
+ (funcall c-insert-tab-function))
+ (funcall indent-function)
+ ))))))
(defun c-indent-exp (&optional shutup-p)
"Indent each line in the balanced expression following point syntactically.
If optional SHUTUP-P is non-nil, no errors are signaled if no
balanced expression is found."
(interactive "*P")
- (let ((here (point-marker))
- end)
- (set-marker-insertion-type here t)
- (unwind-protect
- (let ((start (save-restriction
- ;; Find the closest following open paren that
- ;; ends on another line.
- (narrow-to-region (point-min) (c-point 'eol))
- (let (beg (end (point)))
- (while (and (setq beg (c-down-list-forward end))
- (setq end (c-up-list-forward beg))))
- (and beg
- (eq (char-syntax (char-before beg)) ?\()
- (1- beg))))))
- ;; sanity check
- (if (not start)
- (unless shutup-p
- (error "Cannot find start of balanced expression to indent"))
- (goto-char start)
- (setq end (c-safe (scan-sexps (point) 1)))
- (if (not end)
- (unless shutup-p
- (error "Cannot find end of balanced expression to indent"))
- (forward-line)
- (if (< (point) end)
- (c-indent-region (point) end)))))
- (goto-char here)
- (set-marker here nil))))
+ (c-with-string-fences
+ (let ((here (point-marker))
+ end)
+ (set-marker-insertion-type here t)
+ (unwind-protect
+ (let ((start (save-restriction
+ ;; Find the closest following open paren that
+ ;; ends on another line.
+ (narrow-to-region (point-min) (c-point 'eol))
+ (let (beg (end (point)))
+ (while (and (setq beg (c-down-list-forward end))
+ (setq end (c-up-list-forward beg))))
+ (and beg
+ (eq (char-syntax (char-before beg)) ?\()
+ (1- beg))))))
+ ;; sanity check
+ (if (not start)
+ (unless shutup-p
+ (error "Cannot find start of balanced expression to indent"))
+ (goto-char start)
+ (setq end (c-safe (scan-sexps (point) 1)))
+ (if (not end)
+ (unless shutup-p
+ (error "Cannot find end of balanced expression to indent"))
+ (forward-line)
+ (if (< (point) end)
+ (c-indent-region (point) end)))))
+ (goto-char here)
+ (set-marker here nil)))))
(defun c-indent-defun ()
"Indent the current top-level declaration or macro syntactically.
In the macro case this also has the effect of realigning any line
continuation backslashes, unless `c-auto-align-backslashes' is nil."
(interactive "*")
- (let ((here (point-marker)) decl-limits case-fold-search)
- (unwind-protect
- (progn
- (c-save-buffer-state nil
- ;; We try to be line oriented, unless there are several
- ;; declarations on the same line.
- (if (looking-at c-syntactic-eol)
- (c-backward-token-2 1 nil (c-point 'bol))
- (c-forward-token-2 0 nil (c-point 'eol)))
- (setq decl-limits (c-declaration-limits nil)))
- (if decl-limits
- (c-indent-region (car decl-limits)
- (cdr decl-limits))))
- (goto-char here)
- (set-marker here nil))))
+ (c-with-string-fences
+ (let ((here (point-marker)) decl-limits case-fold-search)
+ (unwind-protect
+ (progn
+ (c-save-buffer-state nil
+ ;; We try to be line oriented, unless there are several
+ ;; declarations on the same line.
+ (if (looking-at c-syntactic-eol)
+ (c-backward-token-2 1 nil (c-point 'bol))
+ (c-forward-token-2 0 nil (c-point 'eol)))
+ (setq decl-limits (c-declaration-limits nil)))
+ (if decl-limits
+ (c-indent-region (car decl-limits)
+ (cdr decl-limits))))
+ (goto-char here)
+ (set-marker here nil)))))
(defun c-indent-region (start end &optional quiet)
"Indent syntactically lines whose first char is between START and END inclusive.
@@ -3734,9 +3760,10 @@ starting on the current line.
Otherwise reindent just the current line."
(interactive
(list current-prefix-arg (c-region-is-active-p)))
- (if region
- (c-indent-region (region-beginning) (region-end))
- (c-indent-command arg)))
+ (c-with-string-fences
+ (if region
+ (c-indent-region (region-beginning) (region-end))
+ (c-indent-command arg))))
;; for progress reporting
(defvar c-progress-info nil)
@@ -4823,15 +4850,16 @@ If point is in any other situation, i.e. in normal code, do nothing.
Optional prefix ARG means justify paragraph as well."
(interactive "*P")
- (let ((fill-paragraph-function
- ;; Avoid infinite recursion.
- (if (not (eq fill-paragraph-function 'c-fill-paragraph))
- fill-paragraph-function)))
- (c-mask-paragraph t nil 'fill-paragraph arg))
- ;; Always return t. This has the effect that if filling isn't done
- ;; above, it isn't done at all, and it's therefore effectively
- ;; disabled in normal code.
- t)
+ (c-with-string-fences
+ (let ((fill-paragraph-function
+ ;; Avoid infinite recursion.
+ (if (not (eq fill-paragraph-function 'c-fill-paragraph))
+ fill-paragraph-function)))
+ (c-mask-paragraph t nil 'fill-paragraph arg))
+ ;; Always return t. This has the effect that if filling isn't done
+ ;; above, it isn't done at all, and it's therefore effectively
+ ;; disabled in normal code.
+ t))
(defun c-do-auto-fill ()
;; Do automatic filling if not inside a context where it should be
@@ -4863,181 +4891,170 @@ If a fill prefix is specified, it overrides all the above."
;; used from auto-fill itself, that's normally disabled to avoid
;; unnecessary recursion.
(interactive)
- (let ((fill-prefix fill-prefix)
- (do-line-break
- (lambda ()
- (delete-horizontal-space)
- (if soft
- (insert-and-inherit ?\n)
- (newline (if allow-auto-fill nil 1)))))
- ;; Already know the literal type and limits when called from
- ;; c-context-line-break.
- (c-lit-limits c-lit-limits)
- (c-lit-type c-lit-type)
- (c-macro-start c-macro-start))
-
- (c-save-buffer-state ()
- (when (not (eq c-auto-fill-prefix t))
- ;; Called from do-auto-fill.
- (unless c-lit-limits
- (setq c-lit-limits (c-literal-limits nil nil t)))
- (unless c-lit-type
- (setq c-lit-type (c-literal-type c-lit-limits)))
- (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
- ((null c-lit-type) 'code)
- (t c-lit-type))
- c-ignore-auto-fill)
- (setq fill-prefix t) ; Used as flag in the cond.
- (if (and (null c-auto-fill-prefix)
- (eq c-lit-type 'c)
- (<= (c-point 'bol) (car c-lit-limits)))
- ;; The adaptive fill function has generated a prefix, but
- ;; we're on the first line in a block comment so it'll be
- ;; wrong. Ignore it to guess a better one below.
- (setq fill-prefix nil)
- (when (and (eq c-lit-type 'c++)
- (not (string-match (concat "\\`[ \t]*"
- c-line-comment-starter)
- (or fill-prefix ""))))
- ;; Kludge: If the function that adapted the fill prefix
- ;; doesn't produce the required comment starter for line
- ;; comments, then we ignore it.
- (setq fill-prefix nil)))
- )))
-
- (cond ((eq fill-prefix t)
- ;; A call from do-auto-fill which should be ignored.
- )
- (fill-prefix
- ;; A fill-prefix overrides anything.
- (funcall do-line-break)
- (insert-and-inherit fill-prefix))
- ((c-save-buffer-state ()
- (unless c-lit-limits
- (setq c-lit-limits (c-literal-limits)))
- (unless c-lit-type
- (setq c-lit-type (c-literal-type c-lit-limits)))
- (memq c-lit-type '(c c++)))
- ;; Some sort of comment.
- (if (or comment-multi-line
- (save-excursion
- (goto-char (car c-lit-limits))
- (end-of-line)
- (< (point) (cdr c-lit-limits))))
- ;; Inside a comment that should be continued.
- (let ((fill (c-save-buffer-state nil
- (c-guess-fill-prefix
- (setq c-lit-limits
- (c-collect-line-comments c-lit-limits))
- c-lit-type)))
- (pos (point))
- (comment-text-end
- (or (and (eq c-lit-type 'c)
- (save-excursion
- (goto-char (- (cdr c-lit-limits) 2))
- (if (looking-at "\\*/") (point))))
- (cdr c-lit-limits))))
- ;; Skip forward past the fill prefix in case
- ;; we're standing in it.
- ;;
- ;; FIXME: This doesn't work well in cases like
- ;;
- ;; /* Bla bla bla bla bla
- ;; bla bla
- ;;
- ;; If point is on the 'B' then the line will be
- ;; broken after "Bla b".
- ;;
- ;; If we have an empty comment, /* */, the next
- ;; lot of code pushes point to the */. We fix
- ;; this by never allowing point to end up to the
- ;; right of where it started.
- (while (and (< (current-column) (cdr fill))
- (not (eolp)))
- (forward-char 1))
- (if (and (> (point) comment-text-end)
- (> (c-point 'bol) (car c-lit-limits)))
- (progn
- ;; The skip takes us out of the (block)
- ;; comment; insert the fill prefix at bol
- ;; instead and keep the position.
- (setq pos (copy-marker pos t))
- (beginning-of-line)
- (insert-and-inherit (car fill))
- (if soft (insert-and-inherit ?\n) (newline 1))
- (goto-char pos)
- (set-marker pos nil))
- ;; Don't break in the middle of a comment starter
- ;; or ender.
- (cond ((> (point) comment-text-end)
- (goto-char comment-text-end))
- ((< (point) (+ (car c-lit-limits) 2))
- (goto-char (+ (car c-lit-limits) 2))))
- (funcall do-line-break)
- (insert-and-inherit (car fill))
- (if (and (looking-at c-block-comment-ender-regexp)
- (memq (char-before) '(?\ ?\t)))
- (backward-char)))) ; can this hit the
- ; middle of a TAB?
- ;; Inside a comment that should be broken.
- (let ((comment-start comment-start)
- (comment-end comment-end)
- col)
- (if (eq c-lit-type 'c)
- (unless (string-match "[ \t]*/\\*" comment-start)
- (setq comment-start "/* " comment-end " */"))
- (unless (string-match "[ \t]*//" comment-start)
- (setq comment-start "// " comment-end "")))
- (setq col (save-excursion
- (back-to-indentation)
- (current-column)))
- (funcall do-line-break)
- (when (and comment-end (not (equal comment-end "")))
- (forward-char -1)
- (insert-and-inherit comment-end)
- (forward-char 1))
- ;; c-comment-indent may look at the current
- ;; indentation, so let's start out with the same
- ;; indentation as the previous one.
- (indent-to col)
- (insert-and-inherit comment-start)
- (indent-for-comment))))
- ((c-query-and-set-macro-start)
- ;; In a macro.
- (unless (looking-at "[ \t]*\\\\$")
- ;; Do not clobber the alignment of the line continuation
- ;; slash; c-backslash-region might look at it.
- (delete-horizontal-space))
- ;; Got an asymmetry here: In normal code this command
- ;; doesn't indent the next line syntactically, and otoh a
- ;; normal syntactically indenting newline doesn't continue
- ;; the macro.
- (c-newline-and-indent (if allow-auto-fill nil 1)))
- (t
- ;; Somewhere else in the code.
- (let ((col (save-excursion
+ (c-with-string-fences
+ (let ((fill-prefix fill-prefix)
+ (do-line-break
+ (lambda ()
+ (delete-horizontal-space)
+ (if soft
+ (insert-and-inherit ?\n)
+ (newline (if allow-auto-fill nil 1)))))
+ ;; Already know the literal type and limits when called from
+ ;; c-context-line-break.
+ (c-lit-limits c-lit-limits)
+ (c-lit-type c-lit-type)
+ (c-macro-start c-macro-start))
+
+ (c-save-buffer-state ()
+ (when (not (eq c-auto-fill-prefix t))
+ ;; Called from do-auto-fill.
+ (unless c-lit-limits
+ (setq c-lit-limits (c-literal-limits nil nil t)))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits)))
+ (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+ ((null c-lit-type) 'code)
+ (t c-lit-type))
+ c-ignore-auto-fill)
+ (setq fill-prefix t) ; Used as flag in the cond.
+ (if (and (null c-auto-fill-prefix)
+ (eq c-lit-type 'c)
+ (<= (c-point 'bol) (car c-lit-limits)))
+ ;; The adaptive fill function has generated a prefix, but
+ ;; we're on the first line in a block comment so it'll be
+ ;; wrong. Ignore it to guess a better one below.
+ (setq fill-prefix nil)
+ (when (and (eq c-lit-type 'c++)
+ (not (string-match (concat "\\`[ \t]*"
+ c-line-comment-starter)
+ (or fill-prefix ""))))
+ ;; Kludge: If the function that adapted the fill prefix
+ ;; doesn't produce the required comment starter for line
+ ;; comments, then we ignore it.
+ (setq fill-prefix nil)))
+ )))
+
+ (cond ((eq fill-prefix t)
+ ;; A call from do-auto-fill which should be ignored.
+ )
+ (fill-prefix
+ ;; A fill-prefix overrides anything.
+ (funcall do-line-break)
+ (insert-and-inherit fill-prefix))
+ ((c-save-buffer-state ()
+ (unless c-lit-limits
+ (setq c-lit-limits (c-literal-limits)))
+ (unless c-lit-type
+ (setq c-lit-type (c-literal-type c-lit-limits)))
+ (memq c-lit-type '(c c++)))
+ ;; Some sort of comment.
+ (if (or comment-multi-line
+ (save-excursion
+ (goto-char (car c-lit-limits))
+ (end-of-line)
+ (< (point) (cdr c-lit-limits))))
+ ;; Inside a comment that should be continued.
+ (let ((fill (c-save-buffer-state nil
+ (c-guess-fill-prefix
+ (setq c-lit-limits
+ (c-collect-line-comments c-lit-limits))
+ c-lit-type)))
+ (pos (point))
+ (comment-text-end
+ (or (and (eq c-lit-type 'c)
+ (save-excursion
+ (goto-char (- (cdr c-lit-limits) 2))
+ (if (looking-at "\\*/") (point))))
+ (cdr c-lit-limits))))
+ ;; Skip forward past the fill prefix in case
+ ;; we're standing in it.
+ ;;
+ ;; FIXME: This doesn't work well in cases like
+ ;;
+ ;; /* Bla bla bla bla bla
+ ;; bla bla
+ ;;
+ ;; If point is on the 'B' then the line will be
+ ;; broken after "Bla b".
+ ;;
+ ;; If we have an empty comment, /* */, the next
+ ;; lot of code pushes point to the */. We fix
+ ;; this by never allowing point to end up to the
+ ;; right of where it started.
+ (while (and (< (current-column) (cdr fill))
+ (not (eolp)))
+ (forward-char 1))
+ (if (and (> (point) comment-text-end)
+ (> (c-point 'bol) (car c-lit-limits)))
+ (progn
+ ;; The skip takes us out of the (block)
+ ;; comment; insert the fill prefix at bol
+ ;; instead and keep the position.
+ (setq pos (copy-marker pos t))
(beginning-of-line)
- (while (and (looking-at "[ \t]*\\\\?$")
- (= (forward-line -1) 0)))
- (current-indentation))))
- (funcall do-line-break)
- (indent-to col))))))
+ (insert-and-inherit (car fill))
+ (if soft (insert-and-inherit ?\n) (newline 1))
+ (goto-char pos)
+ (set-marker pos nil))
+ ;; Don't break in the middle of a comment starter
+ ;; or ender.
+ (cond ((> (point) comment-text-end)
+ (goto-char comment-text-end))
+ ((< (point) (+ (car c-lit-limits) 2))
+ (goto-char (+ (car c-lit-limits) 2))))
+ (funcall do-line-break)
+ (insert-and-inherit (car fill))
+ (if (and (looking-at c-block-comment-ender-regexp)
+ (memq (char-before) '(?\ ?\t)))
+ (backward-char)))) ; can this hit the
+ ; middle of a TAB?
+ ;; Inside a comment that should be broken.
+ (let ((comment-start comment-start)
+ (comment-end comment-end)
+ col)
+ (if (eq c-lit-type 'c)
+ (unless (string-match "[ \t]*/\\*" comment-start)
+ (setq comment-start "/* " comment-end " */"))
+ (unless (string-match "[ \t]*//" comment-start)
+ (setq comment-start "// " comment-end "")))
+ (setq col (save-excursion
+ (back-to-indentation)
+ (current-column)))
+ (funcall do-line-break)
+ (when (and comment-end (not (equal comment-end "")))
+ (forward-char -1)
+ (insert-and-inherit comment-end)
+ (forward-char 1))
+ ;; c-comment-indent may look at the current
+ ;; indentation, so let's start out with the same
+ ;; indentation as the previous one.
+ (indent-to col)
+ (insert-and-inherit comment-start)
+ (indent-for-comment))))
+ ((c-query-and-set-macro-start)
+ ;; In a macro.
+ (unless (looking-at "[ \t]*\\\\$")
+ ;; Do not clobber the alignment of the line continuation
+ ;; slash; c-backslash-region might look at it.
+ (delete-horizontal-space))
+ ;; Got an asymmetry here: In normal code this command
+ ;; doesn't indent the next line syntactically, and otoh a
+ ;; normal syntactically indenting newline doesn't continue
+ ;; the macro.
+ (c-newline-and-indent (if allow-auto-fill nil 1)))
+ (t
+ ;; Somewhere else in the code.
+ (let ((col (save-excursion
+ (beginning-of-line)
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (current-indentation))))
+ (funcall do-line-break)
+ (indent-to col)))))))
(defalias 'c-comment-line-break-function 'c-indent-new-comment-line)
(make-obsolete 'c-comment-line-break-function 'c-indent-new-comment-line "21.1")
-;; Advice for Emacsen older than 21.1 (!), released 2001/10
-(unless (boundp 'comment-line-break-function)
- (defvar c-inside-line-break-advice nil)
- (defadvice indent-new-comment-line (around c-line-break-advice
- activate preactivate)
- "Call `c-indent-new-comment-line' if in CC Mode."
- (if (or c-inside-line-break-advice
- (not c-buffer-is-cc-mode))
- ad-do-it
- (let ((c-inside-line-break-advice t))
- (c-indent-new-comment-line (ad-get-arg 0))))))
-
(defun c-context-line-break ()
"Do a line break suitable to the context.
@@ -5060,58 +5077,59 @@ When point is inside a string, only insert a backslash when it is also
inside a preprocessor directive."
(interactive "*")
- (let* (c-lit-limits c-lit-type
- (c-macro-start c-macro-start)
- case-fold-search)
-
- (c-save-buffer-state ()
- (setq c-lit-limits (c-literal-limits nil nil t)
- c-lit-type (c-literal-type c-lit-limits))
- (when (eq c-lit-type 'c++)
- (setq c-lit-limits (c-collect-line-comments c-lit-limits)))
- (c-query-and-set-macro-start))
-
- (cond
- ((or (eq c-lit-type 'c)
- (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it.
- (< (save-excursion
- (skip-chars-forward " \t")
- (point))
- (1- (cdr c-lit-limits))))
- (and (numberp c-macro-start) ; Macro, but not at the very end of
+ (c-with-string-fences
+ (let* (c-lit-limits c-lit-type
+ (c-macro-start c-macro-start)
+ case-fold-search)
+
+ (c-save-buffer-state ()
+ (setq c-lit-limits (c-literal-limits nil nil t)
+ c-lit-type (c-literal-type c-lit-limits))
+ (when (eq c-lit-type 'c++)
+ (setq c-lit-limits (c-collect-line-comments c-lit-limits)))
+ (c-query-and-set-macro-start))
+
+ (cond
+ ((or (eq c-lit-type 'c)
+ (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it.
+ (< (save-excursion
+ (skip-chars-forward " \t")
+ (point))
+ (1- (cdr c-lit-limits))))
+ (and (numberp c-macro-start) ; Macro, but not at the very end of
; it, not in a string, and not in the
; cpp keyword.
- (not (eq c-lit-type 'string))
- (or (not (looking-at "\\s *$"))
- (eq (char-before) ?\\))
- (<= (save-excursion
- (goto-char c-macro-start)
- (if (looking-at c-opt-cpp-start)
- (goto-char (match-end 0)))
- (point))
- (point))))
- (let ((comment-multi-line t)
- (fill-prefix nil))
- (c-indent-new-comment-line nil t)))
-
- ((eq c-lit-type 'string)
- (if (and (numberp c-macro-start)
- (not (eq (char-before) ?\\)))
- (insert ?\\))
- (newline))
-
- (t (delete-horizontal-space)
- (newline)
- ;; c-indent-line may look at the current indentation, so let's
- ;; start out with the same indentation as the previous line.
- (let ((col (save-excursion
- (backward-char)
- (forward-line 0)
- (while (and (looking-at "[ \t]*\\\\?$")
- (= (forward-line -1) 0)))
- (current-indentation))))
- (indent-to col))
- (indent-according-to-mode)))))
+ (not (eq c-lit-type 'string))
+ (or (not (looking-at "\\s *$"))
+ (eq (char-before) ?\\))
+ (<= (save-excursion
+ (goto-char c-macro-start)
+ (if (looking-at c-opt-cpp-start)
+ (goto-char (match-end 0)))
+ (point))
+ (point))))
+ (let ((comment-multi-line t)
+ (fill-prefix nil))
+ (c-indent-new-comment-line nil t)))
+
+ ((eq c-lit-type 'string)
+ (if (and (numberp c-macro-start)
+ (not (eq (char-before) ?\\)))
+ (insert ?\\))
+ (newline))
+
+ (t (delete-horizontal-space)
+ (newline)
+ ;; c-indent-line may look at the current indentation, so let's
+ ;; start out with the same indentation as the previous line.
+ (let ((col (save-excursion
+ (backward-char)
+ (forward-line 0)
+ (while (and (looking-at "[ \t]*\\\\?$")
+ (= (forward-line -1) 0)))
+ (current-indentation))))
+ (indent-to col))
+ (indent-according-to-mode))))))
(defun c-context-open-line ()
"Insert a line break suitable to the context and leave point before it.
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index a1270243550..9edaf465346 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1563,6 +1563,28 @@ with value CHAR in the region [FROM to)."
(forward-char)))))
+;; Miscellaneous macro(s)
+(defvar c-string-fences-set-flag nil)
+;; Non-nil when we have set string fences with `c-restore-string-fences'.
+(defmacro c-with-string-fences (&rest forms)
+ ;; Restore the string fences, evaluate FORMS, then remove them again. It
+ ;; should only be used at the top level of "boundary" functions in CC Mode,
+ ;; i.e. those called from outside CC Mode which directly or indirectly need
+ ;; unbalanced string markers to have their string-fence syntax-table text
+ ;; properties. This includes all calls to `c-parse-state'. This macro will
+ ;; be invoked recursively; however the `c-string-fences-set-flag' mechanism
+ ;; should ensure consistency, when this happens.
+ (declare (debug t))
+ `(unwind-protect
+ (progn
+ (unless c-string-fences-set-flag
+ (c-restore-string-fences))
+ (let ((c-string-fences-set-flag t))
+ ,@forms))
+ (unless c-string-fences-set-flag
+ (c-clear-string-fences))))
+
+
;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text.
;; For our purposes, these are characterized by being possible to
;; remove again without affecting the other text properties in the
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index ebc1ef43010..cfbb668baeb 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1239,7 +1239,7 @@ comment at the start of cc-engine.el for more info."
(not comma-delimited)
(not (c-looking-at-inexpr-block lim nil t))
(save-excursion
- (c-backward-token-2 1 t nil)
+ (c-backward-token-2 1 t nil) ; Don't test the value
(not (looking-at "=\\([^=]\\|$\\)")))
(or
(not c-opt-block-decls-with-vars-key)
@@ -3422,7 +3422,9 @@ initializing CC Mode. Currently (2020-06) these are `js-mode' and
;; Return a good pos (in the sense of `c-state-cache-good-pos') at the
;; lowest[*] position between POS and HERE which is syntactically equivalent
;; to HERE. This position may be HERE itself. POS is before HERE in the
- ;; buffer.
+ ;; buffer. If POS and HERE are both in the same literal, return the start
+ ;; of the literal. STATE is the parsing state at POS.
+ ;;
;; [*] We don't actually always determine this exact position, since this
;; would require a disproportionate amount of work, given that this function
;; deals only with a corner condition, and POS and HERE are typically on
@@ -3438,7 +3440,7 @@ initializing CC Mode. Currently (2020-06) these are `js-mode' and
(setq pos (point)
state s)))
(if (eq (point) here) ; HERE is in the same literal as POS
- pos
+ (nth 8 state) ; A valid good pos cannot be in a literal.
(setq s (parse-partial-sexp pos here (1+ (car state)) nil state nil))
(cond
((> (car s) (car state)) ; Moved into a paren between POS and HERE
@@ -3884,7 +3886,10 @@ initializing CC Mode. Currently (2020-06) these are `js-mode' and
(cons (if (and ce (< bra ce) (> ce here)) ; {..} straddling HERE?
bra
(point-min))
- (min here from)))))))))
+ (progn
+ (goto-char (min here from))
+ (c-beginning-of-macro)
+ (point))))))))))
(defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here)
;; If BRA+1 is nil, do nothing. Otherwise, BRA+1 is the buffer position
@@ -6139,7 +6144,7 @@ comment at the start of cc-engine.el for more info."
(setq s (cons -1 (cdr s))))
((and (equal match ",")
(eq (car s) -1))) ; at "," in "class foo : bar, ..."
- ((member match '(";" "*" "," "("))
+ ((member match '(";" "*" "," ")"))
(when (and s (cdr s) (<= (car s) 0))
(setq s (cdr s))))
((c-keyword-member kwd-sym 'c-flat-decl-block-kwds)
@@ -6832,7 +6837,7 @@ comment at the start of cc-engine.el for more info."
(let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
(unless (gethash type c-found-types)
(puthash type t c-found-types)
- (when (and (not c-record-found-types) ; Only call `c-fontify-new-fount-type'
+ (when (and (not c-record-found-types) ; Only call `c-fontify-new-found-type'
; when we haven't "bound" c-found-types
; to itself in c-forward-<>-arglist.
(eq (string-match c-symbol-key type) 0)
@@ -6846,7 +6851,7 @@ comment at the start of cc-engine.el for more info."
;; checking `c-new-id-start' and `c-new-id-end'. That's done to avoid
;; adding all prefixes of a type as it's being entered and font locked.
;; This is a bit rough and ready, but now covers adding characters into the
- ;; middle of an identifer.
+ ;; middle of an identifier.
;;
;; This function might do hidden buffer changes.
(if (and c-new-id-start c-new-id-end
@@ -8284,9 +8289,10 @@ multi-line strings (but not C++, for example)."
(defun c-forward-noise-clause ()
;; Point is at a c-noise-macro-with-parens-names macro identifier. Go
;; forward over this name, any parenthesis expression which follows it, and
- ;; any syntactic WS, ending up at the next token. If there is an unbalanced
- ;; paren expression, leave point at it. Always Return t.
- (c-forward-token-2)
+ ;; any syntactic WS, ending up at the next token or EOB. If there is an
+ ;; unbalanced paren expression, leave point at it. Always Return t.
+ (or (zerop (c-forward-token-2))
+ (goto-char (point-max)))
(if (and (eq (char-after) ?\()
(c-go-list-forward))
(c-forward-syntactic-ws))
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 230d39efeeb..625010b04b2 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1820,7 +1820,7 @@ casts and declarations are fontified. Used on level 2 and higher."
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification".
- (let (mode capture-default id-start id-end declaration sub-begin sub-end)
+ (let (mode capture-default id-start id-end declaration sub-begin sub-end tem)
(while (and (< (point) limit)
(search-forward "[" limit t))
(when (progn (backward-char)
@@ -1832,15 +1832,18 @@ casts and declarations are fontified. Used on level 2 and higher."
(char-after)))
;; Is the first element of the list a bare "=" or "&"?
(when mode
- (forward-char)
- (c-forward-syntactic-ws)
- (if (memq (char-after) '(?, ?\]))
- (progn
- (setq capture-default mode)
- (when (eq (char-after) ?,)
- (forward-char)
- (c-forward-syntactic-ws)))
- (c-backward-token-2)))
+ (setq tem nil)
+ (save-excursion
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (if (memq (char-after) '(?, ?\]))
+ (progn
+ (setq capture-default mode)
+ (when (eq (char-after) ?,)
+ (forward-char)
+ (c-forward-syntactic-ws))
+ (setq tem (point)))))
+ (if tem (goto-char tem)))
;; Go round the following loop once per captured item. We use "\\s)"
;; rather than "\\]" here to avoid infinite looping in this situation:
@@ -2253,12 +2256,13 @@ higher."
;; redisplay.
(defvar c-re-redisplay-timer nil)
-(defun c-force-redisplay (start end)
+(defun c-force-redisplay (buffer start end)
;; Force redisplay immediately. This assumes `font-lock-support-mode' is
;; 'jit-lock-mode. Set the variable `c-re-redisplay-timer' to nil.
- (save-excursion (c-font-lock-fontify-region start end))
- (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
- (setq c-re-redisplay-timer nil))
+ (with-current-buffer buffer
+ (save-excursion (c-font-lock-fontify-region start end))
+ (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
+ (setq c-re-redisplay-timer nil)))
(defun c-fontify-new-found-type (type)
;; Cause the fontification of TYPE, a string, wherever it occurs in the
@@ -2288,6 +2292,7 @@ higher."
(not c-re-redisplay-timer))
(setq c-re-redisplay-timer
(run-with-timer 0 nil #'c-force-redisplay
+ (current-buffer)
(match-beginning 0) (match-end 0)))))))))))
diff --git a/lisp/progmodes/cc-guess.el b/lisp/progmodes/cc-guess.el
index ea5dd48986c..584db86539e 100644
--- a/lisp/progmodes/cc-guess.el
+++ b/lisp/progmodes/cc-guess.el
@@ -76,6 +76,8 @@
(cc-require 'cc-engine)
(cc-require 'cc-styles)
+(cc-bytecomp-defun c-restore-string-fences)
+(cc-bytecomp-defun c-clear-string-fences)
(defcustom c-guess-offset-threshold 10
@@ -225,11 +227,12 @@ guess is made from scratch.
Note that the larger the region to guess in, the slower the guessing.
So you can limit the region with `c-guess-region-max'."
(interactive "r\nP")
- (let ((accumulator (when accumulate c-guess-accumulator)))
- (setq c-guess-accumulator (c-guess-examine start end accumulator))
- (let ((pair (c-guess-guess c-guess-accumulator)))
- (setq c-guess-guessed-basic-offset (car pair)
- c-guess-guessed-offsets-alist (cdr pair)))))
+ (c-with-string-fences
+ (let ((accumulator (when accumulate c-guess-accumulator)))
+ (setq c-guess-accumulator (c-guess-examine start end accumulator))
+ (let ((pair (c-guess-guess c-guess-accumulator)))
+ (setq c-guess-guessed-basic-offset (car pair)
+ c-guess-guessed-offsets-alist (cdr pair))))))
(defun c-guess-examine (start end accumulator)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 68070cd0581..c5964165c8d 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -458,12 +458,14 @@ so that all identifiers are recognized as words.")
c-before-change-check-<>-operators
c-truncate-bs-cache
c-before-change-check-unbalanced-strings
- c-parse-quotes-before-change)
+ c-parse-quotes-before-change
+ c-before-change-fix-comment-escapes)
(c objc) '(c-extend-region-for-CPP
c-depropertize-CPP
c-truncate-bs-cache
c-before-change-check-unbalanced-strings
- c-parse-quotes-before-change)
+ c-parse-quotes-before-change
+ c-before-change-fix-comment-escapes)
java '(c-parse-quotes-before-change
c-before-change-check-unbalanced-strings
c-before-change-check-<>-operators)
@@ -500,6 +502,7 @@ parameters \(point-min) and \(point-max).")
c-after-change-mark-abnormal-strings
c-change-expand-fl-region)
(c objc) '(c-depropertize-new-text
+ c-after-change-fix-comment-escapes
c-after-change-escape-NL-in-string
c-parse-quotes-after-change
c-after-change-mark-abnormal-strings
@@ -507,6 +510,7 @@ parameters \(point-min) and \(point-max).")
c-neutralize-syntax-in-CPP
c-change-expand-fl-region)
c++ '(c-depropertize-new-text
+ c-after-change-fix-comment-escapes
c-after-change-escape-NL-in-string
c-after-change-unmark-ml-strings
c-parse-quotes-after-change
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 3a3413dc36a..70fc1cb73a9 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -798,43 +798,44 @@ MODE is the symbol for the mode to initialize, like `c-mode'. See
`c-basic-common-init' for details. It's only optional to be
compatible with old code; callers should always specify it."
- (unless mode
- ;; Called from an old third party package. The fallback is to
- ;; initialize for C.
- (c-init-language-vars-for 'c-mode))
-
- (c-basic-common-init mode c-default-style)
- (when mode
- ;; Only initialize font locking if we aren't called from an old package.
- (c-font-lock-init))
-
- ;; Starting a mode is a sort of "change". So call the change functions...
- (save-restriction
- (widen)
- (setq c-new-BEG (point-min))
- (setq c-new-END (point-max))
- (save-excursion
- (let (before-change-functions after-change-functions)
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)))
- c-get-state-before-change-functions)
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)
- (- (point-max) (point-min))))
- c-before-font-lock-functions))))
-
- (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
- (set (make-local-variable 'outline-level) 'c-outline-level)
- (set (make-local-variable 'add-log-current-defun-function)
- (lambda ()
- (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
- (let ((rfn (assq mode c-require-final-newline)))
- (when rfn
- (if (boundp 'mode-require-final-newline)
- (and (cdr rfn)
- (set (make-local-variable 'require-final-newline)
- mode-require-final-newline))
- (set (make-local-variable 'require-final-newline) (cdr rfn))))))
+ (let (case-fold-search)
+ (unless mode
+ ;; Called from an old third party package. The fallback is to
+ ;; initialize for C.
+ (c-init-language-vars-for 'c-mode))
+
+ (c-basic-common-init mode c-default-style)
+ (when mode
+ ;; Only initialize font locking if we aren't called from an old package.
+ (c-font-lock-init))
+
+ ;; Starting a mode is a sort of "change". So call the change functions...
+ (save-restriction
+ (widen)
+ (setq c-new-BEG (point-min))
+ (setq c-new-END (point-max))
+ (save-excursion
+ (let (before-change-functions after-change-functions)
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)))
+ c-get-state-before-change-functions)
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)
+ (- (point-max) (point-min))))
+ c-before-font-lock-functions))))
+
+ (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
+ (set (make-local-variable 'outline-level) 'c-outline-level)
+ (set (make-local-variable 'add-log-current-defun-function)
+ (lambda ()
+ (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
+ (let ((rfn (assq mode c-require-final-newline)))
+ (when rfn
+ (if (boundp 'mode-require-final-newline)
+ (and (cdr rfn)
+ (set (make-local-variable 'require-final-newline)
+ mode-require-final-newline))
+ (set (make-local-variable 'require-final-newline) (cdr rfn)))))))
(defun c-count-cfss (lv-alist)
;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many
@@ -996,7 +997,8 @@ Note that the style variables are always made local to the buffer."
;; `c-before/after-change', frame 3 is the primitive invoking the change
;; hook.
(memq (cadr (backtrace-frame 3))
- '(put-text-property remove-list-of-text-properties)))
+ '(put-text-property remove-text-properties
+ remove-list-of-text-properties)))
(defun c-depropertize-CPP (beg end)
;; Remove the punctuation syntax-table text property from the CPP parts of
@@ -1318,7 +1320,8 @@ Note that the style variables are always made local to the buffer."
;; balanced by another " is left with a '(1) syntax-table property.
(when
(and c-min-syn-tab-mkr c-max-syn-tab-mkr)
- (let (s pos)
+ (c-save-buffer-state (s pos) ; Prevent text property stuff causing change
+ ; function invocation.
(setq pos c-min-syn-tab-mkr)
(while
(and
@@ -1341,7 +1344,8 @@ Note that the style variables are always made local to the buffer."
(c-search-backward-char-property-with-value-on-char
'c-fl-syn-tab '(15) ?\"
(max (- (point) 500) (point-min))))
- (not (equal (c-get-char-property (point) 'syntax-table) '(1))))
+ (not (equal (c-get-char-property (point) 'syntax-table)
+ '(1))))
(setq pos (1+ pos))))
(while (< pos c-max-syn-tab-mkr)
(setq pos
@@ -1371,7 +1375,9 @@ Note that the style variables are always made local to the buffer."
;; Restore any syntax-table text properties which are "mirrored" by
;; c-fl-syn-tab text properties.
(when (and c-min-syn-tab-mkr c-max-syn-tab-mkr)
- (let ((pos c-min-syn-tab-mkr))
+ (c-save-buffer-state ; Prevent text property stuff causing change function
+ ; invocation.
+ ((pos c-min-syn-tab-mkr))
(while
(and
(< pos c-max-syn-tab-mkr)
@@ -1973,6 +1979,87 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(defvar c-new-id-is-type nil)
(make-variable-buffer-local 'c-new-id-is-type)
+(defun c-before-change-fix-comment-escapes (beg end)
+ "Remove punctuation syntax-table text properties from C/C++ comment markers.
+This is to handle the rare case of two or more backslashes at an
+end of line in a // comment or the equally rare case of a
+backslash preceding the terminator of a /* comment, as \\*/.
+
+This function is used solely as a member of
+`c-get-state-before-change-functions', where it should appear
+late in that variable, and it must be used only together with
+`c-after-change-fix-comment-escapes'.
+
+Note that the function currently only handles comments beginning
+with // and /*, not more generic line and block comments."
+ (c-save-buffer-state (end-state)
+ (setq end-state (c-full-pp-to-literal end))
+ (when (memq (cadr end-state) '(c c++))
+ (goto-char (max (- beg 2) (point-min)))
+ (if (eq (cadr end-state) 'c)
+ (when (search-forward "\\*/"
+ (or (cdr (caddr end-state)) (point-max)) t)
+ (c-clear-char-property (match-beginning 0) 'syntax-table)
+ (c-truncate-lit-pos-cache (match-beginning 0)))
+ (while (search-forward "\\\\\n"
+ (or (cdr (caddr end-state)) (point-max)) t)
+ (c-clear-char-property (match-beginning 0) 'syntax-table)
+ (c-truncate-lit-pos-cache (match-beginning 0)))))))
+
+(defun c-after-change-fix-comment-escapes (beg end _old-len)
+ "Apply punctuation syntax-table text properties to C/C++ comment markers.
+This is to handle the rare case of two or more backslashes at an
+end of line in a // comment or the equally rare case of a
+backslash preceding the terminator of a /* comment, as \\*/.
+
+This function is used solely as a member of
+`c-before-font-lock-functions', where it should appear early in
+that variable, and it must be used only together with
+`c-before-change-fix-comment-escapes'.
+
+Note that the function currently only handles comments beginning
+with // and /*, not more generic line and block comments."
+ (c-save-buffer-state (state)
+ ;; We cannot use `c-full-pp-to-literal' in this function, since the
+ ;; `syntax-table' text properties after point are not yet in a consistent
+ ;; state.
+ (setq state (c-semi-pp-to-literal beg))
+ (goto-char (if (memq (cadr state) '(c c++))
+ (caddr state)
+ (max (- beg 2) (point-min))))
+ (while
+ (re-search-forward "\\\\\\(\\(\\\\\n\\)\\|\\(\\*/\\)\\)"
+ (min (+ end 2) (point-max)) t)
+ (setq state (c-semi-pp-to-literal (match-beginning 0)))
+ (when (cond
+ ((eq (cadr state) 'c)
+ (match-beginning 3))
+ ((eq (cadr state) 'c++)
+ (match-beginning 2)))
+ (c-put-char-property (match-beginning 0) 'syntax-table '(1))
+ (c-truncate-lit-pos-cache (match-beginning 0))))
+
+ (goto-char end)
+ (setq state (c-semi-pp-to-literal (point)))
+ (cond
+ ((eq (cadr state) 'c)
+ (when (search-forward "*/" nil t)
+ (when (eq (char-before (match-beginning 0)) ?\\)
+ (c-put-char-property (1- (match-beginning 0)) 'syntax-table '(1))
+ (c-truncate-lit-pos-cache (1- (match-beginning 0))))))
+ ((eq (cadr state) 'c++)
+ (while
+ (progn
+ (end-of-line)
+ (and (eq (char-before) ?\\)
+ (progn
+ (when (eq (char-before (1- (point))) ?\\)
+ (c-put-char-property (- (point) 2) 'syntax-table '(1))
+ (c-truncate-lit-pos-cache (1- (point))))
+ t)
+ (not (eobp))))
+ (forward-char))))))
+
(defun c-update-new-id (end)
;; Note the bounds of any identifier that END is in or just after, in
;; `c-new-id-start' and `c-new-id-end'. Otherwise set these variables to
@@ -1984,7 +2071,6 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
c-new-id-end (and id-beg
(progn (c-end-of-current-token) (point)))))))
-
(defun c-post-command ()
;; If point was inside of a new identifier and no longer is, record that
;; fact.
@@ -2015,120 +2101,116 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; or a comment - "wrongly" removing a symbol from `c-found-types'
;; isn't critical.
(unless (c-called-from-text-property-change-p)
- (save-restriction
- (widen)
- ;; Clear the list of found types if we make a change at the start of the
- ;; buffer, to make it easier to get rid of misspelled types and
- ;; variables that have gotten recognized as types in malformed code.
- (when (eq beg (point-min))
- (c-clear-found-types))
- (if c-just-done-before-change
- ;; We have two consecutive calls to `before-change-functions'
- ;; without an intervening `after-change-functions'. An example of
- ;; this is bug #38691. To protect CC Mode, assume that the entire
- ;; buffer has changed.
- (setq beg (point-min)
- end (point-max)
- c-just-done-before-change 'whole-buffer)
- (setq c-just-done-before-change t))
- ;; (c-new-BEG c-new-END) will be the region to fontify.
- (setq c-new-BEG beg c-new-END end)
- (setq c-maybe-stale-found-type nil)
- ;; A workaround for syntax-ppss's failure to notice syntax-table text
- ;; property changes.
- (when (fboundp 'syntax-ppss)
- (setq c-syntax-table-hwm most-positive-fixnum))
- (save-match-data
- (widen)
- (unwind-protect
- (progn
- (c-restore-string-fences)
- (save-excursion
- ;; Are we inserting/deleting stuff in the middle of an
- ;; identifier?
- (c-unfind-enclosing-token beg)
- (c-unfind-enclosing-token end)
- ;; Are we coalescing two tokens together, e.g. "fo o"
- ;; -> "foo"?
- (when (< beg end)
- (c-unfind-coalesced-tokens beg end))
- (c-invalidate-sws-region-before beg end)
- ;; Are we (potentially) disrupting the syntactic
- ;; context which makes a type a type? E.g. by
- ;; inserting stuff after "foo" in "foo bar;", or
- ;; before "foo" in "typedef foo *bar;"?
- ;;
- ;; We search for appropriate c-type properties "near"
- ;; the change. First, find an appropriate boundary
- ;; for this property search.
- (let (lim lim-2
- type type-pos
- marked-id term-pos
- (end1
- (or (and (eq (get-text-property end 'face)
- 'font-lock-comment-face)
- (previous-single-property-change end 'face))
- end)))
- (when (>= end1 beg) ; Don't hassle about changes entirely in
+ (c-with-string-fences
+ (save-restriction
+ (widen)
+ ;; Clear the list of found types if we make a change at the start of the
+ ;; buffer, to make it easier to get rid of misspelled types and
+ ;; variables that have gotten recognized as types in malformed code.
+ (when (eq beg (point-min))
+ (c-clear-found-types))
+ (if c-just-done-before-change
+ ;; We have two consecutive calls to `before-change-functions'
+ ;; without an intervening `after-change-functions'. An example of
+ ;; this is bug #38691. To protect CC Mode, assume that the entire
+ ;; buffer has changed.
+ (setq beg (point-min)
+ end (point-max)
+ c-just-done-before-change 'whole-buffer)
+ (setq c-just-done-before-change t))
+ ;; (c-new-BEG c-new-END) will be the region to fontify.
+ (setq c-new-BEG beg c-new-END end)
+ (setq c-maybe-stale-found-type nil)
+ ;; A workaround for syntax-ppss's failure to notice syntax-table text
+ ;; property changes.
+ (when (fboundp 'syntax-ppss)
+ (setq c-syntax-table-hwm most-positive-fixnum))
+ (save-match-data
+ (save-excursion
+ ;; Are we inserting/deleting stuff in the middle of an
+ ;; identifier?
+ (c-unfind-enclosing-token beg)
+ (c-unfind-enclosing-token end)
+ ;; Are we coalescing two tokens together, e.g. "fo o"
+ ;; -> "foo"?
+ (when (< beg end)
+ (c-unfind-coalesced-tokens beg end))
+ (c-invalidate-sws-region-before beg end)
+ ;; Are we (potentially) disrupting the syntactic
+ ;; context which makes a type a type? E.g. by
+ ;; inserting stuff after "foo" in "foo bar;", or
+ ;; before "foo" in "typedef foo *bar;"?
+ ;;
+ ;; We search for appropriate c-type properties "near"
+ ;; the change. First, find an appropriate boundary
+ ;; for this property search.
+ (let (lim lim-2
+ type type-pos
+ marked-id term-pos
+ (end1
+ (or (and (eq (get-text-property end 'face)
+ 'font-lock-comment-face)
+ (previous-single-property-change end 'face))
+ end)))
+ (when (>= end1 beg) ; Don't hassle about changes entirely in
; comments.
- ;; Find a limit for the search for a `c-type' property
- ;; Point is currently undefined. A `goto-char' somewhere is needed. (2020-12-06).
- (setq lim-2 (c-determine-limit 1000 (point) ; that is wrong. FIXME!!! (2020-12-06)
- ))
- (while
- (and (/= (skip-chars-backward "^;{}" lim-2) 0)
- (> (point) (point-min))
- (memq (c-get-char-property (1- (point)) 'face)
- '(font-lock-comment-face font-lock-string-face))))
- (setq lim (max (point-min) (1- (point))))
-
- ;; Look for the latest `c-type' property before end1
- (when (and (> end1 (point-min))
- (setq type-pos
- (if (get-text-property (1- end1) 'c-type)
- end1
- (previous-single-property-change end1 'c-type
- nil lim))))
- (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
-
- (when (memq type '(c-decl-id-start c-decl-type-start))
- ;; Get the identifier, if any, that the property is on.
- (goto-char (1- type-pos))
- (setq marked-id
- (when (looking-at "\\(\\sw\\|\\s_\\)")
- (c-beginning-of-current-token)
- (buffer-substring-no-properties (point) type-pos)))
-
- (goto-char end1)
- (setq lim-2 (c-determine-+ve-limit 1000))
- (skip-chars-forward "^;{}" lim-2) ; FIXME!!! loop for
+ ;; Find a limit for the search for a `c-type' property
+ ;; Point is currently undefined. A `goto-char' somewhere is needed. (2020-12-06).
+ (setq lim-2 (c-determine-limit 1000 (point) ; that is wrong. FIXME!!! (2020-12-06)
+ ))
+ (while
+ (and (/= (skip-chars-backward "^;{}" lim-2) 0)
+ (> (point) (point-min))
+ (memq (c-get-char-property (1- (point)) 'face)
+ '(font-lock-comment-face font-lock-string-face))))
+ (setq lim (max (point-min) (1- (point))))
+
+ ;; Look for the latest `c-type' property before end1
+ (when (and (> end1 (point-min))
+ (setq type-pos
+ (if (get-text-property (1- end1) 'c-type)
+ end1
+ (previous-single-property-change end1 'c-type
+ nil lim))))
+ (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
+
+ (when (memq type '(c-decl-id-start c-decl-type-start))
+ ;; Get the identifier, if any, that the property is on.
+ (goto-char (1- type-pos))
+ (setq marked-id
+ (when (looking-at "\\(\\sw\\|\\s_\\)")
+ (c-beginning-of-current-token)
+ (buffer-substring-no-properties (point) type-pos)))
+
+ (goto-char end1)
+ (setq lim-2 (c-determine-+ve-limit 1000))
+ (skip-chars-forward "^;{}" lim-2) ; FIXME!!! loop for
; comment, maybe
- (setq lim (point))
- (setq term-pos
- (or (c-next-single-property-change end 'c-type nil lim) lim))
- (setq c-maybe-stale-found-type
- (list type marked-id
- type-pos term-pos
- (buffer-substring-no-properties type-pos
- term-pos)
- (buffer-substring-no-properties beg end)))))))
-
- (if c-get-state-before-change-functions
- (mapc (lambda (fn)
- (funcall fn beg end))
- c-get-state-before-change-functions))
-
- (c-laomib-invalidate-cache beg end)))
- (c-clear-string-fences))))
- (c-truncate-lit-pos-cache beg)
- ;; The following must be done here rather than in `c-after-change'
- ;; because newly inserted parens would foul up the invalidation
- ;; algorithm.
- (c-invalidate-state-cache beg)
- ;; The following must happen after the previous, which likely alters
- ;; the macro cache.
- (when c-opt-cpp-symbol
- (c-invalidate-macro-cache beg end))))
+ (setq lim (point))
+ (setq term-pos
+ (or (c-next-single-property-change end 'c-type nil lim) lim))
+ (setq c-maybe-stale-found-type
+ (list type marked-id
+ type-pos term-pos
+ (buffer-substring-no-properties type-pos
+ term-pos)
+ (buffer-substring-no-properties beg end)))))))
+
+ (if c-get-state-before-change-functions
+ (mapc (lambda (fn)
+ (funcall fn beg end))
+ c-get-state-before-change-functions))
+
+ (c-laomib-invalidate-cache beg end))))
+ (c-truncate-lit-pos-cache beg)
+ ;; The following must be done here rather than in `c-after-change'
+ ;; because newly inserted parens would foul up the invalidation
+ ;; algorithm.
+ (c-invalidate-state-cache beg)
+ ;; The following must happen after the previous, which likely alters
+ ;; the macro cache.
+ (when c-opt-cpp-symbol
+ (c-invalidate-macro-cache beg end)))))
(defvar c-in-after-change-fontification nil)
(make-variable-buffer-local 'c-in-after-change-fontification)
@@ -2180,51 +2262,48 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(save-restriction
(save-match-data ; c-recognize-<>-arglists changes match-data
(widen)
- (unwind-protect
- (progn
- (c-restore-string-fences)
- (when (> end (point-max))
- ;; Some emacsen might return positions past the end. This
- ;; has been observed in Emacs 20.7 when rereading a buffer
- ;; changed on disk (haven't been able to minimize it, but
- ;; Emacs 21.3 appears to work).
- (setq end (point-max))
- (when (> beg end)
- (setq beg end)))
-
- ;; C-y is capable of spuriously converting category
- ;; properties c-</>-as-paren-syntax and
- ;; c-cpp-delimiter into hard syntax-table properties.
- ;; Remove these when it happens.
- (when (eval-when-compile (memq 'category-properties c-emacs-features))
- (c-save-buffer-state ()
- (c-clear-char-property-with-value beg end 'syntax-table
- c-<-as-paren-syntax)
- (c-clear-char-property-with-value beg end 'syntax-table
- c->-as-paren-syntax)
- (c-clear-char-property-with-value beg end 'syntax-table nil)))
-
- (c-update-new-id end)
- (c-trim-found-types beg end old-len) ; maybe we don't
- ; need all of these.
- (c-invalidate-sws-region-after beg end old-len)
- ;; (c-invalidate-state-cache beg) ; moved to
- ;; `c-before-change'.
- (c-invalidate-find-decl-cache beg)
-
- (when c-recognize-<>-arglists
- (c-after-change-check-<>-operators beg end))
-
- (setq c-in-after-change-fontification t)
- (save-excursion
- (mapc (lambda (fn)
- (funcall fn beg end old-len))
- c-before-font-lock-functions)))
- (c-clear-string-fences))))))
+ (c-with-string-fences
+ (when (> end (point-max))
+ ;; Some emacsen might return positions past the end. This
+ ;; has been observed in Emacs 20.7 when rereading a buffer
+ ;; changed on disk (haven't been able to minimize it, but
+ ;; Emacs 21.3 appears to work).
+ (setq end (point-max))
+ (when (> beg end)
+ (setq beg end)))
+
+ ;; C-y is capable of spuriously converting category
+ ;; properties c-</>-as-paren-syntax and
+ ;; c-cpp-delimiter into hard syntax-table properties.
+ ;; Remove these when it happens.
+ (when (eval-when-compile (memq 'category-properties c-emacs-features))
+ (c-save-buffer-state ()
+ (c-clear-char-property-with-value beg end 'syntax-table
+ c-<-as-paren-syntax)
+ (c-clear-char-property-with-value beg end 'syntax-table
+ c->-as-paren-syntax)
+ (c-clear-char-property-with-value beg end 'syntax-table nil)))
+
+ (c-update-new-id end)
+ (c-trim-found-types beg end old-len) ; maybe we don't
+ ; need all of these.
+ (c-invalidate-sws-region-after beg end old-len)
+ ;; (c-invalidate-state-cache beg) ; moved to
+ ;; `c-before-change'.
+ (c-invalidate-find-decl-cache beg)
+
+ (when c-recognize-<>-arglists
+ (c-after-change-check-<>-operators beg end))
+
+ (setq c-in-after-change-fontification t)
+ (save-excursion
+ (mapc (lambda (fn)
+ (funcall fn beg end old-len))
+ c-before-font-lock-functions)))))
;; A workaround for syntax-ppss's failure to notice syntax-table text
;; property changes.
- (when (fboundp 'syntax-ppss)
- (syntax-ppss-flush-cache c-syntax-table-hwm)))
+ (when (fboundp 'syntax-ppss)
+ (syntax-ppss-flush-cache c-syntax-table-hwm)))))
(defun c-doc-fl-decl-start (pos)
;; If the line containing POS is in a doc comment continued line (as defined
@@ -2456,46 +2535,42 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(widen)
(let (new-beg new-end new-region case-fold-search)
(c-save-buffer-state nil
- ;; Temporarily reapply the string fence syntax-table properties.
- (unwind-protect
- (progn
- (c-restore-string-fences)
- (if (and c-in-after-change-fontification
- (< beg c-new-END) (> end c-new-BEG))
- ;; Region and the latest after-change fontification region overlap.
- ;; Determine the upper and lower bounds of our adjusted region
- ;; separately.
- (progn
- (if (<= beg c-new-BEG)
- (setq c-in-after-change-fontification nil))
- (setq new-beg
- (if (and (>= beg (c-point 'bol c-new-BEG))
- (<= beg c-new-BEG))
- ;; Either jit-lock has accepted `c-new-BEG', or has
- ;; (probably) extended the change region spuriously
- ;; to BOL, which position likely has a
- ;; syntactically different position. To ensure
- ;; correct fontification, we start at `c-new-BEG',
- ;; assuming any characters to the left of
- ;; `c-new-BEG' on the line do not require
- ;; fontification.
- c-new-BEG
- (setq new-region (c-before-context-fl-expand-region beg end)
- new-end (cdr new-region))
- (car new-region)))
- (setq new-end
- (if (and (>= end (c-point 'bol c-new-END))
- (<= end c-new-END))
- c-new-END
- (or new-end
- (cdr (c-before-context-fl-expand-region beg end))))))
- ;; Context (etc.) fontification.
- (setq new-region (c-before-context-fl-expand-region beg end)
- new-beg (car new-region) new-end (cdr new-region)))
- ;; Finally invoke font lock's functionality.
- (funcall (default-value 'font-lock-fontify-region-function)
- new-beg new-end verbose))
- (c-clear-string-fences))))))
+ (c-with-string-fences
+ (if (and c-in-after-change-fontification
+ (< beg c-new-END) (> end c-new-BEG))
+ ;; Region and the latest after-change fontification region overlap.
+ ;; Determine the upper and lower bounds of our adjusted region
+ ;; separately.
+ (progn
+ (if (<= beg c-new-BEG)
+ (setq c-in-after-change-fontification nil))
+ (setq new-beg
+ (if (and (>= beg (c-point 'bol c-new-BEG))
+ (<= beg c-new-BEG))
+ ;; Either jit-lock has accepted `c-new-BEG', or has
+ ;; (probably) extended the change region spuriously
+ ;; to BOL, which position likely has a
+ ;; syntactically different position. To ensure
+ ;; correct fontification, we start at `c-new-BEG',
+ ;; assuming any characters to the left of
+ ;; `c-new-BEG' on the line do not require
+ ;; fontification.
+ c-new-BEG
+ (setq new-region (c-before-context-fl-expand-region beg end)
+ new-end (cdr new-region))
+ (car new-region)))
+ (setq new-end
+ (if (and (>= end (c-point 'bol c-new-END))
+ (<= end c-new-END))
+ c-new-END
+ (or new-end
+ (cdr (c-before-context-fl-expand-region beg end))))))
+ ;; Context (etc.) fontification.
+ (setq new-region (c-before-context-fl-expand-region beg end)
+ new-beg (car new-region) new-end (cdr new-region)))
+ ;; Finally invoke font lock's functionality.
+ (funcall (default-value 'font-lock-fontify-region-function)
+ new-beg new-end verbose))))))
(defun c-after-font-lock-init ()
;; Put on `font-lock-mode-hook'. This function ensures our after-change
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index 8fe8402b1d8..1cf14d52d55 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -180,6 +180,7 @@
(inclass . +)
(inline-open . 0))))
("linux"
+ (indent-tabs-mode . t)
(c-basic-offset . 8)
(c-comment-only-line-offset . 0)
(c-hanging-braces-alist . ((brace-list-open)
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 6fc898d95be..32031d19462 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -793,14 +793,6 @@ bundle agent rcfiles
(cdr (assq 'functions cfengine3-fallback-syntax)))
'symbols))
-(defcustom cfengine-mode-abbrevs nil
- "Abbrevs for CFEngine2 mode."
- :type '(repeat (list (string :tag "Name")
- (string :tag "Expansion")
- (choice :tag "Hook" (const nil) function))))
-
-(make-obsolete-variable 'cfengine-mode-abbrevs 'edit-abbrevs "24.1")
-
;; Taken from the doc for pre-release 2.1.
(eval-and-compile
(defconst cfengine2-actions
@@ -989,13 +981,7 @@ Intended as the value of `indent-line-function'."
(defun cfengine-fill-paragraph (&optional justify)
"Fill `paragraphs' in Cfengine code."
(interactive "P")
- (or (if (fboundp 'fill-comment-paragraph)
- (fill-comment-paragraph justify)
- ;; else do nothing in a comment
- (nth 4 (parse-partial-sexp (save-excursion
- (beginning-of-defun)
- (point))
- (point))))
+ (or (fill-comment-paragraph justify)
(let ((paragraph-start
;; Include start of parenthesized block.
"\f\\|[ \t]*$\\|.*(")
@@ -1415,7 +1401,6 @@ to the action header."
(setq-local outline-regexp "[ \t]*\\(\\sw\\|\\s_\\)+:+")
(setq-local outline-level #'cfengine2-outline-level)
(setq-local fill-paragraph-function #'cfengine-fill-paragraph)
- (define-abbrev-table 'cfengine2-mode-abbrev-table cfengine-mode-abbrevs)
(setq font-lock-defaults
'(cfengine2-font-lock-keywords nil nil nil beginning-of-line))
;; Fixme: set the args of functions in evaluated classes to string
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index e75a44b6537..9f33186d8b1 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -82,6 +82,25 @@ after `call-process' inserts the grep output into the buffer.")
"Position of the start of the text inserted by `compilation-filter'.
This is bound before running `compilation-filter-hook'.")
+(defcustom compilation-hidden-output nil
+ "Regexp to match output from the compilation that should be hidden.
+This can also be a list of regexps.
+
+The text matched by this variable will be made invisible, which
+means that it'll still be present in the buffer, so that
+navigation commands (for instance, `next-error') can still make
+use of the hidden text to determine the current directory and the
+like.
+
+For instance, to hide the verbose output from recursive
+makefiles, you can say something like:
+
+ (setq compilation-hidden-output
+ \\='(\"^make[^\n]+\n\"))"
+ :type '(choice regexp
+ (repeat regexp))
+ :version "29.1")
+
(defvar compilation-first-column 1
"This is how compilers number the first column, usually 1 or 0.
If this is buffer-local in the destination buffer, Emacs obeys
@@ -257,7 +276,16 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
"): ")
3 4 5 (1 . 2))
- (iar
+ (gradle-android
+ ,(rx bol (* " ") "ERROR:"
+ (group-n 1 ; file
+ (+ (not (in ":\n"))))
+ ":"
+ (group-n 2 (+ digit)) ; line
+ ": ")
+ 1 2)
+
+ (iar
"^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
1 2 nil (3))
@@ -340,66 +368,73 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
": \\*\\*\\* \\[\\(\\(.+?\\):\\([0-9]+\\): .+\\)\\]" 2 3 nil 0 1)
(gnu
+ ;; The `gnu' message syntax is
+ ;; [PROGRAM:]FILE:LINE[-ENDLINE]:[COL[-ENDCOL]:] MESSAGE
+ ;; or
+ ;; [PROGRAM:]FILE:LINE[.COL][-ENDLINE[.ENDCOL]]: MESSAGE
,(rx
bol
- ;; Match an optional program name in the format
- ;; PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE
- ;; which is used for non-interactive programs other than
- ;; compilers (e.g. the "jade:" entry in compilation.txt).
+ ;; Match an optional program name which is used for
+ ;; non-interactive programs other than compilers (e.g. the
+ ;; "jade:" entry in compilation.txt).
(? (| (: alpha (+ (in ?. ?- alnum)) ":" (? " "))
;; Skip indentation generated by GCC's -fanalyzer.
(: (+ " ") "|")))
;; File name group.
(group-n 1
- ;; Avoid matching the file name as a program in the pattern
- ;; above by disallow file names entirely composed of digits.
- (: (regexp "[0-9]*[^0-9\n]")
- ;; This rule says that a file name can be composed
- ;; of any non-newline char, but it also rules out
- ;; some valid but unlikely cases, such as a
- ;; trailing space or a space followed by a -, or a
- ;; colon followed by a space.
- (*? (| (regexp "[^\n :]")
- (regexp " [^-/\n]")
- (regexp ":[^ \n]")))))
- (regexp ": ?")
+ ;; Avoid matching the file name as a program in the pattern
+ ;; above by disallowing file names entirely composed of digits.
+ ;; Do not allow file names beginning with a space.
+ (| (not (in "0-9" "\n\t "))
+ (: (+ (in "0-9"))
+ (not (in "0-9" "\n"))))
+ ;; A file name can be composed of any non-newline char, but
+ ;; rule out some valid but unlikely cases, such as a trailing
+ ;; space or a space followed by a -, or a colon followed by a
+ ;; space.
+ (*? (| (not (in "\n :"))
+ (: " " (not (in ?- "/\n")))
+ (: ":" (not (in " \n"))))))
+ ":" (? " ")
;; Line number group.
- (group-n 2 (regexp "[0-9]+"))
+ (group-n 2 (+ (in "0-9")))
(? (| (: "-"
- (group-n 4 (regexp "[0-9]+")) ; ending line
- (? "." (group-n 5 (regexp "[0-9]+")))) ; ending column
+ (group-n 4 (+ (in "0-9"))) ; ending line
+ (? "." (group-n 5 (+ (in "0-9"))))) ; ending column
(: (in ".:")
- (group-n 3 (regexp "[0-9]+")) ; starting column
+ (group-n 3 (+ (in "0-9"))) ; starting column
(? "-"
- (? (group-n 4 (regexp "[0-9]+")) ".") ; ending line
- (group-n 5 (regexp "[0-9]+")))))) ; ending column
+ (? (group-n 4 (+ (in "0-9"))) ".") ; ending line
+ (group-n 5 (+ (in "0-9"))))))) ; ending column
":"
(| (: (* " ")
(group-n 6 (| "FutureWarning"
"RuntimeWarning"
- "Warning"
- "warning"
+ "Warning" "warning"
"W:")))
(: (* " ")
- (group-n 7 (| (regexp "[Ii]nfo\\(?:\\>\\|rmationa?l?\\)")
- "I:"
- (: "[ skipping " (+ nonl) " ]")
- "instantiated from"
- "required from"
- (regexp "[Nn]ote"))))
+ (group-n 7
+ (| (| "Info" "info"
+ "Information" "information"
+ "Informational" "informational"
+ "I:"
+ "instantiated from"
+ "required from"
+ "Note" "note")
+ (: "[ skipping " (+ nonl) " ]"))))
(: (* " ")
- (regexp "[Ee]rror"))
+ (| "Error" "error"))
;; Avoid matching time stamps on the form "HH:MM:SS" where
;; MM is interpreted as a line number by trying to rule out
;; messages where the text after the line number starts with
;; a 2-digit number.
- (: (regexp "[0-9]?")
- (| (regexp "[^0-9\n]")
+ (: (? (in "0-9"))
+ (| (not (in "0-9\n"))
eol))
- (regexp "[0-9][0-9][0-9]")))
+ (: (in "0-9") (in "0-9") (in "0-9"))))
1 (2 . 4) (3 . 5) (6 . 7))
(cucumber
@@ -951,7 +986,10 @@ Faces `compilation-error-face', `compilation-warning-face',
(defcustom compilation-auto-jump-to-first-error nil
"If non-nil, automatically jump to the first error during compilation."
- :type 'boolean
+ :type '(choice (const :tag "Never" nil)
+ (const :tag "Always" t)
+ (const :tag "If location known" if-location-known)
+ (const :tag "First known location" first-known))
:version "23.1")
(defvar-local compilation-auto-jump-to-next nil
@@ -1182,21 +1220,46 @@ POS and RES.")
l2
(setcdr l1 (cons (list ,key) l2)))))))
+(defun compilation--file-known-p ()
+ "Say whether the file under point can be found."
+ (when-let* ((msg (get-text-property (point) 'compilation-message))
+ (loc (compilation--message->loc msg))
+ (elem (compilation-find-file-1
+ (point-marker)
+ (caar (compilation--loc->file-struct loc))
+ (cadr (car (compilation--loc->file-struct loc)))
+ (compilation--file-struct->formats
+ (compilation--loc->file-struct loc)))))
+ (car elem)))
+
(defun compilation-auto-jump (buffer pos)
(when (buffer-live-p buffer)
(with-current-buffer buffer
(goto-char pos)
(let ((win (get-buffer-window buffer 0)))
(if win (set-window-point win pos)))
- (if compilation-auto-jump-to-first-error
- (compile-goto-error)))))
+ (when compilation-auto-jump-to-first-error
+ (cl-case compilation-auto-jump-to-first-error
+ ('if-location-known
+ (when (compilation--file-known-p)
+ (compile-goto-error)))
+ ('first-known
+ (let (match)
+ (while (and (not (compilation--file-known-p))
+ (setq match (text-property-search-forward
+ 'compilation-message nil nil t)))
+ (goto-char (prop-match-beginning match))))
+ (when (compilation--file-known-p)
+ (compile-goto-error)))
+ (otherwise
+ (compile-goto-error)))))))
;; This function is the central driver, called when font-locking to gather
;; all information needed to later jump to corresponding source code.
;; Return a property list with all meta information on this error location.
(defun compilation-error-properties (file line end-line col end-col type fmt
- rule)
+ rule)
(unless (text-property-not-all (match-beginning 0) (point)
'compilation-message nil)
(if file
@@ -1520,7 +1583,8 @@ to `compilation-error-regexp-alist' if RULES is nil."
;; FIXME-omake: Doing it here seems wrong, at least it should depend on
;; whether or not omake's own error messages are recognized.
(cond
- ((not omake-included) nil)
+ ((or (not omake-included) (not pat))
+ nil)
((string-match "\\`\\([^^]\\|\\^\\( \\*\\|\\[\\)\\)" pat)
nil) ;; Not anchored or anchored but already allows empty spaces.
(t (setq pat (concat "^\\(?: \\)?" (substring pat 1)))))
@@ -1539,7 +1603,7 @@ to `compilation-error-regexp-alist' if RULES is nil."
(error "HYPERLINK should be an integer: %s" (nth 5 item)))
(goto-char start)
- (while (re-search-forward pat end t)
+ (while (and pat (re-search-forward pat end t))
(when (setq props (compilation-error-properties
file line end-line col end-col
(or type 2) fmt rule))
@@ -1752,13 +1816,21 @@ If nil, ask to kill it."
:type 'boolean
:version "24.3")
+(defcustom compilation-max-output-line-length 400
+ "Output lines that are longer than this value will be hidden.
+If nil, don't hide anything."
+ :type '(choice (const :tag "Hide nothing" nil)
+ integer)
+ :version "29.1")
+
(defun compilation--update-in-progress-mode-line ()
;; `compilation-in-progress' affects the mode-line of all
;; buffers when it changes from nil to non-nil or vice-versa.
(unless compilation-in-progress (force-mode-line-update t)))
;;;###autoload
-(defun compilation-start (command &optional mode name-function highlight-regexp)
+(defun compilation-start (command &optional mode name-function highlight-regexp
+ continue)
"Run compilation command COMMAND (low level interface).
If COMMAND starts with a cd command, that becomes the `default-directory'.
The rest of the arguments are optional; for them, nil means use the default.
@@ -1775,6 +1847,12 @@ If HIGHLIGHT-REGEXP is non-nil, `next-error' will temporarily highlight
the matching section of the visited source line; the default is to use the
global value of `compilation-highlight-regexp'.
+If CONTINUE is non-nil, the buffer won't be emptied before
+compilation is started. This can be useful if you wish to
+combine the output from several compilation commands in the same
+buffer. The new output will be at the end of the buffer, and
+point is not changed.
+
Returns the compilation buffer created."
(or mode (setq mode 'compilation-mode))
(let* ((name-of-mode
@@ -1838,7 +1916,12 @@ Returns the compilation buffer created."
(if (= (length expanded-dir) 1)
(car expanded-dir)
substituted-dir)))))
- (erase-buffer)
+ (if continue
+ (progn
+ ;; Save the point so we can restore it.
+ (setq continue (point))
+ (goto-char (point-max)))
+ (erase-buffer))
;; Select the desired mode.
(if (not (eq mode t))
(progn
@@ -1864,12 +1947,13 @@ Returns the compilation buffer created."
(if (or compilation-auto-jump-to-first-error
(eq compilation-scroll-output 'first-error))
(setq-local compilation-auto-jump-to-next t))
- ;; Output a mode setter, for saving and later reloading this buffer.
- (insert "-*- mode: " name-of-mode
- "; default-directory: "
- (prin1-to-string (abbreviate-file-name default-directory))
- " -*-\n"
- (format "%s started at %s\n\n"
+ (when (zerop (buffer-size))
+ ;; Output a mode setter, for saving and later reloading this buffer.
+ (insert "-*- mode: " name-of-mode
+ "; default-directory: "
+ (prin1-to-string (abbreviate-file-name default-directory))
+ " -*-\n"))
+ (insert (format "%s started at %s\n\n"
mode-name
(substring (current-time-string) 0 19))
command "\n")
@@ -1888,28 +1972,33 @@ Returns the compilation buffer created."
(and (derived-mode-p 'comint-mode)
(comint-term-environment))
(list (format "INSIDE_EMACS=%s,compile" emacs-version))
+ ;; Some external programs (like "git grep") use a pager;
+ ;; defeat that.
+ (list "PAGER=")
(copy-sequence process-environment))))
(setq-local compilation-arguments
(list command mode name-function highlight-regexp))
(setq-local revert-buffer-function 'compilation-revert-buffer)
- (and outwin
- ;; Forcing the window-start overrides the usual redisplay
- ;; feature of bringing point into view, so setting the
- ;; window-start to top of the buffer risks losing the
- ;; effect of moving point to EOB below, per
- ;; compilation-scroll-output, if the command is long
- ;; enough to push point outside of the window. This
- ;; could happen, e.g., in `rgrep'.
- (not compilation-scroll-output)
- (set-window-start outwin (point-min)))
+ (when (and outwin
+ (not continue)
+ ;; Forcing the window-start overrides the usual redisplay
+ ;; feature of bringing point into view, so setting the
+ ;; window-start to top of the buffer risks losing the
+ ;; effect of moving point to EOB below, per
+ ;; compilation-scroll-output, if the command is long
+ ;; enough to push point outside of the window. This
+ ;; could happen, e.g., in `rgrep'.
+ (not compilation-scroll-output))
+ (set-window-start outwin (point-min)))
;; Position point as the user will see it.
(let ((desired-visible-point
- ;; Put it at the end if `compilation-scroll-output' is set.
- (if compilation-scroll-output
- (point-max)
- ;; Normally put it at the top.
- (point-min))))
+ (cond
+ (continue continue)
+ ;; Put it at the end if `compilation-scroll-output' is set.
+ (compilation-scroll-output (point-max))
+ ;; Normally put it at the top.
+ (t (point-min)))))
(goto-char desired-visible-point)
(when (and outwin (not (eq outwin (selected-window))))
(set-window-point outwin desired-visible-point)))
@@ -2405,8 +2494,8 @@ commands of Compilation major mode are available. See
(defun compilation-filter (proc string)
"Process filter for compilation buffers.
-Just inserts the text,
-handles carriage motion (see `comint-inhibit-carriage-motion'),
+Just inserts the text, handles carriage motion (see
+`comint-inhibit-carriage-motion'), `compilation-hidden-output',
and runs `compilation-filter-hook'."
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
@@ -2426,13 +2515,18 @@ and runs `compilation-filter-hook'."
;; We used to use `insert-before-markers', so that windows with
;; point at `process-mark' scroll along with the output, but we
;; now use window-point-insertion-type instead.
- (insert string)
+ (if (not compilation-max-output-line-length)
+ (insert string)
+ (dolist (line (string-lines string nil t))
+ (compilation--insert-abbreviated-line
+ line compilation-max-output-line-length)))
+ (when compilation-hidden-output
+ (compilation--hide-output compilation-filter-start))
(unless comint-inhibit-carriage-motion
(comint-carriage-motion (process-mark proc) (point)))
(set-marker (process-mark proc) (point))
;; Update the number of errors in compilation-mode-line-errors
(compilation--ensure-parse (point))
- ;; (setq-local compilation-buffer-modtime (current-time))
(run-hooks 'compilation-filter-hook))
(goto-char pos)
(narrow-to-region min max)
@@ -2440,6 +2534,58 @@ and runs `compilation-filter-hook'."
(set-marker min nil)
(set-marker max nil))))))
+(defun compilation--hide-output (start)
+ (save-excursion
+ (goto-char start)
+ (beginning-of-line)
+ ;; Apply the match to each line, but wait until we have a complete
+ ;; line.
+ (let ((start (point)))
+ (while (search-forward "\n" nil t)
+ (save-restriction
+ (narrow-to-region start (point))
+ (dolist (regexp (ensure-list compilation-hidden-output))
+ (goto-char start)
+ (while (re-search-forward regexp nil t)
+ (add-text-properties (match-beginning 0) (match-end 0)
+ '( invisible t
+ rear-nonsticky t))))
+ (goto-char (point-max)))))))
+
+(defun compilation--insert-abbreviated-line (string width)
+ (if (and (> (current-column) 0)
+ (get-text-property (1- (point)) 'button))
+ ;; We already have an abbreviation; just add the string to it.
+ (let ((beg (point)))
+ (insert string)
+ (add-text-properties
+ beg
+ ;; Don't make the final newline invisible.
+ (if (= (aref string (1- (length string))) ?\n)
+ (1- (point))
+ (point))
+ (text-properties-at (1- beg))))
+ (insert string)
+ ;; If we exceeded the limit, hide the last portion of the line.
+ (when (> (current-column) width)
+ (let ((start (save-excursion
+ (move-to-column width)
+ (point))))
+ (buttonize-region
+ start (point)
+ (lambda (start)
+ (let ((inhibit-read-only t))
+ (remove-text-properties start (save-excursion
+ (goto-char start)
+ (line-end-position))
+ (text-properties-at start)))))
+ (put-text-property
+ start (if (= (aref string (1- (length string))) ?\n)
+ ;; Don't hide the final newline.
+ (1- (point))
+ (point))
+ 'display (if (char-displayable-p ?…) "[…]" "[...]"))))))
+
(defsubst compilation-buffer-internal-p ()
"Test if inside a compilation buffer."
(local-variable-p 'compilation-locs))
@@ -2929,19 +3075,7 @@ and overlay is highlighted between MK and END-MK."
(remove-hook 'pre-command-hook
#'compilation-goto-locus-delete-o))
-(defun compilation-find-file (marker filename directory &rest formats)
- "Find a buffer for file FILENAME.
-If FILENAME is not found at all, ask the user where to find it.
-Pop up the buffer containing MARKER and scroll to MARKER if we ask
-the user where to find the file.
-Search the directories in `compilation-search-path'.
-A nil in `compilation-search-path' means to try the
-\"current\" directory, which is passed in DIRECTORY.
-If DIRECTORY is relative, it is combined with `default-directory'.
-If DIRECTORY is nil, that means use `default-directory'.
-FORMATS, if given, is a list of formats to reformat FILENAME when
-looking for it: for each element FMT in FORMATS, this function
-attempts to find a file whose name is produced by (format FMT FILENAME)."
+(defun compilation-find-file-1 (marker filename directory &optional formats)
(or formats (setq formats '("%s")))
(let ((dirs compilation-search-path)
(spec-dir (if directory
@@ -2990,6 +3124,23 @@ attempts to find a file whose name is produced by (format FMT FILENAME)."
(find-file-noselect name))
fmts (cdr fmts)))
(setq dirs (cdr dirs))))
+ (list buffer spec-dir)))
+
+(defun compilation-find-file (marker filename directory &rest formats)
+ "Find a buffer for file FILENAME.
+If FILENAME is not found at all, ask the user where to find it.
+Pop up the buffer containing MARKER and scroll to MARKER if we ask
+the user where to find the file.
+Search the directories in `compilation-search-path'.
+A nil in `compilation-search-path' means to try the
+\"current\" directory, which is passed in DIRECTORY.
+If DIRECTORY is relative, it is combined with `default-directory'.
+If DIRECTORY is nil, that means use `default-directory'.
+FORMATS, if given, is a list of formats to reformat FILENAME when
+looking for it: for each element FMT in FORMATS, this function
+attempts to find a file whose name is produced by (format FMT FILENAME)."
+ (pcase-let ((`(,buffer ,spec-dir)
+ (compilation-find-file-1 marker filename directory formats)))
(while (null buffer) ;Repeat until the user selects an existing file.
;; The file doesn't exist. Ask the user where to find it.
(save-excursion ;This save-excursion is probably not right.
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 8f33b3e3b73..f51d2fcb115 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -64,7 +64,7 @@
;; This mode supports font-lock, imenu and mode-compile. In the
;; hairy version font-lock is on, but you should activate imenu
;; yourself (note that mode-compile is not standard yet). Well, you
-;; can use imenu from keyboard anyway (M-x imenu), but it is better
+;; can use imenu from keyboard anyway (M-g i), but it is better
;; to bind it like that:
;; (define-key global-map [M-S-down-mouse-3] 'imenu)
@@ -558,6 +558,20 @@ This way enabling/disabling of menu items is more correct."
:type 'boolean
:group 'cperl-speed)
+(defcustom cperl-file-style nil
+ "Indentation style to use in cperl-mode."
+ :type '(choice (const "CPerl")
+ (const "PBP")
+ (const "PerlStyle")
+ (const "GNU")
+ (const "C++")
+ (const "K&R")
+ (const "BSD")
+ (const "Whitesmith")
+ (const :tag "Default" nil))
+ :version "29.1")
+;;;###autoload(put 'cperl-file-style 'safe-local-variable 'stringp)
+
(defcustom cperl-ps-print-face-properties
'((font-lock-keyword-face nil nil bold shadow)
(font-lock-variable-name-face nil nil bold)
@@ -1077,7 +1091,7 @@ Unless KEEP, removes the old indentation."
["Debugger" cperl-db t]
"----"
("Tools"
- ["Imenu" imenu (fboundp 'imenu)]
+ ["Imenu" imenu]
["Imenu on Perl Info" cperl-imenu-on-info (featurep 'imenu)]
"----"
["Ispell PODs" cperl-pod-spell
@@ -1308,7 +1322,7 @@ name, and one for the discovery of a following BLOCK.")
,cperl--ws+-rx
(group-n 2 ,cperl--normal-identifier-rx))
"A regular expression to detect a subroutine start.
-Contains three groups: One one to distinguish lexical from
+Contains three groups: One to distinguish lexical from
\"normal\" subroutines, for the keyword \"sub\", and one for the
subroutine name.")
@@ -1660,9 +1674,11 @@ Settings for classic indent-styles: K&R BSD=C++ GNU PBP PerlStyle=Whitesmith
`cperl-continued-statement-offset' 5 4 2 4 4
CPerl knows several indentation styles, and may bulk set the
-corresponding variables. Use \\[cperl-set-style] to do this. Use
-\\[cperl-set-style-back] to restore the memorized preexisting values
-\(both available from menu). See examples in `cperl-style-examples'.
+corresponding variables. Use \\[cperl-set-style] to do this or
+set the `cperl-file-style' user option. Use
+\\[cperl-set-style-back] to restore the memorized preexisting
+values \(both available from menu). See examples in
+`cperl-style-examples'.
Part of the indentation style is how different parts of if/elsif/else
statements are broken into lines; in CPerl, this is reflected on how
@@ -1795,8 +1811,15 @@ or as help on variables `cperl-tips', `cperl-problems',
(when (and cperl-pod-here-scan
(not cperl-syntaxify-by-font-lock))
(cperl-find-pods-heres))
+ (when cperl-file-style
+ (cperl-set-style cperl-file-style))
+ (add-hook 'hack-local-variables-hook #'cperl--set-file-style nil t)
;; Setup Flymake
(add-hook 'flymake-diagnostic-functions #'perl-flymake nil t))
+
+(defun cperl--set-file-style ()
+ (when cperl-file-style
+ (cperl-set-style cperl-file-style)))
;; Fix for perldb - make default reasonable
(defun cperl-db ()
@@ -3834,7 +3857,7 @@ recursive calls in starting lines of here-documents."
"\\<" cperl-sub-regexp "\\>" ; sub with proto/attr
"\\("
cperl-white-and-comment-rex
- (rx (group (eval cperl--normal-identifier-rx)))
+ (rx (opt (group (eval cperl--normal-identifier-rx))))
"\\)"
"\\("
cperl-maybe-white-and-comment-rex
@@ -6313,7 +6336,7 @@ else
)
("Current"))
"List of variables to set to get a particular indentation style.
-Should be used via `cperl-set-style' or via Perl menu.
+Should be used via `cperl-set-style', `cperl-file-style' or via Perl menu.
See examples in `cperl-style-examples'.")
@@ -6359,7 +6382,8 @@ side-effect of memorizing only. Examples in `cperl-style-examples'."
(eval '(mode-compile)))) ; Avoid a warning
(declare-function Info-find-node "info"
- (filename nodename &optional no-going-back strict-case))
+ (filename nodename &optional no-going-back strict-case
+ noerror))
(defun cperl-info-buffer (type)
;; Return buffer with documentation. Creates if missing.
@@ -7056,9 +7080,7 @@ One may build such TAGS files from CPerl mode menu."
(error "No items found"))
(setq update
;; (imenu-choose-buffer-index "Packages: " (nth 2 cperl-hierarchy))
- (if (if (fboundp 'display-popup-menus-p)
- (display-popup-menus-p)
- window-system)
+ (if (display-popup-menus-p)
(x-popup-menu t (nth 2 cperl-hierarchy))
(require 'tmm)
(tmm-prompt (nth 2 cperl-hierarchy))))
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index 971e3f6174d..03469b9f55b 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -180,9 +180,6 @@ C++ modes are included."
(cwarn-font-lock-keywords cwarn-mode)
(font-lock-flush))
-;;;###autoload
-(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1")
-
;;}}}
;;{{{ Help functions
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index 17cc537e38e..16b2f3ff503 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -996,7 +996,7 @@ if for some reason a circle is in the inheritance graph."
Each line corresponds to a class in a class tree.
Letters do not insert themselves, they are commands.
File operations in the tree buffer work on class tree data structures.
-E.g.\\[save-buffer] writes the tree to the file it was loaded from.
+E.g. \\[save-buffer] writes the tree to the file it was loaded from.
Tree mode key bindings:
\\{ebrowse-tree-mode-map}"
@@ -3633,7 +3633,12 @@ If regular expression is nil, repeat last search."
;;;###autoload
(defun ebrowse-tags-query-replace (from to)
"Query replace FROM with TO in all files of a class tree.
-With prefix arg, process files of marked classes only."
+With prefix arg, process files of marked classes only.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time."
(interactive
"sTree query replace (regexp): \nsTree query replace %s by: ")
(setq ebrowse-tags-loop-call
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 0dfff32f20d..0c4a9bfdbea 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -31,6 +31,7 @@
(require 'cl-generic)
(require 'lisp-mode)
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
(define-abbrev-table 'emacs-lisp-mode-abbrev-table ()
"Abbrev table for Emacs Lisp mode.
@@ -51,6 +52,9 @@ All commands in `lisp-mode-shared-map' are inherited by this map."
:parent lisp-mode-shared-map
"M-TAB" #'completion-at-point
"C-M-x" #'eval-defun
+ "C-c C-e" #'elisp-eval-buffer
+ "C-c C-f" #'elisp-byte-compile-file
+ "C-c C-b" #'elisp-byte-compile-buffer
"C-M-q" #'indent-pp-sexp)
(easy-menu-define emacs-lisp-mode-menu emacs-lisp-mode-map
@@ -237,6 +241,26 @@ Comments in the form will be lost."
(if (bolp) (delete-char -1))
(indent-region start (point)))))
+(defun elisp-mode-syntax-propertize (start end)
+ (goto-char start)
+ (let ((case-fold-search nil))
+ (funcall
+ (syntax-propertize-rules
+ ;; Empty symbol.
+ ("##" (0 (unless (nth 8 (syntax-ppss))
+ (string-to-syntax "_"))))
+ ;; Unicode character names. (The longest name is 88 characters
+ ;; long.)
+ ("\\?\\\\N{[-A-Za-z0-9 ]\\{,100\\}}"
+ (0 (unless (nth 8 (syntax-ppss))
+ (string-to-syntax "_"))))
+ ((rx "#" (or (seq (group-n 1 "&" (+ digit)) ?\") ; Bool-vector.
+ (seq (group-n 1 "s") "(") ; Record.
+ (seq (group-n 1 (+ "^")) "["))) ; Char-table.
+ (1 (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
+ (string-to-syntax "'")))))
+ start end)))
+
(defcustom emacs-lisp-mode-hook nil
"Hook run when entering Emacs Lisp mode."
:options '(eldoc-mode imenu-add-menubar-index checkdoc-minor-mode)
@@ -310,6 +334,7 @@ be used instead.
#'elisp-eldoc-var-docstring nil t)
(add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
(setq-local project-vc-external-roots-function #'elisp-load-path-roots)
+ (setq-local syntax-propertize-function #'elisp-mode-syntax-propertize)
(add-hook 'completion-at-point-functions
#'elisp-completion-at-point nil 'local)
(add-hook 'flymake-diagnostic-functions #'elisp-flymake-checkdoc nil t)
@@ -606,13 +631,13 @@ functions are annotated with \"<f>\" via the
;; t if in function position.
(funpos (eq (char-before beg) ?\())
(quoted (elisp--form-quoted-p beg))
- (fun-sym (condition-case nil
- (save-excursion
- (up-list -1)
- (forward-char 1)
- (and (memq (char-syntax (char-after)) '(?w ?_))
- (read (current-buffer))))
- (error nil))))
+ (is-ignore-error
+ (condition-case nil
+ (save-excursion
+ (up-list -1)
+ (forward-char 1)
+ (looking-at-p "ignore-error\\>"))
+ (error nil))))
(when (and end (or (not (nth 8 (syntax-ppss)))
(memq (char-before beg) '(?` ?‘))))
(let ((table-etc
@@ -621,7 +646,7 @@ functions are annotated with \"<f>\" via the
;; FIXME: We could look at the first element of
;; the current form and use it to provide a more
;; specific completion table in more cases.
- ((eq fun-sym 'ignore-error)
+ (is-ignore-error
(list t (elisp--completion-local-symbols)
:predicate (lambda (sym)
(get sym 'error-conditions))))
@@ -676,7 +701,10 @@ functions are annotated with \"<f>\" via the
(let ((c (char-after)))
(if (eq c ?\() ?\(
(if (memq (char-syntax c) '(?w ?_))
- (read (current-buffer))))))
+ (let ((pt (point)))
+ (forward-sexp)
+ (intern-soft
+ (buffer-substring pt (point))))))))
(error nil))))
(pcase parent
;; FIXME: Rather than hardcode special cases here,
@@ -755,8 +783,8 @@ functions are annotated with \"<f>\" via the
;;; Xref backend
-(declare-function xref-make "xref" (summary location))
-(declare-function xref-item-location "xref" (this))
+(declare-function xref-make "progmodes/xref" (summary location))
+(declare-function xref-item-location "progmodes/xref" (this))
(defun elisp--xref-backend () 'elisp)
@@ -779,7 +807,7 @@ functions are annotated with \"<f>\" via the
(defun elisp--xref-make-xref (type symbol file &optional summary)
"Return an xref for TYPE SYMBOL in FILE.
TYPE must be a type in `find-function-regexp-alist' (use nil for
-'defun). If SUMMARY is non-nil, use it for the summary;
+`defun'). If SUMMARY is non-nil, use it for the summary;
otherwise build the summary from TYPE and SYMBOL."
(xref-make (or summary
(format elisp--xref-format (or type 'defun) symbol))
@@ -1202,6 +1230,8 @@ All commands in `lisp-mode-shared-map' are inherited by this map."
:parent lisp-mode-shared-map
"C-M-x" #'eval-defun
"C-M-q" #'indent-pp-sexp
+ "C-c C-e" #'elisp-eval-buffer
+ "C-c C-b" #'elisp-byte-compile-buffer
"M-TAB" #'completion-at-point
"C-j" #'eval-print-last-sexp)
@@ -1614,8 +1644,6 @@ Return the result of evaluation."
;; printing, not while evaluating.
(defvar elisp--eval-defun-result)
(let ((debug-on-error eval-expression-debug-on-error)
- (print-length eval-expression-print-length)
- (print-level eval-expression-print-level)
elisp--eval-defun-result)
(save-excursion
;; Arrange for eval-region to "read" the (possibly) altered form.
@@ -1630,10 +1658,17 @@ Return the result of evaluation."
(setq beg (point))
(setq form (funcall load-read-function (current-buffer)))
(setq end (point)))
- ;; Alter the form if necessary.
- (let ((form (eval-sexp-add-defvars
- (elisp--eval-defun-1
- (macroexpand form)))))
+ ;; Alter the form if necessary. We bind `print-level' (etc.)
+ ;; in the form itself, because we want evalling the form to
+ ;; use the original values, while we want the printing to use
+ ;; `eval-expression-print-length' (etc.).
+ (let ((form `(let ((print-level ,print-level)
+ (print-length ,print-length))
+ ,(eval-sexp-add-defvars
+ (elisp--eval-defun-1
+ (macroexpand form)))))
+ (print-length eval-expression-print-length)
+ (print-level eval-expression-print-level))
(eval-region beg end standard-output
(lambda (_ignore)
;; Skipping to the end of the specified region
@@ -1649,7 +1684,10 @@ Return the result of evaluation."
elisp--eval-defun-result))
(defun eval-defun (edebug-it)
- "Evaluate the top-level form containing point, or after point.
+ "Evaluate the top-level form containing point.
+If point isn't in a top-level form, evaluate the first top-level
+form after point. If there is no top-level form after point,
+eval the first preceeding top-level form.
If the current defun is actually a call to `defvar' or `defcustom',
evaluating it this way resets the variable using its initial value
@@ -1714,7 +1752,7 @@ which see."
(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner
"Return Elisp documentation for the thing at point as one-line string.
This is meant as a backward compatibility aide to the \"old\"
-Elisp eldoc behaviour. Consider variable docstrings and function
+Elisp eldoc behavior. Consider variable docstrings and function
signatures only, in this order. If none applies, returns nil.
Changes to `eldoc-documentation-functions' and
`eldoc-documentation-strategy' are _not_ reflected here. As such
@@ -1737,7 +1775,8 @@ Intended for `eldoc-documentation-functions' (which see)."
(defun elisp-eldoc-var-docstring (callback &rest _ignored)
"Document variable at point.
-Intended for `eldoc-documentation-functions' (which see)."
+Intended for `eldoc-documentation-functions' (which see).
+Also see `elisp-eldoc-var-docstring-with-value'."
(let* ((sym (elisp--current-symbol))
(docstring (and sym (elisp-get-var-docstring sym))))
(when docstring
@@ -1745,6 +1784,33 @@ Intended for `eldoc-documentation-functions' (which see)."
:thing sym
:face 'font-lock-variable-name-face))))
+(defun elisp-eldoc-var-docstring-with-value (callback &rest _)
+ "Document variable at point.
+Intended for `eldoc-documentation-functions' (which see).
+Compared to `elisp-eldoc-var-docstring', this also includes the
+current variable value and a bigger chunk of the docstring."
+ (when-let ((cs (elisp--current-symbol)))
+ (when (and (boundp cs)
+ ;; nil and t are boundp!
+ (not (null cs))
+ (not (eq cs t)))
+ (funcall callback
+ (format "%.100S %s"
+ (symbol-value cs)
+ (let* ((doc (documentation-property
+ cs 'variable-documentation t))
+ (more (- (length doc) 1000)))
+ (concat (propertize
+ (string-limit (if (string= doc "nil")
+ "Undocumented."
+ doc)
+ 1000)
+ 'face 'font-lock-doc-face)
+ (when (> more 0)
+ (format "[%sc more]" more)))))
+ :thing cs
+ :face 'font-lock-variable-name-face))))
+
(defun elisp-get-fnsym-args-string (sym &optional index)
"Return a string containing the parameter list of the function SYM.
If SYM is a subr and no arglist is obtainable from the docstring
@@ -2062,7 +2128,9 @@ current buffer state and calls REPORT-FN when done."
(when (process-live-p elisp-flymake--byte-compile-process)
(kill-process elisp-flymake--byte-compile-process)))
(let ((temp-file (make-temp-file "elisp-flymake-byte-compile"))
- (source-buffer (current-buffer)))
+ (source-buffer (current-buffer))
+ (coding-system-for-write 'utf-8-unix)
+ (coding-system-for-read 'utf-8))
(save-restriction
(widen)
(write-region (point-min) (point-max) temp-file nil 'nomessage))
@@ -2083,7 +2151,7 @@ current buffer state and calls REPORT-FN when done."
:connection-type 'pipe
:sentinel
(lambda (proc _event)
- (when (eq (process-status proc) 'exit)
+ (unless (process-live-p proc)
(unwind-protect
(cond
((not (and (buffer-live-p source-buffer)
@@ -2112,6 +2180,8 @@ Runs in a batch-mode Emacs. Interactively use variable
(interactive (list buffer-file-name))
(let* ((file (or file
(car command-line-args-left)))
+ (coding-system-for-read 'utf-8-unix)
+ (coding-system-for-write 'utf-8)
(byte-compile-log-buffer
(generate-new-buffer " *dummy-byte-compile-log-buffer*"))
(byte-compile-dest-file-function #'ignore)
@@ -2129,6 +2199,67 @@ Runs in a batch-mode Emacs. Interactively use variable
(terpri)
(pp collected)))
+(defun elisp-eval-buffer ()
+ "Evaluate the forms in the current buffer."
+ (interactive)
+ (eval-buffer)
+ (message "Evaluated the %s buffer" (buffer-name)))
+
+(defun elisp-byte-compile-file (&optional load)
+ "Byte compile the file the current buffer is visiting.
+If LOAD is non-nil, load the resulting .elc file. When called
+interactively, this is the prefix argument."
+ (interactive "P")
+ (unless buffer-file-name
+ (error "This buffer is not visiting a file"))
+ (byte-compile-file buffer-file-name)
+ (when load
+ (load (funcall byte-compile-dest-file-function buffer-file-name))))
+
+(defun elisp-byte-compile-buffer (&optional load)
+ "Byte compile the current buffer, but don't write a file.
+If LOAD is non-nil, load byte-compiled data. When called
+interactively, this is the prefix argument."
+ (interactive "P")
+ (let ((bfn buffer-file-name)
+ file elc)
+ (require 'bytecomp)
+ (unwind-protect
+ (progn
+ (setq file (make-temp-file "compile" nil ".el")
+ elc (funcall byte-compile-dest-file-function file))
+ (write-region (point-min) (point-max) file nil 'silent)
+ (let ((set-message-function
+ (lambda (message)
+ (when (string-match-p "\\`Wrote " message)
+ 'ignore)))
+ (byte-compile-log-warning-function
+ (lambda (string position &optional fill level)
+ (if bfn
+ ;; Massage the warnings to that they point to
+ ;; this file, not the one in /tmp.
+ (let ((byte-compile-current-file bfn)
+ (byte-compile-root-dir (file-name-directory bfn)))
+ (byte-compile--log-warning-for-byte-compile
+ string position fill level))
+ ;; We don't have a file name, so the warnings
+ ;; will point to a file that doesn't exist. This
+ ;; should be fixed in some way.
+ (byte-compile--log-warning-for-byte-compile
+ string position fill level)))))
+ (byte-compile-file file))
+ (when (and bfn (get-buffer "*Compile-Log*"))
+ (with-current-buffer "*Compile-Log*"
+ (setq default-directory (file-name-directory bfn))))
+ (if load
+ (load elc)
+ (message "Byte-compiled the current buffer")))
+ (when file
+ (when (file-exists-p file)
+ (delete-file file))
+ (when (file-exists-p elc)
+ (delete-file elc))))))
+
(put 'read-symbol-shorthands 'safe-local-variable #'consp)
diff --git a/lisp/progmodes/erts-mode.el b/lisp/progmodes/erts-mode.el
index 31a8bded8ad..13da1d478d6 100644
--- a/lisp/progmodes/erts-mode.el
+++ b/lisp/progmodes/erts-mode.el
@@ -51,25 +51,23 @@
:foreground "blue")
(t
:bold t))
- "Face used for displaying specificaton values."
+ "Face used for displaying specification values."
:group 'erts-mode)
(defface erts-mode-start-test
'((t :inherit font-lock-keyword-face))
- "Face used for displaying specificaton test start markers."
+ "Face used for displaying specification test start markers."
:group 'erts-mode)
(defface erts-mode-end-test
'((t :inherit font-lock-comment-face))
- "Face used for displaying specificaton test start markers."
+ "Face used for displaying specification test start markers."
:group 'erts-mode)
-(defvar erts-mode-map
- (let ((map (make-keymap)))
- (set-keymap-parent map prog-mode-map)
- (define-key map "\C-c\C-r" 'erts-tag-region)
- (define-key map "\C-c\C-c" 'erts-run-test)
- map))
+(defvar-keymap erts-mode-map
+ :parent prog-mode-map
+ "C-c C-r" #'erts-tag-region
+ "C-c C-c" #'erts-run-test)
(defvar erts-mode-font-lock-keywords
;; Specifications.
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index e1b1e67dbcf..7766694edff 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1839,7 +1839,13 @@ Also see the documentation of the `tags-file-name' variable."
Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
with the command \\[fileloop-continue].
-For non-interactive use, superseded by `fileloop-initialize-replace'."
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
+For non-interactive use, this is superseded by `fileloop-initialize-replace'."
(declare (advertised-calling-convention (from to &optional delimited) "27.1"))
(interactive (query-replace-read-args "Tags query replace (regexp)" t t))
(fileloop-initialize-replace
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index d7c093444ed..670b6e7e898 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -240,12 +240,13 @@ executable."
(not (string= argument
(buffer-substring (point) (match-end 1))))
(if (or (not executable-query) no-query-flag
- (save-window-excursion
- ;; Make buffer visible before question.
- (switch-to-buffer (current-buffer))
- (y-or-n-p (format-message
- "Replace magic number by `#!%s'? "
- argument))))
+ (save-match-data
+ (save-window-excursion
+ ;; Make buffer visible before question.
+ (switch-to-buffer (current-buffer))
+ (y-or-n-p (format-message
+ "Replace magic number by `#!%s'? "
+ argument)))))
(progn
(replace-match argument t t nil 1)
(message "Magic number changed to `#!%s'" argument))))
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 263cd0ef296..dcd74f0369c 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -600,6 +600,7 @@ and variable-name parts, respectively."
(append
f90-font-lock-keywords-1
(list
+ '("\\(&\\)[ \t]*\\(!\\|$\\)" (1 font-lock-keyword-face))
;; Variable declarations (avoid the real function call).
;; NB by accident (?), this correctly fontifies the "integer" in:
;; integer () function foo ()
@@ -611,8 +612,8 @@ and variable-name parts, respectively."
'("^[ \t0-9]*\\(?:pure\\|elemental\\)?[ \t]*\
\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
enumerator\\|generic\\|procedure\\|logical\\|double[ \t]*precision\\)\
-\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\)"
- (1 font-lock-type-face t) (4 font-lock-variable-name-face t))
+\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\(?:&\n[^&!\n]*\\)*\\)"
+ (1 font-lock-type-face t) (4 font-lock-variable-name-face append))
;; Derived type/class variables.
;; TODO ? If we just highlighted the "type" part, rather than
;; "type(...)", this could be in the previous expression. And this
@@ -654,7 +655,6 @@ logical\\|double[ \t]*precision\\|type[ \t]*(\\(?:\\sw\\|\\s_\\)+)\\|none\\)[ \t
'("\\_<\\(namelist\\|common\\)[ \t]*/\\(\\(?:\\sw\\|\\s_\\)+\\)?/"
(1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
"\\_<else\\([ \t]*if\\|where\\)?\\_>"
- '("\\(&\\)[ \t]*\\(!\\|$\\)" (1 font-lock-keyword-face))
"\\_<\\(then\\|continue\\|format\\|include\\|\\(?:error[ \t]+\\)?stop\\|\
return\\)\\_>"
'("\\_<\\(exit\\|cycle\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)?\\_>"
@@ -825,9 +825,7 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
:style toggle :help "Expand abbreviations while typing in this buffer"]
["Add Imenu Menu" f90-add-imenu-menu
:active (not (lookup-key (current-local-map) [menu-bar index]))
- :included (fboundp 'imenu-add-to-menubar)
- :help "Add an index menu to the menu-bar"
- ]))
+ :help "Add an index menu to the menu-bar"]))
map)
"Keymap used in F90 mode.")
diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el
index eebfa70e348..4ab16831bc1 100644
--- a/lisp/progmodes/flymake-proc.el
+++ b/lisp/progmodes/flymake-proc.el
@@ -903,7 +903,7 @@ can also be executed interactively independently of
(defun flymake-proc--delete-temp-directory (dir-name)
"Attempt to delete temp dir DIR-NAME, do not fail on error."
- (let* ((temp-dir temporary-file-directory)
+ (let* ((temp-dir (file-truename temporary-file-directory))
(suffix (substring dir-name (1+ (length (directory-file-name temp-dir))))))
(while (> (length suffix) 0)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 0c16ddedcbe..0b7958e52fb 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -4,9 +4,9 @@
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: João Távora <joaotavora@gmail.com>
-;; Version: 1.2.1
+;; Version: 1.2.2
;; Keywords: c languages tools
-;; Package-Requires: ((emacs "28.1") (eldoc "1.1.0") (project "0.7.1"))
+;; Package-Requires: ((emacs "26.1") (eldoc "1.1.0") (project "0.7.1"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
;; compatible with the version of Emacs recorded above.
@@ -267,8 +267,8 @@ If set to nil, don't suppress any zero counters."
(format " [%s %s]"
(or sublog 'flymake)
;; Handle file names with "%" correctly. (Bug#51549)
- (string-replace "%" "%%"
- (buffer-name (current-buffer))))))
+ (replace-regexp-in-string "%" "%%"
+ (buffer-name (current-buffer))))))
(display-warning (list 'flymake sublog)
(apply #'format-message msg args)
(if (numberp level)
@@ -303,7 +303,7 @@ generated it."
(defun flymake-error (text &rest args)
"Format TEXT with ARGS and signal an error for Flymake."
(let ((msg (apply #'format-message text args)))
- (flymake-log :error msg)
+ (flymake-log :error "%s" msg)
(error (concat "[Flymake] " msg))))
(cl-defstruct (flymake--diag
@@ -1102,6 +1102,13 @@ The commands `flymake-goto-next-error' and
`flymake-goto-prev-error' can be used to navigate among Flymake
diagnostics annotated in the buffer.
+By default, `flymake-mode' doesn't override the \\[next-error] command, but
+if you're using Flymake a lot (and don't use the regular compilation
+mechanisms that often), it can be useful to put something like
+the following in your init file:
+
+ (setq next-error-function \\='flymake-goto-next-error)
+
The visual appearance of each type of diagnostic can be changed
by setting properties `flymake-overlay-control', `flymake-bitmap'
and `flymake-severity' on the symbols of diagnostic types (like
@@ -1358,6 +1365,11 @@ This is a suitable place for placing the `flymake-error-counter',
Separating each of these with space is not necessary."
:type '(repeat (choice string symbol)))
+(defcustom flymake-mode-line-lighter "Flymake"
+ "The string to use in the Flymake mode line."
+ :type 'string
+ :version "29.1")
+
(defvar flymake-mode-line-title '(:eval (flymake--mode-line-title))
"Mode-line construct to show Flymake's mode name and menu.")
@@ -1386,7 +1398,7 @@ correctly.")
(defun flymake--mode-line-title ()
`(:propertize
- "Flymake"
+ ,flymake-mode-line-lighter
mouse-face mode-line-highlight
help-echo
,(lambda (&rest _)
@@ -1637,6 +1649,8 @@ buffer."
(defun flymake-show-buffer-diagnostics ()
"Show a list of Flymake diagnostics for current buffer."
(interactive)
+ (unless flymake-mode
+ (user-error "Flymake mode is not enabled in the current buffer"))
(let* ((name (flymake--diagnostics-buffer-name))
(source (current-buffer))
(target (or (get-buffer name)
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 86f0be7320e..786c5ae8042 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -2213,7 +2213,6 @@ arg DO-SPACE prevents stripping the whitespace."
:style toggle :help "Expand abbreviations while typing in this buffer"]
["Add Imenu Menu" imenu-add-menubar-index
:active (not (lookup-key (current-local-map) [menu-bar index]))
- :included (fboundp 'imenu-add-to-menubar)
:help "Add an index menu to the menu-bar"]))
(provide 'fortran)
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index ddccbe80e7f..21bb75ae0cf 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -90,6 +90,7 @@
(require 'gud)
(require 'cl-lib)
(require 'cl-seq)
+(require 'bindat)
(eval-when-compile (require 'pcase))
(declare-function speedbar-change-initial-expansion-list
@@ -104,6 +105,7 @@
;; at toplevel, so the compiler doesn't know under which circumstances
;; they're defined.
(declare-function gud-until "gud" (arg))
+(declare-function gud-go "gud" (arg))
(declare-function gud-print "gud" (arg))
(declare-function gud-down "gud" (arg))
(declare-function gud-up "gud" (arg))
@@ -283,8 +285,8 @@ Possible values are:
:type '(choice
(const :tag "Always restore" t)
(const :tag "Don't restore" nil)
- (const :tag "Depends on `gdb-show-main'" 'if-gdb-show-main)
- (const :tag "Depends on `gdb-many-windows'" 'if-gdb-many-windows))
+ (const :tag "Depends on `gdb-show-main'" if-gdb-show-main)
+ (const :tag "Depends on `gdb-many-windows'" if-gdb-many-windows))
:group 'gdb
:version "28.1")
@@ -682,7 +684,7 @@ Note that this variable only takes effect when variable
Until there are such number of source windows on screen, GDB
tries to open a new window when visiting a new source file; after
that GDB starts to reuse existing source windows."
- :type 'number
+ :type 'natnum
:group 'gdb
:version "28.1")
@@ -954,12 +956,16 @@ detailed description of this mode.
(forward-char 2)
(gud-call "-exec-until *%a" arg)))
"\C-u" "Continue to current line or address.")
- ;; TODO Why arg here?
(gud-def
- gud-go (gud-call (if gdb-active-process
- (gdb-gud-context-command "-exec-continue")
- "-exec-run") arg)
- nil "Start or continue execution.")
+ gud-go (progn
+ (when arg
+ (gud-call (concat "-exec-arguments "
+ (read-string "Arguments to exec-run: "))))
+ (gud-call
+ (if gdb-active-process
+ (gdb-gud-context-command "-exec-continue")
+ "-exec-run")))
+ "C-v" "Start or continue execution. Use a prefix to specify arguments.")
;; For debugging Emacs only.
(gud-def gud-pp
@@ -1138,7 +1144,8 @@ no input, and GDB is waiting for input."
(setq name (nth 1 (split-string define "[( ]")))
(push (cons name define) gdb-define-alist))))
-(declare-function tooltip-show "tooltip" (text &optional use-echo-area))
+(declare-function tooltip-show "tooltip" (text &optional use-echo-area
+ text-face default-face))
(defconst gdb--string-regexp (rx "\""
(* (or (seq "\\" nonl)
@@ -1580,7 +1587,7 @@ Buffer mode and name are selected according to buffer type.
If buffer has trigger associated with it in `gdb-buffer-rules',
this trigger is subscribed to `gdb-buf-publisher' and called with
-'update argument."
+`update' argument."
(or (gdb-get-buffer buffer-type thread)
(let ((rules (assoc buffer-type gdb-buffer-rules))
(new (generate-new-buffer "limbo")))
@@ -2105,7 +2112,7 @@ is running."
(not (null gdb-running-threads-count))
(> gdb-running-threads-count 0))))
-;; GUD displays the selected GDB frame. This might might not be the current
+;; GUD displays the selected GDB frame. This might not be the current
;; GDB frame (after up, down etc). If no GDB frame is visible but the last
;; visited breakpoint is, use that window.
(defun gdb-display-source-buffer (buffer)
@@ -3080,6 +3087,45 @@ See `def-gdb-auto-update-handler'."
'gdb-breakpoints-mode
'gdb-invalidate-breakpoints)
+(defun gdb-breakpoints--add-breakpoint-row (tbl bkpt)
+ (let ((at (gdb-mi--field bkpt 'at))
+ (pending (gdb-mi--field bkpt 'pending))
+ (addr (gdb-mi--field bkpt 'addr))
+ (func (gdb-mi--field bkpt 'func))
+ (type (gdb-mi--field bkpt 'type)))
+ (if (and (not func) (string-equal addr "<MULTIPLE>"))
+ (setq func ""))
+ (gdb-table-add-row tbl
+ (list
+ (gdb-mi--field bkpt 'number)
+ (or type "")
+ (or (gdb-mi--field bkpt 'disp) "")
+ (let ((flag (gdb-mi--field bkpt 'enabled)))
+ (if (string-equal flag "y")
+ (eval-when-compile
+ (propertize "y" 'font-lock-face
+ font-lock-warning-face))
+ (eval-when-compile
+ (propertize "n" 'font-lock-face
+ font-lock-comment-face))))
+ addr
+ (or (gdb-mi--field bkpt 'times) "")
+ (if (and type (string-match ".*watchpoint" type))
+ (gdb-mi--field bkpt 'what)
+ (or (and (equal func "") "")
+ pending at
+ (concat "in "
+ (propertize (or func "unknown")
+ 'font-lock-face
+ font-lock-function-name-face)
+ (gdb-frame-location bkpt)))))
+ ;; Add clickable properties only for
+ ;; breakpoints with file:line information
+ (append (list 'gdb-breakpoint bkpt)
+ (when func
+ '(help-echo "mouse-2, RET: visit breakpoint"
+ mouse-face highlight))))))
+
(defun gdb-breakpoints-list-handler-custom ()
(let ((breakpoints-list (gdb-mi--field
(gdb-mi--field (gdb-mi--partial-output 'bkpt)
@@ -3092,37 +3138,14 @@ See `def-gdb-auto-update-handler'."
(add-to-list 'gdb-breakpoints-list
(cons (gdb-mi--field breakpoint 'number)
breakpoint))
- (let ((at (gdb-mi--field breakpoint 'at))
- (pending (gdb-mi--field breakpoint 'pending))
- (func (gdb-mi--field breakpoint 'func))
- (type (gdb-mi--field breakpoint 'type)))
- (gdb-table-add-row table
- (list
- (gdb-mi--field breakpoint 'number)
- (or type "")
- (or (gdb-mi--field breakpoint 'disp) "")
- (let ((flag (gdb-mi--field breakpoint 'enabled)))
- (if (string-equal flag "y")
- (eval-when-compile
- (propertize "y" 'font-lock-face
- font-lock-warning-face))
- (eval-when-compile
- (propertize "n" 'font-lock-face
- font-lock-comment-face))))
- (gdb-mi--field breakpoint 'addr)
- (or (gdb-mi--field breakpoint 'times) "")
- (if (and type (string-match ".*watchpoint" type))
- (gdb-mi--field breakpoint 'what)
- (or pending at
- (concat "in "
- (propertize (or func "unknown")
- 'font-lock-face font-lock-function-name-face)
- (gdb-frame-location breakpoint)))))
- ;; Add clickable properties only for breakpoints with file:line
- ;; information
- (append (list 'gdb-breakpoint breakpoint)
- (when func '(help-echo "mouse-2, RET: visit breakpoint"
- mouse-face highlight))))))
+ ;; Add the breakpoint/header row to the table.
+ (gdb-breakpoints--add-breakpoint-row table breakpoint)
+ ;; If this breakpoint has multiple locations, add them as well.
+ (when-let ((locations (gdb-mi--field breakpoint 'locations)))
+ (dolist (loc locations)
+ (add-to-list 'gdb-breakpoints-list
+ (cons (gdb-mi--field loc 'number) loc))
+ (gdb-breakpoints--add-breakpoint-row table loc))))
(insert (gdb-table-string table " "))
(gdb-place-breakpoints)))
@@ -4288,7 +4311,7 @@ member."
;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards.
(def-gdb-trigger-and-handler
gdb-invalidate-locals
- (concat (gdb-current-context-command "-stack-list-locals")
+ (concat (gdb-current-context-command "-stack-list-variables")
" --simple-values")
gdb-locals-handler gdb-locals-handler-custom
'(start update))
@@ -4299,6 +4322,48 @@ member."
'gdb-locals-mode
'gdb-invalidate-locals)
+
+;; Retrieve the values of all variables before invalidating locals.
+(def-gdb-trigger-and-handler
+ gdb-locals-values
+ (concat (gdb-current-context-command "-stack-list-variables")
+ " --all-values")
+ gdb-locals-values-handler gdb-locals-values-handler-custom
+ '(start update))
+
+(gdb-set-buffer-rules
+ 'gdb-locals-values-buffer
+ 'gdb-locals-values-buffer-name
+ 'gdb-locals-mode
+ 'gdb-locals-values)
+
+(defun gdb-locals-values-buffer-name ()
+ (gdb-current-context-buffer-name
+ (concat "local values of " (gdb-get-target-string))))
+
+(defcustom gdb-locals-simple-values-only nil
+ "Only display simple values in the Locals buffer."
+ :type 'boolean
+ :group 'gud
+ :version "29.1")
+
+(defcustom gdb-locals-value-limit 100
+ "Maximum length the value of a local variable is allowed to be."
+ :type 'integer
+ :group 'gud
+ :version "29.1")
+
+(defvar gdb-locals-values-table (make-hash-table :test #'equal)
+ "Mapping of local variable names to a string with their value.")
+
+(defun gdb-locals-values-handler-custom ()
+ "Store the values of local variables in `gdb-locals-value-map'."
+ (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables)))
+ (dolist (local locals-list)
+ (let ((name (bindat-get-field local 'name))
+ (value (bindat-get-field local 'value)))
+ (puthash name value gdb-locals-values-table)))))
+
(defvar gdb-locals-watch-map
(let ((map (make-sparse-keymap)))
(suppress-keymap map)
@@ -4315,6 +4380,15 @@ member."
map)
"Keymap to edit value of a simple data type local variable.")
+(defun gdb-locals-value-filter (value)
+ "Filter function for the local variable VALUE."
+ (let* ((no-nl (replace-regexp-in-string "\n" " " value))
+ (str (replace-regexp-in-string "[[:space:]]+" " " no-nl))
+ (limit gdb-locals-value-limit))
+ (if (>= (length str) limit)
+ (concat (substring str 0 limit) "...")
+ str)))
+
(defun gdb-edit-locals-value (&optional event)
"Assign a value to a variable displayed in the locals buffer."
(interactive (list last-input-event))
@@ -4327,17 +4401,22 @@ member."
(gud-basic-call
(concat "-gdb-set variable " var " = " value)))))
-;; Don't display values of arrays or structures.
-;; These can be expanded using gud-watch.
+;; Complex data types are looked up in `gdb-locals-values-table'.
(defun gdb-locals-handler-custom ()
- (let ((locals-list (gdb-mi--field (gdb-mi--partial-output) 'locals))
+ "Handler to rebuild the local variables table buffer."
+ (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables))
(table (make-gdb-table)))
(dolist (local locals-list)
(let ((name (gdb-mi--field local 'name))
(value (gdb-mi--field local 'value))
(type (gdb-mi--field local 'type)))
(when (not value)
- (setq value "<complex data type>"))
+ (setq value
+ (if gdb-locals-simple-values-only
+ "<complex data type>"
+ (gethash name gdb-locals-values-table "<unavailable>"))))
+ (setq value (gdb-locals-value-filter value))
+
(if (or (not value)
(string-match "0x" value))
(add-text-properties 0 (length name)
@@ -4860,6 +4939,8 @@ file\" where the GDB session starts (see `gdb-main-file')."
(expand-file-name gdb-default-window-configuration-file
gdb-window-configuration-directory)))
;; Create default layout as before.
+ ;; Make sure that local values are updated before locals.
+ (gdb-get-buffer-create 'gdb-locals-values-buffer)
(gdb-get-buffer-create 'gdb-locals-buffer)
(gdb-get-buffer-create 'gdb-stack-buffer)
(gdb-get-buffer-create 'gdb-breakpoints-buffer)
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index ccc58e6773c..423de7d5818 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -48,8 +48,8 @@ to avoid computing them again.")
"Set SYMBOL to VALUE, and update `grep-host-defaults-alist'.
SYMBOL should be one of `grep-command', `grep-template',
`grep-use-null-device', `grep-find-command' `grep-find-template',
-`grep-find-use-xargs', `grep-use-null-filename-separator', or
-`grep-highlight-matches'."
+`grep-find-use-xargs', `grep-use-null-filename-separator',
+`grep-highlight-matches', or `grep-quoting-style'."
(when grep-host-defaults-alist
(let* ((host-id
(intern (or (file-remote-p default-directory) "localhost")))
@@ -202,6 +202,9 @@ by `grep-compute-defaults'; to change the default value, use
:set #'grep-apply-setting
:version "22.1")
+(defvar grep-quoting-style nil
+ "Whether to use POSIX-like shell argument quoting.")
+
(defcustom grep-files-aliases
'(("all" . "* .*")
("el" . "*.el")
@@ -212,6 +215,7 @@ by `grep-compute-defaults'; to change the default value, use
("hh" . "*.hxx *.hpp *.[Hh] *.HH *.h++")
("h" . "*.h")
("l" . "[Cc]hange[Ll]og*")
+ ("am" . "Makefile.am GNUmakefile *.mk")
("m" . "[Mm]akefile*")
("tex" . "*.tex")
("texi" . "*.texi")
@@ -269,16 +273,16 @@ See `compilation-error-screen-columns'."
(defvar grep-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map compilation-minor-mode-map)
- (define-key map " " 'scroll-up-command)
- (define-key map [?\S-\ ] 'scroll-down-command)
- (define-key map "\^?" 'scroll-down-command)
- (define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
-
- (define-key map "\r" 'compile-goto-error) ;; ?
- (define-key map "{" 'compilation-previous-file)
- (define-key map "}" 'compilation-next-file)
- (define-key map "\t" 'compilation-next-error)
- (define-key map [backtab] 'compilation-previous-error)
+ (define-key map " " #'scroll-up-command)
+ (define-key map [?\S-\ ] #'scroll-down-command)
+ (define-key map "\^?" #'scroll-down-command)
+ (define-key map "\C-c\C-f" #'next-error-follow-minor-mode)
+
+ (define-key map "\r" #'compile-goto-error) ;; ?
+ (define-key map "{" #'compilation-previous-file)
+ (define-key map "}" #'compilation-next-file)
+ (define-key map "\t" #'compilation-next-error)
+ (define-key map [backtab] #'compilation-previous-error)
map)
"Keymap for grep buffers.
`compilation-minor-mode-map' is a cdr of this.")
@@ -322,24 +326,24 @@ See `compilation-error-screen-columns'."
;; FIXME: Nowadays the last button is not "help" but "search"!
(help (last tool-bar-map))) ;; Keep Help last in tool bar
(tool-bar-local-item
- "left-arrow" 'previous-error-no-select 'previous-error-no-select map
+ "left-arrow" #'previous-error-no-select #'previous-error-no-select map
:rtl "right-arrow"
:help "Goto previous match")
(tool-bar-local-item
- "right-arrow" 'next-error-no-select 'next-error-no-select map
+ "right-arrow" #'next-error-no-select #'next-error-no-select map
:rtl "left-arrow"
:help "Goto next match")
(tool-bar-local-item
- "cancel" 'kill-compilation 'kill-compilation map
+ "cancel" #'kill-compilation #'kill-compilation map
:enable '(let ((buffer (compilation-find-buffer)))
(get-buffer-process buffer))
:help "Stop grep")
(tool-bar-local-item
- "refresh" 'recompile 'recompile map
+ "refresh" #'recompile #'recompile map
:help "Restart grep")
(append map help))))
-(defalias 'kill-grep 'kill-compilation)
+(defalias 'kill-grep #'kill-compilation)
;; override compilation-last-buffer
(defvar grep-last-buffer nil
@@ -443,9 +447,9 @@ buffer `default-directory'."
(defvar grep-find-abbreviate-properties
(let ((ellipsis (if (char-displayable-p ?…) "[…]" "[...]"))
(map (make-sparse-keymap)))
- (define-key map [down-mouse-2] 'mouse-set-point)
- (define-key map [mouse-2] 'grep-find-toggle-abbreviation)
- (define-key map "\C-m" 'grep-find-toggle-abbreviation)
+ (define-key map [down-mouse-2] #'mouse-set-point)
+ (define-key map [mouse-2] #'grep-find-toggle-abbreviation)
+ (define-key map "\C-m" #'grep-find-toggle-abbreviation)
`(face nil display ,ellipsis mouse-face highlight
help-echo "RET, mouse-2: show unabbreviated command"
keymap ,map abbreviated-command t))
@@ -453,7 +457,7 @@ buffer `default-directory'."
(defvar grep-mode-font-lock-keywords
'(;; Command output lines.
- (": \\(.+\\): \\(?:Permission denied\\|No such \\(?:file or directory\\|device or address\\)\\)$"
+ (": \\(.\\{,200\\}\\): \\(?:Permission denied\\|No such \\(?:file or directory\\|device or address\\)\\)$"
1 grep-error-face)
;; remove match from grep-regexp-alist before fontifying
("^Grep[/a-zA-Z]* started.*"
@@ -616,8 +620,8 @@ This function is called from `compilation-filter-hook'."
"Compute the defaults for the `grep' command.
The value depends on `grep-command', `grep-template',
`grep-use-null-device', `grep-find-command', `grep-find-template',
-`grep-use-null-filename-separator', `grep-find-use-xargs' and
-`grep-highlight-matches'."
+`grep-use-null-filename-separator', `grep-find-use-xargs',
+`grep-highlight-matches', and `grep-quoting-style'."
;; Keep default values.
(unless grep-host-defaults-alist
(add-to-list
@@ -631,13 +635,14 @@ The value depends on `grep-command', `grep-template',
(grep-use-null-filename-separator
,grep-use-null-filename-separator)
(grep-find-use-xargs ,grep-find-use-xargs)
- (grep-highlight-matches ,grep-highlight-matches)))))
- (let* ((host-id
- (intern (or (file-remote-p default-directory) "localhost")))
+ (grep-highlight-matches ,grep-highlight-matches)
+ (grep-quoting-style ,grep-quoting-style)))))
+ (let* ((remote (file-remote-p default-directory))
+ (host-id (intern (or remote "localhost")))
(host-defaults (assq host-id grep-host-defaults-alist))
(defaults (assq nil grep-host-defaults-alist))
- (quot-braces (shell-quote-argument "{}"))
- (quot-scolon (shell-quote-argument ";")))
+ (quot-braces (shell-quote-argument "{}" remote))
+ (quot-scolon (shell-quote-argument ";" remote)))
;; There are different defaults on different hosts. They must be
;; computed for every host once.
(dolist (setting '(grep-command grep-template
@@ -791,8 +796,11 @@ The value depends on `grep-command', `grep-template',
find-program gcmd null quot-braces))
(t
(format "%s -H <D> <X> -type f <F> -print | \"%s\" %s"
- find-program xargs-program gcmd))))))))
- ;; Save defaults for this host.
+ find-program xargs-program gcmd))))))
+
+ (setq grep-quoting-style (and remote 'posix))))
+
+ ;; Save defaults for this host.
(setq grep-host-defaults-alist
(delete (assq host-id grep-host-defaults-alist)
grep-host-defaults-alist))
@@ -807,7 +815,8 @@ The value depends on `grep-command', `grep-template',
(grep-use-null-filename-separator
,grep-use-null-filename-separator)
(grep-find-use-xargs ,grep-find-use-xargs)
- (grep-highlight-matches ,grep-highlight-matches))))))
+ (grep-highlight-matches ,grep-highlight-matches)
+ (grep-quoting-style ,grep-quoting-style))))))
(defun grep-tag-default ()
(or (and transient-mark-mode mark-active
@@ -820,7 +829,8 @@ The value depends on `grep-command', `grep-template',
(defun grep-default-command ()
"Compute the default grep command for \\[universal-argument] \\[grep] to offer."
- (let ((tag-default (shell-quote-argument (grep-tag-default)))
+ (let ((tag-default
+ (shell-quote-argument (grep-tag-default) grep-quoting-style))
;; This a regexp to match single shell arguments.
;; Could someone please add comments explaining it?
(sh-arg-re
@@ -875,6 +885,14 @@ The value depends on `grep-command', `grep-template',
(setq-local compilation-disable-input t)
(setq-local compilation-error-screen-columns
grep-error-screen-columns)
+ ;; We normally use a nul byte to separate the file name from the
+ ;; contents, but display it as ":". That's fine, but when yanking
+ ;; to other buffers, it's annoying to have the nul byte there.
+ (unless kill-transform-function
+ (setq-local kill-transform-function #'identity))
+ (add-function :filter-return (local 'kill-transform-function)
+ (lambda (string)
+ (string-replace "\0" ":" string)))
(add-hook 'compilation-filter-hook #'grep-filter nil t))
(defun grep--save-buffers ()
@@ -952,8 +970,7 @@ easily repeat a find command."
(grep command-args))))
;;;###autoload
-(defalias 'find-grep 'grep-find)
-
+(defalias 'find-grep #'grep-find)
;; User-friendly interactive API.
@@ -963,7 +980,7 @@ easily repeat a find command."
("<F>" . files)
("<N>" . (null-device))
("<X>" . excl)
- ("<R>" . (shell-quote-argument (or regexp ""))))
+ ("<R>" . (shell-quote-argument (or regexp "") grep-quoting-style)))
"List of substitutions performed by `grep-expand-template'.
If car of an element matches, the cdr is evalled in order to get the
substitution string.
@@ -1010,7 +1027,7 @@ these include `opts', `dir', `files', `null-device', `excl' and
;; Instead of a `grep-read-files-function' variable, we used to lookup
;; mode-specific functions in the major mode's symbol properties, so preserve
;; this behavior for backward compatibility.
- (let ((old-function (get major-mode 'grep-read-files))) ;Obsolete since 28.1
+ (let ((old-function (get major-mode #'grep-read-files))) ;Obsolete since 28.1
(if old-function
(funcall old-function)
(let ((file-name-at-point
@@ -1057,15 +1074,18 @@ REGEXP is used as a string in the prompt."
default-extension
(car grep-files-history)
(car (car grep-files-aliases))))
+ (defaults
+ (delete-dups
+ (delq nil
+ (append (list default default-alias default-extension)
+ (mapcar #'car grep-files-aliases)))))
(files (completing-read
(format-prompt "Search for \"%s\" in files matching wildcard"
default regexp)
- #'read-file-name-internal
- nil nil nil 'grep-files-history
- (delete-dups
- (delq nil
- (append (list default default-alias default-extension)
- (mapcar #'car grep-files-aliases)))))))
+ (completion-table-merge
+ (lambda (_string _pred _action) defaults)
+ #'read-file-name-internal)
+ nil nil nil 'grep-files-history defaults)))
(and files
(or (cdr (assoc files grep-files-aliases))
files))))
@@ -1112,6 +1132,9 @@ command before it's run."
(when (and (stringp regexp) (> (length regexp) 0))
(unless (and dir (file-accessible-directory-p dir))
(setq dir default-directory))
+ (unless (string-equal (file-remote-p dir) (file-remote-p default-directory))
+ (let ((default-directory dir))
+ (grep-compute-defaults)))
(let ((command regexp))
(if (null files)
(if (string= command grep-command)
@@ -1134,11 +1157,13 @@ command before it's run."
(mapconcat
(lambda (ignore)
(cond ((stringp ignore)
- (shell-quote-argument ignore))
+ (shell-quote-argument
+ ignore grep-quoting-style))
((consp ignore)
(and (funcall (car ignore) dir)
(shell-quote-argument
- (cdr ignore))))))
+ (cdr ignore)
+ grep-quoting-style)))))
grep-find-ignored-files
" --exclude=")))
(and (eq grep-use-directories-skip t)
@@ -1158,7 +1183,7 @@ command before it's run."
(if (and grep-use-null-device null-device (null-device))
(concat command " " (null-device))
command)
- 'grep-mode))
+ #'grep-mode))
;; Set default-directory if we started lgrep in the *grep* buffer.
(if (eq next-error-last-buffer (current-buffer))
(setq default-directory dir))))))
@@ -1191,7 +1216,11 @@ When called programmatically and FILES is nil, REGEXP is expected
to specify a command to run.
If CONFIRM is non-nil, the user will be given an opportunity to edit the
-command before it's run."
+command before it's run.
+
+Interactively, the user can use the \\`M-c' command while entering
+the regexp to indicate whether the grep should be case sensitive
+or not."
(interactive
(progn
(grep-compute-defaults)
@@ -1210,13 +1239,17 @@ command before it's run."
(when (and (stringp regexp) (> (length regexp) 0))
(unless (and dir (file-accessible-directory-p dir))
(setq dir default-directory))
+ (unless (string-equal (file-remote-p dir) (file-remote-p default-directory))
+ (let ((default-directory dir))
+ (grep-compute-defaults)))
(if (null files)
(if (not (string= regexp (if (consp grep-find-command)
(car grep-find-command)
grep-find-command)))
- (compilation-start regexp 'grep-mode))
+ (compilation-start regexp #'grep-mode))
(setq dir (file-name-as-directory (expand-file-name dir)))
- (let ((command (rgrep-default-command regexp files nil)))
+ (let* ((case-fold-search (read-regexp-case-fold-search regexp))
+ (command (rgrep-default-command regexp files nil)))
(when command
(if confirm
(setq command
@@ -1225,7 +1258,7 @@ command before it's run."
(add-to-history 'grep-find-history command))
(grep--save-buffers)
(let ((default-directory dir))
- (compilation-start command 'grep-mode))
+ (compilation-start command #'grep-mode))
;; Set default-directory if we started rgrep in the *grep* buffer.
(if (eq next-error-last-buffer (current-buffer))
(setq default-directory dir)))))))
@@ -1245,44 +1278,46 @@ command before it's run."
(grep-expand-template
grep-find-template
regexp
- (concat (shell-quote-argument "(")
+ (concat (shell-quote-argument "(" grep-quoting-style)
" " find-name-arg " "
(mapconcat
- #'shell-quote-argument
+ (lambda (x) (shell-quote-argument x grep-quoting-style))
(split-string files)
(concat " -o " find-name-arg " "))
" "
- (shell-quote-argument ")"))
+ (shell-quote-argument ")" grep-quoting-style))
dir
(concat
(and grep-find-ignored-directories
(concat "-type d "
- (shell-quote-argument "(")
+ (shell-quote-argument "(" grep-quoting-style)
;; we should use shell-quote-argument here
" -path "
- (mapconcat (lambda (d) (shell-quote-argument (concat "*/" d)))
- (rgrep-find-ignored-directories dir)
- " -o -path ")
+ (mapconcat
+ (lambda (d)
+ (shell-quote-argument (concat "*/" d) grep-quoting-style))
+ (rgrep-find-ignored-directories dir)
+ " -o -path ")
" "
- (shell-quote-argument ")")
+ (shell-quote-argument ")" grep-quoting-style)
" -prune -o "))
(and grep-find-ignored-files
- (concat (shell-quote-argument "!") " -type d "
- (shell-quote-argument "(")
+ (concat (shell-quote-argument "!" grep-quoting-style) " -type d "
+ (shell-quote-argument "(" grep-quoting-style)
;; we should use shell-quote-argument here
" -name "
(mapconcat
(lambda (ignore)
(cond ((stringp ignore)
- (shell-quote-argument ignore))
+ (shell-quote-argument ignore grep-quoting-style))
((consp ignore)
(and (funcall (car ignore) dir)
(shell-quote-argument
- (cdr ignore))))))
+ (cdr ignore) grep-quoting-style)))))
grep-find-ignored-files
" -o -name ")
" "
- (shell-quote-argument ")")
+ (shell-quote-argument ")" grep-quoting-style)
" -prune -o ")))))
(defun grep-find-toggle-abbreviation ()
@@ -1352,7 +1387,7 @@ The returned file name is relative."
(caar (compilation--loc->file-struct loc))))
;;;###autoload
-(defalias 'rzgrep 'zrgrep)
+(defalias 'rzgrep #'zrgrep)
(provide 'grep)
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index b1bef82842d..be43effed7d 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -54,8 +54,8 @@
(declare-function gdb-tooltip-print-1 "gdb-mi" (expr))
(declare-function gud-pp "gdb-mi" (arg))
(declare-function gdb-var-delete "gdb-mi" ())
-(declare-function speedbar-toggle-line-expansion "gud" ())
-(declare-function speedbar-edit-line "gud" ())
+(declare-function speedbar-toggle-line-expansion "speedbar" ())
+(declare-function speedbar-edit-line "speedbar" ())
;; FIXME: The declares below are necessary because we don't call `gud-def'
;; at toplevel, so the compiler doesn't know under which circumstances
;; they're defined.
@@ -334,7 +334,7 @@ Used to gray out relevant toolbar icons.")
(">" . gud-down)))
(define-key map key cmd))
map)
- "Keymap to repeat `gud-gdb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `gud-gdb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defun gud-set-repeat-map-property (keymap-symbol)
@@ -744,10 +744,10 @@ The option \"--fullname\" must be included in this value."
output))
-(easy-mmode-defmap gud-minibuffer-local-map
- '(("\C-i" . comint-dynamic-complete-filename))
- "Keymap for minibuffer prompting of gud startup command."
- :inherit minibuffer-local-map)
+(defvar-keymap gud-minibuffer-local-map
+ :doc "Keymap for minibuffer prompting of gud startup command."
+ :parent minibuffer-local-map
+ "C-i" #'comint-dynamic-complete-filename)
(defun gud-query-cmdline (minor-mode &optional init)
(let* ((hist-sym (gud-symbol 'history nil minor-mode))
@@ -759,13 +759,18 @@ The option \"--fullname\" must be included in this value."
(concat (or cmd-name (symbol-name minor-mode))
" "
(or init
- (let ((file nil))
- (dolist (f (directory-files default-directory) file)
- (if (and (file-executable-p f)
- (not (file-directory-p f))
- (or (not file)
- (file-newer-than-file-p f file)))
- (setq file f)))))))
+ (let ((file nil)
+ (files (directory-files default-directory)))
+ ;; On remote systems, this may be slow, so avoid it.
+ (when (or (not (file-remote-p default-directory))
+ (length< files 50))
+ (dolist (f files)
+ (if (and (file-executable-p f)
+ (not (file-directory-p f))
+ (or (not file)
+ (file-newer-than-file-p f file)))
+ (setq file f)))
+ file)))))
gud-minibuffer-local-map nil
hist-sym)))
@@ -869,7 +874,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))))
@@ -1048,7 +1054,7 @@ SKIP is the number of chars to skip on each line, it defaults to 0."
("l" . gud-refresh)))
(define-key map key cmd))
map)
- "Keymap to repeat `sdb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `sdb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defun gud-sdb-marker-filter (string)
@@ -1295,7 +1301,7 @@ whereby $stopformat=1 produces an output format compatible with
gud-irix-p)
(define-key map "f" 'gud-finish))
map)
- "Keymap to repeat `dbx' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `dbx' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
;; The process filter is also somewhat
@@ -1470,7 +1476,7 @@ and source-file directory for your debugger."
(">" . gud-down)))
(define-key map key cmd))
map)
- "Keymap to repeat `xdb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `xdb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defcustom gud-xdb-directories nil
@@ -1558,7 +1564,7 @@ directories if your program contains sources from more than one directory."
("l" . gud-refresh)))
(define-key map key cmd))
map)
- "Keymap to repeat `perldb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `perldb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defun gud-perldb-massage-args (_file args)
@@ -1748,7 +1754,7 @@ working directory and source-file directory for your debugger."
(">" . gud-down)))
(define-key map key cmd))
map)
- "Keymap to repeat `pdb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `pdb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
;; There's no guarantee that Emacs will hand the filter the entire
@@ -1865,7 +1871,7 @@ directory and source-file directory for your debugger."
(">" . gud-down)))
(define-key map key cmd))
map)
- "Keymap to repeat `guiler' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `guiler' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defun gud-guiler-marker-filter (string)
@@ -2392,7 +2398,7 @@ extension EXTN. Normally EXTN is given as the regular expression
("l" . gud-refresh)))
(define-key map key cmd))
map)
- "Keymap to repeat `jdb' stepping instructions `C-x C-a C-n n n'.
+ "Keymap to repeat `jdb' stepping instructions \\`C-x C-a C-n n n'.
Used in `repeat-mode'.")
(defun gud-jdb-find-source-using-classpath (p)
@@ -2454,7 +2460,7 @@ during jdb initialization depending on the value of
;; not supported/followed)
(if (and gud-jdb-use-classpath
(not gud-jdb-classpath-string)
- (or (string-match "classpath:[ \t[]+\\([^]]+\\)" gud-marker-acc)
+ (or (string-match "classpath:[ \t[]+\\([^]]*\\)" gud-marker-acc)
(string-match "-classpath[ \t\"]+\\([^ \"]+\\)" gud-marker-acc)))
(setq gud-jdb-classpath
(gud-jdb-parse-classpath-string
@@ -3688,7 +3694,6 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference."
(message "Dereferencing is now %s."
(if gud-tooltip-dereference "on" "off")))
-(defvar tooltip-use-echo-area)
(declare-function tooltip-show "tooltip" (text &optional use-echo-area))
(declare-function tooltip-strip-prompt "tooltip" (process output))
@@ -3702,8 +3707,7 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference."
"Process debugger output and show it in a tooltip window."
(remove-function (process-filter process) #'gud-tooltip-process-output)
(tooltip-show (tooltip-strip-prompt process output)
- (or gud-tooltip-echo-area tooltip-use-echo-area
- (not tooltip-mode))))
+ (or gud-tooltip-echo-area (not tooltip-mode))))
(defun gud-tooltip-print-command (expr)
"Return a suitable command to print the expression EXPR."
@@ -3747,8 +3751,7 @@ This function must return nil if it doesn't handle EVENT."
(unless (null define-elt)
(tooltip-show
(cdr define-elt)
- (or gud-tooltip-echo-area tooltip-use-echo-area
- (not tooltip-mode)))
+ (or gud-tooltip-echo-area (not tooltip-mode)))
expr))))
(when gud-tooltip-dereference
(setq expr (concat "*" expr)))
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index ba2c5737480..f2ada676ab7 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -109,7 +109,7 @@
;;
;; Extensively modified by Luke Lee in 2013 to support complete C expression
;; evaluation and argumented macro expansion; C++11, C++14, C++17, GCC
-;; extension literals and gcc/clang matching behaviours are supported in 2021.
+;; extension literals and gcc/clang matching behaviors are supported in 2021.
;; Various floating point types and operations are also supported but the
;; actual precision is limited by the Emacs internal floating representation,
;; which is the C data type "double" or IEEE binary64 format.
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
index e1ee9efc54b..ec281f3a496 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/progmodes/icon.el
@@ -31,17 +31,16 @@
"Abbrev table in use in Icon-mode buffers.")
(define-abbrev-table 'icon-mode-abbrev-table ())
-(defvar icon-mode-map
- (let ((map (make-sparse-keymap "Icon")))
- (define-key map "{" 'electric-icon-brace)
- (define-key map "}" 'electric-icon-brace)
- (define-key map "\e\C-h" 'mark-icon-function)
- (define-key map "\e\C-a" 'beginning-of-icon-defun)
- (define-key map "\e\C-e" 'end-of-icon-defun)
- (define-key map "\e\C-q" 'indent-icon-exp)
- (define-key map "\177" 'backward-delete-char-untabify)
- map)
- "Keymap used in Icon mode.")
+(defvar-keymap icon-mode-map
+ :doc "Keymap used in Icon mode."
+ :name "Icon"
+ "{" #'electric-icon-brace
+ "}" #'electric-icon-brace
+ "C-M-h" #'mark-icon-function
+ "C-M-a" #'beginning-of-icon-defun
+ "C-M-e" #'end-of-icon-defun
+ "C-M-q" #'indent-icon-exp
+ "DEL" #'backward-delete-char-untabify)
(easy-menu-define icon-mode-menu icon-mode-map
"Menu for Icon mode."
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index b6063521365..d21a9faec9d 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -231,7 +231,7 @@ because these are used as separators by IDL."
(defcustom idlwave-shell-graphics-window-size '(500 400)
"Size of IDL graphics windows popped up by special IDLWAVE command.
-The command is `C-c C-d C-f' and accepts as a prefix the window nr.
+The command is \\`C-c C-d C-f' and accepts as a prefix the window nr.
A command like `WINDOW,N,xsize=XX,ysize=YY' is sent to IDL."
:group 'idlwave-shell-general-setup
:type '(list
@@ -844,7 +844,7 @@ IDL has currently stepped.")
---------
A complete set of commands for compiling and debugging IDL programs
is available from the menu. Also keybindings starting with a
- `C-c C-d' prefix are available for most commands in the *idl* buffer
+ \\`C-c C-d' prefix are available for most commands in the *idl* buffer
and also in source buffers. The best place to learn about the
keybindings is again the menu.
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index e3985db64ab..a2061fde762 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1001,9 +1001,9 @@ Obsolete, if the IDL Assistant is being used for help."
"List of modifiers to be used for the debugging commands.
Will be used to bind debugging commands in the shell buffer and in all
source buffers. These are additional convenience bindings, the debugging
-commands are always available with the `C-c C-d' prefix.
+commands are always available with the \\`C-c C-d' prefix.
If you set this to (control shift), this means setting a breakpoint will
-be on `C-S-b', compiling a source file on `C-S-c' etc. Possible modifiers
+be on \\`C-S-b', compiling a source file on \\`C-S-c' etc. Possible modifiers
are `control', `meta', `super', `hyper', `alt', and `shift'."
:group 'idlwave-shell-general-setup
:type '(set :tag "Specify modifiers"
@@ -1353,7 +1353,7 @@ the leftover unidentified statements containing an equal sign.")
;; Note that this is documented in the v18 manuals as being a string
;; of length one rather than a single character.
;; The code in this file accepts either format for compatibility.
-(defvar idlwave-comment-indent-char ?\
+(defvar idlwave-comment-indent-char ?\s
"Character to be inserted for IDL comment indentation.
Normally a space.")
@@ -3247,7 +3247,7 @@ ignored."
;; In the following while statements, after one iteration
;; point will be at the beginning of a line in which case
;; the while will not be executed for the
- ;; the first paragraph line and thus will not affect the
+ ;; first paragraph line and thus will not affect the
;; indentation.
;;
;; First check to see if indentation is based on hanging indent.
@@ -8421,7 +8421,7 @@ was pressed."
(defun idlwave-list-shell-load-path-shadows (&optional _arg)
"List the load path shadows of all routines compiled under the shell.
This is very useful for checking an IDL application. Just compile the
-application, do RESOLVE_ALL, and `C-c C-i' to compile all referenced
+application, do RESOLVE_ALL, and \\`C-c C-i' to compile all referenced
routines and update IDLWAVE internal info. Then check for shadowing
with this command."
(interactive)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 9c1358e466d..eb2a1e4fccc 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -660,13 +660,11 @@ This variable is like `sgml-attribute-offset'."
:type 'integer
:safe 'integerp)
-;;; KeyMap
+;;; Keymap
-(defvar js-mode-map
- (let ((keymap (make-sparse-keymap)))
- (define-key keymap [(meta ?.)] #'js-find-symbol)
- keymap)
- "Keymap for `js-mode'.")
+(defvar-keymap js-mode-map
+ :doc "Keymap for `js-mode'."
+ "M-." #'js-find-symbol)
;;; Syntax table and parsing
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index b9fcd033bbb..a18c8bcce44 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -121,13 +121,11 @@ If m4 is not in your PATH, set this to an absolute file name."
("#" (0 (when (m4--quoted-p (match-beginning 0))
(string-to-syntax "."))))))
-(defvar m4-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-b" 'm4-m4-buffer)
- (define-key map "\C-c\C-r" 'm4-m4-region)
- (define-key map "\C-c\C-c" 'comment-region)
- map)
- "Keymap for M4 Mode.")
+(defvar-keymap m4-mode-map
+ :doc "Keymap for M4 Mode."
+ "C-c C-b" #'m4-m4-buffer
+ "C-c C-r" #'m4-m4-region
+ "C-c C-c" #'comment-region)
(easy-menu-define m4-mode-menu m4-mode-map
"Menu for M4 Mode."
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 91307f6c09f..bd01786e08c 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -1170,7 +1170,6 @@ and adds all qualifying names to the list of known targets."
(goto-char (match-end 0))
(insert suffix))))))))
-(define-obsolete-function-alias 'makefile-complete 'completion-at-point "24.1")
;; Backslashification. Stolen from cc-mode.el.
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index 5aaa277431a..f0fd23f3bc3 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -108,30 +108,27 @@
(macro-keywords-2
"\\(primarydef\\|secondarydef\\|tertiarydef\\)")
(args-keywords
- (eval-when-compile
- (regexp-opt
- '("expr" "suffix" "text" "primary" "secondary" "tertiary")
- t)))
+ (regexp-opt
+ '("expr" "suffix" "text" "primary" "secondary" "tertiary")
+ t))
(type-keywords
- (eval-when-compile
- (regexp-opt
- '("boolean" "color" "numeric" "pair" "path" "pen" "picture"
- "string" "transform" "newinternal")
- t)))
+ (regexp-opt
+ '("boolean" "color" "numeric" "pair" "path" "pen" "picture"
+ "string" "transform" "newinternal")
+ t))
(syntactic-keywords
- (eval-when-compile
- (regexp-opt
- '("for" "forever" "forsuffixes" "endfor"
- "step" "until" "upto" "downto" "thru" "within"
- "iff" "if" "elseif" "else" "fi" "exitif" "exitunless"
- "let" "def" "vardef" "enddef" "mode_def"
- "true" "false" "known" "unknown" "and" "or" "not"
- "save" "interim" "inner" "outer" "relax"
- "begingroup" "endgroup" "expandafter" "scantokens"
- "generate" "input" "endinput" "end" "bye"
- "message" "errmessage" "errhelp" "special" "numspecial"
- "readstring" "readfrom" "write")
- t)))
+ (regexp-opt
+ '("for" "forever" "forsuffixes" "endfor"
+ "step" "until" "upto" "downto" "thru" "within"
+ "iff" "if" "elseif" "else" "fi" "exitif" "exitunless"
+ "let" "def" "vardef" "enddef" "mode_def"
+ "true" "false" "known" "unknown" "and" "or" "not"
+ "save" "interim" "inner" "outer" "relax"
+ "begingroup" "endgroup" "expandafter" "scantokens"
+ "generate" "input" "endinput" "end" "bye"
+ "message" "errmessage" "errhelp" "special" "numspecial"
+ "readstring" "readfrom" "write")
+ t))
)
(list
;; embedded TeX code in btex ... etex
@@ -441,8 +438,6 @@ If the list was changed, sort the list and remove duplicates first."
(insert close)))))))
(nth 1 entry))))
-(define-obsolete-function-alias 'meta-complete-symbol
- 'completion-at-point "24.1")
;;; Indentation.
@@ -806,7 +801,6 @@ The environment marked is the one that contains point or follows point."
st)
"Syntax table used in Metafont or MetaPost mode.")
-(define-obsolete-variable-alias 'meta-mode-map 'meta-common-mode-map "24.1")
(defvar meta-common-mode-map
(let ((map (make-sparse-keymap)))
;; Comment Paragraphs:
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index 97a218fcfa3..9d1ceaa55a8 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -78,16 +78,13 @@
;;; Code:
(defvar compile-command)
-;;; Key map
-(defvar mixal-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-c" 'compile)
- (define-key map "\C-c\C-r" 'mixal-run)
- (define-key map "\C-c\C-d" 'mixal-debug)
- (define-key map "\C-h\C-o" 'mixal-describe-operation-code)
- map)
- "Keymap for `mixal-mode'.")
-;; (makunbound 'mixal-mode-map)
+;;; Keymap
+(defvar-keymap mixal-mode-map
+ :doc "Keymap for `mixal-mode'."
+ "C-c C-c" #'compile
+ "C-c C-r" #'mixal-run
+ "C-c C-d" #'mixal-debug
+ "C-h C-o" #'mixal-describe-operation-code)
;;; Syntax table
(defvar mixal-mode-syntax-table
diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el
index a8d644dba0e..e668570ba17 100644
--- a/lisp/progmodes/modula2.el
+++ b/lisp/progmodes/modula2.el
@@ -101,9 +101,8 @@
(defcustom m2-indent 5
"This variable gives the indentation in Modula-2 mode."
- :type 'integer)
-(put 'm2-indent 'safe-local-variable
- (lambda (v) (or (null v) (integerp v))))
+ :type 'integer
+ :safe (lambda (v) (or (null v) (integerp v))))
(defconst m2-smie-grammar
;; An official definition can be found as "M2R10.pdf". This grammar does
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index ecc9386cae3..721dfa51ad3 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -197,8 +197,8 @@ newline or semicolon after an else or end keyword."
(defcustom octave-block-offset 2
"Extra indentation applied to statements in Octave block structures."
- :type 'integer)
-(put 'octave-block-offset 'safe-local-variable 'integerp)
+ :type 'integer
+ :safe #'integerp)
(defvar octave-block-comment-start
(concat (make-string 2 octave-comment-char) " ")
@@ -879,7 +879,8 @@ startup file, `~/.emacs-octave'."
(set-process-filter proc 'comint-output-filter)
;; Just in case, to be sure a cd in the startup file won't have
;; detrimental effects.
- (with-demoted-errors (inferior-octave-resync-dirs))
+ (with-demoted-errors "Octave resync error: %S"
+ (inferior-octave-resync-dirs))
;; Generate a proper prompt, which is critical to
;; `comint-history-isearch-backward-regexp'. Bug#14433.
(comint-send-string proc "\n")))
diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el
index 4ab9b4a9962..63399adf3ae 100644
--- a/lisp/progmodes/opascal.el
+++ b/lisp/progmodes/opascal.el
@@ -1641,10 +1641,10 @@ An error is raised if not in a comment."
(defun opascal-new-comment-line ()
"If in a // comment, do a newline, indented such that one is still in the
comment block. If not in a // comment, just does a normal newline."
- (interactive)
(declare
(obsolete "use comment-indent-new-line with comment-multi-line instead"
"27.1"))
+ (interactive)
(let ((comment (opascal-current-token)))
(if (not (eq 'comment-single-line (opascal-token-kind comment)))
;; Not in a // comment. Just do the normal newline.
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 8dc03b72b1e..8d3194e6a47 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -47,8 +47,8 @@
;; "reset" "rewrite" "write" "writeln")
;; pascal-separator-keywords '("downto" "else" "mod" "div" "then"))
-;; KNOWN BUGS / BUGREPORTS
-;; =======================
+;; KNOWN BUGS / BUG REPORTS
+;; ========================
;; As far as I know, there are no bugs in the current version of this
;; package. This may not be true however, since I never use this mode
;; myself and therefore would never notice them anyway. If you do
@@ -239,14 +239,6 @@ will do all lineups."
(const :tag "Declarations" declaration)
(const :tag "Case statements" case)))
-(defvar pascal-toggle-completions nil
- "If non-nil, `pascal-complete-word' tries all possible completions.
-Repeated use of \\[pascal-complete-word] then shows all
-completions in turn, instead of displaying a list of all possible
-completions.")
-(make-obsolete-variable 'pascal-toggle-completions
- 'completion-cycle-threshold "24.1")
-
(defcustom pascal-type-keywords
'("array" "file" "packed" "char" "integer" "real" "string" "record")
"Keywords for types used when completing a word in a declaration or parmlist.
@@ -1297,13 +1289,6 @@ indent of the current line in parameterlist."
(when (> e b)
(list b e #'pascal-completion))))
-(define-obsolete-function-alias 'pascal-complete-word
- 'completion-at-point "24.1")
-
-(define-obsolete-function-alias 'pascal-show-completions
- 'completion-help-at-point "24.1")
-
-
(defun pascal-get-default-symbol ()
"Return symbol around current point as a string."
(save-excursion
@@ -1382,8 +1367,6 @@ The default is a name found in the buffer around point."
;;;
(defvar pascal-outline-map
(let ((map (make-sparse-keymap)))
- (if (fboundp 'set-keymap-name)
- (set-keymap-name map 'pascal-outline-map))
(define-key map "\M-\C-a" 'pascal-outline-prev-defun)
(define-key map "\M-\C-e" 'pascal-outline-next-defun)
(define-key map "\C-c\C-d" 'pascal-outline-goto-defun)
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 120237b960e..6019840048a 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Version: 0.8.1
-;; Package-Requires: ((emacs "26.1") (xref "1.0.2"))
+;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
;; This is a GNU ELPA :core package. Avoid using functionality that
;; not compatible with the version of Emacs recorded above.
@@ -404,6 +404,12 @@ you might have to restart Emacs to see the effect."
:package-version '(project . "0.2.0")
:safe #'booleanp)
+(defcustom project-vc-include-untracked t
+ "When non-nil, the VC project backend includes untracked files."
+ :type 'boolean
+ :version "29.1"
+ :safe #'booleanp)
+
;; FIXME: Using the current approach, major modes are supposed to set
;; this variable to a buffer-local value. So we don't have access to
;; the "external roots" of language A from buffers of language B, which
@@ -440,30 +446,33 @@ The directory names should be absolute. Used in the VC project
backend implementation of `project-external-roots'.")
(defun project-try-vc (dir)
- (let* ((backend
- ;; FIXME: This is slow. Cache it.
- (ignore-errors (vc-responsible-backend dir)))
- (root
- (pcase backend
- ('Git
- ;; Don't stop at submodule boundary.
- ;; FIXME: Cache for a shorter time.
- (or (vc-file-getprop dir 'project-git-root)
- (let ((root (vc-call-backend backend 'root dir)))
- (vc-file-setprop
- dir 'project-git-root
- (if (and
- ;; FIXME: Invalidate the cache when the value
- ;; of this variable changes.
- (project--vc-merge-submodules-p root)
- (project--submodule-p root))
- (let* ((parent (file-name-directory
- (directory-file-name root))))
- (vc-call-backend backend 'root parent))
- root)))))
- ('nil nil)
- (_ (ignore-errors (vc-call-backend backend 'root dir))))))
- (and root (cons 'vc root))))
+ (or (vc-file-getprop dir 'project-vc)
+ (let* ((backend (ignore-errors (vc-responsible-backend dir)))
+ (root
+ (pcase backend
+ ('Git
+ ;; Don't stop at submodule boundary.
+ (or (vc-file-getprop dir 'project-git-root)
+ (let ((root (vc-call-backend backend 'root dir)))
+ (vc-file-setprop
+ dir 'project-git-root
+ (if (and
+ ;; FIXME: Invalidate the cache when the value
+ ;; of this variable changes.
+ (project--vc-merge-submodules-p root)
+ (project--submodule-p root))
+ (let* ((parent (file-name-directory
+ (directory-file-name root))))
+ (vc-call-backend backend 'root parent))
+ root)))))
+ ('nil nil)
+ (_ (ignore-errors (vc-call-backend backend 'root dir)))))
+ project)
+ (when root
+ (setq project (list 'vc backend root))
+ ;; FIXME: Cache for a shorter time.
+ (vc-file-setprop dir 'project-vc project)
+ project))))
(defun project--submodule-p (root)
;; XXX: We only support Git submodules for now.
@@ -489,7 +498,7 @@ backend implementation of `project-external-roots'.")
(t nil))))
(cl-defmethod project-root ((project (head vc)))
- (cdr project))
+ (nth 2 project))
(cl-defmethod project-external-roots ((project (head vc)))
(project-subtract-directories
@@ -556,7 +565,8 @@ backend implementation of `project-external-roots'.")
files)
;; Include unregistered.
(setq args (append args
- '("-c" "-o")
+ '("-c")
+ (and project-vc-include-untracked '("-o"))
(unless no-gitignore '("--exclude-standard"))))
(when (or files extra-ignores)
(setq args (append args
@@ -591,9 +601,9 @@ backend implementation of `project-external-roots'.")
(delete-consecutive-dups files)))
(`Hg
(let ((default-directory (expand-file-name (file-name-as-directory dir)))
- args)
- ;; Include unregistered.
- (setq args (nconc args '("-mcardu" "--no-status" "-0")))
+ (args (list (concat "-mcard" (and project-vc-include-untracked "u"))
+ "--no-status"
+ "-0")))
(when extra-ignores
(setq args (nconc args
(mapcan
@@ -618,17 +628,17 @@ backend implementation of `project-external-roots'.")
(insert-file-contents ".gitmodules")
(let (res)
(goto-char (point-min))
- (while (re-search-forward "path *= *\\(.+\\)" nil t)
+ (while (re-search-forward "^[ \t]*path *= *\\(.+\\)" nil t)
(push (match-string 1) res))
(nreverse res)))
(file-missing nil)))
(cl-defmethod project-ignores ((project (head vc)) dir)
- (let* ((root (cdr project))
+ (let* ((root (nth 2 project))
backend)
(append
(when (file-equal-p dir root)
- (setq backend (vc-responsible-backend root))
+ (setq backend (cadr project))
(delq
nil
(mapcar
@@ -805,7 +815,6 @@ The following commands are available:
(define-key tab-prefix-map "p" #'project-other-tab-command))
(declare-function grep-read-files "grep")
-(declare-function xref--show-xrefs "xref")
(declare-function xref--find-ignores-arguments "xref")
;;;###autoload
@@ -831,7 +840,7 @@ requires quoting, e.g. `\\[quoted-insert]<space>'."
(project--files-in-directory dir
nil
(grep-read-files regexp))))))
- (xref--show-xrefs
+ (xref-show-xrefs
(apply-partially #'project--find-regexp-in-files regexp files)
nil)))
@@ -859,7 +868,7 @@ pattern to search for."
(project-files pr (cons
(project-root pr)
(project-external-roots pr)))))
- (xref--show-xrefs
+ (xref-show-xrefs
(apply-partially #'project--find-regexp-in-files regexp files)
nil)))
@@ -890,8 +899,12 @@ interactively, include all files under the project root, except
for VCS directories listed in `vc-directory-exclusion-list'."
(interactive "P")
(let* ((pr (project-current t))
- (dirs (list (project-root pr))))
- (project-find-file-in (thing-at-point 'filename) dirs pr include-all)))
+ (root (project-root pr))
+ (dirs (list root)))
+ (project-find-file-in
+ (or (thing-at-point 'filename)
+ (and buffer-file-name (file-relative-name buffer-file-name root)))
+ dirs pr include-all)))
;;;###autoload
(defun project-or-external-find-file (&optional include-all)
@@ -982,7 +995,7 @@ directories listed in `vc-directory-exclusion-list'."
(project-files project dirs)))
(completion-ignore-case read-file-name-completion-ignore-case)
(file (funcall project-read-file-name-function
- "Find file" all-files nil nil
+ "Find file" all-files nil 'file-name-history
suggested-filename)))
(if (string= file "")
(user-error "You didn't specify the file")
@@ -1019,7 +1032,7 @@ directories listed in `vc-directory-exclusion-list'."
"Dired"
;; Some completion UIs show duplicates.
(delete-dups all-dirs)
- nil nil)))
+ nil 'file-name-history)))
(dired dir)))
;;;###autoload
@@ -1034,6 +1047,8 @@ directories listed in `vc-directory-exclusion-list'."
(interactive)
(vc-dir (project-root (project-current t))))
+(declare-function comint-check-proc "comint")
+
;;;###autoload
(defun project-shell ()
"Start an inferior shell in the current project's root directory.
@@ -1042,11 +1057,14 @@ switch to it. Otherwise, create a new shell buffer.
With \\[universal-argument] prefix arg, create a new inferior shell buffer even
if one already exists."
(interactive)
+ (require 'comint)
(let* ((default-directory (project-root (project-current t)))
(default-project-shell-name (project-prefixed-buffer-name "shell"))
(shell-buffer (get-buffer default-project-shell-name)))
(if (and shell-buffer (not current-prefix-arg))
- (pop-to-buffer shell-buffer display-comint-buffer-action)
+ (if (comint-check-proc shell-buffer)
+ (pop-to-buffer shell-buffer (bound-and-true-p display-comint-buffer-action))
+ (shell shell-buffer))
(shell (generate-new-buffer-name default-project-shell-name)))))
;;;###autoload
@@ -1062,7 +1080,7 @@ if one already exists."
(eshell-buffer-name (project-prefixed-buffer-name "eshell"))
(eshell-buffer (get-buffer eshell-buffer-name)))
(if (and eshell-buffer (not current-prefix-arg))
- (pop-to-buffer eshell-buffer display-comint-buffer-action)
+ (pop-to-buffer eshell-buffer (bound-and-true-p display-comint-buffer-action))
(eshell t))))
;;;###autoload
@@ -1098,14 +1116,24 @@ command \\[fileloop-continue]."
(defun project-query-replace-regexp (from to)
"Query-replace REGEXP in all the files of the project.
Stops when a match is found and prompts for whether to replace it.
+At that prompt, the user must type a character saying what to do
+with the match. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
If you exit the `query-replace', you can later continue the
`query-replace' loop using the command \\[fileloop-continue]."
(interactive
- (pcase-let ((`(,from ,to)
- (query-replace-read-args "Query replace (regexp)" t t)))
- (list from to)))
+ (let ((query-replace-read-from-regexp-default 'find-tag-default-as-regexp))
+ (pcase-let ((`(,from ,to)
+ (query-replace-read-args "Query replace (regexp)" t t)))
+ (list from to))))
(fileloop-initialize-replace
- from to (project-files (project-current t)) 'default)
+ from to
+ ;; XXX: Filter out Git submodules, which are not regular files.
+ ;; `project-files' can return those, which is arguably suboptimal,
+ ;; but removing them eagerly has performance cost.
+ (cl-delete-if-not #'file-regular-p (project-files (project-current t)))
+ 'default)
(fileloop-continue))
(defvar compilation-read-command)
@@ -1141,6 +1169,29 @@ If non-nil, it overrides `compilation-buffer-name-function' for
compilation-buffer-name-function)))
(call-interactively #'compile)))
+(defcustom project-ignore-buffer-conditions nil
+ "List of conditions to filter the buffers to be switched to.
+If any of these conditions are satisfied for a buffer in the
+current project, `project-switch-to-buffer',
+`project-display-buffer' and `project-display-buffer-other-frame'
+ignore it.
+See the doc string of `project-kill-buffer-conditions' for the
+general form of conditions."
+ :type '(repeat (choice regexp function symbol
+ (cons :tag "Major mode"
+ (const major-mode) symbol)
+ (cons :tag "Derived mode"
+ (const derived-mode) symbol)
+ (cons :tag "Negation"
+ (const not) sexp)
+ (cons :tag "Conjunction"
+ (const and) sexp)
+ (cons :tag "Disjunction"
+ (const or) sexp)))
+ :version "29.1"
+ :group 'project
+ :package-version '(project . "0.8.2"))
+
(defun project--read-project-buffer ()
(let* ((pr (project-current t))
(current-buffer (current-buffer))
@@ -1150,7 +1201,10 @@ If non-nil, it overrides `compilation-buffer-name-function' for
(predicate
(lambda (buffer)
;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist.
- (memq (cdr buffer) buffers))))
+ (and (memq (cdr buffer) buffers)
+ (not
+ (project--buffer-check
+ (cdr buffer) project-ignore-buffer-conditions))))))
(read-buffer
"Switch to buffer: "
(when (funcall predicate (cons other-name other-buffer))
@@ -1217,10 +1271,9 @@ Each condition is either:
- a cons-cell, where the car describes how to interpret the cdr.
The car can be one of the following:
* `major-mode': the buffer is killed if the buffer's major
- mode is eq to the cons-cell's cdr
+ mode is eq to the cons-cell's cdr.
* `derived-mode': the buffer is killed if the buffer's major
- mode is derived from the major mode denoted by the cons-cell's
- cdr
+ mode is derived from the major mode in the cons-cell's cdr.
* `not': the cdr is interpreted as a negation of a condition.
* `and': the cdr is a list of recursive conditions, that all have
to be met.
@@ -1268,16 +1321,17 @@ Used by `project-kill-buffers'."
(push buf bufs)))
(nreverse bufs)))
-(defun project--kill-buffer-check (buf conditions)
+(defun project--buffer-check (buf conditions)
"Check if buffer BUF matches any element of the list CONDITIONS.
-See `project-kill-buffer-conditions' for more details on the form
-of CONDITIONS."
- (catch 'kill
+See `project-kill-buffer-conditions' or
+`project-ignore-buffer-conditions' for more details on the
+form of CONDITIONS."
+ (catch 'match
(dolist (c conditions)
(when (cond
((stringp c)
(string-match-p c (buffer-name buf)))
- ((symbolp c)
+ ((functionp c)
(funcall c buf))
((eq (car-safe c) 'major-mode)
(eq (buffer-local-value 'major-mode buf)
@@ -1287,15 +1341,15 @@ of CONDITIONS."
(buffer-local-value 'major-mode buf)
(cdr c)))
((eq (car-safe c) 'not)
- (not (project--kill-buffer-check buf (cdr c))))
+ (not (project--buffer-check buf (cdr c))))
((eq (car-safe c) 'or)
- (project--kill-buffer-check buf (cdr c)))
+ (project--buffer-check buf (cdr c)))
((eq (car-safe c) 'and)
(seq-every-p
- (apply-partially #'project--kill-buffer-check
+ (apply-partially #'project--buffer-check
buf)
(mapcar #'list (cdr c)))))
- (throw 'kill t)))))
+ (throw 'match t)))))
(defun project--buffers-to-kill (pr)
"Return list of buffers in project PR to kill.
@@ -1303,7 +1357,7 @@ What buffers should or should not be killed is described
in `project-kill-buffer-conditions'."
(let (bufs)
(dolist (buf (project-buffers pr))
- (when (project--kill-buffer-check buf project-kill-buffer-conditions)
+ (when (project--buffer-check buf project-kill-buffer-conditions)
(push buf bufs)))
bufs))
@@ -1316,7 +1370,9 @@ identical. Only the buffers that match a condition in
`project-kill-buffer-conditions' will be killed. If NO-CONFIRM
is non-nil, the command will not ask the user for confirmation.
NO-CONFIRM is always nil when the command is invoked
-interactively."
+interactively.
+
+Also see the `project-kill-buffers-display-buffer-list' variable."
(interactive)
(let* ((pr (project-current t))
(bufs (project--buffers-to-kill pr))
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 8382c4bd099..5aba95d4c79 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -742,14 +742,6 @@ Relevant only when `prolog-imenu-flag' is non-nil."
:group 'prolog-other
:type 'boolean)
-(defcustom prolog-char-quote-workaround nil
- "If non-nil, declare 0 as a quote character to handle 0'<char>.
-This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
- :version "24.1"
- :group 'prolog-other
- :type 'boolean)
-(make-obsolete-variable 'prolog-char-quote-workaround nil "24.1")
-
;;-------------------------------------------------------------------
;; Internal variables
@@ -1303,7 +1295,7 @@ To find out what version of Prolog mode you are running, enter
(t t)))
;; This statement was missing in Emacs 24.1, 24.2, 24.3.
-(define-obsolete-function-alias 'switch-to-prolog 'run-prolog "24.1")
+(define-obsolete-function-alias 'switch-to-prolog 'run-prolog "24.1") ; "24.4" ; for grep
;;;###autoload
(defun run-prolog (arg)
"Run an inferior Prolog process, input and output via buffer *prolog*.
@@ -1355,8 +1347,6 @@ the variable `prolog-prompt-regexp'."
(error "This Prolog system has defined no interpreter"))
(unless (comint-check-proc "*prolog*")
(with-current-buffer (get-buffer-create "*prolog*")
- (prolog-inferior-mode)
-
;; The "INFERIOR=yes" hack is for SWI-Prolog 7.2.3 and earlier,
;; which assumes it is running under Emacs if either INFERIOR=yes or
;; if EMACS is set to a nonempty value. The EMACS setting is
@@ -1369,6 +1359,7 @@ the variable `prolog-prompt-regexp'."
(cons "INFERIOR=yes" process-environment))))
(apply 'make-comint-in-buffer "prolog" (current-buffer)
pname nil pswitches))
+ (prolog-inferior-mode)
(unless prolog-system
;; Setup auto-detection.
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index edd3139a7aa..1c99937c4b9 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -92,7 +92,7 @@
;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7.
;; See URL `https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To
;; avoid this, the `python-shell-unbuffered' defaults to non-nil and
-;; controls whether `python-shell-calculate-process-environment'
+;; controls whether `python-shell--calculate-process-environment'
;; should set the "PYTHONUNBUFFERED" environment variable on startup:
;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
@@ -149,7 +149,7 @@
;; (setq python-shell-process-environment
;; (list
;; (format "PATH=%s" (mapconcat
-;; 'identity
+;; #'identity
;; (reverse
;; (cons (getenv "PATH")
;; '("/path/to/env/bin/")))
@@ -245,10 +245,9 @@
(require 'ansi-color)
(require 'cl-lib)
(require 'comint)
-(require 'tramp-sh)
+(eval-when-compile (require 'subr-x)) ;For `string-empty-p'.
;; Avoid compiler warnings
-(defvar view-return-to-alist)
(defvar compilation-error-regexp-alist)
(defvar outline-heading-end-regexp)
@@ -273,39 +272,39 @@
(defvar python-mode-map
(let ((map (make-sparse-keymap)))
;; Movement
- (define-key map [remap backward-sentence] 'python-nav-backward-block)
- (define-key map [remap forward-sentence] 'python-nav-forward-block)
- (define-key map [remap backward-up-list] 'python-nav-backward-up-list)
- (define-key map [remap mark-defun] 'python-mark-defun)
- (define-key map "\C-c\C-j" 'imenu)
+ (define-key map [remap backward-sentence] #'python-nav-backward-block)
+ (define-key map [remap forward-sentence] #'python-nav-forward-block)
+ (define-key map [remap backward-up-list] #'python-nav-backward-up-list)
+ (define-key map [remap mark-defun] #'python-mark-defun)
+ (define-key map "\C-c\C-j" #'imenu)
;; Indent specific
- (define-key map "\177" 'python-indent-dedent-line-backspace)
- (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
- (define-key map "\C-c<" 'python-indent-shift-left)
- (define-key map "\C-c>" 'python-indent-shift-right)
+ (define-key map "\177" #'python-indent-dedent-line-backspace)
+ (define-key map (kbd "<backtab>") #'python-indent-dedent-line)
+ (define-key map "\C-c<" #'python-indent-shift-left)
+ (define-key map "\C-c>" #'python-indent-shift-right)
;; Skeletons
- (define-key map "\C-c\C-tc" 'python-skeleton-class)
- (define-key map "\C-c\C-td" 'python-skeleton-def)
- (define-key map "\C-c\C-tf" 'python-skeleton-for)
- (define-key map "\C-c\C-ti" 'python-skeleton-if)
- (define-key map "\C-c\C-tm" 'python-skeleton-import)
- (define-key map "\C-c\C-tt" 'python-skeleton-try)
- (define-key map "\C-c\C-tw" 'python-skeleton-while)
+ (define-key map "\C-c\C-tc" #'python-skeleton-class)
+ (define-key map "\C-c\C-td" #'python-skeleton-def)
+ (define-key map "\C-c\C-tf" #'python-skeleton-for)
+ (define-key map "\C-c\C-ti" #'python-skeleton-if)
+ (define-key map "\C-c\C-tm" #'python-skeleton-import)
+ (define-key map "\C-c\C-tt" #'python-skeleton-try)
+ (define-key map "\C-c\C-tw" #'python-skeleton-while)
;; Shell interaction
- (define-key map "\C-c\C-p" 'run-python)
- (define-key map "\C-c\C-s" 'python-shell-send-string)
- (define-key map "\C-c\C-e" 'python-shell-send-statement)
- (define-key map "\C-c\C-r" 'python-shell-send-region)
- (define-key map "\C-\M-x" 'python-shell-send-defun)
- (define-key map "\C-c\C-c" 'python-shell-send-buffer)
- (define-key map "\C-c\C-l" 'python-shell-send-file)
- (define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
+ (define-key map "\C-c\C-p" #'run-python)
+ (define-key map "\C-c\C-s" #'python-shell-send-string)
+ (define-key map "\C-c\C-e" #'python-shell-send-statement)
+ (define-key map "\C-c\C-r" #'python-shell-send-region)
+ (define-key map "\C-\M-x" #'python-shell-send-defun)
+ (define-key map "\C-c\C-c" #'python-shell-send-buffer)
+ (define-key map "\C-c\C-l" #'python-shell-send-file)
+ (define-key map "\C-c\C-z" #'python-shell-switch-to-shell)
;; Some util commands
- (define-key map "\C-c\C-v" 'python-check)
- (define-key map "\C-c\C-f" 'python-eldoc-at-point)
- (define-key map "\C-c\C-d" 'python-describe-at-point)
+ (define-key map "\C-c\C-v" #'python-check)
+ (define-key map "\C-c\C-f" #'python-eldoc-at-point)
+ (define-key map "\C-c\C-d" #'python-describe-at-point)
;; Utilities
- (substitute-key-definition 'complete-symbol 'completion-at-point
+ (substitute-key-definition #'complete-symbol #'completion-at-point
map global-map)
(easy-menu-define python-menu map "Python Mode menu"
'("Python"
@@ -359,9 +358,12 @@
(defmacro python-rx (&rest regexps)
"Python mode specialized rx macro.
This variant of `rx' supports common Python named REGEXPS."
- `(rx-let ((block-start (seq symbol-start
+ `(rx-let ((sp-bsnl (or space (and ?\\ ?\n)))
+ (block-start (seq symbol-start
(or "def" "class" "if" "elif" "else" "try"
"except" "finally" "for" "while" "with"
+ ;; Python 3.10+ PEP634
+ "match" "case"
;; Python 3.5+ PEP492
(and "async" (+ space)
(or "def" "for" "with")))
@@ -394,7 +396,7 @@ This variant of `rx' supports common Python named REGEXPS."
(open-paren (or "{" "[" "("))
(close-paren (or "}" "]" ")"))
(simple-operator (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))
- (not-simple-operator (not simple-operator))
+ (not-simple-operator (not (or simple-operator ?\n)))
(operator (or "==" ">=" "is" "not"
"**" "//" "<<" ">>" "<=" "!="
"+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
@@ -538,9 +540,9 @@ the {...} holes that appear within f-strings."
(setq ppss (syntax-ppss))))))
(defvar python-font-lock-keywords-level-1
- `((,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
+ `((,(python-rx symbol-start "def" (1+ space) (group symbol-name))
(1 font-lock-function-name-face))
- (,(rx symbol-start "class" (1+ space) (group (1+ (or word ?_))))
+ (,(python-rx symbol-start "class" (1+ space) (group symbol-name))
(1 font-lock-type-face)))
"Font lock keywords to use in `python-mode' for level 1 decoration.
@@ -563,6 +565,8 @@ class declarations.")
;; Python 3.5+ PEP492
(and "async" (+ space) (or "def" "for" "with"))
"await"
+ ;; Python 3.10+
+ "match" "case"
;; Extra:
"self")
symbol-end)
@@ -601,15 +605,18 @@ builtins.")
(defun python-font-lock-assignment-matcher (regexp)
"Font lock matcher for assignments based on REGEXP.
-Return nil if REGEXP matched within a `paren' context (to avoid,
-e.g., default values for arguments or passing arguments by name
-being treated as assignments) or is followed by an '=' sign (to
-avoid '==' being treated as an assignment."
+Search for next occurrence if REGEXP matched within a `paren'
+context (to avoid, e.g., default values for arguments or passing
+arguments by name being treated as assignments) or is followed by
+an '=' sign (to avoid '==' being treated as an assignment. Set
+point to the position one character before the end of the
+occurrence found so that subsequent searches can detect the '='
+sign in chained assignment."
(lambda (limit)
- (let ((res (re-search-forward regexp limit t)))
- (unless (or (python-syntax-context 'paren)
- (equal (char-after (point)) ?=))
- res))))
+ (cl-loop while (re-search-forward regexp limit t)
+ unless (or (python-syntax-context 'paren)
+ (equal (char-after) ?=))
+ return (progn (backward-char) t))))
(defvar python-font-lock-keywords-maximum-decoration
`((python--font-lock-f-strings)
@@ -671,7 +678,7 @@ avoid '==' being treated as an assignment."
;; and variants thereof
;; the cases
;; (a) = 5
- ;; [a] = 5
+ ;; [a] = 5,
;; [*a] = 5, 6
;; are handled separately below
(,(python-font-lock-assignment-matcher
@@ -701,10 +708,11 @@ avoid '==' being treated as an assignment."
(1 font-lock-variable-name-face))
;; special cases
;; (a) = 5
- ;; [a] = 5
+ ;; [a] = 5,
;; [*a] = 5, 6
(,(python-font-lock-assignment-matcher
- (python-rx (or "[" "(") (* space)
+ (python-rx (or line-start ?\; ?=) (* space)
+ (or "[" "(") (* space)
grouped-assignment-target (* space)
(or ")" "]") (* space)
assignment-operator))
@@ -825,7 +833,6 @@ It makes underscores and dots word constituent chars.")
(defcustom python-indent-offset 4
"Default indentation offset for Python."
- :group 'python
:type 'integer
:safe 'integerp)
@@ -835,21 +842,18 @@ It makes underscores and dots word constituent chars.")
(defcustom python-indent-guess-indent-offset t
"Non-nil tells Python mode to guess `python-indent-offset' value."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-indent-guess-indent-offset-verbose t
"Non-nil means to emit a warning when indentation guessing fails."
:version "25.1"
:type 'boolean
- :group 'python
:safe' booleanp)
(defcustom python-indent-trigger-commands
'(indent-for-tab-command yas-expand yas/expand)
"Commands that might trigger a `python-indent-line' call."
- :type '(repeat symbol)
- :group 'python)
+ :type '(repeat symbol))
(defcustom python-indent-def-block-scale 2
"Multiplier applied to indentation inside multi-line def blocks."
@@ -1298,7 +1302,7 @@ Called from a program, START and END specify the region to indent."
;; Don't mess with strings, unless it's the
;; enclosing set of quotes or a docstring.
(or (not (python-syntax-context 'string))
- (eq
+ (equal
(syntax-after
(+ (1- (point))
(current-indentation)
@@ -1435,7 +1439,7 @@ marks the next defun after the ones already marked."
function))
(defvar python-nav-beginning-of-defun-regexp
- (python-rx line-start (* space) defun (+ space) (group symbol-name))
+ (python-rx line-start (* space) defun (+ sp-bsnl) (group symbol-name))
"Regexp matching class or function definition.
The name of the defun should be grouped so it can be retrieved
via `match-string'.")
@@ -1450,26 +1454,34 @@ With positive ARG search backwards, else search forwards."
(line-beg-pos (line-beginning-position))
(line-content-start (+ line-beg-pos (current-indentation)))
(pos (point-marker))
+ (min-indentation (+ (current-indentation)
+ (if (python-info-looking-at-beginning-of-defun)
+ python-indent-offset 0)))
(body-indentation
(and (> arg 0)
(save-excursion
(while (and
- (not (python-info-looking-at-beginning-of-defun))
+ (or (not (python-info-looking-at-beginning-of-defun))
+ (>= (current-indentation) min-indentation))
+ (setq min-indentation
+ (min min-indentation (current-indentation)))
(python-nav-backward-block)))
(or (and (python-info-looking-at-beginning-of-defun)
(+ (current-indentation) python-indent-offset))
0))))
(found
(progn
- (when (and (python-info-looking-at-beginning-of-defun)
+ (when (and (python-info-looking-at-beginning-of-defun nil t)
(or (< arg 0)
;; If looking at beginning of defun, and if
;; pos is > line-content-start, ensure a
;; backward re search match this defun by
;; going to end of line before calling
;; re-search-fn bug#40563
- (and (> arg 0) (> pos line-content-start))))
- (end-of-line 1))
+ (and (> arg 0)
+ (or (python-info-continuation-line-p)
+ (> pos line-content-start)))))
+ (python-nav-end-of-statement))
(while (and (funcall re-search-fn
python-nav-beginning-of-defun-regexp nil t)
@@ -1479,14 +1491,18 @@ With positive ARG search backwards, else search forwards."
(and (> arg 0)
(not (= (current-indentation) 0))
(>= (current-indentation) body-indentation)))))
- (and (python-info-looking-at-beginning-of-defun)
+ (and (python-info-looking-at-beginning-of-defun nil t)
(or (not (= (line-number-at-pos pos)
(line-number-at-pos)))
(and (>= (point) line-beg-pos)
(<= (point) line-content-start)
(> pos line-content-start)))))))
(if found
- (or (beginning-of-line 1) t)
+ (progn
+ (when (< arg 0)
+ (python-nav-beginning-of-statement))
+ (beginning-of-line 1)
+ t)
(and (goto-char pos) nil))))
(defun python-nav-beginning-of-defun (&optional arg)
@@ -1625,28 +1641,29 @@ of the statement."
(while (and (or noend (goto-char (line-end-position)))
(not (eobp))
(cond ((setq string-start (python-syntax-context 'string))
- ;; The assertion can only fail if syntax table
+ ;; The condition can be nil if syntax table
;; text properties and the `syntax-ppss' cache
;; are somehow out of whack. This has been
;; observed when using `syntax-ppss' during
;; narrowing.
- (cl-assert (>= string-start last-string-end)
- :show-args
- "\
-Overlapping strings detected (start=%d, last-end=%d)")
- (goto-char string-start)
- (if (python-syntax-context 'paren)
- ;; Ended up inside a paren, roll again.
- (python-nav-end-of-statement t)
- ;; This is not inside a paren, move to the
- ;; end of this string.
- (goto-char (+ (point)
- (python-syntax-count-quotes
- (char-after (point)) (point))))
- (setq last-string-end
- (or (re-search-forward
- (rx (syntax string-delimiter)) nil t)
- (goto-char (point-max))))))
+ ;; It can also fail in cases where the buffer is in
+ ;; the process of being modified, e.g. when creating
+ ;; a string with `electric-pair-mode' disabled such
+ ;; that there can be an unmatched single quote
+ (when (>= string-start last-string-end)
+ (goto-char string-start)
+ (if (python-syntax-context 'paren)
+ ;; Ended up inside a paren, roll again.
+ (python-nav-end-of-statement t)
+ ;; This is not inside a paren, move to the
+ ;; end of this string.
+ (goto-char (+ (point)
+ (python-syntax-count-quotes
+ (char-after (point)) (point))))
+ (setq last-string-end
+ (or (re-search-forward
+ (rx (syntax string-delimiter)) nil t)
+ (goto-char (point-max)))))))
((python-syntax-context 'paren)
;; The statement won't end before we've escaped
;; at least one level of parenthesis.
@@ -1715,7 +1732,10 @@ backward to previous statement."
(while (and (forward-line 1)
(not (eobp))
(or (and (> (current-indentation) block-indentation)
- (or (python-nav-end-of-statement) t))
+ (let ((start (point)))
+ (python-nav-end-of-statement)
+ ;; must move forward otherwise infinite loop
+ (> (point) start)))
(python-info-current-line-comment-p)
(python-info-current-line-empty-p))))
(python-util-forward-comment -1)
@@ -2031,7 +2051,6 @@ position, else returns nil."
(defcustom python-shell-buffer-name "Python"
"Default buffer name for Python interpreter."
:type 'string
- :group 'python
:safe 'stringp)
(defcustom python-shell-interpreter
@@ -2045,19 +2064,16 @@ Some Python interpreters also require changes to
`python-shell-interpreter' to \"ipython3\" requires setting
`python-shell-interpreter-args' to \"--simple-prompt\"."
:version "28.1"
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-shell-internal-buffer-name "Python Internal"
"Default buffer name for the Internal Python interpreter."
:type 'string
- :group 'python
:safe 'stringp)
(defcustom python-shell-interpreter-args "-i"
"Default arguments for the Python interpreter."
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-shell-interpreter-interactive-arg "-i"
"Interpreter argument to force it to run interactively."
@@ -2122,7 +2138,6 @@ It should not contain a caret (^) at the beginning."
"Should syntax highlighting be enabled in the Python shell buffer?
Restart the Python shell after changing this variable for it to take effect."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-shell-unbuffered t
@@ -2130,7 +2145,6 @@ Restart the Python shell after changing this variable for it to take effect."
When non-nil, this may prevent delayed and missing output in the
Python shell. See commentary for details."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-shell-process-environment nil
@@ -2140,8 +2154,7 @@ When this variable is non-nil, values are exported into the
process environment before starting it. Any variables already
present in the current environment are superseded by variables
set here."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-extra-pythonpaths nil
"List of extra pythonpaths for Python shell.
@@ -2150,8 +2163,7 @@ the PYTHONPATH before starting processes. Any values present
here that already exists in PYTHONPATH are moved to the beginning
of the list so that they are prioritized when looking for
modules."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-exec-path nil
"List of paths for searching executables.
@@ -2159,8 +2171,7 @@ When this variable is non-nil, values added at the beginning of
the PATH before starting processes. Any values present here that
already exists in PATH are moved to the beginning of the list so
that they are prioritized when looking for executables."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-remote-exec-path nil
"List of paths to be ensured remotely for searching executables.
@@ -2171,8 +2182,7 @@ here. Normally you won't use this variable directly unless you
plan to ensure a particular set of paths to all Python shell
executed through tramp connections."
:version "25.1"
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(define-obsolete-variable-alias
'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1")
@@ -2182,13 +2192,11 @@ executed through tramp connections."
This variable, when set to a string, makes the environment to be
modified such that shells are started within the specified
virtualenv."
- :type '(choice (const nil) directory)
- :group 'python)
+ :type '(choice (const nil) directory))
(defcustom python-shell-setup-codes nil
"List of code run by `python-shell-send-setup-code'."
- :type '(repeat symbol)
- :group 'python)
+ :type '(repeat symbol))
(defcustom python-shell-compilation-regexp-alist
`((,(rx line-start (1+ (any " \t")) "File \""
@@ -2202,8 +2210,7 @@ virtualenv."
"(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
1 2))
"`compilation-error-regexp-alist' for inferior Python."
- :type '(alist regexp)
- :group 'python)
+ :type '(alist regexp))
(defvar python-shell-output-filter-in-progress nil)
(defvar python-shell-output-filter-buffer nil)
@@ -2221,33 +2228,34 @@ virtualenv."
(or (getenv "PYTHONPATH") "") path-separator 'omit)))
(python-shell--add-to-path-with-priority
pythonpath python-shell-extra-pythonpaths)
- (mapconcat 'identity pythonpath path-separator)))
+ (mapconcat #'identity pythonpath path-separator)))
(defun python-shell-calculate-process-environment ()
- "Calculate `process-environment' or `tramp-remote-process-environment'.
+ (declare (obsolete python-shell--calculate-process-environment "29.1"))
+ (defvar tramp-remote-process-environment)
+ (let* ((remote-p (file-remote-p default-directory)))
+ (append (python-shell--calculate-process-environment)
+ (if remote-p
+ tramp-remote-process-environment
+ process-environment))))
+
+(defun python-shell--calculate-process-environment ()
+ "Return a list of entries to add to the `process-environment'.
Prepends `python-shell-process-environment', sets extra
pythonpaths from `python-shell-extra-pythonpaths' and sets a few
-virtualenv related vars. If `default-directory' points to a
-remote host, the returned value is intended for
-`tramp-remote-process-environment'."
- (let* ((remote-p (file-remote-p default-directory))
- (process-environment (if remote-p
- tramp-remote-process-environment
- process-environment))
- (virtualenv (when python-shell-virtualenv-root
- (directory-file-name python-shell-virtualenv-root))))
- (dolist (env python-shell-process-environment)
- (pcase-let ((`(,key ,value) (split-string env "=")))
- (setenv key value)))
+virtualenv related vars."
+ (let* ((virtualenv (when python-shell-virtualenv-root
+ (directory-file-name python-shell-virtualenv-root)))
+ (res python-shell-process-environment))
(when python-shell-unbuffered
- (setenv "PYTHONUNBUFFERED" "1"))
+ (push "PYTHONUNBUFFERED=1" res))
(when python-shell-extra-pythonpaths
- (setenv "PYTHONPATH" (python-shell-calculate-pythonpath)))
+ (push (concat "PYTHONPATH=" (python-shell-calculate-pythonpath)) res))
(if (not virtualenv)
- process-environment
- (setenv "PYTHONHOME" nil)
- (setenv "VIRTUAL_ENV" virtualenv))
- process-environment))
+ nil
+ (push "PYTHONHOME" res)
+ (push (concat "VIRTUAL_ENV=" virtualenv) res))
+ res))
(defun python-shell-calculate-exec-path ()
"Calculate `exec-path'.
@@ -2275,14 +2283,26 @@ of `exec-path'."
(defun python-shell-tramp-refresh-remote-path (vec paths)
"Update VEC's remote-path giving PATHS priority."
+ (cl-assert (featurep 'tramp))
+ (declare-function tramp-set-remote-path "tramp-sh")
+ (declare-function tramp-set-connection-property "tramp-cache")
+ (declare-function tramp-get-connection-property "tramp-cache")
(let ((remote-path (tramp-get-connection-property vec "remote-path" nil)))
(when remote-path
+ ;; FIXME: This part of the Tramp code still knows about Python!
(python-shell--add-to-path-with-priority remote-path paths)
(tramp-set-connection-property vec "remote-path" remote-path)
(tramp-set-remote-path vec))))
+
(defun python-shell-tramp-refresh-process-environment (vec env)
"Update VEC's process environment with ENV."
+ (cl-assert (featurep 'tramp))
+ (defvar tramp-end-of-heredoc)
+ (defvar tramp-end-of-output)
+ ;; Do we even know that `tramp-sh' is loaded at this point?
+ ;; What about files accessed via FTP, sudo, ...?
+ (declare-function tramp-send-command "tramp-sh")
;; Stolen from `tramp-open-connection-setup-interactive-shell'.
(let ((env (append (when (fboundp 'tramp-get-remote-locale)
;; Emacs<24.4 compat.
@@ -2295,7 +2315,7 @@ of `exec-path'."
unset vars item)
(while env
(setq item (split-string (car env) "=" 'omit))
- (setcdr item (mapconcat 'identity (cdr item) "="))
+ (setcdr item (mapconcat #'identity (cdr item) "="))
(if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
(push (format "%s %s" (car item) (cdr item)) vars)
(push (car item) unset))
@@ -2305,12 +2325,12 @@ of `exec-path'."
vec
(format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s"
tramp-end-of-heredoc
- (mapconcat 'identity vars "\n")
+ (mapconcat #'identity vars "\n")
tramp-end-of-heredoc)
t))
(when unset
(tramp-send-command
- vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
+ vec (format "unset %s" (mapconcat #'identity unset " ")) t))))
(defmacro python-shell-with-environment (&rest body)
"Modify shell environment during execution of BODY.
@@ -2319,41 +2339,49 @@ execution of body. If `default-directory' points to a remote
machine then modifies `tramp-remote-process-environment' and
`python-shell-remote-exec-path' instead."
(declare (indent 0) (debug (body)))
- (let ((vec (make-symbol "vec")))
- `(progn
- (let* ((,vec
- (when (file-remote-p default-directory)
- (ignore-errors
- (tramp-dissect-file-name default-directory 'noexpand))))
- (process-environment
- (if ,vec
- process-environment
- (python-shell-calculate-process-environment)))
- (exec-path
- (if ,vec
- exec-path
- (python-shell-calculate-exec-path)))
- (tramp-remote-process-environment
- (if ,vec
- (python-shell-calculate-process-environment)
- tramp-remote-process-environment)))
- (when (tramp-get-connection-process ,vec)
- ;; For already existing connections, the new exec path must
- ;; be re-set, otherwise it won't take effect. One example
- ;; of such case is when remote dir-locals are read and
- ;; *then* subprocesses are triggered within the same
- ;; connection.
- (python-shell-tramp-refresh-remote-path
- ,vec (python-shell-calculate-exec-path))
- ;; The `tramp-remote-process-environment' variable is only
- ;; effective when the started process is an interactive
- ;; shell, otherwise (like in the case of processes started
- ;; with `process-file') the environment is not changed.
- ;; This makes environment modifications effective
- ;; unconditionally.
- (python-shell-tramp-refresh-process-environment
- ,vec tramp-remote-process-environment))
- ,(macroexp-progn body)))))
+ `(python-shell--with-environment
+ (python-shell--calculate-process-environment)
+ (lambda () ,@body)))
+
+(defun python-shell--with-environment (extraenv bodyfun)
+ ;; FIXME: This is where the generic code delegates to Tramp.
+ (let* ((vec
+ (and (file-remote-p default-directory)
+ (fboundp 'tramp-dissect-file-name)
+ (ignore-errors
+ (tramp-dissect-file-name default-directory 'noexpand)))))
+ (if vec
+ (python-shell--tramp-with-environment vec extraenv bodyfun)
+ (let ((process-environment
+ (append extraenv process-environment))
+ (exec-path
+ ;; FIXME: This is still Python-specific.
+ (python-shell-calculate-exec-path)))
+ (funcall bodyfun)))))
+
+(defun python-shell--tramp-with-environment (vec extraenv bodyfun)
+ (defvar tramp-remote-process-environment)
+ (declare-function tramp-get-connection-process "tramp" (vec))
+ (let* ((tramp-remote-process-environment
+ (append extraenv tramp-remote-process-environment)))
+ (when (tramp-get-connection-process vec)
+ ;; For already existing connections, the new exec path must
+ ;; be re-set, otherwise it won't take effect. One example
+ ;; of such case is when remote dir-locals are read and
+ ;; *then* subprocesses are triggered within the same
+ ;; connection.
+ (python-shell-tramp-refresh-remote-path
+ ;; FIXME: This is still Python-specific.
+ vec (python-shell-calculate-exec-path))
+ ;; The `tramp-remote-process-environment' variable is only
+ ;; effective when the started process is an interactive
+ ;; shell, otherwise (like in the case of processes started
+ ;; with `process-file') the environment is not changed.
+ ;; This makes environment modifications effective
+ ;; unconditionally.
+ (python-shell-tramp-refresh-process-environment
+ vec tramp-remote-process-environment))
+ (funcall bodyfun)))
(defvar python-shell--prompt-calculated-input-regexp nil
"Calculated input prompt regexp for inferior python shell.
@@ -2636,12 +2664,13 @@ banner and the initial prompt are received separately."
(define-obsolete-function-alias
'python-comint-output-filter-function
- 'ansi-color-filter-apply
+ #'ansi-color-filter-apply
"25.1")
(defun python-comint-postoutput-scroll-to-bottom (output)
"Faster version of `comint-postoutput-scroll-to-bottom'.
Avoids `recenter' calls until OUTPUT is completely sent."
+ (declare (obsolete nil "29.1")) ; Not used.
(when (and (not (string= "" output))
(python-shell-comint-end-of-output-p
(ansi-color-filter-apply output)))
@@ -2821,8 +2850,7 @@ current process to not hang while waiting. This is useful to
safely attach setup code for long-running processes that
eventually provide a shell."
:version "25.1"
- :type 'hook
- :group 'python)
+ :type 'hook)
(defconst python-shell-eval-setup-code
"\
@@ -2948,15 +2976,15 @@ variable.
(setq-local comint-output-filter-functions
'(ansi-color-process-output
python-shell-comint-watch-for-first-prompt-output-filter
- python-comint-postoutput-scroll-to-bottom
comint-watch-for-password-prompt))
(setq-local comint-highlight-input nil)
(setq-local compilation-error-regexp-alist
python-shell-compilation-regexp-alist)
+ (setq-local scroll-conservatively 1)
(add-hook 'completion-at-point-functions
#'python-shell-completion-at-point nil 'local)
(define-key inferior-python-mode-map "\t"
- 'python-shell-completion-complete-or-indent)
+ #'python-shell-completion-complete-or-indent)
(make-local-variable 'python-shell-internal-last-output)
(when python-shell-font-lock-enable
(python-shell-font-lock-turn-on))
@@ -2982,7 +3010,8 @@ killed."
(let* ((cmdlist (split-string-and-unquote cmd))
(interpreter (car cmdlist))
(args (cdr cmdlist))
- (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name
+ (buffer (apply #'make-comint-in-buffer proc-name
+ proc-buffer-name
interpreter nil args))
(python-shell--parent-buffer (current-buffer))
(process (get-buffer-process buffer))
@@ -3080,7 +3109,8 @@ of `error' with a user-friendly message."
(or (python-shell-get-process)
(if interactivep
(user-error
- "Start a Python process first with `M-x run-python' or `%s'"
+ (substitute-command-keys
+ "Start a Python process first with \\`M-x run-python' or `%s'")
;; Get the binding.
(key-description
(where-is-internal
@@ -3131,7 +3161,7 @@ there for compatibility with CEDET.")
(run-python-internal))))
(define-obsolete-function-alias
- 'python-proc 'python-shell-internal-get-or-create-process "24.3")
+ 'python-proc #'python-shell-internal-get-or-create-process "24.3")
(defun python-shell--save-temp-file (string)
(let* ((temporary-file-directory
@@ -3216,11 +3246,13 @@ detecting a prompt at the end of the buffer."
(defun python-shell-send-string-no-output (string &optional process)
"Send STRING to PROCESS and inhibit output.
Return the output."
- (let ((process (or process (python-shell-get-process-or-error)))
- (comint-preoutput-filter-functions
- '(python-shell-output-filter))
- (python-shell-output-filter-in-progress t)
- (inhibit-quit t))
+ (or process (setq process (python-shell-get-process-or-error)))
+ (cl-letf (((process-filter process)
+ (lambda (_proc str)
+ (with-current-buffer (process-buffer process)
+ (python-shell-output-filter str))))
+ (python-shell-output-filter-in-progress t)
+ (inhibit-quit t))
(or
(with-local-quit
(python-shell-send-string string process)
@@ -3248,10 +3280,10 @@ Returns the output. See `python-shell-send-string-no-output'."
(python-shell-internal-get-or-create-process))))
(define-obsolete-function-alias
- 'python-send-receive 'python-shell-internal-send-string "24.3")
+ 'python-send-receive #'python-shell-internal-send-string "24.3")
(define-obsolete-function-alias
- 'python-send-string 'python-shell-internal-send-string "24.3")
+ 'python-send-string #'python-shell-internal-send-string "24.3")
(defun python-shell-buffer-substring (start end &optional nomain no-cookie)
"Send buffer substring from START to END formatted for shell.
@@ -3286,22 +3318,25 @@ the python shell:
(goto-char start)
(python-util-forward-comment 1)
(current-indentation))))
- (fillstr (and (not no-cookie)
- (not starts-at-point-min-p)
- (concat
- (format "# -*- coding: %s -*-\n" encoding)
- (make-string
- ;; Subtract 2 because of the coding cookie.
- (- (line-number-at-pos start) 2) ?\n)))))
+ (fillstr (cond (starts-at-point-min-p
+ nil)
+ ((not no-cookie)
+ (concat
+ (format "# -*- coding: %s -*-\n" encoding)
+ (make-string
+ ;; Subtract 2 because of the coding cookie.
+ (- (line-number-at-pos start) 2) ?\n)))
+ (t
+ (make-string (- (line-number-at-pos start) 1) ?\n)))))
(with-temp-buffer
(python-mode)
(when fillstr
(insert fillstr))
- (insert substring)
- (goto-char (point-min))
(when (not toplevel-p)
- (insert "if True:")
+ (forward-line -1)
+ (insert "if True:\n")
(delete-region (point) (line-end-position)))
+ (insert substring)
(when nomain
(let* ((if-name-main-start-end
(and nomain
@@ -3547,8 +3582,7 @@ def __PYTHON_EL_get_completions(text):
completer.print_mode = True
return completions"
"Code used to setup completion in inferior Python processes."
- :type 'string
- :group 'python)
+ :type 'string)
(define-obsolete-variable-alias
'python-shell-completion-module-string-code
@@ -3821,7 +3855,8 @@ With argument MSG show activation/deactivation message."
;; in use based on its args and uses `apply-partially'
;; to make it up for the 3 args case.
(if (= (length
- (help-function-arglist 'comint-redirect-filter)) 3)
+ (help-function-arglist 'comint-redirect-filter))
+ 3)
(set-process-filter
process (apply-partially
#'comint-redirect-filter original-filter-fn))
@@ -3930,7 +3965,7 @@ using that one instead of current buffer's process."
(define-obsolete-function-alias
'python-shell-completion-complete-at-point
- 'python-shell-completion-at-point
+ #'python-shell-completion-at-point
"25.1")
(defun python-shell-completion-complete-or-indent ()
@@ -3959,7 +3994,6 @@ considered over. The overlay arrow will be removed from the currently tracked
buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all
files opened by pdbtracking will be killed."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-pdbtrack-stacktrace-info-regexp
@@ -4168,7 +4202,7 @@ inferior Python process is updated properly."
(define-obsolete-function-alias
'python-completion-complete-at-point
- 'python-completion-at-point
+ #'python-completion-at-point
"25.1")
@@ -4178,29 +4212,25 @@ inferior Python process is updated properly."
"Function to fill comments.
This is the function used by `python-fill-paragraph' to
fill comments."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-string-function 'python-fill-string
"Function to fill strings.
This is the function used by `python-fill-paragraph' to
fill strings."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-decorator-function 'python-fill-decorator
"Function to fill decorators.
This is the function used by `python-fill-paragraph' to
fill decorators."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-paren-function 'python-fill-paren
"Function to fill parens.
This is the function used by `python-fill-paragraph' to
fill parens."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-docstring-style 'pep-257
"Style used to fill docstrings.
@@ -4270,7 +4300,6 @@ value may result in one of the following docstring styles:
(const :tag "PEP-257 with 2 newlines at end of string." pep-257)
(const :tag "PEP-257 with 1 newline at end of string." pep-257-nn)
(const :tag "Symmetric style." symmetric))
- :group 'python
:safe (lambda (val)
(memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
@@ -4429,7 +4458,6 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
This happens when pressing \"if<SPACE>\", for example, to prompt for
the if condition."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defvar python-skeleton-available '()
@@ -4554,7 +4582,7 @@ The skeleton will be bound to python-skeleton-NAME."
(defun python-skeleton-add-menu-items ()
"Add menu items to Python->Skeletons menu."
- (let ((skeletons (sort python-skeleton-available 'string<)))
+ (let ((skeletons (sort python-skeleton-available #'string<)))
(dolist (skeleton skeletons)
(easy-menu-add-item
nil '("Python" "Skeletons")
@@ -4584,8 +4612,7 @@ def __FFAP_get_module_path(objstr):
except:
return ''"
"Python code to get a module path."
- :type 'string
- :group 'python)
+ :type 'string)
(defun python-ffap-module-path (module)
"Function for `ffap-alist' to return path for MODULE."
@@ -4613,14 +4640,12 @@ def __FFAP_get_module_path(objstr):
(executable-find "epylint")
"install pyflakes, pylint or something else")
"Command used to check a Python file."
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-check-buffer-name
"*Python check: %s*"
"Buffer name used for check commands."
- :type 'string
- :group 'python)
+ :type 'string)
(defvar python-check-custom-command nil
"Internal use.")
@@ -4687,8 +4712,7 @@ See `python-check-command' for the default."
doc = ''
return doc"
"Python code to setup documentation retrieval."
- :type 'string
- :group 'python)
+ :type 'string)
(defun python-eldoc--get-symbol-at-point ()
"Get the current symbol for eldoc.
@@ -4735,14 +4759,13 @@ Set to nil by `python-eldoc-function' if
(defcustom python-eldoc-function-timeout 1
"Timeout for `python-eldoc-function' in seconds."
- :group 'python
:type 'integer
:version "25.1")
(defcustom python-eldoc-function-timeout-permanent t
- "Non-nil means that when `python-eldoc-function' times out
-`python-eldoc-get-doc' will be set to nil."
- :group 'python
+ "If non-nil, a timeout in Python-Eldoc will disable it permanently.
+Python-Eldoc can be re-enabled manually by setting `python-eldoc-get-doc'
+back to t in the affected buffer."
:type 'boolean
:version "25.1")
@@ -4934,7 +4957,7 @@ To this:
(\"decorator.wrapped_f\" . 393))"
;; Inspired by imenu--flatten-index-alist removed in revno 21853.
(apply
- 'nconc
+ #'nconc
(mapcar
(lambda (item)
(let ((name (if prefix
@@ -5017,7 +5040,7 @@ since it returns nil if point is not inside a defun."
(and (= (current-indentation) 0) (throw 'exit t))))
(and names
(concat (and type (format "%s " type))
- (mapconcat 'identity names ".")))))))
+ (mapconcat #'identity names ".")))))))
(defun python-info-current-symbol (&optional replace-self)
"Return current symbol using dotty syntax.
@@ -5038,9 +5061,10 @@ parent defun name."
(replace-regexp-in-string
(python-rx line-start word-start "self" word-end ?.)
(concat
- (mapconcat 'identity
+ (mapconcat #'identity
(butlast (split-string current-defun "\\."))
- ".") ".")
+ ".")
+ ".")
name)))))))
(defun python-info-statement-starts-block-p ()
@@ -5082,7 +5106,7 @@ parent defun name."
(define-obsolete-function-alias
'python-info-closing-block
- 'python-info-dedenter-opening-block-position "24.4")
+ #'python-info-dedenter-opening-block-position "24.4")
(defun python-info-dedenter-opening-block-position ()
"Return the point of the closest block the current line closes.
@@ -5127,7 +5151,8 @@ likely an invalid python file."
(let ((indentation (current-indentation)))
(when (and (not (memq indentation collected-indentations))
(or (not collected-indentations)
- (< indentation (apply #'min collected-indentations)))
+ (< indentation
+ (apply #'min collected-indentations)))
;; There must be no line with indentation
;; smaller than `indentation' (except for
;; blank lines) between the found opening
@@ -5155,7 +5180,7 @@ likely an invalid python file."
(define-obsolete-function-alias
'python-info-closing-block-message
- 'python-info-dedenter-opening-block-message "24.4")
+ #'python-info-dedenter-opening-block-message "24.4")
(defun python-info-dedenter-opening-block-message ()
"Message the first line of the block the current statement closes."
@@ -5280,10 +5305,15 @@ operator."
(forward-line -1)
(python-info-assignment-statement-p t))))
-(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss)
- "Check if point is at `beginning-of-defun' using SYNTAX-PPSS."
+(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss
+ check-statement)
+ "Check if point is at `beginning-of-defun' using SYNTAX-PPSS.
+When CHECK-STATEMENT is non-nil, the current statement is checked
+instead of the current physical line."
(and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss))))
(save-excursion
+ (when check-statement
+ (python-nav-beginning-of-statement))
(beginning-of-line 1)
(looking-at python-nav-beginning-of-defun-regexp))))
@@ -5457,10 +5487,12 @@ allowed files."
(let ((dir-name (file-name-as-directory dir)))
(apply #'nconc
(mapcar (lambda (file-name)
- (let ((full-file-name (expand-file-name file-name dir-name)))
+ (let ((full-file-name
+ (expand-file-name file-name dir-name)))
(when (and
(not (member file-name '("." "..")))
- (funcall (or predicate #'identity) full-file-name))
+ (funcall (or predicate #'identity)
+ full-file-name))
(list full-file-name))))
(directory-files dir-name)))))
@@ -5528,7 +5560,6 @@ required arguments. Once launched it will receive the Python source to be
checked as its standard input.
To use `flake8' you would set this to (\"flake8\" \"-\")."
:version "26.1"
- :group 'python-flymake
:type '(repeat string))
;; The default regexp accommodates for older pyflakes, which did not
@@ -5550,7 +5581,6 @@ If COLUMN or TYPE are nil or that index didn't match, that
information is not present on the matched line and a default will
be used."
:version "26.1"
- :group 'python-flymake
:type '(list regexp
(integer :tag "Line's index")
(choice
@@ -5575,7 +5605,6 @@ configuration could be:
By default messages are considered errors."
:version "26.1"
- :group 'python-flymake
:type '(alist :key-type (regexp)
:value-type (symbol)))
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 72631a6557f..87bb92908d1 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -70,7 +70,7 @@
"Regexp to match modifiers.")
(defconst ruby-block-mid-keywords
- '("then" "else" "elsif" "when" "rescue" "ensure")
+ '("then" "else" "elsif" "when" "in" "rescue" "ensure")
"Keywords where the indentation gets shallower in middle of block statements.")
(defconst ruby-block-mid-re
@@ -325,6 +325,13 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
"Use `ruby-encoding-map' to set encoding magic comment if this is non-nil."
:type 'boolean :group 'ruby)
+(defcustom ruby-toggle-block-space-before-parameters t
+ "When non-nil, ensure space between the \"toggled\" curly and parameters.
+This only affects the output of the command `ruby-toggle-block'."
+ :type 'boolean
+ :safe 'booleanp
+ :version "29.1")
+
;;; SMIE support
(require 'smie)
@@ -362,7 +369,9 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
(for-body (for-head ";" insts))
(for-head (id "in" exp))
(cases (exp "then" insts)
- (cases "when" cases) (insts "else" insts))
+ (cases "when" cases)
+ (cases "in" cases)
+ (insts "else" insts))
(expseq (exp) );;(expseq "," expseq)
(hashvals (exp1 "=>" exp1) (hashvals "," hashvals))
(insts-rescue-insts (insts)
@@ -373,7 +382,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
(if-body (ielsei) (if-body "elsif" if-body)))
'((nonassoc "in") (assoc ";") (right " @ ")
(assoc ",") (right "="))
- '((assoc "when"))
+ '((assoc "when" "in"))
'((assoc "elsif"))
'((assoc "rescue" "ensure"))
'((assoc ",")))
@@ -499,7 +508,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
((member tok '("unless" "if" "while" "until"))
(if (save-excursion (forward-word-strictly -1) (ruby-smie--bosp))
tok "iuwu-mod"))
- ((string-match-p "\\`|[*&]?\\'" tok)
+ ((string-match-p "\\`|[*&]*\\'" tok)
(forward-char (- 1 (length tok)))
(setq tok "|")
(cond
@@ -552,7 +561,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
((ruby-smie--closing-pipe-p) "closing-|")
(t tok)))
((string-match-p "\\`[^|]+|\\'" tok) "closing-|")
- ((string-match-p "\\`|[*&]\\'" tok)
+ ((string-match-p "\\`|[*&]*\\'" tok)
(forward-char 1)
(substring tok 1))
((and (equal tok "") (eq ?\\ (char-before)) (looking-at "\n"))
@@ -588,7 +597,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
(cond
((smie-rule-parent-p "def" "begin" "do" "class" "module" "for"
"while" "until" "unless"
- "if" "then" "elsif" "else" "when"
+ "if" "then" "elsif" "else" "when" "in"
"rescue" "ensure" "{")
(smie-rule-parent ruby-indent-level))
;; For (invalid) code between switch and case.
@@ -652,7 +661,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
ruby-indent-level))))
(`(:before . ,(or "else" "then" "elsif" "rescue" "ensure"))
(smie-rule-parent))
- ('(:before . "when")
+ (`(:before . ,(or "when" "in"))
;; Align to the previous `when', but look up the virtual
;; indentation of `case'.
(if (smie-rule-sibling-p) 0 (smie-rule-parent)))
@@ -1722,13 +1731,14 @@ See `add-log-current-defun-function'."
(insert "}")
(goto-char orig)
(delete-char 2)
- ;; Maybe this should be customizable, let's see if anyone asks.
- (insert "{ ")
- (setq beg-marker (point-marker))
- (when (looking-at "\\s +|")
- (delete-char (- (match-end 0) (match-beginning 0) 1))
- (forward-char)
- (re-search-forward "|" (line-end-position) t))
+ (insert "{")
+ (if (looking-at "\\s +|")
+ (progn
+ (just-one-space (if ruby-toggle-block-space-before-parameters 1 0))
+ (setq beg-marker (point-marker))
+ (forward-char)
+ (re-search-forward "|" (line-end-position) t))
+ (setq beg-marker (point-marker)))
(save-excursion
(skip-chars-forward " \t\n\r")
(setq beg-pos (point))
@@ -2447,6 +2457,13 @@ If there is no Rubocop config file, Rubocop will be passed a flag
(setq-local beginning-of-defun-function #'ruby-beginning-of-defun)
(setq-local end-of-defun-function #'ruby-end-of-defun)
+ ;; `outline-regexp' contains the first part of `ruby-indent-beg-re'
+ (setq-local outline-regexp (concat "^\\s *"
+ (regexp-opt '("class" "module" "def"))
+ "\\_>"))
+ (setq-local outline-level (lambda () (1+ (/ (current-indentation)
+ ruby-indent-level))))
+
(add-hook 'after-save-hook #'ruby-mode-set-encoding nil 'local)
(add-hook 'electric-indent-functions #'ruby--electric-indent-p nil 'local)
(add-hook 'flymake-diagnostic-functions #'ruby-flymake-auto nil 'local)
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index 6f47f645e02..e0453c3b2f4 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -1,7 +1,6 @@
;;; scheme.el --- Scheme (and DSSSL) editing mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-1988, 1997-1998, 2001-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1986-2022 Free Software Foundation, Inc.
;; Author: Bill Rozas <jinx@martigny.ai.mit.edu>
;; Adapted-by: Dave Love <d.love@dl.ac.uk>
@@ -115,12 +114,53 @@
(define-abbrev-table 'scheme-mode-abbrev-table ())
(defvar scheme-imenu-generic-expression
- '((nil
- "^(define\\(?:-\\(?:generic\\(?:-procedure\\)?\\|method\\)\\)?\\s-+(?\\(\\sw+\\)" 1)
- ("Types"
- "^(define-class\\s-+(?\\(\\sw+\\)" 1)
- ("Macros"
- "^(\\(defmacro\\|define-macro\\|define-syntax\\)\\s-+(?\\(\\sw+\\)" 2))
+ `((nil
+ ,(rx bol "(define"
+ (zero-or-one "*")
+ (zero-or-one "-public")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Methods"
+ ,(rx bol "(define-"
+ (or "generic" "method" "accessor")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Classes"
+ ,(rx bol "(define-class"
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Records"
+ ,(rx bol "(define-record-type"
+ (zero-or-one "*")
+ (one-or-more space)
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Conditions"
+ ,(rx bol "(define-condition-type"
+ (one-or-more space)
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Modules"
+ ,(rx bol "(define-module"
+ (one-or-more space)
+ (group "(" (one-or-more any) ")"))
+ 1)
+ ("Macros"
+ ,(rx bol "("
+ (or (and "defmacro"
+ (zero-or-one "*")
+ (zero-or-one "-public"))
+ "define-macro" "define-syntax" "define-syntax-rule")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1))
"Imenu generic expression for Scheme mode. See `imenu-generic-expression'.")
(defun scheme-mode-variables ()
@@ -160,12 +200,10 @@
(defvar scheme-mode-line-process "")
-(defvar scheme-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map lisp-mode-shared-map)
- map)
- "Keymap for Scheme mode.
-All commands in `lisp-mode-shared-map' are inherited by this map.")
+(defvar-keymap scheme-mode-map
+ :doc "Keymap for Scheme mode.
+All commands in `lisp-mode-shared-map' are inherited by this map."
+ :parent lisp-mode-shared-map)
(easy-menu-define scheme-mode-menu scheme-mode-map
"Menu for Scheme mode."
@@ -350,12 +388,18 @@ See `run-hooks'."
st))
(put 'lambda 'scheme-doc-string-elt 2)
+(put 'lambda* 'scheme-doc-string-elt 2)
;; Docstring's pos in a `define' depends on whether it's a var or fun def.
(put 'define 'scheme-doc-string-elt
(lambda ()
;; The function is called with point right after "define".
(forward-comment (point-max))
(if (eq (char-after) ?\() 2 0)))
+(put 'define* 'scheme-doc-string-elt 2)
+(put 'case-lambda 'scheme-doc-string-elt 1)
+(put 'case-lambda* 'scheme-doc-string-elt 1)
+(put 'define-syntax-rule 'scheme-doc-string-elt 2)
+(put 'syntax-rules 'scheme-doc-string-elt 2)
(defun scheme-syntax-propertize (beg end)
(goto-char beg)
@@ -521,10 +565,20 @@ indentation."
(lisp-indent-specform 2 state indent-point normal-indent)
(lisp-indent-specform 1 state indent-point normal-indent)))
-;; (put 'begin 'scheme-indent-function 0), say, causes begin to be indented
-;; like defun if the first form is placed on the next line, otherwise
-;; it is indented like any other form (i.e. forms line up under first).
-
+;; See `scheme-indent-function' (the function) for what these do.
+;; In a nutshell:
+;; . for forms with no `scheme-indent-function' property the 2nd
+;; and subsequent lines will be indented with one space;
+;; . if the value of the property is zero, then when the first form
+;; is on a separate line, the next lines will be indented with 2
+;; spaces instead of the default one space;
+;; . if the value is a positive integer N, the first N lines after
+;; the first one will be indented with 4 spaces, and the rest
+;; will be indented with 2 spaces;
+;; . if the value is `defun', the indentation is like for `defun';
+;; . if the value is a function, it will be called to produce the
+;; required indentation.
+;; See also http://community.schemewiki.org/?emacs-indentation.
(put 'begin 'scheme-indent-function 0)
(put 'case 'scheme-indent-function 1)
(put 'delay 'scheme-indent-function 0)
@@ -535,12 +589,16 @@ indentation."
(put 'letrec 'scheme-indent-function 1)
(put 'let-values 'scheme-indent-function 1) ; SRFI 11
(put 'let*-values 'scheme-indent-function 1) ; SRFI 11
+(put 'and-let* 'scheme-indent-function 1) ; SRFI 2
(put 'sequence 'scheme-indent-function 0) ; SICP, not r4rs
(put 'let-syntax 'scheme-indent-function 1)
(put 'letrec-syntax 'scheme-indent-function 1)
-(put 'syntax-rules 'scheme-indent-function 1)
+(put 'syntax-rules 'scheme-indent-function 'defun)
(put 'syntax-case 'scheme-indent-function 2) ; not r5rs
+(put 'with-syntax 'scheme-indent-function 1)
(put 'library 'scheme-indent-function 1) ; R6RS
+;; Part of at least Guile, Chez Scheme, Chicken
+(put 'eval-when 'scheme-indent-function 1)
(put 'call-with-input-file 'scheme-indent-function 1)
(put 'call-with-port 'scheme-indent-function 1)
@@ -564,6 +622,14 @@ indentation."
;; SRFI-8
(put 'receive 'scheme-indent-function 2)
+;; SRFI-204 (withdrawn, but provided in many implementations, see the SRFI text)
+(put 'match 'scheme-indent-function 1)
+(put 'match-lambda 'scheme-indent-function 0)
+(put 'match-lambda* 'scheme-indent-function 0)
+(put 'match-let 'scheme-indent-function 'scheme-let-indent)
+(put 'match-let* 'scheme-indent-function 1)
+(put 'match-letrec 'scheme-indent-function 1)
+
;;;; MIT Scheme specific indentation.
(if scheme-mit-dialect
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index e0d597d89de..be9f325d93d 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -286,7 +286,7 @@ naming the shell."
:group 'sh-script)
(defcustom sh-imenu-generic-expression
- '((sh
+ `((sh
. ((nil
;; function FOO
;; function FOO()
@@ -295,8 +295,21 @@ naming the shell."
;; FOO()
(nil
"^\\s-*\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*()"
- 1)
- )))
+ 1)))
+ (mksh
+ . ((nil
+ ;; function FOO
+ ;; function FOO()
+ ,(rx bol (* (syntax whitespace)) "function" (+ (syntax whitespace))
+ (group (1+ (not (any "\0\t\n \"$&'();<=>\\`|#*?[]/"))))
+ (* (syntax whitespace)) (? "()"))
+ 1)
+ (nil
+ ;; FOO()
+ ,(rx bol (* (syntax whitespace))
+ (group (1+ (not (any "\0\t\n \"$&'();<=>\\`|#*?[]/"))))
+ (* (syntax whitespace)) "()")
+ 1))))
"Alist of regular expressions for recognizing shell function definitions.
See `sh-feature' and `imenu-generic-expression'."
:type '(alist :key-type (symbol :tag "Shell")
@@ -306,7 +319,7 @@ See `sh-feature' and `imenu-generic-expression'."
:value-type
(repeat :tag "Regexp, index..." sexp)))
:group 'sh-script
- :version "20.4")
+ :version "29.1")
(defun sh-current-defun-name ()
"Find the name of function or variable at point.
@@ -641,7 +654,12 @@ implemented as aliases. See `sh-feature'."
:version "24.4" ; bash4 additions
:group 'sh-script)
-
+(defcustom sh-indent-statement-after-and t
+ "How to indent statements following && in Shell-Script mode.
+If t, indent to align with &&.
+If nil, indent to align with the previous line's indentation."
+ :type 'boolean
+ :version "29.1")
(defcustom sh-leading-keywords
'((bash sh-append sh
@@ -1138,8 +1156,8 @@ Can be set to a number, or to nil which means leave it as is."
"The default indentation increment.
This value is used for the `+' and `-' symbols in an indentation variable."
:type 'integer
+ :safe #'integerp
:group 'sh-indentation)
-(put 'sh-basic-offset 'safe-local-variable 'integerp)
(defcustom sh-indent-comment t
"How a comment line is to be indented.
@@ -1407,10 +1425,10 @@ If FORCE is non-nil and no process found, create one."
(defun sh-show-shell ()
"Pop the shell interaction buffer."
(interactive)
- (pop-to-buffer (process-buffer (sh-shell-process t))))
+ (pop-to-buffer (process-buffer (sh-shell-process t)) display-comint-buffer-action))
(defun sh-send-text (text)
- "Send the text to the `sh-shell-process'."
+ "Send TEXT to `sh-shell-process'."
(comint-send-string (sh-shell-process t) (concat text "\n")))
(defun sh-cd-here ()
@@ -1538,6 +1556,11 @@ with your script for an edit-interpret-debug cycle."
(add-hook 'completion-at-point-functions
#'sh-completion-at-point-function nil t)
(setq-local outline-regexp "###")
+ (setq-local escaped-string-quote
+ (lambda (terminator)
+ (if (eq terminator ?')
+ "'\\'"
+ "\\")))
;; Parse or insert magic number for exec, and set all variables depending
;; on the shell thus determined.
(sh-set-shell
@@ -1549,7 +1572,7 @@ with your script for an edit-interpret-debug cycle."
;; Checks that use `buffer-file-name' follow.
((string-match "\\.m?spec\\'" buffer-file-name) "rpm")
((string-match "[.]sh\\>" buffer-file-name) "sh")
- ((string-match "[.]bash\\>" buffer-file-name) "bash")
+ ((string-match "[.]bash\\(rc\\)?\\>" buffer-file-name) "bash")
((string-match "[.]ksh\\>" buffer-file-name) "ksh")
((string-match "[.]mkshrc\\>" buffer-file-name) "mksh")
((string-match "[.]t?csh\\(rc\\)?\\>" buffer-file-name) "csh")
@@ -1602,7 +1625,7 @@ This adds rules for comments and assignments."
;;; Completion
-(defvar sh--completion-keywords '("if" "while" "until" "for"))
+(defvar sh--completion-keywords '("if" "while" "until" "for" "then"))
(defun sh--vars-before-point ()
(save-excursion
@@ -1774,21 +1797,27 @@ Does not preserve point."
(n (skip-syntax-backward ".")))
(if (or (zerop n)
(and (eq n -1)
+ ;; Skip past quoted white space.
(let ((p (point)))
(if (eq -1 (% (skip-syntax-backward "\\") 2))
t
(goto-char p)
nil))))
(while
- (progn (skip-syntax-backward ".w_'")
- (or (not (zerop (skip-syntax-backward "\\")))
- (when (eq ?\\ (char-before (1- (point))))
- (let ((p (point)))
- (forward-char -1)
- (if (eq -1 (% (skip-syntax-backward "\\") 2))
- t
- (goto-char p)
- nil))))))
+ (progn
+ ;; Skip past words, but stop at semicolons.
+ (while (and (not (zerop (skip-syntax-backward "w_'")))
+ (not (eq (char-before (point)) ?\;))
+ (skip-syntax-backward ".")))
+ (or (not (zerop (skip-syntax-backward "\\")))
+ ;; Skip past quoted white space.
+ (when (eq ?\\ (char-before (1- (point))))
+ (let ((p (point)))
+ (forward-char -1)
+ (if (eq -1 (% (skip-syntax-backward "\\") 2))
+ t
+ (goto-char p)
+ nil))))))
(goto-char (- (point) (% (skip-syntax-backward "\\") 2))))
(buffer-substring-no-properties (point) pos)))
@@ -1897,9 +1926,9 @@ With t, you get the latter as long as that would indent the continuation line
deeper than the initial line."
:version "25.1"
:type '(choice
- (const nil :tag "Never")
- (const t :tag "Only if needed to make it deeper")
- (const always :tag "Always"))
+ (const :value nil :tag "Never")
+ (const :value t :tag "Only if needed to make it deeper")
+ (const :value always :tag "Always"))
:group 'sh-indentation)
(defun sh-smie--continuation-start-indent ()
@@ -1973,7 +2002,7 @@ May return nil if the line should not be treated as continued."
(cons 'column (smie-indent-keyword ";"))
(smie-rule-separator kind)))
(`(:after . ,(or ";;" ";&" ";;&"))
- (with-demoted-errors
+ (with-demoted-errors "SMIE rule error: %S"
(smie-backward-sexp token)
(cons 'column
(if (or (smie-rule-bolp)
@@ -1984,7 +2013,9 @@ May return nil if the line should not be treated as continued."
(current-column)
(smie-indent-calculate)))))
(`(:before . ,(or "|" "&&" "||"))
- (unless (smie-rule-parent-p token)
+ (when (and (not (smie-rule-parent-p token))
+ (or (not (equal token "&&"))
+ sh-indent-statement-after-and))
(smie-backward-sexp token)
`(column . ,(+ (funcall smie-rules-function :elem 'basic)
(smie-indent-virtual)))))
@@ -2379,6 +2410,8 @@ Lines containing only comments are considered empty."
The working directory is that of the buffer, and only environment variables
are already set which is why you can mark a header within the script.
+The executed subshell is `sh-shell-file'.
+
With a positive prefix ARG, instead of sending region, define header from
beginning of buffer to point. With a negative prefix ARG, instead of sending
region, clear header."
@@ -2386,17 +2419,18 @@ region, clear header."
(if flag
(setq sh-header-marker (if (> (prefix-numeric-value flag) 0)
(point-marker)))
- (if sh-header-marker
- (save-excursion
- (let (buffer-undo-list)
- (goto-char sh-header-marker)
- (append-to-buffer (current-buffer) start end)
- (shell-command-on-region (point-min)
- (setq end (+ sh-header-marker
- (- end start)))
- sh-shell-file)
- (delete-region sh-header-marker end)))
- (shell-command-on-region start end (concat sh-shell-file " -")))))
+ (let ((shell-file-name sh-shell-file))
+ (if sh-header-marker
+ (save-excursion
+ (let (buffer-undo-list)
+ (goto-char sh-header-marker)
+ (append-to-buffer (current-buffer) start end)
+ (shell-command-on-region (point-min)
+ (setq end (+ sh-header-marker
+ (- end start)))
+ sh-shell-file)
+ (delete-region sh-header-marker end)))
+ (shell-command-on-region start end (concat sh-shell-file " -"))))))
(defun sh-remember-variable (var)
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 69d16a4357e..b950f93f2a0 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -274,8 +274,8 @@ file. Since that is a plaintext file, this could be dangerous."
(defcustom sql-port 0
"Default port for connecting to a MySQL or Postgres server."
:version "24.1"
- :type 'number
- :safe 'numberp)
+ :type 'natnum
+ :safe 'natnump)
(defcustom sql-default-directory nil
"Default directory for SQL processes."
@@ -3216,7 +3216,7 @@ For both `:file' and `:completion', there can also be a
(cond
((plist-member plist :file)
(let ((file-name
- (read-file-name prompt
+ (read-file-name prompt-def
(file-name-directory last-value)
default
(if (plist-member plist :must-match)
@@ -3246,7 +3246,7 @@ For both `:file' and `:completion', there can also be a
default))
((plist-get plist :number)
- (read-number prompt (or default last-value 0)))
+ (read-number (concat prompt ": ") (or default last-value 0)))
(t
(read-string prompt-def last-value history-var default))))))
@@ -3318,7 +3318,7 @@ function like this: (sql-get-login \\='user \\='password \\='database)."
(sql-get-login-ext 'sql-server "Server" 'sql-server-history plist))
('database
- (sql-get-login-ext 'sql-database "Database: "
+ (sql-get-login-ext 'sql-database "Database"
'sql-database-history plist))
('port
@@ -3648,94 +3648,69 @@ Allows the suppression of continuation prompts.")
(defvar sql-preoutput-hold nil)
-(defun sql-starts-with-prompt-re ()
- "Anchor the prompt expression at the beginning of the output line.
-Remove the start of line regexp."
- (concat "\\`" comint-prompt-regexp))
-
-(defun sql-ends-with-prompt-re ()
- "Anchor the prompt expression at the end of the output line.
-Match a SQL prompt or a password prompt."
- (concat "\\(?:\\(?:" sql-prompt-regexp "\\)\\|"
- "\\(?:" comint-password-prompt-regexp "\\)\\)\\'"))
-
(defun sql-interactive-remove-continuation-prompt (oline)
"Strip out continuation prompts out of the OLINE.
Added to the `comint-preoutput-filter-functions' hook in a SQL
-interactive buffer. If `sql-output-newline-count' is greater than
-zero, then an output line matching the continuation prompt is filtered
-out. If the count is zero, then a newline is inserted into the output
-to force the output from the query to appear on a new line.
-
-The complication to this filter is that the continuation prompts
-may arrive in multiple chunks. If they do, then the function
-saves any unfiltered output in a buffer and prepends that buffer
-to the next chunk to properly match the broken-up prompt.
-
-If the filter gets confused, it should reset and stop filtering
-to avoid deleting non-prompt output."
-
- ;; continue gathering lines of text iff
- ;; + we know what a prompt looks like, and
- ;; + there is held text, or
- ;; + there are continuation prompt yet to come, or
- ;; + not just a prompt string
+interactive buffer. The complication to this filter is that the
+continuation prompts may arrive in multiple chunks. If they do,
+then the function saves any unfiltered output in a buffer and
+prepends that buffer to the next chunk to properly match the
+broken-up prompt.
+
+The filter goes into play only if something is already
+accumulated, or we're waiting for continuation
+prompts (`sql-output-newline-count' is positive). In this case:
+- Accumulate process output into `sql-preoutput-hold'.
+- Remove any complete prompts / continuation prompts that we're waiting
+ for.
+- In case we're expecting more prompts - return all currently
+ accumulated _complete_ lines, leaving the rest for the next
+ invocation. They will appear in the output immediately. This way we
+ don't accumulate large chunks of data for no reason.
+- If we found all expected prompts - just return all current accumulated
+ data."
(when (and comint-prompt-regexp
- (or (> (length (or sql-preoutput-hold "")) 0)
- (> (or sql-output-newline-count 0) 0)
- (not (or (string-match sql-prompt-regexp oline)
- (and sql-prompt-cont-regexp
- (string-match sql-prompt-cont-regexp oline))))))
-
+ ;; We either already have something held, or expect
+ ;; prompts
+ (or sql-preoutput-hold
+ (and sql-output-newline-count
+ (> sql-output-newline-count 0))))
(save-match-data
- (let (prompt-found last-nl)
-
- ;; Add this text to what's left from the last pass
- (setq oline (concat sql-preoutput-hold oline)
- sql-preoutput-hold "")
-
- ;; If we are looking for multiple prompts
- (when (and (integerp sql-output-newline-count)
- (>= sql-output-newline-count 1))
- ;; Loop thru each starting prompt and remove it
- (let ((start-re (sql-starts-with-prompt-re)))
- (while (and (not (string= oline ""))
- (> sql-output-newline-count 0)
- (string-match start-re oline))
- (setq oline (replace-match "" nil nil oline)
- sql-output-newline-count (1- sql-output-newline-count)
- prompt-found t)))
-
- ;; If we've found all the expected prompts, stop looking
- (if (= sql-output-newline-count 0)
- (setq sql-output-newline-count nil)
-
- ;; Still more possible prompts, leave them for the next pass
- (setq sql-preoutput-hold oline
- oline "")))
-
- ;; If no prompts were found, stop looking
- (unless prompt-found
- (setq sql-output-newline-count nil
- oline (concat oline sql-preoutput-hold)
- sql-preoutput-hold ""))
-
- ;; Break up output by physical lines if we haven't hit the final prompt
- (let ((end-re (sql-ends-with-prompt-re)))
- (unless (and (not (string= oline ""))
- (string-match end-re oline)
- (>= (match-end 0) (length oline)))
- ;; Find everything upto the last nl
- (setq last-nl 0)
- (while (string-match "\n" oline last-nl)
- (setq last-nl (match-end 0)))
- ;; Hold after the last nl, return upto last nl
- (setq sql-preoutput-hold (concat (substring oline last-nl)
- sql-preoutput-hold)
- oline (substring oline 0 last-nl)))))))
+ ;; Add this text to what's left from the last pass
+ (setq oline (concat sql-preoutput-hold oline)
+ sql-preoutput-hold nil)
+
+ ;; If we are looking for prompts
+ (when (and sql-output-newline-count
+ (> sql-output-newline-count 0))
+ ;; Loop thru each starting prompt and remove it
+ (while (and (not (string-empty-p oline))
+ (> sql-output-newline-count 0)
+ (string-match comint-prompt-regexp oline))
+ (setq oline (replace-match "" nil nil oline)
+ sql-output-newline-count (1- sql-output-newline-count)))
+
+ ;; If we've found all the expected prompts, stop looking
+ (if (= sql-output-newline-count 0)
+ (setq sql-output-newline-count nil)
+ ;; Still more possible prompts, leave them for the next pass
+ (setq sql-preoutput-hold oline
+ oline "")))
+
+ ;; Lines that are now complete may be passed further
+ (when sql-preoutput-hold
+ (let ((last-nl 0))
+ (while (string-match "\n" sql-preoutput-hold last-nl)
+ (setq last-nl (match-end 0)))
+ ;; Return up to last nl, hold after the last nl
+ (setq oline (substring sql-preoutput-hold 0 last-nl)
+ sql-preoutput-hold (substring sql-preoutput-hold last-nl))
+ (when (string-empty-p sql-preoutput-hold)
+ (setq sql-preoutput-hold nil))))))
oline)
+
;;; Sending the region to the SQLi buffer.
(defvar sql-debug-send nil
"Display text sent to SQL process pragmatically.")
@@ -4184,18 +4159,35 @@ must tell Emacs. Here's how to do that in your init file:
(setq-local abbrev-all-caps 1)
;; Contains the name of database objects
(setq-local sql-contains-names t)
+ (setq-local escaped-string-quote "'")
(setq-local syntax-propertize-function
- (syntax-propertize-rules
- ;; Handle escaped apostrophes within strings.
- ("''"
- (0
- (if (save-excursion (nth 3 (syntax-ppss (match-beginning 0))))
- (string-to-syntax ".")
- (forward-char -1)
- nil)))
- ;; Propertize rules to not have /- and -* start comments.
- ("\\(/-\\)" (1 "."))
- ("\\(-\\*\\)" (1 "."))))
+ (eval
+ '(syntax-propertize-rules
+ ;; Handle escaped apostrophes within strings.
+ ((if (eq sql-product 'mysql)
+ "\\\\'"
+ "''")
+ (0
+ (if (save-excursion
+ (nth 3 (syntax-ppss (match-beginning 0))))
+ (string-to-syntax ".")
+ (forward-char -1)
+ nil)))
+ ;; Propertize rules to not have /- and -* start comments.
+ ("\\(/-\\)" (1 "."))
+ ("\\(-\\*\\)"
+ (1
+ (if (save-excursion
+ (not (ppss-comment-depth
+ (syntax-ppss (match-beginning 1)))))
+ ;; If we're outside a comment, we don't let -*
+ ;; start a comment.
+ (string-to-syntax ".")
+ ;; Inside a comment, ignore it to avoid -*/ not
+ ;; being interpreted as a comment end.
+ (forward-char -1)
+ nil))))
+ t))
;; Set syntax and font-face highlighting
;; Catch changes to sql-product and highlight accordingly
(sql-set-product (or sql-product 'ansi)) ; Fixes bug#13591
@@ -4633,6 +4625,9 @@ the call to \\[sql-product-interactive] with
(setq sql-buffer (buffer-name new-sqli-buffer))
(run-hooks 'sql-set-sqli-hook)))
+ ;; Also set the global value.
+ (setq-default sql-buffer (buffer-name new-sqli-buffer))
+
;; Make sure the connection is complete
;; (Sometimes start up can be slow)
;; and call the login hook
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index b1b78b4d128..e06eb9a6f70 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -264,8 +264,8 @@ Optional argument ARG is the same as for `capitalize-word'."
"Toggle superword movement and editing (Superword mode).
Superword mode is a buffer-local minor mode. Enabling it changes
-the definition of words such that symbols characters are treated
-as parts of words: e.g., in `superword-mode',
+the definition of words such that characters which have symbol
+syntax are treated as parts of words: e.g., in `superword-mode',
\"this_is_a_symbol\" counts as one word.
\\{superword-mode-map}"
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index ed6dce02c03..7dae14f9e02 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -120,13 +120,13 @@
(defcustom tcl-indent-level 4
"Indentation of Tcl statements with respect to containing block."
- :type 'integer)
-(put 'tcl-indent-level 'safe-local-variable #'integerp)
+ :type 'integer
+ :safe #'integerp)
(defcustom tcl-continued-indent-level 4
"Indentation of continuation line relative to first line of command."
- :type 'integer)
-(put 'tcl-continued-indent-level 'safe-local-variable #'integerp)
+ :type 'integer
+ :safe #'integerp)
(defcustom tcl-auto-newline nil
"Non-nil means automatically newline before and after braces you insert."
@@ -344,7 +344,7 @@ information):
Add functions to the hook with `add-hook':
- (add-hook 'tcl-mode-hook #'tcl-guess-application)")
+ (add-hook \\='tcl-mode-hook #\\='tcl-guess-application)")
(defvar tcl-proc-list
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index edce3fef6cf..31d50a1882e 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -3622,10 +3622,10 @@ is 0.
Meaning of *single* declaration:
E.g. In a module's port-list -
module test(input clk, rst, x, output [1:0] y);
- Here 'input clk, rst, x' is 1 *single* declaration statement,
-and 'output [1:0] y' is the other single declaration. In the 1st single
-declaration, POINT is moved to start of 'clk'. And in the 2nd declaration,
-POINT is moved to 'y'."
+ Here `input clk, rst, x' is 1 *single* declaration statement,
+and `output [1:0] y' is the other single declaration. In the 1st single
+declaration, POINT is moved to start of `clk'. And in the 2nd declaration,
+POINT is moved to `y'."
(let (maxpoint old-point)
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index c6693b4de53..39c5eb453b1 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -153,7 +153,11 @@
(defvar lazy-lock-defer-on-scrolling)
(defvar lazy-lock-defer-on-the-fly)
(defvar speedbar-attached-frame)
-
+(defvar arch-alist)
+(defvar pack-alist)
+(defvar file-alist)
+(defvar unit-alist)
+(defvar rule-alist)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Variables
@@ -8396,30 +8400,30 @@ buffer."
((visible-list (vhdl-get-visible-signals))
;; define syntactic regions where signals are read
(scan-regions-list
- '(;; right-hand side of signal/variable assignment
+ `(;; right-hand side of signal/variable assignment
;; (special case: "<=" is relational operator in a condition)
- ((vhdl-re-search-forward "[<:]=" proc-end t)
- (vhdl-re-search-forward ";\\|\\<\\(then\\|loop\\|report\\|severity\\|is\\)\\>" proc-end t))
+ ((vhdl-re-search-forward "[<:]=" ,proc-end t)
+ (vhdl-re-search-forward ";\\|\\<\\(then\\|loop\\|report\\|severity\\|is\\)\\>" ,proc-end t))
;; if condition
- ((vhdl-re-search-forward "^\\s-*if\\>" proc-end t)
- (vhdl-re-search-forward "\\<then\\>" proc-end t))
+ ((vhdl-re-search-forward "^\\s-*if\\>" ,proc-end t)
+ (vhdl-re-search-forward "\\<then\\>" ,proc-end t))
;; elsif condition
- ((vhdl-re-search-forward "\\<elsif\\>" proc-end t)
- (vhdl-re-search-forward "\\<then\\>" proc-end t))
+ ((vhdl-re-search-forward "\\<elsif\\>" ,proc-end t)
+ (vhdl-re-search-forward "\\<then\\>" ,proc-end t))
;; while loop condition
- ((vhdl-re-search-forward "^\\s-*while\\>" proc-end t)
- (vhdl-re-search-forward "\\<loop\\>" proc-end t))
+ ((vhdl-re-search-forward "^\\s-*while\\>" ,proc-end t)
+ (vhdl-re-search-forward "\\<loop\\>" ,proc-end t))
;; exit/next condition
- ((vhdl-re-search-forward "\\<\\(exit\\|next\\)\\s-+\\w+\\s-+when\\>" proc-end t)
- (vhdl-re-search-forward ";" proc-end t))
+ ((vhdl-re-search-forward "\\<\\(exit\\|next\\)\\s-+\\w+\\s-+when\\>" ,proc-end t)
+ (vhdl-re-search-forward ";" ,proc-end t))
;; assert condition
- ((vhdl-re-search-forward "\\<assert\\>" proc-end t)
- (vhdl-re-search-forward "\\(\\<report\\>\\|\\<severity\\>\\|;\\)" proc-end t))
+ ((vhdl-re-search-forward "\\<assert\\>" ,proc-end t)
+ (vhdl-re-search-forward "\\(\\<report\\>\\|\\<severity\\>\\|;\\)" ,proc-end t))
;; case expression
- ((vhdl-re-search-forward "^\\s-*case\\>" proc-end t)
- (vhdl-re-search-forward "\\<is\\>" proc-end t))
+ ((vhdl-re-search-forward "^\\s-*case\\>" ,proc-end t)
+ (vhdl-re-search-forward "\\<is\\>" ,proc-end t))
;; parameter list of procedure call, array index
- ((and (re-search-forward "^\\s-*\\(\\w\\|\\.\\)+[ \t\n\r\f]*(" proc-end t)
+ ((and (re-search-forward "^\\s-*\\(\\w\\|\\.\\)+[ \t\n\r\f]*(" ,proc-end t)
(1- (point)))
(progn (backward-char) (forward-sexp)
(while (looking-at "(") (forward-sexp)) (point)))))
@@ -8785,7 +8789,10 @@ project is defined."
(defun vhdl-electric-period (count) "`..' --> ` => '"
(interactive "p")
(if (and vhdl-stutter-mode (= count 1) (not (vhdl-in-literal)))
- (cond ((= (preceding-char) vhdl-last-input-event)
+ ;; We use this-command-keys below to account for translation of
+ ;; kp-decimal into '.'; vhdl-last-input-event doesn't catch
+ ;; that.
+ (cond ((eq (preceding-char) (aref (this-command-keys) 0))
(progn (delete-char -1)
(unless (eq (preceding-char) ? ) (insert " "))
(insert "=> ")))
@@ -14949,10 +14956,10 @@ otherwise use cached data."
(vhdl-speedbar-expand-units directory)
(vhdl-aput 'vhdl-directory-alist directory (list (list directory))))
-(defun vhdl-speedbar-insert-hierarchy ( ent-alist-arg conf-alist-arg pack-alist
- ent-inst-list depth)
- "Insert hierarchy of ENT-ALIST, CONF-ALIST, and PACK-ALIST."
- (if (not (or ent-alist conf-alist pack-alist))
+(defun vhdl-speedbar-insert-hierarchy ( ent-alist-arg conf-alist-arg
+ package-alist ent-inst-list depth)
+ "Insert hierarchy of ENT-ALIST, CONF-ALIST, and PACKAGE-ALIST."
+ (if (not (or ent-alist conf-alist package-alist))
(vhdl-speedbar-make-title-line "No VHDL design units!" depth)
(let ((ent-alist ent-alist-arg)
(conf-alist conf-alist-arg)
@@ -14982,15 +14989,15 @@ otherwise use cached data."
'vhdl-speedbar-configuration-face depth)
(setq conf-alist (cdr conf-alist)))
;; insert packages
- (when pack-alist (vhdl-speedbar-make-title-line "Packages:" depth))
- (while pack-alist
- (setq pack-entry (car pack-alist))
+ (when package-alist (vhdl-speedbar-make-title-line "Packages:" depth))
+ (while package-alist
+ (setq pack-entry (car package-alist))
(vhdl-speedbar-make-pack-line
(nth 0 pack-entry) (nth 1 pack-entry)
(cons (nth 2 pack-entry) (nth 3 pack-entry))
(cons (nth 7 pack-entry) (nth 8 pack-entry))
depth)
- (setq pack-alist (cdr pack-alist))))))
+ (setq package-alist (cdr package-alist))))))
(declare-function speedbar-line-directory "speedbar" (&optional depth))
@@ -17209,6 +17216,7 @@ specified by a target."
(unless (or (assoc directory vhdl-file-alist)
(vhdl-load-cache directory))
(vhdl-scan-directory-contents directory))))
+ (defvar rule-alist) ; we need it to be dynamically bound
(let* ((directory (abbreviate-file-name (vhdl-default-directory)))
(project (vhdl-project-p))
(ent-alist (vhdl-aget vhdl-entity-alist (or project directory)))
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el
index 4388b0e7de0..2e8e8d23192 100644
--- a/lisp/progmodes/which-func.el
+++ b/lisp/progmodes/which-func.el
@@ -64,7 +64,7 @@
;; Variables for customization
;; ---------------------------
;;
-(defvar which-func-unknown "???"
+(defvar which-func-unknown "n/a"
"String to display in the mode line when current function is unknown.")
(defgroup which-func nil
@@ -216,7 +216,7 @@ It creates the Imenu index for the buffer, if necessary."
(setq which-func-mode nil))))
(defun which-func-update ()
- "Update the Which-Function mode display for all windows."
+ "Update the Which-Function mode display in the current window."
;; (walk-windows 'which-func-update-1 nil 'visible))
(let ((non-essential t))
(which-func-update-1 (selected-window))))
@@ -234,9 +234,6 @@ It creates the Imenu index for the buffer, if necessary."
(setq which-func-mode nil)
(error "Error in which-func-update: %S" info))))))
-;;;###autoload
-(define-obsolete-function-alias 'which-func-mode 'which-function-mode "24.1")
-
(defvar which-func-update-timer nil)
(unless (or (assq 'which-func-mode mode-line-misc-info)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 9ce63a8f8a1..0213ab3cc58 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
-;; Version: 1.3.2
+;; Version: 1.4.1
;; Package-Requires: ((emacs "26.1"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -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))
@@ -227,7 +227,7 @@ This behavior is new in Emacs 28.")
"A match xref item describes a search result."
length)
-(cl-defgeneric xref-match-length ((item xref-match-item))
+(cl-defmethod xref-match-length ((item xref-match-item))
"Return the length of the match."
(xref-match-item-length item))
@@ -381,7 +381,8 @@ elements is negated: these commands will NOT prompt."
(defcustom xref-after-jump-hook '(recenter
xref-pulse-momentarily)
- "Functions called after jumping to an xref."
+ "Functions called after jumping to an xref.
+Also see `xref-current-item'."
:type 'hook)
(defcustom xref-after-return-hook '(xref-pulse-momentarily)
@@ -426,7 +427,7 @@ or earlier: it can break `dired-do-find-regexp-and-replace'."
:version "28.1"
:package-version '(xref . "1.2.0"))
-(make-obsolete-variable 'xref-marker-ring nil "29.1")
+(make-obsolete-variable 'xref--marker-ring 'xref--history "29.1")
(defun xref-set-marker-ring-length (_var _val)
(declare (obsolete nil "29.1"))
@@ -485,13 +486,20 @@ To undo, use \\[xref-go-forward]."
(set-marker marker nil nil)
(run-hooks 'xref-after-return-hook))))
-(defvar xref--current-item nil)
+(define-obsolete-variable-alias
+ 'xref--current-item
+ 'xref-current-item
+ "29.1")
+
+(defvar xref-current-item nil
+ "Dynamically bound to the current item being processed.
+This can be used from `xref-after-jump-hook', for instance.")
(defun xref-pulse-momentarily ()
(pcase-let ((`(,beg . ,end)
(save-excursion
(or
- (let ((length (xref-match-length xref--current-item)))
+ (let ((length (xref-match-length xref-current-item)))
(and length (cons (point) (+ (point) length))))
(back-to-indentation)
(if (eolp)
@@ -548,7 +556,7 @@ If SELECT is non-nil, select the target window."
(window (pop-to-buffer buf t))
(frame (let ((pop-up-frames t)) (pop-to-buffer buf t))))
(xref--goto-char marker))
- (let ((xref--current-item item))
+ (let ((xref-current-item item))
(run-hooks 'xref-after-jump-hook)))
@@ -637,9 +645,15 @@ SELECT is `quit', also quit the *xref* window."
(xref-buffer (current-buffer)))
(cond (select
(if (eq select 'quit) (quit-window nil nil))
- (select-window
- (with-current-buffer xref-buffer
- (xref--show-pos-in-buf marker buf))))
+ (let* ((old-frame (selected-frame))
+ (window (with-current-buffer xref-buffer
+ (xref--show-pos-in-buf marker buf)))
+ (frame (window-frame window)))
+ ;; If we chose another frame, make sure it gets input
+ ;; focus.
+ (unless (eq frame old-frame)
+ (select-frame-set-input-focus frame))
+ (select-window window)))
(t
(save-selected-window
(xref--with-dedicated-window
@@ -656,7 +670,7 @@ SELECT is `quit', also quit the *xref* window."
"Display the source of xref at point in the appropriate window, if any."
(interactive)
(let* ((xref (xref--item-at-point))
- (xref--current-item xref))
+ (xref-current-item xref))
(when xref
(xref--set-arrow)
(xref--show-location (xref-item-location xref)))))
@@ -715,7 +729,7 @@ quit the *xref* buffer."
(let* ((buffer (current-buffer))
(xref (or (xref--item-at-point)
(user-error "Choose a reference to visit")))
- (xref--current-item xref))
+ (xref-current-item xref))
(xref--set-arrow)
(xref--show-location (xref-item-location xref) (if quit 'quit t))
(if (fboundp 'next-error-found)
@@ -738,11 +752,25 @@ quit the *xref* buffer."
"Perform interactive replacement of FROM with TO in all displayed xrefs.
This command interactively replaces FROM with TO in the names of the
-references displayed in the current *xref* buffer."
+references displayed in the current *xref* buffer.
+
+When called interactively, it uses '.*' as FROM, which means
+replace the whole name. Unless called with prefix argument, in
+which case the user is prompted for both FROM and TO.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time."
(interactive
- (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
- (list fr
- (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
+ (let* ((fr
+ (if current-prefix-arg
+ (read-regexp "Query-replace (regexp)" ".*")
+ ".*"))
+ (prompt (if current-prefix-arg
+ (format "Query-replace (regexp) %s with: " fr)
+ "Query-replace all matches with: ")))
+ (list fr (read-regexp prompt))))
(let* (item xrefs iter)
(save-excursion
(while (setq item (xref--search-property 'xref-item))
@@ -936,15 +964,15 @@ beginning of the line."
(let ((win (get-buffer-window (current-buffer))))
(and win (set-window-point win (point))))
(xref--set-arrow)
- (let ((xref--current-item xref))
+ (let ((xref-current-item xref))
(xref--show-location (xref-item-location xref) t)))
(t
(error "No %s xref" (if backward "previous" "next"))))))
(defvar xref--button-map
(let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] #'xref-goto-xref)
- (define-key map [mouse-2] #'xref-select-and-show-xref)
+ (define-key map [follow-link] 'mouse-face)
+ (define-key map [mouse-2] #'xref-goto-xref)
map))
(defun xref-select-and-show-xref (event)
@@ -1093,6 +1121,13 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)."
(cdr pair)))
alist)))
+(defun xref--ensure-default-directory (dd buffer)
+ ;; We might be in a let-binding which will restore the current value
+ ;; to a previous one (bug#53626). So do this later.
+ (run-with-timer
+ 0 nil
+ (lambda () (with-current-buffer buffer (setq default-directory dd)))))
+
(defun xref--show-xref-buffer (fetcher alist)
(cl-assert (functionp fetcher))
(let* ((xrefs
@@ -1103,7 +1138,7 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)."
(dd default-directory)
buf)
(with-current-buffer (get-buffer-create xref-buffer-name)
- (setq default-directory dd)
+ (xref--ensure-default-directory dd (current-buffer))
(xref--xref-buffer-mode)
(xref--show-common-initialize xref-alist fetcher alist)
(pop-to-buffer (current-buffer))
@@ -1202,7 +1237,7 @@ local keymap that binds `RET' to `xref-quit-and-goto-xref'."
(assoc-default 'display-action alist)))
(t
(with-current-buffer (get-buffer-create xref-buffer-name)
- (setq default-directory dd)
+ (xref--ensure-default-directory dd (current-buffer))
(xref--transient-buffer-mode)
(xref--show-common-initialize (xref--analyze xrefs) fetcher alist)
(pop-to-buffer (current-buffer)
@@ -1326,6 +1361,13 @@ definitions."
(defvar xref--read-pattern-history nil)
+;;;###autoload
+(defun xref-show-xrefs (fetcher display-action)
+ "Display some Xref values produced by FETCHER using DISPLAY-ACTION.
+The meanings of both arguments are the same as documented in
+`xref-show-xrefs-function'."
+ (xref--show-xrefs fetcher display-action))
+
(defun xref--show-xrefs (fetcher display-action &optional _always-show-list)
(xref--push-markers)
(unless (functionp fetcher)
@@ -1469,6 +1511,23 @@ is nil, prompt only if there's no usable symbol at point."
(interactive (list (xref--read-identifier "Find references of: ")))
(xref--find-xrefs identifier 'references identifier nil))
+(defun xref-find-references-and-replace (from to)
+ "Replace all references to identifier FROM with TO."
+ (interactive
+ (let* ((query-replace-read-from-default 'find-tag-default)
+ (common
+ (query-replace-read-args "Query replace identifier" nil)))
+ (list (nth 0 common) (nth 1 common))))
+ (require 'xref)
+ (with-current-buffer
+ (let ((xref-show-xrefs-function
+ ;; Some future-proofing (bug#44905).
+ (custom--standard-value 'xref-show-xrefs-function))
+ ;; Disable auto-jumping, it will mess up replacement logic.
+ xref-auto-jump-to-first-xref)
+ (xref-find-references from))
+ (xref-query-replace-in-results ".*" to)))
+
;;;###autoload
(defun xref-find-definitions-at-mouse (event)
"Find the definition of identifier at or around mouse click.
@@ -1496,7 +1555,7 @@ This command is intended to be bound to a mouse event."
(xref-find-references identifier))
(user-error "No identifier here"))))
-(declare-function apropos-parse-pattern "apropos" (pattern))
+(declare-function apropos-parse-pattern "apropos" (pattern &optional do-all))
;;;###autoload
(defun xref-find-apropos (pattern)
@@ -1669,8 +1728,9 @@ IGNORES is a list of glob patterns for files to ignore."
(ripgrep
.
;; '!*/' is there to filter out dirs (e.g. submodules).
- "xargs -0 rg <C> --null -nH --no-messages -g '!*/' -e <R>"
- ))
+ "xargs -0 rg <C> --null -nH --no-heading --no-messages -g '!*/' -e <R>"
+ )
+ (ugrep . "xargs -0 ugrep <C> --null -ns -e <R>"))
"Associative list mapping program identifiers to command templates.
Program identifier should be a symbol, named after the search program.
@@ -1699,6 +1759,7 @@ utility function used by commands like `dired-do-find-regexp' and
:type '(choice
(const :tag "Use Grep" grep)
(const :tag "Use ripgrep" ripgrep)
+ (const :tag "Use ugrep" ugrep)
(symbol :tag "User defined"))
:version "28.1"
:package-version '(xref . "1.0.4"))
@@ -1818,7 +1879,7 @@ to control which program to use when looking for matches."
(xref--find-ignores-arguments ignores dir)))
(defun xref--find-ignores-arguments (ignores dir)
- "Convert IGNORES and DIR to a list of arguments for 'find'.
+ "Convert IGNORES and DIR to a list of arguments for `find'.
IGNORES is a list of glob patterns. DIR is an absolute
directory, used as the root of the ignore globs."
(cl-assert (not (string-match-p "\\`~" dir)))
@@ -1878,21 +1939,22 @@ Such as the current syntax table and the applied syntax properties."
(defvar xref--last-file-buffer nil)
(defvar xref--temp-buffer-file-name nil)
+(defvar xref--hits-remote-id nil)
(defun xref--convert-hits (hits regexp)
(let (xref--last-file-buffer
(tmp-buffer (generate-new-buffer " *xref-temp*"))
- (remote-id (file-remote-p default-directory))
+ (xref--hits-remote-id (file-remote-p default-directory))
(syntax-needed (xref--regexp-syntax-dependent-p regexp)))
(unwind-protect
(mapcan (lambda (hit)
- (xref--collect-matches hit regexp tmp-buffer remote-id syntax-needed))
+ (xref--collect-matches hit regexp tmp-buffer syntax-needed))
hits)
(kill-buffer tmp-buffer))))
-(defun xref--collect-matches (hit regexp tmp-buffer remote-id syntax-needed)
+(defun xref--collect-matches (hit regexp tmp-buffer syntax-needed)
(pcase-let* ((`(,line ,file ,text) hit)
- (file (and file (concat remote-id file)))
+ (file (and file (concat xref--hits-remote-id file)))
(buf (xref--find-file-buffer file))
(inhibit-modification-hooks t))
(if buf
@@ -1965,10 +2027,17 @@ Such as the current syntax table and the applied syntax properties."
(defun xref--find-file-buffer (file)
(unless (equal (car xref--last-file-buffer) file)
- (setq xref--last-file-buffer
- ;; `find-buffer-visiting' is considerably slower,
- ;; especially on remote files.
- (cons file (get-file-buffer file))))
+ ;; `find-buffer-visiting' is considerably slower,
+ ;; especially on remote files.
+ (let ((buf (get-file-buffer file)))
+ (when (and buf
+ (or
+ (buffer-modified-p buf)
+ (unless xref--hits-remote-id
+ (not (verify-visited-file-modtime (current-buffer))))))
+ ;; We can't use buffers whose contents diverge from disk (bug#54025).
+ (setq buf nil))
+ (setq xref--last-file-buffer (cons file buf))))
(cdr xref--last-file-buffer))
(provide 'xref)
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
index 8df5204fa12..069d116907e 100644
--- a/lisp/ps-print.el
+++ b/lisp/ps-print.el
@@ -6415,7 +6415,7 @@ If FACE is not a valid face name, use default face."
(ps-end-job needs-begin-file)
;; Setting this variable tells the unwind form that the
- ;; the PostScript was generated without error.
+ ;; PostScript was generated without error.
(setq completed-safely t))
;; Unwind form: If some bad mojo occurred while generating
diff --git a/lisp/recentf.el b/lisp/recentf.el
index 5e2f2218614..b80ee3dd7d8 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1,4 +1,4 @@
-;;; recentf.el --- setup a menu of recently opened files -*- lexical-binding: t -*-
+;;; recentf.el --- keep track of recently opened files -*- lexical-binding: t -*-
;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
@@ -23,13 +23,22 @@
;;; Commentary:
-;; This package maintains a menu for visiting files that were operated
-;; on recently. When enabled a new "Open Recent" submenu is
-;; displayed in the "File" menu. The recent files list is
-;; automatically saved across Emacs sessions.
+;; This package maintains a list of recently opened files and makes it
+;; easy to visit them. The recent files list is automatically saved
+;; across Emacs sessions.
+
+;; There are three ways to access recent files:
+;;
+;; (1) `M-x recentf-open' prompts for a recently opened file.
+;;
+;; (2) When this mode is enabled, a new "Open Recent" submenu is
+;; displayed in the "File" menu.
+;;
+;; (3) `M-x recentf-open-files' lists recently visited files in a
+;; buffer.
;; You can customize the number of recent files displayed, the
-;; location of the menu and others options. Type:
+;; location of the menu and other options. Type:
;;
;; M-x customize-group RET recentf RET
@@ -45,16 +54,17 @@
;;; Internal data
;;
(defvar recentf-list nil
- "List of recently opened files.")
+ "List of recently opened files for `recentf-mode'.")
-(defsubst recentf-enabled-p ()
- "Return non-nil if recentf mode is currently enabled."
+(defun recentf-enabled-p ()
+ "Return non-nil if `recentf-mode' is currently enabled."
(memq 'recentf-save-list kill-emacs-hook))
+
;;; Customization
;;
(defgroup recentf nil
- "Maintain a menu of recently opened files."
+ "Maintain a list of recently opened files."
:version "21.1"
:group 'files)
@@ -159,7 +169,7 @@ If nil add it at end of menu (see also `easy-menu-add-item')."
(const :tag "Last" nil))
:set 'recentf-menu-customization-changed)
-(defcustom recentf-menu-action 'find-file
+(defcustom recentf-menu-action #'find-file
"Function to invoke with a filename item of the recentf menu.
The default is to call `find-file' to edit the selected file."
:group 'recentf
@@ -168,7 +178,7 @@ The default is to call `find-file' to edit the selected file."
(defcustom recentf-max-menu-items 10
"Maximum number of items in the recentf menu."
:group 'recentf
- :type 'integer)
+ :type 'natnum)
(defcustom recentf-menu-filter nil
"Function used to filter files displayed in the recentf menu.
@@ -237,6 +247,8 @@ This item will replace the \"More...\" item."
(defcustom recentf-auto-cleanup 'mode
"Define when to automatically cleanup the recent list.
+That is, remove duplicates, non-kept, and excluded files.
+
The following values can be set:
- `mode'
@@ -284,7 +296,7 @@ If `file-name-history' is not empty, do nothing."
(make-obsolete-variable 'recentf-load-hook
"use `with-eval-after-load' instead." "28.1")
-(defcustom recentf-filename-handlers nil
+(defcustom recentf-filename-handlers '(abbreviate-file-name)
"Functions to post process recent file names.
They are successively passed a file name to transform it."
:group 'recentf
@@ -294,7 +306,8 @@ They are successively passed a file name to transform it."
(choice
(const file-truename)
(const abbreviate-file-name)
- (function :tag "Other function")))))
+ (function :tag "Other function"))))
+ :version "29.1")
(defcustom recentf-show-file-shortcuts-flag t
"Non-nil means to show \"[N]\" for the Nth item up to 10.
@@ -309,14 +322,14 @@ used as shortcuts to open the Nth file."
(memq system-type '(windows-nt cygwin))
"Non-nil if recentf searches and matches should ignore case.")
-(defsubst recentf-string-equal (s1 s2)
+(defun recentf-string-equal (s1 s2)
"Return non-nil if strings S1 and S2 have identical contents.
Ignore case if `recentf-case-fold-search' is non-nil."
(if recentf-case-fold-search
(string-equal (downcase s1) (downcase s2))
(string-equal s1 s2)))
-(defsubst recentf-string-lessp (s1 s2)
+(defun recentf-string-lessp (s1 s2)
"Return non-nil if string S1 is less than S2 in lexicographic order.
Ignore case if `recentf-case-fold-search' is non-nil."
(if recentf-case-fold-search
@@ -371,7 +384,7 @@ See also the option `recentf-auto-cleanup'.")
;;; File functions
;;
-(defsubst recentf-push (filename)
+(defun recentf-push (filename)
"Push FILENAME into the recent list, if it isn't there yet.
If it is there yet, move it at the beginning of the list.
If `recentf-case-fold-search' is non-nil, ignore case when comparing
@@ -394,7 +407,7 @@ returned nil."
(error nil))
name))
-(defsubst recentf-expand-file-name (name)
+(defun recentf-expand-file-name (name)
"Convert file NAME to absolute, and canonicalize it.
NAME is first passed to the function `expand-file-name', then to
`recentf-filename-handlers' to post process it."
@@ -435,7 +448,7 @@ That is, if it matches any of the `recentf-keep' checks."
checks (cdr checks)))
keepit))
-(defsubst recentf-add-file (filename)
+(defun recentf-add-file (filename)
"Add or move FILENAME at the beginning of the recent list.
Does nothing if the name satisfies any of the `recentf-exclude'
regexps or predicates."
@@ -443,7 +456,7 @@ regexps or predicates."
(when (recentf-include-p filename)
(recentf-push filename)))
-(defsubst recentf-remove-if-non-kept (filename)
+(defun recentf-remove-if-non-kept (filename)
"Remove FILENAME from the recent list, if file is not kept.
Return non-nil if FILENAME has been removed."
(unless (recentf-keep-p filename)
@@ -461,10 +474,30 @@ Return non-nil if F1 is less than F2."
(recentf-string-lessp (file-name-nondirectory f1)
(file-name-nondirectory f2))
(recentf-string-lessp d1 d2))))
+
+
+;;; Open files
+;;
+
+;;;###autoload
+(defun recentf-open (file)
+ "Prompt for FILE in `recentf-list' and visit it.
+Enable `recentf-mode' if it isn't already."
+ (interactive
+ (list
+ (progn (unless recentf-mode (recentf-mode 1))
+ (completing-read (format-prompt "Open recent file" nil)
+ recentf-list nil t))))
+ (when file
+ (funcall recentf-menu-action file)))
+
+;;;###autoload
+(defalias 'recentf 'recentf-open)
+
;;; Menu building
;;
-(defsubst recentf-digit-shortcut-command-name (n)
+(defun recentf-digit-shortcut-command-name (n)
"Return a command name to open the Nth most recent file.
See also the command `recentf-open-most-recent-file'."
(intern (format "recentf-open-most-recent-file-%d" n)))
@@ -476,10 +509,10 @@ See also the command `recentf-open-most-recent-file'."
;; Define a shortcut command.
(defalias cmd
`(lambda ()
- (interactive)
+ (interactive nil recentf-dialog-mode)
(recentf-open-most-recent-file ,k)))
;; Bind it to a digit key.
- (define-key km (vector (+ k ?0)) cmd)))
+ (keymap-set km (format "%d" k) cmd)))
km)
"Digit shortcuts keymap.")
@@ -510,10 +543,6 @@ If non-nil it must contain a list of valid menu-items to be appended
to the recent file list part of the menu. Before calling a menu
filter function this variable is reset to nil.")
-(defsubst recentf-elements (n)
- "Return a list of the first N elements of the recent list."
- (seq-take recentf-list n))
-
(defsubst recentf-make-menu-element (menu-item menu-value)
"Create a new menu-element.
A menu element is a pair (MENU-ITEM . MENU-VALUE), where MENU-ITEM is
@@ -553,7 +582,7 @@ This a menu element (FILE . FILE)."
"Return a list of the first N default menu elements from the recent list.
See also `recentf-make-default-menu-element'."
(mapcar #'recentf-make-default-menu-element
- (recentf-elements n)))
+ (seq-take recentf-list n)))
(defun recentf-apply-menu-filter (filter l)
"Apply function FILTER to the list of menu-elements L.
@@ -650,7 +679,7 @@ Return nil if file NAME is not one of the ten more recent."
:help (concat "Open " value)
:active t)))))
-(defsubst recentf-menu-bar ()
+(defun recentf-menu-bar ()
"Return the keymap of the global menu bar."
(lookup-key global-map [menu-bar]))
@@ -670,7 +699,7 @@ Return nil if file NAME is not one of the ten more recent."
;;; Predefined menu filters
;;
-(defsubst recentf-sort-ascending (l)
+(defun recentf-sort-ascending (l)
"Sort the list of menu elements L in ascending order.
The MENU-ITEM part of each menu element is compared."
(sort (copy-sequence l)
@@ -679,7 +708,7 @@ The MENU-ITEM part of each menu element is compared."
(recentf-menu-element-item e1)
(recentf-menu-element-item e2)))))
-(defsubst recentf-sort-descending (l)
+(defun recentf-sort-descending (l)
"Sort the list of menu elements L in descending order.
The MENU-ITEM part of each menu element is compared."
(sort (copy-sequence l)
@@ -688,7 +717,7 @@ The MENU-ITEM part of each menu element is compared."
(recentf-menu-element-item e2)
(recentf-menu-element-item e1)))))
-(defsubst recentf-sort-basenames-ascending (l)
+(defun recentf-sort-basenames-ascending (l)
"Sort the list of menu elements L in ascending order.
Only filenames sans directory are compared."
(sort (copy-sequence l)
@@ -697,7 +726,7 @@ Only filenames sans directory are compared."
(file-name-nondirectory (recentf-menu-element-value e1))
(file-name-nondirectory (recentf-menu-element-value e2))))))
-(defsubst recentf-sort-basenames-descending (l)
+(defun recentf-sort-basenames-descending (l)
"Sort the list of menu elements L in descending order.
Only filenames sans directory are compared."
(sort (copy-sequence l)
@@ -706,7 +735,7 @@ Only filenames sans directory are compared."
(file-name-nondirectory (recentf-menu-element-value e2))
(file-name-nondirectory (recentf-menu-element-value e1))))))
-(defsubst recentf-sort-directories-ascending (l)
+(defun recentf-sort-directories-ascending (l)
"Sort the list of menu elements L in ascending order.
Compares directories then filenames to order the list."
(sort (copy-sequence l)
@@ -715,7 +744,7 @@ Compares directories then filenames to order the list."
(recentf-menu-element-value e1)
(recentf-menu-element-value e2)))))
-(defsubst recentf-sort-directories-descending (l)
+(defun recentf-sort-directories-descending (l)
"Sort the list of menu elements L in descending order.
Compares directories then filenames to order the list."
(sort (copy-sequence l)
@@ -743,14 +772,14 @@ optional argument NO-DIR is non-nil, or its directory otherwise."
(setq name (format "%s(%s)" name sufx)))
(push (recentf-make-menu-element name full) filtered-list))))
-(defsubst recentf-show-basenames-ascending (l)
+(defun recentf-show-basenames-ascending (l)
"Filter the list of menu elements L to show filenames sans directory.
Filenames are sorted in ascending order.
This filter combines the `recentf-sort-basenames-ascending' and
`recentf-show-basenames' filters."
(recentf-show-basenames (recentf-sort-basenames-ascending l)))
-(defsubst recentf-show-basenames-descending (l)
+(defun recentf-show-basenames-descending (l)
"Filter the list of menu elements L to show filenames sans directory.
Filenames are sorted in descending order.
This filter combines the `recentf-sort-basenames-descending' and
@@ -808,7 +837,7 @@ corresponding sub-menu items are displayed in the main recent files
menu or in the `recentf-arrange-by-rule-others' sub-menu if
defined."
:group 'recentf-filters
- :type 'number)
+ :type 'natnum)
(defcustom recentf-arrange-by-rule-subfilter nil
"Function called by a rule based filter to filter sub-menu elements.
@@ -1037,7 +1066,7 @@ That is, remove a non kept file from the recent list."
(defun recentf-cancel-dialog (&rest _ignore)
"Cancel the current dialog.
IGNORE arguments."
- (interactive)
+ (interactive nil recentf-dialog-mode)
(kill-buffer (current-buffer))
(message "Dialog canceled"))
@@ -1055,19 +1084,20 @@ Go to the beginning of buffer if not found."
(error
(goto-char (point-min)))))
-(defvar recentf-dialog-mode-map
- (let ((km (copy-keymap recentf--shortcuts-keymap)))
- (set-keymap-parent km widget-keymap)
- (define-key km "q" #'recentf-cancel-dialog)
- (define-key km "n" #'next-line)
- (define-key km "p" #'previous-line)
- km)
- "Keymap used in recentf dialogs.")
+(defvar-keymap recentf-dialog-mode-map
+ :doc "Keymap used in recentf dialogs."
+ :parent (make-composed-keymap recentf--shortcuts-keymap widget-keymap)
+ "q" #'recentf-cancel-dialog
+ "n" #'next-line
+ "p" #'previous-line
+ "C-c C-c" #'recentf-edit-list-validate
+ "C-c C-k" #'recentf-cancel-dialog)
(define-derived-mode recentf-dialog-mode nil "recentf-dialog"
"Major mode of recentf dialogs.
\\{recentf-dialog-mode-map}"
+ :interactive nil
:syntax-table nil
:abbrev-table nil
(setq truncate-lines t))
@@ -1104,6 +1134,7 @@ IGNORE other arguments."
(defun recentf-edit-list-validate (&rest _ignore)
"Process the recent list when the edit list dialog is committed.
IGNORE arguments."
+ (interactive nil recentf-dialog-mode)
(if recentf-edit-list
(let ((i 0))
(dolist (e recentf-edit-list)
@@ -1123,8 +1154,8 @@ IGNORE arguments."
(widget-insert
(format-message
(substitute-command-keys
- "Click on OK to delete selected files from the recent list.
-Click on Cancel or type \\[recentf-cancel-dialog] to cancel.\n")))
+ "Click on \"OK\" or type \\[recentf-edit-list-validate] to delete selected files from the recent list.
+Click on \"Cancel\" or type \\[recentf-cancel-dialog] to cancel.\n")))
;; Insert the list of files as checkboxes
(dolist (item recentf-list)
(widget-create 'checkbox
@@ -1337,12 +1368,18 @@ That is, remove duplicates, non-kept, and excluded files."
;;; The minor mode
;;
-(defvar recentf-mode-map (make-sparse-keymap)
- "Keymap to use in recentf mode.")
+(defvar-keymap recentf-mode-map
+ :doc "Keymap to use in `recentf-mode'.")
;;;###autoload
(define-minor-mode recentf-mode
- "Toggle \"Open Recent\" menu (Recentf mode).
+ "Toggle keeping track of opened files (Recentf mode).
+This mode maintains a list of recently opened files and makes it
+easy to visit them. The recent files list is automatically saved
+across Emacs sessions.
+
+You can use `recentf-open' or `recentf-open-files' to visit
+files.
When Recentf mode is enabled, a \"Open Recent\" submenu is
displayed in the \"File\" menu, containing a list of files that
@@ -1353,7 +1390,7 @@ to a file, and killing a buffer is counted as \"operating\" on
the file. If instead you want to prioritize files that appear in
buffers you switch to a lot, you can say something like the following:
- (add-hook 'buffer-list-update-hook 'recentf-track-opened-file)"
+ (add-hook \\='buffer-list-update-hook #\\='recentf-track-opened-file)"
:global t
:group 'recentf
:keymap recentf-mode-map
@@ -1379,6 +1416,11 @@ buffers you switch to a lot, you can say something like the following:
(define-obsolete-function-alias 'recentf-trunc-list #'seq-take "28.1")
+(defun recentf-elements (n)
+ "Return a list of the first N elements of the recent list."
+ (declare (obsolete "use `(seq-take recentf-list n)'." "29.1"))
+ (seq-take recentf-list n))
+
(provide 'recentf)
(run-hooks 'recentf-load-hook)
diff --git a/lisp/rect.el b/lisp/rect.el
index 15d636f074e..e717d2ac7e1 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -656,6 +656,8 @@ on. Only lasts until the region is next deactivated."
:lighter nil
(rectangle--reset-crutches)
(when rectangle-mark-mode
+ (advice-add 'region-beginning :around #'rectangle--region-beginning)
+ (advice-add 'region-end :around #'rectangle--region-end)
(add-hook 'deactivate-mark-hook
(lambda () (rectangle-mark-mode -1)))
(unless (region-active-p)
@@ -754,17 +756,38 @@ Ignores `line-move-visual'."
(rectangle--col-pos col 'point)))
+(defun rectangle--region-beginning (orig)
+ "Like `region-beginning' but supports rectangular regions."
+ (cond
+ ((not rectangle-mark-mode)
+ (funcall orig))
+ (t
+ (apply #'min (mapcar #'car (region-bounds))))))
+
+(defun rectangle--region-end (orig)
+ "Like `region-end' but supports rectangular regions."
+ (cond
+ ((not rectangle-mark-mode)
+ (funcall orig))
+ (t
+ (apply #'max (mapcar #'cdr (region-bounds))))))
+
(defun rectangle--extract-region (orig &optional delete)
(cond
((not rectangle-mark-mode)
(funcall orig delete))
((eq delete 'bounds)
- (extract-rectangle-bounds (region-beginning) (region-end)))
+ (extract-rectangle-bounds
+ ;; Avoid recursive calls from advice
+ (let (rectangle-mark-mode) (region-beginning))
+ (let (rectangle-mark-mode) (region-end))))
(t
(let* ((strs (funcall (if delete
#'delete-extract-rectangle
#'extract-rectangle)
- (region-beginning) (region-end)))
+ ;; Avoid recursive calls from advice
+ (let (rectangle-mark-mode) (region-beginning))
+ (let (rectangle-mark-mode) (region-end))))
(str (mapconcat #'identity strs "\n")))
(when (eq last-command 'kill-region)
;; Try to prevent kill-region from appending this to some
diff --git a/lisp/repeat.el b/lisp/repeat.el
index aaccc22784d..a32f3a4c507 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -176,7 +176,7 @@ that variable on the theory they're doing more good than harm; `repeat' does
that, and usually does do more good than harm. However, like all do-gooders,
sometimes `repeat' gets surprising results from its altruism. The value of
this function is always whether the value of `this-command' would've been
-'repeat if `repeat' hadn't modified it."
+`repeat' if `repeat' hadn't modified it."
(= repeat-num-input-keys-at-repeat num-input-keys))
;; An example of the use of (repeat-is-really-this-command) may still be
@@ -368,8 +368,8 @@ When non-nil and the last typed key (with or without modifiers)
doesn't exist in the keymap attached by the `repeat-map' property,
then don't activate that keymap for the next command. So only the
same keys among repeatable keys are allowed in the repeating sequence.
-For example, with a non-nil value, only `C-x u u' repeats undo,
-whereas `C-/ u' doesn't.
+For example, with a non-nil value, only \\`C-x u u' repeats undo,
+whereas \\`C-/ u' doesn't.
You can also set the property `repeat-check-key' on the command symbol.
This property can override the value of this variable.
@@ -418,7 +418,7 @@ See `describe-repeat-maps' for a list of all repeatable commands."
(and (commandp s)
(get s 'repeat-map)
(push (get s 'repeat-map) keymaps))))))
- (message "Repeat mode is enabled for %d commands and %d keymaps; see `describe-repeat-maps'."
+ (message "Repeat mode is enabled for %d commands and %d keymaps; see `describe-repeat-maps'"
(length commands)
(length (delete-dups keymaps))))))
@@ -500,14 +500,17 @@ See `describe-repeat-maps' for a list of all repeatable commands."
(defun repeat-echo-message-string (keymap)
"Return a string with a list of repeating keys."
(let (keys)
- (map-keymap (lambda (key _) (push key keys)) keymap)
+ (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap)
(format-message "Repeat with %s%s"
(mapconcat (lambda (key)
- (key-description (vector key)))
+ (substitute-command-keys
+ (format "\\`%s'"
+ (key-description (vector key)))))
keys ", ")
(if repeat-exit-key
- (format ", or exit with %s"
- (key-description repeat-exit-key))
+ (substitute-command-keys
+ (format ", or exit with \\`%s'"
+ (key-description repeat-exit-key)))
""))))
(defun repeat-echo-message (keymap)
@@ -557,21 +560,28 @@ Used in `repeat-mode'."
(push s (alist-get (get s 'repeat-map) keymaps)))))
(with-help-window (help-buffer)
(with-current-buffer standard-output
- (princ "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n")
-
- (dolist (keymap (sort keymaps (lambda (a b) (string-lessp (car a) (car b)))))
- (princ (format-message "`%s' keymap is repeatable by these commands:\n"
- (car keymap)))
- (dolist (command (sort (cdr keymap) 'string-lessp))
+ (insert "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n")
+
+ (dolist (keymap (sort keymaps (lambda (a b)
+ (when (and (symbolp (car a))
+ (symbolp (car b)))
+ (string-lessp (car a) (car b))))))
+ (insert (format-message
+ "`%s' keymap is repeatable by these commands:\n"
+ (car keymap)))
+ (dolist (command (sort (cdr keymap) #'string-lessp))
(let* ((info (help-fns--analyze-function command))
- (map (list (symbol-value (car keymap))))
+ (map (list (if (symbolp (car keymap))
+ (symbol-value (car keymap))
+ (car keymap))))
(desc (mapconcat (lambda (key)
- (format-message "`%s'" (key-description key)))
+ (propertize (key-description key)
+ 'face 'help-key-binding))
(or (where-is-internal command map)
(where-is-internal (nth 3 info) map))
", ")))
- (princ (format-message " `%s' (bound to %s)\n" command desc))))
- (princ "\n")))))))
+ (insert (format-message " `%s' (bound to %s)\n" command desc))))
+ (insert "\n")))))))
(provide 'repeat)
diff --git a/lisp/replace.el b/lisp/replace.el
index 60e507c6429..54ee64f64a5 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -30,6 +30,7 @@
(require 'text-mode)
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
(defcustom case-replace t
"Non-nil means `query-replace' should preserve case in replacements."
@@ -186,6 +187,12 @@ See `replace-regexp' and `query-replace-regexp-eval'.")
length)
length)))))
+(defvar query-replace-read-from-default nil
+ "Function to get default non-regexp value for `query-replace-read-from'.")
+
+(defvar query-replace-read-from-regexp-default nil
+ "Function to get default regexp value for `query-replace-read-from'.")
+
(defun query-replace-read-from-suggestions ()
"Return a list of standard suggestions for `query-replace-read-from'.
By default, the list includes the active region, the identifier
@@ -233,8 +240,12 @@ wants to replace FROM with TO."
query-replace-defaults))
(symbol-value query-replace-from-history-variable)))
(minibuffer-allow-text-properties t) ; separator uses text-properties
+ (default (when (and query-replace-read-from-default (not regexp-flag))
+ (funcall query-replace-read-from-default)))
(prompt
- (cond ((and query-replace-defaults separator)
+ (cond ((and query-replace-read-from-regexp-default regexp-flag) prompt)
+ (default (format-prompt prompt default))
+ ((and query-replace-defaults separator)
(format-prompt prompt (car minibuffer-history)))
(query-replace-defaults
(format-prompt
@@ -255,16 +266,26 @@ wants to replace FROM with TO."
(append '((separator . t) (face . t))
text-property-default-nonsticky)))
(if regexp-flag
- (read-regexp prompt nil 'minibuffer-history)
+ (read-regexp
+ (if query-replace-read-from-regexp-default
+ (string-remove-suffix ": " prompt)
+ prompt)
+ query-replace-read-from-regexp-default
+ 'minibuffer-history)
(read-from-minibuffer
prompt nil nil nil nil
- (query-replace-read-from-suggestions) t)))))
+ (if default
+ (delete-dups
+ (cons default (query-replace-read-from-suggestions)))
+ (query-replace-read-from-suggestions))
+ t)))))
(to))
- (if (and (zerop (length from)) query-replace-defaults)
+ (if (and (zerop (length from)) query-replace-defaults (not default))
(cons (caar query-replace-defaults)
(query-replace-compile-replacement
(cdar query-replace-defaults) regexp-flag))
- (setq from (query-replace--split-string from))
+ (setq from (or (and (zerop (length from)) default)
+ (query-replace--split-string from)))
(when (consp from) (setq to (cdr from) from (car from)))
(add-to-history query-replace-from-history-variable from nil t)
;; Warn if user types \n or \t, but don't reject the input.
@@ -345,11 +366,33 @@ should a regexp."
(unless noerror
(barf-if-buffer-read-only))
(save-mark-and-excursion
- (let* ((from (query-replace-read-from prompt regexp-flag))
+ (let* ((delimited-flag (and current-prefix-arg
+ (not (eq current-prefix-arg '-))))
+ (from (minibuffer-with-setup-hook
+ (minibuffer-lazy-highlight-setup
+ :case-fold case-fold-search
+ :filter (when (use-region-p)
+ (replace--region-filter
+ (funcall region-extract-function 'bounds)))
+ :highlight query-replace-lazy-highlight
+ :regexp regexp-flag
+ :regexp-function (or replace-regexp-function
+ delimited-flag
+ (and replace-char-fold
+ (not regexp-flag)
+ #'char-fold-to-regexp))
+ :transform (lambda (string)
+ (let* ((split (query-replace--split-string string))
+ (from-string (if (consp split) (car split) split)))
+ (when (and case-fold-search search-upper-case)
+ (setq isearch-case-fold-search
+ (isearch-no-upper-case-p from-string regexp-flag)))
+ from-string)))
+ (query-replace-read-from prompt regexp-flag)))
(to (if (consp from) (prog1 (cdr from) (setq from (car from)))
(query-replace-read-to from prompt regexp-flag))))
(list from to
- (or (and current-prefix-arg (not (eq current-prefix-arg '-)))
+ (or delimited-flag
(and (plist-member (text-properties-at 0 from) 'isearch-regexp-function)
(get-text-property 0 'isearch-regexp-function from)))
(and current-prefix-arg (eq current-prefix-arg '-))))))
@@ -357,7 +400,9 @@ should a regexp."
(defun query-replace (from-string to-string &optional delimited start end backward region-noncontiguous-p)
"Replace some occurrences of FROM-STRING with TO-STRING.
As each match is found, the user must type a character saying
-what to do with it. For directions, type \\[help-command] at that time.
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer's
@@ -370,7 +415,7 @@ word boundaries. A negative prefix arg means replace backward.
Use \\<minibuffer-local-map>\\[next-history-element] \
to pull the last incremental search string to the minibuffer
that reads FROM-STRING, or invoke replacements from
-incremental search with a key sequence like `C-s C-s M-%'
+incremental search with a key sequence like \\`C-s C-s M-%'
to use its current search string as the string to replace.
Matching is independent of case if both `case-fold-search'
@@ -427,19 +472,21 @@ To customize possible responses, change the bindings in `query-replace-map'."
(defun query-replace-regexp (regexp to-string &optional delimited start end backward region-noncontiguous-p)
"Replace some things after point matching REGEXP with TO-STRING.
As each match is found, the user must type a character saying
-what to do with it. For directions, type \\[help-command] at that time.
+what to do with it. Type \\`SPC' or \\`y' to replace the match,
+\\`DEL' or \\`n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer's
accessible portion.
When invoked interactively, matching a newline with `\\n' will not work;
-use `C-q C-j' instead. To match a tab character (`\\t'), just press `TAB'.
+use \\`C-q C-j' instead. To match a tab character (`\\t'), just press \\`TAB'.
Use \\<minibuffer-local-map>\\[next-history-element] \
to pull the last incremental search regexp to the minibuffer
that reads REGEXP, or invoke replacements from
-incremental search with a key sequence like `C-M-s C-M-s C-M-%'
+incremental search with a key sequence like \\`C-M-s C-M-s C-M-%'
to use its current search regexp as the regexp to replace.
Matching is independent of case if both `case-fold-search'
@@ -524,7 +571,9 @@ Interactive use of this function is deprecated in favor of the
using `search-forward-regexp' and `replace-match' is preferred.
As each match is found, the user must type a character saying
-what to do with it. For directions, type \\[help-command] at that time.
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
TO-EXPR is a Lisp expression evaluated to compute each replacement. It may
reference `replace-count' to get the number of replacements already made.
@@ -610,6 +659,11 @@ Use \\<minibuffer-local-map>\\[next-history-element] \
to pull the last incremental search regexp to the minibuffer
that reads REGEXP.
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
A prefix argument N says to use each replacement string N times
before rotating to the next.
Fourth and fifth arg START and END specify the region to operate on.
@@ -841,6 +895,23 @@ by this function to the end of values available via
(regexp-quote (or (car search-ring) ""))
(car (symbol-value query-replace-from-history-variable))))
+(defvar-keymap read-regexp-map
+ :parent minibuffer-local-map
+ "M-c" #'read-regexp-toggle-case-folding)
+
+(defvar read-regexp--case-fold nil)
+
+(defun read-regexp-toggle-case-folding ()
+ (interactive)
+ (setq read-regexp--case-fold
+ (if (or (eq read-regexp--case-fold 'fold)
+ (and read-regexp--case-fold
+ (not (eq read-regexp--case-fold 'inhibit-fold))))
+ 'inhibit-fold
+ 'fold))
+ (minibuffer-message "Case folding is now %s"
+ (if (eq read-regexp--case-fold 'fold) "on" "off")))
+
(defun read-regexp (prompt &optional defaults history)
"Read and return a regular expression as a string.
Prompt with the string PROMPT. If PROMPT ends in \":\" (followed by
@@ -875,7 +946,16 @@ If the first element of DEFAULTS is non-nil (and if PROMPT does not end
in \":\", followed by optional whitespace), DEFAULT is added to the prompt.
The optional argument HISTORY is a symbol to use for the history list.
-If nil, use `regexp-history'."
+If nil, use `regexp-history'.
+
+If the user has used the \\<read-regexp-map>\\[read-regexp-toggle-case-folding] command to specify case
+sensitivity, the returned string will have a text property named
+`case-fold' that has a value of either `fold' or
+`inhibit-fold'. (It's up to the caller of `read-regexp' to
+respect this or not; see `read-regexp-case-fold-search'.)
+
+This command uses the `read-regexp-map' keymap while reading the
+regexp from the user."
(let* ((defaults
(if (and defaults (symbolp defaults))
(cond
@@ -891,21 +971,37 @@ If nil, use `regexp-history'."
(suggestions (delete-dups (delq nil (delete "" suggestions))))
;; Do not automatically add default to the history for empty input.
(history-add-new-input nil)
+ ;; `read-regexp--case-fold' dynamically bound and may be
+ ;; altered by `M-c'.
+ (read-regexp--case-fold case-fold-search)
(input (read-from-minibuffer
(if (string-match-p ":[ \t]*\\'" prompt)
prompt
(format-prompt prompt (and (length> default 0)
(query-replace-descr default))))
- nil nil nil (or history 'regexp-history) suggestions t)))
- (if (equal input "")
- ;; Return the default value when the user enters empty input.
- (prog1 (or default input)
- (when default
- (add-to-history (or history 'regexp-history) default)))
- ;; Otherwise, add non-empty input to the history and return input.
- (prog1 input
- (add-to-history (or history 'regexp-history) input)))))
-
+ nil read-regexp-map
+ nil (or history 'regexp-history) suggestions t))
+ (result (if (equal input "")
+ ;; Return the default value when the user enters
+ ;; empty input.
+ default
+ input)))
+ (when result
+ (add-to-history (or history 'regexp-history) result))
+ (if (and result
+ (or (eq read-regexp--case-fold 'fold)
+ (eq read-regexp--case-fold 'inhibit-fold)))
+ (propertize result 'case-fold read-regexp--case-fold)
+ (or result input))))
+
+(defun read-regexp-case-fold-search (regexp)
+ "Return a value for `case-fold-search' based on REGEXP and current settings.
+REGEXP is a string as returned by `read-regexp'."
+ (let ((fold (get-text-property 0 'case-fold regexp)))
+ (cond
+ ((eq fold 'fold) t)
+ ((eq fold 'inhibit-fold) nil)
+ (t case-fold-search))))
(defalias 'delete-non-matching-lines 'keep-lines)
(defalias 'delete-matching-lines 'flush-lines)
@@ -1413,10 +1509,15 @@ To return to ordinary Occur mode, use \\[occur-cease-edit]."
(length s1)))))
(prefix-len (funcall common-prefix buf-str text))
(suffix-len (funcall common-prefix
- (reverse buf-str) (reverse text))))
+ (reverse (substring
+ buf-str prefix-len))
+ (reverse (substring
+ text prefix-len)))))
(setq beg-pos (+ beg-pos prefix-len))
(setq end-pos (- end-pos suffix-len))
- (setq text (substring text prefix-len (- suffix-len)))
+ (setq text (substring text prefix-len
+ (and (not (zerop suffix-len))
+ (- suffix-len))))
(delete-region beg-pos end-pos)
(goto-char beg-pos)
(insert text)))
@@ -2086,6 +2187,7 @@ See also `multi-occur'."
;; (for Occur Edit mode).
front-sticky t
rear-nonsticky t
+ read-only t
occur-target ,markers
follow-link t
help-echo "mouse-2: go to this occurrence"))))
@@ -2412,7 +2514,8 @@ To be added to `context-menu-functions'."
\\`^' to move point back to previous match,
\\`u' to undo previous replacement,
\\`U' to undo all replacements,
-\\`E' to edit the replacement string.
+\\`e' to edit the replacement string.
+\\`E' to edit the replacement string with exact case.
In multi-buffer replacements type \\`Y' to replace all remaining
matches in all remaining buffers with no more questions,
\\`N' to skip to the next buffer without replacing remaining matches
@@ -2430,7 +2533,7 @@ in the current buffer."
(define-key map "Y" 'act)
(define-key map "N" 'skip)
(define-key map "e" 'edit-replacement)
- (define-key map "E" 'edit-replacement)
+ (define-key map "E" 'edit-replacement-exact-case)
(define-key map "," 'act-and-show)
(define-key map "q" 'exit)
(define-key map "\r" 'exit)
@@ -2467,8 +2570,9 @@ The \"bindings\" in this map are not commands; they are answers.
The valid answers include `act', `skip', `act-and-show',
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
-`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `undo', `undo-all', `quit', and `help'.
+`edit', `edit-replacement', `edit-replacement-exact-case',
+`delete-and-edit', `automatic', `backup', `undo', `undo-all',
+`quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2625,7 +2729,7 @@ It is called with three arguments, as if it were
"Function to convert the FROM string of query-replace commands to a regexp.
This is used by `query-replace', `query-replace-regexp', etc. as
the value of `isearch-regexp-function' when they search for the
-occurences of the string/regexp to be replaced. This is intended
+occurrences of the string/regexp to be replaced. This is intended
to be used when the string to be replaced, as typed by the user,
is not to be interpreted literally, but instead should be converted
to a regexp that is actually used for the search.")
@@ -2659,6 +2763,11 @@ to a regexp that is actually used for the search.")
(or (if regexp-flag
replace-re-search-function
replace-search-function)
+ ;; `isearch-search-fun' can't be used here because
+ ;; when buffer-local `isearch-search-fun-function'
+ ;; searches e.g. the minibuffer history, then
+ ;; `query-replace' should not operate on the whole
+ ;; history, but only on the minibuffer contents.
(isearch-search-fun-default))))
(funcall search-function search-string limit t)))
@@ -2747,6 +2856,26 @@ to a regexp that is actually used for the search.")
,search-str ,next-replace)
,stack))
+(defun replace--region-filter (bounds)
+ "Return a function that decides if a region is inside BOUNDS.
+BOUNDS is a list of cons cells of the form (START . END). The
+returned function takes as argument two buffer positions, START
+and END."
+ (let ((region-bounds
+ (mapcar (lambda (position)
+ (cons (copy-marker (car position))
+ (copy-marker (cdr position))))
+ bounds)))
+ (lambda (start end)
+ (delq nil (mapcar
+ (lambda (bounds)
+ (and
+ (>= start (car bounds))
+ (<= start (cdr bounds))
+ (>= end (car bounds))
+ (<= end (cdr bounds))))
+ region-bounds)))))
+
(defun perform-replace (from-string replacements
query-flag regexp-flag delimited-flag
&optional repeat-count map start end backward region-noncontiguous-p)
@@ -2831,22 +2960,9 @@ characters."
;; Unless a single contiguous chunk is selected, operate on multiple chunks.
(when region-noncontiguous-p
- (let ((region-bounds
- (mapcar (lambda (position)
- (cons (copy-marker (car position))
- (copy-marker (cdr position))))
- (funcall region-extract-function 'bounds))))
- (setq region-filter
- (lambda (start end)
- (delq nil (mapcar
- (lambda (bounds)
- (and
- (>= start (car bounds))
- (<= start (cdr bounds))
- (>= end (car bounds))
- (<= end (cdr bounds))))
- region-bounds))))
- (add-function :after-while isearch-filter-predicate region-filter)))
+ (setq region-filter (replace--region-filter
+ (funcall region-extract-function 'bounds)))
+ (add-function :after-while isearch-filter-predicate region-filter))
;; If region is active, in Transient Mark mode, operate on region.
(if backward
@@ -3207,7 +3323,13 @@ characters."
(last-command 'recenter-top-bottom))
(recenter-top-bottom)))
((eq def 'edit)
- (let ((opos (point-marker)))
+ (let ((opos (point-marker))
+ ;; Restore original isearch filter to allow
+ ;; using isearch in a recursive edit even
+ ;; when perform-replace was started from
+ ;; `xref--query-replace-1' that let-binds
+ ;; `isearch-filter-predicate' (bug#53758).
+ (isearch-filter-predicate #'isearch-filter-visible))
(setq real-match-data (replace-match-data
nil real-match-data
real-match-data))
@@ -3224,19 +3346,29 @@ characters."
(setq match-again (and (looking-at search-string)
(match-data)))))
;; Edit replacement.
- ((eq def 'edit-replacement)
+ ((or (eq def 'edit-replacement)
+ (eq def 'edit-replacement-exact-case))
(setq real-match-data (replace-match-data
nil real-match-data
real-match-data)
next-replacement
- (read-string "Edit replacement string: "
- next-replacement)
+ (read-string
+ (format "Edit replacement string%s: "
+ (if (eq def
+ 'edit-replacement-exact-case)
+ " (exact case)"
+ ""))
+ next-replacement)
noedit nil)
(if replaced
(set-match-data real-match-data)
(setq noedit
(replace-match-maybe-edit
- next-replacement nocasify literal noedit
+ next-replacement
+ (if (eq def 'edit-replacement-exact-case)
+ t
+ nocasify)
+ literal noedit
real-match-data backward)
replaced t)
(setq next-replacement-replaced next-replacement))
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index afe1cd4bfda..0b18697cea7 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -279,21 +279,24 @@ or remove a tab stop. \\[ruler-mode-toggle-show-tab-stops] or
(let ((edges (window-edges)))
(- (nth 2 edges) (nth 0 edges))))
-(defsubst ruler-mode-window-col (n)
+(defsubst ruler-mode-window-col (event)
"Return a column number relative to the selected window.
-N is a column number relative to selected frame.
+EVENT is the mouse event that gives the current column.
If required, account for screen estate taken by `display-line-numbers'."
- (if display-line-numbers
+ (let ((n (car (posn-col-row event))))
+ (when display-line-numbers
;; FIXME: ruler-mode relies on N being an integer, so if the
;; 'line-number' face is customized to use a font that is larger
;; or smaller than that of the default face, the alignment might
;; be off by up to half a column, unless the font width is an
;; integral multiple or divisor of the default face's font.
(setq n (- n (round (line-number-display-width 'columns)))))
- (- n
- (or (car (window-margins)) 0)
- (fringe-columns 'left)
- (scroll-bar-columns 'left)))
+ (- n
+ (if (eq (posn-area event) 'header-line)
+ (+ (or (car (window-margins)) 0)
+ (fringe-columns 'left)
+ (scroll-bar-columns 'left))
+ 0))))
(defun ruler-mode-mouse-set-left-margin (start-event)
"Set left margin end to the graduation where the mouse pointer is on.
@@ -370,7 +373,7 @@ dragging. See also the variable `ruler-mode-dragged-symbol'."
col newc oldc)
(save-selected-window
(select-window (posn-window start))
- (setq col (ruler-mode-window-col (car (posn-col-row start)))
+ (setq col (ruler-mode-window-col start)
newc (+ col (ruler-mode-text-scaled-window-hscroll)))
(and
(>= col 0) (< col (ruler-mode-text-scaled-window-width))
@@ -455,7 +458,7 @@ Called on each mouse motion event START-EVENT."
col newc)
(save-selected-window
(select-window (posn-window start))
- (setq col (ruler-mode-window-col (car (posn-col-row end)))
+ (setq col (ruler-mode-window-col end)
newc (+ col (ruler-mode-text-scaled-window-hscroll)))
(when (and (>= col 0) (< col (ruler-mode-text-scaled-window-width)))
(set ruler-mode-dragged-symbol newc)))))
@@ -471,7 +474,7 @@ START-EVENT is the mouse click event."
(when (eq start end) ;; mouse click
(save-selected-window
(select-window (posn-window start))
- (setq col (ruler-mode-window-col (car (posn-col-row start)))
+ (setq col (ruler-mode-window-col start)
ts (+ col (ruler-mode-text-scaled-window-hscroll)))
(and (>= col 0) (< col (ruler-mode-text-scaled-window-width))
(not (member ts tab-stop-list))
@@ -492,7 +495,7 @@ START-EVENT is the mouse click event."
(when (eq start end) ;; mouse click
(save-selected-window
(select-window (posn-window start))
- (setq col (ruler-mode-window-col (car (posn-col-row start)))
+ (setq col (ruler-mode-window-col start)
ts (+ col (ruler-mode-text-scaled-window-hscroll)))
(and (>= col 0) (< col (ruler-mode-text-scaled-window-width))
(member ts tab-stop-list)
@@ -506,36 +509,21 @@ START-EVENT is the mouse click event."
(setq ruler-mode-show-tab-stops (not ruler-mode-show-tab-stops))
(force-mode-line-update))
-(defvar ruler-mode-map
- (let ((km (make-sparse-keymap)))
- (define-key km [header-line down-mouse-1]
- #'ignore)
- (define-key km [header-line down-mouse-3]
- #'ignore)
- (define-key km [header-line down-mouse-2]
- #'ruler-mode-mouse-grab-any-column)
- (define-key km [header-line (shift down-mouse-1)]
- #'ruler-mode-mouse-set-left-margin)
- (define-key km [header-line (shift down-mouse-3)]
- #'ruler-mode-mouse-set-right-margin)
- (define-key km [header-line (control down-mouse-1)]
- #'ruler-mode-mouse-add-tab-stop)
- (define-key km [header-line (control down-mouse-3)]
- #'ruler-mode-mouse-del-tab-stop)
- (define-key km [header-line (control down-mouse-2)]
- #'ruler-mode-toggle-show-tab-stops)
- (define-key km [header-line (shift mouse-1)]
- #'ignore)
- (define-key km [header-line (shift mouse-3)]
- #'ignore)
- (define-key km [header-line (control mouse-1)]
- #'ignore)
- (define-key km [header-line (control mouse-3)]
- #'ignore)
- (define-key km [header-line (control mouse-2)]
- #'ignore)
- km)
- "Keymap for ruler minor mode.")
+(defvar-keymap ruler-mode-map
+ :doc "Keymap for `ruler-mode'."
+ "<header-line> <down-mouse-1>" #'ignore
+ "<header-line> <down-mouse-3>" #'ignore
+ "<header-line> <down-mouse-2>" #'ruler-mode-mouse-grab-any-column
+ "<header-line> S-<down-mouse-1>" #'ruler-mode-mouse-set-left-margin
+ "<header-line> S-<down-mouse-3>" #'ruler-mode-mouse-set-right-margin
+ "<header-line> C-<down-mouse-1>" #'ruler-mode-mouse-add-tab-stop
+ "<header-line> C-<down-mouse-3>" #'ruler-mode-mouse-del-tab-stop
+ "<header-line> C-<down-mouse-2>" #'ruler-mode-toggle-show-tab-stops
+ "<header-line> S-<mouse-1>" #'ignore
+ "<header-line> S-<mouse-3>" #'ignore
+ "<header-line> C-<mouse-1>" #'ignore
+ "<header-line> C-<mouse-3>" #'ignore
+ "<header-line> C-<mouse-2>" #'ignore)
(defvar ruler-mode-header-line-format-old nil
"Hold previous value of `header-line-format'.")
diff --git a/lisp/savehist.el b/lisp/savehist.el
index aab304007b2..8924c8dde23 100644
--- a/lisp/savehist.el
+++ b/lisp/savehist.el
@@ -60,14 +60,19 @@ If you want to save only specific histories, use `savehist-save-hook'
to modify the value of `savehist-minibuffer-history-variables'."
:type 'boolean)
-(defcustom savehist-additional-variables ()
+(defcustom savehist-additional-variables nil
"List of additional variables to save.
-Each element is a symbol whose value will be persisted across Emacs
-sessions that use Savehist. The contents of variables should be
-printable with the Lisp printer. You don't need to add minibuffer
-history variables to this list, all minibuffer histories will be
-saved automatically as long as `savehist-save-minibuffer-history' is
-non-nil.
+Each element is a variable that will be persisted across Emacs
+sessions that use Savehist.
+
+An element may be variable name (a symbol) or a cons cell of the form
+\(VAR . MAX-SIZE), which means to truncate VAR's value to at most
+MAX-SIZE elements (if the value is a list) before saving the value.
+
+The contents of variables should be printable with the Lisp
+printer. You don't need to add minibuffer history variables to
+this list, all minibuffer histories will be saved automatically
+as long as `savehist-save-minibuffer-history' is non-nil.
User options should be saved with the Customize interface. This
list is useful for saving automatically updated variables that are not
@@ -92,7 +97,8 @@ This is decimal, not octal. The default is 384 (0600 in octal).
Set to nil to use the default permissions that Emacs uses, typically
mandated by umask. The default is a bit more restrictive to protect
the user's privacy."
- :type 'integer)
+ :type '(choice (natnum :tag "Specify")
+ (const :tag "Use default" :value nil)))
(defcustom savehist-autosave-interval (* 5 60)
"The interval between autosaves of minibuffer history.
@@ -278,12 +284,21 @@ If AUTO-SAVE is non-nil, compare the saved contents to the one last saved,
(delete-region (point) (1+ (point)))))
(insert "))\n"))))))
;; Save the additional variables.
- (dolist (symbol savehist-additional-variables)
- (when (boundp symbol)
- (let ((value (symbol-value symbol)))
- (when (savehist-printable value)
- (prin1 `(setq ,symbol ',value) (current-buffer))
- (insert ?\n))))))
+ (dolist (elem savehist-additional-variables)
+ (let ((symbol (if (consp elem)
+ (car elem)
+ elem)))
+ (when (boundp symbol)
+ (let ((value (symbol-value symbol)))
+ (when (savehist-printable value)
+ ;; When we have a max-size, chop off the last elements.
+ (when (and (consp elem)
+ (listp value)
+ (length> value (cdr elem)))
+ (setq value (copy-sequence value))
+ (setcdr (nthcdr (cdr elem) value) nil))
+ (prin1 `(setq ,symbol ',value) (current-buffer))
+ (insert ?\n)))))))
;; If autosaving, avoid writing if nothing has changed since the
;; last write.
(let ((checksum (md5 (current-buffer) nil nil savehist-coding-system)))
diff --git a/lisp/saveplace.el b/lisp/saveplace.el
index 4d13ad3959c..3830e4b16cf 100644
--- a/lisp/saveplace.el
+++ b/lisp/saveplace.el
@@ -290,7 +290,11 @@ may have changed) back to `save-place-alist'."
;; adding hooks to it.
(with-current-buffer (get-buffer-create " *Saved Places*")
(delete-region (point-min) (point-max))
- (insert-file-contents file)
+ ;; Make sure our 'coding:' cookie in the save-place
+ ;; file will take effect, in case the caller binds
+ ;; coding-system-for-read.
+ (let (coding-system-for-read)
+ (insert-file-contents file))
(goto-char (point-min))
(setq save-place-alist
(with-demoted-errors "Error reading save-place-file: %S"
@@ -342,7 +346,12 @@ may have changed) back to `save-place-alist'."
(save-place-to-alist))
(setq buf-list (cdr buf-list))))))
+(defvar save-place-after-find-file-hook nil
+ "Hook run at the end of `save-place-find-file-hook'.")
+
(defun save-place-find-file-hook ()
+ "Function added to `find-file-hook' by `save-place-mode'.
+It runs the hook `save-place-after-find-file-hook'."
(or save-place-loaded (load-save-place-alist-from-file))
(let ((cell (assoc buffer-file-name save-place-alist)))
(if cell
@@ -351,7 +360,8 @@ may have changed) back to `save-place-alist'."
(and (integerp (cdr cell))
(goto-char (cdr cell))))
;; and make sure it will be saved again for later
- (setq save-place-mode t)))))
+ (setq save-place-mode t))))
+ (run-hooks 'save-place-after-find-file-hook))
(declare-function dired-goto-file "dired" (file))
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
index 3d12723c025..5786a21e88e 100644
--- a/lisp/scroll-bar.el
+++ b/lisp/scroll-bar.el
@@ -132,8 +132,11 @@ Setting the variable with a customization buffer also takes effect."
(define-minor-mode scroll-bar-mode
"Toggle vertical scroll bars on all frames (Scroll Bar mode).
-This command applies to all frames that exist and frames to be
-created in the future."
+This command applies to all frames that exist, as well as new
+frames to be created in the future. This is done by altering the
+frame parameters, so if you (re-)set `default-frame-alist' after
+toggling the scroll bars on or off with this command, the scroll
+bars may reappear on new frames."
:variable ((get-scroll-bar-mode)
. (lambda (v) (set-scroll-bar-mode
(if v (or previous-scroll-bar-mode
diff --git a/lisp/scroll-lock.el b/lisp/scroll-lock.el
index d41e3352332..fa1f3a633b5 100644
--- a/lisp/scroll-lock.el
+++ b/lisp/scroll-lock.el
@@ -30,15 +30,13 @@
;;; Code:
-(defvar scroll-lock-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [remap next-line] 'scroll-lock-next-line)
- (define-key map [remap previous-line] 'scroll-lock-previous-line)
- (define-key map [remap forward-paragraph] 'scroll-lock-forward-paragraph)
- (define-key map [remap backward-paragraph] 'scroll-lock-backward-paragraph)
- (define-key map [S-down] 'scroll-lock-next-line-always-scroll)
- map)
- "Keymap for Scroll Lock mode.")
+(defvar-keymap scroll-lock-mode-map
+ :doc "Keymap for Scroll Lock mode."
+ "<remap> <next-line>" #'scroll-lock-next-line
+ "<remap> <previous-line>" #'scroll-lock-previous-line
+ "<remap> <forward-paragraph>" #'scroll-lock-forward-paragraph
+ "<remap> <backward-paragraph>" #'scroll-lock-backward-paragraph
+ "S-<down>" #'scroll-lock-next-line-always-scroll)
(defvar-local scroll-lock-preserve-screen-pos-save scroll-preserve-screen-position
"Used for saving the state of `scroll-preserve-screen-position'.")
@@ -55,7 +53,7 @@ will scroll the buffer by the respective amount of lines instead
and point will be kept vertically fixed relative to window
boundaries during scrolling.
-Note that the default key binding to Scroll_Lock will not work on
+Note that the default key binding to `scroll' will not work on
MS-Windows systems if `w32-scroll-lock-modifier' is non-nil."
:lighter " ScrLck"
:keymap scroll-lock-mode-map
diff --git a/lisp/select.el b/lisp/select.el
index 7f29f02dab9..6002b2615e1 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -25,9 +25,10 @@
;; Based partially on earlier release by Lucid.
;; The functionality here is divided in two parts:
-;; - Low-level: gui-get-selection, gui-set-selection, gui-selection-owner-p,
-;; gui-selection-exists-p are the backend-dependent functions meant to access
-;; various kinds of selections (CLIPBOARD, PRIMARY, SECONDARY).
+;; - Low-level: gui-backend-get-selection, gui-backend-set-selection,
+;; gui-backend-selection-owner-p, gui-backend-selection-exists-p are
+;; the backend-dependent functions meant to access various kinds of
+;; selections (CLIPBOARD, PRIMARY, SECONDARY).
;; - Higher-level: gui-select-text and gui-selection-value go together to
;; access the general notion of "GUI selection" for interoperation with other
;; applications. This can use either the clipboard or the primary selection,
@@ -108,33 +109,91 @@ E.g. it doesn't exist under MS-Windows."
:group 'killing
:version "25.1")
-;; We keep track of the last text selected here, so we can check the
-;; current selection against it, and avoid passing back our own text
-;; from gui-selection-value. We track both
-;; separately in case another X application only sets one of them
-;; we aren't fooled by the PRIMARY or CLIPBOARD selection staying the same.
+;; We keep track of the last selection here, so we can check the
+;; current selection against it, and avoid passing back with
+;; gui-selection-value the same text we previously killed or
+;; yanked. We track both separately in case another X application only
+;; sets one of them we aren't fooled by the PRIMARY or CLIPBOARD
+;; selection staying the same.
(defvar gui--last-selected-text-clipboard nil
"The value of the CLIPBOARD selection last seen.")
+
(defvar gui--last-selected-text-primary nil
"The value of the PRIMARY selection last seen.")
+(defvar gui--last-selection-timestamp-clipboard nil
+ "The timestamp of the CLIPBOARD selection last seen.")
+
+(defvar gui--last-selection-timestamp-primary nil
+ "The timestamp of the PRIMARY selection last seen.")
+
+(defvar gui-last-cut-in-clipboard nil
+ "Whether or not the last call to `interprogram-cut-function' owned CLIPBOARD.")
+
+(defvar gui-last-cut-in-primary nil
+ "Whether or not the last call to `interprogram-cut-function' owned PRIMARY.")
+
+(defun gui--set-last-clipboard-selection (text)
+ "Save last clipboard selection.
+Save the selected text, passed as argument, and for window
+systems that support it, save the selection timestamp too."
+ (setq gui--last-selected-text-clipboard text)
+ (when (eq window-system 'x)
+ (setq gui--last-selection-timestamp-clipboard
+ (gui-backend-get-selection 'CLIPBOARD 'TIMESTAMP))))
+
+(defun gui--set-last-primary-selection (text)
+ "Save last primary selection.
+Save the selected text, passed as argument, and for window
+systems that support it, save the selection timestamp too."
+ (setq gui--last-selected-text-primary text)
+ (when (eq window-system 'x)
+ (setq gui--last-selection-timestamp-primary
+ (gui-backend-get-selection 'PRIMARY 'TIMESTAMP))))
+
+(defun gui--clipboard-selection-unchanged-p (text)
+ "Check whether the clipboard selection has changed.
+Compare the selection text, passed as argument, with the text
+from the last saved selection. For window systems that support
+it, compare the selection timestamp too."
+ (and
+ (equal text gui--last-selected-text-clipboard)
+ (or (not (eq window-system 'x))
+ (eq gui--last-selection-timestamp-clipboard
+ (gui-backend-get-selection 'CLIPBOARD 'TIMESTAMP)))))
+
+(defun gui--primary-selection-unchanged-p (text)
+ "Check whether the primary selection has changed.
+Compare the selection text, passed as argument, with the text
+from the last saved selection. For window systems that support
+it, compare the selection timestamp too."
+ (and
+ (equal text gui--last-selected-text-primary)
+ (or (not (eq window-system 'x))
+ (eq gui--last-selection-timestamp-primary
+ (gui-backend-get-selection 'PRIMARY 'TIMESTAMP)))))
+
+
(defun gui-select-text (text)
"Select TEXT, a string, according to the window system.
-if `select-enable-clipboard' is non-nil, copy TEXT to the system's clipboard.
+If `select-enable-clipboard' is non-nil, copy TEXT to the system's clipboard.
If `select-enable-primary' is non-nil, put TEXT in the primary selection.
MS-Windows does not have a \"primary\" selection."
(when select-enable-primary
(gui-set-selection 'PRIMARY text)
- (setq gui--last-selected-text-primary text))
+ (gui--set-last-primary-selection text))
(when select-enable-clipboard
;; When cutting, the selection is cleared and PRIMARY
;; set to the empty string. Prevent that, PRIMARY
;; should not be reset by cut (Bug#16382).
(setq saved-region-selection text)
(gui-set-selection 'CLIPBOARD text)
- (setq gui--last-selected-text-clipboard text)))
+ (gui--set-last-clipboard-selection text))
+ ;; Record which selections we now have ownership over.
+ (setq gui-last-cut-in-clipboard select-enable-clipboard
+ gui-last-cut-in-primary select-enable-primary))
(define-obsolete-function-alias 'x-select-text 'gui-select-text "25.1")
(defcustom x-select-request-type nil
@@ -168,20 +227,29 @@ text/plain\\;charset=utf-8)."
Call `gui-get-selection' with an appropriate DATA-TYPE argument
decided by `x-select-request-type'. The return value is already
decoded. If `gui-get-selection' signals an error, return nil."
- (let ((request-type (if (memq window-system '(x pgtk))
- (or x-select-request-type
- '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8))
- 'STRING))
- text)
- (with-demoted-errors "gui-get-selection: %S"
- (if (consp request-type)
- (while (and request-type (not text))
- (setq text (gui-get-selection type (car request-type)))
- (setq request-type (cdr request-type)))
- (setq text (gui-get-selection type request-type))))
- (if text
- (remove-text-properties 0 (length text) '(foreign-selection nil) text))
- text))
+ ;; The doc string of `interprogram-paste-function' says to return
+ ;; nil if no other program has provided text to paste.
+ (unless (and gui-last-cut-in-clipboard
+ ;; `gui-backend-selection-owner-p' might be unreliable on
+ ;; some other window systems.
+ (memq window-system '(x haiku))
+ (eq type 'CLIPBOARD)
+ ;; Should we unify this with gui--clipboard-selection-unchanged-p?
+ (gui-backend-selection-owner-p type))
+ (let ((request-type (if (memq window-system '(x pgtk haiku))
+ (or x-select-request-type
+ '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8))
+ 'STRING))
+ text)
+ (with-demoted-errors "gui-get-selection: %S"
+ (if (consp request-type)
+ (while (and request-type (not text))
+ (setq text (gui-get-selection type (car request-type)))
+ (setq request-type (cdr request-type)))
+ (setq text (gui-get-selection type request-type))))
+ (if text
+ (remove-text-properties 0 (length text) '(foreign-selection nil) text))
+ text)))
(defun gui-selection-value ()
(let ((clip-text
@@ -189,19 +257,25 @@ decoded. If `gui-get-selection' signals an error, return nil."
(let ((text (gui--selection-value-internal 'CLIPBOARD)))
(when (string= text "")
(setq text nil))
- ;; When `select-enable-clipboard' is non-nil,
- ;; killing/copying text (with, say, `C-w') will push the
- ;; text to the clipboard (and store it in
- ;; `gui--last-selected-text-clipboard'). We check
- ;; whether the text on the clipboard is identical to this
- ;; text, and if so, we report that the clipboard is
- ;; empty. See (bug#27442) for further discussion about
- ;; this DWIM action, and possible ways to make this check
- ;; less fragile, if so desired.
- (prog1
- (unless (equal text gui--last-selected-text-clipboard)
- text)
- (setq gui--last-selected-text-clipboard text)))))
+ ;; Check the CLIPBOARD selection for 'newness', i.e.,
+ ;; whether it is different from the last time we did a
+ ;; yank operation or whether it was set by Emacs itself
+ ;; with a kill operation, since in both cases the text
+ ;; will already be in the kill ring. See (bug#27442) and
+ ;; (bug#53894) for further discussion about this DWIM
+ ;; action, and possible ways to make this check less
+ ;; fragile, if so desired.
+
+ ;; Don't check the "newness" of CLIPBOARD if the last
+ ;; call to `gui-select-text' didn't cause us to become
+ ;; its owner. This lets the user yank text killed by
+ ;; `clipboard-kill-region' with `clipboard-yank' without
+ ;; interference from text killed by other means when
+ ;; `select-enable-clipboard' is nil.
+ (unless (and gui-last-cut-in-clipboard
+ (gui--clipboard-selection-unchanged-p text))
+ (gui--set-last-clipboard-selection text)
+ text))))
(primary-text
(when select-enable-primary
(let ((text (gui--selection-value-internal 'PRIMARY)))
@@ -209,10 +283,10 @@ decoded. If `gui-get-selection' signals an error, return nil."
;; Check the PRIMARY selection for 'newness', is it different
;; from what we remembered them to be last time we did a
;; cut/paste operation.
- (prog1
- (unless (equal text gui--last-selected-text-primary)
- text)
- (setq gui--last-selected-text-primary text))))))
+ (unless (and gui-last-cut-in-primary
+ (gui--primary-selection-unchanged-p text))
+ (gui--set-last-primary-selection text)
+ text)))))
;; As we have done one selection, clear this now.
(setq next-selection-coding-system nil)
@@ -227,11 +301,11 @@ decoded. If `gui-get-selection' signals an error, return nil."
;; something like the following has happened since the last time
;; we looked at the selections: Application X set all the
;; selections, then Application Y set only one of them.
- ;; In this case since we don't have
- ;; timestamps there is no way to know what the 'correct' value to
- ;; return is. The nice thing to do would be to tell the user we
- ;; saw multiple possible selections and ask the user which was the
- ;; one they wanted.
+ ;; In this case, for systems that support selection timestamps, we
+ ;; could return the newer. For systems that don't, there is no
+ ;; way to know what the 'correct' value to return is. The nice
+ ;; thing to do would be to tell the user we saw multiple possible
+ ;; selections and ask the user which was the one they wanted.
(or clip-text primary-text)
))
@@ -342,16 +416,21 @@ the formats available in the clipboard if TYPE is `CLIPBOARD'."
(defun gui-set-selection (type data)
"Make an X selection of type TYPE and value DATA.
The argument TYPE (nil means `PRIMARY') says which selection, and
-DATA specifies the contents. TYPE must be a symbol. \(It can also
-be a string, which stands for the symbol with that name, but this
-is considered obsolete.) DATA may be a string, a symbol, an
-integer (or a cons of two integers or list of two integers).
-
-The selection may also be a cons of two markers pointing to the same buffer,
-or an overlay. In these cases, the selection is considered to be the text
-between the markers *at whatever time the selection is examined*.
-Thus, editing done in the buffer after you specify the selection
-can alter the effective value of the selection.
+DATA specifies the contents. TYPE must be a symbol. \(It can
+also be a string, which stands for the symbol with that name, but
+this is considered obsolete.) DATA may be a string, a symbol, or
+an integer.
+
+The selection may also be a cons of two markers pointing to the
+same buffer, or an overlay. In these cases, the selection is
+considered to be the text between the markers *at whatever time
+the selection is examined*. Thus, editing done in the buffer
+after you specify the selection can alter the effective value of
+the selection. If DATA is a string, then its text properties can
+specify alternative values for different data types. For
+example, the value of any property named `text/uri-list' will be
+used instead of DATA itself when another program converts TYPE to
+the target `text/uri-list'.
The data may also be a vector of valid non-vector selection values.
@@ -396,6 +475,45 @@ are not available to other programs."
(symbolp data)
(integerp data)))
+
+;; Minor mode to make losing ownership of PRIMARY behave more like
+;; other X programs.
+
+(defun lost-selection-function (selection)
+ "Handle losing of ownership of SELECTION.
+If SELECTION is `PRIMARY', deactivate the mark in every
+non-temporary buffer."
+ (let ((select-active-regions nil))
+ (when (eq selection 'PRIMARY)
+ (dolist (buffer (buffer-list))
+ (unless (string-match-p "^ "
+ (buffer-name buffer))
+ (with-current-buffer buffer
+ (deactivate-mark t)))))))
+
+(define-minor-mode lost-selection-mode
+ "Toggle `lost-selection-mode'.
+
+When this is enabled, selecting some text in another program will
+cause the mark to be deactivated in all buffers, mimicking the
+behavior of most X Windows programs."
+ :global t
+ :group 'x
+ (if lost-selection-mode
+ (cond ((featurep 'x) (add-hook 'x-lost-selection-functions
+ #'lost-selection-function))
+ ((featurep 'pgtk) (add-hook 'pgtk-lost-selection-functions
+ #'lost-selection-function))
+ ((featurep 'haiku) (add-hook 'haiku-lost-selection-functions
+ #'lost-selection-function)))
+ (cond ((featurep 'x) (remove-hook 'x-lost-selection-functions
+ #'lost-selection-function))
+ ((featurep 'pgtk) (remove-hook 'pgtk-lost-selection-functions
+ #'lost-selection-function))
+ ((featurep 'haiku) (remove-hook 'haiku-lost-selection-functions
+ #'lost-selection-function)))))
+
+
;; Functions to convert the selection into various other selection types.
;; Every selection type that Emacs handles is implemented this way, except
;; for TIMESTAMP, which is a special case.
@@ -427,7 +545,8 @@ two markers or an overlay. Otherwise, it is nil."
(defun xselect--int-to-cons (n)
(cons (ash n -16) (logand n 65535)))
-(defun xselect--encode-string (type str &optional can-modify)
+(defun xselect--encode-string (type str &optional can-modify
+ prefer-string-to-c-string)
(when str
;; If TYPE is nil, this is a local request; return STR as-is.
(if (null type)
@@ -477,7 +596,8 @@ two markers or an overlay. Otherwise, it is nil."
(if eight-bit 'C_STRING
'STRING))))))))
(cond
- ((eq type 'UTF8_STRING)
+ ((or (eq type 'UTF8_STRING)
+ (eq type 'text/plain\;charset=utf-8))
(if (or (not coding)
(not (eq (coding-system-type coding) 'utf-8)))
(setq coding 'utf-8))
@@ -489,6 +609,12 @@ two markers or an overlay. Otherwise, it is nil."
(setq coding 'iso-8859-1))
(setq str (encode-coding-string str coding)))
+ ((eq type 'text/plain)
+ (if (or (not coding)
+ (not (eq (coding-system-type coding) 'charset)))
+ (setq coding 'ascii))
+ (setq str (encode-coding-string str coding)))
+
((eq type 'COMPOUND_TEXT)
(if (or (not coding)
(not (eq (coding-system-type coding) 'iso-2022)))
@@ -513,7 +639,10 @@ two markers or an overlay. Otherwise, it is nil."
(setq str (string-replace "\0" "\\0" str))
(setq next-selection-coding-system nil)
- (cons type str))))
+ (cons (if (and prefer-string-to-c-string
+ (eq type 'C_STRING))
+ 'STRING type)
+ str))))
(defun xselect-convert-to-string (_selection type value)
(let ((str (cond ((stringp value) value)
@@ -531,31 +660,61 @@ two markers or an overlay. Otherwise, it is nil."
(if len
(xselect--int-to-cons len))))
-(defun xselect-convert-to-targets (_selection _type _value)
- ;; return a vector of atoms, but remove duplicates first.
- (let* ((all (cons 'TIMESTAMP
- (cons 'MULTIPLE
- (mapcar 'car selection-converter-alist))))
- (rest all))
- (while rest
- (cond ((memq (car rest) (cdr rest))
- (setcdr rest (delq (car rest) (cdr rest))))
- ((eq (car (cdr rest)) '_EMACS_INTERNAL) ; shh, it's a secret
- (setcdr rest (cdr (cdr rest))))
- (t
- (setq rest (cdr rest)))))
- (apply 'vector all)))
+(defvar x-dnd-targets-list)
+
+(defun xselect-convert-to-targets (selection _type value)
+ ;; Return a vector of atoms, but remove duplicates first.
+ (if (eq selection 'XdndSelection)
+ ;; This isn't required by the XDND protocol, and sure enough no
+ ;; clients seem to dependent on it, but Emacs implements the
+ ;; receiver side of the Motif drop protocol by looking at the
+ ;; initiator selection's TARGETS target (which Motif provides)
+ ;; instead of the target table on the drag window, so it seems
+ ;; plausible for other clients to rely on that as well.
+ (apply #'vector (mapcar #'intern x-dnd-targets-list))
+ (apply #'vector
+ (delete-dups
+ `( TIMESTAMP MULTIPLE
+ . ,(delq '_EMACS_INTERNAL
+ (mapcar (lambda (conv)
+ (if (or (not (consp (cdr conv)))
+ (funcall (cadr conv) selection
+ (car conv) value))
+ (car conv)
+ '_EMACS_INTERNAL))
+ selection-converter-alist)))))))
(defun xselect-convert-to-delete (selection _type _value)
- (gui-backend-set-selection selection nil)
+ ;; This should be handled by the caller of `x-begin-drag'.
+ (unless (eq selection 'XdndSelection)
+ (gui-backend-set-selection selection nil))
;; A return value of nil means that we do not know how to do this conversion,
;; and replies with an "error". A return value of NULL means that we have
;; done the conversion (and any side-effects) but have no value to return.
'NULL)
-(defun xselect-convert-to-filename (_selection _type value)
- (when (setq value (xselect--selection-bounds value))
- (xselect--encode-string 'TEXT (buffer-file-name (nth 2 value)))))
+(defun xselect-convert-to-filename (selection _type value)
+ (if (not (eq selection 'XdndSelection))
+ (when (setq value (xselect--selection-bounds value))
+ (xselect--encode-string 'TEXT (buffer-file-name (nth 2 value))))
+ (if (and (stringp value)
+ (file-exists-p value))
+ ;; Motif expects this to be STRING, but it treats the data as
+ ;; a sequence of bytes instead of a Latin-1 string.
+ (cons 'STRING (encode-coding-string (expand-file-name value)
+ (or file-name-coding-system
+ default-file-name-coding-system)))
+ (when (vectorp value)
+ (with-temp-buffer
+ (cl-loop for file across value
+ do (insert (expand-file-name file) "\0"))
+ ;; Get rid of the last NULL byte.
+ (when (> (point) 1)
+ (delete-char -1))
+ ;; Motif wants STRING.
+ (cons 'STRING (encode-coding-string (buffer-string)
+ (or file-name-coding-system
+ default-file-name-coding-system))))))))
(defun xselect-convert-to-charpos (_selection _type value)
(when (setq value (xselect--selection-bounds value))
@@ -617,11 +776,95 @@ This function returns the string \"emacs\"."
(when (eq selection 'CLIPBOARD)
'NULL))
+(defun xselect-convert-to-username (_selection _type _value)
+ (user-real-login-name))
+
+(defun xselect-convert-to-text-uri-list (_selection _type value)
+ (let ((string
+ (if (stringp value)
+ (xselect--encode-string 'TEXT
+ (concat (url-encode-url value) "\n"))
+ (when (vectorp value)
+ (with-temp-buffer
+ (cl-loop for tem across value
+ do (progn
+ (insert (url-encode-url tem))
+ (insert "\n")))
+ (xselect--encode-string 'TEXT (buffer-string)))))))
+ (cons 'text/uri-list (cdr string))))
+
+(defun xselect-convert-to-xm-file (selection _type value)
+ (when (and (stringp value)
+ (file-exists-p value)
+ (eq selection 'XdndSelection))
+ (xselect--encode-string 'C_STRING
+ (concat value [0]))))
+
+(defun xselect-uri-list-available-p (selection _type value)
+ "Return whether or not `text/uri-list' is a valid target for SELECTION.
+VALUE is the local selection value of SELECTION."
+ (and (eq selection 'XdndSelection)
+ (or (stringp value)
+ (vectorp value))))
+
+(defun xselect-convert-xm-special (_selection _type _value)
+ "")
+
+(defun xselect-dt-netfile-available-p (selection _type value)
+ "Return whether or not `_DT_NETFILE' is a valid target for SELECTION.
+VALUE is SELECTION's local selection value."
+ (and (eq selection 'XdndSelection)
+ (stringp value)
+ (file-exists-p value)
+ (not (file-remote-p value))))
+
+(defun xselect-tt-net-file (file)
+ "Get the canonical ToolTalk filename for FILE.
+FILE must be a local file, or otherwise the conversion will fail.
+The string returned has three components: the hostname of the
+machine where the file is, the real path, and the local path.
+They are encoded into a string of the form
+\"HOST=0-X,RPATH=X-Y,LPATH=Y-Z:DATA\", where X, Y, and Z are the
+positions of the hostname, rpath and lpath inside DATA."
+ (let ((hostname (system-name))
+ (rpath file)
+ (lpath file))
+ (format "HOST=0-%d,RPATH=%d-%d,LPATH=%d-%d:%s%s%s"
+ (1- (length hostname)) (length hostname)
+ (1- (+ (length hostname) (length rpath)))
+ (+ (length hostname) (length rpath))
+ (1- (+ (length hostname) (length rpath)
+ (length lpath)))
+ hostname rpath lpath)))
+
+(defun xselect-convert-to-dt-netfile (selection _type value)
+ "Convert SELECTION to a ToolTalk filename.
+VALUE should be SELECTION's local value."
+ (when (and (eq selection 'XdndSelection)
+ (stringp value)
+ (file-exists-p value)
+ (not (file-remote-p value)))
+ (let ((name (encode-coding-string value
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (cons 'STRING
+ (encode-coding-string (xselect-tt-net-file name)
+ (or file-name-coding-system
+ default-file-name-coding-system)
+ t)))))
+
(setq selection-converter-alist
'((TEXT . xselect-convert-to-string)
(COMPOUND_TEXT . xselect-convert-to-string)
(STRING . xselect-convert-to-string)
(UTF8_STRING . xselect-convert-to-string)
+ (text/plain . xselect-convert-to-string)
+ (text/plain\;charset=utf-8 . xselect-convert-to-string)
+ (text/uri-list . (xselect-uri-list-available-p
+ . xselect-convert-to-text-uri-list))
+ (text/x-xdnd-username . xselect-convert-to-username)
+ (FILE . (xselect-uri-list-available-p
+ . xselect-convert-to-xm-file))
(TARGETS . xselect-convert-to-targets)
(LENGTH . xselect-convert-to-length)
(DELETE . xselect-convert-to-delete)
@@ -637,7 +880,11 @@ This function returns the string \"emacs\"."
(ATOM . xselect-convert-to-atom)
(INTEGER . xselect-convert-to-integer)
(SAVE_TARGETS . xselect-convert-to-save-targets)
- (_EMACS_INTERNAL . xselect-convert-to-identity)))
+ (_EMACS_INTERNAL . xselect-convert-to-identity)
+ (XmTRANSFER_SUCCESS . xselect-convert-xm-special)
+ (XmTRANSFER_FAILURE . xselect-convert-xm-special)
+ (_DT_NETFILE . (xselect-dt-netfile-available-p
+ . xselect-convert-to-dt-netfile))))
(provide 'select)
diff --git a/lisp/server.el b/lisp/server.el
index da60f1cda77..a06f2f952fd 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -779,7 +779,8 @@ by the current Emacs process, use the `server-process' variable."
(condition-case nil
(if server-use-tcp
(with-temp-buffer
- (insert-file-contents-literally (expand-file-name name server-auth-dir))
+ (setq default-directory server-auth-dir)
+ (insert-file-contents-literally (expand-file-name name))
(or (and (looking-at "127\\.0\\.0\\.1:[0-9]+ \\([0-9]+\\)")
(assq 'comm
(process-attributes
@@ -1313,7 +1314,8 @@ The following commands are accepted by the client:
frame-parameters))
;; When resuming on a tty, tty-name is nil.
(tty-name
- (server-create-tty-frame tty-name tty-type proc))
+ (server-create-tty-frame tty-name tty-type proc
+ frame-parameters))
;; If there won't be a current frame to use, fall
;; back to trying to create a new one.
@@ -1366,7 +1368,7 @@ The following commands are accepted by the client:
((functionp initial-buffer-choice)
(funcall initial-buffer-choice)))))
(switch-to-buffer
- (if (buffer-live-p buf) buf (get-buffer-create "*scratch*"))
+ (if (buffer-live-p buf) buf (get-scratch-buffer-create))
'norecord)))
;; Delete the client if necessary.
diff --git a/lisp/ses.el b/lisp/ses.el
index 45e323e8051..ba965ff8a5b 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -84,17 +84,14 @@
(defcustom ses-initial-size '(1 . 1)
"Initial size of a new spreadsheet, as a cons (NUMROWS . NUMCOLS)."
- :group 'ses
:type '(cons (integer :tag "numrows") (integer :tag "numcols")))
(defcustom ses-initial-column-width 7
"Initial width of columns in a new spreadsheet."
- :group 'ses
:type '(integer :match (lambda (widget value) (> value 0))))
(defcustom ses-initial-default-printer "%.7g"
"Initial default printer for a new spreadsheet."
- :group 'ses
:type '(choice string
(list :tag "Parenthesized string" string)
function))
@@ -103,15 +100,30 @@
"Things to do after entering a value into a cell.
An abnormal hook that usually runs a cursor-movement function.
Each function is called with ARG=1."
- :group 'ses
:type 'hook
:options '(forward-char backward-char next-line previous-line))
(defcustom ses-mode-hook nil
"Hook functions to be run upon entering SES mode."
- :group 'ses
:type 'hook)
+(defcustom ses-jump-cell-name-function #'upcase
+ "Function to process the string passed to function `ses-jump'.
+Set it to `identity' to make no change.
+Set it to `upcase' to make cell name change case isensitive.
+
+ May return
+
+* a string, in this case this must be a cell name.
+* a (row . col) cons cell, in this case that must be valid cell coordinates."
+ :type 'function)
+
+(defcustom ses-jump-prefix-function #'ses-jump-prefix
+ "Function that takes the prefix argument passed to function `ses-jump'.
+It may return the same sort of thing as `ses-jump-cell-name-function'."
+ :type 'function)
+
+
;;----------------------------------------------------------------------------
;; Global variables and constants
@@ -233,7 +245,7 @@ Used for listing local printers or renamed cells.")
(suppress-keymap newmap t)
;;These keys insert themselves as the beginning of a numeric value
(dotimes (x (length numeric))
- (define-key newmap (substring numeric x (1+ x)) 'ses-read-cell))
+ (define-key newmap (substring numeric x (1+ x)) #'ses-read-cell))
(define-key newmap [remap clipboard-kill-region] #'ses-kill-override)
(define-key newmap [remap end-of-line] #'ses-end-of-line)
(define-key newmap [remap kill-line] #'ses-delete-row)
@@ -345,7 +357,7 @@ printer and then modify its output.")
(t (error "Unexpected elements `%S' in list `ses-localvars'" x)))))
;;; This variable is documented as being permitted in file-locals:
-(put 'ses--symbolic-formulas 'safe-local-variable 'consp)
+(put 'ses--symbolic-formulas 'safe-local-variable #'consp)
(defconst ses-paramlines-plist
'(ses--col-widths -5 ses--col-printers -4 ses--default-printer -3
@@ -1056,8 +1068,7 @@ the old and FORCE is nil."
(defcustom ses-self-reference-early-detection nil
"Non-nil if cycle detection is early for cells that refer to themselves."
:version "24.1"
- :type 'boolean
- :group 'ses)
+ :type 'boolean)
(defun ses-update-cells (list &optional force)
"Recalculate cells in LIST, checking for dependency loops.
@@ -2064,8 +2075,8 @@ formula:
;; Not to use tab characters for safe (tabs may do bad for column
;; calculation).
indent-tabs-mode nil)
- (1value (add-hook 'change-major-mode-hook 'ses-cleanup nil t))
- (1value (add-hook 'kill-buffer-hook 'ses-killbuffer-hook nil t))
+ (1value (add-hook 'change-major-mode-hook #'ses-cleanup nil t))
+ (1value (add-hook 'kill-buffer-hook #'ses-killbuffer-hook nil t))
(cl-pushnew (current-buffer) ses--ses-buffer-list :test 'eq)
;; This makes revert impossible if the buffer is read-only.
;; (1value (add-hook 'before-revert-hook 'ses-cleanup nil t))
@@ -2116,8 +2127,8 @@ formula:
;; find-alternate-file, post-command-hook doesn't get run for some reason,
;; so use an idle timer to make sure.
(setq ses--deferred-narrow 'ses-mode)
- (1value (add-hook 'post-command-hook 'ses-command-hook nil t))
- (run-with-idle-timer 0.01 nil 'ses-command-hook)
+ (1value (add-hook 'post-command-hook #'ses-command-hook nil t))
+ (run-with-idle-timer 0.01 nil #'ses-command-hook)
(run-mode-hooks 'ses-mode-hook)))
(put 'ses-mode 'mode-class 'special)
@@ -2233,24 +2244,43 @@ Based on the current set of columns and `window-hscroll' position."
;;----------------------------------------------------------------------------
;; Redisplay and recalculation
;;----------------------------------------------------------------------------
+(defun ses-jump-prefix (prefix-int)
+ "Convert an integer (unversal prefix) into a (ROW . COL).
+Does it by numbering cells starting from 0 from top left to bottom right,
+going row by row."
+ (and (>= prefix-int 0)
+ (< prefix-int (* ses--numcols ses--numrows))
+ (cons (/ prefix-int ses--numcols) (% prefix-int ses--numcols))))
+
-(defun ses-jump (sym)
+(defun ses-jump (&optional sym)
"Move point to cell SYM."
- (interactive (let* (names
- (s (completing-read
- "Jump to cell: "
- (and ses--named-cell-hashmap
- (progn (maphash (lambda (key _val)
- (push (symbol-name key) names))
- ses--named-cell-hashmap)
- names)))))
- (if (string= s "")
- (user-error "Invalid cell name")
- (list (intern s)))))
- (let ((rowcol (ses-sym-rowcol sym)))
+ (interactive "P")
+ (setq sym
+ (if current-prefix-arg
+ (funcall ses-jump-prefix-function (prefix-numeric-value sym))
+ (or sym
+ (completing-read
+ "Jump to cell: "
+ (and ses--named-cell-hashmap
+ (let (names)
+ (maphash (lambda (key _val)
+ (push (symbol-name key) names))
+ ses--named-cell-hashmap)
+ names))))))
+ (and (stringp sym)
+ (not (and ses--named-cell-hashmap (gethash (intern sym) ses--named-cell-hashmap)))
+ (setq sym (funcall ses-jump-cell-name-function sym)))
+ (if (stringp sym)
+ (if (string= sym "")
+ (user-error "Empty cell name")
+ (setq sym (intern sym))))
+ (let ((rowcol (if (consp sym)
+ (prog1 sym (setq sym (ses-cell-symbol (car sym) (cdr sym))))
+ (ses-sym-rowcol sym))))
(or rowcol (error "Invalid cell name"))
(if (eq (symbol-value sym) '*skip*)
- (error "Cell is covered by preceding cell"))
+ (error "Cell is covered by preceding cell"))
(ses-goto-print (car rowcol) (cdr rowcol))))
(defun ses-jump-safe (cell)
@@ -2301,7 +2331,7 @@ Narrow to print area if optional argument NONARROW is nil."
"Recalculate and reprint the current cell or range.
If CURCELL is non nil use it as current cell or range
-without any check, otherwise function (ses-check-curcell 'range)
+without any check, otherwise function (ses-check-curcell \\='range)
is called.
For an individual cell, shows the error if the formula or printer
@@ -2507,7 +2537,7 @@ Return nil if cell formula was unsafe and user declined confirmation."
;; Position cursor inside close-quote.
(setq initial (cons initial (length initial))))
(dolist (key ses-completion-keys)
- (define-key ses-mode-edit-map key 'ses-edit-cell-complete-symbol))
+ (define-key ses-mode-edit-map key #'ses-edit-cell-complete-symbol))
;; make it globally visible, so that it can be visible from the minibuffer.
(setq ses--completion-table ses--named-cell-hashmap)
(list row col
@@ -2604,8 +2634,9 @@ With prefix, deletes several cells."
;;----------------------------------------------------------------------------
(defun ses-read-printer-complete-symbol ()
(interactive)
- (let ((completion-at-point-functions (cons 'ses--read-printer-completion-at-point-function
- completion-at-point-functions)))
+ (let ((completion-at-point-functions
+ (cons #'ses--read-printer-completion-at-point-function
+ completion-at-point-functions)))
(completion-at-point)))
(defun ses--read-printer-completion-at-point-function ()
@@ -2647,7 +2678,7 @@ canceled."
(setq default "")
(setq prompt (format-prompt prompt default)))
(dolist (key ses-completion-keys)
- (define-key ses-mode-edit-map key 'ses-read-printer-complete-symbol))
+ (define-key ses-mode-edit-map key #'ses-read-printer-complete-symbol))
;; make it globally visible, so that it can be visible from the minibuffer.
(setq ses--completion-table ses--local-printer-hashmap)
(let ((new (read-from-minibuffer prompt
@@ -3743,15 +3774,15 @@ DEFINITION shall be either a string formatter, e.g.:
\"%.2f\" or (\"%.2f\") for left alignment.
or a lambda expression, e.g. for formatting in ISO format dates
-created with a '(calcFunc-date YEAR MONTH DAY)' formula:
+created with a `(calcFunc-date YEAR MONTH DAY)' formula:
(lambda (x)
(cond
((null val) \"\")
- ((eq (car-safe x) 'date)
- (let ((calc-format-date '(X YYYY \"-\" MM \"-\" DD)))
+ ((eq (car-safe x) \\='date)
+ (let ((calc-format-date \\='(X YYYY \"-\" MM \"-\" DD)))
(math-format-date x)))
- (t (ses-center-span val ?# 'ses-prin1))))
+ (t (ses-center-span val ?# \\='ses-prin1))))
If NAME is already used to name a local printer function, then
the current definition is proposed as default value, and the
@@ -4079,17 +4110,19 @@ SPAN indicates how many rightward columns to include in width (default = 0)."
(ses-center value span ?- printer))
(defun ses-dashfill-span (value &optional printer)
- "Print VALUE, centered using dashes within the span that starts in the
-current column and continues until the next nonblank column."
+ "Print VALUE, centered using dashes.
+Centers within the span that starts in the current column and continues
+until the next nonblank column."
(ses-center-span value ?- printer))
(defun ses-tildefill-span (value &optional printer)
- "Print VALUE, centered using tildes within the span that starts in the
-current column and continues until the next nonblank column."
+ "Print VALUE, centered using tildes.
+Centers within the span that starts in the current column and continues
+until the next nonblank column."
(ses-center-span value ?~ printer))
(defun ses-prin1 (value)
- "Shorthand for '(prin1-to-string VALUE t)'.
+ "Shorthand for `(prin1-to-string VALUE t)'.
Useful to handle the default behavior in custom lambda based
printer functions."
(prin1-to-string value t))
diff --git a/lisp/shell.el b/lisp/shell.el
index dcb6bea0421..85225b128ab 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -98,6 +98,7 @@
(require 'comint)
(require 'pcomplete)
(eval-when-compile (require 'files-x)) ;with-connection-local-variables
+(require 'subr-x)
;;; Customization and Buffer Variables
@@ -330,6 +331,12 @@ Useful for shells like zsh that has this feature."
:group 'shell-directories
:version "28.1")
+(defcustom shell-kill-buffer-on-exit nil
+ "Kill a shell buffer after the shell process terminates."
+ :type 'boolean
+ :group 'shell
+ :version "29.1")
+
(defvar shell-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c\C-f" 'shell-forward-command)
@@ -433,12 +440,11 @@ Useful for shells like zsh that has this feature."
(push (point) begins)
(let ((arg ()))
(while (looking-at
- (eval-when-compile
- (concat
- "\\(?:[^\s\t\n\\\"';]+"
- "\\|'\\([^']*\\)'?"
- "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?"
- "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)")))
+ (concat
+ "\\(?:[^\s\t\n\\\"';]+"
+ "\\|'\\([^']*\\)'?"
+ "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?"
+ "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)"))
(goto-char (match-end 0))
(cond
((match-beginning 3) ;Backslash escape.
@@ -527,7 +533,7 @@ Shell buffers. It implements `shell-completion-execonly' for
the shell. This is useful for entering passwords. Or, add the function
`comint-watch-for-password-prompt' to `comint-output-filter-functions'.
-If you want to make multiple shell buffers, rename the `*shell*' buffer
+If you want to make multiple shell buffers, rename the \"*shell*\" buffer
using \\[rename-buffer] or \\[rename-uniquely] and start a new shell.
If you want to make shell buffers limited in length, add the function
@@ -570,7 +576,14 @@ the initialization of the input ring history, and history expansion.
Variables `comint-output-filter-functions', a hook, and
`comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
control whether input and output cause the window to scroll to the end of the
-buffer."
+buffer.
+
+By default, shell mode does nothing special when it receives a
+\"bell\" character (C-g or ^G). If you
+ (add-hook \\='comint-output-filter-functions #\\='shell-filter-ring-bell nil t)
+from `shell-mode-hook', Emacs will call the `ding' function
+whenever it receives the bell character in output from a
+command."
:interactive nil
(setq comint-prompt-regexp shell-prompt-pattern)
(shell-completion-vars)
@@ -681,6 +694,13 @@ This function can be put on `comint-preoutput-filter-functions'."
(replace-regexp-in-string "[\C-a\C-b]" "" string t t)
string))
+(defun shell-filter-ring-bell (string)
+ "Call `ding' if STRING contains a \"^G\" character.
+This function can be put on `comint-output-filter-functions'."
+ (when (string-search "\a" string)
+ (ding))
+ string)
+
(defun shell-write-history-on-exit (process event)
"Called when the shell process is stopped.
@@ -698,7 +718,7 @@ Sentinels will always get the two parameters PROCESS and EVENT."
(insert (format "\nProcess %s %s\n" process event))))))
;;;###autoload
-(defun shell (&optional buffer)
+(defun shell (&optional buffer file-name)
"Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*').
Interactively, a prefix arg means to prompt for BUFFER.
If `default-directory' is a remote file name, it is also prompted
@@ -709,6 +729,8 @@ If BUFFER exists and shell process is running, just switch to BUFFER.
Program used comes from variable `explicit-shell-file-name',
or (if that is nil) from the ESHELL environment variable,
or (if that is nil) from `shell-file-name'.
+Non-interactively, it can also be specified via the FILE-NAME arg.
+
If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
it is given as initial input (but this may be lost, due to a timing
error, if the shell discards input when it starts up).
@@ -732,25 +754,47 @@ Make the shell buffer the current buffer, and return it.
\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
(interactive
- (list
- (and current-prefix-arg
- (prog1
- (read-buffer "Shell buffer: "
- ;; If the current buffer is an inactive
- ;; shell buffer, use it as the default.
- (if (and (eq major-mode 'shell-mode)
- (null (get-buffer-process (current-buffer))))
- (buffer-name)
- (generate-new-buffer-name "*shell*")))
- (if (file-remote-p default-directory)
- ;; It must be possible to declare a local default-directory.
- ;; FIXME: This can't be right: it changes the default-directory
- ;; of the current-buffer rather than of the *shell* buffer.
- (setq default-directory
- (expand-file-name
- (read-directory-name
- "Default directory: " default-directory default-directory
- t nil))))))))
+ (let* ((buffer
+ (and current-prefix-arg
+ (read-buffer "Shell buffer: "
+ ;; If the current buffer is an inactive
+ ;; shell buffer, use it as the default.
+ (if (and (eq major-mode 'shell-mode)
+ (null (get-buffer-process
+ (current-buffer))))
+ (buffer-name)
+ (generate-new-buffer-name "*shell*")))))
+ (buf (if (or buffer (not (derived-mode-p 'shell-mode))
+ (comint-check-proc (current-buffer)))
+ (get-buffer-create (or buffer "*shell*"))
+ ;; If the current buffer is a dead shell buffer, use it.
+ (current-buffer))))
+
+ (with-current-buffer buf
+ (when (and buffer (file-remote-p default-directory))
+ ;; It must be possible to declare a local default-directory.
+ (setq default-directory
+ (expand-file-name
+ (read-directory-name
+ "Default directory: " default-directory default-directory
+ t nil))))
+ (list
+ buffer
+ ;; On remote hosts, the local `shell-file-name' might be useless.
+ (with-connection-local-variables
+ (when (and (file-remote-p default-directory)
+ (null explicit-shell-file-name)
+ (null (getenv "ESHELL")))
+ ;; `expand-file-name' shall not add the MS Windows volume letter
+ ;; (Bug#49229).
+ (replace-regexp-in-string
+ "^[[:alpha:]]:" ""
+ (file-local-name
+ (expand-file-name
+ (read-file-name "Remote shell path: " default-directory
+ shell-file-name t shell-file-name
+ #'file-remote-p))))))))))
+
(setq buffer (if (or buffer (not (derived-mode-p 'shell-mode))
(comint-check-proc (current-buffer)))
(get-buffer-create (or buffer "*shell*"))
@@ -758,24 +802,11 @@ Make the shell buffer the current buffer, and return it.
(current-buffer)))
;; The buffer's window must be correctly set when we call comint
;; (so that comint sets the COLUMNS env var properly).
- (pop-to-buffer buffer)
+ (pop-to-buffer buffer display-comint-buffer-action)
(with-connection-local-variables
- ;; On remote hosts, the local `shell-file-name' might be useless.
- (when (and (file-remote-p default-directory)
- (called-interactively-p 'any)
- (null explicit-shell-file-name)
- (null (getenv "ESHELL")))
- ;; `expand-file-name' shall not add the MS Windows volume letter
- ;; (Bug#49229).
- (setq-local explicit-shell-file-name
- (replace-regexp-in-string
- "^[[:alpha:]]:" ""
- (file-local-name
- (expand-file-name
- (read-file-name "Remote shell path: " default-directory
- shell-file-name t shell-file-name
- #'file-remote-p))))))
+ (when file-name
+ (setq-local explicit-shell-file-name file-name))
;; Rain or shine, BUFFER must be current by now.
(unless (comint-check-proc buffer)
@@ -783,17 +814,37 @@ Make the shell buffer the current buffer, and return it.
(getenv "ESHELL") shell-file-name))
(name (file-name-nondirectory prog))
(startfile (concat "~/.emacs_" name))
- (xargs-name (intern-soft (concat "explicit-" name "-args"))))
+ (xargs-name (intern-soft (concat "explicit-" name "-args")))
+ (start-point (point)))
(unless (file-exists-p startfile)
(setq startfile (locate-user-emacs-file
(concat "init_" name ".sh"))))
(setq-local shell--start-prog (file-name-nondirectory prog))
(apply #'make-comint-in-buffer "shell" buffer prog
- (if (file-exists-p startfile) startfile)
+ nil
(if (and xargs-name (boundp xargs-name))
(symbol-value xargs-name)
'("-i")))
- (shell-mode))))
+ (shell-mode)
+ (when (file-exists-p startfile)
+ ;; Wait until the prompt has appeared.
+ (while (= start-point (point))
+ (sleep-for 0.1))
+ (shell-eval-command
+ (with-temp-buffer
+ (insert-file-contents startfile)
+ (buffer-string)))))))
+ (when shell-kill-buffer-on-exit
+ (let* ((buffer (current-buffer))
+ (process (get-buffer-process buffer))
+ (sentinel (process-sentinel process)))
+ (set-process-sentinel
+ process
+ (lambda (proc event)
+ (when sentinel
+ (funcall sentinel proc event))
+ (unless (buffer-live-p proc)
+ (kill-buffer buffer))))))
buffer)
;;; Directory tracking
@@ -942,7 +993,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
dir
(if (file-name-absolute-p dir)
;; The name is absolute, so prepend the prefix.
- (concat comint-file-name-prefix dir)
+ (concat comint-file-name-prefix (file-local-name dir))
;; For relative name we assume default-directory already has the prefix.
(expand-file-name dir))))
@@ -1009,7 +1060,9 @@ Environment variables are expanded, see function `substitute-in-file-name'."
"Toggle directory tracking in this shell buffer (Shell Dirtrack mode).
The `dirtrack' package provides an alternative implementation of
-this feature; see the function `dirtrack-mode'."
+this feature; see the function `dirtrack-mode'. Also see
+`comint-osc-directory-tracker' for an escape-sequence based
+solution."
:lighter nil
(setq list-buffers-directory (if shell-dirtrack-mode default-directory))
(if shell-dirtrack-mode
@@ -1026,77 +1079,45 @@ this feature; see the function `dirtrack-mode'."
"Resync the buffer's idea of the current directory stack.
This command queries the shell with the command bound to
`shell-dirstack-query' (default \"dirs\"), reads the next
-line output and parses it to form the new directory stack.
-DON'T issue this command unless the buffer is at a shell prompt.
-Also, note that if some other subprocess decides to do output
-immediately after the query, its output will be taken as the
-new directory stack -- you lose. If this happens, just do the
-command again."
+line output and parses it to form the new directory stack."
(interactive)
- (let* ((proc (get-buffer-process (current-buffer)))
- (pmark (process-mark proc))
- (started-at-pmark (= (point) (marker-position pmark))))
- (save-excursion
- (goto-char pmark)
- ;; If the process echoes commands, don't insert a fake command in
- ;; the buffer or it will appear twice.
- (unless comint-process-echoes
- (insert shell-dirstack-query) (insert "\n"))
- (sit-for 0) ; force redisplay
- (comint-send-string proc shell-dirstack-query)
- (comint-send-string proc "\n")
- (set-marker pmark (point))
- (let ((pt (point))
- (regexp
- (concat
- (if comint-process-echoes
- ;; Skip command echo if the process echoes
- (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
- "\\(\\)")
- "\\(.+\n\\)")))
- ;; This extra newline prevents the user's pending input from spoofing us.
- (insert "\n") (backward-char 1)
- ;; Wait for one line.
- (while (not (looking-at regexp))
- (accept-process-output proc)
- (goto-char pt)))
- (goto-char pmark) (delete-char 1) ; remove the extra newline
- ;; That's the dirlist. Grab it & parse it.
- (let* ((dls (buffer-substring-no-properties
- (match-beginning 0) (1- (match-end 0))))
- (dlsl nil)
- (pos 0)
- (ds nil))
- ;; Split the dirlist into whitespace and non-whitespace chunks.
- ;; dlsl will be a reversed list of tokens.
- (while (string-match "\\(\\S-+\\|\\s-+\\)" dls pos)
- (push (match-string 1 dls) dlsl)
- (setq pos (match-end 1)))
-
- ;; Prepend trailing entries until they form an existing directory,
- ;; whitespace and all. Discard the next whitespace and repeat.
- (while dlsl
- (let ((newelt "")
- tem1 tem2)
- (while newelt
- ;; We need tem1 because we don't want to prepend
- ;; `comint-file-name-prefix' repeatedly into newelt via tem2.
- (setq tem1 (pop dlsl)
- tem2 (concat comint-file-name-prefix tem1 newelt))
- (cond ((file-directory-p tem2)
- (push tem2 ds)
- (when (string= " " (car dlsl))
- (pop dlsl))
- (setq newelt nil))
- (t
- (setq newelt (concat tem1 newelt)))))))
-
- (with-demoted-errors "Couldn't cd: %s"
- (shell-cd (car ds))
- (setq shell-dirstack (cdr ds)
- shell-last-dir (car shell-dirstack))
- (shell-dirstack-message))))
- (if started-at-pmark (goto-char (marker-position pmark)))))
+ (let* ((dls (car
+ (last
+ (string-lines
+ (string-chop-newline
+ (shell-eval-command (concat shell-dirstack-query "\n")))))))
+ (dlsl nil)
+ (pos 0)
+ (ds nil))
+ ;; Split the dirlist into whitespace and non-whitespace chunks.
+ ;; dlsl will be a reversed list of tokens.
+ (while (string-match "\\(\\S-+\\|\\s-+\\)" dls pos)
+ (push (match-string 1 dls) dlsl)
+ (setq pos (match-end 1)))
+
+ ;; Prepend trailing entries until they form an existing directory,
+ ;; whitespace and all. Discard the next whitespace and repeat.
+ (while dlsl
+ (let ((newelt "")
+ tem1 tem2)
+ (while newelt
+ ;; We need tem1 because we don't want to prepend
+ ;; `comint-file-name-prefix' repeatedly into newelt via tem2.
+ (setq tem1 (pop dlsl)
+ tem2 (concat comint-file-name-prefix tem1 newelt))
+ (cond ((file-directory-p tem2)
+ (push tem2 ds)
+ (when (string= " " (car dlsl))
+ (pop dlsl))
+ (setq newelt nil))
+ (t
+ (setq newelt (concat tem1 newelt)))))))
+
+ (with-demoted-errors "Couldn't cd: %s"
+ (shell-cd (car ds))
+ (setq shell-dirstack (cdr ds)
+ shell-last-dir (car shell-dirstack))
+ (shell-dirstack-message))))
;; For your typing convenience:
(defalias 'dirs 'shell-resync-dirs)
@@ -1431,6 +1452,36 @@ Returns t if successful."
(point-max)
(shell--prompt-begin-position))))))
+(defun shell-eval-command (command)
+ "Eval COMMAND in the current shell process and return the result."
+ (let* ((proc (get-buffer-process (current-buffer)))
+ (old-filter (process-filter proc))
+ (result "")
+ prev)
+ (unwind-protect
+ (progn
+ (set-process-filter
+ proc
+ (lambda (_proc string)
+ (setq result (concat result string))))
+ (process-send-string proc command)
+ ;; Wait until we get a prompt (which will be a line without
+ ;; a newline). This is far from fool-proof -- if something
+ ;; outputs incomplete data and then sleeps, we'll think
+ ;; we've received the prompt.
+ (while (not (let* ((lines (string-lines result))
+ (last (car (last lines))))
+ (and (length> lines 0)
+ (not (equal last ""))
+ (or (not prev)
+ (not (equal last prev)))
+ (setq prev last))))
+ (accept-process-output proc 0 100)))
+ ;; Restore old filter.
+ (set-process-filter proc old-filter))
+ ;; Remove the prompt.
+ (replace-regexp-in-string "\n.*\\'" "\n" result)))
+
(provide 'shell)
;;; shell.el ends here
diff --git a/lisp/simple.el b/lisp/simple.el
index 070d2764fe8..e048df36951 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -60,6 +60,24 @@ value of 1 means that nothing is amalgamated.")
(defgroup paren-matching nil
"Highlight (un)matching of parens and expressions."
:group 'matching)
+
+(defvar-local escaped-string-quote "\\"
+ "String to insert before a string quote character in a string to escape it.
+This is typically a backslash (in most languages):
+
+ \\='foo\\\\='bar\\='
+ \"foo\\\"bar\"
+
+But in SQL, for instance, it's \"\\='\":
+
+ \\='foo\\='\\='bar\\='
+
+This can also be a function, which is called with the string
+terminator as the argument, and should return a string to be
+used as the escape.
+
+This variable is used by the `yank-in-context' command.")
+
;;; next-error support framework
@@ -222,7 +240,7 @@ rejected, and the function returns nil."
(defcustom next-error-find-buffer-function #'ignore
"Function called to find a `next-error' capable buffer.
-This functions takes the same three arguments as the function
+This function takes the same three arguments as the function
`next-error-find-buffer', and should return the buffer to be
used by the subsequent invocation of the command `next-error'
and `previous-error'.
@@ -494,7 +512,7 @@ buffer causes automatic display of the corresponding source code location."
(error t))))
(defun next-error-message-highlight (error-buffer)
- "Highlight the current error message in the ‘next-error’ buffer."
+ "Highlight the current error message in the `next-error' buffer."
(when next-error-message-highlight
(with-current-buffer error-buffer
(when (and next-error--message-highlight-overlay
@@ -1072,15 +1090,26 @@ Leave one space or none, according to the context."
"Delete all spaces and tabs around point.
If BACKWARD-ONLY is non-nil, delete them only before point."
(interactive "*P")
+ (delete-space--internal " \t" backward-only))
+
+(defun delete-all-space (&optional backward-only)
+ "Delete all spaces, tabs, and newlines around point.
+If BACKWARD-ONLY is non-nil, delete them only before point."
+ (interactive "*P")
+ (delete-space--internal " \t\r\n" backward-only))
+
+(defun delete-space--internal (chars backward-only)
+ "Delete CHARS around point.
+If BACKWARD-ONLY is non-nil, delete them only before point."
(let ((orig-pos (point)))
(delete-region
(if backward-only
- orig-pos
+ orig-pos
(progn
- (skip-chars-forward " \t")
- (constrain-to-field nil orig-pos t)))
+ (skip-chars-forward chars)
+ (constrain-to-field nil orig-pos t)))
(progn
- (skip-chars-backward " \t")
+ (skip-chars-backward chars)
(constrain-to-field nil orig-pos)))))
(defun just-one-space (&optional n)
@@ -1088,73 +1117,225 @@ If BACKWARD-ONLY is non-nil, delete them only before point."
If N is negative, delete newlines as well, leaving -N spaces.
See also `cycle-spacing'."
(interactive "*p")
- (cycle-spacing n nil 'single-shot))
+ (let ((orig-pos (point))
+ (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+ (num (abs (or n 1))))
+ (skip-chars-backward skip-characters)
+ (constrain-to-field nil orig-pos)
+ (let* ((num (- num (skip-chars-forward " " (+ num (point)))))
+ (mid (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (delete-region mid end)
+ (insert (make-string num ?\s)))))
(defvar cycle-spacing--context nil
- "Store context used in consecutive calls to `cycle-spacing' command.
-The first time `cycle-spacing' runs, it saves in this variable:
-its N argument, the original point position, and the original spacing
-around point.")
+ "Stored context used in consecutive calls to `cycle-spacing' command.
+The value is a property list with the following elements:
+- `:orig-pos' The original position of point when starting the
+ sequence.
+- `:whitespace-string' All whitespace characters around point
+ including newlines.
+- `:n' The prefix arg given to the initial invocation
+ which is reused for all actions in this cycle.
+- `:last-action' The last action performed in the cycle.")
+
+(defcustom cycle-spacing-actions
+ '( just-one-space
+ delete-all-space
+ restore)
+ "List of actions cycled through by `cycle-spacing'.
+Supported values are:
+- `just-one-space' Delete all but N (prefix arg) spaces.
+ See that command's docstring for details.
+- `delete-space-after' Delete spaces after point keeping only N.
+- `delete-space-before' Delete spaces before point keeping only N.
+- `delete-all-space' Delete all spaces around point.
+- `restore' Restore the original spacing.
+
+All actions make use of the prefix arg given to `cycle-spacing'
+in the initial invocation, i.e., `just-one-space' keeps this
+amount of spaces deleting surplus ones. `just-one-space' and all
+other actions have the contract that a positive prefix arg (or
+zero) only deletes tabs and spaces whereas a negative prefix arg
+also deletes newlines.
+
+The `delete-space-before' and `delete-space-after' actions handle
+the prefix arg \\[negative-argument] without a number provided
+specially: all spaces before/after point are deleted (as if N was
+0) including newlines (as if N was negative).
+
+In addition to the predefined actions listed above, any function
+which accepts one argument is allowed. It receives the raw
+prefix arg of this cycle.
+
+In addition, an action may take the form (ACTION ARG) where
+ACTION is one of the predefined actions (except for `restore')
+and ARG is either
+- an integer with the meaning that ACTION should always use this
+ fixed integer instead of the actual prefix arg or
+- the symbol `inverted-arg' with the meaning that ACTION should
+ be performed with the inverted actual prefix arg.
+- the symbol `-' with the meaning that ACTION should include
+ newlines but it's up to the ACTION to decide how to interpret
+ it as a number, e.g., `delete-space-before' and
+ `delete-space-after' treat it like 0 whereas `just-one-space'
+ treats it like -1 as is usual."
+ :group 'editing-basics
+ :type (let ((actions
+ '((const :tag "Just N (prefix arg) spaces" just-one-space)
+ (const :tag "Delete spaces after point" delete-space-after)
+ (const :tag "Delete spaces before point" delete-space-before)
+ (const :tag "Delete all spaces around point" delete-all-space)
+ (function :tag "Function receiving a numeric arg"))))
+ `(repeat
+ (choice
+ ,@actions
+ (list :tag "Action with modified arg"
+ (choice ,@actions)
+ (choice (const :tag "Inverted prefix arg" inverted-arg)
+ (integer :tag "Fixed numeric arg")
+ (const :tag "Negative arg" -)))
+ (const :tag "Restore the original spacing" restore))))
+ :version "29.1")
-(defun cycle-spacing (&optional n preserve-nl-back mode)
+(defun cycle-spacing (&optional n)
"Manipulate whitespace around point in a smart way.
-In interactive use, this function behaves differently in successive
-consecutive calls.
-
-The first call in a sequence acts like `just-one-space'.
-It deletes all spaces and tabs around point, leaving one space
-\(or N spaces). N is the prefix argument. If N is negative,
-it deletes newlines as well, leaving -N spaces.
-\(If PRESERVE-NL-BACK is non-nil, it does not delete newlines before point.)
-
-The second call in a sequence deletes all spaces.
-
-The third call in a sequence restores the original whitespace (and point).
-
-If MODE is `single-shot', it performs only the first step in the sequence.
-If MODE is `fast' and the first step would not result in any change
-\(i.e., there are exactly (abs N) spaces around point),
-the function goes straight to the second step.
-
-Repeatedly calling the function with different values of N starts a
-new sequence each time."
- (interactive "*p")
- (let ((orig-pos (point))
- (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
- (num (abs (or n 1))))
- (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
- (constrain-to-field nil orig-pos)
- (cond
- ;; Command run for the first time, single-shot mode or different argument
- ((or (eq 'single-shot mode)
- (not (equal last-command this-command))
- (not cycle-spacing--context)
- (not (eq (car cycle-spacing--context) n)))
- (let* ((start (point))
- (num (- num (skip-chars-forward " " (+ num (point)))))
- (mid (point))
- (end (progn
- (skip-chars-forward skip-characters)
- (constrain-to-field nil orig-pos t))))
- (setq cycle-spacing--context ;; Save for later.
- ;; Special handling for case where there was no space at all.
- (unless (= start end)
- (cons n (cons orig-pos (buffer-substring start (point))))))
- ;; If this run causes no change in buffer content, delete all spaces,
- ;; otherwise delete all excess spaces.
- (delete-region (if (and (eq mode 'fast) (zerop num) (= mid end))
- start mid) end)
- (insert (make-string num ?\s))))
-
- ;; Command run for the second time.
- ((not (equal orig-pos (point)))
- (delete-region (point) orig-pos))
-
- ;; Command run for the third time.
- (t
- (insert (cddr cycle-spacing--context))
- (goto-char (cadr cycle-spacing--context))
- (setq cycle-spacing--context nil)))))
+Repeated calls perform the actions in `cycle-spacing-actions' one
+after the other, wrapping around after the last one.
+
+All actions are amendable using a prefix arg N. In general, a
+zero or positive prefix arg allows only for deletion of tabs and
+spaces whereas a negative prefix arg also allows for deleting
+newlines.
+
+The prefix arg given at the first invocation starting a cycle is
+provided to all following actions, i.e.,
+ \\[negative-argument] \\[cycle-spacing] \\[cycle-spacing] \\[cycle-spacing]
+is equivalent to
+ \\[negative-argument] \\[cycle-spacing] \\[negative-argument] \\[cycle-spacing] \\[negative-argument] \\[cycle-spacing].
+
+A new sequence can be started by providing a different prefix arg
+than provided at the initial invocation (except for 1), or by
+doing any other command before the next \\[cycle-spacing]."
+ (interactive "*P")
+ ;; Initialize `cycle-spacing--context' if needed.
+ (when (or (not (equal last-command this-command))
+ (not cycle-spacing--context)
+ ;; With M-5 M-SPC M-SPC... we pass the prefix arg 5 to
+ ;; each action and only start a new cycle when a different
+ ;; prefix arg is given and which is not the default value
+ ;; 1.
+ (and n (not (equal (plist-get cycle-spacing--context :n)
+ n))))
+ (let ((orig-pos (point))
+ (skip-characters " \t\n\r"))
+ (save-excursion
+ (skip-chars-backward skip-characters)
+ (constrain-to-field nil orig-pos)
+ (let ((start (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (setq cycle-spacing--context ;; Save for later.
+ (list :orig-pos orig-pos
+ :whitespace-string (buffer-substring start end)
+ :n n
+ :last-action nil))))))
+
+ ;; Cycle through the actions in `cycle-spacing-actions'.
+ (when cycle-spacing--context
+ (cl-labels ((next-action ()
+ (let* ((l cycle-spacing-actions)
+ (elt (plist-get cycle-spacing--context
+ :last-action)))
+ (if (null elt)
+ (car cycle-spacing-actions)
+ (catch 'found
+ (while l
+ (cond
+ ((null (cdr l))
+ (throw 'found
+ (when (eq elt (car l))
+ (car cycle-spacing-actions))))
+ ((and (eq elt (car l))
+ (cdr l))
+ (throw 'found (cadr l)))
+ (t (setq l (cdr l)))))))))
+ (skip-chars (chars max-dist direction)
+ (if (eq direction 'forward)
+ (skip-chars-forward
+ chars
+ (and max-dist (+ (point) max-dist)))
+ (skip-chars-backward
+ chars
+ (and max-dist (- (point) max-dist)))))
+ (delete-space (n include-newlines direction)
+ (let ((orig-point (point))
+ (chars (if include-newlines
+ " \t\r\n"
+ " \t")))
+ (when (or (zerop n)
+ (= n (abs (skip-chars chars n direction))))
+ (let ((start (point))
+ (end (progn
+ (skip-chars chars nil direction)
+ (point))))
+ (unless (= start end)
+ (delete-region start end))
+ (goto-char (if (eq direction 'forward)
+ orig-point
+ (+ n end)))))))
+ (restore ()
+ (delete-all-space)
+ (insert (plist-get cycle-spacing--context
+ :whitespace-string))
+ (goto-char (plist-get cycle-spacing--context
+ :orig-pos))))
+ (let ((action (next-action)))
+ (atomic-change-group
+ (restore)
+ (unless (eq action 'restore)
+ ;; action can be some-action or (some-action <arg>) where
+ ;; arg is either an integer, the arg to be always used for
+ ;; this action or - to use the inverted context n for this
+ ;; action.
+ (let* ((actual-action (if (listp action)
+ (car action)
+ action))
+ (arg (when (listp action)
+ (nth 1 action)))
+ (context-n (plist-get cycle-spacing--context :n))
+ (actual-n (cond
+ ((integerp arg) arg)
+ ((eq 'inverted-arg arg)
+ (* -1 (prefix-numeric-value context-n)))
+ ((eq '- arg) '-)
+ (t context-n)))
+ (numeric-n (prefix-numeric-value actual-n))
+ (include-newlines (or (eq actual-n '-)
+ (and (integerp actual-n)
+ (< actual-n 0)))))
+ (cond
+ ((eq actual-action 'just-one-space)
+ (just-one-space numeric-n))
+ ((eq actual-action 'delete-space-after)
+ (delete-space (if (eq actual-n '-) 0 (abs numeric-n))
+ include-newlines 'forward))
+ ((eq actual-action 'delete-space-before)
+ (delete-space (if (eq actual-n '-) 0 (abs numeric-n))
+ include-newlines 'backward))
+ ((eq actual-action 'delete-all-space)
+ (if include-newlines
+ (delete-all-space)
+ (delete-horizontal-space)))
+ ((functionp actual-action)
+ (funcall actual-action actual-n))
+ (t
+ (error "Don't know how to handle action %S" action)))))
+ (setf (plist-get cycle-spacing--context :last-action)
+ action))))))
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer.
@@ -1292,6 +1473,11 @@ If Transient Mark mode is enabled, the mark is active, and N is 1,
delete the text in the region and deactivate the mark instead.
To disable this, set variable `delete-active-region' to nil.
+If N is positive, characters composed into a single grapheme cluster
+count as a single character and are deleted together. Thus,
+\"\\[universal-argument] 2 \\[delete-forward-char]\" when two grapheme clusters follow point will
+delete the characters composed into both of the grapheme clusters.
+
Optional second arg KILLFLAG non-nil means to kill (save in kill
ring) instead of delete. If called interactively, a numeric
prefix argument specifies N, and KILLFLAG is also set if a prefix
@@ -1312,6 +1498,34 @@ the actual saved text might be different from what was killed."
(kill-region (region-beginning) (region-end) 'region)
(funcall region-extract-function 'delete-only)))
+ ;; For forward deletion, treat composed characters as a single
+ ;; character to delete.
+ ((>= n 1)
+ (let ((pos (point))
+ start cmp)
+ (setq start pos)
+ (while (> n 0)
+ ;; 'find-composition' will return (FROM TO ....) or nil.
+ (setq cmp (find-composition pos))
+ (setq pos
+ (if cmp
+ (let ((from (car cmp))
+ (to (cadr cmp)))
+ (cond
+ ((= (length cmp) 2) ; static composition
+ to)
+ ;; TO can be at POS, in which case we want
+ ;; to make sure we advance at least by 1
+ ;; character.
+ ((<= to pos)
+ (1+ pos))
+ (t
+ (lgstring-glyph-boundary (nth 2 cmp)
+ from (1+ pos)))))
+ (1+ pos)))
+ (setq n (1- n)))
+ (delete-char (- pos start) killflag)))
+
;; Otherwise, do simple deletion.
(t (delete-char n killflag))))
@@ -1457,53 +1671,67 @@ START and END."
(cond ((not (called-interactively-p 'any))
(count-words start end))
(arg
- (count-words--buffer-message))
+ (message "%s" (count-words--buffer-format)))
(t
- (count-words--message "Region" start end))))
+ (message "%s" (count-words--format "Region" start end)))))
-(defun count-words (start end)
+(defun count-words (start end &optional totals)
"Count words between START and END.
If called interactively, START and END are normally the start and
end of the buffer; but if the region is active, START and END are
the start and end of the region. Print a message reporting the
-number of lines, words, and chars.
+number of lines, sentences, words, and chars. With prefix
+argument, also include the data for the entire (un-narrowed)
+buffer.
If called from Lisp, return the number of words between START and
-END, without printing any message."
- (interactive (list nil nil))
- (cond ((not (called-interactively-p 'any))
- (let ((words 0)
- ;; Count across field boundaries. (Bug#41761)
- (inhibit-field-text-motion t))
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (while (forward-word-strictly 1)
- (setq words (1+ words)))))
- words))
- ((use-region-p)
- (call-interactively 'count-words-region))
- (t
- (count-words--buffer-message))))
-
-(defun count-words--buffer-message ()
- (count-words--message
+END, without printing any message. TOTALS is ignored when called
+from Lisp."
+ (interactive (list nil nil current-prefix-arg))
+ ;; When called from Lisp, return the data.
+ (if (not (called-interactively-p 'any))
+ (let ((words 0)
+ ;; Count across field boundaries. (Bug#41761)
+ (inhibit-field-text-motion t))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (forward-word-strictly 1)
+ (setq words (1+ words)))))
+ words)
+ ;; When called interactively, message the data.
+ (let ((totals (if (and totals
+ (or (use-region-p)
+ (buffer-narrowed-p)))
+ (save-restriction
+ (widen)
+ (count-words--format "; buffer in total"
+ (point-min) (point-max)))
+ "")))
+ (if (use-region-p)
+ (message "%s%s" (count-words--format
+ "Region" (region-beginning) (region-end))
+ totals)
+ (message "%s%s" (count-words--buffer-format) totals)))))
+
+(defun count-words--buffer-format ()
+ (count-words--format
(if (buffer-narrowed-p) "Narrowed part of buffer" "Buffer")
(point-min) (point-max)))
-(defun count-words--message (str start end)
+(defun count-words--format (str start end)
(let ((lines (count-lines start end))
+ (sentences (count-sentences start end))
(words (count-words start end))
(chars (- end start)))
- (message "%s has %d line%s, %d word%s, and %d character%s."
+ (format "%s has %d line%s, %d sentence%s, %d word%s, and %d character%s"
str
lines (if (= lines 1) "" "s")
+ sentences (if (= sentences 1) "" "s")
words (if (= words 1) "" "s")
chars (if (= chars 1) "" "s"))))
-(define-obsolete-function-alias 'count-lines-region 'count-words-region "24.1")
-
(defun what-line ()
"Print the current buffer line number and narrowed line number of point."
(interactive)
@@ -1721,10 +1949,6 @@ Such arguments are used as in `read-from-minibuffer'.)"
;; Used for interactive spec `X'.
(eval (read--expression prompt initial-contents)))
-(defvar minibuffer-completing-symbol nil
- "Non-nil means completing a Lisp symbol in the minibuffer.")
-(make-obsolete-variable 'minibuffer-completing-symbol nil "24.1" 'get)
-
(defvar minibuffer-default nil
"The current default value or list of default values in the minibuffer.
The functions `read-from-minibuffer' and `completing-read' bind
@@ -1785,20 +2009,19 @@ display the result of expression evaluation."
PROMPT and optional argument INITIAL-CONTENTS do the same as in
function `read-from-minibuffer'."
- (let ((minibuffer-completing-symbol t))
- (minibuffer-with-setup-hook
- (lambda ()
- ;; FIXME: instead of just applying the syntax table, maybe
- ;; use a special major mode tailored to reading Lisp
- ;; expressions from the minibuffer? (`emacs-lisp-mode'
- ;; doesn't preserve the necessary keybindings.)
- (set-syntax-table emacs-lisp-mode-syntax-table)
- (add-hook 'completion-at-point-functions
- #'elisp-completion-at-point nil t)
- (run-hooks 'eval-expression-minibuffer-setup-hook))
- (read-from-minibuffer prompt initial-contents
- read-expression-map t
- 'read-expression-history))))
+ (minibuffer-with-setup-hook
+ (lambda ()
+ ;; FIXME: instead of just applying the syntax table, maybe
+ ;; use a special major mode tailored to reading Lisp
+ ;; expressions from the minibuffer? (`emacs-lisp-mode'
+ ;; doesn't preserve the necessary keybindings.)
+ (set-syntax-table emacs-lisp-mode-syntax-table)
+ (add-hook 'completion-at-point-functions
+ #'elisp-completion-at-point nil t)
+ (run-hooks 'eval-expression-minibuffer-setup-hook))
+ (read-from-minibuffer prompt initial-contents
+ read-expression-map t
+ 'read-expression-history)))
(defun read--expression-try-read ()
"Try to read an Emacs Lisp expression in the minibuffer.
@@ -1981,7 +2204,7 @@ to get different commands to edit and resubmit."
If it's nil, include all the commands.
If it's a function, it will be called with two parameters: the
symbol of the command and a buffer. The predicate should return
-non-nil if the command should be present when doing `M-x TAB'
+non-nil if the command should be present when doing \\`M-x TAB'
in that buffer."
:version "28.1"
:group 'completion
@@ -1990,9 +2213,53 @@ in that buffer."
command-completion-default-include-p)
(function :tag "Other function")))
-(defun read-extended-command ()
+(defun execute-extended-command-cycle ()
+ "Choose the next version of the extended command predicates.
+See `extended-command-versions'."
+ (interactive)
+ (throw 'cycle
+ (cons (minibuffer-contents)
+ (- (point) (minibuffer-prompt-end)))))
+
+(defvar extended-command-versions
+ (list (list "M-x " (lambda () read-extended-command-predicate))
+ (list "M-X " #'command-completion--command-for-this-buffer-function))
+ "Alist of prompts and what the extended command predicate should be.
+This is used by the \\<minibuffer-local-must-match-map>\\[execute-extended-command-cycle] command when reading an extended command.")
+
+(defun read-extended-command (&optional prompt)
"Read command name to invoke in `execute-extended-command'.
This function uses the `read-extended-command-predicate' user option."
+ (let ((default-predicate read-extended-command-predicate)
+ (read-extended-command-predicate read-extended-command-predicate)
+ already-typed ret)
+ ;; If we have a prompt (which is the name of the version of the
+ ;; command), then set up the predicate from
+ ;; `extended-command-versions'.
+ (if (not prompt)
+ (setq prompt (caar extended-command-versions))
+ (setq read-extended-command-predicate
+ (funcall (cadr (assoc prompt extended-command-versions)))))
+ ;; Normally this will only execute once.
+ (while (not (stringp ret))
+ (when (consp (setq ret (catch 'cycle
+ (read-extended-command-1 prompt
+ already-typed))))
+ ;; But if the user hit `M-X', then we `throw'ed out to that
+ ;; `catch', and we cycle to the next setting.
+ (let ((next (or (cadr (memq (assoc prompt extended-command-versions)
+ extended-command-versions))
+ ;; Last one; cycle back to the first.
+ (car extended-command-versions))))
+ ;; Restore the user's default predicate.
+ (setq read-extended-command-predicate default-predicate)
+ ;; Then calculate the next.
+ (setq prompt (car next)
+ read-extended-command-predicate (funcall (cadr next))
+ already-typed ret))))
+ ret))
+
+(defun read-extended-command-1 (prompt initial-input)
(let ((buffer (current-buffer)))
(minibuffer-with-setup-hook
(lambda ()
@@ -2017,8 +2284,8 @@ This function uses the `read-extended-command-predicate' user option."
(cons def (delete def all))
all)))))
;; Read a string, completing from and restricting to the set of
- ;; all defined commands. Don't provide any initial input.
- ;; Save the command read on the extended-command history list.
+ ;; all defined commands. Save the command read on the
+ ;; extended-command history list.
(completing-read
(concat (cond
((eq current-prefix-arg '-) "- ")
@@ -2036,9 +2303,7 @@ This function uses the `read-extended-command-predicate' user option."
;; but actually a prompt other than "M-x" would be confusing,
;; because "M-x" is a well-known prompt to read a command
;; and it serves as a shorthand for "Extended command: ".
- (if (memq 'shift (event-modifiers last-command-event))
- "M-X "
- "M-x "))
+ (or prompt "M-x "))
(lambda (string pred action)
(if (and suggest-key-bindings (eq action 'metadata))
'(metadata
@@ -2077,12 +2342,12 @@ This function uses the `read-extended-command-predicate' user option."
(funcall read-extended-command-predicate sym buffer)
(error (message "read-extended-command-predicate: %s: %s"
sym (error-message-string err))))))))
- t nil 'extended-command-history))))
+ t initial-input 'extended-command-history))))
(defun command-completion-using-modes-p (symbol buffer)
"Say whether SYMBOL has been marked as a mode-specific command in BUFFER."
;; Check the modes.
- (let ((modes (command-modes symbol)))
+ (when-let ((modes (command-modes symbol)))
;; Common fast case: Just a single mode.
(if (null (cdr modes))
(or (provided-mode-derived-p
@@ -2233,6 +2498,11 @@ invoking, give a prefix argument to `execute-extended-command'."
(find-shorter nil))
(unless (commandp function)
(error "`%s' is not a valid command name" command-name))
+ ;; If we're executing a command that's remapped, we can't actually
+ ;; execute that command with the keymapping we've found with
+ ;; `where-is-internal'.
+ (when (and binding (command-remapping function))
+ (setq binding nil))
;; Some features, such as novice.el, rely on this-command-keys
;; including M-x COMMAND-NAME RET.
(set--this-command-keys (concat "\M-x" (symbol-name function) "\r"))
@@ -2303,27 +2573,80 @@ minor modes), as well as commands bound in the active local key
maps."
(declare (interactive-only command-execute))
(interactive
- (let* ((execute-extended-command--last-typed nil)
- (keymaps
- ;; The major mode's keymap and any active minor modes.
- (cons
- (current-local-map)
- (mapcar
- #'cdr
- (seq-filter
- (lambda (elem)
- (symbol-value (car elem)))
- minor-mode-map-alist))))
- (read-extended-command-predicate
- (lambda (symbol buffer)
- (or (command-completion-using-modes-p symbol buffer)
- (where-is-internal symbol keymaps)))))
+ (let ((execute-extended-command--last-typed nil))
(list current-prefix-arg
- (read-extended-command)
+ (read-extended-command "M-X ")
execute-extended-command--last-typed)))
(with-suppressed-warnings ((interactive-only execute-extended-command))
(execute-extended-command prefixarg command-name typed)))
+(defun command-completion--command-for-this-buffer-function ()
+ (let ((keymaps
+ ;; The major mode's keymap and any active minor modes.
+ (nconc
+ (and (current-local-map) (list (current-local-map)))
+ (mapcar
+ #'cdr
+ (seq-filter
+ (lambda (elem)
+ (symbol-value (car elem)))
+ minor-mode-map-alist)))))
+ (lambda (symbol buffer)
+ (or (command-completion-using-modes-p symbol buffer)
+ ;; Include commands that are bound in a keymap in the
+ ;; current buffer.
+ (and (where-is-internal symbol keymaps)
+ ;; But not if they have a command predicate that
+ ;; says that they shouldn't. (This is the case
+ ;; for `ignore' and `undefined' and similar
+ ;; commands commonly found in keymaps.)
+ (or (null (get symbol 'completion-predicate))
+ (funcall (get symbol 'completion-predicate)
+ symbol buffer)))))))
+
+(cl-defgeneric function-documentation (function)
+ "Extract the raw docstring info from FUNCTION.
+FUNCTION is expected to be a function value rather than, say, a mere symbol.
+This is intended to be specialized via `cl-defmethod' but not called directly:
+if you need a function's documentation use `documentation' which will call this
+function as needed."
+ (let ((docstring-p (lambda (doc)
+ ;; A docstring can be either a string or a reference
+ ;; into either the `etc/DOC' or a `.elc' file.
+ (or (stringp doc)
+ (fixnump doc) (fixnump (cdr-safe doc))))))
+ (pcase function
+ ((pred byte-code-function-p)
+ (when (> (length function) 4)
+ (let ((doc (aref function 4)))
+ (when (funcall docstring-p doc) doc))))
+ ((or (pred stringp) (pred vectorp)) "Keyboard macro.")
+ (`(keymap . ,_)
+ "Prefix command (definition is a keymap associating keystrokes with commands).")
+ ((or `(lambda ,_args . ,body) `(closure ,_env ,_args . ,body)
+ `(autoload ,_file . ,body))
+ (let ((doc (car body)))
+ (when (and (funcall docstring-p doc)
+ ;; Handle a doc reference--but these never come last
+ ;; in the function body, so reject them if they are last.
+ (or (cdr body) (eq 'autoload (car-safe function))))
+ doc)))
+ (_ (signal 'invalid-function (list function))))))
+
+(cl-defmethod function-documentation ((function accessor))
+ (oclosure--accessor-docstring function)) ;; FIXME: η-reduce!
+
+;; This should be in `oclosure.el' but that file is loaded before `cl-generic'.
+(cl-defgeneric oclosure-interactive-form (_function)
+ "Return the interactive form of FUNCTION or nil if none.
+This is called by `interactive-form' when invoked on OClosures.
+It should return either nil or a two-element list of the form (interactive FORM)
+where FORM is like the first arg of the `interactive' special form.
+Add your methods to this generic function, but always call `interactive-form'
+instead."
+ ;; (interactive-form function)
+ nil)
+
(defun command-execute (cmd &optional record-flag keys special)
;; BEWARE: Called directly from the C code.
"Execute CMD as an editor command.
@@ -2348,12 +2671,17 @@ don't clear it."
(setq current-prefix-arg prefix-arg)
(setq prefix-arg nil)
(when current-prefix-arg
- (prefix-command-update))))))
+ (prefix-command-update)))))
+ query)
(if (and (symbolp cmd)
(get cmd 'disabled)
- disabled-command-function)
- ;; FIXME: Weird calling convention!
- (run-hooks 'disabled-command-function)
+ (or (and (setq query (and (consp (get cmd 'disabled))
+ (eq (car (get cmd 'disabled)) 'query)))
+ (not (command-execute--query cmd)))
+ (and (not query) disabled-command-function)))
+ (when (not query)
+ ;; FIXME: Weird calling convention!
+ (run-hooks 'disabled-command-function))
(let ((final cmd))
(while
(progn
@@ -2377,6 +2705,21 @@ don't clear it."
(put cmd 'command-execute-obsolete-warned t)
(message "%s" (macroexp--obsolete-warning
cmd (get cmd 'byte-obsolete-info) "command"))))))))))
+
+(defun command-execute--query (command)
+ "Query the user whether to run COMMAND."
+ (let ((query (get command 'disabled)))
+ (funcall (if (nth 1 query) #'yes-or-no-p #'y-or-n-p)
+ (nth 2 query))))
+
+;;;###autoload
+(defun command-query (command query &optional verbose)
+ "Make executing COMMAND issue QUERY to the user.
+This will, by default, use `y-or-n-p', but if VERBOSE,
+`yes-or-no-p' is used instead."
+ (put command 'disabled
+ (list 'query (not (not verbose)) query)))
+
(defvar minibuffer-history nil
"Default minibuffer history list.
@@ -2787,6 +3130,7 @@ Intended to be added to `minibuffer-setup-hook'."
#'minibuffer-history-isearch-wrap)
(setq-local isearch-push-state-function
#'minibuffer-history-isearch-push-state)
+ (setq-local isearch-lazy-count nil)
(add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
(defun minibuffer-history-isearch-end ()
@@ -2922,12 +3266,12 @@ the minibuffer contents."
(defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
"Table mapping redo records to the corresponding undo one.
-A redo record for an undo in region maps to 'undo-in-region.
+A redo record for an undo in region maps to `undo-in-region'.
A redo record for ordinary undo maps to the following (earlier) undo.
A redo record that undoes to the beginning of the undo list maps to t.
In the rare case where there are (erroneously) consecutive nil's in
`buffer-undo-list', `undo' maps the previous valid undo record to
-'empty, if the previous record is a redo record, `undo' doesn't change
+`empty', if the previous record is a redo record, `undo' doesn't change
its mapping.
To be clear, a redo record is just an undo record, the only difference
@@ -2957,7 +3301,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.
@@ -3173,12 +3518,22 @@ Return what remains of the list."
;; If this records an obsolete save
;; (not matching the actual disk file)
;; then don't mark unmodified.
- (when (or (equal time (visited-file-modtime))
- (and (consp time)
- (equal (list (car time) (cdr time))
- (visited-file-modtime))))
- (unlock-buffer)
- (set-buffer-modified-p nil)))
+ (let ((visited-file-time (visited-file-modtime)))
+ ;; Indirect buffers don't have a visited file, so their
+ ;; file-modtime can be bogus. In that case, use the
+ ;; modtime of the base buffer instead.
+ (if (and (numberp visited-file-time)
+ (= visited-file-time 0)
+ (buffer-base-buffer))
+ (setq visited-file-time
+ (with-current-buffer (buffer-base-buffer)
+ (visited-file-modtime))))
+ (when (or (equal time visited-file-time)
+ (and (consp time)
+ (equal (list (car time) (cdr time))
+ visited-file-time)))
+ (unlock-buffer)
+ (set-buffer-modified-p nil))))
;; Element (nil PROP VAL BEG . END) is property change.
(`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare))
(when (or (> (point-min) beg) (< (point-max) end))
@@ -3836,7 +4191,10 @@ to the end of the list of defaults just after the default value."
(defvar minibuffer-local-shell-command-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
- (define-key map "\t" 'completion-at-point)
+ (define-key map "\t" #'completion-at-point)
+ (define-key map [M-up] #'minibuffer-previous-completion)
+ (define-key map [M-down] #'minibuffer-next-completion)
+ (define-key map [?\M-\r] #'minibuffer-choose-completion)
map)
"Keymap used for completing shell commands in minibuffer.")
@@ -4091,6 +4449,10 @@ interactively when the prefix argument is given), insert the
output in current buffer after point leaving mark after it. This
cannot be done asynchronously.
+If OUTPUT-BUFFER is a buffer or buffer name different from the
+current buffer, instead of outputting at point in that buffer,
+the output will be appended at the end of that buffer.
+
The user option `shell-command-dont-erase-buffer', which see, controls
whether the output buffer is erased and where to put point after
the shell command.
@@ -4202,25 +4564,21 @@ impose the use of a shell (with its need to quote arguments)."
(cond
((eq async-shell-command-buffer 'confirm-kill-process)
;; If will kill a process, query first.
- (if (yes-or-no-p "A command is running in the default buffer. Kill it? ")
- (kill-process proc)
- (user-error "Shell command in progress")))
+ (shell-command--same-buffer-confirm "Kill it")
+ (kill-process proc))
((eq async-shell-command-buffer 'confirm-new-buffer)
;; If will create a new buffer, query first.
- (if (yes-or-no-p "A command is running in the default buffer. Use a new buffer? ")
- (setq buffer (generate-new-buffer bname))
- (user-error "Shell command in progress")))
+ (shell-command--same-buffer-confirm "Use a new buffer")
+ (setq buffer (generate-new-buffer bname)))
((eq async-shell-command-buffer 'new-buffer)
;; It will create a new buffer.
(setq buffer (generate-new-buffer bname)))
((eq async-shell-command-buffer 'confirm-rename-buffer)
;; If will rename the buffer, query first.
- (if (yes-or-no-p "A command is running in the default buffer. Rename it? ")
- (progn
- (with-current-buffer buffer
- (rename-uniquely))
- (setq buffer (get-buffer-create bname)))
- (user-error "Shell command in progress")))
+ (shell-command--same-buffer-confirm "Rename it")
+ (with-current-buffer buffer
+ (rename-uniquely))
+ (setq buffer (get-buffer-create bname)))
((eq async-shell-command-buffer 'rename-buffer)
;; It will rename the buffer.
(with-current-buffer buffer
@@ -4268,6 +4626,24 @@ impose the use of a shell (with its need to quote arguments)."
(shell-command-on-region (point) (point) command
output-buffer nil error-buffer)))))))
+(defun shell-command--same-buffer-confirm (action)
+ (let ((help-form
+ (format
+ "There's a command already running in the default buffer,
+so we can't start a new one in the same one.
+
+Answering \"yes\" will %s.
+
+Answering \"no\" will exit without doing anything, and won't
+start the new command.
+
+Also see the `async-shell-command-buffer' variable."
+ (downcase action))))
+ (unless (yes-or-no-p
+ (format "A command is running in the default buffer. %s? "
+ action))
+ (user-error "Shell command in progress"))))
+
(defun max-mini-window-lines (&optional frame)
"Compute maximum number of lines for echo area in FRAME.
As defined by `max-mini-window-height'. FRAME defaults to the
@@ -4976,17 +5352,6 @@ that `filter-buffer-substring' received. It should return the
buffer substring between BEG and END, after filtering. If DELETE is
non-nil, it should delete the text between BEG and END from the buffer.")
-(defvar buffer-substring-filters nil
- "List of filter functions for `buffer-substring--filter'.
-Each function must accept a single argument, a string, and return a string.
-The buffer substring is passed to the first function in the list,
-and the return value of each function is passed to the next.
-As a special convention, point is set to the start of the buffer text
-being operated on (i.e., the first argument of `buffer-substring--filter')
-before these functions are called.")
-(make-obsolete-variable 'buffer-substring-filters
- 'filter-buffer-substring-function "24.1")
-
(defun filter-buffer-substring (beg end &optional delete)
"Return the buffer substring between BEG and END, after filtering.
If DELETE is non-nil, delete the text between BEG and END from the buffer.
@@ -5007,20 +5372,15 @@ that are special to a buffer, and should not be copied into other buffers."
"Default function to use for `filter-buffer-substring-function'.
Its arguments and return value are as specified for `filter-buffer-substring'.
Also respects the obsolete wrapper hook `filter-buffer-substring-functions'
-\(see `with-wrapper-hook' for details about wrapper hooks),
-and the abnormal hook `buffer-substring-filters'.
+(see `with-wrapper-hook' for details about wrapper hooks).
No filtering is done unless a hook says to."
(subr--with-wrapper-hook-no-warnings
filter-buffer-substring-functions (beg end delete)
(cond
- ((or delete buffer-substring-filters)
+ (delete
(save-excursion
(goto-char beg)
- (let ((string (if delete (delete-and-extract-region beg end)
- (buffer-substring beg end))))
- (dolist (filter buffer-substring-filters)
- (setq string (funcall filter string)))
- string)))
+ (delete-and-extract-region beg end)))
(t
(buffer-substring beg end)))))
@@ -5083,7 +5443,7 @@ ring directly.")
(defcustom kill-ring-max 120
"Maximum length of kill ring before oldest elements are thrown away."
- :type 'integer
+ :type 'natnum
:group 'killing
:version "29.1")
@@ -5195,7 +5555,7 @@ If `kill-append-merge-undo' is non-nil, remove the last undo
boundary in the current buffer."
(let ((cur (car kill-ring)))
(kill-new (if before-p (concat string cur) (concat cur string))
- (or (string= cur "")
+ (or (= (length cur) 0)
(null (get-text-property 0 'yank-handler cur)))))
(when (and kill-append-merge-undo (not buffer-read-only))
(let ((prev buffer-undo-list)
@@ -5363,7 +5723,7 @@ This command's old key binding has been given to `kill-ring-save'."
(let ((str (if region
(funcall region-extract-function nil)
(filter-buffer-substring beg end))))
- (if (eq last-command 'kill-region)
+ (if (eq last-command 'kill-region)
(kill-append str (< end beg))
(kill-new str)))
(setq deactivate-mark t)
@@ -5646,6 +6006,15 @@ See also `yank-handled-properties'."
:group 'killing
:version "24.3")
+(defvar yank-transform-functions nil
+ "Hook run on strings to be yanked.
+Each function in this list will be called (in order) with the
+string to be yanked as the sole argument, and should return the (possibly)
+transformed string.
+
+The functions will be called with the destination buffer as the current
+buffer, and with point at the place where the string is to be inserted.")
+
(defvar yank-window-start nil)
(defvar yank-undo-function nil
"If non-nil, function used by `yank-pop' to delete last stretch of yanked text.
@@ -5717,6 +6086,11 @@ property, as described below.
Properties listed in `yank-handled-properties' are processed,
then those listed in `yank-excluded-properties' are discarded.
+STRING will be run through `yank-transform-functions'.
+`yank-in-context' is a command that uses this mechanism to
+provide a `yank' alternative that conveniently preserves
+string/comment syntax.
+
If STRING has a non-nil `yank-handler' property anywhere, the
normal insert behavior is altered, and instead, for each contiguous
segment of STRING that has a given value of the `yank-handler'
@@ -5767,6 +6141,88 @@ With ARG, rotate that many kills forward (or backward, if negative)."
(interactive "p")
(current-kill arg))
+(defun yank-in-context (&optional arg)
+ "Insert the last stretch of killed text while preserving syntax.
+In particular, if point is inside a string, any quote characters
+in the killed text will be quoted, so that the string remains a
+valid string.
+
+If point is inside a comment, ensure that the inserted text is
+also marked as a comment.
+
+This command otherwise behaves as `yank'. See that command for
+explanation of ARG.
+
+This function uses the `escaped-string-quote' buffer-local
+variable to determine how strings should be escaped."
+ (interactive "*P")
+ (let ((yank-transform-functions (cons #'yank-in-context--transform
+ yank-transform-functions)))
+ (yank arg)))
+
+(defun yank-in-context--transform (string)
+ (let ((ppss (syntax-ppss)))
+ (cond
+ ;; We're in a string.
+ ((ppss-string-terminator ppss)
+ (string-replace
+ (string (ppss-string-terminator ppss))
+ (concat (if (functionp escaped-string-quote)
+ (funcall escaped-string-quote
+ (ppss-string-terminator ppss))
+ escaped-string-quote)
+ (string (ppss-string-terminator ppss)))
+ string))
+ ;; We're in a comment.
+ ((or (ppss-comment-depth ppss)
+ (and (bolp)
+ (not (eobp))
+ ;; If we're in the middle of a bunch of commented text,
+ ;; we probably want to be commented. This is quite DWIM.
+ (or (bobp)
+ (save-excursion
+ (forward-line -1)
+ (forward-char 1)
+ (ppss-comment-depth (syntax-ppss))))
+ (ppss-comment-depth
+ (setq ppss (save-excursion
+ (forward-char 1)
+ (syntax-ppss))))))
+ (cond
+ ((and (eq (ppss-comment-depth ppss) t)
+ (> (length comment-end) 0)
+ (string-search comment-end string))
+ (user-error "Can't insert a string containing a comment terminator in a comment"))
+ ;; If this is a comment syntax that has an explicit end, then
+ ;; we can just insert as is.
+ ((> (length comment-end) 0) string)
+ ;; Line-based comment formats.
+ ((or (string-search "\n" string)
+ (bolp))
+ (let ((mode major-mode)
+ (bolp (bolp))
+ (eolp (eolp))
+ (comment-style 'plain))
+ (with-temp-buffer
+ (funcall mode)
+ (insert string)
+ (when (string-match-p "\n\\'" string)
+ (cond
+ ((not eolp) (delete-char -1))
+ (bolp (insert "\n"))))
+ (comment-normalize-vars)
+ (comment-region-default-1
+ (if bolp
+ (point-min)
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (point)))
+ (point-max))
+ (buffer-string))))
+ (t string)))
+ (t string))))
+
(defvar read-from-kill-ring-history)
(defun read-from-kill-ring (prompt)
"Read a `kill-ring' entry using completion and minibuffer history.
@@ -5905,7 +6361,7 @@ Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
If Transient Mark mode is enabled, the mark is active, and ARG is 1,
delete the text in the region and deactivate the mark instead.
-To disable this, set option ‘delete-active-region’ to nil.
+To disable this, set option `delete-active-region' to nil.
Interactively, ARG is the prefix arg (default 1)
and KILLP is t if a prefix arg was specified."
@@ -5935,21 +6391,34 @@ and KILLP is t if a prefix arg was specified."
;; Avoid warning about delete-backward-char
(with-no-warnings (delete-backward-char n killp))))
-(defun zap-to-char (arg char)
+(defun char-uppercase-p (char)
+ "Return non-nil if CHAR is an upper-case character.
+If the Unicode tables are not yet available, e.g. during bootstrap,
+then gives correct answers only for ASCII characters."
+ (cond ((unicode-property-table-internal 'lowercase)
+ (characterp (get-char-code-property char 'lowercase)))
+ ((and (>= char ?A) (<= char ?Z)))))
+
+(defun zap-to-char (arg char &optional interactive)
"Kill up to and including ARGth occurrence of CHAR.
+When run interactively, the argument INTERACTIVE is non-nil.
Case is ignored if `case-fold-search' is non-nil in the current buffer.
Goes backward if ARG is negative; error if CHAR not found.
-See also `zap-up-to-char'."
+See also `zap-up-to-char'.
+If called interactively, do a case sensitive search if CHAR
+is an upper-case character."
(interactive (list (prefix-numeric-value current-prefix-arg)
(read-char-from-minibuffer "Zap to char: "
- nil 'read-char-history)))
+ nil 'read-char-history)
+ t))
;; Avoid "obsolete" warnings for translation-table-for-input.
(with-no-warnings
(if (char-table-p translation-table-for-input)
(setq char (or (aref translation-table-for-input char) char))))
- (kill-region (point) (progn
- (search-forward (char-to-string char) nil nil arg)
- (point))))
+ (let ((case-fold-search (if (and interactive (char-uppercase-p char))
+ nil
+ case-fold-search)))
+ (kill-region (point) (search-forward (char-to-string char) nil nil arg))))
;; kill-line and its subroutines.
@@ -6424,27 +6893,38 @@ An example is a rectangular region handled as a list of
separate contiguous regions for each line."
(cdr (region-bounds)))
+(defun redisplay--unhighlight-overlay-function (rol)
+ "If ROL is an overlay, call `delete-overlay'."
+ (when (overlayp rol) (delete-overlay rol)))
+
(defvar redisplay-unhighlight-region-function
- (lambda (rol) (when (overlayp rol) (delete-overlay rol))))
+ #'redisplay--unhighlight-overlay-function
+ "Function to remove the region-highlight overlay.")
+
+(defun redisplay--highlight-overlay-function (start end window rol &optional face)
+ "Update the overlay ROL in WINDOW with FACE in range START-END."
+ (unless face (setq face 'region))
+ (if (not (overlayp rol))
+ (let ((nrol (make-overlay start end)))
+ (funcall redisplay-unhighlight-region-function rol)
+ (overlay-put nrol 'window window)
+ (overlay-put nrol 'face face)
+ ;; Normal priority so that a large region doesn't hide all the
+ ;; overlays within it, but high secondary priority so that if it
+ ;; ends/starts in the middle of a small overlay, that small overlay
+ ;; won't hide the region's boundaries.
+ (overlay-put nrol 'priority '(nil . 100))
+ nrol)
+ (unless (eq (overlay-get rol 'face) face)
+ (overlay-put rol 'face face))
+ (unless (and (eq (overlay-buffer rol) (current-buffer))
+ (eq (overlay-start rol) start)
+ (eq (overlay-end rol) end))
+ (move-overlay rol start end (current-buffer)))
+ rol))
(defvar redisplay-highlight-region-function
- (lambda (start end window rol)
- (if (not (overlayp rol))
- (let ((nrol (make-overlay start end)))
- (funcall redisplay-unhighlight-region-function rol)
- (overlay-put nrol 'window window)
- (overlay-put nrol 'face 'region)
- ;; Normal priority so that a large region doesn't hide all the
- ;; overlays within it, but high secondary priority so that if it
- ;; ends/starts in the middle of a small overlay, that small overlay
- ;; won't hide the region's boundaries.
- (overlay-put nrol 'priority '(nil . 100))
- nrol)
- (unless (and (eq (overlay-buffer rol) (current-buffer))
- (eq (overlay-start rol) start)
- (eq (overlay-end rol) end))
- (move-overlay rol start end (current-buffer)))
- rol))
+ #'redisplay--highlight-overlay-function
"Function to move the region-highlight overlay.
This function is called with four parameters, START, END, WINDOW
and OVERLAY. If OVERLAY is nil, a new overlay is created. In
@@ -6469,8 +6949,33 @@ The overlay is returned by the function.")
(funcall redisplay-highlight-region-function
start end window rol)))
(unless (equal new rol)
- (set-window-parameter window 'internal-region-overlay
- new))))))
+ (set-window-parameter window 'internal-region-overlay new))))))
+
+(defcustom cursor-face-highlight-nonselected-window nil
+ "Non-nil means highlight text with `cursor-face' even in nonselected windows.
+This variable is similar to `highlight-nonselected-windows'."
+ :local t
+ :type 'boolean
+ :version "29.1")
+
+(defun redisplay--update-cursor-face-highlight (window)
+ "Highlights the overlay used to highlight text with cursor-face."
+ (let ((rol (window-parameter window 'internal-cursor-face-overlay)))
+ (if-let* (((or cursor-face-highlight-nonselected-window
+ (eq window (selected-window))
+ (and (window-minibuffer-p)
+ (eq window (minibuffer-selected-window)))))
+ (pt (window-point window))
+ (cursor-face (get-text-property pt 'cursor-face)))
+ (let* ((start (previous-single-property-change
+ (1+ pt) 'cursor-face nil (point-min)))
+ (end (next-single-property-change
+ pt 'cursor-face nil (point-max)))
+ (new (redisplay--highlight-overlay-function
+ start end window rol cursor-face)))
+ (unless (equal new rol)
+ (set-window-parameter window 'internal-cursor-face-overlay new)))
+ (redisplay--unhighlight-overlay-function rol))))
(defvar pre-redisplay-functions (list #'redisplay--update-region-highlight)
"Hook run just before redisplay.
@@ -6478,6 +6983,15 @@ It is called in each window that is to be redisplayed. It takes one argument,
which is the window that will be redisplayed. When run, the `current-buffer'
is set to the buffer displayed in that window.")
+(define-minor-mode cursor-face-highlight-mode
+ "When enabled, respect the cursor-face property."
+ :global nil
+ (if cursor-face-highlight-mode
+ (add-hook 'pre-redisplay-functions
+ #'redisplay--update-cursor-face-highlight nil t)
+ (remove-hook 'pre-redisplay-functions
+ #'redisplay--update-cursor-face-highlight t)))
+
(defun redisplay--pre-redisplay-functions (windows)
(with-demoted-errors "redisplay--pre-redisplay-functions: %S"
(if (null windows)
@@ -6487,9 +7001,11 @@ is set to the buffer displayed in that window.")
(with-current-buffer (window-buffer win)
(run-hook-with-args 'pre-redisplay-functions win))))))
-(add-function :before pre-redisplay-function
- #'redisplay--pre-redisplay-functions)
-
+(when (eq pre-redisplay-function #'ignore)
+ ;; Override the default set in the C code.
+ ;; This is not done using `add-function' so as to loosen the bootstrap
+ ;; dependencies.
+ (setq pre-redisplay-function #'redisplay--pre-redisplay-functions))
(defvar-local mark-ring nil
"The list of former marks of the current buffer, most recent first.")
@@ -6497,7 +7013,7 @@ is set to the buffer displayed in that window.")
(defcustom mark-ring-max 16
"Maximum size of mark ring. Start discarding off end if gets this big."
- :type 'integer
+ :type 'natnum
:group 'editing-basics)
(defvar global-mark-ring nil
@@ -6506,7 +7022,7 @@ is set to the buffer displayed in that window.")
(defcustom global-mark-ring-max 16
"Maximum size of global mark ring. \
Start discarding off end if gets this big."
- :type 'integer
+ :type 'natnum
:group 'editing-basics)
(defun pop-to-mark-command ()
@@ -6664,11 +7180,10 @@ mode temporarily."
(user-error "No mark set in this buffer"))
(set-mark (point))
(goto-char omark)
- (cond (temp-highlight
- (setq-local transient-mark-mode (cons 'only transient-mark-mode)))
- ((xor arg (not (region-active-p)))
- (deactivate-mark))
- (t (activate-mark)))
+ (or temp-highlight
+ (cond ((xor arg (not (region-active-p)))
+ (deactivate-mark))
+ (t (activate-mark))))
nil))
(defcustom shift-select-mode t
@@ -7620,31 +8135,28 @@ For motion by visual lines, see `beginning-of-visual-line'."
(put 'set-goal-column 'disabled t)
(defun set-goal-column (arg)
- "Set the current horizontal position as a goal for \\[next-line] and \\[previous-line].
+ "Set the current horizontal position as a goal column.
+This goal column will affect the \\[next-line] and \\[previous-line] commands,
+as well as the \\[scroll-up-command] and \\[scroll-down-command] commands.
+
Those commands will move to this position in the line moved to
rather than trying to keep the same horizontal position.
-With a non-nil argument ARG, clears out the goal column
-so that \\[next-line] and \\[previous-line] resume vertical motion.
-The goal column is stored in the variable `goal-column'.
-This is a buffer-local setting."
+
+With a non-nil argument ARG, clears out the goal column so that
+these commands resume normal motion.
+
+The goal column is stored in the variable `goal-column'. This is
+a buffer-local setting."
(interactive "P")
(if arg
(progn
(setq goal-column nil)
(message "No goal column"))
(setq goal-column (current-column))
- ;; The older method below can be erroneous if `set-goal-column' is bound
- ;; to a sequence containing %
- ;;(message (substitute-command-keys
- ;;"Goal column %d (use \\[set-goal-column] with an arg to unset it)")
- ;;goal-column)
- (message "%s"
- (concat
- (format "Goal column %d " goal-column)
- (substitute-command-keys
- "(use \\[set-goal-column] with an arg to unset it)")))
-
- )
+ (message "Goal column %d %s"
+ goal-column
+ (substitute-command-keys
+ "(use \\[set-goal-column] with an arg to unset it)")))
nil)
;;; Editing based on visual lines, as opposed to logical lines.
@@ -8084,10 +8596,10 @@ constitute a word."
(defcustom fill-prefix nil
"String for filling to insert at front of new line, or nil for none."
:type '(choice (const :tag "None" nil)
- string)
+ string)
+ :safe #'string-or-null-p
:group 'fill)
(make-variable-buffer-local 'fill-prefix)
-(put 'fill-prefix 'safe-local-variable 'string-or-null-p)
(defcustom auto-fill-inhibit-regexp nil
"Regexp to match lines that should not be auto-filled."
@@ -8279,7 +8791,8 @@ Just \\[universal-argument] as argument means to use the current column."
;; We used to use current-column silently, but C-x f is too easily
;; typed as a typo for C-x C-f, so we turned it into an error and
;; now an interactive prompt.
- (read-number "Set fill-column to: " (current-column)))))
+ (read-number (format "Change fill-column from %s to: " fill-column)
+ (current-column)))))
(if (consp arg)
(setq arg (current-column)))
(if (not (integerp arg))
@@ -8411,7 +8924,19 @@ presented."
:global t :group 'mode-line)
(define-minor-mode auto-save-mode
- "Toggle auto-saving in the current buffer (Auto Save mode)."
+ "Toggle auto-saving in the current buffer (Auto Save mode).
+
+When this mode is enabled, Emacs periodically saves each file-visiting
+buffer in a separate \"auto-save file\". This is a safety measure to
+prevent you from losing more than a limited amount of work if the
+system crashes.
+
+Auto-saving does not alter the file visited by the buffer: the visited
+file is changed only when you request saving it explicitly (such as
+with \\[save-buffer]). If you want to save the buffer into its
+visited files automatically, use \\[auto-save-visited-mode]).
+
+For more details, see Info node `(emacs) Auto Save'."
:variable ((and buffer-auto-save-file-name
;; If auto-save is off because buffer has shrunk,
;; then toggling should turn it on.
@@ -8751,9 +9276,10 @@ Valid values include:
paraphernalia if Gnus is running, particularly
the Gcc: header for archiving.
-Additional valid symbols may be available; check with the author of
-your package for details. The function should return non-nil if it
-succeeds.
+Additional valid symbols may be available; check in the manual of
+your mail user agent package for details. You may also define
+your own symbol to be used as value for this variable using
+`define-mail-user-agent'.
See also `read-mail-command' concerning reading mail."
:type '(radio (function-item :tag "Message package"
@@ -9013,6 +9539,16 @@ Its value is a list of the form (START END) where START is the place
where the completion should be inserted and END (if non-nil) is the end
of the text to replace. If END is nil, point is used instead.")
+(defvar completion-base-affixes nil
+ "Base context of the text corresponding to the shown completions.
+This variable is used in the *Completions* buffer.
+Its value is a list of the form (PREFIX SUFFIX) where PREFIX is the text
+before the place where completion should be inserted, and SUFFIX is the text
+after the completion.")
+
+(defvar completion-use-base-affixes nil
+ "Non-nil means to restore original prefix and suffix in the minibuffer.")
+
(defvar completion-list-insert-choice-function #'completion--replace
"Function to use to insert the text chosen in *Completions*.
Called with three arguments (BEG END TEXT), it should replace the text
@@ -9030,103 +9566,160 @@ Go to the window from which completion was requested."
(if (get-buffer-window buf)
(select-window (get-buffer-window buf))))))
-(defcustom completion-wrap-movement t
+(defcustom completion-auto-wrap t
"Non-nil means to wrap around when selecting completion options.
-This affects the commands `next-completion' and
-`previous-completion'."
+This affects the commands `next-completion' and `previous-completion'.
+When `completion-auto-select' is t, it wraps through the minibuffer."
:type 'boolean
:version "29.1"
:group 'completion)
+(defcustom completion-auto-select nil
+ "Non-nil means to automatically select the *Completions* buffer.
+When the value is t, pressing TAB will switch to the completion list
+buffer when Emacs pops up a window showing that buffer.
+If the value is `second-tab', then the first TAB will pop up the
+window showing the completions list buffer, and the next TAB will
+switch to that window.
+See `completion-auto-help' for controlling when the window showing
+the completions is popped up and down."
+ :type '(choice (const :tag "Don't auto-select completions window" nil)
+ (const :tag "Select completions window on first TAB" t)
+ (const :tag "Select completions window on second TAB"
+ second-tab))
+ :version "29.1"
+ :group 'completion)
+
+(defun first-completion ()
+ "Move to the first item in the completion list."
+ (interactive)
+ (goto-char (point-min))
+ (unless (get-text-property (point) 'mouse-face)
+ (when-let ((pos (next-single-property-change (point) 'mouse-face)))
+ (goto-char pos))))
+
+(defun last-completion ()
+ "Move to the last item in the completion list."
+ (interactive)
+ (goto-char (previous-single-property-change
+ (point-max) 'mouse-face nil (point-min)))
+ ;; Move to the start of last one.
+ (unless (get-text-property (point) 'mouse-face)
+ (when-let ((pos (previous-single-property-change (point) 'mouse-face)))
+ (goto-char pos))))
+
(defun previous-completion (n)
"Move to the previous item in the completion list.
With prefix argument N, move back N items (negative N means move
-forward)."
+forward).
+
+Also see the `completion-auto-wrap' variable."
(interactive "p")
(next-completion (- n)))
(defun next-completion (n)
"Move to the next item in the completion list.
With prefix argument N, move N items (negative N means move
-backward)."
+backward).
+
+Also see the `completion-auto-wrap' variable."
(interactive "p")
- (let ((beg (point-min)) (end (point-max)))
+ (let ((tabcommand (member (this-command-keys) '("\t" [backtab])))
+ pos)
(catch 'bound
(while (> n 0)
+ (setq pos (point))
;; If in a completion, move to the end of it.
- (when (get-text-property (point) 'mouse-face)
- (goto-char (next-single-property-change (point) 'mouse-face nil end)))
- ;; If at the last completion option, wrap or skip to the
- ;; minibuffer, if requested.
- (when (and completion-wrap-movement (eobp))
- (if (and (member (this-command-keys) '("\t" [backtab]))
- completion-auto-select)
- (throw 'bound nil)
- (goto-char (point-min))))
- ;; Move to start of next one.
- (unless (get-text-property (point) 'mouse-face)
- (goto-char (next-single-property-change (point) 'mouse-face nil end)))
+ (when (get-text-property pos 'mouse-face)
+ (setq pos (next-single-property-change pos 'mouse-face)))
+ (when pos (setq pos (next-single-property-change pos 'mouse-face)))
+ (if pos
+ ;; Move to the start of next one.
+ (goto-char pos)
+ ;; If at the last completion option, wrap or skip
+ ;; to the minibuffer, if requested.
+ (when completion-auto-wrap
+ (if (and (eq completion-auto-select t) tabcommand
+ (minibufferp completion-reference-buffer))
+ (throw 'bound nil)
+ (first-completion))))
(setq n (1- n)))
+
(while (< n 0)
- (let ((prop (get-text-property (1- (point)) 'mouse-face)))
- ;; If in a completion, move to the start of it.
- (when (and prop (eq prop (get-text-property (point) 'mouse-face)))
- (goto-char (previous-single-property-change
- (point) 'mouse-face nil beg)))
- ;; Move to end of the previous completion.
- (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face))
- (goto-char (previous-single-property-change
- (point) 'mouse-face nil beg)))
- ;; If at the first completion option, wrap or skip to the
- ;; minibuffer, if requested.
- (when (and completion-wrap-movement (bobp))
- (if (and (member (this-command-keys) '("\t" [backtab]))
- completion-auto-select)
+ (setq pos (point))
+ ;; If in a completion, move to the start of it.
+ (when (and (get-text-property pos 'mouse-face)
+ (not (bobp))
+ (get-text-property (1- pos) 'mouse-face))
+ (setq pos (previous-single-property-change pos 'mouse-face)))
+ (when pos (setq pos (previous-single-property-change pos 'mouse-face)))
+ (if pos
+ (progn
+ (goto-char pos)
+ ;; Move to the start of that one.
+ (unless (get-text-property (point) 'mouse-face)
+ (goto-char (previous-single-property-change
+ (point) 'mouse-face nil (point-min)))))
+ ;; If at the first completion option, wrap or skip
+ ;; to the minibuffer, if requested.
+ (when completion-auto-wrap
+ (if (and (eq completion-auto-select t) tabcommand
+ (minibufferp completion-reference-buffer))
(progn
- (goto-char (next-single-property-change (point) 'mouse-face nil end))
(throw 'bound nil))
- (goto-char (point-max))))
- ;; Move to the start of that one.
- (goto-char (previous-single-property-change
- (point) 'mouse-face nil beg))
- (setq n (1+ n)))))
+ (last-completion))))
+ (setq n (1+ n))))
+
(when (/= 0 n)
(switch-to-minibuffer))))
-(defun choose-completion (&optional event)
+(defun choose-completion (&optional event no-exit no-quit)
"Choose the completion at point.
-If EVENT, use EVENT's position to determine the starting position."
- (interactive (list last-nonmenu-event))
+If EVENT, use EVENT's position to determine the starting position.
+With prefix argument NO-EXIT, insert the completion at point to the
+minibuffer, but don't exit the minibuffer. When the prefix argument
+is not provided, then whether to exit the minibuffer depends on the value
+of `completion-no-auto-exit'.
+If NO-QUIT is non-nil, insert the completion at point to the
+minibuffer, but don't quit the completions window."
+ (interactive (list last-nonmenu-event current-prefix-arg))
;; In case this is run via the mouse, give temporary modes such as
;; isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
(with-current-buffer (window-buffer (posn-window (event-start event)))
(let ((buffer completion-reference-buffer)
(base-position completion-base-position)
+ (base-affixes completion-base-affixes)
(insert-function completion-list-insert-choice-function)
+ (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
(choice
(save-excursion
(goto-char (posn-point (event-start event)))
(let (beg)
(cond
- ((and (not (eobp)) (get-text-property (point) 'mouse-face))
+ ((and (not (eobp))
+ (get-text-property (point) 'completion--string))
(setq beg (1+ (point))))
((and (not (bobp))
- (get-text-property (1- (point)) 'mouse-face))
+ (get-text-property (1- (point)) 'completion--string))
(setq beg (point)))
(t (error "No completion here")))
- (setq beg (previous-single-property-change beg 'mouse-face))
+ (setq beg (or (previous-single-property-change
+ beg 'completion--string)
+ beg))
(substring-no-properties
(get-text-property beg 'completion--string))))))
(unless (buffer-live-p buffer)
(error "Destination buffer is dead"))
- (quit-window nil (posn-window (event-start event)))
+ (unless no-quit
+ (quit-window nil (posn-window (event-start event))))
(with-current-buffer buffer
(choose-completion-string
choice buffer
- (or base-position
+ (or (and completion-use-base-affixes base-affixes)
+ base-position
;; If all else fails, just guess.
(list (choose-completion-guess-base-position choice)))
insert-function)))))
@@ -9259,12 +9852,6 @@ Called from `temp-buffer-show-hook'."
:version "22.1"
:group 'completion)
-(defcustom completion-auto-select nil
- "Non-nil means to automatically select the *Completions* buffer."
- :type 'boolean
- :version "29.1"
- :group 'completion)
-
;; This function goes in completion-setup-hook, so that it is called
;; after the text of the completion list buffer is written.
(defun completion-setup-function ()
@@ -9281,19 +9868,24 @@ Called from `temp-buffer-show-hook'."
;; - With fancy completion styles, the code below will not always
;; find the right base directory.
(if minibuffer-completing-file-name
- (file-name-as-directory
+ (file-name-directory
(expand-file-name
(buffer-substring (minibuffer-prompt-end) (point)))))))
(with-current-buffer standard-output
(let ((base-position completion-base-position)
+ (base-affixes completion-base-affixes)
(insert-fun completion-list-insert-choice-function))
(completion-list-mode)
(setq-local completion-base-position base-position)
+ (setq-local completion-base-affixes base-affixes)
(setq-local completion-list-insert-choice-function insert-fun))
(setq-local completion-reference-buffer mainbuf)
(if base-dir (setq default-directory base-dir))
(when completion-tab-width
(setq tab-width completion-tab-width))
+ ;; Maybe enable cursor completions-highlight.
+ (when completions-highlight-face
+ (cursor-face-highlight-mode 1))
;; Maybe insert help string.
(when completion-show-help
(goto-char (point-min))
@@ -9301,31 +9893,25 @@ Called from `temp-buffer-show-hook'."
(insert "Click on a completion to select it.\n"))
(insert (substitute-command-keys
"In this buffer, type \\[choose-completion] to \
-select the completion near point.\n\n")))))
- (when completion-auto-select
- (switch-to-completions)))
+select the completion near point.\n\n"))))))
(add-hook 'completion-setup-hook #'completion-setup-function)
(defun switch-to-completions ()
"Select the completion list window."
(interactive)
- (let ((window (or (get-buffer-window "*Completions*" 0)
- ;; Make sure we have a completions window.
- (progn (minibuffer-completion-help)
- (get-buffer-window "*Completions*" 0)))))
- (when window
- (select-window window)
+ (when-let ((window (or (get-buffer-window "*Completions*" 0)
+ ;; Make sure we have a completions window.
+ (progn (minibuffer-completion-help)
+ (get-buffer-window "*Completions*" 0)))))
+ (select-window window)
+ (when (bobp)
(cond
((and (memq this-command '(completion-at-point minibuffer-complete))
- (equal (this-command-keys) [backtab])
- (bobp))
+ (equal (this-command-keys) [backtab]))
(goto-char (point-max))
- (previous-completion 1))
- ;; In the new buffer, go to the first completion.
- ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'.
- ((bobp)
- (next-completion 1))))))
+ (last-completion))
+ (t (first-completion))))))
(defun read-expression-switch-to-completions ()
"Select the completion list window while reading an expression."
@@ -9441,9 +10027,6 @@ PREFIX is the string that represents this modifier in an event type symbol."
(defvar clone-buffer-hook nil
"Normal hook to run in the new buffer at the end of `clone-buffer'.")
-(defvar clone-indirect-buffer-hook nil
- "Normal hook to run in the new buffer at the end of `clone-indirect-buffer'.")
-
(defun clone-process (process &optional newname)
"Create a twin copy of PROCESS.
If NEWNAME is nil, it defaults to PROCESS' name;
@@ -9596,8 +10179,6 @@ Returns the newly created indirect buffer."
(setq newname (substring newname 0 (match-beginning 0))))
(let* ((name (generate-new-buffer-name newname))
(buffer (make-indirect-buffer (current-buffer) name t)))
- (with-current-buffer buffer
- (run-hooks 'clone-indirect-buffer-hook))
(when display-flag
(pop-to-buffer buffer nil norecord))
buffer))
@@ -9856,7 +10437,7 @@ warning using STRING as the message.")
(and list
(boundp symbol)
(or (eq symbol t)
- (and (stringp (setq symbol (eval symbol)))
+ (and (stringp (setq symbol (symbol-value symbol)))
(string-match-p (nth 2 list) symbol)))
(display-warning package (nth 3 list) :warning)))
(error nil)))
@@ -9994,15 +10575,89 @@ This is an integer between 1 and 12 (inclusive). January is 1.")
(year nil :documentation "This is a four digit integer.")
(weekday nil :documentation "\
This is a number between 0 and 6, and 0 is Sunday.")
- (dst nil :documentation "\
+ (dst -1 :documentation "\
This is t if daylight saving time is in effect, nil if it is not
-in effect, and -1 if daylight saving information is not
-available.")
+in effect, and -1 if daylight saving information is not available.
+Also see `decoded-time-dst'.")
(zone nil :documentation "\
This is an integer indicating the UTC offset in seconds, i.e.,
the number of seconds east of Greenwich.")
)
+;; Document that decoded-time-dst is problematic on 6-element lists.
+;; It should return -1 indicating unknown DST, but currently returns
+;; nil indicating standard time.
+(put 'decoded-time-dst 'function-documentation
+ "Access slot \"dst\" of `decoded-time' struct CL-X.
+This is t if daylight saving time is in effect, nil if it is not
+in effect, and -1 if daylight saving information is not available.
+As a special case, return an unspecified value when given a list
+too short to have a dst element.
+
+(fn CL-X)")
+
+(defun get-scratch-buffer-create ()
+ "Return the *scratch* buffer, creating a new one if needed."
+ (or (get-buffer "*scratch*")
+ (let ((scratch (get-buffer-create "*scratch*")))
+ ;; Don't touch the buffer contents or mode unless we know that
+ ;; we just created it.
+ (with-current-buffer scratch
+ (when initial-scratch-message
+ (insert (substitute-command-keys initial-scratch-message))
+ (set-buffer-modified-p nil))
+ (funcall initial-major-mode))
+ scratch)))
+
+(defun scratch-buffer ()
+ "Switch to the *scratch* buffer.
+If the buffer doesn't exist, create it first."
+ (interactive)
+ (pop-to-buffer-same-window (get-scratch-buffer-create)))
+
+(defun kill-buffer--possibly-save (buffer)
+ (let ((response
+ (cadr
+ (read-multiple-choice
+ (format "Buffer %s modified; kill anyway?"
+ (buffer-name))
+ '((?y "yes" "kill buffer without saving")
+ (?n "no" "exit without doing anything")
+ (?s "save and then kill" "save the buffer and then kill it"))
+ nil nil (not use-short-answers)))))
+ (if (equal response "no")
+ nil
+ (unless (equal response "yes")
+ (with-current-buffer buffer
+ (save-buffer)))
+ t)))
+
+(defsubst string-empty-p (string)
+ "Check whether STRING is empty."
+ (string= string ""))
+
+(defun read-signal-name ()
+ "Read a signal number or name."
+ (let ((value
+ (completing-read "Signal code or name: "
+ (signal-names)
+ nil
+ (lambda (value)
+ (or (string-match "\\`[0-9]+\\'" value)
+ (member value (signal-names)))))))
+ (if (string-match "\\`[0-9]+\\'" value)
+ (string-to-number value)
+ (intern (concat "sig" (downcase value))))))
+
+(defun lax-plist-get (plist prop)
+ "Extract a value from a property list, comparing with `equal'."
+ (declare (obsolete plist-get "29.1"))
+ (plist-get plist prop #'equal))
+
+(defun lax-plist-put (plist prop val)
+ "Change value in PLIST of PROP to VAL, comparing with `equal'."
+ (declare (obsolete plist-put "29.1"))
+ (plist-put plist prop val #'equal))
(provide 'simple)
diff --git a/lisp/so-long.el b/lisp/so-long.el
index f4ae71d9058..4950f0adb50 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -90,7 +90,7 @@
;; * Overview of modes and commands
;; --------------------------------
;; - `global-so-long-mode' - A global minor mode which enables the automated
-;; behaviour, causing the user's preferred action to be invoked whenever a
+;; behavior, causing the user's preferred action to be invoked whenever a
;; newly-visited file contains excessively long lines.
;; - `so-long-mode' - A major mode, and the default action.
;; - `so-long-minor-mode' - A minor mode version of the major mode, and an
@@ -111,7 +111,7 @@
;;
;; On rare occasions you may choose to manually invoke the `so-long' command,
;; which invokes your preferred `so-long-action' (exactly as the automatic
-;; behaviour would do if it had detected long lines). You might use this if a
+;; behavior would do if it had detected long lines). You might use this if a
;; problematic file did not meet your configured criteria, and you wished to
;; trigger the performance improvements manually.
;;
@@ -120,7 +120,7 @@
;; available to `so-long' but, like any other mode, they can be invoked directly
;; if you have a need to do that (see also "Other ways of using so-long" below).
;;
-;; If the behaviour ever triggers when you did not want it to, you can use the
+;; If the behavior ever triggers when you did not want it to, you can use the
;; `so-long-revert' command to restore the buffer to its original state.
;; * Basic configuration
@@ -199,7 +199,7 @@
;;
;; Note that `so-long-minor-modes' is not useful for other global minor modes
;; (as distinguished from globalized minor modes), but in some cases it will be
-;; possible to inhibit or otherwise counter-act the behaviour of a global mode
+;; possible to inhibit or otherwise counter-act the behavior of a global mode
;; by overriding variables, or by employing hooks (see below). You would need
;; to inspect the code for a given global mode (on a case by case basis) to
;; determine whether it's possible to inhibit it for a single buffer -- and if
@@ -211,7 +211,7 @@
;; If `so-long-action' is set to either `so-long-mode' or `so-long-minor-mode',
;; the buffer-local value for each variable in the list is set to the associated
;; value in the alist. Use this to enforce values which will improve
-;; performance or otherwise avoid undesirable behaviours. If `so-long-revert'
+;; performance or otherwise avoid undesirable behaviors. If `so-long-revert'
;; is called, then the original values are restored.
;; * Retaining minor modes and settings when switching to `so-long-mode'
@@ -273,7 +273,7 @@
;; `so-long-mode', completely bypassing the automated decision process.
;; Refer to M-: (info "(emacs) Specifying File Variables") RET
;;
-;; If so-long itself causes problems, disable the automated behaviour with
+;; If so-long itself causes problems, disable the automated behavior with
;; M-- M-x global-so-long-mode, or M-: (global-so-long-mode 0)
;; * Example configuration
@@ -313,7 +313,7 @@
;; (add-hook 'js-mode-hook 'my-js-mode-hook)
;;
;; (defun my-js-mode-hook ()
-;; "Custom `js-mode' behaviours."
+;; "Custom `js-mode' behaviors."
;; (setq-local so-long-max-lines 100)
;; (setq-local so-long-threshold 1000))
;;
@@ -327,7 +327,7 @@
;; (add-hook 'nxml-mode-hook 'my-nxml-mode-hook)
;;
;; (defun my-nxml-mode-hook ()
-;; "Custom `nxml-mode' behaviours."
+;; "Custom `nxml-mode' behaviors."
;; (require 'so-long)
;; (setq-local so-long-variable-overrides
;; (remove '(bidi-inhibit-bpa . t) so-long-variable-overrides)))
@@ -380,7 +380,7 @@
;; meaning you would need to add to `safe-local-variable-values' in order to
;; avoid being queried about them.
;;
-;; Finally, the `so-long-predicate' user option enables the automated behaviour
+;; Finally, the `so-long-predicate' user option enables the automated behavior
;; to be determined by a custom function, if greater control is needed.
;; * Implementation notes
@@ -397,7 +397,7 @@
;; * Caveats
;; ---------
-;; The variables affecting the automated behaviour of this library (such as
+;; The variables affecting the automated behavior of this library (such as
;; `so-long-action') can be used as file- or dir-local values in Emacs 26+, but
;; not in previous versions of Emacs. This is on account of improvements made
;; to `normal-mode' in 26.1, which altered the execution order with respect to
@@ -462,7 +462,7 @@
;; 0.6 - Added `so-long-minor-modes' and `so-long-hook'.
;; 0.5 - Renamed library to "so-long.el".
;; - Added explicit `so-long-enable' command to activate our advice.
-;; 0.4 - Amended/documented behaviour with file-local 'mode' variables.
+;; 0.4 - Amended/documented behavior with file-local 'mode' variables.
;; 0.3 - Defer to a file-local 'mode' variable.
;; 0.2 - Initial release to EmacsWiki.
;; 0.1 - Experimental.
@@ -490,7 +490,7 @@
;; automatically."; however `so-long--ensure-enabled' may forcibly re-enable
;; it contrary to the user's expectations, so for the present this should be
;; considered internal-use only (with `global-so-long-mode' the interface
- ;; for enabling or disabling the automated behaviour). FIXME: Establish a
+ ;; for enabling or disabling the automated behavior). FIXME: Establish a
;; way to support the original use-case, or rename to `so-long--enabled'.
"Internal use. Non-nil when any `so-long' functionality has been used.")
@@ -586,7 +586,7 @@ files would prevent Emacs from handling them correctly."
(defcustom so-long-invisible-buffer-function #'so-long-deferred
"Function called in place of `so-long' when the buffer is not displayed.
-This affects the behaviour of `global-so-long-mode'.
+This affects the behavior of `global-so-long-mode'.
We treat invisible buffers differently from displayed buffers because, in
cases where a library is using a buffer for behind-the-scenes processing,
@@ -618,7 +618,7 @@ the mentioned options might interfere with some intended processing."
'so-long-detected-long-line-p)
"Function called after `set-auto-mode' to decide whether action is needed.
-This affects the behaviour of `global-so-long-mode'.
+This affects the behavior of `global-so-long-mode'.
Only called if the major mode is a member of `so-long-target-modes'.
@@ -703,7 +703,7 @@ will be automatically processed; but custom actions can also do these things.
The value `longlines-mode' causes that minor mode to be enabled. See
longlines.el for more details.
-Each action likewise determines the behaviour of `so-long-revert'.
+Each action likewise determines the behavior of `so-long-revert'.
If the value is nil, or not defined in `so-long-action-alist', then no action
will be taken."
@@ -753,7 +753,7 @@ If ACTION-ARG is provided, it is used in place of `so-long-action'."
(defcustom so-long-file-local-mode-function 'so-long-mode-downgrade
"Function to call during `set-auto-mode' when a file-local mode is set.
-This affects the behaviour of `global-so-long-mode'.
+This affects the behavior of `global-so-long-mode'.
The specified function will be called with a single argument, being the
file-local mode which was established.
@@ -855,7 +855,7 @@ By default this happens if `so-long-action' is set to either `so-long-mode'
or `so-long-minor-mode'. If `so-long-revert' is subsequently invoked, then the
disabled modes are re-enabled by calling them with the numeric argument 1.
-`so-long-hook' can be used where more custom behaviour is desired.
+`so-long-hook' can be used where more custom behavior is desired.
Please submit bug reports to recommend additional modes for this list, whether
they are in Emacs core, GNU ELPA, or elsewhere."
@@ -1312,7 +1312,7 @@ This minor mode is a standard `so-long-action' option."
(if so-long-minor-mode ;; We are enabling the mode.
(progn
;; Housekeeping. `so-long-minor-mode' might be invoked directly rather
- ;; than via `so-long', so replicate the necessary behaviours. The minor
+ ;; than via `so-long', so replicate the necessary behaviors. The minor
;; mode also cares about whether `so-long' was already active, as we do
;; not want to remember values which were (potentially) overridden
;; already.
@@ -1387,9 +1387,9 @@ values), despite potential performance issues, type \\[so-long-revert].
Use \\[so-long-commentary] for more information.
Use \\[so-long-customize] to open the customization group `so-long' to
-configure the behaviour."
+configure the behavior."
;; Housekeeping. `so-long-mode' might be invoked directly rather than via
- ;; `so-long', so replicate the necessary behaviours. We could use this same
+ ;; `so-long', so replicate the necessary behaviors. We could use this same
;; test in `so-long-after-change-major-mode' to run `so-long-hook', but that's
;; not so obviously the right thing to do, so I've omitted it for now.
(unless so-long--calling
@@ -1435,7 +1435,7 @@ configure the behaviour."
This advice acts before `so-long-mode', with the previous mode still active."
(unless (derived-mode-p 'so-long-mode)
;; Housekeeping. `so-long-mode' might be invoked directly rather than
- ;; via `so-long', so replicate the necessary behaviours.
+ ;; via `so-long', so replicate the necessary behaviors.
(unless so-long--calling
(so-long-remember-all :reset))
;; Remember the original major mode, regardless.
@@ -1518,14 +1518,14 @@ The variables are set in accordance with what was remembered in `so-long'."
(kill-local-variable variable))))
(defun so-long-mode-maintain-preserved-variables ()
- "Set any 'preserved' variables.
+ "Set any \"preserved\" variables.
The variables are set in accordance with what was remembered in `so-long'."
(dolist (var (so-long-original 'so-long-mode-preserved-variables))
(so-long-restore-variable var)))
(defun so-long-mode-maintain-preserved-minor-modes ()
- "Enable or disable 'preserved' minor modes.
+ "Enable or disable \"preserved\" minor modes.
The modes are set in accordance with what was remembered in `so-long'."
(dolist (mode (so-long-original 'so-long-mode-preserved-minor-modes))
@@ -1549,7 +1549,7 @@ This is the `so-long-revert-function' for `so-long-mode'."
;; Emacs 26+ has already called `hack-local-variables' (during
;; `run-mode-hooks'; provided there was a `buffer-file-name'), but for older
;; versions we need to call it here. In Emacs 26+ the revised 'HANDLE-MODE'
- ;; argument is set to `no-mode' (being the non-nil-and-non-t behaviour),
+ ;; argument is set to `no-mode' (being the non-nil-and-non-t behavior),
;; which we mimic here by binding `so-long--hack-local-variables-no-mode',
;; in order to prevent a local 'mode' variable from clobbering the major
;; mode we have just called.
@@ -1590,7 +1590,7 @@ because we do not want to downgrade the major mode in that scenario."
;; Act only if `so-long-mode' would be enabled by the current action.
(when (and (symbolp (so-long-function))
(provided-mode-derived-p (so-long-function) 'so-long-mode))
- ;; Downgrade from `so-long-mode' to the `so-long-minor-mode' behaviour.
+ ;; Downgrade from `so-long-mode' to the `so-long-minor-mode' behavior.
(setq so-long-function 'turn-on-so-long-minor-mode
so-long-revert-function 'turn-off-so-long-minor-mode))))
@@ -1610,7 +1610,7 @@ and cannot be conveniently intercepted, so we are forced to replicate it here.
This special-case code will ultimately be removed from Emacs, as it exists to
deal with a deprecated feature; but until then we need to replicate it in order
-to inhibit our own behaviour in the presence of a header comment `mode'
+to inhibit our own behavior in the presence of a header comment `mode'
declaration.
If a file-local mode is detected in the header comment, then we call the
@@ -1747,7 +1747,7 @@ by testing the value against `major-mode'; but as we may have changed the
major mode to `so-long-mode' by this point, that protection is insufficient
and so we need to perform our own test.
-We likewise need to support an equivalent of the `no-mode' behaviour in 26.1+
+We likewise need to support an equivalent of the `no-mode' behavior in 26.1+
to ensure that `so-long-mode-revert' will not restore a file-local mode again
after it has already reverted to the original mode.
@@ -1895,7 +1895,7 @@ When such files are detected by `so-long-predicate', we invoke the selected
Use \\[so-long-commentary] for more information.
Use \\[so-long-customize] to open the customization group `so-long' to
-configure the behaviour."
+configure the behavior."
:global t
:group 'so-long
(if global-so-long-mode
diff --git a/lisp/sort.el b/lisp/sort.el
index eb8e2787d1e..d04f075abd1 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -29,6 +29,8 @@
;;; Code:
+(eval-when-compile (require 'subr-x))
+
(defgroup sort nil
"Commands to sort text in an Emacs buffer."
:group 'data)
@@ -111,7 +113,8 @@ as start and end positions), and with `string<' otherwise."
(lambda (a b) (string< (car a) (car b)))))))
(if reverse (setq sort-lists (nreverse sort-lists)))
(if messages (message "Reordering buffer..."))
- (sort-reorder-buffer sort-lists old)))
+ (with-buffer-unmodified-if-unchanged
+ (sort-reorder-buffer sort-lists old))))
(if messages (message "Reordering buffer... Done"))))
nil)
@@ -286,25 +289,30 @@ FIELD, BEG and END. BEG and END specify region to sort."
(interactive "p\nr")
(let ;; To make `end-of-line' and etc. to ignore fields.
((inhibit-field-text-motion t))
- (sort-fields-1 field beg end
- (lambda ()
- (sort-skip-fields field)
- (let* ((case-fold-search t)
- (base
- (if (looking-at "\\(0x\\)[0-9a-f]\\|\\(0\\)[0-7]")
- (cond ((match-beginning 1)
- (goto-char (match-end 1))
- 16)
- ((match-beginning 2)
- (goto-char (match-end 2))
- 8)
- (t nil)))))
- (string-to-number (buffer-substring (point)
- (save-excursion
- (forward-sexp 1)
- (point)))
- (or base sort-numeric-base))))
- nil)))
+ (sort-fields-1
+ field beg end
+ (lambda ()
+ ;; Don't try to parse blank lines (they'll be
+ ;; sorted at the start).
+ (if (looking-at "[\t ]*$")
+ 0
+ (sort-skip-fields field)
+ (let* ((case-fold-search t)
+ (base
+ (if (looking-at "\\(0x\\)[0-9a-f]\\|\\(0\\)[0-7]")
+ (cond ((match-beginning 1)
+ (goto-char (match-end 1))
+ 16)
+ ((match-beginning 2)
+ (goto-char (match-end 2))
+ 8)
+ (t nil)))))
+ (string-to-number (buffer-substring (point)
+ (save-excursion
+ (forward-sexp 1)
+ (point)))
+ (or base sort-numeric-base)))))
+ nil)))
;;;;;###autoload
;;(defun sort-float-fields (field beg end)
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index e63a2642fe2..9184d6c5254 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -306,10 +306,9 @@ attached to and added to this list before the new frame is initialized."
(symbol :tag "Parameter")
(sexp :tag "Value"))))
-(defcustom speedbar-use-imenu-flag (fboundp 'imenu)
+(defcustom speedbar-use-imenu-flag t
"Non-nil means use imenu for file parsing, nil to use etags.
-XEmacs prior to 20.4 doesn't support imenu, therefore the default is to
-use etags instead. Etags support is not as robust as imenu support."
+Etags support is not as robust as imenu support." ; See Bug#51102
:tag "Use Imenu for tags"
:group 'speedbar
:type 'boolean)
@@ -704,8 +703,6 @@ If you want to change this while speedbar is active, either use
(defvar speedbar-update-flag-disable nil
"Permanently disable changing of the update flag.")
-(define-obsolete-variable-alias
- 'speedbar-syntax-table 'speedbar-mode-syntax-table "24.1")
(defvar speedbar-mode-syntax-table
(let ((st (make-syntax-table)))
;; Turn off paren matching around here.
@@ -720,8 +717,6 @@ If you want to change this while speedbar is active, either use
st)
"Syntax-table used on the speedbar.")
-
-(define-obsolete-variable-alias 'speedbar-key-map 'speedbar-mode-map "24.1")
(defvar speedbar-mode-map
(let ((map (make-keymap)))
(suppress-keymap map t)
@@ -800,15 +795,10 @@ This basically creates a sparse keymap, and makes its parent be
["Auto Update" speedbar-toggle-updates
:active (not speedbar-update-flag-disable)
:style toggle :selected speedbar-update-flag])
- (if (and (or (fboundp 'defimage)
- (fboundp 'make-image-specifier))
- (if (fboundp 'display-graphic-p)
- (display-graphic-p)
- window-system))
- (list
- ["Use Images" speedbar-toggle-images
- :style toggle :selected speedbar-use-images]))
- )
+ (when (and (fboundp 'defimage) (display-graphic-p))
+ (list
+ ["Use Images" speedbar-toggle-images
+ :style toggle :selected speedbar-use-images])))
"Base part of the speedbar menu.")
(defvar speedbar-easymenu-definition-special
@@ -938,7 +928,10 @@ supported at a time.
;; hscroll
(setq-local auto-hscroll-mode nil)
;; reset the selection variable
- (setq speedbar-last-selected-file nil))
+ (setq speedbar-last-selected-file nil)
+ (unless (display-graphic-p)
+ (message (substitute-command-keys
+ "Use \\[speedbar-get-focus] to see the speedbar window"))))
(defun speedbar-frame-reposition-smartly ()
"Reposition the speedbar frame to be next to the attached frame."
@@ -2274,9 +2267,7 @@ the list."
(with-current-buffer (get-file-buffer f)
speedbar-tag-hierarchy-method)
speedbar-tag-hierarchy-method))
- (lst (if (fboundp 'copy-tree)
- (copy-tree lst)
- lst)))
+ (lst (copy-tree lst)))
(while methods
(setq lst (funcall (car methods) lst)
methods (cdr methods)))
diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el
index ba1b81ef7e2..fb2ceab383f 100644
--- a/lisp/sqlite-mode.el
+++ b/lisp/sqlite-mode.el
@@ -24,6 +24,7 @@
;;; Code:
(require 'cl-lib)
+(eval-when-compile (require 'subr-x))
(declare-function sqlite-execute "sqlite.c")
(declare-function sqlite-more-p "sqlite.c")
@@ -129,15 +130,23 @@
(insert (format " %s\n" column))))))))
(defun sqlite-mode--column-names (table)
+ "Return a list of the column names for TABLE."
(let ((sql
(caar
(sqlite-select
sqlite--db
"select sql from sqlite_master where tbl_name = ? AND type = 'table'"
(list table)))))
- (mapcar
- #'string-trim
- (split-string (replace-regexp-in-string "^.*(\\|)$" "" sql) ","))))
+ (with-temp-buffer
+ (insert sql)
+ (mapcar #'string-trim
+ (split-string
+ ;; Extract the args to CREATE TABLE. Point is
+ ;; currently at its end.
+ (buffer-substring
+ (1- (point)) ; right before )
+ (1+ (progn (backward-sexp) (point)))) ; right after (
+ ",")))))
(defun sqlite-mode-list-data ()
"List the data from the table under point."
diff --git a/lisp/startup.el b/lisp/startup.el
index d90e7a7d26e..6c5549e2c64 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -519,20 +519,60 @@ DIRS are relative."
xdg-dir)
(t emacs-d-dir))))
+(defvar comp--compilable)
(defvar comp--delayed-sources)
-(defvar comp--loadable)
+(defun startup--require-comp-safely ()
+ "Require the native compiler avoiding circular dependencies."
+ (when (featurep 'native-compile)
+ ;; Require comp with `comp--compilable' set to nil to break
+ ;; circularity.
+ (let ((comp--compilable nil))
+ (require 'comp))
+ (native--compile-async comp--delayed-sources nil 'late)
+ (setq comp--delayed-sources nil)))
+
(declare-function native--compile-async "comp.el"
(files &optional recursively load selector))
(defun startup--honor-delayed-native-compilations ()
"Honor pending delayed deferred native compilations."
(when (and (native-comp-available-p)
comp--delayed-sources)
- (require 'comp)
- (setq comp--loadable t)
- (native--compile-async comp--delayed-sources nil 'late)
- (setq comp--delayed-sources nil)))
+ (startup--require-comp-safely))
+ (setq comp--compilable t))
(defvar native-comp-eln-load-path)
+(defvar native-comp-deferred-compilation)
+(defvar comp-enable-subr-trampolines)
+
+(defvar startup--original-eln-load-path nil
+ "Original value of `native-comp-eln-load-path'.")
+
+(defun startup-redirect-eln-cache (cache-directory)
+ "Redirect the user's eln-cache directory to CACHE-DIRECTORY.
+CACHE-DIRECTORY must be a single directory, a string.
+This function destructively changes `native-comp-eln-load-path'
+so that its first element is CACHE-DIRECTORY. If CACHE-DIRECTORY
+is not an absolute file name, it is interpreted relative
+to `user-emacs-directory'.
+For best results, call this function in your early-init file,
+so that the rest of initialization and package loading uses
+the updated value."
+ ;; Remove the original eln-cache.
+ (setq native-comp-eln-load-path (cdr native-comp-eln-load-path))
+ ;; Add the new eln-cache.
+ (push (expand-file-name (file-name-as-directory cache-directory)
+ user-emacs-directory)
+ native-comp-eln-load-path))
+
+(defun startup--update-eln-cache ()
+ "Update the user eln-cache directory due to user customizations."
+ ;; Don't override user customizations!
+ (when (equal native-comp-eln-load-path
+ startup--original-eln-load-path)
+ (startup-redirect-eln-cache "eln-cache")
+ (setq startup--original-eln-load-path
+ (copy-sequence native-comp-eln-load-path))))
+
(defun normal-top-level ()
"Emacs calls this function when it first starts up.
It sets `command-line-processed', processes the command-line,
@@ -551,6 +591,14 @@ It is the default value of the variable `top-level'."
(startup--xdg-or-homedot startup--xdg-config-home-emacs nil))
(when (featurep 'native-compile)
+ (unless (native-comp-available-p)
+ ;; Disable deferred async compilation and trampoline synthesis
+ ;; in this session. This is necessary if libgccjit is not
+ ;; available on MS-Windows, but Emacs was built with
+ ;; native-compilation support.
+ (setq native-comp-deferred-compilation nil
+ comp-enable-subr-trampolines nil))
+
;; Form `native-comp-eln-load-path'.
(let ((path-env (getenv "EMACSNATIVELOADPATH")))
(when path-env
@@ -558,18 +606,8 @@ It is the default value of the variable `top-level'."
(unless (string= "" path)
(push path native-comp-eln-load-path)))))
(push (expand-file-name "eln-cache/" user-emacs-directory)
- native-comp-eln-load-path)
- ;; When $HOME is set to '/nonexistent' means we are running the
- ;; testsuite, add a temporary folder in front to produce there
- ;; new compilations.
- (when (and (equal (getenv "HOME") "/nonexistent")
- ;; We may be running in a chroot environment where we
- ;; can't write anything.
- (file-writable-p (expand-file-name
- (or temporary-file-directory ""))))
- (let ((tmp-dir (make-temp-file "emacs-testsuite-" t)))
- (add-hook 'kill-emacs-hook (lambda () (delete-directory tmp-dir t)))
- (push tmp-dir native-comp-eln-load-path))))
+ native-comp-eln-load-path))
+
;; Look in each dir in load-path for a subdirs.el file. If we
;; find one, load it, which will add the appropriate subdirs of
;; that dir into load-path. This needs to be done before setting
@@ -665,7 +703,9 @@ It is the default value of the variable `top-level'."
;; native-comp-eln-load-path.
(expand-file-name
(decode-coding-string dir coding t)))
- npath))))
+ npath)))
+ (setq startup--original-eln-load-path
+ (copy-sequence native-comp-eln-load-path)))
(dolist (filesym '(data-directory doc-directory exec-directory
installation-directory
invocation-directory invocation-name
@@ -715,6 +755,7 @@ It is the default value of the variable `top-level'."
(let ((old-face-font-rescale-alist face-font-rescale-alist))
(unwind-protect
(command-line)
+
;; Do this again, in case .emacs defined more abbreviations.
(if default-directory
(setq default-directory (abbreviate-file-name default-directory)))
@@ -759,10 +800,12 @@ It is the default value of the variable `top-level'."
;; face-font-rescale-alist into account. For such
;; situations, we ought to have a way to find all font
;; objects and regenerate them; currently we do not. As a
- ;; workaround, we specifically reset te default face's :font
- ;; attribute here. See bug#1785.
- (unless (eq face-font-rescale-alist
- old-face-font-rescale-alist)
+ ;; workaround, we specifically reset the default face's :font
+ ;; attribute here, if it was rescaled. See bug#1785.
+ (when (and (not (eq face-font-rescale-alist
+ old-face-font-rescale-alist))
+ (assoc (font-xlfd-name (face-attribute 'default :font))
+ face-font-rescale-alist #'string-match-p))
(set-face-attribute 'default nil :font (font-spec)))
;; Modify the initial frame based on what .emacs puts into
@@ -781,6 +824,7 @@ It is the default value of the variable `top-level'."
(font-menu-add-default))
(unless inhibit-startup-hooks
(run-hooks 'window-setup-hook))))
+
;; Subprocesses of Emacs do not have direct access to the terminal, so
;; unless told otherwise they should only assume a dumb terminal.
;; We are careful to do it late (after term-setup-hook), although the
@@ -978,7 +1022,11 @@ init-file, or to a default value if loading is not possible."
(debug-on-error-initial
(if (eq init-file-debug t)
'startup
- init-file-debug)))
+ init-file-debug))
+ ;; The init file might contain byte-code with embedded NULs,
+ ;; which can cause problems when read back, so disable nul
+ ;; byte detection. (Bug#52554)
+ (inhibit-null-byte-detection t))
(let ((debug-on-error debug-on-error-initial))
(condition-case-unless-debug error
(when init-file-user
@@ -1145,7 +1193,8 @@ please check its value")
("--no-x-resources") ("--debug-init")
("--user") ("--iconic") ("--icon-type") ("--quick")
("--no-blinking-cursor") ("--basic-display")
- ("--dump-file") ("--temacs") ("--seccomp")))
+ ("--dump-file") ("--temacs") ("--seccomp")
+ ("--init-directory")))
(argi (pop args))
(orig-argi argi)
argval)
@@ -1165,6 +1214,14 @@ please check its value")
(t
(setq argval nil
argi orig-argi)))))
+
+ ;; We handle "-scripteval" further down, but we have to
+ ;; inhibit loading the user init file first. (This is for
+ ;; "emacs -x" handling.)
+ (when (equal argi "-scripteval")
+ (setq init-file-user nil
+ noninteractive t))
+
(cond
;; The --display arg is handled partly in C, partly in Lisp.
;; When it shows up here, we just put it back to be handled
@@ -1185,6 +1242,9 @@ please check its value")
(push '(vertical-scroll-bars . nil) initial-frame-alist))
((member argi '("-q" "-no-init-file"))
(setq init-file-user nil))
+ ((member argi '("-init-directory"))
+ (setq user-emacs-directory (or argval (pop args))
+ argval nil))
((member argi '("-u" "-user"))
(setq init-file-user (or argval (pop args))
argval nil))
@@ -1217,12 +1277,16 @@ please check its value")
(setcdr command-line-args args)))
;; Re-evaluate predefined variables whose initial value depends on
- ;; the runtime context.
- (when (listp custom-delayed-init-variables)
- (mapc #'custom-reevaluate-setting
- ;; Initialize them in the same order they were loaded, in
- ;; case there are dependencies between them.
- (reverse custom-delayed-init-variables)))
+ ;; the runtime context. But delay the warning about
+ ;; `user-emacs-directory' being inaccessible until after processing
+ ;; the init file and the command-line arguments, in case the user
+ ;; customized `user-emacs-directory-warning' to nil via those.
+ (let ((user-emacs-directory-warning nil))
+ (when (listp custom-delayed-init-variables)
+ (mapc #'custom-reevaluate-setting
+ ;; Initialize them in the same order they were loaded, in
+ ;; case there are dependencies between them.
+ (reverse custom-delayed-init-variables))))
(setq custom-delayed-init-variables t)
;; Warn for invalid user name.
@@ -1261,7 +1325,8 @@ please check its value")
(and (eq xdg-dir user-emacs-directory)
(not (eq xdg-dir startup--xdg-config-default))))
user-emacs-directory
- ;; The name is not obvious, so access more directories to calculate it.
+ ;; The name is not obvious, so access more directories
+ ;; to calculate it.
(setq xdg-dir (concat "~" init-file-user "/.config/emacs/"))
(startup--xdg-or-homedot xdg-dir init-file-user)))
@@ -1277,6 +1342,12 @@ please check its value")
startup-init-directory)))
(setq early-init-file user-init-file)
+ ;; Amend `native-comp-eln-load-path', since the early-init file may
+ ;; have altered `user-emacs-directory' and/or changed the eln-cache
+ ;; directory.
+ (when (featurep 'native-compile)
+ (startup--update-eln-cache))
+
;; If any package directory exists, initialize the package system.
(and user-init-file
package-enable-at-startup
@@ -1411,6 +1482,12 @@ please check its value")
startup-init-directory))
t)
+ ;; Amend `native-comp-eln-load-path' again, since the early-init
+ ;; file may have altered `user-emacs-directory' and/or changed the
+ ;; eln-cache directory.
+ (when (featurep 'native-compile)
+ (startup--update-eln-cache))
+
(when (and deactivate-mark transient-mark-mode)
(with-current-buffer (window-buffer)
(deactivate-mark)))
@@ -1470,9 +1547,21 @@ please check its value")
(list 'error
(substitute-command-keys "Memory exhausted--use \\[save-some-buffers] then exit and restart Emacs")))
+ ;; Reevaluate `user-emacs-directory-warning' before processing
+ ;; '--eval' arguments, so that the user could override the default
+ ;; value in the '--eval' forms.
+ (custom-reevaluate-setting 'user-emacs-directory-warning)
+
;; Process the remaining args.
(command-line-1 (cdr command-line-args))
+ ;; Check if `user-emacs-directory' is accessible and warn if it
+ ;; isn't, unless `user-emacs-directory-warning' was customized to
+ ;; disable that warning.
+ (when (and user-emacs-directory-warning
+ (not (file-accessible-directory-p user-emacs-directory)))
+ (locate-user-emacs-file ""))
+
;; This is a problem because, e.g. if emacs.d/gnus.el exists,
;; trying to load gnus could load the wrong file.
;; OK, it would not matter if .emacs.d were at the end of load-path.
@@ -2247,7 +2336,7 @@ If you have no Meta key, you may instead type ESC followed by the character.)"))
(insert "\t\t")
(insert-button "Open *scratch* buffer"
'action (lambda (_button) (switch-to-buffer
- (startup--get-buffer-create-scratch)))
+ (get-scratch-buffer-create)))
'follow-link t)
(insert "\n")
(save-restriction
@@ -2379,12 +2468,6 @@ A fancy display is used on graphic displays, normal otherwise."
(defalias 'about-emacs 'display-about-screen)
(defalias 'display-splash-screen 'display-startup-screen)
-(defun startup--get-buffer-create-scratch ()
- (or (get-buffer "*scratch*")
- (with-current-buffer (get-buffer-create "*scratch*")
- (set-buffer-major-mode (current-buffer))
- (current-buffer))))
-
;; This avoids byte-compiler warning in the unexec build.
(declare-function pdumper-stats "pdumper.c" ())
@@ -2577,7 +2660,7 @@ nil default-directory" name)
;; This is used to handle -script. It's not clear
;; we need to document it (it is totally internal).
- ((member argi '("-scriptload"))
+ ((member argi '("-scriptload" "-scripteval"))
(let* ((file (command-line-normalize-file-name
(or argval (pop command-line-args-left))))
;; Take file from default dir.
@@ -2590,7 +2673,10 @@ nil default-directory" name)
;; actually exist on some systems.
(when (file-exists-p truename)
(setq file-ex truename))
- (load file-ex nil t t)))
+ (if (equal argi "-scripteval")
+ ;; This will kill Emacs.
+ (command-line--eval-script file-ex)
+ (command-line--load-script file-ex))))
((equal argi "-insert")
(setq inhibit-startup-screen t)
@@ -2673,7 +2759,7 @@ nil default-directory" name)
(when (eq initial-buffer-choice t)
;; When `initial-buffer-choice' equals t make sure that *scratch*
;; exists.
- (startup--get-buffer-create-scratch))
+ (get-scratch-buffer-create))
;; If *scratch* exists and is empty, insert initial-scratch-message.
;; Do this before switching to *scratch* below to handle bug#9605.
@@ -2697,7 +2783,7 @@ nil default-directory" name)
((functionp initial-buffer-choice)
(funcall initial-buffer-choice))
((eq initial-buffer-choice t)
- (startup--get-buffer-create-scratch))
+ (get-scratch-buffer-create))
(t
(error "`initial-buffer-choice' must be a string, a function, or t")))))
(unless (buffer-live-p buf)
@@ -2712,13 +2798,28 @@ nil default-directory" name)
;; `nondisplayed-buffers-p' is true if there exist buffers
;; in `displayable-buffers' that were not displayed to the
;; user.
- (nondisplayed-buffers-p nil))
+ (nondisplayed-buffers-p nil)
+ (old-face-font-rescale-alist face-font-rescale-alist))
(when (> displayable-buffers-len 0)
(switch-to-buffer (car displayable-buffers)))
- (when (> displayable-buffers-len 1)
- (switch-to-buffer-other-window (car (cdr displayable-buffers)))
+ (cond
+ ;; Two buffers; display them both.
+ ((= displayable-buffers-len 2)
+ (switch-to-buffer-other-window (cadr displayable-buffers))
;; Focus on the first buffer.
(other-window -1))
+ ;; More than two buffers: Ensure that the buffer display order
+ ;; reflects the order they were given on the command line.
+ ;; (This will end up with a `next-buffer' order that's in
+ ;; reverse order -- the final file is the focused one, and then
+ ;; the rest are in `next-buffer' in descending order.
+ ((> displayable-buffers-len 2)
+ (let ((bufs (reverse (cdr displayable-buffers))))
+ (switch-to-buffer-other-window (pop bufs))
+ (dolist (buf bufs)
+ (switch-to-buffer buf nil t))
+ ;; Focus on the first buffer.
+ (other-window -1))))
(when (> displayable-buffers-len 2)
(setq nondisplayed-buffers-p t))
@@ -2742,6 +2843,14 @@ nil default-directory" name)
;; before doing any output.
(run-hooks 'emacs-startup-hook 'term-setup-hook)
+ ;; See the commentary in `normal-top-level' for why we do
+ ;; this.
+ (when (and (not (eq face-font-rescale-alist
+ old-face-font-rescale-alist))
+ (assoc (font-xlfd-name (face-attribute 'default :font))
+ face-font-rescale-alist #'string-match-p))
+ (set-face-attribute 'default nil :font (font-spec)))
+
;; It's important to notice the user settings before we
;; display the startup message; otherwise, the settings
;; won't take effect until the user gives the first
@@ -2765,6 +2874,35 @@ nil default-directory" name)
(display-startup-screen (> displayable-buffers-len 0))))))
+(defun command-line--load-script (file)
+ (load-with-code-conversion
+ file file nil t
+ (lambda (buffer file)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ ;; Removing the #! and then calling `eval-buffer' will make the
+ ;; reader not signal an error if it then turns out that the
+ ;; buffer is empty.
+ (when (looking-at "#!")
+ (delete-line))
+ (eval-buffer buffer nil file nil t)))))
+
+(defun command-line--eval-script (file)
+ (load-with-code-conversion
+ file file nil t
+ (lambda (buffer _)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (when (looking-at "#!")
+ (forward-line))
+ (let (value form)
+ (while (ignore-error 'end-of-file
+ (setq form (read (current-buffer))))
+ (setq value (eval form t)))
+ (kill-emacs (if (numberp value)
+ value
+ 0)))))))
+
(defun command-line-normalize-file-name (file)
"Collapse multiple slashes to one, to handle non-Emacs file names."
(save-match-data
diff --git a/lisp/strokes.el b/lisp/strokes.el
index dc242d8f335..d7a95393166 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -252,7 +252,7 @@ WARNING: Changing the value of this variable will gravely affect the
figure out what it should be based on your needs and on how
quick the particular platform(s) you're operating on, and
only then start programming in your custom strokes."
- :type 'integer)
+ :type 'natnum)
(defcustom strokes-file (locate-user-emacs-file "strokes" ".strokes")
"File containing saved strokes for Strokes mode."
@@ -1031,13 +1031,11 @@ o Strokes are a bit computer-dependent in that they depend somewhat on
(help-mode)
(help-print-return-message)))
-(define-obsolete-function-alias 'strokes-report-bug #'report-emacs-bug "24.1")
-
(defun strokes-window-configuration-changed-p ()
"Non-nil if the `strokes-window-configuration' frame properties changed.
This is based on the last time `strokes-window-configuration' was updated."
- (compare-window-configurations (current-window-configuration)
- strokes-window-configuration))
+ (window-configuration-equal-p (current-window-configuration)
+ strokes-window-configuration))
(defun strokes-update-window-configuration ()
"Ensure that `strokes-window-configuration' is up-to-date."
diff --git a/lisp/subr.el b/lisp/subr.el
index 7906324f80c..f8b386e5631 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -207,6 +207,39 @@ Also see `local-variable-p'."
(:success t)
(void-variable nil)))
+(defmacro buffer-local-set-state (&rest pairs)
+ "Like `setq-local', but allow restoring the previous state of locals later.
+This macro returns an object that can be passed to `buffer-local-restore-state'
+in order to restore the state of the local variables set via this macro.
+
+\(fn [VARIABLE VALUE]...)"
+ (declare (debug setq))
+ (unless (zerop (mod (length pairs) 2))
+ (error "PAIRS must have an even number of variable/value members"))
+ `(prog1
+ (buffer-local-set-state--get ',pairs)
+ (setq-local ,@pairs)))
+
+(defun buffer-local-set-state--get (pairs)
+ (let ((states nil))
+ (while pairs
+ (push (list (car pairs)
+ (and (boundp (car pairs))
+ (local-variable-p (car pairs)))
+ (and (boundp (car pairs))
+ (symbol-value (car pairs))))
+ states)
+ (setq pairs (cddr pairs)))
+ (nreverse states)))
+
+(defun buffer-local-restore-state (states)
+ "Restore values of buffer-local variables recorded in STATES.
+STATES should be an object returned by `buffer-local-set-state'."
+ (pcase-dolist (`(,variable ,local ,value) states)
+ (if local
+ (set variable value)
+ (kill-local-variable variable))))
+
(defmacro push (newelt place)
"Add NEWELT to the list stored in the generalized variable PLACE.
This is morally equivalent to (setf PLACE (cons NEWELT PLACE)),
@@ -243,18 +276,14 @@ change the list."
(defmacro when (cond &rest body)
"If COND yields non-nil, do BODY, else return nil.
When COND yields non-nil, eval BODY forms sequentially and return
-value of last one, or nil if there are none.
-
-\(fn COND BODY...)"
+value of last one, or nil if there are none."
(declare (indent 1) (debug t))
(list 'if cond (cons 'progn body)))
(defmacro unless (cond &rest body)
"If COND yields nil, do BODY, else return nil.
When COND yields nil, eval BODY forms sequentially and return
-value of last one, or nil if there are none.
-
-\(fn COND BODY...)"
+value of last one, or nil if there are none."
(declare (indent 1) (debug t))
(cons 'if (cons cond (cons nil body))))
@@ -412,7 +441,10 @@ To signal with MESSAGE without interpreting format characters
like `%', `\\=`' and `\\='', use (error \"%s\" MESSAGE).
In Emacs, the convention is that error messages start with a capital
letter but *do not* end with a period. Please follow this convention
-for the sake of consistency."
+for the sake of consistency.
+
+To alter the look of the displayed error messages, you can use
+the `command-error-function' variable."
(declare (advertised-calling-convention (string &rest args) "23.1"))
(signal 'error (list (apply #'format-message args))))
@@ -428,7 +460,10 @@ To signal with MESSAGE without interpreting format characters
like `%', `\\=`' and `\\='', use (user-error \"%s\" MESSAGE).
In Emacs, the convention is that error messages start with a capital
letter but *do not* end with a period. Please follow this convention
-for the sake of consistency."
+for the sake of consistency.
+
+To alter the look of the displayed error messages, you can use
+the `command-error-function' variable."
(signal 'user-error (list (apply #'format-message format args))))
(defun define-error (name message &optional parent)
@@ -505,12 +540,12 @@ i.e., subtract 2 * `most-negative-fixnum' from VALUE before shifting it."
;; you may want to amend the other, too.
(defun internal--compiler-macro-cXXr (form x)
(let* ((head (car form))
- (n (symbol-name (car form)))
+ (n (symbol-name head))
(i (- (length n) 2)))
(if (not (string-match "c[ad]+r\\'" n))
(if (and (fboundp head) (symbolp (symbol-function head)))
- (internal--compiler-macro-cXXr (cons (symbol-function head) (cdr form))
- x)
+ (internal--compiler-macro-cXXr
+ (cons (symbol-function head) (cdr form)) x)
(error "Compiler macro for cXXr applied to non-cXXr form"))
(while (> i (match-beginning 0))
(setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
@@ -929,7 +964,7 @@ side-effects, and the argument LIST is not modified."
(defun kbd (keys)
"Convert KEYS to the internal Emacs key representation.
KEYS should be a string in the format returned by commands such
-as `C-h k' (`describe-key').
+as \\[describe-key] (`describe-key').
This is the same format used for saving keyboard macros (see
`edmacro-mode').
@@ -945,6 +980,20 @@ Here's some example key sequences:
For an approximate inverse of this, see `key-description'."
(declare (pure t) (side-effect-free t))
(let ((res (key-parse keys)))
+ ;; For historical reasons, parse "C-x ( C-d C-x )" as "C-d", since
+ ;; `kbd' used to be a wrapper around `read-kbd-macro'.
+ (when (and (>= (length res) 4)
+ (eq (aref res 0) ?\C-x)
+ (eq (aref res 1) ?\()
+ (eq (aref res (- (length res) 2)) ?\C-x)
+ (eq (aref res (- (length res) 1)) ?\)))
+ (setq res (apply #'vector (let ((lres (append res nil)))
+ ;; Remove the first and last two elements.
+ (setq lres (cddr lres))
+ (setq lres (nreverse lres))
+ (setq lres (cddr lres))
+ (nreverse lres)))))
+
(if (not (memq nil (mapcar (lambda (ch)
(and (numberp ch)
(<= 0 ch 127)))
@@ -1149,8 +1198,17 @@ Subkeymaps may be modified but are not canonicalized."
(setq map (map-keymap ;; -internal
(lambda (key item)
(if (consp key)
- ;; Treat char-ranges specially.
- (push (cons key item) ranges)
+ (if (= (car key) (1- (cdr key)))
+ ;; If we have a two-character range, then
+ ;; treat it as two separate characters
+ ;; (because this makes `describe-bindings'
+ ;; look better and shouldn't affect
+ ;; anything else).
+ (progn
+ (push (cons (car key) item) bindings)
+ (push (cons (cdr key) item) bindings))
+ ;; Treat char-ranges specially.
+ (push (cons key item) ranges))
(push (cons key item) bindings)))
map)))
;; Create the new map.
@@ -1484,21 +1542,21 @@ the `click' modifier."
;; sure the symbol has already been parsed.
(cdr (internal-event-symbol-parse-modifiers type))
(let ((list nil)
- (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@
- ?\H-\^@ ?\s-\^@ ?\A-\^@)))))
- (if (not (zerop (logand type ?\M-\^@)))
+ (char (logand type (lognot (logior ?\M-\0 ?\C-\0 ?\S-\0
+ ?\H-\0 ?\s-\0 ?\A-\0)))))
+ (if (not (zerop (logand type ?\M-\0)))
(push 'meta list))
- (if (or (not (zerop (logand type ?\C-\^@)))
+ (if (or (not (zerop (logand type ?\C-\0)))
(< char 32))
(push 'control list))
- (if (or (not (zerop (logand type ?\S-\^@)))
+ (if (or (not (zerop (logand type ?\S-\0)))
(/= char (downcase char)))
(push 'shift list))
- (or (zerop (logand type ?\H-\^@))
+ (or (zerop (logand type ?\H-\0))
(push 'hyper list))
- (or (zerop (logand type ?\s-\^@))
+ (or (zerop (logand type ?\s-\0))
(push 'super list))
- (or (zerop (logand type ?\A-\^@))
+ (or (zerop (logand type ?\A-\0))
(push 'alt list))
list))))
@@ -1512,7 +1570,7 @@ in the current Emacs session, then this function may return nil."
(setq event (car event)))
(if (symbolp event)
(car (get event 'event-symbol-elements))
- (let* ((base (logand event (1- ?\A-\^@)))
+ (let* ((base (logand event (1- ?\A-\0)))
(uncontrolled (if (< base 32) (logior base 64) base)))
;; There are some numbers that are invalid characters and
;; cause `downcase' to get an error.
@@ -1647,13 +1705,19 @@ pixels. POSITION should be a list of the form returned by
(declare-function scroll-bar-scale "scroll-bar" (num-denom whole))
-(defun posn-col-row (position)
+(defun posn-col-row (position &optional use-window)
"Return the nominal column and row in POSITION, measured in characters.
The column and row values are approximations calculated from the x
and y coordinates in POSITION and the frame's default character width
and default line height, including spacing.
+
+If USE-WINDOW is non-nil, use the typical width of a character in
+the window indicated by POSITION instead of the frame. (This
+makes a difference is a window has a zoom level.)
+
For a scroll-bar event, the result column is 0, and the row
corresponds to the vertical position of the click in the scroll bar.
+
POSITION should be a list of the form returned by the `event-start'
and `event-end' functions."
(let* ((pair (posn-x-y position))
@@ -1671,20 +1735,23 @@ and `event-end' functions."
((eq area 'horizontal-scroll-bar)
(cons (scroll-bar-scale pair (window-width window)) 0))
(t
- ;; FIXME: This should take line-spacing properties on
- ;; newlines into account.
- (let* ((spacing (when (display-graphic-p frame)
- (or (with-current-buffer
- (window-buffer (frame-selected-window frame))
- line-spacing)
- (frame-parameter frame 'line-spacing)))))
- (cond ((floatp spacing)
- (setq spacing (truncate (* spacing
- (frame-char-height frame)))))
- ((null spacing)
- (setq spacing 0)))
- (cons (/ (car pair) (frame-char-width frame))
- (/ (cdr pair) (+ (frame-char-height frame) spacing))))))))
+ (if use-window
+ (cons (/ (car pair) (window-font-width window))
+ (/ (cdr pair) (window-font-height window)))
+ ;; FIXME: This should take line-spacing properties on
+ ;; newlines into account.
+ (let* ((spacing (when (display-graphic-p frame)
+ (or (with-current-buffer
+ (window-buffer (frame-selected-window frame))
+ line-spacing)
+ (frame-parameter frame 'line-spacing)))))
+ (cond ((floatp spacing)
+ (setq spacing (truncate (* spacing
+ (frame-char-height frame)))))
+ ((null spacing)
+ (setq spacing 0)))
+ (cons (/ (car pair) (frame-char-width frame))
+ (/ (cdr pair) (+ (frame-char-height frame) spacing)))))))))
(defun posn-actual-col-row (position)
"Return the window row number in POSITION and character number in that row.
@@ -1789,8 +1856,6 @@ be a list of the form returned by `event-start' and `event-end'."
;;;; Obsolescence declarations for variables, and aliases.
(make-obsolete-variable 'redisplay-end-trigger-functions 'jit-lock-register "23.1")
-(make-obsolete-variable 'deferred-action-list 'post-command-hook "24.1")
-(make-obsolete-variable 'deferred-action-function 'post-command-hook "24.1")
(make-obsolete-variable 'redisplay-dont-pause nil "24.5")
(make-obsolete 'window-redisplay-end-trigger nil "23.1")
(make-obsolete 'set-window-redisplay-end-trigger nil "23.1")
@@ -1816,11 +1881,8 @@ be a list of the form returned by `event-start' and `event-end'."
(make-obsolete-variable 'load-dangerous-libraries
"no longer used." "27.1")
-(defvar inhibit--record-char nil
- "Obsolete variable.
-This was used internally by quail.el and keyboard.c in Emacs 27.
-It does nothing in Emacs 28.")
-(make-obsolete-variable 'inhibit--record-char nil "28.1")
+(define-obsolete-function-alias 'compare-window-configurations
+ #'window-configuration-equal-p "29.1")
;; We can't actually make `values' obsolete, because that will result
;; in warnings when using `values' in let-bindings.
@@ -1896,7 +1958,9 @@ performance impact when running `add-hook' and `remove-hook'."
(set (make-local-variable hook) (list t)))
;; Detect the case where make-local-variable was used on a hook
;; and do what we used to do.
- (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook)))
+ (when (and (local-variable-if-set-p hook)
+ (not (and (consp (symbol-value hook))
+ (memq t (symbol-value hook)))))
(setq local t)))
(let ((hook-value (if local (symbol-value hook) (default-value hook))))
;; If the hook value is a single function, turn it into a list.
@@ -1904,26 +1968,34 @@ performance impact when running `add-hook' and `remove-hook'."
(setq hook-value (list hook-value)))
;; Do the actual addition if necessary
(unless (member function hook-value)
- (when (stringp function) ;FIXME: Why?
- (setq function (purecopy function)))
- ;; All those `equal' tests performed between functions can end up being
- ;; costly since those functions may be large recursive and even cyclic
- ;; structures, so we index `hook--depth-alist' with `eq'. (bug#46326)
- (when (or (get hook 'hook--depth-alist) (not (zerop depth)))
- ;; Note: The main purpose of the above `when' test is to avoid running
- ;; this `setf' before `gv' is loaded during bootstrap.
- (setf (alist-get function (get hook 'hook--depth-alist) 0) depth))
- (setq hook-value
- (if (< 0 depth)
- (append hook-value (list function))
- (cons function hook-value)))
- (let ((depth-alist (get hook 'hook--depth-alist)))
- (when depth-alist
- (setq hook-value
- (sort (if (< 0 depth) hook-value (copy-sequence hook-value))
- (lambda (f1 f2)
- (< (alist-get f1 depth-alist 0 nil #'eq)
- (alist-get f2 depth-alist 0 nil #'eq))))))))
+ (let ((depth-sym (get hook 'hook--depth-alist)))
+ ;; While the `member' test above has to use `equal' for historical
+ ;; reasons, `equal' is a performance problem on large/cyclic functions,
+ ;; so we index `hook--depth-alist' with `eql'. (bug#46326)
+ (unless (zerop depth)
+ (unless depth-sym
+ (setq depth-sym (make-symbol "depth-alist"))
+ (set depth-sym nil)
+ (setf (get hook 'hook--depth-alist) depth-sym))
+ (if local (make-local-variable depth-sym))
+ (setf (alist-get function
+ (if local (symbol-value depth-sym)
+ (default-value depth-sym))
+ 0)
+ depth))
+ (setq hook-value
+ (if (< 0 depth)
+ (append hook-value (list function))
+ (cons function hook-value)))
+ (when depth-sym
+ (let ((depth-alist (if local (symbol-value depth-sym)
+ (default-value depth-sym))))
+ (when depth-alist
+ (setq hook-value
+ (sort (if (< 0 depth) hook-value (copy-sequence hook-value))
+ (lambda (f1 f2)
+ (< (alist-get f1 depth-alist 0 nil #'eq)
+ (alist-get f2 depth-alist 0 nil #'eq))))))))))
;; Set the actual variable
(if local
(progn
@@ -1971,7 +2043,7 @@ one will be removed."
(format "%s hook to remove: "
(if local "Buffer-local" "Global"))
fn-alist
- nil t)
+ nil t nil 'set-variable-value-history)
fn-alist nil nil #'string=)))
(list hook function local)))
(or (boundp hook) (set hook nil))
@@ -1996,9 +2068,14 @@ one will be removed."
(when old-fun
;; Remove auxiliary depth info to avoid leaks (bug#46414)
;; and to avoid the list growing too long.
- (let* ((depths (get hook 'hook--depth-alist))
- (di (assq old-fun depths)))
- (when di (put hook 'hook--depth-alist (delq di depths)))))
+ (let* ((depth-sym (get hook 'hook--depth-alist))
+ (depth-alist (if depth-sym (if local (symbol-value depth-sym)
+ (default-value depth-sym))))
+ (di (assq old-fun depth-alist)))
+ (when di
+ (setf (if local (symbol-value depth-sym)
+ (default-value depth-sym))
+ (remq di depth-alist)))))
;; If the function is on the global hook, we need to shadow it locally
;;(when (and local (member function (default-value hook))
;; (not (member (cons 'not function) hook-value)))
@@ -2160,7 +2237,7 @@ can do the job."
(not (macroexp-const-p append)))
exp
(let* ((sym (cadr list-var))
- (append (eval append))
+ (append (eval append lexical-binding))
(msg (format-message
"`add-to-list' can't use lexical var `%s'; use `push' or `cl-pushnew'"
sym))
@@ -2347,6 +2424,102 @@ Affects only hooks run in the current buffer."
(let ((delay-mode-hooks t))
,@body)))
+;;; `when-let' and friends.
+
+(defun internal--build-binding (binding prev-var)
+ "Check and build a single BINDING with PREV-VAR."
+ (setq binding
+ (cond
+ ((symbolp binding)
+ (list binding binding))
+ ((null (cdr binding))
+ (list (make-symbol "s") (car binding)))
+ (t binding)))
+ (when (> (length binding) 2)
+ (signal 'error
+ (cons "`let' bindings can have only one value-form" binding)))
+ (let ((var (car binding)))
+ `(,var (and ,prev-var ,(cadr binding)))))
+
+(defun internal--build-bindings (bindings)
+ "Check and build conditional value forms for BINDINGS."
+ (let ((prev-var t))
+ (mapcar (lambda (binding)
+ (let ((binding (internal--build-binding binding prev-var)))
+ (setq prev-var (car binding))
+ binding))
+ bindings)))
+
+(defmacro if-let* (varlist then &rest else)
+ "Bind variables according to VARLIST and evaluate THEN or ELSE.
+This is like `if-let' but doesn't handle a VARLIST of the form
+\(SYMBOL SOMETHING) specially."
+ (declare (indent 2)
+ (debug ((&rest [&or symbolp (symbolp form) (form)])
+ body)))
+ (if varlist
+ `(let* ,(setq varlist (internal--build-bindings varlist))
+ (if ,(caar (last varlist))
+ ,then
+ ,@else))
+ `(let* () ,then)))
+
+(defmacro when-let* (varlist &rest body)
+ "Bind variables according to VARLIST and conditionally evaluate BODY.
+This is like `when-let' but doesn't handle a VARLIST of the form
+\(SYMBOL SOMETHING) specially."
+ (declare (indent 1) (debug if-let*))
+ (list 'if-let* varlist (macroexp-progn body)))
+
+(defmacro and-let* (varlist &rest body)
+ "Bind variables according to VARLIST and conditionally evaluate BODY.
+Like `when-let*', except if BODY is empty and all the bindings
+are non-nil, then the result is non-nil."
+ (declare (indent 1) (debug if-let*))
+ (let (res)
+ (if varlist
+ `(let* ,(setq varlist (internal--build-bindings varlist))
+ (when ,(setq res (caar (last varlist)))
+ ,@(or body `(,res))))
+ `(let* () ,@(or body '(t))))))
+
+(defmacro if-let (spec then &rest else)
+ "Bind variables according to SPEC and evaluate THEN or ELSE.
+Evaluate each binding in turn, as in `let*', stopping if a
+binding value is nil. If all are non-nil return the value of
+THEN, otherwise the last form in ELSE.
+
+Each element of SPEC is a list (SYMBOL VALUEFORM) that binds
+SYMBOL to the value of VALUEFORM. An element can additionally be
+of the form (VALUEFORM), which is evaluated and checked for nil;
+i.e. SYMBOL can be omitted if only the test result is of
+interest. It can also be of the form SYMBOL, then the binding of
+SYMBOL is checked for nil.
+
+As a special case, interprets a SPEC of the form \(SYMBOL SOMETHING)
+like \((SYMBOL SOMETHING)). This exists for backward compatibility
+with an old syntax that accepted only one binding."
+ (declare (indent 2)
+ (debug ([&or (symbolp form) ; must be first, Bug#48489
+ (&rest [&or symbolp (symbolp form) (form)])]
+ body)))
+ (when (and (<= (length spec) 2)
+ (not (listp (car spec))))
+ ;; Adjust the single binding case
+ (setq spec (list spec)))
+ (list 'if-let* spec then (macroexp-progn else)))
+
+(defmacro when-let (spec &rest body)
+ "Bind variables according to SPEC and conditionally evaluate BODY.
+Evaluate each binding in turn, stopping if a binding value is nil.
+If all are non-nil, return the value of the last form in BODY.
+
+The variable list SPEC is the same as in `if-let'."
+ (declare (indent 1) (debug if-let))
+ (list 'if-let spec (macroexp-progn body)))
+
+
+
;; PUBLIC: find if the current mode derives from another.
(defun provided-mode-derived-p (mode &rest modes)
@@ -2695,7 +2868,8 @@ It can be retrieved with `(process-get PROCESS PROPNAME)'."
(defun memory-limit ()
"Return an estimate of Emacs virtual memory usage, divided by 1024."
- (or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0))
+ (let ((default-directory temporary-file-directory))
+ (or (cdr (assq 'vsize (process-attributes (emacs-pid)))) 0)))
;;;; Input and display facilities.
@@ -2709,7 +2883,7 @@ It can be retrieved with `(process-get PROCESS PROPNAME)'."
(defconst read-key-full-map
(let ((map (make-sparse-keymap)))
- (define-key map [t] 'dummy)
+ (define-key map [t] #'ignore) ;Dummy binding.
;; ESC needs to be unbound so that escape sequences in
;; `input-decode-map' are still processed by `read-key-sequence'.
@@ -2866,6 +3040,7 @@ by doing (clear-string STRING)."
(use-local-map read-passwd-map)
(setq-local inhibit-modification-hooks nil) ;bug#15501.
(setq-local show-paren-mode nil) ;bug#16091.
+ (setq-local inhibit--record-char t)
(add-hook 'post-command-hook #'read-password--hide-password nil t))
(unwind-protect
(let ((enable-recursive-minibuffers t)
@@ -2891,7 +3066,8 @@ DEFAULT specifies a default value to return if the user just types RET.
The value of DEFAULT is inserted into PROMPT.
HIST specifies a history list variable. See `read-from-minibuffer'
for details of the HIST argument.
-This function is used by the `interactive' code letter `n'."
+
+This function is used by the `interactive' code letter \"n\"."
(let ((n nil)
(default1 (if (consp default) (car default) default)))
(when default1
@@ -3094,7 +3270,7 @@ If there is a natural number at point, use it as default."
(make-hash-table :test 'equal))
(defun read-char-from-minibuffer-insert-char ()
- "Insert the character you type in the minibuffer and exit.
+ "Insert the character you type into the minibuffer and exit minibuffer.
Discard all previous input before inserting and exiting the minibuffer."
(interactive)
(when (minibufferp)
@@ -3103,9 +3279,11 @@ Discard all previous input before inserting and exiting the minibuffer."
(exit-minibuffer)))
(defun read-char-from-minibuffer-insert-other ()
- "Handle inserting of a character other than allowed.
-Display an error on trying to insert a disallowed character.
-Also discard all previous input in the minibuffer."
+ "Reject a disallowed character typed into the minibuffer.
+This command is intended to be bound to keys that users are not
+allowed to type into the minibuffer. When the user types any
+such key, this command discard all minibuffer input and displays
+an error message."
(interactive)
(when (minibufferp)
(delete-minibuffer-contents)
@@ -3249,6 +3427,15 @@ switch back again to the minibuffer before entering the
character. This is not possible when using `read-key', but using
`read-key' may be less confusing to some users.")
+(defvar from--tty-menu-p nil
+ "Non-nil means the current command was invoked from a TTY menu.")
+(defun use-dialog-box-p ()
+ "Say whether the current command should prompt the user via a dialog box."
+ (and last-input-event ; not during startup
+ (or (listp last-nonmenu-event) ; invoked by a mouse event
+ from--tty-menu-p) ; invoked via TTY menu
+ use-dialog-box))
+
(defun y-or-n-p (prompt)
"Ask user a \"y or n\" question.
Return t if answer is \"y\" and nil if it is \"n\".
@@ -3308,10 +3495,7 @@ like) while `y-or-n-p' is running)."
((and (member str '("h" "H")) help-form) (print help-form))
(t (setq temp-prompt (concat "Please answer y or n. "
prompt))))))))
- ((and (display-popup-menus-p)
- last-input-event ; not during startup
- (listp last-nonmenu-event)
- use-dialog-box)
+ ((use-dialog-box-p)
(setq prompt (funcall padded prompt t)
answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip)))))
(y-or-n-p-use-read-key
@@ -3728,14 +3912,18 @@ Note: :data and :device are currently not supported on Windows."
(declare-function w32-shell-dos-semantics "w32-fns" nil)
-(defun shell-quote-argument (argument)
+(defun shell-quote-argument (argument &optional posix)
"Quote ARGUMENT for passing as argument to an inferior shell.
This function is designed to work with the syntax of your system's
standard shell, and might produce incorrect results with unusual shells.
-See Info node `(elisp)Security Considerations'."
- (cond
- ((eq system-type 'ms-dos)
+See Info node `(elisp)Security Considerations'.
+
+If the optional POSIX argument is non-nil, ARGUMENT is quoted
+according to POSIX shell quoting rules, regardless of the
+system's shell."
+(cond
+ ((and (not posix) (eq system-type 'ms-dos))
;; Quote using double quotes, but escape any existing quotes in
;; the argument with backslashes.
(let ((result "")
@@ -3750,7 +3938,7 @@ See Info node `(elisp)Security Considerations'."
start (1+ end))))
(concat "\"" result (substring argument start) "\"")))
- ((and (eq system-type 'windows-nt) (w32-shell-dos-semantics))
+ ((and (not posix) (eq system-type 'windows-nt) (w32-shell-dos-semantics))
;; First, quote argument so that CommandLineToArgvW will
;; understand it. See
@@ -3816,6 +4004,11 @@ Otherwise, return nil."
(setq object (indirect-function object)))
(and (subrp object) (eq (cdr (subr-arity object)) 'unevalled)))
+(defun plistp (object)
+ "Non-nil if and only if OBJECT is a valid plist."
+ (let ((len (proper-list-p object)))
+ (and len (zerop (% len 2)))))
+
(defun macrop (object)
"Non-nil if and only if OBJECT is a macro."
(let ((def (indirect-function object)))
@@ -3893,7 +4086,12 @@ remove properties specified by `yank-excluded-properties'."
This function is like `insert', except it honors the variables
`yank-handled-properties' and `yank-excluded-properties', and the
-`yank-handler' text property, in the way that `yank' does."
+`yank-handler' text property, in the way that `yank' does.
+
+It also runs the string through `yank-transform-functions'."
+ ;; Allow altering the yank string.
+ (run-hook-wrapped 'yank-transform-functions
+ (lambda (f) (setq string (funcall f string)) nil))
(let (to)
(while (setq to (next-single-property-change 0 'yank-handler string))
(insert-for-yank-1 (substring string 0 to))
@@ -4294,11 +4492,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
@@ -4424,8 +4624,9 @@ of that nature."
(unwind-protect
(progn
,@body)
- (unless ,modified
- (restore-buffer-modified-p nil))))))
+ (when (or (not ,modified)
+ (eq ,modified 'autosaved))
+ (restore-buffer-modified-p ,modified))))))
(defmacro with-output-to-string (&rest body)
"Execute BODY, return the text it sent to `standard-output', as a string."
@@ -4454,7 +4655,7 @@ is allowed once again. (Immediately, if `inhibit-quit' is nil.)"
;; Without this, it will not be handled until the next function
;; call, and that might allow it to exit thru a condition-case
;; that intends to handle the quit signal next time.
- (eval '(ignore nil)))))
+ (eval '(ignore nil) t))))
(defmacro while-no-input (&rest body)
"Execute BODY only as long as there's no pending input.
@@ -4504,9 +4705,6 @@ even if this catches the signal."
,@(cdr handler)))
handlers)))
-(define-obsolete-function-alias 'condition-case-no-debug
- 'condition-case-unless-debug "24.1")
-
(defmacro with-demoted-errors (format &rest body)
"Run BODY and demote any errors to simple messages.
FORMAT is a string passed to `message' to format any error message.
@@ -4514,19 +4712,21 @@ It should contain a single %-sequence; e.g., \"Error: %S\".
If `debug-on-error' is non-nil, run BODY without catching its errors.
This is to be used around code that is not expected to signal an error
-but that should be robust in the unexpected case that an error is signaled.
-
-For backward compatibility, if FORMAT is not a constant string, it
-is assumed to be part of BODY, in which case the message format
-used is \"Error: %S\"."
+but that should be robust in the unexpected case that an error is signaled."
(declare (debug t) (indent 1))
- (let ((err (make-symbol "err"))
- (format (if (and (stringp format) body) format
- (prog1 "Error: %S"
- (if format (push format body))))))
- `(condition-case-unless-debug ,err
- ,(macroexp-progn body)
- (error (message ,format ,err) nil))))
+ (let* ((err (make-symbol "err"))
+ (orig-body body)
+ (format (if (and (stringp format) body) format
+ (prog1 "Error: %S"
+ (if format (push format body)))))
+ (exp
+ `(condition-case-unless-debug ,err
+ ,(macroexp-progn body)
+ (error (message ,format ,err) nil))))
+ (if (eq orig-body body) exp
+ ;; The use without `format' is obsolete, let's warn when we bump
+ ;; into any such remaining uses.
+ (macroexp-warn-and-return "Missing format argument" exp nil nil format))))
(defmacro combine-after-change-calls (&rest body)
"Execute BODY, but don't call the after-change functions till the end.
@@ -5808,7 +6008,16 @@ To test whether a function can be called interactively, use
(define-obsolete-function-alias
'set-temporary-overlay-map #'set-transient-map "24.4")
-(defun set-transient-map (map &optional keep-pred on-exit)
+(defvar set-transient-map-timeout nil
+ "Timeout in seconds for deactivation of a transient keymap.
+If this is a number, it specifies the amount of idle time
+after which to deactivate the keymap set by `set-transient-map',
+thus overriding the value of the TIMEOUT argument to that function.")
+
+(defvar set-transient-map-timer nil
+ "Timer for `set-transient-map-timeout'.")
+
+(defun set-transient-map (map &optional keep-pred on-exit message timeout)
"Set MAP as a temporary keymap taking precedence over other keymaps.
Normally, MAP is used only once, to look up the very next key.
However, if the optional argument KEEP-PRED is t, MAP stays
@@ -5819,24 +6028,52 @@ if it returns non-nil, then MAP stays active.
Optional arg ON-EXIT, if non-nil, specifies a function that is
called, with no arguments, after MAP is deactivated.
-This uses `overriding-terminal-local-map', which takes precedence over all
-other keymaps. As usual, if no match for a key is found in MAP, the normal
-key lookup sequence then continues.
+Optional arg MESSAGE, if non-nil, requests display of an informative
+message after activating the transient map. If MESSAGE is a string,
+it specifies the format string for the message to display, and the %k
+specifier in the string is replaced with the list of keys from the
+transient map. Any other non-nil value of MESSAGE means to use the
+message format string \"Repeat with %k\". Upon deactivating the map,
+the displayed message will be cleared out.
+
+Optional arg TIMEOUT, if non-nil, should be a number specifying the
+number of seconds of idle time after which the map is deactivated.
+The variable `set-transient-map-timeout', if non-nil, overrides the
+value of TIMEOUT.
+
+This function uses `overriding-terminal-local-map', which takes precedence
+over all other keymaps. As usual, if no match for a key is found in MAP,
+the normal key lookup sequence then continues.
This returns an \"exit function\", which can be called with no argument
to deactivate this transient map, regardless of KEEP-PRED."
- (let* ((clearfun (make-symbol "clear-transient-map"))
+ (let* ((timeout (or set-transient-map-timeout timeout))
+ (message
+ (when message
+ (let (keys)
+ (map-keymap (lambda (key cmd) (and cmd (push key keys))) map)
+ (format-spec (if (stringp message) message "Repeat with %k")
+ `((?k . ,(mapconcat
+ (lambda (key)
+ (substitute-command-keys
+ (format "\\`%s'"
+ (key-description (vector key)))))
+ keys ", ")))))))
+ (clearfun (make-symbol "clear-transient-map"))
(exitfun
(lambda ()
(internal-pop-keymap map 'overriding-terminal-local-map)
(remove-hook 'pre-command-hook clearfun)
+ ;; Clear the prompt after exiting.
+ (when message (message ""))
+ (when set-transient-map-timer (cancel-timer set-transient-map-timer))
(when on-exit (funcall on-exit)))))
;; Don't use letrec, because equal (in add/remove-hook) could get trapped
;; in a cycle. (bug#46326)
(fset clearfun
(lambda ()
(with-demoted-errors "set-transient-map PCH: %S"
- (unless (cond
+ (if (cond
((null keep-pred) nil)
((and (not (eq map (cadr overriding-terminal-local-map)))
(memq map (cddr overriding-terminal-local-map)))
@@ -5853,13 +6090,23 @@ to deactivate this transient map, regardless of KEEP-PRED."
t)
((eq t keep-pred)
(let ((mc (lookup-key map (this-command-keys-vector))))
+ ;; We may have a remapped command, so chase
+ ;; down that.
+ (when (and mc (symbolp mc))
+ (setq mc (or (command-remapping mc) mc)))
;; If the key is unbound `this-command` is
;; nil and so is `mc`.
(and mc (eq this-command mc))))
(t (funcall keep-pred)))
+ ;; Repeat the message for the next command.
+ (when message (message "%s" message))
(funcall exitfun)))))
(add-hook 'pre-command-hook clearfun)
(internal-push-keymap map 'overriding-terminal-local-map)
+ (when timeout
+ (when set-transient-map-timer (cancel-timer set-transient-map-timer))
+ (setq set-transient-map-timer (run-with-idle-timer timeout nil exitfun)))
+ (when message (message "%s" message))
exitfun))
;;;; Progress reporters.
@@ -6537,4 +6784,182 @@ string will be displayed only if BODY takes longer than TIMEOUT seconds.
(lambda ()
,@body)))
+(defun function-alias-p (func &optional noerror)
+ "Return nil if FUNC is not a function alias.
+If FUNC is a function alias, return the function alias chain.
+
+If the function alias chain contains loops, an error will be
+signalled. If NOERROR, the non-loop parts of the chain is returned."
+ (declare (side-effect-free t))
+ (let ((chain nil)
+ (orig-func func))
+ (nreverse
+ (catch 'loop
+ (while (and (symbolp func)
+ (setq func (symbol-function func))
+ (symbolp func))
+ (when (or (memq func chain)
+ (eq func orig-func))
+ (if noerror
+ (throw 'loop chain)
+ (signal 'cyclic-function-indirection (list orig-func))))
+ (push func chain))
+ chain))))
+
+(defun readablep (object)
+ "Say whether OBJECT has a readable syntax.
+This means that OBJECT can be printed out and then read back
+again by the Lisp reader. This function returns nil if OBJECT is
+unreadable, and the printed representation (from `prin1') of
+OBJECT if it is readable."
+ (declare (side-effect-free t))
+ (catch 'unreadable
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ (throw 'unreadable nil))))
+ (prin1-to-string object))))
+
+(defun delete-line ()
+ "Delete the current line."
+ (delete-region (line-beginning-position)
+ (progn
+ (forward-line 1)
+ (point))))
+
+(defun ensure-empty-lines (&optional lines)
+ "Ensure that there are LINES number of empty lines before point.
+If LINES is nil or omitted, ensure that there is a single empty
+line before point.
+
+If called interactively, LINES is given by the prefix argument.
+
+If there are more than LINES empty lines before point, the number
+of empty lines is reduced to LINES.
+
+If point is not at the beginning of a line, a newline character
+is inserted before adjusting the number of empty lines."
+ (interactive "p")
+ (unless (bolp)
+ (insert "\n"))
+ (let ((lines (or lines 1))
+ (start (save-excursion
+ (if (re-search-backward "[^\n]" nil t)
+ (+ (point) 2)
+ (point-min)))))
+ (cond
+ ((> (- (point) start) lines)
+ (delete-region (point) (- (point) (- (point) start lines))))
+ ((< (- (point) start) lines)
+ (insert (make-string (- lines (- (point) start)) ?\n))))))
+
+(defun string-lines (string &optional omit-nulls keep-newlines)
+ "Split STRING into a list of lines.
+If OMIT-NULLS, empty lines will be removed from the results.
+If KEEP-NEWLINES, don't strip trailing newlines from the result
+lines."
+ (if (equal string "")
+ (if omit-nulls
+ nil
+ (list ""))
+ (let ((lines nil)
+ (start 0))
+ (while (< start (length string))
+ (let ((newline (string-search "\n" string start)))
+ (if newline
+ (progn
+ (when (or (not omit-nulls)
+ (not (= start newline)))
+ (let ((line (substring string start
+ (if keep-newlines
+ (1+ newline)
+ newline))))
+ (when (not (and keep-newlines omit-nulls
+ (equal line "\n")))
+ (push line lines))))
+ (setq start (1+ newline)))
+ ;; No newline in the remaining part.
+ (if (zerop start)
+ ;; Avoid a string copy if there are no newlines at all.
+ (push string lines)
+ (push (substring string start) lines))
+ (setq start (length string)))))
+ (nreverse lines))))
+
+(defun buffer-match-p (condition buffer-or-name &optional arg)
+ "Return non-nil if BUFFER-OR-NAME matches CONDITION.
+CONDITION is either:
+- a regular expression, to match a buffer name,
+- a predicate function that takes a buffer object and ARG as
+ arguments, and returns non-nil if the buffer matches,
+- a cons-cell, where the car describes how to interpret the cdr.
+ The car can be one of the following:
+ * `derived-mode': the buffer matches if the buffer's major mode
+ is derived from the major mode in the cons-cell's cdr.
+ * `major-mode': the buffer matches if the buffer's major mode
+ is eq to the cons-cell's cdr. Prefer using `derived-mode'
+ instead when both can work.
+ * `not': the cdr is interpreted as a negation of a condition.
+ * `and': the cdr is a list of recursive conditions, that all have
+ to be met.
+ * `or': the cdr is a list of recursive condition, of which at
+ least one has to be met."
+ (letrec
+ ((buffer (get-buffer buffer-or-name))
+ (match
+ (lambda (conditions)
+ (catch 'match
+ (dolist (condition conditions)
+ (when (cond
+ ((stringp condition)
+ (string-match-p condition (buffer-name buffer)))
+ ((functionp condition)
+ (if (eq 1 (cdr (func-arity condition)))
+ (funcall condition buffer)
+ (funcall condition buffer arg)))
+ ((eq (car-safe condition) 'major-mode)
+ (eq
+ (buffer-local-value 'major-mode buffer)
+ (cdr condition)))
+ ((eq (car-safe condition) 'derived-mode)
+ (provided-mode-derived-p
+ (buffer-local-value 'major-mode buffer)
+ (cdr condition)))
+ ((eq (car-safe condition) 'not)
+ (not (funcall match (cdr condition))))
+ ((eq (car-safe condition) 'or)
+ (funcall match (cdr condition)))
+ ((eq (car-safe condition) 'and)
+ (catch 'fail
+ (dolist (c (cdr conditions))
+ (unless (funcall match c)
+ (throw 'fail nil)))
+ t)))
+ (throw 'match t)))))))
+ (funcall match (list condition))))
+
+(defun match-buffers (condition &optional buffers arg)
+ "Return a list of buffers that match CONDITION.
+See `buffer-match' for details on CONDITION. By default all
+buffers are checked, this can be restricted by passing an
+optional argument BUFFERS, set to a list of buffers to check.
+ARG is passed to `buffer-match', for predicate conditions in
+CONDITION."
+ (let (bufs)
+ (dolist (buf (or buffers (buffer-list)))
+ (when (buffer-match-p condition (get-buffer buf) arg)
+ (push buf bufs)))
+ bufs))
+
+(defmacro with-memoization (place &rest code)
+ "Return the value of CODE and stash it in PLACE.
+If PLACE's value is non-nil, then don't bother evaluating CODE
+and return the value found in PLACE instead."
+ (declare (indent 1) (debug (gv-place body)))
+ (gv-letplace (getter setter) place
+ `(or ,getter
+ ,(macroexp-let2 nil val (macroexp-progn code)
+ `(progn
+ ,(funcall setter val)
+ ,val)))))
+
;;; subr.el ends here
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index d49fc2efeab..fdfbe207b5f 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -229,7 +229,7 @@ a list of frames to update."
(defun tab-bar--key-to-number (key)
"Return the tab number represented by KEY.
-If KEY is a symbol 'tab-N', where N is a tab number, the value is N.
+If KEY is a symbol `tab-N', where N is a tab number, the value is N.
If KEY is \\='current-tab, the value is nil.
For any other value of KEY, the value is t."
(cond
@@ -426,7 +426,7 @@ on each new frame when the global `tab-bar-mode' is disabled,
or if you want to disable the tab bar individually on each
new frame when the global `tab-bar-mode' is enabled, by using
- (add-hook 'after-make-frame-functions 'toggle-frame-tab-bar)"
+ (add-hook \\='after-make-frame-functions #\\='toggle-frame-tab-bar)"
(interactive)
(set-frame-parameter frame 'tab-bar-lines
(if (> (frame-parameter frame 'tab-bar-lines) 0) 0 1))
@@ -474,18 +474,22 @@ you can use the command `toggle-frame-tab-bar'."
If t, start a new tab with the current buffer, i.e. the buffer
that was current before calling the command that adds a new tab
(this is the same what `make-frame' does by default).
+If the value is the symbol `window', then keep the selected
+window as a single window on the new tab, and keep all its
+window parameters except `window-atom' and `window-side'.
If the value is a string, use it as a buffer name to switch to
if such buffer exists, or switch to a buffer visiting the file or
directory that the string specifies. If the value is a function,
call it with no arguments and switch to the buffer that it returns.
-If nil, duplicate the contents of the tab that was active
+If `clone', duplicate the contents of the tab that was active
before calling the command that adds a new tab."
:type '(choice (const :tag "Current buffer" t)
+ (const :tag "Current window" window)
(string :tag "Buffer" "*scratch*")
(directory :tag "Directory" :value "~/")
(file :tag "File" :value "~/.emacs")
(function :tag "Function")
- (const :tag "Duplicate tab" nil))
+ (const :tag "Duplicate tab" clone))
:group 'tab-bar
:version "27.1")
@@ -614,7 +618,7 @@ Also add the number of windows in the window configuration."
"Maximum length of the tab name from the current buffer.
Effective when `tab-bar-tab-name-function' is customized
to `tab-bar-tab-name-truncated'."
- :type 'integer
+ :type 'natnum
:group 'tab-bar
:version "27.1")
@@ -751,9 +755,13 @@ Used by `tab-bar-format-menu-bar'."
(menu-bar-keymap))
(popup-menu menu event)))
+(defvar tab-bar-menu-bar-button
+ (propertize "Menu" 'face 'tab-bar-tab-inactive)
+ "Button for the menu bar.")
+
(defun tab-bar-format-menu-bar ()
"Produce the Menu button for the tab bar that shows the menu bar."
- `((menu-bar menu-item (propertize "Menu" 'face 'tab-bar-tab-inactive)
+ `((menu-bar menu-item ,tab-bar-menu-bar-button
tab-bar-menu-bar :help "Menu Bar")))
(defun tab-bar-format-history ()
@@ -907,8 +915,8 @@ when the tab is current. Return the result as a keymap."
(let* ((rest (cdr (memq 'tab-bar-format-align-right tab-bar-format)))
(rest (tab-bar-format-list rest))
(rest (mapconcat (lambda (item) (nth 2 item)) rest ""))
- (hpos (length rest))
- (str (propertize " " 'display `(space :align-to (- right ,hpos)))))
+ (hpos (string-pixel-width (propertize rest 'face 'tab-bar)))
+ (str (propertize " " 'display `(space :align-to (- right (,hpos))))))
`((align-right menu-item ,str ignore))))
(defun tab-bar-format-global ()
@@ -918,7 +926,7 @@ When `tab-bar-format-global' is added to `tab-bar-format'
then modes that display information on the mode line
using `global-mode-string' will display the same text
on the tab bar instead."
- `((global menu-item ,(string-trim-right (format-mode-line global-mode-string)) ignore)))
+ `((global menu-item ,(format-mode-line global-mode-string) ignore)))
(defun tab-bar-format-list (format-list)
(let ((i 0))
@@ -1310,7 +1318,8 @@ configuration."
(let ((tab-bar-new-tab-choice 'window))
(tab-bar-new-tab))
(tab-bar-switch-to-recent-tab)
- (delete-window)
+ (let ((ignore-window-parameters t))
+ (delete-window))
(tab-bar-switch-to-recent-tab))
@@ -1357,14 +1366,26 @@ After the tab is created, the hooks in
;; Handle the case when it's called in the active minibuffer.
(when (minibuffer-selected-window)
(select-window (minibuffer-selected-window)))
+ ;; Remove window parameters that can cause problems
+ ;; with `delete-other-windows' and `split-window'.
+ (unless (eq tab-bar-new-tab-choice 'clone)
+ (set-window-parameter nil 'window-atom nil)
+ (set-window-parameter nil 'window-side nil))
(let ((ignore-window-parameters t))
- (delete-other-windows))
- (unless (eq tab-bar-new-tab-choice 'window)
- ;; Create a new window to get rid of old window parameters
- ;; (e.g. prev/next buffers) of old window.
- (split-window) (delete-window))
+ (if (eq tab-bar-new-tab-choice 'clone)
+ ;; Create new unique windows with the same layout
+ (window-state-put (window-state-get))
+ (delete-other-windows)
+ (if (eq tab-bar-new-tab-choice 'window)
+ ;; Create new unique window from remaining window
+ (window-state-put (window-state-get))
+ ;; Create a new window to get rid of old window parameters
+ ;; (e.g. prev/next buffers) of old window.
+ (split-window) (delete-window))))
+
(let ((buffer
- (if (functionp tab-bar-new-tab-choice)
+ (if (and (functionp tab-bar-new-tab-choice)
+ (not (memq tab-bar-new-tab-choice '(clone window))))
(funcall tab-bar-new-tab-choice)
(if (stringp tab-bar-new-tab-choice)
(or (get-buffer tab-bar-new-tab-choice)
@@ -1440,7 +1461,7 @@ If FROM-NUMBER is a tab number, a new tab is created from that tab."
"Clone the current tab to ARG positions to the right.
ARG and FROM-NUMBER have the same meaning as in `tab-bar-new-tab'."
(interactive "P")
- (let ((tab-bar-new-tab-choice nil)
+ (let ((tab-bar-new-tab-choice 'clone)
(tab-bar-new-tab-group t))
(tab-bar-new-tab arg from-number)))
@@ -1638,9 +1659,10 @@ happens interactively)."
(setq index (max 0 (min index (length tabs))))
(cl-pushnew tab (nthcdr index tabs))
(when (eq index 0)
- ;; pushnew handles the head of tabs but not frame-parameter
+ ;; `pushnew' handles the head of tabs but not frame-parameter
(tab-bar-tabs-set tabs))
- (tab-bar-select-tab (1+ index))))
+ (tab-bar-select-tab (1+ index)))
+ (tab-bar--update-tab-bar-lines))
(message "No more closed tabs to undo")))
@@ -2298,9 +2320,9 @@ Interactively, prompt for the buffer to switch to."
(declare (advertised-calling-convention (buffer-or-name) "28.1"))
(interactive
(list (read-buffer-to-switch "Switch to buffer in other tab: ")))
- (display-buffer (window-normalize-buffer-to-switch-to buffer-or-name)
- '((display-buffer-in-tab)
- (inhibit-same-window . nil))))
+ (pop-to-buffer (window-normalize-buffer-to-switch-to buffer-or-name)
+ '((display-buffer-in-tab)
+ (inhibit-same-window . nil))))
(defun find-file-other-tab (filename &optional wildcards)
"Edit file FILENAME, in another tab.
@@ -2403,7 +2425,7 @@ When `switch-to-buffer-obey-display-actions' is non-nil,
(define-key map "o" 'tab-next)
(define-key map "O" 'tab-previous)
map)
- "Keymap to repeat tab switch key sequences `C-x t o o O'.
+ "Keymap to repeat tab switch key sequences \\`C-x t o o O'.
Used in `repeat-mode'.")
(put 'tab-next 'repeat-map 'tab-bar-switch-repeat-map)
(put 'tab-previous 'repeat-map 'tab-bar-switch-repeat-map)
@@ -2413,7 +2435,7 @@ Used in `repeat-mode'.")
(define-key map "m" 'tab-move)
(define-key map "M" 'tab-bar-move-tab-backward)
map)
- "Keymap to repeat tab move key sequences `C-x t m m M'.
+ "Keymap to repeat tab move key sequences \\`C-x t m m M'.
Used in `repeat-mode'.")
(put 'tab-move 'repeat-map 'tab-bar-move-repeat-map)
(put 'tab-bar-move-tab-backward 'repeat-map 'tab-bar-move-repeat-map)
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 1c1217cdf6e..3e3b4c95595 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -288,7 +288,7 @@ variable `tab-line-tab-name-function'."
"Maximum length of the tab name from the current buffer.
Effective when `tab-line-tab-name-function' is customized
to `tab-line-tab-name-truncated-buffer'."
- :type 'integer
+ :type 'natnum
:group 'tab-line
:version "27.1")
@@ -486,7 +486,7 @@ which the tab will represent."
(funcall tab-line-tab-name-function tab tabs)
(cdr (assq 'name tab))))
(face (if selected-p
- (if (eq (selected-window) (old-selected-window))
+ (if (mode-line-window-selected-p)
'tab-line-tab-current
'tab-line-tab)
'tab-line-tab-inactive)))
@@ -558,8 +558,9 @@ inherit from `tab-line-tab-inactive-alternate'. For use in
When TAB is a non-file-visiting buffer, make FACE inherit from
`tab-line-tab-special'. For use in
`tab-line-tab-face-functions'."
- (when (and buffer-p (not (buffer-file-name tab)))
- (setf face `(:inherit (tab-line-tab-special ,face))))
+ (let ((buffer (if buffer-p tab (cdr (assq 'buffer tab)))))
+ (when (and buffer (not (buffer-file-name buffer)))
+ (setf face `(:inherit (tab-line-tab-special ,face)))))
face)
(defun tab-line-tab-face-modified (tab _tabs face buffer-p _selected-p)
@@ -567,8 +568,9 @@ When TAB is a non-file-visiting buffer, make FACE inherit from
When TAB is a modified, file-backed buffer, make FACE inherit
from `tab-line-tab-modified'. For use in
`tab-line-tab-face-functions'."
- (when (and buffer-p (buffer-file-name tab) (buffer-modified-p tab))
- (setf face `(:inherit (tab-line-tab-modified ,face))))
+ (let ((buffer (if buffer-p tab (cdr (assq 'buffer tab)))))
+ (when (and buffer (buffer-file-name buffer) (buffer-modified-p buffer))
+ (setf face `(:inherit (tab-line-tab-modified ,face)))))
face)
(defun tab-line-tab-face-group (tab _tabs face _buffer-p _selected-p)
@@ -589,7 +591,7 @@ For use in `tab-line-tab-face-functions'."
;; handle tab-line scrolling
(window-parameter nil 'tab-line-hscroll)
;; for setting face 'tab-line-tab-current'
- (eq (selected-window) (old-selected-window))
+ (mode-line-window-selected-p)
(and (memq 'tab-line-tab-face-modified
tab-line-tab-face-functions)
(buffer-file-name) (buffer-modified-p))))
diff --git a/lisp/term.el b/lisp/term.el
index 895dfbed6c1..a28d8c5d761 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -523,6 +523,16 @@ This means text can automatically reflow if the window is resized."
(make-obsolete-variable 'term-suppress-hard-newline nil
"27.1")
+(defcustom term-clear-full-screen-programs t
+ "Whether to clear contents of full-screen terminal programs after exit.
+If non-nil, output of full-screen terminal programs is cleared after
+exiting them. Note however that a minority of such programs
+don't send an appropriate escape sequence to the terminal before
+exiting so their output isn't cleared regardless of this option."
+ :version "29.1"
+ :type 'boolean
+ :group 'term)
+
;; Where gud-display-frame should put the debugging arrow. This is
;; set by the marker-filter, which scans the debugger's output for
;; indications of the current pc.
@@ -905,9 +915,16 @@ Term buffers are truncated from the top to be no greater than this number.
Notice that a setting of 0 means \"don't truncate anything\". This variable
is buffer-local."
:group 'term
- :type 'integer
+ :type 'natnum
:version "27.1")
+(defcustom term-bind-function-keys nil
+ "If nil, don't alter <f1>, <f2> and so on.
+If non-nil, bind these keys in `term-mode' and send them to the
+underlying shell."
+ :type 'boolean
+ :version "29.1")
+
;; Set up term-raw-map, etc.
@@ -948,6 +965,10 @@ is buffer-local."
(define-key map [next] 'term-send-next)
(define-key map [xterm-paste] #'term--xterm-paste)
(define-key map [?\C-/] #'term-send-C-_)
+
+ (when term-bind-function-keys
+ (dotimes (key 21)
+ (keymap-set map (format "<f%d>" key) #'term-send-function-key)))
map)
"Keyboard map for sending characters directly to the inferior process.")
@@ -1031,11 +1052,10 @@ is buffer-local."
"Change `term-escape-char' and keymaps that depend on it."
(when term-escape-char
;; Undo previous term-set-escape-char.
- (define-key term-raw-map term-escape-char 'term-send-raw))
+ (define-key term-raw-map term-escape-char 'term-send-raw)
+ (define-key term-raw-escape-map term-escape-char nil t))
(setq term-escape-char (if (vectorp key) key (vector key)))
(define-key term-raw-map term-escape-char term-raw-escape-map)
- ;; FIXME: If we later call term-set-escape-char again with another key,
- ;; we should undo this binding.
(define-key term-raw-escape-map term-escape-char 'term-send-raw))
(term-set-escape-char (or term-escape-char ?\C-c))
@@ -1270,7 +1290,8 @@ Entry to this mode runs the hooks on `term-mode-hook'."
(when (/= width term-width)
(save-excursion
(term--remove-fake-newlines)))
- (let ((point (point)))
+ (let ((point (point))
+ (home-marker (marker-position term-home-marker)))
(setq term-height height)
(setq term-width width)
(setq term-start-line-column nil)
@@ -1279,11 +1300,20 @@ Entry to this mode runs the hooks on `term-mode-hook'."
(term--reset-scroll-region)
;; `term-set-scroll-region' causes these to be set, we have to
;; clear them again since we're changing point (Bug#30544).
+ (term--unwrap-visible-long-lines width)
(setq term-start-line-column nil)
(setq term-current-row nil)
(setq term-current-column nil)
- (goto-char point))
- (term--unwrap-visible-long-lines width)))
+ (goto-char point)
+
+ (when (term-using-alternate-sub-buffer)
+ (term-handle-deferred-scroll)
+ ;; When using an alternative sub-buffer, the home marker should
+ ;; not move forward. Bring it back by deleting text in front of
+ ;; it.
+ (when (> term-home-marker home-marker)
+ (let ((inhibit-read-only t))
+ (delete-region home-marker term-home-marker)))))))
;; Recursive routine used to check if any string in term-kill-echo-list
;; matches part of the buffer before point.
@@ -1391,14 +1421,31 @@ Entry to this mode runs the hooks on `term-mode-hook'."
(defun term-send-del () (interactive) (term-send-raw-string "\e[3~"))
(defun term-send-backspace () (interactive) (term-send-raw-string "\C-?"))
(defun term-send-C-_ () (interactive) (term-send-raw-string "\C-_"))
+
+(defun term-send-function-key ()
+ "If bound to a function key, this will send that key to the underlying shell."
+ (interactive)
+ (let ((key (this-command-keys-vector)))
+ (when (and (= (length key) 1)
+ (symbolp (elt key 0)))
+ (let ((name (symbol-name (elt key 0))))
+ (when (string-match "\\`f\\([0-9]+\\)\\'" name)
+ (let* ((num (string-to-number (match-string 1 name)))
+ (ansi
+ (cond
+ ((<= num 5) (+ num 10))
+ ((<= num 10) (+ num 11))
+ ((<= num 14) (+ num 12))
+ ((<= num 16) (+ num 13))
+ ((<= num 20) (+ num 14)))))
+ (when ansi
+ (term-send-raw-string (format "\e[%d~" ansi)))))))))
+
(defun term-char-mode ()
"Switch to char (\"raw\") sub-mode of term mode.
Each character you type is sent directly to the inferior without
-intervention from Emacs, except for the escape character (usually C-c).
-
-This command will send existing partial lines to the terminal
-process."
+intervention from Emacs, except for the escape character (usually C-c)."
(interactive)
;; FIXME: Emit message? Cfr ilisp-raw-message
(when (term-in-line-mode)
@@ -1417,10 +1464,10 @@ process."
(when (> (point) pmark)
(unwind-protect
(progn
- (add-function :override term-input-sender #'term-send-string)
+ (add-function :override (local 'term-input-sender) #'term-send-string)
(end-of-line)
(term-send-input))
- (remove-function term-input-sender #'term-send-string))))
+ (remove-function (local 'term-input-sender) #'term-send-string))))
(term-update-mode-line)))
(defun term-line-mode ()
@@ -1530,7 +1577,8 @@ commands to use in that buffer.
(or explicit-shell-file-name
(getenv "ESHELL")
shell-file-name))))
- (set-buffer (make-term "terminal" program))
+ (let ((prog (split-string-shell-command program)))
+ (set-buffer (apply #'make-term "terminal" (car prog) nil (cdr prog))))
(term-char-mode)
(pop-to-buffer-same-window "*terminal*"))
@@ -1611,6 +1659,7 @@ Using \"emacs\" loses, because bash disables editing if $TERM == emacs.")
"%s%s:li#%d:co#%d:cl=\\E[H\\E[J:cd=\\E[J:bs:am:xn:cm=\\E[%%i%%d;%%dH\
:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt\
:al=\\E[L:dl=\\E[M:DL=\\E[%%dM:AL=\\E[%%dL:cs=\\E[%%i%%d;%%dr:sf=^J\
+:NR:te=\\E[47l:ti=\\E[47h\
:dc=\\E[P:DC=\\E[%%dP:IC=\\E[%%d@:im=\\E[4h:ei=\\E[4l:mi:\
:mb=\\E[5m:mh=\\E[2m:ZR=\\E[23m:ZH=\\E[3m\
:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:md=\\E[1m:mr=\\E[7m:me=\\E[m\
@@ -2424,7 +2473,7 @@ Checks if STRING contains a password prompt as defined by
"Long inputs send to term processes are broken up into chunks of this size.
If your process is choking on big inputs, try lowering the value."
:group 'term
- :type 'integer)
+ :type 'natnum)
(defun term-send-string (proc str)
"Send to PROC the contents of STR as input.
@@ -3539,16 +3588,14 @@ otherwise use the current foreground color."
((eq char ?h)
(cond ((eq (car params) 4) ;; (terminfo: smir)
(setq term-insert-mode t))
- ;; ((eq (car params) 47) ;; (terminfo: smcup)
- ;; (term-switch-to-alternate-sub-buffer t))
- ))
+ ((eq (car params) 47) ;; (terminfo: smcup)
+ (term-switch-to-alternate-sub-buffer t))))
;; \E[?l - DEC Private Mode Reset
((eq char ?l)
(cond ((eq (car params) 4) ;; (terminfo: rmir)
(setq term-insert-mode nil))
- ;; ((eq (car params) 47) ;; (terminfo: rmcup)
- ;; (term-switch-to-alternate-sub-buffer nil))
- ))
+ ((eq (car params) 47) ;; (terminfo: rmcup)
+ (term-switch-to-alternate-sub-buffer nil))))
;; Modified to allow ansi coloring -mm
;; \E[m - Set/reset modes, set bg/fg
@@ -3595,32 +3642,35 @@ The top-most line is line 0."
(term-move-columns (- (term-current-column)))
(term-goto 0 0))
-;; (defun term-switch-to-alternate-sub-buffer (set)
-;; ;; If asked to switch to (from) the alternate sub-buffer, and already (not)
-;; ;; using it, do nothing. This test is needed for some programs (including
-;; ;; Emacs) that emit the ti termcap string twice, for unknown reason.
-;; (term-handle-deferred-scroll)
-;; (if (eq set (not (term-using-alternate-sub-buffer)))
-;; (let ((row (term-current-row))
-;; (col (term-horizontal-column)))
-;; (cond (set
-;; (goto-char (point-max))
-;; (if (not (eq (preceding-char) ?\n))
-;; (term-insert-char ?\n 1))
-;; (setq term-scroll-with-delete t)
-;; (setq term-saved-home-marker (copy-marker term-home-marker))
-;; (set-marker term-home-marker (point)))
-;; (t
-;; (setq term-scroll-with-delete
-;; (not (and (= term-scroll-start 0)
-;; (= term-scroll-end term-height))))
-;; (set-marker term-home-marker term-saved-home-marker)
-;; (set-marker term-saved-home-marker nil)
-;; (setq term-saved-home-marker nil)
-;; (goto-char term-home-marker)))
-;; (setq term-current-column nil)
-;; (setq term-current-row 0)
-;; (term-goto row col))))
+(defun term-switch-to-alternate-sub-buffer (set)
+ ;; If asked to switch to (from) the alternate sub-buffer, and already (not)
+ ;; using it, do nothing. This test is needed for some programs (including
+ ;; Emacs) that emit the ti termcap string twice, for unknown reason.
+ (term-handle-deferred-scroll)
+ (when (eq set (not (term-using-alternate-sub-buffer)))
+ (cond
+ (set
+ (goto-char (point-max))
+ (if (not (eq (preceding-char) ?\n))
+ (term-insert-char ?\n 1))
+ (setq term-scroll-with-delete t)
+ (setq term-saved-home-marker (copy-marker term-home-marker))
+ (set-marker term-home-marker (point)))
+ (t
+ (setq term-scroll-with-delete
+ (not (and (= term-scroll-start 0)
+ (= term-scroll-end (term--last-line)))))
+ (goto-char (point-max))
+ (when term-clear-full-screen-programs
+ (delete-region term-home-marker (point))
+ (set-marker term-home-marker term-saved-home-marker))
+ (set-marker term-saved-home-marker nil)
+ (setq term-saved-home-marker nil)))
+
+ (setq term-start-line-column nil)
+ (setq term-current-column nil)
+ (setq term-current-row nil)
+ (term-handle-deferred-scroll)))
;; Default value for the symbol term-command-function.
@@ -4323,7 +4373,7 @@ the process. Any more args are arguments to PROGRAM."
(defun ansi-term (program &optional new-buffer-name)
"Start a terminal-emulator in a new buffer.
This is almost the same as `term' apart from always creating a new buffer,
-and `C-x' being marked as a `term-escape-char'."
+and \\`C-x' being marked as a `term-escape-char'."
(interactive (list (read-from-minibuffer "Run program: "
(or explicit-shell-file-name
(getenv "ESHELL")
@@ -4346,7 +4396,10 @@ and `C-x' being marked as a `term-escape-char'."
;; for now they have the *term-ansi-term*<?> form but we'll see...
(setq term-ansi-buffer-name (generate-new-buffer-name term-ansi-buffer-name))
- (setq term-ansi-buffer-name (term-ansi-make-term term-ansi-buffer-name program))
+ (let ((prog (split-string-shell-command program)))
+ (setq term-ansi-buffer-name
+ (apply #'term-ansi-make-term term-ansi-buffer-name (car prog)
+ nil (cdr prog))))
(set-buffer term-ansi-buffer-name)
(term-mode)
diff --git a/lisp/term/common-win.el b/lisp/term/common-win.el
index 7a48fc04c6c..f7faba9cb7c 100644
--- a/lisp/term/common-win.el
+++ b/lisp/term/common-win.el
@@ -59,21 +59,19 @@
(setq system-key-alist
(list
;; These are special "keys" used to pass events from C to lisp.
- (cons 1 'ns-power-off)
- (cons 2 'ns-open-file)
- (cons 3 'ns-open-temp-file)
- (cons 4 'ns-drag-file)
- (cons 5 'ns-drag-color)
- (cons 6 'ns-drag-text)
- (cons 7 'ns-change-font)
- (cons 8 'ns-open-file-line)
-;;; (cons 9 'ns-insert-working-text)
-;;; (cons 10 'ns-delete-working-text)
- (cons 11 'ns-spi-service-call)
- (cons 12 'ns-new-frame)
- (cons 13 'ns-toggle-toolbar)
- (cons 14 'ns-show-prefs)
- ))))
+ (cons 1 (make-non-key-event 'ns-power-off))
+ (cons 2 (make-non-key-event 'ns-open-file))
+ (cons 3 (make-non-key-event 'ns-open-temp-file))
+ (cons 4 (make-non-key-event 'ns-drag-file))
+ (cons 5 (make-non-key-event 'ns-drag-color))
+ (cons 6 (make-non-key-event 'ns-drag-text))
+ (cons 8 (make-non-key-event 'ns-open-file-line))
+;;; (cons 9 (make-non-key-event 'ns-insert-working-text))
+;;; (cons 10 (make-non-key-event 'ns-delete-working-text))
+ (cons 11 (make-non-key-event 'ns-spi-service-call))
+ (cons 12 (make-non-key-event 'ns-new-frame))
+ (cons 13 (make-non-key-event 'ns-toggle-toolbar))
+ (cons 14 (make-non-key-event 'ns-show-prefs))))))
(set-terminal-parameter frame 'x-setup-function-keys t)))
(defvar x-invocation-args)
@@ -419,6 +417,16 @@ the operating system.")
(setq defined-colors (cons this-color defined-colors))))
defined-colors)))
+;;;; Session management.
+
+(defvar emacs-save-session-functions nil
+ "Special hook run when a save-session event occurs.
+The functions do not get any argument.
+Functions can return non-nil to inform the session manager that the
+window system shutdown should be aborted.
+
+See also `emacs-session-save'.")
+
(provide 'term/common-win)
;;; common-win.el ends here
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index ffd67e9cf06..f6e4829cad4 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -24,6 +24,7 @@
;;; Code:
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'subr-x))
(unless (featurep 'haiku)
(error "%s: Loading haiku-win without having Haiku"
invocation-name))
@@ -36,7 +37,7 @@
(require 'fontset)
(require 'dnd)
-(add-to-list 'display-format-alist '(".*" . haiku-win))
+(add-to-list 'display-format-alist '(".*" . haiku))
;;;; Command line argument handling.
@@ -44,13 +45,167 @@
(defvar x-command-line-resources)
(defvar haiku-initialized)
+(defvar haiku-signal-invalid-refs)
+(defvar haiku-drag-track-function)
+(defvar haiku-allowed-ui-colors)
+
+(defvar haiku-dnd-selection-value nil
+ "The local value of the special `XdndSelection' selection.")
+
+(defvar haiku-dnd-selection-converters '((STRING . haiku-dnd-convert-string)
+ (FILE_NAME . haiku-dnd-convert-file-name)
+ (text/uri-list . haiku-dnd-convert-text-uri-list))
+ "Alist of X selection types to functions that act as selection converters.
+The functions should accept a single argument VALUE, describing
+the value of the drag-and-drop selection, and return a list of
+two elements TYPE and DATA, where TYPE is a string containing the
+MIME type of DATA, and DATA is a unibyte string, or nil if the
+data could not be converted.
+
+DATA may also be a list of items; that means to add every
+individual item in DATA to the serialized message, instead of
+DATA in its entirety.
+
+DATA can optionally have a text property `type', which specifies
+the type of DATA inside the system message (see the doc string of
+`haiku-drag-message' for more details). If DATA is a list, then
+that property is obtained from the first element of DATA.")
+
+(defvar haiku-normal-selection-encoders '(haiku-select-encode-xstring
+ haiku-select-encode-utf-8-string
+ haiku-select-encode-file-name)
+ "List of functions which act as selection encoders.
+These functions accept two arguments SELECTION and VALUE, and
+return an association appropriate for a serialized system
+message (or nil if VALUE is not applicable to the encoder) that
+will be put into the system selection SELECTION. VALUE is the
+content that is being put into the selection by
+`gui-set-selection'. See the doc string of `haiku-drag-message'
+for more details on the structure of the associations.")
+
+;; This list has to be set correctly, otherwise Emacs will crash upon
+;; encountering an invalid color.
+(setq haiku-allowed-ui-colors
+ ["B_PANEL_BACKGROUND_COLOR" "B_MENU_BACKGROUND_COLOR"
+ "B_WINDOW_TAB_COLOR" "B_KEYBOARD_NAVIGATION_COLOR"
+ "B_DESKTOP_COLOR" "B_MENU_SELECTED_BACKGROUND_COLOR"
+ "B_MENU_ITEM_TEXT_COLOR" "B_MENU_SELECTED_ITEM_TEXT_COLOR"
+ "B_MENU_SELECTED_BORDER_COLOR" "B_PANEL_TEXT_COLOR"
+ "B_DOCUMENT_BACKGROUND_COLOR" "B_DOCUMENT_TEXT_COLOR"
+ "B_CONTROL_BACKGROUND_COLOR" "B_CONTROL_TEXT_COLOR"
+ "B_CONTROL_BORDER_COLOR" "B_CONTROL_HIGHLIGHT_COLOR"
+ "B_NAVIGATION_PULSE_COLOR" "B_SHINE_COLOR"
+ "B_SHADOW_COLOR" "B_TOOLTIP_BACKGROUND_COLOR"
+ "B_TOOLTIP_TEXT_COLOR" "B_WINDOW_TEXT_COLOR"
+ "B_WINDOW_INACTIVE_TAB_COLOR" "B_WINDOW_INACTIVE_TEXT_COLOR"
+ "B_WINDOW_BORDER_COLOR" "B_WINDOW_INACTIVE_BORDER_COLOR"
+ "B_CONTROL_MARK_COLOR" "B_LIST_BACKGROUND_COLOR"
+ "B_LIST_SELECTED_BACKGROUND_COLOR" "B_LIST_ITEM_TEXT_COLOR"
+ "B_LIST_SELECTED_ITEM_TEXT_COLOR" "B_SCROLL_BAR_THUMB_COLOR"
+ "B_LINK_TEXT_COLOR" "B_LINK_HOVER_COLOR"
+ "B_LINK_VISITED_COLOR" "B_LINK_ACTIVE_COLOR"
+ "B_STATUS_BAR_COLOR" "B_SUCCESS_COLOR" "B_FAILURE_COLOR"])
+
+(defvar x-colors)
+;; Also update `x-colors' to take that into account.
+(setq x-colors (append haiku-allowed-ui-colors x-colors))
+
+(defun haiku-selection-bounds (value)
+ "Return bounds of selection value VALUE.
+The return value is a list (BEG END BUF) if VALUE is a cons of
+two markers or an overlay. Otherwise, it is nil."
+ (cond ((bufferp value)
+ (with-current-buffer value
+ (when (mark t)
+ (list (mark t) (point) value))))
+ ((and (consp value)
+ (markerp (car value))
+ (markerp (cdr value)))
+ (when (and (marker-buffer (car value))
+ (buffer-name (marker-buffer (car value)))
+ (eq (marker-buffer (car value))
+ (marker-buffer (cdr value))))
+ (list (marker-position (car value))
+ (marker-position (cdr value))
+ (marker-buffer (car value)))))
+ ((overlayp value)
+ (when (overlay-buffer value)
+ (list (overlay-start value)
+ (overlay-end value)
+ (overlay-buffer value))))))
+
+(defun haiku-dnd-convert-string (value)
+ "Convert VALUE to a UTF-8 string and appropriate MIME type.
+Return a list of the appropriate MIME type, and UTF-8 data of
+VALUE as a unibyte string, or nil if VALUE was not a string."
+ (unless (stringp value)
+ (when-let ((bounds (haiku-selection-bounds value)))
+ (setq value (ignore-errors
+ (with-current-buffer (nth 2 bounds)
+ (buffer-substring (nth 0 bounds)
+ (nth 1 bounds)))))))
+ (when (stringp value)
+ (list "text/plain" (string-to-unibyte
+ (encode-coding-string value 'utf-8)))))
+
+(defun haiku-dnd-convert-file-name (value)
+ "Convert VALUE to a file system reference if it is a file name."
+ (cond ((and (stringp value)
+ (not (file-remote-p value))
+ (file-exists-p value))
+ (list "refs" (propertize (expand-file-name value)
+ 'type 'ref)))
+ ((vectorp value)
+ (list "refs"
+ (cl-loop for item across value
+ collect (propertize (expand-file-name item)
+ 'type 'ref))))))
+
+(defun haiku-dnd-convert-text-uri-list (value)
+ "Convert VALUE to a list of URLs."
+ (cond
+ ((stringp value) (list "text/uri-list"
+ (concat (url-encode-url value) "\n")))
+ ((vectorp value) (list "text/uri-list"
+ (with-temp-buffer
+ (cl-loop for tem across value
+ do (progn
+ (insert (url-encode-url tem))
+ (insert "\n")))
+ (buffer-string))))))
+
+(eval-and-compile
+ (defun haiku-get-numeric-enum (name)
+ "Return the numeric value of the system enumerator NAME."
+ (or (get name 'haiku-numeric-enum)
+ (let ((value 0)
+ (offset 0)
+ (string (symbol-name name)))
+ (cl-loop for octet across string
+ do (progn
+ (when (or (< octet 0)
+ (> octet 255))
+ (error "Out of range octet: %d" octet))
+ (setq value
+ (logior value
+ (lsh octet
+ (- (* (1- (length string)) 8)
+ offset))))
+ (setq offset (+ offset 8))))
+ (prog1 value
+ (put name 'haiku-enumerator-id value))))))
+
+(defmacro haiku-numeric-enum (name)
+ "Expand to the numeric value NAME as a system identifier."
+ (haiku-get-numeric-enum name))
(declare-function x-open-connection "haikufns.c")
(declare-function x-handle-args "common-win")
(declare-function haiku-selection-data "haikuselect.c")
(declare-function haiku-selection-put "haikuselect.c")
-(declare-function haiku-selection-targets "haikuselect.c")
+(declare-function haiku-selection-owner-p "haikuselect.c")
(declare-function haiku-put-resource "haikufns.c")
+(declare-function haiku-drag-message "haikuselect.c")
(defun haiku--handle-x-command-line-resources (command-line-resources)
"Handle command line X resources specified with the option `-xrm'.
@@ -67,7 +222,6 @@ The resources should be a list of strings in COMMAND-LINE-RESOURCES."
"Set up the window system. WINDOW-SYSTEM must be HAIKU.
DISPLAY may be set to the name of a display that will be initialized."
(cl-assert (not haiku-initialized))
-
(create-default-fontset)
(when x-command-line-resources
(haiku--handle-x-command-line-resources
@@ -85,29 +239,79 @@ DISPLAY may be set to the name of a display that will be initialized."
"Convert symbolic selection type TYPE to its MIME equivalent.
If TYPE is nil, return \"text/plain\"."
(cond
- ((memq type '(TEXT COMPOUND_TEXT STRING UTF8_STRING)) "text/plain")
+ ((eq type 'STRING) "text/plain;charset=iso-8859-1")
+ ((eq type 'UTF8_STRING) "text/plain")
((stringp type) type)
((symbolp type) (symbol-name type))
(t "text/plain")))
+(defun haiku-selection-targets (clipboard)
+ "Find the types of data available from CLIPBOARD.
+CLIPBOARD should be the symbol `PRIMARY', `SECONDARY' or
+`CLIPBOARD'. Return the available types as a list of strings."
+ (mapcar #'car (haiku-selection-data clipboard nil)))
+
+(defun haiku-select-encode-xstring (_selection value)
+ "Convert VALUE to a system message association.
+VALUE will be encoded as Latin-1 (like on X Windows) and stored
+under the type `text/plain;charset=iso-8859-1'."
+ (unless (stringp value)
+ (when-let ((bounds (haiku-selection-bounds value)))
+ (setq value (ignore-errors
+ (with-current-buffer (nth 2 bounds)
+ (buffer-substring (nth 0 bounds)
+ (nth 1 bounds)))))))
+ (when (and (stringp value) (not (string-empty-p value)))
+ (list "text/plain;charset=iso-8859-1" (haiku-numeric-enum MIME)
+ (encode-coding-string value 'iso-latin-1))))
+
+(defun haiku-select-encode-utf-8-string (_selection value)
+ "Convert VALUE to a system message association.
+VALUE will be encoded as UTF-8 and stored under the type
+`text/plain'."
+ (unless (stringp value)
+ (when-let ((bounds (haiku-selection-bounds value)))
+ (setq value (ignore-errors
+ (with-current-buffer (nth 2 bounds)
+ (buffer-substring (nth 0 bounds)
+ (nth 1 bounds)))))))
+ (when (and (stringp value) (not (string-empty-p value)))
+ (list "text/plain" (haiku-numeric-enum MIME)
+ (encode-coding-string value 'utf-8-unix))))
+
+(defun haiku-select-encode-file-name (_selection value)
+ "Convert VALUE to a system message association.
+This takes the file name of VALUE's buffer (if it is an overlay
+or a pair of markers) and turns it into a file system reference."
+ (when (setq value (xselect--selection-bounds value))
+ (list "refs" 'ref (buffer-file-name (nth 2 value)))))
+
(cl-defmethod gui-backend-get-selection (type data-type
&context (window-system haiku))
(if (eq data-type 'TARGETS)
(apply #'vector (mapcar #'intern
(haiku-selection-targets type)))
- (haiku-selection-data type (haiku--selection-type-to-mime data-type))))
+ (if (eq type 'XdndSelection)
+ haiku-dnd-selection-value
+ (haiku-selection-data type (haiku--selection-type-to-mime data-type)))))
(cl-defmethod gui-backend-set-selection (type value
&context (window-system haiku))
- (haiku-selection-put type "text/plain" value t))
+ (if (eq type 'XdndSelection)
+ (setq haiku-dnd-selection-value value)
+ (let ((message nil))
+ (dolist (encoder haiku-normal-selection-encoders)
+ (let ((result (funcall encoder type value)))
+ (when result
+ (push result message))))
+ (haiku-selection-put type message))))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system haiku))
(haiku-selection-data selection "text/plain"))
-(cl-defmethod gui-backend-selection-owner-p (_
- &context (window-system haiku))
- t)
+(cl-defmethod gui-backend-selection-owner-p (selection &context (window-system haiku))
+ (haiku-selection-owner-p selection))
(declare-function haiku-read-file-name "haikufns.c")
@@ -121,20 +325,190 @@ If TYPE is nil, return \"text/plain\"."
(or dir (and default-filename
(file-name-directory default-filename)))
mustmatch only-dir-p
- (file-name-nondirectory default-filename))
+ (and default-filename
+ (file-name-nondirectory default-filename)))
(error "x-file-dialog on a tty frame")))
-(defun haiku-dnd-handle-drag-n-drop-event (event)
+(defun haiku-parse-drag-actions (message)
+ "Given the drag-and-drop message MESSAGE, retrieve the desired action."
+ (let ((actions (cddr (assoc "be:actions" message)))
+ (sorted nil))
+ (dolist (action (list (haiku-numeric-enum DDCP)
+ (haiku-numeric-enum DDMV)
+ (haiku-numeric-enum DDLN)))
+ (when (member action actions)
+ (push sorted action)))
+ (cond
+ ((eql (car sorted) (haiku-numeric-enum DDCP)) 'copy)
+ ((eql (car sorted) (haiku-numeric-enum DDMV)) 'move)
+ ((eql (car sorted) (haiku-numeric-enum DDLN)) 'link)
+ (t 'private))))
+
+(defun haiku-drag-and-drop (event)
"Handle specified drag-n-drop EVENT."
(interactive "e")
(let* ((string (caddr event))
(window (posn-window (event-start event))))
- (with-selected-window window
- (raise-frame)
- (dnd-handle-one-url window 'private (concat "file:" string)))))
+ (if (eq string 'lambda) ; This means the mouse moved.
+ (dnd-handle-movement (event-start event))
+ (let ((action (haiku-parse-drag-actions string)))
+ (cond
+ ;; Don't allow dropping on something other than the text area.
+ ;; It does nothing and doesn't work with text anyway.
+ ((posn-area (event-start event)))
+ ((assoc "refs" string)
+ (with-selected-window window
+ (dolist (filename (cddr (assoc "refs" string)))
+ (dnd-handle-one-url window action
+ (concat "file:" filename)))))
+ ((assoc "text/uri-list" string)
+ (dolist (text (cddr (assoc "text/uri-list" string)))
+ (let ((uri-list (split-string text "[\0\r\n]" t)))
+ (dolist (bf uri-list)
+ (dnd-handle-one-url window action bf)))))
+ ((assoc "text/plain" string)
+ (with-selected-window window
+ (dolist (text (cddr (assoc "text/plain" string)))
+ (unless mouse-yank-at-point
+ (goto-char (posn-point (event-start event))))
+ (dnd-insert-text window action
+ (if (multibyte-string-p text)
+ text
+ (decode-coding-string text 'undecided))))))
+ ((not (eq (cdr (assq 'type string))
+ 3003)) ; Type of the placeholder message Emacs uses
+ ; to cancel a drop on C-g.
+ (message "Don't know how to drop any of: %s"
+ (mapcar #'car string))))))))
+
+(define-key special-event-map [drag-n-drop] 'haiku-drag-and-drop)
+
+(defvaralias 'haiku-use-system-tooltips 'use-system-tooltips)
+
+(defun haiku-use-system-tooltips-watcher (&rest _ignored)
+ "Variable watcher to force a menu bar update when `use-system-tooltip' changes.
+This is necessary because on Haiku `use-system-tooltip' doesn't
+take effect on menu items until the menu bar is updated again."
+ (force-mode-line-update t))
+
+;; Note that `mouse-position' can't return the actual frame the mouse
+;; pointer is under, so this only works for the frame where the drop
+;; started.
+(defun haiku-dnd-drag-handler ()
+ "Handle mouse movement during drag-and-drop."
+ (let ((track-mouse 'drag-source)
+ (mouse-position (mouse-pixel-position)))
+ (when (car mouse-position)
+ (dnd-handle-movement (posn-at-x-y (cadr mouse-position)
+ (cddr mouse-position)
+ (car mouse-position)))
+ (redisplay))))
+
+(setq haiku-drag-track-function #'haiku-dnd-drag-handler)
+
+(defun x-begin-drag (targets &optional action frame _return-frame
+ allow-current-frame follow-tooltip)
+ "SKIP: real doc in xfns.c."
+ (unless haiku-dnd-selection-value
+ (error "No local value for XdndSelection"))
+ (let ((message nil)
+ (mouse-highlight nil)
+ (haiku-signal-invalid-refs nil))
+ (dolist (target targets)
+ (let* ((target-atom (intern target))
+ (selection-converter (cdr (assoc target-atom
+ haiku-dnd-selection-converters)))
+ (value (if (stringp haiku-dnd-selection-value)
+ (or (get-text-property 0 target-atom
+ haiku-dnd-selection-value)
+ haiku-dnd-selection-value)
+ haiku-dnd-selection-value)))
+ (when selection-converter
+ (let ((selection-result (funcall selection-converter value)))
+ (when selection-result
+ (let* ((field (cdr (assoc (car selection-result) message)))
+ (maybe-string (if (stringp (cadr selection-result))
+ (cadr selection-result)
+ (caadr selection-result))))
+ (unless (cadr field)
+ ;; Add B_MIME_TYPE to the message if the type was not
+ ;; previously specified, or the type if it was.
+ (push (or (get-text-property 0 'type maybe-string)
+ (haiku-numeric-enum MIME))
+ (alist-get (car selection-result) message
+ nil nil #'equal))))
+ (if (not (consp (cadr selection-result)))
+ (push (cadr selection-result)
+ (cdr (alist-get (car selection-result) message
+ nil nil #'equal)))
+ (dolist (tem (cadr selection-result))
+ (push tem
+ (cdr (alist-get (car selection-result) message
+ nil nil #'equal))))))))))
+ (prog1 (or (and (symbolp action)
+ action)
+ 'XdndActionCopy)
+ (haiku-drag-message (or frame (selected-frame))
+ message allow-current-frame
+ follow-tooltip))))
+
+(add-variable-watcher 'use-system-tooltips #'haiku-use-system-tooltips-watcher)
+
+
+;;;; Session management.
+
+(declare-function haiku-save-session-reply "haikufns.c")
+
+(defun emacs-session-save ()
+ "SKIP: real doc in x-win.el."
+ (with-temp-buffer ; Saving sessions is not yet supported.
+ (condition-case nil
+ ;; A return of t means cancel the shutdown.
+ (run-hook-with-args-until-success
+ 'emacs-save-session-functions)
+ (error t))))
+
+(defun handle-save-session (_event)
+ "SKIP: real doc in xsmfns.c."
+ (interactive "e")
+ (let ((cancel-shutdown t))
+ (unwind-protect
+ (setq cancel-shutdown (emacs-session-save))
+ (haiku-save-session-reply (not cancel-shutdown)))
+ ;; The App Server will kill Emacs after receiving the reply, but
+ ;; the Deskbar will not, so kill ourself here.
+ (unless cancel-shutdown (kill-emacs))))
+
+
+;;;; Cursors.
+
+;; We use the same interface as X, but the cursor numbers are
+;; different, and there are also less cursors.
-(define-key special-event-map [drag-n-drop]
- 'haiku-dnd-handle-drag-n-drop-event)
+(defconst x-pointer-X-cursor 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-arrow 1) ; B_CURSOR_ID_SYSTEM_DEFAULT
+(defconst x-pointer-bottom-left-corner 22) ; B_CURSOR_ID_RESIZE_SOUTH_WEST
+(defconst x-pointer-bottom-right-corner 21) ; B_CURSOR_ID_RESIZE_SOUTH_EAST
+(defconst x-pointer-bottom-side 17) ; B_CURSOR_ID_RESIZE_SOUTH
+(defconst x-pointer-clock 14) ; B_CURSOR_ID_PROGRESS
+(defconst x-pointer-cross 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-cross-reverse 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-crosshair 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-diamond-cross 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-hand1 7) ; B_CURSOR_ID_GRAB
+(defconst x-pointer-hand2 8) ; B_CURSOR_ID_GRABBING
+(defconst x-pointer-left-side 18) ; B_CURSOR_ID_RESIZE_WEST
+(defconst x-pointer-right-side 16) ; B_CURSOR_ID_RESIZE_EAST
+(defconst x-pointer-sb-down-arrow 17) ; B_CURSOR_ID_RESIZE_SOUTH
+(defconst x-pointer-sb-left-arrow 18) ; B_CURSOR_ID_RESIZE_WEST
+(defconst x-pointer-sb-right-arrow 16) ; B_CURSOR_ID_RESIZE_EAST
+(defconst x-pointer-sb-up-arrow 16) ; B_CURSOR_ID_RESIZE_NORTH
+(defconst x-pointer-target 5) ; B_CURSOR_ID_CROSS_HAIR
+(defconst x-pointer-top-left-corner 20) ; B_CURSOR_ID_RESIZE_NORTH_WEST
+(defconst x-pointer-top-right-corner 19) ; B_CURSOR_ID_RESIZE_NORTH_EAST
+(defconst x-pointer-top-side 16) ; B_CURSOR_ID_RESIZE_NORTH
+(defconst x-pointer-watch 14) ; B_CURSOR_ID_PROGRESS
+(defconst x-pointer-invisible 12) ; B_CURSOR_ID_NO_CURSOR
(provide 'haiku-win)
(provide 'term/haiku-win)
diff --git a/lisp/term/linux.el b/lisp/term/linux.el
index 6d43e477ac9..ab5a6d8698f 100644
--- a/lisp/term/linux.el
+++ b/lisp/term/linux.el
@@ -17,6 +17,10 @@
(ignore-errors (when gpm-mouse-mode (require 't-mouse) (gpm-mouse-enable)))
+ ;; Don't translate ESC TAB to backtab as directed
+ ;; by ncurses-6.3.
+ (define-key input-decode-map "\e\t" nil)
+
;; Make Latin-1 input characters work, too.
;; Meta will continue to work, because the kernel
;; turns that into Escape.
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index da6c5adee22..e26191b33b4 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -97,8 +97,6 @@ The properties returned may include `top', `left', `height', and `width'."
;;;; Keyboard mapping.
-(define-obsolete-variable-alias 'ns-alternatives-map 'x-alternatives-map "24.1")
-
;; Here are some Nextstep-like bindings for command key sequences.
(define-key global-map [?\s-,] 'customize)
(define-key global-map [?\s-'] 'next-window-any-frame)
@@ -142,7 +140,7 @@ The properties returned may include `top', `left', `height', and `width'."
(define-key global-map [?\s-p] 'ns-print-buffer)
(define-key global-map [?\s-q] 'save-buffers-kill-emacs)
(define-key global-map [?\s-s] 'save-buffer)
-(define-key global-map [?\s-t] 'ns-popup-font-panel)
+(define-key global-map [?\s-t] 'menu-set-font)
(define-key global-map [?\s-u] 'revert-buffer)
(define-key global-map [?\s-v] 'yank)
(define-key global-map [?\s-w] 'delete-frame)
@@ -176,7 +174,6 @@ The properties returned may include `top', `left', `height', and `width'."
(define-key global-map [ns-power-off] 'save-buffers-kill-emacs)
(define-key global-map [ns-open-file] 'ns-find-file)
(define-key global-map [ns-open-temp-file] [ns-open-file])
-(define-key global-map [ns-change-font] 'ns-respond-to-change-font)
(define-key global-map [ns-open-file-line] 'ns-open-file-select-line)
(define-key global-map [ns-spi-service-call] 'ns-spi-service-call)
(define-key global-map [ns-new-frame] 'make-frame)
@@ -508,25 +505,28 @@ unless the current buffer is a scratch buffer."
Switch to a buffer editing the last file dropped, or insert the
string dropped into the current buffer."
(interactive "e")
- (let* ((window (posn-window (event-start event)))
- (arg (car (cdr (cdr event))))
- (type (car arg))
- (operations (car (cdr arg)))
- (objects (cdr (cdr arg)))
- (string (mapconcat 'identity objects "\n")))
- (set-frame-selected-window nil window)
- (raise-frame)
- (setq window (selected-window))
- (cond ((or (memq 'ns-drag-operation-generic operations)
- (memq 'ns-drag-operation-copy operations))
- ;; Perform the default/copy action.
- (dolist (data objects)
- (dnd-handle-one-url window 'private (if (eq type 'file)
- (concat "file:" data)
- data))))
- (t
- ;; Insert the text as is.
- (dnd-insert-text window 'private string)))))
+ (if (eq (car-safe (cdr-safe (cdr-safe event))) 'lambda)
+ (dnd-handle-movement (event-start event))
+ (let* ((window (posn-window (event-start event)))
+ (arg (car (cdr (cdr event))))
+ (type (car arg))
+ (operations (car (cdr arg)))
+ (objects (cdr (cdr arg)))
+ (string (mapconcat 'identity objects "\n")))
+ (set-frame-selected-window nil window)
+ (raise-frame)
+ (setq window (selected-window))
+ (goto-char (posn-point (event-start event)))
+ (cond ((or (memq 'ns-drag-operation-generic operations)
+ (memq 'ns-drag-operation-copy operations))
+ ;; Perform the default/copy action.
+ (dolist (data objects)
+ (dnd-handle-one-url window 'private (if (eq type 'file)
+ (concat "file:" data)
+ data))))
+ (t
+ ;; Insert the text as is.
+ (dnd-insert-text window 'private string))))))
(global-set-key [drag-n-drop] 'ns-drag-n-drop)
@@ -620,34 +620,6 @@ If FRAME is nil, the change applies to the selected frame."
;; Needed for font listing functions under both backend and normal
(setq scalable-fonts-allowed t)
-;; Set to use font panel instead
-(declare-function ns-popup-font-panel "nsfns.m" (&optional frame))
-(defalias 'x-select-font 'ns-popup-font-panel "Pop up the font panel.
-This function has been overloaded in Nextstep.")
-(defalias 'mouse-set-font 'ns-popup-font-panel "Pop up the font panel.
-This function has been overloaded in Nextstep.")
-
-;; nsterm.m
-(defvar ns-input-font)
-(defvar ns-input-fontsize)
-
-(defun ns-respond-to-change-font ()
- "Set the font chosen in the font-picker panel.
-Respond to changeFont: event, expecting ns-input-font and
-ns-input-fontsize of new font."
- (interactive)
- (let ((face 'default))
- (set-face-attribute face t
- :family ns-input-font
- :height (* 10 ns-input-fontsize))
- (set-face-attribute face (selected-frame)
- :family ns-input-font
- :height (* 10 ns-input-fontsize))
- (let ((spec (list (list t (face-attr-construct 'default)))))
- (put face 'customized-face spec)
- (custom-push-theme 'theme-face face 'user 'set spec)
- (put face 'face-modified nil))))
-
;; Default fontset for macOS. This is mainly here to show how a fontset
;; can be set up manually. Ordinarily, fontsets are auto-created whenever
;; a font is chosen by
@@ -708,10 +680,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;;;; Pasteboard support.
-(define-obsolete-function-alias 'ns-store-cut-buffer-internal
- 'gui-set-selection "24.1")
-
-
(defun ns-copy-including-secondary ()
(interactive)
(call-interactively 'kill-ring-save)
@@ -896,12 +864,18 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(declare-function ns-disown-selection-internal "nsselect.m" (selection))
(declare-function ns-selection-owner-p "nsselect.m" (&optional selection))
(declare-function ns-selection-exists-p "nsselect.m" (&optional selection))
+(declare-function ns-begin-drag "nsselect.m")
+
+(defvar ns-dnd-selection-value nil
+ "The value of the special `XdndSelection' selection on NS.")
+
(declare-function ns-get-selection "nsselect.m" (selection-symbol target-type))
-(cl-defmethod gui-backend-set-selection (selection value
- &context (window-system ns))
- (if value (ns-own-selection-internal selection value)
- (ns-disown-selection-internal selection)))
+(cl-defmethod gui-backend-set-selection (selection value &context (window-system ns))
+ (if (eq selection 'XdndSelection)
+ (setq ns-dnd-selection-value value)
+ (if value (ns-own-selection-internal selection value)
+ (ns-disown-selection-internal selection))))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system ns))
@@ -915,6 +889,41 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
&context (window-system ns))
(ns-get-selection selection-symbol target-type))
+(defun x-begin-drag (targets &optional action frame return-frame
+ allow-current-frame follow-tooltip)
+ "SKIP: real doc in xfns.c."
+ (unless ns-dnd-selection-value
+ (error "No local value for XdndSelection"))
+ (let ((pasteboard nil))
+ (when (and (member "STRING" targets)
+ (stringp ns-dnd-selection-value))
+ (push (cons 'string ns-dnd-selection-value) pasteboard))
+ (when (and (member "FILE_NAME" targets)
+ (file-exists-p ns-dnd-selection-value))
+ (let ((value (if (stringp ns-dnd-selection-value)
+ (or (get-text-property 0 'FILE_NAME
+ ns-dnd-selection-value)
+ ns-dnd-selection-value)
+ ns-dnd-selection-value)))
+ (if (vectorp value)
+ (push (cons 'file
+ (cl-loop for file across value
+ collect (expand-file-name file)))
+ pasteboard)
+ (push (cons 'file
+ (url-encode-url (concat "file://"
+ (expand-file-name
+ ns-dnd-selection-value))))
+ pasteboard))))
+ (ns-begin-drag frame pasteboard action return-frame
+ allow-current-frame follow-tooltip)))
+
+(defun ns-handle-drag-motion (frame x y)
+ "Handle mouse movement on FRAME at X and Y during drag-and-drop.
+This moves point to the current mouse position if
+ `dnd-indicate-insertion-point' is enabled."
+ (dnd-handle-movement (posn-at-x-y x y frame)))
+
(provide 'ns-win)
(provide 'term/ns-win)
diff --git a/lisp/term/pc-win.el b/lisp/term/pc-win.el
index 327d51f2759..514267a52d6 100644
--- a/lisp/term/pc-win.el
+++ b/lisp/term/pc-win.el
@@ -246,6 +246,14 @@ Consult the selection. Treat empty strings as if they were unset."
;; if it does not exist, or exists and compares
;; equal with the last text we've put into the
;; Windows clipboard.
+ ;; NOTE: that variable is actually the last text any program
+ ;; (not just Emacs) has put into the windows clipboard (up
+ ;; until the last time Emacs read or set the clipboard), so
+ ;; it's not suitable for checking actual selection
+ ;; ownership. This should not result in a bug for the current
+ ;; uses of gui-backend-selection-owner however, since they
+ ;; don't actually care about selection ownership, but about
+ ;; the selected text having changed.
(cond
((not text) t)
((equal text gui--last-selected-text-clipboard) text)
diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el
index 9bcf3eac646..ee1aad3d0ec 100644
--- a/lisp/term/pgtk-win.el
+++ b/lisp/term/pgtk-win.el
@@ -1,4 +1,4 @@
-;;; xterm.el --- define function key sequences and standard colors for xterm -*- lexical-binding: t -*-
+;;; pgtk-win.el --- parse relevant switches and set up for Pure-GTK -*- lexical-binding: t -*-
;; Copyright (C) 1995, 2001-2020, 2022 Free Software Foundation, Inc.
@@ -23,10 +23,11 @@
;;; Commentary:
;;; Code:
+
(eval-when-compile (require 'cl-lib))
-(or (featurep 'pgtk)
- (error "%s: Loading pgtk-win.el but not compiled for pure Gtk+-3."
- invocation-name))
+(unless (featurep 'pgtk)
+ (error "%s: Loading pgtk-win.el but not compiled with PGTK."
+ invocation-name))
;; Documentation-purposes only: actually loaded in loadup.el.
(require 'term/common-win)
@@ -37,39 +38,14 @@
(require 'menu-bar)
(require 'fontset)
(require 'dnd)
-
-(defgroup pgtk nil
- "Pure-GTK specific features."
- :group 'environment)
-
-;;;; Command line argument handling.
+(require 'pgtk-dnd)
(defvar x-invocation-args)
-;; Set in term/common-win.el; currently unused by Gtk's x-open-connection.
(defvar x-command-line-resources)
-
-;; pgtkterm.c.
(defvar pgtk-input-file)
-
-(declare-function pgtk-use-im-context "pgtkim.c")
(defvar pgtk-use-im-context-on-new-connection)
-(defun pgtk-handle-nxopen (_switch &optional temp)
- (setq unread-command-events (append unread-command-events
- (if temp '(pgtk-open-temp-file)
- '(pgtk-open-file)))
- pgtk-input-file (append pgtk-input-file (list (pop x-invocation-args)))))
-
-(defun pgtk-handle-nxopentemp (switch)
- (pgtk-handle-nxopen switch t))
-
-(defun pgtk-ignore-1-arg (_switch)
- (setq x-invocation-args (cdr x-invocation-args)))
-
-;;;; File handling.
-
-(declare-function pgtk-hide-emacs "pgtkfns.c" (on))
-
+(declare-function pgtk-use-im-context "pgtkim.c")
(defun pgtk-drag-n-drop (event &optional new-frame force-text)
"Edit the files listed in the drag-n-drop EVENT.
@@ -91,7 +67,6 @@ Switch to a buffer editing the last file dropped."
(dnd-insert-text window 'private data)
(dnd-handle-one-url window 'private url-or-string))))
-
(defun pgtk-drag-n-drop-other-frame (event)
"Edit the files listed in the drag-n-drop EVENT, in other frames.
May create new frames, or reuse existing ones. The frame editing
@@ -110,165 +85,48 @@ the last file dropped is selected."
(pgtk-drag-n-drop event t t))
(global-set-key [drag-n-drop] 'pgtk-drag-n-drop)
-(global-set-key [C-drag-n-drop] 'pgtk-drag-n-drop-other-frame)
-(global-set-key [M-drag-n-drop] 'pgtk-drag-n-drop-as-text)
-(global-set-key [C-M-drag-n-drop] 'pgtk-drag-n-drop-as-text-other-frame)
-
-;;;; Frame-related functions.
-
-;; pgtkterm.c
-(defvar pgtk-alternate-modifier)
-(defvar pgtk-right-alternate-modifier)
-(defvar pgtk-right-command-modifier)
-(defvar pgtk-right-control-modifier)
-
-;; You say tomAYto, I say tomAHto..
-(with-no-warnings
- (defvaralias 'pgtk-option-modifier 'pgtk-alternate-modifier)
- (defvaralias 'pgtk-right-option-modifier 'pgtk-right-alternate-modifier))
-
-(defun pgtk-do-hide-emacs ()
- (interactive)
- (pgtk-hide-emacs t))
-
-(declare-function pgtk-hide-others "pgtkfns.c" ())
-
-(defun pgtk-do-hide-others ()
- (interactive)
- (pgtk-hide-others))
-
-(declare-function pgtk-emacs-info-panel "pgtkfns.c" ())
-
-(defun pgtk-do-emacs-info-panel ()
- (interactive)
- (pgtk-emacs-info-panel))
-
-(defun pgtk-next-frame ()
- "Switch to next visible frame."
- (interactive)
- (other-frame 1))
-
-(defun pgtk-prev-frame ()
- "Switch to previous visible frame."
- (interactive)
- (other-frame -1))
-
-;; Frame will be focused anyway, so select it
-;; (if this is not done, mode line is dimmed until first interaction)
-;; FIXME: Sounds like we're working around a bug in the underlying code.
-(add-hook 'after-make-frame-functions 'select-frame)
-
-(defvar tool-bar-mode)
-(declare-function tool-bar-mode "tool-bar" (&optional arg))
-
-;; Based on a function by David Reitter <dreitter@inf.ed.ac.uk> ;
-;; see https://lists.gnu.org/archive/html/emacs-devel/2005-09/msg00681.html .
-(defun pgtk-toggle-toolbar (&optional frame)
- "Switches the tool bar on and off in frame FRAME.
- If FRAME is nil, the change applies to the selected frame."
- (interactive)
- (modify-frame-parameters
- frame (list (cons 'tool-bar-lines
- (if (> (or (frame-parameter frame 'tool-bar-lines) 0) 0)
- 0 1)) ))
- (if (not tool-bar-mode) (tool-bar-mode t)))
-
-
-;;;; Dialog-related functions.
-
-;; Ask user for confirm before printing. Due to Kevin Rodgers.
-(defun pgtk-print-buffer ()
- "Interactive front-end to `print-buffer': asks for user confirmation first."
- (interactive)
- (if (and (called-interactively-p 'interactive)
- (or (listp last-nonmenu-event)
- (and (char-or-string-p (event-basic-type last-command-event))
- (memq 'super (event-modifiers last-command-event)))))
- (let ((last-nonmenu-event (if (listp last-nonmenu-event)
- last-nonmenu-event
- ;; Fake it:
- `(mouse-1 POSITION 1))))
- (if (y-or-n-p (format "Print buffer %s? " (buffer-name)))
- (print-buffer)
- (error "Canceled")))
- (print-buffer)))
-
-;;;; Font support.
-
-;; Needed for font listing functions under both backend and normal
-(setq scalable-fonts-allowed t)
-
-;; Default fontset. This is mainly here to show how a fontset
-;; can be set up manually. Ordinarily, fontsets are auto-created whenever
-;; a font is chosen by
-(defvar pgtk-standard-fontset-spec
- ;; Only some code supports this so far, so use uglier XLFD version
- ;; "-pgtk-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai"
- (mapconcat 'identity
- '("-*-Monospace-*-*-*-*-10-*-*-*-*-*-fontset-standard"
- "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1")
- ",")
- "String of fontset spec of the standard fontset.
-This defines a fontset consisting of the Courier and other fonts.
-See the documentation of `create-fontset-from-fontset-spec' for the format.")
-
-
-;;;; Pasteboard support.
-
-(define-obsolete-function-alias 'pgtk-store-cut-buffer-internal
- 'gui-set-selection "24.1")
-
-
-(defun pgtk-copy-including-secondary ()
- (interactive)
- (call-interactively 'kill-ring-save)
- (gui-set-selection 'SECONDARY (buffer-substring (point) (mark t))))
-
-(defun pgtk-paste-secondary ()
- (interactive)
- (insert (gui-get-selection 'SECONDARY)))
-
(defun pgtk-suspend-error ()
- ;; Don't allow suspending if any of the frames are PGTK frames.
+ "Don't allow suspending if any of the frames are PGTK frames."
(if (memq 'pgtk (mapcar 'window-system (frame-list)))
(error "Cannot suspend Emacs while a PGTK GUI frame exists")))
-
-
(defvar pgtk-initialized nil
"Non-nil if pure-GTK windowing has been initialized.")
(declare-function x-handle-args "common-win" (args))
(declare-function x-open-connection "pgtkfns.c"
(display &optional xrm-string must-succeed))
-(declare-function pgtk-set-resource "pgtkfns.c" (owner name value))
+(declare-function pgtk-set-resource "pgtkfns.c" (attribute value))
-;; Do the actual pure-GTK Windows setup here; the above code just
-;; defines functions and variables that we use now.
+;; Do the actual window system setup here; the above code just defines
+;; functions and variables that we use now.
(cl-defmethod window-system-initialization (&context (window-system pgtk)
&optional display)
- "Initialize Emacs for pure-GTK windowing."
+ "Initialize the PGTK window system.
+WINDOW-SYSTEM is, aptly, `pgtk'.
+DISPLAY is the name of the display Emacs should connect to."
(cl-assert (not pgtk-initialized))
;; PENDING: not needed?
(setq command-line-args (x-handle-args command-line-args))
;; Make sure we have a valid resource name.
- (or (stringp x-resource-name)
+ (when (boundp 'x-resource-name)
+ (unless (stringp x-resource-name)
(let (i)
(setq x-resource-name (copy-sequence invocation-name))
;; Change any . or * characters in x-resource-name to hyphens,
;; so as not to choke when we use it in X resource queries.
(while (setq i (string-match "[.*]" x-resource-name))
- (aset x-resource-name i ?-))))
+ (aset x-resource-name i ?-)))))
;; Setup the default fontset.
(create-default-fontset)
;; Create the standard fontset.
(condition-case err
- (create-fontset-from-fontset-spec pgtk-standard-fontset-spec t)
+ (create-fontset-from-fontset-spec standard-fontset-spec t)
(error (display-warning
'initialization
(format "Creation of the standard fontset failed: %s" err)
@@ -290,6 +148,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;; Any display name is OK.
(add-to-list 'display-format-alist '(".*" . pgtk))
+
(cl-defmethod handle-args-function (args &context (window-system pgtk))
(x-handle-args args))
@@ -297,10 +156,10 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
(x-create-frame-with-faces params))
(declare-function pgtk-own-selection-internal "pgtkselect.c" (selection value &optional frame))
-(declare-function pgtk-disown-selection-internal "pgtkselect.c" (selection &optional time_object terminal))
+(declare-function pgtk-disown-selection-internal "pgtkselect.c" (selection &optional terminal))
(declare-function pgtk-selection-owner-p "pgtkselect.c" (&optional selection terminal))
(declare-function pgtk-selection-exists-p "pgtkselect.c" (&optional selection terminal))
-(declare-function pgtk-get-selection-internal "pgtkselect.c" (selection-symbol target-type &optional time_stamp terminal))
+(declare-function pgtk-get-selection-internal "pgtkselect.c" (selection-symbol target-type &optional terminal))
(cl-defmethod gui-backend-set-selection (selection value
&context (window-system pgtk))
@@ -357,14 +216,12 @@ EVENT is a `preedit-text-event'."
(define-key special-event-map [preedit-text] 'pgtk-preedit-text)
-(add-hook 'after-init-hook
- (function
- (lambda ()
- (when (eq window-system 'pgtk)
- (pgtk-use-im-context pgtk-use-im-context-on-new-connection)))))
-
+(defun pgtk-use-im-context-handler ()
+ "Set up input context usage after Emacs initialization."
+ (when (eq window-system 'pgtk)
+ (pgtk-use-im-context pgtk-use-im-context-on-new-connection)))
-;;;
+(add-hook 'after-init-hook #'pgtk-use-im-context-handler)
(defcustom x-gtk-stock-map
(mapcar (lambda (arg)
@@ -510,6 +367,33 @@ This uses `icon-map-list' to map icon file names to stock icon names."
(t
(popup-menu (mouse-menu-bar-map) last-nonmenu-event))))
+(defun pgtk-device-class (name)
+ "Return the device class of NAME.
+Users should not call this function; see `device-class' instead."
+ (cond
+ ((string-match-p "XTEST" name) 'test)
+ ((string= "Virtual core pointer" name) 'core-pointer)
+ ((string= "Virtual core keyboard" name) 'core-keyboard)
+ (t (let ((number (ignore-errors
+ (string-to-number name))))
+ (when number
+ (cl-case number
+ (0 'mouse)
+ (1 'pen)
+ (2 'eraser)
+ (3 'puck)
+ (4 'keyboard)
+ (5 'touchscreen)
+ (6 'touchpad)
+ (7 'trackpoint)
+ (8 'pad)))))))
+
+(defvaralias 'x-gtk-use-system-tooltips 'use-system-tooltips)
+
+
+(define-key special-event-map [drag-n-drop] #'pgtk-dnd-handle-drag-n-drop-event)
+(add-hook 'after-make-frame-functions #'pgtk-dnd-init-frame)
+
(provide 'pgtk-win)
(provide 'term/pgtk-win)
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 4ed01de9aef..993f1d43208 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -81,7 +81,6 @@
(&optional frame exclude-proportional))
(defvar w32-color-map) ;; defined in w32fns.c
-(make-obsolete 'w32-default-color-map nil "24.1")
(declare-function w32-send-sys-command "w32fns.c")
(declare-function set-message-beep "w32fns.c")
@@ -275,6 +274,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
'(gif "libgif-5.dll" "giflib4.dll" "libungif4.dll" "libungif.dll")))
'(svg "librsvg-2-2.dll")
'(webp "libwebp-7.dll" "libwebp.dll")
+ '(webpdemux "libwebpdemux-2.dll" "libwebpdemux.dll")
'(sqlite3 "libsqlite3-0.dll")
'(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
'(glib "libglib-2.0-0.dll")
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
index 6b5e3964191..3a0bd65f29c 100644
--- a/lisp/term/x-win.el
+++ b/lisp/term/x-win.el
@@ -85,6 +85,8 @@
(defvar x-selection-timeout)
(defvar x-session-id)
(defvar x-session-previous-id)
+(defvar x-dnd-movement-function)
+(defvar x-dnd-unsupported-drop-function)
(defun x-handle-no-bitmap-icon (_switch)
(setq default-frame-alist (cons '(icon-type) default-frame-alist)))
@@ -107,14 +109,6 @@
(setq x-session-previous-id (car x-invocation-args)
x-invocation-args (cdr x-invocation-args)))
-(defvar emacs-save-session-functions nil
- "Special hook run when a save-session event occurs.
-The functions do not get any argument.
-Functions can return non-nil to inform the session manager that the
-window system shutdown should be aborted.
-
-See also `emacs-session-save'.")
-
(defun emacs-session-filename (session-id)
"Construct a filename to save the session in based on SESSION-ID.
Return a filename in `user-emacs-directory', unless the session file
@@ -247,7 +241,9 @@ exists."
(defconst x-pointer-ur-angle 148)
(defconst x-pointer-watch 150)
(defconst x-pointer-xterm 152)
-(defconst x-pointer-invisible 255)
+(defconst x-pointer-invisible 65536) ;; This value is larger than a
+ ;; CARD16, so it cannot be a
+ ;; valid cursor.
;;;; Keysyms
@@ -1175,9 +1171,6 @@ as returned by `x-server-vendor'."
;;;; Selections
-(define-obsolete-function-alias 'x-cut-buffer-or-selection-value
- 'x-selection-value "24.1")
-
;; Arrange for the kill and yank functions to set and check the clipboard.
(defun x-clipboard-yank ()
@@ -1186,8 +1179,12 @@ as returned by `x-server-vendor'."
(interactive "*")
(let ((clipboard-text (gui--selection-value-internal 'CLIPBOARD))
(select-enable-clipboard t))
- (if (and clipboard-text (> (length clipboard-text) 0))
- (kill-new clipboard-text))
+ (when (and clipboard-text (> (length clipboard-text) 0))
+ ;; Avoid asserting ownership of CLIPBOARD, which will cause
+ ;; `gui-selection-value' to return nil in the future.
+ ;; (bug#56273)
+ (let ((select-enable-clipboard nil))
+ (kill-new clipboard-text)))
(yank)))
(declare-function accelerate-menu "xmenu.c" (&optional frame) t)
@@ -1295,14 +1292,6 @@ This returns an error if any Emacs frames are X frames."
(cons (cons 'width (cdr (assq 'width parsed)))
default-frame-alist))))))
- ;; Check the reverseVideo resource.
- (let ((case-fold-search t))
- (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
- (if (and rv
- (string-match "^\\(true\\|yes\\|on\\)$" rv))
- (setq default-frame-alist
- (cons '(reverse . t) default-frame-alist)))))
-
;; Set x-selection-timeout, measured in milliseconds.
(let ((res-selection-timeout (x-get-resource "selectionTimeout"
"SelectionTimeout")))
@@ -1378,7 +1367,8 @@ This returns an error if any Emacs frames are X frames."
(cl-defmethod gui-backend-get-selection (selection-symbol target-type
&context (window-system x)
&optional time-stamp terminal)
- (x-get-selection-internal selection-symbol target-type time-stamp terminal))
+ (x-get-selection-internal selection-symbol target-type
+ time-stamp terminal))
;; Initiate drag and drop
(add-hook 'after-make-frame-functions 'x-dnd-init-frame)
@@ -1489,6 +1479,12 @@ If you don't want stock icons, set the variable to nil."
(string :tag "Stock/named")))))
:group 'x)
+(defcustom x-display-cursor-at-start-of-preedit-string nil
+ "If non-nil, display the cursor at the start of any pre-edit text."
+ :version "29.1"
+ :type 'boolean
+ :group 'x)
+
(defconst x-gtk-stock-cache (make-hash-table :weakness t :test 'equal))
(defun x-gtk-map-stock (file)
@@ -1521,20 +1517,102 @@ 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)
- (setq x-preedit-overlay (make-overlay (point) (point)))
- (overlay-put x-preedit-overlay 'before-string
- (propertize (nth 1 event) 'face '(:underline t)))))
+ (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
+ (propertize string 'cursor t)
+ string)))))
(define-key special-event-map [preedit-text] 'x-preedit-text)
+(defvaralias 'x-gtk-use-system-tooltips 'use-system-tooltips)
+
+(declare-function x-internal-focus-input-context "xfns.c" (focus))
+
+(defun x-gtk-use-native-input-watcher (_symbol newval &rest _ignored)
+ "Variable watcher for `x-gtk-use-native-input'.
+If NEWVAL is non-nil, focus the GTK input context of focused
+frames on all displays."
+ (when (and (featurep 'gtk)
+ (eq (framep (selected-frame)) 'x))
+ (x-internal-focus-input-context newval)))
+
+(add-variable-watcher 'x-gtk-use-native-input
+ #'x-gtk-use-native-input-watcher)
+
+(defun x-dnd-movement (_frame position)
+ "Handle movement to POSITION during drag-and-drop."
+ (dnd-handle-movement position)
+ (redisplay))
+
+(defun x-device-class (name)
+ "Return the device class of NAME.
+Users should not call this function; see `device-class' instead."
+ (let ((downcased-name (downcase name)))
+ (cond
+ ((string-match-p "XTEST" name) 'test)
+ ((string= "Virtual core pointer" name) 'core-pointer)
+ ((string= "Virtual core keyboard" name) 'core-keyboard)
+ ((string-match-p "eraser" downcased-name) 'eraser)
+ ((string-match-p " pad" downcased-name) 'pad)
+ ((or (or (string-match-p "wacom" downcased-name)
+ (string-match-p "pen" downcased-name))
+ (string-match-p "stylus" downcased-name))
+ 'pen)
+ ((or (string-prefix-p "xwayland-touch:" name)
+ (string-match-p "touchscreen" downcased-name))
+ 'touchscreen)
+ ((or (string-match-p "trackpoint" downcased-name)
+ (string-match-p "stick" downcased-name))
+ 'trackpoint)
+ ((or (string-match-p "mouse" downcased-name)
+ (string-match-p "optical" downcased-name)
+ (string-match-p "pointer" downcased-name))
+ 'mouse)
+ ((string-match-p "cursor" downcased-name) 'puck)
+ ((or (string-match-p "keyboard" downcased-name)
+ ;; One of my cheap keyboards is really named this...
+ (string= name "USB USB Keykoard"))
+ 'keyboard)
+ ((string-match-p "button" downcased-name) 'power-button)
+ ((string-match-p "touchpad" downcased-name) 'touchpad)
+ ((or (string-match-p "midi" downcased-name)
+ (string-match-p "piano" downcased-name))
+ 'piano)
+ ((or (string-match-p "wskbd" downcased-name) ; NetBSD/OpenBSD
+ (and (string-match-p "/dev" downcased-name)
+ (string-match-p "kbd" downcased-name)))
+ 'keyboard))))
+
+(setq x-dnd-movement-function #'x-dnd-movement)
+(setq x-dnd-unsupported-drop-function #'x-dnd-handle-unsupported-drop)
+
(provide 'x-win)
(provide 'term/x-win)
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index a7e257f41c5..08e38c9a050 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -66,7 +66,7 @@ If you select a region larger than this size, it won't be copied to your system
clipboard. Since clipboard data is base 64 encoded, the actual number of
string bytes that can be copied is 3/4 of this value."
:version "25.1"
- :type 'integer)
+ :type 'natnum)
(defcustom xterm-set-window-title nil
"Whether Emacs should set window titles to an Emacs frame in an XTerm."
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index e37b0d988ab..2cf9ded04bf 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -46,8 +46,8 @@
;;
;; * Rubber-banding: When drawing lines you can interactively see the
;; result while holding the mouse button down and moving the mouse. If
-;; your machine is not fast enough (a 386 is a bit to slow, but a
-;; pentium is well enough), you can turn this feature off. You will
+;; your machine is not fast enough (a 386 is a bit too slow, but a
+;; Pentium is good enough), you can turn this feature off. You will
;; then see 1's and 2's which mark the 1st and 2nd endpoint of the line
;; you are drawing.
;;
@@ -75,10 +75,10 @@
;; * Flood-filling: You can fill any area with a certain character by
;; flood-filling.
;;
-;; * Cut copy and paste: You can cut, copy and paste rectangular
+;; * Cut, copy and paste: You can cut, copy and paste rectangular
;; regions. Artist also interfaces with the rect package (this can be
;; turned off if it causes you any trouble) so anything you cut in
-;; artist can be yanked with C-x r y and vice versa.
+;; artist can be yanked with `C-x r y' and vice versa.
;;
;; * Drawing with keys: Everything you can do with the mouse, you can
;; also do without the mouse.
@@ -86,7 +86,7 @@
;; * Arrows: After having drawn a (straight) line or a (straight)
;; poly-line, you can set arrows on the line-ends by typing < or >.
;;
-;; * Aspect-ratio: You can set the variable artist-aspect-ratio to
+;; * Aspect-ratio: You can set the user option `artist-aspect-ratio' to
;; reflect the height-width ratio for the font you are using. Squares
;; and circles are then drawn square/round. Note, that once your
;; ascii-file is shown with font with a different height-width ratio,
@@ -95,7 +95,7 @@
;; * Picture mode compatibility: Artist is picture mode compatible (this
;; can be turned off).
;;
-;; See the documentation for the function artist-mode for a detailed
+;; See the documentation for the function `artist-mode' for a detailed
;; description on how to use artist.
;;
;;
@@ -119,8 +119,8 @@
;;; Known bugs:
;; It is not possible to change between shifted and unshifted operation
-;; while drawing with the mouse. (See the comment in the function
-;; artist-shift-has-changed for further details.)
+;; while drawing with the mouse. (See the comment in the function
+;; `artist-shift-has-changed' for further details.)
;;; ChangeLog:
@@ -149,9 +149,9 @@
;;
;; 1.2.1 15-Nov-2000
;; New: Documentation fixes.
-;; Bugfix: Sets next-line-add-newlines to t while in artist-mode.
+;; Bugfix: Set `next-line-add-newlines' to t while in `artist-mode'.
;; Drawing with keys was confusing without this fix, if
-;; next-line-add-newlines was set to nil.
+;; `next-line-add-newlines' was set to nil.
;; Thanks to Tatsuo Furukawa <tatsuo@kobe.hp.com> for this.
;;
;; 1.2 22-Oct-2000
@@ -184,7 +184,6 @@
;; Variables
-(defconst artist-version "1.2.6")
(defconst artist-maintainer-address "tab@lysator.liu.se, bug-gnu-emacs@gnu.org")
(defvar x-pointer-crosshair)
@@ -463,7 +462,7 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.")
(if artist-picture-compatibility
(require 'picture))
-;; Variables that are made local in artist-mode-init
+;; Variables that are made local in `artist-mode-init'
(defvar artist-key-is-drawing nil)
(defvar artist-key-endpoint1 nil)
(defvar artist-key-poly-point-list nil)
@@ -475,60 +474,57 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.")
(defvar artist-arrow-point-1 nil)
(defvar artist-arrow-point-2 nil)
-(defvar artist-mode-map
- (let ((map (make-sparse-keymap)))
- (setq artist-mode-map (make-sparse-keymap))
- (define-key map [down-mouse-1] 'artist-down-mouse-1)
- (define-key map [S-down-mouse-1] 'artist-down-mouse-1)
- (define-key map [down-mouse-2] 'artist-mouse-choose-operation)
- (define-key map [S-down-mouse-2] 'artist-mouse-choose-operation)
- (define-key map [down-mouse-3] 'artist-down-mouse-3)
- (define-key map [S-down-mouse-3] 'artist-down-mouse-3)
- (define-key map [C-mouse-4] 'artist-select-prev-op-in-list)
- (define-key map [C-mouse-5] 'artist-select-next-op-in-list)
- (define-key map "\r" 'artist-key-set-point) ; return
- (define-key map [up] 'artist-previous-line)
- (define-key map "\C-p" 'artist-previous-line)
- (define-key map [down] 'artist-next-line)
- (define-key map "\C-n" 'artist-next-line)
- (define-key map [left] 'artist-backward-char)
- (define-key map "\C-b" 'artist-backward-char)
- (define-key map [right] 'artist-forward-char)
- (define-key map "\C-f" 'artist-forward-char)
- (define-key map "<" 'artist-toggle-first-arrow)
- (define-key map ">" 'artist-toggle-second-arrow)
- (define-key map "\C-c\C-a\C-e" 'artist-select-erase-char)
- (define-key map "\C-c\C-a\C-f" 'artist-select-fill-char)
- (define-key map "\C-c\C-a\C-l" 'artist-select-line-char)
- (define-key map "\C-c\C-a\C-o" 'artist-select-operation)
- (define-key map "\C-c\C-a\C-r" 'artist-toggle-rubber-banding)
- (define-key map "\C-c\C-a\C-t" 'artist-toggle-trim-line-endings)
- (define-key map "\C-c\C-a\C-s" 'artist-toggle-borderless-shapes)
- (define-key map "\C-c\C-c" 'artist-mode-off)
- (define-key map "\C-c\C-al" 'artist-select-op-line)
- (define-key map "\C-c\C-aL" 'artist-select-op-straight-line)
- (define-key map "\C-c\C-ar" 'artist-select-op-rectangle)
- (define-key map "\C-c\C-aR" 'artist-select-op-square)
- (define-key map "\C-c\C-as" 'artist-select-op-square)
- (define-key map "\C-c\C-ap" 'artist-select-op-poly-line)
- (define-key map "\C-c\C-aP" 'artist-select-op-straight-poly-line)
- (define-key map "\C-c\C-ae" 'artist-select-op-ellipse)
- (define-key map "\C-c\C-ac" 'artist-select-op-circle)
- (define-key map "\C-c\C-at" 'artist-select-op-text-see-thru)
- (define-key map "\C-c\C-aT" 'artist-select-op-text-overwrite)
- (define-key map "\C-c\C-aS" 'artist-select-op-spray-can)
- (define-key map "\C-c\C-az" 'artist-select-op-spray-set-size)
- (define-key map "\C-c\C-a\C-d" 'artist-select-op-erase-char)
- (define-key map "\C-c\C-aE" 'artist-select-op-erase-rectangle)
- (define-key map "\C-c\C-av" 'artist-select-op-vaporize-line)
- (define-key map "\C-c\C-aV" 'artist-select-op-vaporize-lines)
- (define-key map "\C-c\C-a\C-k" 'artist-select-op-cut-rectangle)
- (define-key map "\C-c\C-a\M-w" 'artist-select-op-copy-rectangle)
- (define-key map "\C-c\C-a\C-y" 'artist-select-op-paste)
- (define-key map "\C-c\C-af" 'artist-select-op-flood-fill)
- (define-key map "\C-c\C-a\C-b" 'artist-submit-bug-report)
- map)
- "Keymap for `artist-mode'.")
+(defvar-keymap artist-mode-map
+ :doc "Keymap for `artist-mode'."
+ "<down-mouse-1>" #'artist-down-mouse-1
+ "S-<down-mouse-1>" #'artist-down-mouse-1
+ "<down-mouse-2>" #'artist-mouse-choose-operation
+ "S-<down-mouse-2>" #'artist-mouse-choose-operation
+ "<down-mouse-3>" #'artist-down-mouse-3
+ "S-<down-mouse-3>" #'artist-down-mouse-3
+ "C-<mouse-4>" #'artist-select-prev-op-in-list
+ "C-<mouse-5>" #'artist-select-next-op-in-list
+ "RET" #'artist-key-set-point ; return
+ "<up>" #'artist-previous-line
+ "C-p" #'artist-previous-line
+ "<down>" #'artist-next-line
+ "C-n" #'artist-next-line
+ "<left>" #'artist-backward-char
+ "C-b" #'artist-backward-char
+ "<right>" #'artist-forward-char
+ "C-f" #'artist-forward-char
+ "<" #'artist-toggle-first-arrow
+ ">" #'artist-toggle-second-arrow
+ "C-c C-a C-e" #'artist-select-erase-char
+ "C-c C-a C-f" #'artist-select-fill-char
+ "C-c C-a C-l" #'artist-select-line-char
+ "C-c C-a C-o" #'artist-select-operation
+ "C-c C-a C-r" #'artist-toggle-rubber-banding
+ "C-c C-a C-t" #'artist-toggle-trim-line-endings
+ "C-c C-a C-s" #'artist-toggle-borderless-shapes
+ "C-c C-c" #'artist-mode-off
+ "C-c C-a l" #'artist-select-op-line
+ "C-c C-a L" #'artist-select-op-straight-line
+ "C-c C-a r" #'artist-select-op-rectangle
+ "C-c C-a R" #'artist-select-op-square
+ "C-c C-a s" #'artist-select-op-square
+ "C-c C-a p" #'artist-select-op-poly-line
+ "C-c C-a P" #'artist-select-op-straight-poly-line
+ "C-c C-a e" #'artist-select-op-ellipse
+ "C-c C-a c" #'artist-select-op-circle
+ "C-c C-a t" #'artist-select-op-text-see-thru
+ "C-c C-a T" #'artist-select-op-text-overwrite
+ "C-c C-a S" #'artist-select-op-spray-can
+ "C-c C-a z" #'artist-select-op-spray-set-size
+ "C-c C-a C-d" #'artist-select-op-erase-char
+ "C-c C-a E" #'artist-select-op-erase-rectangle
+ "C-c C-a v" #'artist-select-op-vaporize-line
+ "C-c C-a V" #'artist-select-op-vaporize-lines
+ "C-c C-a C-k" #'artist-select-op-cut-rectangle
+ "C-c C-a M-w" #'artist-select-op-copy-rectangle
+ "C-c C-a C-y" #'artist-select-op-paste
+ "C-c C-a f" #'artist-select-op-flood-fill
+ "C-c C-a C-b" #'artist-submit-bug-report)
(easy-menu-define artist-menu-map artist-mode-map
"Menu for `artist-mode'."
@@ -1335,25 +1331,25 @@ Variables
This is a brief overview of the different variables. For more info,
see the documentation for the variables (type \\[describe-variable] <variable> RET).
- artist-rubber-banding Interactively do rubber-banding or not
- artist-first-char What to set at first/second point...
- artist-second-char ...when not rubber-banding
- artist-interface-with-rect If cut/copy/paste should interface with rect
- artist-arrows The arrows to use when drawing arrows
- artist-aspect-ratio Character height-to-width for squares
- artist-trim-line-endings Trimming of line endings
- artist-flood-fill-right-border Right border when flood-filling
- artist-flood-fill-show-incrementally Update display while filling
- artist-pointer-shape Pointer shape to use while drawing
- artist-ellipse-left-char Character to use for narrow ellipses
- artist-ellipse-right-char Character to use for narrow ellipses
- artist-borderless-shapes If shapes should have borders
- artist-picture-compatibility Whether or not to be picture mode compatible
- artist-vaporize-fuzziness Tolerance when recognizing lines
- artist-spray-interval Seconds between repeated sprayings
- artist-spray-radius Size of the spray-area
- artist-spray-chars The spray-\"color\"
- artist-spray-new-chars Initial spray-\"color\"
+ `artist-rubber-banding' Interactively do rubber-banding or not
+ `artist-first-char' What to set at first/second point...
+ `artist-second-char' ...when not rubber-banding
+ `artist-interface-with-rect' Should cut/copy/paste interface with rect
+ `artist-arrows' The arrows to use when drawing arrows
+ `artist-aspect-ratio' Character height-to-width for squares
+ `artist-trim-line-endings' Trimming of line endings
+ `artist-flood-fill-right-border' Right border when flood-filling
+ `artist-flood-fill-show-incrementally' Update display while filling
+ `artist-pointer-shape' Pointer shape to use while drawing
+ `artist-ellipse-left-char' Character to use for narrow ellipses
+ `artist-ellipse-right-char' Character to use for narrow ellipses
+ `artist-borderless-shapes' If shapes should have borders
+ `artist-picture-compatibility' Picture mode compatibility on or off
+ `artist-vaporize-fuzziness' Tolerance when recognizing lines
+ `artist-spray-interval' Seconds between repeated sprayings
+ `artist-spray-radius' Size of the spray-area
+ `artist-spray-chars' The spray-\"color\"
+ `artist-spray-new-char' Initial spray-\"color\"
Hooks
@@ -1371,8 +1367,11 @@ Keymap summary
(t
;; Turn mode on
(artist-mode-init)
- (let ((font (face-attribute 'default :font)))
- (when (and (fontp font) (not (font-get font :spacing)))
+ (let* ((font (face-attribute 'default :font))
+ (spacing-prop (if (fontp font)
+ (font-get font :spacing)
+ t)))
+ (when (or (null spacing-prop) (eq spacing-prop 0))
(message "The default font isn't monospaced, so the drawings in this buffer may look odd"))))))
;; Init and exit
@@ -4916,7 +4915,7 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos))
(timer nil))
@@ -4932,7 +4931,7 @@ The event, EV, is the mouse event."
(while (or (mouse-movement-p ev)
(member 'down (event-modifiers ev)))
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x1 (artist--adjust-x (car ev-start-pos)))
(setq y1 (cdr ev-start-pos))
@@ -5012,7 +5011,7 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t)))
(x1-last (artist--adjust-x (car ev-start-pos)))
(y1-last (cdr ev-start-pos))
(x2 x1-last)
@@ -5104,7 +5103,7 @@ The event, EV, is the mouse event."
;; set x2 and y2
;;
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5131,7 +5130,7 @@ The event, EV, is the mouse event."
;;
;; set x2 and y2
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5215,7 +5214,8 @@ Operation is done once. The event, EV, is the mouse event."
(arrow-pred (artist-go-get-arrow-pred-from-symbol op))
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf
+ (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos)))
(select-window (posn-window ev-start))
@@ -5249,7 +5249,8 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf
+ (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos))
(x2)
@@ -5263,7 +5264,7 @@ The event, EV, is the mouse event."
(while (or (mouse-movement-p ev)
(member 'down (event-modifiers ev)))
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5359,7 +5360,7 @@ The event, EV, is the mouse event."
(setq vars (delq x vars)))) vars)
(reporter-submit-bug-report
artist-maintainer-address
- (concat "artist.el " artist-version)
+ (concat "artist.el in Emacs " emacs-version)
vars
nil nil
(concat "Hello Tomas,\n\n"
@@ -5367,6 +5368,9 @@ The event, EV, is the mouse event."
(define-obsolete-function-alias 'artist-uniq #'seq-uniq "28.1")
+(defconst artist-version "1.2.6")
+(make-obsolete-variable 'artist-version 'emacs-version "29.1")
+
(provide 'artist)
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index ab471db3ddc..6763da046ff 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -316,8 +316,6 @@ If parsing fails, try to set this variable to nil."
(option (choice :tag "Alternative" :value nil
(const nil) integer)))))))
-(define-obsolete-variable-alias 'bibtex-entry-field-alist
- 'bibtex-BibTeX-entry-alist "24.1")
(defcustom bibtex-BibTeX-entry-alist
'(("Article" "Article in Journal"
(("author")
@@ -764,6 +762,20 @@ for a new entry."
("eprint") ("eprintclass" nil nil 4) ("primaryclass" nil nil -4)
("eprinttype" nil nil 5) ("archiveprefix" nil nil -5)
("url") ("urldate")))
+ ("Conference" "Article in Conference Proceedings" ; same as InProceedings
+ (("author")
+ ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)"))
+ (("booktitle" "Name of the conference proceedings")
+ ("year"))
+ (("editor")
+ ("volume" "Volume of the conference proceedings in the series")
+ ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
+ ("series" "Series in which the conference proceedings appeared")
+ ("pages" "Pages in the conference proceedings")
+ ("month") ("address")
+ ("organization" "Sponsoring organization of the conference")
+ ("publisher" "Publishing company, its location")
+ ("note")))
("Reference" "Single-Volume Work of Reference" ; same as @collection
(("editor") ("title") ("date" nil nil 1) ("year" nil nil -1))
nil
@@ -848,6 +860,15 @@ for a new entry."
(("type" "Type of the PhD thesis")
("address" "Address of the school (if not part of field \"school\") or country")
("month") ("note")))
+ ("MastersThesis" "Master's Thesis"
+ (("author")
+ ("title" "Title of the master's thesis (BibTeX converts it to lowercase)")
+ ("school" "School where the master's thesis was written")
+ ("year"))
+ nil
+ (("type" "Type of the master's thesis (if other than \"Master's thesis\")")
+ ("address" "Address of the school (if not part of field \"school\") or country")
+ ("month") ("note")))
("TechReport" "Technical Report"
(("author")
("title" "Title of the technical report (BibTeX converts it to lowercase)")
@@ -2275,11 +2296,17 @@ is non-nil, FUN is not called for @String entries."
(set-marker-insertion-type end-marker t)
(save-excursion
(goto-char (point-min))
- (while (setq found (bibtex-skip-to-valid-entry))
- (set-marker end-marker (cdr found))
- (looking-at bibtex-any-entry-maybe-empty-head)
- (funcall fun (bibtex-key-in-head "") (car found) end-marker)
- (goto-char end-marker)))))
+ (let ((prev nil))
+ (while (setq found (bibtex-skip-to-valid-entry))
+ ;; If we have invalid entries, ensure that we have forward
+ ;; progress so that we don't infloop.
+ (if (equal (point) prev)
+ (forward-line 1)
+ (setq prev (point))
+ (set-marker end-marker (cdr found))
+ (looking-at bibtex-any-entry-maybe-empty-head)
+ (funcall fun (bibtex-key-in-head "") (car found) end-marker)
+ (goto-char end-marker)))))))
(defun bibtex-progress-message (&optional flag interval)
"Echo a message about progress of current buffer.
@@ -3644,14 +3671,6 @@ if that value is non-nil.
(if (not (consp (nth 1 (car entry-alist))))
;; new format
entry-alist
- ;; Convert old format of `bibtex-entry-field-alist'
- (unless (get var 'entry-list-format)
- (put var 'entry-list-format "pre-24")
- (message "Old format of `%s' (pre GNU Emacs 24).
-Please convert to the new format."
- (if (eq (indirect-variable 'bibtex-entry-field-alist) var)
- 'bibtex-entry-field-alist var))
- (sit-for 3))
(let (lst)
(dolist (entry entry-alist)
(let ((fl (nth 1 entry)) req xref opt)
@@ -4119,11 +4138,11 @@ Optional arg POS is the position of the BibTeX entry to use."
(goto-char pnt)))))
(defun bibtex-mark-entry ()
- "Put mark at beginning, point at end of current BibTeX entry.
+ "Put mark at end, point at beginning of current BibTeX entry.
Activate mark in Transient Mark mode."
(interactive)
- (push-mark (bibtex-beginning-of-entry) t t)
- (bibtex-end-of-entry))
+ (push-mark (bibtex-end-of-entry) t t)
+ (bibtex-beginning-of-entry))
(defun bibtex-count-entries (&optional count-string-entries)
"Count number of entries in current buffer or region.
@@ -5010,7 +5029,7 @@ on the value of `bibtex-entry-format'.
If the reference key of the entry is empty or a prefix argument is given,
calculate a new reference key. (Note: this works only if fields in entry
begin on separate lines prior to calling `bibtex-clean-entry' or if
-'realign is contained in `bibtex-entry-format'.)
+`realign' is contained in `bibtex-entry-format'.)
Don't call `bibtex-clean-entry' on @Preamble entries.
At end of the cleaning process, the functions in
`bibtex-clean-entry-hook' are called with region narrowed to entry."
@@ -5289,7 +5308,6 @@ entries from minibuffer."
(goto-char (point-max))
(message "Buffer is now parsable. Please save it.")))
-(define-obsolete-function-alias 'bibtex-complete #'completion-at-point "24.1")
(defun bibtex-completion-at-point-function ()
(let ((pnt (point))
(case-fold-search t)
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 1139fd1976e..a2a7774aba7 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -269,6 +269,10 @@
("resize" "none" "both" "horizontal" "vertical")
("text-overflow" "clip" "ellipsis" string)
+ ;; CSS Cascading and Inheritance Level 3
+ ;; (https://www.w3.org/TR/css-cascade-3/#property-index)
+ ("all")
+
;; CSS Color Module Level 3
;; (https://www.w3.org/TR/css3-color/#property)
("color" color)
@@ -304,27 +308,27 @@
;; CSS Box Alignment Module Level 3
;; (https://www.w3.org/TR/css-align-3/#property-index)
- ("align-content"
- baseline-position content-distribution overflow-position content-position)
- ("align-items"
- "normal" "stretch" baseline-position overflow-position self-position)
- ("align-self"
- "auto" "normal" "stretch"
- baseline-position overflow-position self-position)
- ("justify-content" "normal"
- content-distribution overflow-position content-position "left" "right")
- ("justify-items"
- "normal" "stretch" baseline-position overflow-position self-position
- "left" "right" "legacy")
- ("justify-self"
- "auto" "normal" "stretch" baseline-position overflow-position self-position
- "left" "right")
+ ("align-content" baseline-position content-distribution
+ overflow-position content-position)
+ ("align-items" "normal" "stretch" baseline-position
+ overflow-position self-position)
+ ("align-self" "auto" "normal" "stretch" baseline-position
+ overflow-position self-position)
+ ("column-gap" "normal" length-percentage)
+ ("gap" row-gap column-gap)
+ ("justify-content" "normal" content-distribution overflow-position
+ content-position "left" "right")
+ ("justify-items" "normal" "stretch" baseline-position
+ overflow-position self-position "left" "right" "legacy" "center")
+ ("justify-self" "auto" "normal" "stretch" baseline-position
+ overflow-position self-position "left" "right")
("place-content" align-content justify-content)
("place-items" align-items justify-items)
("place-self" justify-self align-self)
+ ("row-gap" "normal" length-percentage)
- ;; CSS Flexible Box Layout Module Level 2
- ;; (https://www.w3.org/TR/css-flexbox-2/#property-index)
+ ;; CSS Flexible Box Layout Module Level 1
+ ;; (https://www.w3.org/TR/css-flexbox-1/#property-index)
("flex" "none" flex-grow flex-shrink flex-basis)
("flex-basis" "auto" "content" width)
("flex-direction" "row" "row-reverse" "column" "column-reverse")
@@ -413,21 +417,20 @@
("mask-type" "luminance" "alpha")
("clip" "rect()" "auto")
- ;; CSS Multi-column Layout Module
+ ;; CSS Multi-column Layout Module Level 1
;; (https://www.w3.org/TR/css3-multicol/#property-index)
;; "break-after", "break-before", and "break-inside" are left out
;; below, because they're already included in CSS Fragmentation
;; Module Level 3.
- ("column-count" integer "auto")
- ("column-fill" "auto" "balance")
- ("column-gap" length "normal")
+ ("column-count" "auto" integer)
+ ("column-fill" "auto" "balance" "balance-all")
("column-rule" column-rule-width column-rule-style
- column-rule-color "transparent")
+ column-rule-color)
("column-rule-color" color)
- ("column-rule-style" border-style)
- ("column-rule-width" border-width)
+ ("column-rule-style" line-style)
+ ("column-rule-width" line-width)
("column-span" "none" "all")
- ("column-width" length "auto")
+ ("column-width" "auto" length)
("columns" column-width column-count)
;; CSS Overflow Module Level 3
@@ -925,6 +928,32 @@ cannot be completed sensibly: `custom-ident',
(defface css-proprietary-property '((t :inherit (css-property italic)))
"Face to use for vendor-specific properties.")
+(defun css--selector-regexp (sassy)
+ (concat
+ "\\(?:"
+ (if (not sassy)
+ "[-_%*#.>[:alnum:]]+"
+ ;; Same as for non-sassy except we do want to allow { and }
+ ;; chars in selectors in the case of #{$foo}
+ ;; variable interpolation!
+ (concat "\\(?:[-_%*#.>&+~[:alnum:]]*" scss--hash-re
+ "\\|[-_%*#.>&+~[:alnum:]]+\\)"))
+ ;; Even though pseudo-elements should be prefixed by ::, a
+ ;; single colon is accepted for backward compatibility.
+ "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
+ css-pseudo-element-ids)
+ t)
+ "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)\\)?"
+ ;; Braces after selectors.
+ "\\(?:\\[[^]\n]+\\]\\)?"
+ ;; Parentheses after selectors.
+ "\\(?:([^)]+)\\)?"
+ ;; Main bit over. But perhaps just [target]?
+ "\\|\\[[^]\n]+\\]"
+ ;; :root, ::marker and the like.
+ "\\|::?[[:alnum:]]+\\(?:([^)]+)\\)?"
+ "\\)"))
+
(defun css--font-lock-keywords (&optional sassy)
`((,(concat "!\\s-*" (regexp-opt css--bang-ids))
(0 font-lock-builtin-face))
@@ -945,28 +974,16 @@ cannot be completed sensibly: `custom-ident',
;; selector between [...] should simply not be highlighted.
(,(concat
"^[ \t]*\\("
- (if (not sassy)
- ;; We don't allow / as first char, so as not to
- ;; take a comment as the beginning of a selector.
- "[^@/:{}() \t\n][^:{}()]*"
- ;; Same as for non-sassy except we do want to allow { and }
- ;; chars in selectors in the case of #{$foo}
- ;; variable interpolation!
- (concat "\\(?:" scss--hash-re
- "\\|[^@/:{}() \t\n#]\\)"
- "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*"))
- ;; Even though pseudo-elements should be prefixed by ::, a
- ;; single colon is accepted for backward compatibility.
- "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
- css-pseudo-element-ids)
- t)
- "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)"
- "\\(?:([^)]+)\\)?"
- (if (not sassy)
- "[^:{}()\n]*"
- (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*"))
+ ;; We have at least one selector.
+ (css--selector-regexp sassy)
+ ;; And then possibly more.
+ "\\(?:"
+ ;; Separators between selectors.
+ "[ \n\t,+~>]+"
+ (css--selector-regexp sassy)
"\\)*"
- "\\)\\(?:\n[ \t]*\\)*{")
+ ;; And then a brace.
+ "\\)[ \n\t]*{")
(1 'css-selector keep))
;; In the above rule, we allow the open-brace to be on some subsequent
;; line. This will only work if we properly mark the intervening text
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index dc26a3c1b7f..42d547504c1 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -110,11 +110,11 @@
"26.1" 'set)
(defcustom dns-mode-font-lock-keywords
- `((,(concat "^\\$" (regexp-opt dns-mode-control-entities))
+ `((,(concat "^\\$" (regexp-opt dns-mode-control-entities) "\\>")
0 ,dns-mode-control-entity-face)
("^\\$[a-z0-9A-Z]+" 0 ,dns-mode-bad-control-entity-face)
- (,(regexp-opt dns-mode-classes) 0 ,dns-mode-class-face)
- (,(regexp-opt dns-mode-types) 0 ,dns-mode-type-face))
+ (,(regexp-opt dns-mode-classes 'words) 0 ,dns-mode-class-face)
+ (,(regexp-opt dns-mode-types 'words) 0 ,dns-mode-type-face))
"Font lock keywords used to highlight text in DNS master file mode."
:version "26.1"
:type 'sexp)
@@ -165,7 +165,7 @@ manually with \\[dns-mode-soa-increment-serial]."
;;;###autoload
(define-derived-mode dns-mode text-mode "DNS"
"Major mode for viewing and editing DNS master files.
-This mode is inherited from text mode. It add syntax
+This mode is derived from text mode. It adds syntax
highlighting, and some commands for handling DNS master files.
Its keymap inherits from `text-mode' and it has the same
variables for customizing indentation. It has its own abbrev
diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el
new file mode 100644
index 00000000000..af0aa2ddeab
--- /dev/null
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -0,0 +1,269 @@
+;;; emacs-news-mode.el --- major mode to edit and view the NEWS file -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Keywords: tools
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'outline)
+
+(defgroup emacs-news-mode nil
+ "Major mode for editing and viewing the Emacs NEWS file."
+ :group 'lisp)
+
+(defface emacs-news-is-documented
+ '((t :inherit font-lock-type-face))
+ "Face used for displaying the \"is documented\" tag."
+ :version "29.1")
+
+(defface emacs-news-does-not-need-documentation
+ '((t :inherit font-lock-preprocessor-face))
+ "Face used for displaying the \"does not need documentation\" tag."
+ :version "29.1")
+
+(defvar-keymap emacs-news-common-map
+ ;; Navigation like `org-mode'/`outline-minor-mode'.
+ "C-c C-f" #'outline-forward-same-level
+ "C-c C-b" #'outline-backward-same-level
+ "C-c C-n" #'outline-next-visible-heading
+ "C-c C-p" #'outline-previous-visible-heading
+ "C-c C-u" #'outline-up-heading)
+
+(defvar-keymap emacs-news-mode-map
+ :parent emacs-news-common-map
+ "C-c C-s" #'emacs-news-next-untagged-entry
+ "C-c C-r" #'emacs-news-previous-untagged-entry
+ "C-c C-t" #'emacs-news-toggle-tag
+ "C-c C-g" #'emacs-news-goto-section
+ "C-c C-j" #'emacs-news-find-heading
+ "C-c C-e" #'emacs-news-count-untagged-entries
+ "<remap> <open-line>" #'emacs-news-open-line)
+
+(defvar-keymap emacs-news-view-mode-map
+ :parent emacs-news-common-map)
+
+(defvar emacs-news-mode-font-lock-keywords
+ `(("^---$" 0 'emacs-news-does-not-need-documentation)
+ ("^\\+\\+\\+$" 0 'emacs-news-is-documented)))
+
+(defun emacs-news--mode-common ()
+ (setq-local font-lock-defaults '(emacs-news-mode-font-lock-keywords t))
+ (setq-local outline-regexp "\\*+ "
+ outline-minor-mode-cycle t
+ ;; We subtract one from the level, because we have a
+ ;; space after the asterisks.
+ outline-level (lambda () (1- (length (match-string 0))))
+ outline-minor-mode-highlight 'append)
+ (outline-minor-mode))
+
+;;;###autoload
+(define-derived-mode emacs-news-mode text-mode "NEWS"
+ "Major mode for editing the Emacs NEWS file."
+ (setq-local fill-paragraph-function #'emacs-news--fill-paragraph)
+ (emacs-news--mode-common))
+
+;;;###autoload
+(define-derived-mode emacs-news-view-mode special-mode "NEWS"
+ "Major mode for viewing the Emacs NEWS file."
+ (setq buffer-read-only t)
+ (emacs-news--buttonize)
+ (button-mode)
+ (emacs-news--mode-common))
+
+(defun emacs-news--fill-paragraph (&optional justify)
+ (cond
+ ;; We're in a heading -- do nothing.
+ ((save-excursion
+ (beginning-of-line)
+ (looking-at "\\*+ "))
+ )
+ ;; We're in a news item -- exclude the heading before filling.
+ ((and (save-excursion
+ (re-search-backward (concat "^\\(?:" paragraph-start "\\|\\*+ \\)")
+ nil t))
+ (= (char-after (match-beginning 0)) ?*))
+ (save-restriction
+ (narrow-to-region (save-excursion
+ (goto-char (match-beginning 0))
+ (forward-line 1)
+ (point))
+ (point-max))
+ (fill-paragraph justify)))
+ ;; Fill normally.
+ (t
+ (fill-paragraph justify))))
+
+(defun emacs-news-next-untagged-entry (&optional reverse)
+ "Go to the next untagged NEWS entry.
+If REVERSE (interactively, the prefix), go to the previous
+untagged NEWS entry."
+ (interactive "P" emacs-news-mode)
+ (let ((start (point))
+ (found nil))
+ ;; Don't consider the current line, because that would stop
+ ;; progress if calling this command repeatedly.
+ (unless reverse
+ (forward-line 1))
+ (while (and (not found)
+ (funcall (if reverse #'re-search-backward
+ #'re-search-forward)
+ "^\\(\\*+\\) " nil t))
+ (when (and (not (save-excursion
+ (forward-line -1)
+ (looking-at "---$\\|\\+\\+\\+$")))
+ ;; We have an entry without a tag before it, but
+ ;; check whether it's a heading (which we can
+ ;; determine if the next entry has more asterisks).
+ (not (emacs-news--heading-p)))
+ ;; It wasn't a sub-heading, so we've found one.
+ (setq found t)))
+ (if found
+ (progn
+ (push-mark start)
+ (message "Untagged entry")
+ (beginning-of-line)
+ t)
+ (message "No further untagged entries")
+ (goto-char start)
+ nil)))
+
+(defun emacs-news--heading-p ()
+ (save-excursion
+ (beginning-of-line)
+ ;; A heading starts with * characters, and then a blank line, and
+ ;; then paragraphs with more * characters than in the heading.
+ (and (looking-at "\\(\\*+\\) ")
+ (let ((level (length (match-string 1))))
+ (forward-line 1)
+ (and (looking-at "$")
+ (re-search-forward "^\\(\\*+\\) " nil t)
+ (> (length (match-string 1)) level))))))
+
+(defun emacs-news-previous-untagged-entry ()
+ "Go to the previous untagged NEWS entry."
+ (interactive nil emacs-news-mode)
+ (emacs-news-next-untagged-entry t))
+
+(defun emacs-news-toggle-tag ()
+ "Toggle documentation tag of current headline in the Emacs NEWS file."
+ (interactive nil emacs-news-mode)
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (cond ((or (looking-at (rx bol (or "---" "+++") eol)))
+ (forward-line 2))
+ ((or (looking-at (rx bol "*** ")))
+ (forward-line 1)))
+ (outline-previous-visible-heading 1)
+ (forward-line -1)
+ (cond ((not (looking-at (rx bol (or "---" "+++") eol)))
+ (insert "\n---"))
+ ((looking-at (rx bol "---" eol))
+ (delete-char 3)
+ (insert "+++"))
+ ((looking-at (rx bol "+++" eol))
+ (delete-char 4))
+ (t (user-error "Invalid headline tag; can't toggle")))))
+
+(defun emacs-news-count-untagged-entries ()
+ "Say how many untagged entries there are in the current NEWS buffer."
+ (interactive nil emacs-news-mode)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((i 0))
+ (while (emacs-news-next-untagged-entry)
+ (setq i (1+ i)))
+ (message (if (= i 1)
+ "There's 1 untagged entry"
+ (format "There are %s untagged entries" i))))))
+
+(defun emacs-news--buttonize ()
+ "Make manual and symbol references into buttons."
+ (save-excursion
+ (with-silent-modifications
+ (let ((inhibit-read-only t))
+ ;; Do functions and variables.
+ (goto-char (point-min))
+ (search-forward "\f" nil t)
+ (while (re-search-forward "'\\([^-][^ \t\n]+\\)'" nil t)
+ ;; Filter out references to key sequences.
+ (let ((string (match-string 1)))
+ (when-let ((symbol (intern-soft string)))
+ (when (or (boundp symbol)
+ (fboundp symbol))
+ (buttonize-region (match-beginning 1) (match-end 1)
+ (lambda (symbol)
+ (describe-symbol symbol))
+ symbol)))))
+ ;; Do manual references.
+ (goto-char (point-min))
+ (search-forward "\f" nil t)
+ (while (re-search-forward "\"\\(([a-z0-9]+)[ \n][^\"]\\{1,80\\}\\)\""
+ nil t)
+ (buttonize-region (match-beginning 1) (match-end 1)
+ (lambda (node) (info node))
+ (match-string 1)))))))
+
+(defun emacs-news--sections (regexp)
+ (let ((sections nil))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward (concat "^" regexp "\\(.*\\)") nil t)
+ (when (save-match-data (emacs-news--heading-p))
+ (push (buffer-substring-no-properties
+ (match-beginning 1) (match-end 1))
+ sections))))
+ (nreverse sections)))
+
+(defun emacs-news-goto-section (section)
+ "Go to SECTION in the Emacs NEWS file."
+ (interactive (list
+ (completing-read "Goto section: " (emacs-news--sections "\\* ")
+ nil t))
+ emacs-news-mode)
+ (goto-char (point-min))
+ (when (search-forward (concat "\n* " section) nil t)
+ (beginning-of-line)))
+
+(defun emacs-news-find-heading (heading)
+ "Go to HEADING in the Emacs NEWS file."
+ (interactive (list
+ (completing-read "Goto heading: "
+ (emacs-news--sections "\\*\\*\\*? ")
+ nil t))
+ emacs-news-mode)
+ (goto-char (point-min))
+ (when (re-search-forward (concat "^*+ " (regexp-quote heading)) nil t)
+ (beginning-of-line)))
+
+(defun emacs-news-open-line (n)
+ "Open a new line in a NEWS file.
+This is like `open-line', but skips any temporary NEWS-style
+documentation marks on the previous line."
+ (interactive "*p" emacs-news-mode)
+ (when (save-excursion (forward-line -1)
+ (looking-at (rx bol (or "---" "+++") eol)))
+ (forward-line -1))
+ (open-line n))
+
+(provide 'emacs-news-mode)
+
+;;; emacs-news-mode.el ends here
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index 50ff668a9ff..935be06812f 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -539,6 +539,30 @@ the range of text to assign text property SYMBOL with value VALUE."
(list start end 'display prop)
(list start end 'display (list 'disable-eval prop)))))
+(defvar enriched--markup-shown)
+(defun enriched-toggle-markup ()
+ "Toggle whether to see markup in the current buffer."
+ (interactive)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (with-silent-modifications
+ (if (bound-and-true-p enriched--markup-shown)
+ (progn
+ (setq-local enriched--markup-shown nil)
+ ;; Remove any faces, because they will be decoded, too.
+ (goto-char (point-min))
+ (let (match)
+ (while (setq match (text-property-search-forward 'face))
+ (put-text-property (prop-match-beginning match)
+ (prop-match-end match)
+ 'face nil)))
+ (enriched-decode (point-min) (point-max))
+ (enriched-mode 1))
+ (setq-local enriched--markup-shown t)
+ (enriched-encode (point-min) (point-max) (current-buffer))
+ (enriched-mode -1))))))
+
(provide 'enriched)
;;; enriched.el ends here
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index f41fd186e73..23ba1a24f1f 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -29,6 +29,8 @@
;;; Code:
+(eval-when-compile (require 'subr-x))
+
(defgroup fill nil
"Indenting and filling text."
:link '(custom-manual "(emacs)Filling")
@@ -44,8 +46,8 @@ A value of nil means that any change in indentation starts a new paragraph."
(defcustom colon-double-space nil
"Non-nil means put two spaces after a colon when filling."
- :type 'boolean)
-(put 'colon-double-space 'safe-local-variable #'booleanp)
+ :type 'boolean
+ :safe #'booleanp)
(defcustom fill-separate-heterogeneous-words-with-space nil
"Non-nil means to use a space to separate words of a different kind.
@@ -644,20 +646,27 @@ The break position will be always after LINEBEG and generally before point."
(defun fill-region-as-paragraph (from to &optional justify
nosqueeze squeeze-after)
- "Fill the region as one paragraph.
-It removes any paragraph breaks in the region and extra newlines at the end,
-indents and fills lines between the margins given by the
-`current-left-margin' and `current-fill-column' functions.
-\(In most cases, the variable `fill-column' controls the width.)
-It leaves point at the beginning of the line following the paragraph.
-
-Normally performs justification according to the `current-justification'
-function, but with a prefix arg, does full justification instead.
-
-From a program, optional third arg JUSTIFY can specify any type of
-justification. Fourth arg NOSQUEEZE non-nil means not to make spaces
-between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil,
-means don't canonicalize spaces before that position.
+ "Fill the region as if it were a single paragraph.
+This command removes any paragraph breaks in the region and
+extra newlines at the end, and indents and fills lines between the
+margins given by the `current-left-margin' and `current-fill-column'
+functions. (In most cases, the variable `fill-column' controls the
+width.) It leaves point at the beginning of the line following the
+region.
+
+Normally, the command performs justification according to
+the `current-justification' function, but with a prefix arg, it
+does full justification instead.
+
+When called from Lisp, optional third arg JUSTIFY can specify any
+type of justification; see `default-justification' for the possible
+values.
+Optional fourth arg NOSQUEEZE non-nil means not to make spaces
+between words canonical before filling.
+Fifth arg SQUEEZE-AFTER, if non-nil, should be a buffer position; it
+means canonicalize spaces only starting from that position.
+See `canonically-space-region' for the meaning of canonicalization
+of spaces.
Return the `fill-prefix' used for filling.
@@ -713,8 +722,7 @@ space does not end a sentence, so don't break a line there."
(or justify (setq justify (current-justification)))
;; Don't let Adaptive Fill mode alter the fill prefix permanently.
- (let ((actual-fill-prefix fill-prefix)
- (fill-prefix fill-prefix))
+ (let ((fill-prefix fill-prefix))
;; Figure out how this paragraph is indented, if desired.
(when (and adaptive-fill-mode
(or (null fill-prefix) (string= fill-prefix "")))
@@ -754,18 +762,9 @@ space does not end a sentence, so don't break a line there."
;; This is the actual filling loop.
(goto-char from)
- (let ((first t)
- linebeg)
- (while (< (point) to)
- ;; On the first line, there may be text in the fill prefix
- ;; zone (when `fill-prefix' is specified externally, and
- ;; not computed). In that case, don't consider that area
- ;; when trying to find a place to put a line break
- ;; (bug#45720).
- (if (not first)
- (setq linebeg (point))
- (setq first nil
- linebeg (+ (point) (length actual-fill-prefix))))
+ (let (linebeg)
+ (while (< (point) to)
+ (setq linebeg (point))
(move-to-column (current-fill-column))
(if (when (and (< (point) to) (< linebeg to))
;; Find the position where we'll break the line.
@@ -842,75 +841,67 @@ region, instead of just filling the current paragraph."
(interactive (progn
(barf-if-buffer-read-only)
(list (if current-prefix-arg 'full) t)))
- (let ((hash (and (not (buffer-modified-p))
- (buffer-hash))))
- (prog1
- (or
- ;; 1. Fill the region if it is active when called interactively.
- (and region transient-mark-mode mark-active
- (not (eq (region-beginning) (region-end)))
- (or (fill-region (region-beginning) (region-end) justify) t))
- ;; 2. Try fill-paragraph-function.
- (and (not (eq fill-paragraph-function t))
- (or fill-paragraph-function
- (and (minibufferp (current-buffer))
- (= 1 (point-min))))
- (let ((function (or fill-paragraph-function
- ;; In the minibuffer, don't count
- ;; the width of the prompt.
- 'fill-minibuffer-function))
- ;; If fill-paragraph-function is set, it probably
- ;; takes care of comments and stuff. If not, it
- ;; will have to set fill-paragraph-handle-comment
- ;; back to t explicitly or return nil.
- (fill-paragraph-handle-comment nil)
- (fill-paragraph-function t))
- (funcall function justify)))
- ;; 3. Try our syntax-aware filling code.
- (and fill-paragraph-handle-comment
- ;; Our code only handles \n-terminated comments right now.
- comment-start (equal comment-end "")
- (let ((fill-paragraph-handle-comment nil))
- (fill-comment-paragraph justify)))
- ;; 4. If it all fails, default to the good ol' text paragraph filling.
- (let ((before (point))
- (paragraph-start paragraph-start)
- ;; Fill prefix used for filling the paragraph.
- fill-pfx)
- ;; Try to prevent code sections and comment sections from being
- ;; filled together.
- (when (and fill-paragraph-handle-comment comment-start-skip)
- (setq paragraph-start
- (concat paragraph-start "\\|[ \t]*\\(?:"
- comment-start-skip "\\)")))
- (save-excursion
- ;; To make sure the return value of forward-paragraph is
- ;; meaningful, we have to start from the beginning of
- ;; line, otherwise skipping past the last few chars of a
- ;; paragraph-separator would count as a paragraph (and
- ;; not skipping any chars at EOB would not count as a
- ;; paragraph even if it is).
- (move-to-left-margin)
- (if (not (zerop (fill-forward-paragraph 1)))
- ;; There's no paragraph at or after point: give up.
- (setq fill-pfx "")
- (let ((end (point))
- (beg (progn (fill-forward-paragraph -1) (point))))
- (goto-char before)
- (setq fill-pfx
- (if use-hard-newlines
- ;; Can't use fill-region-as-paragraph, since this
- ;; paragraph may still contain hard newlines. See
- ;; fill-region.
- (fill-region beg end justify)
- (fill-region-as-paragraph beg end justify))))))
- fill-pfx))
- ;; If we didn't change anything in the buffer (and the buffer
- ;; was previously unmodified), then flip the modification status
- ;; back to "unchanged".
- (when (and hash
- (equal hash (buffer-hash)))
- (set-buffer-modified-p nil)))))
+ (with-buffer-unmodified-if-unchanged
+ (or
+ ;; 1. Fill the region if it is active when called interactively.
+ (and region transient-mark-mode mark-active
+ (not (eq (region-beginning) (region-end)))
+ (or (fill-region (region-beginning) (region-end) justify) t))
+ ;; 2. Try fill-paragraph-function.
+ (and (not (eq fill-paragraph-function t))
+ (or fill-paragraph-function
+ (and (minibufferp (current-buffer))
+ (= 1 (point-min))))
+ (let ((function (or fill-paragraph-function
+ ;; In the minibuffer, don't count
+ ;; the width of the prompt.
+ 'fill-minibuffer-function))
+ ;; If fill-paragraph-function is set, it probably
+ ;; takes care of comments and stuff. If not, it
+ ;; will have to set fill-paragraph-handle-comment
+ ;; back to t explicitly or return nil.
+ (fill-paragraph-handle-comment nil)
+ (fill-paragraph-function t))
+ (funcall function justify)))
+ ;; 3. Try our syntax-aware filling code.
+ (and fill-paragraph-handle-comment
+ ;; Our code only handles \n-terminated comments right now.
+ comment-start (equal comment-end "")
+ (let ((fill-paragraph-handle-comment nil))
+ (fill-comment-paragraph justify)))
+ ;; 4. If it all fails, default to the good ol' text paragraph filling.
+ (let ((before (point))
+ (paragraph-start paragraph-start)
+ ;; Fill prefix used for filling the paragraph.
+ fill-pfx)
+ ;; Try to prevent code sections and comment sections from being
+ ;; filled together.
+ (when (and fill-paragraph-handle-comment comment-start-skip)
+ (setq paragraph-start
+ (concat paragraph-start "\\|[ \t]*\\(?:"
+ comment-start-skip "\\)")))
+ (save-excursion
+ ;; To make sure the return value of forward-paragraph is
+ ;; meaningful, we have to start from the beginning of
+ ;; line, otherwise skipping past the last few chars of a
+ ;; paragraph-separator would count as a paragraph (and
+ ;; not skipping any chars at EOB would not count as a
+ ;; paragraph even if it is).
+ (move-to-left-margin)
+ (if (not (zerop (fill-forward-paragraph 1)))
+ ;; There's no paragraph at or after point: give up.
+ (setq fill-pfx "")
+ (let ((end (point))
+ (beg (progn (fill-forward-paragraph -1) (point))))
+ (goto-char before)
+ (setq fill-pfx
+ (if use-hard-newlines
+ ;; Can't use fill-region-as-paragraph, since this
+ ;; paragraph may still contain hard newlines. See
+ ;; fill-region.
+ (fill-region beg end justify)
+ (fill-region-as-paragraph beg end justify))))))
+ fill-pfx))))
(declare-function comment-search-forward "newcomment" (limit &optional noerror))
(declare-function comment-string-strip "newcomment" (str beforep afterp))
@@ -1114,6 +1105,10 @@ space does not end a sentence, so don't break a line there."
(defcustom default-justification 'left
"Method of justifying text not otherwise specified.
Possible values are `left', `right', `full', `center', or `none'.
+The values `left' and `right' mean lines are lined up at,
+respectively, left or right margin, and ragged at the other margin.
+`full' means lines are lined up at both margins. `center' means each
+line is centered. `none' means no justification or centering.
The requested kind of justification is done whenever lines are filled.
The `justification' text-property can locally override this variable."
:type '(choice (const left)
@@ -1143,6 +1138,7 @@ However, it returns nil rather than `none' to mean \"don't justify\"."
(defun set-justification (begin end style &optional whole-par)
"Set the region's justification style to STYLE.
This commands prompts for the kind of justification to use.
+See `default-justification' for the possible values and their meaning.
If the mark is not active, this command operates on the current paragraph.
If the mark is active, it operates on the region. However, if the
beginning and end of the region are not at paragraph breaks, they are
@@ -1194,7 +1190,8 @@ If the mark is not active, this applies to the current paragraph."
(defun set-justification-left (b e)
"Make paragraphs in the region left-justified.
-This means they are flush at the left margin and ragged on the right.
+This means lines are flush (lined up) at the left margin and ragged
+on the right.
This is usually the default, but see the variable `default-justification'.
If the mark is not active, this applies to the current paragraph."
(interactive (list (if mark-active (region-beginning) (point))
@@ -1203,7 +1200,8 @@ If the mark is not active, this applies to the current paragraph."
(defun set-justification-right (b e)
"Make paragraphs in the region right-justified.
-This means they are flush at the right margin and ragged on the left.
+This means lines are flush (lined up) at the right margin and ragged
+on the left.
If the mark is not active, this applies to the current paragraph."
(interactive (list (if mark-active (region-beginning) (point))
(if mark-active (region-end) (point))))
@@ -1211,7 +1209,7 @@ If the mark is not active, this applies to the current paragraph."
(defun set-justification-full (b e)
"Make paragraphs in the region fully justified.
-This makes lines flush on both margins by inserting spaces between words.
+This makes lines be lined up on both margins by inserting spaces between words.
If the mark is not active, this applies to the current paragraph."
(interactive (list (if mark-active (region-beginning) (point))
(if mark-active (region-end) (point))))
@@ -1246,7 +1244,8 @@ If the mark is not active, this applies to the current paragraph."
Normally does full justification: adds spaces to the line to make it end at
the column given by `current-fill-column'.
Optional first argument HOW specifies alternate type of justification:
-it can be `left', `right', `full', `center', or `none'.
+it can be `left', `right', `full', `center', or `none'; for their
+meaning, see `default-justification'.
If HOW is t, will justify however the `current-justification' function says to.
If HOW is nil or missing, full justification is done by default.
Second arg EOP non-nil means that this is the last line of the paragraph, so
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 664214419fa..2c5e30fecd8 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -489,6 +489,9 @@ Flyspell mode is a buffer-local minor mode. When enabled, it
spawns a single Ispell process and checks each word. The default
flyspell behavior is to highlight incorrect words.
+This mode is geared toward text modes. In buffers that contain
+code, `flyspell-prog-mode' is usually a better choice.
+
Bindings:
\\[ispell-word]: correct words (using Ispell).
\\[flyspell-auto-correct-word]: automatically correct word.
@@ -1939,9 +1942,7 @@ before point that's highlighted as misspelled."
'face 'flyspell-incorrect
string))
(setq pos (cdr pos)))
- (if (fboundp 'display-message)
- (display-message 'no-log string)
- (message "%s" string))))
+ (message "%s" string)))
;;*---------------------------------------------------------------------*/
;;* flyspell-abbrev-table ... */
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index ae3b18ed179..8c8522a6e5e 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -797,6 +797,9 @@ See `ispell-buffer-with-debug' for an example of use."
"An alist of parsed Aspell dicts and associated parameters.
Internal use.")
+(defvar ispell--aspell-found-dictionaries nil
+ "An alist of identified aspell dictionaries.")
+
(defun ispell-find-aspell-dictionaries ()
"Find Aspell's dictionaries, and record in `ispell-aspell-dictionary-alist'."
(let* ((dictionaries
@@ -810,7 +813,8 @@ Internal use.")
(mapcar #'ispell-aspell-find-dictionary dictionaries))))
;; Ensure aspell's alias dictionary will override standard
;; definitions.
- (setq found (ispell-aspell-add-aliases found))
+ (setq found (ispell-aspell-add-aliases found)
+ ispell--aspell-found-dictionaries (copy-sequence found))
;; Merge into FOUND any elements from the standard ispell-dictionary-base-alist
;; which have no element in FOUND at all.
(dolist (dict ispell-dictionary-base-alist)
@@ -1378,9 +1382,11 @@ The variable `ispell-library-directory' defines their location."
(if (and name
(or
;; Include all for Aspell (we already know existing dicts)
- ispell-really-aspell
+ (and ispell-really-aspell
+ (assoc name ispell--aspell-found-dictionaries))
;; Include all if `ispell-library-directory' is nil (Hunspell)
- (not ispell-library-directory)
+ (and (not ispell-really-aspell)
+ (not ispell-library-directory))
;; If explicit (-d with an absolute path) and existing dict.
(and dict-explt
(file-name-absolute-p dict-explt)
@@ -1673,14 +1679,13 @@ Valid forms include:
("\\\\bibliographystyle" ispell-tex-arg-end)
("\\\\makebox" ispell-tex-arg-end 0)
("\\\\e?psfig" ispell-tex-arg-end)
- ("\\\\document\\(class\\|style\\)" .
- "\\\\begin[ \t\n]*{[ \t\n]*document[ \t\n]*}"))
+ ("\\\\document\\(class\\|style\\)" . "\\\\begin[ \t\n]*{document}"))
(;; delimited with \begin. In ispell: displaymath, eqnarray, eqnarray*,
;; equation, minipage, picture, tabular, tabular* (ispell)
("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0)
("list" ispell-tex-arg-end 2)
- ("program" . "\\\\end[ \t\n]*{[ \t\n]*program[ \t\n]*}")
- ("verbatim\\*?" . "\\\\end[ \t\n]*{[ \t\n]*verbatim\\*?[ \t\n]*}"))))
+ ("program" . "\\\\end[ \t]*{program}")
+ ("verbatim\\*?" . "\\\\end[ \t]*{verbatim\\*?}"))))
"Lists of regions to be skipped in TeX mode.
First list is used raw.
Second list has key placed inside \\begin{}.
@@ -2610,15 +2615,18 @@ Optional REFRESH will unhighlighted then highlight, using block cursor
(text (buffer-substring-no-properties start end))
; Save highlight region.
(inhibit-quit t) ; inhibit interrupt processing here.
- (buffer-undo-list t)) ; don't clutter the undo list.
+ (buffer-undo-list t) ; don't clutter the undo list.
+ (end1 (if (markerp end) (marker-position end) end)))
(goto-char end)
(delete-region start end)
- (insert-char ? (- end start)) ; minimize amount of redisplay
+ (insert-char ? (- end1 start)) ; minimize amount of redisplay
(sit-for 0) ; update display
(if highlight (setq inverse-video (not inverse-video))) ; toggle video
- (delete-region start end) ; delete whitespace
+ (delete-region start end1) ; delete whitespace
(insert text) ; insert text in inverse video.
(sit-for 0) ; update display showing inverse video.
+ (if (markerp end)
+ (set-marker end end1)) ; restore marker position
(if (not highlight)
(goto-char end)
(setq inverse-video (not inverse-video)) ; toggle video
@@ -2987,8 +2995,7 @@ By just answering RET you can find out what the current dictionary is."
(interactive
(list (completing-read
"Use new dictionary (RET for current, SPC to complete): "
- (and (fboundp 'ispell-valid-dictionary-list)
- (mapcar #'list (ispell-valid-dictionary-list)))
+ (mapcar #'list (ispell-valid-dictionary-list))
nil t)
current-prefix-arg))
(ispell-set-spellchecker-params) ; Initialize variables and dicts alists
@@ -3048,6 +3055,8 @@ when needed."
;;;###autoload
(defun ispell-region (reg-start reg-end &optional recheckp shift)
"Interactively check a region for spelling errors.
+Leave the mark at the last misspelled word that the user was queried about.
+
Return nil if spell session was terminated, otherwise returns shift offset
amount for last line processed."
(interactive "r") ; Don't flag errors on read-only bufs.
@@ -3059,7 +3068,8 @@ amount for last line processed."
(region-type (if (and (= reg-start (point-min)) (= reg-end (point-max)))
(buffer-name) "region"))
(program-basename (file-name-nondirectory ispell-program-name))
- (dictionary (or ispell-current-dictionary "default")))
+ (dictionary (or ispell-current-dictionary "default"))
+ max-word)
(unwind-protect
(save-excursion
(message "Spell-checking %s using %s with %s dictionary..."
@@ -3155,10 +3165,14 @@ ispell-region: Search for first region to skip after (ispell-begin-skip-region-r
;; Reset `in-comment' (and indirectly `add-comment') for new line
in-comment nil))
(setq ispell-end (point)) ; "end" tracks region retrieved.
- (if string ; there is something to spell check!
- ;; (special start end)
- (setq shift (ispell-process-line string
- (and recheckp shift))))
+ ;; There is something to spell check!
+ (when string
+ ;; (special start end)
+ (let ((res (ispell-process-line string
+ (and recheckp shift))))
+ (setq shift (car res))
+ (when (cdr res)
+ (setq max-word (cdr res)))))
(goto-char ispell-end)))))
(if ispell-quit
nil
@@ -3169,6 +3183,9 @@ ispell-region: Search for first region to skip after (ispell-begin-skip-region-r
(kill-buffer ispell-choices-buffer))
(set-marker skip-region-start nil)
(set-marker rstart nil)
+ ;; Allow the user to pop back to the last position.
+ (when max-word
+ (push-mark max-word t))
(if ispell-quit
(progn
;; preserve or clear the region for ispell-continue.
@@ -3403,9 +3420,12 @@ Returns a string with the line data."
This will modify the buffer for spelling errors.
Requires variables ISPELL-START and ISPELL-END to be defined in its
dynamic scope.
-Returns the sum SHIFT due to changes in word replacements."
+
+Returns a cons cell where the `car' is sum SHIFT due to changes
+in word replacements, and the `cdr' is the location of the final
+word that was queried about."
;;(declare special ispell-start ispell-end)
- (let (poss accept-list)
+ (let (poss accept-list max-word)
(if (not (numberp shift))
(setq shift 0))
;; send string to spell process and get input.
@@ -3459,6 +3479,7 @@ Returns the sum SHIFT due to changes in word replacements."
(error (concat "Ispell misalignment: word "
"`%s' point %d; probably incompatible versions")
ispell-pipe-word actual-point)))
+ (setq max-word (marker-position word-start))
;; ispell-cmd-loop can go recursive & change buffer
(if ispell-keep-choices-win
(setq replace (ispell-command-loop
@@ -3555,7 +3576,7 @@ Returns the sum SHIFT due to changes in word replacements."
(set-marker line-end nil)))
;; Finished with misspelling!
(setq ispell-filter (cdr ispell-filter)))
- shift))
+ (cons shift max-word)))
;;;###autoload
@@ -3596,7 +3617,8 @@ to limit the check."
;;;###autoload
(defun ispell-buffer ()
- "Check the current buffer for spelling errors interactively."
+ "Check the current buffer for spelling errors interactively.
+Leave the mark at the last misspelled word that the user was queried about."
(interactive)
(ispell-region (point-min) (point-max)))
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
index 24149f9afb8..6b71f26e4f2 100644
--- a/lisp/textmodes/page-ext.el
+++ b/lisp/textmodes/page-ext.el
@@ -515,13 +515,12 @@ resets the page-delimiter to the original value."
(defvar pages-buffer-original-position)
(defvar pages-buffer-original-page)
-(defun pages-directory
- (pages-list-all-headers-p count-lines-p &optional regexp)
+(defun pages-directory (pages-list-all-headers-p count-lines-p &optional regexp)
"Display a directory of the page headers in a temporary buffer.
A header is the first non-blank line after the `page-delimiter'.
-\\[pages-directory-mode]
+\\<pages-directory-mode-map>
You may move point to one of the lines in the temporary buffer,
-then use \\<pages-directory-goto> to go to the same line in the pages buffer.
+then use \\[pages-directory-goto] to go to the same line in the pages buffer.
In interactive use:
@@ -587,7 +586,9 @@ directory for only the accessible portion of the buffer."
(pages-directory-mode)
(setq buffer-read-only nil)
(insert
- "==== Pages Directory: use `C-c C-c' to go to page under cursor. ====" ?\n)
+ (substitute-command-keys
+ "==== Pages Directory: use \\<pages-directory-mode-map>\
+\\[pages-directory-goto] to go to page under cursor. ====") "\n")
(setq pages-buffer pages-target-buffer)
(setq pages-pos-list nil))
@@ -772,7 +773,9 @@ directory."
(goto-char (point-min))
(delete-region (point) (line-end-position))
(insert
- "=== Address List Directory: use `C-c C-c' to go to page under cursor. ===")
+ (substitute-command-keys
+ "=== Address List Directory: use \\<pages-directory-mode-map>\
+\\[pages-directory-goto] to go to page under cursor. ==="))
(set-buffer-modified-p nil)
))
(error "No addresses file found!")))
diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el
index 3fc18323349..5d6f017eb99 100644
--- a/lisp/textmodes/page.el
+++ b/lisp/textmodes/page.el
@@ -35,11 +35,18 @@ A page boundary is any line whose beginning matches the regexp
(interactive "p")
(or count (setq count 1))
(while (and (> count 0) (not (eobp)))
- ;; In case the page-delimiter matches the null string,
- ;; don't find a match without moving.
- (if (bolp) (forward-char 1))
- (unless (re-search-forward page-delimiter nil t)
- (goto-char (point-max)))
+ (if (and (looking-at page-delimiter)
+ (> (match-end 0) (point)))
+ ;; If we're standing at the page delimiter, then just skip to
+ ;; the end of it. (But only if it's not a zero-length
+ ;; delimiter, because then we wouldn't have forward progress.)
+ (goto-char (match-end 0))
+ ;; In case the page-delimiter matches the null string,
+ ;; don't find a match without moving.
+ (when (bolp)
+ (forward-char 1))
+ (unless (re-search-forward page-delimiter nil t)
+ (goto-char (point-max))))
(setq count (1- count)))
(while (and (< count 0) (not (bobp)))
;; In case the page-delimiter matches the null string,
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index 7daf71e990e..cd726ad4776 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -96,8 +96,8 @@ lines that start paragraphs from lines that separate them.
If the variable `use-hard-newlines' is non-nil, then only lines following a
hard newline are considered to match."
- :type 'regexp)
-(put 'paragraph-start 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
;; paragraph-start requires a hard newline, but paragraph-separate does not:
;; It is assumed that paragraph-separate is distinctive enough to be believed
@@ -113,8 +113,8 @@ This is matched against the text at the left margin, which is not necessarily
the beginning of the line, so it should not use \"^\" as an anchor. This
ensures that the paragraph functions will work equally within a region of
text indented by a margin setting."
- :type 'regexp)
-(put 'paragraph-separate 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
(defcustom sentence-end-double-space t
"Non-nil means a single space does not end a sentence.
@@ -125,8 +125,8 @@ This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
:type 'boolean
+ :safe #'booleanp
:group 'fill)
-(put 'sentence-end-double-space 'safe-local-variable #'booleanp)
(defcustom sentence-end-without-period nil
"Non-nil means a sentence will end without a period.
@@ -137,8 +137,8 @@ This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
:type 'boolean
+ :safe #'booleanp
:group 'fill)
-(put 'sentence-end-without-period 'safe-local-variable #'booleanp)
(defcustom sentence-end-without-space
"。.?!"
@@ -147,8 +147,8 @@ regexp describing the end of a sentence, when the value of the variable
This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
- :type 'string)
-(put 'sentence-end-without-space 'safe-local-variable #'stringp)
+ :type 'string
+ :safe #'stringp)
(defcustom sentence-end nil
"Regexp describing the end of a sentence.
@@ -158,14 +158,14 @@ All paragraph boundaries also end sentences, regardless.
The value nil means to use the default value defined by the
function `sentence-end'. You should always use this function
to obtain the value of this variable."
- :type '(choice regexp (const :tag "Use default value" nil)))
-(put 'sentence-end 'safe-local-variable #'string-or-null-p)
+ :type '(choice regexp (const :tag "Use default value" nil))
+ :safe #'string-or-null-p)
(defcustom sentence-end-base "[.?!…‽][]\"'”’)}»›]*"
"Regexp matching the basic end of a sentence, not including following space."
:type 'regexp
+ :safe #'stringp
:version "25.1")
-(put 'sentence-end-base 'safe-local-variable #'stringp)
(defun sentence-end ()
"Return the regexp describing the end of a sentence.
@@ -192,14 +192,14 @@ in between. See Info node `(elisp)Standard Regexps'."
(defcustom page-delimiter "^\014"
"Regexp describing line-beginnings that separate pages."
- :type 'regexp)
-(put 'page-delimiter 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
(defcustom paragraph-ignore-fill-prefix nil
"Non-nil means the paragraph commands are not affected by `fill-prefix'.
This is desirable in modes where blank lines are the paragraph delimiters."
- :type 'boolean)
-(put 'paragraph-ignore-fill-prefix 'safe-local-variable #'booleanp)
+ :type 'boolean
+ :safe #'booleanp)
;; Silence the compiler.
(defun forward-paragraph (&optional arg)
@@ -477,7 +477,23 @@ sentences. Also, every paragraph boundary terminates sentences as well."
(skip-chars-backward " \t\n")
(goto-char par-end)))
(setq arg (1- arg)))
- (constrain-to-field nil opoint t)))
+ (let ((npoint (constrain-to-field nil opoint t)))
+ (not (= npoint opoint)))))
+
+(defun count-sentences (start end)
+ "Count sentences in current buffer from START to END."
+ (let ((sentences 0)
+ (inhibit-field-text-motion t))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (ignore-errors (forward-sentence))
+ (setq sentences (1+ sentences)))
+ ;; Remove last possibly empty sentence
+ (when (/= (skip-chars-backward " \t\n") 0)
+ (setq sentences (1- sentences)))
+ sentences))))
(defun repunctuate-sentences-filter (_start _end)
"Search filter used by `repunctuate-sentences' to skip unneeded spaces.
diff --git a/lisp/textmodes/pixel-fill.el b/lisp/textmodes/pixel-fill.el
index 418d6a37c97..e47653e734a 100644
--- a/lisp/textmodes/pixel-fill.el
+++ b/lisp/textmodes/pixel-fill.el
@@ -45,9 +45,9 @@ of a line or the end of a line."
(defun pixel-fill-width (&optional columns window)
"Return the pixel width corresponding to COLUMNS in WINDOW.
-If COLUMNS in nil, use the enture window width.
+If COLUMNS is nil or omitted, use the entire window width.
-If WINDOW is nil, this defaults to the current window."
+If WINDOW is nil or omitted, this defaults to the selected window."
(unless window
(setq window (selected-window)))
(let ((frame (window-frame window)))
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 4e487d745c2..26b14ebc79e 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -360,7 +360,7 @@ The name of the first different author/editor is used."
;; Parse the bibliography environment
(defun reftex-extract-bib-entries-from-thebibliography (files)
- "Extract bib-entries from the \begin{thebibliography} environment.
+ "Extract bib-entries from the \\begin{thebibliography} environment.
Parsing is not as good as for the BibTeX database stuff.
The environment should be located in FILES."
(let* (start end buf entries re re-list file default)
@@ -580,7 +580,7 @@ If FORMAT is non-nil `format' entry accordingly."
(concat key "\n " authors " " year " " extra "\n " title "\n\n")))
(defun reftex-parse-bibitem (item)
- "Parse a \bibitem entry in ITEM."
+ "Parse a \\bibitem entry in ITEM."
(let ((key "") (text ""))
(when (string-match "\\`{\\([^}]+\\)}\\([^\000]*\\)" item)
(setq key (match-string 1 item)
@@ -596,7 +596,7 @@ If FORMAT is non-nil `format' entry accordingly."
(cons "&entry" (concat key " " text)))))
(defun reftex-format-bibitem (item)
- "Format a \bibitem entry in ITEM so that it is (relatively) nice to look at."
+ "Format a \\bibitem entry in ITEM so that it is (relatively) nice to look at."
(let ((text (reftex-get-bib-field "&text" item))
(key (reftex-get-bib-field "&key" item))
(lines nil))
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index 5ab9ecd8db3..062cea9c505 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -88,6 +88,12 @@ No active TAGS table is required."
(defun reftex-query-replace-document (&optional from to delimited)
"Do `query-replace-regexp' of FROM with TO over the entire document.
Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
with the command \\[tags-loop-continue].
No active TAGS table is required."
@@ -184,8 +190,8 @@ No active TAGS table is required."
default))))
(if (string= from "") (setq from default))
(unless to
- (setq to (read-string (format "Replace label %s with: "
- from))))
+ (setq to (read-string (format "Replace label %s with: " from)
+ nil nil from)))
(reftex-query-replace-document
(concat "{" (regexp-quote from) "}")
(format "{%s}" to))))
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index 734f82aba3f..b517cc16634 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -269,8 +269,6 @@ will prompt for other arguments."
(and newtag (cdr cell) (not (member newtag (cdr cell)))
(push newtag (cdr cell)))))
-(define-obsolete-variable-alias
- 'reftex-index-map 'reftex-index-mode-map "24.1")
(defvar reftex-index-mode-map
(let ((map (make-sparse-keymap)))
;; Index map
@@ -1198,8 +1196,6 @@ This gets refreshed in every phrases command.")
'((reftex-index-phrases-font-lock-keywords)
nil t nil beginning-of-line)
"Font lock defaults for `reftex-index-phrases-mode'.")
-(define-obsolete-variable-alias
- 'reftex-index-phrases-map 'reftex-index-phrases-mode-map "24.1")
(defvar reftex-index-phrases-mode-map
(let ((map (make-sparse-keymap)))
;; Keybindings and Menu for phrases buffer
@@ -1272,10 +1268,11 @@ This gets refreshed in every phrases command.")
;;;###autoload
(defun reftex-index-phrase-selection-or-word (arg)
"Add current selection or word at point to the phrases buffer.
+\\<reftex-index-phrases-mode-map>
When you are in transient-mark-mode and the region is active, the
selection will be used - otherwise the word at point.
You get a chance to edit the entry in the phrases buffer - finish with
-`C-c C-c'."
+\\[reftex-index-phrases-save-and-return]."
(interactive "P")
(set-marker reftex-index-return-marker (point))
(reftex-index-selection-or-word arg 'phrase)
@@ -1373,7 +1370,7 @@ If the buffer is non-empty, delete the old header first."
;;;###autoload
(define-derived-mode reftex-index-phrases-mode fundamental-mode "Phrases"
"Major mode for managing the Index phrases of a LaTeX document.
-This buffer was created with RefTeX.
+This buffer was created with RefTeX. \\<reftex-index-phrases-mode-map>
To insert new phrases, use
- `C-c \\' in the LaTeX document to copy selection or word
@@ -1684,8 +1681,8 @@ this function repeatedly."
(defun reftex-index-phrases-set-macro-key ()
"Change the macro key for the current line.
Prompts for a macro key and insert is at the beginning of the line.
-If you reply with SPACE, the macro keyn will be removed, so that the
-default macro will be used. If you reply with `RET', just prints
+If you reply with \\`SPC', the macro key will be removed, so that the
+default macro will be used. If you reply with \\`RET', just prints
information about the currently selected macro."
(interactive)
(reftex-index-phrases-parse-header)
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index 016c9cf3990..49cef297882 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -370,13 +370,18 @@ of master file."
docstruct))
(defun reftex-using-biblatex-p ()
- "Return non-nil if we are using biblatex rather than bibtex."
+ "Return non-nil if we are using biblatex or other specific cite package.
+biblatex and other similar packages like multibib allow multiple macro
+calls to load a bibliography file. This function should be able to
+detect those packages."
(if (boundp 'TeX-active-styles)
;; the sophisticated AUCTeX way
- (member "biblatex" TeX-active-styles)
+ (or (member "biblatex" TeX-active-styles)
+ (member "multibib" TeX-active-styles))
;; poor-man's check...
(save-excursion
- (re-search-forward "^[^%\n]*?\\\\usepackage.*{biblatex}" nil t))))
+ (re-search-forward
+ "^[^%\n]*?\\\\usepackage\\(\\[[^]]*\\]\\)?{biblatex\\|multibib}" nil t))))
;;;###autoload
(defun reftex-locate-bibliography-files (master-dir &optional files)
@@ -384,7 +389,7 @@ of master file."
(unless files
(save-excursion
(goto-char (point-min))
- ;; when biblatex is used, multiple \bibliography or
+ ;; when biblatex or multibib are used, multiple \bibliography or
;; \addbibresource macros are allowed. With plain bibtex, only
;; the first is used.
(let ((using-biblatex (reftex-using-biblatex-p))
@@ -392,7 +397,7 @@ of master file."
(while (and again
(re-search-forward
(concat
- ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
+ ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
"\\(^\\)[^%\n\r]*\\\\\\("
(mapconcat #'identity reftex-bibliography-commands "\\|")
"\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)")
@@ -415,7 +420,7 @@ of master file."
;; find the file
(reftex-locate-file x "bib" master-dir)))
files))
- (delq nil files)))
+ (delq nil (delete-dups files))))
(defun reftex-replace-label-list-segment (old insert &optional entirely)
"Replace the segment in OLD which corresponds to INSERT.
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index d77411483f7..5942801a8a9 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -59,8 +59,6 @@
(define-key map [follow-link] 'mouse-face)
map))
-(define-obsolete-variable-alias
- 'reftex-select-label-map 'reftex-select-label-mode-map "24.1")
(defvar reftex-select-label-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map reftex-select-shared-map)
@@ -109,8 +107,6 @@ During a selection process, these are the local bindings.
;; We do not set a local map - reftex-select-item does this.
)
-(define-obsolete-variable-alias
- 'reftex-select-bib-map 'reftex-select-bib-mode-map "24.1")
(defvar reftex-select-bib-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map reftex-select-shared-map)
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index 4ba3c2193ee..5599eaee024 100644
--- a/lisp/textmodes/reftex-toc.el
+++ b/lisp/textmodes/reftex-toc.el
@@ -28,7 +28,6 @@
(require 'reftex)
;;;
-(define-obsolete-variable-alias 'reftex-toc-map 'reftex-toc-mode-map "24.1")
(defvar reftex-toc-mode-map
(let ((map (make-sparse-keymap)))
@@ -157,22 +156,22 @@ Here are all local bindings.
(defconst reftex-toc-help
" AVAILABLE KEYS IN TOC BUFFER
============================
-n / p next-line / previous-line
-SPC Show the corresponding location of the LaTeX document.
-TAB Goto the location and keep the TOC window.
-RET Goto the location and hide the TOC window (also on mouse-2).
-< / > Promote / Demote section, or all sections in region.
-C-c > Display Index. With prefix arg, restrict index to current section.
-q / k Hide/Kill *toc* buffer, return to position of reftex-toc command.
-l i c F Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders.
-t Change maximum toc depth (e.g. `3 t' hides levels greater than 3).
-f / g Toggle follow mode / Refresh *toc* buffer.
-a / d Toggle auto recenter / Toggle dedicated frame
-r / C-u r Reparse the LaTeX document / Reparse entire LaTeX document.
-. In other window, show position from where `reftex-toc' was called.
-M-% Global search and replace to rename label at point.
-x Switch to TOC of external document (with LaTeX package `xr').
-z Jump to a specific section (e.g. '3 z' goes to section 3).")
+\\`n' / \\`p' `next-line' / `previous-line'
+\\`SPC' Show the corresponding location of the LaTeX document.
+\\`TAB' Goto the location and keep the TOC window.
+\\`RET' Goto the location and hide the TOC window (also on `mouse-2').
+\\`<' / \\`>' Promote / Demote section, or all sections in region.
+\\`C-c >' Display Index. With prefix arg, restrict index to current section.
+\\`q' / \\`k' Hide/Kill *toc* buffer, return to position of reftex-toc command.
+\\`l' \\`i' \\`c' \\`F' Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders.
+\\`t' Change maximum toc depth (e.g. `3 t' hides levels greater than 3).
+\\`f' / \\`g' Toggle follow mode / Refresh *toc* buffer.
+\\`a' / \\`d' Toggle auto recenter / Toggle dedicated frame
+\\`r' / \\`C-u r' Reparse the LaTeX document / Reparse entire LaTeX document.
+\\`.' In other window, show position from where `reftex-toc' was called.
+\\`M-%' Global search and replace to rename label at point.
+\\`x' Switch to TOC of external document (with LaTeX package `xr').
+\\`z' Jump to a specific section (e.g. \\`3 z' goes to section 3).")
(defvar reftex--rebuilding-toc nil)
@@ -381,7 +380,7 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(- (or reftex-last-window-height (window-height))
(window-height)))))
(when (> count 0)
- (with-demoted-errors ;E.g. the window might be the root window!
+ (with-demoted-errors "Enlarge window error: %S"
(enlarge-window count reftex-toc-split-windows-horizontally)))))
(defun reftex-toc-dframe-p (&optional frame error)
@@ -394,7 +393,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(frame-parameter frame 'name))
"RefTeX TOC Frame")))
(if (and res error)
- (error "This frame is view-only. Use `C-c =' to create TOC window for commands"))
+ (error (substitute-command-keys
+ "This frame is view-only. Use \\[reftex-toc] \
+to create TOC window for commands")))
res))
(defun reftex-toc-show-help ()
@@ -402,7 +403,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(interactive)
(reftex-toc-dframe-p nil 'error)
(with-output-to-temp-buffer "*RefTeX Help*"
- (princ reftex-toc-help))
+ (let ((help (substitute-command-keys reftex-toc-help)))
+ (with-current-buffer standard-output
+ (insert help))))
(reftex-enlarge-to-fit "*RefTeX Help*" t)
;; If follow mode is active, arrange to delay it one command
(if reftex-toc-follow-mode
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index f9d832f1556..f9f09825fa0 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -1318,7 +1318,7 @@ macro before insertion. For example, it will change
\\cite[][]{Jones} -> \\cite{Jones}
\\cite[][Chapter 1]{Jones} -> \\cite[Chapter 1]{Jones}
\\cite[see][]{Jones} -> \\cite[see][]{Jones}
- \\cite[see][Chapter 1]{Jones} -> \\cite{Jones}
+ \\cite[see][Chapter 1]{Jones} -> \\cite[see][Chapter 1]{Jones}
It is possible that other packages have other conventions about which
optional argument is interpreted how - that is why this cleaning up
can be turned off."
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 907d50889a1..e72576cdc74 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -2257,8 +2257,7 @@ IGNORE-WORDS List of words which should be removed from the string."
("Customize"
["Browse RefTeX Group" reftex-customize t]
"--"
- ["Build Full Customize Menu" reftex-create-customize-menu
- (fboundp 'customize-menu-create)])
+ ["Build Full Customize Menu" reftex-create-customize-menu])
("Documentation"
["Info" reftex-info t]
["Commentary" reftex-show-commentary t])))
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index d65aea62862..f7ebe04bcf5 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -296,7 +296,8 @@ With a prefix or a visible region, use the region as INITIAL."
(insert "\n\n" annotation))
(setq remember-initial-contents nil)
(goto-char (point-min)))
- (message "Use C-c C-c to remember the data.")))
+ (message (substitute-command-keys
+ "Use \\[remember-finalize] to remember the data"))))
;;;###autoload
(defun remember-other-frame (&optional initial)
@@ -653,7 +654,7 @@ to turn the *scratch* buffer into your notes buffer."
(remember-notes-mode 1)
(current-buffer)))))
(when switch-to
- (switch-to-buffer buf))
+ (pop-to-buffer-same-window buf))
buf))
(defun remember-notes--kill-buffer-query ()
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index 9d3e9effe6e..ecc3f259359 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -48,10 +48,10 @@
;; the contents of this package and how to use it.
;;
;; For more information about reStructuredText, see
-;; http://docutils.sourceforge.net/rst.html
+;; https://docutils.sourceforge.io/rst.html
;;
;; For full details on how to use the contents of this file, see
-;; http://docutils.sourceforge.net/docs/user/emacs.html
+;; https://docutils.sourceforge.io/docs/user/emacs.html
;;
;; There are a number of convenient key bindings provided by rst-mode. For the
;; bindings, try C-c C-h when in rst-mode. There are also many variables that
@@ -72,7 +72,7 @@
;;; DOWNLOAD
;; The latest release of this file lies in the docutils source code repository:
-;; http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/docutils/tools/editors/emacs/rst.el
+;; https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/tools/editors/emacs/rst.el
;;; INSTALLATION
@@ -81,7 +81,7 @@
;; (require 'rst)
;;
;; If you are using `.txt' as a standard extension for reST files as
-;; http://docutils.sourceforge.net/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file
+;; https://docutils.sourceforge.io/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file
;; suggests you may use one of the `Local Variables in Files' mechanism Emacs
;; provides to set the major mode automatically. For instance you may use::
;;
@@ -274,7 +274,7 @@ in parentheses follows the development revision and the time stamp.")
(defgroup rst nil "Support for reStructuredText documents."
:group 'text
:version "23.1"
- :link '(url-link "http://docutils.sourceforge.net/rst.html"))
+ :link '(url-link "https://docutils.sourceforge.io/rst.html"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -522,7 +522,7 @@ argument list for `rst-re'.")
(defvar rst-re-alist) ; Forward declare to use it in `rst-re'.
-;; FIXME: Use `sregex' or `rx' instead of re-inventing the wheel.
+;; FIXME: Use `rx' instead of re-inventing the wheel.
(rst-testcover-add-compose 'rst-re)
(defun rst-re (&rest args)
;; testcover: ok.
@@ -2351,7 +2351,7 @@ If user selects bullets or #, it's just added with position arranged by
`rst-insert-list-new-tag'.
If user selects enumerations, a further prompt is given. User need to
-input a starting item, for example 'e' for 'A)' style. The position is
+input a starting item, for example `e' for `A)' style. The position is
also arranged by `rst-insert-list-new-tag'."
(let* ((itemstyle (completing-read
(format-prompt "Select preferred item style" "#.")
@@ -3584,125 +3584,46 @@ Region is from BEG to END. With WITH-EMPTY prefix empty lines too."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-block-face 'rst-block
- "All syntax marking up a special block."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-block-face
- "customize the face `rst-block' instead."
- "24.1")
-
(defface rst-external '((t :inherit font-lock-type-face))
"Face used for field names and interpreted text."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-external-face 'rst-external
- "Field names and interpreted text."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-external-face
- "customize the face `rst-external' instead."
- "24.1")
-
(defface rst-definition '((t :inherit font-lock-function-name-face))
"Face used for all other defining constructs."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-definition-face 'rst-definition
- "All other defining constructs."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-definition-face
- "customize the face `rst-definition' instead."
- "24.1")
-
(defface rst-directive '((t :inherit font-lock-builtin-face))
"Face used for directives and roles."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-directive-face 'rst-directive
- "Directives and roles."
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-directive-face
- "customize the face `rst-directive' instead."
- "24.1")
-
(defface rst-comment '((t :inherit font-lock-comment-face))
"Face used for comments."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-comment-face 'rst-comment
- "Comments."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-comment-face
- "customize the face `rst-comment' instead."
- "24.1")
-
(defface rst-emphasis1 '((t :inherit italic))
"Face used for simple emphasis."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-emphasis1-face 'rst-emphasis1
- "Simple emphasis."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-emphasis1-face
- "customize the face `rst-emphasis1' instead."
- "24.1")
-
(defface rst-emphasis2 '((t :inherit bold))
"Face used for double emphasis."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-emphasis2-face 'rst-emphasis2
- "Double emphasis."
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-emphasis2-face
- "customize the face `rst-emphasis2' instead."
- "24.1")
-
(defface rst-literal '((t :inherit font-lock-string-face))
"Face used for literal text."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-literal-face 'rst-literal
- "Literal text."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-literal-face
- "customize the face `rst-literal' instead."
- "24.1")
-
(defface rst-reference '((t :inherit font-lock-variable-name-face))
"Face used for references to a definition."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-reference-face 'rst-reference
- "References to a definition."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-reference-face
- "customize the face `rst-reference' instead."
- "24.1")
-
(defface rst-transition '((t :inherit font-lock-keyword-face))
"Face used for a transition."
:package-version '(rst . "1.3.0")
@@ -3786,7 +3707,7 @@ of your own."
(defvar rst-font-lock-keywords
;; The reST-links in the comments below all relate to sections in
- ;; http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html.
+ ;; https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html.
`(;; FIXME: Block markup is not recognized in blocks after explicit markup
;; start.
@@ -3794,23 +3715,23 @@ of your own."
;; `Bullet Lists`_
;; FIXME: A bullet directly after a field name is not recognized.
(,(rst-re 'lin-beg '(:grp bul-sta))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Enumerated Lists`_
(,(rst-re 'lin-beg '(:grp enmany-sta))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Definition Lists`_
;; FIXME: missing.
;; `Field Lists`_
(,(rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx)
- 1 rst-external-face)
+ 1 'rst-external)
;; `Option Lists`_
(,(rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*")
'(:alt "$" (:seq hws-prt "\\{2\\}")))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Line Blocks`_
;; Only for lines containing no more bar - to distinguish from tables.
(,(rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$")
- 1 rst-block-face)
+ 1 'rst-block)
;; `Tables`_
;; FIXME: missing
@@ -3818,22 +3739,22 @@ of your own."
;; All the `Explicit Markup Blocks`_
;; `Footnotes`_ / `Citations`_
(,(rst-re 'lin-beg 'fnc-sta-2)
- (1 rst-definition-face)
- (2 rst-definition-face))
+ (1 'rst-definition)
+ (2 'rst-definition))
;; `Directives`_ / `Substitution Definitions`_
(,(rst-re 'lin-beg 'dir-sta-3)
- (1 rst-directive-face)
- (2 rst-definition-face)
- (3 rst-directive-face))
+ (1 'rst-directive)
+ (2 'rst-definition)
+ (3 'rst-directive))
;; `Hyperlink Targets`_
(,(rst-re 'lin-beg
'(:grp exm-sta "_" (:alt
(:seq "`" ilcbkqdef-tag "`")
(:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":")
'bli-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
(,(rst-re 'lin-beg '(:grp "__") 'bli-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; All `Inline Markup`_
;; Most of them may be multiline though this is uninteresting.
@@ -3841,16 +3762,16 @@ of your own."
;; FIXME: Condition 5 preventing fontification of e.g. "*" not implemented
;; `Strong Emphasis`_.
(,(rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx)
- 1 rst-emphasis2-face)
+ 1 'rst-emphasis2)
;; `Emphasis`_
(,(rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx)
- 1 rst-emphasis1-face)
+ 1 'rst-emphasis1)
;; `Inline Literals`_
(,(rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx)
- 1 rst-literal-face)
+ 1 'rst-literal)
;; `Inline Internal Targets`_
(,(rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; `Hyperlink References`_
;; FIXME: `Embedded URIs and Aliases`_ not considered.
;; FIXME: Directly adjacent marked up words are not fontified correctly
@@ -3858,28 +3779,28 @@ of your own."
(,(rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`")
(:seq "\\sw" (:alt "\\sw" "-") "+\\sw"))
"__?") 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Interpreted Text`_
(,(rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?")
'(:grp "`" ilcbkq-tag "`")
'(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx)
- (1 rst-directive-face)
- (2 rst-external-face)
- (3 rst-directive-face))
+ (1 'rst-directive)
+ (2 'rst-external)
+ (3 'rst-directive))
;; `Footnote References`_ / `Citation References`_
(,(rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Substitution References`_
;; FIXME: References substitutions like |this|_ or |this|__ are not
;; fontified correctly.
(,(rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Standalone Hyperlinks`_
;; FIXME: This takes it easy by using a whitespace as delimiter.
(,(rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
(,(rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; Do all block fontification as late as possible so 'append works.
@@ -3906,18 +3827,18 @@ of your own."
;; `Comments`_
;; This is multiline.
(,(rst-re 'lin-beg 'cmt-sta-1)
- (1 rst-comment-face)
+ (1 'rst-comment)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit (match-end 1))
nil
- (0 rst-comment-face append)))
+ (0 'rst-comment append)))
(,(rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$")
- (1 rst-comment-face)
- (2 rst-comment-face)
+ (1'rst-comment)
+ (2'rst-comment)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit 'next)
nil
- (0 rst-comment-face append)))
+ (0 'rst-comment append)))
;; FIXME: This is not rendered as comment::
;; .. .. list-table::
@@ -3941,11 +3862,11 @@ of your own."
;; `Indented Literal Blocks`_
;; This is multiline.
(,(rst-re 'lin-beg 'lit-sta-2)
- (2 rst-block-face)
+ (2 'rst-block)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit t)
nil
- (0 rst-literal-face append)))
+ (0 'rst-literal append)))
;; FIXME: `Quoted Literal Blocks`_ missing.
;; This is multiline.
@@ -3972,8 +3893,8 @@ of your own."
;;
;; Indentation is not required for doctest blocks.
(,(rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+"))
- (1 rst-block-face)
- (2 rst-literal-face)))
+ (1 'rst-block)
+ (2 'rst-literal)))
"Keywords to highlight in rst mode.")
(defvar font-lock-beg)
@@ -4402,7 +4323,7 @@ buffer, if the region is not selected."
;; FIXME: Add `rst-compile-html-preview'.
-;; FIXME: Add support for `restview` (http://mg.pov.lt/restview/). May be a
+;; FIXME: Add support for `restview` (https://mg.pov.lt/restview/). May be a
;; more general facility for calling commands on a reST file would make
;; sense.
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 83631e64752..13ff3dcab6a 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -419,11 +419,11 @@ These have to be run via `sgml-syntax-propertize'"))
(defun sgml-syntax-propertize (start end &optional rules-function)
"Syntactic keywords for `sgml-mode'."
(setq sgml--syntax-propertize-ppss (cons start (syntax-ppss start)))
- (cl-assert (>= (cadr sgml--syntax-propertize-ppss) 0))
- (sgml-syntax-propertize-inside end)
- (funcall (or rules-function sgml--syntax-propertize) (point) end)
- ;; Catch any '>' after the last quote.
- (sgml--syntax-propertize-ppss end))
+ (when (>= (cadr sgml--syntax-propertize-ppss) 0)
+ (sgml-syntax-propertize-inside end)
+ (funcall (or rules-function sgml--syntax-propertize) (point) end)
+ ;; Catch any '>' after the last quote.
+ (sgml--syntax-propertize-ppss end)))
(defun sgml-syntax-propertize-inside (end)
(let ((ppss (syntax-ppss)))
@@ -600,12 +600,11 @@ Do \\[describe-key] on the following bindings to discover what they do.
(setq-local tildify-foreach-region-function
(apply-partially
'tildify-foreach-ignore-environments
- `((,(eval-when-compile
- (concat
- "<\\("
- (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var"
- "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR"))
- "\\)\\>[^>]*>"))
+ `((,(concat
+ "<\\("
+ (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var"
+ "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR"))
+ "\\)\\>[^>]*>")
. ("</" 1 ">"))
("<! *--" . "-- *>")
("<" . ">"))))
@@ -2409,6 +2408,7 @@ To work around that, do:
(lambda () (char-before (match-end 0))))
(setq-local add-log-current-defun-function #'html-current-defun-name)
(setq-local sentence-end-base "[.?!][]\"'”)}]*\\(<[^>]*>\\)*")
+ (add-hook 'completion-at-point-functions 'html-mode--complete-at-point nil t)
(when (fboundp 'libxml-parse-html-region)
(defvar css-class-list-function)
@@ -2434,6 +2434,36 @@ To work around that, do:
;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose
)
+(defun html-mode--complete-at-point ()
+ ;; Complete a tag like <colg etc.
+ (or
+ (when-let ((tag (save-excursion
+ (and (looking-back "<\\([^ \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1)))))
+ (list (match-beginning 1) (point)
+ (mapcar #'car html-tag-alist)))
+ ;; Complete params like <colgroup ali etc.
+ (when-let ((tag (save-excursion (sgml-beginning-of-tag)))
+ (params (seq-filter #'consp (cdr (assoc tag html-tag-alist))))
+ (param (save-excursion
+ (and (looking-back "[ \t\n]\\([^= \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1)))))
+ (list (match-beginning 1) (point)
+ (mapcar #'car params)))
+ ;; Complete param values like <colgroup align=mi etc.
+ (when-let ((tag (save-excursion (sgml-beginning-of-tag)))
+ (params (seq-filter #'consp (cdr (assoc tag html-tag-alist))))
+ (param (save-excursion
+ (and (looking-back
+ "[ \t\n]\\([^= \t\n]+\\)=\\([^= \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1))))
+ (values (cdr (assoc param params))))
+ (list (match-beginning 2) (point)
+ (mapcar #'car values)))))
+
(defun html-mode--html-yank-handler (_type html)
(save-restriction
(insert html)
diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el
new file mode 100644
index 00000000000..53850674ac0
--- /dev/null
+++ b/lisp/textmodes/string-edit.el
@@ -0,0 +1,136 @@
+;;; string-edit.el --- editing long strings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defface string-edit-prompt
+ '((t (:inherit font-lock-comment-face)))
+ "Face used on `string-edit' help text."
+ :group 'text
+ :version "29.1")
+
+(defvar string-edit--success-callback)
+(defvar string-edit--abort-callback)
+
+;;;###autoload
+(cl-defun string-edit (prompt string success-callback
+ &key abort-callback)
+ "Switch to a new buffer to edit STRING.
+When the user finishes editing (with \\<string-edit-mode-map>\\[string-edit-done]), SUCCESS-CALLBACK
+is called with the resulting string.
+
+If the user aborts (with \\<string-edit-mode-map>\\[string-edit-abort]), ABORT-CALLBACK (if any) is
+called with no parameters.
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If PROMPT is nil, no help text
+will be inserted."
+ (with-current-buffer (generate-new-buffer "*edit string*")
+ (when prompt
+ (let ((inhibit-read-only t))
+ (insert prompt)
+ (ensure-empty-lines 0)
+ (add-text-properties (point-min) (point)
+ (list 'intangible t
+ 'face 'string-edit-prompt
+ 'read-only t))
+ (insert (propertize (make-separator-line) 'rear-nonsticky t))
+ (add-text-properties (point-min) (point)
+ (list 'string-edit--prompt t))))
+ (let ((start (point)))
+ (insert string)
+ (goto-char start))
+
+ ;; Use `fit-window-to-buffer' after the buffer is filled with text.
+ (pop-to-buffer (current-buffer)
+ '(display-buffer-below-selected
+ (window-height . (lambda (window)
+ (fit-window-to-buffer window nil 10)))))
+
+ (set-buffer-modified-p nil)
+ (setq buffer-undo-list nil)
+ (string-edit-mode)
+ (setq-local string-edit--success-callback success-callback)
+ (when abort-callback
+ (setq-local string-edit--abort-callback abort-callback))
+ (setq-local header-line-format
+ (substitute-command-keys
+ "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing or \\[string-edit-abort] to abort"))
+ (message "%s" (substitute-command-keys
+ "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing"))))
+
+;;;###autoload
+(defun read-string-from-buffer (prompt string)
+ "Switch to a new buffer to edit STRING in a recursive edit.
+The user finishes editing with \\<string-edit-mode-map>\\[string-edit-done], or aborts with \\<string-edit-mode-map>\\[string-edit-abort]).
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If nil, no prompt will be
+inserted in the buffer."
+ (string-edit
+ prompt
+ string
+ (lambda (edited)
+ (setq string edited)
+ (exit-recursive-edit))
+ :abort-callback (lambda ()
+ (exit-recursive-edit)
+ (error "Aborted edit")))
+ (recursive-edit)
+ string)
+
+(defvar-keymap string-edit-mode-map
+ "C-c C-c" #'string-edit-done
+ "C-c C-k" #'string-edit-abort)
+
+(define-derived-mode string-edit-mode text-mode "String"
+ "Mode for editing strings."
+ :interactive nil)
+
+(defun string-edit-done ()
+ "Finish editing the string and call the callback function.
+This will kill the current buffer."
+ (interactive)
+ (goto-char (point-min))
+ ;; Skip past the help text.
+ (when-let ((match (text-property-search-forward
+ 'string-edit--prompt nil t)))
+ (goto-char (prop-match-beginning match)))
+ (let ((string (buffer-substring (point) (point-max)))
+ (callback string-edit--success-callback))
+ (quit-window 'kill)
+ (funcall callback string)))
+
+(defun string-edit-abort ()
+ "Abort editing the current string."
+ (interactive)
+ (let ((callback string-edit--abort-callback))
+ (quit-window 'kill)
+ (when callback
+ (funcall callback))))
+
+(provide 'string-edit)
+
+;;; string-edit.el ends here
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 2175900194c..fc06c4c0da1 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -753,6 +753,18 @@ the cell contents dynamically."
:type 'string
:group 'table)
+(defcustom table-latex-environment "tabular"
+ "Tabular-compatible environment to use when generating latex.
+The value should be a string suitable for use as a LaTeX environment
+that's compatible with the \"tabular\" protocol, such as \"tabular\"
+and \"longtable\"."
+ :tag "Latex environment used to export tables"
+ :type '(choice
+ (const :tag "tabular" "tabular")
+ (const :tag "longtable" "longtable")
+ string)
+ :version "29.1")
+
(defcustom table-cals-thead-rows 1
"Number of top rows to become header rows in CALS table."
:tag "CALS Header Rows"
@@ -3025,7 +3037,8 @@ CALS (DocBook DTD):
"")))
((eq language 'latex)
(insert (format "%% This LaTeX table template is generated by emacs %s\n" emacs-version)
- "\\begin{tabular}{|" (apply #'concat (make-list (length col-list) "l|")) "}\n"
+ "\\begin{" table-latex-environment "}{|"
+ (apply #'concat (make-list (length col-list) "l|")) "}\n"
"\\hline\n"))
((eq language 'cals)
(insert (format "<!-- This CALS table template is generated by emacs %s -->\n" emacs-version)
@@ -3051,7 +3064,7 @@ CALS (DocBook DTD):
((eq language 'html)
(insert "</table>\n"))
((eq language 'latex)
- (insert "\\end{tabular}\n"))
+ (insert "\\end{" table-latex-environment "}\n"))
((eq language 'cals)
(set-marker-insertion-type (table-get-source-info 'colspec-marker) t) ;; insert before
(save-excursion
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 1925d93d93a..d34133f8564 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -248,9 +248,9 @@ Normally set to either `plain-tex-mode' or `latex-mode'."
(defcustom tex-fontify-script t
"If non-nil, fontify subscript and superscript strings."
:type 'boolean
+ :safe #'booleanp
:group 'tex
:version "23.1")
-(put 'tex-fontify-script 'safe-local-variable #'booleanp)
(defcustom tex-font-script-display '(-0.2 0.2)
"How much to lower and raise subscript and superscript content.
@@ -505,7 +505,9 @@ An alternative value is \" . \", if you use a font with a narrow period."
"documentstyle" "documentclass" "verbatiminput"
"includegraphics" "includegraphics*")
t))
- (verbish (regexp-opt '("url" "nolinkurl" "path") t))
+ (verbish (regexp-opt '("url" "nolinkurl" "path"
+ "href" "ProvidesFile")
+ t))
;; Miscellany.
(slash "\\\\")
(opt " *\\(\\[[^]]*\\] *\\)*")
@@ -981,14 +983,13 @@ Inherits `shell-mode-map' with a few additions.")
(when (and slash (not comment))
(setq mode
(if (looking-at
- (eval-when-compile
- (concat
- (regexp-opt '("documentstyle" "documentclass"
- "begin" "subsection" "section"
- "part" "chapter" "newcommand"
- "renewcommand" "RequirePackage")
- 'words)
- "\\|NeedsTeXFormat{LaTeX")))
+ (concat
+ (regexp-opt '("documentstyle" "documentclass"
+ "begin" "subsection" "section"
+ "part" "chapter" "newcommand"
+ "renewcommand" "RequirePackage")
+ 'words)
+ "\\|NeedsTeXFormat{LaTeX"))
(if (and (looking-at
"document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
;; SliTeX is almost never used any more nowadays.
@@ -1176,12 +1177,7 @@ subshell is initiated, `tex-shell-hook' is run."
(setq-local outline-regexp latex-outline-regexp)
(setq-local outline-level #'latex-outline-level)
(setq-local forward-sexp-function #'latex-forward-sexp)
- (setq-local skeleton-end-hook nil)
- (setq-local comment-region-function #'latex--comment-region)
- (setq-local comment-style 'plain))
-
-(defun latex--comment-region (beg end &optional arg)
- (comment-region-default-1 beg end arg t))
+ (setq-local skeleton-end-hook nil))
;;;###autoload
(define-derived-mode slitex-mode latex-mode "SliTeX"
@@ -1245,11 +1241,10 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
(apply-partially
#'tildify-foreach-ignore-environments
`(("\\\\\\\\" . "") ; do not remove this
- (,(eval-when-compile
- (concat "\\\\begin{\\("
- (regexp-opt '("verbatim" "math" "displaymath"
- "equation" "eqnarray" "eqnarray*"))
- "\\)}"))
+ (,(concat "\\\\begin{\\("
+ (regexp-opt '("verbatim" "math" "displaymath"
+ "equation" "eqnarray" "eqnarray*"))
+ "\\)}")
. ("\\\\end{" 1 "}"))
("\\\\verb\\*?\\(.\\)" . (1))
("\\$\\$?" . (0))
@@ -2129,11 +2124,10 @@ If NOT-ALL is non-nil, save the `.dvi' file."
(defvar tex-compile-history nil)
(defvar tex-input-files-re
- (eval-when-compile
- (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
- "bbl" "ind" "sty" "cls") t)
- ;; Include files with no dots (for directories).
- "\\'\\|\\`[^.]+\\'")))
+ (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
+ "bbl" "ind" "sty" "cls") t)
+ ;; Include files with no dots (for directories).
+ "\\'\\|\\`[^.]+\\'"))
(defcustom tex-use-reftex t
"If non-nil, use RefTeX's list of files to determine what command to use."
@@ -2987,13 +2981,7 @@ There might be text before point."
(put-text-property
(1- (match-beginning 1)) (match-beginning 1)
'syntax-table
- (if (= (1+ (line-beginning-position)) (match-beginning 1))
- ;; The `%' is a single-char comment, which Emacs
- ;; syntax-table can't deal with. We could turn it
- ;; into a non-comment, or use `\n%' or `%^' as the comment.
- ;; Instead, we include it in the ^^A comment.
- (string-to-syntax "< b")
- (string-to-syntax ">")))
+ (string-to-syntax ">"))
(let ((end (line-end-position)))
(if (< end (point-max))
(put-text-property
@@ -3016,8 +3004,9 @@ There might be text before point."
(defconst doctex-syntax-propertize-rules
(syntax-propertize-precompile-rules
latex-syntax-propertize-rules
- ;; For DocTeX comment-in-doc.
- ("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
+ ;; For DocTeX comment-in-doc (DocTeX ≥3 also allows ^^X).
+ ;; We make the comment start on the second char because of bug#35140.
+ ("\\^\\(\\^\\)[AX]" (1 (doctex-font-lock-^^A))))))
(defvar doctex-font-lock-keywords
(append tex-font-lock-keywords
@@ -3566,28 +3555,122 @@ There might be text before point."
("\\ordmasculine" . ?º)
("\\lambdabar" . ?ƛ)
("\\celsius" . ?℃)
+ ;; Text symbols formerly part of textcomp package:
+ ("\\textdollar" . ?$)
+ ("\\textborn" . ?*)
+ ("\\textless" . ?<)
+ ("\\textgreater" . ?>)
+ ("\\textbackslash" . ?\\)
+ ("\\textasciicircum" . ?^)
+ ("\\textunderscore" . ?_)
+ ("\\textbraceleft" . ?\{)
+ ("\\textbar" . ?|)
+ ("\\textbraceright" . ?\})
+ ("\\textasciitilde" . ?~)
+ ("\\textexclamdown" . ?¡)
+ ("\\textcent" . ?¢)
+ ("\\textsterling" . ?£)
+ ("\\textcurrency" . ?¤)
+ ("\\textyen" . ?¥)
+ ("\\textbrokenbar" . ?¦)
+ ("\\textsection" . ?§)
+ ("\\textasciidieresis" . ?¨)
+ ("\\textcopyright" . ?©)
+ ("\\textordfeminine" . ?ª)
+ ("\\guillemetleft" . ?«)
+ ("\\guillemotleft" . ?«)
+ ("\\textlnot" . ?¬)
+ ("\\textregistered" . ?®)
+ ("\\textasciimacron" . ?¯)
+ ("\\textdegree" . ?°)
+ ("\\textpm" . ?±)
+ ("\\texttwosuperior" . ?²)
+ ("\\textthreesuperior" . ?³)
+ ("\\textasciiacute" . ?´)
("\\textmu" . ?µ)
+ ("\\textparagraph" . ?¶)
+ ("\\textpilcrow" . ?¶)
+ ("\\textperiodcentered" . ?·)
+ ("\\textonesuperior" . ?¹)
+ ("\\textordmasculine" . ?º)
+ ("\\guillemetright" . ?»)
+ ("\\guillemotright" . ?»)
+ ("\\textonequarter" . ?¼)
+ ("\\textonehalf" . ?½)
+ ("\\textthreequarters" . ?¾)
+ ("\\textquestiondown" . ?¿)
+ ("\\texttimes" . ?×)
+ ("\\textdiv" . ?÷)
+ ("\\textflorin" . ?ƒ)
+ ("\\textasciicaron" . ?ˇ)
+ ("\\textasciibreve" . ?˘)
+ ("\\textacutedbl" . ?˝)
+ ("\\textgravedbl" . 757)
+ ("\\texttildelow" . 759)
+ ("\\textbaht" . ?฿)
+ ("\\textendash" . ?–)
+ ("\\textemdash" . ?—)
+ ("\\textbardbl" . ?‖)
+ ("\\textquoteleft" . 8216)
+ ("\\textquoteright" . 8217)
+ ("\\quotesinglbase" . 8218)
+ ("\\textquotedblleft" . 8220)
+ ("\\textquotedblright" . 8221)
+ ("\\quotedblbase" . 8222)
+ ;; \textdagger and \textdied are replaced with DAGGER (#x2020) and
+ ;; not with LATIN CROSS (#x271d)
+ ("\\textdagger" . ?†)
+ ("\\textdied" . ?†)
+ ("\\textdaggerdbl" . ?‡)
+ ("\\textbullet" . ?•)
+ ("\\textellipsis" . ?…)
+ ("\\textperthousand" . ?‰)
+ ("\\textpertenthousand" . ?‱)
+ ("\\guilsinglleft" . ?‹)
+ ("\\guilsinglright" . ?›)
+ ("\\textreferencemark" . ?※)
+ ("\\textinterrobang" . ?‽)
("\\textfractionsolidus" . ?⁄)
- ("\\textbigcircle" . ?⃝)
- ("\\textmusicalnote" . ?♪)
- ("\\textdied" . ?✝)
+ ("\\textlquill" . 8261) ; Literal ?⁅ breaks indentation
+ ("\\textrquill" . 8262) ; Literal ?⁆ breaks indentation
+ ("\\textdiscount" . ?⁒)
("\\textcolonmonetary" . ?₡)
- ("\\textwon" . ?₩)
+ ("\\textlira" . ?₤)
("\\textnaira" . ?₦)
+ ("\\textwon" . ?₩)
+ ("\\textdong" . ?₫)
+ ("\\texteuro" . ?€)
("\\textpeso" . ?₱)
- ("\\textlira" . ?₤)
- ("\\textrecipe" . ?℞)
- ("\\textinterrobang" . ?‽)
- ("\\textpertenthousand" . ?‱)
- ("\\textbaht" . ?฿)
+ ("\\textguarani" . ?₲)
+ ("\\textcelsius" . ?℃)
("\\textnumero" . ?№)
- ("\\textdiscount" . ?⁒)
+ ("\\textcircledP" . ?℗)
+ ("\\textrecipe" . ?℞)
+ ("\\textservicemark" . ?℠)
+ ("\\texttrademark" . ?™)
+ ("\\textohm" . ?Ω)
+ ("\\textmho" . ?℧)
("\\textestimated" . ?℮)
+ ("\\textleftarrow" . ?←)
+ ("\\textuparrow" . ?↑)
+ ("\\textrightarrow" . ?→)
+ ("\\textdownarrow" . ?↓)
+ ("\\textminus" . ?−)
+ ("\\textsurd" . ?√)
+ ("\\textlangle" . 9001) ; Literal ?〈 breaks indentation
+ ("\\textrangle" . 9002) ; Literal ?〉 breaks indentation
+ ("\\textblank" . ?␢)
+ ("\\textvisiblespace" . ?␣)
("\\textopenbullet" . ?◦)
- ("\\textlquill" . 8261) ; Literal ?⁅ breaks indentation.
- ("\\textrquill" . 8262) ; Literal ?⁆ breaks indentation.
- ("\\textcircledP" . ?℗)
- ("\\textreferencemark" . ?※))
+ ;; \textbigcircle is replaced with LARGE CIRCLE (#x25ef) and not
+ ;; with COMBINING ENCLOSING CIRCLE (#x20dd)
+ ("\\textbigcircle" . ?◯)
+ ("\\textmusicalnote" . ?♪)
+ ("\\textmarried" . ?⚭)
+ ("\\textdivorced" . ?⚮)
+ ("\\textlbrackdbl" . 10214) ; Literal ?⟦ breaks indentation
+ ("\\textrbrackdbl" . 10215) ; Literal ?⟧ breaks indentation
+ ("\\textinterrobangdown" . ?⸘))
"A `prettify-symbols-alist' usable for (La)TeX modes.")
(defun tex--prettify-symbols-compose-p (_start end _match)
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 7f6ed3d1da9..5d6f5deae1b 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -31,6 +31,16 @@
;;; Code:
+(eval-when-compile (require 'cl-lib)
+ (require 'flymake)
+ (require 'rx))
+(declare-function flymake-diag-region "flymake"
+ (buffer line &optional col))
+(declare-function flymake-make-diagnostic "flymake"
+ ( locus beg end type text
+ &optional data overlay-properties))
+(declare-function flymake--log-1 "flymake" (level sublog msg &rest args))
+
(eval-when-compile (require 'tex-mode))
(declare-function tex-buffer "tex-mode" ())
(declare-function tex-region "tex-mode" (beg end))
@@ -335,6 +345,69 @@ Subexpression 1 is what goes into the corresponding `@end' statement.")
(if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
(match-string-no-properties 1))))
+;;; Flymake support
+(defvar-local texinfo--flymake-proc nil)
+(defun texinfo-flymake (report-fn &rest _)
+ "Texinfo checking for Flymake.
+
+REPORT-FN is the callback function."
+ (let ((executable (or (executable-find "makeinfo")
+ (executable-find "texi2any")))
+ (source (current-buffer)))
+
+ (unless executable
+ (error "Flymake for Texinfo requires `makeinfo' or `texi2any'"))
+
+ (when (process-live-p texinfo--flymake-proc)
+ (kill-process texinfo--flymake-proc))
+
+ (save-restriction
+ (widen)
+ (setq texinfo--flymake-proc
+ (make-process
+ :name "texinfo-flymake"
+ :noquery t
+ :connection-type 'pipe
+ :buffer (generate-new-buffer " *texinfo-flymake*")
+ :command `(,executable "-o" ,null-device "-")
+ :sentinel
+ (lambda (proc _event)
+ (when (memq (process-status proc) '(exit signal))
+ (unwind-protect
+ (if (eq (buffer-local-value 'texinfo--flymake-proc
+ source)
+ proc)
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ (cl-loop
+ while (search-forward-regexp
+ (rx line-start
+ "-:"
+ (group-n 1 (0+ digit)) ; Line
+ (optional ":" (group-n 2 (0+ digit))) ; col
+ ": "
+ (optional (group-n 3 "warning: ")) ; warn
+ (group-n 4 (0+ nonl)) ; Message
+ line-end)
+ nil t)
+ for msg = (match-string 4)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 1)))
+ for type = (if (match-string 3)
+ :warning
+ :error)
+ collect (flymake-make-diagnostic
+ source beg end type msg)
+ into diags
+ finally (funcall report-fn diags)))
+ (flymake-log :warning "Cancelling obsolete check %s"
+ proc))
+ (kill-buffer (process-buffer proc)))))))
+ (process-send-region texinfo--flymake-proc (point-min) (point-max))
+ (process-send-eof texinfo--flymake-proc))))
+
+
;;; Texinfo mode
;;;###autoload
@@ -454,7 +527,10 @@ value of `texinfo-mode-hook'."
(let ((prevent-filling "^@\\(def\\|multitable\\)"))
(if (null auto-fill-inhibit-regexp)
prevent-filling
- (concat auto-fill-inhibit-regexp "\\|" prevent-filling)))))
+ (concat auto-fill-inhibit-regexp "\\|" prevent-filling))))
+
+ ;; Set up Flymake support.
+ (add-hook 'flymake-diagnostic-functions #'texinfo-flymake nil t))
(defvar texinfo-fillable-commands '("@noindent")
"A list of commands that can be filled.")
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
index 5b468dc808b..e44aa06e3dd 100644
--- a/lisp/textmodes/texnfo-upd.el
+++ b/lisp/textmodes/texnfo-upd.el
@@ -1367,7 +1367,7 @@ left at the end of the node line."
;; There may be an @chapter or other such command between
;; the top node line and the next node line, as a title
;; for an `ifinfo' section. This @chapter command must
- ;; must be skipped. So the procedure is to search for
+ ;; be skipped. So the procedure is to search for
;; the next `@node' line, and then copy its name.
(if (re-search-forward "^@node" nil t)
(progn
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 9dcfb10d6df..2a7ad295ab7 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -494,9 +494,8 @@ variable will be set to the representation."
(if (not (string-equal " " (or space tildify-space-string)))
(when space
(setq tildify-space-string space))
- (message (eval-when-compile
- (concat "Hard space is a single space character, tildify-"
- "mode won't have any effect, disabling.")))
+ (message (concat "Hard space is a single space character, tildify-"
+ "mode won't have any effect, disabling."))
(setq tildify-mode nil))))
(if tildify-mode
(add-hook 'post-self-insert-hook #'tildify-space nil t)
diff --git a/lisp/textmodes/word-wrap-mode.el b/lisp/textmodes/word-wrap-mode.el
new file mode 100644
index 00000000000..c354fc773a7
--- /dev/null
+++ b/lisp/textmodes/word-wrap-mode.el
@@ -0,0 +1,80 @@
+;;; word-wrap-mode.el --- minor mode for `word-wrap' tweaks -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+;; The list below lists all characters that have a general-category of
+;; Zs, but with the ones we don't want to add here commented out.
+(defcustom word-wrap-whitespace-characters
+ '(;;?\N{SPACE}
+ ;;?\N{NO-BREAK SPACE}
+ ?\N{OGHAM SPACE MARK}
+ ?\N{EN QUAD}
+ ?\N{EM QUAD}
+ ?\N{EN SPACE}
+ ?\N{EM SPACE}
+ ?\N{THREE-PER-EM SPACE}
+ ?\N{FOUR-PER-EM SPACE}
+ ?\N{SIX-PER-EM SPACE}
+ ?\N{FIGURE SPACE}
+ ?\N{PUNCTUATION SPACE}
+ ?\N{THIN SPACE}
+ ?\N{HAIR SPACE}
+ ;;?\N{NARROW NO-BREAK SPACE}
+ ?\N{MEDIUM MATHEMATICAL SPACE}
+ ?\N{IDEOGRAPHIC SPACE}
+ ;; Not in the Zs category:
+ ?\N{ZERO WIDTH SPACE})
+ "Characters that `word-wrap-whitespace-mode' should add to `word-wrap'."
+ :version "29.1"
+ :type '(repeat character)
+ :group 'display)
+
+(defvar word-wrap-mode--previous-state)
+
+;;;###autoload
+(define-minor-mode word-wrap-whitespace-mode
+ "Allow `word-wrap' to fold on all breaking whitespace characters.
+The characters to break on are defined by `word-wrap-whitespace-characters'."
+ :group 'display
+ (if word-wrap-whitespace-mode
+ (progn
+ (setq-local word-wrap-mode--previous-state
+ (cons (category-table)
+ (buffer-local-set-state
+ word-wrap-by-category t
+ word-wrap t)))
+ (set-category-table (copy-category-table))
+ (dolist (char word-wrap-whitespace-characters)
+ (modify-category-entry char ?|)))
+ (set-category-table (car word-wrap-mode--previous-state))
+ (buffer-local-restore-state (cdr word-wrap-mode--previous-state))))
+
+;;;###autoload
+(define-globalized-minor-mode global-word-wrap-whitespace-mode
+ word-wrap-whitespace-mode word-wrap-whitespace-mode
+ :group 'display)
+
+(provide 'word-wrap-mode)
+
+;;; word-wrap-mode.el ends here
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 045264528ff..b3dca5890f1 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -82,7 +82,7 @@ question.
(defun forward-thing (thing &optional n)
"Move forward to the end of the Nth next THING.
THING should be a symbol specifying a type of syntactic entity.
-Possibilities include `symbol', `list', `sexp', `defun',
+Possibilities include `symbol', `list', `sexp', `defun', `number',
`filename', `url', `email', `uuid', `word', `sentence', `whitespace',
`line', and `page'."
(let ((forward-op (or (get thing 'forward-op)
@@ -97,7 +97,7 @@ Possibilities include `symbol', `list', `sexp', `defun',
(defun bounds-of-thing-at-point (thing)
"Determine the start and end buffer locations for the THING at point.
THING should be a symbol specifying a type of syntactic entity.
-Possibilities include `symbol', `list', `sexp', `defun',
+Possibilities include `symbol', `list', `sexp', `defun', `number',
`filename', `url', `email', `uuid', `word', `sentence', `whitespace',
`line', and `page'.
@@ -508,14 +508,14 @@ If no URL is found, return nil.
If optional argument LAX is non-nil, look for URLs that are not
well-formed, such as foo@bar or <nobody>.
-If optional arguments BOUNDS are non-nil, it should be a cons
+If optional argument BOUNDS is non-nil, it should be a cons
cell of the form (START . END), containing the beginning and end
positions of the URI. Otherwise, these positions are detected
automatically from the text around point.
If the scheme component is absent, either because a URI delimited
with <url:...> lacks one, or because an ill-formed URI was found
-with LAX or BEG and END, try to add a scheme in the returned URI.
+with LAX or BOUNDS, try to add a scheme in the returned URI.
The scheme is chosen heuristically: \"mailto:\" if the address
looks like an email address, \"ftp://\" if it starts with
\"ftp\", etc."
@@ -732,6 +732,7 @@ Signal an error if the entire string was not used."
"Return the symbol at point, or nil if none is found."
(let ((thing (thing-at-point 'symbol)))
(if thing (intern thing))))
+
;;;###autoload
(defun number-at-point ()
"Return the number at point, or nil if none is found.
@@ -746,7 +747,9 @@ like \"0xBEEF09\" or \"#xBEEF09\", are recognized."
(string-to-number
(buffer-substring (match-beginning 0) (match-end 0))))))
+(put 'number 'forward-op 'forward-word)
(put 'number 'thing-at-point 'number-at-point)
+
;;;###autoload
(defun list-at-point (&optional ignore-comment-or-string)
"Return the Lisp list at point, or nil if none is found.
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index 695fa8a8562..158597d7c8c 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -73,16 +73,16 @@
(defcustom thumbs-per-line 4
"Number of thumbnails per line to show in directory."
- :type 'integer)
+ :type 'natnum)
(defcustom thumbs-max-image-number 16
- "Maximum number of images initially displayed in thumbs buffer."
- :type 'integer)
+ "Maximum number of images initially displayed in thumbs buffer."
+ :type 'natnum)
(defcustom thumbs-thumbsdir-max-size 50000000
"Maximum size for thumbnails directory.
-When it reaches that size (in bytes), a warning is sent."
- :type 'integer)
+When it reaches that size (in bytes), a warning is displayed."
+ :type 'natnum)
;; Unfortunately Windows XP has a program called CONVERT.EXE in
;; C:/WINDOWS/SYSTEM32/ for partitioning NTFS systems. So Emacs
@@ -106,12 +106,12 @@ This must be the ImageMagick \"convert\" utility."
(defcustom thumbs-relief 5
"Size of button-like border around thumbnails."
- :type 'integer)
+ :type 'natnum)
(defcustom thumbs-margin 2
"Size of the margin around thumbnails.
This is where you see the cursor."
- :type 'integer)
+ :type 'natnum)
(defcustom thumbs-thumbsdir-auto-clean t
"If set, delete older file in the thumbnails directory.
@@ -121,7 +121,7 @@ than `thumbs-thumbsdir-max-size'."
(defcustom thumbs-image-resizing-step 10
"Step by which to resize image as a percentage."
- :type 'integer)
+ :type 'natnum)
(defcustom thumbs-temp-dir temporary-file-directory
"Temporary directory to use.
@@ -215,16 +215,17 @@ FILEIN is the input file,
FILEOUT is the output file,
ACTION is the command to send to convert.
Optional arguments are:
-ARG any arguments to the ACTION command,
+ARG if non-nil, the argument of the ACTION command,
OUTPUT-FORMAT is the file format to output (default is jpeg),
ACTION-PREFIX is the symbol to place before the ACTION command
(defaults to `-' but can sometimes be `+')."
- (call-process thumbs-conversion-program nil nil nil
- (or action-prefix "-")
- action
- (or arg "")
- filein
- (format "%s:%s" (or output-format "jpeg") fileout)))
+ (let ((action-param (concat (or action-prefix "-") action))
+ (fileout-param (format "%s:%s" (or output-format "jpeg") fileout)))
+ (if arg
+ (call-process thumbs-conversion-program nil nil nil
+ action-param arg filein fileout-param)
+ (call-process thumbs-conversion-program nil nil nil
+ action-param filein fileout-param))))
(defun thumbs-new-image-size (s increment)
"New image (a cons of width x height)."
@@ -296,7 +297,8 @@ smaller according to whether INCREMENT is 1 or -1."
(defun thumbs-file-size (img)
(let ((i (image-size
- (find-image `((:type ,(image-type-from-file-name img) :file ,img))) t)))
+ (find-image `((:type ,(image-supported-file-p img) :file ,img)))
+ t)))
(concat (number-to-string (round (car i))) "x"
(number-to-string (round (cdr i))))))
@@ -399,7 +401,7 @@ and SAME-WINDOW to show thumbs in the same window."
thumbs-image-num (or num 0))
(delete-region (point-min)(point-max))
(save-excursion
- (thumbs-insert-image img (image-type-from-file-name img) 0)))))
+ (thumbs-insert-image img (image-supported-file-p img) 0)))))
(defun thumbs-find-image-at-point (&optional img otherwin)
"Display image IMG for thumbnail at point.
@@ -533,7 +535,7 @@ Open another window."
" - " (number-to-string num)))
(let ((inhibit-read-only t))
(erase-buffer)
- (thumbs-insert-image img (image-type-from-file-name img) 0)
+ (thumbs-insert-image img (image-supported-file-p img) 0)
(goto-char (point-min))))
(setq thumbs-image-num num
thumbs-current-image-filename img))))
@@ -609,7 +611,7 @@ ACTION and ARG should be a valid convert command."
(thumbs-call-convert (or old thumbs-current-image-filename)
tmp
action
- (or arg ""))
+ arg)
(save-excursion
(thumbs-insert-image tmp 'jpeg 0))
(setq thumbs-current-tmp-filename tmp)))
@@ -765,7 +767,7 @@ ACTION and ARG should be a valid convert command."
(define-key dired-mode-map "\C-tw" 'thumbs-dired-setroot)
(define-obsolete-function-alias 'thumbs-image-type
- #'image-type-from-file-name "29.1")
+ #'image-supported-file-p "29.1")
(provide 'thumbs)
diff --git a/lisp/time.el b/lisp/time.el
index cd985bfb288..e7066cae7a5 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -93,7 +93,7 @@ Non-nil means \\[display-time] should display day and date as well as time."
(defcustom display-time-interval 60
"Seconds between updates of time in the mode line."
- :type 'integer)
+ :type 'natnum)
(defcustom display-time-24hr-format nil
"Non-nil indicates time should be displayed as hh:mm, 0 <= hh <= 23.
@@ -519,7 +519,7 @@ If the value is t instead of an alist, use the value of
(defcustom world-clock-timer-second 60
"Interval in seconds for updating the `world-clock' buffer."
- :type 'integer
+ :type 'natnum
:version "28.1")
(defface world-clock-label
diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el
index 7ec5c0beccc..82b458e0107 100644
--- a/lisp/tool-bar.el
+++ b/lisp/tool-bar.el
@@ -89,15 +89,29 @@ functions.")
(declare-function image-mask-p "image.c" (spec &optional frame))
-(defconst tool-bar-keymap-cache (make-hash-table :weakness t :test 'equal))
+(defconst tool-bar-keymap-cache (make-hash-table :test #'equal))
+
+(defun tool-bar--cache-key ()
+ (cons (frame-terminal) (sxhash-eq tool-bar-map)))
+
+(defun tool-bar--flush-cache ()
+ "Remove all cached entries that refer to the current `tool-bar-map'."
+ (let ((id (sxhash-eq tool-bar-map))
+ (entries nil))
+ (maphash (lambda (k _)
+ (when (equal (cdr k) id)
+ (push k entries)))
+ tool-bar-keymap-cache)
+ (dolist (k entries)
+ (remhash k tool-bar-keymap-cache))))
(defun tool-bar-make-keymap (&optional _ignore)
"Generate an actual keymap from `tool-bar-map'.
Its main job is to figure out which images to use based on the display's
color capability and based on the available image libraries."
- (let ((key (cons (frame-terminal) tool-bar-map)))
- (or (gethash key tool-bar-keymap-cache)
- (puthash key (tool-bar-make-keymap-1) tool-bar-keymap-cache))))
+ (or (gethash (tool-bar--cache-key) tool-bar-keymap-cache)
+ (setf (gethash (tool-bar--cache-key) tool-bar-keymap-cache)
+ (tool-bar-make-keymap-1))))
(defun tool-bar-make-keymap-1 ()
"Generate an actual keymap from `tool-bar-map', without caching."
@@ -139,7 +153,8 @@ ICON.xbm, using `find-image'.
Use this function only to make bindings in the global value of `tool-bar-map'.
To define items in any other map, use `tool-bar-local-item'."
- (apply #'tool-bar-local-item icon def key tool-bar-map props))
+ (apply #'tool-bar-local-item icon def key tool-bar-map props)
+ (tool-bar--flush-cache))
(defun tool-bar--image-expression (icon)
"Return an expression that evaluates to an image spec for ICON."
@@ -177,6 +192,7 @@ ICON.xbm, using `find-image'."
(let* ((image-exp (tool-bar--image-expression icon)))
(define-key-after map (vector key)
`(menu-item ,(symbol-name key) ,def :image ,image-exp ,@props))
+ (tool-bar--flush-cache)
(force-mode-line-update)))
;;;###autoload
@@ -243,6 +259,7 @@ holds a keymap."
(setq rest (cdr rest)))
(append `(menu-item ,(car defn) ,rest)
(list :image image-exp) props))))
+ (tool-bar--flush-cache)
(force-mode-line-update))))
;;; Set up some global items. Additions/deletions up for grabs.
diff --git a/lisp/tooltip.el b/lisp/tooltip.el
index 1cf16fdb5d2..95cb1cc62c0 100644
--- a/lisp/tooltip.el
+++ b/lisp/tooltip.el
@@ -58,9 +58,11 @@ echo area, instead of making a pop-up window."
(if (and tooltip-mode (fboundp 'x-show-tip))
(progn
(add-hook 'pre-command-hook 'tooltip-hide)
- (add-hook 'tooltip-functions 'tooltip-help-tips))
+ (add-hook 'tooltip-functions 'tooltip-help-tips)
+ (add-hook 'x-pre-popup-menu-hook 'tooltip-hide))
(unless (and (boundp 'gud-tooltip-mode) gud-tooltip-mode)
- (remove-hook 'pre-command-hook 'tooltip-hide))
+ (remove-hook 'pre-command-hook 'tooltip-hide)
+ (remove-hook 'x-pre-popup-menu-hook 'tooltip-hide))
(remove-hook 'tooltip-functions 'tooltip-help-tips))
(setq show-help-function
(if tooltip-mode 'tooltip-show-help 'tooltip-show-help-non-mode)))
@@ -138,15 +140,6 @@ When using the GTK toolkit, this face will only be used if
:group 'tooltip
:group 'basic-faces)
-(defcustom tooltip-use-echo-area nil
- "Use the echo area instead of tooltip frames for help and GUD tooltips.
-This variable is obsolete; instead of setting it to t, disable
-`tooltip-mode' (which has a similar effect)."
- :type 'boolean)
-
-(make-obsolete-variable 'tooltip-use-echo-area
- "disable Tooltip mode instead" "24.1" 'set)
-
(defcustom tooltip-resize-echo-area nil
"If non-nil, using the echo area for tooltips will resize the echo area.
By default, when the echo area is used for displaying tooltips,
@@ -228,25 +221,42 @@ change the existing association. Value is the resulting alist."
(declare-function x-show-tip "xfns.c"
(string &optional frame parms timeout dx dy))
-(defun tooltip-show (text &optional use-echo-area)
+(defun tooltip-show (text &optional use-echo-area text-face default-face)
"Show a tooltip window displaying TEXT.
Text larger than `x-max-tooltip-size' is clipped.
-If the alist in `tooltip-frame-parameters' includes `left' and `top'
-parameters, they determine the x and y position where the tooltip
-is displayed. Otherwise, the tooltip pops at offsets specified by
-`tooltip-x-offset' and `tooltip-y-offset' from the current mouse
-position.
+If the alist in `tooltip-frame-parameters' includes `left' and
+`top' parameters, they determine the x and y position where the
+tooltip is displayed. Otherwise, the tooltip pops at offsets
+specified by `tooltip-x-offset' and `tooltip-y-offset' from the
+current mouse position.
+
+The text properties of TEXT are also modified to add the
+appropriate faces before displaying the tooltip. If your code
+depends on them, you should copy the tooltip string before
+passing it to this function.
Optional second arg USE-ECHO-AREA non-nil means to show tooltip
-in echo area."
+in echo area.
+
+The third and fourth args TEXT-FACE and DEFAULT-FACE specify
+faces used to display the tooltip, and default to `tooltip' if
+not specified. TEXT-FACE specifies a face used to display text
+in the tooltip, while DEFAULT-FACE specifies a face that provides
+the background, foreground and border colors of the tooltip
+frame.
+
+Note that the last two arguments are not respected when
+`use-system-tooltips' is non-nil and Emacs is built with support
+for system tooltips, such as on NS, Haiku, and with the GTK
+toolkit."
(if use-echo-area
(tooltip-show-help-non-mode text)
(condition-case error
(let ((params (copy-sequence tooltip-frame-parameters))
- (fg (face-attribute 'tooltip :foreground))
- (bg (face-attribute 'tooltip :background)))
+ (fg (face-attribute (or default-face 'tooltip) :foreground))
+ (bg (face-attribute (or default-face 'tooltip) :background)))
(when (stringp fg)
(setf (alist-get 'foreground-color params) fg)
(setf (alist-get 'border-color params) fg))
@@ -256,7 +266,8 @@ in echo area."
;; faces used in our TEXT. Among other things, this allows
;; tooltips to use the `help-key-binding' face used in
;; `substitute-command-keys' substitutions.
- (add-face-text-property 0 (length text) 'tooltip t text)
+ (add-face-text-property 0 (length text)
+ (or text-face 'tooltip) t text)
(x-show-tip text
(selected-frame)
params
@@ -339,6 +350,8 @@ This is used by `tooltip-show-help' and
(defvar tooltip-previous-message nil
"The previous content of the echo area.")
+(defvar haiku-use-system-tooltips)
+
(defun tooltip-show-help-non-mode (help)
"Function installed as `show-help-function' when Tooltip mode is off.
It is also called if Tooltip mode is on, for text-only displays."
@@ -374,8 +387,9 @@ It is also called if Tooltip mode is on, for text-only displays."
"Function installed as `show-help-function'.
MSG is either a help string to display, or nil to cancel the display."
(if (and (display-graphic-p)
- (or (not (eq window-system 'haiku)) ;; On Haiku, there isn't a reliable way to show tooltips
- ;; above menus.
+ ;; Tooltips can't be displayed on top of the global menu
+ ;; bar on NS.
+ (or (not (eq window-system 'ns))
(not (menu-or-popup-active-p))))
(let ((previous-help tooltip-help-message))
(setq tooltip-help-message msg)
@@ -383,9 +397,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
@@ -401,7 +418,7 @@ This is installed on the hook `tooltip-functions', which
is run when the timer with id `tooltip-timeout-id' fires.
Value is non-nil if this function handled the tip."
(when (stringp tooltip-help-message)
- (tooltip-show tooltip-help-message tooltip-use-echo-area)
+ (tooltip-show tooltip-help-message (not tooltip-mode))
t))
(provide 'tooltip)
diff --git a/lisp/transient.el b/lisp/transient.el
index 0d7f9d0317b..41b69b1abac 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
;; Author: Jonas Bernoulli <jonas@bernoul.li>
-;; Homepage: https://github.com/magit/transient
+;; URL: https://github.com/magit/transient
;; Keywords: bindings
;; Package-Requires: ((emacs "25.1"))
@@ -61,10 +61,10 @@
(eval-when-compile
(require 'subr-x))
-(declare-function info 'info)
-(declare-function Man-find-section 'man)
-(declare-function Man-next-section 'man)
-(declare-function Man-getpage-in-background 'man)
+(declare-function info "info")
+(declare-function Man-find-section "man")
+(declare-function Man-next-section "man")
+(declare-function Man-getpage-in-background "man")
(defvar Man-notify-method)
@@ -246,7 +246,7 @@ for infix argument are highlighted when only a long argument
In the rare case that a short-hand is specified but does not
match the key binding, then it is highlighed differently.
-The highlighting is done using using `transient-mismatched-key'
+The highlighting is done using `transient-mismatched-key'
and `transient-nonstandard-key'."
:package-version '(transient . "0.1.0")
:group 'transient
@@ -1384,7 +1384,7 @@ The optional argument COMMAND is intended for internal use. If
you are contemplating using it in your own code, then you should
probably use this instead:
- (get COMMAND 'transient--suffix)"
+ (get COMMAND \\='transient--suffix)"
(when command
(cl-check-type command command))
(if (or transient--prefix
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el
index 4ba96a36a47..f91b36bfc28 100644
--- a/lisp/tree-widget.el
+++ b/lisp/tree-widget.el
@@ -319,6 +319,7 @@ has been found accessible."
'(
("guide" . arrow)
("no-guide" . arrow)
+ ("nohandle-guide" . arrow)
("end-guide" . arrow)
("handle" . arrow)
("no-handle" . arrow)
@@ -440,6 +441,12 @@ Handle mouse button 1 click on buttons.")
:format "%t"
)
+(define-widget 'tree-widget-nohandle-guide 'item
+ "Vertical guide line, when there is no handle."
+ :tag " |"
+ ;;:tag-glyph (tree-widget-find-image "nohandle-guide")
+ :format "%t")
+
(define-widget 'tree-widget-end-guide 'item
"End of a vertical guide line."
:tag " \\=`"
@@ -483,6 +490,7 @@ Handle mouse button 1 click on buttons.")
:empty-icon 'tree-widget-empty-icon
:leaf-icon 'tree-widget-leaf-icon
:guide 'tree-widget-guide
+ :nohandle-guide 'tree-widget-nohandle-guide
:end-guide 'tree-widget-end-guide
:no-guide 'tree-widget-no-guide
:handle 'tree-widget-handle
@@ -612,11 +620,13 @@ This hook should be local in the buffer setup to display widgets.")
;;;; Expanded node.
(let ((args (widget-get tree :args))
(guide (widget-get tree :guide))
+ (nohandle-guide (widget-get tree :nohandle-guide))
(noguide (widget-get tree :no-guide))
(endguide (widget-get tree :end-guide))
(handle (widget-get tree :handle))
(nohandle (widget-get tree :no-handle))
(guidi (tree-widget-find-image "guide"))
+ (nohandle-guidi (tree-widget-find-image "nohandle-guide"))
(noguidi (tree-widget-find-image "no-guide"))
(endguidi (tree-widget-find-image "end-guide"))
(handli (tree-widget-find-image "handle"))
@@ -648,8 +658,8 @@ This hook should be local in the buffer setup to display widgets.")
;; Insert guide lines elements from previous levels.
(dolist (f (reverse flags))
(widget-create-child-and-convert
- tree (if f guide noguide)
- :tag-glyph (if f guidi noguidi))
+ tree (if f nohandle-guide noguide)
+ :tag-glyph (if f nohandle-guidi noguidi))
(widget-create-child-and-convert
tree nohandle :tag-glyph nohandli))
;; Insert guide line element for this level.
diff --git a/lisp/tutorial.el b/lisp/tutorial.el
index 2d313076e3a..2c787ae5595 100644
--- a/lisp/tutorial.el
+++ b/lisp/tutorial.el
@@ -385,7 +385,7 @@ correspond to what the tutorial says.\n\n")
"Find the key bindings used in the tutorial that have changed.
Return a list with elements of the form
- '(KEY DEF-FUN DEF-FUN-TXT WHERE REMARK QUIET)
+ (KEY DEF-FUN DEF-FUN-TXT WHERE REMARK QUIET)
where
@@ -649,13 +649,15 @@ with some explanatory links."
(unless (eq prop-val 'key-sequence)
(delete-region prop-start prop-end))))))
+(defvar tutorial--starting-point)
(defun tutorial--save-on-kill ()
"Query the user about saving the tutorial when killing Emacs."
(when (buffer-live-p tutorial--buffer)
(with-current-buffer tutorial--buffer
- (if (y-or-n-p "Save your position in the tutorial? ")
- (tutorial--save-tutorial-to (tutorial--saved-file))
- (message "Tutorial position not saved"))))
+ (unless (= (point) tutorial--starting-point)
+ (if (y-or-n-p "Save your position in the tutorial? ")
+ (tutorial--save-tutorial-to (tutorial--saved-file))
+ (message "Tutorial position not saved")))))
t)
(defun tutorial--save-tutorial ()
@@ -734,7 +736,6 @@ See `tutorial--save-tutorial' for more information."
(message "Can't save tutorial: %s is not a directory"
tutorial-dir)))))
-
;;;###autoload
(defun help-with-tutorial (&optional arg dont-ask-for-revert)
"Select the Emacs learn-by-doing tutorial.
@@ -914,6 +915,7 @@ Run the Viper tutorial? "))
(forward-line 1)
(newline (- n (/ n 2)))))
(goto-char (point-min)))
+ (setq-local tutorial--starting-point (point))
(setq buffer-undo-list nil)
(set-buffer-modified-p nil)))))
diff --git a/lisp/type-break.el b/lisp/type-break.el
index 267facccc47..dca5a43b893 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -69,7 +69,7 @@
(defcustom type-break-interval (* 60 60)
"Number of seconds between scheduled typing breaks."
- :type 'integer
+ :type 'natnum
:group 'type-break)
(defcustom type-break-good-rest-interval (/ type-break-interval 6)
@@ -82,7 +82,7 @@ rest from typing, then the next typing break is simply rescheduled for later.
If a break is interrupted before this much time elapses, the user will be
asked whether or not really to interrupt the break."
:set-after '(type-break-interval)
- :type 'integer
+ :type 'natnum
:group 'type-break)
(defcustom type-break-good-break-interval nil
@@ -148,7 +148,7 @@ To avoid being queried at all, set `type-break-query-mode' to nil."
"Number of seconds between queries to take a break, if put off.
The user will continue to be prompted at this interval until he or she
finally submits to taking a typing break."
- :type 'integer
+ :type 'natnum
:group 'type-break)
(defcustom type-break-time-warning-intervals '(300 120 60 30)
@@ -171,7 +171,7 @@ will occur."
"Number of keystrokes for which warnings should be repeated.
That is, for each of this many keystrokes the warning is redisplayed
in the echo area to make sure it's really seen."
- :type 'integer
+ :type 'natnum
:group 'type-break)
(defcustom type-break-time-stamp-format "[%H:%M] "
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index 2ef1f04f70d..0b7db9b54fb 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -128,7 +128,6 @@ you can set, browse the `uniquify' custom group."
"If non-nil, rerationalize buffer names after a buffer has been killed."
:type 'boolean)
-;; The default value matches certain Gnus buffers.
(defcustom uniquify-ignore-buffers-re nil
"Regular expression matching buffer names that should not be uniquified.
For instance, set this to \"^draft-[0-9]+$\" to avoid having uniquify rename
diff --git a/lisp/url/url-auth.el b/lisp/url/url-auth.el
index 585010d21c5..53cefb46e4b 100644
--- a/lisp/url/url-auth.el
+++ b/lisp/url/url-auth.el
@@ -87,11 +87,13 @@ instead of the filename inheritance method."
((and prompt (not byserv))
(setq user (or
(url-do-auth-source-search server type :user)
- (read-string (url-auth-user-prompt href realm)
- (or user (user-real-login-name))))
+ (and (url-interactive-p)
+ (read-string (url-auth-user-prompt href realm)
+ (or user (user-real-login-name)))))
pass (or
(url-do-auth-source-search server type :secret)
- (read-passwd "Password: " nil (or pass ""))))
+ (and (url-interactive-p)
+ (read-passwd "Password: " nil (or pass "")))))
(set url-basic-auth-storage
(cons (list server
(cons file
@@ -117,11 +119,13 @@ instead of the filename inheritance method."
(progn
(setq user (or
(url-do-auth-source-search server type :user)
- (read-string (url-auth-user-prompt href realm)
- (user-real-login-name)))
+ (and (url-interactive-p)
+ (read-string (url-auth-user-prompt href realm)
+ (user-real-login-name))))
pass (or
(url-do-auth-source-search server type :secret)
- (read-passwd "Password: "))
+ (and (url-interactive-p)
+ (read-passwd "Password: ")))
retval (base64-encode-string (format "%s:%s" user pass) t)
byserv (assoc server (symbol-value url-basic-auth-storage)))
(setcdr byserv
@@ -233,11 +237,13 @@ CREDS is a plist that may have properties `:user' and `:secret'."
;; plist-put modify the same plist.
(setq creds
(plist-put creds :user
- (read-string (url-auth-user-prompt url realm)
- (or (plist-get creds :user)
- (user-real-login-name)))))
+ (and (url-interactive-p)
+ (read-string (url-auth-user-prompt url realm)
+ (or (plist-get creds :user)
+ (user-real-login-name))))))
(plist-put creds :secret
- (read-passwd "Password: " nil (plist-get creds :secret))))
+ (and (url-interactive-p)
+ (read-passwd "Password: " nil (plist-get creds :secret)))))
(defun url-digest-auth-directory-id-assoc (dirkey keylist)
"Find the best match for DIRKEY in key alist KEYLIST.
@@ -301,8 +307,8 @@ object."
(defun url-digest-auth-build-response (key url realm attrs)
"Compute authorization string for the given challenge using KEY.
-The string looks like 'Digest username=\"John\", realm=\"The
-Realm\", ...'
+The string looks like \"Digest username=\"John\", realm=\"The
+Realm\", ...\"
Part of the challenge is already solved in a pre-computed KEY
which is list of a realm (or a directory), user name, and hash
diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el
index 3e69227124f..db8c121cf00 100644
--- a/lisp/url/url-cache.el
+++ b/lisp/url/url-cache.el
@@ -37,7 +37,7 @@
"Default maximum time in seconds before cache files expire.
Used by the function `url-cache-expired'."
:version "24.1"
- :type 'integer
+ :type 'natnum
:group 'url-cache)
;; Cache manager
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index 6b9ce5da93e..0709cdd3fa1 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -26,6 +26,7 @@
(require 'url-util)
(require 'url-parse)
(require 'url-domsuf)
+(require 'generate-lisp-file)
(eval-when-compile (require 'cl-lib))
@@ -158,10 +159,7 @@ i.e. 1970-1-1) are loaded as expiring one year from now instead."
(insert ")\n(setq url-cookie-secure-storage\n '")
(pp url-cookie-secure-storage (current-buffer)))
(insert ")\n")
- (insert " \n;; Local Variables:\n"
- ";; version-control: never\n"
- ";; no-byte-compile: t\n"
- ";; End:\n")
+ (generate-lisp-file-trailer fname :inhibit-provide t :autoloads t)
(setq-local version-control 'never)
(write-file fname))
(setq url-cookies-changed-since-last-save nil))))
@@ -362,7 +360,7 @@ to run the `url-cookie-setup-save-timer' function manually."
(set-default var val)
(if (bound-and-true-p url-setup-done)
(url-cookie-setup-save-timer)))
- :type 'integer
+ :type 'natnum
:group 'url-cookie)
(defun url-cookie-setup-save-timer ()
@@ -494,12 +492,10 @@ Use \\<url-cookie-mode-map>\\[url-cookie-delete] to remove cookies."
(url-cookie--generate-buffer)
(goto-char point))))
-(defvar url-cookie-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [delete] 'url-cookie-delete)
- (define-key map [(control k)] 'url-cookie-delete)
- (define-key map [(control _)] 'url-cookie-undo)
- map))
+(defvar-keymap url-cookie-mode-map
+ "<delete>" #'url-cookie-delete
+ "C-k" #'url-cookie-delete
+ "C-_" #'url-cookie-undo)
(define-derived-mode url-cookie-mode special-mode "URL Cookie"
"Mode for listing cookies.
diff --git a/lisp/url/url-dired.el b/lisp/url/url-dired.el
index 1bbd741c1a7..e2c23a8b6d9 100644
--- a/lisp/url/url-dired.el
+++ b/lisp/url/url-dired.el
@@ -25,12 +25,10 @@
(autoload 'dired-get-filename "dired")
-(defvar url-dired-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'url-dired-find-file)
- (define-key map [mouse-2] 'url-dired-find-file-mouse)
- map)
- "Keymap used when browsing directories.")
+(defvar-keymap url-dired-minor-mode-map
+ :doc "Keymap used when browsing directories."
+ "C-m" #'url-dired-find-file
+ "<mouse-2>" #'url-dired-find-file-mouse)
(defun url-dired-find-file ()
"In dired, visit the file or directory named on this line."
diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el
index 31e5c07234c..3863ac99144 100644
--- a/lisp/url/url-file.el
+++ b/lisp/url/url-file.el
@@ -29,6 +29,12 @@
(require 'url-dired)
(declare-function mm-disable-multibyte "mm-util" ())
+(defvar url-allow-non-local-files nil
+ "If non-nil, allow URL to fetch non-local files.
+By default, this is not allowed, since that would allow rendering
+HTML to fetch files on other systems if given a <img
+src=\"/ssh:host...\"> element, which can be disturbing.")
+
(defconst url-file-default-port 21 "Default FTP port.")
(defconst url-file-asynchronous-p t "FTP transfers are asynchronous.")
(defalias 'url-file-expand-file-name 'url-default-expander)
@@ -70,18 +76,15 @@ to them."
buff func
func args
args efs))
- (let ((size (file-attribute-size (file-attributes name))))
- (with-current-buffer buff
- (goto-char (point-max))
- (if (/= -1 size)
- (insert (format "Content-length: %d\n" size)))
- (insert "\n")
- (insert-file-contents-literally name)
- (if (not (url-file-host-is-local-p (url-host url-current-object)))
- (condition-case ()
- (delete-file name)
- (error nil)))
- (apply func args))))
+ (with-current-buffer buff
+ (goto-char (point-max))
+ (insert-file-contents-literally name)
+ (insert (format "Content-length: %d\n\n" (buffer-size)))
+ (if (not (url-file-host-is-local-p (url-host url-current-object)))
+ (condition-case ()
+ (delete-file name)
+ (error nil)))
+ (apply func args)))
(declare-function ange-ftp-set-passwd "ange-ftp" (host user passwd))
(declare-function ange-ftp-copy-file-internal "ange-ftp"
@@ -111,7 +114,8 @@ to them."
(memq system-type '(ms-dos windows-nt)))
(substring file 1))
;; file: URL with a file:/bar:/foo-like spec.
- ((string-match "\\`/[^/]+:/" file)
+ ((and (not url-allow-non-local-files)
+ (string-match "\\`/[^/]+:/" file))
(concat "/:" file))
(t
file))))
diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el
index cb4814afcad..058e601301b 100644
--- a/lisp/url/url-history.el
+++ b/lisp/url/url-history.el
@@ -63,7 +63,7 @@ to run the `url-history-setup-save-timer' function manually."
(set-default var val)
(if (bound-and-true-p url-setup-done)
(url-history-setup-save-timer)))
- :type 'integer
+ :type 'natnum
:group 'url-history)
(defvar url-history-timer nil)
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index 16c3a6a1e62..4e5d017036c 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -36,6 +36,7 @@
(defvar url-current-object)
(defvar url-http-after-change-function)
(defvar url-http-chunked-counter)
+(defvar url-http-chunked-last-crlf-missing)
(defvar url-http-chunked-length)
(defvar url-http-chunked-start)
(defvar url-http-connection-opened)
@@ -332,7 +333,10 @@ Use `url-http-referer' as the Referer-header (subject to `url-privacy-level')."
(if (and using-proxy
;; Bug#35969.
(not (equal "https" (url-type url-http-target-url))))
- (url-recreate-url url-http-target-url) real-fname))
+ (let ((url (copy-sequence url-http-target-url)))
+ (setf (url-host url) (puny-encode-domain (url-host url)))
+ (url-recreate-url url))
+ real-fname))
" HTTP/" url-http-version "\r\n"
;; Version of MIME we speak
"MIME-Version: 1.0\r\n"
@@ -585,6 +589,13 @@ should be shown to the user."
(url-http-debug "url-http-parse-headers called in (%s)" (buffer-name))
(url-http-parse-response)
(mail-narrow-to-head)
+ (when url-debug
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ (url-http-debug "Response: %s"
+ (buffer-substring (point) (line-end-position)))
+ (forward-line 1))))
;;(narrow-to-region (point-min) url-http-end-of-headers)
(let ((connection (mail-fetch-field "Connection")))
;; In HTTP 1.0, keep the connection only if there is a
@@ -1068,90 +1079,105 @@ the callback to be triggered."
Cannot give a sophisticated percentage, but we need a different
function to look for the special 0-length chunk that signifies
the end of the document."
- (save-excursion
- (goto-char st)
- (let ((read-next-chunk t)
- (case-fold-search t)
- (regexp nil)
- (no-initial-crlf nil))
- ;; We need to loop thru looking for more chunks even within
- ;; one after-change-function call.
- (while read-next-chunk
- (setq no-initial-crlf (= 0 url-http-chunked-counter))
- (if url-http-content-type
+ (if url-http-chunked-last-crlf-missing
+ (progn
+ (goto-char url-http-chunked-last-crlf-missing)
+ (if (not (looking-at "\r\n"))
+ (url-http-debug
+ "Still spinning for the terminator of last chunk...")
+ (url-http-debug "Saw the last CRLF.")
+ (delete-region (match-beginning 0) (match-end 0))
+ (when (url-http-parse-headers)
+ (url-http-activate-callback))))
+ (save-excursion
+ (goto-char st)
+ (let ((read-next-chunk t)
+ (case-fold-search t)
+ (regexp nil)
+ (no-initial-crlf nil))
+ ;; We need to loop thru looking for more chunks even within
+ ;; one after-change-function call.
+ (while read-next-chunk
+ (setq no-initial-crlf (= 0 url-http-chunked-counter))
+ (if url-http-content-type
+ (url-display-percentage nil
+ "Reading [%s]... chunk #%d"
+ url-http-content-type url-http-chunked-counter)
(url-display-percentage nil
- "Reading [%s]... chunk #%d"
- url-http-content-type url-http-chunked-counter)
- (url-display-percentage nil
- "Reading... chunk #%d"
- url-http-chunked-counter))
- (url-http-debug "Reading chunk %d (%d %d %d)"
- url-http-chunked-counter st nd length)
- (setq regexp (if no-initial-crlf
- "\\([0-9a-z]+\\).*\r?\n"
- "\r?\n\\([0-9a-z]+\\).*\r?\n"))
-
- (if url-http-chunked-start
- ;; We know how long the chunk is supposed to be, skip over
- ;; leading crap if possible.
- (if (> nd (+ url-http-chunked-start url-http-chunked-length))
- (progn
- (url-http-debug "Got to the end of chunk #%d!"
- url-http-chunked-counter)
- (goto-char (+ url-http-chunked-start
- url-http-chunked-length)))
- (url-http-debug "Still need %d bytes to hit end of chunk"
- (- (+ url-http-chunked-start
- url-http-chunked-length)
- nd))
- (setq read-next-chunk nil)))
- (if (not read-next-chunk)
- (url-http-debug "Still spinning for next chunk...")
- (if no-initial-crlf (skip-chars-forward "\r\n"))
- (if (not (looking-at regexp))
- (progn
- ;; Must not have received the entirety of the chunk header,
- ;; need to spin some more.
- (url-http-debug "Did not see start of chunk @ %d!" (point))
- (setq read-next-chunk nil))
- ;; The data we got may have started in the middle of the
- ;; initial chunk header, so move back to the start of the
- ;; line and re-compute.
- (when (= url-http-chunked-counter 0)
- (beginning-of-line)
- (looking-at regexp))
- (add-text-properties (match-beginning 0) (match-end 0)
- (list 'chunked-encoding t
- 'face 'cursor
- 'invisible t))
- (setq url-http-chunked-length (string-to-number (buffer-substring
- (match-beginning 1)
- (match-end 1))
- 16)
- url-http-chunked-counter (1+ url-http-chunked-counter)
- url-http-chunked-start (set-marker
- (or url-http-chunked-start
- (make-marker))
- (match-end 0)))
- (delete-region (match-beginning 0) (match-end 0))
- (url-http-debug "Saw start of chunk %d (length=%d, start=%d"
- url-http-chunked-counter url-http-chunked-length
- (marker-position url-http-chunked-start))
- (if (= 0 url-http-chunked-length)
- (progn
- ;; Found the end of the document! Wheee!
- (url-http-debug "Saw end of stream chunk!")
- (setq read-next-chunk nil)
- (url-display-percentage nil nil)
- ;; Every chunk, even the last 0-length one, is
- ;; terminated by CRLF. Skip it.
- (when (looking-at "\r?\n")
- (url-http-debug "Removing terminator of last chunk")
- (delete-region (match-beginning 0) (match-end 0)))
- (if (re-search-forward "^\r?\n" nil t)
- (url-http-debug "Saw end of trailers..."))
- (if (url-http-parse-headers)
- (url-http-activate-callback))))))))))
+ "Reading... chunk #%d"
+ url-http-chunked-counter))
+ (url-http-debug "Reading chunk %d (%d %d %d)"
+ url-http-chunked-counter st nd length)
+ (setq regexp (if no-initial-crlf
+ "\\([0-9a-z]+\\).*\r?\n"
+ "\r?\n\\([0-9a-z]+\\).*\r?\n"))
+
+ (if url-http-chunked-start
+ ;; We know how long the chunk is supposed to be, skip over
+ ;; leading crap if possible.
+ (if (> nd (+ url-http-chunked-start url-http-chunked-length))
+ (progn
+ (url-http-debug "Got to the end of chunk #%d!"
+ url-http-chunked-counter)
+ (goto-char (+ url-http-chunked-start
+ url-http-chunked-length)))
+ (url-http-debug "Still need %d bytes to hit end of chunk"
+ (- (+ url-http-chunked-start
+ url-http-chunked-length)
+ nd))
+ (setq read-next-chunk nil)))
+ (if (not read-next-chunk)
+ (url-http-debug "Still spinning for next chunk...")
+ (if no-initial-crlf (skip-chars-forward "\r\n"))
+ (if (not (looking-at regexp))
+ (progn
+ ;; Must not have received the entirety of the chunk header,
+ ;; need to spin some more.
+ (url-http-debug "Did not see start of chunk @ %d!" (point))
+ (setq read-next-chunk nil))
+ ;; The data we got may have started in the middle of the
+ ;; initial chunk header, so move back to the start of the
+ ;; line and re-compute.
+ (when (= url-http-chunked-counter 0)
+ (beginning-of-line)
+ (looking-at regexp))
+ (add-text-properties (match-beginning 0) (match-end 0)
+ (list 'chunked-encoding t
+ 'face 'cursor
+ 'invisible t))
+ (setq url-http-chunked-length
+ (string-to-number (buffer-substring (match-beginning 1)
+ (match-end 1))
+ 16)
+ url-http-chunked-counter (1+ url-http-chunked-counter)
+ url-http-chunked-start (set-marker
+ (or url-http-chunked-start
+ (make-marker))
+ (match-end 0)))
+ (delete-region (match-beginning 0) (match-end 0))
+ (url-http-debug "Saw start of chunk %d (length=%d, start=%d"
+ url-http-chunked-counter url-http-chunked-length
+ (marker-position url-http-chunked-start))
+ (if (= 0 url-http-chunked-length)
+ (progn
+ ;; Found the end of the document! Wheee!
+ (url-http-debug "Saw end of stream chunk!")
+ (setq read-next-chunk nil)
+ (url-display-percentage nil nil)
+ ;; Every chunk, even the last 0-length one, is
+ ;; terminated by CRLF. Skip it.
+ (if (not (looking-at "\r?\n"))
+ (progn
+ (url-http-debug
+ "Spinning for the terminator of last chunk...")
+ (setq url-http-chunked-last-crlf-missing
+ (point)))
+ (url-http-debug "Removing terminator of last chunk")
+ (delete-region (match-beginning 0) (match-end 0))
+ (when (re-search-forward "^\r?\n" nil t)
+ (url-http-debug "Saw end of trailers..."))
+ (when (url-http-parse-headers)
+ (url-http-activate-callback))))))))))))
(defun url-http-wait-for-headers-change-function (_st nd _length)
;; This will wait for the headers to arrive and then splice in the
@@ -1304,9 +1330,7 @@ The return value of this function is the retrieval buffer."
(cl-check-type url url "Need a pre-parsed URL.")
(let* (;; (host (url-host (or url-using-proxy url)))
;; (port (url-port (or url-using-proxy url)))
- (nsm-noninteractive (or url-request-noninteractive
- (and (boundp 'url-http-noninteractive)
- url-http-noninteractive)))
+ (nsm-noninteractive (not (url-interactive-p)))
;; The following binding is needed in url-open-stream, which
;; is called from url-http-find-free-connection.
(url-current-object url)
@@ -1337,6 +1361,7 @@ The return value of this function is the retrieval buffer."
url-http-after-change-function
url-http-response-version
url-http-response-status
+ url-http-chunked-last-crlf-missing
url-http-chunked-length
url-http-chunked-counter
url-http-chunked-start
@@ -1361,6 +1386,7 @@ The return value of this function is the retrieval buffer."
url-http-noninteractive url-request-noninteractive
url-http-data url-request-data
url-http-process connection
+ url-http-chunked-last-crlf-missing nil
url-http-chunked-length nil
url-http-chunked-start nil
url-http-chunked-counter 0
@@ -1407,10 +1433,10 @@ The return value of this function is the retrieval buffer."
(and proxy-auth
(concat "Proxy-Authorization: " proxy-auth "\r\n")))
"\r\n")
- (url-host url-current-object)
+ (puny-encode-domain (url-host url-current-object))
(or (url-port url-current-object)
url-https-default-port)
- (url-host url-current-object))))
+ (puny-encode-domain (url-host url-current-object)))))
(defun url-https-proxy-after-change-function (_st _nd _length)
(let* ((process-buffer (current-buffer))
@@ -1432,12 +1458,12 @@ The return value of this function is the retrieval buffer."
(condition-case e
(let ((tls-connection (gnutls-negotiate
:process proc
- :hostname (url-host url-current-object)
+ :hostname (puny-encode-domain (url-host url-current-object))
:verify-error nil)))
;; check certificate validity
(setq tls-connection
(nsm-verify-connection tls-connection
- (url-host url-current-object)
+ (puny-encode-domain (url-host url-current-object))
(url-port url-current-object)))
(with-current-buffer process-buffer (erase-buffer))
(set-process-buffer tls-connection process-buffer)
diff --git a/lisp/url/url-queue.el b/lisp/url/url-queue.el
index 8741bca9423..cf45a7f681a 100644
--- a/lisp/url/url-queue.el
+++ b/lisp/url/url-queue.el
@@ -31,17 +31,18 @@
(eval-when-compile (require 'cl-lib))
(require 'browse-url)
(require 'url-parse)
+(require 'url-file)
(defcustom url-queue-parallel-processes 6
"The number of concurrent processes."
:version "24.1"
- :type 'integer
+ :type 'natnum
:group 'url)
(defcustom url-queue-timeout 5
"How long to let a job live once it's started (in seconds)."
:version "24.1"
- :type 'integer
+ :type 'natnum
:group 'url)
;;; Internal variables.
@@ -155,14 +156,16 @@ The variable `url-queue-timeout' sets a timeout."
(defun url-queue-start-retrieve (job)
(setf (url-queue-buffer job)
(ignore-errors
- (with-current-buffer (if (buffer-live-p (url-queue-context-buffer job))
+ (with-current-buffer (if (buffer-live-p
+ (url-queue-context-buffer job))
(url-queue-context-buffer job)
(current-buffer))
- (let ((url-request-noninteractive t))
- (url-retrieve (url-queue-url job)
- #'url-queue-callback-function (list job)
- (url-queue-silentp job)
- (url-queue-inhibit-cookiesp job)))))))
+ (let ((url-request-noninteractive t)
+ (url-allow-non-local-files t))
+ (url-retrieve (url-queue-url job)
+ #'url-queue-callback-function (list job)
+ (url-queue-silentp job)
+ (url-queue-inhibit-cookiesp job)))))))
(defun url-queue-prune-old-entries ()
(let (dead-jobs)
diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el
index 30c1961407e..c414a025a14 100644
--- a/lisp/url/url-tramp.el
+++ b/lisp/url/url-tramp.el
@@ -44,36 +44,40 @@ In case URL is not convertible, nil is returned."
(port
(and obj (natnump (url-portspec obj))
(number-to-string (url-portspec obj)))))
- (when (and obj (member (url-type obj) url-tramp-protocols))
- (when (url-password obj)
- (password-cache-add
- (tramp-make-tramp-file-name
- (make-tramp-file-name
- :method (url-type obj) :user (url-user obj)
- :host (url-host obj)))
- (url-password obj)))
- (tramp-make-tramp-file-name
- (make-tramp-file-name
- :method (url-type obj) :user (url-user obj)
- :host (url-host obj) :port port :localname (url-filename obj))))))
+ (if (and obj (member (url-type obj) url-tramp-protocols))
+ (progn
+ (when (url-password obj)
+ (password-cache-add
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method (url-type obj) :user (url-user obj)
+ :host (url-host obj)))
+ (url-password obj)))
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method (url-type obj) :user (url-user obj)
+ :host (url-host obj) :port port :localname (url-filename obj))))
+ url)))
(defun url-tramp-convert-tramp-to-url (file)
"Convert FILE, a Tramp file name, to a URL.
In case FILE is not convertible, nil is returned."
- (let* ((obj (ignore-errors (tramp-dissect-file-name file)))
+ (let* ((obj (and (tramp-tramp-file-p file)
+ (ignore-errors (tramp-dissect-file-name file))))
(port
(and obj (stringp (tramp-file-name-port obj))
(string-to-number (tramp-file-name-port obj)))))
- (when (and obj (member (tramp-file-name-method obj) url-tramp-protocols))
- (url-recreate-url
- (url-parse-make-urlobj
- (tramp-file-name-method obj)
- (tramp-file-name-user obj)
- nil ; password.
- (tramp-file-name-host obj)
- port
- (tramp-file-name-localname obj)
- nil nil t))))) ; target attributes fullness.
+ (if (and obj (member (tramp-file-name-method obj) url-tramp-protocols))
+ (url-recreate-url
+ (url-parse-make-urlobj
+ (tramp-file-name-method obj)
+ (tramp-file-name-user obj)
+ nil ; password.
+ (tramp-file-name-host obj)
+ port
+ (tramp-file-name-localname obj)
+ nil nil t)) ; target attributes fullness.
+ file)))
;;;###autoload
(defun url-tramp-file-handler (operation &rest args)
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index b8b7980e40b..fc84d451760 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -1,7 +1,6 @@
;;; url-util.el --- Miscellaneous helper routines for URL library -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2001, 2004-2022 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1996-2022 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -217,9 +216,7 @@ Will not do anything if `url-show-status' is nil."
;;;###autoload
(defun url-percentage (x y)
- (if (fboundp 'float)
- (round (* 100 (/ x (float y))))
- (/ (* x 100) y)))
+ (round (* 100 (/ x (float y)))))
;;;###autoload
(defalias 'url-basepath 'url-file-directory)
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index 83c089a930a..de42599e0d4 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -1,7 +1,6 @@
;;; url-vars.el --- Variables for Uniform Resource Locator tool -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1999, 2001, 2004-2022 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1996-2022 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
@@ -131,7 +130,7 @@ Samples:
This variable controls several other variables and is _NOT_ automatically
updated. Call the function `url-setup-privacy-info' after modifying this
variable."
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val) (set-default sym val) (url-setup-privacy-info))
:type '(radio (const :tag "None (you believe in the basic goodness of humanity)"
:value none)
@@ -204,10 +203,9 @@ from the ACCESS_proxy environment variables."
:type 'boolean
:group 'url-cache)
-(defvar url-mime-separator-chars (mapcar 'identity
- (concat "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789'()+_,-./=?"))
+(defvar url-mime-separator-chars (append "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789'()+_,-./=?")
"Characters allowable in a MIME multipart separator.")
(defcustom url-bad-port-list
@@ -254,7 +252,7 @@ Generated according to current coding system priorities."
(push (car elt) accum)))
(nreverse accum)))))
(concat (format "%s;q=1, " (pop ordered))
- (mapconcat 'symbol-name ordered ";q=0.5, ")
+ (mapconcat #'symbol-name ordered ";q=0.5, ")
";q=0.5")))
(defvar url-mime-charset-string nil
@@ -299,7 +297,7 @@ get the first available language (as opposed to the default)."
(defcustom url-max-password-attempts 5
"Maximum number of times a password will be prompted for.
Applies when a protected document is denied by the server."
- :type 'integer
+ :type 'natnum
:group 'url)
(defcustom url-show-status t
@@ -332,7 +330,7 @@ undefined."
(defcustom url-max-redirections 30
"The maximum number of redirection requests to honor in a HTTP connection.
A negative number means to honor an unlimited number of redirection requests."
- :type 'integer
+ :type 'natnum
:group 'url)
(defcustom url-confirmation-func 'y-or-n-p
@@ -398,7 +396,7 @@ Should be one of:
(defvar url-lazy-message-time 0)
;; Fixme: We may not be able to run SSL.
-(defvar url-extensions-header "Security/Digest Security/SSL")
+(defvar url-extensions-header nil)
(defvar url-parse-syntax-table
(copy-syntax-table emacs-lisp-mode-syntax-table)
@@ -424,11 +422,15 @@ Should be one of:
This should be set, e.g. by mail user agents rendering HTML to avoid
`bugs' which call home.")
+(defun url-interactive-p ()
+ "Non-nil when the current request is from an interactive context."
+ (not (or url-request-noninteractive
+ (bound-and-true-p url-http-noninteractive))))
+
;; Obsolete
(defconst url-version "Emacs" "Version number of URL package.")
(make-obsolete-variable 'url-version 'emacs-version "28.1")
(provide 'url-vars)
-
;;; url-vars.el ends here
diff --git a/lisp/url/url.el b/lisp/url/url.el
index 4592f0f2e72..d08ff04eda9 100644
--- a/lisp/url/url.el
+++ b/lisp/url/url.el
@@ -158,7 +158,7 @@ If URL is a multibyte string, it will be encoded as utf-8 and
URL-encoded before it's used."
;; XXX: There is code in Emacs that does dynamic binding
;; of the following variables around url-retrieve:
- ;; url-standalone-mode, url-gateway-unplugged, w3-honor-stylesheets,
+ ;; url-standalone-mode, url-gateway-unplugged,
;; url-confirmation-func, url-cookie-multiple-line,
;; url-cookie-{{,secure-}storage,confirmation}
;; url-standalone-mode and url-gateway-unplugged should work as
diff --git a/lisp/userlock.el b/lisp/userlock.el
index d985cb5c8bf..a8e699385c7 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -65,7 +65,7 @@ in any way you like."
opponent))
(while (null answer)
(message (substitute-command-keys
- "%s locked by %s: (\\`s', \\`q', \\`p', \\`?'? ")
+ "%s locked by %s: (\\`s', \\`q', \\`p', \\`?')? ")
short-file short-opponent)
(if noninteractive (error "Cannot resolve lock conflict in batch mode"))
(let ((tem (let ((inhibit-quit t)
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index e9a21825e18..e02d84f1f56 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -789,10 +789,9 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'."
If a ChangeLog file does not already exist, a non-nil value
means to put log entries in a suitably named buffer."
:type 'boolean
+ :safe #'booleanp
:version "27.1")
-(put 'add-log-dont-create-changelog-file 'safe-local-variable #'booleanp)
-
(defun add-log--pseudo-changelog-buffer-name (changelog-file-name)
"Compute a suitable name for a non-file visiting ChangeLog buffer.
CHANGELOG-FILE-NAME is the file name of the actual ChangeLog file
@@ -1068,8 +1067,23 @@ the change log file in another window."
(insert-before-markers "("))
(error nil)))))
+;; If we're filling a line that has a whole bunch of file names, and
+;; we're still in the file names, then transform this so that it'll
+;; still font-lock properly.
+(defun change-log-fill-file-list ()
+ (save-excursion
+ (unless (bobp)
+ (forward-line -1)
+ (when (looking-at change-log-file-names-re)
+ (goto-char (match-end 0))
+ (while (looking-at "\\=, \\([^ ,:([\n]+\\)")
+ (goto-char (match-end 0)))
+ (when (looking-at ", *\n")
+ (replace-match ":\n *" t t))))))
+
(defun change-log-indent ()
(change-log-fill-parenthesized-list)
+ (change-log-fill-file-list)
(let* ((indent
(save-excursion
(beginning-of-line)
diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el
index b56b4c0d83a..64d5d1081a3 100644
--- a/lisp/vc/compare-w.el
+++ b/lisp/vc/compare-w.el
@@ -1,7 +1,6 @@
;;; compare-w.el --- compare text between windows for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986, 1989, 1993, 1997, 2001-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1986-2022 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience files vc
@@ -99,7 +98,7 @@ may fail by finding the wrong match. The bigger number makes
difference regions more coarse-grained.
The default value 32 is good for the most cases."
- :type 'integer
+ :type 'natnum
:version "22.1")
(defcustom compare-windows-recenter nil
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index ca8df5d3805..30ba4153a9e 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1479,6 +1479,14 @@ See `after-change-functions' for the meaning of BEG, END and LEN."
(defvar whitespace-style)
(defvar whitespace-trailing-regexp)
+(defvar-local diff-mode-read-only nil
+ "Non-nil when read-only diff buffer uses short keys.")
+
+;; It should be lower than `outline-minor-mode' and `view-mode'.
+(or (assq 'diff-mode-read-only minor-mode-map-alist)
+ (nconc minor-mode-map-alist
+ (list (cons 'diff-mode-read-only diff-mode-shared-map))))
+
;;;###autoload
(define-derived-mode diff-mode fundamental-mode "Diff"
"Major mode for viewing/editing context diffs.
@@ -1516,23 +1524,23 @@ a diff with \\[diff-reverse-direction].
(diff-setup-whitespace)
- (if diff-default-read-only
- (setq buffer-read-only t))
+ ;; read-only setup
+ (when diff-default-read-only
+ (setq buffer-read-only t))
+ (when buffer-read-only
+ (setq diff-mode-read-only t))
+ (add-hook 'read-only-mode-hook
+ (lambda ()
+ (setq diff-mode-read-only buffer-read-only))
+ nil t)
+
;; setup change hooks
(if (not diff-update-on-the-fly)
(add-hook 'write-contents-functions #'diff-write-contents-hooks nil t)
(make-local-variable 'diff-unhandled-changes)
(add-hook 'after-change-functions #'diff-after-change-function nil t)
(add-hook 'post-command-hook #'diff-post-command-hook nil t))
- ;; Neat trick from Dave Love to add more bindings in read-only mode:
- (let ((ro-bind (cons 'buffer-read-only diff-mode-shared-map)))
- (add-to-list 'minor-mode-overriding-map-alist ro-bind)
- ;; Turn off this little trick in case the buffer is put in view-mode.
- (add-hook 'view-mode-hook
- (lambda ()
- (setq minor-mode-overriding-map-alist
- (delq ro-bind minor-mode-overriding-map-alist)))
- nil t))
+
;; add-log support
(setq-local add-log-current-defun-function #'diff-current-defun)
(setq-local add-log-buffer-file-name-function
@@ -1588,8 +1596,8 @@ modified lines of the diff."
nil)))
(when (eq diff-buffer-type 'git)
(setq diff-outline-regexp
- (concat "\\(^diff --git.*\n\\|" diff-hunk-header-re "\\)"))
- (setq-local outline-level #'diff--outline-level))
+ (concat "\\(^diff --git.*\n\\|" diff-hunk-header-re "\\)")))
+ (setq-local outline-level #'diff--outline-level)
(setq-local outline-regexp diff-outline-regexp))
(defun diff-delete-if-empty ()
@@ -2066,7 +2074,7 @@ For use in `add-log-current-defun-function'."
(re-search-forward "^[^ ]" nil t))
(pcase-let ((`(,buf ,_line-offset ,pos ,src ,dst ,switched)
(ignore-errors ;Signals errors in place of prompting.
- ;; Use `noprompt' since this is used in which-func-mode
+ ;; Use `noprompt' since this is used in which-function-mode
;; and such.
(diff-find-source-location nil nil 'noprompt))))
(when buf
@@ -2264,21 +2272,24 @@ Return new point, if it was moved."
"Iterate over all hunks between point and MAX.
Call FUN with two args (BEG and END) for each hunk."
(save-excursion
- (let* ((beg (or (ignore-errors (diff-beginning-of-hunk))
- (ignore-errors (diff-hunk-next) (point))
- max)))
- (while (< beg max)
- (goto-char beg)
- (cl-assert (looking-at diff-hunk-header-re))
- (let ((end
- (save-excursion (diff-end-of-hunk) (point))))
- (cl-assert (< beg end))
- (funcall fun beg end)
- (goto-char end)
- (setq beg (if (looking-at diff-hunk-header-re)
- end
- (or (ignore-errors (diff-hunk-next) (point))
- max))))))))
+ (catch 'malformed
+ (let* ((beg (or (ignore-errors (diff-beginning-of-hunk))
+ (ignore-errors (diff-hunk-next) (point))
+ max)))
+ (while (< beg max)
+ (goto-char beg)
+ (unless (looking-at diff-hunk-header-re)
+ (throw 'malformed nil))
+ (let ((end
+ (save-excursion (diff-end-of-hunk) (point))))
+ (unless (< beg end)
+ (throw 'malformed nil))
+ (funcall fun beg end)
+ (goto-char end)
+ (setq beg (if (looking-at diff-hunk-header-re)
+ end
+ (or (ignore-errors (diff-hunk-next) (point))
+ max)))))))))
(defun diff--font-lock-refined (max)
"Apply hunk refinement from font-lock."
@@ -2589,40 +2600,103 @@ fixed, visit it in a buffer."
(defun diff--font-lock-prettify (limit)
(when diff-font-lock-prettify
- (save-excursion
- ;; FIXME: Include the first space for context-style hunks!
- (while (re-search-forward "^[-+! ]" limit t)
- (let ((spec (alist-get (char-before)
- '((?+ . (left-fringe diff-fringe-add diff-indicator-added))
- (?- . (left-fringe diff-fringe-del diff-indicator-removed))
- (?! . (left-fringe diff-fringe-rep diff-indicator-changed))
- (?\s . (left-fringe diff-fringe-nul fringe))))))
- (put-text-property (match-beginning 0) (match-end 0) 'display spec))))
+ (when (> (frame-parameter nil 'left-fringe) 0)
+ (save-excursion
+ ;; FIXME: Include the first space for context-style hunks!
+ (while (re-search-forward "^[-+! ]" limit t)
+ (unless (eq (get-text-property (match-beginning 0) 'face)
+ 'diff-header)
+ (put-text-property
+ (match-beginning 0) (match-end 0)
+ 'display
+ (alist-get
+ (char-before)
+ '((?+ . (left-fringe diff-fringe-add diff-indicator-added))
+ (?- . (left-fringe diff-fringe-del diff-indicator-removed))
+ (?! . (left-fringe diff-fringe-rep diff-indicator-changed))
+ (?\s . (left-fringe diff-fringe-nul fringe)))))))))
;; Mimicks the output of Magit's diff.
;; FIXME: This has only been tested with Git's diff output.
+ ;; FIXME: Add support for Git's "rename from/to"?
(while (re-search-forward "^diff " limit t)
- ;; FIXME: Switching between context<->unified leads to messed up
- ;; file headers by cutting the `display' property in chunks!
+ ;; We split the regexp match into a search plus a looking-at because
+ ;; we want to use LIMIT for the search but we still want to match
+ ;; all the header's lines even if LIMIT falls in the middle of it.
(when (save-excursion
(forward-line 0)
(looking-at
(eval-when-compile
- (concat "diff.*\n"
- "\\(?:\\(?:new file\\|deleted\\).*\n\\)?"
- "\\(?:index.*\n\\)?"
- "--- \\(?:" null-device "\\|a/\\(.*\\)\\)\n"
- "\\+\\+\\+ \\(?:" null-device "\\|b/\\(.*\\)\\)\n"))))
- (put-text-property (match-beginning 0) (1- (match-end 0))
- 'display
- (propertize
- (cond
- ((null (match-string 1))
- (concat "new file " (match-string 2)))
- ((null (match-string 2))
- (concat "deleted " (match-string 1)))
- (t
- (concat "modified " (match-string 1))))
- 'face '(diff-file-header diff-header))))))
+ (let* ((index "\\(?:index.*\n\\)?")
+ (file4 (concat
+ "\\(?:" null-device "\\|[ab]/\\(?4:.*\\)\\)"))
+ (file5 (concat
+ "\\(?:" null-device "\\|[ab]/\\(?5:.*\\)\\)"))
+ (header (concat "--- " file4 "\n"
+ "\\+\\+\\+ " file5 "\n"))
+ (binary (concat
+ "Binary files " file4
+ " and " file5 " \\(?7:differ\\)\n"))
+ (horb (concat "\\(?:" header "\\|" binary "\\)?")))
+ (concat "diff.*?\\(?: a/\\(.*?\\) b/\\(.*\\)\\)?\n"
+ "\\(?:"
+ ;; For new/deleted files, there might be no
+ ;; header (and no hunk) if the file is/was empty.
+ "\\(?3:new\\(?6:\\)\\|deleted\\) file mode \\(?10:[0-7]\\{6\\}\\)\n"
+ index horb
+ ;; Normal case. There might be no header
+ ;; (and no hunk) if only the file mode
+ ;; changed.
+ "\\|"
+ "\\(?:old mode \\(?8:[0-7]\\{6\\}\\)\n\\)?"
+ "\\(?:new mode \\(?9:[0-7]\\{6\\}\\)\n\\)?"
+ index horb "\\)")))))
+ ;; The file names can be extracted either from the `diff' line
+ ;; or from the two header lines. Prefer the header line info if
+ ;; available since the `diff' line is ambiguous in case the
+ ;; file names include " b/" or " a/".
+ ;; FIXME: This prettification throws away all the information
+ ;; about the index hashes.
+ (let ((oldfile (or (match-string 4) (match-string 1)))
+ (newfile (or (match-string 5) (match-string 2)))
+ (kind (if (match-beginning 7) " BINARY"
+ (unless (or (match-beginning 4)
+ (match-beginning 5)
+ (not (match-beginning 3)))
+ " empty")))
+ (filemode
+ (cond
+ ((match-beginning 10)
+ (concat " file with mode " (match-string 10) " "))
+ ((and (match-beginning 8) (match-beginning 9))
+ (concat " file (mode changed from "
+ (match-string 8) " to " (match-string 9) ") "))
+ (t " file "))))
+ (add-text-properties
+ (match-beginning 0) (1- (match-end 0))
+ (list 'display
+ (propertize
+ (cond
+ ((match-beginning 3)
+ (concat (capitalize (match-string 3)) kind filemode
+ (if (match-beginning 6) newfile oldfile)))
+ ((and (null (match-string 4)) (match-string 5))
+ (concat "New " kind filemode newfile))
+ ((null (match-string 2))
+ ;; We used to use
+ ;; (concat "Deleted" kind filemode oldfile)
+ ;; here but that misfires for `diff-buffers'
+ ;; (see 24 Jun 2022 message in bug#54034).
+ ;; AFAIK if (match-string 2) is nil then so is
+ ;; (match-string 1), so "Deleted" doesn't sound right,
+ ;; so better just let the header in plain sight for now.
+ ;; FIXME: `diff-buffers' should maybe try to better
+ ;; mimic Git's format with "a/" and "b/" so prettification
+ ;; can "just work!"
+ nil)
+ (t
+ (concat "Modified" kind filemode oldfile)))
+ 'face '(diff-file-header diff-header))
+ 'font-lock-multiline t))))))
nil)
;;; Syntax highlighting from font-lock
@@ -2667,7 +2741,8 @@ When OLD is non-nil, highlight the hunk from the old source."
;; Trim a trailing newline to find hunk in diff-syntax-fontify-props
;; in diffs that have no newline at end of diff file.
(text (string-trim-right
- (or (with-demoted-errors (diff-hunk-text hunk (not old) nil))
+ (or (with-demoted-errors "Error getting hunk text: %S"
+ (diff-hunk-text hunk (not old) nil))
"")))
(line (if (looking-at "\\(?:\\*\\{15\\}.*\n\\)?[-@* ]*\\([0-9,]+\\)\\([ acd+]+\\([0-9,]+\\)\\)?")
(if old (match-string 1)
diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index 4abcf6c15a7..3e35a3329b1 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -52,6 +52,12 @@ set (`vc-git-diff-switches' for git, for instance), and
"The command to use to run diff."
:type 'string)
+(defcustom diff-entire-buffers t
+ "If non-nil, diff the entire buffers, not just the visible part.
+If nil, only use the narrowed-to parts of the buffers."
+ :type 'boolean
+ :version "29.1")
+
;; prompt if prefix arg present
(defun diff-switches ()
(if current-prefix-arg
@@ -119,7 +125,9 @@ temporary file with the buffer's contents."
(if (bufferp file-or-buf)
(with-current-buffer file-or-buf
(let ((tempfile (make-temp-file "buffer-content-")))
- (write-region nil nil tempfile nil 'nomessage)
+ (if diff-entire-buffers
+ (write-region nil nil tempfile nil 'nomessage)
+ (write-region (point-min) (point-max) tempfile nil 'nomessage))
tempfile))
(file-local-copy file-or-buf)))
@@ -145,7 +153,7 @@ Possible values are:
;; Noninteractive helper for creating and reverting diff buffers
"Compare the OLD and NEW file/buffer.
If the optional SWITCHES is nil, the switches specified in the
-variable ‘diff-switches’ are passed to the diff command,
+variable `diff-switches' are passed to the diff command,
otherwise SWITCHES is used. SWITCHES can be a string or a list
of strings.
@@ -274,7 +282,9 @@ interactively for diff switches. Otherwise, the switches
specified in the variable `diff-switches' are passed to the
diff command.
-OLD and NEW may each be a buffer or a buffer name."
+OLD and NEW may each be a buffer or a buffer name.
+
+Also see the `diff-entire-buffers' variable."
(interactive
(let ((newb (read-buffer "Diff new buffer" (current-buffer) t))
(oldb (read-buffer "Diff original buffer"
diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el
index ca56a2851db..07b853817d1 100644
--- a/lisp/vc/ediff-diff.el
+++ b/lisp/vc/ediff-diff.el
@@ -85,7 +85,10 @@ options after the default ones.
This variable is not for customizing the look of the differences produced by
the command \\[ediff-show-diff-output]. Use the variable
-`ediff-custom-diff-options' for that."
+`ediff-custom-diff-options' for that.
+
+Setting this variable directly may not yield the expected
+results. It should be set via the Customize interface instead."
:set #'ediff-set-diff-options
:type 'string)
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index de0a4d71ed2..273bad5d353 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -955,9 +955,9 @@ this variable represents.")
(((class color))
(:foreground "red3" :background "green"))
(t (:underline t :stipple "gray3")))
- "Face for highlighting the refinement of the selected diff in the ancestor buffer.
-At present, this face is not used and no fine differences are computed for the
-ancestor buffer."
+ "Face for highlighting refinement of the selected diff in the ancestor buffer.
+At present, this face is not used and no fine differences are
+computed for the ancestor buffer."
:group 'ediff-highlighting)
;; An internal variable. Ediff takes the face from here. When unhighlighting,
;; this variable is set to nil, then again to the appropriate face.
@@ -1055,7 +1055,7 @@ this variable represents.")
(:foreground "cyan3" :background "light grey"
:weight bold :extend t))
(t (:italic t :stipple ,stipple-pixmap :extend t)))
- "Face for highlighting even-numbered non-current differences in the ancestor buffer."
+ "Face for highlighting even-numbered non-current differences in ancestor buffer."
:group 'ediff-highlighting)
;; An internal variable. Ediff takes the face from here. When unhighlighting,
;; this variable is set to nil, then again to the appropriate face.
@@ -1146,7 +1146,7 @@ this variable represents.")
(((class color))
(:foreground "green3" :background "black" :weight bold :extend t))
(t (:italic t :stipple "gray1" :extend t)))
- "Face for highlighting odd-numbered non-current differences in the ancestor buffer."
+ "Face for highlighting odd-numbered non-current differences in ancestor buffer."
:group 'ediff-highlighting)
;; An internal variable. Ediff takes the face from here. When unhighlighting,
;; this variable is set to nil, then again to the appropriate face.
diff --git a/lisp/vc/ediff-merg.el b/lisp/vc/ediff-merg.el
index de8c587b1ca..aae6ad549ea 100644
--- a/lisp/vc/ediff-merg.el
+++ b/lisp/vc/ediff-merg.el
@@ -54,7 +54,7 @@ Valid values are the symbols `default-A', `default-B', and `combined'."
The value must be a list of the form
\(STRING1 bufspec1 STRING2 bufspec2 STRING3 bufspec3 STRING4)
where bufspec is the symbol A, B, or Ancestor. For instance, if the value is
-'(STRING1 A STRING2 Ancestor STRING3 B STRING4) then the
+`(STRING1 A STRING2 Ancestor STRING3 B STRING4)' then the
combined text will look like this:
STRING1
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index 48716901116..b7c349fc1cd 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -128,7 +128,7 @@
(defconst ediff-meta-buffer-verbose-message "Ediff Session Group Panel: %s
Useful commands (type ? to hide them and free up screen):
- button2, v, or RET over session record: start that Ediff session
+ mouse-2, v, or RET over session record: start that Ediff session
M:\tin sessions invoked from here, brings back this group panel
R:\tdisplay the registry of active Ediff sessions
h:\tmark session for hiding (toggle)
@@ -1236,7 +1236,7 @@ behavior."
(insert "\t\t*** Directory Differences ***\n")
(insert "
Useful commands:
- C,button2: over file name -- copy this file to directory that doesn't have it
+ C,mouse-2: over file name -- copy this file to directory that doesn't have it
q: hide this buffer
n,SPC: next line
p,DEL: previous line\n\n")
@@ -1429,7 +1429,7 @@ Useful commands:
This is a registry of all active Ediff sessions.
Useful commands:
- button2, `v', RET over a session record: switch to that session
+ mouse-2, `v', RET over a session record: switch to that session
M over a session record: display the associated session group
R in any Ediff session: display session registry
n,SPC: next session
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index b41def2aff3..040a9a63c5a 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -3431,6 +3431,9 @@ Without an argument, it saves customized diff argument, if available
))
(defun ediff-show-diff-output (arg)
+ "With prefix argument ARG, show plain diff output.
+Without an argument, save the customized diff argument, if available
+(and plain output, if customized output was not generated)."
(interactive "P")
(ediff-barf-if-not-control-buffer)
(ediff-compute-custom-diffs-maybe)
@@ -3438,7 +3441,10 @@ Without an argument, it saves customized diff argument, if available
(ediff-skip-unsuitable-frames ' ok-unsplittable))
(let ((buf (cond ((and arg (ediff-buffer-live-p ediff-diff-buffer))
ediff-diff-buffer)
- ((ediff-buffer-live-p ediff-custom-diff-buffer)
+ ((and (ediff-buffer-live-p ediff-custom-diff-buffer)
+ ;; We may not have gotten a custom output if
+ ;; we're working on unsaved buffers.
+ (> (buffer-size ediff-custom-diff-buffer) 0))
ediff-custom-diff-buffer)
((ediff-buffer-live-p ediff-diff-buffer)
ediff-diff-buffer)
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index 1e702edb419..6db3667545e 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -1135,7 +1135,8 @@ It assumes that it is called from within the control buffer."
(setq mode-line-format
(if (ediff-narrow-control-frame-p)
(list " " mode-line-buffer-identification)
- (list "-- " mode-line-buffer-identification " Quick Help")))
+ (list "-- " mode-line-buffer-identification
+ (list 'ediff-use-long-help-message " Quick Help"))))
;; control buffer id
(setq mode-line-buffer-identification
(if (ediff-narrow-control-frame-p)
@@ -1213,18 +1214,20 @@ It assumes that it is called from within the control buffer."
ediff-control-buffer-suffix))
(defun ediff-make-wide-control-buffer-id ()
- (cond ((< ediff-current-difference 0)
- (list (format "%%b At start of %d diffs"
- ediff-number-of-differences)))
- ((>= ediff-current-difference ediff-number-of-differences)
- (list (format "%%b At end of %d diffs"
- ediff-number-of-differences)))
- (t
- (list (format "%%b diff %d of %d"
- (1+ ediff-current-difference)
- ediff-number-of-differences)))))
-
-
+ (list
+ (concat "%b "
+ (propertize
+ (cond ((< ediff-current-difference 0)
+ (format "At start of %d diffs"
+ ediff-number-of-differences))
+ ((>= ediff-current-difference ediff-number-of-differences)
+ (format "At end of %d diffs"
+ ediff-number-of-differences))
+ (t
+ (format "diff %d of %d"
+ (1+ ediff-current-difference)
+ ediff-number-of-differences)))
+ 'face 'mode-line-buffer-id))))
;; If buff is not live, return nil
(defun ediff-get-visible-buffer-window (buff)
diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el
index b2fdb07d5fb..422ed5c0a4d 100644
--- a/lisp/vc/emerge.el
+++ b/lisp/vc/emerge.el
@@ -221,7 +221,7 @@ depend on the flags."
(defcustom emerge-min-visible-lines 3
"Number of lines to show above and below the flags when displaying a difference."
- :type 'integer)
+ :type 'natnum)
(defcustom emerge-temp-file-prefix
(expand-file-name "emerge" temporary-file-directory)
@@ -1647,7 +1647,7 @@ the height of the merge window.
(defun emerge-scroll-left (&optional arg)
"Scroll left all three merge buffers, if they are in windows.
If an argument is given, that is how many columns are scrolled, else nearly
-the width of the A and B windows. `C-u -' alone as argument scrolls half the
+the width of the A and B windows. \\`C-u -' alone as argument scrolls half the
width of the A and B windows."
(interactive "P")
(emerge-operate-on-windows
@@ -1675,7 +1675,7 @@ width of the A and B windows."
(defun emerge-scroll-right (&optional arg)
"Scroll right all three merge buffers, if they are in windows.
If an argument is given, that is how many columns are scrolled, else nearly
-the width of the A and B windows. `C-u -' alone as argument scrolls half the
+the width of the A and B windows. \\`C-u -' alone as argument scrolls half the
width of the A and B windows."
(interactive "P")
(emerge-operate-on-windows
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 79dafe60cc2..e958673fea8 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -710,10 +710,14 @@ different header separator appropriate for `log-edit-mode'."
(interactive)
(when (or (called-interactively-p 'interactive)
(log-edit-empty-buffer-p))
- (insert "Summary: ")
- (when log-edit-setup-add-author
- (insert "\nAuthor: "))
- (insert "\n\n")
+ (dolist (header (append '("Summary") (and log-edit-setup-add-author
+ '("Author"))))
+ ;; Make `C-a' work like in other buffers with header names.
+ (insert (propertize (concat header ": ")
+ 'field 'header
+ 'rear-nonsticky t)
+ "\n"))
+ (insert "\n")
(message-position-point)))
(defun log-edit-insert-cvs-template ()
diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el
index 9952345db50..415b1564eda 100644
--- a/lisp/vc/log-view.el
+++ b/lisp/vc/log-view.el
@@ -134,11 +134,7 @@
"n" #'log-view-msg-next
"p" #'log-view-msg-prev
"TAB" #'log-view-msg-next
- "<backtab>" #'log-view-msg-prev
- "N" #'log-view-file-next
- "P" #'log-view-file-prev
- "M-n" #'log-view-file-next
- "M-p" #'log-view-file-prev)
+ "<backtab>" #'log-view-msg-prev)
(easy-menu-define log-view-mode-menu log-view-mode-map
"Log-View Display Menu."
@@ -166,9 +162,15 @@
["Previous Log Entry" log-view-msg-prev
:help "Go to the previous count'th log message"]
["Next File" log-view-file-next
- :help "Go to the next count'th file"]
+ :help "Go to the next count'th file"
+ :active (derived-mode-p vc-cvs-log-view-mode
+ vc-rcs-log-view-mode
+ vc-sccs-log-view-mode)]
["Previous File" log-view-file-prev
- :help "Go to the previous count'th file"]))
+ :help "Go to the previous count'th file"
+ :active (derived-mode-p vc-cvs-log-view-mode
+ vc-rcs-log-view-mode
+ vc-sccs-log-view-mode)]))
(defvar log-view-mode-hook nil
"Hook run at the end of `log-view-mode'.")
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index 11d14f95766..b48a4a1cbf1 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -130,9 +130,11 @@ to confuse some users sometimes."
(defvar cvs-bakprefix ".#"
"The prefix that CVS prepends to files when rcsmerge'ing.")
-(easy-mmode-defmap cvs-status-map
- '(([(mouse-2)] . cvs-mode-toggle-mark))
- "Local keymap for text properties of status.")
+(declare-function cvs-mode-toggle-mark "pcvs" (e))
+
+(defvar-keymap cvs-status-map
+ :doc "Local keymap for text properties of status."
+ "<mouse-2>" #'cvs-mode-toggle-mark)
;; Constructor:
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index 6a4f6542b5e..003b26eca41 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -925,8 +925,11 @@ Its behavior has mainly two restrictions:
to `smerge-refine-regions'.
This only matters if `smerge-refine-weight-hack' is nil.")
-(defvar smerge-refine-ignore-whitespace t
- "If non-nil, `smerge-refine' should try to ignore change in whitespace.")
+(defcustom smerge-refine-ignore-whitespace t
+ "If non-nil, `smerge-refine' should try to ignore change in whitespace."
+ :type 'boolean
+ :version "29.1"
+ :group 'diff)
(defvar smerge-refine-weight-hack t
"If non-nil, pass to diff as many lines as there are chars in the region.
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el
index bd4ff3e015a..4a511f1f688 100644
--- a/lisp/vc/vc-annotate.el
+++ b/lisp/vc/vc-annotate.el
@@ -57,7 +57,7 @@ is applied to the background."
:set (lambda (symbol value)
(set-default symbol value)
(when (boundp 'vc-annotate-color-map)
- (with-demoted-errors
+ (with-demoted-errors "VC color map error: %S"
;; Update the value of the dependent variable.
(custom-reevaluate-setting 'vc-annotate-color-map))))
:version "25.1"
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index 836630acb5d..ee394a93af4 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -640,7 +640,7 @@ Returns nil if unable to find this information."
;; Could run `bzr status' in the directory and see if it succeeds, but
;; that's relatively expensive.
(defalias 'vc-bzr-responsible-p #'vc-bzr-root
- "Return non-nil if FILE is (potentially) controlled by bzr.
+ "Return the directory if FILE is (potentially) controlled by bzr.
The criterion is that there is a `.bzr' directory in the same
or a superior directory.")
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index e234b9a0447..1f81ff2e0fe 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -26,6 +26,7 @@
(require 'vc-rcs)
(eval-when-compile (require 'vc))
+(require 'log-view)
(declare-function vc-checkout "vc" (file &optional rev))
(declare-function vc-expand-dirs "vc" (file-or-dir-list backend))
@@ -308,7 +309,7 @@ to the CVS command."
(vc-switches 'CVS 'register)))
(defun vc-cvs-responsible-p (file)
- "Return non-nil if CVS thinks it is responsible for FILE."
+ "Return the directory if CVS thinks it is responsible for FILE."
(let ((dir (if (file-directory-p file)
file
(file-name-directory file))))
@@ -1257,6 +1258,14 @@ ignore file."
(if sort (sort-lines nil (point-min) (point-max)))
(save-buffer)))))
+(defvar-keymap vc-cvs-log-view-mode-map
+ "N" #'log-view-file-next
+ "P" #'log-view-file-prev
+ "M-n" #'log-view-file-next
+ "M-p" #'log-view-file-prev)
+
+(define-derived-mode vc-cvs-log-view-mode log-view-mode "CVS-Log-View")
+
(provide 'vc-cvs)
;;; vc-cvs.el ends here
diff --git a/lisp/vc/vc-dav.el b/lisp/vc/vc-dav.el
index 61e2cd23900..94621599e4a 100644
--- a/lisp/vc/vc-dav.el
+++ b/lisp/vc/vc-dav.el
@@ -137,9 +137,9 @@ It should return a status of either 0 (no differences found), or
)
(defun vc-dav-responsible-p (url)
- "Return non-nil if DAV considers itself `responsible' for URL."
+ "Return the URL if DAV considers itself `responsible' for URL."
;; Check for DAV support on the web server.
- (and t url))
+ url)
;;; Unimplemented functions
;;
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index ba6e098d987..9335da10065 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -325,6 +325,7 @@ See `run-hooks'."
(define-key map "U" #'vc-dir-unmark-all-files)
(define-key map "\C-?" #'vc-dir-unmark-file-up)
(define-key map "\M-\C-?" #'vc-dir-unmark-all-files)
+ (define-key map "%" #'vc-dir-mark-by-regexp)
;; Movement.
(define-key map "n" #'vc-dir-next-line)
(define-key map " " #'vc-dir-next-line)
@@ -750,6 +751,23 @@ share the same state."
(vc-dir-mark-file crt)))
(setq crt (ewoc-next vc-ewoc crt))))))))
+(defun vc-dir-mark-by-regexp (regexp &optional unmark)
+ "Mark all files that match REGEXP.
+If UNMARK (interactively, the prefix), unmark instead."
+ (interactive "sMark files matching: \nP")
+ (ewoc-map
+ (lambda (filearg)
+ (when (and (not (vc-dir-fileinfo->directory filearg))
+ (eq (not unmark)
+ (not (vc-dir-fileinfo->marked filearg)))
+ ;; We don't want to match on the part of the file
+ ;; that's above the current directory.
+ (string-match-p regexp (file-relative-name
+ (vc-dir-fileinfo->name filearg))))
+ (setf (vc-dir-fileinfo->marked filearg) (not unmark))
+ t))
+ vc-ewoc))
+
(defun vc-dir-mark-files (mark-files)
"Mark files specified by file names in the argument MARK-FILES.
MARK-FILES should be a list of absolute filenames."
@@ -924,7 +942,7 @@ system."
"Search through all marked files for a match for REGEXP.
For marked directories, use the files displayed from those directories.
Stops when a match is found.
-To continue searching for next match, use command \\[tags-loop-continue]."
+To continue searching for next match, use command \\[fileloop-continue]."
(interactive "sSearch marked files (regexp): ")
(tags-search regexp
(mapcar #'car (vc-dir-marked-only-files-and-states))))
@@ -933,8 +951,14 @@ To continue searching for next match, use command \\[tags-loop-continue]."
"Do `query-replace-regexp' of FROM with TO, on all marked files.
If a directory is marked, then use the files displayed for that directory.
Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
+
+As each match is found, the user must type a character saying
+what to do with it. Type SPC or `y' to replace the match,
+DEL or `n' to skip and go to the next match. For more directions,
+type \\[help-command] at that time.
+
If you exit (\\[keyboard-quit], RET or q), you can resume the query replace
-with the command \\[tags-loop-continue]."
+with the command \\[fileloop-continue]."
;; FIXME: this is almost a copy of `dired-do-query-replace-regexp'. This
;; should probably be made generic and used in both places instead of
;; duplicating it here.
@@ -1538,9 +1562,8 @@ These are the commands available for use in the file status buffer:
This implements the `bookmark-make-record-function' type for
`vc-dir' buffers."
(let* ((bookmark-name
- (concat "(" (symbol-name vc-dir-backend) ") "
- (file-name-nondirectory
- (directory-file-name default-directory))))
+ (file-name-nondirectory
+ (directory-file-name default-directory)))
(defaults (list bookmark-name default-directory)))
`(,bookmark-name
,@(bookmark-make-record-default 'no-file)
@@ -1560,6 +1583,8 @@ type returned by `vc-dir-bookmark-make-record'."
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk)))))
+(put 'vc-dir-bookmark-jump 'bookmark-handler-type "VC")
+
(provide 'vc-dir)
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 2e6690c5376..8937454d111 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1599,7 +1599,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(declare-function grep-read-regexp "grep" ())
(declare-function grep-read-files "grep" (regexp))
(declare-function grep-expand-template "grep"
- (template &optional regexp files dir excl))
+ (template &optional regexp files dir excl more-opts))
(defvar compilation-environment)
;; Derived from `lgrep'.
@@ -1695,8 +1695,8 @@ This command shares argument histories with \\[rgrep] and \\[grep]."
(vc-setup-buffer "*vc-git-stash*")
(vc-git-command "*vc-git-stash*" 'async nil "stash" "show" "-p" name)
(set-buffer "*vc-git-stash*")
- (diff-mode)
(setq buffer-read-only t)
+ (diff-mode)
(pop-to-buffer (current-buffer)))
(defun vc-git-stash-apply (name)
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index e71796b745b..80508570f32 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -99,7 +99,7 @@ interpreted as hostnames."
:type 'regexp
:group 'vc)
-(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg Mtn)
+(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg)
;; RCS, CVS, SVN, SCCS, and SRC come first because they are per-dir
;; rather than per-tree. RCS comes first because of the multibackend
;; support intended to use RCS for local commits (with a remote CVS server).
@@ -141,7 +141,8 @@ confirmation whether it should follow the link. If nil, the link is
visited and a warning displayed."
:type '(choice (const :tag "Ask for confirmation" ask)
(const :tag "Visit link and warn" nil)
- (const :tag "Follow link" t))
+ (const :tag "Follow link" t))
+ :safe #'null
:group 'vc)
(defcustom vc-display-status t
@@ -555,15 +556,6 @@ this function."
templates))))
-;; toggle-read-only is obsolete since 24.3, but since vc-t-r-o was made
-;; obsolete earlier, it is ok for the latter to be an alias to the former,
-;; since the latter will be removed first. We can't just make it
-;; an alias for read-only-mode, since that is not 100% the same.
-(defalias 'vc-toggle-read-only 'toggle-read-only)
-(make-obsolete 'vc-toggle-read-only
- "use `read-only-mode' instead (or `toggle-read-only' in older versions of Emacs)."
- "24.1")
-
(defun vc-default-make-version-backups-p (_backend _file)
"Return non-nil if unmodified versions should be backed up locally.
The default is to switch off this feature."
@@ -798,9 +790,10 @@ In the latter case, VC mode is deactivated for this buffer."
(add-hook 'vc-mode-line-hook #'vc-mode-line nil t)
(let (backend)
(cond
- ((setq backend (with-demoted-errors (vc-backend buffer-file-name)))
- ;; Let the backend setup any buffer-local things he needs.
- (vc-call-backend backend 'find-file-hook)
+ ((setq backend (with-demoted-errors "VC refresh error: %S"
+ (vc-backend buffer-file-name)))
+ ;; Let the backend setup any buffer-local things he needs.
+ (vc-call-backend backend 'find-file-hook)
;; Compute the state and put it in the mode line.
(vc-mode-line buffer-file-name backend)
(unless vc-make-backup-files
@@ -964,7 +957,7 @@ In the latter case, VC mode is deactivated for this buffer."
(defalias 'vc-menu-map vc-menu-map)
-(declare-function vc-responsible-backend "vc" (file))
+(declare-function vc-responsible-backend "vc" (file &optional no-error))
(defun vc-menu-map-filter (orig-binding)
(if (and (symbolp orig-binding) (fboundp orig-binding))
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 20f3b1fba71..a4345c7d7e2 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -40,6 +40,7 @@
(eval-when-compile
(require 'cl-lib)
(require 'vc))
+(require 'log-view)
(declare-function vc-read-revision "vc"
(prompt &optional files backend default initial-input))
@@ -99,7 +100,7 @@ to use --brief and sets this variable to remember whether it worked."
"Where to look for RCS master files.
For a description of possible values, see `vc-check-master-templates'."
:type '(choice (const :tag "Use standard RCS file names"
- '("%sRCS/%s,v" "%s%s,v" "%sRCS/%s"))
+ ("%sRCS/%s,v" "%s%s,v" "%sRCS/%s"))
(repeat :tag "User-specified"
(choice string
function)))
@@ -288,7 +289,7 @@ to the RCS command."
(match-string 1))))))
(defun vc-rcs-responsible-p (file)
- "Return non-nil if RCS thinks it would be responsible for registering FILE."
+ "Return the directory if RCS thinks it would be responsible for FILE."
;; TODO: check for all the patterns in vc-rcs-master-templates
(let ((dir (if (file-directory-p file)
file
@@ -1062,9 +1063,9 @@ file."
(defun vc-rcs-consult-headers (file)
"Search for RCS headers in FILE, and set properties accordingly.
-Returns: nil if no headers were found
- 'rev if a workfile revision was found
- 'rev-and-lock if revision and lock info was found"
+Returns: nil if no headers were found
+ `rev' if a workfile revision was found
+ `rev-and-lock' if revision and lock info was found"
(cond
((not (get-file-buffer file)) nil)
((let (status version)
@@ -1456,6 +1457,14 @@ The `:insn' key is a keyword to distinguish it as a vc-rcs.el extension."
`((headers ,desc ,@headers)
(revisions ,@revs)))))
+(defvar-keymap vc-rcs-log-view-mode-map
+ "N" #'log-view-file-next
+ "P" #'log-view-file-prev
+ "M-n" #'log-view-file-next
+ "M-p" #'log-view-file-prev)
+
+(define-derived-mode vc-rcs-log-view-mode log-view-mode "RCS-Log-View")
+
(provide 'vc-rcs)
;;; vc-rcs.el ends here
diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el
index 4bbf92b3274..9622bf5e097 100644
--- a/lisp/vc/vc-sccs.el
+++ b/lisp/vc/vc-sccs.el
@@ -27,6 +27,7 @@
(eval-when-compile
(require 'vc))
+(require 'log-view)
;;;
;;; Customization options
@@ -212,7 +213,7 @@ to the SCCS command."
(vc-sccs-do-command nil 0 "get" (vc-master-name file)))))
(defun vc-sccs-responsible-p (file)
- "Return non-nil if SCCS thinks it would be responsible for registering FILE."
+ "Return the directory if SCCS thinks it would be responsible for FILE."
;; TODO: check for all the patterns in vc-sccs-master-templates
(or (and (file-directory-p
(expand-file-name "SCCS" (file-name-directory file)))
@@ -518,6 +519,14 @@ If NAME is nil or a revision number string it's just passed through."
(file-name-directory (vc-master-name file))))
(vc-parse-buffer (concat name "\t:\t" file "\t\\(.+\\)") 1))))
+(defvar-keymap vc-sccs-log-view-mode-map
+ "N" #'log-view-file-next
+ "P" #'log-view-file-prev
+ "M-n" #'log-view-file-next
+ "M-p" #'log-view-file-prev)
+
+(define-derived-mode vc-sccs-log-view-mode log-view-mode "SCCS-Log-View")
+
(provide 'vc-sccs)
;;; vc-sccs.el ends here
diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el
index 1c1a7b5d139..432448bde58 100644
--- a/lisp/vc/vc-src.el
+++ b/lisp/vc/vc-src.el
@@ -120,7 +120,7 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
"Where to look for SRC master files.
For a description of possible values, see `vc-check-master-templates'."
:type '(choice (const :tag "Use standard SRC file names"
- '("%s.src/%s,v"))
+ ("%s.src/%s,v"))
(repeat :tag "User-specified"
(choice string
function))))
@@ -242,11 +242,13 @@ This function differs from vc-do-command in that it invokes `vc-src-program'."
(vc-src-command nil files "add"))
(defun vc-src-responsible-p (file)
- "Return non-nil if SRC thinks it would be responsible for registering FILE."
- (file-directory-p (expand-file-name ".src"
- (if (file-directory-p file)
- file
- (file-name-directory file)))))
+ "Return the directory if SRC thinks it would be responsible for FILE."
+ (let ((dir (expand-file-name ".src"
+ (if (file-directory-p file)
+ file
+ (file-name-directory file)))))
+ (and (file-directory-p dir)
+ dir)))
(defun vc-src-checkin (files comment &optional _rev)
"SRC-specific version of `vc-backend-checkin'.
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index b38a676acbd..270877041aa 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -201,8 +201,8 @@ switches."
;; FIXME are there other possible combinations?
(cond ((eq state 'edited) (setq state 'needs-merge))
((not state) (setq state 'needs-update))))
- (when (and state (not (string= "." filename)))
- (setq result (cons (list filename state) result)))))
+ (when state
+ (setq result (cons (list filename state) result)))))
(funcall callback result)))
;; dir-status-files called from vc-dir, which loads vc,
@@ -212,7 +212,7 @@ switches."
(autoload 'vc-expand-dirs "vc")
(defun vc-svn-dir-status-files (_dir files callback)
- "Run 'svn status' for DIR and update BUFFER via CALLBACK.
+ "Run \"svn status\" for DIR and update BUFFER via CALLBACK.
CALLBACK is called as (CALLBACK RESULT BUFFER), where
RESULT is a list of conses (FILE . STATE) for directory DIR."
;; FIXME shouldn't this rather default to all the files in dir?
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 6041c79efca..d3e53858c16 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -220,7 +220,7 @@
;;
;; - responsible-p (file)
;;
-;; Return non-nil if this backend considers itself "responsible" for
+;; Return the directory if this backend considers itself "responsible" for
;; FILE, which can also be a directory. This function is used to find
;; out what backend to use for registration of new files and for things
;; like change log generation. The default implementation always
@@ -824,7 +824,7 @@ for the backend you use."
"Limit the number of items shown by the VC log commands.
Zero means unlimited.
Not all VC backends are able to support this feature."
- :type 'integer)
+ :type 'natnum)
(defcustom vc-allow-async-revert nil
"Specifies whether the diff during \\[vc-revert] may be asynchronous.
@@ -1004,13 +1004,14 @@ responsible for the given file."
;;
;; First try: find a responsible backend. If this is for registration,
;; it must be a backend under which FILE is not yet registered.
- (let ((dirs (delq nil
- (mapcar
- (lambda (backend)
- (when-let ((dir (vc-call-backend
- backend 'responsible-p file)))
- (cons backend dir)))
- vc-handled-backends))))
+ (let* ((file (expand-file-name file))
+ (dirs (delq nil
+ (mapcar
+ (lambda (backend)
+ (when-let ((dir (vc-call-backend
+ backend 'responsible-p file)))
+ (cons backend dir)))
+ vc-handled-backends))))
;; Just a single response (or none); use it.
(if (< (length dirs) 2)
(caar dirs)
@@ -1730,12 +1731,35 @@ to override the value of `vc-diff-switches' and `diff-switches'."
;; any switches in diff-switches.
(when (listp switches) switches))))
-(defun vc-diff-finish (buffer messages)
+(defun vc-shrink-buffer-window (&optional buffer)
+ "Call `shrink-window-if-larger-than-buffer' only when BUFFER is visible.
+BUFFER defaults to the current buffer."
+ (let ((window (get-buffer-window buffer t)))
+ (when window
+ (shrink-window-if-larger-than-buffer window))))
+
+(defvar vc-diff-finish-functions '(vc-shrink-buffer-window)
+ "Functions run at the end of the diff command.
+Each function runs in the diff output buffer without args.")
+
+(defun vc-diff-restore-buffer (original new)
+ "Restore point in buffer NEW to where it was in ORIGINAL.
+
+This function works by updating buffer ORIGINAL with the contents
+of NEW (without destroying existing markers), swapping their text
+objects, and finally killing buffer ORIGINAL."
+ (with-current-buffer original
+ (let ((inhibit-read-only t))
+ (replace-buffer-contents new)))
+ (with-current-buffer new
+ (buffer-swap-text original))
+ (kill-buffer original))
+
+(defun vc-diff-finish (buffer messages &optional oldbuf)
;; The empty sync output case has already been handled, so the only
;; possibility of an empty output is for an async process.
(when (buffer-live-p buffer)
- (let ((window (get-buffer-window buffer t))
- (emptyp (zerop (buffer-size buffer))))
+ (let ((emptyp (zerop (buffer-size buffer))))
(with-current-buffer buffer
(and messages emptyp
(let ((inhibit-read-only t))
@@ -1743,9 +1767,12 @@ to override the value of `vc-diff-switches' and `diff-switches'."
(message "%s" (cdr messages))))
(diff-setup-whitespace)
(diff-setup-buffer-type)
- (goto-char (point-min))
- (when window
- (shrink-window-if-larger-than-buffer window)))
+ ;; `oldbuf' is the buffer that used to show this diff. Make
+ ;; sure that we restore point in it if it's given.
+ (if oldbuf
+ (vc-diff-restore-buffer oldbuf buffer)
+ (goto-char (point-min)))
+ (run-hooks 'vc-diff-finish-functions))
(when (and messages (not emptyp))
(message "%sdone" (car messages))))))
@@ -1769,7 +1796,11 @@ Return t if the buffer had changes, nil otherwise."
;; but the only way to set it for each file included would
;; be to call the back end separately for each file.
(coding-system-for-read
- (if files (vc-coding-system-for-diff (car files)) 'undecided)))
+ (if files (vc-coding-system-for-diff (car files)) 'undecided))
+ (orig-diff-buffer-clone
+ (if revert-buffer-in-progress-p
+ (clone-buffer
+ (generate-new-buffer-name " *vc-diff-clone*") nil))))
;; On MS-Windows and MS-DOS, Diff is likely to produce DOS-style
;; EOLs, which will look ugly if (car files) happens to have Unix
;; EOLs.
@@ -1808,16 +1839,16 @@ Return t if the buffer had changes, nil otherwise."
(setq files (nreverse filtered))))
(vc-call-backend (car vc-fileset) 'diff files rev1 rev2 buffer async)
(set-buffer buffer)
+ ;; Make the *vc-diff* buffer read only, the diff-mode key
+ ;; bindings are nicer for read only buffers. pcl-cvs does the
+ ;; same thing.
+ (setq buffer-read-only t)
(diff-mode)
(setq-local diff-vc-backend (car vc-fileset))
(setq-local diff-vc-revisions (list rev1 rev2))
(setq-local revert-buffer-function
(lambda (_ignore-auto _noconfirm)
(vc-diff-internal async vc-fileset rev1 rev2 verbose)))
- ;; Make the *vc-diff* buffer read only, the diff-mode key
- ;; bindings are nicer for read only buffers. pcl-cvs does the
- ;; same thing.
- (setq buffer-read-only t)
(if (and (zerop (buffer-size))
(not (get-buffer-process (current-buffer))))
;; Treat this case specially so as not to pop the buffer.
@@ -1830,7 +1861,8 @@ Return t if the buffer had changes, nil otherwise."
;; after `pop-to-buffer'; the former assumes the diff buffer is
;; shown in some window.
(let ((buf (current-buffer)))
- (vc-run-delayed (vc-diff-finish buf (when verbose messages))))
+ (vc-run-delayed (vc-diff-finish buf (when verbose messages)
+ orig-diff-buffer-clone)))
;; In the async case, we return t even if there are no differences
;; because we don't know that yet.
t)))
@@ -2498,6 +2530,10 @@ earlier revisions. Show up to LIMIT entries (non-nil means unlimited)."
(put 'vc-log-view-type 'permanent-local t)
(defvar vc-sentinel-movepoint)
+(defvar vc-log-finish-functions '(vc-shrink-buffer-window)
+ "Functions run at the end of the log command.
+Each function runs in the log output buffer without args.")
+
(defun vc-log-internal-common (backend
buffer-name
files
@@ -2529,11 +2565,11 @@ earlier revisions. Show up to LIMIT entries (non-nil means unlimited)."
(vc-run-delayed
(let ((inhibit-read-only t))
(funcall setup-buttons-func backend files retval)
- (shrink-window-if-larger-than-buffer)
(when goto-location-func
(funcall goto-location-func backend)
(setq vc-sentinel-movepoint (point)))
- (set-buffer-modified-p nil)))))
+ (set-buffer-modified-p nil)
+ (run-hooks 'vc-log-finish-functions)))))
(defun vc-incoming-outgoing-internal (backend remote-location buffer-name type)
(vc-log-internal-common
@@ -2618,7 +2654,10 @@ with its diffs (if the underlying VCS supports that)."
(error "Directory is not version controlled")))
(setq default-directory rootdir)
(vc-print-log-internal backend (list rootdir) revision revision limit
- (when with-diff 'with-diff))))
+ (when with-diff 'with-diff))
+ ;; We're looking at the root, so displaying " from <some-file>" in
+ ;; the mode line isn't helpful.
+ (setq vc-parent-buffer-name nil)))
;;;###autoload
(defun vc-print-branch-log (branch)
diff --git a/lisp/vcursor.el b/lisp/vcursor.el
index 8b7105df519..a54227c1bce 100644
--- a/lisp/vcursor.el
+++ b/lisp/vcursor.el
@@ -216,23 +216,17 @@
;; Key bindings
;; ============
;;
-;; There is an alternative set of key bindings which will be used
-;; automatically for a PC if Oemacs is detected. This set uses separate
-;; control, shift and meta keys with function keys 1 to 10. In
-;; particular, movement keys are concentrated on f5 to f8 with (in
-;; increasing order of distance traveled) C-, M- and S- as prefixes.
-;; See the actual bindings below (search for C-f1). This is because the
-;; C-S- prefix is represented by weird key sequences and the set is
-;; incomplete; if you don't mind that, some hints are given in comments
-;; below.
+;; There is an alternative set of key bindings named "Oemacs" (for
+;; historical reasons). This set uses separate control, shift and
+;; meta keys with function keys 1 to 10. In particular, movement keys
+;; are concentrated on f5 to f8 with (in increasing order of distance
+;; traveled) C-, M- and S- as prefixes. See the actual bindings below
+;; (search for C-f1). This is because the C-S- prefix is represented
+;; by weird key sequences and the set is incomplete; if you don't mind
+;; that, some hints are given in comments below.
;;
-;; You can specify the usual or the Oemacs bindings by setting the
-;; variable vcursor-key-bindings to `xterm' or `oemacs'. You can also set
-;; it to nil, in which case vcursor will not make any key bindings
-;; and you can define your own. The default is t, which makes vcursor
-;; guess (it will use xterm unless it thinks Oemacs is running). The
-;; oemacs set will work on an X terminal with function keys, but the
-;; xterm set will not work under Oemacs.
+;; You can specify which set of key bindings to use by customizing the
+;; user option `vcursor-key-bindings'.
;;
;; Usage on dumb terminals
;; =======================
@@ -355,8 +349,7 @@ on loading vcursor and from the customize package."
(set var value)
(cond
((not value)) ;; Don't set any key bindings.
- ((or (eq value 'oemacs)
- (and (eq value t) (fboundp 'oemacs-version)))
+ ((eq value 'oemacs)
(global-set-key [C-f1] #'vcursor-toggle-copy)
(global-set-key [C-f2] #'vcursor-copy)
(global-set-key [C-f3] #'vcursor-copy-word)
@@ -386,33 +379,6 @@ on loading vcursor and from the customize package."
(global-set-key [S-f9] #'vcursor-execute-key)
(global-set-key [S-f10] #'vcursor-execute-command)
-
- ;; Partial dictionary of Oemacs key sequences for you to roll your own,
- ;; e.g C-S-up: (global-set-key "\M-[\C-f\M-\C-m" 'vcursor-previous-line)
- ;; Sequence: Sends:
- ;; "\M-[\C-f\M-\C-m" C-S-up
- ;; "\M-[\C-f\M-\C-q" C-S-down
- ;; "\M-[\C-fs" C-S-left
- ;; "\M-[\C-ft" C-S-right
- ;;
- ;; "\M-[\C-fw" C-S-home
- ;; "\M-[\C-b\C-o" S-tab
- ;; "\M-[\C-f\M-\C-r" C-S-insert
- ;; "\M-[\C-fu" C-S-end
- ;; "\M-[\C-f\M-\C-s" C-S-delete
- ;; "\M-[\C-f\M-\C-d" C-S-prior
- ;; "\M-[\C-fv" C-S-next
- ;;
- ;; "\M-[\C-f^" C-S-f1
- ;; "\M-[\C-f_" C-S-f2
- ;; "\M-[\C-f`" C-S-f3
- ;; "\M-[\C-fa" C-S-f4
- ;; "\M-[\C-fb" C-S-f5
- ;; "\M-[\C-fc" C-S-f6
- ;; "\M-[\C-fd" C-S-f7
- ;; "\M-[\C-fe" C-S-f8
- ;; "\M-[\C-ff" C-S-f9
- ;; "\M-[\C-fg" C-S-f10
)
(t
(global-set-key (vcursor-cs-binding "up") #'vcursor-previous-line)
@@ -456,11 +422,12 @@ on loading vcursor and from the customize package."
(global-set-key (vcursor-cs-binding "f10") #'vcursor-execute-command)
)))
+;; TODO: Get rid of references to "oemacs", which was an ancient
+;; MS-DOS compatible release of Emacs 19.
(defcustom vcursor-key-bindings nil
"How to bind keys when vcursor is loaded.
-If t, guess; if `xterm', use bindings suitable for an X terminal; if
-`oemacs', use bindings which work on a PC with Oemacs. If nil, don't
-define any key bindings.
+If t or `xterm', use the default bindings; if `oemacs', use
+alternative key bindings. If nil, don't define any key bindings.
Default is nil."
:type '(choice (const t) (const nil) (const xterm) (const oemacs))
@@ -854,9 +821,7 @@ Arguments N and optional ALL-FRAMES are the same as with `other-window'.
ALL-FRAMES is also used to decide whether to split the window."
(interactive "p")
- (if (if (fboundp 'oemacs-version)
- (one-window-p nil)
- (one-window-p nil all-frames))
+ (if (one-window-p nil all-frames)
(display-buffer (current-buffer) t))
(save-excursion
(save-window-excursion
diff --git a/lisp/version.el b/lisp/version.el
index 45f72b4329f..7e360209d85 100644
--- a/lisp/version.el
+++ b/lisp/version.el
@@ -56,8 +56,13 @@ developing Emacs.")
(declare-function haiku-get-version-string "haikufns.c")
(defun emacs-version (&optional here)
- "Return string describing the version of Emacs that is running.
-If optional argument HERE is non-nil, insert string at point.
+ "Display the version of Emacs that is running in this session.
+With a prefix argument, insert the Emacs version string at point
+instead of displaying it.
+If called from Lisp, by default return the version string; but
+if the optional argument HERE is non-nil, insert the string at
+point instead.
+
Don't use this function in programs to choose actions according
to the system configuration; look at `system-configuration' instead."
(interactive "P")
diff --git a/lisp/view.el b/lisp/view.el
index bfc0341b2a8..287112f2d44 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,7 +1,6 @@
;;; view.el --- peruse file or buffer without editing -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1989, 1994-1995, 1997, 2000-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1985-2022 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
@@ -26,9 +25,11 @@
;; This package provides the `view' minor mode documented in the Emacs
;; user's manual.
+;;
;; View mode entry and exit is done through the functions `view-mode-enter'
;; and `view-mode-exit'. Use these functions to enter or exit `view-mode' from
;; Emacs Lisp programs.
+;;
;; We use both view- and View- as prefix for symbols. View- is used as
;; prefix for commands that have a key binding. view- is used for commands
;; without key binding. The purpose of this is to make it easier for a
@@ -101,8 +102,6 @@ functions that enable or disable view mode.")
(defvar-local view-old-buffer-read-only nil)
-(defvar-local view-old-Helper-return-blurb nil)
-
(defvar-local view-page-size nil
"Default number of lines to scroll by View page commands.
If nil that means use the window size.")
@@ -113,18 +112,6 @@ If nil that means use half the window size.")
(defvar-local view-last-regexp nil) ; Global is better???
-(defvar-local view-return-to-alist nil
- "What to do with used windows and where to go when finished viewing buffer.
-This is local in each buffer being viewed.
-It is added to by `view-mode-enter' when starting to view a buffer and
-subtracted from by `view-mode-exit' when finished viewing the buffer.
-
-See RETURN-TO-ALIST argument of function `view-mode-exit' for the format of
-`view-return-to-alist'.")
-(make-obsolete-variable
- 'view-return-to-alist "this variable is no longer used." "24.1")
-(put 'view-return-to-alist 'permanent-local t)
-
(defvar-local view-exit-action nil
"If non-nil, a function called when finished viewing.
The function should take one argument (a buffer).
@@ -146,7 +133,7 @@ This is local in each buffer, once it is used.")
;; Some redundant "less"-like key bindings below have been commented out.
(defvar-keymap view-mode-map
- :doc "Keymap for ‘view-mode’."
+ :doc "Keymap for `view-mode'."
"C" #'View-kill-and-leave
"c" #'View-leave
"Q" #'View-quit-all
@@ -454,15 +441,7 @@ Entry to view-mode runs the normal hook `view-mode-hook'."
(setq view-page-size nil
view-half-page-size nil
view-old-buffer-read-only buffer-read-only
- buffer-read-only t)
- (if (boundp 'Helper-return-blurb)
- (setq view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
- Helper-return-blurb)
- Helper-return-blurb
- (format "continue viewing %s"
- (if (buffer-file-name)
- (file-name-nondirectory (buffer-file-name))
- (buffer-name))))))
+ buffer-read-only t))
(define-obsolete-function-alias 'view-mode-enable 'view-mode "24.4")
@@ -482,46 +461,10 @@ Entry to view-mode runs the normal hook `view-mode-hook'."
;; so that View mode stays off if read-only-mode is called.
(if (local-variable-p 'view-read-only)
(kill-local-variable 'view-read-only))
- (if (boundp 'Helper-return-blurb)
- (setq Helper-return-blurb view-old-Helper-return-blurb))
(if buffer-read-only
(setq buffer-read-only view-old-buffer-read-only)))
;;;###autoload
-(defun view-return-to-alist-update (buffer &optional item)
- "Update `view-return-to-alist' of buffer BUFFER.
-Remove from `view-return-to-alist' all entries referencing dead
-windows. Optional argument ITEM non-nil means add ITEM to
-`view-return-to-alist' after purging. For a description of items
-that can be added see the RETURN-TO-ALIST argument of the
-function `view-mode-exit'. If `view-return-to-alist' contains an
-entry for the selected window, purge that entry from
-`view-return-to-alist' before adding ITEM."
- (declare (obsolete "this function has no effect." "24.1"))
- (with-current-buffer buffer
- (when view-return-to-alist
- (let* ((list view-return-to-alist)
- entry entry-window last)
- (while list
- (setq entry (car list))
- (setq entry-window (car entry))
- (if (and (windowp entry-window)
- (or (and item (eq entry-window (selected-window)))
- (not (window-live-p entry-window))))
- ;; Remove that entry.
- (if last
- (setcdr last (cdr list))
- (setq view-return-to-alist
- (cdr view-return-to-alist)))
- ;; Leave entry alone.
- (setq last entry))
- (setq list (cdr list)))))
- ;; Add ITEM.
- (when item
- (setq view-return-to-alist
- (cons item view-return-to-alist)))))
-
-;;;###autoload
(defun view-mode-enter (&optional quit-restore exit-action)
"Enter View mode and set up exit from view mode depending on optional arguments.
Optional argument QUIT-RESTORE if non-nil must specify a valid
@@ -988,6 +931,9 @@ If TIMES is negative, search backwards."
(and (zerop times)
(looking-at ".*")))
+(defvar-local view-old-Helper-return-blurb nil)
+(make-obsolete 'view-old-Helper-return-blurb nil "29.1")
+
(provide 'view)
;;; view.el ends here
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
index f353566b060..85e37ec609a 100644
--- a/lisp/w32-fns.el
+++ b/lisp/w32-fns.el
@@ -312,8 +312,8 @@ names."
;;;; System name and version for emacsbug.el
-(declare-function w32-version "w32-win" ())
-(declare-function w32-read-registry "w32fns" (root key name))
+(declare-function w32-version "term/w32-win" ())
+(declare-function w32-read-registry "w32fns.c" (root key name))
(defun w32--os-description ()
"Return a string describing the underlying OS and its version."
@@ -359,23 +359,6 @@ names."
;;;; Support for build process
-;; From autoload.el
-(defvar autoload-make-program)
-(defvar generated-autoload-file)
-
-(defun w32-batch-update-autoloads ()
- "Like `batch-update-autoloads', but takes the name of the autoloads file
-from the command line.
-
-This is required because some Windows build environments, such as MSYS,
-munge command-line arguments that include file names to a horrible mess
-that Emacs is unable to cope with."
- (let ((generated-autoload-file
- (expand-file-name (pop command-line-args-left)))
- ;; I can only assume the same considerations may apply here...
- (autoload-make-program (pop command-line-args-left)))
- (batch-update-autoloads)))
-
(defun w32-append-code-lines (orig extra)
"Append non-empty non-comment lines in the file EXTRA to the file ORIG.
diff --git a/lisp/wdired.el b/lisp/wdired.el
index 1c02562721a..a5858ed190e 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -155,6 +155,11 @@ nonexistent directory will fail."
:version "26.1"
:type 'boolean)
+(defcustom wdired-search-replace-filenames t
+ "Non-nil to search and replace in file names only."
+ :version "29.1"
+ :type 'boolean)
+
(defvar-keymap wdired-mode-map
:doc "Keymap used in `wdired-mode'."
"C-x C-s" #'wdired-finish-edit
@@ -169,6 +174,7 @@ nonexistent directory will fail."
"C-p" #'wdired-previous-line
"<down>" #'wdired-next-line
"C-n" #'wdired-next-line
+ "C-(" #'dired-hide-details-mode
"<remap> <upcase-word>" #'wdired-upcase-word
"<remap> <capitalize-word>" #'wdired-capitalize-word
"<remap> <downcase-word>" #'wdired-downcase-word
@@ -216,6 +222,7 @@ symbolic link targets, and filenames permission."
(error "This mode can be enabled only by `wdired-change-to-wdired-mode'"))
(put 'wdired-mode 'mode-class 'special)
+(declare-function dired-isearch-search-filenames "dired-aux")
;;;###autoload
(defun wdired-change-to-wdired-mode ()
@@ -236,9 +243,16 @@ See `wdired-mode'."
(dired-remember-marks (point-min) (point-max)))
(setq-local wdired--old-point (point))
(wdired--set-permission-bounds)
- (setq-local query-replace-skip-read-only t)
- (add-function :after-while (local 'isearch-filter-predicate)
- #'wdired-isearch-filter-read-only)
+ (when wdired-search-replace-filenames
+ (add-function :around (local 'isearch-search-fun-function)
+ #'dired-isearch-search-filenames
+ '((isearch-message-prefix . "filename ")))
+ (setq-local replace-search-function
+ (setq-local replace-re-search-function
+ (funcall isearch-search-fun-function)))
+ ;; Original dired hook removes dired-isearch-search-filenames that
+ ;; is needed outside isearch for lazy-highlighting in query-replace.
+ (remove-hook 'isearch-mode-hook #'dired-isearch-filenames-setup t))
(use-local-map wdired-mode-map)
(force-mode-line-update)
(setq buffer-read-only nil)
@@ -318,11 +332,6 @@ or \\[wdired-abort-changes] to abort changes")))
;; Is this good enough? Assumes no extra white lines from dired.
(put-text-property (1- (point-max)) (point-max) 'read-only t)))))))
-(defun wdired-isearch-filter-read-only (beg end)
- "Skip matches that have a read-only property."
- (not (text-property-not-all (min beg end) (max beg end)
- 'read-only nil)))
-
;; Protect the buffer so only the filenames can be changed, and put
;; properties so filenames (old and new) can be easily found.
(defun wdired--preprocess-files ()
@@ -437,8 +446,13 @@ non-nil means return old filename."
(remove-text-properties
(point-min) (point-max)
'(front-sticky nil rear-nonsticky nil read-only nil keymap nil)))
- (remove-function (local 'isearch-filter-predicate)
- #'wdired-isearch-filter-read-only)
+ (when wdired-search-replace-filenames
+ (remove-function (local 'isearch-search-fun-function)
+ #'dired-isearch-search-filenames)
+ (kill-local-variable 'replace-search-function)
+ (kill-local-variable 'replace-re-search-function)
+ ;; Restore dired hook
+ (add-hook 'isearch-mode-hook #'dired-isearch-filenames-setup nil t))
(use-local-map dired-mode-map)
(force-mode-line-update)
(setq buffer-read-only t)
@@ -507,7 +521,15 @@ non-nil means return old filename."
files-renamed))))
(forward-line -1)))
(when files-renamed
- (setq errors (+ errors (wdired-do-renames files-renamed))))
+ (pcase-let ((`(,errs . ,successful-renames)
+ (wdired-do-renames files-renamed)))
+ (cl-incf errors errs)
+ ;; Some of the renames may fail -- in that case, don't mark an
+ ;; already-existing file with the same name as renamed.
+ (pcase-dolist (`(,file . _) wdired--old-marks)
+ (unless (member file successful-renames)
+ (setq wdired--old-marks
+ (assoc-delete-all file wdired--old-marks #'equal))))))
;; We have to be in wdired-mode when wdired-do-renames is executed
;; so that wdired--restore-properties runs, but we have to change
;; back to dired-mode before reverting the buffer to avoid using
@@ -552,7 +574,8 @@ non-nil means return old filename."
(errors 0)
(total (1- (length renames)))
(prep (make-progress-reporter "Renaming" 0 total))
- (overwrite (or (not wdired-confirm-overwrite) 1)))
+ (overwrite (or (not wdired-confirm-overwrite) 1))
+ (successful-renames nil))
(while (or renames
;; We've done one round through the renames, we have found
;; some residue, but we also made some progress, so maybe
@@ -603,13 +626,15 @@ non-nil means return old filename."
(wdired-create-parentdirs file-new))
(dired-rename-file file-ori file-new
overwrite))
+ (:success
+ (push file-new successful-renames))
(error
(setq errors (1+ errors))
(dired-log "Rename `%s' to `%s' failed:\n%s\n"
file-ori file-new
err)))))))))
(progress-reporter-done prep)
- errors))
+ (cons errors successful-renames)))
(defun wdired-create-parentdirs (file-new)
"Create parent directories for FILE-NEW if they don't exist."
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 8e726c40dd8..240f99effc2 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -276,116 +276,125 @@
It's a list containing some or all of the following values:
- face enable all visualization via faces (see below).
-
- trailing trailing blanks are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- tabs TABs are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- spaces SPACEs and HARD SPACEs are visualized via
- faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- lines lines which have columns beyond
- `whitespace-line-column' are highlighted via
- faces.
- Whole line is highlighted.
- It has precedence over `lines-tail' (see
- below).
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- lines-tail lines which have columns beyond
- `whitespace-line-column' are highlighted via
- faces.
- But only the part of line which goes
- beyond `whitespace-line-column' column.
- It has effect only if `lines' (see above)
- is not present in `whitespace-style'
- and if `face' (see above) is present in
- `whitespace-style'.
-
- newline NEWLINEs are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
+ face enable all visualization via faces (see below).
+
+ trailing trailing blanks are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ tabs TABs are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ spaces SPACEs and HARD SPACEs are visualized via
+ faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ lines lines which have columns beyond
+ `whitespace-line-column' are highlighted via
+ faces.
+ Whole line is highlighted.
+ It has precedence over `lines-tail' and
+ `lines-char' (see below).
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ lines-tail lines which have columns beyond
+ `whitespace-line-column' are highlighted via
+ faces.
+ But only the part of line which goes
+ beyond `whitespace-line-column' column.
+ It has effect only if `lines' (see above)
+ is not present in `whitespace-style'
+ and if `face' (see above) is present in
+ `whitespace-style'.
+
+ lines-char lines which have columns beyond
+ `whitespace-line-column' are highlighted via
+ putting a face on the first character that goes
+ beyond the `whitespace-line-column' column.
+ It has effect only if `lines' or
+ `lines-tail' (see above) is not present
+ in `whitespace-style' and if `face' (see
+ above) is present in `whitespace-style'.
+
+ newline NEWLINEs are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
missing-newline-at-eof Missing newline at the end of the file is
visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- empty empty lines at beginning and/or end of buffer
- are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- indentation::tab `tab-width' or more SPACEs at beginning of line
- are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- indentation::space TABs at beginning of line are visualized via
- faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- indentation `tab-width' or more SPACEs at beginning of line
- are visualized, if `indent-tabs-mode' (which
- see) is non-nil; otherwise, TABs at beginning
- of line are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- big-indent Big indentations are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-after-tab::tab `tab-width' or more SPACEs after a TAB
- are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-after-tab::space TABs are visualized when `tab-width' or
- more SPACEs occur after a TAB, via
- faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-after-tab `tab-width' or more SPACEs after a TAB
- are visualized, if `indent-tabs-mode'
- (which see) is non-nil; otherwise,
- the TABs are visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-before-tab::tab SPACEs before TAB are visualized via
- faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-before-tab::space TABs are visualized when SPACEs occur
- before TAB, via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-before-tab SPACEs before TAB are visualized, if
- `indent-tabs-mode' (which see) is
- non-nil; otherwise, the TABs are
- visualized via faces.
- It has effect only if `face' (see above)
- is present in `whitespace-style'.
-
- space-mark SPACEs and HARD SPACEs are visualized via
- display table.
-
- tab-mark TABs are visualized via display table.
-
- newline-mark NEWLINEs are visualized via display table.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ empty empty lines at beginning and/or end of buffer
+ are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ indentation::tab `tab-width' or more SPACEs at beginning of line
+ are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ indentation::space TABs at beginning of line are visualized via
+ faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ indentation `tab-width' or more SPACEs at beginning of line
+ are visualized, if `indent-tabs-mode' (which
+ see) is non-nil; otherwise, TABs at beginning
+ of line are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ big-indent Big indentations are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-after-tab::tab `tab-width' or more SPACEs after a TAB
+ are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-after-tab::space TABs are visualized when `tab-width' or
+ more SPACEs occur after a TAB, via
+ faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-after-tab `tab-width' or more SPACEs after a TAB
+ are visualized, if `indent-tabs-mode'
+ (which see) is non-nil; otherwise,
+ the TABs are visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-before-tab::tab SPACEs before TAB are visualized via
+ faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-before-tab::space TABs are visualized when SPACEs occur
+ before TAB, via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-before-tab SPACEs before TAB are visualized, if
+ `indent-tabs-mode' (which see) is
+ non-nil; otherwise, the TABs are
+ visualized via faces.
+ It has effect only if `face' (see above)
+ is present in `whitespace-style'.
+
+ space-mark SPACEs and HARD SPACEs are visualized via
+ display table.
+
+ tab-mark TABs are visualized via display table.
+
+ newline-mark NEWLINEs are visualized via display table.
Any other value is ignored.
@@ -431,6 +440,7 @@ See also `whitespace-display-mappings' for documentation."
(const :tag "(Face) SPACEs and HARD SPACEs" spaces)
(const :tag "(Face) Lines" lines)
(const :tag "(Face) Lines, only overlong part" lines-tail)
+ (const :tag "(Face) Lines, only first character" lines-char)
(const :tag "(Face) NEWLINEs" newline)
(const :tag "(Face) Missing newlines at EOB"
missing-newline-at-eof)
@@ -772,7 +782,8 @@ Used when `whitespace-style' includes `big-indent'."
It must be an integer or nil. If nil, the `fill-column' variable value is
used.
-Used when `whitespace-style' includes `lines' or `lines-tail'."
+Used when `whitespace-style' includes `lines', `lines-tail' or
+`lines-char'."
:type '(choice :tag "Line Length Limit"
(integer :tag "Line Length")
(const :tag "Use fill-column" nil))
@@ -808,21 +819,21 @@ Each element has the following form:
Where:
-KIND is the kind of character.
- It can be one of the following symbols:
+KIND is the kind of character.
+ It can be one of the following symbols:
- tab-mark for TAB character
+ tab-mark for TAB character
- space-mark for SPACE or HARD SPACE character
+ space-mark for SPACE or HARD SPACE character
- newline-mark for NEWLINE character
+ newline-mark for NEWLINE character
-CHAR is the character to be mapped.
+CHAR is the character to be mapped.
-VECTOR is a vector of characters to be displayed in place of CHAR.
- The first display vector that can be displayed is used;
- if no display vector for a mapping can be displayed, then
- that character is displayed unmodified.
+VECTOR is a vector of characters to be displayed in place of CHAR.
+ The first display vector that can be displayed is used;
+ if no display vector for a mapping can be displayed, then
+ that character is displayed unmodified.
The NEWLINE character is displayed using the face given by
`whitespace-newline' variable.
@@ -880,27 +891,27 @@ C++ modes only."
It's a list containing some or all of the following values:
- nil no action is taken.
+ nil no action is taken.
- cleanup cleanup any bogus whitespace always when local
- whitespace is turned on.
- See `whitespace-cleanup' and
- `whitespace-cleanup-region'.
+ cleanup cleanup any bogus whitespace always when local
+ whitespace is turned on.
+ See `whitespace-cleanup' and
+ `whitespace-cleanup-region'.
- report-on-bogus report if there is any bogus whitespace always
- when local whitespace is turned on.
+ report-on-bogus report if there is any bogus whitespace always
+ when local whitespace is turned on.
- auto-cleanup cleanup any bogus whitespace when buffer is
- written.
- See `whitespace-cleanup' and
- `whitespace-cleanup-region'.
+ auto-cleanup cleanup any bogus whitespace when buffer is
+ written.
+ See `whitespace-cleanup' and
+ `whitespace-cleanup-region'.
- abort-on-bogus abort if there is any bogus whitespace and the
- buffer is written.
+ abort-on-bogus abort if there is any bogus whitespace and the
+ buffer is written.
- warn-if-read-only give a warning if `cleanup' or `auto-cleanup'
- is included in `whitespace-action' and the
- buffer is read-only.
+ warn-if-read-only give a warning if `cleanup' or `auto-cleanup'
+ is included in `whitespace-action' and the
+ buffer is read-only.
Any other value is treated as nil."
:type '(choice :tag "Actions"
@@ -1058,6 +1069,7 @@ See also `whitespace-newline' and `whitespace-display-mappings'."
trailing
lines
lines-tail
+ lines-char
newline
empty
indentation
@@ -1085,6 +1097,7 @@ See also `whitespace-newline' and `whitespace-display-mappings'."
(?r . trailing)
(?l . lines)
(?L . lines-tail)
+ (?\C-l . lines-char)
(?n . newline)
(?e . empty)
(?\C-i . indentation)
@@ -1244,6 +1257,7 @@ Interactively, it accepts one of the following chars:
r toggle trailing blanks visualization
l toggle \"long lines\" visualization
L toggle \"long lines\" tail visualization
+ C-l toggle \"long lines\" one character visualization
n toggle NEWLINE visualization
e toggle empty line at bob and/or eob visualization
C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
@@ -1274,6 +1288,7 @@ The valid symbols are:
trailing toggle trailing blanks visualization
lines toggle \"long lines\" visualization
lines-tail toggle \"long lines\" tail visualization
+ lines-char toggle \"long lines\" one character visualization
newline toggle NEWLINE visualization
empty toggle empty line at bob and/or eob visualization
indentation toggle indentation SPACEs visualization
@@ -1682,7 +1697,7 @@ cleaning up these problems."
(rstart (min start end))
(rend (max start end))
;; Fall back to whitespace-style so we can run before
- ;; before the mode is active.
+ ;; the mode is active.
(style (copy-sequence
(or whitespace-active-style whitespace-style)))
(bogus-list
@@ -1770,6 +1785,7 @@ cleaning up these problems."
[] r - toggle trailing blanks visualization
[] l - toggle \"long lines\" visualization
[] L - toggle \"long lines\" tail visualization
+ [] C-l - toggle \"long lines\" one character visualization
[] n - toggle NEWLINE visualization
[] e - toggle empty line at bob and/or eob visualization
[] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode')
@@ -1892,6 +1908,7 @@ It accepts one of the following chars:
r toggle trailing blanks visualization
l toggle \"long lines\" visualization
L toggle \"long lines\" tail visualization
+ C-l toggle \"long lines\" one character visualization
n toggle NEWLINE visualization
e toggle empty line at bob and/or eob visualization
C-i toggle indentation SPACEs visualization (via `indent-tabs-mode')
@@ -2020,6 +2037,7 @@ resultant list will be returned."
(memq 'trailing whitespace-active-style)
(memq 'lines whitespace-active-style)
(memq 'lines-tail whitespace-active-style)
+ (memq 'lines-char whitespace-active-style)
(memq 'newline whitespace-active-style)
(memq 'empty whitespace-active-style)
(memq 'indentation whitespace-active-style)
@@ -2066,12 +2084,17 @@ resultant list will be returned."
;; Show trailing blanks.
`((,#'whitespace-trailing-regexp 1 whitespace-trailing t)))
,@(when (or (memq 'lines whitespace-active-style)
- (memq 'lines-tail whitespace-active-style))
+ (memq 'lines-tail whitespace-active-style)
+ (memq 'lines-char whitespace-active-style))
;; Show "long" lines.
`((,#'whitespace-lines-regexp
- ,(if (memq 'lines whitespace-active-style)
- 0 ; whole line
- 2) ; line tail
+ ,(cond
+ ;; whole line
+ ((memq 'lines whitespace-active-style) 0)
+ ;; line tail
+ ((memq 'lines-tail whitespace-active-style) 2)
+ ;; first overflowing character
+ ((memq 'lines-char whitespace-active-style) 3))
whitespace-line prepend)))
,@(when (or (memq 'space-before-tab whitespace-active-style)
(memq 'space-before-tab::tab whitespace-active-style)
@@ -2089,16 +2112,7 @@ resultant list will be returned."
,@(when (or (memq 'indentation whitespace-active-style)
(memq 'indentation::tab whitespace-active-style)
(memq 'indentation::space whitespace-active-style))
- `((,(cond
- ((memq 'indentation whitespace-active-style)
- ;; Show indentation SPACEs (indent-tabs-mode).
- (whitespace-indentation-regexp))
- ((memq 'indentation::tab whitespace-active-style)
- ;; Show indentation SPACEs (SPACEs).
- (whitespace-indentation-regexp 'tab))
- ((memq 'indentation::space whitespace-active-style)
- ;; Show indentation SPACEs (TABs).
- (whitespace-indentation-regexp 'space)))
+ `((,#'whitespace--indentation-matcher
1 whitespace-indentation t)))
,@(when (memq 'big-indent whitespace-active-style)
;; Show big indentation.
@@ -2182,7 +2196,7 @@ resultant list will be returned."
(re-search-forward
(let ((line-column (or whitespace-line-column fill-column)))
(format
- "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$"
+ "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(?2:\\(?3:.\\).*\\)$"
tab-width
(1- tab-width)
(/ line-column tab-width)
@@ -2333,6 +2347,26 @@ Also refontify when necessary."
(font-lock-flush ostart (overlay-end whitespace-point--used))
(delete-overlay whitespace-point--used))))))
+(defun whitespace--indentation-matcher (limit)
+ "Indentation matcher for `font-lock-keywords'.
+This matcher is a function instead of a static regular expression
+so that the next call to `font-lock-flush' picks up any changes
+to `indent-tabs-mode' and `tab-width'."
+ (re-search-forward
+ (whitespace-indentation-regexp
+ (cond
+ ((memq 'indentation whitespace-active-style) nil)
+ ((memq 'indentation::tab whitespace-active-style) 'tab)
+ ((memq 'indentation::space whitespace-active-style) 'space)))
+ limit t))
+
+(defun whitespace--variable-watcher (_symbol _newval _op buffer)
+ "Variable watcher that calls `font-lock-flush' for BUFFER."
+ (when buffer
+ (with-current-buffer buffer
+ (when whitespace-mode
+ (font-lock-flush)))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Hacked from visws.el (Miles Bader <miles@gnu.org>)
@@ -2445,9 +2479,16 @@ It should be added buffer-locally to `write-file-functions'."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defvar whitespace--watched-vars
+ '(fill-column indent-tabs-mode tab-width whitespace-line-column))
+
+(dolist (var whitespace--watched-vars)
+ (add-variable-watcher var #'whitespace--variable-watcher))
(defun whitespace-unload-function ()
"Unload the whitespace library."
+ (dolist (var whitespace--watched-vars)
+ (remove-variable-watcher var #'whitespace--variable-watcher))
(global-whitespace-mode -1)
;; be sure all local whitespace mode is turned off
(save-current-buffer
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index f00a524c0c4..53626182470 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -880,6 +880,7 @@ The child is converted, using the keyword arguments ARGS."
"Make a deep copy of WIDGET."
(widget-apply (copy-sequence widget) :copy))
+;;;###autoload
(defun widget-convert (type &rest args)
"Convert TYPE to a widget without inserting it in the buffer.
The optional ARGS are additional keyword arguments."
@@ -3532,13 +3533,17 @@ It reads a directory name from an editable text field."
(define-widget 'key 'editable-field
"A key sequence."
:prompt-value 'widget-field-prompt-value
- :match 'key-valid-p
+ :match #'widget-key-valid-p
:format "%{%t%}: %v"
:validate 'widget-key-validate
:keymap widget-key-sequence-map
:help-echo "C-q: insert KEY, EVENT, or CODE; RET: enter value"
:tag "Key")
+(defun widget-key-valid-p (_widget value)
+ "Non-nil if VALUE is a valid value for the key widget WIDGET."
+ (key-valid-p value))
+
(defun widget-key-validate (widget)
(unless (and (stringp (widget-value widget))
(key-valid-p (widget-value widget)))
diff --git a/lisp/widget.el b/lisp/widget.el
index 300a95bd229..e6a856b2927 100644
--- a/lisp/widget.el
+++ b/lisp/widget.el
@@ -91,7 +91,6 @@ The third argument DOC is a documentation string for the widget."
(put name 'widget-documentation (purecopy doc))
name)
-;; This is used by external widget code (in W3, at least).
(define-obsolete-function-alias 'widget-plist-member #'plist-member "26.1")
(provide 'widget)
diff --git a/lisp/windmove.el b/lisp/windmove.el
index c8ea4fd1e54..958a9585dc3 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -644,7 +644,7 @@ Default value of MODIFIERS is `shift-meta'."
(defun windmove-delete-in-direction (dir &optional arg)
"Delete the window at direction DIR.
If prefix ARG is `\\[universal-argument]', also kill the buffer in that window.
-With `M-0' prefix, delete the selected window and
+With \\`M-0' prefix, delete the selected window and
select the window at direction DIR.
When `windmove-wrap-around' is non-nil, takes the window
from the opposite side of the frame."
diff --git a/lisp/window.el b/lisp/window.el
index 3f61d531282..4d88ffa9039 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -451,7 +451,7 @@ window to a height less than the one specified here, an
application should instead call `window-resize' with a non-nil
IGNORE argument. In order to have `split-window' make a window
shorter, explicitly specify the SIZE argument of that function."
- :type 'integer
+ :type 'natnum
:version "24.1"
:group 'windows)
@@ -483,7 +483,7 @@ window to a width less than the one specified here, an
application should instead call `window-resize' with a non-nil
IGNORE argument. In order to have `split-window' make a window
narrower, explicitly specify the SIZE argument of that function."
- :type 'integer
+ :type 'natnum
:version "24.1"
:group 'windows)
@@ -2488,15 +2488,23 @@ and no others."
(defalias 'some-window 'get-window-with-predicate)
+(defcustom display-buffer-avoid-small-windows nil
+ "If non-nil, windows that have fewer lines than this are avoided.
+This is used by `get-lru-window'. The value is interpreted in units
+of the frame's canonical line height, like `window-total-height' does."
+ :type '(choice (const nil) number)
+ :version "29.1"
+ :group 'windows)
+
(defun get-lru-window (&optional all-frames dedicated not-selected no-other)
- "Return the least recently used window on frames specified by ALL-FRAMES.
+ "Return the least recently used window on frames specified by ALL-FRAMES.
Return a full-width window if possible. A minibuffer window is
never a candidate. A dedicated window is never a candidate
unless DEDICATED is non-nil, so if all windows are dedicated, the
value is nil. Avoid returning the selected window if possible.
Optional argument NOT-SELECTED non-nil means never return the
selected window. Optional argument NO-OTHER non-nil means to
-never return a window whose 'no-other-window' parameter is
+never return a window whose `no-other-window' parameter is
non-nil.
The following non-nil values of the optional argument ALL-FRAMES
@@ -2513,15 +2521,23 @@ have special meanings:
- A frame means consider all windows on that frame only.
Any other value of ALL-FRAMES means consider all windows on the
-selected frame and no others."
- (let (best-window best-time second-best-window second-best-time time)
- (dolist (window (window-list-1 nil 'nomini all-frames))
+selected frame and no others.
+
+`display-buffer-avoid-small-windows', if non-nil, is also taken into
+consideration. Windows whose height is smaller that the value of that
+variable will be avoided if larger windows are available."
+ (let ((windows (window-list-1 nil 'nomini all-frames))
+ best-window best-time second-best-window second-best-time time)
+ (dolist (window windows)
(when (and (or dedicated (not (window-dedicated-p window)))
(or (not not-selected) (not (eq window (selected-window))))
(or (not no-other)
(not (window-parameter window 'no-other-window))))
(setq time (window-use-time window))
(if (or (eq window (selected-window))
+ (and display-buffer-avoid-small-windows
+ (< (window-height window)
+ display-buffer-avoid-small-windows))
(not (window-full-width-p window)))
(when (or (not second-best-time) (< time second-best-time))
(setq second-best-time time)
@@ -2538,7 +2554,7 @@ never a candidate unless DEDICATED is non-nil, so if all windows
are dedicated, the value is nil. Optional argument NOT-SELECTED
non-nil means never return the selected window. Optional
argument NO-OTHER non-nil means to never return a window whose
-'no-other-window' parameter is non-nil.
+`no-other-window' parameter is non-nil.
The following non-nil values of the optional argument ALL-FRAMES
have special meanings:
@@ -2574,7 +2590,7 @@ never a candidate unless DEDICATED is non-nil, so if all windows
are dedicated, the value is nil. Optional argument NOT-SELECTED
non-nil means never return the selected window. Optional
argument NO-OTHER non-nil means to never return a window whose
-'no-other-window' parameter is non-nil.
+`no-other-window' parameter is non-nil.
The following non-nil values of the optional argument ALL-FRAMES
have special meanings:
@@ -4165,8 +4181,8 @@ another live window on that frame to serve as its selected
window. This option allows to control which window gets selected
instead.
-The possible choices are 'mru' (the default) to select the most
-recently used window on that frame, and 'pos' to choose the
+The possible choices are `mru' (the default) to select the most
+recently used window on that frame, and `pos' to choose the
window at the frame coordinates of point of the previously
selected window. If this is nil, choose the frame's first window
instead. A window with a non-nil `no-other-window' parameter is
@@ -4578,7 +4594,9 @@ as well. In that case, if this option specifies a function, it
will be called with the third argument nil.
Under certain circumstances `switch-to-prev-buffer' may ignore
-this option, for example, when there is only one buffer left."
+this option, for example, when there is only one buffer left.
+
+Also see `switch-to-prev-buffer-skip-regexp'."
:type
'(choice (const :tag "Never" nil)
(const :tag "This frame" this)
@@ -4589,16 +4607,37 @@ this option, for example, when there is only one buffer left."
:version "27.1"
:group 'windows)
+(defcustom switch-to-prev-buffer-skip-regexp nil
+ "Buffers that `switch-to-prev-buffer' and `switch-to-next-buffer' should skip.
+The value can either be a regexp or a list of regexps. Buffers whose
+names match these regexps are skipped by `switch-to-prev-buffer'
+and `switch-to-next-buffer'.
+
+Also see `switch-to-prev-buffer-skip'."
+ :type '(choice regexp
+ (repeat regexp))
+ :version "29.1"
+ :group 'windows)
+
(defun switch-to-prev-buffer-skip-p (skip window buffer &optional bury-or-kill)
"Return non-nil if `switch-to-prev-buffer' should skip BUFFER.
SKIP is a value derived from `switch-to-prev-buffer-skip', WINDOW
the window `switch-to-prev-buffer' acts upon. Optional argument
BURY-OR-KILL is passed unchanged by `switch-to-prev-buffer' and
omitted in calls from `switch-to-next-buffer'."
- (when skip
- (if (functionp skip)
- (funcall skip window buffer bury-or-kill)
- (get-buffer-window buffer skip))))
+ (or (and skip
+ (if (functionp skip)
+ (funcall skip window buffer bury-or-kill)
+ (get-buffer-window buffer skip)))
+ (and switch-to-prev-buffer-skip-regexp
+ (or (and (stringp switch-to-prev-buffer-skip-regexp)
+ (string-match-p switch-to-prev-buffer-skip-regexp
+ (buffer-name buffer)))
+ (and (consp switch-to-prev-buffer-skip-regexp)
+ (catch 'found
+ (dolist (regexp switch-to-prev-buffer-skip-regexp)
+ (when (string-match-p regexp (buffer-name buffer))
+ (throw 'tag t)))))))))
(defun switch-to-prev-buffer (&optional window bury-or-kill)
"In WINDOW switch to previous buffer.
@@ -4886,10 +4925,7 @@ the buffer `*scratch*', creating it if necessary."
(setq frame (or frame (selected-frame)))
(or (get-next-valid-buffer (nreverse (buffer-list frame))
buffer visible-ok frame)
- (get-buffer "*scratch*")
- (let ((scratch (get-buffer-create "*scratch*")))
- (set-buffer-major-mode scratch)
- scratch)))
+ (get-scratch-buffer-create)))
(defcustom frame-auto-hide-function #'iconify-frame
"Function called to automatically hide frames.
@@ -5007,7 +5043,11 @@ minibuffer window or is dedicated to its buffer."
BUFFER-OR-NAME may be a buffer or the name of an existing buffer
and defaults to the current buffer.
-Interactively, prompt for the buffer.
+Interactively, this command will prompt for the buffer name. A
+prefix argument of 0 (zero) means that only windows in the
+current terminal's frames will be deleted. Any other prefix
+argument means that only windows in the current frame will be
+deleted.
The following non-nil values of the optional argument FRAME
have special meanings:
@@ -5044,7 +5084,21 @@ If the buffer specified by BUFFER-OR-NAME is shown in a
minibuffer window, do nothing for that window. For any window
that does not show that buffer, remove the buffer from that
window's lists of previous and next buffers."
- (interactive "bDelete windows on (buffer):\nP")
+ (interactive
+ (let ((frame (cond
+ ((and (numberp current-prefix-arg)
+ (zerop current-prefix-arg))
+ 0)
+ (current-prefix-arg t))))
+ (list (read-buffer "Delete windows on (buffer): "
+ nil nil
+ (lambda (buf)
+ (get-buffer-window
+ (if (consp buf) (car buf) buf)
+ (cond
+ ((null frame) t)
+ ((numberp frame) frame)))))
+ frame)))
(let ((buffer (window-normalize-buffer buffer-or-name))
;; Handle the "inverted" meaning of the FRAME argument wrt other
;; `window-list-1' based function.
@@ -5104,6 +5158,14 @@ all window-local buffer lists."
:version "27.1"
:group 'windows)
+(defun window--quit-restore-select-window (window)
+ "Select WINDOW after having quit another one.
+Do not select an inactive minibuffer window."
+ (when (and (window-live-p window)
+ (or (not (window-minibuffer-p window))
+ (minibuffer-window-active-p window)))
+ (select-window window)))
+
(defun quit-restore-window (&optional window bury-or-kill)
"Quit WINDOW and deal with its buffer.
WINDOW must be a live window and defaults to the selected one.
@@ -5117,7 +5179,7 @@ parameter to nil. See Info node `(elisp) Quitting Windows' for
more details.
If WINDOW's dedicated flag is t, try to delete WINDOW. If it
-equals the value 'side', restore that value when WINDOW is not
+equals the value `side', restore that value when WINDOW is not
deleted.
Optional second argument BURY-OR-KILL tells how to proceed with
@@ -5142,6 +5204,7 @@ nil means to not handle the buffer in a particular way. This
(setq window (window-normalize-window window t))
(let* ((buffer (window-buffer window))
(quit-restore (window-parameter window 'quit-restore))
+ (quit-restore-2 (nth 2 quit-restore))
(prev-buffer (catch 'prev-buffer
(dolist (buf (window-prev-buffers window))
(unless (eq (car buf) buffer)
@@ -5153,15 +5216,13 @@ nil means to not handle the buffer in a particular way. This
((and dedicated (not (eq dedicated 'side))
(window--delete window 'dedicated (eq bury-or-kill 'kill)))
;; If the previously selected window is still alive, select it.
- (when (window-live-p (nth 2 quit-restore))
- (select-window (nth 2 quit-restore))))
+ (window--quit-restore-select-window quit-restore-2))
((and (not prev-buffer)
(eq (nth 1 quit-restore) 'tab)
(eq (nth 3 quit-restore) buffer))
(tab-bar-close-tab)
;; If the previously selected window is still alive, select it.
- (when (window-live-p (nth 2 quit-restore))
- (select-window (nth 2 quit-restore))))
+ (window--quit-restore-select-window quit-restore-2))
((and (not prev-buffer)
(or (eq (nth 1 quit-restore) 'frame)
(and (eq (nth 1 quit-restore) 'window)
@@ -5173,8 +5234,7 @@ nil means to not handle the buffer in a particular way. This
;; Delete WINDOW if possible.
(window--delete window nil (eq bury-or-kill 'kill)))
;; If the previously selected window is still alive, select it.
- (when (window-live-p (nth 2 quit-restore))
- (select-window (nth 2 quit-restore))))
+ (window--quit-restore-select-window quit-restore-2))
((and (listp (setq quad (nth 1 quit-restore)))
(buffer-live-p (car quad))
(eq (nth 3 quit-restore) buffer))
@@ -5218,8 +5278,8 @@ nil means to not handle the buffer in a particular way. This
;; Reset the quit-restore parameter.
(set-window-parameter window 'quit-restore nil)
;; Select old window.
- (when (window-live-p (nth 2 quit-restore))
- (select-window (nth 2 quit-restore))))
+ ;; If the previously selected window is still alive, select it.
+ (window--quit-restore-select-window quit-restore-2))
(t
;; Show some other buffer in WINDOW and reset the quit-restore
;; parameter.
@@ -5232,8 +5292,8 @@ nil means to not handle the buffer in a particular way. This
(when (eq dedicated 'side)
(set-window-dedicated-p window 'side))
(window--delete window nil (eq bury-or-kill 'kill))
- (when (window-live-p (nth 2 quit-restore))
- (select-window (nth 2 quit-restore))))))
+ ;; If the previously selected window is still alive, select it.
+ (window--quit-restore-select-window quit-restore-2))))
;; Deal with the buffer.
(cond
@@ -5698,12 +5758,12 @@ right, if any."
;;; Balancing windows.
;; The following routine uses the recycled code from an old version of
-;; `window--resize-child-windows'. It's not very pretty, but coding it the way the
-;; new `window--resize-child-windows' code does would hardly make it any shorter or
-;; more readable (FWIW we'd need three loops - one to calculate the
-;; minimum sizes per window, one to enlarge or shrink windows until the
-;; new parent-size matches, and one where we shrink the largest/enlarge
-;; the smallest window).
+;; `window--resize-child-windows'. It's not very pretty, but coding it
+;; the way the new `window--resize-child-windows' code does would hardly
+;; make it any shorter or more readable (FWIW we'd need three loops -
+;; one to calculate the minimum sizes per window, one to enlarge or
+;; shrink windows until the new parent-size matches, and one where we
+;; shrink the largest/enlarge the smallest window).
(defun balance-windows-2 (window horizontal)
"Subroutine of `balance-windows-1'.
WINDOW must be a vertical combination (horizontal if HORIZONTAL
@@ -5714,9 +5774,10 @@ is non-nil)."
(first (window-child window))
(sub first)
(number-of-children 0)
+ (rest 0)
(parent-size (window-new-pixel window))
(total-sum parent-size)
- failed size sub-total sub-delta sub-amount rest)
+ failed size sub-total sub-delta sub-amount)
(while sub
(if (window-size-fixed-p sub horizontal)
(progn
@@ -6394,7 +6455,11 @@ windows can get as small as `window-safe-min-height' and
(window--state-put-2 ignore pixelwise))
(while window-state-put-stale-windows
(let ((window (pop window-state-put-stale-windows)))
- (when (eq (window-deletable-p window) t)
+ ;; Avoid that 'window-deletable-p' throws an error if window
+ ;; was already deleted when exiting 'with-temp-buffer' above
+ ;; (Bug#54028).
+ (when (and (window-valid-p window)
+ (eq (window-deletable-p window) t))
(delete-window window))))
(window--check frame))))
@@ -7386,6 +7451,7 @@ The actual non-nil value of this variable will be copied to the
(const display-buffer-pop-up-window)
(const display-buffer-same-window)
(const display-buffer-pop-up-frame)
+ (const display-buffer-full-frame)
(const display-buffer-in-child-frame)
(const display-buffer-below-selected)
(const display-buffer-at-bottom)
@@ -7435,9 +7501,9 @@ Its value takes effect before processing the ACTION argument of
If non-nil, this is an alist of elements (CONDITION . ACTION),
where:
- CONDITION is either a regexp matching buffer names, or a
- function that takes two arguments - a buffer name and the
- ACTION argument of `display-buffer' - and returns a boolean.
+ CONDITION is passed to `buffer-match-p', along with the buffer
+ that is to be displayed and the ACTION argument of
+ `display-buffer', to check if ACTION should be used.
ACTION is a cons cell (FUNCTIONS . ALIST), where FUNCTIONS is an
action function or a list of action functions and ALIST is an
@@ -7474,14 +7540,6 @@ ALIST. See `display-buffer' for details."
:version "24.1"
:group 'windows)
-(defcustom display-comint-buffer-action 'display-buffer-same-window
- "The action to display a comint buffer."
- :type display-buffer--action-function-custom-type
- :risky t
- :version "29.1"
- :group 'windows
- :group 'comint)
-
(defconst display-buffer-fallback-action
'((display-buffer--maybe-same-window ;FIXME: why isn't this redundant?
display-buffer-reuse-window
@@ -7498,22 +7556,16 @@ all fail. It should never be set by programs or users. See
`display-buffer'.")
(put 'display-buffer-fallback-action 'risky-local-variable t)
-(defun display-buffer-assq-regexp (buffer-name alist action)
- "Retrieve ALIST entry corresponding to BUFFER-NAME.
-This returns the cdr of the alist entry ALIST if either its key
-is a string that matches BUFFER-NAME, as reported by
-`string-match-p'; or if the key is a function that returns
-non-nil when called with three arguments: the ALIST key,
-BUFFER-NAME and ACTION. ACTION should have the form of the
-action argument passed to `display-buffer'."
+(defun display-buffer-assq-regexp (buffer-or-name alist action)
+ "Retrieve ALIST entry corresponding to buffer specified by BUFFER-OR-NAME.
+This returns the cdr of the alist entry ALIST if the entry's
+key (its car) and BUFFER-OR-NAME satisfy `buffer-match-p', using
+the key as CONDITION argument of `buffer-match-p'. ACTION should
+have the form of the action argument passed to `display-buffer'."
(catch 'match
(dolist (entry alist)
- (let ((key (car entry)))
- (when (or (and (stringp key)
- (string-match-p key buffer-name))
- (and (functionp key)
- (funcall key buffer-name action)))
- (throw 'match (cdr entry)))))))
+ (when (buffer-match-p (car entry) buffer-or-name action)
+ (throw 'match (cdr entry))))))
(defvar display-buffer--same-window-action
'(display-buffer-same-window
@@ -7546,6 +7598,7 @@ to an expression containing one of these \"action\" functions:
`display-buffer-use-least-recent-window' -- Try to avoid re-using
windows that have recently been switched to.
`display-buffer-pop-up-window' -- Pop up a new window.
+ `display-buffer-full-frame' -- Delete other windows and use the full frame.
`display-buffer-below-selected' -- Use or pop up a window below
the selected one.
`display-buffer-at-bottom' -- Use or pop up a window at the
@@ -7558,7 +7611,7 @@ to an expression containing one of these \"action\" functions:
For instance:
- (setq display-buffer-alist '((\".*\" display-buffer-at-bottom)))
+ (setq display-buffer-alist \\='((\".*\" display-buffer-at-bottom)))
Buffer display can be further customized to a very high degree;
the rest of this docstring explains some of the many
@@ -7613,7 +7666,7 @@ Action alist entries are:
the window specified in frame lines), a floating point
number (the fraction of its total height with respect to the
total height of the frame's root window), a cons cell whose
- car is 'body-lines' and whose cdr is an integer that
+ car is `body-lines' and whose cdr is an integer that
specifies the height of the window's body in frame lines, or
a function to be called with one argument - the chosen
window. That function is supposed to adjust the height of
@@ -7624,7 +7677,7 @@ Action alist entries are:
the window specified in frame lines), a floating point
number (the fraction of its total width with respect to the
width of the frame's root window), a cons cell whose car is
- 'body-columns' and whose cdr is an integer that specifies the
+ `body-columns' and whose cdr is an integer that specifies the
width of the window's body in frame columns, or a function to
be called with one argument - the chosen window. That
function is supposed to adjust the width of the window.
@@ -7632,7 +7685,7 @@ Action alist entries are:
alone on their frame and specifies the desired size of that
window either as a cons of integers (the total width and
height of the window on that frame), a cons cell whose car is
- 'body-chars' and whose cdr is a cons of integers (the desired
+ `body-chars' and whose cdr is a cons of integers (the desired
width and height of the window's body in columns and lines of
its frame), or a function to be called with one argument -
the chosen window. That function is supposed to adjust the
@@ -7682,7 +7735,7 @@ specified by the ACTION argument."
;; Otherwise, use the defined actions.
(let* ((user-action
(display-buffer-assq-regexp
- (buffer-name buffer) display-buffer-alist action))
+ buffer display-buffer-alist action))
(special-action (display-buffer--special-action buffer))
;; Extra actions from the arguments to this function:
(extra-action
@@ -7779,6 +7832,23 @@ indirectly called by the latter."
(window-dedicated-p))
(window--display-buffer buffer (selected-window) 'reuse alist)))
+(defun display-buffer-full-frame (buffer alist)
+ "Display BUFFER in the current frame, taking the entire frame.
+ALIST is an association list of action symbols and values. See
+Info node `(elisp) Buffer Display Action Alists' for details of
+such alists.
+
+This is an action function for buffer display, see Info
+node `(elisp) Buffer Display Action Functions'. It should be
+called only by `display-buffer' or a function directly or
+indirectly called by the latter."
+ (when-let ((window (or (display-buffer-reuse-window buffer alist)
+ (display-buffer-same-window buffer alist)
+ (display-buffer-pop-up-window buffer alist)
+ (display-buffer-use-some-window buffer alist))))
+ (delete-other-windows window)
+ window))
+
(defun display-buffer--maybe-same-window (buffer alist)
"Conditionally display BUFFER in the selected window.
ALIST is an association list of action symbols and values. See
@@ -8575,6 +8645,14 @@ currently selected window; otherwise it will be displayed in
another window."
(pop-to-buffer buffer display-buffer--same-window-action norecord))
+(defcustom display-comint-buffer-action display-buffer--same-window-action
+ "`display-buffer' action for displaying comint buffers."
+ :type display-buffer--action-custom-type
+ :risky t
+ :version "29.1"
+ :group 'windows
+ :group 'comint)
+
(defun read-buffer-to-switch (prompt)
"Read the name of a buffer to switch to, prompting with PROMPT.
Return the name of the buffer as a string.
@@ -8604,12 +8682,13 @@ If BUFFER-OR-NAME is nil, return the buffer returned by
`other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME
exists, return that buffer. If no such buffer exists, create a
buffer with the name BUFFER-OR-NAME and return that buffer."
- (if buffer-or-name
- (or (get-buffer buffer-or-name)
- (let ((buffer (get-buffer-create buffer-or-name)))
- (set-buffer-major-mode buffer)
- buffer))
- (other-buffer)))
+ (pcase buffer-or-name
+ ('nil (other-buffer))
+ ("*scratch*" (get-scratch-buffer-create))
+ (_ (or (get-buffer buffer-or-name)
+ (let ((buffer (get-buffer-create buffer-or-name)))
+ (set-buffer-major-mode buffer)
+ buffer)))))
(defcustom switch-to-buffer-preserve-window-point t
"If non-nil, `switch-to-buffer' tries to preserve `window-point'.
@@ -8852,6 +8931,7 @@ to deactivate this overriding action."
(let* ((old-window (or (minibuffer-selected-window) (selected-window)))
(new-window nil)
(minibuffer-depth (minibuffer-depth))
+ (obey-display switch-to-buffer-obey-display-actions)
(clearfun (make-symbol "clear-display-buffer-overriding-action"))
(postfun (make-symbol "post-display-buffer-override-next-command"))
(action (lambda (buffer alist)
@@ -8876,6 +8956,7 @@ to deactivate this overriding action."
(funcall post-function old-window new-window)))))
(fset clearfun
(lambda ()
+ (setq switch-to-buffer-obey-display-actions obey-display)
(setcar display-buffer-overriding-action
(delq action (car display-buffer-overriding-action)))))
(fset postfun
@@ -8892,6 +8973,7 @@ to deactivate this overriding action."
(add-hook 'post-command-hook postfun)
(when echofun
(add-hook 'prefix-command-echo-keystrokes-functions echofun))
+ (setq switch-to-buffer-obey-display-actions t)
(push action (car display-buffer-overriding-action))
exitfun))
@@ -9097,10 +9179,11 @@ present. See also `fit-frame-to-buffer-sizes'."
(defcustom fit-frame-to-buffer-sizes '(nil nil nil nil)
"Size boundaries of frame for `fit-frame-to-buffer'.
-This list specifies the total maximum and minimum lines and
-maximum and minimum columns of the root window of any frame that
-shall be fit to its buffer. If any of these values is non-nil,
-it overrides the corresponding argument of `fit-frame-to-buffer'.
+This list specifies the total maximum and minimum numbers of
+lines and the maximum and minimum numbers of columns of the body
+of the root window of any frame that shall be fit to its buffer.
+Any value specified by ths variable will be overridden by the
+corresponding argument of `fit-frame-to-buffer', if non-nil.
On window systems where the menubar can wrap, fitting a frame to
its buffer may swallow the last line(s). Specifying an
@@ -9296,30 +9379,30 @@ for `fit-frame-to-buffer'."
(t parent-or-display-height))
;; The following is the maximum height that fits into the
;; top and bottom margins.
- (max (- bottom-margin top-margin outer-minus-body-height))))
+ (max (- bottom-margin top-margin outer-minus-body-height) 0)))
(min-height
(cond
((numberp min-height) (* min-height line-height))
((numberp (nth 1 sizes)) (* (nth 1 sizes) line-height))
- (t (window-min-size window nil nil t))))
+ (t (window-safe-min-size window nil t))))
(max-width
- (min
- (cond
- ((numberp max-width) (* max-width char-width))
- ((numberp (nth 2 sizes)) (* (nth 2 sizes) char-width))
- (t parent-or-display-width))
- ;; The following is the maximum width that fits into the
- ;; left and right margins.
- (max (- right-margin left-margin outer-minus-body-width))))
+ (unless (eq only 'vertically)
+ (min
+ (cond
+ ((numberp max-width) (* max-width char-width))
+ ((numberp (nth 2 sizes)) (* (nth 2 sizes) char-width))
+ (t parent-or-display-width))
+ ;; The following is the maximum width that fits into the
+ ;; left and right margins.
+ (max (- right-margin left-margin outer-minus-body-width) 0))))
(min-width
(cond
((numberp min-width) (* min-width char-width))
- ((numberp (nth 3 sizes)) (nth 3 sizes))
- (t (window-min-size window t nil t))))
+ ((numberp (nth 3 sizes)) (* (nth 3 sizes) char-width))
+ (t (window-safe-min-size window t t))))
;; Note: Currently, for a new frame the sizes of the header
;; and mode line may be estimated incorrectly
- (size
- (window-text-pixel-size window from to max-width max-height))
+ (size (window-text-pixel-size window from to max-width max-height))
(width (max (car size) min-width))
(height (max (cdr size) min-height)))
;; Don't change height or width when the window's size is fixed
@@ -10014,68 +10097,119 @@ When point is already on that position, then signal an error."
(defun scroll-up-command (&optional arg)
"Scroll text of selected window upward ARG lines; or near full screen if no ARG.
+Interactively, giving this command a numerical prefix will scroll
+up by that many lines (and down by that many lines if the number
+is negative). Without a prefix, scroll up by a full screen.
+If given a `C-u -' prefix, scroll a full page down instead.
+
If `scroll-error-top-bottom' is non-nil and `scroll-up' cannot
scroll window further, move cursor to the bottom line.
When point is already on that position, then signal an error.
A near full screen is `next-screen-context-lines' less than a full screen.
Negative ARG means scroll downward.
-If ARG is the atom `-', scroll downward by nearly full screen."
+
+If ARG is the atom `-', scroll downward by nearly full screen.
+
+The command \\[set-goal-column] can be used to create a
+semipermanent goal column for this command."
(interactive "^P")
- (cond
- ((null scroll-error-top-bottom)
- (scroll-up arg))
- ((eq arg '-)
- (scroll-down-command nil))
- ((< (prefix-numeric-value arg) 0)
- (scroll-down-command (- (prefix-numeric-value arg))))
- ((eobp)
- (scroll-up arg)) ; signal error
- (t
- (condition-case nil
- (scroll-up arg)
- (end-of-buffer
- (if arg
- ;; When scrolling by ARG lines can't be done,
- ;; move by ARG lines instead.
- (forward-line arg)
- ;; When ARG is nil for full-screen scrolling,
- ;; move to the bottom of the buffer.
- (goto-char (point-max))))))))
+ (prog1
+ (cond
+ ((null scroll-error-top-bottom)
+ (scroll-up arg))
+ ((eq arg '-)
+ (scroll-down-command nil))
+ ((< (prefix-numeric-value arg) 0)
+ (scroll-down-command (- (prefix-numeric-value arg))))
+ ((eobp)
+ (scroll-up arg)) ; signal error
+ (t
+ (condition-case nil
+ (scroll-up arg)
+ (end-of-buffer
+ (if arg
+ ;; When scrolling by ARG lines can't be done,
+ ;; move by ARG lines instead.
+ (forward-line arg)
+ ;; When ARG is nil for full-screen scrolling,
+ ;; move to the bottom of the buffer.
+ (goto-char (point-max)))))))
+ (scroll-command--goto-goal-column)))
+
+(defun scroll-command--goto-goal-column ()
+ (when goal-column
+ ;; Move to the desired column.
+ (if (and line-move-visual
+ (not (or truncate-lines truncate-partial-width-windows)))
+ ;; Under line-move-visual, goal-column should be
+ ;; interpreted in units of the frame's canonical character
+ ;; width, which is exactly what vertical-motion does.
+ (vertical-motion (cons goal-column 0))
+ (line-move-to-column (truncate goal-column)))))
(put 'scroll-up-command 'scroll-command t)
(defun scroll-down-command (&optional arg)
"Scroll text of selected window down ARG lines; or near full screen if no ARG.
+Interactively, giving this command a numerical prefix will scroll
+down by that many lines (and up by that many lines if the number
+is negative). Without a prefix, scroll down by a full screen.
+If given a `C-u -' prefix, scroll a full page up instead.
+
If `scroll-error-top-bottom' is non-nil and `scroll-down' cannot
scroll window further, move cursor to the top line.
When point is already on that position, then signal an error.
A near full screen is `next-screen-context-lines' less than a full screen.
Negative ARG means scroll upward.
-If ARG is the atom `-', scroll upward by nearly full screen."
+
+If ARG is the atom `-', scroll upward by nearly full screen.
+
+The command \\[set-goal-column] can be used to create a
+semipermanent goal column for this command."
(interactive "^P")
- (cond
- ((null scroll-error-top-bottom)
- (scroll-down arg))
- ((eq arg '-)
- (scroll-up-command nil))
- ((< (prefix-numeric-value arg) 0)
- (scroll-up-command (- (prefix-numeric-value arg))))
- ((bobp)
- (scroll-down arg)) ; signal error
- (t
- (condition-case nil
- (scroll-down arg)
- (beginning-of-buffer
- (if arg
- ;; When scrolling by ARG lines can't be done,
- ;; move by ARG lines instead.
- (forward-line (- arg))
- ;; When ARG is nil for full-screen scrolling,
- ;; move to the top of the buffer.
- (goto-char (point-min))))))))
+ (prog1
+ (cond
+ ((null scroll-error-top-bottom)
+ (scroll-down arg))
+ ((eq arg '-)
+ (scroll-up-command nil))
+ ((< (prefix-numeric-value arg) 0)
+ (scroll-up-command (- (prefix-numeric-value arg))))
+ ((bobp)
+ (scroll-down arg)) ; signal error
+ (t
+ (condition-case nil
+ (scroll-down arg)
+ (beginning-of-buffer
+ (if arg
+ ;; When scrolling by ARG lines can't be done,
+ ;; move by ARG lines instead.
+ (forward-line (- arg))
+ ;; When ARG is nil for full-screen scrolling,
+ ;; move to the top of the buffer.
+ (goto-char (point-min)))))))
+ (scroll-command--goto-goal-column)))
(put 'scroll-down-command 'scroll-command t)
+(defun scroll-other-window (&optional lines)
+ "Scroll next window upward LINES lines; or near full screen if no ARG.
+See `scroll-up-command' for details."
+ (interactive "P")
+ (with-selected-window (other-window-for-scrolling)
+ (funcall (or (command-remapping #'scroll-up-command)
+ #'scroll-up-command)
+ lines)))
+
+(defun scroll-other-window-down (&optional lines)
+ "Scroll next window downward LINES lines; or near full screen if no ARG.
+See `scroll-down-command' for details."
+ (interactive "P")
+ (with-selected-window (other-window-for-scrolling)
+ (funcall (or (command-remapping #'scroll-down-command)
+ #'scroll-down-command)
+ lines)))
+
;;; Scrolling commands which scroll a line instead of full screen.
(defun scroll-up-line (&optional arg)
diff --git a/lisp/winner.el b/lisp/winner.el
index e671b83880a..38ab5f51016 100644
--- a/lisp/winner.el
+++ b/lisp/winner.el
@@ -50,7 +50,7 @@
(defcustom winner-ring-size 200
"Maximum number of stored window configurations per frame."
- :type 'integer)
+ :type 'natnum)
(defcustom winner-boring-buffers '("*Completions*")
"List of buffer names whose windows `winner-undo' will not restore.
@@ -343,8 +343,8 @@ Winner mode is a global minor mode that records the changes in
the window configuration (i.e. how the frames are partitioned
into windows) so that the changes can be \"undone\" using the
command `winner-undo'. By default this one is bound to the key
-sequence `C-c <left>'. If you change your mind (while undoing),
-you can press `C-c <right>' (calling `winner-redo')."
+sequence \\`C-c <left>'. If you change your mind (while undoing),
+you can press \\`C-c <right>' (calling `winner-redo')."
:global t
(if winner-mode
(progn
diff --git a/lisp/woman.el b/lisp/woman.el
index 2e0d9a9090d..c74faa8af48 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -841,10 +841,12 @@ Only useful when run on a graphic display such as X or MS-Windows."
:tag "WoMan Formatting"
:group 'woman)
-(defcustom woman-fill-column 65
- "Right margin for formatted text -- default is 65."
- :type 'integer
- :group 'woman-formatting)
+;; This could probably be 80 to match 'Man-width'.
+(defcustom woman-fill-column 70
+ "Right margin for formatted text -- default is 70."
+ :type 'natnum
+ :group 'woman-formatting
+ :version "29.1")
(defcustom woman-fill-frame nil
;; Based loosely on a suggestion by Theodore Jump:
@@ -1151,7 +1153,7 @@ updated (e.g. to re-interpret the current directory).
Used non-interactively, arguments are optional: if given then TOPIC
should be a topic string and non-nil RE-CACHE forces re-caching."
(interactive (list nil current-prefix-arg))
- ;; The following test is for non-interactive calls via gnudoit etc.
+ ;; The following test is for non-interactive calls via emacsclient, etc.
(if (or (not (stringp topic)) (string-match-p "\\S " topic))
(let ((file-name (woman-file-name topic re-cache)))
(if file-name
@@ -1813,8 +1815,7 @@ Argument EVENT is the invoking mouse event."
"--"
["Describe (Wo)Man Mode" describe-mode t]
["Mini Help" woman-mini-help t]
- ,@(if (fboundp 'customize-group)
- '(["Customize..." (customize-group 'woman) t]))
+ ["Customize..." (customize-group 'woman) t]
"--"
("Advanced"
["View Source" (view-file woman-last-file-name) woman-last-file-name]
@@ -2280,9 +2281,9 @@ Currently set only from \\='\\\" t in the first line of the source file.")
(replace-match woman-unpadded-space-string t t))
;; Discard optional hyphen \%; concealed newlines \<newline>;
- ;; point-size change function \sN,\s+N, \s-N:
+ ;; kerning \/, \,; point-size change function \sN,\s+N, \s-N:
(goto-char from)
- (while (re-search-forward "\\\\\\([%\n]\\|s[-+]?[0-9]+\\)" nil t)
+ (while (re-search-forward "\\\\\\([%\n/,]\\|s[-+]?[0-9]+\\)" nil t)
(woman-delete-match 0))
;; BEWARE: THIS SHOULD PROBABLY ALL BE DONE MUCH LATER!!!!!
@@ -4579,6 +4580,8 @@ logging the message."
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))
+(put 'woman-bookmark-jump 'bookmark-handler-type "WoMan")
+
;; Obsolete.
(defvar woman-version "0.551 (beta)" "WoMan version information.")
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index 559679131bd..92899e7a0c6 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -24,8 +24,9 @@
;;; Commentary:
-;; This file provides the drop part only. Currently supported protocols
-;; are XDND, Motif and the old KDE 1.x protocol.
+;; This file provides the receiving side of the XDND and Motif
+;; protocols, and both the receiving and initiating ends of the old
+;; KDE (OffiX) and new OffiX protocols.
;;; Code:
@@ -35,25 +36,26 @@
(defcustom x-dnd-test-function #'x-dnd-default-test-function
"The function drag and drop uses to determine if to accept or reject a drop.
The function takes three arguments, WINDOW, ACTION and TYPES.
-WINDOW is where the mouse is when the function is called. WINDOW may be a
-frame if the mouse isn't over a real window (i.e. menu bar, tool bar or
-scroll bar). ACTION is the suggested action from the drag and drop source,
-one of the symbols move, copy, link or ask. TYPES is a list of available
-types for the drop.
-
-The function shall return nil to reject the drop or a cons with two values,
-the wanted action as car and the wanted type as cdr. The wanted action
-can be copy, move, link, ask or private.
+WINDOW is where the mouse is when the function is called. WINDOW
+may be a frame if the mouse isn't over a real window (i.e. menu
+bar, tool bar or scroll bar). ACTION is the suggested action
+from the drag and drop source, one of the symbols move, copy,
+link or ask. TYPES is a vector of available types for the drop.
+
+Each element of TYPE should either be a string (containing the
+name of the type's X atom), or a symbol, whose name will be used.
+
+The function shall return nil to reject the drop or a cons with
+two values, the wanted action as car and the wanted type as cdr.
+The wanted action can be copy, move, link, ask or private.
+
The default value for this variable is `x-dnd-default-test-function'."
:version "22.1"
:type 'symbol
:group 'x)
-
-
(defcustom x-dnd-types-alist
- `(
- (,(purecopy "text/uri-list") . x-dnd-handle-uri-list)
+ `((,(purecopy "text/uri-list") . x-dnd-handle-uri-list)
(,(purecopy "text/x-moz-url") . x-dnd-handle-moz-url)
(,(purecopy "_NETSCAPE_URL") . x-dnd-handle-uri-list)
(,(purecopy "FILE_NAME") . x-dnd-handle-file-name)
@@ -65,7 +67,9 @@ The default value for this variable is `x-dnd-default-test-function'."
(,(purecopy "COMPOUND_TEXT") . x-dnd-insert-ctext)
(,(purecopy "STRING") . dnd-insert-text)
(,(purecopy "TEXT") . dnd-insert-text)
- )
+ (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file)
+ (,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files)
+ (,(purecopy "DndTypeText") . dnd-insert-text))
"Which function to call to handle a drop of that type.
If the type for the drop is not present, or the function is nil,
the drop is rejected. The function takes three arguments, WINDOW, ACTION
@@ -80,28 +84,82 @@ if drop is successful, nil if not."
(defcustom x-dnd-known-types
(mapcar 'purecopy
- '("text/uri-list"
- "text/x-moz-url"
- "_NETSCAPE_URL"
- "FILE_NAME"
- "UTF8_STRING"
- "text/plain;charset=UTF-8"
- "text/plain;charset=utf-8"
- "text/unicode"
- "text/plain"
- "COMPOUND_TEXT"
- "STRING"
- "TEXT"
- ))
+ '("XdndDirectSave0"
+ "text/uri-list"
+ "text/x-moz-url"
+ "_NETSCAPE_URL"
+ "FILE_NAME"
+ "UTF8_STRING"
+ "text/plain;charset=UTF-8"
+ "text/plain;charset=utf-8"
+ "text/unicode"
+ "text/plain"
+ "COMPOUND_TEXT"
+ "STRING"
+ "TEXT"
+ "DndTypeFile"
+ "DndTypeText"))
"The types accepted by default for dropped data.
The types are chosen in the order they appear in the list."
:version "22.1"
:type '(repeat string)
- :group 'x
-)
+ :group 'x)
+
+(defcustom x-dnd-use-offix-drop 'files
+ "If non-nil, use the OffiX protocol to drop files and text.
+This allows dropping (via `dired-mouse-drag-files' or
+`mouse-drag-and-drop-region-cross-program') on some old Java
+applets and old KDE programs. Turning this off allows dropping
+only text on some other programs such as xterm and urxvt.
+
+If the symbol `files', use the OffiX protocol when dropping
+files, and the fallback drop method (which is used with programs
+like xterm) for text."
+ :version "29.1"
+ :type '(choice (const :tag "Don't use the OffiX protocol for drag-and-drop" nil)
+ (const :tag "Only use the OffiX protocol to drop files" files)
+ (const :tag "Use the OffiX protocol for both files and text" t))
+ :group 'x)
+
+(defcustom x-dnd-direct-save-function #'x-dnd-save-direct
+ "Function called when a file is dropped that Emacs must save.
+It is called with two arguments: the first is either nil or t,
+and the second is a string.
+
+If the first argument is t, the second argument is the name the
+dropped file should be saved under. The function should return a
+complete file name describing where the file should be saved.
+
+It can also return nil, which means to cancel the drop.
+
+If the first argument is nil, the second is the name of the file
+that was dropped."
+ :version "29.1"
+ :type '(choice (const :tag "Prompt for name before saving"
+ x-dnd-save-direct)
+ (const :tag "Save and open immediately without prompting"
+ x-dnd-save-direct-immediately)
+ (function :tag "Other function"))
+ :group 'x)
+
+(defcustom x-dnd-copy-types '("chromium/x-renderer-taint")
+ "List of data types offered by programs that don't support `private'.
+Some programs (such as Chromium) do not support
+`XdndActionPrivate'. The default `x-dnd-test-function' will
+always return `copy' instead, for programs offering one of the
+data types in this list."
+ :version "29.1"
+ :type '(repeat string)
+ :group 'x)
;; Internal variables
+(defvar x-dnd-debug-errors nil
+ "Whether or not to signal protocol errors during drag-and-drop.
+This is useful for debugging errors in the DND code, but makes
+drag-and-drop much slower over network connections with high
+latency.")
+
(defvar x-dnd-current-state nil
"The current state for a drop.
This is an alist with one entry for each display. The value for each display
@@ -115,21 +173,38 @@ the type we want for the drop,
the action we want for the drop,
any protocol specific data.")
+(declare-function x-get-selection-internal "xselect.c"
+ (selection-symbol target-type &optional time-stamp terminal))
+(declare-function x-display-set-last-user-time "xfns.c")
+
+(defconst x-dnd-xdnd-to-action
+ '(("XdndActionPrivate" . private)
+ ("XdndActionCopy" . copy)
+ ("XdndActionMove" . move)
+ ("XdndActionLink" . link)
+ ("XdndActionAsk" . ask)
+ ("XdndActionDirectSave" . direct-save))
+ "Mapping from XDND action types to Lisp symbols.")
+
(defvar x-dnd-empty-state [nil nil nil nil nil nil nil])
(declare-function x-register-dnd-atom "xselect.c")
+(defvar x-fast-protocol-requests)
+
(defun x-dnd-init-frame (&optional frame)
"Setup drag and drop for FRAME (i.e. create appropriate properties)."
(when (eq 'x (window-system frame))
- (x-register-dnd-atom "DndProtocol" frame)
- (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame)
- (x-register-dnd-atom "XdndEnter" frame)
- (x-register-dnd-atom "XdndPosition" frame)
- (x-register-dnd-atom "XdndLeave" frame)
- (x-register-dnd-atom "XdndDrop" frame)
- (x-dnd-init-xdnd-for-frame frame)
- (x-dnd-init-motif-for-frame frame)))
+ (let ((x-fast-protocol-requests (not x-dnd-debug-errors)))
+ (x-register-dnd-atom "DndProtocol" frame)
+ (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame)
+ (x-register-dnd-atom "XdndEnter" frame)
+ (x-register-dnd-atom "XdndPosition" frame)
+ (x-register-dnd-atom "XdndLeave" frame)
+ (x-register-dnd-atom "XdndDrop" frame)
+ (x-register-dnd-atom "_DND_PROTOCOL" frame)
+ (x-dnd-init-xdnd-for-frame frame)
+ (x-dnd-init-motif-for-frame frame))))
(defun x-dnd-get-state-cons-for-frame (frame-or-window)
"Return the entry in `x-dnd-current-state' for a frame or window."
@@ -147,14 +222,22 @@ any protocol specific data.")
(defun x-dnd-default-test-function (_window _action types)
"The default test function for drag and drop.
-WINDOW is where the mouse is when this function is called. It may be
-a frame if the mouse is over the menu bar, scroll bar or tool bar.
-ACTION is the suggested action from the source, and TYPES are the
-types the drop data can have. This function only accepts drops with
-types in `x-dnd-known-types'. It always returns the action private."
+WINDOW is where the mouse is when this function is called. It
+may be a frame if the mouse is over the menu bar, scroll bar or
+tool bar. ACTION is the suggested action from the source, and
+TYPES are the types the drop data can have. This function only
+accepts drops with types in `x-dnd-known-types'. It always
+returns the action `private', unless `types' contains a value
+inside `x-dnd-copy-types'."
(let ((type (x-dnd-choose-type types)))
- (when type (cons 'private type))))
-
+ (when type (let ((list x-dnd-copy-types))
+ (catch 'out
+ (while t
+ (if (not list)
+ (throw 'out (cons 'private type))
+ (if (x-dnd-find-type (car list) types)
+ (throw 'out (cons 'copy type))
+ (setq list (cdr list))))))))))
(defun x-dnd-current-type (frame-or-window)
"Return the type we want the DND data to be in for the current drop.
@@ -167,29 +250,49 @@ FRAME-OR-WINDOW is the frame or window that the mouse is over."
(setcdr (x-dnd-get-state-cons-for-frame frame-or-window)
(copy-sequence x-dnd-empty-state)))
-(defun x-dnd-maybe-call-test-function (window action)
+(defun x-dnd-find-type (target types)
+ "Find the type TARGET in an array of types TYPES.
+TARGET must be a string, but TYPES can contain either symbols or
+strings."
+ (catch 'done
+ (dotimes (i (length types))
+ (let* ((type (aref types i))
+ (typename (if (symbolp type)
+ (symbol-name type) type)))
+ (when (equal target typename)
+ (throw 'done t))))
+ nil))
+
+(defun x-dnd-maybe-call-test-function (window action &optional xdnd)
"Call `x-dnd-test-function' if something has changed.
WINDOW is the window the mouse is over. ACTION is the suggested
action from the source. If nothing has changed, return the last
-action and type we got from `x-dnd-test-function'."
+action and type we got from `x-dnd-test-function'.
+
+XDND means the XDND protocol is being used."
(let ((buffer (when (window-live-p window)
(window-buffer window)))
(current-state (x-dnd-get-state-for-frame window)))
- (unless (and (equal buffer (aref current-state 0))
- (equal window (aref current-state 1))
- (equal action (aref current-state 3)))
- (save-current-buffer
- (when buffer (set-buffer buffer))
- (let* ((action-type (funcall x-dnd-test-function
- window
- action
- (aref current-state 2)))
- (handler (cdr (assoc (cdr action-type) x-dnd-types-alist))))
- ;; Ignore action-type if we have no handler.
- (setq current-state
- (x-dnd-save-state window
- action
- (when handler action-type)))))))
+ (if (and xdnd (x-dnd-find-type "XdndDirectSave0"
+ (aref current-state 2)))
+ (setq current-state
+ (x-dnd-save-state window 'direct-save
+ '(direct-save . "XdndDirectSave0")))
+ (unless (and (equal buffer (aref current-state 0))
+ (equal window (aref current-state 1))
+ (equal action (aref current-state 3)))
+ (save-current-buffer
+ (when buffer (set-buffer buffer))
+ (let* ((action-type (funcall x-dnd-test-function
+ window
+ action
+ (aref current-state 2)))
+ (handler (cdr (assoc (cdr action-type) x-dnd-types-alist))))
+ ;; Ignore action-type if we have no handler.
+ (setq current-state
+ (x-dnd-save-state window
+ action
+ (when handler action-type))))))))
(let ((current-state (x-dnd-get-state-for-frame window)))
(cons (aref current-state 5)
(aref current-state 4))))
@@ -322,7 +425,10 @@ nil if not."
;; If dropping in an ordinary window which we could use,
;; let dnd-open-file-other-window specify what to do.
(progn
- (when (not mouse-yank-at-point)
+ (when (and (not mouse-yank-at-point)
+ ;; If dropping on top of the mode line, insert
+ ;; the text at point instead.
+ (posn-point (event-start event)))
(goto-char (posn-point (event-start event))))
(funcall handler window action data))
;; If we can't display the file here,
@@ -336,51 +442,152 @@ nil if not."
Currently XDND, Motif and old KDE 1.x protocols are recognized."
(interactive "e")
(let* ((client-message (car (cdr (cdr event))))
- (window (posn-window (event-start event)))
- (message-atom (aref client-message 0))
- (frame (aref client-message 1))
- (format (aref client-message 2))
- (data (aref client-message 3)))
-
- (cond ((equal "DndProtocol" message-atom) ; Old KDE 1.x.
- (x-dnd-handle-old-kde event frame window message-atom format data))
-
- ((equal "_MOTIF_DRAG_AND_DROP_MESSAGE" message-atom) ; Motif
- (x-dnd-handle-motif event frame window message-atom format data))
-
- ((and (> (length message-atom) 4) ; XDND protocol.
- (equal "Xdnd" (substring message-atom 0 4)))
- (x-dnd-handle-xdnd event frame window message-atom format data)))))
+ (x-fast-protocol-requests (not x-dnd-debug-errors))
+ (window (posn-window (event-start event))))
+ (if (eq (and (consp client-message)
+ (car client-message))
+ 'XdndSelection)
+ ;; This is an internal Emacs message caused by something being
+ ;; dropped on top of a frame.
+ (progn
+ (let ((action (cdr (assoc (symbol-name (cadr client-message))
+ x-dnd-xdnd-to-action)))
+ (targets (cddr client-message))
+ (local-value (nth 2 client-message)))
+ (when (windowp window)
+ (select-window window))
+ (x-dnd-save-state window nil nil
+ (apply #'vector targets))
+ (x-dnd-maybe-call-test-function window action)
+ (unwind-protect
+ (x-dnd-drop-data event (if (framep window) window
+ (window-frame window))
+ window
+ (x-get-local-selection
+ local-value
+ (intern (x-dnd-current-type window)))
+ (x-dnd-current-type window))
+ (x-dnd-forget-drop window))))
+ (let ((message-atom (aref client-message 0))
+ (frame (aref client-message 1))
+ (format (aref client-message 2))
+ (data (aref client-message 3)))
+ (cond ((equal "DndProtocol" message-atom) ; Old KDE 1.x.
+ (x-dnd-handle-old-kde event frame window message-atom format data))
+ ((equal "_DND_PROTOCOL" message-atom) ; OffiX protocol.
+ (x-dnd-handle-offix event frame window message-atom format data))
+ ((equal "_MOTIF_DRAG_AND_DROP_MESSAGE" message-atom) ; Motif
+ (x-dnd-handle-motif event frame window message-atom format data))
+
+ ((and (> (length message-atom) 4) ; XDND protocol.
+ (equal "Xdnd" (substring message-atom 0 4)))
+ (x-dnd-handle-xdnd event frame window message-atom format data)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Old KDE protocol. Only dropping of files.
+;;; Old KDE protocol.
(declare-function x-window-property "xfns.c"
(prop &optional frame type source delete-p vector-ret-p))
-(defun x-dnd-handle-old-kde (_event frame window _message _format _data)
- "Open the files in a KDE 1.x drop."
- (let ((values (x-window-property "DndSelection" frame nil 0 t)))
- (x-dnd-handle-uri-list window 'private
- (replace-regexp-in-string "\0$" "" values))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+(defvar x-dnd-offix-old-kde-to-name '((-1 . DndTypeInvalid)
+ (0 . DndTypeUnknown)
+ (1 . DndTypeRawData)
+ (2 . DndTypeFile)
+ (3 . DndTypeFiles)
+ (4 . DndTypeText)
+ (5 . DndTypeDir)
+ (6 . DndTypeLink)
+ (7 . DndTypeExe)
+ (8 . DndTypeUrl))
+ "Alist of old KDE data types to their names.")
+
+(defun x-dnd-handle-old-kde (event frame window _message _format data)
+ "Handle an old KDE (OffiX) drop.
+EVENT, FRAME, WINDOW and DATA mean the same thing they do in
+`x-dnd-handle-offix.'"
+ (let ((proto (aref data 4)))
+ ;; If PROTO > 0, this is an old KDE drop emulated by a program
+ ;; supporting a newer version of the OffiX protocol, so we should
+ ;; wait for the corresponding modern event instead.
+ (when (zerop proto)
+ (let ((type (cdr (assq (aref data 0) x-dnd-offix-old-kde-to-name)))
+ (data (x-window-property "DndSelection" frame nil 0 t)))
+ ;; First save state.
+ (x-dnd-save-state window nil nil (vector type) nil)
+ ;; Now call the test function to decide what action to perform.
+ (x-dnd-maybe-call-test-function window 'private)
+ (unwind-protect
+ (when (windowp window)
+ (select-window window))
+ (x-dnd-drop-data event frame window data
+ (symbol-name type))
+ (x-dnd-forget-drop window))))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; New OffiX protocol.
+
+(defvar x-dnd-offix-id-to-name '((-1 . DndTypeInvalid)
+ (0 . DndTypeUnknown)
+ (1 . DndTypeRawData)
+ (2 . DndTypeFile)
+ (3 . DndTypeFiles)
+ (4 . DndTypeText)
+ (5 . DndTypeDir)
+ (6 . DndTypeLink)
+ (7 . DndTypeExe)
+ (8 . DndTypeUrl)
+ (9 . DndTypeMime)
+ (10 . DndTypePixmap))
+ "Alist of OffiX data types to their names.")
+
+(defun x-dnd-handle-offix-file (window action string)
+ "Convert OffiX file name to a regular file name.
+Then, call `x-dnd-handle-file-name'.
+
+WINDOW and ACTION mean the same as in `x-dnd-handle-file-name'.
+STRING is the raw OffiX file name data."
+ (x-dnd-handle-file-name window action
+ (replace-regexp-in-string "\0$" "" string)))
+
+(defun x-dnd-handle-offix-files (window action string)
+ "Convert OffiX file name list to a URI list.
+Then, call `x-dnd-handle-file-name'.
+
+WINDOW and ACTION mean the same as in `x-dnd-handle-file-name'.
+STRING is the raw OffiX file name data."
+ (x-dnd-handle-file-name window action
+ ;; OffiX file name lists contain one extra
+ ;; NULL byte at the end.
+ (if (string-suffix-p "\0\0" string)
+ (substring string 0 (1- (length string)))
+ string)))
+
+(defun x-dnd-handle-offix (event frame window _message-atom _format data)
+ "Handle OffiX drop event EVENT.
+FRAME is the frame where the drop happened.
+WINDOW is the window where the drop happened.
+_MESSAGE-ATOM and _FORMAT are unused.
+DATA is the vector containing the contents of the client
+message (format 32) that caused EVENT to be generated."
+ (let ((type (cdr (assq (aref data 0) x-dnd-offix-id-to-name)))
+ (data (x-window-property "_DND_SELECTION" frame nil 0 t)))
+ ;; First save state.
+ (x-dnd-save-state window nil nil (vector type) nil)
+ ;; Now call the test function to decide what action to perform.
+ (x-dnd-maybe-call-test-function window 'private)
+ (unwind-protect
+ (when (windowp window)
+ (select-window window))
+ (x-dnd-drop-data event frame window data
+ (symbol-name type))
+ (x-dnd-forget-drop window))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; XDND protocol.
-(defconst x-dnd-xdnd-to-action
- '(("XdndActionPrivate" . private)
- ("XdndActionCopy" . copy)
- ("XdndActionMove" . move)
- ("XdndActionLink" . link)
- ("XdndActionAsk" . ask))
- "Mapping from XDND action types to Lisp symbols.")
-
(declare-function x-change-window-property "xfns.c"
- (prop value &optional frame type format outer-P))
+ (prop value &optional frame type format outer-P window-id))
(defun x-dnd-init-xdnd-for-frame (frame)
"Set the XdndAware property for FRAME to indicate that we do XDND."
@@ -389,7 +596,7 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized."
frame "ATOM" 32 t))
(defun x-dnd-get-drop-width-height (frame w accept)
- "Return the width/height to be sent in a XDndStatus message.
+ "Return the width/height to be sent in a XdndStatus message.
FRAME is the frame and W is the window where the drop happened.
If ACCEPT is nil return 0 (empty rectangle),
otherwise if W is a window, return its width/height,
@@ -406,7 +613,7 @@ otherwise return the frame width/height."
0))
(defun x-dnd-get-drop-x-y (frame w)
- "Return the x/y coordinates to be sent in a XDndStatus message.
+ "Return the x/y coordinates to be sent in a XdndStatus message.
Coordinates are required to be absolute.
FRAME is the frame and W is the window where the drop happened.
If W is a window, return its absolute coordinates,
@@ -425,8 +632,6 @@ otherwise return the frame coordinates."
(declare-function x-get-atom-name "xselect.c" (value &optional frame))
(declare-function x-send-client-message "xselect.c"
(display dest from message-type format values))
-(declare-function x-get-selection-internal "xselect.c"
- (selection-symbol target-type &optional time-stamp terminal))
(defun x-dnd-version-from-flags (flags)
"Return the version byte from the 32 bit FLAGS in an XDndEnter message."
@@ -446,72 +651,111 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
(version (x-dnd-version-from-flags flags))
(more-than-3 (x-dnd-more-than-3-from-flags flags))
(dnd-source (aref data 0)))
- (message "%s %s" version more-than-3)
- (if version ;; If flags is bad, version will be nil.
- (x-dnd-save-state
- window nil nil
- (if (> more-than-3 0)
- (x-window-property "XdndTypeList"
- frame "AnyPropertyType"
- dnd-source nil t)
- (vector (x-get-atom-name (aref data 2))
- (x-get-atom-name (aref data 3))
- (x-get-atom-name (aref data 4))))))))
+ (when version ;; If flags is bad, version will be nil.
+ (x-dnd-save-state
+ window nil nil
+ (if (> more-than-3 0)
+ (x-window-property "XdndTypeList"
+ frame "AnyPropertyType"
+ dnd-source nil t)
+ (vector (x-get-atom-name (aref data 2))
+ (x-get-atom-name (aref data 3))
+ (x-get-atom-name (aref data 4))))
+ version))))
((equal "XdndPosition" message)
- (let* ((action (x-get-atom-name (aref data 4)))
+ (let* ((state (x-dnd-get-state-for-frame window))
+ (version (aref state 6))
+ (action (if (< version 2) 'copy ; `copy' is the default action.
+ (x-get-atom-name (aref data 4))))
(dnd-source (aref data 0))
(action-type (x-dnd-maybe-call-test-function
window
- (cdr (assoc action x-dnd-xdnd-to-action))))
- (reply-action (car (rassoc (car action-type)
- x-dnd-xdnd-to-action)))
+ (cdr (assoc action x-dnd-xdnd-to-action)) t))
+ (reply-action (car (rassoc
+ ;; Mozilla and some other programs
+ ;; support XDS, but only if we
+ ;; reply with `copy'. We can
+ ;; recognize these broken programs
+ ;; by checking to see if
+ ;; `XdndActionDirectSave' was
+ ;; originally specified.
+ (if (and (eq (car action-type)
+ 'direct-save)
+ (not (eq action 'direct-save)))
+ 'copy
+ (car action-type))
+ x-dnd-xdnd-to-action)))
(accept ;; 1 = accept, 0 = reject
- (if (and reply-action action-type) 1 0))
+ (if (and reply-action action-type
+ ;; Only allow drops on the text area of a
+ ;; window.
+ (not (posn-area (event-start event))))
+ 1 0))
(list-to-send
(list (string-to-number
(frame-parameter frame 'outer-window-id))
- accept ;; 1 = Accept, 0 = reject.
+ ;; 1 = accept, 0 = reject. 2 = "want position
+ ;; updates even for movement inside the given
+ ;; widget bounds".
+ (+ (if dnd-indicate-insertion-point 2 0) accept)
(x-dnd-get-drop-x-y frame window)
(x-dnd-get-drop-width-height
frame window (eq accept 1))
- (or reply-action 0)
- )))
+ ;; The no-toolkit Emacs build can actually
+ ;; receive drops from programs that speak
+ ;; versions of XDND earlier than 3 (such as
+ ;; GNUstep), since the toplevel window is the
+ ;; innermost window.
+ (if (>= version 2)
+ (or reply-action 0)
+ 0))))
(x-send-client-message
frame dnd-source frame "XdndStatus" 32 list-to-send)
- ))
+ (dnd-handle-movement (event-start event))))
((equal "XdndLeave" message)
(x-dnd-forget-drop window))
((equal "XdndDrop" message)
(if (windowp window) (select-window window))
- (let* ((dnd-source (aref data 0))
+ (let* ((state (x-dnd-get-state-for-frame frame))
+ (version (aref state 6))
+ (dnd-source (aref data 0))
(timestamp (aref data 2))
- (value (and (x-dnd-current-type window)
- (x-get-selection-internal
- 'XdndSelection
- (intern (x-dnd-current-type window))
- timestamp)))
- success action)
-
- (setq action (if value
- (condition-case info
- (x-dnd-drop-data event frame window value
- (x-dnd-current-type window))
- (error
- (message "Error: %s" info)
- nil))))
-
- (setq success (if action 1 0))
-
- (x-send-client-message
- frame dnd-source frame "XdndFinished" 32
- (list (string-to-number (frame-parameter frame 'outer-window-id))
- success ;; 1 = Success, 0 = Error
- (if success "XdndActionPrivate" 0)
- ))
- (x-dnd-forget-drop window)))
+ (current-action (aref state 5))
+ (current-type (aref state 4))
+ success action value)
+ (x-display-set-last-user-time timestamp)
+ (if (and (eq current-action 'direct-save)
+ (equal current-type "XdndDirectSave0"))
+ (x-dnd-handle-xds-drop event window dnd-source version)
+ (setq value (and (x-dnd-current-type window)
+ (x-get-selection-internal
+ 'XdndSelection
+ (intern (x-dnd-current-type window))
+ timestamp)))
+ (unwind-protect
+ (setq action (if value
+ (condition-case info
+ (x-dnd-drop-data
+ event frame window value
+ (x-dnd-current-type window))
+ (error
+ (message "Error: %s" info)
+ nil))))
+ (setq success (if action 1 0))
+ (when (>= version 2)
+ (x-send-client-message
+ frame dnd-source frame "XdndFinished" 32
+ (list (string-to-number
+ (frame-parameter frame 'outer-window-id))
+ (if (>= version 5) success 0) ;; 1 = Success, 0 = Error
+ (if (or (not action) (< version 5)) 0
+ (or (car (rassoc action
+ x-dnd-xdnd-to-action))
+ 0)))))
+ (x-dnd-forget-drop window)))))
(t (error "Unknown XDND message %s %s" message data))))
@@ -562,6 +806,88 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
(reverse bytes)
bytes)))
+(defun x-dnd-xm-unpack-targets-table-header (data)
+ "Decode the header of DATA, a Motif targets table.
+Return a list of the following fields with the given types:
+
+ Field name Type
+ - BYTE_ORDER BYTE
+ - PROTOCOL BYTE
+ - TARGET_LIST_COUNT CARD16
+ - TOTAL_DATA_SIZE CARD32"
+ (let* ((byte-order (aref data 0))
+ (protocol (aref data 1))
+ (target-list-count (x-dnd-get-motif-value
+ data 2 2 byte-order))
+ (total-data-size (x-dnd-get-motif-value
+ data 4 4 byte-order)))
+ (list byte-order protocol target-list-count
+ total-data-size)))
+
+(defun x-dnd-xm-read-single-rec (data i)
+ "Read a single rec from DATA, a Motif targets table.
+I is the offset into DATA to begin reading at. Return a list
+of (CONSUMED NTARGETS TARGETS), where CONSUMED is the number of
+bytes read from DATA, NTARGETS is the total number of targets
+inside the current rec, and TARGETS is a vector of atoms
+describing the selection targets in the current rec."
+ (let* ((byte-order (aref data 0))
+ (n-targets (x-dnd-get-motif-value
+ data i 2 byte-order))
+ (targets (make-vector n-targets nil))
+ (consumed 0))
+ (while (< consumed n-targets)
+ (aset targets consumed (x-dnd-get-motif-value
+ data (+ i 2 (* consumed 4))
+ 4 byte-order))
+ (setq consumed (1+ consumed)))
+ (list (+ 2 (* consumed 4)) n-targets targets)))
+
+(defun x-dnd-xm-read-targets-table (frame)
+ "Read the Motif targets table on FRAME.
+Return a vector of vectors of numbers, which are the atoms of the
+available selection targets for each index into the selection
+table."
+ (let* ((drag-window (x-window-property "_MOTIF_DRAG_WINDOW"
+ frame "WINDOW" 0 nil t))
+ (targets-data (x-window-property "_MOTIF_DRAG_TARGETS"
+ frame "_MOTIF_DRAG_TARGETS"
+ drag-window nil t))
+ (header (x-dnd-xm-unpack-targets-table-header targets-data))
+ (vec (make-vector (nth 2 header) nil))
+ (current-byte 8)
+ (i 0))
+ (unless (stringp targets-data)
+ (error "Expected format 8, got %s" (type-of targets-data)))
+ (prog1 vec
+ (while (< i (nth 2 header))
+ (let ((rec (x-dnd-xm-read-single-rec targets-data
+ current-byte)))
+ (aset vec i (nth 2 rec))
+ (setq current-byte (+ current-byte (car rec)))
+ (setq i (1+ i))))
+ (unless (eq current-byte (nth 3 header))
+ (error "Targets table header says size is %d, but it is actually %d"
+ (nth 3 header) current-byte)))))
+
+(defun x-dnd-xm-read-targets (frame window selection)
+ "Read targets of SELECTION on FRAME from the targets table.
+WINDOW should be the drag-and-drop operation's initiator.
+Return a vector of atoms containing the selection targets."
+ (let* ((targets-table (x-dnd-xm-read-targets-table frame))
+ (initiator-info (x-window-property selection frame
+ "_MOTIF_DRAG_INITIATOR_INFO"
+ window nil nil))
+ (byte-order (aref initiator-info 0))
+ (idx (x-dnd-get-motif-value initiator-info
+ 2 2 byte-order))
+ (vector (aref targets-table idx))
+ (i 0))
+ (prog1 vector
+ (while (< i (length vector))
+ (aset vector i
+ (intern (x-get-atom-name (aref vector i))))
+ (setq i (1+ i))))))
(defvar x-dnd-motif-message-types
'((0 . XmTOP_LEVEL_ENTER)
@@ -583,178 +909,571 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
(2 . private)) ; Motif does not have private, so use copy for private.
"Mapping from number to operation for Motif DND.")
-(defun x-dnd-handle-motif (event frame window message-atom _format data)
- (let* ((message-type (cdr (assoc (aref data 0) x-dnd-motif-message-types)))
+(defun x-dnd-handle-motif (event frame window _message-atom _format data)
+ (let* ((message-type (cdr (assoc (logand (aref data 0) #x3f)
+ x-dnd-motif-message-types)))
+ (initiator-p (eq (lsh (aref data 0) -7) 0))
(source-byteorder (aref data 1))
(my-byteorder (byteorder))
(source-flags (x-dnd-get-motif-value data 2 2 source-byteorder))
(source-action (cdr (assoc (logand ?\xF source-flags)
x-dnd-motif-to-action))))
- (cond ((eq message-type 'XmTOP_LEVEL_ENTER)
- (let* ((dnd-source (x-dnd-get-motif-value
- data 8 4 source-byteorder))
- (selection-atom (x-dnd-get-motif-value
- data 12 4 source-byteorder))
- (atom-name (x-get-atom-name selection-atom))
- (types (when atom-name
- (x-get-selection-internal (intern atom-name)
- 'TARGETS))))
- (x-dnd-forget-drop frame)
- (when types (x-dnd-save-state window nil nil
- types
- dnd-source))))
-
- ;; Can not forget drop here, LEAVE comes before DROP_START and
- ;; we need the state in DROP_START.
- ((eq message-type 'XmTOP_LEVEL_LEAVE)
- nil)
-
- ((eq message-type 'XmDRAG_MOTION)
- (let* ((state (x-dnd-get-state-for-frame frame))
- (timestamp (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 4 4
- source-byteorder)
- 4 my-byteorder))
- (x (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 8 2 source-byteorder)
- 2 my-byteorder))
- (y (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 10 2 source-byteorder)
- 2 my-byteorder))
- (dnd-source (aref state 6))
- (first-move (not (aref state 3)))
- (action-type (x-dnd-maybe-call-test-function
- window
- source-action))
- (reply-action (car (rassoc (car action-type)
- x-dnd-motif-to-action)))
- (reply-flags
- (x-dnd-motif-value-to-list
- (if reply-action
- (+ reply-action
- ?\x30 ; 30: valid drop site
- ?\x700) ; 700: can do copy, move or link
- ?\x30) ; 30: drop site, but noop.
- 2 my-byteorder))
- (reply (append
- (list
- (+ ?\x80 ; 0x80 indicates a reply.
- (if first-move
- 3 ; First time, reply is SITE_ENTER.
- 2)) ; Not first time, reply is DRAG_MOTION.
- my-byteorder)
- reply-flags
- timestamp
- x
- y)))
- (x-send-client-message frame
- dnd-source
- frame
- "_MOTIF_DRAG_AND_DROP_MESSAGE"
- 8
- reply)))
-
- ((eq message-type 'XmOPERATION_CHANGED)
- (let* ((state (x-dnd-get-state-for-frame frame))
- (timestamp (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 4 4 source-byteorder)
- 4 my-byteorder))
- (dnd-source (aref state 6))
- (action-type (x-dnd-maybe-call-test-function
- window
- source-action))
- (reply-action (car (rassoc (car action-type)
- x-dnd-motif-to-action)))
- (reply-flags
- (x-dnd-motif-value-to-list
- (if reply-action
- (+ reply-action
- ?\x30 ; 30: valid drop site
- ?\x700) ; 700: can do copy, move or link
- ?\x30) ; 30: drop site, but noop
- 2 my-byteorder))
- (reply (append
- (list
- (+ ?\x80 ; 0x80 indicates a reply.
- 8) ; 8 is OPERATION_CHANGED
- my-byteorder)
- reply-flags
- timestamp)))
- (x-send-client-message frame
- dnd-source
- frame
- "_MOTIF_DRAG_AND_DROP_MESSAGE"
- 8
- reply)))
-
- ((eq message-type 'XmDROP_START)
- (let* ((x (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 8 2 source-byteorder)
- 2 my-byteorder))
- (y (x-dnd-motif-value-to-list
- (x-dnd-get-motif-value data 10 2 source-byteorder)
- 2 my-byteorder))
- (selection-atom (x-dnd-get-motif-value
- data 12 4 source-byteorder))
- (atom-name (x-get-atom-name selection-atom))
- (dnd-source (x-dnd-get-motif-value
- data 16 4 source-byteorder))
- (action-type (x-dnd-maybe-call-test-function
- window
- source-action))
- (reply-action (car (rassoc (car action-type)
- x-dnd-motif-to-action)))
- (reply-flags
- (x-dnd-motif-value-to-list
- (if reply-action
- (+ reply-action
- ?\x30 ; 30: valid drop site
- ?\x700) ; 700: can do copy, move or link
- (+ ?\x30 ; 30: drop site, but noop.
- ?\x200)) ; 200: drop cancel.
- 2 my-byteorder))
- (reply (append
- (list
- (+ ?\x80 ; 0x80 indicates a reply.
- 5) ; DROP_START.
- my-byteorder)
- reply-flags
- x
- y))
- (timestamp (x-dnd-get-motif-value
- data 4 4 source-byteorder))
- action)
-
- (x-send-client-message frame
- dnd-source
- frame
- "_MOTIF_DRAG_AND_DROP_MESSAGE"
- 8
- reply)
- (setq action
- (when (and reply-action atom-name)
- (let* ((value (x-get-selection-internal
- (intern atom-name)
- (intern (x-dnd-current-type window)))))
- (when value
- (condition-case info
- (x-dnd-drop-data event frame window value
- (x-dnd-current-type window))
- (error
- (message "Error: %s" info)
- nil))))))
- (x-get-selection-internal
- (intern atom-name)
- (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE)
- timestamp)
- (x-dnd-forget-drop frame)))
-
- (t (error "Unknown Motif DND message %s %s" message-atom data)))))
+ (when initiator-p
+ (cond ((eq message-type 'XmTOP_LEVEL_ENTER)
+ (let* ((dnd-source (x-dnd-get-motif-value
+ data 8 4 source-byteorder))
+ (selection-atom (x-dnd-get-motif-value
+ data 12 4 source-byteorder))
+ (atom-name (x-get-atom-name selection-atom))
+ (types (x-dnd-xm-read-targets frame dnd-source
+ atom-name)))
+ (x-dnd-forget-drop frame)
+ (when types (x-dnd-save-state window nil nil
+ types dnd-source))))
+
+ ;; Can not forget drop here, LEAVE comes before DROP_START and
+ ;; we need the state in DROP_START.
+ ((eq message-type 'XmTOP_LEVEL_LEAVE)
+ nil)
+
+ ((eq message-type 'XmDRAG_MOTION)
+ (let* ((state (x-dnd-get-state-for-frame frame))
+ (timestamp (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 4 4
+ source-byteorder)
+ 4 my-byteorder))
+ (x (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 8 2 source-byteorder)
+ 2 my-byteorder))
+ (y (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 10 2 source-byteorder)
+ 2 my-byteorder))
+ (dnd-source (aref state 6))
+ (first-move (not (aref state 3)))
+ (action-type (x-dnd-maybe-call-test-function
+ window
+ source-action))
+ (reply-action (car (rassoc (car action-type)
+ x-dnd-motif-to-action)))
+ (reply-flags
+ (if (posn-area (event-start event))
+ (x-dnd-motif-value-to-list ?\x20 ; 20: invalid drop site
+ 2 my-byteorder)
+ (x-dnd-motif-value-to-list
+ (if reply-action
+ (+ reply-action
+ ?\x30 ; 30: valid drop site
+ ?\x700) ; 700: can do copy, move or link
+ ?\x30) ; 30: drop site, but noop.
+ 2 my-byteorder)))
+ (reply (append
+ (list
+ (+ ?\x80 ; 0x80 indicates a reply.
+ (if first-move
+ 3 ; First time, reply is SITE_ENTER.
+ 2)) ; Not first time, reply is DRAG_MOTION.
+ my-byteorder)
+ reply-flags
+ timestamp
+ x
+ y)))
+ (x-display-set-last-user-time timestamp)
+ (x-send-client-message frame
+ dnd-source
+ frame
+ "_MOTIF_DRAG_AND_DROP_MESSAGE"
+ 8
+ reply)
+ (dnd-handle-movement (event-start event))))
+
+ ((eq message-type 'XmOPERATION_CHANGED)
+ (let* ((state (x-dnd-get-state-for-frame frame))
+ (timestamp (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 4 4 source-byteorder)
+ 4 my-byteorder))
+ (dnd-source (aref state 6))
+ (action-type (x-dnd-maybe-call-test-function
+ window
+ source-action))
+ (reply-action (car (rassoc (car action-type)
+ x-dnd-motif-to-action)))
+ (reply-flags
+ (if (posn-area (event-start event))
+ (x-dnd-motif-value-to-list ?\x20 ; 20: invalid drop site
+ 2 my-byteorder)
+ (x-dnd-motif-value-to-list
+ (if reply-action
+ (+ reply-action
+ ?\x30 ; 30: valid drop site
+ ?\x700) ; 700: can do copy, move or link
+ ?\x30) ; 30: drop site, but noop.
+ 2 my-byteorder)))
+ (reply (append
+ (list
+ (+ ?\x80 ; 0x80 indicates a reply.
+ 8) ; 8 is OPERATION_CHANGED
+ my-byteorder)
+ reply-flags
+ timestamp)))
+ (x-display-set-last-user-time timestamp)
+ (x-send-client-message frame
+ dnd-source
+ frame
+ "_MOTIF_DRAG_AND_DROP_MESSAGE"
+ 8
+ reply)))
+
+ ((eq message-type 'XmDROP_START)
+ (when (windowp window)
+ (select-window window))
+ (let* ((x (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 8 2 source-byteorder)
+ 2 my-byteorder))
+ (y (x-dnd-motif-value-to-list
+ (x-dnd-get-motif-value data 10 2 source-byteorder)
+ 2 my-byteorder))
+ (selection-atom (x-dnd-get-motif-value
+ data 12 4 source-byteorder))
+ (atom-name (x-get-atom-name selection-atom))
+ (dnd-source (x-dnd-get-motif-value
+ data 16 4 source-byteorder)))
+
+ ;; This might be a drop from a program that doesn't use
+ ;; the Motif drag protocol. Compute all the necessary
+ ;; state here if that is true.
+ (unless (and (x-dnd-get-state-for-frame frame)
+ (aref (x-dnd-get-state-for-frame frame) 2))
+ (x-dnd-forget-drop frame)
+ (let ((types (x-dnd-xm-read-targets frame dnd-source
+ atom-name)))
+ (x-dnd-save-state window nil nil types dnd-source)))
+
+ (let* ((action-type (x-dnd-maybe-call-test-function
+ window
+ source-action))
+ (reply-action (and (not (posn-area (event-start event)))
+ (car (rassoc (car action-type)
+ x-dnd-motif-to-action))))
+ (reply-flags
+ (x-dnd-motif-value-to-list
+ (if (posn-area (event-start event))
+ (+ ?\x20 ; 20: invalid drop site
+ ?\x200) ; 200: drop cancel
+ (if reply-action
+ (+ reply-action
+ ?\x30 ; 30: valid drop site
+ ?\x700) ; 700: can do copy, move or link
+ (+ ?\x30 ; 30: drop site, but noop.
+ ?\x200))) ; 200: drop cancel.
+ 2 my-byteorder))
+ (reply (append
+ (list
+ (+ ?\x80 ; 0x80 indicates a reply.
+ 5) ; DROP_START.
+ my-byteorder)
+ reply-flags
+ x y))
+ (timestamp (x-dnd-get-motif-value
+ data 4 4 source-byteorder))
+ action)
+ (x-display-set-last-user-time timestamp)
+ (x-send-client-message frame
+ dnd-source
+ frame
+ "_MOTIF_DRAG_AND_DROP_MESSAGE"
+ 8
+ reply)
+ (unwind-protect
+ (setq action
+ (when (and reply-action atom-name)
+ (let* ((value (x-get-selection-internal
+ (intern atom-name)
+ (intern (x-dnd-current-type window))
+ timestamp)))
+ (when value
+ (condition-case info
+ (x-dnd-drop-data event frame window value
+ (x-dnd-current-type window))
+ (error
+ (message "Error: %s" info)
+ nil))))))
+ (x-get-selection-internal
+ (intern atom-name)
+ (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE)
+ timestamp)
+ (x-dnd-forget-drop frame)))))
+
+ (t (message "Unknown Motif drag-and-drop message: %s"
+ (logand (aref data 0) #x3f)))))))
;;;
+
+
+;;; Handling drops.
+
+(defvar x-treat-local-requests-remotely)
+(declare-function x-get-local-selection "xfns.c")
+
+(defun x-dnd-convert-to-offix (targets local-selection)
+ "Convert local selection data to OffiX data.
+TARGETS should be the list of targets currently available in
+`XdndSelection'. Return a list of an OffiX type, and data
+suitable for passing to `x-change-window-property', or nil if the
+data could not be converted.
+LOCAL-SELECTION should be the local selection data describing the
+selection data to convert."
+ (let ((x-treat-local-requests-remotely t)
+ file-name-data string-data)
+ (cond
+ ((and (member "FILE_NAME" targets)
+ (setq file-name-data
+ (x-get-local-selection local-selection 'FILE_NAME)))
+ (if (string-match-p "\0" file-name-data)
+ ;; This means there are multiple file names in
+ ;; XdndSelection. Convert the file name data to a format
+ ;; that OffiX understands.
+ (cons 'DndTypeFiles (concat file-name-data "\0\0"))
+ (cons 'DndTypeFile (concat file-name-data "\0"))))
+ ((and (member "STRING" targets)
+ (setq string-data
+ (x-get-local-selection local-selection 'STRING)))
+ (cons 'DndTypeText (encode-coding-string string-data
+ 'latin-1))))))
+
+(defun x-dnd-do-offix-drop (targets x y frame window-id contents)
+ "Perform an OffiX drop on WINDOW-ID with the given selection contents.
+Return non-nil if the drop succeeded, or nil if it did not
+happen, which can happen if TARGETS didn't contain anything that
+the OffiX protocol can represent.
+
+X and Y are the root window coordinates of the drop. TARGETS is
+the list of targets CONTENTS can be converted to, and CONTENTS is
+the local selection data to drop onto the target window.
+
+FRAME is the frame that will act as a source window for the
+drop."
+ (if-let* ((data (x-dnd-convert-to-offix targets contents))
+ (type-id (car (rassq (car data)
+ x-dnd-offix-id-to-name)))
+ (source-id (string-to-number
+ (frame-parameter frame 'window-id)))
+ (message-data (list type-id ; l[0] = DataType
+ 0 ; l[1] = event->xbutton.state
+ source-id ; l[2] = window
+ (+ x (* 65536 y)) ; l[3] = drop_x + 65536 * drop_y
+ 1))) ; l[4] = protocol version
+ (prog1 t
+ ;; Send a legacy (old KDE) message first. Newer clients will
+ ;; ignore it, since the protocol version is 1.
+ (x-change-window-property "DndSelection"
+ (cdr data) frame
+ "STRING" 8 nil 0)
+ (x-send-client-message frame window-id
+ frame "DndProtocol"
+ 32 message-data)
+ ;; Now send a modern _DND_PROTOCOL message.
+ (x-change-window-property "_DND_SELECTION"
+ (cdr data) frame
+ "STRING" 8 nil 0)
+ (x-send-client-message frame window-id
+ frame "_DND_PROTOCOL"
+ 32 message-data))))
+
+(defun x-dnd-handle-unsupported-drop (targets x y action window-id frame _time local-selection-data)
+ "Return non-nil if the drop described by TARGETS and ACTION should not proceed.
+X and Y are the root window coordinates of the drop.
+FRAME is the frame the drop originated on.
+WINDOW-ID is the X window the drop should happen to.
+LOCAL-SELECTION-DATA is the local selection data of the drop."
+ (let ((chosen-action nil))
+ (not (and (or (eq action 'XdndActionCopy)
+ (eq action 'XdndActionMove))
+ (not (and x-dnd-use-offix-drop local-selection-data
+ (or (not (eq x-dnd-use-offix-drop 'files))
+ (member "FILE_NAME" targets))
+ (when (x-dnd-do-offix-drop targets x
+ y frame window-id
+ local-selection-data)
+ (setq chosen-action 'XdndActionCopy))))
+ (let ((delegate-p (or (member "STRING" targets)
+ (member "UTF8_STRING" targets)
+ (member "COMPOUND_TEXT" targets)
+ (member "TEXT" targets))))
+ (prog1 delegate-p
+ ;; A string will avoid the drop emulation done in C
+ ;; code, but won't be returned from `x-begin-drag'.
+ (setq chosen-action (unless delegate-p ""))))))
+ chosen-action))
+
+(defvar x-dnd-targets-list)
+(defvar x-dnd-native-test-function)
+
+(defun x-dnd-handle-native-drop (pos action)
+ "Compute the action for a drop at POS.
+Return the appropriate drag-and-drop action for a local drop at POS.
+ACTION is the action given to `x-begin-drag'."
+ (let ((state (funcall x-dnd-test-function
+ (posn-window pos)
+ (cdr (assoc (symbol-name action)
+ x-dnd-xdnd-to-action))
+ (apply #'vector x-dnd-targets-list))))
+ (when state
+ (intern (car (rassq (car state) x-dnd-xdnd-to-action))))))
+
+(setq x-dnd-native-test-function #'x-dnd-handle-native-drop)
+
+;;; XDS protocol support.
+
+(declare-function x-begin-drag "xfns.c")
+(declare-function x-delete-window-property "xfns.c")
+(defvar selection-converter-alist)
+
+(defvar x-dnd-xds-current-file nil
+ "The file name for which a direct save is currently being performed.")
+
+(defvar x-dnd-xds-source-frame nil
+ "The frame from which a direct save is currently being performed.")
+
+(defvar x-dnd-xds-performed nil
+ "Whether or not the drop target made a request for `XdndDirectSave0'.")
+
+(defvar x-dnd-disable-motif-protocol)
+(defvar x-dnd-use-unsupported-drop)
+
+(defun x-dnd-handle-direct-save (_selection _type _value)
+ "Handle a selection request for `XdndDirectSave'."
+ (setq x-dnd-xds-performed t)
+ (let* ((uri (x-window-property "XdndDirectSave0"
+ x-dnd-xds-source-frame
+ "AnyPropertyType" nil t))
+ (local-file-uri (if (and (string-match "^file://\\([^/]*\\)" uri)
+ (not (equal (match-string 1 uri) "")))
+ (dnd-get-local-file-uri uri)
+ uri))
+ (local-name (and local-file-uri
+ (dnd-get-local-file-name local-file-uri))))
+ (if (not local-name)
+ '(STRING . "F")
+ (condition-case nil
+ (progn
+ (copy-file x-dnd-xds-current-file
+ local-name t)
+ (when (equal x-dnd-xds-current-file
+ dnd-last-dragged-remote-file)
+ (dnd-remove-last-dragged-remote-file)))
+ (:success '(STRING . "S"))
+ (error '(STRING . "E"))))))
+
+(defun x-dnd-handle-octet-stream (_selection _type _value)
+ "Handle a selecton request for `application/octet-stream'.
+Return the contents of the XDS file."
+ (cons 'application/octet-stream
+ (ignore-errors
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (setq buffer-file-coding-system 'binary)
+ (insert-file-contents-literally x-dnd-xds-current-file)
+ (buffer-substring-no-properties (point-min)
+ (point-max))))))
+
+(defun x-dnd-do-direct-save (file name frame allow-same-frame)
+ "Perform a direct save operation on FILE, from FRAME.
+FILE is the file containing the contents to drop.
+NAME is the name that should be given to the file after dropping.
+FRAME is the frame from which the drop will originate.
+ALLOW-SAME-FRAME means whether or not dropping will be allowed
+on FRAME.
+
+Return the action taken by the drop target, or nil if no action
+was taken, or the direct save failed."
+ (dnd-remove-last-dragged-remote-file)
+ (let ((file-name file)
+ (original-file-name file)
+ (selection-converter-alist
+ (append '((XdndDirectSave0 . x-dnd-handle-direct-save)
+ (application/octet-stream . x-dnd-handle-octet-stream))
+ selection-converter-alist))
+ (x-dnd-xds-current-file nil)
+ (x-dnd-xds-source-frame frame)
+ (x-dnd-xds-performed nil)
+ ;; The XDS protocol is built on top of XDND, and cannot
+ ;; possibly work with Motif or OffiX programs.
+ (x-dnd-disable-motif-protocol t)
+ (x-dnd-use-offix-drop nil)
+ (x-dnd-use-unsupported-drop nil)
+ (prop-deleted nil)
+ encoded-name)
+ (unwind-protect
+ (progn
+ (when (file-remote-p file)
+ (setq file-name (file-local-copy file))
+ (setq dnd-last-dragged-remote-file file-name)
+ (add-hook 'kill-emacs-hook
+ #'dnd-remove-last-dragged-remote-file))
+ (setq encoded-name
+ (encode-coding-string name
+ (or file-name-coding-system
+ default-file-name-coding-system)))
+ (setq x-dnd-xds-current-file file-name)
+ (x-change-window-property "XdndDirectSave0" encoded-name
+ frame "text/plain" 8 nil)
+ (gui-set-selection 'XdndSelection (concat "file://" file-name))
+ ;; FIXME: this does not work with GTK file managers, since
+ ;; they always reach for `text/uri-list' first, contrary to
+ ;; the spec.
+ (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list"
+ "application/octet-stream")
+ 'XdndActionDirectSave
+ frame nil allow-same-frame)))
+ (if (not x-dnd-xds-performed)
+ action
+ (let ((property (x-window-property "XdndDirectSave0" frame
+ "AnyPropertyType" nil t)))
+ (setq prop-deleted t)
+ ;; "System-G" deletes the property upon success.
+ (and (or (null property)
+ (and (stringp property)
+ (not (equal property ""))))
+ action)))))
+ (unless prop-deleted
+ (x-delete-window-property "XdndDirectSave0" frame))
+ ;; Delete any remote copy that was made.
+ (when (not (equal file-name original-file-name))
+ (delete-file file-name)))))
+
+(defun x-dnd-save-direct (need-name name)
+ "Handle dropping a file that should be saved immediately.
+NEED-NAME tells whether or not the file was not yet saved. NAME
+is either the name of the file, or the name the drop source wants
+us to save under.
+
+Prompt the user for a file name, then open it."
+ (if need-name
+ (let ((file-name (read-file-name "Write file: "
+ default-directory
+ nil nil name)))
+ (when (file-exists-p file-name)
+ (unless (y-or-n-p (format-message
+ "File `%s' exists; overwrite? " file-name))
+ (setq file-name nil)))
+ file-name)
+ ;; TODO: move this to dired.el once a platform-agonistic
+ ;; interface can be found.
+ (if (derived-mode-p 'dired-mode)
+ (revert-buffer)
+ (find-file name))))
+
+(defun x-dnd-save-direct-immediately (need-name name)
+ "Save and open a dropped file, like `x-dnd-save-direct'.
+NEED-NAME tells whether or not the file was not yet saved. NAME
+is either the name of the file, or the name the drop source wants
+us to save under.
+
+Unlike `x-dnd-save-direct', do not prompt for the name by which
+to save the file. Simply save it in the current directory."
+ (if need-name
+ (let ((file-name (expand-file-name name)))
+ (when (file-exists-p file-name)
+ (unless (y-or-n-p (format-message
+ "File `%s' exists; overwrite? " file-name))
+ (setq file-name nil)))
+ file-name)
+ ;; TODO: move this to dired.el once a platform-agonistic
+ ;; interface can be found.
+ (if (derived-mode-p 'dired-mode)
+ (revert-buffer)
+ (find-file name))))
+
+(defun x-dnd-handle-octet-stream-for-drop (save-to)
+ "Save the contents of the XDS selection to SAVE-TO.
+Return non-nil if successful, nil otherwise."
+ (ignore-errors
+ (let ((coding-system-for-write 'raw-text)
+ (data (x-get-selection-internal 'XdndSelection
+ 'application/octet-stream)))
+ (when data
+ (write-region data nil save-to)
+ t))))
+
+(defun x-dnd-handle-xds-drop (event window source version)
+ "Handle an XDS (X Direct Save) protocol drop.
+EVENT is the drag-n-drop event containing the drop.
+WINDOW is the window on top of which the drop is supposed to happen.
+SOURCE is the X window that sent the drop.
+VERSION is the version of the XDND protocol understood by SOURCE."
+ (if (not (windowp window))
+ ;; We can't perform an XDS drop if there's no window from which
+ ;; to determine the current directory.
+ (let* ((start (event-start event))
+ (frame (posn-window start)))
+ (x-send-client-message frame source frame
+ "XdndFinished" 32
+ (list (string-to-number
+ (frame-parameter frame
+ 'outer-window-id)))))
+ (let ((desired-name (x-window-property "XdndDirectSave0"
+ (window-frame window)
+ ;; We currently don't handle
+ ;; any alternative character
+ ;; encodings.
+ "text/plain" source))
+ (frame (window-frame window))
+ (success nil) save-to save-to-remote hostname)
+ (unwind-protect
+ (when (stringp desired-name)
+ (setq desired-name (decode-coding-string
+ desired-name
+ (or file-name-coding-system
+ default-file-name-coding-system)))
+ (let ((name (funcall x-dnd-direct-save-function
+ t desired-name)))
+ (setq save-to name save-to-remote name))
+ (when save-to
+ (if (file-remote-p save-to)
+ (setq hostname (file-remote-p save-to 'host)
+ save-to (file-local-name save-to))
+ (setq hostname (system-name)))
+ (with-selected-window window
+ (let ((uri (format "file://%s%s" hostname save-to)))
+ (x-change-window-property "XdndDirectSave0"
+ (encode-coding-string
+ (url-encode-url uri) 'ascii)
+ frame "text/plain" 8 nil source)
+ (let ((result (x-get-selection-internal 'XdndSelection
+ 'XdndDirectSave0)))
+ (cond ((equal result "F")
+ (setq success
+ (x-dnd-handle-octet-stream-for-drop save-to-remote))
+ (unless success
+ (x-change-window-property "XdndDirectSave0" ""
+ frame "text/plain" 8
+ nil source)))
+ ((equal result "S")
+ (setq success t))
+ ((equal result "E")
+ (setq success nil))
+ (t (error "Broken implementation of XDS: got %s in reply"
+ result)))
+ (when success
+ (funcall x-dnd-direct-save-function nil save-to-remote)))))))
+ ;; We assume XDS always comes from a client supporting version 2
+ ;; or later, since custom actions aren't present before.
+ (x-send-client-message frame source frame
+ "XdndFinished" 32
+ (list (string-to-number
+ (frame-parameter frame
+ 'outer-window-id))
+ (if (>= version 5)
+ (if success 1 0)
+ 0)
+ (if (or (not success)
+ (< version 5))
+ 0
+ "XdndDirectSave0")))))))
+
(provide 'x-dnd)
;;; x-dnd.el ends here
diff --git a/lisp/xdg.el b/lisp/xdg.el
index 6a0b1dedd1d..c7d9c0e785e 100644
--- a/lisp/xdg.el
+++ b/lisp/xdg.el
@@ -171,13 +171,12 @@ file:///foo/bar.jpg"
;; https://www.freedesktop.org/wiki/Software/xdg-user-dirs/
(defconst xdg-line-regexp
- (eval-when-compile
- (rx "XDG_"
- (group-n 1 (or "DESKTOP" "DOWNLOAD" "TEMPLATES" "PUBLICSHARE"
- "DOCUMENTS" "MUSIC" "PICTURES" "VIDEOS"))
- "_DIR=\""
- (group-n 2 (or "/" "$HOME/") (*? (or (not (any "\"")) "\\\"")))
- "\""))
+ (rx "XDG_"
+ (group-n 1 (or "DESKTOP" "DOWNLOAD" "TEMPLATES" "PUBLICSHARE"
+ "DOCUMENTS" "MUSIC" "PICTURES" "VIDEOS"))
+ "_DIR=\""
+ (group-n 2 (or "/" "$HOME/") (*? (or (not (any "\"")) "\\\"")))
+ "\"")
"Regexp matching non-comment lines in `xdg-user-dirs' config files.")
(defvar xdg-user-dirs nil
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index 487c6b2219d..88bc8ff6c5e 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -36,7 +36,7 @@
(require 'format-spec)
(declare-function make-xwidget "xwidget.c"
- (type title width height arguments &optional buffer related))
+ (type title width height &optional arguments buffer related))
(declare-function xwidget-buffer "xwidget.c" (xwidget))
(declare-function set-xwidget-buffer "xwidget.c" (xwidget buffer))
(declare-function xwidget-size-request "xwidget.c" (xwidget))
@@ -451,7 +451,7 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget."
xwidget-webkit--progress-update-timer
(run-at-time 0.5 0.5 #'xwidget-webkit--update-progress-timer-function
xwidget)))))
- ;; This funciton will be called multi times, so only
+ ;; This function will be called multi times, so only
;; change buffer name when the load actually completes
;; this can limit buffer-name flicker in mode-line.
(when (or (string-equal (nth 3 last-input-event)
@@ -987,6 +987,7 @@ You can retrieve the value with `xwidget-get'."
(define-key xwidget-webkit-edit-mode-map [M-up] 'xwidget-webkit-pass-command-event)
(define-key xwidget-webkit-edit-mode-map [M-down] 'xwidget-webkit-pass-command-event)
(define-key xwidget-webkit-edit-mode-map [M-return] 'xwidget-webkit-pass-command-event)
+(define-key xwidget-webkit-edit-mode-map [C-backspace] 'xwidget-webkit-pass-command-event)
(define-minor-mode xwidget-webkit-edit-mode
"Minor mode for editing the content of WebKit buffers.
diff --git a/lisp/yank-media.el b/lisp/yank-media.el
index 9836082fb2a..5cd75eb3186 100644
--- a/lisp/yank-media.el
+++ b/lisp/yank-media.el
@@ -155,30 +155,7 @@ non-supported selection data types."
(format "%s" data))
((string-match-p "\\`text/" (symbol-name data-type))
;; We may have utf-16, which Emacs won't detect automatically.
- (let ((coding-system
- (and (zerop (mod (length data) 2))
- (let ((stats (vector 0 0)))
- (dotimes (i (length data))
- (when (zerop (elt data i))
- (setf (aref stats (mod i 2))
- (1+ (aref stats (mod i 2))))))
- ;; If we have more than 90% every-other nul, then it's
- ;; pretty likely to be utf-16.
- (cond
- ((> (if (zerop (elt stats 1))
- 1
- (/ (float (elt stats 0))
- (float (elt stats 1))))
- 0.9)
- ;; Big endian.
- 'utf-16-be)
- ((> (if (zerop (elt stats 0))
- 1
- (/ (float (elt stats 1))
- (float (elt stats 0))))
- 0.9)
- ;; Little endian.
- 'utf-16-le))))))
+ (let ((coding-system (yank-media--utf-16-p data)))
(if coding-system
(decode-coding-string data coding-system)
;; Some programs add a nul character at the end of text/*
@@ -189,6 +166,25 @@ non-supported selection data types."
(t
data)))
+(defun yank-media--utf-16-p (data)
+ (and (zerop (mod (length data) 2))
+ (let ((stats (vector 0 0)))
+ (dotimes (i (length data))
+ (when (zerop (elt data i))
+ (setf (aref stats (mod i 2))
+ (1+ (aref stats (mod i 2))))))
+ ;; If we have more than 90% every-other nul, then it's
+ ;; pretty likely to be utf-16.
+ (cond
+ ((> (/ (float (elt stats 0)) (/ (length data) 2))
+ 0.9)
+ ;; Big endian.
+ 'utf-16-be)
+ ((> (/ (float (elt stats 1)) (/ (length data) 2))
+ 0.9)
+ ;; Little endian.
+ 'utf-16-le)))))
+
(provide 'yank-media)
;;; yank-media.el ends here
diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c
index fa60fc89d08..52ea304f717 100644
--- a/lwlib/lwlib-Xm.c
+++ b/lwlib/lwlib-Xm.c
@@ -115,6 +115,7 @@ static void xm_generic_callback (Widget, XtPointer, XtPointer);
static void xm_nosel_callback (Widget, XtPointer, XtPointer);
static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
+static void xm_pop_up_callback (Widget, XtPointer, XtPointer);
static void xm_internal_update_other_instances (Widget, XtPointer,
XtPointer);
static void xm_arm_callback (Widget, XtPointer, XtPointer);
@@ -269,28 +270,23 @@ static void
xm_arm_callback (Widget w, XtPointer client_data, XtPointer call_data)
{
XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *) call_data;
- widget_value *wv = (widget_value *) client_data;
- widget_instance *instance;
-
- /* Get the id of the menu bar or popup menu this widget is in. */
- while (w != NULL)
- {
- if (XmIsRowColumn (w))
- {
- unsigned char type = 0xff;
-
- XtVaGetValues (w, XmNrowColumnType, &type, NULL);
- if (type == XmMENU_BAR || type == XmMENU_POPUP)
- break;
- }
+ widget_value *wv = NULL;
+ widget_instance *instance = client_data;
+ XtPointer user_data;
+ Arg al[2];
+ int ac = 0;
- w = XtParent (w);
- }
+ XtSetArg (al[ac], XmNuserData, &user_data); ac++;
+ XtGetValues (w, al, ac);
+ wv = user_data;
- if (w != NULL)
+ if (wv != NULL)
{
- instance = lw_get_widget_instance (w);
- if (instance && instance->info->highlight_cb)
+ if (instance->info->highlight_cb
+ && (cbs->reason == XmCR_DISARM
+ || (cbs->event
+ && (cbs->event->type == EnterNotify
+ || cbs->event->type == MotionNotify))))
{
call_data = cbs->reason == XmCR_DISARM ? NULL : wv;
instance->info->highlight_cb (w, instance->info->id, call_data);
@@ -501,9 +497,11 @@ make_menu_in_widget (widget_instance* instance,
;
children = (Widget*)(void*)XtMalloc (num_children * sizeof (Widget));
+#ifndef LESSTIF_VERSION
/* WIDGET should be a RowColumn. */
if (!XmIsRowColumn (widget))
emacs_abort ();
+#endif
/* Determine whether WIDGET is a menu bar. */
type = -1;
@@ -516,8 +514,12 @@ make_menu_in_widget (widget_instance* instance,
/* Add a callback to popups and pulldowns that is called when
it is made invisible again. */
if (!menubar_p)
- XtAddCallback (XtParent (widget), XmNpopdownCallback,
- xm_pop_down_callback, (XtPointer)instance);
+ {
+ XtAddCallback (XtParent (widget), XmNpopdownCallback,
+ xm_pop_down_callback, (XtPointer) instance);
+ XtAddCallback (XtParent (widget), XmNpopupCallback,
+ xm_pop_up_callback, (XtPointer) instance);
+ }
/* Preserve the first KEEP_FIRST_CHILDREN old children. */
for (child_index = 0, cur = val; child_index < keep_first_children;
@@ -537,7 +539,7 @@ make_menu_in_widget (widget_instance* instance,
ac = 0;
XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
- XtSetArg (al[ac], XmNuserData, cur->call_data); ac++;
+ XtSetArg (al[ac], XmNuserData, cur); ac++;
if (instance->pop_up_p && !cur->contents && !cur->call_data
&& !lw_separator_p (cur->name, &separator, 1))
@@ -568,14 +570,18 @@ make_menu_in_widget (widget_instance* instance,
? XmN_OF_MANY : XmONE_OF_MANY));
++ac;
button = XmCreateToggleButton (widget, cur->name, al, ac);
- XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
- XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
+ XtAddCallback (button, XmNarmCallback, xm_arm_callback,
+ (XtPointer) instance);
+ XtAddCallback (button, XmNdisarmCallback, xm_arm_callback,
+ (XtPointer) instance);
}
else
{
button = XmCreatePushButton (widget, cur->name, al, ac);
- XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
- XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
+ XtAddCallback (button, XmNarmCallback, xm_arm_callback,
+ (XtPointer) instance);
+ XtAddCallback (button, XmNdisarmCallback, xm_arm_callback,
+ (XtPointer) instance);
}
xm_update_label (instance, button, cur);
@@ -642,7 +648,7 @@ update_one_menu_entry (widget_instance* instance,
/* update the sensitivity and userdata */
/* Common to all widget types */
XtSetSensitive (widget, val->enabled);
- XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
+ XtVaSetValues (widget, XmNuserData, val, NULL);
/* update the menu button as a label. */
if (val->this_one_change >= VISIBLE_CHANGE)
@@ -842,7 +848,7 @@ xm_update_one_widget (widget_instance* instance,
/* Common to all widget types */
XtSetSensitive (widget, val->enabled);
- XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
+ XtVaSetValues (widget, XmNuserData, val, NULL);
/* Common to all label like widgets */
if (XtIsSubclass (widget, xmLabelWidgetClass))
@@ -1787,6 +1793,7 @@ do_call (Widget widget,
int ac;
XtPointer user_data;
widget_instance* instance = (widget_instance*)closure;
+ widget_value *wv;
Widget instance_widget;
LWLIB_ID id;
@@ -1804,17 +1811,18 @@ do_call (Widget widget,
user_data = NULL;
XtSetArg (al [ac], XmNuserData, &user_data); ac++;
XtGetValues (widget, al, ac);
+ wv = user_data;
switch (type)
{
case pre_activate:
if (instance->info->pre_activate_cb)
- instance->info->pre_activate_cb (widget, id, user_data);
+ instance->info->pre_activate_cb (widget, id, wv ? wv->call_data : NULL);
break;
case selection:
if (instance->info->selection_cb)
- instance->info->selection_cb (widget, id, user_data);
+ instance->info->selection_cb (widget, id, wv ? wv->call_data : NULL);
break;
case no_selection:
@@ -1824,7 +1832,7 @@ do_call (Widget widget,
case post_activate:
if (instance->info->post_activate_cb)
- instance->info->post_activate_cb (widget, id, user_data);
+ instance->info->post_activate_cb (widget, id, wv ? wv->call_data : NULL);
break;
default:
@@ -1912,6 +1920,18 @@ xm_pop_down_callback (Widget widget,
do_call (widget, closure, post_activate);
}
+static void
+xm_pop_up_callback (Widget widget,
+ XtPointer closure,
+ XtPointer call_data)
+{
+ widget_instance *instance = (widget_instance *) closure;
+
+ if ((!instance->pop_up_p && XtParent (widget) == instance->widget)
+ || XtParent (widget) == instance->parent)
+ do_call (widget, closure, pre_activate);
+}
+
/* set the keyboard focus */
void
diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c
index 30546b60e51..863f65c915f 100644
--- a/lwlib/lwlib.c
+++ b/lwlib/lwlib.c
@@ -1324,10 +1324,14 @@ lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
{
/* Old-style separator, maybe. It's a separator if it contains
only dashes. */
- while (*label == '-')
- ++label;
- separator_p = *label == 0;
- *type = SEPARATOR_SHADOW_ETCHED_IN;
+ if (*label == '-')
+ {
+ while (*label == '-')
+ ++label;
+ separator_p = *label == 0;
+
+ *type = SEPARATOR_SHADOW_ETCHED_IN;
+ }
}
return separator_p;
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index 369162c7fec..eba85631bd8 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -48,6 +48,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif /* not emacs */
static int pointer_grabbed;
+static int keyboard_grabbed;
static XEvent menu_post_event;
static char
@@ -245,11 +246,6 @@ WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec;
int submenu_destroyed;
-/* For debug, if installation-directory is non-nil this is not an installed
- Emacs. In that case we do not grab the keyboard to make it easier to
- debug. */
-#define GRAB_KEYBOARD (EQ (Vinstallation_directory, Qnil))
-
static int next_release_must_exit;
/* Utilities */
@@ -259,7 +255,9 @@ static void
ungrab_all (Widget w, Time ungrabtime)
{
XtUngrabPointer (w, ungrabtime);
- if (GRAB_KEYBOARD) XtUngrabKeyboard (w, ungrabtime);
+
+ if (keyboard_grabbed)
+ XtUngrabKeyboard (w, ungrabtime);
}
/* Like abort, but remove grabs from widget W before. */
@@ -2104,8 +2102,10 @@ XlwMenuDestroy (Widget w)
if (pointer_grabbed)
ungrab_all ((Widget)w, CurrentTime);
pointer_grabbed = 0;
+ keyboard_grabbed = 0;
- submenu_destroyed = 1;
+ if (!XtIsShell (XtParent (w)))
+ submenu_destroyed = 1;
release_drawing_gcs (mw);
release_shadow_gcs (mw);
@@ -2720,15 +2720,22 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event)
mw->menu.cursor_shape,
event->time) == Success)
{
- if (! GRAB_KEYBOARD
- || XtGrabKeyboard ((Widget)mw, False, GrabModeAsync,
- GrabModeAsync, event->time) == Success)
+ if (true
+#ifdef emacs
+ && lucid__menu_grab_keyboard
+#endif
+ && XtGrabKeyboard ((Widget) mw, False, GrabModeAsync,
+ GrabModeAsync, event->time) == Success)
{
- XtSetKeyboardFocus((Widget)mw, None);
+ XtSetKeyboardFocus ((Widget) mw, None);
pointer_grabbed = 1;
+ keyboard_grabbed = 1;
}
else
- XtUngrabPointer ((Widget)mw, event->time);
+ {
+ XtUngrabPointer ((Widget) mw, event->time);
+ keyboard_grabbed = 0;
+ }
}
#ifdef emacs
@@ -2742,4 +2749,6 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event)
((XMotionEvent*)event)->is_hint = 0;
handle_motion_event (mw, (XMotionEvent*)event);
+
+ XlwMenuRedisplay ((Widget) mw, NULL, None);
}
diff --git a/m4/copy-file-range.m4 b/m4/copy-file-range.m4
index 4c7ec4eaafa..1b8b9d88589 100644
--- a/m4/copy-file-range.m4
+++ b/m4/copy-file-range.m4
@@ -7,6 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
[
AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
dnl Persuade glibc <unistd.h> to declare copy_file_range.
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
@@ -21,7 +22,7 @@ AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
[AC_LANG_PROGRAM(
[[#include <unistd.h>
]],
- [[ssize_t (*func) (int, off_t *, int, off_t, size_t, unsigned)
+ [[ssize_t (*func) (int, off_t *, int, off_t *, size_t, unsigned)
= copy_file_range;
return func (0, 0, 0, 0, 0, 0) & 127;
]])
@@ -32,5 +33,27 @@ AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
if test "$gl_cv_func_copy_file_range" != yes; then
HAVE_COPY_FILE_RANGE=0
+ else
+ AC_DEFINE([HAVE_COPY_FILE_RANGE], 1,
+ [Define to 1 if the function copy_file_range exists.])
+
+ case $host_os in
+ linux*)
+ AC_CACHE_CHECK([whether copy_file_range is known to work],
+ [gl_cv_copy_file_range_known_to_work],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <linux/version.h>
+ ]],
+ [[#if LINUX_VERSION_CODE < KERNEL_VERSION (5, 3, 0)
+ #error "copy_file_range is buggy"
+ #endif
+ ]])],
+ [gl_cv_copy_file_range_known_to_work=yes],
+ [gl_cv_copy_file_range_known_to_work=no])])
+ if test "$gl_cv_copy_file_range_known_to_work" = no; then
+ REPLACE_COPY_FILE_RANGE=1
+ fi;;
+ esac
fi
])
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
index 2e914dbc070..8a12bddd571 100644
--- a/m4/extern-inline.m4
+++ b/m4/extern-inline.m4
@@ -7,7 +7,22 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_EXTERN_INLINE],
[
- AH_VERBATIM([extern_inline],
+ AC_CACHE_CHECK([whether ctype.h defines __header_inline],
+ [gl_cv_have___header_inline],
+ [AC_PREPROC_IFELSE(
+ [AC_LANG_SOURCE([[#include <ctype.h>
+ #ifndef __header_inline
+ #error "<ctype.h> does not define __header_inline"
+ #endif
+ ]])],
+ [gl_cv_have___header_inline=yes],
+ [gl_cv_have___header_inline=no])])
+ if test "$gl_cv_have___header_inline" = yes; then
+ AC_DEFINE([HAVE___HEADER_INLINE], [1],
+ [Define to 1 if ctype.h defines __header_inline.])
+ fi
+
+ AH_VERBATIM([HAVE___HEADER_INLINE_1],
[/* Please see the Gnulib manual for how to use these macros.
Suppress extern inline with HP-UX cc, as it appears to be broken; see
@@ -54,7 +69,7 @@ AC_DEFUN([gl_EXTERN_INLINE],
*/
#if (((defined __APPLE__ && defined __MACH__) \
|| defined __DragonFly__ || defined __FreeBSD__) \
- && (defined __header_inline \
+ && (defined HAVE___HEADER_INLINE \
? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \
&& ! defined __clang__) \
: ((! defined _DONT_USE_CTYPE_INLINE_ \
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
index a5cf95a88be..f743ce1b025 100644
--- a/m4/fchmodat.m4
+++ b/m4/fchmodat.m4
@@ -1,4 +1,4 @@
-# fchmodat.m4 serial 6
+# fchmodat.m4 serial 7
dnl Copyright (C) 2004-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -97,6 +97,6 @@ AC_DEFUN([gl_FUNC_FCHMODAT],
# Prerequisites of lib/fchmodat.c.
AC_DEFUN([gl_PREREQ_FCHMODAT],
[
- AC_CHECK_FUNCS_ONCE([lchmod])
+ AC_CHECK_FUNCS_ONCE([readlinkat])
:
])
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 87a9a751b6a..30911d1581a 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 69
+# gnulib-common.m4 serial 73
dnl Copyright (C) 2007-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -69,7 +69,9 @@ AC_DEFUN([gl_COMMON_BODY], [
[/* Attributes. */
#if (defined __has_attribute \
&& (!defined __clang_minor__ \
- || 3 < __clang_major__ + (5 <= __clang_minor__)))
+ || (defined __apple_build_version__ \
+ ? 6000000 <= __apple_build_version__ \
+ : 3 < __clang_major__ + (5 <= __clang_minor__))))
# define _GL_HAS_ATTRIBUTE(attr) __has_attribute (__##attr##__)
#else
# define _GL_HAS_ATTRIBUTE(attr) _GL_ATTR_##attr
@@ -104,6 +106,10 @@ AC_DEFUN([gl_COMMON_BODY], [
#endif
#ifdef __has_c_attribute
+# if ((defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710 \
+ && _GL_GNUC_PREREQ (4, 6))
+# pragma GCC diagnostic ignored "-Wpedantic"
+# endif
# define _GL_HAS_C_ATTRIBUTE(attr) __has_c_attribute (__##attr##__)
#else
# define _GL_HAS_C_ATTRIBUTE(attr) 0
@@ -181,7 +187,12 @@ AC_DEFUN([gl_COMMON_BODY], [
#else
# define _GL_ATTRIBUTE_DEALLOC(f, i)
#endif
-#define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1)
+/* If gnulib's <string.h> or <wchar.h> has already defined this macro, continue
+ to use this earlier definition, since <stdlib.h> may not have been included
+ yet. */
+#ifndef _GL_ATTRIBUTE_DEALLOC_FREE
+# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1)
+#endif
/* _GL_ATTRIBUTE_DEPRECATED: Declares that an entity is deprecated.
The compiler may warn if the entity is used. */
@@ -813,6 +824,24 @@ AC_DEFUN([gl_CACHE_VAL_SILENT],
])
])
+# gl_CONDITIONAL(conditional, condition)
+# is like AM_CONDITIONAL(conditional, condition), except that it does not
+# produce an error
+# configure: error: conditional "..." was never defined.
+# Usually this means the macro was only invoked conditionally.
+# when only invoked conditionally. Instead, in that case, both the _TRUE
+# and the _FALSE case are disabled.
+AC_DEFUN([gl_CONDITIONAL],
+[
+ pushdef([AC_CONFIG_COMMANDS_PRE], [:])dnl
+ AM_CONDITIONAL([$1], [$2])
+ popdef([AC_CONFIG_COMMANDS_PRE])dnl
+ if test -z "${[$1]_TRUE}" && test -z "${[$1]_FALSE}"; then
+ [$1]_TRUE='#'
+ [$1]_FALSE='#'
+ fi
+])
+
# gl_CC_ALLOW_WARNINGS
# sets and substitutes a variable GL_CFLAG_ALLOW_WARNINGS, to a $(CC) option
# that reverts a preceding '-Werror' option, if available.
@@ -879,6 +908,72 @@ AC_DEFUN([gl_CXX_ALLOW_WARNINGS],
AC_SUBST([GL_CXXFLAG_ALLOW_WARNINGS])
])
+# gl_CC_GNULIB_WARNINGS
+# sets and substitutes a variable GL_CFLAG_GNULIB_WARNINGS, to a $(CC) option
+# set that enables or disables warnings as suitable for the Gnulib coding style.
+AC_DEFUN([gl_CC_GNULIB_WARNINGS],
+[
+ AC_REQUIRE([gl_CC_ALLOW_WARNINGS])
+ dnl Assume that the compiler supports -Wno-* options only if it also supports
+ dnl -Wno-error.
+ GL_CFLAG_GNULIB_WARNINGS=''
+ if test -n "$GL_CFLAG_ALLOW_WARNINGS"; then
+ dnl Enable these warning options:
+ dnl
+ dnl GCC clang
+ dnl -Wno-cast-qual >= 3 >= 3.9
+ dnl -Wno-conversion >= 3 >= 3.9
+ dnl -Wno-float-conversion >= 4.9 >= 3.9
+ dnl -Wno-float-equal >= 3 >= 3.9
+ dnl -Wimplicit-fallthrough >= 7 >= 3.9
+ dnl -Wno-pedantic >= 4.8 >= 3.9
+ dnl -Wno-sign-compare >= 3 >= 3.9
+ dnl -Wno-sign-conversion >= 4.3 >= 3.9
+ dnl -Wno-type-limits >= 4.3 >= 3.9
+ dnl -Wno-undef >= 3 >= 3.9
+ dnl -Wno-unsuffixed-float-constants >= 4.5
+ dnl -Wno-unused-function >= 3 >= 3.9
+ dnl -Wno-unused-parameter >= 3 >= 3.9
+ dnl
+ cat > conftest.c <<\EOF
+ #if __GNUC__ >= 3 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
+ -Wno-cast-qual
+ -Wno-conversion
+ -Wno-float-equal
+ -Wno-sign-compare
+ -Wno-undef
+ -Wno-unused-function
+ -Wno-unused-parameter
+ #endif
+ #if __GNUC__ + (__GNUC_MINOR__ >= 9) > 4 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
+ -Wno-float-conversion
+ #endif
+ #if __GNUC__ >= 7 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
+ -Wimplicit-fallthrough
+ #endif
+ #if __GNUC__ + (__GNUC_MINOR__ >= 8) > 4 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
+ -Wno-pedantic
+ #endif
+ #if __GNUC__ + (__GNUC_MINOR__ >= 3) > 4 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
+ -Wno-sign-conversion
+ -Wno-type-limits
+ #endif
+ #if __GNUC__ + (__GNUC_MINOR__ >= 5) > 4
+ -Wno-unsuffixed-float-constants
+ #endif
+EOF
+ gl_command="$CC $CFLAGS $CPPFLAGS -E conftest.c > conftest.out"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_options=`grep -v '#' conftest.out`
+ for word in $gl_options; do
+ GL_CFLAG_GNULIB_WARNINGS="$GL_CFLAG_GNULIB_WARNINGS $word"
+ done
+ fi
+ rm -f conftest.c conftest.out
+ fi
+ AC_SUBST([GL_CFLAG_GNULIB_WARNINGS])
+])
+
dnl gl_CONDITIONAL_HEADER([foo.h])
dnl takes a shell variable GL_GENERATE_FOO_H (with value true or false) as input
dnl and produces
@@ -903,7 +998,7 @@ AC_DEFUN([gl_CONDITIONAL_HEADER],
*) echo "*** gl_generate_var is not set correctly" 1>&2; exit 1 ;;
esac
AC_SUBST(gl_header_name)
- AM_CONDITIONAL(gl_generate_cond, [$gl_generate_var])
+ gl_CONDITIONAL(gl_generate_cond, [$gl_generate_var])
m4_popdef([gl_generate_cond])
m4_popdef([gl_generate_var])
m4_popdef([gl_header_name])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index c47ea915f14..fb5f1b52a43 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -3,7 +3,7 @@
#
# This file 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
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful,
@@ -140,6 +140,7 @@ AC_DEFUN([gl_EARLY],
# Code from module mktime:
# Code from module mktime-internal:
# Code from module multiarch:
+ # Code from module nanosleep:
# Code from module nocrash:
# Code from module nproc:
# Code from module nstrftime:
@@ -236,9 +237,8 @@ AC_DEFUN([gl_INIT],
gl_CONDITIONAL_HEADER([byteswap.h])
AC_PROG_MKDIR_P
gl_CANONICALIZE_LGPL
- if test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1; then
- AC_LIBOBJ([canonicalize-lgpl])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_CANONICALIZE_LGPL],
+ [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1])
gl_MODULE_INDICATOR([canonicalize-lgpl])
gl_STDLIB_MODULE_INDICATOR([canonicalize_file_name])
gl_STDLIB_MODULE_INDICATOR([realpath])
@@ -247,9 +247,9 @@ AC_DEFUN([gl_INIT],
gl_CLOCK_TIME
gl_MODULE_INDICATOR([close-stream])
gl_FUNC_COPY_FILE_RANGE
- if test $HAVE_COPY_FILE_RANGE = 0; then
- AC_LIBOBJ([copy-file-range])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_COPY_FILE_RANGE],
+ [test $HAVE_COPY_FILE_RANGE = 0 ||
+ test $REPLACE_COPY_FILE_RANGE = 1])
gl_UNISTD_MODULE_INDICATOR([copy-file-range])
AC_REQUIRE([AC_C_RESTRICT])
gl_MD5
@@ -265,10 +265,10 @@ AC_DEFUN([gl_INIT],
AC_PROG_MKDIR_P
gl_DOUBLE_SLASH_ROOT
gl_FUNC_DUP2
- if test $REPLACE_DUP2 = 1; then
- AC_LIBOBJ([dup2])
+ gl_CONDITIONAL([GL_COND_OBJ_DUP2], [test $REPLACE_DUP2 = 1])
+ AM_COND_IF([GL_COND_OBJ_DUP2], [
gl_PREREQ_DUP2
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([dup2])
gl_ENVIRON
gl_UNISTD_MODULE_INDICATOR([environ])
@@ -278,83 +278,77 @@ AC_DEFUN([gl_INIT],
gl_EXECINFO_H
gl_CONDITIONAL_HEADER([execinfo.h])
AC_PROG_MKDIR_P
- if $GL_GENERATE_EXECINFO_H; then
- AC_LIBOBJ([execinfo])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_EXECINFO], [$GL_GENERATE_EXECINFO_H])
gl_FUNC_EXPLICIT_BZERO
- if test $HAVE_EXPLICIT_BZERO = 0; then
- AC_LIBOBJ([explicit_bzero])
+ gl_CONDITIONAL([GL_COND_OBJ_EXPLICIT_BZERO], [test $HAVE_EXPLICIT_BZERO = 0])
+ AM_COND_IF([GL_COND_OBJ_EXPLICIT_BZERO], [
gl_PREREQ_EXPLICIT_BZERO
- fi
+ ])
gl_STRING_MODULE_INDICATOR([explicit_bzero])
AC_REQUIRE([gl_EXTERN_INLINE])
gl_FUNC_FACCESSAT
- if test $HAVE_FACCESSAT = 0 || test $REPLACE_FACCESSAT = 1; then
- AC_LIBOBJ([faccessat])
+ gl_CONDITIONAL([GL_COND_OBJ_FACCESSAT],
+ [test $HAVE_FACCESSAT = 0 || test $REPLACE_FACCESSAT = 1])
+ AM_COND_IF([GL_COND_OBJ_FACCESSAT], [
gl_PREREQ_FACCESSAT
- fi
+ ])
gl_MODULE_INDICATOR([faccessat])
gl_UNISTD_MODULE_INDICATOR([faccessat])
gl_FUNC_FCHMODAT
- if test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1; then
- AC_LIBOBJ([fchmodat])
+ gl_CONDITIONAL([GL_COND_OBJ_FCHMODAT],
+ [test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1])
+ AM_COND_IF([GL_COND_OBJ_FCHMODAT], [
gl_PREREQ_FCHMODAT
- fi
+ ])
gl_SYS_STAT_MODULE_INDICATOR([fchmodat])
gl_FUNC_FCNTL
- if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
- AC_LIBOBJ([fcntl])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_FCNTL],
+ [test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1])
gl_FCNTL_MODULE_INDICATOR([fcntl])
gl_FCNTL_H
gl_FCNTL_H_REQUIRE_DEFAULTS
AC_PROG_MKDIR_P
gl_FUNC_FDOPENDIR
- if test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1; then
- AC_LIBOBJ([fdopendir])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_FDOPENDIR],
+ [test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1])
gl_DIRENT_MODULE_INDICATOR([fdopendir])
gl_MODULE_INDICATOR([fdopendir])
gl_FILE_HAS_ACL
gl_FILEMODE
AC_C_FLEXIBLE_ARRAY_MEMBER
gl_FUNC_FPENDING
- if test $gl_cv_func___fpending = no; then
- AC_LIBOBJ([fpending])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_FPENDING], [test $gl_cv_func___fpending = no])
gl_FUNC_FREE
- if test $REPLACE_FREE = 1; then
- AC_LIBOBJ([free])
+ gl_CONDITIONAL([GL_COND_OBJ_FREE], [test $REPLACE_FREE = 1])
+ AM_COND_IF([GL_COND_OBJ_FREE], [
gl_PREREQ_FREE
- fi
+ ])
gl_STDLIB_MODULE_INDICATOR([free-posix])
gl_FUNC_FSTATAT
- if test $HAVE_FSTATAT = 0 || test $REPLACE_FSTATAT = 1; then
- AC_LIBOBJ([fstatat])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_FSTATAT],
+ [test $HAVE_FSTATAT = 0 || test $REPLACE_FSTATAT = 1])
gl_SYS_STAT_MODULE_INDICATOR([fstatat])
gl_FSUSAGE
- if test $gl_cv_fs_space = yes; then
- AC_LIBOBJ([fsusage])
+ gl_CONDITIONAL([GL_COND_OBJ_FSUSAGE], [test $gl_cv_fs_space = yes])
+ AM_COND_IF([GL_COND_OBJ_FSUSAGE], [
gl_PREREQ_FSUSAGE_EXTRA
- fi
+ ])
gl_FUNC_FSYNC
- if test $HAVE_FSYNC = 0; then
- AC_LIBOBJ([fsync])
+ gl_CONDITIONAL([GL_COND_OBJ_FSYNC], [test $HAVE_FSYNC = 0])
+ AM_COND_IF([GL_COND_OBJ_FSYNC], [
gl_PREREQ_FSYNC
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([fsync])
gl_FUNC_FUTIMENS
- if test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1; then
- AC_LIBOBJ([futimens])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_FUTIMENS],
+ [test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1])
gl_SYS_STAT_MODULE_INDICATOR([futimens])
AC_REQUIRE([AC_CANONICAL_HOST])
gl_GETLOADAVG
- if test $HAVE_GETLOADAVG = 0; then
- AC_LIBOBJ([getloadavg])
+ gl_CONDITIONAL([GL_COND_OBJ_GETLOADAVG], [test $HAVE_GETLOADAVG = 0])
+ AM_COND_IF([GL_COND_OBJ_GETLOADAVG], [
gl_PREREQ_GETLOADAVG
- fi
+ ])
gl_STDLIB_MODULE_INDICATOR([getloadavg])
gl_FUNC_GETOPT_GNU
dnl Because of the way gl_FUNC_GETOPT_GNU is implemented (the gl_getopt_required
@@ -364,26 +358,25 @@ AC_DEFUN([gl_INIT],
gl_CONDITIONAL_HEADER([getopt.h])
gl_CONDITIONAL_HEADER([getopt-cdefs.h])
AC_PROG_MKDIR_P
- if test $REPLACE_GETOPT = 1; then
- AC_LIBOBJ([getopt])
- AC_LIBOBJ([getopt1])
+ gl_CONDITIONAL([GL_COND_OBJ_GETOPT], [test $REPLACE_GETOPT = 1])
+ AM_COND_IF([GL_COND_OBJ_GETOPT], [
dnl Define the substituted variable GNULIB_UNISTD_H_GETOPT to 1.
gl_UNISTD_H_REQUIRE_DEFAULTS
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_UNISTD_H_GETOPT], [1])
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([getopt-posix])
AC_REQUIRE([AC_CANONICAL_HOST])
gl_FUNC_GETRANDOM
- if test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1; then
- AC_LIBOBJ([getrandom])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_GETRANDOM],
+ [test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1])
gl_SYS_RANDOM_MODULE_INDICATOR([getrandom])
gl_GETTIME
gl_FUNC_GETTIMEOFDAY
- if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then
- AC_LIBOBJ([gettimeofday])
+ gl_CONDITIONAL([GL_COND_OBJ_GETTIMEOFDAY],
+ [test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1])
+ AM_COND_IF([GL_COND_OBJ_GETTIMEOFDAY], [
gl_PREREQ_GETTIMEOFDAY
- fi
+ ])
gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
gl_IEEE754_H
gl_CONDITIONAL_HEADER([ieee754.h])
@@ -396,17 +389,15 @@ AC_DEFUN([gl_INIT],
gl_LIBGMP
gl_CONDITIONAL_HEADER([gmp.h])
AC_PROG_MKDIR_P
- if test $HAVE_LIBGMP != yes; then
- AC_LIBOBJ([mini-gmp-gnulib])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_MINI_GMP_GNULIB], [test $HAVE_LIBGMP != yes])
gl_LIMITS_H
gl_CONDITIONAL_HEADER([limits.h])
AC_PROG_MKDIR_P
gl_FUNC_LSTAT
- if test $REPLACE_LSTAT = 1; then
- AC_LIBOBJ([lstat])
+ gl_CONDITIONAL([GL_COND_OBJ_LSTAT], [test $REPLACE_LSTAT = 1])
+ AM_COND_IF([GL_COND_OBJ_LSTAT], [
gl_PREREQ_LSTAT
- fi
+ ])
gl_SYS_STAT_MODULE_INDICATOR([lstat])
gl_FUNC_MEMMEM_SIMPLE
if test $HAVE_MEMMEM = 0 || test $REPLACE_MEMMEM = 1; then
@@ -414,23 +405,23 @@ AC_DEFUN([gl_INIT],
fi
gl_STRING_MODULE_INDICATOR([memmem])
gl_FUNC_MEMPCPY
- if test $HAVE_MEMPCPY = 0; then
- AC_LIBOBJ([mempcpy])
+ gl_CONDITIONAL([GL_COND_OBJ_MEMPCPY], [test $HAVE_MEMPCPY = 0])
+ AM_COND_IF([GL_COND_OBJ_MEMPCPY], [
gl_PREREQ_MEMPCPY
- fi
+ ])
gl_STRING_MODULE_INDICATOR([mempcpy])
gl_FUNC_MEMRCHR
- if test $ac_cv_func_memrchr = no; then
- AC_LIBOBJ([memrchr])
+ gl_CONDITIONAL([GL_COND_OBJ_MEMRCHR], [test $ac_cv_func_memrchr = no])
+ AM_COND_IF([GL_COND_OBJ_MEMRCHR], [
gl_PREREQ_MEMRCHR
- fi
+ ])
gl_STRING_MODULE_INDICATOR([memrchr])
gl_MINMAX
gl_FUNC_MKOSTEMP
- if test $HAVE_MKOSTEMP = 0; then
- AC_LIBOBJ([mkostemp])
+ gl_CONDITIONAL([GL_COND_OBJ_MKOSTEMP], [test $HAVE_MKOSTEMP = 0])
+ AM_COND_IF([GL_COND_OBJ_MKOSTEMP], [
gl_PREREQ_MKOSTEMP
- fi
+ ])
gl_MODULE_INDICATOR([mkostemp])
gl_STDLIB_MODULE_INDICATOR([mkostemp])
gl_FUNC_MKTIME
@@ -440,47 +431,49 @@ AC_DEFUN([gl_INIT],
fi
gl_TIME_MODULE_INDICATOR([mktime])
gl_MULTIARCH
+ gl_FUNC_NANOSLEEP
+ gl_CONDITIONAL([GL_COND_OBJ_NANOSLEEP],
+ [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1])
+ gl_TIME_MODULE_INDICATOR([nanosleep])
gl_NPROC
gl_FUNC_GNU_STRFTIME
gl_PATHMAX
gl_FUNC_PIPE2
gl_UNISTD_MODULE_INDICATOR([pipe2])
gl_FUNC_PSELECT
- if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
- AC_LIBOBJ([pselect])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_PSELECT],
+ [test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1])
gl_SYS_SELECT_MODULE_INDICATOR([pselect])
gl_FUNC_PTHREAD_SIGMASK
- if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then
- AC_LIBOBJ([pthread_sigmask])
+ gl_CONDITIONAL([GL_COND_OBJ_PTHREAD_SIGMASK],
+ [test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1])
+ AM_COND_IF([GL_COND_OBJ_PTHREAD_SIGMASK], [
gl_PREREQ_PTHREAD_SIGMASK
- fi
+ ])
gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask])
gl_FUNC_READLINK
- if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
- AC_LIBOBJ([readlink])
+ gl_CONDITIONAL([GL_COND_OBJ_READLINK],
+ [test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1])
+ AM_COND_IF([GL_COND_OBJ_READLINK], [
gl_PREREQ_READLINK
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([readlink])
gl_FUNC_READLINKAT
- if test $HAVE_READLINKAT = 0 || test $REPLACE_READLINKAT = 1; then
- AC_LIBOBJ([readlinkat])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_READLINKAT],
+ [test $HAVE_READLINKAT = 0 || test $REPLACE_READLINKAT = 1])
gl_UNISTD_MODULE_INDICATOR([readlinkat])
gl_REGEX
- if test $ac_use_included_regex = yes; then
- AC_LIBOBJ([regex])
+ gl_CONDITIONAL([GL_COND_OBJ_REGEX], [test $ac_use_included_regex = yes])
+ AM_COND_IF([GL_COND_OBJ_REGEX], [
gl_PREREQ_REGEX
- fi
+ ])
gl_FUNC_SIG2STR
- if test $ac_cv_func_sig2str = no; then
- AC_LIBOBJ([sig2str])
+ gl_CONDITIONAL([GL_COND_OBJ_SIG2STR], [test $ac_cv_func_sig2str = no])
+ AM_COND_IF([GL_COND_OBJ_SIG2STR], [
gl_PREREQ_SIG2STR
- fi
+ ])
gl_FUNC_SIGDESCR_NP
- if test $HAVE_SIGDESCR_NP = 0; then
- AC_LIBOBJ([sigdescr_np])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_SIGDESCR_NP], [test $HAVE_SIGDESCR_NP = 0])
gl_STRING_MODULE_INDICATOR([sigdescr_np])
gl_SIGNAL_H
gl_SIGNAL_H_REQUIRE_DEFAULTS
@@ -504,6 +497,8 @@ AC_DEFUN([gl_INIT],
gl_STDIO_H
gl_STDIO_H_REQUIRE_DEFAULTS
AC_PROG_MKDIR_P
+ gl_CONDITIONAL([GL_COND_OBJ_STDIO_READ], [test $REPLACE_STDIO_READ_FUNCS = 1])
+ gl_CONDITIONAL([GL_COND_OBJ_STDIO_WRITE], [test $REPLACE_STDIO_WRITE_FUNCS = 1])
dnl No need to create extra modules for these functions. Everyone who uses
dnl <stdio.h> likely needs them.
gl_STDIO_MODULE_INDICATOR([fscanf])
@@ -531,30 +526,31 @@ AC_DEFUN([gl_INIT],
gl_STDLIB_H_REQUIRE_DEFAULTS
AC_PROG_MKDIR_P
gl_FUNC_STPCPY
- if test $HAVE_STPCPY = 0; then
- AC_LIBOBJ([stpcpy])
+ gl_CONDITIONAL([GL_COND_OBJ_STPCPY], [test $HAVE_STPCPY = 0])
+ AM_COND_IF([GL_COND_OBJ_STPCPY], [
gl_PREREQ_STPCPY
- fi
+ ])
gl_STRING_MODULE_INDICATOR([stpcpy])
gl_STRING_H
gl_STRING_H_REQUIRE_DEFAULTS
AC_PROG_MKDIR_P
gl_FUNC_STRNLEN
- if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then
- AC_LIBOBJ([strnlen])
+ gl_CONDITIONAL([GL_COND_OBJ_STRNLEN],
+ [test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1])
+ AM_COND_IF([GL_COND_OBJ_STRNLEN], [
gl_PREREQ_STRNLEN
- fi
+ ])
gl_STRING_MODULE_INDICATOR([strnlen])
gl_FUNC_STRTOIMAX
- if test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
- AC_LIBOBJ([strtoimax])
+ gl_CONDITIONAL([GL_COND_OBJ_STRTOIMAX],
+ [test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1])
+ AM_COND_IF([GL_COND_OBJ_STRTOIMAX], [
gl_PREREQ_STRTOIMAX
- fi
+ ])
gl_INTTYPES_MODULE_INDICATOR([strtoimax])
gl_FUNC_SYMLINK
- if test $HAVE_SYMLINK = 0 || test $REPLACE_SYMLINK = 1; then
- AC_LIBOBJ([symlink])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_SYMLINK],
+ [test $HAVE_SYMLINK = 0 || test $REPLACE_SYMLINK = 1])
gl_UNISTD_MODULE_INDICATOR([symlink])
gl_SYS_RANDOM_H
gl_SYS_RANDOM_H_REQUIRE_DEFAULTS
@@ -577,21 +573,21 @@ AC_DEFUN([gl_INIT],
gl_TIME_H_REQUIRE_DEFAULTS
AC_PROG_MKDIR_P
gl_TIME_R
- if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
- AC_LIBOBJ([time_r])
+ gl_CONDITIONAL([GL_COND_OBJ_TIME_R],
+ [test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1])
+ AM_COND_IF([GL_COND_OBJ_TIME_R], [
gl_PREREQ_TIME_R
- fi
+ ])
gl_TIME_MODULE_INDICATOR([time_r])
gl_TIME_RZ
- if test $HAVE_TIMEZONE_T = 0; then
- AC_LIBOBJ([time_rz])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ], [test $HAVE_TIMEZONE_T = 0])
gl_TIME_MODULE_INDICATOR([time_rz])
gl_FUNC_TIMEGM
- if test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1; then
- AC_LIBOBJ([timegm])
+ gl_CONDITIONAL([GL_COND_OBJ_TIMEGM],
+ [test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1])
+ AM_COND_IF([GL_COND_OBJ_TIMEGM], [
gl_PREREQ_TIMEGM
- fi
+ ])
gl_TIME_MODULE_INDICATOR([timegm])
gl_TIMER_TIME
gl_TIMESPEC
@@ -610,9 +606,8 @@ AC_DEFUN([gl_INIT],
[An alias of GNULIB_STDIO_SINGLE_THREAD.])
gl_FUNC_GLIBC_UNLOCKED_IO
gl_FUNC_UTIMENSAT
- if test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1; then
- AC_LIBOBJ([utimensat])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_UTIMENSAT],
+ [test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1])
gl_SYS_STAT_MODULE_INDICATOR([utimensat])
AC_C_VARARRAYS
gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=false
@@ -660,11 +655,11 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_dirfd; then
gl_FUNC_DIRFD
- if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no \
- || test $REPLACE_DIRFD = 1; then
- AC_LIBOBJ([dirfd])
+ gl_CONDITIONAL([GL_COND_OBJ_DIRFD],
+ [test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no || test $REPLACE_DIRFD = 1])
+ AM_COND_IF([GL_COND_OBJ_DIRFD], [
gl_PREREQ_DIRFD
- fi
+ ])
gl_DIRENT_MODULE_INDICATOR([dirfd])
gl_gnulib_enabled_dirfd=true
fi
@@ -686,10 +681,10 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_euidaccess; then
gl_FUNC_EUIDACCESS
- if test $HAVE_EUIDACCESS = 0; then
- AC_LIBOBJ([euidaccess])
+ gl_CONDITIONAL([GL_COND_OBJ_EUIDACCESS], [test $HAVE_EUIDACCESS = 0])
+ AM_COND_IF([GL_COND_OBJ_EUIDACCESS], [
gl_PREREQ_EUIDACCESS
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([euidaccess])
gl_gnulib_enabled_euidaccess=true
if test $HAVE_EUIDACCESS = 0; then
@@ -702,10 +697,11 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_getdtablesize; then
gl_FUNC_GETDTABLESIZE
- if test $HAVE_GETDTABLESIZE = 0 || test $REPLACE_GETDTABLESIZE = 1; then
- AC_LIBOBJ([getdtablesize])
+ gl_CONDITIONAL([GL_COND_OBJ_GETDTABLESIZE],
+ [test $HAVE_GETDTABLESIZE = 0 || test $REPLACE_GETDTABLESIZE = 1])
+ AM_COND_IF([GL_COND_OBJ_GETDTABLESIZE], [
gl_PREREQ_GETDTABLESIZE
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([getdtablesize])
gl_gnulib_enabled_getdtablesize=true
fi
@@ -714,9 +710,8 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_getgroups; then
gl_FUNC_GETGROUPS
- if test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1; then
- AC_LIBOBJ([getgroups])
- fi
+ gl_CONDITIONAL([GL_COND_OBJ_GETGROUPS],
+ [test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1])
gl_UNISTD_MODULE_INDICATOR([getgroups])
gl_gnulib_enabled_getgroups=true
if test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1; then
@@ -736,10 +731,10 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1; then
gl_FUNC_GROUP_MEMBER
- if test $HAVE_GROUP_MEMBER = 0; then
- AC_LIBOBJ([group-member])
+ gl_CONDITIONAL([GL_COND_OBJ_GROUP_MEMBER], [test $HAVE_GROUP_MEMBER = 0])
+ AM_COND_IF([GL_COND_OBJ_GROUP_MEMBER], [
gl_PREREQ_GROUP_MEMBER
- fi
+ ])
gl_UNISTD_MODULE_INDICATOR([group-member])
gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=true
if test $HAVE_GROUP_MEMBER = 0; then
@@ -754,10 +749,10 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_lchmod; then
gl_FUNC_LCHMOD
- if test $HAVE_LCHMOD = 0; then
- AC_LIBOBJ([lchmod])
+ gl_CONDITIONAL([GL_COND_OBJ_LCHMOD], [test $HAVE_LCHMOD = 0])
+ AM_COND_IF([GL_COND_OBJ_LCHMOD], [
gl_PREREQ_LCHMOD
- fi
+ ])
gl_SYS_STAT_MODULE_INDICATOR([lchmod])
gl_gnulib_enabled_lchmod=true
fi
@@ -806,10 +801,10 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_open; then
gl_FUNC_OPEN
- if test $REPLACE_OPEN = 1; then
- AC_LIBOBJ([open])
+ gl_CONDITIONAL([GL_COND_OBJ_OPEN], [test $REPLACE_OPEN = 1])
+ AM_COND_IF([GL_COND_OBJ_OPEN], [
gl_PREREQ_OPEN
- fi
+ ])
gl_FCNTL_MODULE_INDICATOR([open])
gl_gnulib_enabled_open=true
if test $REPLACE_OPEN = 1; then
@@ -827,10 +822,10 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_rawmemchr; then
gl_FUNC_RAWMEMCHR
- if test $HAVE_RAWMEMCHR = 0; then
- AC_LIBOBJ([rawmemchr])
+ gl_CONDITIONAL([GL_COND_OBJ_RAWMEMCHR], [test $HAVE_RAWMEMCHR = 0])
+ AM_COND_IF([GL_COND_OBJ_RAWMEMCHR], [
gl_PREREQ_RAWMEMCHR
- fi
+ ])
gl_STRING_MODULE_INDICATOR([rawmemchr])
gl_gnulib_enabled_rawmemchr=true
fi
@@ -889,10 +884,11 @@ AC_DEFUN([gl_INIT],
{
if ! $gl_gnulib_enabled_strtoll; then
gl_FUNC_STRTOLL
- if test $HAVE_STRTOLL = 0 || test $REPLACE_STRTOLL = 1; then
- AC_LIBOBJ([strtoll])
+ gl_CONDITIONAL([GL_COND_OBJ_STRTOLL],
+ [test $HAVE_STRTOLL = 0 || test $REPLACE_STRTOLL = 1])
+ AM_COND_IF([GL_COND_OBJ_STRTOLL], [
gl_PREREQ_STRTOLL
- fi
+ ])
gl_STDLIB_MODULE_INDICATOR([strtoll])
gl_gnulib_enabled_strtoll=true
fi
@@ -1035,16 +1031,28 @@ AC_DEFUN([gl_INIT],
AC_CONFIG_COMMANDS_PRE([
gl_libobjs=
gl_ltlibobjs=
+ gl_libobjdeps=
if test -n "$gl_LIBOBJS"; then
# Remove the extension.
+changequote(,)dnl
sed_drop_objext='s/\.o$//;s/\.obj$//'
+ sed_dirname1='s,//*,/,g'
+ sed_dirname2='s,\(.\)/$,\1,'
+ sed_dirname3='s,^[^/]*$,.,'
+ sed_dirname4='s,\(.\)/[^/]*$,\1,'
+ sed_basename1='s,.*/,,'
+changequote([, ])dnl
for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do
gl_libobjs="$gl_libobjs $i.$ac_objext"
gl_ltlibobjs="$gl_ltlibobjs $i.lo"
+ i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"`
+ i_base=`echo "$i" | sed -e "$sed_basename1"`
+ gl_libobjdeps="$gl_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po"
done
fi
AC_SUBST([gl_LIBOBJS], [$gl_libobjs])
AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs])
+ AC_SUBST([gl_LIBOBJDEPS], [$gl_libobjdeps])
])
gltests_libdeps=
gltests_ltlibdeps=
@@ -1087,17 +1095,30 @@ changequote([, ])dnl
AC_CONFIG_COMMANDS_PRE([
gltests_libobjs=
gltests_ltlibobjs=
+ gltests_libobjdeps=
if test -n "$gltests_LIBOBJS"; then
# Remove the extension.
+changequote(,)dnl
sed_drop_objext='s/\.o$//;s/\.obj$//'
+ sed_dirname1='s,//*,/,g'
+ sed_dirname2='s,\(.\)/$,\1,'
+ sed_dirname3='s,^[^/]*$,.,'
+ sed_dirname4='s,\(.\)/[^/]*$,\1,'
+ sed_basename1='s,.*/,,'
+changequote([, ])dnl
for i in `for i in $gltests_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do
gltests_libobjs="$gltests_libobjs $i.$ac_objext"
gltests_ltlibobjs="$gltests_ltlibobjs $i.lo"
+ i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"`
+ i_base=`echo "$i" | sed -e "$sed_basename1"`
+ gltests_libobjdeps="$gltests_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po"
done
fi
AC_SUBST([gltests_LIBOBJS], [$gltests_libobjs])
AC_SUBST([gltests_LTLIBOBJS], [$gltests_ltlibobjs])
+ AC_SUBST([gltests_LIBOBJDEPS], [$gltests_libobjdeps])
])
+ AC_REQUIRE([gl_CC_GNULIB_WARNINGS])
LIBGNU_LIBDEPS="$gl_libdeps"
AC_SUBST([LIBGNU_LIBDEPS])
LIBGNU_LTLIBDEPS="$gl_ltlibdeps"
@@ -1288,6 +1309,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/mkostemp.c
lib/mktime-internal.h
lib/mktime.c
+ lib/nanosleep.c
lib/nproc.c
lib/nproc.h
lib/nstrftime.c
@@ -1330,6 +1352,8 @@ AC_DEFUN([gl_FILE_LIST], [
lib/stddef.in.h
lib/stdint.in.h
lib/stdio-impl.h
+ lib/stdio-read.c
+ lib/stdio-write.c
lib/stdio.in.h
lib/stdlib.in.h
lib/stpcpy.c
@@ -1438,6 +1462,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/mktime.m4
m4/mode_t.m4
m4/multiarch.m4
+ m4/nanosleep.m4
m4/nocrash.m4
m4/nproc.m4
m4/nstrftime.m4
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
index 5baee738efd..cd43beed851 100644
--- a/m4/lchmod.m4
+++ b/m4/lchmod.m4
@@ -1,4 +1,4 @@
-#serial 8
+#serial 10
dnl Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
@@ -15,9 +15,7 @@ AC_DEFUN([gl_FUNC_LCHMOD],
dnl Persuade glibc <sys/stat.h> to declare lchmod().
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
- AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
-
- AC_CHECK_FUNCS_ONCE([lchmod lstat])
+ AC_CHECK_FUNCS_ONCE([lchmod])
if test "$ac_cv_func_lchmod" = no; then
HAVE_LCHMOD=0
fi
diff --git a/m4/libgmp.m4 b/m4/libgmp.m4
index a2dee933829..d69dcc7237a 100644
--- a/m4/libgmp.m4
+++ b/m4/libgmp.m4
@@ -1,4 +1,4 @@
-# libgmp.m4 serial 6
+# libgmp.m4 serial 7
# Configure the GMP library or a replacement.
dnl Copyright 2020-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
@@ -63,8 +63,8 @@ AC_DEFUN([gl_LIBGMP],
else
GL_GENERATE_GMP_H=true
fi
- AM_CONDITIONAL([GL_GENERATE_MINI_GMP_H],
+ gl_CONDITIONAL([GL_GENERATE_MINI_GMP_H],
[test $HAVE_LIBGMP != yes])
- AM_CONDITIONAL([GL_GENERATE_GMP_GMP_H],
+ gl_CONDITIONAL([GL_GENERATE_GMP_GMP_H],
[test $HAVE_LIBGMP = yes && test "$ac_cv_header_gmp_h" != yes])
])
diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4
index 253393e51bd..f4b5853f020 100644
--- a/m4/manywarnings.m4
+++ b/m4/manywarnings.m4
@@ -167,11 +167,13 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)],
# them here so that the above 'comm' command doesn't report a false match.
gl_AS_VAR_APPEND([$1], [' -Warray-bounds=2'])
gl_AS_VAR_APPEND([$1], [' -Wattribute-alias=2'])
+ gl_AS_VAR_APPEND([$1], [' -Wbidi-chars=any,ucn'])
gl_AS_VAR_APPEND([$1], [' -Wformat-overflow=2'])
gl_AS_VAR_APPEND([$1], [' -Wformat=2'])
gl_AS_VAR_APPEND([$1], [' -Wformat-truncation=2'])
gl_AS_VAR_APPEND([$1], [' -Wimplicit-fallthrough=5'])
gl_AS_VAR_APPEND([$1], [' -Wshift-overflow=2'])
+ gl_AS_VAR_APPEND([$1], [' -Wuse-after-free=3'])
gl_AS_VAR_APPEND([$1], [' -Wunused-const-variable=2'])
gl_AS_VAR_APPEND([$1], [' -Wvla-larger-than=4031'])
diff --git a/m4/mktime.m4 b/m4/mktime.m4
index d48f40d187b..431b17dcb0d 100644
--- a/m4/mktime.m4
+++ b/m4/mktime.m4
@@ -1,4 +1,4 @@
-# serial 36
+# serial 37
dnl Copyright (C) 2002-2003, 2005-2007, 2009-2022 Free Software Foundation,
dnl Inc.
dnl This file is free software; the Free Software Foundation
@@ -82,7 +82,8 @@ spring_forward_gap ()
instead of "TZ=America/Vancouver" in order to detect the bug even
on systems that don't support the Olson extension, or don't have the
full zoneinfo tables installed. */
- putenv ("TZ=PST8PDT,M4.1.0,M10.5.0");
+ if (putenv ("TZ=PST8PDT,M4.1.0,M10.5.0") != 0)
+ return -1;
tm.tm_year = 98;
tm.tm_mon = 3;
@@ -170,7 +171,8 @@ year_2050_test ()
instead of "TZ=America/Vancouver" in order to detect the bug even
on systems that don't support the Olson extension, or don't have the
full zoneinfo tables installed. */
- putenv ("TZ=PST8PDT,M4.1.0,M10.5.0");
+ if (putenv ("TZ=PST8PDT,M4.1.0,M10.5.0") != 0)
+ return -1;
t = mktime (&tm);
@@ -181,6 +183,25 @@ year_2050_test ()
|| (0 < t && answer - 120 <= t && t <= answer + 120));
}
+static int
+indiana_test ()
+{
+ if (putenv ("TZ=America/Indiana/Indianapolis") != 0)
+ return -1;
+ struct tm tm;
+ tm.tm_year = 1986 - 1900; tm.tm_mon = 4 - 1; tm.tm_mday = 28;
+ tm.tm_hour = 16; tm.tm_min = 24; tm.tm_sec = 50; tm.tm_isdst = 0;
+ time_t std = mktime (&tm);
+ if (! (std == 515107490 || std == 515107503))
+ return 1;
+
+ /* This platform supports TZDB, either without or with leap seconds.
+ Return true if GNU Bug#48085 is absent. */
+ tm.tm_isdst = 1;
+ time_t dst = mktime (&tm);
+ return std - dst == 60 * 60;
+}
+
int
main ()
{
@@ -236,7 +257,7 @@ main ()
result |= 16;
if (! spring_forward_gap ())
result |= 32;
- if (! year_2050_test ())
+ if (! year_2050_test () || ! indiana_test ())
result |= 64;
return result;
}]])],
diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
new file mode 100644
index 00000000000..1964b1ea47d
--- /dev/null
+++ b/m4/nanosleep.m4
@@ -0,0 +1,139 @@
+# serial 41
+
+dnl From Jim Meyering.
+dnl Check for the nanosleep function.
+dnl If not found, use the supplied replacement.
+dnl
+
+# Copyright (C) 1999-2001, 2003-2022 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_NANOSLEEP],
+[
+ AC_REQUIRE([gl_TIME_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ dnl Persuade glibc and Solaris <time.h> to declare nanosleep.
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+ AC_CHECK_DECLS_ONCE([alarm])
+
+ nanosleep_save_libs=$LIBS
+
+ # Solaris 2.5.1 needs -lposix4 to get the nanosleep function.
+ # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
+ LIB_NANOSLEEP=
+ AC_SUBST([LIB_NANOSLEEP])
+ AC_SEARCH_LIBS([nanosleep], [rt posix4],
+ [test "$ac_cv_search_nanosleep" = "none required" ||
+ LIB_NANOSLEEP=$ac_cv_search_nanosleep])
+ if test "x$ac_cv_search_nanosleep" != xno; then
+ dnl The system has a nanosleep function.
+
+ AC_REQUIRE([gl_MULTIARCH])
+ if test $APPLE_UNIVERSAL_BUILD = 1; then
+ # A universal build on Apple Mac OS X platforms.
+ # The test result would be 'no (mishandles large arguments)' in 64-bit
+ # mode but 'yes' in 32-bit mode. But we need a configuration result that
+ # is valid in both modes.
+ gl_cv_func_nanosleep='no (mishandles large arguments)'
+ fi
+
+ AC_CACHE_CHECK([for working nanosleep],
+ [gl_cv_func_nanosleep],
+ [
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+ #include <errno.h>
+ #include <limits.h>
+ #include <signal.h>
+ #include <time.h>
+ #include <unistd.h>
+ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+ #define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
+
+ #if HAVE_DECL_ALARM
+ static void
+ check_for_SIGALRM (int sig)
+ {
+ if (sig != SIGALRM)
+ _exit (1);
+ }
+ #endif
+
+ int
+ main ()
+ {
+ static struct timespec ts_sleep;
+ static struct timespec ts_remaining;
+ /* Test for major problems first. */
+ if (! nanosleep)
+ return 2;
+ ts_sleep.tv_sec = 0;
+ ts_sleep.tv_nsec = 1;
+ #if HAVE_DECL_ALARM
+ {
+ static struct sigaction act;
+ act.sa_handler = check_for_SIGALRM;
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGALRM, &act, NULL);
+ alarm (1);
+ if (nanosleep (&ts_sleep, NULL) != 0)
+ return 3;
+ /* Test for a minor problem: the handling of large arguments. */
+ ts_sleep.tv_sec = TYPE_MAXIMUM (time_t);
+ ts_sleep.tv_nsec = 999999999;
+ alarm (1);
+ if (nanosleep (&ts_sleep, &ts_remaining) != -1)
+ return 4;
+ if (errno != EINTR)
+ return 5;
+ if (ts_remaining.tv_sec <= TYPE_MAXIMUM (time_t) - 10)
+ return 6;
+ }
+ #else /* A simpler test for native Windows. */
+ if (nanosleep (&ts_sleep, &ts_remaining) < 0)
+ return 3;
+ #endif
+ return 0;
+ }]])],
+ [gl_cv_func_nanosleep=yes],
+ [case $? in dnl (
+ 4|5|6) gl_cv_func_nanosleep='no (mishandles large arguments)';; dnl (
+ *) gl_cv_func_nanosleep=no;;
+ esac],
+ [case "$host_os" in dnl ((
+ linux*) # Guess it halfway works when the kernel is Linux.
+ gl_cv_func_nanosleep='guessing no (mishandles large arguments)' ;;
+ mingw*) # Guess no on native Windows.
+ gl_cv_func_nanosleep='guessing no' ;;
+ *) # If we don't know, obey --enable-cross-guesses.
+ gl_cv_func_nanosleep="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ ])
+ case "$gl_cv_func_nanosleep" in
+ *yes)
+ REPLACE_NANOSLEEP=0
+ ;;
+ *)
+ REPLACE_NANOSLEEP=1
+ case "$gl_cv_func_nanosleep" in
+ *"mishandles large arguments"*)
+ AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], [1],
+ [Define to 1 if nanosleep mishandles large arguments.])
+ ;;
+ esac
+ ;;
+ esac
+ else
+ HAVE_NANOSLEEP=0
+ fi
+ LIBS=$nanosleep_save_libs
+])
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index cc80e77365f..42e96071f8b 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 57
+# stdio_h.m4 serial 59
dnl Copyright (C) 2007-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -40,41 +40,32 @@ AC_DEFUN_ONCE([gl_STDIO_H],
attribute "__gnu_printf__" instead of "__printf__"])
fi
- dnl This ifdef is necessary to avoid an error "missing file lib/stdio-read.c"
- dnl "expected source file, required through AC_LIBSOURCES, not found". It is
- dnl also an optimization, to avoid performing a configure check whose result
- dnl is not used. But it does not make the test of GNULIB_STDIO_H_NONBLOCKING
- dnl or GNULIB_NONBLOCKING redundant.
+ dnl This ifdef is an optimization, to avoid performing a configure check whose
+ dnl result is not used. But it does not make the test of
+ dnl GNULIB_STDIO_H_NONBLOCKING or GNULIB_NONBLOCKING redundant.
m4_ifdef([gl_NONBLOCKING_IO], [
gl_NONBLOCKING_IO
if test $gl_cv_have_nonblocking != yes; then
REPLACE_STDIO_READ_FUNCS=1
- AC_LIBOBJ([stdio-read])
fi
])
- dnl This ifdef is necessary to avoid an error "missing file lib/stdio-write.c"
- dnl "expected source file, required through AC_LIBSOURCES, not found". It is
- dnl also an optimization, to avoid performing a configure check whose result
- dnl is not used. But it does not make the test of GNULIB_STDIO_H_SIGPIPE or
- dnl GNULIB_SIGPIPE redundant.
+ dnl This ifdef is an optimization, to avoid performing a configure check whose
+ dnl result is not used. But it does not make the test of
+ dnl GNULIB_STDIO_H_SIGPIPE or GNULIB_SIGPIPE redundant.
m4_ifdef([gl_SIGNAL_SIGPIPE], [
gl_SIGNAL_SIGPIPE
if test $gl_cv_header_signal_h_SIGPIPE != yes; then
REPLACE_STDIO_WRITE_FUNCS=1
- AC_LIBOBJ([stdio-write])
fi
])
- dnl This ifdef is necessary to avoid an error "missing file lib/stdio-write.c"
- dnl "expected source file, required through AC_LIBSOURCES, not found". It is
- dnl also an optimization, to avoid performing a configure check whose result
- dnl is not used. But it does not make the test of GNULIB_STDIO_H_NONBLOCKING
- dnl or GNULIB_NONBLOCKING redundant.
+ dnl This ifdef is an optimization, to avoid performing a configure check whose
+ dnl result is not used. But it does not make the test of
+ dnl GNULIB_STDIO_H_NONBLOCKING or GNULIB_NONBLOCKING redundant.
m4_ifdef([gl_NONBLOCKING_IO], [
gl_NONBLOCKING_IO
if test $gl_cv_have_nonblocking != yes; then
REPLACE_STDIO_WRITE_FUNCS=1
- AC_LIBOBJ([stdio-write])
fi
])
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index b5a9789b818..2adbfdeef4e 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,4 +1,4 @@
-# sys_stat_h.m4 serial 41 -*- Autoconf -*-
+# sys_stat_h.m4 serial 42 -*- Autoconf -*-
dnl Copyright (C) 2006-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -46,7 +46,7 @@ AC_DEFUN_ONCE([gl_SYS_STAT_H],
dnl Check for declarations of anything we want to poison if the
dnl corresponding gnulib module is not in use.
gl_WARN_ON_USE_PREPARE([[#include <sys/stat.h>
- ]], [fchmodat fstat fstatat futimens getumask lchmod lstat
+ ]], [chmod fchmodat fstat fstatat futimens getumask lchmod lstat
mkdirat mkfifo mkfifoat mknod mknodat stat utimensat])
AC_REQUIRE([AC_C_RESTRICT])
@@ -72,6 +72,7 @@ AC_DEFUN([gl_SYS_STAT_H_REQUIRE_DEFAULTS],
[
m4_defun(GL_MODULE_INDICATOR_PREFIX[_SYS_STAT_H_MODULE_INDICATOR_DEFAULTS], [
gl_UNISTD_H_REQUIRE_DEFAULTS dnl for REPLACE_FCHDIR
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CHMOD])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FCHMODAT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTAT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTATAT])
@@ -112,6 +113,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
HAVE_MKNOD=1; AC_SUBST([HAVE_MKNOD])
HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT])
HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT])
+ REPLACE_CHMOD=0; AC_SUBST([REPLACE_CHMOD])
REPLACE_FCHMODAT=0; AC_SUBST([REPLACE_FCHMODAT])
REPLACE_FSTAT=0; AC_SUBST([REPLACE_FSTAT])
REPLACE_FSTATAT=0; AC_SUBST([REPLACE_FSTATAT])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index f93f97a1bda..4c66ccc0a40 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -222,6 +222,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
REPLACE_ACCESS=0; AC_SUBST([REPLACE_ACCESS])
REPLACE_CHOWN=0; AC_SUBST([REPLACE_CHOWN])
REPLACE_CLOSE=0; AC_SUBST([REPLACE_CLOSE])
+ REPLACE_COPY_FILE_RANGE=0; AC_SUBST([REPLACE_COPY_FILE_RANGE])
REPLACE_DUP=0; AC_SUBST([REPLACE_DUP])
REPLACE_DUP2=0; AC_SUBST([REPLACE_DUP2])
REPLACE_EXECL=0; AC_SUBST([REPLACE_EXECL])
diff --git a/make-dist b/make-dist
index 447e90f018e..4646a2809bf 100755
--- a/make-dist
+++ b/make-dist
@@ -174,7 +174,7 @@ fi
### Find out which version of Emacs this is.
version=`
- sed -n 's/^AC_INIT(GNU Emacs,[ ]*\([^ ,)]*\).*/\1/p' <configure.ac
+ sed -n 's/^AC_INIT(\[GNU Emacs],[ ]*\[\([^]]*\).*/\1/p' <configure.ac
` || version=
if [ ! "${version}" ]; then
printf '%s\n' \
@@ -485,6 +485,8 @@ if [ "${make_tar}" = yes ]; then
esac
echo "Creating tar file"
taropt='--numeric-owner --owner=0 --group=0 --mode=go+u,go-w'
+ tar -H ustar -cf /dev/null $tempdir/src/lisp.h 2>/dev/null &&
+ taropt="$taropt -H ustar"
tar --sort=name -cf /dev/null $tempdir/src/lisp.h 2>/dev/null &&
taropt="$taropt --sort=name"
[ "$verbose" = "yes" ] && taropt="$taropt --verbose"
diff --git a/msdos/sed1v2.inp b/msdos/sed1v2.inp
index e041e4e5b8d..b7818f8b21e 100644
--- a/msdos/sed1v2.inp
+++ b/msdos/sed1v2.inp
@@ -50,13 +50,16 @@ s/\.h\.in/.h-in/
/^LIB_ACL *=/s/@LIB_ACL@//
/^LIB_EACCESS *=/s/@LIB_EACCESS@//
/^LIB_FDATASYNC *=/s/@LIB_FDATASYNC@//
+/^LIB_NANOSLEEP *=/s/@LIB_NANOSLEEP@//
s/ *@LIBTIFF@//
s/ *@LIBJPEG@//
s/ *@LIBPNG@//
s/ *@LIBGIF@//
s/ *@LIBXPM@//
+s/ *@WEBP_LIBS@//
/^HAVE_NATIVE_COMP *=/s/@HAVE_NATIVE_COMP@/no/
/^HAVE_PDUMPER *=/s/@HAVE_PDUMPER@/no/
+/^HAVE_BE_APP *=/s/@HAVE_BE_APP@/no/
/^CHECK_STRUCTS *=/s/@CHECK_STRUCTS@//
/^RUN_TEMACS \=/s/temacs/temacs.exe/
/^XFT_LIBS *=/s/@XFT_LIBS@//
@@ -78,6 +81,10 @@ s/ *@LIBXPM@//
/^NOTIFY_LIBS *=/s/@NOTIFY_LIBS@//
/^NOTIFY_CFLAGS *=/s/@NOTIFY_CFLAGS@//
/^GTK_OBJ *=/s/@GTK_OBJ@//
+/^PGTK_OBJ *=/s/@PGTK_OBJ@//
+/^PGTK_LIBS *=/s/@PGTK_LIBS@//
+/^HAIKU_OBJ *=/s/@HAIKU_OBJ@//
+/^HAIKU_CXX_OBJ *=/s/@HAIKU_CXX_OBJ@//
/^LIBS_TERMCAP *=/s/@LIBS_TERMCAP@//
/^TERMCAP_OBJ *=/s/@TERMCAP_OBJ@/termcap.o tparam.o/
/^LIBXMU *=/s/@LIBXMU@//
@@ -110,6 +117,18 @@ s/ *@LIBXPM@//
/^XFIXES_CFLAGS *=/s/@XFIXES_CFLAGS@//
/^XDBE_LIBS *=/s/@XDBE_LIBS@//
/^XDBE_CFLAGS *=/s/@XDBE_CFLAGS@//
+/^XCOMPOSITE_LIBS *=/s/@XCOMPOSITE_LIBS@//
+/^XCOMPOSITE_CFLAGS *=/s/@XCOMPOSITE_CFLAGS@//
+/^XSHAPE_LIBS *=/s/@XSHAPE_LIBS@//
+/^XSHAPE_CFLAGS *=/s/@XSHAPE_CFLAGS@//
+/^XINPUT_LIBS *=/s/@XINPUT_LIBS@//
+/^XINPUT_CFLAGS *=/s/@XINPUT_CFLAGS@//
+/^XSYNC_LIBS *=/s/@XSYNC_LIBS@//
+/^XSYNC_CFLAGS *=/s/@XSYNC_CFLAGS@//
+/^WEBP_CFLAGS *=/s/@WEBP_CFLAGS@//
+/^SQLITE3_LIBS *=/s/@SQLITE3_LIBS@//
+/^HAIKU_LIBS *=/s/@HAIKU_LIBS@//
+/^HAIKU_CFLAGS *=/s/@HAIKU_CFLAGS@//
/^CYGWIN_OBJ *=/s/@CYGWIN_OBJ@//
/^WINDOW_SYSTEM_OBJ *=/s/@WINDOW_SYSTEM_OBJ@//
/^MSDOS_OBJ *=/s/= */= dosfns.o msdos.o w16select.o/
@@ -179,6 +198,8 @@ s/ *@LIBXPM@//
/^PAXCTL_dumped *=/s/=.*$/=/
/^PAXCTL_notdumped *=/s/=.*$/=/
/^DUMPING *=/s/@DUMPING@/unexec/
+/^[ \t]*MAKE_PDUMPER_FINGERPRINT = *$/c\
+MAKE_PDUMPER_FINGERPRINT =
/^lisp\.mk:/,/^$/c\
lisp.mk: $(lispsource)/loadup.el\
@rm -f $@\
@@ -190,6 +211,10 @@ lisp.mk: $(lispsource)/loadup.el\
/^ [ ]*\$(AM_V_at)\$(libsrc)\/make-docfile -d/s!make-docfile!make-docfile -o $(etc)/DOC!
/ > \$(etc)\/DOC *$/s/ >.*$//
+/^\$(etc)\/DOC/,/^$/{
+ /^$/i\
+ cd ../src
+}
/^ [ ]*\$(AM_V_GLOBALS)\$(libsrc)\/make-docfile.*>.*globals.tmp/s!make-docfile!make-docfile -o globals.tmp!
/^ [ ]*\$(AM_V_GLOBALS)\$(libsrc)\/make-doc/s!>.*$!!
/^\$(libsrc)\/make-docfile\$(EXEEXT): /i\
@@ -255,4 +280,4 @@ s| -I\$(top_srcdir)/lib||
s| -I\. -I\$(srcdir)| -I.|
/^ *test "X/d
/\$(CC) -o \$@.tmp/s/\$@.tmp/\$@/
-/mv \$@.tmp \$@/d \ No newline at end of file
+/mv \$@.tmp \$@/d
diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp
index 59ebec9e756..9847e710c0f 100644
--- a/msdos/sedlibmk.inp
+++ b/msdos/sedlibmk.inp
@@ -180,15 +180,21 @@ s/@PACKAGE@/emacs/
/^GL_GNULIB_ENVIRON *=/s/@GL_GNULIB_ENVIRON@/1/
/^GL_GNULIB_FDATASYNC *=/s/@GL_GNULIB_FDATASYNC@/1/
/^GL_GNULIB_GETLOADAVG *=/s/@GL_GNULIB_GETLOADAVG@/1/
+/^GL_GNULIB_GETRANDOM *=/s/@GL_GNULIB_GETRANDOM@/1/
/^GL_GNULIB_UNISTD_H_GETOPT *=/s/@GL_GNULIB_UNISTD_H_GETOPT@/1/
+/^GL_GNULIB_MEMMEM *=/s/@GL_GNULIB_MEMMEM@/1/
/^GL_GNULIB_MEMRCHR *=/s/@GL_GNULIB_MEMRCHR@/1/
/^GL_GNULIB_MEMPCPY *=/s/@GL_GNULIB_MEMPCPY@/1/
/^GL_GNULIB_MKOSTEMP *=/s/@GL_GNULIB_MKOSTEMP@/1/
/^GL_GNULIB_MKTIME *=/s/@GL_GNULIB_MKTIME@/1/
+/^GL_GNULIB_SIGDESCR_NP *=/s/@GL_GNULIB_SIGDESCR_NP@/1/
/^GL_GNULIB_TIME_R *=/s/@GL_GNULIB_TIME_R@/1/
/^GL_GNULIB_TIMEGM *=/s/@GL_GNULIB_TIMEGM@/1/
/^GL_GNULIB_TIME_RZ *=/s/@GL_GNULIB_TIME_RZ@/1/
/^GL_GNULIB_UNSETENV *=/s/@GL_GNULIB_UNSETENV@/1/
+# Apparently without this `rawmemchr' isn't declared, so
+# we get warnings building canonicalize-lgpl.o
+/^GL_GNULIB_RAWMEMCHR *=/s/@GL_GNULIB_RAWMEMCHR@/1/
/^GL_GNULIB_[^ =]* *= *@/s/@[^@\n]*@/0/
/^GL_GSETTINGS_CFLAGS *=/s/@[^@\n]*@//
/^GL_GSETTINGS_LIBS *=/s/@[^@\n]*@//
@@ -268,6 +274,8 @@ s/@PACKAGE@/emacs/
# MKDIR_P lines are edited further below
# MKDIR_P is only used to create lib/malloc, and the folder is
# already present in the distribution, so this should work fine.
+# (No longer true as of Emacs 29, but the directories we need
+# are created in config.bat!)
/^MKDIR_P *=/s/@MKDIR_P@/echo/
/^NEXT_AS_FIRST_DIRECTIVE_DIRENT_H *=/s/@[^@\n]*@/<dirent.h>/
/^NEXT_AS_FIRST_DIRECTIVE_ERRNO_H *=/s/@[^@\n]*@//
@@ -403,18 +411,21 @@ s/^ -*test -z.*|| rm/ -rm/
s/@echo /@djecho /
#
# Determine which headers to generate
-s/= @GL_GENERATE_ALLOCA_H_TRUE@/= 1/
-s/= @GL_GENERATE_BYTESWAP_H@/= 1/
-s/= @GL_GENERATE_EXECINFO_H@/= 1/
-s/= @GL_GENERATE_IEEE754_H@/= 1/
-s/= @GL_GENERATE_STDALIGN_H@/= 1/
-s/= @GL_GENERATE_STDDEF_H@/= 1/
-s/= @GL_GENERATE_STDINT_H@/= 1/
-s/= @GL_GENERATE_LIMITS_H@/= 1/
-s/= @GL_GENERATE_ERRNO_H@/= /
-s/= @GL_GENERATE_LIMITS_H@/= /
-s/= @GL_GENERATE_GMP_GMP_H@/= 1/
-s/= @GL_GENERATE_MINI_GMP_H@/= 1/
+s/= @GL_GENERATE_ALLOCA_H_CONDITION@/= 1/
+s/= @GL_GENERATE_BYTESWAP_H_CONDITION@/= 1/
+s/= @GL_GENERATE_EXECINFO_H_CONDITION@/= 1/
+s/= @GL_GENERATE_IEEE754_H_CONDITION@/= 1/
+s/= @GL_GENERATE_STDALIGN_H_CONDITION@/= 1/
+s/= @GL_GENERATE_STDDEF_H_CONDITION@/= 1/
+s/= @GL_GENERATE_STDINT_H_CONDITION@/= 1/
+s/= @GL_GENERATE_LIMITS_H_CONDITION@/= 1/
+s/= @GL_GENERATE_ERRNO_H_CONDITION@/= /
+s/= @GL_GENERATE_LIMITS_H_CONDITION@/= /
+s/= @GL_GENERATE_GMP_H_CONDITION@/= 1/
+s/= @GL_GENERATE_GMP_GMP_H_CONDITION@/= /
+s/= @GL_GENERATE_MINI_GMP_H_CONDITION@/= 1/
+s/= @GL_COND_OBJ_STDIO_READ_CONDITION@/= /
+s/= @GL_COND_OBJ_STDIO_WRITE_CONDITION@/= /
s/\$\(MKDIR_P\) malloc//
#
# Determine which modules to build and which to omit
@@ -426,7 +437,6 @@ OMIT_GNULIB_MODULE_careadlinkat = true\
OMIT_GNULIB_MODULE_cloexec = true\
OMIT_GNULIB_MODULE_dirent = true\
OMIT_GNULIB_MODULE_dirfd = true\
-OMIT_GNULIB_MODULE_scratch_buffer = true\
OMIT_GNULIB_MODULE_dup2 = true\
OMIT_GNULIB_MODULE_errno = true\
OMIT_GNULIB_MODULE_euidaccess = true\
@@ -442,6 +452,7 @@ OMIT_GNULIB_MODULE_group-member = true\
OMIT_GNULIB_MODULE_inttypes-incomplete = true\
OMIT_GNULIB_MODULE_localtime-buffer = true\
OMIT_GNULIB_MODULE_lstat = true\
+OMIT_GNULIB_MODULE_nanosleep = true\
OMIT_GNULIB_MODULE_open = true\
OMIT_GNULIB_MODULE_pipe2 = true\
OMIT_GNULIB_MODULE_pselect = true\
diff --git a/nextstep/Makefile.in b/nextstep/Makefile.in
index 92d7f28fe6b..9c7059f2c0b 100644
--- a/nextstep/Makefile.in
+++ b/nextstep/Makefile.in
@@ -47,7 +47,9 @@ ns_check_file = @ns_appdir@/@ns_check_file@
all: ${ns_appdir} ${ns_appbindir}/Emacs ${ns_applibexecdir}/Emacs.pdmp
-${ns_check_file} ${ns_appdir}: ${srcdir}/${ns_appsrc} ${ns_appsrc}
+${ns_check_file}: ${ns_appdir}
+
+${ns_appdir}: ${srcdir}/${ns_appsrc} ${ns_appsrc}
rm -rf ${ns_appdir}
${MKDIR_P} ${ns_appdir}
( cd ${srcdir}/${ns_appsrc} ; tar cfh - . ) | \
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index 4748474f1dc..69119b135e2 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -74,3 +74,4 @@ OMIT_GNULIB_MODULE_futimens = true
OMIT_GNULIB_MODULE_utimensat = true
OMIT_GNULIB_MODULE_file-has-acl = true
OMIT_GNULIB_MODULE_nproc = true
+OMIT_GNULIB_MODULE_nanosleep = true
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index 3f4b2f34892..2dd9a9a476c 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -295,6 +295,7 @@ extern int sys_unlink (const char *);
#undef umask
#define umask sys_umask
extern int sys_umask (int);
+#define clock sys_clock
/* Subprocess calls that are emulated. */
#define spawnve sys_spawnve
diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site
index 6ab81e943f1..7ca19cbad06 100644
--- a/nt/mingw-cfg.site
+++ b/nt/mingw-cfg.site
@@ -167,3 +167,6 @@ ac_cv_func_strsignal=no
# implementation of 'free' doesn't touch errno, and it emits a
# compilation warning.
gl_cv_func_free_preserves_errno=yes
+# Don't build the Gnulib nanosleep module: it requires W2K or later,
+# and MinGW does have nanosleep.
+gl_cv_func_nanosleep=yes
diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c
index 646631df84b..e679c2ffed6 100644
--- a/oldXMenu/Activate.c
+++ b/oldXMenu/Activate.c
@@ -121,6 +121,8 @@ int x_menu_grab_keyboard = 1;
static Wait_func wait_func;
static void* wait_data;
+static Translate_func translate_func = NULL;
+static Expose_func expose_func = NULL;
void
XMenuActivateSetWaitFunction (Wait_func func, void *data)
@@ -129,6 +131,18 @@ XMenuActivateSetWaitFunction (Wait_func func, void *data)
wait_data = data;
}
+void
+XMenuActivateSetTranslateFunction (Translate_func func)
+{
+ translate_func = func;
+}
+
+void
+XMenuActivateSetExposeFunction (Expose_func func)
+{
+ expose_func = func;
+}
+
int
XMenuActivate(
register Display *display, /* Display to put menu on. */
@@ -332,6 +346,9 @@ XMenuActivate(
feq = feq_tmp;
}
else if (_XMEventHandler) (*_XMEventHandler)(&event);
+
+ if (expose_func)
+ expose_func (&event);
break;
}
if (event_xmp->activated) {
@@ -449,6 +466,9 @@ XMenuActivate(
* If the current selection was activated then
* deactivate it.
*/
+ /* Emacs specific, HELP_STRING cannot be validly NULL
+ * in the real XMenu library. */
+ help_callback (NULL, cur_p->serial, cur_s->serial);
if (cur_s->activated) {
cur_s->activated = False;
_XMRefreshSelection(display, menu, cur_s);
@@ -515,6 +535,12 @@ XMenuActivate(
feq = feq_tmp;
}
else if (_XMEventHandler) (*_XMEventHandler)(&event);
+ break;
+#ifdef HAVE_XINPUT2
+ case GenericEvent:
+ if (translate_func)
+ translate_func (&event);
+#endif
}
/*
* If a selection has been made, break out of the event loop.
diff --git a/oldXMenu/XMenu.h b/oldXMenu/XMenu.h
index 50ea6834090..54061235ae7 100644
--- a/oldXMenu/XMenu.h
+++ b/oldXMenu/XMenu.h
@@ -255,6 +255,12 @@ typedef struct _xmenu {
typedef void (*Wait_func)(void*);
+/* Function for translating GenericEvents. It is should call
+ XPutBackEvent on an equivalent artificial core event on any
+ function it wants to translate. */
+typedef void (*Translate_func)(XEvent *);
+typedef void (*Expose_func)(XEvent *);
+
/*
* XMenu library routine declarations.
*/
@@ -274,6 +280,8 @@ void XMenuEventHandler(int (*handler) (XEvent *));
int XMenuLocate(Display *display, XMenu *menu, int p_num, int s_num, int x_pos, int y_pos, int *ul_x, int *ul_y, int *width, int *height);
void XMenuSetFreeze(XMenu *menu, int freeze);
void XMenuActivateSetWaitFunction(Wait_func func, void *data);
+void XMenuActivateSetTranslateFunction(Translate_func func);
+void XMenuActivateSetExposeFunction(Expose_func func);
int XMenuActivate(Display *display, XMenu *menu, int *p_num, int *s_num, int x_pos, int y_pos, unsigned int event_mask, char **data, void (*help_callback) (char const *, int, int));
char *XMenuPost(Display *display, XMenu *menu, int *p_num, int *s_num, int x_pos, int y_pos, int event_mask);
int XMenuDeletePane(Display *display, XMenu *menu, int p_num);
diff --git a/oldXMenu/XMenuInt.h b/oldXMenu/XMenuInt.h
index 86b8e057cd5..5d5365ad8f2 100644
--- a/oldXMenu/XMenuInt.h
+++ b/oldXMenu/XMenuInt.h
@@ -37,6 +37,8 @@ without express or implied warranty.
#include <config.h>
+#include <attribute.h>
+
/* Avoid warnings about redefining NULL by including <stdio.h> first;
the other file which wants to define it (<stddef.h> on Ultrix
systems) can deal if NULL is already defined, but <stdio.h> can't. */
diff --git a/src/.gdbinit b/src/.gdbinit
index 132f414af94..9ec536a96d1 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -751,6 +751,15 @@ Print $ as a overlay pointer.
This command assumes that $ is an Emacs Lisp overlay value.
end
+define xsymwithpos
+ xgetptr $
+ print (struct Lisp_Symbol_With_Pos *) $ptr
+end
+document xsymwithpos
+Print $ as a symbol with position.
+This command assumes that $ is an Emacs Lisp symbol with position value.
+end
+
define xsymbol
set $sym = $
xgetsym $sym
@@ -1016,6 +1025,9 @@ define xpr
if $vec == PVEC_OVERLAY
xoverlay
end
+ if $vec == PVEC_SYMBOL_WITH_POS
+ xsymwithpos
+ end
if $vec == PVEC_PROCESS
xprocess
end
diff --git a/src/Makefile.in b/src/Makefile.in
index 04fabd5f424..7d15b7afd51 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -146,6 +146,7 @@ M17N_FLT_LIBS = @M17N_FLT_LIBS@
LIB_ACL=@LIB_ACL@
LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
LIB_EACCESS=@LIB_EACCESS@
+LIB_NANOSLEEP=@LIB_NANOSLEEP@
LIB_TIMER_TIME=@LIB_TIMER_TIME@
DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -264,9 +265,18 @@ XFIXES_CFLAGS = @XFIXES_CFLAGS@
XINPUT_LIBS = @XINPUT_LIBS@
XINPUT_CFLAGS = @XINPUT_CFLAGS@
+XSYNC_LIBS = @XSYNC_LIBS@
+XSYNC_CFLAGS = @XSYNC_CFLAGS@
+
XDBE_LIBS = @XDBE_LIBS@
XDBE_CFLAGS = @XDBE_CFLAGS@
+XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
+XCOMPOSITE_CFLAGS = @XCOMPOSITE_CFLAGS@
+
+XSHAPE_LIBS = @XSHAPE_LIBS@
+XSHAPE_CFLAGS = @XSHAPE_CFLAGS@
+
## widget.o if USE_X_TOOLKIT, otherwise empty.
WIDGET_OBJ=@WIDGET_OBJ@
@@ -396,9 +406,9 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
$(XINPUT_CFLAGS) $(WEBP_CFLAGS) $(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) \
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
$(HARFBUZZ_CFLAGS) $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
- $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \
+ $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) $(XSYNC_CFLAGS) \
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
- $(WERROR_CFLAGS) $(HAIKU_CFLAGS)
+ $(WERROR_CFLAGS) $(HAIKU_CFLAGS) $(XCOMPOSITE_CFLAGS) $(XSHAPE_CFLAGS)
ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS)
ALL_OBJC_CFLAGS = $(EMACS_CFLAGS) \
$(filter-out $(NON_OBJC_CFLAGS),$(WARN_CFLAGS)) $(CFLAGS) \
@@ -424,7 +434,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
minibuf.o fileio.o dired.o \
cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \
alloc.o pdumper.o data.o doc.o editfns.o callint.o \
- eval.o floatfns.o fns.o font.o print.o lread.o $(MODULES_OBJ) \
+ eval.o floatfns.o fns.o sort.o font.o print.o lread.o $(MODULES_OBJ) \
syntax.o $(UNEXEC_OBJ) bytecode.o comp.o $(DYNLIB_OBJ) \
process.o gnutls.o callproc.o \
region-cache.o sound.o timefns.o atimer.o \
@@ -545,17 +555,17 @@ lisp = $(addprefix ${lispsource}/,${shortlisp})
LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(PGTK_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
$(LIBX_OTHER) $(LIBSOUND) \
$(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
- $(WEBKIT_LIBS) \
+ $(LIB_NANOSLEEP) $(WEBKIT_LIBS) \
$(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
$(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
- $(XDBE_LIBS) \
+ $(XDBE_LIBS) $(XSYNC_LIBS) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(HARFBUZZ_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
$(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
$(JSON_LIBS) $(LIBGMP) $(LIBGCCJIT_LIBS) $(XINPUT_LIBS) $(HAIKU_LIBS) \
- $(SQLITE3_LIBS)
+ $(SQLITE3_LIBS) $(XCOMPOSITE_LIBS) $(XSHAPE_LIBS)
## FORCE it so that admin/unidata can decide whether this file is
## up-to-date. Although since charprop depends on bootstrap-emacs,
@@ -616,7 +626,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 $@
@@ -678,9 +688,9 @@ $(LIBEGNU_ARCHIVE): $(config_h)
$(MAKE) -C $(dir $@) all
ifeq ($(HAVE_PDUMPER),yes)
- MAKE_PDUMPER_FINGERPRINT = $(libsrc)/make-fingerprint$(EXEEXT)
+MAKE_PDUMPER_FINGERPRINT = $(libsrc)/make-fingerprint$(EXEEXT)
else
- MAKE_PDUMPER_FINGERPRINT =
+MAKE_PDUMPER_FINGERPRINT =
endif
## We have to create $(etc) here because init_cmdargs tests its
@@ -914,6 +924,9 @@ $(bootstrap_pdmp): bootstrap-emacs$(EXEEXT)
$(RUN_TEMACS) --batch $(BUILD_DETAILS) -l loadup --temacs=pbootstrap \
--bin-dest $(BIN_DESTDIR) --eln-dest $(ELN_DESTDIR)
@: Compile some files earlier to speed up further compilation.
+ @: First, byte compile these files, ....
+ ANCIENT=yes $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
+ @: .... then use their .elcs in native compiling these and other files.
$(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
endif
diff --git a/src/alloc.c b/src/alloc.c
index 7582a426011..f115a3cebaa 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -445,26 +445,11 @@ static void compact_small_strings (void);
static void free_large_strings (void);
extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
-/* Forward declare mark accessor functions: they're used all over the
- place. */
-
-inline static bool vector_marked_p (const struct Lisp_Vector *v);
-inline static void set_vector_marked (struct Lisp_Vector *v);
-
-inline static bool vectorlike_marked_p (const union vectorlike_header *v);
-inline static void set_vectorlike_marked (union vectorlike_header *v);
-
-inline static bool cons_marked_p (const struct Lisp_Cons *c);
-inline static void set_cons_marked (struct Lisp_Cons *c);
-
-inline static bool string_marked_p (const struct Lisp_String *s);
-inline static void set_string_marked (struct Lisp_String *s);
-
-inline static bool symbol_marked_p (const struct Lisp_Symbol *s);
-inline static void set_symbol_marked (struct Lisp_Symbol *s);
-
-inline static bool interval_marked_p (INTERVAL i);
-inline static void set_interval_marked (INTERVAL i);
+static bool vector_marked_p (struct Lisp_Vector const *);
+static bool vectorlike_marked_p (union vectorlike_header const *);
+static void set_vectorlike_marked (union vectorlike_header *);
+static bool interval_marked_p (INTERVAL);
+static void set_interval_marked (INTERVAL);
/* When scanning the C stack for live Lisp objects, Emacs keeps track of
what memory allocated via lisp_malloc and lisp_align_malloc is intended
@@ -490,7 +475,7 @@ enum mem_type
static bool
deadp (Lisp_Object x)
{
- return EQ (x, dead_object ());
+ return BASE_EQ (x, dead_object ());
}
#ifdef GC_MALLOC_CHECK
@@ -592,7 +577,7 @@ pointer_align (void *ptr, int alignment)
static ATTRIBUTE_NO_SANITIZE_UNDEFINED void *
XPNTR (Lisp_Object a)
{
- return (SYMBOLP (a)
+ return (BARE_SYMBOL_P (a)
? (char *) lispsym + (XLI (a) - LISP_WORD_TAG (Lisp_Symbol))
: (char *) XLP (a) - (XLI (a) & ~VALMASK));
}
@@ -1047,9 +1032,12 @@ lisp_free (void *block)
return;
MALLOC_BLOCK_INPUT;
+#ifndef GC_MALLOC_CHECK
+ struct mem_node *m = mem_find (block);
+#endif
free (block);
#ifndef GC_MALLOC_CHECK
- mem_delete (mem_find (block));
+ mem_delete (m);
#endif
MALLOC_UNBLOCK_INPUT;
}
@@ -1853,7 +1841,8 @@ allocate_string (void)
static void
allocate_string_data (struct Lisp_String *s,
- EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
+ EMACS_INT nchars, EMACS_INT nbytes, bool clearit,
+ bool immovable)
{
sdata *data;
struct sblock *b;
@@ -1867,7 +1856,7 @@ allocate_string_data (struct Lisp_String *s,
MALLOC_BLOCK_INPUT;
- if (nbytes > LARGE_STRING_BYTES)
+ if (nbytes > LARGE_STRING_BYTES || immovable)
{
size_t size = FLEXSIZEOF (struct sblock, data, needed);
@@ -1967,7 +1956,7 @@ resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
}
else
{
- allocate_string_data (XSTRING (string), nchars, new_nbytes, false);
+ allocate_string_data (XSTRING (string), nchars, new_nbytes, false, false);
unsigned char *new_data = SDATA (string);
new_charaddr = new_data + cidx_byte;
memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
@@ -2483,7 +2472,7 @@ make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
s = allocate_string ();
s->u.s.intervals = NULL;
- allocate_string_data (s, nchars, nbytes, clearit);
+ allocate_string_data (s, nchars, nbytes, clearit, false);
XSETSTRING (string, s);
string_chars_consed += nbytes;
return string;
@@ -2513,6 +2502,29 @@ make_formatted_string (char *buf, const char *format, ...)
return make_string (buf, length);
}
+/* Pin a unibyte string in place so that it won't move during GC. */
+void
+pin_string (Lisp_Object string)
+{
+ eassert (STRINGP (string) && !STRING_MULTIBYTE (string));
+ struct Lisp_String *s = XSTRING (string);
+ ptrdiff_t size = STRING_BYTES (s);
+ unsigned char *data = s->u.s.data;
+
+ if (!(size > LARGE_STRING_BYTES
+ || PURE_P (data) || pdumper_object_p (data)
+ || s->u.s.size_byte == -3))
+ {
+ eassert (s->u.s.size_byte == -1);
+ sdata *old_sdata = SDATA_OF_STRING (s);
+ allocate_string_data (s, size, size, false, true);
+ memcpy (s->u.s.data, data, size);
+ old_sdata->string = NULL;
+ SDATA_NBYTES (old_sdata) = size;
+ }
+ s->u.s.size_byte = -3;
+}
+
/***********************************************************************
Float Allocation
@@ -3515,6 +3527,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
&& FIXNATP (args[COMPILED_STACK_DEPTH])))
error ("Invalid byte-code object");
+ pin_string (args[COMPILED_BYTECODE]); // Bytecode must be immovable.
+
/* We used to purecopy everything here, if purify-flag was set. This worked
OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
dangerous, since make-byte-code is used during execution to build
@@ -3599,13 +3613,13 @@ static struct Lisp_Symbol *symbol_free_list;
static void
set_symbol_name (Lisp_Object sym, Lisp_Object name)
{
- XSYMBOL (sym)->u.s.name = name;
+ XBARE_SYMBOL (sym)->u.s.name = name;
}
void
init_symbol (Lisp_Object val, Lisp_Object name)
{
- struct Lisp_Symbol *p = XSYMBOL (val);
+ struct Lisp_Symbol *p = XBARE_SYMBOL (val);
set_symbol_name (val, name);
set_symbol_plist (val, Qnil);
p->u.s.redirect = SYMBOL_PLAINVAL;
@@ -3668,6 +3682,21 @@ make_misc_ptr (void *a)
return make_lisp_ptr (p, Lisp_Vectorlike);
}
+/* Return a new symbol with position with the specified SYMBOL and POSITION. */
+Lisp_Object
+build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position)
+{
+ Lisp_Object val;
+ struct Lisp_Symbol_With_Pos *p
+ = (struct Lisp_Symbol_With_Pos *) allocate_vector (2);
+ XSETVECTOR (val, p);
+ XSETPVECTYPESIZE (XVECTOR (val), PVEC_SYMBOL_WITH_POS, 2, 0);
+ p->sym = symbol;
+ p->pos = position;
+
+ return val;
+}
+
/* Return a new overlay with specified START, END and PLIST. */
Lisp_Object
@@ -3850,7 +3879,7 @@ run_finalizer_handler (Lisp_Object args)
static void
run_finalizer_function (Lisp_Object function)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef HAVE_PDUMPER
++number_finalizers_run;
#endif
@@ -4884,10 +4913,10 @@ mark_maybe_pointer (void *p, bool symbol_only)
miss objects if __alignof__ were used. */
#define GC_POINTER_ALIGNMENT alignof (void *)
-/* Mark Lisp objects referenced from the address range START+OFFSET..END
- or END+OFFSET..START. */
+/* Mark Lisp objects referenced from the address range START..END
+ or END..START. */
-static void ATTRIBUTE_NO_SANITIZE_ADDRESS
+void ATTRIBUTE_NO_SANITIZE_ADDRESS
mark_memory (void const *start, void const *end)
{
char const *pp;
@@ -4956,7 +4985,7 @@ marking. Emacs has determined that the method it uses to do the\n\
marking will likely work on your system, but this isn't sure.\n\
\n\
If you are a system-programmer, or can get the help of a local wizard\n\
-who is, please take a look at the function mark_stack in alloc.c, and\n\
+who is, please take a look at the function mark_c_stack in alloc.c, and\n\
verify that the methods used are appropriate for your system.\n\
\n\
Please mail the result to <emacs-devel@gnu.org>.\n\
@@ -4969,7 +4998,7 @@ marking. Emacs has determined that the default method it uses to do the\n\
marking will not work on your system. We will need a system-dependent\n\
solution for your system.\n\
\n\
-Please take a look at the function mark_stack in alloc.c, and\n\
+Please take a look at the function mark_c_stack in alloc.c, and\n\
try to find a way to make it work on your system.\n\
\n\
Note that you may get false negatives, depending on the compiler.\n\
@@ -5111,7 +5140,7 @@ typedef union
from the stack start. */
void
-mark_stack (char const *bottom, char const *end)
+mark_c_stack (char const *bottom, char const *end)
{
/* This assumes that the stack is a contiguous region in memory. If
that's not the case, something has to be done here to iterate
@@ -5212,7 +5241,7 @@ valid_lisp_object_p (Lisp_Object obj)
if (PURE_P (p))
return 1;
- if (SYMBOLP (obj) && c_symbol_p (p))
+ if (BARE_SYMBOL_P (obj) && c_symbol_p (p))
return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
if (p == &buffer_defaults || p == &buffer_local_symbols)
@@ -5638,14 +5667,18 @@ purecopy (Lisp_Object obj)
memcpy (vec, objp, nbytes);
for (i = 0; i < size; i++)
vec->contents[i] = purecopy (vec->contents[i]);
+ // Byte code strings must be pinned.
+ if (COMPILEDP (obj) && size >= 2 && STRINGP (vec->contents[1])
+ && !STRING_MULTIBYTE (vec->contents[1]))
+ pin_string (vec->contents[1]);
XSETVECTOR (obj, vec);
}
- else if (SYMBOLP (obj))
+ else if (BARE_SYMBOL_P (obj))
{
- if (!XSYMBOL (obj)->u.s.pinned && !c_symbol_p (XSYMBOL (obj)))
+ if (!XBARE_SYMBOL (obj)->u.s.pinned && !c_symbol_p (XBARE_SYMBOL (obj)))
{ /* We can't purify them, but they appear in many pure objects.
Mark them as `pinned' so we know to mark them at every GC cycle. */
- XSYMBOL (obj)->u.s.pinned = true;
+ XBARE_SYMBOL (obj)->u.s.pinned = true;
symbol_block_pinned = symbol_block;
}
/* Don't hash-cons it. */
@@ -5699,10 +5732,10 @@ allow_garbage_collection (intmax_t consing)
garbage_collection_inhibited--;
}
-ptrdiff_t
+specpdl_ref
inhibit_garbage_collection (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_intmax (allow_garbage_collection, consing_until_gc);
garbage_collection_inhibited++;
consing_until_gc = HI_THRESHOLD;
@@ -6055,6 +6088,8 @@ maybe_garbage_collect (void)
garbage_collect ();
}
+static inline bool mark_stack_empty_p (void);
+
/* Subroutine of Fgarbage_collect that does most of the work. */
void
garbage_collect (void)
@@ -6062,7 +6097,7 @@ garbage_collect (void)
Lisp_Object tail, buffer;
char stack_top_variable;
bool message_p;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct timespec start;
eassert (weak_hash_tables == NULL);
@@ -6070,6 +6105,8 @@ garbage_collect (void)
if (garbage_collection_inhibited)
return;
+ eassert(mark_stack_empty_p ());
+
/* Record this function, so it appears on the profiler's backtraces. */
record_in_backtrace (QAutomatic_GC, 0, 0);
@@ -6143,6 +6180,7 @@ garbage_collect (void)
mark_pinned_objects ();
mark_pinned_symbols ();
+ mark_lread ();
mark_terminals ();
mark_kboards ();
mark_threads ();
@@ -6162,6 +6200,14 @@ garbage_collect (void)
mark_fringe_data ();
#endif
+#ifdef HAVE_X_WINDOWS
+ mark_xterm ();
+#endif
+
+#ifdef HAVE_NS
+ mark_nsterm ();
+#endif
+
/* Everything is now marked, except for the data in font caches,
undo lists, and finalizers. The first two are compacted by
removing an items which aren't reachable otherwise. */
@@ -6192,6 +6238,8 @@ garbage_collect (void)
mark_and_sweep_weak_table_contents ();
eassert (weak_hash_tables == NULL);
+ eassert (mark_stack_empty_p ());
+
gc_sweep ();
unmark_main_thread ();
@@ -6220,7 +6268,7 @@ garbage_collect (void)
if (!NILP (Vpost_gc_hook))
{
- ptrdiff_t gc_count = inhibit_garbage_collection ();
+ specpdl_ref gc_count = inhibit_garbage_collection ();
safe_run_hooks (Qpost_gc_hook);
unbind_to (gc_count, Qnil);
}
@@ -6259,7 +6307,7 @@ where each entry has the form (NAME SIZE USED FREE), where:
to return them to the OS).
However, if there was overflow in pure space, and Emacs was dumped
-using the 'unexec' method, `garbage-collect' returns nil, because
+using the \"unexec\" method, `garbage-collect' returns nil, because
real GC can't be done.
Note that calling this function does not guarantee that absolutely all
@@ -6273,7 +6321,10 @@ For further details, see Info node `(elisp)Garbage Collection'. */)
if (garbage_collection_inhibited)
return Qnil;
+ specpdl_ref count = SPECPDL_INDEX ();
+ specbind (Qsymbols_with_pos_enabled, Qnil);
garbage_collect ();
+ unbind_to (count, Qnil);
struct gcstat gcst = gcstat;
Lisp_Object total[] = {
@@ -6362,15 +6413,25 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
}
}
+/* Whether to remember a few of the last marked values for debugging. */
+#define GC_REMEMBER_LAST_MARKED 0
+
+#if GC_REMEMBER_LAST_MARKED
enum { LAST_MARKED_SIZE = 1 << 9 }; /* Must be a power of 2. */
Lisp_Object last_marked[LAST_MARKED_SIZE] EXTERNALLY_VISIBLE;
static int last_marked_index;
+#endif
+
+/* Whether to enable the mark_object_loop_halt debugging feature. */
+#define GC_CDR_COUNT 0
+#if GC_CDR_COUNT
/* For debugging--call abort when we cdr down this many
links of a list, in mark_object. In debugging,
the call to abort will hit a breakpoint.
Normally this is zero and the check never goes off. */
ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE;
+#endif
static void
mark_vectorlike (union vectorlike_header *header)
@@ -6412,7 +6473,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
Lisp_Object val = ptr->contents[i];
if (FIXNUMP (val) ||
- (SYMBOLP (val) && symbol_marked_p (XSYMBOL (val))))
+ (BARE_SYMBOL_P (val) && symbol_marked_p (XBARE_SYMBOL (val))))
continue;
if (SUB_CHAR_TABLE_P (val))
{
@@ -6424,19 +6485,6 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
}
}
-NO_INLINE /* To reduce stack depth in mark_object. */
-static Lisp_Object
-mark_compiled (struct Lisp_Vector *ptr)
-{
- int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
-
- set_vector_marked (ptr);
- for (i = 0; i < size; i++)
- if (i != COMPILED_CONSTANTS)
- mark_object (ptr->contents[i]);
- return size > COMPILED_CONSTANTS ? ptr->contents[COMPILED_CONSTANTS] : Qnil;
-}
-
/* Mark the chain of overlays starting at PTR. */
static void
@@ -6589,110 +6637,160 @@ mark_window (struct Lisp_Vector *ptr)
(w, mark_discard_killed_buffers (w->next_buffers));
}
-static void
-mark_hash_table (struct Lisp_Vector *ptr)
-{
- struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
-
- mark_vectorlike (&h->header);
- mark_object (h->test.name);
- mark_object (h->test.user_hash_function);
- mark_object (h->test.user_cmp_function);
- /* If hash table is not weak, mark all keys and values. For weak
- tables, mark only the vector and not its contents --- that's what
- makes it weak. */
- if (NILP (h->weak))
- mark_object (h->key_and_value);
- else
+/* Entry of the mark stack. */
+struct mark_entry
+{
+ ptrdiff_t n; /* number of values, or 0 if a single value */
+ union {
+ Lisp_Object value; /* when n = 0 */
+ Lisp_Object *values; /* when n > 0 */
+ } u;
+};
+
+/* This stack is used during marking for traversing data structures without
+ using C recursion. */
+struct mark_stack
+{
+ struct mark_entry *stack; /* base of stack */
+ ptrdiff_t size; /* allocated size in entries */
+ ptrdiff_t sp; /* current number of entries */
+};
+
+static struct mark_stack mark_stk = {NULL, 0, 0};
+
+static inline bool
+mark_stack_empty_p (void)
+{
+ return mark_stk.sp <= 0;
+}
+
+/* Pop and return a value from the mark stack (which must be nonempty). */
+static inline Lisp_Object
+mark_stack_pop (void)
+{
+ eassume (!mark_stack_empty_p ());
+ struct mark_entry *e = &mark_stk.stack[mark_stk.sp - 1];
+ if (e->n == 0) /* single value */
{
- eassert (h->next_weak == NULL);
- h->next_weak = weak_hash_tables;
- weak_hash_tables = h;
- set_vector_marked (XVECTOR (h->key_and_value));
+ --mark_stk.sp;
+ return e->u.value;
}
+ /* Array of values: pop them left to right, which seems to be slightly
+ faster than right to left. */
+ e->n--;
+ if (e->n == 0)
+ --mark_stk.sp; /* last value consumed */
+ return (++e->u.values)[-1];
}
-void
-mark_objects (Lisp_Object *obj, ptrdiff_t n)
+NO_INLINE static void
+grow_mark_stack (void)
{
- for (ptrdiff_t i = 0; i < n; i++)
- mark_object (obj[i]);
+ struct mark_stack *ms = &mark_stk;
+ eassert (ms->sp == ms->size);
+ ptrdiff_t min_incr = ms->sp == 0 ? 8192 : 1;
+ ms->stack = xpalloc (ms->stack, &ms->size, min_incr, -1, sizeof *ms->stack);
+ eassert (ms->sp < ms->size);
}
-/* Determine type of generic Lisp_Object and mark it accordingly.
+/* Push VALUE onto the mark stack. */
+static inline void
+mark_stack_push_value (Lisp_Object value)
+{
+ if (mark_stk.sp >= mark_stk.size)
+ grow_mark_stack ();
+ mark_stk.stack[mark_stk.sp++] = (struct mark_entry){.n = 0, .u.value = value};
+}
- This function implements a straightforward depth-first marking
- algorithm and so the recursion depth may be very high (a few
- tens of thousands is not uncommon). To minimize stack usage,
- a few cold paths are moved out to NO_INLINE functions above.
- In general, inlining them doesn't help you to gain more speed. */
+/* Push the N values at VALUES onto the mark stack. */
+static inline void
+mark_stack_push_values (Lisp_Object *values, ptrdiff_t n)
+{
+ eassume (n >= 0);
+ if (n == 0)
+ return;
+ if (mark_stk.sp >= mark_stk.size)
+ grow_mark_stack ();
+ mark_stk.stack[mark_stk.sp++] = (struct mark_entry){.n = n,
+ .u.values = values};
+}
-void
-mark_object (Lisp_Object arg)
+/* Traverse and mark objects on the mark stack above BASE_SP.
+
+ Traversal is depth-first using the mark stack for most common
+ object types. Recursion is used for other types, in the hope that
+ they are rare enough that C stack usage is kept low. */
+static void
+process_mark_stack (ptrdiff_t base_sp)
{
- register Lisp_Object obj;
- void *po;
#if GC_CHECK_MARKED_OBJECTS
struct mem_node *m = NULL;
#endif
+#if GC_CDR_COUNT
ptrdiff_t cdr_count = 0;
+#endif
- obj = arg;
- loop:
+ eassume (mark_stk.sp >= base_sp && base_sp >= 0);
- po = XPNTR (obj);
- if (PURE_P (po))
- return;
+ while (mark_stk.sp > base_sp)
+ {
+ Lisp_Object obj = mark_stack_pop ();
+ mark_obj: ;
+ void *po = XPNTR (obj);
+ if (PURE_P (po))
+ continue;
- last_marked[last_marked_index++] = obj;
- last_marked_index &= LAST_MARKED_SIZE - 1;
+#if GC_REMEMBER_LAST_MARKED
+ last_marked[last_marked_index++] = obj;
+ last_marked_index &= LAST_MARKED_SIZE - 1;
+#endif
- /* Perform some sanity checks on the objects marked here. Abort if
- we encounter an object we know is bogus. This increases GC time
- by ~80%. */
+ /* Perform some sanity checks on the objects marked here. Abort if
+ we encounter an object we know is bogus. This increases GC time
+ by ~80%. */
#if GC_CHECK_MARKED_OBJECTS
- /* Check that the object pointed to by PO is known to be a Lisp
- structure allocated from the heap. */
+ /* Check that the object pointed to by PO is known to be a Lisp
+ structure allocated from the heap. */
#define CHECK_ALLOCATED() \
- do { \
- if (pdumper_object_p (po)) \
- { \
- if (!pdumper_object_p_precise (po)) \
- emacs_abort (); \
- break; \
- } \
- m = mem_find (po); \
- if (m == MEM_NIL) \
- emacs_abort (); \
- } while (0)
-
- /* Check that the object pointed to by PO is live, using predicate
- function LIVEP. */
-#define CHECK_LIVE(LIVEP, MEM_TYPE) \
- do { \
- if (pdumper_object_p (po)) \
- break; \
- if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
- emacs_abort (); \
- } while (0)
-
- /* Check both of the above conditions, for non-symbols. */
-#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
- do { \
- CHECK_ALLOCATED (); \
- CHECK_LIVE (LIVEP, MEM_TYPE); \
- } while (false)
-
- /* Check both of the above conditions, for symbols. */
-#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \
- do { \
- if (!c_symbol_p (ptr)) \
- { \
- CHECK_ALLOCATED (); \
- CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
- } \
- } while (false)
+ do { \
+ if (pdumper_object_p (po)) \
+ { \
+ if (!pdumper_object_p_precise (po)) \
+ emacs_abort (); \
+ break; \
+ } \
+ m = mem_find (po); \
+ if (m == MEM_NIL) \
+ emacs_abort (); \
+ } while (0)
+
+ /* Check that the object pointed to by PO is live, using predicate
+ function LIVEP. */
+#define CHECK_LIVE(LIVEP, MEM_TYPE) \
+ do { \
+ if (pdumper_object_p (po)) \
+ break; \
+ if (! (m->type == MEM_TYPE && LIVEP (m, po))) \
+ emacs_abort (); \
+ } while (0)
+
+ /* Check both of the above conditions, for non-symbols. */
+#define CHECK_ALLOCATED_AND_LIVE(LIVEP, MEM_TYPE) \
+ do { \
+ CHECK_ALLOCATED (); \
+ CHECK_LIVE (LIVEP, MEM_TYPE); \
+ } while (false)
+
+ /* Check both of the above conditions, for symbols. */
+#define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \
+ do { \
+ if (!c_symbol_p (ptr)) \
+ { \
+ CHECK_ALLOCATED (); \
+ CHECK_LIVE (live_symbol_p, MEM_TYPE_SYMBOL); \
+ } \
+ } while (false)
#else /* not GC_CHECK_MARKED_OBJECTS */
@@ -6701,199 +6799,220 @@ mark_object (Lisp_Object arg)
#endif /* not GC_CHECK_MARKED_OBJECTS */
- switch (XTYPE (obj))
- {
- case Lisp_String:
- {
- register struct Lisp_String *ptr = XSTRING (obj);
- if (string_marked_p (ptr))
- break;
- CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING);
- set_string_marked (ptr);
- mark_interval_tree (ptr->u.s.intervals);
+ switch (XTYPE (obj))
+ {
+ case Lisp_String:
+ {
+ register struct Lisp_String *ptr = XSTRING (obj);
+ if (string_marked_p (ptr))
+ break;
+ CHECK_ALLOCATED_AND_LIVE (live_string_p, MEM_TYPE_STRING);
+ set_string_marked (ptr);
+ mark_interval_tree (ptr->u.s.intervals);
#ifdef GC_CHECK_STRING_BYTES
- /* Check that the string size recorded in the string is the
- same as the one recorded in the sdata structure. */
- string_bytes (ptr);
+ /* Check that the string size recorded in the string is the
+ same as the one recorded in the sdata structure. */
+ string_bytes (ptr);
#endif /* GC_CHECK_STRING_BYTES */
- }
- break;
+ }
+ break;
- case Lisp_Vectorlike:
- {
- register struct Lisp_Vector *ptr = XVECTOR (obj);
+ case Lisp_Vectorlike:
+ {
+ register struct Lisp_Vector *ptr = XVECTOR (obj);
- if (vector_marked_p (ptr))
- break;
+ if (vector_marked_p (ptr))
+ break;
- enum pvec_type pvectype
- = PSEUDOVECTOR_TYPE (ptr);
+ enum pvec_type pvectype
+ = PSEUDOVECTOR_TYPE (ptr);
#ifdef GC_CHECK_MARKED_OBJECTS
- if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
- {
- m = mem_find (po);
- if (m == MEM_NIL)
- emacs_abort ();
- if (m->type == MEM_TYPE_VECTORLIKE)
- CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
- else
- CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
- }
+ if (!pdumper_object_p (po) && !SUBRP (obj) && !main_thread_p (po))
+ {
+ m = mem_find (po);
+ if (m == MEM_NIL)
+ emacs_abort ();
+ if (m->type == MEM_TYPE_VECTORLIKE)
+ CHECK_LIVE (live_large_vector_p, MEM_TYPE_VECTORLIKE);
+ else
+ CHECK_LIVE (live_small_vector_p, MEM_TYPE_VECTOR_BLOCK);
+ }
#endif
- switch (pvectype)
- {
- case PVEC_BUFFER:
- mark_buffer ((struct buffer *) ptr);
- break;
-
- case PVEC_COMPILED:
- /* Although we could treat this just like a vector, mark_compiled
- returns the COMPILED_CONSTANTS element, which is marked at the
- next iteration of goto-loop here. This is done to avoid a few
- recursive calls to mark_object. */
- obj = mark_compiled (ptr);
- if (!NILP (obj))
- goto loop;
- break;
-
- case PVEC_FRAME:
- mark_frame (ptr);
- break;
-
- case PVEC_WINDOW:
- mark_window (ptr);
- break;
-
- case PVEC_HASH_TABLE:
- mark_hash_table (ptr);
- break;
-
- case PVEC_CHAR_TABLE:
- case PVEC_SUB_CHAR_TABLE:
- mark_char_table (ptr, (enum pvec_type) pvectype);
- break;
-
- case PVEC_BOOL_VECTOR:
- /* bool vectors in a dump are permanently "marked", since
- they're in the old section and don't have mark bits.
- If we're looking at a dumped bool vector, we should
- have aborted above when we called vector_marked_p, so
- we should never get here. */
- eassert (!pdumper_object_p (ptr));
- set_vector_marked (ptr);
- break;
-
- case PVEC_OVERLAY:
- mark_overlay (XOVERLAY (obj));
- break;
-
- case PVEC_SUBR:
-#ifdef HAVE_NATIVE_COMP
- if (SUBR_NATIVE_COMPILEDP (obj))
+ switch (pvectype)
{
+ case PVEC_BUFFER:
+ mark_buffer ((struct buffer *) ptr);
+ break;
+
+ case PVEC_FRAME:
+ mark_frame (ptr);
+ break;
+
+ case PVEC_WINDOW:
+ mark_window (ptr);
+ break;
+
+ case PVEC_HASH_TABLE:
+ {
+ struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr;
+ ptrdiff_t size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
+ set_vector_marked (ptr);
+ mark_stack_push_values (ptr->contents, size);
+ mark_stack_push_value (h->test.name);
+ mark_stack_push_value (h->test.user_hash_function);
+ mark_stack_push_value (h->test.user_cmp_function);
+ if (NILP (h->weak))
+ mark_stack_push_value (h->key_and_value);
+ else
+ {
+ /* For weak tables, mark only the vector and not its
+ contents --- that's what makes it weak. */
+ eassert (h->next_weak == NULL);
+ h->next_weak = weak_hash_tables;
+ weak_hash_tables = h;
+ set_vector_marked (XVECTOR (h->key_and_value));
+ }
+ break;
+ }
+
+ case PVEC_CHAR_TABLE:
+ case PVEC_SUB_CHAR_TABLE:
+ mark_char_table (ptr, (enum pvec_type) pvectype);
+ break;
+
+ case PVEC_BOOL_VECTOR:
+ /* bool vectors in a dump are permanently "marked", since
+ they're in the old section and don't have mark bits.
+ If we're looking at a dumped bool vector, we should
+ have aborted above when we called vector_marked_p, so
+ we should never get here. */
+ eassert (!pdumper_object_p (ptr));
set_vector_marked (ptr);
- struct Lisp_Subr *subr = XSUBR (obj);
- mark_object (subr->native_intspec);
- mark_object (subr->native_comp_u);
- mark_object (subr->lambda_list);
- mark_object (subr->type);
- }
+ break;
+
+ case PVEC_OVERLAY:
+ mark_overlay (XOVERLAY (obj));
+ break;
+
+ case PVEC_SUBR:
+#ifdef HAVE_NATIVE_COMP
+ if (SUBR_NATIVE_COMPILEDP (obj))
+ {
+ set_vector_marked (ptr);
+ struct Lisp_Subr *subr = XSUBR (obj);
+ mark_stack_push_value (subr->intspec.native);
+ mark_stack_push_value (subr->command_modes);
+ mark_stack_push_value (subr->native_comp_u);
+ mark_stack_push_value (subr->lambda_list);
+ mark_stack_push_value (subr->type);
+ }
#endif
- break;
+ break;
- case PVEC_FREE:
- emacs_abort ();
+ case PVEC_FREE:
+ emacs_abort ();
- default:
- /* A regular vector, or a pseudovector needing no special
- treatment. */
- mark_vectorlike (&ptr->header);
+ default:
+ {
+ /* A regular vector or pseudovector needing no special
+ treatment. */
+ ptrdiff_t size = ptr->header.size;
+ if (size & PSEUDOVECTOR_FLAG)
+ size &= PSEUDOVECTOR_SIZE_MASK;
+ set_vector_marked (ptr);
+ mark_stack_push_values (ptr->contents, size);
+ }
+ break;
+ }
}
- }
- break;
+ break;
- case Lisp_Symbol:
- {
- struct Lisp_Symbol *ptr = XSYMBOL (obj);
- nextsym:
- if (symbol_marked_p (ptr))
- break;
- CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
- set_symbol_marked (ptr);
- /* Attempt to catch bogus objects. */
- eassert (valid_lisp_object_p (ptr->u.s.function));
- mark_object (ptr->u.s.function);
- mark_object (ptr->u.s.plist);
- switch (ptr->u.s.redirect)
+ case Lisp_Symbol:
{
- case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break;
- case SYMBOL_VARALIAS:
- {
- Lisp_Object tem;
- XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
- mark_object (tem);
+ struct Lisp_Symbol *ptr = XBARE_SYMBOL (obj);
+ nextsym:
+ if (symbol_marked_p (ptr))
break;
- }
- case SYMBOL_LOCALIZED:
- mark_localized_symbol (ptr);
- break;
- case SYMBOL_FORWARDED:
- /* If the value is forwarded to a buffer or keyboard field,
- these are marked when we see the corresponding object.
- And if it's forwarded to a C variable, either it's not
- a Lisp_Object var, or it's staticpro'd already. */
- break;
- default: emacs_abort ();
+ CHECK_ALLOCATED_AND_LIVE_SYMBOL ();
+ set_symbol_marked (ptr);
+ /* Attempt to catch bogus objects. */
+ eassert (valid_lisp_object_p (ptr->u.s.function));
+ mark_stack_push_value (ptr->u.s.function);
+ mark_stack_push_value (ptr->u.s.plist);
+ switch (ptr->u.s.redirect)
+ {
+ case SYMBOL_PLAINVAL:
+ mark_stack_push_value (SYMBOL_VAL (ptr));
+ break;
+ case SYMBOL_VARALIAS:
+ {
+ Lisp_Object tem;
+ XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
+ mark_stack_push_value (tem);
+ break;
+ }
+ case SYMBOL_LOCALIZED:
+ mark_localized_symbol (ptr);
+ break;
+ case SYMBOL_FORWARDED:
+ /* If the value is forwarded to a buffer or keyboard field,
+ these are marked when we see the corresponding object.
+ And if it's forwarded to a C variable, either it's not
+ a Lisp_Object var, or it's staticpro'd already. */
+ break;
+ default: emacs_abort ();
+ }
+ if (!PURE_P (XSTRING (ptr->u.s.name)))
+ set_string_marked (XSTRING (ptr->u.s.name));
+ mark_interval_tree (string_intervals (ptr->u.s.name));
+ /* Inner loop to mark next symbol in this bucket, if any. */
+ po = ptr = ptr->u.s.next;
+ if (ptr)
+ goto nextsym;
}
- if (!PURE_P (XSTRING (ptr->u.s.name)))
- set_string_marked (XSTRING (ptr->u.s.name));
- mark_interval_tree (string_intervals (ptr->u.s.name));
- /* Inner loop to mark next symbol in this bucket, if any. */
- po = ptr = ptr->u.s.next;
- if (ptr)
- goto nextsym;
- }
- break;
-
- case Lisp_Cons:
- {
- struct Lisp_Cons *ptr = XCONS (obj);
- if (cons_marked_p (ptr))
break;
- CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS);
- set_cons_marked (ptr);
- /* If the cdr is nil, avoid recursion for the car. */
- if (NILP (ptr->u.s.u.cdr))
+
+ case Lisp_Cons:
{
+ struct Lisp_Cons *ptr = XCONS (obj);
+ if (cons_marked_p (ptr))
+ break;
+ CHECK_ALLOCATED_AND_LIVE (live_cons_p, MEM_TYPE_CONS);
+ set_cons_marked (ptr);
+ /* Avoid growing the stack if the cdr is nil.
+ In any case, make sure the car is expanded first. */
+ if (!NILP (ptr->u.s.u.cdr))
+ {
+ mark_stack_push_value (ptr->u.s.u.cdr);
+#if GC_CDR_COUNT
+ cdr_count++;
+ if (cdr_count == mark_object_loop_halt)
+ emacs_abort ();
+#endif
+ }
+ /* Speedup hack for the common case (successive list elements). */
obj = ptr->u.s.car;
- cdr_count = 0;
- goto loop;
+ goto mark_obj;
}
- mark_object (ptr->u.s.car);
- obj = ptr->u.s.u.cdr;
- cdr_count++;
- if (cdr_count == mark_object_loop_halt)
- emacs_abort ();
- goto loop;
- }
- case Lisp_Float:
- CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
- /* Do not mark floats stored in a dump image: these floats are
- "cold" and do not have mark bits. */
- if (pdumper_object_p (XFLOAT (obj)))
- eassert (pdumper_cold_object_p (XFLOAT (obj)));
- else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
- XFLOAT_MARK (XFLOAT (obj));
- break;
+ case Lisp_Float:
+ CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
+ /* Do not mark floats stored in a dump image: these floats are
+ "cold" and do not have mark bits. */
+ if (pdumper_object_p (XFLOAT (obj)))
+ eassert (pdumper_cold_object_p (XFLOAT (obj)));
+ else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
+ XFLOAT_MARK (XFLOAT (obj));
+ break;
- case_Lisp_Int:
- break;
+ case_Lisp_Int:
+ break;
- default:
- emacs_abort ();
+ default:
+ emacs_abort ();
+ }
}
#undef CHECK_LIVE
@@ -6901,6 +7020,22 @@ mark_object (Lisp_Object arg)
#undef CHECK_ALLOCATED_AND_LIVE
}
+void
+mark_object (Lisp_Object obj)
+{
+ ptrdiff_t sp = mark_stk.sp;
+ mark_stack_push_value (obj);
+ process_mark_stack (sp);
+}
+
+void
+mark_objects (Lisp_Object *objs, ptrdiff_t n)
+{
+ ptrdiff_t sp = mark_stk.sp;
+ mark_stack_push_values (objs, n);
+ process_mark_stack (sp);
+}
+
/* Mark the Lisp pointers in the terminal objects.
Called by Fgarbage_collect. */
@@ -6937,7 +7072,7 @@ survives_gc_p (Lisp_Object obj)
break;
case Lisp_Symbol:
- survives_p = symbol_marked_p (XSYMBOL (obj));
+ survives_p = symbol_marked_p (XBARE_SYMBOL (obj));
break;
case Lisp_String:
@@ -7337,7 +7472,8 @@ Frames, windows, buffers, and subprocesses count as vectors
make_int (strings_consed));
}
-#if defined GNU_LINUX && defined __GLIBC__
+#if defined GNU_LINUX && defined __GLIBC__ && \
+ (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 10)
DEFUN ("malloc-info", Fmalloc_info, Smalloc_info, 0, 0, "",
doc: /* Report malloc information to stderr.
This function outputs to stderr an XML-formatted
@@ -7351,10 +7487,41 @@ arenas. */)
}
#endif
+#ifdef HAVE_MALLOC_TRIM
+DEFUN ("malloc-trim", Fmalloc_trim, Smalloc_trim, 0, 1, "",
+ doc: /* Release free heap memory to the OS.
+This function asks libc to return unused heap memory back to the operating
+system. This function isn't guaranteed to do anything, and is mainly
+meant as a debugging tool.
+
+If LEAVE_PADDING is given, ask the system to leave that much unused
+space in the heap of the Emacs process. This should be an integer, and if
+not given, it defaults to 0.
+
+This function returns nil if no memory could be returned to the
+system, and non-nil if some memory could be returned. */)
+ (Lisp_Object leave_padding)
+{
+ int pad = 0;
+
+ if (! NILP (leave_padding))
+ {
+ CHECK_FIXNAT (leave_padding);
+ pad = XFIXNUM (leave_padding);
+ }
+
+ /* 1 means that memory was released to the system. */
+ if (malloc_trim (pad) == 1)
+ return Qt;
+ else
+ return Qnil;
+}
+#endif
+
static bool
symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj)
{
- struct Lisp_Symbol *sym = XSYMBOL (symbol);
+ struct Lisp_Symbol *sym = XBARE_SYMBOL (symbol);
Lisp_Object val = find_symbol_value (symbol);
return (EQ (val, obj)
|| EQ (sym->u.s.function, obj)
@@ -7373,7 +7540,7 @@ Lisp_Object
which_symbols (Lisp_Object obj, EMACS_INT find_max)
{
struct symbol_block *sblk;
- ptrdiff_t gc_count = inhibit_garbage_collection ();
+ specpdl_ref gc_count = inhibit_garbage_collection ();
Lisp_Object found = Qnil;
if (! deadp (obj))
@@ -7697,9 +7864,14 @@ N should be nonnegative. */);
defsubr (&Sgarbage_collect_maybe);
defsubr (&Smemory_info);
defsubr (&Smemory_use_counts);
-#if defined GNU_LINUX && defined __GLIBC__
+#if defined GNU_LINUX && defined __GLIBC__ && \
+ (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 10)
+
defsubr (&Smalloc_info);
#endif
+#ifdef HAVE_MALLOC_TRIM
+ defsubr (&Smalloc_trim);
+#endif
defsubr (&Ssuspicious_object);
Lisp_Object watcher;
@@ -7707,14 +7879,14 @@ N should be nonnegative. */);
static union Aligned_Lisp_Subr Swatch_gc_cons_threshold =
{{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
{ .a4 = watch_gc_cons_threshold },
- 4, 4, "watch_gc_cons_threshold", {0}, 0}};
+ 4, 4, "watch_gc_cons_threshold", {0}, lisp_h_Qnil}};
XSETSUBR (watcher, &Swatch_gc_cons_threshold.s);
Fadd_variable_watcher (Qgc_cons_threshold, watcher);
static union Aligned_Lisp_Subr Swatch_gc_cons_percentage =
{{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
{ .a4 = watch_gc_cons_percentage },
- 4, 4, "watch_gc_cons_percentage", {0}, 0}};
+ 4, 4, "watch_gc_cons_percentage", {0}, lisp_h_Qnil}};
XSETSUBR (watcher, &Swatch_gc_cons_percentage.s);
Fadd_variable_watcher (Qgc_cons_percentage, watcher);
}
diff --git a/src/atimer.c b/src/atimer.c
index 1c6c881fc02..18301120ffe 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -18,6 +18,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
+#ifdef WINDOWSNT
+#define raise(s) w32_raise(s)
+#endif
+
#include "lisp.h"
#include "keyboard.h"
#include "syssignal.h"
@@ -297,11 +301,6 @@ set_alarm (void)
{
if (atimers)
{
-#ifdef HAVE_SETITIMER
- struct itimerval it;
-#endif
- struct timespec now, interval;
-
#ifdef HAVE_ITIMERSPEC
if (0 <= timerfd || alarm_timer_ok)
{
@@ -337,20 +336,24 @@ set_alarm (void)
}
#endif
- /* Determine interval till the next timer is ripe.
- Don't set the interval to 0; this disables the timer. */
- now = current_timespec ();
- interval = (timespec_cmp (atimers->expiration, now) <= 0
- ? make_timespec (0, 1000 * 1000)
- : timespec_sub (atimers->expiration, now));
+ /* Determine interval till the next timer is ripe. */
+ struct timespec now = current_timespec ();
+ if (timespec_cmp (atimers->expiration, now) <= 0)
+ {
+ /* Timer is (over)due -- just trigger the signal right way. */
+ raise (SIGALRM);
+ }
+ else
+ {
+ struct timespec interval = timespec_sub (atimers->expiration, now);
#ifdef HAVE_SETITIMER
-
- memset (&it, 0, sizeof it);
- it.it_value = make_timeval (interval);
- setitimer (ITIMER_REAL, &it, 0);
-#endif /* not HAVE_SETITIMER */
- alarm (max (interval.tv_sec, 1));
+ struct itimerval it = {.it_value = make_timeval (interval)};
+ setitimer (ITIMER_REAL, &it, 0);
+#else
+ alarm (max (interval.tv_sec, 1));
+#endif
+ }
}
}
diff --git a/src/bidi.c b/src/bidi.c
index c5d524f0493..c4d04136e9e 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -1277,6 +1277,12 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
SET_TEXT_POS (pos, charpos, bytepos);
*disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p,
disp_prop);
+ /* The factor of 100 below is a heuristic that needs to be
+ tuned. It means we consider 100 buffer positions examined by
+ the above call roughly equivalent to the display engine
+ iterating over a single buffer position. */
+ if (max_redisplay_ticks > 0 && *disp_pos > charpos)
+ update_redisplay_ticks ((*disp_pos - charpos) / 100 + 1, w);
}
/* Fetch the character at BYTEPOS. */
@@ -1385,6 +1391,8 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len);
*disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p,
disp_prop);
+ if (max_redisplay_ticks > 0 && *disp_pos > charpos + *nchars)
+ update_redisplay_ticks ((*disp_pos - charpos - *nchars) / 100 + 1, w);
}
return ch;
@@ -1462,7 +1470,7 @@ bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
/* Prevent quitting inside re_match_2, as redisplay_window could
have temporarily moved point. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
val = fast_looking_at (sep_re, charpos, bytepos, ZV, ZV_BYTE, Qnil);
@@ -1552,7 +1560,7 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
/* Prevent quitting inside re_match_2, as redisplay_window could
have temporarily moved point. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
while (pos_byte > BEGV_BYTE
@@ -1583,6 +1591,9 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
return pos_byte;
}
+/* This tracks how far we needed to search for first strong character. */
+static ptrdiff_t nsearch_for_strong;
+
/* On a 3.4 GHz machine, searching forward for a strong directional
character in a long paragraph full of weaks or neutrals takes about
1 ms for each 20K characters. The number below limits each call to
@@ -1652,6 +1663,8 @@ find_first_strong_char (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t end,
pos += *nchars;
bytepos += *ch_len;
}
+
+ nsearch_for_strong += pos - pos1;
return type;
}
@@ -1681,6 +1694,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
calls to BYTE_TO_CHAR and its ilk. */
ptrdiff_t begbyte = string_p ? 0 : BEGV_BYTE;
ptrdiff_t end = string_p ? bidi_it->string.schars : ZV;
+ ptrdiff_t pos = bidi_it->charpos;
+
+ nsearch_for_strong = 0;
/* Special case for an empty buffer. */
if (bytepos == begbyte && bidi_it->charpos == end)
@@ -1702,7 +1718,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
else if (dir == NEUTRAL_DIR) /* P2 */
{
ptrdiff_t ch_len, nchars;
- ptrdiff_t pos, disp_pos = -1;
+ ptrdiff_t disp_pos = -1;
int disp_prop = 0;
bidi_type_t type;
const unsigned char *s;
@@ -1800,6 +1816,14 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
bidi_it->level_stack[0].level = 0;
bidi_line_init (bidi_it);
+
+ /* The factor of 50 below is a heuristic that needs to be tuned. It
+ means we consider 50 buffer positions examined by this function
+ roughly equivalent to the display engine iterating over a single
+ buffer position. */
+ ptrdiff_t nexamined = bidi_it->charpos - pos + nsearch_for_strong;
+ if (max_redisplay_ticks > 0 && nexamined > 0)
+ update_redisplay_ticks (nexamined / 50, bidi_it->w);
}
@@ -2566,6 +2590,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
bidi_bracket_type_t btype;
bidi_type_t type = bidi_it->type;
bool retval = false;
+ ptrdiff_t n = 0;
/* When scanning backwards, we don't expect any unresolved bidi
bracket characters. */
@@ -2695,6 +2720,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
}
old_sidx = bidi_it->stack_idx;
type = bidi_resolve_weak (bidi_it);
+ n++;
/* Skip level runs excluded from this isolating run sequence. */
new_sidx = bidi_it->stack_idx;
if (bidi_it->level_stack[new_sidx].level > current_level
@@ -2718,6 +2744,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
goto give_up;
}
type = bidi_resolve_weak (bidi_it);
+ n++;
}
}
if (type == NEUTRAL_B
@@ -2758,6 +2785,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
(which requires the display engine to copy the cache back and
forth many times). */
if (maxlevel == base_level
+ && (l2r_seen || r2l_seen) /* N0d */
&& ((base_level == 0 && !r2l_seen)
|| (base_level == 1 && !l2r_seen)))
{
@@ -2793,6 +2821,12 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
}
give_up:
+ /* The factor of 20 below is a heuristic that needs to be tuned. It
+ means we consider 20 buffer positions examined by this function
+ roughly equivalent to the display engine iterating over a single
+ buffer position. */
+ if (max_redisplay_ticks > 0 && n > 0)
+ update_redisplay_ticks (n / 20 + 1, bidi_it->w);
return retval;
}
@@ -2920,13 +2954,17 @@ bidi_resolve_brackets (struct bidi_it *bidi_it)
int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level;
bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L;
- eassert (bidi_it->prev_for_neutral.type != UNKNOWN_BT);
eassert (bidi_it->bracket_pairing_pos > bidi_it->charpos);
if (bidi_it->bracket_enclosed_type == embedding_type) /* N0b */
type = embedding_type;
- else
+ else if (bidi_it->bracket_enclosed_type == STRONG_L /* N0c, N0d */
+ || bidi_it->bracket_enclosed_type == STRONG_R)
{
- switch (bidi_it->prev_for_neutral.type)
+ bidi_type_t prev_type_for_neutral = bidi_it->prev_for_neutral.type;
+
+ if (prev_type_for_neutral == UNKNOWN_BT)
+ prev_type_for_neutral = embedding_type;
+ switch (prev_type_for_neutral)
{
case STRONG_R:
case WEAK_EN:
@@ -3358,6 +3396,7 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
else
{
int new_level;
+ ptrdiff_t pos0 = bidi_it->charpos;
/* If we are at end of level, its edges must be cached. */
if (end_flag)
@@ -3393,6 +3432,12 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
bidi_cache_iterator_state (bidi_it, 1, 1);
}
} while (new_level >= level);
+ /* The factor of 50 below is a heuristic that needs to be
+ tuned. It means we consider 50 buffer positions examined by
+ the above call roughly equivalent to the display engine
+ iterating over a single buffer position. */
+ if (max_redisplay_ticks > 0 && bidi_it->charpos > pos0)
+ update_redisplay_ticks ((bidi_it->charpos - pos0) / 50 + 1, bidi_it->w);
}
}
@@ -3569,7 +3614,9 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
ptrdiff_t
bidi_find_first_overridden (struct bidi_it *bidi_it)
{
- ptrdiff_t found_pos = ZV;
+ ptrdiff_t eob
+ = STRINGP (bidi_it->string.lstring) ? bidi_it->string.schars : ZV;
+ ptrdiff_t found_pos = eob;
/* Maximum bidi levels we allow for L2R and R2L characters. Note
that these are levels after resolving explicit embeddings,
overrides, and isolates, i.e. before resolving implicit levels. */
@@ -3607,8 +3654,8 @@ bidi_find_first_overridden (struct bidi_it *bidi_it)
|| ((category == WEAK || bidi_it->orig_type == NEUTRAL_ON)
&& level > max_weak))
found_pos = bidi_it->charpos;
- } while (found_pos == ZV
- && bidi_it->charpos < ZV
+ } while (found_pos == eob
+ && bidi_it->charpos < eob
&& bidi_it->ch != BIDI_EOB
&& bidi_it->ch != '\n');
diff --git a/src/bignum.c b/src/bignum.c
index cb5322f291a..e4e4d45d686 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -476,3 +476,96 @@ check_int_nonnegative (Lisp_Object x)
CHECK_INTEGER (x);
return NILP (Fnatnump (x)) ? 0 : check_integer_range (x, 0, INT_MAX);
}
+
+/* Return a random mp_limb_t. */
+
+static mp_limb_t
+get_random_limb (void)
+{
+ if (GMP_NUMB_BITS <= ULONG_WIDTH)
+ return get_random_ulong ();
+
+ /* Work around GCC -Wshift-count-overflow false alarm. */
+ int shift = GMP_NUMB_BITS <= ULONG_WIDTH ? 0 : ULONG_WIDTH;
+
+ /* This is in case someone builds GMP with unusual definitions for
+ MINI_GMP_LIMB_TYPE or _LONG_LONG_LIMB. */
+ mp_limb_t r = 0;
+ for (int i = 0; i < GMP_NUMB_BITS; i += ULONG_WIDTH)
+ r = (r << shift) | get_random_ulong ();
+ return r;
+}
+
+/* Return a random mp_limb_t I in the range 0 <= I < LIM.
+ If LIM is zero, simply return a random mp_limb_t. */
+
+static mp_limb_t
+get_random_limb_lim (mp_limb_t lim)
+{
+ /* Return the remainder of a random mp_limb_t R divided by LIM,
+ except reject the rare case where R is so close to the maximum
+ mp_limb_t that the remainder isn't random. */
+ mp_limb_t difflim = - lim, diff, remainder;
+ do
+ {
+ mp_limb_t r = get_random_limb ();
+ if (lim == 0)
+ return r;
+ remainder = r % lim;
+ diff = r - remainder;
+ }
+ while (difflim < diff);
+
+ return remainder;
+}
+
+/* Return a random Lisp integer I in the range 0 <= I < LIMIT,
+ where LIMIT is a positive bignum. */
+
+Lisp_Object
+get_random_bignum (struct Lisp_Bignum const *limit)
+{
+ mpz_t const *lim = bignum_val (limit);
+ mp_size_t nlimbs = mpz_size (*lim);
+ eassume (0 < nlimbs);
+ mp_limb_t *r_limb = mpz_limbs_write (mpz[0], nlimbs);
+ mp_limb_t const *lim_limb = mpz_limbs_read (*lim);
+ mp_limb_t limhi = lim_limb[nlimbs - 1];
+ eassert (limhi);
+ bool edgy;
+
+ do
+ {
+ /* Generate the result one limb at a time, most significant first.
+ Choose the most significant limb RHI randomly from 0..LIMHI,
+ where LIMHI is the LIM's first limb, except choose from
+ 0..(LIMHI-1) if there is just one limb. RHI == LIMHI is an
+ unlucky edge case as later limbs might cause the result to be
+ exceed or equal LIM; if this happens, it causes another
+ iteration in the outer loop. */
+
+ mp_limb_t rhi = get_random_limb_lim (limhi + (1 < nlimbs));
+ edgy = rhi == limhi;
+ r_limb[nlimbs - 1] = rhi;
+
+ for (mp_size_t i = nlimbs - 1; 0 < i--; )
+ {
+ /* get_random_limb_lim (edgy ? limb_lim[i] + 1 : 0)
+ would be wrong here, as the full mp_limb_t range is
+ needed in later limbs for the edge case to have the
+ proper weighting. */
+ mp_limb_t ri = get_random_limb ();
+ if (edgy)
+ {
+ if (lim_limb[i] < ri)
+ break;
+ edgy = lim_limb[i] == ri;
+ }
+ r_limb[i] = ri;
+ }
+ }
+ while (edgy);
+
+ mpz_limbs_finish (mpz[0], nlimbs);
+ return make_integer_mpz ();
+}
diff --git a/src/bignum.h b/src/bignum.h
index 5f94ce850cf..de9ee17c027 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -51,6 +51,7 @@ extern void emacs_mpz_mul_2exp (mpz_t, mpz_t const, EMACS_INT)
extern void emacs_mpz_pow_ui (mpz_t, mpz_t const, unsigned long)
ARG_NONNULL ((1, 2));
extern double mpz_get_d_rounded (mpz_t const) ATTRIBUTE_CONST;
+extern Lisp_Object get_random_bignum (struct Lisp_Bignum const *);
INLINE_HEADER_BEGIN
diff --git a/src/buffer.c b/src/buffer.c
index 10ac91915c6..509ce51b55e 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -912,6 +912,10 @@ does not run the hooks `kill-buffer-hook',
Fset (intern ("buffer-save-without-query"), Qnil);
Fset (intern ("buffer-file-number"), Qnil);
Fset (intern ("buffer-stale-function"), Qnil);
+ /* Cloned buffers need extra setup, to do things such as deep
+ variable copies for list variables that might be mangled due
+ to destructive operations in the indirect buffer. */
+ run_hook (Qclone_indirect_buffer_hook);
set_buffer_internal_1 (old_b);
}
@@ -1061,7 +1065,7 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too)
eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED);
/* Need not do anything if some other buffer's binding is
now cached. */
- if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
+ if (BASE_EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
{
/* Symbol is set up for this buffer's old local value:
swap it out! */
@@ -1155,11 +1159,9 @@ is first appended to NAME, to speed up finding a non-existent buffer. */)
else
{
char number[sizeof "-999999"];
-
- /* Use XFIXNUM instead of XFIXNAT to work around GCC bug 80776. */
- int i = XFIXNUM (Frandom (make_fixnum (1000000)));
- eassume (0 <= i && i < 1000000);
-
+ EMACS_INT r = get_random ();
+ eassume (0 <= r);
+ int i = r % 1000000;
AUTO_STRING_WITH_LEN (lnumber, number, sprintf (number, "-%d", i));
genbase = concat2 (name, lnumber);
if (NILP (Fget_buffer (genbase)))
@@ -1216,7 +1218,7 @@ is the default binding of the variable. */)
{
register Lisp_Object result = buffer_local_value (variable, buffer);
- if (EQ (result, Qunbound))
+ if (BASE_EQ (result, Qunbound))
xsignal1 (Qvoid_variable, variable);
return result;
@@ -1247,7 +1249,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
{ /* Look in local_var_alist. */
struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
XSETSYMBOL (variable, sym); /* Update In case of aliasing. */
- result = Fassoc (variable, BVAR (buf, local_var_alist), Qnil);
+ result = assq_no_quit (variable, BVAR (buf, local_var_alist));
if (!NILP (result))
{
if (blv->fwd.fwdptr)
@@ -1311,7 +1313,7 @@ buffer_lisp_local_variables (struct buffer *buf, bool clone)
if (buf != current_buffer)
val = XCDR (elt);
- result = Fcons (!clone && EQ (val, Qunbound)
+ result = Fcons (!clone && BASE_EQ (val, Qunbound)
? XCAR (elt)
: Fcons (XCAR (elt), val),
result);
@@ -1334,7 +1336,7 @@ buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym)
{
sym = NILP (sym) ? PER_BUFFER_SYMBOL (offset) : sym;
Lisp_Object val = per_buffer_value (buf, offset);
- return EQ (val, Qunbound) ? sym : Fcons (sym, val);
+ return BASE_EQ (val, Qunbound) ? sym : Fcons (sym, val);
}
return Qnil;
}
@@ -1374,12 +1376,23 @@ No argument or nil as argument means use current buffer as BUFFER. */)
DEFUN ("buffer-modified-p", Fbuffer_modified_p, Sbuffer_modified_p,
0, 1, 0,
- doc: /* Return t if BUFFER was modified since its file was last read or saved.
-No argument or nil as argument means use current buffer as BUFFER. */)
+ doc: /* Return non-nil if BUFFER was modified since its file was last read or saved.
+No argument or nil as argument means use current buffer as BUFFER.
+
+If BUFFER was autosaved since it was last modified, this function
+returns the symbol `autosaved'. */)
(Lisp_Object buffer)
{
struct buffer *buf = decode_buffer (buffer);
- return BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf) ? Qt : Qnil;
+ if (BUF_SAVE_MODIFF (buf) < BUF_MODIFF (buf))
+ {
+ if (BUF_AUTOSAVE_MODIFF (buf) == BUF_MODIFF (buf))
+ return Qautosaved;
+ else
+ return Qt;
+ }
+ else
+ return Qnil;
}
DEFUN ("force-mode-line-update", Fforce_mode_line_update,
@@ -1434,6 +1447,11 @@ and `buffer-file-truename' are non-nil. */)
DEFUN ("restore-buffer-modified-p", Frestore_buffer_modified_p,
Srestore_buffer_modified_p, 1, 1, 0,
doc: /* Like `set-buffer-modified-p', but doesn't redisplay buffer's mode line.
+A nil FLAG means to mark the buffer as unmodified. A non-nil FLAG
+means mark the buffer as modified. A special value of `autosaved'
+will mark the buffer as modified and also as autosaved since it was
+last modified.
+
This function also locks or unlocks the file visited by the buffer,
if both `buffer-file-truename' and `buffer-file-name' are non-nil.
@@ -1473,16 +1491,19 @@ state of the current buffer. Use with care. */)
recent-auto-save-p from t to nil.
Vice versa, if FLAG is non-nil and SAVE_MODIFF>=auto_save_modified
we risk changing recent-auto-save-p from nil to t. */
- SAVE_MODIFF = (NILP (flag)
- /* FIXME: This unavoidably sets recent-auto-save-p to nil. */
- ? MODIFF
- /* Let's try to preserve recent-auto-save-p. */
- : SAVE_MODIFF < MODIFF ? SAVE_MODIFF
- /* If SAVE_MODIFF == auto_save_modified == MODIFF,
- we can either decrease SAVE_MODIFF and auto_save_modified
- or increase MODIFF. */
- : modiff_incr (&MODIFF));
-
+ if (NILP (flag))
+ /* This unavoidably sets recent-auto-save-p to nil. */
+ SAVE_MODIFF = MODIFF;
+ else
+ {
+ /* If SAVE_MODIFF == auto_save_modified == MODIFF, we can either
+ decrease SAVE_MODIFF and auto_save_modified or increase
+ MODIFF. */
+ if (SAVE_MODIFF >= MODIFF)
+ SAVE_MODIFF = modiff_incr (&MODIFF);
+ if (EQ (flag, Qautosaved))
+ BUF_AUTOSAVE_MODIFF (b) = MODIFF;
+ }
return flag;
}
@@ -1497,6 +1518,18 @@ use current buffer as BUFFER. */)
return modiff_to_integer (BUF_MODIFF (decode_buffer (buffer)));
}
+DEFUN ("internal--set-buffer-modified-tick",
+ Finternal__set_buffer_modified_tick, Sinternal__set_buffer_modified_tick,
+ 1, 2, 0,
+ doc: /* Set BUFFER's tick counter to TICK.
+No argument or nil as argument means use current buffer as BUFFER. */)
+ (Lisp_Object tick, Lisp_Object buffer)
+{
+ CHECK_FIXNUM (tick);
+ BUF_MODIFF (decode_buffer (buffer)) = XFIXNUM (tick);
+ return Qnil;
+}
+
DEFUN ("buffer-chars-modified-tick", Fbuffer_chars_modified_tick,
Sbuffer_chars_modified_tick, 0, 1, 0,
doc: /* Return BUFFER's character-change tick counter.
@@ -1574,7 +1607,7 @@ This does not change the name of the visited file (if any). */)
static bool
candidate_buffer (Lisp_Object b, Lisp_Object buffer)
{
- return (BUFFERP (b) && !EQ (b, buffer)
+ return (BUFFERP (b) && !BASE_EQ (b, buffer)
&& BUFFER_LIVE_P (XBUFFER (b))
&& !BUFFER_HIDDEN_P (XBUFFER (b)));
}
@@ -1632,16 +1665,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */)
if (!NILP (notsogood))
return notsogood;
else
- {
- AUTO_STRING (scratch, "*scratch*");
- buf = Fget_buffer (scratch);
- if (NILP (buf))
- {
- buf = Fget_buffer_create (scratch, Qnil);
- Fset_buffer_major_mode (buf);
- }
- return buf;
- }
+ return safe_call (1, Qget_scratch_buffer_create);
}
/* The following function is a safe variant of Fother_buffer: It doesn't
@@ -1657,15 +1681,7 @@ other_buffer_safely (Lisp_Object buffer)
if (candidate_buffer (buf, buffer))
return buf;
- AUTO_STRING (scratch, "*scratch*");
- buf = Fget_buffer (scratch);
- if (NILP (buf))
- {
- buf = Fget_buffer_create (scratch, Qnil);
- Fset_buffer_major_mode (buf);
- }
-
- return buf;
+ return safe_call (1, Qget_scratch_buffer_create);
}
DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
@@ -1770,7 +1786,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Run hooks with the buffer to be killed as the current buffer. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool modified;
record_unwind_protect_excursion ();
@@ -1793,10 +1809,12 @@ cleaning up all windows currently displaying the buffer to be killed. */)
/* Query if the buffer is still modified. */
if (INTERACTIVE && modified)
{
- AUTO_STRING (format, "Buffer %s modified; kill anyway? ");
- tem = do_yes_or_no_p (CALLN (Fformat, format, BVAR (b, name)));
- if (NILP (tem))
+ /* Ask whether to kill the buffer, and exit if the user says
+ "no". */
+ if (NILP (call1 (Qkill_buffer__possibly_save, buffer)))
return unbind_to (count, Qnil);
+ /* Recheck modified. */
+ modified = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
}
/* Delete the autosave file, if requested. */
@@ -1835,7 +1853,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
since anything can happen within do_yes_or_no_p. */
/* Don't kill the minibuffer now current. */
- if (EQ (buffer, XWINDOW (minibuf_window)->contents))
+ if (BASE_EQ (buffer, XWINDOW (minibuf_window)->contents))
return Qnil;
/* When we kill an ordinary buffer which shares its buffer text
@@ -1879,7 +1897,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
is the sole other buffer give up. */
XSETBUFFER (tem, current_buffer);
if (EQ (tem, XWINDOW (minibuf_window)->contents)
- && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
+ && BASE_EQ (buffer, Fother_buffer (buffer, Qnil, Qnil)))
return Qnil;
/* Now there is no question: we can kill the buffer. */
@@ -2093,7 +2111,6 @@ Use this function before selecting the buffer, since it may need to inspect
the current buffer's major mode. */)
(Lisp_Object buffer)
{
- ptrdiff_t count;
Lisp_Object function;
CHECK_BUFFER (buffer);
@@ -2116,7 +2133,7 @@ the current buffer's major mode. */)
`hack-local-variables' get run. */
return Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* To select a nonfundamental mode,
select the buffer temporarily and then call the mode function. */
@@ -2486,23 +2503,23 @@ results, see Info node `(elisp)Swapping Text'. */)
{
ws = Fcons (w, ws);
if (MARKERP (XWINDOW (w)->pointm)
- && (EQ (XWINDOW (w)->contents, buf1)
- || EQ (XWINDOW (w)->contents, buf2)))
+ && (BASE_EQ (XWINDOW (w)->contents, buf1)
+ || BASE_EQ (XWINDOW (w)->contents, buf2)))
Fset_marker (XWINDOW (w)->pointm,
make_fixnum
(BUF_BEGV (XBUFFER (XWINDOW (w)->contents))),
XWINDOW (w)->contents);
/* Blindly copied from pointm part. */
if (MARKERP (XWINDOW (w)->old_pointm)
- && (EQ (XWINDOW (w)->contents, buf1)
- || EQ (XWINDOW (w)->contents, buf2)))
+ && (BASE_EQ (XWINDOW (w)->contents, buf1)
+ || BASE_EQ (XWINDOW (w)->contents, buf2)))
Fset_marker (XWINDOW (w)->old_pointm,
make_fixnum
(BUF_BEGV (XBUFFER (XWINDOW (w)->contents))),
XWINDOW (w)->contents);
if (MARKERP (XWINDOW (w)->start)
- && (EQ (XWINDOW (w)->contents, buf1)
- || EQ (XWINDOW (w)->contents, buf2)))
+ && (BASE_EQ (XWINDOW (w)->contents, buf1)
+ || BASE_EQ (XWINDOW (w)->contents, buf2)))
Fset_marker (XWINDOW (w)->start,
make_fixnum
(XBUFFER (XWINDOW (w)->contents)->last_window_start),
@@ -2512,10 +2529,11 @@ results, see Info node `(elisp)Swapping Text'. */)
}
if (current_buffer->text->intervals)
- (eassert (EQ (current_buffer->text->intervals->up.obj, buffer)),
+ (eassert (BASE_EQ (current_buffer->text->intervals->up.obj, buffer)),
XSETBUFFER (current_buffer->text->intervals->up.obj, current_buffer));
if (other_buffer->text->intervals)
- (eassert (EQ (other_buffer->text->intervals->up.obj, Fcurrent_buffer ())),
+ (eassert (BASE_EQ (other_buffer->text->intervals->up.obj,
+ Fcurrent_buffer ())),
XSETBUFFER (other_buffer->text->intervals->up.obj, other_buffer));
return Qnil;
@@ -3925,9 +3943,9 @@ for the rear of the overlay advance when text is inserted there
else
CHECK_BUFFER (buffer);
- if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+ if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer))
signal_error ("Marker points into wrong buffer", beg);
- if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+ if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer))
signal_error ("Marker points into wrong buffer", end);
CHECK_FIXNUM_COERCE_MARKER (beg);
@@ -4031,7 +4049,7 @@ buffer. */)
{
struct buffer *b, *ob = 0;
Lisp_Object obuffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t n_beg, n_end;
ptrdiff_t o_beg UNINIT, o_end UNINIT;
@@ -4045,9 +4063,9 @@ buffer. */)
if (NILP (Fbuffer_live_p (buffer)))
error ("Attempt to move overlay to a dead buffer");
- if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer))
+ if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer))
signal_error ("Marker points into wrong buffer", beg);
- if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer))
+ if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer))
signal_error ("Marker points into wrong buffer", end);
CHECK_FIXNUM_COERCE_MARKER (beg);
@@ -4092,7 +4110,7 @@ buffer. */)
n_end = marker_position (OVERLAY_END (overlay));
/* If the overlay has changed buffers, do a thorough redisplay. */
- if (!EQ (buffer, obuffer))
+ if (!BASE_EQ (buffer, obuffer))
{
/* Redisplay where the overlay was. */
if (ob)
@@ -4152,7 +4170,7 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
{
Lisp_Object buffer;
struct buffer *b;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
CHECK_OVERLAY (overlay);
@@ -5551,6 +5569,7 @@ syms_of_buffer (void)
DEFSYM (Qbefore_change_functions, "before-change-functions");
DEFSYM (Qafter_change_functions, "after-change-functions");
DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions");
+ DEFSYM (Qget_scratch_buffer_create, "get-scratch-buffer-create");
DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar");
Fput (Qvertical_scroll_bar, Qchoice, list4 (Qnil, Qt, Qleft, Qright));
@@ -5569,6 +5588,8 @@ syms_of_buffer (void)
Fput (Qprotected_field, Qerror_message,
build_pure_c_string ("Attempt to modify a protected field"));
+ DEFSYM (Qclone_indirect_buffer_hook, "clone-indirect-buffer-hook");
+
DEFVAR_PER_BUFFER ("tab-line-format",
&BVAR (current_buffer, tab_line_format),
Qnil,
@@ -5580,8 +5601,11 @@ the mode line appears at the bottom. */);
&BVAR (current_buffer, header_line_format),
Qnil,
doc: /* Analogous to `mode-line-format', but controls the header line.
-The header line appears, optionally, at the top of a window;
-the mode line appears at the bottom. */);
+The header line appears, optionally, at the top of a window; the mode
+line appears at the bottom.
+
+Also see `header-line-indent-mode' if `display-line-number-mode' is
+used. */);
DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format),
Qnil,
@@ -6392,6 +6416,13 @@ If `delete-auto-save-files' is nil, any autosave deletion is inhibited. */);
This is the default. If nil, auto-save file deletion is inhibited. */);
delete_auto_save_files = 1;
+ DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook,
+ doc: /* Normal hook to run in the new buffer at the end of `make-indirect-buffer'.
+
+Since `clone-indirect-buffer' calls `make-indirect-buffer', this hook
+will run for `clone-indirect-buffer' calls as well. */);
+ Vclone_indirect_buffer_hook = Qnil;
+
defsubr (&Sbuffer_live_p);
defsubr (&Sbuffer_list);
defsubr (&Sget_buffer);
@@ -6408,6 +6439,7 @@ This is the default. If nil, auto-save file deletion is inhibited. */);
defsubr (&Sforce_mode_line_update);
defsubr (&Sset_buffer_modified_p);
defsubr (&Sbuffer_modified_tick);
+ defsubr (&Sinternal__set_buffer_modified_tick);
defsubr (&Sbuffer_chars_modified_tick);
defsubr (&Srename_buffer);
defsubr (&Sother_buffer);
@@ -6442,5 +6474,9 @@ This is the default. If nil, auto-save file deletion is inhibited. */);
defsubr (&Soverlay_put);
defsubr (&Srestore_buffer_modified_p);
+ DEFSYM (Qautosaved, "autosaved");
+
+ DEFSYM (Qkill_buffer__possibly_save, "kill-buffer--possibly-save");
+
Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt);
}
diff --git a/src/bytecode.c b/src/bytecode.c
index 472992be180..d75767bb0c5 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -21,11 +21,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "blockinput.h"
+#include "sysstdio.h"
#include "character.h"
#include "buffer.h"
#include "keyboard.h"
#include "syntax.h"
#include "window.h"
+#include "puresize.h"
/* Work around GCC bug 54561. */
#if GNUC_PREREQ (4, 3, 0)
@@ -174,8 +176,8 @@ DEFINE (Bmin, 0136) \
DEFINE (Bmult, 0137) \
\
DEFINE (Bpoint, 0140) \
-/* Was Bmark in v17. */ \
-DEFINE (Bsave_current_buffer, 0141) /* Obsolete. */ \
+/* 0141 was Bmark in v17, Bsave_current_buffer in 18-19. */ \
+DEFINE (Bsave_current_buffer_OBSOLETE, 0141) /* Obsolete since 20. */ \
DEFINE (Bgoto_char, 0142) \
DEFINE (Binsert, 0143) \
DEFINE (Bpoint_max, 0144) \
@@ -185,13 +187,15 @@ DEFINE (Bfollowing_char, 0147) \
DEFINE (Bpreceding_char, 0150) \
DEFINE (Bcurrent_column, 0151) \
DEFINE (Bindent_to, 0152) \
+/* 0153 was Bscan_buffer in v17. */ \
DEFINE (Beolp, 0154) \
DEFINE (Beobp, 0155) \
DEFINE (Bbolp, 0156) \
DEFINE (Bbobp, 0157) \
DEFINE (Bcurrent_buffer, 0160) \
DEFINE (Bset_buffer, 0161) \
-DEFINE (Bsave_current_buffer_1, 0162) /* Replacing Bsave_current_buffer. */ \
+DEFINE (Bsave_current_buffer, 0162) \
+/* 0163 was Bset_mark in v17. */ \
DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \
\
DEFINE (Bforward_char, 0165) \
@@ -226,7 +230,7 @@ DEFINE (Bcondition_case, 0217) /* Obsolete since Emacs-25. */ \
DEFINE (Btemp_output_buffer_setup, 0220) /* Obsolete since Emacs-24.1. */ \
DEFINE (Btemp_output_buffer_show, 0221) /* Obsolete since Emacs-24.1. */ \
\
-DEFINE (Bunbind_all, 0222) /* Obsolete. Never used. */ \
+/* 0222 was Bunbind_all, never used. */ \
\
DEFINE (Bset_marker, 0223) \
DEFINE (Bmatch_beginning, 0224) \
@@ -252,11 +256,7 @@ DEFINE (Brem, 0246) \
DEFINE (Bnumberp, 0247) \
DEFINE (Bintegerp, 0250) \
\
-DEFINE (BRgoto, 0252) \
-DEFINE (BRgotoifnil, 0253) \
-DEFINE (BRgotoifnonnil, 0254) \
-DEFINE (BRgotoifnilelsepop, 0255) \
-DEFINE (BRgotoifnonnilelsepop, 0256) \
+/* 0252-0256 were relative jumps, apparently never used. */ \
\
DEFINE (BlistN, 0257) \
DEFINE (BconcatN, 0260) \
@@ -276,11 +276,6 @@ enum byte_code_op
#define DEFINE(name, value) name = value,
BYTE_CODES
#undef DEFINE
-
-#if BYTE_CODE_SAFE
- Bscan_buffer = 0153, /* No longer generated as of v18. */
- Bset_mark = 0163, /* this loser is no longer generated as of v18 */
-#endif
};
/* Fetch the next byte from the bytecode stream. */
@@ -290,7 +285,7 @@ enum byte_code_op
/* Fetch two bytes from the bytecode stream and make a 16-bit number
out of them. */
-#define FETCH2 (op = FETCH, op + (FETCH << 8))
+#define FETCH2 (op = FETCH, op | (FETCH << 8))
/* Push X onto the execution stack. The expression X should not
contain TOP, to avoid competing side effects. */
@@ -330,8 +325,8 @@ If the third argument is incorrect, Emacs may crash. */)
the original unibyte form. */
bytestr = Fstring_as_unibyte (bytestr);
}
-
- return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL);
+ Lisp_Object fun = CALLN (Fmake_byte_code, Qnil, bytestr, vector, maxdepth);
+ return exec_byte_code (fun, 0, 0, NULL);
}
static void
@@ -340,70 +335,213 @@ bcall0 (Lisp_Object f)
Ffuncall (1, &f);
}
-/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and
- MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect,
- emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp
- argument list (including &rest, &optional, etc.), and ARGS, of size
- NARGS, should be a vector of the actual arguments. The arguments in
- ARGS are pushed on the stack according to ARGS_TEMPLATE before
- executing BYTESTR. */
+/* The bytecode stack size in bytes.
+ This is a fairly generous amount, but:
+ - if users need more, we could allocate more, or just reserve the address
+ space and allocate on demand
+ - if threads are used more, then it might be a good idea to reduce the
+ per-thread overhead in time and space
+ - for maximum flexibility but a small runtime penalty, we could allocate
+ the stack in smaller chunks as needed
+*/
+#define BC_STACK_SIZE (512 * 1024 * sizeof (Lisp_Object))
+
+/* Bytecode interpreter stack:
+
+ |--------------| --
+ |fun | | ^ stack growth
+ |saved_pc | | | direction
+ |saved_top ------- |
+ fp--->|saved_fp ---- | | current frame
+ |--------------| | | | (called from bytecode in this example)
+ | (free) | | | |
+ top-->| ...stack... | | | |
+ : ... : | | |
+ |incoming args | | | |
+ |--------------| | | --
+ |fun | | | |
+ |saved_pc | | | |
+ |saved_top | | | |
+ |saved_fp |<- | | previous frame
+ |--------------| | |
+ | (free) | | |
+ | ...stack... |<---- |
+ : ... : |
+ |incoming args | |
+ |--------------| --
+ : :
+*/
+
+/* bytecode stack frame header (footer, actually) */
+struct bc_frame {
+ struct bc_frame *saved_fp; /* previous frame pointer,
+ NULL if bottommost frame */
+
+ /* In a frame called directly from C, the following two members are NULL. */
+ Lisp_Object *saved_top; /* previous stack pointer */
+ const unsigned char *saved_pc; /* previous program counter */
+
+ Lisp_Object fun; /* current function object */
+
+ Lisp_Object next_stack[]; /* data stack of next frame */
+};
+
+void
+init_bc_thread (struct bc_thread_state *bc)
+{
+ bc->stack = xmalloc (BC_STACK_SIZE);
+ bc->stack_end = bc->stack + BC_STACK_SIZE;
+ /* Put a dummy header at the bottom to indicate the first free location. */
+ bc->fp = (struct bc_frame *)bc->stack;
+ memset (bc->fp, 0, sizeof *bc->fp);
+}
+
+void
+free_bc_thread (struct bc_thread_state *bc)
+{
+ xfree (bc->stack);
+}
+
+void
+mark_bytecode (struct bc_thread_state *bc)
+{
+ struct bc_frame *fp = bc->fp;
+ Lisp_Object *top = NULL; /* stack pointer of topmost frame not known */
+ for (;;)
+ {
+ struct bc_frame *next_fp = fp->saved_fp;
+ /* Only the dummy frame at the bottom has saved_fp = NULL. */
+ if (!next_fp)
+ break;
+ mark_object (fp->fun);
+ Lisp_Object *frame_base = next_fp->next_stack;
+ if (top)
+ {
+ /* The stack pointer of a frame is known: mark the part of the stack
+ above it conservatively. This includes any outgoing arguments. */
+ mark_memory (top + 1, fp);
+ /* Mark the rest of the stack precisely. */
+ mark_objects (frame_base, top + 1 - frame_base);
+ }
+ else
+ {
+ /* The stack pointer is unknown -- mark everything conservatively. */
+ mark_memory (frame_base, fp);
+ }
+ top = fp->saved_top;
+ fp = next_fp;
+ }
+}
+
+DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats,
+ 0, 0, 0,
+ doc: /* internal */)
+ (void)
+{
+ struct bc_thread_state *bc = &current_thread->bc;
+ int nframes = 0;
+ int nruns = 0;
+ for (struct bc_frame *fp = bc->fp; fp; fp = fp->saved_fp)
+ {
+ nframes++;
+ if (fp->saved_top == NULL)
+ nruns++;
+ }
+ fprintf (stderr, "%d stack frames, %d runs\n", nframes, nruns);
+ return Qnil;
+}
+
+/* Whether a stack pointer is valid in the current frame. */
+static bool
+valid_sp (struct bc_thread_state *bc, Lisp_Object *sp)
+{
+ struct bc_frame *fp = bc->fp;
+ return sp < (Lisp_Object *)fp && sp + 1 >= fp->saved_fp->next_stack;
+}
+
+/* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity
+ encoded as an integer (the one in FUN is ignored), and ARGS, of
+ size NARGS, should be a vector of the actual arguments. The
+ arguments in ARGS are pushed on the stack according to
+ ARGS_TEMPLATE before executing FUN. */
Lisp_Object
-exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
- Lisp_Object args_template, ptrdiff_t nargs, Lisp_Object *args)
+exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
+ ptrdiff_t nargs, Lisp_Object *args)
{
#ifdef BYTE_CODE_METER
int volatile this_op = 0;
#endif
+ unsigned char quitcounter = 1;
+ struct bc_thread_state *bc = &current_thread->bc;
- eassert (!STRING_MULTIBYTE (bytestr));
+ /* Values used for the first stack record when called from C. */
+ Lisp_Object *top = NULL;
+ unsigned char const *pc = NULL;
+ Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE);
+
+ setup_frame: ;
+ eassert (!STRING_MULTIBYTE (bytestr));
+ eassert (string_immovable_p (bytestr));
+ /* FIXME: in debug mode (!NDEBUG, BYTE_CODE_SAFE or enabled checking),
+ save the specpdl index on function entry and check that it is the same
+ when returning, to detect unwind imbalances. This would require adding
+ a field to the frame header. */
+
+ Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS);
+ Lisp_Object maxdepth = AREF (fun, COMPILED_STACK_DEPTH);
ptrdiff_t const_length = ASIZE (vector);
ptrdiff_t bytestr_length = SCHARS (bytestr);
Lisp_Object *vectorp = XVECTOR (vector)->contents;
- unsigned char quitcounter = 1;
- EMACS_INT stack_items = XFIXNAT (maxdepth) + 1;
- USE_SAFE_ALLOCA;
- void *alloc;
- SAFE_ALLOCA_LISP_EXTRA (alloc, stack_items, bytestr_length);
- Lisp_Object *stack_base = alloc;
- Lisp_Object *top = stack_base;
- *top = vector; /* Ensure VECTOR survives GC (Bug#33014). */
- Lisp_Object *stack_lim = stack_base + stack_items;
- unsigned char const *bytestr_data = memcpy (stack_lim,
- SDATA (bytestr), bytestr_length);
- unsigned char const *pc = bytestr_data;
- ptrdiff_t count = SPECPDL_INDEX ();
-
- if (!NILP (args_template))
- {
- eassert (FIXNUMP (args_template));
- ptrdiff_t at = XFIXNUM (args_template);
- bool rest = (at & 128) != 0;
- int mandatory = at & 127;
- ptrdiff_t nonrest = at >> 8;
- ptrdiff_t maxargs = rest ? PTRDIFF_MAX : nonrest;
- if (! (mandatory <= nargs && nargs <= maxargs))
- Fsignal (Qwrong_number_of_arguments,
- list2 (Fcons (make_fixnum (mandatory), make_fixnum (nonrest)),
- make_fixnum (nargs)));
- ptrdiff_t pushedargs = min (nonrest, nargs);
- for (ptrdiff_t i = 0; i < pushedargs; i++, args++)
- PUSH (*args);
- if (nonrest < nargs)
- PUSH (Flist (nargs - nonrest, args));
- else
- for (ptrdiff_t i = nargs - rest; i < nonrest; i++)
- PUSH (Qnil);
- }
+ EMACS_INT max_stack = XFIXNAT (maxdepth);
+ Lisp_Object *frame_base = bc->fp->next_stack;
+ struct bc_frame *fp = (struct bc_frame *)(frame_base + max_stack);
+
+ if ((char *)fp->next_stack > bc->stack_end)
+ error ("Bytecode stack overflow");
+
+ /* Save the function object so that the bytecode and vector are
+ held from removal by the GC. */
+ fp->fun = fun;
+ /* Save previous stack pointer and pc in the new frame. If we came
+ directly from outside, these will be NULL. */
+ fp->saved_top = top;
+ fp->saved_pc = pc;
+ fp->saved_fp = bc->fp;
+ bc->fp = fp;
+
+ top = frame_base - 1;
+ unsigned char const *bytestr_data = SDATA (bytestr);
+ pc = bytestr_data;
+
+ /* ARGS_TEMPLATE is composed of bit fields:
+ bits 0..6 minimum number of arguments
+ bits 7 1 iff &rest argument present
+ bits 8..14 maximum number of arguments */
+ bool rest = (args_template & 128) != 0;
+ int mandatory = args_template & 127;
+ ptrdiff_t nonrest = args_template >> 8;
+ if (! (mandatory <= nargs && (rest || nargs <= nonrest)))
+ Fsignal (Qwrong_number_of_arguments,
+ list2 (Fcons (make_fixnum (mandatory), make_fixnum (nonrest)),
+ make_fixnum (nargs)));
+ ptrdiff_t pushedargs = min (nonrest, nargs);
+ for (ptrdiff_t i = 0; i < pushedargs; i++, args++)
+ PUSH (*args);
+ if (nonrest < nargs)
+ PUSH (Flist (nargs - nonrest, args));
+ else
+ for (ptrdiff_t i = nargs - rest; i < nonrest; i++)
+ PUSH (Qnil);
while (true)
{
int op;
enum handlertype type;
- if (BYTE_CODE_SAFE && ! (stack_base <= top && top < stack_lim))
+ if (BYTE_CODE_SAFE && !valid_sp (bc, top))
emacs_abort ();
#ifdef BYTE_CODE_METER
@@ -451,17 +589,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
#ifdef BYTE_CODE_THREADED
- /* A convenience define that saves us a lot of typing and makes
- the table clearer. */
-#define LABEL(OP) [OP] = &&insn_ ## OP
-
/* This is the dispatch table for the threaded interpreter. */
static const void *const targets[256] =
{
[0 ... (Bconstant - 1)] = &&insn_default,
[Bconstant ... 255] = &&insn_Bconstant,
-#define DEFINE(name, value) LABEL (name) ,
+#define DEFINE(name, value) [name] = &&insn_ ## name,
BYTE_CODES
#undef DEFINE
};
@@ -493,7 +627,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
Lisp_Object v1 = vectorp[op], v2;
if (!SYMBOLP (v1)
|| XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL
- || (v2 = SYMBOL_VAL (XSYMBOL (v1)), EQ (v2, Qunbound)))
+ || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound)))
v2 = Fsymbol_value (v1);
PUSH (v2);
NEXT;
@@ -560,7 +694,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
/* Inline the most common case. */
if (SYMBOLP (sym)
- && !EQ (val, Qunbound)
+ && !BASE_EQ (val, Qunbound)
&& XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL
&& !SYMBOL_TRAPPED_WRITE_P (sym))
SET_SYMBOL_VAL (XSYMBOL (sym), val);
@@ -629,7 +763,59 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
}
}
#endif
- TOP = Ffuncall (op + 1, &TOP);
+ maybe_quit ();
+
+ if (++lisp_eval_depth > max_lisp_eval_depth)
+ {
+ if (max_lisp_eval_depth < 100)
+ max_lisp_eval_depth = 100;
+ if (lisp_eval_depth > max_lisp_eval_depth)
+ error ("Lisp nesting exceeds `max-lisp-eval-depth'");
+ }
+
+ ptrdiff_t call_nargs = op;
+ Lisp_Object call_fun = TOP;
+ Lisp_Object *call_args = &TOP + 1;
+
+ specpdl_ref count1 = record_in_backtrace (call_fun,
+ call_args, call_nargs);
+ maybe_gc ();
+ if (debug_on_next_call)
+ do_debug_on_call (Qlambda, count1);
+
+ Lisp_Object original_fun = call_fun;
+ if (SYMBOLP (call_fun))
+ call_fun = XSYMBOL (call_fun)->u.s.function;
+ Lisp_Object template;
+ Lisp_Object bytecode;
+ if (COMPILEDP (call_fun)
+ // Lexical binding only.
+ && (template = AREF (call_fun, COMPILED_ARGLIST),
+ FIXNUMP (template))
+ // No autoloads.
+ && (bytecode = AREF (call_fun, COMPILED_BYTECODE),
+ !CONSP (bytecode)))
+ {
+ fun = call_fun;
+ bytestr = bytecode;
+ args_template = XFIXNUM (template);
+ nargs = call_nargs;
+ args = call_args;
+ goto setup_frame;
+ }
+
+ Lisp_Object val;
+ if (SUBRP (call_fun) && !SUBR_NATIVE_COMPILED_DYNP (call_fun))
+ val = funcall_subr (XSUBR (call_fun), call_nargs, call_args);
+ else
+ val = funcall_general (original_fun, call_nargs, call_args);
+
+ lisp_eval_depth--;
+ if (backtrace_debug_on_exit (specpdl_ptr - 1))
+ val = call_debugger (list2 (Qexit, val));
+ specpdl_ptr--;
+
+ TOP = val;
NEXT;
}
@@ -649,20 +835,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Bunbind5):
op -= Bunbind;
dounbind:
- unbind_to (SPECPDL_INDEX () - op, Qnil);
- NEXT;
-
- CASE (Bunbind_all): /* Obsolete. Never used. */
- /* To unbind back to the beginning of this frame. Not used yet,
- but will be needed for tail-recursion elimination. */
- unbind_to (count, Qnil);
+ unbind_to (specpdl_ref_add (SPECPDL_INDEX (), -op), Qnil);
NEXT;
CASE (Bgoto):
op = FETCH2;
op_branch:
op -= pc - bytestr_data;
- op_relative_branch:
if (BYTE_CODE_SAFE
&& ! (bytestr_data - pc <= op
&& op < bytestr_data + bytestr_length - pc))
@@ -697,38 +876,41 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
DISCARD (1);
NEXT;
- CASE (BRgoto):
- op = FETCH - 128;
- goto op_relative_branch;
-
- CASE (BRgotoifnil):
- op = FETCH - 128;
- if (NILP (POP))
- goto op_relative_branch;
- NEXT;
-
- CASE (BRgotoifnonnil):
- op = FETCH - 128;
- if (!NILP (POP))
- goto op_relative_branch;
- NEXT;
-
- CASE (BRgotoifnilelsepop):
- op = FETCH - 128;
- if (NILP (TOP))
- goto op_relative_branch;
- DISCARD (1);
- NEXT;
-
- CASE (BRgotoifnonnilelsepop):
- op = FETCH - 128;
- if (!NILP (TOP))
- goto op_relative_branch;
- DISCARD (1);
- NEXT;
-
CASE (Breturn):
- goto exit;
+ {
+ Lisp_Object *saved_top = bc->fp->saved_top;
+ if (saved_top)
+ {
+ Lisp_Object val = TOP;
+
+ lisp_eval_depth--;
+ if (backtrace_debug_on_exit (specpdl_ptr - 1))
+ val = call_debugger (list2 (Qexit, val));
+ specpdl_ptr--;
+
+ top = saved_top;
+ pc = bc->fp->saved_pc;
+ struct bc_frame *fp = bc->fp->saved_fp;
+ bc->fp = fp;
+
+ Lisp_Object fun = fp->fun;
+ Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE);
+ Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS);
+ bytestr_data = SDATA (bytestr);
+ vectorp = XVECTOR (vector)->contents;
+ if (BYTE_CODE_SAFE)
+ {
+ /* Only required for checking, not for execution. */
+ const_length = ASIZE (vector);
+ bytestr_length = SCHARS (bytestr);
+ }
+
+ TOP = val;
+ NEXT;
+ }
+ else
+ goto exit;
+ }
CASE (Bdiscard):
DISCARD (1);
@@ -742,14 +924,14 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
record_unwind_protect_excursion ();
NEXT;
- CASE (Bsave_current_buffer): /* Obsolete since ??. */
- CASE (Bsave_current_buffer_1):
+ CASE (Bsave_current_buffer_OBSOLETE): /* Obsolete since 20. */
+ CASE (Bsave_current_buffer):
record_unwind_current_buffer ();
NEXT;
CASE (Bsave_window_excursion): /* Obsolete since 24.1. */
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
record_unwind_protect (restore_window_configuration,
Fcurrent_window_configuration (Qnil));
TOP = Fprogn (TOP);
@@ -783,9 +965,23 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
if (sys_setjmp (c->jmp))
{
struct handler *c = handlerlist;
+ handlerlist = c->next;
top = c->bytecode_top;
op = c->bytecode_dest;
- handlerlist = c->next;
+ struct bc_frame *fp = bc->fp;
+
+ Lisp_Object fun = fp->fun;
+ Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE);
+ Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS);
+ bytestr_data = SDATA (bytestr);
+ vectorp = XVECTOR (vector)->contents;
+ if (BYTE_CODE_SAFE)
+ {
+ /* Only required for checking, not for execution. */
+ const_length = ASIZE (vector);
+ bytestr_length = SCHARS (bytestr);
+ }
+ pc = bytestr_data;
PUSH (c->val);
goto op_branch;
}
@@ -825,7 +1021,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
temp_output_buffer_show (TOP);
TOP = v1;
/* pop binding of standard-output */
- unbind_to (SPECPDL_INDEX () - 1, Qnil);
+ unbind_to (specpdl_ref_add (SPECPDL_INDEX (), -1), Qnil);
NEXT;
}
@@ -903,15 +1099,39 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Baref):
{
- Lisp_Object v1 = POP;
- TOP = Faref (TOP, v1);
+ Lisp_Object idxval = POP;
+ Lisp_Object arrayval = TOP;
+ ptrdiff_t size;
+ ptrdiff_t idx;
+ if (((VECTORP (arrayval) && (size = ASIZE (arrayval), true))
+ || (RECORDP (arrayval) && (size = PVSIZE (arrayval), true)))
+ && FIXNUMP (idxval)
+ && (idx = XFIXNUM (idxval),
+ idx >= 0 && idx < size))
+ TOP = AREF (arrayval, idx);
+ else
+ TOP = Faref (arrayval, idxval);
NEXT;
}
CASE (Baset):
{
- Lisp_Object v2 = POP, v1 = POP;
- TOP = Faset (TOP, v1, v2);
+ Lisp_Object newelt = POP;
+ Lisp_Object idxval = POP;
+ Lisp_Object arrayval = TOP;
+ ptrdiff_t size;
+ ptrdiff_t idx;
+ if (((VECTORP (arrayval) && (size = ASIZE (arrayval), true))
+ || (RECORDP (arrayval) && (size = PVSIZE (arrayval), true)))
+ && FIXNUMP (idxval)
+ && (idx = XFIXNUM (idxval),
+ idx >= 0 && idx < size))
+ {
+ ASET (arrayval, idx, newelt);
+ TOP = newelt;
+ }
+ else
+ TOP = Faset (arrayval, idxval, newelt);
NEXT;
}
@@ -986,43 +1206,72 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Beqlsign):
{
- Lisp_Object v1 = POP;
- TOP = arithcompare (TOP, v1, ARITH_EQUAL);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ TOP = BASE_EQ (v1, v2) ? Qt : Qnil;
+ else
+ TOP = arithcompare (v1, v2, ARITH_EQUAL);
NEXT;
}
CASE (Bgtr):
{
- Lisp_Object v1 = POP;
- TOP = arithcompare (TOP, v1, ARITH_GRTR);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ TOP = XFIXNUM (v1) > XFIXNUM (v2) ? Qt : Qnil;
+ else
+ TOP = arithcompare (v1, v2, ARITH_GRTR);
NEXT;
}
CASE (Blss):
{
- Lisp_Object v1 = POP;
- TOP = arithcompare (TOP, v1, ARITH_LESS);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ TOP = XFIXNUM (v1) < XFIXNUM (v2) ? Qt : Qnil;
+ else
+ TOP = arithcompare (v1, v2, ARITH_LESS);
NEXT;
}
CASE (Bleq):
{
- Lisp_Object v1 = POP;
- TOP = arithcompare (TOP, v1, ARITH_LESS_OR_EQUAL);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ TOP = XFIXNUM (v1) <= XFIXNUM (v2) ? Qt : Qnil;
+ else
+ TOP = arithcompare (v1, v2, ARITH_LESS_OR_EQUAL);
NEXT;
}
CASE (Bgeq):
{
- Lisp_Object v1 = POP;
- TOP = arithcompare (TOP, v1, ARITH_GRTR_OR_EQUAL);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ TOP = XFIXNUM (v1) >= XFIXNUM (v2) ? Qt : Qnil;
+ else
+ TOP = arithcompare (v1, v2, ARITH_GRTR_OR_EQUAL);
NEXT;
}
CASE (Bdiff):
- DISCARD (1);
- TOP = Fminus (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ EMACS_INT res;
+ if (FIXNUMP (v1) && FIXNUMP (v2)
+ && (res = XFIXNUM (v1) - XFIXNUM (v2),
+ !FIXNUM_OVERFLOW_P (res)))
+ TOP = make_fixnum (res);
+ else
+ TOP = Fminus (2, &TOP);
+ NEXT;
+ }
CASE (Bnegate):
TOP = (FIXNUMP (TOP) && XFIXNUM (TOP) != MOST_NEGATIVE_FIXNUM
@@ -1031,34 +1280,83 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
NEXT;
CASE (Bplus):
- DISCARD (1);
- TOP = Fplus (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ EMACS_INT res;
+ if (FIXNUMP (v1) && FIXNUMP (v2)
+ && (res = XFIXNUM (v1) + XFIXNUM (v2),
+ !FIXNUM_OVERFLOW_P (res)))
+ TOP = make_fixnum (res);
+ else
+ TOP = Fplus (2, &TOP);
+ NEXT;
+ }
CASE (Bmax):
- DISCARD (1);
- TOP = Fmax (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ {
+ if (XFIXNUM (v2) > XFIXNUM (v1))
+ TOP = v2;
+ }
+ else
+ TOP = Fmax (2, &TOP);
+ NEXT;
+ }
CASE (Bmin):
- DISCARD (1);
- TOP = Fmin (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2))
+ {
+ if (XFIXNUM (v2) < XFIXNUM (v1))
+ TOP = v2;
+ }
+ else
+ TOP = Fmin (2, &TOP);
+ NEXT;
+ }
CASE (Bmult):
- DISCARD (1);
- TOP = Ftimes (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ intmax_t res;
+ if (FIXNUMP (v1) && FIXNUMP (v2)
+ && !INT_MULTIPLY_WRAPV (XFIXNUM (v1), XFIXNUM (v2), &res)
+ && !FIXNUM_OVERFLOW_P (res))
+ TOP = make_fixnum (res);
+ else
+ TOP = Ftimes (2, &TOP);
+ NEXT;
+ }
CASE (Bquo):
- DISCARD (1);
- TOP = Fquo (2, &TOP);
- NEXT;
+ {
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ EMACS_INT res;
+ if (FIXNUMP (v1) && FIXNUMP (v2) && XFIXNUM (v2) != 0
+ && (res = XFIXNUM (v1) / XFIXNUM (v2),
+ !FIXNUM_OVERFLOW_P (res)))
+ TOP = make_fixnum (res);
+ else
+ TOP = Fquo (2, &TOP);
+ NEXT;
+ }
CASE (Brem):
{
- Lisp_Object v1 = POP;
- TOP = Frem (TOP, v1);
+ Lisp_Object v2 = POP;
+ Lisp_Object v1 = TOP;
+ if (FIXNUMP (v1) && FIXNUMP (v2) && XFIXNUM (v2) != 0)
+ TOP = make_fixnum (XFIXNUM (v1) % XFIXNUM (v2));
+ else
+ TOP = Frem (v1, v2);
NEXT;
}
@@ -1081,12 +1379,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
NEXT;
CASE (Bpoint_max):
- {
- Lisp_Object v1;
- XSETFASTINT (v1, ZV);
- PUSH (v1);
- NEXT;
- }
+ PUSH (make_fixed_natnum (ZV));
+ NEXT;
CASE (Bpoint_min):
PUSH (make_fixed_natnum (BEGV));
@@ -1167,13 +1461,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
NEXT;
CASE (Bchar_syntax):
- {
- CHECK_CHARACTER (TOP);
- int c = XFIXNAT (TOP);
- if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
- c = make_char_multibyte (c);
- XSETFASTINT (TOP, syntax_code_spec[SYNTAX (c)]);
- }
+ TOP = Fchar_syntax (TOP);
NEXT;
CASE (Bbuffer_substring):
@@ -1291,15 +1579,23 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Bsetcar):
{
- Lisp_Object v1 = POP;
- TOP = Fsetcar (TOP, v1);
+ Lisp_Object newval = POP;
+ Lisp_Object cell = TOP;
+ CHECK_CONS (cell);
+ CHECK_IMPURE (cell, XCONS (cell));
+ XSETCAR (cell, newval);
+ TOP = newval;
NEXT;
}
CASE (Bsetcdr):
{
- Lisp_Object v1 = POP;
- TOP = Fsetcdr (TOP, v1);
+ Lisp_Object newval = POP;
+ Lisp_Object cell = TOP;
+ CHECK_CONS (cell);
+ CHECK_IMPURE (cell, XCONS (cell));
+ XSETCDR (cell, newval);
+ TOP = newval;
NEXT;
}
@@ -1324,19 +1620,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
TOP = INTEGERP (TOP) ? Qt : Qnil;
NEXT;
-#if BYTE_CODE_SAFE
- /* These are intentionally written using 'case' syntax,
- because they are incompatible with the threaded
- interpreter. */
-
- case Bset_mark:
- error ("set-mark is an obsolete bytecode");
- break;
- case Bscan_buffer:
- error ("scan-buffer is an obsolete bytecode");
- break;
-#endif
-
CASE_ABORT:
/* Actually this is Bstack_ref with offset 0, but we use Bdup
for that instead. */
@@ -1395,6 +1678,12 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
/* TODO: Perhaps introduce another byte-code for switch when the
number of cases is less, which uses a simple vector for linear
search as the jump table. */
+
+ /* TODO: Instead of pushing the table in a separate
+ Bconstant op, use an immediate argument (maybe separate
+ switch opcodes for 1-byte and 2-byte constant indices).
+ This would also get rid of some hacks that assume each
+ Bswitch to be preceded by a Bconstant. */
Lisp_Object jmp_table = POP;
if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table))
emacs_abort ();
@@ -1437,16 +1726,9 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
exit:
- /* Binds and unbinds are supposed to be compiled balanced. */
- if (SPECPDL_INDEX () != count)
- {
- if (SPECPDL_INDEX () > count)
- unbind_to (count, Qnil);
- error ("binding stack not balanced (serious byte compiler bug)");
- }
+ bc->fp = bc->fp->saved_fp;
Lisp_Object result = TOP;
- SAFE_FREE ();
return result;
}
@@ -1468,6 +1750,7 @@ void
syms_of_bytecode (void)
{
defsubr (&Sbyte_code);
+ defsubr (&Sinternal_stack_stats);
#ifdef BYTE_CODE_METER
diff --git a/src/callint.c b/src/callint.c
index ce77c893f48..ffa3b231eb5 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -170,7 +170,7 @@ check_mark (bool for_region)
of VALUES to do its job. */
static void
-fix_command (Lisp_Object input, Lisp_Object values)
+fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values)
{
/* FIXME: Instead of this ugly hack, we should provide a way for an
interactive spec to return an expression/function that will re-build the
@@ -230,6 +230,37 @@ fix_command (Lisp_Object input, Lisp_Object values)
}
}
}
+
+ /* If the list contains a bunch of trailing nil values, and they are
+ optional, remove them from the list. This makes navigating the
+ history less confusing, since it doesn't contain a lot of
+ parameters that aren't used. */
+ if (CONSP (values))
+ {
+ Lisp_Object arity = Ffunc_arity (function);
+ /* We don't want to do this simplification if we have an &rest
+ function, because (cl-defun foo (a &optional (b 'zot)) ..)
+ etc. */
+ if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity)))
+ {
+ Lisp_Object final = Qnil;
+ ptrdiff_t final_i = 0, i = 0;
+ for (Lisp_Object tail = values;
+ CONSP (tail);
+ tail = XCDR (tail), ++i)
+ {
+ if (!NILP (XCAR (tail)))
+ {
+ final = tail;
+ final_i = i;
+ }
+ }
+
+ /* Chop the trailing optional values. */
+ if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
+ XSETCDR (final, Qnil);
+ }
+ }
}
/* Helper function to call `read-file-name' from C. */
@@ -251,7 +282,7 @@ return non-nil.
usage: (funcall-interactively FUNCTION &rest ARGUMENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t speccount = SPECPDL_INDEX ();
+ specpdl_ref speccount = SPECPDL_INDEX ();
temporarily_switch_to_single_kboard (NULL);
/* Nothing special to do here, all the work is inside
@@ -279,7 +310,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
`this-command-keys-vector' is used. */)
(Lisp_Object function, Lisp_Object record_flag, Lisp_Object keys)
{
- ptrdiff_t speccount = SPECPDL_INDEX ();
+ specpdl_ref speccount = SPECPDL_INDEX ();
bool arg_from_tty = false;
ptrdiff_t key_count;
@@ -315,7 +346,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
Lisp_Object up_event = Qnil;
/* Set SPECS to the interactive form, or barf if not interactive. */
- Lisp_Object form = Finteractive_form (function);
+ Lisp_Object form = call1 (Qinteractive_form, function);
if (! CONSP (form))
wrong_type_argument (Qcommandp, function);
Lisp_Object specs = Fcar (XCDR (form));
@@ -340,7 +371,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
Make a copy of the list of values, for the command history,
and turn them into things we can eval. */
Lisp_Object values = quotify_args (Fcopy_sequence (specs));
- fix_command (input, values);
+ fix_command (input, function, values);
call4 (intern ("add-to-history"), intern ("command-history"),
Fcons (function, values), Qnil, Qt);
}
@@ -408,7 +439,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
&& (w = XCAR (w), WINDOWP (w)))
{
if (MINI_WINDOW_P (XWINDOW (w))
- && ! (minibuf_level > 0 && EQ (w, minibuf_window)))
+ && ! (minibuf_level > 0 && BASE_EQ (w, minibuf_window)))
error ("Attempt to select inactive minibuffer window");
/* If the current buffer wants to clean up, let it. */
@@ -478,7 +509,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
case 'b': /* Name of existing buffer. */
args[i] = Fcurrent_buffer ();
- if (EQ (selected_window, minibuf_window))
+ if (BASE_EQ (selected_window, minibuf_window))
args[i] = Fother_buffer (args[i], Qnil, Qnil);
args[i] = Fread_buffer (callint_message, args[i], Qt, Qnil);
break;
@@ -541,7 +572,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
case 'k': /* Key sequence. */
{
- ptrdiff_t speccount1 = SPECPDL_INDEX ();
+ specpdl_ref speccount1 = SPECPDL_INDEX ();
specbind (Qcursor_in_echo_area, Qt);
/* Prompt in `minibuffer-prompt' face. */
Fput_text_property (make_fixnum (0),
@@ -571,7 +602,7 @@ invoke it (via an `interactive' spec that contains, for instance, an
case 'K': /* Key sequence to be defined. */
{
- ptrdiff_t speccount1 = SPECPDL_INDEX ();
+ specpdl_ref speccount1 = SPECPDL_INDEX ();
specbind (Qcursor_in_echo_area, Qt);
/* Prompt in `minibuffer-prompt' face. */
Fput_text_property (make_fixnum (0),
diff --git a/src/callproc.c b/src/callproc.c
index 4d3b0bb8e06..dd162f36a6c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -85,6 +85,10 @@ extern char **environ;
#include "nsterm.h"
#endif
+#ifdef HAVE_PGTK
+#include "pgtkterm.h"
+#endif
+
/* Pattern used by call-process-region to make temp files. */
static Lisp_Object Vtemp_file_name_pattern;
@@ -122,7 +126,7 @@ enum
CALLPROC_FDS
};
-static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
+static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, specpdl_ref);
#ifdef DOS_NT
# define CHILD_SETUP_TYPE int
@@ -289,7 +293,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
{
Lisp_Object infile, encoded_infile;
int filefd;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (nargs >= 2 && ! NILP (args[1]))
{
@@ -310,12 +314,13 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
if (filefd < 0)
report_file_error ("Opening process input file", infile);
record_unwind_protect_int (close_file_unwind, filefd);
- return unbind_to (count, call_process (nargs, args, filefd, -1));
+ return unbind_to (count, call_process (nargs, args, filefd,
+ make_invalid_specpdl_ref ()));
}
/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file.
- If TEMPFILE_INDEX is nonnegative, it is the specpdl index of an
+ If TEMPFILE_INDEX is valid, it is the specpdl index of an
unwinder that is intended to remove the input temporary file; in
this case NARGS must be at least 2 and ARGS[1] is the file's name.
@@ -323,7 +328,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
static Lisp_Object
call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
- ptrdiff_t tempfile_index)
+ specpdl_ref tempfile_index)
{
Lisp_Object buffer, current_dir, path;
bool display_p;
@@ -331,7 +336,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
int callproc_fd[CALLPROC_FDS];
int status;
ptrdiff_t i;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
USE_SAFE_ALLOCA;
char **new_argv;
@@ -616,7 +621,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
callproc_fd[i] = -1;
}
emacs_close (filefd);
- clear_unwind_protect (count - 1);
+ clear_unwind_protect (specpdl_ref_add (count, -1));
if (tempfile)
{
@@ -654,7 +659,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
if (FIXNUMP (buffer))
{
- if (tempfile_index < 0)
+ if (!specpdl_ref_valid_p (tempfile_index))
record_deleted_pid (pid, Qnil);
else
{
@@ -681,7 +686,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
callproc_fd[i] = -1;
}
emacs_close (filefd);
- clear_unwind_protect (count - 1);
+ clear_unwind_protect (specpdl_ref_add (count, -1));
#endif /* not MSDOS */
@@ -813,7 +818,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
else
{ /* We have to decode the input. */
Lisp_Object curbuf;
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
XSETBUFFER (curbuf, current_buffer);
/* We cannot allow after-change-functions be run
@@ -957,7 +962,6 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
{
Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
char *tempfile;
- ptrdiff_t count;
#ifdef WINDOWSNT
/* Cannot use the result of Fexpand_file_name, because it
@@ -977,7 +981,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
filename_string = Fcopy_sequence (ENCODE_FILE (pattern));
tempfile = SSDATA (filename_string);
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_nothing ();
fd = mkostemp (tempfile, O_BINARY | O_CLOEXEC);
if (fd < 0)
@@ -1009,7 +1013,7 @@ create_temp_file (ptrdiff_t nargs, Lisp_Object *args,
val = complement_process_encoding_system (val);
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
specbind (intern ("coding-system-for-write"), val);
/* POSIX lets mk[s]temp use "."; don't invoke jka-compr if we
@@ -1069,7 +1073,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object infile, val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object start = args[0];
Lisp_Object end = args[1];
bool empty_input;
@@ -1123,7 +1127,8 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
}
args[1] = infile;
- val = call_process (nargs, args, fd, empty_input ? -1 : count);
+ val = call_process (nargs, args, fd,
+ empty_input ? make_invalid_specpdl_ref () : count);
return unbind_to (count, val);
}
@@ -1334,7 +1339,8 @@ emacs_posix_spawn_init_actions (posix_spawn_file_actions_t *actions,
}
static int
-emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes)
+emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes,
+ const sigset_t *oldset)
{
int error = posix_spawnattr_init (attributes);
if (error != 0)
@@ -1376,11 +1382,7 @@ emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes)
goto out;
/* Stop blocking SIGCHLD in the child. */
- sigset_t oldset;
- error = pthread_sigmask (SIG_SETMASK, NULL, &oldset);
- if (error != 0)
- goto out;
- error = posix_spawnattr_setsigmask (attributes, &oldset);
+ error = posix_spawnattr_setsigmask (attributes, oldset);
if (error != 0)
goto out;
@@ -1391,23 +1393,6 @@ emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes)
return error;
}
-static int
-emacs_posix_spawn_init (posix_spawn_file_actions_t *actions,
- posix_spawnattr_t *attributes, int std_in,
- int std_out, int std_err, const char *cwd)
-{
- int error = emacs_posix_spawn_init_actions (actions, std_in,
- std_out, std_err, cwd);
- if (error != 0)
- return error;
-
- error = emacs_posix_spawn_init_attributes (attributes);
- if (error != 0)
- return error;
-
- return 0;
-}
-
#endif
/* Start a new asynchronous subprocess. If successful, return zero
@@ -1442,9 +1427,12 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
if (use_posix_spawn)
{
/* Initialize optional attributes before blocking. */
- int error
- = emacs_posix_spawn_init (&actions, &attributes, std_in,
- std_out, std_err, cwd);
+ int error = emacs_posix_spawn_init_actions (&actions, std_in,
+ std_out, std_err, cwd);
+ if (error != 0)
+ return error;
+
+ error = emacs_posix_spawn_init_attributes (&attributes, oldset);
if (error != 0)
return error;
}
@@ -1500,7 +1488,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
if (pty != NULL)
pid = fork ();
else
- pid = vfork ();
+ pid = VFORK ();
#else
pid = vfork ();
#endif
@@ -1703,6 +1691,7 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value,
/* For DISPLAY try to get the values from the frame or the initial env. */
if (strcmp (var, "DISPLAY") == 0)
{
+#ifndef HAVE_PGTK
Lisp_Object display
= Fframe_parameter (NILP (frame) ? selected_frame : frame, Qdisplay);
if (STRINGP (display))
@@ -1711,6 +1700,7 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value,
*valuelen = SBYTES (display);
return 1;
}
+#endif
/* If still not found, Look for DISPLAY in Vinitial_environment. */
if (getenv_internal_1 (var, varlen, value, valuelen,
Vinitial_environment))
@@ -1828,6 +1818,18 @@ make_environment_block (Lisp_Object current_dir)
if (NILP (display))
{
Lisp_Object tmp = Fframe_parameter (selected_frame, Qdisplay);
+
+#ifdef HAVE_PGTK
+ /* The only time GDK actually returns correct information is
+ when it's running under X Windows. DISPLAY shouldn't be
+ set to a Wayland display either, since that's an X specific
+ variable. */
+ if (FRAME_WINDOW_P (SELECTED_FRAME ())
+ && strcmp (G_OBJECT_TYPE_NAME (FRAME_X_DISPLAY (SELECTED_FRAME ())),
+ "GdkX11Display"))
+ tmp = Qnil;
+#endif
+
if (!STRINGP (tmp) && CONSP (Vinitial_environment))
/* If still not found, Look for DISPLAY in Vinitial_environment. */
tmp = Fgetenv_internal (build_string ("DISPLAY"),
diff --git a/src/ccl.c b/src/ccl.c
index 377eb3a0ea5..1a4f73500a3 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -33,6 +33,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "charset.h"
#include "ccl.h"
#include "coding.h"
+#include "keyboard.h"
+
+/* Avoid GCC 12 bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105784>. */
+#if GNUC_PREREQ (12, 0, 0)
+# pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value"
+#endif
/* Table of registered CCL programs. Each element is a vector of
NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the
diff --git a/src/character.c b/src/character.c
index eba417d005d..d12df23f8ea 100644
--- a/src/character.c
+++ b/src/character.c
@@ -654,15 +654,14 @@ str_as_multibyte (unsigned char *str, ptrdiff_t len, ptrdiff_t nbytes,
ptrdiff_t
count_size_as_multibyte (const unsigned char *str, ptrdiff_t len)
{
- const unsigned char *endp = str + len;
+ /* Count the number of non-ASCII (raw) bytes, since they will occupy
+ two bytes in a multibyte string. */
+ ptrdiff_t nonascii = 0;
+ for (ptrdiff_t i = 0; i < len; i++)
+ nonascii += str[i] >> 7;
ptrdiff_t bytes;
-
- for (bytes = 0; str < endp; str++)
- {
- int n = *str < 0x80 ? 1 : 2;
- if (INT_ADD_WRAPV (bytes, n, &bytes))
- string_overflow ();
- }
+ if (INT_ADD_WRAPV (len, nonascii, &bytes))
+ string_overflow ();
return bytes;
}
@@ -735,31 +734,6 @@ str_as_unibyte (unsigned char *str, ptrdiff_t bytes)
return (to - str);
}
-/* Convert eight-bit chars in SRC (in multibyte form) to the
- corresponding byte and store in DST. CHARS is the number of
- characters in SRC. The value is the number of bytes stored in DST.
- Usually, the value is the same as CHARS, but is less than it if SRC
- contains a non-ASCII, non-eight-bit character. */
-
-ptrdiff_t
-str_to_unibyte (const unsigned char *src, unsigned char *dst, ptrdiff_t chars)
-{
- ptrdiff_t i;
-
- for (i = 0; i < chars; i++)
- {
- int c = string_char_advance (&src);
-
- if (CHAR_BYTE8_P (c))
- c = CHAR_TO_BYTE8 (c);
- else if (! ASCII_CHAR_P (c))
- return i;
- *dst++ = c;
- }
- return i;
-}
-
-
static ptrdiff_t
string_count_byte8 (Lisp_Object string)
{
diff --git a/src/character.h b/src/character.h
index 6ee6bcab205..2ca935ba04c 100644
--- a/src/character.h
+++ b/src/character.h
@@ -569,8 +569,6 @@ extern ptrdiff_t str_as_multibyte (unsigned char *, ptrdiff_t, ptrdiff_t,
ptrdiff_t *);
extern ptrdiff_t str_to_multibyte (unsigned char *, ptrdiff_t, ptrdiff_t);
extern ptrdiff_t str_as_unibyte (unsigned char *, ptrdiff_t);
-extern ptrdiff_t str_to_unibyte (const unsigned char *, unsigned char *,
- ptrdiff_t);
extern ptrdiff_t strwidth (const char *, ptrdiff_t);
extern ptrdiff_t c_string_width (const unsigned char *, ptrdiff_t, int,
ptrdiff_t *, ptrdiff_t *);
diff --git a/src/charset.c b/src/charset.c
index dec9d56df2c..9edbd4c8c84 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -483,7 +483,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
AUTO_STRING (map, ".map");
AUTO_STRING (txt, ".txt");
AUTO_LIST2 (suffixes, map, txt);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_nothing ();
specbind (Qfile_name_handler_alist, Qnil);
fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false, false);
@@ -495,7 +495,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
report_file_errno ("Loading charset map", mapfile, open_errno);
}
set_unwind_protect_ptr (count, fclose_unwind, fp);
- unbind_to (count + 1, Qnil);
+ unbind_to (specpdl_ref_add (count, 1), Qnil);
/* Use record_xmalloc, as `charset_map_entries' is
large (larger than MAX_ALLOCA). */
@@ -793,16 +793,21 @@ map_charset_chars (void (*c_function)(Lisp_Object, Lisp_Object), Lisp_Object fun
DEFUN ("map-charset-chars", Fmap_charset_chars, Smap_charset_chars, 2, 5, 0,
doc: /* Call FUNCTION for all characters in CHARSET.
-FUNCTION is called with an argument RANGE and the optional 3rd
-argument ARG.
-
-RANGE is a cons (FROM . TO), where FROM and TO indicate a range of
-characters contained in CHARSET.
-
-The optional 4th and 5th arguments FROM-CODE and TO-CODE specify the
-range of code points (in CHARSET) of target characters. Note that
-these are not character codes, but code points in CHARSET; for the
-difference see `decode-char' and `list-charset-chars'. */)
+Optional 3rd argument ARG is an additional argument to be passed
+to FUNCTION, see below.
+Optional 4th and 5th arguments FROM-CODE and TO-CODE specify the
+range of code points (in CHARSET) of target characters on which to
+map the FUNCTION. Note that these are not character codes, but code
+points of CHARSET; for the difference see `decode-char' and
+`list-charset-chars'. If FROM-CODE is nil or imitted, it stands for
+the first code point of CHARSET; if TO-CODE is nil or omitted, it
+stands for the last code point of CHARSET.
+
+FUNCTION will be called with two arguments: RANGE and ARG.
+RANGE is a cons (FROM . TO), where FROM and TO specify a range of
+characters that belong to CHARSET on which FUNCTION should do its
+job. FROM and TO are Emacs character codes, unlike FROM-CODE and
+TO-CODE, which are CHARSET code points. */)
(Lisp_Object function, Lisp_Object charset, Lisp_Object arg, Lisp_Object from_code, Lisp_Object to_code)
{
struct charset *cs;
diff --git a/src/coding.c b/src/coding.c
index df6c423caaa..3fb4f148b1c 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -1131,7 +1131,6 @@ detect_coding_utf_8 (struct coding_system *coding,
ptrdiff_t consumed_chars = 0;
bool bom_found = 0;
ptrdiff_t nchars = coding->head_ascii;
- int eol_seen = coding->eol_seen;
detect_info->checked |= CATEGORY_MASK_UTF_8;
/* A coding system of this category is always ASCII compatible. */
@@ -1161,15 +1160,10 @@ detect_coding_utf_8 (struct coding_system *coding,
{
if (src < src_end && *src == '\n')
{
- eol_seen |= EOL_SEEN_CRLF;
src++;
nchars++;
}
- else
- eol_seen |= EOL_SEEN_CR;
}
- else if (c == '\n')
- eol_seen |= EOL_SEEN_LF;
continue;
}
ONE_MORE_BYTE (c1);
@@ -6534,7 +6528,7 @@ detect_coding (struct coding_system *coding)
if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qundecided))
{
int c, i;
- struct coding_detection_info detect_info;
+ struct coding_detection_info detect_info = {0};
bool null_byte_found = 0, eight_bit_found = 0;
bool inhibit_nbd = inhibit_flag (coding->spec.undecided.inhibit_nbd,
inhibit_null_byte_detection);
@@ -6543,7 +6537,6 @@ detect_coding (struct coding_system *coding)
bool prefer_utf_8 = coding->spec.undecided.prefer_utf_8;
coding->head_ascii = 0;
- detect_info.checked = detect_info.found = detect_info.rejected = 0;
for (src = coding->source; src < src_end; src++)
{
c = *src;
@@ -6718,12 +6711,8 @@ detect_coding (struct coding_system *coding)
else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id)))
== coding_category_utf_8_auto)
{
- Lisp_Object coding_systems;
- struct coding_detection_info detect_info;
-
- coding_systems
+ Lisp_Object coding_systems
= AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom);
- detect_info.found = detect_info.rejected = 0;
if (check_ascii (coding) == coding->src_bytes)
{
if (CONSP (coding_systems))
@@ -6731,6 +6720,7 @@ detect_coding (struct coding_system *coding)
}
else
{
+ struct coding_detection_info detect_info = {0};
if (CONSP (coding_systems)
&& detect_coding_utf_8 (coding, &detect_info))
{
@@ -6744,20 +6734,19 @@ detect_coding (struct coding_system *coding)
else if (XFIXNUM (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id)))
== coding_category_utf_16_auto)
{
- Lisp_Object coding_systems;
- struct coding_detection_info detect_info;
-
- coding_systems
+ Lisp_Object coding_systems
= AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom);
- detect_info.found = detect_info.rejected = 0;
coding->head_ascii = 0;
- if (CONSP (coding_systems)
- && detect_coding_utf_16 (coding, &detect_info))
+ if (CONSP (coding_systems))
{
- if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
- found = XCAR (coding_systems);
- else if (detect_info.found & CATEGORY_MASK_UTF_16_BE)
- found = XCDR (coding_systems);
+ struct coding_detection_info detect_info = {0};
+ if (detect_coding_utf_16 (coding, &detect_info))
+ {
+ if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
+ found = XCAR (coding_systems);
+ else if (detect_info.found & CATEGORY_MASK_UTF_16_BE)
+ found = XCDR (coding_systems);
+ }
}
}
@@ -7907,7 +7896,7 @@ coding_restore_undo_list (Lisp_Object arg)
void
decode_coding_gap (struct coding_system *coding, ptrdiff_t bytes)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object attrs;
eassert (GPT_BYTE == PT_BYTE);
@@ -8071,7 +8060,7 @@ decode_coding_object (struct coding_system *coding,
ptrdiff_t to, ptrdiff_t to_byte,
Lisp_Object dst_object)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
unsigned char *destination UNINIT;
ptrdiff_t dst_bytes UNINIT;
ptrdiff_t chars = to - from;
@@ -8170,7 +8159,7 @@ decode_coding_object (struct coding_system *coding,
ptrdiff_t prev_Z = Z, prev_Z_BYTE = Z_BYTE;
Lisp_Object val;
Lisp_Object undo_list = BVAR (current_buffer, undo_list);
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
record_unwind_protect (coding_restore_undo_list,
Fcons (undo_list, Fcurrent_buffer ()));
@@ -8205,7 +8194,7 @@ decode_coding_object (struct coding_system *coding,
if (saved_pt >= 0)
{
/* This is the case of:
- (BUFFERP (src_object) && EQ (src_object, dst_object))
+ (BUFFERP (src_object) && BASE_EQ (src_object, dst_object))
As we have moved PT while replacing the original buffer
contents, we must recover it now. */
set_buffer_internal (XBUFFER (src_object));
@@ -8290,7 +8279,7 @@ encode_coding_object (struct coding_system *coding,
ptrdiff_t to, ptrdiff_t to_byte,
Lisp_Object dst_object)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t chars = to - from;
ptrdiff_t bytes = to_byte - from_byte;
Lisp_Object attrs;
@@ -8309,7 +8298,7 @@ encode_coding_object (struct coding_system *coding,
attrs = CODING_ID_ATTRS (coding->id);
bool same_buffer = false;
- if (EQ (src_object, dst_object) && BUFFERP (src_object))
+ if (BASE_EQ (src_object, dst_object) && BUFFERP (src_object))
{
struct Lisp_Marker *tail;
@@ -8390,7 +8379,7 @@ encode_coding_object (struct coding_system *coding,
if (BUFFERP (dst_object))
{
coding->dst_object = dst_object;
- if (EQ (src_object, dst_object))
+ if (BASE_EQ (src_object, dst_object))
{
coding->dst_pos = from;
coding->dst_pos_byte = from_byte;
@@ -8445,7 +8434,7 @@ encode_coding_object (struct coding_system *coding,
if (saved_pt >= 0)
{
/* This is the case of:
- (BUFFERP (src_object) && EQ (src_object, dst_object))
+ (BUFFERP (src_object) && BASE_EQ (src_object, dst_object))
As we have moved PT while replacing the original buffer
contents, we must recover it now. */
set_buffer_internal (XBUFFER (src_object));
@@ -8584,7 +8573,7 @@ are lower-case). */)
(Lisp_Object prompt, Lisp_Object default_coding_system)
{
Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (SYMBOLP (default_coding_system))
default_coding_system = SYMBOL_NAME (default_coding_system);
@@ -8645,7 +8634,7 @@ detect_coding_system (const unsigned char *src,
Lisp_Object val = Qnil;
struct coding_system coding;
ptrdiff_t id;
- struct coding_detection_info detect_info;
+ struct coding_detection_info detect_info = {0};
enum coding_category base_category;
bool null_byte_found = 0, eight_bit_found = 0;
@@ -8664,8 +8653,6 @@ detect_coding_system (const unsigned char *src,
coding.mode |= CODING_MODE_LAST_BLOCK;
coding.head_ascii = 0;
- detect_info.checked = detect_info.found = detect_info.rejected = 0;
-
/* At first, detect text-format if necessary. */
base_category = XFIXNUM (CODING_ATTR_CATEGORY (attrs));
if (base_category == coding_category_undecided)
@@ -9429,7 +9416,7 @@ code_convert_region (Lisp_Object start, Lisp_Object end,
setup_coding_system (coding_system, &coding);
coding.mode |= CODING_MODE_LAST_BLOCK;
- if (BUFFERP (dst_object) && !EQ (dst_object, src_object))
+ if (BUFFERP (dst_object) && !BASE_EQ (dst_object, src_object))
{
struct buffer *buf = XBUFFER (dst_object);
ptrdiff_t buf_pt = BUF_PT (buf);
@@ -10798,7 +10785,7 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */)
&& ((STRINGP (target)
&& STRINGP (XCAR (elt))
&& fast_string_match (XCAR (elt), target) >= 0)
- || (FIXNUMP (target) && EQ (target, XCAR (elt)))))
+ || (FIXNUMP (target) && BASE_EQ (target, XCAR (elt)))))
{
val = XCDR (elt);
/* Here, if VAL is both a valid coding system and a valid
@@ -11512,7 +11499,7 @@ DEFUN ("coding-system-put", Fcoding_system_put, Scoding_system_put,
}
ASET (attrs, coding_attr_plist,
- Fplist_put (CODING_ATTR_PLIST (attrs), prop, val));
+ plist_put (CODING_ATTR_PLIST (attrs), prop, val));
return val;
}
diff --git a/src/comp.c b/src/comp.c
index 64db13fc1cb..81d27299fa4 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -447,13 +447,14 @@ load_gccjit_if_necessary (bool mandatory)
/* Increase this number to force a new Vcomp_abi_hash to be generated. */
-#define ABI_VERSION "4"
+#define ABI_VERSION "5"
/* Length of the hashes used for eln file naming. */
#define HASH_LENGTH 8
/* C symbols emitted for the load relocation mechanism. */
#define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
+#define F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM "f_symbols_with_pos_enabled_reloc"
#define PURE_RELOC_SYM "pure_reloc"
#define DATA_RELOC_SYM "d_reloc"
#define DATA_RELOC_IMPURE_SYM "d_reloc_imp"
@@ -479,6 +480,10 @@ load_gccjit_if_necessary (bool mandatory)
#define THIRD(x) \
XCAR (XCDR (XCDR (x)))
+/* Like call0 but stringify and intern. */
+#define CALL0I(fun) \
+ CALLN (Ffuncall, intern_c_string (STR (fun)))
+
/* Like call1 but stringify and intern. */
#define CALL1I(fun, arg) \
CALLN (Ffuncall, intern_c_string (STR (fun)), arg)
@@ -511,8 +516,6 @@ typedef struct {
ptrdiff_t size;
} f_reloc_t;
-sigset_t saved_sigset;
-
static f_reloc_t freloc;
#define NUM_CAST_TYPES 15
@@ -542,6 +545,7 @@ typedef struct {
gcc_jit_type *emacs_int_type;
gcc_jit_type *emacs_uint_type;
gcc_jit_type *void_ptr_type;
+ gcc_jit_type *bool_ptr_type;
gcc_jit_type *char_ptr_type;
gcc_jit_type *ptrdiff_type;
gcc_jit_type *uintptr_type;
@@ -563,6 +567,16 @@ typedef struct {
gcc_jit_field *lisp_cons_u_s_u_cdr;
gcc_jit_type *lisp_cons_type;
gcc_jit_type *lisp_cons_ptr_type;
+ /* struct Lisp_Symbol_With_Position */
+ gcc_jit_rvalue *f_symbols_with_pos_enabled_ref;
+ gcc_jit_struct *lisp_symbol_with_position;
+ gcc_jit_field *lisp_symbol_with_position_header;
+ gcc_jit_field *lisp_symbol_with_position_sym;
+ gcc_jit_field *lisp_symbol_with_position_pos;
+ gcc_jit_type *lisp_symbol_with_position_type;
+ gcc_jit_type *lisp_symbol_with_position_ptr_type;
+ gcc_jit_function *get_symbol_with_position;
+ gcc_jit_function *symbol_with_pos_sym;
/* struct jmp_buf. */
gcc_jit_struct *jmp_buf_s;
/* struct handler. */
@@ -632,7 +646,7 @@ typedef struct {
static comp_t comp;
-FILE *logfile = NULL;
+static FILE *logfile;
/* This is used for serialized objects by the reload mechanism. */
typedef struct {
@@ -650,13 +664,16 @@ typedef struct {
Helper functions called by the run-time.
*/
-void helper_unwind_protect (Lisp_Object handler);
-Lisp_Object helper_temp_output_buffer_setup (Lisp_Object x);
-Lisp_Object helper_unbind_n (Lisp_Object n);
-void helper_save_restriction (void);
-bool helper_PSEUDOVECTOR_TYPEP_XUNTAG (Lisp_Object a, enum pvec_type code);
+static void helper_unwind_protect (Lisp_Object);
+static Lisp_Object helper_unbind_n (Lisp_Object);
+static void helper_save_restriction (void);
+static bool helper_PSEUDOVECTOR_TYPEP_XUNTAG (Lisp_Object, enum pvec_type);
+static struct Lisp_Symbol_With_Pos *
+helper_GET_SYMBOL_WITH_POSITION (Lisp_Object);
-void *helper_link_table[] =
+/* Note: helper_link_table must match the list created by
+ `declare_runtime_imported_funcs'. */
+static void *helper_link_table[] =
{ wrong_type_argument,
helper_PSEUDOVECTOR_TYPEP_XUNTAG,
pure_write_error,
@@ -664,6 +681,7 @@ void *helper_link_table[] =
record_unwind_protect_excursion,
helper_unbind_n,
helper_save_restriction,
+ helper_GET_SYMBOL_WITH_POSITION,
record_unwind_current_buffer,
set_internal,
helper_unwind_protect,
@@ -738,12 +756,12 @@ comp_hash_source_file (Lisp_Object filename)
DEFUN ("comp--subr-signature", Fcomp__subr_signature,
Scomp__subr_signature, 1, 1, 0,
- doc: /* Support function to 'hash_native_abi'.
+ doc: /* Support function to hash_native_abi.
For internal use. */)
(Lisp_Object subr)
{
return concat2 (Fsubr_name (subr),
- Fprin1_to_string (Fsubr_arity (subr), Qnil));
+ Fprin1_to_string (Fsubr_arity (subr), Qnil, Qnil));
}
/* Produce a key hashing Vcomp_subr_list. */
@@ -1328,9 +1346,9 @@ emit_XCONS (gcc_jit_rvalue *a)
}
static gcc_jit_rvalue *
-emit_EQ (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
+emit_BASE_EQ (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
{
- emit_comment ("EQ");
+ emit_comment ("BASE_EQ");
return gcc_jit_context_new_comparison (
comp.ctxt,
@@ -1341,6 +1359,30 @@ emit_EQ (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
}
static gcc_jit_rvalue *
+emit_AND (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
+{
+ return gcc_jit_context_new_binary_op (
+ comp.ctxt,
+ NULL,
+ GCC_JIT_BINARY_OP_LOGICAL_AND,
+ comp.bool_type,
+ x,
+ y);
+}
+
+static gcc_jit_rvalue *
+emit_OR (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
+{
+ return gcc_jit_context_new_binary_op (
+ comp.ctxt,
+ NULL,
+ GCC_JIT_BINARY_OP_LOGICAL_OR,
+ comp.bool_type,
+ x,
+ y);
+}
+
+static gcc_jit_rvalue *
emit_TAGGEDP (gcc_jit_rvalue *obj, Lisp_Word_tag tag)
{
/* (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
@@ -1402,6 +1444,85 @@ emit_CONSP (gcc_jit_rvalue *obj)
}
static gcc_jit_rvalue *
+emit_BARE_SYMBOL_P (gcc_jit_rvalue *obj)
+{
+ emit_comment ("BARE_SYMBOL_P");
+
+ return gcc_jit_context_new_cast (comp.ctxt,
+ NULL,
+ emit_TAGGEDP (obj, Lisp_Symbol),
+ comp.bool_type);
+}
+
+static gcc_jit_rvalue *
+emit_SYMBOL_WITH_POS_P (gcc_jit_rvalue *obj)
+{
+ emit_comment ("SYMBOL_WITH_POS_P");
+
+ gcc_jit_rvalue *args[] =
+ { obj,
+ gcc_jit_context_new_rvalue_from_int (comp.ctxt,
+ comp.int_type,
+ PVEC_SYMBOL_WITH_POS)
+ };
+
+ return gcc_jit_context_new_call (comp.ctxt,
+ NULL,
+ comp.pseudovectorp,
+ 2,
+ args);
+}
+
+static gcc_jit_rvalue *
+emit_SYMBOL_WITH_POS_SYM (gcc_jit_rvalue *obj)
+{
+ emit_comment ("SYMBOL_WITH_POS_SYM");
+
+ gcc_jit_rvalue *arg [] = { obj };
+ return gcc_jit_context_new_call (comp.ctxt,
+ NULL,
+ comp.symbol_with_pos_sym,
+ 1,
+ arg);
+}
+
+static gcc_jit_rvalue *
+emit_EQ (gcc_jit_rvalue *x, gcc_jit_rvalue *y)
+{
+ return
+ emit_OR (
+ gcc_jit_context_new_comparison (
+ comp.ctxt, NULL,
+ GCC_JIT_COMPARISON_EQ,
+ emit_XLI (x), emit_XLI (y)),
+ emit_AND (
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference (comp.f_symbols_with_pos_enabled_ref,
+ NULL)),
+ emit_OR (
+ emit_AND (
+ emit_SYMBOL_WITH_POS_P (x),
+ emit_OR (
+ emit_AND (
+ emit_SYMBOL_WITH_POS_P (y),
+ emit_BASE_EQ (
+ emit_XLI (emit_SYMBOL_WITH_POS_SYM (x)),
+ emit_XLI (emit_SYMBOL_WITH_POS_SYM (y)))),
+ emit_AND (
+ emit_BARE_SYMBOL_P (y),
+ emit_BASE_EQ (
+ emit_XLI (emit_SYMBOL_WITH_POS_SYM (x)),
+ emit_XLI (y))))),
+ emit_AND (
+ emit_BARE_SYMBOL_P (x),
+ emit_AND (
+ emit_SYMBOL_WITH_POS_P (y),
+ emit_BASE_EQ (
+ emit_XLI (x),
+ emit_XLI (emit_SYMBOL_WITH_POS_SYM (y))))))));
+}
+
+static gcc_jit_rvalue *
emit_FLOATP (gcc_jit_rvalue *obj)
{
emit_comment ("FLOATP");
@@ -1586,7 +1707,7 @@ static gcc_jit_lvalue *
emit_lisp_obj_reloc_lval (Lisp_Object obj)
{
emit_comment (format_string ("l-value for lisp obj: %s",
- SSDATA (Fprin1_to_string (obj, Qnil))));
+ SSDATA (Fprin1_to_string (obj, Qnil, Qnil))));
imm_reloc_t reloc = obj_to_reloc (obj);
return gcc_jit_context_new_array_access (comp.ctxt,
@@ -1599,9 +1720,9 @@ static gcc_jit_rvalue *
emit_lisp_obj_rval (Lisp_Object obj)
{
emit_comment (format_string ("const lisp obj: %s",
- SSDATA (Fprin1_to_string (obj, Qnil))));
+ SSDATA (Fprin1_to_string (obj, Qnil, Qnil))));
- if (EQ (obj, Qnil))
+ if (NILP (obj))
{
gcc_jit_rvalue *n;
n = emit_rvalue_from_lisp_word ((Lisp_Word) iQnil);
@@ -1615,7 +1736,7 @@ static gcc_jit_rvalue *
emit_NILP (gcc_jit_rvalue *x)
{
emit_comment ("NILP");
- return emit_EQ (x, emit_lisp_obj_rval (Qnil));
+ return emit_BASE_EQ (x, emit_lisp_obj_rval (Qnil));
}
static gcc_jit_rvalue *
@@ -1731,6 +1852,29 @@ emit_CHECK_CONS (gcc_jit_rvalue *x)
args));
}
+static void
+emit_CHECK_SYMBOL_WITH_POS (gcc_jit_rvalue *x)
+{
+ emit_comment ("CHECK_SYMBOL_WITH_POS");
+
+ gcc_jit_rvalue *args[] =
+ { gcc_jit_context_new_cast (comp.ctxt,
+ NULL,
+ emit_SYMBOL_WITH_POS_P (x),
+ comp.int_type),
+ emit_lisp_obj_rval (Qsymbol_with_pos_p),
+ x };
+
+ gcc_jit_block_add_eval (
+ comp.block,
+ NULL,
+ gcc_jit_context_new_call (comp.ctxt,
+ NULL,
+ comp.check_type,
+ 3,
+ args));
+}
+
static gcc_jit_rvalue *
emit_car_addr (gcc_jit_rvalue *c)
{
@@ -1824,7 +1968,7 @@ emit_mvar_rval (Lisp_Object mvar)
SSDATA (
Fprin1_to_string (
NILP (func) ? value : CALL1I (comp-func-c-name, func),
- Qnil)));
+ Qnil, Qnil)));
}
if (FIXNUMP (value))
{
@@ -2095,7 +2239,13 @@ emit_limple_insn (Lisp_Object insn)
gcc_jit_block *target1 = retrive_block (arg[2]);
gcc_jit_block *target2 = retrive_block (arg[3]);
- emit_cond_jump (emit_EQ (a, b), target1, target2);
+ if ((!NILP (CALL1I (comp-cstr-imm-vld-p, arg[0]))
+ && NILP (CALL1I (comp-cstr-imm, arg[0])))
+ || (!NILP (CALL1I (comp-cstr-imm-vld-p, arg[1]))
+ && NILP (CALL1I (comp-cstr-imm, arg[1]))))
+ emit_cond_jump (emit_BASE_EQ (a, b), target1, target2);
+ else
+ emit_cond_jump (emit_EQ (a, b), target1, target2);
}
else if (EQ (op, Qcond_jump_narg_leq))
{
@@ -2321,7 +2471,7 @@ emit_limple_insn (Lisp_Object insn)
else if (EQ (op, Qsetimm))
{
/* Ex: (setimm #s(comp-mvar 9 1 t 3 nil) a). */
- emit_comment (SSDATA (Fprin1_to_string (arg[1], Qnil)));
+ emit_comment (SSDATA (Fprin1_to_string (arg[1], Qnil, Qnil)));
imm_reloc_t reloc = obj_to_reloc (arg[1]);
emit_frame_assignment (
arg[0],
@@ -2487,7 +2637,7 @@ emit_static_object (const char *name, Lisp_Object obj)
strings cause of this funny bug that will affect all pre gcc10 era gccs:
https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Preserve uninterned symbols, this is specifically necessary for
CL macro expansion in dynamic scope code (bug#42088). See
`byte-compile-output-file-form'. */
@@ -2497,7 +2647,7 @@ emit_static_object (const char *name, Lisp_Object obj)
specbind (intern_c_string ("print-quoted"), Qt);
specbind (intern_c_string ("print-gensym"), Qt);
specbind (intern_c_string ("print-circle"), Qt);
- Lisp_Object str = Fprin1_to_string (obj, Qnil);
+ Lisp_Object str = Fprin1_to_string (obj, Qnil, Qnil);
unbind_to (count, Qnil);
ptrdiff_t len = SBYTES (str);
@@ -2714,7 +2864,8 @@ declare_imported_data (void)
/*
Declare as imported all the functions that are requested from the runtime.
- These are either subrs or not.
+ These are either subrs or not. Note that the list created here must match
+ the array `helper_link_table'.
*/
static Lisp_Object
declare_runtime_imported_funcs (void)
@@ -2751,6 +2902,10 @@ declare_runtime_imported_funcs (void)
ADD_IMPORTED (helper_save_restriction, comp.void_type, 0, NULL);
+ args[0] = comp.lisp_obj_type;
+ ADD_IMPORTED (helper_GET_SYMBOL_WITH_POSITION, comp.lisp_symbol_with_position_ptr_type,
+ 1, args);
+
ADD_IMPORTED (record_unwind_current_buffer, comp.void_type, 0, NULL);
args[0] = args[1] = args[2] = comp.lisp_obj_type;
@@ -2798,6 +2953,15 @@ emit_ctxt_code (void)
gcc_jit_type_get_pointer (comp.thread_state_ptr_type),
CURRENT_THREAD_RELOC_SYM));
+ comp.f_symbols_with_pos_enabled_ref =
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_context_new_global (
+ comp.ctxt,
+ NULL,
+ GCC_JIT_GLOBAL_EXPORTED,
+ comp.bool_ptr_type,
+ F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM));
+
comp.pure_ptr =
gcc_jit_lvalue_as_rvalue (
gcc_jit_context_new_global (
@@ -2977,6 +3141,39 @@ define_lisp_cons (void)
}
+static void
+define_lisp_symbol_with_position (void)
+{
+ comp.lisp_symbol_with_position_header =
+ gcc_jit_context_new_field (comp.ctxt,
+ NULL,
+ comp.ptrdiff_type,
+ "header");
+ comp.lisp_symbol_with_position_sym =
+ gcc_jit_context_new_field (comp.ctxt,
+ NULL,
+ comp.lisp_obj_type,
+ "sym");
+ comp.lisp_symbol_with_position_pos =
+ gcc_jit_context_new_field (comp.ctxt,
+ NULL,
+ comp.lisp_obj_type,
+ "pos");
+ gcc_jit_field *fields [3] = {comp.lisp_symbol_with_position_header,
+ comp.lisp_symbol_with_position_sym,
+ comp.lisp_symbol_with_position_pos};
+ comp.lisp_symbol_with_position =
+ gcc_jit_context_new_struct_type (comp.ctxt,
+ NULL,
+ "comp_lisp_symbol_with_position",
+ 3,
+ fields);
+ comp.lisp_symbol_with_position_type =
+ gcc_jit_struct_as_type (comp.lisp_symbol_with_position);
+ comp.lisp_symbol_with_position_ptr_type =
+ gcc_jit_type_get_pointer (comp.lisp_symbol_with_position_type);
+}
+
/* Opaque jmp_buf definition. */
static void
@@ -3673,6 +3870,82 @@ define_PSEUDOVECTORP (void)
}
static void
+define_GET_SYMBOL_WITH_POSITION (void)
+{
+ gcc_jit_param *param[] =
+ { gcc_jit_context_new_param (comp.ctxt,
+ NULL,
+ comp.lisp_obj_type,
+ "a") };
+
+ comp.get_symbol_with_position =
+ gcc_jit_context_new_function (comp.ctxt, NULL,
+ GCC_JIT_FUNCTION_INTERNAL,
+ comp.lisp_symbol_with_position_ptr_type,
+ "GET_SYMBOL_WITH_POSITION",
+ 1,
+ param,
+ 0);
+
+ DECL_BLOCK (entry_block, comp.get_symbol_with_position);
+
+ comp.block = entry_block;
+ comp.func = comp.get_symbol_with_position;
+
+ gcc_jit_rvalue *args[] =
+ { gcc_jit_param_as_rvalue (param[0]) };
+ /* FIXME use XUNTAG now that's available. */
+ gcc_jit_block_end_with_return (
+ entry_block,
+ NULL,
+ emit_call (intern_c_string ("helper_GET_SYMBOL_WITH_POSITION"),
+ comp.lisp_symbol_with_position_ptr_type,
+ 1, args, false));
+}
+
+static void define_SYMBOL_WITH_POS_SYM (void)
+{
+ gcc_jit_rvalue *tmpr, *swp;
+ gcc_jit_lvalue *tmpl;
+
+ gcc_jit_param *param [] =
+ { gcc_jit_context_new_param (comp.ctxt,
+ NULL,
+ comp.lisp_obj_type,
+ "a") };
+ comp.symbol_with_pos_sym =
+ gcc_jit_context_new_function (comp.ctxt, NULL,
+ GCC_JIT_FUNCTION_INTERNAL,
+ comp.lisp_obj_type,
+ "SYMBOL_WITH_POS_SYM",
+ 1,
+ param,
+ 0);
+
+ DECL_BLOCK (entry_block, comp.symbol_with_pos_sym);
+ comp.func = comp.symbol_with_pos_sym;
+ comp.block = entry_block;
+
+ emit_CHECK_SYMBOL_WITH_POS (gcc_jit_param_as_rvalue (param [0]));
+
+ gcc_jit_rvalue *args[] = { gcc_jit_param_as_rvalue (param [0]) };
+
+ swp = gcc_jit_context_new_call (comp.ctxt,
+ NULL,
+ comp.get_symbol_with_position,
+ 1,
+ args);
+ tmpl = gcc_jit_rvalue_dereference (swp, NULL);
+ tmpr = gcc_jit_lvalue_as_rvalue (tmpl);
+ gcc_jit_block_end_with_return (entry_block,
+ NULL,
+ gcc_jit_rvalue_access_field (
+ tmpr,
+ NULL,
+ comp.lisp_symbol_with_position_sym));
+}
+
+static void
define_CHECK_IMPURE (void)
{
gcc_jit_param *param[] =
@@ -3989,7 +4262,7 @@ compile_function (Lisp_Object func)
{
Lisp_Object block_name = HASH_KEY (ht, i);
if (!EQ (block_name, Qentry)
- && !EQ (block_name, Qunbound))
+ && !BASE_EQ (block_name, Qunbound))
declare_block (block_name);
}
@@ -4002,7 +4275,7 @@ compile_function (Lisp_Object func)
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++)
{
Lisp_Object block_name = HASH_KEY (ht, i);
- if (!EQ (block_name, Qunbound))
+ if (!BASE_EQ (block_name, Qunbound))
{
Lisp_Object block = HASH_VALUE (ht, i);
Lisp_Object insns = CALL1I (comp-block-insns, block);
@@ -4124,7 +4397,7 @@ one for the file name and another for its contents, followed by .eln. */)
{
Lisp_Object match_idx =
Fstring_match (XCAR (lds_re_tail), filename, Qnil, Qnil);
- if (EQ (match_idx, make_fixnum (0)))
+ if (BASE_EQ (match_idx, make_fixnum (0)))
{
filename =
Freplace_match (build_string ("//"), Qt, Qt, filename, Qnil);
@@ -4309,6 +4582,7 @@ Return t on success. */)
gcc_jit_context_get_type (comp.ctxt, GCC_JIT_TYPE_LONG_LONG);
comp.unsigned_long_long_type =
gcc_jit_context_get_type (comp.ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ comp.bool_ptr_type = gcc_jit_type_get_pointer (comp.bool_type);
comp.char_ptr_type = gcc_jit_type_get_pointer (comp.char_type);
comp.emacs_int_type = gcc_jit_context_get_int_type (comp.ctxt,
sizeof (EMACS_INT),
@@ -4381,6 +4655,7 @@ Return t on success. */)
/* Define data structures. */
define_lisp_cons ();
+ define_lisp_symbol_with_position ();
define_jmp_buf ();
define_handler_struct ();
define_thread_state_struct ();
@@ -4602,7 +4877,9 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
/* Define inline functions. */
define_CAR_CDR ();
define_PSEUDOVECTORP ();
+ define_GET_SYMBOL_WITH_POSITION ();
define_CHECK_TYPE ();
+ define_SYMBOL_WITH_POS_SYM ();
define_CHECK_IMPURE ();
define_bool_to_lisp_obj ();
define_setcar_setcdr ();
@@ -4613,12 +4890,12 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
struct Lisp_Hash_Table *func_h =
XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt));
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
- if (!EQ (HASH_VALUE (func_h, i), Qunbound))
+ if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound))
declare_function (HASH_VALUE (func_h, i));
/* Compile all functions. Can't be done before because the
relocation structs has to be already defined. */
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
- if (!EQ (HASH_VALUE (func_h, i), Qunbound))
+ if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound))
compile_function (HASH_VALUE (func_h, i));
/* Work around bug#46495 (GCC PR99126). */
@@ -4692,12 +4969,11 @@ unknown (before GCC version 10). */)
/******************************************************************************/
/* Helper functions called from the run-time. */
-/* These can't be statics till shared mechanism is used to solve relocations. */
/* Note: this are all potentially definable directly to gcc and are here just */
/* for laziness. Change this if a performance impact is measured. */
/******************************************************************************/
-void
+static void
helper_unwind_protect (Lisp_Object handler)
{
/* Support for a function here is new in 24.4. */
@@ -4705,28 +4981,20 @@ helper_unwind_protect (Lisp_Object handler)
handler);
}
-Lisp_Object
-helper_temp_output_buffer_setup (Lisp_Object x)
-{
- CHECK_STRING (x);
- temp_output_buffer_setup (SSDATA (x));
- return Vstandard_output;
-}
-
-Lisp_Object
+static Lisp_Object
helper_unbind_n (Lisp_Object n)
{
- return unbind_to (SPECPDL_INDEX () - XFIXNUM (n), Qnil);
+ return unbind_to (specpdl_ref_add (SPECPDL_INDEX (), -XFIXNUM (n)), Qnil);
}
-void
+static void
helper_save_restriction (void)
{
record_unwind_protect (save_restriction_restore,
save_restriction_save ());
}
-bool
+static bool
helper_PSEUDOVECTOR_TYPEP_XUNTAG (Lisp_Object a, enum pvec_type code)
{
return PSEUDOVECTOR_TYPEP (XUNTAG (a, Lisp_Vectorlike,
@@ -4734,6 +5002,14 @@ helper_PSEUDOVECTOR_TYPEP_XUNTAG (Lisp_Object a, enum pvec_type code)
code);
}
+static struct Lisp_Symbol_With_Pos *
+helper_GET_SYMBOL_WITH_POSITION (Lisp_Object a)
+{
+ if (!SYMBOL_WITH_POS_P (a))
+ wrong_type_argument (Qwrong_type_argument, a);
+ return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Symbol_With_Pos);
+}
+
/* `native-comp-eln-load-path' clean-up support code. */
@@ -4745,6 +5021,12 @@ return_nil (Lisp_Object arg)
{
return Qnil;
}
+
+static Lisp_Object
+directory_files_matching (Lisp_Object name, Lisp_Object match)
+{
+ return Fdirectory_files (name, Qt, match, Qnil, Qnil);
+}
#endif
/* Windows does not let us delete a .eln file that is currently loaded
@@ -4762,11 +5044,11 @@ eln_load_path_final_clean_up (void)
FOR_EACH_TAIL (dir_tail)
{
Lisp_Object files_in_dir =
- internal_condition_case_5 (Fdirectory_files,
+ internal_condition_case_2 (directory_files_matching,
Fexpand_file_name (Vcomp_native_version_dir,
XCAR (dir_tail)),
- Qt, build_string ("\\.eln\\.old\\'"), Qnil,
- Qnil, Qt, return_nil);
+ build_string ("\\.eln\\.old\\'"),
+ Qt, return_nil);
FOR_EACH_TAIL (files_in_dir)
internal_delete_file (XCAR (files_in_dir));
}
@@ -4840,13 +5122,14 @@ maybe_defer_native_compilation (Lisp_Object function_name,
return;
}
+ Fputhash (function_name, definition, Vcomp_deferred_pending_h);
+
/* This is so deferred compilation is able to compile comp
dependencies breaking circularity. */
- if (comp__loadable)
+ if (comp__compilable)
{
/* Startup is done, comp is usable. */
- Frequire (Qcomp, Qnil, Qnil);
- Fputhash (function_name, definition, Vcomp_deferred_pending_h);
+ CALL0I (startup--require-comp-safely);
CALLN (Ffuncall, intern_c_string ("native--compile-async"),
src, Qnil, Qlate);
}
@@ -4982,7 +5265,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
identify is we have at least another load active on it. */
bool recursive_load = comp_u->load_ongoing;
comp_u->load_ongoing = true;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (!recursive_load)
record_unwind_protect (unset_cu_load_ongoing, comp_u_lisp_obj);
@@ -5000,12 +5283,15 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
{
struct thread_state ***current_thread_reloc =
dynlib_sym (handle, CURRENT_THREAD_RELOC_SYM);
+ bool **f_symbols_with_pos_enabled_reloc =
+ dynlib_sym (handle, F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM);
void **pure_reloc = dynlib_sym (handle, PURE_RELOC_SYM);
Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM);
Lisp_Object *data_imp_relocs = comp_u->data_imp_relocs;
void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM);
if (!(current_thread_reloc
+ && f_symbols_with_pos_enabled_reloc
&& pure_reloc
&& data_relocs
&& data_imp_relocs
@@ -5017,6 +5303,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file);
*current_thread_reloc = &current_thread;
+ *f_symbols_with_pos_enabled_reloc = &symbols_with_pos_enabled;
*pure_reloc = pure;
/* Imported functions. */
@@ -5055,7 +5342,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
are necessary exclusively during the first load. Once these
are collected we don't have to maintain them in the heap
forever. */
- Lisp_Object volatile data_ephemeral_vec;
+ Lisp_Object volatile data_ephemeral_vec = Qnil;
/* In case another load of the same CU is active on the stack
all ephemeral data is hold by that frame. Re-writing
'data_ephemeral_vec' would be not only a waste of cycles but
@@ -5119,7 +5406,7 @@ native_function_doc (Lisp_Object function)
static Lisp_Object
make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
Lisp_Object c_name, Lisp_Object type, Lisp_Object doc_idx,
- Lisp_Object intspec, Lisp_Object comp_u)
+ Lisp_Object intspec, Lisp_Object command_modes, Lisp_Object comp_u)
{
struct Lisp_Native_Comp_Unit *cu = XNATIVE_COMP_UNIT (comp_u);
dynlib_handle_ptr handle = cu->handle;
@@ -5152,7 +5439,8 @@ make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
x->s.min_args = XFIXNUM (minarg);
x->s.max_args = FIXNUMP (maxarg) ? XFIXNUM (maxarg) : MANY;
x->s.symbol_name = xstrdup (SSDATA (symbol_name));
- x->s.native_intspec = intspec;
+ x->s.intspec.native = intspec;
+ x->s.command_modes = command_modes;
x->s.doc = XFIXNUM (doc_idx);
#ifdef HAVE_NATIVE_COMP
x->s.native_comp_u = comp_u;
@@ -5175,12 +5463,15 @@ This gets called by top_level_run during the load phase. */)
{
Lisp_Object doc_idx = FIRST (rest);
Lisp_Object intspec = SECOND (rest);
+ Lisp_Object command_modes = THIRD (rest);
+
struct Lisp_Native_Comp_Unit *cu = XNATIVE_COMP_UNIT (comp_u);
if (cu->loaded_once)
return Qnil;
Lisp_Object tem =
- make_subr (c_name, minarg, maxarg, c_name, type, doc_idx, intspec, comp_u);
+ make_subr (c_name, minarg, maxarg, c_name, type, doc_idx, intspec,
+ command_modes, comp_u);
/* We must protect it against GC because the function is not
reachable through symbols. */
@@ -5205,23 +5496,13 @@ This gets called by top_level_run during the load phase. */)
{
Lisp_Object doc_idx = FIRST (rest);
Lisp_Object intspec = SECOND (rest);
+ Lisp_Object command_modes = THIRD (rest);
+
Lisp_Object tem =
make_subr (SYMBOL_NAME (name), minarg, maxarg, c_name, type, doc_idx,
- intspec, comp_u);
-
- if (AUTOLOADP (XSYMBOL (name)->u.s.function))
- /* Remember that the function was already an autoload. */
- LOADHIST_ATTACH (Fcons (Qt, name));
- LOADHIST_ATTACH (Fcons (Qdefun, name));
-
- { /* Handle automatic advice activation (bug#42038).
- See `defalias'. */
- Lisp_Object hook = Fget (name, Qdefalias_fset_function);
- if (!NILP (hook))
- call2 (hook, name, tem);
- else
- Ffset (name, tem);
- }
+ intspec, command_modes, comp_u);
+
+ defalias (name, tem);
return tem;
}
@@ -5321,9 +5602,9 @@ syms_of_comp (void)
DEFVAR_LISP ("comp--delayed-sources", Vcomp__delayed_sources,
doc: /* List of sources to be native-compiled when startup is finished.
For internal use. */);
- DEFVAR_BOOL ("comp--loadable",
- comp__loadable,
- doc: /* Non-nil when comp.el can be loaded.
+ DEFVAR_BOOL ("comp--compilable",
+ comp__compilable,
+ doc: /* Non-nil when comp.el can be native compiled.
For internal use. */);
/* Compiler control customizes. */
DEFVAR_BOOL ("native-comp-deferred-compilation",
@@ -5386,6 +5667,7 @@ compiled one. */);
DEFSYM (Qnumberp, "numberp");
DEFSYM (Qintegerp, "integerp");
DEFSYM (Qcomp_maybe_gc_or_quit, "comp-maybe-gc-or-quit");
+ DEFSYM (Qsymbol_with_pos_p, "symbol-with-pos-p");
/* Allocation classes. */
DEFSYM (Qd_default, "d-default");
@@ -5499,7 +5781,7 @@ For internal use. */);
DEFVAR_LISP ("native-comp-eln-load-path", Vnative_comp_eln_load_path,
doc: /* List of eln cache directories.
-If a directory is non absolute is assumed to be relative to
+If a directory is non absolute it is assumed to be relative to
`invocation-directory'.
`comp-native-version-dir' value is used as a sub-folder name inside
each eln cache directory.
@@ -5536,3 +5818,6 @@ be preloaded. */);
defsubr (&Snative_comp_available_p);
}
+/* Local Variables: */
+/* c-file-offsets: ((arglist-intro . +)) */
+/* End: */
diff --git a/src/comp.h b/src/comp.h
index 40f1e9b979c..da53f32971e 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -53,6 +53,8 @@ struct Lisp_Native_Comp_Unit
#ifdef HAVE_NATIVE_COMP
+INLINE_HEADER_BEGIN
+
INLINE bool
NATIVE_COMP_UNITP (Lisp_Object a)
{
@@ -99,6 +101,8 @@ void unload_comp_unit (struct Lisp_Native_Comp_Unit *cu)
extern void syms_of_comp (void);
+INLINE_HEADER_END
+
#endif /* #ifdef HAVE_NATIVE_COMP */
#endif /* #ifndef COMP_H */
diff --git a/src/composite.c b/src/composite.c
index 711284ba6fc..1596e996d6c 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -575,7 +575,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
}
if (min_pos < max_pos)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
@@ -688,7 +688,7 @@ composition_gstring_cache_clear_font (Lisp_Object font_object)
{
Lisp_Object k = HASH_KEY (h, i);
- if (!EQ (k, Qunbound))
+ if (!BASE_EQ (k, Qunbound))
{
Lisp_Object gstring = HASH_VALUE (h, i);
@@ -704,8 +704,8 @@ DEFUN ("clear-composition-cache", Fclear_composition_cache,
Clear composition cache. */)
(void)
{
- Lisp_Object args[] = {QCtest, Qequal, QCsize, make_fixnum (311)};
- gstring_hash_table = CALLMANY (Fmake_hash_table, args);
+ gstring_hash_table = CALLN (Fmake_hash_table, QCtest, Qequal,
+ QCsize, make_fixnum (311));
/* Fixme: We call Fclear_face_cache to force complete re-building of
display glyphs. But, it may be better to call this function from
Fclear_face_cache instead. */
@@ -892,7 +892,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
ptrdiff_t limit, struct window *win, struct face *face,
Lisp_Object string, Lisp_Object direction, int ch)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object pos = make_fixnum (charpos);
ptrdiff_t to;
ptrdiff_t pt = PT, pt_byte = PT_BYTE;
@@ -988,7 +988,9 @@ inhibit_auto_composition (void)
less than CHARPOS, search backward to ENDPOS+1 assuming that
set_iterator_to_next works in reverse order. In this case, if a
composition closest to CHARPOS is found, set cmp_it->stop_pos to
- the last character of the composition.
+ the last character of the composition. STRING, if non-nil, is
+ the string (as opposed to a buffer) whose characters should be
+ tested for being composable.
If no composition is found, set cmp_it->ch to -2. If a static
composition is found, set cmp_it->ch to -1. Otherwise, set
@@ -996,7 +998,9 @@ inhibit_auto_composition (void)
composition. */
void
-composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t endpos, Lisp_Object string)
+composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
+ ptrdiff_t bytepos, ptrdiff_t endpos,
+ Lisp_Object string)
{
ptrdiff_t start, end;
int c;
@@ -1035,7 +1039,9 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
cmp_it->stop_pos = endpos = start;
cmp_it->ch = -1;
}
- if (NILP (BVAR (current_buffer, enable_multibyte_characters))
+ if ((NILP (string)
+ && NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ || (STRINGP (string) && !STRING_MULTIBYTE (string))
|| inhibit_auto_composition ())
return;
if (bytepos < 0)
@@ -1292,6 +1298,16 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos,
if (cmp_it->lookback > 0)
{
cpos = charpos - cmp_it->lookback;
+ /* Reject the composition if it starts before ENDPOS,
+ which here can only happen if
+ composition-break-at-point is non-nil and point is
+ inside the composition. */
+ if (cpos < endpos)
+ {
+ eassert (composition_break_at_point);
+ eassert (endpos == PT);
+ goto no_composition;
+ }
if (STRINGP (string))
bpos = string_char_to_byte (string, cpos);
else
@@ -1497,10 +1513,11 @@ struct position_record
/* Similar to find_composition, but find an automatic composition instead.
This function looks for automatic composition at or near position
- POS of OBJECT (a buffer or a string). OBJECT defaults to the
- current buffer. It must be assured that POS is not within a static
- composition. Also, the current buffer must be displayed in some
- window, otherwise the function will return FALSE.
+ POS of STRING object, either a buffer or a Lisp string. If STRING
+ is nil, it defaults to the current buffer. It must be assured that
+ POS is not within a static composition. Also, the current buffer
+ must be displayed in some window, otherwise the function will
+ return FALSE.
If LIMIT is negative, and there's no composition that includes POS
(i.e. starts at or before POS and ends at or after POS), return
@@ -1509,8 +1526,8 @@ struct position_record
MAX_AUTO_COMPOSITION_LOOKBACK, the maximum number of look-back for
automatic compositions (3) -- this is a limitation imposed by
composition rules in composition-function-table, which see. If
- BACKLIM is negative, it stands for the beginning of OBJECT: BEGV
- for a buffer or position zero for a string.
+ BACKLIM is negative, it stands for the beginning of STRING object:
+ BEGV for a buffer or position zero for a string.
If LIMIT is positive, search for a composition forward (LIMIT >
POS) or backward (LIMIT < POS). In this case, LIMIT bounds the
@@ -1519,18 +1536,21 @@ struct position_record
function can find a composition that starts after POS.
BACKLIM limits how far back is the function allowed to look in
- OBJECT while trying to find a position where it is safe to start
- searching forward for compositions. Such a safe place is generally
- the position after a character that can never be composed.
+ STRING object while trying to find a position where it is safe to
+ start searching forward for compositions. Such a safe place is
+ generally the position after a character that can never be
+ composed.
If BACKLIM is negative, that means the first character position of
- OBJECT; this is useful when calling the function for the first time
- for a given buffer or string, since it is possible that a
- composition begins before POS. However, if POS is very far from
- the beginning of OBJECT, a negative value of BACKLIM could make the
- function slow. Also, in this case the function may return START
- and END that do not include POS, something that is not necessarily
- wanted, and needs to be explicitly checked by the caller.
+ STRING object; this is useful when calling the function for the
+ first time for a given buffer or string, since it is possible that
+ a composition begins before POS. However, if POS is very far from
+ the beginning of STRING object, a negative value of BACKLIM could
+ make the function slow. For that reason, when STRING is a buffer
+ or nil, we restrict the search back to the first newline before
+ POS. Also, in this case the function may return START and END that
+ do not include POS, something that is not necessarily wanted, and
+ needs to be explicitly checked by the caller.
When calling the function in a loop for the same buffer/string, the
caller should generally set BACKLIM equal to POS, to avoid costly
@@ -1569,7 +1589,15 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
cur.pos = pos;
if (NILP (string))
{
- head = backlim < 0 ? BEGV : backlim, tail = ZV, stop = GPT;
+ if (backlim < 0)
+ {
+ /* This assumes a newline can never be composed. */
+ head = find_newline (pos, -1, 0, -1, -1, NULL, NULL, false) + 1;
+ }
+ else
+ head = backlim;
+ tail = ZV;
+ stop = GPT;
cur.pos_byte = CHAR_TO_BYTE (cur.pos);
cur.p = BYTE_POS_ADDR (cur.pos_byte);
}
@@ -1855,7 +1883,8 @@ should be ignored. */)
else
{
CHECK_STRING (string);
- validate_subarray (string, from, to, SCHARS (string), &frompos, &topos);
+ ptrdiff_t chars = SCHARS (string);
+ validate_subarray (string, from, to, chars, &frompos, &topos);
if (! STRING_MULTIBYTE (string))
{
ptrdiff_t i;
@@ -1865,9 +1894,10 @@ should be ignored. */)
error ("Attempt to shape unibyte text");
/* STRING is a pure-ASCII string, so we can convert it (or,
rather, its copy) to multibyte and use that thereafter. */
- Lisp_Object string_copy = Fconcat (1, &string);
- STRING_SET_MULTIBYTE (string_copy);
- string = string_copy;
+ /* FIXME: Not clear why we need to do that: AFAICT the rest of
+ the code should work on an ASCII-only unibyte string just
+ as well (bug#56347). */
+ string = make_multibyte_string (SSDATA (string), chars, chars);
}
frombyte = string_char_to_byte (string, frompos);
}
@@ -1961,7 +1991,9 @@ See `find-composition' for more details. */)
if (!find_composition (from, to, &start, &end, &prop, string))
{
- if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
+ if (((NILP (string)
+ && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ || (!NILP (string) && STRING_MULTIBYTE (string)))
&& ! inhibit_auto_composition ()
&& find_automatic_composition (from, to, (ptrdiff_t) -1,
&start, &end, &gstring, string))
@@ -2064,7 +2096,8 @@ The default value is the function `compose-chars-after'. */);
Use the command `auto-composition-mode' to change this variable.
If this variable is a string, `auto-composition-mode' will be disabled in
-buffers displayed on a terminal whose type compares equal to this string. */);
+buffers displayed on a terminal whose type, as reported by `tty-type',
+compares equal to that string. */);
Vauto_composition_mode = Qt;
DEFVAR_LISP ("auto-composition-function", Vauto_composition_function,
diff --git a/src/conf_post.h b/src/conf_post.h
index 6db76a2dfad..6ecebf36ab9 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -32,13 +32,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* To help make dependencies clearer elsewhere, this file typically
does not #include other files. The exceptions are stdbool.h
because it is unlikely to interfere with configuration and bool is
- such a core part of the C language, attribute.h because its
- ATTRIBUTE_* macros are used here, and ms-w32.h (DOS_NT
+ such a core part of the C language, and ms-w32.h (DOS_NT
only) because it historically was included here and changing that
would take some work. */
#include <stdbool.h>
-#include <attribute.h>
#if defined WINDOWSNT && !defined DEFER_MS_W32_H
# include <ms-w32.h>
@@ -182,6 +180,26 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
# define SIZE_MAX 4294967295U
#endif
+/* Things that lib/reg* wants. */
+
+#define mbrtowc(pwc, s, n, ps) mbtowc ((pwc), (s), (n))
+#define wcrtomb(s, wc, ps) wctomb ((s), (wc))
+#define btowc(b) ((wchar_t) (b))
+#define towupper(chr) toupper (chr)
+#define towlower(chr) tolower (chr)
+#define iswalnum(chr) isalnum (chr)
+#define wctype(name) ((wctype_t) 0)
+#define iswctype(wc, type) false
+#define mbsinit(ps) 1
+
+/* Some things that lib/at-func.c wants. */
+#define GNULIB_SUPPORT_ONLY_AT_FDCWD
+
+/* Needed by lib/lchmod.c. */
+#define EOPNOTSUPP EINVAL
+
+#define MALLOC_0_IS_NONNULL 1
+
/* We must intercept 'opendir' calls to stash away the directory name,
so we could reuse it in readlinkat; see msdos.c. */
#define opendir sys_opendir
@@ -249,7 +267,7 @@ extern void _DebPrint (const char *fmt, ...);
/* Tell regex.c to use a type compatible with Emacs. */
#define RE_TRANSLATE_TYPE Lisp_Object
#define RE_TRANSLATE(TBL, C) char_table_translate (TBL, C)
-#define RE_TRANSLATE_P(TBL) (!EQ (TBL, make_fixnum (0)))
+#define RE_TRANSLATE_P(TBL) (!BASE_EQ (TBL, make_fixnum (0)))
#endif
/* Tell time_rz.c to use Emacs's getter and setter for TZ.
@@ -259,8 +277,8 @@ extern void _DebPrint (const char *fmt, ...);
extern char *emacs_getenv_TZ (void);
extern int emacs_setenv_TZ (char const *);
-#define NO_INLINE ATTRIBUTE_NOINLINE
-#define EXTERNALLY_VISIBLE ATTRIBUTE_EXTERNALLY_VISIBLE
+#define NO_INLINE _GL_ATTRIBUTE_NOINLINE
+#define EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
#if GNUC_PREREQ (4, 4, 0) && defined __GLIBC_MINOR__
# define PRINTF_ARCHETYPE __gnu_printf__
@@ -290,9 +308,9 @@ extern int emacs_setenv_TZ (char const *);
# define PRINTF_ARCHETYPE __printf__
#endif
#define ATTRIBUTE_FORMAT_PRINTF(string_index, first_to_check) \
- ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check))
+ _GL_ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check))
-#define ARG_NONNULL ATTRIBUTE_NONNULL
+#define ARG_NONNULL _GL_ATTRIBUTE_NONNULL
/* Declare NAME to be a pointer to an object of type TYPE, initialized
to the address ADDR, which may be of a different type. Accesses
@@ -300,15 +318,16 @@ extern int emacs_setenv_TZ (char const *);
behavior, even if options like gcc -fstrict-aliasing are used. */
#define DECLARE_POINTER_ALIAS(name, type, addr) \
- type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
+ type _GL_ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
#if 3 <= __GNUC__
# define ATTRIBUTE_SECTION(name) __attribute__((section (name)))
#else
-#define ATTRIBUTE_SECTION(name)
+# define ATTRIBUTE_SECTION(name)
#endif
-#define ATTRIBUTE_MALLOC_SIZE(args) ATTRIBUTE_MALLOC ATTRIBUTE_ALLOC_SIZE (args)
+#define ATTRIBUTE_MALLOC_SIZE(args) \
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE (args)
/* Work around GCC bug 59600: when a function is inlined, the inlined
code may have its addresses sanitized even if the function has the
@@ -353,6 +372,19 @@ extern int emacs_setenv_TZ (char const *);
# define vfork fork
#endif
+/* vfork is deprecated on at least macOS 11.6 and later, but it still works
+ and is faster than fork, so silence the warning as if we knew what we
+ are doing. */
+#ifdef DARWIN_OS
+#define VFORK() \
+ (_Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
+ vfork () \
+ _Pragma("clang diagnostic pop"))
+#else
+#define VFORK() vfork ()
+#endif
+
#if ! (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__)
# undef PROFILING
#endif
diff --git a/src/cygw32.c b/src/cygw32.c
index 1b43de2c05e..759d9af94de 100644
--- a/src/cygw32.c
+++ b/src/cygw32.c
@@ -56,7 +56,7 @@ conv_filename_to_w32_unicode (Lisp_Object in, int absolute_p)
ssize_t converted_len;
Lisp_Object converted;
unsigned flags;
- int count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
chdir_to_default_directory ();
@@ -85,7 +85,7 @@ conv_filename_from_w32_unicode (const wchar_t* in, int absolute_p)
ssize_t converted_len;
Lisp_Object converted;
unsigned flags;
- int count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
chdir_to_default_directory ();
@@ -115,7 +115,7 @@ For the reverse operation, see `cygwin-convert-file-name-from-windows'. */)
(Lisp_Object file, Lisp_Object absolute_p)
{
return from_unicode (
- conv_filename_to_w32_unicode (file, EQ (absolute_p, Qnil) ? 0 : 1));
+ conv_filename_to_w32_unicode (file, NILP (absolute_p) ? 0 : 1));
}
DEFUN ("cygwin-convert-file-name-from-windows",
@@ -128,7 +128,7 @@ For the reverse operation, see `cygwin-convert-file-name-to-windows'. */)
(Lisp_Object file, Lisp_Object absolute_p)
{
return conv_filename_from_w32_unicode (to_unicode (file, &file),
- EQ (absolute_p, Qnil) ? 0 : 1);
+ NILP (absolute_p) ? 0 : 1);
}
void
diff --git a/src/data.c b/src/data.c
index 5d0790692b7..568349ba839 100644
--- a/src/data.c
+++ b/src/data.c
@@ -211,11 +211,13 @@ for example, (type-of 1) returns `integer'. */)
return Qcons;
case Lisp_Vectorlike:
+ /* WARNING!! Keep 'cl--typeof-types' in sync with this code!! */
switch (PSEUDOVECTOR_TYPE (XVECTOR (object)))
{
case PVEC_NORMAL_VECTOR: return Qvector;
case PVEC_BIGNUM: return Qinteger;
case PVEC_MARKER: return Qmarker;
+ case PVEC_SYMBOL_WITH_POS: return Qsymbol_with_pos;
case PVEC_OVERLAY: return Qoverlay;
case PVEC_FINALIZER: return Qfinalizer;
case PVEC_USER_PTR: return Quser_ptr;
@@ -318,6 +320,26 @@ DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0,
return Qt;
}
+DEFUN ("bare-symbol-p", Fbare_symbol_p, Sbare_symbol_p, 1, 1, 0,
+ doc: /* Return t if OBJECT is a symbol, but not a symbol together with position. */
+ attributes: const)
+ (Lisp_Object object)
+{
+ if (BARE_SYMBOL_P (object))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("symbol-with-pos-p", Fsymbol_with_pos_p, Ssymbol_with_pos_p, 1, 1, 0,
+ doc: /* Return t if OBJECT is a symbol together with position. */
+ attributes: const)
+ (Lisp_Object object)
+{
+ if (SYMBOL_WITH_POS_P (object))
+ return Qt;
+ return Qnil;
+}
+
DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0,
doc: /* Return t if OBJECT is a symbol. */
attributes: const)
@@ -677,7 +699,7 @@ global value outside of any lexical scope. */)
default: emacs_abort ();
}
- return (EQ (valcontents, Qunbound) ? Qnil : Qt);
+ return (BASE_EQ (valcontents, Qunbound) ? Qnil : Qt);
}
/* It has been previously suggested to make this function an alias for
@@ -755,11 +777,66 @@ DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0,
return name;
}
+DEFUN ("bare-symbol", Fbare_symbol, Sbare_symbol, 1, 1, 0,
+ doc: /* Extract, if need be, the bare symbol from SYM, a symbol. */)
+ (register Lisp_Object sym)
+{
+ if (BARE_SYMBOL_P (sym))
+ return sym;
+ /* Type checking is done in the following macro. */
+ return SYMBOL_WITH_POS_SYM (sym);
+}
+
+DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0,
+ doc: /* Extract the position from a symbol with position. */)
+ (register Lisp_Object ls)
+{
+ /* Type checking is done in the following macro. */
+ return SYMBOL_WITH_POS_POS (ls);
+}
+
+DEFUN ("remove-pos-from-symbol", Fremove_pos_from_symbol,
+ Sremove_pos_from_symbol, 1, 1, 0,
+ doc: /* If ARG is a symbol with position, return it without the position.
+Otherwise, return ARG unchanged. Compare with `bare-symbol'. */)
+ (register Lisp_Object arg)
+{
+ if (SYMBOL_WITH_POS_P (arg))
+ return (SYMBOL_WITH_POS_SYM (arg));
+ return arg;
+}
+
+DEFUN ("position-symbol", Fposition_symbol, Sposition_symbol, 2, 2, 0,
+ doc: /* Create a new symbol with position.
+SYM is a symbol, with or without position, the symbol to position.
+POS, the position, is either a fixnum or a symbol with position from which
+the position will be taken. */)
+ (register Lisp_Object sym, register Lisp_Object pos)
+{
+ Lisp_Object bare;
+ Lisp_Object position;
+
+ if (BARE_SYMBOL_P (sym))
+ bare = sym;
+ else if (SYMBOL_WITH_POS_P (sym))
+ bare = XSYMBOL_WITH_POS (sym)->sym;
+ else
+ wrong_type_argument (Qsymbolp, sym);
+
+ if (FIXNUMP (pos))
+ position = pos;
+ else if (SYMBOL_WITH_POS_P (pos))
+ position = XSYMBOL_WITH_POS (pos)->pos;
+ else
+ wrong_type_argument (Qfixnum_or_symbol_with_pos_p, pos);
+
+ return build_symbol_with_pos (bare, position);
+}
+
DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
doc: /* Set SYMBOL's function definition to DEFINITION, and return DEFINITION. */)
(register Lisp_Object symbol, Lisp_Object definition)
{
- register Lisp_Object function;
CHECK_SYMBOL (symbol);
/* Perhaps not quite the right error signal, but seems good enough. */
if (NILP (symbol) && !NILP (definition))
@@ -767,17 +844,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
think this one little sanity check is worth its cost, but anyway. */
xsignal1 (Qsetting_constant, symbol);
- function = XSYMBOL (symbol)->u.s.function;
-
- if (!NILP (Vautoload_queue) && !NILP (function))
- Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue);
-
- if (AUTOLOADP (function))
- Fput (symbol, Qautoload, XCDR (function));
-
eassert (valid_lisp_object_p (definition));
#ifdef HAVE_NATIVE_COMP
+ register Lisp_Object function = XSYMBOL (symbol)->u.s.function;
+
if (comp_enable_subr_trampolines
&& SUBRP (function)
&& !SUBR_NATIVE_COMPILEDP (function))
@@ -789,6 +860,75 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
return definition;
}
+static void
+add_to_function_history (Lisp_Object symbol, Lisp_Object olddef)
+{
+ eassert (!NILP (olddef));
+
+ Lisp_Object past = Fget (symbol, Qfunction_history);
+ Lisp_Object file = Qnil;
+ /* FIXME: Sadly, `Vload_file_name` gives less precise information
+ (it's sometimes non-nil when it shoujld be nil). */
+ Lisp_Object tail = Vcurrent_load_list;
+ FOR_EACH_TAIL_SAFE (tail)
+ if (NILP (XCDR (tail)) && STRINGP (XCAR (tail)))
+ file = XCAR (tail);
+
+ Lisp_Object tem = plist_member (past, file);
+ if (!NILP (tem))
+ { /* New def from a file used before.
+ Overwrite the previous record associated with this file. */
+ if (EQ (tem, past))
+ /* The new def is from the same file as the last change, so
+ there's nothing to do: unloading the file should revert to
+ the status before the last change rather than before this load. */
+ return;
+ Lisp_Object pastlen = Flength (past);
+ Lisp_Object temlen = Flength (tem);
+ EMACS_INT tempos = XFIXNUM (pastlen) - XFIXNUM (temlen);
+ eassert (tempos > 1);
+ Lisp_Object prev = Fnthcdr (make_fixnum (tempos - 2), past);
+ /* Remove the previous info for this file.
+ E.g. change `hist` from (... OTHERFILE DEF3 THISFILE DEF2 ...)
+ to (... OTHERFILE DEF2). */
+ XSETCDR (prev, XCDR (tem));
+ }
+ /* Push new def from new file. */
+ Fput (symbol, Qfunction_history, Fcons (file, Fcons (olddef, past)));
+}
+
+void
+defalias (Lisp_Object symbol, Lisp_Object definition)
+{
+ {
+ bool autoload = AUTOLOADP (definition);
+ if (!will_dump_p () || !autoload)
+ { /* Only add autoload entries after dumping, because the ones before are
+ not useful and else we get loads of them from the loaddefs.el.
+ That saves us about 110KB in the pdmp file (Jan 2022). */
+ LOADHIST_ATTACH (Fcons (Qdefun, symbol));
+ }
+ }
+
+ {
+ Lisp_Object olddef = XSYMBOL (symbol)->u.s.function;
+ if (!NILP (olddef))
+ {
+ if (!NILP (Vautoload_queue))
+ Vautoload_queue = Fcons (symbol, Vautoload_queue);
+ add_to_function_history (symbol, olddef);
+ }
+ }
+
+ { /* Handle automatic advice activation. */
+ Lisp_Object hook = Fget (symbol, Qdefalias_fset_function);
+ if (!NILP (hook))
+ call2 (hook, symbol, definition);
+ else
+ Ffset (symbol, definition);
+ }
+}
+
DEFUN ("defalias", Fdefalias, Sdefalias, 2, 3, 0,
doc: /* Set SYMBOL's function definition to DEFINITION.
Associates the function with the current load file, if any.
@@ -808,26 +948,7 @@ The return value is undefined. */)
&& !KEYMAPP (definition))
definition = Fpurecopy (definition);
- {
- bool autoload = AUTOLOADP (definition);
- if (!will_dump_p () || !autoload)
- { /* Only add autoload entries after dumping, because the ones before are
- not useful and else we get loads of them from the loaddefs.el. */
-
- if (AUTOLOADP (XSYMBOL (symbol)->u.s.function))
- /* Remember that the function was already an autoload. */
- LOADHIST_ATTACH (Fcons (Qt, symbol));
- LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol));
- }
- }
-
- { /* Handle automatic advice activation. */
- Lisp_Object hook = Fget (symbol, Qdefalias_fset_function);
- if (!NILP (hook))
- call2 (hook, symbol, definition);
- else
- Ffset (symbol, definition);
- }
+ defalias (symbol, definition);
maybe_defer_native_compilation (symbol, definition);
@@ -952,6 +1073,7 @@ Value, if non-nil, is a list (interactive SPEC). */)
(Lisp_Object cmd)
{
Lisp_Object fun = indirect_function (cmd); /* Check cycles. */
+ bool genfun = false;
if (NILP (fun))
return Qnil;
@@ -970,10 +1092,10 @@ Value, if non-nil, is a list (interactive SPEC). */)
if (SUBRP (fun))
{
- if (SUBR_NATIVE_COMPILEDP (fun) && !NILP (XSUBR (fun)->native_intspec))
- return XSUBR (fun)->native_intspec;
+ if (SUBR_NATIVE_COMPILEDP (fun) && !NILP (XSUBR (fun)->intspec.native))
+ return XSUBR (fun)->intspec.native;
- const char *spec = XSUBR (fun)->intspec;
+ const char *spec = XSUBR (fun)->intspec.string;
if (spec)
return list2 (Qinteractive,
(*spec != '(') ? build_string (spec) :
@@ -984,15 +1106,17 @@ Value, if non-nil, is a list (interactive SPEC). */)
if (PVSIZE (fun) > COMPILED_INTERACTIVE)
{
Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
- if (VECTORP (form))
- /* The vector form is the new form, where the first
- element is the interactive spec, and the second is the
- command modes. */
- return list2 (Qinteractive, AREF (form, 0));
- else
- /* Old form -- just the interactive spec. */
- return list2 (Qinteractive, form);
+ /* The vector form is the new form, where the first
+ element is the interactive spec, and the second is the
+ command modes. */
+ return list2 (Qinteractive, VECTORP (form) ? AREF (form, 0) : form);
}
+ else if (PVSIZE (fun) > COMPILED_DOC_STRING)
+ {
+ Lisp_Object doc = AREF (fun, COMPILED_DOC_STRING);
+ /* An invalid "docstring" is a sign that we have an OClosure. */
+ genfun = !(NILP (doc) || VALID_DOCSTRING_P (doc));
+ }
}
#ifdef HAVE_MODULES
else if (MODULE_FUNCTIONP (fun))
@@ -1015,13 +1139,21 @@ Value, if non-nil, is a list (interactive SPEC). */)
if (EQ (funcar, Qclosure))
form = Fcdr (form);
Lisp_Object spec = Fassq (Qinteractive, form);
- if (NILP (Fcdr (Fcdr (spec))))
+ if (NILP (spec) && VALID_DOCSTRING_P (CAR_SAFE (form)))
+ /* A "docstring" is a sign that we may have an OClosure. */
+ genfun = true;
+ else if (NILP (Fcdr (Fcdr (spec))))
return spec;
else
return list2 (Qinteractive, Fcar (Fcdr (spec)));
}
}
- return Qnil;
+ if (genfun
+ /* Avoid burping during bootstrap. */
+ && !NILP (Fsymbol_function (Qoclosure_interactive_form)))
+ return call1 (Qoclosure_interactive_form, fun);
+ else
+ return Qnil;
}
DEFUN ("command-modes", Fcommand_modes, Scommand_modes, 1, 1, 0,
@@ -1047,7 +1179,11 @@ The value, if non-nil, is a list of mode name symbols. */)
fun = Fsymbol_function (fun);
}
- if (COMPILEDP (fun))
+ if (SUBRP (fun))
+ {
+ return XSUBR (fun)->command_modes;
+ }
+ else if (COMPILEDP (fun))
{
if (PVSIZE (fun) <= COMPILED_INTERACTIVE)
return Qnil;
@@ -1410,8 +1546,13 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
/* Find the value of a symbol, returning Qunbound if it's not bound.
This is helpful for code which just wants to get a variable's value
if it has one, without signaling an error.
- Note that it must not be possible to quit
- within this function. Great care is required for this. */
+
+ This function is very similar to buffer_local_value, but we have
+ two separate code paths here since find_symbol_value has to be very
+ efficient, while buffer_local_value doesn't have to be.
+
+ Note that it must not be possible to quit within this function.
+ Great care is required for this. */
Lisp_Object
find_symbol_value (Lisp_Object symbol)
@@ -1449,7 +1590,7 @@ global value outside of any lexical scope. */)
Lisp_Object val;
val = find_symbol_value (symbol);
- if (!EQ (val, Qunbound))
+ if (!BASE_EQ (val, Qunbound))
return val;
xsignal1 (Qvoid_variable, symbol);
@@ -1476,7 +1617,7 @@ void
set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
enum Set_Internal_Bind bindflag)
{
- bool voide = EQ (newval, Qunbound);
+ bool voide = BASE_EQ (newval, Qunbound);
/* If restoring in a dead buffer, do nothing. */
/* if (BUFFERP (where) && NILP (XBUFFER (where)->name))
@@ -1717,7 +1858,7 @@ notify_variable_watchers (Lisp_Object symbol,
{
symbol = Findirect_variable (symbol);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect (restore_symbol_trapped_write, symbol);
/* Avoid recursion. */
set_symbol_trapped_write (symbol, SYMBOL_UNTRAPPED_WRITE);
@@ -1803,15 +1944,15 @@ default_value (Lisp_Object symbol)
DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0,
doc: /* Return t if SYMBOL has a non-void default value.
-A variable may have a buffer-local or a `let'-bound local value. This
-function says whether the variable has a non-void value outside of the
-current context. Also see `default-value'. */)
+A variable may have a buffer-local value. This function says whether
+the variable has a non-void value outside of the current buffer
+context. Also see `default-value'. */)
(Lisp_Object symbol)
{
register Lisp_Object value;
value = default_value (symbol);
- return (EQ (value, Qunbound) ? Qnil : Qt);
+ return (BASE_EQ (value, Qunbound) ? Qnil : Qt);
}
DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0,
@@ -1822,7 +1963,7 @@ local bindings in certain buffers. */)
(Lisp_Object symbol)
{
Lisp_Object value = default_value (symbol);
- if (!EQ (value, Qunbound))
+ if (!BASE_EQ (value, Qunbound))
return value;
xsignal1 (Qvoid_variable, symbol);
@@ -2002,7 +2143,7 @@ See also `defvar-local'. */)
case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
case SYMBOL_PLAINVAL:
forwarded = 0; valcontents.value = SYMBOL_VAL (sym);
- if (EQ (valcontents.value, Qunbound))
+ if (BASE_EQ (valcontents.value, Qunbound))
valcontents.value = Qnil;
break;
case SYMBOL_LOCALIZED:
@@ -2103,7 +2244,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
/* Make sure this buffer has its own value of symbol. */
XSETSYMBOL (variable, sym); /* Update in case of aliasing. */
- tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+ tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
if (NILP (tem))
{
if (let_shadows_buffer_binding_p (sym))
@@ -2183,7 +2324,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
/* Get rid of this buffer's alist element, if any. */
XSETSYMBOL (variable, sym); /* Propagate variable indirection. */
- tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+ tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
if (!NILP (tem))
bset_local_var_alist
(current_buffer,
@@ -2194,7 +2335,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
forwarded objects won't work right. */
{
Lisp_Object buf; XSETBUFFER (buf, current_buffer);
- if (EQ (buf, blv->where))
+ if (BASE_EQ (buf, blv->where))
swap_in_global_binding (sym);
}
@@ -2224,7 +2365,7 @@ Also see `buffer-local-boundp'.*/)
case SYMBOL_PLAINVAL: return Qnil;
case SYMBOL_LOCALIZED:
{
- Lisp_Object tail, elt, tmp;
+ Lisp_Object tmp;
struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
XSETBUFFER (tmp, buf);
XSETSYMBOL (variable, sym); /* Update in case of aliasing. */
@@ -2232,13 +2373,9 @@ Also see `buffer-local-boundp'.*/)
if (EQ (blv->where, tmp)) /* The binding is already loaded. */
return blv_found (blv) ? Qt : Qnil;
else
- for (tail = BVAR (buf, local_var_alist); CONSP (tail); tail = XCDR (tail))
- {
- elt = XCAR (tail);
- if (EQ (variable, XCAR (elt)))
- return Qt;
- }
- return Qnil;
+ return NILP (assq_no_quit (variable, BVAR (buf, local_var_alist)))
+ ? Qnil
+ : Qt;
}
case SYMBOL_FORWARDED:
{
@@ -2697,6 +2834,9 @@ DEFUN ("<", Flss, Slss, 1, MANY, 0,
usage: (< NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
+ if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1]))
+ return XFIXNUM (args[0]) < XFIXNUM (args[1]) ? Qt : Qnil;
+
return arithcompare_driver (nargs, args, ARITH_LESS);
}
@@ -2705,6 +2845,9 @@ DEFUN (">", Fgtr, Sgtr, 1, MANY, 0,
usage: (> NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
+ if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1]))
+ return XFIXNUM (args[0]) > XFIXNUM (args[1]) ? Qt : Qnil;
+
return arithcompare_driver (nargs, args, ARITH_GRTR);
}
@@ -2713,6 +2856,9 @@ DEFUN ("<=", Fleq, Sleq, 1, MANY, 0,
usage: (<= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
+ if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1]))
+ return XFIXNUM (args[0]) <= XFIXNUM (args[1]) ? Qt : Qnil;
+
return arithcompare_driver (nargs, args, ARITH_LESS_OR_EQUAL);
}
@@ -2721,6 +2867,9 @@ DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0,
usage: (>= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
+ if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1]))
+ return XFIXNUM (args[0]) >= XFIXNUM (args[1]) ? Qt : Qnil;
+
return arithcompare_driver (nargs, args, ARITH_GRTR_OR_EQUAL);
}
@@ -2852,6 +3001,29 @@ cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
return val;
}
+/* Render NUMBER in decimal into BUFFER which ends right before END.
+ Return the start of the string; the end is always at END.
+ The string is not null-terminated. */
+char *
+fixnum_to_string (EMACS_INT number, char *buffer, char *end)
+{
+ EMACS_INT x = number;
+ bool negative = x < 0;
+ if (negative)
+ x = -x;
+ char *p = end;
+ do
+ {
+ eassume (p > buffer && p - 1 < end);
+ *--p = '0' + x % 10;
+ x /= 10;
+ }
+ while (x);
+ if (negative)
+ *--p = '-';
+ return p;
+}
+
DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,
doc: /* Return the decimal representation of NUMBER as a string.
Uses a minus sign if negative.
@@ -2859,19 +3031,22 @@ NUMBER may be an integer or a floating point number. */)
(Lisp_Object number)
{
char buffer[max (FLOAT_TO_STRING_BUFSIZE, INT_BUFSIZE_BOUND (EMACS_INT))];
- int len;
- CHECK_NUMBER (number);
+ if (FIXNUMP (number))
+ {
+ char *end = buffer + sizeof buffer;
+ char *p = fixnum_to_string (XFIXNUM (number), buffer, end);
+ return make_unibyte_string (p, end - p);
+ }
if (BIGNUMP (number))
return bignum_to_string (number, 10);
if (FLOATP (number))
- len = float_to_string (buffer, XFLOAT_DATA (number));
- else
- len = sprintf (buffer, "%"pI"d", XFIXNUM (number));
+ return make_unibyte_string (buffer,
+ float_to_string (buffer, XFLOAT_DATA (number)));
- return make_unibyte_string (buffer, len);
+ wrong_type_argument (Qnumberp, number);
}
DEFUN ("string-to-number", Fstring_to_number, Sstring_to_number, 1, 2, 0,
@@ -3352,7 +3527,7 @@ In this case, the sign bit is duplicated. */)
if (! FIXNUMP (count))
{
- if (EQ (value, make_fixnum (0)))
+ if (BASE_EQ (value, make_fixnum (0)))
return value;
if (mpz_sgn (*xbignum_val (count)) < 0)
{
@@ -3397,11 +3572,11 @@ Lisp_Object
expt_integer (Lisp_Object x, Lisp_Object y)
{
/* Special cases for -1 <= x <= 1, which never overflow. */
- if (EQ (x, make_fixnum (1)))
+ if (BASE_EQ (x, make_fixnum (1)))
return x;
- if (EQ (x, make_fixnum (0)))
- return EQ (x, y) ? make_fixnum (1) : x;
- if (EQ (x, make_fixnum (-1)))
+ if (BASE_EQ (x, make_fixnum (0)))
+ return BASE_EQ (x, y) ? make_fixnum (1) : x;
+ if (BASE_EQ (x, make_fixnum (-1)))
return ((FIXNUMP (y) ? XFIXNUM (y) & 1 : mpz_odd_p (*xbignum_val (y)))
? x : make_fixnum (1));
@@ -3896,7 +4071,7 @@ A is a bool vector, B is t or nil, and I is an index into A. */)
void
syms_of_data (void)
{
- Lisp_Object error_tail, arith_tail;
+ Lisp_Object error_tail, arith_tail, recursion_tail;
DEFSYM (Qquote, "quote");
DEFSYM (Qlambda, "lambda");
@@ -3931,8 +4106,14 @@ syms_of_data (void)
DEFSYM (Qmark_inactive, "mark-inactive");
DEFSYM (Qinhibited_interaction, "inhibited-interaction");
+ DEFSYM (Qrecursion_error, "recursion-error");
+ DEFSYM (Qexcessive_variable_binding, "excessive-variable-binding");
+ DEFSYM (Qexcessive_lisp_nesting, "excessive-lisp-nesting");
+
DEFSYM (Qlistp, "listp");
DEFSYM (Qconsp, "consp");
+ DEFSYM (Qbare_symbol_p, "bare-symbol-p");
+ DEFSYM (Qsymbol_with_pos_p, "symbol-with-pos-p");
DEFSYM (Qsymbolp, "symbolp");
DEFSYM (Qfixnump, "fixnump");
DEFSYM (Qintegerp, "integerp");
@@ -3958,6 +4139,8 @@ syms_of_data (void)
DEFSYM (Qchar_table_p, "char-table-p");
DEFSYM (Qvector_or_char_table_p, "vector-or-char-table-p");
+ DEFSYM (Qfixnum_or_symbol_with_pos_p, "fixnum-or-symbol-with-pos-p");
+ DEFSYM (Qoclosure_interactive_form, "oclosure-interactive-form");
DEFSYM (Qsubrp, "subrp");
DEFSYM (Qunevalled, "unevalled");
@@ -4036,12 +4219,23 @@ syms_of_data (void)
PUT_ERROR (Qunderflow_error, Fcons (Qrange_error, arith_tail),
"Arithmetic underflow error");
+ recursion_tail = pure_cons (Qrecursion_error, error_tail);
+ Fput (Qrecursion_error, Qerror_conditions, recursion_tail);
+ Fput (Qrecursion_error, Qerror_message, build_pure_c_string
+ ("Excessive recursive calling error"));
+
+ PUT_ERROR (Qexcessive_variable_binding, recursion_tail,
+ "Variable binding depth exceeds max-specpdl-size");
+ PUT_ERROR (Qexcessive_lisp_nesting, recursion_tail,
+ "Lisp nesting exceeds `max-lisp-eval-depth'");
+
/* Types that type-of returns. */
DEFSYM (Qinteger, "integer");
DEFSYM (Qsymbol, "symbol");
DEFSYM (Qstring, "string");
DEFSYM (Qcons, "cons");
DEFSYM (Qmarker, "marker");
+ DEFSYM (Qsymbol_with_pos, "symbol-with-pos");
DEFSYM (Qoverlay, "overlay");
DEFSYM (Qfinalizer, "finalizer");
DEFSYM (Qmodule_function, "module-function");
@@ -4074,6 +4268,7 @@ syms_of_data (void)
DEFSYM (Qinteractive_form, "interactive-form");
DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
+ DEFSYM (Qfunction_history, "function-history");
DEFSYM (Qbyte_code_function_p, "byte-code-function-p");
@@ -4093,6 +4288,8 @@ syms_of_data (void)
defsubr (&Snumber_or_marker_p);
defsubr (&Sfloatp);
defsubr (&Snatnump);
+ defsubr (&Sbare_symbol_p);
+ defsubr (&Ssymbol_with_pos_p);
defsubr (&Ssymbolp);
defsubr (&Skeywordp);
defsubr (&Sstringp);
@@ -4123,6 +4320,10 @@ syms_of_data (void)
defsubr (&Sindirect_function);
defsubr (&Ssymbol_plist);
defsubr (&Ssymbol_name);
+ defsubr (&Sbare_symbol);
+ defsubr (&Ssymbol_with_pos_pos);
+ defsubr (&Sremove_pos_from_symbol);
+ defsubr (&Sposition_symbol);
defsubr (&Smakunbound);
defsubr (&Sfmakunbound);
defsubr (&Sboundp);
@@ -4205,6 +4406,12 @@ This variable cannot be set; trying to do so will signal an error. */);
Vmost_negative_fixnum = make_fixnum (MOST_NEGATIVE_FIXNUM);
make_symbol_constant (intern_c_string ("most-negative-fixnum"));
+ DEFSYM (Qsymbols_with_pos_enabled, "symbols-with-pos-enabled");
+ DEFVAR_BOOL ("symbols-with-pos-enabled", symbols_with_pos_enabled,
+ doc: /* Non-nil when "symbols with position" can be used as symbols.
+Bind this to non-nil in applications such as the byte compiler. */);
+ symbols_with_pos_enabled = false;
+
DEFSYM (Qwatchers, "watchers");
DEFSYM (Qmakunbound, "makunbound");
DEFSYM (Qunlet, "unlet");
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 7cfdbbe23cf..943a4aff8e7 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -1690,29 +1690,30 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
/* Loop over the registered functions. Construct an event. */
- while (!NILP (value))
+ for (; !NILP (value); value = CDR_SAFE (value))
{
key = CAR_SAFE (value);
+ Lisp_Object key_uname = CAR_SAFE (key);
/* key has the structure (UNAME SERVICE PATH HANDLER). */
- if (((uname == NULL)
- || (NILP (CAR_SAFE (key)))
- || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0))
- && ((path == NULL)
- || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
- || (strcmp (path,
- SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
- == 0))
- && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
- {
- EVENT_INIT (event);
- event.kind = DBUS_EVENT;
- event.frame_or_window = Qnil;
- /* Handler. */
- event.arg
- = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
- break;
- }
- value = CDR_SAFE (value);
+ if (uname && !NILP (key_uname)
+ && strcmp (uname, SSDATA (key_uname)) != 0)
+ continue;
+ Lisp_Object key_service_etc = CDR_SAFE (key);
+ Lisp_Object key_path_etc = CDR_SAFE (key_service_etc);
+ Lisp_Object key_path = CAR_SAFE (key_path_etc);
+ if (path && !NILP (key_path)
+ && strcmp (path, SSDATA (key_path)) != 0)
+ continue;
+ Lisp_Object handler = CAR_SAFE (CDR_SAFE (key_path_etc));
+ if (NILP (handler))
+ continue;
+
+ /* Construct an event and exit the loop. */
+ EVENT_INIT (event);
+ event.kind = DBUS_EVENT;
+ event.frame_or_window = Qnil;
+ event.arg = Fcons (handler, args);
+ break;
}
if (NILP (value))
diff --git a/src/decompress.c b/src/decompress.c
index 60f8bfd6a26..dbdc9104a37 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -67,8 +67,9 @@ init_zlib_functions (void)
#endif /* WINDOWSNT */
+#ifdef HAVE_NATIVE_COMP
-#define MD5_BLOCKSIZE 32768 /* From md5.c */
+# define MD5_BLOCKSIZE 32768 /* From md5.c */
static char acc_buff[2 * MD5_BLOCKSIZE];
static size_t acc_size;
@@ -106,7 +107,7 @@ md5_gz_stream (FILE *source, void *resblock)
unsigned char in[MD5_BLOCKSIZE];
unsigned char out[MD5_BLOCKSIZE];
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
if (!zlib_initialized)
zlib_initialized = init_zlib_functions ();
if (!zlib_initialized)
@@ -114,7 +115,7 @@ md5_gz_stream (FILE *source, void *resblock)
message1 ("zlib library not found");
return -1;
}
-#endif
+# endif
eassert (!acc_size);
@@ -164,7 +165,8 @@ md5_gz_stream (FILE *source, void *resblock)
return 0;
}
-#undef MD5_BLOCKSIZE
+# undef MD5_BLOCKSIZE
+#endif
@@ -239,7 +241,7 @@ This function can be called only in unibyte buffers. */)
z_stream stream;
int inflate_status;
struct decompress_unwind_data unwind_data;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
validate_region (&start, &end);
diff --git a/src/deps.mk b/src/deps.mk
index deffab93eca..39edd5c1dd3 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -279,7 +279,7 @@ eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h frame.h \
dispextern.h lisp.h globals.h $(config_h) coding.h composite.h xterm.h \
msdos.h
floatfns.o: floatfns.c syssignal.h lisp.h globals.h $(config_h)
-fns.o: fns.c commands.h lisp.h $(config_h) frame.h buffer.h character.h \
+fns.o: fns.c sort.c commands.h lisp.h $(config_h) frame.h buffer.h character.h \
keyboard.h keymap.h window.h $(INTERVALS_H) coding.h ../lib/md5.h \
../lib/sha1.h ../lib/sha256.h ../lib/sha512.h blockinput.h atimer.h \
systime.h xterm.h ../lib/unistd.h globals.h
diff --git a/src/dired.c b/src/dired.c
index 7fb54f2f67b..c2c099f0a5f 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -195,7 +195,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
/* Unfortunately, we can now invoke expand-file-name and
file-attributes on filenames, both of which can throw, so we must
do a proper unwind-protect. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_ptr (directory_files_internal_unwind, d);
#ifdef WINDOWSNT
@@ -219,6 +219,13 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
}
#endif
+ if (!NILP (full) && !STRING_MULTIBYTE (directory))
+ { /* We will be concatenating 'directory' with local file name.
+ We always decode local file names, so in order to safely concatenate
+ them we need 'directory' to be decoded as well (bug#56469). */
+ directory = DECODE_FILE (directory);
+ }
+
ptrdiff_t directory_nbytes = SBYTES (directory);
re_match_object = Qt;
@@ -263,9 +270,20 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
ptrdiff_t name_nbytes = SBYTES (name);
ptrdiff_t nbytes = directory_nbytes + needsep + name_nbytes;
ptrdiff_t nchars = SCHARS (directory) + needsep + SCHARS (name);
- finalname = make_uninit_multibyte_string (nchars, nbytes);
- if (nchars == nbytes)
- STRING_SET_UNIBYTE (finalname);
+ /* DECODE_FILE may return non-ASCII unibyte strings (e.g. when
+ file-name-coding-system is 'binary'), so we don't know for sure
+ that the bytes we have follow our internal utf-8 representation
+ for multibyte strings. If nchars == nbytes we don't need to
+ care and just return a unibyte string; and if not, that means
+ one of 'name' or 'directory' is multibyte, in which case we
+ presume that the other one would also be multibyte if it
+ contained non-ASCII.
+ FIXME: This last presumption is broken when 'directory' is
+ multibyte (with non-ASCII), and 'name' is unibyte with non-ASCII
+ (because file-name-coding-system is 'binary'). */
+ finalname = (nchars == nbytes)
+ ? make_uninit_string (nbytes)
+ : make_uninit_multibyte_string (nchars, nbytes);
memcpy (SDATA (finalname), SDATA (directory), directory_nbytes);
if (needsep)
SSET (finalname, directory_nbytes, DIRECTORY_SEP);
@@ -289,7 +307,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
#endif
/* Discard the unwind protect. */
- specpdl_ptr = specpdl + count;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
if (NILP (nosort))
list = Fsort (Fnreverse (list),
@@ -455,7 +473,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
anything. */
bool includeall = 1;
bool check_decoded = false;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
elt = Qnil;
@@ -482,8 +500,8 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
decoded names in order to filter false positives, such as "a"
falsely matching "a-ring". */
if (!NILP (file_encoding)
- && !NILP (Fplist_get (Fcoding_system_plist (file_encoding),
- Qdecomposed_characters)))
+ && !NILP (plist_get (Fcoding_system_plist (file_encoding),
+ Qdecomposed_characters)))
{
check_decoded = true;
if (STRING_MULTIBYTE (file))
@@ -521,9 +539,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
name = DECODE_FILE (name);
ptrdiff_t name_blen = SBYTES (name), name_len = SCHARS (name);
if (completion_ignore_case
- && !EQ (Fcompare_strings (name, zero, file_len, file, zero, file_len,
- Qt),
- Qt))
+ && !BASE_EQ (Fcompare_strings (name, zero, file_len, file, zero,
+ file_len, Qt),
+ Qt))
continue;
switch (dirent_type (dp))
@@ -603,10 +621,12 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
skip = name_len - elt_len;
cmp_len = make_fixnum (elt_len);
if (skip < 0
- || !EQ (Fcompare_strings (name, make_fixnum (skip),
- Qnil,
- elt, zero, cmp_len, Qt),
- Qt))
+ || !BASE_EQ (Fcompare_strings (name,
+ make_fixnum (skip),
+ Qnil,
+ elt, zero, cmp_len,
+ Qt),
+ Qt))
continue;
}
break;
@@ -637,10 +657,12 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
skip = name_len - elt_len;
cmp_len = make_fixnum (elt_len);
if (skip < 0
- || !EQ (Fcompare_strings (name, make_fixnum (skip),
- Qnil,
- elt, zero, cmp_len, Qt),
- Qt))
+ || !BASE_EQ (Fcompare_strings (name,
+ make_fixnum (skip),
+ Qnil,
+ elt, zero, cmp_len,
+ Qt),
+ Qt))
continue;
}
break;
@@ -699,7 +721,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
= Fcompare_strings (name, zero, make_fixnum (compare),
file, zero, make_fixnum (compare),
completion_ignore_case ? Qt : Qnil);
- if (!EQ (cmp, Qt))
+ if (!BASE_EQ (cmp, Qt))
continue;
}
@@ -722,7 +744,8 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
= Fcompare_strings (bestmatch, zero, make_fixnum (compare),
name, zero, make_fixnum (compare),
completion_ignore_case ? Qt : Qnil);
- ptrdiff_t matchsize = EQ (cmp, Qt) ? compare : eabs (XFIXNUM (cmp)) - 1;
+ ptrdiff_t matchsize = BASE_EQ (cmp, Qt)
+ ? compare : eabs (XFIXNUM (cmp)) - 1;
if (completion_ignore_case)
{
@@ -751,13 +774,13 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
file, zero,
Qnil,
Qnil),
- EQ (Qt, cmp))
+ BASE_EQ (Qt, cmp))
&& (cmp = Fcompare_strings (bestmatch, zero,
make_fixnum (SCHARS (file)),
file, zero,
Qnil,
Qnil),
- ! EQ (Qt, cmp))))
+ ! BASE_EQ (Qt, cmp))))
bestmatch = name;
}
bestmatchsize = matchsize;
@@ -944,7 +967,7 @@ file_attributes (int fd, char const *name,
Lisp_Object dirname, Lisp_Object filename,
Lisp_Object id_format)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct stat s;
/* An array to hold the mode string generated by filemodestring,
diff --git a/src/dispextern.h b/src/dispextern.h
index 954992a0ec2..ca7834dec55 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1075,6 +1075,9 @@ struct glyph_row
right-to-left paragraph. */
bool_bf reversed_p : 1;
+ /* Whether or not a stipple was drawn in this row at some point. */
+ bool_bf stipple_p : 1;
+
/* Continuation lines width at the start of the row. */
int continuation_lines_width;
@@ -1720,6 +1723,12 @@ struct face
int box_vertical_line_width;
int box_horizontal_line_width;
+
+ /* The amount of pixels above the descent line the underline should
+ be displayed. It does not take effect unless
+ `underline_at_descent_line_p` is t. */
+ int underline_pixels_above_descent_line;
+
/* Type of box drawn. A value of FACE_NO_BOX means no box is drawn
around text in this face. A value of FACE_SIMPLE_BOX means a box
of width box_line_width is drawn in color box_color. A value of
@@ -1753,6 +1762,9 @@ struct face
bool_bf strike_through_color_defaulted_p : 1;
bool_bf box_color_defaulted_p : 1;
+ /* True means the underline should be drawn at the descent line. */
+ bool_bf underline_at_descent_line_p : 1;
+
/* TTY appearances. Colors are found in `lface' with empty color
string meaning the default color of the TTY. */
bool_bf tty_bold_p : 1;
@@ -1844,7 +1856,6 @@ enum face_id
CHILD_FRAME_BORDER_FACE_ID,
TAB_BAR_FACE_ID,
TAB_LINE_FACE_ID,
- MODE_LINE_FACE_ID,
BASIC_FACE_ID_SENTINEL
};
@@ -2731,11 +2742,11 @@ struct it
/* The line number of point's line, or zero if not computed yet. */
ptrdiff_t pt_lnum;
- /* Number of pixels to offset tab stops due to width fixup of the
- first glyph that crosses first_visible_x. This is only needed on
- GUI frames, only when display-line-numbers is in effect, and only
- in hscrolled windows. */
- int tab_offset;
+ /* Number of pixels to adjust tab stops and stretch glyphs due to
+ width fixup of the first stretch glyph that crosses first_visible_x.
+ This is only needed on GUI frames, only when display-line-numbers
+ is in effect, and only in hscrolled windows. */
+ int stretch_adjust;
/* Left fringe bitmap number (enum fringe_bitmap_type). */
unsigned left_user_fringe_bitmap : FRINGE_ID_BITS;
@@ -3074,12 +3085,15 @@ struct image
XFORM xform;
#endif
#ifdef HAVE_HAIKU
- /* Non-zero if the image has not yet been transformed for display. */
- int have_be_transforms_p;
+ /* The affine transformation to apply to this image. */
+ double transform[3][3];
+
+ /* The original width and height of the image. */
+ int original_width, original_height;
- double be_rotate;
- double be_scale_x;
- double be_scale_y;
+ /* Whether or not bilinear filtering should be used to "smooth" the
+ image. */
+ bool use_bilinear_filtering;
#endif
/* Colors allocated for this image, if any. Allocated via xmalloc. */
@@ -3396,6 +3410,8 @@ int partial_line_height (struct it *it_origin);
bool in_display_vector_p (struct it *);
int frame_mode_line_height (struct frame *);
extern bool redisplaying_p;
+extern bool display_working_on_window_p;
+extern void unwind_display_working_on_window (void);
extern bool help_echo_showing_p;
extern Lisp_Object help_echo_string, help_echo_window;
extern Lisp_Object help_echo_object, previous_help_echo_string;
@@ -3452,11 +3468,14 @@ extern Lisp_Object handle_tab_bar_click (struct frame *,
int, int, bool, int);
extern void handle_tool_bar_click (struct frame *,
int, int, bool, int);
+extern void handle_tool_bar_click_with_device (struct frame *, int, int, bool,
+ int, Lisp_Object);
extern void expose_frame (struct frame *, int, int, int, int);
extern bool gui_intersect_rectangles (const Emacs_Rectangle *,
const Emacs_Rectangle *,
Emacs_Rectangle *);
+extern void gui_consider_frame_title (Lisp_Object);
#endif /* HAVE_WINDOW_SYSTEM */
extern void note_mouse_highlight (struct frame *, int, int);
@@ -3480,6 +3499,9 @@ bool update_window_fringes (struct window *, bool);
void gui_init_fringe (struct redisplay_interface *);
+extern int max_used_fringe_bitmap;
+void gui_define_fringe_bitmap (struct frame *, int);
+
#ifdef HAVE_NTGUI
void w32_reset_fringes (void);
#endif
@@ -3488,6 +3510,8 @@ extern unsigned row_hash (struct glyph_row *);
extern bool buffer_flipping_blocked_p (void);
+extern void update_redisplay_ticks (int, struct window *);
+
/* Defined in image.c */
#ifdef HAVE_WINDOW_SYSTEM
@@ -3599,6 +3623,9 @@ void gamma_correct (struct frame *, XColor *);
#ifdef HAVE_NTGUI
void gamma_correct (struct frame *, COLORREF *);
#endif
+#ifdef HAVE_HAIKU
+void gamma_correct (struct frame *, Emacs_Color *);
+#endif
#ifdef HAVE_WINDOW_SYSTEM
diff --git a/src/dispnew.c b/src/dispnew.c
index 178d5caffb2..53a47c4b2f2 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1837,7 +1837,18 @@ adjust_frame_glyphs (struct frame *f)
if (FRAME_WINDOW_P (f))
adjust_frame_glyphs_for_window_redisplay (f);
else
- adjust_frame_glyphs_for_frame_redisplay (f);
+ {
+ adjust_frame_glyphs_for_frame_redisplay (f);
+ eassert (FRAME_INITIAL_P (f)
+ || noninteractive
+ || !initialized
+ || (f->current_matrix
+ && f->current_matrix->nrows > 0
+ && f->current_matrix->rows
+ && f->desired_matrix
+ && f->desired_matrix->nrows > 0
+ && f->desired_matrix->rows));
+ }
/* Don't forget the buffer for decode_mode_spec. */
adjust_decode_mode_spec_buffer (f);
@@ -2119,6 +2130,19 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
SET_FRAME_GARBAGED (f);
}
}
+ else if (!FRAME_INITIAL_P (f) && !noninteractive && initialized)
+ {
+ if (!f->desired_matrix->nrows || !f->desired_matrix->rows)
+ {
+ adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
+ if (!f->current_matrix->nrows || !f->current_matrix->rows)
+ {
+ adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
+ SET_FRAME_GARBAGED (f);
+ }
+ }
}
@@ -2708,12 +2732,25 @@ set_frame_matrix_frame (struct frame *f)
operations in window matrices of frame_matrix_frame. */
static void
-make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
+make_current (struct glyph_matrix *desired_matrix,
+ struct glyph_matrix *current_matrix, int row)
{
struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
bool mouse_face_p = current_row->mouse_face_p;
+ /* If we aborted redisplay of this window, a row in the desired
+ matrix might not have its hash computed. But update_window
+ relies on each row having its correct hash, so do it here if
+ needed. */
+ if (!desired_row->hash
+ /* A glyph row that is not completely empty is unlikely to have
+ a zero hash value. */
+ && !(!desired_row->used[0]
+ && !desired_row->used[1]
+ && !desired_row->used[2]))
+ desired_row->hash = row_hash (desired_row);
+
/* Do current_row = desired_row. This exchanges glyph pointers
between both rows, and does a structure assignment otherwise. */
assign_row (current_row, desired_row);
@@ -3907,7 +3944,8 @@ update_marginal_area (struct window *w, struct glyph_row *updated_row,
Value is true if display has changed. */
static bool
-update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
+update_text_area (struct window *w, struct glyph_row *updated_row, int vpos,
+ bool *partial_p)
{
struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
@@ -3928,9 +3966,13 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
However, it causes excessive flickering when mouse is moved
across the mode line. Luckily, turning it off for the mode
line doesn't seem to hurt anything. -- cyd.
- But it is still needed for the header line. -- kfs. */
+ But it is still needed for the header line. -- kfs.
+ The header line vpos is 1 if a tab line is enabled. (18th
+ Apr 2022) */
|| (current_row->mouse_face_p
- && !(current_row->mode_line_p && vpos > 0))
+ && !(current_row->mode_line_p
+ && (vpos > (w->current_matrix->tab_line_p
+ && w->current_matrix->header_line_p))))
|| current_row->x != desired_row->x)
{
output_cursor_to (w, vpos, 0, desired_row->y, desired_row->x);
@@ -4009,6 +4051,13 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
{
x += desired_glyph->pixel_width;
++desired_glyph, ++current_glyph, ++i;
+
+ /* Say that only a partial update was performed of
+ the current row (i.e. not all the glyphs were
+ drawn). This is used to preserve the stipple_p
+ flag of the current row inside
+ update_window_line. */
+ *partial_p = true;
}
/* Consider the case that the current row contains "xxx
@@ -4080,9 +4129,15 @@ update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
rif->write_glyphs (w, updated_row, start,
TEXT_AREA, i - start_hpos);
changed_p = 1;
+ *partial_p = true;
}
}
+ /* This means we will draw from the start, so no partial update
+ is being performed. */
+ if (!i)
+ *partial_p = false;
+
/* Write the rest. */
if (i < desired_row->used[TEXT_AREA])
{
@@ -4155,7 +4210,9 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
- bool changed_p = 0;
+
+ /* partial_p is true if not all of desired_row was drawn. */
+ bool changed_p = 0, partial_p = 0, was_stipple;
/* A row can be completely invisible in case a desired matrix was
built with a vscroll and then make_cursor_line_fully_visible shifts
@@ -4179,7 +4236,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
}
/* Update the display of the text area. */
- if (update_text_area (w, desired_row, vpos))
+ if (update_text_area (w, desired_row, vpos, &partial_p))
{
changed_p = 1;
if (current_row->mouse_face_p)
@@ -4208,7 +4265,17 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
}
/* Update current_row from desired_row. */
+ was_stipple = current_row->stipple_p;
make_current (w->desired_matrix, w->current_matrix, vpos);
+
+ /* If only a partial update was performed, any stipple already
+ displayed in MATRIX_ROW (w->current_matrix, vpos) might still be
+ there, so don't hurry to clear that flag if it's not in
+ desired_row. */
+
+ if (partial_p && was_stipple)
+ current_row->stipple_p = true;
+
return changed_p;
}
@@ -4230,11 +4297,11 @@ set_window_cursor_after_update (struct window *w)
/* If we are showing a message instead of the mini-buffer,
show the cursor for the message instead. */
&& XWINDOW (minibuf_window) == w
- && EQ (minibuf_window, echo_area_window)
+ && BASE_EQ (minibuf_window, echo_area_window)
/* These cases apply only to the frame that contains
the active mini-buffer window. */
&& FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+ && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
cx = cy = vpos = hpos = 0;
@@ -4388,7 +4455,6 @@ add_row_entry (struct glyph_row *row)
return entry;
}
-
/* Try to reuse part of the current display of W by scrolling lines.
HEADER_LINE_P means W has a header line.
@@ -4434,6 +4500,14 @@ scrolling_window (struct window *w, int tab_line_p)
struct glyph_row *d = MATRIX_ROW (desired_matrix, i);
struct glyph_row *c = MATRIX_ROW (current_matrix, i);
+ /* If there is a row with a stipple currently on the glass, give
+ up. Stipples look different depending on where on the
+ display they are drawn, so scrolling the display will produce
+ incorrect results. */
+
+ if (c->stipple_p)
+ return 0;
+
if (c->enabled_p
&& d->enabled_p
&& !d->redraw_fringe_bitmaps_p
@@ -4463,6 +4537,16 @@ scrolling_window (struct window *w, int tab_line_p)
first_old = first_new = i;
+ while (i < current_matrix->nrows - 1)
+ {
+ /* If there is a stipple after the first change, give up as
+ well. */
+ if (MATRIX_ROW (current_matrix, i)->stipple_p)
+ return 0;
+
+ ++i;
+ }
+
/* Set last_new to the index + 1 of the row that reaches the
bottom boundary in the desired matrix. Give up if we find a
disabled row before we reach the bottom boundary. */
@@ -4877,13 +4961,13 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
/* If we are showing a message instead of the mini-buffer,
show the cursor for the message instead of for the
(now hidden) mini-buffer contents. */
- || (EQ (minibuf_window, selected_window)
- && EQ (minibuf_window, echo_area_window)
+ || (BASE_EQ (minibuf_window, selected_window)
+ && BASE_EQ (minibuf_window, echo_area_window)
&& !NILP (echo_area_buffer[0])))
/* These cases apply only to the frame that contains
the active mini-buffer window. */
&& FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+ && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
int col;
@@ -6176,15 +6260,13 @@ Return t if redisplay was performed, nil if redisplay was preempted
immediately by pending input. */)
(Lisp_Object force)
{
- ptrdiff_t count;
-
swallow_events (true);
if ((detect_input_pending_run_timers (1)
&& NILP (force) && !redisplay_dont_pause)
|| !NILP (Vexecuting_kbd_macro))
return Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (!NILP (force) && !redisplay_dont_pause)
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (2);
@@ -6237,7 +6319,7 @@ pass nil for VARIABLE. */)
{
if (idx == ASIZE (state))
goto changed;
- if (!EQ (AREF (state, idx++), frame))
+ if (!BASE_EQ (AREF (state, idx++), frame))
goto changed;
if (idx == ASIZE (state))
goto changed;
@@ -6252,7 +6334,7 @@ pass nil for VARIABLE. */)
continue;
if (idx == ASIZE (state))
goto changed;
- if (!EQ (AREF (state, idx++), buf))
+ if (!BASE_EQ (AREF (state, idx++), buf))
goto changed;
if (idx == ASIZE (state))
goto changed;
@@ -6662,6 +6744,8 @@ The value is a symbol:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
+ `pgtk' for an Emacs frame using pure GTK facilities.
+ `haiku' for an Emacs frame running in Haiku.
Use of this variable as a boolean is deprecated. Instead,
use `display-graphic-p' or any of the other `display-*-p'
@@ -6675,6 +6759,8 @@ The value is a symbol:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
+ `pgtk' for an Emacs frame using pure GTK facilities.
+ `haiku' for an Emacs frame running in Haiku.
Use of this variable as a boolean is deprecated. Instead,
use `display-graphic-p' or any of the other `display-*-p'
@@ -6715,6 +6801,10 @@ See `buffer-display-table' for more information. */);
beginning of the next redisplay). */
redisplay_dont_pause = true;
+ DEFVAR_LISP ("x-show-tooltip-timeout", Vx_show_tooltip_timeout,
+ doc: /* The default timeout (in seconds) for `x-show-tip'. */);
+ Vx_show_tooltip_timeout = make_fixnum (5);
+
DEFVAR_LISP ("tab-bar-position", Vtab_bar_position,
doc: /* Specify on which side from the tool bar the tab bar shall be.
Possible values are t (below the tool bar), nil (above the tool bar).
diff --git a/src/doc.c b/src/doc.c
index 0b12eb154d6..34b80d03aa9 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -83,7 +83,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
{
char *from, *to, *name, *p, *p1;
Lisp_Object file, pos;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object dir;
USE_SAFE_ALLOCA;
@@ -341,60 +341,12 @@ string is passed through `substitute-command-keys'. */)
else if (MODULE_FUNCTIONP (fun))
doc = module_function_documentation (XMODULE_FUNCTION (fun));
#endif
- else if (COMPILEDP (fun))
- {
- if (PVSIZE (fun) <= COMPILED_DOC_STRING)
- return Qnil;
- else
- {
- Lisp_Object tem = AREF (fun, COMPILED_DOC_STRING);
- if (STRINGP (tem))
- doc = tem;
- else if (FIXNATP (tem) || CONSP (tem))
- doc = tem;
- else
- return Qnil;
- }
- }
- else if (STRINGP (fun) || VECTORP (fun))
- {
- return build_string ("Keyboard macro.");
- }
- else if (CONSP (fun))
- {
- Lisp_Object funcar = XCAR (fun);
- if (!SYMBOLP (funcar))
- xsignal1 (Qinvalid_function, fun);
- else if (EQ (funcar, Qkeymap))
- return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
- else if (EQ (funcar, Qlambda)
- || (EQ (funcar, Qclosure) && (fun = XCDR (fun), 1))
- || EQ (funcar, Qautoload))
- {
- Lisp_Object tem1 = Fcdr (Fcdr (fun));
- Lisp_Object tem = Fcar (tem1);
- if (STRINGP (tem))
- doc = tem;
- /* Handle a doc reference--but these never come last
- in the function body, so reject them if they are last. */
- else if ((FIXNATP (tem) || (CONSP (tem) && FIXNUMP (XCDR (tem))))
- && !NILP (XCDR (tem1)))
- doc = tem;
- else
- return Qnil;
- }
- else
- goto oops;
- }
else
- {
- oops:
- xsignal1 (Qinvalid_function, fun);
- }
+ doc = call1 (intern ("function-documentation"), fun);
/* If DOC is 0, it's typically because of a dumped file missing
from the DOC file (bug in src/Makefile.in). */
- if (EQ (doc, make_fixnum (0)))
+ if (BASE_EQ (doc, make_fixnum (0)))
doc = Qnil;
if (FIXNUMP (doc) || CONSP (doc))
{
@@ -448,7 +400,7 @@ aren't strings. */)
tem = Fget (indirect, prop);
}
- if (EQ (tem, make_fixnum (0)))
+ if (BASE_EQ (tem, make_fixnum (0)))
tem = Qnil;
/* See if we want to look for the string in the DOC file. */
@@ -514,11 +466,17 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset)
{
/* This bytecode object must have a slot for the
docstring, since we've found a docstring for it. */
- if (PVSIZE (fun) > COMPILED_DOC_STRING)
+ if (PVSIZE (fun) > COMPILED_DOC_STRING
+ /* Don't overwrite a non-docstring value placed there,
+ * such as the symbols used for Oclosures. */
+ && VALID_DOCSTRING_P (AREF (fun, COMPILED_DOC_STRING)))
ASET (fun, COMPILED_DOC_STRING, make_fixnum (offset));
else
{
- AUTO_STRING (format, "No docstring slot for %s");
+ AUTO_STRING (format,
+ (PVSIZE (fun) > COMPILED_DOC_STRING
+ ? "Docstring slot busy for %s"
+ : "No docstring slot for %s"));
CALLN (Fmessage, format,
(SYMBOLP (obj)
? SYMBOL_NAME (obj)
@@ -545,7 +503,6 @@ the same file name is found in the `doc-directory'. */)
EMACS_INT pos;
Lisp_Object sym;
char *p, *name;
- ptrdiff_t count;
char const *dirname;
ptrdiff_t dirlen;
/* Preloaded defcustoms using custom-initialize-delay are added to
@@ -569,7 +526,7 @@ the same file name is found in the `doc-directory'. */)
dirlen = SBYTES (Vdoc_directory);
}
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
USE_SAFE_ALLOCA;
name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
lispstpcpy (stpcpy (name, dirname), filename); /*** Add this line ***/
@@ -612,6 +569,8 @@ the same file name is found in the `doc-directory'. */)
if (p)
{
end = strchr (p, '\n');
+ if (!end)
+ error ("DOC file invalid at position %"pI"d", pos);
/* We used to skip files not in build_files, so that when a
function was defined several times in different files
@@ -678,7 +637,7 @@ default_to_grave_quoting_style (void)
Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table),
LEFT_SINGLE_QUOTATION_MARK);
return (VECTORP (dv) && ASIZE (dv) == 1
- && EQ (AREF (dv, 0), make_fixnum ('`')));
+ && BASE_EQ (AREF (dv, 0), make_fixnum ('`')));
}
DEFUN ("text-quoting-style", Ftext_quoting_style,
diff --git a/src/dynlib.c b/src/dynlib.c
index 8cb9a233745..e2c71f14489 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -279,11 +279,13 @@ dynlib_open (const char *path)
return dlopen (path, RTLD_LAZY | RTLD_GLOBAL);
}
+# ifdef HAVE_NATIVE_COMP
dynlib_handle_ptr
dynlib_open_for_eln (const char *path)
{
return dlopen (path, RTLD_LAZY);
}
+# endif
void *
dynlib_sym (dynlib_handle_ptr h, const char *sym)
@@ -313,11 +315,13 @@ dynlib_error (void)
return dlerror ();
}
+# ifdef HAVE_NATIVE_COMP
int
dynlib_close (dynlib_handle_ptr h)
{
return dlclose (h) == 0;
}
+# endif
#else
diff --git a/src/dynlib.h b/src/dynlib.h
index ac3d8e58ab3..03b8f983564 100644
--- a/src/dynlib.h
+++ b/src/dynlib.h
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef DYNLIB_H
#define DYNLIB_H
+#include <attribute.h>
#include <stdbool.h>
typedef void *dynlib_handle_ptr;
diff --git a/src/editfns.c b/src/editfns.c
index 790f66e3a02..4587b1132b1 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -161,7 +161,7 @@ DEFUN ("byte-to-string", Fbyte_to_string, Sbyte_to_string, 1, 1, 0,
if (XFIXNUM (byte) < 0 || XFIXNUM (byte) > 255)
error ("Invalid byte");
b = XFIXNUM (byte);
- return make_string_from_bytes ((char *) &b, 1, 1);
+ return make_unibyte_string ((char *) &b, 1);
}
DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
@@ -648,7 +648,7 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */)
prev_new = make_fixnum (XFIXNUM (new_pos) - 1);
if (NILP (Vinhibit_field_text_motion)
- && !EQ (new_pos, old_pos)
+ && !BASE_EQ (new_pos, old_pos)
&& (!NILP (Fget_char_property (new_pos, Qfield, Qnil))
|| !NILP (Fget_char_property (old_pos, Qfield, Qnil))
/* To recognize field boundaries, we must also look at the
@@ -797,7 +797,7 @@ save_excursion_save (union specbinding *pdl)
pdl->unwind_excursion.marker = Fpoint_marker ();
/* Selected window if current buffer is shown in it, nil otherwise. */
pdl->unwind_excursion.window
- = (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
+ = (BASE_EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
? selected_window : Qnil);
}
@@ -821,7 +821,7 @@ save_excursion_restore (Lisp_Object marker, Lisp_Object window)
/* If buffer was visible in a window, and a different window was
selected, and the old selected window is still showing this
buffer, restore point in that window. */
- if (WINDOWP (window) && !EQ (window, selected_window))
+ if (WINDOWP (window) && !BASE_EQ (window, selected_window))
{
/* Set window point if WINDOW is live and shows the current buffer. */
Lisp_Object contents = XWINDOW (window)->contents;
@@ -847,7 +847,7 @@ usage: (save-excursion &rest BODY) */)
(Lisp_Object args)
{
register Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_excursion ();
@@ -861,7 +861,7 @@ BODY is executed just like `progn'.
usage: (save-current-buffer &rest BODY) */)
(Lisp_Object args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
return unbind_to (count, Fprogn (args));
@@ -2022,7 +2022,7 @@ nil. */)
return Qt;
}
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t diags = size_a + size_b + 3;
@@ -2247,7 +2247,7 @@ Both characters must have the same length of multi-byte form. */)
ptrdiff_t changed = 0;
unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
unsigned char *p;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#define COMBINING_NO 0
#define COMBINING_BEFORE 1
#define COMBINING_AFTER 2
@@ -2820,7 +2820,7 @@ usage: (save-restriction &rest BODY) */)
(Lisp_Object body)
{
register Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect (save_restriction_restore, save_restriction_save ());
val = Fprogn (body);
@@ -2843,7 +2843,7 @@ otherwise MSGID-PLURAL. */)
CHECK_INTEGER (n);
/* Placeholder implementation until we get our act together. */
- return EQ (n, make_fixnum (1)) ? msgid : msgid_plural;
+ return BASE_EQ (n, make_fixnum (1)) ? msgid : msgid_plural;
}
DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
@@ -3112,7 +3112,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
ptrdiff_t bufsize = sizeof initial_buffer;
ptrdiff_t max_bufsize = STRING_BYTES_BOUND + 1;
char *p;
- ptrdiff_t buf_save_value_index UNINIT;
+ specpdl_ref buf_save_value_index UNINIT;
char *format, *end;
ptrdiff_t nchars;
/* When we make a multibyte string, we must pay attention to the
@@ -3327,7 +3327,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
if (EQ (arg, args[n]))
{
Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
- spec->argument = arg = Fprin1_to_string (arg, noescape);
+ spec->argument = arg = Fprin1_to_string (arg, noescape, Qnil);
if (STRING_MULTIBYTE (arg) && ! multibyte)
{
multibyte = true;
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 392b3ba9659..1c392d65df8 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -411,7 +411,7 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n)
reference that's identical to some global reference. */
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
- if (!EQ (HASH_KEY (h, i), Qunbound)
+ if (!BASE_EQ (HASH_KEY (h, i), Qunbound)
&& &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
return true;
}
@@ -955,11 +955,9 @@ single memcpy to convert the magnitude. This way we largely avoid the
import/export overhead on most platforms.
*/
-enum
-{
- /* Documented maximum count of magnitude elements. */
- module_bignum_count_max = min (SIZE_MAX, PTRDIFF_MAX) / sizeof (emacs_limb_t)
-};
+/* Documented maximum count of magnitude elements. */
+#define module_bignum_count_max \
+ ((ptrdiff_t) min (SIZE_MAX, PTRDIFF_MAX) / sizeof (emacs_limb_t))
/* Verify that emacs_limb_t indeed has unique object
representations. */
@@ -1137,7 +1135,7 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
rt->private_members = &rt_priv;
rt->get_environment = module_get_environment;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_module (SPECPDL_MODULE_RUNTIME, rt);
record_unwind_protect_module (SPECPDL_MODULE_ENVIRONMENT, rt_priv.env);
@@ -1166,7 +1164,7 @@ funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist)
emacs_env pub;
struct emacs_env_private priv;
emacs_env *env = initialize_environment (&pub, &priv);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_module (SPECPDL_MODULE_ENVIRONMENT, env);
USE_SAFE_ALLOCA;
diff --git a/src/emacs.c b/src/emacs.c
index f6e2c01ee74..3c768412818 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -140,6 +140,10 @@ extern char etext;
#include "fingerprint.h"
#include "epaths.h"
+/* Include these only because of INLINE. */
+#include "comp.h"
+#include "thread.h"
+
static const char emacs_version[] = PACKAGE_VERSION;
static const char emacs_copyright[] = COPYRIGHT;
static const char emacs_bugreport[] = PACKAGE_BUGREPORT;
@@ -155,6 +159,10 @@ Lisp_Object empty_unibyte_string, empty_multibyte_string;
#ifdef WINDOWSNT
/* Cache for externally loaded libraries. */
Lisp_Object Vlibrary_cache;
+/* Original command line string as received from the OS. */
+static char *initial_cmdline;
+/* Original working directory when invoked. */
+static const char *initial_wd;
#endif
struct gflags gflags;
@@ -190,8 +198,11 @@ static uintmax_t heap_bss_diff;
We mark being in the exec'd process by a daemon name argument of
form "--daemon=\nFD0,FD1\nNAME" where FD are the pipe file descriptors,
- NAME is the original daemon name, if any. */
-#if defined NS_IMPL_COCOA || defined CYGWIN
+ NAME is the original daemon name, if any.
+
+ On Haiku, the table of semaphores used for looper locks doesn't
+ persist across forked processes. */
+#if defined NS_IMPL_COCOA || defined CYGWIN || defined HAVE_HAIKU
# define DAEMON_MUST_EXEC
#endif
@@ -222,6 +233,7 @@ HANDLE w32_daemon_event;
/* Save argv and argc. */
char **initial_argv;
int initial_argc;
+static char *initial_emacs_executable = NULL;
/* The name of the working directory, or NULL if this info is unavailable. */
char const *emacs_wd;
@@ -284,7 +296,10 @@ Initialization options:\n\
-q --no-site-file --no-site-lisp --no-splash\n\
--no-x-resources\n\
--script FILE run FILE as an Emacs Lisp script\n\
---terminal, -t DEVICE use DEVICE for terminal I/O\n\
+-x to be used in #!/usr/bin/emacs -x\n\
+ and has approximately the same meaning\n\
+ as -Q --script\n\
+--terminal, -t DEVICE use DEVICE for terminal I/O\n \
--user, -u USER load ~USER/.emacs instead of your own\n\
\n\
",
@@ -420,7 +435,7 @@ terminate_due_to_signal (int sig, int backtrace_limit)
don't care about the message stack. */
if (sig == SIGINT && noninteractive)
clear_message_stack ();
- Fkill_emacs (make_fixnum (sig));
+ Fkill_emacs (make_fixnum (sig), Qnil);
}
shut_down_emacs (sig, Qnil);
@@ -453,7 +468,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
{
int i;
Lisp_Object name, dir, handler;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object raw_name;
AUTO_STRING (slash_colon, "/:");
@@ -703,34 +718,6 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr,
}
}
-#ifdef HAVE_PDUMPER
-
-static const char *
-dump_error_to_string (int result)
-{
- switch (result)
- {
- case PDUMPER_LOAD_SUCCESS:
- return "success";
- case PDUMPER_LOAD_OOM:
- return "out of memory";
- case PDUMPER_NOT_LOADED:
- return "not loaded";
- case PDUMPER_LOAD_FILE_NOT_FOUND:
- return "could not open file";
- case PDUMPER_LOAD_BAD_FILE_TYPE:
- return "not a dump file";
- case PDUMPER_LOAD_FAILED_DUMP:
- return "dump file is result of failed dump attempt";
- case PDUMPER_LOAD_VERSION_MISMATCH:
- return "not built for this Emacs executable";
- default:
- return (result <= PDUMPER_LOAD_ERROR
- ? "generic error"
- : strerror (result - PDUMPER_LOAD_ERROR));
- }
-}
-
/* Find a name (absolute or relative) of the Emacs executable whose
name (as passed into this program) is ARGV0. Called early in
initialization by portable dumper loading code, so avoid Lisp and
@@ -739,7 +726,7 @@ dump_error_to_string (int result)
if not found. Store into *CANDIDATE_SIZE a lower bound on the size
of any heap allocation. */
static char *
-load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
+find_emacs_executable (char const *argv0, ptrdiff_t *candidate_size)
{
*candidate_size = 0;
@@ -830,7 +817,36 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
#endif /* !WINDOWSNT */
}
-static void
+#ifdef HAVE_PDUMPER
+
+static const char *
+dump_error_to_string (int result)
+{
+ switch (result)
+ {
+ case PDUMPER_LOAD_SUCCESS:
+ return "success";
+ case PDUMPER_LOAD_OOM:
+ return "out of memory";
+ case PDUMPER_NOT_LOADED:
+ return "not loaded";
+ case PDUMPER_LOAD_FILE_NOT_FOUND:
+ return "could not open file";
+ case PDUMPER_LOAD_BAD_FILE_TYPE:
+ return "not a dump file";
+ case PDUMPER_LOAD_FAILED_DUMP:
+ return "dump file is result of failed dump attempt";
+ case PDUMPER_LOAD_VERSION_MISMATCH:
+ return "not built for this Emacs executable";
+ default:
+ return (result <= PDUMPER_LOAD_ERROR
+ ? "generic error"
+ : strerror (result - PDUMPER_LOAD_ERROR));
+ }
+}
+
+/* This function returns the Emacs executable. */
+static char *
load_pdump (int argc, char **argv)
{
const char *const suffix = ".pdmp";
@@ -879,7 +895,7 @@ load_pdump (int argc, char **argv)
#ifndef NS_SELF_CONTAINED
ptrdiff_t exec_bufsize;
#endif
- emacs_executable = load_pdump_find_executable (argv[0], &bufsize);
+ emacs_executable = find_emacs_executable (argv[0], &bufsize);
#ifndef NS_SELF_CONTAINED
exec_bufsize = bufsize;
#endif
@@ -896,7 +912,7 @@ load_pdump (int argc, char **argv)
if (result != PDUMPER_LOAD_SUCCESS)
fatal ("could not load dump file \"%s\": %s",
dump_file, dump_error_to_string (result));
- return;
+ return emacs_executable;
}
/* Look for a dump file in the same directory as the executable; it
@@ -959,20 +975,24 @@ load_pdump (int argc, char **argv)
sprintf (dump_file, "%s%c%s-%s%s",
path_exec, DIRECTORY_SEP, argv0_base, hexbuf, suffix);
#if !defined (NS_SELF_CONTAINED)
- /* Assume the Emacs binary lives in a sibling directory as set up by
- the default installation configuration. */
- const char *go_up = "../../../../bin/";
- needed += (strip_suffix ? strlen (strip_suffix) : 0)
- - strlen (suffix) + strlen (go_up);
- if (exec_bufsize < needed)
+ if (!(emacs_executable && *emacs_executable))
{
- xfree (emacs_executable);
- emacs_executable = xpalloc (NULL, &exec_bufsize, needed - exec_bufsize,
- -1, 1);
+ /* If we didn't find the Emacs binary, assume that it lives in a
+ sibling directory as set up by the default installation
+ configuration. */
+ const char *go_up = "../../../../bin/";
+ needed += (strip_suffix ? strlen (strip_suffix) : 0)
+ - strlen (suffix) + strlen (go_up);
+ if (exec_bufsize < needed)
+ {
+ xfree (emacs_executable);
+ emacs_executable = xpalloc (NULL, &exec_bufsize,
+ needed - exec_bufsize, -1, 1);
+ }
+ sprintf (emacs_executable, "%s%c%s%s%s",
+ path_exec, DIRECTORY_SEP, go_up, argv0_base,
+ strip_suffix ? strip_suffix : "");
}
- sprintf (emacs_executable, "%s%c%s%s%s",
- path_exec, DIRECTORY_SEP, go_up, argv0_base,
- strip_suffix ? strip_suffix : "");
#endif
result = pdumper_load (dump_file, emacs_executable);
@@ -1021,7 +1041,8 @@ load_pdump (int argc, char **argv)
out:
xfree (dump_file);
- xfree (emacs_executable);
+
+ return emacs_executable;
}
#endif /* HAVE_PDUMPER */
@@ -1312,6 +1333,7 @@ main (int argc, char **argv)
}
}
init_heap (use_dynamic_heap);
+ initial_cmdline = GetCommandLine ();
#endif
#if defined WINDOWSNT || defined HAVE_NTGUI
/* Set global variables used to detect Windows version. Do this as
@@ -1334,7 +1356,10 @@ main (int argc, char **argv)
#ifdef HAVE_PDUMPER
if (attempt_load_pdump)
- load_pdump (argc, argv);
+ initial_emacs_executable = load_pdump (argc, argv);
+#else
+ ptrdiff_t bufsize;
+ initial_emacs_executable = find_emacs_executable (argv[0], &bufsize);
#endif
argc = maybe_disable_address_randomization (argc, argv);
@@ -1384,7 +1409,7 @@ main (int argc, char **argv)
related to the GUI system, like -font, -geometry, and -title, and
then processes the rest of arguments whose priority is below
those that are related to the GUI system. The arguments
- porcessed by 'command-line' are removed from 'command-line-args';
+ processed by 'command-line' are removed from 'command-line-args';
the arguments processed by 'command-line-1' aren't, they are only
removed from 'command-line-args-left'.
@@ -1394,54 +1419,19 @@ main (int argc, char **argv)
should be explicitly recognized, ignored, and removed from
'command-line-args-left' in 'command-line-1'. */
+ bool only_version = false;
sort_args (argc, argv);
argc = 0;
while (argv[argc]) argc++;
skip_args = 0;
if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args))
- {
- const char *version, *copyright;
- if (initialized)
- {
- Lisp_Object tem, tem2;
- tem = Fsymbol_value (intern_c_string ("emacs-version"));
- tem2 = Fsymbol_value (intern_c_string ("emacs-copyright"));
- if (!STRINGP (tem))
- {
- fputs ("Invalid value of 'emacs-version'\n", stderr);
- exit (1);
- }
- if (!STRINGP (tem2))
- {
- fputs ("Invalid value of 'emacs-copyright'\n", stderr);
- exit (1);
- }
- else
- {
- version = SSDATA (tem);
- copyright = SSDATA (tem2);
- }
- }
- else
- {
- version = emacs_version;
- copyright = emacs_copyright;
- }
- printf (("%s %s\n"
- "%s\n"
- "%s comes with ABSOLUTELY NO WARRANTY.\n"
- "You may redistribute copies of %s\n"
- "under the terms of the GNU General Public License.\n"
- "For more information about these matters, "
- "see the file named COPYING.\n"),
- PACKAGE_NAME, version, copyright, PACKAGE_NAME, PACKAGE_NAME);
- exit (0);
- }
+ only_version = true;
#ifdef HAVE_PDUMPER
if (argmatch (argv, argc, "-fingerprint", "--fingerprint", 4,
- NULL, &skip_args))
+ NULL, &skip_args)
+ && !only_version)
{
if (initialized)
{
@@ -1458,12 +1448,16 @@ main (int argc, char **argv)
#endif
emacs_wd = emacs_get_current_dir_name ();
+#ifdef WINDOWSNT
+ initial_wd = emacs_wd;
+#endif
#ifdef HAVE_PDUMPER
if (dumped_with_pdumper_p ())
pdumper_record_wd (emacs_wd);
#endif
- if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args))
+ if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args)
+ && !only_version)
{
#ifdef WINDOWSNT
/* argv[] array is kept in its original ANSI codepage encoding,
@@ -1589,7 +1583,7 @@ main (int argc, char **argv)
inhibit_window_system = 0;
/* Handle the -t switch, which specifies filename to use as terminal. */
- while (1)
+ while (!only_version)
{
char *term;
if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args))
@@ -1627,7 +1621,8 @@ main (int argc, char **argv)
/* Handle the -batch switch, which means don't do interactive display. */
noninteractive = 0;
- if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args))
+ if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args)
+ || only_version)
{
noninteractive = 1;
Vundo_outer_limit = Qnil;
@@ -1644,7 +1639,8 @@ main (int argc, char **argv)
}
/* Handle the --help option, which gives a usage message. */
- if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args))
+ if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)
+ && !only_version)
{
int i;
printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
@@ -1665,20 +1661,27 @@ main (int argc, char **argv)
int sockfd = -1;
- if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, &skip_args)
- || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, &skip_args))
+ if (!only_version)
{
- daemon_type = 1; /* foreground */
- }
- else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
- || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args)
- || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL, &skip_args)
- || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, &dname_arg, &skip_args))
- {
- daemon_type = 2; /* background */
+ if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL,
+ &skip_args)
+ || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg,
+ &skip_args))
+ {
+ daemon_type = 1; /* foreground */
+ }
+ else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
+ || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg,
+ &skip_args)
+ || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL,
+ &skip_args)
+ || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10,
+ &dname_arg, &skip_args))
+ {
+ daemon_type = 2; /* background */
+ }
}
-
if (daemon_type > 0)
{
#ifndef DOS_NT
@@ -1727,12 +1730,25 @@ main (int argc, char **argv)
sockfd = SD_LISTEN_FDS_START;
#endif /* HAVE_LIBSYSTEMD */
-#ifdef USE_GTK
+ /* On X, the bug happens because we call abort to avoid GLib
+ crashes upon a longjmp in our X error handler.
+
+ On PGTK, GTK calls exit in its own error handlers for either
+ X or Wayland. Display different messages depending on the
+ window system to avoid referring users to the wrong GTK bug
+ report. */
+#ifdef HAVE_PGTK
+ fputs ("Due to a limitation in GTK 3, Emacs built with PGTK will simply exit when a\n"
+ "display connection is closed. The problem is especially difficult to fix,\n"
+ "such that Emacs on Wayland with multiple displays is unlikely ever to be able\n"
+ "to survive disconnects.\n",
+ stderr);
+#elif defined USE_GTK
fputs ("\nWarning: due to a long standing Gtk+ bug\nhttps://gitlab.gnome.org/GNOME/gtk/issues/221\n\
Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.\n\
Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.\n",
stderr);
-#endif /* USE_GTK */
+#endif
if (daemon_type == 2)
{
@@ -1914,16 +1930,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_bignum ();
init_threads ();
init_eval ();
-#ifdef HAVE_PGTK
- init_pgtkterm (); /* before init_atimer(). */
-#endif
running_asynch_code = 0;
init_random ();
-
-#ifdef HAVE_PDUMPER
- if (dumped_with_pdumper_p ())
- init_xfaces ();
-#endif
+ init_xfaces ();
#if defined HAVE_JSON && !defined WINDOWSNT
init_json ();
@@ -1932,6 +1941,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
if (!initialized)
syms_of_comp ();
+ /* Do less garbage collection in batch mode (since these tend to be
+ more short-lived, and the memory is returned to the OS on exit
+ anyway). */
+ Vgc_cons_percentage = make_float (noninteractive? 1.0: 0.1);
+
no_loadup
= argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
@@ -1945,7 +1959,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
bool module_assertions
= argmatch (argv, argc, "-module-assertions", "--module-assertions", 15,
NULL, &skip_args);
- if (will_dump_p () && module_assertions)
+ if (will_dump_p () && module_assertions && !only_version)
{
fputs ("Module assertions are not supported during dumping\n", stderr);
exit (1);
@@ -1993,7 +2007,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
int count_before = skip_args;
/* Skip any number of -d options, but only use the last one. */
- while (1)
+ while (!only_version)
{
int count_before_this = skip_args;
@@ -2029,6 +2043,16 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
no_site_lisp = 1;
}
+ if (argmatch (argv, argc, "-x", 0, 1, &junk, &skip_args))
+ {
+ noninteractive = 1;
+ no_site_lisp = 1;
+ /* This is picked up in startup.el. */
+ argv[skip_args - 1] = (char *) "-scripteval";
+ skip_args -= 1;
+ sort_args (argc, argv);
+ }
+
/* Don't actually discard this arg. */
skip_args = count_before;
}
@@ -2125,6 +2149,72 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */
init_fileio ();
init_lread ();
+
+ /* If "-version" was specified, produce version information and
+ exit. We do it here because the code below needs to call Lisp
+ primitives, which cannot be done safely before we call all the
+ init_FOO initialization functions above. */
+ if (only_version)
+ {
+ const char *version, *copyright;
+
+ if (initialized)
+ {
+ Lisp_Object tem = Fsymbol_value (intern_c_string ("emacs-version"));
+ Lisp_Object tem2 = Fsymbol_value (intern_c_string ("emacs-copyright"));
+ if (!STRINGP (tem))
+ {
+ fputs ("Invalid value of 'emacs-version'\n", stderr);
+ exit (1);
+ }
+ if (!STRINGP (tem2))
+ {
+ fputs ("Invalid value of 'emacs-copyright'\n", stderr);
+ exit (1);
+ }
+ else
+ {
+ version = SSDATA (tem);
+ copyright = SSDATA (tem2);
+ }
+ }
+ else
+ {
+ version = emacs_version;
+ copyright = emacs_copyright;
+ }
+ printf ("%s %s\n", PACKAGE_NAME, version);
+
+ if (initialized)
+ {
+ Lisp_Object rversion, rbranch, rtime;
+
+ rversion
+ = Fsymbol_value (intern_c_string ("emacs-repository-version"));
+ rbranch
+ = Fsymbol_value (intern_c_string ("emacs-repository-branch"));
+ rtime
+ = Fsymbol_value (intern_c_string ("emacs-build-time"));
+
+ if (!NILP (rversion) && !NILP (rbranch) && !NILP (rtime))
+ printf ("Development version %s on %s branch; build date %s.\n",
+ SSDATA (Fsubstring (rversion, make_fixnum (0),
+ make_fixnum (12))),
+ SSDATA (rbranch),
+ SSDATA (Fformat_time_string (build_string ("%Y-%m-%d"),
+ rtime, Qnil)));
+ }
+
+ printf (("%s\n"
+ "%s comes with ABSOLUTELY NO WARRANTY.\n"
+ "You may redistribute copies of %s\n"
+ "under the terms of the GNU General Public License.\n"
+ "For more information about these matters, "
+ "see the file named COPYING.\n"),
+ copyright, PACKAGE_NAME, PACKAGE_NAME);
+ exit (0);
+ }
+
#ifdef WINDOWSNT
/* Check to see if Emacs has been installed correctly. */
check_windows_init_file ();
@@ -2328,11 +2418,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#if defined WINDOWSNT || defined HAVE_NTGUI
globals_of_w32select ();
#endif
+ }
#ifdef HAVE_HAIKU
- init_haiku_select ();
+ init_haiku_select ();
#endif
- }
init_charset ();
@@ -2470,8 +2560,10 @@ static const struct standard_args standard_args[] =
/* (Note that to imply -nsl, -Q is partially handled here.) */
{ "-Q", "--quick", 55, 0 },
{ "-quick", 0, 55, 0 },
+ { "-x", 0, 55, 0 },
{ "-q", "--no-init-file", 50, 0 },
{ "-no-init-file", 0, 50, 0 },
+ { "-init-directory", "--init-directory", 30, 1 },
{ "-no-x-resources", "--no-x-resources", 40, 0 },
{ "-no-site-file", "--no-site-file", 40, 0 },
{ "-u", "--user", 30, 1 },
@@ -2719,24 +2811,47 @@ sort_args (int argc, char **argv)
xfree (priority);
}
-DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
+DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 2, "P",
doc: /* Exit the Emacs job and kill it.
If ARG is an integer, return ARG as the exit program code.
If ARG is a string, stuff it as keyboard input.
Any other value of ARG, or ARG omitted, means return an
exit code that indicates successful program termination.
+If RESTART is non-nil, instead of just exiting at the end, start a new
+Emacs process, using the same command line arguments as the currently
+running Emacs process.
+
This function is called upon receipt of the signals SIGTERM
or SIGHUP, and upon SIGINT in batch mode.
-The value of `kill-emacs-hook', if not void,
-is a list of functions (of no args),
-all of which are called before Emacs is actually killed. */
+The value of `kill-emacs-hook', if not void, is a list of functions
+(of no args), all of which are called before Emacs is actually
+killed. */
attributes: noreturn)
- (Lisp_Object arg)
+ (Lisp_Object arg, Lisp_Object restart)
{
int exit_code;
+#ifndef WINDOWSNT
+ /* Do some checking before shutting down Emacs, because errors
+ can't be meaningfully reported afterwards. */
+ if (!NILP (restart))
+ {
+ /* This is very unlikely, but it's possible to execute a binary
+ (on some systems) with no argv. */
+ if (initial_argc < 1)
+ error ("No command line arguments known; unable to re-execute Emacs");
+
+ /* Check that the binary hasn't gone away. */
+ if (!initial_emacs_executable)
+ error ("Unknown Emacs executable");
+
+ if (!file_access_p (initial_emacs_executable, F_OK))
+ error ("Emacs executable \"%s\" can't be found", initial_argv[0]);
+ }
+#endif
+
#ifdef HAVE_LIBSYSTEMD
/* Notify systemd we are shutting down, but only if we have notified
it about startup. */
@@ -2780,6 +2895,17 @@ all of which are called before Emacs is actually killed. */
eln_load_path_final_clean_up ();
#endif
+ if (!NILP (restart))
+ {
+#ifdef WINDOWSNT
+ if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0)
+#else
+ initial_argv[0] = initial_emacs_executable;
+ if (execvp (*initial_argv, initial_argv) < 1)
+#endif
+ emacs_perror ("Unable to re-execute Emacs");
+ }
+
if (FIXNUMP (arg))
exit_code = (XFIXNUM (arg) < 0
? XFIXNUM (arg) | INT_MIN
@@ -2810,9 +2936,6 @@ shut_down_emacs (int sig, Lisp_Object stuff)
/* Don't update display from now on. */
Vinhibit_redisplay = Qt;
-#ifdef HAVE_HAIKU
- be_app_quit ();
-#endif
/* If we are controlling the terminal, reset terminal modes. */
#ifndef DOS_NT
pid_t tpgrp = tcgetpgrp (STDIN_FILENO);
@@ -2867,6 +2990,10 @@ shut_down_emacs (int sig, Lisp_Object stuff)
check_message_stack ();
}
+#ifdef HAVE_NATIVE_COMP
+ eln_load_path_final_clean_up ();
+#endif
+
#ifdef MSDOS
dos_cleanup ();
#endif
@@ -2900,7 +3027,7 @@ You must run Emacs in batch mode in order to dump it. */)
{
Lisp_Object tem;
Lisp_Object symbol;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
check_pure_size ();
@@ -3073,6 +3200,9 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
{
const char *path, *p;
Lisp_Object lpath, element, tem;
+#ifdef NS_SELF_CONTAINED
+ void *autorelease = NULL;
+#endif
/* Default is to use "." for empty path elements.
But if argument EMPTY is true, use nil instead. */
Lisp_Object empty_element = empty ? Qnil : build_string (".");
@@ -3100,6 +3230,8 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
if (!path)
{
#ifdef NS_SELF_CONTAINED
+ /* ns_relocate needs a valid autorelease pool around it. */
+ autorelease = ns_alloc_autorelease_pool ();
path = ns_relocate (defalt);
#else
path = defalt;
@@ -3202,6 +3334,11 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
else
break;
}
+
+#ifdef NS_SELF_CONTAINED
+ if (autorelease)
+ ns_release_autorelease_pool (autorelease);
+#endif
return Fnreverse (lpath);
}
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index da56031e2a4..f2c9fa7b7db 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -164,15 +164,33 @@ 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;
+ /* Overriding the size hints with our own values of min_width
+ and min_height used to work, but these days just results in
+ frames resizing unpredictably and emitting GTK warnings while
+ Emacs fights with GTK over the size of the frame. So instead
+ of doing that, just respect the hints set by GTK, but make
+ sure they are an integer multiple of the resize increments so
+ that bug#8919 stays fixed. */
+
+ /* int w = f->output_data.x->size_hints.min_width;
+ int h = f->output_data.x->size_hints.min_height;
+
+ data[5] = w;
+ data[6] = h; */
+
+ /* Make sure min_width and min_height are multiples of width_inc
+ and height_inc. */
+
+ if (hints->flags & PResizeInc)
+ {
+ /* Some versions of GTK set PResizeInc even if the
+ increments are at their initial values. */
+
+ if (hints->width_inc && data[5] % hints->width_inc)
+ data[5] += (hints->width_inc - (data[5] % hints->width_inc));
+ if (hints->height_inc && data[6] % hints->height_inc)
+ data[6] += (hints->height_inc - (data[6] % hints->height_inc));
+ }
}
XChangeProperty (d, w, prop, XA_WM_SIZE_HINTS, 32, PropModeReplace,
diff --git a/src/eval.c b/src/eval.c
index 5514583b6a1..141d2546f08 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -65,7 +65,7 @@ union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE;
union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
-static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t);
+static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, specpdl_ref);
static Lisp_Object lambda_arity (Lisp_Object);
static Lisp_Object
@@ -104,13 +104,6 @@ specpdl_where (union specbinding *pdl)
}
static Lisp_Object
-specpdl_saved_value (union specbinding *pdl)
-{
- eassert (pdl->kind >= SPECPDL_LET);
- return pdl->let.saved_value;
-}
-
-static Lisp_Object
specpdl_arg (union specbinding *pdl)
{
eassert (pdl->kind == SPECPDL_UNWIND);
@@ -138,13 +131,6 @@ backtrace_args (union specbinding *pdl)
return pdl->bt.args;
}
-static bool
-backtrace_debug_on_exit (union specbinding *pdl)
-{
- eassert (pdl->kind == SPECPDL_BACKTRACE);
- return pdl->bt.debug_on_exit;
-}
-
/* Functions to modify slots of backtrace records. */
static void
@@ -237,8 +223,8 @@ init_eval_once_for_pdumper (void)
{
enum { size = 50 };
union specbinding *pdlvec = malloc ((size + 1) * sizeof *specpdl);
- specpdl_size = size;
specpdl = specpdl_ptr = pdlvec + 1;
+ specpdl_end = specpdl + size;
}
void
@@ -281,19 +267,18 @@ restore_stack_limits (Lisp_Object data)
integer_to_intmax (XCDR (data), &max_lisp_eval_depth);
}
-static void grow_specpdl (void);
-
/* Call the Lisp debugger, giving it argument ARG. */
Lisp_Object
call_debugger (Lisp_Object arg)
{
bool debug_while_redisplaying;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
intmax_t old_depth = max_lisp_eval_depth;
/* Do not allow max_specpdl_size less than actual depth (Bug#16603). */
- intmax_t old_max = max (max_specpdl_size, count);
+ ptrdiff_t counti = specpdl_ref_to_count (count);
+ intmax_t old_max = max (max_specpdl_size, counti);
/* The previous value of 40 is too small now that the debugger
prints using cl-prin1 instead of prin1. Printing lists nested 8
@@ -303,9 +288,9 @@ call_debugger (Lisp_Object arg)
/* While debugging Bug#16603, previous value of 100 was found
too small to avoid specpdl overflow in the debugger itself. */
- max_ensure_room (&max_specpdl_size, count, 200);
+ max_ensure_room (&max_specpdl_size, counti, 200);
- if (old_max == count)
+ if (old_max == counti)
{
/* We can enter the debugger due to specpdl overflow (Bug#16603). */
specpdl_ptr--;
@@ -354,11 +339,11 @@ call_debugger (Lisp_Object arg)
return unbind_to (count, val);
}
-static void
-do_debug_on_call (Lisp_Object code, ptrdiff_t count)
+void
+do_debug_on_call (Lisp_Object code, specpdl_ref count)
{
debug_on_next_call = 0;
- set_backtrace_debug_on_exit (specpdl + count, true);
+ set_backtrace_debug_on_exit (specpdl_ref_to_ptr (count), true);
call_debugger (list1 (code));
}
@@ -574,6 +559,10 @@ usage: (function ARG) */)
{ /* Handle the special (:documentation <form>) to build the docstring
dynamically. */
Lisp_Object docstring = eval_sub (Fcar (XCDR (tmp)));
+ if (SYMBOLP (docstring) && !NILP (docstring))
+ /* Hack for OClosures: Allow the docstring to be a symbol
+ * (the OClosure's type). */
+ docstring = Fsymbol_name (docstring);
CHECK_STRING (docstring);
cdr = Fcons (XCAR (cdr), Fcons (docstring, XCDR (XCDR (cdr))));
}
@@ -677,23 +666,7 @@ default_toplevel_binding (Lisp_Object symbol)
binding = pdl;
break;
- case SPECPDL_UNWIND:
- case SPECPDL_UNWIND_ARRAY:
- case SPECPDL_UNWIND_PTR:
- case SPECPDL_UNWIND_INT:
- case SPECPDL_UNWIND_INTMAX:
- case SPECPDL_UNWIND_EXCURSION:
- case SPECPDL_UNWIND_VOID:
- case SPECPDL_BACKTRACE:
-#ifdef HAVE_MODULES
- case SPECPDL_MODULE_RUNTIME:
- case SPECPDL_MODULE_ENVIRONMENT:
-#endif
- case SPECPDL_LET_LOCAL:
- break;
-
- default:
- emacs_abort ();
+ default: break;
}
}
return binding;
@@ -720,23 +693,7 @@ lexbound_p (Lisp_Object symbol)
}
break;
- case SPECPDL_UNWIND:
- case SPECPDL_UNWIND_ARRAY:
- case SPECPDL_UNWIND_PTR:
- case SPECPDL_UNWIND_INT:
- case SPECPDL_UNWIND_INTMAX:
- case SPECPDL_UNWIND_EXCURSION:
- case SPECPDL_UNWIND_VOID:
- case SPECPDL_BACKTRACE:
-#ifdef HAVE_MODULES
- case SPECPDL_MODULE_RUNTIME:
- case SPECPDL_MODULE_ENVIRONMENT:
-#endif
- case SPECPDL_LET_LOCAL:
- break;
-
- default:
- emacs_abort ();
+ default: break;
}
}
return false;
@@ -750,7 +707,7 @@ DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_valu
union specbinding *binding = default_toplevel_binding (symbol);
Lisp_Object value
= binding ? specpdl_old_value (binding) : Fdefault_value (symbol);
- if (!EQ (value, Qunbound))
+ if (!BASE_EQ (value, Qunbound))
return value;
xsignal1 (Qvoid_variable, symbol);
}
@@ -784,7 +741,9 @@ value. */)
and where the `foo` package only gets loaded when <foo-function>
is called, so the outer `let` incorrectly made the binding lexical
because the <foo-var> wasn't yet declared as dynamic at that point. */
- error ("Defining as dynamic an already lexical var");
+ xsignal2 (Qerror,
+ build_string ("Defining as dynamic an already lexical var"),
+ symbol);
XSYMBOL (symbol)->u.s.declared_special = true;
if (!NILP (doc))
@@ -797,6 +756,33 @@ value. */)
return Qnil;
}
+static Lisp_Object
+defvar (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring, bool eval)
+{
+ Lisp_Object tem;
+
+ CHECK_SYMBOL (sym);
+
+ tem = Fdefault_boundp (sym);
+
+ /* Do it before evaluating the initial value, for self-references. */
+ Finternal__define_uninitialized_variable (sym, docstring);
+
+ if (NILP (tem))
+ Fset_default (sym, eval ? eval_sub (initvalue) : initvalue);
+ else
+ { /* Check if there is really a global binding rather than just a let
+ binding that shadows the global unboundness of the var. */
+ union specbinding *binding = default_toplevel_binding (sym);
+ if (binding && BASE_EQ (specpdl_old_value (binding), Qunbound))
+ {
+ set_specpdl_old_value (binding,
+ eval ? eval_sub (initvalue) : initvalue);
+ }
+ }
+ return sym;
+}
+
DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
doc: /* Define SYMBOL as a variable, and return SYMBOL.
You are not required to define a variable in order to use it, but
@@ -811,12 +797,10 @@ value. If SYMBOL is buffer-local, its default value is what is set;
buffer-local values are not affected. If INITVALUE is missing,
SYMBOL's value is not set.
-If SYMBOL has a local binding, then this form affects the local
-binding. This is usually not what you want. Thus, if you need to
-load a file defining variables, with this form or with `defconst' or
-`defcustom', you should always load that file _outside_ any bindings
-for these variables. (`defconst' and `defcustom' behave similarly in
-this respect.)
+If SYMBOL is let-bound, then this form does not affect the local let
+binding but the toplevel default binding instead, like
+`set-toplevel-default-binding`.
+(`defcustom' behaves similarly in this respect.)
The optional argument DOCSTRING is a documentation string for the
variable.
@@ -827,7 +811,7 @@ To define a buffer-local variable, use `defvar-local'.
usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
(Lisp_Object args)
{
- Lisp_Object sym, tem, tail;
+ Lisp_Object sym, tail;
sym = XCAR (args);
tail = XCDR (args);
@@ -839,24 +823,8 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
if (!NILP (XCDR (tail)) && !NILP (XCDR (XCDR (tail))))
error ("Too many arguments");
Lisp_Object exp = XCAR (tail);
-
- tem = Fdefault_boundp (sym);
tail = XCDR (tail);
-
- /* Do it before evaluating the initial value, for self-references. */
- Finternal__define_uninitialized_variable (sym, CAR (tail));
-
- if (NILP (tem))
- Fset_default (sym, eval_sub (exp));
- else
- { /* Check if there is really a global binding rather than just a let
- binding that shadows the global unboundness of the var. */
- union specbinding *binding = default_toplevel_binding (sym);
- if (binding && EQ (specpdl_old_value (binding), Qunbound))
- {
- set_specpdl_old_value (binding, eval_sub (exp));
- }
- }
+ return defvar (sym, exp, CAR (tail), true);
}
else if (!NILP (Vinternal_interpreter_environment)
&& (SYMBOLP (sym) && !XSYMBOL (sym)->u.s.declared_special))
@@ -875,6 +843,14 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
return sym;
}
+DEFUN ("defvar-1", Fdefvar_1, Sdefvar_1, 2, 3, 0,
+ doc: /* Like `defvar' but as a function.
+More specifically behaves like (defvar SYM 'INITVALUE DOCSTRING). */)
+ (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring)
+{
+ return defvar (sym, initvalue, docstring, false);
+}
+
DEFUN ("defconst", Fdefconst, Sdefconst, 2, UNEVALLED, 0,
doc: /* Define SYMBOL as a constant variable.
This declares that neither programs nor users should ever change the
@@ -904,9 +880,18 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */)
error ("Too many arguments");
docstring = XCAR (XCDR (XCDR (args)));
}
+ tem = eval_sub (XCAR (XCDR (args)));
+ return Fdefconst_1 (sym, tem, docstring);
+}
+DEFUN ("defconst-1", Fdefconst_1, Sdefconst_1, 2, 3, 0,
+ doc: /* Like `defconst' but as a function.
+More specifically, behaves like (defconst SYM 'INITVALUE DOCSTRING). */)
+ (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring)
+{
+ CHECK_SYMBOL (sym);
+ Lisp_Object tem = initvalue;
Finternal__define_uninitialized_variable (sym, docstring);
- tem = eval_sub (XCAR (XCDR (args)));
if (!NILP (Vpurify_flag))
tem = Fpurecopy (tem);
Fset_default (sym, tem); /* FIXME: set-default-toplevel-value? */
@@ -936,7 +921,7 @@ usage: (let* VARLIST BODY...) */)
(Lisp_Object args)
{
Lisp_Object var, val, elt, lexenv;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
lexenv = Vinternal_interpreter_environment;
@@ -996,7 +981,7 @@ usage: (let VARLIST BODY...) */)
{
Lisp_Object *temps, tem, lexenv;
Lisp_Object elt;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t argnum;
USE_SAFE_ALLOCA;
@@ -1100,7 +1085,7 @@ If FUNCTION takes less time to execute than TIMEOUT seconds, MESSAGE
is not displayed. */)
(Lisp_Object timeout, Lisp_Object message, Lisp_Object function)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
CHECK_NUMBER (timeout);
CHECK_STRING (message);
@@ -1266,6 +1251,13 @@ unwind_to_catch (struct handler *catch, enum nonlocal_exit type,
set_poll_suppress_count (catch->poll_suppress_count);
unblock_input_to (catch->interrupt_input_blocked);
+#ifdef HAVE_X_WINDOWS
+ /* Restore the X error handler stack. This is important because
+ otherwise a display disconnect won't unwind the stack of error
+ traps to the right depth. */
+ x_unwind_errors_to (catch->x_error_handler_depth);
+#endif
+
do
{
/* Unwind the specpdl stack, and then restore the proper set of
@@ -1280,6 +1272,7 @@ unwind_to_catch (struct handler *catch, enum nonlocal_exit type,
eassert (handlerlist == catch);
lisp_eval_depth = catch->f_lisp_eval_depth;
+ set_act_rec (current_thread, catch->act_rec);
sys_longjmp (catch->jmp, 1);
}
@@ -1313,7 +1306,7 @@ usage: (unwind-protect BODYFORM UNWINDFORMS...) */)
(Lisp_Object args)
{
Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect (prog_ignore, XCDR (args));
val = eval_sub (XCAR (args));
@@ -1383,7 +1376,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
&& (SYMBOLP (XCAR (tem))
|| CONSP (XCAR (tem))))))
error ("Invalid condition handler: %s",
- SDATA (Fprin1_to_string (tem, Qt)));
+ SDATA (Fprin1_to_string (tem, Qt, Qnil)));
if (CONSP (tem) && EQ (XCAR (tem), QCsuccess))
success_handler = XCDR (tem);
else
@@ -1437,7 +1430,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
/* Bind HANDLER_VAR to VAL while evaluating HANDLER_BODY.
The unbind_to undoes just this binding; whoever longjumped
to us unwound the stack to C->pdlcount before throwing. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (handler_var, val);
return unbind_to (count, Fprogn (handler_body));
}
@@ -1458,7 +1451,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
handler_var = Qinternal_interpreter_environment;
}
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (handler_var, result);
return unbind_to (count, Fprogn (success_handler));
}
@@ -1547,90 +1540,6 @@ internal_condition_case_2 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object),
}
}
-/* Like internal_condition_case_1 but call BFUN with ARG1, ARG2, ARG3 as
- its arguments. */
-
-Lisp_Object
-internal_condition_case_3 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object,
- Lisp_Object),
- Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object handlers,
- Lisp_Object (*hfun) (Lisp_Object))
-{
- struct handler *c = push_handler (handlers, CONDITION_CASE);
- if (sys_setjmp (c->jmp))
- {
- Lisp_Object val = handlerlist->val;
- clobbered_eassert (handlerlist == c);
- handlerlist = handlerlist->next;
- return hfun (val);
- }
- else
- {
- Lisp_Object val = bfun (arg1, arg2, arg3);
- eassert (handlerlist == c);
- handlerlist = c->next;
- return val;
- }
-}
-
-/* Like internal_condition_case_1 but call BFUN with ARG1, ARG2, ARG3, ARG4 as
- its arguments. */
-
-Lisp_Object
-internal_condition_case_4 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object),
- Lisp_Object arg1, Lisp_Object arg2,
- Lisp_Object arg3, Lisp_Object arg4,
- Lisp_Object handlers,
- Lisp_Object (*hfun) (Lisp_Object))
-{
- struct handler *c = push_handler (handlers, CONDITION_CASE);
- if (sys_setjmp (c->jmp))
- {
- Lisp_Object val = handlerlist->val;
- clobbered_eassert (handlerlist == c);
- handlerlist = handlerlist->next;
- return hfun (val);
- }
- else
- {
- Lisp_Object val = bfun (arg1, arg2, arg3, arg4);
- eassert (handlerlist == c);
- handlerlist = c->next;
- return val;
- }
-}
-
-/* Like internal_condition_case_1 but call BFUN with ARG1, ARG2, ARG3,
- ARG4, ARG5 as its arguments. */
-
-Lisp_Object
-internal_condition_case_5 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object,
- Lisp_Object),
- Lisp_Object arg1, Lisp_Object arg2,
- Lisp_Object arg3, Lisp_Object arg4,
- Lisp_Object arg5, Lisp_Object handlers,
- Lisp_Object (*hfun) (Lisp_Object))
-{
- struct handler *c = push_handler (handlers, CONDITION_CASE);
- if (sys_setjmp (c->jmp))
- {
- Lisp_Object val = handlerlist->val;
- clobbered_eassert (handlerlist == c);
- handlerlist = handlerlist->next;
- return hfun (val);
- }
- else
- {
- Lisp_Object val = bfun (arg1, arg2, arg3, arg4, arg5);
- eassert (handlerlist == c);
- handlerlist = c->next;
- return val;
- }
-}
-
/* Like internal_condition_case but call BFUN with NARGS as first,
and ARGS as second argument. */
@@ -1720,8 +1629,12 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype)
c->next = handlerlist;
c->f_lisp_eval_depth = lisp_eval_depth;
c->pdlcount = SPECPDL_INDEX ();
+ c->act_rec = get_act_rec (current_thread);
c->poll_suppress_count = poll_suppress_count;
c->interrupt_input_blocked = interrupt_input_blocked;
+#ifdef HAVE_X_WINDOWS
+ c->x_error_handler_depth = x_error_message_count;
+#endif
handlerlist = c;
return c;
}
@@ -1738,27 +1651,14 @@ process_quit_flag (void)
Lisp_Object flag = Vquit_flag;
Vquit_flag = Qnil;
if (EQ (flag, Qkill_emacs))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (EQ (Vthrow_on_input, flag))
Fthrow (Vthrow_on_input, Qt);
quit ();
}
-/* Check quit-flag and quit if it is non-nil. Typing C-g does not
- directly cause a quit; it only sets Vquit_flag. So the program
- needs to call maybe_quit at times when it is safe to quit. Every
- loop that might run for a long time or might not exit ought to call
- maybe_quit at least once, at a safe place. Unless that is
- impossible, of course. But it is very desirable to avoid creating
- loops where maybe_quit is impossible.
-
- If quit-flag is set to `kill-emacs' the SIGINT handler has received
- a request to exit Emacs when it is safe to do.
-
- When not quitting, process any pending signals. */
-
void
-maybe_quit (void)
+probably_quit (void)
{
if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
process_quit_flag ();
@@ -1831,11 +1731,12 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
&& ! NILP (error_symbol)
/* Don't try to call a lisp function if we've already overflowed
the specpdl stack. */
- && specpdl_ptr < specpdl + specpdl_size)
+ && specpdl_ptr < specpdl_end)
{
/* Edebug takes care of restoring these variables when it exits. */
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20);
- max_ensure_room (&max_specpdl_size, SPECPDL_INDEX (), 40);
+ ptrdiff_t counti = specpdl_ref_to_count (SPECPDL_INDEX ());
+ max_ensure_room (&max_specpdl_size, counti, 40);
call2 (Vsignal_hook_function, error_symbol, data);
}
@@ -1893,18 +1794,20 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
}
/* If we're in batch mode, print a backtrace unconditionally to help
- with debugging. Make sure to use `debug' unconditionally to not
- interfere with ERT or other packages that install custom
- debuggers. Don't try to call the debugger while dumping or
- bootstrapping, it wouldn't work anyway. */
+ with debugging. Make sure to use `debug-early' unconditionally
+ to not interfere with ERT or other packages that install custom
+ debuggers. */
if (!debugger_called && !NILP (error_symbol)
&& (NILP (clause) || EQ (h->tag_or_ch, Qerror))
&& noninteractive && backtrace_on_error_noninteractive
- && !will_dump_p () && !will_bootstrap_p ()
- && NILP (Vinhibit_debugger))
+ && NILP (Vinhibit_debugger)
+ && !NILP (Ffboundp (Qdebug_early)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
- specbind (Vdebugger, Qdebug);
+ max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
+ specpdl_ref count = SPECPDL_INDEX ();
+ ptrdiff_t counti = specpdl_ref_to_count (count);
+ max_ensure_room (&max_specpdl_size, counti, 200);
+ specbind (Qdebugger, Qdebug_early);
call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
unbind_to (count, Qnil);
}
@@ -2167,8 +2070,7 @@ then strings and vectors are not accepted. */)
(Lisp_Object function, Lisp_Object for_call_interactively)
{
register Lisp_Object fun;
- register Lisp_Object funcar;
- Lisp_Object if_prop = Qnil;
+ bool genfun = false; /* If true, we should consult `interactive-form'. */
fun = function;
@@ -2176,52 +2078,89 @@ then strings and vectors are not accepted. */)
if (NILP (fun))
return Qnil;
- /* Check an `interactive-form' property if present, analogous to the
- function-documentation property. */
- fun = function;
- while (SYMBOLP (fun))
- {
- Lisp_Object tmp = Fget (fun, Qinteractive_form);
- if (!NILP (tmp))
- if_prop = Qt;
- fun = Fsymbol_function (fun);
- }
-
/* Emacs primitives are interactive if their DEFUN specifies an
interactive spec. */
if (SUBRP (fun))
- return XSUBR (fun)->intspec ? Qt : if_prop;
-
+ {
+ if (XSUBR (fun)->intspec.string)
+ return Qt;
+ }
/* Bytecode objects are interactive if they are long enough to
have an element whose index is COMPILED_INTERACTIVE, which is
where the interactive spec is stored. */
else if (COMPILEDP (fun))
- return (PVSIZE (fun) > COMPILED_INTERACTIVE ? Qt : if_prop);
+ {
+ if (PVSIZE (fun) > COMPILED_INTERACTIVE)
+ return Qt;
+ else if (PVSIZE (fun) > COMPILED_DOC_STRING)
+ {
+ Lisp_Object doc = AREF (fun, COMPILED_DOC_STRING);
+ /* An invalid "docstring" is a sign that we have an OClosure. */
+ genfun = !(NILP (doc) || VALID_DOCSTRING_P (doc));
+ }
+ }
#ifdef HAVE_MODULES
/* Module functions are interactive if their `interactive_form'
field is non-nil. */
else if (MODULE_FUNCTIONP (fun))
- return NILP (module_function_interactive_form (XMODULE_FUNCTION (fun)))
- ? if_prop
- : Qt;
+ {
+ if (!NILP (module_function_interactive_form (XMODULE_FUNCTION (fun))))
+ return Qt;
+ }
#endif
/* Strings and vectors are keyboard macros. */
- if (STRINGP (fun) || VECTORP (fun))
+ else if (STRINGP (fun) || VECTORP (fun))
return (NILP (for_call_interactively) ? Qt : Qnil);
/* Lists may represent commands. */
- if (!CONSP (fun))
+ else if (!CONSP (fun))
return Qnil;
- funcar = XCAR (fun);
- if (EQ (funcar, Qclosure))
- return (!NILP (Fassq (Qinteractive, Fcdr (Fcdr (XCDR (fun)))))
- ? Qt : if_prop);
- else if (EQ (funcar, Qlambda))
- return !NILP (Fassq (Qinteractive, Fcdr (XCDR (fun)))) ? Qt : if_prop;
- else if (EQ (funcar, Qautoload))
- return !NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))) ? Qt : if_prop;
+ else
+ {
+ Lisp_Object funcar = XCAR (fun);
+ if (EQ (funcar, Qautoload))
+ {
+ if (!NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))))
+ return Qt;
+ }
+ else
+ {
+ Lisp_Object body = CDR_SAFE (XCDR (fun));
+ if (EQ (funcar, Qclosure))
+ body = CDR_SAFE (body);
+ else if (!EQ (funcar, Qlambda))
+ return Qnil;
+ if (!NILP (Fassq (Qinteractive, body)))
+ return Qt;
+ else if (VALID_DOCSTRING_P (CAR_SAFE (body)))
+ /* A "docstring" is a sign that we may have an OClosure. */
+ genfun = true;
+ }
+ }
+
+ /* By now, if it's not a function we already returned nil. */
+
+ /* Check an `interactive-form' property if present, analogous to the
+ function-documentation property. */
+ fun = function;
+ while (SYMBOLP (fun))
+ {
+ Lisp_Object tmp = Fget (fun, Qinteractive_form);
+ if (!NILP (tmp))
+ error ("Found an 'interactive-form' property!");
+ fun = Fsymbol_function (fun);
+ }
+
+ /* If there's no immediate interactive form but it's an OClosure,
+ then delegate to the generic-function in case it has
+ a type-specific interactive-form. */
+ if (genfun)
+ {
+ Lisp_Object iform = call1 (Qinteractive_form, fun);
+ return NILP (iform) ? Qnil : Qt;
+ }
else
return Qnil;
}
@@ -2256,7 +2195,7 @@ this does nothing and returns nil. */)
&& !AUTOLOADP (XSYMBOL (function)->u.s.function))
return Qnil;
- if (!NILP (Vpurify_flag) && EQ (docstring, make_fixnum (0)))
+ if (!NILP (Vpurify_flag) && BASE_EQ (docstring, make_fixnum (0)))
/* `read1' in lread.c has found the docstring starting with "\
and assumed the docstring will be provided by Snarf-documentation, so it
passed us 0 instead. But that leads to accidental sharing in purecopy's
@@ -2267,28 +2206,50 @@ this does nothing and returns nil. */)
Qnil);
}
-void
+static void
un_autoload (Lisp_Object oldqueue)
{
- Lisp_Object queue, first, second;
-
/* Queue to unwind is current value of Vautoload_queue.
oldqueue is the shadowed value to leave in Vautoload_queue. */
- queue = Vautoload_queue;
+ Lisp_Object queue = Vautoload_queue;
Vautoload_queue = oldqueue;
while (CONSP (queue))
{
- first = XCAR (queue);
- second = Fcdr (first);
- first = Fcar (first);
- if (EQ (first, make_fixnum (0)))
- Vfeatures = second;
+ Lisp_Object first = XCAR (queue);
+ if (CONSP (first) && BASE_EQ (XCAR (first), make_fixnum (0)))
+ Vfeatures = XCDR (first);
else
- Ffset (first, second);
+ Ffset (first, Fcar (Fcdr (Fget (first, Qfunction_history))));
queue = XCDR (queue);
}
}
+Lisp_Object
+load_with_autoload_queue
+ (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage,
+ Lisp_Object nosuffix, Lisp_Object must_suffix)
+{
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ /* If autoloading gets an error (which includes the error of failing
+ to define the function being called), we use Vautoload_queue
+ to undo function definitions and `provide' calls made by
+ the function. We do this in the specific case of autoloading
+ because autoloading is not an explicit request "load this file",
+ but rather a request to "call this function".
+
+ The value saved here is to be restored into Vautoload_queue. */
+ record_unwind_protect (un_autoload, Vautoload_queue);
+ Vautoload_queue = Qt;
+ Lisp_Object tem
+ = save_match_data_load (file, noerror, nomessage, nosuffix, must_suffix);
+
+ /* Once loading finishes, don't undo it. */
+ Vautoload_queue = Qt;
+ unbind_to (count, Qnil);
+ return tem;
+}
+
/* Load an autoloaded function.
FUNNAME is the symbol which is the function's name.
FUNDEF is the autoload definition (a list). */
@@ -2301,8 +2262,6 @@ If equal to `macro', MACRO-ONLY specifies that FUNDEF should only be loaded if
it defines a macro. */)
(Lisp_Object fundef, Lisp_Object funname, Lisp_Object macro_only)
{
- ptrdiff_t count = SPECPDL_INDEX ();
-
if (!CONSP (fundef) || !EQ (Qautoload, XCAR (fundef)))
return fundef;
@@ -2314,31 +2273,22 @@ it defines a macro. */)
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (will_dump_p () && !will_bootstrap_p ())
- error ("Attempt to autoload %s while preparing to dump",
- SDATA (SYMBOL_NAME (funname)));
+ {
+ /* Avoid landing here recursively while outputting the
+ backtrace from the error. */
+ gflags.will_dump_ = false;
+ error ("Attempt to autoload %s while preparing to dump",
+ SDATA (SYMBOL_NAME (funname)));
+ }
CHECK_SYMBOL (funname);
- /* If autoloading gets an error (which includes the error of failing
- to define the function being called), we use Vautoload_queue
- to undo function definitions and `provide' calls made by
- the function. We do this in the specific case of autoloading
- because autoloading is not an explicit request "load this file",
- but rather a request to "call this function".
-
- The value saved here is to be restored into Vautoload_queue. */
- record_unwind_protect (un_autoload, Vautoload_queue);
- Vautoload_queue = Qt;
/* If `macro_only' is set and fundef isn't a macro, assume this autoload to
be a "best-effort" (e.g. to try and find a compiler macro),
so don't signal an error if autoloading fails. */
Lisp_Object ignore_errors
= (EQ (kind, Qt) || EQ (kind, Qmacro)) ? Qnil : macro_only;
- save_match_data_load (Fcar (Fcdr (fundef)), ignore_errors, Qt, Qnil, Qt);
-
- /* Once loading finishes, don't undo it. */
- Vautoload_queue = Qt;
- unbind_to (count, Qnil);
+ load_with_autoload_queue (Fcar (Fcdr (fundef)), ignore_errors, Qt, Qnil, Qt);
if (NILP (funname) || !NILP (ignore_errors))
return Qnil;
@@ -2363,62 +2313,33 @@ LEXICAL can also be an actual lexical environment, in the form of an
alist mapping symbols to their value. */)
(Lisp_Object form, Lisp_Object lexical)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinternal_interpreter_environment,
CONSP (lexical) || NILP (lexical) ? lexical : list1 (Qt));
return unbind_to (count, eval_sub (form));
}
-/* Grow the specpdl stack by one entry.
- The caller should have already initialized the entry.
- Signal an error on stack overflow.
-
- Make sure that there is always one unused entry past the top of the
- stack, so that the just-initialized entry is safely unwound if
- memory exhausted and an error is signaled here. Also, allocate a
- never-used entry just before the bottom of the stack; sometimes its
- address is taken. */
-
-static void
-grow_specpdl (void)
+void
+grow_specpdl_allocation (void)
{
- specpdl_ptr++;
+ eassert (specpdl_ptr == specpdl_end);
- if (specpdl_ptr == specpdl + specpdl_size)
+ specpdl_ref count = SPECPDL_INDEX ();
+ ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000);
+ union specbinding *pdlvec = specpdl - 1;
+ ptrdiff_t size = specpdl_end - specpdl;
+ ptrdiff_t pdlvecsize = size + 1;
+ if (max_size <= size)
{
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000);
- union specbinding *pdlvec = specpdl - 1;
- ptrdiff_t pdlvecsize = specpdl_size + 1;
- if (max_size <= specpdl_size)
- {
- if (max_specpdl_size < 400)
- max_size = max_specpdl_size = 400;
- if (max_size <= specpdl_size)
- signal_error ("Variable binding depth exceeds max-specpdl-size",
- Qnil);
- }
- pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
- specpdl = pdlvec + 1;
- specpdl_size = pdlvecsize - 1;
- specpdl_ptr = specpdl + count;
+ if (max_specpdl_size < 400)
+ max_size = max_specpdl_size = 400;
+ if (max_size <= size)
+ xsignal0 (Qexcessive_variable_binding);
}
-}
-
-ptrdiff_t
-record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
-
- eassert (nargs >= UNEVALLED);
- specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
- specpdl_ptr->bt.debug_on_exit = false;
- specpdl_ptr->bt.function = function;
- current_thread->stack_top = specpdl_ptr->bt.args = args;
- specpdl_ptr->bt.nargs = nargs;
- grow_specpdl ();
-
- return count;
+ pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
+ specpdl = pdlvec + 1;
+ specpdl_end = specpdl + pdlvecsize - 1;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
}
/* Eval a sub-expression of the current expression (i.e. in the same
@@ -2450,7 +2371,7 @@ eval_sub (Lisp_Object form)
if (max_lisp_eval_depth < 100)
max_lisp_eval_depth = 100;
if (lisp_eval_depth > max_lisp_eval_depth)
- error ("Lisp nesting exceeds `max-lisp-eval-depth'");
+ xsignal0 (Qexcessive_lisp_nesting);
}
Lisp_Object original_fun = XCAR (form);
@@ -2458,7 +2379,7 @@ eval_sub (Lisp_Object form)
CHECK_LIST (original_args);
/* This also protects them from gc. */
- ptrdiff_t count
+ specpdl_ref count
= record_in_backtrace (original_fun, &original_args, UNEVALLED);
if (debug_on_next_call)
@@ -2507,13 +2428,13 @@ eval_sub (Lisp_Object form)
vals[argnum++] = eval_sub (arg);
}
- set_backtrace_args (specpdl + count, vals, argnum);
+ set_backtrace_args (specpdl_ref_to_ptr (count), vals, argnum);
val = XSUBR (fun)->function.aMANY (argnum, vals);
lisp_eval_depth--;
/* Do the debug-on-exit now, while VALS still exists. */
- if (backtrace_debug_on_exit (specpdl + count))
+ if (backtrace_debug_on_exit (specpdl_ref_to_ptr (count)))
val = call_debugger (list2 (Qexit, val));
SAFE_FREE ();
specpdl_ptr--;
@@ -2529,7 +2450,7 @@ eval_sub (Lisp_Object form)
args_left = Fcdr (args_left);
}
- set_backtrace_args (specpdl + count, argvals, numargs);
+ set_backtrace_args (specpdl_ref_to_ptr (count), argvals, numargs);
switch (i)
{
@@ -2601,7 +2522,7 @@ eval_sub (Lisp_Object form)
}
if (EQ (funcar, Qmacro))
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
Lisp_Object exp;
/* Bind lexical-binding during expansion of the macro, so the
macro can know reliably if the code it outputs will be
@@ -2633,7 +2554,7 @@ eval_sub (Lisp_Object form)
}
lisp_eval_depth--;
- if (backtrace_debug_on_exit (specpdl + count))
+ if (backtrace_debug_on_exit (specpdl_ref_to_ptr (count)))
val = call_debugger (list2 (Qexit, val));
specpdl_ptr--;
@@ -2849,7 +2770,7 @@ run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args,
sym = args[0];
val = find_symbol_value (sym);
- if (EQ (val, Qunbound) || NILP (val))
+ if (BASE_EQ (val, Qunbound) || NILP (val))
return ret;
else if (!CONSP (val) || FUNCTIONP (val))
{
@@ -2924,78 +2845,14 @@ apply1 (Lisp_Object fn, Lisp_Object arg)
return NILP (arg) ? Ffuncall (1, &fn) : CALLN (Fapply, fn, arg);
}
-/* Call function fn on no arguments. */
-Lisp_Object
-call0 (Lisp_Object fn)
-{
- return Ffuncall (1, &fn);
-}
-
-/* Call function fn with 1 argument arg1. */
-Lisp_Object
-call1 (Lisp_Object fn, Lisp_Object arg1)
-{
- return CALLN (Ffuncall, fn, arg1);
-}
-
-/* Call function fn with 2 arguments arg1, arg2. */
-Lisp_Object
-call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
-{
- return CALLN (Ffuncall, fn, arg1, arg2);
-}
-
-/* Call function fn with 3 arguments arg1, arg2, arg3. */
-Lisp_Object
-call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3);
-}
-
-/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */
-Lisp_Object
-call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4);
-}
-
-/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */
-Lisp_Object
-call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5);
-}
-
-/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */
-Lisp_Object
-call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6);
-}
-
-/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */
-Lisp_Object
-call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-}
+DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0,
+ doc: /* Return t if OBJECT is a function.
-/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5,
- arg6, arg7, arg8. */
-Lisp_Object
-call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7,
- Lisp_Object arg8)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
-}
+An object is a function if it is callable via `funcall'; this includes
+symbols with function bindings, but excludes macros and special forms.
-DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0,
- doc: /* Return t if OBJECT is a function. */)
+Ordinarily return nil if OBJECT is not a function, although t might be
+returned in rare cases. */)
(Lisp_Object object)
{
if (FUNCTIONP (object))
@@ -3034,74 +2891,74 @@ FUNCTIONP (Lisp_Object object)
return false;
}
-DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
- doc: /* Call first argument as a function, passing remaining arguments to it.
-Return the value that function returns.
-Thus, (funcall \\='cons \\='x \\='y) returns (x . y).
-usage: (funcall FUNCTION &rest ARGUMENTS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
+Lisp_Object
+funcall_general (Lisp_Object fun, ptrdiff_t numargs, Lisp_Object *args)
{
- Lisp_Object fun, original_fun;
- Lisp_Object funcar;
- ptrdiff_t numargs = nargs - 1;
- Lisp_Object val;
- ptrdiff_t count;
-
- maybe_quit ();
-
- if (++lisp_eval_depth > max_lisp_eval_depth)
- {
- if (max_lisp_eval_depth < 100)
- max_lisp_eval_depth = 100;
- if (lisp_eval_depth > max_lisp_eval_depth)
- error ("Lisp nesting exceeds `max-lisp-eval-depth'");
- }
-
- count = record_in_backtrace (args[0], &args[1], nargs - 1);
-
- maybe_gc ();
-
- if (debug_on_next_call)
- do_debug_on_call (Qlambda, count);
-
- original_fun = args[0];
-
+ Lisp_Object original_fun = fun;
retry:
-
- /* Optimize for no indirection. */
- fun = original_fun;
if (SYMBOLP (fun) && !NILP (fun)
&& (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun)))
fun = indirect_function (fun);
if (SUBRP (fun) && !SUBR_NATIVE_COMPILED_DYNP (fun))
- val = funcall_subr (XSUBR (fun), numargs, args + 1);
+ return funcall_subr (XSUBR (fun), numargs, args);
else if (COMPILEDP (fun)
|| SUBR_NATIVE_COMPILED_DYNP (fun)
|| MODULE_FUNCTIONP (fun))
- val = funcall_lambda (fun, numargs, args + 1);
+ return funcall_lambda (fun, numargs, args);
else
{
if (NILP (fun))
xsignal1 (Qvoid_function, original_fun);
if (!CONSP (fun))
xsignal1 (Qinvalid_function, original_fun);
- funcar = XCAR (fun);
+ Lisp_Object funcar = XCAR (fun);
if (!SYMBOLP (funcar))
xsignal1 (Qinvalid_function, original_fun);
if (EQ (funcar, Qlambda)
|| EQ (funcar, Qclosure))
- val = funcall_lambda (fun, numargs, args + 1);
+ return funcall_lambda (fun, numargs, args);
else if (EQ (funcar, Qautoload))
{
Fautoload_do_load (fun, original_fun, Qnil);
+ fun = original_fun;
goto retry;
}
else
xsignal1 (Qinvalid_function, original_fun);
}
+}
+
+DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
+ doc: /* Call first argument as a function, passing remaining arguments to it.
+Return the value that function returns.
+Thus, (funcall \\='cons \\='x \\='y) returns (x . y).
+usage: (funcall FUNCTION &rest ARGUMENTS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ specpdl_ref count;
+
+ maybe_quit ();
+
+ if (++lisp_eval_depth > max_lisp_eval_depth)
+ {
+ if (max_lisp_eval_depth < 100)
+ max_lisp_eval_depth = 100;
+ if (lisp_eval_depth > max_lisp_eval_depth)
+ xsignal0 (Qexcessive_lisp_nesting);
+ }
+
+ count = record_in_backtrace (args[0], &args[1], nargs - 1);
+
+ maybe_gc ();
+
+ if (debug_on_next_call)
+ do_debug_on_call (Qlambda, count);
+
+ Lisp_Object val = funcall_general (args[0], nargs - 1, args + 1);
+
lisp_eval_depth--;
- if (backtrace_debug_on_exit (specpdl + count))
+ if (backtrace_debug_on_exit (specpdl_ref_to_ptr (count)))
val = call_debugger (list2 (Qexit, val));
specpdl_ptr--;
return val;
@@ -3114,99 +2971,82 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
Lisp_Object
funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
{
- if (numargs < subr->min_args
- || (subr->max_args >= 0 && subr->max_args < numargs))
+ eassume (numargs >= 0);
+ if (numargs >= subr->min_args)
{
- Lisp_Object fun;
- XSETSUBR (fun, subr);
- xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs));
- }
+ /* Conforming call to finite-arity subr. */
+ if (numargs <= subr->max_args)
+ {
+ Lisp_Object argbuf[8];
+ Lisp_Object *a;
+ if (numargs < subr->max_args)
+ {
+ eassume (subr->max_args <= ARRAYELTS (argbuf));
+ a = argbuf;
+ memcpy (a, args, numargs * word_size);
+ memclear (a + numargs, (subr->max_args - numargs) * word_size);
+ }
+ else
+ a = args;
+ switch (subr->max_args)
+ {
+ case 0:
+ return subr->function.a0 ();
+ case 1:
+ return subr->function.a1 (a[0]);
+ case 2:
+ return subr->function.a2 (a[0], a[1]);
+ case 3:
+ return subr->function.a3 (a[0], a[1], a[2]);
+ case 4:
+ return subr->function.a4 (a[0], a[1], a[2], a[3]);
+ case 5:
+ return subr->function.a5 (a[0], a[1], a[2], a[3], a[4]);
+ case 6:
+ return subr->function.a6 (a[0], a[1], a[2], a[3], a[4], a[5]);
+ case 7:
+ return subr->function.a7 (a[0], a[1], a[2], a[3], a[4], a[5],
+ a[6]);
+ case 8:
+ return subr->function.a8 (a[0], a[1], a[2], a[3], a[4], a[5],
+ a[6], a[7]);
+ default:
+ /* If a subr takes more than 8 arguments without using MANY
+ or UNEVALLED, we need to extend this function to support it.
+ Until this is done, there is no way to call the function. */
+ emacs_abort ();
+ }
+ }
- else if (subr->max_args == UNEVALLED)
- {
- Lisp_Object fun;
- XSETSUBR (fun, subr);
- xsignal1 (Qinvalid_function, fun);
+ /* Call to n-adic subr. */
+ if (subr->max_args == MANY)
+ return subr->function.aMANY (numargs, args);
}
- else if (subr->max_args == MANY)
- return (subr->function.aMANY) (numargs, args);
+ /* Anything else is an error. */
+ Lisp_Object fun;
+ XSETSUBR (fun, subr);
+ if (subr->max_args == UNEVALLED)
+ xsignal1 (Qinvalid_function, fun);
else
- {
- Lisp_Object internal_argbuf[8];
- Lisp_Object *internal_args;
- if (subr->max_args > numargs)
- {
- eassert (subr->max_args <= ARRAYELTS (internal_argbuf));
- internal_args = internal_argbuf;
- memcpy (internal_args, args, numargs * word_size);
- memclear (internal_args + numargs,
- (subr->max_args - numargs) * word_size);
- }
- else
- internal_args = args;
- switch (subr->max_args)
- {
- case 0:
- return (subr->function.a0 ());
- case 1:
- return (subr->function.a1 (internal_args[0]));
- case 2:
- return (subr->function.a2
- (internal_args[0], internal_args[1]));
- case 3:
- return (subr->function.a3
- (internal_args[0], internal_args[1], internal_args[2]));
- case 4:
- return (subr->function.a4
- (internal_args[0], internal_args[1], internal_args[2],
- internal_args[3]));
- case 5:
- return (subr->function.a5
- (internal_args[0], internal_args[1], internal_args[2],
- internal_args[3], internal_args[4]));
- case 6:
- return (subr->function.a6
- (internal_args[0], internal_args[1], internal_args[2],
- internal_args[3], internal_args[4], internal_args[5]));
- case 7:
- return (subr->function.a7
- (internal_args[0], internal_args[1], internal_args[2],
- internal_args[3], internal_args[4], internal_args[5],
- internal_args[6]));
- case 8:
- return (subr->function.a8
- (internal_args[0], internal_args[1], internal_args[2],
- internal_args[3], internal_args[4], internal_args[5],
- internal_args[6], internal_args[7]));
-
- default:
-
- /* If a subr takes more than 8 arguments without using MANY
- or UNEVALLED, we need to extend this function to support it.
- Until this is done, there is no way to call the function. */
- emacs_abort ();
- }
- }
+ xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs));
}
/* Call the compiled Lisp function FUN. If we have not yet read FUN's
bytecode string and constants vector, fetch them from the file first. */
static Lisp_Object
-fetch_and_exec_byte_code (Lisp_Object fun, Lisp_Object syms_left,
+fetch_and_exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
ptrdiff_t nargs, Lisp_Object *args)
{
if (CONSP (AREF (fun, COMPILED_BYTECODE)))
Ffetch_bytecode (fun);
- return exec_byte_code (AREF (fun, COMPILED_BYTECODE),
- AREF (fun, COMPILED_CONSTANTS),
- AREF (fun, COMPILED_STACK_DEPTH),
- syms_left, nargs, args);
+
+ return exec_byte_code (fun, args_template, nargs, args);
}
static Lisp_Object
-apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
+apply_lambda (Lisp_Object fun, Lisp_Object args, specpdl_ref count)
{
Lisp_Object *arg_vector;
Lisp_Object tem;
@@ -3223,12 +3063,12 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
arg_vector[i] = tem;
}
- set_backtrace_args (specpdl + count, arg_vector, numargs);
+ set_backtrace_args (specpdl_ref_to_ptr (count), arg_vector, numargs);
tem = funcall_lambda (fun, numargs, arg_vector);
lisp_eval_depth--;
/* Do the debug-on-exit now, while arg_vector still exists. */
- if (backtrace_debug_on_exit (specpdl + count))
+ if (backtrace_debug_on_exit (specpdl_ref_to_ptr (count)))
tem = call_debugger (list2 (Qexit, tem));
SAFE_FREE ();
specpdl_ptr--;
@@ -3245,7 +3085,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
register Lisp_Object *arg_vector)
{
Lisp_Object val, syms_left, next, lexenv;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t i;
bool optional, rest;
@@ -3270,18 +3110,15 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
else if (COMPILEDP (fun))
{
syms_left = AREF (fun, COMPILED_ARGLIST);
+ /* Bytecode objects using lexical binding have an integral
+ ARGLIST slot value: pass the arguments to the byte-code
+ engine directly. */
if (FIXNUMP (syms_left))
- /* A byte-code object with an integer args template means we
- shouldn't bind any arguments, instead just call the byte-code
- interpreter directly; it will push arguments as necessary.
-
- Byte-code objects with a nil args template (the default)
- have dynamically-bound arguments, and use the
- argument-binding code below instead (as do all interpreted
- functions, even lexically bound ones). */
- {
- return fetch_and_exec_byte_code (fun, syms_left, nargs, arg_vector);
- }
+ return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left),
+ nargs, arg_vector);
+ /* Otherwise the bytecode object uses dynamic binding and the
+ ARGLIST slot contains a standard formal argument list whose
+ variables are bound dynamically below. */
lexenv = Qnil;
}
#ifdef HAVE_MODULES
@@ -3366,7 +3203,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
val = XSUBR (fun)->function.a0 ();
}
else
- val = fetch_and_exec_byte_code (fun, Qnil, 0, NULL);
+ val = fetch_and_exec_byte_code (fun, 0, 0, NULL);
return unbind_to (count, val);
}
@@ -3517,6 +3354,7 @@ DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
bytecode = Fstring_as_unibyte (bytecode);
}
+ pin_string (bytecode);
ASET (object, COMPILED_BYTECODE, bytecode);
ASET (object, COMPILED_CONSTANTS, XCDR (tem));
}
@@ -3607,9 +3445,6 @@ specbind (Lisp_Object symbol, Lisp_Object value)
specpdl_ptr->let.kind = SPECPDL_LET;
specpdl_ptr->let.symbol = symbol;
specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
- specpdl_ptr->let.saved_value = Qnil;
- grow_specpdl ();
- do_specbind (sym, specpdl_ptr - 1, value, SET_INTERNAL_BIND);
break;
case SYMBOL_LOCALIZED:
case SYMBOL_FORWARDED:
@@ -3619,10 +3454,9 @@ specbind (Lisp_Object symbol, Lisp_Object value)
specpdl_ptr->let.symbol = symbol;
specpdl_ptr->let.old_value = ovalue;
specpdl_ptr->let.where = Fcurrent_buffer ();
- specpdl_ptr->let.saved_value = Qnil;
eassert (sym->u.s.redirect != SYMBOL_LOCALIZED
- || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ())));
+ || (BASE_EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ())));
if (sym->u.s.redirect == SYMBOL_LOCALIZED)
{
@@ -3637,22 +3471,17 @@ specbind (Lisp_Object symbol, Lisp_Object value)
having their own value. This is consistent with what
happens with other buffer-local variables. */
if (NILP (Flocal_variable_p (symbol, Qnil)))
- {
- specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
- grow_specpdl ();
- do_specbind (sym, specpdl_ptr - 1, value, SET_INTERNAL_BIND);
- return;
- }
+ specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
}
else
specpdl_ptr->let.kind = SPECPDL_LET;
- grow_specpdl ();
- do_specbind (sym, specpdl_ptr - 1, value, SET_INTERNAL_BIND);
break;
}
default: emacs_abort ();
}
+ grow_specpdl ();
+ do_specbind (sym, specpdl_ptr - 1, value, SET_INTERNAL_BIND);
}
/* Push unwind-protect entries of various types. */
@@ -3682,6 +3511,20 @@ record_unwind_protect_ptr (void (*function) (void *), void *arg)
specpdl_ptr->unwind_ptr.kind = SPECPDL_UNWIND_PTR;
specpdl_ptr->unwind_ptr.func = function;
specpdl_ptr->unwind_ptr.arg = arg;
+ specpdl_ptr->unwind_ptr.mark = NULL;
+ grow_specpdl ();
+}
+
+/* Like `record_unwind_protect_ptr', but also specifies a function
+ for GC-marking Lisp objects only reachable through ARG. */
+void
+record_unwind_protect_ptr_mark (void (*function) (void *), void *arg,
+ void (*mark) (void *))
+{
+ specpdl_ptr->unwind_ptr.kind = SPECPDL_UNWIND_PTR;
+ specpdl_ptr->unwind_ptr.func = function;
+ specpdl_ptr->unwind_ptr.arg = arg;
+ specpdl_ptr->unwind_ptr.mark = mark;
grow_specpdl ();
}
@@ -3725,27 +3568,10 @@ record_unwind_protect_module (enum specbind_tag kind, void *ptr)
specpdl_ptr->kind = kind;
specpdl_ptr->unwind_ptr.func = NULL;
specpdl_ptr->unwind_ptr.arg = ptr;
+ specpdl_ptr->unwind_ptr.mark = NULL;
grow_specpdl ();
}
-void
-rebind_for_thread_switch (void)
-{
- union specbinding *bind;
-
- for (bind = specpdl; bind != specpdl_ptr; ++bind)
- {
- if (bind->kind >= SPECPDL_LET)
- {
- Lisp_Object value = specpdl_saved_value (bind);
- Lisp_Object sym = specpdl_symbol (bind);
- bind->let.saved_value = Qnil;
- do_specbind (XSYMBOL (sym), bind, value,
- SET_INTERNAL_THREAD_SWITCH);
- }
- }
-}
-
static void
do_one_unbind (union specbinding *this_binding, bool unwinding,
enum Set_Internal_Bind bindflag)
@@ -3777,6 +3603,7 @@ do_one_unbind (union specbinding *this_binding, bool unwinding,
this_binding->unwind_excursion.window);
break;
case SPECPDL_BACKTRACE:
+ case SPECPDL_NOP:
break;
#ifdef HAVE_MODULES
case SPECPDL_MODULE_RUNTIME:
@@ -3841,9 +3668,9 @@ record_unwind_protect_nothing (void)
It need not be at the top of the stack. */
void
-clear_unwind_protect (ptrdiff_t count)
+clear_unwind_protect (specpdl_ref count)
{
- union specbinding *p = specpdl + count;
+ union specbinding *p = specpdl_ref_to_ptr (count);
p->unwind_void.kind = SPECPDL_UNWIND_VOID;
p->unwind_void.func = do_nothing;
}
@@ -3853,10 +3680,10 @@ clear_unwind_protect (ptrdiff_t count)
previous value without invoking it. */
void
-set_unwind_protect (ptrdiff_t count, void (*func) (Lisp_Object),
+set_unwind_protect (specpdl_ref count, void (*func) (Lisp_Object),
Lisp_Object arg)
{
- union specbinding *p = specpdl + count;
+ union specbinding *p = specpdl_ref_to_ptr (count);
p->unwind.kind = SPECPDL_UNWIND;
p->unwind.func = func;
p->unwind.arg = arg;
@@ -3864,25 +3691,26 @@ set_unwind_protect (ptrdiff_t count, void (*func) (Lisp_Object),
}
void
-set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg)
+set_unwind_protect_ptr (specpdl_ref count, void (*func) (void *), void *arg)
{
- union specbinding *p = specpdl + count;
+ union specbinding *p = specpdl_ref_to_ptr (count);
p->unwind_ptr.kind = SPECPDL_UNWIND_PTR;
p->unwind_ptr.func = func;
p->unwind_ptr.arg = arg;
+ p->unwind_ptr.mark = NULL;
}
/* Pop and execute entries from the unwind-protect stack until the
depth COUNT is reached. Return VALUE. */
Lisp_Object
-unbind_to (ptrdiff_t count, Lisp_Object value)
+unbind_to (specpdl_ref count, Lisp_Object value)
{
Lisp_Object quitf = Vquit_flag;
Vquit_flag = Qnil;
- while (specpdl_ptr != specpdl + count)
+ while (specpdl_ptr != specpdl_ref_to_ptr (count))
{
/* Copy the binding, and decrement specpdl_ptr, before we do
the work to unbind it. We decrement first
@@ -3902,22 +3730,6 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
return value;
}
-void
-unbind_for_thread_switch (struct thread_state *thr)
-{
- union specbinding *bind;
-
- for (bind = thr->m_specpdl_ptr; bind > thr->m_specpdl;)
- {
- if ((--bind)->kind >= SPECPDL_LET)
- {
- Lisp_Object sym = specpdl_symbol (bind);
- bind->let.saved_value = find_symbol_value (sym);
- do_one_unbind (bind, false, SET_INTERNAL_THREAD_SWITCH);
- }
- }
-}
-
DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0,
doc: /* Return non-nil if SYMBOL's global binding has been declared special.
A special variable is one that will be bound dynamically, even in a
@@ -4073,11 +3885,13 @@ or a lambda expression for macro calls. */)
value and the old value stored in the specpdl), kind of like the inplace
pointer-reversal trick. As it turns out, the rewind does the same as the
unwind, except it starts from the other end of the specpdl stack, so we use
- the same function for both unwind and rewind. */
-static void
-backtrace_eval_unrewind (int distance)
+ the same function for both unwind and rewind.
+ This same code is used when switching threads, except in that case
+ we unwind/rewind the whole specpdl of the threads. */
+void
+specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only)
{
- union specbinding *tmp = specpdl_ptr;
+ union specbinding *tmp = pdl;
int step = -1;
if (distance < 0)
{ /* It's a rewind rather than unwind. */
@@ -4095,6 +3909,8 @@ backtrace_eval_unrewind (int distance)
unwind_protect, but the problem is that we don't know how to
rewind them afterwards. */
case SPECPDL_UNWIND:
+ if (vars_only)
+ break;
if (tmp->unwind.func == set_buffer_if_live)
{
Lisp_Object oldarg = tmp->unwind.arg;
@@ -4103,6 +3919,8 @@ backtrace_eval_unrewind (int distance)
}
break;
case SPECPDL_UNWIND_EXCURSION:
+ if (vars_only)
+ break;
{
Lisp_Object marker = tmp->unwind_excursion.marker;
Lisp_Object window = tmp->unwind_excursion.window;
@@ -4110,17 +3928,6 @@ backtrace_eval_unrewind (int distance)
save_excursion_restore (marker, window);
}
break;
- case SPECPDL_UNWIND_ARRAY:
- case SPECPDL_UNWIND_PTR:
- case SPECPDL_UNWIND_INT:
- case SPECPDL_UNWIND_INTMAX:
- case SPECPDL_UNWIND_VOID:
- case SPECPDL_BACKTRACE:
-#ifdef HAVE_MODULES
- case SPECPDL_MODULE_RUNTIME:
- case SPECPDL_MODULE_ENVIRONMENT:
-#endif
- break;
case SPECPDL_LET:
{ /* If variable has a trivial value (no forwarding), we can
just set it. No need to check for constant symbols here,
@@ -4143,7 +3950,7 @@ backtrace_eval_unrewind (int distance)
Lisp_Object sym = specpdl_symbol (tmp);
Lisp_Object old_value = specpdl_old_value (tmp);
set_specpdl_old_value (tmp, default_value (sym));
- Fset_default (sym, old_value);
+ set_default_internal (sym, old_value, SET_INTERNAL_THREAD_SWITCH);
}
break;
case SPECPDL_LET_LOCAL:
@@ -4159,21 +3966,37 @@ backtrace_eval_unrewind (int distance)
{
set_specpdl_old_value
(tmp, buffer_local_value (symbol, where));
- set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
+ set_internal (symbol, old_value, where,
+ SET_INTERNAL_THREAD_SWITCH);
}
+ else
+ /* If the var is not local any more, it can't be undone nor
+ redone, so just zap it.
+ This is important in case the buffer re-gains a local value
+ before we unrewind again, in which case we'd risk applying
+ this entry in the wrong direction. */
+ tmp->kind = SPECPDL_NOP;
}
break;
+
+ default: break;
}
}
}
+static void
+backtrace_eval_unrewind (int distance)
+{
+ specpdl_unrewind (specpdl_ptr, distance, false);
+}
+
DEFUN ("backtrace-eval", Fbacktrace_eval, Sbacktrace_eval, 2, 3, NULL,
doc: /* Evaluate EXP in the context of some activation frame.
NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'. */)
(Lisp_Object exp, Lisp_Object nframes, Lisp_Object base)
{
union specbinding *pdl = get_backtrace_frame (nframes, base);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t distance = specpdl_ptr - pdl;
eassert (distance >= 0);
@@ -4247,22 +4070,7 @@ NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'.
}
break;
- case SPECPDL_UNWIND:
- case SPECPDL_UNWIND_ARRAY:
- case SPECPDL_UNWIND_PTR:
- case SPECPDL_UNWIND_INT:
- case SPECPDL_UNWIND_INTMAX:
- case SPECPDL_UNWIND_EXCURSION:
- case SPECPDL_UNWIND_VOID:
- case SPECPDL_BACKTRACE:
-#ifdef HAVE_MODULES
- case SPECPDL_MODULE_RUNTIME:
- case SPECPDL_MODULE_ENVIRONMENT:
-#endif
- break;
-
- default:
- emacs_abort ();
+ default: break;
}
}
}
@@ -4320,15 +4128,22 @@ mark_specpdl (union specbinding *first, union specbinding *ptr)
case SPECPDL_LET:
mark_object (specpdl_symbol (pdl));
mark_object (specpdl_old_value (pdl));
- mark_object (specpdl_saved_value (pdl));
break;
case SPECPDL_UNWIND_PTR:
+ if (pdl->unwind_ptr.mark)
+ pdl->unwind_ptr.mark (pdl->unwind_ptr.arg);
+ break;
+
case SPECPDL_UNWIND_INT:
case SPECPDL_UNWIND_INTMAX:
case SPECPDL_UNWIND_VOID:
+ case SPECPDL_NOP:
break;
+ /* While other loops that scan the specpdl use "default: break;"
+ for simplicity, here we explicitly list all cases and abort
+ if we find an unexpected value, as a sanity check. */
default:
emacs_abort ();
}
@@ -4422,6 +4237,7 @@ before making `inhibit-quit' nil. */);
DEFSYM (Qclosure, "closure");
DEFSYM (QCdocumentation, ":documentation");
DEFSYM (Qdebug, "debug");
+ DEFSYM (Qdebug_early, "debug-early");
DEFVAR_LISP ("inhibit-debugger", Vinhibit_debugger,
doc: /* Non-nil means never enter the debugger.
@@ -4468,6 +4284,7 @@ might not be safe to continue. */);
doc: /* Non-nil means display call stack frames as lists. */);
debugger_stack_frame_as_list = 0;
+ DEFSYM (Qdebugger, "debugger");
DEFVAR_LISP ("debugger", Vdebugger,
doc: /* Function to call to invoke debugger.
If due to frame exit, args are `exit' and the value being returned;
@@ -4475,7 +4292,7 @@ If due to frame exit, args are `exit' and the value being returned;
If due to error, args are `error' and a list of the args to `signal'.
If due to `apply' or `funcall' entry, one arg, `lambda'.
If due to `eval' entry, one arg, t. */);
- Vdebugger = Qnil;
+ Vdebugger = Qdebug_early;
DEFVAR_LISP ("signal-hook-function", Vsignal_hook_function,
doc: /* If non-nil, this is a function for `signal' to call.
@@ -4557,9 +4374,11 @@ alist of active lexical bindings. */);
defsubr (&Sdefault_toplevel_value);
defsubr (&Sset_default_toplevel_value);
defsubr (&Sdefvar);
+ defsubr (&Sdefvar_1);
defsubr (&Sdefvaralias);
DEFSYM (Qdefvaralias, "defvaralias");
defsubr (&Sdefconst);
+ defsubr (&Sdefconst_1);
defsubr (&Sinternal__define_uninitialized_variable);
defsubr (&Smake_var_non_special);
defsubr (&Slet);
diff --git a/src/fileio.c b/src/fileio.c
index 9c50cbb35a6..9697f6c8cf1 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -708,20 +708,20 @@ This function does not grok magic file names. */)
memset (data + prefix_len, 'X', nX);
memcpy (data + prefix_len + nX, SSDATA (encoded_suffix), suffix_len);
int kind = (NILP (dir_flag) ? GT_FILE
- : EQ (dir_flag, make_fixnum (0)) ? GT_NOCREATE
+ : BASE_EQ (dir_flag, make_fixnum (0)) ? GT_NOCREATE
: GT_DIR);
int fd = gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind);
bool failed = fd < 0;
if (!failed)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, fd);
val = DECODE_FILE (val);
if (STRINGP (text) && SBYTES (text) != 0)
write_region (text, Qnil, val, Qnil, Qnil, Qnil, Qnil, fd);
failed = NILP (dir_flag) && emacs_close (fd) != 0;
/* Discard the unwind protect. */
- specpdl_ptr = specpdl + count;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
}
if (failed)
{
@@ -2165,7 +2165,7 @@ permissions. */)
Lisp_Object preserve_permissions)
{
Lisp_Object handler;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object encoded_file, encoded_newname;
#if HAVE_LIBSELINUX
char *con;
@@ -2416,7 +2416,7 @@ permissions. */)
#endif /* not WINDOWSNT */
/* Discard the unwind protects. */
- specpdl_ptr = specpdl + count;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
return Qnil;
}
@@ -2505,6 +2505,8 @@ With a prefix argument, TRASH is nil. */)
return Qnil;
}
+#if defined HAVE_NATIVE_COMP && defined WINDOWSNT
+
static Lisp_Object
internal_delete_file_1 (Lisp_Object ignore)
{
@@ -2523,6 +2525,8 @@ internal_delete_file (Lisp_Object filename)
Qt, internal_delete_file_1);
return NILP (tem);
}
+
+#endif
/* Return -1 if FILE is a case-insensitive file name, 0 if not,
and a positive errno value if the result cannot be determined. */
@@ -2597,9 +2601,9 @@ is case-insensitive. */)
if (err <= 0)
return err < 0 ? Qt : Qnil;
Lisp_Object parent = file_name_directory (filename);
- /* Avoid infinite loop if the root has trouble
- (impossible?). */
- if (!NILP (Fstring_equal (parent, filename)))
+ /* Avoid infinite loop if the root has trouble (if that's even possible).
+ Without a parent, we just don't know and return nil as well. */
+ if (!STRINGP (parent) || !NILP (Fstring_equal (parent, filename)))
return Qnil;
filename = parent;
}
@@ -2714,11 +2718,25 @@ This is what happens in interactive use with M-x. */)
: Qnil);
if (!NILP (symlink_target))
Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
+ else if (S_ISFIFO (file_st.st_mode))
+ {
+ /* If it's a FIFO, calling `copy-file' will hang if it's a
+ inter-file system move, so do it here. (It will signal
+ an error in that case, but it won't hang in any case.) */
+ if (!NILP (ok_if_already_exists))
+ barf_or_query_if_file_exists (newname, false,
+ "rename to it",
+ FIXNUMP (ok_if_already_exists),
+ false);
+ if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) != 0)
+ report_file_errno ("Renaming", list2 (file, newname), errno);
+ return Qnil;
+ }
else
Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt);
}
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qdelete_by_moving_to_trash, Qnil);
if (dirp)
call2 (Qdelete_directory, file, Qt);
@@ -3514,8 +3532,9 @@ DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 3,
Only the 12 low bits of MODE are used. If optional FLAG is `nofollow',
do not follow FILENAME if it is a symbolic link.
-Interactively, mode bits are read by `read-file-modes', which accepts
-symbolic notation, like the `chmod' command from GNU Coreutils. */)
+Interactively, prompt for FILENAME, and read MODE with
+`read-file-modes', which accepts symbolic notation, like the `chmod'
+command from GNU Coreutils. */)
(Lisp_Object filename, Lisp_Object mode, Lisp_Object flag)
{
CHECK_FIXNUM (mode);
@@ -3880,6 +3899,10 @@ The optional third and fourth arguments BEG and END specify what portion
of the file to insert. These arguments count bytes in the file, not
characters in the buffer. If VISIT is non-nil, BEG and END must be nil.
+When inserting data from a special file (e.g., /dev/urandom), you
+can't specify VISIT or BEG, and END should be specified to avoid
+inserting unlimited data into the buffer.
+
If optional fifth argument REPLACE is non-nil, replace the current
buffer contents (in the accessible portion) with the file contents.
This is better than simply deleting and inserting the whole thing
@@ -3903,11 +3926,11 @@ by calling `format-decode', which see. */)
ptrdiff_t how_much;
off_t beg_offset, end_offset;
int unprocessed;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object handler, val, insval, orig_filename, old_undo;
Lisp_Object p;
ptrdiff_t total = 0;
- bool not_regular = 0;
+ bool regular = true;
int save_errno = 0;
char read_buf[READ_BUF_SIZE];
struct coding_system coding;
@@ -3922,7 +3945,6 @@ by calling `format-decode', which see. */)
&& BEG == Z);
Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
bool we_locked_file = false;
- ptrdiff_t fd_index;
Lisp_Object window_markers = Qnil;
/* same_at_start and same_at_end count bytes, because file access counts
bytes and BEG and END count bytes. */
@@ -3931,6 +3953,7 @@ by calling `format-decode', which see. */)
/* SAME_AT_END_CHARPOS counts characters, because
restore_window_points needs the old character count. */
ptrdiff_t same_at_end_charpos = ZV;
+ bool seekable = true;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
@@ -3984,7 +4007,7 @@ by calling `format-decode', which see. */)
goto notfound;
}
- fd_index = SPECPDL_INDEX ();
+ specpdl_ref fd_index = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, fd);
/* Replacement should preserve point as it preserves markers. */
@@ -4004,7 +4027,8 @@ by calling `format-decode', which see. */)
least signal an error. */
if (!S_ISREG (st.st_mode))
{
- not_regular = 1;
+ regular = false;
+ seekable = lseek (fd, 0, SEEK_CUR) < 0;
if (! NILP (visit))
{
@@ -4012,7 +4036,12 @@ by calling `format-decode', which see. */)
goto notfound;
}
- if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
+ if (!NILP (beg) && !seekable)
+ xsignal2 (Qfile_error,
+ build_string ("cannot use a start position in a non-seekable file/device"),
+ orig_filename);
+
+ if (!NILP (replace))
xsignal2 (Qfile_error,
build_string ("not a regular file"), orig_filename);
}
@@ -4034,7 +4063,7 @@ by calling `format-decode', which see. */)
end_offset = file_offset (end);
else
{
- if (not_regular)
+ if (!regular)
end_offset = TYPE_MAXIMUM (off_t);
else
{
@@ -4056,7 +4085,7 @@ by calling `format-decode', which see. */)
/* Check now whether the buffer will become too large,
in the likely case where the file's length is not changing.
This saves a lot of needless work before a buffer overflow. */
- if (! not_regular)
+ if (regular)
{
/* The likely offset where we will stop reading. We could read
more (or less), if the file grows (or shrinks) as we read it. */
@@ -4094,7 +4123,7 @@ by calling `format-decode', which see. */)
{
/* Don't try looking inside a file for a coding system
specification if it is not seekable. */
- if (! not_regular && ! NILP (Vset_auto_coding_function))
+ if (regular && !NILP (Vset_auto_coding_function))
{
/* Find a coding system specified in the heading two
lines or in the tailing several lines of the file.
@@ -4327,7 +4356,7 @@ by calling `format-decode', which see. */)
if (! giveup_match_end)
{
ptrdiff_t temp;
- ptrdiff_t this_count = SPECPDL_INDEX ();
+ specpdl_ref this_count = SPECPDL_INDEX ();
/* We win! We can handle REPLACE the optimized way. */
@@ -4398,7 +4427,7 @@ by calling `format-decode', which see. */)
unsigned char *decoded;
ptrdiff_t temp;
ptrdiff_t this = 0;
- ptrdiff_t this_count = SPECPDL_INDEX ();
+ specpdl_ref this_count = SPECPDL_INDEX ();
bool multibyte
= ! NILP (BVAR (current_buffer, enable_multibyte_characters));
Lisp_Object conversion_buffer;
@@ -4556,7 +4585,7 @@ by calling `format-decode', which see. */)
goto handled;
}
- if (! not_regular)
+ if (seekable || !NILP (end))
total = end_offset - beg_offset;
else
/* For a special file, all we can do is guess. */
@@ -4602,7 +4631,7 @@ by calling `format-decode', which see. */)
ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE);
ptrdiff_t this;
- if (not_regular)
+ if (!seekable && NILP (end))
{
Lisp_Object nbytes;
@@ -4653,7 +4682,7 @@ by calling `format-decode', which see. */)
For a special file, where TOTAL is just a buffer size,
so don't bother counting in HOW_MUCH.
(INSERTED is where we count the number of characters inserted.) */
- if (! not_regular)
+ if (seekable || !NILP (end))
how_much += this;
inserted += this;
}
@@ -4704,7 +4733,7 @@ by calling `format-decode', which see. */)
= Fcons (multibyte,
Fcons (BVAR (current_buffer, undo_list),
Fcurrent_buffer ()));
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
bset_enable_multibyte_characters (current_buffer, Qnil);
bset_undo_list (current_buffer, Qt);
@@ -4831,7 +4860,7 @@ by calling `format-decode', which see. */)
Funlock_file (BVAR (current_buffer, file_truename));
Funlock_file (filename);
}
- if (not_regular)
+ if (!regular)
xsignal2 (Qfile_error,
build_string ("not a regular file"), orig_filename);
}
@@ -4855,7 +4884,7 @@ by calling `format-decode', which see. */)
if (inserted > 0)
{
/* Don't run point motion or modification hooks when decoding. */
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
ptrdiff_t old_inserted = inserted;
specbind (Qinhibit_point_motion_hooks, Qt);
specbind (Qinhibit_modification_hooks, Qt);
@@ -5186,8 +5215,8 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
const char *fn;
struct stat st;
struct timespec modtime;
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t count1 UNINIT;
+ specpdl_ref count = SPECPDL_INDEX ();
+ specpdl_ref count1 UNINIT;
Lisp_Object handler;
Lisp_Object visit_file;
Lisp_Object annotations;
@@ -5390,7 +5419,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
ok = 0, save_errno = errno;
/* Discard the unwind protect for close_file_unwind. */
- specpdl_ptr = specpdl + count1;
+ specpdl_ptr = specpdl_ref_to_ptr (count1);
}
/* Some file systems have a bug where st_mtime is not updated
@@ -5520,7 +5549,10 @@ DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
doc: /* Return t if (car A) is numerically less than (car B). */)
(Lisp_Object a, Lisp_Object b)
{
- return arithcompare (Fcar (a), Fcar (b), ARITH_LESS);
+ Lisp_Object ca = Fcar (a), cb = Fcar (b);
+ if (FIXNUMP (ca) && FIXNUMP (cb))
+ return XFIXNUM (ca) < XFIXNUM (cb) ? Qt : Qnil;
+ return arithcompare (ca, cb, ARITH_LESS);
}
/* Build the complete list of annotations appropriate for writing out
@@ -5800,6 +5832,15 @@ See Info node `(elisp)Modification Time' for more details. */)
return Qnil;
}
+Lisp_Object
+buffer_visited_file_modtime (struct buffer *buf)
+{
+ int ns = buf->modtime.tv_nsec;
+ if (ns < 0)
+ return make_fixnum (UNKNOWN_MODTIME_NSECS - ns);
+ return make_lisp_time (buf->modtime);
+}
+
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
Svisited_file_modtime, 0, 0, 0,
doc: /* Return the current buffer's recorded visited file modification time.
@@ -5809,10 +5850,7 @@ visited file doesn't exist.
See Info node `(elisp)Modification Time' for more details. */)
(void)
{
- int ns = current_buffer->modtime.tv_nsec;
- if (ns < 0)
- return make_fixnum (UNKNOWN_MODTIME_NSECS - ns);
- return make_lisp_time (current_buffer->modtime);
+ return buffer_visited_file_modtime (current_buffer);
}
DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5839,6 +5877,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */)
current_buffer->modtime = mtime;
current_buffer->modtime_size = -1;
}
+ else if (current_buffer->base_buffer)
+ error ("An indirect buffer does not have a visited file");
else
{
register Lisp_Object filename;
@@ -5952,14 +5992,19 @@ do_auto_save_eh (Lisp_Object ignore)
DEFUN ("do-auto-save", Fdo_auto_save, Sdo_auto_save, 0, 2, "",
doc: /* Auto-save all buffers that need it.
-This is all buffers that have auto-saving enabled
-and are changed since last auto-saved.
-Auto-saving writes the buffer into a file
-so that your editing is not lost if the system crashes.
-This file is not the file you visited; that changes only when you save.
+This auto-saves all buffers that have auto-saving enabled and
+were changed since last auto-saved.
+
+Auto-saving writes the buffer into a file so that your edits are
+not lost if the system crashes.
+
+The auto-save file is not the file you visited; that changes only
+when you save.
+
Normally, run the normal hook `auto-save-hook' before saving.
A non-nil NO-MESSAGE argument means do not print any message if successful.
+
A non-nil CURRENT-ONLY argument means save only current buffer. */)
(Lisp_Object no_message, Lisp_Object current_only)
{
@@ -5969,12 +6014,13 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
int do_handled_files;
Lisp_Object oquit;
FILE *stream = NULL;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool orig_minibuffer_auto_raise = minibuffer_auto_raise;
bool old_message_p = 0;
struct auto_save_unwind auto_save_unwind;
- intmax_t sum = INT_ADD_WRAPV (specpdl_size, 40, &sum) ? INTMAX_MAX : sum;
+ intmax_t sum = INT_ADD_WRAPV (specpdl_end - specpdl, 40, &sum)
+ ? INTMAX_MAX : sum;
if (max_specpdl_size < sum)
max_specpdl_size = sum;
diff --git a/src/filelock.c b/src/filelock.c
index a213c2b3cae..a657cc4582c 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -413,14 +413,20 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
Return 0 if successful, an error number on failure. */
static int
-lock_file_1 (char *lfname, bool force)
+lock_file_1 (Lisp_Object lfname, bool force)
{
- /* Call this first because it can GC. */
intmax_t boot = get_boot_time ();
-
Lisp_Object luser_name = Fuser_login_name (Qnil);
- char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
Lisp_Object lhost_name = Fsystem_name ();
+
+ /* Protect against the extremely unlikely case of the host name
+ containing an @ character. */
+ if (!NILP (lhost_name) && strchr (SSDATA (lhost_name), '@'))
+ lhost_name = CALLN (Ffuncall, intern ("string-replace"),
+ build_string ("@"), build_string ("-"),
+ lhost_name);
+
+ char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : "";
char lock_info_str[MAX_LFINFO + 1];
intmax_t pid = getpid ();
@@ -439,7 +445,7 @@ lock_file_1 (char *lfname, bool force)
user_name, host_name, pid))
return ENAMETOOLONG;
- return create_lock_file (lfname, lock_info_str, force);
+ return create_lock_file (SSDATA (lfname), lock_info_str, force);
}
/* Return true if times A and B are no more than one second apart. */
@@ -490,15 +496,29 @@ read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
return nbytes;
}
+/* True if errno values are negative. Although the C standard
+ requires them to be positive, they are negative in Haiku. */
+enum { NEGATIVE_ERRNO = EDOM < 0 };
+
+/* Nonzero values that are not errno values. */
+enum
+ {
+ /* Another process on this machine owns it. */
+ ANOTHER_OWNS_IT = NEGATIVE_ERRNO ? 1 : -1,
+
+ /* This Emacs process owns it. */
+ I_OWN_IT = 2 * ANOTHER_OWNS_IT
+ };
+
/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
- -1 if another process owns it (and set OWNER (if non-null) to info),
- -2 if the current process owns it,
+ ANOTHER_OWNS_IT if another process owns it
+ (and set OWNER (if non-null) to info),
+ I_OWN_IT if the current process owns it,
or an errno value if something is wrong with the locking mechanism. */
static int
-current_lock_owner (lock_info_type *owner, char *lfname)
+current_lock_owner (lock_info_type *owner, Lisp_Object lfname)
{
- int ret;
lock_info_type local_owner;
ptrdiff_t lfinfolen;
intmax_t pid, boot_time;
@@ -510,7 +530,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
owner = &local_owner;
/* If nonexistent lock file, all is well; otherwise, got strange error. */
- lfinfolen = read_lock_data (lfname, owner->user);
+ lfinfolen = read_lock_data (SSDATA (lfname), owner->user);
if (lfinfolen < 0)
return errno == ENOENT || errno == ENOTDIR ? 0 : errno;
if (MAX_LFINFO < lfinfolen)
@@ -564,65 +584,78 @@ current_lock_owner (lock_info_type *owner, char *lfname)
if (lfinfo_end != owner->user + lfinfolen)
return EINVAL;
- /* On current host? */
Lisp_Object system_name = Fsystem_name ();
+ /* If `system-name' returns nil, that means we're in a
+ --no-build-details Emacs, and the name part of the link (e.g.,
+ .#test.txt -> larsi@.118961:1646577954) is an empty string. */
+ if (NILP (system_name))
+ system_name = build_string ("");
+ /* Protect against the extremely unlikely case of the host name
+ containing an @ character. */
+ else if (strchr (SSDATA (system_name), '@'))
+ system_name = CALLN (Ffuncall, intern ("string-replace"),
+ build_string ("@"), build_string ("-"),
+ system_name);
+ /* On current host? */
if (STRINGP (system_name)
&& dot - (at + 1) == SBYTES (system_name)
&& memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0)
{
if (pid == getpid ())
- ret = -2; /* We own it. */
+ return I_OWN_IT;
else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
&& (kill (pid, 0) >= 0 || errno == EPERM)
&& (boot_time == 0
|| (boot_time <= TYPE_MAXIMUM (time_t)
&& within_one_second (boot_time, get_boot_time ()))))
- ret = -1; /* An existing process on this machine owns it. */
+ return ANOTHER_OWNS_IT;
/* The owner process is dead or has a strange pid, so try to
zap the lockfile. */
else
- return unlink (lfname) < 0 ? errno : 0;
+ return unlink (SSDATA (lfname)) < 0 ? errno : 0;
}
else
{ /* If we wanted to support the check for stale locks on remote machines,
here's where we'd do it. */
- ret = -1;
+ return ANOTHER_OWNS_IT;
}
-
- return ret;
}
/* Lock the lock named LFNAME if possible.
Return 0 in that case.
- Return negative if some other process owns the lock, and info about
+ Return ANOTHER_OWNS_IT if some other process owns the lock, and info about
that process in CLASHER.
- Return positive errno value if cannot lock for any other reason. */
+ Return errno value if cannot lock for any other reason. */
static int
-lock_if_free (lock_info_type *clasher, char *lfname)
+lock_if_free (lock_info_type *clasher, Lisp_Object lfname)
{
int err;
while ((err = lock_file_1 (lfname, 0)) == EEXIST)
{
err = current_lock_owner (clasher, lfname);
+
+ /* Return if we locked it, or another process owns it, or it is
+ a strange error. */
if (err != 0)
- {
- if (err < 0)
- return -2 - err; /* We locked it, or someone else has it. */
- break; /* current_lock_owner returned strange error. */
- }
+ return err == I_OWN_IT ? 0 : err;
- /* We deleted a stale lock; try again to lock the file. */
+ /* We deleted a stale lock or some other process deleted the lock;
+ try again to lock the file. */
}
return err;
}
+/* Return the encoded name of the lock file for FN, or nil if none. */
+
static Lisp_Object
make_lock_file_name (Lisp_Object fn)
{
- return call1 (Qmake_lock_file_name, Fexpand_file_name (fn, Qnil));
+ Lisp_Object lock_file_name = call1 (Qmake_lock_file_name,
+ Fexpand_file_name (fn, Qnil));
+ return !NILP (lock_file_name) ? ENCODE_FILE (lock_file_name) : Qnil;
}
/* lock_file locks file FN,
@@ -654,47 +687,46 @@ lock_file (Lisp_Object fn)
if (will_dump_p ())
return Qnil;
- /* If the file name has special constructs in it,
- call the corresponding file name handler. */
- Lisp_Object handler;
- handler = Ffind_file_name_handler (fn, Qlock_file);
- if (!NILP (handler))
+ Lisp_Object lfname = Qnil;
+ if (create_lockfiles)
{
- return call2 (handler, Qlock_file, fn);
+ /* Create the name of the lock-file for file fn */
+ lfname = make_lock_file_name (fn);
+ if (NILP (lfname))
+ return Qnil;
}
- Lisp_Object lock_filename = make_lock_file_name (fn);
- if (NILP (lock_filename))
- return Qnil;
- char *lfname = SSDATA (ENCODE_FILE (lock_filename));
-
/* See if this file is visited and has changed on disk since it was
visited. */
Lisp_Object subject_buf = get_truename_buffer (fn);
if (!NILP (subject_buf)
&& NILP (Fverify_visited_file_modtime (subject_buf))
&& !NILP (Ffile_exists_p (fn))
- && current_lock_owner (NULL, lfname) != -2)
+ && !(!NILP (lfname) && current_lock_owner (NULL, lfname) == I_OWN_IT))
call1 (intern ("userlock--ask-user-about-supersession-threat"), fn);
- /* Try to lock the lock. FIXME: This ignores errors when
- lock_if_free returns a positive errno value. */
- if (lock_if_free (&lock_info, lfname) < 0)
+ /* Don't do locking if the user has opted out. */
+ if (!NILP (lfname))
{
- /* Someone else has the lock. Consider breaking it. */
- Lisp_Object attack;
- char *dot = lock_info.dot;
- ptrdiff_t pidlen = lock_info.colon - (dot + 1);
- static char const replacement[] = " (pid ";
- int replacementlen = sizeof replacement - 1;
- memmove (dot + replacementlen, dot + 1, pidlen);
- strcpy (dot + replacementlen + pidlen, ")");
- memcpy (dot, replacement, replacementlen);
- attack = call2 (intern ("ask-user-about-lock"), fn,
- build_string (lock_info.user));
- /* Take the lock if the user said so. */
- if (!NILP (attack))
- lock_file_1 (lfname, 1);
+ /* Try to lock the lock. FIXME: This ignores errors when
+ lock_if_free returns an errno value. */
+ if (lock_if_free (&lock_info, lfname) == ANOTHER_OWNS_IT)
+ {
+ /* Someone else has the lock. Consider breaking it. */
+ Lisp_Object attack;
+ char *dot = lock_info.dot;
+ ptrdiff_t pidlen = lock_info.colon - (dot + 1);
+ static char const replacement[] = " (pid ";
+ int replacementlen = sizeof replacement - 1;
+ memmove (dot + replacementlen, dot + 1, pidlen);
+ strcpy (dot + replacementlen + pidlen, ")");
+ memcpy (dot, replacement, replacementlen);
+ attack = call2 (intern ("ask-user-about-lock"), fn,
+ build_string (lock_info.user));
+ /* Take the lock if the user said so. */
+ if (!NILP (attack))
+ lock_file_1 (lfname, 1);
+ }
}
return Qnil;
}
@@ -702,17 +734,14 @@ lock_file (Lisp_Object fn)
static Lisp_Object
unlock_file (Lisp_Object fn)
{
- char *lfname;
-
- Lisp_Object lock_filename = make_lock_file_name (fn);
- if (NILP (lock_filename))
+ Lisp_Object lfname = make_lock_file_name (fn);
+ if (NILP (lfname))
return Qnil;
- lfname = SSDATA (ENCODE_FILE (lock_filename));
int err = current_lock_owner (0, lfname);
- if (err == -2 && unlink (lfname) != 0 && errno != ENOENT)
- err = errno;
- if (0 < err)
+ if (! (err == 0 || err == ANOTHER_OWNS_IT
+ || (err == I_OWN_IT
+ && (unlink (SSDATA (lfname)) == 0 || (err = errno) == ENOENT))))
report_file_errno ("Unlocking file", fn, err);
return Qnil;
@@ -748,12 +777,16 @@ If the option `create-lockfiles' is nil, this does nothing. */)
(Lisp_Object file)
{
#ifndef MSDOS
- /* Don't do locking if the user has opted out. */
- if (create_lockfiles)
- {
- CHECK_STRING (file);
- lock_file (file);
- }
+ CHECK_STRING (file);
+
+ /* If the file name has special constructs in it,
+ call the corresponding file name handler. */
+ Lisp_Object handler;
+ handler = Ffind_file_name_handler (file, Qlock_file);
+ if (!NILP (handler))
+ return call2 (handler, Qlock_file, file);
+
+ lock_file (file);
#endif /* MSDOS */
return Qnil;
}
@@ -850,16 +883,17 @@ t if it is locked by you, else a string saying which user has locked it. */)
return call2 (handler, Qfile_locked_p, filename);
}
- Lisp_Object lock_filename = make_lock_file_name (filename);
- if (NILP (lock_filename))
+ Lisp_Object lfname = make_lock_file_name (filename);
+ if (NILP (lfname))
return Qnil;
- char *lfname = SSDATA (ENCODE_FILE (lock_filename));
owner = current_lock_owner (&locker, lfname);
switch (owner)
{
- case -2: ret = Qt; break;
- case -1: ret = make_string (locker.user, locker.at - locker.user); break;
+ case I_OWN_IT: ret = Qt; break;
+ case ANOTHER_OWNS_IT:
+ ret = make_string (locker.user, locker.at - locker.user);
+ break;
case 0: ret = Qnil; break;
default: report_file_errno ("Testing file lock", filename, owner);
}
@@ -877,8 +911,8 @@ syms_of_filelock (void)
DEFVAR_BOOL ("create-lockfiles", create_lockfiles,
doc: /* Non-nil means use lockfiles to avoid editing collisions.
-The name of the (per-buffer) lockfile is constructed by prepending a
-'.#' to the name of the file being locked. See also `lock-buffer' and
+The name of the (per-buffer) lockfile is constructed by prepending
+".#" to the name of the file being locked. See also `lock-buffer' and
Info node `(emacs)Interlocking'. */);
create_lockfiles = true;
diff --git a/src/floatfns.c b/src/floatfns.c
index f2b3b13acd8..293184c70f1 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -29,14 +29,20 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
C99 and C11 require the following math.h functions in addition to
the C89 functions. Of these, Emacs currently exports only the
- starred ones to Lisp, since we haven't found a use for the others:
- acosh, atanh, cbrt, *copysign, erf, erfc, exp2, expm1, fdim, fma,
- fmax, fmin, fpclassify, hypot, ilogb, isfinite, isgreater,
- isgreaterequal, isinf, isless, islessequal, islessgreater, *isnan,
- isnormal, isunordered, lgamma, log1p, *log2 [via (log X 2)], *logb
- (approximately), lrint/llrint, lround/llround, nan, nearbyint,
- nextafter, nexttoward, remainder, remquo, *rint, round, scalbln,
- scalbn, signbit, tgamma, *trunc.
+ starred ones to Lisp, since we haven't found a use for the others.
+ Also, it uses the ones marked "+" internally:
+ acosh, atanh, cbrt, copysign (implemented by signbit), erf, erfc,
+ exp2, expm1, fdim, fma, fmax, fmin, fpclassify, hypot, +ilogb,
+ isfinite, isgreater, isgreaterequal, isinf, isless, islessequal,
+ islessgreater, *isnan, isnormal, isunordered, lgamma, log1p, *log2
+ [via (log X 2)], logb (approximately; implemented by frexp),
+ +lrint/llrint, +lround/llround, nan, nearbyint, nextafter,
+ nexttoward, remainder, remquo, *rint, round, scalbln, +scalbn,
+ +signbit, tgamma, *trunc.
+
+ The C standard also requires functions for float and long double
+ that are not listed above. Of these functions, Emacs uses only the
+ following internally: fabsf, powf, sprintf.
*/
#include <config.h>
diff --git a/src/fns.c b/src/fns.c
index 86c49e6fc6b..61ed01eee4e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -39,9 +39,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "puresize.h"
#include "gnutls.h"
-static void sort_vector_copy (Lisp_Object pred, ptrdiff_t len,
- Lisp_Object src[restrict VLA_ELEMS (len)],
- Lisp_Object dest[restrict VLA_ELEMS (len)]);
enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
static bool internal_equal (Lisp_Object, Lisp_Object,
enum equal_kind, int, Lisp_Object);
@@ -55,49 +52,24 @@ DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
return argument;
}
+/* Return a random Lisp fixnum I in the range 0 <= I < LIM,
+ where LIM is taken from a positive fixnum. */
static Lisp_Object
-ccall2 (Lisp_Object (f) (ptrdiff_t nargs, Lisp_Object *args),
- Lisp_Object arg1, Lisp_Object arg2)
+get_random_fixnum (EMACS_INT lim)
{
- Lisp_Object args[2] = {arg1, arg2};
- return f (2, args);
-}
-
-static Lisp_Object
-get_random_bignum (Lisp_Object limit)
-{
- /* This is a naive transcription into bignums of the fixnum algorithm.
- I'd be quite surprised if that's anywhere near the best algorithm
- for it. */
- while (true)
+ /* Return the remainder of a random integer R (in range 0..INTMASK)
+ divided by LIM, except reject the rare case where R is so close
+ to INTMASK that the remainder isn't random. */
+ EMACS_INT difflim = INTMASK - lim + 1, diff, remainder;
+ do
{
- Lisp_Object val = make_fixnum (0);
- Lisp_Object lim = limit;
- int bits = 0;
- int bitsperiteration = FIXNUM_BITS - 1;
- do
- {
- /* Shift by one so it is a valid positive fixnum. */
- EMACS_INT rand = get_random () >> 1;
- Lisp_Object lrand = make_fixnum (rand);
- bits += bitsperiteration;
- val = ccall2 (Flogior,
- Fash (val, make_fixnum (bitsperiteration)),
- lrand);
- lim = Fash (lim, make_fixnum (- bitsperiteration));
- }
- while (!EQ (lim, make_fixnum (0)));
- /* Return the remainder, except reject the rare case where
- get_random returns a number so close to INTMASK that the
- remainder isn't random. */
- Lisp_Object remainder = Frem (val, limit);
- if (!NILP (ccall2 (Fleq,
- ccall2 (Fminus, val, remainder),
- ccall2 (Fminus,
- Fash (make_fixnum (1), make_fixnum (bits)),
- limit))))
- return remainder;
+ EMACS_INT r = get_random ();
+ remainder = r % lim;
+ diff = r - remainder;
}
+ while (difflim < diff);
+
+ return make_fixnum (remainder);
}
DEFUN ("random", Frandom, Srandom, 0, 1, 0,
@@ -111,32 +83,26 @@ With a string argument, set the seed based on the string's contents.
See Info node `(elisp)Random Numbers' for more details. */)
(Lisp_Object limit)
{
- EMACS_INT val;
-
if (EQ (limit, Qt))
init_random ();
else if (STRINGP (limit))
seed_random (SSDATA (limit), SBYTES (limit));
- if (BIGNUMP (limit))
+ else if (FIXNUMP (limit))
{
- if (0 > mpz_sgn (*xbignum_val (limit)))
- xsignal2 (Qwrong_type_argument, Qnatnump, limit);
- return get_random_bignum (limit);
+ EMACS_INT lim = XFIXNUM (limit);
+ if (lim <= 0)
+ xsignal1 (Qargs_out_of_range, limit);
+ return get_random_fixnum (lim);
+ }
+ else if (BIGNUMP (limit))
+ {
+ struct Lisp_Bignum *lim = XBIGNUM (limit);
+ if (mpz_sgn (*bignum_val (lim)) <= 0)
+ xsignal1 (Qargs_out_of_range, limit);
+ return get_random_bignum (lim);
}
- val = get_random ();
- if (FIXNUMP (limit) && 0 < XFIXNUM (limit))
- while (true)
- {
- /* Return the remainder, except reject the rare case where
- get_random returns a number so close to INTMASK that the
- remainder isn't random. */
- EMACS_INT remainder = val % XFIXNUM (limit);
- if (val - remainder <= INTMASK - XFIXNUM (limit) + 1)
- return make_fixnum (remainder);
- val = get_random ();
- }
- return make_ufixnum (val);
+ return make_ufixnum (get_random ());
}
/* Random data-structure functions. */
@@ -475,15 +441,24 @@ Symbols are also allowed; their print names are used instead. */)
{
if (SYMBOLP (string1))
string1 = SYMBOL_NAME (string1);
+ else
+ CHECK_STRING (string1);
if (SYMBOLP (string2))
string2 = SYMBOL_NAME (string2);
- CHECK_STRING (string1);
- CHECK_STRING (string2);
+ else
+ CHECK_STRING (string2);
+
+ ptrdiff_t n = min (SCHARS (string1), SCHARS (string2));
+ if (!STRING_MULTIBYTE (string1) && !STRING_MULTIBYTE (string2))
+ {
+ /* Both arguments are unibyte (hot path). */
+ int d = memcmp (SSDATA (string1), SSDATA (string2), n);
+ return d < 0 || (d == 0 && n < SCHARS (string2)) ? Qt : Qnil;
+ }
ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0;
- ptrdiff_t end = min (SCHARS (string1), SCHARS (string2));
- while (i1 < end)
+ while (i1 < n)
{
/* When we find a mismatch, we must compare the
characters, not just the bytes. */
@@ -516,37 +491,9 @@ Symbols are also allowed; their print names are used instead. */)
string2 = SYMBOL_NAME (string2);
CHECK_STRING (string1);
CHECK_STRING (string2);
- return string_version_cmp (string1, string2) < 0 ? Qt : Qnil;
-}
-
-/* Return negative, 0, positive if STRING1 is <, =, > STRING2 as per
- string-version-lessp. */
-int
-string_version_cmp (Lisp_Object string1, Lisp_Object string2)
-{
- char *p1 = SSDATA (string1);
- char *p2 = SSDATA (string2);
- char *lim1 = p1 + SBYTES (string1);
- char *lim2 = p2 + SBYTES (string2);
- int cmp;
-
- while ((cmp = filevercmp (p1, p2)) == 0)
- {
- /* If the strings are identical through their first null bytes,
- skip past identical prefixes and try again. */
- ptrdiff_t size = strlen (p1) + 1;
- eassert (size == strlen (p2) + 1);
- p1 += size;
- p2 += size;
- bool more1 = p1 <= lim1;
- bool more2 = p2 <= lim2;
- if (!more1)
- return more2;
- if (!more2)
- return -1;
- }
-
- return cmp;
+ int cmp = filenvercmp (SSDATA (string1), SBYTES (string1),
+ SSDATA (string2), SBYTES (string2));
+ return cmp < 0 ? Qt : Qnil;
}
DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 4, 0,
@@ -642,19 +589,21 @@ Do NOT use this function to compare file names for equality. */)
#endif /* !__STDC_ISO_10646__, !WINDOWSNT */
}
-static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args,
- enum Lisp_Type target_type, bool last_special);
+static Lisp_Object concat_to_list (ptrdiff_t nargs, Lisp_Object *args,
+ Lisp_Object last_tail);
+static Lisp_Object concat_to_vector (ptrdiff_t nargs, Lisp_Object *args);
+static Lisp_Object concat_to_string (ptrdiff_t nargs, Lisp_Object *args);
Lisp_Object
concat2 (Lisp_Object s1, Lisp_Object s2)
{
- return concat (2, ((Lisp_Object []) {s1, s2}), Lisp_String, 0);
+ return concat_to_string (2, ((Lisp_Object []) {s1, s2}));
}
Lisp_Object
concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3)
{
- return concat (3, ((Lisp_Object []) {s1, s2, s3}), Lisp_String, 0);
+ return concat_to_string (3, ((Lisp_Object []) {s1, s2, s3}));
}
DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
@@ -665,7 +614,9 @@ The last argument is not copied, just used as the tail of the new list.
usage: (append &rest SEQUENCES) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- return concat (nargs, args, Lisp_Cons, 1);
+ if (nargs == 0)
+ return Qnil;
+ return concat_to_list (nargs - 1, args, args[nargs - 1]);
}
DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
@@ -678,7 +629,7 @@ to be `eq'.
usage: (concat &rest SEQUENCES) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- return concat (nargs, args, Lisp_String, 0);
+ return concat_to_string (nargs, args);
}
DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
@@ -688,7 +639,7 @@ Each argument may be a list, vector or string.
usage: (vconcat &rest SEQUENCES) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- return concat (nargs, args, Lisp_Vectorlike, 0);
+ return concat_to_vector (nargs, args);
}
@@ -702,16 +653,48 @@ the same empty object instead of its copy. */)
{
if (NILP (arg)) return arg;
- if (RECORDP (arg))
+ if (CONSP (arg))
{
- return Frecord (PVSIZE (arg), XVECTOR (arg)->contents);
+ Lisp_Object val = Fcons (XCAR (arg), Qnil);
+ Lisp_Object prev = val;
+ Lisp_Object tail = XCDR (arg);
+ FOR_EACH_TAIL (tail)
+ {
+ Lisp_Object c = Fcons (XCAR (tail), Qnil);
+ XSETCDR (prev, c);
+ prev = c;
+ }
+ CHECK_LIST_END (tail, tail);
+ return val;
}
- if (CHAR_TABLE_P (arg))
+ if (STRINGP (arg))
{
- return copy_char_table (arg);
+ ptrdiff_t bytes = SBYTES (arg);
+ ptrdiff_t chars = SCHARS (arg);
+ Lisp_Object val = STRING_MULTIBYTE (arg)
+ ? make_uninit_multibyte_string (chars, bytes)
+ : make_uninit_string (bytes);
+ memcpy (SDATA (val), SDATA (arg), bytes);
+ INTERVAL ivs = string_intervals (arg);
+ if (ivs)
+ {
+ INTERVAL copy = copy_intervals (ivs, 0, chars);
+ set_interval_object (copy, val);
+ set_string_intervals (val, copy);
+ }
+ return val;
}
+ if (VECTORP (arg))
+ return Fvector (ASIZE (arg), XVECTOR (arg)->contents);
+
+ if (RECORDP (arg))
+ return Frecord (PVSIZE (arg), XVECTOR (arg)->contents);
+
+ if (CHAR_TABLE_P (arg))
+ return copy_char_table (arg);
+
if (BOOL_VECTOR_P (arg))
{
EMACS_INT nbits = bool_vector_size (arg);
@@ -721,294 +704,371 @@ the same empty object instead of its copy. */)
return val;
}
- if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
- wrong_type_argument (Qsequencep, arg);
-
- return concat (1, &arg, XTYPE (arg), 0);
+ wrong_type_argument (Qsequencep, arg);
}
-/* This structure holds information of an argument of `concat' that is
- a string and has text properties to be copied. */
+/* This structure holds information of an argument of `concat_to_string'
+ that is a string and has text properties to be copied. */
struct textprop_rec
{
ptrdiff_t argnum; /* refer to ARGS (arguments of `concat') */
- ptrdiff_t from; /* refer to ARGS[argnum] (argument string) */
ptrdiff_t to; /* refer to VAL (the target string) */
};
static Lisp_Object
-concat (ptrdiff_t nargs, Lisp_Object *args,
- enum Lisp_Type target_type, bool last_special)
+concat_to_string (ptrdiff_t nargs, Lisp_Object *args)
{
- Lisp_Object val;
- Lisp_Object tail;
- Lisp_Object this;
- ptrdiff_t toindex;
- ptrdiff_t toindex_byte = 0;
- EMACS_INT result_len;
- EMACS_INT result_len_byte;
- ptrdiff_t argnum;
- Lisp_Object last_tail;
- Lisp_Object prev;
- bool some_multibyte;
- /* When we make a multibyte string, we can't copy text properties
- while concatenating each string because the length of resulting
- string can't be decided until we finish the whole concatenation.
- So, we record strings that have text properties to be copied
- here, and copy the text properties after the concatenation. */
- struct textprop_rec *textprops = NULL;
- /* Number of elements in textprops. */
- ptrdiff_t num_textprops = 0;
USE_SAFE_ALLOCA;
- tail = Qnil;
-
- /* In append, the last arg isn't treated like the others */
- if (last_special && nargs > 0)
- {
- nargs--;
- last_tail = args[nargs];
- }
- else
- last_tail = Qnil;
-
- /* Check each argument. */
- for (argnum = 0; argnum < nargs; argnum++)
- {
- this = args[argnum];
- if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
- || COMPILEDP (this) || BOOL_VECTOR_P (this)))
- wrong_type_argument (Qsequencep, this);
- }
-
- /* Compute total length in chars of arguments in RESULT_LEN.
- If desired output is a string, also compute length in bytes
- in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
+ /* Check types and compute total length in chars of arguments in RESULT_LEN,
+ length in bytes in RESULT_LEN_BYTE, and determine in DEST_MULTIBYTE
whether the result should be a multibyte string. */
- result_len_byte = 0;
- result_len = 0;
- some_multibyte = 0;
- for (argnum = 0; argnum < nargs; argnum++)
+ EMACS_INT result_len = 0;
+ EMACS_INT result_len_byte = 0;
+ bool dest_multibyte = false;
+ bool some_unibyte = false;
+ for (ptrdiff_t i = 0; i < nargs; i++)
{
+ Lisp_Object arg = args[i];
EMACS_INT len;
- this = args[argnum];
- len = XFIXNAT (Flength (this));
- if (target_type == Lisp_String)
- {
- /* We must count the number of bytes needed in the string
- as well as the number of characters. */
- ptrdiff_t i;
- Lisp_Object ch;
- int c;
- ptrdiff_t this_len_byte;
- if (VECTORP (this) || COMPILEDP (this))
- for (i = 0; i < len; i++)
- {
- ch = AREF (this, i);
- CHECK_CHARACTER (ch);
- c = XFIXNAT (ch);
- this_len_byte = CHAR_BYTES (c);
- if (STRING_BYTES_BOUND - result_len_byte < this_len_byte)
- string_overflow ();
- result_len_byte += this_len_byte;
- if (! ASCII_CHAR_P (c) && ! CHAR_BYTE8_P (c))
- some_multibyte = 1;
- }
- else if (BOOL_VECTOR_P (this) && bool_vector_size (this) > 0)
- wrong_type_argument (Qintegerp, Faref (this, make_fixnum (0)));
- else if (CONSP (this))
- for (; CONSP (this); this = XCDR (this))
- {
- ch = XCAR (this);
- CHECK_CHARACTER (ch);
- c = XFIXNAT (ch);
- this_len_byte = CHAR_BYTES (c);
- if (STRING_BYTES_BOUND - result_len_byte < this_len_byte)
- string_overflow ();
- result_len_byte += this_len_byte;
- if (! ASCII_CHAR_P (c) && ! CHAR_BYTE8_P (c))
- some_multibyte = 1;
- }
- else if (STRINGP (this))
+ /* We must count the number of bytes needed in the string
+ as well as the number of characters. */
+
+ if (STRINGP (arg))
+ {
+ ptrdiff_t arg_len_byte = SBYTES (arg);
+ len = SCHARS (arg);
+ if (STRING_MULTIBYTE (arg))
+ dest_multibyte = true;
+ else
+ some_unibyte = true;
+ if (STRING_BYTES_BOUND - result_len_byte < arg_len_byte)
+ string_overflow ();
+ result_len_byte += arg_len_byte;
+ }
+ else if (VECTORP (arg))
+ {
+ len = ASIZE (arg);
+ ptrdiff_t arg_len_byte = 0;
+ for (ptrdiff_t j = 0; j < len; j++)
{
- if (STRING_MULTIBYTE (this))
- {
- some_multibyte = 1;
- this_len_byte = SBYTES (this);
- }
- else
- this_len_byte = count_size_as_multibyte (SDATA (this),
- SCHARS (this));
- if (STRING_BYTES_BOUND - result_len_byte < this_len_byte)
- string_overflow ();
- result_len_byte += this_len_byte;
+ Lisp_Object ch = AREF (arg, j);
+ CHECK_CHARACTER (ch);
+ int c = XFIXNAT (ch);
+ arg_len_byte += CHAR_BYTES (c);
+ if (!ASCII_CHAR_P (c) && !CHAR_BYTE8_P (c))
+ dest_multibyte = true;
+ }
+ if (STRING_BYTES_BOUND - result_len_byte < arg_len_byte)
+ string_overflow ();
+ result_len_byte += arg_len_byte;
+ }
+ else if (NILP (arg))
+ continue;
+ else if (CONSP (arg))
+ {
+ len = XFIXNAT (Flength (arg));
+ ptrdiff_t arg_len_byte = 0;
+ for (; CONSP (arg); arg = XCDR (arg))
+ {
+ Lisp_Object ch = XCAR (arg);
+ CHECK_CHARACTER (ch);
+ int c = XFIXNAT (ch);
+ arg_len_byte += CHAR_BYTES (c);
+ if (!ASCII_CHAR_P (c) && !CHAR_BYTE8_P (c))
+ dest_multibyte = true;
}
+ if (STRING_BYTES_BOUND - result_len_byte < arg_len_byte)
+ string_overflow ();
+ result_len_byte += arg_len_byte;
}
+ else
+ wrong_type_argument (Qsequencep, arg);
result_len += len;
if (MOST_POSITIVE_FIXNUM < result_len)
memory_full (SIZE_MAX);
}
- if (! some_multibyte)
+ if (dest_multibyte && some_unibyte)
+ {
+ /* Non-ASCII characters in unibyte strings take two bytes when
+ converted to multibyte -- count them and adjust the total. */
+ for (ptrdiff_t i = 0; i < nargs; i++)
+ {
+ Lisp_Object arg = args[i];
+ if (STRINGP (arg) && !STRING_MULTIBYTE (arg))
+ {
+ ptrdiff_t bytes = SCHARS (arg);
+ const unsigned char *s = SDATA (arg);
+ ptrdiff_t nonascii = 0;
+ for (ptrdiff_t j = 0; j < bytes; j++)
+ nonascii += s[j] >> 7;
+ if (STRING_BYTES_BOUND - result_len_byte < nonascii)
+ string_overflow ();
+ result_len_byte += nonascii;
+ }
+ }
+ }
+
+ if (!dest_multibyte)
result_len_byte = result_len;
/* Create the output object. */
- if (target_type == Lisp_Cons)
- val = Fmake_list (make_fixnum (result_len), Qnil);
- else if (target_type == Lisp_Vectorlike)
- val = make_nil_vector (result_len);
- else if (some_multibyte)
- val = make_uninit_multibyte_string (result_len, result_len_byte);
- else
- val = make_uninit_string (result_len);
-
- /* In `append', if all but last arg are nil, return last arg. */
- if (target_type == Lisp_Cons && NILP (val))
- return last_tail;
+ Lisp_Object result = dest_multibyte
+ ? make_uninit_multibyte_string (result_len, result_len_byte)
+ : make_uninit_string (result_len);
/* Copy the contents of the args into the result. */
- if (CONSP (val))
- tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
- else
- toindex = 0, toindex_byte = 0;
+ ptrdiff_t toindex = 0;
+ ptrdiff_t toindex_byte = 0;
- prev = Qnil;
- if (STRINGP (val))
- SAFE_NALLOCA (textprops, 1, nargs);
+ /* When we make a multibyte string, we can't copy text properties
+ while concatenating each string because the length of resulting
+ string can't be decided until we finish the whole concatenation.
+ So, we record strings that have text properties to be copied
+ here, and copy the text properties after the concatenation. */
+ struct textprop_rec *textprops;
+ /* Number of elements in textprops. */
+ ptrdiff_t num_textprops = 0;
+ SAFE_NALLOCA (textprops, 1, nargs);
- for (argnum = 0; argnum < nargs; argnum++)
+ for (ptrdiff_t i = 0; i < nargs; i++)
{
- Lisp_Object thislen;
- ptrdiff_t thisleni = 0;
- ptrdiff_t thisindex = 0;
- ptrdiff_t thisindex_byte = 0;
-
- this = args[argnum];
- if (!CONSP (this))
- thislen = Flength (this), thisleni = XFIXNUM (thislen);
-
- /* Between strings of the same kind, copy fast. */
- if (STRINGP (this) && STRINGP (val)
- && STRING_MULTIBYTE (this) == some_multibyte)
+ Lisp_Object arg = args[i];
+ if (STRINGP (arg))
{
- ptrdiff_t thislen_byte = SBYTES (this);
-
- memcpy (SDATA (val) + toindex_byte, SDATA (this), SBYTES (this));
- if (string_intervals (this))
+ if (string_intervals (arg))
+ {
+ textprops[num_textprops].argnum = i;
+ textprops[num_textprops].to = toindex;
+ num_textprops++;
+ }
+ ptrdiff_t nchars = SCHARS (arg);
+ if (STRING_MULTIBYTE (arg) == dest_multibyte)
+ {
+ /* Between strings of the same kind, copy fast. */
+ ptrdiff_t arg_len_byte = SBYTES (arg);
+ memcpy (SDATA (result) + toindex_byte, SDATA (arg), arg_len_byte);
+ toindex_byte += arg_len_byte;
+ }
+ else
{
- textprops[num_textprops].argnum = argnum;
- textprops[num_textprops].from = 0;
- textprops[num_textprops++].to = toindex;
+ /* Copy a single-byte string to a multibyte string. */
+ toindex_byte += copy_text (SDATA (arg),
+ SDATA (result) + toindex_byte,
+ nchars, 0, 1);
}
- toindex_byte += thislen_byte;
- toindex += thisleni;
+ toindex += nchars;
}
- /* Copy a single-byte string to a multibyte string. */
- else if (STRINGP (this) && STRINGP (val))
+ else if (VECTORP (arg))
{
- if (string_intervals (this))
+ ptrdiff_t len = ASIZE (arg);
+ for (ptrdiff_t j = 0; j < len; j++)
{
- textprops[num_textprops].argnum = argnum;
- textprops[num_textprops].from = 0;
- textprops[num_textprops++].to = toindex;
+ int c = XFIXNAT (AREF (arg, j));
+ if (dest_multibyte)
+ toindex_byte += CHAR_STRING (c, SDATA (result) + toindex_byte);
+ else
+ SSET (result, toindex_byte++, c);
+ toindex++;
}
- toindex_byte += copy_text (SDATA (this),
- SDATA (val) + toindex_byte,
- SCHARS (this), 0, 1);
- toindex += thisleni;
}
else
- /* Copy element by element. */
- while (1)
+ for (Lisp_Object tail = arg; !NILP (tail); tail = XCDR (tail))
{
- register Lisp_Object elt;
-
- /* Fetch next element of `this' arg into `elt', or break if
- `this' is exhausted. */
- if (NILP (this)) break;
- if (CONSP (this))
- elt = XCAR (this), this = XCDR (this);
- else if (thisindex >= thisleni)
- break;
- else if (STRINGP (this))
- {
- int c;
- if (STRING_MULTIBYTE (this))
- c = fetch_string_char_advance_no_check (this, &thisindex,
- &thisindex_byte);
- else
- {
- c = SREF (this, thisindex); thisindex++;
- if (some_multibyte && !ASCII_CHAR_P (c))
- c = BYTE8_TO_CHAR (c);
- }
- XSETFASTINT (elt, c);
- }
- else if (BOOL_VECTOR_P (this))
- {
- elt = bool_vector_ref (this, thisindex);
- thisindex++;
- }
+ int c = XFIXNAT (XCAR (tail));
+ if (dest_multibyte)
+ toindex_byte += CHAR_STRING (c, SDATA (result) + toindex_byte);
else
- {
- elt = AREF (this, thisindex);
- thisindex++;
- }
-
- /* Store this element into the result. */
- if (toindex < 0)
- {
- XSETCAR (tail, elt);
- prev = tail;
- tail = XCDR (tail);
- }
- else if (VECTORP (val))
- {
- ASET (val, toindex, elt);
- toindex++;
- }
- else
- {
- int c;
- CHECK_CHARACTER (elt);
- c = XFIXNAT (elt);
- if (some_multibyte)
- toindex_byte += CHAR_STRING (c, SDATA (val) + toindex_byte);
- else
- SSET (val, toindex_byte++, c);
- toindex++;
- }
+ SSET (result, toindex_byte++, c);
+ toindex++;
}
}
- if (!NILP (prev))
- XSETCDR (prev, last_tail);
if (num_textprops > 0)
{
- Lisp_Object props;
ptrdiff_t last_to_end = -1;
-
- for (argnum = 0; argnum < num_textprops; argnum++)
+ for (ptrdiff_t i = 0; i < num_textprops; i++)
{
- this = args[textprops[argnum].argnum];
- props = text_property_list (this,
- make_fixnum (0),
- make_fixnum (SCHARS (this)),
- Qnil);
+ Lisp_Object arg = args[textprops[i].argnum];
+ Lisp_Object props = text_property_list (arg,
+ make_fixnum (0),
+ make_fixnum (SCHARS (arg)),
+ Qnil);
/* If successive arguments have properties, be sure that the
value of `composition' property be the copy. */
- if (last_to_end == textprops[argnum].to)
+ if (last_to_end == textprops[i].to)
make_composition_value_copy (props);
- add_text_properties_from_list (val, props,
- make_fixnum (textprops[argnum].to));
- last_to_end = textprops[argnum].to + SCHARS (this);
+ add_text_properties_from_list (result, props,
+ make_fixnum (textprops[i].to));
+ last_to_end = textprops[i].to + SCHARS (arg);
}
}
SAFE_FREE ();
- return val;
+ return result;
+}
+
+/* Concatenate sequences into a list. */
+Lisp_Object
+concat_to_list (ptrdiff_t nargs, Lisp_Object *args, Lisp_Object last_tail)
+{
+ /* Copy the contents of the args into the result. */
+ Lisp_Object result = Qnil;
+ Lisp_Object last = Qnil; /* Last cons in result if nonempty. */
+
+ for (ptrdiff_t i = 0; i < nargs; i++)
+ {
+ Lisp_Object arg = args[i];
+ /* List arguments are treated specially since this is the common case. */
+ if (CONSP (arg))
+ {
+ Lisp_Object head = Fcons (XCAR (arg), Qnil);
+ Lisp_Object prev = head;
+ arg = XCDR (arg);
+ FOR_EACH_TAIL (arg)
+ {
+ Lisp_Object next = Fcons (XCAR (arg), Qnil);
+ XSETCDR (prev, next);
+ prev = next;
+ }
+ CHECK_LIST_END (arg, arg);
+ if (NILP (result))
+ result = head;
+ else
+ XSETCDR (last, head);
+ last = prev;
+ }
+ else if (NILP (arg))
+ ;
+ else if (VECTORP (arg) || STRINGP (arg)
+ || BOOL_VECTOR_P (arg) || COMPILEDP (arg))
+ {
+ ptrdiff_t arglen = XFIXNUM (Flength (arg));
+ ptrdiff_t argindex_byte = 0;
+
+ /* Copy element by element. */
+ for (ptrdiff_t argindex = 0; argindex < arglen; argindex++)
+ {
+ /* Fetch next element of `arg' arg into `elt', or break if
+ `arg' is exhausted. */
+ Lisp_Object elt;
+ if (STRINGP (arg))
+ {
+ int c;
+ if (STRING_MULTIBYTE (arg))
+ {
+ ptrdiff_t char_idx = argindex;
+ c = fetch_string_char_advance_no_check (arg, &char_idx,
+ &argindex_byte);
+ }
+ else
+ c = SREF (arg, argindex);
+ elt = make_fixed_natnum (c);
+ }
+ else if (BOOL_VECTOR_P (arg))
+ elt = bool_vector_ref (arg, argindex);
+ else
+ elt = AREF (arg, argindex);
+
+ /* Store this element into the result. */
+ Lisp_Object node = Fcons (elt, Qnil);
+ if (NILP (result))
+ result = node;
+ else
+ XSETCDR (last, node);
+ last = node;
+ }
+ }
+ else
+ wrong_type_argument (Qsequencep, arg);
+ }
+
+ if (NILP (result))
+ result = last_tail;
+ else
+ XSETCDR (last, last_tail);
+
+ return result;
+}
+
+/* Concatenate sequences into a vector. */
+Lisp_Object
+concat_to_vector (ptrdiff_t nargs, Lisp_Object *args)
+{
+ /* Check argument types and compute total length of arguments. */
+ EMACS_INT result_len = 0;
+ for (ptrdiff_t i = 0; i < nargs; i++)
+ {
+ Lisp_Object arg = args[i];
+ if (!(VECTORP (arg) || CONSP (arg) || NILP (arg) || STRINGP (arg)
+ || BOOL_VECTOR_P (arg) || COMPILEDP (arg)))
+ wrong_type_argument (Qsequencep, arg);
+ EMACS_INT len = XFIXNAT (Flength (arg));
+ result_len += len;
+ if (MOST_POSITIVE_FIXNUM < result_len)
+ memory_full (SIZE_MAX);
+ }
+
+ /* Create the output vector. */
+ Lisp_Object result = make_uninit_vector (result_len);
+ Lisp_Object *dst = XVECTOR (result)->contents;
+
+ /* Copy the contents of the args into the result. */
+
+ for (ptrdiff_t i = 0; i < nargs; i++)
+ {
+ Lisp_Object arg = args[i];
+ if (VECTORP (arg))
+ {
+ ptrdiff_t size = ASIZE (arg);
+ memcpy (dst, XVECTOR (arg)->contents, size * sizeof *dst);
+ dst += size;
+ }
+ else if (CONSP (arg))
+ do
+ {
+ *dst++ = XCAR (arg);
+ arg = XCDR (arg);
+ }
+ while (!NILP (arg));
+ else if (NILP (arg))
+ ;
+ else if (STRINGP (arg))
+ {
+ ptrdiff_t size = SCHARS (arg);
+ if (STRING_MULTIBYTE (arg))
+ {
+ ptrdiff_t byte = 0;
+ for (ptrdiff_t i = 0; i < size;)
+ {
+ int c = fetch_string_char_advance_no_check (arg, &i, &byte);
+ *dst++ = make_fixnum (c);
+ }
+ }
+ else
+ for (ptrdiff_t i = 0; i < size; i++)
+ *dst++ = make_fixnum (SREF (arg, i));
+ }
+ else if (BOOL_VECTOR_P (arg))
+ {
+ ptrdiff_t size = bool_vector_size (arg);
+ for (ptrdiff_t i = 0; i < size; i++)
+ *dst++ = bool_vector_ref (arg, i);
+ }
+ else
+ {
+ eassert (COMPILEDP (arg));
+ ptrdiff_t size = PVSIZE (arg);
+ memcpy (dst, XVECTOR (arg)->contents, size * sizeof *dst);
+ dst += size;
+ }
+ }
+ eassert (dst == XVECTOR (result)->contents + result_len);
+
+ return result;
}
static Lisp_Object string_char_byte_cache_string;
@@ -1036,7 +1096,7 @@ string_char_to_byte (Lisp_Object string, ptrdiff_t char_index)
if (best_above == best_above_byte)
return char_index;
- if (EQ (string, string_char_byte_cache_string))
+ if (BASE_EQ (string, string_char_byte_cache_string))
{
if (string_char_byte_cache_charpos < char_index)
{
@@ -1096,7 +1156,7 @@ string_byte_to_char (Lisp_Object string, ptrdiff_t byte_index)
if (best_above == best_above_byte)
return byte_index;
- if (EQ (string, string_char_byte_cache_string))
+ if (BASE_EQ (string, string_char_byte_cache_string))
{
if (string_char_byte_cache_bytepos < byte_index)
{
@@ -1353,19 +1413,24 @@ an error is signaled. */)
(Lisp_Object string)
{
CHECK_STRING (string);
+ if (!STRING_MULTIBYTE (string))
+ return string;
- if (STRING_MULTIBYTE (string))
+ ptrdiff_t chars = SCHARS (string);
+ Lisp_Object ret = make_uninit_string (chars);
+ unsigned char *src = SDATA (string);
+ unsigned char *dst = SDATA (ret);
+ for (ptrdiff_t i = 0; i < chars; i++)
{
- ptrdiff_t chars = SCHARS (string);
- unsigned char *str = xmalloc (chars);
- ptrdiff_t converted = str_to_unibyte (SDATA (string), str, chars);
-
- if (converted < chars)
- error ("Can't convert the %"pD"dth character to unibyte", converted);
- string = make_unibyte_string ((char *) str, chars);
- xfree (str);
+ unsigned char b = *src++;
+ if (b <= 0x7f)
+ *dst++ = b; /* ASCII */
+ else if (CHAR_BYTE8_HEAD_P (b))
+ *dst++ = 0x80 | (b & 1) << 6 | (*src++ & 0x3f); /* raw byte */
+ else
+ error ("Cannot convert character at index %"pD"d to unibyte", i);
}
- return string;
+ return ret;
}
@@ -1380,7 +1445,7 @@ Elements of ALIST that are not conses are also shared. */)
{
if (NILP (alist))
return alist;
- alist = concat (1, &alist, Lisp_Cons, false);
+ alist = Fcopy_sequence (alist);
for (Lisp_Object tem = alist; !NILP (tem); tem = XCDR (tem))
{
Lisp_Object car = XCAR (tem);
@@ -1567,7 +1632,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
{
/* If the tortoise just jumped (which is rare),
update TORTOISE_NUM accordingly. */
- if (EQ (tail, li.tortoise))
+ if (BASE_EQ (tail, li.tortoise))
tortoise_num = num;
saved_tail = XCDR (tail);
@@ -2005,7 +2070,7 @@ This function may destructively modify SEQ to produce the value. */)
next = XCDR (tail);
/* If SEQ contains a cycle, attempting to reverse it
in-place will inevitably come back to SEQ. */
- if (EQ (next, seq))
+ if (BASE_EQ (next, seq))
circular_list (seq);
Fsetcdr (tail, prev);
prev = tail;
@@ -2104,8 +2169,11 @@ See also the function `nreverse', which is used more often. */)
return new;
}
-/* Sort LIST using PREDICATE, preserving original order of elements
- considered as equal. */
+
+/* Stably sort LIST ordered by PREDICATE using the TIMSORT
+ algorithm. This converts the list to a vector, sorts the vector,
+ and returns the result converted back to a list. The input list is
+ destructively reused to hold the sorted result. */
static Lisp_Object
sort_list (Lisp_Object list, Lisp_Object predicate)
@@ -2113,112 +2181,43 @@ sort_list (Lisp_Object list, Lisp_Object predicate)
ptrdiff_t length = list_length (list);
if (length < 2)
return list;
-
- Lisp_Object tem = Fnthcdr (make_fixnum (length / 2 - 1), list);
- Lisp_Object back = Fcdr (tem);
- Fsetcdr (tem, Qnil);
-
- return merge (Fsort (list, predicate), Fsort (back, predicate), predicate);
-}
-
-/* Using PRED to compare, return whether A and B are in order.
- Compare stably when A appeared before B in the input. */
-static bool
-inorder (Lisp_Object pred, Lisp_Object a, Lisp_Object b)
-{
- return NILP (call2 (pred, b, a));
-}
-
-/* Using PRED to compare, merge from ALEN-length A and BLEN-length B
- into DEST. Argument arrays must be nonempty and must not overlap,
- except that B might be the last part of DEST. */
-static void
-merge_vectors (Lisp_Object pred,
- ptrdiff_t alen, Lisp_Object const a[restrict VLA_ELEMS (alen)],
- ptrdiff_t blen, Lisp_Object const b[VLA_ELEMS (blen)],
- Lisp_Object dest[VLA_ELEMS (alen + blen)])
-{
- eassume (0 < alen && 0 < blen);
- Lisp_Object const *alim = a + alen;
- Lisp_Object const *blim = b + blen;
-
- while (true)
+ else
{
- if (inorder (pred, a[0], b[0]))
+ Lisp_Object *result;
+ USE_SAFE_ALLOCA;
+ SAFE_ALLOCA_LISP (result, length);
+ Lisp_Object tail = list;
+ for (ptrdiff_t i = 0; i < length; i++)
{
- *dest++ = *a++;
- if (a == alim)
- {
- if (dest != b)
- memcpy (dest, b, (blim - b) * sizeof *dest);
- return;
- }
+ result[i] = Fcar (tail);
+ tail = XCDR (tail);
}
- else
+ tim_sort (predicate, result, length);
+
+ ptrdiff_t i = 0;
+ tail = list;
+ while (CONSP (tail))
{
- *dest++ = *b++;
- if (b == blim)
- {
- memcpy (dest, a, (alim - a) * sizeof *dest);
- return;
- }
+ XSETCAR (tail, result[i]);
+ tail = XCDR (tail);
+ i++;
}
+ SAFE_FREE ();
+ return list;
}
}
-/* Using PRED to compare, sort LEN-length VEC in place, using TMP for
- temporary storage. LEN must be at least 2. */
-static void
-sort_vector_inplace (Lisp_Object pred, ptrdiff_t len,
- Lisp_Object vec[restrict VLA_ELEMS (len)],
- Lisp_Object tmp[restrict VLA_ELEMS (len >> 1)])
-{
- eassume (2 <= len);
- ptrdiff_t halflen = len >> 1;
- sort_vector_copy (pred, halflen, vec, tmp);
- if (1 < len - halflen)
- sort_vector_inplace (pred, len - halflen, vec + halflen, vec);
- merge_vectors (pred, halflen, tmp, len - halflen, vec + halflen, vec);
-}
-
-/* Using PRED to compare, sort from LEN-length SRC into DST.
- Len must be positive. */
-static void
-sort_vector_copy (Lisp_Object pred, ptrdiff_t len,
- Lisp_Object src[restrict VLA_ELEMS (len)],
- Lisp_Object dest[restrict VLA_ELEMS (len)])
-{
- eassume (0 < len);
- ptrdiff_t halflen = len >> 1;
- if (halflen < 1)
- dest[0] = src[0];
- else
- {
- if (1 < halflen)
- sort_vector_inplace (pred, halflen, src, dest);
- if (1 < len - halflen)
- sort_vector_inplace (pred, len - halflen, src + halflen, dest);
- merge_vectors (pred, halflen, src, len - halflen, src + halflen, dest);
- }
-}
-
-/* Sort VECTOR in place using PREDICATE, preserving original order of
- elements considered as equal. */
+/* Stably sort VECTOR ordered by PREDICATE using the TIMSORT
+ algorithm. */
static void
sort_vector (Lisp_Object vector, Lisp_Object predicate)
{
- ptrdiff_t len = ASIZE (vector);
- if (len < 2)
+ ptrdiff_t length = ASIZE (vector);
+ if (length < 2)
return;
- ptrdiff_t halflen = len >> 1;
- Lisp_Object *tmp;
- USE_SAFE_ALLOCA;
- SAFE_ALLOCA_LISP (tmp, halflen);
- for (ptrdiff_t i = 0; i < halflen; i++)
- tmp[i] = make_fixnum (0);
- sort_vector_inplace (predicate, len, XVECTOR (vector)->contents, tmp);
- SAFE_FREE ();
+
+ tim_sort (predicate, XVECTOR (vector)->contents, length);
}
DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
@@ -2264,7 +2263,7 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred)
}
Lisp_Object tem;
- if (inorder (pred, Fcar (l1), Fcar (l2)))
+ if (!NILP (call2 (pred, Fcar (l1), Fcar (l2))))
{
tem = l1;
l1 = Fcdr (l1);
@@ -2333,24 +2332,27 @@ merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, Lisp
/* This does not check for quits. That is safe since it must terminate. */
-DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
+DEFUN ("plist-get", Fplist_get, Splist_get, 2, 3, 0,
doc: /* Extract a value from a property list.
PLIST is a property list, which is a list of the form
\(PROP1 VALUE1 PROP2 VALUE2...).
This function returns the value corresponding to the given PROP, or
nil if PROP is not one of the properties on the list. The comparison
-with PROP is done using `eq'.
+with PROP is done using PREDICATE, which defaults to `eq'.
-This function never signals an error. */)
- (Lisp_Object plist, Lisp_Object prop)
+This function doesn't signal an error if PLIST is invalid. */)
+ (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate)
{
Lisp_Object tail = plist;
+ if (NILP (predicate))
+ return plist_get (plist, prop);
+
FOR_EACH_TAIL_SAFE (tail)
{
if (! CONSP (XCDR (tail)))
break;
- if (EQ (prop, XCAR (tail)))
+ if (!NILP (call2 (predicate, prop, XCAR (tail))))
return XCAR (XCDR (tail));
tail = XCDR (tail);
}
@@ -2358,39 +2360,58 @@ This function never signals an error. */)
return Qnil;
}
+/* Faster version of the above that works with EQ only */
+Lisp_Object
+plist_get (Lisp_Object plist, Lisp_Object prop)
+{
+ Lisp_Object tail = plist;
+ FOR_EACH_TAIL_SAFE (tail)
+ {
+ if (! CONSP (XCDR (tail)))
+ break;
+ if (EQ (prop, XCAR (tail)))
+ return XCAR (XCDR (tail));
+ tail = XCDR (tail);
+ }
+ return Qnil;
+}
+
DEFUN ("get", Fget, Sget, 2, 2, 0,
doc: /* Return the value of SYMBOL's PROPNAME property.
This is the last value stored with `(put SYMBOL PROPNAME VALUE)'. */)
(Lisp_Object symbol, Lisp_Object propname)
{
CHECK_SYMBOL (symbol);
- Lisp_Object propval = Fplist_get (CDR (Fassq (symbol, Voverriding_plist_environment)),
- propname);
+ Lisp_Object propval = plist_get (CDR (Fassq (symbol,
+ Voverriding_plist_environment)),
+ propname);
if (!NILP (propval))
return propval;
- return Fplist_get (XSYMBOL (symbol)->u.s.plist, propname);
+ return plist_get (XSYMBOL (symbol)->u.s.plist, propname);
}
-DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
+DEFUN ("plist-put", Fplist_put, Splist_put, 3, 4, 0,
doc: /* Change value in PLIST of PROP to VAL.
PLIST is a property list, which is a list of the form
\(PROP1 VALUE1 PROP2 VALUE2 ...).
-The comparison with PROP is done using `eq'.
+The comparison with PROP is done using PREDICATE, which defaults to `eq'.
If PROP is already a property on the list, its value is set to VAL,
otherwise the new PROP VAL pair is added. The new plist is returned;
use `(setq x (plist-put x prop val))' to be sure to use the new value.
The PLIST is modified by side effects. */)
- (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
+ (Lisp_Object plist, Lisp_Object prop, Lisp_Object val, Lisp_Object predicate)
{
Lisp_Object prev = Qnil, tail = plist;
+ if (NILP (predicate))
+ return plist_put (plist, prop, val);
FOR_EACH_TAIL (tail)
{
if (! CONSP (XCDR (tail)))
break;
- if (EQ (prop, XCAR (tail)))
+ if (!NILP (call2 (predicate, prop, XCAR (tail))))
{
Fsetcar (XCDR (tail), val);
return plist;
@@ -2408,47 +2429,8 @@ The PLIST is modified by side effects. */)
return plist;
}
-DEFUN ("put", Fput, Sput, 3, 3, 0,
- doc: /* Store SYMBOL's PROPNAME property with value VALUE.
-It can be retrieved with `(get SYMBOL PROPNAME)'. */)
- (Lisp_Object symbol, Lisp_Object propname, Lisp_Object value)
-{
- CHECK_SYMBOL (symbol);
- set_symbol_plist
- (symbol, Fplist_put (XSYMBOL (symbol)->u.s.plist, propname, value));
- return value;
-}
-
-DEFUN ("lax-plist-get", Flax_plist_get, Slax_plist_get, 2, 2, 0,
- doc: /* Extract a value from a property list, comparing with `equal'.
-This function is otherwise like `plist-get', but may signal an error
-if PLIST isn't a valid plist. */)
- (Lisp_Object plist, Lisp_Object prop)
-{
- Lisp_Object tail = plist;
- FOR_EACH_TAIL (tail)
- {
- if (! CONSP (XCDR (tail)))
- break;
- if (! NILP (Fequal (prop, XCAR (tail))))
- return XCAR (XCDR (tail));
- tail = XCDR (tail);
- }
-
- CHECK_TYPE (NILP (tail), Qplistp, plist);
-
- return Qnil;
-}
-
-DEFUN ("lax-plist-put", Flax_plist_put, Slax_plist_put, 3, 3, 0,
- doc: /* Change value in PLIST of PROP to VAL, comparing with `equal'.
-PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP and VAL are any objects.
-If PROP is already a property on the list, its value is set to VAL,
-otherwise the new PROP VAL pair is added. The new plist is returned;
-use `(setq x (lax-plist-put x prop val))' to be sure to use the new value.
-The PLIST is modified by side effects. */)
- (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
+Lisp_Object
+plist_put (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
{
Lisp_Object prev = Qnil, tail = plist;
FOR_EACH_TAIL (tail)
@@ -2456,7 +2438,7 @@ The PLIST is modified by side effects. */)
if (! CONSP (XCDR (tail)))
break;
- if (! NILP (Fequal (prop, XCAR (tail))))
+ if (EQ (prop, XCAR (tail)))
{
Fsetcar (XCDR (tail), val);
return plist;
@@ -2466,12 +2448,24 @@ The PLIST is modified by side effects. */)
tail = XCDR (tail);
}
CHECK_TYPE (NILP (tail), Qplistp, plist);
- Lisp_Object newcell = list2 (prop, val);
+ Lisp_Object newcell
+ = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
if (NILP (prev))
return newcell;
Fsetcdr (XCDR (prev), newcell);
return plist;
}
+
+DEFUN ("put", Fput, Sput, 3, 3, 0,
+ doc: /* Store SYMBOL's PROPNAME property with value VALUE.
+It can be retrieved with `(get SYMBOL PROPNAME)'. */)
+ (Lisp_Object symbol, Lisp_Object propname, Lisp_Object value)
+{
+ CHECK_SYMBOL (symbol);
+ set_symbol_plist
+ (symbol, plist_put (XSYMBOL (symbol)->u.s.plist, propname, value));
+ return value;
+}
DEFUN ("eql", Feql, Seql, 2, 2, 0,
doc: /* Return t if the two args are `eq' or are indistinguishable numbers.
@@ -2569,7 +2563,14 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
}
}
- if (EQ (o1, o2))
+ /* A symbol with position compares the contained symbol, and is
+ `equal' to the corresponding ordinary symbol. */
+ if (SYMBOL_WITH_POS_P (o1))
+ o1 = SYMBOL_WITH_POS_SYM (o1);
+ if (SYMBOL_WITH_POS_P (o2))
+ o2 = SYMBOL_WITH_POS_SYM (o2);
+
+ if (BASE_EQ (o1, o2))
return true;
if (XTYPE (o1) != XTYPE (o2))
return false;
@@ -2807,20 +2808,26 @@ usage: (nconc &rest LISTS) */)
static EMACS_INT
mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
{
- if (VECTORP (seq) || COMPILEDP (seq))
+ if (NILP (seq))
+ return 0;
+ else if (CONSP (seq))
{
+ Lisp_Object tail = seq;
for (ptrdiff_t i = 0; i < leni; i++)
{
- Lisp_Object dummy = call1 (fn, AREF (seq, i));
+ if (! CONSP (tail))
+ return i;
+ Lisp_Object dummy = call1 (fn, XCAR (tail));
if (vals)
vals[i] = dummy;
+ tail = XCDR (tail);
}
}
- else if (BOOL_VECTOR_P (seq))
+ else if (VECTORP (seq) || COMPILEDP (seq))
{
- for (EMACS_INT i = 0; i < leni; i++)
+ for (ptrdiff_t i = 0; i < leni; i++)
{
- Lisp_Object dummy = call1 (fn, bool_vector_ref (seq, i));
+ Lisp_Object dummy = call1 (fn, AREF (seq, i));
if (vals)
vals[i] = dummy;
}
@@ -2838,17 +2845,14 @@ mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
vals[i_before] = dummy;
}
}
- else /* Must be a list, since Flength did not get an error */
+ else
{
- Lisp_Object tail = seq;
- for (ptrdiff_t i = 0; i < leni; i++)
+ eassert (BOOL_VECTOR_P (seq));
+ for (EMACS_INT i = 0; i < leni; i++)
{
- if (! CONSP (tail))
- return i;
- Lisp_Object dummy = call1 (fn, XCAR (tail));
+ Lisp_Object dummy = call1 (fn, bool_vector_ref (seq, i));
if (vals)
vals[i] = dummy;
- tail = XCDR (tail);
}
}
@@ -2881,12 +2885,18 @@ FUNCTION must be a function of one argument, and must return a value
SAFE_ALLOCA_LISP (args, args_alloc);
ptrdiff_t nmapped = mapcar1 (leni, args, function, sequence);
ptrdiff_t nargs = 2 * nmapped - 1;
+ eassert (nmapped == leni);
- for (ptrdiff_t i = nmapped - 1; i > 0; i--)
- args[i + i] = args[i];
+ if (NILP (separator) || (STRINGP (separator) && SCHARS (separator) == 0))
+ nargs = nmapped;
+ else
+ {
+ for (ptrdiff_t i = nmapped - 1; i > 0; i--)
+ args[i + i] = args[i];
- for (ptrdiff_t i = 1; i < nargs; i += 2)
- args[i] = separator;
+ for (ptrdiff_t i = 1; i < nargs; i += 2)
+ args[i] = separator;
+ }
Lisp_Object ret = Fconcat (nargs, args);
SAFE_FREE ();
@@ -2965,6 +2975,9 @@ it does up to one space will be removed.
The user must confirm the answer with RET, and can edit it until it
has been confirmed.
+If the `use-short-answers' variable is non-nil, instead of asking for
+\"yes\" or \"no\", this function will ask for \"y\" or \"n\".
+
If dialog boxes are supported, a dialog box will be used
if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */)
(Lisp_Object prompt)
@@ -2991,7 +3004,7 @@ if `last-nonmenu-event' is nil, and `use-dialog-box' is non-nil. */)
AUTO_STRING (yes_or_no, "(yes or no) ");
prompt = CALLN (Fconcat, prompt, yes_or_no);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qenable_recursive_minibuffers, Qt);
while (1)
@@ -3105,25 +3118,25 @@ require_unwind (Lisp_Object old_value)
}
DEFUN ("require", Frequire, Srequire, 1, 3, 0,
- doc: /* If feature FEATURE is not loaded, load it from FILENAME.
-If FEATURE is not a member of the list `features', then the feature is
-not loaded; so load the file FILENAME.
+ doc: /* If FEATURE is not already loaded, load it from FILENAME.
+If FEATURE is not a member of the list `features', then the feature was
+not yet loaded; so load it from file FILENAME.
If FILENAME is omitted, the printname of FEATURE is used as the file
-name, and `load' will try to load this name appended with the suffix
-`.elc', `.el', or the system-dependent suffix for dynamic module
-files, in that order. The name without appended suffix will not be
-used. See `get-load-suffixes' for the complete list of suffixes.
+name, and `load' is called to try to load the file by that name, after
+appending the suffix `.elc', `.el', or the system-dependent suffix for
+dynamic module files, in that order; but the function will not try to
+load the file without any suffix. See `get-load-suffixes' for the
+complete list of suffixes.
-The directories in `load-path' are searched when trying to find the
-file name.
+To find the file, this function searches the directories in `load-path'.
-If the optional third argument NOERROR is non-nil, then return nil if
-the file is not found instead of signaling an error. Normally the
-return value is FEATURE.
+If the optional third argument NOERROR is non-nil, then, if
+the file is not found, the function returns nil instead of signaling
+an error. Normally the return value is FEATURE.
-The normal messages at start and end of loading FILENAME are
-suppressed. */)
+The normal messages issued by `load' at start and end of loading
+FILENAME are suppressed. */)
(Lisp_Object feature, Lisp_Object filename, Lisp_Object noerror)
{
Lisp_Object tem;
@@ -3153,14 +3166,19 @@ suppressed. */)
if (NILP (tem))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int nesting = 0;
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (will_dump_p () && !will_bootstrap_p ())
- error ("(require %s) while preparing to dump",
- SDATA (SYMBOL_NAME (feature)));
+ {
+ /* Avoid landing here recursively while outputting the
+ backtrace from the error. */
+ gflags.will_dump_ = false;
+ error ("(require %s) while preparing to dump",
+ SDATA (SYMBOL_NAME (feature)));
+ }
/* A certain amount of recursive `require' is legitimate,
but if we require the same feature recursively 3 times,
@@ -3180,12 +3198,8 @@ suppressed. */)
record_unwind_protect (require_unwind, require_nesting_list);
require_nesting_list = Fcons (feature, require_nesting_list);
- /* Value saved here is to be restored into Vautoload_queue */
- record_unwind_protect (un_autoload, Vautoload_queue);
- Vautoload_queue = Qt;
-
/* Load the file. */
- tem = save_match_data_load
+ tem = load_with_autoload_queue
(NILP (filename) ? Fsymbol_name (feature) : filename,
noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
@@ -3207,8 +3221,6 @@ suppressed. */)
SDATA (tem3), tem2);
}
- /* Once loading finishes, don't undo it. */
- Vautoload_queue = Qt;
feature = unbind_to (count, feature);
}
@@ -3222,22 +3234,25 @@ suppressed. */)
bottleneck of Widget operation. Here is their translation to C,
for the sole reason of efficiency. */
-DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
+DEFUN ("plist-member", Fplist_member, Splist_member, 2, 3, 0,
doc: /* Return non-nil if PLIST has the property PROP.
PLIST is a property list, which is a list of the form
\(PROP1 VALUE1 PROP2 VALUE2 ...).
-The comparison with PROP is done using `eq'.
+The comparison with PROP is done using PREDICATE, which defaults to
+`eq'.
Unlike `plist-get', this allows you to distinguish between a missing
property and a property with the value nil.
The value is actually the tail of PLIST whose car is PROP. */)
- (Lisp_Object plist, Lisp_Object prop)
+ (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate)
{
Lisp_Object tail = plist;
+ if (NILP (predicate))
+ predicate = Qeq;
FOR_EACH_TAIL (tail)
{
- if (EQ (XCAR (tail), prop))
+ if (!NILP (call2 (predicate, XCAR (tail), prop)))
return tail;
tail = XCDR (tail);
if (! CONSP (tail))
@@ -3247,13 +3262,22 @@ The value is actually the tail of PLIST whose car is PROP. */)
return Qnil;
}
+/* plist_member isn't used much in the Emacs sources, so just provide
+ a shim so that the function name follows the same pattern as
+ plist_get/plist_put. */
+Lisp_Object
+plist_member (Lisp_Object plist, Lisp_Object prop)
+{
+ return Fplist_member (plist, prop, Qnil);
+}
+
DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
doc: /* In WIDGET, set PROPERTY to VALUE.
The value can later be retrieved with `widget-get'. */)
(Lisp_Object widget, Lisp_Object property, Lisp_Object value)
{
CHECK_CONS (widget);
- XSETCDR (widget, Fplist_put (XCDR (widget), property, value));
+ XSETCDR (widget, plist_put (XCDR (widget), property, value));
return value;
}
@@ -3270,7 +3294,7 @@ later with `widget-put'. */)
if (NILP (widget))
return Qnil;
CHECK_CONS (widget);
- tmp = Fplist_member (XCDR (widget), property);
+ tmp = plist_member (XCDR (widget), property);
if (CONSP (tmp))
{
tmp = XCDR (tmp);
@@ -4160,13 +4184,13 @@ hash_table_user_defined_call (ptrdiff_t nargs, Lisp_Object *args,
{
if (!h->mutable)
return Ffuncall (nargs, args);
- ptrdiff_t count = inhibit_garbage_collection ();
+ specpdl_ref count = inhibit_garbage_collection ();
record_unwind_protect_ptr (restore_mutability, h);
h->mutable = false;
return unbind_to (count, Ffuncall (nargs, args));
}
-/* Ignore HT and compare KEY1 and KEY2 using 'eql'.
+/* Ignore H and compare KEY1 and KEY2 using 'eql'.
Value is true if KEY1 and KEY2 are the same. */
static Lisp_Object
@@ -4175,7 +4199,7 @@ cmpfn_eql (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h)
return Feql (key1, key2);
}
-/* Ignore HT and compare KEY1 and KEY2 using 'equal'.
+/* Ignore H and compare KEY1 and KEY2 using 'equal'.
Value is true if KEY1 and KEY2 are the same. */
static Lisp_Object
@@ -4185,7 +4209,7 @@ cmpfn_equal (Lisp_Object key1, Lisp_Object key2, struct Lisp_Hash_Table *h)
}
-/* Given HT, compare KEY1 and KEY2 using HT->user_cmp_function.
+/* Given H, compare KEY1 and KEY2 using H->user_cmp_function.
Value is true if KEY1 and KEY2 are the same. */
static Lisp_Object
@@ -4196,34 +4220,35 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2,
return hash_table_user_defined_call (ARRAYELTS (args), args, h);
}
-/* Ignore HT and return a hash code for KEY which uses 'eq' to compare
- keys. */
+/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys. */
static Lisp_Object
hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
{
+ if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
+ key = SYMBOL_WITH_POS_SYM (key);
return make_ufixnum (XHASH (key) ^ XTYPE (key));
}
-/* Ignore HT and return a hash code for KEY which uses 'equal' to compare keys.
+/* Ignore H and return a hash code for KEY which uses 'equal' to compare keys.
The hash code is at most INTMASK. */
-Lisp_Object
+static Lisp_Object
hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
{
return make_ufixnum (sxhash (key));
}
-/* Ignore HT and return a hash code for KEY which uses 'eql' to compare keys.
+/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys.
The hash code is at most INTMASK. */
-Lisp_Object
+static Lisp_Object
hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h)
{
return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h);
}
-/* Given HT, return a hash code for KEY which uses a user-defined
+/* Given H, return a hash code for KEY which uses a user-defined
function to compare keys. */
Lisp_Object
@@ -4479,7 +4504,8 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash)
{
ptrdiff_t start_of_bucket, i;
- Lisp_Object hash_code = h->test.hashfn (key, h);
+ Lisp_Object hash_code;
+ hash_code = h->test.hashfn (key, h);
if (hash)
*hash = hash_code;
@@ -4529,7 +4555,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
/* Store key/value in the key_and_value vector. */
i = h->next_free;
eassert (NILP (HASH_HASH (h, i)));
- eassert (EQ (Qunbound, (HASH_KEY (h, i))));
+ eassert (BASE_EQ (Qunbound, (HASH_KEY (h, i))));
h->next_free = HASH_NEXT (h, i);
set_hash_key_slot (h, i, key);
set_hash_value_slot (h, i, value);
@@ -4916,6 +4942,8 @@ sxhash_obj (Lisp_Object obj, int depth)
hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth));
return SXHASH_REDUCE (hash);
}
+ else if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS)
+ return sxhash_obj (XSYMBOL_WITH_POS (obj)->sym, depth + 1);
else
/* Others are 'equal' if they are 'eq', so take their
address as hash. */
@@ -4951,7 +4979,8 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
doc: /* Return an integer hash code for OBJ suitable for `eql'.
-If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)).
+If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)), but the opposite
+isn't necessarily true.
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
@@ -4961,7 +4990,8 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */)
DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
doc: /* Return an integer hash code for OBJ suitable for `equal'.
-If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)).
+If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)), but the
+opposite isn't necessarily true.
Hash codes are not guaranteed to be preserved across Emacs sessions. */)
(Lisp_Object obj)
@@ -5268,7 +5298,7 @@ FUNCTION is called with two arguments, KEY and VALUE.
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
Lisp_Object k = HASH_KEY (h, i);
- if (!EQ (k, Qunbound))
+ if (!BASE_EQ (k, Qunbound))
call2 (function, k, HASH_VALUE (h, i));
}
@@ -5918,9 +5948,12 @@ from the absolute start of the buffer, disregarding the narrowing. */)
if (!NILP (absolute))
start = BEG_BYTE;
- /* Check that POSITION is in the accessible range of the buffer. */
- if (pos < BEGV || pos > ZV)
+ /* Check that POSITION is in the accessible range of the buffer, or,
+ if we're reporting absolute positions, in the buffer. */
+ if (NILP (absolute) && (pos < BEGV || pos > ZV))
args_out_of_range_3 (make_int (pos), make_int (BEGV), make_int (ZV));
+ else if (!NILP (absolute) && (pos < 1 || pos > Z))
+ args_out_of_range_3 (make_int (pos), make_int (1), make_int (Z));
return make_int (count_lines (start, CHAR_TO_BYTE (pos)) + 1);
}
@@ -6096,8 +6129,6 @@ The same variable also affects the function `read-answer'. */);
defsubr (&Sget);
defsubr (&Splist_put);
defsubr (&Sput);
- defsubr (&Slax_plist_get);
- defsubr (&Slax_plist_put);
defsubr (&Seql);
defsubr (&Sequal);
defsubr (&Sequal_including_properties);
diff --git a/src/font.c b/src/font.c
index 266e5bc75c6..3846cfc1079 100644
--- a/src/font.c
+++ b/src/font.c
@@ -731,7 +731,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
{
Lisp_Object prev = Qnil;
- if (EQ (val, Qunbound))
+ if (BASE_EQ (val, Qunbound))
return val;
while (CONSP (extra)
&& NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
@@ -745,7 +745,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
return val;
}
XSETCDR (slot, val);
- if (EQ (val, Qunbound))
+ if (BASE_EQ (val, Qunbound))
ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
return val;
}
@@ -2183,7 +2183,9 @@ font_score (Lisp_Object entity, Lisp_Object *spec_prop)
/* Score three style numeric fields. Maximum difference is 127. */
for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
- if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
+ if (! NILP (spec_prop[i])
+ && ! EQ (AREF (entity, i), spec_prop[i])
+ && FIXNUMP (AREF (entity, i)))
{
EMACS_INT diff = ((XFIXNUM (AREF (entity, i)) >> 8)
- (XFIXNUM (spec_prop[i]) >> 8));
@@ -2764,26 +2766,31 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
{
if (FIXNUMP (AREF (spec, prop)))
{
- int required = XFIXNUM (AREF (spec, prop)) >> 8;
- int candidate = XFIXNUM (AREF (entity, prop)) >> 8;
+ if (!FIXNUMP (AREF (entity, prop)))
+ prop = FONT_SPEC_MAX;
+ else
+ {
+ int required = XFIXNUM (AREF (spec, prop)) >> 8;
+ int candidate = XFIXNUM (AREF (entity, prop)) >> 8;
- if (candidate != required
+ if (candidate != required
#ifdef HAVE_NTGUI
- /* A kludge for w32 font search, where listing a
- family returns only 4 standard weights: regular,
- italic, bold, bold-italic. For other values one
- must specify the font, not just the family in the
- :family attribute of the face. But specifying
- :family in the face attributes looks for regular
- weight, so if we require exact match, the
- non-regular font will be rejected. So we relax
- the accuracy of the match here, and let
- font_sort_entities find the best match. */
- && (prop != FONT_WEIGHT_INDEX
- || eabs (candidate - required) > 100)
+ /* A kludge for w32 font search, where listing a
+ family returns only 4 standard weights: regular,
+ italic, bold, bold-italic. For other values one
+ must specify the font, not just the family in the
+ :family attribute of the face. But specifying
+ :family in the face attributes looks for regular
+ weight, so if we require exact match, the
+ non-regular font will be rejected. So we relax
+ the accuracy of the match here, and let
+ font_sort_entities find the best match. */
+ && (prop != FONT_WEIGHT_INDEX
+ || eabs (candidate - required) > 100)
#endif
- )
- prop = FONT_SPEC_MAX;
+ )
+ prop = FONT_SPEC_MAX;
+ }
}
}
if (prop < FONT_SPEC_MAX
@@ -3582,8 +3589,8 @@ font_open_by_name (struct frame *f, Lisp_Object name)
The second is with frame F NULL. In this case, DRIVER is globally
registered in the variable `font_driver_list'. All font-driver
- implementations must call this function in its syms_of_XXXX
- (e.g. syms_of_xfont). */
+ implementations must call this function in its
+ syms_of_XXXX_for_pdumper (e.g. syms_of_xfont_for_pdumper). */
void
register_font_driver (struct font_driver const *driver, struct frame *f)
@@ -4230,26 +4237,33 @@ merge_font_spec (Lisp_Object from, Lisp_Object to)
DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
doc: /* Return the value of FONT's property KEY.
FONT is a font-spec, a font-entity, or a font-object.
-KEY is any symbol, but these are reserved for specific meanings:
- :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
- :size, :name, :script, :otf
+KEY can be any symbol, but these are reserved for specific meanings:
+ :foundry, :family, :adstyle, :registry, :weight, :slant, :width,
+ :size, :dpi, :spacing, :avgwidth, :script, :lang, :otf
See the documentation of `font-spec' for their meanings.
-In addition, if FONT is a font-entity or a font-object, values of
-:script and :otf are different from those of a font-spec as below:
-The value of :script may be a list of scripts that are supported by the font.
+If FONT is a font-entity or a font-object, then values of
+:script and :otf properties are different from those of a font-spec
+as below:
-The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
-representing the OpenType features supported by the font by this form:
- ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
-SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
-Layout tags.
+ The value of :script may be a list of scripts that are supported by
+ the font.
+
+ The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are
+ lists representing the OpenType features supported by the font, of
+ this form: ((SCRIPT (LANGSYS FEATURE ...) ...) ...), where
+ SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
+ Layout tags. See `otf-script-alist' for the OpenType script tags.
In addition to the keys listed above, the following keys are reserved
for the specific meanings as below:
-The value of :combining-capability is non-nil if the font-backend of
-FONT supports rendering of combining characters for non-OTF fonts. */)
+ The value of :type is a symbol that identifies the font backend to be
+ used, such as `ftcrhb' or `xfthb' on X , `harfbuzz' or `uniscribe' on
+ MS-Windows, `ns' on Cocoa/GNUstep, etc.
+
+ The value of :combining-capability is non-nil if the font-backend of
+ FONT supports rendering of combining characters for non-OTF fonts. */)
(Lisp_Object font, Lisp_Object key)
{
int idx;
@@ -4377,7 +4391,9 @@ accepted by the function `font-spec' (which see), VAL must be what
allowed in `font-spec'.
If FONT is a font-entity or a font-object, KEY must not be the one
-accepted by `font-spec'. */)
+accepted by `font-spec'.
+
+See also `font-get' for KEYs that have special meanings. */)
(Lisp_Object font, Lisp_Object prop, Lisp_Object val)
{
int idx;
diff --git a/src/font.h b/src/font.h
index 424616a4a1e..06bd297ccb2 100644
--- a/src/font.h
+++ b/src/font.h
@@ -155,8 +155,9 @@ enum font_property_index
/* In a font-spec, the value is an alist of extra information of a
font such as name, OpenType features, and language coverage.
In addition, in a font-entity, the value may contain a pair
- (font-entity . INFO) where INFO is extra information to identify
- a font (font-driver dependent). */
+ (font-entity . INFO) where INFO is extra information to
+ identify a font (font-driver dependent). In a font-entity,
+ this holds font driver-specific information. */
FONT_EXTRA_INDEX, /* alist alist */
/* This value is the length of font-spec vector. */
diff --git a/src/fontset.c b/src/fontset.c
index eb563a69e2b..1793715450e 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1450,28 +1450,30 @@ static void update_auto_fontset_alist (Lisp_Object, Lisp_Object);
DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
doc: /*
-Modify fontset NAME to use FONT-SPEC for TARGET characters.
+Modify FONTSET to use font specification in FONT-SPEC for displaying CHARACTERS.
-NAME is a fontset name (a string), nil for the fontset of FRAME,
-or t for the default fontset.
+FONTSET should be a fontset name (a string); or nil, meaning the
+fontset of FRAME; or t, meaning the default fontset.
-TARGET may be a single character to use FONT-SPEC for.
+CHARACTERS may be a single character to use FONT-SPEC for.
-TARGET may be a cons (FROM . TO), where FROM and TO are characters.
+CHARACTERS may be a cons (FROM . TO), where FROM and TO are characters.
In that case, use FONT-SPEC for all the characters in the range
between FROM and TO (inclusive).
-TARGET may be a script symbol. In that case, use FONT-SPEC for
+CHARACTERS may be a script symbol. In that case, use FONT-SPEC for
all the characters that belong to the script. See the variable
-`script-representative-chars' for the list of known scripts.
+`script-representative-chars' for the list of known scripts, and
+see the variable `char-script-table' for the script of any specific
+character.
-TARGET may be a charset. In that case, use FONT-SPEC for all
-the characters in the charset. See `list-character-sets' and
+CHARACTERS may be a charset symbol. In that case, use FONT-SPEC for
+all the characters in the charset. See `list-character-sets' and
`list-charset-chars' for the list of character sets and their
characters.
-TARGET may be nil. In that case, use FONT-SPEC for any character for
-which no font-spec is specified.
+CHARACTERS may be nil. In that case, use FONT-SPEC for any
+character for which no font-spec is specified in FONTSET.
FONT-SPEC may one of these:
* A font-spec object made by the function `font-spec' (which see).
@@ -1479,25 +1481,28 @@ FONT-SPEC may one of these:
REGISTRY is a font registry name. FAMILY may contain foundry
name, and REGISTRY may contain encoding name.
* A font name string.
- * nil, which explicitly specifies that there's no font for TARGET.
+ * nil, which explicitly specifies that there's no font for CHARACTERS.
-Optional 4th argument FRAME is a frame, or nil for the selected frame,
-to be considered in the case that NAME is nil.
+Optional 4th argument FRAME is a frame whose fontset should be modified;
+it is used if FONTSET is nil. If FONTSET is nil and FRAME is omitted
+or nil, that stands for the fontset of the selected frame.
Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
-to the previously set font specifications for TARGET. If it is
-`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
-appended. By default, FONT-SPEC overrides the previous settings. */)
- (Lisp_Object name, Lisp_Object target, Lisp_Object font_spec, Lisp_Object frame, Lisp_Object add)
+to the previously set font specifications for CHARACTERS. If it is
+`prepend', FONT-SPEC is prepended to the existing font specifications.
+If it is `append', FONT-SPEC is appended. By default, FONT-SPEC
+overwrites the previous settings. */)
+ (Lisp_Object fontset, Lisp_Object characters, Lisp_Object font_spec,
+ Lisp_Object frame, Lisp_Object add)
{
- Lisp_Object fontset;
+ Lisp_Object fontset_obj;
Lisp_Object font_def, registry, family;
Lisp_Object range_list;
struct charset *charset = NULL;
Lisp_Object fontname;
bool ascii_changed = 0;
- fontset = check_fontset_name (name, &frame);
+ fontset_obj = check_fontset_name (fontset, &frame);
fontname = Qnil;
if (CONSP (font_spec))
@@ -1555,18 +1560,18 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
else
font_def = Qnil;
- if (CHARACTERP (target))
+ if (CHARACTERP (characters))
{
- if (XFIXNAT (target) < 0x80)
+ if (XFIXNAT (characters) < 0x80)
error ("Can't set a font for partial ASCII range");
- range_list = list1 (Fcons (target, target));
+ range_list = list1 (Fcons (characters, characters));
}
- else if (CONSP (target))
+ else if (CONSP (characters))
{
Lisp_Object from, to;
- from = Fcar (target);
- to = Fcdr (target);
+ from = Fcar (characters);
+ to = Fcdr (characters);
CHECK_CHARACTER (from);
CHECK_CHARACTER (to);
if (XFIXNAT (from) < 0x80)
@@ -1575,38 +1580,38 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
error ("Can't set a font for partial ASCII range");
ascii_changed = 1;
}
- range_list = list1 (target);
+ range_list = list1 (characters);
}
- else if (SYMBOLP (target) && !NILP (target))
+ else if (SYMBOLP (characters) && !NILP (characters))
{
Lisp_Object script_list;
Lisp_Object val;
range_list = Qnil;
script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
- if (! NILP (Fmemq (target, script_list)))
+ if (! NILP (Fmemq (characters, script_list)))
{
- if (EQ (target, Qlatin))
+ if (EQ (characters, Qlatin))
ascii_changed = 1;
- val = list1 (target);
+ val = list1 (characters);
map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
val);
range_list = Fnreverse (XCDR (val));
}
- if (CHARSETP (target))
+ if (CHARSETP (characters))
{
- CHECK_CHARSET_GET_CHARSET (target, charset);
+ CHECK_CHARSET_GET_CHARSET (characters, charset);
if (charset->ascii_compatible_p)
ascii_changed = 1;
}
else if (NILP (range_list))
error ("Invalid script or charset name: %s",
- SDATA (SYMBOL_NAME (target)));
+ SDATA (SYMBOL_NAME (characters)));
}
- else if (NILP (target))
+ else if (NILP (characters))
range_list = list1 (Qnil);
else
- error ("Invalid target for setting a font");
+ error ("Invalid second argument for setting a font in a fontset");
if (ascii_changed)
{
@@ -1614,7 +1619,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
if (NILP (font_spec))
error ("Can't set ASCII font to nil");
- val = CHAR_TABLE_REF (fontset, 0);
+ val = CHAR_TABLE_REF (fontset_obj, 0);
if (! NILP (val) && EQ (add, Qappend))
/* We are going to change just an additional font for ASCII. */
ascii_changed = 0;
@@ -1622,7 +1627,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
if (charset)
{
- Lisp_Object arg = CALLN (Fvector, fontset, font_def, add,
+ Lisp_Object arg = CALLN (Fvector, fontset_obj, font_def, add,
ascii_changed ? Qt : Qnil, range_list);
map_charset_chars (set_fontset_font, Qnil, arg, charset,
@@ -1631,15 +1636,15 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
range_list = AREF (arg, 4);
}
for (; CONSP (range_list); range_list = XCDR (range_list))
- FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
+ FONTSET_ADD (fontset_obj, XCAR (range_list), font_def, add);
if (ascii_changed)
{
Lisp_Object tail, fr;
- int fontset_id = XFIXNUM (FONTSET_ID (fontset));
+ int fontset_id = XFIXNUM (FONTSET_ID (fontset_obj));
- set_fontset_ascii (fontset, fontname);
- name = FONTSET_NAME (fontset);
+ set_fontset_ascii (fontset_obj, fontname);
+ fontset = FONTSET_NAME (fontset_obj);
FOR_EACH_FRAME (tail, fr)
{
struct frame *f = XFRAME (fr);
@@ -1657,17 +1662,17 @@ appended. By default, FONT-SPEC overrides the previous settings. */)
font_object = font_open_by_spec (f, font_spec);
if (! NILP (font_object))
{
- update_auto_fontset_alist (font_object, fontset);
- AUTO_FRAME_ARG (arg, Qfont, Fcons (name, font_object));
+ update_auto_fontset_alist (font_object, fontset_obj);
+ AUTO_FRAME_ARG (arg, Qfont, Fcons (fontset, font_object));
Fmodify_frame_parameters (fr, arg);
}
}
}
- /* Free all realized fontsets whose base is FONTSET. This way, the
+ /* Free all realized fontsets whose base is FONTSET_OBJ. This way, the
specified character(s) are surely redisplayed by a correct
font. */
- free_realized_fontsets (fontset);
+ free_realized_fontsets (fontset_obj);
return Qnil;
}
diff --git a/src/frame.c b/src/frame.c
index 92120792f8f..923ef2d609a 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -277,6 +277,8 @@ The value is a symbol:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
+ `pgtk' for an Emacs frame using pure GTK facilities.
+ `haiku' for an Emacs frame running in Haiku.
FRAME defaults to the currently selected frame.
@@ -333,7 +335,7 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
* additionally limit the minimum frame height to a value large enough
* to support menu bar, tab bar, mode line and echo area.
*/
-int
+static int
frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
Lisp_Object ignore, Lisp_Object pixelwise)
{
@@ -1442,10 +1444,6 @@ affects all frames on the same terminal device. */)
If FRAME is a switch-frame event `(switch-frame FRAME1)', use
FRAME1 as frame.
- If TRACK is non-zero and the frame that currently has the focus
- redirects its focus to the selected frame, redirect that focused
- frame's focus to FRAME instead.
-
FOR_DELETION non-zero means that the selected frame is being
deleted, which includes the possibility that the frame's terminal
is dead.
@@ -1453,7 +1451,7 @@ affects all frames on the same terminal device. */)
The value of NORECORD is passed as argument to Fselect_window. */
Lisp_Object
-do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
+do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord)
{
struct frame *sf = SELECTED_FRAME (), *f;
@@ -1475,59 +1473,6 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
else if (f == sf)
return frame;
- /* If a frame's focus has been redirected toward the currently
- selected frame, we should change the redirection to point to the
- newly selected frame. This means that if the focus is redirected
- from a minibufferless frame to a surrogate minibuffer frame, we
- can use `other-window' to switch between all the frames using
- that minibuffer frame, and the focus redirection will follow us
- around. */
-#if 0
- /* This is too greedy; it causes inappropriate focus redirection
- that's hard to get rid of. */
- if (track)
- {
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object focus;
-
- if (!FRAMEP (XCAR (tail)))
- emacs_abort ();
-
- focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
-
- if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
- Fredirect_frame_focus (XCAR (tail), frame);
- }
- }
-#else /* ! 0 */
- /* Instead, apply it only to the frame we're pointing to. */
-#ifdef HAVE_WINDOW_SYSTEM
- if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
- {
- Lisp_Object focus, gfocus;
-
- gfocus = FRAME_TERMINAL (f)->get_focus_frame (f);
- if (FRAMEP (gfocus))
- {
- focus = FRAME_FOCUS_FRAME (XFRAME (gfocus));
- if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
- /* Redirect frame focus also when FRAME has its minibuffer
- window on the selected frame (see Bug#24500).
-
- Don't do that: It causes redirection problem with a
- separate minibuffer frame (Bug#24803) and problems
- when updating the cursor on such frames.
- || (NILP (focus)
- && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window))) */
- Fredirect_frame_focus (gfocus, frame);
- }
- }
-#endif /* HAVE_X_WINDOWS */
-#endif /* ! 0 */
-
if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
@@ -1570,6 +1515,19 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
last_nonminibuf_frame = XFRAME (selected_frame);
+ /* If the selected window in the target frame is its mini-window, we move
+ to a different window, the most recently used one, unless there is a
+ valid active minibuffer in the mini-window. */
+ if (EQ (f->selected_window, f->minibuffer_window)
+ /* The following test might fail if the mini-window contains a
+ non-active minibuffer. */
+ && NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt)))
+ {
+ Lisp_Object w = call1 (Qget_mru_window, frame);
+ if (WINDOW_LIVE_P (w)) /* W can be nil in minibuffer-only frames. */
+ Fset_frame_selected_window (frame, w, Qnil);
+ }
+
Fselect_window (f->selected_window, norecord);
/* We want to make sure that the next event generates a frame-switch
@@ -1612,7 +1570,7 @@ This function returns FRAME, or nil if FRAME has been deleted. */)
/* Do not select a tooltip frame (Bug#47207). */
error ("Cannot select a tooltip frame");
else
- return do_switch_frame (frame, 1, 0, norecord);
+ return do_switch_frame (frame, 0, norecord);
}
DEFUN ("handle-switch-frame", Fhandle_switch_frame,
@@ -1628,7 +1586,7 @@ necessarily represent user-visible input focus. */)
kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
run_hook (Qmouse_leave_buffer_hook);
- return do_switch_frame (event, 0, 0, Qnil);
+ return do_switch_frame (event, 0, Qnil);
}
DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
@@ -1985,6 +1943,15 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
else
error ("Attempt to delete the only frame");
}
+#ifdef HAVE_X_WINDOWS
+ else if ((x_dnd_in_progress && f == x_dnd_frame)
+ || (x_dnd_waiting_for_finish && f == x_dnd_finish_frame))
+ error ("Attempt to delete the drop source frame");
+#endif
+#ifdef HAVE_HAIKU
+ else if (f == haiku_dnd_frame)
+ error ("Attempt to delete the drop source frame");
+#endif
XSETFRAME (frame, f);
@@ -2134,7 +2101,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
Fraise_frame (frame1);
#endif
- do_switch_frame (frame1, 0, 1, Qnil);
+ do_switch_frame (frame1, 1, Qnil);
sf = SELECTED_FRAME ();
}
else
@@ -2152,6 +2119,17 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
x_clear_frame_selections (f);
#endif
+#ifdef HAVE_PGTK
+ if (FRAME_PGTK_P (f))
+ {
+ /* Do special selection events now, in case the window gets
+ destroyed by this deletion. Does this run Lisp code? */
+ swallow_events (false);
+
+ pgtk_clear_frame_selections (f);
+ }
+#endif
+
/* Free glyphs.
This function must be called before the window tree of the
frame is deleted because windows contain dynamically allocated
@@ -2323,7 +2301,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
kset_default_minibuffer_frame (kb, Qnil);
}
- /* Cause frame titles to update--necessary if we now have just one frame. */
+ /* Cause frame titles to update--necessary if we now have just one
+ frame. */
if (!is_tooltip_frame)
update_mode_lines = 15;
@@ -2380,9 +2359,12 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
}
DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
- doc: /* Delete FRAME, permanently eliminating it from use.
+ 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
+frames can be undeleted with `undelete-frame', which see.
+
A frame may not be deleted if its minibuffer serves as surrogate
minibuffer for another frame. Normally, you may not delete a frame if
all other frames are invisible, but if the second optional argument
@@ -2500,9 +2482,12 @@ vertical offset, measured in units of the frame's default character size.
If Emacs is running on a mouseless terminal or hasn't been programmed
to read the mouse position, it returns the selected frame for FRAME
and nil for X and Y.
-If `mouse-position-function' is non-nil, `mouse-position' calls it,
-passing the normal return value to that function as an argument,
-and returns whatever that function returns. */)
+
+FRAME might be nil if `track-mouse' is set to `drag-source'. This
+means there is no frame under the mouse. If `mouse-position-function'
+is non-nil, `mouse-position' calls it, passing the normal return value
+to that function as an argument, and returns whatever that function
+returns. */)
(void)
{
return mouse_position (true);
@@ -2529,7 +2514,7 @@ mouse_position (bool call_mouse_position_function)
&time_dummy);
}
- if (! NILP (x))
+ if (! NILP (x) && f)
{
int col = XFIXNUM (x);
int row = XFIXNUM (y);
@@ -2537,7 +2522,10 @@ mouse_position (bool call_mouse_position_function)
XSETINT (x, col);
XSETINT (y, row);
}
- XSETFRAME (lispy_dummy, f);
+ if (f)
+ XSETFRAME (lispy_dummy, f);
+ else
+ lispy_dummy = Qnil;
retval = Fcons (lispy_dummy, Fcons (x, y));
if (call_mouse_position_function && !NILP (Vmouse_position_function))
retval = call1 (Vmouse_position_function, retval);
@@ -2550,9 +2538,11 @@ DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
The position is given in pixel units, where (0, 0) is the
upper-left corner of the frame, X is the horizontal offset, and Y is
the vertical offset.
-If Emacs is running on a mouseless terminal or hasn't been programmed
-to read the mouse position, it returns the selected frame for FRAME
-and nil for X and Y. */)
+FRAME might be nil if `track-mouse' is set to `drag-source'. This
+means there is no frame under the mouse. If Emacs is running on a
+mouseless terminal or hasn't been programmed to read the mouse
+position, it returns the selected frame for FRAME and nil for X and
+Y. */)
(void)
{
struct frame *f;
@@ -2573,7 +2563,11 @@ and nil for X and Y. */)
&time_dummy);
}
- XSETFRAME (lispy_dummy, f);
+ if (f)
+ XSETFRAME (lispy_dummy, f);
+ else
+ lispy_dummy = Qnil;
+
retval = Fcons (lispy_dummy, Fcons (x, y));
if (!NILP (Vmouse_position_function))
retval = call1 (Vmouse_position_function, retval);
@@ -3490,7 +3484,10 @@ DEFUN ("frame-native-width", Fframe_native_width,
Sframe_native_width, 0, 1, 0,
doc: /* Return FRAME's native width in pixels.
For a terminal frame, the result really gives the width in characters.
-If FRAME is omitted or nil, the selected frame is used. */)
+If FRAME is omitted or nil, the selected frame is used.
+
+If you're interested only in the width of the text portion of the
+frame, see `frame-text-width' instead. */)
(Lisp_Object frame)
{
struct frame *f = decode_any_frame (frame);
@@ -3514,6 +3511,9 @@ minibuffer or echo area), mode line, and header line. It does not
include the tool bar or menu bar. With other graphical versions, it may
also include the tool bar and the menu bar.
+If you're interested only in the height of the text portion of the
+frame, see `frame-text-height' instead.
+
For a text terminal, it includes the menu bar. In this case, the
result is really in characters rather than pixels (i.e., is identical
to `frame-height'). */)
@@ -3611,7 +3611,7 @@ DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
DEFUN ("frame-child-frame-border-width", Fframe_child_frame_border_width, Sframe_child_frame_border_width, 0, 1, 0,
doc: /* Return width of FRAME's child-frame border in pixels.
- If FRAME's 'child-frame-border-width' parameter is nil, return FRAME's
+ If FRAME's `child-frame-border-width' parameter is nil, return FRAME's
internal border width instead. */)
(Lisp_Object frame)
{
@@ -3902,6 +3902,10 @@ static const struct frame_parm_table frame_parms[] =
{"z-group", SYMBOL_INDEX (Qz_group)},
{"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
{"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
+ {"alpha-background", SYMBOL_INDEX (Qalpha_background)},
+#ifdef HAVE_X_WINDOWS
+ {"shaded", SYMBOL_INDEX (Qshaded)},
+#endif
#ifdef NS_IMPL_COCOA
{"ns-appearance", SYMBOL_INDEX (Qns_appearance)},
{"ns-transparent-titlebar", SYMBOL_INDEX (Qns_transparent_titlebar)},
@@ -4241,7 +4245,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
}
/* Don't die if just one of these was set. */
- if (EQ (left, Qunbound))
+ if (BASE_EQ (left, Qunbound))
{
left_no_change = 1;
if (f->left_pos < 0)
@@ -4249,7 +4253,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
else
XSETINT (left, f->left_pos);
}
- if (EQ (top, Qunbound))
+ if (BASE_EQ (top, Qunbound))
{
top_no_change = 1;
if (f->top_pos < 0)
@@ -5019,6 +5023,34 @@ gui_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
}
+void
+gui_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ double alpha = 1.0;
+
+ if (NILP (arg))
+ alpha = 1.0;
+ else if (FLOATP (arg))
+ {
+ alpha = XFLOAT_DATA (arg);
+ if (! (0 <= alpha && alpha <= 1.0))
+ args_out_of_range (make_float (0.0), make_float (1.0));
+ }
+ else if (FIXNUMP (arg))
+ {
+ EMACS_INT ialpha = XFIXNUM (arg);
+ if (! (0 <= ialpha && ialpha <= 100))
+ args_out_of_range (make_fixnum (0), make_fixnum (100));
+ alpha = ialpha / 100.0;
+ }
+ else
+ wrong_type_argument (Qnumberp, arg);
+
+ f->alpha_background = alpha;
+
+ recompute_basic_faces (f);
+ SET_FRAME_GARBAGED (f);
+}
/**
* gui_set_no_special_glyphs:
@@ -5041,7 +5073,9 @@ gui_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object o
bool
gui_mouse_grabbed (Display_Info *dpyinfo)
{
- return (dpyinfo->grabbed
+ return ((dpyinfo->grabbed
+ || (dpyinfo->terminal->any_grab_hook
+ && dpyinfo->terminal->any_grab_hook (dpyinfo)))
&& dpyinfo->last_mouse_frame
&& FRAME_LIVE_P (dpyinfo->last_mouse_frame));
}
@@ -5379,7 +5413,7 @@ gui_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
value = gui_display_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
attribute, class, type);
- if (! NILP (value) && ! EQ (value, Qunbound))
+ if (! NILP (value) && ! BASE_EQ (value, Qunbound))
store_frame_param (f, param, value);
return value;
@@ -5400,7 +5434,7 @@ gui_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
Lisp_Object tem;
tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type);
- if (EQ (tem, Qunbound))
+ if (BASE_EQ (tem, Qunbound))
tem = deflt;
AUTO_FRAME_ARG (arg, prop, tem);
gui_set_frame_parameters (f, arg);
@@ -5662,9 +5696,9 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
- if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
+ if (!BASE_EQ (width, Qunbound) || !BASE_EQ (height, Qunbound))
{
- if (!EQ (width, Qunbound))
+ if (!BASE_EQ (width, Qunbound))
{
if (CONSP (width) && EQ (XCAR (width), Qtext_pixels))
{
@@ -5700,7 +5734,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
}
}
- if (!EQ (height, Qunbound))
+ if (!BASE_EQ (height, Qunbound))
{
if (CONSP (height) && EQ (XCAR (height), Qtext_pixels))
{
@@ -5738,7 +5772,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0,
RES_TYPE_NUMBER);
- if (!NILP (user_size) && !EQ (user_size, Qunbound))
+ if (!NILP (user_size) && !BASE_EQ (user_size, Qunbound))
window_prompting |= USSize;
else
window_prompting |= PSize;
@@ -5751,7 +5785,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0,
RES_TYPE_NUMBER);
- if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
+ if (! BASE_EQ (top, Qunbound) || ! BASE_EQ (left, Qunbound))
{
if (EQ (top, Qminus))
{
@@ -5774,7 +5808,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
else if (FLOATP (top))
f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
&outer_done, 0);
- else if (EQ (top, Qunbound))
+ else if (BASE_EQ (top, Qunbound))
f->top_pos = 0;
else
{
@@ -5804,7 +5838,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
else if (FLOATP (left))
f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
&outer_done, 0);
- else if (EQ (left, Qunbound))
+ else if (BASE_EQ (left, Qunbound))
f->left_pos = 0;
else
{
@@ -5813,7 +5847,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p,
window_prompting |= XNegative;
}
- if (!NILP (user_position) && ! EQ (user_position, Qunbound))
+ if (!NILP (user_position) && ! BASE_EQ (user_position, Qunbound))
window_prompting |= USPosition;
else
window_prompting |= PPosition;
@@ -6050,6 +6084,7 @@ syms_of_frame (void)
DEFSYM (Qfullheight, "fullheight");
DEFSYM (Qfullboth, "fullboth");
DEFSYM (Qmaximized, "maximized");
+ DEFSYM (Qshaded, "shaded");
DEFSYM (Qx_resource_name, "x-resource-name");
DEFSYM (Qx_frame_parameter, "x-frame-parameter");
@@ -6095,6 +6130,7 @@ syms_of_frame (void)
#endif
DEFSYM (Qalpha, "alpha");
+ DEFSYM (Qalpha_background, "alpha-background");
DEFSYM (Qauto_lower, "auto-lower");
DEFSYM (Qauto_raise, "auto-raise");
DEFSYM (Qborder_color, "border-color");
@@ -6194,14 +6230,24 @@ You can also use a floating number between 0.0 and 1.0. */);
doc: /* Alist of default values for frame creation.
These may be set in your init file, like this:
(setq default-frame-alist \\='((width . 80) (height . 55) (menu-bar-lines . 1)))
+
These override values given in window system configuration data,
- including X Windows' defaults database.
+including X Windows' defaults database.
+
+Note that many display-related modes (like `scroll-bar-mode' or
+`menu-bar-mode') alter `default-frame-alist', so if you set this
+variable directly, you may be overriding other settings
+unintentionally. Instead it's often better to use
+`modify-all-frames-parameters' or push new elements to the front of
+this alist.
+
For values specific to the first Emacs frame, see `initial-frame-alist'.
+
For window-system specific values, see `window-system-default-frame-alist'.
+
For values specific to the separate minibuffer frame, see
- `minibuffer-frame-alist'.
-The `menu-bar-lines' element of the list controls whether new frames
- have menu bars; `menu-bar-mode' works by altering this element.
+`minibuffer-frame-alist'.
+
Setting this variable does not affect existing frames, only new ones. */);
Vdefault_frame_alist = Qnil;
@@ -6221,7 +6267,7 @@ Setting this variable does not affect existing frames, only new ones. */);
DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
scroll_bar_adjust_thumb_portion_p,
- doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
+ doc: /* Adjust scroll bars for overscrolling for Gtk+, Motif and Haiku.
Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
even if the end of the buffer is shown (i.e. overscrolling).
Set to nil if you want the thumb to be at the bottom when the end of the buffer
@@ -6467,6 +6513,14 @@ This variable is effective only with the X toolkit (and there only when
Gtk+ tooltips are not used) and on Windows. */);
tooltip_reuse_hidden_frame = false;
+ DEFVAR_BOOL ("use-system-tooltips", use_system_tooltips,
+ doc: /* Use the toolkit to display tooltips.
+This option is only meaningful when Emacs is built with GTK+ or Haiku
+windowing support, and results in tooltips that look like those
+displayed by other GTK+ or Haiku programs, but will not be able to
+display text properties inside tooltip text. */);
+ use_system_tooltips = true;
+
DEFVAR_LISP ("iconify-child-frame", iconify_child_frame,
doc: /* How to handle iconification of child frames.
This variable tells Emacs how to proceed when it is asked to iconify a
@@ -6482,6 +6536,14 @@ making the child frame unresponsive to user actions, the default is to
iconify the top level frame instead. */);
iconify_child_frame = Qiconify_top_level;
+ DEFVAR_LISP ("frame-internal-parameters", frame_internal_parameters,
+ doc: /* Frame parameters specific to every frame. */);
+#ifdef HAVE_X_WINDOWS
+ frame_internal_parameters = list4 (Qname, Qparent_id, Qwindow_id, Qouter_window_id);
+#else
+ frame_internal_parameters = list3 (Qname, Qparent_id, Qwindow_id);
+#endif
+
defsubr (&Sframep);
defsubr (&Sframe_live_p);
defsubr (&Swindow_system);
diff --git a/src/frame.h b/src/frame.h
index cb2f58e2611..458b6257e49 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -102,6 +102,10 @@ struct frame
Lisp_Object parent_frame;
#endif /* HAVE_WINDOW_SYSTEM */
+ /* Last device to move over this frame. Any value that isn't a
+ string means the "Virtual core pointer". */
+ Lisp_Object last_mouse_device;
+
/* The frame which should receive keystrokes that occur in this
frame, or nil if they should go to the frame itself. This is
usually nil, but if the frame is minibufferless, we can use this
@@ -123,6 +127,7 @@ struct frame
/* This frame's selected window.
Each frame has its own window hierarchy
and one of the windows in it is selected within the frame.
+ This window may be the mini-window of the frame, if any.
The selected window of the selected frame is Emacs's selected window. */
Lisp_Object selected_window;
@@ -637,6 +642,9 @@ struct frame
Negative values mean not to change alpha. */
double alpha[2];
+ /* Background opacity */
+ double alpha_background;
+
/* Exponent for gamma correction of colors. 1/(VIEWING_GAMMA *
SCREEN_GAMMA) where viewing_gamma is 0.4545 and SCREEN_GAMMA is a
frame parameter. 0 means don't do gamma correction. */
@@ -1285,8 +1293,28 @@ SET_FRAME_VISIBLE (struct frame *f, int v)
}
/* Set iconified status of frame F. */
-#define SET_FRAME_ICONIFIED(f, i) \
- (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
+INLINE void
+SET_FRAME_ICONIFIED (struct frame *f, int i)
+{
+#ifdef HAVE_WINDOW_SYSTEM
+ Lisp_Object frame;
+#endif
+
+ eassert (0 <= (i) && (i) <= 1);
+
+ f->iconified = i;
+
+#ifdef HAVE_WINDOW_SYSTEM
+ /* Iconifying a frame might cause the frame title to change if no
+ title was explicitly specified. Force the frame title to be
+ recomputed. */
+
+ XSETFRAME (frame, f);
+
+ if (FRAME_WINDOW_P (f))
+ gui_consider_frame_title (frame);
+#endif
+}
extern Lisp_Object selected_frame;
extern Lisp_Object old_selected_frame;
@@ -1335,8 +1363,6 @@ extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object);
extern void adjust_frame_size (struct frame *, int, int, int, bool,
Lisp_Object);
extern Lisp_Object mouse_position (bool);
-extern int frame_windows_min_size (Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object);
extern void frame_size_history_plain (struct frame *, Lisp_Object);
extern void frame_size_history_extra (struct frame *, Lisp_Object,
int, int, int, int, int, int);
@@ -1669,6 +1695,7 @@ extern void gui_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object)
extern long gui_figure_window_size (struct frame *, Lisp_Object, bool, bool);
extern void gui_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
+extern void gui_set_alpha_background (struct frame *, Lisp_Object, Lisp_Object);
extern void gui_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
extern void validate_x_resource_name (void);
diff --git a/src/fringe.c b/src/fringe.c
index 1f4dd46ec5a..bf0b5fde761 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -30,7 +30,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "termhooks.h"
#include "pdumper.h"
-#include "pgtkterm.h"
+#ifdef HAVE_PGTK
+# include "pgtkterm.h"
+#endif
/* Fringe bitmaps are represented in three different ways:
@@ -971,7 +973,7 @@ update_window_fringes (struct window *w, bool keep_current_p)
if (w->pseudo_window_p)
return 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* This function could be called for redisplaying non-selected
windows, in which case point has been temporarily moved to that
@@ -1823,6 +1825,23 @@ gui_init_fringe (struct redisplay_interface *rif)
}
}
+/* Call frame F's specific define_fringe_bitmap method for a fringe
+ bitmap number N. Called by various *term.c functions when they
+ need to display a fringe bitmap whose terminal-specific data is not
+ available. */
+void
+gui_define_fringe_bitmap (struct frame *f, int n)
+{
+ struct redisplay_interface *rif = FRAME_RIF (f);
+
+ if (!rif || !rif->define_fringe_bitmap || n >= max_used_fringe_bitmap)
+ return;
+
+ struct fringe_bitmap *fb = fringe_bitmaps[n];
+ if (fb)
+ rif->define_fringe_bitmap (n, fb->bits, fb->height, fb->width);
+}
+
#ifdef HAVE_NTGUI
void
w32_reset_fringes (void)
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 558e44d5b91..6bb41110d5c 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -37,6 +37,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "font.h"
#include "ftfont.h"
#include "pdumper.h"
+#ifdef HAVE_PGTK
+#include "xsettings.h"
+#endif
#ifdef USE_BE_CAIRO
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
@@ -168,7 +171,12 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
cairo_matrix_t font_matrix, ctm;
cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size);
cairo_matrix_init_identity (&ctm);
+
+#ifdef HAVE_PGTK
+ cairo_font_options_t *options = xsettings_get_font_options ();
+#else
cairo_font_options_t *options = cairo_font_options_create ();
+#endif
#ifdef USE_BE_CAIRO
if (be_use_subpixel_antialiasing ())
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL);
@@ -522,12 +530,23 @@ ftcrfont_draw (struct glyph_string *s,
int from, int to, int x, int y, bool with_background)
{
struct frame *f = s->f;
- struct face *face = s->face;
struct font_info *ftcrfont_info = (struct font_info *) s->font;
cairo_t *cr;
cairo_glyph_t *glyphs;
int len = to - from;
int i;
+#ifdef USE_BE_CAIRO
+ unsigned long be_foreground, be_background;
+
+ if (s->hl != DRAW_CURSOR)
+ {
+ be_foreground = s->face->foreground;
+ be_background = s->face->background;
+ }
+ else
+ haiku_merge_cursor_foreground (s, &be_foreground,
+ &be_background);
+#endif
block_input ();
@@ -538,12 +557,12 @@ ftcrfont_draw (struct glyph_string *s,
cr = pgtk_begin_cr_clip (f);
#endif
#else
- BView_draw_lock (FRAME_HAIKU_VIEW (f));
+ /* Presumably the draw lock is already held by
+ haiku_draw_glyph_string. */
EmacsWindow_begin_cr_critical_section (FRAME_HAIKU_WINDOW (f));
cr = haiku_begin_cr_clip (f, s);
if (!cr)
{
- BView_draw_unlock (FRAME_HAIKU_VIEW (f));
EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
unblock_input ();
return 0;
@@ -555,23 +574,21 @@ ftcrfont_draw (struct glyph_string *s,
{
#ifndef USE_BE_CAIRO
#ifdef HAVE_X_WINDOWS
- x_set_cr_source_with_gc_background (f, s->gc);
+ x_set_cr_source_with_gc_background (f, s->gc, s->hl != DRAW_CURSOR);
#else
- pgtk_set_cr_source_with_color (f, s->xgcv.background);
+ pgtk_set_cr_source_with_color (f, s->xgcv.background,
+ s->hl != DRAW_CURSOR);
#endif
#else
- struct face *face = s->face;
-
- uint32_t col = s->hl == DRAW_CURSOR ?
- FRAME_CURSOR_COLOR (s->f).pixel : face->background;
+ uint32_t col = be_background;
cairo_set_source_rgb (cr, RED_FROM_ULONG (col) / 255.0,
GREEN_FROM_ULONG (col) / 255.0,
BLUE_FROM_ULONG (col) / 255.0);
#endif
s->background_filled_p = 1;
- cairo_rectangle (cr, x, y - FONT_BASE (face->font),
- s->width, FONT_HEIGHT (face->font));
+ cairo_rectangle (cr, x, y - FONT_BASE (s->font),
+ s->width, FONT_HEIGHT (s->font));
cairo_fill (cr);
}
@@ -587,13 +604,12 @@ ftcrfont_draw (struct glyph_string *s,
}
#ifndef USE_BE_CAIRO
#ifdef HAVE_X_WINDOWS
- x_set_cr_source_with_gc_foreground (f, s->gc);
+ x_set_cr_source_with_gc_foreground (f, s->gc, false);
#else
- pgtk_set_cr_source_with_color (f, s->xgcv.foreground);
+ pgtk_set_cr_source_with_color (f, s->xgcv.foreground, false);
#endif
#else
- uint32_t col = s->hl == DRAW_CURSOR ?
- FRAME_OUTPUT_DATA (s->f)->cursor_fg : face->foreground;
+ uint32_t col = be_foreground;
cairo_set_source_rgb (cr, RED_FROM_ULONG (col) / 255.0,
GREEN_FROM_ULONG (col) / 255.0,
@@ -610,13 +626,34 @@ ftcrfont_draw (struct glyph_string *s,
#else
haiku_end_cr_clip (cr);
EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
- BView_draw_unlock (FRAME_HAIKU_VIEW (f));
#endif
unblock_input ();
return len;
}
+#ifdef HAVE_PGTK
+/* Determine if FONT_OBJECT is a valid cached font for ENTITY by
+ comparing the options used to open it with the user's current
+ preferences specified via GSettings. */
+static bool
+ftcrfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
+ Lisp_Object entity)
+{
+ struct font_info *info = (struct font_info *) XFONT_OBJECT (font_object);
+
+ cairo_font_options_t *options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (info->cr_scaled_font, options);
+ cairo_font_options_t *gsettings_options = xsettings_get_font_options ();
+
+ bool equal = cairo_font_options_equal (options, gsettings_options);
+ cairo_font_options_destroy (options);
+ cairo_font_options_destroy (gsettings_options);
+
+ return equal;
+}
+#endif
+
#ifdef HAVE_HARFBUZZ
static Lisp_Object
@@ -687,6 +724,9 @@ struct font_driver const ftcrfont_driver =
#endif
.filter_properties = ftfont_filter_properties,
.combining_capability = ftfont_combining_capability,
+#ifdef HAVE_PGTK
+ .cached_font_ok = ftcrfont_cached_font_ok
+#endif
};
#ifdef HAVE_HARFBUZZ
struct font_driver ftcrhbfont_driver;
diff --git a/src/ftfont.c b/src/ftfont.c
index 2bdcce306bc..301a145b7ac 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -189,6 +189,24 @@ ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
return Qnil;
if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
return Qnil;
+#ifdef FC_VARIABLE
+ /* This is a virtual/meta FcPattern for a variable weight font, from
+ which it is possible to extract an FcRange value specifying the
+ minimum and maximum weights available in this file. We don't
+ need to know that information explicitly, so skip it. We will be
+ called with an FcPattern for each actually available, non-virtual
+ weight.
+
+ Fontconfig started generating virtual/meta patterns for variable
+ weight fonts in the same release that FC_VARIABLE was added, so
+ we conditionalize on that constant. This also ensures that
+ FcPatternGetRange is available. */
+ FcRange *range;
+ if (FcPatternGetRange (p, FC_WEIGHT, 0, &range) == FcResultMatch
+ && FcPatternGetBool (p, FC_VARIABLE, 0, &b) == FcResultMatch
+ && b == FcTrue)
+ return Qnil;
+#endif /* FC_VARIABLE */
file = (char *) str;
key = Fcons (build_unibyte_string (file), make_fixnum (idx));
@@ -627,8 +645,29 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec)
return spec;
}
+#if defined HAVE_XFT && defined FC_COLOR
+static bool
+xft_color_font_whitelisted_p (const char *family)
+{
+ Lisp_Object tem, name;
+
+ tem = Vxft_color_font_whitelist;
+
+ FOR_EACH_TAIL_SAFE (tem)
+ {
+ name = XCAR (tem);
+
+ if (STRINGP (name) && !strcmp (family, SSDATA (name)))
+ return true;
+ }
+
+ return false;
+}
+#endif
+
static FcPattern *
-ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, const char **langname)
+ftfont_spec_pattern (Lisp_Object spec, char *otlayout,
+ struct OpenTypeSpec **otspec, const char **langname)
{
Lisp_Object tmp, extra;
FcPattern *pattern = NULL;
@@ -767,6 +806,8 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
/* We really don't like color fonts, they cause Xft crashes. See
Bug#30874. */
if (xft_ignore_color_fonts
+ && (NILP (AREF (spec, FONT_FAMILY_INDEX))
+ || NILP (Vxft_color_font_whitelist))
&& ! FcPatternAddBool (pattern, FC_COLOR, FcFalse))
goto err;
#endif
@@ -863,6 +904,9 @@ ftfont_list (struct frame *f, Lisp_Object spec)
#if defined HAVE_XFT && defined FC_COLOR
FC_COLOR,
#endif
+#ifdef FC_VARIABLE
+ FC_VARIABLE,
+#endif /* FC_VARIABLE */
NULL);
if (! objset)
goto err;
@@ -909,7 +953,12 @@ ftfont_list (struct frame *f, Lisp_Object spec)
returns them even when it shouldn't really do so, so we
need to manually skip them here (Bug#37786). */
FcBool b;
+ FcChar8 *str;
+
if (xft_ignore_color_fonts
+ && (FcPatternGetString (fontset->fonts[i], FC_FAMILY,
+ 0, &str) != FcResultMatch
+ || !xft_color_font_whitelisted_p ((char *) str))
&& FcPatternGetBool (fontset->fonts[i], FC_COLOR, 0, &b)
== FcResultMatch && b != FcFalse)
continue;
diff --git a/src/gnutls.c b/src/gnutls.c
index 3ec38370679..a0de0238c47 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -616,6 +616,9 @@ gnutls_try_handshake (struct Lisp_Process *proc)
gnutls_session_t state = proc->gnutls_state;
int ret;
bool non_blocking = proc->is_non_blocking_client;
+ /* Sleep for ten milliseconds when busy-looping in
+ gnutls_handshake. */
+ struct timespec delay = { 0, 1000 * 1000 * 10 };
if (proc->gnutls_complete_negotiation_p)
non_blocking = false;
@@ -630,6 +633,7 @@ gnutls_try_handshake (struct Lisp_Process *proc)
maybe_quit ();
if (non_blocking && ret != GNUTLS_E_INTERRUPTED)
break;
+ nanosleep (&delay, NULL);
}
proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
@@ -1517,7 +1521,7 @@ returned as the :certificate entry. */)
/* Initialize global GnuTLS state to defaults.
Call 'gnutls-global-deinit' when GnuTLS usage is no longer needed.
Return zero on success. */
-Lisp_Object
+static Lisp_Object
emacs_gnutls_global_init (void)
{
int ret = GNUTLS_E_SUCCESS;
@@ -1631,10 +1635,10 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
char *c_hostname;
if (NILP (proplist))
- proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters));
+ proplist = Fcdr (plist_get (p->childp, QCtls_parameters));
- verify_error = Fplist_get (proplist, QCverify_error);
- hostname = Fplist_get (proplist, QChostname);
+ verify_error = plist_get (proplist, QCverify_error);
+ hostname = plist_get (proplist, QChostname);
if (EQ (verify_error, Qt))
verify_error_all = true;
@@ -1664,7 +1668,7 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
p->gnutls_peer_verification = peer_verification;
- warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings"));
+ warnings = plist_get (Fgnutls_peer_status (proc), intern (":warnings"));
if (!NILP (warnings))
{
for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail))
@@ -1866,13 +1870,13 @@ one trustfile (usually a CA bundle). */)
return Qnil;
}
- hostname = Fplist_get (proplist, QChostname);
- priority_string = Fplist_get (proplist, QCpriority);
- trustfiles = Fplist_get (proplist, QCtrustfiles);
- keylist = Fplist_get (proplist, QCkeylist);
- crlfiles = Fplist_get (proplist, QCcrlfiles);
- loglevel = Fplist_get (proplist, QCloglevel);
- prime_bits = Fplist_get (proplist, QCmin_prime_bits);
+ hostname = plist_get (proplist, QChostname);
+ priority_string = plist_get (proplist, QCpriority);
+ trustfiles = plist_get (proplist, QCtrustfiles);
+ keylist = plist_get (proplist, QCkeylist);
+ crlfiles = plist_get (proplist, QCcrlfiles);
+ loglevel = plist_get (proplist, QCloglevel);
+ prime_bits = plist_get (proplist, QCmin_prime_bits);
if (!STRINGP (hostname))
{
@@ -1925,7 +1929,7 @@ one trustfile (usually a CA bundle). */)
check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred));
XPROCESS (proc)->gnutls_x509_cred = x509_cred;
- verify_flags = Fplist_get (proplist, QCverify_flags);
+ verify_flags = plist_get (proplist, QCverify_flags);
if (TYPE_RANGED_FIXNUMP (unsigned int, verify_flags))
{
gnutls_verify_flags = XFIXNAT (verify_flags);
@@ -2105,7 +2109,7 @@ one trustfile (usually a CA bundle). */)
}
XPROCESS (proc)->gnutls_complete_negotiation_p =
- !NILP (Fplist_get (proplist, QCcomplete_negotiation));
+ !NILP (plist_get (proplist, QCcomplete_negotiation));
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
ret = emacs_gnutls_handshake (XPROCESS (proc));
if (ret < GNUTLS_E_SUCCESS)
@@ -2344,7 +2348,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
if (!NILP (info) && CONSP (info))
{
- Lisp_Object v = Fplist_get (info, QCcipher_id);
+ Lisp_Object v = plist_get (info, QCcipher_id);
if (TYPE_RANGED_FIXNUMP (gnutls_cipher_algorithm_t, v))
gca = XFIXNUM (v);
}
@@ -2621,7 +2625,7 @@ itself. */)
if (!NILP (info) && CONSP (info))
{
- Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
+ Lisp_Object v = plist_get (info, QCmac_algorithm_id);
if (TYPE_RANGED_FIXNUMP (gnutls_mac_algorithm_t, v))
gma = XFIXNUM (v);
}
@@ -2711,7 +2715,7 @@ the number itself. */)
if (!NILP (info) && CONSP (info))
{
- Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
+ Lisp_Object v = plist_get (info, QCdigest_algorithm_id);
if (TYPE_RANGED_FIXNUMP (gnutls_digest_algorithm_t, v))
gda = XFIXNUM (v);
}
diff --git a/src/gnutls.h b/src/gnutls.h
index 791e5340c2d..19d3d3f5bc6 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -90,7 +90,6 @@ extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err);
extern int w32_gnutls_rnd (gnutls_rnd_level_t, void *, size_t);
#endif
extern Lisp_Object emacs_gnutls_deinit (Lisp_Object);
-extern Lisp_Object emacs_gnutls_global_init (void);
extern int gnutls_try_handshake (struct Lisp_Process *p);
extern Lisp_Object gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 93f51d77962..f2018bc01f5 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -76,6 +76,34 @@ typedef struct pgtk_output xp_output;
#define XG_TEXT_OPEN GTK_STOCK_OPEN
#endif
+#ifdef HAVE_GTK3
+static void emacs_menu_bar_get_preferred_width (GtkWidget *, gint *, gint *);
+static GType emacs_menu_bar_get_type (void);
+
+typedef struct _EmacsMenuBar
+{
+ GtkMenuBar parent;
+} EmacsMenuBar;
+
+typedef struct _EmacsMenuBarClass
+{
+ GtkMenuBarClass parent;
+} EmacsMenuBarClass;
+
+G_DEFINE_TYPE (EmacsMenuBar, emacs_menu_bar, GTK_TYPE_MENU_BAR)
+#endif
+
+#ifndef HAVE_PGTK
+static void xg_im_context_commit (GtkIMContext *, gchar *, gpointer);
+static void xg_im_context_preedit_changed (GtkIMContext *, gpointer);
+static void xg_im_context_preedit_end (GtkIMContext *, gpointer);
+static bool xg_widget_key_press_event_cb (GtkWidget *, GdkEvent *, gpointer);
+#endif
+
+#if GTK_CHECK_VERSION (3, 10, 0)
+static void xg_widget_style_updated (GtkWidget *, gpointer);
+#endif
+
#ifndef HAVE_GTK3
#ifdef HAVE_FREETYPE
@@ -114,7 +142,46 @@ struct xg_frame_tb_info
bool xg_gtk_initialized; /* Used to make sure xwidget calls are possible */
#endif
-static GtkWidget * xg_get_widget_from_map (ptrdiff_t idx);
+static GtkWidget *xg_get_widget_from_map (ptrdiff_t idx, Display *dpy);
+
+
+
+#ifdef HAVE_GTK3
+static void
+emacs_menu_bar_init (EmacsMenuBar *menu_bar)
+{
+ return;
+}
+
+static void
+emacs_menu_bar_class_init (EmacsMenuBarClass *klass)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->get_preferred_width = emacs_menu_bar_get_preferred_width;
+}
+
+static void
+emacs_menu_bar_get_preferred_width (GtkWidget *widget,
+ gint *minimum, gint *natural)
+{
+ GtkWidgetClass *widget_class;
+
+ widget_class = GTK_WIDGET_CLASS (emacs_menu_bar_parent_class);
+ widget_class->get_preferred_width (widget, minimum, natural);
+
+ if (minimum)
+ *minimum = 0;
+}
+
+static GtkWidget *
+emacs_menu_bar_new (void)
+{
+ return GTK_WIDGET (g_object_new (emacs_menu_bar_get_type (), NULL));
+}
+
+#endif
/***********************************************************************
@@ -199,6 +266,7 @@ xg_display_open (char *display_name, GdkDisplay **dpy)
static int
xg_get_gdk_scale (void)
{
+#ifdef HAVE_GTK3
const char *sscale = getenv ("GDK_SCALE");
if (sscale)
@@ -207,6 +275,7 @@ xg_get_gdk_scale (void)
if (0 < scale)
return min (scale, INT_MAX);
}
+#endif
return 1;
}
@@ -667,67 +736,74 @@ xg_check_special_colors (struct frame *f,
const char *color_name,
Emacs_Color *color)
{
- bool success_p = 0;
- bool get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
- bool get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
+ bool success_p;
+ bool get_bg;
+ bool get_fg;
+#ifdef HAVE_GTK3
+ GtkStyleContext *gsty;
+ GdkRGBA col;
+ char buf[sizeof "rgb://rrrr/gggg/bbbb"];
+ int state;
+ GdkRGBA *c;
+ unsigned short r, g, b;
+#else
+ GtkStyle *gsty;
+ GdkColor *grgb;
+#endif
+
+ get_bg = !strcmp ("gtk_selection_bg_color", color_name);
+ get_fg = !get_bg && !strcmp ("gtk_selection_fg_color", color_name);
+ success_p = false;
+
+#ifdef HAVE_PGTK
+ while (FRAME_PARENT_FRAME (f))
+ f = FRAME_PARENT_FRAME (f);
+#endif
- if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg))
+ if (!FRAME_GTK_WIDGET (f) || !(get_bg || get_fg))
return success_p;
block_input ();
- {
#ifdef HAVE_GTK3
-#ifndef HAVE_PGTK
- GtkStyleContext *gsty
- = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
-#else
- GtkStyleContext *gsty
- = gtk_widget_get_style_context (FRAME_WIDGET (f));
-#endif
- GdkRGBA col;
- char buf[sizeof "rgb://rrrr/gggg/bbbb"];
- int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
- if (get_fg)
- gtk_style_context_get_color (gsty, state, &col);
- else
- {
- GdkRGBA *c;
- /* FIXME: Retrieving the background color is deprecated in
- GTK+ 3.16. New versions of GTK+ don't use the concept of a
- single background color any more, so we shouldn't query for
- it. */
- gtk_style_context_get (gsty, state,
- GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c,
- NULL);
- col = *c;
- gdk_rgba_free (c);
- }
+ gsty = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+ state = GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED;
+
+ if (get_fg)
+ gtk_style_context_get_color (gsty, state, &col);
+ else
+ {
+ /* FIXME: Retrieving the background color is deprecated in
+ GTK+ 3.16. New versions of GTK+ don't use the concept of a
+ single background color any more, so we shouldn't query for
+ it. */
+ gtk_style_context_get (gsty, state,
+ GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c,
+ NULL);
+ col = *c;
+ gdk_rgba_free (c);
+ }
- unsigned short
- r = col.red * 65535,
- g = col.green * 65535,
- b = col.blue * 65535;
+ r = col.red * 65535;
+ g = col.green * 65535;
+ b = col.blue * 65535;
#ifndef HAVE_PGTK
- sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b);
- success_p = x_parse_color (f, buf, color) != 0;
+ sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b);
+ success_p = x_parse_color (f, buf, color) != 0;
#else
- sprintf (buf, "#%04x%04x%04x", r, g, b);
- success_p = pgtk_parse_color (f, buf, color) != 0;
+ sprintf (buf, "#%04x%04x%04x", r, g, b);
+ success_p = pgtk_parse_color (f, buf, color) != 0;
#endif
#else
- GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
- GdkColor *grgb = get_bg
- ? &gsty->bg[GTK_STATE_SELECTED]
- : &gsty->fg[GTK_STATE_SELECTED];
+ gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
+ grgb = (get_bg ? &gsty->bg[GTK_STATE_SELECTED]
+ : &gsty->fg[GTK_STATE_SELECTED]);
- color->red = grgb->red;
- color->green = grgb->green;
- color->blue = grgb->blue;
- color->pixel = grgb->pixel;
- success_p = 1;
+ color->red = grgb->red;
+ color->green = grgb->green;
+ color->blue = grgb->blue;
+ color->pixel = grgb->pixel;
+ success_p = 1;
#endif
-
- }
unblock_input ();
return success_p;
}
@@ -992,6 +1068,7 @@ xg_set_geometry (struct frame *f)
/* Handle negative positions without consulting
gtk_window_parse_geometry (Bug#25851). The position will
be off by scrollbar width + window manager decorations. */
+#ifndef HAVE_PGTK
if (f->size_hint_flags & XNegative)
f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
- FRAME_PIXEL_WIDTH (f) + f->left_pos);
@@ -999,6 +1076,15 @@ xg_set_geometry (struct frame *f)
if (f->size_hint_flags & YNegative)
f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
- FRAME_PIXEL_HEIGHT (f) + f->top_pos);
+#else
+ if (f->size_hint_flags & XNegative)
+ f->left_pos = (pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f))
+ - FRAME_PIXEL_WIDTH (f) + f->left_pos);
+
+ if (f->size_hint_flags & YNegative)
+ f->top_pos = (pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f))
+ - FRAME_PIXEL_HEIGHT (f) + f->top_pos);
+#endif
/* GTK works in scaled pixels, so convert from X pixels. */
gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
@@ -1113,7 +1199,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
outer_height /= xg_get_scale (f);
outer_width /= xg_get_scale (f);
- x_wm_set_size_hint (f, 0, 0);
+ xg_wm_set_size_hint (f, 0, 0);
/* Resize the top level widget so rows and columns remain constant.
@@ -1159,7 +1245,11 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f))
{
was_visible = true;
+#ifndef HAVE_PGTK
hide_child_frame = EQ (x_gtk_resize_child_frames, Qhide);
+#else
+ hide_child_frame = false;
+#endif
if (outer_width != gwidth || outer_height != gheight)
{
@@ -1437,6 +1527,9 @@ xg_create_frame_widgets (struct frame *f)
#ifndef HAVE_GTK3
GtkRcStyle *style;
#endif
+#ifndef HAVE_PGTK
+ GtkIMContext *imc;
+#endif
GtkWindowType type = GTK_WINDOW_TOPLEVEL;
char *title = 0;
@@ -1459,6 +1552,12 @@ xg_create_frame_widgets (struct frame *f)
gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK);
#endif
+ gtk_widget_set_app_paintable (wtop, f->alpha_background != 1.0);
+#if GTK_CHECK_VERSION (3, 10, 0)
+ g_signal_connect (G_OBJECT (wtop), "style-updated",
+ G_CALLBACK (xg_widget_style_updated), f);
+#endif
+
/* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu
has backported it to Gtk+ 2.0 and they add the resize grip for
Gtk+ 2.0 applications also. But it has a bug that makes Emacs loop
@@ -1530,10 +1629,7 @@ xg_create_frame_widgets (struct frame *f)
with regular X drawing primitives, so from a GTK/GDK point of
view, the widget is totally blank. When an expose comes, this
will make the widget blank, and then Emacs redraws it. This flickers
- a lot, so we turn off double buffering.
- FIXME: gtk_widget_set_double_buffered is deprecated and might stop
- working in the future. We need to migrate away from combining
- X and GTK+ drawing to a pure GTK+ build. */
+ a lot, so we turn off double buffering. */
#ifndef HAVE_PGTK
gtk_widget_set_double_buffered (wfixed, FALSE);
@@ -1577,6 +1673,21 @@ xg_create_frame_widgets (struct frame *f)
#endif
| GDK_VISIBILITY_NOTIFY_MASK);
+ GdkScreen *screen = gtk_widget_get_screen (wtop);
+
+#if !defined HAVE_PGTK
+ GdkVisual *visual = gdk_x11_screen_lookup_visual (screen,
+ XVisualIDFromVisual (FRAME_X_VISUAL (f)));
+
+ if (!visual)
+ emacs_abort ();
+#else
+ GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
+#endif
+
+ gtk_widget_set_visual (wtop, visual);
+ gtk_widget_set_visual (wfixed, visual);
+
#ifndef HAVE_PGTK
/* Must realize the windows so the X window gets created. It is used
by callers of this function. */
@@ -1598,6 +1709,7 @@ xg_create_frame_widgets (struct frame *f)
/* Must use g_strdup because gtk_widget_modify_style does g_free. */
style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
gtk_widget_modify_style (wfixed, style);
+ gtk_widget_set_can_focus (wfixed, TRUE);
#else
gtk_widget_set_can_focus (wfixed, TRUE);
#ifdef HAVE_PGTK
@@ -1621,10 +1733,25 @@ xg_create_frame_widgets (struct frame *f)
#ifndef HAVE_PGTK
gtk_widget_set_tooltip_text (wtop, "Dummy text");
g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f);
+
+ imc = gtk_im_multicontext_new ();
+ g_object_ref (imc);
+ gtk_im_context_set_use_preedit (imc, TRUE);
+
+ g_signal_connect (G_OBJECT (imc), "commit",
+ G_CALLBACK (xg_im_context_commit), f);
+ g_signal_connect (G_OBJECT (imc), "preedit-changed",
+ G_CALLBACK (xg_im_context_preedit_changed), NULL);
+ g_signal_connect (G_OBJECT (imc), "preedit-end",
+ G_CALLBACK (xg_im_context_preedit_end), NULL);
+ FRAME_X_OUTPUT (f)->im_context = imc;
+
+ g_signal_connect (G_OBJECT (wfixed), "key-press-event",
+ G_CALLBACK (xg_widget_key_press_event_cb),
+ NULL);
#endif
{
- GdkScreen *screen = gtk_widget_get_screen (wtop);
GtkSettings *gs = gtk_settings_get_for_screen (screen);
/* Only connect this signal once per screen. */
if (! g_signal_handler_find (G_OBJECT (gs),
@@ -1761,6 +1888,7 @@ xg_free_frame_widgets (struct frame *f)
/* x_free_frame_resources should have taken care of it */
#ifndef HAVE_PGTK
eassert (!FRAME_X_DOUBLE_BUFFERED_P (f));
+ g_object_unref (FRAME_X_OUTPUT (f)->im_context);
#endif
gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
@@ -1787,7 +1915,7 @@ xg_free_frame_widgets (struct frame *f)
flag (this is useful when FLAGS is 0). */
void
-x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
+xg_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
{
/* Must use GTK routines here, otherwise GTK resets the size hints
to its own defaults. */
@@ -1875,12 +2003,12 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
else if (win_gravity == StaticGravity)
size_hints.win_gravity = GDK_GRAVITY_STATIC;
- if (x_gtk_use_window_move)
- {
- if (flags & PPosition) hint_flags |= GDK_HINT_POS;
- if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS;
- if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE;
- }
+ if (flags & PPosition)
+ hint_flags |= GDK_HINT_POS;
+ if (flags & USPosition)
+ hint_flags |= GDK_HINT_USER_POS;
+ if (flags & USSize)
+ hint_flags |= GDK_HINT_USER_SIZE;
if (user_position)
{
@@ -1927,8 +2055,8 @@ xg_set_background_color (struct frame *f, unsigned long bg)
!NILP (bar);
bar = XSCROLL_BAR (bar)->next)
{
- GtkWidget *scrollbar =
- xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window);
+ GtkWidget *scrollbar = xg_get_widget_from_map (XSCROLL_BAR (bar)->x_window,
+ FRAME_X_DISPLAY (f));
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f));
}
@@ -2326,7 +2454,7 @@ xg_maybe_add_timer (gpointer data)
static int
xg_dialog_run (struct frame *f, GtkWidget *w)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct xg_dialog_data dd;
xg_set_screen (w, f);
@@ -2928,6 +3056,16 @@ xg_mark_data (void)
}
}
}
+
+#ifndef HAVE_PGTK
+ if (xg_pending_quit_event.kind != NO_EVENT)
+ {
+ eassert (xg_pending_quit_event.kind == ASCII_KEYSTROKE_EVENT);
+
+ mark_object (xg_pending_quit_event.frame_or_window);
+ mark_object (xg_pending_quit_event.arg);
+ }
+#endif
}
/* Callback called when a menu item is destroyed. Used to free data.
@@ -3158,8 +3296,13 @@ menu_bar_button_pressed_cb (GtkWidget *widget, GdkEvent *event,
{
struct frame *f = user_data;
- if (event->button.button < 4)
- set_frame_menubar (f, true);
+ if (event->button.button < 4
+ && event->button.window != gtk_widget_get_window (widget)
+ && !popup_activated ())
+ {
+ pgtk_menu_set_in_use (true);
+ set_frame_menubar (f, true);
+ }
return false;
}
@@ -3221,7 +3364,12 @@ create_menus (widget_value *data,
}
else
{
+#ifndef HAVE_GTK3
wmenu = gtk_menu_bar_new ();
+#else
+ wmenu = emacs_menu_bar_new ();
+#endif
+
#ifdef HAVE_PGTK
g_signal_connect (G_OBJECT (wmenu), "button-press-event",
G_CALLBACK (menu_bar_button_pressed_cb), f);
@@ -3974,6 +4122,7 @@ xg_update_frame_menubar (struct frame *f)
{
xp_output *x = f->output_data.xp;
GtkRequisition req;
+ int scale = xg_get_scale (f);
if (!x->menubar_widget || gtk_widget_get_mapped (x->menubar_widget))
return;
@@ -3991,9 +4140,21 @@ xg_update_frame_menubar (struct frame *f)
gtk_widget_show_all (x->menubar_widget);
gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
req.height *= xg_get_scale (f);
- if (FRAME_MENUBAR_HEIGHT (f) != req.height)
+
+#if !defined HAVE_PGTK && defined HAVE_GTK3
+ if (FRAME_DISPLAY_INFO (f)->n_planes == 32)
{
- FRAME_MENUBAR_HEIGHT (f) = req.height;
+ GdkScreen *screen = gtk_widget_get_screen (x->menubar_widget);
+ GdkVisual *visual = gdk_screen_get_system_visual (screen);
+
+ gtk_widget_realize (x->menubar_widget);
+ gtk_widget_set_visual (x->menubar_widget, visual);
+ }
+#endif
+
+ if (FRAME_MENUBAR_HEIGHT (f) != (req.height * scale))
+ {
+ FRAME_MENUBAR_HEIGHT (f) = req.height * scale;
adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
}
unblock_input ();
@@ -4083,13 +4244,13 @@ xg_event_is_for_menubar (struct frame *f, const XEvent *event)
}
else
{
-#else
+#endif
rec.x = event->xbutton.x / scale;
rec.y = event->xbutton.y / scale;
-#endif
#ifdef HAVE_XINPUT2
}
#endif
+
rec.width = 1;
rec.height = 1;
@@ -4120,6 +4281,8 @@ bool xg_ignore_gtk_scrollbar;
static int scroll_bar_width_for_theme;
static int scroll_bar_height_for_theme;
+#if defined HAVE_PGTK || !defined HAVE_GTK3
+
/* Xlib's `Window' fits in 32 bits. But we want to store pointers, and they
may be larger than 32 bits. Keep a mapping from integer index to widget
pointers to get around the 32 bit limitation. */
@@ -4191,7 +4354,7 @@ xg_remove_widget_from_map (ptrdiff_t idx)
/* Get the widget pointer at IDX from id_to_widget. */
static GtkWidget *
-xg_get_widget_from_map (ptrdiff_t idx)
+xg_get_widget_from_map (ptrdiff_t idx, Display *dpy)
{
if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0)
return id_to_widget.widgets[idx];
@@ -4199,6 +4362,42 @@ xg_get_widget_from_map (ptrdiff_t idx)
return 0;
}
+#else
+static void
+find_scrollbar_cb (GtkWidget *widget, gpointer user_data)
+{
+ GtkWidget **scroll_bar = user_data;
+
+ if (GTK_IS_SCROLLBAR (widget))
+ *scroll_bar = widget;
+}
+
+static GtkWidget *
+xg_get_widget_from_map (ptrdiff_t window, Display *dpy)
+{
+ GtkWidget *gwdesc, *scroll_bar = NULL;
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
+ (Window) window);
+ if (gdkwin)
+ {
+ GdkEvent event;
+ event.any.window = gdkwin;
+ event.any.type = GDK_NOTHING;
+ gwdesc = gtk_get_event_widget (&event);
+
+ if (gwdesc && GTK_IS_EVENT_BOX (gwdesc))
+ gtk_container_forall (GTK_CONTAINER (gwdesc),
+ find_scrollbar_cb, &scroll_bar);
+ }
+ else
+ return NULL;
+
+ return scroll_bar;
+}
+#endif
+
static void
update_theme_scrollbar_width (void)
{
@@ -4258,7 +4457,7 @@ xg_get_default_scrollbar_height (struct frame *f)
return scroll_bar_width_for_theme * xg_get_scale (f);
}
-#ifndef HAVE_PGTK
+#ifndef HAVE_GTK3
/* Return the scrollbar id for X Window WID on display DPY.
Return -1 if WID not in id_to_widget. */
@@ -4285,12 +4484,40 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid)
DATA is the index into id_to_widget for WIDGET.
We free pointer to last scroll bar values here and remove the index. */
+#if !defined HAVE_GTK3 || defined HAVE_PGTK
static void
xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
{
intptr_t id = (intptr_t) data;
xg_remove_widget_from_map (id);
}
+#endif
+
+#if defined HAVE_GTK3 && !defined HAVE_PGTK
+static void
+xg_scroll_bar_size_allocate_cb (GtkWidget *widget,
+ GdkRectangle *allocation,
+ gpointer user_data)
+{
+ GdkEvent *event = gtk_get_current_event ();
+ GdkEvent dummy;
+
+ if (event && event->any.type == GDK_CONFIGURE)
+ x_scroll_bar_configure (event);
+ else
+ {
+ /* These are the only fields used by x_scroll_bar_configure. */
+ dummy.configure.send_event = FALSE;
+ dummy.configure.x = allocation->x;
+ dummy.configure.y = allocation->y;
+ dummy.configure.width = allocation->width;
+ dummy.configure.height = allocation->height;
+ dummy.configure.window = gtk_widget_get_window (widget);
+
+ x_scroll_bar_configure (&dummy);
+ }
+}
+#endif
static void
xg_finish_scroll_bar_creation (struct frame *f,
@@ -4301,19 +4528,32 @@ xg_finish_scroll_bar_creation (struct frame *f,
const char *scroll_bar_name)
{
GtkWidget *webox = gtk_event_box_new ();
+#ifdef HAVE_GTK3
+ GtkCssProvider *foreground_provider;
+ GtkCssProvider *background_provider;
+#endif
gtk_widget_set_name (wscroll, scroll_bar_name);
#ifndef HAVE_GTK3
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
#endif
- g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
+ g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer) f);
+#if defined HAVE_GTK3 && !defined HAVE_PGTK
+ g_signal_connect (G_OBJECT (webox), "size-allocate",
+ G_CALLBACK (xg_scroll_bar_size_allocate_cb),
+ NULL);
+#endif
+
+#if defined HAVE_PGTK || !defined HAVE_GTK3
ptrdiff_t scroll_id = xg_store_widget_in_map (wscroll);
g_signal_connect (G_OBJECT (wscroll),
"destroy",
G_CALLBACK (xg_gtk_scroll_destroy),
(gpointer) scroll_id);
+#endif
+
g_signal_connect (G_OBJECT (wscroll),
"change-value",
scroll_callback,
@@ -4341,27 +4581,35 @@ xg_finish_scroll_bar_creation (struct frame *f,
gtk_widget_realize (webox);
#ifdef HAVE_PGTK
gtk_widget_show_all (webox);
-#endif
-#ifndef HAVE_PGTK
+#elif defined HAVE_GTK3
+ bar->x_window = GTK_WIDGET_TO_X_WIN (webox);
+ gtk_widget_show_all (webox);
+#else
GTK_WIDGET_TO_X_WIN (webox);
#endif
/* Set the cursor to an arrow. */
xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor);
-#ifdef HAVE_PGTK
+#ifdef HAVE_GTK3
GtkStyleContext *ctxt = gtk_widget_get_style_context (wscroll);
- gtk_style_context_add_provider (ctxt,
- GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)->
- scrollbar_foreground_css_provider),
+ foreground_provider = FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider;
+ background_provider = FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider;
+
+ gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (foreground_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
- gtk_style_context_add_provider (ctxt,
- GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)->
- scrollbar_background_css_provider),
+ gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (background_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+#ifndef HAVE_PGTK
+ gtk_widget_add_events (webox, GDK_STRUCTURE_MASK);
+ gtk_widget_set_double_buffered (wscroll, FALSE);
+#endif
#endif
+#if defined HAVE_PGTK || !defined HAVE_GTK3
bar->x_window = scroll_id;
+#endif
}
/* Create a scroll bar widget for frame F. Store the scroll bar
@@ -4435,7 +4683,8 @@ xg_create_horizontal_scroll_bar (struct frame *f,
void
xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id)
{
- GtkWidget *w = xg_get_widget_from_map (scrollbar_id);
+ GtkWidget *w = xg_get_widget_from_map (scrollbar_id,
+ FRAME_X_DISPLAY (f));
if (w)
{
GtkWidget *wparent = gtk_widget_get_parent (w);
@@ -4458,11 +4707,15 @@ xg_update_scrollbar_pos (struct frame *f,
int width,
int height)
{
- GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+ GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id,
+ FRAME_X_DISPLAY (f));
if (wscroll)
{
GtkWidget *wfixed = f->output_data.xp->edit_widget;
GtkWidget *wparent = gtk_widget_get_parent (wscroll);
+#if !defined HAVE_PGTK && defined HAVE_GTK3
+ GdkWindow *wdesc = gtk_widget_get_window (wparent);
+#endif
gint msl;
int scale = xg_get_scale (f);
@@ -4495,7 +4748,18 @@ xg_update_scrollbar_pos (struct frame *f,
{
gtk_widget_show_all (wparent);
gtk_widget_set_size_request (wscroll, width, height);
+
+#if !defined HAVE_PGTK && defined HAVE_GTK3
+ if (wdesc)
+ {
+ gdk_window_move_resize (wdesc, left, top, width, height);
+#if GTK_CHECK_VERSION (3, 20, 0)
+ gtk_widget_queue_allocate (wparent);
+#endif
+ }
+#endif
}
+
if (oldx != -1 && oldw > 0 && oldh > 0)
{
/* Clear under old scroll bar position. */
@@ -4510,7 +4774,8 @@ xg_update_scrollbar_pos (struct frame *f,
if (!hidden)
{
- GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id);
+ GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id,
+ FRAME_X_DISPLAY (f));
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
#ifndef HAVE_PGTK
@@ -4549,13 +4814,16 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
int width,
int height)
{
-
- GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+ GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id,
+ FRAME_X_DISPLAY (f));
if (wscroll)
{
GtkWidget *wfixed = f->output_data.xp->edit_widget;
GtkWidget *wparent = gtk_widget_get_parent (wscroll);
+#if !defined HAVE_PGTK && defined HAVE_GTK3
+ GdkWindow *wdesc = gtk_widget_get_window (wparent);
+#endif
gint msl;
int scale = xg_get_scale (f);
@@ -4587,6 +4855,16 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
{
gtk_widget_show_all (wparent);
gtk_widget_set_size_request (wscroll, width, height);
+
+#if !defined HAVE_PGTK && defined HAVE_GTK3
+ if (wdesc)
+ {
+ gdk_window_move_resize (wdesc, left, top, width, height);
+#if GTK_CHECK_VERSION (3, 20, 0)
+ gtk_widget_queue_allocate (wparent);
+#endif
+ }
+#endif
}
if (oldx != -1 && oldw > 0 && oldh > 0)
/* Clear under old scroll bar position. */
@@ -4602,7 +4880,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
{
GtkWidget *scrollbar =
- xg_get_widget_from_map (scrollbar_id);
+ xg_get_widget_from_map (scrollbar_id, FRAME_X_DISPLAY (f));
GtkWidget *webox = gtk_widget_get_parent (scrollbar);
#ifndef HAVE_PGTK
@@ -4642,9 +4920,10 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
int position,
int whole)
{
- GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
-
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window,
+ FRAME_X_DISPLAY (f));
+
if (wscroll && bar->dragging == -1)
{
@@ -4729,7 +5008,9 @@ xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
int position,
int whole)
{
- GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window);
+ struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window,
+ FRAME_X_DISPLAY (f));
if (wscroll && bar->dragging == -1)
{
@@ -4761,7 +5042,8 @@ xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
frame. This function does additional checks. */
bool
-xg_event_is_for_scrollbar (struct frame *f, const EVENT *event)
+xg_event_is_for_scrollbar (struct frame *f, const EVENT *event,
+ bool for_valuator)
{
bool retval = 0;
@@ -4771,11 +5053,11 @@ xg_event_is_for_scrollbar (struct frame *f, const EVENT *event)
&& event->type == GenericEvent
&& (event->xgeneric.extension
== FRAME_DISPLAY_INFO (f)->xi2_opcode)
- && ((event->xgeneric.evtype == XI_ButtonPress
- && xev->detail < 4)
- || (event->xgeneric.evtype == XI_Motion)))
+ && (event->xgeneric.evtype == XI_ButtonPress
+ && xev->detail < 4))
|| (event->type == ButtonPress
- && event->xbutton.button < 4)))
+ && event->xbutton.button < 4)
+ || for_valuator))
#else
if (f
#ifndef HAVE_PGTK
@@ -4805,19 +5087,7 @@ xg_event_is_for_scrollbar (struct frame *f, const EVENT *event)
#else
gwin = gdk_display_get_window_at_pointer (gdpy, NULL, NULL);
#endif
-#ifndef HAVE_XINPUT2
retval = gwin != gtk_widget_get_window (f->output_data.xp->edit_widget);
-#else
- retval = (gwin
- && (gwin
- != gtk_widget_get_window (f->output_data.xp->edit_widget)));
-#endif
-#ifdef HAVE_XINPUT2
- GtkWidget *grab = gtk_grab_get_current ();
- if (event->type == GenericEvent
- && event->xgeneric.evtype == XI_Motion)
- retval = retval || (grab && GTK_IS_SCROLLBAR (grab));
-#endif
}
#ifdef HAVE_XINPUT2
else if (f && ((FRAME_DISPLAY_INFO (f)->supports_xi2
@@ -5423,6 +5693,7 @@ xg_update_tool_bar_sizes (struct frame *f)
GtkRequisition req;
int nl = 0, nr = 0, nt = 0, nb = 0;
GtkWidget *top_widget = x->toolbar_widget;
+ int scale = xg_get_scale (f);
gtk_widget_get_preferred_size (GTK_WIDGET (top_widget), NULL, &req);
if (x->toolbar_in_hbox)
@@ -5431,8 +5702,10 @@ xg_update_tool_bar_sizes (struct frame *f)
gtk_container_child_get (GTK_CONTAINER (x->hbox_widget),
top_widget,
"position", &pos, NULL);
- if (pos == 0) nl = req.width;
- else nr = req.width;
+ if (pos == 0)
+ nl = req.width * scale;
+ else
+ nr = req.width * scale;
}
else
{
@@ -5440,8 +5713,10 @@ xg_update_tool_bar_sizes (struct frame *f)
gtk_container_child_get (GTK_CONTAINER (x->vbox_widget),
top_widget,
"position", &pos, NULL);
- if (pos == 0 || (pos == 1 && x->menubar_widget)) nt = req.height;
- else nb = req.height;
+ if (pos == 0 || (pos == 1 && x->menubar_widget))
+ nt = req.height * scale;
+ else
+ nb = req.height * scale;
}
if (nl != FRAME_TOOLBAR_LEFT_WIDTH (f)
@@ -5914,8 +6189,10 @@ xg_initialize (void)
xg_menu_cb_list.prev = xg_menu_cb_list.next =
xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0;
+#if defined HAVE_PGTK || !defined HAVE_GTK3
id_to_widget.max_size = id_to_widget.used = 0;
id_to_widget.widgets = 0;
+#endif
settings = gtk_settings_get_for_screen (gdk_display_get_default_screen
(gdk_display_get_default ()));
@@ -5963,4 +6240,443 @@ xg_initialize (void)
#endif
}
+#ifndef HAVE_PGTK
+static void
+xg_add_virtual_mods (struct x_display_info *dpyinfo, GdkEventKey *key)
+{
+ guint modifiers = key->state;
+
+ if (modifiers & dpyinfo->meta_mod_mask)
+ {
+ /* GDK always assumes Mod1 is alt, but that's no reason for
+ us to make that mistake as well. */
+ if (!dpyinfo->alt_mod_mask)
+ key->state |= GDK_MOD1_MASK;
+ else
+ key->state |= GDK_META_MASK;
+ }
+
+ if (modifiers & dpyinfo->alt_mod_mask)
+ key->state |= GDK_MOD1_MASK;
+ if (modifiers & dpyinfo->super_mod_mask)
+ key->state |= GDK_SUPER_MASK;
+ if (modifiers & dpyinfo->hyper_mod_mask)
+ key->state |= GDK_HYPER_MASK;
+}
+
+static unsigned int
+xg_virtual_mods_to_x (struct x_display_info *dpyinfo, guint virtual)
+{
+ unsigned int modifiers = virtual & ~(GDK_SUPER_MASK
+ | GDK_META_MASK
+ | GDK_HYPER_MASK
+ | GDK_MOD2_MASK
+ | GDK_MOD3_MASK
+ | GDK_MOD4_MASK
+ | GDK_MOD5_MASK);
+
+ if (virtual & GDK_META_MASK)
+ modifiers |= dpyinfo->meta_mod_mask;
+ if (virtual & GDK_SUPER_MASK)
+ modifiers |= dpyinfo->super_mod_mask;
+ if (virtual & GDK_HYPER_MASK)
+ modifiers |= dpyinfo->hyper_mod_mask;
+
+ return modifiers;
+}
+
+static void
+xg_im_context_commit (GtkIMContext *imc, gchar *str,
+ gpointer user_data)
+{
+ struct frame *f = user_data;
+ struct input_event ie;
+#ifdef HAVE_XINPUT2
+ struct xi_device_t *source;
+ struct x_display_info *dpyinfo;
+#endif
+
+ EVENT_INIT (ie);
+ /* This used to use g_utf8_to_ucs4_fast, which led to bad results
+ when STR wasn't actually a UTF-8 string, which some input method
+ modules commit. */
+
+ ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ ie.arg = decode_string_utf_8 (Qnil, str, strlen (str),
+ Qnil, false, Qnil, Qnil);
+
+ /* STR is invalid and not really encoded in UTF-8. */
+ if (NILP (ie.arg))
+ ie.arg = build_unibyte_string (str);
+
+ Fput_text_property (make_fixnum (0),
+ make_fixnum (SCHARS (ie.arg)),
+ Qcoding, Qt, ie.arg);
+
+#ifdef HAVE_XINPUT2
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ /* There is no timestamp associated with commit events, so use the
+ device that sent the last event to be filtered. */
+ if (dpyinfo->pending_keystroke_time)
+ {
+ dpyinfo->pending_keystroke_time = 0;
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
+
+ if (source)
+ ie.device = source->name;
+ }
+#endif
+
+ XSETFRAME (ie.frame_or_window, f);
+ ie.modifiers = 0;
+ ie.timestamp = 0;
+
+ kbd_buffer_store_event (&ie);
+}
+
+static void
+xg_im_context_preedit_changed (GtkIMContext *imc, gpointer user_data)
+{
+ PangoAttrList *list;
+ gchar *str;
+ gint cursor;
+ struct input_event inev;
+
+ gtk_im_context_get_preedit_string (imc, &str, &list, &cursor);
+
+ EVENT_INIT (inev);
+ inev.kind = PREEDIT_TEXT_EVENT;
+ inev.arg = build_string_from_utf8 (str);
+
+ if (SCHARS (inev.arg))
+ Fput_text_property (make_fixnum (min (SCHARS (inev.arg) - 1,
+ max (0, cursor))),
+ make_fixnum (min (SCHARS (inev.arg),
+ max (0, cursor) + 1)),
+ Qcursor, Qt, inev.arg);
+
+ kbd_buffer_store_event (&inev);
+
+ g_free (str);
+ pango_attr_list_unref (list);
+}
+
+static void
+xg_im_context_preedit_end (GtkIMContext *imc, gpointer user_data)
+{
+ struct input_event inev;
+
+ EVENT_INIT (inev);
+ inev.kind = PREEDIT_TEXT_EVENT;
+ inev.arg = Qnil;
+ kbd_buffer_store_event (&inev);
+}
+
+static bool
+xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
+{
+ Lisp_Object tail, tem;
+ struct frame *f = NULL;
+ union buffered_input_event inev;
+ guint keysym = event->key.keyval;
+ unsigned int xstate;
+ gunichar uc;
+#ifdef HAVE_XINPUT2
+ Time pending_keystroke_time;
+ struct xi_device_t *source;
+#endif
+
+ FOR_EACH_FRAME (tail, tem)
+ {
+ if (FRAME_X_P (XFRAME (tem))
+ && (FRAME_GTK_WIDGET (XFRAME (tem)) == widget))
+ {
+ f = XFRAME (tem);
+ break;
+ }
+ }
+
+ if (!f)
+ return true;
+
+ if (popup_activated ())
+ return true;
+
+#ifdef HAVE_XINPUT2
+ pending_keystroke_time
+ = FRAME_DISPLAY_INFO (f)->pending_keystroke_time;
+
+ if (event->key.time >= pending_keystroke_time)
+ FRAME_DISPLAY_INFO (f)->pending_keystroke_time = 0;
+#endif
+
+ if (!x_gtk_use_native_input
+ && !FRAME_DISPLAY_INFO (f)->prefer_native_input)
+ return true;
+
+ EVENT_INIT (inev.ie);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ xstate = xg_virtual_mods_to_x (FRAME_DISPLAY_INFO (f),
+ event->key.state);
+
+ inev.ie.modifiers
+ |= x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), xstate);
+ inev.ie.timestamp = event->key.time;
+
+#ifdef HAVE_XINPUT2
+ if (event->key.time == pending_keystroke_time)
+ {
+ source = xi_device_from_id (FRAME_DISPLAY_INFO (f),
+ FRAME_DISPLAY_INFO (f)->pending_keystroke_source);
+
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+
+ if (event->key.is_modifier)
+ goto done;
+
+#ifndef HAVE_GTK3
+ /* FIXME: event->key.is_modifier is not accurate on GTK 2. */
+
+ if (keysym >= GDK_KEY_Shift_L && keysym <= GDK_KEY_Hyper_R)
+ goto done;
+#endif
+
+ /* First deal with keysyms which have defined
+ translations to characters. */
+ if (keysym >= 32 && keysym < 128)
+ /* Avoid explicitly decoding each ASCII character. */
+ {
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
+ goto done;
+ }
+
+ /* Keysyms directly mapped to Unicode characters. */
+ if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
+ {
+ if (keysym < 0x01000080)
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ else
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.code = keysym & 0xFFFFFF;
+ goto done;
+ }
+
+ /* Random non-modifier sorts of keysyms. */
+ if (((keysym >= GDK_KEY_BackSpace && keysym <= GDK_KEY_Escape)
+ || keysym == GDK_KEY_Delete
+#ifdef GDK_KEY_ISO_Left_Tab
+ || (keysym >= GDK_KEY_ISO_Left_Tab && keysym <= GDK_KEY_ISO_Enter)
+#endif
+ || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
+ || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
+#ifdef GDK_KEY_dead_circumflex
+ || keysym == GDK_KEY_dead_circumflex
+#endif
+#ifdef GDK_KEY_dead_grave
+ || keysym == GDK_KEY_dead_grave
+#endif
+#ifdef GDK_KEY_dead_tilde
+ || keysym == GDK_KEY_dead_tilde
+#endif
+#ifdef GDK_KEY_dead_diaeresis
+ || keysym == GDK_KEY_dead_diaeresis
+#endif
+#ifdef GDK_KEY_dead_macron
+ || keysym == GDK_KEY_dead_macron
+#endif
+#ifdef GDK_KEY_dead_degree
+ || keysym == GDK_KEY_dead_degree
+#endif
+#ifdef GDK_KEY_dead_acute
+ || keysym == GDK_KEY_dead_acute
+#endif
+#ifdef GDK_KEY_dead_cedilla
+ || keysym == GDK_KEY_dead_cedilla
+#endif
+#ifdef GDK_KEY_dead_breve
+ || keysym == GDK_KEY_dead_breve
+#endif
+#ifdef GDK_KEY_dead_ogonek
+ || keysym == GDK_KEY_dead_ogonek
+#endif
+#ifdef GDK_KEY_dead_caron
+ || keysym == GDK_KEY_dead_caron
+#endif
+#ifdef GDK_KEY_dead_doubleacute
+ || keysym == GDK_KEY_dead_doubleacute
+#endif
+#ifdef GDK_KEY_dead_abovedot
+ || keysym == GDK_KEY_dead_abovedot
+#endif
+ || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
+ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
+ /* Any "vendor-specific" key is ok. */
+ || (keysym & (1 << 28))))
+ {
+ inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
+ goto done;
+ }
+
+ uc = gdk_keyval_to_unicode (keysym);
+
+ if (uc)
+ {
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (uc)
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.ie.code = uc;
+ }
+ else
+ {
+ inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
+ }
+
+ done:
+ if (inev.ie.kind != NO_EVENT)
+ {
+ xg_pending_quit_event.kind = NO_EVENT;
+ kbd_buffer_store_buffered_event (&inev, &xg_pending_quit_event);
+ }
+
+ XNoOp (FRAME_X_DISPLAY (f));
+#ifdef USABLE_SIGIO
+ raise (SIGIO);
+#endif
+ return true;
+}
+
+bool
+xg_filter_key (struct frame *frame, XEvent *xkey)
+{
+ GdkEvent *xg_event = gdk_event_new ((xkey->type == KeyPress
+#ifdef HAVE_XINPUT2
+ || (xkey->type == GenericEvent
+ && xkey->xgeneric.evtype == XI_KeyPress)
+#endif
+ ) ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
+ GdkDisplay *dpy = gtk_widget_get_display (FRAME_GTK_WIDGET (frame));
+ GdkKeymap *keymap = gdk_keymap_get_for_display (dpy);
+ GdkModifierType consumed;
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
+ bool result;
+
+ xg_event->any.window = gtk_widget_get_window (FRAME_GTK_WIDGET (frame));
+ g_object_ref (xg_event->any.window);
+
+#if GTK_CHECK_VERSION (3, 20, 0)
+ GdkSeat *seat = gdk_display_get_default_seat (dpy);
+
+ gdk_event_set_device (xg_event,
+ gdk_seat_get_keyboard (seat));
+#elif GTK_CHECK_VERSION (3, 16, 0)
+ GdkDeviceManager *manager = gdk_display_get_device_manager (dpy);
+ GList *devices = gdk_device_manager_list_devices (manager,
+ GDK_DEVICE_TYPE_MASTER);
+ GdkDevice *device;
+ GList *tem;
+ for (tem = devices; tem; tem = tem->next)
+ {
+ device = GDK_DEVICE (tem->data);
+
+ if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+ {
+ gdk_event_set_device (xg_event, device);
+ break;
+ }
+ }
+
+ g_list_free (devices);
+#endif
+
+#ifdef HAVE_XINPUT2
+ if (xkey->type != GenericEvent)
+ {
+#endif
+ xg_event->key.hardware_keycode = xkey->xkey.keycode;
+
+#ifdef HAVE_XKB
+ if (dpyinfo->supports_xkb)
+ xg_event->key.group = XkbGroupForCoreState (xkey->xkey.state);
+#endif
+ xg_event->key.state = xkey->xkey.state;
+ gdk_keymap_translate_keyboard_state (keymap,
+ xkey->xkey.keycode,
+ xkey->xkey.state,
+ xg_event->key.group,
+ &xg_event->key.keyval,
+ 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);
+#endif
+#ifdef HAVE_XINPUT2
+ }
+ else
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) xkey->xcookie.data;
+
+ 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,
+ xg_event->key.group,
+ &xg_event->key.keyval,
+ NULL, NULL, &consumed);
+ xg_add_virtual_mods (dpyinfo, &xg_event->key);
+ xg_event->key.state &= ~consumed;
+#if GTK_CHECK_VERSION (3, 6, 0)
+ xg_event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap,
+ xg_event->key.hardware_keycode);
+#endif
+ }
+#endif
+
+ result = gtk_im_context_filter_keypress (FRAME_X_OUTPUT (frame)->im_context,
+ &xg_event->key);
+
+ gdk_event_free (xg_event);
+
+ return result;
+}
+#endif
+
+#if GTK_CHECK_VERSION (3, 10, 0)
+static void
+xg_widget_style_updated (GtkWidget *widget, gpointer user_data)
+{
+ struct frame *f = user_data;
+
+ if (f->alpha_background < 1.0)
+ {
+#ifndef HAVE_PGTK
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ NULL, 0);
+#else
+ if (FRAME_GTK_OUTER_WIDGET (f)
+ && gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f)))
+ gdk_window_set_opaque_region (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
+ NULL);
+#endif
+ }
+}
+#endif
#endif /* USE_GTK */
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 5a918259280..190d6628314 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -148,10 +148,13 @@ extern void xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
int portion,
int position,
int whole);
-extern bool xg_event_is_for_scrollbar (struct frame *, const EVENT *);
+extern bool xg_event_is_for_scrollbar (struct frame *, const EVENT *,
+ bool for_valuator);
extern int xg_get_default_scrollbar_width (struct frame *f);
extern int xg_get_default_scrollbar_height (struct frame *f);
+extern void xg_wm_set_size_hint (struct frame *, long int, bool);
+
extern void update_frame_tool_bar (struct frame *f);
extern void free_frame_tool_bar (struct frame *f);
extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos);
@@ -217,7 +220,11 @@ extern void xg_print_frames_dialog (Lisp_Object);
extern bool xg_is_menu_window (Display *dpy, Window);
#endif
-/* Mark all callback data that are Lisp_object:s during GC. */
+#ifndef HAVE_PGTK
+extern bool xg_filter_key (struct frame *frame, XEvent *xkey);
+#endif
+
+/* Mark all callback data that are Lisp_Objects during GC. */
extern void xg_mark_data (void);
/* Initialize GTK specific parts. */
diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc
index 5d355ac2058..8e911dd1843 100644
--- a/src/haiku_draw_support.cc
+++ b/src/haiku_draw_support.cc
@@ -280,16 +280,42 @@ hsl_color_rgb (double h, double s, double l, uint32_t *rgb)
void
BView_DrawBitmap (void *view, void *bitmap, int x, int y,
int width, int height, int vx, int vy, int vwidth,
- int vheight)
+ int vheight, bool use_bilinear_filtering)
{
BView *vw = get_view (view);
BBitmap *bm = (BBitmap *) bitmap;
- vw->PushState ();
+ vw->SetDrawingMode (B_OP_OVER);
+ if (!use_bilinear_filtering)
+ vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
+ BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
+ else
+ vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
+ BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1),
+ B_FILTER_BITMAP_BILINEAR);
+ vw->SetDrawingMode (B_OP_COPY);
+}
+
+void
+BView_DrawBitmapTiled (void *view, void *bitmap, int x, int y,
+ int width, int height, int vx, int vy,
+ int vwidth, int vheight)
+{
+ BView *vw = get_view (view);
+ BBitmap *bm = (BBitmap *) bitmap;
+ BRect bounds = bm->Bounds ();
+
+ if (width == -1)
+ width = BE_RECT_WIDTH (bounds);
+
+ if (height == -1)
+ height = BE_RECT_HEIGHT (bounds);
+
vw->SetDrawingMode (B_OP_OVER);
vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
- BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
- vw->PopState ();
+ BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1),
+ B_TILE_BITMAP);
+ vw->SetDrawingMode (B_OP_COPY);
}
void
@@ -300,20 +326,25 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
BBitmap *bm = (BBitmap *) bitmap;
BBitmap bc (bm->Bounds (), B_RGBA32);
BRect rect (x, y, x + width - 1, y + height - 1);
+ uint32_t *bits;
+ size_t stride;
+ rgb_color low_color;
+ BRect bounds;
if (bc.InitCheck () != B_OK || bc.ImportBits (bm) != B_OK)
return;
- uint32_t *bits = (uint32_t *) bc.Bits ();
- size_t stride = bc.BytesPerRow ();
+ bits = (uint32_t *) bc.Bits ();
+ stride = bc.BytesPerRow ();
if (bm->ColorSpace () == B_GRAY1)
{
- rgb_color low_color = vw->LowColor ();
- BRect bounds = bc.Bounds ();
+ low_color = vw->LowColor ();
+ bounds = bc.Bounds ();
+
for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
{
- for (int x = 0; x <= BE_RECT_WIDTH (bounds); ++x)
+ for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x)
{
if (bits[y * (stride / 4) + x] == 0xFF000000)
bits[y * (stride / 4) + x] = RGB_COLOR_UINT32 (low_color);
@@ -323,166 +354,183 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
}
}
- vw->PushState ();
- vw->SetDrawingMode (bm->ColorSpace () == B_GRAY1 ? B_OP_OVER : B_OP_ERASE);
+ vw->SetDrawingMode ((bm->ColorSpace ()
+ == B_GRAY1)
+ ? B_OP_OVER : B_OP_ERASE);
vw->DrawBitmap (&bc, rect);
- vw->PopState ();
+ vw->SetDrawingMode (B_OP_COPY);
}
void
-BView_DrawMask (void *src, void *view,
- int x, int y, int width, int height,
- int vx, int vy, int vwidth, int vheight,
- uint32_t color)
+be_draw_image_mask (void *src, void *view, int x, int y, int width,
+ int height, int vx, int vy, int vwidth, int vheight,
+ uint32_t color)
{
BBitmap *source = (BBitmap *) src;
BBitmap bm (source->Bounds (), B_RGBA32);
BRect bounds = bm.Bounds ();
+ int bx, by, bit;
+ BView *vw;
if (bm.InitCheck () != B_OK)
return;
- for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
+
+ /* Fill the background color or transparency into the bitmap,
+ depending on the value of the mask. */
+ for (by = 0; by < BE_RECT_HEIGHT (bounds); ++by)
{
- for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x)
+ for (bx = 0; bx < BE_RECT_WIDTH (bounds); ++bx)
{
- int bit = haiku_get_pixel ((void *) source, x, y);
+ bit = haiku_get_pixel ((void *) source, bx, by);
if (!bit)
- haiku_put_pixel ((void *) &bm, x, y, ((uint32_t) 255 << 24) | color);
+ haiku_put_pixel ((void *) &bm, bx, by,
+ ((uint32_t) 255 << 24) | color);
else
- haiku_put_pixel ((void *) &bm, x, y, 0);
+ haiku_put_pixel ((void *) &bm, bx, by, 0);
}
}
- BView *vw = get_view (view);
+
+ vw = get_view (view);
vw->SetDrawingMode (B_OP_OVER);
vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1),
BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
+ vw->SetDrawingMode (B_OP_COPY);
}
-static BBitmap *
-rotate_bitmap_270 (BBitmap *bmp)
+void
+be_apply_affine_transform (void *view, double m0, double m1, double tx,
+ double m2, double m3, double ty)
{
- BRect r = bmp->Bounds ();
- BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right),
- bmp->ColorSpace (), true);
- if (bm->InitCheck () != B_OK)
- gui_abort ("Failed to init bitmap for rotate");
- int w = BE_RECT_WIDTH (r);
- int h = BE_RECT_HEIGHT (r);
-
- for (int y = 0; y < h; ++y)
- for (int x = 0; x < w; ++x)
- haiku_put_pixel ((void *) bm, y, w - x - 1,
- haiku_get_pixel ((void *) bmp, x, y));
+ BAffineTransform transform (m0, m2, m1, m3, tx, ty);
- return bm;
+ get_view (view)->SetTransform (transform);
}
-static BBitmap *
-rotate_bitmap_90 (BBitmap *bmp)
+void
+be_apply_inverse_transform (double (*matrix3x3)[3], int x, int y,
+ int *x_out, int *y_out)
{
- BRect r = bmp->Bounds ();
- BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right),
- bmp->ColorSpace (), true);
- if (bm->InitCheck () != B_OK)
- gui_abort ("Failed to init bitmap for rotate");
- int w = BE_RECT_WIDTH (r);
- int h = BE_RECT_HEIGHT (r);
+ BAffineTransform transform (matrix3x3[0][0], matrix3x3[1][0],
+ matrix3x3[0][1], matrix3x3[1][1],
+ matrix3x3[0][2], matrix3x3[1][2]);
+ BPoint point (x, y);
- for (int y = 0; y < h; ++y)
- for (int x = 0; x < w; ++x)
- haiku_put_pixel ((void *) bm, h - y - 1, x,
- haiku_get_pixel ((void *) bmp, x, y));
+ transform.ApplyInverse (&point);
- return bm;
+ *x_out = std::floor (point.x);
+ *y_out = std::floor (point.y);
}
-void *
-BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color,
- double rot, int desw, int desh)
+void
+BView_FillTriangle (void *view, int x1, int y1,
+ int x2, int y2, int x3, int y3)
{
- BBitmap *bm = (BBitmap *) bitmap;
- BBitmap *mk = (BBitmap *) mask;
- int copied_p = 0;
+ BView *vw = get_view (view);
+ vw->FillTriangle (BPoint (x1, y1), BPoint (x2, y2),
+ BPoint (x3, y3));
+}
- if (rot == 90)
- {
- copied_p = 1;
- bm = rotate_bitmap_90 (bm);
- if (mk)
- mk = rotate_bitmap_90 (mk);
- }
+void
+BView_InvertRect (void *view, int x, int y, int width, int height)
+{
+ BView *vw = get_view (view);
- if (rot == 270)
- {
- copied_p = 1;
- bm = rotate_bitmap_270 (bm);
- if (mk)
- mk = rotate_bitmap_270 (mk);
- }
+ vw->InvertRect (BRect (x, y, x + width - 1, y + height - 1));
+}
- BRect n = BRect (0, 0, desw - 1, desh - 1);
- BView vw (n, NULL, B_FOLLOW_NONE, 0);
- BBitmap *dst = new BBitmap (n, bm->ColorSpace (), true);
- if (dst->InitCheck () != B_OK)
- if (bm->InitCheck () != B_OK)
- gui_abort ("Failed to init bitmap for scale");
- dst->AddChild (&vw);
+static void
+be_draw_cross_on_pixmap_1 (BBitmap *bitmap, int x, int y, int width,
+ int height, uint32_t color)
+{
+ BBitmap dest (bitmap->Bounds (),
+ bitmap->ColorSpace (),
+ true, false);
+ BView view (bitmap->Bounds (), NULL, B_FOLLOW_NONE, 0);
+ rgb_color high_color;
- if (!vw.LockLooper ())
- gui_abort ("Failed to lock offscreen view for scale");
+ rgb32_to_rgb_color (color, &high_color);
+ dest.ImportBits (bitmap);
- if (rot != 90 && rot != 270)
- {
- BAffineTransform tr;
- tr.RotateBy (BPoint (desw / 2, desh / 2), rot * M_PI / 180.0);
- vw.SetTransform (tr);
- }
+ if (!dest.Lock ())
+ return;
- vw.MovePenTo (0, 0);
- vw.DrawBitmap (bm, n);
- if (mk)
- {
- BRect k = mk->Bounds ();
- BView_DrawMask ((void *) mk, (void *) &vw,
- 0, 0, BE_RECT_WIDTH (k),
- BE_RECT_HEIGHT (k),
- 0, 0, desw, desh, m_color);
- }
- vw.Sync ();
- vw.RemoveSelf ();
+ dest.AddChild (&view);
- if (copied_p)
- delete bm;
- if (copied_p && mk)
- delete mk;
- return dst;
+ view.SetHighColor (high_color);
+ view.StrokeLine (BPoint (x, y),
+ BPoint (x + width - 1, y + height - 1));
+ view.StrokeLine (BPoint (x, y + height - 1),
+ BPoint (x + width - 1, y));
+ view.RemoveSelf ();
+ bitmap->ImportBits (&dest);
}
void
-BView_FillTriangle (void *view, int x1, int y1,
- int x2, int y2, int x3, int y3)
+be_draw_cross_on_pixmap (void *bitmap, int x, int y, int width,
+ int height, uint32_t color)
{
- BView *vw = get_view (view);
- vw->FillTriangle (BPoint (x1, y1), BPoint (x2, y2),
- BPoint (x3, y3));
+ BBitmap *target = (BBitmap *) bitmap;
+
+ be_draw_cross_on_pixmap_1 (target, x, y, width, height,
+ color);
}
void
-BView_SetHighColorForVisibleBell (void *view, uint32_t color)
+be_draw_bitmap_with_mask (void *view, void *bitmap, void *mask,
+ int dx, int dy, int width, int height,
+ int vx, int vy, int vwidth, int vheight,
+ bool use_bilinear_filtering)
{
- BView *vw = (BView *) view;
- rgb_color col;
- rgb32_to_rgb_color (color, &col);
+ BBitmap *source ((BBitmap *) bitmap);
+ BBitmap combined (source->Bounds (), B_RGBA32);
+ BRect bounds;
+ int x, y, bit;
+ BView *vw;
+ uint32_t source_mask;
+ unsigned long pixel;
+
+ if (combined.InitCheck () != B_OK)
+ return;
- vw->SetHighColor (col);
-}
+ if (combined.ImportBits (source) != B_OK)
+ return;
-void
-BView_FillRectangleForVisibleBell (void *view, int x, int y, int width, int height)
-{
- BView *vw = (BView *) view;
- BRect rect = BRect (x, y, x + width - 1, y + height - 1);
+ bounds = source->Bounds ();
- vw->FillRect (rect);
+ if (source->ColorSpace () == B_RGB32)
+ source_mask = 255u << 24;
+ else
+ source_mask = 0;
+
+ for (y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
+ {
+ for (x = 0; x < BE_RECT_WIDTH (bounds); ++x)
+ {
+ bit = haiku_get_pixel (mask, x, y);
+
+ if (bit)
+ {
+ pixel = haiku_get_pixel (bitmap, x, y);
+ haiku_put_pixel ((void *) &combined, x, y,
+ source_mask | pixel);
+ }
+ else
+ haiku_put_pixel ((void *) &combined, x, y, 0);
+ }
+ }
+
+ vw = get_view (view);
+
+ vw->SetDrawingMode (B_OP_OVER);
+ if (!use_bilinear_filtering)
+ vw->DrawBitmap (&combined,
+ BRect (dx, dy, dx + width - 1, dy + height - 1),
+ BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
+ else
+ vw->DrawBitmap (&combined,
+ BRect (dx, dy, dx + width - 1, dy + height - 1),
+ BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1),
+ B_FILTER_BITMAP_BILINEAR);
+ vw->SetDrawingMode (B_OP_COPY);
}
diff --git a/src/haiku_font_support.cc b/src/haiku_font_support.cc
index 6ea10b2e47c..d824cc59ae2 100644
--- a/src/haiku_font_support.cc
+++ b/src/haiku_font_support.cc
@@ -27,15 +27,111 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "haiku_support.h"
+/* Cache used during font lookup. It contains an opened font object
+ we can look inside, and some previously determined information. */
+struct font_object_cache_bucket
+{
+ struct font_object_cache_bucket *next;
+ unsigned int hash;
+
+ BFont *font_object;
+};
+
+static struct font_object_cache_bucket *font_object_cache[2048];
+
/* Haiku doesn't expose font language data in BFont objects. Thus, we
select a few representative characters for each supported `:lang'
(currently Chinese, Korean and Japanese,) and test for those
instead. */
-static uint32_t language_code_points[MAX_LANGUAGE][4] =
- {{20154, 20754, 22996, 0}, /* Chinese. */
- {51312, 49440, 44544, 0}, /* Korean. */
- {26085, 26412, 12371, 0}, /* Japanese. */};
+static int language_code_points[MAX_LANGUAGE][3] =
+ {{20154, 20754, 22996}, /* Chinese. */
+ {51312, 49440, 44544}, /* Korean. */
+ {26085, 26412, 12371}, /* Japanese. */};
+
+static unsigned int
+hash_string (const char *name_or_style)
+{
+ unsigned int i;
+
+ i = 3323198485ul;
+ for (; *name_or_style; ++name_or_style)
+ {
+ i ^= *name_or_style;
+ i *= 0x5bd1e995;
+ i ^= i >> 15;
+ }
+ return i;
+}
+
+static struct font_object_cache_bucket *
+cache_font_object_data (const char *family, const char *style,
+ BFont *font_object)
+{
+ uint32_t hash;
+ struct font_object_cache_bucket *bucket, *next;
+
+ hash = hash_string (family) ^ hash_string (style);
+ bucket = font_object_cache[hash % 2048];
+
+ for (next = bucket; next; next = next->next)
+ {
+ if (next->hash == hash)
+ {
+ delete next->font_object;
+ next->font_object = font_object;
+
+ return next;
+ }
+ }
+
+ next = new struct font_object_cache_bucket;
+ next->font_object = font_object;
+ next->hash = hash;
+ next->next = bucket;
+ font_object_cache[hash % 2048] = next;
+ return next;
+}
+
+static struct font_object_cache_bucket *
+lookup_font_object_data (const char *family, const char *style)
+{
+ uint32_t hash;
+ struct font_object_cache_bucket *bucket, *next;
+
+ hash = hash_string (family) ^ hash_string (style);
+ bucket = font_object_cache[hash % 2048];
+
+ for (next = bucket; next; next = next->next)
+ {
+ if (next->hash == hash)
+ return next;
+ }
+
+ return NULL;
+}
+
+static bool
+font_object_has_chars (struct font_object_cache_bucket *cached,
+ int *chars, int nchars, bool just_one_of)
+{
+ int i;
+
+ for (i = 0; i < nchars; ++i)
+ {
+ if (just_one_of
+ && cached->font_object->IncludesBlock (chars[i],
+ chars[i]))
+ return true;
+
+ if (!just_one_of
+ && !cached->font_object->IncludesBlock (chars[i],
+ chars[i]))
+ return false;
+ }
+
+ return !just_one_of;
+}
static void
estimate_font_ascii (BFont *font, int *max_width,
@@ -68,7 +164,11 @@ estimate_font_ascii (BFont *font, int *max_width,
*min_width = min;
*max_width = max;
- *avg_width = total / count;
+
+ if (count)
+ *avg_width = total / count;
+ else
+ *avg_width = 0;
}
void
@@ -81,9 +181,9 @@ BFont_close (void *font)
}
void
-BFont_dat (void *font, int *px_size, int *min_width, int *max_width,
- int *avg_width, int *height, int *space_width, int *ascent,
- int *descent, int *underline_position, int *underline_thickness)
+BFont_metrics (void *font, int *px_size, int *min_width, int *max_width,
+ int *avg_width, int *height, int *space_width, int *ascent,
+ int *descent, int *underline_position, int *underline_thickness)
{
BFont *ft = (BFont *) font;
struct font_height fheight;
@@ -159,9 +259,9 @@ BFont_char_bounds (void *font, const char *mb_str, int *advance,
ft->GetEdges (mb_str, 1, &edge_info);
ft->GetEscapements (mb_str, 1, &escapement);
- *advance = std::ceil (escapement * size);
- *lb = std::ceil (edge_info.left * size);
- *rb = *advance + std::ceil (edge_info.right * size);
+ *advance = std::lrint (escapement * size);
+ *lb = std::lrint (edge_info.left * size);
+ *rb = *advance + std::lrint (edge_info.right * size);
}
/* The same, but for a variable amount of chars. */
@@ -192,18 +292,21 @@ font_style_to_flags (char *st, struct haiku_font_pattern *pattern)
{
char *style = strdup (st);
char *token;
- pattern->weight = -1;
+ int tok = 0;
+
+ if (!style)
+ return;
+
+ pattern->weight = NO_WEIGHT;
pattern->width = NO_WIDTH;
pattern->slant = NO_SLANT;
- int tok = 0;
while ((token = std::strtok (!tok ? style : NULL, " ")) && tok < 3)
{
if (token && !strcmp (token, "Thin"))
pattern->weight = HAIKU_THIN;
- else if (token && !strcmp (token, "UltraLight"))
- pattern->weight = HAIKU_ULTRALIGHT;
- else if (token && !strcmp (token, "ExtraLight"))
+ else if (token && (!strcmp (token, "UltraLight")
+ || !strcmp (token, "ExtraLight")))
pattern->weight = HAIKU_EXTRALIGHT;
else if (token && !strcmp (token, "Light"))
pattern->weight = HAIKU_LIGHT;
@@ -217,19 +320,20 @@ font_style_to_flags (char *st, struct haiku_font_pattern *pattern)
if (pattern->width == NO_WIDTH)
pattern->width = NORMAL_WIDTH;
- if (pattern->weight == -1)
+ if (pattern->weight == NO_WEIGHT)
pattern->weight = HAIKU_REGULAR;
}
- else if (token && !strcmp (token, "SemiBold"))
+ else if (token && (!strcmp (token, "SemiBold")
+ /* Likewise, this was reported by a user. */
+ || !strcmp (token, "Semibold")))
pattern->weight = HAIKU_SEMI_BOLD;
else if (token && !strcmp (token, "Bold"))
pattern->weight = HAIKU_BOLD;
- else if (token && (!strcmp (token, "ExtraBold") ||
+ else if (token && (!strcmp (token, "ExtraBold")
/* This has actually been seen in the wild. */
- !strcmp (token, "Extrabold")))
+ || !strcmp (token, "Extrabold")
+ || !strcmp (token, "UltraBold")))
pattern->weight = HAIKU_EXTRA_BOLD;
- else if (token && !strcmp (token, "UltraBold"))
- pattern->weight = HAIKU_ULTRA_BOLD;
else if (token && !strcmp (token, "Book"))
pattern->weight = HAIKU_BOOK;
else if (token && !strcmp (token, "Heavy"))
@@ -268,7 +372,7 @@ font_style_to_flags (char *st, struct haiku_font_pattern *pattern)
tok++;
}
- if (pattern->weight != -1)
+ if (pattern->weight != NO_WEIGHT)
pattern->specified |= FSPEC_WEIGHT;
if (pattern->slant != NO_SLANT)
pattern->specified |= FSPEC_SLANT;
@@ -283,6 +387,7 @@ font_style_to_flags (char *st, struct haiku_font_pattern *pattern)
pattern->specified |= FSPEC_STYLE;
std::strncpy ((char *) &pattern->style, st,
sizeof pattern->style - 1);
+ pattern->style[sizeof pattern->style - 1] = '\0';
}
free (style);
@@ -292,54 +397,86 @@ static bool
font_check_wanted_chars (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
- BFont ft;
+ BFont *ft;
+ static struct font_object_cache_bucket *cached;
+ unicode_block wanted_block;
+
+ cached = lookup_font_object_data (family, style);
+ if (cached)
+ ft = cached->font_object;
+ else
+ {
+ ft = new BFont;
- if (ft.SetFamilyAndStyle (family, style) != B_OK)
- return false;
+ if (ft->SetFamilyAndStyle (family, style) != B_OK)
+ {
+ delete ft;
+ return false;
+ }
- for (int i = 0; i < pattern->want_chars_len; ++i)
- if (!ft.IncludesBlock (pattern->wanted_chars[i],
- pattern->wanted_chars[i]))
- return false;
+ cached = cache_font_object_data (family, style, ft);
+ }
- return true;
+ return font_object_has_chars (cached, pattern->wanted_chars,
+ pattern->want_chars_len, false);
}
static bool
font_check_one_of (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
- BFont ft;
+ BFont *ft;
+ static struct font_object_cache_bucket *cached;
+ unicode_block wanted_block;
+
+ cached = lookup_font_object_data (family, style);
+ if (cached)
+ ft = cached->font_object;
+ else
+ {
+ ft = new BFont;
- if (ft.SetFamilyAndStyle (family, style) != B_OK)
- return false;
+ if (ft->SetFamilyAndStyle (family, style) != B_OK)
+ {
+ delete ft;
+ return false;
+ }
- for (int i = 0; i < pattern->need_one_of_len; ++i)
- if (ft.IncludesBlock (pattern->need_one_of[i],
- pattern->need_one_of[i]))
- return true;
+ cached = cache_font_object_data (family, style, ft);
+ }
- return false;
+ return font_object_has_chars (cached, pattern->need_one_of,
+ pattern->need_one_of_len, true);
}
static bool
font_check_language (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
- BFont ft;
+ BFont *ft;
+ static struct font_object_cache_bucket *cached;
- if (ft.SetFamilyAndStyle (family, style) != B_OK)
- return false;
+ cached = lookup_font_object_data (family, style);
+ if (cached)
+ ft = cached->font_object;
+ else
+ {
+ ft = new BFont;
+
+ if (ft->SetFamilyAndStyle (family, style) != B_OK)
+ {
+ delete ft;
+ return false;
+ }
+
+ cached = cache_font_object_data (family, style, ft);
+ }
if (pattern->language == MAX_LANGUAGE)
return false;
- for (uint32_t *ch = (uint32_t *)
- &language_code_points[pattern->language]; *ch; ch++)
- if (!ft.IncludesBlock (*ch, *ch))
- return false;
-
- return true;
+ return font_object_has_chars (cached, language_code_points[pattern->language],
+ 3, false);
}
static bool
@@ -353,16 +490,20 @@ font_family_style_matches_p (font_family family, char *style, uint32_t flags,
if (style)
font_style_to_flags (style, &m);
- if ((pattern->specified & FSPEC_FAMILY) &&
- strcmp ((char *) &pattern->family, family))
+ if ((pattern->specified & FSPEC_FAMILY)
+ && strcmp ((char *) &pattern->family, family))
return false;
- if (!ignore_flags_p && (pattern->specified & FSPEC_SPACING) &&
- !(pattern->mono_spacing_p) != !(flags & B_IS_FIXED))
+ if (!ignore_flags_p && (pattern->specified & FSPEC_SPACING)
+ && !(pattern->mono_spacing_p) != !(flags & B_IS_FIXED))
return false;
if (pattern->specified & FSPEC_STYLE)
return style && !strcmp (style, pattern->style);
+ /* Don't allow matching fonts with an adstyle if no style was
+ specified in the query pattern. */
+ else if (m.specified & FSPEC_STYLE)
+ return false;
if ((pattern->specified & FSPEC_WEIGHT)
&& (pattern->weight
@@ -371,7 +512,8 @@ font_family_style_matches_p (font_family family, char *style, uint32_t flags,
if ((pattern->specified & FSPEC_SLANT)
&& (pattern->slant
- != ((m.specified & FSPEC_SLANT) ? m.slant : SLANT_REGULAR)))
+ != (m.specified & FSPEC_SLANT
+ ? m.slant : SLANT_REGULAR)))
return false;
if ((pattern->specified & FSPEC_WANTED)
@@ -379,8 +521,9 @@ font_family_style_matches_p (font_family family, char *style, uint32_t flags,
return false;
if ((pattern->specified & FSPEC_WIDTH)
- && (pattern->width !=
- ((m.specified & FSPEC_WIDTH) ? m.width : NORMAL_WIDTH)))
+ && (pattern->width
+ != (m.specified & FSPEC_WIDTH
+ ? m.width : NORMAL_WIDTH)))
return false;
if ((pattern->specified & FSPEC_NEED_ONE_OF)
@@ -405,6 +548,7 @@ haiku_font_fill_pattern (struct haiku_font_pattern *pattern,
pattern->specified |= FSPEC_FAMILY;
std::strncpy (pattern->family, family,
sizeof pattern->family - 1);
+ pattern->family[sizeof pattern->family - 1] = '\0';
pattern->specified |= FSPEC_SPACING;
pattern->mono_spacing_p = flags & B_IS_FIXED;
}
@@ -430,18 +574,21 @@ BFont_find (struct haiku_font_pattern *pt)
font_family name;
font_style sname;
uint32 flags;
- int sty_count;
- int fam_count = count_font_families ();
+ int sty_count, fam_count, si, fi;
+ struct haiku_font_pattern *p, *head, *n;
+ bool oblique_seen_p;
+
+ fam_count = count_font_families ();
- for (int fi = 0; fi < fam_count; ++fi)
+ for (fi = 0; fi < fam_count; ++fi)
{
if (get_font_family (fi, &name, &flags) == B_OK)
{
sty_count = count_font_styles (name);
- if (!sty_count &&
- font_family_style_matches_p (name, NULL, flags, pt))
+ if (!sty_count
+ && font_family_style_matches_p (name, NULL, flags, pt))
{
- struct haiku_font_pattern *p = new struct haiku_font_pattern;
+ p = new struct haiku_font_pattern;
p->specified = 0;
p->oblique_seen_p = 1;
haiku_font_fill_pattern (p, name, NULL, flags);
@@ -451,14 +598,20 @@ BFont_find (struct haiku_font_pattern *pt)
p->last = NULL;
p->next_family = r;
r = p;
+
+ if (pt->specified & FSPEC_ANTIALIAS)
+ {
+ p->specified |= FSPEC_ANTIALIAS;
+ p->use_antialiasing = pt->use_antialiasing;
+ }
}
else if (sty_count)
{
- for (int si = 0; si < sty_count; ++si)
+ for (si = 0; si < sty_count; ++si)
{
- int oblique_seen_p = 0;
- struct haiku_font_pattern *head = r;
- struct haiku_font_pattern *p = NULL;
+ oblique_seen_p = 0;
+ head = r;
+ p = NULL;
if (get_font_style (name, si, &sname, &flags) == B_OK)
{
@@ -467,8 +620,24 @@ BFont_find (struct haiku_font_pattern *pt)
p = new struct haiku_font_pattern;
p->specified = 0;
haiku_font_fill_pattern (p, name, (char *) &sname, flags);
- if (p->specified & FSPEC_SLANT &&
- ((p->slant == SLANT_OBLIQUE) || (p->slant == SLANT_ITALIC)))
+
+ /* Add the indices to this font now so we
+ won't have to loop over each font in
+ order to open it later. */
+
+ p->specified |= FSPEC_INDICES;
+ p->family_index = fi;
+ p->style_index = si;
+
+ if (pt->specified & FSPEC_ANTIALIAS)
+ {
+ p->specified |= FSPEC_ANTIALIAS;
+ p->use_antialiasing = pt->use_antialiasing;
+ }
+
+ if (p->specified & FSPEC_SLANT
+ && (p->slant == SLANT_OBLIQUE
+ || p->slant == SLANT_ITALIC))
oblique_seen_p = 1;
p->next = r;
@@ -483,9 +652,7 @@ BFont_find (struct haiku_font_pattern *pt)
p->last = NULL;
for (; head; head = head->last)
- {
- head->oblique_seen_p = oblique_seen_p;
- }
+ head->oblique_seen_p = oblique_seen_p;
}
}
}
@@ -498,13 +665,18 @@ BFont_find (struct haiku_font_pattern *pt)
if (!(pt->specified & FSPEC_SLANT))
{
/* r->last is invalid from here onwards. */
- for (struct haiku_font_pattern *p = r; p;)
+ for (p = r; p;)
{
if (!p->oblique_seen_p)
{
- struct haiku_font_pattern *n = new haiku_font_pattern;
+ n = new haiku_font_pattern;
*n = *p;
+
n->slant = SLANT_OBLIQUE;
+
+ /* Opening a font by its indices doesn't provide enough
+ information to synthesize the oblique font later. */
+ n->specified &= ~FSPEC_INDICES;
p->next = n;
p = p->next_family;
}
@@ -516,51 +688,99 @@ BFont_find (struct haiku_font_pattern *pt)
return r;
}
+/* Find and open a font with the family at FAMILY and the style at
+ STYLE, and set its size to SIZE. Value is NULL if opening the font
+ failed. */
+void *
+be_open_font_at_index (int family, int style, float size)
+{
+ font_family family_name;
+ font_style style_name;
+ uint32 flags;
+ status_t rc;
+ BFont *font;
+
+ rc = get_font_family (family, &family_name, &flags);
+
+ if (rc != B_OK)
+ return NULL;
+
+ rc = get_font_style (family_name, style, &style_name, &flags);
+
+ if (rc != B_OK)
+ return NULL;
+
+ font = new BFont;
+
+ rc = font->SetFamilyAndStyle (family_name, style_name);
+
+ if (rc != B_OK)
+ {
+ delete font;
+ return NULL;
+ }
+
+ font->SetSize (size);
+ font->SetEncoding (B_UNICODE_UTF8);
+ font->SetSpacing (B_BITMAP_SPACING);
+ return font;
+}
+
/* Find and open a font matching the pattern PAT, which must have its
family set. */
int
BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size)
{
- int sty_count;
+ int sty_count, si, code;
font_family name;
font_style sname;
+ BFont *ft;
uint32 flags = 0;
+ struct haiku_font_pattern copy;
+
if (!(pat->specified & FSPEC_FAMILY))
return 1;
+
strncpy (name, pat->family, sizeof name - 1);
+ name[sizeof name - 1] = '\0';
+
sty_count = count_font_styles (name);
- if (!sty_count &&
- font_family_style_matches_p (name, NULL, flags, pat, 1))
+ if (!sty_count
+ && font_family_style_matches_p (name, NULL, flags, pat, 1))
{
- BFont *ft = new BFont;
+ ft = new BFont;
+ ft->SetSize (size);
+ ft->SetEncoding (B_UNICODE_UTF8);
+ ft->SetSpacing (B_BITMAP_SPACING);
+
if (ft->SetFamilyAndStyle (name, NULL) != B_OK)
{
delete ft;
return 1;
}
- ft->SetSize (size);
- ft->SetEncoding (B_UNICODE_UTF8);
- ft->SetSpacing (B_BITMAP_SPACING);
*font = (void *) ft;
return 0;
}
else if (sty_count)
{
- for (int si = 0; si < sty_count; ++si)
+ for (si = 0; si < sty_count; ++si)
{
- if (get_font_style (name, si, &sname, &flags) == B_OK &&
- font_family_style_matches_p (name, (char *) &sname, flags, pat))
+ if (get_font_style (name, si, &sname, &flags) == B_OK
+ && font_family_style_matches_p (name, (char *) &sname,
+ flags, pat))
{
- BFont *ft = new BFont;
+ ft = new BFont;
+ ft->SetSize (size);
+ ft->SetEncoding (B_UNICODE_UTF8);
+ ft->SetSpacing (B_BITMAP_SPACING);
+
if (ft->SetFamilyAndStyle (name, sname) != B_OK)
{
delete ft;
return 1;
}
- ft->SetSize (size);
- ft->SetEncoding (B_UNICODE_UTF8);
- ft->SetSpacing (B_BITMAP_SPACING);
+
*font = (void *) ft;
return 0;
}
@@ -569,12 +789,14 @@ BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size)
if (pat->specified & FSPEC_SLANT && pat->slant == SLANT_OBLIQUE)
{
- struct haiku_font_pattern copy = *pat;
+ copy = *pat;
copy.slant = SLANT_REGULAR;
- int code = BFont_open_pattern (&copy, font, size);
+ code = BFont_open_pattern (&copy, font, size);
+
if (code)
return code;
- BFont *ft = (BFont *) *font;
+
+ ft = (BFont *) *font;
/* XXX Font measurements don't respect shear. Haiku bug?
This apparently worked in BeOS.
ft->SetShear (100.0); */
@@ -595,6 +817,7 @@ BFont_populate_fixed_family (struct haiku_font_pattern *ptn)
ptn->specified |= FSPEC_FAMILY;
strncpy (ptn->family, f, sizeof ptn->family - 1);
+ ptn->family[sizeof ptn->family - 1] = '\0';
}
void
@@ -606,10 +829,113 @@ BFont_populate_plain_family (struct haiku_font_pattern *ptn)
ptn->specified |= FSPEC_FAMILY;
strncpy (ptn->family, f, sizeof ptn->family - 1);
+ ptn->family[sizeof ptn->family - 1] = '\0';
+}
+
+haiku_font_family_or_style *
+be_list_font_families (size_t *length)
+{
+ int32 families = count_font_families ();
+ haiku_font_family_or_style *array;
+ int32 idx;
+ uint32 flags;
+
+ array = (haiku_font_family_or_style *) malloc (sizeof *array * families);
+
+ if (!array)
+ return NULL;
+
+ for (idx = 0; idx < families; ++idx)
+ {
+ if (get_font_family (idx, &array[idx], &flags) != B_OK)
+ array[idx][0] = '\0';
+ }
+
+ *length = families;
+
+ return array;
+}
+
+void
+be_init_font_data (void)
+{
+ memset (&font_object_cache, 0, sizeof font_object_cache);
+}
+
+/* Free the font object cache. This is called every 50 updates of a
+ frame. */
+void
+be_evict_font_cache (void)
+{
+ struct font_object_cache_bucket *bucket, *last;
+ int i;
+
+ for (i = 0; i < 2048; ++i)
+ {
+ bucket = font_object_cache[i];
+
+ while (bucket)
+ {
+ last = bucket;
+ bucket = bucket->next;
+ delete last->font_object;
+ delete last;
+ }
+
+ font_object_cache[i] = NULL;
+ }
+}
+
+void
+be_font_style_to_flags (char *style, struct haiku_font_pattern *pattern)
+{
+ pattern->specified = 0;
+
+ font_style_to_flags (style, pattern);
}
int
-BFont_string_width (void *font, const char *utf8)
+be_find_font_indices (struct haiku_font_pattern *pattern,
+ int *family_index, int *style_index)
{
- return ((BFont *) font)->StringWidth (utf8);
+ int32 i, j, n_families, n_styles;
+ font_family family;
+ font_style style;
+ uint32 flags;
+
+ n_families = count_font_families ();
+
+ for (i = 0; i < n_families; ++i)
+ {
+ if (get_font_family (i, &family, &flags) == B_OK)
+ {
+ n_styles = count_font_styles (family);
+
+ for (j = 0; j < n_styles; ++j)
+ {
+ if (get_font_style (family, j, &style, &flags) == B_OK
+ && font_family_style_matches_p (family, style,
+ flags, pattern))
+ {
+ *family_index = i;
+ *style_index = j;
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+void
+be_set_font_antialiasing (void *font, bool antialias_p)
+{
+ BFont *font_object;
+
+ font_object = (BFont *) font;
+ font_object->SetFlags (antialias_p
+ ? B_FORCE_ANTIALIASING
+ : B_DISABLE_ANTIALIASING);
}
diff --git a/src/haiku_io.c b/src/haiku_io.c
index cb7750634cf..5cc70f6f71f 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -36,10 +36,19 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Emacs. */
port_id port_application_to_emacs;
+/* The port used to send popup menu messages from the application
+ thread to Emacs. */
+port_id port_popup_menu_to_emacs;
+
+/* The port used to send replies to the application after a session
+ management event. */
+port_id port_emacs_to_session_manager;
+
void
haiku_io_init (void)
{
port_application_to_emacs = create_port (PORT_CAP, "application emacs port");
+ port_emacs_to_session_manager = create_port (1, "session manager port");
}
static ssize_t
@@ -75,21 +84,31 @@ haiku_len (enum haiku_event_type type)
return sizeof (struct haiku_wheel_move_event);
case MENU_BAR_RESIZE:
return sizeof (struct haiku_menu_bar_resize_event);
+ case MENU_BAR_CLICK:
+ return sizeof (struct haiku_menu_bar_click_event);
case MENU_BAR_OPEN:
case MENU_BAR_CLOSE:
return sizeof (struct haiku_menu_bar_state_event);
case MENU_BAR_SELECT_EVENT:
return sizeof (struct haiku_menu_bar_select_event);
- case FILE_PANEL_EVENT:
- return sizeof (struct haiku_file_panel_event);
case MENU_BAR_HELP_EVENT:
return sizeof (struct haiku_menu_bar_help_event);
case ZOOM_EVENT:
return sizeof (struct haiku_zoom_event);
- case REFS_EVENT:
- return sizeof (struct haiku_refs_event);
+ case DRAG_AND_DROP_EVENT:
+ return sizeof (struct haiku_drag_and_drop_event);
case APP_QUIT_REQUESTED_EVENT:
return sizeof (struct haiku_app_quit_requested_event);
+ case DUMMY_EVENT:
+ return sizeof (struct haiku_dummy_event);
+ case MENU_BAR_LEFT:
+ return sizeof (struct haiku_menu_bar_left_event);
+ case SCROLL_BAR_PART_EVENT:
+ return sizeof (struct haiku_scroll_bar_part_event);
+ case SCREEN_CHANGED_EVENT:
+ return sizeof (struct haiku_screen_changed_event);
+ case CLIPBOARD_CHANGED_EVENT:
+ return sizeof (struct haiku_clipboard_changed_event);
}
emacs_abort ();
@@ -98,9 +117,11 @@ haiku_len (enum haiku_event_type type)
/* Read the size of the next message into len, returning -1 if the
query fails or there is no next message. */
void
-haiku_read_size (ssize_t *len)
+haiku_read_size (ssize_t *len, bool popup_menu_p)
{
- port_id from = port_application_to_emacs;
+ port_id from = (popup_menu_p
+ ? port_popup_menu_to_emacs
+ : port_application_to_emacs);
ssize_t size;
size = port_buffer_size_etc (from, B_TIMEOUT, 0);
@@ -129,13 +150,16 @@ haiku_read (enum haiku_event_type *type, void *buf, ssize_t len)
}
/* The same as haiku_read, but time out after TIMEOUT microseconds.
+ POPUP_MENU_P means to read from the popup menu port instead.
Input is blocked when an attempt to read is in progress. */
int
haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len,
- time_t timeout)
+ bigtime_t timeout, bool popup_menu_p)
{
int32 typ;
- port_id from = port_application_to_emacs;
+ port_id from = (popup_menu_p
+ ? port_popup_menu_to_emacs
+ : port_application_to_emacs);
block_input ();
if (read_port_etc (from, &typ, buf, len,
@@ -165,9 +189,12 @@ haiku_write (enum haiku_event_type type, void *buf)
}
int
-haiku_write_without_signal (enum haiku_event_type type, void *buf)
+haiku_write_without_signal (enum haiku_event_type type, void *buf,
+ bool popup_menu_p)
{
- port_id to = port_application_to_emacs;
+ port_id to = (popup_menu_p
+ ? port_popup_menu_to_emacs
+ : port_application_to_emacs);
if (write_port (to, (int32_t) type, buf, haiku_len (type)) < B_OK)
return -1;
@@ -184,24 +211,3 @@ haiku_io_init_in_app_thread (void)
if (pthread_sigmask (SIG_BLOCK, &set, NULL))
perror ("pthread_sigmask");
}
-
-/* Record an unwind protect from C++ code. */
-void
-record_c_unwind_protect_from_cxx (void (*fn) (void *), void *r)
-{
- record_unwind_protect_ptr (fn, r);
-}
-
-/* SPECPDL_IDX that is safe from C++ code. */
-ptrdiff_t
-c_specpdl_idx_from_cxx (void)
-{
- return SPECPDL_INDEX ();
-}
-
-/* unbind_to (IDX, Qnil), but safe from C++ code. */
-void
-c_unbind_to_nil_from_cxx (ptrdiff_t idx)
-{
- unbind_to (idx, Qnil);
-}
diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 041e244f3ea..e1f2a815241 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -18,212 +18,493 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
+#include <Application.h>
#include <Clipboard.h>
+#include <Message.h>
+#include <Path.h>
+#include <Entry.h>
#include <cstdlib>
#include <cstring>
#include "haikuselect.h"
-
+/* The clipboard object representing the primary selection. */
static BClipboard *primary = NULL;
+
+/* The clipboard object representing the secondary selection. */
static BClipboard *secondary = NULL;
+
+/* The clipboard object used by other programs, representing the
+ clipboard. */
static BClipboard *system_clipboard = NULL;
-int selection_state_flag;
+/* The number of times the system clipboard has changed. */
+static int64 count_clipboard = -1;
-static char *
-BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len)
-{
- if (!cb->Lock ())
- return 0;
+/* The number of times the primary selection has changed. */
+static int64 count_primary = -1;
- BMessage *dat = cb->Data ();
- if (!dat)
- {
- cb->Unlock ();
- return 0;
- }
+/* The number of times the secondary selection has changed. */
+static int64 count_secondary = -1;
- const char *ptr;
- ssize_t bt;
- dat->FindData (type, B_MIME_TYPE, (const void **) &ptr, &bt);
+/* Whether or not we currently think Emacs owns the primary
+ selection. */
+static bool owned_primary;
- if (!ptr)
+/* Likewise for the secondary selection. */
+static bool owned_secondary;
+
+/* And the clipboard. */
+static bool owned_clipboard;
+
+static BClipboard *
+get_clipboard_object (enum haiku_clipboard clipboard)
+{
+ switch (clipboard)
{
- cb->Unlock ();
- return NULL;
- }
+ case CLIPBOARD_PRIMARY:
+ return primary;
- if (len)
- *len = bt;
+ case CLIPBOARD_SECONDARY:
+ return secondary;
- cb->Unlock ();
+ case CLIPBOARD_CLIPBOARD:
+ return system_clipboard;
+ }
- return strndup (ptr, bt);
+ abort ();
}
-static void
-BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size)
+static char *
+be_find_clipboard_data_1 (BClipboard *cb, const char *type, ssize_t *len)
{
BMessage *data;
- char *name;
- int32 count_found;
- type_code type;
- int32 i;
- int index;
+ const char *ptr;
+ ssize_t nbytes;
+ void *value;
if (!cb->Lock ())
- {
- buf[0] = NULL;
- return;
- }
+ return NULL;
data = cb->Data ();
- index = 0;
if (!data)
{
- buf[0] = NULL;
cb->Unlock ();
- return;
+ return NULL;
}
- for (i = 0; (data->GetInfo (B_ANY_TYPE, i, &name,
- &type, &count_found)
- == B_OK); ++i)
+ data->FindData (type, B_MIME_TYPE, (const void **) &ptr,
+ &nbytes);
+
+ if (!ptr)
{
- if (type == B_MIME_TYPE)
- {
- if (index < (buf_size - 1))
- {
- buf[index++] = strdup (name);
-
- if (!buf[index - 1])
- break;
- }
- }
+ cb->Unlock ();
+ return NULL;
}
- buf[index] = NULL;
+ if (len)
+ *len = nbytes;
+
+ value = malloc (nbytes);
+ if (!data)
+ {
+ cb->Unlock ();
+ return NULL;
+ }
+
+ memcpy (value, ptr, nbytes);
cb->Unlock ();
+
+ return (char *) value;
}
static void
-BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
- ssize_t len, bool clear)
+be_set_clipboard_data_1 (BClipboard *cb, const char *type, const char *data,
+ ssize_t len, bool clear)
{
+ BMessage *message_data;
+
if (!cb->Lock ())
return;
if (clear)
cb->Clear ();
- BMessage *mdat = cb->Data ();
- if (!mdat)
+ message_data = cb->Data ();
+
+ if (!message_data)
{
cb->Unlock ();
return;
}
- if (dat)
+ if (data)
{
- if (mdat->ReplaceData (type, B_MIME_TYPE, dat, len)
+ if (message_data->ReplaceData (type, B_MIME_TYPE, data, len)
== B_NAME_NOT_FOUND)
- mdat->AddData (type, B_MIME_TYPE, dat, len);
+ message_data->AddData (type, B_MIME_TYPE, data, len);
}
else
- mdat->RemoveName (type);
+ message_data->RemoveName (type);
+
cb->Commit ();
cb->Unlock ();
}
+void
+be_update_clipboard_count (enum haiku_clipboard id)
+{
+ switch (id)
+ {
+ case CLIPBOARD_CLIPBOARD:
+ count_clipboard = system_clipboard->SystemCount ();
+ owned_clipboard = true;
+ break;
+
+ case CLIPBOARD_PRIMARY:
+ count_primary = primary->SystemCount ();
+ owned_primary = true;
+ break;
+
+ case CLIPBOARD_SECONDARY:
+ count_secondary = secondary->SystemCount ();
+ owned_secondary = true;
+ break;
+ }
+}
+
char *
-BClipboard_find_system_data (const char *type, ssize_t *len)
+be_find_clipboard_data (enum haiku_clipboard id, const char *type,
+ ssize_t *len)
+{
+ return be_find_clipboard_data_1 (get_clipboard_object (id),
+ type, len);
+}
+
+void
+be_set_clipboard_data (enum haiku_clipboard id, const char *type,
+ const char *data, ssize_t len, bool clear)
{
- if (!system_clipboard)
- return 0;
+ be_update_clipboard_count (id);
- return BClipboard_find_data (system_clipboard, type, len);
+ be_set_clipboard_data_1 (get_clipboard_object (id), type,
+ data, len, clear);
}
-char *
-BClipboard_find_primary_selection_data (const char *type, ssize_t *len)
+static bool
+clipboard_owner_p (void)
{
- if (!primary)
- return 0;
+ return (count_clipboard >= 0
+ && (count_clipboard + 1
+ == system_clipboard->SystemCount ()));
+}
- return BClipboard_find_data (primary, type, len);
+static bool
+primary_owner_p (void)
+{
+ return (count_primary >= 0
+ && (count_primary + 1
+ == primary->SystemCount ()));
}
-char *
-BClipboard_find_secondary_selection_data (const char *type, ssize_t *len)
+static bool
+secondary_owner_p (void)
+{
+ return (count_secondary >= 0
+ && (count_secondary + 1
+ == secondary->SystemCount ()));
+}
+
+bool
+be_clipboard_owner_p (enum haiku_clipboard clipboard)
{
- if (!secondary)
- return 0;
+ switch (clipboard)
+ {
+ case CLIPBOARD_PRIMARY:
+ return primary_owner_p ();
+
+ case CLIPBOARD_SECONDARY:
+ return secondary_owner_p ();
+
+ case CLIPBOARD_CLIPBOARD:
+ return clipboard_owner_p ();
+ }
- return BClipboard_find_data (secondary, type, len);
+ abort ();
}
void
-BClipboard_set_system_data (const char *type, const char *data,
- ssize_t len, bool clear)
+be_clipboard_init (void)
{
- if (!system_clipboard)
- return;
+ system_clipboard = new BClipboard ("system");
+ primary = new BClipboard ("primary");
+ secondary = new BClipboard ("secondary");
+}
+
+int
+be_enum_message (void *message, int32 *tc, int32 index,
+ int32 *count, const char **name_return)
+{
+ BMessage *msg = (BMessage *) message;
+ type_code type;
+ char *name;
+ status_t rc;
- BClipboard_set_data (system_clipboard, type, data, len, clear);
+ rc = msg->GetInfo (B_ANY_TYPE, index, &name, &type, count);
+
+ if (rc != B_OK)
+ return 1;
+
+ *tc = type;
+ *name_return = name;
+ return 0;
}
-void
-BClipboard_set_primary_selection_data (const char *type, const char *data,
- ssize_t len, bool clear)
+int
+be_get_refs_data (void *message, const char *name,
+ int32 index, char **path_buffer)
{
- if (!primary)
- return;
+ status_t rc;
+ BEntry entry;
+ BPath path;
+ entry_ref ref;
+ BMessage *msg;
+
+ msg = (BMessage *) message;
+ rc = msg->FindRef (name, index, &ref);
- BClipboard_set_data (primary, type, data, len, clear);
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.SetTo (&ref, 0);
+
+ if (rc != B_OK)
+ return 1;
+
+ rc = entry.GetPath (&path);
+
+ if (rc != B_OK)
+ return 1;
+
+ *path_buffer = strdup (path.Path ());
+ return 0;
}
-void
-BClipboard_set_secondary_selection_data (const char *type, const char *data,
- ssize_t len, bool clear)
+int
+be_get_point_data (void *message, const char *name,
+ int32 index, float *x, float *y)
{
- if (!secondary)
- return;
+ status_t rc;
+ BMessage *msg;
+ BPoint point;
+
+ msg = (BMessage *) message;
+ rc = msg->FindPoint (name, index, &point);
+
+ if (rc != B_OK)
+ return 1;
+
+ *x = point.x;
+ *y = point.y;
- BClipboard_set_data (secondary, type, data, len, clear);
+ return 0;
}
-void
-BClipboard_free_data (void *ptr)
+int
+be_get_message_data (void *message, const char *name,
+ int32 type_code, int32 index,
+ const void **buf_return,
+ ssize_t *size_return)
+{
+ BMessage *msg = (BMessage *) message;
+
+ return msg->FindData (name, type_code,
+ index, buf_return, size_return) != B_OK;
+}
+
+uint32
+be_get_message_type (void *message)
{
- std::free (ptr);
+ BMessage *msg = (BMessage *) message;
+
+ return msg->what;
}
void
-BClipboard_system_targets (char **buf, int len)
+be_set_message_type (void *message, uint32 what)
+{
+ BMessage *msg = (BMessage *) message;
+
+ msg->what = what;
+}
+
+void *
+be_get_message_message (void *message, const char *name,
+ int32 index)
+{
+ BMessage *msg = (BMessage *) message;
+ BMessage *out = new (std::nothrow) BMessage;
+
+ if (!out)
+ return NULL;
+
+ if (msg->FindMessage (name, index, out) != B_OK)
+ {
+ delete out;
+ return NULL;
+ }
+
+ return out;
+}
+
+void *
+be_create_simple_message (void)
+{
+ return new BMessage (B_SIMPLE_DATA);
+}
+
+int
+be_add_message_data (void *message, const char *name,
+ int32 type_code, const void *buf,
+ ssize_t buf_size)
+{
+ BMessage *msg = (BMessage *) message;
+
+ return msg->AddData (name, type_code, buf, buf_size) != B_OK;
+}
+
+int
+be_add_refs_data (void *message, const char *name,
+ const char *filename)
+{
+ BEntry entry (filename);
+ entry_ref ref;
+ BMessage *msg = (BMessage *) message;
+
+ if (entry.InitCheck () != B_OK)
+ return 1;
+
+ if (entry.GetRef (&ref) != B_OK)
+ return 1;
+
+ return msg->AddRef (name, &ref) != B_OK;
+}
+
+int
+be_add_point_data (void *message, const char *name,
+ float x, float y)
+{
+ BMessage *msg = (BMessage *) message;
+
+ return msg->AddPoint (name, BPoint (x, y)) != B_OK;
+}
+
+int
+be_add_message_message (void *message, const char *name,
+ void *data)
+{
+ BMessage *msg = (BMessage *) message;
+ BMessage *data_message = (BMessage *) data;
+
+ if (msg->AddMessage (name, data_message) != B_OK)
+ return 1;
+
+ return 0;
+}
+
+int
+be_lock_clipboard_message (enum haiku_clipboard clipboard,
+ void **message_return, bool clear)
{
- BClipboard_get_targets (system_clipboard, buf, len);
+ BClipboard *board;
+
+ board = get_clipboard_object (clipboard);
+
+ if (!board->Lock ())
+ return 1;
+
+ if (clear)
+ board->Clear ();
+
+ *message_return = board->Data ();
+ return 0;
}
void
-BClipboard_primary_targets (char **buf, int len)
+be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard)
{
- BClipboard_get_targets (primary, buf, len);
+ BClipboard *board;
+
+ board = get_clipboard_object (clipboard);
+
+ if (discard)
+ board->Revert ();
+ else
+ board->Commit ();
+
+ board->Unlock ();
}
void
-BClipboard_secondary_targets (char **buf, int len)
+be_handle_clipboard_changed_message (void)
{
- BClipboard_get_targets (secondary, buf, len);
+ int64 n_clipboard, n_primary, n_secondary;
+
+ n_clipboard = system_clipboard->SystemCount ();
+ n_primary = primary->SystemCount ();
+ n_secondary = secondary->SystemCount ();
+
+ if (count_clipboard != -1
+ && (n_clipboard > count_clipboard + 1)
+ && owned_clipboard)
+ {
+ owned_clipboard = false;
+ haiku_selection_disowned (CLIPBOARD_CLIPBOARD,
+ n_clipboard);
+ }
+
+ if (count_primary != -1
+ && (n_primary > count_primary + 1)
+ && owned_primary)
+ {
+ owned_primary = false;
+ haiku_selection_disowned (CLIPBOARD_PRIMARY,
+ n_primary);
+ }
+
+ if (count_secondary != -1
+ && (n_secondary > count_secondary + 1)
+ && owned_secondary)
+ {
+ owned_secondary = false;
+ haiku_selection_disowned (CLIPBOARD_SECONDARY,
+ n_secondary);
+ }
}
void
-init_haiku_select (void)
+be_start_watching_selection (enum haiku_clipboard id)
{
- system_clipboard = new BClipboard ("system");
- primary = new BClipboard ("primary");
- secondary = new BClipboard ("secondary");
+ BClipboard *clipboard;
+
+ clipboard = get_clipboard_object (id);
+ clipboard->StartWatching (be_app);
+}
+
+bool
+be_selection_outdated_p (enum haiku_clipboard id, int64 count)
+{
+ if (id == CLIPBOARD_CLIPBOARD && count_clipboard > count)
+ return true;
+
+ if (id == CLIPBOARD_PRIMARY && count_primary > count)
+ return true;
+
+ if (id == CLIPBOARD_SECONDARY && count_secondary > count)
+ return true;
+
+ return false;
}
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 2e9eff40676..a3d3b7a17d3 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -17,10 +17,13 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
+#include <attribute.h>
#include <app/Application.h>
#include <app/Cursor.h>
+#include <app/Clipboard.h>
#include <app/Messenger.h>
+#include <app/Roster.h>
#include <interface/GraphicsDefs.h>
#include <interface/InterfaceDefs.h>
@@ -36,6 +39,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <interface/MenuBar.h>
#include <interface/Alert.h>
#include <interface/Button.h>
+#include <interface/ControlLook.h>
+#include <interface/Deskbar.h>
+#include <interface/ListView.h>
+#include <interface/StringItem.h>
+#include <interface/SplitView.h>
+#include <interface/ScrollView.h>
+#include <interface/StringView.h>
+#include <interface/TextControl.h>
+#include <interface/CheckBox.h>
#include <locale/UnicodeChar.h>
@@ -52,6 +64,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <support/Beep.h>
#include <support/DataIO.h>
#include <support/Locker.h>
+#include <support/ObjectList.h>
#include <translation/TranslatorRoster.h>
#include <translation/TranslationDefs.h>
@@ -62,6 +75,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <kernel/scheduler.h>
#include <private/interface/ToolTip.h>
+#include <private/interface/WindowPrivate.h>
#include <cmath>
#include <cstring>
@@ -70,59 +84,152 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <csignal>
#include <cfloat>
-#include <pthread.h>
-
#ifdef USE_BE_CAIRO
#include <cairo.h>
#endif
#include "haiku_support.h"
-#define SCROLL_BAR_UPDATE 3000
+/* Some messages that Emacs sends to itself. */
+enum
+ {
+ SCROLL_BAR_UPDATE = 3000,
+ WAIT_FOR_RELEASE = 3001,
+ RELEASE_NOW = 3002,
+ CANCEL_DROP = 3003,
+ SHOW_MENU_BAR = 3004,
+ BE_MENU_BAR_OPEN = 3005,
+ QUIT_APPLICATION = 3006,
+ REPLAY_MENU_BAR = 3007,
+ FONT_FAMILY_SELECTED = 3008,
+ FONT_STYLE_SELECTED = 3009,
+ FILE_PANEL_SELECTION = 3010,
+ QUIT_PREVIEW_DIALOG = 3011,
+ SET_FONT_INDICES = 3012,
+ SET_PREVIEW_DIALOG = 3013,
+ UPDATE_PREVIEW_DIALOG = 3014,
+ SEND_MOVE_FRAME_EVENT = 3015,
+ SET_DISABLE_ANTIALIASING = 3016,
+ };
+
+/* X11 keysyms that we use. */
+enum
+ {
+ KEY_BACKSPACE = 0xff08,
+ KEY_TAB = 0xff09,
+ KEY_RETURN = 0xff0d,
+ KEY_PAUSE = 0xff13,
+ KEY_ESCAPE = 0xff1b,
+ KEY_DELETE = 0xffff,
+ KEY_HOME = 0xff50,
+ KEY_LEFT_ARROW = 0xff51,
+ KEY_UP_ARROW = 0xff52,
+ KEY_RIGHT_ARROW = 0xff53,
+ KEY_DOWN_ARROW = 0xff54,
+ KEY_PAGE_UP = 0xff55,
+ KEY_PAGE_DOWN = 0xff56,
+ KEY_END = 0xff57,
+ KEY_PRINT = 0xff61,
+ KEY_INSERT = 0xff63,
+ /* This is used to indicate the first function key. */
+ KEY_F1 = 0xffbe,
+ /* These are found on some multilingual keyboards. */
+ KEY_HANGUL = 0xff31,
+ KEY_HANGUL_HANJA = 0xff34,
+ KEY_HIRIGANA_KATAGANA = 0xff27,
+ KEY_ZENKAKU_HANKAKU = 0xff2a,
+ };
+
+struct font_selection_dialog_message
+{
+ /* Whether or not font selection was cancelled. */
+ bool_bf cancel : 1;
+
+ /* Whether or not a size was explicitly specified. */
+ bool_bf size_specified : 1;
+
+ /* Whether or not antialiasing should be disabled. */
+ bool_bf disable_antialias : 1;
+
+ /* The index of the selected font family. */
+ int family_idx;
+
+ /* The index of the selected font style. */
+ int style_idx;
+
+ /* The selected font size. */
+ int size;
+};
+/* The color space of the main screen. B_NO_COLOR_SPACE means it has
+ not yet been computed. */
static color_space dpy_color_space = B_NO_COLOR_SPACE;
-static key_map *key_map = NULL;
-static char *key_chars = NULL;
+
+/* The keymap, or NULL if it has not been initialized. */
+static key_map *key_map;
+
+/* Indices of characters into the keymap. */
+static char *key_chars;
+
+/* Lock around keymap data, since it's touched from different
+ threads. */
static BLocker key_map_lock;
/* The locking semantics of BWindows running in multiple threads are
so complex that child frame state (which is the only state that is
shared between different BWindows at runtime) does best with a
single global lock. */
-
static BLocker child_frame_lock;
-/* A LeaveNotify event (well, the closest equivalent on Haiku, which
- is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might
- be sent out-of-order with regards to motion events from other
- windows, such as when the mouse pointer rapidly moves from an
- undecorated child frame to its parent. This can cause a failure to
- clear the mouse face on the former if an event for the latter is
- read by Emacs first and ends up showing the mouse face there.
-
- While this lock doesn't really ensure that the events will be
- delivered in the correct order, it makes them arrive in the correct
- order "most of the time" on my machine, which is good enough and
- preferable to adding a lot of extra complexity to the event
- handling code to sort motion events by their timestamps.
-
- Obviously this depends on the number of execution units that are
- available, and the scheduling priority of each thread involved in
- the input handling, but it will be good enough for most people. */
-
-static BLocker movement_locker;
+/* Variable where the popup menu thread returns the chosen menu
+ item. */
+static BMessage volatile *popup_track_message;
+
+/* Variable in which alert dialog threads return the selected button
+ number. */
+static int32 volatile alert_popup_value;
+
+/* The current window ID. This is increased every time a frame is
+ created. */
+static int current_window_id;
+
+/* The view that has the passive grab. */
+static void *grab_view;
+
+/* The locker for that variable. */
+static BLocker grab_view_locker;
+
+/* Whether or not a drag-and-drop operation is in progress. */
+static bool drag_and_drop_in_progress;
+
+/* Many places require us to lock the child frame data, and then lock
+ the locker of some random window. Unfortunately, locking such a
+ window might be delayed due to an arriving message, which then
+ calls a callback inside that window that tries to lock the child
+ frame data but doesn't finish since the child frame lock is already
+ held, not letting the code that held the child frame lock proceed,
+ thereby causing a deadlock.
+
+ Rectifying that problem is simple: all code in a looper callback
+ must lock the child frame data with this macro instead.
+
+ IOW, if some other code is already running with the child frame
+ lock held, don't interfere: wait until it's finished before
+ continuing. */
+#define CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK \
+ if (child_frame_lock.LockWithTimeout (200) != B_OK) \
+ { \
+ /* The Haiku equivalent of XPutBackEvent. */ \
+ if (CurrentMessage ()) \
+ PostMessage (CurrentMessage ()); \
+ } \
+ else
/* This could be a private API, but it's used by (at least) the Qt
port, so it's probably here to stay. */
extern status_t get_subpixel_antialiasing (bool *);
-extern "C"
-{
- extern _Noreturn void emacs_abort (void);
- /* Also defined in haikuterm.h. */
- extern void be_app_quit (void);
-}
-
+/* The ID of the thread the BApplication is running in. */
static thread_id app_thread;
_Noreturn void
@@ -132,7 +239,127 @@ gui_abort (const char *msg)
fprintf (stderr, "Under Haiku, Emacs cannot recover from errors in GUI code\n");
fprintf (stderr, "App Server disconnects usually manifest as bitmap "
"initialization failures or lock failures.");
- emacs_abort ();
+ abort ();
+}
+
+struct be_popup_menu_data
+{
+ int x, y;
+ BPopUpMenu *menu;
+};
+
+static int32
+be_popup_menu_thread_entry (void *thread_data)
+{
+ struct be_popup_menu_data *data;
+ struct haiku_dummy_event dummy;
+ BMenuItem *it;
+
+ data = (struct be_popup_menu_data *) thread_data;
+
+ it = data->menu->Go (BPoint (data->x, data->y));
+
+ if (it)
+ popup_track_message = it->Message ();
+ else
+ popup_track_message = NULL;
+
+ haiku_write (DUMMY_EVENT, &dummy);
+ return 0;
+}
+
+/* Convert a raw character RAW produced by the keycode KEY into a key
+ symbol and place it in KEYSYM.
+
+ If RAW cannot be converted into a keysym, value is 0. If RAW can
+ be converted into a keysym, but it should be ignored, value is -1.
+
+ Any other value means success, and that the keysym should be used
+ instead of mapping the keycode into a character. */
+
+static int
+keysym_from_raw_char (int32 raw, int32 key, unsigned *code)
+{
+ switch (raw)
+ {
+ case B_BACKSPACE:
+ *code = KEY_BACKSPACE;
+ break;
+ case B_RETURN:
+ *code = KEY_RETURN;
+ break;
+ case B_TAB:
+ *code = KEY_TAB;
+ break;
+ case B_ESCAPE:
+ *code = KEY_ESCAPE;
+ break;
+ case B_LEFT_ARROW:
+ *code = KEY_LEFT_ARROW;
+ break;
+ case B_RIGHT_ARROW:
+ *code = KEY_RIGHT_ARROW;
+ break;
+ case B_UP_ARROW:
+ *code = KEY_UP_ARROW;
+ break;
+ case B_DOWN_ARROW:
+ *code = KEY_DOWN_ARROW;
+ break;
+ case B_INSERT:
+ *code = KEY_INSERT;
+ break;
+ case B_DELETE:
+ *code = KEY_DELETE;
+ break;
+ case B_HOME:
+ *code = KEY_HOME;
+ break;
+ case B_END:
+ *code = KEY_END;
+ break;
+ case B_PAGE_UP:
+ *code = KEY_PAGE_UP;
+ break;
+ case B_PAGE_DOWN:
+ *code = KEY_PAGE_DOWN;
+ break;
+
+ case B_FUNCTION_KEY:
+ *code = KEY_F1 + key - 2;
+
+ if (*code - KEY_F1 == 12)
+ *code = KEY_PRINT;
+ else if (*code - KEY_F1 == 13)
+ /* Okay, Scroll Lock is a bit too much: keyboard.c doesn't
+ know about it yet, and it shouldn't, since that's a
+ modifier key.
+
+ *code = KEY_SCROLL_LOCK; */
+ return -1;
+ else if (*code - KEY_F1 == 14)
+ *code = KEY_PAUSE;
+
+ break;
+
+ case B_HANGUL:
+ *code = KEY_HANGUL;
+ break;
+ case B_HANGUL_HANJA:
+ *code = KEY_HANGUL_HANJA;
+ break;
+ case B_KATAKANA_HIRAGANA:
+ *code = KEY_HIRIGANA_KATAGANA;
+ break;
+ case B_HANKAKU_ZENKAKU:
+ *code = KEY_ZENKAKU_HANKAKU;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
}
static void
@@ -178,6 +405,40 @@ map_shift (uint32_t kc, uint32_t *ch)
}
static void
+map_caps (uint32_t kc, uint32_t *ch)
+{
+ if (!key_map_lock.Lock ())
+ gui_abort ("Failed to lock keymap");
+ if (!key_map)
+ get_key_map (&key_map, &key_chars);
+ if (!key_map)
+ return;
+ if (kc >= 128)
+ return;
+
+ int32_t m = key_map->caps_map[kc];
+ map_key (key_chars, m, ch);
+ key_map_lock.Unlock ();
+}
+
+static void
+map_caps_shift (uint32_t kc, uint32_t *ch)
+{
+ if (!key_map_lock.Lock ())
+ gui_abort ("Failed to lock keymap");
+ if (!key_map)
+ get_key_map (&key_map, &key_chars);
+ if (!key_map)
+ return;
+ if (kc >= 128)
+ return;
+
+ int32_t m = key_map->caps_shift_map[kc];
+ map_key (key_chars, m, ch);
+ key_map_lock.Unlock ();
+}
+
+static void
map_normal (uint32_t kc, uint32_t *ch)
{
if (!key_map_lock.Lock ())
@@ -194,11 +455,167 @@ map_normal (uint32_t kc, uint32_t *ch)
key_map_lock.Unlock ();
}
+static BRect
+get_zoom_rect (BWindow *window)
+{
+ BScreen screen;
+ BDeskbar deskbar;
+ BRect screen_frame;
+ BRect frame;
+ BRect deskbar_frame;
+ BRect window_frame;
+ BRect decorator_frame;
+
+ if (!screen.IsValid ())
+ gui_abort ("Failed to calculate screen rect");
+
+ screen_frame = frame = screen.Frame ();
+ deskbar_frame = deskbar.Frame ();
+
+ if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ())
+ {
+ switch (deskbar.Location ())
+ {
+ case B_DESKBAR_TOP:
+ frame.top = deskbar_frame.bottom + 2;
+ break;
+
+ case B_DESKBAR_BOTTOM:
+ case B_DESKBAR_LEFT_BOTTOM:
+ case B_DESKBAR_RIGHT_BOTTOM:
+ frame.bottom = deskbar_frame.top - 2;
+ break;
+
+ case B_DESKBAR_LEFT_TOP:
+ if (!deskbar.IsExpanded ())
+ frame.top = deskbar_frame.bottom + 2;
+ else if (!deskbar.IsAlwaysOnTop ()
+ && !deskbar.IsAutoRaise ())
+ frame.left = deskbar_frame.right + 2;
+ break;
+
+ default:
+ if (deskbar.IsExpanded ()
+ && !deskbar.IsAlwaysOnTop ()
+ && !deskbar.IsAutoRaise ())
+ frame.right = deskbar_frame.left - 2;
+ }
+ }
+
+ if (window)
+ {
+ window_frame = window->Frame ();
+ decorator_frame = window->DecoratorFrame ();
+
+ frame.top += (window_frame.top
+ - decorator_frame.top);
+ frame.bottom -= (decorator_frame.bottom
+ - window_frame.bottom);
+ frame.left += (window_frame.left
+ - decorator_frame.left);
+ frame.right -= (decorator_frame.right
+ - window_frame.right);
+
+ if (frame.top > deskbar_frame.bottom
+ || frame.bottom < deskbar_frame.top)
+ {
+ frame.left = screen_frame.left + (window_frame.left
+ - decorator_frame.left);
+ frame.right = screen_frame.right - (decorator_frame.right
+ - window_frame.right);
+ }
+ }
+
+ return frame;
+}
+
+/* Invisible window used to get B_SCREEN_CHANGED events. */
+class EmacsScreenChangeMonitor : public BWindow
+{
+ BRect previous_screen_frame;
+
+public:
+ EmacsScreenChangeMonitor (void) : BWindow (BRect (-100, -100, 0, 0), "",
+ B_NO_BORDER_WINDOW_LOOK,
+ B_FLOATING_ALL_WINDOW_FEEL,
+ B_AVOID_FRONT | B_AVOID_FOCUS)
+ {
+ BScreen screen (this);
+
+ if (!screen.IsValid ())
+ return;
+
+ previous_screen_frame = screen.Frame ();
+
+ /* Immediately show this window upon creation. It will not steal
+ the focus or become visible. */
+ Show ();
+
+ if (!LockLooper ())
+ return;
+
+ Hide ();
+ UnlockLooper ();
+ }
+
+ void
+ DispatchMessage (BMessage *msg, BHandler *handler)
+ {
+ struct haiku_screen_changed_event rq;
+ BRect frame;
+
+ if (msg->what == B_SCREEN_CHANGED)
+ {
+ if (msg->FindInt64 ("when", &rq.when) != B_OK)
+ rq.when = 0;
+
+ if (msg->FindRect ("frame", &frame) != B_OK
+ || frame != previous_screen_frame)
+ {
+ haiku_write (SCREEN_CHANGED_EVENT, &rq);
+
+ if (frame.IsValid ())
+ previous_screen_frame = frame;
+ }
+ }
+
+ BWindow::DispatchMessage (msg, handler);
+ }
+};
+
class Emacs : public BApplication
{
public:
- Emacs () : BApplication ("application/x-vnd.GNU-emacs")
+ BMessage settings;
+ bool settings_valid_p;
+ EmacsScreenChangeMonitor *monitor;
+
+ Emacs (void) : BApplication ("application/x-vnd.GNU-emacs"),
+ settings_valid_p (false)
{
+ BPath settings_path;
+
+ if (find_directory (B_USER_SETTINGS_DIRECTORY, &settings_path) != B_OK)
+ return;
+
+ settings_path.Append (PACKAGE_NAME);
+
+ BEntry entry (settings_path.Path ());
+ BFile settings_file (&entry, B_READ_ONLY | B_CREATE_FILE);
+
+ if (settings.Unflatten (&settings_file) != B_OK)
+ return;
+
+ settings_valid_p = true;
+ monitor = new EmacsScreenChangeMonitor;
+ }
+
+ ~Emacs (void)
+ {
+ if (monitor->LockLooper ())
+ monitor->Quit ();
+ else
+ delete monitor;
}
void
@@ -215,39 +632,31 @@ public:
QuitRequested (void)
{
struct haiku_app_quit_requested_event rq;
+ struct haiku_session_manager_reply reply;
+ int32 reply_type;
+
haiku_write (APP_QUIT_REQUESTED_EVENT, &rq);
- return 0;
+
+ if (read_port (port_emacs_to_session_manager,
+ &reply_type, &reply, sizeof reply) < B_OK)
+ /* Return true so the system kills us, since there's no real
+ alternative if this read fails. */
+ return true;
+
+ return reply.quit_reply;
}
void
- RefsReceived (BMessage *msg)
+ MessageReceived (BMessage *msg)
{
- struct haiku_refs_event rq;
- entry_ref ref;
- BEntry entry;
- BPath path;
- int32 cookie = 0;
- int32 x, y;
- void *window;
-
- if ((msg->FindPointer ("window", 0, &window) != B_OK)
- || (msg->FindInt32 ("x", 0, &x) != B_OK)
- || (msg->FindInt32 ("y", 0, &y) != B_OK))
- return;
+ struct haiku_clipboard_changed_event rq;
- rq.window = window;
- rq.x = x;
- rq.y = y;
-
- while (msg->FindRef ("refs", cookie++, &ref) == B_OK)
- {
- if (entry.SetTo (&ref, 0) == B_OK
- && entry.GetPath (&path) == B_OK)
- {
- rq.ref = strdup (path.Path ());
- haiku_write (REFS_EVENT, &rq);
- }
- }
+ if (msg->what == QUIT_APPLICATION)
+ Quit ();
+ else if (msg->what == B_CLIPBOARD_CHANGED)
+ haiku_write (CLIPBOARD_CHANGED_EVENT, &rq);
+ else
+ BApplication::MessageReceived (msg);
}
};
@@ -259,23 +668,45 @@ public:
struct child_frame *next;
int xoff, yoff;
EmacsWindow *window;
- } *subset_windows = NULL;
+ } *subset_windows;
- EmacsWindow *parent = NULL;
+ EmacsWindow *parent;
BRect pre_fullscreen_rect;
BRect pre_zoom_rect;
- int x_before_zoom = INT_MIN;
- int y_before_zoom = INT_MIN;
- int fullscreen_p = 0;
- int zoomed_p = 0;
- int shown_flag = 0;
- volatile int was_shown_p = 0;
- bool menu_bar_active_p = false;
+ int x_before_zoom;
+ int y_before_zoom;
+ bool shown_flag;
+ volatile bool was_shown_p;
+ bool menu_bar_active_p;
+ bool override_redirect_p;
+ window_look pre_override_redirect_look;
+ window_feel pre_override_redirect_feel;
+ uint32 pre_override_redirect_workspaces;
+ int window_id;
+ bool *menus_begun;
+ enum haiku_z_group z_group;
+ bool tooltip_p;
+ enum haiku_fullscreen_mode fullscreen_mode;
EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK,
- B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS)
+ B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS),
+ subset_windows (NULL),
+ parent (NULL),
+ x_before_zoom (INT_MIN),
+ y_before_zoom (INT_MIN),
+ shown_flag (false),
+ was_shown_p (false),
+ menu_bar_active_p (false),
+ override_redirect_p (false),
+ window_id (current_window_id),
+ menus_begun (NULL),
+ z_group (Z_GROUP_NONE),
+ tooltip_p (false),
+ fullscreen_mode (FULLSCREEN_MODE_NONE)
{
-
+ /* This pulse rate is used by scroll bars for repeating a button
+ action while a button is held down. */
+ SetPulseRate (30000);
}
~EmacsWindow ()
@@ -299,6 +730,19 @@ public:
}
void
+ RecomputeFeel (void)
+ {
+ if (override_redirect_p || tooltip_p)
+ SetFeel (kMenuWindowFeel);
+ else if (parent)
+ SetFeel (B_FLOATING_SUBSET_WINDOW_FEEL);
+ else if (z_group == Z_GROUP_ABOVE)
+ SetFeel (B_FLOATING_ALL_WINDOW_FEEL);
+ else
+ SetFeel (B_NORMAL_WINDOW_FEEL);
+ }
+
+ void
UpwardsSubset (EmacsWindow *w)
{
for (; w; w = w->parent)
@@ -345,17 +789,16 @@ public:
void
Unparent (void)
{
+ EmacsWindow *parent;
+
if (!child_frame_lock.Lock ())
gui_abort ("Failed to lock child frame state lock");
- this->SetFeel (B_NORMAL_WINDOW_FEEL);
+
+ parent = this->parent;
+ this->parent = NULL;
+ RecomputeFeel ();
UpwardsUnSubsetChildren (parent);
this->RemoveFromSubset (this);
- this->parent = NULL;
- if (fullscreen_p)
- {
- fullscreen_p = 0;
- MakeFullscreen (1);
- }
child_frame_lock.Unlock ();
}
@@ -401,16 +844,10 @@ public:
UnparentAndUnlink ();
this->parent = window;
- this->SetFeel (B_FLOATING_SUBSET_WINDOW_FEEL);
+ RecomputeFeel ();
this->AddToSubset (this);
if (!IsHidden () && this->parent)
UpwardsSubsetChildren (parent);
- if (fullscreen_p)
- {
- fullscreen_p = 0;
- MakeFullscreen (1);
- }
- this->Sync ();
window->LinkChild (this);
child_frame_lock.Unlock ();
@@ -437,11 +874,23 @@ public:
}
void
+ MoveToIncludingFrame (int x, int y)
+ {
+ BRect decorator, frame;
+
+ decorator = DecoratorFrame ();
+ frame = Frame ();
+
+ MoveTo (x + frame.left - decorator.left,
+ y + frame.top - decorator.top);
+ }
+
+ void
DoMove (struct child_frame *f)
{
BRect frame = this->Frame ();
- f->window->MoveTo (frame.left + f->xoff,
- frame.top + f->yoff);
+ f->window->MoveToIncludingFrame (frame.left + f->xoff,
+ frame.top + f->yoff);
}
void
@@ -489,74 +938,36 @@ public:
void
MessageReceived (BMessage *msg)
{
- int32 old_what = 0;
-
if (msg->WasDropped ())
{
- entry_ref ref;
BPoint whereto;
+ int32 windowid;
+ struct haiku_drag_and_drop_event rq;
- if (msg->FindRef ("refs", &ref) == B_OK)
- {
- msg->what = B_REFS_RECEIVED;
- msg->AddPointer ("window", this);
- if (msg->FindPoint ("_drop_point_", &whereto) == B_OK)
- {
- this->ConvertFromScreen (&whereto);
- msg->AddInt32 ("x", whereto.x);
- msg->AddInt32 ("y", whereto.y);
- }
- be_app->PostMessage (msg);
- msg->SendReply (B_OK);
- }
+ if (msg->FindInt32 ("emacs:window_id", &windowid) == B_OK
+ && !msg->IsSourceRemote ()
+ && windowid == this->window_id)
+ return;
+
+ whereto = msg->DropPoint ();
+
+ this->ConvertFromScreen (&whereto);
+
+ rq.window = this;
+ rq.message = DetachCurrentMessage ();
+ rq.x = whereto.x;
+ rq.y = whereto.y;
+
+ haiku_write (DRAG_AND_DROP_EVENT, &rq);
}
else if (msg->GetPointer ("menuptr"))
{
struct haiku_menu_bar_select_event rq;
+
rq.window = this;
rq.ptr = (void *) msg->GetPointer ("menuptr");
- haiku_write (MENU_BAR_SELECT_EVENT, &rq);
- }
- else if (msg->what == 'FPSE'
- || ((msg->FindInt32 ("old_what", &old_what) == B_OK
- && old_what == 'FPSE')))
- {
- struct haiku_file_panel_event rq;
- BEntry entry;
- BPath path;
- entry_ref ref;
-
- rq.ptr = NULL;
-
- if (msg->FindRef ("refs", &ref) == B_OK &&
- entry.SetTo (&ref, 0) == B_OK &&
- entry.GetPath (&path) == B_OK)
- {
- const char *str_path = path.Path ();
- if (str_path)
- rq.ptr = strdup (str_path);
- }
- if (msg->FindRef ("directory", &ref),
- entry.SetTo (&ref, 0) == B_OK &&
- entry.GetPath (&path) == B_OK)
- {
- const char *name = msg->GetString ("name");
- const char *str_path = path.Path ();
-
- if (name)
- {
- char str_buf[std::strlen (str_path)
- + std::strlen (name) + 2];
- snprintf ((char *) &str_buf,
- std::strlen (str_path)
- + std::strlen (name) + 2, "%s/%s",
- str_path, name);
- rq.ptr = strdup (str_buf);
- }
- }
-
- haiku_write (FILE_PANEL_EVENT, &rq);
+ haiku_write (MENU_BAR_SELECT_EVENT, &rq);
}
else
BWindow::MessageReceived (msg);
@@ -579,7 +990,11 @@ public:
rq.window = this;
- int32_t code = msg->GetInt32 ("raw_char", 0);
+ int32 raw, key;
+ int ret;
+ msg->FindInt32 ("raw_char", &raw);
+ msg->FindInt32 ("key", &key);
+ msg->FindInt64 ("when", &rq.time);
rq.modifiers = 0;
uint32_t mods = modifiers ();
@@ -596,15 +1011,33 @@ public:
if (mods & B_OPTION_KEY)
rq.modifiers |= HAIKU_MODIFIER_SUPER;
- rq.mb_char = code;
- rq.kc = msg->GetInt32 ("key", -1);
- rq.unraw_mb_char =
- BUnicodeChar::FromUTF8 (msg->GetString ("bytes"));
+ ret = keysym_from_raw_char (raw, key, &rq.keysym);
+
+ if (!ret)
+ rq.keysym = 0;
- if ((mods & B_SHIFT_KEY) && rq.kc >= 0)
- map_shift (rq.kc, &rq.unraw_mb_char);
- else if (rq.kc >= 0)
- map_normal (rq.kc, &rq.unraw_mb_char);
+ if (ret < 0)
+ return;
+
+ rq.multibyte_char = 0;
+
+ if (!rq.keysym)
+ {
+ if (mods & B_SHIFT_KEY)
+ {
+ if (mods & B_CAPS_LOCK)
+ map_caps_shift (key, &rq.multibyte_char);
+ else
+ map_shift (key, &rq.multibyte_char);
+ }
+ else
+ {
+ if (mods & B_CAPS_LOCK)
+ map_caps (key, &rq.multibyte_char);
+ else
+ map_normal (key, &rq.multibyte_char);
+ }
+ }
haiku_write (msg->what == B_KEY_DOWN ? KEY_DOWN : KEY_UP, &rq);
}
@@ -638,17 +1071,30 @@ public:
haiku_write (WHEEL_MOVE_EVENT, &rq);
};
}
+ else if (msg->what == SEND_MOVE_FRAME_EVENT)
+ FrameMoved (Frame ().LeftTop ());
+ else if (msg->what == B_SCREEN_CHANGED)
+ {
+ if (fullscreen_mode != FULLSCREEN_MODE_NONE)
+ SetFullscreen (fullscreen_mode);
+
+ BWindow::DispatchMessage (msg, handler);
+ }
else
BWindow::DispatchMessage (msg, handler);
}
void
- MenusBeginning ()
+ MenusBeginning (void)
{
struct haiku_menu_bar_state_event rq;
+
rq.window = this;
+ if (!menus_begun)
+ haiku_write (MENU_BAR_OPEN, &rq);
+ else
+ *menus_begun = true;
- haiku_write (MENU_BAR_OPEN, &rq);
menu_bar_active_p = true;
}
@@ -667,43 +1113,70 @@ public:
{
struct haiku_resize_event rq;
rq.window = this;
- rq.px_heightf = newHeight + 1.0f;
- rq.px_widthf = newWidth + 1.0f;
+ rq.width = newWidth + 1.0f;
+ rq.height = newHeight + 1.0f;
haiku_write (FRAME_RESIZED, &rq);
BWindow::FrameResized (newWidth, newHeight);
}
void
- FrameMoved (BPoint newPosition)
+ FrameMoved (BPoint new_position)
{
struct haiku_move_event rq;
+ BRect frame, decorator_frame;
+ struct child_frame *f;
+
+ if (fullscreen_mode == FULLSCREEN_MODE_WIDTH
+ && new_position.x != 0)
+ {
+ MoveTo (0, new_position.y);
+ return;
+ }
+
+ if (fullscreen_mode == FULLSCREEN_MODE_HEIGHT
+ && new_position.y != 0)
+ {
+ MoveTo (new_position.x, 0);
+ return;
+ }
+
rq.window = this;
- rq.x = std::lrint (newPosition.x);
- rq.y = std::lrint (newPosition.y);
+ rq.x = std::lrint (new_position.x);
+ rq.y = std::lrint (new_position.y);
+
+ frame = Frame ();
+ decorator_frame = DecoratorFrame ();
+
+ rq.decorator_width
+ = std::lrint (frame.left - decorator_frame.left);
+ rq.decorator_height
+ = std::lrint (frame.top - decorator_frame.top);
haiku_write (MOVE_EVENT, &rq);
- if (!child_frame_lock.Lock ())
- gui_abort ("Failed to lock child frame state lock");
- for (struct child_frame *f = subset_windows;
- f; f = f->next)
- DoMove (f);
- child_frame_lock.Unlock ();
+ CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
+ {
+ for (f = subset_windows; f; f = f->next)
+ DoMove (f);
+ child_frame_lock.Unlock ();
- Sync ();
- BWindow::FrameMoved (newPosition);
+ BWindow::FrameMoved (new_position);
+ }
}
void
WorkspacesChanged (uint32_t old, uint32_t n)
{
- if (!child_frame_lock.Lock ())
- gui_abort ("Failed to lock child frames for changing workspaces");
- for (struct child_frame *f = subset_windows;
- f; f = f->next)
- DoUpdateWorkspace (f);
- child_frame_lock.Unlock ();
+ struct child_frame *f;
+
+ CHILD_FRAME_LOCK_INSIDE_LOOPER_CALLBACK
+ {
+ for (f = subset_windows; f; f = f->next)
+ DoUpdateWorkspace (f);
+
+ child_frame_lock.Unlock ();
+ }
}
void
@@ -713,7 +1186,7 @@ public:
gui_abort ("Failed to lock child frame state lock");
if (!this->parent)
- this->MoveTo (x, y);
+ this->MoveToIncludingFrame (x, y);
else
this->parent->MoveChild (this, x, y, 0);
child_frame_lock.Unlock ();
@@ -731,12 +1204,13 @@ public:
void
Minimize (bool minimized_p)
{
- BWindow::Minimize (minimized_p);
struct haiku_iconification_event rq;
+
rq.window = this;
rq.iconified_p = !parent && minimized_p;
-
haiku_write (ICONIFICATION, &rq);
+
+ BWindow::Minimize (minimized_p);
}
void
@@ -784,73 +1258,113 @@ public:
child_frame_lock.Unlock ();
}
- void
- Zoom (BPoint o, float w, float h)
+ BRect
+ ClearFullscreen (enum haiku_fullscreen_mode target_mode)
{
- struct haiku_zoom_event rq;
- rq.window = this;
+ BRect original_frame;
- rq.x = o.x;
- rq.y = o.y;
+ switch (fullscreen_mode)
+ {
+ case FULLSCREEN_MODE_MAXIMIZED:
+ original_frame = pre_zoom_rect;
- rq.width = w + 1;
- rq.height = h + 1;
+ if (target_mode == FULLSCREEN_MODE_NONE)
+ BWindow::Zoom (pre_zoom_rect.LeftTop (),
+ BE_RECT_WIDTH (pre_zoom_rect) - 1,
+ BE_RECT_HEIGHT (pre_zoom_rect) - 1);
+ break;
- if (fullscreen_p)
- MakeFullscreen (0);
+ case FULLSCREEN_MODE_BOTH:
+ case FULLSCREEN_MODE_HEIGHT:
+ case FULLSCREEN_MODE_WIDTH:
+ original_frame = pre_fullscreen_rect;
+ SetFlags (Flags () & ~(B_NOT_MOVABLE
+ | B_NOT_ZOOMABLE
+ | B_NOT_RESIZABLE));
- if (o.x != x_before_zoom ||
- o.y != y_before_zoom)
- {
- x_before_zoom = Frame ().left;
- y_before_zoom = Frame ().top;
- pre_zoom_rect = Frame ();
- zoomed_p = 1;
- haiku_write (ZOOM_EVENT, &rq);
- }
- else
- {
- zoomed_p = 0;
- x_before_zoom = y_before_zoom = INT_MIN;
+ if (target_mode != FULLSCREEN_MODE_NONE)
+ goto out;
+
+ MoveTo (pre_fullscreen_rect.LeftTop ());
+ ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1,
+ BE_RECT_HEIGHT (pre_fullscreen_rect) - 1);
+ break;
+
+ case FULLSCREEN_MODE_NONE:
+ original_frame = Frame ();
+ break;
}
- BWindow::Zoom (o, w, h);
+ out:
+ fullscreen_mode = FULLSCREEN_MODE_NONE;
+ return original_frame;
}
- void
- UnZoom (void)
+ BRect
+ FullscreenRectForMode (enum haiku_fullscreen_mode mode)
{
- if (!zoomed_p)
- return;
- zoomed_p = 0;
+ BScreen screen (this);
+ BRect frame;
+
+ if (!screen.IsValid ())
+ return BRect (0, 0, 0, 0);
+
+ frame = screen.Frame ();
- EmacsMoveTo (pre_zoom_rect.left, pre_zoom_rect.top);
- ResizeTo (BE_RECT_WIDTH (pre_zoom_rect),
- BE_RECT_HEIGHT (pre_zoom_rect));
+ if (mode == FULLSCREEN_MODE_HEIGHT)
+ frame.right -= BE_RECT_WIDTH (frame) / 2;
+ else if (mode == FULLSCREEN_MODE_WIDTH)
+ frame.bottom -= BE_RECT_HEIGHT (frame) / 2;
+
+ return frame;
}
void
- GetParentWidthHeight (int *width, int *height)
+ SetFullscreen (enum haiku_fullscreen_mode mode)
{
- if (!child_frame_lock.Lock ())
- gui_abort ("Failed to lock child frame state lock");
+ BRect zoom_rect, frame;
- if (parent)
- {
- BRect frame = parent->Frame ();
- *width = BE_RECT_WIDTH (frame);
- *height = BE_RECT_HEIGHT (frame);
- }
- else
+ frame = ClearFullscreen (mode);
+
+ switch (mode)
{
- BScreen s (this);
- BRect frame = s.Frame ();
+ case FULLSCREEN_MODE_MAXIMIZED:
+ pre_zoom_rect = frame;
+ zoom_rect = get_zoom_rect (this);
+ BWindow::Zoom (zoom_rect.LeftTop (),
+ BE_RECT_WIDTH (zoom_rect) - 1,
+ BE_RECT_HEIGHT (zoom_rect) - 1);
+ break;
- *width = BE_RECT_WIDTH (frame);
- *height = BE_RECT_HEIGHT (frame);
+ case FULLSCREEN_MODE_BOTH:
+ SetFlags (Flags () | B_NOT_MOVABLE);
+ FALLTHROUGH;
+
+ case FULLSCREEN_MODE_HEIGHT:
+ case FULLSCREEN_MODE_WIDTH:
+ SetFlags (Flags () | B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
+ pre_fullscreen_rect = frame;
+ zoom_rect = FullscreenRectForMode (mode);
+ ResizeTo (BE_RECT_WIDTH (zoom_rect) - 1,
+ BE_RECT_HEIGHT (zoom_rect) - 1);
+ MoveTo (zoom_rect.left, zoom_rect.top);
+ break;
+
+ case FULLSCREEN_MODE_NONE:
+ break;
}
- child_frame_lock.Unlock ();
+ fullscreen_mode = mode;
+ }
+
+ void
+ Zoom (BPoint origin, float width, float height)
+ {
+ struct haiku_zoom_event rq;
+
+ rq.window = this;
+ rq.fullscreen_mode = fullscreen_mode;
+ haiku_write (ZOOM_EVENT, &rq);
}
void
@@ -873,55 +1387,12 @@ public:
child_frame_lock.Lock ();
gui_abort ("Trying to calculate offsets for a child frame that doesn't exist");
}
-
- void
- MakeFullscreen (int make_fullscreen_p)
- {
- BScreen screen (this);
-
- if (!screen.IsValid ())
- gui_abort ("Trying to make a window fullscreen without a screen");
-
- if (make_fullscreen_p == fullscreen_p)
- return;
-
- fullscreen_p = make_fullscreen_p;
- uint32 flags = Flags ();
- if (fullscreen_p)
- {
- if (zoomed_p)
- UnZoom ();
-
- flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE;
- pre_fullscreen_rect = Frame ();
-
- if (!child_frame_lock.Lock ())
- gui_abort ("Failed to lock child frame state lock");
-
- if (parent)
- parent->OffsetChildRect (&pre_fullscreen_rect, this);
-
- child_frame_lock.Unlock ();
-
- int w, h;
- EmacsMoveTo (0, 0);
- GetParentWidthHeight (&w, &h);
- ResizeTo (w, h);
- }
- else
- {
- flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE);
- EmacsMoveTo (pre_fullscreen_rect.left,
- pre_fullscreen_rect.top);
- ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect),
- BE_RECT_HEIGHT (pre_fullscreen_rect));
- }
- SetFlags (flags);
- }
};
class EmacsMenuBar : public BMenuBar
{
+ bool tracking_p;
+
public:
EmacsMenuBar () : BMenuBar (BRect (0, 0, 0, 0), NULL)
{
@@ -940,49 +1411,175 @@ public:
{
struct haiku_menu_bar_resize_event rq;
rq.window = this->Window ();
- rq.height = std::lrint (newHeight);
- rq.width = std::lrint (newWidth);
+ rq.height = std::lrint (newHeight + 1);
+ rq.width = std::lrint (newWidth + 1);
haiku_write (MENU_BAR_RESIZE, &rq);
BMenuBar::FrameResized (newWidth, newHeight);
}
+
+ void
+ MouseDown (BPoint point)
+ {
+ struct haiku_menu_bar_click_event rq;
+ EmacsWindow *ew = (EmacsWindow *) Window ();
+
+ rq.window = ew;
+ rq.x = std::lrint (point.x);
+ rq.y = std::lrint (point.y);
+
+ if (!ew->menu_bar_active_p)
+ haiku_write (MENU_BAR_CLICK, &rq);
+ else
+ BMenuBar::MouseDown (point);
+ }
+
+ void
+ MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
+ {
+ struct haiku_menu_bar_left_event rq;
+
+ if (transit == B_EXITED_VIEW)
+ {
+ rq.x = std::lrint (point.x);
+ rq.y = std::lrint (point.y);
+ rq.window = this->Window ();
+
+ haiku_write (MENU_BAR_LEFT, &rq);
+ }
+
+ BMenuBar::MouseMoved (point, transit, msg);
+ }
+
+ void
+ MessageReceived (BMessage *msg)
+ {
+ BRect frame;
+ BPoint pt, l;
+ EmacsWindow *window;
+ bool menus_begun;
+
+ if (msg->what == SHOW_MENU_BAR)
+ {
+ window = (EmacsWindow *) Window ();
+ frame = Frame ();
+ pt = frame.LeftTop ();
+ l = pt;
+ menus_begun = false;
+ Parent ()->ConvertToScreen (&pt);
+
+ window->menus_begun = &menus_begun;
+ set_mouse_position (pt.x, pt.y);
+ BMenuBar::MouseDown (l);
+ window->menus_begun = NULL;
+
+ if (!menus_begun)
+ msg->SendReply (msg);
+ else
+ msg->SendReply (BE_MENU_BAR_OPEN);
+ }
+ else if (msg->what == REPLAY_MENU_BAR)
+ {
+ window = (EmacsWindow *) Window ();
+ menus_begun = false;
+ window->menus_begun = &menus_begun;
+
+ if (msg->FindPoint ("emacs:point", &pt) == B_OK)
+ BMenuBar::MouseDown (pt);
+
+ window->menus_begun = NULL;
+
+ if (!menus_begun)
+ msg->SendReply (msg);
+ else
+ msg->SendReply (BE_MENU_BAR_OPEN);
+ }
+ else
+ BMenuBar::MessageReceived (msg);
+ }
};
class EmacsView : public BView
{
public:
- uint32_t visible_bell_color = 0;
- uint32_t previous_buttons = 0;
- int looper_locked_count = 0;
+ uint32_t previous_buttons;
+ int looper_locked_count;
BRegion sb_region;
+ BRegion invalid_region;
- BView *offscreen_draw_view = NULL;
- BBitmap *offscreen_draw_bitmap_1 = NULL;
- BBitmap *copy_bitmap = NULL;
+ BView *offscreen_draw_view;
+ BBitmap *offscreen_draw_bitmap_1;
+ BBitmap *copy_bitmap;
#ifdef USE_BE_CAIRO
- cairo_surface_t *cr_surface = NULL;
+ cairo_surface_t *cr_surface;
+ cairo_t *cr_context;
BLocker cr_surface_lock;
#endif
- BPoint tt_absl_pos;
+ BMessage *wait_for_release_message;
- color_space cspace;
-
- EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", B_FOLLOW_NONE, B_WILL_DRAW)
+ EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs",
+ B_FOLLOW_NONE, B_WILL_DRAW),
+ previous_buttons (0),
+ looper_locked_count (0),
+ offscreen_draw_view (NULL),
+ offscreen_draw_bitmap_1 (NULL),
+ copy_bitmap (NULL),
+#ifdef USE_BE_CAIRO
+ cr_surface (NULL),
+ cr_context (NULL),
+#endif
+ wait_for_release_message (NULL)
{
}
~EmacsView ()
{
+ if (wait_for_release_message)
+ {
+ wait_for_release_message->SendReply (wait_for_release_message);
+ delete wait_for_release_message;
+ }
+
TearDownDoubleBuffering ();
+
+ if (!grab_view_locker.Lock ())
+ gui_abort ("Couldn't lock grab view locker");
+ if (grab_view == this)
+ grab_view = NULL;
+ grab_view_locker.Unlock ();
}
void
- AttachedToWindow (void)
+ MessageReceived (BMessage *msg)
{
- cspace = B_RGBA32;
+ uint32 buttons;
+ BLooper *looper = Looper ();
+
+ if (msg->what == WAIT_FOR_RELEASE)
+ {
+ if (wait_for_release_message)
+ gui_abort ("Wait for release message already exists");
+
+ GetMouse (NULL, &buttons, false);
+
+ if (!buttons)
+ msg->SendReply (msg);
+ else
+ wait_for_release_message = looper->DetachCurrentMessage ();
+ }
+ else if (msg->what == RELEASE_NOW)
+ {
+ if (wait_for_release_message)
+ wait_for_release_message->SendReply (msg);
+
+ delete wait_for_release_message;
+ wait_for_release_message = NULL;
+ }
+ else
+ BView::MessageReceived (msg);
}
#ifdef USE_BE_CAIRO
@@ -993,8 +1590,10 @@ public:
gui_abort ("Could not lock cr surface during detachment");
if (!cr_surface)
gui_abort ("Trying to detach window cr surface when none exists");
+ cairo_destroy (cr_context);
cairo_surface_destroy (cr_surface);
cr_surface = NULL;
+ cr_context = NULL;
cr_surface_lock.Unlock ();
}
@@ -1014,6 +1613,10 @@ public:
offscreen_draw_bitmap_1->BytesPerRow ());
if (!cr_surface)
gui_abort ("Cr surface allocation failed for double-buffered view");
+
+ cr_context = cairo_create (cr_surface);
+ if (!cr_context)
+ gui_abort ("cairo_t allocation failed for double-buffered view");
cr_surface_lock.Unlock ();
}
#endif
@@ -1060,7 +1663,7 @@ public:
#endif
offscreen_draw_view->RemoveSelf ();
delete offscreen_draw_bitmap_1;
- offscreen_draw_bitmap_1 = new BBitmap (Frame (), cspace, 1);
+ offscreen_draw_bitmap_1 = new BBitmap (Frame (), B_RGBA32, 1);
if (offscreen_draw_bitmap_1->InitCheck () != B_OK)
gui_abort ("Offscreen draw bitmap initialization failed");
@@ -1075,38 +1678,18 @@ public:
#endif
if (looper_locked_count)
- {
- offscreen_draw_bitmap_1->Lock ();
- }
+ offscreen_draw_bitmap_1->Lock ();
UnlockLooper ();
}
}
void
- Pulse (void)
- {
- visible_bell_color = 0;
- SetFlags (Flags () & ~B_PULSE_NEEDED);
- Window ()->SetPulseRate (0);
- Invalidate ();
- }
-
- void
Draw (BRect expose_bounds)
{
struct haiku_expose_event rq;
EmacsWindow *w = (EmacsWindow *) Window ();
- if (visible_bell_color > 0)
- {
- PushState ();
- BView_SetHighColorForVisibleBell (this, visible_bell_color);
- FillRect (Frame ());
- PopState ();
- return;
- }
-
if (w->shown_flag && offscreen_draw_view)
{
PushState ();
@@ -1143,18 +1726,6 @@ public:
}
void
- DoVisibleBell (uint32_t color)
- {
- if (!LockLooper ())
- gui_abort ("Failed to lock looper during visible bell");
- visible_bell_color = color | (255 << 24);
- SetFlags (Flags () | B_PULSE_NEEDED);
- Window ()->SetPulseRate (100 * 1000);
- Invalidate ();
- UnlockLooper ();
- }
-
- void
FlipBuffers (void)
{
if (!LockLooper ())
@@ -1162,7 +1733,6 @@ public:
if (!offscreen_draw_view)
gui_abort ("Failed to lock offscreen view during buffer flip");
- offscreen_draw_view->Flush ();
offscreen_draw_view->Sync ();
EmacsWindow *w = (EmacsWindow *) Window ();
@@ -1175,17 +1745,19 @@ public:
copy_bitmap = NULL;
}
if (!copy_bitmap)
- copy_bitmap = new BBitmap (offscreen_draw_bitmap_1);
+ {
+ copy_bitmap = new BBitmap (offscreen_draw_bitmap_1);
+ SetViewBitmap (copy_bitmap, Frame (),
+ Frame (), B_FOLLOW_NONE, 0);
+ }
else
copy_bitmap->ImportBits (offscreen_draw_bitmap_1);
if (copy_bitmap->InitCheck () != B_OK)
gui_abort ("Failed to init copy bitmap during buffer flip");
- SetViewBitmap (copy_bitmap,
- Frame (), Frame (), B_FOLLOW_NONE, 0);
-
- Invalidate ();
+ Invalidate (&invalid_region);
+ invalid_region.MakeEmpty ();
UnlockLooper ();
return;
}
@@ -1198,7 +1770,7 @@ public:
if (offscreen_draw_view)
gui_abort ("Failed to lock offscreen view setting up double buffering");
- offscreen_draw_bitmap_1 = new BBitmap (Frame (), cspace, 1);
+ offscreen_draw_bitmap_1 = new BBitmap (Frame (), B_RGBA32, 1);
if (offscreen_draw_bitmap_1->InitCheck () != B_OK)
gui_abort ("Failed to init offscreen bitmap");
#ifdef USE_BE_CAIRO
@@ -1213,58 +1785,87 @@ public:
gui_abort ("Failed to lock bitmap after double buffering was set up");
}
+ invalid_region.MakeEmpty ();
UnlockLooper ();
Invalidate ();
}
void
- MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
+ MouseMoved (BPoint point, uint32 transit, const BMessage *drag_msg)
{
struct haiku_mouse_motion_event rq;
+ int32 windowid;
+ EmacsWindow *window;
+
+ window = (EmacsWindow *) Window ();
+
+ if (transit == B_EXITED_VIEW)
+ rq.just_exited_p = true;
+ else
+ rq.just_exited_p = false;
- rq.just_exited_p = transit == B_EXITED_VIEW;
rq.x = point.x;
rq.y = point.y;
- rq.be_code = transit;
- rq.window = this->Window ();
+ rq.window = window;
+ rq.time = system_time ();
- if (ToolTip ())
- ToolTip ()->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x),
- -(point.y - tt_absl_pos.y)));
+ if (drag_msg && (drag_msg->IsSourceRemote ()
+ || drag_msg->FindInt32 ("emacs:window_id",
+ &windowid) != B_OK
+ || windowid != window->window_id))
+ rq.dnd_message = true;
+ else
+ rq.dnd_message = false;
- if (movement_locker.Lock ())
+ if (!grab_view_locker.Lock ())
+ gui_abort ("Couldn't lock grab view locker");
+
+ if (grab_view && this != grab_view)
{
- haiku_write (MOUSE_MOTION, &rq);
- movement_locker.Unlock ();
+ grab_view_locker.Unlock ();
+ return;
}
+
+ grab_view_locker.Unlock ();
+
+ haiku_write (MOUSE_MOTION, &rq);
}
void
- MouseDown (BPoint point)
+ BasicMouseDown (BPoint point, BView *scroll_bar)
{
struct haiku_button_event rq;
- uint32 buttons;
+ uint32 mods, buttons;
this->GetMouse (&point, &buttons, false);
+ if (!grab_view_locker.Lock ())
+ gui_abort ("Couldn't lock grab view locker");
+ if (buttons)
+ grab_view = this;
+ grab_view_locker.Unlock ();
+
rq.window = this->Window ();
- rq.btn_no = 0;
+ rq.scroll_bar = scroll_bar;
- if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON) &&
- (buttons & B_PRIMARY_MOUSE_BUTTON))
+ if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON)
+ && (buttons & B_PRIMARY_MOUSE_BUTTON))
rq.btn_no = 0;
- else if (!(previous_buttons & B_SECONDARY_MOUSE_BUTTON) &&
- (buttons & B_SECONDARY_MOUSE_BUTTON))
+ else if (!(previous_buttons & B_SECONDARY_MOUSE_BUTTON)
+ && (buttons & B_SECONDARY_MOUSE_BUTTON))
rq.btn_no = 2;
- else if (!(previous_buttons & B_TERTIARY_MOUSE_BUTTON) &&
- (buttons & B_TERTIARY_MOUSE_BUTTON))
+ else if (!(previous_buttons & B_TERTIARY_MOUSE_BUTTON)
+ && (buttons & B_TERTIARY_MOUSE_BUTTON))
rq.btn_no = 1;
+ else
+ return;
+
previous_buttons = buttons;
rq.x = point.x;
rq.y = point.y;
- uint32_t mods = modifiers ();
+ mods = modifiers ();
rq.modifiers = 0;
if (mods & B_SHIFT_KEY)
@@ -1279,21 +1880,46 @@ public:
if (mods & B_OPTION_KEY)
rq.modifiers |= HAIKU_MODIFIER_SUPER;
- SetMouseEventMask (B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+ if (!scroll_bar)
+ SetMouseEventMask (B_POINTER_EVENTS, (B_LOCK_WINDOW_FOCUS
+ | B_NO_POINTER_HISTORY));
+ rq.time = system_time ();
haiku_write (BUTTON_DOWN, &rq);
}
void
- MouseUp (BPoint point)
+ MouseDown (BPoint point)
+ {
+ BasicMouseDown (point, NULL);
+ }
+
+ void
+ BasicMouseUp (BPoint point, BView *scroll_bar)
{
struct haiku_button_event rq;
- uint32 buttons;
+ uint32 buttons, mods;
this->GetMouse (&point, &buttons, false);
+ if (!grab_view_locker.Lock ())
+ gui_abort ("Couldn't lock grab view locker");
+ if (!buttons)
+ grab_view = NULL;
+ grab_view_locker.Unlock ();
+
+ if (!buttons && wait_for_release_message)
+ {
+ wait_for_release_message->SendReply (wait_for_release_message);
+ delete wait_for_release_message;
+ wait_for_release_message = NULL;
+
+ previous_buttons = buttons;
+ return;
+ }
+
rq.window = this->Window ();
- rq.btn_no = 0;
+ rq.scroll_bar = scroll_bar;
if ((previous_buttons & B_PRIMARY_MOUSE_BUTTON)
&& !(buttons & B_PRIMARY_MOUSE_BUTTON))
@@ -1304,12 +1930,15 @@ public:
else if ((previous_buttons & B_TERTIARY_MOUSE_BUTTON)
&& !(buttons & B_TERTIARY_MOUSE_BUTTON))
rq.btn_no = 1;
+ else
+ return;
+
previous_buttons = buttons;
rq.x = point.x;
rq.y = point.y;
- uint32_t mods = modifiers ();
+ mods = modifiers ();
rq.modifiers = 0;
if (mods & B_SHIFT_KEY)
@@ -1324,56 +1953,326 @@ public:
if (mods & B_OPTION_KEY)
rq.modifiers |= HAIKU_MODIFIER_SUPER;
- if (!buttons)
- SetMouseEventMask (0, 0);
-
+ rq.time = system_time ();
haiku_write (BUTTON_UP, &rq);
}
+
+ void
+ MouseUp (BPoint point)
+ {
+ BasicMouseUp (point, NULL);
+ }
};
class EmacsScrollBar : public BScrollBar
{
public:
- void *scroll_bar;
-
- EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) :
- BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ?
- B_HORIZONTAL : B_VERTICAL)
+ int dragging;
+ bool horizontal;
+ enum haiku_scroll_bar_part current_part;
+ float old_value;
+ scroll_bar_info info;
+
+ /* True if button events should be passed to the parent. */
+ bool handle_button;
+ bool in_overscroll;
+ bool can_overscroll;
+ bool maybe_overscroll;
+ BPoint last_overscroll;
+ int last_reported_overscroll_value;
+ int max_value, real_max_value;
+ int overscroll_start_value;
+ bigtime_t repeater_start;
+ EmacsView *parent;
+
+ EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p,
+ EmacsView *parent)
+ : BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ?
+ B_HORIZONTAL : B_VERTICAL),
+ dragging (0),
+ handle_button (false),
+ in_overscroll (false),
+ can_overscroll (false),
+ maybe_overscroll (false),
+ parent (parent)
{
BView *vw = (BView *) this;
vw->SetResizingMode (B_FOLLOW_NONE);
+ horizontal = horizontal_p;
+ get_scroll_bar_info (&info);
+ SetSteps (5000, 10000);
}
void
MessageReceived (BMessage *msg)
{
+ int32 portion, range, dragging, value;
+ float proportion;
+
if (msg->what == SCROLL_BAR_UPDATE)
{
- this->SetRange (0, msg->GetInt32 ("emacs:range", 0));
- this->SetValue (msg->GetInt32 ("emacs:units", 0));
+ portion = msg->GetInt32 ("emacs:portion", 0);
+ range = msg->GetInt32 ("emacs:range", 0);
+ dragging = msg->GetInt32 ("emacs:dragging", 0);
+ proportion = ((range <= 0 || portion <= 0)
+ ? 1.0f : (float) portion / range);
+ value = msg->GetInt32 ("emacs:units", 0);
+ can_overscroll = msg->GetBool ("emacs:overscroll", false);
+
+ if (value < 0)
+ value = 0;
+
+ if (dragging != 1)
+ {
+ if (in_overscroll || dragging != -1)
+ {
+ /* Set the value to the smallest possible one.
+ Otherwise, the call to SetRange could lead to
+ spurious updates. */
+ old_value = 0;
+ SetValue (0);
+
+ /* Unlike on Motif, PORTION isn't included in the total
+ range of the scroll bar. */
+
+ SetRange (0, range - portion);
+ SetProportion (proportion);
+ max_value = range - portion;
+ real_max_value = range;
+
+ if (in_overscroll || value > max_value)
+ value = max_value;
+
+ old_value = roundf (value);
+ SetValue (old_value);
+ }
+ else
+ {
+ value = Value ();
+
+ old_value = 0;
+ SetValue (0);
+ SetRange (0, range - portion);
+ SetProportion (proportion);
+ old_value = value;
+ SetValue (value);
+ max_value = range - portion;
+ real_max_value = range;
+ }
+ }
}
BScrollBar::MessageReceived (msg);
}
void
+ Pulse (void)
+ {
+ struct haiku_scroll_bar_part_event rq;
+ BPoint point;
+ uint32 buttons;
+
+ if (!dragging)
+ {
+ SetFlags (Flags () & ~B_PULSE_NEEDED);
+ return;
+ }
+
+ if (repeater_start < system_time ())
+ {
+ GetMouse (&point, &buttons, false);
+
+ if (ButtonRegionFor (current_part).Contains (point))
+ {
+ rq.scroll_bar = this;
+ rq.window = Window ();
+ rq.part = current_part;
+ haiku_write (SCROLL_BAR_PART_EVENT, &rq);
+ }
+ }
+
+ BScrollBar::Pulse ();
+ }
+
+ void
ValueChanged (float new_value)
{
struct haiku_scroll_bar_value_event rq;
- rq.scroll_bar = scroll_bar;
- rq.position = new_value;
- haiku_write (SCROLL_BAR_VALUE_EVENT, &rq);
+ new_value = Value ();
+
+ if (dragging)
+ {
+ if (new_value != old_value)
+ {
+ if (dragging > 1)
+ {
+ SetValue (old_value);
+ SetFlags (Flags () | B_PULSE_NEEDED);
+ }
+ else
+ dragging++;
+ }
+
+ return;
+ }
+
+ if (new_value != old_value)
+ {
+ rq.scroll_bar = this;
+ rq.window = Window ();
+ rq.position = new_value;
+ old_value = new_value;
+
+ haiku_write (SCROLL_BAR_VALUE_EVENT, &rq);
+ }
+ }
+
+ BRegion
+ ButtonRegionFor (enum haiku_scroll_bar_part button)
+ {
+ BRegion region;
+ BRect bounds;
+ BRect rect;
+ float button_size;
+
+ bounds = Bounds ();
+ bounds.InsetBy (0.0, 0.0);
+
+ if (horizontal)
+ button_size = bounds.Height () + 1.0f;
+ else
+ button_size = bounds.Width () + 1.0f;
+
+ rect = BRect (bounds.left, bounds.top,
+ bounds.left + button_size - 1.0f,
+ bounds.top + button_size - 1.0f);
+
+ if (button == HAIKU_SCROLL_BAR_UP_BUTTON)
+ {
+ if (!horizontal)
+ {
+ region.Include (rect);
+ if (info.double_arrows)
+ region.Include (rect.OffsetToCopy (bounds.left,
+ bounds.bottom - 2 * button_size + 1));
+ }
+ else
+ {
+ region.Include (rect);
+ if (info.double_arrows)
+ region.Include (rect.OffsetToCopy (bounds.right - 2 * button_size,
+ bounds.top));
+ }
+ }
+ else
+ {
+ if (!horizontal)
+ {
+ region.Include (rect.OffsetToCopy (bounds.left, bounds.bottom - button_size));
+
+ if (info.double_arrows)
+ region.Include (rect.OffsetByCopy (0.0, button_size));
+ }
+ else
+ {
+ region.Include (rect.OffsetToCopy (bounds.right - button_size, bounds.top));
+
+ if (info.double_arrows)
+ region.Include (rect.OffsetByCopy (button_size, 0.0));
+ }
+ }
+
+ return region;
}
void
MouseDown (BPoint pt)
{
struct haiku_scroll_bar_drag_event rq;
+ struct haiku_scroll_bar_part_event part;
+ BRegion r;
+ BLooper *looper;
+ BMessage *message;
+ int32 buttons, mods;
+
+ looper = Looper ();
+ message = NULL;
+
+ if (!looper)
+ GetMouse (&pt, (uint32 *) &buttons, false);
+ else
+ {
+ message = looper->CurrentMessage ();
+
+ if (!message || message->FindInt32 ("buttons", &buttons) != B_OK)
+ GetMouse (&pt, (uint32 *) &buttons, false);
+ }
+
+ if (message && (message->FindInt32 ("modifiers", &mods)
+ == B_OK)
+ && mods & B_CONTROL_KEY)
+ {
+ /* Allow C-mouse-3 to split the window on a scroll bar. */
+ handle_button = true;
+ SetMouseEventMask (B_POINTER_EVENTS, (B_SUSPEND_VIEW_FOCUS
+ | B_LOCK_WINDOW_FOCUS));
+ parent->BasicMouseDown (ConvertToParent (pt), this);
+
+ return;
+ }
+
+ repeater_start = system_time () + 300000;
+
+ if (buttons == B_PRIMARY_MOUSE_BUTTON)
+ {
+ r = ButtonRegionFor (HAIKU_SCROLL_BAR_UP_BUTTON);
+
+ if (r.Contains (pt))
+ {
+ part.scroll_bar = this;
+ part.window = Window ();
+ part.part = HAIKU_SCROLL_BAR_UP_BUTTON;
+ dragging = 1;
+ current_part = HAIKU_SCROLL_BAR_UP_BUTTON;
+
+ haiku_write (SCROLL_BAR_PART_EVENT, &part);
+ goto out;
+ }
+
+ r = ButtonRegionFor (HAIKU_SCROLL_BAR_DOWN_BUTTON);
+
+ if (r.Contains (pt))
+ {
+ part.scroll_bar = this;
+ part.window = Window ();
+ part.part = HAIKU_SCROLL_BAR_DOWN_BUTTON;
+ dragging = 1;
+ current_part = HAIKU_SCROLL_BAR_DOWN_BUTTON;
+
+ if (Value () == max_value)
+ {
+ SetFlags (Flags () | B_PULSE_NEEDED);
+ dragging = 2;
+ }
+
+ haiku_write (SCROLL_BAR_PART_EVENT, &part);
+ goto out;
+ }
+
+ maybe_overscroll = true;
+ }
+
rq.dragging_p = 1;
- rq.scroll_bar = scroll_bar;
+ rq.window = Window ();
+ rq.scroll_bar = this;
+
+ SetMouseEventMask (B_POINTER_EVENTS, (B_SUSPEND_VIEW_FOCUS
+ | B_LOCK_WINDOW_FOCUS));
haiku_write (SCROLL_BAR_DRAG_EVENT, &rq);
+
+ out:
BScrollBar::MouseDown (pt);
}
@@ -1381,12 +2280,119 @@ public:
MouseUp (BPoint pt)
{
struct haiku_scroll_bar_drag_event rq;
+
+ in_overscroll = false;
+ maybe_overscroll = false;
+
+ if (handle_button)
+ {
+ handle_button = false;
+ parent->BasicMouseUp (ConvertToParent (pt), this);
+
+ return;
+ }
+
rq.dragging_p = 0;
- rq.scroll_bar = scroll_bar;
+ rq.scroll_bar = this;
+ rq.window = Window ();
haiku_write (SCROLL_BAR_DRAG_EVENT, &rq);
+ dragging = 0;
+
BScrollBar::MouseUp (pt);
}
+
+ void
+ MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
+ {
+ struct haiku_menu_bar_left_event rq;
+ struct haiku_scroll_bar_value_event value_event;
+ int range, diff, value, trough_size;
+ BRect bounds;
+ BPoint conv;
+ uint32 buttons;
+
+ GetMouse (NULL, &buttons, false);
+
+ if (transit == B_EXITED_VIEW)
+ {
+ conv = ConvertToParent (point);
+
+ rq.x = std::lrint (conv.x);
+ rq.y = std::lrint (conv.y);
+ rq.window = this->Window ();
+
+ haiku_write (MENU_BAR_LEFT, &rq);
+ }
+
+ if (in_overscroll)
+ {
+ if (horizontal)
+ diff = point.x - last_overscroll.x;
+ else
+ diff = point.y - last_overscroll.y;
+
+ if (diff < 0)
+ {
+ in_overscroll = false;
+ goto allow;
+ }
+
+ range = real_max_value;
+ bounds = Bounds ();
+ bounds.InsetBy (1.0, 1.0);
+ value = overscroll_start_value;
+ trough_size = (horizontal
+ ? BE_RECT_WIDTH (bounds)
+ : BE_RECT_HEIGHT (bounds));
+ trough_size -= (horizontal
+ ? BE_RECT_HEIGHT (bounds)
+ : BE_RECT_WIDTH (bounds)) / 2;
+ if (info.double_arrows)
+ trough_size -= (horizontal
+ ? BE_RECT_HEIGHT (bounds)
+ : BE_RECT_WIDTH (bounds)) / 2;
+
+ value += ((double) range / trough_size) * diff;
+
+ if (value != last_reported_overscroll_value)
+ {
+ last_reported_overscroll_value = value;
+
+ value_event.scroll_bar = this;
+ value_event.window = Window ();
+ value_event.position = value;
+
+ haiku_write (SCROLL_BAR_VALUE_EVENT, &value_event);
+ return;
+ }
+ }
+ else if (can_overscroll
+ && (buttons == B_PRIMARY_MOUSE_BUTTON)
+ && maybe_overscroll)
+ {
+ value = Value ();
+
+ if (value >= max_value)
+ {
+ BScrollBar::MouseMoved (point, transit, msg);
+
+ if (value == Value ())
+ {
+ overscroll_start_value = value;
+ in_overscroll = true;
+ last_overscroll = point;
+ last_reported_overscroll_value = value;
+
+ MouseMoved (point, transit, msg);
+ return;
+ }
+ }
+ }
+
+ allow:
+ BScrollBar::MouseMoved (point, transit, msg);
+ }
};
class EmacsTitleMenuItem : public BMenuItem
@@ -1404,7 +2410,7 @@ public:
menu->PushState ();
menu->SetFont (be_bold_font);
- BView_SetHighColorForVisibleBell (menu, 0);
+ menu->SetHighColor (ui_color (B_MENU_ITEM_TEXT_COLOR));
BMenuItem::DrawContent ();
menu->PopState ();
}
@@ -1413,29 +2419,26 @@ public:
class EmacsMenuItem : public BMenuItem
{
public:
- int menu_bar_id = -1;
- void *wind_ptr = NULL;
- char *key = NULL;
- char *help = NULL;
-
- EmacsMenuItem (const char *ky,
- const char *str,
- const char *help,
- BMessage *message = NULL) : BMenuItem (str, message)
+ int menu_bar_id;
+ void *menu_ptr;
+ void *wind_ptr;
+ char *key;
+ char *help;
+
+ EmacsMenuItem (const char *key_label, const char *label,
+ const char *help, BMessage *message = NULL)
+ : BMenuItem (label, message),
+ menu_bar_id (-1),
+ menu_ptr (NULL),
+ wind_ptr (NULL),
+ key (NULL),
+ help (NULL)
{
- if (ky)
- {
- key = strdup (ky);
- if (!key)
- gui_abort ("strdup failed");
- }
+ if (key_label)
+ key = strdup (key_label);
if (help)
- {
- this->help = strdup (help);
- if (!this->help)
- gui_abort ("strdup failed");
- }
+ this->help = strdup (help);
}
~EmacsMenuItem ()
@@ -1455,11 +2458,17 @@ public:
if (key)
{
- BRect r = menu->Frame ();
- int w = menu->StringWidth (key);
+ BRect r = Frame ();
+ int w;
+
+ menu->PushState ();
+ menu->ClipToRect (r);
+ menu->SetFont (be_plain_font);
+ w = menu->StringWidth (key);
menu->MovePenTo (BPoint (BE_RECT_WIDTH (r) - w - 4,
menu->PenLocation ().y));
menu->DrawString (key);
+ menu->PopState ();
}
}
@@ -1475,49 +2484,837 @@ public:
Highlight (bool highlight_p)
{
struct haiku_menu_bar_help_event rq;
+ struct haiku_dummy_event dummy;
+ BMenu *menu = Menu ();
+ BRect r;
+ BPoint pt;
+ uint32 buttons;
- if (menu_bar_id >= 0)
+ if (help)
+ menu->SetToolTip (highlight_p ? help : NULL);
+ else
{
rq.window = wind_ptr;
rq.mb_idx = highlight_p ? menu_bar_id : -1;
+ rq.highlight_p = highlight_p;
+ rq.data = menu_ptr;
+
+ r = Frame ();
+ menu->GetMouse (&pt, &buttons);
- haiku_write (MENU_BAR_HELP_EVENT, &rq);
+ if (!highlight_p || r.Contains (pt))
+ {
+ if (menu_bar_id > 0)
+ haiku_write (MENU_BAR_HELP_EVENT, &rq);
+ else
+ {
+ haiku_write_without_signal (MENU_BAR_HELP_EVENT, &rq, true);
+ haiku_write (DUMMY_EVENT, &dummy);
+ }
+ }
}
- else if (help)
+
+ BMenuItem::Highlight (highlight_p);
+ }
+};
+
+class EmacsFontPreviewDialog : public BWindow
+{
+ BStringView text_view;
+ BMessenger preview_source;
+ BFont *current_font;
+ bool is_visible;
+
+ void
+ DoLayout (void)
+ {
+ float width, height;
+
+ text_view.GetPreferredSize (&width, &height);
+ text_view.ResizeTo (width - 1, height - 1);
+
+ SetSizeLimits (width, width, height, height);
+ ResizeTo (width - 1, height - 1);
+ }
+
+ bool
+ QuitRequested (void)
+ {
+ preview_source.SendMessage (QUIT_PREVIEW_DIALOG);
+
+ return false;
+ }
+
+ void
+ MessageReceived (BMessage *message)
+ {
+ int32 family, style;
+ uint32 flags;
+ font_family name;
+ font_style sname;
+ status_t rc;
+ const char *size_name;
+ int size;
+
+ if (message->what == SET_FONT_INDICES)
{
- Menu ()->SetToolTip (highlight_p ? help : NULL);
+ size_name = message->FindString ("emacs:size");
+
+ if (message->FindInt32 ("emacs:family", &family) != B_OK
+ || message->FindInt32 ("emacs:style", &style) != B_OK)
+ return;
+
+ rc = get_font_family (family, &name, &flags);
+
+ if (rc != B_OK)
+ return;
+
+ rc = get_font_style (name, style, &sname, &flags);
+
+ if (rc != B_OK)
+ return;
+
+ if (current_font)
+ delete current_font;
+
+ current_font = new BFont;
+ current_font->SetFamilyAndStyle (name, sname);
+
+ if (message->GetBool ("emacs:disable_antialiasing", false))
+ current_font->SetFlags (B_DISABLE_ANTIALIASING);
+
+ if (size_name && strlen (size_name))
+ {
+ size = atoi (size_name);
+ current_font->SetSize (size);
+ }
+
+ text_view.SetFont (current_font);
+ DoLayout ();
+ return;
}
- BMenuItem::Highlight (highlight_p);
+ BWindow::MessageReceived (message);
+ }
+
+public:
+
+ EmacsFontPreviewDialog (BWindow *target)
+ : BWindow (BRect (45, 45, 500, 300),
+ "Preview font",
+ B_FLOATING_WINDOW_LOOK,
+ B_MODAL_APP_WINDOW_FEEL,
+ B_NOT_ZOOMABLE | B_NOT_RESIZABLE),
+ text_view (BRect (0, 0, 0, 0),
+ NULL, "The quick brown fox "
+ "jumped over the lazy dog"),
+ preview_source (target),
+ current_font (NULL)
+ {
+ AddChild (&text_view);
+ DoLayout ();
+ }
+
+ ~EmacsFontPreviewDialog (void)
+ {
+ text_view.RemoveSelf ();
+
+ if (current_font)
+ delete current_font;
}
};
-class EmacsPopUpMenu : public BPopUpMenu
+class TripleLayoutView : public BView
{
+ BScrollView *view_1;
+ BView *view_2, *view_3;
+
+ void
+ FrameResized (float new_width, float new_height)
+ {
+ BRect frame;
+ float width, height, height_1, width_1;
+ float basic_height;
+
+ frame = Frame ();
+
+ view_2->GetPreferredSize (&width, &height);
+ view_3->GetPreferredSize (&width_1, &height_1);
+
+ basic_height = height + height_1;
+
+ view_1->MoveTo (0, 0);
+ view_1->ResizeTo (BE_RECT_WIDTH (frame),
+ BE_RECT_HEIGHT (frame) - basic_height);
+ view_2->MoveTo (2, BE_RECT_HEIGHT (frame) - basic_height);
+ view_2->ResizeTo (BE_RECT_WIDTH (frame) - 4, height);
+ view_3->MoveTo (2, BE_RECT_HEIGHT (frame) - height_1);
+ view_3->ResizeTo (BE_RECT_WIDTH (frame) - 4, height_1);
+
+ BView::FrameResized (new_width, new_height);
+ }
+
+ /* This is called by the BSplitView. */
+ BSize
+ MinSize (void)
+ {
+ float width, height;
+ float width_1, height_1;
+ BSize size_1;
+
+ size_1 = view_1->MinSize ();
+ view_2->GetPreferredSize (&width, &height);
+ view_3->GetPreferredSize (&width_1, &height_1);
+
+ return BSize (std::max (size_1.width,
+ std::max (width_1, width)),
+ std::max (size_1.height, height + height_1));
+ }
+
public:
- EmacsPopUpMenu (const char *name) : BPopUpMenu (name, 0)
+ TripleLayoutView (BScrollView *first, BView *second,
+ BView *third) : BView (NULL, B_FRAME_EVENTS),
+ view_1 (first),
+ view_2 (second),
+ view_3 (third)
+ {
+ FrameResized (801, 801);
+ }
+};
+
+class EmacsFontSelectionDialog : public BWindow
+{
+ BView basic_view;
+ BCheckBox antialias_checkbox;
+ BCheckBox preview_checkbox;
+ BSplitView split_view;
+ BListView font_family_pane;
+ BListView font_style_pane;
+ BScrollView font_family_scroller;
+ BScrollView font_style_scroller;
+ TripleLayoutView style_view;
+ BObjectList<BStringItem> all_families;
+ BObjectList<BStringItem> all_styles;
+ BButton cancel_button, ok_button;
+ BTextControl size_entry;
+ port_id comm_port;
+ bool allow_monospace_only;
+ int pending_selection_idx;
+ EmacsFontPreviewDialog *preview;
+
+ void
+ ShowPreview (void)
{
+ if (!preview)
+ {
+ preview = new EmacsFontPreviewDialog (this);
+ preview->Show ();
+ UpdatePreview ();
+ }
}
void
- FrameResized (float w, float h)
+ UpdatePreview (void)
{
- Invalidate ();
- BPopUpMenu::FrameResized (w, h);
+ int family, style;
+ BMessage message;
+ BMessenger messenger (preview);
+
+ family = font_family_pane.CurrentSelection ();
+ style = font_style_pane.CurrentSelection ();
+
+ message.what = SET_FONT_INDICES;
+ message.AddInt32 ("emacs:family", family);
+ message.AddInt32 ("emacs:style", style);
+
+ if (antialias_checkbox.Value () == B_CONTROL_ON)
+ message.AddBool ("emacs:disable_antialiasing", true);
+
+ message.AddString ("emacs:size",
+ size_entry.Text ());
+
+ messenger.SendMessage (&message);
+ }
+
+ void
+ HidePreview (void)
+ {
+ if (preview)
+ {
+ if (preview->LockLooper ())
+ preview->Quit ();
+ /* I hope this works. */
+ else
+ delete preview;
+
+ preview = NULL;
+ }
+ }
+
+ void
+ UpdateStylesForIndex (int idx)
+ {
+ int n, i, previous_selection;
+ uint32 flags;
+ font_family family;
+ font_style style;
+ BStringItem *item;
+ char *current_style;
+
+ n = all_styles.CountItems ();
+ current_style = NULL;
+ previous_selection = font_style_pane.CurrentSelection ();
+
+ if (previous_selection >= 0)
+ {
+ item = all_styles.ItemAt (previous_selection);
+ current_style = strdup (item->Text ());
+ }
+
+ font_style_pane.MakeEmpty ();
+ all_styles.MakeEmpty ();
+
+ if (get_font_family (idx, &family, &flags) == B_OK)
+ {
+ n = count_font_styles (family);
+
+ for (i = 0; i < n; ++i)
+ {
+ if (get_font_style (family, i, &style, &flags) == B_OK)
+ item = new BStringItem (style);
+ else
+ item = new BStringItem ("<error>");
+
+ if (current_style && pending_selection_idx < 0
+ && !strcmp (current_style, style))
+ pending_selection_idx = i;
+
+ font_style_pane.AddItem (item);
+ all_styles.AddItem (item);
+ }
+ }
+
+ if (pending_selection_idx >= 0)
+ {
+ font_style_pane.Select (pending_selection_idx);
+ font_style_pane.ScrollToSelection ();
+ }
+
+ pending_selection_idx = -1;
+ UpdateForSelectedStyle ();
+
+ if (current_style)
+ free (current_style);
+ }
+
+ bool
+ QuitRequested (void)
+ {
+ struct font_selection_dialog_message rq;
+
+ rq.cancel = true;
+ write_port (comm_port, 0, &rq, sizeof rq);
+
+ return false;
+ }
+
+ void
+ UpdateForSelectedStyle (void)
+ {
+ int style = font_style_pane.CurrentSelection ();
+
+ if (style < 0)
+ ok_button.SetEnabled (false);
+ else
+ ok_button.SetEnabled (true);
+
+ if (style >= 0 && preview)
+ UpdatePreview ();
+ }
+
+ void
+ MessageReceived (BMessage *msg)
+ {
+ const char *text;
+ int idx;
+ struct font_selection_dialog_message rq;
+
+ if (msg->what == FONT_FAMILY_SELECTED)
+ {
+ idx = font_family_pane.CurrentSelection ();
+ UpdateStylesForIndex (idx);
+ }
+ else if (msg->what == FONT_STYLE_SELECTED)
+ UpdateForSelectedStyle ();
+ else if (msg->what == B_OK
+ && font_style_pane.CurrentSelection () >= 0)
+ {
+ text = size_entry.Text ();
+
+ rq.cancel = false;
+ rq.family_idx = font_family_pane.CurrentSelection ();
+ rq.style_idx = font_style_pane.CurrentSelection ();
+ rq.size = atoi (text);
+ rq.size_specified = rq.size > 0 || strlen (text);
+
+ if (antialias_checkbox.Value () == B_CONTROL_ON)
+ rq.disable_antialias = true;
+ else
+ rq.disable_antialias = false;
+
+ write_port (comm_port, 0, &rq, sizeof rq);
+ }
+ else if (msg->what == B_CANCEL)
+ {
+ rq.cancel = true;
+
+ write_port (comm_port, 0, &rq, sizeof rq);
+ }
+ else if (msg->what == SET_PREVIEW_DIALOG)
+ {
+ if (preview_checkbox.Value () == B_CONTROL_OFF)
+ HidePreview ();
+ else
+ ShowPreview ();
+ }
+ else if (msg->what == QUIT_PREVIEW_DIALOG)
+ {
+ preview_checkbox.SetValue (B_CONTROL_OFF);
+ HidePreview ();
+ }
+ else if (msg->what == UPDATE_PREVIEW_DIALOG)
+ {
+ if (preview)
+ UpdatePreview ();
+ }
+ else if (msg->what == SET_DISABLE_ANTIALIASING)
+ {
+ if (preview)
+ UpdatePreview ();
+ }
+
+ BWindow::MessageReceived (msg);
+ }
+
+public:
+
+ ~EmacsFontSelectionDialog (void)
+ {
+ if (preview)
+ {
+ if (preview->LockLooper ())
+ preview->Quit ();
+ /* I hope this works. */
+ else
+ delete preview;
+ }
+
+ font_family_pane.MakeEmpty ();
+ font_style_pane.MakeEmpty ();
+
+ font_family_pane.RemoveSelf ();
+ font_style_pane.RemoveSelf ();
+ antialias_checkbox.RemoveSelf ();
+ preview_checkbox.RemoveSelf ();
+ style_view.RemoveSelf ();
+ font_family_scroller.RemoveSelf ();
+ font_style_scroller.RemoveSelf ();
+ cancel_button.RemoveSelf ();
+ ok_button.RemoveSelf ();
+ size_entry.RemoveSelf ();
+ basic_view.RemoveSelf ();
+
+ if (comm_port >= B_OK)
+ delete_port (comm_port);
+ }
+
+ EmacsFontSelectionDialog (bool monospace_only,
+ int initial_family_idx,
+ int initial_style_idx,
+ int initial_size,
+ bool initial_antialias)
+ : BWindow (BRect (0, 0, 500, 500),
+ "Select font from list",
+ B_TITLED_WINDOW_LOOK,
+ B_MODAL_APP_WINDOW_FEEL, 0),
+ basic_view (NULL, 0),
+ antialias_checkbox ("Disable antialiasing", "Disable antialiasing",
+ new BMessage (SET_DISABLE_ANTIALIASING)),
+ preview_checkbox ("Show preview", "Show preview",
+ new BMessage (SET_PREVIEW_DIALOG)),
+ font_family_pane (BRect (0, 0, 0, 0), NULL,
+ B_SINGLE_SELECTION_LIST,
+ B_FOLLOW_ALL_SIDES),
+ font_style_pane (BRect (0, 0, 0, 0), NULL,
+ B_SINGLE_SELECTION_LIST,
+ B_FOLLOW_ALL_SIDES),
+ font_family_scroller (NULL, &font_family_pane,
+ B_FOLLOW_LEFT | B_FOLLOW_TOP,
+ 0, false, true),
+ font_style_scroller (NULL, &font_style_pane,
+ B_FOLLOW_ALL_SIDES,
+ B_SUPPORTS_LAYOUT, false, true),
+ style_view (&font_style_scroller, &antialias_checkbox,
+ &preview_checkbox),
+ all_families (20, true),
+ all_styles (20, true),
+ cancel_button ("Cancel", "Cancel",
+ new BMessage (B_CANCEL)),
+ ok_button ("OK", "OK", new BMessage (B_OK)),
+ size_entry (NULL, "Size:", NULL,
+ new BMessage (UPDATE_PREVIEW_DIALOG)),
+ allow_monospace_only (monospace_only),
+ pending_selection_idx (initial_style_idx),
+ preview (NULL)
+ {
+ BStringItem *family_item;
+ int i, n_families;
+ font_family name;
+ uint32 flags, c;
+ BMessage *selection;
+ BTextView *size_text;
+ char format_buffer[4];
+
+ AddChild (&basic_view);
+
+ basic_view.AddChild (&split_view);
+ basic_view.AddChild (&cancel_button);
+ basic_view.AddChild (&ok_button);
+ basic_view.AddChild (&size_entry);
+ split_view.AddChild (&font_family_scroller, 0.7);
+ split_view.AddChild (&style_view, 0.3);
+ style_view.AddChild (&font_style_scroller);
+ style_view.AddChild (&antialias_checkbox);
+ style_view.AddChild (&preview_checkbox);
+
+ basic_view.SetViewUIColor (B_PANEL_BACKGROUND_COLOR);
+ style_view.SetViewUIColor (B_PANEL_BACKGROUND_COLOR);
+
+ FrameResized (801, 801);
+ UpdateForSelectedStyle ();
+
+ selection = new BMessage (FONT_FAMILY_SELECTED);
+ font_family_pane.SetSelectionMessage (selection);
+ selection = new BMessage (FONT_STYLE_SELECTED);
+ font_style_pane.SetSelectionMessage (selection);
+ selection = new BMessage (B_OK);
+ font_style_pane.SetInvocationMessage (selection);
+ selection = new BMessage (UPDATE_PREVIEW_DIALOG);
+ size_entry.SetModificationMessage (selection);
+
+ comm_port = create_port (1, "font dialog port");
+
+ n_families = count_font_families ();
+
+ for (i = 0; i < n_families; ++i)
+ {
+ if (get_font_family (i, &name, &flags) == B_OK)
+ {
+ family_item = new BStringItem (name);
+
+ all_families.AddItem (family_item);
+ font_family_pane.AddItem (family_item);
+
+ family_item->SetEnabled (!allow_monospace_only
+ || flags & B_IS_FIXED);
+ }
+ else
+ {
+ family_item = new BStringItem ("<error>");
+
+ all_families.AddItem (family_item);
+ font_family_pane.AddItem (family_item);
+ }
+ }
+
+ if (initial_family_idx >= 0)
+ {
+ font_family_pane.Select (initial_family_idx);
+ font_family_pane.ScrollToSelection ();
+ }
+
+ size_text = size_entry.TextView ();
+
+ for (c = 0; c <= 47; ++c)
+ size_text->DisallowChar (c);
+
+ for (c = 58; c <= 127; ++c)
+ size_text->DisallowChar (c);
+
+ if (initial_size > 0 && initial_size < 1000)
+ {
+ sprintf (format_buffer, "%d", initial_size);
+ size_entry.SetText (format_buffer);
+ }
+
+ if (!initial_antialias)
+ antialias_checkbox.SetValue (B_CONTROL_ON);
+ }
+
+ void
+ FrameResized (float new_width, float new_height)
+ {
+ BRect frame;
+ float ok_height, ok_width;
+ float cancel_height, cancel_width;
+ float size_width, size_height;
+ float bone;
+ int max_height;
+
+ ok_button.GetPreferredSize (&ok_width, &ok_height);
+ cancel_button.GetPreferredSize (&cancel_width,
+ &cancel_height);
+ size_entry.GetPreferredSize (&size_width, &size_height);
+
+ max_height = std::max (std::max (ok_height, cancel_height),
+ size_height);
+
+ SetSizeLimits (cancel_width + ok_width + size_width + 6,
+ 65535, max_height + 64, 65535);
+ frame = Frame ();
+
+ basic_view.ResizeTo (BE_RECT_WIDTH (frame), BE_RECT_HEIGHT (frame));
+ split_view.ResizeTo (BE_RECT_WIDTH (frame) - 1,
+ BE_RECT_HEIGHT (frame) - 4 - max_height);
+
+ bone = BE_RECT_HEIGHT (frame) - 2 - max_height / 2;
+
+ ok_button.MoveTo ((BE_RECT_WIDTH (frame)
+ - 4 - cancel_width - ok_width),
+ bone - ok_height / 2);
+ cancel_button.MoveTo (BE_RECT_WIDTH (frame) - 2 - cancel_width,
+ bone - cancel_height / 2);
+ size_entry.MoveTo (2, bone - size_height / 2);
+
+ ok_button.ResizeTo (ok_width, ok_height);
+ cancel_button.ResizeTo (cancel_width, cancel_height);
+ size_entry.ResizeTo (std::max (size_width,
+ BE_RECT_WIDTH (frame) / 4),
+ size_height);
+ }
+
+ void
+ WaitForChoice (struct font_selection_dialog_message *msg,
+ void (*process_pending_signals_function) (void),
+ bool (*should_quit_function) (void))
+ {
+ int32 reply_type;
+ struct object_wait_info infos[2];
+ ssize_t status;
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = comm_port;
+ infos[1].type = B_OBJECT_TYPE_PORT;
+ infos[1].events = B_EVENT_READ;
+
+ while (true)
+ {
+ status = wait_for_objects (infos, 2);
+
+ if (status < B_OK)
+ continue;
+
+ if (infos[1].events & B_EVENT_READ)
+ {
+ if (read_port (comm_port, &reply_type,
+ msg, sizeof *msg) >= B_OK)
+ return;
+
+ goto cancel;
+ }
+
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
+
+ if (should_quit_function ())
+ goto cancel;
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_READ;
+ }
+
+ cancel:
+ msg->cancel = true;
+ return;
+ }
+
+ status_t
+ InitCheck (void)
+ {
+ return comm_port >= B_OK ? B_OK : comm_port;
+ }
+};
+
+class EmacsFilePanelCallbackLooper : public BLooper
+{
+ port_id comm_port;
+
+ void
+ MessageReceived (BMessage *msg)
+ {
+ const char *str_path, *name;
+ char *file_name, *str_buf;
+ BEntry entry;
+ BPath path;
+ entry_ref ref;
+ int32 old_what;
+
+ if (msg->what == FILE_PANEL_SELECTION
+ || ((msg->FindInt32 ("old_what", &old_what) == B_OK
+ && old_what == FILE_PANEL_SELECTION)))
+ {
+ file_name = NULL;
+
+ if (msg->FindRef ("refs", &ref) == B_OK
+ && entry.SetTo (&ref, 0) == B_OK
+ && entry.GetPath (&path) == B_OK)
+ {
+ str_path = path.Path ();
+
+ if (str_path)
+ file_name = strdup (str_path);
+ }
+ else if (msg->FindRef ("directory", &ref) == B_OK
+ && entry.SetTo (&ref, 0) == B_OK
+ && entry.GetPath (&path) == B_OK)
+ {
+ name = msg->GetString ("name");
+ str_path = path.Path ();
+
+ if (name)
+ {
+ str_buf = (char *) alloca (std::strlen (str_path)
+ + std::strlen (name) + 2);
+ snprintf (str_buf, std::strlen (str_path)
+ + std::strlen (name) + 2, "%s/%s",
+ str_path, name);
+ file_name = strdup (str_buf);
+ }
+ }
+
+ write_port (comm_port, 0, &file_name, sizeof file_name);
+ }
+
+ BLooper::MessageReceived (msg);
+ }
+
+public:
+ EmacsFilePanelCallbackLooper (void) : BLooper ()
+ {
+ comm_port = create_port (1, "file panel port");
+ }
+
+ ~EmacsFilePanelCallbackLooper (void)
+ {
+ delete_port (comm_port);
+ }
+
+ char *
+ ReadFileName (void (*process_pending_signals_function) (void))
+ {
+ object_wait_info infos[2];
+ ssize_t status;
+ int32 reply_type;
+ char *file_name;
+
+ file_name = NULL;
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = comm_port;
+ infos[1].type = B_OBJECT_TYPE_PORT;
+ infos[1].events = B_EVENT_READ;
+
+ while (true)
+ {
+ status = wait_for_objects (infos, 2);
+
+ if (status == B_INTERRUPTED || status == B_WOULD_BLOCK)
+ continue;
+
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
+
+ if (infos[1].events & B_EVENT_READ)
+ {
+ status = read_port (comm_port,
+ &reply_type, &file_name,
+ sizeof file_name);
+
+ if (status < B_OK)
+ file_name = NULL;
+
+ goto out;
+ }
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_READ;
+ }
+
+ out:
+ return file_name;
+ }
+
+ status_t
+ InitCheck (void)
+ {
+ return comm_port >= B_OK ? B_OK : comm_port;
+ }
+};
+
+/* A view that is added as a child of a tooltip's text view, and
+ prevents motion events from reaching it (thereby moving the
+ tooltip). */
+class EmacsMotionSuppressionView : public BView
+{
+ void
+ AttachedToWindow (void)
+ {
+ BView *text_view, *tooltip_view;
+
+ /* We know that this view is a child of the text view, whose
+ parent is the tooltip view, and that the tooltip view has
+ already set its mouse event mask. */
+
+ text_view = Parent ();
+
+ if (!text_view)
+ return;
+
+ tooltip_view = text_view->Parent ();
+
+ if (!tooltip_view)
+ return;
+
+ tooltip_view->SetEventMask (B_KEYBOARD_EVENTS, 0);
+ }
+
+public:
+ EmacsMotionSuppressionView (void) : BView (BRect (-1, -1, 1, 1),
+ NULL, 0, 0)
+ {
+ return;
}
};
static int32
start_running_application (void *data)
{
+ Emacs *app = (Emacs *) data;
+
haiku_io_init_in_app_thread ();
- if (!((Emacs *) data)->Lock ())
+ if (!app->Lock ())
gui_abort ("Failed to lock application");
- ((Emacs *) data)->Run ();
- ((Emacs *) data)->Unlock ();
+ app->Run ();
+ app->Unlock ();
return 0;
}
@@ -1587,44 +3384,58 @@ BBitmap_dimensions (void *bitmap, int *left, int *top,
*mono_p = (((BBitmap *) bitmap)->ColorSpace () == B_GRAY1);
}
+static void
+wait_for_exit_of_app_thread (void)
+{
+ status_t ret;
+
+ be_app->PostMessage (QUIT_APPLICATION);
+ wait_for_thread (app_thread, &ret);
+}
+
/* Set up an application and return it. If starting the application
thread fails, abort Emacs. */
void *
BApplication_setup (void)
{
- if (be_app)
- return be_app;
thread_id id;
Emacs *app;
+ if (be_app)
+ return be_app;
+
app = new Emacs;
app->Unlock ();
+
if ((id = spawn_thread (start_running_application, "Emacs app thread",
B_DEFAULT_MEDIA_PRIORITY, app)) < 0)
gui_abort ("spawn_thread failed");
resume_thread (id);
-
app_thread = id;
+
+ atexit (wait_for_exit_of_app_thread);
return app;
}
/* Set up and return a window with its view put in VIEW. */
void *
-BWindow_new (void *_view)
+BWindow_new (void **view)
{
- BWindow *window = new (std::nothrow) EmacsWindow;
- BView **v = (BView **) _view;
+ BWindow *window;
+ BView *vw;
+
+ window = new (std::nothrow) EmacsWindow;
if (!window)
{
- *v = NULL;
+ *view = NULL;
return window;
}
- BView *vw = new (std::nothrow) EmacsView;
+ vw = new (std::nothrow) EmacsView;
if (!vw)
{
- *v = NULL;
+ *view = NULL;
window->LockLooper ();
window->Quit ();
return NULL;
@@ -1638,15 +3449,17 @@ BWindow_new (void *_view)
the first time. */
window->UnlockLooper ();
window->AddChild (vw);
- *v = vw;
+ *view = vw;
return window;
}
void
BWindow_quit (void *window)
{
- ((BWindow *) window)->LockLooper ();
- ((BWindow *) window)->Quit ();
+ BWindow *w = (BWindow *) window;
+
+ w->LockLooper ();
+ w->Quit ();
}
/* Set WINDOW's offset to X, Y. */
@@ -1666,6 +3479,16 @@ BWindow_set_offset (void *window, int x, int y)
wn->MoveTo (x, y);
}
+void
+BWindow_dimensions (void *window, int *width, int *height)
+{
+ BWindow *w = (BWindow *) window;
+ BRect frame = w->Frame ();
+
+ *width = BE_RECT_WIDTH (frame);
+ *height = BE_RECT_HEIGHT (frame);
+}
+
/* Iconify WINDOW. */
void
BWindow_iconify (void *window)
@@ -1705,7 +3528,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
@@ -1719,15 +3542,18 @@ BWindow_activate (void *window)
/* Return the pixel dimensions of the main screen in WIDTH and
HEIGHT. */
void
-BScreen_px_dim (int *width, int *height)
+be_get_screen_dimensions (int *width, int *height)
{
BScreen screen;
+ BRect frame;
+
if (!screen.IsValid ())
gui_abort ("Invalid screen");
- BRect frame = screen.Frame ();
- *width = frame.right - frame.left;
- *height = frame.bottom - frame.top;
+ frame = screen.Frame ();
+
+ *width = BE_RECT_WIDTH (frame);
+ *height = BE_RECT_HEIGHT (frame);
}
/* Resize VIEW to WIDTH, HEIGHT. */
@@ -1742,55 +3568,28 @@ BView_resize_to (void *view, int width, int height)
vw->UnlockLooper ();
}
-void *
-BCursor_create_default (void)
-{
- return new BCursor (B_CURSOR_ID_SYSTEM_DEFAULT);
-}
-
-void *
-BCursor_create_modeline (void)
-{
- return new BCursor (B_CURSOR_ID_CONTEXT_MENU);
-}
-
-void *
-BCursor_from_id (enum haiku_cursor cursor)
-{
- return new BCursor ((enum BCursorID) cursor);
-}
-
-void *
-BCursor_create_i_beam (void)
-{
- return new BCursor (B_CURSOR_ID_I_BEAM);
-}
-
-void *
-BCursor_create_progress_cursor (void)
+void
+be_delete_cursor (void *cursor)
{
- return new BCursor (B_CURSOR_ID_PROGRESS);
+ if (cursor)
+ delete (BCursor *) cursor;
}
void *
-BCursor_create_grab (void)
-{
- return new BCursor (B_CURSOR_ID_GRAB);
-}
-
-void
-BCursor_delete (void *cursor)
+be_create_cursor_from_id (int id)
{
- delete (BCursor *) cursor;
+ return new BCursor ((enum BCursorID) id);
}
void
BView_set_view_cursor (void *view, void *cursor)
{
- if (!((BView *) view)->LockLooper ())
+ BView *v = (BView *) view;
+
+ if (!v->LockLooper ())
gui_abort ("Failed to lock view setting cursor");
- ((BView *) view)->SetViewCursor ((BCursor *) cursor);
- ((BView *) view)->UnlockLooper ();
+ v->SetViewCursor ((BCursor *) cursor);
+ v->UnlockLooper ();
}
void
@@ -1799,88 +3598,24 @@ BWindow_Flush (void *window)
((BWindow *) window)->Flush ();
}
-/* Map the keycode KC, storing the result in CODE and 1 in
- NON_ASCII_P if it should be used. */
-void
-BMapKey (uint32_t kc, int *non_ascii_p, unsigned *code)
-{
- if (*code == 10 && kc != 0x42)
- {
- *code = XK_Return;
- *non_ascii_p = 1;
- return;
- }
-
- switch (kc)
- {
- default:
- *non_ascii_p = 0;
- if (kc < 0xe && kc > 0x1)
- {
- *code = XK_F1 + kc - 2;
- *non_ascii_p = 1;
- }
- return;
- case 0x1e:
- *code = XK_BackSpace;
- break;
- case 0x61:
- *code = XK_Left;
- break;
- case 0x63:
- *code = XK_Right;
- break;
- case 0x57:
- *code = XK_Up;
- break;
- case 0x62:
- *code = XK_Down;
- break;
- case 0x64:
- *code = XK_Insert;
- break;
- case 0x65:
- *code = XK_Delete;
- break;
- case 0x37:
- *code = XK_Home;
- break;
- case 0x58:
- *code = XK_End;
- break;
- case 0x39:
- *code = XK_Page_Up;
- break;
- case 0x5a:
- *code = XK_Page_Down;
- break;
- case 0x1:
- *code = XK_Escape;
- break;
- case 0x68:
- *code = XK_Menu;
- break;
- }
- *non_ascii_p = 1;
-}
-
/* Make a scrollbar, attach it to VIEW's window, and return it. */
void *
-BScrollBar_make_for_view (void *view, int horizontal_p,
- int x, int y, int x1, int y1,
- void *scroll_bar_ptr)
+be_make_scroll_bar_for_view (void *view, int horizontal_p,
+ int x, int y, int x1, int y1)
{
- EmacsScrollBar *sb = new EmacsScrollBar (x, y, x1, y1, horizontal_p);
- sb->scroll_bar = scroll_bar_ptr;
-
+ EmacsScrollBar *scroll_bar;
BView *vw = (BView *) view;
- BView *sv = (BView *) sb;
+
if (!vw->LockLooper ())
gui_abort ("Failed to lock scrollbar owner");
- vw->AddChild ((BView *) sb);
- sv->WindowActivated (vw->Window ()->IsActive ());
+
+ scroll_bar = new EmacsScrollBar (x, y, x1, y1, horizontal_p,
+ (EmacsView *) vw);
+
+ vw->AddChild (scroll_bar);
vw->UnlockLooper ();
- return sb;
+
+ return scroll_bar;
}
void
@@ -1906,19 +3641,25 @@ BView_move_frame (void *view, int x, int y, int x1, int y1)
gui_abort ("Failed to lock view moving frame");
vw->MoveTo (x, y);
vw->ResizeTo (x1 - x, y1 - y);
- vw->Flush ();
- vw->Sync ();
vw->UnlockLooper ();
}
+/* DRAGGING can either be 0 (which means to update everything), 1
+ (which means to update nothing), or -1 (which means to update only
+ the thumb size and range). */
+
void
-BView_scroll_bar_update (void *sb, int portion, int whole, int position)
+BView_scroll_bar_update (void *sb, int portion, int whole, int position,
+ int dragging, bool can_overscroll)
{
BScrollBar *bar = (BScrollBar *) sb;
BMessage msg = BMessage (SCROLL_BAR_UPDATE);
BMessenger mr = BMessenger (bar);
msg.AddInt32 ("emacs:range", whole);
msg.AddInt32 ("emacs:units", position);
+ msg.AddInt32 ("emacs:portion", portion);
+ msg.AddInt32 ("emacs:dragging", dragging);
+ msg.AddBool ("emacs:overscroll", can_overscroll);
mr.SendMessage (&msg);
}
@@ -1927,7 +3668,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. */
@@ -1943,14 +3686,23 @@ BView_invalidate (void *view)
/* Lock VIEW in preparation for drawing operations. This should be
called before any attempt to draw onto VIEW or to lock it for Cairo
- drawing. `BView_draw_unlock' should be called afterwards. */
+ drawing. `BView_draw_unlock' should be called afterwards.
+
+ If any drawing is going to take place, INVALID_REGION should be
+ true, and X, Y, WIDTH, HEIGHT should specify a rectangle in which
+ the drawing will take place. */
void
-BView_draw_lock (void *view)
+BView_draw_lock (void *view, bool invalidate_region,
+ int x, int y, int width, int height)
{
EmacsView *vw = (EmacsView *) view;
if (vw->looper_locked_count)
{
vw->looper_locked_count++;
+
+ if (invalidate_region && vw->offscreen_draw_view)
+ vw->invalid_region.Include (BRect (x, y, x + width - 1,
+ y + height - 1));
return;
}
BView *v = (BView *) find_appropriate_view_for_draw (vw);
@@ -1964,10 +3716,24 @@ BView_draw_lock (void *view)
if (v != vw && !vw->LockLooper ())
gui_abort ("Failed to lock view while acquiring draw lock");
+
+ if (invalidate_region && vw->offscreen_draw_view)
+ vw->invalid_region.Include (BRect (x, y, x + width - 1,
+ y + height - 1));
vw->looper_locked_count++;
}
void
+BView_invalidate_region (void *view, int x, int y, int width, int height)
+{
+ EmacsView *vw = (EmacsView *) view;
+
+ if (vw->offscreen_draw_view)
+ vw->invalid_region.Include (BRect (x, y, x + width - 1,
+ y + height - 1));
+}
+
+void
BView_draw_unlock (void *view)
{
EmacsView *vw = (EmacsView *) view;
@@ -1991,53 +3757,25 @@ BWindow_center_on_screen (void *window)
w->CenterOnScreen ();
}
-/* Tell VIEW it has been clicked at X by Y. */
-void
-BView_mouse_down (void *view, int x, int y)
-{
- BView *vw = (BView *) view;
- if (vw->LockLooper ())
- {
- vw->MouseDown (BPoint (x, y));
- vw->UnlockLooper ();
- }
-}
-
-/* Tell VIEW the mouse has been released at X by Y. */
-void
-BView_mouse_up (void *view, int x, int y)
-{
- BView *vw = (BView *) view;
- if (vw->LockLooper ())
- {
- vw->MouseUp (BPoint (x, y));
- vw->UnlockLooper ();
- }
-}
-
-/* Tell VIEW that the mouse has moved to Y by Y. */
+/* Import fringe bitmap (short array, low bit rightmost) BITS into
+ BITMAP using the B_GRAY1 colorspace. */
void
-BView_mouse_moved (void *view, int x, int y, uint32_t transit)
-{
- BView *vw = (BView *) view;
- if (vw->LockLooper ())
- {
- vw->MouseMoved (BPoint (x, y), transit, NULL);
- vw->UnlockLooper ();
- }
-}
-
-/* Import BITS into BITMAP using the B_GRAY1 colorspace. */
-void
-BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h)
+BBitmap_import_fringe_bitmap (void *bitmap, unsigned short *bits, int wd, int h)
{
BBitmap *bmp = (BBitmap *) bitmap;
unsigned char *data = (unsigned char *) bmp->Bits ();
- unsigned short *bts = (unsigned short *) bits;
+ int i;
- for (int i = 0; i < (h * (wd / 8)); i++)
+ for (i = 0; i < h; i++)
{
- *((unsigned short *) data) = bts[i];
+ if (wd <= 8)
+ data[0] = bits[i] & 0xff;
+ else
+ {
+ data[1] = bits[i] & 0xff;
+ data[0] = bits[i] >> 8;
+ }
+
data += bmp->BytesPerRow ();
}
}
@@ -2067,6 +3805,23 @@ BView_forget_scroll_bar (void *view, int x, int y, int width, int height)
}
}
+bool
+BView_inside_scroll_bar (void *view, int x, int y)
+{
+ EmacsView *vw = (EmacsView *) view;
+ bool val;
+
+ if (vw->LockLooper ())
+ {
+ val = vw->sb_region.Contains (BPoint (x, y));
+ vw->UnlockLooper ();
+ }
+ else
+ val = false;
+
+ return val;
+}
+
void
BView_get_mouse (void *view, int *x, int *y)
{
@@ -2115,13 +3870,24 @@ BView_convert_from_screen (void *view, int *x, int *y)
void
BWindow_change_decoration (void *window, int decorate_p)
{
- BWindow *w = (BWindow *) window;
+ EmacsWindow *w = (EmacsWindow *) window;
if (!w->LockLooper ())
gui_abort ("Failed to lock window while changing its decorations");
- if (decorate_p)
- w->SetLook (B_TITLED_WINDOW_LOOK);
+
+ if (!w->override_redirect_p)
+ {
+ if (decorate_p)
+ w->SetLook (B_TITLED_WINDOW_LOOK);
+ else
+ w->SetLook (B_NO_BORDER_WINDOW_LOOK);
+ }
else
- w->SetLook (B_NO_BORDER_WINDOW_LOOK);
+ {
+ if (decorate_p)
+ w->pre_override_redirect_look = B_TITLED_WINDOW_LOOK;
+ else
+ w->pre_override_redirect_look = B_NO_BORDER_WINDOW_LOOK;
+ }
w->UnlockLooper ();
}
@@ -2129,11 +3895,16 @@ BWindow_change_decoration (void *window, int decorate_p)
void
BWindow_set_tooltip_decoration (void *window)
{
- BWindow *w = (BWindow *) window;
+ EmacsWindow *w = (EmacsWindow *) window;
if (!w->LockLooper ())
gui_abort ("Failed to lock window while setting ttip decoration");
+ w->tooltip_p = true;
+ w->RecomputeFeel ();
w->SetLook (B_BORDERED_WINDOW_LOOK);
- w->SetFeel (B_FLOATING_APP_WINDOW_FEEL);
+ w->SetFlags (B_NOT_ZOOMABLE
+ | B_NOT_MINIMIZABLE
+ | B_AVOID_FRONT
+ | B_AVOID_FOCUS);
w->UnlockLooper ();
}
@@ -2150,7 +3921,6 @@ BWindow_set_avoid_focus (void *window, int avoid_focus_p)
w->SetFlags (w->Flags () & ~B_AVOID_FOCUS);
else
w->SetFlags (w->Flags () | B_AVOID_FOCUS);
- w->Sync ();
w->UnlockLooper ();
}
@@ -2164,25 +3934,12 @@ BView_emacs_delete (void *view)
delete vw;
}
-/* Return the current workspace. */
-uint32_t
-haiku_current_workspace (void)
-{
- return current_workspace ();
-}
-
-/* Return a bitmask consisting of workspaces WINDOW is on. */
-uint32_t
-BWindow_workspaces (void *window)
-{
- return ((BWindow *) window)->Workspaces ();
-}
-
/* Create a popup menu. */
void *
BPopUpMenu_new (const char *name)
{
- BPopUpMenu *menu = new EmacsPopUpMenu (name);
+ BPopUpMenu *menu = new BPopUpMenu (name);
+
menu->SetRadioMode (0);
return menu;
}
@@ -2192,9 +3949,11 @@ BPopUpMenu_new (const char *name)
void
BMenu_add_title (void *menu, const char *text)
{
- EmacsTitleMenuItem *it = new EmacsTitleMenuItem (text);
- BMenu *mn = (BMenu *) menu;
- mn->AddItem (it);
+ BMenu *be_menu = (BMenu *) menu;
+ EmacsTitleMenuItem *it;
+
+ it = new EmacsTitleMenuItem (text);
+ be_menu->AddItem (it);
}
/* Add an item to the menu MENU. */
@@ -2216,6 +3975,7 @@ BMenu_add_item (void *menu, const char *label, void *ptr, bool enabled_p,
it->menu_bar_id = (intptr_t) ptr;
it->wind_ptr = mbw_ptr;
}
+ it->menu_ptr = ptr;
if (ptr)
msg->AddPointer ("menuptr", ptr);
m->AddItem (it);
@@ -2260,20 +4020,120 @@ BMenu_new_menu_bar_submenu (void *menu, const char *label)
data of the selected item (if one exists), or NULL. X, Y should
be in the screen coordinate system. */
void *
-BMenu_run (void *menu, int x, int y)
+BMenu_run (void *menu, int x, int y,
+ void (*run_help_callback) (void *, void *),
+ void (*block_input_function) (void),
+ void (*unblock_input_function) (void),
+ struct timespec (*process_pending_signals_function) (void),
+ void *run_help_callback_data)
{
BPopUpMenu *mn = (BPopUpMenu *) menu;
+ enum haiku_event_type type;
+ void *buf;
+ void *ptr = NULL;
+ struct be_popup_menu_data data;
+ struct object_wait_info infos[3];
+ struct haiku_menu_bar_help_event *event;
+ BMessage *msg;
+ ssize_t stat;
+ struct timespec next_time;
+ bigtime_t timeout;
+
+ block_input_function ();
+ port_popup_menu_to_emacs = create_port (1800, "popup menu port");
+ data.x = x;
+ data.y = y;
+ data.menu = mn;
+ unblock_input_function ();
+
+ if (port_popup_menu_to_emacs < B_OK)
+ return NULL;
+
+ block_input_function ();
mn->SetRadioMode (0);
- BMenuItem *it = mn->Go (BPoint (x, y));
- if (it)
+ buf = alloca (200);
+
+ infos[0].object = port_popup_menu_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = spawn_thread (be_popup_menu_thread_entry,
+ "Menu tracker", B_DEFAULT_MEDIA_PRIORITY,
+ (void *) &data);
+ infos[1].type = B_OBJECT_TYPE_THREAD;
+ infos[1].events = B_EVENT_INVALID;
+
+ infos[2].object = port_application_to_emacs;
+ infos[2].type = B_OBJECT_TYPE_PORT;
+ infos[2].events = B_EVENT_READ;
+ unblock_input_function ();
+
+ if (infos[1].object < B_OK)
{
- BMessage *mg = it->Message ();
- if (mg)
- return (void *) mg->GetPointer ("menuptr");
+ block_input_function ();
+ delete_port (port_popup_menu_to_emacs);
+ unblock_input_function ();
+ return NULL;
+ }
+
+ block_input_function ();
+ resume_thread (infos[1].object);
+ unblock_input_function ();
+
+ while (true)
+ {
+ next_time = process_pending_signals_function ();
+
+ if (next_time.tv_nsec < 0)
+ timeout = 10000000000;
else
- return NULL;
+ timeout = (next_time.tv_sec * 1000000
+ + next_time.tv_nsec / 1000);
+
+ if ((stat = wait_for_objects_etc ((object_wait_info *) &infos, 3,
+ B_RELATIVE_TIMEOUT, timeout)) < B_OK)
+ {
+ if (stat == B_INTERRUPTED || stat == B_TIMED_OUT
+ || stat == B_WOULD_BLOCK)
+ continue;
+ else
+ gui_abort ("Failed to wait for popup");
+ }
+
+ if (infos[0].events & B_EVENT_READ)
+ {
+ while (!haiku_read_with_timeout (&type, buf, 200, 0, true))
+ {
+ switch (type)
+ {
+ case MENU_BAR_HELP_EVENT:
+ event = (struct haiku_menu_bar_help_event *) buf;
+ run_help_callback (event->highlight_p
+ ? event->data
+ : NULL, run_help_callback_data);
+ break;
+ default:
+ gui_abort ("Unknown popup menu event");
+ }
+ }
+ }
+
+ if (infos[1].events & B_EVENT_INVALID)
+ {
+ block_input_function ();
+ msg = (BMessage *) popup_track_message;
+ if (popup_track_message)
+ ptr = (void *) msg->GetPointer ("menuptr");
+
+ delete_port (port_popup_menu_to_emacs);
+ unblock_input_function ();
+ return ptr;
+ }
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_INVALID;
+ infos[2].events = B_EVENT_READ;
}
- return NULL;
}
/* Delete the entire menu hierarchy of MENU, and then delete MENU
@@ -2386,12 +4246,83 @@ BAlert_add_button (void *alert, const char *text)
return al->ButtonAt (al->CountButtons () - 1);
}
+/* Make sure the leftmost button is grouped to the left hand side of
+ the alert. */
+void
+BAlert_set_offset_spacing (void *alert)
+{
+ BAlert *al = (BAlert *) alert;
+
+ al->SetButtonSpacing (B_OFFSET_SPACING);
+}
+
+static int32
+be_alert_thread_entry (void *thread_data)
+{
+ BAlert *alert = (BAlert *) thread_data;
+ int32 value;
+
+ if (alert->LockLooper ())
+ value = alert->Go ();
+ else
+ value = -1;
+
+ alert_popup_value = value;
+ return 0;
+}
+
/* Run ALERT, returning the number of the button that was selected,
or -1 if no button was selected before the alert was closed. */
-int32_t
-BAlert_go (void *alert)
+int32
+BAlert_go (void *alert,
+ void (*block_input_function) (void),
+ void (*unblock_input_function) (void),
+ void (*process_pending_signals_function) (void))
{
- return ((BAlert *) alert)->Go ();
+ struct object_wait_info infos[2];
+ ssize_t stat;
+ BAlert *alert_object = (BAlert *) alert;
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ block_input_function ();
+ /* Alerts are created locked, just like other windows. */
+ alert_object->UnlockLooper ();
+ infos[1].object = spawn_thread (be_alert_thread_entry,
+ "Popup tracker",
+ B_DEFAULT_MEDIA_PRIORITY,
+ alert);
+ infos[1].type = B_OBJECT_TYPE_THREAD;
+ infos[1].events = B_EVENT_INVALID;
+ unblock_input_function ();
+
+ if (infos[1].object < B_OK)
+ return -1;
+
+ block_input_function ();
+ resume_thread (infos[1].object);
+ unblock_input_function ();
+
+ while (true)
+ {
+ stat = wait_for_objects ((object_wait_info *) &infos, 2);
+
+ if (stat == B_INTERRUPTED)
+ continue;
+ else if (stat < B_OK)
+ gui_abort ("Failed to wait for popup dialog");
+
+ if (infos[1].events & B_EVENT_INVALID)
+ return alert_popup_value;
+
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_INVALID;
+ }
}
/* Enable or disable BUTTON depending on ENABLED_P. */
@@ -2410,30 +4341,48 @@ BView_set_tooltip (void *view, const char *tooltip)
/* Set VIEW's tooltip to a sticky tooltip at X by Y. */
void
-BView_set_and_show_sticky_tooltip (void *view, const char *tooltip,
- int x, int y)
+be_show_sticky_tooltip (void *view, const char *tooltip_text,
+ int x, int y)
{
- BToolTip *tip;
- BView *vw = (BView *) view;
+ BToolTip *tooltip;
+ BView *vw, *tooltip_view;
+ BPoint point;
+
+ vw = (BView *) view;
+
if (!vw->LockLooper ())
gui_abort ("Failed to lock view while showing sticky tooltip");
- vw->SetToolTip (tooltip);
- tip = vw->ToolTip ();
- BPoint pt;
- EmacsView *ev = dynamic_cast<EmacsView *> (vw);
- if (ev)
- ev->tt_absl_pos = BPoint (x, y);
- vw->GetMouse (&pt, NULL, 1);
- pt.x -= x;
- pt.y -= y;
+ vw->SetToolTip ((const char *) NULL);
+
+ /* If the tooltip text is empty, then a tooltip object won't be
+ created by SetToolTip. */
+ if (tooltip_text[0] == '\0')
+ tooltip_text = " ";
+
+ vw->SetToolTip (tooltip_text);
+
+ tooltip = vw->ToolTip ();
+
+ vw->GetMouse (&point, NULL, 1);
+ point.x -= x;
+ point.y -= y;
+
+ point.x = -point.x;
+ point.y = -point.y;
- pt.x = -pt.x;
- pt.y = -pt.y;
+ /* We don't have to make the tooltip sticky since not receiving
+ mouse movement is enough to prevent it from being hidden. */
+ tooltip->SetMouseRelativeLocation (point);
- tip->SetMouseRelativeLocation (pt);
- tip->SetSticky (1);
- vw->ShowToolTip (tip);
+ /* Prevent the tooltip from moving in response to mouse
+ movement. */
+ tooltip_view = tooltip->View ();
+
+ if (tooltip_view)
+ tooltip_view->AddChild (new EmacsMotionSuppressionView);
+
+ vw->ShowToolTip (tooltip);
vw->UnlockLooper ();
}
@@ -2444,25 +4393,32 @@ BAlert_delete (void *alert)
delete (BAlert *) alert;
}
-/* Place the resolution of the monitor in DPI in RSSX and RSSY. */
+/* Place the resolution of the monitor in DPI in X_OUT and Y_OUT. */
void
-BScreen_res (double *rrsx, double *rrsy)
+be_get_display_resolution (double *x_out, double *y_out)
{
BScreen s (B_MAIN_SCREEN_ID);
+ monitor_info i;
+ double x_inches, y_inches;
+ BRect frame;
+
if (!s.IsValid ())
gui_abort ("Invalid screen for resolution checks");
- monitor_info i;
if (s.GetMonitorInfo (&i) == B_OK)
{
- *rrsx = (double) i.width / (double) 2.54;
- *rrsy = (double) i.height / (double) 2.54;
- }
- else
- {
- *rrsx = 72.27;
- *rrsy = 72.27;
+ frame = s.Frame ();
+
+ x_inches = (double) i.width * 25.4;
+ y_inches = (double) i.height * 25.4;
+
+ *x_out = (double) BE_RECT_WIDTH (frame) / x_inches;
+ *y_out = (double) BE_RECT_HEIGHT (frame) / y_inches;
+ return;
}
+
+ *x_out = 72.0;
+ *y_out = 72.0;
}
/* Add WINDOW to OTHER_WINDOW's subset and parent it to
@@ -2493,6 +4449,8 @@ void
be_get_version_string (char *version, int len)
{
std::strncpy (version, "Unknown Haiku release", len - 1);
+ version[len - 1] = '\0';
+
BPath path;
if (find_directory (B_BEOS_LIB_DIRECTORY, &path) == B_OK)
{
@@ -2506,7 +4464,10 @@ be_get_version_string (char *version, int len)
&& appFileInfo.GetVersionInfo (&versionInfo,
B_APP_VERSION_KIND) == B_OK
&& versionInfo.short_info[0] != '\0')
- std::strncpy (version, versionInfo.short_info, len - 1);
+ {
+ std::strncpy (version, versionInfo.short_info, len - 1);
+ version[len - 1] = '\0';
+ }
}
}
@@ -2515,24 +4476,35 @@ int
be_get_display_planes (void)
{
color_space space = dpy_color_space;
+ BScreen screen;
+
if (space == B_NO_COLOR_SPACE)
{
- BScreen screen; /* This is actually a very slow operation. */
if (!screen.IsValid ())
gui_abort ("Invalid screen");
+
space = dpy_color_space = screen.ColorSpace ();
}
- if (space == B_RGB32 || space == B_RGB24)
- return 24;
- if (space == B_RGB16)
- return 16;
- if (space == B_RGB15)
- return 15;
- if (space == B_CMAP8)
- return 8;
+ switch (space)
+ {
+ case B_RGB32:
+ case B_RGB24:
+ return 24;
+ case B_RGB16:
+ return 16;
+ case B_RGB15:
+ return 15;
+ case B_CMAP8:
+ case B_GRAY8:
+ return 8;
+ case B_GRAY1:
+ return 1;
+
+ default:
+ gui_abort ("Bad colorspace for screen");
+ }
- gui_abort ("Bad colorspace for screen");
/* https://www.haiku-os.org/docs/api/classBScreen.html
says a valid screen can't be anything else. */
return -1;
@@ -2542,28 +4514,58 @@ be_get_display_planes (void)
int
be_get_display_color_cells (void)
{
+ BScreen screen;
color_space space = dpy_color_space;
+
if (space == B_NO_COLOR_SPACE)
{
- BScreen screen;
if (!screen.IsValid ())
gui_abort ("Invalid screen");
+
space = dpy_color_space = screen.ColorSpace ();
}
- if (space == B_RGB32 || space == B_RGB24)
- return 1677216;
- if (space == B_RGB16)
- return 65536;
- if (space == B_RGB15)
- return 32768;
- if (space == B_CMAP8)
- return 256;
+ switch (space)
+ {
+ case B_RGB32:
+ case B_RGB24:
+ return 16777216;
+ case B_RGB16:
+ return 65536;
+ case B_RGB15:
+ return 32768;
+ case B_CMAP8:
+ case B_GRAY8:
+ return 256;
+ case B_GRAY1:
+ return 2;
+
+ default:
+ gui_abort ("Bad colorspace for screen");
+ }
- gui_abort ("Bad colorspace for screen");
return -1;
}
+/* Return whether or not the current display is only capable of
+ producing grayscale colors. */
+bool
+be_is_display_grayscale (void)
+{
+ BScreen screen;
+ color_space space = dpy_color_space;
+
+ if (space == B_NO_COLOR_SPACE)
+ {
+ if (!screen.IsValid ())
+ gui_abort ("Invalid screen");
+
+ space = dpy_color_space = screen.ColorSpace ();
+ }
+
+ return space == B_GRAY8 || space == B_GRAY1;
+}
+
/* Warp the pointer to X by Y. */
void
be_warp_pointer (int x, int y)
@@ -2655,159 +4657,74 @@ EmacsView_double_buffered_p (void *vw)
return db_p;
}
-struct popup_file_dialog_data
-{
- BMessage *msg;
- BFilePanel *panel;
- BEntry *entry;
-};
-
-static void
-unwind_popup_file_dialog (void *ptr)
-{
- struct popup_file_dialog_data *data =
- (struct popup_file_dialog_data *) ptr;
- BFilePanel *panel = data->panel;
- delete panel;
- delete data->entry;
- delete data->msg;
-}
-
-static void
-be_popup_file_dialog_safe_set_target (BFilePanel *dialog, BWindow *window)
-{
- dialog->SetTarget (BMessenger (window));
-}
-
/* Popup a file dialog. */
char *
-be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int dir_only_p,
- void *window, const char *save_text, const char *prompt,
- void (*block_input_function) (void),
- void (*unblock_input_function) (void),
- void (*maybe_quit_function) (void))
-{
- ptrdiff_t idx = c_specpdl_idx_from_cxx ();
- /* setjmp/longjmp is UB with automatic objects. */
- block_input_function ();
- BWindow *w = (BWindow *) window;
- uint32_t mode = dir_only_p ? B_DIRECTORY_NODE : B_FILE_NODE | B_DIRECTORY_NODE;
- BEntry *path = new BEntry;
- BMessage *msg = new BMessage ('FPSE');
- BFilePanel *panel = new BFilePanel (open_p ? B_OPEN_PANEL : B_SAVE_PANEL,
- NULL, NULL, mode);
-
- struct popup_file_dialog_data dat;
- dat.entry = path;
- dat.msg = msg;
- dat.panel = panel;
-
- record_c_unwind_protect_from_cxx (unwind_popup_file_dialog, &dat);
- if (default_dir)
+be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
+ int dir_only_p, void *window, const char *save_text,
+ const char *prompt,
+ void (*process_pending_signals_function) (void))
+{
+ BWindow *panel_window;
+ BEntry path;
+ BMessage msg (FILE_PANEL_SELECTION);
+ BFilePanel panel (open_p ? B_OPEN_PANEL : B_SAVE_PANEL,
+ NULL, NULL, (dir_only_p
+ ? B_DIRECTORY_NODE
+ : B_FILE_NODE | B_DIRECTORY_NODE));
+ char *file_name;
+ EmacsFilePanelCallbackLooper *looper;
+
+ looper = new EmacsFilePanelCallbackLooper;
+
+ if (looper->InitCheck () < B_OK)
{
- if (path->SetTo (default_dir, 0) != B_OK)
- default_dir = NULL;
+ delete looper;
+ return NULL;
}
- panel->SetMessage (msg);
if (default_dir)
- panel->SetPanelDirectory (path);
- if (save_text)
- panel->SetSaveText (save_text);
- panel->SetHideWhenDone (0);
- panel->Window ()->SetTitle (prompt);
- be_popup_file_dialog_safe_set_target (panel, w);
-
- panel->Show ();
- unblock_input_function ();
-
- void *buf = alloca (200);
- while (1)
{
- enum haiku_event_type type;
- char *ptr = NULL;
+ if (path.SetTo (default_dir, 0) != B_OK)
+ default_dir = NULL;
+ }
- if (!haiku_read_with_timeout (&type, buf, 200, 100000))
- {
- block_input_function ();
- if (type != FILE_PANEL_EVENT)
- haiku_write (type, buf);
- else if (!ptr)
- ptr = (char *) ((struct haiku_file_panel_event *) buf)->ptr;
- unblock_input_function ();
+ panel_window = panel.Window ();
- maybe_quit_function ();
- }
+ if (default_dir)
+ panel.SetPanelDirectory (&path);
- ssize_t b_s;
- block_input_function ();
- haiku_read_size (&b_s);
- if (!b_s || ptr || panel->Window ()->IsHidden ())
- {
- c_unbind_to_nil_from_cxx (idx);
- unblock_input_function ();
- return ptr;
- }
- unblock_input_function ();
- }
-}
+ if (save_text)
+ panel.SetSaveText (save_text);
-void
-be_app_quit (void)
-{
- if (be_app)
- {
- while (!be_app->Lock ());
- be_app->Quit ();
- }
-}
+ panel_window->SetTitle (prompt);
+ panel_window->SetFeel (B_MODAL_APP_WINDOW_FEEL);
-/* Temporarily fill VIEW with COLOR. */
-void
-EmacsView_do_visible_bell (void *view, uint32_t color)
-{
- EmacsView *vw = (EmacsView *) view;
- vw->DoVisibleBell (color);
-}
+ panel.SetHideWhenDone (false);
+ panel.SetTarget (BMessenger (looper));
+ panel.SetMessage (&msg);
+ panel.Show ();
-/* Zoom WINDOW. */
-void
-BWindow_zoom (void *window)
-{
- BWindow *w = (BWindow *) window;
- w->Zoom ();
-}
+ looper->Run ();
+ file_name = looper->ReadFileName (process_pending_signals_function);
-/* Make WINDOW fullscreen if FULLSCREEN_P. */
-void
-EmacsWindow_make_fullscreen (void *window, int fullscreen_p)
-{
- EmacsWindow *w = (EmacsWindow *) window;
- w->MakeFullscreen (fullscreen_p);
-}
+ if (looper->Lock ())
+ looper->Quit ();
-/* Unzoom (maximize) WINDOW. */
-void
-EmacsWindow_unzoom (void *window)
-{
- EmacsWindow *w = (EmacsWindow *) window;
- w->UnZoom ();
+ return file_name;
}
-/* Move the pointer into MBAR and start tracking. */
-void
+/* Move the pointer into MBAR and start tracking. Return whether the
+ menu bar was opened correctly. */
+bool
BMenuBar_start_tracking (void *mbar)
{
EmacsMenuBar *mb = (EmacsMenuBar *) mbar;
- if (!mb->LockLooper ())
- gui_abort ("Couldn't lock menubar");
- BRect frame = mb->Frame ();
- BPoint pt = frame.LeftTop ();
- BPoint l = pt;
- mb->Parent ()->ConvertToScreen (&pt);
- set_mouse_position (pt.x, pt.y);
- mb->MouseDown (l);
- mb->UnlockLooper ();
+ BMessenger messenger (mb);
+ BMessage reply;
+
+ messenger.SendMessage (SHOW_MENU_BAR, &reply);
+
+ return reply.what == BE_MENU_BAR_OPEN;
}
#ifdef HAVE_NATIVE_IMAGE_API
@@ -2905,12 +4822,12 @@ BView_show_tooltip (void *view)
#ifdef USE_BE_CAIRO
-/* Return VIEW's cairo surface. */
-cairo_surface_t *
-EmacsView_cairo_surface (void *view)
+/* Return VIEW's cairo context. */
+cairo_t *
+EmacsView_cairo_context (void *view)
{
EmacsView *vw = (EmacsView *) view;
- return vw->cr_surface;
+ return vw->cr_context;
}
/* Transfer each clip rectangle in VIEW to the cairo context
@@ -2989,17 +4906,6 @@ be_get_display_screens (void)
}
/* Set the minimum width the user can resize WINDOW to. */
-void
-BWindow_set_min_size (void *window, int width, int height)
-{
- BWindow *w = (BWindow *) window;
-
- if (!w->LockLooper ())
- gui_abort ("Failed to lock window looper setting min size");
- w->SetSizeLimits (width, -1, height, -1);
- w->UnlockLooper ();
-}
-
/* Synchronize WINDOW's connection to the App Server. */
void
BWindow_sync (void *window)
@@ -3058,3 +4964,459 @@ be_use_subpixel_antialiasing (void)
return current_subpixel_antialiasing;
}
+
+void
+BWindow_set_override_redirect (void *window, bool override_redirect_p)
+{
+ EmacsWindow *w = (EmacsWindow *) window;
+
+ if (w->LockLooper ())
+ {
+ if (override_redirect_p && !w->override_redirect_p)
+ {
+ w->override_redirect_p = true;
+ w->pre_override_redirect_look = w->Look ();
+ w->RecomputeFeel ();
+ w->SetLook (B_NO_BORDER_WINDOW_LOOK);
+ w->pre_override_redirect_workspaces = w->Workspaces ();
+ w->SetWorkspaces (B_ALL_WORKSPACES);
+ }
+ else if (w->override_redirect_p)
+ {
+ w->override_redirect_p = false;
+ w->SetLook (w->pre_override_redirect_look);
+ w->RecomputeFeel ();
+ w->SetWorkspaces (w->pre_override_redirect_workspaces);
+ }
+
+ w->UnlockLooper ();
+ }
+}
+
+/* Find a resource by the name NAME inside the settings file. The
+ string returned is in UTF-8 encoding, and will stay allocated as
+ long as the BApplication (a.k.a display) is alive. */
+const char *
+be_find_setting (const char *name)
+{
+ Emacs *app = (Emacs *) be_app;
+ const char *value;
+
+ /* Note that this is thread-safe since the constructor of `Emacs'
+ runs in the main thread. */
+ if (!app->settings_valid_p)
+ return NULL;
+
+ if (app->settings.FindString (name, 0, &value) != B_OK)
+ return NULL;
+
+ return value;
+}
+
+void
+BMessage_delete (void *message)
+{
+ delete (BMessage *) message;
+}
+
+static int32
+be_drag_message_thread_entry (void *thread_data)
+{
+ BMessenger *messenger;
+ BMessage reply;
+
+ messenger = (BMessenger *) thread_data;
+ messenger->SendMessage (WAIT_FOR_RELEASE, &reply);
+
+ return 0;
+}
+
+bool
+be_drag_message (void *view, void *message, bool allow_same_view,
+ void (*block_input_function) (void),
+ void (*unblock_input_function) (void),
+ void (*process_pending_signals_function) (void),
+ bool (*should_quit_function) (void))
+{
+ EmacsView *vw = (EmacsView *) view;
+ EmacsWindow *window = (EmacsWindow *) vw->Window ();
+ BMessage *msg = (BMessage *) message;
+ BMessage wait_for_release;
+ BMessenger messenger (vw);
+ BMessage cancel_message (CANCEL_DROP);
+ struct object_wait_info infos[2];
+ ssize_t stat;
+
+ block_input_function ();
+
+ if (!allow_same_view &&
+ (msg->ReplaceInt32 ("emacs:window_id", window->window_id)
+ == B_NAME_NOT_FOUND))
+ msg->AddInt32 ("emacs:window_id", window->window_id);
+
+ if (!vw->LockLooper ())
+ gui_abort ("Failed to lock view looper for drag");
+
+ vw->DragMessage (msg, BRect (0, 0, 0, 0));
+ vw->UnlockLooper ();
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = spawn_thread (be_drag_message_thread_entry,
+ "Drag waiter thread",
+ B_DEFAULT_MEDIA_PRIORITY,
+ (void *) &messenger);
+ infos[1].type = B_OBJECT_TYPE_THREAD;
+ infos[1].events = B_EVENT_INVALID;
+ unblock_input_function ();
+
+ if (infos[1].object < B_OK)
+ return false;
+
+ block_input_function ();
+ resume_thread (infos[1].object);
+ unblock_input_function ();
+
+ drag_and_drop_in_progress = true;
+
+ while (true)
+ {
+ block_input_function ();
+ stat = wait_for_objects ((struct object_wait_info *) &infos, 2);
+ unblock_input_function ();
+
+ if (stat == B_INTERRUPTED || stat == B_TIMED_OUT
+ || stat == B_WOULD_BLOCK)
+ continue;
+
+ if (stat < B_OK)
+ gui_abort ("Failed to wait for drag");
+
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
+
+ if (should_quit_function ())
+ {
+ /* Do the best we can to prevent something from being
+ dropped, since Haiku doesn't provide a way to actually
+ cancel drag-and-drop. */
+ if (vw->LockLooper ())
+ {
+ vw->DragMessage (&cancel_message, BRect (0, 0, 0, 0));
+ vw->UnlockLooper ();
+ }
+
+ messenger.SendMessage (CANCEL_DROP);
+ drag_and_drop_in_progress = false;
+ return true;
+ }
+
+ if (infos[1].events & B_EVENT_INVALID)
+ {
+ drag_and_drop_in_progress = false;
+ return false;
+ }
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_INVALID;
+ }
+}
+
+bool
+be_drag_and_drop_in_progress (void)
+{
+ return drag_and_drop_in_progress;
+}
+
+/* Replay the menu bar click event EVENT. Return whether or not the
+ menu bar actually opened. */
+bool
+be_replay_menu_bar_event (void *menu_bar,
+ struct haiku_menu_bar_click_event *event)
+{
+ BMenuBar *m = (BMenuBar *) menu_bar;
+ BMessenger messenger (m);
+ BMessage reply, msg (REPLAY_MENU_BAR);
+
+ msg.AddPoint ("emacs:point", BPoint (event->x, event->y));
+ messenger.SendMessage (&msg, &reply);
+ return reply.what == BE_MENU_BAR_OPEN;
+}
+
+void
+BWindow_set_z_group (void *window, enum haiku_z_group z_group)
+{
+ EmacsWindow *w = (EmacsWindow *) window;
+
+ if (w->LockLooper ())
+ {
+ if (w->z_group != z_group)
+ {
+ w->z_group = z_group;
+ w->RecomputeFeel ();
+
+ if (w->z_group == Z_GROUP_BELOW)
+ w->SetFlags (w->Flags () | B_AVOID_FRONT);
+ else
+ w->SetFlags (w->Flags () & ~B_AVOID_FRONT);
+ }
+
+ w->UnlockLooper ();
+ }
+}
+
+int
+be_get_ui_color (const char *name, uint32_t *color)
+{
+ color_which which;
+ rgb_color rgb;
+
+ which = which_ui_color (name);
+
+ if (which == B_NO_COLOR)
+ return 1;
+
+ rgb = ui_color (which);
+ *color = (rgb.blue | rgb.green << 8
+ | rgb.red << 16 | 255 << 24);
+
+ return 0;
+}
+
+bool
+be_select_font (void (*process_pending_signals_function) (void),
+ bool (*should_quit_function) (void),
+ haiku_font_family_or_style *family,
+ haiku_font_family_or_style *style,
+ int *size, bool allow_monospace_only,
+ int initial_family, int initial_style,
+ int initial_size, bool initial_antialias,
+ bool *disable_antialias)
+{
+ EmacsFontSelectionDialog *dialog;
+ struct font_selection_dialog_message msg;
+ uint32 flags;
+ font_family family_buffer;
+ font_style style_buffer;
+
+ dialog = new EmacsFontSelectionDialog (allow_monospace_only,
+ initial_family, initial_style,
+ initial_size, initial_antialias);
+ dialog->CenterOnScreen ();
+
+ if (dialog->InitCheck () < B_OK)
+ {
+ dialog->Quit ();
+ return false;
+ }
+
+ dialog->Show ();
+ dialog->WaitForChoice (&msg, process_pending_signals_function,
+ should_quit_function);
+
+ if (!dialog->LockLooper ())
+ gui_abort ("Failed to lock font selection dialog looper");
+ dialog->Quit ();
+
+ if (msg.cancel)
+ return false;
+
+ if (get_font_family (msg.family_idx,
+ &family_buffer, &flags) != B_OK
+ || get_font_style (family_buffer, msg.style_idx,
+ &style_buffer, &flags) != B_OK)
+ return false;
+
+ memcpy (family, family_buffer, sizeof *family);
+ memcpy (style, style_buffer, sizeof *style);
+ *size = msg.size_specified ? msg.size : -1;
+ *disable_antialias = msg.disable_antialias;
+
+ return true;
+}
+
+void
+BWindow_set_sticky (void *window, bool sticky)
+{
+ BWindow *w = (BWindow *) window;
+
+ if (w->LockLooper ())
+ {
+ w->SetFlags (sticky ? (w->Flags ()
+ | B_SAME_POSITION_IN_ALL_WORKSPACES)
+ : w->Flags () & ~B_SAME_POSITION_IN_ALL_WORKSPACES);
+
+ w->UnlockLooper ();
+ }
+}
+
+status_t
+be_roster_launch (const char *type, const char *file, char **cargs,
+ ptrdiff_t nargs, void *message, team_id *team_id)
+{
+ BEntry entry;
+ entry_ref ref;
+
+ if (type)
+ {
+ if (message)
+ return be_roster->Launch (type, (BMessage *) message,
+ team_id);
+
+ return be_roster->Launch (type, (nargs > INT_MAX
+ ? INT_MAX : nargs),
+ cargs, team_id);
+ }
+
+ if (entry.SetTo (file) != B_OK)
+ return B_ERROR;
+
+ if (entry.GetRef (&ref) != B_OK)
+ return B_ERROR;
+
+ if (message)
+ return be_roster->Launch (&ref, (BMessage *) message,
+ team_id);
+
+ return be_roster->Launch (&ref, (nargs > INT_MAX
+ ? INT_MAX : nargs),
+ cargs, team_id);
+}
+
+void *
+be_create_pixmap_cursor (void *bitmap, int x, int y)
+{
+ BBitmap *bm;
+ BCursor *cursor;
+
+ bm = (BBitmap *) bitmap;
+ cursor = new BCursor (bm, BPoint (x, y));
+
+ if (cursor->InitCheck () != B_OK)
+ {
+ delete cursor;
+ return NULL;
+ }
+
+ return cursor;
+}
+
+void
+be_get_window_decorator_dimensions (void *window, int *left, int *top,
+ int *right, int *bottom)
+{
+ BWindow *wnd;
+ BRect frame, window_frame;
+
+ wnd = (BWindow *) window;
+
+ if (!wnd->LockLooper ())
+ gui_abort ("Failed to lock window looper frame");
+
+ frame = wnd->DecoratorFrame ();
+ window_frame = wnd->Frame ();
+
+ if (left)
+ *left = window_frame.left - frame.left;
+
+ if (top)
+ *top = window_frame.top - frame.top;
+
+ if (right)
+ *right = frame.right - window_frame.right;
+
+ if (bottom)
+ *bottom = frame.bottom - window_frame.bottom;
+
+ wnd->UnlockLooper ();
+}
+
+void
+be_get_window_decorator_frame (void *window, int *left, int *top,
+ int *width, int *height)
+{
+ BWindow *wnd;
+ BRect frame;
+
+ wnd = (BWindow *) window;
+
+ if (!wnd->LockLooper ())
+ gui_abort ("Failed to lock window looper frame");
+
+ frame = wnd->DecoratorFrame ();
+
+ *left = frame.left;
+ *top = frame.top;
+ *width = BE_RECT_WIDTH (frame);
+ *height = BE_RECT_HEIGHT (frame);
+
+ wnd->UnlockLooper ();
+}
+
+/* Request that a MOVE_EVENT be sent for WINDOW. This is so that
+ frame offsets can be updated after a frame parameter affecting
+ decorators changes. Sending an event instead of updating the
+ offsets directly avoids race conditions where events with older
+ information are received after the update happens. */
+void
+be_send_move_frame_event (void *window)
+{
+ BWindow *wnd = (BWindow *) window;
+ BMessenger msg (wnd);
+
+ msg.SendMessage (SEND_MOVE_FRAME_EVENT);
+}
+
+void
+be_lock_window (void *window)
+{
+ BWindow *wnd = (BWindow *) window;
+
+ if (!wnd->LockLooper ())
+ gui_abort ("Failed to lock window looper");
+}
+
+void
+be_unlock_window (void *window)
+{
+ BWindow *wnd = (BWindow *) window;
+
+ wnd->UnlockLooper ();
+}
+
+void
+be_set_window_fullscreen_mode (void *window, enum haiku_fullscreen_mode mode)
+{
+ EmacsWindow *w = (EmacsWindow *) window;
+
+ if (!w->LockLooper ())
+ gui_abort ("Failed to lock window to set fullscreen mode");
+
+ w->SetFullscreen (mode);
+ w->UnlockLooper ();
+}
+
+bool
+be_get_explicit_workarea (int *x, int *y, int *width, int *height)
+{
+ BDeskbar deskbar;
+ BRect zoom;
+ deskbar_location location;
+
+ location = deskbar.Location ();
+
+ if (location != B_DESKBAR_TOP
+ && location != B_DESKBAR_BOTTOM)
+ return false;
+
+ zoom = get_zoom_rect (NULL);
+
+ *x = zoom.left;
+ *y = zoom.top;
+ *width = BE_RECT_WIDTH (zoom);
+ *height = BE_RECT_HEIGHT (zoom);
+
+ return true;
+}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 6a99eb245dc..5f44494a8d3 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -34,21 +34,46 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <math.h>
+#include <kernel/OS.h>
+
enum haiku_cursor
{
- CURSOR_ID_NO_CURSOR = 12,
- CURSOR_ID_RESIZE_NORTH = 15,
- CURSOR_ID_RESIZE_EAST = 16,
- CURSOR_ID_RESIZE_SOUTH = 17,
- CURSOR_ID_RESIZE_WEST = 18,
- CURSOR_ID_RESIZE_NORTH_EAST = 19,
- CURSOR_ID_RESIZE_NORTH_WEST = 20,
- CURSOR_ID_RESIZE_SOUTH_EAST = 21,
- CURSOR_ID_RESIZE_SOUTH_WEST = 22,
- CURSOR_ID_RESIZE_NORTH_SOUTH = 23,
- CURSOR_ID_RESIZE_EAST_WEST = 24,
+ CURSOR_ID_SYSTEM_DEFAULT = 1,
+ CURSOR_ID_CONTEXT_MENU = 3,
+ CURSOR_ID_COPY = 4,
+ CURSOR_ID_CREATE_LINK = 29,
+ CURSOR_ID_CROSS_HAIR = 5,
+ CURSOR_ID_FOLLOW_LINK = 6,
+ CURSOR_ID_GRAB = 7,
+ CURSOR_ID_GRABBING = 8,
+ CURSOR_ID_HELP = 9,
+ CURSOR_ID_I_BEAM = 2,
+ CURSOR_ID_I_BEAM_HORIZONTAL = 10,
+ CURSOR_ID_MOVE = 11,
+ CURSOR_ID_NO_CURSOR = 12,
+ CURSOR_ID_NOT_ALLOWED = 13,
+ CURSOR_ID_PROGRESS = 14,
+ CURSOR_ID_RESIZE_NORTH = 15,
+ CURSOR_ID_RESIZE_EAST = 16,
+ CURSOR_ID_RESIZE_SOUTH = 17,
+ CURSOR_ID_RESIZE_WEST = 18,
+ CURSOR_ID_RESIZE_NORTH_EAST = 19,
+ CURSOR_ID_RESIZE_NORTH_WEST = 20,
+ CURSOR_ID_RESIZE_SOUTH_EAST = 21,
+ CURSOR_ID_RESIZE_SOUTH_WEST = 22,
+ CURSOR_ID_RESIZE_NORTH_SOUTH = 23,
+ CURSOR_ID_RESIZE_EAST_WEST = 24,
CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST = 25,
- CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST = 26
+ CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST = 26,
+ CURSOR_ID_ZOOM_IN = 27,
+ CURSOR_ID_ZOOM_OUT = 28
+ };
+
+enum haiku_z_group
+ {
+ Z_GROUP_ABOVE,
+ Z_GROUP_NONE,
+ Z_GROUP_BELOW,
};
enum haiku_alert_type
@@ -74,19 +99,34 @@ enum haiku_event_type
ICONIFICATION,
MOVE_EVENT,
SCROLL_BAR_VALUE_EVENT,
+ SCROLL_BAR_PART_EVENT,
SCROLL_BAR_DRAG_EVENT,
WHEEL_MOVE_EVENT,
MENU_BAR_RESIZE,
+ MENU_BAR_CLICK,
MENU_BAR_OPEN,
MENU_BAR_SELECT_EVENT,
MENU_BAR_CLOSE,
- FILE_PANEL_EVENT,
MENU_BAR_HELP_EVENT,
ZOOM_EVENT,
- REFS_EVENT,
- APP_QUIT_REQUESTED_EVENT
+ DRAG_AND_DROP_EVENT,
+ APP_QUIT_REQUESTED_EVENT,
+ DUMMY_EVENT,
+ SCREEN_CHANGED_EVENT,
+ MENU_BAR_LEFT,
+ CLIPBOARD_CHANGED_EVENT,
};
+struct haiku_clipboard_changed_event
+{
+ char dummy;
+};
+
+struct haiku_screen_changed_event
+{
+ bigtime_t when;
+};
+
struct haiku_quit_requested_event
{
void *window;
@@ -95,8 +135,8 @@ struct haiku_quit_requested_event
struct haiku_resize_event
{
void *window;
- float px_heightf;
- float px_widthf;
+ float width;
+ float height;
};
struct haiku_expose_event
@@ -108,12 +148,11 @@ struct haiku_expose_event
int height;
};
-struct haiku_refs_event
+struct haiku_drag_and_drop_event
{
void *window;
int x, y;
- /* Free this with free! */
- char *ref;
+ void *message;
};
struct haiku_app_quit_requested_event
@@ -121,18 +160,28 @@ struct haiku_app_quit_requested_event
char dummy;
};
-#define HAIKU_MODIFIER_ALT (1)
-#define HAIKU_MODIFIER_CTRL (1 << 1)
-#define HAIKU_MODIFIER_SHIFT (1 << 2)
-#define HAIKU_MODIFIER_SUPER (1 << 3)
+struct haiku_dummy_event
+{
+ char dummy;
+};
+
+enum haiku_modifier_specification
+ {
+ HAIKU_MODIFIER_ALT = 1,
+ HAIKU_MODIFIER_CTRL = (1 << 1),
+ HAIKU_MODIFIER_SHIFT = (1 << 2),
+ HAIKU_MODIFIER_SUPER = (1 << 3),
+ };
struct haiku_key_event
{
void *window;
int modifiers;
- uint32_t mb_char;
- uint32_t unraw_mb_char;
- short kc;
+ unsigned keysym;
+ uint32_t multibyte_char;
+
+ /* Time the keypress occurred, in microseconds. */
+ bigtime_t time;
};
struct haiku_activation_event
@@ -147,16 +196,31 @@ struct haiku_mouse_motion_event
bool just_exited_p;
int x;
int y;
- uint32_t be_code;
+ bigtime_t time;
+ bool dnd_message;
+};
+
+struct haiku_menu_bar_left_event
+{
+ void *window;
+ int x, y;
+};
+
+struct haiku_menu_bar_click_event
+{
+ void *window;
+ int x, y;
};
struct haiku_button_event
{
void *window;
+ void *scroll_bar;
int btn_no;
int modifiers;
int x;
int y;
+ bigtime_t time;
};
struct haiku_iconification_event
@@ -168,8 +232,9 @@ struct haiku_iconification_event
struct haiku_move_event
{
void *window;
- int x;
- int y;
+ int x, y;
+ int decorator_width;
+ int decorator_height;
};
struct haiku_wheel_move_event
@@ -186,35 +251,34 @@ struct haiku_menu_bar_select_event
void *ptr;
};
-struct haiku_file_panel_event
-{
- void *ptr;
-};
-
struct haiku_menu_bar_help_event
{
void *window;
int mb_idx;
+ void *data;
+ bool highlight_p;
};
struct haiku_zoom_event
{
void *window;
- int x;
- int y;
- int width;
- int height;
+ int fullscreen_mode;
};
-#define FSPEC_FAMILY 1
-#define FSPEC_STYLE (1 << 1)
-#define FSPEC_SLANT (1 << 2)
-#define FSPEC_WEIGHT (1 << 3)
-#define FSPEC_SPACING (1 << 4)
-#define FSPEC_WANTED (1 << 5)
-#define FSPEC_NEED_ONE_OF (1 << 6)
-#define FSPEC_WIDTH (1 << 7)
-#define FSPEC_LANGUAGE (1 << 8)
+enum haiku_font_specification
+ {
+ FSPEC_FAMILY = 1,
+ FSPEC_STYLE = 1 << 1,
+ FSPEC_SLANT = 1 << 2,
+ FSPEC_WEIGHT = 1 << 3,
+ FSPEC_SPACING = 1 << 4,
+ FSPEC_WANTED = 1 << 5,
+ FSPEC_NEED_ONE_OF = 1 << 6,
+ FSPEC_WIDTH = 1 << 7,
+ FSPEC_LANGUAGE = 1 << 8,
+ FSPEC_INDICES = 1 << 9,
+ FSPEC_ANTIALIAS = 1 << 10,
+ };
typedef char haiku_font_family_or_style[64];
@@ -248,42 +312,124 @@ enum haiku_font_language
MAX_LANGUAGE /* This isn't a language. */
};
+enum haiku_font_weight
+ {
+ NO_WEIGHT = -1,
+ HAIKU_THIN = 0,
+ HAIKU_EXTRALIGHT = 40,
+ HAIKU_LIGHT = 50,
+ HAIKU_SEMI_LIGHT = 75,
+ HAIKU_REGULAR = 100,
+ HAIKU_SEMI_BOLD = 180,
+ HAIKU_BOLD = 200,
+ HAIKU_EXTRA_BOLD = 205,
+ HAIKU_BOOK = 400,
+ HAIKU_HEAVY = 800,
+ HAIKU_ULTRA_HEAVY = 900,
+ HAIKU_BLACK = 1000,
+ HAIKU_MEDIUM = 2000,
+ };
+
+enum haiku_fullscreen_mode
+ {
+ FULLSCREEN_MODE_NONE,
+ FULLSCREEN_MODE_WIDTH,
+ FULLSCREEN_MODE_HEIGHT,
+ FULLSCREEN_MODE_BOTH,
+ FULLSCREEN_MODE_MAXIMIZED,
+ };
+
struct haiku_font_pattern
{
+ /* Bitmask indicating which fields are set. */
int specified;
+
+ /* The next font in this list. */
struct haiku_font_pattern *next;
- /* The next two fields are only temporarily used during the font
- discovery process! Do not rely on them being correct outside
- BFont_find. */
+
+ /* The last font in the list during font lookup. */
struct haiku_font_pattern *last;
+
+ /* The next font in the list whose family differs from this one.
+ Only valid during font lookup. */
struct haiku_font_pattern *next_family;
+
+ /* The family of the font. */
haiku_font_family_or_style family;
+
+ /* The style of the font. */
haiku_font_family_or_style style;
- int weight;
+
+ /* Whether or the font is monospace. */
int mono_spacing_p;
- int want_chars_len;
- int need_one_of_len;
+
+ /* The slant of the font. */
enum haiku_font_slant slant;
+
+ /* The width of the font. */
enum haiku_font_width width;
+
+ /* The language of the font. Used during font lookup. */
enum haiku_font_language language;
- uint32_t *wanted_chars;
- uint32_t *need_one_of;
+ /* The weight of the font. */
+ enum haiku_font_weight weight;
+
+ /* List of characters that must be present in the font for the match
+ to succeed. */
+ int *wanted_chars;
+
+ /* The number of characters in `wanted_chars'. */
+ int want_chars_len;
+
+ /* List of characters. The font must fullfill at least one of
+ them for the match to succeed. */
+ int *need_one_of;
+
+ /* The number of characters in `need_one_of'. */
+ int need_one_of_len;
+
+ /* The index of the family of the font this pattern represents. */
+ int family_index;
+
+ /* The index of the style of the font this pattern represents. */
+ int style_index;
+
+ /* Temporary field used during font enumeration. */
int oblique_seen_p;
+
+ /* Whether or not to enable antialising in the font. This field is
+ special in that it's not handled by `BFont_open_pattern'. */
+ int use_antialiasing;
};
struct haiku_scroll_bar_value_event
{
void *scroll_bar;
+ void *window;
int position;
};
struct haiku_scroll_bar_drag_event
{
void *scroll_bar;
+ void *window;
int dragging_p;
};
+enum haiku_scroll_bar_part
+ {
+ HAIKU_SCROLL_BAR_UP_BUTTON,
+ HAIKU_SCROLL_BAR_DOWN_BUTTON
+ };
+
+struct haiku_scroll_bar_part_event
+{
+ void *scroll_bar;
+ void *window;
+ enum haiku_scroll_bar_part part;
+};
+
struct haiku_menu_bar_resize_event
{
void *window;
@@ -296,21 +442,10 @@ struct haiku_menu_bar_state_event
void *window;
};
-#define HAIKU_THIN 0
-#define HAIKU_ULTRALIGHT 20
-#define HAIKU_EXTRALIGHT 40
-#define HAIKU_LIGHT 50
-#define HAIKU_SEMI_LIGHT 75
-#define HAIKU_REGULAR 100
-#define HAIKU_SEMI_BOLD 180
-#define HAIKU_BOLD 200
-#define HAIKU_EXTRA_BOLD 205
-#define HAIKU_ULTRA_BOLD 210
-#define HAIKU_BOOK 400
-#define HAIKU_HEAVY 800
-#define HAIKU_ULTRA_HEAVY 900
-#define HAIKU_BLACK 1000
-#define HAIKU_MEDIUM 2000
+struct haiku_session_manager_reply
+{
+ bool quit_reply;
+};
#ifdef __cplusplus
/* Haiku's built in Height and Width functions for calculating
@@ -330,577 +465,277 @@ struct haiku_menu_bar_state_event
dimensions of a BRect, instead of relying on the broken Width and
Height functions. */
-#define BE_RECT_HEIGHT(rect) (ceil (((rect).bottom - (rect).top) + 1))
-#define BE_RECT_WIDTH(rect) (ceil (((rect).right - (rect).left) + 1))
+#define BE_RECT_HEIGHT(rect) (ceil (((rect).bottom - (rect).top) + 1))
+#define BE_RECT_WIDTH(rect) (ceil (((rect).right - (rect).left) + 1))
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C"
{
#endif
-#include <pthread.h>
#include <OS.h>
#ifdef __cplusplus
- typedef void *haiku;
+typedef void *haiku;
- extern void
- haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel);
-
- extern unsigned long
- haiku_get_pixel (haiku bitmap, int x, int y);
+extern void haiku_put_pixel (haiku, int, int, unsigned long);
+extern unsigned long haiku_get_pixel (haiku, int, int);
#endif
- extern port_id port_application_to_emacs;
-
- extern void haiku_io_init (void);
- extern void haiku_io_init_in_app_thread (void);
-
- extern void
- haiku_read_size (ssize_t *len);
-
- extern int
- haiku_read (enum haiku_event_type *type, void *buf, ssize_t len);
-
- extern int
- haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len,
- time_t timeout);
-
- extern int
- haiku_write (enum haiku_event_type type, void *buf);
-
- extern int
- haiku_write_without_signal (enum haiku_event_type type, void *buf);
-
- extern void
- rgb_color_hsl (uint32_t rgb, double *h, double *s, double *l);
-
- extern void
- hsl_color_rgb (double h, double s, double l, uint32_t *rgb);
-
- extern void *
- BBitmap_new (int width, int height, int mono_p);
-
- extern void *
- BBitmap_data (void *bitmap);
-
- extern int
- BBitmap_convert (void *bitmap, void **new_bitmap);
-
- extern void
- BBitmap_free (void *bitmap);
-
- extern void
- BBitmap_dimensions (void *bitmap, int *left, int *top,
- int *right, int *bottom, int32_t *bytes_per_row,
- int *mono_p);
-
- extern void *
- BApplication_setup (void);
-
- extern void *
- BWindow_new (void *view);
-
- extern void
- BWindow_quit (void *window);
-
- extern void
- BWindow_set_offset (void *window, int x, int y);
-
- extern void
- BWindow_iconify (void *window);
-
- extern void
- BWindow_set_visible (void *window, int visible_p);
-
- extern void
- BFont_close (void *font);
-
- extern void
- BFont_dat (void *font, int *px_size, int *min_width, int *max_width,
- int *avg_width, int *height, int *space_width, int *ascent,
- int *descent, int *underline_position, int *underline_thickness);
-
- extern int
- BFont_have_char_p (void *font, int32_t chr);
-
- extern int
- BFont_have_char_block (void *font, int32_t beg, int32_t end);
-
- extern void
- BFont_char_bounds (void *font, const char *mb_str, int *advance,
- int *lb, int *rb);
-
- extern void
- BFont_nchar_bounds (void *font, const char *mb_str, int *advance,
- int *lb, int *rb, int32_t n);
-
- extern void
- BWindow_retitle (void *window, const char *title);
-
- extern void
- BWindow_resize (void *window, int width, int height);
-
- extern void
- BWindow_activate (void *window);
-
- extern void
- BView_StartClip (void *view);
-
- extern void
- BView_EndClip (void *view);
-
- extern void
- BView_SetHighColor (void *view, uint32_t color);
-
- extern void
- BView_SetHighColorForVisibleBell (void *view, uint32_t color);
-
- extern void
- BView_FillRectangleForVisibleBell (void *view, int x, int y, int width,
- int height);
-
- extern void
- BView_SetLowColor (void *view, uint32_t color);
-
- extern void
- BView_SetPenSize (void *view, int u);
-
- extern void
- BView_SetFont (void *view, void *font);
-
- extern void
- BView_MovePenTo (void *view, int x, int y);
-
- extern void
- BView_DrawString (void *view, const char *chr, ptrdiff_t len);
-
- extern void
- BView_DrawChar (void *view, char chr);
-
- extern void
- BView_FillRectangle (void *view, int x, int y, int width, int height);
-
- extern void
- BView_FillRectangleAbs (void *view, int x, int y, int x1, int y1);
-
- extern void
- BView_FillTriangle (void *view, int x1, int y1,
- int x2, int y2, int x3, int y3);
-
- extern void
- BView_StrokeRectangle (void *view, int x, int y, int width, int height);
-
- extern void
- BView_SetViewColor (void *view, uint32_t color);
-
- extern void
- BView_ClipToRect (void *view, int x, int y, int width, int height);
-
- extern void
- BView_ClipToInverseRect (void *view, int x, int y, int width, int height);
-
- extern void
- BView_StrokeLine (void *view, int sx, int sy, int tx, int ty);
-
- extern void
- BView_CopyBits (void *view, int x, int y, int width, int height,
- int tox, int toy, int towidth, int toheight);
-
- extern void
- BView_DrawBitmap (void *view, void *bitmap, int x, int y,
- int width, int height, int vx, int vy, int vwidth,
- int vheight);
-
- extern void
- BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
- int y, int width, int height);
-
- extern void
- BView_DrawMask (void *src, void *view,
- int x, int y, int width, int height,
- int vx, int vy, int vwidth, int vheight,
- uint32_t color);
-
- extern void *
- BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color,
- double rot, int desw, int desh);
-
- extern void
- BScreen_px_dim (int *width, int *height);
-
- extern void
- BView_resize_to (void *view, int width, int height);
-
- /* Functions for creating and freeing cursors. */
- extern void *
- BCursor_create_default (void);
-
- extern void *
- BCursor_from_id (enum haiku_cursor cursor);
-
- extern void *
- BCursor_create_modeline (void);
-
- extern void *
- BCursor_create_i_beam (void);
-
- extern void *
- BCursor_create_progress_cursor (void);
-
- extern void *
- BCursor_create_grab (void);
-
- extern void
- BCursor_delete (void *cursor);
-
- extern void
- BView_set_view_cursor (void *view, void *cursor);
-
- extern void
- BWindow_Flush (void *window);
-
- extern void
- BMapKey (uint32_t kc, int *non_ascii_p, unsigned *code);
-
- extern void *
- BScrollBar_make_for_view (void *view, int horizontal_p,
- int x, int y, int x1, int y1,
- void *scroll_bar_ptr);
-
- extern void
- BScrollBar_delete (void *sb);
-
- extern void
- BView_move_frame (void *view, int x, int y, int x1, int y1);
-
- extern void
- BView_scroll_bar_update (void *sb, int portion, int whole, int position);
-
- extern int
- BScrollBar_default_size (int horizontal_p);
-
- extern void
- BView_invalidate (void *view);
-
- extern void
- BView_draw_lock (void *view);
-
- extern void
- BView_draw_unlock (void *view);
-
- extern void
- BWindow_center_on_screen (void *window);
-
- extern void
- BView_mouse_moved (void *view, int x, int y, uint32_t transit);
-
- extern void
- BView_mouse_down (void *view, int x, int y);
-
- extern void
- BView_mouse_up (void *view, int x, int y);
-
- extern void
- BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h);
-
- extern void
- haiku_font_pattern_free (struct haiku_font_pattern *pt);
-
- extern struct haiku_font_pattern *
- BFont_find (struct haiku_font_pattern *pt);
-
- extern int
- BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size);
-
- extern void
- BFont_populate_fixed_family (struct haiku_font_pattern *ptn);
-
- extern void
- BFont_populate_plain_family (struct haiku_font_pattern *ptn);
-
- extern void
- BView_publish_scroll_bar (void *view, int x, int y, int width, int height);
-
- extern void
- BView_forget_scroll_bar (void *view, int x, int y, int width, int height);
-
- extern void
- BView_get_mouse (void *view, int *x, int *y);
-
- extern void
- BView_convert_to_screen (void *view, int *x, int *y);
-
- extern void
- BView_convert_from_screen (void *view, int *x, int *y);
-
- extern void
- BWindow_change_decoration (void *window, int decorate_p);
-
- extern void
- BWindow_set_tooltip_decoration (void *window);
-
- extern void
- BWindow_set_avoid_focus (void *window, int avoid_focus_p);
-
- extern void
- BView_emacs_delete (void *view);
-
- extern uint32_t
- haiku_current_workspace (void);
-
- extern uint32_t
- BWindow_workspaces (void *window);
-
- extern void *
- BPopUpMenu_new (const char *name);
-
- extern void
- BMenu_add_item (void *menu, const char *label, void *ptr, bool enabled_p,
- bool marked_p, bool mbar_p, void *mbw_ptr, const char *key,
- const char *help);
-
- extern void
- BMenu_add_separator (void *menu);
-
- extern void *
- BMenu_new_submenu (void *menu, const char *label, bool enabled_p);
-
- extern void *
- BMenu_new_menu_bar_submenu (void *menu, const char *label);
-
- extern int
- BMenu_count_items (void *menu);
-
- extern void *
- BMenu_item_at (void *menu, int idx);
-
- extern void *
- BMenu_run (void *menu, int x, int y);
-
- extern void
- BPopUpMenu_delete (void *menu);
-
- extern void *
- BMenuBar_new (void *view);
-
- extern void
- BMenu_delete_all (void *menu);
-
- extern void
- BMenuBar_delete (void *menubar);
-
- extern void
- BMenu_item_set_label (void *item, const char *label);
-
- extern void *
- BMenu_item_get_menu (void *item);
-
- extern void
- BMenu_delete_from (void *menu, int start, int count);
-
- extern void
- haiku_ring_bell (void);
-
- extern void *
- BAlert_new (const char *text, enum haiku_alert_type type);
-
- extern void *
- BAlert_add_button (void *alert, const char *text);
-
- extern int32_t
- BAlert_go (void *alert);
-
- extern void
- BButton_set_enabled (void *button, int enabled_p);
-
- extern void
- BView_set_tooltip (void *view, const char *tooltip);
-
- extern void
- BAlert_delete (void *alert);
-
- extern void
- BScreen_res (double *rrsx, double *rrsy);
-
- extern void
- EmacsWindow_parent_to (void *window, void *other_window);
-
- extern void
- EmacsWindow_unparent (void *window);
-
- extern int
- BFont_string_width (void *font, const char *utf8);
-
- extern void
- be_get_version_string (char *version, int len);
-
- extern int
- be_get_display_planes (void);
-
- extern int
- be_get_display_color_cells (void);
-
- extern void
- be_warp_pointer (int x, int y);
-
- extern void
- EmacsWindow_move_weak_child (void *window, void *child, int xoff, int yoff);
-
- extern void
- EmacsView_set_up_double_buffering (void *vw);
-
- extern void
- EmacsView_disable_double_buffering (void *vw);
-
- extern void
- EmacsView_flip_and_blit (void *vw);
-
- extern int
- EmacsView_double_buffered_p (void *vw);
-
- extern char *
- be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
- int dir_only_p, void *window, const char *save_text,
- const char *prompt,
- void (*block_input_function) (void),
- void (*unblock_input_function) (void),
- void (*maybe_quit_function) (void));
-
- extern void
- record_c_unwind_protect_from_cxx (void (*) (void *), void *);
-
- extern ptrdiff_t
- c_specpdl_idx_from_cxx (void);
-
- extern void
- c_unbind_to_nil_from_cxx (ptrdiff_t idx);
-
- extern void
- EmacsView_do_visible_bell (void *view, uint32_t color);
-
- extern void
- BWindow_zoom (void *window);
-
- extern void
- EmacsWindow_make_fullscreen (void *window, int fullscreen_p);
-
- extern void
- EmacsWindow_unzoom (void *window);
+extern port_id port_application_to_emacs;
+extern port_id port_popup_menu_to_emacs;
+extern port_id port_emacs_to_session_manager;
+
+extern void haiku_io_init (void);
+extern void haiku_io_init_in_app_thread (void);
+
+extern void haiku_read_size (ssize_t *, bool);
+
+extern int haiku_read (enum haiku_event_type *, void *, ssize_t);
+extern int haiku_read_with_timeout (enum haiku_event_type *, void *, ssize_t,
+ bigtime_t, bool);
+extern int haiku_write (enum haiku_event_type, void *);
+extern int haiku_write_without_signal (enum haiku_event_type, void *, bool);
+
+extern void rgb_color_hsl (uint32_t, double *, double *, double *);
+extern void hsl_color_rgb (double, double, double, uint32_t *);
+
+extern void *BBitmap_new (int, int, int);
+extern void *BBitmap_data (void *);
+extern int BBitmap_convert (void *, void **);
+extern void be_draw_cross_on_pixmap (void *, int, int, int, int,
+ uint32_t);
+
+extern void BBitmap_free (void *);
+
+extern void BBitmap_dimensions (void *, int *, int *, int *, int *,
+ int32_t *, int *);
+extern void *BApplication_setup (void);
+extern void *BWindow_new (void **);
+extern void BWindow_quit (void *);
+
+extern void BWindow_set_offset (void *, int, int);
+extern void BWindow_iconify (void *);
+extern void BWindow_set_visible (void *, int);
+extern void BWindow_retitle (void *, const char *);
+extern void BWindow_resize (void *, int, int);
+extern void BWindow_activate (void *);
+extern void BWindow_center_on_screen (void *);
+extern void BWindow_change_decoration (void *, int);
+extern void BWindow_set_tooltip_decoration (void *);
+extern void BWindow_set_avoid_focus (void *, int);
+extern void BWindow_set_size_alignment (void *, int, int);
+extern void BWindow_sync (void *);
+extern void BWindow_send_behind (void *, void *);
+extern bool BWindow_is_active (void *);
+extern void BWindow_set_override_redirect (void *, bool);
+extern void BWindow_dimensions (void *, int *, int *);
+extern void BWindow_set_z_group (void *, enum haiku_z_group);
+extern void BWindow_set_sticky (void *, bool);
+extern void BWindow_Flush (void *);
+
+extern void BFont_close (void *);
+extern void BFont_metrics (void *, int *, int *, int *, int *,
+ int *, int *, int *, int *, int *, int *);
+extern int BFont_have_char_p (void *, int32_t);
+extern int BFont_have_char_block (void *, int32_t, int32_t);
+extern void BFont_char_bounds (void *, const char *, int *, int *, int *);
+extern void BFont_nchar_bounds (void *, const char *, int *, int *,
+ int *, int32_t);
+extern struct haiku_font_pattern *BFont_find (struct haiku_font_pattern *);
+
+extern void BView_StartClip (void *);
+extern void BView_EndClip (void *);
+extern void BView_SetHighColor (void *, uint32_t);
+extern void BView_SetLowColor (void *, uint32_t);
+extern void BView_SetPenSize (void *, int);
+extern void BView_SetFont (void *, void *);
+extern void BView_MovePenTo (void *, int, int);
+extern void BView_DrawString (void *, const char *, ptrdiff_t);
+extern void BView_DrawChar (void *, char);
+extern void BView_FillRectangle (void *, int, int, int, int);
+extern void BView_FillRectangleAbs (void *, int, int, int, int);
+extern void BView_FillTriangle (void *, int, int, int, int, int, int);
+extern void BView_StrokeRectangle (void *, int, int, int, int);
+extern void BView_SetViewColor (void *, uint32_t);
+extern void BView_ClipToRect (void *, int, int, int, int);
+extern void BView_ClipToInverseRect (void *, int, int, int, int);
+extern void BView_StrokeLine (void *, int, int, int, int);
+extern void BView_CopyBits (void *, int, int, int, int, int, int, int, int);
+extern void BView_InvertRect (void *, int, int, int, int);
+extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int,
+ int, int, bool);
+extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int);
+extern void BView_DrawBitmapTiled (void *, void *, int, int,
+ int, int, int, int, int, int);
+
+extern void BView_resize_to (void *, int, int);
+extern void BView_set_view_cursor (void *, void *);
+extern void BView_move_frame (void *, int, int, int, int);
+extern void BView_scroll_bar_update (void *, int, int, int, int, bool);
+
+extern void *be_transform_bitmap (void *, void *, uint32_t, double,
+ int, int, bool);
+extern void be_apply_affine_transform (void *, double, double, double,
+ double, double, double);
+extern void be_apply_inverse_transform (double (*)[3], int, int, int *, int *);
+extern void be_draw_image_mask (void *, void *, int, int, int, int, int, int,
+ int, int, uint32_t);
+extern void be_draw_bitmap_with_mask (void *, void *, void *, int, int, int,
+ int, int, int, int, int, bool);
+
+extern void be_get_display_resolution (double *, double *);
+extern void be_get_screen_dimensions (int *, int *);
+
+/* Functions for creating and freeing cursors. */
+extern void *be_create_cursor_from_id (int);
+extern void *be_create_pixmap_cursor (void *, int, int);
+extern void be_delete_cursor (void *);
+
+extern void *be_make_scroll_bar_for_view (void *, int, int, int, int, int);
+extern void BScrollBar_delete (void *);
+extern int BScrollBar_default_size (int);
+
+extern void BView_invalidate (void *);
+extern void BView_draw_lock (void *, bool, int, int, int, int);
+extern void BView_invalidate_region (void *, int, int, int, int);
+extern void BView_draw_unlock (void *);
+extern void BBitmap_import_fringe_bitmap (void *, unsigned short *, int, int);
+
+extern void haiku_font_pattern_free (struct haiku_font_pattern *);
+
+extern int BFont_open_pattern (struct haiku_font_pattern *, void **, float);
+extern void BFont_populate_fixed_family (struct haiku_font_pattern *);
+extern void BFont_populate_plain_family (struct haiku_font_pattern *);
+
+extern void BView_publish_scroll_bar (void *, int, int, int, int);
+extern void BView_forget_scroll_bar (void *, int, int, int, int);
+extern bool BView_inside_scroll_bar (void *, int, int);
+extern void BView_get_mouse (void *, int *, int *);
+extern void BView_convert_to_screen (void *, int *, int *);
+extern void BView_convert_from_screen (void *, int *, int *);
+
+extern void BView_emacs_delete (void *);
+
+extern void *BPopUpMenu_new (const char *);
+
+extern void BMenu_add_item (void *, const char *, void *, bool,
+ bool, bool, void *, const char *,
+ const char *);
+extern void BMenu_add_separator (void *);
+extern void *BMenu_new_submenu (void *, const char *, bool);
+extern void *BMenu_new_menu_bar_submenu (void *, const char *);
+extern int BMenu_count_items (void *);
+extern void *BMenu_item_at (void *, int);
+extern void *BMenu_run (void *, int, int, void (*) (void *, void *),
+ void (*) (void), void (*) (void),
+ struct timespec (*) (void), void *);
+extern void BPopUpMenu_delete (void *);
+extern void *BMenuBar_new (void *);
+extern void BMenu_delete_all (void *);
+extern void BMenuBar_delete (void *);
+extern void BMenu_item_set_label (void *, const char *);
+extern void *BMenu_item_get_menu (void *);
+extern void BMenu_delete_from (void *, int, int);
+
+extern void haiku_ring_bell (void);
+
+extern void *BAlert_new (const char *, enum haiku_alert_type);
+extern void *BAlert_add_button (void *, const char *);
+extern void BAlert_set_offset_spacing (void *);
+extern int32 BAlert_go (void *, void (*) (void), void (*) (void),
+ void (*) (void));
+extern void BButton_set_enabled (void *, int);
+extern void BView_set_tooltip (void *, const char *);
+extern void BView_show_tooltip (void *);
+extern void be_show_sticky_tooltip (void *, const char *, int, int);
+
+extern void BAlert_delete (void *);
+
+extern void EmacsWindow_parent_to (void *, void *);
+extern void EmacsWindow_unparent (void *);
+extern void EmacsWindow_move_weak_child (void *, void *, int, int);
+
+extern void be_get_version_string (char *, int);
+extern int be_get_display_planes (void);
+extern int be_get_display_color_cells (void);
+extern bool be_is_display_grayscale (void);
+extern void be_warp_pointer (int, int);
+
+extern void EmacsView_set_up_double_buffering (void *);
+extern void EmacsView_disable_double_buffering (void *);
+extern void EmacsView_flip_and_blit (void *);
+extern int EmacsView_double_buffered_p (void *);
+
+extern char *be_popup_file_dialog (int, const char *, int,
+ int, void *, const char *,
+ const char *, void (*) (void));
#ifdef HAVE_NATIVE_IMAGE_API
- extern int
- be_can_translate_type_to_bitmap_p (const char *mime);
-
- extern void *
- be_translate_bitmap_from_file_name (const char *filename);
-
- extern void *
- be_translate_bitmap_from_memory (const void *buf, size_t bytes);
+extern int be_can_translate_type_to_bitmap_p (const char *);
+extern void *be_translate_bitmap_from_file_name (const char *);
+extern void *be_translate_bitmap_from_memory (const void *, size_t);
#endif
- extern void
- BMenuBar_start_tracking (void *mbar);
-
- extern size_t
- BBitmap_bytes_length (void *bitmap);
-
- extern void
- BView_show_tooltip (void *view);
+extern bool BMenuBar_start_tracking (void *);
+extern size_t BBitmap_bytes_length (void *);
#ifdef USE_BE_CAIRO
- extern cairo_surface_t *
- EmacsView_cairo_surface (void *view);
-
- extern void
- BView_cr_dump_clipping (void *view, cairo_t *ctx);
-
- extern void
- EmacsWindow_begin_cr_critical_section (void *window);
-
- extern void
- EmacsWindow_end_cr_critical_section (void *window);
+extern cairo_t *EmacsView_cairo_context (void *);
+extern void BView_cr_dump_clipping (void *, cairo_t *);
+extern void EmacsWindow_begin_cr_critical_section (void *);
+extern void EmacsWindow_end_cr_critical_section (void *);
#endif
- extern void
- BView_set_and_show_sticky_tooltip (void *view, const char *tooltip,
- int x, int y);
-
- extern void
- BMenu_add_title (void *menu, const char *text);
-
- extern int
- be_plain_font_height (void);
-
- extern int
- be_string_width_with_plain_font (const char *str);
-
- extern int
- be_get_display_screens (void);
-
- extern void
- BWindow_set_min_size (void *window, int width, int height);
-
- extern void
- BWindow_set_size_alignment (void *window, int align_width, int align_height);
-
- extern void
- BWindow_sync (void *window);
-
- extern void
- BWindow_send_behind (void *window, void *other_window);
-
- extern bool
- BWindow_is_active (void *window);
-
- extern bool
- be_use_subpixel_antialiasing (void);
-
+extern void BMenu_add_title (void *, const char *);
+
+extern int be_plain_font_height (void);
+extern int be_string_width_with_plain_font (const char *);
+extern void be_init_font_data (void);
+extern void be_evict_font_cache (void);
+extern int be_get_display_screens (void);
+extern bool be_use_subpixel_antialiasing (void);
+extern const char *be_find_setting (const char *);
+extern haiku_font_family_or_style *be_list_font_families (size_t *);
+extern void be_font_style_to_flags (char *, struct haiku_font_pattern *);
+extern void *be_open_font_at_index (int, int, float);
+extern void be_set_font_antialiasing (void *, bool);
+extern int be_get_ui_color (const char *, uint32_t *);
+
+extern void BMessage_delete (void *);
+
+extern bool be_drag_message (void *, void *, bool, void (*) (void),
+ void (*) (void), void (*) (void),
+ bool (*) (void));
+extern bool be_drag_and_drop_in_progress (void);
+
+extern bool be_replay_menu_bar_event (void *, struct haiku_menu_bar_click_event *);
+extern bool be_select_font (void (*) (void), bool (*) (void),
+ haiku_font_family_or_style *,
+ haiku_font_family_or_style *,
+ int *, bool, int, int, int,
+ bool, bool *);
+
+extern int be_find_font_indices (struct haiku_font_pattern *, int *, int *);
+extern status_t be_roster_launch (const char *, const char *, char **,
+ ptrdiff_t, void *, team_id *);
+extern void be_get_window_decorator_dimensions (void *, int *, int *, int *, int *);
+extern void be_get_window_decorator_frame (void *, int *, int *, int *, int *);
+extern void be_send_move_frame_event (void *);
+extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode);
+
+extern void be_lock_window (void *);
+extern void be_unlock_window (void *);
+extern bool be_get_explicit_workarea (int *, int *, int *, int *);
#ifdef __cplusplus
- extern void *
- find_appropriate_view_for_draw (void *vw);
}
-extern _Noreturn void
-gui_abort (const char *msg);
+extern _Noreturn void gui_abort (const char *);
+extern void *find_appropriate_view_for_draw (void *);
#endif /* _cplusplus */
-/* Borrowed from X.Org keysymdef.h */
-#define XK_BackSpace 0xff08 /* Back space, back char */
-#define XK_Tab 0xff09
-#define XK_Linefeed 0xff0a /* Linefeed, LF */
-#define XK_Clear 0xff0b
-#define XK_Return 0xff0d /* Return, enter */
-#define XK_Pause 0xff13 /* Pause, hold */
-#define XK_Scroll_Lock 0xff14
-#define XK_Sys_Req 0xff15
-#define XK_Escape 0xff1b
-#define XK_Delete 0xffff /* Delete, rubout */
-#define XK_Home 0xff50
-#define XK_Left 0xff51 /* Move left, left arrow */
-#define XK_Up 0xff52 /* Move up, up arrow */
-#define XK_Right 0xff53 /* Move right, right arrow */
-#define XK_Down 0xff54 /* Move down, down arrow */
-#define XK_Prior 0xff55 /* Prior, previous */
-#define XK_Page_Up 0xff55
-#define XK_Next 0xff56 /* Next */
-#define XK_Page_Down 0xff56
-#define XK_End 0xff57 /* EOL */
-#define XK_Begin 0xff58 /* BOL */
-#define XK_Select 0xff60 /* Select, mark */
-#define XK_Print 0xff61
-#define XK_Execute 0xff62 /* Execute, run, do */
-#define XK_Insert 0xff63 /* Insert, insert here */
-#define XK_Undo 0xff65
-#define XK_Redo 0xff66 /* Redo, again */
-#define XK_Menu 0xff67
-#define XK_Find 0xff68 /* Find, search */
-#define XK_Cancel 0xff69 /* Cancel, stop, abort, exit */
-#define XK_Help 0xff6a /* Help */
-#define XK_Break 0xff6b
-#define XK_Mode_switch 0xff7e /* Character set switch */
-#define XK_script_switch 0xff7e /* Alias for mode_switch */
-#define XK_Num_Lock 0xff7f
-#define XK_F1 0xffbe
-
#endif /* _HAIKU_SUPPORT_H_ */
+
+// Local Variables:
+// eval: (setf (alist-get 'inextern-lang c-offsets-alist) 0)
+// End:
diff --git a/src/haikufns.c b/src/haikufns.c
index 4a0d2272d08..e0a65b499f4 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -34,6 +34,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "haiku_support.h"
#include "termhooks.h"
+#include "bitmaps/leftptr.xbm"
+#include "bitmaps/leftpmsk.xbm"
+
#include <stdlib.h>
#include <kernel/OS.h>
@@ -45,7 +48,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
/* The frame of the currently visible tooltip. */
-static Lisp_Object tip_frame;
+Lisp_Object tip_frame;
+
+/* The X and Y deltas of the last call to `x-show-tip'. */
+Lisp_Object tip_dx, tip_dy;
/* The window-system window corresponding to the frame of the
currently visible tooltip. */
@@ -64,11 +70,10 @@ static Lisp_Object tip_last_frame;
/* PARMS argument of last `x-show-tip' call. */
static Lisp_Object tip_last_parms;
-static void
-haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
-static void
-haiku_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name);
+static void haiku_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
+static void haiku_set_title (struct frame *, Lisp_Object, Lisp_Object);
+/* The number of references to an image cache. */
static ptrdiff_t image_cache_refcount;
static Lisp_Object
@@ -94,7 +99,7 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
Lisp_Object value
= gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (r[i].tem, value), parms);
}
}
@@ -102,6 +107,22 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo,
return parms;
}
+/* Update the left and top offsets of F after its decorators
+ change. */
+static void
+haiku_update_after_decoration_change (struct frame *f)
+{
+ /* Don't reset offsets during initial frame creation, since the
+ contents of f->left_pos and f->top_pos won't be applied to the
+ window until `x-create-frame' finishes, so setting them here will
+ overwrite the offsets that the window should be moved to. */
+
+ if (!FRAME_OUTPUT_DATA (f)->configury_done)
+ return;
+
+ be_send_move_frame_event (FRAME_HAIKU_WINDOW (f));
+}
+
void
haiku_change_tool_bar_height (struct frame *f, int height)
{
@@ -250,12 +271,32 @@ haiku_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
haiku_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
}
+void
+gamma_correct (struct frame *f, Emacs_Color *color)
+{
+ if (f->gamma)
+ {
+ color->red = (pow (color->red / 65535.0, f->gamma)
+ * 65535.0 + 0.5);
+ color->green = (pow (color->green / 65535.0, f->gamma)
+ * 65535.0 + 0.5);
+ color->blue = (pow (color->blue / 65535.0, f->gamma)
+ * 65535.0 + 0.5);
+ color->pixel = RGB_TO_ULONG (color->red / 256,
+ color->green / 256,
+ color->blue / 256);
+ }
+}
int
haiku_get_color (const char *name, Emacs_Color *color)
{
unsigned short r16, g16, b16;
- Lisp_Object tem;
+ Lisp_Object tem, col;
+ int32 clr, rc;
+ uint32_t ui_color;
+ ptrdiff_t size, i;
+ Lisp_Object string;
if (parse_color_spec (name, &r16, &g16, &b16))
{
@@ -272,10 +313,11 @@ haiku_get_color (const char *name, Emacs_Color *color)
tem = x_display_list->color_map;
for (; CONSP (tem); tem = XCDR (tem))
{
- Lisp_Object col = XCAR (tem);
+ col = XCAR (tem);
+
if (CONSP (col) && !xstrcasecmp (SSDATA (XCAR (col)), name))
{
- int32_t clr = XFIXNUM (XCDR (col));
+ clr = XFIXNUM (XCDR (col));
color->pixel = clr;
color->red = RED_FROM_ULONG (clr) * 257;
color->green = GREEN_FROM_ULONG (clr) * 257;
@@ -284,11 +326,34 @@ haiku_get_color (const char *name, Emacs_Color *color)
return 0;
}
}
-
unblock_input ();
}
- return 1;
+ rc = 1;
+ if (VECTORP (Vhaiku_allowed_ui_colors))
+ {
+ size = ASIZE (Vhaiku_allowed_ui_colors);
+
+ for (i = 0; i < size; ++i)
+ {
+ string = AREF (Vhaiku_allowed_ui_colors, i);
+
+ block_input ();
+ if (STRINGP (string) && !strcmp (SSDATA (string), name))
+ rc = be_get_ui_color (name, &ui_color);
+ unblock_input ();
+ }
+ }
+
+ if (!rc)
+ {
+ color->pixel = ui_color;
+ color->red = RED_FROM_ULONG (ui_color) * 257;
+ color->green = GREEN_FROM_ULONG (ui_color) * 257;
+ color->blue = BLUE_FROM_ULONG (ui_color) * 257;
+ }
+
+ return rc;
}
static struct haiku_display_info *
@@ -296,15 +361,15 @@ haiku_display_info_for_name (Lisp_Object name)
{
CHECK_STRING (name);
- if (!NILP (Fstring_equal (name, build_string ("be"))))
+ if (!strcmp (SSDATA (name), "be"))
{
- if (!x_display_list)
+ if (x_display_list)
return x_display_list;
- error ("Be windowing not initialized");
+ return haiku_term_init ();
}
- error ("Be displays can only be named \"be\"");
+ error ("Haiku displays can only be named \"be\"");
}
static struct haiku_display_info *
@@ -321,14 +386,14 @@ check_haiku_display_info (Lisp_Object object)
else if (x_display_list)
dpyinfo = x_display_list;
else
- error ("Be windowing not present");
+ error ("Haiku windowing not present");
}
else if (TERMINALP (object))
{
struct terminal *t = decode_live_terminal (object);
if (t->type != output_haiku)
- error ("Terminal %d is not a Be display", t->id);
+ error ("Terminal %d is not a Haiku display", t->id);
dpyinfo = t->display_info.haiku;
}
@@ -396,8 +461,8 @@ haiku_set_child_frame_border_width (struct frame *f,
}
static void
-haiku_set_parent_frame (struct frame *f,
- Lisp_Object new_value, Lisp_Object old_value)
+haiku_set_parent_frame (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
{
struct frame *p = NULL;
block_input ();
@@ -418,19 +483,68 @@ haiku_set_parent_frame (struct frame *f,
}
if (!NILP (old_value))
- EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f));
+ {
+ EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f));
+ FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
+ }
+
if (!NILP (new_value))
{
EmacsWindow_parent_to (FRAME_HAIKU_WINDOW (f),
FRAME_HAIKU_WINDOW (p));
BWindow_set_offset (FRAME_HAIKU_WINDOW (f),
f->left_pos, f->top_pos);
+
+ /* This isn't actually used for anything, but makes the
+ `parent-id' parameter correct. */
+ FRAME_OUTPUT_DATA (f)->parent_desc = FRAME_HAIKU_WINDOW (p);
}
fset_parent_frame (f, new_value);
unblock_input ();
}
static void
+haiku_set_z_group (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ int rc;
+
+ /* Tooltip frames can't have Z groups, since the window feel is
+ overridden during frame creation. */
+ if (FRAME_TOOLTIP_P (f))
+ return;
+
+ rc = 1;
+ block_input ();
+
+ if (NILP (new_value))
+ {
+ BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_NONE);
+ FRAME_Z_GROUP (f) = z_group_none;
+ }
+ else if (EQ (new_value, Qabove))
+ {
+ BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_ABOVE);
+ FRAME_Z_GROUP (f) = z_group_above;
+ }
+ else if (EQ (new_value, Qbelow))
+ {
+ BWindow_set_z_group (FRAME_HAIKU_WINDOW (f), Z_GROUP_BELOW);
+ FRAME_Z_GROUP (f) = z_group_below;
+ }
+ else
+ rc = 0;
+
+ unblock_input ();
+
+ if (!rc)
+ error ("Invalid z-group specification");
+
+ /* Setting the Z-group can change the frame's decorator. */
+ haiku_update_after_decoration_change (f);
+}
+
+static void
haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
haiku_set_name (f, arg, 1);
@@ -439,15 +553,22 @@ haiku_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
static void
haiku_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- block_input ();
if (!EQ (new_value, old_value))
FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
+ block_input ();
if (FRAME_HAIKU_WINDOW (f))
- {
- BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f),
- FRAME_NO_ACCEPT_FOCUS (f));
- }
+ BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (f),
+ FRAME_NO_ACCEPT_FOCUS (f));
+ unblock_input ();
+}
+
+static void
+initial_setup_back_buffer (struct frame *f)
+{
+ block_input ();
+ if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
+ EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
unblock_input ();
}
@@ -499,37 +620,34 @@ unwind_create_tip_frame (Lisp_Object frame)
tip_frame = Qnil;
}
-static void
-haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+static unsigned long
+haiku_decode_color (struct frame *f, Lisp_Object color_name)
{
- struct haiku_output *output = FRAME_OUTPUT_DATA (f);
- unsigned long old_fg;
+ Emacs_Color cdef;
- Emacs_Color color;
+ CHECK_STRING (color_name);
- if (haiku_get_color (SSDATA (arg), &color))
- {
- store_frame_param (f, Qforeground_color, oldval);
- unblock_input ();
- error ("Bad color");
- }
+ if (!haiku_get_color (SSDATA (color_name), &cdef))
+ return cdef.pixel;
+ signal_error ("Undefined color", color_name);
+}
+
+static void
+haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ struct haiku_output *output;
+ unsigned long fg, old_fg;
+
+ fg = haiku_decode_color (f, arg);
old_fg = FRAME_FOREGROUND_PIXEL (f);
- FRAME_FOREGROUND_PIXEL (f) = color.pixel;
+ FRAME_FOREGROUND_PIXEL (f) = fg;
+ output = FRAME_OUTPUT_DATA (f);
if (FRAME_HAIKU_WINDOW (f))
{
-
- block_input ();
if (output->cursor_color.pixel == old_fg)
- {
- output->cursor_color.pixel = old_fg;
- output->cursor_color.red = RED_FROM_ULONG (old_fg);
- output->cursor_color.green = GREEN_FROM_ULONG (old_fg);
- output->cursor_color.blue = BLUE_FROM_ULONG (old_fg);
- }
-
- unblock_input ();
+ haiku_query_color (fg, &output->cursor_color);
update_face_from_frame_parameter (f, Qforeground_color, arg);
@@ -538,35 +656,38 @@ haiku_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval
}
}
-static void
-unwind_popup (void)
-{
- if (!popup_activated_p)
- emacs_abort ();
- --popup_activated_p;
-}
-
static Lisp_Object
-haiku_create_frame (Lisp_Object parms, int ttip_p)
+haiku_create_frame (Lisp_Object parms)
{
- struct frame *f;
+ struct frame *f, *cascade_target;
Lisp_Object frame, tem;
Lisp_Object name;
bool minibuffer_only = false;
- bool face_change_before = face_change;
long window_prompting = 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object display;
struct haiku_display_info *dpyinfo = NULL;
struct kboard *kb;
+ if (x_display_list->focused_frame)
+ cascade_target = x_display_list->focused_frame;
+ else if (x_display_list->focus_event_frame)
+ cascade_target = x_display_list->focus_event_frame;
+ else
+ cascade_target = NULL;
+
+ /* Always cascade from the most toplevel frame. */
+
+ while (cascade_target && FRAME_PARENT_FRAME (cascade_target))
+ cascade_target = FRAME_PARENT_FRAME (cascade_target);
+
parms = Fcopy_alist (parms);
Vx_resource_name = Vinvocation_name;
display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
RES_TYPE_STRING);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_haiku_display_info (display);
kb = dpyinfo->terminal->kboard;
@@ -577,15 +698,13 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0,
RES_TYPE_STRING);
if (!STRINGP (name)
- && ! EQ (name, Qunbound)
+ && ! BASE_EQ (name, Qunbound)
&& ! NILP (name))
error ("Invalid frame name--not a string or nil");
if (STRINGP (name))
Vx_resource_name = name;
- block_input ();
-
/* make_frame_without_minibuffer can run Lisp code and garbage collect. */
/* No need to protect DISPLAY because that's not used after passing
it to make_frame_without_minibuffer. */
@@ -593,10 +712,8 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer,
"minibuffer", "Minibuffer",
RES_TYPE_SYMBOL);
- if (ttip_p)
- f = make_frame (0);
- else if (EQ (tem, Qnone) || NILP (tem))
- f = make_frame_without_minibuffer (Qnil, kb, display);
+ if (EQ (tem, Qnone) || NILP (tem))
+ f = make_frame_without_minibuffer (Qnil, kb, display);
else if (EQ (tem, Qonly))
{
f = make_minibuffer_frame ();
@@ -606,41 +723,30 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
f = make_frame_without_minibuffer (tem, kb, display);
else
f = make_frame (1);
+
XSETFRAME (frame, f);
f->terminal = dpyinfo->terminal;
f->output_method = output_haiku;
f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
-
- f->output_data.haiku->pending_zoom_x = INT_MIN;
- f->output_data.haiku->pending_zoom_y = INT_MIN;
- f->output_data.haiku->pending_zoom_width = INT_MIN;
- f->output_data.haiku->pending_zoom_height = INT_MIN;
-
- if (ttip_p)
- f->wants_modeline = false;
+ f->output_data.haiku->wait_for_event_type = -1;
+ f->output_data.haiku->relief_background = -1;
fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name,
"iconName", "Title",
RES_TYPE_STRING));
- if (! STRINGP (f->icon_name) || ttip_p)
+ if (! STRINGP (f->icon_name))
fset_icon_name (f, Qnil);
FRAME_DISPLAY_INFO (f) = dpyinfo;
/* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
- if (!ttip_p)
- record_unwind_protect (unwind_create_frame, frame);
- else
- record_unwind_protect (unwind_create_tip_frame, frame);
-
- FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
- FRAME_OUTPUT_DATA (f)->explicit_parent = 0;
+ record_unwind_protect (unwind_create_frame, frame);
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
{
fset_name (f, Vinvocation_name);
f->explicit_name = 0;
@@ -660,8 +766,6 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
#endif
register_font_driver (&haikufont_driver, f);
- f->tooltip = ttip_p;
-
image_cache_refcount =
FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
@@ -670,21 +774,25 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
FRAME_RIF (f)->default_font_parameter (f, parms);
- unblock_input ();
+ if (!FRAME_FONT (f))
+ {
+ delete_frame (frame, Qnoelisp);
+ error ("Invalid frame font");
+ }
gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
"borderwidth", "BorderWidth", RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (ttip_p ? 1 : 2),
+ gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (0),
"internalBorderWidth", "InternalBorderWidth",
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
"childFrameBorderWidth", "childFrameBorderWidth",
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
- NULL, NULL, RES_TYPE_NUMBER);
+ NULL, NULL, RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
- NULL, NULL, RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qvertical_scroll_bars, !ttip_p ? Qt : Qnil,
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
"verticalScrollBars", "VerticalScrollBars",
RES_TYPE_SYMBOL);
gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
@@ -694,13 +802,15 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
"foreground", "Foreground", RES_TYPE_STRING);
gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
"background", "Background", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"),
+ "pointerColor", "Foreground", RES_TYPE_STRING);
gui_default_parameter (f, parms, Qline_spacing, Qnil,
"lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qleft_fringe, Qnil,
"leftFringe", "LeftFringe", RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qright_fringe, Qnil,
"rightFringe", "RightFringe", RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qno_special_glyphs, ttip_p ? Qnil : Qt,
+ gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
NULL, NULL, RES_TYPE_BOOLEAN);
init_frame_faces (f);
@@ -714,120 +824,72 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
RES_TYPE_NUMBER);
if (FIXNUMP (tem))
store_frame_param (f, Qmin_height, tem);
+
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
Qx_create_frame_1);
- if (!ttip_p)
- {
- gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
- gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
- NULL, NULL, RES_TYPE_BOOLEAN);
- gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
- NULL, NULL, RES_TYPE_BOOLEAN);
-
- /* The resources controlling the menu-bar, tool-bar, and tab-bar are
- processed specially at startup, and reflected in the mode
- variables; ignore them here. */
- gui_default_parameter (f, parms, Qmenu_bar_lines,
- NILP (Vmenu_bar_mode)
- ? make_fixnum (0) : make_fixnum (1),
- NULL, NULL, RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qtab_bar_lines,
- NILP (Vtab_bar_mode)
- ? make_fixnum (0) : make_fixnum (1),
- NULL, NULL, RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qtool_bar_lines,
- NILP (Vtool_bar_mode)
- ? make_fixnum (0) : make_fixnum (1),
- NULL, NULL, RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
- "BufferPredicate", RES_TYPE_SYMBOL);
- gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
- RES_TYPE_STRING);
- }
+ gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+ /* The resources controlling the menu-bar, tool-bar, and tab-bar are
+ processed specially at startup, and reflected in the mode
+ variables; ignore them here. */
+ gui_default_parameter (f, parms, Qmenu_bar_lines,
+ NILP (Vmenu_bar_mode)
+ ? make_fixnum (0) : make_fixnum (1),
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qtab_bar_lines,
+ NILP (Vtab_bar_mode)
+ ? make_fixnum (0) : make_fixnum (1),
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qtool_bar_lines,
+ NILP (Vtool_bar_mode)
+ ? make_fixnum (0) : make_fixnum (1),
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
+ "BufferPredicate", RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
+ RES_TYPE_STRING);
parms = get_geometry_from_preferences (dpyinfo, parms);
window_prompting = gui_figure_window_size (f, parms, false, true);
- if (ttip_p)
- {
- /* No fringes on tip frame. */
- f->fringe_cols = 0;
- f->left_fringe_width = 0;
- f->right_fringe_width = 0;
- /* No dividers on tip frame. */
- f->right_divider_width = 0;
- f->bottom_divider_width = 0;
- }
-
tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
RES_TYPE_BOOLEAN);
- f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem));
-
- /* Add `tooltip' frame parameter's default value. */
- if (NILP (Fframe_parameter (frame, Qtooltip)) && ttip_p)
- Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
-
-#define ASSIGN_CURSOR(cursor, be_cursor) \
- (FRAME_OUTPUT_DATA (f)->cursor = be_cursor)
-
- ASSIGN_CURSOR (text_cursor, BCursor_create_i_beam ());
- ASSIGN_CURSOR (nontext_cursor, BCursor_create_default ());
- ASSIGN_CURSOR (modeline_cursor, BCursor_create_modeline ());
- ASSIGN_CURSOR (hand_cursor, BCursor_create_grab ());
- ASSIGN_CURSOR (hourglass_cursor, BCursor_create_progress_cursor ());
- ASSIGN_CURSOR (horizontal_drag_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_EAST_WEST));
- ASSIGN_CURSOR (vertical_drag_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_NORTH_SOUTH));
- ASSIGN_CURSOR (left_edge_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_WEST));
- ASSIGN_CURSOR (top_left_corner_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_NORTH_WEST));
- ASSIGN_CURSOR (top_edge_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_NORTH));
- ASSIGN_CURSOR (top_right_corner_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_NORTH_EAST));
- ASSIGN_CURSOR (right_edge_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_EAST));
- ASSIGN_CURSOR (bottom_right_corner_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_EAST));
- ASSIGN_CURSOR (bottom_edge_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_SOUTH));
- ASSIGN_CURSOR (bottom_left_corner_cursor,
- BCursor_from_id (CURSOR_ID_RESIZE_SOUTH_WEST));
- ASSIGN_CURSOR (no_cursor,
- BCursor_from_id (CURSOR_ID_NO_CURSOR));
-
- ASSIGN_CURSOR (current_cursor, FRAME_OUTPUT_DATA (f)->text_cursor);
-#undef ASSIGN_CURSOR
-
-
- if (ttip_p)
- f->no_split = true;
+ f->no_split = minibuffer_only || (!BASE_EQ (tem, Qunbound) && !NILP (tem));
+
f->terminal->reference_count++;
FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
+
if (!FRAME_OUTPUT_DATA (f)->window)
xsignal1 (Qerror, build_unibyte_string ("Could not create window"));
- if (!minibuffer_only && !ttip_p && FRAME_EXTERNAL_MENU_BAR (f))
+ block_input ();
+ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
initialize_frame_menubar (f);
-
- FRAME_OUTPUT_DATA (f)->window_desc = FRAME_OUTPUT_DATA (f)->window;
+ unblock_input ();
Vframe_list = Fcons (frame, Vframe_list);
- Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
+ Lisp_Object parent_frame = gui_display_get_arg (dpyinfo, parms,
+ Qparent_frame, NULL, NULL,
RES_TYPE_SYMBOL);
- if (EQ (parent_frame, Qunbound)
+ if (BASE_EQ (parent_frame, Qunbound)
|| NILP (parent_frame)
|| !FRAMEP (parent_frame)
|| !FRAME_LIVE_P (XFRAME (parent_frame)))
parent_frame = Qnil;
+ /* It doesn't make sense to center child frames, the resulting
+ position makes no sense. */
+ if (!NILP (parent_frame))
+ window_prompting |= PPosition;
+
fset_parent_frame (f, parent_frame);
store_frame_param (f, Qparent_frame, parent_frame);
@@ -835,106 +897,325 @@ haiku_create_frame (Lisp_Object parms, int ttip_p)
haiku_set_parent_frame (f, parent_frame, Qnil);
gui_default_parameter (f, parms, Qundecorated, Qnil, NULL, NULL, RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qoverride_redirect, Qnil, NULL, NULL, RES_TYPE_BOOLEAN);
gui_default_parameter (f, parms, Qicon_type, Qnil,
"bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
- if (ttip_p)
- {
- gui_default_parameter (f, parms, Qundecorated, Qt, NULL, NULL, RES_TYPE_BOOLEAN);
- gui_default_parameter (f, parms, Qno_accept_focus, Qt, NULL, NULL,
- RES_TYPE_BOOLEAN);
- }
- else
- {
- gui_default_parameter (f, parms, Qauto_raise, Qnil,
- "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
- gui_default_parameter (f, parms, Qauto_lower, Qnil,
- "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
- gui_default_parameter (f, parms, Qcursor_type, Qbox,
- "cursorType", "CursorType", RES_TYPE_SYMBOL);
- gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth",
- RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
- "scrollBarHeight", "ScrollBarHeight",
- RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qalpha, Qnil,
- "alpha", "Alpha", RES_TYPE_NUMBER);
- gui_default_parameter (f, parms, Qfullscreen, Qnil,
- "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
- }
+ gui_default_parameter (f, parms, Qauto_raise, Qnil,
+ "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qauto_lower, Qnil,
+ "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qcursor_type, Qbox,
+ "cursorType", "CursorType", RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+ "scrollBarWidth", "ScrollBarWidth",
+ RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
+ "scrollBarHeight", "ScrollBarHeight",
+ RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha, Qnil,
+ "alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qfullscreen, Qnil,
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
"inhibitDoubleBuffering", "InhibitDoubleBuffering",
RES_TYPE_BOOLEAN);
- if (ttip_p)
- {
- Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
-
- call2 (Qface_set_after_frame_default, frame, Qnil);
-
- if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
- {
- AUTO_FRAME_ARG (arg, Qbackground_color, bg);
- Fmodify_frame_parameters (frame, arg);
- }
- }
-
- if (ttip_p)
- face_change = face_change_before;
-
f->can_set_window_size = true;
adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
- 0, true, ttip_p ? Qtip_frame : Qx_create_frame_2);
+ 0, true, Qx_create_frame_2);
- if (!FRAME_OUTPUT_DATA (f)->explicit_parent && !ttip_p)
- {
- Lisp_Object visibility;
+ Lisp_Object visibility;
- visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
- RES_TYPE_SYMBOL);
- if (EQ (visibility, Qunbound))
- visibility = Qt;
- if (EQ (visibility, Qicon))
- haiku_iconify_frame (f);
- else if (!NILP (visibility))
- haiku_visualize_frame (f);
- else /* Qnil */
- {
- f->was_invisible = true;
- }
- }
-
- if (!ttip_p)
+ visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
+ RES_TYPE_SYMBOL);
+ if (BASE_EQ (visibility, Qunbound))
+ visibility = Qt;
+ if (EQ (visibility, Qicon))
+ haiku_iconify_frame (f);
+ else if (!NILP (visibility))
+ haiku_visualize_frame (f);
+ else /* Qnil */
{
- if (FRAME_HAS_MINIBUF_P (f)
- && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
- || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
- kset_default_minibuffer_frame (kb, frame);
+ f->was_invisible = true;
}
+ if (FRAME_HAS_MINIBUF_P (f)
+ && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
+ || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
+ kset_default_minibuffer_frame (kb, frame);
+
+ gui_default_parameter (f, parms, Qz_group, Qnil,
+ NULL, NULL, RES_TYPE_SYMBOL);
+
for (tem = parms; CONSP (tem); tem = XCDR (tem))
if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
+ block_input ();
if (window_prompting & (USPosition | PPosition))
haiku_set_offset (f, f->left_pos, f->top_pos, 1);
+ else if (cascade_target)
+ haiku_set_offset (f, cascade_target->left_pos + 15,
+ cascade_target->top_pos + 15, 1);
else
BWindow_center_on_screen (FRAME_HAIKU_WINDOW (f));
+ unblock_input ();
+
+ FRAME_OUTPUT_DATA (f)->configury_done = true;
+
+ if (f->want_fullscreen != FULLSCREEN_NONE)
+ FRAME_TERMINAL (f)->fullscreen_hook (f);
/* Make sure windows on this frame appear in calls to next-window
and similar functions. */
Vwindow_list = Qnil;
- if (ttip_p)
- adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
- 0, true, Qtip_frame);
+ return unbind_to (count, frame);
+}
+
+/* Create a frame for a tooltip. PARMS is a list of frame parameters.
+ TEXT is the string to display in the tip frame. Value is the
+ frame.
+
+ Note that functions called here, esp. gui_default_parameter can
+ signal errors, for instance when a specified color name is
+ undefined. We have to make sure that we're in a consistent state
+ when this happens. */
+static Lisp_Object
+haiku_create_tip_frame (Lisp_Object parms)
+{
+ struct frame *f;
+ Lisp_Object frame;
+ Lisp_Object name;
+ specpdl_ref count = SPECPDL_INDEX ();
+ bool face_change_before = face_change;
+ struct haiku_display_info *dpyinfo = x_display_list;
+
+ if (!dpyinfo->terminal->name)
+ error ("Terminal is not live, can't create new frames on it");
+
+ parms = Fcopy_alist (parms);
+
+ /* Get the name of the frame to use for resource lookup. */
+ name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
+ RES_TYPE_STRING);
+ if (!STRINGP (name)
+ && !BASE_EQ (name, Qunbound)
+ && !NILP (name))
+ error ("Invalid frame name--not a string or nil");
+
+ frame = Qnil;
+ f = make_frame (false);
+ f->wants_modeline = false;
+ XSETFRAME (frame, f);
+ record_unwind_protect (unwind_create_tip_frame, frame);
+
+ f->terminal = dpyinfo->terminal;
+
+ /* By setting the output method, we're essentially saying that
+ the frame is live, as per FRAME_LIVE_P. If we get a signal
+ from this point on, x_destroy_window might screw up reference
+ counts etc. */
+ f->output_method = output_haiku;
+ f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku);
+ f->output_data.haiku->wait_for_event_type = -1;
+ f->output_data.haiku->relief_background = -1;
+
+ f->tooltip = true;
+ fset_icon_name (f, Qnil);
+ FRAME_DISPLAY_INFO (f) = dpyinfo;
+
+ FRAME_OUTPUT_DATA (f)->parent_desc = NULL;
+
+ /* Set the name; the functions to which we pass f expect the name to
+ be set. */
+ if (BASE_EQ (name, Qunbound) || NILP (name))
+ f->explicit_name = false;
+ else
+ {
+ fset_name (f, name);
+ f->explicit_name = true;
+ /* use the frame's title when getting resources for this frame. */
+ specbind (Qx_resource_name, name);
+ }
+
+#ifdef USE_BE_CAIRO
+ register_font_driver (&ftcrfont_driver, f);
+#ifdef HAVE_HARFBUZZ
+ register_font_driver (&ftcrhbfont_driver, f);
+#endif
+#endif
+ register_font_driver (&haikufont_driver, f);
+
+ image_cache_refcount =
+ FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
+
+ gui_default_parameter (f, parms, Qfont_backend, Qnil,
+ "fontBackend", "FontBackend", RES_TYPE_STRING);
+
+ /* Extract the window parameters from the supplied values that are
+ needed to determine window geometry. */
+ FRAME_RIF (f)->default_font_parameter (f, parms);
+
+ /* This defaults to 1 in order to match xterm. We recognize either
+ internalBorderWidth or internalBorder (which is what xterm calls
+ it). */
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ {
+ Lisp_Object value;
+
+ value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
+ "internalBorder", "internalBorder",
+ RES_TYPE_NUMBER);
+ if (! BASE_EQ (value, Qunbound))
+ parms = Fcons (Fcons (Qinternal_border_width, value),
+ parms);
+ }
+
+ gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
+ "internalBorderWidth", "internalBorderWidth",
+ RES_TYPE_NUMBER);
+
+ gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
+ NULL, NULL, RES_TYPE_NUMBER);
+
+ /* Also do the stuff which must be set before the window exists. */
+ gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+ "foreground", "Foreground", RES_TYPE_STRING);
+
+ gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+ "background", "Background", RES_TYPE_STRING);
+
+ /* FIXME: is there a better method to tell Emacs to not recolor the
+ cursors other than setting the color to a special value? */
+ gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"),
+ "pointerColor", "Foreground", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+ "cursorColor", "Foreground", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
+ "borderColor", "BorderColor", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+ /* Init faces before gui_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
+ init_frame_faces (f);
+
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
+ gui_figure_window_size (f, parms, false, false);
+
+ {
+ void *window;
+
+ block_input ();
+ window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view);
+
+ FRAME_OUTPUT_DATA (f)->window = window;
+ if (!window)
+ emacs_abort ();
+
+ BWindow_set_tooltip_decoration (window);
+ unblock_input ();
+ }
+
+ gui_default_parameter (f, parms, Qauto_raise, Qnil,
+ "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qauto_lower, Qnil,
+ "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qcursor_type, Qbox,
+ "cursorType", "CursorType", RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qalpha, Qnil,
+ "alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+
+ initial_setup_back_buffer (f);
+
+ /* Add `tooltip' frame parameter's default value. */
+ if (NILP (Fframe_parameter (frame, Qtooltip)))
+ {
+ AUTO_FRAME_ARG (arg, Qtooltip, Qt);
+ Fmodify_frame_parameters (frame, arg);
+ }
+
+ /* FIXME - can this be done in a similar way to normal frames?
+ https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
+
+ {
+ Lisp_Object disptype;
+
+ if (be_get_display_planes () == 1)
+ disptype = Qmono;
+ else if (be_is_display_grayscale ())
+ disptype = Qgrayscale;
+ else
+ disptype = Qcolor;
+
+ if (NILP (Fframe_parameter (frame, Qdisplay_type)))
+ {
+ AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
+ Fmodify_frame_parameters (frame, arg);
+ }
+ }
+
+ /* Set up faces after all frame parameters are known. This call
+ also merges in face attributes specified for new frames.
+
+ Frame parameters may be changed if .Xdefaults contains
+ specifications for the default font. For example, if there is an
+ `Emacs.default.attributeBackground: pink', the `background-color'
+ attribute of the frame gets set, which let's the internal border
+ of the tooltip frame appear in pink. Prevent this. */
+ {
+ Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+ call2 (Qface_set_after_frame_default, frame, Qnil);
+
+ if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+ {
+ AUTO_FRAME_ARG (arg, Qbackground_color, bg);
+ Fmodify_frame_parameters (frame, arg);
+ }
+ }
+
+ f->no_split = true;
+
+ /* Now that the frame will be official, it counts as a reference to
+ its display and terminal. */
+ f->terminal->reference_count++;
+
+ /* It is now ok to make the frame official even if we get an error
+ below. And the frame needs to be on Vframe_list or making it
+ visible won't work. */
+ Vframe_list = Fcons (frame, Vframe_list);
+ f->can_set_window_size = true;
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+ 0, true, Qtip_frame);
+
+ /* Setting attributes of faces of the tooltip frame from resources
+ and similar will set face_change, which leads to the clearing of
+ all current matrices. Since this isn't necessary here, avoid it
+ by resetting face_change to the value it had before we created
+ the tip frame. */
+ face_change = face_change_before;
+
+ /* Discard the unwind_protect. */
return unbind_to (count, frame);
}
+
static void
compute_tip_xy (struct frame *f,
Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
@@ -959,7 +1240,11 @@ compute_tip_xy (struct frame *f,
/* Default min and max values. */
min_x = 0;
min_y = 0;
- BScreen_px_dim (&max_x, &max_y);
+
+ be_get_screen_dimensions (&max_x, &max_y);
+
+ max_x = max_x - 1;
+ max_y = max_y - 1;
block_input ();
BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
@@ -1005,16 +1290,17 @@ compute_tip_xy (struct frame *f,
static Lisp_Object
haiku_hide_tip (bool delete)
{
+ Lisp_Object it, frame;
+
if (!NILP (tip_timer))
{
call1 (Qcancel_timer, tip_timer);
tip_timer = Qnil;
}
- Lisp_Object it, frame;
FOR_EACH_FRAME (it, frame)
- if (FRAME_WINDOW_P (XFRAME (frame)) &&
- FRAME_HAIKU_VIEW (XFRAME (frame)))
+ if (FRAME_WINDOW_P (XFRAME (frame))
+ && FRAME_HAIKU_VIEW (XFRAME (frame)))
BView_set_tooltip (FRAME_HAIKU_VIEW (XFRAME (frame)), NULL);
if (NILP (tip_frame)
@@ -1023,10 +1309,9 @@ haiku_hide_tip (bool delete)
return Qnil;
else
{
- ptrdiff_t count;
Lisp_Object was_open = Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
@@ -1065,14 +1350,34 @@ haiku_set_undecorated (struct frame *f, Lisp_Object new_value,
FRAME_UNDECORATED (f) = !NILP (new_value);
BWindow_change_decoration (FRAME_HAIKU_WINDOW (f), NILP (new_value));
unblock_input ();
+
+ haiku_update_after_decoration_change (f);
+}
+
+static void
+haiku_set_override_redirect (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ if (EQ (new_value, old_value))
+ return;
+
+ block_input ();
+ BWindow_set_override_redirect (FRAME_HAIKU_WINDOW (f),
+ !NILP (new_value));
+ FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
+ unblock_input ();
+
+ haiku_update_after_decoration_change (f);
}
static void
haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
+ int nlines;
+
if (FRAME_TOOLTIP_P (f))
return;
- int nlines;
+
if (TYPE_RANGED_FIXNUMP (int, value))
nlines = XFIXNUM (value);
else
@@ -1080,9 +1385,6 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval
fset_redisplay (f);
- FRAME_MENU_BAR_LINES (f) = 0;
- FRAME_MENU_BAR_HEIGHT (f) = 0;
-
if (nlines)
{
FRAME_EXTERNAL_MENU_BAR (f) = 1;
@@ -1091,11 +1393,14 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval
}
else
{
+ FRAME_MENU_BAR_LINES (f) = 0;
+ FRAME_MENU_BAR_HEIGHT (f) = 0;
+
if (FRAME_EXTERNAL_MENU_BAR (f))
free_frame_menubar (f);
+
FRAME_EXTERNAL_MENU_BAR (f) = 0;
- if (FRAME_HAIKU_P (f))
- FRAME_HAIKU_MENU_BAR (f) = 0;
+ FRAME_HAIKU_MENU_BAR (f) = 0;
}
adjust_frame_glyphs (f);
@@ -1109,112 +1414,129 @@ haiku_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval
static Lisp_Object
frame_geometry (Lisp_Object frame, Lisp_Object attribute)
{
- struct frame *f = decode_live_frame (frame);
- check_window_system (f);
+ struct frame *f, *parent;
+ void *window;
+ int outer_x, outer_y, outer_width, outer_height;
+ int right_off, bottom_off, top_off;
+ int native_x, native_y;
+
+ f = decode_window_system_frame (frame);
+ parent = FRAME_PARENT_FRAME (f);
+ window = FRAME_HAIKU_WINDOW (f);
+
+ be_lock_window (window);
+ be_get_window_decorator_frame (window, &outer_x, &outer_y,
+ &outer_width, &outer_height);
+ be_get_window_decorator_dimensions (window, NULL, &top_off,
+ &right_off, &bottom_off);
+ be_unlock_window (window);
+
+ native_x = FRAME_OUTPUT_DATA (f)->frame_x;
+ native_y = FRAME_OUTPUT_DATA (f)->frame_y;
+
+ if (parent)
+ {
+ /* Adjust all the coordinates by the coordinates of the parent
+ frame. */
+ outer_x -= FRAME_OUTPUT_DATA (parent)->frame_x;
+ outer_y -= FRAME_OUTPUT_DATA (parent)->frame_y;
+ native_x -= FRAME_OUTPUT_DATA (parent)->frame_x;
+ native_y -= FRAME_OUTPUT_DATA (parent)->frame_y;
+ }
if (EQ (attribute, Qouter_edges))
- return list4i (f->left_pos, f->top_pos,
- f->left_pos, f->top_pos);
+ return list4i (outer_x, outer_y,
+ outer_x + outer_width,
+ outer_y + outer_height);
else if (EQ (attribute, Qnative_edges))
- return list4i (f->left_pos, f->top_pos,
- f->left_pos + FRAME_PIXEL_WIDTH (f),
- f->top_pos + FRAME_PIXEL_HEIGHT (f));
+ return list4i (native_x, native_y,
+ native_x + FRAME_PIXEL_WIDTH (f),
+ native_y + FRAME_PIXEL_HEIGHT (f));
else if (EQ (attribute, Qinner_edges))
- return list4i (f->left_pos + FRAME_INTERNAL_BORDER_WIDTH (f),
- f->top_pos + FRAME_INTERNAL_BORDER_WIDTH (f) +
- FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f),
- f->left_pos - FRAME_INTERNAL_BORDER_WIDTH (f) +
- FRAME_PIXEL_WIDTH (f),
- f->top_pos + FRAME_PIXEL_HEIGHT (f) -
- FRAME_INTERNAL_BORDER_WIDTH (f));
+ return list4i (native_x + FRAME_INTERNAL_BORDER_WIDTH (f),
+ native_y + FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_MENU_BAR_HEIGHT (f) + FRAME_TOOL_BAR_HEIGHT (f),
+ native_x - FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_PIXEL_WIDTH (f),
+ native_y + FRAME_PIXEL_HEIGHT (f)
+ - FRAME_INTERNAL_BORDER_WIDTH (f));
else
- return
- list (Fcons (Qouter_position,
- Fcons (make_fixnum (f->left_pos),
- make_fixnum (f->top_pos))),
- Fcons (Qouter_size,
- Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)),
- make_fixnum (FRAME_PIXEL_HEIGHT (f)))),
- Fcons (Qexternal_border_size,
- Fcons (make_fixnum (0), make_fixnum (0))),
- Fcons (Qtitle_bar_size,
- Fcons (make_fixnum (0), make_fixnum (0))),
- Fcons (Qmenu_bar_external, Qnil),
- Fcons (Qmenu_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) -
- (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
- make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))),
- Fcons (Qtool_bar_external, Qnil),
- Fcons (Qtool_bar_position, Qtop),
- Fcons (Qtool_bar_size, Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f) -
- (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
- make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))),
- Fcons (Qinternal_border_width, make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f))));
+ return list (Fcons (Qouter_position,
+ Fcons (make_fixnum (outer_x),
+ make_fixnum (outer_y))),
+ Fcons (Qouter_size,
+ Fcons (make_fixnum (outer_width),
+ make_fixnum (outer_height))),
+ Fcons (Qexternal_border_size,
+ Fcons (make_fixnum (right_off),
+ make_fixnum (bottom_off))),
+ Fcons (Qtitle_bar_size,
+ Fcons (make_fixnum (outer_width),
+ make_fixnum (top_off))),
+ Fcons (Qmenu_bar_external, Qnil),
+ Fcons (Qmenu_bar_size,
+ Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)
+ - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
+ make_fixnum (FRAME_MENU_BAR_HEIGHT (f)))),
+ Fcons (Qtool_bar_external, Qnil),
+ Fcons (Qtool_bar_position, Qtop),
+ Fcons (Qtool_bar_size,
+ Fcons (make_fixnum (FRAME_PIXEL_WIDTH (f)
+ - (FRAME_INTERNAL_BORDER_WIDTH (f) * 2)),
+ make_fixnum (FRAME_TOOL_BAR_HEIGHT (f)))),
+ Fcons (Qinternal_border_width,
+ make_fixnum (FRAME_INTERNAL_BORDER_WIDTH (f))));
}
void
haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- CHECK_STRING (arg);
+ unsigned long background;
- block_input ();
- Emacs_Color color;
+ background = haiku_decode_color (f, arg);
- if (haiku_get_color (SSDATA (arg), &color))
- {
- store_frame_param (f, Qbackground_color, oldval);
- unblock_input ();
- error ("Bad color");
- }
-
- FRAME_OUTPUT_DATA (f)->cursor_fg = color.pixel;
- FRAME_BACKGROUND_PIXEL (f) = color.pixel;
+ FRAME_OUTPUT_DATA (f)->cursor_fg = background;
+ FRAME_BACKGROUND_PIXEL (f) = background;
if (FRAME_HAIKU_VIEW (f))
{
- struct face *defface;
-
- BView_draw_lock (FRAME_HAIKU_VIEW (f));
- BView_SetViewColor (FRAME_HAIKU_VIEW (f), color.pixel);
+ BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0);
+ BView_SetViewColor (FRAME_HAIKU_VIEW (f), background);
BView_draw_unlock (FRAME_HAIKU_VIEW (f));
- defface = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
- if (defface)
- {
- defface->background = color.pixel;
- update_face_from_frame_parameter (f, Qbackground_color, arg);
- clear_frame (f);
- }
- }
+ FRAME_OUTPUT_DATA (f)->cursor_fg = background;
+ update_face_from_frame_parameter (f, Qbackground_color, arg);
- if (FRAME_VISIBLE_P (f))
- SET_FRAME_GARBAGED (f);
- unblock_input ();
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
}
void
haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- CHECK_STRING (arg);
+ unsigned long fore_pixel, pixel;
- block_input ();
- Emacs_Color color;
+ pixel = haiku_decode_color (f, arg);
- if (haiku_get_color (SSDATA (arg), &color))
+ if (!NILP (Vx_cursor_fore_pixel))
{
- store_frame_param (f, Qcursor_color, oldval);
- unblock_input ();
- error ("Bad color");
+ fore_pixel = haiku_decode_color (f, Vx_cursor_fore_pixel);
+ FRAME_OUTPUT_DATA (f)->cursor_fg = fore_pixel;
}
+ else
+ FRAME_OUTPUT_DATA (f)->cursor_fg = FRAME_BACKGROUND_PIXEL (f);
+
+ haiku_query_color (pixel, &FRAME_CURSOR_COLOR (f));
- FRAME_CURSOR_COLOR (f) = color;
if (FRAME_VISIBLE_P (f))
{
- gui_update_cursor (f, 0);
- gui_update_cursor (f, 1);
+ gui_update_cursor (f, false);
+ gui_update_cursor (f, true);
}
+
update_face_from_frame_parameter (f, Qcursor_color, arg);
- unblock_input ();
}
void
@@ -1228,11 +1550,7 @@ haiku_get_pixel (haiku bitmap, int x, int y)
{
unsigned char *data;
int32_t bytes_per_row;
- int mono_p;
- int left;
- int right;
- int top;
- int bottom;
+ int mono_p, left, right, top, bottom, byte;
data = BBitmap_data (bitmap);
BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
@@ -1244,20 +1562,17 @@ haiku_get_pixel (haiku bitmap, int x, int y)
if (!mono_p)
return ((uint32_t *) (data + (bytes_per_row * y)))[x];
- int byte = y * bytes_per_row + x / 8;
+ byte = y * bytes_per_row + x / 8;
return data[byte] & (1 << (x % 8));
}
void
haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel)
{
- unsigned char *data;
+ unsigned char *data, *byte;
int32_t bytes_per_row;
- int mono_p;
- int left;
- int right;
- int top;
- int bottom;
+ int mono_p, left, right, top, bottom;
+ ptrdiff_t off, bit, xoff;
data = BBitmap_data (bitmap);
BBitmap_dimensions (bitmap, &left, &top, &right, &bottom,
@@ -1268,11 +1583,11 @@ haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel)
if (mono_p)
{
- ptrdiff_t off = y * bytes_per_row;
- ptrdiff_t bit = x % 8;
- ptrdiff_t xoff = x / 8;
+ off = y * bytes_per_row;
+ bit = x % 8;
+ xoff = x / 8;
- unsigned char *byte = data + off + xoff;
+ byte = data + off + xoff;
if (!pixel)
*byte &= ~(1 << bit);
else
@@ -1301,6 +1616,7 @@ haiku_free_frame_resources (struct frame *f)
dpyinfo = FRAME_DISPLAY_INFO (f);
free_frame_faces (f);
+ haiku_free_custom_cursors (f);
/* Free scroll bars */
for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
@@ -1339,24 +1655,8 @@ haiku_free_frame_resources (struct frame *f)
if (window)
BWindow_quit (window);
- /* Free cursors */
-
- BCursor_delete (f->output_data.haiku->text_cursor);
- BCursor_delete (f->output_data.haiku->nontext_cursor);
- BCursor_delete (f->output_data.haiku->modeline_cursor);
- BCursor_delete (f->output_data.haiku->hand_cursor);
- BCursor_delete (f->output_data.haiku->hourglass_cursor);
- BCursor_delete (f->output_data.haiku->horizontal_drag_cursor);
- BCursor_delete (f->output_data.haiku->vertical_drag_cursor);
- BCursor_delete (f->output_data.haiku->left_edge_cursor);
- BCursor_delete (f->output_data.haiku->top_left_corner_cursor);
- BCursor_delete (f->output_data.haiku->top_edge_cursor);
- BCursor_delete (f->output_data.haiku->top_right_corner_cursor);
- BCursor_delete (f->output_data.haiku->right_edge_cursor);
- BCursor_delete (f->output_data.haiku->bottom_right_corner_cursor);
- BCursor_delete (f->output_data.haiku->bottom_edge_cursor);
- BCursor_delete (f->output_data.haiku->bottom_left_corner_cursor);
- BCursor_delete (f->output_data.haiku->no_cursor);
+ if (FRAME_OUTPUT_DATA (f)->saved_menu_event)
+ xfree (FRAME_OUTPUT_DATA (f)->saved_menu_event);
xfree (FRAME_OUTPUT_DATA (f));
FRAME_OUTPUT_DATA (f) = NULL;
@@ -1370,13 +1670,11 @@ haiku_iconify_frame (struct frame *frame)
if (FRAME_ICONIFIED_P (frame))
return;
- block_input ();
-
SET_FRAME_VISIBLE (frame, false);
SET_FRAME_ICONIFIED (frame, true);
+ block_input ();
BWindow_iconify (FRAME_HAIKU_WINDOW (frame));
-
unblock_input ();
}
@@ -1418,13 +1716,15 @@ haiku_unvisualize_frame (struct frame *f)
}
void
-haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+haiku_set_internal_border_width (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
{
int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
int new_width = check_int_nonnegative (arg);
if (new_width == old_width)
return;
+
f->internal_border_width = new_width;
if (FRAME_HAIKU_WINDOW (f))
@@ -1472,28 +1772,33 @@ check_x_display_info (Lisp_Object object)
return check_haiku_display_info (object);
}
-/* Rename frame F to NAME. If NAME is nil, set F's name to "GNU
- Emacs". If EXPLICIT_P is non-zero, that indicates Lisp code is
- setting the name, not redisplay; in that case, set F's name to NAME
- and set F->explicit_name; if NAME is nil, clear F->explicit_name.
+/* Rename frame F to NAME. If NAME is nil, set F's name to the
+ default name. If EXPLICIT_P is non-zero, that indicates Lisp code
+ is setting the name, not redisplay; in that case, set F's name to
+ NAME and set F->explicit_name; if NAME is nil, clear
+ F->explicit_name.
If EXPLICIT_P is zero, it means redisplay is setting the name; the
name provided will be ignored if explicit_name is set. */
void
haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p)
{
+ struct haiku_display_info *dpyinfo;
+
if (explicit_p)
{
if (f->explicit_name && NILP (name))
- update_mode_lines = 24;
+ update_mode_lines = 37;
f->explicit_name = !NILP (name);
}
else if (f->explicit_name)
return;
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
if (NILP (name))
- name = build_unibyte_string ("GNU Emacs");
+ name = dpyinfo->default_name;
if (!NILP (Fstring_equal (name, f->name)))
return;
@@ -1512,27 +1817,304 @@ haiku_set_inhibit_double_buffering (struct frame *f,
Lisp_Object old_value)
{
block_input ();
-#ifndef USE_BE_CAIRO
if (FRAME_HAIKU_WINDOW (f))
{
+#ifndef USE_BE_CAIRO
if (NILP (new_value))
- {
#endif
- EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
- if (!NILP (old_value))
- {
- SET_FRAME_GARBAGED (f);
- expose_frame (f, 0, 0, 0, 0);
- }
+ EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f));
#ifndef USE_BE_CAIRO
- }
else
EmacsView_disable_double_buffering (FRAME_HAIKU_VIEW (f));
- }
#endif
+
+ SET_FRAME_GARBAGED (f);
+ }
+ unblock_input ();
+}
+
+static void
+haiku_set_sticky (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ block_input ();
+ BWindow_set_sticky (FRAME_HAIKU_WINDOW (f), !NILP (new_value));
unblock_input ();
}
+struct user_cursor_info
+{
+ /* A pointer to the Lisp_Object describing the cursor. */
+ Lisp_Object *lisp_cursor;
+
+ /* The offset of the cursor in the `struct haiku_output' of each
+ frame. */
+ ptrdiff_t output_offset;
+
+ /* The offset of the default value of the cursor in the display
+ info structure. */
+ ptrdiff_t default_offset;
+};
+
+struct user_cursor_bitmap_info
+{
+ /* A bitmap to use instead of the font cursor to create cursors in a
+ certain color. */
+ const void *bits;
+
+ /* The mask for that bitmap. */
+ const void *mask;
+
+ /* The dimensions of the cursor bitmap. */
+ int width, height;
+
+ /* The position inside the cursor bitmap corresponding to the
+ position of the mouse pointer. */
+ int x, y;
+};
+
+#define INIT_USER_CURSOR(lisp, cursor) \
+ { (lisp), offsetof (struct haiku_output, cursor), \
+ offsetof (struct haiku_display_info, cursor) }
+
+struct user_cursor_info custom_cursors[] =
+ {
+ INIT_USER_CURSOR (&Vx_pointer_shape, text_cursor),
+ INIT_USER_CURSOR (NULL, nontext_cursor),
+ INIT_USER_CURSOR (NULL, modeline_cursor),
+ INIT_USER_CURSOR (&Vx_sensitive_text_pointer_shape, hand_cursor),
+ INIT_USER_CURSOR (&Vx_hourglass_pointer_shape, hourglass_cursor),
+ INIT_USER_CURSOR (NULL, horizontal_drag_cursor),
+ INIT_USER_CURSOR (NULL, vertical_drag_cursor),
+ INIT_USER_CURSOR (NULL, left_edge_cursor),
+ INIT_USER_CURSOR (NULL, top_left_corner_cursor),
+ INIT_USER_CURSOR (NULL, top_edge_cursor),
+ INIT_USER_CURSOR (NULL, top_right_corner_cursor),
+ INIT_USER_CURSOR (NULL, right_edge_cursor),
+ INIT_USER_CURSOR (NULL, bottom_right_corner_cursor),
+ INIT_USER_CURSOR (NULL, bottom_edge_cursor),
+ INIT_USER_CURSOR (NULL, bottom_left_corner_cursor),
+ INIT_USER_CURSOR (NULL, no_cursor),
+ };
+
+struct user_cursor_bitmap_info cursor_bitmaps[] =
+ {
+ { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7 }, /* text_cursor */
+ { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 }, /* nontext_cursor */
+ { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 }, /* modeline_cursor */
+ { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3 }, /* hand_cursor */
+ { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7 }, /* hourglass_cursor */
+ { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7 }, /* horizontal_drag_cursor */
+ { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7 }, /* vertical_drag_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* left_edge_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* top_left_corner_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* top_edge_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* top_right_corner_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* right_edge_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* bottom_right_corner_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* bottom_edge_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* bottom_left_corner_cursor */
+ { NULL, NULL, 0, 0, 0, 0 }, /* no_cursor */
+ };
+
+/* Array of cursor bitmaps for each system cursor ID. This is used to
+ color in user-specified cursors. */
+struct user_cursor_bitmap_info cursor_bitmaps_for_id[28] =
+ {
+ { NULL, NULL, 0, 0, 0, 0 },
+ { left_ptr_bits, left_ptrmsk_bits, 16, 16, 3, 1 },
+ { ibeam_ptr_bits, ibeam_ptrmask_bits, 15, 15, 7, 7 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { cross_ptr_bits, cross_ptrmask_bits, 30, 30, 15, 15 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { hand_ptr_bits, hand_ptrmask_bits, 15, 15, 4, 3 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { hourglass_bits, hourglass_mask_bits, 15, 15, 7, 7 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { horizd_ptr_bits, horizd_ptrmask_bits, 15, 15, 7, 7 },
+ { vertd_ptr_bits, vertd_ptrmask_bits, 15, 15, 7, 7 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ { NULL, NULL, 0, 0, 0, 0 },
+ };
+
+static void *
+haiku_create_colored_cursor (struct user_cursor_bitmap_info *info,
+ uint32_t foreground, uint32_t background)
+{
+ const char *bits, *mask;
+ void *bitmap, *cursor;
+ int width, height, bytes_per_line, x, y;
+
+ bits = info->bits;
+ mask = info->mask;
+ width = info->width;
+ height = info->height;
+ bytes_per_line = (width + 7) / 8;
+
+ bitmap = BBitmap_new (width, height, false);
+
+ if (!bitmap)
+ memory_full (SIZE_MAX);
+
+ for (y = 0; y < height; ++y)
+ {
+ for (x = 0; x < width; ++x)
+ {
+ if (mask[x / 8] >> (x % 8) & 1)
+ haiku_put_pixel (bitmap, x, y,
+ (bits[x / 8] >> (x % 8) & 1
+ ? (foreground | 255u << 24)
+ : (background | 255u << 24)));
+ else
+ haiku_put_pixel (bitmap, x, y, 0);
+ }
+
+ mask += bytes_per_line;
+ bits += bytes_per_line;
+ }
+
+ cursor = be_create_pixmap_cursor (bitmap, info->x, info->y);
+ BBitmap_free (bitmap);
+
+ return cursor;
+}
+
+/* Free all cursors on F that were allocated specifically for the
+ frame. */
+void
+haiku_free_custom_cursors (struct frame *f)
+{
+ struct user_cursor_info *cursor;
+ struct haiku_output *output;
+ struct haiku_display_info *dpyinfo;
+ Emacs_Cursor *frame_cursor;
+ Emacs_Cursor *display_cursor;
+ int i;
+
+ output = FRAME_OUTPUT_DATA (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ for (i = 0; i < ARRAYELTS (custom_cursors); ++i)
+ {
+ cursor = &custom_cursors[i];
+ frame_cursor = (Emacs_Cursor *) ((char *) output
+ + cursor->output_offset);
+ display_cursor = (Emacs_Cursor *) ((char *) dpyinfo
+ + cursor->default_offset);
+
+ if (*frame_cursor != *display_cursor && *frame_cursor)
+ {
+ if (output->current_cursor == *frame_cursor)
+ output->current_cursor = *display_cursor;
+
+ be_delete_cursor (*frame_cursor);
+ }
+
+ *frame_cursor = *display_cursor;
+ }
+}
+
+static void
+haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ struct haiku_output *output;
+ Emacs_Cursor *frame_cursor, old, *recolored;
+ int i, n, rc;
+ bool color_specified_p;
+ Emacs_Color color;
+
+ CHECK_STRING (arg);
+ color_specified_p = true;
+
+ if (!strcmp (SSDATA (arg), "font-color"))
+ color_specified_p = false;
+ else
+ rc = haiku_get_color (SSDATA (arg), &color);
+
+ if (color_specified_p && rc)
+ signal_error ("Undefined color", arg);
+
+ output = FRAME_OUTPUT_DATA (f);
+
+ /* This will also reset all the cursors back to their default
+ values. */
+ haiku_free_custom_cursors (f);
+
+ for (i = 0; i < ARRAYELTS (custom_cursors); ++i)
+ {
+ frame_cursor = (Emacs_Cursor *) ((char *) output
+ + custom_cursors[i].output_offset);
+ old = *frame_cursor;
+
+ if (custom_cursors[i].lisp_cursor
+ && FIXNUMP (*custom_cursors[i].lisp_cursor))
+ {
+ if (!RANGED_FIXNUMP (0, *custom_cursors[i].lisp_cursor,
+ 28)) /* 28 is the largest Haiku cursor ID. */
+ signal_error ("Invalid cursor",
+ *custom_cursors[i].lisp_cursor);
+
+ n = XFIXNUM (*custom_cursors[i].lisp_cursor);
+
+ if (color_specified_p && cursor_bitmaps_for_id[n].bits)
+ {
+ recolored
+ = haiku_create_colored_cursor (&cursor_bitmaps_for_id[n],
+ color.pixel,
+ FRAME_BACKGROUND_PIXEL (f));
+
+ if (recolored)
+ {
+ *frame_cursor = recolored;
+ continue;
+ }
+ }
+
+ /* Create and set the custom cursor. */
+ *frame_cursor = be_create_cursor_from_id (n);
+ }
+ else if (color_specified_p && cursor_bitmaps[i].bits)
+ {
+ recolored
+ = haiku_create_colored_cursor (&cursor_bitmaps[i], color.pixel,
+ FRAME_BACKGROUND_PIXEL (f));
+
+ if (recolored)
+ *frame_cursor = recolored;
+ }
+ }
+
+ /* This function can be called before the frame's window is
+ created. */
+ if (FRAME_HAIKU_WINDOW (f))
+ {
+ if (output->current_cursor == old
+ && old != *frame_cursor)
+ {
+ output->current_cursor = *frame_cursor;
+
+ BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
+ *frame_cursor);
+ }
+ }
+
+ update_face_from_frame_parameter (f, Qmouse_color, arg);
+}
+
DEFUN ("haiku-set-mouse-absolute-pixel-position",
@@ -1563,19 +2145,15 @@ the mouse cursor position in pixels relative to a position (0, 0) of the
selected frame's display. */)
(void)
{
- if (!x_display_list)
- return Qnil;
-
struct frame *f = SELECTED_FRAME ();
+ void *view;
+ int x, y;
- if (FRAME_INITIAL_P (f) || !FRAME_HAIKU_P (f)
- || !FRAME_HAIKU_VIEW (f))
+ if (FRAME_INITIAL_P (f) || !FRAME_HAIKU_P (f))
return Qnil;
block_input ();
- void *view = FRAME_HAIKU_VIEW (f);
-
- int x, y;
+ view = FRAME_HAIKU_VIEW (f);
BView_get_mouse (view, &x, &y);
BView_convert_to_screen (view, &x, &y);
unblock_input ();
@@ -1587,7 +2165,9 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object terminal)
{
- return Qt;
+ check_haiku_display_info (terminal);
+
+ return be_is_display_grayscale () ? Qnil : Qt;
}
DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
@@ -1595,6 +2175,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
(Lisp_Object color, Lisp_Object frame)
{
Emacs_Color col;
+
CHECK_STRING (color);
decode_window_system_frame (frame);
@@ -1606,17 +2187,19 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
(Lisp_Object color, Lisp_Object frame)
{
Emacs_Color col;
+ int rc;
+
CHECK_STRING (color);
decode_window_system_frame (frame);
block_input ();
- if (haiku_get_color (SSDATA (color), &col))
- {
- unblock_input ();
- return Qnil;
- }
+ rc = haiku_get_color (SSDATA (color), &col);
unblock_input ();
- return list3i (lrint (col.red), lrint (col.green), lrint (col.blue));
+
+ if (rc)
+ return Qnil;
+
+ return list3i (col.red, col.green, col.blue);
}
DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
@@ -1624,25 +2207,34 @@ DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object terminal)
{
- return Qnil;
+ check_haiku_display_info (terminal);
+
+ return be_is_display_grayscale () ? Qt : Qnil;
}
DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
- 1, 3, 0,
- doc: /* SKIP: real doc in xfns.c. */)
+ 1, 3, 0, doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
{
- struct haiku_display_info *dpy_info;
CHECK_STRING (display);
if (NILP (Fstring_equal (display, build_string ("be"))))
- !NILP (must_succeed) ? fatal ("Bad display") : error ("Bad display");
- dpy_info = haiku_term_init ();
+ {
+ if (!NILP (must_succeed))
+ fatal ("Invalid display %s", SDATA (display));
+ else
+ signal_error ("Invalid display", display);
+ }
- if (!dpy_info)
- !NILP (must_succeed) ? fatal ("Display not responding") :
- error ("Display not responding");
+ if (x_display_list)
+ {
+ if (!NILP (must_succeed))
+ fatal ("A display is already open");
+ else
+ error ("A display is already open");
+ }
+ haiku_term_init ();
return Qnil;
}
@@ -1652,10 +2244,10 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
(Lisp_Object terminal)
{
+ int width, height;
check_haiku_display_info (terminal);
- int width, height;
- BScreen_px_dim (&width, &height);
+ be_get_screen_dimensions (&width, &height);
return make_fixnum (width);
}
@@ -1665,11 +2257,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_heigh
(Lisp_Object terminal)
{
+ int width, height;
check_haiku_display_info (terminal);
- int width, height;
- BScreen_px_dim (&width, &height);
- return make_fixnum (width);
+ be_get_screen_dimensions (&width, &height);
+ return make_fixnum (height);
}
DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
@@ -1677,10 +2269,9 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1,
(Lisp_Object terminal)
{
struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
-
int width, height;
- BScreen_px_dim (&width, &height);
+ be_get_screen_dimensions (&width, &height);
return make_fixnum (height / (dpyinfo->resy / 25.4));
}
@@ -1690,11 +2281,10 @@ DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
(Lisp_Object terminal)
{
struct haiku_display_info *dpyinfo = check_haiku_display_info (terminal);
-
int width, height;
- BScreen_px_dim (&width, &height);
- return make_fixnum (height / (dpyinfo->resy / 25.4));
+ be_get_screen_dimensions (&width, &height);
+ return make_fixnum (width / (dpyinfo->resx / 25.4));
}
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
@@ -1702,7 +2292,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object parms)
{
- return haiku_create_frame (parms, 0);
+ return haiku_create_frame (parms);
}
DEFUN ("x-display-visual-class", Fx_display_visual_class,
@@ -1710,16 +2300,20 @@ DEFUN ("x-display-visual-class", Fx_display_visual_class,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object terminal)
{
+ int planes;
+ bool grayscale_p;
+
check_haiku_display_info (terminal);
- int planes = be_get_display_planes ();
+ grayscale_p = be_is_display_grayscale ();
+ if (grayscale_p)
+ return Qstatic_gray;
+ planes = be_get_display_planes ();
if (planes == 8)
- return intern ("static-color");
- else if (planes == 16 || planes == 15)
- return intern ("pseudo-color");
+ return Qstatic_color;
- return intern ("direct-color");
+ return Qtrue_color;
}
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
@@ -1727,31 +2321,30 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
(Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
{
- struct frame *tip_f;
+ struct frame *f, *tip_f;
struct window *w;
int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t count_1;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object window, size, tip_buf;
-
AUTO_STRING (tip, " *tip*");
specbind (Qinhibit_redisplay, Qt);
CHECK_STRING (string);
+ if (SCHARS (string) == 0)
+ string = make_unibyte_string (" ", 1);
if (NILP (frame))
frame = selected_frame;
- decode_window_system_frame (frame);
+ f = decode_window_system_frame (frame);
if (NILP (timeout))
- timeout = make_fixnum (5);
- else
- CHECK_FIXNAT (timeout);
+ timeout = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
if (NILP (dx))
dx = make_fixnum (5);
@@ -1763,7 +2356,10 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
else
CHECK_FIXNUM (dy);
- if (haiku_use_system_tooltips)
+ tip_dx = dx;
+ tip_dy = dy;
+
+ if (use_system_tooltips)
{
int root_x, root_y;
CHECK_STRING (string);
@@ -1796,8 +2392,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
reliable way to get it. */
compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
BView_convert_from_screen (FRAME_HAIKU_VIEW (f), &root_x, &root_y);
- BView_set_and_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string),
- root_x, root_y);
+ be_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string),
+ root_x, root_y);
unblock_input ();
goto start_timer;
}
@@ -1806,24 +2402,21 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
{
if (FRAME_VISIBLE_P (XFRAME (tip_frame))
&& EQ (frame, tip_last_frame)
- && !NILP (Fequal_including_properties (string, tip_last_string))
- && !NILP (Fequal (parms, tip_last_parms)))
+ && !NILP (Fequal_including_properties (tip_last_string, string))
+ && !NILP (Fequal (tip_last_parms, parms)))
{
/* Only DX and DY have changed. */
tip_f = XFRAME (tip_frame);
if (!NILP (tip_timer))
{
- Lisp_Object timer = tip_timer;
-
+ call1 (Qcancel_timer, tip_timer);
tip_timer = Qnil;
- call1 (Qcancel_timer, timer);
}
block_input ();
compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
- haiku_set_offset (tip_f, root_x, root_y, 1);
- haiku_visualize_frame (tip_f);
+ BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), root_x, root_y);
unblock_input ();
goto start_timer;
@@ -1834,8 +2427,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
Lisp_Object tail, elt, parm, last;
/* Check if every parameter in PARMS has the same value in
- tip_last_parms. This may destruct tip_last_parms
- which, however, will be recreated below. */
+ tip_last_parms. This may destruct tip_last_parms which,
+ however, will be recreated below. */
for (tail = parms; CONSP (tail); tail = XCDR (tail))
{
elt = XCAR (tail);
@@ -1861,8 +2454,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
call2 (Qassq_delete_all, parm, tip_last_parms);
}
- /* Now check if there's a parameter left in tip_last_parms with a
- non-nil value. */
+ /* Now check if every parameter in what is left of
+ tip_last_parms with a non-nil value has an association in
+ PARMS. */
for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
{
elt = XCAR (tail);
@@ -1888,10 +2482,6 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
tip_last_string = string;
tip_last_parms = parms;
- /* Block input until the tip has been fully drawn, to avoid crashes
- when drawing tips in menus. */
- block_input ();
-
if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
{
/* Add default values to frame parameters. */
@@ -1902,21 +2492,16 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
if (NILP (Fassq (Qborder_width, parms)))
parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
if (NILP (Fassq (Qborder_color, parms)))
- parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")),
- parms);
+ parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
if (NILP (Fassq (Qbackground_color, parms)))
parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
parms);
- /* Create a frame for the tooltip and record it in the global
+ /* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
-
- if (NILP (tip_frame = haiku_create_frame (parms, 1)))
- {
- /* Creating the tip frame failed. */
- unblock_input ();
- return unbind_to (count, Qnil);
- }
+ if (NILP (tip_frame = haiku_create_tip_frame (parms)))
+ /* Creating the tip frame failed. */
+ return unbind_to (count, Qnil);
}
tip_f = XFRAME (tip_frame);
@@ -1956,12 +2541,12 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
- FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
+ FRAME_TOTAL_COLS (tip_f) = w->total_cols;
adjust_frame_glyphs (tip_f);
- /* Insert STRING into the root window's buffer and fit the frame to
- the buffer. */
- count_1 = SPECPDL_INDEX ();
+ /* Insert STRING into root window's buffer and fit the frame to the
+ buffer. */
+ specpdl_ref count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
@@ -1981,22 +2566,39 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
/* Add the frame's internal border to calculated size. */
width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+
/* Calculate position of tooltip frame. */
compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
- 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));
+
+ /* Show tooltip frame. */
+ block_input ();
+ void *wnd = FRAME_HAIKU_WINDOW (tip_f);
+ BWindow_resize (wnd, width, height);
+ /* The window decorator might cause the actual width and height to
+ be larger than WIDTH and HEIGHT, so use the actual sizes. */
+ BWindow_dimensions (wnd, &width, &height);
+ BView_resize_to (FRAME_HAIKU_VIEW (tip_f), width, height);
BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f),
- FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor);
- SET_FRAME_VISIBLE (tip_f, 1);
- BWindow_set_visible (FRAME_HAIKU_WINDOW (tip_f), 1);
+ FRAME_OUTPUT_DATA (f)->current_cursor);
+ BWindow_set_offset (wnd, root_x, root_y);
+ BWindow_set_visible (wnd, true);
+ SET_FRAME_VISIBLE (tip_f, true);
+ FRAME_PIXEL_WIDTH (tip_f) = width;
+ FRAME_PIXEL_HEIGHT (tip_f) = height;
+ BWindow_sync (wnd);
+
+ /* This is needed because the app server resets the cursor whenever
+ a new window is mapped, so we won't see the cursor set on the
+ tooltip if the mouse pointer isn't actually over it. */
+ BView_set_view_cursor (FRAME_HAIKU_VIEW (f),
+ FRAME_OUTPUT_DATA (f)->current_cursor);
+ unblock_input ();
w->must_be_updated_p = true;
- flush_frame (tip_f);
update_single_window (w);
+ flush_frame (tip_f);
set_buffer_internal_1 (old_buffer);
unbind_to (count_1, Qnil);
- unblock_input ();
windows_or_buffers_changed = old_windows_or_buffers_changed;
start_timer:
@@ -2094,8 +2696,7 @@ DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object frame)
{
- struct frame *f = decode_live_frame (frame);
- check_window_system (f);
+ struct frame *f = decode_window_system_frame (frame);
return EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)) ? Qt : Qnil;
}
@@ -2105,13 +2706,14 @@ DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_s
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object terminal)
{
+ struct frame *f;
+
if (FRAMEP (terminal))
{
- CHECK_LIVE_FRAME (terminal);
- struct frame *f = decode_window_system_frame (terminal);
+ f = decode_window_system_frame (terminal);
- if (FRAME_HAIKU_VIEW (f) &&
- EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
+ if (FRAME_HAIKU_VIEW (f)
+ && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
return FRAME_PARENT_FRAME (f) ? Qwhen_mapped : Qalways;
else
return Qnot_useful;
@@ -2202,16 +2804,21 @@ Optional arg MUSTMATCH, if non-nil, means the returned file or
directory must exist.
Optional arg DIR_ONLY_P, if non-nil, means choose only directories.
Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry field. */)
- (Lisp_Object prompt, Lisp_Object frame,
- Lisp_Object dir, Lisp_Object mustmatch,
- Lisp_Object dir_only_p, Lisp_Object save_text)
+ (Lisp_Object prompt, Lisp_Object frame, Lisp_Object dir,
+ Lisp_Object mustmatch, Lisp_Object dir_only_p, Lisp_Object save_text)
{
- ptrdiff_t idx;
- if (!x_display_list)
- error ("Be windowing not initialized");
+ struct frame *f;
+ char *file_name;
+ Lisp_Object value;
+
+ if (popup_activated_p)
+ error ("Trying to use a menu from within a menu-entry");
if (!NILP (dir))
- CHECK_STRING (dir);
+ {
+ CHECK_STRING (dir);
+ dir = ENCODE_FILE (dir);
+ }
if (!NILP (save_text))
CHECK_STRING (save_text);
@@ -2221,37 +2828,28 @@ Optional arg SAVE_TEXT, if non-nil, specifies some text to show in the entry fie
CHECK_STRING (prompt);
- CHECK_LIVE_FRAME (frame);
- check_window_system (XFRAME (frame));
-
- idx = SPECPDL_INDEX ();
- record_unwind_protect_void (unwind_popup);
-
- struct frame *f = XFRAME (frame);
-
- FRAME_DISPLAY_INFO (f)->focus_event_frame = f;
+ f = decode_window_system_frame (frame);
++popup_activated_p;
- char *fn = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
- !NILP (dir) ? SSDATA (ENCODE_UTF_8 (dir)) : NULL,
- !NILP (mustmatch), !NILP (dir_only_p),
- FRAME_HAIKU_WINDOW (f),
- !NILP (save_text) ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL,
- SSDATA (ENCODE_UTF_8 (prompt)),
- block_input, unblock_input, maybe_quit);
-
- unbind_to (idx, Qnil);
+ unrequest_sigio ();
+ file_name = be_popup_file_dialog (!NILP (mustmatch) || !NILP (dir_only_p),
+ !NILP (dir) ? SSDATA (dir) : NULL,
+ !NILP (mustmatch), !NILP (dir_only_p),
+ FRAME_HAIKU_WINDOW (f),
+ (!NILP (save_text)
+ ? SSDATA (ENCODE_UTF_8 (save_text)) : NULL),
+ SSDATA (ENCODE_UTF_8 (prompt)),
+ process_pending_signals);
+ request_sigio ();
+ --popup_activated_p;
- block_input ();
- BWindow_activate (FRAME_HAIKU_WINDOW (f));
- unblock_input ();
+ if (!file_name)
+ quit ();
- if (!fn)
- return Qnil;
+ value = build_string (file_name);
+ free (file_name);
- Lisp_Object p = build_string_from_utf8 (fn);
- free (fn);
- return p;
+ return DECODE_FILE (value);
}
DEFUN ("haiku-put-resource", Fhaiku_put_resource, Shaiku_put_resource,
@@ -2301,6 +2899,7 @@ Frames are listed from topmost (first) to bottommost (last). */)
if (NILP (sel))
return frames;
+
return Fcons (sel, frames);
}
@@ -2309,13 +2908,15 @@ DEFUN ("x-display-save-under", Fx_display_save_under,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object terminal)
{
+ struct frame *f;
check_haiku_display_info (terminal);
if (FRAMEP (terminal))
{
- struct frame *f = decode_window_system_frame (terminal);
- return FRAME_HAIKU_VIEW (f) && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)) ?
- Qt : Qnil;
+ f = decode_window_system_frame (terminal);
+ return ((FRAME_HAIKU_VIEW (f)
+ && EmacsView_double_buffered_p (FRAME_HAIKU_VIEW (f)))
+ ? Qt : Qnil);
}
return Qnil;
@@ -2330,13 +2931,10 @@ means that if both frames are visible and the display areas of these
frames overlap, FRAME1 (partially) obscures FRAME2.
Some window managers may refuse to restack windows. */)
- (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
+ (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
{
- struct frame *f1 = decode_live_frame (frame1);
- struct frame *f2 = decode_live_frame (frame2);
-
- check_window_system (f1);
- check_window_system (f2);
+ struct frame *f1 = decode_window_system_frame (frame1);
+ struct frame *f2 = decode_window_system_frame (frame2);
block_input ();
@@ -2382,6 +2980,81 @@ Some window managers may refuse to restack windows. */)
return Qnil;
}
+DEFUN ("haiku-save-session-reply", Fhaiku_save_session_reply,
+ Shaiku_save_session_reply, 1, 1, 0,
+ doc: /* Reply to a `save-session' event.
+QUIT-REPLY means whether or not all files were saved and program
+termination should proceed.
+
+Calls to this function must be balanced by the amount of
+`save-session' events received. This is done automatically, so do not
+call this function yourself. */)
+ (Lisp_Object quit_reply)
+{
+ struct haiku_session_manager_reply reply;
+ reply.quit_reply = !NILP (quit_reply);
+
+ block_input ();
+ unrequest_sigio ();
+ write_port (port_emacs_to_session_manager, 0, &reply,
+ sizeof reply);
+ request_sigio ();
+ unblock_input ();
+
+ return Qnil;
+}
+
+DEFUN ("haiku-display-monitor-attributes-list",
+ Fhaiku_display_monitor_attributes_list,
+ Shaiku_display_monitor_attributes_list,
+ 0, 1, 0,
+ doc: /* Return a list of physical monitor attributes on the display TERMINAL.
+
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be a terminal object, a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display.
+
+Internal use only, use `display-monitor-attributes-list' instead. */)
+ (Lisp_Object terminal)
+{
+ struct MonitorInfo monitor;
+ struct haiku_display_info *dpyinfo;
+ Lisp_Object frames, tail, tem;
+
+ dpyinfo = check_haiku_display_info (terminal);
+ frames = Qnil;
+
+ FOR_EACH_FRAME (tail, tem)
+ {
+ maybe_quit ();
+
+ if (FRAME_HAIKU_P (XFRAME (tem))
+ && !FRAME_TOOLTIP_P (XFRAME (tem)))
+ frames = Fcons (tem, frames);
+ }
+
+ monitor.geom.x = 0;
+ monitor.geom.y = 0;
+ be_get_screen_dimensions ((int *) &monitor.geom.width,
+ (int *) &monitor.geom.height);
+
+ monitor.mm_width = (monitor.geom.width
+ / (dpyinfo->resx / 25.4));
+ monitor.mm_height = (monitor.geom.height
+ / (dpyinfo->resy / 25.4));
+ monitor.name = (char *) "BeOS monitor";
+
+ if (!be_get_explicit_workarea ((int *) &monitor.work.x,
+ (int *) &monitor.work.y,
+ (int *) &monitor.work.width,
+ (int *) &monitor.work.height))
+ monitor.work = monitor.geom;
+
+ return make_monitor_attribute_list (&monitor, 1, 0,
+ make_vector (1, frames),
+ "fallback");
+}
+
frame_parm_handler haiku_frame_parm_handlers[] =
{
gui_set_autoraise,
@@ -2400,7 +3073,7 @@ frame_parm_handler haiku_frame_parm_handlers[] =
gui_set_right_divider_width,
gui_set_bottom_divider_width,
haiku_set_menu_bar_lines,
- NULL, /* set mouse color */
+ haiku_set_mouse_color,
haiku_explicitly_set_name,
gui_set_scroll_bar_width,
gui_set_scroll_bar_height,
@@ -2421,7 +3094,7 @@ frame_parm_handler haiku_frame_parm_handlers[] =
gui_set_fullscreen,
gui_set_font_backend,
gui_set_alpha,
- NULL, /* set sticky */
+ haiku_set_sticky,
NULL, /* set tool bar pos */
haiku_set_inhibit_double_buffering,
haiku_set_undecorated,
@@ -2429,9 +3102,10 @@ frame_parm_handler haiku_frame_parm_handlers[] =
NULL, /* set skip taskbar */
haiku_set_no_focus_on_map,
haiku_set_no_accept_focus,
- NULL, /* set z group */
- NULL, /* set override redir */
- gui_set_no_special_glyphs
+ haiku_set_z_group,
+ haiku_set_override_redirect,
+ gui_set_no_special_glyphs,
+ gui_set_alpha_background,
};
void
@@ -2444,6 +3118,14 @@ syms_of_haikufns (void)
DEFSYM (Qalways, "always");
DEFSYM (Qnot_useful, "not-useful");
DEFSYM (Qwhen_mapped, "when-mapped");
+ DEFSYM (Qtooltip_reuse_hidden_frame, "tooltip-reuse-hidden-frame");
+
+ DEFSYM (Qstatic_color, "static-color");
+ DEFSYM (Qstatic_gray, "static-gray");
+ DEFSYM (Qtrue_color, "true-color");
+ DEFSYM (Qmono, "mono");
+ DEFSYM (Qgrayscale, "grayscale");
+ DEFSYM (Qcolor, "color");
defsubr (&Sx_hide_tip);
defsubr (&Sxw_display_color_p);
@@ -2477,6 +3159,8 @@ syms_of_haikufns (void)
defsubr (&Shaiku_frame_list_z_order);
defsubr (&Sx_display_save_under);
defsubr (&Shaiku_frame_restack);
+ defsubr (&Shaiku_save_session_reply);
+ defsubr (&Shaiku_display_monitor_attributes_list);
tip_timer = Qnil;
staticpro (&tip_timer);
@@ -2488,18 +3172,37 @@ syms_of_haikufns (void)
staticpro (&tip_last_string);
tip_last_parms = Qnil;
staticpro (&tip_last_parms);
+ tip_dx = Qnil;
+ staticpro (&tip_dx);
+ tip_dy = Qnil;
+ staticpro (&tip_dy);
DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
doc: /* SKIP: real doc in xfns.c. */);
Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
- DEFVAR_BOOL ("haiku-use-system-tooltips", haiku_use_system_tooltips,
- doc: /* When non-nil, Emacs will display tooltips using the App Kit.
-This can avoid a great deal of consing that does not play
-well with the Haiku memory allocator, but comes with the
-disadvantage of not being able to use special display properties
-within tooltips. */);
- haiku_use_system_tooltips = 1;
+ DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_cursor_fore_pixel = Qnil;
+
+ DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_hourglass_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-sensitive-text-pointer-shape",
+ Vx_sensitive_text_pointer_shape,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_sensitive_text_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("haiku-allowed-ui-colors", Vhaiku_allowed_ui_colors,
+ doc: /* Vector of UI colors that Emacs can look up from the system.
+If this is set up incorrectly, Emacs can crash when encoutering an
+invalid color. */);
+ Vhaiku_allowed_ui_colors = Qnil;
#ifdef USE_BE_CAIRO
DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
diff --git a/src/haikufont.c b/src/haikufont.c
index e08792be4b3..3e7f6f86dcb 100644
--- a/src/haikufont.c
+++ b/src/haikufont.c
@@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "fontset.h"
#include "haikuterm.h"
#include "character.h"
+#include "coding.h"
#include "font.h"
#include "termchar.h"
#include "pdumper.h"
@@ -136,7 +137,7 @@ haikufont_apply_registry (struct haiku_font_pattern *pattern,
for (l = 0; uniquifier[l]; ++l);
- uint32_t *a = xmalloc (l * sizeof *a);
+ int *a = xmalloc (l * sizeof *a);
for (l = 0; uniquifier[l]; ++l)
a[l] = uniquifier[l];
@@ -148,6 +149,7 @@ haikufont_apply_registry (struct haiku_font_pattern *pattern,
memcpy (&a[old_l], pattern->wanted_chars, (l - old_l) * sizeof *a);
xfree (pattern->wanted_chars);
}
+
pattern->specified |= FSPEC_WANTED;
pattern->want_chars_len = l;
pattern->wanted_chars = a;
@@ -182,7 +184,7 @@ haikufont_get_fallback_entity (void)
ASET (ent, FONT_FOUNDRY_INDEX, Qhaiku);
ASET (ent, FONT_FAMILY_INDEX, Qnil);
ASET (ent, FONT_ADSTYLE_INDEX, Qnil);
- ASET (ent, FONT_REGISTRY_INDEX, Qutf_8);
+ ASET (ent, FONT_REGISTRY_INDEX, Qiso10646_1);
ASET (ent, FONT_SIZE_INDEX, make_fixnum (0));
ASET (ent, FONT_AVGWIDTH_INDEX, make_fixnum (0));
ASET (ent, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
@@ -206,8 +208,6 @@ haikufont_weight_to_lisp (int weight)
{
case HAIKU_THIN:
return Qthin;
- case HAIKU_ULTRALIGHT:
- return Qultra_light;
case HAIKU_EXTRALIGHT:
return Qextra_light;
case HAIKU_LIGHT:
@@ -222,8 +222,6 @@ haikufont_weight_to_lisp (int weight)
return Qbold;
case HAIKU_EXTRA_BOLD:
return Qextra_bold;
- case HAIKU_ULTRA_BOLD:
- return Qultra_bold;
case HAIKU_BOOK:
return Qbook;
case HAIKU_HEAVY:
@@ -244,14 +242,14 @@ haikufont_lisp_to_weight (Lisp_Object weight)
if (EQ (weight, Qthin))
return HAIKU_THIN;
if (EQ (weight, Qultra_light))
- return HAIKU_ULTRALIGHT;
+ return HAIKU_EXTRALIGHT;
if (EQ (weight, Qextra_light))
return HAIKU_EXTRALIGHT;
if (EQ (weight, Qlight))
return HAIKU_LIGHT;
if (EQ (weight, Qsemi_light))
return HAIKU_SEMI_LIGHT;
- if (EQ (weight, Qnormal))
+ if (EQ (weight, Qnormal) || EQ (weight, Qregular))
return HAIKU_REGULAR;
if (EQ (weight, Qsemi_bold))
return HAIKU_SEMI_BOLD;
@@ -260,7 +258,7 @@ haikufont_lisp_to_weight (Lisp_Object weight)
if (EQ (weight, Qextra_bold))
return HAIKU_EXTRA_BOLD;
if (EQ (weight, Qultra_bold))
- return HAIKU_ULTRA_BOLD;
+ return HAIKU_EXTRA_BOLD;
if (EQ (weight, Qbook))
return HAIKU_BOOK;
if (EQ (weight, Qheavy))
@@ -272,7 +270,7 @@ haikufont_lisp_to_weight (Lisp_Object weight)
if (EQ (weight, Qmedium))
return HAIKU_MEDIUM;
- emacs_abort ();
+ return HAIKU_REGULAR;
}
static Lisp_Object
@@ -295,15 +293,16 @@ haikufont_slant_to_lisp (enum haiku_font_slant slant)
static enum haiku_font_slant
haikufont_lisp_to_slant (Lisp_Object slant)
{
- if (EQ (slant, Qitalic) ||
- EQ (slant, Qreverse_italic))
+ if (EQ (slant, Qitalic)
+ || EQ (slant, Qreverse_italic))
return SLANT_ITALIC;
- if (EQ (slant, Qoblique) ||
- EQ (slant, Qreverse_oblique))
+ if (EQ (slant, Qoblique)
+ || EQ (slant, Qreverse_oblique))
return SLANT_OBLIQUE;
- if (EQ (slant, Qnormal))
+ if (EQ (slant, Qnormal) || EQ (slant, Qregular))
return SLANT_REGULAR;
- emacs_abort ();
+
+ return SLANT_REGULAR;
}
static Lisp_Object
@@ -347,7 +346,7 @@ haikufont_lisp_to_width (Lisp_Object lisp)
return CONDENSED;
if (EQ (lisp, Qsemi_condensed))
return SEMI_CONDENSED;
- if (EQ (lisp, Qnormal))
+ if (EQ (lisp, Qnormal) || EQ (lisp, Qregular))
return NORMAL_WIDTH;
if (EQ (lisp, Qexpanded))
return EXPANDED;
@@ -355,7 +354,8 @@ haikufont_lisp_to_width (Lisp_Object lisp)
return EXTRA_EXPANDED;
if (EQ (lisp, Qultra_expanded))
return ULTRA_EXPANDED;
- emacs_abort ();
+
+ return NORMAL_WIDTH;
}
static int
@@ -381,49 +381,129 @@ haikufont_maybe_handle_special_family (Lisp_Object family,
static Lisp_Object
haikufont_pattern_to_entity (struct haiku_font_pattern *ptn)
{
- Lisp_Object ent = font_make_entity ();
- ASET (ent, FONT_TYPE_INDEX, Qhaiku);
- ASET (ent, FONT_FOUNDRY_INDEX, Qhaiku);
- ASET (ent, FONT_FAMILY_INDEX, Qdefault);
- ASET (ent, FONT_ADSTYLE_INDEX, Qnil);
- ASET (ent, FONT_REGISTRY_INDEX, Qutf_8);
- ASET (ent, FONT_SIZE_INDEX, make_fixnum (0));
- ASET (ent, FONT_AVGWIDTH_INDEX, make_fixnum (0));
- ASET (ent, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
- FONT_SET_STYLE (ent, FONT_WIDTH_INDEX, Qnormal);
- FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX, Qnormal);
- FONT_SET_STYLE (ent, FONT_SLANT_INDEX, Qnormal);
+ Lisp_Object entity, extras;
+
+ entity = font_make_entity ();
+ extras = Qnil;
+
+ ASET (entity, FONT_TYPE_INDEX, Qhaiku);
+ ASET (entity, FONT_FOUNDRY_INDEX, Qhaiku);
+ ASET (entity, FONT_FAMILY_INDEX, Qdefault);
+ ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
+ ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
+ ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
+ ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
+ ASET (entity, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO));
+
+ /* FONT_EXTRA_INDEX in a font entity can contain a cons of two
+ numbers (STYLE . IDX) under the key :indices that tell Emacs how
+ to open a font. */
+ if (ptn->specified & FSPEC_INDICES)
+ extras = Fcons (Fcons (QCindices,
+ Fcons (make_fixnum (ptn->family_index),
+ make_fixnum (ptn->style_index))),
+ extras);
+
+ if (ptn->specified & FSPEC_ANTIALIAS)
+ extras = Fcons (Fcons (QCantialias,
+ ptn->use_antialiasing ? Qt : Qnil),
+ extras);
+
+ ASET (entity, FONT_EXTRA_INDEX, extras);
+
+ FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, Qnormal);
+ FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, Qnormal);
+ FONT_SET_STYLE (entity, FONT_SLANT_INDEX, Qnormal);
if (ptn->specified & FSPEC_FAMILY)
- ASET (ent, FONT_FAMILY_INDEX, intern (ptn->family));
+ ASET (entity, FONT_FAMILY_INDEX, intern (ptn->family));
else
- ASET (ent, FONT_FAMILY_INDEX, Qdefault);
+ ASET (entity, FONT_FAMILY_INDEX, Qdefault);
if (ptn->specified & FSPEC_STYLE)
- ASET (ent, FONT_ADSTYLE_INDEX, intern (ptn->style));
+ ASET (entity, FONT_ADSTYLE_INDEX, intern (ptn->style));
else
{
if (ptn->specified & FSPEC_WEIGHT)
- FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX,
+ FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
haikufont_weight_to_lisp (ptn->weight));
if (ptn->specified & FSPEC_SLANT)
- FONT_SET_STYLE (ent, FONT_SLANT_INDEX,
+ FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
haikufont_slant_to_lisp (ptn->slant));
if (ptn->specified & FSPEC_WIDTH)
- FONT_SET_STYLE (ent, FONT_WIDTH_INDEX,
+ FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
haikufont_width_to_lisp (ptn->width));
}
if (ptn->specified & FSPEC_SPACING)
- ASET (ent, FONT_SPACING_INDEX,
- make_fixnum (ptn->mono_spacing_p ?
- FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL));
- return ent;
+ ASET (entity, FONT_SPACING_INDEX,
+ make_fixnum (ptn->mono_spacing_p
+ ? FONT_SPACING_MONO
+ : FONT_SPACING_PROPORTIONAL));
+
+ return entity;
+}
+
+static void
+haikufont_pattern_from_object (struct haiku_font_pattern *pattern,
+ Lisp_Object font_object)
+{
+ Lisp_Object val;
+
+ pattern->specified = 0;
+
+ val = AREF (font_object, FONT_FAMILY_INDEX);
+ if (!NILP (val))
+ {
+ pattern->specified |= FSPEC_FAMILY;
+ strncpy ((char *) &pattern->family,
+ SSDATA (SYMBOL_NAME (val)),
+ sizeof pattern->family - 1);
+ pattern->family[sizeof pattern->family - 1] = '\0';
+ }
+
+ val = AREF (font_object, FONT_ADSTYLE_INDEX);
+ if (!NILP (val))
+ {
+ pattern->specified |= FSPEC_STYLE;
+ strncpy ((char *) &pattern->style,
+ SSDATA (SYMBOL_NAME (val)),
+ sizeof pattern->style - 1);
+ pattern->style[sizeof pattern->style - 1] = '\0';
+ }
+
+ val = FONT_WEIGHT_FOR_FACE (font_object);
+ if (!NILP (val) && !EQ (val, Qunspecified))
+ {
+ pattern->specified |= FSPEC_WEIGHT;
+ pattern->weight = haikufont_lisp_to_weight (val);
+ }
+
+ val = FONT_SLANT_FOR_FACE (font_object);
+ if (!NILP (val) && !EQ (val, Qunspecified))
+ {
+ pattern->specified |= FSPEC_SLANT;
+ pattern->slant = haikufont_lisp_to_slant (val);
+ }
+
+ val = FONT_WIDTH_FOR_FACE (font_object);
+ if (!NILP (val) && !EQ (val, Qunspecified))
+ {
+ pattern->specified |= FSPEC_WIDTH;
+ pattern->width = haikufont_lisp_to_width (val);
+ }
+
+ val = assq_no_quit (QCantialias,
+ AREF (font_object, FONT_EXTRA_INDEX));
+ if (CONSP (val))
+ {
+ pattern->specified |= FSPEC_ANTIALIAS;
+ pattern->use_antialiasing = !NILP (XCDR (val));
+ }
}
static void
-haikufont_spec_or_entity_to_pattern (Lisp_Object ent,
- int list_p,
+haikufont_spec_or_entity_to_pattern (Lisp_Object ent, int list_p,
struct haiku_font_pattern *ptn)
{
Lisp_Object tem;
@@ -436,44 +516,47 @@ haikufont_spec_or_entity_to_pattern (Lisp_Object ent,
strncpy ((char *) &ptn->style,
SSDATA (SYMBOL_NAME (tem)),
sizeof ptn->style - 1);
+ ptn->style[sizeof ptn->style - 1] = '\0';
}
tem = FONT_SLANT_SYMBOLIC (ent);
- if (!NILP (tem))
+ if (!NILP (tem) && !EQ (tem, Qunspecified))
{
ptn->specified |= FSPEC_SLANT;
ptn->slant = haikufont_lisp_to_slant (tem);
}
tem = FONT_WEIGHT_SYMBOLIC (ent);
- if (!NILP (tem))
+ if (!NILP (tem) && !EQ (tem, Qunspecified))
{
ptn->specified |= FSPEC_WEIGHT;
ptn->weight = haikufont_lisp_to_weight (tem);
}
tem = FONT_WIDTH_SYMBOLIC (ent);
- if (!NILP (tem))
+ if (!NILP (tem) && !EQ (tem, Qunspecified))
{
ptn->specified |= FSPEC_WIDTH;
ptn->width = haikufont_lisp_to_width (tem);
}
tem = AREF (ent, FONT_SPACING_INDEX);
- if (FIXNUMP (tem))
+ if (!NILP (tem) && !EQ (tem, Qunspecified))
{
ptn->specified |= FSPEC_SPACING;
ptn->mono_spacing_p = XFIXNUM (tem) != FONT_SPACING_PROPORTIONAL;
}
tem = AREF (ent, FONT_FAMILY_INDEX);
- if (!NILP (tem) &&
- (list_p && !haikufont_maybe_handle_special_family (tem, ptn)))
+ if (!NILP (tem) && !EQ (tem, Qunspecified)
+ && (list_p
+ && !haikufont_maybe_handle_special_family (tem, ptn)))
{
ptn->specified |= FSPEC_FAMILY;
strncpy ((char *) &ptn->family,
SSDATA (SYMBOL_NAME (tem)),
sizeof ptn->family - 1);
+ ptn->family[sizeof ptn->family - 1] = '\0';
}
tem = assq_no_quit (QCscript, AREF (ent, FONT_EXTRA_INDEX));
@@ -551,6 +634,13 @@ haikufont_spec_or_entity_to_pattern (Lisp_Object ent,
}
}
+ tem = assq_no_quit (QCantialias, AREF (ent, FONT_EXTRA_INDEX));
+ if (CONSP (tem))
+ {
+ ptn->specified |= FSPEC_ANTIALIAS;
+ ptn->use_antialiasing = !NILP (XCDR (tem));
+ }
+
tem = AREF (ent, FONT_REGISTRY_INDEX);
if (SYMBOLP (tem))
haikufont_apply_registry (ptn, tem);
@@ -588,27 +678,29 @@ haikufont_match (struct frame *f, Lisp_Object font_spec)
static Lisp_Object
haikufont_list (struct frame *f, Lisp_Object font_spec)
{
- block_input ();
- Lisp_Object lst = Qnil;
+ Lisp_Object lst, tem;
+ struct haiku_font_pattern ptn, *found, *pt;
+ lst = Qnil;
+
+ block_input ();
/* Returning irrelevant results on receiving an OTF form will cause
fontset.c to loop over and over, making displaying some
characters very slow. */
- Lisp_Object tem = assq_no_quit (QCotf, AREF (font_spec, FONT_EXTRA_INDEX));
+ tem = assq_no_quit (QCotf, AREF (font_spec, FONT_EXTRA_INDEX));
+
if (CONSP (tem) && !NILP (XCDR (tem)))
{
unblock_input ();
return Qnil;
}
- struct haiku_font_pattern ptn;
haikufont_spec_or_entity_to_pattern (font_spec, 1, &ptn);
- struct haiku_font_pattern *found = BFont_find (&ptn);
+ found = BFont_find (&ptn);
haikufont_done_with_query_pattern (&ptn);
if (found)
{
- for (struct haiku_font_pattern *pt = found;
- pt; pt = pt->next)
+ for (pt = found; pt; pt = pt->next)
lst = Fcons (haikufont_pattern_to_entity (pt), lst);
haiku_font_pattern_free (found);
}
@@ -668,10 +760,11 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x)
struct haiku_font_pattern ptn;
struct font *font;
void *be_font;
- Lisp_Object font_object;
- Lisp_Object tem;
+ Lisp_Object font_object, tem, extra, indices, antialias;
+ int px_size, min_width, max_width;
+ int avg_width, height, space_width, ascent;
+ int descent, underline_pos, underline_thickness;
- block_input ();
if (x <= 0)
{
/* Get pixel size from frame instead. */
@@ -679,16 +772,45 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x)
x = NILP (tem) ? 0 : XFIXNAT (tem);
}
- haikufont_spec_or_entity_to_pattern (font_entity, 1, &ptn);
+ extra = AREF (font_entity, FONT_EXTRA_INDEX);
+
+ indices = assq_no_quit (QCindices, extra);
+ antialias = assq_no_quit (QCantialias, extra);
+
+ if (CONSP (indices))
+ indices = XCDR (indices);
+
+ /* If the font's indices is already available, open the font using
+ those instead. */
- if (BFont_open_pattern (&ptn, &be_font, x))
+ if (CONSP (indices) && FIXNUMP (XCAR (indices))
+ && FIXNUMP (XCDR (indices)))
+ {
+ block_input ();
+ be_font = be_open_font_at_index (XFIXNUM (XCAR (indices)),
+ XFIXNUM (XCDR (indices)), x);
+ unblock_input ();
+
+ if (!be_font)
+ return Qnil;
+ }
+ else
{
+ block_input ();
+ haikufont_spec_or_entity_to_pattern (font_entity, 1, &ptn);
+
+ if (BFont_open_pattern (&ptn, &be_font, x))
+ {
+ haikufont_done_with_query_pattern (&ptn);
+ unblock_input ();
+ return Qnil;
+ }
+
haikufont_done_with_query_pattern (&ptn);
unblock_input ();
- return Qnil;
}
- haikufont_done_with_query_pattern (&ptn);
+ block_input ();
font_object = font_make_object (VECSIZE (struct haikufont_info),
font_entity, x);
@@ -706,6 +828,9 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x)
font_info->be_font = be_font;
font_info->glyphs = xzalloc (0x100 * sizeof *font_info->glyphs);
+ if (CONSP (antialias))
+ be_set_font_antialiasing (be_font, !NILP (XCDR (antialias)));
+
font->pixel_size = 0;
font->driver = &haikufont_driver;
font->encoding_charset = -1;
@@ -718,14 +843,10 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x)
font_info->metrics = NULL;
font_info->metrics_nrows = 0;
- int px_size, min_width, max_width,
- avg_width, height, space_width, ascent,
- descent, underline_pos, underline_thickness;
-
- BFont_dat (be_font, &px_size, &min_width,
- &max_width, &avg_width, &height,
- &space_width, &ascent, &descent,
- &underline_pos, &underline_thickness);
+ BFont_metrics (be_font, &px_size, &min_width,
+ &max_width, &avg_width, &height,
+ &space_width, &ascent, &descent,
+ &underline_pos, &underline_thickness);
font->pixel_size = px_size;
font->min_width = min_width;
@@ -752,22 +873,31 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x)
static void
haikufont_close (struct font *font)
{
+ struct haikufont_info *info = (struct haikufont_info *) font;
+ int i;
+
if (font_data_structures_may_be_ill_formed ())
return;
- struct haikufont_info *info = (struct haikufont_info *) font;
block_input ();
if (info && info->be_font)
BFont_close (info->be_font);
- for (int i = 0; i < info->metrics_nrows; i++)
- if (info->metrics[i])
- xfree (info->metrics[i]);
+ for (i = 0; i < info->metrics_nrows; i++)
+ {
+ if (info->metrics[i])
+ xfree (info->metrics[i]);
+ }
+
if (info->metrics)
xfree (info->metrics);
- for (int i = 0; i < 0x100; ++i)
- if (info->glyphs[i])
- xfree (info->glyphs[i]);
+
+ for (i = 0; i < 0x100; ++i)
+ {
+ if (info->glyphs[i])
+ xfree (info->glyphs[i]);
+ }
+
xfree (info->glyphs);
unblock_input ();
}
@@ -951,11 +1081,21 @@ haikufont_draw (struct glyph_string *s, int from, int to,
struct font_info *info = (struct font_info *) s->font;
unsigned char mb[MAX_MULTIBYTE_LENGTH];
void *view = FRAME_HAIKU_VIEW (f);
+ unsigned long foreground, background;
block_input ();
prepare_face_for_display (s->f, face);
- BView_draw_lock (view);
+ if (s->hl != DRAW_CURSOR)
+ {
+ foreground = s->face->foreground;
+ background = s->face->background;
+ }
+ else
+ haiku_merge_cursor_foreground (s, &foreground, &background);
+
+ /* Presumably the draw lock is already held by
+ haiku_draw_glyph_string; */
if (with_background)
{
int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
@@ -976,18 +1116,12 @@ haikufont_draw (struct glyph_string *s, int from, int to,
s->first_glyph->slice.glyphless.lower_yoff
- s->first_glyph->slice.glyphless.upper_yoff;
- BView_SetHighColor (view, s->hl == DRAW_CURSOR ?
- FRAME_CURSOR_COLOR (s->f).pixel : face->background);
-
- BView_FillRectangle (view, x, y - ascent, s->width, height);
+ haiku_draw_background_rect (s, s->face, x, y - ascent,
+ s->width, height);
s->background_filled_p = 1;
}
- if (s->hl == DRAW_CURSOR)
- BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
- else
- BView_SetHighColor (view, face->foreground);
-
+ BView_SetHighColor (view, foreground);
BView_MovePenTo (view, x, y);
BView_SetFont (view, ((struct haikufont_info *) info)->be_font);
@@ -999,12 +1133,13 @@ haikufont_draw (struct glyph_string *s, int from, int to,
else
{
ptrdiff_t b_len = 0;
- char *b = xmalloc (b_len);
+ char *b = alloca ((to - from + 1) * MAX_MULTIBYTE_LENGTH);
for (int idx = from; idx < to; ++idx)
{
int len = CHAR_STRING (s->char2b[idx], mb);
- b = xrealloc (b, b_len = (b_len + len));
+ b_len += len;
+
if (len == 1)
b[b_len - len] = mb[0];
else
@@ -1012,13 +1147,58 @@ haikufont_draw (struct glyph_string *s, int from, int to,
}
BView_DrawString (view, b, b_len);
- xfree (b);
}
- BView_draw_unlock (view);
+
unblock_input ();
return 1;
}
+static Lisp_Object
+haikufont_list_family (struct frame *f)
+{
+ Lisp_Object list = Qnil;
+ size_t length;
+ ptrdiff_t idx;
+ haiku_font_family_or_style *styles;
+
+ block_input ();
+ styles = be_list_font_families (&length);
+ unblock_input ();
+
+ if (!styles)
+ return list;
+
+ block_input ();
+ for (idx = 0; idx < length; ++idx)
+ {
+ if (styles[idx][0])
+ list = Fcons (intern ((char *) &styles[idx]), list);
+ }
+
+ free (styles);
+ unblock_input ();
+
+ return list;
+}
+
+/* List of boolean properties in font names accepted by this font
+ driver. */
+static const char *const haikufont_booleans[] =
+ {
+ ":antialias",
+ NULL,
+ };
+
+/* List of non-boolean properties. Currently empty. */
+static const char *const haikufont_non_booleans[1];
+
+static void
+haikufont_filter_properties (Lisp_Object font, Lisp_Object alist)
+{
+ font_filter_properties (font, alist, haikufont_booleans,
+ haikufont_non_booleans);
+}
+
struct font_driver const haikufont_driver =
{
.type = LISPSYM_INITIALLY (Qhaiku),
@@ -1032,9 +1212,111 @@ struct font_driver const haikufont_driver =
.prepare_face = haikufont_prepare_face,
.encode_char = haikufont_encode_char,
.text_extents = haikufont_text_extents,
- .shape = haikufont_shape
+ .shape = haikufont_shape,
+ .list_family = haikufont_list_family,
+ .filter_properties = haikufont_filter_properties,
};
+static bool
+haikufont_should_quit_popup (void)
+{
+ return !NILP (Vquit_flag);
+}
+
+DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
+ doc: /* Read a font using a native dialog.
+Return a font spec describing the font chosen by the user.
+
+FRAME is the frame on which to pop up the font chooser. If omitted or
+nil, it defaults to the selected frame.
+If EXCLUDE-PROPORTIONAL is non-nil, exclude proportional fonts
+in the font selection dialog. */)
+ (Lisp_Object frame, Lisp_Object exclude_proportional)
+{
+ struct frame *f;
+ struct font *font;
+ Lisp_Object font_object;
+ haiku_font_family_or_style family, style;
+ int rc, size, initial_family, initial_style, initial_size;
+ struct haiku_font_pattern pattern;
+ Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle, lsize;
+ bool disable_antialiasing, initial_antialias;
+
+ f = decode_window_system_frame (frame);
+
+ if (popup_activated_p)
+ error ("Trying to use a menu from within a menu-entry");
+
+ initial_style = -1;
+ initial_family = -1;
+ initial_size = -1;
+ initial_antialias = true;
+
+ font = FRAME_FONT (f);
+
+ if (font)
+ {
+ XSETFONT (font_object, font);
+
+ haikufont_pattern_from_object (&pattern, font_object);
+ be_find_font_indices (&pattern, &initial_family,
+ &initial_style);
+ haikufont_done_with_query_pattern (&pattern);
+
+ initial_size = font->pixel_size;
+
+ /* This field is safe to access even after
+ haikufont_done_with_query_pattern. */
+ if (pattern.specified & FSPEC_ANTIALIAS)
+ initial_antialias = pattern.use_antialiasing;
+ }
+
+ popup_activated_p++;
+ unrequest_sigio ();
+ rc = be_select_font (process_pending_signals,
+ haikufont_should_quit_popup,
+ &family, &style, &size,
+ !NILP (exclude_proportional),
+ initial_family, initial_style,
+ initial_size, initial_antialias,
+ &disable_antialiasing);
+ request_sigio ();
+ popup_activated_p--;
+
+ if (!rc)
+ quit ();
+
+ be_font_style_to_flags (style, &pattern);
+
+ lfamily = build_string_from_utf8 (family);
+ lweight = (pattern.specified & FSPEC_WEIGHT
+ ? haikufont_weight_to_lisp (pattern.weight) : Qnil);
+ lslant = (pattern.specified & FSPEC_SLANT
+ ? haikufont_slant_to_lisp (pattern.slant) : Qnil);
+ lwidth = (pattern.specified & FSPEC_WIDTH
+ ? haikufont_width_to_lisp (pattern.width) : Qnil);
+ ladstyle = (pattern.specified & FSPEC_STYLE
+ ? intern (pattern.style) : Qnil);
+ lsize = (size >= 0 ? make_fixnum (size) : Qnil);
+
+ if (disable_antialiasing)
+ return CALLN (Ffont_spec, QCfamily, lfamily,
+ QCweight, lweight, QCslant, lslant,
+ QCwidth, lwidth, QCadstyle, ladstyle,
+ QCsize, lsize, QCantialias, Qnil);
+
+ return CALLN (Ffont_spec, QCfamily, lfamily,
+ QCweight, lweight, QCslant, lslant,
+ QCwidth, lwidth, QCadstyle, ladstyle,
+ QCsize, lsize);
+}
+
+static void
+syms_of_haikufont_for_pdumper (void)
+{
+ register_font_driver (&haikufont_driver, NULL);
+}
+
void
syms_of_haikufont (void)
{
@@ -1054,10 +1336,22 @@ syms_of_haikufont (void)
DEFSYM (Qexpanded, "expanded");
DEFSYM (Qextra_expanded, "extra-expanded");
DEFSYM (Qultra_expanded, "ultra-expanded");
+ DEFSYM (Qregular, "regular");
DEFSYM (Qzh, "zh");
DEFSYM (Qko, "ko");
DEFSYM (Qjp, "jp");
+ DEFSYM (QCindices, ":indices");
+
+#ifdef USE_BE_CAIRO
+ Fput (Qhaiku, Qfont_driver_superseded_by, Qftcr);
+#endif
+ pdumper_do_now_and_after_load (syms_of_haikufont_for_pdumper);
+
font_cache = list (Qnil);
staticpro (&font_cache);
+
+ defsubr (&Sx_select_font);
+
+ be_init_font_data ();
}
diff --git a/src/haikugui.h b/src/haikugui.h
index b744885a42b..0dc127e6b63 100644
--- a/src/haikugui.h
+++ b/src/haikugui.h
@@ -19,11 +19,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _HAIKU_GUI_H_
#define _HAIKU_GUI_H_
-#ifdef _cplusplus
-extern "C"
-{
-#endif
-
typedef struct haiku_char_struct
{
int rbearing;
@@ -100,7 +95,109 @@ typedef haiku Drawable;
typedef haiku Window;
typedef int Display;
-#ifdef _cplusplus
-};
-#endif
+/* Cursor bitmaps. These are only used to create colored cursors when
+ the user specifies a mouse color. */
+
+MAYBE_UNUSED static unsigned char cross_ptr_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf0, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char cross_ptrmask_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
+ 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00,
+ 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x07, 0xf0, 0x1f, 0xfe, 0x0f, 0xf8, 0x3f, 0xfc, 0x07,
+ 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01,
+ 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0,
+ 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char ibeam_ptr_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
+ 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xc0, 0x01, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char ibeam_ptrmask_bits[] =
+ {
+ 0x00, 0x00, 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0xe0, 0x03, 0xe0,
+ 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03, 0xe0, 0x03,
+ 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char hand_ptr_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xa0, 0x02, 0xa0,
+ 0x02, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char hand_ptrmask_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xf0, 0x07, 0xf0, 0x07, 0xf8,
+ 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f, 0xf8, 0x0f,
+ 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char horizd_ptr_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x28,
+ 0x0a, 0xf4, 0x17, 0x02, 0x20, 0xf4, 0x17, 0x28, 0x0a, 0x10, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char horizd_ptrmask_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x38,
+ 0x0e, 0xfc, 0x1f, 0xfe, 0x3f, 0xfc, 0x1f, 0x38, 0x0e, 0x10, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char vertd_ptr_bits[] =
+ {
+ 0x00, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, 0x50, 0x05, 0x60,
+ 0x03, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x60, 0x03, 0x50, 0x05,
+ 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char vertd_ptrmask_bits[] =
+ {
+ 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xe0,
+ 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07,
+ 0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char hourglass_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x24,
+ 0x10, 0x44, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x88, 0x08,
+ 0x10, 0x04, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00
+ };
+
+MAYBE_UNUSED static unsigned char hourglass_mask_bits[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0xfc,
+ 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xfc, 0x1f, 0xf8, 0x0f,
+ 0xf0, 0x07, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00
+ };
+
#endif /* _HAIKU_GUI_H_ */
diff --git a/src/haikuimage.c b/src/haikuimage.c
index 4ffa214f1cf..af3021c5cd9 100644
--- a/src/haikuimage.c
+++ b/src/haikuimage.c
@@ -42,8 +42,10 @@ haiku_can_use_native_image_api (Lisp_Object type)
mime_type = "image/jpeg";
else if (EQ (type, Qpng))
mime_type = "image/png";
+#ifndef HAVE_GIF
else if (EQ (type, Qgif))
mime_type = "image/gif";
+#endif
else if (EQ (type, Qtiff))
mime_type = "image/tiff";
else if (EQ (type, Qbmp))
@@ -52,6 +54,12 @@ haiku_can_use_native_image_api (Lisp_Object type)
mime_type = "image/svg";
else if (EQ (type, Qpbm))
mime_type = "image/pbm";
+ /* Don't use native image APIs for image types that have animations,
+ since those aren't supported by the Translation Kit. */
+#ifndef HAVE_WEBP
+ else if (EQ (type, Qwebp))
+ mime_type = "image/webp";
+#endif
if (!mime_type)
return 0;
@@ -105,5 +113,4 @@ haiku_load_image (struct frame *f, struct image *img,
void
syms_of_haikuimage (void)
{
- DEFSYM (Qbmp, "bmp");
}
diff --git a/src/haikumenu.c b/src/haikumenu.c
index f335bdacb40..3f68eadfd93 100644
--- a/src/haikumenu.c
+++ b/src/haikumenu.c
@@ -29,37 +29,41 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "haiku_support.h"
static Lisp_Object *volatile menu_item_selection;
+static struct timespec menu_timer_timespec;
int popup_activated_p = 0;
-struct submenu_stack_cell
-{
- void *parent_menu;
- void *pane;
-};
-
static void
digest_menu_items (void *first_menu, int start, int menu_items_used,
- int mbar_p)
+ bool is_menu_bar)
{
void **menus, **panes;
- ssize_t menu_len = (menu_items_used + 1 - start) * sizeof *menus;
- ssize_t pane_len = (menu_items_used + 1 - start) * sizeof *panes;
+ ssize_t menu_len;
+ ssize_t pane_len;
+ int i, menu_depth;
+ void *menu, *window, *view;
+ Lisp_Object pane_name, prefix;
+ const char *pane_string;
+ Lisp_Object item_name, enable, descrip, def, selected, help;
- menus = alloca (menu_len);
- panes = alloca (pane_len);
+ USE_SAFE_ALLOCA;
- int i = start, menu_depth = 0;
+ menu_len = (menu_items_used + 1 - start) * sizeof *menus;
+ pane_len = (menu_items_used + 1 - start) * sizeof *panes;
+ menu = first_menu;
+ i = start;
+ menu_depth = 0;
+
+ menus = SAFE_ALLOCA (menu_len);
+ panes = SAFE_ALLOCA (pane_len);
memset (menus, 0, menu_len);
memset (panes, 0, pane_len);
-
- void *menu = first_menu;
-
menus[0] = first_menu;
- void *window = NULL;
- void *view = NULL;
+ window = NULL;
+ view = NULL;
+
if (FRAMEP (Vmenu_updating_frame) &&
FRAME_LIVE_P (XFRAME (Vmenu_updating_frame)) &&
FRAME_HAIKU_P (XFRAME (Vmenu_updating_frame)))
@@ -69,7 +73,7 @@ digest_menu_items (void *first_menu, int start, int menu_items_used,
}
if (view)
- BView_draw_lock (view);
+ BView_draw_lock (view, false, 0, 0, 0, 0);
while (i < menu_items_used)
{
@@ -88,9 +92,6 @@ digest_menu_items (void *first_menu, int start, int menu_items_used,
i += 1;
else if (EQ (AREF (menu_items, i), Qt))
{
- Lisp_Object pane_name, prefix;
- const char *pane_string;
-
if (menu_items_n_panes == 1)
{
i += MENU_ITEMS_PANE_LENGTH;
@@ -121,7 +122,6 @@ digest_menu_items (void *first_menu, int start, int menu_items_used,
}
else
{
- Lisp_Object item_name, enable, descrip, def, selected, help;
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
@@ -142,22 +142,34 @@ digest_menu_items (void *first_menu, int start, int menu_items_used,
}
if (STRINGP (help) && STRING_MULTIBYTE (help))
- {
- help = ENCODE_UTF_8 (help);
- ASET (menu_items, i + MENU_ITEMS_ITEM_HELP, help);
- }
+ help = ENCODE_UTF_8 (help);
if (i + MENU_ITEMS_ITEM_LENGTH < menu_items_used &&
NILP (AREF (menu_items, i + MENU_ITEMS_ITEM_LENGTH)))
menu = BMenu_new_submenu (menu, SSDATA (item_name), !NILP (enable));
else if (NILP (def) && menu_separator_name_p (SSDATA (item_name)))
BMenu_add_separator (menu);
- else if (!mbar_p)
+ else if (!is_menu_bar)
+ {
+ if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode)))
+ BMenu_add_item (menu, SSDATA (item_name),
+ !NILP (def) ? aref_addr (menu_items, i) : NULL,
+ !NILP (enable), !NILP (selected), 0, window,
+ !NILP (descrip) ? SSDATA (descrip) : NULL,
+ NULL);
+ else
+ BMenu_add_item (menu, SSDATA (item_name),
+ !NILP (def) ? aref_addr (menu_items, i) : NULL,
+ !NILP (enable), !NILP (selected), 0, window,
+ !NILP (descrip) ? SSDATA (descrip) : NULL,
+ STRINGP (help) ? SSDATA (help) : NULL);
+ }
+ else if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode)))
BMenu_add_item (menu, SSDATA (item_name),
- !NILP (def) ? aref_addr (menu_items, i) : NULL,
- !NILP (enable), !NILP (selected), 0, window,
+ !NILP (def) ? (void *) (intptr_t) i : NULL,
+ !NILP (enable), !NILP (selected), 1, window,
!NILP (descrip) ? SSDATA (descrip) : NULL,
- STRINGP (help) ? SSDATA (help) : NULL);
+ NULL);
else
BMenu_add_item (menu, SSDATA (item_name),
!NILP (def) ? (void *) (intptr_t) i : NULL,
@@ -171,6 +183,8 @@ digest_menu_items (void *first_menu, int start, int menu_items_used,
if (view)
BView_draw_unlock (view);
+
+ SAFE_FREE ();
}
static Lisp_Object
@@ -178,6 +192,11 @@ haiku_dialog_show (struct frame *f, Lisp_Object title,
Lisp_Object header, const char **error_name)
{
int i, nb_buttons = 0;
+ bool boundary_seen = false;
+ Lisp_Object pane_name, vals[10];
+ void *alert, *button;
+ bool enabled_item_seen_p = false;
+ int32 val;
*error_name = NULL;
@@ -187,17 +206,15 @@ haiku_dialog_show (struct frame *f, Lisp_Object title,
return Qnil;
}
- Lisp_Object pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
+ pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
i = MENU_ITEMS_PANE_LENGTH;
if (STRING_MULTIBYTE (pane_name))
pane_name = ENCODE_UTF_8 (pane_name);
block_input ();
- void *alert = BAlert_new (SSDATA (pane_name), NILP (header) ? HAIKU_INFO_ALERT :
- HAIKU_IDEA_ALERT);
-
- Lisp_Object vals[10];
+ alert = BAlert_new (SSDATA (pane_name), NILP (header) ? HAIKU_INFO_ALERT :
+ HAIKU_IDEA_ALERT);
while (i < menu_items_used)
{
@@ -217,7 +234,11 @@ haiku_dialog_show (struct frame *f, Lisp_Object title,
if (EQ (item_name, Qquote))
{
+ if (nb_buttons)
+ boundary_seen = true;
+
i++;
+ continue;
}
if (nb_buttons >= 9)
@@ -233,9 +254,11 @@ haiku_dialog_show (struct frame *f, Lisp_Object title,
if (!NILP (descrip) && STRING_MULTIBYTE (descrip))
descrip = ENCODE_UTF_8 (descrip);
- void *button = BAlert_add_button (alert, SSDATA (item_name));
+ button = BAlert_add_button (alert, SSDATA (item_name));
BButton_set_enabled (button, !NILP (enable));
+ enabled_item_seen_p |= !NILP (enable);
+
if (!NILP (descrip))
BView_set_tooltip (button, SSDATA (descrip));
@@ -244,15 +267,39 @@ haiku_dialog_show (struct frame *f, Lisp_Object title,
i += MENU_ITEMS_ITEM_LENGTH;
}
- int32_t val = BAlert_go (alert);
+ /* Haiku only lets us specify a single button to place on the
+ left. */
+ if (boundary_seen)
+ BAlert_set_offset_spacing (alert);
+
+ /* If there isn't a single enabled item, add an "Ok" button so the
+ popup can be dismissed. */
+ if (!enabled_item_seen_p)
+ BAlert_add_button (alert, "Ok");
unblock_input ();
+ unrequest_sigio ();
+ ++popup_activated_p;
+ val = BAlert_go (alert, block_input, unblock_input,
+ process_pending_signals);
+ --popup_activated_p;
+ request_sigio ();
+
if (val < 0)
quit ();
- else
+ else if (val < nb_buttons)
return vals[val];
- return Qnil;
+ /* The dialog was dismissed via the button appended to dismiss popup
+ dialogs without a single enabled item. */
+ if (nb_buttons)
+ quit ();
+ /* Otherwise, the Ok button was added because no buttons were seen
+ at all. */
+ else
+ return Qt;
+
+ emacs_abort ();
}
Lisp_Object
@@ -261,7 +308,7 @@ haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
Lisp_Object title;
const char *error_name = NULL;
Lisp_Object selection;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
check_window_system (f);
@@ -279,9 +326,7 @@ haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
list_of_panes (list1 (contents));
/* Display them in a dialog box. */
- block_input ();
selection = haiku_dialog_show (f, title, header, &error_name);
- unblock_input ();
unbind_to (specpdl_count, Qnil);
discard_menu_items ();
@@ -291,16 +336,65 @@ haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
return selection;
}
+static void
+haiku_menu_show_help (void *help, void *data)
+{
+ Lisp_Object *id = (Lisp_Object *) help;
+
+ if (help)
+ show_help_echo (id[MENU_ITEMS_ITEM_HELP],
+ Qnil, Qnil, Qnil);
+ else
+ show_help_echo (Qnil, Qnil, Qnil, Qnil);
+}
+
+static Lisp_Object
+haiku_process_pending_signals_for_menu_1 (void *ptr)
+{
+ menu_timer_timespec = timer_check ();
+
+ return Qnil;
+}
+
+static Lisp_Object
+haiku_process_pending_signals_for_menu_2 (enum nonlocal_exit exit, Lisp_Object error)
+{
+ menu_timer_timespec.tv_sec = 0;
+ menu_timer_timespec.tv_nsec = -1;
+
+ return Qnil;
+}
+
+static struct timespec
+haiku_process_pending_signals_for_menu (void)
+{
+ process_pending_signals ();
+
+ /* The original idea was to let timers throw so that timeouts can
+ work correctly, but there's no way to pop down a BPopupMenu
+ that's currently popped up. */
+ internal_catch_all (haiku_process_pending_signals_for_menu_1, NULL,
+ haiku_process_pending_signals_for_menu_2);
+
+ return menu_timer_timespec;
+}
+
Lisp_Object
haiku_menu_show (struct frame *f, int x, int y, int menuflags,
Lisp_Object title, const char **error_name)
{
- int i = 0, submenu_depth = 0;
- void *view = FRAME_HAIKU_VIEW (f);
- void *menu;
+ int i, submenu_depth, j;
+ void *view, *menu;
+ Lisp_Object *subprefix_stack;
+ Lisp_Object prefix, entry;
- Lisp_Object *subprefix_stack =
- alloca (menu_items_used * sizeof (Lisp_Object));
+ USE_SAFE_ALLOCA;
+
+ view = FRAME_HAIKU_VIEW (f);
+ i = 0;
+ submenu_depth = 0;
+ subprefix_stack
+ = SAFE_ALLOCA (menu_items_used * sizeof (Lisp_Object));
eassert (FRAME_HAIKU_P (f));
@@ -309,6 +403,8 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags,
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
+
+ SAFE_FREE ();
return Qnil;
}
@@ -324,15 +420,20 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags,
}
digest_menu_items (menu, 0, menu_items_used, 0);
BView_convert_to_screen (view, &x, &y);
- menu_item_selection = BMenu_run (menu, x, y);
unblock_input ();
+ unrequest_sigio ();
+ popup_activated_p++;
+ menu_item_selection = BMenu_run (menu, x, y, haiku_menu_show_help,
+ block_input, unblock_input,
+ haiku_process_pending_signals_for_menu, NULL);
+ popup_activated_p--;
+ request_sigio ();
+
FRAME_DISPLAY_INFO (f)->grabbed = 0;
if (menu_item_selection)
{
- Lisp_Object prefix, entry;
-
prefix = entry = Qnil;
i = 0;
while (i < menu_items_used)
@@ -366,8 +467,6 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags,
{
if (menuflags & MENU_KEYMAPS)
{
- int j;
-
entry = list1 (entry);
if (!NILP (prefix))
entry = Fcons (prefix, entry);
@@ -378,6 +477,8 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags,
block_input ();
BPopUpMenu_delete (menu);
unblock_input ();
+
+ SAFE_FREE ();
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
@@ -394,20 +495,27 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags,
block_input ();
BPopUpMenu_delete (menu);
unblock_input ();
+
+ SAFE_FREE ();
return Qnil;
}
void
free_frame_menubar (struct frame *f)
{
+ void *mbar;
+
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_MENU_BAR_HEIGHT (f) = 0;
FRAME_EXTERNAL_MENU_BAR (f) = 0;
block_input ();
- void *mbar = FRAME_HAIKU_MENU_BAR (f);
+ mbar = FRAME_HAIKU_MENU_BAR (f);
+ FRAME_HAIKU_MENU_BAR (f) = NULL;
+
if (mbar)
BMenuBar_delete (mbar);
+
if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
--popup_activated_p;
FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
@@ -430,28 +538,38 @@ set_frame_menubar (struct frame *f, bool deep_p)
{
void *mbar = FRAME_HAIKU_MENU_BAR (f);
void *view = FRAME_HAIKU_VIEW (f);
-
- int first_time_p = 0;
+ bool first_time_p = false;
if (!mbar)
{
+ block_input ();
mbar = FRAME_HAIKU_MENU_BAR (f) = BMenuBar_new (view);
first_time_p = 1;
+
+ /* Now wait for the MENU_BAR_RESIZE event informing us of the
+ initial dimensions of that menu bar. */
+ if (FRAME_VISIBLE_P (f))
+ haiku_wait_for_event (f, MENU_BAR_RESIZE);
+
+ unblock_input ();
}
Lisp_Object items;
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
+ int count;
+ ptrdiff_t subitems, i;
+ int *submenu_start, *submenu_end, *submenu_n_panes;
+ Lisp_Object *submenu_names;
XSETFRAME (Vmenu_updating_frame, f);
if (!deep_p)
{
- FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 0;
items = FRAME_MENU_BAR_ITEMS (f);
Lisp_Object string;
@@ -490,6 +608,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
do always reinitialize them. */
if (first_time_p)
previous_menu_items_used = 0;
+
buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
specbind (Qinhibit_quit, Qt);
/* Don't let the debugger step into this code
@@ -525,29 +644,23 @@ set_frame_menubar (struct frame *f, bool deep_p)
/* Fill in menu_items with the current menu bar contents.
This can evaluate Lisp code. */
save_menu_items ();
+
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
- init_menu_items ();
- int i;
- int count = BMenu_count_items (mbar);
- int subitems = ASIZE (items) / 4;
-
- int *submenu_start, *submenu_end, *submenu_n_panes;
- Lisp_Object *submenu_names;
-
+ subitems = ASIZE (items) / 4;
submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
submenu_end = alloca (subitems * sizeof *submenu_end);
submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
submenu_names = alloca (subitems * sizeof (Lisp_Object));
- for (i = 0; i < subitems; ++i)
+ init_menu_items ();
+ for (i = 0; i < subitems; i++)
{
Lisp_Object key, string, maps;
- key = AREF (items, i * 4);
- string = AREF (items, i * 4 + 1);
- maps = AREF (items, i * 4 + 2);
-
+ key = AREF (items, 4 * i);
+ string = AREF (items, 4 * i + 1);
+ maps = AREF (items, 4 * i + 2);
if (NILP (string))
break;
@@ -555,16 +668,42 @@ set_frame_menubar (struct frame *f, bool deep_p)
string = ENCODE_UTF_8 (string);
submenu_start[i] = menu_items_used;
+
menu_items_n_panes = 0;
parse_single_submenu (key, string, maps);
submenu_n_panes[i] = menu_items_n_panes;
+
submenu_end[i] = menu_items_used;
submenu_names[i] = string;
}
- finish_menu_items ();
+
submenu_start[i] = -1;
+ finish_menu_items ();
+
+ set_buffer_internal_1 (prev);
+
+ /* If there has been no change in the Lisp-level contents
+ of the menu bar, skip redisplaying it. Just exit. */
+
+ /* Compare the new menu items with the ones computed last time. */
+ for (i = 0; i < previous_menu_items_used; i++)
+ if (menu_items_used == i
+ || (!EQ (previous_items[i], AREF (menu_items, i))))
+ break;
+ if (i == menu_items_used && i == previous_menu_items_used && i != 0)
+ {
+ /* The menu items have not changed. Don't bother updating
+ the menus in any form, since it would be a no-op. */
+ discard_menu_items ();
+ unbind_to (specpdl_count, Qnil);
+ return;
+ }
+
+ /* Convert menu_items into widget_value trees
+ to display the menu. This cannot evaluate Lisp code. */
block_input ();
+ count = BMenu_count_items (mbar);
for (i = 0; submenu_start[i] >= 0; ++i)
{
void *mn = NULL;
@@ -580,31 +719,23 @@ set_frame_menubar (struct frame *f, bool deep_p)
}
unblock_input ();
- set_buffer_internal_1 (prev);
-
- FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 1;
+ /* The menu items are different, so store them in the frame. */
fset_menu_bar_vector (f, menu_items);
f->menu_bar_items_used = menu_items_used;
}
+
+ /* This undoes save_menu_items. */
unbind_to (specpdl_count, Qnil);
}
void
run_menu_bar_help_event (struct frame *f, int mb_idx)
{
- Lisp_Object frame;
- Lisp_Object vec;
- Lisp_Object help;
-
- block_input ();
- if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
- {
- unblock_input ();
- return;
- }
+ Lisp_Object frame, vec, help;
XSETFRAME (frame, f);
+ block_input ();
if (mb_idx < 0)
{
kbd_buffer_store_help_event (frame, Qnil);
@@ -613,8 +744,8 @@ run_menu_bar_help_event (struct frame *f, int mb_idx)
}
vec = f->menu_bar_vector;
- if (mb_idx >= ASIZE (vec))
- emacs_abort ();
+ if ((mb_idx + MENU_ITEMS_ITEM_HELP) >= ASIZE (vec))
+ return;
help = AREF (vec, mb_idx + MENU_ITEMS_ITEM_HELP);
if (STRINGP (help) || NILP (help))
@@ -639,23 +770,65 @@ the position of the last non-menu event instead. */)
(Lisp_Object frame)
{
struct frame *f = decode_window_system_frame (frame);
+ int rc;
if (FRAME_EXTERNAL_MENU_BAR (f))
{
- if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
- set_frame_menubar (f, 1);
+ block_input ();
+ set_frame_menubar (f, 1);
+ rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
+ unblock_input ();
+
+ if (!rc)
+ return Qnil;
+
+ FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
+ popup_activated_p += 1;
}
else
+ return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map),
+ last_nonmenu_event);
+
+ return Qnil;
+}
+
+void
+haiku_activate_menubar (struct frame *f)
+{
+ int rc;
+
+ if (!FRAME_HAIKU_MENU_BAR (f))
+ return;
+
+ set_frame_menubar (f, true);
+
+ if (FRAME_OUTPUT_DATA (f)->saved_menu_event)
{
- return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map),
- last_nonmenu_event);
+ block_input ();
+ rc = be_replay_menu_bar_event (FRAME_HAIKU_MENU_BAR (f),
+ FRAME_OUTPUT_DATA (f)->saved_menu_event);
+ xfree (FRAME_OUTPUT_DATA (f)->saved_menu_event);
+ FRAME_OUTPUT_DATA (f)->saved_menu_event = NULL;
+ unblock_input ();
+
+ if (!rc)
+ return;
+
+ FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
+ popup_activated_p += 1;
}
+ else
+ {
+ block_input ();
+ rc = BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
+ unblock_input ();
- block_input ();
- BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
- unblock_input ();
+ if (!rc)
+ return;
- return Qnil;
+ FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
+ popup_activated_p += 1;
+ }
}
void
@@ -664,6 +837,7 @@ syms_of_haikumenu (void)
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
DEFSYM (Qpopup_menu, "popup-menu");
DEFSYM (Qmouse_menu_bar_map, "mouse-menu-bar-map");
+ DEFSYM (Qtooltip_mode, "tooltip-mode");
defsubr (&Smenu_or_popup_active_p);
defsubr (&Shaiku_menu_bar_open);
diff --git a/src/haikuselect.c b/src/haikuselect.c
index 2e619c69f7a..9d8c4a2cd16 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -23,152 +23,1077 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "coding.h"
#include "haikuselect.h"
#include "haikuterm.h"
+#include "haiku_support.h"
+#include "keyboard.h"
#include <stdlib.h>
-static Lisp_Object
-haiku_selection_data_1 (Lisp_Object clipboard)
-{
- Lisp_Object result = Qnil;
- char *targets[256];
+/* The frame that is currently the source of a drag-and-drop
+ operation, or NULL if none is in progress. The reason for this
+ variable is to prevent it from being deleted, which really breaks
+ the nested event loop inside be_drag_message. */
+struct frame *haiku_dnd_frame;
- block_input ();
+/* Whether or not to move the tip frame during drag-and-drop. */
+bool haiku_dnd_follow_tooltip;
+
+static void haiku_lisp_to_message (Lisp_Object, void *);
+
+static enum haiku_clipboard
+haiku_get_clipboard_name (Lisp_Object clipboard)
+{
if (EQ (clipboard, QPRIMARY))
- BClipboard_primary_targets ((char **) &targets, 256);
- else if (EQ (clipboard, QSECONDARY))
- BClipboard_secondary_targets ((char **) &targets, 256);
- else if (EQ (clipboard, QCLIPBOARD))
- BClipboard_system_targets ((char **) &targets, 256);
- else
- {
- unblock_input ();
- signal_error ("Bad clipboard", clipboard);
- }
+ return CLIPBOARD_PRIMARY;
- for (int i = 0; targets[i]; ++i)
- {
- result = Fcons (build_unibyte_string (targets[i]),
- result);
- free (targets[i]);
- }
- unblock_input ();
+ if (EQ (clipboard, QSECONDARY))
+ return CLIPBOARD_SECONDARY;
- return result;
-}
+ if (EQ (clipboard, QCLIPBOARD))
+ return CLIPBOARD_CLIPBOARD;
-DEFUN ("haiku-selection-targets", Fhaiku_selection_targets,
- Shaiku_selection_targets, 1, 1, 0,
- doc: /* Find the types of data available from CLIPBOARD.
-CLIPBOARD should be the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'.
-Return the available types as a list of strings. */)
- (Lisp_Object clipboard)
-{
- return haiku_selection_data_1 (clipboard);
+ signal_error ("Invalid clipboard", clipboard);
}
DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data,
2, 2, 0,
doc: /* Retrieve content typed as NAME from the clipboard
CLIPBOARD. CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or
-`CLIPBOARD'. NAME is a MIME type denoting the type of the data to
-fetch. */)
+`CLIPBOARD'. NAME is a string describing the MIME type denoting the
+type of the data to fetch. If NAME is nil, then the entire contents
+of the clipboard will be returned instead, as a serialized system
+message in the format accepted by `haiku-drag-message', which see. */)
(Lisp_Object clipboard, Lisp_Object name)
{
- CHECK_SYMBOL (clipboard);
- CHECK_STRING (name);
char *dat;
ssize_t len;
+ Lisp_Object str;
+ void *message;
+ enum haiku_clipboard clipboard_name;
+ int rc;
- block_input ();
- if (EQ (clipboard, QPRIMARY))
- dat = BClipboard_find_primary_selection_data (SSDATA (name), &len);
- else if (EQ (clipboard, QSECONDARY))
- dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len);
- else if (EQ (clipboard, QCLIPBOARD))
- dat = BClipboard_find_system_data (SSDATA (name), &len);
- else
+ CHECK_SYMBOL (clipboard);
+ clipboard_name = haiku_get_clipboard_name (clipboard);
+
+ if (!NILP (name))
{
+ CHECK_STRING (name);
+
+ block_input ();
+ dat = be_find_clipboard_data (clipboard_name,
+ SSDATA (name), &len);
unblock_input ();
- signal_error ("Bad clipboard", clipboard);
- }
- unblock_input ();
- if (!dat)
- return Qnil;
+ if (!dat)
+ return Qnil;
- Lisp_Object str = make_unibyte_string (dat, len);
- Lisp_Object lispy_type = Qnil;
+ str = make_unibyte_string (dat, len);
- if (!strcmp (SSDATA (name), "text/utf-8") ||
- !strcmp (SSDATA (name), "text/plain"))
- {
- if (string_ascii_p (str))
- lispy_type = QSTRING;
- else
- lispy_type = QUTF8_STRING;
+ /* `foreign-selection' just means that the selection has to be
+ decoded by `gui-get-selection'. It has no other meaning,
+ AFAICT. */
+ Fput_text_property (make_fixnum (0), make_fixnum (len),
+ Qforeign_selection, Qt, str);
+
+ block_input ();
+ free (dat);
+ unblock_input ();
}
+ else
+ {
+ block_input ();
+ rc = be_lock_clipboard_message (clipboard_name, &message, false);
+ unblock_input ();
- if (!NILP (lispy_type))
- Fput_text_property (make_fixnum (0), make_fixnum (len),
- Qforeign_selection, lispy_type, str);
+ if (rc)
+ signal_error ("Couldn't open clipboard", clipboard);
- block_input ();
- BClipboard_free_data (dat);
- unblock_input ();
+ block_input ();
+ str = haiku_message_to_lisp (message);
+ be_unlock_clipboard (clipboard_name, true);
+ unblock_input ();
+ }
return str;
}
+static void
+haiku_unwind_clipboard_lock (int clipboard)
+{
+ be_unlock_clipboard (clipboard, false);
+}
+
DEFUN ("haiku-selection-put", Fhaiku_selection_put, Shaiku_selection_put,
- 3, 4, 0,
+ 2, 4, 0,
doc: /* Add or remove content from the clipboard CLIPBOARD.
CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'. NAME
is a MIME type denoting the type of the data to add. DATA is the
string that will be placed in the clipboard, or nil if the content is
-to be removed. If NAME is the string "text/utf-8" or the string
-"text/plain", encode it as UTF-8 before storing it into the clipboard.
-CLEAR, if non-nil, means to erase all the previous contents of the
-clipboard. */)
+to be removed. CLEAR, if non-nil, means to erase all the previous
+contents of the clipboard.
+
+Alternatively, NAME can be a system message in the format accepted by
+`haiku-drag-message', which will replace the contents of CLIPBOARD.
+In that case, the arguments after NAME are ignored. */)
(Lisp_Object clipboard, Lisp_Object name, Lisp_Object data,
Lisp_Object clear)
{
+ enum haiku_clipboard clipboard_name;
+ specpdl_ref ref;
+ char *dat;
+ ptrdiff_t len;
+ int rc;
+ void *message;
+
CHECK_SYMBOL (clipboard);
+ clipboard_name = haiku_get_clipboard_name (clipboard);
+
+ if (CONSP (name) || NILP (name))
+ {
+ be_update_clipboard_count (clipboard_name);
+
+ rc = be_lock_clipboard_message (clipboard_name,
+ &message, true);
+
+ if (rc)
+ signal_error ("Couldn't open clipboard", clipboard);
+
+ ref = SPECPDL_INDEX ();
+ record_unwind_protect_int (haiku_unwind_clipboard_lock,
+ clipboard_name);
+ haiku_lisp_to_message (name, message);
+
+ return unbind_to (ref, Qnil);
+ }
+
CHECK_STRING (name);
if (!NILP (data))
CHECK_STRING (data);
+ dat = !NILP (data) ? SSDATA (data) : NULL;
+ len = !NILP (data) ? SBYTES (data) : 0;
+
+ be_set_clipboard_data (clipboard_name, SSDATA (name), dat, len,
+ !NILP (clear));
+ return Qnil;
+}
+
+DEFUN ("haiku-selection-owner-p", Fhaiku_selection_owner_p, Shaiku_selection_owner_p,
+ 0, 1, 0,
+ doc: /* Whether the current Emacs process owns the given SELECTION.
+The arg should be the name of the selection in question, typically one
+of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. */)
+ (Lisp_Object selection)
+{
+ bool value;
+ enum haiku_clipboard name;
+
block_input ();
- /* It seems that Haiku applications counter-intuitively expect
- UTF-8 data in both text/utf-8 and text/plain. */
- if (!NILP (data) && STRING_MULTIBYTE (data) &&
- (!strcmp (SSDATA (name), "text/utf-8") ||
- !strcmp (SSDATA (name), "text/plain")))
- data = ENCODE_UTF_8 (data);
+ name = haiku_get_clipboard_name (selection);
+ value = be_clipboard_owner_p (name);
+ unblock_input ();
- char *dat = !NILP (data) ? SSDATA (data) : NULL;
- ptrdiff_t len = !NILP (data) ? SBYTES (data) : 0;
+ return value ? Qt : Qnil;
+}
- if (EQ (clipboard, QPRIMARY))
- BClipboard_set_primary_selection_data (SSDATA (name), dat, len,
- !NILP (clear));
- else if (EQ (clipboard, QSECONDARY))
- BClipboard_set_secondary_selection_data (SSDATA (name), dat, len,
- !NILP (clear));
- else if (EQ (clipboard, QCLIPBOARD))
- BClipboard_set_system_data (SSDATA (name), dat, len, !NILP (clear));
+/* Return the Lisp representation of MESSAGE. See Fhaiku_drag_message
+ for the format of the object returned. */
+Lisp_Object
+haiku_message_to_lisp (void *message)
+{
+ Lisp_Object list = Qnil, tem, t1, t2;
+ const char *name;
+ char *pbuf;
+ const void *buf;
+ ssize_t buf_size;
+ int32 i, j, count, type_code;
+ int rc;
+ void *msg;
+ float point_x, point_y;
+
+ for (i = 0; !be_enum_message (message, &type_code, i,
+ &count, &name); ++i)
+ {
+ tem = Qnil;
+
+ for (j = 0; j < count; ++j)
+ {
+ rc = be_get_message_data (message, name,
+ type_code, j,
+ &buf, &buf_size);
+ if (rc)
+ emacs_abort ();
+
+ switch (type_code)
+ {
+ case 'MSGG':
+ msg = be_get_message_message (message, name, j);
+ if (!msg)
+ memory_full (SIZE_MAX);
+ t1 = haiku_message_to_lisp (msg);
+ BMessage_delete (msg);
+
+ break;
+
+ case 'BOOL':
+ t1 = (*(bool *) buf) ? Qt : Qnil;
+ break;
+
+ case 'RREF':
+ rc = be_get_refs_data (message, name,
+ j, &pbuf);
+
+ if (rc)
+ {
+ t1 = Qnil;
+ break;
+ }
+
+ if (!pbuf)
+ memory_full (SIZE_MAX);
+
+ t1 = DECODE_FILE (build_string (pbuf));
+
+ free (pbuf);
+ break;
+
+ case 'BPNT':
+ rc = be_get_point_data (message, name,
+ j, &point_x,
+ &point_y);
+
+ if (rc)
+ {
+ t1 = Qnil;
+ break;
+ }
+
+ t1 = Fcons (make_float (point_x),
+ make_float (point_y));
+ break;
+
+ case 'SHRT':
+ t1 = make_fixnum (*(int16 *) buf);
+ break;
+
+ case 'LONG':
+ t1 = make_int (*(int32 *) buf);
+ break;
+
+ case 'LLNG':
+ t1 = make_int ((intmax_t) *(int64 *) buf);
+ break;
+
+ case 'BYTE':
+ case 'CHAR':
+ t1 = make_fixnum (*(int8 *) buf);
+ break;
+
+ case 'SIZT':
+ t1 = make_uint ((uintmax_t) *(size_t *) buf);
+ break;
+
+ case 'SSZT':
+ t1 = make_int ((intmax_t) *(ssize_t *) buf);
+ break;
+
+ case 'DBLE':
+ t1 = make_float (*(double *) buf);
+ break;
+
+ case 'FLOT':
+ t1 = make_float (*(float *) buf);
+ break;
+
+ default:
+ t1 = make_uninit_string (buf_size);
+ memcpy (SDATA (t1), buf, buf_size);
+ }
+
+ tem = Fcons (t1, tem);
+ }
+
+ switch (type_code)
+ {
+ case 'CSTR':
+ t2 = Qstring;
+ break;
+
+ case 'SHRT':
+ t2 = Qshort;
+ break;
+
+ case 'LONG':
+ t2 = Qlong;
+ break;
+
+ case 'LLNG':
+ t2 = Qllong;
+ break;
+
+ case 'BYTE':
+ t2 = Qbyte;
+ break;
+
+ case 'RREF':
+ t2 = Qref;
+ break;
+
+ case 'CHAR':
+ t2 = Qchar;
+ break;
+
+ case 'BOOL':
+ t2 = Qbool;
+ break;
+
+ case 'MSGG':
+ t2 = Qmessage;
+ break;
+
+ case 'SIZT':
+ t2 = Qsize_t;
+ break;
+
+ case 'SSZT':
+ t2 = Qssize_t;
+ break;
+
+ case 'BPNT':
+ t2 = Qpoint;
+ break;
+
+ case 'DBLE':
+ t2 = Qdouble;
+ break;
+
+ case 'FLOT':
+ t2 = Qfloat;
+ break;
+
+ default:
+ t2 = make_int (type_code);
+ }
+
+ tem = Fcons (t2, tem);
+ list = Fcons (Fcons (build_string_from_utf8 (name), tem), list);
+ }
+
+ tem = Fcons (Qtype, make_uint (be_get_message_type (message)));
+ return Fcons (tem, list);
+}
+
+static int32
+lisp_to_type_code (Lisp_Object obj)
+{
+ if (BIGNUMP (obj))
+ return (int32) bignum_to_intmax (obj);
+
+ if (FIXNUMP (obj))
+ return XFIXNUM (obj);
+
+ if (EQ (obj, Qstring))
+ return 'CSTR';
+ else if (EQ (obj, Qshort))
+ return 'SHRT';
+ else if (EQ (obj, Qlong))
+ return 'LONG';
+ else if (EQ (obj, Qllong))
+ return 'LLNG';
+ else if (EQ (obj, Qbyte))
+ return 'BYTE';
+ else if (EQ (obj, Qref))
+ return 'RREF';
+ else if (EQ (obj, Qchar))
+ return 'CHAR';
+ else if (EQ (obj, Qbool))
+ return 'BOOL';
+ else if (EQ (obj, Qmessage))
+ return 'MSGG';
+ else if (EQ (obj, Qsize_t))
+ return 'SIZT';
+ else if (EQ (obj, Qssize_t))
+ return 'SSZT';
+ else if (EQ (obj, Qpoint))
+ return 'BPNT';
+ else if (EQ (obj, Qfloat))
+ return 'FLOT';
+ else if (EQ (obj, Qdouble))
+ return 'DBLE';
else
+ return -1;
+}
+
+static void
+haiku_lisp_to_message (Lisp_Object obj, void *message)
+{
+ Lisp_Object tem, t1, name, type_sym, t2, data;
+ int32 type_code, long_data;
+ int16 short_data;
+ int64 llong_data;
+ int8 char_data;
+ bool bool_data;
+ void *msg_data;
+ size_t sizet_data;
+ ssize_t ssizet_data;
+ intmax_t t4;
+ uintmax_t t5;
+ float t6, t7, float_data;
+ double double_data;
+ int rc;
+ specpdl_ref ref;
+
+ tem = obj;
+
+ FOR_EACH_TAIL (tem)
{
- unblock_input ();
- signal_error ("Bad clipboard", clipboard);
+ t1 = XCAR (tem);
+ CHECK_CONS (t1);
+
+ name = XCAR (t1);
+
+ if (EQ (name, Qtype))
+ {
+ t2 = XCDR (t1);
+
+ if (BIGNUMP (t2))
+ {
+ t5 = bignum_to_uintmax (t2);
+
+ if (!t5 || t5 > TYPE_MAXIMUM (uint32))
+ signal_error ("Value too large", t2);
+
+ block_input ();
+ be_set_message_type (message, t5);
+ unblock_input ();
+ }
+ else
+ {
+ if (!TYPE_RANGED_FIXNUMP (uint32, t2))
+ signal_error ("Invalid data type", t2);
+
+ block_input ();
+ be_set_message_type (message, XFIXNAT (t2));
+ unblock_input ();
+ }
+
+ continue;
+ }
+
+ CHECK_STRING (name);
+
+ t1 = XCDR (t1);
+ CHECK_CONS (t1);
+
+ type_sym = XCAR (t1);
+ type_code = lisp_to_type_code (type_sym);
+
+ if (type_code == -1)
+ signal_error ("Unknown data type", type_sym);
+
+ CHECK_LIST (t1);
+ t2 = XCDR (t1);
+ FOR_EACH_TAIL (t2)
+ {
+ data = XCAR (t2);
+
+ if (FIXNUMP (type_sym) || BIGNUMP (type_sym))
+ goto decode_normally;
+
+ switch (type_code)
+ {
+ case 'MSGG':
+ ref = SPECPDL_INDEX ();
+
+ block_input ();
+ msg_data = be_create_simple_message ();
+ unblock_input ();
+
+ record_unwind_protect_ptr (BMessage_delete, msg_data);
+ haiku_lisp_to_message (data, msg_data);
+
+ block_input ();
+ rc = be_add_message_message (message, SSDATA (name), msg_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Invalid message", data);
+ unbind_to (ref, Qnil);
+ break;
+
+ case 'RREF':
+ CHECK_STRING (data);
+
+ if (be_add_refs_data (message, SSDATA (name),
+ SSDATA (ENCODE_FILE (data)))
+ && haiku_signal_invalid_refs)
+ signal_error ("Invalid file name", data);
+ break;
+
+ case 'BPNT':
+ CHECK_CONS (data);
+ CHECK_NUMBER (XCAR (data));
+ CHECK_NUMBER (XCDR (data));
+
+ t6 = XFLOATINT (XCAR (data));
+ t7 = XFLOATINT (XCDR (data));
+
+ if (be_add_point_data (message, SSDATA (name),
+ t6, t7))
+ signal_error ("Invalid point", data);
+ break;
+
+ case 'FLOT':
+ CHECK_NUMBER (data);
+ float_data = XFLOATINT (data);
+
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &float_data,
+ sizeof float_data);
+
+ if (rc)
+ signal_error ("Failed to add float", data);
+ break;
+
+ case 'DBLE':
+ CHECK_NUMBER (data);
+ double_data = XFLOATINT (data);
+
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &double_data,
+ sizeof double_data);
+
+ if (rc)
+ signal_error ("Failed to add double", data);
+ break;
+
+ case 'SHRT':
+ if (!TYPE_RANGED_FIXNUMP (int16, data))
+ signal_error ("Invalid value", data);
+ short_data = XFIXNUM (data);
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &short_data,
+ sizeof short_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add short", data);
+ break;
+
+ case 'LONG':
+ if (BIGNUMP (data))
+ {
+ t4 = bignum_to_intmax (data);
+
+ /* We know that int32 is signed. */
+ if (!t4 || t4 > TYPE_MINIMUM (int32)
+ || t4 < TYPE_MAXIMUM (int32))
+ signal_error ("Value too large", data);
+
+ long_data = (int32) t4;
+ }
+ else
+ {
+ if (!TYPE_RANGED_FIXNUMP (int32, data))
+ signal_error ("Invalid value", data);
+
+ long_data = (int32) XFIXNUM (data);
+ }
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &long_data,
+ sizeof long_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add long", data);
+ break;
+
+ case 'LLNG':
+ if (BIGNUMP (data))
+ {
+ t4 = bignum_to_intmax (data);
+
+ if (!t4 || t4 > TYPE_MINIMUM (int64)
+ || t4 < TYPE_MAXIMUM (int64))
+ signal_error ("Value too large", data);
+
+ llong_data = (int64) t4;
+ }
+ else
+ {
+ if (!TYPE_RANGED_FIXNUMP (int64, data))
+ signal_error ("Invalid value", data);
+
+ llong_data = (int64) XFIXNUM (data);
+ }
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &llong_data,
+ sizeof llong_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add llong", data);
+ break;
+
+ case 'SIZT':
+ if (BIGNUMP (data))
+ {
+ t4 = bignum_to_intmax (data);
+
+ if (!t4 || t4 > TYPE_MAXIMUM (size_t))
+ signal_error ("Value too large", data);
+
+ sizet_data = (size_t) t4;
+ }
+ else
+ {
+ if (!TYPE_RANGED_FIXNUMP (size_t, data))
+ signal_error ("Invalid value", data);
+
+ sizet_data = (int64) XFIXNUM (data);
+ }
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &sizet_data,
+ sizeof sizet_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add sizet", data);
+ break;
+
+ case 'SSZT':
+ if (BIGNUMP (data))
+ {
+ t4 = bignum_to_intmax (data);
+
+ if (!t4 || t4 > TYPE_MINIMUM (ssize_t)
+ || t4 < TYPE_MAXIMUM (ssize_t))
+ signal_error ("Value too large", data);
+
+ ssizet_data = (ssize_t) t4;
+ }
+ else
+ {
+ if (!TYPE_RANGED_FIXNUMP (ssize_t, data))
+ signal_error ("Invalid value", data);
+
+ ssizet_data = (int64) XFIXNUM (data);
+ }
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &ssizet_data,
+ sizeof ssizet_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add ssizet", data);
+ break;
+
+ case 'CHAR':
+ case 'BYTE':
+ if (!TYPE_RANGED_FIXNUMP (int8, data))
+ signal_error ("Invalid value", data);
+ char_data = XFIXNUM (data);
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &char_data,
+ sizeof char_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add char", data);
+ break;
+
+ case 'BOOL':
+ bool_data = !NILP (data);
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, &bool_data,
+ sizeof bool_data);
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add bool", data);
+ break;
+
+ default:
+ decode_normally:
+ CHECK_STRING (data);
+
+ block_input ();
+ rc = be_add_message_data (message, SSDATA (name),
+ type_code, SDATA (data),
+ SBYTES (data));
+ unblock_input ();
+
+ if (rc)
+ signal_error ("Failed to add", data);
+ }
+ }
+ CHECK_LIST_END (t2, t1);
}
+ CHECK_LIST_END (tem, obj);
+}
+
+static bool
+haiku_should_quit_drag (void)
+{
+ return !NILP (Vquit_flag);
+}
+
+static void
+haiku_unwind_drag_message (void *message)
+{
+ haiku_dnd_frame = NULL;
+ BMessage_delete (message);
+}
+
+DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message,
+ 2, 4, 0,
+ doc: /* Begin dragging MESSAGE from FRAME.
+
+MESSAGE an alist of strings, denoting message field names, to a list
+the form (TYPE DATA ...), where TYPE is an integer denoting the system
+data type of DATA, and DATA is in the general case a unibyte string.
+
+If TYPE is a symbol instead of an integer, then DATA was specially
+decoded. If TYPE is `ref', then DATA is the absolute file name of a
+file, or nil if decoding the file name failed. If TYPE is `string',
+then DATA is a unibyte string. If TYPE is `short', then DATA is a
+16-bit signed integer. If TYPE is `long', then DATA is a 32-bit
+signed integer. If TYPE is `llong', then DATA is a 64-bit signed
+integer. If TYPE is `byte' or `char', then DATA is an 8-bit signed
+integer. If TYPE is `bool', then DATA is a boolean. If TYPE is
+`size_t', then DATA is an integer that can hold between 0 and the
+maximum value returned by the `sizeof' C operator on the current
+system. If TYPE is `ssize_t', then DATA is an integer that can hold
+values from -1 to the maximum value of the C data type `ssize_t' on
+the current system. If TYPE is `point', then DATA is a cons of float
+values describing the X and Y coordinates of an on-screen location.
+If TYPE is `float', then DATA is a low-precision floating point
+number, whose exact precision is not guaranteed. If TYPE is `double',
+then DATA is a floating point number that can represent any value a
+Lisp float can represent.
+
+If the field name is not a string but the symbol `type', then it
+associates to a 32-bit unsigned integer describing the type of the
+system message.
+
+FRAME is a window system frame that must be visible, from which the
+drag will originate.
+
+ALLOW-SAME-FRAME, if nil or not specified, means that MESSAGE will be
+ignored if it is dropped on top of FRAME.
+
+FOLLOW-TOOLTIP, if non-nil, will cause any non-system tooltip
+currently being displayed to move along with the mouse pointer. */)
+ (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame,
+ Lisp_Object follow_tooltip)
+{
+ specpdl_ref idx;
+ void *be_message;
+ struct frame *f;
+ bool rc;
+
+ idx = SPECPDL_INDEX ();
+ f = decode_window_system_frame (frame);
+
+ if (!FRAME_VISIBLE_P (f))
+ error ("Frame is invisible");
+
+ haiku_dnd_frame = f;
+ haiku_dnd_follow_tooltip = !NILP (follow_tooltip);
+ be_message = be_create_simple_message ();
+
+ record_unwind_protect_ptr (haiku_unwind_drag_message, be_message);
+ haiku_lisp_to_message (message, be_message);
+
+ rc = be_drag_message (FRAME_HAIKU_VIEW (f), be_message,
+ !NILP (allow_same_frame),
+ block_input, unblock_input,
+ process_pending_signals,
+ haiku_should_quit_drag);
+
+ /* Don't clear the mouse grab if the user decided to quit instead
+ of the drop finishing. */
+ if (rc)
+ quit ();
+
+ /* Now dismiss the tooltip, since the drop presumably succeeded. */
+ if (!NILP (follow_tooltip))
+ Fx_hide_tip ();
+
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
+
+ return unbind_to (idx, Qnil);
+}
+
+DEFUN ("haiku-roster-launch", Fhaiku_roster_launch, Shaiku_roster_launch,
+ 2, 2, 0,
+ doc: /* Launch an application associated with FILE-OR-TYPE.
+Return the process ID of any process created, the symbol
+`already-running' if ARGS was sent to a program that's already
+running, or nil if launching the application failed because no
+application was found for FILE-OR-TYPE.
+
+Signal an error if FILE-OR-TYPE is invalid, or if ARGS is a message
+but the application doesn't accept messages.
+
+FILE-OR-TYPE can either be a string denoting a MIME type, or a list
+with one argument FILE, denoting a file whose associated application
+will be launched.
+
+ARGS can either be a vector of strings containing the arguments that
+will be passed to the application, or a system message in the form
+accepted by `haiku-drag-message' that will be sent to the application
+after it starts. */)
+ (Lisp_Object file_or_type, Lisp_Object args)
+{
+ char **cargs;
+ char *type, *file;
+ team_id team_id;
+ status_t rc;
+ ptrdiff_t i, nargs;
+ Lisp_Object tem, canonical;
+ void *message;
+ specpdl_ref depth;
+
+ type = NULL;
+ file = NULL;
+ cargs = NULL;
+ message = NULL;
+ nargs = 0;
+ depth = SPECPDL_INDEX ();
+
+ USE_SAFE_ALLOCA;
+
+ if (STRINGP (file_or_type))
+ SAFE_ALLOCA_STRING (type, file_or_type);
+ else
+ {
+ CHECK_LIST (file_or_type);
+ tem = XCAR (file_or_type);
+ canonical = Fexpand_file_name (tem, Qnil);
+
+ CHECK_STRING (tem);
+ SAFE_ALLOCA_STRING (file, ENCODE_FILE (canonical));
+ CHECK_LIST_END (XCDR (file_or_type), file_or_type);
+ }
+
+ if (VECTORP (args))
+ {
+ nargs = ASIZE (args);
+ cargs = SAFE_ALLOCA (nargs * sizeof *cargs);
+
+ for (i = 0; i < nargs; ++i)
+ {
+ tem = AREF (args, i);
+ CHECK_STRING (tem);
+ maybe_quit ();
+
+ cargs[i] = SAFE_ALLOCA (SBYTES (tem) + 1);
+ memcpy (cargs[i], SDATA (tem), SBYTES (tem) + 1);
+ }
+ }
+ else
+ {
+ message = be_create_simple_message ();
+
+ record_unwind_protect_ptr (BMessage_delete, message);
+ haiku_lisp_to_message (args, message);
+ }
+
+ block_input ();
+ rc = be_roster_launch (type, file, cargs, nargs, message,
+ &team_id);
unblock_input ();
+ /* `be_roster_launch' can potentially take a while in IO, but
+ signals from async input will interrupt that operation. If the
+ user wanted to quit, act like it. */
+ maybe_quit ();
+
+ if (rc == B_OK)
+ return SAFE_FREE_UNBIND_TO (depth,
+ make_uint (team_id));
+ else if (rc == B_ALREADY_RUNNING)
+ return Qalready_running;
+ else if (rc == B_BAD_VALUE)
+ signal_error ("Invalid type or bad arguments",
+ list2 (file_or_type, args));
+
+ return SAFE_FREE_UNBIND_TO (depth, Qnil);
+}
+
+static void
+haiku_dnd_compute_tip_xy (int *root_x, int *root_y)
+{
+ int min_x, min_y, max_x, max_y;
+ int width, height;
+
+ width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
+ height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
+
+ min_x = 0;
+ min_y = 0;
+ be_get_screen_dimensions (&max_x, &max_y);
+
+ if (*root_y + XFIXNUM (tip_dy) <= min_y)
+ *root_y = min_y; /* Can happen for negative dy */
+ else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
+ /* It fits below the pointer */
+ *root_y += XFIXNUM (tip_dy);
+ else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
+ /* It fits above the pointer. */
+ *root_y -= height + XFIXNUM (tip_dy);
+ else
+ /* Put it on the top. */
+ *root_y = min_y;
+
+ if (*root_x + XFIXNUM (tip_dx) <= min_x)
+ *root_x = 0; /* Can happen for negative dx */
+ else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
+ /* It fits to the right of the pointer. */
+ *root_x += XFIXNUM (tip_dx);
+ else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
+ /* It fits to the left of the pointer. */
+ *root_x -= width + XFIXNUM (tip_dx);
+ else
+ /* Put it left justified on the screen -- it ought to fit that way. */
+ *root_x = min_x;
+}
+
+static Lisp_Object
+haiku_note_drag_motion_1 (void *data)
+{
+ if (!NILP (Vhaiku_drag_track_function))
+ return call0 (Vhaiku_drag_track_function);
+
+ return Qnil;
+}
+
+static Lisp_Object
+haiku_note_drag_motion_2 (enum nonlocal_exit exit, Lisp_Object error)
+{
return Qnil;
}
void
+haiku_note_drag_motion (void)
+{
+ struct frame *tip_f;
+ int x, y;
+
+ if (FRAMEP (tip_frame) && haiku_dnd_follow_tooltip
+ && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
+ {
+ tip_f = XFRAME (tip_frame);
+
+ if (FRAME_LIVE_P (tip_f) && FRAME_VISIBLE_P (tip_f))
+ {
+ BView_get_mouse (FRAME_HAIKU_VIEW (haiku_dnd_frame),
+ &x, &y);
+ BView_convert_to_screen (FRAME_HAIKU_VIEW (haiku_dnd_frame),
+ &x, &y);
+
+ haiku_dnd_compute_tip_xy (&x, &y);
+ BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), x, y);
+ }
+ }
+
+ internal_catch_all (haiku_note_drag_motion_1, NULL,
+ haiku_note_drag_motion_2);
+}
+
+void
+init_haiku_select (void)
+{
+ be_clipboard_init ();
+}
+
+void
+haiku_handle_selection_clear (struct input_event *ie)
+{
+ enum haiku_clipboard id;
+
+ id = haiku_get_clipboard_name (ie->arg);
+
+ if (be_selection_outdated_p (id, ie->timestamp))
+ return;
+
+ CALLN (Frun_hook_with_args,
+ Qhaiku_lost_selection_functions, ie->arg);
+
+ /* This is required for redisplay to happen if something changed the
+ display inside the selection loss functions. */
+ redisplay_preserve_echo_area (20);
+}
+
+void
+haiku_selection_disowned (enum haiku_clipboard id, int64 count)
+{
+ struct input_event ie;
+
+ EVENT_INIT (ie);
+ ie.kind = SELECTION_CLEAR_EVENT;
+
+ switch (id)
+ {
+ case CLIPBOARD_CLIPBOARD:
+ ie.arg = QCLIPBOARD;
+ break;
+
+ case CLIPBOARD_PRIMARY:
+ ie.arg = QPRIMARY;
+ break;
+
+ case CLIPBOARD_SECONDARY:
+ ie.arg = QSECONDARY;
+ break;
+ }
+
+ ie.timestamp = count;
+ kbd_buffer_store_event (&ie);
+}
+
+void
+haiku_start_watching_selections (void)
+{
+ be_start_watching_selection (CLIPBOARD_CLIPBOARD);
+ be_start_watching_selection (CLIPBOARD_PRIMARY);
+ be_start_watching_selection (CLIPBOARD_SECONDARY);
+}
+
+void
syms_of_haikuselect (void)
{
+ DEFVAR_BOOL ("haiku-signal-invalid-refs", haiku_signal_invalid_refs,
+ doc: /* If nil, silently ignore invalid file names in system messages.
+Otherwise, an error will be signalled if adding a file reference to a
+system message failed. */);
+ haiku_signal_invalid_refs = true;
+
+ DEFVAR_LISP ("haiku-drag-track-function", Vhaiku_drag_track_function,
+ doc: /* If non-nil, a function to call upon mouse movement while dragging a message.
+The function is called without any arguments. `mouse-position' can be
+used to retrieve the current position of the mouse. */);
+ Vhaiku_drag_track_function = Qnil;
+
+ DEFVAR_LISP ("haiku-lost-selection-functions", Vhaiku_lost_selection_functions,
+ doc: /* A list of functions to be called when Emacs loses an X selection.
+These are only called if a connection to the Haiku display was opened. */);
+ Vhaiku_lost_selection_functions = Qnil;
+
DEFSYM (QSECONDARY, "SECONDARY");
DEFSYM (QCLIPBOARD, "CLIPBOARD");
DEFSYM (QSTRING, "STRING");
@@ -176,7 +1101,31 @@ syms_of_haikuselect (void)
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (QTARGETS, "TARGETS");
+ DEFSYM (Qhaiku_lost_selection_functions,
+ "haiku-lost-selection-functions");
+
+ DEFSYM (Qmessage, "message");
+ DEFSYM (Qstring, "string");
+ DEFSYM (Qref, "ref");
+ DEFSYM (Qshort, "short");
+ DEFSYM (Qlong, "long");
+ DEFSYM (Qllong, "llong");
+ DEFSYM (Qbyte, "byte");
+ DEFSYM (Qchar, "char");
+ DEFSYM (Qbool, "bool");
+ DEFSYM (Qtype, "type");
+ DEFSYM (Qsize_t, "size_t");
+ DEFSYM (Qssize_t, "ssize_t");
+ DEFSYM (Qpoint, "point");
+ DEFSYM (Qfloat, "float");
+ DEFSYM (Qdouble, "double");
+ DEFSYM (Qalready_running, "already-running");
+
defsubr (&Shaiku_selection_data);
defsubr (&Shaiku_selection_put);
- defsubr (&Shaiku_selection_targets);
+ defsubr (&Shaiku_selection_owner_p);
+ defsubr (&Shaiku_drag_message);
+ defsubr (&Shaiku_roster_launch);
+
+ haiku_dnd_frame = NULL;
}
diff --git a/src/haikuselect.h b/src/haikuselect.h
index 80f33c6ed25..61efeb9cd93 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -21,54 +21,58 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef __cplusplus
#include <cstdio>
+#else
+#include <stdio.h>
#endif
+#include <SupportDefs.h>
+
+enum haiku_clipboard
+ {
+ CLIPBOARD_PRIMARY,
+ CLIPBOARD_SECONDARY,
+ CLIPBOARD_CLIPBOARD
+ };
+
#ifdef __cplusplus
-#include <stdio.h>
extern "C"
{
- extern void init_haiku_select (void);
#endif
+/* Defined in haikuselect.c. */
+extern void haiku_selection_disowned (enum haiku_clipboard, int64);
+
+/* Defined in haiku_select.cc. */
+extern void be_clipboard_init (void);
+extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, ssize_t *);
+extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const char *,
+ ssize_t, bool);
+extern bool be_clipboard_owner_p (enum haiku_clipboard);
+extern void be_update_clipboard_count (enum haiku_clipboard);
+
+extern int be_enum_message (void *, int32 *, int32, int32 *, const char **);
+extern int be_get_message_data (void *, const char *, int32, int32,
+ const void **, ssize_t *);
+extern int be_get_refs_data (void *, const char *, int32, char **);
+extern int be_get_point_data (void *, const char *, int32, float *, float *);
+extern uint32 be_get_message_type (void *);
+extern void be_set_message_type (void *, uint32);
+extern void *be_get_message_message (void *, const char *, int32);
+extern void *be_create_simple_message (void);
+extern int be_add_message_data (void *, const char *, int32, const void *, ssize_t);
+extern int be_add_refs_data (void *, const char *, const char *);
+extern int be_add_point_data (void *, const char *, float, float);
+extern int be_add_message_message (void *, const char *, void *);
+extern int be_lock_clipboard_message (enum haiku_clipboard, void **, bool);
+extern void be_unlock_clipboard (enum haiku_clipboard, bool);
+extern void be_handle_clipboard_changed_message (void);
+extern void be_start_watching_selection (enum haiku_clipboard);
+extern bool be_selection_outdated_p (enum haiku_clipboard, int64);
- /* Whether or not the selection was recently changed. */
- extern int selection_state_flag;
-
- /* Find a string with the MIME type TYPE in the system clipboard. */
- extern char *
- BClipboard_find_system_data (const char *type, ssize_t *len);
-
- /* Ditto, but for the primary selection and not clipboard. */
- extern char *
- BClipboard_find_primary_selection_data (const char *type, ssize_t *len);
-
- /* Ditto, this time for the secondary selection. */
- extern char *
- BClipboard_find_secondary_selection_data (const char *type, ssize_t *len);
-
- extern void
- BClipboard_set_system_data (const char *type, const char *data, ssize_t len,
- bool clear);
-
- extern void
- BClipboard_set_primary_selection_data (const char *type, const char *data,
- ssize_t len, bool clear);
-
- extern void
- BClipboard_set_secondary_selection_data (const char *type, const char *data,
- ssize_t len, bool clear);
-
- extern void
- BClipboard_system_targets (char **buf, int len);
-
- extern void
- BClipboard_primary_targets (char **buf, int len);
-
- extern void
- BClipboard_secondary_targets (char **buf, int len);
-
- /* Free the returned data. */
- extern void BClipboard_free_data (void *ptr);
#ifdef __cplusplus
};
#endif
#endif /* _HAIKU_SELECT_H_ */
+
+// Local Variables:
+// eval: (setf (alist-get 'inextern-lang c-offsets-alist) 0)
+// End:
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 2239770de95..bcb3af0e2c3 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "haiku_support.h"
#include "thread.h"
#include "window.h"
+#include "haikuselect.h"
#include <math.h>
#include <stdlib.h>
@@ -40,20 +41,28 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <cairo.h>
#endif
-struct haiku_display_info *x_display_list = NULL;
-extern frame_parm_handler haiku_frame_parm_handlers[];
+/* Minimum and maximum values used for Haiku scroll bars. */
+#define BE_SB_MAX 12000000
+/* The single Haiku display (if any). */
+struct haiku_display_info *x_display_list;
+
+/* This is used to determine when to evict the font lookup cache,
+ which we do every 50 updates. */
+static int up_to_date_count;
+
+/* List of defined fringe bitmaps. */
static void **fringe_bmps;
-static int fringe_bitmap_fillptr = 0;
+/* The amount of fringe bitmaps in that list. */
+static int max_fringe_bmp;
+
+/* Alist of resources to their values. */
static Lisp_Object rdb;
-struct unhandled_event
-{
- struct unhandled_event *next;
- enum haiku_event_type type;
- uint8_t buffer[200];
-};
+/* Non-zero means that a HELP_EVENT has been generated since Emacs
+ start. */
+static bool any_help_event_p;
char *
get_keysym_name (int keysym)
@@ -88,25 +97,32 @@ static void
haiku_coords_from_parent (struct frame *f, int *x, int *y)
{
struct frame *p = FRAME_PARENT_FRAME (f);
- eassert (p);
- for (struct frame *parent = p; parent;
- parent = FRAME_PARENT_FRAME (parent))
- {
- *x -= parent->left_pos;
- *y -= parent->top_pos;
- }
+ *x -= FRAME_OUTPUT_DATA (p)->frame_x;
+ *y -= FRAME_OUTPUT_DATA (p)->frame_y;
+}
+
+static void
+haiku_toolkit_position (struct frame *f, int x, int y,
+ bool *menu_bar_p, bool *tool_bar_p)
+{
+ if (FRAME_OUTPUT_DATA (f)->menubar)
+ *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
+ && y >= 0 && y < FRAME_MENU_BAR_HEIGHT (f));
}
static void
haiku_delete_terminal (struct terminal *terminal)
{
- emacs_abort ();
+ error ("The Haiku terminal cannot be deleted");
}
static const char *
-get_string_resource (void *ignored, const char *name, const char *class)
+haiku_get_string_resource (void *ignored, const char *name,
+ const char *class)
{
+ const char *native;
+
if (!name)
return NULL;
@@ -115,26 +131,24 @@ get_string_resource (void *ignored, const char *name, const char *class)
if (!NILP (lval))
return SSDATA (XCDR (lval));
+ if ((native = be_find_setting (name)))
+ return native;
+
return NULL;
}
static void
haiku_update_size_hints (struct frame *f)
{
- int base_width, base_height;
- eassert (FRAME_HAIKU_P (f) && FRAME_HAIKU_WINDOW (f));
-
- base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
- base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+ if (f->tooltip)
+ return;
block_input ();
BWindow_set_size_alignment (FRAME_HAIKU_WINDOW (f),
- frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f),
- frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f));
- BWindow_set_min_size (FRAME_HAIKU_WINDOW (f), base_width,
- base_height
- + FRAME_TOOL_BAR_HEIGHT (f)
- + FRAME_MENU_BAR_HEIGHT (f));
+ (frame_resize_pixelwise
+ ? 1 : FRAME_COLUMN_WIDTH (f)),
+ (frame_resize_pixelwise
+ ? 1 : FRAME_LINE_HEIGHT (f)));
unblock_input ();
}
@@ -154,8 +168,12 @@ haiku_clip_to_string (struct glyph_string *s)
FRAME_PIXEL_HEIGHT (s->f),
10, 10);
else
- BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[0].x,
- r[0].y, r[0].width, r[0].height);
+ {
+ BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[0].x,
+ r[0].y, r[0].width, r[0].height);
+ BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), r[0].x,
+ r[0].y, r[0].width, r[0].height);
+ }
}
if (n > 1)
@@ -168,8 +186,12 @@ haiku_clip_to_string (struct glyph_string *s)
FRAME_PIXEL_HEIGHT (s->f),
10, 10);
else
- BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[1].x, r[1].y,
- r[1].width, r[1].height);
+ {
+ BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), r[1].x, r[1].y,
+ r[1].width, r[1].height);
+ BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), r[1].x,
+ r[1].y, r[1].width, r[1].height);
+ }
}
}
@@ -178,6 +200,8 @@ haiku_clip_to_string_exactly (struct glyph_string *s, struct glyph_string *dst)
{
BView_ClipToRect (FRAME_HAIKU_VIEW (s->f), s->x, s->y,
s->width, s->height);
+ BView_invalidate_region (FRAME_HAIKU_VIEW (s->f), s->x,
+ s->y, s->width, s->height);
}
static void
@@ -186,7 +210,7 @@ haiku_flip_buffers (struct frame *f)
void *view = FRAME_OUTPUT_DATA (f)->view;
block_input ();
- BView_draw_lock (view);
+ BView_draw_lock (view, false, 0, 0, 0, 0);
FRAME_DIRTY_P (f) = 0;
EmacsView_flip_and_blit (view);
BView_draw_unlock (view);
@@ -201,6 +225,13 @@ haiku_frame_up_to_date (struct frame *f)
FRAME_MOUSE_UPDATE (f);
if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
haiku_flip_buffers (f);
+
+ up_to_date_count++;
+ if (up_to_date_count == 50)
+ {
+ be_evict_font_cache ();
+ up_to_date_count = 0;
+ }
unblock_input ();
}
@@ -217,7 +248,7 @@ haiku_clear_frame_area (struct frame *f, int x, int y,
{
void *vw = FRAME_HAIKU_VIEW (f);
block_input ();
- BView_draw_lock (vw);
+ BView_draw_lock (vw, true, x, y, width, height);
BView_StartClip (vw);
BView_ClipToRect (vw, x, y, width, height);
BView_SetHighColor (vw, FRAME_BACKGROUND_PIXEL (f));
@@ -231,14 +262,18 @@ static void
haiku_clear_frame (struct frame *f)
{
void *view = FRAME_HAIKU_VIEW (f);
+
+ mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
+
block_input ();
- BView_draw_lock (view);
+ BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
BView_StartClip (view);
- BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
- FRAME_PIXEL_HEIGHT (f) + 1);
+ BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (f));
- BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) + 1,
- FRAME_PIXEL_HEIGHT (f) + 1);
+ BView_FillRectangle (view, 0, 0, FRAME_PIXEL_WIDTH (f) ,
+ FRAME_PIXEL_HEIGHT (f));
BView_EndClip (view);
BView_draw_unlock (view);
unblock_input ();
@@ -252,11 +287,16 @@ haiku_clear_frame (struct frame *f)
static Lisp_Object
haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
- struct font *font = XFONT_OBJECT (font_object);
+ struct font *font;
+ int ascent, descent, unit;
+
+ font = XFONT_OBJECT (font_object);
+
if (fontset < 0)
fontset = fontset_from_font (font_object);
FRAME_FONTSET (f) = fontset;
+
if (FRAME_FONT (f) == font)
return font_object;
@@ -264,26 +304,22 @@ haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- int ascent, descent;
get_font_ascent_descent (font, &ascent, &descent);
FRAME_LINE_HEIGHT (f) = ascent + descent;
FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
- int unit = FRAME_COLUMN_WIDTH (f);
+ unit = FRAME_COLUMN_WIDTH (f);
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
FRAME_CONFIG_SCROLL_BAR_COLS (f)
= (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
else
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
- if (FRAME_HAIKU_WINDOW (f))
- {
- adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
- FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
- 3, false, Qfont);
+ if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f))
+ adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f),
+ 3, false, Qfont);
- haiku_clear_under_internal_border (f);
- }
return font_object;
}
@@ -365,6 +401,137 @@ 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 ();
+ }
+}
+
+static struct frame *
+haiku_mouse_or_wdesc_frame (void *window, bool accept_tooltip)
+{
+ struct frame *lm_f = (gui_mouse_grabbed (x_display_list)
+ ? x_display_list->last_mouse_frame
+ : NULL);
+
+ if (lm_f && !EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source))
+ return lm_f;
+ else
+ {
+ struct frame *w_f = haiku_window_to_frame (window);
+
+ /* Do not return a tooltip frame. */
+ if (!w_f || (FRAME_TOOLTIP_P (w_f) && !accept_tooltip))
+ return EQ (track_mouse, Qdropping) ? lm_f : NULL;
+ else
+ /* When dropping it would be probably nice to raise w_f
+ here. */
+ return w_f;
+ }
+}
+
+/* Set the thumb size and position of scroll bar BAR. We are
+ currently displaying PORTION out of a whole WHOLE, and our position
+ POSITION. */
+
+static void
+haiku_set_scroll_bar_thumb (struct scroll_bar *bar, int portion,
+ int position, int whole)
+{
+ void *scroll_bar = bar->scroll_bar;
+ double top, shown, size, value;
+
+ if (scroll_bar_adjust_thumb_portion_p)
+ {
+ /* We use an estimate of 30 chars per line rather than the real
+ `portion' value. This has the disadvantage that the thumb
+ size is not very representative, but it makes our life a lot
+ easier. Otherwise, we have to constantly adjust the thumb
+ size, which we can't always do quickly enough: while
+ dragging, the size of the thumb might prevent the user from
+ dragging the thumb all the way to the end. */
+ portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
+ /* When the thumb is at the bottom, position == whole. So we
+ need to increase `whole' to make space for the thumb. */
+ whole += portion;
+ }
+ else
+ bar->page_size = 0;
+
+ if (whole <= 0)
+ top = 0, shown = 1;
+ else
+ {
+ top = (double) position / whole;
+ shown = (double) portion / whole;
+ }
+
+ /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
+ is the scroll bar's maximum and MIN is the scroll bar's minimum
+ value. */
+ size = clip_to_bounds (1, shown * BE_SB_MAX, BE_SB_MAX);
+
+ /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
+ value = top * BE_SB_MAX;
+ value = min (value, BE_SB_MAX - size);
+
+ if (!bar->dragging && scroll_bar_adjust_thumb_portion_p)
+ bar->page_size = size;
+
+ BView_scroll_bar_update (scroll_bar, lrint (size),
+ BE_SB_MAX, ceil (value),
+ (scroll_bar_adjust_thumb_portion_p
+ ? bar->dragging : bar->dragging ? -1 : 0),
+ !scroll_bar_adjust_thumb_portion_p);
+}
+
+static void
+haiku_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion,
+ int position, int whole)
+{
+ void *scroll_bar = bar->scroll_bar;
+ double size, value, shown, top;
+
+ shown = (double) portion / whole;
+ top = (double) position / whole;
+
+ size = shown * BE_SB_MAX;
+ value = top * BE_SB_MAX;
+
+ if (!bar->dragging)
+ bar->page_size = size;
+
+ BView_scroll_bar_update (scroll_bar, lrint (size), BE_SB_MAX,
+ ceil (value), bar->dragging ? -1 : 0, true);
+}
+
+static struct scroll_bar *
+haiku_scroll_bar_from_widget (void *scroll_bar, void *window)
+{
+ Lisp_Object tem;
+ struct frame *frame = haiku_window_to_frame (window);
+
+ if (!frame)
+ return NULL;
+
+ if (!scroll_bar)
+ return NULL;
+
+ if (!NILP (FRAME_SCROLL_BARS (frame)))
+ {
+ for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem);
+ tem = XSCROLL_BAR (tem)->next)
+ {
+ if (XSCROLL_BAR (tem)->scroll_bar == scroll_bar)
+ return XSCROLL_BAR (tem);
+ }
+ }
+
+ return NULL;
}
/* Unfortunately, NOACTIVATE is not implementable on Haiku. */
@@ -389,7 +556,7 @@ haiku_new_focus_frame (struct frame *frame)
x_display_list->focused_frame = frame;
- if (frame && frame->auto_raise)
+ if (frame && frame->auto_raise && !popup_activated_p)
haiku_frame_raise_lower (frame, 1);
}
unblock_input ();
@@ -410,20 +577,24 @@ haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
}
static bool
-haiku_defined_color (struct frame *f,
- const char *name,
- Emacs_Color *color,
- bool alloc,
- bool make_index)
+haiku_defined_color (struct frame *f, const char *name,
+ Emacs_Color *color, bool alloc, bool make_index)
{
- return !haiku_get_color (name, color);
+ int rc;
+
+ rc = !haiku_get_color (name, color);
+
+ if (rc && f->gamma && alloc)
+ gamma_correct (f, color);
+
+ return rc;
}
/* Adapted from xterm `x_draw_box_rect'. */
static void
-haiku_draw_box_rect (struct glyph_string *s,
- int left_x, int top_y, int right_x, int bottom_y, int hwidth,
- int vwidth, bool left_p, bool right_p, struct haiku_rect *clip_rect)
+haiku_draw_box_rect (struct glyph_string *s, int left_x, int top_y,
+ int right_x, int bottom_y, int hwidth, int vwidth,
+ bool left_p, bool right_p, struct haiku_rect *clip_rect)
{
void *view = FRAME_HAIKU_VIEW (s->f);
struct face *face = s->face;
@@ -444,51 +615,72 @@ haiku_draw_box_rect (struct glyph_string *s,
}
static void
-haiku_calculate_relief_colors (struct glyph_string *s,
- uint32_t *rgbout_w, uint32_t *rgbout_b,
- uint32_t *rgbout_c)
+haiku_calculate_relief_colors (struct glyph_string *s, uint32_t *rgbout_w,
+ uint32_t *rgbout_b)
{
- struct face *face = s->face;
-
- prepare_face_for_display (s->f, s->face);
+ double h, cs, l;
+ uint32_t rgbin;
+ struct haiku_output *di;
+
+ if (s->face->use_box_color_for_shadows_p)
+ rgbin = s->face->box_color;
+ else if (s->first_glyph->type == IMAGE_GLYPH
+ && s->img->pixmap
+ && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+ rgbin = IMAGE_BACKGROUND (s->img, s->f, 0);
+ else
+ rgbin = s->face->background;
- uint32_t rgbin = face->use_box_color_for_shadows_p
- ? face->box_color : face->background;
+ di = FRAME_OUTPUT_DATA (s->f);
if (s->hl == DRAW_CURSOR)
rgbin = FRAME_CURSOR_COLOR (s->f).pixel;
- double h, cs, l;
- rgb_color_hsl (rgbin, &h, &cs, &l);
+ if (di->relief_background != rgbin)
+ {
+ di->relief_background = rgbin & 0xffffffff;
- hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6), rgbout_b);
- hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2), rgbout_w);
- hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.8), rgbout_c);
+ rgb_color_hsl (rgbin, &h, &cs, &l);
+ hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 0.6),
+ &di->black_relief_pixel);
+ hsl_color_rgb (h, cs, fmin (1.0, fmax (0.2, l) * 1.2),
+ &di->white_relief_pixel);
+ }
+
+ *rgbout_w = di->white_relief_pixel;
+ *rgbout_b = di->black_relief_pixel;
}
static void
-haiku_draw_relief_rect (struct glyph_string *s,
- int left_x, int top_y, int right_x, int bottom_y,
- int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
- bool left_p, bool right_p,
- struct haiku_rect *clip_rect, bool fancy_p)
+haiku_draw_relief_rect (struct glyph_string *s, int left_x, int top_y,
+ int right_x, int bottom_y, int hwidth, int vwidth,
+ bool raised_p, bool top_p, bool bot_p, bool left_p,
+ bool right_p, struct haiku_rect *clip_rect)
{
- uint32_t color_white;
- uint32_t color_black;
- uint32_t color_corner;
+ uint32_t color_white, color_black;
+ void *view;
- haiku_calculate_relief_colors (s, &color_white, &color_black,
- &color_corner);
+ view = FRAME_HAIKU_VIEW (s->f);
+ haiku_calculate_relief_colors (s, &color_white, &color_black);
- void *view = FRAME_HAIKU_VIEW (s->f);
BView_SetHighColor (view, raised_p ? color_white : color_black);
+
if (clip_rect)
- BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width,
- clip_rect->height);
+ {
+ BView_StartClip (view);
+ haiku_clip_to_string (s);
+ BView_ClipToRect (view, clip_rect->x, clip_rect->y,
+ clip_rect->width, clip_rect->height);
+ }
+
if (top_p)
- BView_FillRectangle (view, left_x, top_y, right_x - left_x + 1, hwidth);
+ BView_FillRectangle (view, left_x, top_y,
+ right_x - left_x + 1, hwidth);
+
if (left_p)
- BView_FillRectangle (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
+ BView_FillRectangle (view, left_x, top_y,
+ vwidth, bottom_y - top_y + 1);
+
BView_SetHighColor (view, !raised_p ? color_white : color_black);
if (bot_p)
@@ -529,10 +721,10 @@ haiku_draw_relief_rect (struct glyph_string *s,
if (vwidth > 1 && right_p)
BView_StrokeLine (view, right_x, top_y, right_x, bottom_y);
- BView_SetHighColor (view, color_corner);
+ BView_SetHighColor (view, FRAME_BACKGROUND_PIXEL (s->f));
/* Omit corner pixels. */
- if (hwidth > 1 || vwidth > 1)
+ if (hwidth > 1 && vwidth > 1)
{
if (left_p && top_p)
BView_FillRectangle (view, left_x, top_y, 1, 1);
@@ -543,25 +735,46 @@ haiku_draw_relief_rect (struct glyph_string *s,
if (right_p && bot_p)
BView_FillRectangle (view, right_x, bottom_y, 1, 1);
}
+
+ if (clip_rect)
+ BView_EndClip (view);
+}
+
+static void
+haiku_get_scale_factor (int *scale_x, int *scale_y)
+{
+ struct haiku_display_info *dpyinfo = x_display_list;
+
+ if (dpyinfo->resx > 96)
+ *scale_x = floor (dpyinfo->resx / 96);
+ if (dpyinfo->resy > 96)
+ *scale_y = floor (dpyinfo->resy / 96);
}
static void
haiku_draw_underwave (struct glyph_string *s, int width, int x)
{
- int wave_height = 3, wave_length = 2;
- int y, dx, dy, odd, xmax;
+ int wave_height, wave_length;
+ int y, dx, dy, odd, xmax, scale_x, scale_y;
+ float ax, ay, bx, by;
+ void *view;
+
+ scale_x = 1;
+ scale_y = 1;
+ haiku_get_scale_factor (&scale_x, &scale_y);
+ wave_height = 3 * scale_y;
+ wave_length = 2 * scale_x;
+
dx = wave_length;
dy = wave_height - 1;
y = s->ybase - wave_height + 3;
-
- float ax, ay, bx, by;
xmax = x + width;
-
- void *view = FRAME_HAIKU_VIEW (s->f);
+ view = FRAME_HAIKU_VIEW (s->f);
BView_StartClip (view);
haiku_clip_to_string (s);
BView_ClipToRect (view, x, y, width, wave_height);
+
ax = x - ((int) (x) % dx) + (float) 0.5;
bx = ax + dx;
odd = (int) (ax / dx) % 2;
@@ -572,6 +785,8 @@ haiku_draw_underwave (struct glyph_string *s, int width, int x)
else
by += dy;
+ BView_SetPenSize (view, scale_y);
+
while (ax <= xmax)
{
BView_StrokeLine (view, ax, ay, bx, by);
@@ -579,27 +794,33 @@ haiku_draw_underwave (struct glyph_string *s, int width, int x)
bx += dx, by = y + 0.5 + odd * dy;
odd = !odd;
}
+
+ BView_SetPenSize (view, 1);
BView_EndClip (view);
}
static void
haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
- uint8_t dcol, int width, int x)
+ int width, int x)
{
+ unsigned long cursor_color;
+
if (s->for_overlaps)
return;
+ if (s->hl == DRAW_CURSOR)
+ haiku_merge_cursor_foreground (s, &cursor_color, NULL);
+
void *view = FRAME_HAIKU_VIEW (s->f);
- BView_draw_lock (view);
if (face->underline)
{
if (s->hl == DRAW_CURSOR)
- BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
+ BView_SetHighColor (view, cursor_color);
else if (!face->underline_defaulted_p)
BView_SetHighColor (view, face->underline_color);
else
- BView_SetHighColor (view, dcol);
+ BView_SetHighColor (view, face->foreground);
if (face->underline == FACE_UNDER_WAVE)
haiku_draw_underwave (s, width, x);
@@ -608,22 +829,19 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
unsigned long thickness, position;
int y;
- if (s->prev && s->prev && s->prev->hl == DRAW_MOUSE_FACE)
+ if (s->prev
+ && s->prev->face->underline == FACE_UNDER_LINE
+ && (s->prev->face->underline_at_descent_line_p
+ == s->face->underline_at_descent_line_p)
+ && (s->prev->face->underline_pixels_above_descent_line
+ == s->face->underline_pixels_above_descent_line))
{
- struct face *prev_face = s->prev->face;
-
- if (prev_face && prev_face->underline == FACE_UNDER_LINE)
- {
- /* We use the same underline style as the previous one. */
- thickness = s->prev->underline_thickness;
- position = s->prev->underline_position;
- }
- else
- goto calculate_underline_metrics;
+ /* We use the same underline style as the previous one. */
+ thickness = s->prev->underline_thickness;
+ position = s->prev->underline_position;
}
else
{
- calculate_underline_metrics:;
struct font *font = font_for_underline_metrics (s);
unsigned long minimum_offset;
bool underline_at_descent_line;
@@ -639,12 +857,13 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_underline_at_descent_line, s->w));
underline_at_descent_line
- = !(NILP (val) || EQ (val, Qunbound));
+ = (!(NILP (val) || BASE_EQ (val, Qunbound))
+ || s->face->underline_at_descent_line_p);
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_use_underline_position_properties, s->w));
use_underline_position_properties
- = !(NILP (val) || EQ (val, Qunbound));
+ = !(NILP (val) || BASE_EQ (val, Qunbound));
/* Get the underline thickness. Default is 1 pixel. */
if (font && font->underline_thickness > 0)
@@ -652,7 +871,9 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
else
thickness = 1;
if (underline_at_descent_line)
- position = (s->height - thickness) - (s->ybase - s->y);
+ position = ((s->height - thickness)
+ - (s->ybase - s->y)
+ - s->face->underline_pixels_above_descent_line);
else
{
/* Get the underline position. This is the
@@ -692,11 +913,11 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
{
unsigned long dy = 0, h = 1;
if (s->hl == DRAW_CURSOR)
- BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
+ BView_SetHighColor (view, cursor_color);
else if (!face->overline_color_defaulted_p)
BView_SetHighColor (view, face->overline_color);
else
- BView_SetHighColor (view, dcol);
+ BView_SetHighColor (view, face->foreground);
BView_FillRectangle (view, s->x, s->y + dy, s->width, h);
}
@@ -716,26 +937,22 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
unsigned long dy = (glyph_height - h) / 2;
if (s->hl == DRAW_CURSOR)
- BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
+ BView_SetHighColor (view, cursor_color);
else if (!face->strike_through_color_defaulted_p)
BView_SetHighColor (view, face->strike_through_color);
else
- BView_SetHighColor (view, dcol);
+ BView_SetHighColor (view, face->foreground);
BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h);
}
-
- BView_draw_unlock (view);
}
static void
-haiku_draw_string_box (struct glyph_string *s, int clip_p)
+haiku_draw_string_box (struct glyph_string *s)
{
int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
bool raised_p, left_p, right_p;
struct glyph *last_glyph;
- struct haiku_rect clip_rect;
-
struct face *face = s->face;
last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
@@ -783,54 +1000,116 @@ haiku_draw_string_box (struct glyph_string *s, int clip_p)
&& (s->next == NULL
|| s->next->hl != s->hl)));
- get_glyph_string_clip_rect (s, &clip_rect);
-
if (face->box == FACE_SIMPLE_BOX)
haiku_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
- vwidth, left_p, right_p, &clip_rect);
+ vwidth, left_p, right_p, NULL);
else
haiku_draw_relief_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
vwidth, raised_p, true, true, left_p, right_p,
- &clip_rect, 1);
-
- if (clip_p)
- {
- void *view = FRAME_HAIKU_VIEW (s->f);
-
- haiku_draw_text_decoration (s, face, face->foreground, s->width, s->x);
- BView_ClipToInverseRect (view, left_x, top_y, right_x - left_x + 1, hwidth);
- if (left_p)
- BView_ClipToInverseRect (view, left_x, top_y, vwidth, bottom_y - top_y + 1);
- BView_ClipToInverseRect (view, left_x, bottom_y - hwidth + 1,
- right_x - left_x + 1, hwidth);
- if (right_p)
- BView_ClipToInverseRect (view, right_x - vwidth + 1,
- top_y, vwidth, bottom_y - top_y + 1);
- }
+ NULL);
}
static void
haiku_draw_plain_background (struct glyph_string *s, struct face *face,
- int box_line_hwidth, int box_line_vwidth)
+ int x, int y, int width, int height)
{
void *view = FRAME_HAIKU_VIEW (s->f);
+ unsigned long cursor_color;
+
if (s->hl == DRAW_CURSOR)
- BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
+ {
+ haiku_merge_cursor_foreground (s, NULL, &cursor_color);
+ BView_SetHighColor (view, cursor_color);
+ }
else
BView_SetHighColor (view, face->background_defaulted_p ?
FRAME_BACKGROUND_PIXEL (s->f) :
- face->background);
+ face->background);
- BView_FillRectangle (view, s->x,
- s->y + box_line_hwidth,
- s->background_width,
- s->height - 2 * box_line_hwidth);
+ BView_FillRectangle (view, x, y, width, height);
+}
+
+static struct haiku_bitmap_record *
+haiku_get_bitmap_rec (struct frame *f, ptrdiff_t id)
+{
+ return &FRAME_DISPLAY_INFO (f)->bitmaps[id - 1];
+}
+
+static void
+haiku_update_bitmap_rec (struct haiku_bitmap_record *rec,
+ uint32_t new_foreground,
+ uint32_t new_background)
+{
+ char *bits;
+ int x, y, bytes_per_line;
+
+ if (new_foreground == rec->stipple_foreground
+ && new_background == rec->stipple_background)
+ return;
+
+ bits = rec->stipple_bits;
+ bytes_per_line = (rec->width + 7) / 8;
+
+ for (y = 0; y < rec->height; y++)
+ {
+ for (x = 0; x < rec->width; x++)
+ haiku_put_pixel (rec->img, x, y,
+ ((bits[x / 8] >> (x % 8)) & 1
+ ? new_foreground : new_background));
+
+ bits += bytes_per_line;
+ }
+
+ rec->stipple_foreground = new_foreground;
+ rec->stipple_background = new_background;
}
static void
haiku_draw_stipple_background (struct glyph_string *s, struct face *face,
- int box_line_hwidth, int box_line_vwidth)
+ int x, int y, int width, int height,
+ bool explicit_colors_p,
+ uint32 explicit_background,
+ uint32 explicit_foreground)
+{
+ struct haiku_bitmap_record *rec;
+ unsigned long foreground, background;
+ void *view;
+
+ view = FRAME_HAIKU_VIEW (s->f);
+ rec = haiku_get_bitmap_rec (s->f, s->face->stipple);
+
+ if (explicit_colors_p)
+ {
+ background = explicit_background;
+ foreground = explicit_foreground;
+ }
+ else if (s->hl == DRAW_CURSOR)
+ haiku_merge_cursor_foreground (s, &foreground, &background);
+ else
+ {
+ foreground = s->face->foreground;
+ background = s->face->background;
+ }
+
+ haiku_update_bitmap_rec (rec, foreground, background);
+
+ BView_StartClip (view);
+ haiku_clip_to_string (s);
+ BView_ClipToRect (view, x, y, width, height);
+ BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
+ 0, 0, x + width, y + height);
+ BView_EndClip (view);
+}
+
+void
+haiku_draw_background_rect (struct glyph_string *s, struct face *face,
+ int x, int y, int width, int height)
{
+ if (!s->stippled_p)
+ haiku_draw_plain_background (s, face, x, y, width, height);
+ else
+ haiku_draw_stipple_background (s, face, x, y, width, height,
+ false, 0, 0);
}
static void
@@ -846,12 +1125,10 @@ haiku_maybe_draw_background (struct glyph_string *s, int force_p)
|| FONT_TOO_HIGH (s->font)
|| s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
{
- if (!face->stipple)
- haiku_draw_plain_background (s, face, box_line_width,
- box_vline_width);
- else
- haiku_draw_stipple_background (s, face, box_line_width,
- box_vline_width);
+ haiku_draw_background_rect (s, s->face, s->x, s->y + box_line_width,
+ s->background_width,
+ s->height - 2 * box_line_width);
+
s->background_filled_p = 1;
}
}
@@ -907,6 +1184,8 @@ haiku_draw_glyph_string_foreground (struct glyph_string *s)
for (i = 0; i < s->nchars; ++i)
{
struct glyph *g = s->first_glyph + i;
+
+ BView_SetPenSize (view, 1);
BView_StrokeRectangle (view, x, s->y, g->pixel_width,
s->height);
x += g->pixel_width;
@@ -938,6 +1217,7 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
unsigned char2b[8];
int x, i, j;
struct face *face = s->face;
+ unsigned long color;
/* If first glyph of S has a left box line, start drawing the text
of S to the right of that box line. */
@@ -1001,11 +1281,21 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
s->ybase + glyph->slice.glyphless.lower_yoff,
false);
}
+
if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
- BView_FillRectangle (FRAME_HAIKU_VIEW (s->f),
- x, s->ybase - glyph->ascent,
- glyph->pixel_width - 1,
- glyph->ascent + glyph->descent - 1);
+ {
+ if (s->hl == DRAW_CURSOR)
+ haiku_merge_cursor_foreground (s, NULL, &color);
+ else
+ color = s->face->foreground;
+
+ BView_SetHighColor (FRAME_HAIKU_VIEW (s->f), color);
+ BView_SetPenSize (FRAME_HAIKU_VIEW (s->f), 1);
+ BView_StrokeRectangle (FRAME_HAIKU_VIEW (s->f),
+ x, s->ybase - glyph->ascent,
+ glyph->pixel_width,
+ glyph->ascent + glyph->descent);
+ }
x += glyph->pixel_width;
}
}
@@ -1013,9 +1303,8 @@ haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
static void
haiku_draw_stretch_glyph_string (struct glyph_string *s)
{
- eassert (s->first_glyph->type == STRETCH_GLYPH);
-
struct face *face = s->face;
+ uint32_t bkg;
if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
{
@@ -1047,7 +1336,10 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
x -= width;
void *view = FRAME_HAIKU_VIEW (s->f);
- BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
+ unsigned long cursor_color;
+
+ haiku_merge_cursor_foreground (s, NULL, &cursor_color);
+ BView_SetHighColor (view, cursor_color);
BView_FillRectangle (view, x, s->y, width, s->height);
if (width < background_width)
@@ -1060,9 +1352,11 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
int y = s->y;
int w = background_width - width, h = s->height;
+ /* Draw stipples manually because we want the background
+ part of a stretch glyph to have a stipple even if the
+ cursor is visible on top. */
if (!face->stipple)
{
- uint32_t bkg;
if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
haiku_mouse_face_colors (s, NULL, &bkg);
else
@@ -1071,6 +1365,16 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
BView_SetHighColor (view, bkg);
BView_FillRectangle (view, x, y, w, h);
}
+ else
+ {
+ if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
+ haiku_mouse_face_colors (s, NULL, &bkg);
+ else
+ bkg = face->background;
+
+ haiku_draw_stipple_background (s, s->face, x, y, w, h,
+ true, bkg, face->foreground);
+ }
}
}
else if (!s->background_filled_p)
@@ -1088,17 +1392,8 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
}
if (background_width > 0)
- {
- void *view = FRAME_HAIKU_VIEW (s->f);
- uint32_t bkg;
- if (s->hl == DRAW_CURSOR)
- bkg = FRAME_CURSOR_COLOR (s->f).pixel;
- else
- bkg = s->face->background;
-
- BView_SetHighColor (view, bkg);
- BView_FillRectangle (view, x, s->y, background_width, s->height);
- }
+ haiku_draw_background_rect (s, s->face, s->x, s->y,
+ background_width, s->height);
}
s->background_filled_p = 1;
}
@@ -1107,7 +1402,6 @@ static void
haiku_start_clip (struct glyph_string *s)
{
void *view = FRAME_HAIKU_VIEW (s->f);
- BView_draw_lock (view);
BView_StartClip (view);
}
@@ -1116,7 +1410,6 @@ haiku_end_clip (struct glyph_string *s)
{
void *view = FRAME_HAIKU_VIEW (s->f);
BView_EndClip (view);
- BView_draw_unlock (view);
}
static void
@@ -1147,7 +1440,7 @@ static void
haiku_update_end (struct frame *f)
{
MOUSE_HL_INFO (f)->mouse_face_defer = false;
- flush_frame (f);
+ BWindow_Flush (FRAME_HAIKU_WINDOW (f));
}
static void
@@ -1173,14 +1466,16 @@ haiku_draw_composite_glyph_string_foreground (struct glyph_string *s)
/* Draw a rectangle for the composition if the font for the very
first character of the composition could not be loaded. */
-
if (s->font_not_found_p && !s->cmp_from)
{
if (s->hl == DRAW_CURSOR)
BView_SetHighColor (view, FRAME_OUTPUT_DATA (s->f)->cursor_fg);
else
BView_SetHighColor (view, s->face->foreground);
- BView_StrokeRectangle (view, s->x, s->y, s->width - 1, s->height - 1);
+
+ BView_SetPenSize (view, 1);
+ BView_StrokeRectangle (view, s->x, s->y,
+ s->width, s->height);
}
else if (!s->first_glyph->u.cmp.automatic)
{
@@ -1332,19 +1627,29 @@ haiku_draw_image_relief (struct glyph_string *s)
get_glyph_string_clip_rect (s, &r);
haiku_draw_relief_rect (s, x, y, x1, y1, thick, thick, raised_p,
- top_p, bot_p, left_p, right_p, &r, 0);
+ top_p, bot_p, left_p, right_p, &r);
+}
+
+static void
+haiku_translate_transform (double (*transform)[3], double dx,
+ double dy)
+{
+ transform[0][2] += dx;
+ transform[1][2] += dy;
}
static void
haiku_draw_image_glyph_string (struct glyph_string *s)
{
struct face *face = s->face;
-
+ void *view, *bitmap, *mask;
int box_line_hwidth = max (face->box_vertical_line_width, 0);
int box_line_vwidth = max (face->box_horizontal_line_width, 0);
-
- int x, y;
- int height, width;
+ int x, y, height, width, relief;
+ struct haiku_rect nr;
+ Emacs_Rectangle cr, ir, r;
+ unsigned long background;
+ double image_transform[3][3];
height = s->height;
if (s->slice.y == 0)
@@ -1365,19 +1670,21 @@ haiku_draw_image_glyph_string (struct glyph_string *s)
if (s->slice.y == 0)
y += box_line_vwidth;
- void *view = FRAME_HAIKU_VIEW (s->f);
- void *bitmap = s->img->pixmap;
+ view = FRAME_HAIKU_VIEW (s->f);
+ bitmap = s->img->pixmap;
s->stippled_p = face->stipple != 0;
- BView_SetHighColor (view, face->background);
- BView_FillRectangle (view, x, y, width, height);
+ if (s->hl == DRAW_CURSOR)
+ haiku_merge_cursor_foreground (s, NULL, &background);
+ else
+ background = face->background;
+
+ haiku_draw_background_rect (s, face, x, y,
+ width, height);
if (bitmap)
{
- struct haiku_rect nr;
- Emacs_Rectangle cr, ir, r;
-
get_glyph_string_clip_rect (s, &nr);
CONVERT_TO_EMACS_RECT (cr, nr);
x = s->x;
@@ -1399,45 +1706,91 @@ haiku_draw_image_glyph_string (struct glyph_string *s)
ir.height = s->slice.height;
r = ir;
- void *mask = s->img->mask;
+ mask = s->img->mask;
if (gui_intersect_rectangles (&cr, &ir, &r))
{
- if (s->img->have_be_transforms_p)
+ memcpy (&image_transform, &s->img->transform,
+ sizeof image_transform);
+
+ if (s->slice.x != x || s->slice.y != y
+ || s->slice.width != s->img->width
+ || s->slice.height != s->img->height)
{
- bitmap = BBitmap_transform_bitmap (bitmap,
- s->img->mask,
- face->background,
- s->img->be_rotate,
- s->img->width,
- s->img->height);
- mask = NULL;
+ BView_StartClip (view);
+ BView_ClipToRect (view, r.x, r.y, r.width, r.height);
}
- BView_DrawBitmap (view, bitmap,
- s->slice.x + r.x - x,
- s->slice.y + r.y - y,
- r.width, r.height,
- r.x, r.y, r.width, r.height);
- if (mask)
+ haiku_translate_transform (image_transform,
+ x - s->slice.x,
+ y - s->slice.y);
+
+ be_apply_affine_transform (view,
+ image_transform[0][0],
+ image_transform[0][1],
+ image_transform[0][2],
+ image_transform[1][0],
+ image_transform[1][1],
+ image_transform[1][2]);
+
+ if (!s->stippled_p || !mask)
{
- BView_DrawMask (mask, view,
- s->slice.x + r.x - x,
- s->slice.y + r.y - y,
- r.width, r.height,
- r.x, r.y, r.width, r.height,
- face->background);
+ BView_DrawBitmap (view, bitmap, 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ s->img->use_bilinear_filtering);
+
+ if (mask)
+ be_draw_image_mask (mask, view, 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ background);
}
-
- if (s->img->have_be_transforms_p)
- BBitmap_free (bitmap);
+ else
+ /* In order to make sure the stipple background remains
+ visible, use the mask for the alpha channel of BITMAP
+ and composite it onto the view instead. */
+ be_draw_bitmap_with_mask (view, bitmap, mask, 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ 0, 0,
+ s->img->original_width,
+ s->img->original_height,
+ s->img->use_bilinear_filtering);
+
+ if (s->slice.x != x || s->slice.y != y
+ || s->slice.width != s->img->width
+ || s->slice.height != s->img->height)
+ BView_EndClip (view);
+
+ be_apply_affine_transform (view, 1, 0, 0, 0, 1, 0);
}
- if (s->hl == DRAW_CURSOR)
+ if (!s->img->mask)
{
- BView_SetPenSize (view, 1);
- BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
- BView_StrokeRectangle (view, r.x, r.y, r.width, r.height);
+ /* When the image has a mask, we can expect that at
+ least part of a mouse highlight or a block cursor will
+ be visible. If the image doesn't have a mask, make
+ a block cursor visible by drawing a rectangle around
+ the image. I believe it's looking better if we do
+ nothing here for mouse-face. */
+
+ if (s->hl == DRAW_CURSOR)
+ {
+ relief = eabs (s->img->relief);
+
+ BView_SetPenSize (view, 1);
+ BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel);
+ BView_StrokeRectangle (view, x - relief, y - relief,
+ s->slice.width + relief * 2,
+ s->slice.height + relief * 2);
+ }
}
}
@@ -1450,12 +1803,14 @@ haiku_draw_image_glyph_string (struct glyph_string *s)
static void
haiku_draw_glyph_string (struct glyph_string *s)
{
+ void *view = FRAME_HAIKU_VIEW (s->f);;
+ struct face *face = s->face;
+
block_input ();
+ BView_draw_lock (view, false, 0, 0, 0, 0);
prepare_face_for_display (s->f, s->face);
- struct face *face = s->face;
- if (face != s->face)
- prepare_face_for_display (s->f, face);
+ s->stippled_p = s->hl != DRAW_CURSOR && face->stipple;
if (s->next && s->right_overhang && !s->for_overlaps)
{
@@ -1467,13 +1822,16 @@ haiku_draw_glyph_string (struct glyph_string *s)
width += next->width, next = next->next)
if (next->first_glyph->type != IMAGE_GLYPH)
{
- prepare_face_for_display (s->f, s->next->face);
- haiku_start_clip (s->next);
- haiku_clip_to_string (s->next);
+ prepare_face_for_display (s->f, next->face);
+ next->stippled_p
+ = next->hl != DRAW_CURSOR && next->face->stipple;
+
+ haiku_start_clip (next);
+ haiku_clip_to_string (next);
if (next->first_glyph->type != STRETCH_GLYPH)
- haiku_maybe_draw_background (s->next, 1);
+ haiku_maybe_draw_background (next, true);
else
- haiku_draw_stretch_glyph_string (s->next);
+ haiku_draw_stretch_glyph_string (next);
haiku_end_clip (s);
}
}
@@ -1489,7 +1847,7 @@ haiku_draw_glyph_string (struct glyph_string *s)
haiku_clip_to_string (s);
haiku_maybe_draw_background (s, 1);
box_filled_p = 1;
- haiku_draw_string_box (s, 0);
+ haiku_draw_string_box (s);
}
else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
&& !s->clip_tail
@@ -1542,10 +1900,9 @@ haiku_draw_glyph_string (struct glyph_string *s)
if (!s->for_overlaps)
{
if (!box_filled_p && face->box != FACE_NO_BOX)
- haiku_draw_string_box (s, 1);
+ haiku_draw_string_box (s);
else
- haiku_draw_text_decoration (s, face, face->foreground,
- s->width, s->x);
+ haiku_draw_text_decoration (s, face, s->width, s->x);
if (s->prev)
{
@@ -1599,7 +1956,19 @@ haiku_draw_glyph_string (struct glyph_string *s)
}
}
}
+
haiku_end_clip (s);
+ BView_draw_unlock (view);
+
+ /* Set the stipple_p flag indicating whether or not a stipple was
+ drawn in s->row. That is the case either when s is a stretch
+ glyph string and s->face->stipple is not NULL, or when
+ s->face->stipple exists and s->hl is not DRAW_CURSOR. */
+ if (s->face->stipple
+ && (s->first_glyph->type == STRETCH_GLYPH
+ || s->hl != DRAW_CURSOR))
+ s->row->stipple_p = true;
+
unblock_input ();
}
@@ -1633,13 +2002,18 @@ haiku_after_update_window_line (struct window *w,
if (face)
{
void *view = FRAME_HAIKU_VIEW (f);
- BView_draw_lock (view);
+ BView_draw_lock (view, false, 0, 0, 0, 0);
BView_StartClip (view);
- BView_SetHighColor (view, face->background_defaulted_p ?
- FRAME_BACKGROUND_PIXEL (f) : face->background);
+ BView_SetHighColor (view, (face->background_defaulted_p
+ ? FRAME_BACKGROUND_PIXEL (f)
+ : face->background));
BView_FillRectangle (view, 0, y, width, height);
BView_FillRectangle (view, FRAME_PIXEL_WIDTH (f) - width,
y, width, height);
+ BView_invalidate_region (FRAME_HAIKU_VIEW (f),
+ 0, y, width, height);
+ BView_invalidate_region (view, FRAME_PIXEL_WIDTH (f) - width,
+ y, width, height);
BView_EndClip (view);
BView_draw_unlock (view);
}
@@ -1657,118 +2031,243 @@ static void
haiku_set_window_size (struct frame *f, bool change_gravity,
int width, int height)
{
+ Lisp_Object frame;
+
+ /* On X Windows, window managers typically disallow resizing a
+ window when it is fullscreen. Do the same here. */
+
+ XSETFRAME (frame, f);
+ if (!NILP (Fframe_parameter (frame, Qfullscreen))
+ /* Only do this if the fullscreen status has actually been
+ applied. */
+ && f->want_fullscreen == FULLSCREEN_NONE
+ /* And if the configury during frame creation has been
+ completed. Otherwise, there will be no valid "old size" to
+ go back to. */
+ && FRAME_OUTPUT_DATA (f)->configury_done)
+ return;
+
haiku_update_size_hints (f);
if (FRAME_HAIKU_WINDOW (f))
{
block_input ();
- BWindow_resize (FRAME_HAIKU_WINDOW (f), width, height);
+ BWindow_resize (FRAME_HAIKU_WINDOW (f),
+ width, height);
+
+ if (FRAME_VISIBLE_P (f)
+ && (width != FRAME_PIXEL_WIDTH (f)
+ || height != FRAME_PIXEL_HEIGHT (f)))
+ haiku_wait_for_event (f, FRAME_RESIZED);
unblock_input ();
}
+
+ do_pending_window_change (false);
}
static void
-haiku_draw_window_cursor (struct window *w,
- struct glyph_row *glyph_row,
- int x, int y,
- enum text_cursor_kinds cursor_type,
- int cursor_width, bool on_p, bool active_p)
+haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row)
{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
-
- struct glyph *phys_cursor_glyph;
+ struct frame *f;
+ int x, y, wd, h;
struct glyph *cursor_glyph;
+ uint32_t foreground;
+ void *view;
- void *view = FRAME_HAIKU_VIEW (f);
-
- int fx, fy, h, cursor_height;
+ f = XFRAME (WINDOW_FRAME (w));
+ view = FRAME_HAIKU_VIEW (f);
- if (!on_p)
+ /* Get the glyph the cursor is on. If we can't tell because
+ the current matrix is invalid or such, give up. */
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
return;
- if (cursor_type == NO_CURSOR)
- {
- w->phys_cursor_width = 0;
- return;
- }
+ /* Compute frame-relative coordinates for phys cursor. */
+ get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
+ wd = w->phys_cursor_width;
- w->phys_cursor_on_p = true;
- w->phys_cursor_type = cursor_type;
+ /* The foreground of cursor_gc is typically the same as the normal
+ background color, which can cause the cursor box to be invisible. */
+ foreground = FRAME_CURSOR_COLOR (f).pixel;
- phys_cursor_glyph = get_phys_cursor_glyph (w);
+ /* When on R2L character, show cursor at the right edge of the
+ glyph, unless the cursor box is as wide as the glyph or wider
+ (the latter happens when x-stretch-cursor is non-nil). */
+ if ((cursor_glyph->resolved_level & 1) != 0
+ && cursor_glyph->pixel_width > wd)
+ x += cursor_glyph->pixel_width - wd;
- if (!phys_cursor_glyph)
- {
- if (glyph_row->exact_window_width_line_p
- && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
- {
- glyph_row->cursor_in_fringe_p = 1;
- draw_fringe_bitmap (w, glyph_row, 0);
- }
- return;
- }
+ /* Set clipping, draw the rectangle, and reset clipping again.
+ This also marks the region as invalidated. */
+
+ BView_draw_lock (view, true, x, y, wd, h);
+ BView_StartClip (view);
+ haiku_clip_to_row (w, row, TEXT_AREA);
+
+ /* Now set the foreground color and pen size. */
+ BView_SetHighColor (view, foreground);
+ BView_SetPenSize (view, 1);
+
+ /* Actually draw the rectangle. */
+ BView_StrokeRectangle (view, x, y, wd, h);
+
+ /* Reset clipping. */
+ BView_EndClip (view);
+ BView_draw_unlock (view);
+}
- get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
+static void
+haiku_draw_bar_cursor (struct window *w, struct glyph_row *row,
+ int width, enum text_cursor_kinds kind)
+{
+ struct frame *f;
+ struct glyph *cursor_glyph;
+ struct glyph_row *r;
+ struct face *face;
+ uint32_t foreground;
+ void *view;
+ int x, y, dummy_x, dummy_y, dummy_h;
+
+ f = XFRAME (w->frame);
- if (cursor_type == BAR_CURSOR)
+ /* If cursor is out of bounds, don't draw garbage. This can happen
+ in mini-buffer windows when switching between echo area glyphs
+ and mini-buffer. */
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
+ return;
+
+ /* If on an image, draw like a normal cursor. That's usually better
+ visible than drawing a bar, esp. if the image is large so that
+ the bar might not be in the window. */
+ if (cursor_glyph->type == IMAGE_GLYPH)
{
- if (cursor_width < 1)
- cursor_width = max (FRAME_CURSOR_WIDTH (f), 1);
- if (cursor_width < w->phys_cursor_width)
- w->phys_cursor_width = cursor_width;
+ r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+ draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
}
- else if (cursor_type == HBAR_CURSOR)
+ else
{
- cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width;
- if (cursor_height > glyph_row->height)
- cursor_height = glyph_row->height;
- if (h > cursor_height)
- fy += h - cursor_height;
- h = cursor_height;
- }
+ view = FRAME_HAIKU_VIEW (f);
+ face = FACE_FROM_ID (f, cursor_glyph->face_id);
+
+ /* If the glyph's background equals the color we normally draw
+ the bars cursor in, the bar cursor in its normal color is
+ invisible. Use the glyph's foreground color instead in this
+ case, on the assumption that the glyph's colors are chosen so
+ that the glyph is legible. */
+ if (face->background == FRAME_CURSOR_COLOR (f).pixel)
+ foreground = face->foreground;
+ else
+ foreground = FRAME_CURSOR_COLOR (f).pixel;
- BView_draw_lock (view);
- BView_StartClip (view);
- BView_SetHighColor (view, FRAME_CURSOR_COLOR (f).pixel);
- haiku_clip_to_row (w, glyph_row, TEXT_AREA);
+ BView_draw_lock (view, false, 0, 0, 0, 0);
+ BView_StartClip (view);
+ BView_SetHighColor (view, foreground);
+ haiku_clip_to_row (w, row, TEXT_AREA);
+
+ if (kind == BAR_CURSOR)
+ {
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+
+ if (width < 0)
+ width = FRAME_CURSOR_WIDTH (f);
+ width = min (cursor_glyph->pixel_width, width);
+
+ w->phys_cursor_width = width;
+
+ /* If the character under cursor is R2L, draw the bar cursor
+ on the right of its glyph, rather than on the left. */
+ if ((cursor_glyph->resolved_level & 1) != 0)
+ x += cursor_glyph->pixel_width - width;
+
+ BView_FillRectangle (view, x, y, width, row->height);
+ BView_invalidate_region (view, x, y, width, row->height);
+ }
+ else /* HBAR_CURSOR */
+ {
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+ row->height - width);
+
+ if (width < 0)
+ width = row->height;
+
+ width = min (row->height, width);
- switch (cursor_type)
+ get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
+ &dummy_y, &dummy_h);
+
+ if ((cursor_glyph->resolved_level & 1) != 0
+ && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
+ x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
+
+ BView_FillRectangle (view, x, y, w->phys_cursor_width - 1,
+ width);
+ BView_invalidate_region (view, x, y, w->phys_cursor_width - 1,
+ width);
+ }
+
+ BView_EndClip (view);
+ BView_draw_unlock (view);
+ }
+}
+
+static void
+haiku_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
+ int x, int y, enum text_cursor_kinds cursor_type,
+ int cursor_width, bool on_p, bool active_p)
+{
+ if (on_p)
{
- default:
- case DEFAULT_CURSOR:
- case NO_CURSOR:
- break;
- case HBAR_CURSOR:
- BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
- break;
- case BAR_CURSOR:
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph->resolved_level & 1)
- BView_FillRectangle (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width,
- fy, w->phys_cursor_width, h);
- else
- BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h);
- break;
- case HOLLOW_BOX_CURSOR:
- if (phys_cursor_glyph->type != IMAGE_GLYPH)
+ w->phys_cursor_type = cursor_type;
+ w->phys_cursor_on_p = true;
+
+ if (glyph_row->exact_window_width_line_p
+ && (glyph_row->reversed_p
+ ? (w->phys_cursor.hpos < 0)
+ : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
{
- BView_SetPenSize (view, 1);
- BView_StrokeRectangle (view, fx, fy, w->phys_cursor_width, h);
+ glyph_row->cursor_in_fringe_p = true;
+ draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
}
else
- draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
- break;
- case FILLED_BOX_CURSOR:
- draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+ {
+ switch (cursor_type)
+ {
+ case HOLLOW_BOX_CURSOR:
+ haiku_draw_hollow_cursor (w, glyph_row);
+ break;
+
+ case FILLED_BOX_CURSOR:
+ draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+ break;
+
+ case BAR_CURSOR:
+ haiku_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+ break;
+
+ case HBAR_CURSOR:
+ haiku_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+ break;
+
+ case NO_CURSOR:
+ w->phys_cursor_width = 0;
+ break;
+
+ default:
+ emacs_abort ();
+ }
+ }
}
- BView_EndClip (view);
- BView_draw_unlock (view);
}
static void
haiku_show_hourglass (struct frame *f)
{
- if (FRAME_OUTPUT_DATA (f)->hourglass_p)
+ if (FRAME_TOOLTIP_P (f)
+ || FRAME_OUTPUT_DATA (f)->hourglass_p)
return;
block_input ();
@@ -1783,7 +2282,8 @@ haiku_show_hourglass (struct frame *f)
static void
haiku_hide_hourglass (struct frame *f)
{
- if (!FRAME_OUTPUT_DATA (f)->hourglass_p)
+ if (FRAME_TOOLTIP_P (f)
+ || !FRAME_OUTPUT_DATA (f)->hourglass_p)
return;
block_input ();
@@ -1835,7 +2335,7 @@ haiku_draw_vertical_window_border (struct window *w,
face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
void *view = FRAME_HAIKU_VIEW (f);
- BView_draw_lock (view);
+ BView_draw_lock (view, true, x, y_0, 1, y_1);
BView_StartClip (view);
if (face)
BView_SetHighColor (view, face->foreground);
@@ -1847,19 +2347,25 @@ haiku_draw_vertical_window_border (struct window *w,
static void
haiku_set_scroll_bar_default_width (struct frame *f)
{
- int unit = FRAME_COLUMN_WIDTH (f);
- FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = BScrollBar_default_size (0) + 1;
- FRAME_CONFIG_SCROLL_BAR_COLS (f) =
- (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
+ int unit, size;
+
+ unit = FRAME_COLUMN_WIDTH (f);
+ size = BScrollBar_default_size (0) + 1;
+
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = size;
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (size + unit - 1) / unit;
}
static void
haiku_set_scroll_bar_default_height (struct frame *f)
{
- int height = FRAME_LINE_HEIGHT (f);
- FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = BScrollBar_default_size (1) + 1;
- FRAME_CONFIG_SCROLL_BAR_LINES (f) =
- (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
+ int height, size;
+
+ height = FRAME_LINE_HEIGHT (f);
+ size = BScrollBar_default_size (true) + 1;
+
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = size;
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (size + height - 1) / height;
}
static void
@@ -1880,7 +2386,7 @@ haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
: FRAME_FOREGROUND_PIXEL (f));
void *view = FRAME_HAIKU_VIEW (f);
- BView_draw_lock (view);
+ BView_draw_lock (view, true, x0, y0, x1 - x0 + 1, y1 - y0 + 1);
BView_StartClip (view);
if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
@@ -1899,11 +2405,11 @@ haiku_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
last pixels differently. */
{
BView_SetHighColor (view, color_first);
- BView_StrokeLine (f, x0, y0, x1 - 1, y0);
+ BView_StrokeLine (view, x0, y0, x1 - 1, y0);
BView_SetHighColor (view, color);
BView_FillRectangle (view, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
BView_SetHighColor (view, color_last);
- BView_StrokeLine (view, x0, y1, x1 - 1, y1);
+ BView_FillRectangle (view, x0, y1 - 1, x1 - x0, 1);
}
else
{
@@ -2041,15 +2547,17 @@ static struct scroll_bar *
haiku_scroll_bar_create (struct window *w, int left, int top,
int width, int height, bool horizontal_p)
{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct frame *f;
Lisp_Object barobj;
+ struct scroll_bar *bar;
+ void *scroll_bar;
+ void *view;
- void *sb = NULL;
- void *vw = FRAME_HAIKU_VIEW (f);
+ f = XFRAME (WINDOW_FRAME (w));
+ view = FRAME_HAIKU_VIEW (f);
block_input ();
- struct scroll_bar *bar
- = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
+ bar = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
XSETWINDOW (bar->window, w);
bar->top = top;
@@ -2062,15 +2570,14 @@ haiku_scroll_bar_create (struct window *w, int left, int top,
bar->update = -1;
bar->horizontal = horizontal_p;
- sb = BScrollBar_make_for_view (vw, horizontal_p,
- left, top, left + width - 1,
- top + height - 1, bar);
-
- BView_publish_scroll_bar (vw, left, top, width, height);
+ scroll_bar = be_make_scroll_bar_for_view (view, horizontal_p,
+ left, top, left + width - 1,
+ top + height - 1);
+ BView_publish_scroll_bar (view, left, top, width, height);
bar->next = FRAME_SCROLL_BARS (f);
bar->prev = Qnil;
- bar->scroll_bar = sb;
+ bar->scroll_bar = scroll_bar;
XSETVECTOR (barobj, bar);
fset_scroll_bars (f, barobj);
@@ -2084,25 +2591,26 @@ haiku_scroll_bar_create (struct window *w, int left, int top,
static void
haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position)
{
- eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
Lisp_Object barobj;
struct scroll_bar *bar;
int top, height, left, width;
int window_x, window_width;
+ void *view;
+ eassert (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w));
/* Get window dimensions. */
window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
left = window_x;
width = window_width;
top = WINDOW_SCROLL_BAR_AREA_Y (w);
height = WINDOW_CONFIG_SCROLL_BAR_HEIGHT (w);
+ view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
block_input ();
if (NILP (w->horizontal_scroll_bar))
{
bar = haiku_scroll_bar_create (w, left, top, width, height, true);
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
bar->update = position;
bar->position = position;
bar->total = whole;
@@ -2111,27 +2619,23 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p
{
bar = XSCROLL_BAR (w->horizontal_scroll_bar);
- if (bar->left != left || bar->top != top ||
- bar->width != width || bar->height != height)
+ if (bar->left != left || bar->top != top
+ || bar->width != width || bar->height != height)
{
- void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
BView_forget_scroll_bar (view, bar->left, bar->top,
bar->width, bar->height);
BView_move_frame (bar->scroll_bar, left, top,
left + width - 1, top + height - 1);
BView_publish_scroll_bar (view, left, top, width, height);
+
bar->left = left;
bar->top = top;
bar->width = width;
bar->height = height;
}
-
- if (!bar->dragging)
- {
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
- BView_invalidate (bar->scroll_bar);
- }
}
+
+ haiku_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
bar->position = position;
bar->total = whole;
XSETVECTOR (barobj, bar);
@@ -2140,14 +2644,15 @@ haiku_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int p
}
static void
-haiku_set_vertical_scroll_bar (struct window *w,
- int portion, int whole, int position)
+haiku_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position)
{
- eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
Lisp_Object barobj;
struct scroll_bar *bar;
int top, height, left, width;
int window_y, window_height;
+ void *view;
+
+ eassert (WINDOW_HAS_VERTICAL_SCROLL_BAR (w));
/* Get window dimensions. */
window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
@@ -2157,12 +2662,13 @@ haiku_set_vertical_scroll_bar (struct window *w,
/* Compute the left edge and the width of the scroll bar area. */
left = WINDOW_SCROLL_BAR_AREA_X (w);
width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
- block_input ();
+ view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
+
+ block_input ();
if (NILP (w->vertical_scroll_bar))
{
bar = haiku_scroll_bar_create (w, left, top, width, height, false);
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
bar->position = position;
bar->total = whole;
}
@@ -2170,30 +2676,23 @@ haiku_set_vertical_scroll_bar (struct window *w,
{
bar = XSCROLL_BAR (w->vertical_scroll_bar);
- if (bar->left != left || bar->top != top ||
- bar->width != width || bar->height != height)
+ if (bar->left != left || bar->top != top
+ || bar->width != width || bar->height != height)
{
- void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (w));
BView_forget_scroll_bar (view, bar->left, bar->top,
bar->width, bar->height);
BView_move_frame (bar->scroll_bar, left, top,
left + width - 1, top + height - 1);
- flush_frame (WINDOW_XFRAME (w));
BView_publish_scroll_bar (view, left, top, width, height);
+
bar->left = left;
bar->top = top;
bar->width = width;
bar->height = height;
}
-
- if (!bar->dragging)
- {
- BView_scroll_bar_update (bar->scroll_bar, portion, whole, position);
- bar->update = position;
- BView_invalidate (bar->scroll_bar);
- }
}
+ haiku_set_scroll_bar_thumb (bar, portion, position, whole);
bar->position = position;
bar->total = whole;
@@ -2206,24 +2705,69 @@ static void
haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
struct draw_fringe_bitmap_params *p)
{
- void *view = FRAME_HAIKU_VIEW (XFRAME (WINDOW_FRAME (w)));
- struct face *face = p->face;
+ struct face *face;
+ struct frame *f;
+ struct haiku_bitmap_record *rec;
+ void *view, *bitmap;
+ uint32 col;
- BView_draw_lock (view);
+ f = XFRAME (WINDOW_FRAME (w));
+ view = FRAME_HAIKU_VIEW (f);
+ face = p->face;
+
+ block_input ();
+ BView_draw_lock (view, true, 0, 0, 0, 0);
BView_StartClip (view);
+ if (p->wd && p->h)
+ BView_invalidate_region (view, p->x, p->y, p->wd, p->h);
+
haiku_clip_to_row (w, row, ANY_AREA);
+
if (p->bx >= 0 && !p->overlay_p)
{
- BView_SetHighColor (view, face->background);
- BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
+ BView_invalidate_region (view, p->bx, p->by, p->nx, p->ny);
+
+ if (!face->stipple)
+ {
+ BView_SetHighColor (view, face->background);
+ BView_FillRectangle (view, p->bx, p->by, p->nx, p->ny);
+ }
+ else
+ {
+ rec = haiku_get_bitmap_rec (f, face->stipple);
+ haiku_update_bitmap_rec (rec, face->foreground,
+ face->background);
+
+ BView_StartClip (view);
+ haiku_clip_to_row (w, row, ANY_AREA);
+ BView_ClipToRect (view, p->bx, p->by, p->nx, p->ny);
+ BView_DrawBitmapTiled (view, rec->img, 0, 0, -1, -1,
+ 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+ BView_EndClip (view);
+
+ row->stipple_p = true;
+ }
}
- if (p->which && p->which < fringe_bitmap_fillptr)
+ if (p->which
+ && p->which < max_fringe_bmp
+ && p->which < max_used_fringe_bitmap)
{
- void *bitmap = fringe_bmps[p->which];
+ bitmap = fringe_bmps[p->which];
- uint32_t col;
+ if (!bitmap)
+ {
+ /* This fringe bitmap is known to fringe.c, but lacks the
+ BBitmap which shadows that bitmap. This is typical to
+ define-fringe-bitmap being called when the selected frame
+ was not a GUI frame, for example, when packages that
+ define fringe bitmaps are loaded by a daemon Emacs.
+ Create the missing pattern now. */
+ gui_define_fringe_bitmap (WINDOW_XFRAME (w), p->which);
+ bitmap = fringe_bmps[p->which];
+ }
if (!p->cursor_p)
col = face->foreground;
@@ -2243,31 +2787,36 @@ haiku_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
}
BView_EndClip (view);
BView_draw_unlock (view);
+ unblock_input ();
}
static void
haiku_define_fringe_bitmap (int which, unsigned short *bits,
int h, int wd)
{
- if (which >= fringe_bitmap_fillptr)
+ if (which >= max_fringe_bmp)
{
- int i = fringe_bitmap_fillptr;
- fringe_bitmap_fillptr = which + 20;
- fringe_bmps = !i ? xmalloc (fringe_bitmap_fillptr * sizeof (void *)) :
- xrealloc (fringe_bmps, fringe_bitmap_fillptr * sizeof (void *));
+ int i = max_fringe_bmp;
+ max_fringe_bmp = which + 20;
+ fringe_bmps = !i ? xmalloc (max_fringe_bmp * sizeof (void *)) :
+ xrealloc (fringe_bmps, max_fringe_bmp * sizeof (void *));
- while (i < fringe_bitmap_fillptr)
+ while (i < max_fringe_bmp)
fringe_bmps[i++] = NULL;
}
+ block_input ();
fringe_bmps[which] = BBitmap_new (wd, h, 1);
- BBitmap_import_mono_bits (fringe_bmps[which], bits, wd, h);
+ if (!fringe_bmps[which])
+ memory_full (SIZE_MAX);
+ BBitmap_import_fringe_bitmap (fringe_bmps[which], bits, wd, h);
+ unblock_input ();
}
static void
haiku_destroy_fringe_bitmap (int which)
{
- if (which >= fringe_bitmap_fillptr)
+ if (which >= max_fringe_bmp)
return;
if (fringe_bmps[which])
@@ -2306,78 +2855,55 @@ haiku_scroll_run (struct window *w, struct run *run)
height = run->height;
}
- if (!height)
- return;
-
block_input ();
gui_clear_cursor (w);
- BView_draw_lock (view);
-#ifdef USE_BE_CAIRO
- if (EmacsView_double_buffered_p (view))
- {
-#endif
- BView_StartClip (view);
- BView_CopyBits (view, x, from_y, width, height,
- x, to_y, width, height);
- BView_EndClip (view);
-#ifdef USE_BE_CAIRO
- }
- else
- {
- EmacsWindow_begin_cr_critical_section (FRAME_HAIKU_WINDOW (f));
- cairo_surface_t *surface = FRAME_CR_SURFACE (f);
- cairo_surface_t *s
- = cairo_surface_create_similar (surface,
- cairo_surface_get_content (surface),
- width, height);
- cairo_t *cr = cairo_create (s);
- if (surface)
- {
- cairo_set_source_surface (cr, surface, -x, -from_y);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- cr = haiku_begin_cr_clip (f, NULL);
- cairo_save (cr);
- cairo_set_source_surface (cr, s, x, to_y);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_rectangle (cr, x, to_y, width, height);
- cairo_fill (cr);
- cairo_restore (cr);
- cairo_surface_destroy (s);
- haiku_end_cr_clip (cr);
- }
- EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
- }
-#endif
+
+ BView_draw_lock (view, true, x, to_y, width, height);
+ BView_StartClip (view);
+ BView_CopyBits (view, x, from_y, width, height,
+ x, to_y, width, height);
+ BView_EndClip (view);
BView_draw_unlock (view);
unblock_input ();
}
+/* Haiku doesn't provide any way to get the frame actually underneath
+ the pointer, so we typically return dpyinfo->last_mouse_frame if
+ the display is grabbed and `track-mouse' is not `dropping' or
+ `drag-source'; failing that, we return the selected frame, and
+ finally a random window system frame (as long as `track-mouse' is
+ not `drag-source') if that didn't work either. */
static void
haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
Time *timestamp)
{
+ Lisp_Object frame, tail;
+ struct frame *f1;
+ int screen_x, screen_y;
+ void *view;
+
if (!fp)
return;
+ f1 = NULL;
block_input ();
- Lisp_Object frame, tail;
- struct frame *f1 = NULL;
+
FOR_EACH_FRAME (tail, frame)
- XFRAME (frame)->mouse_moved = false;
+ {
+ if (FRAME_HAIKU_P (XFRAME (frame)))
+ XFRAME (frame)->mouse_moved = false;
+ }
- if (gui_mouse_grabbed (x_display_list) && !EQ (track_mouse, Qdropping))
+ if (gui_mouse_grabbed (x_display_list)
+ && !EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source))
f1 = x_display_list->last_mouse_frame;
+ else
+ f1 = x_display_list->last_mouse_motion_frame;
- if (!f1 || FRAME_TOOLTIP_P (f1))
- f1 = ((EQ (track_mouse, Qdropping) && gui_mouse_grabbed (x_display_list))
- ? x_display_list->last_mouse_frame
- : NULL);
-
- if (!f1 && insist > 0)
+ if (!f1 && FRAME_HAIKU_P (SELECTED_FRAME ()))
f1 = SELECTED_FRAME ();
if (!f1 || (!FRAME_HAIKU_P (f1) && (insist > 0)))
@@ -2386,26 +2912,37 @@ haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
!FRAME_TOOLTIP_P (XFRAME (frame)))
f1 = XFRAME (frame);
- if (FRAME_TOOLTIP_P (f1))
+ if (f1 && FRAME_TOOLTIP_P (f1))
f1 = NULL;
if (f1 && FRAME_HAIKU_P (f1))
{
- int sx, sy;
- void *view = FRAME_HAIKU_VIEW (f1);
+ view = FRAME_HAIKU_VIEW (f1);
+
if (view)
{
- BView_get_mouse (view, &sx, &sy);
-
- remember_mouse_glyph (f1, sx, sy, &x_display_list->last_mouse_glyph);
+ BView_get_mouse (view, &screen_x, &screen_y);
+ remember_mouse_glyph (f1, screen_x, screen_y,
+ &x_display_list->last_mouse_glyph);
x_display_list->last_mouse_glyph_frame = f1;
*bar_window = Qnil;
- *part = scroll_bar_above_handle;
- *fp = f1;
+ *part = scroll_bar_nowhere;
+
+ /* If track-mouse is `drag-source' and the mouse pointer is
+ certain to not be actually under the chosen frame, return
+ NULL in FP to at least try being consistent with X. */
+ if (EQ (track_mouse, Qdrag_source)
+ && (screen_x < 0 || screen_y < 0
+ || screen_x >= FRAME_PIXEL_WIDTH (f1)
+ || screen_y >= FRAME_PIXEL_HEIGHT (f1)))
+ *fp = NULL;
+ else
+ *fp = f1;
+
*timestamp = x_display_list->last_mouse_movement_time;
- XSETINT (*x, sx);
- XSETINT (*y, sy);
+ XSETINT (*x, screen_x);
+ XSETINT (*y, screen_y);
}
}
@@ -2415,15 +2952,21 @@ haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
static void
haiku_flush (struct frame *f)
{
- if (FRAME_VISIBLE_P (f))
+ /* This is needed for tooltip frames to work properly with double
+ buffering. */
+ if (FRAME_DIRTY_P (f) && !buffer_flipping_blocked_p ())
+ haiku_flip_buffers (f);
+
+ if (FRAME_VISIBLE_P (f) && !FRAME_TOOLTIP_P (f))
BWindow_Flush (FRAME_HAIKU_WINDOW (f));
}
static void
haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
{
- if (f->tooltip)
+ if (FRAME_TOOLTIP_P (f))
return;
+
block_input ();
if (!f->pointer_invisible && FRAME_HAIKU_VIEW (f)
&& !FRAME_OUTPUT_DATA (f)->hourglass_p)
@@ -2433,20 +2976,13 @@ haiku_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
}
static void
-haiku_update_window_end (struct window *w, bool cursor_on_p,
- bool mouse_face_overwritten_p)
-{
-
-}
-
-static void
haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
{
struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
RES_TYPE_STRING);
Lisp_Object font = Qnil;
- if (EQ (font_param, Qunbound))
+ if (BASE_EQ (font_param, Qunbound))
font_param = Qnil;
if (NILP (font_param))
@@ -2457,10 +2993,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));
@@ -2510,8 +3043,8 @@ static struct redisplay_interface haiku_redisplay_interface =
gui_clear_end_of_line,
haiku_scroll_run,
haiku_after_update_window_line,
- NULL,
- haiku_update_window_end,
+ NULL, /* update_window_begin */
+ NULL, /* update_window_end */
haiku_flush,
gui_clear_window_mouse_face,
gui_get_glyph_overhangs,
@@ -2527,7 +3060,7 @@ static struct redisplay_interface haiku_redisplay_interface =
haiku_draw_window_cursor,
haiku_draw_vertical_window_border,
haiku_draw_window_divider,
- 0, /* shift glyphs for insert */
+ NULL, /* shift glyphs for insert */
haiku_show_hourglass,
haiku_hide_hourglass,
haiku_default_font_parameter,
@@ -2536,54 +3069,88 @@ static struct redisplay_interface haiku_redisplay_interface =
static void
haiku_make_fullscreen_consistent (struct frame *f)
{
- Lisp_Object lval = get_frame_param (f, Qfullscreen);
-
- if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p)
+ Lisp_Object lval;
+ struct haiku_output *output;
+
+ output = FRAME_OUTPUT_DATA (f);
+
+ if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH)
+ lval = Qfullboth;
+ else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH)
+ lval = Qfullwidth;
+ else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT)
+ lval = Qfullheight;
+ else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
lval = Qmaximized;
- else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p)
+ else
lval = Qnil;
store_frame_param (f, Qfullscreen, lval);
}
static void
-flush_dirty_back_buffers (void)
+haiku_flush_dirty_back_buffer_on (struct frame *f)
{
- block_input ();
- Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, frame)
+ if (!FRAME_GARBAGED_P (f)
+ && !buffer_flipping_blocked_p ()
+ && FRAME_DIRTY_P (f))
+ haiku_flip_buffers (f);
+}
+
+/* N.B. that support for TYPE must be explicitly added to
+ haiku_read_socket. */
+void
+haiku_wait_for_event (struct frame *f, int type)
+{
+ int input_blocked_to;
+ object_wait_info info;
+ specpdl_ref depth;
+
+ input_blocked_to = interrupt_input_blocked;
+ info.object = port_application_to_emacs;
+ info.type = B_OBJECT_TYPE_PORT;
+ info.events = B_EVENT_READ;
+
+ depth = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
+
+ FRAME_OUTPUT_DATA (f)->wait_for_event_type = type;
+
+ while (FRAME_OUTPUT_DATA (f)->wait_for_event_type == type)
{
- struct frame *f = XFRAME (frame);
- if (FRAME_LIVE_P (f) &&
- FRAME_HAIKU_P (f) &&
- FRAME_HAIKU_WINDOW (f) &&
- !FRAME_GARBAGED_P (f) &&
- !buffer_flipping_blocked_p () &&
- FRAME_DIRTY_P (f))
- haiku_flip_buffers (f);
+ if (wait_for_objects (&info, 1) < B_OK)
+ continue;
+
+ pending_signals = true;
+ /* This will call the read_socket_hook. */
+ totally_unblock_input ();
+ interrupt_input_blocked = input_blocked_to;
+ info.events = B_EVENT_READ;
}
- unblock_input ();
+
+ unbind_to (depth, Qnil);
}
static int
haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
- block_input ();
- int message_count = 0;
- static void *buf = NULL;
+ int message_count;
+ void *buf;
ssize_t b_size;
- struct unhandled_event *unhandled_events = NULL;
- int button_or_motion_p;
- int need_flush = 0;
+ int button_or_motion_p, do_help;
+ enum haiku_event_type type;
+ struct input_event inev, inev2;
+
+ message_count = 0;
+ button_or_motion_p = 0;
+ do_help = 0;
- if (!buf)
- buf = xmalloc (200);
- haiku_read_size (&b_size);
+ buf = alloca (200);
+
+ block_input ();
+ haiku_read_size (&b_size, false);
while (b_size >= 0)
{
- enum haiku_event_type type;
- struct input_event inev, inev2;
-
if (b_size > 200)
emacs_abort ();
@@ -2595,7 +3162,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
inev2.arg = Qnil;
button_or_motion_p = 0;
-
haiku_read (&type, buf, b_size);
switch (type)
@@ -2620,12 +3186,35 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (!f)
continue;
- int width = lrint (b->px_widthf);
- int height = lrint (b->px_heightf);
+ int width = lrint (b->width);
+ int height = lrint (b->height);
+
+ if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
+ == FRAME_RESIZED)
+ FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
+
+ if (FRAME_TOOLTIP_P (f))
+ {
+ if (FRAME_PIXEL_WIDTH (f) != width
+ || FRAME_PIXEL_HEIGHT (f) != height)
+ SET_FRAME_GARBAGED (f);
+
+ FRAME_PIXEL_WIDTH (f) = width;
+ FRAME_PIXEL_HEIGHT (f) = height;
- BView_draw_lock (FRAME_HAIKU_VIEW (f));
+ haiku_clear_under_internal_border (f);
+
+ /* Flush the frame and flip buffers here. It is
+ necessary for tooltips displayed inside menus, as
+ redisplay cannot happen. */
+ haiku_flush (f);
+ continue;
+ }
+
+ BView_draw_lock (FRAME_HAIKU_VIEW (f), false, 0, 0, 0, 0);
BView_resize_to (FRAME_HAIKU_VIEW (f), width, height);
BView_draw_unlock (FRAME_HAIKU_VIEW (f));
+
if (width != FRAME_PIXEL_WIDTH (f)
|| height != FRAME_PIXEL_HEIGHT (f)
|| (f->new_size_p
@@ -2638,18 +3227,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
haiku_clear_under_internal_border (f);
}
- if (FRAME_OUTPUT_DATA (f)->pending_zoom_width != width ||
- FRAME_OUTPUT_DATA (f)->pending_zoom_height != height)
- {
- FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
- haiku_make_fullscreen_consistent (f);
- }
- else
- {
- FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
- FRAME_OUTPUT_DATA (f)->pending_zoom_width = INT_MIN;
- FRAME_OUTPUT_DATA (f)->pending_zoom_height = INT_MIN;
- }
break;
}
case FRAME_EXPOSED:
@@ -2661,7 +3238,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
continue;
expose_frame (f, b->x, b->y, b->width, b->height);
-
haiku_clear_under_internal_border (f);
break;
}
@@ -2670,7 +3246,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
struct haiku_key_event *b = buf;
Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
struct frame *f = haiku_window_to_frame (b->window);
- int non_ascii_p;
+
if (!f)
continue;
@@ -2683,20 +3259,26 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
clear_mouse_face (hlinfo);
hlinfo->mouse_face_hidden = true;
- need_flush = 1;
+ haiku_flush_dirty_back_buffer_on (f);
}
- inev.code = b->unraw_mb_char;
-
- BMapKey (b->kc, &non_ascii_p, &inev.code);
+ inev.code = b->keysym ? b->keysym : b->multibyte_char;
- if (non_ascii_p)
+ if (b->keysym)
inev.kind = NON_ASCII_KEYSTROKE_EVENT;
else
inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT :
ASCII_KEYSTROKE_EVENT;
- inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
+ inev.timestamp = b->time / 1000;
+ inev.modifiers = (haiku_modifiers_to_emacs (b->modifiers)
+ | (extra_keyboard_modifiers
+ & (meta_modifier
+ | hyper_modifier
+ | ctrl_modifier
+ | alt_modifier
+ | shift_modifier)));
+
XSETFRAME (inev.frame_or_window, f);
break;
}
@@ -2708,8 +3290,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (!f)
continue;
- if ((x_display_list->focus_event_frame != f && b->activated_p) ||
- (x_display_list->focus_event_frame == f && !b->activated_p))
+ if ((x_display_list->focus_event_frame != f && b->activated_p)
+ || (x_display_list->focus_event_frame == f && !b->activated_p))
{
haiku_new_focus_frame (b->activated_p ? f : NULL);
if (b->activated_p)
@@ -2722,26 +3304,62 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
break;
}
+ case MENU_BAR_LEFT:
+ {
+ struct haiku_menu_bar_left_event *b = buf;
+ struct frame *f = haiku_window_to_frame (b->window);
+
+ if (!f)
+ continue;
+
+ if (b->y > 0 && b->y <= FRAME_PIXEL_HEIGHT (f)
+ && b->x > 0 && b->x <= FRAME_PIXEL_WIDTH (f))
+ break;
+
+ if (f->auto_lower && !popup_activated_p)
+ haiku_frame_raise_lower (f, 0);
+
+ break;
+ }
case MOUSE_MOTION:
{
struct haiku_mouse_motion_event *b = buf;
- struct frame *f = haiku_window_to_frame (b->window);
+ struct frame *f = haiku_mouse_or_wdesc_frame (b->window, true);
Mouse_HLInfo *hlinfo = &x_display_list->mouse_highlight;
+ Lisp_Object frame;
if (!f)
continue;
- Lisp_Object frame;
+ if (FRAME_TOOLTIP_P (f))
+ {
+ /* Dismiss the tooltip if the mouse moves onto a
+ tooltip frame (except when drag-and-drop is in
+ progress and we are trying to move the tooltip
+ along with the mouse pointer). FIXME: for some
+ reason we don't get leave notification events for
+ this. */
+
+ if (any_help_event_p
+ && !(be_drag_and_drop_in_progress ()
+ && haiku_dnd_follow_tooltip)
+ && !((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && gui_mouse_grabbed (x_display_list)))
+ do_help = -1;
+ break;
+ }
+
XSETFRAME (frame, f);
- x_display_list->last_mouse_movement_time = time (NULL);
+ x_display_list->last_mouse_movement_time = b->time / 1000;
button_or_motion_p = 1;
if (hlinfo->mouse_face_hidden)
{
hlinfo->mouse_face_hidden = false;
clear_mouse_face (hlinfo);
- need_flush = 1;
+ haiku_flush_dirty_back_buffer_on (f);
}
if (b->just_exited_p)
@@ -2754,18 +3372,47 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
clear_mouse_face (hlinfo);
hlinfo->mouse_face_mouse_frame = 0;
- need_flush = 1;
+ haiku_flush_dirty_back_buffer_on (f);
+ }
+
+ if (f->auto_lower && !popup_activated_p
+ /* Don't do this if the mouse entered a scroll bar. */
+ && !BView_inside_scroll_bar (FRAME_HAIKU_VIEW (f),
+ b->x, b->y))
+ {
+ /* If we're leaving towards the menu bar, don't
+ auto-lower here, and wait for a exit
+ notification from the menu bar instead. */
+ if (b->x > FRAME_PIXEL_WIDTH (f)
+ || b->y >= FRAME_MENU_BAR_HEIGHT (f)
+ || b->x < 0
+ || b->y < 0)
+ haiku_frame_raise_lower (f, 0);
}
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
+ && !((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && gui_mouse_grabbed (x_display_list)))
+ do_help = -1;
}
else
{
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;
@@ -2773,18 +3420,17 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
- /* A LeaveNotify event (well, the closest equivalent on Haiku, which
- is a B_MOUSE_MOVED event with `transit' set to B_EXITED_VIEW) might
- be sent out-of-order with regards to motion events from other
- windows, such as when the mouse pointer rapidly moves from an
- undecorated child frame to its parent. This can cause a failure to
- clear the mouse face on the former if an event for the latter is
- read by Emacs first and ends up showing the mouse face there.
+ /* A crossing event might be sent out-of-order with
+ regard to motion events from other windows, such as
+ when the mouse pointer rapidly moves from an
+ undecorated child frame to its parent. This can
+ cause a failure to clear the mouse face on the
+ former if an event for the latter is read by Emacs
+ first and ends up showing the mouse face there.
- In case the `movement_locker' (also see the comment
- there) doesn't take care of the problem, work
- around it by clearing the mouse face now, if it is
- currently shown on a different frame. */
+ Work around the problem by clearing the mouse face
+ now if it is currently shown on a different
+ frame. */
if (hlinfo->mouse_face_hidden
|| (f != hlinfo->mouse_face_mouse_frame
@@ -2799,14 +3445,13 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
|| b->y < r.y || b->y >= r.y + r.height)
{
f->mouse_moved = true;
- dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (f, b->x, b->y);
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))
{
@@ -2816,36 +3461,74 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (WINDOWP (window)
&& !EQ (window, last_mouse_window)
&& !EQ (window, selected_window)
+ && !popup_activated_p
+ && !MINI_WINDOW_P (XWINDOW (selected_window))
&& (!NILP (focus_follows_mouse)
- || (EQ (XWINDOW (window)->frame,
- XWINDOW (selected_window)->frame))))
+ || f == SELECTED_FRAME ()))
{
- inev.kind = SELECT_WINDOW_EVENT;
- inev.frame_or_window = window;
+ inev2.kind = SELECT_WINDOW_EVENT;
+ inev2.frame_or_window = window;
}
last_mouse_window = window;
}
+
+ if (f->auto_raise)
+ {
+ if (!BWindow_is_active (FRAME_HAIKU_WINDOW (f)))
+ haiku_frame_raise_lower (f, 1);
+ }
+
+ if (!NILP (help_echo_string)
+ || !NILP (previous_help_echo_string))
+ do_help = 1;
+
+ if (b->dnd_message)
+ {
+ /* It doesn't make sense to show tooltips when
+ another program is dragging stuff over us. */
+
+ if (any_help_event_p || do_help)
+ do_help = -1;
+
+ if (!be_drag_and_drop_in_progress ())
+ {
+ inev.kind = DRAG_N_DROP_EVENT;
+ inev.arg = Qlambda;
+
+ XSETINT (inev.x, b->x);
+ XSETINT (inev.y, b->y);
+ XSETFRAME (inev.frame_or_window, f);
+ }
+ else
+ haiku_note_drag_motion ();
+
+ break;
+ }
}
+
+ if (FRAME_DIRTY_P (f))
+ haiku_flush_dirty_back_buffer_on (f);
break;
}
case BUTTON_UP:
case BUTTON_DOWN:
{
struct haiku_button_event *b = buf;
- struct frame *f = haiku_window_to_frame (b->window);
+ struct frame *f = haiku_mouse_or_wdesc_frame (b->window, false);
Lisp_Object tab_bar_arg = Qnil;
int tab_bar_p = 0, tool_bar_p = 0;
+ bool up_okay_p = false;
+ struct scroll_bar *bar;
- if (!f)
+ if (popup_activated_p || !f)
continue;
- struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
+ bar = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
x_display_list->last_mouse_glyph_frame = 0;
- x_display_list->last_mouse_movement_time = time (NULL);
+ x_display_list->last_mouse_movement_time = b->time / 1000;
button_or_motion_p = 1;
/* Is this in the tab-bar? */
@@ -2863,7 +3546,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
tab_bar_arg = handle_tab_bar_click
(f, x, y, type == BUTTON_DOWN, inev.modifiers);
- need_flush = 1;
+ haiku_flush_dirty_back_buffer_on (f);
}
}
@@ -2875,43 +3558,79 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
int y = b->y;
window = window_from_coordinates (f, x, y, 0, true, true);
- tool_bar_p = EQ (window, f->tool_bar_window);
+ tool_bar_p = (EQ (window, f->tool_bar_window)
+ && (type != BUTTON_UP
+ || f->last_tool_bar_item != -1));
if (tool_bar_p)
{
handle_tool_bar_click
(f, x, y, type == BUTTON_DOWN, inev.modifiers);
- need_flush = 1;
+ haiku_flush_dirty_back_buffer_on (f);
}
}
if (type == BUTTON_UP)
{
inev.modifiers |= up_modifier;
- dpyinfo->grabbed &= ~(1 << b->btn_no);
+ up_okay_p = (x_display_list->grabbed & (1 << b->btn_no));
+ x_display_list->grabbed &= ~(1 << b->btn_no);
}
else
{
+ up_okay_p = true;
inev.modifiers |= down_modifier;
- dpyinfo->last_mouse_frame = f;
- dpyinfo->grabbed |= (1 << b->btn_no);
+ x_display_list->last_mouse_frame = f;
+ x_display_list->grabbed |= (1 << b->btn_no);
if (f && !tab_bar_p)
f->last_tab_bar_item = -1;
if (f && !tool_bar_p)
f->last_tool_bar_item = -1;
}
- if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
+ if (bar)
+ {
+ inev.kind = (bar->horizontal
+ ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+ : SCROLL_BAR_CLICK_EVENT);
+ inev.part = (bar->horizontal
+ ? scroll_bar_horizontal_handle
+ : scroll_bar_handle);
+ }
+ else if (up_okay_p
+ && !(tab_bar_p && NILP (tab_bar_arg))
+ && !tool_bar_p)
inev.kind = MOUSE_CLICK_EVENT;
+
inev.arg = tab_bar_arg;
inev.code = b->btn_no;
f->mouse_moved = false;
- XSETINT (inev.x, b->x);
- XSETINT (inev.y, b->y);
+ if (bar)
+ {
+ if (bar->horizontal)
+ {
+ XSETINT (inev.x, min (max (0, b->x - bar->left),
+ bar->width));
+ XSETINT (inev.y, bar->width);
+ }
+ else
+ {
+ XSETINT (inev.x, min (max (0, b->y - bar->top),
+ bar->height));
+ XSETINT (inev.y, bar->height);
+ }
+
+ inev.frame_or_window = bar->window;
+ }
+ else
+ {
+ XSETINT (inev.x, b->x);
+ XSETINT (inev.y, b->y);
+ XSETFRAME (inev.frame_or_window, f);
+ }
- XSETFRAME (inev.frame_or_window, f);
break;
}
case ICONIFICATION:
@@ -2928,7 +3647,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
SET_FRAME_ICONIFIED (f, 0);
inev.kind = DEICONIFY_EVENT;
-
/* Haiku doesn't expose frames on deiconification, but
if we are double-buffered, the previous screen
contents should have been preserved. */
@@ -2952,40 +3670,36 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
struct haiku_move_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
+ int top, left;
+ struct frame *p;
if (!f)
continue;
- if (FRAME_OUTPUT_DATA (f)->pending_zoom_x != b->x ||
- FRAME_OUTPUT_DATA (f)->pending_zoom_y != b->y)
- FRAME_OUTPUT_DATA (f)->zoomed_p = 0;
- else
- {
- FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
- FRAME_OUTPUT_DATA (f)->pending_zoom_x = INT_MIN;
- FRAME_OUTPUT_DATA (f)->pending_zoom_y = INT_MIN;
- }
+ FRAME_OUTPUT_DATA (f)->frame_x = b->x;
+ FRAME_OUTPUT_DATA (f)->frame_y = b->y;
if (FRAME_PARENT_FRAME (f))
haiku_coords_from_parent (f, &b->x, &b->y);
- if (b->x != f->left_pos || b->y != f->top_pos)
+ left = b->x - b->decorator_width;
+ top = b->y - b->decorator_height;
+
+ if (left != f->left_pos || top != f->top_pos)
{
inev.kind = MOVE_FRAME_EVENT;
- XSETINT (inev.x, b->x);
- XSETINT (inev.y, b->y);
+ XSETINT (inev.x, left);
+ XSETINT (inev.y, top);
- f->left_pos = b->x;
- f->top_pos = b->y;
+ f->left_pos = left;
+ f->top_pos = top;
- struct frame *p;
+ p = FRAME_PARENT_FRAME (f);
- if ((p = FRAME_PARENT_FRAME (f)))
- {
- void *window = FRAME_HAIKU_WINDOW (p);
- EmacsWindow_move_weak_child (window, b->window, b->x, b->y);
- }
+ if (p)
+ EmacsWindow_move_weak_child (FRAME_HAIKU_WINDOW (p),
+ b->window, left, top);
XSETFRAME (inev.frame_or_window, f);
}
@@ -2996,7 +3710,12 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
case SCROLL_BAR_VALUE_EVENT:
{
struct haiku_scroll_bar_value_event *b = buf;
- struct scroll_bar *bar = b->scroll_bar;
+ struct scroll_bar *bar
+ = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
+ int portion, whole;
+
+ if (!bar)
+ continue;
struct window *w = XWINDOW (bar->window);
@@ -3008,21 +3727,76 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (bar->position != b->position)
{
- inev.kind = bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
- SCROLL_BAR_CLICK_EVENT;
- inev.part = bar->horizontal ?
- scroll_bar_horizontal_handle : scroll_bar_handle;
+ inev.kind = (bar->horizontal
+ ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT :
+ SCROLL_BAR_CLICK_EVENT);
+ inev.part = (bar->horizontal
+ ? scroll_bar_horizontal_handle
+ : scroll_bar_handle);
+
+ if (bar->horizontal)
+ {
+ portion = bar->total * ((float) b->position
+ / BE_SB_MAX);
+ whole = (bar->total
+ * ((float) (BE_SB_MAX - bar->page_size)
+ / BE_SB_MAX));
+ portion = min (portion, whole);
+ }
+ else
+ {
+ whole = BE_SB_MAX - bar->page_size;
+ portion = min (b->position, whole);
+ }
- XSETINT (inev.x, b->position);
- XSETINT (inev.y, bar->total);
+ XSETINT (inev.x, portion);
+ XSETINT (inev.y, whole);
XSETWINDOW (inev.frame_or_window, w);
}
break;
}
+ case SCROLL_BAR_PART_EVENT:
+ {
+ struct haiku_scroll_bar_part_event *b = buf;
+ struct scroll_bar *bar
+ = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
+
+ if (!bar)
+ continue;
+
+ inev.kind = (bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+ : SCROLL_BAR_CLICK_EVENT);
+
+ bar->dragging = 0;
+
+ switch (b->part)
+ {
+ case HAIKU_SCROLL_BAR_UP_BUTTON:
+ inev.part = (bar->horizontal
+ ? scroll_bar_left_arrow
+ : scroll_bar_up_arrow);
+ break;
+ case HAIKU_SCROLL_BAR_DOWN_BUTTON:
+ inev.part = (bar->horizontal
+ ? scroll_bar_right_arrow
+ : scroll_bar_down_arrow);
+ break;
+ }
+
+ XSETINT (inev.x, 0);
+ XSETINT (inev.y, 0);
+ inev.frame_or_window = bar->window;
+
+ break;
+ }
case SCROLL_BAR_DRAG_EVENT:
{
struct haiku_scroll_bar_drag_event *b = buf;
- struct scroll_bar *bar = b->scroll_bar;
+ struct scroll_bar *bar
+ = haiku_scroll_bar_from_widget (b->scroll_bar, b->window);
+
+ if (!bar)
+ continue;
bar->dragging = b->dragging_p;
if (!b->dragging_p && bar->horizontal)
@@ -3035,13 +3809,28 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
struct haiku_wheel_move_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
- int x, y;
+ int x, y, scroll_width, scroll_height;
static float px = 0.0f, py = 0.0f;
+ Lisp_Object wheel_window;
if (!f)
continue;
+
BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
+ wheel_window = window_from_coordinates (f, x, y, 0, false, false);
+
+ if (NILP (wheel_window))
+ {
+ scroll_width = FRAME_PIXEL_WIDTH (f);
+ scroll_height = FRAME_PIXEL_HEIGHT (f);
+ }
+ else
+ {
+ scroll_width = XWINDOW (wheel_window)->pixel_width;
+ scroll_height = XWINDOW (wheel_window)->pixel_height;
+ }
+
inev.modifiers = haiku_modifiers_to_emacs (b->modifiers);
inev2.modifiers = inev.modifiers;
@@ -3053,9 +3842,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
py = 0;
px += (b->delta_x
- * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
+ * powf (scroll_width, 2.0f / 3.0f));
py += (b->delta_y
- * powf (FRAME_PIXEL_HEIGHT (f), 2.0f / 3.0f));
+ * powf (scroll_height, 2.0f / 3.0f));
if (fabsf (py) >= FRAME_LINE_HEIGHT (f)
|| fabsf (px) >= FRAME_COLUMN_WIDTH (f)
@@ -3082,7 +3871,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
break;
}
-
case MENU_BAR_RESIZE:
{
struct haiku_menu_bar_resize_event *b = buf;
@@ -3091,11 +3879,15 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
continue;
+ if (FRAME_OUTPUT_DATA (f)->wait_for_event_type
+ == MENU_BAR_RESIZE)
+ FRAME_OUTPUT_DATA (f)->wait_for_event_type = -1;
+
int old_height = FRAME_MENU_BAR_HEIGHT (f);
- FRAME_MENU_BAR_HEIGHT (f) = b->height + 1;
- FRAME_MENU_BAR_LINES (f) =
- (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
+ FRAME_MENU_BAR_HEIGHT (f) = b->height;
+ FRAME_MENU_BAR_LINES (f)
+ = (b->height + FRAME_LINE_HEIGHT (f)) / FRAME_LINE_HEIGHT (f);
if (old_height != b->height)
{
@@ -3104,6 +3896,21 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
}
break;
}
+ case MENU_BAR_CLICK:
+ {
+ struct haiku_menu_bar_click_event *b = buf;
+ struct frame *f = haiku_window_to_frame (b->window);
+
+ if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
+ continue;
+
+ if (!FRAME_OUTPUT_DATA (f)->saved_menu_event)
+ FRAME_OUTPUT_DATA (f)->saved_menu_event = xmalloc (sizeof *b);
+ *FRAME_OUTPUT_DATA (f)->saved_menu_event = *b;
+ inev.kind = MENU_BAR_ACTIVATE_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
+ break;
+ }
case MENU_BAR_OPEN:
case MENU_BAR_CLOSE:
{
@@ -3115,18 +3922,6 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (type == MENU_BAR_OPEN)
{
- if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
- {
- BView_draw_lock (FRAME_HAIKU_VIEW (f));
- /* This shouldn't be here, but nsmenu does it, so
- it should probably be safe. */
- int was_waiting_for_input_p = waiting_for_input;
- if (waiting_for_input)
- waiting_for_input = 0;
- set_frame_menubar (f, 1);
- waiting_for_input = was_waiting_for_input_p;
- BView_draw_unlock (FRAME_HAIKU_VIEW (f));
- }
FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 1;
popup_activated_p += 1;
}
@@ -3134,6 +3929,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
{
if (!popup_activated_p)
emacs_abort ();
+
if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
{
FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
@@ -3150,22 +3946,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (!f || !FRAME_EXTERNAL_MENU_BAR (f))
continue;
- if (FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
- find_and_call_menu_selection (f, f->menu_bar_items_used,
- f->menu_bar_vector, b->ptr);
- break;
- }
- case FILE_PANEL_EVENT:
- {
- if (!popup_activated_p)
- continue;
-
- struct unhandled_event *ev = xmalloc (sizeof *ev);
- ev->next = unhandled_events;
- ev->type = type;
- memcpy (&ev->buffer, buf, 200);
-
- unhandled_events = ev;
+ find_and_call_menu_selection (f, f->menu_bar_items_used,
+ f->menu_bar_vector, b->ptr);
break;
}
case MENU_BAR_HELP_EVENT:
@@ -3176,96 +3958,137 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
continue;
struct frame *f = haiku_window_to_frame (b->window);
- if (!f || !FRAME_EXTERNAL_MENU_BAR (f) ||
- !FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
+ if (!f || !FRAME_EXTERNAL_MENU_BAR (f)
+ || !FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
continue;
run_menu_bar_help_event (f, b->mb_idx);
-
break;
}
case ZOOM_EVENT:
{
struct haiku_zoom_event *b = buf;
-
struct frame *f = haiku_window_to_frame (b->window);
if (!f)
continue;
- FRAME_OUTPUT_DATA (f)->pending_zoom_height = b->height;
- FRAME_OUTPUT_DATA (f)->pending_zoom_width = b->width;
- FRAME_OUTPUT_DATA (f)->pending_zoom_x = b->x;
- FRAME_OUTPUT_DATA (f)->pending_zoom_y = b->y;
+ if (b->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
+ f->want_fullscreen = FULLSCREEN_NONE;
+ else
+ f->want_fullscreen = FULLSCREEN_MAXIMIZED;
- FRAME_OUTPUT_DATA (f)->zoomed_p = 1;
- haiku_make_fullscreen_consistent (f);
+ FRAME_TERMINAL (f)->fullscreen_hook (f);
break;
}
- case REFS_EVENT:
+ case DRAG_AND_DROP_EVENT:
{
- struct haiku_refs_event *b = buf;
+ struct haiku_drag_and_drop_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
if (!f)
- continue;
+ {
+ BMessage_delete (b->message);
+ continue;
+ }
inev.kind = DRAG_N_DROP_EVENT;
- inev.arg = build_string_from_utf8 (b->ref);
+ inev.arg = haiku_message_to_lisp (b->message);
XSETINT (inev.x, b->x);
XSETINT (inev.y, b->y);
XSETFRAME (inev.frame_or_window, f);
- /* There should be no problem with calling free here.
- free on Haiku is thread-safe. */
- free (b->ref);
+ BMessage_delete (b->message);
+ break;
+ }
+ case SCREEN_CHANGED_EVENT:
+ {
+ struct haiku_screen_changed_event *b = buf;
+
+ inev.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (inev.arg, x_display_list->terminal);
+ inev.timestamp = b->when / 1000;
break;
}
+ case CLIPBOARD_CHANGED_EVENT:
+ be_handle_clipboard_changed_message ();
+ break;
case APP_QUIT_REQUESTED_EVENT:
+ inev.kind = SAVE_SESSION_EVENT;
+ inev.arg = Qt;
+ break;
case KEY_UP:
+ case DUMMY_EVENT:
default:
break;
}
- haiku_read_size (&b_size);
+ haiku_read_size (&b_size, false);
if (inev.kind != NO_EVENT)
{
- if (inev.kind != HELP_EVENT)
+ if (inev.kind != HELP_EVENT && !inev.timestamp)
inev.timestamp = (button_or_motion_p
? x_display_list->last_mouse_movement_time
- : time (NULL));
+ : system_time () / 1000);
kbd_buffer_store_event_hold (&inev, hold_quit);
++message_count;
}
if (inev2.kind != NO_EVENT)
{
- if (inev2.kind != HELP_EVENT)
+ if (inev2.kind != HELP_EVENT && !inev.timestamp)
inev2.timestamp = (button_or_motion_p
? x_display_list->last_mouse_movement_time
- : time (NULL));
+ : system_time () / 1000);
kbd_buffer_store_event_hold (&inev2, hold_quit);
++message_count;
}
}
- for (struct unhandled_event *ev = unhandled_events; ev;)
+ if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT))
{
- haiku_write_without_signal (ev->type, &ev->buffer);
- struct unhandled_event *old = ev;
- ev = old->next;
- xfree (old);
- }
+ Lisp_Object help_frame = Qnil;
- if (need_flush)
- flush_dirty_back_buffers ();
+ 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);
+ }
+ }
unblock_input ();
+
return message_count;
}
+static Lisp_Object
+haiku_get_focus_frame (struct frame *f)
+{
+ Lisp_Object lisp_focus;
+ struct frame *focus;
+
+ focus = FRAME_DISPLAY_INFO (f)->focused_frame;
+
+ if (!focus)
+ return Qnil;
+
+ XSETFRAME (lisp_focus, focus);
+ return lisp_focus;
+}
+
static void
haiku_frame_rehighlight (struct frame *frame)
{
@@ -3286,6 +4109,99 @@ haiku_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
}
static void
+haiku_flash (struct frame *f)
+{
+ /* Get the height not including a menu bar widget. */
+ int height = FRAME_PIXEL_HEIGHT (f);
+ /* Height of each line to flash. */
+ int flash_height = FRAME_LINE_HEIGHT (f);
+ /* These will be the left and right margins of the rectangles. */
+ int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = flash_right - flash_left;
+ void *view = FRAME_HAIKU_VIEW (f);
+ object_wait_info info;
+ bigtime_t wakeup;
+
+ info.object = port_application_to_emacs;
+ info.type = B_OBJECT_TYPE_PORT;
+ info.events = B_EVENT_READ;
+ wakeup = system_time () + 150000;
+
+ BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+ BView_StartClip (view);
+ /* If window is tall, flash top and bottom line. */
+ if (height > 3 * FRAME_LINE_HEIGHT (f))
+ {
+ BView_InvertRect (view, flash_left,
+ (FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_TOP_MARGIN_HEIGHT (f)),
+ width, flash_height);
+
+ BView_InvertRect (view, flash_left,
+ (height - flash_height
+ - FRAME_INTERNAL_BORDER_WIDTH (f)),
+ width, flash_height);
+ }
+ else
+ /* If it is short, flash it all. */
+ BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ BView_EndClip (view);
+ BView_draw_unlock (view);
+
+ flush_frame (f);
+
+ if (EmacsView_double_buffered_p (view))
+ haiku_flip_buffers (f);
+
+ /* Keep waiting until past the time wakeup or any input gets
+ available. */
+ while (!detect_input_pending ())
+ {
+ /* Break if result would not be positive. */
+ if (wakeup < system_time ())
+ break;
+
+ /* Try to wait that long--but we might wake up sooner. */
+ wait_for_objects_etc (&info, 1, B_ABSOLUTE_TIMEOUT, wakeup);
+
+ if (info.events & B_EVENT_READ)
+ break;
+
+ info.events = B_EVENT_READ;
+ }
+
+ BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+ BView_StartClip (view);
+ /* If window is tall, flash top and bottom line. */
+ if (height > 3 * FRAME_LINE_HEIGHT (f))
+ {
+ BView_InvertRect (view, flash_left,
+ (FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_TOP_MARGIN_HEIGHT (f)),
+ width, flash_height);
+
+ BView_InvertRect (view, flash_left,
+ (height - flash_height
+ - FRAME_INTERNAL_BORDER_WIDTH (f)),
+ width, flash_height);
+ }
+ else
+ /* If it is short, flash it all. */
+ BView_InvertRect (view, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ BView_EndClip (view);
+ BView_draw_unlock (view);
+
+ flush_frame (f);
+ if (EmacsView_double_buffered_p (view))
+ haiku_flip_buffers (f);
+}
+
+static void
haiku_beep (struct frame *f)
{
if (visible_bell)
@@ -3294,21 +4210,7 @@ haiku_beep (struct frame *f)
if (view)
{
block_input ();
- BView_draw_lock (view);
- if (!EmacsView_double_buffered_p (view))
- {
- BView_SetHighColorForVisibleBell (view, FRAME_FOREGROUND_PIXEL (f));
- BView_FillRectangleForVisibleBell (view, 0, 0, FRAME_PIXEL_WIDTH (f),
- FRAME_PIXEL_HEIGHT (f));
- SET_FRAME_GARBAGED (f);
- expose_frame (f, 0, 0, 0, 0);
- }
- else
- {
- EmacsView_do_visible_bell (view, FRAME_FOREGROUND_PIXEL (f));
- haiku_flip_buffers (f);
- }
- BView_draw_unlock (view);
+ haiku_flash (f);
unblock_input ();
}
}
@@ -3321,12 +4223,12 @@ haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
{
void *view = FRAME_HAIKU_VIEW (f);
- if (view)
+ if (view && !FRAME_TOOLTIP_P (f))
{
block_input ();
- BView_set_view_cursor (view, invisible_p ?
- FRAME_OUTPUT_DATA (f)->no_cursor :
- FRAME_OUTPUT_DATA (f)->current_cursor);
+ BView_set_view_cursor (view, (invisible_p
+ ? FRAME_OUTPUT_DATA (f)->no_cursor
+ : FRAME_OUTPUT_DATA (f)->current_cursor));
f->pointer_invisible = invisible_p;
unblock_input ();
}
@@ -3335,22 +4237,32 @@ haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
static void
haiku_fullscreen (struct frame *f)
{
+ enum haiku_fullscreen_mode mode;
+
+ /* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is
+ being created, and its regular width and height have not yet been
+ set. This function will be called again by haiku_create_frame,
+ so do nothing. */
+ if (!FRAME_OUTPUT_DATA (f)->configury_done)
+ return;
+
if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
- {
- EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
- BWindow_zoom (FRAME_HAIKU_WINDOW (f));
- }
+ mode = FULLSCREEN_MODE_MAXIMIZED;
else if (f->want_fullscreen == FULLSCREEN_BOTH)
- EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1);
- else if (f->want_fullscreen == FULLSCREEN_NONE)
- {
- EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
- EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f));
- }
+ mode = FULLSCREEN_MODE_BOTH;
+ else if (f->want_fullscreen == FULLSCREEN_WIDTH)
+ mode = FULLSCREEN_MODE_WIDTH;
+ else if (f->want_fullscreen == FULLSCREEN_HEIGHT)
+ mode = FULLSCREEN_MODE_HEIGHT;
+ else
+ mode = FULLSCREEN_MODE_NONE;
f->want_fullscreen = FULLSCREEN_NONE;
+ be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode);
+ FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode;
haiku_update_size_hints (f);
+ haiku_make_fullscreen_consistent (f);
}
static struct terminal *
@@ -3371,7 +4283,7 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo)
terminal->frame_visible_invisible_hook = haiku_set_frame_visible_invisible;
terminal->set_frame_offset_hook = haiku_set_offset;
terminal->delete_terminal_hook = haiku_delete_terminal;
- terminal->get_string_resource_hook = get_string_resource;
+ terminal->get_string_resource_hook = haiku_get_string_resource;
terminal->set_new_font_hook = haiku_new_font;
terminal->defined_color_hook = haiku_defined_color;
terminal->set_window_size_hook = haiku_set_window_size;
@@ -3400,6 +4312,9 @@ haiku_create_terminal (struct haiku_display_info *dpyinfo)
terminal->menu_show_hook = haiku_menu_show;
terminal->toggle_invisible_pointer_hook = haiku_toggle_invisible_pointer;
terminal->fullscreen_hook = haiku_fullscreen;
+ terminal->toolkit_position_hook = haiku_toolkit_position;
+ terminal->activate_menubar_hook = haiku_activate_menubar;
+ terminal->get_focus_frame = haiku_get_focus_frame;
return terminal;
}
@@ -3409,36 +4324,34 @@ haiku_term_init (void)
{
struct haiku_display_info *dpyinfo;
struct terminal *terminal;
-
- Lisp_Object color_file, color_map;
+ Lisp_Object color_file, color_map, system_name;
+ ptrdiff_t nbytes;
+ void *name_buffer;
block_input ();
- Fset_input_interrupt_mode (Qnil);
+ Fset_input_interrupt_mode (Qt);
baud_rate = 19200;
-
dpyinfo = xzalloc (sizeof *dpyinfo);
-
haiku_io_init ();
- if (port_application_to_emacs < B_OK)
+ if (port_application_to_emacs < B_OK
+ || port_emacs_to_session_manager < B_OK)
emacs_abort ();
color_file = Fexpand_file_name (build_string ("rgb.txt"),
Fsymbol_value (intern ("data-directory")));
-
color_map = Fx_load_color_file (color_file);
+
if (NILP (color_map))
fatal ("Could not read %s.\n", SDATA (color_file));
dpyinfo->color_map = color_map;
-
dpyinfo->display = BApplication_setup ();
-
- BScreen_res (&dpyinfo->resx, &dpyinfo->resy);
-
dpyinfo->next = x_display_list;
dpyinfo->n_planes = be_get_display_planes ();
+ be_get_display_resolution (&dpyinfo->resx, &dpyinfo->resy);
+
x_display_list = dpyinfo;
terminal = haiku_create_terminal (dpyinfo);
@@ -3456,6 +4369,45 @@ haiku_term_init (void)
dpyinfo->smallest_char_width = 1;
gui_init_fringe (terminal->rif);
+
+#define ASSIGN_CURSOR(cursor, cursor_id) \
+ (dpyinfo->cursor = be_create_cursor_from_id (cursor_id))
+ ASSIGN_CURSOR (text_cursor, CURSOR_ID_I_BEAM);
+ ASSIGN_CURSOR (nontext_cursor, CURSOR_ID_SYSTEM_DEFAULT);
+ ASSIGN_CURSOR (modeline_cursor, CURSOR_ID_CONTEXT_MENU);
+ ASSIGN_CURSOR (hand_cursor, CURSOR_ID_GRAB);
+ ASSIGN_CURSOR (hourglass_cursor, CURSOR_ID_PROGRESS);
+ ASSIGN_CURSOR (horizontal_drag_cursor, CURSOR_ID_RESIZE_EAST_WEST);
+ ASSIGN_CURSOR (vertical_drag_cursor, CURSOR_ID_RESIZE_NORTH_SOUTH);
+ ASSIGN_CURSOR (left_edge_cursor, CURSOR_ID_RESIZE_WEST);
+ ASSIGN_CURSOR (top_left_corner_cursor, CURSOR_ID_RESIZE_NORTH_WEST);
+ ASSIGN_CURSOR (top_edge_cursor, CURSOR_ID_RESIZE_NORTH);
+ ASSIGN_CURSOR (top_right_corner_cursor, CURSOR_ID_RESIZE_NORTH_EAST);
+ ASSIGN_CURSOR (right_edge_cursor, CURSOR_ID_RESIZE_EAST);
+ ASSIGN_CURSOR (bottom_right_corner_cursor, CURSOR_ID_RESIZE_SOUTH_EAST);
+ ASSIGN_CURSOR (bottom_edge_cursor, CURSOR_ID_RESIZE_SOUTH);
+ ASSIGN_CURSOR (bottom_left_corner_cursor, CURSOR_ID_RESIZE_SOUTH_WEST);
+ ASSIGN_CURSOR (no_cursor, CURSOR_ID_NO_CURSOR);
+#undef ASSIGN_CURSOR
+
+ system_name = Fsystem_name ();
+
+ if (STRINGP (system_name))
+ {
+ nbytes = sizeof "GNU Emacs" + sizeof " at ";
+
+ if (INT_ADD_WRAPV (nbytes, SBYTES (system_name), &nbytes))
+ memory_full (SIZE_MAX);
+
+ name_buffer = alloca (nbytes);
+ sprintf (name_buffer, "%s%s%s", "GNU Emacs",
+ " at ", SDATA (system_name));
+ dpyinfo->default_name = build_string (name_buffer);
+ }
+ else
+ dpyinfo->default_name = build_string ("GNU Emacs");
+
+ haiku_start_watching_selections ();
unblock_input ();
return dpyinfo;
@@ -3477,7 +4429,10 @@ put_xrm_resource (Lisp_Object name, Lisp_Object val)
void
haiku_clear_under_internal_border (struct frame *f)
{
- if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
+ if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
+ /* This is needed because tooltip frames set up the internal
+ border before init_frame_faces. */
+ && FRAME_FACE_CACHE (f))
{
int border = FRAME_INTERNAL_BORDER_WIDTH (f);
int width = FRAME_PIXEL_WIDTH (f);
@@ -3493,8 +4448,10 @@ haiku_clear_under_internal_border (struct frame *f)
: INTERNAL_BORDER_FACE_ID));
struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
void *view = FRAME_HAIKU_VIEW (f);
+
block_input ();
- BView_draw_lock (view);
+ BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
BView_StartClip (view);
BView_ClipToRect (view, 0, 0, FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f));
@@ -3519,15 +4476,24 @@ void
mark_haiku_display (void)
{
if (x_display_list)
- mark_object (x_display_list->color_map);
+ {
+ mark_object (x_display_list->color_map);
+ mark_object (x_display_list->default_name);
+ }
}
void
haiku_scroll_bar_remove (struct scroll_bar *bar)
{
+ void *view;
+ struct frame *f;
+
+ f = WINDOW_XFRAME (XWINDOW (bar->window));
+ view = FRAME_HAIKU_VIEW (f);
+
block_input ();
- void *view = FRAME_HAIKU_VIEW (WINDOW_XFRAME (XWINDOW (bar->window)));
- BView_forget_scroll_bar (view, bar->left, bar->top, bar->width, bar->height);
+ BView_forget_scroll_bar (view, bar->left, bar->top,
+ bar->width, bar->height);
BScrollBar_delete (bar->scroll_bar);
expose_frame (WINDOW_XFRAME (XWINDOW (bar->window)),
bar->left, bar->top, bar->width, bar->height);
@@ -3536,7 +4502,6 @@ haiku_scroll_bar_remove (struct scroll_bar *bar)
wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
else
wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
-
unblock_input ();
};
@@ -3544,6 +4509,22 @@ void
haiku_set_offset (struct frame *frame, int x, int y,
int change_gravity)
{
+ Lisp_Object lframe;
+
+ /* Don't allow moving a fullscreen frame: the semantics of that are
+ unclear. */
+
+ XSETFRAME (lframe, frame);
+ if (EQ (Fframe_parameter (lframe, Qfullscreen), Qfullboth)
+ /* Only do this if the fullscreen status has actually been
+ applied. */
+ && frame->want_fullscreen == FULLSCREEN_NONE
+ /* And if the configury during frame creation has been
+ completed. Otherwise, there will be no valid "old position"
+ to go back to. */
+ && FRAME_OUTPUT_DATA (frame)->configury_done)
+ return;
+
if (change_gravity > 0)
{
frame->top_pos = y;
@@ -3568,22 +4549,54 @@ haiku_set_offset (struct frame *frame, int x, int y,
cairo_t *
haiku_begin_cr_clip (struct frame *f, struct glyph_string *s)
{
- cairo_surface_t *surface = FRAME_CR_SURFACE (f);
- if (!surface)
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+
+ if (!cr)
return NULL;
- cairo_t *context = cairo_create (surface);
- return context;
+ cairo_save (cr);
+ return cr;
}
void
haiku_end_cr_clip (cairo_t *cr)
{
- cairo_destroy (cr);
+ if (!cr)
+ return;
+
+ cairo_restore (cr);
}
#endif
void
+haiku_merge_cursor_foreground (struct glyph_string *s,
+ unsigned long *foreground_out,
+ unsigned long *background_out)
+{
+ unsigned long background = FRAME_CURSOR_COLOR (s->f).pixel;
+ unsigned long foreground = s->face->background;
+
+ if (background == foreground)
+ foreground = s->face->background;
+ if (background == foreground)
+ foreground = FRAME_OUTPUT_DATA (s->f)->cursor_fg;
+ if (background == foreground)
+ foreground = s->face->foreground;
+
+ if (background == s->face->background
+ && foreground == s->face->foreground)
+ {
+ background = s->face->foreground;
+ foreground = s->face->background;
+ }
+
+ if (foreground_out)
+ *foreground_out = foreground;
+ if (background_out)
+ *background_out = background;
+}
+
+void
syms_of_haikuterm (void)
{
DEFVAR_BOOL ("haiku-initialized", haiku_initialized,
@@ -3644,7 +4657,6 @@ This is either one of the symbols `shift', `control', `command', and
Setting it to any other value is equivalent to `shift'. */);
Vhaiku_shift_keysym = Qnil;
-
DEFSYM (Qx_use_underline_position_properties,
"x-use-underline-position-properties");
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 3e39403ab4d..46a2218e492 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -32,16 +32,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "font.h"
#include "systime.h"
-#define C_FRAME struct frame *
-#define C_FONT struct font *
-#define C_TERMINAL struct terminal *
-
#define HAVE_CHAR_CACHE_MAX 65535
extern int popup_activated_p;
-extern void be_app_quit (void);
-
struct haikufont_info
{
struct font font;
@@ -58,13 +52,17 @@ struct haiku_bitmap_record
char *file;
int refcount;
int height, width, depth;
+
+ uint32_t stipple_foreground;
+ uint32_t stipple_background;
+ void *stipple_bits;
};
struct haiku_display_info
{
/* Chain of all haiku_display_info structures. */
struct haiku_display_info *next;
- C_TERMINAL terminal;
+ struct terminal *terminal;
Lisp_Object name_list_element;
Lisp_Object color_map;
@@ -86,34 +84,53 @@ struct haiku_display_info
int n_planes;
int color_p;
- Window root_window;
Lisp_Object rdb;
+ Lisp_Object default_name;
Emacs_Cursor vertical_scroll_bar_cursor;
Emacs_Cursor horizontal_scroll_bar_cursor;
Mouse_HLInfo mouse_highlight;
- C_FRAME highlight_frame;
- C_FRAME last_mouse_frame;
- C_FRAME last_mouse_motion_frame;
+ struct frame *highlight_frame;
+ struct frame *last_mouse_frame;
+ struct frame *last_mouse_motion_frame;
int last_mouse_motion_x;
int last_mouse_motion_y;
struct haiku_rect last_mouse_glyph;
- void *last_mouse_scroll_bar;
-
haiku display;
double resx, resy;
Time last_mouse_movement_time;
+
+ Window root_window;
+
+ Emacs_Cursor text_cursor;
+ Emacs_Cursor nontext_cursor;
+ Emacs_Cursor modeline_cursor;
+ Emacs_Cursor hand_cursor;
+ Emacs_Cursor hourglass_cursor;
+ Emacs_Cursor horizontal_drag_cursor;
+ Emacs_Cursor vertical_drag_cursor;
+ Emacs_Cursor left_edge_cursor;
+ Emacs_Cursor top_left_corner_cursor;
+ Emacs_Cursor top_edge_cursor;
+ Emacs_Cursor top_right_corner_cursor;
+ Emacs_Cursor right_edge_cursor;
+ Emacs_Cursor bottom_right_corner_cursor;
+ Emacs_Cursor bottom_edge_cursor;
+ Emacs_Cursor bottom_left_corner_cursor;
+ Emacs_Cursor no_cursor;
};
struct haiku_output
{
+ struct haiku_display_info *display_info;
+
Emacs_Cursor text_cursor;
Emacs_Cursor nontext_cursor;
Emacs_Cursor modeline_cursor;
@@ -130,44 +147,67 @@ struct haiku_output
Emacs_Cursor bottom_edge_cursor;
Emacs_Cursor bottom_left_corner_cursor;
Emacs_Cursor no_cursor;
-
Emacs_Cursor current_cursor;
- struct haiku_display_info *display_info;
-
- int baseline_offset;
- int fontset;
-
Emacs_Color cursor_color;
- Window window_desc, parent_desc;
- char explicit_parent;
-
- int titlebar_height;
- int toolbar_height;
+ Window parent_desc;
haiku window;
haiku view;
haiku menubar;
- int menu_up_to_date_p;
- int zoomed_p;
+ int fontset;
+ int baseline_offset;
- int pending_zoom_x;
- int pending_zoom_y;
- int pending_zoom_width;
- int pending_zoom_height;
+ /* Whether or not the hourglass cursor is currently being
+ displayed. */
+ bool_bf hourglass_p : 1;
- int menu_bar_open_p;
+ /* Whether or not the menu bar is open. */
+ bool_bf menu_bar_open_p : 1;
- C_FONT font;
+ /* Whether or not there is data in a back buffer that hasn't been
+ displayed yet. */
+ bool_bf dirty_p : 1;
- int hourglass_p;
- uint32_t cursor_fg;
- bool dirty_p;
+ struct font *font;
/* The pending position we're waiting for. */
int pending_top, pending_left;
+
+ /* Whether or not adjust_frame_size and haiku_set_offset have yet
+ been called by haiku_create_frame. */
+ bool configury_done;
+
+ /* The default cursor foreground color. */
+ uint32_t cursor_fg;
+
+ /* If non-NULL, the last menu bar click event received. */
+ struct haiku_menu_bar_click_event *saved_menu_event;
+
+ /* The type of any event that's being waited for. */
+ int wait_for_event_type;
+
+ /* The "dark" color of the current relief. */
+ uint32_t black_relief_pixel;
+
+ /* The "light" color of the current relief. */
+ uint32_t white_relief_pixel;
+
+ /* The background for which the relief colors above were computed.
+ They are changed only when a different background is involved.
+ -1 means no color has been computed. */
+ long relief_background;
+
+ /* The absolute position of this frame. This differs from left_pos
+ and top_pos in that the decorator and parent frames are not taken
+ into account. */
+ int frame_x, frame_y;
+
+ /* The current fullscreen mode of this frame. This should be `enum
+ haiku_fullscreen_mode', but that isn't available here. */
+ int fullscreen_mode;
};
struct x_output
@@ -178,6 +218,15 @@ struct x_output
extern struct haiku_display_info *x_display_list;
extern struct font_driver const haikufont_driver;
+extern Lisp_Object tip_frame;
+extern Lisp_Object tip_dx;
+extern Lisp_Object tip_dy;
+
+extern struct frame *haiku_dnd_frame;
+extern bool haiku_dnd_follow_tooltip;
+
+extern frame_parm_handler haiku_frame_parm_handlers[];
+
struct scroll_bar
{
/* These fields are shared by all vectors. */
@@ -214,26 +263,32 @@ struct scroll_bar
/* True if the scroll bar is horizontal. */
bool horizontal;
+
+ /* The amount of units taken up by the thumb, which represents the
+ portion of the buffer currently on screen. */
+ int page_size;
};
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
-#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p)
-#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1)
-#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku)
-#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
-#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view)
-#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar)
-#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info)
-#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font)
-#define FRAME_FONTSET(f) (FRAME_OUTPUT_DATA (f)->fontset)
-#define FRAME_NATIVE_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
-#define FRAME_BASELINE_OFFSET(f) (FRAME_OUTPUT_DATA (f)->baseline_offset)
-#define FRAME_CURSOR_COLOR(f) (FRAME_OUTPUT_DATA (f)->cursor_color)
+#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p)
+#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1)
+#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku)
+#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
+#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view)
+#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar)
+#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info)
+#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font)
+#define FRAME_FONTSET(f) (FRAME_OUTPUT_DATA (f)->fontset)
+#define FRAME_NATIVE_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
+#define FRAME_BASELINE_OFFSET(f) (FRAME_OUTPUT_DATA (f)->baseline_offset)
+#define FRAME_CURSOR_COLOR(f) (FRAME_OUTPUT_DATA (f)->cursor_color)
#ifdef USE_BE_CAIRO
-#define FRAME_CR_SURFACE(f) \
- (FRAME_HAIKU_VIEW (f) ? EmacsView_cairo_surface (FRAME_HAIKU_VIEW (f)) : 0);
+#define FRAME_CR_CONTEXT(f) \
+ (FRAME_HAIKU_VIEW (f) \
+ ? EmacsView_cairo_context (FRAME_HAIKU_VIEW (f)) \
+ : NULL)
#endif
extern void syms_of_haikuterm (void);
@@ -248,49 +303,60 @@ extern void haiku_visualize_frame (struct frame *);
extern void haiku_unvisualize_frame (struct frame *);
extern void haiku_set_offset (struct frame *, int, int, int);
extern void haiku_set_frame_visible_invisible (struct frame *, bool);
-extern void haiku_free_frame_resources (struct frame *f);
-extern void haiku_scroll_bar_remove (struct scroll_bar *bar);
-extern void haiku_clear_under_internal_border (struct frame *f);
-extern void haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p);
+extern void haiku_free_frame_resources (struct frame *);
+extern void haiku_scroll_bar_remove (struct scroll_bar *);
+extern void haiku_clear_under_internal_border (struct frame *);
+extern void haiku_set_name (struct frame *, Lisp_Object, bool);
+extern Lisp_Object haiku_message_to_lisp (void *);
extern struct haiku_display_info *haiku_term_init (void);
extern void mark_haiku_display (void);
-extern int haiku_get_color (const char *name, Emacs_Color *color);
-extern void haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
-extern void haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
-extern void haiku_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
-extern void haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
-extern void haiku_change_tab_bar_height (struct frame *f, int height);
-extern void haiku_change_tool_bar_height (struct frame *f, int height);
+extern int haiku_get_color (const char *, Emacs_Color *);
+extern void haiku_set_background_color (struct frame *, Lisp_Object, Lisp_Object);
+extern void haiku_set_cursor_color (struct frame *, Lisp_Object, Lisp_Object);
+extern void haiku_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
+extern void haiku_set_internal_border_width (struct frame *, Lisp_Object, Lisp_Object);
+extern void haiku_change_tab_bar_height (struct frame *, int);
+extern void haiku_change_tool_bar_height (struct frame *, int);
+extern void haiku_free_custom_cursors (struct frame *);
-extern void haiku_query_color (uint32_t col, Emacs_Color *color);
+extern void haiku_query_color (uint32_t, Emacs_Color *);
-extern unsigned long haiku_get_pixel (haiku bitmap, int x, int y);
-extern void haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel);
+extern unsigned long haiku_get_pixel (haiku, int, int);
+extern void haiku_put_pixel (haiku, int, int, unsigned long);
-extern Lisp_Object haiku_menu_show (struct frame *f, int x, int y, int menu_flags,
- Lisp_Object title, const char **error_name);
-extern Lisp_Object haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents);
+extern Lisp_Object haiku_menu_show (struct frame *, int, int, int,
+ Lisp_Object, const char **);
+extern Lisp_Object haiku_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
+extern void haiku_activate_menubar (struct frame *);
+extern void haiku_wait_for_event (struct frame *, int);
+extern void haiku_note_drag_motion (void);
-extern void initialize_frame_menubar (struct frame *f);
+extern void initialize_frame_menubar (struct frame *);
-extern void run_menu_bar_help_event (struct frame *f, int mb_idx);
-extern void put_xrm_resource (Lisp_Object name, Lisp_Object val);
+extern void run_menu_bar_help_event (struct frame *, int);
+extern void put_xrm_resource (Lisp_Object, Lisp_Object);
#ifdef HAVE_NATIVE_IMAGE_API
-extern bool haiku_can_use_native_image_api (Lisp_Object type);
-extern int haiku_load_image (struct frame *f, struct image *img,
- Lisp_Object spec_file, Lisp_Object spec_data);
+extern bool haiku_can_use_native_image_api (Lisp_Object);
+extern int haiku_load_image (struct frame *, struct image *,
+ Lisp_Object, Lisp_Object);
extern void syms_of_haikuimage (void);
#endif
+extern void haiku_draw_background_rect (struct glyph_string *, struct face *,
+ int, int, int, int);
+
#ifdef USE_BE_CAIRO
-extern cairo_t *
-haiku_begin_cr_clip (struct frame *f, struct glyph_string *s);
+extern cairo_t *haiku_begin_cr_clip (struct frame *, struct glyph_string *);
-extern void
-haiku_end_cr_clip (cairo_t *cr);
+extern void haiku_end_cr_clip (cairo_t *);
#endif
+
+extern void haiku_merge_cursor_foreground (struct glyph_string *, unsigned long *,
+ unsigned long *);
+extern void haiku_handle_selection_clear (struct input_event *);
+extern void haiku_start_watching_selections (void);
#endif /* _HAIKU_TERM_H_ */
diff --git a/src/image.c b/src/image.c
index e7d347b7820..c0a7b85cb3b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -542,8 +542,26 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
#endif /* HAVE_PGTK */
#ifdef HAVE_HAIKU
- void *bitmap = BBitmap_new (width, height, 1);
- BBitmap_import_mono_bits (bitmap, bits, width, height);
+ void *bitmap, *stipple;
+ int bytes_per_line, x, y;
+
+ bitmap = BBitmap_new (width, height, false);
+
+ if (!bitmap)
+ return -1;
+
+ bytes_per_line = (width + 7) / 8;
+ stipple = xmalloc (height * bytes_per_line);
+ memcpy (stipple, bits, height * bytes_per_line);
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ PUT_PIXEL (bitmap, x, y, ((bits[8] >> (x % 8)) & 1
+ ? f->foreground_pixel
+ : f->background_pixel));
+ bits += bytes_per_line;
+ }
#endif
id = image_allocate_bitmap_record (f);
@@ -563,6 +581,11 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
#ifdef HAVE_HAIKU
dpyinfo->bitmaps[id - 1].img = bitmap;
dpyinfo->bitmaps[id - 1].depth = 1;
+ dpyinfo->bitmaps[id - 1].stipple_bits = stipple;
+ dpyinfo->bitmaps[id - 1].stipple_foreground
+ = f->foreground_pixel & 0xffffffff;
+ dpyinfo->bitmaps[id - 1].stipple_background
+ = f->background_pixel & 0xffffffff;
#endif
dpyinfo->bitmaps[id - 1].file = NULL;
@@ -588,24 +611,55 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
return id;
}
+#if defined HAVE_HAIKU || defined HAVE_NS
+static char *slurp_file (int, ptrdiff_t *);
+static Lisp_Object image_find_image_fd (Lisp_Object, int *);
+static bool xbm_read_bitmap_data (struct frame *, char *, char *,
+ int *, int *, char **, bool);
+#endif
+
/* Create bitmap from file FILE for frame F. */
ptrdiff_t
image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
{
-#if defined (HAVE_NTGUI) || defined (HAVE_HAIKU)
+#if defined (HAVE_NTGUI)
return -1; /* W32_TODO : bitmap support */
#else
Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
#endif
#ifdef HAVE_NS
- ptrdiff_t id;
- void *bitmap = ns_image_from_file (file);
+ ptrdiff_t id, size;
+ int fd, width, height, rc;
+ char *contents, *data;
+ void *bitmap;
- if (!bitmap)
+ if (!STRINGP (image_find_image_fd (file, &fd)))
+ return -1;
+
+ contents = slurp_file (fd, &size);
+
+ if (!contents)
+ return -1;
+
+ rc = xbm_read_bitmap_data (f, contents, contents + size,
+ &width, &height, &data, 0);
+
+ if (!rc)
+ {
+ xfree (contents);
return -1;
+ }
+
+ bitmap = ns_image_from_XBM (data, width, height, 0, 0);
+ if (!bitmap)
+ {
+ xfree (contents);
+ xfree (data);
+ return -1;
+ }
id = image_allocate_bitmap_record (f);
dpyinfo->bitmaps[id - 1].img = bitmap;
@@ -614,6 +668,9 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
dpyinfo->bitmaps[id - 1].depth = 1;
dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap);
dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap);
+
+ xfree (contents);
+ xfree (data);
return id;
#endif
@@ -633,7 +690,6 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
dpyinfo->bitmaps[id - 1].img = bitmap;
dpyinfo->bitmaps[id - 1].refcount = 1;
dpyinfo->bitmaps[id - 1].file = xlispstrdup (file);
- //dpyinfo->bitmaps[id - 1].depth = 1;
dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap);
dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap);
dpyinfo->bitmaps[id - 1].pattern
@@ -688,6 +744,89 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
return id;
#endif /* HAVE_X_WINDOWS */
+
+#ifdef HAVE_HAIKU
+ ptrdiff_t id, size;
+ int fd, width, height, rc, bytes_per_line, x, y;
+ char *contents, *data, *tmp;
+ void *bitmap;
+ Lisp_Object found;
+
+ /* Look for an existing bitmap with the same name. */
+ for (id = 0; id < dpyinfo->bitmaps_last; ++id)
+ {
+ if (dpyinfo->bitmaps[id].refcount
+ && dpyinfo->bitmaps[id].file
+ && !strcmp (dpyinfo->bitmaps[id].file, SSDATA (file)))
+ {
+ ++dpyinfo->bitmaps[id].refcount;
+ return id + 1;
+ }
+ }
+
+ /* Search bitmap-file-path for the file, if appropriate. */
+ if (openp (Vx_bitmap_file_path, file, Qnil, &found,
+ make_fixnum (R_OK), false, false)
+ < 0)
+ return -1;
+
+ if (!STRINGP (image_find_image_fd (file, &fd))
+ && !STRINGP (image_find_image_fd (found, &fd)))
+ return -1;
+
+ contents = slurp_file (fd, &size);
+
+ if (!contents)
+ return -1;
+
+ rc = xbm_read_bitmap_data (f, contents, contents + size,
+ &width, &height, &data, 0);
+
+ if (!rc)
+ {
+ xfree (contents);
+ return -1;
+ }
+
+ bitmap = BBitmap_new (width, height, false);
+
+ if (!bitmap)
+ {
+ xfree (contents);
+ xfree (data);
+ return -1;
+ }
+
+ id = image_allocate_bitmap_record (f);
+
+ dpyinfo->bitmaps[id - 1].img = bitmap;
+ dpyinfo->bitmaps[id - 1].depth = 1;
+ dpyinfo->bitmaps[id - 1].file = xlispstrdup (file);
+ dpyinfo->bitmaps[id - 1].height = height;
+ dpyinfo->bitmaps[id - 1].width = width;
+ dpyinfo->bitmaps[id - 1].refcount = 1;
+ dpyinfo->bitmaps[id - 1].stipple_foreground
+ = f->foreground_pixel & 0xffffffff;
+ dpyinfo->bitmaps[id - 1].stipple_background
+ = f->background_pixel & 0xffffffff;
+ dpyinfo->bitmaps[id - 1].stipple_bits = data;
+
+ bytes_per_line = (width + 7) / 8;
+ tmp = data;
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ PUT_PIXEL (bitmap, x, y, ((tmp[x / 8] >> (x % 8)) & 1
+ ? f->foreground_pixel
+ : f->background_pixel));
+
+ tmp += bytes_per_line;
+ }
+
+ xfree (contents);
+ return id;
+#endif
}
/* Free bitmap B. */
@@ -720,6 +859,9 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
#ifdef HAVE_HAIKU
BBitmap_free (bm->img);
+
+ if (bm->stipple_bits)
+ xfree (bm->stipple_bits);
#endif
if (bm->file)
@@ -1177,7 +1319,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
return false;
maybe_done:
- if (EQ (XCDR (plist), Qnil))
+ if (NILP (XCDR (plist)))
{
/* Check that all mandatory fields are present. */
for (i = 0; i < nkeywords; ++i)
@@ -1792,13 +1934,50 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash,
}
+/* Filter out image elements that don't affect display, but will
+ disrupt finding the image in the cache. This should perhaps be
+ user-configurable, but for now it's hard-coded (but new elements
+ can be added at will). */
+static Lisp_Object
+filter_image_spec (Lisp_Object spec)
+{
+ Lisp_Object out = Qnil;
+
+ /* Skip past the `image' element. */
+ if (CONSP (spec))
+ spec = XCDR (spec);
+
+ while (CONSP (spec))
+ {
+ Lisp_Object key = XCAR (spec);
+ spec = XCDR (spec);
+ if (CONSP (spec))
+ {
+ Lisp_Object value = XCAR (spec);
+ spec = XCDR (spec);
+
+ /* Some animation-related data doesn't affect display, but
+ breaks the image cache. Filter those out. */
+ if (!(EQ (key, QCanimate_buffer)
+ || EQ (key, QCanimate_tardiness)
+ || EQ (key, QCanimate_position)
+ || EQ (key, QCanimate_multi_frame_data)))
+ {
+ out = Fcons (value, out);
+ out = Fcons (key, out);
+ }
+ }
+ }
+ return out;
+}
+
/* Search frame F for an image with spec SPEC, and free it. */
static void
uncache_image (struct frame *f, Lisp_Object spec)
{
struct image *img;
- EMACS_UINT hash = sxhash (spec);
+ EMACS_UINT hash = sxhash (filter_image_spec (spec));
/* Because the background colors are based on the current face, we
can have multiple copies of an image with the same spec. We want
@@ -2130,8 +2309,8 @@ postprocess_image (struct frame *f, struct image *img)
tem = XCDR (conversion);
if (CONSP (tem))
image_edge_detection (f, img,
- Fplist_get (tem, QCmatrix),
- Fplist_get (tem, QCcolor_adjustment));
+ plist_get (tem, QCmatrix),
+ plist_get (tem, QCcolor_adjustment));
}
}
}
@@ -2324,17 +2503,17 @@ compute_image_size (double width, double height,
finally move the origin back to the top left of the image, which
may now be a different corner.
- Note that different GUI backends (X, Cairo, w32, NS) want the
- transform matrix defined as transform from the original image to
- the transformed image, while others want the matrix to describe the
- transform of the space, which boils down to inverting the matrix.
+ Note that different GUI backends (X, Cairo, w32, NS, Haiku) want
+ the transform matrix defined as transform from the original image
+ to the transformed image, while others want the matrix to describe
+ the transform of the space, which boils down to inverting the
+ matrix.
It's possible to pre-calculate the matrix multiplications and just
generate one transform matrix that will do everything we need in a
single step, but the maths for each element is much more complex
and performing the steps separately makes for more readable code. */
-#ifndef HAVE_HAIKU
typedef double matrix3x3[3][3];
static void
@@ -2349,7 +2528,6 @@ matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result)
result[i][j] = sum;
}
}
-#endif /* not HAVE_HAIKU */
static void
compute_image_rotation (struct image *img, double *rotation)
@@ -2374,6 +2552,22 @@ compute_image_rotation (struct image *img, double *rotation)
static void
image_set_transform (struct frame *f, struct image *img)
{
+ bool flip;
+
+#if defined HAVE_HAIKU
+ matrix3x3 identity = {
+ { 1, 0, 0 },
+ { 0, 1, 0 },
+ { 0, 0, 1 },
+ };
+
+ img->original_width = img->width;
+ img->original_height = img->height;
+ img->use_bilinear_filtering = false;
+
+ memcpy (&img->transform, identity, sizeof identity);
+#endif
+
# if (defined HAVE_IMAGEMAGICK \
&& !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE)
/* ImageMagick images already have the correct transform. */
@@ -2408,8 +2602,10 @@ image_set_transform (struct frame *f, struct image *img)
double rotation = 0.0;
compute_image_rotation (img, &rotation);
-#ifndef HAVE_HAIKU
-# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
+ /* Determine flipping. */
+ flip = !NILP (image_spec_value (img->spec, QCflip, NULL));
+
+# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU
/* We want scale up operations to use a nearest neighbor filter to
show real pixels instead of munging them, but scale down
operations to use a blended filter, to avoid aliasing and the like.
@@ -2423,6 +2619,10 @@ image_set_transform (struct frame *f, struct image *img)
smoothing = !NILP (s);
# endif
+#ifdef HAVE_HAIKU
+ img->use_bilinear_filtering = smoothing;
+#endif
+
/* Perform scale transformation. */
matrix3x3 matrix
@@ -2432,7 +2632,7 @@ image_set_transform (struct frame *f, struct image *img)
: img->width / (double) width),
[1][1] = (!IEEE_FLOATING_POINT && height == 0 ? DBL_MAX
: img->height / (double) height),
-# elif defined HAVE_NTGUI || defined HAVE_NS
+# elif defined HAVE_NTGUI || defined HAVE_NS || defined HAVE_HAIKU
[0][0] = (!IEEE_FLOATING_POINT && img->width == 0 ? DBL_MAX
: width / (double) img->width),
[1][1] = (!IEEE_FLOATING_POINT && img->height == 0 ? DBL_MAX
@@ -2447,26 +2647,65 @@ image_set_transform (struct frame *f, struct image *img)
/* Perform rotation transformation. */
int rotate_flag = -1;
- if (rotation == 0)
+
+ /* Haiku needs this, since the transformation is done on the basis
+ of the view, and not the image. */
+#ifdef HAVE_HAIKU
+ int extra_tx, extra_ty;
+
+ extra_tx = 0;
+ extra_ty = 0;
+#endif
+
+ if (rotation == 0 && !flip)
rotate_flag = 0;
else
{
# if (defined USE_CAIRO || defined HAVE_XRENDER \
- || defined HAVE_NTGUI || defined HAVE_NS)
+ || defined HAVE_NTGUI || defined HAVE_NS \
+ || defined HAVE_HAIKU)
int cos_r, sin_r;
- if (rotation == 90)
+ if (rotation == 0)
+ {
+ /* FLIP is always true here. As this will rotate by 0
+ degrees, it has no visible effect. Applying only
+ translation matrix to the image would be sufficient for
+ horizontal flipping, but writing special handling for
+ this case would increase code complexity somewhat. */
+ cos_r = 1;
+ sin_r = 0;
+ rotate_flag = 1;
+
+#ifdef HAVE_HAIKU
+ extra_tx = width;
+ extra_ty = 0;
+#endif
+ }
+ else if (rotation == 90)
{
width = img->height;
height = img->width;
cos_r = 0;
sin_r = 1;
rotate_flag = 1;
+
+#ifdef HAVE_HAIKU
+ if (!flip)
+ extra_ty = height;
+ extra_tx = 0;
+#endif
}
else if (rotation == 180)
{
cos_r = -1;
sin_r = 0;
rotate_flag = 1;
+
+#ifdef HAVE_HAIKU
+ if (!flip)
+ extra_tx = width;
+ extra_ty = height;
+#endif
}
else if (rotation == 270)
{
@@ -2475,6 +2714,13 @@ image_set_transform (struct frame *f, struct image *img)
cos_r = 0;
sin_r = -1;
rotate_flag = 1;
+
+#ifdef HAVE_HAIKU
+ extra_tx = width;
+
+ if (flip)
+ extra_ty = height;
+#endif
}
if (0 < rotate_flag)
@@ -2495,9 +2741,14 @@ image_set_transform (struct frame *f, struct image *img)
matrix3x3 v;
matrix3x3_mult (rot, u, v);
- /* 3. Translate back. */
+ /* 3. Translate back. Flip horizontally if requested. */
t[2][0] = width * -.5;
t[2][1] = height * -.5;
+ if (flip)
+ {
+ t[0][0] = -t[0][0];
+ t[2][0] = -t[2][0];
+ }
matrix3x3_mult (t, v, matrix);
# else
/* 1. Translate so (0, 0) is in the center of the image. */
@@ -2515,9 +2766,10 @@ image_set_transform (struct frame *f, struct image *img)
matrix3x3 v;
matrix3x3_mult (u, rot, v);
- /* 3. Translate back. */
+ /* 3. Translate back. Flip horizontally if requested. */
t[2][0] = width * .5;
t[2][1] = height * .5;
+ if (flip) t[0][0] = -t[0][0];
matrix3x3_mult (v, t, matrix);
# endif
img->width = width;
@@ -2578,35 +2830,17 @@ image_set_transform (struct frame *f, struct image *img)
img->xform.eM22 = matrix[1][1];
img->xform.eDx = matrix[2][0];
img->xform.eDy = matrix[2][1];
-# endif
-#else
- if (rotation != 0 &&
- rotation != 90 &&
- rotation != 180 &&
- rotation != 270 &&
- rotation != 360)
- {
- image_error ("No native support for rotation by %g degrees",
- make_float (rotation));
- return;
- }
-
- rotation = fmod (rotation, 360.0);
+# elif defined HAVE_HAIKU
+ /* Store the transform in the struct image for later. */
+ memcpy (&img->transform, &matrix, sizeof matrix);
- if (rotation == 90 || rotation == 270)
+ /* Also add the extra translations. */
+ if (rotate_flag)
{
- int w = width;
- width = height;
- height = w;
+ img->transform[0][2] = extra_tx;
+ img->transform[1][2] = extra_ty;
}
-
- img->have_be_transforms_p = rotation != 0 || (img->width != width) || (img->height != height);
- img->be_rotate = rotation;
- img->be_scale_x = 1.0 / (img->width / (double) width);
- img->be_scale_y = 1.0 / (img->height / (double) height);
- img->width = width;
- img->height = height;
-#endif /* not HAVE_HAIKU */
+#endif
}
#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */
@@ -2639,7 +2873,7 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
eassert (valid_image_p (spec));
/* Look up SPEC in the hash table of the image cache. */
- hash = sxhash (spec);
+ hash = sxhash (filter_image_spec (spec));
img = search_image_cache (f, spec, hash, foreground, background,
font_size, font_family, false);
if (img && img->load_failed_p)
@@ -2778,6 +3012,92 @@ cache_image (struct frame *f, struct image *img)
}
+#if defined (HAVE_WEBP) || defined (HAVE_GIF)
+
+/* To speed animations up, we keep a cache (based on EQ-ness of the
+ image spec/object) where we put the animator iterator. */
+
+struct anim_cache
+{
+ Lisp_Object spec;
+ /* For webp, this will be an iterator, and for libgif, a gif handle. */
+ void *handle;
+ /* If we need to maintain temporary data of some sort. */
+ void *temp;
+ /* A function to call to free the handle. */
+ void (*destructor) (void *);
+ int index, width, height, frames;
+ struct timespec update_time;
+ struct anim_cache *next;
+};
+
+static struct anim_cache *anim_cache = NULL;
+
+static struct anim_cache *
+anim_create_cache (Lisp_Object spec)
+{
+ struct anim_cache *cache = xmalloc (sizeof (struct anim_cache));
+ cache->handle = NULL;
+ cache->temp = NULL;
+
+ cache->index = -1;
+ cache->next = NULL;
+ cache->spec = spec;
+ return cache;
+}
+
+/* Discard cached images that haven't been used for a minute. */
+static void
+anim_prune_animation_cache (void)
+{
+ struct anim_cache **pcache = &anim_cache;
+ struct timespec old = timespec_sub (current_timespec (),
+ make_timespec (60, 0));
+
+ while (*pcache)
+ {
+ struct anim_cache *cache = *pcache;
+ if (timespec_cmp (old, cache->update_time) <= 0)
+ pcache = &cache->next;
+ else
+ {
+ if (cache->handle)
+ cache->destructor (cache);
+ if (cache->temp)
+ xfree (cache->temp);
+ *pcache = cache->next;
+ xfree (cache);
+ }
+ }
+}
+
+static struct anim_cache *
+anim_get_animation_cache (Lisp_Object spec)
+{
+ struct anim_cache *cache;
+ struct anim_cache **pcache = &anim_cache;
+
+ anim_prune_animation_cache ();
+
+ while (1)
+ {
+ cache = *pcache;
+ if (! cache)
+ {
+ *pcache = cache = anim_create_cache (spec);
+ break;
+ }
+ if (EQ (spec, cache->spec))
+ break;
+ pcache = &cache->next;
+ }
+
+ cache->update_time = current_timespec ();
+ return cache;
+}
+
+#endif /* HAVE_WEBP || HAVE_GIF */
+
/* Call FN on every image in the image cache of frame F. Used to mark
Lisp Objects in the image cache. */
@@ -2804,6 +3124,11 @@ mark_image_cache (struct image_cache *c)
if (c->images[i])
mark_image (c->images[i]);
}
+
+#if defined HAVE_WEBP || defined HAVE_GIF
+ for (struct anim_cache *cache = anim_cache; cache; cache = cache->next)
+ mark_object (cache->spec);
+#endif
}
@@ -2848,13 +3173,12 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
{
Display *display = FRAME_X_DISPLAY (f);
Drawable drawable = FRAME_X_DRAWABLE (f);
- Screen *screen = FRAME_X_SCREEN (f);
eassert (input_blocked_p ());
if (depth <= 0)
- depth = DefaultDepthOfScreen (screen);
- *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
+ depth = FRAME_DISPLAY_INFO (f)->n_planes;
+ *ximg = XCreateImage (display, FRAME_X_VISUAL (f),
depth, ZPixmap, 0, NULL, width, height,
depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
if (*ximg == NULL)
@@ -2906,12 +3230,11 @@ x_create_xrender_picture (struct frame *f, Emacs_Pixmap pixmap, int depth)
{
Picture p;
Display *display = FRAME_X_DISPLAY (f);
- int event_basep, error_basep;
- if (XRenderQueryExtension (display, &event_basep, &error_basep))
+ if (FRAME_DISPLAY_INFO (f)->xrender_supported_p)
{
if (depth <= 0)
- depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+ depth = FRAME_DISPLAY_INFO (f)->n_planes;
if (depth == 32 || depth == 24 || depth == 8 || depth == 4 || depth == 1)
{
/* FIXME: Do we need to handle all possible bit depths?
@@ -3403,7 +3726,7 @@ slurp_file (int fd, ptrdiff_t *size)
if (fp)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_ptr (fclose_unwind, fp);
if (fstat (fileno (fp), &st) == 0
@@ -3455,6 +3778,8 @@ enum xbm_keyword_index
XBM_ALGORITHM,
XBM_HEURISTIC_MASK,
XBM_MASK,
+ XBM_DATA_WIDTH,
+ XBM_DATA_HEIGHT,
XBM_LAST
};
@@ -3476,7 +3801,9 @@ static const struct image_keyword xbm_format[XBM_LAST] =
{":relief", IMAGE_INTEGER_VALUE, 0},
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":data-width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":data-height", IMAGE_POSITIVE_INTEGER_VALUE, 0}
};
/* Tokens returned from xbm_scan. */
@@ -3498,8 +3825,8 @@ enum xbm_token
an entry `:file FILENAME' where FILENAME is a string.
If the specification is for a bitmap loaded from memory it must
- contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
- WIDTH and HEIGHT are integers > 0. DATA may be:
+ contain `:data-width WIDTH', `:data-height HEIGHT', and `:data DATA',
+ where WIDTH and HEIGHT are integers > 0. DATA may be:
1. a string large enough to hold the bitmap data, i.e. it must
have a size >= (WIDTH + 7) / 8 * HEIGHT
@@ -3509,9 +3836,7 @@ enum xbm_token
3. a vector of strings or bool-vectors, one for each line of the
bitmap.
- 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
- may not be specified in this case because they are defined in the
- XBM file.
+ 4. a string containing an in-memory XBM file.
Both the file and data forms may contain the additional entries
`:background COLOR' and `:foreground COLOR'. If not present,
@@ -3531,13 +3856,13 @@ xbm_image_p (Lisp_Object object)
if (kw[XBM_FILE].count)
{
- if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
+ if (kw[XBM_DATA].count)
return 0;
}
else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
{
/* In-memory XBM file. */
- if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+ if (kw[XBM_FILE].count)
return 0;
}
else
@@ -3546,14 +3871,14 @@ xbm_image_p (Lisp_Object object)
int width, height, stride;
/* Entries for `:width', `:height' and `:data' must be present. */
- if (!kw[XBM_WIDTH].count
- || !kw[XBM_HEIGHT].count
+ if (!kw[XBM_DATA_WIDTH].count
+ || !kw[XBM_DATA_HEIGHT].count
|| !kw[XBM_DATA].count)
return 0;
data = kw[XBM_DATA].value;
- width = XFIXNAT (kw[XBM_WIDTH].value);
- height = XFIXNAT (kw[XBM_HEIGHT].value);
+ width = XFIXNAT (kw[XBM_DATA_WIDTH].value);
+ height = XFIXNAT (kw[XBM_DATA_HEIGHT].value);
if (!kw[XBM_STRIDE].count)
stride = width;
@@ -3679,6 +4004,48 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
*ival = value;
return overflow ? XBM_TK_OVERFLOW : XBM_TK_NUMBER;
}
+ /* Character literal. XBM images typically contain hex escape
+ sequences and not actual characters, so we only try to handle
+ that here. */
+ else if (c == '\'')
+ {
+ int value = 0, digit;
+ bool overflow = false;
+
+ if (*s == end)
+ return 0;
+
+ c = *(*s)++;
+
+ if (c != '\\' || *s == end)
+ return 0;
+
+ c = *(*s)++;
+
+ if (c == 'x')
+ {
+ while (*s < end)
+ {
+ c = *(*s)++;
+
+ if (c == '\'')
+ {
+ *ival = value;
+ return overflow ? XBM_TK_OVERFLOW : XBM_TK_NUMBER;
+ }
+
+ digit = char_hexdigit (c);
+
+ if (digit < 0)
+ return 0;
+
+ overflow |= INT_MULTIPLY_WRAPV (value, 16, &value);
+ value += digit;
+ }
+ }
+
+ return 0;
+ }
else if (c_isalpha (c) || c == '_')
{
*sval++ = c;
@@ -3802,7 +4169,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
data,
img->width, img->height,
fg, bg,
- DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+ FRAME_DISPLAY_INFO (f)->n_planes);
# if !defined USE_CAIRO && defined HAVE_XRENDER
if (img->pixmap)
img->picture = x_create_xrender_picture (f, img->pixmap, 0);
@@ -3817,6 +4184,21 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
convert_mono_to_color_image (f, img, fg, bg);
#elif defined HAVE_NS
img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg);
+#elif defined HAVE_HAIKU
+ img->pixmap = BBitmap_new (img->width, img->height, 0);
+
+ if (img->pixmap)
+ {
+ int bytes_per_line = (img->width + 7) / 8;
+
+ for (int y = 0; y < img->height; y++)
+ {
+ for (int x = 0; x < img->width; x++)
+ PUT_PIXEL (img->pixmap, x, y,
+ (data[x / 8] >> (x % 8)) & 1 ? fg : bg);
+ data += bytes_per_line;
+ }
+ }
#endif
}
@@ -4001,6 +4383,7 @@ xbm_load_image (struct frame *f, struct image *img, char *contents, char *end)
rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
&data, 0);
+
if (rc)
{
unsigned long foreground = img->face_foreground;
@@ -4119,8 +4502,8 @@ xbm_load (struct frame *f, struct image *img)
/* Get specified width, and height. */
if (!in_memory_file_p)
{
- img->width = XFIXNAT (fmt[XBM_WIDTH].value);
- img->height = XFIXNAT (fmt[XBM_HEIGHT].value);
+ img->width = XFIXNAT (fmt[XBM_DATA_WIDTH].value);
+ img->height = XFIXNAT (fmt[XBM_DATA_HEIGHT].value);
eassert (img->width > 0 && img->height > 0);
if (!check_image_size (f, img->width, img->height))
{
@@ -4633,8 +5016,10 @@ xpm_load (struct frame *f, struct image *img)
#ifndef HAVE_NTGUI
attrs.visual = FRAME_X_VISUAL (f);
attrs.colormap = FRAME_X_COLORMAP (f);
+ attrs.depth = FRAME_DISPLAY_INFO (f)->n_planes;
attrs.valuemask |= XpmVisual;
attrs.valuemask |= XpmColormap;
+ attrs.valuemask |= XpmDepth;
#endif /* HAVE_NTGUI */
#ifdef ALLOC_XPM_COLORS
@@ -5979,7 +6364,7 @@ image_edge_detection (struct frame *f, struct image *img,
}
-#if defined HAVE_X_WINDOWS || defined USE_CAIRO
+#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_HAIKU
static void
image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap,
int x, int y, unsigned int width, unsigned int height,
@@ -6013,9 +6398,11 @@ image_pixmap_draw_cross (struct frame *f, Emacs_Pixmap pixmap,
XDrawLine (dpy, pixmap, gc, x, y, x + width - 1, y + height - 1);
XDrawLine (dpy, pixmap, gc, x, y + height - 1, x + width - 1, y);
XFreeGC (dpy, gc);
-#endif /* HAVE_X_WINDOWS */
+#elif HAVE_HAIKU
+ be_draw_cross_on_pixmap (pixmap, x, y, width, height, color);
+#endif
}
-#endif /* HAVE_X_WINDOWS || USE_CAIRO */
+#endif /* HAVE_X_WINDOWS || USE_CAIRO || HAVE_HAIKU */
/* Transform image IMG on frame F so that it looks disabled. */
@@ -6057,25 +6444,23 @@ image_disable_image (struct frame *f, struct image *img)
{
#ifndef HAVE_NTGUI
#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
-#ifndef HAVE_HAIKU
-#ifndef USE_CAIRO
+#if !defined USE_CAIRO && !defined HAVE_HAIKU
#define CrossForeground(f) BLACK_PIX_DEFAULT (f)
#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
-#else /* USE_CAIRO */
+#else /* USE_CAIRO || HAVE_HAIKU */
#define CrossForeground(f) 0
#define MaskForeground(f) PIX_MASK_DRAW
-#endif /* USE_CAIRO */
+#endif /* USE_CAIRO || HAVE_HAIKU */
-#ifndef USE_CAIRO
+#if !defined USE_CAIRO && !defined HAVE_HAIKU
image_sync_to_pixmaps (f, img);
-#endif /* !USE_CAIRO */
+#endif /* !USE_CAIRO && !HAVE_HAIKU */
image_pixmap_draw_cross (f, img->pixmap, 0, 0, img->width, img->height,
CrossForeground (f));
if (img->mask)
image_pixmap_draw_cross (f, img->mask, 0, 0, img->width, img->height,
MaskForeground (f));
-#endif /* !HAVE_HAIKU */
#endif /* !HAVE_NS */
#else
HDC hdc, bmpdc;
@@ -8603,116 +8988,191 @@ static const int interlace_increment[] = {8, 8, 4, 2};
#define GIF_LOCAL_DESCRIPTOR_EXTENSION 249
+static void
+gif_destroy (struct anim_cache* cache)
+{
+ int gif_err;
+ gif_close (cache->handle, &gif_err);
+}
+
static bool
gif_load (struct frame *f, struct image *img)
{
int rc, width, height, x, y, i, j;
ColorMapObject *gif_color_map;
- GifFileType *gif;
+ GifFileType *gif = NULL;
gif_memory_source memsrc;
Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
- EMACS_INT idx;
+ unsigned long *pixmap = NULL;
+ EMACS_INT idx = -1;
int gif_err;
+ struct anim_cache* cache = NULL;
+ /* Which sub-image are we to display? */
+ Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
- if (NILP (specified_data))
+ idx = FIXNUMP (image_number) ? XFIXNAT (image_number) : 0;
+
+ if (!NILP (image_number))
{
- Lisp_Object file = image_find_image_file (specified_file);
- if (!STRINGP (file))
+ /* If this is an animated image, create a cache for it. */
+ cache = anim_get_animation_cache (img->spec);
+ /* We have an old cache entry, so use it. */
+ if (cache->handle)
{
- image_error ("Cannot find image file `%s'", specified_file);
- return false;
+ gif = cache->handle;
+ pixmap = cache->temp;
+ /* We're out of sync, so start from the beginning. */
+ if (cache->index != idx - 1)
+ cache->index = -1;
}
+ }
- Lisp_Object encoded_file = ENCODE_FILE (file);
+ /* If we don't have a cached entry, read the image. */
+ if (! gif)
+ {
+ if (NILP (specified_data))
+ {
+ Lisp_Object file = image_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file);
+ return false;
+ }
+
+ Lisp_Object encoded_file = ENCODE_FILE (file);
#ifdef WINDOWSNT
- encoded_file = ansi_encode_filename (encoded_file);
+ encoded_file = ansi_encode_filename (encoded_file);
#endif
- /* Open the GIF file. */
+ /* Open the GIF file. */
#if GIFLIB_MAJOR < 5
- gif = DGifOpenFileName (SSDATA (encoded_file));
+ gif = DGifOpenFileName (SSDATA (encoded_file));
#else
- gif = DGifOpenFileName (SSDATA (encoded_file), &gif_err);
+ gif = DGifOpenFileName (SSDATA (encoded_file), &gif_err);
#endif
- if (gif == NULL)
- {
+ if (gif == NULL)
+ {
#if HAVE_GIFERRORSTRING
- const char *errstr = GifErrorString (gif_err);
- if (errstr)
- image_error ("Cannot open `%s': %s", file, build_string (errstr));
- else
+ const char *errstr = GifErrorString (gif_err);
+ if (errstr)
+ image_error ("Cannot open `%s': %s", file,
+ build_string (errstr));
+ else
#endif
- image_error ("Cannot open `%s'", file);
- return false;
+ image_error ("Cannot open `%s'", file);
+ return false;
+ }
}
- }
- else
- {
- if (!STRINGP (specified_data))
+ else
{
- image_error ("Invalid image data `%s'", specified_data);
- return false;
- }
+ if (!STRINGP (specified_data))
+ {
+ image_error ("Invalid image data `%s'", specified_data);
+ return false;
+ }
- /* Read from memory! */
- current_gif_memory_src = &memsrc;
- memsrc.bytes = SDATA (specified_data);
- memsrc.len = SBYTES (specified_data);
- memsrc.index = 0;
+ /* Read from memory! */
+ current_gif_memory_src = &memsrc;
+ memsrc.bytes = SDATA (specified_data);
+ memsrc.len = SBYTES (specified_data);
+ memsrc.index = 0;
#if GIFLIB_MAJOR < 5
- gif = DGifOpen (&memsrc, gif_read_from_memory);
+ gif = DGifOpen (&memsrc, gif_read_from_memory);
#else
- gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
+ gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
+#endif
+ if (!gif)
+ {
+#if HAVE_GIFERRORSTRING
+ const char *errstr = GifErrorString (gif_err);
+ if (errstr)
+ image_error ("Cannot open memory source `%s': %s",
+ img->spec, build_string (errstr));
+ else
#endif
- if (!gif)
+ image_error ("Cannot open memory source `%s'", img->spec);
+ return false;
+ }
+ }
+
+ /* Before reading entire contents, check the declared image size. */
+ if (!check_image_size (f, gif->SWidth, gif->SHeight))
+ {
+ image_size_error ();
+ goto gif_error;
+ }
+
+ /* Read entire contents. */
+ rc = DGifSlurp (gif);
+ if (rc == GIF_ERROR || gif->ImageCount <= 0)
{
#if HAVE_GIFERRORSTRING
- const char *errstr = GifErrorString (gif_err);
+ const char *errstr = GifErrorString (gif->Error);
if (errstr)
- image_error ("Cannot open memory source `%s': %s",
- img->spec, build_string (errstr));
+ if (NILP (specified_data))
+ image_error ("Error reading `%s' (%s)", img->spec,
+ build_string (errstr));
+ else
+ image_error ("Error reading GIF data: %s",
+ build_string (errstr));
else
#endif
- image_error ("Cannot open memory source `%s'", img->spec);
- return false;
+ if (NILP (specified_data))
+ image_error ("Error reading `%s'", img->spec);
+ else
+ image_error ("Error reading GIF data");
+ goto gif_error;
}
- }
- /* Before reading entire contents, check the declared image size. */
- if (!check_image_size (f, gif->SWidth, gif->SHeight))
+ width = img->width = gif->SWidth;
+ height = img->height = gif->SHeight;
+
+ /* Check that the selected subimages fit. It's not clear whether
+ the GIF spec requires this, but Emacs can crash if they don't fit. */
+ for (j = 0; j < gif->ImageCount; ++j)
+ {
+ struct SavedImage *subimage = gif->SavedImages + j;
+ int subimg_width = subimage->ImageDesc.Width;
+ int subimg_height = subimage->ImageDesc.Height;
+ int subimg_top = subimage->ImageDesc.Top;
+ int subimg_left = subimage->ImageDesc.Left;
+ if (subimg_width < 0
+ || subimg_height < 0
+ || subimg_top < 0
+ || subimg_left < 0
+ || subimg_top + subimg_height > height
+ || subimg_left + subimg_width > width)
+ {
+ image_error ("Subimage does not fit in image");
+ goto gif_error;
+ }
+ }
+ }
+ else
{
- image_size_error ();
- goto gif_error;
+ /* Cached image; set data. */
+ width = img->width = gif->SWidth;
+ height = img->height = gif->SHeight;
}
- /* Read entire contents. */
- rc = DGifSlurp (gif);
- if (rc == GIF_ERROR || gif->ImageCount <= 0)
+ if (idx < 0 || idx >= gif->ImageCount)
{
- if (NILP (specified_data))
- image_error ("Error reading `%s'", img->spec);
- else
- image_error ("Error reading GIF data");
+ image_error ("Invalid image number `%s' in image `%s'",
+ make_fixnum (idx), img->spec);
goto gif_error;
}
- /* Which sub-image are we to display? */
- {
- Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
- idx = FIXNUMP (image_number) ? XFIXNAT (image_number) : 0;
- if (idx < 0 || idx >= gif->ImageCount)
- {
- image_error ("Invalid image number `%s' in image `%s'",
- image_number, img->spec);
- goto gif_error;
- }
- }
-
- width = img->width = gif->SWidth;
- height = img->height = gif->SHeight;
+ /* It's an animated image, so initialize the cache. */
+ if (cache && !cache->handle)
+ {
+ cache->handle = gif;
+ cache->destructor = (void (*)(void *)) &gif_destroy;
+ cache->width = width;
+ cache->height = height;
+ }
img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
@@ -8727,29 +9187,20 @@ gif_load (struct frame *f, struct image *img)
goto gif_error;
}
- /* Check that the selected subimages fit. It's not clear whether
- the GIF spec requires this, but Emacs can crash if they don't fit. */
- for (j = 0; j <= idx; ++j)
- {
- struct SavedImage *subimage = gif->SavedImages + j;
- int subimg_width = subimage->ImageDesc.Width;
- int subimg_height = subimage->ImageDesc.Height;
- int subimg_top = subimage->ImageDesc.Top;
- int subimg_left = subimage->ImageDesc.Left;
- if (! (subimg_width >= 0 && subimg_height >= 0
- && 0 <= subimg_top && subimg_top <= height - subimg_height
- && 0 <= subimg_left && subimg_left <= width - subimg_width))
- {
- image_error ("Subimage does not fit in image");
- goto gif_error;
- }
- }
-
/* Create the X image and pixmap. */
Emacs_Pix_Container ximg;
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
goto gif_error;
+ /* We construct the (possibly composited animated) image in this
+ buffer. */
+ if (!pixmap)
+ {
+ pixmap = xmalloc (width * height * sizeof (unsigned long));
+ if (cache)
+ cache->temp = pixmap;
+ }
+
/* Clear the part of the screen image not covered by the image.
Full animated GIF support requires more here (see the gif89 spec,
disposal methods). Let's simply assume that the part not covered
@@ -8764,29 +9215,25 @@ gif_load (struct frame *f, struct image *img)
frame_bg = lookup_rgb_color (f, color.red, color.green, color.blue);
}
#endif /* USE_CAIRO */
+
for (y = 0; y < img->corners[TOP_CORNER]; ++y)
for (x = 0; x < width; ++x)
- PUT_PIXEL (ximg, x, y, frame_bg);
+ *(pixmap + x + y * width) = frame_bg;
for (y = img->corners[BOT_CORNER]; y < height; ++y)
for (x = 0; x < width; ++x)
- PUT_PIXEL (ximg, x, y, frame_bg);
+ *(pixmap + x + y * width) = frame_bg;
for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
{
for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
- PUT_PIXEL (ximg, x, y, frame_bg);
+ *(pixmap + x + y * width) = frame_bg;
for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
- PUT_PIXEL (ximg, x, y, frame_bg);
+ *(pixmap + x + y * width) = frame_bg;
}
/* Read the GIF image into the X image. */
- /* FIXME: With the current implementation, loading an animated gif
- is quadratic in the number of animation frames, since each frame
- is a separate struct image. We must provide a way for a single
- gif_load call to construct and save all animation frames. */
-
init_color_table ();
unsigned long bgcolor UNINIT;
@@ -8801,7 +9248,18 @@ gif_load (struct frame *f, struct image *img)
#endif
}
- for (j = 0; j <= idx; ++j)
+ int start_frame = 0;
+
+ /* We have animation data in the cache. */
+ if (cache && cache->temp)
+ {
+ start_frame = cache->index + 1;
+ if (start_frame > idx)
+ start_frame = 0;
+ cache->index = idx;
+ }
+
+ for (j = start_frame; j <= idx; ++j)
{
/* We use a local variable `raster' here because RasterBits is a
char *, which invites problems with bytes >= 0x80. */
@@ -8852,6 +9310,14 @@ gif_load (struct frame *f, struct image *img)
if (disposal == DISPOSAL_UNSPECIFIED)
disposal = DISPOSE_DO_NOT;
+ /* This is not quite correct -- the specification is unclear,
+ but I think we're supposed to restore to the frame before the
+ previous frame? And we don't have that data at this point.
+ But DISPOSE_DO_NOT is less wrong than substituting the
+ background, so do that for now. */
+ if (disposal == DISPOSE_PREVIOUS)
+ disposal = DISPOSE_DO_NOT;
+
gif_color_map = subimage->ImageDesc.ColorMap;
if (!gif_color_map)
gif_color_map = gif->SColorMap;
@@ -8891,8 +9357,8 @@ gif_load (struct frame *f, struct image *img)
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != DISPOSE_DO_NOT)
{
- PUT_PIXEL (ximg, x + subimg_left, row + subimg_top,
- pixel_colors[c]);
+ *(pixmap + x + subimg_left + (y + subimg_top) * width) =
+ pixel_colors[c];
}
}
}
@@ -8905,13 +9371,19 @@ gif_load (struct frame *f, struct image *img)
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != DISPOSE_DO_NOT)
{
- PUT_PIXEL (ximg, x + subimg_left, y + subimg_top,
- pixel_colors[c]);
+ *(pixmap + x + subimg_left + (y + subimg_top) * width) =
+ pixel_colors[c];
}
}
}
}
+ /* We now have the complete image (possibly composed from a series
+ of animated frames) in pixmap. Put it into ximg. */
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ PUT_PIXEL (ximg, x, y, *(pixmap + x + y * width));
+
#ifdef COLOR_TABLE_SUPPORT
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
@@ -8940,11 +9412,11 @@ gif_load (struct frame *f, struct image *img)
}
}
img->lisp_data = list2 (Qextension_data, img->lisp_data);
- if (delay)
- img->lisp_data
- = Fcons (Qdelay,
- Fcons (make_float (delay / 100.0),
- img->lisp_data));
+ img->lisp_data
+ = Fcons (Qdelay,
+ /* Default GIF delay is 1/15th of a second. */
+ Fcons (make_float (delay? delay / 100.0: 1.0 / 15),
+ img->lisp_data));
}
if (gif->ImageCount > 1)
@@ -8952,17 +9424,22 @@ gif_load (struct frame *f, struct image *img)
Fcons (make_fixnum (gif->ImageCount),
img->lisp_data));
- if (gif_close (gif, &gif_err) == GIF_ERROR)
+ if (!cache)
{
+ if (pixmap)
+ xfree (pixmap);
+ if (gif_close (gif, &gif_err) == GIF_ERROR)
+ {
#if HAVE_GIFERRORSTRING
- char const *error_text = GifErrorString (gif_err);
+ char const *error_text = GifErrorString (gif_err);
- if (error_text)
- image_error ("Error closing `%s': %s",
- img->spec, build_string (error_text));
- else
+ if (error_text)
+ image_error ("Error closing `%s': %s",
+ img->spec, build_string (error_text));
+ else
#endif
- image_error ("Error closing `%s'", img->spec);
+ image_error ("Error closing `%s'", img->spec);
+ }
}
/* Maybe fill in the background field while we have ximg handy. */
@@ -8976,7 +9453,14 @@ gif_load (struct frame *f, struct image *img)
return true;
gif_error:
+ if (pixmap)
+ xfree (pixmap);
gif_close (gif, NULL);
+ if (cache)
+ {
+ cache->handle = NULL;
+ cache->temp = NULL;
+ }
return false;
}
@@ -8991,6 +9475,7 @@ gif_load (struct frame *f, struct image *img)
***********************************************************************/
#include "webp/decode.h"
+#include "webp/demux.h"
/* Indices of image specification fields in webp_format, below. */
@@ -9005,6 +9490,7 @@ enum webp_keyword_index
WEBP_ALGORITHM,
WEBP_HEURISTIC_MASK,
WEBP_MASK,
+ WEBP_INDEX,
WEBP_BACKGROUND,
WEBP_LAST
};
@@ -9023,6 +9509,7 @@ static const struct image_keyword webp_format[WEBP_LAST] =
{":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
@@ -9055,20 +9542,41 @@ DEF_DLL_FN (VP8StatusCode, WebPGetFeaturesInternal,
DEF_DLL_FN (uint8_t *, WebPDecodeRGBA, (const uint8_t *, size_t, int *, int *));
DEF_DLL_FN (uint8_t *, WebPDecodeRGB, (const uint8_t *, size_t, int *, int *));
DEF_DLL_FN (void, WebPFree, (void *));
+DEF_DLL_FN (uint32_t, WebPDemuxGetI, (const WebPDemuxer *, WebPFormatFeature));
+DEF_DLL_FN (WebPDemuxer *, WebPDemuxInternal,
+ (const WebPData *, int, WebPDemuxState *, int));
+DEF_DLL_FN (void, WebPDemuxDelete, (WebPDemuxer *));
+DEF_DLL_FN (int, WebPAnimDecoderGetNext,
+ (WebPAnimDecoder *, uint8_t **, int *));
+DEF_DLL_FN (WebPAnimDecoder *, WebPAnimDecoderNewInternal,
+ (const WebPData *, const WebPAnimDecoderOptions *, int));
+DEF_DLL_FN (int, WebPAnimDecoderOptionsInitInternal,
+ (WebPAnimDecoderOptions *, int));
+DEF_DLL_FN (int, WebPAnimDecoderHasMoreFrames, (const WebPAnimDecoder *));
+DEF_DLL_FN (void, WebPAnimDecoderDelete, (WebPAnimDecoder *));
static bool
init_webp_functions (void)
{
- HMODULE library;
+ HMODULE library1, library2;
- if (!(library = w32_delayed_load (Qwebp)))
+ if (!((library1 = w32_delayed_load (Qwebp))
+ && (library2 = w32_delayed_load (Qwebpdemux))))
return false;
- LOAD_DLL_FN (library, WebPGetInfo);
- LOAD_DLL_FN (library, WebPGetFeaturesInternal);
- LOAD_DLL_FN (library, WebPDecodeRGBA);
- LOAD_DLL_FN (library, WebPDecodeRGB);
- LOAD_DLL_FN (library, WebPFree);
+ LOAD_DLL_FN (library1, WebPGetInfo);
+ LOAD_DLL_FN (library1, WebPGetFeaturesInternal);
+ LOAD_DLL_FN (library1, WebPDecodeRGBA);
+ LOAD_DLL_FN (library1, WebPDecodeRGB);
+ LOAD_DLL_FN (library1, WebPFree);
+ LOAD_DLL_FN (library2, WebPDemuxGetI);
+ LOAD_DLL_FN (library2, WebPDemuxInternal);
+ LOAD_DLL_FN (library2, WebPDemuxDelete);
+ LOAD_DLL_FN (library2, WebPAnimDecoderGetNext);
+ LOAD_DLL_FN (library2, WebPAnimDecoderNewInternal);
+ LOAD_DLL_FN (library2, WebPAnimDecoderOptionsInitInternal);
+ LOAD_DLL_FN (library2, WebPAnimDecoderHasMoreFrames);
+ LOAD_DLL_FN (library2, WebPAnimDecoderDelete);
return true;
}
@@ -9077,6 +9585,14 @@ init_webp_functions (void)
#undef WebPDecodeRGBA
#undef WebPDecodeRGB
#undef WebPFree
+#undef WebPDemuxGetI
+#undef WebPDemux
+#undef WebPDemuxDelete
+#undef WebPAnimDecoderGetNext
+#undef WebPAnimDecoderNew
+#undef WebPAnimDecoderOptionsInit
+#undef WebPAnimDecoderHasMoreFrames
+#undef WebPAnimDecoderDelete
#define WebPGetInfo fn_WebPGetInfo
#define WebPGetFeatures(d,s,f) \
@@ -9084,9 +9600,26 @@ init_webp_functions (void)
#define WebPDecodeRGBA fn_WebPDecodeRGBA
#define WebPDecodeRGB fn_WebPDecodeRGB
#define WebPFree fn_WebPFree
+#define WebPDemuxGetI fn_WebPDemuxGetI
+#define WebPDemux(d) \
+ fn_WebPDemuxInternal(d,0,NULL,WEBP_DEMUX_ABI_VERSION)
+#define WebPDemuxDelete fn_WebPDemuxDelete
+#define WebPAnimDecoderGetNext fn_WebPAnimDecoderGetNext
+#define WebPAnimDecoderNew(d,o) \
+ fn_WebPAnimDecoderNewInternal(d,o,WEBP_DEMUX_ABI_VERSION)
+#define WebPAnimDecoderOptionsInit(o) \
+ fn_WebPAnimDecoderOptionsInitInternal(o,WEBP_DEMUX_ABI_VERSION)
+#define WebPAnimDecoderHasMoreFrames fn_WebPAnimDecoderHasMoreFrames
+#define WebPAnimDecoderDelete fn_WebPAnimDecoderDelete
#endif /* WINDOWSNT */
+static void
+webp_destroy (struct anim_cache* cache)
+{
+ WebPAnimDecoderDelete (cache->handle);
+}
+
/* Load WebP image IMG for use on frame F. Value is true if
successful. */
@@ -9096,6 +9629,9 @@ webp_load (struct frame *f, struct image *img)
ptrdiff_t size = 0;
uint8_t *contents;
Lisp_Object file = Qnil;
+ int frames = 0;
+ double delay = 0;
+ WebPAnimDecoder* anim = NULL;
/* Open the WebP file. */
Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
@@ -9139,6 +9675,9 @@ webp_load (struct frame *f, struct image *img)
goto webp_error1;
}
+ Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
+ ptrdiff_t idx = FIXNUMP (image_number) ? XFIXNAT (image_number) : 0;
+
/* Get WebP features. */
WebPBitstreamFeatures features;
VP8StatusCode result = WebPGetFeatures (contents, size, &features);
@@ -9162,19 +9701,90 @@ webp_load (struct frame *f, struct image *img)
goto webp_error1;
}
- /* Decode WebP data. */
- uint8_t *decoded;
+ uint8_t *decoded = NULL;
int width, height;
- if (features.has_alpha)
- /* Linear [r0, g0, b0, a0, r1, g1, b1, a1, ...] order. */
- decoded = WebPDecodeRGBA (contents, size, &width, &height);
+
+ if (features.has_animation)
+ {
+ /* Animated image. */
+ int timestamp;
+
+ struct anim_cache* cache = anim_get_animation_cache (img->spec);
+ /* Get the next frame from the animation cache. */
+ if (cache->handle && cache->index == idx - 1)
+ {
+ WebPAnimDecoderGetNext (cache->handle, &decoded, &timestamp);
+ delay = timestamp;
+ cache->index++;
+ anim = cache->handle;
+ width = cache->width;
+ height = cache->height;
+ frames = cache->frames;
+ }
+ else
+ {
+ /* Start a new cache entry. */
+ if (cache->handle)
+ WebPAnimDecoderDelete (cache->handle);
+
+ WebPData webp_data;
+ if (NILP (specified_data))
+ /* If we got the data from a file, then we don't need to
+ copy the data. */
+ webp_data.bytes = cache->temp = contents;
+ else
+ /* We got the data from a string, so copy it over so that
+ it doesn't get garbage-collected. */
+ {
+ webp_data.bytes = xmalloc (size);
+ memcpy ((void*) webp_data.bytes, contents, size);
+ }
+ /* In any case, we release the allocated memory when we
+ purge the anim cache. */
+ webp_data.size = size;
+
+ /* Get the width/height of the total image. */
+ WebPDemuxer* demux = WebPDemux (&webp_data);
+ cache->width = width = WebPDemuxGetI (demux, WEBP_FF_CANVAS_WIDTH);
+ cache->height = height = WebPDemuxGetI (demux,
+ WEBP_FF_CANVAS_HEIGHT);
+ cache->frames = frames = WebPDemuxGetI (demux, WEBP_FF_FRAME_COUNT);
+ cache->destructor = (void (*)(void *)) webp_destroy;
+ WebPDemuxDelete (demux);
+
+ WebPAnimDecoderOptions dec_options;
+ WebPAnimDecoderOptionsInit (&dec_options);
+ anim = WebPAnimDecoderNew (&webp_data, &dec_options);
+
+ cache->handle = anim;
+ cache->index = idx;
+
+ while (WebPAnimDecoderHasMoreFrames (anim)) {
+ WebPAnimDecoderGetNext (anim, &decoded, &timestamp);
+ /* Each frame has its own delay, but we don't really support
+ that. So just use the delay from the first frame. */
+ if (delay == 0)
+ delay = timestamp;
+ /* Stop when we get to the desired index. */
+ if (idx-- == 0)
+ break;
+ }
+ }
+ }
else
- /* Linear [r0, g0, b0, r1, g1, b1, ...] order. */
- decoded = WebPDecodeRGB (contents, size, &width, &height);
+ {
+ /* Non-animated image. */
+ if (features.has_alpha)
+ /* Linear [r0, g0, b0, a0, r1, g1, b1, a1, ...] order. */
+ decoded = WebPDecodeRGBA (contents, size, &width, &height);
+ else
+ /* Linear [r0, g0, b0, r1, g1, b1, ...] order. */
+ decoded = WebPDecodeRGB (contents, size, &width, &height);
+ }
if (!decoded)
{
- image_error ("Error when interpreting WebP image data");
+ image_error ("Error when decoding WebP image data");
goto webp_error1;
}
@@ -9193,7 +9803,8 @@ webp_load (struct frame *f, struct image *img)
/* Create an image and pixmap serving as mask if the WebP image
contains an alpha channel. */
if (features.has_alpha
- && !image_create_x_image_and_pixmap (f, img, width, height, 1, &mask_img, true))
+ && !image_create_x_image_and_pixmap (f, img, width, height, 1,
+ &mask_img, true))
{
image_destroy_x_image (ximg);
image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
@@ -9203,6 +9814,13 @@ webp_load (struct frame *f, struct image *img)
/* Fill the X image and mask from WebP data. */
init_color_table ();
+ img->corners[TOP_CORNER] = 0;
+ img->corners[LEFT_CORNER] = 0;
+ img->corners[BOT_CORNER]
+ = img->corners[TOP_CORNER] + height;
+ img->corners[RIGHT_CORNER]
+ = img->corners[LEFT_CORNER] + width;
+
uint8_t *p = decoded;
for (int y = 0; y < height; ++y)
{
@@ -9217,7 +9835,7 @@ webp_load (struct frame *f, struct image *img)
image. WebP allows up to 256 levels of partial transparency.
We handle this like with PNG (which see), using the frame's
background color to combine the image with. */
- if (features.has_alpha)
+ if (features.has_alpha || anim)
{
if (mask_img)
PUT_PIXEL (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
@@ -9248,14 +9866,24 @@ webp_load (struct frame *f, struct image *img)
img->width = width;
img->height = height;
+ /* Return animation data. */
+ img->lisp_data = Fcons (Qcount,
+ Fcons (make_fixnum (frames),
+ img->lisp_data));
+ img->lisp_data = Fcons (Qdelay,
+ Fcons (make_float (delay / 1000),
+ img->lisp_data));
+
/* Clean up. */
- WebPFree (decoded);
- if (NILP (specified_data))
+ if (!anim)
+ WebPFree (decoded);
+ if (NILP (specified_data) && !anim)
xfree (contents);
return true;
webp_error2:
- WebPFree (decoded);
+ if (!anim)
+ WebPFree (decoded);
webp_error1:
if (NILP (specified_data))
@@ -9422,7 +10050,7 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent])
(which is the first one, and then there's a number of images that
follow. If following images have non-transparent colors, these are
composed "on top" of the master image. So, in general, one has to
- compute ann the preceding images to be able to display a particular
+ compute all the preceding images to be able to display a particular
sub-image.
Computing all the preceding images is too slow, so we maintain a
@@ -10673,11 +11301,16 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
viewbox_height = dimension_data.height;
#endif
+#ifdef HAVE_NATIVE_TRANSFORMS
compute_image_size (viewbox_width, viewbox_height, img,
&width, &height);
width = scale_image_size (width, 1, FRAME_SCALE_FACTOR (f));
height = scale_image_size (height, 1, FRAME_SCALE_FACTOR (f));
+#else
+ width = viewbox_width;
+ height = viewbox_height;
+#endif
if (! check_image_size (f, width, height))
{
@@ -10878,7 +11511,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
#endif
/* FIXME: Use error->message so the user knows what is the actual
problem with the image. */
- image_error ("Error parsing SVG image `%s'", img->spec);
+ image_error ("Error parsing SVG image");
g_clear_error (&err);
return 0;
}
@@ -11020,7 +11653,7 @@ gs_load (struct frame *f, struct image *img)
block_input ();
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
img->width, img->height,
- DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+ FRAME_DISPLAY_INFO (f)->n_planes);
unblock_input ();
}
@@ -11093,7 +11726,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
/* On displays with a mutable colormap, figure out the colors
allocated for the image by looking at the pixels of an XImage for
img->pixmap. */
- if (x_mutable_colormap (FRAME_X_VISUAL (f)))
+ if (x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
{
XImage *ximg;
@@ -11196,10 +11829,7 @@ The list of capabilities can include one or more of the following:
|| defined (HAVE_HAIKU)
return list2 (Qscale, Qrotate90);
# elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER)
- int event_basep, error_basep;
-
- if (XRenderQueryExtension (FRAME_X_DISPLAY (f),
- &event_basep, &error_basep))
+ if (FRAME_DISPLAY_INFO (f)->xrender_supported_p)
return list2 (Qscale, Qrotate90);
# elif defined (HAVE_NTGUI)
return (w32_image_rotations_p ()
@@ -11365,6 +11995,7 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (QCtransform_smoothing, ":transform-smoothing");
DEFSYM (QCcolor_adjustment, ":color-adjustment");
DEFSYM (QCmask, ":mask");
+ DEFSYM (QCflip, ":flip");
/* Other symbols. */
DEFSYM (Qlaplace, "laplace");
@@ -11457,8 +12088,10 @@ non-numeric, there is no explicit limit on the size of images. */);
add_image_type (Qpng);
#endif
-#if defined (HAVE_WEBP)
+#if defined (HAVE_WEBP) || (defined (HAVE_NATIVE_IMAGE_API) \
+ && defined (HAVE_HAIKU))
DEFSYM (Qwebp, "webp");
+ DEFSYM (Qwebpdemux, "webpdemux");
add_image_type (Qwebp);
#endif
@@ -11490,6 +12123,12 @@ non-numeric, there is no explicit limit on the size of images. */);
#if HAVE_NATIVE_IMAGE_API
DEFSYM (Qnative_image, "native-image");
+
+# if defined HAVE_NTGUI || defined HAVE_HAIKU
+ DEFSYM (Qbmp, "bmp");
+ add_image_type (Qbmp);
+# endif
+
# ifdef HAVE_NTGUI
DEFSYM (Qgdiplus, "gdiplus");
DEFSYM (Qshlwapi, "shlwapi");
@@ -11512,6 +12151,11 @@ non-numeric, there is no explicit limit on the size of images. */);
defsubr (&Slookup_image);
#endif
+ DEFSYM (QCanimate_buffer, ":animate-buffer");
+ DEFSYM (QCanimate_tardiness, ":animate-tardiness");
+ DEFSYM (QCanimate_position, ":animate-position");
+ DEFSYM (QCanimate_multi_frame_data, ":animate-multi-frame-data");
+
defsubr (&Simage_transforms_p);
DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
diff --git a/src/indent.c b/src/indent.c
index 5c21cd8f99d..d4ef075f001 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -468,31 +468,40 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
{
Lisp_Object val, overlay;
- if (CONSP (val = get_char_property_and_overlay
- (make_fixnum (pos), Qdisplay, Qnil, &overlay))
- && EQ (Qspace, XCAR (val)))
- { /* FIXME: Use calc_pixel_width_or_height. */
- Lisp_Object plist = XCDR (val), prop;
+ if (!NILP (val = get_char_property_and_overlay (make_fixnum (pos), Qdisplay,
+ Qnil, &overlay)))
+ {
int width = -1;
- EMACS_INT align_to_max =
- (col < MOST_POSITIVE_FIXNUM - INT_MAX
- ? (EMACS_INT) INT_MAX + col
- : MOST_POSITIVE_FIXNUM);
-
- if ((prop = Fplist_get (plist, QCwidth),
- RANGED_FIXNUMP (0, prop, INT_MAX))
- || (prop = Fplist_get (plist, QCrelative_width),
- RANGED_FIXNUMP (0, prop, INT_MAX)))
- width = XFIXNUM (prop);
- else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop)
- && XFLOAT_DATA (prop) <= INT_MAX)
- width = (int)(XFLOAT_DATA (prop) + 0.5);
- else if ((prop = Fplist_get (plist, QCalign_to),
- RANGED_FIXNUMP (col, prop, align_to_max)))
- width = XFIXNUM (prop) - col;
- else if (FLOATP (prop) && col <= XFLOAT_DATA (prop)
- && (XFLOAT_DATA (prop) <= align_to_max))
- width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
+ Lisp_Object plist = Qnil;
+
+ /* Handle '(space ...)' display specs. */
+ if (CONSP (val) && EQ (Qspace, XCAR (val)))
+ { /* FIXME: Use calc_pixel_width_or_height. */
+ Lisp_Object prop;
+ EMACS_INT align_to_max =
+ (col < MOST_POSITIVE_FIXNUM - INT_MAX
+ ? (EMACS_INT) INT_MAX + col
+ : MOST_POSITIVE_FIXNUM);
+
+ plist = XCDR (val);
+ if ((prop = plist_get (plist, QCwidth),
+ RANGED_FIXNUMP (0, prop, INT_MAX))
+ || (prop = plist_get (plist, QCrelative_width),
+ RANGED_FIXNUMP (0, prop, INT_MAX)))
+ width = XFIXNUM (prop);
+ else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop)
+ && XFLOAT_DATA (prop) <= INT_MAX)
+ width = (int)(XFLOAT_DATA (prop) + 0.5);
+ else if ((prop = plist_get (plist, QCalign_to),
+ RANGED_FIXNUMP (col, prop, align_to_max)))
+ width = XFIXNUM (prop) - col;
+ else if (FLOATP (prop) && col <= XFLOAT_DATA (prop)
+ && (XFLOAT_DATA (prop) <= align_to_max))
+ width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
+ }
+ /* Handle 'display' strings. */
+ else if (STRINGP (val))
+ width = XFIXNUM (Fstring_width (val, Qnil, Qnil));
if (width >= 0)
{
@@ -504,7 +513,8 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
/* For :relative-width, we need to multiply by the column
width of the character at POS, if it is greater than 1. */
- if (!NILP (Fplist_get (plist, QCrelative_width))
+ if (!NILP (plist)
+ && !NILP (plist_get (plist, QCrelative_width))
&& !NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
int b, wd;
@@ -516,6 +526,7 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
return width;
}
}
+
return -1;
}
@@ -1193,7 +1204,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
/* Negative width means use all available text columns. */
if (width < 0)
{
- width = window_body_width (win, 0);
+ width = window_body_width (win, WINDOW_BODY_IN_CANONICAL_CHARS);
/* We must make room for continuation marks if we don't have fringes. */
#ifdef HAVE_WINDOW_SYSTEM
if (!FRAME_WINDOW_P (XFRAME (win->frame)))
@@ -1803,7 +1814,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */)
? window_internal_height (w)
: XFIXNUM (XCDR (topos))),
(NILP (topos)
- ? (window_body_width (w, 0)
+ ? (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
- (
#ifdef HAVE_WINDOW_SYSTEM
FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
@@ -1850,7 +1861,7 @@ vmotion (ptrdiff_t from, ptrdiff_t from_byte,
/* If the window contains this buffer, use it for getting text properties.
Otherwise use the current buffer as arg for doing that. */
- if (EQ (w->contents, Fcurrent_buffer ()))
+ if (BASE_EQ (w->contents, Fcurrent_buffer ()))
text_prop_object = window;
else
text_prop_object = Fcurrent_buffer ();
@@ -1968,7 +1979,7 @@ line_number_display_width (struct window *w, int *width, int *pixel_width)
struct text_pos startpos;
bool saved_restriction = false;
struct buffer *old_buf = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
SET_TEXT_POS_FROM_MARKER (startpos, w->start);
void *itdata = bidi_shelve_cache ();
@@ -2105,7 +2116,7 @@ whether or not it is currently displayed in some window. */)
struct window *w;
Lisp_Object lcols = Qnil;
void *itdata = NULL;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Allow LINES to be of the form (HPOS . VPOS) aka (COLUMNS . LINES). */
if (CONSP (lines))
@@ -2166,6 +2177,8 @@ whether or not it is currently displayed in some window. */)
line_number_display_width (w, &lnum_width, &lnum_pixel_width);
SET_TEXT_POS (pt, PT, PT_BYTE);
itdata = bidi_shelve_cache ();
+ record_unwind_protect_void (unwind_display_working_on_window);
+ display_working_on_window_p = true;
start_display (&it, w, pt);
it.lnum_width = lnum_width;
first_x = it.first_visible_x;
@@ -2198,7 +2211,10 @@ whether or not it is currently displayed in some window. */)
}
else
it_overshoot_count =
- !(it.method == GET_FROM_IMAGE || it.method == GET_FROM_STRETCH);
+ /* If image_id is negative, it's a fringe bitmap, which by
+ definition doesn't affect display in the text area. */
+ !((it.method == GET_FROM_IMAGE && it.image_id >= 0)
+ || it.method == GET_FROM_STRETCH);
if (start_x_given)
{
diff --git a/src/inotify.c b/src/inotify.c
index e92ad40abcc..16d20e7e925 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -217,7 +217,7 @@ add_watch (int wd, Lisp_Object filename,
/* Assign a watch ID that is not already in use, by looking
for a gap in the existing sorted list. */
for (; ! NILP (XCDR (tail)); tail = XCDR (tail), id++)
- if (!EQ (XCAR (XCAR (XCDR (tail))), make_fixnum (id)))
+ if (!BASE_EQ (XCAR (XCAR (XCDR (tail))), make_fixnum (id)))
break;
if (MOST_POSITIVE_FIXNUM < id)
emacs_abort ();
diff --git a/src/insdel.c b/src/insdel.c
index d9ba222b1d1..6f180ac5800 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -2134,7 +2134,7 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
Lisp_Object start, end;
Lisp_Object start_marker, end_marker;
Lisp_Object preserve_marker;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct rvoe_arg rvoe_arg;
start = make_fixnum (start_int);
@@ -2201,7 +2201,7 @@ signal_before_change (ptrdiff_t start_int, ptrdiff_t end_int,
void
signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct rvoe_arg rvoe_arg;
Lisp_Object tmp, save_insert_behind_hooks, save_insert_in_from_hooks;
@@ -2298,7 +2298,7 @@ DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
doc: /* This function is for use internally in the function `combine-after-change-calls'. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
ptrdiff_t beg, end, change;
ptrdiff_t begpos, endpos;
Lisp_Object tail;
diff --git a/src/intervals.c b/src/intervals.c
index ed374f16b53..85152c58a5d 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -121,7 +121,6 @@ copy_properties (INTERVAL source, INTERVAL target)
{
if (DEFAULT_INTERVAL_P (source) && DEFAULT_INTERVAL_P (target))
return;
- eassume (source && target);
COPY_INTERVAL_CACHE (source, target);
set_interval_plist (target, Fcopy_sequence (source->plist));
@@ -1738,11 +1737,11 @@ lookup_char_property (Lisp_Object plist, Lisp_Object prop, bool textprop)
{
tail = XCDR (tail);
for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail))
- fallback = Fplist_get (plist, XCAR (tail));
+ fallback = plist_get (plist, XCAR (tail));
}
if (textprop && NILP (fallback) && CONSP (Vdefault_text_properties))
- fallback = Fplist_get (Vdefault_text_properties, prop);
+ fallback = plist_get (Vdefault_text_properties, prop);
return fallback;
}
@@ -2180,7 +2179,7 @@ get_local_map (ptrdiff_t position, struct buffer *buffer, Lisp_Object type)
{
Lisp_Object prop, lispy_position, lispy_buffer;
ptrdiff_t old_begv, old_zv, old_begv_byte, old_zv_byte;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
position = clip_to_bounds (BUF_BEGV (buffer), position, BUF_ZV (buffer));
diff --git a/src/intervals.h b/src/intervals.h
index 484fca2e756..0ce581208e3 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -251,7 +251,7 @@ extern void traverse_intervals_noorder (INTERVAL,
void (*) (INTERVAL, void *), void *);
extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t)
ATTRIBUTE_RETURNS_NONNULL;
-extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t);
+extern INTERVAL split_interval_left (INTERVAL, ptrdiff_t) ATTRIBUTE_RETURNS_NONNULL;
extern INTERVAL find_interval (INTERVAL, ptrdiff_t);
extern INTERVAL next_interval (INTERVAL);
extern INTERVAL previous_interval (INTERVAL);
diff --git a/src/json.c b/src/json.c
index 21a6df67857..9a455f507b4 100644
--- a/src/json.c
+++ b/src/json.c
@@ -337,7 +337,7 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp,
const struct json_configuration *conf)
{
json_t *json;
- ptrdiff_t count;
+ specpdl_ref count;
if (VECTORP (lisp))
{
@@ -364,7 +364,7 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp,
for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
Lisp_Object key = HASH_KEY (h, i);
- if (!EQ (key, Qunbound))
+ if (!BASE_EQ (key, Qunbound))
{
CHECK_STRING (key);
Lisp_Object ekey = json_encode (key);
@@ -584,7 +584,7 @@ any JSON false values.
usage: (json-serialize OBJECT &rest ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
if (!json_initialized)
@@ -693,7 +693,7 @@ OBJECT.
usage: (json-insert OBJECT &rest ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
if (!json_initialized)
@@ -950,7 +950,7 @@ represent a JSON false value. It defaults to `:false'.
usage: (json-parse-string STRING &rest ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
if (!json_initialized)
@@ -975,7 +975,7 @@ usage: (json-parse-string STRING &rest ARGS) */)
json_error_t error;
json_t *object
- = json_loads (SSDATA (encoded), JSON_DECODE_ANY, &error);
+ = json_loads (SSDATA (encoded), JSON_DECODE_ANY | JSON_ALLOW_NUL, &error);
if (object == NULL)
json_parse_error (&error);
@@ -1047,7 +1047,7 @@ represent a JSON false value. It defaults to `:false'.
usage: (json-parse-buffer &rest args) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
if (!json_initialized)
@@ -1071,7 +1071,9 @@ usage: (json-parse-buffer &rest args) */)
json_error_t error;
json_t *object
= json_load_callback (json_read_buffer_callback, &data,
- JSON_DECODE_ANY | JSON_DISABLE_EOF_CHECK,
+ JSON_DECODE_ANY
+ | JSON_DISABLE_EOF_CHECK
+ | JSON_ALLOW_NUL,
&error);
if (object == NULL)
diff --git a/src/keyboard.c b/src/keyboard.c
index a9f3257282b..7c13ac96114 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -95,8 +95,6 @@ volatile int interrupt_input_blocked;
The maybe_quit function checks this. */
volatile bool pending_signals;
-enum { KBD_BUFFER_SIZE = 4096 };
-
KBOARD *initial_kboard;
KBOARD *current_kboard;
static KBOARD *all_kboards;
@@ -290,14 +288,14 @@ bool input_was_pending;
/* Circular buffer for pre-read keyboard input. */
-static union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE];
+union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE];
/* Pointer to next available character in kbd_buffer.
If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. */
-static union buffered_input_event *kbd_fetch_ptr;
+union buffered_input_event *kbd_fetch_ptr;
/* Pointer to next place to store character in kbd_buffer. */
-static union buffered_input_event *kbd_store_ptr;
+union buffered_input_event *kbd_store_ptr;
/* The above pair of variables forms a "queue empty" flag. When we
enqueue a non-hook event, we increment kbd_store_ptr. When we
@@ -336,6 +334,11 @@ static struct timespec timer_idleness_start_time;
static struct timespec timer_last_idleness_start_time;
+/* Predefined strings for core device names. */
+
+static Lisp_Object virtual_core_pointer_name;
+static Lisp_Object virtual_core_keyboard_name;
+
/* Global variable declarations. */
@@ -386,14 +389,6 @@ next_kbd_event (union buffered_input_event *ptr)
return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1;
}
-#ifdef HAVE_X11
-static union buffered_input_event *
-prev_kbd_event (union buffered_input_event *ptr)
-{
- return ptr == kbd_buffer ? kbd_buffer + KBD_BUFFER_SIZE - 1 : ptr - 1;
-}
-#endif
-
/* Like EVENT_START, but assume EVENT is an event.
This pacifies gcc -Wnull-dereference, which might otherwise
complain about earlier checks that EVENT is indeed an event. */
@@ -682,13 +677,15 @@ add_command_key (Lisp_Object key)
Lisp_Object
recursive_edit_1 (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
if (command_loop_level > 0)
{
specbind (Qstandard_output, Qt);
specbind (Qstandard_input, Qt);
+ specbind (Qsymbols_with_pos_enabled, Qnil);
+ specbind (Qprint_symbols_bare, Qnil);
}
#ifdef HAVE_WINDOW_SYSTEM
@@ -774,7 +771,7 @@ throwing to \\='exit:
This function is called by the editor initialization to begin editing. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object buffer;
/* If we enter while input is blocked, don't lock up here.
@@ -937,7 +934,7 @@ static Lisp_Object
cmd_error (Lisp_Object data)
{
Lisp_Object old_level, old_length;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object conditions;
char macroerror[sizeof "After..kbd macro iterations: "
+ INT_STRLEN_BOUND (EMACS_INT)];
@@ -1052,7 +1049,7 @@ Default value of `command-error-function'. */)
print_error_message (data, Qexternal_debugging_output,
SSDATA (context), signal);
Fterpri (Qexternal_debugging_output, Qnil);
- Fkill_emacs (make_fixnum (-1));
+ Fkill_emacs (make_fixnum (-1), Qnil);
}
else
{
@@ -1115,7 +1112,7 @@ command_loop (void)
/* End of file in -batch run causes exit here. */
if (noninteractive)
- Fkill_emacs (Qt);
+ Fkill_emacs (Qt, Qnil);
}
}
@@ -1230,7 +1227,7 @@ DEFUN ("internal--track-mouse", Finternal_track_mouse, Sinternal_track_mouse,
doc: /* Call BODYFUN with mouse movement events enabled. */)
(Lisp_Object bodyfun)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
record_unwind_protect (tracking_off, track_mouse);
@@ -1308,9 +1305,6 @@ command_loop_1 (void)
/* If there are warnings waiting, process them. */
if (!NILP (Vdelayed_warnings_list))
safe_run_hooks (Qdelayed_warnings_hook);
-
- if (!NILP (Vdeferred_action_list))
- safe_run_hooks (Qdeferred_action_function);
}
/* Do this after running Vpost_command_hook, for consistency. */
@@ -1324,7 +1318,7 @@ command_loop_1 (void)
Lisp_Object cmd;
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
/* Make sure the current window's buffer is selected. */
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
@@ -1348,12 +1342,12 @@ command_loop_1 (void)
if (minibuf_level
&& !NILP (echo_area_buffer[0])
- && EQ (minibuf_window, echo_area_window)
+ && BASE_EQ (minibuf_window, echo_area_window)
&& NUMBERP (Vminibuffer_message_timeout))
{
/* Bind inhibit-quit to t so that C-g gets read in
rather than quitting back to the minibuffer. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
sit_for (Vminibuffer_message_timeout, 0, 2);
@@ -1395,7 +1389,7 @@ command_loop_1 (void)
/* A filter may have run while we were reading the input. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
++num_input_keys;
@@ -1485,7 +1479,7 @@ command_loop_1 (void)
/* Here for a command that isn't executed directly. */
#ifdef HAVE_WINDOW_SYSTEM
- ptrdiff_t scount = SPECPDL_INDEX ();
+ specpdl_ref scount = SPECPDL_INDEX ();
if (display_hourglass_p
&& NILP (Vexecuting_kbd_macro))
@@ -1504,7 +1498,14 @@ command_loop_1 (void)
point_before_last_command_or_undo = PT;
buffer_before_last_command_or_undo = current_buffer;
+ /* Restart our counting of redisplay ticks before
+ executing the command, so that we don't blame the new
+ command for the sins of the previous one. */
+ update_redisplay_ticks (0, NULL);
+ display_working_on_window_p = false;
+
call1 (Qcommand_execute, Vthis_command);
+ display_working_on_window_p = false;
#ifdef HAVE_WINDOW_SYSTEM
/* Do not check display_hourglass_p here, because
@@ -1533,8 +1534,6 @@ command_loop_1 (void)
if (!NILP (Vdelayed_warnings_list))
safe_run_hooks (Qdelayed_warnings_hook);
- safe_run_hooks (Qdeferred_action_function);
-
kset_last_command (current_kboard, Vthis_command);
kset_real_last_command (current_kboard, Vreal_this_command);
if (!CONSP (last_command_event))
@@ -1570,9 +1569,15 @@ command_loop_1 (void)
call0 (Qdeactivate_mark);
else
{
+ Lisp_Object symval;
/* Even if not deactivating the mark, set PRIMARY if
`select-active-regions' is non-nil. */
- if (!NILP (Fwindow_system (Qnil))
+ if ((!NILP (Fwindow_system (Qnil))
+ || ((symval =
+ find_symbol_value (Qtty_select_active_regions),
+ (!EQ (symval, Qunbound) && !NILP (symval)))
+ && !NILP (Fterminal_parameter (Qnil,
+ Qxterm__set_selection))))
/* Even if mark_active is non-nil, the actual buffer
marker may not have been set yet (Bug#7044). */
&& XMARKER (BVAR (current_buffer, mark))->buffer
@@ -1601,23 +1606,33 @@ command_loop_1 (void)
if (current_buffer == prev_buffer
&& XBUFFER (XWINDOW (selected_window)->contents) == current_buffer
- && last_point_position != PT
- && NILP (Vdisable_point_adjustment)
- && NILP (Vglobal_disable_point_adjustment))
+ && last_point_position != PT)
{
- if (last_point_position > BEGV
- && last_point_position < ZV
- && (composition_adjust_point (last_point_position,
- last_point_position)
- != last_point_position))
- /* The last point was temporarily set within a grapheme
- cluster to prevent automatic composition. To recover
- the automatic composition, we must update the
- display. */
- windows_or_buffers_changed = 21;
- if (!already_adjusted)
- adjust_point_for_property (last_point_position,
- MODIFF != prev_modiff);
+ if (NILP (Vdisable_point_adjustment)
+ && NILP (Vglobal_disable_point_adjustment)
+ && !composition_break_at_point)
+ {
+ if (last_point_position > BEGV
+ && last_point_position < ZV
+ && (composition_adjust_point (last_point_position,
+ last_point_position)
+ != last_point_position))
+ /* The last point was temporarily set within a grapheme
+ cluster to prevent automatic composition. To recover
+ the automatic composition, we must update the
+ display. */
+ windows_or_buffers_changed = 21;
+ if (!already_adjusted)
+ adjust_point_for_property (last_point_position,
+ MODIFF != prev_modiff);
+ }
+ else if (PT > BEGV && PT < ZV
+ && (composition_adjust_point (last_point_position, PT)
+ != PT))
+ /* Now point is within a grapheme cluster. We must update
+ the display so that this cluster is de-composed on the
+ screen and the cursor is correctly placed at point. */
+ windows_or_buffers_changed = 39;
}
/* Install chars successfully executed in kbd macro. */
@@ -1631,7 +1646,7 @@ command_loop_1 (void)
Lisp_Object
read_menu_command (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* We don't want to echo the keystrokes while navigating the
menus. */
@@ -1643,7 +1658,7 @@ read_menu_command (void)
unbind_to (count, Qnil);
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (i == 0 || i == -1)
return Qt;
@@ -1876,7 +1891,7 @@ safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args)
void
safe_run_hooks (Lisp_Object hook)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), safe_run_hook_funcall);
@@ -1895,6 +1910,9 @@ int poll_suppress_count;
static struct atimer *poll_timer;
+/* The poll period that constructed this timer. */
+static Lisp_Object poll_timer_time;
+
#if defined CYGWIN || defined DOS_NT
/* Poll for input, so that we catch a C-g if it comes in. */
void
@@ -1936,17 +1954,18 @@ start_polling (void)
/* If poll timer doesn't exist, or we need one with
a different interval, start a new one. */
- if (poll_timer == NULL
- || poll_timer->interval.tv_sec != polling_period)
+ if (NUMBERP (Vpolling_period)
+ && (poll_timer == NULL
+ || NILP (Fequal (Vpolling_period, poll_timer_time))))
{
- time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
- struct timespec interval = make_timespec (period, 0);
+ struct timespec interval = dtotimespec (XFLOATINT (Vpolling_period));
if (poll_timer)
cancel_atimer (poll_timer);
poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
poll_for_input, NULL);
+ poll_timer_time = Vpolling_period;
}
/* Let the timer's callback function poll for input
@@ -2014,14 +2033,28 @@ void
bind_polling_period (int n)
{
#ifdef POLL_FOR_INPUT
- intmax_t new = polling_period;
+ if (FIXNUMP (Vpolling_period))
+ {
+ intmax_t new = XFIXNUM (Vpolling_period);
+
+ if (n > new)
+ new = n;
- if (n > new)
- new = n;
+ stop_other_atimers (poll_timer);
+ stop_polling ();
+ specbind (Qpolling_period, make_int (new));
+ }
+ else if (FLOATP (Vpolling_period))
+ {
+ double new = XFLOAT_DATA (Vpolling_period);
+
+ stop_other_atimers (poll_timer);
+ stop_polling ();
+ specbind (Qpolling_period, (n > new
+ ? make_int (n)
+ : Vpolling_period));
+ }
- stop_other_atimers (poll_timer);
- stop_polling ();
- specbind (Qpolling_period, make_int (new));
/* Start a new alarm with the new period. */
start_polling ();
#endif
@@ -2191,7 +2224,7 @@ read_event_from_main_queue (struct timespec *end_time,
return c;
/* Actually read a character, waiting if necessary. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2224,7 +2257,7 @@ read_event_from_main_queue (struct timespec *end_time,
/* Terminate Emacs in batch mode if at eof. */
if (noninteractive && FIXNUMP (c) && XFIXNUM (c) < 0)
- Fkill_emacs (make_fixnum (1));
+ Fkill_emacs (make_fixnum (1), Qnil);
if (FIXNUMP (c))
{
@@ -2393,7 +2426,6 @@ read_char (int commandflag, Lisp_Object map,
bool *used_mouse_menu, struct timespec *end_time)
{
Lisp_Object c;
- ptrdiff_t jmpcount;
sys_jmp_buf local_getcjmp;
sys_jmp_buf save_jump;
Lisp_Object tem, save;
@@ -2431,6 +2463,7 @@ read_char (int commandflag, Lisp_Object map,
else
reread = false;
+ Vlast_event_device = Qnil;
if (CONSP (Vunread_command_events))
{
@@ -2551,7 +2584,7 @@ read_char (int commandflag, Lisp_Object map,
&& (input_was_pending || !redisplay_dont_pause)))
{
input_was_pending = input_pending;
- if (help_echo_showing_p && !EQ (selected_window, minibuf_window))
+ if (help_echo_showing_p && !BASE_EQ (selected_window, minibuf_window))
redisplay_preserve_echo_area (5);
else
redisplay ();
@@ -2635,7 +2668,7 @@ read_char (int commandflag, Lisp_Object map,
around any call to sit_for or kbd_buffer_get_event;
it *must not* be in effect when we call redisplay. */
- jmpcount = SPECPDL_INDEX ();
+ specpdl_ref jmpcount = SPECPDL_INDEX ();
if (sys_setjmp (local_getcjmp))
{
/* Handle quits while reading the keyboard. */
@@ -2718,7 +2751,7 @@ read_char (int commandflag, Lisp_Object map,
{
Lisp_Object tem0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2795,7 +2828,7 @@ read_char (int commandflag, Lisp_Object map,
timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4);
timeout = delay_level * timeout / 4;
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2899,7 +2932,7 @@ read_char (int commandflag, Lisp_Object map,
goto exit;
}
- if (EQ (c, make_fixnum (-2)))
+ if (BASE_EQ (c, make_fixnum (-2)))
return c;
if (CONSP (c) && EQ (XCAR (c), Qt))
@@ -3078,7 +3111,7 @@ read_char (int commandflag, Lisp_Object map,
Lisp_Object keys;
ptrdiff_t key_count;
ptrdiff_t command_key_start;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Save the echo status. */
bool saved_immediate_echo = current_kboard->immediate_echo;
@@ -3203,7 +3236,7 @@ read_char (int commandflag, Lisp_Object map,
/* Process the help character specially if enabled. */
if (!NILP (Vhelp_form) && help_char_p (c))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
help_form_saved_window_configs
= Fcons (Fcurrent_window_configuration (Qnil),
@@ -3224,7 +3257,7 @@ read_char (int commandflag, Lisp_Object map,
unbind_to (count, Qnil);
redisplay ();
- if (EQ (c, make_fixnum (040)))
+ if (BASE_EQ (c, make_fixnum (040)))
{
cancel_echoing ();
do
@@ -3282,6 +3315,11 @@ help_char_p (Lisp_Object c)
static void
record_char (Lisp_Object c)
{
+ /* subr.el/read-passwd binds inhibit_record_char to avoid recording
+ passwords. */
+ if (!record_all_keys && inhibit_record_char)
+ return;
+
int recorded = 0;
if (CONSP (c) && (EQ (XCAR (c), Qhelp_echo) || EQ (XCAR (c), Qmouse_movement)))
@@ -3495,6 +3533,11 @@ readable_events (int flags)
return 1;
}
+#ifdef HAVE_X_WINDOWS
+ if (x_detect_pending_selection_requests ())
+ return 1;
+#endif
+
if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ())
return 1;
if (single_kboard)
@@ -3666,25 +3709,6 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
Vquit_flag = Vthrow_on_input;
}
-
-#ifdef HAVE_X11
-
-/* Put a selection input event back in the head of the event queue. */
-
-void
-kbd_buffer_unget_event (struct selection_input_event *event)
-{
- /* Don't let the very last slot in the buffer become full, */
- union buffered_input_event *kp = prev_kbd_event (kbd_fetch_ptr);
- if (kp != kbd_store_ptr)
- {
- kp->sie = *event;
- kbd_fetch_ptr = kp;
- }
-}
-
-#endif
-
/* Limit help event positions to this range, to avoid overflow problems. */
#define INPUT_EVENT_POS_MAX \
((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \
@@ -3709,7 +3733,7 @@ Time_to_position (Time encoded_pos)
{
if (encoded_pos <= INPUT_EVENT_POS_MAX)
return encoded_pos;
- Time encoded_pos_min = INPUT_EVENT_POS_MIN;
+ Time encoded_pos_min = position_to_Time (INPUT_EVENT_POS_MIN);
eassert (encoded_pos_min <= encoded_pos);
ptrdiff_t notpos = -1 - encoded_pos;
return -1 - notpos;
@@ -3731,6 +3755,7 @@ gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window,
Lisp_Object object, ptrdiff_t pos)
{
struct input_event event;
+ EVENT_INIT (event);
event.kind = HELP_EVENT;
event.frame_or_window = frame;
@@ -3748,6 +3773,7 @@ void
kbd_buffer_store_help_event (Lisp_Object frame, Lisp_Object help)
{
struct input_event event;
+ EVENT_INIT (event);
event.kind = HELP_EVENT;
event.frame_or_window = frame;
@@ -3806,6 +3832,26 @@ clear_event (struct input_event *event)
event->kind = NO_EVENT;
}
+static Lisp_Object
+kbd_buffer_get_event_1 (Lisp_Object arg)
+{
+ Lisp_Object coding_system = Fget_text_property (make_fixnum (0),
+ Qcoding, arg);
+
+ if (EQ (coding_system, Qt))
+ return arg;
+
+ return code_convert_string (arg, (!NILP (coding_system)
+ ? coding_system
+ : Vlocale_coding_system),
+ Qnil, 0, false, 0);
+}
+
+static Lisp_Object
+kbd_buffer_get_event_2 (Lisp_Object val)
+{
+ return Qnil;
+}
/* Read one event from the event buffer, waiting if necessary.
The value is a Lisp object representing the event.
@@ -3818,7 +3864,12 @@ kbd_buffer_get_event (KBOARD **kbp,
bool *used_mouse_menu,
struct timespec *end_time)
{
- Lisp_Object obj;
+ Lisp_Object obj, str;
+#ifdef HAVE_X_WINDOWS
+ bool had_pending_selection_requests;
+
+ had_pending_selection_requests = false;
+#endif
#ifdef subprocesses
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
@@ -3844,6 +3895,8 @@ kbd_buffer_get_event (KBOARD **kbp,
}
#endif /* !defined HAVE_DBUS && !defined USE_FILE_NOTIFY && !defined THREADS_ENABLED */
+ *kbp = current_kboard;
+
/* Wait until there is input available. */
for (;;)
{
@@ -3869,10 +3922,18 @@ kbd_buffer_get_event (KBOARD **kbp,
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
gobble_input ();
#endif
+
if (kbd_fetch_ptr != kbd_store_ptr)
break;
if (some_mouse_moved ())
break;
+#ifdef HAVE_X_WINDOWS
+ if (x_detect_pending_selection_requests ())
+ {
+ had_pending_selection_requests = true;
+ break;
+ }
+#endif
if (end_time)
{
struct timespec now = current_timespec ();
@@ -3909,6 +3970,16 @@ kbd_buffer_get_event (KBOARD **kbp,
gobble_input ();
}
+#ifdef HAVE_X_WINDOWS
+ /* Handle pending selection requests. This can happen if Emacs
+ enters a recursive edit inside a nested event loop (probably
+ because the debugger opened) or someone called
+ `read-char'. */
+
+ if (had_pending_selection_requests)
+ x_handle_pending_selection_requests ();
+#endif
+
if (CONSP (Vunread_command_events))
{
Lisp_Object first;
@@ -3936,24 +4007,56 @@ kbd_buffer_get_event (KBOARD **kbp,
We return nil for them. */
switch (event->kind)
{
+#ifndef HAVE_HAIKU
case SELECTION_REQUEST_EVENT:
case SELECTION_CLEAR_EVENT:
{
-#ifdef HAVE_X11
+#if defined HAVE_X11 || HAVE_PGTK
/* Remove it from the buffer before processing it,
since otherwise swallow_events will see it
and process it again. */
struct selection_input_event copy = event->sie;
kbd_fetch_ptr = next_kbd_event (event);
input_pending = readable_events (0);
+
+#ifdef HAVE_X11
x_handle_selection_event (&copy);
#else
+ pgtk_handle_selection_event (&copy);
+#endif
+#else
/* We're getting selection request events, but we don't have
a window system. */
emacs_abort ();
#endif
}
break;
+#else
+ case SELECTION_REQUEST_EVENT:
+ emacs_abort ();
+
+ case SELECTION_CLEAR_EVENT:
+ {
+ struct input_event copy = event->ie;
+
+ kbd_fetch_ptr = next_kbd_event (event);
+ input_pending = readable_events (0);
+ haiku_handle_selection_clear (&copy);
+ }
+ break;
+#endif
+
+ case MONITORS_CHANGED_EVENT:
+ {
+ kbd_fetch_ptr = next_kbd_event (event);
+ input_pending = readable_events (0);
+
+ CALLN (Frun_hook_with_args,
+ Qdisplay_monitors_changed_functions,
+ event->ie.arg);
+
+ break;
+ }
#ifdef HAVE_EXT_MENU_BAR
case MENU_BAR_ACTIVATE_EVENT:
@@ -4032,6 +4135,15 @@ kbd_buffer_get_event (KBOARD **kbp,
obj = make_lispy_switch_frame (frame);
internal_last_event_frame = frame;
+ if (EQ (event->ie.device, Qt))
+ Vlast_event_device = ((event->ie.kind == ASCII_KEYSTROKE_EVENT
+ || event->ie.kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ || event->ie.kind == NON_ASCII_KEYSTROKE_EVENT)
+ ? virtual_core_keyboard_name
+ : virtual_core_pointer_name);
+ else
+ Vlast_event_device = event->ie.device;
+
/* If we didn't decide to make a switch-frame event, go ahead
and build a real event from the queue entry. */
if (NILP (obj))
@@ -4087,10 +4199,55 @@ kbd_buffer_get_event (KBOARD **kbp,
XSETCAR (Fnthcdr (make_fixnum (3),
maybe_event->ie.arg),
make_float (fmod (pinch_angle, 360.0)));
+
+ if (!EQ (maybe_event->ie.device, Qt))
+ Vlast_event_device = maybe_event->ie.device;
+
maybe_event = next_kbd_event (event);
}
}
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ /* This string has to be decoded. */
+ && STRINGP (event->ie.arg))
+ {
+ str = internal_condition_case_1 (kbd_buffer_get_event_1,
+ event->ie.arg, Qt,
+ kbd_buffer_get_event_2);
+
+ /* Decoding the string failed, so use the original,
+ where at least ASCII text will work. */
+ if (NILP (str))
+ str = event->ie.arg;
+
+ if (!SCHARS (str))
+ {
+ kbd_fetch_ptr = next_kbd_event (event);
+ obj = Qnil;
+ break;
+ }
+
+ /* car is the index of the next character in the
+ string that will be sent and cdr is the string
+ itself. */
+ event->ie.arg = Fcons (make_fixnum (0), str);
+ }
+
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ && CONSP (event->ie.arg))
+ {
+ eassert (FIXNUMP (XCAR (event->ie.arg)));
+ eassert (STRINGP (XCDR (event->ie.arg)));
+ eassert (XFIXNUM (XCAR (event->ie.arg))
+ < SCHARS (XCDR (event->ie.arg)));
+
+ event->ie.code = XFIXNUM (Faref (XCDR (event->ie.arg),
+ XCAR (event->ie.arg)));
+
+ XSETCAR (event->ie.arg,
+ make_fixnum (XFIXNUM (XCAR (event->ie.arg)) + 1));
+ }
+
obj = make_lispy_event (&event->ie);
#ifdef HAVE_EXT_MENU_BAR
@@ -4113,9 +4270,15 @@ kbd_buffer_get_event (KBOARD **kbp,
*used_mouse_menu = true;
#endif
- /* Wipe out this event, to catch bugs. */
- clear_event (&event->ie);
- kbd_fetch_ptr = next_kbd_event (event);
+ if (event->kind != MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ || !CONSP (event->ie.arg)
+ || (XFIXNUM (XCAR (event->ie.arg))
+ >= SCHARS (XCDR (event->ie.arg))))
+ {
+ /* Wipe out this event, to catch bugs. */
+ clear_event (&event->ie);
+ kbd_fetch_ptr = next_kbd_event (event);
+ }
}
}
}
@@ -4123,12 +4286,13 @@ kbd_buffer_get_event (KBOARD **kbp,
/* Try generating a mouse motion event. */
else if (some_mouse_moved ())
{
- struct frame *f = some_mouse_moved ();
+ struct frame *f, *movement_frame = some_mouse_moved ();
Lisp_Object bar_window;
enum scroll_bar_part part;
Lisp_Object x, y;
Time t;
+ f = movement_frame;
*kbp = current_kboard;
/* Note that this uses F to determine which terminal to look at.
If there is no valid info, it does not store anything
@@ -4163,7 +4327,16 @@ kbd_buffer_get_event (KBOARD **kbp,
return a mouse-motion event. */
if (!NILP (x) && NILP (obj))
obj = make_lispy_movement (f, bar_window, part, x, y, t);
+
+ if (!NILP (obj))
+ Vlast_event_device = (STRINGP (movement_frame->last_mouse_device)
+ ? movement_frame->last_mouse_device
+ : virtual_core_pointer_name);
}
+#ifdef HAVE_X_WINDOWS
+ else if (had_pending_selection_requests)
+ obj = Qnil;
+#endif
else
/* We were promised by the above while loop that there was
something for us to read! */
@@ -4182,14 +4355,24 @@ kbd_buffer_get_event (KBOARD **kbp,
static void
process_special_events (void)
{
- for (union buffered_input_event *event = kbd_fetch_ptr;
- event != kbd_store_ptr; event = next_kbd_event (event))
+ union buffered_input_event *event;
+#if defined HAVE_X11 || defined HAVE_PGTK || defined HAVE_HAIKU
+#ifndef HAVE_HAIKU
+ struct selection_input_event copy;
+#else
+ struct input_event copy;
+#endif
+ int moved_events;
+#endif
+
+ for (event = kbd_fetch_ptr; event != kbd_store_ptr;
+ event = next_kbd_event (event))
{
/* If we find a stored X selection request, handle it now. */
if (event->kind == SELECTION_REQUEST_EVENT
|| event->kind == SELECTION_CLEAR_EVENT)
{
-#ifdef HAVE_X11
+#if defined HAVE_X11 || defined HAVE_PGTK
/* Remove the event from the fifo buffer before processing;
otherwise swallow_events called recursively could see it
@@ -4197,8 +4380,7 @@ process_special_events (void)
between kbd_fetch_ptr and EVENT one slot to the right,
cyclically. */
- struct selection_input_event copy = event->sie;
- int moved_events;
+ copy = event->sie;
if (event < kbd_fetch_ptr)
{
@@ -4214,8 +4396,34 @@ process_special_events (void)
moved_events * sizeof *kbd_fetch_ptr);
kbd_fetch_ptr = next_kbd_event (kbd_fetch_ptr);
input_pending = readable_events (0);
+
+#ifdef HAVE_X11
x_handle_selection_event (&copy);
#else
+ pgtk_handle_selection_event (&copy);
+#endif
+#elif defined HAVE_HAIKU
+ if (event->ie.kind != SELECTION_CLEAR_EVENT)
+ emacs_abort ();
+
+ copy = event->ie;
+
+ if (event < kbd_fetch_ptr)
+ {
+ memmove (kbd_buffer + 1, kbd_buffer,
+ (event - kbd_buffer) * sizeof *kbd_buffer);
+ kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
+ moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
+ }
+ else
+ moved_events = event - kbd_fetch_ptr;
+
+ memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
+ moved_events * sizeof *kbd_fetch_ptr);
+ kbd_fetch_ptr = next_kbd_event (kbd_fetch_ptr);
+ input_pending = readable_events (0);
+ haiku_handle_selection_clear (&copy);
+#else
/* We're getting selection request events, but we don't have
a window system. */
emacs_abort ();
@@ -4419,7 +4627,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
if (NILP (AREF (chosen_timer, 0)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
@@ -4473,6 +4681,8 @@ timer_check (void)
Lisp_Object tem = Vinhibit_quit;
Vinhibit_quit = Qt;
+ block_input ();
+ turn_on_atimers (false);
/* We use copies of the timers' lists to allow a timer to add itself
again, without locking up Emacs if the newly added timer is
@@ -4486,6 +4696,8 @@ timer_check (void)
else
idle_timers = Qnil;
+ turn_on_atimers (true);
+ unblock_input ();
Vinhibit_quit = tem;
do
@@ -5149,17 +5361,19 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
Lisp_Object window_or_frame = f
? window_from_coordinates (f, mx, my, &part, true, true)
: Qnil;
+#ifdef HAVE_WINDOW_SYSTEM
+ bool tool_bar_p = false;
+ bool menu_bar_p = false;
/* Report mouse events on the tab bar and (on GUI frames) on the
tool bar. */
-#ifdef HAVE_WINDOW_SYSTEM
- if ((WINDOWP (f->tab_bar_window)
- && EQ (window_or_frame, f->tab_bar_window))
+ if (f && ((WINDOWP (f->tab_bar_window)
+ && EQ (window_or_frame, f->tab_bar_window))
#ifndef HAVE_EXT_TOOL_BAR
- || (WINDOWP (f->tool_bar_window)
- && EQ (window_or_frame, f->tool_bar_window))
+ || (WINDOWP (f->tool_bar_window)
+ && EQ (window_or_frame, f->tool_bar_window))
#endif
- )
+ ))
{
/* While 'track-mouse' is neither nil nor t, do not report this
event as something that happened on the tool or tab bar since
@@ -5182,6 +5396,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
coordinates. FIXME! */
window_or_frame = Qnil;
}
+
+ if (f && FRAME_TERMINAL (f)->toolkit_position_hook)
+ {
+ FRAME_TERMINAL (f)->toolkit_position_hook (f, mx, my, &menu_bar_p,
+ &tool_bar_p);
+
+ if (NILP (track_mouse) || EQ (track_mouse, Qt))
+ {
+ if (menu_bar_p)
+ posn = Qmenu_bar;
+ else if (tool_bar_p)
+ posn = Qtool_bar;
+ }
+ }
#endif
if (f
&& !FRAME_WINDOW_P (f)
@@ -5367,7 +5595,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
if (IMAGEP (object))
{
Lisp_Object image_map, hotspot;
- if ((image_map = Fplist_get (XCDR (object), QCmap),
+ if ((image_map = plist_get (XCDR (object), QCmap),
!NILP (image_map))
&& (hotspot = find_hot_spot (image_map, dx, dy),
CONSP (hotspot))
@@ -5410,9 +5638,16 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
}
#endif
}
-
else
- window_or_frame = Qnil;
+ {
+ if (EQ (track_mouse, Qdrag_source))
+ {
+ xret = mx;
+ yret = my;
+ }
+
+ window_or_frame = Qnil;
+ }
return Fcons (window_or_frame,
Fcons (posn,
@@ -7033,7 +7268,10 @@ lucid_event_type_list_p (Lisp_Object object)
If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal
events (FOCUS_IN_EVENT).
If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse
- movements and toolkit scroll bar thumb drags. */
+ movements and toolkit scroll bar thumb drags.
+
+ On X, this also returns if the selection event chain is full, since
+ that's also "keyboard input". */
static bool
get_input_pending (int flags)
@@ -7832,7 +8070,7 @@ eval_dyn (Lisp_Object form)
Lisp_Object
menu_item_eval_property (Lisp_Object sexpr)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
@@ -9282,7 +9520,7 @@ read_char_minibuf_menu_prompt (int commandflag,
if (!FIXNUMP (obj) || XFIXNUM (obj) == -2
|| (! EQ (obj, menu_prompt_more_char)
&& (!FIXNUMP (menu_prompt_more_char)
- || ! EQ (obj, make_fixnum (Ctl (XFIXNUM (menu_prompt_more_char)))))))
+ || ! BASE_EQ (obj, make_fixnum (Ctl (XFIXNUM (menu_prompt_more_char)))))))
{
if (!NILP (KVAR (current_kboard, defining_kbd_macro)))
store_kbd_macro_char (obj);
@@ -9499,7 +9737,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
bool dont_downcase_last, bool can_return_switch_frame,
bool fix_current_buffer, bool prevent_redisplay)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* How many keys there are in the current key sequence. */
int t;
@@ -9856,7 +10094,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
if (fix_current_buffer)
{
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (XBUFFER (XWINDOW (selected_window)->contents)
!= current_buffer)
Fset_buffer (XWINDOW (selected_window)->contents);
@@ -9980,7 +10218,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
record_unwind_current_buffer ();
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
set_buffer_internal (XBUFFER (XWINDOW (window)->contents));
goto replay_sequence;
}
@@ -10435,7 +10673,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
Lisp_Object can_return_switch_frame,
Lisp_Object cmd_loop, bool allow_string)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (!NILP (prompt))
CHECK_STRING (prompt);
@@ -10903,7 +11141,7 @@ Some operating systems cannot stop the Emacs process and resume it later.
On such systems, Emacs starts a subshell instead of suspending. */)
(Lisp_Object stuffstring)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int old_height, old_width;
int width, height;
@@ -11210,7 +11448,7 @@ quit_throw_to_read_char (bool from_signal)
/* When not called from a signal handler it is safe to call
Lisp. */
if (!from_signal && EQ (Vquit_flag, Qkill_emacs))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
/* Prevent another signal from doing this before we finish. */
clear_waiting_for_input ();
@@ -11221,7 +11459,7 @@ quit_throw_to_read_char (bool from_signal)
if (FRAMEP (internal_last_event_frame)
&& !EQ (internal_last_event_frame, selected_frame))
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
- 0, 0, Qnil);
+ 0, Qnil);
sys_longjmp (getcjmp, 1);
}
@@ -11649,6 +11887,10 @@ init_keyboard (void)
interrupt_input_blocked = 0;
pending_signals = false;
+ virtual_core_pointer_name = build_string ("Virtual core pointer");
+ virtual_core_keyboard_name = build_string ("Virtual core keyboard");
+ Vlast_event_device = Qnil;
+
/* This means that command_loop_1 won't try to select anything the first
time through. */
internal_last_event_frame = Qnil;
@@ -11842,7 +12084,6 @@ syms_of_keyboard (void)
DEFSYM (Qundo_auto__undoably_changed_buffers,
"undo-auto--undoably-changed-buffers");
- DEFSYM (Qdeferred_action_function, "deferred-action-function");
DEFSYM (Qdelayed_warnings_hook, "delayed-warnings-hook");
DEFSYM (Qfunction_key, "function-key");
@@ -11943,6 +12184,8 @@ syms_of_keyboard (void)
DEFSYM (Qpolling_period, "polling-period");
DEFSYM (Qgui_set_selection, "gui-set-selection");
+ DEFSYM (Qxterm__set_selection, "xterm--set-selection");
+ DEFSYM (Qtty_select_active_regions, "tty-select-active-regions");
/* The primary selection. */
DEFSYM (QPRIMARY, "PRIMARY");
@@ -12064,6 +12307,17 @@ syms_of_keyboard (void)
help_form_saved_window_configs = Qnil;
staticpro (&help_form_saved_window_configs);
+#ifdef POLL_FOR_INPUT
+ poll_timer_time = Qnil;
+ staticpro (&poll_timer_time);
+#endif
+
+ virtual_core_pointer_name = Qnil;
+ staticpro (&virtual_core_pointer_name);
+
+ virtual_core_keyboard_name = Qnil;
+ staticpro (&virtual_core_keyboard_name);
+
defsubr (&Scurrent_idle_time);
defsubr (&Sevent_symbol_parse_modifiers);
defsubr (&Sevent_convert_list);
@@ -12221,18 +12475,21 @@ The value may be integer or floating point.
If the value is zero, don't echo at all. */);
Vecho_keystrokes = make_fixnum (1);
- DEFVAR_INT ("polling-period", polling_period,
+ DEFVAR_LISP ("polling-period", Vpolling_period,
doc: /* Interval between polling for input during Lisp execution.
The reason for polling is to make C-g work to stop a running program.
Polling is needed only when using X windows and SIGIO does not work.
Polling is automatically disabled in all other cases. */);
- polling_period = 2;
+ Vpolling_period = make_float (2.0);
DEFVAR_LISP ("double-click-time", Vdouble_click_time,
doc: /* Maximum time between mouse clicks to make a double-click.
Measured in milliseconds. The value nil means disable double-click
recognition; t means double-clicks have no time limit and are detected
-by position only. */);
+by position only.
+
+In Lisp, you might want to use `mouse-double-click-time' instead of
+reading the value of this variable directly. */);
Vdouble_click_time = make_fixnum (500);
DEFVAR_INT ("double-click-fuzz", double_click_fuzz,
@@ -12262,6 +12519,17 @@ This does not include events generated by keyboard macros. */);
If the last event came from a keyboard macro, this is set to `macro'. */);
Vlast_event_frame = Qnil;
+ DEFVAR_LISP ("last-event-device", Vlast_event_device,
+ doc: /* The name of the input device of the most recently read event.
+When the input extension is being used on X, this is the name of the X
+Input Extension device from which the last event was generated as a
+string. Otherwise, this is "Virtual core keyboard" for keyboard input
+events, and "Virtual core pointer" for other events.
+
+It is nil if the last event did not come from an input device (i.e. it
+came from `unread-command-events' instead). */);
+ Vlast_event_device = Qnil;
+
/* This variable is set up in sysdep.c. */
DEFVAR_LISP ("tty-erase-char", Vtty_erase_char,
doc: /* The ERASE character as set by the user with stty. */);
@@ -12384,12 +12652,26 @@ See also `pre-command-hook'. */);
DEFSYM (Qtouchscreen_end, "touchscreen-end");
DEFSYM (Qtouchscreen_update, "touchscreen-update");
DEFSYM (Qpinch, "pinch");
+ DEFSYM (Qdisplay_monitors_changed_functions,
+ "display-monitors-changed-functions");
+
+ DEFSYM (Qcoding, "coding");
+
Fset (Qecho_area_clear_hook, Qnil);
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,
doc: /* Non-nil means menu bar, specified Lucid style, needs to be recomputed. */);
Vlucid_menu_bar_dirty_flag = Qnil;
+#ifdef USE_LUCID
+ DEFVAR_BOOL ("lucid--menu-grab-keyboard",
+ lucid__menu_grab_keyboard,
+ doc: /* If non-nil, grab keyboard during menu operations.
+This is only relevant when using the Lucid X toolkit. It can be
+convenient to disable this for debugging purposes. */);
+ lucid__menu_grab_keyboard = true;
+#endif
+
DEFVAR_LISP ("menu-bar-final-items", Vmenu_bar_final_items,
doc: /* List of menu bar items to move to the end of the menu bar.
The elements of the list are event types that may have menu bar
@@ -12441,12 +12723,15 @@ and the minor mode maps regardless of `overriding-local-map'. */);
doc: /* Non-nil means generate motion events for mouse motion.
The special values `dragging' and `dropping' assert that the mouse
cursor retains its appearance during mouse motion. Any non-nil value
-but `dropping' asserts that motion events always relate to the frame
-where the mouse movement started. The value `dropping' asserts
-that motion events relate to the frame where the mouse cursor is seen
-when generating the event. If there's no such frame, such motion
-events relate to the frame where the mouse movement started. */);
-
+but `dropping' or `drag-source' asserts that motion events always
+relate to the frame where the mouse movement started. The value
+`dropping' asserts that motion events relate to the frame where the
+mouse cursor is seen when generating the event. If there's no such
+frame, such motion events relate to the frame where the mouse movement
+started. The value `drag-source' is like `dropping', but the
+`posn-window' will be nil in mouse position lists inside mouse
+movement events if there is no frame directly visible underneath the
+mouse pointer. */);
DEFVAR_KBOARD ("system-key-alist", Vsystem_key_alist,
doc: /* Alist of system-specific X windows key symbols.
Each element should have the form (N . SYMBOL) where N is the
@@ -12516,17 +12801,6 @@ This keymap works like `input-decode-map', but comes after `function-key-map'.
Another difference is that it is global rather than terminal-local. */);
Vkey_translation_map = Fmake_sparse_keymap (Qnil);
- DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list,
- doc: /* List of deferred actions to be performed at a later time.
-The precise format isn't relevant here; we just check whether it is nil. */);
- Vdeferred_action_list = Qnil;
-
- DEFVAR_LISP ("deferred-action-function", Vdeferred_action_function,
- doc: /* Function to call to handle deferred actions, after each command.
-This function is called with no arguments after each command
-whenever `deferred-action-list' is non-nil. */);
- Vdeferred_action_function = Qnil;
-
DEFVAR_LISP ("delayed-warnings-list", Vdelayed_warnings_list,
doc: /* List of warnings to be displayed after this command.
Each element must be a list (TYPE MESSAGE [LEVEL [BUFFER-NAME]]),
@@ -12618,6 +12892,14 @@ Called with three arguments:
- the context (a string which normally goes at the start of the message),
- the Lisp function within which the error was signaled.
+For instance, to make error messages stand out more in the echo area,
+you could say something like:
+
+ (setq command-error-function
+ (lambda (data _ _)
+ (message "%s" (propertize (error-message-string data)
+ \\='face \\='error))))
+
Also see `set-message-function' (which controls how non-error messages
are displayed). */);
Vcommand_error_function = intern ("command-error-default-function");
@@ -12632,11 +12914,12 @@ and tool-bar buttons. */);
DEFVAR_LISP ("select-active-regions",
Vselect_active_regions,
- doc: /* If non-nil, an active region automatically sets the primary selection.
-If the value is `only', only temporarily active regions (usually made
-by mouse-dragging or shift-selection) set the window selection.
+ doc: /* If non-nil, any active region automatically sets the primary selection.
+This variable only has an effect when Transient Mark mode is enabled.
-This takes effect only when Transient Mark mode is enabled. */);
+If the value is `only', only temporarily active regions (usually made
+by mouse-dragging or shift-selection) set the window system's primary
+selection. */);
Vselect_active_regions = Qt;
DEFVAR_LISP ("saved-region-selection",
@@ -12721,6 +13004,30 @@ Otherwise, a wheel event will be sent every time the mouse wheel is
moved. */);
mwheel_coalesce_scroll_events = true;
+ DEFVAR_LISP ("display-monitors-changed-functions", Vdisplay_monitors_changed_functions,
+ doc: /* Abnormal hook run when the monitor configuration changes.
+This can happen if a monitor is rotated, moved, plugged in or removed
+from a multi-monitor setup, if the primary monitor changes, or if the
+resolution of a monitor changes. The hook should accept a single
+argument, which is the terminal on which the monitor configuration
+changed. */);
+ Vdisplay_monitors_changed_functions = Qnil;
+
+ DEFVAR_BOOL ("inhibit--record-char",
+ inhibit_record_char,
+ doc: /* If non-nil, don't record input events.
+This inhibits recording input events for the purposes of keyboard
+macros, dribble file, and `recent-keys'.
+Internal use only. */);
+ inhibit_record_char = false;
+
+ DEFVAR_BOOL ("record-all-keys", record_all_keys,
+ doc: /* Non-nil means record all keys you type.
+When nil, the default, characters typed as part of passwords are
+not recorded. The non-nil value countermands `inhibit--record-char',
+which see. */);
+ record_all_keys = false;
+
pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
}
@@ -12748,7 +13055,6 @@ syms_of_keyboard_for_pdumper (void)
PDUMPER_RESET (num_input_keys, 0);
PDUMPER_RESET (num_nonmacro_input_events, 0);
PDUMPER_RESET_LV (Vlast_event_frame, Qnil);
- PDUMPER_RESET_LV (Vdeferred_action_list, Qnil);
PDUMPER_RESET_LV (Vdelayed_warnings_list, Qnil);
/* Create the initial keyboard. Qt means 'unset'. */
@@ -12870,12 +13176,21 @@ mark_kboards (void)
{
/* These two special event types have no Lisp_Objects to mark. */
if (event->kind != SELECTION_REQUEST_EVENT
- && event->kind != SELECTION_CLEAR_EVENT)
+#ifndef HAVE_HAIKU
+ && event->kind != SELECTION_CLEAR_EVENT
+#endif
+ )
{
mark_object (event->ie.x);
mark_object (event->ie.y);
mark_object (event->ie.frame_or_window);
mark_object (event->ie.arg);
+
+ /* This should never be allocated for a single event, but
+ mark it anyway in the situation where the list of devices
+ changed but an event with an old device is still present
+ in the queue. */
+ mark_object (event->ie.device);
}
}
}
diff --git a/src/keyboard.h b/src/keyboard.h
index 167b7d79e8f..507d80c2975 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -27,6 +27,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
# include "xterm.h" /* for struct selection_input_event */
#endif
+#ifdef HAVE_PGTK
+#include "pgtkterm.h" /* for struct selection_input_event */
+#endif
+
INLINE_HEADER_BEGIN
/* Most code should use this macro to access Lisp fields in struct kboard. */
@@ -226,7 +230,7 @@ union buffered_input_event
{
ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH;
struct input_event ie;
-#ifdef HAVE_X11
+#if defined HAVE_X11 || defined HAVE_PGTK
struct selection_input_event sie;
#endif
};
@@ -358,6 +362,11 @@ enum menu_item_idx
MENU_ITEMS_ITEM_LENGTH
};
+enum
+ {
+ KBD_BUFFER_SIZE = 4096
+ };
+
extern void unuse_menu_items (void);
/* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU
@@ -419,6 +428,10 @@ extern void unuse_menu_items (void);
happens. */
extern struct timespec *input_available_clear_time;
+extern union buffered_input_event kbd_buffer[KBD_BUFFER_SIZE];
+extern union buffered_input_event *kbd_fetch_ptr;
+extern union buffered_input_event *kbd_store_ptr;
+
extern bool ignore_mouse_drag_p;
extern Lisp_Object parse_modifiers (Lisp_Object);
@@ -472,9 +485,6 @@ kbd_buffer_store_event_hold (struct input_event *event,
kbd_buffer_store_buffered_event ((union buffered_input_event *) event,
hold_quit);
}
-#ifdef HAVE_X11
-extern void kbd_buffer_unget_event (struct selection_input_event *);
-#endif
extern void poll_for_input_1 (void);
extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object);
@@ -486,8 +496,6 @@ extern bool kbd_buffer_events_waiting (void);
extern void add_user_signal (int, const char *);
extern int tty_read_avail_input (struct terminal *, struct input_event *);
-extern bool volatile pending_signals;
-extern void process_pending_signals (void);
extern struct timespec timer_check (void);
extern void mark_kboards (void);
diff --git a/src/keymap.c b/src/keymap.c
index ed69b1c4277..506b755e5da 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -395,7 +395,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx,
if (noinherit || NILP (retval))
/* If NOINHERIT, stop here, the rest is inherited. */
break;
- else if (!EQ (retval, Qunbound))
+ else if (!BASE_EQ (retval, Qunbound))
{
Lisp_Object parent_entry;
eassert (KEYMAPP (retval));
@@ -454,7 +454,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx,
}
/* If we found a binding, clean it up and return it. */
- if (!EQ (val, Qunbound))
+ if (!BASE_EQ (val, Qunbound))
{
if (EQ (val, Qt))
/* A Qt binding is just like an explicit nil binding
@@ -466,12 +466,12 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx,
if (!KEYMAPP (val))
{
- if (NILP (retval) || EQ (retval, Qunbound))
+ if (NILP (retval) || BASE_EQ (retval, Qunbound))
retval = val;
if (!NILP (val))
break; /* Shadows everything that follows. */
}
- else if (NILP (retval) || EQ (retval, Qunbound))
+ else if (NILP (retval) || BASE_EQ (retval, Qunbound))
retval = val;
else if (CONSP (retval_tail))
{
@@ -487,7 +487,8 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx,
maybe_quit ();
}
- return EQ (Qunbound, retval) ? get_keyelt (t_binding, autoload) : retval;
+ return BASE_EQ (Qunbound, retval)
+ ? get_keyelt (t_binding, autoload) : retval;
}
}
@@ -496,7 +497,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx,
bool t_ok, bool noinherit, bool autoload)
{
Lisp_Object val = access_keymap_1 (map, idx, t_ok, noinherit, autoload);
- return EQ (val, Qunbound) ? Qnil : val;
+ return BASE_EQ (val, Qunbound) ? Qnil : val;
}
static void
@@ -1025,8 +1026,14 @@ DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0,
doc: /* Return a copy of the keymap KEYMAP.
Note that this is almost never needed. If you want a keymap that's like
-another yet with a few changes, you should use map inheritance rather
-than copying. I.e. something like:
+another yet with a few changes, you should use keymap inheritance rather
+than copying. That is, something like:
+
+ (defvar-keymap foo-map
+ :parent <theirmap>
+ ...)
+
+Or, if you need to support Emacs versions older than 29:
(let ((map (make-sparse-keymap)))
(set-keymap-parent map <theirmap>)
@@ -1550,7 +1557,7 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr)
for ( ; CONSP (alist); alist = XCDR (alist))
if ((assoc = XCAR (alist), CONSP (assoc))
&& (var = XCAR (assoc), SYMBOLP (var))
- && (val = find_symbol_value (var), !EQ (val, Qunbound))
+ && (val = find_symbol_value (var), !BASE_EQ (val, Qunbound))
&& !NILP (val))
{
Lisp_Object temp;
@@ -1650,7 +1657,7 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and
like in the respective argument of `key-binding'. */)
(Lisp_Object olp, Lisp_Object position)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object keymaps = list1 (current_global_map);
@@ -2595,7 +2602,10 @@ The optional 5th arg NO-REMAP alters how command remapping is handled:
- If DEFINITION is remapped to OTHER-COMMAND, normally return the
bindings for OTHER-COMMAND. But if NO-REMAP is non-nil, return the
- bindings for DEFINITION instead, ignoring its remapping. */)
+ bindings for DEFINITION instead, ignoring its remapping.
+
+Keys that are represented as events that have a `non-key-event' non-nil
+symbol property are ignored. */)
(Lisp_Object definition, Lisp_Object keymap, Lisp_Object firstonly, Lisp_Object noindirect, Lisp_Object no_remap)
{
/* The keymaps in which to search. */
@@ -2719,7 +2729,12 @@ The optional 5th arg NO-REMAP alters how command remapping is handled:
/* It is a true unshadowed match. Record it, unless it's already
been seen (as could happen when inheriting keymaps). */
- if (NILP (Fmember (sequence, found)))
+ if (NILP (Fmember (sequence, found))
+ /* Filter out non key events. */
+ && !(VECTORP (sequence)
+ && ASIZE (sequence) == 1
+ && SYMBOLP (AREF (sequence, 0))
+ && !NILP (Fget (AREF (sequence, 0), Qnon_key_event))))
found = Fcons (sequence, found);
/* If firstonly is Qnon_ascii, then we can return the first
@@ -2867,7 +2882,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
Vkey_translation_map, Qnil, Qnil, prefix,
- msg, nomenu, Qt, Qnil, Qnil);
+ msg, nomenu, Qt, Qnil, Qnil, buffer);
}
/* Print the (major mode) local map. */
@@ -2881,7 +2896,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
start1, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
start1 = Qnil;
}
@@ -2894,7 +2909,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
start1, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
}
else
@@ -2917,7 +2932,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
start1, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
}
@@ -2950,7 +2965,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
maps[i], Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (maps[i], shadow);
SAFE_FREE ();
}
@@ -2968,7 +2983,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
start1, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
}
else
{
@@ -2976,7 +2991,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
start1, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qnil, Qnil);
+ msg, nomenu, Qnil, Qnil, Qnil, buffer);
}
shadow = Fcons (start1, shadow);
@@ -2987,7 +3002,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
current_global_map, Qt, shadow, prefix,
- msg, nomenu, Qnil, Qt, Qnil);
+ msg, nomenu, Qnil, Qt, Qnil, buffer);
/* Print the function-key-map translations under this prefix. */
if (!NILP (KVAR (current_kboard, Vlocal_function_key_map)))
@@ -2996,7 +3011,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
KVAR (current_kboard, Vlocal_function_key_map), Qnil, Qnil, prefix,
- msg, nomenu, Qt, Qnil, Qnil);
+ msg, nomenu, Qt, Qnil, Qnil, buffer);
}
/* Print the input-decode-map translations under this prefix. */
@@ -3006,7 +3021,7 @@ You type Translation\n\
CALLN (Ffuncall,
Qdescribe_map_tree,
KVAR (current_kboard, Vinput_decode_map), Qnil, Qnil, prefix,
- msg, nomenu, Qt, Qnil, Qnil);
+ msg, nomenu, Qt, Qnil, Qnil, buffer);
}
return Qnil;
}
@@ -3031,7 +3046,7 @@ This is text showing the elements of vector matched against indices.
DESCRIBER is the output function used; nil means use `princ'. */)
(Lisp_Object vector, Lisp_Object describer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (NILP (describer))
describer = intern ("princ");
specbind (Qstandard_output, Fcurrent_buffer ());
@@ -3077,7 +3092,7 @@ the one in this keymap, we ignore this one. */)
Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
Lisp_Object mention_shadow)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qstandard_output, Fcurrent_buffer ());
CHECK_VECTOR_OR_CHAR_TABLE (vector);
@@ -3460,4 +3475,6 @@ that describe key bindings. That is why the default is nil. */);
DEFSYM (Qkey_parse, "key-parse");
DEFSYM (Qkey_valid_p, "key-valid-p");
+
+ DEFSYM (Qnon_key_event, "non-key-event");
}
diff --git a/src/kqueue.c b/src/kqueue.c
index c3c4631784d..99a9434cc2e 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -159,8 +159,8 @@ kqueue_compare_dir_list (Lisp_Object watch_object)
(watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (old_entry)), Qnil);
/* Status change time has been changed, the file attributes
have changed. */
- if (NILP (Fequal (Fnth (make_fixnum (3), old_entry),
- Fnth (make_fixnum (3), new_entry))))
+ if (NILP (Fequal (Fnth (make_fixnum (3), old_entry),
+ Fnth (make_fixnum (3), new_entry))))
kqueue_generate_event
(watch_object, Fcons (Qattrib, Qnil),
XCAR (XCDR (old_entry)), Qnil);
diff --git a/src/lisp.h b/src/lisp.h
index f8fe2a69060..dc496cc1658 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -31,6 +31,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <inttypes.h>
#include <limits.h>
+#include <attribute.h>
#include <intprops.h>
#include <verify.h>
@@ -137,25 +138,9 @@ verify (BITS_WORD_MAX >> (BITS_PER_BITS_WORD - 1) == 1);
/* Use pD to format ptrdiff_t values, which suffice for indexes into
buffers and strings. Emacs never allocates objects larger than
PTRDIFF_MAX bytes, as they cause problems with pointer subtraction.
- In C99, pD can always be "t"; configure it here for the sake of
- pre-C99 libraries such as glibc 2.0 and Solaris 8.
-
- On Haiku, the size of ptrdiff_t is inconsistent with the value of
- PTRDIFF_MAX. In that case, "t" should be sufficient. */
-
-#ifndef HAIKU
-#if PTRDIFF_MAX == INT_MAX
-# define pD ""
-#elif PTRDIFF_MAX == LONG_MAX
-# define pD "l"
-#elif PTRDIFF_MAX == LLONG_MAX
-# define pD "ll"
-#else
-# define pD "t"
-#endif
-#else
-# define pD "t"
-#endif
+ In C99, pD can always be "t", as we no longer need to worry about
+ pre-C99 libraries such as glibc 2.0 (1997) and Solaris 8 (2000). */
+#define pD "t"
/* Convenience macro for rarely-used functions that do not return. */
#define AVOID _Noreturn ATTRIBUTE_COLD void
@@ -357,6 +342,7 @@ typedef EMACS_INT Lisp_Word;
# define lisp_h_XIL(i) (i)
# define lisp_h_XLP(o) ((void *) (uintptr_t) (o))
# endif
+# define lisp_h_Qnil 0
#else
# if LISP_WORDS_ARE_POINTERS
# define lisp_h_XLI(o) ((EMACS_INT) (o).i)
@@ -367,20 +353,49 @@ typedef EMACS_INT Lisp_Word;
# define lisp_h_XIL(i) ((Lisp_Object) {i})
# define lisp_h_XLP(o) ((void *) (uintptr_t) (o).i)
# endif
+# define lisp_h_Qnil {0}
#endif
+#define lisp_h_PSEUDOVECTORP(a,code) \
+ (lisp_h_VECTORLIKEP((a)) && \
+ ((XUNTAG ((a), Lisp_Vectorlike, union vectorlike_header)->size \
+ & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
+ == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))))
+
#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x)
#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
#define lisp_h_CHECK_TYPE(ok, predicate, x) \
((ok) ? (void) 0 : wrong_type_argument (predicate, x))
#define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons)
-#define lisp_h_EQ(x, y) (XLI (x) == XLI (y))
+#define lisp_h_BASE_EQ(x, y) (XLI (x) == XLI (y))
+#define lisp_h_BASE2_EQ(x, y) \
+ (BASE_EQ (x, y) \
+ || (symbols_with_pos_enabled \
+ && SYMBOL_WITH_POS_P (x) \
+ && BASE_EQ (XSYMBOL_WITH_POS (x)->sym, y)))
+
+/* FIXME: Do we really need to inline the whole thing?
+ * What about keeping the part after `symbols_with_pos_enabled` in
+ * a separate function? */
+#define lisp_h_EQ(x, y) \
+ ((XLI ((x)) == XLI ((y))) \
+ || (symbols_with_pos_enabled \
+ && (SYMBOL_WITH_POS_P ((x)) \
+ ? (BARE_SYMBOL_P ((y)) \
+ ? XLI (XSYMBOL_WITH_POS((x))->sym) == XLI (y) \
+ : SYMBOL_WITH_POS_P((y)) \
+ && (XLI (XSYMBOL_WITH_POS((x))->sym) \
+ == XLI (XSYMBOL_WITH_POS((y))->sym))) \
+ : (SYMBOL_WITH_POS_P ((y)) \
+ && BARE_SYMBOL_P ((x)) \
+ && (XLI (x) == XLI ((XSYMBOL_WITH_POS ((y)))->sym))))))
+
#define lisp_h_FIXNUMP(x) \
(! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \
- (unsigned) (Lisp_Int0 >> !USE_LSB_TAG)) \
& ((1 << INTTYPEBITS) - 1)))
#define lisp_h_FLOATP(x) TAGGEDP (x, Lisp_Float)
-#define lisp_h_NILP(x) EQ (x, Qnil)
+#define lisp_h_NILP(x) BASE_EQ (x, Qnil)
#define lisp_h_SET_SYMBOL_VAL(sym, v) \
(eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \
(sym)->u.s.val.value = (v))
@@ -389,7 +404,10 @@ typedef EMACS_INT Lisp_Word;
#define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write)
#define lisp_h_SYMBOL_VAL(sym) \
(eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), (sym)->u.s.val.value)
-#define lisp_h_SYMBOLP(x) TAGGEDP (x, Lisp_Symbol)
+#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP ((x), PVEC_SYMBOL_WITH_POS)
+#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP ((x), Lisp_Symbol)
+#define lisp_h_SYMBOLP(x) ((BARE_SYMBOL_P ((x)) || \
+ (symbols_with_pos_enabled && (SYMBOL_WITH_POS_P ((x))))))
#define lisp_h_TAGGEDP(a, tag) \
(! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
- (unsigned) (tag)) \
@@ -434,11 +452,13 @@ typedef EMACS_INT Lisp_Word;
# define XLI(o) lisp_h_XLI (o)
# define XIL(i) lisp_h_XIL (i)
# define XLP(o) lisp_h_XLP (o)
+# define BARE_SYMBOL_P(x) lisp_h_BARE_SYMBOL_P (x)
# define CHECK_FIXNUM(x) lisp_h_CHECK_FIXNUM (x)
# define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x)
# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
# define CONSP(x) lisp_h_CONSP (x)
-# define EQ(x, y) lisp_h_EQ (x, y)
+# define BASE_EQ(x, y) lisp_h_BASE_EQ (x, y)
+# define BASE2_EQ(x, y) lisp_h_BASE2_EQ (x, y)
# define FLOATP(x) lisp_h_FLOATP (x)
# define FIXNUMP(x) lisp_h_FIXNUMP (x)
# define NILP(x) lisp_h_NILP (x)
@@ -446,7 +466,7 @@ typedef EMACS_INT Lisp_Word;
# define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym)
# define SYMBOL_TRAPPED_WRITE_P(sym) lisp_h_SYMBOL_TRAPPED_WRITE_P (sym)
# define SYMBOL_VAL(sym) lisp_h_SYMBOL_VAL (sym)
-# define SYMBOLP(x) lisp_h_SYMBOLP (x)
+/* # define SYMBOLP(x) lisp_h_SYMBOLP (x) */ /* X is accessed more than once. */
# define TAGGEDP(a, tag) lisp_h_TAGGEDP (a, tag)
# define VECTORLIKEP(x) lisp_h_VECTORLIKEP (x)
# define XCAR(c) lisp_h_XCAR (c)
@@ -608,6 +628,8 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object);
extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
extern Lisp_Object default_value (Lisp_Object symbol);
+extern void defalias (Lisp_Object symbol, Lisp_Object definition);
+extern char *fixnum_to_string (EMACS_INT number, char *buffer, char *end);
/* Defined in emacs.c. */
@@ -989,57 +1011,12 @@ union vectorlike_header
ptrdiff_t size;
};
-INLINE bool
-(SYMBOLP) (Lisp_Object x)
-{
- return lisp_h_SYMBOLP (x);
-}
-
-INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
-XSYMBOL (Lisp_Object a)
-{
- eassert (SYMBOLP (a));
- intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
- void *p = (char *) lispsym + i;
- return p;
-}
-
-INLINE Lisp_Object
-make_lisp_symbol (struct Lisp_Symbol *sym)
-{
- /* GCC 7 x86-64 generates faster code if lispsym is
- cast to char * rather than to intptr_t. */
- char *symoffset = (char *) ((char *) sym - (char *) lispsym);
- Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
- eassert (XSYMBOL (a) == sym);
- return a;
-}
-
-INLINE Lisp_Object
-builtin_lisp_symbol (int index)
+struct Lisp_Symbol_With_Pos
{
- return make_lisp_symbol (&lispsym[index]);
-}
-
-INLINE bool
-c_symbol_p (struct Lisp_Symbol *sym)
-{
- char *bp = (char *) lispsym;
- char *sp = (char *) sym;
- if (PTRDIFF_MAX < INTPTR_MAX)
- return bp <= sp && sp < bp + sizeof lispsym;
- else
- {
- ptrdiff_t offset = sp - bp;
- return 0 <= offset && offset < sizeof lispsym;
- }
-}
-
-INLINE void
-(CHECK_SYMBOL) (Lisp_Object x)
-{
- lisp_h_CHECK_SYMBOL (x);
-}
+ union vectorlike_header header;
+ Lisp_Object sym; /* A symbol */
+ Lisp_Object pos; /* A fixnum */
+} GCALIGNED_STRUCT;
/* In the size word of a vector, this bit means the vector has been marked. */
@@ -1064,6 +1041,7 @@ enum pvec_type
PVEC_MARKER,
PVEC_OVERLAY,
PVEC_FINALIZER,
+ PVEC_SYMBOL_WITH_POS,
PVEC_MISC_PTR,
PVEC_USER_PTR,
PVEC_PROCESS,
@@ -1123,6 +1101,92 @@ enum More_Lisp_Bits
values. They are macros for use in #if and static initializers. */
#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
+
+INLINE bool
+PSEUDOVECTORP (Lisp_Object a, int code)
+{
+ return lisp_h_PSEUDOVECTORP (a, code);
+}
+
+INLINE bool
+(BARE_SYMBOL_P) (Lisp_Object x)
+{
+ return lisp_h_BARE_SYMBOL_P (x);
+}
+
+INLINE bool
+(SYMBOL_WITH_POS_P) (Lisp_Object x)
+{
+ return lisp_h_SYMBOL_WITH_POS_P (x);
+}
+
+INLINE bool
+(SYMBOLP) (Lisp_Object x)
+{
+ return lisp_h_SYMBOLP (x);
+}
+
+INLINE struct Lisp_Symbol_With_Pos *
+XSYMBOL_WITH_POS (Lisp_Object a)
+{
+ eassert (SYMBOL_WITH_POS_P (a));
+ return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Symbol_With_Pos);
+}
+
+INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
+(XBARE_SYMBOL) (Lisp_Object a)
+{
+ eassert (BARE_SYMBOL_P (a));
+ intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
+ void *p = (char *) lispsym + i;
+ return p;
+}
+
+INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
+(XSYMBOL) (Lisp_Object a)
+{
+ eassert (SYMBOLP ((a)));
+ if (!symbols_with_pos_enabled || BARE_SYMBOL_P (a))
+ return XBARE_SYMBOL (a);
+ return XBARE_SYMBOL (XSYMBOL_WITH_POS (a)->sym);
+}
+
+INLINE Lisp_Object
+make_lisp_symbol (struct Lisp_Symbol *sym)
+{
+ /* GCC 7 x86-64 generates faster code if lispsym is
+ cast to char * rather than to intptr_t. */
+ char *symoffset = (char *) ((char *) sym - (char *) lispsym);
+ Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
+ eassert (XSYMBOL (a) == sym);
+ return a;
+}
+
+INLINE Lisp_Object
+builtin_lisp_symbol (int index)
+{
+ return make_lisp_symbol (&lispsym[index]);
+}
+
+INLINE bool
+c_symbol_p (struct Lisp_Symbol *sym)
+{
+ char *bp = (char *) lispsym;
+ char *sp = (char *) sym;
+ if (PTRDIFF_MAX < INTPTR_MAX)
+ return bp <= sp && sp < bp + sizeof lispsym;
+ else
+ {
+ ptrdiff_t offset = sp - bp;
+ return 0 <= offset && offset < sizeof lispsym;
+ }
+}
+
+INLINE void
+(CHECK_SYMBOL) (Lisp_Object x)
+{
+ lisp_h_CHECK_SYMBOL (x);
+}
/* True if the possibly-unsigned integer I doesn't fit in a fixnum. */
@@ -1254,7 +1318,22 @@ make_fixed_natnum (EMACS_INT n)
}
/* Return true if X and Y are the same object. */
+INLINE bool
+(BASE_EQ) (Lisp_Object x, Lisp_Object y)
+{
+ return lisp_h_BASE_EQ (x, y);
+}
+
+/* Return true if X and Y are the same object, reckoning X to be the
+ same as a bare symbol Y if X is Y with position. */
+INLINE bool
+(BASE2_EQ) (Lisp_Object x, Lisp_Object y)
+{
+ return lisp_h_BASE2_EQ (x, y);
+}
+/* Return true if X and Y are the same object, reckoning a symbol with
+ position as being the same as the bare symbol. */
INLINE bool
(EQ) (Lisp_Object x, Lisp_Object y)
{
@@ -1496,7 +1575,9 @@ struct Lisp_String
struct
{
ptrdiff_t size; /* MSB is used as the markbit. */
- ptrdiff_t size_byte; /* Set to -1 for unibyte strings. */
+ ptrdiff_t size_byte; /* Set to -1 for unibyte strings,
+ -2 for data in rodata,
+ -3 for immovable unibyte strings. */
INTERVAL intervals; /* Text properties in this string. */
unsigned char *data;
} s;
@@ -1559,13 +1640,13 @@ STRING_MULTIBYTE (Lisp_Object str)
/* Mark STR as a multibyte string. Assure that STR contains only
ASCII characters in advance. */
-#define STRING_SET_MULTIBYTE(STR) \
- do { \
- if (XSTRING (STR)->u.s.size == 0) \
- (STR) = empty_multibyte_string; \
- else \
- XSTRING (STR)->u.s.size_byte = XSTRING (STR)->u.s.size; \
- } while (false)
+INLINE void
+STRING_SET_MULTIBYTE (Lisp_Object str)
+{
+ /* The 0-length strings are unique&shared so we can't modify them. */
+ eassert (XSTRING (str)->u.s.size > 0);
+ XSTRING (str)->u.s.size_byte = XSTRING (str)->u.s.size;
+}
/* Convenience functions for dealing with Lisp strings. */
@@ -1644,6 +1725,13 @@ CHECK_STRING_NULL_BYTES (Lisp_Object string)
Qfilenamep, string);
}
+/* True if STR is immovable (whose data won't move during GC). */
+INLINE bool
+string_immovable_p (Lisp_Object str)
+{
+ return XSTRING (str)->u.s.size_byte == -3;
+}
+
/* A regular vector is just a header plus an array of Lisp_Objects. */
struct Lisp_Vector
@@ -1720,21 +1808,6 @@ PSEUDOVECTOR_TYPEP (const union vectorlike_header *a, enum pvec_type code)
== (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS)));
}
-/* True if A is a pseudovector whose code is CODE. */
-INLINE bool
-PSEUDOVECTORP (Lisp_Object a, int code)
-{
- if (! VECTORLIKEP (a))
- return false;
- else
- {
- /* Converting to union vectorlike_header * avoids aliasing issues. */
- return PSEUDOVECTOR_TYPEP (XUNTAG (a, Lisp_Vectorlike,
- union vectorlike_header),
- code);
- }
-}
-
/* A boolvector is a kind of vectorlike, with contents like a string. */
struct Lisp_Bool_Vector
@@ -2032,19 +2105,17 @@ XSUB_CHAR_TABLE (Lisp_Object a)
INLINE Lisp_Object
CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
{
- struct Lisp_Char_Table *tbl = NULL;
- Lisp_Object val;
- do
+ for (struct Lisp_Char_Table *tbl = XCHAR_TABLE (ct); ;
+ tbl = XCHAR_TABLE (tbl->parent))
{
- tbl = tbl ? XCHAR_TABLE (tbl->parent) : XCHAR_TABLE (ct);
- val = (! SUB_CHAR_TABLE_P (tbl->ascii) ? tbl->ascii
- : XSUB_CHAR_TABLE (tbl->ascii)->contents[idx]);
+ Lisp_Object val = (SUB_CHAR_TABLE_P (tbl->ascii)
+ ? XSUB_CHAR_TABLE (tbl->ascii)->contents[idx]
+ : tbl->ascii);
if (NILP (val))
val = tbl->defalt;
+ if (!NILP (val) || NILP (tbl->parent))
+ return val;
}
- while (NILP (val) && ! NILP (tbl->parent));
-
- return val;
}
/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
@@ -2093,9 +2164,10 @@ struct Lisp_Subr
short min_args, max_args;
const char *symbol_name;
union {
- const char *intspec;
- Lisp_Object native_intspec;
- };
+ const char *string;
+ Lisp_Object native;
+ } intspec;
+ Lisp_Object command_modes;
EMACS_INT doc;
#ifdef HAVE_NATIVE_COMP
Lisp_Object native_comp_u;
@@ -2124,6 +2196,16 @@ XSUBR (Lisp_Object a)
return &XUNTAG (a, Lisp_Vectorlike, union Aligned_Lisp_Subr)->s;
}
+/* Return whether a value might be a valid docstring.
+ Used to distinguish the presence of non-docstring in the docstring slot,
+ as in the case of OClosures. */
+INLINE bool
+VALID_DOCSTRING_P (Lisp_Object doc)
+{
+ return FIXNUMP (doc) || STRINGP (doc)
+ || (CONSP (doc) && STRINGP (XCAR (doc)) && FIXNUMP (XCDR (doc)));
+}
+
enum char_table_specials
{
/* This is the number of slots that every char table must have. This
@@ -2646,6 +2728,22 @@ XOVERLAY (Lisp_Object a)
return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay);
}
+INLINE Lisp_Object
+SYMBOL_WITH_POS_SYM (Lisp_Object a)
+{
+ if (!SYMBOL_WITH_POS_P (a))
+ wrong_type_argument (Qsymbol_with_pos_p, a);
+ return XSYMBOL_WITH_POS (a)->sym;
+}
+
+INLINE Lisp_Object
+SYMBOL_WITH_POS_POS (Lisp_Object a)
+{
+ if (!SYMBOL_WITH_POS_P (a))
+ wrong_type_argument (Qsymbol_with_pos_p, a);
+ return XSYMBOL_WITH_POS (a)->pos;
+}
+
INLINE bool
USER_PTRP (Lisp_Object x)
{
@@ -3098,12 +3196,12 @@ CHECK_SUBR (Lisp_Object x)
/* This version of DEFUN declares a function prototype with the right
arguments, so we can catch errors with maxargs at compile-time. */
-#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
- SUBR_SECTION_ATTRIBUTE \
- static union Aligned_Lisp_Subr sname = \
- {{{ PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
- { .a ## maxargs = fnname }, \
- minargs, maxargs, lname, {intspec}, 0}}; \
+#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
+ SUBR_SECTION_ATTRIBUTE \
+ static union Aligned_Lisp_Subr sname = \
+ {{{ PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
+ { .a ## maxargs = fnname }, \
+ minargs, maxargs, lname, {intspec}, lisp_h_Qnil}}; \
Lisp_Object fnname
/* defsubr (Sname);
@@ -3127,6 +3225,76 @@ enum maxargs
'Finsert (1, &text);'. */
#define CALLN(f, ...) CALLMANY (f, ((Lisp_Object []) {__VA_ARGS__}))
+/* Call function fn on no arguments. */
+INLINE Lisp_Object
+call0 (Lisp_Object fn)
+{
+ return Ffuncall (1, &fn);
+}
+
+/* Call function fn with 1 argument arg1. */
+INLINE Lisp_Object
+call1 (Lisp_Object fn, Lisp_Object arg1)
+{
+ return CALLN (Ffuncall, fn, arg1);
+}
+
+/* Call function fn with 2 arguments arg1, arg2. */
+INLINE Lisp_Object
+call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2);
+}
+
+/* Call function fn with 3 arguments arg1, arg2, arg3. */
+INLINE Lisp_Object
+call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3);
+}
+
+/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */
+INLINE Lisp_Object
+call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+ Lisp_Object arg4)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4);
+}
+
+/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */
+INLINE Lisp_Object
+call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+ Lisp_Object arg4, Lisp_Object arg5)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5);
+}
+
+/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */
+INLINE Lisp_Object
+call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+ Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */
+INLINE Lisp_Object
+call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+ Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+}
+
+/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5,
+ arg6, arg7, arg8. */
+INLINE Lisp_Object
+call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+ Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7,
+ Lisp_Object arg8)
+{
+ return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+}
+
extern void defvar_lisp (struct Lisp_Objfwd const *, char const *);
extern void defvar_lisp_nopro (struct Lisp_Objfwd const *, char const *);
extern void defvar_bool (struct Lisp_Boolfwd const *, char const *);
@@ -3212,6 +3380,7 @@ enum specbind_tag {
SPECPDL_UNWIND_EXCURSION, /* Likewise, on an excursion. */
SPECPDL_UNWIND_VOID, /* Likewise, with no arg. */
SPECPDL_BACKTRACE, /* An element of the backtrace. */
+ SPECPDL_NOP, /* A filler. */
#ifdef HAVE_MODULES
SPECPDL_MODULE_RUNTIME, /* A live module runtime. */
SPECPDL_MODULE_ENVIRONMENT, /* A live module environment. */
@@ -3240,8 +3409,9 @@ union specbinding
} unwind_array;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
- void (*func) (void *);
+ void (*func) (void *); /* Unwind function. */
void *arg;
+ void (*mark) (void *); /* GC mark function (if non-null). */
} unwind_ptr;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
@@ -3265,9 +3435,6 @@ union specbinding
ENUM_BF (specbind_tag) kind : CHAR_BIT;
/* `where' is not used in the case of SPECPDL_LET. */
Lisp_Object symbol, old_value, where;
- /* Normally this is unused; but it is set to the symbol's
- current value when a thread is swapped out. */
- Lisp_Object saved_value;
} let;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
@@ -3278,10 +3445,144 @@ union specbinding
} bt;
};
+/* We use 64-bit platforms as a proxy for ones with ABIs that treat
+ small structs efficiently. */
+#if SIZE_MAX > 0xffffffff
+#define WRAP_SPECPDL_REF 1
+#endif
+
+/* Abstract reference to a specpdl entry.
+ The number is always a multiple of sizeof (union specbinding). */
+#ifdef WRAP_SPECPDL_REF
+/* Use a proper type for specpdl_ref if it does not make the code slower,
+ since the type checking is quite useful. */
+typedef struct { ptrdiff_t bytes; } specpdl_ref;
+#else
+typedef ptrdiff_t specpdl_ref;
+#endif
+
+/* Internal use only. */
+INLINE specpdl_ref
+wrap_specpdl_ref (ptrdiff_t bytes)
+{
+#ifdef WRAP_SPECPDL_REF
+ return (specpdl_ref){.bytes = bytes};
+#else
+ return bytes;
+#endif
+}
+
+/* Internal use only. */
INLINE ptrdiff_t
+unwrap_specpdl_ref (specpdl_ref ref)
+{
+#ifdef WRAP_SPECPDL_REF
+ return ref.bytes;
+#else
+ return ref;
+#endif
+}
+
+INLINE specpdl_ref
+specpdl_count_to_ref (ptrdiff_t count)
+{
+ return wrap_specpdl_ref (count * sizeof (union specbinding));
+}
+
+INLINE ptrdiff_t
+specpdl_ref_to_count (specpdl_ref ref)
+{
+ return unwrap_specpdl_ref (ref) / sizeof (union specbinding);
+}
+
+/* Whether two `specpdl_ref' refer to the same entry. */
+INLINE bool
+specpdl_ref_eq (specpdl_ref a, specpdl_ref b)
+{
+ return unwrap_specpdl_ref (a) == unwrap_specpdl_ref (b);
+}
+
+/* Whether `a' refers to an earlier entry than `b'. */
+INLINE bool
+specpdl_ref_lt (specpdl_ref a, specpdl_ref b)
+{
+ return unwrap_specpdl_ref (a) < unwrap_specpdl_ref (b);
+}
+
+INLINE bool
+specpdl_ref_valid_p (specpdl_ref ref)
+{
+ return unwrap_specpdl_ref (ref) >= 0;
+}
+
+INLINE specpdl_ref
+make_invalid_specpdl_ref (void)
+{
+ return wrap_specpdl_ref (-1);
+}
+
+/* Return a reference that is `delta' steps more recent than `ref'.
+ `delta' may be negative or zero. */
+INLINE specpdl_ref
+specpdl_ref_add (specpdl_ref ref, ptrdiff_t delta)
+{
+ return wrap_specpdl_ref (unwrap_specpdl_ref (ref)
+ + delta * sizeof (union specbinding));
+}
+
+INLINE union specbinding *
+specpdl_ref_to_ptr (specpdl_ref ref)
+{
+ return (union specbinding *)((char *)specpdl + unwrap_specpdl_ref (ref));
+}
+
+/* Return a reference to the most recent specpdl entry. */
+INLINE specpdl_ref
SPECPDL_INDEX (void)
{
- return specpdl_ptr - specpdl;
+ return wrap_specpdl_ref ((char *)specpdl_ptr - (char *)specpdl);
+}
+
+INLINE bool
+backtrace_debug_on_exit (union specbinding *pdl)
+{
+ eassert (pdl->kind == SPECPDL_BACKTRACE);
+ return pdl->bt.debug_on_exit;
+}
+
+void grow_specpdl_allocation (void);
+
+/* Grow the specpdl stack by one entry.
+ The caller should have already initialized the entry.
+ Signal an error on stack overflow.
+
+ Make sure that there is always one unused entry past the top of the
+ stack, so that the just-initialized entry is safely unwound if
+ memory exhausted and an error is signaled here. Also, allocate a
+ never-used entry just before the bottom of the stack; sometimes its
+ address is taken. */
+INLINE void
+grow_specpdl (void)
+{
+ specpdl_ptr++;
+ if (specpdl_ptr == specpdl_end)
+ grow_specpdl_allocation ();
+}
+
+INLINE specpdl_ref
+record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
+{
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ eassert (nargs >= UNEVALLED);
+ specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
+ specpdl_ptr->bt.debug_on_exit = false;
+ specpdl_ptr->bt.function = function;
+ current_thread->stack_top = specpdl_ptr->bt.args = args;
+ specpdl_ptr->bt.nargs = nargs;
+ grow_specpdl ();
+
+ return count;
}
/* This structure helps implement the `catch/throw' and `condition-case/signal'
@@ -3340,19 +3641,46 @@ struct handler
but a few others are handled by storing their value here. */
sys_jmp_buf jmp;
EMACS_INT f_lisp_eval_depth;
- ptrdiff_t pdlcount;
+ specpdl_ref pdlcount;
+ struct bc_frame *act_rec;
int poll_suppress_count;
int interrupt_input_blocked;
+
+#ifdef HAVE_X_WINDOWS
+ int x_error_handler_depth;
+#endif
};
extern Lisp_Object memory_signal_data;
-extern void maybe_quit (void);
-
/* True if ought to quit now. */
#define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
+extern bool volatile pending_signals;
+extern void process_pending_signals (void);
+extern void probably_quit (void);
+
+/* Check quit-flag and quit if it is non-nil. Typing C-g does not
+ directly cause a quit; it only sets Vquit_flag. So the program
+ needs to call maybe_quit at times when it is safe to quit. Every
+ loop that might run for a long time or might not exit ought to call
+ maybe_quit at least once, at a safe place. Unless that is
+ impossible, of course. But it is very desirable to avoid creating
+ loops where maybe_quit is impossible.
+
+ If quit-flag is set to `kill-emacs' the SIGINT handler has received
+ a request to exit Emacs when it is safe to do.
+
+ When not quitting, process any pending signals. */
+
+INLINE void
+maybe_quit (void)
+{
+ if (!NILP (Vquit_flag) || pending_signals)
+ probably_quit ();
+}
+
/* Process a quit rarely, based on a counter COUNT, for efficiency.
"Rarely" means once per USHRT_MAX + 1 times; this is somewhat
arbitrary, but efficient. */
@@ -3680,8 +4008,6 @@ extern void hexbuf_digest (char *, void const *, int);
extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
EMACS_UINT hash_string (char const *, ptrdiff_t);
EMACS_UINT sxhash (Lisp_Object);
-Lisp_Object hashfn_eql (Lisp_Object, struct Lisp_Hash_Table *);
-Lisp_Object hashfn_equal (Lisp_Object, struct Lisp_Hash_Table *);
Lisp_Object hashfn_user_defined (Lisp_Object, struct Lisp_Hash_Table *);
Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,
Lisp_Object, bool);
@@ -3697,7 +4023,6 @@ extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, Lisp_Object));
extern Lisp_Object do_yes_or_no_p (Lisp_Object);
-extern int string_version_cmp (Lisp_Object, Lisp_Object);
extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);
extern bool equal_no_quit (Lisp_Object, Lisp_Object);
@@ -3709,8 +4034,15 @@ extern ptrdiff_t string_char_to_byte (Lisp_Object, ptrdiff_t);
extern ptrdiff_t string_byte_to_char (Lisp_Object, ptrdiff_t);
extern Lisp_Object string_to_multibyte (Lisp_Object);
extern Lisp_Object string_make_unibyte (Lisp_Object);
+extern Lisp_Object plist_get (Lisp_Object plist, Lisp_Object prop);
+extern Lisp_Object plist_put (Lisp_Object plist, Lisp_Object prop,
+ Lisp_Object val);
+extern Lisp_Object plist_member (Lisp_Object plist, Lisp_Object prop);
extern void syms_of_fns (void);
+/* Defined in sort.c */
+extern void tim_sort (Lisp_Object, Lisp_Object *, const ptrdiff_t);
+
/* Defined in floatfns.c. */
verify (FLT_RADIX == 2 || FLT_RADIX == 16);
enum { LOG2_FLT_RADIX = FLT_RADIX == 2 ? 1 : 4 };
@@ -3858,8 +4190,9 @@ extern void refill_memory_reserve (void);
#endif
extern void alloc_unexec_pre (void);
extern void alloc_unexec_post (void);
-extern void mark_stack (char const *, char const *);
+extern void mark_c_stack (char const *, char const *);
extern void flush_stack_call_func1 (void (*func) (void *arg), void *arg);
+extern void mark_memory (void const *start, void const *end);
/* Force callee-saved registers and register windows onto the stack,
so that conservative garbage collection can see their values. */
@@ -3982,6 +4315,7 @@ extern Lisp_Object make_specified_string (const char *,
ptrdiff_t, ptrdiff_t, bool);
extern Lisp_Object make_pure_string (const char *, ptrdiff_t, ptrdiff_t, bool);
extern Lisp_Object make_pure_c_string (const char *, ptrdiff_t);
+extern void pin_string (Lisp_Object string);
/* Make a string allocated in pure space, use STR as string data. */
@@ -4076,7 +4410,8 @@ extern struct Lisp_Vector *allocate_pseudovector (int, int, int,
extern bool gc_in_progress;
extern Lisp_Object make_float (double);
extern void display_malloc_warning (void);
-extern ptrdiff_t inhibit_garbage_collection (void);
+extern specpdl_ref inhibit_garbage_collection (void);
+extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object);
extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
extern void free_cons (struct Lisp_Cons *);
extern void init_alloc_once (void);
@@ -4171,6 +4506,7 @@ extern void dir_warning (const char *, Lisp_Object);
extern void init_obarray_once (void);
extern void init_lread (void);
extern void syms_of_lread (void);
+extern void mark_lread (void);
INLINE Lisp_Object
intern (const char *str)
@@ -4219,23 +4555,11 @@ extern bool FUNCTIONP (Lisp_Object);
extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector);
extern Lisp_Object eval_sub (Lisp_Object form);
extern Lisp_Object apply1 (Lisp_Object, Lisp_Object);
-extern Lisp_Object call0 (Lisp_Object);
-extern Lisp_Object call1 (Lisp_Object, Lisp_Object);
-extern Lisp_Object call2 (Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-extern Lisp_Object call8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object internal_catch (Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object);
extern Lisp_Object internal_lisp_condition_case (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object internal_condition_case (Lisp_Object (*) (void), Lisp_Object, Lisp_Object (*) (Lisp_Object));
extern Lisp_Object internal_condition_case_1 (Lisp_Object (*) (Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
extern Lisp_Object internal_condition_case_2 (Lisp_Object (*) (Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
-extern Lisp_Object internal_condition_case_3 (Lisp_Object (*) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
-extern Lisp_Object internal_condition_case_4 (Lisp_Object (*) (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
-extern Lisp_Object internal_condition_case_5 (Lisp_Object (*) (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
extern Lisp_Object internal_condition_case_n
(Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *,
Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *));
@@ -4247,24 +4571,28 @@ extern void specbind (Lisp_Object, Lisp_Object);
extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
extern void record_unwind_protect_array (Lisp_Object *, ptrdiff_t);
extern void record_unwind_protect_ptr (void (*) (void *), void *);
+extern void record_unwind_protect_ptr_mark (void (*function) (void *),
+ void *arg, void (*mark) (void *));
extern void record_unwind_protect_int (void (*) (int), int);
extern void record_unwind_protect_intmax (void (*) (intmax_t), intmax_t);
extern void record_unwind_protect_void (void (*) (void));
extern void record_unwind_protect_excursion (void);
extern void record_unwind_protect_nothing (void);
extern void record_unwind_protect_module (enum specbind_tag, void *);
-extern void clear_unwind_protect (ptrdiff_t);
-extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object);
-extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
-extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
-extern void rebind_for_thread_switch (void);
-extern void unbind_for_thread_switch (struct thread_state *);
+extern void clear_unwind_protect (specpdl_ref);
+extern void set_unwind_protect (specpdl_ref, void (*) (Lisp_Object),
+ Lisp_Object);
+extern void set_unwind_protect_ptr (specpdl_ref, void (*) (void *), void *);
+extern Lisp_Object unbind_to (specpdl_ref, Lisp_Object);
+void specpdl_unrewind (union specbinding *pdl, int distance, bool vars_only);
extern AVOID error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
extern AVOID verror (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
extern Lisp_Object vformat_string (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
-extern void un_autoload (Lisp_Object);
+extern Lisp_Object load_with_autoload_queue
+ (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage,
+ Lisp_Object nosuffix, Lisp_Object must_suffix);
extern Lisp_Object call_debugger (Lisp_Object arg);
extern void init_eval_once (void);
extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
@@ -4273,11 +4601,13 @@ extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
extern void init_eval (void);
extern void syms_of_eval (void);
extern void prog_ignore (Lisp_Object);
-extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t);
extern void mark_specpdl (union specbinding *first, union specbinding *ptr);
extern void get_backtrace (Lisp_Object array);
Lisp_Object backtrace_top_function (void);
extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
+void do_debug_on_call (Lisp_Object code, specpdl_ref count);
+Lisp_Object funcall_general (Lisp_Object fun,
+ ptrdiff_t numargs, Lisp_Object *args);
/* Defined in unexmacosx.c. */
#if defined DARWIN_OS && defined HAVE_UNEXEC
@@ -4403,6 +4733,7 @@ extern bool internal_delete_file (Lisp_Object);
extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *);
extern bool file_directory_p (Lisp_Object);
extern bool file_accessible_directory_p (Lisp_Object);
+extern Lisp_Object buffer_visited_file_modtime (struct buffer *);
extern void init_fileio (void);
extern void syms_of_fileio (void);
@@ -4511,7 +4842,7 @@ extern void syms_of_indent (void);
/* Defined in frame.c. */
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
-extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
+extern Lisp_Object do_switch_frame (Lisp_Object, int, Lisp_Object);
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
extern void frames_discard_buffer (Lisp_Object);
extern void init_frame_once (void);
@@ -4619,9 +4950,24 @@ extern int read_bytecode_char (bool);
/* Defined in bytecode.c. */
extern void syms_of_bytecode (void);
-extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object, ptrdiff_t, Lisp_Object *);
+extern Lisp_Object exec_byte_code (Lisp_Object, ptrdiff_t,
+ ptrdiff_t, Lisp_Object *);
extern Lisp_Object get_byte_code_arity (Lisp_Object);
+extern void init_bc_thread (struct bc_thread_state *bc);
+extern void free_bc_thread (struct bc_thread_state *bc);
+extern void mark_bytecode (struct bc_thread_state *bc);
+
+INLINE struct bc_frame *
+get_act_rec (struct thread_state *th)
+{
+ return th->bc.fp;
+}
+
+INLINE void
+set_act_rec (struct thread_state *th, struct bc_frame *act_rec)
+{
+ th->bc.fp = act_rec;
+}
/* Defined in macros.c. */
extern void init_macros (void);
@@ -4676,6 +5022,7 @@ extern void child_setup_tty (int);
extern void setup_pty (int);
extern int set_window_size (int, int, int);
extern EMACS_INT get_random (void);
+extern unsigned long int get_random_ulong (void);
extern void seed_random (void *, ptrdiff_t);
extern void init_random (void);
extern void emacs_backtrace (int);
@@ -4767,9 +5114,7 @@ extern void syms_of_w32cygwinx (void);
extern Lisp_Object Vface_alternative_font_family_alist;
extern Lisp_Object Vface_alternative_font_registry_alist;
extern void syms_of_xfaces (void);
-#ifdef HAVE_PDUMPER
extern void init_xfaces (void);
-#endif
#ifdef HAVE_X_WINDOWS
/* Defined in xfns.c. */
@@ -4946,7 +5291,7 @@ extern void *record_xmalloc (size_t)
#define USE_SAFE_ALLOCA \
ptrdiff_t sa_avail = MAX_ALLOCA; \
- ptrdiff_t sa_count = SPECPDL_INDEX ()
+ specpdl_ref sa_count = SPECPDL_INDEX ()
#define AVAIL_ALLOCA(size) (sa_avail -= (size), alloca (size))
@@ -4984,9 +5329,9 @@ extern void *record_xmalloc (size_t)
#define SAFE_FREE() safe_free (sa_count)
INLINE void
-safe_free (ptrdiff_t sa_count)
+safe_free (specpdl_ref sa_count)
{
- while (specpdl_ptr != specpdl + sa_count)
+ while (specpdl_ptr != specpdl_ref_to_ptr (sa_count))
{
specpdl_ptr--;
if (specpdl_ptr->kind == SPECPDL_UNWIND_PTR)
@@ -5012,9 +5357,9 @@ safe_free (ptrdiff_t sa_count)
safe_free_unbind_to (count, sa_count, val)
INLINE Lisp_Object
-safe_free_unbind_to (ptrdiff_t count, ptrdiff_t sa_count, Lisp_Object val)
+safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val)
{
- eassert (count <= sa_count);
+ eassert (!specpdl_ref_lt (sa_count, count));
return unbind_to (count, val);
}
@@ -5172,7 +5517,7 @@ struct for_each_tail_internal
intended for use only by the above macros.
Use Brent’s teleporting tortoise-hare algorithm. See:
- Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
+ Brent RP. BIT. 1980;20(2):176-184. doi:10.1007/BF01933190
https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf
This macro uses maybe_quit because of an excess of caution. The
@@ -5189,7 +5534,7 @@ struct for_each_tail_internal
|| ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \
|| (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \
li.tortoise = (tail), false)) \
- && EQ (tail, li.tortoise)) \
+ && BASE_EQ (tail, li.tortoise)) \
? (cycle) : (void) 0))
/* Do a `for' loop over alist values. */
diff --git a/src/lread.c b/src/lread.c
index 2eff20f15df..759cc08946d 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -128,9 +128,8 @@ static ptrdiff_t read_from_string_index;
static ptrdiff_t read_from_string_index_byte;
static ptrdiff_t read_from_string_limit;
-/* Number of characters read in the current call to Fread or
- Fread_from_string. */
-static EMACS_INT readchar_count;
+/* Position in object from which characters are being read by `readchar'. */
+static EMACS_INT readchar_offset;
/* This contains the last string skipped with #@. */
static char *saved_doc_string;
@@ -213,7 +212,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
if (multibyte)
*multibyte = 0;
- readchar_count++;
+ readchar_offset++;
if (BUFFERP (readcharfun))
{
@@ -424,7 +423,7 @@ skip_dyn_eof (Lisp_Object readcharfun)
static void
unreadchar (Lisp_Object readcharfun, int c)
{
- readchar_count--;
+ readchar_offset--;
if (c == -1)
/* Don't back up the pointer if we're unreading the end-of-input mark,
since readchar didn't advance it when we read it. */
@@ -551,13 +550,21 @@ invalid_syntax_lisp (Lisp_Object s, Lisp_Object readcharfun)
{
if (BUFFERP (readcharfun))
{
+ ptrdiff_t line, column;
+
+ /* Get the line/column in the readcharfun buffer. */
+ {
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ record_unwind_protect_excursion ();
+ set_buffer_internal (XBUFFER (readcharfun));
+ line = count_lines (BEGV_BYTE, PT_BYTE) + 1;
+ column = current_column ();
+ unbind_to (count, Qnil);
+ }
+
xsignal (Qinvalid_read_syntax,
- list3 (s,
- /* We should already be in the readcharfun
- buffer when this error is called, so no need
- to switch to it first. */
- make_fixnum (count_lines (BEGV_BYTE, PT_BYTE) + 1),
- make_fixnum (current_column ())));
+ list3 (s, make_fixnum (line), make_fixnum (column)));
}
else
xsignal1 (Qinvalid_read_syntax, s);
@@ -647,12 +654,8 @@ struct subst
};
static Lisp_Object read_internal_start (Lisp_Object, Lisp_Object,
- Lisp_Object);
-static Lisp_Object read0 (Lisp_Object);
-static Lisp_Object read1 (Lisp_Object, int *, bool);
-
-static Lisp_Object read_list (bool, Lisp_Object);
-static Lisp_Object read_vector (Lisp_Object, bool);
+ Lisp_Object, bool);
+static Lisp_Object read0 (Lisp_Object, bool);
static Lisp_Object substitute_object_recurse (struct subst *, Lisp_Object);
static void substitute_in_interval (INTERVAL, void *);
@@ -933,7 +936,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
ch = READCHAR;
if (ch == '\n') ch = READCHAR;
/* It is OK to leave the position after a #! line, since
- that is what read1 does. */
+ that is what read0 does. */
}
if (ch != ';')
@@ -1170,6 +1173,13 @@ compute_found_effective (Lisp_Object found)
return concat2 (src_name, build_string ("c"));
}
+static void
+loadhist_initialize (Lisp_Object filename)
+{
+ eassert (STRINGP (filename) || NILP (filename));
+ specbind (Qcurrent_load_list, Fcons (filename, Qnil));
+}
+
DEFUN ("load", Fload, Sload, 1, 5, 0,
doc: /* Execute a file of Lisp code named FILE.
First try FILE with `.elc' appended, then try with `.el', then try
@@ -1220,8 +1230,8 @@ Return t if the file exists and loads successfully. */)
{
FILE *stream UNINIT;
int fd;
- int fd_index UNINIT;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref fd_index UNINIT;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object found, efound, hist_file_name;
/* True means we printed the ".el is newer" message. */
bool newer = 0;
@@ -1234,10 +1244,9 @@ Return t if the file exists and loads successfully. */)
CHECK_STRING (file);
/* If file name is magic, call the handler. */
- /* This shouldn't be necessary any more now that `openp' handles it right.
- handler = Ffind_file_name_handler (file, Qload);
- if (!NILP (handler))
- return call5 (handler, Qload, file, noerror, nomessage, nosuffix); */
+ handler = Ffind_file_name_handler (file, Qload);
+ if (!NILP (handler))
+ return call5 (handler, Qload, file, noerror, nomessage, nosuffix);
/* The presence of this call is the result of a historical accident:
it used to be in every file-operation and when it got removed
@@ -1553,8 +1562,7 @@ Return t if the file exists and loads successfully. */)
if (is_module)
{
#ifdef HAVE_MODULES
- specbind (Qcurrent_load_list, Qnil);
- LOADHIST_ATTACH (found);
+ loadhist_initialize (found);
Fmodule_load (found);
build_load_history (found, true);
#else
@@ -1565,8 +1573,7 @@ Return t if the file exists and loads successfully. */)
else if (is_native_elisp)
{
#ifdef HAVE_NATIVE_COMP
- specbind (Qcurrent_load_list, Qnil);
- LOADHIST_ATTACH (hist_file_name);
+ loadhist_initialize (hist_file_name);
Fnative_elisp_load (found, Qnil);
build_load_history (hist_file_name, true);
#else
@@ -1629,7 +1636,7 @@ save_match_data_load (Lisp_Object file, Lisp_Object noerror,
Lisp_Object nomessage, Lisp_Object nosuffix,
Lisp_Object must_suffix)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_save_match_data ();
Lisp_Object result = Fload (file, noerror, nomessage, nosuffix, must_suffix);
return unbind_to (count, result);
@@ -1657,7 +1664,7 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */)
(Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate)
{
Lisp_Object file;
- int fd = openp (path, filename, suffixes, &file, predicate, false, false);
+ int fd = openp (path, filename, suffixes, &file, predicate, false, true);
if (NILP (predicate) && fd >= 0)
emacs_close (fd);
return file;
@@ -1728,13 +1735,24 @@ maybe_swap_for_eln (bool no_native, Lisp_Object *filename, int *fd,
{
if (!NILP (find_symbol_value (
Qnative_comp_warning_on_missing_source)))
- call2 (intern_c_string ("display-warning"),
- Qcomp,
- CALLN (Fformat,
- build_string ("Cannot look-up eln file as no source "
- "file was found for %s"),
- *filename));
- return;
+ {
+ /* If we have an installation without any .el files,
+ there's really no point in giving a warning here,
+ because that will trigger a cascade of warnings. So
+ just do a sanity check and refuse to do anything if we
+ can't find even central .el files. */
+ if (NILP (Flocate_file_internal (build_string ("simple.el"),
+ Vload_path,
+ Qnil, Qnil)))
+ return;
+ call2 (intern_c_string ("display-warning"),
+ Qcomp,
+ CALLN (Fformat,
+ build_string ("Cannot look up eln file as "
+ "no source file was found for %s"),
+ *filename));
+ return;
+ }
}
}
Lisp_Object eln_rel_name = Fcomp_el_to_eln_rel_filename (src_name);
@@ -2165,7 +2183,7 @@ readevalloop (Lisp_Object readcharfun,
{
int c;
Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct buffer *b = 0;
bool continue_reading_p;
Lisp_Object lex_bound;
@@ -2175,6 +2193,9 @@ readevalloop (Lisp_Object readcharfun,
bool first_sexp = 1;
Lisp_Object macroexpand = intern ("internal-macroexpand-for-load");
+ if (!NILP (sourcename))
+ CHECK_STRING (sourcename);
+
if (NILP (Ffboundp (macroexpand))
|| (STRINGP (sourcename) && suffix_p (sourcename, ".elc")))
/* Don't macroexpand before the corresponding function is defined
@@ -2198,7 +2219,6 @@ readevalloop (Lisp_Object readcharfun,
emacs_abort ();
specbind (Qstandard_input, readcharfun);
- specbind (Qcurrent_load_list, Qnil);
record_unwind_protect_int (readevalloop_1, load_convert_to_unibyte);
load_convert_to_unibyte = !NILP (unibyte);
@@ -2207,7 +2227,7 @@ readevalloop (Lisp_Object readcharfun,
lexical environment, otherwise, turn off lexical binding. */
lex_bound = find_symbol_value (Qlexical_binding);
specbind (Qinternal_interpreter_environment,
- (NILP (lex_bound) || EQ (lex_bound, Qunbound)
+ (NILP (lex_bound) || BASE_EQ (lex_bound, Qunbound)
? Qnil : list1 (Qt)));
specbind (Qmacroexp__dynvars, Vmacroexp__dynvars);
@@ -2216,12 +2236,12 @@ readevalloop (Lisp_Object readcharfun,
&& !NILP (sourcename) && !NILP (Ffile_name_absolute_p (sourcename)))
sourcename = Fexpand_file_name (sourcename, Qnil);
- LOADHIST_ATTACH (sourcename);
+ loadhist_initialize (sourcename);
continue_reading_p = 1;
while (continue_reading_p)
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
if (b != 0 && !BUFFER_LIVE_P (b))
error ("Reading from killed buffer");
@@ -2272,6 +2292,7 @@ readevalloop (Lisp_Object readcharfun,
if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'
|| c == NO_BREAK_SPACE)
goto read_next;
+ UNREAD (c);
if (! HASH_TABLE_P (read_objects_map)
|| XHASH_TABLE (read_objects_map)->count)
@@ -2286,12 +2307,9 @@ readevalloop (Lisp_Object readcharfun,
DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
Qnil, false);
if (!NILP (Vpurify_flag) && c == '(')
- {
- val = read_list (0, readcharfun);
- }
+ val = read0 (readcharfun, false);
else
{
- UNREAD (c);
if (!NILP (readfun))
{
val = call1 (readfun, readcharfun);
@@ -2309,7 +2327,7 @@ readevalloop (Lisp_Object readcharfun,
else if (! NILP (Vload_read_function))
val = call1 (Vload_read_function, readcharfun);
else
- val = read_internal_start (readcharfun, Qnil, Qnil);
+ val = read_internal_start (readcharfun, Qnil, Qnil, false);
}
/* Empty hashes can be reused; otherwise, reset on next call. */
if (HASH_TABLE_P (read_objects_map)
@@ -2335,7 +2353,7 @@ readevalloop (Lisp_Object readcharfun,
{
Vvalues = Fcons (val, Vvalues);
if (EQ (Vstandard_output, Qt))
- Fprin1 (val, Qnil);
+ Fprin1 (val, Qnil, Qnil);
else
Fprint (val, Qnil);
}
@@ -2376,7 +2394,7 @@ will be evaluated without lexical binding.
This function preserves the position of point. */)
(Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, Lisp_Object unibyte, Lisp_Object do_allow_print)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object tem, buf;
if (NILP (buffer))
@@ -2421,7 +2439,7 @@ This function does not move point. */)
(Lisp_Object start, Lisp_Object end, Lisp_Object printflag, Lisp_Object read_function)
{
/* FIXME: Do the eval-sexp-add-defvars dance! */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object tem, cbuf;
cbuf = Fcurrent_buffer ();
@@ -2467,7 +2485,35 @@ STREAM or the value of `standard-input' may be:
return call1 (intern ("read-minibuffer"),
build_string ("Lisp expression: "));
- return read_internal_start (stream, Qnil, Qnil);
+ return read_internal_start (stream, Qnil, Qnil, false);
+}
+
+DEFUN ("read-positioning-symbols", Fread_positioning_symbols,
+ Sread_positioning_symbols, 0, 1, 0,
+ doc: /* Read one Lisp expression as text from STREAM, return as Lisp object.
+Convert each occurrence of a symbol into a "symbol with pos" object.
+
+If STREAM is nil, use the value of `standard-input' (which see).
+STREAM or the value of `standard-input' may be:
+ a buffer (read from point and advance it)
+ a marker (read from where it points and advance it)
+ a function (call it with no arguments for each character,
+ call it with a char as argument to push a char back)
+ a string (takes text from string, starting at the beginning)
+ t (read text line using minibuffer and use it, or read from
+ standard input in batch mode). */)
+ (Lisp_Object stream)
+{
+ if (NILP (stream))
+ stream = Vstandard_input;
+ if (EQ (stream, Qt))
+ stream = Qread_char;
+ if (EQ (stream, Qread_char))
+ /* FIXME: ?! When is this used !? */
+ return call1 (intern ("read-minibuffer"),
+ build_string ("Lisp expression: "));
+
+ return read_internal_start (stream, Qnil, Qnil, true);
}
DEFUN ("read-from-string", Fread_from_string, Sread_from_string, 1, 3, 0,
@@ -2483,18 +2529,21 @@ the end of STRING. */)
Lisp_Object ret;
CHECK_STRING (string);
/* `read_internal_start' sets `read_from_string_index'. */
- ret = read_internal_start (string, start, end);
+ ret = read_internal_start (string, start, end, false);
return Fcons (ret, make_fixnum (read_from_string_index));
}
/* Function to set up the global context we need in toplevel read
- calls. START and END only used when STREAM is a string. */
+ calls. START and END only used when STREAM is a string.
+ LOCATE_SYMS true means read symbol occurrences as symbols with
+ position. */
static Lisp_Object
-read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
+read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end,
+ bool locate_syms)
{
Lisp_Object retval;
- readchar_count = 0;
+ readchar_offset = BUFFERP (stream) ? XBUFFER (stream)->pt : 0;
/* We can get called from readevalloop which may have set these
already. */
if (! HASH_TABLE_P (read_objects_map)
@@ -2507,9 +2556,6 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
read_objects_completed
= make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD, Qnil, false);
- if (EQ (Vread_with_symbol_positions, Qt)
- || EQ (Vread_with_symbol_positions, stream))
- Vread_symbol_positions_list = Qnil;
if (STRINGP (stream)
|| ((CONSP (stream) && STRINGP (XCAR (stream)))))
@@ -2530,11 +2576,7 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
read_from_string_limit = endval;
}
- retval = read0 (stream);
- if (EQ (Vread_with_symbol_positions, Qt)
- || EQ (Vread_with_symbol_positions, stream))
- Vread_symbol_positions_list = Fnreverse (Vread_symbol_positions_list);
- /* Empty hashes can be reused; otherwise, reset on next call. */
+ retval = read0 (stream, locate_syms);
if (HASH_TABLE_P (read_objects_map)
&& XHASH_TABLE (read_objects_map)->count > 0)
read_objects_map = Qnil;
@@ -2544,24 +2586,6 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
return retval;
}
-
-/* Use this for recursive reads, in contexts where internal tokens
- are not allowed. */
-
-static Lisp_Object
-read0 (Lisp_Object readcharfun)
-{
- register Lisp_Object val;
- int c;
-
- val = read1 (readcharfun, &c, 0);
- if (!c)
- return val;
-
- invalid_syntax_lisp (Fmake_string (make_fixnum (1), make_fixnum (c), Qnil),
- readcharfun);
-}
-
/* Grow a read buffer BUF that contains OFFSET useful bytes of data,
by at least MAX_MULTIBYTE_LENGTH bytes. Update *BUF_ADDR and
*BUF_SIZE accordingly; 0 <= OFFSET <= *BUF_SIZE. If *BUF_ADDR is
@@ -2572,7 +2596,7 @@ read0 (Lisp_Object readcharfun)
static char *
grow_read_buffer (char *buf, ptrdiff_t offset,
- char **buf_addr, ptrdiff_t *buf_size, ptrdiff_t count)
+ char **buf_addr, ptrdiff_t *buf_size, specpdl_ref count)
{
char *p = xpalloc (*buf_addr, buf_size, MAX_MULTIBYTE_LENGTH, -1, 1);
if (!*buf_addr)
@@ -2620,7 +2644,7 @@ enum { UNICODE_CHARACTER_NAME_LENGTH_BOUND = 200 };
If the escape sequence forces unibyte, return eight-bit char. */
static int
-read_escape (Lisp_Object readcharfun, bool stringp)
+read_escape (Lisp_Object readcharfun)
{
int c = READCHAR;
/* \u allows up to four hex digits, \U up to eight. Default to the
@@ -2650,12 +2674,10 @@ read_escape (Lisp_Object readcharfun, bool stringp)
return '\t';
case 'v':
return '\v';
+
case '\n':
- return -1;
- case ' ':
- if (stringp)
- return -1;
- return ' ';
+ /* ?\LF is an error; it's probably a user mistake. */
+ error ("Invalid escape character syntax");
case 'M':
c = READCHAR;
@@ -2663,7 +2685,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
error ("Invalid escape character syntax");
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
return c | meta_modifier;
case 'S':
@@ -2672,7 +2694,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
error ("Invalid escape character syntax");
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
return c | shift_modifier;
case 'H':
@@ -2681,7 +2703,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
error ("Invalid escape character syntax");
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
return c | hyper_modifier;
case 'A':
@@ -2690,19 +2712,19 @@ read_escape (Lisp_Object readcharfun, bool stringp)
error ("Invalid escape character syntax");
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
return c | alt_modifier;
case 's':
c = READCHAR;
- if (stringp || c != '-')
+ if (c != '-')
{
UNREAD (c);
return ' ';
}
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
return c | super_modifier;
case 'C':
@@ -2713,7 +2735,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
case '^':
c = READCHAR;
if (c == '\\')
- c = read_escape (readcharfun, 0);
+ c = read_escape (readcharfun);
if ((c & ~CHAR_MODIFIER_MASK) == '?')
return 0177 | (c & CHAR_MODIFIER_MASK);
else if (! ASCII_CHAR_P ((c & ~CHAR_MODIFIER_MASK)))
@@ -2864,8 +2886,8 @@ read_escape (Lisp_Object readcharfun, bool stringp)
invalid_syntax ("Empty character name", readcharfun);
name[length] = '\0';
- /* character_name_to_code can invoke read1, recursively.
- This is why read1's buffer is not static. */
+ /* character_name_to_code can invoke read0, recursively.
+ This is why read0's buffer is not static. */
return character_name_to_code (name, length, readcharfun);
}
@@ -2894,20 +2916,17 @@ digit_to_number (int character, int base)
return digit < base ? digit : -1;
}
-static char const invalid_radix_integer_format[] = "integer, radix %"pI"d";
-
-/* Small, as read1 is recursive (Bug#31995). But big enough to hold
- the invalid_radix_integer string. */
-enum { stackbufsize = max (64,
- (sizeof invalid_radix_integer_format
- - sizeof "%"pI"d"
- + INT_STRLEN_BOUND (EMACS_INT) + 1)) };
+/* Size of the fixed-size buffer used during reading.
+ It should be at least big enough for `invalid_radix_integer' but
+ can usefully be much bigger than that. */
+enum { stackbufsize = 1024 };
static void
invalid_radix_integer (EMACS_INT radix, char stackbuf[VLA_ELEMS (stackbufsize)],
Lisp_Object readcharfun)
{
- sprintf (stackbuf, invalid_radix_integer_format, radix);
+ int n = snprintf (stackbuf, stackbufsize, "integer, radix %"pI"d", radix);
+ eassert (n < stackbufsize);
invalid_syntax (stackbuf, readcharfun);
}
@@ -2925,7 +2944,7 @@ read_integer (Lisp_Object readcharfun, int radix,
char *p = read_buffer;
char *heapbuf = NULL;
int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int c = READCHAR;
if (c == '-' || c == '+')
@@ -2973,761 +2992,1114 @@ read_integer (Lisp_Object readcharfun, int radix,
*p = '\0';
return unbind_to (count, string_to_number (read_buffer, radix, NULL));
}
+
-/* If the next token is ')' or ']' or '.', we store that character
- in *PCH and the return value is not interesting. Else, we store
- zero in *PCH and we read and return one lisp object.
-
- FIRST_IN_LIST is true if this is the first element of a list. */
-
+/* Read a character literal (preceded by `?'). */
static Lisp_Object
-read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
+read_char_literal (Lisp_Object readcharfun)
{
- int c;
- bool uninterned_symbol = false;
- bool skip_shorthand = false;
- bool multibyte;
- char stackbuf[stackbufsize];
- current_thread->stack_top = stackbuf;
+ int ch = READCHAR;
+ if (ch < 0)
+ end_of_file_error ();
- *pch = 0;
+ /* Accept `single space' syntax like (list ? x) where the
+ whitespace character is SPC or TAB.
+ Other literal whitespace like NL, CR, and FF are not accepted,
+ as there are well-established escape sequences for these. */
+ if (ch == ' ' || ch == '\t')
+ return make_fixnum (ch);
- retry:
+ if ( ch == '(' || ch == ')' || ch == '[' || ch == ']'
+ || ch == '"' || ch == ';')
+ {
+ CHECK_LIST (Vlread_unescaped_character_literals);
+ Lisp_Object char_obj = make_fixed_natnum (ch);
+ if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals)))
+ Vlread_unescaped_character_literals =
+ Fcons (char_obj, Vlread_unescaped_character_literals);
+ }
- c = READCHAR_REPORT_MULTIBYTE (&multibyte);
- if (c < 0)
- end_of_file_error ();
+ if (ch == '\\')
+ ch = read_escape (readcharfun);
- switch (c)
- {
- case '(':
- return read_list (0, readcharfun);
+ int modifiers = ch & CHAR_MODIFIER_MASK;
+ ch &= ~CHAR_MODIFIER_MASK;
+ if (CHAR_BYTE8_P (ch))
+ ch = CHAR_TO_BYTE8 (ch);
+ ch |= modifiers;
- case '[':
- return read_vector (readcharfun, 0);
+ int nch = READCHAR;
+ UNREAD (nch);
+ if (nch <= 32
+ || nch == '"' || nch == '\'' || nch == ';' || nch == '('
+ || nch == ')' || nch == '[' || nch == ']' || nch == '#'
+ || nch == '?' || nch == '`' || nch == ',' || nch == '.')
+ return make_fixnum (ch);
- case ')':
- case ']':
- {
- *pch = c;
- return Qnil;
- }
+ invalid_syntax ("?", readcharfun);
+}
- case '#':
- c = READCHAR;
- if (c == 's')
+/* Read a string literal (preceded by '"'). */
+static Lisp_Object
+read_string_literal (char stackbuf[VLA_ELEMS (stackbufsize)],
+ Lisp_Object readcharfun)
+{
+ char *read_buffer = stackbuf;
+ ptrdiff_t read_buffer_size = stackbufsize;
+ specpdl_ref count = SPECPDL_INDEX ();
+ char *heapbuf = NULL;
+ char *p = read_buffer;
+ char *end = read_buffer + read_buffer_size;
+ /* True if we saw an escape sequence specifying
+ a multibyte character. */
+ bool force_multibyte = false;
+ /* True if we saw an escape sequence specifying
+ a single-byte character. */
+ bool force_singlebyte = false;
+ bool cancel = false;
+ ptrdiff_t nchars = 0;
+
+ int ch;
+ while ((ch = READCHAR) >= 0 && ch != '\"')
+ {
+ if (end - p < MAX_MULTIBYTE_LENGTH)
{
- c = READCHAR;
- if (c == '(')
+ ptrdiff_t offset = p - read_buffer;
+ read_buffer = grow_read_buffer (read_buffer, offset,
+ &heapbuf, &read_buffer_size,
+ count);
+ p = read_buffer + offset;
+ end = read_buffer + read_buffer_size;
+ }
+
+ if (ch == '\\')
+ {
+ /* First apply string-specific escape rules: */
+ ch = READCHAR;
+ switch (ch)
{
- /* Accept extended format for hash tables (extensible to
- other types), e.g.
- #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
- Lisp_Object tmp = read_list (0, readcharfun);
- Lisp_Object head = CAR_SAFE (tmp);
- Lisp_Object data = Qnil;
- Lisp_Object val = Qnil;
- /* The size is 2 * number of allowed keywords to
- make-hash-table. */
- Lisp_Object params[12];
- Lisp_Object ht;
- Lisp_Object key = Qnil;
- int param_count = 0;
-
- if (!EQ (head, Qhash_table))
+ case 's':
+ /* `\s' is always a space in strings. */
+ ch = ' ';
+ break;
+ case ' ':
+ case '\n':
+ /* `\SPC' and `\LF' generate no characters at all. */
+ if (p == read_buffer)
+ cancel = true;
+ continue;
+ default:
+ UNREAD (ch);
+ ch = read_escape (readcharfun);
+ break;
+ }
+
+ int modifiers = ch & CHAR_MODIFIER_MASK;
+ ch &= ~CHAR_MODIFIER_MASK;
+
+ if (CHAR_BYTE8_P (ch))
+ force_singlebyte = true;
+ else if (! ASCII_CHAR_P (ch))
+ force_multibyte = true;
+ else /* I.e. ASCII_CHAR_P (ch). */
+ {
+ /* Allow `\C-SPC' and `\^SPC'. This is done here because
+ the literals ?\C-SPC and ?\^SPC (rather inconsistently)
+ yield (' ' | CHAR_CTL); see bug#55738. */
+ if (modifiers == CHAR_CTL && ch == ' ')
+ {
+ ch = 0;
+ modifiers = 0;
+ }
+ if (modifiers & CHAR_SHIFT)
{
- ptrdiff_t size = XFIXNUM (Flength (tmp));
- Lisp_Object record = Fmake_record (CAR_SAFE (tmp),
- make_fixnum (size - 1),
- Qnil);
- for (int i = 1; i < size; i++)
+ /* Shift modifier is valid only with [A-Za-z]. */
+ if (ch >= 'A' && ch <= 'Z')
+ modifiers &= ~CHAR_SHIFT;
+ else if (ch >= 'a' && ch <= 'z')
{
- tmp = Fcdr (tmp);
- ASET (record, i, Fcar (tmp));
+ ch -= ('a' - 'A');
+ modifiers &= ~CHAR_SHIFT;
}
- return record;
}
- tmp = CDR_SAFE (tmp);
+ if (modifiers & CHAR_META)
+ {
+ /* Move the meta bit to the right place for a
+ string. */
+ modifiers &= ~CHAR_META;
+ ch = BYTE8_TO_CHAR (ch | 0x80);
+ force_singlebyte = true;
+ }
+ }
- /* This is repetitive but fast and simple. */
- params[param_count] = QCsize;
- params[param_count + 1] = Fplist_get (tmp, Qsize);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+ /* Any modifiers remaining are invalid. */
+ if (modifiers)
+ invalid_syntax ("Invalid modifier in string", readcharfun);
+ p += CHAR_STRING (ch, (unsigned char *) p);
+ }
+ else
+ {
+ p += CHAR_STRING (ch, (unsigned char *) p);
+ if (CHAR_BYTE8_P (ch))
+ force_singlebyte = true;
+ else if (! ASCII_CHAR_P (ch))
+ force_multibyte = true;
+ }
+ nchars++;
+ }
- params[param_count] = QCtest;
- params[param_count + 1] = Fplist_get (tmp, Qtest);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+ if (ch < 0)
+ end_of_file_error ();
- params[param_count] = QCweakness;
- params[param_count + 1] = Fplist_get (tmp, Qweakness);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+ /* If purifying, and string starts with \ newline,
+ return zero instead. This is for doc strings
+ that we are really going to find in etc/DOC.nn.nn. */
+ if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
+ {
+ unbind_to (count, Qnil);
+ return make_fixnum (0);
+ }
- params[param_count] = QCrehash_size;
- params[param_count + 1] = Fplist_get (tmp, Qrehash_size);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+ if (!force_multibyte && force_singlebyte)
+ {
+ /* READ_BUFFER contains raw 8-bit bytes and no multibyte
+ forms. Convert it to unibyte. */
+ nchars = str_as_unibyte ((unsigned char *) read_buffer,
+ p - read_buffer);
+ p = read_buffer + nchars;
+ }
- params[param_count] = QCrehash_threshold;
- params[param_count + 1] = Fplist_get (tmp, Qrehash_threshold);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+ Lisp_Object obj = make_specified_string (read_buffer, nchars, p - read_buffer,
+ (force_multibyte
+ || (p - read_buffer != nchars)));
+ return unbind_to (count, obj);
+}
- params[param_count] = QCpurecopy;
- params[param_count + 1] = Fplist_get (tmp, Qpurecopy);
- if (!NILP (params[param_count + 1]))
- param_count += 2;
+/* Make a hash table from the constructor plist. */
+static Lisp_Object
+hash_table_from_plist (Lisp_Object plist)
+{
+ Lisp_Object params[12];
+ Lisp_Object *par = params;
+
+ /* This is repetitive but fast and simple. */
+#define ADDPARAM(name) \
+ do { \
+ Lisp_Object val = plist_get (plist, Q ## name); \
+ if (!NILP (val)) \
+ { \
+ *par++ = QC ## name; \
+ *par++ = val; \
+ } \
+ } while (0)
+
+ ADDPARAM (size);
+ ADDPARAM (test);
+ ADDPARAM (weakness);
+ ADDPARAM (rehash_size);
+ ADDPARAM (rehash_threshold);
+ ADDPARAM (purecopy);
+
+ Lisp_Object data = plist_get (plist, Qdata);
+
+ /* Now use params to make a new hash table and fill it. */
+ Lisp_Object ht = Fmake_hash_table (par - params, params);
+
+ Lisp_Object last = data;
+ FOR_EACH_TAIL_SAFE (data)
+ {
+ Lisp_Object key = XCAR (data);
+ data = XCDR (data);
+ if (!CONSP (data))
+ break;
+ Lisp_Object val = XCAR (data);
+ last = XCDR (data);
+ Fputhash (key, val, ht);
+ }
+ if (!NILP (last))
+ error ("Hash table data is not a list of even length");
- /* This is the hash table data. */
- data = Fplist_get (tmp, Qdata);
+ return ht;
+}
- /* Now use params to make a new hash table and fill it. */
- ht = Fmake_hash_table (param_count, params);
+static Lisp_Object
+record_from_list (Lisp_Object elems)
+{
+ ptrdiff_t size = list_length (elems);
+ Lisp_Object obj = Fmake_record (XCAR (elems),
+ make_fixnum (size - 1),
+ Qnil);
+ Lisp_Object tl = XCDR (elems);
+ for (int i = 1; i < size; i++)
+ {
+ ASET (obj, i, XCAR (tl));
+ tl = XCDR (tl);
+ }
+ return obj;
+}
- Lisp_Object last = data;
- FOR_EACH_TAIL_SAFE (data)
- {
- key = XCAR (data);
- data = XCDR (data);
- if (!CONSP (data))
- break;
- val = XCAR (data);
- last = XCDR (data);
- Fputhash (key, val, ht);
- }
- if (!NILP (last))
- error ("Hash table data is not a list of even length");
+/* Turn a reversed list into a vector. */
+static Lisp_Object
+vector_from_rev_list (Lisp_Object elems)
+{
+ ptrdiff_t size = list_length (elems);
+ Lisp_Object obj = make_nil_vector (size);
+ Lisp_Object *vec = XVECTOR (obj)->contents;
+ for (ptrdiff_t i = size - 1; i >= 0; i--)
+ {
+ vec[i] = XCAR (elems);
+ Lisp_Object next = XCDR (elems);
+ free_cons (XCONS (elems));
+ elems = next;
+ }
+ return obj;
+}
- return ht;
- }
- UNREAD (c);
- invalid_syntax ("#", readcharfun);
- }
- if (c == '^')
- {
- c = READCHAR;
- if (c == '[')
- {
- Lisp_Object tmp;
- tmp = read_vector (readcharfun, 0);
- if (ASIZE (tmp) < CHAR_TABLE_STANDARD_SLOTS)
- error ("Invalid size char-table");
- XSETPVECTYPE (XVECTOR (tmp), PVEC_CHAR_TABLE);
- return tmp;
- }
- else if (c == '^')
- {
- c = READCHAR;
- if (c == '[')
- {
- /* Sub char-table can't be read as a regular
- vector because of a two C integer fields. */
- Lisp_Object tbl, tmp = read_list (1, readcharfun);
- ptrdiff_t size = list_length (tmp);
- int i, depth, min_char;
- struct Lisp_Cons *cell;
-
- if (size == 0)
- error ("Zero-sized sub char-table");
-
- if (! RANGED_FIXNUMP (1, XCAR (tmp), 3))
- error ("Invalid depth in sub char-table");
- depth = XFIXNUM (XCAR (tmp));
- if (chartab_size[depth] != size - 2)
- error ("Invalid size in sub char-table");
- cell = XCONS (tmp), tmp = XCDR (tmp), size--;
- free_cons (cell);
-
- if (! RANGED_FIXNUMP (0, XCAR (tmp), MAX_CHAR))
- error ("Invalid minimum character in sub-char-table");
- min_char = XFIXNUM (XCAR (tmp));
- cell = XCONS (tmp), tmp = XCDR (tmp), size--;
- free_cons (cell);
-
- tbl = make_uninit_sub_char_table (depth, min_char);
- for (i = 0; i < size; i++)
- {
- XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (tmp);
- cell = XCONS (tmp), tmp = XCDR (tmp);
- free_cons (cell);
- }
- return tbl;
- }
- invalid_syntax ("#^^", readcharfun);
- }
- invalid_syntax ("#^", readcharfun);
- }
- if (c == '&')
+static Lisp_Object
+bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
+{
+ Lisp_Object obj = vector_from_rev_list (elems);
+ Lisp_Object *vec = XVECTOR (obj)->contents;
+ ptrdiff_t size = ASIZE (obj);
+
+ if (!(size >= COMPILED_STACK_DEPTH + 1 && size <= COMPILED_INTERACTIVE + 1
+ && (FIXNUMP (vec[COMPILED_ARGLIST])
+ || CONSP (vec[COMPILED_ARGLIST])
+ || NILP (vec[COMPILED_ARGLIST]))
+ && FIXNATP (vec[COMPILED_STACK_DEPTH])))
+ invalid_syntax ("Invalid byte-code object", readcharfun);
+
+ if (load_force_doc_strings
+ && NILP (vec[COMPILED_CONSTANTS])
+ && STRINGP (vec[COMPILED_BYTECODE]))
+ {
+ /* Lazily-loaded bytecode is represented by the constant slot being nil
+ and the bytecode slot a (lazily loaded) string containing the
+ print representation of (BYTECODE . CONSTANTS). Unpack the
+ pieces by coerceing the string to unibyte and reading the result. */
+ Lisp_Object enc = vec[COMPILED_BYTECODE];
+ Lisp_Object pair = Fread (Fcons (enc, readcharfun));
+ if (!CONSP (pair))
+ invalid_syntax ("Invalid byte-code object", readcharfun);
+
+ vec[COMPILED_BYTECODE] = XCAR (pair);
+ vec[COMPILED_CONSTANTS] = XCDR (pair);
+ }
+
+ if (!((STRINGP (vec[COMPILED_BYTECODE])
+ && VECTORP (vec[COMPILED_CONSTANTS]))
+ || CONSP (vec[COMPILED_BYTECODE])))
+ invalid_syntax ("Invalid byte-code object", readcharfun);
+
+ if (STRINGP (vec[COMPILED_BYTECODE]))
+ {
+ if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE]))
{
- Lisp_Object length;
- length = read1 (readcharfun, pch, first_in_list);
- c = READCHAR;
- if (c == '"')
- {
- Lisp_Object tmp, val;
- EMACS_INT size_in_chars = bool_vector_bytes (XFIXNAT (length));
- unsigned char *data;
-
- UNREAD (c);
- tmp = read1 (readcharfun, pch, first_in_list);
- if (STRING_MULTIBYTE (tmp)
- || (size_in_chars != SCHARS (tmp)
- /* We used to print 1 char too many
- when the number of bits was a multiple of 8.
- Accept such input in case it came from an old
- version. */
- && ! (XFIXNAT (length)
- == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR)))
- invalid_syntax ("#&...", readcharfun);
-
- val = make_uninit_bool_vector (XFIXNAT (length));
- data = bool_vector_uchar_data (val);
- memcpy (data, SDATA (tmp), size_in_chars);
- /* Clear the extraneous bits in the last byte. */
- if (XFIXNUM (length) != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR)
- data[size_in_chars - 1]
- &= (1 << (XFIXNUM (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
- return val;
- }
- invalid_syntax ("#&...", readcharfun);
+ /* BYTESTR must have been produced by Emacs 20.2 or earlier
+ because it produced a raw 8-bit string for byte-code and
+ now such a byte-code string is loaded as multibyte with
+ raw 8-bit characters converted to multibyte form.
+ Convert them back to the original unibyte form. */
+ vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]);
}
- if (c == '[')
- {
- /* Accept compiled functions at read-time so that we don't have to
- build them using function calls. */
- Lisp_Object tmp;
- struct Lisp_Vector *vec;
- tmp = read_vector (readcharfun, 1);
- vec = XVECTOR (tmp);
- if (! (COMPILED_STACK_DEPTH < ASIZE (tmp)
- && (FIXNUMP (AREF (tmp, COMPILED_ARGLIST))
- || CONSP (AREF (tmp, COMPILED_ARGLIST))
- || NILP (AREF (tmp, COMPILED_ARGLIST)))
- && ((STRINGP (AREF (tmp, COMPILED_BYTECODE))
- && VECTORP (AREF (tmp, COMPILED_CONSTANTS)))
- || CONSP (AREF (tmp, COMPILED_BYTECODE)))
- && FIXNATP (AREF (tmp, COMPILED_STACK_DEPTH))))
- invalid_syntax ("Invalid byte-code object", readcharfun);
-
- if (STRINGP (AREF (tmp, COMPILED_BYTECODE))
- && STRING_MULTIBYTE (AREF (tmp, COMPILED_BYTECODE)))
- {
- /* BYTESTR must have been produced by Emacs 20.2 or earlier
- because it produced a raw 8-bit string for byte-code and
- now such a byte-code string is loaded as multibyte with
- raw 8-bit characters converted to multibyte form.
- Convert them back to the original unibyte form. */
- ASET (tmp, COMPILED_BYTECODE,
- Fstring_as_unibyte (AREF (tmp, COMPILED_BYTECODE)));
- }
+ // Bytecode must be immovable.
+ pin_string (vec[COMPILED_BYTECODE]);
+ }
- XSETPVECTYPE (vec, PVEC_COMPILED);
- return tmp;
- }
- if (c == '(')
- {
- Lisp_Object tmp;
- int ch;
-
- /* Read the string itself. */
- tmp = read1 (readcharfun, &ch, 0);
- if (ch != 0 || !STRINGP (tmp))
- invalid_syntax ("#", readcharfun);
- /* Read the intervals and their properties. */
- while (1)
- {
- Lisp_Object beg, end, plist;
+ XSETPVECTYPE (XVECTOR (obj), PVEC_COMPILED);
+ return obj;
+}
- beg = read1 (readcharfun, &ch, 0);
- end = plist = Qnil;
- if (ch == ')')
- break;
- if (ch == 0)
- end = read1 (readcharfun, &ch, 0);
- if (ch == 0)
- plist = read1 (readcharfun, &ch, 0);
- if (ch)
- invalid_syntax ("Invalid string property list", readcharfun);
- Fset_text_properties (beg, end, plist, tmp);
- }
+static Lisp_Object
+char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
+{
+ Lisp_Object obj = vector_from_rev_list (elems);
+ if (ASIZE (obj) < CHAR_TABLE_STANDARD_SLOTS)
+ invalid_syntax ("Invalid size char-table", readcharfun);
+ XSETPVECTYPE (XVECTOR (obj), PVEC_CHAR_TABLE);
+ return obj;
- return tmp;
- }
+}
+
+static Lisp_Object
+sub_char_table_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
+{
+ /* A sub-char-table can't be read as a regular vector because of two
+ C integer fields. */
+ elems = Fnreverse (elems);
+ ptrdiff_t size = list_length (elems);
+ if (size < 2)
+ error ("Invalid size of sub-char-table");
+
+ if (!RANGED_FIXNUMP (1, XCAR (elems), 3))
+ error ("Invalid depth in sub-char-table");
+ int depth = XFIXNUM (XCAR (elems));
+
+ if (chartab_size[depth] != size - 2)
+ error ("Invalid size in sub-char-table");
+ elems = XCDR (elems);
+
+ if (!RANGED_FIXNUMP (0, XCAR (elems), MAX_CHAR))
+ error ("Invalid minimum character in sub-char-table");
+ int min_char = XFIXNUM (XCAR (elems));
+ elems = XCDR (elems);
+
+ Lisp_Object tbl = make_uninit_sub_char_table (depth, min_char);
+ for (int i = 0; i < size - 2; i++)
+ {
+ XSUB_CHAR_TABLE (tbl)->contents[i] = XCAR (elems);
+ elems = XCDR (elems);
+ }
+ return tbl;
+}
+
+static Lisp_Object
+string_props_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
+{
+ elems = Fnreverse (elems);
+ if (NILP (elems) || !STRINGP (XCAR (elems)))
+ invalid_syntax ("#", readcharfun);
+ Lisp_Object obj = XCAR (elems);
+ for (Lisp_Object tl = XCDR (elems); !NILP (tl);)
+ {
+ Lisp_Object beg = XCAR (tl);
+ tl = XCDR (tl);
+ if (NILP (tl))
+ invalid_syntax ("Invalid string property list", readcharfun);
+ Lisp_Object end = XCAR (tl);
+ tl = XCDR (tl);
+ if (NILP (tl))
+ invalid_syntax ("Invalid string property list", readcharfun);
+ Lisp_Object plist = XCAR (tl);
+ tl = XCDR (tl);
+ Fset_text_properties (beg, end, plist, obj);
+ }
+ return obj;
+}
- /* #@NUMBER is used to skip NUMBER following bytes.
- That's used in .elc files to skip over doc strings
- and function definitions. */
- if (c == '@')
+/* Read a bool vector (preceded by "#&"). */
+static Lisp_Object
+read_bool_vector (char stackbuf[VLA_ELEMS (stackbufsize)],
+ Lisp_Object readcharfun)
+{
+ ptrdiff_t length = 0;
+ for (;;)
+ {
+ int c = READCHAR;
+ if (c < '0' || c > '9')
{
- enum { extra = 100 };
- ptrdiff_t i, nskip = 0, digits = 0;
+ if (c != '"')
+ invalid_syntax ("#&", readcharfun);
+ break;
+ }
+ if (INT_MULTIPLY_WRAPV (length, 10, &length)
+ | INT_ADD_WRAPV (length, c - '0', &length))
+ invalid_syntax ("#&", readcharfun);
+ }
- /* Read a decimal integer. */
- while ((c = READCHAR) >= 0
- && c >= '0' && c <= '9')
- {
- if ((STRING_BYTES_BOUND - extra) / 10 <= nskip)
- string_overflow ();
- digits++;
- nskip *= 10;
- nskip += c - '0';
- if (digits == 2 && nskip == 0)
- { /* We've just seen #@00, which means "skip to end". */
- skip_dyn_eof (readcharfun);
- return Qnil;
- }
- }
+ ptrdiff_t size_in_chars = bool_vector_bytes (length);
+ Lisp_Object str = read_string_literal (stackbuf, readcharfun);
+ if (STRING_MULTIBYTE (str)
+ || !(size_in_chars == SCHARS (str)
+ /* We used to print 1 char too many when the number of bits
+ was a multiple of 8. Accept such input in case it came
+ from an old version. */
+ || length == (SCHARS (str) - 1) * BOOL_VECTOR_BITS_PER_CHAR))
+ invalid_syntax ("#&...", readcharfun);
+
+ Lisp_Object obj = make_uninit_bool_vector (length);
+ unsigned char *data = bool_vector_uchar_data (obj);
+ memcpy (data, SDATA (str), size_in_chars);
+ /* Clear the extraneous bits in the last byte. */
+ if (length != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR)
+ data[size_in_chars - 1] &= (1 << (length % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
+ return obj;
+}
+
+/* Skip (and optionally remember) a lazily-loaded string
+ preceded by "#@". */
+static void
+skip_lazy_string (Lisp_Object readcharfun)
+{
+ ptrdiff_t nskip = 0;
+ ptrdiff_t digits = 0;
+ for (;;)
+ {
+ int c = READCHAR;
+ if (c < '0' || c > '9')
+ {
if (nskip > 0)
/* We can't use UNREAD here, because in the code below we side-step
- READCHAR. Instead, assume the first char after #@NNN occupies
- a single byte, which is the case normally since it's just
- a space. */
+ READCHAR. Instead, assume the first char after #@NNN occupies
+ a single byte, which is the case normally since it's just
+ a space. */
nskip--;
else
UNREAD (c);
-
- if (load_force_doc_strings
- && (FROM_FILE_P (readcharfun)))
- {
- /* If we are supposed to force doc strings into core right now,
- record the last string that we skipped,
- and record where in the file it comes from. */
-
- /* But first exchange saved_doc_string
- with prev_saved_doc_string, so we save two strings. */
- {
- char *temp = saved_doc_string;
- ptrdiff_t temp_size = saved_doc_string_size;
- file_offset temp_pos = saved_doc_string_position;
- ptrdiff_t temp_len = saved_doc_string_length;
-
- saved_doc_string = prev_saved_doc_string;
- saved_doc_string_size = prev_saved_doc_string_size;
- saved_doc_string_position = prev_saved_doc_string_position;
- saved_doc_string_length = prev_saved_doc_string_length;
-
- prev_saved_doc_string = temp;
- prev_saved_doc_string_size = temp_size;
- prev_saved_doc_string_position = temp_pos;
- prev_saved_doc_string_length = temp_len;
- }
-
- if (saved_doc_string_size == 0)
- {
- saved_doc_string = xmalloc (nskip + extra);
- saved_doc_string_size = nskip + extra;
- }
- if (nskip > saved_doc_string_size)
- {
- saved_doc_string = xrealloc (saved_doc_string, nskip + extra);
- saved_doc_string_size = nskip + extra;
- }
-
- FILE *instream = infile->stream;
- saved_doc_string_position = (file_tell (instream)
- - infile->lookahead);
-
- /* Copy that many bytes into saved_doc_string. */
- i = 0;
- for (int n = min (nskip, infile->lookahead); 0 < n; n--)
- saved_doc_string[i++]
- = c = infile->buf[--infile->lookahead];
- block_input ();
- for (; i < nskip && 0 <= c; i++)
- saved_doc_string[i] = c = getc (instream);
- unblock_input ();
-
- saved_doc_string_length = i;
- }
- else
- /* Skip that many bytes. */
- skip_dyn_bytes (readcharfun, nskip);
-
- goto retry;
+ break;
}
- if (c == '!')
+ if (INT_MULTIPLY_WRAPV (nskip, 10, &nskip)
+ | INT_ADD_WRAPV (nskip, c - '0', &nskip))
+ invalid_syntax ("#@", readcharfun);
+ digits++;
+ if (digits == 2 && nskip == 0)
{
- /* #! appears at the beginning of an executable file.
- Skip the first line. */
- while (c != '\n' && c >= 0)
- c = READCHAR;
- goto retry;
+ /* #@00 means "skip to end" */
+ skip_dyn_eof (readcharfun);
+ return;
}
- if (c == '$')
- return Vload_file_name;
- if (c == '\'')
- return list2 (Qfunction, read0 (readcharfun));
- /* #:foo is the uninterned symbol named foo. */
- if (c == ':')
+ }
+
+ if (load_force_doc_strings && FROM_FILE_P (readcharfun))
+ {
+ /* If we are supposed to force doc strings into core right now,
+ record the last string that we skipped,
+ and record where in the file it comes from. */
+
+ /* But first exchange saved_doc_string
+ with prev_saved_doc_string, so we save two strings. */
+ {
+ char *temp = saved_doc_string;
+ ptrdiff_t temp_size = saved_doc_string_size;
+ file_offset temp_pos = saved_doc_string_position;
+ ptrdiff_t temp_len = saved_doc_string_length;
+
+ saved_doc_string = prev_saved_doc_string;
+ saved_doc_string_size = prev_saved_doc_string_size;
+ saved_doc_string_position = prev_saved_doc_string_position;
+ saved_doc_string_length = prev_saved_doc_string_length;
+
+ prev_saved_doc_string = temp;
+ prev_saved_doc_string_size = temp_size;
+ prev_saved_doc_string_position = temp_pos;
+ prev_saved_doc_string_length = temp_len;
+ }
+
+ enum { extra = 100 };
+ if (saved_doc_string_size == 0)
{
- uninterned_symbol = true;
- read_hash_prefixed_symbol:
- c = READCHAR;
- if (!(c > 040
- && c != NO_BREAK_SPACE
- && (c >= 0200
- || strchr ("\"';()[]#`,", c) == NULL)))
- {
- /* No symbol character follows, this is the empty
- symbol. */
- UNREAD (c);
- return Fmake_symbol (empty_unibyte_string);
- }
- goto read_symbol;
+ saved_doc_string = xmalloc (nskip + extra);
+ saved_doc_string_size = nskip + extra;
}
- /* #_foo is really the symbol foo, regardless of shorthands */
- if (c == '_')
+ if (nskip > saved_doc_string_size)
{
- skip_shorthand = true;
- goto read_hash_prefixed_symbol;
+ saved_doc_string = xrealloc (saved_doc_string, nskip + extra);
+ saved_doc_string_size = nskip + extra;
}
- /* ## is the empty symbol. */
- if (c == '#')
- return Fintern (empty_unibyte_string, Qnil);
- if (c >= '0' && c <= '9')
- {
- EMACS_INT n = c - '0';
- bool overflow = false;
+ FILE *instream = infile->stream;
+ saved_doc_string_position = (file_tell (instream) - infile->lookahead);
- /* Read a non-negative integer. */
- while ('0' <= (c = READCHAR) && c <= '9')
- {
- overflow |= INT_MULTIPLY_WRAPV (n, 10, &n);
- overflow |= INT_ADD_WRAPV (n, c - '0', &n);
- }
+ /* Copy that many bytes into saved_doc_string. */
+ ptrdiff_t i = 0;
+ int c = 0;
+ for (int n = min (nskip, infile->lookahead); n > 0; n--)
+ saved_doc_string[i++] = c = infile->buf[--infile->lookahead];
+ block_input ();
+ for (; i < nskip && c >= 0; i++)
+ saved_doc_string[i] = c = getc (instream);
+ unblock_input ();
- if (!overflow)
- {
- if (c == 'r' || c == 'R')
- {
- if (! (2 <= n && n <= 36))
- invalid_radix_integer (n, stackbuf, readcharfun);
- return read_integer (readcharfun, n, stackbuf);
- }
+ saved_doc_string_length = i;
+ }
+ else
+ /* Skip that many bytes. */
+ skip_dyn_bytes (readcharfun, nskip);
+}
- if (n <= MOST_POSITIVE_FIXNUM && ! NILP (Vread_circle))
- {
- /* Reader forms that can reuse previously read objects. */
- /* #n=object returns object, but associates it with
- n for #n#. */
- if (c == '=')
- {
- /* Make a placeholder for #n# to use temporarily. */
- /* Note: We used to use AUTO_CONS to allocate
- placeholder, but that is a bad idea, since it
- will place a stack-allocated cons cell into
- the list in read_objects_map, which is a
- staticpro'd global variable, and thus each of
- its elements is marked during each GC. A
- stack-allocated object will become garbled
- when its stack slot goes out of scope, and
- some other function reuses it for entirely
- different purposes, which will cause crashes
- in GC. */
- Lisp_Object placeholder = Fcons (Qnil, Qnil);
- struct Lisp_Hash_Table *h
- = XHASH_TABLE (read_objects_map);
- Lisp_Object number = make_fixnum (n), hash;
-
- ptrdiff_t i = hash_lookup (h, number, &hash);
- if (i >= 0)
- /* Not normal, but input could be malformed. */
- set_hash_value_slot (h, i, placeholder);
- else
- hash_put (h, number, placeholder, hash);
-
- /* Read the object itself. */
- Lisp_Object tem = read0 (readcharfun);
-
- /* If it can be recursive, remember it for
- future substitutions. */
- if (! SYMBOLP (tem)
- && ! NUMBERP (tem)
- && ! (STRINGP (tem) && !string_intervals (tem)))
- {
- struct Lisp_Hash_Table *h2
- = XHASH_TABLE (read_objects_completed);
- i = hash_lookup (h2, tem, &hash);
- eassert (i < 0);
- hash_put (h2, tem, Qnil, hash);
- }
-
- /* Now put it everywhere the placeholder was... */
- if (CONSP (tem))
- {
- Fsetcar (placeholder, XCAR (tem));
- Fsetcdr (placeholder, XCDR (tem));
- return placeholder;
- }
- else
- {
- Flread__substitute_object_in_subtree
- (tem, placeholder, read_objects_completed);
-
- /* ...and #n# will use the real value from now on. */
- i = hash_lookup (h, number, &hash);
- eassert (i >= 0);
- set_hash_value_slot (h, i, tem);
-
- return tem;
- }
- }
+/* Length of prefix only consisting of symbol constituent characters. */
+static ptrdiff_t
+symbol_char_span (const char *s)
+{
+ const char *p = s;
+ while ( *p == '^' || *p == '*' || *p == '+' || *p == '-' || *p == '/'
+ || *p == '<' || *p == '=' || *p == '>' || *p == '_' || *p == '|')
+ p++;
+ return p - s;
+}
- /* #n# returns a previously read object. */
- if (c == '#')
- {
- struct Lisp_Hash_Table *h
- = XHASH_TABLE (read_objects_map);
- ptrdiff_t i = hash_lookup (h, make_fixnum (n), NULL);
- if (i >= 0)
- return HASH_VALUE (h, i);
- }
- }
- }
- /* Fall through to error message. */
+static void
+skip_space_and_comments (Lisp_Object readcharfun)
+{
+ int c;
+ do
+ {
+ c = READCHAR;
+ if (c == ';')
+ do
+ c = READCHAR;
+ while (c >= 0 && c != '\n');
+ if (c < 0)
+ end_of_file_error ();
+ }
+ while (c <= 32 || c == NO_BREAK_SPACE);
+ UNREAD (c);
+}
+
+/* When an object is read, the type of the top read stack entry indicates
+ the syntactic context. */
+enum read_entry_type
+{
+ /* preceding syntactic context */
+ RE_list_start, /* "(" */
+
+ RE_list, /* "(" (+ OBJECT) */
+ RE_list_dot, /* "(" (+ OBJECT) "." */
+
+ RE_vector, /* "[" (* OBJECT) */
+ RE_record, /* "#s(" (* OBJECT) */
+ RE_char_table, /* "#^[" (* OBJECT) */
+ RE_sub_char_table, /* "#^^[" (* OBJECT) */
+ RE_byte_code, /* "#[" (* OBJECT) */
+ RE_string_props, /* "#(" (* OBJECT) */
+
+ RE_special, /* "'" | "#'" | "`" | "," | ",@" */
+
+ RE_numbered, /* "#" (+ DIGIT) "=" */
+};
+
+struct read_stack_entry
+{
+ enum read_entry_type type;
+ union {
+ /* RE_list, RE_list_dot */
+ struct {
+ Lisp_Object head; /* first cons of list */
+ Lisp_Object tail; /* last cons of list */
+ } list;
+
+ /* RE_vector, RE_record, RE_char_table, RE_sub_char_table,
+ RE_byte_code, RE_string_props */
+ struct {
+ Lisp_Object elems; /* list of elements in reverse order */
+ bool old_locate_syms; /* old value of locate_syms */
+ } vector;
+
+ /* RE_special */
+ struct {
+ Lisp_Object symbol; /* symbol from special syntax */
+ } special;
+
+ /* RE_numbered */
+ struct {
+ Lisp_Object number; /* number as a fixnum */
+ Lisp_Object placeholder; /* placeholder object */
+ } numbered;
+ } u;
+};
+
+struct read_stack
+{
+ struct read_stack_entry *stack; /* base of stack */
+ ptrdiff_t size; /* allocated size in entries */
+ ptrdiff_t sp; /* current number of entries */
+};
+
+static struct read_stack rdstack = {NULL, 0, 0};
+
+void
+mark_lread (void)
+{
+ /* Mark the read stack, which may contain data not otherwise traced */
+ for (ptrdiff_t i = 0; i < rdstack.sp; i++)
+ {
+ struct read_stack_entry *e = &rdstack.stack[i];
+ switch (e->type)
+ {
+ case RE_list_start:
+ break;
+ case RE_list:
+ case RE_list_dot:
+ mark_object (e->u.list.head);
+ mark_object (e->u.list.tail);
+ break;
+ case RE_vector:
+ case RE_record:
+ case RE_char_table:
+ case RE_sub_char_table:
+ case RE_byte_code:
+ case RE_string_props:
+ mark_object (e->u.vector.elems);
+ break;
+ case RE_special:
+ mark_object (e->u.special.symbol);
+ break;
+ case RE_numbered:
+ mark_object (e->u.numbered.number);
+ mark_object (e->u.numbered.placeholder);
+ break;
}
- else if (c == 'x' || c == 'X')
- return read_integer (readcharfun, 16, stackbuf);
- else if (c == 'o' || c == 'O')
- return read_integer (readcharfun, 8, stackbuf);
- else if (c == 'b' || c == 'B')
- return read_integer (readcharfun, 2, stackbuf);
+ }
+}
- UNREAD (c);
- invalid_syntax ("#", readcharfun);
+static inline struct read_stack_entry *
+read_stack_top (void)
+{
+ eassume (rdstack.sp > 0);
+ return &rdstack.stack[rdstack.sp - 1];
+}
- case ';':
- while ((c = READCHAR) >= 0 && c != '\n');
- goto retry;
+static inline struct read_stack_entry *
+read_stack_pop (void)
+{
+ eassume (rdstack.sp > 0);
+ return &rdstack.stack[--rdstack.sp];
+}
- case '\'':
- return list2 (Qquote, read0 (readcharfun));
+static inline bool
+read_stack_empty_p (ptrdiff_t base_sp)
+{
+ return rdstack.sp <= base_sp;
+}
- case '`':
- return list2 (Qbackquote, read0 (readcharfun));
+NO_INLINE static void
+grow_read_stack (void)
+{
+ struct read_stack *rs = &rdstack;
+ eassert (rs->sp == rs->size);
+ rs->stack = xpalloc (rs->stack, &rs->size, 1, -1, sizeof *rs->stack);
+ eassert (rs->sp < rs->size);
+}
- case ',':
- {
- Lisp_Object comma_type = Qnil;
- Lisp_Object value;
- int ch = READCHAR;
+static inline void
+read_stack_push (struct read_stack_entry e)
+{
+ if (rdstack.sp >= rdstack.size)
+ grow_read_stack ();
+ rdstack.stack[rdstack.sp++] = e;
+}
- if (ch == '@')
- comma_type = Qcomma_at;
- else
- {
- if (ch >= 0) UNREAD (ch);
- comma_type = Qcomma;
- }
- value = read0 (readcharfun);
- return list2 (comma_type, value);
- }
- case '?':
- {
- int modifiers;
- int next_char;
- bool ok;
+/* Read a Lisp object.
+ If LOCATE_SYMS is true, symbols are read with position. */
+static Lisp_Object
+read0 (Lisp_Object readcharfun, bool locate_syms)
+{
+ char stackbuf[stackbufsize];
+ char *read_buffer = stackbuf;
+ ptrdiff_t read_buffer_size = sizeof stackbuf;
+ char *heapbuf = NULL;
+ specpdl_ref count = SPECPDL_INDEX ();
- c = READCHAR;
- if (c < 0)
- end_of_file_error ();
-
- /* Accept `single space' syntax like (list ? x) where the
- whitespace character is SPC or TAB.
- Other literal whitespace like NL, CR, and FF are not accepted,
- as there are well-established escape sequences for these. */
- if (c == ' ' || c == '\t')
- return make_fixnum (c);
-
- if (c == '(' || c == ')' || c == '[' || c == ']'
- || c == '"' || c == ';')
+ ptrdiff_t base_sp = rdstack.sp;
+
+ bool uninterned_symbol;
+ bool skip_shorthand;
+
+ /* Read an object into `obj'. */
+ read_obj: ;
+ Lisp_Object obj;
+ bool multibyte;
+ int c = READCHAR_REPORT_MULTIBYTE (&multibyte);
+ if (c < 0)
+ end_of_file_error ();
+
+ switch (c)
+ {
+ case '(':
+ read_stack_push ((struct read_stack_entry) {.type = RE_list_start});
+ goto read_obj;
+
+ case ')':
+ if (read_stack_empty_p (base_sp))
+ invalid_syntax (")", readcharfun);
+ switch (read_stack_top ()->type)
+ {
+ case RE_list_start:
+ read_stack_pop ();
+ obj = Qnil;
+ break;
+ case RE_list:
+ obj = read_stack_pop ()->u.list.head;
+ break;
+ case RE_record:
{
- CHECK_LIST (Vlread_unescaped_character_literals);
- Lisp_Object char_obj = make_fixed_natnum (c);
- if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals)))
- Vlread_unescaped_character_literals =
- Fcons (char_obj, Vlread_unescaped_character_literals);
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ Lisp_Object elems = Fnreverse (read_stack_pop ()->u.vector.elems);
+ if (NILP (elems))
+ invalid_syntax ("#s", readcharfun);
+
+ if (BASE_EQ (XCAR (elems), Qhash_table))
+ obj = hash_table_from_plist (XCDR (elems));
+ else
+ obj = record_from_list (elems);
+ break;
}
+ case RE_string_props:
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ obj = string_props_from_rev_list (read_stack_pop () ->u.vector.elems,
+ readcharfun);
+ break;
+ default:
+ invalid_syntax (")", readcharfun);
+ }
+ break;
- if (c == '\\')
- c = read_escape (readcharfun, 0);
- modifiers = c & CHAR_MODIFIER_MASK;
- c &= ~CHAR_MODIFIER_MASK;
- if (CHAR_BYTE8_P (c))
- c = CHAR_TO_BYTE8 (c);
- c |= modifiers;
-
- next_char = READCHAR;
- ok = (next_char <= 040
- || (next_char < 0200
- && strchr ("\"';()[]#?`,.", next_char) != NULL));
- UNREAD (next_char);
- if (ok)
- return make_fixnum (c);
-
- invalid_syntax ("?", readcharfun);
- }
+ case '[':
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_vector,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ /* FIXME: should vectors be read with locate_syms=false? */
+ goto read_obj;
- case '"':
+ case ']':
+ if (read_stack_empty_p (base_sp))
+ invalid_syntax ("]", readcharfun);
+ switch (read_stack_top ()->type)
+ {
+ case RE_vector:
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ obj = vector_from_rev_list (read_stack_pop ()->u.vector.elems);
+ break;
+ case RE_byte_code:
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ obj = bytecode_from_rev_list (read_stack_pop ()->u.vector.elems,
+ readcharfun);
+ break;
+ case RE_char_table:
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ obj = char_table_from_rev_list (read_stack_pop ()->u.vector.elems,
+ readcharfun);
+ break;
+ case RE_sub_char_table:
+ locate_syms = read_stack_top ()->u.vector.old_locate_syms;
+ obj = sub_char_table_from_rev_list (read_stack_pop ()->u.vector.elems,
+ readcharfun);
+ break;
+ default:
+ invalid_syntax ("]", readcharfun);
+ break;
+ }
+ break;
+
+ case '#':
{
- ptrdiff_t count = SPECPDL_INDEX ();
- char *read_buffer = stackbuf;
- ptrdiff_t read_buffer_size = sizeof stackbuf;
- char *heapbuf = NULL;
- char *p = read_buffer;
- char *end = read_buffer + read_buffer_size;
- int ch;
- /* True if we saw an escape sequence specifying
- a multibyte character. */
- bool force_multibyte = false;
- /* True if we saw an escape sequence specifying
- a single-byte character. */
- bool force_singlebyte = false;
- bool cancel = false;
- ptrdiff_t nchars = 0;
-
- while ((ch = READCHAR) >= 0
- && ch != '\"')
+ int ch = READCHAR;
+ switch (ch)
{
- if (end - p < MAX_MULTIBYTE_LENGTH)
+ case '\'':
+ /* #'X -- special syntax for (function X) */
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_special,
+ .u.special.symbol = Qfunction,
+ });
+ goto read_obj;
+
+ case '#':
+ /* ## -- the empty symbol */
+ obj = Fintern (empty_unibyte_string, Qnil);
+ break;
+
+ case 's':
+ /* #s(...) -- a record or hash-table */
+ ch = READCHAR;
+ if (ch != '(')
{
- ptrdiff_t offset = p - read_buffer;
- read_buffer = grow_read_buffer (read_buffer, offset,
- &heapbuf, &read_buffer_size,
- count);
- p = read_buffer + offset;
- end = read_buffer + read_buffer_size;
+ UNREAD (ch);
+ invalid_syntax ("#s", readcharfun);
}
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_record,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ locate_syms = false;
+ goto read_obj;
+
+ case '^':
+ /* #^[...] -- char-table
+ #^^[...] -- sub-char-table */
+ ch = READCHAR;
+ if (ch == '^')
+ {
+ ch = READCHAR;
+ if (ch == '[')
+ {
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_sub_char_table,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ locate_syms = false;
+ goto read_obj;
+ }
+ else
+ {
+ UNREAD (ch);
+ invalid_syntax ("#^^", readcharfun);
+ }
+ }
+ else if (ch == '[')
+ {
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_char_table,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ locate_syms = false;
+ goto read_obj;
+ }
+ else
+ {
+ UNREAD (ch);
+ invalid_syntax ("#^", readcharfun);
+ }
+
+ case '(':
+ /* #(...) -- string with properties */
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_string_props,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ locate_syms = false;
+ goto read_obj;
+
+ case '[':
+ /* #[...] -- byte-code */
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_byte_code,
+ .u.vector.elems = Qnil,
+ .u.vector.old_locate_syms = locate_syms,
+ });
+ locate_syms = false;
+ goto read_obj;
+
+ case '&':
+ /* #&N"..." -- bool-vector */
+ obj = read_bool_vector (stackbuf, readcharfun);
+ break;
- if (ch == '\\')
+ case '!':
+ /* #! appears at the beginning of an executable file.
+ Skip the rest of the line. */
+ {
+ int c;
+ do
+ c = READCHAR;
+ while (c >= 0 && c != '\n');
+ goto read_obj;
+ }
+
+ case 'x':
+ case 'X':
+ obj = read_integer (readcharfun, 16, stackbuf);
+ break;
+
+ case 'o':
+ case 'O':
+ obj = read_integer (readcharfun, 8, stackbuf);
+ break;
+
+ case 'b':
+ case 'B':
+ obj = read_integer (readcharfun, 2, stackbuf);
+ break;
+
+ case '@':
+ /* #@NUMBER is used to skip NUMBER following bytes.
+ That's used in .elc files to skip over doc strings
+ and function definitions that can be loaded lazily. */
+ skip_lazy_string (readcharfun);
+ goto read_obj;
+
+ case '$':
+ /* #$ -- reference to lazy-loaded string */
+ obj = Vload_file_name;
+ break;
+
+ case ':':
+ /* #:X -- uninterned symbol */
+ c = READCHAR;
+ if (c <= 32 || c == NO_BREAK_SPACE
+ || c == '"' || c == '\'' || c == ';' || c == '#'
+ || c == '(' || c == ')' || c == '[' || c == ']'
+ || c == '`' || c == ',')
{
- int modifiers;
+ /* No symbol character follows: this is the empty symbol. */
+ UNREAD (c);
+ obj = Fmake_symbol (empty_unibyte_string);
+ break;
+ }
+ uninterned_symbol = true;
+ skip_shorthand = false;
+ goto read_symbol;
- ch = read_escape (readcharfun, 1);
+ case '_':
+ /* #_X -- symbol without shorthand */
+ c = READCHAR;
+ if (c <= 32 || c == NO_BREAK_SPACE
+ || c == '"' || c == '\'' || c == ';' || c == '#'
+ || c == '(' || c == ')' || c == '[' || c == ']'
+ || c == '`' || c == ',')
+ {
+ /* No symbol character follows: this is the empty symbol. */
+ UNREAD (c);
+ obj = Fintern (empty_unibyte_string, Qnil);
+ break;
+ }
+ uninterned_symbol = false;
+ skip_shorthand = true;
+ goto read_symbol;
- /* CH is -1 if \ newline or \ space has just been seen. */
- if (ch == -1)
+ default:
+ if (ch >= '0' && ch <= '9')
+ {
+ /* #N=OBJ or #N# -- first read the number N */
+ EMACS_INT n = ch - '0';
+ int c;
+ for (;;)
{
- if (p == read_buffer)
- cancel = true;
- continue;
+ c = READCHAR;
+ if (c < '0' || c > '9')
+ break;
+ if (INT_MULTIPLY_WRAPV (n, 10, &n)
+ || INT_ADD_WRAPV (n, c - '0', &n))
+ invalid_syntax ("#", readcharfun);
}
-
- modifiers = ch & CHAR_MODIFIER_MASK;
- ch = ch & ~CHAR_MODIFIER_MASK;
-
- if (CHAR_BYTE8_P (ch))
- force_singlebyte = true;
- else if (! ASCII_CHAR_P (ch))
- force_multibyte = true;
- else /* I.e. ASCII_CHAR_P (ch). */
+ if (c == 'r' || c == 'R')
{
- /* Allow `\C- ' and `\C-?'. */
- if (modifiers == CHAR_CTL)
- {
- if (ch == ' ')
- ch = 0, modifiers = 0;
- else if (ch == '?')
- ch = 127, modifiers = 0;
- }
- if (modifiers & CHAR_SHIFT)
+ /* #NrDIGITS -- radix-N number */
+ if (n < 0 || n > 36)
+ invalid_radix_integer (n, stackbuf, readcharfun);
+ obj = read_integer (readcharfun, n, stackbuf);
+ break;
+ }
+ else if (n <= MOST_POSITIVE_FIXNUM && !NILP (Vread_circle))
+ {
+ if (c == '=')
{
- /* Shift modifier is valid only with [A-Za-z]. */
- if (ch >= 'A' && ch <= 'Z')
- modifiers &= ~CHAR_SHIFT;
- else if (ch >= 'a' && ch <= 'z')
- ch -= ('a' - 'A'), modifiers &= ~CHAR_SHIFT;
+ /* #N=OBJ -- assign number N to OBJ */
+ Lisp_Object placeholder = Fcons (Qnil, Qnil);
+
+ struct Lisp_Hash_Table *h
+ = XHASH_TABLE (read_objects_map);
+ Lisp_Object number = make_fixnum (n);
+ Lisp_Object hash;
+ ptrdiff_t i = hash_lookup (h, number, &hash);
+ if (i >= 0)
+ /* Not normal, but input could be malformed. */
+ set_hash_value_slot (h, i, placeholder);
+ else
+ hash_put (h, number, placeholder, hash);
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_numbered,
+ .u.numbered.number = number,
+ .u.numbered.placeholder = placeholder,
+ });
+ goto read_obj;
}
-
- if (modifiers & CHAR_META)
+ else if (c == '#')
{
- /* Move the meta bit to the right place for a
- string. */
- modifiers &= ~CHAR_META;
- ch = BYTE8_TO_CHAR (ch | 0x80);
- force_singlebyte = true;
+ /* #N# -- reference to numbered object */
+ struct Lisp_Hash_Table *h
+ = XHASH_TABLE (read_objects_map);
+ ptrdiff_t i = hash_lookup (h, make_fixnum (n), NULL);
+ if (i < 0)
+ invalid_syntax ("#", readcharfun);
+ obj = HASH_VALUE (h, i);
+ break;
}
+ else
+ invalid_syntax ("#", readcharfun);
}
-
- /* Any modifiers remaining are invalid. */
- if (modifiers)
- invalid_syntax ("Invalid modifier in string", readcharfun);
- p += CHAR_STRING (ch, (unsigned char *) p);
+ else
+ invalid_syntax ("#", readcharfun);
}
else
- {
- p += CHAR_STRING (ch, (unsigned char *) p);
- if (CHAR_BYTE8_P (ch))
- force_singlebyte = true;
- else if (! ASCII_CHAR_P (ch))
- force_multibyte = true;
- }
- nchars++;
+ invalid_syntax ("#", readcharfun);
}
+ break;
+ }
+
+ case '?':
+ obj = read_char_literal (readcharfun);
+ break;
+
+ case '"':
+ obj = read_string_literal (stackbuf, readcharfun);
+ break;
- if (ch < 0)
- end_of_file_error ();
+ case '\'':
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_special,
+ .u.special.symbol = Qquote,
+ });
+ goto read_obj;
- /* If purifying, and string starts with \ newline,
- return zero instead. This is for doc strings
- that we are really going to find in etc/DOC.nn.nn. */
- if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
- return unbind_to (count, make_fixnum (0));
+ case '`':
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_special,
+ .u.special.symbol = Qbackquote,
+ });
+ goto read_obj;
- if (! force_multibyte && force_singlebyte)
+ case ',':
+ {
+ int ch = READCHAR;
+ Lisp_Object sym;
+ if (ch == '@')
+ sym = Qcomma_at;
+ else
{
- /* READ_BUFFER contains raw 8-bit bytes and no multibyte
- forms. Convert it to unibyte. */
- nchars = str_as_unibyte ((unsigned char *) read_buffer,
- p - read_buffer);
- p = read_buffer + nchars;
+ if (ch >= 0)
+ UNREAD (ch);
+ sym = Qcomma;
}
+ read_stack_push ((struct read_stack_entry) {
+ .type = RE_special,
+ .u.special.symbol = sym,
+ });
+ goto read_obj;
+ }
- Lisp_Object result
- = make_specified_string (read_buffer, nchars, p - read_buffer,
- (force_multibyte
- || (p - read_buffer != nchars)));
- return unbind_to (count, result);
+ case ';':
+ {
+ int c;
+ do
+ c = READCHAR;
+ while (c >= 0 && c != '\n');
+ goto read_obj;
}
case '.':
{
- int next_char = READCHAR;
- UNREAD (next_char);
-
- if (next_char <= 040
- || (next_char < 0200
- && strchr ("\"';([#?`,", next_char) != NULL))
+ int nch = READCHAR;
+ UNREAD (nch);
+ if (nch <= 32 || nch == NO_BREAK_SPACE
+ || nch == '"' || nch == '\'' || nch == ';'
+ || nch == '(' || nch == '[' || nch == '#'
+ || nch == '?' || nch == '`' || nch == ',')
{
- *pch = c;
- return Qnil;
+ if (!read_stack_empty_p (base_sp)
+ && read_stack_top ()->type == RE_list)
+ {
+ read_stack_top ()->type = RE_list_dot;
+ goto read_obj;
+ }
+ invalid_syntax (".", readcharfun);
}
}
- /* The atom-reading loop below will now loop at least once,
- assuring that we will not try to UNREAD two characters in a
- row. */
+ /* may be a number or symbol starting with a dot */
FALLTHROUGH;
+
default:
- if (c <= 040) goto retry;
- if (c == NO_BREAK_SPACE)
- goto retry;
+ if (c <= 32 || c == NO_BREAK_SPACE)
+ goto read_obj;
+ uninterned_symbol = false;
+ skip_shorthand = false;
+ /* symbol or number */
read_symbol:
{
- ptrdiff_t count = SPECPDL_INDEX ();
- char *read_buffer = stackbuf;
- ptrdiff_t read_buffer_size = sizeof stackbuf;
- char *heapbuf = NULL;
char *p = read_buffer;
char *end = read_buffer + read_buffer_size;
bool quoted = false;
- EMACS_INT start_position = readchar_count - 1;
+ EMACS_INT start_position = readchar_offset - 1;
do
{
@@ -3744,7 +4116,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
if (c == '\\')
{
c = READCHAR;
- if (c == -1)
+ if (c < 0)
end_of_file_error ();
quoted = true;
}
@@ -3755,94 +4127,205 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
*p++ = c;
c = READCHAR;
}
- while (c > 040
+ while (c > 32
&& c != NO_BREAK_SPACE
- && (c >= 0200
- || strchr ("\"';()[]#`,", c) == NULL));
+ && (c >= 128
+ || !( c == '"' || c == '\'' || c == ';' || c == '#'
+ || c == '(' || c == ')' || c == '[' || c == ']'
+ || c == '`' || c == ',')));
*p = 0;
ptrdiff_t nbytes = p - read_buffer;
UNREAD (c);
- if (!quoted && !uninterned_symbol && !skip_shorthand)
+ /* Only attempt to parse the token as a number if it starts as one. */
+ char c0 = read_buffer[0];
+ if (((c0 >= '0' && c0 <= '9') || c0 == '.' || c0 == '-' || c0 == '+')
+ && !quoted && !uninterned_symbol && !skip_shorthand)
{
ptrdiff_t len;
Lisp_Object result = string_to_number (read_buffer, 10, &len);
- if (! NILP (result) && len == nbytes)
- return unbind_to (count, result);
+ if (!NILP (result) && len == nbytes)
+ {
+ obj = result;
+ break;
+ }
}
- {
- Lisp_Object result;
- ptrdiff_t nchars
- = (multibyte
- ? multibyte_chars_in_text ((unsigned char *) read_buffer,
- nbytes)
- : nbytes);
-
- if (uninterned_symbol)
- {
- Lisp_Object name
- = ((! NILP (Vpurify_flag)
- ? make_pure_string : make_specified_string)
- (read_buffer, nchars, nbytes, multibyte));
- result = Fmake_symbol (name);
- }
- else
- {
- /* Don't create the string object for the name unless
- we're going to retain it in a new symbol.
-
- Like intern_1 but supports multibyte names. */
- Lisp_Object obarray = check_obarray (Vobarray);
-
- char* longhand = NULL;
- ptrdiff_t longhand_chars = 0;
- ptrdiff_t longhand_bytes = 0;
-
- Lisp_Object tem;
- if (skip_shorthand
- /* The following ASCII characters are used in the
- only "core" Emacs Lisp symbols that are comprised
- entirely of characters that have the 'symbol
- constituent' syntax. We exempt them from
- transforming according to shorthands. */
- || strspn (read_buffer, "^*+-/<=>_|") >= nbytes)
- tem = oblookup (obarray, read_buffer, nchars, nbytes);
- else
- tem = oblookup_considering_shorthand (obarray, read_buffer,
+
+ /* symbol, possibly uninterned */
+ ptrdiff_t nchars
+ = (multibyte
+ ? multibyte_chars_in_text ((unsigned char *)read_buffer, nbytes)
+ : nbytes);
+ Lisp_Object result;
+ if (uninterned_symbol)
+ {
+ Lisp_Object name
+ = (!NILP (Vpurify_flag)
+ ? make_pure_string (read_buffer, nchars, nbytes, multibyte)
+ : make_specified_string (read_buffer, nchars, nbytes,
+ multibyte));
+ result = Fmake_symbol (name);
+ }
+ else
+ {
+ /* Don't create the string object for the name unless
+ we're going to retain it in a new symbol.
+
+ Like intern_1 but supports multibyte names. */
+ Lisp_Object obarray = check_obarray (Vobarray);
+
+ char *longhand = NULL;
+ ptrdiff_t longhand_chars = 0;
+ ptrdiff_t longhand_bytes = 0;
+
+ Lisp_Object found;
+ if (skip_shorthand
+ /* We exempt characters used in the "core" Emacs Lisp
+ symbols that are comprised entirely of characters
+ that have the 'symbol constituent' syntax from
+ transforming according to shorthands. */
+ || symbol_char_span (read_buffer) >= nbytes)
+ found = oblookup (obarray, read_buffer, nchars, nbytes);
+ else
+ found = oblookup_considering_shorthand (obarray, read_buffer,
nchars, nbytes, &longhand,
&longhand_chars,
&longhand_bytes);
- if (SYMBOLP (tem))
- result = tem;
- else if (longhand)
- {
- Lisp_Object name
- = make_specified_string (longhand, longhand_chars,
- longhand_bytes, multibyte);
- xfree (longhand);
- result = intern_driver (name, obarray, tem);
- }
- else
- {
- Lisp_Object name
- = make_specified_string (read_buffer, nchars, nbytes,
- multibyte);
- result = intern_driver (name, obarray, tem);
- }
- }
+ if (SYMBOLP (found))
+ result = found;
+ else if (longhand)
+ {
+ Lisp_Object name = make_specified_string (longhand,
+ longhand_chars,
+ longhand_bytes,
+ multibyte);
+ xfree (longhand);
+ result = intern_driver (name, obarray, found);
+ }
+ else
+ {
+ Lisp_Object name = make_specified_string (read_buffer, nchars,
+ nbytes, multibyte);
+ result = intern_driver (name, obarray, found);
+ }
+ }
+ if (locate_syms && !NILP (result))
+ result = build_symbol_with_pos (result,
+ make_fixnum (start_position));
- if (EQ (Vread_with_symbol_positions, Qt)
- || EQ (Vread_with_symbol_positions, readcharfun))
- Vread_symbol_positions_list
- = Fcons (Fcons (result, make_fixnum (start_position)),
- Vread_symbol_positions_list);
- return unbind_to (count, result);
- }
+ obj = result;
+ break;
}
}
+
+ /* We have read an object in `obj'. Use the stack to decide what to
+ do with it. */
+ while (rdstack.sp > base_sp)
+ {
+ struct read_stack_entry *e = read_stack_top ();
+ switch (e->type)
+ {
+ case RE_list_start:
+ e->type = RE_list;
+ e->u.list.head = e->u.list.tail = Fcons (obj, Qnil);
+ goto read_obj;
+
+ case RE_list:
+ {
+ Lisp_Object tl = Fcons (obj, Qnil);
+ XSETCDR (e->u.list.tail, tl);
+ e->u.list.tail = tl;
+ goto read_obj;
+ }
+
+ case RE_list_dot:
+ {
+ skip_space_and_comments (readcharfun);
+ int ch = READCHAR;
+ if (ch != ')')
+ invalid_syntax ("expected )", readcharfun);
+ XSETCDR (e->u.list.tail, obj);
+ read_stack_pop ();
+ obj = e->u.list.head;
+ break;
+ }
+
+ case RE_vector:
+ case RE_record:
+ case RE_char_table:
+ case RE_sub_char_table:
+ case RE_byte_code:
+ case RE_string_props:
+ e->u.vector.elems = Fcons (obj, e->u.vector.elems);
+ goto read_obj;
+
+ case RE_special:
+ read_stack_pop ();
+ obj = list2 (e->u.special.symbol, obj);
+ break;
+
+ case RE_numbered:
+ {
+ read_stack_pop ();
+ Lisp_Object placeholder = e->u.numbered.placeholder;
+ if (CONSP (obj))
+ {
+ if (BASE_EQ (obj, placeholder))
+ /* Catch silly games like #1=#1# */
+ invalid_syntax ("nonsensical self-reference", readcharfun);
+
+ /* Optimisation: since the placeholder is already
+ a cons, repurpose it as the actual value.
+ This allows us to skip the substitution below,
+ since the placeholder is already referenced
+ inside OBJ at the appropriate places. */
+ Fsetcar (placeholder, XCAR (obj));
+ Fsetcdr (placeholder, XCDR (obj));
+
+ struct Lisp_Hash_Table *h2
+ = XHASH_TABLE (read_objects_completed);
+ Lisp_Object hash;
+ ptrdiff_t i = hash_lookup (h2, placeholder, &hash);
+ eassert (i < 0);
+ hash_put (h2, placeholder, Qnil, hash);
+ obj = placeholder;
+ }
+ else
+ {
+ /* If it can be recursive, remember it for future
+ substitutions. */
+ if (!SYMBOLP (obj) && !NUMBERP (obj)
+ && !(STRINGP (obj) && !string_intervals (obj)))
+ {
+ struct Lisp_Hash_Table *h2
+ = XHASH_TABLE (read_objects_completed);
+ Lisp_Object hash;
+ ptrdiff_t i = hash_lookup (h2, obj, &hash);
+ eassert (i < 0);
+ hash_put (h2, obj, Qnil, hash);
+ }
+
+ /* Now put it everywhere the placeholder was... */
+ Flread__substitute_object_in_subtree (obj, placeholder,
+ read_objects_completed);
+
+ /* ...and #n# will use the real value from now on. */
+ struct Lisp_Hash_Table *h = XHASH_TABLE (read_objects_map);
+ Lisp_Object hash;
+ ptrdiff_t i = hash_lookup (h, e->u.numbered.number, &hash);
+ eassert (i >= 0);
+ set_hash_value_slot (h, i, obj);
+ }
+ break;
+ }
+ }
+ }
+
+ return unbind_to (count, obj);
}
+
DEFUN ("lread--substitute-object-in-subtree",
Flread__substitute_object_in_subtree,
@@ -4089,212 +4572,6 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
}
-static Lisp_Object
-read_vector (Lisp_Object readcharfun, bool bytecodeflag)
-{
- Lisp_Object tem = read_list (1, readcharfun);
- ptrdiff_t size = list_length (tem);
- Lisp_Object vector = make_nil_vector (size);
-
- /* Avoid accessing past the end of a vector if the vector is too
- small to be valid for bytecode. */
- bytecodeflag &= COMPILED_STACK_DEPTH < size;
-
- Lisp_Object *ptr = XVECTOR (vector)->contents;
- for (ptrdiff_t i = 0; i < size; i++)
- {
- Lisp_Object item = Fcar (tem);
- /* If `load-force-doc-strings' is t when reading a lazily-loaded
- bytecode object, the docstring containing the bytecode and
- constants values must be treated as unibyte and passed to
- Fread, to get the actual bytecode string and constants vector. */
- if (bytecodeflag && load_force_doc_strings)
- {
- if (i == COMPILED_BYTECODE)
- {
- if (!STRINGP (item))
- error ("Invalid byte code");
-
- /* Delay handling the bytecode slot until we know whether
- it is lazily-loaded (we can tell by whether the
- constants slot is nil). */
- ASET (vector, COMPILED_CONSTANTS, item);
- item = Qnil;
- }
- else if (i == COMPILED_CONSTANTS)
- {
- Lisp_Object bytestr = ptr[COMPILED_CONSTANTS];
-
- if (NILP (item))
- {
- /* Coerce string to unibyte (like string-as-unibyte,
- but without generating extra garbage and
- guaranteeing no change in the contents). */
- STRING_SET_CHARS (bytestr, SBYTES (bytestr));
- STRING_SET_UNIBYTE (bytestr);
-
- item = Fread (Fcons (bytestr, readcharfun));
- if (!CONSP (item))
- error ("Invalid byte code");
-
- struct Lisp_Cons *otem = XCONS (item);
- bytestr = XCAR (item);
- item = XCDR (item);
- free_cons (otem);
- }
-
- /* Now handle the bytecode slot. */
- ASET (vector, COMPILED_BYTECODE, bytestr);
- }
- else if (i == COMPILED_DOC_STRING
- && STRINGP (item)
- && ! STRING_MULTIBYTE (item))
- {
- if (EQ (readcharfun, Qget_emacs_mule_file_char))
- item = Fdecode_coding_string (item, Qemacs_mule, Qnil, Qnil);
- else
- item = Fstring_as_multibyte (item);
- }
- }
- ASET (vector, i, item);
- struct Lisp_Cons *otem = XCONS (tem);
- tem = Fcdr (tem);
- free_cons (otem);
- }
- return vector;
-}
-
-/* FLAG means check for ']' to terminate rather than ')' and '.'. */
-
-static Lisp_Object
-read_list (bool flag, Lisp_Object readcharfun)
-{
- Lisp_Object val, tail;
- Lisp_Object elt, tem;
- /* 0 is the normal case.
- 1 means this list is a doc reference; replace it with the number 0.
- 2 means this list is a doc reference; replace it with the doc string. */
- int doc_reference = 0;
-
- /* Initialize this to 1 if we are reading a list. */
- bool first_in_list = flag <= 0;
-
- val = Qnil;
- tail = Qnil;
-
- while (1)
- {
- int ch;
- elt = read1 (readcharfun, &ch, first_in_list);
-
- first_in_list = 0;
-
- /* While building, if the list starts with #$, treat it specially. */
- if (EQ (elt, Vload_file_name)
- && ! NILP (elt))
- {
- if (!NILP (Vpurify_flag))
- doc_reference = 0;
- else if (load_force_doc_strings)
- doc_reference = 2;
- }
- if (ch)
- {
- if (flag > 0)
- {
- if (ch == ']')
- return val;
- invalid_syntax (") or . in a vector", readcharfun);
- }
- if (ch == ')')
- return val;
- if (ch == '.')
- {
- if (!NILP (tail))
- XSETCDR (tail, read0 (readcharfun));
- else
- val = read0 (readcharfun);
- read1 (readcharfun, &ch, 0);
-
- if (ch == ')')
- {
- if (doc_reference == 2 && FIXNUMP (XCDR (val)))
- {
- char *saved = NULL;
- file_offset saved_position;
- /* Get a doc string from the file we are loading.
- If it's in saved_doc_string, get it from there.
-
- Here, we don't know if the string is a
- bytecode string or a doc string. As a
- bytecode string must be unibyte, we always
- return a unibyte string. If it is actually a
- doc string, caller must make it
- multibyte. */
-
- /* Position is negative for user variables. */
- EMACS_INT pos = eabs (XFIXNUM (XCDR (val)));
- if (pos >= saved_doc_string_position
- && pos < (saved_doc_string_position
- + saved_doc_string_length))
- {
- saved = saved_doc_string;
- saved_position = saved_doc_string_position;
- }
- /* Look in prev_saved_doc_string the same way. */
- else if (pos >= prev_saved_doc_string_position
- && pos < (prev_saved_doc_string_position
- + prev_saved_doc_string_length))
- {
- saved = prev_saved_doc_string;
- saved_position = prev_saved_doc_string_position;
- }
- if (saved)
- {
- ptrdiff_t start = pos - saved_position;
- ptrdiff_t from, to;
-
- /* Process quoting with ^A,
- and find the end of the string,
- which is marked with ^_ (037). */
- for (from = start, to = start;
- saved[from] != 037;)
- {
- int c = saved[from++];
- if (c == 1)
- {
- c = saved[from++];
- saved[to++] = (c == 1 ? c
- : c == '0' ? 0
- : c == '_' ? 037
- : c);
- }
- else
- saved[to++] = c;
- }
-
- return make_unibyte_string (saved + start,
- to - start);
- }
- else
- return get_doc_string (val, 1, 0);
- }
-
- return val;
- }
- invalid_syntax (". in wrong context", readcharfun);
- }
- invalid_syntax ("] in a list", readcharfun);
- }
- tem = list1 (elt);
- if (!NILP (tail))
- XSETCDR (tail, tem);
- else
- val = tem;
- tail = tem;
- }
-}
-
static Lisp_Object initial_obarray;
/* `oblookup' stores the bucket number here, for the sake of Funintern. */
@@ -4401,7 +4678,7 @@ define_symbol (Lisp_Object sym, char const *str)
/* Qunbound is uninterned, so that it's not confused with any symbol
'unbound' created by a Lisp program. */
- if (! EQ (sym, Qunbound))
+ if (! BASE_EQ (sym, Qunbound))
{
Lisp_Object bucket = oblookup (initial_obarray, str, len, len);
eassert (FIXNUMP (bucket));
@@ -4589,10 +4866,12 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff
hash = hash_string (ptr, size_byte) % obsize;
bucket = AREF (obarray, hash);
oblookup_last_bucket_number = hash;
- if (EQ (bucket, make_fixnum (0)))
+ if (BASE_EQ (bucket, make_fixnum (0)))
;
else if (!SYMBOLP (bucket))
- error ("Bad data in guts of obarray"); /* Like CADR error message. */
+ /* Like CADR error message. */
+ xsignal2 (Qwrong_type_argument, Qobarrayp,
+ build_string ("Bad data in guts of obarray"));
else
for (tail = bucket; ; XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next))
{
@@ -4609,7 +4888,7 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff
/* Like 'oblookup', but considers 'Vread_symbol_shorthands',
potentially recognizing that IN is shorthand for some other
- longhand name, which is then then placed in OUT. In that case,
+ longhand name, which is then placed in OUT. In that case,
memory is malloc'ed for OUT (which the caller must free) while
SIZE_OUT and SIZE_BYTE_OUT respectively hold the character and byte
sizes of the transformed symbol name. If IN is not recognized
@@ -5090,6 +5369,7 @@ void
syms_of_lread (void)
{
defsubr (&Sread);
+ defsubr (&Sread_positioning_symbols);
defsubr (&Sread_from_string);
defsubr (&Slread__substitute_object_in_subtree);
defsubr (&Sintern);
@@ -5123,35 +5403,6 @@ This variable is obsolete as of Emacs 28.1 and should not be used. */);
See documentation of `read' for possible values. */);
Vstandard_input = Qt;
- DEFVAR_LISP ("read-with-symbol-positions", Vread_with_symbol_positions,
- doc: /* If non-nil, add position of read symbols to `read-symbol-positions-list'.
-
-If this variable is a buffer, then only forms read from that buffer
-will be added to `read-symbol-positions-list'.
-If this variable is t, then all read forms will be added.
-The effect of all other values other than nil are not currently
-defined, although they may be in the future.
-
-The positions are relative to the last call to `read' or
-`read-from-string'. It is probably a bad idea to set this variable at
-the toplevel; bind it instead. */);
- Vread_with_symbol_positions = Qnil;
-
- DEFVAR_LISP ("read-symbol-positions-list", Vread_symbol_positions_list,
- doc: /* A list mapping read symbols to their positions.
-This variable is modified during calls to `read' or
-`read-from-string', but only when `read-with-symbol-positions' is
-non-nil.
-
-Each element of the list looks like (SYMBOL . CHAR-POSITION), where
-CHAR-POSITION is an integer giving the offset of that occurrence of the
-symbol from the position where `read' or `read-from-string' started.
-
-Note that a symbol will appear multiple times in this list, if it was
-read multiple times. The list is in the same order as the symbols
-were read in. */);
- Vread_symbol_positions_list = Qnil;
-
DEFVAR_LISP ("read-circle", Vread_circle,
doc: /* Non-nil means read recursive structures using #N= and #N# syntax. */);
Vread_circle = Qt;
@@ -5234,12 +5485,9 @@ for symbols and features not associated with any file.
The remaining ENTRIES in the alist element describe the functions and
variables defined in that file, the features provided, and the
features required. Each entry has the form `(provide . FEATURE)',
-`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)',
-`(defface . SYMBOL)', `(define-type . SYMBOL)',
-`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'.
-Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry,
-and mean that SYMBOL was an autoload before this file redefined it
-as a function. In addition, entries may also be single symbols,
+`(require . FEATURE)', `(defun . FUNCTION)', `(defface . SYMBOL)',
+ `(define-type . SYMBOL)', or `(cl-defmethod METHOD SPECIALIZERS)'.
+In addition, entries may also be single symbols,
which means that symbol was defined by `defvar' or `defconst'.
During preloading, the file name recorded is relative to the main Lisp
@@ -5272,7 +5520,9 @@ of the file, regardless of whether or not it has the `.elc' extension. */);
Vcurrent_load_list = Qnil;
DEFVAR_LISP ("load-read-function", Vload_read_function,
- doc: /* Function used by `load' and `eval-region' for reading expressions.
+ doc: /* Function used for reading expressions.
+It is used by `load' and `eval-region'.
+
Called with a single argument (the stream from which to read).
The default is to use the function `read'. */);
DEFSYM (Qread, "read");
@@ -5433,6 +5683,7 @@ This variable's value can only be set via file-local variables.
See Info node `(elisp)Shorthands' for more details. */);
Vread_symbol_shorthands = Qnil;
DEFSYM (Qobarray_cache, "obarray-cache");
+ DEFSYM (Qobarrayp, "obarrayp");
DEFSYM (Qmacroexp__dynvars, "macroexp--dynvars");
DEFVAR_LISP ("macroexp--dynvars", Vmacroexp__dynvars,
diff --git a/src/macfont.m b/src/macfont.m
index f623c3ca2f5..fe30908f5d6 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -57,8 +57,10 @@ static CFStringRef mac_font_create_preferred_family_for_attributes (CFDictionary
static CFIndex mac_font_shape (CTFontRef, CFStringRef,
struct mac_glyph_layout *, CFIndex,
enum lgstring_direction);
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
static CFArrayRef mac_font_copy_default_descriptors_for_language (CFStringRef);
static CFStringRef mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef, CFArrayRef);
+#endif
#if USE_CT_GLYPH_INFO
static CGGlyph mac_ctfont_get_glyph_for_cid (CTFontRef, CTCharacterCollection,
CGFontIndex);
@@ -845,7 +847,7 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
{{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
{{-0.4, 50}, /* light */
{-0.24, 87.5}, /* (semi-light + normal) / 2 */
- {0, 100}, /* normal */
+ {0, 80}, /* normal */
{0.24, 140}, /* (semi-bold + normal) / 2 */
{0.4, 200}, /* bold */
{CGFLOAT_MAX, CGFLOAT_MAX}},
@@ -927,7 +929,7 @@ macfont_descriptor_entity (CTFontDescriptorRef desc, Lisp_Object extra,
cfnumber_get_font_symbolic_traits_value (num, &sym_traits);
CFRelease (dict);
}
- if (EQ (AREF (entity, FONT_SIZE_INDEX), make_fixnum (0)))
+ if (BASE_EQ (AREF (entity, FONT_SIZE_INDEX), make_fixnum (0)))
ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute);
@@ -2651,7 +2653,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL);
val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX));
- if (CONSP (val) && EQ (XCDR (val), make_fixnum (1)))
+ if (CONSP (val) && BASE_EQ (XCDR (val), make_fixnum (1)))
macfont_info->screen_font = mac_screen_font_create_with_name (font_name,
size);
else
@@ -3570,15 +3572,17 @@ mac_font_create_preferred_family_for_attributes (CFDictionaryRef attributes)
if (languages && CFArrayGetCount (languages) > 0)
{
- if (CTGetCoreTextVersion () >= kCTVersionNumber10_9)
- values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
- else
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+ if (CTGetCoreTextVersion () < kCTVersionNumber10_9)
{
CFCharacterSetRef charset =
CFDictionaryGetValue (attributes, kCTFontCharacterSetAttribute);
result = mac_font_copy_default_name_for_charset_and_languages (charset, languages);
}
+ else
+#endif
+ values[num_values++] = CFArrayGetValueAtIndex (languages, 0);
}
if (result == NULL)
{
@@ -3997,6 +4001,7 @@ mac_ctfont_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection,
}
#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
static CFArrayRef
mac_font_copy_default_descriptors_for_language (CFStringRef language)
{
@@ -4131,6 +4136,7 @@ mac_font_copy_default_name_for_charset_and_languages (CFCharacterSetRef charset,
return result;
}
+#endif
void *
macfont_get_nsctfont (struct font *font)
diff --git a/src/macros.c b/src/macros.c
index 3d00c28838d..6b6865d9298 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -273,9 +273,15 @@ pop_kbd_macro (Lisp_Object info)
}
DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 3, 0,
- doc: /* Execute MACRO as string of editor command characters.
-MACRO can also be a vector of keyboard events. If MACRO is a symbol,
-its function definition is used.
+ doc: /* Execute MACRO as a sequence of events.
+If MACRO is a string or vector, then the events in it are executed
+exactly as if they had been input by the user.
+
+If MACRO is a symbol, its function definition is used. If that is
+another symbol, this process repeats. Eventually the result should be
+a string or vector. If the result is not a symbol, string, or vector,
+an error is signaled.
+
COUNT is a repeat count, or nil for once, or 0 for infinite loop.
Optional third arg LOOPFUNC may be a function that is called prior to
@@ -287,7 +293,7 @@ buffer before the macro is executed. */)
{
Lisp_Object final;
Lisp_Object tem;
- ptrdiff_t pdlcount = SPECPDL_INDEX ();
+ specpdl_ref pdlcount = SPECPDL_INDEX ();
EMACS_INT repeat = 1;
EMACS_INT success_count = 0;
diff --git a/src/menu.c b/src/menu.c
index 18ecaf0b0ba..eeb0c9a7e5b 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1118,10 +1118,10 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
Lisp_Object title;
const char *error_name = NULL;
Lisp_Object selection = Qnil;
- struct frame *f = NULL;
+ struct frame *f;
Lisp_Object x, y, window;
int menuflags = 0;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
if (NILP (position))
/* This is an obsolete call, which wants us to precompute the
@@ -1269,9 +1269,9 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
}
}
else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
+ /* ??? Not really clean; should be Qwindow_or_framep
but I don't want to make one now. */
- CHECK_WINDOW (window);
+ wrong_type_argument (Qwindowp, window);
xpos += check_integer_range (x,
(xpos < INT_MIN - MOST_NEGATIVE_FIXNUM
@@ -1391,9 +1391,9 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
}
#endif
-#ifdef HAVE_NS /* FIXME: ns-specific, why? --Stef */
record_unwind_protect_void (discard_menu_items);
-#endif
+
+ run_hook (Qx_pre_popup_menu_hook);
/* Display them in a menu, but not if F is the initial frame that
doesn't have its hooks set (e.g., in a batch session), because
@@ -1402,13 +1402,13 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
selection = FRAME_TERMINAL (f)->menu_show_hook (f, xpos, ypos, menuflags,
title, &error_name);
-#ifdef HAVE_NS
unbind_to (specpdl_count, Qnil);
-#else
- discard_menu_items ();
-#endif
-#ifdef HAVE_NTGUI /* FIXME: Is it really w32-specific? --Stef */
+#ifdef HAVE_NTGUI /* W32 specific because other terminals clear
+ the grab inside their `menu_show_hook's if
+ it's actually required (i.e. there isn't a
+ way to query the buttons currently held down
+ after XMenuActivate). */
if (FRAME_W32_P (f))
FRAME_DISPLAY_INFO (f)->grabbed = 0;
#endif
@@ -1602,6 +1602,14 @@ syms_of_menu (void)
staticpro (&menu_items);
DEFSYM (Qhide, "hide");
+ DEFSYM (Qx_pre_popup_menu_hook, "x-pre-popup-menu-hook");
+
+ DEFVAR_LISP ("x-pre-popup-menu-hook", Vx_pre_popup_menu_hook,
+ doc: /* Hook run before `x-popup-menu' displays a popup menu.
+It is only run before the menu is really going to be displayed. It
+won't be run if `x-popup-menu' fails or returns for some other reason
+(such as the keymap is invalid). */);
+ Vx_pre_popup_menu_hook = Qnil;
defsubr (&Sx_popup_menu);
defsubr (&Sx_popup_dialog);
diff --git a/src/minibuf.c b/src/minibuf.c
index d0e58b61f27..0fba334b22b 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -34,6 +34,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "systty.h"
#include "pdumper.h"
+#ifdef HAVE_NTGUI
+#include "w32term.h"
+#endif
+
/* List of buffers for use as minibuffers.
The first element of the list is used for the outermost minibuffer
invocation, the next element is used for a recursive minibuffer
@@ -41,7 +45,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
minibuffer recursions are encountered. */
Lisp_Object Vminibuffer_list;
-Lisp_Object Vcommand_loop_level_list;
+static Lisp_Object Vcommand_loop_level_list;
/* Data to remember during recursive minibuffer invocations. */
@@ -197,20 +201,12 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
return;
if (FRAME_LIVE_P (f)
&& !EQ (f->minibuffer_window, of->minibuffer_window)
- && WINDOW_LIVE_P (f->minibuffer_window) /* F not a tootip frame */
+ && WINDOW_LIVE_P (f->minibuffer_window) /* F not a tooltip frame */
&& WINDOW_LIVE_P (of->minibuffer_window))
{
zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
if (for_deletion && XFRAME (MB_frame) != of)
MB_frame = selected_frame;
- if (!for_deletion
- && MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
- {
- Lisp_Object old_frame;
- XSETFRAME (old_frame, of);
- Fset_frame_selected_window (old_frame,
- Fframe_first_window (old_frame), Qnil);
- }
}
}
@@ -261,7 +257,7 @@ without invoking the usual minibuffer commands. */)
static void read_minibuf_unwind (void);
static void minibuffer_unwind (void);
-static void run_exit_minibuf_hook (void);
+static void run_exit_minibuf_hook (Lisp_Object minibuf);
/* Read a Lisp object from VAL and return it. If VAL is an empty
@@ -431,8 +427,8 @@ No argument or nil as argument means use the current buffer as BUFFER. */)
{
if (NILP (buffer))
buffer = Fcurrent_buffer ();
- return EQ (buffer, (Fcar (Fnthcdr (make_fixnum (minibuf_level),
- Vminibuffer_list))))
+ return BASE_EQ (buffer, (Fcar (Fnthcdr (make_fixnum (minibuf_level),
+ Vminibuffer_list))))
? Qt
: Qnil;
}
@@ -578,7 +574,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
bool allow_props, bool inherit_input_method)
{
Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
Lisp_Object calling_frame = selected_frame;
Lisp_Object calling_window = selected_window;
@@ -745,7 +741,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
separately from read_minibuf_unwind because we need to make sure that
read_minibuf_unwind is fully executed even if exit-minibuffer-hook
signals an error. --Stef */
- record_unwind_protect_void (run_exit_minibuf_hook);
+ record_unwind_protect (run_exit_minibuf_hook, minibuffer);
/* Now that we can restore all those variables, start changing them. */
@@ -764,7 +760,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
/* If variable is unbound, make it nil. */
histval = find_symbol_value (histvar);
- if (EQ (histval, Qunbound))
+ if (BASE_EQ (histval, Qunbound))
{
Fset (histvar, Qnil);
histval = Qnil;
@@ -833,7 +829,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
/* Erase the buffer. */
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
Ferase_buffer ();
@@ -916,7 +912,17 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
XWINDOW (minibuf_window)->cursor.x = 0;
XWINDOW (minibuf_window)->must_be_updated_p = true;
update_frame (XFRAME (selected_frame), true, true);
+#ifndef HAVE_NTGUI
flush_frame (XFRAME (XWINDOW (minibuf_window)->frame));
+#else
+ /* The reason this function isn't `flush_display' in the RIF is
+ that `flush_frame' is also called in many other circumstances
+ when some code wants X requests to be sent to the X server,
+ but there is no corresponding "flush" concept on MS Windows,
+ and flipping buffers every time `flush_frame' is called
+ causes flicker. */
+ w32_flip_buffers_if_dirty (XFRAME (XWINDOW (minibuf_window)->frame));
+#endif
}
/* Make minibuffer contents into a string. */
@@ -991,7 +997,7 @@ nth_minibuffer (EMACS_INT depth)
static void
set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
Fset_buffer (buf);
@@ -1062,9 +1068,14 @@ static EMACS_INT minibuf_c_loop_level (EMACS_INT depth)
}
static void
-run_exit_minibuf_hook (void)
+run_exit_minibuf_hook (Lisp_Object minibuf)
{
+ specpdl_ref count = SPECPDL_INDEX ();
+ record_unwind_current_buffer ();
+ if (BUFFER_LIVE_P (XBUFFER (minibuf)))
+ Fset_buffer (minibuf);
safe_run_hooks (Qminibuffer_exit_hook);
+ unbind_to (count, Qnil);
}
/* This variable records the expired minibuffer's frame between the
@@ -1112,8 +1123,8 @@ read_minibuf_unwind (void)
found:
if (!EQ (exp_MB_frame, saved_selected_frame)
&& !NILP (exp_MB_frame))
- do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
- minibuf_window */
+ do_switch_frame (exp_MB_frame, 0, Qt); /* This also sets
+ minibuf_window */
/* To keep things predictable, in case it matters, let's be in the
minibuffer when we reset the relevant variables. Don't depend on
@@ -1155,7 +1166,7 @@ read_minibuf_unwind (void)
/* Erase the minibuffer we were using at this level. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Prevent error in erase-buffer. */
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
@@ -1225,7 +1236,7 @@ read_minibuf_unwind (void)
/* Restore the selected frame. */
if (!EQ (exp_MB_frame, saved_selected_frame)
&& !NILP (exp_MB_frame))
- do_switch_frame (saved_selected_frame, 0, 0, Qt);
+ do_switch_frame (saved_selected_frame, 0, Qt);
}
/* Replace the expired minibuffer in frame exp_MB_frame with the next less
@@ -1292,8 +1303,9 @@ Fifth arg HIST, if non-nil, specifies a history list and optionally
HISTPOS is the initial position for use by the minibuffer history
commands. For consistency, you should also specify that element of
the history as the value of INITIAL-CONTENTS. Positions are counted
- starting from 1 at the beginning of the list. If HIST is t, history
- is not recorded.
+ starting from 1 at the beginning of the list. If HIST is nil, the
+ default history list `minibuffer-history' is used. If HIST is t,
+ history is not recorded.
If `history-add-new-input' is non-nil (the default), the result will
be added to the history list using `add-to-history'.
@@ -1384,7 +1396,7 @@ Fifth arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits
(Lisp_Object prompt, Lisp_Object initial_input, Lisp_Object history, Lisp_Object default_value, Lisp_Object inherit_input_method)
{
Lisp_Object val;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Just in case we're in a recursive minibuffer, make it clear that the
previous minibuffer's completion table does not apply to the new
@@ -1483,7 +1495,7 @@ function, instead of the usual behavior. */)
Lisp_Object result;
char *s;
ptrdiff_t len;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (BUFFERP (def))
def = BVAR (XBUFFER (def), name);
@@ -1567,36 +1579,47 @@ match_regexps (Lisp_Object string, Lisp_Object regexps,
}
DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
- doc: /* Return common substring of all completions of STRING in COLLECTION.
+ doc: /* Return longest common substring of all completions of STRING in COLLECTION.
+
Test each possible completion specified by COLLECTION
to see if it begins with STRING. The possible completions may be
strings or symbols. Symbols are converted to strings before testing,
-see `symbol-name'.
-All that match STRING are compared together; the longest initial sequence
-common to all these matches is the return value.
-If there is no match at all, the return value is nil.
-For a unique match which is exact, the return value is t.
+by using `symbol-name'.
+
+If no possible completions match, the function returns nil; if
+there's just one exact match, it returns t; otherwise it returns
+the longest initial substring common to all possible completions
+that begin with STRING.
If COLLECTION is an alist, the keys (cars of elements) are the
possible completions. If an element is not a cons cell, then the
-element itself is the possible completion.
-If COLLECTION is a hash-table, all the keys that are strings or symbols
-are the possible completions.
+element itself is a possible completion.
+If COLLECTION is a hash-table, all the keys that are either strings
+or symbols are the possible completions.
If COLLECTION is an obarray, the names of all symbols in the obarray
are the possible completions.
COLLECTION can also be a function to do the completion itself.
-It receives three arguments: the values STRING, PREDICATE and nil.
+It receives three arguments: STRING, PREDICATE and nil.
Whatever it returns becomes the value of `try-completion'.
-If optional third argument PREDICATE is non-nil,
-it is used to test each possible match.
-The match is a candidate only if PREDICATE returns non-nil.
-The argument given to PREDICATE is the alist element
-or the symbol from the obarray. If COLLECTION is a hash-table,
-predicate is called with two arguments: the key and the value.
-Additionally to this predicate, `completion-regexp-list'
-is used to further constrain the set of candidates. */)
+If optional third argument PREDICATE is non-nil, it must be a function
+of one or two arguments, and is used to test each possible completion.
+A possible completion is accepted only if PREDICATE returns non-nil.
+
+The argument given to PREDICATE is either a string or a cons cell (whose
+car is a string) from the alist, or a symbol from the obarray.
+If COLLECTION is a hash-table, PREDICATE is called with two arguments:
+the string key and the associated value.
+
+To be acceptable, a possible completion must also match all the regexps
+in `completion-regexp-list' (unless COLLECTION is a function, in
+which case that function should itself handle `completion-regexp-list').
+
+If `completion-ignore-case' is non-nil, possible completions are matched
+while ignoring letter-case, but no guarantee is made about the letter-case
+of the return value, except that it comes either from the user's input
+or from one of the possible completions. */)
(Lisp_Object string, Lisp_Object collection, Lisp_Object predicate)
{
@@ -1670,7 +1693,8 @@ is used to further constrain the set of candidates. */)
else /* if (type == hash_table) */
{
while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection))
- && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound))
+ && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx),
+ Qunbound))
idx++;
if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection)))
break;
@@ -1767,10 +1791,10 @@ is used to further constrain the set of candidates. */)
if (bestmatchsize != SCHARS (eltstring)
|| bestmatchsize != matchsize
|| (completion_ignore_case
- && !EQ (Fcompare_strings (old_bestmatch, zero, lcompare,
- eltstring, zero, lcompare,
- Qnil),
- Qt)))
+ && !BASE_EQ (Fcompare_strings (old_bestmatch, zero,
+ lcompare, eltstring, zero,
+ lcompare, Qnil),
+ Qt)))
/* Don't count the same string multiple times. */
matchcount += matchcount <= 1;
bestmatchsize = matchsize;
@@ -1806,11 +1830,13 @@ is used to further constrain the set of candidates. */)
}
DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 4, 0,
- doc: /* Search for partial matches to STRING in COLLECTION.
-Test each of the possible completions specified by COLLECTION
+ doc: /* Search for partial matches of STRING in COLLECTION.
+
+Test each possible completion specified by COLLECTION
to see if it begins with STRING. The possible completions may be
strings or symbols. Symbols are converted to strings before testing,
-see `symbol-name'.
+by using `symbol-name'.
+
The value is a list of all the possible completions that match STRING.
If COLLECTION is an alist, the keys (cars of elements) are the
@@ -1822,17 +1848,21 @@ If COLLECTION is an obarray, the names of all symbols in the obarray
are the possible completions.
COLLECTION can also be a function to do the completion itself.
-It receives three arguments: the values STRING, PREDICATE and t.
+It receives three arguments: STRING, PREDICATE and t.
Whatever it returns becomes the value of `all-completions'.
-If optional third argument PREDICATE is non-nil,
-it is used to test each possible match.
-The match is a candidate only if PREDICATE returns non-nil.
-The argument given to PREDICATE is the alist element
-or the symbol from the obarray. If COLLECTION is a hash-table,
-predicate is called with two arguments: the key and the value.
-Additionally to this predicate, `completion-regexp-list'
-is used to further constrain the set of candidates.
+If optional third argument PREDICATE is non-nil, it must be a function
+of one or two arguments, and is used to test each possible completion.
+A possible completion is accepted only if PREDICATE returns non-nil.
+
+The argument given to PREDICATE is either a string or a cons cell (whose
+car is a string) from the alist, or a symbol from the obarray.
+If COLLECTION is a hash-table, PREDICATE is called with two arguments:
+the string key and the associated value.
+
+To be acceptable, a possible completion must also match all the regexps
+in `completion-regexp-list' (unless COLLECTION is a function, in
+which case that function should itself handle `completion-regexp-list').
An obsolete optional fourth argument HIDE-SPACES is still accepted for
backward compatibility. If non-nil, strings in COLLECTION that start
@@ -1901,7 +1931,8 @@ with a space are ignored unless STRING itself starts with a space. */)
else /* if (type == 3) */
{
while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection))
- && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound))
+ && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx),
+ Qunbound))
idx++;
if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection)))
break;
@@ -1980,6 +2011,9 @@ REQUIRE-MATCH can take the following values:
input, but she needs to confirm her choice if she called
`minibuffer-complete' right before `minibuffer-complete-and-exit'
and the input is not an element of COLLECTION.
+- a function, which will be called with the input as the
+ argument. If the function returns a non-nil value, the
+ minibuffer is exited with that argument as the value.
- anything else behaves like t except that typing RET does not exit if it
does non-null completion.
@@ -2077,10 +2111,11 @@ the values STRING, PREDICATE and `lambda'. */)
if (SYMBOLP (tail))
while (1)
{
- if (EQ (Fcompare_strings (string, make_fixnum (0), Qnil,
- Fsymbol_name (tail),
- make_fixnum (0) , Qnil, Qt),
- Qt))
+ if (BASE_EQ (Fcompare_strings (string, make_fixnum (0),
+ Qnil,
+ Fsymbol_name (tail),
+ make_fixnum (0) , Qnil, Qt),
+ Qt))
{
tem = tail;
break;
@@ -2108,12 +2143,12 @@ the values STRING, PREDICATE and `lambda'. */)
for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
tem = HASH_KEY (h, i);
- if (EQ (tem, Qunbound)) continue;
+ if (BASE_EQ (tem, Qunbound)) continue;
Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem);
if (!STRINGP (strkey)) continue;
- if (EQ (Fcompare_strings (string, Qnil, Qnil,
- strkey, Qnil, Qnil,
- completion_ignore_case ? Qt : Qnil),
+ if (BASE_EQ (Fcompare_strings (string, Qnil, Qnil,
+ strkey, Qnil, Qnil,
+ completion_ignore_case ? Qt : Qnil),
Qt))
goto found_matching_key;
}
diff --git a/src/msdos.c b/src/msdos.c
index f126d28c985..1608245904c 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -2725,7 +2725,8 @@ dos_rawgetc (void)
event.x = make_fixnum (x);
event.y = make_fixnum (y);
event.frame_or_window = selected_frame;
- event.arg = Qnil;
+ event.arg = tty_handle_tab_bar_click (SELECTED_FRAME (),
+ x, y, press, &event);
event.timestamp = event_timestamp ();
kbd_buffer_store_event (&event);
}
diff --git a/src/msdos.h b/src/msdos.h
index 7e57c7c1102..24697bcf24b 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -22,6 +22,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <dpmi.h>
#include "termhooks.h" /* struct terminal */
+struct terminal;
+
+extern unsigned int _dos_commit(int);
+#define tcdrain(f) _dos_commit(f)
int dos_ttraw (struct tty_display_info *);
int dos_ttcooked (void);
@@ -57,6 +61,11 @@ ssize_t readlinkat (int, const char *, char *, size_t);
int fstatat (int, char const *, struct stat *, int);
int unsetenv (const char *);
int faccessat (int, const char *, int, int);
+int openat (int, const char *, int, int);
+int fchmodat (int, const char *, mode_t, int);
+int futimens (int, const struct timespec[2]);
+int utimensat (int, const char *, const struct timespec[2], int);
+
void msdos_fatal_signal (int);
void syms_of_msdos (void);
int pthread_sigmask (int, const sigset_t *, sigset_t *);
diff --git a/src/nsfns.m b/src/nsfns.m
index 11132a294a5..16174210669 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -47,12 +47,42 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
#ifdef NS_IMPL_COCOA
#include <IOKit/graphics/IOGraphicsLib.h>
#include "macfont.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+#include <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
+#define IOMasterPort IOMainPort
+#endif
+#endif
#endif
#ifdef HAVE_NS
static EmacsTooltip *ns_tooltip = nil;
+/* The frame of the currently visible tooltip, or nil if none. */
+static Lisp_Object tip_frame;
+
+/* The X and Y deltas of the last call to `x-show-tip'. */
+static Lisp_Object tip_dx, tip_dy;
+
+/* The window-system window corresponding to the frame of the
+ currently visible tooltip. */
+static NSWindow *tip_window;
+
+/* A timer that hides or deletes the currently visible tooltip when it
+ fires. */
+static Lisp_Object tip_timer;
+
+/* STRING argument of last `x-show-tip' call. */
+static Lisp_Object tip_last_string;
+
+/* Normalized FRAME argument of last `x-show-tip' call. */
+static Lisp_Object tip_last_frame;
+
+/* PARMS argument of last `x-show-tip' call. */
+static Lisp_Object tip_last_parms;
+
/* Static variables to handle AppleScript execution. */
static Lisp_Object as_script, *as_result;
static int as_status;
@@ -352,7 +382,7 @@ ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
/* See if it's changed. */
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg))
@@ -769,11 +799,13 @@ ns_implicitly_set_icon_type (struct frame *f)
Lisp_Object chain, elt;
NSAutoreleasePool *pool;
BOOL setMini = YES;
+ NSWorkspace *workspace;
NSTRACE ("ns_implicitly_set_icon_type");
block_input ();
pool = [[NSAutoreleasePool alloc] init];
+ workspace = [NSWorkspace sharedWorkspace];
if (f->output_data.ns->miniimage
&& [[NSString stringWithLispString:f->name]
isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
@@ -818,7 +850,21 @@ ns_implicitly_set_icon_type (struct frame *f)
if (image == nil)
{
- image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
+#ifndef NS_IMPL_GNUSTEP
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ if ([workspace respondsToSelector: @selector (iconForContentType:)])
+#endif
+ image = [[workspace iconForContentType:
+ [UTType typeWithIdentifier: @"text"]] retain];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ else
+#endif
+#endif
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ image = [[workspace iconForFileType: @"text"] retain];
+#endif
setMini = NO;
}
@@ -891,7 +937,10 @@ static Lisp_Object
ns_appkit_version_str (void)
{
NSString *tmp;
+ Lisp_Object string;
+ NSAutoreleasePool *autorelease;
+ autorelease = [[NSAutoreleasePool alloc] init];
#ifdef NS_IMPL_GNUSTEP
tmp = [NSString stringWithFormat:@"gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION)];
#elif defined (NS_IMPL_COCOA)
@@ -901,7 +950,10 @@ ns_appkit_version_str (void)
#else
tmp = [NSString initWithUTF8String:@"ns-unknown"];
#endif
- return [tmp lispString];
+ string = [tmp lispString];
+ [autorelease release];
+
+ return string;
}
@@ -1004,6 +1056,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
ns_set_z_group,
0, /* x_set_override_redirect */
gui_set_no_special_glyphs,
+ gui_set_alpha_background,
#ifdef NS_IMPL_COCOA
ns_set_appearance,
ns_set_transparent_titlebar,
@@ -1014,7 +1067,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
/* Handler for signals raised during x_create_frame.
FRAME is the frame which is partially constructed. */
-static void
+static Lisp_Object
unwind_create_frame (Lisp_Object frame)
{
struct frame *f = XFRAME (frame);
@@ -1023,7 +1076,7 @@ unwind_create_frame (Lisp_Object frame)
display is disconnected after the frame has become official, but
before x_create_frame removes the unwind protect. */
if (!FRAME_LIVE_P (f))
- return;
+ return Qnil;
/* If frame is ``official'', nothing to do. */
if (NILP (Fmemq (frame, Vframe_list)))
@@ -1050,7 +1103,18 @@ unwind_create_frame (Lisp_Object frame)
/* Check that reference counts are indeed correct. */
eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
#endif
+
+ return Qt;
}
+
+ return Qnil;
+}
+
+
+static void
+do_unwind_create_frame (Lisp_Object frame)
+{
+ unwind_create_frame (frame);
}
/*
@@ -1105,12 +1169,13 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
Lisp_Object name;
int minibuffer_only = 0;
long window_prompting = 0;
- ptrdiff_t count = specpdl_ptr - specpdl;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object display;
struct ns_display_info *dpyinfo = NULL;
Lisp_Object parent, parent_frame;
struct kboard *kb;
static int desc_ctr = 1;
+ NSWindow *main_window = [NSApp mainWindow];
/* gui_display_get_arg modifies parms. */
parms = Fcopy_alist (parms);
@@ -1183,7 +1248,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
FRAME_DISPLAY_INFO (f) = dpyinfo;
/* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
- record_unwind_protect (unwind_create_frame, frame);
+ record_unwind_protect (do_unwind_create_frame, frame);
f->output_data.ns->window_desc = desc_ctr++;
if (TYPE_RANGED_FIXNUMP (Window, parent))
@@ -1436,6 +1501,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qfullscreen, Qnil,
"fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
@@ -1480,8 +1547,27 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
- if (window_prompting & USPosition)
+ /* This cascading behavior (which is the job of the window manager
+ on X-based systems) is something NS applications are expected to
+ implement themselves. At least one person tells me he used
+ Carbon Emacs solely for this behavior. */
+ if (window_prompting & (USPosition | PPosition) || FRAME_PARENT_FRAME (f))
ns_set_offset (f, f->left_pos, f->top_pos, 1);
+ else
+ {
+ NSWindow *frame_window = [FRAME_NS_VIEW (f) window];
+ NSPoint top_left;
+
+ if (main_window)
+ {
+ top_left = NSMakePoint (NSMinX ([main_window frame]),
+ NSMaxY ([main_window frame]));
+ top_left = [frame_window cascadeTopLeftFromPoint: top_left];
+ [frame_window cascadeTopLeftFromPoint: top_left];
+ }
+ else
+ [frame_window center];
+ }
/* Make sure windows on this frame appear in calls to next-window
and similar functions. */
@@ -1564,26 +1650,22 @@ Some window managers may refuse to restack windows. */)
}
}
-DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
- 0, 1, "",
- doc: /* Pop up the font panel. */)
- (Lisp_Object frame)
+DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
+ doc: /* Read a font using a Nextstep dialog.
+Return a font specification describing the selected font.
+
+FRAME is the frame on which to pop up the font chooser. If omitted or
+nil, it defaults to the selected frame. */)
+ (Lisp_Object frame, Lisp_Object ignored)
{
struct frame *f = decode_window_system_frame (frame);
- id fm = [NSFontManager sharedFontManager];
- struct font *font = f->output_data.ns->font;
- NSFont *nsfont;
-#ifdef NS_IMPL_GNUSTEP
- nsfont = ((struct nsfont_info *)font)->nsfont;
-#endif
-#ifdef NS_IMPL_COCOA
- nsfont = (NSFont *) macfont_get_nsctfont (font);
-#endif
- [fm setSelectedFont: nsfont isMultiple: NO];
- [fm orderFrontFontPanel: NSApp];
- return Qnil;
-}
+ Lisp_Object font = [FRAME_NS_VIEW (f) showFontPanel];
+
+ if (NILP (font))
+ quit ();
+ return font;
+}
DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
0, 1, "",
@@ -1652,16 +1734,18 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
id panel;
Lisp_Object fname = Qnil;
-
- NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
- [NSString stringWithLispString:prompt];
- NSString *dirS = NILP (dir) || !STRINGP (dir) ?
- [NSString stringWithLispString:BVAR (current_buffer, directory)] :
- [NSString stringWithLispString:dir];
- NSString *initS = NILP (init) || !STRINGP (init) ? nil :
- [NSString stringWithLispString:init];
+ NSString *promptS, *dirS, *initS, *str;
NSEvent *nxev;
+ promptS = (NILP (prompt) || !STRINGP (prompt)
+ ? nil : [NSString stringWithLispString: prompt]);
+ dirS = (NILP (dir) || !STRINGP (dir)
+ ? [NSString stringWithLispString:
+ ENCODE_FILE (BVAR (current_buffer, directory))] :
+ [NSString stringWithLispString: ENCODE_FILE (dir)]);
+ initS = (NILP (init) || !STRINGP (init)
+ ? nil : [NSString stringWithLispString: init]);
+
check_window_system (NULL);
if (fileDelegate == nil)
@@ -1699,7 +1783,20 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
ns_fd_data.ret = NO;
#ifdef NS_IMPL_COCOA
if (! NILP (mustmatch) || ! NILP (dir_only_p))
- [panel setAllowedFileTypes: nil];
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ if ([panel respondsToSelector: @selector (setAllowedContentTypes:)])
+#endif
+ [panel setAllowedContentTypes: [NSArray array]];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ else
+#endif
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+ [panel setAllowedFileTypes: nil];
+#endif
+ }
if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
if (initS && NILP (Ffile_directory_p (init)))
[panel setNameFieldStringValue: [initS lastPathComponent]];
@@ -1733,9 +1830,15 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
if (ns_fd_data.ret == MODAL_OK_RESPONSE)
{
- NSString *str = ns_filename_from_panel (panel);
- if (! str) str = ns_directory_from_panel (panel);
- if (str) fname = [str lispString];
+ str = ns_filename_from_panel (panel);
+
+ if (!str)
+ str = ns_directory_from_panel (panel);
+ if (str)
+ fname = [str lispString];
+
+ if (!NILP (fname))
+ fname = DECODE_FILE (fname);
}
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
@@ -1759,7 +1862,7 @@ ns_get_defaults_value (const char *key)
DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
doc: /* Return the value of the property NAME of OWNER from the defaults database.
If OWNER is nil, Emacs is assumed. */)
- (Lisp_Object owner, Lisp_Object name)
+ (Lisp_Object owner, Lisp_Object name)
{
const char *value;
@@ -1780,7 +1883,7 @@ DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
If OWNER is nil, Emacs is assumed.
If VALUE is nil, the default is removed. */)
- (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
+ (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
{
check_window_system (NULL);
if (NILP (owner))
@@ -1807,7 +1910,7 @@ DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
Sx_server_max_request_size,
0, 1, 0,
doc: /* SKIP: real doc in xfns.c. */)
- (Lisp_Object terminal)
+ (Lisp_Object terminal)
{
check_ns_display_info (terminal);
/* This function has no real equivalent under Nextstep. Return nil to
@@ -2080,6 +2183,7 @@ The optional argument FRAME is currently ignored. */)
Lisp_Object list = Qnil;
NSEnumerator *colorlists;
NSColorList *clist;
+ NSAutoreleasePool *pool;
if (!NILP (frame))
{
@@ -2089,7 +2193,9 @@ The optional argument FRAME is currently ignored. */)
}
block_input ();
-
+ /* This can be called during dumping, so we need to set up a
+ temporary autorelease pool. */
+ pool = [[NSAutoreleasePool alloc] init];
colorlists = [[NSColorList availableColorLists] objectEnumerator];
while ((clist = [colorlists nextObject]))
{
@@ -2100,12 +2206,9 @@ The optional argument FRAME is currently ignored. */)
NSString *cname;
while ((cname = [cnames nextObject]))
list = Fcons ([cname lispString], list);
-/* for (i = [[clist allKeys] count] - 1; i >= 0; i--)
- list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
- UTF8String]), list); */
}
}
-
+ [pool release];
unblock_input ();
return list;
@@ -2669,7 +2772,8 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
}
else
{
- // Flip y coordinate as NS has y starting from the bottom.
+ /* Flip y coordinate as NS screen coordinates originate from
+ the bottom. */
y = (short) (primary_display_height - fr.size.height - fr.origin.y);
vy = (short) (primary_display_height -
vfr.size.height - vfr.origin.y);
@@ -2681,11 +2785,12 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
m->geom.height = (unsigned short) fr.size.height;
m->work.x = (short) vfr.origin.x;
- // y is flipped on NS, so vy - y are pixels missing at the bottom,
- // and fr.size.height - vfr.size.height are pixels missing in total.
- // Pixels missing at top are
- // fr.size.height - vfr.size.height - vy + y.
- // work.y is then pixels missing at top + y.
+ /* y is flipped on NS, so vy - y are pixels missing at the
+ bottom, and fr.size.height - vfr.size.height are pixels
+ missing in total.
+
+ Pixels missing at top are fr.size.height - vfr.size.height -
+ vy + y. work.y is then pixels missing at top + y. */
m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
m->work.width = (unsigned short) vfr.size.width;
m->work.height = (unsigned short) vfr.size.height;
@@ -2700,13 +2805,14 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
}
#else
- // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
+ /* Assume 92 dpi as x-display-mm-height and x-display-mm-width
+ do. */
m->mm_width = (int) (25.4 * fr.size.width / 92.0);
m->mm_height = (int) (25.4 * fr.size.height / 92.0);
#endif
}
- // Primary monitor is always first for NS.
+ /* Primary monitor is always ordered first for NS. */
attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
0, "NS");
@@ -2736,16 +2842,10 @@ DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
return make_fixnum (1 << min (dpyinfo->n_planes, 24));
}
-/* TODO: move to xdisp or similar */
static void
-compute_tip_xy (struct frame *f,
- Lisp_Object parms,
- Lisp_Object dx,
- Lisp_Object dy,
- int width,
- int height,
- int *root_x,
- int *root_y)
+compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
+ Lisp_Object dy, int width, int height, int *root_x,
+ int *root_y)
{
Lisp_Object left, top, right, bottom;
NSPoint pt;
@@ -2814,18 +2914,318 @@ compute_tip_xy (struct frame *f,
*root_y = screen.frame.origin.y + screen.frame.size.height - height;
}
+static void
+unwind_create_tip_frame (Lisp_Object frame)
+{
+ Lisp_Object deleted;
+
+ deleted = unwind_create_frame (frame);
+ if (EQ (deleted, Qt))
+ {
+ tip_window = NULL;
+ tip_frame = Qnil;
+ }
+}
+
+/* Create a frame for a tooltip on the display described by DPYINFO.
+ PARMS is a list of frame parameters. TEXT is the string to
+ display in the tip frame. Value is the frame.
+
+ Note that functions called here, esp. gui_default_parameter can
+ signal errors, for instance when a specified color name is
+ undefined. We have to make sure that we're in a consistent state
+ when this happens. */
+
+static Lisp_Object
+ns_create_tip_frame (struct ns_display_info *dpyinfo, Lisp_Object parms)
+{
+ struct frame *f;
+ Lisp_Object frame;
+ Lisp_Object name;
+ specpdl_ref count = SPECPDL_INDEX ();
+ bool face_change_before = face_change;
+
+ if (!dpyinfo->terminal->name)
+ error ("Terminal is not live, can't create new frames on it");
+
+ parms = Fcopy_alist (parms);
+
+ /* Get the name of the frame to use for resource lookup. */
+ name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
+ RES_TYPE_STRING);
+ if (!STRINGP (name)
+ && !EQ (name, Qunbound)
+ && !NILP (name))
+ error ("Invalid frame name--not a string or nil");
+
+ frame = Qnil;
+ f = make_frame (false);
+ f->wants_modeline = false;
+ XSETFRAME (frame, f);
+ record_unwind_protect (unwind_create_tip_frame, frame);
+
+ f->terminal = dpyinfo->terminal;
+
+ f->output_method = output_ns;
+ f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
+ f->tooltip = true;
+
+ FRAME_FONTSET (f) = -1;
+ FRAME_DISPLAY_INFO (f) = dpyinfo;
+
+ block_input ();
+#ifdef NS_IMPL_COCOA
+ mac_register_font_driver (f);
+#else
+ register_font_driver (&nsfont_driver, f);
+#endif
+ unblock_input ();
+
+ image_cache_refcount =
+ FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
+
+ gui_default_parameter (f, parms, Qfont_backend, Qnil,
+ "fontBackend", "FontBackend", RES_TYPE_STRING);
+
+ {
+#ifdef NS_IMPL_COCOA
+ /* use for default font name */
+ id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
+ gui_default_parameter (f, parms, Qfontsize,
+ make_fixnum (0 /* (int)[font pointSize] */),
+ "fontSize", "FontSize", RES_TYPE_NUMBER);
+ // Remove ' Regular', not handled by backends.
+ char *fontname = xstrdup ([[font displayName] UTF8String]);
+ int len = strlen (fontname);
+ if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
+ fontname[len-8] = '\0';
+ gui_default_parameter (f, parms, Qfont,
+ build_string (fontname),
+ "font", "Font", RES_TYPE_STRING);
+ xfree (fontname);
+#else
+ gui_default_parameter (f, parms, Qfont,
+ build_string ("fixed"),
+ "font", "Font", RES_TYPE_STRING);
+#endif
+ }
+
+ gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
+ "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
+
+ /* This defaults to 1 in order to match xterm. We recognize either
+ internalBorderWidth or internalBorder (which is what xterm calls
+ it). */
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ {
+ Lisp_Object value;
+
+ value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
+ "internalBorder", "internalBorder",
+ RES_TYPE_NUMBER);
+ if (! EQ (value, Qunbound))
+ parms = Fcons (Fcons (Qinternal_border_width, value),
+ parms);
+ }
+
+ gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
+ "internalBorderWidth", "internalBorderWidth",
+ RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
+ NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0),
+ NULL, NULL, RES_TYPE_NUMBER);
+
+ /* Also do the stuff which must be set before the window exists. */
+ gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+ "foreground", "Foreground", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+ "background", "Background", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
+ "pointerColor", "Foreground", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+ "cursorColor", "Foreground", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
+ "borderColor", "BorderColor", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+ /* Init faces before gui_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
+ init_frame_faces (f);
+
+ f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
+
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
+ gui_figure_window_size (f, parms, false, false);
+
+ block_input ();
+ [[EmacsView alloc] initFrameFromEmacs: f];
+ ns_icon (f, parms);
+ unblock_input ();
+
+ gui_default_parameter (f, parms, Qauto_raise, Qnil,
+ "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qauto_lower, Qnil,
+ "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qcursor_type, Qbox,
+ "cursorType", "CursorType", RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qalpha, Qnil,
+ "alpha", "Alpha", RES_TYPE_NUMBER);
+
+ /* Add `tooltip' frame parameter's default value. */
+ if (NILP (Fframe_parameter (frame, Qtooltip)))
+ {
+ AUTO_FRAME_ARG (arg, Qtooltip, Qt);
+ Fmodify_frame_parameters (frame, arg);
+ }
+
+ /* FIXME - can this be done in a similar way to normal frames?
+ https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */
+
+ /* Set the `display-type' frame parameter before setting up faces. */
+ {
+ Lisp_Object disptype = intern ("color");
+
+ if (NILP (Fframe_parameter (frame, Qdisplay_type)))
+ {
+ AUTO_FRAME_ARG (arg, Qdisplay_type, disptype);
+ Fmodify_frame_parameters (frame, arg);
+ }
+ }
+
+ /* Set up faces after all frame parameters are known. This call
+ also merges in face attributes specified for new frames.
+
+ Frame parameters may be changed if .Xdefaults contains
+ specifications for the default font. For example, if there is an
+ `Emacs.default.attributeBackground: pink', the `background-color'
+ attribute of the frame gets set, which let's the internal border
+ of the tooltip frame appear in pink. Prevent this. */
+ {
+ Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+ call2 (Qface_set_after_frame_default, frame, Qnil);
+
+ if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+ {
+ AUTO_FRAME_ARG (arg, Qbackground_color, bg);
+ Fmodify_frame_parameters (frame, arg);
+ }
+ }
+
+ f->no_split = true;
+
+ /* Now that the frame will be official, it counts as a reference to
+ its display and terminal. */
+ f->terminal->reference_count++;
+
+ /* It is now ok to make the frame official even if we get an error
+ below. And the frame needs to be on Vframe_list or making it
+ visible won't work. */
+ Vframe_list = Fcons (frame, Vframe_list);
+ f->can_set_window_size = true;
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+ 0, true, Qtip_frame);
+
+ /* Setting attributes of faces of the tooltip frame from resources
+ and similar will set face_change, which leads to the clearing of
+ all current matrices. Since this isn't necessary here, avoid it
+ by resetting face_change to the value it had before we created
+ the tip frame. */
+ face_change = face_change_before;
+
+ /* Discard the unwind_protect. */
+ return unbind_to (count, frame);
+}
+
+static Lisp_Object
+x_hide_tip (bool delete)
+{
+ if (!NILP (tip_timer))
+ {
+ call1 (intern ("cancel-timer"), tip_timer);
+ tip_timer = Qnil;
+ }
+
+ if (!(ns_tooltip == nil || ![ns_tooltip isActive]))
+ {
+ [ns_tooltip hide];
+ tip_last_frame = Qnil;
+ return Qt;
+ }
+
+ if ((NILP (tip_last_frame) && NILP (tip_frame))
+ || (!use_system_tooltips
+ && !delete
+ && !NILP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
+ /* Either there's no tooltip to hide or it's an already invisible
+ Emacs tooltip and we don't want to change its type. Return
+ quickly. */
+ return Qnil;
+ else
+ {
+ specpdl_ref count;
+ Lisp_Object was_open = Qnil;
+
+ count = SPECPDL_INDEX ();
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+ /* Now look whether there's an Emacs tip around. */
+ if (!NILP (tip_frame))
+ {
+ struct frame *f = XFRAME (tip_frame);
+
+ if (FRAME_LIVE_P (f))
+ {
+ if (delete || use_system_tooltips)
+ {
+ /* Delete the Emacs tooltip frame when DELETE is true
+ or we change the tooltip type from an Emacs one to
+ a GTK+ system one. */
+ delete_frame (tip_frame, Qnil);
+ tip_frame = Qnil;
+ }
+ else
+ ns_make_frame_invisible (f);
+
+ was_open = Qt;
+ }
+ else
+ tip_frame = Qnil;
+ }
+ else
+ tip_frame = Qnil;
+
+ return unbind_to (count, was_open);
+ }
+}
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
doc: /* SKIP: real doc in xfns.c. */)
(Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
{
int root_x, root_y;
- ptrdiff_t count = SPECPDL_INDEX ();
- struct frame *f;
+ specpdl_ref count = SPECPDL_INDEX ();
+ struct frame *f, *tip_f;
+ struct window *w;
+ struct buffer *old_buffer;
+ struct text_pos pos;
+ int width, height;
+ int old_windows_or_buffers_changed = windows_or_buffers_changed;
+ specpdl_ref count_1;
+ Lisp_Object window, size, tip_buf;
char *str;
- NSSize size;
- NSColor *color;
- Lisp_Object t;
+ NSWindow *nswindow;
+
+ AUTO_STRING (tip, " *tip*");
specbind (Qinhibit_redisplay, Qt);
@@ -2833,9 +3233,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
str = SSDATA (string);
f = decode_window_system_frame (frame);
if (NILP (timeout))
- timeout = make_fixnum (5);
- else
- CHECK_FIXNAT (timeout);
+ timeout = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
if (NILP (dx))
dx = make_fixnum (5);
@@ -2847,32 +3246,253 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
else
CHECK_FIXNUM (dy);
- block_input ();
- if (ns_tooltip == nil)
- ns_tooltip = [[EmacsTooltip alloc] init];
+ tip_dx = dx;
+ tip_dy = dy;
+
+ if (use_system_tooltips)
+ {
+ NSSize size;
+ NSColor *color;
+ Lisp_Object t;
+
+ block_input ();
+ if (ns_tooltip == nil)
+ ns_tooltip = [[EmacsTooltip alloc] init];
+ else
+ Fx_hide_tip ();
+
+ t = gui_display_get_arg (NULL, parms, Qbackground_color, NULL, NULL,
+ RES_TYPE_STRING);
+ if (ns_lisp_to_color (t, &color) == 0)
+ [ns_tooltip setBackgroundColor: color];
+
+ t = gui_display_get_arg (NULL, parms, Qforeground_color, NULL, NULL,
+ RES_TYPE_STRING);
+ if (ns_lisp_to_color (t, &color) == 0)
+ [ns_tooltip setForegroundColor: color];
+
+ [ns_tooltip setText: str];
+ size = [ns_tooltip frame].size;
+
+ /* Move the tooltip window where the mouse pointer is. Resize and
+ show it. */
+ compute_tip_xy (f, parms, dx, dy, (int) size.width, (int) size.height,
+ &root_x, &root_y);
+
+ [ns_tooltip showAtX: root_x Y: root_y for: XFIXNUM (timeout)];
+ unblock_input ();
+ }
else
- Fx_hide_tip ();
+ {
+ if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
+ {
+ if (FRAME_VISIBLE_P (XFRAME (tip_frame))
+ && EQ (frame, tip_last_frame)
+ && !NILP (Fequal_including_properties (tip_last_string, string))
+ && !NILP (Fequal (tip_last_parms, parms)))
+ {
+ /* Only DX and DY have changed. */
+ tip_f = XFRAME (tip_frame);
+ if (!NILP (tip_timer))
+ {
+ call1 (intern ("cancel-timer"), tip_timer);
+ tip_timer = Qnil;
+ }
+
+ nswindow = [FRAME_NS_VIEW (tip_f) window];
+
+ block_input ();
+ compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
+ FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
+ [nswindow setFrame: NSMakeRect (root_x, root_y,
+ FRAME_PIXEL_WIDTH (tip_f),
+ FRAME_PIXEL_HEIGHT (tip_f))
+ display: YES];
+ [nswindow setLevel: NSPopUpMenuWindowLevel];
+ [nswindow orderFront: NSApp];
+ [nswindow display];
+
+ SET_FRAME_VISIBLE (tip_f, 1);
+ unblock_input ();
+
+ goto start_timer;
+ }
+ else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
+ {
+ bool delete = false;
+ Lisp_Object tail, elt, parm, last;
+
+ /* Check if every parameter in PARMS has the same value in
+ tip_last_parms. This may destruct tip_last_parms which,
+ however, will be recreated below. */
+ for (tail = parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ /* The left, top, right and bottom parameters are handled
+ by compute_tip_xy so they can be ignored here. */
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
+ && !EQ (parm, Qright) && !EQ (parm, Qbottom))
+ {
+ last = Fassq (parm, tip_last_parms);
+ if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ else
+ tip_last_parms =
+ call2 (intern ("assq-delete-all"), parm, tip_last_parms);
+ }
+ else
+ tip_last_parms =
+ call2 (intern ("assq-delete-all"), parm, tip_last_parms);
+ }
+
+ /* Now check if every parameter in what is left of
+ tip_last_parms with a non-nil value has an association in
+ PARMS. */
+ for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
+ {
+ elt = XCAR (tail);
+ parm = Fcar (elt);
+ if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
+ && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
+ {
+ /* We lost, delete the old tooltip. */
+ delete = true;
+ break;
+ }
+ }
+
+ x_hide_tip (delete);
+ }
+ else
+ x_hide_tip (true);
+ }
+ else
+ x_hide_tip (true);
- t = gui_display_get_arg (NULL, parms, Qbackground_color, NULL, NULL,
- RES_TYPE_STRING);
- if (ns_lisp_to_color (t, &color) == 0)
- [ns_tooltip setBackgroundColor: color];
+ tip_last_frame = frame;
+ tip_last_string = string;
+ tip_last_parms = parms;
- t = gui_display_get_arg (NULL, parms, Qforeground_color, NULL, NULL,
- RES_TYPE_STRING);
- if (ns_lisp_to_color (t, &color) == 0)
- [ns_tooltip setForegroundColor: color];
+ if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
+ {
+ /* Add default values to frame parameters. */
+ if (NILP (Fassq (Qname, parms)))
+ parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
+ if (NILP (Fassq (Qborder_width, parms)))
+ parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
+ if (NILP (Fassq (Qborder_color, parms)))
+ parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
+ if (NILP (Fassq (Qbackground_color, parms)))
+ parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
+ parms);
+
+ /* Create a frame for the tooltip, and record it in the global
+ variable tip_frame. */
+ if (NILP (tip_frame = ns_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
+ /* Creating the tip frame failed. */
+ return unbind_to (count, Qnil);
+ }
+
+ tip_f = XFRAME (tip_frame);
+ window = FRAME_ROOT_WINDOW (tip_f);
+ tip_buf = Fget_buffer_create (tip, Qnil);
+ /* We will mark the tip window a "pseudo-window" below, and such
+ windows cannot have display margins. */
+ bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
+ bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
+ set_window_buffer (window, tip_buf, false, false);
+ w = XWINDOW (window);
+ w->pseudo_window_p = true;
+ /* Try to avoid that `other-window' select us (Bug#47207). */
+ Fset_window_parameter (window, Qno_other_window, Qt);
+
+ /* Set up the frame's root window. Note: The following code does not
+ try to size the window or its frame correctly. Its only purpose is
+ to make the subsequent text size calculations work. The right
+ sizes should get installed when the toolkit gets back to us. */
+ w->left_col = 0;
+ w->top_line = 0;
+ w->pixel_left = 0;
+ w->pixel_top = 0;
+
+ if (CONSP (Vx_max_tooltip_size)
+ && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
+ && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
+ {
+ w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
+ w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
+ }
+ else
+ {
+ w->total_cols = 80;
+ w->total_lines = 40;
+ }
- [ns_tooltip setText: str];
- size = [ns_tooltip frame].size;
+ w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
+ w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
+ FRAME_TOTAL_COLS (tip_f) = w->total_cols;
+ adjust_frame_glyphs (tip_f);
+
+ /* Insert STRING into root window's buffer and fit the frame to the
+ buffer. */
+ count_1 = SPECPDL_INDEX ();
+ old_buffer = current_buffer;
+ set_buffer_internal_1 (XBUFFER (w->contents));
+ bset_truncate_lines (current_buffer, Qnil);
+ specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
+ specbind (Qinhibit_point_motion_hooks, Qt);
+ Ferase_buffer ();
+ Finsert (1, &string);
+ clear_glyph_matrix (w->desired_matrix);
+ clear_glyph_matrix (w->current_matrix);
+ SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
+ try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
+ /* Calculate size of tooltip window. */
+ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
+ /* Add the frame's internal border to calculated size. */
+ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+ height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+
+ /* Calculate position of tooltip frame. */
+ compute_tip_xy (tip_f, parms, dx, dy, width,
+ height, &root_x, &root_y);
+
+ block_input ();
+ nswindow = [FRAME_NS_VIEW (tip_f) window];
+ [nswindow setFrame: NSMakeRect (root_x, root_y,
+ width, height)
+ display: YES];
+ [nswindow setLevel: NSPopUpMenuWindowLevel];
+ [nswindow orderFront: NSApp];
+ [nswindow display];
+
+ SET_FRAME_VISIBLE (tip_f, YES);
+ FRAME_PIXEL_WIDTH (tip_f) = width;
+ FRAME_PIXEL_HEIGHT (tip_f) = height;
+ unblock_input ();
- /* Move the tooltip window where the mouse pointer is. Resize and
- show it. */
- compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
- &root_x, &root_y);
+ w->must_be_updated_p = true;
+ update_single_window (w);
+ flush_frame (tip_f);
+ set_buffer_internal_1 (old_buffer);
+ unbind_to (count_1, Qnil);
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
- [ns_tooltip showAtX: root_x Y: root_y for: XFIXNUM (timeout)];
- unblock_input ();
+ start_timer:
+ /* Let the tip disappear after timeout seconds. */
+ tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
+ intern ("x-hide-tip"));
+ }
return unbind_to (count, Qnil);
}
@@ -2882,10 +3502,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
doc: /* SKIP: real doc in xfns.c. */)
(void)
{
- if (ns_tooltip == nil || ![ns_tooltip isActive])
- return Qnil;
- [ns_tooltip hide];
- return Qt;
+ return x_hide_tip (!tooltip_reuse_hidden_frame);
}
/* Return geometric attributes of FRAME. According to the value of
@@ -3183,6 +3800,48 @@ all_nonzero_ascii (unsigned char *str, ptrdiff_t n)
}
@end
+void
+ns_move_tooltip_to_mouse_location (NSPoint screen_point)
+{
+ int root_x, root_y;
+ NSSize size;
+ NSWindow *window;
+ struct frame *tip_f;
+
+ window = nil;
+
+ if (!FIXNUMP (tip_dx) || !FIXNUMP (tip_dy))
+ return;
+
+ if (ns_tooltip)
+ size = [ns_tooltip frame].size;
+ else if (!FRAMEP (tip_frame)
+ || !FRAME_LIVE_P (XFRAME (tip_frame))
+ || !FRAME_VISIBLE_P (XFRAME (tip_frame)))
+ return;
+ else
+ {
+ tip_f = XFRAME (tip_frame);
+ window = [FRAME_NS_VIEW (tip_f) window];
+ size = [window frame].size;
+ }
+
+ root_x = screen_point.x;
+ root_y = screen_point.y;
+
+ /* We can directly use `compute_tip_xy' here, since it doesn't cons
+ nearly as much as it does on X. */
+ compute_tip_xy (NULL, Qnil, tip_dx, tip_dy, (int) size.width,
+ (int) size.height, &root_x, &root_y);
+
+ if (ns_tooltip)
+ [ns_tooltip moveTo: NSMakePoint (root_x, root_y)];
+ else
+ [window setFrame: NSMakeRect (root_x, root_y,
+ size.width, size.height)
+ display: YES];
+}
+
/* ==========================================================================
Lisp interface declaration
@@ -3228,6 +3887,10 @@ be used as the image of the icon representing the frame. */);
Default is t. */);
ns_use_proxy_icon = true;
+ DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
+
defsubr (&Sns_read_file_name);
defsubr (&Sns_get_resource);
defsubr (&Sns_set_resource);
@@ -3271,12 +3934,27 @@ Default is t. */);
defsubr (&Sns_emacs_info_panel);
defsubr (&Sns_list_services);
defsubr (&Sns_perform_service);
- defsubr (&Sns_popup_font_panel);
+ defsubr (&Sx_select_font);
defsubr (&Sns_popup_color_panel);
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
+ tip_timer = Qnil;
+ staticpro (&tip_timer);
+ tip_frame = Qnil;
+ staticpro (&tip_frame);
+ tip_last_frame = Qnil;
+ staticpro (&tip_last_frame);
+ tip_last_string = Qnil;
+ staticpro (&tip_last_string);
+ tip_last_parms = Qnil;
+ staticpro (&tip_last_parms);
+ tip_dx = Qnil;
+ staticpro (&tip_dx);
+ tip_dy = Qnil;
+ staticpro (&tip_dy);
+
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
defsubr (&Ssystem_move_file_to_trash);
#endif
diff --git a/src/nsfont.m b/src/nsfont.m
index f3c8a82930b..b54118afe5d 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1176,15 +1176,12 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
face = s->face;
- r.origin.x = s->x;
- if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
- r.origin.x += max (s->face->box_vertical_line_width, 0);
-
- r.origin.y = s->y;
+ r.origin.x = x;
+ r.origin.y = y;
r.size.height = FONT_HEIGHT (font);
- for (int i = from; i < to; ++i)
- c[i] = s->char2b[i];
+ for (int i = 0; i < len; ++i)
+ c[i] = s->char2b[i + from];
/* Fill background if requested. */
if (with_background && !isComposite)
@@ -1210,8 +1207,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
}
/* set up for character rendering */
- r.origin.y = y;
-
if (s->hl == DRAW_CURSOR)
col = FRAME_BACKGROUND_COLOR (s->f);
else
@@ -1721,8 +1716,8 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned int block)
metrics->rbearing = lrint (rb);
metrics->lbearing = lrint (lb);
- metrics->descent = NSMinY (r);
- metrics->ascent = NSMaxY (r);
+ metrics->descent = - NSMaxY (r);
+ metrics->ascent = - NSMinY (r);
}
unblock_input ();
}
@@ -1768,8 +1763,11 @@ syms_of_nsfont (void)
DEFSYM (Qcondensed, "condensed");
DEFSYM (Qexpanded, "expanded");
DEFSYM (Qmedium, "medium");
+
DEFVAR_LISP ("ns-reg-to-script", Vns_reg_to_script,
- doc: /* Internal use: maps font registry to Unicode script. */);
+ doc: /* Internal map of font registry to Unicode script. */);
+ Vns_reg_to_script = Qnil;
+
pdumper_do_now_and_after_load (syms_of_nsfont_for_pdumper);
}
diff --git a/src/nsimage.m b/src/nsimage.m
index 2fff987f9fc..9cb5090dd0d 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -142,7 +142,7 @@ ns_load_image (struct frame *f, struct image *img,
eassert (valid_image_p (img->spec));
- lisp_index = Fplist_get (XCDR (img->spec), QCindex);
+ lisp_index = plist_get (XCDR (img->spec), QCindex);
index = FIXNUMP (lisp_index) ? XFIXNAT (lisp_index) : 0;
if (STRINGP (spec_file))
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 4d3c7528160..d02d7bae4b5 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -52,6 +52,10 @@ EmacsMenu *svcsMenu;
/* Nonzero means a menu is currently active. */
static int popup_activated_flag;
+/* The last frame whose menubar was updated. (This is the frame whose
+ menu bar is currently being displayed.) */
+static struct frame *last_menubar_frame;
+
/* NOTE: toolbar implementation is at end,
following complete menu implementation. */
@@ -71,6 +75,12 @@ void
free_frame_menubar (struct frame *f)
{
id menu = [NSApp mainMenu];
+
+ if (f != last_menubar_frame)
+ return;
+
+ last_menubar_frame = NULL;
+
for (int i = [menu numberOfItems] - 1 ; i >= 0; i--)
{
NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i];
@@ -135,9 +145,9 @@ ns_update_menubar (struct frame *f, bool deep_p)
#endif
return;
}
- XSETFRAME (Vmenu_updating_frame, f);
-/*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */
+ XSETFRAME (Vmenu_updating_frame, f);
+ last_menubar_frame = f;
block_input ();
/* Menu may have been created automatically; if so, discard it. */
@@ -155,7 +165,7 @@ ns_update_menubar (struct frame *f, bool deep_p)
#if NSMENUPROFILE
ftime (&tb);
- t = -(1000*tb.time+tb.millitm);
+ t = -(1000 * tb.time + tb.millitm);
#endif
if (deep_p)
@@ -164,7 +174,7 @@ ns_update_menubar (struct frame *f, bool deep_p)
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
@@ -413,7 +423,7 @@ ns_update_menubar (struct frame *f, bool deep_p)
#if NSMENUPROFILE
ftime (&tb);
- t += 1000*tb.time+tb.millitm;
+ t += 1000 * tb.time + tb.millitm;
fprintf (stderr, "Menu update took %ld msec.\n", t);
#endif
@@ -649,7 +659,8 @@ prettify_key (const char *key)
work around it by using tabs to split the title into two
columns. */
NSFont *menuFont = [NSFont menuFontOfSize:0];
- NSDictionary *font_attribs = @{NSFontAttributeName: menuFont};
+ NSDictionary *font_attribs = [NSDictionary dictionaryWithObjectsAndKeys:
+ menuFont, NSFontAttributeName, nil];
CGFloat maxNameWidth = 0;
CGFloat maxKeyWidth = 0;
@@ -677,11 +688,12 @@ prettify_key (const char *key)
NSTextTab *tab =
[[[NSTextTab alloc] initWithTextAlignment: NSTextAlignmentRight
location: maxWidth
- options: @{}] autorelease];
+ options: [NSDictionary dictionary]] autorelease];
NSMutableParagraphStyle *pstyle = [[[NSMutableParagraphStyle alloc] init]
autorelease];
- [pstyle setTabStops: @[tab]];
- attributes = @{NSParagraphStyleAttributeName: pstyle};
+ [pstyle setTabStops: [NSArray arrayWithObject:tab]];
+ attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+ pstyle, NSParagraphStyleAttributeName, nil];
#endif
/* clear existing contents */
@@ -739,15 +751,15 @@ prettify_key (const char *key)
/* p = [view convertPoint:p fromView: nil]; */
p.y = NSHeight ([view frame]) - p.y;
e = [[view window] currentEvent];
- event = [NSEvent mouseEventWithType: NSEventTypeRightMouseDown
- location: p
- modifierFlags: 0
- timestamp: [e timestamp]
- windowNumber: [[view window] windowNumber]
- context: nil
- eventNumber: 0 /* [e eventNumber] */
- clickCount: 1
- pressure: 0];
+ event = [NSEvent mouseEventWithType: NSEventTypeRightMouseDown
+ location: p
+ modifierFlags: 0
+ timestamp: [e timestamp]
+ windowNumber: [[view window] windowNumber]
+ context: nil
+ eventNumber: 0 /* [e eventNumber] */
+ clickCount: 1
+ pressure: 0];
context_menu_value = -1;
[NSMenu popUpContextMenu: self withEvent: event forView: view];
@@ -758,6 +770,45 @@ prettify_key (const char *key)
: Qnil;
}
+- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item
+{
+ NSInteger idx = [item tag];
+ struct frame *f = SELECTED_FRAME ();
+ Lisp_Object vec = f->menu_bar_vector;
+ Lisp_Object help, frame, *client_data;
+
+ XSETFRAME (frame, f);
+
+ /* This menu isn't a menubar, so use the pointer to the popup menu
+ data. */
+ if (context_menu_value != 0)
+ {
+ client_data = (Lisp_Object *) idx;
+
+ if (client_data)
+ help = client_data[MENU_ITEMS_ITEM_HELP];
+ else
+ help = Qnil;
+ }
+ /* Just dismiss any help-echo that might already be in progress if
+ no menu item will be highlighted. */
+ else if (item == nil || idx <= 0)
+ help = Qnil;
+ else
+ {
+ if (idx >= ASIZE (vec))
+ return;
+
+ /* Otherwise, get the help data from the menu bar vector. */
+ help = AREF (vec, idx + MENU_ITEMS_ITEM_HELP);
+ }
+
+ popup_activated_flag++;
+ if (STRINGP (help) || NILP (help))
+ show_help_echo (help, Qnil, Qnil, Qnil);
+ popup_activated_flag--;
+}
+
#ifdef NS_IMPL_GNUSTEP
- (void) close
{
@@ -777,6 +828,25 @@ prettify_key (const char *key)
/* GNUstep seems to have a number of required methods in
NSMenuDelegate that are optional in Cocoa. */
+- (BOOL) menu: (NSMenu*) menu updateItem: (NSMenuItem*) item
+ atIndex: (NSInteger) index shouldCancel: (BOOL) shouldCancel
+{
+ return YES;
+}
+
+- (BOOL) menuHasKeyEquivalent: (NSMenu*) menu
+ forEvent: (NSEvent*) event
+ target: (id*) target
+ action: (SEL*) action
+{
+ return NO;
+}
+
+- (NSInteger) numberOfItemsInMenu: (NSMenu*) menu
+{
+ return [super numberOfItemsInMenu: menu];
+}
+
- (void) menuWillOpen:(NSMenu *)menu
{
}
@@ -790,10 +860,6 @@ prettify_key (const char *key)
{
return NSZeroRect;
}
-
-- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
-{
-}
#endif
@end /* EmacsMenu */
@@ -813,37 +879,35 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
EmacsMenu *pmenu;
NSPoint p;
Lisp_Object tem;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count;
widget_value *wv, *first_wv = 0;
+ widget_value *save_wv = 0, *prev_wv = 0;
+ widget_value **submenu_stack;
+ int submenu_depth = 0;
+ int first_pane = 1;
+ int i;
bool keymaps = (menuflags & MENU_KEYMAPS);
+ USE_SAFE_ALLOCA;
+
NSTRACE ("ns_menu_show");
block_input ();
p.x = x; p.y = y;
- /* Don't GC due to a mysterious bug. */
- inhibit_garbage_collection ();
-
/* now parse stage 2 as in ns_update_menubar */
wv = make_widget_value ("contextmenu", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
first_wv = wv;
-#if 0
- /* FIXME: a couple of one-line differences prevent reuse. */
- wv = digest_single_submenu (0, menu_items_used, 0);
-#else
- {
- widget_value *save_wv = 0, *prev_wv = 0;
- widget_value **submenu_stack
- = alloca (menu_items_used * sizeof *submenu_stack);
- /* Lisp_Object *subprefix_stack
- = alloca (menu_items_used * sizeof *subprefix_stack); */
- int submenu_depth = 0;
- int first_pane = 1;
- int i;
+ submenu_stack
+ = SAFE_ALLOCA (menu_items_used * sizeof *submenu_stack);
+
+ specpdl_count = SPECPDL_INDEX ();
+
+ /* Don't GC due to a mysterious bug. */
+ inhibit_garbage_collection ();
/* Loop over all panes and items, filling in the tree. */
i = 0;
@@ -973,8 +1037,6 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
i += MENU_ITEMS_ITEM_LENGTH;
}
}
- }
-#endif
if (!NILP (title))
{
@@ -1009,6 +1071,8 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
unbind_to (specpdl_count, Qnil);
unblock_input ();
+
+ SAFE_FREE ();
return tem;
}
@@ -1433,6 +1497,15 @@ update_frame_tool_bar (struct frame *f)
[timer retain];
}
+- (void) moveTo: (NSPoint) screen_point
+{
+ [win setFrame: NSMakeRect (screen_point.x,
+ screen_point.y,
+ [self frame].size.width,
+ [self frame].size.height)
+ display: YES];
+}
+
- (void) hide
{
[win close];
@@ -1472,31 +1545,38 @@ pop_down_menu (void *arg)
if (popup_activated_flag)
{
- block_input ();
popup_activated_flag = 0;
[panel close];
+ /* For some reason this is required on macOS, or the selected
+ frame gets the keyboard focus but doesn't become
+ highlighted. */
+#ifdef NS_IMPL_COCOA
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
- unblock_input ();
+#endif
+ discard_menu_items ();
}
}
-
Lisp_Object
ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
{
- id dialog;
+ EmacsDialogPanel *dialog;
Lisp_Object tem, title;
NSPoint p;
- BOOL isQ;
+ BOOL is_question;
+ const char *error_name;
+ specpdl_ref specpdl_count;
NSTRACE ("ns_popup_dialog");
+ specpdl_count = SPECPDL_INDEX ();
- isQ = NILP (header);
-
+ is_question = NILP (header);
check_window_system (f);
- p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2;
- p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2;
+ p.x = ((int) f->left_pos
+ + ((int) FRAME_COLUMN_WIDTH (f) * f->text_cols) / 2);
+ p.y = ((int) f->top_pos
+ + (FRAME_LINE_HEIGHT (f) * f->text_lines) / 2);
title = Fcar (contents);
CHECK_STRING (title);
@@ -1506,21 +1586,30 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
the dialog. */
contents = list2 (title, Fcons (build_string ("Ok"), Qt));
- block_input ();
- dialog = [[EmacsDialogPanel alloc] initFromContents: contents
- isQuestion: isQ];
-
- {
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect_void (unuse_menu_items);
+ list_of_panes (list1 (contents));
- record_unwind_protect_ptr (pop_down_menu, dialog);
- popup_activated_flag = 1;
- tem = [dialog runDialogAt: p];
- unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */
- }
+ block_input ();
+ dialog = [[EmacsDialogPanel alloc] initWithTitle: SSDATA (title)
+ isQuestion: is_question];
+ [dialog processMenuItems: menu_items
+ used: menu_items_used
+ withErrorOutput: &error_name];
+ [dialog resizeBoundsPriorToDisplay];
unblock_input ();
+ if (error_name)
+ {
+ discard_menu_items ();
+ [dialog close];
+ error ("%s", error_name);
+ }
+
+ record_unwind_protect_ptr (pop_down_menu, dialog);
+ popup_activated_flag = 1;
+ tem = [dialog runDialogAt: p];
+ unbind_to (specpdl_count, Qnil);
return tem;
}
@@ -1561,7 +1650,6 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
NSImage *img;
dialog_return = Qundefined;
- button_values = NULL;
area.origin.x = 3*SPACER;
area.origin.y = 2*SPACER;
area.size.width = ICONSIZE;
@@ -1645,58 +1733,65 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
}
-- (BOOL)windowShouldClose: (id)sender
+- (BOOL)windowShouldClose: (id) sender
{
window_closed = YES;
- [NSApp stop:self];
+ [NSApp stop: self];
return NO;
}
-- (void)dealloc
+- (void) dealloc
{
- xfree (button_values);
[super dealloc];
}
-- (void)process_dialog: (Lisp_Object) list
+- (void) processMenuItems: (Lisp_Object) menu_items
+ used: (ptrdiff_t) menu_items_used
+ withErrorOutput: (const char **) error_name
{
- Lisp_Object item, lst = list;
- int row = 0;
- int buttons = 0, btnnr = 0;
+ int i, nb_buttons = 0, row = 0;
+ Lisp_Object item_name, enable;
- for (; CONSP (lst); lst = XCDR (lst))
+ i = MENU_ITEMS_PANE_LENGTH;
+ *error_name = NULL;
+
+ /* Loop over all panes and items, filling in the tree. */
+ while (i < menu_items_used)
{
- item = XCAR (list);
- if (CONSP (item))
- ++buttons;
- }
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
- if (buttons > 0)
- button_values = xmalloc (buttons * sizeof *button_values);
+ if (NILP (item_name))
+ {
+ *error_name = "Submenu in dialog items";
+ return;
+ }
- for (; CONSP (list); list = XCDR (list))
- {
- item = XCAR (list);
- if (STRINGP (item))
- {
- [self addString: SSDATA (item) row: row++];
- }
- else if (CONSP (item))
- {
- button_values[btnnr] = XCDR (item);
- [self addButton: SSDATA (XCAR (item)) value: btnnr row: row++];
- ++btnnr;
- }
- else if (NILP (item))
- {
- [self addSplit];
- row = 0;
- }
+ if (EQ (item_name, Qquote))
+ /* This is the boundary between elements on the left and those
+ on the right, but that boundary is currently not handled on
+ NS. */
+ continue;
+
+ if (nb_buttons > 9)
+ {
+ *error_name = "Too many dialog items";
+ return;
+ }
+
+ [self addButton: SSDATA (item_name)
+ value: (NSInteger) aref_addr (menu_items, i)
+ row: row++
+ enable: !NILP (enable)];
+
+ i += MENU_ITEMS_ITEM_LENGTH;
+ nb_buttons++;
}
}
-- (void)addButton: (char *)str value: (int)tag row: (int)row
+- (void) addButton: (char *) str value: (NSInteger) tag
+ row: (int) row enable: (BOOL) enable
{
id cell;
@@ -1705,7 +1800,8 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
[matrix addRow];
rows++;
}
- cell = [matrix cellAtRow: row column: cols-1];
+
+ cell = [matrix cellAtRow: row column: cols - 1];
[cell setTarget: self];
[cell setAction: @selector (clicked: )];
[cell setTitle: [NSString stringWithUTF8String: str]];
@@ -1715,7 +1811,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
}
-- (void)addString: (char *)str row: (int)row
+- (void)addString: (char *) str row: (int) row
{
id cell;
@@ -1738,96 +1834,95 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
}
-- (void)clicked: sender
+- (void) clicked: sender
{
NSArray *sellist = nil;
- EMACS_INT seltag;
+ NSUInteger seltag;
+ Lisp_Object *selarray;
sellist = [sender selectedCells];
+
if ([sellist count] < 1)
return;
seltag = [[sellist objectAtIndex: 0] tag];
- dialog_return = button_values[seltag];
- [NSApp stop:self];
+ selarray = (void *) seltag;
+ dialog_return = selarray[MENU_ITEMS_ITEM_VALUE];
+ [NSApp stop: self];
}
-- (instancetype)initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ
+- (instancetype) initWithTitle: (char *) title_string
+ isQuestion: (BOOL) is_question
{
- Lisp_Object head;
[super init];
- if (CONSP (contents))
- {
- head = Fcar (contents);
- [self process_dialog: Fcdr (contents)];
- }
- else
- head = contents;
+ if (title_string)
+ [title setStringValue:
+ [NSString stringWithUTF8String: title_string]];
- if (STRINGP (head))
- [title setStringValue:
- [NSString stringWithUTF8String: SSDATA (head)]];
- else if (isQ == YES)
- [title setStringValue: @"Question"];
+ if (is_question)
+ [command setStringValue: @"Question"];
else
- [title setStringValue: @"Information"];
+ [command setStringValue: @"Information"];
- {
- int i;
- NSRect r, s, t;
+ return self;
+}
- if (cols == 1 && rows > 1) /* Never told where to split. */
- {
- [matrix addColumn];
- for (i = 0; i < rows/2; i++)
- {
- [matrix putCell: [matrix cellAtRow: (rows+1)/2 column: 0]
- atRow: i column: 1];
- [matrix removeRow: (rows+1)/2];
- }
- }
+- (void) resizeBoundsPriorToDisplay
+{
+ int i;
+ NSRect r, s, t;
+ NSSize csize;
- [matrix sizeToFit];
+ if (cols == 1 && rows > 1)
{
- NSSize csize = [matrix cellSize];
- if (csize.width < MINCELLWIDTH)
- {
- csize.width = MINCELLWIDTH;
- [matrix setCellSize: csize];
- [matrix sizeToCells];
- }
+ [matrix addColumn];
+ for (i = 0; i < rows / 2; i++)
+ {
+ [matrix putCell: [matrix cellAtRow: (rows + 1) /2
+ column: 0]
+ atRow: i column: 1];
+ [matrix removeRow: (rows + 1) / 2];
+ }
}
- [title sizeToFit];
- [command sizeToFit];
+ [matrix sizeToFit];
- t = [matrix frame];
- r = [title frame];
- if (r.size.width+r.origin.x > t.size.width+t.origin.x)
- {
- t.origin.x = r.origin.x;
- t.size.width = r.size.width;
- }
- r = [command frame];
- if (r.size.width+r.origin.x > t.size.width+t.origin.x)
- {
- t.origin.x = r.origin.x;
- t.size.width = r.size.width;
- }
+ csize = [matrix cellSize];
+ if (csize.width < MINCELLWIDTH)
+ {
+ csize.width = MINCELLWIDTH;
+ [matrix setCellSize: csize];
+ [matrix sizeToCells];
+ }
- r = [self frame];
- s = [(NSView *)[self contentView] frame];
- r.size.width += t.origin.x+t.size.width +2*SPACER-s.size.width;
- r.size.height += t.origin.y+t.size.height+SPACER-s.size.height;
- [self setFrame: r display: NO];
- }
+ [title sizeToFit];
+ [command sizeToFit];
- return self;
-}
+ t = [matrix frame];
+ r = [title frame];
+ if (r.size.width + r.origin.x > t.size.width + t.origin.x)
+ {
+ t.origin.x = r.origin.x;
+ t.size.width = r.size.width;
+ }
+ r = [command frame];
+ if (r.size.width + r.origin.x > t.size.width + t.origin.x)
+ {
+ t.origin.x = r.origin.x;
+ t.size.width = r.size.width;
+ }
+ r = [self frame];
+ s = [(NSView *) [self contentView] frame];
+ r.size.width += (t.origin.x + t.size.width
+ + 2 * SPACER - s.size.width);
+ r.size.height += (t.origin.y + t.size.height
+ + SPACER - s.size.height);
+ [self setFrame: r display: NO];
+}
- (void)timeout_handler: (NSTimer *)timedEntry
{
@@ -1845,11 +1940,11 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
/* We use stop because stopModal/abortModal out of the main loop
does not seem to work in 10.6. But as we use stop we must send a
real event so the stop is seen and acted upon. */
- [NSApp stop:self];
+ [NSApp stop: self];
[NSApp postEvent: nxev atStart: NO];
}
-- (Lisp_Object)runDialogAt: (NSPoint)p
+- (Lisp_Object) runDialogAt: (NSPoint) p
{
Lisp_Object ret = Qundefined;
@@ -1869,13 +1964,17 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
[[NSRunLoop currentRunLoop] addTimer: tmo
forMode: NSModalPanelRunLoopMode];
}
+
timer_fired = NO;
dialog_return = Qundefined;
[NSApp runModalForWindow: self];
ret = dialog_return;
- if (! timer_fired)
+
+ if (!timer_fired)
{
- if (tmo != nil) [tmo invalidate]; /* Cancels timer. */
+ if (tmo != nil)
+ [tmo invalidate]; /* Cancels timer. */
+
break;
}
}
diff --git a/src/nsselect.m b/src/nsselect.m
index 13ca9b9c442..c46bfeaf42a 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -17,13 +17,11 @@ 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 <https://www.gnu.org/licenses/>. */
-/*
-Originally by Carl Edman
-Updated by Christian Limpach (chris@nice.ch)
-OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
-macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
-GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
-*/
+/* Originally by Carl Edman
+ Updated by Christian Limpach (chris@nice.ch)
+ OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
+ macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
+ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) */
/* This should be the first include, as it may set up #defines affecting
interpretation of even the system includes. */
@@ -250,7 +248,7 @@ ns_get_foreign_selection (Lisp_Object symbol, Lisp_Object target)
NSString *type;
NSEnumerator *e = [[pb types] objectEnumerator];
- while (type = [e nextObject])
+ while ((type = [e nextObject]))
{
NSString *val = [typeLookup valueForKey:type];
if (val && ! [types containsObject:val])
@@ -559,6 +557,225 @@ nxatoms_of_nsselect (void)
nil] retain];
}
+static void
+ns_decode_data_to_pasteboard (Lisp_Object type, Lisp_Object data,
+ NSPasteboard *pasteboard)
+{
+ NSArray *types, *new;
+ NSMutableArray *temp;
+ Lisp_Object tem;
+ specpdl_ref count;
+#if !NS_USE_NSPasteboardTypeFileURL
+ NSURL *url;
+#endif
+
+ types = [pasteboard types];
+ count = SPECPDL_INDEX ();
+
+ CHECK_SYMBOL (type);
+
+ if (EQ (type, Qstring))
+ {
+ CHECK_STRING (data);
+
+ new = [types arrayByAddingObject: NSPasteboardTypeString];
+
+ [pasteboard declareTypes: new
+ owner: nil];
+ [pasteboard setString: [NSString stringWithLispString: data]
+ forType: NSPasteboardTypeString];
+ }
+ else if (EQ (type, Qfile))
+ {
+#if NS_USE_NSPasteboardTypeFileURL
+ if (CONSP (data))
+ new = [types arrayByAddingObject: NSPasteboardTypeURL];
+ else
+ new = [types arrayByAddingObject: NSPasteboardTypeFileURL];
+#else
+ new = [types arrayByAddingObject: NSFilenamesPboardType];
+#endif
+
+ [pasteboard declareTypes: new
+ owner: nil];
+
+ if (STRINGP (data))
+ {
+#if NS_USE_NSPasteboardTypeFileURL
+ [pasteboard setString: [NSString stringWithLispString: data]
+ forType: NSPasteboardTypeFileURL];
+#else
+ url = [NSURL URLWithString: [NSString stringWithLispString: data]];
+
+ if (!url)
+ signal_error ("Invalid file URL", data);
+
+ [pasteboard setString: [url path]
+ forType: NSFilenamesPboardType];
+#endif
+ }
+ else
+ {
+ CHECK_LIST (data);
+ temp = [[NSMutableArray alloc] init];
+ record_unwind_protect_ptr (ns_release_object, temp);
+
+ for (tem = data; CONSP (tem); tem = XCDR (tem))
+ {
+ CHECK_STRING (XCAR (tem));
+
+ [temp addObject: [NSString stringWithLispString: XCAR (tem)]];
+ }
+ CHECK_LIST_END (tem, data);
+#if NS_USE_NSPasteboardTypeFileURL
+ [pasteboard setPropertyList: temp
+ /* We have to use this deprecated pasteboard
+ type, since Apple doesn't let us use
+ dragImage:at: to drag multiple file URLs. */
+ forType: @"NSFilenamesPboardType"];
+#else
+ [pasteboard setPropertyList: temp
+ forType: NSFilenamesPboardType];
+#endif
+ unbind_to (count, Qnil);
+ }
+ }
+ else
+ signal_error ("Unknown pasteboard type", type);
+}
+
+static void
+ns_lisp_to_pasteboard (Lisp_Object object,
+ NSPasteboard *pasteboard)
+{
+ Lisp_Object tem, type, data;
+
+ [pasteboard declareTypes: [NSArray array]
+ owner: nil];
+
+ CHECK_LIST (object);
+ for (tem = object; CONSP (tem); tem = XCDR (tem))
+ {
+ maybe_quit ();
+
+ type = Fcar (Fcar (tem));
+ data = Fcdr (Fcar (tem));
+
+ ns_decode_data_to_pasteboard (type, data, pasteboard);
+ }
+ CHECK_LIST_END (tem, object);
+}
+
+static NSDragOperation
+ns_dnd_action_to_operation (Lisp_Object action)
+{
+ if (EQ (action, QXdndActionCopy))
+ return NSDragOperationCopy;
+
+ if (EQ (action, QXdndActionMove))
+ return NSDragOperationMove;
+
+ if (EQ (action, QXdndActionLink))
+ return NSDragOperationLink;
+
+ signal_error ("Unsupported drag-and-drop action", action);
+}
+
+static Lisp_Object
+ns_dnd_action_from_operation (NSDragOperation operation)
+{
+ switch (operation)
+ {
+ case NSDragOperationCopy:
+ return QXdndActionCopy;
+
+ case NSDragOperationMove:
+ return QXdndActionMove;
+
+ case NSDragOperationLink:
+ return QXdndActionLink;
+
+ case NSDragOperationNone:
+ return Qnil;
+
+ default:
+ return QXdndActionPrivate;
+ }
+}
+
+DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 6, 0,
+ doc: /* Begin a drag-and-drop operation on FRAME.
+
+FRAME must be a window system frame. PBOARD is an alist of (TYPE
+. DATA), where TYPE is one of the following data types that determine
+the meaning of DATA:
+
+ - `string' means DATA should be a string describing text that will
+ be dragged to another program.
+
+ - `file' means DATA should be a file URL that will be dragged to
+ another program. DATA may also be a list of file names; that
+ means each file in the list will be dragged to another program.
+
+ACTION is the action that will be taken by the drop target towards the
+data inside PBOARD.
+
+Return the action that the drop target actually chose to perform, or
+nil if no action was performed (either because there was no drop
+target, or the drop was rejected). If RETURN-FRAME is the symbol
+`now', also return any frame that mouse moves into during the
+drag-and-drop operation, whilst simultaneously cancelling it. Any
+other non-nil value means to do the same, but to wait for the mouse to
+leave FRAME first.
+
+If ALLOW-SAME-FRAME is nil, dropping on FRAME will result in the drop
+being ignored.
+
+FOLLOW-TOOLTIP means the same thing it does in `x-begin-drag'. */)
+ (Lisp_Object frame, Lisp_Object pboard, Lisp_Object action,
+ Lisp_Object return_frame, Lisp_Object allow_same_frame,
+ Lisp_Object follow_tooltip)
+{
+ struct frame *f, *return_to;
+ NSPasteboard *pasteboard;
+ EmacsWindow *window;
+ NSDragOperation operation;
+ enum ns_return_frame_mode mode;
+ Lisp_Object val;
+
+ if (EQ (return_frame, Qnow))
+ mode = RETURN_FRAME_NOW;
+ else if (!NILP (return_frame))
+ mode = RETURN_FRAME_EVENTUALLY;
+ else
+ mode = RETURN_FRAME_NEVER;
+
+ if (NILP (pboard))
+ signal_error ("Empty pasteboard", pboard);
+
+ f = decode_window_system_frame (frame);
+ pasteboard = [NSPasteboard pasteboardWithName: NSPasteboardNameDrag];
+ window = (EmacsWindow *) [FRAME_NS_VIEW (f) window];
+
+ operation = ns_dnd_action_to_operation (action);
+ ns_lisp_to_pasteboard (pboard, pasteboard);
+
+ operation = [window beginDrag: operation
+ forPasteboard: pasteboard
+ withMode: mode
+ returnFrameTo: &return_to
+ prohibitSame: (BOOL) NILP (allow_same_frame)
+ followTooltip: (BOOL) !NILP (follow_tooltip)];
+
+ if (return_to)
+ {
+ XSETFRAME (val, return_to);
+ return val;
+ }
+
+ return ns_dnd_action_from_operation (operation);
+}
+
void
syms_of_nsselect (void)
{
@@ -568,12 +785,18 @@ syms_of_nsselect (void)
DEFSYM (QFILE_NAME, "FILE_NAME");
DEFSYM (QTARGETS, "TARGETS");
+ DEFSYM (QXdndActionCopy, "XdndActionCopy");
+ DEFSYM (QXdndActionMove, "XdndActionMove");
+ DEFSYM (QXdndActionLink, "XdndActionLink");
+ DEFSYM (QXdndActionPrivate, "XdndActionPrivate");
+ DEFSYM (Qnow, "now");
defsubr (&Sns_disown_selection_internal);
defsubr (&Sns_get_selection);
defsubr (&Sns_own_selection_internal);
defsubr (&Sns_selection_exists_p);
defsubr (&Sns_selection_owner_p);
+ defsubr (&Sns_begin_drag);
Vselection_alist = Qnil;
staticpro (&Vselection_alist);
diff --git a/src/nsterm.h b/src/nsterm.h
index f0276461231..7a097b32489 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -408,23 +408,48 @@ typedef id instancetype;
@end
#endif
+enum ns_return_frame_mode
+ {
+ RETURN_FRAME_NEVER,
+ RETURN_FRAME_EVENTUALLY,
+ RETURN_FRAME_NOW,
+ };
+
/* EmacsWindow */
@interface EmacsWindow : NSWindow
{
NSPoint grabOffset;
+ NSEvent *last_drag_event;
+ NSDragOperation drag_op;
+ NSDragOperation selected_op;
+
+ struct frame *dnd_return_frame;
+ enum ns_return_frame_mode dnd_mode;
+ BOOL dnd_allow_same_frame;
+ BOOL dnd_move_tooltip_with_frame;
}
#ifdef NS_IMPL_GNUSTEP
- (NSInteger) orderedIndex;
#endif
-- (instancetype)initWithEmacsFrame:(struct frame *)f;
-- (instancetype)initWithEmacsFrame:(struct frame *)f fullscreen:(BOOL)fullscreen screen:(NSScreen *)screen;
-- (void)createToolbar:(struct frame *)f;
-- (void)setParentChildRelationships;
-- (NSInteger)borderWidth;
-- (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above;
-- (void)setAppearance;
+- (instancetype) initWithEmacsFrame: (struct frame *) f;
+- (instancetype) initWithEmacsFrame: (struct frame *) f
+ fullscreen: (BOOL) fullscreen
+ screen: (NSScreen *) screen;
+- (void) createToolbar: (struct frame *) f;
+- (void) setParentChildRelationships;
+- (NSInteger) borderWidth;
+- (BOOL) restackWindow: (NSWindow *) win above: (BOOL) above;
+- (void) setAppearance;
+- (void) setLastDragEvent: (NSEvent *) event;
+- (NSDragOperation) beginDrag: (NSDragOperation) op
+ forPasteboard: (NSPasteboard *) pasteboard
+ withMode: (enum ns_return_frame_mode) mode
+ returnFrameTo: (struct frame **) frame_return
+ prohibitSame: (BOOL) prohibit_same_frame
+ followTooltip: (BOOL) follow_tooltip;
+- (BOOL) mustNotDropOn: (NSView *) receiver;
@end
@@ -442,23 +467,25 @@ typedef id instancetype;
#else
@interface EmacsView : NSView <NSTextInput>
#endif
- {
+{
#ifdef NS_IMPL_COCOA
- char *old_title;
- BOOL maximizing_resize;
+ char *old_title;
+ BOOL maximizing_resize;
#endif
- BOOL windowClosing;
- NSString *workingText;
- BOOL processingCompose;
- int fs_state, fs_before_fs, next_maximized;
- int maximized_width, maximized_height;
- EmacsWindow *nonfs_window;
- BOOL fs_is_native;
+ BOOL font_panel_active;
+ NSFont *font_panel_result;
+ BOOL windowClosing;
+ NSString *workingText;
+ BOOL processingCompose;
+ int fs_state, fs_before_fs, next_maximized;
+ int maximized_width, maximized_height;
+ EmacsWindow *nonfs_window;
+ BOOL fs_is_native;
@public
- struct frame *emacsframe;
- int scrollbarsNeedingUpdate;
- NSRect ns_userRect;
- }
+ struct frame *emacsframe;
+ int scrollbarsNeedingUpdate;
+ NSRect ns_userRect;
+}
/* AppKit-side interface */
- (instancetype)menuDown: (id)sender;
@@ -485,9 +512,10 @@ typedef id instancetype;
#ifdef NS_IMPL_GNUSTEP
- (void)windowDidMove: (id)sender;
#endif
+- (Lisp_Object) showFontPanel;
- (int)fullscreenState;
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
- (void)lockFocus;
- (void)unlockFocus;
#endif
@@ -571,22 +599,32 @@ typedef id instancetype;
========================================================================== */
@interface EmacsDialogPanel : NSPanel
- {
- NSTextField *command;
- NSTextField *title;
- NSMatrix *matrix;
- int rows, cols;
- BOOL timer_fired, window_closed;
- Lisp_Object dialog_return;
- Lisp_Object *button_values;
- }
-- (instancetype)initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ;
-- (void)process_dialog: (Lisp_Object)list;
-- (void)addButton: (char *)str value: (int)tag row: (int)row;
-- (void)addString: (char *)str row: (int)row;
-- (void)addSplit;
-- (Lisp_Object)runDialogAt: (NSPoint)p;
-- (void)timeout_handler: (NSTimer *)timedEntry;
+{
+ NSTextField *command;
+ NSTextField *title;
+ NSMatrix *matrix;
+ int rows, cols;
+ BOOL timer_fired, window_closed;
+ Lisp_Object dialog_return;
+}
+
+- (instancetype) initWithTitle: (char *) title_str
+ isQuestion: (BOOL) is_question;
+- (void) processMenuItems: (Lisp_Object) menu_items
+ used: (ptrdiff_t) menu_items_used
+ withErrorOutput: (const char **) error_name;
+
+- (void) addButton: (char *) str
+ value: (NSInteger) tag
+ row: (int) row
+ enable: (BOOL) enable;
+- (void) addString: (char *) str
+ row: (int) row;
+- (void) addSplit;
+- (void) resizeBoundsPriorToDisplay;
+
+- (Lisp_Object) runDialogAt: (NSPoint) p;
+- (void) timeout_handler: (NSTimer *) timedEntry;
@end
#ifdef NS_IMPL_COCOA
@@ -594,19 +632,21 @@ typedef id instancetype;
#else
@interface EmacsTooltip : NSObject
#endif
- {
- NSWindow *win;
- NSTextField *textField;
- NSTimer *timer;
- }
+{
+ NSWindow *win;
+ NSTextField *textField;
+ NSTimer *timer;
+}
+
- (instancetype) init;
-- (void) setText: (char *)text;
-- (void) setBackgroundColor: (NSColor *)col;
-- (void) setForegroundColor: (NSColor *)col;
-- (void) showAtX: (int)x Y: (int)y for: (int)seconds;
+- (void) setText: (char *) text;
+- (void) setBackgroundColor: (NSColor *) col;
+- (void) setForegroundColor: (NSColor *) col;
+- (void) showAtX: (int) x Y: (int) y for: (int) seconds;
- (void) hide;
- (BOOL) isActive;
- (NSRect) frame;
+- (void) moveTo: (NSPoint) screen_point;
@end
@@ -684,6 +724,7 @@ typedef id instancetype;
int em_whole;
}
+- (void) mark;
- (instancetype) initFrame: (NSRect )r window: (Lisp_Object)win;
- (void)setFrame: (NSRect)r;
@@ -698,7 +739,7 @@ typedef id instancetype;
+ (CGFloat)scrollerWidth;
@end
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
@interface EmacsLayer : CALayer
{
NSMutableArray *cache;
@@ -1104,6 +1145,9 @@ extern const char *ns_get_pending_menu_title (void);
#endif
/* Implemented in nsfns, published in nsterm. */
+#ifdef __OBJC__
+extern void ns_move_tooltip_to_mouse_location (NSPoint);
+#endif
extern void ns_implicitly_set_name (struct frame *f, Lisp_Object arg,
Lisp_Object oldval);
extern void ns_set_scroll_bar_default_width (struct frame *f);
@@ -1173,6 +1217,7 @@ extern size_t ns_image_size_in_bytes (void *img);
/* This in nsterm.m */
extern float ns_antialias_threshold;
extern void ns_make_frame_visible (struct frame *f);
+extern void ns_make_frame_invisible (struct frame *f);
extern void ns_iconify_frame (struct frame *f);
extern void ns_set_undecorated (struct frame *f, Lisp_Object new_value,
Lisp_Object old_value);
@@ -1290,6 +1335,7 @@ extern char gnustep_base_version[]; /* version tracking */
#define NSAlertStyleCritical NSCriticalAlertStyle
#define NSControlSizeRegular NSRegularControlSize
#define NSCompositingOperationCopy NSCompositeCopy
+#define NSTextAlignmentRight NSRightTextAlignment
/* And adds NSWindowStyleMask. */
#ifdef __OBJC__
@@ -1308,6 +1354,7 @@ enum NSWindowTabbingMode
#if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_13)
/* Deprecated in macOS 10.13. */
#define NSPasteboardNameGeneral NSGeneralPboard
+#define NSPasteboardNameDrag NSDragPboard
#endif
#if !defined (NS_IMPL_COCOA) || !defined (MAC_OS_X_VERSION_10_14)
@@ -1325,5 +1372,9 @@ enum NSWindowTabbingMode
#define NSControlStateValueOn NSOnState
#define NSControlStateValueOff NSOffState
#define NSBezelStyleRounded NSRoundedBezelStyle
+#define NSButtonTypeMomentaryPushIn NSMomentaryPushInButton
#endif
+
+extern void mark_nsterm (void);
+
#endif /* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
index a15dc47a226..7f232e72922 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -79,6 +79,9 @@ static EmacsMenu *dockMenu;
static EmacsMenu *mainMenu;
#endif
+/* The last known monitor attributes list. */
+static Lisp_Object last_known_monitors;
+
/* ==========================================================================
NSTRACE, Trace support.
@@ -89,8 +92,8 @@ static EmacsMenu *mainMenu;
/* The following use "volatile" since they can be accessed from
parallel threads. */
-volatile int nstrace_num = 0;
-volatile int nstrace_depth = 0;
+volatile int nstrace_num;
+volatile int nstrace_depth;
/* When 0, no trace is emitted. This is used by NSTRACE_WHEN and
NSTRACE_UNLESS to silence functions called.
@@ -101,33 +104,41 @@ volatile int nstrace_depth = 0;
volatile int nstrace_enabled_global = 1;
/* Called when nstrace_enabled goes out of scope. */
-void nstrace_leave(int * pointer_to_nstrace_enabled)
+void
+nstrace_leave (int *pointer_to_nstrace_enabled)
{
if (*pointer_to_nstrace_enabled)
- {
- --nstrace_depth;
- }
+ --nstrace_depth;
}
/* Called when nstrace_saved_enabled_global goes out of scope. */
-void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global)
+void
+nstrace_restore_global_trace_state (int *pointer_to_saved_enabled_global)
{
nstrace_enabled_global = *pointer_to_saved_enabled_global;
}
-char const * nstrace_fullscreen_type_name (int fs_type)
+const char *
+nstrace_fullscreen_type_name (int fs_type)
{
switch (fs_type)
{
- case -1: return "-1";
- case FULLSCREEN_NONE: return "FULLSCREEN_NONE";
- case FULLSCREEN_WIDTH: return "FULLSCREEN_WIDTH";
- case FULLSCREEN_HEIGHT: return "FULLSCREEN_HEIGHT";
- case FULLSCREEN_BOTH: return "FULLSCREEN_BOTH";
- case FULLSCREEN_MAXIMIZED: return "FULLSCREEN_MAXIMIZED";
- default: return "FULLSCREEN_?????";
+ case -1:
+ return "-1";
+ case FULLSCREEN_NONE:
+ return "FULLSCREEN_NONE";
+ case FULLSCREEN_WIDTH:
+ return "FULLSCREEN_WIDTH";
+ case FULLSCREEN_HEIGHT:
+ return "FULLSCREEN_HEIGHT";
+ case FULLSCREEN_BOTH:
+ return "FULLSCREEN_BOTH";
+ case FULLSCREEN_MAXIMIZED:
+ return "FULLSCREEN_MAXIMIZED";
+ default:
+ return "FULLSCREEN_?????";
}
}
#endif
@@ -163,7 +174,7 @@ char const * nstrace_fullscreen_type_name (int fs_type)
&& NSAppKitVersionNumber >= NSAppKitVersionNumber10_7)
return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]];
#endif
- return [self colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]];
+ return [self colorUsingColorSpace: [NSColorSpace genericRGBColorSpace]];
}
+ (NSColor *)colorWithUnsignedLong:(unsigned long)c
@@ -347,7 +358,7 @@ mod_of_kind (Lisp_Object modifier, Lisp_Object kind)
return modifier;
else
{
- Lisp_Object val = Fplist_get (modifier, kind);
+ Lisp_Object val = plist_get (modifier, kind);
return SYMBOLP (val) ? val : Qnil;
}
}
@@ -429,28 +440,28 @@ ev_modifiers_helper (unsigned int flags, unsigned int left_mask,
/* This is a piece of code which is common to all the event handling
methods. Maybe it should even be a function. */
-#define EV_TRAILER(e) \
- { \
- XSETFRAME (emacs_event->frame_or_window, emacsframe); \
- EV_TRAILER2 (e); \
+#define EV_TRAILER(e) \
+ { \
+ XSETFRAME (emacs_event->frame_or_window, emacsframe); \
+ EV_TRAILER2 (e); \
}
#define EV_TRAILER2(e) \
{ \
- if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
- if (q_event_ptr) \
- { \
- Lisp_Object tem = Vinhibit_quit; \
- Vinhibit_quit = Qt; \
- n_emacs_events_pending++; \
- kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
- Vinhibit_quit = tem; \
- } \
- else \
- hold_event (emacs_event); \
- EVENT_INIT (*emacs_event); \
- ns_send_appdefined (-1); \
- }
+ if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
+ if (q_event_ptr) \
+ { \
+ Lisp_Object tem = Vinhibit_quit; \
+ Vinhibit_quit = Qt; \
+ n_emacs_events_pending++; \
+ kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
+ Vinhibit_quit = tem; \
+ } \
+ else \
+ hold_event (emacs_event); \
+ EVENT_INIT (*emacs_event); \
+ ns_send_appdefined (-1); \
+ }
/* TODO: Get rid of need for these forward declarations. */
@@ -751,7 +762,18 @@ ns_parent_window_rect (struct frame *f)
EmacsView *parentView = FRAME_NS_VIEW (FRAME_PARENT_FRAME (f));
parentRect = [parentView convertRect:[parentView frame]
toView:nil];
+
+#if defined (NS_IMPL_COCOA) && !defined (MAC_OS_X_VERSION_10_7)
+ parentRect.origin = [[parentView window] convertBaseToScreen:parentRect.origin];
+#elif defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ if ([[parentView window]
+ respondsToSelector:@selector(convertRectToScreen:)])
+ parentRect = [[parentView window] convertRectToScreen:parentRect];
+ else
+ parentRect.origin = [[parentView window] convertBaseToScreen:parentRect.origin];
+#else
parentRect = [[parentView window] convertRectToScreen:parentRect];
+#endif
}
else
parentRect = [[[NSScreen screens] objectAtIndex:0] frame];
@@ -788,10 +810,16 @@ ns_row_rect (struct window *w, struct glyph_row *row,
double
ns_frame_scale_factor (struct frame *f)
{
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > 1060
- return [[FRAME_NS_VIEW (f) window] backingScaleFactor];
-#else
+#if defined (NS_IMPL_GNUSTEP) || !defined (MAC_OS_X_VERSION_10_7)
return [[FRAME_NS_VIEW (f) window] userSpaceScaleFactor];
+#elif MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ if ([[FRAME_NS_VIEW (f) window]
+ respondsToSelector:@selector(backingScaleFactor:)])
+ return [[FRAME_NS_VIEW (f) window] backingScaleFactor];
+ else
+ return [[FRAME_NS_VIEW (f) window] userSpaceScaleFactor];
+#else
+ return [[FRAME_NS_VIEW (f) window] backingScaleFactor];
#endif
}
@@ -1060,7 +1088,7 @@ ns_update_end (struct frame *f)
block_input ();
[view unlockFocus];
-#if defined (NS_IMPL_GNUSTEP)
+#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400
[[view window] flushWindow];
#endif
@@ -1127,7 +1155,7 @@ ns_unfocus (struct frame *f)
{
EmacsView *view = FRAME_NS_VIEW (f);
[view unlockFocus];
-#if defined (NS_IMPL_GNUSTEP)
+#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400
[[view window] flushWindow];
#endif
}
@@ -1500,7 +1528,7 @@ ns_make_frame_visible (struct frame *f)
}
-static void
+void
ns_make_frame_invisible (struct frame *f)
/* --------------------------------------------------------------------------
Hide the window (X11 semantics)
@@ -1691,10 +1719,8 @@ ns_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
static void
-ns_set_window_size (struct frame *f,
- bool change_gravity,
- int width,
- int height)
+ns_set_window_size (struct frame *f, bool change_gravity,
+ int width, int height)
/* --------------------------------------------------------------------------
Adjust window pixel size based on native sizes WIDTH and HEIGHT.
Impl is a bit more complex than other terms, need to do some
@@ -2270,6 +2296,12 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
Lisp_Object frame, tail;
struct frame *f = NULL;
struct ns_display_info *dpyinfo;
+ bool return_no_frame_flag = false;
+#ifdef NS_IMPL_COCOA
+ NSPoint screen_position;
+ NSInteger window_number;
+ NSWindow *w;
+#endif
NSTRACE ("ns_mouse_position");
@@ -2296,32 +2328,56 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
This doesn't work on GNUstep, although in recent versions there
is compatibility code that makes it a noop. */
- NSPoint screen_position = [NSEvent mouseLocation];
- NSInteger window_number = 0;
+ screen_position = [NSEvent mouseLocation];
+ window_number = 0;
+
do
{
- NSWindow *w;
+ window_number = [NSWindow windowNumberAtPoint: screen_position
+ belowWindowWithWindowNumber: window_number];
+ w = [NSApp windowWithWindowNumber: window_number];
- window_number = [NSWindow windowNumberAtPoint:screen_position
- belowWindowWithWindowNumber:window_number];
- w = [NSApp windowWithWindowNumber:window_number];
+ if ((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && w && [[w delegate] isKindOfClass: [EmacsTooltip class]])
+ continue;
- if (w && [[w delegate] isKindOfClass:[EmacsView class]])
- f = ((EmacsView *)[w delegate])->emacsframe;
+ if (w && [[w delegate] isKindOfClass: [EmacsView class]])
+ f = ((EmacsView *) [w delegate])->emacsframe;
+ else if (EQ (track_mouse, Qdrag_source))
+ break;
+
+ if (f && (EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && FRAME_TOOLTIP_P (f))
+ continue;
}
while (window_number > 0 && !f);
#endif
if (!f)
- f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame : SELECTED_FRAME ();
+ {
+ f = (dpyinfo->ns_focus_frame
+ ? dpyinfo->ns_focus_frame : SELECTED_FRAME ());
+ return_no_frame_flag = EQ (track_mouse, Qdrag_source);
+ }
+
+ if (!FRAME_NS_P (f))
+ f = NULL;
+
+ if (f && FRAME_TOOLTIP_P (f))
+ f = dpyinfo->last_mouse_frame;
/* While dropping, use the last mouse frame only if there is no
currently focused frame. */
- if (!f
- && EQ (track_mouse, Qdropping)
+ if (!f && (EQ (track_mouse, Qdropping)
+ || EQ (track_mouse, Qdrag_source))
&& dpyinfo->last_mouse_frame
&& FRAME_LIVE_P (dpyinfo->last_mouse_frame))
- f = dpyinfo->last_mouse_frame;
+ {
+ f = dpyinfo->last_mouse_frame;
+ return_no_frame_flag = EQ (track_mouse, Qdrag_source);
+ }
if (f && FRAME_NS_P (f))
{
@@ -2340,7 +2396,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
if (y) XSETINT (*y, lrint (view_position.y));
if (time)
*time = dpyinfo->last_mouse_movement_time;
- *fp = f;
+ *fp = return_no_frame_flag ? NULL : f;
}
unblock_input ();
@@ -2916,6 +2972,14 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
}
NSBezierPath *bmp = [fringe_bmp objectForKey:[NSNumber numberWithInt:p->which]];
+
+ if (bmp == nil
+ && p->which < max_used_fringe_bitmap)
+ {
+ gui_define_fringe_bitmap (f, p->which);
+ bmp = [fringe_bmp objectForKey: [NSNumber numberWithInt: p->which]];
+ }
+
if (bmp)
{
NSAffineTransform *transform = [NSAffineTransform transform];
@@ -3043,7 +3107,9 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
break;
case HOLLOW_BOX_CURSOR:
draw_phys_cursor_glyph (w, glyph_row, DRAW_NORMAL_TEXT);
- [NSBezierPath strokeRect: r];
+
+ /* This works like it does in PostScript, not X Windows. */
+ [NSBezierPath strokeRect: NSInsetRect (r, 0.5, 0.5)];
break;
case HBAR_CURSOR:
NSRectFill (r);
@@ -3265,7 +3331,11 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
/* If the prev was underlined, match its appearance. */
if (s->prev
&& s->prev->face->underline == FACE_UNDER_LINE
- && s->prev->underline_thickness > 0)
+ && s->prev->underline_thickness > 0
+ && (s->prev->face->underline_at_descent_line_p
+ == s->face->underline_at_descent_line_p)
+ && (s->prev->face->underline_pixels_above_descent_line
+ == s->face->underline_pixels_above_descent_line))
{
thickness = s->prev->underline_thickness;
position = s->prev->underline_position;
@@ -3286,7 +3356,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_underline_at_descent_line, s->w));
- underline_at_descent_line = !(NILP (val) || EQ (val, Qunbound));
+ underline_at_descent_line = (!(NILP (val) || EQ (val, Qunbound))
+ || s->face->underline_at_descent_line_p);
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_use_underline_position_properties, s->w));
@@ -3299,7 +3370,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
/* Determine the offset of underlining from the baseline. */
if (underline_at_descent_line)
- position = descent - thickness;
+ position = (descent - thickness
+ - s->face->underline_pixels_above_descent_line);
else if (use_underline_position_properties
&& font && font->underline_position >= 0)
position = font->underline_position;
@@ -3308,7 +3380,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
else
position = minimum_offset;
- position = max (position, minimum_offset);
+ if (!s->face->underline_pixels_above_descent_line)
+ position = max (position, minimum_offset);
/* Ensure underlining is not cropped. */
if (descent <= position)
@@ -3405,36 +3478,35 @@ ns_draw_box (NSRect r, CGFloat hthickness, CGFloat vthickness,
static void
ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p,
- char top_p, char bottom_p, char left_p, char right_p,
- struct glyph_string *s)
+ char top_p, char bottom_p, char left_p, char right_p,
+ struct glyph_string *s)
/* --------------------------------------------------------------------------
Draw a relief rect inside r, optionally leaving some sides open.
Note we can't just use an NSDrawBezel command, because of the possibility
of some sides not being drawn, and because the rect will be filled.
-------------------------------------------------------------------------- */
{
- static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
- NSColor *newBaseCol = nil;
+ static NSColor *baseCol, *lightCol, *darkCol;
+ NSColor *newBaseCol;
NSRect inner;
+ NSBezierPath *p;
+
+ baseCol = nil;
+ lightCol = nil;
+ newBaseCol = nil;
+ p = nil;
NSTRACE ("ns_draw_relief");
/* set up colors */
if (s->face->use_box_color_for_shadows_p)
- {
- newBaseCol = [NSColor colorWithUnsignedLong:s->face->box_color];
- }
-/* else if (s->first_glyph->type == IMAGE_GLYPH
- && s->img->pixmap
- && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
- {
- newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
- } */
+ newBaseCol = [NSColor colorWithUnsignedLong: s->face->box_color];
else
- {
- newBaseCol = [NSColor colorWithUnsignedLong:s->face->background];
- }
+ newBaseCol = [NSColor colorWithUnsignedLong: s->face->background];
+
+ if (s->hl == DRAW_CURSOR)
+ newBaseCol = FRAME_CURSOR_COLOR (s->f);
if (newBaseCol == nil)
newBaseCol = [NSColor grayColor];
@@ -3444,35 +3516,49 @@ ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p,
[baseCol release];
baseCol = [newBaseCol retain];
[lightCol release];
- lightCol = [[baseCol highlightWithLevel: 0.2] retain];
+ lightCol = [[baseCol highlightWithLevel: 0.4] retain];
[darkCol release];
- darkCol = [[baseCol shadowWithLevel: 0.3] retain];
+ darkCol = [[baseCol shadowWithLevel: 0.4] retain];
}
/* Calculate the inner rectangle. */
- inner = NSMakeRect (NSMinX (outer) + (left_p ? hthickness : 0),
- NSMinY (outer) + (top_p ? vthickness : 0),
- NSWidth (outer) - (left_p ? hthickness : 0)
- - (right_p ? hthickness : 0),
- NSHeight (outer) - (top_p ? vthickness : 0)
- - (bottom_p ? vthickness : 0));
+ inner = outer;
+
+ if (left_p)
+ {
+ inner.origin.x += vthickness;
+ inner.size.width -= vthickness;
+ }
+
+ if (right_p)
+ inner.size.width -= vthickness;
+
+ if (top_p)
+ {
+ inner.origin.y += hthickness;
+ inner.size.height -= hthickness;
+ }
+
+ if (bottom_p)
+ inner.size.height -= hthickness;
[(raised_p ? lightCol : darkCol) set];
if (top_p || left_p)
{
- NSBezierPath *p = [NSBezierPath bezierPath];
- [p moveToPoint:NSMakePoint (NSMinX (outer), NSMinY (outer))];
+ p = [NSBezierPath bezierPath];
+
+ [p moveToPoint: NSMakePoint (NSMinX (outer), NSMinY (outer))];
if (top_p)
{
- [p lineToPoint:NSMakePoint (NSMaxX (outer), NSMinY (outer))];
- [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMinY (inner))];
+ [p lineToPoint: NSMakePoint (NSMaxX (outer), NSMinY (outer))];
+ [p lineToPoint: NSMakePoint (NSMaxX (inner), NSMinY (inner))];
}
- [p lineToPoint:NSMakePoint (NSMinX (inner), NSMinY (inner))];
+ [p lineToPoint: NSMakePoint (NSMinX (inner), NSMinY (inner))];
if (left_p)
{
- [p lineToPoint:NSMakePoint (NSMinX (inner), NSMaxY (inner))];
- [p lineToPoint:NSMakePoint (NSMinX (outer), NSMaxY (outer))];
+ [p lineToPoint: NSMakePoint (NSMinX (inner), NSMaxY (inner))];
+ [p lineToPoint: NSMakePoint (NSMinX (outer), NSMaxY (outer))];
}
[p closePath];
[p fill];
@@ -3480,24 +3566,93 @@ ns_draw_relief (NSRect outer, int hthickness, int vthickness, char raised_p,
[(raised_p ? darkCol : lightCol) set];
- if (bottom_p || right_p)
+ if (bottom_p || right_p)
{
- NSBezierPath *p = [NSBezierPath bezierPath];
- [p moveToPoint:NSMakePoint (NSMaxX (outer), NSMaxY (outer))];
+ p = [NSBezierPath bezierPath];
+
+ [p moveToPoint: NSMakePoint (NSMaxX (outer), NSMaxY (outer))];
if (right_p)
{
- [p lineToPoint:NSMakePoint (NSMaxX (outer), NSMinY (outer))];
- [p lineToPoint:NSMakePoint (NSMaxX (inner), NSMinY (inner))];
+ [p lineToPoint: NSMakePoint (NSMaxX (outer), NSMinY (outer))];
+ [p lineToPoint: NSMakePoint (NSMaxX (inner), NSMinY (inner))];
}
[p lineToPoint:NSMakePoint (NSMaxX (inner), NSMaxY (inner))];
if (bottom_p)
{
- [p lineToPoint:NSMakePoint (NSMinX (inner), NSMaxY (inner))];
- [p lineToPoint:NSMakePoint (NSMinX (outer), NSMaxY (outer))];
+ [p lineToPoint: NSMakePoint (NSMinX (inner), NSMaxY (inner))];
+ [p lineToPoint: NSMakePoint (NSMinX (outer), NSMaxY (outer))];
}
[p closePath];
[p fill];
}
+
+ /* If one of h/vthickness are more than 1, draw the outermost line
+ on the respective sides in the black relief color. */
+
+ if (p)
+ [p removeAllPoints];
+ else
+ p = [NSBezierPath bezierPath];
+
+ if (hthickness > 1 && top_p)
+ {
+ [p moveToPoint: NSMakePoint (NSMinX (outer),
+ NSMinY (outer) + 0.5)];
+ [p lineToPoint: NSMakePoint (NSMaxX (outer),
+ NSMinY (outer) + 0.5)];
+ }
+
+ if (hthickness > 1 && bottom_p)
+ {
+ [p moveToPoint: NSMakePoint (NSMinX (outer),
+ NSMaxY (outer) - 0.5)];
+ [p lineToPoint: NSMakePoint (NSMaxX (outer),
+ NSMaxY (outer) - 0.5)];
+ }
+
+ if (vthickness > 1 && left_p)
+ {
+ [p moveToPoint: NSMakePoint (NSMinX (outer) + 0.5,
+ NSMinY (outer) + 0.5)];
+ [p lineToPoint: NSMakePoint (NSMinX (outer) + 0.5,
+ NSMaxY (outer) - 0.5)];
+ }
+
+ if (vthickness > 1 && left_p)
+ {
+ [p moveToPoint: NSMakePoint (NSMinX (outer) + 0.5,
+ NSMinY (outer) + 0.5)];
+ [p lineToPoint: NSMakePoint (NSMinX (outer) + 0.5,
+ NSMaxY (outer) - 0.5)];
+ }
+
+ [darkCol set];
+ [p stroke];
+
+ if (vthickness > 1 && hthickness > 1)
+ {
+ [FRAME_BACKGROUND_COLOR (s->f) set];
+
+ if (left_p && top_p)
+ [NSBezierPath fillRect: NSMakeRect (NSMinX (outer),
+ NSMinY (outer),
+ 1, 1)];
+
+ if (right_p && top_p)
+ [NSBezierPath fillRect: NSMakeRect (NSMaxX (outer) - 1,
+ NSMinY (outer),
+ 1, 1)];
+
+ if (right_p && bottom_p)
+ [NSBezierPath fillRect: NSMakeRect (NSMaxX (outer) - 1,
+ NSMaxY (outer) - 1,
+ 1, 1)];
+
+ if (left_p && bottom_p)
+ [NSBezierPath fillRect: NSMakeRect (NSMinX (outer),
+ NSMaxY (outer) - 1,
+ 1, 1)];
+ }
}
@@ -3579,6 +3734,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
{
int box_line_width = max (s->face->box_horizontal_line_width, 0);
+
if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
/* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
dimensions, since the actual glyphs might be much
@@ -3605,7 +3761,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
NSRect r = NSMakeRect (s->x, s->y + box_line_width,
s->background_width,
- s->height-2*box_line_width);
+ s->height - 2 * box_line_width);
NSRectFill (r);
s->background_filled_p = 1;
@@ -3613,6 +3769,92 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
}
}
+static void
+ns_draw_image_relief (struct glyph_string *s)
+{
+ int x1, y1, thick;
+ bool raised_p, top_p, bot_p, left_p, right_p;
+ int extra_x, extra_y;
+ int x = s->x;
+ int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += max (s->face->box_vertical_line_width, 0);
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
+
+ if (s->hl == DRAW_IMAGE_SUNKEN
+ || s->hl == DRAW_IMAGE_RAISED)
+ {
+ if (s->face->id == TAB_BAR_FACE_ID)
+ thick = (tab_bar_button_relief < 0
+ ? DEFAULT_TAB_BAR_BUTTON_RELIEF
+ : min (tab_bar_button_relief, 1000000));
+ else
+ thick = (tool_bar_button_relief < 0
+ ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
+ : min (tool_bar_button_relief, 1000000));
+ raised_p = s->hl == DRAW_IMAGE_RAISED;
+ }
+ else
+ {
+ thick = eabs (s->img->relief);
+ raised_p = s->img->relief > 0;
+ }
+
+ x1 = x + s->slice.width - 1;
+ y1 = y + s->slice.height - 1;
+
+ extra_x = extra_y = 0;
+ if (s->face->id == TAB_BAR_FACE_ID)
+ {
+ if (CONSP (Vtab_bar_button_margin)
+ && FIXNUMP (XCAR (Vtab_bar_button_margin))
+ && FIXNUMP (XCDR (Vtab_bar_button_margin)))
+ {
+ extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
+ extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
+ }
+ else if (FIXNUMP (Vtab_bar_button_margin))
+ extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
+ }
+
+ if (s->face->id == TOOL_BAR_FACE_ID)
+ {
+ if (CONSP (Vtool_bar_button_margin)
+ && FIXNUMP (XCAR (Vtool_bar_button_margin))
+ && FIXNUMP (XCDR (Vtool_bar_button_margin)))
+ {
+ extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
+ extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
+ }
+ else if (FIXNUMP (Vtool_bar_button_margin))
+ extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
+ }
+
+ top_p = bot_p = left_p = right_p = false;
+
+ if (s->slice.x == 0)
+ x -= thick + extra_x, left_p = true;
+ if (s->slice.y == 0)
+ y -= thick + extra_y, top_p = true;
+ if (s->slice.x + s->slice.width == s->img->width)
+ x1 += thick + extra_x, right_p = true;
+ if (s->slice.y + s->slice.height == s->img->height)
+ y1 += thick + extra_y, bot_p = true;
+
+ ns_draw_relief (NSMakeRect (x, y, x1 - x + 1, y1 - y + 1), thick,
+ thick, raised_p, top_p, bot_p, left_p, right_p, s);
+}
static void
ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
@@ -3624,8 +3866,6 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
int bg_x, bg_y, bg_height;
- int th;
- char raised_p;
NSRect br;
struct face *face = s->face;
NSColor *tdCol;
@@ -3719,51 +3959,29 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
if (s->hl == DRAW_CURSOR)
{
[FRAME_CURSOR_COLOR (s->f) set];
- tdCol = [NSColor colorWithUnsignedLong:NS_FACE_BACKGROUND (face)];
+ tdCol = [NSColor colorWithUnsignedLong: NS_FACE_BACKGROUND (face)];
}
else
- {
- tdCol = [NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (face)];
- }
+ tdCol = [NSColor colorWithUnsignedLong: NS_FACE_FOREGROUND (face)];
/* Draw underline, overline, strike-through. */
ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x);
- /* Draw relief, if requested */
- if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
- {
- if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
- {
- th = (tool_bar_button_relief < 0
- ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
- : min (tool_bar_button_relief, 1000000));
- raised_p = (s->hl == DRAW_IMAGE_RAISED);
- }
- else
- {
- th = abs (s->img->relief);
- raised_p = (s->img->relief > 0);
- }
-
- r.origin.x = x - th;
- r.origin.y = y - th;
- r.size.width = s->slice.width + 2*th-1;
- r.size.height = s->slice.height + 2*th-1;
- ns_draw_relief (r, th, th, raised_p,
- s->slice.y == 0,
- s->slice.y + s->slice.height == s->img->height,
- s->slice.x == 0,
- s->slice.x + s->slice.width == s->img->width, s);
- }
+ /* If we must draw a relief around the image, do it. */
+ if (s->img->relief
+ || s->hl == DRAW_IMAGE_RAISED
+ || s->hl == DRAW_IMAGE_SUNKEN)
+ ns_draw_image_relief (s);
- /* If there is no mask, the background won't be seen,
- so draw a rectangle on the image for the cursor.
- Do this for all images, getting transparency right is not reliable. */
+ /* If there is no mask, the background won't be seen, so draw a
+ rectangle on the image for the cursor. Do this for all images,
+ getting transparency right is not reliable. */
if (s->hl == DRAW_CURSOR)
{
int thickness = abs (s->img->relief);
if (thickness == 0) thickness = 1;
- ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
+ ns_draw_box (br, thickness, thickness,
+ FRAME_CURSOR_COLOR (s->f), 1, 1);
}
}
@@ -3919,6 +4137,85 @@ ns_draw_composite_glyph_string_foreground (struct glyph_string *s)
}
}
+/* Draw the foreground of glyph string S for glyphless characters. */
+static void
+ns_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
+{
+ struct glyph *glyph = s->first_glyph;
+ NSGlyph char2b[8];
+ int x, i, j;
+
+ /* If first glyph of S has a left box line, start drawing the text
+ of S to the right of that box line. */
+ if (s->face && s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + max (s->face->box_vertical_line_width, 0);
+ else
+ x = s->x;
+
+ s->char2b = char2b;
+
+ for (i = 0; i < s->nchars; i++, glyph++)
+ {
+ char buf[7];
+ char *str = NULL;
+ int len = glyph->u.glyphless.len;
+
+ if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
+ {
+ if (len > 0
+ && CHAR_TABLE_P (Vglyphless_char_display)
+ && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
+ >= 1))
+ {
+ Lisp_Object acronym
+ = (! glyph->u.glyphless.for_no_font
+ ? CHAR_TABLE_REF (Vglyphless_char_display,
+ glyph->u.glyphless.ch)
+ : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
+ if (STRINGP (acronym))
+ str = SSDATA (acronym);
+ }
+ }
+ else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
+ {
+ unsigned int ch = glyph->u.glyphless.ch;
+ eassume (ch <= MAX_CHAR);
+ sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
+ str = buf;
+ }
+
+ if (str)
+ {
+ int upper_len = (len + 1) / 2;
+
+ /* It is assured that all LEN characters in STR is ASCII. */
+ for (j = 0; j < len; j++)
+ char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
+ s->font->driver->draw (s, 0, upper_len,
+ x + glyph->slice.glyphless.upper_xoff,
+ s->ybase + glyph->slice.glyphless.upper_yoff,
+ false);
+ s->font->driver->draw (s, upper_len, len,
+ x + glyph->slice.glyphless.lower_xoff,
+ s->ybase + glyph->slice.glyphless.lower_yoff,
+ false);
+ }
+ if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
+ ns_draw_box (NSMakeRect (x, s->ybase - glyph->ascent,
+ glyph->pixel_width - 1,
+ glyph->ascent + glyph->descent - 1),
+ 1, 1,
+ [NSColor colorWithUnsignedLong:NS_FACE_FOREGROUND (s->face)],
+ YES, YES);
+ x += glyph->pixel_width;
+ }
+
+ /* GCC 12 complains even though nothing ever uses s->char2b after
+ this function returns. */
+ s->char2b = NULL;
+}
+
static void
ns_draw_glyph_string (struct glyph_string *s)
/* --------------------------------------------------------------------------
@@ -4032,9 +4329,7 @@ ns_draw_glyph_string (struct glyph_string *s)
else
ns_maybe_dumpglyphs_background
(s, s->first_glyph->type == COMPOSITE_GLYPH);
- /* ... */
- /* Not yet implemented. */
- /* ... */
+ ns_draw_glyphless_glyph_string_foreground (s);
break;
default:
@@ -4247,11 +4542,14 @@ check_native_fs ()
static int
-ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
+ns_read_socket_1 (struct terminal *terminal, struct input_event *hold_quit,
+ BOOL no_release)
/* --------------------------------------------------------------------------
External (hook): Post an event to ourself and keep reading events until
we read it back again. In effect process all events which were waiting.
From 21+ we have to manage the event buffer ourselves.
+
+ NO_RELEASE means not to touch the global autorelease pool.
-------------------------------------------------------------------------- */
{
struct input_event ev;
@@ -4282,11 +4580,14 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
ns_init_events (&ev);
q_event_ptr = hold_quit;
- /* We manage autorelease pools by allocate/reallocate each time around
- the loop; strict nesting is occasionally violated but seems not to
- matter... earlier methods using full nesting caused major memory leaks. */
- [outerpool release];
- outerpool = [[NSAutoreleasePool alloc] init];
+ if (!no_release)
+ {
+ /* We manage autorelease pools by allocate/reallocate each time around
+ the loop; strict nesting is occasionally violated but seems not to
+ matter... earlier methods using full nesting caused major memory leaks. */
+ [outerpool release];
+ outerpool = [[NSAutoreleasePool alloc] init];
+ }
/* If have pending open-file requests, attend to the next one of those. */
if (ns_pending_files && [ns_pending_files count] != 0
@@ -4325,11 +4626,17 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
return nevents;
}
+static int
+ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
+{
+ return ns_read_socket_1 (terminal, hold_quit, NO);
+}
-int
-ns_select (int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timespec *timeout,
- sigset_t *sigmask)
+
+static int
+ns_select_1 (int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timespec *timeout,
+ sigset_t *sigmask, BOOL run_loop_only)
/* --------------------------------------------------------------------------
Replacement for select, checking for events
-------------------------------------------------------------------------- */
@@ -4345,7 +4652,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
check_native_fs ();
#endif
- if (hold_event_q.nr > 0)
+ if (hold_event_q.nr > 0 && !run_loop_only)
{
/* We already have events pending. */
raise (SIGIO);
@@ -4363,12 +4670,12 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
if (NSApp == nil
|| ![NSThread isMainThread]
|| (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
- return thread_select(pselect, nfds, readfds, writefds,
- exceptfds, timeout, sigmask);
+ return thread_select (pselect, nfds, readfds, writefds,
+ exceptfds, timeout, sigmask);
else
{
struct timespec t = {0, 0};
- thread_select(pselect, 0, NULL, NULL, NULL, &t, sigmask);
+ thread_select (pselect, 0, NULL, NULL, NULL, &t, sigmask);
}
/* FIXME: This draining of outerpool causes a crash when a buffer
@@ -4486,6 +4793,15 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
return result;
}
+int
+ns_select (int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timespec *timeout,
+ sigset_t *sigmask)
+{
+ return ns_select_1 (nfds, readfds, writefds, exceptfds,
+ timeout, sigmask, NO);
+}
+
#ifdef HAVE_PTHREAD
void
ns_run_loop_break (void)
@@ -4897,11 +5213,22 @@ ns_update_window_end (struct window *w, bool cursor_on_p,
}
#endif
-/* This and next define (many of the) public functions in this file. */
-/* gui_* are generic versions in xdisp.c that we, and other terms, get away
- with using despite presence in the "system dependent" redisplay
- interface. In addition, many of the ns_ methods have code that is
- shared with all terms, indicating need for further refactoring. */
+static void
+ns_flush_display (struct frame *f)
+{
+ struct input_event ie;
+
+ EVENT_INIT (ie);
+ ns_read_socket_1 (FRAME_TERMINAL (f), &ie, YES);
+}
+
+/* This and next define (many of the) public functions in this
+ file. */
+/* gui_* are generic versions in xdisp.c that we, and other terms, get
+ away with using despite presence in the "system dependent"
+ redisplay interface. In addition, many of the ns_ methods have
+ code that is shared with all terms, indicating need for further
+ refactoring. */
extern frame_parm_handler ns_frame_parm_handlers[];
static struct redisplay_interface ns_redisplay_interface =
{
@@ -4918,7 +5245,7 @@ static struct redisplay_interface ns_redisplay_interface =
#else
ns_update_window_end,
#endif
- 0, /* flush_display */
+ ns_flush_display,
gui_clear_window_mouse_face,
gui_get_glyph_overhangs,
gui_fix_overlapping_area,
@@ -4939,6 +5266,39 @@ static struct redisplay_interface ns_redisplay_interface =
ns_default_font_parameter
};
+#ifdef NS_IMPL_COCOA
+static void
+ns_displays_reconfigured (CGDirectDisplayID display,
+ CGDisplayChangeSummaryFlags flags,
+ void *user_info)
+{
+ struct input_event ie;
+ union buffered_input_event *ev;
+ Lisp_Object new_monitors;
+
+ EVENT_INIT (ie);
+
+ new_monitors = Fns_display_monitor_attributes_list (Qnil);
+
+ if (!NILP (Fequal (new_monitors, last_known_monitors)))
+ return;
+
+ last_known_monitors = new_monitors;
+
+ ev = (kbd_store_ptr == kbd_buffer
+ ? kbd_buffer + KBD_BUFFER_SIZE - 1
+ : kbd_store_ptr - 1);
+
+ if (kbd_store_ptr != kbd_fetch_ptr
+ && ev->ie.kind == MONITORS_CHANGED_EVENT)
+ return;
+
+ ie.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (ie.arg, x_display_list->terminal);
+
+ kbd_buffer_store_event (&ie);
+}
+#endif
static void
ns_delete_display (struct ns_display_info *dpyinfo)
@@ -5294,6 +5654,16 @@ ns_term_init (Lisp_Object display_name)
catch_child_signal ();
#endif
+#ifdef NS_IMPL_COCOA
+ /* Begin listening for display reconfiguration, so we can run the
+ appropriate hooks. FIXME: is this called when the resolution of
+ a monitor changes? */
+
+ CGDisplayRegisterReconfigurationCallback (ns_displays_reconfigured,
+ NULL);
+#endif
+ last_known_monitors = Fns_display_monitor_attributes_list (Qnil);
+
NSTRACE_MSG ("ns_term_init done");
unblock_input ();
@@ -5305,20 +5675,21 @@ ns_term_init (Lisp_Object display_name)
void
ns_term_shutdown (int sig)
{
+ NSAutoreleasePool *pool;
+ /* We also need an autorelease pool here, since this can be called
+ during dumping. */
+ pool = [[NSAutoreleasePool alloc] init];
[[NSUserDefaults standardUserDefaults] synchronize];
+ [pool release];
/* code not reached in emacs.c after this is called by shut_down_emacs: */
if (STRINGP (Vauto_save_list_file_name))
unlink (SSDATA (Vauto_save_list_file_name));
if (sig == 0 || sig == SIGTERM)
- {
- [NSApp terminate: NSApp];
- }
- else // force a stack trace to happen
- {
- emacs_abort ();
- }
+ [NSApp terminate: NSApp];
+ else /* Force a stack trace to happen. */
+ emacs_abort ();
}
@@ -5333,6 +5704,10 @@ ns_term_shutdown (int sig)
- (id)init
{
+#ifdef NS_IMPL_GNUSTEP
+ NSNotificationCenter *notification_center;
+#endif
+
NSTRACE ("[EmacsApp init]");
if ((self = [super init]))
@@ -5345,6 +5720,14 @@ ns_term_shutdown (int sig)
#endif
}
+#ifdef NS_IMPL_GNUSTEP
+ notification_center = [NSNotificationCenter defaultCenter];
+ [notification_center addObserver: self
+ selector: @selector(updateMonitors:)
+ name: NSApplicationDidChangeScreenParametersNotification
+ object: nil];
+#endif
+
return self;
}
@@ -5357,11 +5740,11 @@ ns_term_shutdown (int sig)
#define NSAppKitVersionNumber10_9 1265
#endif
- if ((int)NSAppKitVersionNumber != NSAppKitVersionNumber10_9)
- {
- [super run];
- return;
- }
+ if ((int) NSAppKitVersionNumber != NSAppKitVersionNumber10_9)
+ {
+ [super run];
+ return;
+ }
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -5545,6 +5928,36 @@ ns_term_shutdown (int sig)
return YES;
}
+#ifdef NS_IMPL_GNUSTEP
+- (void) updateMonitors: (NSNotification *) notification
+{
+ struct input_event ie;
+ union buffered_input_event *ev;
+ Lisp_Object new_monitors;
+
+ EVENT_INIT (ie);
+
+ new_monitors = Fns_display_monitor_attributes_list (Qnil);
+
+ if (!NILP (Fequal (new_monitors, last_known_monitors)))
+ return;
+
+ last_known_monitors = new_monitors;
+
+ ev = (kbd_store_ptr == kbd_buffer
+ ? kbd_buffer + KBD_BUFFER_SIZE - 1
+ : kbd_store_ptr - 1);
+
+ if (kbd_store_ptr != kbd_fetch_ptr
+ && ev->ie.kind == MONITORS_CHANGED_EVENT)
+ return;
+
+ ie.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (ie.arg, x_display_list->terminal);
+
+ kbd_buffer_store_event (&ie);
+}
+#endif
/* **************************************************************************
@@ -5823,7 +6236,7 @@ not_in_argv (NSString *arg)
fd_set fds;
FD_ZERO (&fds);
FD_SET (selfds[0], &fds);
- result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
+ result = pselect (selfds[0]+1, &fds, NULL, NULL, NULL, NULL);
if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
waiting = 0;
}
@@ -5929,6 +6342,123 @@ not_in_argv (NSString *arg)
@end /* EmacsApp */
+static Lisp_Object
+ns_font_desc_to_font_spec (NSFontDescriptor *desc, NSFont *font)
+{
+ NSFontSymbolicTraits traits = [desc symbolicTraits];
+ NSDictionary *dict = [desc objectForKey: NSFontTraitsAttribute];
+ NSString *family = [font familyName];
+ Lisp_Object lwidth, lslant, lweight, lheight;
+ NSNumber *tem;
+
+ lwidth = Qnil;
+ lslant = Qnil;
+ lweight = Qnil;
+ lheight = Qnil;
+
+ if (traits & NSFontBoldTrait)
+ lweight = Qbold;
+
+ if (traits & NSFontItalicTrait)
+ lslant = Qitalic;
+
+ if (traits & NSFontCondensedTrait)
+ lwidth = Qcondensed;
+ else if (traits & NSFontExpandedTrait)
+ lwidth = Qexpanded;
+
+ if (dict != nil)
+ {
+ tem = [dict objectForKey: NSFontSlantTrait];
+
+ if (tem != nil)
+ lslant = ([tem floatValue] > 0
+ ? Qitalic : ([tem floatValue] < 0
+ ? Qreverse_italic
+ : Qnormal));
+
+ tem = [dict objectForKey: NSFontWeightTrait];
+
+#ifdef NS_IMPL_GNUSTEP
+ if (tem != nil)
+ lweight = ([tem floatValue] > 0
+ ? Qbold : ([tem floatValue] < -0.4f
+ ? Qlight : Qnormal));
+#else
+ if (tem != nil)
+ {
+ if ([tem floatValue] >= 0.4)
+ lweight = Qbold;
+ else if ([tem floatValue] >= 0.24)
+ lweight = Qmedium;
+ else if ([tem floatValue] >= 0)
+ lweight = Qnormal;
+ else if ([tem floatValue] >= -0.24)
+ lweight = Qsemi_light;
+ else
+ lweight = Qlight;
+ }
+#endif
+
+ tem = [dict objectForKey: NSFontWidthTrait];
+
+ if (tem != nil)
+ lwidth = ([tem floatValue] > 0
+ ? Qexpanded : ([tem floatValue] < 0
+ ? Qcondensed : Qnormal));
+ }
+
+ lheight = make_float ([font pointSize]);
+
+ return CALLN (Ffont_spec,
+ QCwidth, lwidth, QCslant, lslant,
+ QCweight, lweight, QCsize, lheight,
+ QCfamily, (family
+ ? [family lispString]
+ : Qnil));
+}
+
+#ifdef NS_IMPL_COCOA
+static NSView *
+ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
+{
+ NSMatrix *matrix;
+ NSButtonCell *prototype;
+ NSSize cell_size;
+ NSRect frame;
+ NSButtonCell *cancel, *ok;
+
+ prototype = [[NSButtonCell alloc] init];
+ [prototype setBezelStyle: NSBezelStyleRounded];
+ [prototype setTitle: @"Cancel"];
+ cell_size = [prototype cellSize];
+ frame = NSMakeRect (0, 0, cell_size.width * 2,
+ cell_size.height);
+ matrix = [[NSMatrix alloc] initWithFrame: frame
+ mode: NSTrackModeMatrix
+ prototype: prototype
+ numberOfRows: 1
+ numberOfColumns: 2];
+ [prototype release];
+
+ ok = (NSButtonCell *) [matrix cellAtRow: 0 column: 0];
+ cancel = (NSButtonCell *) [matrix cellAtRow: 0 column: 1];
+
+ [ok setTitle: @"OK"];
+ [ok setTarget: target];
+ [ok setAction: select];
+ [ok setButtonType: NSButtonTypeMomentaryPushIn];
+
+ [cancel setTitle: @"Cancel"];
+ [cancel setTarget: target];
+ [cancel setAction: cancel_action];
+ [cancel setButtonType: NSButtonTypeMomentaryPushIn];
+
+ [matrix selectCell: ok];
+
+ return matrix;
+}
+#endif
/* ==========================================================================
@@ -5965,42 +6495,129 @@ not_in_argv (NSString *arg)
/* Called on font panel selection. */
-- (void)changeFont: (id)sender
+- (void) changeFont: (id) sender
{
- NSEvent *e = [[self window] currentEvent];
- struct face *face = FACE_FROM_ID (emacsframe, DEFAULT_FACE_ID);
- struct font *font = face->font;
- id newFont;
- CGFloat size;
+ struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
NSFont *nsfont;
- NSTRACE ("[EmacsView changeFont:]");
+#ifdef NS_IMPL_GNUSTEP
+ nsfont = ((struct nsfont_info *) font)->nsfont;
+#else
+ nsfont = (NSFont *) macfont_get_nsctfont (font);
+#endif
- if (!emacs_event)
+ if (!font_panel_active)
return;
-#ifdef NS_IMPL_GNUSTEP
- nsfont = ((struct nsfont_info *)font)->nsfont;
+ if (font_panel_result)
+ [font_panel_result release];
+
+ font_panel_result = (NSFont *) [sender convertFont: nsfont];
+
+ if (font_panel_result)
+ [font_panel_result retain];
+
+#ifndef NS_IMPL_COCOA
+ font_panel_active = NO;
+ [NSApp stop: self];
#endif
+}
+
#ifdef NS_IMPL_COCOA
- nsfont = (NSFont *) macfont_get_nsctfont (font);
-#endif
+- (void) noteUserSelectedFont
+{
+ font_panel_active = NO;
- if ((newFont = [sender convertFont: nsfont]))
- {
- SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
+ /* If no font was previously selected, use the currently selected
+ font. */
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->modifiers = 0;
- emacs_event->code = KEY_NS_CHANGE_FONT;
+ if (!font_panel_result && FRAME_FONT (emacsframe))
+ {
+ font_panel_result
+ = macfont_get_nsctfont (FRAME_FONT (emacsframe));
- size = [newFont pointSize];
- ns_input_fontsize = make_fixnum (lrint (size));
- ns_input_font = [[newFont familyName] lispString];
- EV_TRAILER (e);
+ if (font_panel_result)
+ [font_panel_result retain];
}
+
+ [NSApp stop: self];
+}
+
+- (void) noteUserCancelledSelection
+{
+ font_panel_active = NO;
+
+ if (font_panel_result)
+ [font_panel_result release];
+ font_panel_result = nil;
+
+ [NSApp stop: self];
}
+#endif
+- (Lisp_Object) showFontPanel
+{
+ id fm = [NSFontManager sharedFontManager];
+ struct font *font = FRAME_OUTPUT_DATA (emacsframe)->font;
+ NSFont *nsfont, *result;
+ struct timespec timeout;
+#ifdef NS_IMPL_COCOA
+ NSView *buttons;
+ BOOL canceled;
+#endif
+
+#ifdef NS_IMPL_GNUSTEP
+ nsfont = ((struct nsfont_info *) font)->nsfont;
+#else
+ nsfont = (NSFont *) macfont_get_nsctfont (font);
+#endif
+
+#ifdef NS_IMPL_COCOA
+ buttons
+ = ns_create_font_panel_buttons (self,
+ @selector (noteUserSelectedFont),
+ @selector (noteUserCancelledSelection));
+ [[fm fontPanel: YES] setAccessoryView: buttons];
+ [buttons release];
+#endif
+
+ [fm setSelectedFont: nsfont isMultiple: NO];
+ [fm orderFrontFontPanel: NSApp];
+
+ font_panel_active = YES;
+ timeout = make_timespec (0, 100000000);
+
+ block_input ();
+ while (font_panel_active
+#ifdef NS_IMPL_COCOA
+ && (canceled = [[fm fontPanel: YES] isVisible])
+#else
+ && [[fm fontPanel: YES] isVisible]
+#endif
+ )
+ ns_select_1 (0, NULL, NULL, NULL, &timeout, NULL, YES);
+ unblock_input ();
+
+ if (font_panel_result)
+ [font_panel_result autorelease];
+
+#ifdef NS_IMPL_COCOA
+ if (!canceled)
+ font_panel_result = nil;
+#endif
+
+ result = font_panel_result;
+ font_panel_result = nil;
+
+ [[fm fontPanel: YES] setIsVisible: NO];
+ font_panel_active = NO;
+
+ if (result)
+ return ns_font_desc_to_font_spec ([result fontDescriptor],
+ result);
+
+ return Qnil;
+}
- (BOOL)acceptsFirstResponder
{
@@ -6008,7 +6625,6 @@ not_in_argv (NSString *arg)
return YES;
}
-
- (void)resetCursorRects
{
NSRect visible = [self visibleRect];
@@ -6485,17 +7101,24 @@ not_in_argv (NSString *arg)
{
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
+ EmacsWindow *window;
NSTRACE ("[EmacsView mouseDown:]");
if (!emacs_event)
return;
+ if (FRAME_TOOLTIP_P (emacsframe))
+ return;
+
dpyinfo->last_mouse_frame = emacsframe;
/* Appears to be needed to prevent spurious movement events generated on
button clicks. */
emacsframe->mouse_moved = 0;
+ window = (EmacsWindow *) [self window];
+ [window setLastDragEvent: theEvent];
+
if ([theEvent type] == NSEventTypeScrollWheel)
{
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
@@ -6688,7 +7311,8 @@ not_in_argv (NSString *arg)
tab_bar_p = EQ (window, emacsframe->tab_bar_window);
if (tab_bar_p)
- tab_bar_arg = handle_tab_bar_click (emacsframe, x, y, EV_UDMODIFIERS (theEvent) & down_modifier,
+ tab_bar_arg = handle_tab_bar_click (emacsframe, x, y,
+ EV_UDMODIFIERS (theEvent) & down_modifier,
EV_MODIFIERS (theEvent) | EV_UDMODIFIERS (theEvent));
}
@@ -6763,6 +7387,9 @@ not_in_argv (NSString *arg)
NSPoint pt;
BOOL dragging;
+ if (FRAME_TOOLTIP_P (emacsframe))
+ return;
+
NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]");
dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e);
@@ -6791,6 +7418,7 @@ not_in_argv (NSString *arg)
if (WINDOWP (window)
&& !EQ (window, last_mouse_window)
&& !EQ (window, selected_window)
+ && !MINI_WINDOW_P (XWINDOW (selected_window))
&& (!NILP (focus_follows_mouse)
|| (EQ (XWINDOW (window)->frame,
XWINDOW (selected_window)->frame))))
@@ -6844,7 +7472,7 @@ not_in_argv (NSString *arg)
[self mouseMoved: e];
}
-#ifdef NS_IMPL_COCOA
+#if defined NS_IMPL_COCOA && defined MAC_OS_X_VERSION_10_7
- (void) magnifyWithEvent: (NSEvent *) event
{
NSPoint pt = [self convertPoint: [event locationInWindow] fromView: nil];
@@ -7064,6 +7692,9 @@ not_in_argv (NSString *arg)
{
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
struct frame *old_focus = dpyinfo->ns_focus_frame;
+ struct input_event event;
+
+ EVENT_INIT (event);
NSTRACE ("[EmacsView windowDidBecomeKey]");
@@ -7072,11 +7703,9 @@ not_in_argv (NSString *arg)
ns_frame_rehighlight (emacsframe);
- if (emacs_event)
- {
- emacs_event->kind = FOCUS_IN_EVENT;
- EV_TRAILER ((id)nil);
- }
+ event.kind = FOCUS_IN_EVENT;
+ XSETFRAME (event.frame_or_window, emacsframe);
+ kbd_buffer_store_event (&event);
}
@@ -7182,7 +7811,7 @@ not_in_argv (NSString *arg)
[[EmacsWindow alloc] initWithEmacsFrame:f];
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
/* These settings mean AppKit will retain the contents of the frame
on resize. Unfortunately it also means the frame will not be
automatically marked for display, but we can do that ourselves in
@@ -7846,8 +8475,8 @@ not_in_argv (NSString *arg)
}
-#ifdef NS_IMPL_COCOA
-- (CALayer *)makeBackingLayer;
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+- (CALayer *)makeBackingLayer
{
EmacsLayer *l = [[EmacsLayer alloc]
initWithColorSpace:[[[self window] colorSpace] CGColorSpace]];
@@ -7862,19 +8491,12 @@ not_in_argv (NSString *arg)
{
NSTRACE ("[EmacsView lockFocus]");
- if ([self wantsLayer])
- {
- CGContextRef context = [(EmacsLayer*)[self layer] getContext];
+ CGContextRef context = [(EmacsLayer*)[self layer] getContext];
- [NSGraphicsContext
+ [NSGraphicsContext
setCurrentContext:[NSGraphicsContext
graphicsContextWithCGContext:context
flipped:YES]];
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
- else
- [super lockFocus];
-#endif
}
@@ -7882,18 +8504,8 @@ not_in_argv (NSString *arg)
{
NSTRACE ("[EmacsView unlockFocus]");
- if ([self wantsLayer])
- {
- [NSGraphicsContext setCurrentContext:nil];
- [self setNeedsDisplay:YES];
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
- else
- {
- [super unlockFocus];
- [super flushWindow];
- }
-#endif
+ [NSGraphicsContext setCurrentContext:nil];
+ [self setNeedsDisplay:YES];
}
@@ -7902,19 +8514,16 @@ not_in_argv (NSString *arg)
{
NSTRACE ("EmacsView windowDidChangeBackingProperties:]");
- if ([self wantsLayer])
- {
- NSRect frame = [self frame];
- EmacsLayer *layer = (EmacsLayer *)[self layer];
+ NSRect frame = [self frame];
+ EmacsLayer *layer = (EmacsLayer *)[self layer];
- [layer setContentsScale:[[notification object] backingScaleFactor]];
- [layer setColorSpace:[[[notification object] colorSpace] CGColorSpace]];
+ [layer setContentsScale:[[notification object] backingScaleFactor]];
+ [layer setColorSpace:[[[notification object] colorSpace] CGColorSpace]];
- ns_clear_frame (emacsframe);
- expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame));
- }
+ ns_clear_frame (emacsframe);
+ expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame));
}
-#endif /* NS_IMPL_COCOA */
+#endif
- (void)copyRect:(NSRect)srcRect to:(NSPoint)dest
@@ -7925,77 +8534,46 @@ not_in_argv (NSString *arg)
NSRect dstRect = NSMakeRect (dest.x, dest.y, NSWidth (srcRect),
NSHeight (srcRect));
- NSRect frame = [self frame];
-
- /* TODO: This check is an attempt to debug a rare graphical glitch
- on macOS and should be removed before the Emacs 28 release. */
- if (!NSContainsRect (frame, srcRect)
- || !NSContainsRect (frame, dstRect))
- {
- NSLog (@"[EmacsView copyRect:to:] Attempting to copy to or "
- "from an area outside the graphics buffer.");
- NSLog (@" Frame: (%f, %f) %f×%f",
- NSMinX (frame), NSMinY (frame),
- NSWidth (frame), NSHeight (frame));
- NSLog (@" Source: (%f, %f) %f×%f",
- NSMinX (srcRect), NSMinY (srcRect),
- NSWidth (srcRect), NSHeight (srcRect));
- NSLog (@" Destination: (%f, %f) %f×%f",
- NSMinX (dstRect), NSMinY (dstRect),
- NSWidth (dstRect), NSHeight (dstRect));
- }
-#ifdef NS_IMPL_COCOA
- if ([self wantsLayer])
- {
- double scale = [[self window] backingScaleFactor];
- CGContextRef context = [(EmacsLayer *)[self layer] getContext];
- int bpp = CGBitmapContextGetBitsPerPixel (context) / 8;
- void *pixels = CGBitmapContextGetData (context);
- int rowSize = CGBitmapContextGetBytesPerRow (context);
- int srcRowSize = NSWidth (srcRect) * scale * bpp;
- void *srcPixels = (char *) pixels
- + (int) (NSMinY (srcRect) * scale * rowSize
- + NSMinX (srcRect) * scale * bpp);
- void *dstPixels = (char *) pixels
- + (int) (dest.y * scale * rowSize
- + dest.x * scale * bpp);
-
- if (NSIntersectsRect (srcRect, dstRect)
- && NSMinY (srcRect) < NSMinY (dstRect))
- for (int y = NSHeight (srcRect) * scale - 1 ; y >= 0 ; y--)
- memmove ((char *) dstPixels + y * rowSize,
- (char *) srcPixels + y * rowSize,
- srcRowSize);
- else
- for (int y = 0 ; y < NSHeight (srcRect) * scale ; y++)
- memmove ((char *) dstPixels + y * rowSize,
- (char *) srcPixels + y * rowSize,
- srcRowSize);
-
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ double scale = [[self window] backingScaleFactor];
+ CGContextRef context = [(EmacsLayer *)[self layer] getContext];
+ int bpp = CGBitmapContextGetBitsPerPixel (context) / 8;
+ void *pixels = CGBitmapContextGetData (context);
+ int rowSize = CGBitmapContextGetBytesPerRow (context);
+ int srcRowSize = NSWidth (srcRect) * scale * bpp;
+ void *srcPixels = (char *) pixels
+ + (int) (NSMinY (srcRect) * scale * rowSize
+ + NSMinX (srcRect) * scale * bpp);
+ void *dstPixels = (char *) pixels
+ + (int) (dest.y * scale * rowSize
+ + dest.x * scale * bpp);
+
+ if (NSIntersectsRect (srcRect, dstRect)
+ && NSMinY (srcRect) < NSMinY (dstRect))
+ for (int y = NSHeight (srcRect) * scale - 1 ; y >= 0 ; y--)
+ memmove ((char *) dstPixels + y * rowSize,
+ (char *) srcPixels + y * rowSize,
+ srcRowSize);
else
- {
-#endif
-#endif /* NS_IMPL_COCOA */
+ for (int y = 0 ; y < NSHeight (srcRect) * scale ; y++)
+ memmove ((char *) dstPixels + y * rowSize,
+ (char *) srcPixels + y * rowSize,
+ srcRowSize);
-#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400
- hide_bell(); // Ensure the bell image isn't scrolled.
+#else
+ hide_bell(); // Ensure the bell image isn't scrolled.
- ns_focus (emacsframe, &dstRect, 1);
- [self scrollRect: srcRect
- by: NSMakeSize (dstRect.origin.x - srcRect.origin.x,
- dstRect.origin.y - srcRect.origin.y)];
- ns_unfocus (emacsframe);
-#endif
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400
- }
+ ns_focus (emacsframe, &dstRect, 1);
+ [self scrollRect: srcRect
+ by: NSMakeSize (dstRect.origin.x - srcRect.origin.x,
+ dstRect.origin.y - srcRect.origin.y)];
+ ns_unfocus (emacsframe);
#endif
}
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
/* If the frame has been garbaged but the toolkit wants to draw, for
example when resizing the frame, we end up with a blank screen.
Sometimes this results in an unpleasant flicker, so try to
@@ -8050,36 +8628,113 @@ not_in_argv (NSString *arg)
-(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
{
+ id source;
+
NSTRACE ("[EmacsView draggingEntered:]");
+
+ source = [sender draggingSource];
+
+ if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+ && [source mustNotDropOn: self])
+ return NSDragOperationNone;
+
return NSDragOperationGeneric;
}
--(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
+-(BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
{
+ id source;
+
+ source = [sender draggingSource];
+
+ if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+ && [source mustNotDropOn: self])
+ return NO;
+
return YES;
}
+- (BOOL) wantsPeriodicDraggingUpdates
+{
+ return YES;
+}
+
+- (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender
+{
+#ifdef NS_IMPL_GNUSTEP
+ struct input_event ie;
+#else
+ Lisp_Object frame;
+#endif
+ NSPoint position;
+ int x, y;
+ NSAutoreleasePool *ap;
+ specpdl_ref count;
+
+ ap = [[NSAutoreleasePool alloc] init];
+ count = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (ns_release_autorelease_pool, ap);
+
+#ifdef NS_IMPL_GNUSTEP
+ EVENT_INIT (ie);
+ ie.kind = DRAG_N_DROP_EVENT;
+#endif
+
+ /* Get rid of mouse face. */
+ [self mouseExited: [[self window] currentEvent]];
+
+ position = [self convertPoint: [sender draggingLocation]
+ fromView: nil];
+ x = lrint (position.x);
+ y = lrint (position.y);
+
+#ifdef NS_IMPL_GNUSTEP
+ XSETINT (ie.x, x);
+ XSETINT (ie.y, y);
+ XSETFRAME (ie.frame_or_window, emacsframe);
+ ie.arg = Qlambda;
+ ie.modifiers = 0;
+
+ kbd_buffer_store_event (&ie);
+#else
+ /* Input events won't be processed until the drop happens on macOS,
+ so call this function instead. */
+ XSETFRAME (frame, emacsframe);
+
+ safe_call (4, Vns_drag_motion_function, frame,
+ make_fixnum (x), make_fixnum (y));
--(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
+ redisplay ();
+#endif
+
+ unbind_to (count, Qnil);
+ return NSDragOperationGeneric;
+}
+
+- (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
{
- id pb;
+ id pb, source;
int x, y;
NSString *type;
- NSEvent *theEvent = [[self window] currentEvent];
NSPoint position;
NSDragOperation op = [sender draggingSourceOperationMask];
Lisp_Object operations = Qnil;
Lisp_Object strings = Qnil;
Lisp_Object type_sym;
+ struct input_event ie;
- NSTRACE ("[EmacsView performDragOperation:]");
+ NSTRACE (@"[EmacsView performDragOperation:]");
- if (!emacs_event)
+ source = [sender draggingSource];
+
+ if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+ && [source mustNotDropOn: self])
return NO;
position = [self convertPoint: [sender draggingLocation] fromView: nil];
- x = lrint (position.x); y = lrint (position.y);
+ x = lrint (position.x);
+ y = lrint (position.y);
pb = [sender draggingPasteboard];
type = [pb availableTypeFromArray: ns_drag_types];
@@ -8095,11 +8750,9 @@ not_in_argv (NSString *arg)
if (op & NSDragOperationGeneric || NILP (operations))
operations = Fcons (Qns_drag_operation_generic, operations);
- if (type == 0)
- {
- return NO;
- }
-#if NS_USE_NSPasteboardTypeFileURL != 0
+ if (!type)
+ return NO;
+#if NS_USE_NSPasteboardTypeFileURL
else if ([type isEqualToString: NSPasteboardTypeFileURL])
{
type_sym = Qfile;
@@ -8114,18 +8767,29 @@ not_in_argv (NSString *arg)
#else // !NS_USE_NSPasteboardTypeFileURL
else if ([type isEqualToString: NSFilenamesPboardType])
{
- NSArray *files;
+ id files;
NSEnumerator *fenum;
NSString *file;
- if (!(files = [pb propertyListForType: type]))
+ files = [pb propertyListForType: type];
+
+ if (!files)
return NO;
type_sym = Qfile;
- fenum = [files objectEnumerator];
- while ( (file = [fenum nextObject]) )
- strings = Fcons ([file lispString], strings);
+ /* On GNUstep, files might be a string. */
+
+ if ([files respondsToSelector: @selector (objectEnumerator:)])
+ {
+ fenum = [files objectEnumerator];
+
+ while ((file = [fenum nextObject]))
+ strings = Fcons ([file lispString], strings);
+ }
+ else
+ /* Then `files' is an NSString. */
+ strings = list1 ([files lispString]);
}
#endif // !NS_USE_NSPasteboardTypeFileURL
else if ([type isEqualToString: NSPasteboardTypeURL])
@@ -8142,29 +8806,26 @@ not_in_argv (NSString *arg)
{
NSString *data;
- if (! (data = [pb stringForType: type]))
+ data = [pb stringForType: type];
+
+ if (!data)
return NO;
type_sym = Qnil;
-
strings = list1 ([data lispString]);
}
else
- {
- fputs ("Invalid data type in dragging pasteboard\n", stderr);
- return NO;
- }
+ return NO;
- emacs_event->kind = DRAG_N_DROP_EVENT;
- XSETINT (emacs_event->x, x);
- XSETINT (emacs_event->y, y);
- emacs_event->modifiers = 0;
-
- emacs_event->arg = Fcons (type_sym,
- Fcons (operations,
- strings));
- EV_TRAILER (theEvent);
+ EVENT_INIT (ie);
+ ie.kind = DRAG_N_DROP_EVENT;
+ ie.arg = Fcons (type_sym, Fcons (operations,
+ strings));
+ XSETINT (ie.x, x);
+ XSETINT (ie.y, y);
+ XSETFRAME (ie.frame_or_window, emacsframe);
+ kbd_buffer_store_event (&ie);
return YES;
}
@@ -8271,17 +8932,18 @@ not_in_argv (NSString *arg)
@implementation EmacsWindow
-- (instancetype) initWithEmacsFrame:(struct frame *)f
+- (instancetype) initWithEmacsFrame: (struct frame *) f
{
return [self initWithEmacsFrame:f fullscreen:NO screen:nil];
}
-- (instancetype) initWithEmacsFrame:(struct frame *)f
- fullscreen:(BOOL)fullscreen
- screen:(NSScreen *)screen
+- (instancetype) initWithEmacsFrame: (struct frame *) f
+ fullscreen: (BOOL) fullscreen
+ screen: (NSScreen *) screen
{
NSWindowStyleMask styleMask;
+ int width, height;
NSTRACE ("[EmacsWindow initWithEmacsFrame:fullscreen:screen:]");
@@ -8294,20 +8956,24 @@ not_in_argv (NSString *arg)
styleMask |= NSWindowStyleMaskResizable;
#endif
}
+ else if (f->tooltip)
+ styleMask = 0;
else
- styleMask = NSWindowStyleMaskTitled
- | NSWindowStyleMaskResizable
- | NSWindowStyleMaskMiniaturizable
- | NSWindowStyleMaskClosable;
-
- self = [super initWithContentRect:
- NSMakeRect (0, 0,
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines))
- styleMask:styleMask
- backing:NSBackingStoreBuffered
- defer:YES
- screen:screen];
+ styleMask = (NSWindowStyleMaskTitled
+ | NSWindowStyleMaskResizable
+ | NSWindowStyleMaskMiniaturizable
+ | NSWindowStyleMaskClosable);
+
+ last_drag_event = nil;
+
+ width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols);
+ height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines);
+
+ self = [super initWithContentRect: NSMakeRect (0, 0, width, height)
+ styleMask: styleMask
+ backing: NSBackingStoreBuffered
+ defer: YES
+ screen: screen];
if (self)
{
NSString *name;
@@ -8394,7 +9060,7 @@ not_in_argv (NSString *arg)
EmacsToolbar *toolbar = [[EmacsToolbar alloc]
initForView:view
- withIdentifier:[NSString stringWithLispString:f->name]];
+ withIdentifier:[NSString stringWithFormat:@"%p", f]];
[self setToolbar:toolbar];
update_frame_tool_bar_1 (f, toolbar);
@@ -8415,6 +9081,11 @@ not_in_argv (NSString *arg)
/* We need to release the toolbar ourselves. */
[[self toolbar] release];
+
+ /* Also the last button press event . */
+ if (last_drag_event)
+ [last_drag_event release];
+
[super dealloc];
}
@@ -8446,7 +9117,7 @@ not_in_argv (NSString *arg)
expected later. */
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
- if ([child respondsToSelector:@selector(setAccessibilitySubrole:)])
+ if ([self respondsToSelector:@selector(setAccessibilitySubrole:)])
#endif
/* Set the accessibility subroles. */
if (parentFrame)
@@ -8478,7 +9149,7 @@ not_in_argv (NSString *arg)
#ifdef NS_IMPL_COCOA
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- if ([ourView respondsToSelector:@selector (toggleFullScreen)]
+ if ([ourView respondsToSelector:@selector (toggleFullScreen)])
#endif
/* If we are the descendent of a fullscreen window and we
have no new parent, go fullscreen. */
@@ -8503,11 +9174,11 @@ not_in_argv (NSString *arg)
#ifdef NS_IMPL_COCOA
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- if ([ourView respondsToSelector:@selector (toggleFullScreen)]
+ if ([ourView respondsToSelector:@selector (toggleFullScreen)])
#endif
- /* Child frames must not be fullscreen. */
- if ([ourView fsIsNative] && [ourView isFullscreen])
- [ourView toggleFullScreen:self];
+ /* Child frames must not be fullscreen. */
+ if ([ourView fsIsNative] && [ourView isFullscreen])
+ [ourView toggleFullScreen:self];
#endif
[parentWindow addChildWindow:self
@@ -8939,6 +9610,153 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return YES;
}
+- (void) setLastDragEvent: (NSEvent *) event
+{
+ if (last_drag_event)
+ [last_drag_event release];
+ last_drag_event = [event copy];
+}
+
+- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) is_local
+{
+ return drag_op;
+}
+
+- (void) draggedImage: (NSImage *) image
+ endedAt: (NSPoint) screen_point
+ operation: (NSDragOperation) operation
+{
+ selected_op = operation;
+}
+
+- (void) draggedImage: (NSImage *) dragged_image
+ movedTo: (NSPoint) screen_point
+{
+ NSPoint mouse_loc;
+#ifdef NS_IMPL_COCOA
+ NSInteger window_number;
+ NSWindow *w;
+#endif
+
+ mouse_loc = [NSEvent mouseLocation];
+
+#ifdef NS_IMPL_COCOA
+ if (dnd_mode != RETURN_FRAME_NEVER)
+ {
+ window_number = [NSWindow windowNumberAtPoint: mouse_loc
+ belowWindowWithWindowNumber: 0];
+ w = [NSApp windowWithWindowNumber: window_number];
+
+ if (!w || w != self)
+ dnd_mode = RETURN_FRAME_NOW;
+
+ if (dnd_mode != RETURN_FRAME_NOW
+ || ![[w delegate] isKindOfClass: [EmacsView class]]
+ || ((EmacsView *) [w delegate])->emacsframe->tooltip)
+ goto out;
+
+ dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe;
+
+ /* FIXME: there must be a better way to leave the event loop. */
+ [NSException raise: @""
+ format: @"Must return DND frame"];
+ }
+
+ out:
+#endif
+
+ if (dnd_move_tooltip_with_frame)
+ ns_move_tooltip_to_mouse_location (mouse_loc);
+}
+
+- (BOOL) mustNotDropOn: (NSView *) receiver
+{
+ return ([receiver window] == self
+ ? !dnd_allow_same_frame : NO);
+}
+
+- (NSDragOperation) beginDrag: (NSDragOperation) op
+ forPasteboard: (NSPasteboard *) pasteboard
+ withMode: (enum ns_return_frame_mode) mode
+ returnFrameTo: (struct frame **) frame_return
+ prohibitSame: (BOOL) prohibit_same_frame
+ followTooltip: (BOOL) follow_tooltip
+{
+ NSImage *image;
+#ifdef NS_IMPL_COCOA
+ NSInteger window_number;
+ NSWindow *w;
+#endif
+ drag_op = op;
+ selected_op = NSDragOperationNone;
+ image = [[NSImage alloc] initWithSize: NSMakeSize (1.0, 1.0)];
+ dnd_mode = mode;
+ dnd_return_frame = NULL;
+ dnd_allow_same_frame = !prohibit_same_frame;
+ dnd_move_tooltip_with_frame = follow_tooltip;
+
+ /* Now draw transparency onto the image. */
+ [image lockFocus];
+ [[NSColor colorWithUnsignedLong: 0] set];
+ NSRectFillUsingOperation (NSMakeRect (0, 0, 1, 1),
+ NSCompositingOperationCopy);
+ [image unlockFocus];
+
+ block_input ();
+#ifdef NS_IMPL_COCOA
+ if (mode == RETURN_FRAME_NOW)
+ {
+ window_number = [NSWindow windowNumberAtPoint: [NSEvent mouseLocation]
+ belowWindowWithWindowNumber: 0];
+ w = [NSApp windowWithWindowNumber: window_number];
+
+ if (w && [[w delegate] isKindOfClass: [EmacsView class]]
+ && !((EmacsView *) [w delegate])->emacsframe->tooltip)
+ {
+ *frame_return = ((EmacsView *) [w delegate])->emacsframe;
+ [image release];
+ unblock_input ();
+
+ return NSDragOperationNone;
+ }
+ }
+
+ @try
+ {
+#endif
+ if (last_drag_event)
+ [self dragImage: image
+ at: NSMakePoint (0, 0)
+ offset: NSMakeSize (0, 0)
+ event: last_drag_event
+ pasteboard: pasteboard
+ source: self
+ slideBack: NO];
+#ifdef NS_IMPL_COCOA
+ }
+ @catch (NSException *e)
+ {
+ /* Ignore. This is probably the wrong way to leave the
+ drag-and-drop run loop. */
+ }
+#endif
+ unblock_input ();
+
+ /* The drop happened, so delete the tooltip. */
+ if (follow_tooltip)
+ Fx_hide_tip ();
+
+ /* Assume all buttons have been released since the drag-and-drop
+ operation is now over. */
+ if (!dnd_return_frame)
+ x_display_list->grabbed = 0;
+
+ [image release];
+
+ *frame_return = dnd_return_frame;
+ return selected_op;
+}
+
@end /* EmacsWindow */
@@ -9106,6 +9924,16 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return ret;
}
+- (void) mark
+{
+ if (window)
+ {
+ Lisp_Object win;
+ XSETWINDOW (win, window);
+ mark_object (win);
+ }
+}
+
- (void)resetCursorRects
{
@@ -9439,7 +10267,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
@end /* EmacsScroller */
-#ifdef NS_IMPL_COCOA
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
/* ==========================================================================
@@ -9847,6 +10675,26 @@ ns_xlfd_to_fontname (const char *xlfd)
return ret;
}
+void
+mark_nsterm (void)
+{
+ NSTRACE ("mark_nsterm");
+ Lisp_Object tail, frame;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_NS_P (f))
+ {
+ NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
+ for (int i = [subviews count] - 1; i >= 0; --i)
+ {
+ id scroller = [subviews objectAtIndex: i];
+ if ([scroller isKindOfClass: [EmacsScroller class]])
+ [scroller mark];
+ }
+ }
+ }
+}
void
syms_of_nsterm (void)
@@ -9871,6 +10719,7 @@ syms_of_nsterm (void)
DEFSYM (Qns_drag_operation_copy, "ns-drag-operation-copy");
DEFSYM (Qns_drag_operation_link, "ns-drag-operation-link");
DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic");
+ DEFSYM (Qns_handle_drag_motion, "ns-handle-drag-motion");
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
@@ -9878,117 +10727,117 @@ syms_of_nsterm (void)
Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier));
- DEFVAR_LISP ("ns-input-file", ns_input_file,
- "The file specified in the last NS event.");
- ns_input_file =Qnil;
+ DEFVAR_LISP ("ns-input-font", ns_input_font,
+ doc: /* The font specified in the last NS event. */);
+ ns_input_font = Qnil;
- DEFVAR_LISP ("ns-working-text", ns_working_text,
- "String for visualizing working composition sequence.");
- ns_working_text =Qnil;
+ DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
+ doc: /* The fontsize specified in the last NS event. */);
+ ns_input_fontsize = Qnil;
- DEFVAR_LISP ("ns-input-font", ns_input_font,
- "The font specified in the last NS event.");
- ns_input_font =Qnil;
+ DEFVAR_LISP ("ns-input-line", ns_input_line,
+ doc: /* The line specified in the last NS event. */);
+ ns_input_line = Qnil;
- DEFVAR_LISP ("ns-input-fontsize", ns_input_fontsize,
- "The fontsize specified in the last NS event.");
- ns_input_fontsize =Qnil;
+ DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
+ doc: /* The service name specified in the last NS event. */);
+ ns_input_spi_name = Qnil;
- DEFVAR_LISP ("ns-input-line", ns_input_line,
- "The line specified in the last NS event.");
- ns_input_line =Qnil;
+ DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
+ doc: /* The service argument specified in the last NS event. */);
+ ns_input_spi_arg = Qnil;
- DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
- "The service name specified in the last NS event.");
- ns_input_spi_name =Qnil;
+ DEFVAR_LISP ("ns-input-file", ns_input_file,
+ doc: /* The file specified in the last NS event. */);
+ ns_input_file = Qnil;
- DEFVAR_LISP ("ns-input-spi-arg", ns_input_spi_arg,
- "The service argument specified in the last NS event.");
- ns_input_spi_arg =Qnil;
+ DEFVAR_LISP ("ns-working-text", ns_working_text,
+ doc: /* String for visualizing working composition sequence. */);
+ ns_working_text = Qnil;
DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
- "This variable describes the behavior of the alternate or option key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the alternate or option key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_alternate_modifier = Qmeta;
DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
- "This variable describes the behavior of the right alternate or option key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-It can also be `left' to use the value of `ns-alternate-modifier' instead.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the right alternate or option key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+It can also be `left' to use the value of `ns-alternate-modifier' instead.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_right_alternate_modifier = Qleft;
DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
- "This variable describes the behavior of the command key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the command key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_command_modifier = Qsuper;
DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
- "This variable describes the behavior of the right command key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-It can also be `left' to use the value of `ns-command-modifier' instead.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the right command key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+It can also be `left' to use the value of `ns-command-modifier' instead.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_right_command_modifier = Qleft;
DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
- "This variable describes the behavior of the control key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the control key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_control_modifier = Qcontrol;
DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
- "This variable describes the behavior of the right control key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-It can also be `left' to use the value of `ns-control-modifier' instead.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the right control key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+It can also be `left' to use the value of `ns-control-modifier' instead.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_right_control_modifier = Qleft;
DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
- "This variable describes the behavior of the function (fn) key.\n\
-Either SYMBOL, describing the behavior for any event,\n\
-or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior\n\
-separately for ordinary keys, function keys, and mouse events.\n\
-\n\
-Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
-If `none', the key is ignored by Emacs and retains its standard meaning.");
+ doc: /* This variable describes the behavior of the function (fn) key.
+Either SYMBOL, describing the behavior for any event,
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behavior
+separately for ordinary keys, function keys, and mouse events.
+
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.
+If `none', the key is ignored by Emacs and retains its standard meaning. */);
ns_function_modifier = Qnone;
DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
- "Non-nil (the default) means to render text antialiased.");
+ doc: /* Non-nil (the default) means to render text antialiased. */);
ns_antialias_text = Qt;
DEFVAR_LISP ("ns-use-thin-smoothing", ns_use_thin_smoothing,
- "Non-nil turns on a font smoothing method that produces thinner strokes.");
+ doc: /* Non-nil turns on a font smoothing method that produces thinner strokes. */);
ns_use_thin_smoothing = Qnil;
DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
- "Whether to confirm application quit using dialog.");
+ doc: /* Whether to confirm application quit using dialog. */);
ns_confirm_quit = Qnil;
DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
@@ -10058,6 +10907,16 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */);
mice with smooth scrolling capability. */);
Vns_scroll_event_delta_factor = make_float (1.0);
+ DEFVAR_LISP ("ns-drag-motion-function", Vns_drag_motion_function,
+ doc: /* Function called when another program drags items over Emacs.
+
+It is called with three arguments FRAME, X, and Y, whenever the user
+moves the mouse over an Emacs frame as part of a drag-and-drop
+operation. FRAME is the frame the mouse is on top of, and X and Y are
+the frame-relative positions of the mouse in the X and Y axises
+respectively. */);
+ Vns_drag_motion_function = Qns_handle_drag_motion;
+
/* Tell Emacs about this window system. */
Fprovide (Qns, Qnil);
@@ -10066,6 +10925,9 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */);
DEFSYM (QCordinary, ":ordinary");
DEFSYM (QCfunction, ":function");
DEFSYM (QCmouse, ":mouse");
+ DEFSYM (Qcondensed, "condensed");
+ DEFSYM (Qreverse_italic, "reverse-italic");
+ DEFSYM (Qexpanded, "expanded");
#ifdef NS_IMPL_COCOA
Fprovide (Qcocoa, Qnil);
@@ -10075,4 +10937,6 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */);
syms_of_nsfont ();
#endif
+ last_known_monitors = Qnil;
+ staticpro (&last_known_monitors);
}
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
index f79873235cb..be0eba0bcb1 100644
--- a/src/nsxwidget.m
+++ b/src/nsxwidget.m
@@ -69,10 +69,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
[configuration.preferences setValue:@YES
forKey:@"developerExtrasEnabled"];
+#if 0 /* Plugins are not supported by Mac OS X anymore. */
Lisp_Object enablePlugins =
Fintern (build_string ("xwidget-webkit-enable-plugins"), Qnil);
+
if (!EQ (Fsymbol_value (enablePlugins), Qnil))
configuration.preferences.plugInsEnabled = YES;
+#endif
self = [super initWithFrame:frame configuration:configuration];
if (self)
diff --git a/src/pdumper.c b/src/pdumper.c
index eeebb7ed0e8..af451920eb6 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "coding.h"
#include "fingerprint.h"
#include "frame.h"
-#include "getpagesize.h"
#include "intervals.h"
#include "lisp.h"
#include "pdumper.h"
@@ -163,7 +162,7 @@ ptrdiff_t_to_dump_off (ptrdiff_t value)
/* Worst-case allocation granularity on any system that might load
this dump. */
static int
-dump_get_page_size (void)
+dump_get_max_page_size (void)
{
return 64 * 1024;
}
@@ -1070,7 +1069,7 @@ dump_queue_enqueue (struct dump_queue *dump_queue,
}
}
- if (!EQ (weights, orig_weights))
+ if (!BASE_EQ (weights, orig_weights))
Fputhash (object, weights, dump_queue->link_weights);
}
@@ -1211,8 +1210,8 @@ dump_queue_find_score_of_one_weight_queue (struct dump_queue *dump_queue,
static Lisp_Object
dump_queue_dequeue (struct dump_queue *dump_queue, dump_off basis)
{
- eassert (EQ (Fhash_table_count (dump_queue->sequence_numbers),
- Fhash_table_count (dump_queue->link_weights)));
+ eassert (BASE_EQ (Fhash_table_count (dump_queue->sequence_numbers),
+ Fhash_table_count (dump_queue->link_weights)));
eassert (XFIXNUM (Fhash_table_count (dump_queue->sequence_numbers))
<= (dump_tailq_length (&dump_queue->fancy_weight_objects)
@@ -1384,7 +1383,7 @@ print_paths_to_root_1 (struct dump_context *ctx,
{
Lisp_Object referrer = XCAR (referrers);
referrers = XCDR (referrers);
- Lisp_Object repr = Fprin1_to_string (referrer, Qnil);
+ Lisp_Object repr = Fprin1_to_string (referrer, Qnil, Qnil);
for (int i = 0; i < level; ++i)
putc (' ', stderr);
fwrite (SDATA (repr), 1, SBYTES (repr), stderr);
@@ -2068,7 +2067,7 @@ dump_interval_tree (struct dump_context *ctx,
static dump_off
dump_string (struct dump_context *ctx, const struct Lisp_String *string)
{
-#if CHECK_STRUCTS && !defined (HASH_Lisp_String_348C2B2FDB)
+#if CHECK_STRUCTS && !defined (HASH_Lisp_String_C2CAF90352)
# error "Lisp_String changed. See CHECK_STRUCTS comment in config.h."
#endif
/* If we have text properties, write them _after_ the string so that
@@ -2079,7 +2078,7 @@ dump_string (struct dump_context *ctx, const struct Lisp_String *string)
we seldom write to string data and never relocate it, so lumping
it together at the end of the dump saves on COW faults.
- If, however, the string's size_byte field is -1, the string data
+ If, however, the string's size_byte field is -2, the string data
is actually a pointer to Emacs data segment, so we can do even
better by emitting a relocation instead of bothering to copy the
string data. */
@@ -2854,7 +2853,7 @@ dump_bool_vector (struct dump_context *ctx, const struct Lisp_Vector *v)
static dump_off
dump_subr (struct dump_context *ctx, const struct Lisp_Subr *subr)
{
-#if CHECK_STRUCTS && !defined (HASH_Lisp_Subr_F09D8E8E19)
+#if CHECK_STRUCTS && !defined (HASH_Lisp_Subr_20B7443AD7)
# error "Lisp_Subr changed. See CHECK_STRUCTS comment in config.h."
#endif
struct Lisp_Subr out;
@@ -2877,12 +2876,14 @@ dump_subr (struct dump_context *ctx, const struct Lisp_Subr *subr)
dump_remember_cold_op (ctx,
COLD_OP_NATIVE_SUBR,
make_lisp_ptr ((void *) subr, Lisp_Vectorlike));
- dump_field_lv (ctx, &out, subr, &subr->native_intspec, WEIGHT_NORMAL);
+ dump_field_lv (ctx, &out, subr, &subr->intspec.native, WEIGHT_NORMAL);
+ dump_field_lv (ctx, &out, subr, &subr->command_modes, WEIGHT_NORMAL);
}
else
{
dump_field_emacs_ptr (ctx, &out, subr, &subr->symbol_name);
- dump_field_emacs_ptr (ctx, &out, subr, &subr->intspec);
+ dump_field_emacs_ptr (ctx, &out, subr, &subr->intspec.string);
+ dump_field_emacs_ptr (ctx, &out, subr, &subr->command_modes);
}
DUMP_FIELD_COPY (&out, subr, doc);
#ifdef HAVE_NATIVE_COMP
@@ -2948,7 +2949,7 @@ dump_vectorlike (struct dump_context *ctx,
Lisp_Object lv,
dump_off offset)
{
-#if CHECK_STRUCTS && !defined HASH_pvec_type_19F6CF5169
+#if CHECK_STRUCTS && !defined HASH_pvec_type_AFF6FED5BD
# error "pvec_type changed. See CHECK_STRUCTS comment in config.h."
#endif
const struct Lisp_Vector *v = XVECTOR (lv);
@@ -3032,6 +3033,8 @@ dump_vectorlike (struct dump_context *ctx,
error_unsupported_dump_object (ctx, lv, "sqlite");
case PVEC_MODULE_FUNCTION:
error_unsupported_dump_object (ctx, lv, "module function");
+ case PVEC_SYMBOL_WITH_POS:
+ error_unsupported_dump_object (ctx, lv, "symbol with pos");
default:
error_unsupported_dump_object(ctx, lv, "weird pseudovector");
}
@@ -3755,7 +3758,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object lreloc)
reloc.u.dump_offset = dump_recall_object (ctx, target_value);
if (reloc.u.dump_offset <= 0)
{
- Lisp_Object repr = Fprin1_to_string (target_value, Qnil);
+ Lisp_Object repr = Fprin1_to_string (target_value, Qnil, Qnil);
error ("relocation target was not dumped: %s", SDATA (repr));
}
dump_check_dump_off (ctx, reloc.u.dump_offset);
@@ -4044,7 +4047,7 @@ types. */)
}
while (number_finalizers_run);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Bind `command-line-processed' to nil before dumping,
so that the dumped Emacs will process its command line
@@ -4207,7 +4210,7 @@ types. */)
eassert (dump_queue_empty_p (&ctx->dump_queue));
dump_off discardable_end = ctx->offset;
- dump_align_output (ctx, dump_get_page_size ());
+ dump_align_output (ctx, dump_get_max_page_size ());
ctx->header.cold_start = ctx->offset;
/* Start the cold section. This section contains bytes that should
@@ -4925,7 +4928,7 @@ dump_mmap_contiguous (struct dump_memory_map *maps, int nr_maps)
return true;
size_t total_size = 0;
- int worst_case_page_size = dump_get_page_size ();
+ int worst_case_page_size = dump_get_max_page_size ();
for (int i = 0; i < nr_maps; ++i)
{
@@ -5540,7 +5543,10 @@ pdumper_load (const char *dump_filename, char *argv0)
struct dump_header header_buf = { 0 };
struct dump_header *header = &header_buf;
- struct dump_memory_map sections[NUMBER_DUMP_SECTIONS] = { 0 };
+ struct dump_memory_map sections[NUMBER_DUMP_SECTIONS];
+
+ /* Use memset instead of "= { 0 }" to work around GCC bug 105961. */
+ memset (sections, 0, sizeof sections);
const struct timespec start_time = current_timespec ();
char *dump_filename_copy;
@@ -5613,7 +5619,7 @@ pdumper_load (const char *dump_filename, char *argv0)
err = PDUMPER_LOAD_OOM;
adj_discardable_start = header->discardable_start;
- dump_page_size = dump_get_page_size ();
+ dump_page_size = dump_get_max_page_size ();
/* Snap to next page boundary. */
adj_discardable_start = ROUNDUP (adj_discardable_start, dump_page_size);
eassert (adj_discardable_start % dump_page_size == 0);
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index c604e2f1002..5c43e5f3607 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -38,13 +38,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "xsettings.h"
#include "atimer.h"
-
-#ifdef HAVE_PGTK
-
-/* Static variables to handle applescript execution. */
-static Lisp_Object as_script, *as_result;
-static int as_status;
-
static ptrdiff_t image_cache_refcount;
static int x_decode_color (struct frame *f, Lisp_Object color_name,
@@ -184,7 +177,7 @@ pgtk_display_info_for_name (Lisp_Object name)
static void
-x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
unsigned long fg, old_fg;
@@ -211,7 +204,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
static void
-x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
unsigned long bg;
@@ -235,7 +228,25 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
static void
-x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ gui_set_alpha_background (f, arg, oldval);
+
+ /* This prevents GTK from painting the window's background, which
+ interferes with transparent background in some environments */
+
+ gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f),
+ f->alpha_background != 1.0);
+
+ if (FRAME_GTK_OUTER_WIDGET (f)
+ && gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f))
+ && f->alpha_background != 1.0)
+ gdk_window_set_opaque_region (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
+ NULL);
+}
+
+static void
+pgtk_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
int pix;
@@ -246,7 +257,7 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
static void
-x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
unsigned long fore_pixel, pixel;
struct pgtk_output *x = f->output_data.pgtk;
@@ -349,7 +360,8 @@ pgtk_set_name (struct frame *f, Lisp_Object name, int explicit)
specified a name for the frame; the name will override any set by the
redisplay code. */
static void
-x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_explicitly_set_name (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
{
pgtk_set_name (f, arg, true);
}
@@ -370,7 +382,7 @@ pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg,
If NAME is nil, use the frame name as the title. */
static void
-x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
+pgtk_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
{
/* Don't change the title if it's already NAME. */
if (EQ (name, f->title))
@@ -396,7 +408,7 @@ pgtk_set_doc_edited (void)
static void
-x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
+pgtk_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
/* Right now, menu bars don't work properly in minibuf-only frames;
@@ -442,7 +454,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
The frame's height doesn't change. */
static void
-x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
+pgtk_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
@@ -456,13 +468,12 @@ x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
else
nlines = 0;
- x_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+ pgtk_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
}
-
/* Set the pixel height of the tab bar of frame F to HEIGHT. */
void
-x_change_tab_bar_height (struct frame *f, int height)
+pgtk_change_tab_bar_height (struct frame *f, int height)
{
int unit = FRAME_LINE_HEIGHT (f);
int old_height = FRAME_TAB_BAR_HEIGHT (f);
@@ -534,7 +545,7 @@ x_change_tool_bar_height (struct frame *f, int height)
/* Toolbar support. */
static void
-x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
+pgtk_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
int nlines;
@@ -553,26 +564,33 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
}
static void
-x_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int border = check_int_nonnegative (arg);
+ int border;
+
+ if (NILP (arg))
+ border = -1;
+ else if (RANGED_FIXNUMP (0, arg, INT_MAX))
+ border = XFIXNAT (arg);
+ else
+ signal_error ("Invalid child frame border width", arg);
if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
{
f->child_frame_border_width = border;
- if (FRAME_X_WINDOW (f))
+ if (FRAME_GTK_WIDGET (f))
{
- adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width);
+ adjust_frame_size (f, -1, -1, 3,
+ false, Qchild_frame_border_width);
pgtk_clear_under_internal_border (f);
}
}
-
}
static void
-x_set_internal_border_width (struct frame *f, Lisp_Object arg,
- Lisp_Object oldval)
+pgtk_set_internal_border_width (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
{
int border = check_int_nonnegative (arg);
@@ -589,13 +607,13 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg,
}
static void
-x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
bool result;
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg))
@@ -619,13 +637,13 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
}
static void
-x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
bool result;
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!NILP (arg) || NILP (oldval))
@@ -650,68 +668,19 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
unblock_input ();
}
-/* This is the same as the xfns.c definition. */
static void
-x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+pgtk_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
set_frame_cursor_types (f, arg);
}
-/* called to set mouse pointer color, but all other terms use it to
- initialize pointer types (and don't set the color ;) */
-static void
-x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
-{
-}
-
-
static void
-x_icon (struct frame *f, Lisp_Object parms)
-/* --------------------------------------------------------------------------
- Strangely-named function to set icon position parameters in frame.
- This is irrelevant under macOS, but might be needed under GNUstep,
- depending on the window manager used. Note, this is not a standard
- frame parameter-setter; it is called directly from x-create-frame.
- -------------------------------------------------------------------------- */
+pgtk_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
-#if 0
- Lisp_Object icon_x, icon_y;
- struct pgtk_display_info *dpyinfo = check_pgtk_display_info (Qnil);
-
- FRAME_X_OUTPUT (f)->icon_top = -1;
- FRAME_X_OUTPUT (f)->icon_left = -1;
-
- /* Set the position of the icon. */
- icon_x =
- gui_display_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
- icon_y =
- gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
- {
- CHECK_NUMBER (icon_x);
- CHECK_NUMBER (icon_y);
- FRAME_X_OUTPUT (f)->icon_top = XFIXNUM (icon_y);
- FRAME_X_OUTPUT (f)->icon_left = XFIXNUM (icon_x);
- }
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
- error ("Both left and top icon corners of icon must be specified");
-#endif
}
-/**
- * x_set_undecorated:
- *
- * Set frame F's `undecorated' parameter. If non-nil, F's window-system
- * window is drawn without decorations, title, minimize/maximize boxes
- * and external borders. This usually means that the window cannot be
- * dragged, resized, iconified, maximized or deleted with the mouse. If
- * nil, draw the frame with all the elements listed above unless these
- * have been suspended via window manager settings.
- *
- * Some window managers may not honor this parameter.
- */
static void
-x_set_undecorated (struct frame *f, Lisp_Object new_value,
+pgtk_set_undecorated (struct frame *f, Lisp_Object new_value,
Lisp_Object old_value)
{
if (!EQ (new_value, old_value))
@@ -721,18 +690,8 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value,
}
}
-/**
- * x_set_skip_taskbar:
- *
- * Set frame F's `skip-taskbar' parameter. If non-nil, this should
- * remove F's icon from the taskbar associated with the display of F's
- * window-system window and inhibit switching to F's window via
- * <Alt>-<TAB>. If nil, lift these restrictions.
- *
- * Some window managers may not honor this parameter.
- */
static void
-x_set_skip_taskbar (struct frame *f, Lisp_Object new_value,
+pgtk_set_skip_taskbar (struct frame *f, Lisp_Object new_value,
Lisp_Object old_value)
{
if (!EQ (new_value, old_value))
@@ -742,18 +701,9 @@ x_set_skip_taskbar (struct frame *f, Lisp_Object new_value,
}
}
-/**
- * x_set_override_redirect:
- *
- * Set frame F's `override_redirect' parameter which, if non-nil, hints
- * that the window manager doesn't want to deal with F. Usually, such
- * frames have no decorations and always appear on top of all frames.
- *
- * Some window managers may not honor this parameter.
- */
static void
-x_set_override_redirect (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value)
+pgtk_set_override_redirect (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
{
if (!EQ (new_value, old_value))
{
@@ -768,9 +718,7 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value,
}
}
-/* Set icon from FILE for frame F. By using GTK functions the icon
- may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */
-
+/* Set icon from FILE for frame F. */
bool
xg_set_icon (struct frame *f, Lisp_Object file)
{
@@ -862,6 +810,9 @@ pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value,
GtkCssProvider *css_provider =
FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider;
+ if (FRAME_TOOLTIP_P (f))
+ return;
+
if (NILP (new_value))
{
gtk_css_provider_load_from_data (css_provider, "", -1, NULL);
@@ -874,13 +825,10 @@ pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value,
if (!pgtk_parse_color (f, SSDATA (new_value), &rgb))
error ("Unknown color.");
- /* On pgtk, this frame parameter should be ignored, and honor gtk theme. */
-#if 0
char css[64];
sprintf (css, "scrollbar slider { background-color: #%06x; }",
(unsigned int) rgb.pixel & 0xffffff);
gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
-#endif
update_face_from_frame_parameter (f, Qscroll_bar_foreground, new_value);
}
@@ -907,13 +855,13 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value,
if (!pgtk_parse_color (f, SSDATA (new_value), &rgb))
error ("Unknown color.");
- /* On pgtk, this frame parameter should be ignored, and honor gtk theme. */
-#if 0
+ /* On pgtk, this frame parameter should be ignored, and honor
+ gtk theme. (It honors the GTK theme if not explicitly set, so
+ I see no harm in letting users tinker a bit more.) */
char css[64];
sprintf (css, "scrollbar trough { background-color: #%06x; }",
(unsigned int) rgb.pixel & 0xffffff);
gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
-#endif
update_face_from_frame_parameter (f, Qscroll_bar_background, new_value);
}
@@ -992,58 +940,58 @@ unless TYPE is `png'. */)
return pgtk_cr_export_frames (frames, surface_type);
}
-
-/* Note: see frame.c for template, also where generic functions are impl */
-frame_parm_handler pgtk_frame_parm_handlers[] = {
- gui_set_autoraise, /* generic OK */
- gui_set_autolower, /* generic OK */
- x_set_background_color,
- x_set_border_color,
- gui_set_border_width,
- x_set_cursor_color,
- x_set_cursor_type,
- gui_set_font, /* generic OK */
- x_set_foreground_color,
- x_set_icon_name,
- x_set_icon_type,
- x_set_child_frame_border_width,
- x_set_internal_border_width, /* generic OK */
- gui_set_right_divider_width,
- gui_set_bottom_divider_width,
- x_set_menu_bar_lines,
- x_set_mouse_color,
- x_explicitly_set_name,
- gui_set_scroll_bar_width, /* generic OK */
- gui_set_scroll_bar_height, /* generic OK */
- x_set_title,
- gui_set_unsplittable, /* generic OK */
- gui_set_vertical_scroll_bars, /* generic OK */
- gui_set_horizontal_scroll_bars, /* generic OK */
- gui_set_visibility, /* generic OK */
- x_set_tab_bar_lines,
- x_set_tool_bar_lines,
- pgtk_set_scroll_bar_foreground,
- pgtk_set_scroll_bar_background,
- gui_set_screen_gamma, /* generic OK */
- gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
- gui_set_left_fringe, /* generic OK */
- gui_set_right_fringe, /* generic OK */
- 0, /* x_set_wait_for_wm */
- gui_set_fullscreen, /* generic OK */
- gui_set_font_backend, /* generic OK */
- gui_set_alpha,
- pgtk_set_sticky,
- pgtk_set_tool_bar_position,
- 0, /* x_set_inhibit_double_buffering */
- x_set_undecorated,
- x_set_parent_frame,
- x_set_skip_taskbar,
- x_set_no_focus_on_map,
- x_set_no_accept_focus,
- x_set_z_group,
- x_set_override_redirect,
- gui_set_no_special_glyphs,
-};
+frame_parm_handler pgtk_frame_parm_handlers[] =
+ {
+ gui_set_autoraise, /* generic OK */
+ gui_set_autolower, /* generic OK */
+ pgtk_set_background_color,
+ pgtk_set_border_color,
+ gui_set_border_width,
+ pgtk_set_cursor_color,
+ pgtk_set_cursor_type,
+ gui_set_font, /* generic OK */
+ pgtk_set_foreground_color,
+ pgtk_set_icon_name,
+ pgtk_set_icon_type,
+ pgtk_set_child_frame_border_width,
+ pgtk_set_internal_border_width, /* generic OK */
+ gui_set_right_divider_width,
+ gui_set_bottom_divider_width,
+ pgtk_set_menu_bar_lines,
+ pgtk_set_mouse_color,
+ pgtk_explicitly_set_name,
+ gui_set_scroll_bar_width, /* generic OK */
+ gui_set_scroll_bar_height, /* generic OK */
+ pgtk_set_title,
+ gui_set_unsplittable, /* generic OK */
+ gui_set_vertical_scroll_bars, /* generic OK */
+ gui_set_horizontal_scroll_bars, /* generic OK */
+ gui_set_visibility, /* generic OK */
+ pgtk_set_tab_bar_lines,
+ pgtk_set_tool_bar_lines,
+ pgtk_set_scroll_bar_foreground,
+ pgtk_set_scroll_bar_background,
+ gui_set_screen_gamma, /* generic OK */
+ gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
+ gui_set_left_fringe, /* generic OK */
+ gui_set_right_fringe, /* generic OK */
+ 0,
+ gui_set_fullscreen, /* generic OK */
+ gui_set_font_backend, /* generic OK */
+ gui_set_alpha,
+ pgtk_set_sticky,
+ pgtk_set_tool_bar_position,
+ 0,
+ pgtk_set_undecorated,
+ pgtk_set_parent_frame,
+ pgtk_set_skip_taskbar,
+ pgtk_set_no_focus_on_map,
+ pgtk_set_no_accept_focus,
+ pgtk_set_z_group,
+ pgtk_set_override_redirect,
+ gui_set_no_special_glyphs,
+ pgtk_set_alpha_background,
+ };
/* Handler for signals raised during x_create_frame and
@@ -1075,7 +1023,7 @@ unwind_create_frame (Lisp_Object frame)
&& FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
FRAME_IMAGE_CACHE (f)->refcount++;
- x_free_frame_resources (f);
+ pgtk_free_frame_resources (f);
free_glyphs (f);
return Qt;
}
@@ -1120,7 +1068,7 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms)
gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
RES_TYPE_STRING);
Lisp_Object font = Qnil;
- if (EQ (font_param, Qunbound))
+ if (BASE_EQ (font_param, Qunbound))
font_param = Qnil;
if (NILP (font_param))
@@ -1208,7 +1156,7 @@ incorrect when you specify fractional scale factor in compositor.
If you set scale factor by this function, it is used instead of Gdk's one.
Pass nil as SCALE-FACTOR if you want to reset the specified monitor's
-scale factor. */ )
+scale factor. */)
(Lisp_Object monitor_model, Lisp_Object scale_factor)
{
CHECK_STRING (monitor_model);
@@ -1259,7 +1207,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
bool minibuffer_only = false;
bool undecorated = false, override_redirect = false;
long window_prompting = 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object display;
struct pgtk_display_info *dpyinfo = NULL;
Lisp_Object parent, parent_frame;
@@ -1273,10 +1221,10 @@ This function is an internal primitive--use `make-frame' instead. */ )
display =
gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display =
gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_pgtk_display_info (display);
kb = dpyinfo->terminal->kboard;
@@ -1287,7 +1235,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
name =
gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
RES_TYPE_STRING);
- if (!STRINGP (name) && !EQ (name, Qunbound) && !NILP (name))
+ if (!STRINGP (name) && !BASE_EQ (name, Qunbound) && !NILP (name))
error ("Invalid frame name--not a string or nil");
if (STRINGP (name))
@@ -1297,7 +1245,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
parent =
gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL,
RES_TYPE_NUMBER);
- if (EQ (parent, Qunbound))
+ if (BASE_EQ (parent, Qunbound))
parent = Qnil;
if (!NILP (parent))
CHECK_NUMBER (parent);
@@ -1323,7 +1271,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
RES_TYPE_SYMBOL);
/* Accept parent-frame iff parent-id was not specified. */
if (!NILP (parent)
- || EQ (parent_frame, Qunbound)
+ || BASE_EQ (parent_frame, Qunbound)
|| NILP (parent_frame)
|| !FRAMEP (parent_frame)
|| !FRAME_LIVE_P (XFRAME (parent_frame))
@@ -1337,7 +1285,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
(tem =
(gui_display_get_arg
(dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN)))
- && !(EQ (tem, Qunbound)))
+ && !(BASE_EQ (tem, Qunbound)))
undecorated = true;
FRAME_UNDECORATED (f) = undecorated;
@@ -1347,7 +1295,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
(tem =
(gui_display_get_arg
(dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN)))
- && !(EQ (tem, Qunbound)))
+ && !(BASE_EQ (tem, Qunbound)))
override_redirect = true;
FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
@@ -1359,9 +1307,6 @@ This function is an internal primitive--use `make-frame' instead. */ )
f->output_method = output_pgtk;
FRAME_X_OUTPUT (f) = xzalloc (sizeof *FRAME_X_OUTPUT (f));
-#if 0
- FRAME_X_OUTPUT (f)->icon_bitmap = -1;
-#endif
FRAME_FONTSET (f) = -1;
FRAME_X_OUTPUT (f)->white_relief.pixel = -1;
FRAME_X_OUTPUT (f)->black_relief.pixel = -1;
@@ -1426,7 +1371,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
f->explicit_name = false;
@@ -1459,12 +1404,8 @@ This function is an internal primitive--use `make-frame' instead. */ )
error ("Invalid frame font");
}
- /* Frame contents get displaced if an embedded X window has a border. */
-#if 0
- if (!FRAME_X_EMBEDDED_P (f))
-#endif
- gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
- "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qborder_width, make_fixnum (0),
+ "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
if (NILP (Fassq (Qinternal_border_width, parms)))
{
@@ -1473,7 +1414,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (!EQ (value, Qunbound))
+ if (!BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value), parms);
}
@@ -1490,14 +1431,13 @@ This function is an internal primitive--use `make-frame' instead. */ )
value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width,
"childFrameBorder", "childFrameBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qchild_frame_border_width, value),
parms);
}
- gui_default_parameter (f, parms, Qchild_frame_border_width,
- make_fixnum (0),
+ gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
"childFrameBorderWidth", "childFrameBorderWidth",
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0),
@@ -1543,10 +1483,11 @@ This function is an internal primitive--use `make-frame' instead. */ )
init_frame_faces (f);
/* We have to call adjust_frame_size here since otherwise
- x_set_tool_bar_lines will already work with the character sizes
- installed by init_frame_faces while the frame's pixel size is still
- calculated from a character size of 1 and we subsequently hit the
- (height >= 0) assertion in window_box_height.
+ pgtk_set_tool_bar_lines will already work with the character
+ sizes installed by init_frame_faces while the frame's pixel size
+ is still calculated from a character size of 1 and we
+ subsequently hit the (height >= 0) assertion in
+ window_box_height.
The non-pixelwise code apparently worked around this because it
had one frame line vs one toolbar line which left us with a zero
@@ -1554,14 +1495,12 @@ This function is an internal primitive--use `make-frame' instead. */ )
Also process `min-width' and `min-height' parameters right here
because `frame-windows-min-size' needs them. */
- tem =
- gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
- RES_TYPE_NUMBER);
+ tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
+ RES_TYPE_NUMBER);
if (NUMBERP (tem))
store_frame_param (f, Qmin_width, tem);
- tem =
- gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
- RES_TYPE_NUMBER);
+ tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
+ RES_TYPE_NUMBER);
if (NUMBERP (tem))
store_frame_param (f, Qmin_height, tem);
adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
@@ -1608,15 +1547,16 @@ This function is an internal primitive--use `make-frame' instead. */ )
RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
-#if 0
- x_icon_verify (f, parms);
-#endif
-
- /* Create the X widget or window. */
- /* x_window (f); */
xg_create_frame_widgets (f);
pgtk_set_event_handler (f);
+ if (FRAME_GTK_OUTER_WIDGET (f))
+ gtk_widget_realize (FRAME_GTK_OUTER_WIDGET (f));
+
+ /* Many callers (including the Lisp functions that call
+ FRAME_SCALE_FACTOR) expect the widget to be realized. */
+ if (FRAME_GTK_WIDGET (f))
+ gtk_widget_realize (FRAME_GTK_WIDGET (f));
#define INSTALL_CURSOR(FIELD, NAME) \
FRAME_X_OUTPUT (f)->FIELD = gdk_cursor_new_for_display (FRAME_X_DISPLAY (f), GDK_ ## NAME)
@@ -1639,11 +1579,6 @@ This function is an internal primitive--use `make-frame' instead. */ )
#undef INSTALL_CURSOR
- x_icon (f, parms);
-#if 0
- x_make_gc (f);
-#endif
-
/* Now consider the frame official. */
f->terminal->reference_count++;
FRAME_DISPLAY_INFO (f)->reference_count++;
@@ -1667,6 +1602,8 @@ This function is an internal primitive--use `make-frame' instead. */ )
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
if (!NILP (parent_frame))
{
@@ -1724,7 +1661,7 @@ This function is an internal primitive--use `make-frame' instead. */ )
badly we want them. This should be done after we have the menu
bar so that its size can be taken into account. */
block_input ();
- x_wm_set_size_hint (f, window_prompting, false);
+ xg_wm_set_size_hint (f, window_prompting, false);
unblock_input ();
adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
@@ -1741,22 +1678,39 @@ This function is an internal primitive--use `make-frame' instead. */ )
cannot control visibility, so don't try. */
if (!FRAME_X_OUTPUT (f)->explicit_parent)
{
+ /* When called from `x-create-frame-with-faces' visibility is
+ always explicitly nil. */
Lisp_Object visibility
- =
- gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
- RES_TYPE_SYMBOL);
+ = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
+ RES_TYPE_SYMBOL);
+ Lisp_Object height
+ = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ Lisp_Object width
+ = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
if (EQ (visibility, Qicon))
- pgtk_iconify_frame (f);
+ {
+ f->was_invisible = true;
+ pgtk_iconify_frame (f);
+ }
else
{
- if (EQ (visibility, Qunbound))
+ if (BASE_EQ (visibility, Qunbound))
visibility = Qt;
if (!NILP (visibility))
pgtk_make_frame_visible (f);
+ else
+ f->was_invisible = true;
}
+ /* Leave f->was_invisible true only if height or width were
+ specified too. This takes effect only when we are not called
+ from `x-create-frame-with-faces' (see above comment). */
+ f->was_invisible
+ = (f->was_invisible
+ && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound)));
+
store_frame_param (f, Qvisibility, visibility);
}
@@ -1798,29 +1752,10 @@ This function is an internal primitive--use `make-frame' instead. */ )
return unbind_to (count, frame);
}
-
-#if 0
-static int
-pgtk_window_is_ancestor (PGTKWindow * win, PGTKWindow * candidate)
-/* Test whether CANDIDATE is an ancestor window of WIN. */
-{
- if (candidate == NULL)
- return 0;
- else if (win == candidate)
- return 1;
- else
- return pgtk_window_is_ancestor (win,[candidate parentWindow]);
-}
-#endif
-
-/**
- * x_frame_restack:
- *
- * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
- * practice this is a two-step action: The first step removes F1's
- * window-system window from the display. The second step reinserts
- * F1's window below (above if ABOVE_FLAG is true) that of F2.
- */
+/* Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil.
+ In practice this is a two-step action: The first step removes F1's
+ window-system window from the display. The second step reinserts
+ F1's window below (above if ABOVE_FLAG is true) that of F2. */
static void
pgtk_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
{
@@ -1829,7 +1764,6 @@ pgtk_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
unblock_input ();
}
-
DEFUN ("pgtk-frame-restack", Fpgtk_frame_restack, Spgtk_frame_restack, 2, 3, 0,
doc: /* Restack FRAME1 below FRAME2.
This means that if both frames are visible and the display areas of
@@ -2109,7 +2043,7 @@ use `(length \(display-monitor-attributes-list TERMINAL))' instead. */)
DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
- doc: /* Return the height in millimeters of the the display TERMINAL.
+ doc: /* Return the height in millimeters of the display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display.
@@ -2150,7 +2084,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */)
DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
- doc: /* Return the width in millimeters of the the display TERMINAL.
+ doc: /* Return the width in millimeters of the display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display.
@@ -2191,7 +2125,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */)
DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store, 0, 1, 0,
- doc: /* Return an indication of whether the the display TERMINAL does backing store.
+ doc: /* Return an indication of whether the display TERMINAL does backing store.
The value may be `buffered', `retained', or `non-retained'.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
@@ -2204,7 +2138,7 @@ If omitted or nil, that stands for the selected frame's display. */)
DEFUN ("x-display-visual-class", Fx_display_visual_class, Sx_display_visual_class, 0, 1, 0,
- doc: /* Return the visual class of the the display TERMINAL.
+ doc: /* Return the visual class of the display TERMINAL.
The value is one of the symbols `static-gray', `gray-scale',
`static-color', `pseudo-color', `true-color', or `direct-color'.
@@ -2246,7 +2180,6 @@ terminate Emacs if we can't open the connection. */)
CHECK_STRING (display);
- nxatoms_of_pgtkselect ();
dpyinfo = pgtk_term_init (display, SSDATA (Vx_resource_name));
if (dpyinfo == 0)
{
@@ -2291,27 +2224,6 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
return result;
}
-
-DEFUN ("pgtk-hide-others", Fpgtk_hide_others, Spgtk_hide_others, 0, 0, 0,
- doc: /* Hides all applications other than Emacs. */)
- (void)
-{
- check_window_system (NULL);
- return Qnil;
-}
-
-DEFUN ("pgtk-hide-emacs", Fpgtk_hide_emacs, Spgtk_hide_emacs, 1, 1, 0,
- doc: /* If ON is non-nil, the entire Emacs application is hidden.
-Otherwise if Emacs is hidden, it is unhidden.
-If ON is equal to `activate', Emacs is unhidden and becomes
-the active application. */)
- (Lisp_Object on)
-{
- check_window_system (NULL);
- return Qnil;
-}
-
-
DEFUN ("pgtk-font-name", Fpgtk_font_name, Spgtk_font_name, 1, 1, 0,
doc: /* Determine font PostScript or family name for font NAME.
NAME should be a string containing either the font name or an XLFD
@@ -2347,7 +2259,6 @@ check_x_display_info (Lisp_Object frame)
return check_pgtk_display_info (frame);
}
-
void
pgtk_set_scroll_bar_default_width (struct frame *f)
{
@@ -2395,9 +2306,8 @@ pgtk_get_string_resource (XrmDatabase rdb, const char *name,
return res;
}
-
Lisp_Object
-x_get_focus_frame (struct frame *frame)
+pgtk_get_focus_frame (struct frame *frame)
{
struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
Lisp_Object focus;
@@ -2409,13 +2319,6 @@ x_get_focus_frame (struct frame *frame)
return focus;
}
-/* ==========================================================================
-
- Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
-
- ========================================================================== */
-
-
DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
doc: /* Internal function called by `color-defined-p', which see. */)
(Lisp_Object color, Lisp_Object frame)
@@ -2447,7 +2350,6 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
return Qnil;
}
-
DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
doc: /* Internal function called by `display-color-p', which see. */)
(Lisp_Object terminal)
@@ -2456,7 +2358,6 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
return Qt;
}
-
DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, 0, 1, 0,
doc: /* Return t if the display supports shades of gray.
Note that color displays do support shades of gray.
@@ -2468,7 +2369,6 @@ If omitted or nil, that stands for the selected frame's display. */)
return Qnil;
}
-
DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, 0, 1, 0,
doc: /* Return the width in pixels of the display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
@@ -2514,7 +2414,6 @@ each physical monitor, use `display-monitor-attributes-list'. */)
return make_fixnum (width);
}
-
DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_height, 0, 1, 0,
doc: /* Return the height in pixels of the display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
@@ -2766,7 +2665,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
struct frame *f;
Lisp_Object frame;
Lisp_Object name;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool face_change_before = face_change;
if (!dpyinfo->terminal->name)
@@ -2778,7 +2677,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
RES_TYPE_STRING);
if (!STRINGP (name)
- && !EQ (name, Qunbound)
+ && !BASE_EQ (name, Qunbound)
&& !NILP (name))
error ("Invalid frame name--not a string or nil");
@@ -2796,9 +2695,6 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
counts etc. */
f->output_method = output_pgtk;
f->output_data.pgtk = xzalloc (sizeof *f->output_data.pgtk);
-#if 0
- f->output_data.pgtk->icon_bitmap = -1;
-#endif
FRAME_FONTSET (f) = -1;
f->output_data.pgtk->white_relief.pixel = -1;
f->output_data.pgtk->black_relief.pixel = -1;
@@ -2832,7 +2728,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
f->explicit_name = false;
@@ -2873,7 +2769,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
@@ -2924,10 +2820,6 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
gtk_window_set_type_hint (GTK_WINDOW (tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP);
f->output_data.pgtk->current_cursor = f->output_data.pgtk->text_cursor;
-#if 0
- x_make_gc (f);
-#endif
-
gui_default_parameter (f, parms, Qauto_raise, Qnil,
"autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
gui_default_parameter (f, parms, Qauto_lower, Qnil,
@@ -2936,6 +2828,8 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
"cursorType", "CursorType", RES_TYPE_SYMBOL);
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -2966,7 +2860,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct
Frame parameters may be changed if .Xdefaults contains
specifications for the default font. For example, if there is an
`Emacs.default.attributeBackground: pink', the `background-color'
- attribute of the frame get's set, which let's the internal border
+ attribute of the frame gets set, which lets the internal border
of the tooltip frame appear in pink. Prevent this. */
{
Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
@@ -3074,8 +2968,8 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
{
min_x = 0;
min_y = 0;
- max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f));
- max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f));
+ max_x = pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f));
+ max_y = pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f));
}
if (INTEGERP (top))
@@ -3114,7 +3008,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
/* Hide tooltip. Delete its frame if DELETE is true. */
static Lisp_Object
-x_hide_tip (bool delete)
+pgtk_hide_tip (bool delete)
{
if (!NILP (tip_timer))
{
@@ -3128,7 +3022,7 @@ x_hide_tip (bool delete)
value of x_gtk_use_system_tooltips might not be the same as used
for the tooltip we have to hide, see Bug#30399. */
if ((NILP (tip_last_frame) && NILP (tip_frame))
- || (!x_gtk_use_system_tooltips
+ || (!use_system_tooltips
&& !delete
&& FRAMEP (tip_frame)
&& FRAME_LIVE_P (XFRAME (tip_frame))
@@ -3139,10 +3033,9 @@ x_hide_tip (bool delete)
return Qnil;
else
{
- ptrdiff_t count;
Lisp_Object was_open = Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
@@ -3161,7 +3054,7 @@ x_hide_tip (bool delete)
/* When using GTK+ system tooltips (compare Bug#41200) reset
tip_last_frame. It will be reassigned when showing the next
GTK+ system tooltip. */
- if (x_gtk_use_system_tooltips)
+ if (use_system_tooltips)
tip_last_frame = Qnil;
/* Now look whether there's an Emacs tip around. */
@@ -3171,7 +3064,7 @@ x_hide_tip (bool delete)
if (FRAME_LIVE_P (f))
{
- if (delete || x_gtk_use_system_tooltips)
+ if (delete || use_system_tooltips)
{
/* Delete the Emacs tooltip frame when DELETE is true
or we change the tooltip type from an Emacs one to
@@ -3206,7 +3099,8 @@ PARMS is an optional list of frame parameters which can be used to
change the tooltip's appearance.
Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
-means use the default timeout of 5 seconds.
+means use the default timeout from the `x-show-tooltip-timeout'
+variable.
If the list of frame parameters PARMS contains a `left' parameter,
display the tooltip at that x-position. If the list of frame parameters
@@ -3234,8 +3128,7 @@ Text larger than the specified size is clipped. */)
struct text_pos pos;
int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t count_1;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object window, size, tip_buf;
AUTO_STRING (tip, " *tip*");
@@ -3253,9 +3146,8 @@ Text larger than the specified size is clipped. */)
return unbind_to (count, Qnil);
if (NILP (timeout))
- timeout = make_fixnum (5);
- else
- CHECK_FIXNAT (timeout);
+ timeout = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
if (NILP (dx))
dx = make_fixnum (5);
@@ -3267,7 +3159,7 @@ Text larger than the specified size is clipped. */)
else
CHECK_FIXNUM (dy);
- if (x_gtk_use_system_tooltips)
+ if (use_system_tooltips)
{
bool ok;
@@ -3356,13 +3248,13 @@ Text larger than the specified size is clipped. */)
}
}
- x_hide_tip (delete);
+ pgtk_hide_tip (delete);
}
else
- x_hide_tip (true);
+ pgtk_hide_tip (true);
}
else
- x_hide_tip (true);
+ pgtk_hide_tip (true);
tip_last_frame = frame;
tip_last_string = string;
@@ -3430,7 +3322,7 @@ Text larger than the specified size is clipped. */)
/* Insert STRING into root window's buffer and fit the frame to the
buffer. */
- count_1 = SPECPDL_INDEX ();
+ specpdl_ref count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
@@ -3489,7 +3381,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
Value is t if tooltip was open, nil otherwise. */)
(void)
{
- return x_hide_tip (!tooltip_reuse_hidden_frame);
+ return pgtk_hide_tip (!tooltip_reuse_hidden_frame);
}
/* Return geometric attributes of FRAME. According to the value of
@@ -3515,10 +3407,8 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
int left_pos, top_pos;
if (FRAME_GTK_OUTER_WIDGET (f))
- {
- gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- &left_pos, &top_pos);
- }
+ gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+ &left_pos, &top_pos);
else
{
GtkAllocation alloc;
@@ -3747,7 +3637,6 @@ visible. */)
(Lisp_Object frames)
{
Lisp_Object rest, tmp;
- int count;
if (!CONSP (frames))
frames = list1 (frames);
@@ -3766,7 +3655,7 @@ visible. */)
frames = Fnreverse (tmp);
/* Make sure the current matrices are up-to-date. */
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (32);
unbind_to (count, Qnil);
@@ -3804,7 +3693,7 @@ value of DIR as in previous invocations; this is standard MS Windows behavior.
char *fn;
Lisp_Object file = Qnil;
Lisp_Object decoded_file;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
char *cdef_file;
check_window_system (f);
@@ -3872,7 +3761,7 @@ nil, it defaults to the selected frame. */)
Lisp_Object font;
Lisp_Object font_param;
char *default_name = NULL;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (popup_activated ())
error ("Trying to use a menu from within a menu-entry");
@@ -3907,11 +3796,18 @@ nil, it defaults to the selected frame. */)
return unbind_to (count, font);
}
-/* ==========================================================================
+DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object enable)
+{
+ gboolean enable_debug = !NILP (enable);
- Lisp interface declaration
+ block_input ();
+ gtk_window_set_interactive_debugging (enable_debug);
+ unblock_input ();
- ========================================================================== */
+ return NILP (enable) ? Qnil : Qt;
+}
void
syms_of_pgtkfns (void)
@@ -3926,38 +3822,10 @@ syms_of_pgtkfns (void)
DEFSYM (Qresize_mode, "resize-mode");
DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
- doc: /* A string indicating the foreground color of the cursor box. */);
+ doc: /* SKIP: real doc in xfns.c. */);
Vx_cursor_fore_pixel = Qnil;
- DEFVAR_LISP ("pgtk-icon-type-alist", Vpgtk_icon_type_alist,
- doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
-If the title of a frame matches REGEXP, then IMAGE.tiff is
-selected as the image of the icon representing the frame when it's
-miniaturized. If an element is t, then Emacs tries to select an icon
-based on the filetype of the visited file.
-
-The images have to be installed in a folder called English.lproj in the
-Emacs folder. You have to restart Emacs after installing new icons.
-
-Example: Install an icon Gnus.tiff and execute the following code
-
-(setq pgtk-icon-type-alist
-(append pgtk-icon-type-alist
-\\='((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
-. \"Gnus\"))))
-
-When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
-be used as the image of the icon representing the frame. */);
- Vpgtk_icon_type_alist = list1 (Qt);
-
-
- /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
- is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
- But for a user it is a toolkit for X, and indeed, configure
- accepts --with-x-toolkit=gtk. */
- Fprovide (intern_c_string ("x-toolkit"), Qnil);
Fprovide (intern_c_string ("gtk"), Qnil);
- Fprovide (intern_c_string ("move-toolbar"), Qnil);
DEFVAR_LISP ("gtk-version-string", Vgtk_version_string,
doc: /* Version info for GTK+. */);
@@ -3984,7 +3852,6 @@ be used as the image of the icon representing the frame. */);
g_free (ver);
}
-
defsubr (&Spgtk_set_resource);
defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
defsubr (&Sx_display_grayscale_p);
@@ -4012,9 +3879,7 @@ be used as the image of the icon representing the frame. */);
defsubr (&Sx_open_connection);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
-
- defsubr (&Spgtk_hide_others);
- defsubr (&Spgtk_hide_emacs);
+ defsubr (&Sx_gtk_debug);
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
@@ -4030,10 +3895,6 @@ be used as the image of the icon representing the frame. */);
defsubr (&Sx_file_dialog);
defsubr (&Sx_select_font);
- as_status = 0;
- as_script = Qnil;
- as_result = 0;
-
monitor_scale_factor_alist = Qnil;
staticpro (&monitor_scale_factor_alist);
@@ -4050,58 +3911,21 @@ be used as the image of the icon representing the frame. */);
/* This is not ifdef:ed, so other builds than GTK can customize it. */
DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog,
- doc: /* Non-nil means prompt with the old GTK file selection dialog.
-If nil or if the file selection dialog is not available, the new GTK file
-chooser is used instead. To turn off all file dialogs set the
-variable `use-file-dialog'. */);
+ doc: /* SKIP: real doc in xfns.c. */);
x_gtk_use_old_file_dialog = false;
DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files,
- doc: /* If non-nil, the GTK file chooser will by default show hidden files.
-Note that this is just the default, there is a toggle button on the file
-chooser to show or not show hidden files on a case by case basis. */);
+ doc: /* SKIP: real doc in xfns.c. */);
x_gtk_show_hidden_files = false;
DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text,
- doc: /* If non-nil, the GTK file chooser will show additional help text.
-If more space for files in the file chooser dialog is wanted, set this to nil
-to turn the additional text off. */);
+ doc: /* SKIP: real doc in xfns.c. */);
x_gtk_file_dialog_help_text = true;
- DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
- doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
-Otherwise use Emacs own tooltip implementation.
-When using Gtk+ tooltips, the tooltip face is not used. */);
- x_gtk_use_system_tooltips = true;
-
DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
- doc: /* Maximum size for tooltips.
-Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
+ doc: /* SKIP: real doc in xfns.c. */);
Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40));
- DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
- doc: /* If non-nil, resize child frames specially with GTK builds.
-If this is nil, resize child frames like any other frames. This is the
-default and usually works with most desktops. Some desktop environments
-(GNOME shell in particular when using the mutter window manager),
-however, may refuse to resize a child frame when Emacs is built with
-GTK3. For those environments, the two settings below are provided.
-
-If this equals the symbol 'hide', Emacs temporarily hides the child
-frame during resizing. This approach seems to work reliably, may
-however induce some flicker when the frame is made visible again.
-
-If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
-always trigger an immediate resize of the child frame. This method is
-deprecated by GTK and may not work in future versions of that toolkit.
-It also may freeze Emacs when used with other desktop environments. It
-avoids, however, the unpleasant flicker induced by the hiding approach.
-
-This variable is considered a temporary workaround and will be hopefully
-eliminated in future versions of Emacs. */);
- x_gtk_resize_child_frames = Qnil;
-
-
DEFSYM (Qmono, "mono");
DEFSYM (Qassq_delete_all, "assq-delete-all");
@@ -4115,5 +3939,3 @@ eliminated in future versions of Emacs. */);
DEFSYM (Qreverse_portrait, "reverse-portrait");
DEFSYM (Qreverse_landscape, "reverse-landscape");
}
-
-#endif
diff --git a/src/pgtkim.c b/src/pgtkim.c
index 8577ba2116e..e1fffafb611 100644
--- a/src/pgtkim.c
+++ b/src/pgtkim.c
@@ -25,7 +25,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "pgtkterm.h"
static void
-im_context_commit_cb (GtkIMContext * imc, gchar * str, gpointer user_data)
+im_context_commit_cb (GtkIMContext *imc,
+ gchar *str,
+ gpointer user_data)
{
struct pgtk_display_info *dpyinfo = user_data;
struct frame *f = dpyinfo->im.focused_frame;
@@ -39,21 +41,21 @@ im_context_commit_cb (GtkIMContext * imc, gchar * str, gpointer user_data)
}
static gboolean
-im_context_retrieve_surrounding_cb (GtkIMContext * imc, gpointer user_data)
+im_context_retrieve_surrounding_cb (GtkIMContext *imc, gpointer user_data)
{
gtk_im_context_set_surrounding (imc, "", -1, 0);
return TRUE;
}
static gboolean
-im_context_delete_surrounding_cb (GtkIMContext * imc, int offset, int n_chars,
+im_context_delete_surrounding_cb (GtkIMContext *imc, int offset, int n_chars,
gpointer user_data)
{
return TRUE;
}
static Lisp_Object
-make_color_string (PangoAttrColor * pac)
+make_color_string (PangoAttrColor *pac)
{
char buf[256];
sprintf (buf, "#%02x%02x%02x",
@@ -62,7 +64,7 @@ make_color_string (PangoAttrColor * pac)
}
static void
-im_context_preedit_changed_cb (GtkIMContext * imc, gpointer user_data)
+im_context_preedit_changed_cb (GtkIMContext *imc, gpointer user_data)
{
struct pgtk_display_info *dpyinfo = user_data;
struct frame *f = dpyinfo->im.focused_frame;
@@ -149,7 +151,7 @@ im_context_preedit_changed_cb (GtkIMContext * imc, gpointer user_data)
}
static void
-im_context_preedit_end_cb (GtkIMContext * imc, gpointer user_data)
+im_context_preedit_end_cb (GtkIMContext *imc, gpointer user_data)
{
struct pgtk_display_info *dpyinfo = user_data;
struct frame *f = dpyinfo->im.focused_frame;
@@ -163,7 +165,7 @@ im_context_preedit_end_cb (GtkIMContext * imc, gpointer user_data)
}
static void
-im_context_preedit_start_cb (GtkIMContext * imc, gpointer user_data)
+im_context_preedit_start_cb (GtkIMContext *imc, gpointer user_data)
{
}
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c
index d1b1bfffb36..2eabf6ac1bc 100644
--- a/src/pgtkmenu.c
+++ b/src/pgtkmenu.c
@@ -43,7 +43,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <gtk/gtk.h>
/* Flag which when set indicates a dialog or menu has been posted by
- Xt on behalf of one of the widget sets. */
+ GTK on behalf of one of the widget sets. */
static int popup_activated_flag;
/* Set menu_items_inuse so no other popup menu or dialog is created. */
@@ -62,19 +62,14 @@ pgtk_menu_set_in_use (bool in_use)
struct frame *f = XFRAME (frame);
if (in_use && FRAME_Z_GROUP_ABOVE (f))
- x_set_z_group (f, Qabove_suspended, Qabove);
+ pgtk_set_z_group (f, Qabove_suspended, Qabove);
else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
- x_set_z_group (f, Qabove, Qabove_suspended);
+ pgtk_set_z_group (f, Qabove, Qabove_suspended);
}
}
DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
- doc: /* Start key navigation of the menu bar in FRAME.
- This initially opens the first menu bar item and you can then navigate with the
- arrow keys, select a menu entry with the return key or cancel with the
- escape key. If FRAME has no menu bar this function does nothing.
-
- If FRAME is nil or not given, use the selected frame. */)
+ doc: /* SKIP: real doc in USE_GTK definition in xmenu.c. */)
(Lisp_Object frame)
{
GtkWidget *menubar;
@@ -132,7 +127,7 @@ pgtk_activate_menubar (struct frame *f)
static void
popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
{
- popup_activated_flag = 0;
+ pgtk_menu_set_in_use (false);
}
/* Function that finds the frame for WIDGET and shows the HELP text
@@ -141,31 +136,15 @@ popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
static void
show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help)
{
- /* Don't show this tooltip.
- * Tooltips are always tied to main widget, so stacking order
- * on Wayland is:
- * (above)
- * - menu
- * - tooltip
- * - main widget
- * (below)
- * This is applicable to tooltips for menu, and menu tooltips
- * are shown below menus.
- * As a workaround, I entrust Gtk with menu tooltips, and
- * let emacs not to show menu tooltips.
- */
-
-#if 0
- Lisp_Object frame;
-
- if (f)
- {
- XSETFRAME (frame, f);
- kbd_buffer_store_help_event (frame, help);
- }
- else
- show_help_echo (help, Qnil, Qnil, Qnil);
-#endif
+ /* Don't show help echo on PGTK, as tooltips are always transient
+ for the main widget, so on Wayland the menu will display above
+ and obscure the tooltip. FIXME: this is some low hanging fruit
+ for fixing. After you fix Fx_show_tip in pgtkterm.c so that it
+ can display tooltips above menus, copy the definition of this
+ function from xmenu.c.
+
+ As a workaround, GTK is used to display menu tooltips, outside
+ the Emacs help echo machinery. */
}
/* Callback called when menu items are highlighted/unhighlighted
@@ -279,7 +258,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
{
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
@@ -558,7 +537,7 @@ create_and_show_popup_menu (struct frame *f, widget_value * first_wv,
int x, int y, bool for_click)
{
GtkWidget *menu;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_PGTK_P (f));
@@ -625,17 +604,12 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
= alloca (menu_items_used * sizeof *subprefix_stack);
int submenu_depth = 0;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_PGTK_P (f));
*error_name = NULL;
- if (!FRAME_GTK_OUTER_WIDGET (f)) {
- *error_name = "Can't popup from child frames.";
- return Qnil;
- }
-
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
@@ -902,7 +876,7 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
if (menu)
{
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
record_unwind_protect_ptr (pop_down_menu, menu);
/* Display the menu. */
@@ -934,17 +908,12 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title,
/* Whether we've seen the boundary between left-hand elts and right-hand. */
bool boundary_seen = false;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_PGTK_P (f));
*error_name = NULL;
- if (!FRAME_GTK_OUTER_WIDGET (f)) {
- *error_name = "Can't popup from child frames.";
- return Qnil;
- }
-
if (menu_items_n_panes > 1)
{
*error_name = "Multiple panes in dialog box";
@@ -1087,7 +1056,7 @@ pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
Lisp_Object title;
const char *error_name;
Lisp_Object selection;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
check_window_system (f);
diff --git a/src/pgtkselect.c b/src/pgtkselect.c
index 23a79895d54..e0230003b3a 100644
--- a/src/pgtkselect.c
+++ b/src/pgtkselect.c
@@ -17,14 +17,6 @@ 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 <https://www.gnu.org/licenses/>. */
-/*
-Originally by Carl Edman
-Updated by Christian Limpach (chris@nice.ch)
-OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
-macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
-GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
-*/
-
/* This should be the first include, as it may set up #defines affecting
interpretation of even the system includes. */
#include <config.h>
@@ -33,25 +25,37 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
#include "pgtkterm.h"
#include "termhooks.h"
#include "keyboard.h"
-#include "pgtkselect.h"
-#include <gdk/gdk.h>
-
-#if 0
-static Lisp_Object Vselection_alist;
-#endif
+#include "atimer.h"
+#include "blockinput.h"
-static GQuark quark_primary_data = 0;
-static GQuark quark_primary_size = 0;
-static GQuark quark_secondary_data = 0;
-static GQuark quark_secondary_size = 0;
-static GQuark quark_clipboard_data = 0;
-static GQuark quark_clipboard_size = 0;
+/* This file deliberately does not implement INCR, since it adds a
+ bunch of extra code for no real gain, as PGTK isn't supposed to
+ support X11 anyway. */
-/* ==========================================================================
+/* Advance declaration of structs. */
+struct selection_data;
+struct prop_location;
- Internal utility functions
-
- ========================================================================== */
+static void pgtk_decline_selection_request (struct selection_input_event *);
+static bool pgtk_convert_selection (Lisp_Object, Lisp_Object, GdkAtom, bool,
+ struct pgtk_display_info *);
+static bool waiting_for_other_props_on_window (GdkDisplay *, GdkWindow *);
+#if 0
+static struct prop_location *expect_property_change (GdkDisplay *, GdkWindow *,
+ GdkAtom, int);
+#endif
+static void unexpect_property_change (struct prop_location *);
+static void wait_for_property_change (struct prop_location *);
+static Lisp_Object pgtk_get_window_property_as_lisp_data (struct pgtk_display_info *,
+ GdkWindow *, GdkAtom,
+ Lisp_Object, GdkAtom, bool);
+static Lisp_Object selection_data_to_lisp_data (struct pgtk_display_info *,
+ const unsigned char *,
+ ptrdiff_t, GdkAtom, int);
+static void lisp_data_to_selection_data (struct pgtk_display_info *, Lisp_Object,
+ struct selection_data *);
+static Lisp_Object pgtk_get_local_selection (Lisp_Object, Lisp_Object,
+ bool, struct pgtk_display_info *);
/* From a Lisp_Object, return a suitable frame for selection
operations. OBJECT may be a frame, a terminal object, or nil
@@ -100,489 +104,1765 @@ frame_for_pgtk_selection (Lisp_Object object)
return NULL;
}
-static GtkClipboard *
-symbol_to_gtk_clipboard (GtkWidget * widget, Lisp_Object symbol)
+#define LOCAL_SELECTION(selection_symbol, dpyinfo) \
+ assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist)
+
+static GdkAtom
+symbol_to_gdk_atom (Lisp_Object sym)
{
- GdkAtom atom;
+ if (NILP (sym))
+ return GDK_NONE;
- CHECK_SYMBOL (symbol);
- if (NILP (symbol))
- {
- atom = GDK_SELECTION_PRIMARY;
- }
- else if (EQ (symbol, QCLIPBOARD))
+ if (EQ (sym, QPRIMARY))
+ return GDK_SELECTION_PRIMARY;
+ if (EQ (sym, QSECONDARY))
+ return GDK_SELECTION_SECONDARY;
+ if (EQ (sym, QCLIPBOARD))
+ return GDK_SELECTION_CLIPBOARD;
+
+ if (!SYMBOLP (sym))
+ emacs_abort ();
+
+ return gdk_atom_intern (SSDATA (SYMBOL_NAME (sym)), FALSE);
+}
+
+static Lisp_Object
+gdk_atom_to_symbol (GdkAtom atom)
+{
+ return intern (gdk_atom_name (atom));
+}
+
+
+
+/* Do protocol to assert ourself as a selection owner.
+ FRAME shall be the owner; it must be a valid GDK frame.
+ Update the Vselection_alist so that we can reply to later requests for
+ our selection. */
+
+static void
+pgtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
+ Lisp_Object frame)
+{
+ struct frame *f = XFRAME (frame);
+ struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ guint32 timestamp = gtk_get_current_event_time ();
+ GdkAtom selection_atom = symbol_to_gdk_atom (selection_name);
+ Lisp_Object targets;
+ ptrdiff_t i, ntargets;
+ GtkTargetEntry *gtargets;
+
+ if (timestamp == GDK_CURRENT_TIME)
+ timestamp = dpyinfo->last_user_time;
+
+ /* Assert ownership over the selection. Ideally we would use only
+ the GDK selection API for this, but it just doesn't work on
+ Wayland. */
+
+ if (!gdk_selection_owner_set_for_display (dpyinfo->display,
+ FRAME_GDK_WINDOW (f),
+ selection_atom,
+ timestamp, TRUE))
+ signal_error ("Could not assert ownership over selection", selection_name);
+
+ /* Update the local cache */
+ {
+ Lisp_Object selection_data;
+ Lisp_Object prev_value;
+
+ selection_data = list4 (selection_name, selection_value,
+ INT_TO_INTEGER (timestamp), frame);
+ prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
+
+ tset_selection_alist
+ (dpyinfo->terminal,
+ Fcons (selection_data, dpyinfo->terminal->Vselection_alist));
+
+ /* If we already owned the selection, remove the old selection
+ data. Don't use Fdelq as that may quit. */
+ if (!NILP (prev_value))
+ {
+ /* We know it's not the CAR, so it's easy. */
+ Lisp_Object rest = dpyinfo->terminal->Vselection_alist;
+ for (; CONSP (rest); rest = XCDR (rest))
+ if (EQ (prev_value, Fcar (XCDR (rest))))
+ {
+ XSETCDR (rest, XCDR (XCDR (rest)));
+ break;
+ }
+ }
+ }
+
+ /* Announce the targets to the display server. This isn't required
+ on X, but is on Wayland. */
+
+ targets = pgtk_get_local_selection (selection_name, QTARGETS,
+ true, dpyinfo);
+
+ /* GC must not happen inside this segment. */
+ block_input ();
+ gtk_selection_clear_targets (FRAME_GTK_WIDGET (f), selection_atom);
+
+ if (VECTORP (targets))
{
- atom = GDK_SELECTION_CLIPBOARD;
+ gtargets = xzalloc (sizeof *gtargets * ASIZE (targets));
+ ntargets = 0;
+
+ for (i = 0; i < ASIZE (targets); ++i)
+ {
+ if (SYMBOLP (AREF (targets, i)))
+ gtargets[ntargets++].target
+ = SSDATA (SYMBOL_NAME (AREF (targets, i)));
+ }
+
+ gtk_selection_add_targets (FRAME_GTK_WIDGET (f),
+ selection_atom, gtargets,
+ ntargets);
+
+ xfree (gtargets);
}
- else if (EQ (symbol, QPRIMARY))
+ unblock_input ();
+}
+
+static Lisp_Object
+pgtk_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
+ bool local_request, struct pgtk_display_info *dpyinfo)
+{
+ Lisp_Object local_value, tem;
+ Lisp_Object handler_fn, value, check;
+
+ local_value = LOCAL_SELECTION (selection_symbol, dpyinfo);
+
+ if (NILP (local_value)) return Qnil;
+
+ /* TIMESTAMP is a special case. */
+ if (EQ (target_type, QTIMESTAMP))
{
- atom = GDK_SELECTION_PRIMARY;
+ handler_fn = Qnil;
+ value = XCAR (XCDR (XCDR (local_value)));
}
- else if (EQ (symbol, QSECONDARY))
+ else
{
- atom = GDK_SELECTION_SECONDARY;
+ /* Don't allow a quit within the converter.
+ When the user types C-g, he would be surprised
+ if by luck it came during a converter. */
+ specpdl_ref count = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
+
+ CHECK_SYMBOL (target_type);
+ handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
+
+ if (CONSP (handler_fn))
+ handler_fn = XCDR (handler_fn);
+
+ tem = XCAR (XCDR (local_value));
+
+ if (STRINGP (tem))
+ {
+ local_value = Fget_text_property (make_fixnum (0),
+ target_type, tem);
+
+ if (!NILP (local_value))
+ tem = local_value;
+ }
+
+ if (!NILP (handler_fn))
+ value = call3 (handler_fn, selection_symbol,
+ (local_request
+ ? Qnil
+ : target_type),
+ tem);
+ else
+ value = Qnil;
+ value = unbind_to (count, value);
}
- else if (EQ (symbol, Qt))
+
+ /* Make sure this value is of a type that we could transmit
+ to another client. */
+
+ check = value;
+ if (CONSP (value)
+ && SYMBOLP (XCAR (value)))
+ check = XCDR (value);
+
+ if (STRINGP (check)
+ || VECTORP (check)
+ || SYMBOLP (check)
+ || INTEGERP (check)
+ || NILP (value))
+ return value;
+ /* Check for a value that CONS_TO_INTEGER could handle. */
+ else if (CONSP (check)
+ && INTEGERP (XCAR (check))
+ && (INTEGERP (XCDR (check))
+ ||
+ (CONSP (XCDR (check))
+ && INTEGERP (XCAR (XCDR (check)))
+ && NILP (XCDR (XCDR (check))))))
+ return value;
+
+ signal_error ("Invalid data returned by selection-conversion function",
+ list2 (handler_fn, value));
+}
+
+static void
+pgtk_decline_selection_request (struct selection_input_event *event)
+{
+ gdk_selection_send_notify (SELECTION_EVENT_REQUESTOR (event),
+ SELECTION_EVENT_SELECTION (event),
+ SELECTION_EVENT_TARGET (event),
+ GDK_NONE, SELECTION_EVENT_TIME (event));
+}
+
+struct selection_data
+{
+ unsigned char *data;
+ ptrdiff_t size;
+ int format;
+ GdkAtom type;
+ bool nofree;
+ GdkAtom property;
+
+ /* This can be set to non-NULL during x_reply_selection_request, if
+ the selection is waiting for an INCR transfer to complete. Don't
+ free these; that's done by unexpect_property_change. */
+ struct prop_location *wait_object;
+ struct selection_data *next;
+};
+
+struct pgtk_selection_request
+{
+ /* The last element in this stack. */
+ struct pgtk_selection_request *last;
+
+ /* Its display info. */
+ struct pgtk_display_info *dpyinfo;
+
+ /* Its selection input event. */
+ struct selection_input_event *request;
+
+ /* Linked list of the above (in support of MULTIPLE targets). */
+ struct selection_data *converted_selections;
+
+ /* "Data" to send a requestor for a failed MULTIPLE subtarget. */
+ GdkAtom conversion_fail_tag;
+
+ /* Whether or not conversion was successful. */
+ bool converted;
+};
+
+/* Stack of selections currently being processed.
+ NULL if all requests have been fully processed. */
+
+struct pgtk_selection_request *selection_request_stack;
+
+static void
+pgtk_push_current_selection_request (struct selection_input_event *se,
+ struct pgtk_display_info *dpyinfo)
+{
+ struct pgtk_selection_request *frame;
+
+ frame = xmalloc (sizeof *frame);
+ frame->converted = false;
+ frame->last = selection_request_stack;
+ frame->request = se;
+ frame->dpyinfo = dpyinfo;
+ frame->converted_selections = NULL;
+ frame->conversion_fail_tag = GDK_NONE;
+
+ selection_request_stack = frame;
+}
+
+static void
+pgtk_pop_current_selection_request (void)
+{
+ struct pgtk_selection_request *tem;
+
+ tem = selection_request_stack;
+ selection_request_stack = selection_request_stack->last;
+
+ xfree (tem);
+}
+
+/* Used as an unwind-protect clause so that, if a selection-converter signals
+ an error, we tell the requestor that we were unable to do what they wanted
+ before we throw to top-level or go into the debugger or whatever. */
+
+static void
+pgtk_selection_request_lisp_error (void)
+{
+ struct selection_data *cs, *next;
+ struct pgtk_selection_request *frame;
+
+ frame = selection_request_stack;
+
+ for (cs = frame->converted_selections; cs; cs = next)
{
- atom = GDK_SELECTION_SECONDARY;
+ next = cs->next;
+ if (! cs->nofree && cs->data)
+ xfree (cs->data);
+ xfree (cs);
}
- else
+ frame->converted_selections = NULL;
+
+ if (!frame->converted && frame->dpyinfo->display)
+ pgtk_decline_selection_request (frame->request);
+}
+
+/* This stuff is so that INCR selections are reentrant (that is, so we can
+ be servicing multiple INCR selection requests simultaneously.) I haven't
+ actually tested that yet. */
+
+/* Keep a list of the property changes that are awaited. */
+
+struct prop_location
+{
+ int identifier;
+ GdkDisplay *display;
+ GdkWindow *window;
+ GdkAtom property;
+ int desired_state;
+ bool arrived;
+ struct prop_location *next;
+};
+
+#if 0
+
+static int prop_location_identifier;
+
+#endif
+
+static Lisp_Object property_change_reply;
+
+static struct prop_location *property_change_reply_object;
+
+static struct prop_location *property_change_wait_list;
+
+static void
+set_property_change_object (struct prop_location *location)
+{
+ /* Input must be blocked so we don't get the event before we set these. */
+ if (!input_blocked_p ())
+ emacs_abort ();
+
+ XSETCAR (property_change_reply, Qnil);
+ property_change_reply_object = location;
+}
+
+
+/* Send the reply to a selection request event EVENT. */
+
+static void
+pgtk_reply_selection_request (struct selection_input_event *event,
+ struct pgtk_display_info *dpyinfo)
+{
+ GdkDisplay *display = SELECTION_EVENT_DISPLAY (event);
+ GdkWindow *window = SELECTION_EVENT_REQUESTOR (event);
+ ptrdiff_t bytes_remaining;
+ struct selection_data *cs;
+ struct pgtk_selection_request *frame;
+
+ frame = selection_request_stack;
+
+ block_input ();
+ /* Loop over converted selections, storing them in the requested
+ properties. If data is large, only store the first N bytes
+ (section 2.7.2 of ICCCM). Note that we store the data for a
+ MULTIPLE request in the opposite order; the ICCM says only that
+ the conversion itself must be done in the same order. */
+ for (cs = frame->converted_selections; cs; cs = cs->next)
{
- atom = 0;
- error ("Bad selection");
+ if (cs->property == GDK_NONE)
+ continue;
+
+ bytes_remaining = cs->size;
+ bytes_remaining *= cs->format >> 3;
+
+ gdk_property_change (window, cs->property,
+ cs->type, cs->format,
+ GDK_PROP_MODE_APPEND,
+ cs->data, cs->size);
}
- return gtk_widget_get_clipboard (widget, atom);
+ /* Now issue the SelectionNotify event. */
+ gdk_selection_send_notify (window,
+ SELECTION_EVENT_SELECTION (event),
+ SELECTION_EVENT_TARGET (event),
+ SELECTION_EVENT_PROPERTY (event),
+ SELECTION_EVENT_TIME (event));
+ gdk_display_flush (display);
+
+ /* Finish sending the rest of each of the INCR values. This should
+ be improved; there's a chance of deadlock if more than one
+ subtarget in a MULTIPLE selection requires an INCR transfer, and
+ the requestor and Emacs loop waiting on different transfers. */
+ for (cs = frame->converted_selections; cs; cs = cs->next)
+ if (cs->wait_object)
+ {
+ int format_bytes = cs->format / 8;
+
+ /* Must set this inside block_input (). unblock_input may read
+ events and setting property_change_reply in
+ wait_for_property_change is then too late. */
+ set_property_change_object (cs->wait_object);
+ unblock_input ();
+
+ bytes_remaining = cs->size;
+ bytes_remaining *= format_bytes;
+
+ /* Wait for the requestor to ack by deleting the property.
+ This can run Lisp code (process handlers) or signal. */
+ wait_for_property_change (cs->wait_object);
+
+ /* Now write a zero-length chunk to the property to tell the
+ requestor that we're done. */
+ block_input ();
+ if (! waiting_for_other_props_on_window (display, window))
+ gdk_window_set_events (window, 0);
+ gdk_property_change (window, cs->property, cs->type, cs->format,
+ GDK_PROP_MODE_REPLACE, cs->data, 0);
+ }
+
+ gdk_display_sync (display);
+ unblock_input ();
}
+
+
+/* Handle a SelectionRequest event EVENT.
+ This is called from keyboard.c when such an event is found in the queue. */
+
static void
-selection_type_to_quarks (GdkAtom type, GQuark * quark_data,
- GQuark * quark_size)
+pgtk_handle_selection_request (struct selection_input_event *event)
{
- if (type == GDK_SELECTION_PRIMARY)
+ guint32 local_selection_time;
+ struct pgtk_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event);
+ GdkAtom selection = SELECTION_EVENT_SELECTION (event);
+ Lisp_Object selection_symbol = gdk_atom_to_symbol (selection);
+ GdkAtom target = SELECTION_EVENT_TARGET (event);
+ Lisp_Object target_symbol = gdk_atom_to_symbol (target);
+ GdkAtom property = SELECTION_EVENT_PROPERTY (event);
+ Lisp_Object local_selection_data;
+ bool success = false;
+ specpdl_ref count = SPECPDL_INDEX ();
+ bool pushed;
+ Lisp_Object alias, tem;
+
+ alias = Vpgtk_selection_alias_alist;
+
+ FOR_EACH_TAIL_SAFE (alias)
{
- *quark_data = quark_primary_data;
- *quark_size = quark_primary_size;
+ tem = Qnil;
+
+ if (CONSP (alias))
+ tem = XCAR (alias);
+
+ if (CONSP (tem)
+ && EQ (XCAR (tem), selection_symbol)
+ && SYMBOLP (XCDR (tem)))
+ {
+ selection_symbol = XCDR (tem);
+ break;
+ }
}
- else if (type == GDK_SELECTION_SECONDARY)
+
+ pushed = false;
+
+ if (!dpyinfo)
+ goto DONE;
+
+ local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo);
+
+ /* Decline if we don't own any selections. */
+ if (NILP (local_selection_data)) goto DONE;
+
+ /* Decline requests issued prior to our acquiring the selection. */
+ CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
+ guint32, local_selection_time);
+ if (SELECTION_EVENT_TIME (event) != GDK_CURRENT_TIME
+ && local_selection_time > SELECTION_EVENT_TIME (event))
+ goto DONE;
+
+ block_input ();
+ pushed = true;
+ pgtk_push_current_selection_request (event, dpyinfo);
+ record_unwind_protect_void (pgtk_pop_current_selection_request);
+ record_unwind_protect_void (pgtk_selection_request_lisp_error);
+ unblock_input ();
+
+ if (EQ (target_symbol, QMULTIPLE))
{
- *quark_data = quark_secondary_data;
- *quark_size = quark_secondary_size;
+ /* For MULTIPLE targets, the event property names a list of atom
+ pairs; the first atom names a target and the second names a
+ non-GDK_NONE property. */
+ GdkWindow *requestor = SELECTION_EVENT_REQUESTOR (event);
+ Lisp_Object multprop;
+ ptrdiff_t j, nselections;
+ struct selection_data cs;
+
+ if (property == GDK_NONE)
+ goto DONE;
+
+ multprop = pgtk_get_window_property_as_lisp_data (dpyinfo,
+ requestor,
+ property,
+ QMULTIPLE,
+ selection,
+ true);
+
+ if (!VECTORP (multprop) || ASIZE (multprop) % 2)
+ goto DONE;
+
+ nselections = ASIZE (multprop) / 2;
+ /* Perform conversions. This can signal. */
+ for (j = 0; j < nselections; j++)
+ {
+ Lisp_Object subtarget = AREF (multprop, 2*j);
+ GdkAtom subproperty = symbol_to_gdk_atom (AREF (multprop, 2 * j + 1));
+ bool subsuccess = false;
+
+ if (subproperty != GDK_NONE)
+ subsuccess = pgtk_convert_selection (selection_symbol, subtarget,
+ subproperty, true, dpyinfo);
+ if (!subsuccess)
+ ASET (multprop, 2*j+1, Qnil);
+ }
+ /* Save conversion results */
+ lisp_data_to_selection_data (dpyinfo, multprop, &cs);
+ gdk_property_change (requestor, property,
+ cs.type, cs.format,
+ GDK_PROP_MODE_REPLACE,
+ cs.data, cs.size);
+ success = true;
}
- else if (type == GDK_SELECTION_CLIPBOARD)
+ else
{
- *quark_data = quark_clipboard_data;
- *quark_size = quark_clipboard_size;
+ if (property == GDK_NONE)
+ property = SELECTION_EVENT_TARGET (event);
+
+ success = pgtk_convert_selection (selection_symbol,
+ target_symbol, property,
+ false, dpyinfo);
}
+
+ DONE:
+
+ if (pushed)
+ selection_request_stack->converted = true;
+
+ if (success)
+ pgtk_reply_selection_request (event, dpyinfo);
else
+ pgtk_decline_selection_request (event);
+
+ /* Run the `pgtk-sent-selection-functions' abnormal hook. */
+ if (!NILP (Vpgtk_sent_selection_functions)
+ && !BASE_EQ (Vpgtk_sent_selection_functions, Qunbound))
+ CALLN (Frun_hook_with_args, Qpgtk_sent_selection_functions,
+ selection_symbol, target_symbol, success ? Qt : Qnil);
+
+ unbind_to (count, Qnil);
+}
+
+/* Perform the requested selection conversion, and write the data to
+ the converted_selections linked list, where it can be accessed by
+ x_reply_selection_request. If FOR_MULTIPLE, write out
+ the data even if conversion fails, using conversion_fail_tag.
+
+ Return true if (and only if) successful. */
+
+static bool
+pgtk_convert_selection (Lisp_Object selection_symbol,
+ Lisp_Object target_symbol, GdkAtom property,
+ bool for_multiple, struct pgtk_display_info *dpyinfo)
+{
+ Lisp_Object lisp_selection;
+ struct selection_data *cs;
+ struct pgtk_selection_request *frame;
+
+ lisp_selection
+ = pgtk_get_local_selection (selection_symbol, target_symbol,
+ false, dpyinfo);
+
+ frame = selection_request_stack;
+
+ /* A nil return value means we can't perform the conversion. */
+ if (NILP (lisp_selection)
+ || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection))))
{
- /* fixme: Is it safe to use 'error' here? */
- error ("Unknown selection type.");
+ if (for_multiple)
+ {
+ cs = xmalloc (sizeof *cs);
+ cs->data = ((unsigned char *)
+ &selection_request_stack->conversion_fail_tag);
+ cs->size = 1;
+ cs->format = 32;
+ cs->type = GDK_SELECTION_TYPE_ATOM;
+ cs->nofree = true;
+ cs->property = property;
+ cs->wait_object = NULL;
+ cs->next = frame->converted_selections;
+ frame->converted_selections = cs;
+ }
+
+ return false;
}
+
+ /* Otherwise, record the converted selection to binary. */
+ cs = xmalloc (sizeof *cs);
+ cs->data = NULL;
+ cs->nofree = true;
+ cs->property = property;
+ cs->wait_object = NULL;
+ cs->next = frame->converted_selections;
+ frame->converted_selections = cs;
+ lisp_data_to_selection_data (dpyinfo, lisp_selection, cs);
+ return true;
}
+
+
+/* Handle a SelectionClear event EVENT, which indicates that some
+ client cleared out our previously asserted selection.
+ This is called from keyboard.c when such an event is found in the queue. */
+
static void
-get_func (GtkClipboard * cb, GtkSelectionData * data, guint info,
- gpointer user_data_or_owner)
+pgtk_handle_selection_clear (struct selection_input_event *event)
{
- GObject *obj = G_OBJECT (user_data_or_owner);
- const char *str;
- int size;
- GQuark quark_data, quark_size;
+ GdkAtom selection = SELECTION_EVENT_SELECTION (event);
+ guint32 changed_owner_time = SELECTION_EVENT_TIME (event);
- selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data,
- &quark_size);
+ Lisp_Object selection_symbol, local_selection_data;
+ guint32 local_selection_time;
+ struct pgtk_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event);
+ Lisp_Object Vselection_alist;
- str = g_object_get_qdata (obj, quark_data);
- size = GPOINTER_TO_SIZE (g_object_get_qdata (obj, quark_size));
- gtk_selection_data_set_text (data, str, size);
+ if (!dpyinfo) return;
+
+ selection_symbol = gdk_atom_to_symbol (selection);
+ local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo);
+
+ /* Well, we already believe that we don't own it, so that's just fine. */
+ if (NILP (local_selection_data)) return;
+
+ CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
+ guint32, local_selection_time);
+
+ /* We have reasserted the selection since this SelectionClear was
+ generated, so we can disregard it. */
+ if (changed_owner_time != GDK_CURRENT_TIME
+ && local_selection_time > changed_owner_time)
+ return;
+
+ /* Otherwise, really clear. Don't use Fdelq as that may quit. */
+ Vselection_alist = dpyinfo->terminal->Vselection_alist;
+ if (EQ (local_selection_data, CAR (Vselection_alist)))
+ Vselection_alist = XCDR (Vselection_alist);
+ else
+ {
+ Lisp_Object rest;
+ for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest))
+ if (EQ (local_selection_data, CAR (XCDR (rest))))
+ {
+ XSETCDR (rest, XCDR (XCDR (rest)));
+ break;
+ }
+ }
+ tset_selection_alist (dpyinfo->terminal, Vselection_alist);
+
+ /* Run the `pgtk-lost-selection-functions' abnormal hook. */
+ CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, selection_symbol);
+
+ redisplay_preserve_echo_area (20);
}
-static void
-clear_func (GtkClipboard * cb, gpointer user_data_or_owner)
+void
+pgtk_handle_selection_event (struct selection_input_event *event)
+{
+ if (event->kind != SELECTION_REQUEST_EVENT)
+ pgtk_handle_selection_clear (event);
+ else
+ pgtk_handle_selection_request (event);
+}
+
+/* Clear all selections that were made from frame F.
+ We do this when about to delete a frame. */
+
+void
+pgtk_clear_frame_selections (struct frame *f)
+{
+ Lisp_Object frame, rest, timestamp, symbol;
+ guint32 time;
+ struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ struct terminal *t = dpyinfo->terminal;
+
+ XSETFRAME (frame, f);
+
+ /* Delete elements from the beginning of Vselection_alist. */
+ while (CONSP (t->Vselection_alist)
+ && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist)))))))
+ {
+ symbol = Fcar (Fcar (t->Vselection_alist));
+
+ /* Run the `pgtk-lost-selection-functions' abnormal hook. */
+ CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions,
+ symbol);
+
+ timestamp = Fcar (Fcdr (Fcdr (Fcar (t->Vselection_alist))));
+ CONS_TO_INTEGER (timestamp, guint32, time);
+
+ /* On Wayland, GDK will still ask the (now non-existent) frame for
+ selection data, even though we no longer think the selection is
+ owned by us. Manually relinquish ownership of the selection. */
+ gdk_selection_owner_set_for_display (dpyinfo->display,
+ NULL,
+ symbol_to_gdk_atom (symbol),
+ time, TRUE);
+
+ tset_selection_alist (t, XCDR (t->Vselection_alist));
+ }
+
+ /* Delete elements after the beginning of Vselection_alist. */
+ for (rest = t->Vselection_alist; CONSP (rest); rest = XCDR (rest))
+ if (CONSP (XCDR (rest))
+ && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest))))))))
+ {
+ symbol = XCAR (XCAR (XCDR (rest)));
+ CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions,
+ symbol);
+
+ timestamp = XCAR (XCDR (XCDR (XCAR (XCDR (rest)))));
+ CONS_TO_INTEGER (timestamp, guint32, time);
+
+ gdk_selection_owner_set_for_display (dpyinfo->display,
+ NULL,
+ symbol_to_gdk_atom (symbol),
+ time, TRUE);
+
+ XSETCDR (rest, XCDR (XCDR (rest)));
+ break;
+ }
+}
+
+/* True if any properties for DISPLAY and WINDOW
+ are on the list of what we are waiting for. */
+
+static bool
+waiting_for_other_props_on_window (GdkDisplay *display, GdkWindow *window)
{
- GObject *obj = G_OBJECT (user_data_or_owner);
- GQuark quark_data, quark_size;
+ for (struct prop_location *p = property_change_wait_list; p; p = p->next)
+ if (p->display == display && p->window == window)
+ return true;
+ return false;
+}
+
+/* Add an entry to the list of property changes we are waiting for.
+ DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for.
+ The return value is a number that uniquely identifies
+ this awaited property change. */
- selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data,
- &quark_size);
+/* Currently unused -- uncomment later if we decide to implement INCR
+ transfer for X. */
+
+#if 0
- g_object_set_qdata (obj, quark_data, NULL);
- g_object_set_qdata (obj, quark_size, 0);
+static struct prop_location *
+expect_property_change (GdkDisplay *display, GdkWindow *window,
+ GdkAtom property, int state)
+{
+ struct prop_location *pl = xmalloc (sizeof *pl);
+ pl->identifier = ++prop_location_identifier;
+ pl->display = display;
+ pl->window = window;
+ pl->property = property;
+ pl->desired_state = state;
+ pl->next = property_change_wait_list;
+ pl->arrived = false;
+ property_change_wait_list = pl;
+ return pl;
}
+#endif
+
+/* Delete an entry from the list of property changes we are waiting for.
+ IDENTIFIER is the number that uniquely identifies the entry. */
-/* ==========================================================================
+static void
+unexpect_property_change (struct prop_location *location)
+{
+ struct prop_location *prop, **pprev = &property_change_wait_list;
- Functions used externally
+ for (prop = property_change_wait_list; prop; prop = *pprev)
+ {
+ if (prop == location)
+ {
+ *pprev = prop->next;
+ xfree (prop);
+ break;
+ }
+ else
+ pprev = &prop->next;
+ }
+}
- ========================================================================== */
+/* Remove the property change expectation element for IDENTIFIER. */
-void
-pgtk_selection_init (void)
+static void
+wait_for_property_change_unwind (void *loc)
{
- if (quark_primary_data == 0)
+ struct prop_location *location = loc;
+
+ unexpect_property_change (location);
+ if (location == property_change_reply_object)
+ property_change_reply_object = 0;
+}
+
+/* Actually wait for a property change.
+ IDENTIFIER should be the value that expect_property_change returned. */
+
+static void
+wait_for_property_change (struct prop_location *location)
+{
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ /* Make sure to do unexpect_property_change if we quit or err. */
+ record_unwind_protect_ptr (wait_for_property_change_unwind, location);
+
+ /* See comment in x_reply_selection_request about setting
+ property_change_reply. Do not do it here. */
+
+ /* If the event we are waiting for arrives beyond here, it will set
+ property_change_reply, because property_change_reply_object says so. */
+ if (! location->arrived)
{
- quark_primary_data = g_quark_from_static_string ("pgtk-primary-data");
- quark_primary_size = g_quark_from_static_string ("pgtk-primary-size");
- quark_secondary_data =
- g_quark_from_static_string ("pgtk-secondary-data");
- quark_secondary_size =
- g_quark_from_static_string ("pgtk-secondary-size");
- quark_clipboard_data =
- g_quark_from_static_string ("pgtk-clipboard-data");
- quark_clipboard_size =
- g_quark_from_static_string ("pgtk-clipboard-size");
+ intmax_t timeout = max (0, pgtk_selection_timeout);
+ intmax_t secs = timeout / 1000;
+ int nsecs = (timeout % 1000) * 1000000;
+
+ wait_reading_process_output (secs, nsecs, 0, false,
+ property_change_reply, NULL, 0);
+
+ if (NILP (XCAR (property_change_reply)))
+ error ("Timed out waiting for property-notify event");
}
+
+ unbind_to (count, Qnil);
}
+/* Called from the big filter in response to a PropertyNotify
+ event. */
+
void
-pgtk_selection_lost (GtkWidget * widget, GdkEventSelection * event,
- gpointer user_data)
+pgtk_handle_property_notify (GdkEventProperty *event)
{
- GQuark quark_data, quark_size;
+ struct prop_location *rest;
+ GdkDisplay *dpy;
- selection_type_to_quarks (event->selection, &quark_data, &quark_size);
+ dpy = gdk_window_get_display (event->window);
- g_object_set_qdata (G_OBJECT (widget), quark_data, NULL);
- g_object_set_qdata (G_OBJECT (widget), quark_size, 0);
+ for (rest = property_change_wait_list; rest; rest = rest->next)
+ {
+ if (!rest->arrived
+ && rest->property == event->atom
+ && rest->window == event->window
+ && rest->display == dpy
+ && rest->desired_state == event->state)
+ {
+ rest->arrived = true;
+
+ /* If this is the one wait_for_property_change is waiting for,
+ tell it to wake up. */
+ if (rest == property_change_reply_object)
+ XSETCAR (property_change_reply, Qt);
+
+ return;
+ }
+ }
}
-static bool
-pgtk_selection_usable (void)
-{
- if (pgtk_enable_selection_on_multi_display)
- return true;
-
- /*
- * https://github.com/GNOME/gtk/blob/gtk-3-24/gdk/wayland/gdkselection-wayland.c#L1033
- *
- * Gdk uses gdk_display_get_default() when handling selections, so
- * selections don't work properly on multi-display environment.
- *
- * ----------------
- * #include <gtk/gtk.h>
- *
- * static GtkWidget *top1, *top2;
- *
- * int main (int argc, char **argv)
- * {
- * GtkWidget *w;
- * GtkTextBuffer *buf;
- *
- * gtk_init (&argc, &argv);
- *
- * static char *text = "\
- * It is fine today.\n\
- * It will be fine tomorrow too.\n\
- * It is too hot.";
- *
- * top1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- * gtk_window_set_title (GTK_WINDOW (top1), "default");
- * gtk_widget_show (top1);
- * w = gtk_text_view_new ();
- * gtk_container_add (GTK_CONTAINER (top1), w);
- * gtk_widget_show (w);
- * buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w));
- * gtk_text_buffer_insert_at_cursor (buf, text, strlen (text));
- * gtk_text_buffer_add_selection_clipboard (buf, gtk_widget_get_clipboard (w, GDK_SELECTION_PRIMARY));
- *
- * unsetenv ("GDK_BACKEND");
- * GdkDisplay *gdpy;
- * const char *dpyname2;
- * if (strcmp (G_OBJECT_TYPE_NAME (gtk_widget_get_window (top1)), "GdkWaylandWindow") == 0)
- * dpyname2 = ":0";
- * else
- * dpyname2 = "wayland-0";
- * gdpy = gdk_display_open (dpyname2);
- * top2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- * gtk_window_set_title (GTK_WINDOW (top2), dpyname2);
- * gtk_window_set_screen (GTK_WINDOW (top2), gdk_display_get_default_screen (gdpy));
- * gtk_widget_show (top2);
- * w = gtk_text_view_new ();
- * gtk_container_add (GTK_CONTAINER (top2), w);
- * gtk_widget_show (w);
- * buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w));
- * gtk_text_buffer_insert_at_cursor (buf, text, strlen (text));
- * gtk_text_buffer_add_selection_clipboard (buf, gtk_widget_get_clipboard (w, GDK_SELECTION_PRIMARY));
- *
- * gtk_main ();
- *
- * return 0;
- * }
- * ----------------
- *
- * This code fails if
- * GDK_BACKEND=x11 ./test
- * and select on both of windows.
- *
- * ----------------
- * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.041: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
- *
- * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.042: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
- *
- * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
- *
- * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
- * ----------------
- * (gtk-3.24.10)
- *
- * This function checks whether selections work by the number of displays.
- * If you use more than 2 displays, then selection is disabled.
- */
+static void
+pgtk_display_selection_waiting_message (struct atimer *timer)
+{
+ Lisp_Object val;
- GdkDisplayManager *dpyman = gdk_display_manager_get ();
- GSList *list = gdk_display_manager_list_displays (dpyman);
- int len = g_slist_length (list);
- g_slist_free (list);
- return len < 2;
+ val = build_string ("Waiting for reply from selection owner...");
+ message3_nolog (val);
}
-/* ==========================================================================
+static void
+pgtk_cancel_atimer (void *atimer)
+{
+ cancel_atimer (atimer);
+}
- Lisp Defuns
+
+/* Variables for communication with pgtk_handle_selection_notify. */
+static GdkAtom reading_which_selection;
+static Lisp_Object reading_selection_reply;
+static GdkWindow *reading_selection_window;
- ========================================================================== */
+/* Do protocol to read selection-data from the window server.
+ Converts this to Lisp data and returns it.
+ FRAME is the frame whose window shall request the selection. */
+static Lisp_Object
+pgtk_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
+ Lisp_Object time_stamp, Lisp_Object frame)
+{
+ struct frame *f = XFRAME (frame);
+ struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ GdkWindow *requestor_window = FRAME_GDK_WINDOW (f);
+ guint32 requestor_time = dpyinfo->last_user_time;
+ GdkAtom selection_atom = symbol_to_gdk_atom (selection_symbol);
+ GdkAtom type_atom = (CONSP (target_type)
+ ? symbol_to_gdk_atom (XCAR (target_type))
+ : symbol_to_gdk_atom (target_type));
+ struct atimer *delayed_message;
+ struct timespec message_interval;
+ specpdl_ref count;
+
+ count = SPECPDL_INDEX ();
+
+ if (!FRAME_LIVE_P (f))
+ return unbind_to (count, Qnil);
+
+ if (!NILP (time_stamp))
+ CONS_TO_INTEGER (time_stamp, guint32, requestor_time);
+
+ block_input ();
+ /* Prepare to block until the reply has been read. */
+ reading_selection_window = requestor_window;
+ reading_which_selection = selection_atom;
+ XSETCAR (reading_selection_reply, Qnil);
+
+ gdk_selection_convert (requestor_window, selection_atom,
+ type_atom, requestor_time);
+ unblock_input ();
+
+ /* It should not be necessary to stop handling selection requests
+ during this time. In fact, the SAVE_TARGETS mechanism requires
+ us to handle a clipboard manager's requests before it returns
+ GDK_SELECTION_NOTIFY. */
+
+ message_interval = make_timespec (1, 0);
+ delayed_message = start_atimer (ATIMER_RELATIVE, message_interval,
+ pgtk_display_selection_waiting_message,
+ NULL);
+ record_unwind_protect_ptr (pgtk_cancel_atimer, delayed_message);
+
+ /* This allows quits. Also, don't wait forever. */
+ intmax_t timeout = max (0, pgtk_selection_timeout);
+ intmax_t secs = timeout / 1000;
+ int nsecs = (timeout % 1000) * 1000000;
+
+ wait_reading_process_output (secs, nsecs, 0, false,
+ reading_selection_reply, NULL, 0);
+
+ if (NILP (XCAR (reading_selection_reply)))
+ error ("Timed out waiting for reply from selection owner");
+ if (EQ (XCAR (reading_selection_reply), Qlambda))
+ return unbind_to (count, Qnil);
+
+ /* Otherwise, the selection is waiting for us on the requested property. */
+ return unbind_to (count,
+ pgtk_get_window_property_as_lisp_data (dpyinfo,
+ requestor_window,
+ GDK_NONE,
+ target_type,
+ selection_atom,
+ false));
+}
-DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, Spgtk_own_selection_internal, 2, 3, 0,
- doc: /* Assert an X selection of type SELECTION and value VALUE.
-SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
-\(Those are literal upper-case symbol names, since that's what X expects.)
-VALUE is typically a string, or a cons of two markers, but may be
-anything that the functions on `selection-converter-alist' know about.
+/* Subroutines of pgtk_get_window_property_as_lisp_data */
-FRAME should be a frame that should own the selection. If omitted or
-nil, it defaults to the selected frame. */)
- (Lisp_Object selection, Lisp_Object value, Lisp_Object frame)
+static ptrdiff_t
+pgtk_size_for_format (gint format)
{
- Lisp_Object successful_p = Qnil;
- Lisp_Object target_symbol, rest;
- GtkClipboard *cb;
- struct frame *f;
- GQuark quark_data, quark_size;
+ switch (format)
+ {
+ case 8:
+ return sizeof (unsigned char);
+ case 16:
+ return sizeof (unsigned short);
+ case 32:
+ return sizeof (unsigned long);
+
+ default:
+ emacs_abort ();
+ }
+}
- check_window_system (NULL);
+/* Use xfree, not g_free, to free the data obtained with this function. */
- if (!pgtk_selection_usable ())
- return Qnil;
+static void
+pgtk_get_window_property (GdkWindow *window, unsigned char **data_ret,
+ ptrdiff_t *bytes_ret, GdkAtom *actual_type_ret,
+ int *actual_format_ret, unsigned long *actual_size_ret)
+{
+ gint length, actual_format;
+ unsigned char *data;
+ ptrdiff_t element_size;
+ void *xdata;
+ GdkAtom actual_type;
+ unsigned long i;
+ unsigned int *idata;
+ unsigned long *ldata;
+
+ data = NULL;
+
+ length = gdk_selection_property_get (window, &data,
+ &actual_type,
+ &actual_format);
+
+ if (!data)
+ {
+ *data_ret = NULL;
+ *actual_type_ret = GDK_NONE;
+ *bytes_ret = 0;
+ *actual_format_ret = 8;
+ *actual_size_ret = 0;
- if (NILP (frame))
- frame = selected_frame;
- if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame)))
- error ("pgtk selection unavailable for this frame");
- f = XFRAME (frame);
+ return;
+ }
+
+ if (actual_type == GDK_SELECTION_TYPE_ATOM
+ || actual_type == gdk_atom_intern_static_string ("ATOM_PAIR"))
+ {
+ /* GDK should not allow anything else. */
+ eassert (actual_format == 32);
+
+ length = length / sizeof (GdkAtom);
+ xdata = xmalloc (sizeof (GdkAtom) * length + 1);
+ memcpy (xdata, data, 1 + length * sizeof (GdkAtom));
+
+ g_free (data);
+
+ *data_ret = xdata;
+ *actual_type_ret = actual_type;
+ *bytes_ret = length * sizeof (GdkAtom);
+ *actual_format_ret = 32;
+ *actual_size_ret = length;
- cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection);
- selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data,
- &quark_size);
+ return;
+ }
+
+ element_size = pgtk_size_for_format (actual_format);
+ length = length / element_size;
- /* We only support copy of text. */
- target_symbol = QTEXT;
- if (STRINGP (value))
+ /* Add an extra byte on the end. GDK guarantees that it is
+ NULL. */
+ xdata = xmalloc (1 + element_size * length);
+ memcpy (xdata, data, 1 + element_size * length);
+
+ if (actual_format == 32 && LONG_WIDTH > 32)
{
- GtkTargetList *list;
- GtkTargetEntry *targets;
- gint n_targets;
- GtkWidget *widget;
+ ldata = (typeof (ldata)) data;
+ idata = xdata;
- list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_text_targets (list, 0);
+ for (i = 0; i < length; ++i)
+ idata[i] = ldata[i];
- {
- /* text/plain: Strings encoded by Gtk are not correctly decoded by Chromium(Wayland). */
- GdkAtom atom_text_plain = gdk_atom_intern ("text/plain", false);
- gtk_target_list_remove (list, atom_text_plain);
- }
+ /* There is always enough space in idata. */
+ idata[length] = 0;
+ *bytes_ret = sizeof *idata * length;
+ }
+ else
+ /* I think GDK itself prevents element_size from exceeding the
+ length at which this computation fails. */
+ *bytes_ret = element_size * length;
+
+ /* Now free the original `data' allocated by GDK. */
+ g_free (data);
+
+ *data_ret = xdata;
+ *actual_type_ret = GDK_NONE;
+ *actual_size_ret = length;
+ *actual_format_ret = actual_format;
+ *actual_type_ret = actual_type;
+}
- targets = gtk_target_table_new_from_list (list, &n_targets);
+static Lisp_Object
+pgtk_get_window_property_as_lisp_data (struct pgtk_display_info *dpyinfo,
+ GdkWindow *window, GdkAtom property,
+ Lisp_Object target_type, GdkAtom selection_atom,
+ bool for_multiple)
+{
+ GdkAtom actual_type;
+ int actual_format;
+ unsigned long actual_size;
+ unsigned char *data = 0;
+ ptrdiff_t bytes = 0;
+ Lisp_Object val;
+ GdkDisplay *display = dpyinfo->display;
+
+ pgtk_get_window_property (window, &data, &bytes,
+ &actual_type, &actual_format,
+ &actual_size);
+
+ if (!data)
+ {
+ if (for_multiple)
+ return Qnil;
- int size = SBYTES (value);
- gchar *str = xmalloc (size + 1);
- memcpy (str, SSDATA (value), size);
- str[size] = '\0';
+ if (gdk_selection_owner_get_for_display (display, selection_atom))
+ {
+ AUTO_STRING (format, "Selection owner couldn't convert: %s");
+ CALLN (Fmessage, format,
+ actual_type
+ ? list2 (target_type,
+ gdk_atom_to_symbol (actual_type))
+ : target_type);
+ return Qnil;
+ }
+ else
+ {
+ AUTO_STRING (format, "No selection: %s");
+ CALLN (Fmessage, format,
+ gdk_atom_to_symbol (selection_atom));
+ return Qnil;
+ }
+ }
+
+ if (!for_multiple && property != GDK_NONE)
+ gdk_property_delete (window, property);
+
+ /* It's been read. Now convert it to a lisp object in some semi-rational
+ manner. */
+ val = selection_data_to_lisp_data (dpyinfo, data, bytes,
+ actual_type, actual_format);
+
+ /* Use xfree, not g_free, because pgtk_get_window_property calls
+ xmalloc itself. */
+ xfree (data);
+ return val;
+}
- widget = FRAME_GTK_WIDGET (f);
- g_object_set_qdata_full (G_OBJECT (widget), quark_data, str, xfree);
- g_object_set_qdata_full (G_OBJECT (widget), quark_size,
- GSIZE_TO_POINTER (size), NULL);
+
+
+/* These functions convert from the selection data read from the
+ server into something that we can use from Lisp, and vice versa.
+
+ Type: Format: Size: Lisp Type:
+ ----- ------- ----- -----------
+ * 8 * String
+ ATOM 32 1 Symbol
+ ATOM 32 > 1 Vector of Symbols
+ * 16 1 Integer
+ * 16 > 1 Vector of Integers
+ * 32 1 if small enough: fixnum
+ otherwise: bignum
+ * 32 > 1 Vector of the above
+
+ When converting an object to C, it may be of the form (SYMBOL
+ . <data>) where SYMBOL is what we should claim that the type is.
+ Format and representation are as above.
+
+ Important: When format is 32, data should contain an array of int,
+ not an array of long as GDK returns. Unless TYPE is also
+ GDK_SELECTION_TYPE_ATOM, in which case data should be an array of
+ GdkAtom. This makes a difference when sizeof (long) != sizeof
+ (int). */
+
+static Lisp_Object
+selection_data_to_lisp_data (struct pgtk_display_info *dpyinfo,
+ const unsigned char *data,
+ ptrdiff_t size, GdkAtom type, int format)
+{
+ if (type == gdk_atom_intern_static_string ("NULL"))
+ return QNULL;
+ /* Convert any 8-bit data to a string, for compactness. */
+ else if (format == 8)
+ {
+ Lisp_Object str, lispy_type;
- if (gtk_clipboard_set_with_owner (cb,
- targets, n_targets,
- get_func, clear_func,
- G_OBJECT (FRAME_GTK_WIDGET (f))))
+ str = make_unibyte_string ((char *) data, size);
+ /* Indicate that this string is from foreign selection by a text
+ property `foreign-selection' so that the caller of
+ x-get-selection-internal (usually x-get-selection) can know
+ that the string must be decode. */
+ if (type == gdk_atom_intern_static_string ("COMPOUND_TEXT"))
+ lispy_type = QCOMPOUND_TEXT;
+ else if (type == gdk_atom_intern_static_string ("UTF8_STRING"))
+ lispy_type = QUTF8_STRING;
+ else
+ lispy_type = QSTRING;
+
+ Fput_text_property (make_fixnum (0), make_fixnum (size),
+ Qforeign_selection, lispy_type, str);
+ return str;
+ }
+ /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to
+ a vector of symbols. */
+ else if (format == 32
+ && (type == GDK_SELECTION_TYPE_ATOM
+ /* Treat ATOM_PAIR type similar to list of atoms. */
+ || type == gdk_atom_intern_static_string ("ATOM_PAIR")))
+ {
+ ptrdiff_t i;
+ GdkAtom *idata = (GdkAtom *) data;
+
+ if (size == sizeof (GdkAtom))
+ return gdk_atom_to_symbol (idata[0]);
+ else
{
- successful_p = Qt;
+ Lisp_Object v = make_nil_vector (size / sizeof (GdkAtom));
+
+ for (i = 0; i < size / sizeof (GdkAtom); i++)
+ ASET (v, i, gdk_atom_to_symbol (idata[i]));
+ return v;
}
- gtk_clipboard_set_can_store (cb, NULL, 0);
+ }
+
+ /* Convert a single 16-bit number or a small 32-bit number to a Lisp_Int.
+ If the number is 32 bits and won't fit in a Lisp_Int, convert it
+ to a bignum.
+
+ INTEGER is a signed type, CARDINAL is unsigned.
+ Assume any other types are unsigned as well.
+ */
+ else if (format == 32 && size == sizeof (int))
+ {
+ if (type == GDK_SELECTION_TYPE_INTEGER)
+ return INT_TO_INTEGER (((int *) data) [0]);
+ else
+ return INT_TO_INTEGER (((unsigned int *) data) [0]);
+ }
+ else if (format == 16 && size == sizeof (short))
+ {
+ if (type == GDK_SELECTION_TYPE_INTEGER)
+ return make_fixnum (((short *) data) [0]);
+ else
+ return make_fixnum (((unsigned short *) data) [0]);
+ }
+ /* Convert any other kind of data to a vector of numbers, represented
+ as above (as an integer, or a cons of two 16 bit integers.)
+ */
+ else if (format == 16)
+ {
+ ptrdiff_t i;
+ Lisp_Object v = make_uninit_vector (size / 2);
+
+ if (type == GDK_SELECTION_TYPE_INTEGER)
+ {
+ for (i = 0; i < size / 2; i++)
+ {
+ short j = ((short *) data) [i];
+ ASET (v, i, make_fixnum (j));
+ }
+ }
+ else
+ {
+ for (i = 0; i < size / 2; i++)
+ {
+ unsigned short j = ((unsigned short *) data) [i];
+ ASET (v, i, make_fixnum (j));
+ }
+ }
+ return v;
+ }
+ else
+ {
+ ptrdiff_t i;
+ Lisp_Object v = make_nil_vector (size / sizeof (gint));
+
+ if (type == GDK_SELECTION_TYPE_INTEGER)
+ {
+ for (i = 0; i < size / sizeof (gint); i++)
+ {
+ int j = ((gint *) data) [i];
+ ASET (v, i, INT_TO_INTEGER (j));
+ }
+ }
+ else
+ {
+ for (i = 0; i < size / sizeof (gint); i++)
+ {
+ unsigned int j = ((unsigned int *) data) [i];
+ ASET (v, i, INT_TO_INTEGER (j));
+ }
+ }
+ return v;
+ }
+}
+
+/* Convert OBJ to an X long value, and return it as unsigned long.
+ OBJ should be an integer or a cons representing an integer.
+ Treat values in the range X_LONG_MAX + 1 .. X_ULONG_MAX as X
+ unsigned long values: in theory these values are supposed to be
+ signed but in practice unsigned 32-bit data are communicated via X
+ selections and we need to support that. */
+static unsigned long
+cons_to_gdk_long (Lisp_Object obj)
+{
+ if (G_MAXUINT32 <= INTMAX_MAX
+ || NILP (Fnatnump (CONSP (obj) ? XCAR (obj) : obj)))
+ return cons_to_signed (obj, 0, min (G_MAXUINT32, INTMAX_MAX));
+ else
+ return cons_to_unsigned (obj, G_MAXUINT32);
+}
+
+/* Use xfree, not XFree, to free the data obtained with this function. */
+
+static void
+lisp_data_to_selection_data (struct pgtk_display_info *dpyinfo,
+ Lisp_Object obj, struct selection_data *cs)
+{
+ Lisp_Object type = Qnil;
+
+ eassert (cs != NULL);
+ cs->nofree = false;
- gtk_target_table_free (targets, n_targets);
- gtk_target_list_unref (list);
+ if (CONSP (obj) && SYMBOLP (XCAR (obj)))
+ {
+ type = XCAR (obj);
+ obj = XCDR (obj);
+ if (CONSP (obj) && NILP (XCDR (obj)))
+ obj = XCAR (obj);
}
- if (!EQ (Vpgtk_sent_selection_hooks, Qunbound))
+ if (EQ (obj, QNULL) || (EQ (type, QNULL)))
+ { /* This is not the same as declining */
+ cs->format = 32;
+ cs->size = 0;
+ cs->data = NULL;
+ type = QNULL;
+ }
+ else if (STRINGP (obj))
+ {
+ if (SCHARS (obj) < SBYTES (obj))
+ /* OBJ is a multibyte string containing a non-ASCII char. */
+ signal_error ("Non-ASCII string must be encoded in advance", obj);
+ if (NILP (type))
+ type = QSTRING;
+ cs->format = 8;
+ cs->size = SBYTES (obj);
+ cs->data = SDATA (obj);
+ cs->nofree = true;
+ }
+ else if (SYMBOLP (obj))
{
- /* FIXME: Use run-hook-with-args! */
- for (rest = Vpgtk_sent_selection_hooks; CONSP (rest);
- rest = Fcdr (rest))
- call3 (Fcar (rest), selection, target_symbol, successful_p);
+ void *data = xmalloc (sizeof (GdkAtom) + 1);
+ GdkAtom *x_atom_ptr = data;
+ cs->data = data;
+ cs->format = 32;
+ cs->size = 1;
+ cs->data[sizeof (GdkAtom)] = 0;
+ *x_atom_ptr = symbol_to_gdk_atom (obj);
+ if (NILP (type)) type = QATOM;
}
+ else if (RANGED_FIXNUMP (SHRT_MIN, obj, SHRT_MAX))
+ {
+ void *data = xmalloc (sizeof (short) + 1);
+ short *short_ptr = data;
+ cs->data = data;
+ cs->format = 16;
+ cs->size = 1;
+ cs->data[sizeof (short)] = 0;
+ *short_ptr = XFIXNUM (obj);
+ if (NILP (type)) type = QINTEGER;
+ }
+ else if (INTEGERP (obj)
+ || (CONSP (obj) && INTEGERP (XCAR (obj))
+ && (FIXNUMP (XCDR (obj))
+ || (CONSP (XCDR (obj))
+ && FIXNUMP (XCAR (XCDR (obj)))))))
+ {
+ void *data = xmalloc (sizeof (unsigned long) + 1);
+ unsigned long *x_long_ptr = data;
+ cs->data = data;
+ cs->format = 32;
+ cs->size = 1;
+ cs->data[sizeof (unsigned long)] = 0;
+ *x_long_ptr = cons_to_gdk_long (obj);
+ if (NILP (type)) type = QINTEGER;
+ }
+ else if (VECTORP (obj))
+ {
+ /* Lisp_Vectors may represent a set of ATOMs;
+ a set of 16 or 32 bit INTEGERs;
+ or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
+ */
+ ptrdiff_t i;
+ ptrdiff_t size = ASIZE (obj);
+
+ if (SYMBOLP (AREF (obj, 0)))
+ /* This vector is an ATOM set */
+ {
+ void *data;
+ GdkAtom *x_atoms;
+ if (NILP (type)) type = QATOM;
+ for (i = 0; i < size; i++)
+ if (!SYMBOLP (AREF (obj, i)))
+ signal_error ("All elements of selection vector must have same type", obj);
+
+ cs->data = data = xnmalloc (size, sizeof *x_atoms);
+ x_atoms = data;
+ cs->format = 32;
+ cs->size = size;
+ for (i = 0; i < size; i++)
+ x_atoms[i] = symbol_to_gdk_atom (AREF (obj, i));
+ }
+ else
+ /* This vector is an INTEGER set, or something like it */
+ {
+ int format = 16;
+ int data_size = sizeof (short);
+ void *data;
+ unsigned long *x_atoms;
+ short *shorts;
+ if (NILP (type)) type = QINTEGER;
+ for (i = 0; i < size; i++)
+ {
+ if (! RANGED_FIXNUMP (SHRT_MIN, AREF (obj, i), SHRT_MAX))
+ {
+ /* Use sizeof (long) even if it is more than 32 bits.
+ See comment in x_get_window_property and
+ x_fill_property_data. */
+ data_size = sizeof (long);
+ format = 32;
+ break;
+ }
+ }
+ cs->data = data = xnmalloc (size, data_size);
+ x_atoms = data;
+ shorts = data;
+ cs->format = format;
+ cs->size = size;
+ for (i = 0; i < size; i++)
+ {
+ if (format == 32)
+ x_atoms[i] = cons_to_gdk_long (AREF (obj, i));
+ else
+ shorts[i] = XFIXNUM (AREF (obj, i));
+ }
+ }
+ }
+ else
+ signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
+
+ cs->type = symbol_to_gdk_atom (type);
+}
+static Lisp_Object
+clean_local_selection_data (Lisp_Object obj)
+{
+ if (CONSP (obj)
+ && INTEGERP (XCAR (obj))
+ && CONSP (XCDR (obj))
+ && FIXNUMP (XCAR (XCDR (obj)))
+ && NILP (XCDR (XCDR (obj))))
+ obj = Fcons (XCAR (obj), XCDR (obj));
+
+ if (CONSP (obj)
+ && INTEGERP (XCAR (obj))
+ && FIXNUMP (XCDR (obj)))
+ {
+ if (BASE_EQ (XCAR (obj), make_fixnum (0)))
+ return XCDR (obj);
+ if (BASE_EQ (XCAR (obj), make_fixnum (-1)))
+ return make_fixnum (- XFIXNUM (XCDR (obj)));
+ }
+ if (VECTORP (obj))
+ {
+ ptrdiff_t i;
+ ptrdiff_t size = ASIZE (obj);
+ Lisp_Object copy;
+ if (size == 1)
+ return clean_local_selection_data (AREF (obj, 0));
+ copy = make_nil_vector (size);
+ for (i = 0; i < size; i++)
+ ASET (copy, i, clean_local_selection_data (AREF (obj, i)));
+ return copy;
+ }
+ return obj;
+}
+
+DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal,
+ Spgtk_own_selection_internal, 2, 3, 0,
+ doc: /* Assert a selection of type SELECTION and value VALUE.
+SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
+\(Those are literal upper-case symbol names, since that's what GDK expects.)
+VALUE is typically a string, or a cons of two markers, but may be
+anything that the functions on `selection-converter-alist' know about.
+
+FRAME should be a frame that should own the selection. If omitted or
+nil, it defaults to the selected frame. */)
+ (Lisp_Object selection, Lisp_Object value, Lisp_Object frame)
+{
+ if (NILP (frame)) frame = selected_frame;
+ if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame)))
+ error ("GDK selection unavailable for this frame");
+
+ CHECK_SYMBOL (selection);
+ if (NILP (value)) error ("VALUE may not be nil");
+ pgtk_own_selection (selection, value, frame);
return value;
}
+/* Request the selection value from the owner. If we are the owner,
+ simply return our selection value. If we are not the owner, this
+ will block until all of the data has arrived. */
-DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, Spgtk_disown_selection_internal, 1, 3, 0,
- doc: /* If we own the selection SELECTION, disown it.
-Disowning it means there is no such selection.
+DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal,
+ Spgtk_get_selection_internal, 2, 4, 0,
+ doc: /* Return text selected from some X window.
+SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
+\(Those are literal upper-case symbol names, since that's what X expects.)
+TARGET-TYPE is the type of data desired, typically `STRING'.
-Sets the last-change time for the selection to TIME-OBJECT (by default
-the time of the last event).
+TIME-STAMP is the time to use in the XConvertSelection call for foreign
+selections. If omitted, defaults to the time for the last event.
TERMINAL should be a terminal object or a frame specifying the X
server to query. If omitted or nil, that stands for the selected
-frame's display, or the first available X display.
-
-On Nextstep, the TIME-OBJECT and TERMINAL arguments are unused.
-On MS-DOS, all this does is return non-nil if we own the selection.
-On PGTK, the TIME-OBJECT is unused. */)
- (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal)
+frame's display, or the first available X display. */)
+ (Lisp_Object selection_symbol, Lisp_Object target_type,
+ Lisp_Object time_stamp, Lisp_Object terminal)
{
+ Lisp_Object val = Qnil;
+ Lisp_Object maybe_alias;
struct frame *f = frame_for_pgtk_selection (terminal);
- GtkClipboard *cb;
- if (!pgtk_selection_usable ())
- return Qnil;
+ CHECK_SYMBOL (selection_symbol);
+ CHECK_SYMBOL (target_type);
+ if (EQ (target_type, QMULTIPLE))
+ error ("Retrieving MULTIPLE selections is currently unimplemented");
if (!f)
- return Qnil;
+ error ("GDK selection unavailable for this frame");
+
+ /* Quitting inside this function is okay, so we don't have to use
+ FOR_EACH_TAIL_SAFE. */
+ maybe_alias = Fassq (selection_symbol, Vpgtk_selection_alias_alist);
- cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection);
+ if (!NILP (maybe_alias))
+ {
+ selection_symbol = XCDR (maybe_alias);
+ CHECK_SYMBOL (selection_symbol);
+ }
- gtk_clipboard_clear (cb);
+ val = pgtk_get_local_selection (selection_symbol, target_type, true,
+ FRAME_DISPLAY_INFO (f));
- return Qt;
+ if (NILP (val) && FRAME_LIVE_P (f))
+ {
+ Lisp_Object frame;
+ XSETFRAME (frame, f);
+ return pgtk_get_foreign_selection (selection_symbol, target_type,
+ time_stamp, frame);
+ }
+
+ if (CONSP (val) && SYMBOLP (XCAR (val)))
+ {
+ val = XCDR (val);
+ if (CONSP (val) && NILP (XCDR (val)))
+ val = XCAR (val);
+ }
+ return clean_local_selection_data (val);
}
+DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal,
+ Spgtk_disown_selection_internal, 1, 3, 0,
+ doc: /* If we own the selection SELECTION, disown it.
+Disowning it means there is no such selection.
-DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, 0, 2, 0,
- doc: /* Whether there is an owner for the given X selection.
-SELECTION should be the name of the selection in question, typically
-one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects
-these literal upper-case names.) The symbol nil is the same as
-`PRIMARY', and t is the same as `SECONDARY'.
+Sets the last-change time for the selection to TIME-OBJECT (by default
+the time of the last event).
TERMINAL should be a terminal object or a frame specifying the X
server to query. If omitted or nil, that stands for the selected
-frame's display, or the first available X display.
-
-On Nextstep, TERMINAL is unused. */)
- (Lisp_Object selection, Lisp_Object terminal)
+frame's display, or the first available X display. */)
+ (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal)
{
+ guint32 timestamp;
+ GdkAtom selection_atom;
struct frame *f = frame_for_pgtk_selection (terminal);
- GtkClipboard *cb;
+ struct pgtk_display_info *dpyinfo;
- if (!pgtk_selection_usable ())
+ if (!f)
return Qnil;
- if (!f)
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+ CHECK_SYMBOL (selection);
+
+ /* Don't disown the selection when we're not the owner. */
+ if (NILP (LOCAL_SELECTION (selection, dpyinfo)))
return Qnil;
- cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection);
+ selection_atom = symbol_to_gdk_atom (selection);
- return gtk_clipboard_wait_is_text_available (cb) ? Qt : Qnil;
-}
+ block_input ();
+ if (NILP (time_object))
+ timestamp = dpyinfo->last_user_time;
+ else
+ CONS_TO_INTEGER (time_object, guint32, timestamp);
+ gdk_selection_owner_set_for_display (dpyinfo->display, NULL,
+ selection_atom, timestamp,
+ TRUE);
+ unblock_input ();
+ return Qt;
+}
-DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, 0, 2, 0,
- doc: /* Whether the current Emacs process owns the given X Selection.
+DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p,
+ 0, 2, 0,
+ doc: /* Whether the current Emacs process owns the given selection.
The arg should be the name of the selection in question, typically one of
the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
-\(Those are literal upper-case symbol names, since that's what X expects.)
+\(Those are literal upper-case symbol names, since that's what GDK expects.)
For convenience, the symbol nil is the same as `PRIMARY',
and t is the same as `SECONDARY'.
-TERMINAL should be a terminal object or a frame specifying the X
+TERMINAL should be a terminal object or a frame specifying the GDK
server to query. If omitted or nil, that stands for the selected
-frame's display, or the first available X display.
-
-On Nextstep, TERMINAL is unused. */)
+frame's display, or the first available X display. */)
(Lisp_Object selection, Lisp_Object terminal)
{
struct frame *f = frame_for_pgtk_selection (terminal);
- GtkClipboard *cb;
- GObject *obj;
- GQuark quark_data, quark_size;
- if (!pgtk_selection_usable ())
- return Qnil;
-
- cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection);
- selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data,
- &quark_size);
+ CHECK_SYMBOL (selection);
+ if (NILP (selection)) selection = QPRIMARY;
+ if (EQ (selection, Qt)) selection = QSECONDARY;
- obj = gtk_clipboard_get_owner (cb);
-
- return obj && g_object_get_qdata (obj, quark_data) != NULL ? Qt : Qnil;
+ if (f && !NILP (LOCAL_SELECTION (selection, FRAME_DISPLAY_INFO (f))))
+ return Qt;
+ else
+ return Qnil;
}
+DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p,
+ 0, 2, 0,
+ doc: /* Whether there is an owner for the given selection.
+SELECTION should be the name of the selection in question, typically
+one of the symbols `PRIMARY', `SECONDARY', `CLIPBOARD', or
+`CLIPBOARD_MANAGER' (GDK expects these literal upper-case names.) The
+symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'.
-DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, Spgtk_get_selection_internal, 2, 4, 0,
- doc: /* Return text selected from some X window.
-SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.
-\(Those are literal upper-case symbol names, since that's what X expects.)
-TARGET-TYPE is the type of data desired, typically `STRING'.
-
-TIME-STAMP is the time to use in the XConvertSelection call for foreign
-selections. If omitted, defaults to the time for the last event.
-
-TERMINAL should be a terminal object or a frame specifying the X
+TERMINAL should be a terminal object or a frame specifying the GDK
server to query. If omitted or nil, that stands for the selected
-frame's display, or the first available X display.
-
-On Nextstep, TIME-STAMP and TERMINAL are unused.
-On PGTK, TIME-STAMP is unused. */)
- (Lisp_Object selection_symbol, Lisp_Object target_type,
- Lisp_Object time_stamp, Lisp_Object terminal)
+frame's display, or the first available X display. */)
+ (Lisp_Object selection, Lisp_Object terminal)
{
+ GdkWindow *owner;
+ GdkAtom atom;
struct frame *f = frame_for_pgtk_selection (terminal);
- GtkClipboard *cb;
+ struct pgtk_display_info *dpyinfo;
- CHECK_SYMBOL (selection_symbol);
- CHECK_SYMBOL (target_type);
- if (EQ (target_type, QMULTIPLE))
- error ("Retrieving MULTIPLE selections is currently unimplemented");
- if (!f)
- error ("PGTK selection unavailable for this frame");
+ CHECK_SYMBOL (selection);
+ if (NILP (selection)) selection = QPRIMARY;
+ if (EQ (selection, Qt)) selection = QSECONDARY;
- if (!pgtk_selection_usable ())
+ if (!f)
return Qnil;
- cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection_symbol);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
- GdkAtom target_atom = gdk_atom_intern (SSDATA (SYMBOL_NAME (target_type)), false);
- GtkSelectionData *seldata = gtk_clipboard_wait_for_contents (cb, target_atom);
+ if (!NILP (LOCAL_SELECTION (selection, dpyinfo)))
+ return Qt;
- if (seldata == NULL)
- return Qnil;
+ atom = symbol_to_gdk_atom (selection);
+ if (atom == 0) return Qnil;
+ block_input ();
+ owner = gdk_selection_owner_get_for_display (dpyinfo->display, atom);
+ unblock_input ();
+ return (owner ? Qt : Qnil);
+}
+
+/* Called to handle GDK_SELECTION_NOTIFY events.
+ If it's the selection we are waiting for, stop waiting
+ by setting the car of reading_selection_reply to non-nil.
+ We store t there if the reply is successful, lambda if not. */
- const guchar *sd_data = gtk_selection_data_get_data (seldata);
- int sd_len = gtk_selection_data_get_length (seldata);
- int sd_format = gtk_selection_data_get_format (seldata);
- GdkAtom sd_type = gtk_selection_data_get_data_type (seldata);
+void
+pgtk_handle_selection_notify (GdkEventSelection *event)
+{
+ /* GDK doesn't populate event->requestor, contrary to what the ICCCM
+ says should be done with SelectionNotify events. */
+
+ if (event->selection != reading_which_selection)
+ return;
+
+ XSETCAR (reading_selection_reply,
+ (event->property != GDK_NONE ? Qt : Qlambda));
+}
- if (sd_format == 8)
+
+/***********************************************************************
+ Drag and drop support
+***********************************************************************/
+
+DEFUN ("pgtk-register-dnd-targets", Fpgtk_register_dnd_targets,
+ Spgtk_register_dnd_targets, 2, 2, 0,
+ doc: /* Register TARGETS on FRAME.
+TARGETS should be a list of strings describing data types (selection
+targets) that can be dropped on top of FRAME. */)
+ (Lisp_Object frame, Lisp_Object targets)
+{
+ struct frame *f;
+ GtkTargetEntry *entries;
+ GtkTargetList *list;
+ ptrdiff_t length, n;
+ Lisp_Object tem, t;
+ char *buf;
+ USE_SAFE_ALLOCA;
+
+ f = decode_window_system_frame (frame);
+ CHECK_LIST (targets);
+ length = list_length (targets);
+ n = 0;
+ entries = SAFE_ALLOCA (sizeof *entries * length);
+ memset (entries, 0, sizeof *entries * length);
+ tem = targets;
+
+ FOR_EACH_TAIL (tem)
{
- Lisp_Object str, lispy_type;
+ if (!CONSP (tem))
+ continue;
- str = make_unibyte_string ((char *) sd_data, sd_len);
- /* Indicate that this string is from foreign selection by a text
- property `foreign-selection' so that the caller of
- x-get-selection-internal (usually x-get-selection) can know
- that the string must be decode. */
- if (sd_type == gdk_atom_intern ("COMPOUND_TEXT", false))
- lispy_type = QCOMPOUND_TEXT;
- else if (sd_type == gdk_atom_intern ("UTF8_STRING", false))
- lispy_type = QUTF8_STRING;
- else if (sd_type == gdk_atom_intern ("text/plain;charset=utf-8", false))
- lispy_type = Qtext_plain_charset_utf_8;
- else
- lispy_type = QSTRING;
- Fput_text_property (make_fixnum (0), make_fixnum (sd_len),
- Qforeign_selection, lispy_type, str);
+ t = XCAR (tem);
- gtk_selection_data_free (seldata);
- return str;
+ CHECK_STRING (t);
+ SAFE_ALLOCA_STRING (buf, t);
+
+ entries[n++].target = buf;
}
+ CHECK_LIST_END (tem, targets);
+
+ if (n != length)
+ emacs_abort ();
+
+ list = gtk_target_list_new (entries, n);
+ gtk_drag_dest_set_target_list (FRAME_GTK_WIDGET (f), list);
+ gtk_target_list_unref (list);
+
+ SAFE_FREE ();
- gtk_selection_data_free (seldata);
return Qnil;
}
+DEFUN ("pgtk-drop-finish", Fpgtk_drop_finish, Spgtk_drop_finish, 3, 3, 0,
+ doc: /* Finish the drag-n-drop event that happened at TIMESTAMP.
+SUCCESS is whether or not the drop was successful, i.e. the action
+chosen in the last call to `pgtk-update-drop-status' was performed.
+TIMESTAMP is the time associated with the drag-n-drop event that is
+being finished.
+DELETE is whether or not the action was `move'. */)
+ (Lisp_Object success, Lisp_Object timestamp, Lisp_Object delete)
+{
+ pgtk_finish_drop (success, timestamp, delete);
-void
-nxatoms_of_pgtkselect (void)
+ return Qnil;
+}
+
+DEFUN ("pgtk-update-drop-status", Fpgtk_update_drop_status,
+ Spgtk_update_drop_status, 2, 2, 0,
+ doc: /* Update the status of the current drag-and-drop operation.
+ACTION is the action the drop source should take.
+TIMESTAMP is the same as in `pgtk-drop-finish'. */)
+ (Lisp_Object action, Lisp_Object timestamp)
{
+ pgtk_update_drop_status (action, timestamp);
+
+ return Qnil;
}
void
@@ -592,41 +1872,89 @@ syms_of_pgtkselect (void)
DEFSYM (QSECONDARY, "SECONDARY");
DEFSYM (QTEXT, "TEXT");
DEFSYM (QFILE_NAME, "FILE_NAME");
+ DEFSYM (QSTRING, "STRING");
+ DEFSYM (QINTEGER, "INTEGER");
+ DEFSYM (QTIMESTAMP, "TIMESTAMP");
+ DEFSYM (QTEXT, "TEXT");
DEFSYM (QMULTIPLE, "MULTIPLE");
-
- DEFSYM (Qforeign_selection, "foreign-selection");
+ DEFSYM (QNULL, "NULL");
+ DEFSYM (QATOM, "ATOM");
+ DEFSYM (QTARGETS, "TARGETS");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
- DEFSYM (QSTRING, "STRING");
DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT");
- DEFSYM (Qtext_plain_charset_utf_8, "text/plain;charset=utf-8");
+
+ DEFSYM (Qforeign_selection, "foreign-selection");
+
+ DEFSYM (Qpgtk_sent_selection_functions, "pgtk-sent-selection-functions");
+ DEFSYM (Qpgtk_lost_selection_functions, "pgtk-lost-selection-functions");
defsubr (&Spgtk_disown_selection_internal);
defsubr (&Spgtk_get_selection_internal);
defsubr (&Spgtk_own_selection_internal);
defsubr (&Spgtk_selection_exists_p);
defsubr (&Spgtk_selection_owner_p);
-
-#if 0
- Vselection_alist = Qnil;
- staticpro (&Vselection_alist);
-#endif
+ defsubr (&Spgtk_register_dnd_targets);
+ defsubr (&Spgtk_update_drop_status);
+ defsubr (&Spgtk_drop_finish);
+
+ DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
+ doc: /* SKIP: real doc in xselect.c. */);
+ Vselection_converter_alist = Qnil;
+
+ DEFVAR_LISP ("pgtk-lost-selection-functions", Vpgtk_lost_selection_functions,
+ doc: /* A list of functions to be called when Emacs loses a selection.
+\(This happens when some other client makes its own selection
+or when a Lisp program explicitly clears the selection.)
+The functions are called with one argument, the selection type
+\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */);
+ Vpgtk_lost_selection_functions = Qnil;
+
+ DEFVAR_LISP ("pgtk-sent-selection-functions", Vpgtk_sent_selection_functions,
+ doc: /* A list of functions to be called when Emacs answers a selection request.
+The functions are called with three arguments:
+ - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
+ - the selection-type which Emacs was asked to convert the
+ selection into before sending (for example, `STRING' or `LENGTH');
+ - a flag indicating success or failure for responding to the request.
+We might have failed (and declined the request) for any number of reasons,
+including being asked for a selection that we no longer own, or being asked
+to convert into a type that we don't know about or that is inappropriate.
+xThis hook doesn't let you change the behavior of Emacs's selection replies,
+it merely informs you that they have happened. */);
+ Vpgtk_sent_selection_functions = Qnil;
DEFVAR_LISP ("pgtk-sent-selection-hooks", Vpgtk_sent_selection_hooks,
- "A list of functions to be called when Emacs answers a selection request.\n\
-The functions are called with four arguments:\n\
- - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
- - the selection-type which Emacs was asked to convert the\n\
- selection into before sending (for example, `STRING' or `LENGTH');\n\
- - a flag indicating success or failure for responding to the request.\n\
-We might have failed (and declined the request) for any number of reasons,\n\
-including being asked for a selection that we no longer own, or being asked\n\
-to convert into a type that we don't know about or that is inappropriate.\n\
-This hook doesn't let you change the behavior of Emacs's selection replies,\n\
-it merely informs you that they have happened.");
+ doc: /* A list of functions to be called when Emacs answers a selection request
+The functions are called with four arguments:
+ - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
+ - the selection-type which Emacs was asked to convert the
+ selection into before sending (for example, `STRING' or `LENGTH');
+ - a flag indicating success or failure for responding to the request.
+We might have failed (and declined the request) for any number of reasons,
+including being asked for a selection that we no longer own, or being asked
+to convert into a type that we don't know about or that is inappropriate.
+This hook doesn't let you change the behavior of Emacs's selection replies,
+it merely informs you that they have happened. */);
Vpgtk_sent_selection_hooks = Qnil;
- DEFVAR_BOOL ("pgtk-enable-selection-on-multi-display", pgtk_enable_selection_on_multi_display,
- doc: /* Enable selection on multi display environment.
-This may cause crash. */);
- pgtk_enable_selection_on_multi_display = false;
+ DEFVAR_INT ("pgtk-selection-timeout", pgtk_selection_timeout,
+ doc: /* Number of milliseconds to wait for a selection reply.
+If the selection owner doesn't reply in this time, we give up.
+A value of 0 means wait as long as necessary. */);
+ pgtk_selection_timeout = 0;
+
+ DEFVAR_LISP ("pgtk-selection-alias-alist", Vpgtk_selection_alias_alist,
+ doc: /* List of selections to alias to another.
+It should be an alist of a selection name to another. When a
+selection request arrives for the first selection, Emacs will respond
+as if the request was meant for the other.
+
+Note that this does not affect setting or owning selections. */);
+ Vpgtk_selection_alias_alist = Qnil;
+
+ reading_selection_reply = Fcons (Qnil, Qnil);
+ staticpro (&reading_selection_reply);
+
+ property_change_reply = Fcons (Qnil, Qnil);
+ staticpro (&property_change_reply);
}
diff --git a/src/pgtkselect.h b/src/pgtkselect.h
deleted file mode 100644
index 0509c83bdec..00000000000
--- a/src/pgtkselect.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Definitions and headers for selection of pure Gtk+3.
- Copyright (C) 1989, 1993, 2005, 2008-2022 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 <https://www.gnu.org/licenses/>. */
-
-
-#include "dispextern.h"
-#include "frame.h"
-
-#ifdef HAVE_PGTK
-
-#include <gtk/gtk.h>
-
-extern void pgtk_selection_init (void);
-extern void pgtk_selection_lost (GtkWidget * widget,
- GdkEventSelection * event,
- gpointer user_data);
-
-#endif /* HAVE_PGTK */
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 1d301d11f6f..b283cef7cde 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -1,4 +1,4 @@
-/* Pure Gtk+-3 communication module. -*- coding: utf-8 -*-
+/* Communication module for window systems using GTK.
Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2022 Free Software
Foundation, Inc.
@@ -36,6 +36,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <c-strcase.h>
#include <ftoastr.h>
+#include <dlfcn.h>
+
#include "lisp.h"
#include "blockinput.h"
#include "frame.h"
@@ -47,7 +49,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "fontset.h"
#include "composite.h"
#include "ccl.h"
-#include "dynlib.h"
#include "termhooks.h"
#include "termopts.h"
@@ -60,58 +61,223 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "font.h"
#include "xsettings.h"
-#include "pgtkselect.h"
#include "emacsgtkfixed.h"
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
-#define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
-
-#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context)
+#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context)
#define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active)
-#define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f)))
+#define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f)))
/* Non-zero means that a HELP_EVENT has been generated since Emacs
start. */
static bool any_help_event_p;
-struct pgtk_display_info *x_display_list; /* Chain of existing displays */
-extern Lisp_Object tip_frame;
+/* Chain of existing displays */
+struct pgtk_display_info *x_display_list;
-static struct event_queue_t
+struct event_queue_t
{
union buffered_input_event *q;
int nr, cap;
-} event_q = {
- NULL, 0, 0,
};
+/* A queue of events that will be read by the read_socket_hook. */
+static struct event_queue_t event_q;
+
/* Non-zero timeout value means ignore next mouse click if it arrives
before that timeout elapses (i.e. as part of the same sequence of
events resulting from clicking on a frame to select it). */
-
static Time ignore_next_mouse_click_timeout;
+/* The default Emacs icon . */
static Lisp_Object xg_default_icon_file;
-static void pgtk_delete_display (struct pgtk_display_info *dpyinfo);
-static void pgtk_clear_frame_area (struct frame *f, int x, int y, int width,
- int height);
-static void pgtk_fill_rectangle (struct frame *f, unsigned long color, int x,
- int y, int width, int height);
-static void pgtk_clip_to_row (struct window *w, struct glyph_row *row,
- enum glyph_row_area area, cairo_t * cr);
-static struct frame *pgtk_any_window_to_frame (GdkWindow * window);
-
-/*
- * This is not a flip context in the same sense as gpu rendering
- * scences, it only occurs when a new context was required due to a
- * resize or other fundamental change. This is called when that
- * context's surface has completed drawing
- */
+/* The current GdkDragContext of a drop. */
+static GdkDragContext *current_drop_context;
+
+/* Whether or not current_drop_context was set from a drop
+ handler. */
+static bool current_drop_context_drop;
+
+/* The time of the last drop. */
+static guint32 current_drop_time;
+
+static void pgtk_delete_display (struct pgtk_display_info *);
+static void pgtk_clear_frame_area (struct frame *, int, int, int, int);
+static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int,
+ int, int, bool);
+static void pgtk_clip_to_row (struct window *, struct glyph_row *,
+ enum glyph_row_area, cairo_t *);
+static struct frame *pgtk_any_window_to_frame (GdkWindow *);
+static void pgtk_regenerate_devices (struct pgtk_display_info *);
+
+static void
+pgtk_device_added_or_removal_cb (GdkSeat *seat, GdkDevice *device,
+ gpointer user_data)
+{
+ pgtk_regenerate_devices (user_data);
+}
+
+static void
+pgtk_seat_added_cb (GdkDisplay *dpy, GdkSeat *seat,
+ gpointer user_data)
+{
+ pgtk_regenerate_devices (user_data);
+
+ g_signal_connect (G_OBJECT (seat), "device-added",
+ G_CALLBACK (pgtk_device_added_or_removal_cb),
+ user_data);
+ g_signal_connect (G_OBJECT (seat), "device-removed",
+ G_CALLBACK (pgtk_device_added_or_removal_cb),
+ user_data);
+}
+
+static void
+pgtk_seat_removed_cb (GdkDisplay *dpy, GdkSeat *seat,
+ gpointer user_data)
+{
+ pgtk_regenerate_devices (user_data);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (seat),
+ G_CALLBACK (pgtk_device_added_or_removal_cb),
+ user_data);
+}
+
+static void
+pgtk_enumerate_devices (struct pgtk_display_info *dpyinfo,
+ bool initial_p)
+{
+ struct pgtk_device_t *rec;
+ GList *all_seats, *devices_on_seat, *tem, *t1;
+ GdkSeat *seat;
+ char printbuf[1026]; /* Believe it or not, some device names are
+ actually almost this long. */
+
+ block_input ();
+ all_seats = gdk_display_list_seats (dpyinfo->gdpy);
+
+ for (tem = all_seats; tem; tem = tem->next)
+ {
+ seat = GDK_SEAT (tem->data);
+
+ if (initial_p)
+ {
+ g_signal_connect (G_OBJECT (seat), "device-added",
+ G_CALLBACK (pgtk_device_added_or_removal_cb),
+ dpyinfo);
+ g_signal_connect (G_OBJECT (seat), "device-removed",
+ G_CALLBACK (pgtk_device_added_or_removal_cb),
+ dpyinfo);
+ }
+
+ /* We only want slaves, not master devices. */
+ devices_on_seat = gdk_seat_get_slaves (seat,
+ GDK_SEAT_CAPABILITY_ALL);
+
+ for (t1 = devices_on_seat; t1; t1 = t1->next)
+ {
+ rec = xmalloc (sizeof *rec);
+ rec->seat = g_object_ref (seat);
+ rec->device = GDK_DEVICE (t1->data);
+
+ snprintf (printbuf, 1026, "%u:%s",
+ gdk_device_get_source (rec->device),
+ gdk_device_get_name (rec->device));
+
+ rec->name = build_string (printbuf);
+ rec->next = dpyinfo->devices;
+ dpyinfo->devices = rec;
+ }
+
+ g_list_free (devices_on_seat);
+ }
+
+ g_list_free (all_seats);
+ unblock_input ();
+}
+
+static void
+pgtk_free_devices (struct pgtk_display_info *dpyinfo)
+{
+ struct pgtk_device_t *last, *tem;
+
+ tem = dpyinfo->devices;
+ while (tem)
+ {
+ last = tem;
+ tem = tem->next;
+
+ g_object_unref (last->seat);
+ xfree (last);
+ }
+
+ dpyinfo->devices = NULL;
+}
+
+static void
+pgtk_regenerate_devices (struct pgtk_display_info *dpyinfo)
+{
+ pgtk_free_devices (dpyinfo);
+ pgtk_enumerate_devices (dpyinfo, false);
+}
+
+static void
+pgtk_toolkit_position (struct frame *f, int x, int y,
+ bool *menu_bar_p, bool *tool_bar_p)
+{
+ GdkRectangle test_rect;
+ int scale;
+
+ y += (FRAME_MENUBAR_HEIGHT (f)
+ + FRAME_TOOLBAR_TOP_HEIGHT (f));
+ x += FRAME_TOOLBAR_LEFT_WIDTH (f);
+
+ if (FRAME_EXTERNAL_MENU_BAR (f))
+ *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
+ && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
+
+ if (FRAME_X_OUTPUT (f)->toolbar_widget)
+ {
+ scale = xg_get_scale (f);
+ test_rect.x = x / scale;
+ test_rect.y = y / scale;
+ test_rect.width = 1;
+ test_rect.height = 1;
+
+ *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
+ &test_rect, NULL);
+ }
+}
+
+static Lisp_Object
+pgtk_get_device_for_event (struct pgtk_display_info *dpyinfo,
+ GdkEvent *event)
+{
+ struct pgtk_device_t *tem;
+ GdkDevice *device;
+
+ device = gdk_event_get_source_device (event);
+
+ if (!device)
+ return Qt;
+
+ for (tem = dpyinfo->devices; tem; tem = tem->next)
+ {
+ if (tem->device == device)
+ return tem->name;
+ }
+
+ return Qt;
+}
+
+/* This is not a flip context in the same sense as gpu rendering
+ scenes, it only occurs when a new context was required due to a
+ resize or other fundamental change. This is called when that
+ context's surface has completed drawing. */
static void
flip_cr_context (struct frame *f)
@@ -122,8 +288,9 @@ flip_cr_context (struct frame *f)
if (cr != FRAME_CR_CONTEXT (f))
{
cairo_destroy (cr);
- FRAME_CR_ACTIVE_CONTEXT (f) = cairo_reference (FRAME_CR_CONTEXT (f));
+ FRAME_CR_ACTIVE_CONTEXT (f)
+ = cairo_reference (FRAME_CR_CONTEXT (f));
}
unblock_input ();
}
@@ -133,6 +300,9 @@ static void
evq_enqueue (union buffered_input_event *ev)
{
struct event_queue_t *evq = &event_q;
+ struct frame *frame;
+ struct pgtk_display_info *dpyinfo;
+
if (evq->cap == 0)
{
evq->cap = 4;
@@ -146,6 +316,27 @@ evq_enqueue (union buffered_input_event *ev)
}
evq->q[evq->nr++] = *ev;
+
+ if (ev->ie.kind != SELECTION_REQUEST_EVENT
+ && ev->ie.kind != SELECTION_CLEAR_EVENT)
+ {
+ frame = NULL;
+
+ if (WINDOWP (ev->ie.frame_or_window))
+ frame = WINDOW_XFRAME (XWINDOW (ev->ie.frame_or_window));
+
+ if (FRAMEP (ev->ie.frame_or_window))
+ frame = XFRAME (ev->ie.frame_or_window);
+
+ if (frame)
+ {
+ dpyinfo = FRAME_DISPLAY_INFO (frame);
+
+ if (dpyinfo->last_user_time < ev->ie.timestamp)
+ dpyinfo->last_user_time = ev->ie.timestamp;
+ }
+ }
+
raise (SIGIO);
}
@@ -153,18 +344,35 @@ 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;
}
void
mark_pgtkterm (void)
{
+ struct pgtk_display_info *dpyinfo;
+ struct pgtk_device_t *device;
struct event_queue_t *evq = &event_q;
int i, n = evq->nr;
+
for (i = 0; i < n; i++)
{
union buffered_input_event *ev = &evq->q[i];
@@ -172,19 +380,22 @@ mark_pgtkterm (void)
mark_object (ev->ie.y);
mark_object (ev->ie.frame_or_window);
mark_object (ev->ie.arg);
+ mark_object (ev->ie.device);
+ }
+
+ for (dpyinfo = x_display_list; dpyinfo;
+ dpyinfo = dpyinfo->next)
+ {
+ for (device = dpyinfo->devices; device;
+ device = device->next)
+ mark_object (device->name);
}
}
char *
get_keysym_name (int keysym)
-/* --------------------------------------------------------------------------
- Called by keyboard.c. Not sure if the return val is important, except
- that it be unique.
- -------------------------------------------------------------------------- */
{
- static char value[16];
- sprintf (value, "%d", keysym);
- return value;
+ return gdk_keyval_name (keysym);
}
void
@@ -234,7 +445,7 @@ pgtk_frame_raise_lower (struct frame *f, bool raise_flag)
/* Free X resources of frame F. */
void
-x_free_frame_resources (struct frame *f)
+pgtk_free_frame_resources (struct frame *f)
{
struct pgtk_display_info *dpyinfo;
Mouse_HLInfo *hlinfo;
@@ -335,7 +546,7 @@ x_free_frame_resources (struct frame *f)
}
void
-x_destroy_window (struct frame *f)
+pgtk_destroy_window (struct frame *f)
/* --------------------------------------------------------------------------
External: Delete the window
-------------------------------------------------------------------------- */
@@ -344,7 +555,7 @@ x_destroy_window (struct frame *f)
check_window_system (f);
if (dpyinfo->gdpy != NULL)
- x_free_frame_resources (f);
+ pgtk_free_frame_resources (f);
dpyinfo->reference_count--;
}
@@ -353,7 +564,7 @@ x_destroy_window (struct frame *f)
from its current recorded position values and gravity. */
static void
-x_calc_absolute_position (struct frame *f)
+pgtk_calc_absolute_position (struct frame *f)
{
int flags = f->size_hint_flags;
struct frame *p = FRAME_PARENT_FRAME (f);
@@ -387,7 +598,7 @@ x_calc_absolute_position (struct frame *f)
f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
+ f->left_pos);
else
- f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
+ f->left_pos = (pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f))
- width + f->left_pos);
}
@@ -413,7 +624,7 @@ x_calc_absolute_position (struct frame *f)
f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
+ f->top_pos);
else
- f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
+ f->top_pos = (pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f))
- height + f->top_pos);
}
@@ -430,13 +641,8 @@ x_calc_absolute_position (struct frame *f)
which means, do adjust for borders but don't change the gravity. */
static void
-x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
-/* --------------------------------------------------------------------------
- External: Position the window
- -------------------------------------------------------------------------- */
+pgtk_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
{
- int modified_top, modified_left;
-
if (change_gravity > 0)
{
f->top_pos = yoff;
@@ -449,49 +655,26 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
f->win_gravity = NorthWestGravity;
}
- x_calc_absolute_position (f);
+ pgtk_calc_absolute_position (f);
block_input ();
- x_wm_set_size_hint (f, 0, false);
+ xg_wm_set_size_hint (f, 0, false);
- if (x_gtk_use_window_move)
+ if (change_gravity != 0)
{
- if (change_gravity != 0)
+ if (FRAME_GTK_OUTER_WIDGET (f))
+ gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+ f->left_pos, f->top_pos);
+ else
{
- if (FRAME_GTK_OUTER_WIDGET (f))
- {
- gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- f->left_pos, f->top_pos);
- }
- else
- {
- GtkWidget *fixed = FRAME_GTK_WIDGET (f);
- GtkWidget *parent = gtk_widget_get_parent (fixed);
- gtk_fixed_move (GTK_FIXED (parent), fixed,
- f->left_pos, f->top_pos);
- }
+ GtkWidget *fixed = FRAME_GTK_WIDGET (f);
+ GtkWidget *parent = gtk_widget_get_parent (fixed);
+ gtk_fixed_move (GTK_FIXED (parent), fixed,
+ f->left_pos, f->top_pos);
}
- unblock_input ();
- return;
}
-
- modified_left = f->left_pos;
- modified_top = f->top_pos;
-
- if (FRAME_GTK_OUTER_WIDGET (f))
- {
- gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- modified_left, modified_top);
- }
- else
- {
- GtkWidget *fixed = FRAME_GTK_WIDGET (f);
- GtkWidget *parent = gtk_widget_get_parent (fixed);
- gtk_fixed_move (GTK_FIXED (parent), fixed,
- modified_left, modified_top);
- }
-
unblock_input ();
+ return;
}
static void
@@ -510,31 +693,8 @@ pgtk_set_window_size (struct frame *f, bool change_gravity,
gtk_widget_get_size_request (FRAME_GTK_WIDGET (f), &pixelwidth,
&pixelheight);
-#if 0
- if (pixelwise)
- {
- pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
- pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
- }
- else
- {
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
- }
-#else
pixelwidth = width;
pixelheight = height;
-#endif
-
-#if 0
- frame_size_history_add
- (f, Qx_set_window_size_1, width, height,
- list5 (Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)),
- Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)),
- make_fixnum (f->border_width),
- make_fixnum (FRAME_PGTK_TITLEBAR_HEIGHT (f)),
- make_fixnum (FRAME_TOOLBAR_HEIGHT (f))));
-#endif
for (GtkWidget * w = FRAME_GTK_WIDGET (f); w != NULL;
w = gtk_widget_get_parent (w))
@@ -545,7 +705,7 @@ pgtk_set_window_size (struct frame *f, bool change_gravity,
f->output_data.pgtk->preferred_width = pixelwidth;
f->output_data.pgtk->preferred_height = pixelheight;
- x_wm_set_size_hint (f, 0, 0);
+ xg_wm_set_size_hint (f, 0, 0);
xg_frame_set_char_size (f, pixelwidth, pixelheight);
gtk_widget_queue_resize (FRAME_WIDGET (f));
@@ -567,10 +727,6 @@ pgtk_iconify_frame (struct frame *f)
block_input ();
-#if 0
- x_set_bitmap_icon (f);
-#endif
-
if (FRAME_GTK_OUTER_WIDGET (f))
{
if (!FRAME_VISIBLE_P (f))
@@ -585,20 +741,8 @@ pgtk_iconify_frame (struct frame *f)
/* Make sure the X server knows where the window should be positioned,
in case the user deiconifies with the window manager. */
- if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f)
-#if 0
- && !FRAME_X_EMBEDDED_P (f)
-#endif
- )
- x_set_offset (f, f->left_pos, f->top_pos, 0);
-
-#if 0
- if (!FRAME_VISIBLE_P (f))
- {
- /* If the frame was withdrawn, before, we must map it. */
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- }
-#endif
+ if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
+ pgtk_set_offset (f, f->left_pos, f->top_pos, 0);
SET_FRAME_ICONIFIED (f, true);
SET_FRAME_VISIBLE (f, 0);
@@ -607,8 +751,8 @@ pgtk_iconify_frame (struct frame *f)
}
static gboolean
-pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget * widget,
- GdkEventAny * event,
+pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget *widget,
+ GdkEventAny *event,
gpointer user_data)
{
int *foundptr = user_data;
@@ -629,19 +773,19 @@ pgtk_wait_for_map_event (struct frame *f, bool multiple_times)
{
if (FLOATP (Vpgtk_wait_for_event_timeout))
{
- guint msec =
- (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000);
+ guint msec
+ = (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000);
int found = 0;
int timed_out = 0;
- gulong id =
- g_signal_connect (FRAME_WIDGET (f), "map-event",
- G_CALLBACK
- (pgtk_make_frame_visible_wait_for_map_event_cb),
- &found);
- guint src =
- g_timeout_add (msec,
- pgtk_make_frame_visible_wait_for_map_event_timeout,
- &timed_out);
+ gulong id
+ = g_signal_connect (FRAME_WIDGET (f), "map-event",
+ G_CALLBACK
+ (pgtk_make_frame_visible_wait_for_map_event_cb),
+ &found);
+ guint src
+ = g_timeout_add (msec,
+ pgtk_make_frame_visible_wait_for_map_event_timeout,
+ &timed_out);
if (!multiple_times)
{
@@ -655,6 +799,7 @@ pgtk_wait_for_map_event (struct frame *f, bool multiple_times)
}
g_signal_handler_disconnect (FRAME_WIDGET (f), id);
+
if (!timed_out)
g_source_remove (src);
}
@@ -662,9 +807,6 @@ pgtk_wait_for_map_event (struct frame *f, bool multiple_times)
void
pgtk_make_frame_visible (struct frame *f)
-/* --------------------------------------------------------------------------
- External: Show the window (X11 semantics)
- -------------------------------------------------------------------------- */
{
GtkWidget *win = FRAME_GTK_OUTER_WIDGET (f);
@@ -681,17 +823,11 @@ pgtk_make_frame_visible (struct frame *f)
void
pgtk_make_frame_invisible (struct frame *f)
-/* --------------------------------------------------------------------------
- External: Hide the window (X11 semantics)
- -------------------------------------------------------------------------- */
{
gtk_widget_hide (FRAME_WIDGET (f));
- /* Map events are emitted many times, and
- * map_event() do SET_FRAME_VISIBLE(f, 1).
- * I expect visible = 0, so process those map events here and
- * SET_FRAME_VISIBLE(f, 0) after that.
- */
+ /* Handle any pending map event(s), then make the frame visible
+ manually, to avoid race conditions. */
pgtk_wait_for_map_event (f, true);
SET_FRAME_VISIBLE (f, 0);
@@ -770,45 +906,26 @@ pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset)
}
int
-x_display_pixel_height (struct pgtk_display_info *dpyinfo)
+pgtk_display_pixel_height (struct pgtk_display_info *dpyinfo)
{
GdkDisplay *gdpy = dpyinfo->gdpy;
GdkScreen *gscr = gdk_display_get_default_screen (gdpy);
+
return gdk_screen_get_height (gscr);
}
int
-x_display_pixel_width (struct pgtk_display_info *dpyinfo)
+pgtk_display_pixel_width (struct pgtk_display_info *dpyinfo)
{
GdkDisplay *gdpy = dpyinfo->gdpy;
GdkScreen *gscr = gdk_display_get_default_screen (gdpy);
+
return gdk_screen_get_width (gscr);
}
void
-x_set_parent_frame (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value)
-/* --------------------------------------------------------------------------
- Set frame F's `parent-frame' parameter. If non-nil, make F a child
- frame of the frame specified by that parameter. Technically, this
- makes F's window-system window a child window of the parent frame's
- window-system window. If nil, make F's window-system window a
- top-level window--a child of its display's root window.
-
- A child frame's `left' and `top' parameters specify positions
- relative to the top-left corner of its parent frame's native
- rectangle. On macOS moving a parent frame moves all its child
- frames too, keeping their position relative to the parent
- unaltered. When a parent frame is iconified or made invisible, its
- child frames are made invisible. When a parent frame is deleted,
- its child frames are deleted too.
-
- Whether a child frame has a tool bar may be window-system or window
- manager dependent. It's advisable to disable it via the frame
- parameter settings.
-
- Some window managers may not honor this parameter.
- -------------------------------------------------------------------------- */
+pgtk_set_parent_frame (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
{
struct frame *p = NULL;
@@ -848,7 +965,8 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value,
{
GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed);
- /* Here, unhighlight can be called and may change border_color_css_provider. */
+ /* Here, unhighlight can be called and may change
+ border_color_css_provider. */
gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed);
if (FRAME_GTK_OUTER_WIDGET (f))
@@ -869,10 +987,11 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value,
{
xg_create_frame_outer_widgets (f);
pgtk_set_event_handler (f);
- gtk_box_pack_start (GTK_BOX (f->output_data.pgtk->hbox_widget), fixed, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (f->output_data.pgtk->hbox_widget),
+ fixed, TRUE, TRUE, 0);
f->output_data.pgtk->preferred_width = alloc.width;
f->output_data.pgtk->preferred_height = alloc.height;
- x_wm_set_size_hint (f, 0, 0);
+ xg_wm_set_size_hint (f, 0, 0);
xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, alloc.width),
FRAME_PIXEL_TO_TEXT_HEIGHT (f, alloc.height));
gtk_widget_queue_resize (FRAME_WIDGET (f));
@@ -903,34 +1022,17 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value,
g_object_unref (fixed);
- if (FRAME_GTK_OUTER_WIDGET (f))
- {
- if (EQ (x_gtk_resize_child_frames, Qresize_mode))
- gtk_container_set_resize_mode
- (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
- p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
- }
-
unblock_input ();
fset_parent_frame (f, new_value);
}
}
-
+/* Doesn't work on wayland. */
void
-x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value)
-/* Set frame F's `no-focus-on-map' parameter which, if non-nil, means
- * that F's window-system window does not want to receive input focus
- * when it is mapped. (A frame's window is mapped when the frame is
- * displayed for the first time and when the frame changes its state
- * from `iconified' or `invisible' to `visible'.)
- *
- * Some window managers may not honor this parameter. */
+pgtk_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
{
- /* doesn't work on wayland. */
-
if (!EQ (new_value, old_value))
{
xg_set_no_focus_on_map (f, new_value);
@@ -939,36 +1041,16 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
}
void
-x_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value)
-/* Set frame F's `no-accept-focus' parameter which, if non-nil, hints
- * that F's window-system window does not want to receive input focus
- * via mouse clicks or by moving the mouse into it.
- *
- * If non-nil, this may have the unwanted side-effect that a user cannot
- * scroll a non-selected frame with the mouse.
- *
- * Some window managers may not honor this parameter. */
+pgtk_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
{
- /* doesn't work on wayland. */
-
xg_set_no_accept_focus (f, new_value);
FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
}
void
-x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
-/* Set frame F's `z-group' parameter. If `above', F's window-system
- window is displayed above all windows that do not have the `above'
- property set. If nil, F's window is shown below all windows that
- have the `above' property set and above all windows that have the
- `below' property set. If `below', F's window is displayed below
- all windows that do.
-
- Some window managers may not honor this parameter. */
+pgtk_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
- /* doesn't work on wayland. */
-
if (!FRAME_GTK_OUTER_WIDGET (f))
return;
@@ -1029,7 +1111,7 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo)
face. */
static void
-x_set_cursor_gc (struct glyph_string *s)
+pgtk_set_cursor_gc (struct glyph_string *s)
{
if (s->font == FRAME_FONT (s->f)
&& s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
@@ -1067,7 +1149,7 @@ x_set_cursor_gc (struct glyph_string *s)
/* Set up S->gc of glyph string S for drawing text in mouse face. */
static void
-x_set_mouse_face_gc (struct glyph_string *s)
+pgtk_set_mouse_face_gc (struct glyph_string *s)
{
prepare_face_for_display (s->f, s->face);
@@ -1096,7 +1178,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
matrix was built, so there isn't much to do, here. */
static void
-x_set_mode_line_face_gc (struct glyph_string *s)
+pgtk_set_mode_line_face_gc (struct glyph_string *s)
{
s->xgcv.foreground = s->face->foreground;
s->xgcv.background = s->face->background;
@@ -1108,7 +1190,7 @@ x_set_mode_line_face_gc (struct glyph_string *s)
pattern. */
static void
-x_set_glyph_string_gc (struct glyph_string *s)
+pgtk_set_glyph_string_gc (struct glyph_string *s)
{
prepare_face_for_display (s->f, s->face);
@@ -1120,17 +1202,17 @@ x_set_glyph_string_gc (struct glyph_string *s)
}
else if (s->hl == DRAW_INVERSE_VIDEO)
{
- x_set_mode_line_face_gc (s);
+ pgtk_set_mode_line_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_CURSOR)
{
- x_set_cursor_gc (s);
+ pgtk_set_cursor_gc (s);
s->stippled_p = false;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
- x_set_mouse_face_gc (s);
+ pgtk_set_mouse_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
@@ -1148,7 +1230,7 @@ x_set_glyph_string_gc (struct glyph_string *s)
line or menu if we don't have X toolkit support. */
static void
-x_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr)
+pgtk_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr)
{
XRectangle r[2];
int n = get_glyph_string_clip_rects (s, r, 2);
@@ -1163,14 +1245,13 @@ x_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr)
}
}
-
/* Set SRC's clipping for output of glyph string DST. This is called
when we are drawing DST's left_overhang or right_overhang only in
the area of SRC. */
static void
-x_set_glyph_string_clipping_exactly (struct glyph_string *src,
- struct glyph_string *dst, cairo_t * cr)
+pgtk_set_glyph_string_clipping_exactly (struct glyph_string *src,
+ struct glyph_string *dst, cairo_t * cr)
{
dst->clip[0].x = src->x;
dst->clip[0].y = src->y;
@@ -1182,7 +1263,6 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src,
cairo_clip (cr);
}
-
/* RIF:
Compute left and right overhang of glyph string S. */
@@ -1223,16 +1303,17 @@ pgtk_compute_glyph_string_overhangs (struct glyph_string *s)
}
}
-
-/* Fill rectangle X, Y, W, H with background color of glyph string S. */
-
+/* Fill rectangle X, Y, W, H with background color of glyph string
+ S. */
static void
-x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
+pgtk_clear_glyph_string_rect (struct glyph_string *s, int x, int y,
+ int w, int h)
{
- pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h);
+ pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h,
+ (s->first_glyph->type != STRETCH_GLYPH
+ || s->hl != DRAW_CURSOR));
}
-
static void
fill_background_by_face (struct frame *f, struct face *face, int x, int y,
int width, int height)
@@ -1274,9 +1355,8 @@ fill_background (struct glyph_string *s, int x, int y, int width, int height)
background even if it wouldn't be drawn normally. This is used
when a string preceding S draws into the background of S, or S
contains the first component of a composition. */
-
static void
-x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
+pgtk_draw_glyph_string_background (struct glyph_string *s, bool force_p)
{
/* Nothing to do if background has already been drawn or if it
shouldn't be drawn in the first place. */
@@ -1287,9 +1367,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
if (s->stippled_p)
{
/* Fill background with a stipple pattern. */
-
- fill_background (s,
- s->x, s->y + box_line_width,
+ fill_background (s, s->x, s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
s->background_filled_p = true;
@@ -1303,9 +1381,9 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
|| s->font_not_found_p
|| s->extends_to_end_of_line_p || force_p)
{
- x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
- s->background_width,
- s->height - 2 * box_line_width);
+ pgtk_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
+ s->background_width,
+ s->height - 2 * box_line_width);
s->background_filled_p = true;
}
}
@@ -1314,12 +1392,12 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
static void
pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y,
- int width, int height)
+ int width, int height, bool respect_alpha_background)
{
cairo_t *cr;
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, respect_alpha_background);
cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
cairo_set_line_width (cr, 1);
cairo_stroke (cr);
@@ -1327,9 +1405,8 @@ pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y,
}
/* Draw the foreground of glyph string S. */
-
static void
-x_draw_glyph_string_foreground (struct glyph_string *s)
+pgtk_draw_glyph_string_foreground (struct glyph_string *s)
{
int i, x;
@@ -1349,7 +1426,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
struct glyph *g = s->first_glyph + i;
pgtk_draw_rectangle (s->f,
s->face->foreground, x, s->y,
- g->pixel_width - 1, s->height - 1);
+ g->pixel_width - 1, s->height - 1,
+ false);
x += g->pixel_width;
}
}
@@ -1373,9 +1451,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
}
/* Draw the foreground of composite glyph string S. */
-
static void
-x_draw_composite_glyph_string_foreground (struct glyph_string *s)
+pgtk_draw_composite_glyph_string_foreground (struct glyph_string *s)
{
int i, j, x;
struct font *font = s->font;
@@ -1399,7 +1476,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
{
if (s->cmp_from == 0)
pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y,
- s->width - 1, s->height - 1);
+ s->width - 1, s->height - 1, false);
}
else if (!s->first_glyph->u.cmp.automatic)
{
@@ -1464,9 +1541,8 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
/* Draw the foreground of glyph string S for glyphless characters. */
-
static void
-x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
+pgtk_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
{
struct glyph *glyph = s->first_glyph;
unsigned char2b[8];
@@ -1541,9 +1617,14 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
pgtk_draw_rectangle (s->f, s->face->foreground,
x, s->ybase - glyph->ascent,
glyph->pixel_width - 1,
- glyph->ascent + glyph->descent - 1);
+ glyph->ascent + glyph->descent - 1,
+ false);
x += glyph->pixel_width;
}
+
+ /* Pacify GCC 12 even though s->char2b is not used after this
+ function returns. */
+ s->char2b = NULL;
}
/* Brightness beyond which a color won't have its highlight brightness
@@ -1560,20 +1641,18 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
-/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
- or DELTA. Try a color with RGB values multiplied by FACTOR first.
- If this produces the same color as PIXEL, try a color where all RGB
- values have DELTA added. Return the allocated color in *PIXEL.
- DISPLAY is the X display, CMAP is the colormap to operate on.
- Value is non-zero if successful. */
+/* Compute a color which is lighter or darker than *PIXEL by FACTOR or
+ DELTA. Try a color with RGB values multiplied by FACTOR first. If
+ this produces the same color as PIXEL, try a color where all RGB
+ values have DELTA added. Return the computed color in *PIXEL. F
+ is the frame to act on. */
-static bool
-x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor,
- int delta)
+static void
+pgtk_compute_lighter_color (struct frame *f, unsigned long *pixel,
+ double factor, int delta)
{
Emacs_Color color, new;
long bright;
- bool success_p;
/* Get RGB color values. */
color.pixel = *pixel;
@@ -1613,38 +1692,33 @@ x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor,
}
}
- /* Try to allocate the color. */
- new.pixel = new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8;
- success_p = true;
- if (success_p)
+ new.pixel = (new.red >> 8 << 16
+ | new.green >> 8 << 8
+ | new.blue >> 8);
+
+ if (new.pixel == *pixel)
{
- if (new.pixel == *pixel)
- {
- /* If we end up with the same color as before, try adding
- delta to the RGB values. */
- new.red = min (0xffff, delta + color.red);
- new.green = min (0xffff, delta + color.green);
- new.blue = min (0xffff, delta + color.blue);
- new.pixel =
- new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8;
- success_p = true;
- }
- else
- success_p = true;
- *pixel = new.pixel;
+ /* If we end up with the same color as before, try adding
+ delta to the RGB values. */
+ new.red = min (0xffff, delta + color.red);
+ new.green = min (0xffff, delta + color.green);
+ new.blue = min (0xffff, delta + color.blue);
+ new.pixel = (new.red >> 8 << 16
+ | new.green >> 8 << 8
+ | new.blue >> 8);
}
- return success_p;
+ *pixel = new.pixel;
}
static void
-x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x,
- int y, int width, int height, int top_p)
+pgtk_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x,
+ int y, int width, int height, int top_p)
{
cairo_t *cr;
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
cairo_move_to (cr, top_p ? x : x + height, y);
cairo_line_to (cr, x, y + height);
cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
@@ -1663,15 +1737,15 @@ enum corners
};
static void
-x_erase_corners_for_relief (struct frame *f, unsigned long color, int x,
- int y, int width, int height, double radius,
- double margin, int corners)
+pgtk_erase_corners_for_relief (struct frame *f, unsigned long color, int x,
+ int y, int width, int height, double radius,
+ double margin, int corners)
{
cairo_t *cr;
int i;
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
for (i = 0; i < CORNER_LAST; i++)
if (corners & (1 << i))
{
@@ -1695,16 +1769,9 @@ x_erase_corners_for_relief (struct frame *f, unsigned long color, int x,
pgtk_end_cr_clip (f);
}
-/* Set up the foreground color for drawing relief lines of glyph
- string S. RELIEF is a pointer to a struct relief containing the GC
- with which lines will be drawn. Use a color that is FACTOR or
- DELTA lighter or darker than the relief's background which is found
- in S->f->output_data.pgtk->relief_background. If such a color cannot
- be allocated, use DEFAULT_PIXEL, instead. */
-
static void
-x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
- int delta, unsigned long default_pixel)
+pgtk_setup_relief_color (struct frame *f, struct relief *relief, double factor,
+ int delta, unsigned long default_pixel)
{
Emacs_GC xgcv;
struct pgtk_output *di = FRAME_X_OUTPUT (f);
@@ -1714,16 +1781,15 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
/* Allocate new color. */
xgcv.foreground = default_pixel;
pixel = background;
- if (x_alloc_lighter_color (f, &pixel, factor, delta))
- xgcv.foreground = relief->pixel = pixel;
+ pgtk_compute_lighter_color (f, &pixel, factor, delta);
+ xgcv.foreground = relief->pixel = pixel;
relief->xgcv = xgcv;
}
/* Set up colors for the relief lines around glyph string S. */
-
static void
-x_setup_relief_colors (struct glyph_string *s)
+pgtk_setup_relief_colors (struct glyph_string *s)
{
struct pgtk_output *di = FRAME_X_OUTPUT (s->f);
unsigned long color;
@@ -1740,30 +1806,27 @@ x_setup_relief_colors (struct glyph_string *s)
color = s->xgcv.background;
}
- if (TRUE)
+ if (!di->relief_background_valid_p
+ || di->relief_background != color)
{
+ di->relief_background_valid_p = true;
di->relief_background = color;
- x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
- WHITE_PIX_DEFAULT (s->f));
- x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
- BLACK_PIX_DEFAULT (s->f));
+ pgtk_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
+ WHITE_PIX_DEFAULT (s->f));
+ pgtk_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
+ BLACK_PIX_DEFAULT (s->f));
}
}
-
static void
-x_set_clip_rectangles (struct frame *f, cairo_t * cr, XRectangle * rectangles,
- int n)
+pgtk_set_clip_rectangles (struct frame *f, cairo_t *cr,
+ XRectangle *rectangles, int n)
{
if (n > 0)
{
for (int i = 0; i < n; i++)
- {
- cairo_rectangle (cr,
- rectangles[i].x,
- rectangles[i].y,
- rectangles[i].width, rectangles[i].height);
- }
+ cairo_rectangle (cr, rectangles[i].x, rectangles[i].y,
+ rectangles[i].width, rectangles[i].height);
cairo_clip (cr);
}
}
@@ -1777,11 +1840,11 @@ x_set_clip_rectangles (struct frame *f, cairo_t * cr, XRectangle * rectangles,
when drawing. */
static void
-x_draw_relief_rect (struct frame *f,
- int left_x, int top_y, int right_x, int bottom_y,
- int hwidth, int vwidth, bool raised_p, bool top_p,
- bool bot_p, bool left_p, bool right_p,
- XRectangle * clip_rect)
+pgtk_draw_relief_rect (struct frame *f,
+ int left_x, int top_y, int right_x, int bottom_y,
+ int hwidth, int vwidth, bool raised_p, bool top_p,
+ bool bot_p, bool left_p, bool right_p,
+ XRectangle *clip_rect)
{
unsigned long top_left_color, bottom_right_color;
int corners = 0;
@@ -1799,12 +1862,12 @@ x_draw_relief_rect (struct frame *f,
bottom_right_color = FRAME_X_OUTPUT (f)->white_relief.xgcv.foreground;
}
- x_set_clip_rectangles (f, cr, clip_rect, 1);
+ pgtk_set_clip_rectangles (f, cr, clip_rect, 1);
if (left_p)
{
pgtk_fill_rectangle (f, top_left_color, left_x, top_y,
- vwidth, bottom_y + 1 - top_y);
+ vwidth, bottom_y + 1 - top_y, false);
if (top_p)
corners |= 1 << CORNER_TOP_LEFT;
if (bot_p)
@@ -1813,7 +1876,7 @@ x_draw_relief_rect (struct frame *f,
if (right_p)
{
pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - vwidth, top_y,
- vwidth, bottom_y + 1 - top_y);
+ vwidth, bottom_y + 1 - top_y, false);
if (top_p)
corners |= 1 << CORNER_TOP_RIGHT;
if (bot_p)
@@ -1823,34 +1886,32 @@ x_draw_relief_rect (struct frame *f,
{
if (!right_p)
pgtk_fill_rectangle (f, top_left_color, left_x, top_y,
- right_x + 1 - left_x, hwidth);
+ right_x + 1 - left_x, hwidth, false);
else
- x_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y,
- right_x + 1 - left_x, hwidth, 1);
+ pgtk_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y,
+ right_x + 1 - left_x, hwidth, 1);
}
if (bot_p)
{
if (!left_p)
pgtk_fill_rectangle (f, bottom_right_color, left_x,
bottom_y + 1 - hwidth, right_x + 1 - left_x,
- hwidth);
+ hwidth, false);
else
- x_fill_trapezoid_for_relief (f, bottom_right_color,
- left_x, bottom_y + 1 - hwidth,
- right_x + 1 - left_x, hwidth, 0);
+ pgtk_fill_trapezoid_for_relief (f, bottom_right_color,
+ left_x, bottom_y + 1 - hwidth,
+ right_x + 1 - left_x, hwidth, 0);
}
if (left_p && vwidth > 1)
pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y,
- 1, bottom_y + 1 - top_y);
+ 1, bottom_y + 1 - top_y, false);
if (top_p && hwidth > 1)
pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y,
- right_x + 1 - left_x, 1);
+ right_x + 1 - left_x, 1, false);
if (corners)
- {
- x_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x,
- top_y, right_x - left_x + 1,
- bottom_y - top_y + 1, 6, 1, corners);
- }
+ pgtk_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x,
+ top_y, right_x - left_x + 1,
+ bottom_y - top_y + 1, 6, 1, corners);
pgtk_end_cr_clip (f);
}
@@ -1863,10 +1924,10 @@ x_draw_relief_rect (struct frame *f,
rectangle to use when drawing. */
static void
-x_draw_box_rect (struct glyph_string *s,
- int left_x, int top_y, int right_x, int bottom_y, int hwidth,
- int vwidth, bool left_p, bool right_p,
- XRectangle * clip_rect)
+pgtk_draw_box_rect (struct glyph_string *s, int left_x,
+ int top_y, int right_x, int bottom_y, int hwidth,
+ int vwidth, bool left_p, bool right_p,
+ XRectangle * clip_rect)
{
unsigned long foreground_backup;
@@ -1875,27 +1936,29 @@ x_draw_box_rect (struct glyph_string *s,
foreground_backup = s->xgcv.foreground;
s->xgcv.foreground = s->face->box_color;
- x_set_clip_rectangles (s->f, cr, clip_rect, 1);
+ pgtk_set_clip_rectangles (s->f, cr, clip_rect, 1);
/* Top. */
pgtk_fill_rectangle (s->f, s->xgcv.foreground,
- left_x, top_y, right_x - left_x + 1, hwidth);
+ left_x, top_y, right_x - left_x + 1, hwidth,
+ false);
/* Left. */
if (left_p)
pgtk_fill_rectangle (s->f, s->xgcv.foreground,
- left_x, top_y, vwidth, bottom_y - top_y + 1);
+ left_x, top_y, vwidth, bottom_y - top_y + 1,
+ false);
/* Bottom. */
pgtk_fill_rectangle (s->f, s->xgcv.foreground,
left_x, bottom_y - hwidth + 1, right_x - left_x + 1,
- hwidth);
+ hwidth, false);
/* Right. */
if (right_p)
pgtk_fill_rectangle (s->f, s->xgcv.foreground,
right_x - vwidth + 1, top_y, vwidth,
- bottom_y - top_y + 1);
+ bottom_y - top_y + 1, false);
s->xgcv.foreground = foreground_backup;
@@ -1906,7 +1969,7 @@ x_draw_box_rect (struct glyph_string *s,
/* Draw a box around glyph string S. */
static void
-x_draw_glyph_string_box (struct glyph_string *s)
+pgtk_draw_glyph_string_box (struct glyph_string *s)
{
int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
bool raised_p, left_p, right_p;
@@ -1939,33 +2002,27 @@ x_draw_glyph_string_box (struct glyph_string *s)
get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
- x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
- vwidth, left_p, right_p, &clip_rect);
+ pgtk_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
+ vwidth, left_p, right_p, &clip_rect);
else
{
- x_setup_relief_colors (s);
- x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
- vwidth, raised_p, true, true, left_p, right_p,
- &clip_rect);
+ pgtk_setup_relief_colors (s);
+ pgtk_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
+ vwidth, raised_p, true, true, left_p, right_p,
+ &clip_rect);
}
}
static void
-x_get_scale_factor (int *scale_x, int *scale_y)
-{
- *scale_x = *scale_y = 1;
-}
-
-static void
-x_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y,
- int width, int height, int wave_length)
+pgtk_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y,
+ int width, int height, int wave_length)
{
cairo_t *cr;
double dx = wave_length, dy = height - 1;
int xoffset, n;
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
cairo_rectangle (cr, x, y, width, height);
cairo_clip (cr);
@@ -1997,34 +2054,19 @@ x_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y,
pgtk_end_cr_clip (f);
}
-/*
- Draw a wavy line under S. The wave fills wave_height pixels from y0.
-
- x0 wave_length = 2
- --
- y0 * * * * *
- |* * * * * * * * *
- wave_height = 3 | * * * *
-
-*/
static void
-x_draw_underwave (struct glyph_string *s, unsigned long color)
+pgtk_draw_underwave (struct glyph_string *s, unsigned long color)
{
- /* Adjust for scale/HiDPI. */
- int scale_x, scale_y;
-
- x_get_scale_factor (&scale_x, &scale_y);
-
- int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
+ int wave_height = 3, wave_length = 2;
- x_draw_horizontal_wave (s->f, color, s->x, s->ybase - wave_height + 3,
- s->width, wave_height, wave_length);
+ pgtk_draw_horizontal_wave (s->f, color, s->x, s->ybase - wave_height + 3,
+ s->width, wave_height, wave_length);
}
/* Draw a relief around the image glyph string S. */
static void
-x_draw_image_relief (struct glyph_string *s)
+pgtk_draw_image_relief (struct glyph_string *s)
{
int x1, y1, thick;
bool raised_p, top_p, bot_p, left_p, right_p;
@@ -2107,33 +2149,29 @@ x_draw_image_relief (struct glyph_string *s)
if (s->slice.y + s->slice.height == s->img->height)
y1 += thick + extra_y, bot_p = true;
- x_setup_relief_colors (s);
+ pgtk_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
- top_p, bot_p, left_p, right_p, &r);
+ pgtk_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
+ top_p, bot_p, left_p, right_p, &r);
}
/* Draw part of the background of glyph string S. X, Y, W, and H
give the rectangle to draw. */
static void
-x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w,
- int h)
+pgtk_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w,
+ int h)
{
if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
-
- fill_background (s, x, y, w, h);
- }
+ fill_background (s, x, y, w, h);
else
- x_clear_glyph_string_rect (s, x, y, w, h);
+ pgtk_clear_glyph_string_rect (s, x, y, w, h);
}
static void
-x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
- int src_x, int src_y, int width, int height,
- int dest_x, int dest_y, bool overlay_p)
+pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
+ int src_x, int src_y, int width, int height,
+ int dest_x, int dest_y, bool overlay_p)
{
cairo_t *cr = pgtk_begin_cr_clip (f);
@@ -2141,7 +2179,7 @@ x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
cairo_rectangle (cr, dest_x, dest_y, width, height);
else
{
- pgtk_set_cr_source_with_gc_background (f, gc);
+ pgtk_set_cr_source_with_gc_background (f, gc, false);
cairo_rectangle (cr, dest_x, dest_y, width, height);
cairo_fill_preserve (cr);
}
@@ -2158,7 +2196,7 @@ x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
}
else
{
- pgtk_set_cr_source_with_gc_foreground (f, gc);
+ pgtk_set_cr_source_with_gc_foreground (f, gc, false);
cairo_clip (cr);
cairo_mask (cr, image);
}
@@ -2169,7 +2207,7 @@ x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
/* Draw foreground of image glyph string S. */
static void
-x_draw_image_foreground (struct glyph_string *s)
+pgtk_draw_image_foreground (struct glyph_string *s)
{
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
@@ -2191,10 +2229,10 @@ x_draw_image_foreground (struct glyph_string *s)
if (s->img->cr_data)
{
cairo_t *cr = pgtk_begin_cr_clip (s->f);
- x_set_glyph_string_clipping (s, cr);
- x_cr_draw_image (s->f, &s->xgcv, s->img->cr_data,
- s->slice.x, s->slice.y, s->slice.width, s->slice.height,
- x, y, true);
+ pgtk_set_glyph_string_clipping (s, cr);
+ pgtk_cr_draw_image (s->f, &s->xgcv, s->img->cr_data,
+ s->slice.x, s->slice.y, s->slice.width, s->slice.height,
+ x, y, true);
if (!s->img->mask)
{
/* When the image has a mask, we can expect that at
@@ -2206,9 +2244,9 @@ x_draw_image_foreground (struct glyph_string *s)
if (s->hl == DRAW_CURSOR)
{
int relief = eabs (s->img->relief);
- pgtk_draw_rectangle (s->f, s->xgcv.foreground, x - relief, y - relief,
- s->slice.width + relief*2 - 1,
- s->slice.height + relief*2 - 1);
+ pgtk_draw_rectangle (s->f, s->xgcv.foreground, x - relief,
+ y - relief, s->slice.width + relief * 2 - 1,
+ s->slice.height + relief * 2 - 1, false);
}
}
pgtk_end_cr_clip (s->f);
@@ -2216,7 +2254,7 @@ x_draw_image_foreground (struct glyph_string *s)
else
/* Draw a rectangle if image could not be loaded. */
pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y,
- s->slice.width - 1, s->slice.height - 1);
+ s->slice.width - 1, s->slice.height - 1, false);
}
/* Draw image glyph string S.
@@ -2234,7 +2272,7 @@ x_draw_image_foreground (struct glyph_string *s)
*/
static void
-x_draw_image_glyph_string (struct glyph_string *s)
+pgtk_draw_image_glyph_string (struct glyph_string *s)
{
int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
@@ -2257,41 +2295,39 @@ x_draw_image_glyph_string (struct glyph_string *s)
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
- {
- int x = s->x;
- int y = s->y;
- int width = s->background_width;
+ int x = s->x;
+ int y = s->y;
+ int width = s->background_width;
- if (s->first_glyph->left_box_line_p
- && s->slice.x == 0)
- {
- x += box_line_hwidth;
- width -= box_line_hwidth;
- }
+ if (s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ {
+ x += box_line_hwidth;
+ width -= box_line_hwidth;
+ }
- if (s->slice.y == 0)
- y += box_line_vwidth;
+ if (s->slice.y == 0)
+ y += box_line_vwidth;
- x_draw_glyph_string_bg_rect (s, x, y, width, height);
- }
+ pgtk_draw_glyph_string_bg_rect (s, x, y, width, height);
s->background_filled_p = true;
}
/* Draw the foreground. */
- x_draw_image_foreground (s);
+ pgtk_draw_image_foreground (s);
/* If we must draw a relief around the image, do it. */
if (s->img->relief
|| s->hl == DRAW_IMAGE_RAISED
|| s->hl == DRAW_IMAGE_SUNKEN)
- x_draw_image_relief (s);
+ pgtk_draw_image_relief (s);
}
/* Draw stretch glyph string S. */
static void
-x_draw_stretch_glyph_string (struct glyph_string *s)
+pgtk_draw_stretch_glyph_string (struct glyph_string *s)
{
eassert (s->first_glyph->type == STRETCH_GLYPH);
@@ -2327,7 +2363,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
x -= width;
/* Draw cursor. */
- x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
+ pgtk_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
/* Clear rest using the GC of the original non-cursor face. */
if (width < background_width)
@@ -2343,7 +2379,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
x = s->x;
if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
{
- x_set_mouse_face_gc (s);
+ pgtk_set_mouse_face_gc (s);
color = s->xgcv.foreground;
}
else
@@ -2352,17 +2388,13 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
cairo_t *cr = pgtk_begin_cr_clip (s->f);
get_glyph_string_clip_rect (s, &r);
- x_set_clip_rectangles (s->f, cr, &r, 1);
+ pgtk_set_clip_rectangles (s->f, cr, &r, 1);
if (s->face->stipple)
- {
- /* Fill background with a stipple pattern. */
- fill_background (s, x, y, w, h);
- }
+ fill_background (s, x, y, w, h);
else
- {
- pgtk_fill_rectangle (s->f, color, x, y, w, h);
- }
+ pgtk_fill_rectangle (s->f, color, x, y, w, h,
+ true);
pgtk_end_cr_clip (s->f);
}
@@ -2370,32 +2402,19 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
else if (!s->background_filled_p)
{
int background_width = s->background_width;
- int x = s->x, text_left_x = window_box_left_offset (s->w, TEXT_AREA);
+ int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
/* Don't draw into left fringe or scrollbar area except for
- header line and mode line. */
- if (x < text_left_x && !s->row->mode_line_p)
+ header line and mode line. */
+ if (s->area == TEXT_AREA
+ && x < text_left_x && !s->row->mode_line_p)
{
- int left_x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w);
- int right_x = text_left_x;
-
- if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
- left_x += WINDOW_LEFT_FRINGE_WIDTH (s->w);
- else
- right_x -= WINDOW_LEFT_FRINGE_WIDTH (s->w);
-
- /* Adjust X and BACKGROUND_WIDTH to fit inside the space
- between LEFT_X and RIGHT_X. */
- if (x < left_x)
- {
- background_width -= left_x - x;
- x = left_x;
- }
- if (x + background_width > right_x)
- background_width = right_x - x;
+ background_width -= text_left_x - x;
+ x = text_left_x;
}
+
if (background_width > 0)
- x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+ pgtk_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
}
s->background_filled_p = true;
@@ -2420,19 +2439,19 @@ pgtk_draw_glyph_string (struct glyph_string *s)
if (next->first_glyph->type != IMAGE_GLYPH)
{
cairo_t *cr = pgtk_begin_cr_clip (next->f);
- x_set_glyph_string_gc (next);
- x_set_glyph_string_clipping (next, cr);
+ pgtk_set_glyph_string_gc (next);
+ pgtk_set_glyph_string_clipping (next, cr);
if (next->first_glyph->type == STRETCH_GLYPH)
- x_draw_stretch_glyph_string (next);
+ pgtk_draw_stretch_glyph_string (next);
else
- x_draw_glyph_string_background (next, true);
+ pgtk_draw_glyph_string_background (next, true);
next->num_clips = 0;
pgtk_end_cr_clip (next->f);
}
}
/* Set up S->gc, set clipping and draw S. */
- x_set_glyph_string_gc (s);
+ pgtk_set_glyph_string_gc (s);
cairo_t *cr = pgtk_begin_cr_clip (s->f);
@@ -2444,10 +2463,10 @@ pgtk_draw_glyph_string (struct glyph_string *s)
|| s->first_glyph->type == COMPOSITE_GLYPH))
{
- x_set_glyph_string_clipping (s, cr);
- x_draw_glyph_string_background (s, true);
- x_draw_glyph_string_box (s);
- x_set_glyph_string_clipping (s, cr);
+ pgtk_set_glyph_string_clipping (s, cr);
+ pgtk_draw_glyph_string_background (s, true);
+ pgtk_draw_glyph_string_box (s);
+ pgtk_set_glyph_string_clipping (s, cr);
relief_drawn_p = true;
}
else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
@@ -2457,14 +2476,14 @@ pgtk_draw_glyph_string (struct glyph_string *s)
/* We must clip just this glyph. left_overhang part has already
drawn when s->prev was drawn, and right_overhang part will be
drawn later when s->next is drawn. */
- x_set_glyph_string_clipping_exactly (s, s, cr);
+ pgtk_set_glyph_string_clipping_exactly (s, s, cr);
else
- x_set_glyph_string_clipping (s, cr);
+ pgtk_set_glyph_string_clipping (s, cr);
switch (s->first_glyph->type)
{
case IMAGE_GLYPH:
- x_draw_image_glyph_string (s);
+ pgtk_draw_image_glyph_string (s);
break;
case XWIDGET_GLYPH:
@@ -2472,15 +2491,15 @@ pgtk_draw_glyph_string (struct glyph_string *s)
break;
case STRETCH_GLYPH:
- x_draw_stretch_glyph_string (s);
+ pgtk_draw_stretch_glyph_string (s);
break;
case CHAR_GLYPH:
if (s->for_overlaps)
s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, false);
- x_draw_glyph_string_foreground (s);
+ pgtk_draw_glyph_string_background (s, false);
+ pgtk_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
@@ -2488,16 +2507,16 @@ pgtk_draw_glyph_string (struct glyph_string *s)
&& !s->first_glyph->u.cmp.automatic))
s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, true);
- x_draw_composite_glyph_string_foreground (s);
+ pgtk_draw_glyph_string_background (s, true);
+ pgtk_draw_composite_glyph_string_foreground (s);
break;
case GLYPHLESS_GLYPH:
if (s->for_overlaps)
s->background_filled_p = true;
else
- x_draw_glyph_string_background (s, true);
- x_draw_glyphless_glyph_string_foreground (s);
+ pgtk_draw_glyph_string_background (s, true);
+ pgtk_draw_glyphless_glyph_string_foreground (s);
break;
default:
@@ -2508,7 +2527,7 @@ pgtk_draw_glyph_string (struct glyph_string *s)
{
/* Draw relief if not yet drawn. */
if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
- x_draw_glyph_string_box (s);
+ pgtk_draw_glyph_string_box (s);
/* Draw underline. */
if (s->face->underline)
@@ -2516,19 +2535,21 @@ pgtk_draw_glyph_string (struct glyph_string *s)
if (s->face->underline == FACE_UNDER_WAVE)
{
if (s->face->underline_defaulted_p)
- x_draw_underwave (s, s->xgcv.foreground);
+ pgtk_draw_underwave (s, s->xgcv.foreground);
else
- {
- x_draw_underwave (s, s->face->underline_color);
- }
+ pgtk_draw_underwave (s, s->face->underline_color);
}
else if (s->face->underline == FACE_UNDER_LINE)
{
unsigned long thickness, position;
int y;
- if (s->prev && s->prev->face->underline
- && s->prev->face->underline == FACE_UNDER_LINE)
+ if (s->prev
+ && s->prev->face->underline == FACE_UNDER_LINE
+ && (s->prev->face->underline_at_descent_line_p
+ == s->face->underline_at_descent_line_p)
+ && (s->prev->face->underline_pixels_above_descent_line
+ == s->face->underline_pixels_above_descent_line))
{
/* We use the same underline style as the previous one. */
thickness = s->prev->underline_thickness;
@@ -2543,8 +2564,11 @@ pgtk_draw_glyph_string (struct glyph_string *s)
thickness = font->underline_thickness;
else
thickness = 1;
- if (x_underline_at_descent_line)
- position = (s->height - thickness) - (s->ybase - s->y);
+ if ((x_underline_at_descent_line
+ || s->face->underline_at_descent_line_p))
+ position = ((s->height - thickness)
+ - (s->ybase - s->y)
+ - s->face->underline_pixels_above_descent_line);
else
{
/* Get the underline position. This is the recommended
@@ -2563,7 +2587,11 @@ pgtk_draw_glyph_string (struct glyph_string *s)
else
position = underline_minimum_offset;
}
- position = max (position, underline_minimum_offset);
+
+ /* Ignore minimum_offset if the amount of pixels was
+ explicitly specified. */
+ if (!s->face->underline_pixels_above_descent_line)
+ position = max (position, underline_minimum_offset);
}
/* Check the sanity of thickness and position. We should
avoid drawing underline out of the current line area. */
@@ -2576,11 +2604,13 @@ pgtk_draw_glyph_string (struct glyph_string *s)
y = s->ybase + position;
if (s->face->underline_defaulted_p)
pgtk_fill_rectangle (s->f, s->xgcv.foreground,
- s->x, y, s->width, thickness);
+ s->x, y, s->width, thickness,
+ false);
else
{
pgtk_fill_rectangle (s->f, s->face->underline_color,
- s->x, y, s->width, thickness);
+ s->x, y, s->width, thickness,
+ false);
}
}
}
@@ -2591,12 +2621,10 @@ pgtk_draw_glyph_string (struct glyph_string *s)
if (s->face->overline_color_defaulted_p)
pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, s->y + dy,
- s->width, h);
+ s->width, h, false);
else
- {
- pgtk_fill_rectangle (s->f, s->face->overline_color, s->x,
- s->y + dy, s->width, h);
- }
+ pgtk_fill_rectangle (s->f, s->face->overline_color, s->x,
+ s->y + dy, s->width, h, false);
}
/* Draw strike-through. */
@@ -2616,12 +2644,10 @@ pgtk_draw_glyph_string (struct glyph_string *s)
if (s->face->strike_through_color_defaulted_p)
pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, glyph_y + dy,
- s->width, h);
+ s->width, h, false);
else
- {
- pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x,
- glyph_y + dy, s->width, h);
- }
+ pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x,
+ glyph_y + dy, s->width, h, false);
}
if (s->prev)
@@ -2637,13 +2663,13 @@ pgtk_draw_glyph_string (struct glyph_string *s)
enum draw_glyphs_face save = prev->hl;
prev->hl = s->hl;
- x_set_glyph_string_gc (prev);
+ pgtk_set_glyph_string_gc (prev);
cairo_save (cr);
- x_set_glyph_string_clipping_exactly (s, prev, cr);
+ pgtk_set_glyph_string_clipping_exactly (s, prev, cr);
if (prev->first_glyph->type == CHAR_GLYPH)
- x_draw_glyph_string_foreground (prev);
+ pgtk_draw_glyph_string_foreground (prev);
else
- x_draw_composite_glyph_string_foreground (prev);
+ pgtk_draw_composite_glyph_string_foreground (prev);
prev->hl = save;
prev->num_clips = 0;
cairo_restore (cr);
@@ -2663,13 +2689,13 @@ pgtk_draw_glyph_string (struct glyph_string *s)
enum draw_glyphs_face save = next->hl;
next->hl = s->hl;
- x_set_glyph_string_gc (next);
+ pgtk_set_glyph_string_gc (next);
cairo_save (cr);
- x_set_glyph_string_clipping_exactly (s, next, cr);
+ pgtk_set_glyph_string_clipping_exactly (s, next, cr);
if (next->first_glyph->type == CHAR_GLYPH)
- x_draw_glyph_string_foreground (next);
+ pgtk_draw_glyph_string_foreground (next);
else
- x_draw_composite_glyph_string_foreground (next);
+ pgtk_draw_composite_glyph_string_foreground (next);
cairo_restore (cr);
next->hl = save;
next->num_clips = 0;
@@ -2678,6 +2704,11 @@ pgtk_draw_glyph_string (struct glyph_string *s)
}
}
+ /* TODO: figure out in which cases the stipple is actually drawn on
+ PGTK. */
+ if (!s->row->stipple_p)
+ s->row->stipple_p = s->face->stipple;
+
/* Reset clipping. */
pgtk_end_cr_clip (s->f);
s->num_clips = 0;
@@ -2734,7 +2765,7 @@ pgtk_clear_frame_area (struct frame *f, int x, int y, int width, int height)
/* Draw a hollow box cursor on window W in glyph row ROW. */
static void
-x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
+pgtk_draw_hollow_cursor (struct window *w, struct glyph_row *row)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
int x, y, wd, h;
@@ -2753,7 +2784,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
/* The foreground of cursor_gc is typically the same as the normal
background color, which can cause the cursor box to be invisible. */
cairo_t *cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color);
+ pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color, false);
/* When on R2L character, show cursor at the right edge of the
glyph, unless the cursor box is as wide as the glyph or wider
@@ -2767,7 +2798,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
}
/* Set clipping, draw the rectangle, and reset clipping again. */
pgtk_clip_to_row (w, row, TEXT_AREA, cr);
- pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color, x, y, wd, h - 1);
+ pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color,
+ x, y, wd, h - 1, false);
pgtk_end_cr_clip (f);
}
@@ -2779,7 +2811,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
--gerd. */
static void
-x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
+pgtk_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
enum text_cursor_kinds kind)
{
struct frame *f = XFRAME (w->frame);
@@ -2841,7 +2873,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
pgtk_fill_rectangle (f, color, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- width, row->height);
+ width, row->height, false);
}
else /* HBAR_CURSOR */
{
@@ -2862,7 +2894,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
pgtk_fill_rectangle (f, color, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
row->height - width),
- w->phys_cursor_width - 1, width);
+ w->phys_cursor_width - 1, width, false);
}
pgtk_end_cr_clip (f);
@@ -2877,6 +2909,7 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
int cursor_width, bool on_p, bool active_p)
{
struct frame *f = XFRAME (w->frame);
+
if (on_p)
{
w->phys_cursor_type = cursor_type;
@@ -2895,7 +2928,7 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
switch (cursor_type)
{
case HOLLOW_BOX_CURSOR:
- x_draw_hollow_cursor (w, glyph_row);
+ pgtk_draw_hollow_cursor (w, glyph_row);
break;
case FILLED_BOX_CURSOR:
@@ -2903,11 +2936,11 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
break;
case BAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+ pgtk_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
break;
case HBAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+ pgtk_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
break;
case NO_CURSOR:
@@ -2933,17 +2966,17 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
}
static void
-pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect,
- cairo_rectangle_t * dst_rect)
+pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect,
+ cairo_rectangle_t *dst_rect)
{
cairo_t *cr;
cairo_surface_t *surface; /* temporary surface */
- surface =
- cairo_surface_create_similar (FRAME_CR_SURFACE (f),
- CAIRO_CONTENT_COLOR_ALPHA,
- (int) src_rect->width,
- (int) src_rect->height);
+ surface
+ = cairo_surface_create_similar (FRAME_CR_SURFACE (f),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (int) src_rect->width,
+ (int) src_rect->height);
cr = cairo_create (surface);
cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x,
@@ -2955,6 +2988,7 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect,
cr = pgtk_begin_cr_clip (f);
cairo_set_source_surface (cr, surface, dst_rect->x, dst_rect->y);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_rectangle (cr, dst_rect->x, dst_rect->y, dst_rect->width,
dst_rect->height);
cairo_clip (cr);
@@ -3162,10 +3196,9 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
}
if (FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img != NULL)
- {
- gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img);
- }
+ gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+ FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img);
+
f->output_data.pgtk->icon_bitmap = bitmap_id;
return false;
@@ -3216,7 +3249,7 @@ pgtk_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
if (face)
- pgtk_set_cr_source_with_color (f, face->foreground);
+ pgtk_set_cr_source_with_color (f, face->foreground, false);
cairo_rectangle (cr, x, y0, 1, y1 - y0);
cairo_fill (cr);
@@ -3247,32 +3280,32 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
/* Vertical. */
{
- pgtk_set_cr_source_with_color (f, color_first);
+ pgtk_set_cr_source_with_color (f, color_first, false);
cairo_rectangle (cr, x0, y0, 1, y1 - y0);
cairo_fill (cr);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
cairo_rectangle (cr, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
cairo_fill (cr);
- pgtk_set_cr_source_with_color (f, color_last);
+ pgtk_set_cr_source_with_color (f, color_last, false);
cairo_rectangle (cr, x1 - 1, y0, 1, y1 - y0);
cairo_fill (cr);
}
else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
/* Horizontal. */
{
- pgtk_set_cr_source_with_color (f, color_first);
+ pgtk_set_cr_source_with_color (f, color_first, false);
cairo_rectangle (cr, x0, y0, x1 - x0, 1);
cairo_fill (cr);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
cairo_rectangle (cr, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
cairo_fill (cr);
- pgtk_set_cr_source_with_color (f, color_last);
+ pgtk_set_cr_source_with_color (f, color_last, false);
cairo_rectangle (cr, x0, y1 - 1, x1 - x0, 1);
cairo_fill (cr);
}
else
{
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, false);
cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0);
cairo_fill (cr);
}
@@ -3325,8 +3358,8 @@ pgtk_frame_up_to_date (struct frame *f)
static void
pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window,
- enum scroll_bar_part *part, Lisp_Object * x,
- Lisp_Object * y, Time * timestamp)
+ enum scroll_bar_part *part, Lisp_Object *x,
+ Lisp_Object *y, Time *timestamp)
{
struct frame *f1;
struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
@@ -3335,6 +3368,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window,
GdkDevice *device;
GdkModifierType mask;
GdkWindow *win;
+ bool return_frame_flag = false;
block_input ();
@@ -3348,54 +3382,54 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window,
dpyinfo->last_mouse_scroll_bar = NULL;
- if (gui_mouse_grabbed (dpyinfo))
- {
- /* 1.1. use last_mouse_frame as frame where the pointer is on. */
- f1 = dpyinfo->last_mouse_frame;
- }
+ if (gui_mouse_grabbed (dpyinfo)
+ && (!EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source)))
+ f1 = dpyinfo->last_mouse_frame;
else
{
f1 = *fp;
- /* 1.2. get frame where the pointer is on. */
win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp));
seat = gdk_display_get_default_seat (dpyinfo->gdpy);
device = gdk_seat_get_pointer (seat);
- win =
- gdk_window_get_device_position (win, device, &win_x, &win_y, &mask);
+ win = gdk_window_get_device_position (win, device, &win_x,
+ &win_y, &mask);
if (win != NULL)
f1 = pgtk_any_window_to_frame (win);
else
{
- /* crossing display server? */
f1 = SELECTED_FRAME ();
+
+ if (!FRAME_PGTK_P (f1))
+ f1 = dpyinfo->last_mouse_frame;
+
+ return_frame_flag = EQ (track_mouse, Qdrag_source);
}
}
- /* f1 can be a terminal frame. Bug#50322 */
+ /* F1 can be a terminal frame. (Bug#50322) */
if (f1 == NULL || !FRAME_PGTK_P (f1))
{
unblock_input ();
return;
}
- /* 2. get the display and the device. */
win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1));
- GdkDisplay *gdpy = gdk_window_get_display (win);
- seat = gdk_display_get_default_seat (gdpy);
+ seat = gdk_display_get_default_seat (dpyinfo->gdpy);
device = gdk_seat_get_pointer (seat);
- /* 3. get x, y relative to edit window of the frame. */
- win = gdk_window_get_device_position (win, device, &win_x, &win_y, &mask);
+ win = gdk_window_get_device_position (win, device,
+ &win_x, &win_y, &mask);
if (f1 != NULL)
{
- dpyinfo = FRAME_DISPLAY_INFO (f1);
- remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
+ remember_mouse_glyph (f1, win_x, win_y,
+ &dpyinfo->last_mouse_glyph);
dpyinfo->last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
- *fp = f1;
+ *fp = !return_frame_flag ? f1 : NULL;
XSETINT (*x, win_x);
XSETINT (*y, win_y);
*timestamp = dpyinfo->last_mouse_movement_time;
@@ -3421,10 +3455,10 @@ pgtk_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
{
i = max_fringe_bmp;
max_fringe_bmp = which + 20;
- fringe_bmp =
- (cairo_pattern_t **) xrealloc (fringe_bmp,
- max_fringe_bmp *
- sizeof (cairo_pattern_t *));
+ fringe_bmp
+ = (cairo_pattern_t **) xrealloc (fringe_bmp,
+ max_fringe_bmp *
+ sizeof (cairo_pattern_t *));
while (i < max_fringe_bmp)
fringe_bmp[i++] = 0;
}
@@ -3485,41 +3519,6 @@ pgtk_clip_to_row (struct window *w, struct glyph_row *row,
}
static void
-pgtk_cr_draw_image (struct frame *f, Emacs_GC * gc, cairo_pattern_t * image,
- int src_x, int src_y, int width, int height,
- int dest_x, int dest_y, bool overlay_p)
-{
- cairo_t *cr = pgtk_begin_cr_clip (f);
-
- if (overlay_p)
- cairo_rectangle (cr, dest_x, dest_y, width, height);
- else
- {
- pgtk_set_cr_source_with_gc_background (f, gc);
- cairo_rectangle (cr, dest_x, dest_y, width, height);
- cairo_fill_preserve (cr);
- }
- cairo_translate (cr, dest_x - src_x, dest_y - src_y);
-
- cairo_surface_t *surface;
- cairo_pattern_get_surface (image, &surface);
- cairo_format_t format = cairo_image_surface_get_format (surface);
- if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
- {
- cairo_set_source (cr, image);
- cairo_fill (cr);
- }
- else
- {
- pgtk_set_cr_source_with_gc_foreground (f, gc);
- cairo_clip (cr);
- cairo_mask (cr, image);
- }
-
- pgtk_end_cr_clip (f);
-}
-
-static void
pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
struct draw_fringe_bitmap_params *p)
{
@@ -3533,26 +3532,37 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
if (p->bx >= 0 && !p->overlay_p)
{
- /* In case the same realized face is used for fringes and
- for something displayed in the text (e.g. face `region' on
+ /* In case the same realized face is used for fringes and for
+ something displayed in the text (e.g. face `region' on
mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
+ FillSolid in pgtk_draw_glyph_string_background. */
if (face->stipple)
- {
- fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny);
- }
+ fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny);
else
{
- pgtk_set_cr_source_with_color (f, face->background);
+ pgtk_set_cr_source_with_color (f, face->background, true);
cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny);
cairo_fill (cr);
}
}
- if (p->which && p->which < max_fringe_bmp)
+ if (p->which
+ && p->which < max_fringe_bmp
+ && p->which < max_used_fringe_bitmap)
{
Emacs_GC gcv;
+ if (!fringe_bmp[p->which])
+ {
+ /* This fringe bitmap is known to fringe.c, but lacks the
+ cairo_pattern_t pattern which shadows that bitmap. This
+ is typical to define-fringe-bitmap being called when the
+ selected frame was not a GUI frame, for example, when
+ packages that define fringe bitmaps are loaded by a
+ daemon Emacs. Create the missing pattern now. */
+ gui_define_fringe_bitmap (f, p->which);
+ }
+
gcv.foreground = (p->cursor_p
? (p->overlay_p ? face->background
: FRAME_X_OUTPUT (f)->cursor_color)
@@ -3571,7 +3581,8 @@ static int hourglass_enter_count = 0;
static void
hourglass_cb (struct atimer *timer)
{
- /*NOP*/}
+
+}
static void
pgtk_show_hourglass (struct frame *f)
@@ -3579,7 +3590,9 @@ pgtk_show_hourglass (struct frame *f)
struct pgtk_output *x = FRAME_X_OUTPUT (f);
if (x->hourglass_widget != NULL)
gtk_widget_destroy (x->hourglass_widget);
- x->hourglass_widget = gtk_event_box_new (); /* gtk_event_box is GDK_INPUT_ONLY. */
+
+ /* This creates a GDK_INPUT_ONLY window. */
+ x->hourglass_widget = gtk_event_box_new ();
gtk_widget_set_has_window (x->hourglass_widget, true);
gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (f)), x->hourglass_widget, 0, 0);
gtk_widget_show (x->hourglass_widget);
@@ -3588,17 +3601,16 @@ pgtk_show_hourglass (struct frame *f)
gdk_window_set_cursor (gtk_widget_get_window (x->hourglass_widget),
x->hourglass_cursor);
- /* For cursor animation, we receive signals, set pending_signals, and dispatch. */
+ /* For cursor animation, we receive signals, set pending_signals,
+ and wait for the signal handler to run. */
if (hourglass_enter_count++ == 0)
{
struct timespec ts = make_timespec (0, 50 * 1000 * 1000);
if (hourglass_atimer != NULL)
cancel_atimer (hourglass_atimer);
- hourglass_atimer =
- start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL);
+ hourglass_atimer
+ = start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL);
}
-
- /* Cursor frequently stops animation. gtk's bug? */
}
static void
@@ -3659,35 +3671,19 @@ static struct redisplay_interface pgtk_redisplay_interface = {
pgtk_default_font_parameter,
};
-static void
-pgtk_redraw_scroll_bars (struct frame *f)
-{
-}
-
void
pgtk_clear_frame (struct frame *f)
-/* --------------------------------------------------------------------------
- External (hook): Erase the entire frame
- -------------------------------------------------------------------------- */
{
- /* comes on initial frame because we have
- after-make-frame-functions = select-frame */
if (!FRAME_DEFAULT_FACE (f))
return;
- /* mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); */
+ mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
block_input ();
-
pgtk_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
-
- /* as of 2006/11 or so this is now needed */
- pgtk_redraw_scroll_bars (f);
unblock_input ();
}
-/* Invert the middle quarter of the frame for .15 sec. */
-
static void
recover_from_visible_bell (struct atimer *timer)
{
@@ -3703,83 +3699,89 @@ recover_from_visible_bell (struct atimer *timer)
FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
}
+/* Invert the middle quarter of the frame for .15 sec. */
+
static void
pgtk_flash (struct frame *f)
{
+ cairo_surface_t *surface_orig, *surface;
+ cairo_t *cr;
+ int width, height, flash_height, flash_left, flash_right;
+ struct timespec delay;
+
+ if (!FRAME_CR_CONTEXT (f))
+ return;
+
block_input ();
- {
- cairo_surface_t *surface_orig = FRAME_CR_SURFACE (f);
+ surface_orig = FRAME_CR_SURFACE (f);
- int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
- int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
- cairo_surface_t *surface =
- cairo_surface_create_similar (surface_orig, CAIRO_CONTENT_COLOR_ALPHA,
- width, height);
+ width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
+ height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
+ surface = cairo_surface_create_similar (surface_orig,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ width, height);
- cairo_t *cr = cairo_create (surface);
- cairo_set_source_surface (cr, surface_orig, 0, 0);
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_clip (cr);
- cairo_paint (cr);
+ cr = cairo_create (surface);
+ cairo_set_source_surface (cr, surface_orig, 0, 0);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_clip (cr);
+ cairo_paint (cr);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
+ /* Get the height not including a menu bar widget. */
+ height = FRAME_PIXEL_HEIGHT (f);
+ /* Height of each line to flash. */
+ flash_height = FRAME_LINE_HEIGHT (f);
+ /* These will be the left and right margins of the rectangles. */
+ flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+ flash_right = (FRAME_PIXEL_WIDTH (f)
+ - FRAME_INTERNAL_BORDER_WIDTH (f));
+ width = flash_right - flash_left;
+
+ /* If window is tall, flash top and bottom line. */
+ if (height > 3 * FRAME_LINE_HEIGHT (f))
+ {
+ cairo_rectangle (cr,
+ flash_left,
+ (FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_TOP_MARGIN_HEIGHT (f)),
+ width, flash_height);
+ cairo_fill (cr);
+
+ cairo_rectangle (cr,
+ flash_left,
+ (height - flash_height
+ - FRAME_INTERNAL_BORDER_WIDTH (f)),
+ width, flash_height);
+ cairo_fill (cr);
+ }
+ else
{
- /* Get the height not including a menu bar widget. */
- int height = FRAME_PIXEL_HEIGHT (f);
- /* Height of each line to flash. */
- int flash_height = FRAME_LINE_HEIGHT (f);
- /* These will be the left and right margins of the rectangles. */
- int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
- int flash_right =
- FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
- int width = flash_right - flash_left;
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- cairo_rectangle (cr,
- flash_left,
- (FRAME_INTERNAL_BORDER_WIDTH (f)
- + FRAME_TOP_MARGIN_HEIGHT (f)),
- width, flash_height);
- cairo_fill (cr);
+ /* If it is short, flash it all. */
+ cairo_rectangle (cr,
+ flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ cairo_fill (cr);
+ }
- cairo_rectangle (cr,
- flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- cairo_fill (cr);
- }
- else
- {
- /* If it is short, flash it all. */
- cairo_rectangle (cr,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
- cairo_fill (cr);
- }
+ FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface;
- FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface;
- {
- struct timespec delay = make_timespec (0, 50 * 1000 * 1000);
- if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
- {
- cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell);
- FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
- }
- FRAME_X_OUTPUT (f)->atimer_visible_bell =
- start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f);
- }
+ delay = make_timespec (0, 50 * 1000 * 1000);
+ if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
+ {
+ cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell);
+ FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
}
- cairo_destroy (cr);
- }
+ FRAME_X_OUTPUT (f)->atimer_visible_bell
+ = start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f);
+
+ cairo_destroy (cr);
unblock_input ();
}
@@ -3861,8 +3863,9 @@ pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
EVENT_INIT (inev.ie);
- inev.ie.kind =
- horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : SCROLL_BAR_CLICK_EVENT;
+ inev.ie.kind = (horizontal
+ ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+ : SCROLL_BAR_CLICK_EVENT);
inev.ie.frame_or_window = window;
inev.ie.arg = Qnil;
inev.ie.timestamp = 0;
@@ -3894,28 +3897,21 @@ xg_scroll_callback (GtkRange * range,
switch (scroll)
{
case GTK_SCROLL_JUMP:
-#if 0
- /* Buttons 1 2 or 3 must be grabbed. */
- if (FRAME_DISPLAY_INFO (f)->grabbed != 0
- && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
-#endif
- {
- if (bar->horizontal)
- {
- part = scroll_bar_horizontal_handle;
- whole = (int) (gtk_adjustment_get_upper (adj) -
- gtk_adjustment_get_page_size (adj));
- portion = min ((int) value, whole);
- bar->dragging = portion;
- }
- else
- {
- part = scroll_bar_handle;
- whole = gtk_adjustment_get_upper (adj) -
- gtk_adjustment_get_page_size (adj);
- portion = min ((int) value, whole);
- bar->dragging = portion;
- }
+ if (bar->horizontal)
+ {
+ part = scroll_bar_horizontal_handle;
+ whole = (int) (gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj));
+ portion = min ((int) value, whole);
+ bar->dragging = portion;
+ }
+ else
+ {
+ part = scroll_bar_handle;
+ whole = gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj);
+ portion = min ((int) value, whole);
+ bar->dragging = portion;
}
break;
case GTK_SCROLL_STEP_BACKWARD:
@@ -3977,7 +3973,7 @@ xg_end_scroll_callback (GtkWidget * widget,
and X window of the scroll bar in BAR. */
static void
-x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
+pgtk_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
{
const char *scroll_bar_name = SCROLL_BAR_NAME;
@@ -3988,8 +3984,8 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
}
static void
-x_create_horizontal_toolkit_scroll_bar (struct frame *f,
- struct scroll_bar *bar)
+pgtk_create_horizontal_toolkit_scroll_bar (struct frame *f,
+ struct scroll_bar *bar)
{
const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
@@ -4004,30 +4000,28 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f,
displaying PORTION out of a whole WHOLE, and our position POSITION. */
static void
-x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion,
- int position, int whole)
+pgtk_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion,
+ int position, int whole)
{
xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
}
static void
-x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
- int portion, int position,
- int whole)
+pgtk_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
+ int portion, int position,
+ int whole)
{
xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
}
-
-
/* Create a scroll bar and return the scroll bar vector for it. W is
the Emacs window on which to create the scroll bar. TOP, LEFT,
WIDTH and HEIGHT are the pixel coordinates and dimensions of the
scroll bar. */
static struct scroll_bar *
-x_scroll_bar_create (struct window *w, int top, int left,
- int width, int height, bool horizontal)
+pgtk_scroll_bar_create (struct window *w, int top, int left,
+ int width, int height, bool horizontal)
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar
@@ -4037,9 +4031,9 @@ x_scroll_bar_create (struct window *w, int top, int left,
block_input ();
if (horizontal)
- x_create_horizontal_toolkit_scroll_bar (f, bar);
+ pgtk_create_horizontal_toolkit_scroll_bar (f, bar);
else
- x_create_toolkit_scroll_bar (f, bar);
+ pgtk_create_toolkit_scroll_bar (f, bar);
XSETWINDOW (bar->window, w);
bar->top = top;
@@ -4077,7 +4071,7 @@ x_scroll_bar_create (struct window *w, int top, int left,
nil. */
static void
-x_scroll_bar_remove (struct scroll_bar *bar)
+pgtk_scroll_bar_remove (struct scroll_bar *bar)
{
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
block_input ();
@@ -4125,7 +4119,7 @@ pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole,
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false);
+ bar = pgtk_scroll_bar_create (w, top, left, width, max (height, 1), false);
}
else
{
@@ -4165,13 +4159,12 @@ pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole,
unblock_input ();
}
- x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+ pgtk_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
XSETVECTOR (barobj, bar);
wset_vertical_scroll_bar (w, barobj);
}
-
static void
pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole,
int position)
@@ -4203,7 +4196,7 @@ pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole,
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, left, width, height, true);
+ bar = pgtk_scroll_bar_create (w, top, left, width, height, true);
}
else
{
@@ -4246,7 +4239,7 @@ pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole,
unblock_input ();
}
- x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
+ pgtk_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
XSETVECTOR (barobj, bar);
wset_horizontal_scroll_bar (w, barobj);
@@ -4286,7 +4279,6 @@ pgtk_condemn_scroll_bars (struct frame *frame)
}
}
-
/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
Note that WINDOW isn't necessarily condemned at all. */
@@ -4390,7 +4382,7 @@ pgtk_judge_scroll_bars (struct frame *f)
{
struct scroll_bar *b = XSCROLL_BAR (bar);
- x_scroll_bar_remove (b);
+ pgtk_scroll_bar_remove (b);
next = b->next;
b->next = b->prev = Qnil;
@@ -4471,15 +4463,22 @@ pgtk_delete_terminal (struct terminal *terminal)
g_clear_object (&dpyinfo->vertical_scroll_bar_cursor);
g_clear_object (&dpyinfo->horizontal_scroll_bar_cursor);
g_clear_object (&dpyinfo->invisible_cursor);
- if (dpyinfo->last_click_event != NULL) {
- gdk_event_free (dpyinfo->last_click_event);
- dpyinfo->last_click_event = NULL;
- }
+ if (dpyinfo->last_click_event != NULL)
+ {
+ gdk_event_free (dpyinfo->last_click_event);
+ dpyinfo->last_click_event = NULL;
+ }
+ /* Disconnect these handlers before the display closes so
+ useless removal signals don't fire. */
+ g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
+ G_CALLBACK (pgtk_seat_added_cb),
+ dpyinfo);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
+ G_CALLBACK (pgtk_seat_removed_cb),
+ dpyinfo);
xg_display_close (dpyinfo->gdpy);
- /* Do not close the connection here because it's already closed
- by X(t)CloseDisplay (Bug#18403). */
dpyinfo->gdpy = NULL;
}
@@ -4503,7 +4502,7 @@ pgtk_query_frame_background_color (struct frame *f, Emacs_Color * bgcolor)
}
static void
-pgtk_free_pixmap (struct frame *_f, Emacs_Pixmap pixmap)
+pgtk_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
{
if (pixmap)
{
@@ -4527,17 +4526,18 @@ pgtk_focus_frame (struct frame *f, bool noactivate)
}
}
-
static void
-set_opacity_recursively (GtkWidget * w, gpointer data)
+set_opacity_recursively (GtkWidget *w, gpointer data)
{
gtk_widget_set_opacity (w, *(double *) data);
+
if (GTK_IS_CONTAINER (w))
- gtk_container_foreach (GTK_CONTAINER (w), set_opacity_recursively, data);
+ gtk_container_foreach (GTK_CONTAINER (w),
+ set_opacity_recursively, data);
}
static void
-x_set_frame_alpha (struct frame *f)
+pgtk_set_frame_alpha (struct frame *f)
{
struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
double alpha = 1.0;
@@ -4561,22 +4561,6 @@ x_set_frame_alpha (struct frame *f)
else if (alpha < alpha_min && alpha_min <= 1.0)
alpha = alpha_min;
-#if 0
- /* If there is a parent from the window manager, put the property there
- also, to work around broken window managers that fail to do that.
- Do this unconditionally as this function is called on reparent when
- alpha has not changed on the frame. */
-
- if (!FRAME_PARENT_FRAME (f))
- {
- Window parent = x_find_topmost_parent (f);
- if (parent != None)
- XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *) &opac, 1);
- }
-#endif
-
set_opacity_recursively (FRAME_WIDGET (f), &alpha);
/* without this, blending mode is strange on wayland. */
gtk_widget_queue_resize_no_redraw (FRAME_WIDGET (f));
@@ -4585,22 +4569,13 @@ x_set_frame_alpha (struct frame *f)
static void
frame_highlight (struct frame *f)
{
- /* We used to only do this if Vx_no_window_manager was non-nil, but
- the ICCCM (section 4.1.6) says that the window's border pixmap
- and border pixel are window attributes which are "private to the
- client", so we can always change it to whatever we want. */
block_input ();
- /* I recently started to get errors in this XSetWindowBorder, depending on
- the window-manager in use, tho something more is at play since I've been
- using that same window-manager binary for ever. Let's not crash just
- because of this (bug#9310). */
-
GtkWidget *w = FRAME_WIDGET (f);
- char *css =
- g_strdup_printf ("decoration { border: solid %dpx #%06x; }",
- f->border_width,
- (unsigned int) FRAME_X_OUTPUT (f)->border_pixel & 0x00ffffff);
+ char *css = g_strdup_printf ("decoration { border: solid %dpx #%06x; }",
+ f->border_width,
+ ((unsigned int) FRAME_X_OUTPUT (f)->border_pixel
+ & 0x00ffffff));
GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
GtkCssProvider *css_provider = gtk_css_provider_new ();
@@ -4619,33 +4594,32 @@ frame_highlight (struct frame *f)
unblock_input ();
gui_update_cursor (f, true);
- x_set_frame_alpha (f);
+ pgtk_set_frame_alpha (f);
}
static void
frame_unhighlight (struct frame *f)
{
- /* We used to only do this if Vx_no_window_manager was non-nil, but
- the ICCCM (section 4.1.6) says that the window's border pixmap
- and border pixel are window attributes which are "private to the
- client", so we can always change it to whatever we want. */
+ GtkWidget *w;
+ char *css;
+ GtkStyleContext *ctxt;
+ GtkCssProvider *css_provider, *old;
+
block_input ();
- /* Same as above for XSetWindowBorder (bug#9310). */
- GtkWidget *w = FRAME_WIDGET (f);
+ w = FRAME_WIDGET (f);
- char *css =
- g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }",
- f->border_width);
+ css = g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }",
+ f->border_width);
- GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
- GtkCssProvider *css_provider = gtk_css_provider_new ();
+ ctxt = gtk_widget_get_style_context (w);
+ css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
g_free (css);
- GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
+ old = FRAME_X_OUTPUT (f)->border_color_css_provider;
FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
if (old != NULL)
{
@@ -4655,7 +4629,7 @@ frame_unhighlight (struct frame *f)
unblock_input ();
gui_update_cursor (f, true);
- x_set_frame_alpha (f);
+ pgtk_set_frame_alpha (f);
}
@@ -4694,16 +4668,15 @@ pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo)
the appropriate X display info. */
static void
-XTframe_rehighlight (struct frame *frame)
+pgtk_frame_rehighlight_hook (struct frame *frame)
{
pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
}
-
-/* Toggle mouse pointer visibility on frame F by using invisible cursor. */
-
+/* Set whether or not the mouse pointer should be visible on frame
+ F. */
static void
-x_toggle_visible_pointer (struct frame *f, bool invisible)
+pgtk_toggle_invisible_pointer (struct frame *f, bool invisible)
{
Emacs_Cursor cursor;
if (invisible)
@@ -4713,22 +4686,10 @@ x_toggle_visible_pointer (struct frame *f, bool invisible)
gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
cursor);
f->pointer_invisible = invisible;
-}
-static void
-x_setup_pointer_blanking (struct pgtk_display_info *dpyinfo)
-{
- dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer;
- dpyinfo->invisible_cursor =
- gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_BLANK_CURSOR);
-}
-
-static void
-XTtoggle_invisible_pointer (struct frame *f, bool invisible)
-{
- block_input ();
- FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
- unblock_input ();
+ /* This is needed to make the pointer visible upon receiving a
+ motion notify event. */
+ gdk_display_flush (FRAME_X_DISPLAY (f));
}
/* The focus has changed. Update the frames as necessary to reflect
@@ -4738,7 +4699,7 @@ XTtoggle_invisible_pointer (struct frame *f, bool invisible)
Lisp code can tell when the switch took place by examining the events. */
static void
-x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame)
+pgtk_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame)
{
struct frame *old_focus = dpyinfo->x_focus_frame;
/* doesn't work on wayland */
@@ -4774,9 +4735,6 @@ pgtk_buffer_flipping_unblocked_hook (struct frame *f)
static struct terminal *
pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
-/* --------------------------------------------------------------------------
- Set up use of Gtk before we make the first connection.
- -------------------------------------------------------------------------- */
{
struct terminal *terminal;
@@ -4787,13 +4745,13 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
terminal->clear_frame_hook = pgtk_clear_frame;
terminal->ring_bell_hook = pgtk_ring_bell;
- terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
+ terminal->toggle_invisible_pointer_hook = pgtk_toggle_invisible_pointer;
terminal->update_begin_hook = pgtk_update_begin;
terminal->update_end_hook = pgtk_update_end;
terminal->read_socket_hook = pgtk_read_socket;
terminal->frame_up_to_date_hook = pgtk_frame_up_to_date;
terminal->mouse_position_hook = pgtk_mouse_position;
- terminal->frame_rehighlight_hook = XTframe_rehighlight;
+ terminal->frame_rehighlight_hook = pgtk_frame_rehighlight_hook;
terminal->buffer_flipping_unblocked_hook = pgtk_buffer_flipping_unblocked_hook;
terminal->frame_raise_lower_hook = pgtk_frame_raise_lower;
terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible;
@@ -4801,14 +4759,14 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
terminal->menu_show_hook = pgtk_menu_show;
terminal->activate_menubar_hook = pgtk_activate_menubar;
terminal->popup_dialog_hook = pgtk_popup_dialog;
- terminal->change_tab_bar_height_hook = x_change_tab_bar_height;
+ terminal->change_tab_bar_height_hook = pgtk_change_tab_bar_height;
terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar;
terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar;
terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars;
terminal->redeem_scroll_bar_hook = pgtk_redeem_scroll_bar;
terminal->judge_scroll_bars_hook = pgtk_judge_scroll_bars;
terminal->get_string_resource_hook = pgtk_get_string_resource;
- terminal->delete_frame_hook = x_destroy_window;
+ terminal->delete_frame_hook = pgtk_destroy_window;
terminal->delete_terminal_hook = pgtk_delete_terminal;
terminal->query_frame_background_color = pgtk_query_frame_background_color;
terminal->defined_color_hook = pgtk_defined_color;
@@ -4816,16 +4774,17 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
terminal->set_bitmap_icon_hook = pgtk_bitmap_icon;
terminal->implicit_set_name_hook = pgtk_implicitly_set_name;
terminal->iconify_frame_hook = pgtk_iconify_frame;
- terminal->set_scroll_bar_default_width_hook =
- pgtk_set_scroll_bar_default_width;
- terminal->set_scroll_bar_default_height_hook =
- pgtk_set_scroll_bar_default_height;
+ terminal->set_scroll_bar_default_width_hook
+ = pgtk_set_scroll_bar_default_width;
+ terminal->set_scroll_bar_default_height_hook
+ = pgtk_set_scroll_bar_default_height;
terminal->set_window_size_hook = pgtk_set_window_size;
terminal->query_colors = pgtk_query_colors;
- terminal->get_focus_frame = x_get_focus_frame;
+ terminal->get_focus_frame = pgtk_get_focus_frame;
terminal->focus_frame_hook = pgtk_focus_frame;
- terminal->set_frame_offset_hook = x_set_offset;
+ terminal->set_frame_offset_hook = pgtk_set_offset;
terminal->free_pixmap = pgtk_free_pixmap;
+ terminal->toolkit_position_hook = pgtk_toolkit_position;
/* Other hooks are NULL by default. */
@@ -4840,7 +4799,7 @@ struct pgtk_window_is_of_frame_recursive_t
};
static void
-pgtk_window_is_of_frame_recursive (GtkWidget * widget, gpointer data)
+pgtk_window_is_of_frame_recursive (GtkWidget *widget, gpointer data)
{
struct pgtk_window_is_of_frame_recursive_t *datap = data;
@@ -4856,14 +4815,13 @@ pgtk_window_is_of_frame_recursive (GtkWidget * widget, gpointer data)
return;
}
- if (GTK_IS_CONTAINER (widget)) {
+ if (GTK_IS_CONTAINER (widget))
gtk_container_foreach (GTK_CONTAINER (widget),
pgtk_window_is_of_frame_recursive, datap);
- }
}
static bool
-pgtk_window_is_of_frame (struct frame *f, GdkWindow * window)
+pgtk_window_is_of_frame (struct frame *f, GdkWindow *window)
{
struct pgtk_window_is_of_frame_recursive_t data;
data.window = window;
@@ -4876,7 +4834,7 @@ pgtk_window_is_of_frame (struct frame *f, GdkWindow * window)
/* Like x_window_to_frame but also compares the window with the widget's
windows. */
static struct frame *
-pgtk_any_window_to_frame (GdkWindow * window)
+pgtk_any_window_to_frame (GdkWindow *window)
{
Lisp_Object tail, frame;
struct frame *f, *found = NULL;
@@ -4885,16 +4843,16 @@ pgtk_any_window_to_frame (GdkWindow * window)
return NULL;
FOR_EACH_FRAME (tail, frame)
- {
- if (found)
- break;
- f = XFRAME (frame);
- if (FRAME_PGTK_P (f))
- {
- if (pgtk_window_is_of_frame (f, window))
- found = f;
- }
- }
+ {
+ if (found)
+ break;
+ f = XFRAME (frame);
+ if (FRAME_PGTK_P (f))
+ {
+ if (pgtk_window_is_of_frame (f, window))
+ found = f;
+ }
+ }
return found;
}
@@ -4902,7 +4860,6 @@ pgtk_any_window_to_frame (GdkWindow * window)
static gboolean
pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
{
-#if GTK_CHECK_VERSION (3, 18, 0)
struct frame *f;
union buffered_input_event inev;
GtkWidget *frame_widget;
@@ -4932,22 +4889,23 @@ pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
make_float (event->touchpad_pinch.angle_delta));
inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
event->touchpad_pinch.state);
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
evq_enqueue (&inev);
}
return TRUE;
}
-#endif
return FALSE;
}
static void
pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y,
- int width, int height)
+ int width, int height, bool respect_alpha_background)
{
cairo_t *cr;
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, color);
+ pgtk_set_cr_source_with_color (f, color, respect_alpha_background);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
pgtk_end_cr_clip (f);
@@ -5001,7 +4959,7 @@ pgtk_clear_under_internal_border (struct frame *f)
}
static gboolean
-pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data)
+pgtk_handle_draw (GtkWidget *widget, cairo_t *cr, gpointer *data)
{
struct frame *f;
@@ -5027,19 +4985,11 @@ pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data)
}
static void
-size_allocate (GtkWidget * widget, GtkAllocation * alloc,
+size_allocate (GtkWidget *widget, GtkAllocation *alloc,
gpointer user_data)
{
struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
- /* Between a frame is created and not shown, size is allocated and
- * this handler is called. When that, since the widget's window is
- * NULL, we can't get f, pgtk_cr_update_surface_desired_size is not
- * called, and its size is 0x0. That causes empty frame.
- *
- * Fortunately since we know f in pgtk_set_event_handler, we can get
- * it through user_data;
- */
if (!f)
f = user_data;
@@ -5051,88 +5001,8 @@ size_allocate (GtkWidget * widget, GtkAllocation * alloc,
}
static void
-x_find_modifier_meanings (struct pgtk_display_info *dpyinfo)
-{
- GdkDisplay *gdpy = dpyinfo->gdpy;
- GdkKeymap *keymap = gdk_keymap_get_for_display (gdpy);
- GdkModifierType state = GDK_META_MASK;
- gboolean r = gdk_keymap_map_virtual_modifiers (keymap, &state);
- if (r)
- {
- /* Meta key exists. */
- if (state == GDK_META_MASK)
- {
- dpyinfo->meta_mod_mask = GDK_MOD1_MASK; /* maybe this is meta. */
- dpyinfo->alt_mod_mask = 0;
- }
- else
- {
- dpyinfo->meta_mod_mask = state & ~GDK_META_MASK;
- if (dpyinfo->meta_mod_mask == GDK_MOD1_MASK)
- dpyinfo->alt_mod_mask = 0;
- else
- dpyinfo->alt_mod_mask = GDK_MOD1_MASK;
- }
- }
- else
- {
- dpyinfo->meta_mod_mask = GDK_MOD1_MASK;
- dpyinfo->alt_mod_mask = 0;
- }
-
- state = GDK_SUPER_MASK;
- r = gdk_keymap_map_virtual_modifiers (keymap, &state);
- if (r)
- {
- /* Super key exists. */
- if (state == GDK_SUPER_MASK)
- {
- dpyinfo->super_mod_mask = GDK_MOD4_MASK; /* maybe this is super. */
- }
- else
- {
- dpyinfo->super_mod_mask = state & ~GDK_SUPER_MASK;
- }
- }
- else
- {
- dpyinfo->super_mod_mask = GDK_MOD4_MASK;
- }
-
- state = GDK_HYPER_MASK;
- r = gdk_keymap_map_virtual_modifiers (keymap, &state);
- if (r)
- {
- /* Hyper key exists. */
- if (state == GDK_HYPER_MASK)
- {
- dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; /* maybe this is hyper. */
- }
- else
- {
- dpyinfo->hyper_mod_mask = state & ~GDK_HYPER_MASK;
- }
- }
- else
- {
- dpyinfo->hyper_mod_mask = GDK_MOD3_MASK;
- }
-
- /* If xmodmap says:
- * $ xmodmap | grep mod4
- * mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf)
- * then, when mod4 is pressed, both of super and hyper are recognized ON.
- * Maybe many people have such configuration, and they don't like such behavior,
- * so I disable hyper if such configuration is detected.
- */
- if (dpyinfo->hyper_mod_mask == dpyinfo->super_mod_mask)
- dpyinfo->hyper_mod_mask = 0;
-}
-
-static void
-get_modifier_values (int *mod_ctrl,
- int *mod_meta,
- int *mod_alt, int *mod_hyper, int *mod_super)
+get_modifier_values (int *mod_ctrl, int *mod_meta, int *mod_alt,
+ int *mod_hyper, int *mod_super)
{
Lisp_Object tem;
@@ -5177,14 +5047,13 @@ pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state)
mod |= shift_modifier;
if (state & GDK_CONTROL_MASK)
mod |= mod_ctrl;
- if (state & dpyinfo->meta_mod_mask)
+ if (state & GDK_META_MASK || state & GDK_MOD1_MASK)
mod |= mod_meta;
- if (state & dpyinfo->alt_mod_mask)
- mod |= mod_alt;
- if (state & dpyinfo->super_mod_mask)
+ if (state & GDK_SUPER_MASK)
mod |= mod_super;
- if (state & dpyinfo->hyper_mod_mask)
+ if (state & GDK_HYPER_MASK)
mod |= mod_hyper;
+
return mod;
}
@@ -5202,18 +5071,16 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state)
&mod_super);
mask = 0;
- if (state & mod_alt)
- mask |= dpyinfo->alt_mod_mask;
if (state & mod_super)
- mask |= dpyinfo->super_mod_mask;
+ mask |= GDK_SUPER_MASK;
if (state & mod_hyper)
- mask |= dpyinfo->hyper_mod_mask;
+ mask |= GDK_HYPER_MASK;
if (state & shift_modifier)
mask |= GDK_SHIFT_MASK;
if (state & mod_ctrl)
mask |= GDK_CONTROL_MASK;
if (state & mod_meta)
- mask |= dpyinfo->meta_mod_mask;
+ mask |= GDK_MOD1_MASK;
return mask;
}
@@ -5229,11 +5096,11 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state)
void
-pgtk_enqueue_string (struct frame *f, gchar * str)
+pgtk_enqueue_string (struct frame *f, gchar *str)
{
- gunichar *ustr;
+ gunichar *ustr, *uptr;
- ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
+ uptr = ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
if (ustr == NULL)
return;
for (; *ustr != 0; ustr++)
@@ -5252,6 +5119,7 @@ pgtk_enqueue_string (struct frame *f, gchar * str)
evq_enqueue (&inev);
}
+ g_free (uptr);
}
void
@@ -5269,20 +5137,15 @@ pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit)
}
static gboolean
-key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
+key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
{
- struct coding_system coding;
union buffered_input_event inev;
ptrdiff_t nbytes = 0;
Mouse_HLInfo *hlinfo;
+ struct frame *f;
- USE_SAFE_ALLOCA;
-
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
EVENT_INIT (inev.ie);
- inev.ie.kind = NO_EVENT;
- inev.ie.arg = Qnil;
-
- struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
hlinfo = MOUSE_HL_INFO (f);
/* If mouse-highlight is an integer, input clears out
@@ -5295,20 +5158,6 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
if (f != 0)
{
- /* While super is pressed, gtk_im_context_filter_keypress() always process the
- * key events ignoring super.
- * As a work around, don't call it while super or hyper are pressed...
- */
- struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- if (!(event->key.state & (dpyinfo->super_mod_mask | dpyinfo->hyper_mod_mask)))
- {
- if (pgtk_im_filter_keypress (f, &event->key))
- return TRUE;
- }
- }
-
- if (f != 0)
- {
guint keysym, orig_keysym;
/* al%imercury@uunet.uu.net says that making this 81
instead of 80 fixed a bug whereby meta chars made
@@ -5325,13 +5174,22 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
unsigned char *copy_bufptr = copy_buffer;
int copy_bufsiz = sizeof (copy_buffer);
int modifiers;
- Lisp_Object coding_system = Qlatin_1;
Lisp_Object c;
- guint state = event->key.state;
+ guint state;
+
+ state = event->key.state;
+
+ /* While super is pressed, the input method will always always
+ resend the key events ignoring super. As a workaround, don't
+ filter key events with super or hyper pressed. */
+ if (!(event->key.state & (GDK_SUPER_MASK | GDK_HYPER_MASK)))
+ {
+ if (pgtk_im_filter_keypress (f, &event->key))
+ return TRUE;
+ }
- state |=
- pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f),
- extra_keyboard_modifiers);
+ state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f),
+ extra_keyboard_modifiers);
modifiers = state;
/* This will have to go some day... */
@@ -5363,6 +5221,9 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
{
inev.ie.kind = ASCII_KEYSTROKE_EVENT;
inev.ie.code = keysym;
+
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
goto done;
}
@@ -5374,6 +5235,9 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
else
inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
inev.ie.code = keysym & 0xFFFFFF;
+
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
goto done;
}
@@ -5386,6 +5250,9 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = XFIXNAT (c);
+
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
goto done;
}
@@ -5449,9 +5316,6 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
|| (orig_keysym & (1 << 28))
|| (keysym != GDK_KEY_VoidSymbol && nbytes == 0))
&& !(event->key.is_modifier
- /* Gtk's modifier keys are different from Xlib's ones.
- * I need to exclude them.
- */
|| IsModifierKey (orig_keysym)
/* The symbols from GDK_KEY_ISO_Lock
to GDK_KEY_ISO_Last_Group_Lock
@@ -5464,68 +5328,21 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
#endif
))
{
- STORE_KEYSYM_FOR_DEBUG (keysym);
/* make_lispy_event will convert this to a symbolic
key. */
inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
inev.ie.code = keysym;
+
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
goto done;
}
- { /* Raw bytes, not keysym. */
- ptrdiff_t i;
- int nchars, len;
-
- for (i = 0, nchars = 0; i < nbytes; i++)
- {
- if (ASCII_CHAR_P (copy_bufptr[i]))
- nchars++;
- STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
- }
-
- if (nchars < nbytes)
- {
- /* Decode the input data. */
-
- /* The input should be decoded with locale `coding_system'. */
- if (!NILP (Vlocale_coding_system))
- coding_system = Vlocale_coding_system;
- setup_coding_system (coding_system, &coding);
- coding.src_multibyte = false;
- coding.dst_multibyte = true;
- /* The input is converted to events, thus we can't
- handle composition. Anyway, there's no XIM that
- gives us composition information. */
- coding.common_flags &= ~CODING_ANNOTATION_MASK;
-
- SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, nbytes);
- coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = coding.destination;
- }
-
- /* Convert the input data to a sequence of
- character events. */
- for (i = 0; i < nbytes; i += len)
- {
- int ch;
- if (nchars == nbytes)
- ch = copy_bufptr[i], len = 1;
- else
- ch = string_char_and_length (copy_bufptr + i, &len);
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = ch;
- evq_enqueue (&inev);
- }
-
- /* count += nchars; */
-
- inev.ie.kind = NO_EVENT; /* Already stored above. */
+ {
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
if (keysym == GDK_KEY_VoidSymbol)
goto done;
@@ -5537,11 +5354,8 @@ done:
{
XSETFRAME (inev.ie.frame_or_window, f);
evq_enqueue (&inev);
- /* count++; */
}
- SAFE_FREE ();
-
return TRUE;
}
@@ -5559,6 +5373,7 @@ configure_event (GtkWidget *widget,
gpointer *user_data)
{
struct frame *f = pgtk_any_window_to_frame (event->configure.window);
+
if (f && widget == FRAME_GTK_OUTER_WIDGET (f))
{
if (any_help_event_p)
@@ -5571,6 +5386,15 @@ configure_event (GtkWidget *widget,
help_echo_string = Qnil;
gen_help_event (Qnil, frame, Qnil, Qnil, 0);
}
+
+ if (f->win_gravity == NorthWestGravity)
+ gtk_window_get_position (GTK_WINDOW (widget),
+ &f->left_pos, &f->top_pos);
+ else
+ {
+ f->top_pos = event->configure.y;
+ f->left_pos = event->configure.x;
+ }
}
return FALSE;
}
@@ -5603,9 +5427,9 @@ map_event (GtkWidget *widget,
/* The `z-group' is reset every time a frame becomes
invisible. Handle this here. */
if (FRAME_Z_GROUP (f) == z_group_above)
- x_set_z_group (f, Qabove, Qnil);
+ pgtk_set_z_group (f, Qabove, Qnil);
else if (FRAME_Z_GROUP (f) == z_group_below)
- x_set_z_group (f, Qbelow, Qnil);
+ pgtk_set_z_group (f, Qbelow, Qnil);
}
SET_FRAME_VISIBLE (f, 1);
@@ -5630,15 +5454,18 @@ window_state_event (GtkWidget *widget,
gpointer *user_data)
{
struct frame *f = pgtk_any_window_to_frame (event->window_state.window);
+ GdkWindowState new_state;
union buffered_input_event inev;
+ new_state = event->window_state.new_window_state;
+
EVENT_INIT (inev.ie);
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
if (f)
{
- if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED)
+ if (new_state & GDK_WINDOW_STATE_FOCUSED)
{
if (FRAME_ICONIFIED_P (f))
{
@@ -5654,6 +5481,38 @@ window_state_event (GtkWidget *widget,
}
}
+ if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
+ store_frame_param (f, Qfullscreen, Qfullboth);
+ else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
+ store_frame_param (f, Qfullscreen, Qmaximized);
+ else if ((new_state & GDK_WINDOW_STATE_TOP_TILED)
+ && (new_state & GDK_WINDOW_STATE_BOTTOM_TILED)
+ && !(new_state & GDK_WINDOW_STATE_TOP_RESIZABLE)
+ && !(new_state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE))
+ store_frame_param (f, Qfullscreen, Qfullheight);
+ else if ((new_state & GDK_WINDOW_STATE_LEFT_TILED)
+ && (new_state & GDK_WINDOW_STATE_RIGHT_TILED)
+ && !(new_state & GDK_WINDOW_STATE_LEFT_RESIZABLE)
+ && !(new_state & GDK_WINDOW_STATE_RIGHT_RESIZABLE))
+ store_frame_param (f, Qfullscreen, Qfullwidth);
+ else
+ store_frame_param (f, Qfullscreen, Qnil);
+
+ if (new_state & GDK_WINDOW_STATE_ICONIFIED)
+ SET_FRAME_ICONIFIED (f, true);
+ else
+ {
+ FRAME_X_OUTPUT (f)->has_been_visible = true;
+ inev.ie.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ SET_FRAME_ICONIFIED (f, false);
+ }
+
+ if (new_state & GDK_WINDOW_STATE_STICKY)
+ store_frame_param (f, Qsticky, Qt);
+ else
+ store_frame_param (f, Qsticky, Qnil);
+
if (inev.ie.kind != NO_EVENT)
evq_enqueue (&inev);
return FALSE;
@@ -5691,15 +5550,15 @@ delete_event (GtkWidget *widget,
a FOCUS_IN_EVENT into *BUFP. */
static void
-x_focus_changed (gboolean is_enter, int state,
- struct pgtk_display_info *dpyinfo, struct frame *frame,
- union buffered_input_event *bufp)
+pgtk_focus_changed (gboolean is_enter, int state,
+ struct pgtk_display_info *dpyinfo, struct frame *frame,
+ union buffered_input_event *bufp)
{
if (is_enter)
{
if (dpyinfo->x_focus_event_frame != frame)
{
- x_new_focus_frame (dpyinfo, frame);
+ pgtk_new_focus_frame (dpyinfo, frame);
dpyinfo->x_focus_event_frame = frame;
/* Don't stop displaying the initial startup message
@@ -5724,14 +5583,14 @@ x_focus_changed (gboolean is_enter, int state,
if (dpyinfo->x_focus_event_frame == frame)
{
dpyinfo->x_focus_event_frame = 0;
- x_new_focus_frame (dpyinfo, 0);
+ pgtk_new_focus_frame (dpyinfo, NULL);
bufp->ie.kind = FOCUS_OUT_EVENT;
XSETFRAME (bufp->ie.frame_or_window, frame);
}
if (frame->pointer_invisible)
- XTtoggle_invisible_pointer (frame, false);
+ pgtk_toggle_invisible_pointer (frame, false);
}
}
@@ -5740,10 +5599,12 @@ enter_notify_event (GtkWidget *widget, GdkEvent *event,
gpointer *user_data)
{
union buffered_input_event inev;
- struct frame *frame =
- pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+ struct frame *frame
+ = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
if (frame == NULL)
return FALSE;
+
struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
struct frame *focus_frame = dpyinfo->x_focus_frame;
int focus_state
@@ -5755,7 +5616,7 @@ enter_notify_event (GtkWidget *widget, GdkEvent *event,
if (event->crossing.detail != GDK_NOTIFY_INFERIOR
&& event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
- x_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
+ pgtk_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
if (inev.ie.kind != NO_EVENT)
evq_enqueue (&inev);
return TRUE;
@@ -5766,10 +5627,12 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
gpointer *user_data)
{
union buffered_input_event inev;
- struct frame *frame =
- pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+ struct frame *frame
+ = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
if (frame == NULL)
return FALSE;
+
struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
struct frame *focus_frame = dpyinfo->x_focus_frame;
int focus_state
@@ -5790,7 +5653,7 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
if (event->crossing.detail != GDK_NOTIFY_INFERIOR
&& event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
- x_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
+ pgtk_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
if (frame)
{
@@ -5809,11 +5672,11 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
}
static gboolean
-focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
+focus_in_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
{
union buffered_input_event inev;
- struct frame *frame =
- pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+ struct frame *frame
+ = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
if (frame == NULL)
return TRUE;
@@ -5822,8 +5685,8 @@ focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
- x_focus_changed (TRUE, FOCUS_EXPLICIT,
- FRAME_DISPLAY_INFO (frame), frame, &inev);
+ pgtk_focus_changed (TRUE, FOCUS_EXPLICIT,
+ FRAME_DISPLAY_INFO (frame), frame, &inev);
if (inev.ie.kind != NO_EVENT)
evq_enqueue (&inev);
@@ -5833,11 +5696,11 @@ focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
}
static gboolean
-focus_out_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
+focus_out_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
{
union buffered_input_event inev;
- struct frame *frame =
- pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+ struct frame *frame
+ = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
if (frame == NULL)
return TRUE;
@@ -5846,8 +5709,8 @@ focus_out_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
- x_focus_changed (FALSE, FOCUS_EXPLICIT,
- FRAME_DISPLAY_INFO (frame), frame, &inev);
+ pgtk_focus_changed (FALSE, FOCUS_EXPLICIT,
+ FRAME_DISPLAY_INFO (frame), frame, &inev);
if (inev.ie.kind != NO_EVENT)
evq_enqueue (&inev);
@@ -5865,7 +5728,8 @@ focus_out_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
another motion event, so we can check again the next time it moves. */
static bool
-note_mouse_movement (struct frame *frame, const GdkEventMotion * event)
+note_mouse_movement (struct frame *frame,
+ const GdkEventMotion *event)
{
XRectangle *r;
struct pgtk_display_info *dpyinfo;
@@ -5885,6 +5749,9 @@ note_mouse_movement (struct frame *frame, const GdkEventMotion * event)
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
dpyinfo->last_mouse_glyph_frame = NULL;
+ frame->last_mouse_device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
+ (GdkEvent *) event);
return true;
}
@@ -5901,6 +5768,9 @@ note_mouse_movement (struct frame *frame, const GdkEventMotion * event)
/* Remember which glyph we're now on. */
remember_mouse_glyph (frame, event->x, event->y, r);
dpyinfo->last_mouse_glyph_frame = frame;
+ frame->last_mouse_device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
+ (GdkEvent *) event);
return true;
}
@@ -5908,17 +5778,14 @@ note_mouse_movement (struct frame *frame, const GdkEventMotion * event)
}
static gboolean
-motion_notify_event (GtkWidget * widget, GdkEvent * event,
- gpointer * user_data)
+motion_notify_event (GtkWidget *widget, GdkEvent *event,
+ gpointer *user_data)
{
union buffered_input_event inev;
struct frame *f, *frame;
struct pgtk_display_info *dpyinfo;
Mouse_HLInfo *hlinfo;
- /* This is needed to make pointer visible when motion_notify event */
- pending_signals = true;
-
EVENT_INIT (inev.ie);
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
@@ -5938,8 +5805,9 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event,
clear_mouse_face (hlinfo);
}
- if (f && xg_event_is_for_scrollbar (f, event))
+ if (f && xg_event_is_for_scrollbar (f, event, false))
f = 0;
+
if (f)
{
/* Maybe generate a SELECT_WINDOW_EVENT for
@@ -5984,11 +5852,9 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event,
help_echo_string = previous_help_echo_string;
}
else
- {
- /* If we move outside the frame, then we're
- certainly no longer on any text in the frame. */
- clear_mouse_face (hlinfo);
- }
+ /* If we move outside the frame, then we're
+ certainly no longer on any text in the frame. */
+ clear_mouse_face (hlinfo);
/* If the contents of the global variable help_echo_string
has changed, generate a HELP_EVENT. */
@@ -6016,26 +5882,6 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event,
return TRUE;
}
-/* Mouse clicks and mouse movement. Rah.
-
- Formerly, we used PointerMotionHintMask (in standard_event_mask)
- so that we would have to call XQueryPointer after each MotionNotify
- event to ask for another such event. However, this made mouse tracking
- slow, and there was a bug that made it eventually stop.
-
- Simply asking for MotionNotify all the time seems to work better.
-
- In order to avoid asking for motion events and then throwing most
- of them away or busy-polling the server for mouse positions, we ask
- the server for pointer motion hints. This means that we get only
- one event per group of mouse movements. "Groups" are delimited by
- other kinds of events (focus changes and button clicks, for
- example), or by XQueryPointer calls; when one of these happens, we
- get another MotionNotify event the next time the mouse moves. This
- is at least as efficient as getting motion events when mouse
- tracking is on, and I suspect only negligibly worse when tracking
- is off. */
-
/* Prepare a mouse-event in *RESULT for placement in the input queue.
If the event is a button press, then note that we have grabbed
@@ -6043,7 +5889,8 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event,
static Lisp_Object
construct_mouse_click (struct input_event *result,
- const GdkEventButton * event, struct frame *f)
+ const GdkEventButton *event,
+ struct frame *f)
{
/* Make the event type NO_EVENT; we'll change that when we decide
otherwise. */
@@ -6058,11 +5905,14 @@ construct_mouse_click (struct input_event *result,
XSETINT (result->y, event->y);
XSETFRAME (result->frame_or_window, f);
result->arg = Qnil;
+ result->device = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f),
+ (GdkEvent *) event);
return Qnil;
}
static gboolean
-button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
+button_event (GtkWidget *widget, GdkEvent *event,
+ gpointer *user_data)
{
union buffered_input_event inev;
struct frame *f, *frame;
@@ -6086,9 +5936,6 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
dpyinfo = FRAME_DISPLAY_INFO (frame);
dpyinfo->last_mouse_glyph_frame = NULL;
-#if 0
- x_display_set_last_user_time (dpyinfo, event->button.time);
-#endif
if (gui_mouse_grabbed (dpyinfo))
f = dpyinfo->last_mouse_frame;
@@ -6117,14 +5964,6 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
}
}
- /* xg_event_is_for_scrollbar() doesn't work correctly on sway, and
- * we shouldn't need it.
- */
-#if 0
- if (f && xg_event_is_for_scrollbar (f, event))
- f = 0;
-#endif
-
if (f)
{
/* Is this in the tab-bar? */
@@ -6166,11 +6005,6 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
if (!NILP (tab_bar_arg))
inev.ie.arg = tab_bar_arg;
}
-#if 0
- if (FRAME_X_EMBEDDED_P (f))
- xembed_send_message (f, event->button.time,
- XEMBED_REQUEST_FOCUS, 0, 0, 0);
-#endif
}
if (event->type == GDK_BUTTON_PRESS)
@@ -6197,7 +6031,7 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
}
static gboolean
-scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
+scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
{
union buffered_input_event inev;
struct frame *f, *frame;
@@ -6229,6 +6063,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
if (gdk_event_is_scroll_stop_event (event))
{
inev.ie.kind = TOUCH_END_EVENT;
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
evq_enqueue (&inev);
return TRUE;
}
@@ -6322,47 +6158,245 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data)
}
if (inev.ie.kind != NO_EVENT)
- evq_enqueue (&inev);
+ {
+ inev.ie.device
+ = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
+ evq_enqueue (&inev);
+ }
return TRUE;
}
+
+
+/* C part of drop handling code.
+ The Lisp part is in pgtk-dnd.el. */
+
+static GdkDragAction
+symbol_to_drag_action (Lisp_Object act)
+{
+ if (EQ (act, Qcopy))
+ return GDK_ACTION_COPY;
+
+ if (EQ (act, Qmove))
+ return GDK_ACTION_MOVE;
+
+ if (EQ (act, Qlink))
+ return GDK_ACTION_LINK;
+
+ if (EQ (act, Qprivate))
+ return GDK_ACTION_PRIVATE;
+
+ if (NILP (act))
+ return GDK_ACTION_DEFAULT;
+
+ signal_error ("Invalid drag acction", act);
+}
+
+static Lisp_Object
+drag_action_to_symbol (GdkDragAction action)
+{
+ switch (action)
+ {
+ case GDK_ACTION_COPY:
+ return Qcopy;
+
+ case GDK_ACTION_MOVE:
+ return Qmove;
+
+ case GDK_ACTION_LINK:
+ return Qlink;
+
+ case GDK_ACTION_PRIVATE:
+ return Qprivate;
+
+ case GDK_ACTION_DEFAULT:
+ default:
+ return Qnil;
+ }
+}
+
+void
+pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time)
+{
+ guint32 time;
+
+ CONS_TO_INTEGER (event_time, guint32, time);
+
+ if (!current_drop_context || time < current_drop_time)
+ return;
+
+ gdk_drag_status (current_drop_context,
+ symbol_to_drag_action (action),
+ time);
+}
+
+void
+pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time,
+ Lisp_Object del)
+{
+ guint32 time;
+
+ CONS_TO_INTEGER (event_time, guint32, time);
+
+ if (!current_drop_context || time < current_drop_time)
+ return;
+
+ gtk_drag_finish (current_drop_context, !NILP (success),
+ !NILP (del), time);
+
+ if (current_drop_context_drop)
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+}
+
static void
-drag_data_received (GtkWidget * widget, GdkDragContext * context,
- gint x, gint y,
- GtkSelectionData * data,
- guint info, guint time, gpointer user_data)
+drag_leave (GtkWidget *widget, GdkDragContext *context,
+ guint time, gpointer user_data)
{
- struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
- gchar **uris = gtk_selection_data_get_uris (data);
+ struct frame *f;
+ union buffered_input_event inev;
- if (uris != NULL)
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
+ if (current_drop_context)
{
- for (int i = 0; uris[i] != NULL; i++)
- {
- union buffered_input_event inev;
- Lisp_Object arg = Qnil;
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
- EVENT_INIT (inev.ie);
- inev.ie.kind = NO_EVENT;
- inev.ie.arg = Qnil;
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+ }
- arg = list2 (Qurl, build_string (uris[i]));
+ EVENT_INIT (inev.ie);
- inev.ie.kind = DRAG_N_DROP_EVENT;
- inev.ie.modifiers = 0;
- XSETINT (inev.ie.x, x);
- XSETINT (inev.ie.y, y);
- XSETFRAME (inev.ie.frame_or_window, f);
- inev.ie.arg = arg;
- inev.ie.timestamp = 0;
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = Qnil;
+ inev.ie.timestamp = time;
- evq_enqueue (&inev);
- }
+ XSETINT (inev.ie.x, 0);
+ XSETINT (inev.ie.y, 0);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ evq_enqueue (&inev);
+}
+
+static gboolean
+drag_motion (GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, guint time)
+
+{
+ struct frame *f;
+ union buffered_input_event inev;
+ GdkAtom name;
+ GdkDragAction suggestion;
+
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
+ if (!f)
+ return FALSE;
+
+ if (current_drop_context)
+ {
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
+
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
+ }
+
+ current_drop_context = g_object_ref (context);
+ current_drop_time = time;
+ current_drop_context_drop = false;
+
+ name = gdk_drag_get_selection (context);
+ suggestion = gdk_drag_context_get_suggested_action (context);
+
+ EVENT_INIT (inev.ie);
+
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
+ make_uint (time),
+ drag_action_to_symbol (suggestion));
+ inev.ie.timestamp = time;
+
+ XSETINT (inev.ie.x, x);
+ XSETINT (inev.ie.y, y);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ evq_enqueue (&inev);
+
+ return TRUE;
+}
+
+static gboolean
+drag_drop (GtkWidget *widget, GdkDragContext *context,
+ int x, int y, guint time, gpointer user_data)
+{
+ struct frame *f;
+ union buffered_input_event inev;
+ GdkAtom name;
+ GdkDragAction selected_action;
+
+ f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
+
+ if (!f)
+ return FALSE;
+
+ if (current_drop_context)
+ {
+ if (current_drop_context_drop)
+ gtk_drag_finish (current_drop_context,
+ FALSE, FALSE, current_drop_time);
+
+ g_clear_pointer (&current_drop_context,
+ g_object_unref);
}
- gtk_drag_finish (context, TRUE, FALSE, time);
+ current_drop_context = g_object_ref (context);
+ current_drop_time = time;
+ current_drop_context_drop = true;
+
+ name = gdk_drag_get_selection (context);
+ selected_action = gdk_drag_context_get_selected_action (context);
+
+ EVENT_INIT (inev.ie);
+
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ inev.ie.modifiers = 0;
+ inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
+ make_uint (time),
+ drag_action_to_symbol (selected_action));
+ inev.ie.timestamp = time;
+
+ XSETINT (inev.ie.x, x);
+ XSETINT (inev.ie.y, y);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ evq_enqueue (&inev);
+
+ return TRUE;
}
+static void
+pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data)
+{
+ struct terminal *terminal;
+ union buffered_input_event inev;
+
+ EVENT_INIT (inev.ie);
+ terminal = user_data;
+ inev.ie.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (inev.ie.arg, terminal);
+
+ evq_enqueue (&inev);
+}
+
+static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer);
+
void
pgtk_set_event_handler (struct frame *f)
{
@@ -6373,9 +6407,9 @@ pgtk_set_event_handler (struct frame *f)
return;
}
- gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0,
- GDK_ACTION_COPY);
- gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f));
+ gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0,
+ (GDK_ACTION_MOVE | GDK_ACTION_COPY
+ | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
if (FRAME_GTK_OUTER_WIDGET (f))
{
@@ -6414,14 +6448,24 @@ pgtk_set_event_handler (struct frame *f)
G_CALLBACK (button_event), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event",
G_CALLBACK (scroll_event), NULL);
- g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
- G_CALLBACK (pgtk_selection_lost), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
G_CALLBACK (configure_event), NULL);
- g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received",
- G_CALLBACK (drag_data_received), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave",
+ G_CALLBACK (drag_leave), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion",
+ G_CALLBACK (drag_motion), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop",
+ G_CALLBACK (drag_drop), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
G_CALLBACK (pgtk_handle_draw), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
+ G_CALLBACK (pgtk_selection_event), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
+ G_CALLBACK (pgtk_selection_event), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-request-event",
+ G_CALLBACK (pgtk_selection_event), NULL);
+ g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-notify-event",
+ G_CALLBACK (pgtk_selection_event), NULL);
g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event",
G_CALLBACK (pgtk_handle_event), NULL);
}
@@ -6481,25 +6525,72 @@ same_x_server (const char *name1, const char *name2)
&& (*name2 == '.' || *name2 == '\0'));
}
-#define GNOME_INTERFACE_SCHEMA "org.gnome.desktop.interface"
+static struct frame *
+pgtk_find_selection_owner (GdkWindow *window)
+{
+ Lisp_Object tail, tem;
+ struct frame *f;
-static gdouble pgtk_text_scaling_factor (void)
+ FOR_EACH_FRAME (tail, tem)
+ {
+ f = XFRAME (tem);
+
+ if (FRAME_PGTK_P (f)
+ && (FRAME_GDK_WINDOW (f) == window))
+ return f;
+ }
+
+ return NULL;
+}
+
+static gboolean
+pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
{
- GSettingsSchemaSource *schema_source = g_settings_schema_source_get_default ();
- if (schema_source != NULL)
+ struct frame *f;
+ union buffered_input_event inev;
+
+ if (event->type == GDK_PROPERTY_NOTIFY)
+ pgtk_handle_property_notify (&event->property);
+ else if (event->type == GDK_SELECTION_CLEAR
+ || event->type == GDK_SELECTION_REQUEST)
{
- GSettingsSchema *schema = g_settings_schema_source_lookup (schema_source,
- GNOME_INTERFACE_SCHEMA, true);
- if (schema != NULL)
- {
- g_settings_schema_unref (schema);
- GSettings *set = g_settings_new (GNOME_INTERFACE_SCHEMA);
- return g_settings_get_double (set, "text-scaling-factor");
+ f = pgtk_find_selection_owner (event->selection.window);
+
+ if (f)
+ {
+ EVENT_INIT (inev.ie);
+
+ inev.sie.kind = (event->type == GDK_SELECTION_CLEAR
+ ? SELECTION_CLEAR_EVENT
+ : SELECTION_REQUEST_EVENT);
+
+ SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f);
+ SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection;
+ SELECTION_EVENT_TIME (&inev.sie) = event->selection.time;
+
+ if (event->type == GDK_SELECTION_REQUEST)
+ {
+ /* FIXME: when does GDK destroy the requestor GdkWindow
+ object?
+
+ It would make sense to wait for the transfer to
+ complete. But I don't know if GDK actually does
+ that. */
+ SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor;
+ SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target;
+ SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property;
+ }
+
+ evq_enqueue (&inev);
+ return TRUE;
}
}
- return 1;
-}
+ else if (event->type == GDK_SELECTION_NOTIFY)
+ pgtk_handle_selection_notify (&event->selection);
+ return FALSE;
+}
/* Open a connection to X display DISPLAY_NAME, and return
the structure that describes the open display.
@@ -6514,9 +6605,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
static int x_initialized = 0;
static unsigned x_display_id = 0;
static char *initial_display = NULL;
- static dynlib_handle_ptr *handle = NULL;
char *dpy_name;
+ static void *handle = NULL;
Lisp_Object lisp_dpy_name = Qnil;
+ GdkScreen *gscr;
+ gdouble dpi;
block_input ();
@@ -6653,9 +6746,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
*nametail++ = '@';
lispstpcpy (nametail, system_name);
- /* Figure out which modifier bits mean what. */
- x_find_modifier_meanings (dpyinfo);
-
/* Get the scroll bar cursor. */
/* We must create a GTK cursor, it is required for GTK widgets. */
dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy);
@@ -6670,34 +6760,35 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
reset_mouse_highlight (&dpyinfo->mouse_highlight);
- {
- GdkScreen *gscr = gdk_display_get_default_screen (dpyinfo->gdpy);
+ gscr = gdk_display_get_default_screen (dpyinfo->gdpy);
+ dpi = gdk_screen_get_resolution (gscr);
- gdouble dpi = gdk_screen_get_resolution (gscr);
- if (dpi < 0)
- dpi = 96.0;
+ if (dpi < 0)
+ dpi = 96.0;
- dpi *= pgtk_text_scaling_factor ();
- dpyinfo->resx = dpi;
- dpyinfo->resy = dpi;
- }
+ dpyinfo->resx = dpi;
+ dpyinfo->resy = dpi;
+
+ g_signal_connect (G_OBJECT (gscr), "monitors-changed",
+ G_CALLBACK (pgtk_monitors_changed_cb),
+ terminal);
- /* smooth scroll setting */
- dpyinfo->scroll.x_per_char = 2;
- dpyinfo->scroll.y_per_line = 2;
+ /* Set up scrolling increments. */
+ dpyinfo->scroll.x_per_char = 1;
+ dpyinfo->scroll.y_per_line = 1;
dpyinfo->connection = -1;
if (!handle)
- handle = dynlib_open (NULL);
+ handle = dlopen (NULL, RTLD_LAZY);
#ifdef GDK_WINDOWING_X11
if (!strcmp (G_OBJECT_TYPE_NAME (dpy), "GdkX11Display") && handle)
{
void *(*gdk_x11_display_get_xdisplay) (GdkDisplay *)
- = dynlib_sym (handle, "gdk_x11_display_get_xdisplay");
+ = dlsym (handle, "gdk_x11_display_get_xdisplay");
int (*x_connection_number) (void *)
- = dynlib_sym (handle, "XConnectionNumber");
+ = dlsym (handle, "XConnectionNumber");
if (x_connection_number
&& gdk_x11_display_get_xdisplay)
@@ -6711,7 +6802,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
{
struct wl_display *wl_dpy = gdk_wayland_display_get_wl_display (dpy);
int (*display_get_fd) (struct wl_display *)
- = dynlib_sym (handle, "wl_display_get_fd");
+ = dlsym (handle, "wl_display_get_fd");
if (display_get_fd)
dpyinfo->connection = display_get_fd (wl_dpy);
@@ -6729,14 +6820,19 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
init_sigio (dpyinfo->connection);
}
- x_setup_pointer_blanking (dpyinfo);
+ dpyinfo->invisible_cursor
+ = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_BLANK_CURSOR);
xsettings_initialize (dpyinfo);
- pgtk_selection_init ();
-
pgtk_im_init (dpyinfo);
+ g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added",
+ G_CALLBACK (pgtk_seat_added_cb), dpyinfo);
+ g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-removed",
+ G_CALLBACK (pgtk_seat_removed_cb), dpyinfo);
+ pgtk_enumerate_devices (dpyinfo, true);
+
unblock_input ();
return dpyinfo;
@@ -6770,6 +6866,7 @@ pgtk_delete_display (struct pgtk_display_info *dpyinfo)
tail->next = tail->next->next;
}
+ pgtk_free_devices (dpyinfo);
xfree (dpyinfo);
}
@@ -6802,9 +6899,9 @@ pgtk_xlfd_to_fontname (const char *xlfd)
}
bool
-pgtk_defined_color (struct frame *f,
- const char *name,
- Emacs_Color * color_def, bool alloc, bool makeIndex)
+pgtk_defined_color (struct frame *f, const char *name,
+ Emacs_Color *color_def, bool alloc,
+ bool makeIndex)
/* --------------------------------------------------------------------------
Return true if named color found, and set color_def rgb accordingly.
If makeIndex and alloc are nonzero put the color in the color_table,
@@ -6885,7 +6982,8 @@ pgtk_clear_area (struct frame *f, int x, int y, int width, int height)
eassert (width > 0 && height > 0);
cr = pgtk_begin_cr_clip (f);
- pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color);
+ pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color,
+ true);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
pgtk_end_cr_clip (f);
@@ -6895,7 +6993,6 @@ pgtk_clear_area (struct frame *f, int x, int y, int width, int height)
void
syms_of_pgtkterm (void)
{
- /* from 23+ we need to tell emacs what modifiers there are.. */
DEFSYM (Qmodifier_value, "modifier-value");
DEFSYM (Qalt, "alt");
DEFSYM (Qhyper, "hyper");
@@ -6909,12 +7006,17 @@ syms_of_pgtkterm (void)
DEFSYM (Qlatin_1, "latin-1");
- xg_default_icon_file =
- build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
+ xg_default_icon_file
+ = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
staticpro (&xg_default_icon_file);
DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
+ DEFSYM (Qcopy, "copy");
+ DEFSYM (Qmove, "move");
+ DEFSYM (Qlink, "link");
+ DEFSYM (Qprivate, "private");
+
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
@@ -6923,80 +7025,46 @@ syms_of_pgtkterm (void)
Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier));
DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
- doc: /* Which keys Emacs uses for the ctrl modifier.
-This should be one of the symbols `ctrl', `alt', `hyper', `meta',
-`super'. For example, `ctrl' means use the Ctrl_L and Ctrl_R keysyms.
-The default is nil, which is the same as `ctrl'. */ );
+ doc: /* SKIP: real doc in xterm.c. */);
Vx_ctrl_keysym = Qnil;
DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
- doc: /* Which keys Emacs uses for the alt modifier.
-This should be one of the symbols `ctrl', `alt', `hyper', `meta',
-`super'. For example, `alt' means use the Alt_L and Alt_R keysyms.
-The default is nil, which is the same as `alt'. */ );
+ doc: /* SKIP: real doc in xterm.c. */);
Vx_alt_keysym = Qnil;
DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
- doc: /* Which keys Emacs uses for the hyper modifier.
-This should be one of the symbols `ctrl', `alt', `hyper', `meta',
-`super'. For example, `hyper' means use the Hyper_L and Hyper_R
-keysyms. The default is nil, which is the same as `hyper'. */ );
+ doc: /* SKIP: real doc in xterm.c. */);
Vx_hyper_keysym = Qnil;
DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
- doc: /* Which keys Emacs uses for the meta modifier.
-This should be one of the symbols `ctrl', `alt', `hyper', `meta',
-`super'. For example, `meta' means use the Meta_L and Meta_R keysyms.
-The default is nil, which is the same as `meta'. */ );
+ doc: /* SKIP: real doc in xterm.c. */);
Vx_meta_keysym = Qnil;
DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
- doc: /* Which keys Emacs uses for the super modifier.
-This should be one of the symbols `ctrl', `alt', `hyper', `meta',
-`super'. For example, `super' means use the Super_L and Super_R
-keysyms. The default is nil, which is the same as `super'. */ );
+ doc: /* SKIP: real doc in xterm.c. */);
Vx_super_keysym = Qnil;
- /* TODO: move to common code */
- DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
- doc: /* Which toolkit scroll bars Emacs uses, if any.
-A value of nil means Emacs doesn't use toolkit scroll bars.
-With the X Window system, the value is a symbol describing the
-X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
-With MS Windows or Nextstep, the value is t. */ );
- /* Vx_toolkit_scroll_bars = Qt; */
- Vx_toolkit_scroll_bars = intern_c_string ("gtk");
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ x_use_underline_position_properties,
+ doc: /* SKIP: real doc in xterm.c. */);
+ x_use_underline_position_properties = 1;
- DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties,
- doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
-A value of nil means ignore them. If you encounter fonts with bogus
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil. */);
- x_use_underline_position_properties = 0;
-
- DEFVAR_BOOL ("x-underline-at-descent-line", x_underline_at_descent_line,
- doc: /* Non-nil means to draw the underline at the same place as the descent line.
-A value of nil means to draw the underline according to the value of the
-variable `x-use-underline-position-properties', which is usually at the
-baseline level. The default value is nil. */);
+ DEFVAR_BOOL ("x-underline-at-descent-line",
+ x_underline_at_descent_line,
+ doc: /* SKIP: real doc in xterm.c. */);
x_underline_at_descent_line = 0;
- DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
- doc: /* Non-nil means rely on gtk_window_move to set frame positions.
-If this variable is t (the default), the GTK build uses the function
-gtk_window_move to set or store frame positions and disables some time
-consuming frame position adjustments. In newer versions of GTK, Emacs
-always uses gtk_window_move and ignores the value of this variable. */);
- x_gtk_use_window_move = true;
-
+ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
+ doc: /* SKIP: real doc in xterm.c. */);
+ Vx_toolkit_scroll_bars = intern_c_string ("gtk");
DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout,
- doc: /* How long to wait for X events.
+ doc: /* How long to wait for GTK events.
-Emacs will wait up to this many seconds to receive X events after
-making changes which affect the state of the graphical interface.
-Under some window managers this can take an indefinite amount of time,
-so it is important to limit the wait.
+Emacs will wait up to this many seconds to receive some GTK events
+after making changes which affect the state of the graphical
+interface. Under some window managers this can take an indefinite
+amount of time, so it is important to limit the wait.
If set to a non-float value, there will be no wait at all. */);
Vpgtk_wait_for_event_timeout = make_float (0.1);
@@ -7015,13 +7083,12 @@ If set to a non-float value, there will be no wait at all. */);
}
/* Cairo does not allow resizing a surface/context after it is
- * created, so we need to trash the old context, create a new context
- * on the next cr_clip_begin with the new dimensions and request a
- * re-draw.
- *
- * This Will leave the active context available to present on screen
- * until a redrawn frame is completed.
- */
+ created, so we need to trash the old context, create a new context
+ on the next cr_clip_begin with the new dimensions and request a
+ re-draw.
+
+ This will leave the active context available to present on screen
+ until a redrawn frame is completed. */
void
pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force)
{
@@ -7068,25 +7135,42 @@ pgtk_end_cr_clip (struct frame *f)
}
void
-pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC * gc)
+pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc,
+ bool respects_alpha_background)
{
- pgtk_set_cr_source_with_color (f, gc->foreground);
+ pgtk_set_cr_source_with_color (f, gc->foreground,
+ respects_alpha_background);
}
void
-pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC * gc)
+pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc,
+ bool respects_alpha_background)
{
- pgtk_set_cr_source_with_color (f, gc->background);
+ pgtk_set_cr_source_with_color (f, gc->background,
+ respects_alpha_background);
}
void
-pgtk_set_cr_source_with_color (struct frame *f, unsigned long color)
+pgtk_set_cr_source_with_color (struct frame *f, unsigned long color,
+ bool respects_alpha_background)
{
Emacs_Color col;
col.pixel = color;
pgtk_query_color (f, &col);
- cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0,
- col.green / 65535.0, col.blue / 65535.0);
+
+ if (!respects_alpha_background)
+ {
+ cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0,
+ col.green / 65535.0, col.blue / 65535.0);
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
+ }
+ else
+ {
+ cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0,
+ col.green / 65535.0, col.blue / 65535.0,
+ f->alpha_background);
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
+ }
}
void
@@ -7098,7 +7182,7 @@ pgtk_cr_draw_frame (cairo_t * cr, struct frame *f)
static cairo_status_t
pgtk_cr_accumulate_data (void *closure, const unsigned char *data,
- unsigned int length)
+ unsigned int length)
{
Lisp_Object *acc = (Lisp_Object *) closure;
@@ -7125,8 +7209,6 @@ pgtk_cr_destroy (void *cr)
unblock_input ();
}
-
-
Lisp_Object
pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
{
@@ -7136,7 +7218,7 @@ pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
int width, height;
void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
Lisp_Object acc = Qnil;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (31);
@@ -7219,9 +7301,3 @@ pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
}
-
-
-void
-init_pgtkterm (void)
-{
-}
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index 42b03e315ef..fcc6c5310e9 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -40,8 +40,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <cairo-svg.h>
#endif
-/* could use list to store these, but rest of emacs has a big infrastructure
- for managing a table of bitmap "records" */
struct pgtk_bitmap_record
{
void *img;
@@ -51,13 +49,22 @@ struct pgtk_bitmap_record
cairo_pattern_t *pattern;
};
+struct pgtk_device_t
+{
+ GdkSeat *seat;
+ GdkDevice *device;
+
+ Lisp_Object name;
+ struct pgtk_device_t *next;
+};
+
#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define ALPHA_FROM_ULONG(color) ((color) >> 24)
-#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
+#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
-#define BLUE_FROM_ULONG(color) ((color) & 0xff)
+#define BLUE_FROM_ULONG(color) ((color) & 0xff)
struct scroll_bar
{
@@ -89,7 +96,7 @@ struct scroll_bar
editing large files, we establish a minimum height by always
drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
where they would be normally; the bottom and top are in a
- different co-ordinate system. */
+ different coordinate system. */
int start, end;
/* If the scroll bar handle is currently being dragged by the user,
@@ -112,8 +119,6 @@ struct scroll_bar
bool horizontal;
};
-
-/* init'd in pgtk_initialize_display_info () */
struct pgtk_display_info
{
/* Chain of all pgtk_display_info structures. */
@@ -122,8 +127,14 @@ struct pgtk_display_info
/* The generic display parameters corresponding to this PGTK display. */
struct terminal *terminal;
- /* This says how to access this display in Gdk. */
- GdkDisplay *gdpy;
+ union
+ {
+ /* This says how to access this display through GDK. */
+ GdkDisplay *gdpy;
+
+ /* An alias defined to make porting X code easier. */
+ GdkDisplay *display;
+ };
/* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */
Lisp_Object name_list_element;
@@ -205,30 +216,28 @@ struct pgtk_display_info
/* Time of last mouse movement. */
Time last_mouse_movement_time;
+ /* Time of last user interaction. */
+ guint32 last_user_time;
+
/* The scroll bar in which the last motion event occurred. */
void *last_mouse_scroll_bar;
- /* The invisible cursor used for pointer blanking.
- Unused if this display supports Xfixes extension. */
+ /* The invisible cursor used for pointer blanking. */
Emacs_Cursor invisible_cursor;
- /* Function used to toggle pointer visibility on this display. */
- void (*toggle_visible_pointer) (struct frame *, bool);
-
/* The GDK cursor for scroll bars and popup menus. */
GdkCursor *xg_cursor;
+ /* List of all devices for all seats on this display. */
+ struct pgtk_device_t *devices;
/* The frame where the mouse was last time we reported a mouse position. */
struct frame *last_mouse_glyph_frame;
- /* Modifier masks in gdk */
- int meta_mod_mask, alt_mod_mask, super_mod_mask, hyper_mod_mask;
-
/* The last click event. */
GdkEvent *last_click_event;
- /* input method */
+ /* IM context data. */
struct
{
GtkIMContext *context;
@@ -249,10 +258,6 @@ extern struct pgtk_display_info *x_display_list;
struct pgtk_output
{
-#if 0
- void *view;
- void *miniimage;
-#endif
unsigned long foreground_color;
unsigned long background_color;
void *toolbar;
@@ -396,6 +401,10 @@ struct pgtk_output
They are changed only when a different background is involved. */
unsigned long relief_background;
+ /* Whether or not a relief background has been computed for this
+ frame. */
+ bool_bf relief_background_valid_p : 1;
+
/* Keep track of focus. May be EXPLICIT if we received a FocusIn for this
frame, or IMPLICIT if we received an EnterNotify.
FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
@@ -409,7 +418,7 @@ struct pgtk_output
struct atimer *scale_factor_atimer;
};
-/* this dummy decl needed to support TTYs */
+/* Satisfy term.c. */
struct x_output
{
int unused;
@@ -439,14 +448,15 @@ enum
#define FRAME_FONT(f) (FRAME_X_OUTPUT (f)->font)
#define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT (f)->widget)
#define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT (f)->edit_widget)
-#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET (f) ? \
- FRAME_GTK_OUTER_WIDGET (f) : \
- FRAME_GTK_WIDGET (f))
+#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET (f) \
+ ? FRAME_GTK_OUTER_WIDGET (f) \
+ : FRAME_GTK_WIDGET (f))
-/* aliases */
#define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET (f)
#define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET (f)
#define FRAME_NATIVE_WINDOW(f) GTK_WINDOW (FRAME_X_WINDOW (f))
+#define FRAME_GDK_WINDOW(f) \
+ (gtk_widget_get_window (FRAME_GTK_WIDGET (f)))
#define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO (f)->gdpy)
@@ -455,59 +465,8 @@ enum
/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
-#define PGTK_FACE_FOREGROUND(f) ((f)->foreground)
-#define PGTK_FACE_BACKGROUND(f) ((f)->background)
#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID)
-
-/* Compute pixel height of the frame's titlebar. */
-#define FRAME_PGTK_TITLEBAR_HEIGHT(f) 0
-
-/* Compute pixel size for vertical scroll bars */
-#define PGTK_SCROLL_BAR_WIDTH(f) \
- (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
- ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \
- ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
- : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \
- : 0)
-
-/* Compute pixel size for horizontal scroll bars */
-#define PGTK_SCROLL_BAR_HEIGHT(f) \
- (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \
- ? rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 \
- ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \
- : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f))) \
- : 0)
-
-/* Difference btwn char-column-calculated and actual SB widths.
- This is only a concern for rendering when SB on left. */
-#define PGTK_SCROLL_BAR_ADJUST(w, f) \
- (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? \
- (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \
- - PGTK_SCROLL_BAR_WIDTH (f)) : 0)
-
-/* Difference btwn char-line-calculated and actual SB heights.
- This is only a concern for rendering when SB on top. */
-#define PGTK_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f) \
- (WINDOW_HAS_HORIZONTAL_SCROLL_BARS (w) ? \
- (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \
- - PGTK_SCROLL_BAR_HEIGHT (f)) : 0)
-
#define FRAME_MENUBAR_HEIGHT(f) (FRAME_X_OUTPUT (f)->menubar_height)
-
-/* Calculate system coordinates of the left and top of the parent
- window or, if there is no parent window, the screen. */
-#define PGTK_PARENT_WINDOW_LEFT_POS(f) \
- (FRAME_PARENT_FRAME (f) != NULL \
- ? [[FRAME_PGTK_VIEW (f) window] parentWindow].frame.origin.x : 0)
-#define PGTK_PARENT_WINDOW_TOP_POS(f) \
- (FRAME_PARENT_FRAME (f) != NULL \
- ? ([[FRAME_PGTK_VIEW (f) window] parentWindow].frame.origin.y \
- + [[FRAME_PGTK_VIEW (f) window] parentWindow].frame.size.height \
- - FRAME_PGTK_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f))) \
- : [[[PGTKScreen screepgtk] objectAtIndex: 0] frame].size.height)
-
-#define FRAME_PGTK_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table)
-
#define FRAME_TOOLBAR_TOP_HEIGHT(f) ((f)->output_data.pgtk->toolbar_top_height)
#define FRAME_TOOLBAR_BOTTOM_HEIGHT(f) \
((f)->output_data.pgtk->toolbar_bottom_height)
@@ -535,78 +494,101 @@ enum
#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
((f)->output_data.pgtk->cr_surface_desired_height)
+
+/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT
+ or SELECTION_CLEAR_EVENT, then its contents are really described
+ by this structure. */
+
+/* For an event of kind SELECTION_REQUEST_EVENT,
+ this structure really describes the contents. */
+
+struct selection_input_event
+{
+ ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH;
+ struct pgtk_display_info *dpyinfo;
+ /* We spell it with an "o" here because X does. */
+ GdkWindow *requestor;
+ GdkAtom selection, target, property;
+ guint32 time;
+};
+
+/* Unlike macros below, this can't be used as an lvalue. */
+INLINE GdkDisplay *
+SELECTION_EVENT_DISPLAY (struct selection_input_event *ev)
+{
+ return ev->dpyinfo->display;
+}
+#define SELECTION_EVENT_DPYINFO(eventp) \
+ ((eventp)->dpyinfo)
+/* We spell it with an "o" here because X does. */
+#define SELECTION_EVENT_REQUESTOR(eventp) \
+ ((eventp)->requestor)
+#define SELECTION_EVENT_SELECTION(eventp) \
+ ((eventp)->selection)
+#define SELECTION_EVENT_TARGET(eventp) \
+ ((eventp)->target)
+#define SELECTION_EVENT_PROPERTY(eventp) \
+ ((eventp)->property)
+#define SELECTION_EVENT_TIME(eventp) \
+ ((eventp)->time)
+
+extern void pgtk_handle_selection_event (struct selection_input_event *);
+extern void pgtk_clear_frame_selections (struct frame *);
+extern void pgtk_handle_property_notify (GdkEventProperty *);
+extern void pgtk_handle_selection_notify (GdkEventSelection *);
+
/* Display init/shutdown functions implemented in pgtkterm.c */
-extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name,
- char *resource_name);
-extern void pgtk_term_shutdown (int sig);
+extern struct pgtk_display_info *pgtk_term_init (Lisp_Object, char *);
+extern void pgtk_term_shutdown (int);
/* Implemented in pgtkterm, published in or needed from pgtkfns. */
-extern void pgtk_clear_frame (struct frame *f);
-extern char *pgtk_xlfd_to_fontname (const char *xlfd);
+extern void pgtk_clear_frame (struct frame *);
+extern char *pgtk_xlfd_to_fontname (const char *);
-/* Implemented in pgtkfns. */
+/* Implemented in pgtkfns.c. */
extern void pgtk_set_doc_edited (void);
-extern const char *pgtk_get_defaults_value (const char *key);
-extern const char *pgtk_get_string_resource (XrmDatabase rdb,
- const char *name,
- const char *class);
-extern void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg,
- Lisp_Object oldval);
+extern const char *pgtk_get_defaults_value (const char *);
+extern const char *pgtk_get_string_resource (XrmDatabase, const char *, const char *);
+extern void pgtk_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
/* Color management implemented in pgtkterm. */
-extern bool pgtk_defined_color (struct frame *f,
- const char *name,
- Emacs_Color * color_def, bool alloc,
- bool makeIndex);
-extern void pgtk_query_color (struct frame *f, Emacs_Color * color);
-extern void pgtk_query_colors (struct frame *f, Emacs_Color * colors,
- int ncolors);
-extern int pgtk_parse_color (struct frame *f, const char *color_name,
- Emacs_Color * color);
+extern bool pgtk_defined_color (struct frame *, const char *,
+ Emacs_Color *, bool, bool);
+extern void pgtk_query_color (struct frame *, Emacs_Color *);
+extern void pgtk_query_colors (struct frame *, Emacs_Color *, int);
+extern int pgtk_parse_color (struct frame *, const char *, Emacs_Color *);
/* Implemented in pgtkterm.c */
-extern void pgtk_clear_area (struct frame *f, int x, int y, int width,
- int height);
-extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo,
- int state);
-extern void pgtk_clear_under_internal_border (struct frame *f);
-extern void pgtk_set_event_handler (struct frame *f);
+extern void pgtk_clear_area (struct frame *, int, int, int, int);
+extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *, int);
+extern void pgtk_clear_under_internal_border (struct frame *);
+extern void pgtk_set_event_handler (struct frame *);
/* Implemented in pgtkterm.c */
-extern int x_display_pixel_height (struct pgtk_display_info *);
-extern int x_display_pixel_width (struct pgtk_display_info *);
+extern int pgtk_display_pixel_height (struct pgtk_display_info *);
+extern int pgtk_display_pixel_width (struct pgtk_display_info *);
-/* Implemented in pgtkterm.c */
-extern void x_destroy_window (struct frame *f);
-extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value);
-extern void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value);
-extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value);
-extern void x_set_z_group (struct frame *f, Lisp_Object new_value,
- Lisp_Object old_value);
+extern void pgtk_destroy_window (struct frame *);
+extern void pgtk_set_parent_frame (struct frame *, Lisp_Object, Lisp_Object);
+extern void pgtk_set_no_focus_on_map (struct frame *, Lisp_Object, Lisp_Object);
+extern void pgtk_set_no_accept_focus (struct frame *, Lisp_Object, Lisp_Object);
+extern void pgtk_set_z_group (struct frame *, Lisp_Object, Lisp_Object);
/* Cairo related functions implemented in pgtkterm.c */
extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int, bool);
-extern cairo_t *pgtk_begin_cr_clip (struct frame *f);
-extern void pgtk_end_cr_clip (struct frame *f);
-extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f,
- Emacs_GC * gc);
-extern void pgtk_set_cr_source_with_gc_background (struct frame *f,
- Emacs_GC * gc);
-extern void pgtk_set_cr_source_with_color (struct frame *f,
- unsigned long color);
-extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f);
-extern void pgtk_cr_destroy_frame_context (struct frame *f);
-extern Lisp_Object pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type);
+extern cairo_t *pgtk_begin_cr_clip (struct frame *);
+extern void pgtk_end_cr_clip (struct frame *);
+extern void pgtk_set_cr_source_with_gc_foreground (struct frame *, Emacs_GC *, bool);
+extern void pgtk_set_cr_source_with_gc_background (struct frame *, Emacs_GC *, bool);
+extern void pgtk_set_cr_source_with_color (struct frame *, unsigned long, bool);
+extern void pgtk_cr_draw_frame (cairo_t *, struct frame *);
+extern void pgtk_cr_destroy_frame_context (struct frame *);
+extern Lisp_Object pgtk_cr_export_frames (Lisp_Object , cairo_surface_type_t);
/* Defined in pgtkmenu.c */
-extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header,
- Lisp_Object contents);
-extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title,
- Lisp_Object header,
- const char **error_name);
+extern Lisp_Object pgtk_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
+extern Lisp_Object pgtk_dialog_show (struct frame *, Lisp_Object, Lisp_Object,
+ const char **);
extern void initialize_frame_menubar (struct frame *);
@@ -617,49 +599,47 @@ extern void syms_of_pgtkmenu (void);
extern void syms_of_pgtkselect (void);
extern void syms_of_pgtkim (void);
-/* Implemented in pgtkselect. */
-extern void nxatoms_of_pgtkselect (void);
-
/* Initialization and marking implemented in pgtkterm.c */
-extern void init_pgtkterm (void);
extern void mark_pgtkterm (void);
-extern void pgtk_delete_terminal (struct terminal *terminal);
+extern void pgtk_delete_terminal (struct terminal *);
-extern void pgtk_make_frame_visible (struct frame *f);
-extern void pgtk_make_frame_invisible (struct frame *f);
-extern void x_wm_set_size_hint (struct frame *, long, bool);
-extern void x_free_frame_resources (struct frame *);
-extern void pgtk_iconify_frame (struct frame *f);
-extern void pgtk_focus_frame (struct frame *f, bool noactivate);
-extern void pgtk_set_scroll_bar_default_width (struct frame *f);
-extern void pgtk_set_scroll_bar_default_height (struct frame *f);
-extern Lisp_Object x_get_focus_frame (struct frame *frame);
+extern void pgtk_make_frame_visible (struct frame *);
+extern void pgtk_make_frame_invisible (struct frame *);
+extern void pgtk_free_frame_resources (struct frame *);
+extern void pgtk_iconify_frame (struct frame *);
+extern void pgtk_focus_frame (struct frame *, bool);
+extern void pgtk_set_scroll_bar_default_width (struct frame *);
+extern void pgtk_set_scroll_bar_default_height (struct frame *);
+extern Lisp_Object pgtk_get_focus_frame (struct frame *);
-extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo);
+extern void pgtk_frame_rehighlight (struct pgtk_display_info *);
-extern void x_change_tab_bar_height (struct frame *, int);
+extern void pgtk_change_tab_bar_height (struct frame *, int);
-extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object);
+extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object);
-extern void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms);
+extern void pgtk_default_font_parameter (struct frame *, Lisp_Object);
-extern void pgtk_menu_set_in_use (bool in_use);
+extern void pgtk_menu_set_in_use (bool);
+/* Drag and drop functions used by Lisp. */
+extern void pgtk_update_drop_status (Lisp_Object, Lisp_Object);
+extern void pgtk_finish_drop (Lisp_Object, Lisp_Object, Lisp_Object);
-extern void pgtk_enqueue_string (struct frame *f, gchar * str);
-extern void pgtk_enqueue_preedit (struct frame *f, Lisp_Object image_data);
-extern void pgtk_im_focus_in (struct frame *f);
-extern void pgtk_im_focus_out (struct frame *f);
-extern bool pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev);
-extern void pgtk_im_set_cursor_location (struct frame *f, int x, int y,
- int width, int height);
-extern void pgtk_im_init (struct pgtk_display_info *dpyinfo);
-extern void pgtk_im_finish (struct pgtk_display_info *dpyinfo);
+extern void pgtk_enqueue_string (struct frame *, gchar *);
+extern void pgtk_enqueue_preedit (struct frame *, Lisp_Object);
+extern void pgtk_im_focus_in (struct frame *);
+extern void pgtk_im_focus_out (struct frame *);
+extern bool pgtk_im_filter_keypress (struct frame *, GdkEventKey *);
+extern void pgtk_im_set_cursor_location (struct frame *, int, int,
+ int, int);
+extern void pgtk_im_init (struct pgtk_display_info *);
+extern void pgtk_im_finish (struct pgtk_display_info *);
extern bool xg_set_icon (struct frame *, Lisp_Object);
-extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data);
+extern bool xg_set_icon_from_xpm_data (struct frame *, const char **);
-extern bool pgtk_text_icon (struct frame *f, const char *icon_name);
+extern bool pgtk_text_icon (struct frame *, const char *);
extern double pgtk_frame_scale_factor (struct frame *);
extern int pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *, int);
diff --git a/src/print.c b/src/print.c
index a3c9011215f..4d7e42df1e8 100644
--- a/src/print.c
+++ b/src/print.c
@@ -101,7 +101,7 @@ bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
struct buffer *old = current_buffer; \
ptrdiff_t old_point = -1, start_point = -1; \
ptrdiff_t old_point_byte = -1, start_point_byte = -1; \
- ptrdiff_t specpdl_count = SPECPDL_INDEX (); \
+ specpdl_ref specpdl_count = SPECPDL_INDEX (); \
bool free_print_buffer = 0; \
bool multibyte \
= !NILP (BVAR (current_buffer, enable_multibyte_characters)); \
@@ -556,7 +556,7 @@ write_string (const char *data, Lisp_Object printcharfun)
void
temp_output_buffer_setup (const char *bufname)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
register struct buffer *old = current_buffer;
register Lisp_Object buf;
@@ -620,7 +620,86 @@ If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used. */)
return val;
}
-DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0,
+static Lisp_Object Vprint_variable_mapping;
+
+static void
+print_bind_all_defaults (void)
+{
+ for (Lisp_Object vars = Vprint_variable_mapping; !NILP (vars);
+ vars = XCDR (vars))
+ {
+ Lisp_Object elem = XCDR (XCAR (vars));
+ specbind (XCAR (elem), XCAR (XCDR (elem)));
+ }
+}
+
+static void
+print_create_variable_mapping (void)
+{
+ Lisp_Object total[] = {
+ list3 (intern ("length"), intern ("print-length"), Qnil),
+ list3 (intern ("level"), intern ("print-level"), Qnil),
+ list3 (intern ("circle"), intern ("print-circle"), Qnil),
+ list3 (intern ("quoted"), intern ("print-quoted"), Qt),
+ list3 (intern ("escape-newlines"), intern ("print-escape-newlines"), Qnil),
+ list3 (intern ("escape-control-characters"),
+ intern ("print-escape-control-characters"), Qnil),
+ list3 (intern ("escape-nonascii"), intern ("print-escape-nonascii"), Qnil),
+ list3 (intern ("escape-multibyte"),
+ intern ("print-escape-multibyte"), Qnil),
+ list3 (intern ("charset-text-property"),
+ intern ("print-charset-text-property"), Qnil),
+ list3 (intern ("unreadeable-function"),
+ intern ("print-unreadable-function"), Qnil),
+ list3 (intern ("gensym"), intern ("print-gensym"), Qnil),
+ list3 (intern ("continuous-numbering"),
+ intern ("print-continuous-numbering"), Qnil),
+ list3 (intern ("number-table"), intern ("print-number-table"), Qnil),
+ list3 (intern ("float-format"), intern ("float-output-format"), Qnil),
+ list3 (intern ("integers-as-characters"),
+ intern ("print-integers-as-characters"), Qnil),
+ };
+
+ Vprint_variable_mapping = CALLMANY (Flist, total);
+}
+
+static void
+print_bind_overrides (Lisp_Object overrides)
+{
+ if (NILP (Vprint_variable_mapping))
+ print_create_variable_mapping ();
+
+ if (EQ (overrides, Qt))
+ print_bind_all_defaults ();
+ else if (!CONSP (overrides))
+ xsignal (Qwrong_type_argument, Qconsp);
+ else
+ {
+ while (!NILP (overrides))
+ {
+ Lisp_Object setting = XCAR (overrides);
+ if (EQ (setting, Qt))
+ print_bind_all_defaults ();
+ else if (!CONSP (setting))
+ xsignal (Qwrong_type_argument, Qconsp);
+ else
+ {
+ Lisp_Object key = XCAR (setting),
+ value = XCDR (setting);
+ Lisp_Object map = Fassq (key, Vprint_variable_mapping);
+ if (NILP (map))
+ xsignal2 (Qwrong_type_argument, Qsymbolp, map);
+ specbind (XCAR (XCDR (map)), value);
+ }
+
+ if (!NILP (XCDR (overrides)) && !CONSP (XCDR (overrides)))
+ xsignal (Qwrong_type_argument, Qconsp);
+ overrides = XCDR (overrides);
+ }
+ }
+}
+
+DEFUN ("prin1", Fprin1, Sprin1, 1, 3, 0,
doc: /* Output the printed representation of OBJECT, any Lisp object.
Quoting characters are printed when needed to make output that `read'
can handle, whenever this is possible. For complex objects, the behavior
@@ -642,21 +721,43 @@ of these:
- t, in which case the output is displayed in the echo area.
If PRINTCHARFUN is omitted, the value of `standard-output' (which see)
-is used instead. */)
- (Lisp_Object object, Lisp_Object printcharfun)
+is used instead.
+
+Optional argument OVERRIDES should be a list of settings for print-related
+variables. An element in this list can be the symbol t, which means "reset
+all the values to their defaults". Otherwise, an element should be a pair,
+where the `car' or the pair is the setting symbol, and the `cdr' is the
+value of the setting to use for this `prin1' call.
+
+For instance:
+
+ (prin1 object nil \\='((length . 100) (circle . t))).
+
+See the manual entry `(elisp)Output Overrides' for a list of possible
+values.
+
+As a special case, OVERRIDES can also simply be the symbol t, which
+means "use default values for all the print-related settings". */)
+ (Lisp_Object object, Lisp_Object printcharfun, Lisp_Object overrides)
{
+ specpdl_ref count = SPECPDL_INDEX ();
+
if (NILP (printcharfun))
printcharfun = Vstandard_output;
+ if (!NILP (overrides))
+ print_bind_overrides (overrides);
+
PRINTPREPARE;
print (object, printcharfun, 1);
PRINTFINISH;
- return object;
+
+ return unbind_to (count, object);
}
/* A buffer which is used to hold output being built by prin1-to-string. */
Lisp_Object Vprin1_to_string_buffer;
-DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 2, 0,
+DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 3, 0,
doc: /* Return a string containing the printed representation of OBJECT.
OBJECT can be any Lisp object. This function outputs quoting characters
when necessary to make output that `read' can handle, whenever possible,
@@ -666,13 +767,18 @@ the behavior is controlled by `print-level' and `print-length', which see.
OBJECT is any of the Lisp data types: a number, a string, a symbol,
a list, a buffer, a window, a frame, etc.
+See `prin1' for the meaning of OVERRIDES.
+
A printed representation of an object is text which describes that object. */)
- (Lisp_Object object, Lisp_Object noescape)
+ (Lisp_Object object, Lisp_Object noescape, Lisp_Object overrides)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_modification_hooks, Qt);
+ if (!NILP (overrides))
+ print_bind_overrides (overrides);
+
/* Save and restore this: we are altering a buffer
but we don't want to deactivate the mark just for that.
No need for specbind, since errors deactivate the mark. */
@@ -728,7 +834,13 @@ is used instead. */)
if (NILP (printcharfun))
printcharfun = Vstandard_output;
PRINTPREPARE;
- print (object, printcharfun, 0);
+ if (STRINGP (object)
+ && !string_intervals (object)
+ && NILP (Vprint_continuous_numbering))
+ /* fast path for plain strings */
+ print_string (object, printcharfun);
+ else
+ print (object, printcharfun, 0);
PRINTFINISH;
return object;
}
@@ -768,6 +880,16 @@ is used instead. */)
return object;
}
+DEFUN ("flush-standard-output", Fflush_standard_output, Sflush_standard_output,
+ 0, 0, 0,
+ doc: /* Flush standard-output.
+This can be useful after using `princ' and the like in scripts. */)
+ (void)
+{
+ fflush (stdout);
+ return Qnil;
+}
+
DEFUN ("external-debugging-output", Fexternal_debugging_output, Sexternal_debugging_output, 1, 1, 0,
doc: /* Write CHARACTER to stderr.
You can call `print' while debugging emacs, and pass it this function
@@ -837,7 +959,7 @@ append to existing target file. */)
void
debug_print (Lisp_Object arg)
{
- Fprin1 (arg, Qexternal_debugging_output);
+ Fprin1 (arg, Qexternal_debugging_output, Qnil);
fputs ("\r\n", stderr);
}
@@ -944,7 +1066,14 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
errmsg = Fget (errname, Qerror_message);
/* During loadup 'substitute-command-keys' might not be available. */
if (!NILP (Ffboundp (Qsubstitute_command_keys)))
- errmsg = call1 (Qsubstitute_command_keys, errmsg);
+ {
+ /* `substitute-command-keys' may bug out, which would lead
+ to infinite recursion when we're called from
+ skip_debugger, so ignore errors. */
+ Lisp_Object subs = safe_call1 (Qsubstitute_command_keys, errmsg);
+ if (!NILP (subs))
+ errmsg = subs;
+ }
file_error = Fmemq (Qfile_error, error_conditions);
}
@@ -978,7 +1107,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
|| EQ (errname, Qend_of_file) || EQ (errname, Quser_error))
Fprinc (obj, stream);
else
- Fprin1 (obj, stream);
+ Fprin1 (obj, stream, Qnil);
}
}
}
@@ -1126,7 +1255,6 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{
/* Construct Vprint_number_table.
This increments print_number_index for the objects added. */
- print_depth = 0;
print_preprocess (obj);
if (HASH_TABLE_P (Vprint_number_table))
@@ -1138,7 +1266,7 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
Lisp_Object key = HASH_KEY (h, i);
- if (!EQ (key, Qunbound)
+ if (!BASE_EQ (key, Qunbound)
&& EQ (HASH_VALUE (h, i), Qt))
Fremhash (key, Vprint_number_table);
}
@@ -1150,10 +1278,7 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
}
#define PRINT_CIRCLE_CANDIDATE_P(obj) \
- ((STRINGP (obj) \
- && (string_intervals (obj) \
- || print_depth > 1 \
- || !NILP (Vprint_continuous_numbering))) \
+ (STRINGP (obj) \
|| CONSP (obj) \
|| (VECTORLIKEP (obj) \
&& (VECTORP (obj) || COMPILEDP (obj) \
@@ -1164,6 +1289,78 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
&& SYMBOLP (obj) \
&& !SYMBOL_INTERNED_P (obj)))
+/* The print preprocess stack, used to traverse data structures. */
+
+struct print_pp_entry {
+ ptrdiff_t n; /* number of values, or 0 if a single value */
+ union {
+ Lisp_Object value; /* when n = 0 */
+ Lisp_Object *values; /* when n > 0 */
+ } u;
+};
+
+struct print_pp_stack {
+ struct print_pp_entry *stack; /* base of stack */
+ ptrdiff_t size; /* allocated size in entries */
+ ptrdiff_t sp; /* current number of entries */
+};
+
+static struct print_pp_stack ppstack = {NULL, 0, 0};
+
+NO_INLINE static void
+grow_pp_stack (void)
+{
+ struct print_pp_stack *ps = &ppstack;
+ eassert (ps->sp == ps->size);
+ ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack);
+ eassert (ps->sp < ps->size);
+}
+
+static inline void
+pp_stack_push_value (Lisp_Object value)
+{
+ if (ppstack.sp >= ppstack.size)
+ grow_pp_stack ();
+ ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = 0,
+ .u.value = value};
+}
+
+static inline void
+pp_stack_push_values (Lisp_Object *values, ptrdiff_t n)
+{
+ eassume (n >= 0);
+ if (n == 0)
+ return;
+ if (ppstack.sp >= ppstack.size)
+ grow_pp_stack ();
+ ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = n,
+ .u.values = values};
+}
+
+static inline bool
+pp_stack_empty_p (void)
+{
+ return ppstack.sp <= 0;
+}
+
+static inline Lisp_Object
+pp_stack_pop (void)
+{
+ eassume (!pp_stack_empty_p ());
+ struct print_pp_entry *e = &ppstack.stack[ppstack.sp - 1];
+ if (e->n == 0) /* single value */
+ {
+ --ppstack.sp;
+ return e->u.value;
+ }
+ /* Array of values: pop them left to right, which seems to be slightly
+ faster than right to left. */
+ e->n--;
+ if (e->n == 0)
+ --ppstack.sp; /* last value consumed */
+ return (++e->u.values)[-1];
+}
+
/* Construct Vprint_number_table for the print-circle feature
according to the structure of OBJ. OBJ itself and all its elements
will be added to Vprint_number_table recursively if it is a list,
@@ -1175,86 +1372,81 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
static void
print_preprocess (Lisp_Object obj)
{
- int i;
- ptrdiff_t size;
- int loop_count = 0;
- Lisp_Object halftail;
-
eassert (!NILP (Vprint_circle));
+ ptrdiff_t base_sp = ppstack.sp;
- print_depth++;
- halftail = obj;
-
- loop:
- if (PRINT_CIRCLE_CANDIDATE_P (obj))
+ for (;;)
{
- if (!HASH_TABLE_P (Vprint_number_table))
- Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq);
-
- Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
- if (!NILP (num)
- /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
- always print the gensym with a number. This is a special for
- the lisp function byte-compile-output-docform. */
- || (!NILP (Vprint_continuous_numbering)
- && SYMBOLP (obj)
- && !SYMBOL_INTERNED_P (obj)))
- { /* OBJ appears more than once. Let's remember that. */
- if (!FIXNUMP (num))
- {
- print_number_index++;
- /* Negative number indicates it hasn't been printed yet. */
- Fputhash (obj, make_fixnum (- print_number_index),
- Vprint_number_table);
+ if (PRINT_CIRCLE_CANDIDATE_P (obj))
+ {
+ if (!HASH_TABLE_P (Vprint_number_table))
+ Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq);
+
+ Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
+ if (!NILP (num)
+ /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
+ always print the gensym with a number. This is a special for
+ the lisp function byte-compile-output-docform. */
+ || (!NILP (Vprint_continuous_numbering)
+ && SYMBOLP (obj)
+ && !SYMBOL_INTERNED_P (obj)))
+ { /* OBJ appears more than once. Let's remember that. */
+ if (!FIXNUMP (num))
+ {
+ print_number_index++;
+ /* Negative number indicates it hasn't been printed yet. */
+ Fputhash (obj, make_fixnum (- print_number_index),
+ Vprint_number_table);
+ }
}
- print_depth--;
- return;
- }
- else
- /* OBJ is not yet recorded. Let's add to the table. */
- Fputhash (obj, Qt, Vprint_number_table);
+ else
+ {
+ /* OBJ is not yet recorded. Let's add to the table. */
+ Fputhash (obj, Qt, Vprint_number_table);
- switch (XTYPE (obj))
- {
- case Lisp_String:
- /* A string may have text properties, which can be circular. */
- traverse_intervals_noorder (string_intervals (obj),
- print_preprocess_string, NULL);
- break;
+ switch (XTYPE (obj))
+ {
+ case Lisp_String:
+ /* A string may have text properties,
+ which can be circular. */
+ traverse_intervals_noorder (string_intervals (obj),
+ print_preprocess_string, NULL);
+ break;
- case Lisp_Cons:
- /* Use HALFTAIL and LOOP_COUNT to detect circular lists,
- just as in print_object. */
- if (loop_count && EQ (obj, halftail))
- break;
- print_preprocess (XCAR (obj));
- obj = XCDR (obj);
- loop_count++;
- if (!(loop_count & 1))
- halftail = XCDR (halftail);
- goto loop;
-
- case Lisp_Vectorlike:
- size = ASIZE (obj);
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
- for (i = (SUB_CHAR_TABLE_P (obj)
- ? SUB_CHAR_TABLE_OFFSET : 0); i < size; i++)
- print_preprocess (AREF (obj, i));
- if (HASH_TABLE_P (obj))
- { /* For hash tables, the key_and_value slot is past
- `size' because it needs to be marked specially in case
- the table is weak. */
- struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
- print_preprocess (h->key_and_value);
- }
- break;
+ case Lisp_Cons:
+ if (!NILP (XCDR (obj)))
+ pp_stack_push_value (XCDR (obj));
+ obj = XCAR (obj);
+ continue;
- default:
- break;
+ case Lisp_Vectorlike:
+ {
+ struct Lisp_Vector *vec = XVECTOR (obj);
+ ptrdiff_t size = ASIZE (obj);
+ if (size & PSEUDOVECTOR_FLAG)
+ size &= PSEUDOVECTOR_SIZE_MASK;
+ ptrdiff_t start = (SUB_CHAR_TABLE_P (obj)
+ ? SUB_CHAR_TABLE_OFFSET : 0);
+ pp_stack_push_values (vec->contents + start, size - start);
+ if (HASH_TABLE_P (obj))
+ {
+ struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+ obj = h->key_and_value;
+ continue;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
}
+
+ if (ppstack.sp <= base_sp)
+ break;
+ obj = pp_stack_pop ();
}
- print_depth--;
}
DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0,
@@ -1387,6 +1579,7 @@ static bool
print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
char *buf)
{
+ /* First do all the vectorlike types that have a readable syntax. */
switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
{
case PVEC_BIGNUM:
@@ -1398,8 +1591,84 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
strout (str, len, len, printcharfun);
SAFE_FREE ();
}
+ return true;
+
+ case PVEC_BOOL_VECTOR:
+ {
+ EMACS_INT size = bool_vector_size (obj);
+ ptrdiff_t size_in_bytes = bool_vector_bytes (size);
+ ptrdiff_t real_size_in_bytes = size_in_bytes;
+ unsigned char *data = bool_vector_uchar_data (obj);
+
+ int len = sprintf (buf, "#&%"pI"d\"", size);
+ strout (buf, len, len, printcharfun);
+
+ /* Don't print more bytes than the specified maximum.
+ Negative values of print-length are invalid. Treat them
+ like a print-length of nil. */
+ if (FIXNATP (Vprint_length)
+ && XFIXNAT (Vprint_length) < size_in_bytes)
+ size_in_bytes = XFIXNAT (Vprint_length);
+
+ for (ptrdiff_t i = 0; i < size_in_bytes; i++)
+ {
+ maybe_quit ();
+ unsigned char c = data[i];
+ if (c == '\n' && print_escape_newlines)
+ print_c_string ("\\n", printcharfun);
+ else if (c == '\f' && print_escape_newlines)
+ print_c_string ("\\f", printcharfun);
+ else if (c > '\177'
+ || (print_escape_control_characters && c_iscntrl (c)))
+ {
+ /* Use octal escapes to avoid encoding issues. */
+ octalout (c, data, i + 1, size_in_bytes, printcharfun);
+ }
+ else
+ {
+ if (c == '\"' || c == '\\')
+ printchar ('\\', printcharfun);
+ printchar (c, printcharfun);
+ }
+ }
+
+ if (size_in_bytes < real_size_in_bytes)
+ print_c_string (" ...", printcharfun);
+ printchar ('\"', printcharfun);
+ }
+ return true;
+
+ default:
break;
+ }
+
+ /* Then do all the pseudovector types that don't have a readable
+ syntax. First check whether this is handled by
+ `print-unreadable-function'. */
+ if (!NILP (Vprint_unreadable_function)
+ && FUNCTIONP (Vprint_unreadable_function))
+ {
+ specpdl_ref count = SPECPDL_INDEX ();
+ /* Bind `print-unreadable-function' to nil to avoid accidental
+ infinite recursion in the function called. */
+ Lisp_Object func = Vprint_unreadable_function;
+ specbind (Qprint_unreadable_function, Qnil);
+ Lisp_Object result = CALLN (Ffuncall, func, obj,
+ escapeflag? Qt: Qnil);
+ unbind_to (count, Qnil);
+
+ if (!NILP (result))
+ {
+ if (STRINGP (result))
+ print_string (result, printcharfun);
+ /* It's handled, so stop processing here. */
+ return true;
+ }
+ }
+ /* Not handled; print unreadable object. */
+ switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
+ {
case PVEC_MARKER:
print_c_string ("#<marker ", printcharfun);
/* Do you think this is necessary? */
@@ -1416,6 +1685,30 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
printchar ('>', printcharfun);
break;
+ case PVEC_SYMBOL_WITH_POS:
+ {
+ struct Lisp_Symbol_With_Pos *sp = XSYMBOL_WITH_POS (obj);
+ if (print_symbols_bare)
+ print_object (sp->sym, printcharfun, escapeflag);
+ else
+ {
+ print_c_string ("#<symbol ", printcharfun);
+ if (BARE_SYMBOL_P (sp->sym))
+ print_object (sp->sym, printcharfun, escapeflag);
+ else
+ print_c_string ("NOT A SYMBOL!!", printcharfun);
+ if (FIXNUMP (sp->pos))
+ {
+ print_c_string (" at ", printcharfun);
+ print_object (sp->pos, printcharfun, escapeflag);
+ }
+ else
+ print_c_string (" NOT A POSITION!!", printcharfun);
+ printchar ('>', printcharfun);
+ }
+ }
+ break;
+
case PVEC_OVERLAY:
print_c_string ("#<overlay ", printcharfun);
if (! XMARKER (OVERLAY_START (obj))->buffer)
@@ -1437,7 +1730,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_c_string ("#<user-ptr ", printcharfun);
int i = sprintf (buf, "ptr=%p finalizer=%p",
XUSER_PTR (obj)->p,
- XUSER_PTR (obj)->finalizer);
+ (void *) XUSER_PTR (obj)->finalizer);
strout (buf, i, i, printcharfun);
printchar ('>', printcharfun);
}
@@ -1470,51 +1763,6 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_string (XPROCESS (obj)->name, printcharfun);
break;
- case PVEC_BOOL_VECTOR:
- {
- EMACS_INT size = bool_vector_size (obj);
- ptrdiff_t size_in_bytes = bool_vector_bytes (size);
- ptrdiff_t real_size_in_bytes = size_in_bytes;
- unsigned char *data = bool_vector_uchar_data (obj);
-
- int len = sprintf (buf, "#&%"pI"d\"", size);
- strout (buf, len, len, printcharfun);
-
- /* Don't print more bytes than the specified maximum.
- Negative values of print-length are invalid. Treat them
- like a print-length of nil. */
- if (FIXNATP (Vprint_length)
- && XFIXNAT (Vprint_length) < size_in_bytes)
- size_in_bytes = XFIXNAT (Vprint_length);
-
- for (ptrdiff_t i = 0; i < size_in_bytes; i++)
- {
- maybe_quit ();
- unsigned char c = data[i];
- if (c == '\n' && print_escape_newlines)
- print_c_string ("\\n", printcharfun);
- else if (c == '\f' && print_escape_newlines)
- print_c_string ("\\f", printcharfun);
- else if (c > '\177'
- || (print_escape_control_characters && c_iscntrl (c)))
- {
- /* Use octal escapes to avoid encoding issues. */
- octalout (c, data, i + 1, size_in_bytes, printcharfun);
- }
- else
- {
- if (c == '\"' || c == '\\')
- printchar ('\\', printcharfun);
- printchar (c, printcharfun);
- }
- }
-
- if (size_in_bytes < real_size_in_bytes)
- print_c_string (" ...", printcharfun);
- printchar ('\"', printcharfun);
- }
- break;
-
case PVEC_SUBR:
print_c_string ("#<subr ", printcharfun);
print_c_string (XSUBR (obj)->symbol_name, printcharfun);
@@ -1578,79 +1826,6 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
break;
- case PVEC_HASH_TABLE:
- {
- struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
- /* Implement a readable output, e.g.:
- #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
- /* Always print the size. */
- int len = sprintf (buf, "#s(hash-table size %"pD"d",
- HASH_TABLE_SIZE (h));
- strout (buf, len, len, printcharfun);
-
- if (!NILP (h->test.name))
- {
- print_c_string (" test ", printcharfun);
- print_object (h->test.name, printcharfun, escapeflag);
- }
-
- if (!NILP (h->weak))
- {
- print_c_string (" weakness ", printcharfun);
- print_object (h->weak, printcharfun, escapeflag);
- }
-
- print_c_string (" rehash-size ", printcharfun);
- print_object (Fhash_table_rehash_size (obj),
- printcharfun, escapeflag);
-
- print_c_string (" rehash-threshold ", printcharfun);
- print_object (Fhash_table_rehash_threshold (obj),
- printcharfun, escapeflag);
-
- if (h->purecopy)
- {
- print_c_string (" purecopy ", printcharfun);
- print_object (h->purecopy ? Qt : Qnil, printcharfun, escapeflag);
- }
-
- print_c_string (" data ", printcharfun);
-
- /* Print the data here as a plist. */
- ptrdiff_t real_size = HASH_TABLE_SIZE (h);
- ptrdiff_t size = h->count;
-
- /* Don't print more elements than the specified maximum. */
- if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
- size = XFIXNAT (Vprint_length);
-
- printchar ('(', printcharfun);
- ptrdiff_t j = 0;
- for (ptrdiff_t i = 0; i < real_size; i++)
- {
- Lisp_Object key = HASH_KEY (h, i);
- if (!EQ (key, Qunbound))
- {
- if (j++) printchar (' ', printcharfun);
- print_object (key, printcharfun, escapeflag);
- printchar (' ', printcharfun);
- print_object (HASH_VALUE (h, i), printcharfun, escapeflag);
- if (j == size)
- break;
- }
- }
-
- if (j < h->count)
- {
- if (j)
- printchar (' ', printcharfun);
- print_c_string ("...", printcharfun);
- }
-
- print_c_string ("))", printcharfun);
- }
- break;
-
case PVEC_BUFFER:
if (!BUFFER_LIVE_P (XBUFFER (obj)))
print_c_string ("#<killed buffer>", printcharfun);
@@ -1726,7 +1901,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_string (XTHREAD (obj)->name, printcharfun);
else
{
- int len = sprintf (buf, "%p", XTHREAD (obj));
+ void *p = XTHREAD (obj);
+ int len = sprintf (buf, "%p", p);
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
@@ -1738,7 +1914,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_string (XMUTEX (obj)->name, printcharfun);
else
{
- int len = sprintf (buf, "%p", XMUTEX (obj));
+ void *p = XMUTEX (obj);
+ int len = sprintf (buf, "%p", p);
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
@@ -1750,95 +1927,13 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_string (XCONDVAR (obj)->name, printcharfun);
else
{
- int len = sprintf (buf, "%p", XCONDVAR (obj));
+ void *p = XCONDVAR (obj);
+ int len = sprintf (buf, "%p", p);
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
break;
- case PVEC_RECORD:
- {
- ptrdiff_t size = PVSIZE (obj);
-
- /* Don't print more elements than the specified maximum. */
- ptrdiff_t n
- = (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size
- ? XFIXNAT (Vprint_length) : size);
-
- print_c_string ("#s(", printcharfun);
- for (ptrdiff_t i = 0; i < n; i ++)
- {
- if (i) printchar (' ', printcharfun);
- print_object (AREF (obj, i), printcharfun, escapeflag);
- }
- if (n < size)
- print_c_string (" ...", printcharfun);
- printchar (')', printcharfun);
- }
- break;
-
- case PVEC_SUB_CHAR_TABLE:
- case PVEC_COMPILED:
- case PVEC_CHAR_TABLE:
- case PVEC_NORMAL_VECTOR:
- {
- ptrdiff_t size = ASIZE (obj);
- if (COMPILEDP (obj))
- {
- printchar ('#', printcharfun);
- size &= PSEUDOVECTOR_SIZE_MASK;
- }
- if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj))
- {
- /* Print a char-table as if it were a vector,
- lumping the parent and default slots in with the
- character slots. But add #^ as a prefix. */
-
- /* Make each lowest sub_char_table start a new line.
- Otherwise we'll make a line extremely long, which
- results in slow redisplay. */
- if (SUB_CHAR_TABLE_P (obj)
- && XSUB_CHAR_TABLE (obj)->depth == 3)
- printchar ('\n', printcharfun);
- print_c_string ("#^", printcharfun);
- if (SUB_CHAR_TABLE_P (obj))
- printchar ('^', printcharfun);
- size &= PSEUDOVECTOR_SIZE_MASK;
- }
- if (size & PSEUDOVECTOR_FLAG)
- return false;
-
- printchar ('[', printcharfun);
-
- int idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0;
- Lisp_Object tem;
- ptrdiff_t real_size = size;
-
- /* For a sub char-table, print heading non-Lisp data first. */
- if (SUB_CHAR_TABLE_P (obj))
- {
- int i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth,
- XSUB_CHAR_TABLE (obj)->min_char);
- strout (buf, i, i, printcharfun);
- }
-
- /* Don't print more elements than the specified maximum. */
- if (FIXNATP (Vprint_length)
- && XFIXNAT (Vprint_length) < size)
- size = XFIXNAT (Vprint_length);
-
- for (int i = idx; i < size; i++)
- {
- if (i) printchar (' ', printcharfun);
- tem = AREF (obj, i);
- print_object (tem, printcharfun, escapeflag);
- }
- if (size < real_size)
- print_c_string (" ...", printcharfun);
- printchar (']', printcharfun);
- }
- break;
-
#ifdef HAVE_MODULES
case PVEC_MODULE_FUNCTION:
{
@@ -1921,32 +2016,132 @@ named_escape (int i)
return 0;
}
+enum print_entry_type
+ {
+ PE_list, /* print rest of list */
+ PE_rbrac, /* print ")" */
+ PE_vector, /* print rest of vector */
+ PE_hash, /* print rest of hash data */
+ };
+
+struct print_stack_entry
+{
+ enum print_entry_type type;
+
+ union
+ {
+ struct
+ {
+ Lisp_Object last; /* cons whose car was just printed */
+ intmax_t maxlen; /* max number of elements left to print */
+ /* State for Brent cycle detection. See
+ Brent RP. BIT. 1980;20(2):176-184. doi:10.1007/BF01933190
+ https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf */
+ Lisp_Object tortoise; /* slow pointer */
+ ptrdiff_t n; /* tortoise step countdown */
+ ptrdiff_t m; /* tortoise step period */
+ intmax_t tortoise_idx; /* index of tortoise */
+ } list;
+
+ struct
+ {
+ Lisp_Object obj; /* object to print after " . " */
+ } dotted_cdr;
+
+ struct
+ {
+ Lisp_Object obj; /* vector object */
+ ptrdiff_t size; /* length of vector */
+ ptrdiff_t idx; /* index of next element */
+ const char *end; /* string to print at end */
+ bool truncated; /* whether to print "..." before end */
+ } vector;
+
+ struct
+ {
+ Lisp_Object obj; /* hash-table object */
+ ptrdiff_t nobjs; /* number of keys and values to print */
+ ptrdiff_t idx; /* index of key-value pair */
+ ptrdiff_t printed; /* number of keys and values printed */
+ bool truncated; /* whether to print "..." before end */
+ } hash;
+ } u;
+};
+
+struct print_stack
+{
+ struct print_stack_entry *stack; /* base of stack */
+ ptrdiff_t size; /* allocated size in entries */
+ ptrdiff_t sp; /* current number of entries */
+};
+
+static struct print_stack prstack = {NULL, 0, 0};
+
+NO_INLINE static void
+grow_print_stack (void)
+{
+ struct print_stack *ps = &prstack;
+ eassert (ps->sp == ps->size);
+ ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack);
+ eassert (ps->sp < ps->size);
+}
+
+static inline void
+print_stack_push (struct print_stack_entry e)
+{
+ if (prstack.sp >= prstack.size)
+ grow_print_stack ();
+ prstack.stack[prstack.sp++] = e;
+}
+
+static void
+print_stack_push_vector (const char *lbrac, const char *rbrac,
+ Lisp_Object obj, ptrdiff_t start, ptrdiff_t size,
+ Lisp_Object printcharfun)
+{
+ print_c_string (lbrac, printcharfun);
+
+ ptrdiff_t print_size = ((FIXNATP (Vprint_length)
+ && XFIXNAT (Vprint_length) < size)
+ ? XFIXNAT (Vprint_length) : size);
+ print_stack_push ((struct print_stack_entry){
+ .type = PE_vector,
+ .u.vector.obj = obj,
+ .u.vector.size = print_size,
+ .u.vector.idx = start,
+ .u.vector.end = rbrac,
+ .u.vector.truncated = (print_size < size),
+ });
+}
+
static void
print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{
+ ptrdiff_t base_depth = print_depth;
+ ptrdiff_t base_sp = prstack.sp;
char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
max (sizeof " . #" + INT_STRLEN_BOUND (intmax_t),
max ((sizeof " with data 0x"
+ (sizeof (uintmax_t) * CHAR_BIT + 4 - 1) / 4),
40)))];
current_thread->stack_top = buf;
+
+ print_obj:
maybe_quit ();
/* Detect circularities and truncate them. */
if (NILP (Vprint_circle))
{
/* Simple but incomplete way. */
- int i;
-
if (print_depth >= PRINT_CIRCLE)
error ("Apparently circular structure being printed");
- for (i = 0; i < print_depth; i++)
- if (EQ (obj, being_printed[i]))
+ for (int i = 0; i < print_depth; i++)
+ if (BASE_EQ (obj, being_printed[i]))
{
int len = sprintf (buf, "#%d", i);
strout (buf, len, len, printcharfun);
- return;
+ goto next_obj;
}
being_printed[print_depth] = obj;
}
@@ -1970,7 +2165,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
/* Just print #n# if OBJ has already been printed. */
int len = sprintf (buf, "#%"pI"d#", n);
strout (buf, len, len, printcharfun);
- return;
+ goto next_obj;
}
}
}
@@ -2004,8 +2199,10 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
}
else
{
- int len = sprintf (buf, "%"pI"d", i);
- strout (buf, len, len, printcharfun);
+ char *end = buf + sizeof buf;
+ char *start = fixnum_to_string (i, buf, end);
+ ptrdiff_t len = end - start;
+ strout (start, len, len, printcharfun);
}
}
break;
@@ -2042,7 +2239,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
for (i = 0, i_byte = 0; i_byte < size_byte;)
{
/* Here, we must convert each multi-byte form to the
- corresponding character code before handing it to printchar. */
+ corresponding character code before handing it to
+ printchar. */
int c = fetch_string_char_advance (obj, &i, &i_byte);
maybe_quit ();
@@ -2062,7 +2260,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
else if (multibyte
&& ! ASCII_CHAR_P (c) && print_escape_multibyte)
{
- /* When requested, print multibyte chars using hex escapes. */
+ /* When requested, print multibyte chars using
+ hex escapes. */
char outbuf[sizeof "\\x" + INT_STRLEN_BOUND (c)];
int len = sprintf (outbuf, "\\x%04x", c + 0u);
strout (outbuf, len, len, printcharfun);
@@ -2115,14 +2314,19 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
Lisp_Object name = SYMBOL_NAME (obj);
ptrdiff_t size_byte = SBYTES (name);
- /* Set CONFUSING if NAME looks like a number, calling
- string_to_number for non-obvious cases. */
char *p = SSDATA (name);
bool signedp = *p == '-' || *p == '+';
ptrdiff_t len;
- bool confusing = ((c_isdigit (p[signedp]) || p[signedp] == '.')
- && !NILP (string_to_number (p, 10, &len))
- && len == size_byte);
+ bool confusing =
+ /* Set CONFUSING if NAME looks like a number, calling
+ string_to_number for non-obvious cases. */
+ ((c_isdigit (p[signedp]) || p[signedp] == '.')
+ && !NILP (string_to_number (p, 10, &len))
+ && len == size_byte)
+ /* We don't escape "." or "?" (unless they're the first
+ character in the symbol name). */
+ || *p == '?'
+ || *p == '.';
if (! NILP (Vprint_gensym)
&& !SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (obj))
@@ -2145,8 +2349,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
{
if (c == '\"' || c == '\\' || c == '\''
|| c == ';' || c == '#' || c == '(' || c == ')'
- || c == ',' || c == '.' || c == '`'
- || c == '[' || c == ']' || c == '?' || c <= 040
+ || c == ',' || c == '`'
+ || c == '[' || c == ']' || c <= 040
|| c == NO_BREAK_SPACE
|| confusing)
{
@@ -2168,14 +2372,22 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
&& EQ (XCAR (obj), Qquote))
{
printchar ('\'', printcharfun);
- print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
+ obj = XCAR (XCDR (obj));
+ --print_depth; /* tail recursion */
+ goto print_obj;
}
else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
&& EQ (XCAR (obj), Qfunction))
{
print_c_string ("#'", printcharfun);
- print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
+ obj = XCAR (XCDR (obj));
+ --print_depth; /* tail recursion */
+ goto print_obj;
}
+ /* FIXME: Do we really need the new_backquote_output gating of
+ special syntax for comma and comma-at? There is basically no
+ benefit from it at all, and it would be nice to get rid of
+ the recursion here without additional complexity. */
else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
&& EQ (XCAR (obj), Qbackquote))
{
@@ -2185,9 +2397,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
new_backquote_output--;
}
else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
- && new_backquote_output
&& (EQ (XCAR (obj), Qcomma)
- || EQ (XCAR (obj), Qcomma_at)))
+ || EQ (XCAR (obj), Qcomma_at))
+ && new_backquote_output)
{
print_object (XCAR (obj), printcharfun, false);
new_backquote_output--;
@@ -2197,70 +2409,135 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
else
{
printchar ('(', printcharfun);
-
/* Negative values of print-length are invalid in CL.
Treat them like nil, as CMUCL does. */
intmax_t print_length = (FIXNATP (Vprint_length)
? XFIXNAT (Vprint_length)
: INTMAX_MAX);
- Lisp_Object objtail = Qnil;
- intmax_t i = 0;
- FOR_EACH_TAIL_SAFE (obj)
+ if (print_length == 0)
+ print_c_string ("...)", printcharfun);
+ else
{
- if (i != 0)
- {
- printchar (' ', printcharfun);
-
- if (!NILP (Vprint_circle))
- {
- /* With the print-circle feature. */
- Lisp_Object num = Fgethash (obj, Vprint_number_table,
- Qnil);
- if (FIXNUMP (num))
- {
- print_c_string (". ", printcharfun);
- print_object (obj, printcharfun, escapeflag);
- goto end_of_list;
- }
- }
- }
-
- if (print_length <= i)
- {
- print_c_string ("...", printcharfun);
- goto end_of_list;
- }
-
- i++;
- print_object (XCAR (obj), printcharfun, escapeflag);
- objtail = XCDR (obj);
+ print_stack_push ((struct print_stack_entry){
+ .type = PE_list,
+ .u.list.last = obj,
+ .u.list.maxlen = print_length,
+ .u.list.tortoise = obj,
+ .u.list.n = 2,
+ .u.list.m = 2,
+ .u.list.tortoise_idx = 0,
+ });
+ /* print the car */
+ obj = XCAR (obj);
+ goto print_obj;
}
+ }
+ break;
- /* OBJTAIL non-nil here means it's the end of a dotted list
- or FOR_EACH_TAIL_SAFE detected a circular list. */
- if (!NILP (objtail))
- {
- print_c_string (" . ", printcharfun);
+ case Lisp_Vectorlike:
+ /* First do all the vectorlike types that have a readable syntax. */
+ switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
+ {
+ case PVEC_NORMAL_VECTOR:
+ {
+ print_stack_push_vector ("[", "]", obj, 0, ASIZE (obj),
+ printcharfun);
+ goto next_obj;
+ }
+ case PVEC_RECORD:
+ {
+ print_stack_push_vector ("#s(", ")", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
+ }
+ case PVEC_COMPILED:
+ {
+ print_stack_push_vector ("#[", "]", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
+ }
+ case PVEC_CHAR_TABLE:
+ {
+ print_stack_push_vector ("#^[", "]", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
+ }
+ case PVEC_SUB_CHAR_TABLE:
+ {
+ /* Make each lowest sub_char_table start a new line.
+ Otherwise we'll make a line extremely long, which
+ results in slow redisplay. */
+ if (XSUB_CHAR_TABLE (obj)->depth == 3)
+ printchar ('\n', printcharfun);
+ print_c_string ("#^^[", printcharfun);
+ int n = sprintf (buf, "%d %d",
+ XSUB_CHAR_TABLE (obj)->depth,
+ XSUB_CHAR_TABLE (obj)->min_char);
+ strout (buf, n, n, printcharfun);
+ print_stack_push_vector ("", "]", obj,
+ SUB_CHAR_TABLE_OFFSET, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
+ }
+ case PVEC_HASH_TABLE:
+ {
+ struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
+ /* Implement a readable output, e.g.:
+ #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
+ /* Always print the size. */
+ int len = sprintf (buf, "#s(hash-table size %"pD"d",
+ HASH_TABLE_SIZE (h));
+ strout (buf, len, len, printcharfun);
- if (CONSP (objtail) && NILP (Vprint_circle))
- {
- int len = sprintf (buf, "#%"PRIdMAX, i >> 1);
- strout (buf, len, len, printcharfun);
- goto end_of_list;
- }
+ if (!NILP (h->test.name))
+ {
+ print_c_string (" test ", printcharfun);
+ print_object (h->test.name, printcharfun, escapeflag);
+ }
- print_object (objtail, printcharfun, escapeflag);
- }
+ if (!NILP (h->weak))
+ {
+ print_c_string (" weakness ", printcharfun);
+ print_object (h->weak, printcharfun, escapeflag);
+ }
- end_of_list:
- printchar (')', printcharfun);
+ print_c_string (" rehash-size ", printcharfun);
+ print_object (Fhash_table_rehash_size (obj),
+ printcharfun, escapeflag);
+
+ print_c_string (" rehash-threshold ", printcharfun);
+ print_object (Fhash_table_rehash_threshold (obj),
+ printcharfun, escapeflag);
+
+ if (h->purecopy)
+ print_c_string (" purecopy t", printcharfun);
+
+ print_c_string (" data (", printcharfun);
+
+ ptrdiff_t size = h->count;
+ /* Don't print more elements than the specified maximum. */
+ if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
+ size = XFIXNAT (Vprint_length);
+
+ print_stack_push ((struct print_stack_entry){
+ .type = PE_hash,
+ .u.hash.obj = obj,
+ .u.hash.nobjs = size * 2,
+ .u.hash.idx = 0,
+ .u.hash.printed = 0,
+ .u.hash.truncated = (size < h->count),
+ });
+ goto next_obj;
+ }
+
+ default:
+ break;
}
- break;
- case Lisp_Vectorlike:
if (print_vectorlike (obj, printcharfun, escapeflag, buf))
break;
FALLTHROUGH;
+
default:
{
int len;
@@ -2275,10 +2552,157 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
print_c_string ((" Save your buffers immediately"
" and please report this bug>"),
printcharfun);
+ break;
}
}
-
print_depth--;
+
+ next_obj:
+ if (prstack.sp > base_sp)
+ {
+ /* Handle a continuation on the print stack. */
+ struct print_stack_entry *e = &prstack.stack[prstack.sp - 1];
+ switch (e->type)
+ {
+ case PE_list:
+ {
+ /* after "(" ELEM (* " " ELEM) */
+ Lisp_Object next = XCDR (e->u.list.last);
+ if (NILP (next))
+ {
+ /* end of list: print ")" */
+ printchar (')', printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+ }
+ else if (CONSP (next))
+ {
+ if (!NILP (Vprint_circle))
+ {
+ /* With the print-circle feature. */
+ Lisp_Object num = Fgethash (next, Vprint_number_table,
+ Qnil);
+ if (FIXNUMP (num))
+ {
+ print_c_string (" . ", printcharfun);
+ obj = next;
+ e->type = PE_rbrac;
+ goto print_obj;
+ }
+ }
+
+ /* list continues: print " " ELEM ... */
+
+ printchar (' ', printcharfun);
+
+ --e->u.list.maxlen;
+ if (e->u.list.maxlen <= 0)
+ {
+ print_c_string ("...)", printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+ }
+
+ e->u.list.last = next;
+ e->u.list.n--;
+ if (e->u.list.n == 0)
+ {
+ /* Double tortoise update period and teleport it. */
+ e->u.list.tortoise_idx += e->u.list.m;
+ e->u.list.m <<= 1;
+ e->u.list.n = e->u.list.m;
+ e->u.list.tortoise = next;
+ }
+ else if (BASE_EQ (next, e->u.list.tortoise))
+ {
+ /* FIXME: This #N tail index is somewhat ambiguous;
+ see bug#55395. */
+ int len = sprintf (buf, ". #%" PRIdMAX ")",
+ e->u.list.tortoise_idx);
+ strout (buf, len, len, printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+ }
+ obj = XCAR (next);
+ }
+ else
+ {
+ /* non-nil ending: print " . " ELEM ")" */
+ print_c_string (" . ", printcharfun);
+ obj = next;
+ e->type = PE_rbrac;
+ }
+ break;
+ }
+
+ case PE_rbrac:
+ printchar (')', printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+
+ case PE_vector:
+ if (e->u.vector.idx >= e->u.vector.size)
+ {
+ if (e->u.vector.truncated)
+ {
+ if (e->u.vector.idx > 0)
+ printchar (' ', printcharfun);
+ print_c_string ("...", printcharfun);
+ }
+ print_c_string (e->u.vector.end, printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+ }
+ if (e->u.vector.idx > 0)
+ printchar (' ', printcharfun);
+ obj = AREF (e->u.vector.obj, e->u.vector.idx);
+ e->u.vector.idx++;
+ break;
+
+ case PE_hash:
+ if (e->u.hash.printed >= e->u.hash.nobjs)
+ {
+ if (e->u.hash.truncated)
+ {
+ if (e->u.hash.printed)
+ printchar (' ', printcharfun);
+ print_c_string ("...", printcharfun);
+ }
+ print_c_string ("))", printcharfun);
+ --prstack.sp;
+ --print_depth;
+ goto next_obj;
+ }
+
+ if (e->u.hash.printed)
+ printchar (' ', printcharfun);
+
+ struct Lisp_Hash_Table *h = XHASH_TABLE (e->u.hash.obj);
+ if ((e->u.hash.printed & 1) == 0)
+ {
+ Lisp_Object key;
+ ptrdiff_t idx = e->u.hash.idx;
+ while (BASE_EQ ((key = HASH_KEY (h, idx)), Qunbound))
+ idx++;
+ e->u.hash.idx = idx;
+ obj = key;
+ }
+ else
+ {
+ obj = HASH_VALUE (h, e->u.hash.idx);
+ e->u.hash.idx++;
+ }
+ e->u.hash.printed++;
+ break;
+ }
+ goto print_obj;
+ }
+ eassert (print_depth == base_depth);
}
@@ -2446,6 +2870,13 @@ priorities. Values other than nil or t are also treated as
`default'. */);
Vprint_charset_text_property = Qdefault;
+ DEFVAR_BOOL ("print-symbols-bare", print_symbols_bare,
+ doc: /* A flag to control printing of symbols with position.
+If the value is nil, print these objects complete with position.
+Otherwise print just the bare symbol. */);
+ print_symbols_bare = false;
+ DEFSYM (Qprint_symbols_bare, "print-symbols-bare");
+
/* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
staticpro (&Vprin1_to_string_buffer);
@@ -2464,4 +2895,24 @@ priorities. Values other than nil or t are also treated as
print_prune_charset_plist = Qnil;
staticpro (&print_prune_charset_plist);
+
+ DEFVAR_LISP ("print-unreadable-function", Vprint_unreadable_function,
+ doc: /* If non-nil, a function to call when printing unreadable objects.
+By default, Emacs printing functions (like `prin1') print unreadable
+objects as \"#<...>\", where \"...\" describes the object (for
+instance, \"#<marker in no buffer>\").
+
+If non-nil, it should be a function that will be called with two
+arguments: the object to be printed, and the NOESCAPE flag (see
+`prin1-to-string'). If this function returns nil, the object will be
+printed as usual. If it returns a string, that string will then be
+printed. If the function returns anything else, the object will not
+be printed. */);
+ Vprint_unreadable_function = Qnil;
+ DEFSYM (Qprint_unreadable_function, "print-unreadable-function");
+
+ defsubr (&Sflush_standard_output);
+
+ /* Initialized in print_create_variable_mapping. */
+ staticpro (&Vprint_variable_mapping);
}
diff --git a/src/process.c b/src/process.c
index 9664180cfd4..d6d51b26e11 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1071,13 +1071,24 @@ record_deleted_pid (pid_t pid, Lisp_Object filename)
}
-DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
+DEFUN ("delete-process", Fdelete_process, Sdelete_process, 0, 1,
+ "(list 'message)",
doc: /* Delete PROCESS: kill it and forget about it immediately.
PROCESS may be a process, a buffer, the name of a process or buffer, or
-nil, indicating the current buffer's process. */)
+nil, indicating the current buffer's process.
+
+Interactively, it will kill the current buffer's process. */)
(register Lisp_Object process)
{
register struct Lisp_Process *p;
+ bool mess = false;
+
+ /* We use this to see whether we were called interactively. */
+ if (EQ (process, Qmessage))
+ {
+ mess = true;
+ process = Qnil;
+ }
process = get_process (process);
p = XPROCESS (process);
@@ -1131,6 +1142,8 @@ nil, indicating the current buffer's process. */)
}
}
remove_process (process);
+ if (mess)
+ message ("Deleted process");
return Qnil;
}
@@ -1268,7 +1281,7 @@ Return BUFFER. */)
update_process_mark (p);
}
if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p))
- pset_childp (p, Fplist_put (p->childp, QCbuffer, buffer));
+ pset_childp (p, plist_put (p->childp, QCbuffer, buffer));
setup_process_coding_systems (process);
return buffer;
}
@@ -1347,7 +1360,7 @@ The string argument is normally a multibyte string, except:
pset_filter (p, filter);
if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p))
- pset_childp (p, Fplist_put (p->childp, QCfilter, filter));
+ pset_childp (p, plist_put (p->childp, QCfilter, filter));
setup_process_coding_systems (process);
return filter;
}
@@ -1379,7 +1392,7 @@ It gets two arguments: the process, and a string describing the change. */)
pset_sentinel (p, sentinel);
if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p))
- pset_childp (p, Fplist_put (p->childp, QCsentinel, sentinel));
+ pset_childp (p, plist_put (p->childp, QCsentinel, sentinel));
return sentinel;
}
@@ -1540,25 +1553,25 @@ waiting for the process to be fully set up.*/)
if (DATAGRAM_CONN_P (process)
&& (EQ (key, Qt) || EQ (key, QCremote)))
- contact = Fplist_put (contact, QCremote,
- Fprocess_datagram_address (process));
+ contact = plist_put (contact, QCremote,
+ Fprocess_datagram_address (process));
#endif
if ((!NETCONN_P (process) && !SERIALCONN_P (process) && !PIPECONN_P (process))
|| EQ (key, Qt))
return contact;
if (NILP (key) && NETCONN_P (process))
- return list2 (Fplist_get (contact, QChost),
- Fplist_get (contact, QCservice));
+ return list2 (plist_get (contact, QChost),
+ plist_get (contact, QCservice));
if (NILP (key) && SERIALCONN_P (process))
- return list2 (Fplist_get (contact, QCport),
- Fplist_get (contact, QCspeed));
+ return list2 (plist_get (contact, QCport),
+ plist_get (contact, QCspeed));
/* FIXME: Return a meaningful value (e.g., the child end of the pipe)
if the pipe process is useful for purposes other than receiving
stderr. */
if (NILP (key) && PIPECONN_P (process))
return Qt;
- return Fplist_get (contact, key);
+ return plist_get (contact, key);
}
DEFUN ("process-plist", Fprocess_plist, Sprocess_plist,
@@ -1752,7 +1765,7 @@ usage: (make-process &rest ARGS) */)
{
Lisp_Object buffer, name, command, program, proc, contact, current_dir, tem;
Lisp_Object xstderr, stderrproc;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (nargs == 0)
return Qnil;
@@ -1760,7 +1773,7 @@ usage: (make-process &rest ARGS) */)
/* Save arguments for process-contact and clone-process. */
contact = Flist (nargs, args);
- if (!NILP (Fplist_get (contact, QCfile_handler)))
+ if (!NILP (plist_get (contact, QCfile_handler)))
{
Lisp_Object file_handler
= Ffind_file_name_handler (BVAR (current_buffer, directory),
@@ -1769,7 +1782,7 @@ usage: (make-process &rest ARGS) */)
return CALLN (Fapply, file_handler, Qmake_process, contact);
}
- buffer = Fplist_get (contact, QCbuffer);
+ buffer = plist_get (contact, QCbuffer);
if (!NILP (buffer))
buffer = Fget_buffer_create (buffer, Qnil);
@@ -1779,10 +1792,10 @@ usage: (make-process &rest ARGS) */)
chdir, since it's in a vfork. */
current_dir = get_current_directory (true);
- name = Fplist_get (contact, QCname);
+ name = plist_get (contact, QCname);
CHECK_STRING (name);
- command = Fplist_get (contact, QCcommand);
+ command = plist_get (contact, QCcommand);
if (CONSP (command))
program = XCAR (command);
else
@@ -1791,10 +1804,10 @@ usage: (make-process &rest ARGS) */)
if (!NILP (program))
CHECK_STRING (program);
- bool query_on_exit = NILP (Fplist_get (contact, QCnoquery));
+ bool query_on_exit = NILP (plist_get (contact, QCnoquery));
stderrproc = Qnil;
- xstderr = Fplist_get (contact, QCstderr);
+ xstderr = plist_get (contact, QCstderr);
if (PROCESSP (xstderr))
{
if (!PIPECONN_P (xstderr))
@@ -1820,18 +1833,18 @@ usage: (make-process &rest ARGS) */)
eassert (NILP (XPROCESS (proc)->plist));
pset_type (XPROCESS (proc), Qreal);
pset_buffer (XPROCESS (proc), buffer);
- pset_sentinel (XPROCESS (proc), Fplist_get (contact, QCsentinel));
- pset_filter (XPROCESS (proc), Fplist_get (contact, QCfilter));
+ pset_sentinel (XPROCESS (proc), plist_get (contact, QCsentinel));
+ pset_filter (XPROCESS (proc), plist_get (contact, QCfilter));
pset_command (XPROCESS (proc), Fcopy_sequence (command));
if (!query_on_exit)
XPROCESS (proc)->kill_without_query = 1;
- tem = Fplist_get (contact, QCstop);
+ tem = plist_get (contact, QCstop);
/* Normal processes can't be started in a stopped state, see
Bug#30460. */
CHECK_TYPE (NILP (tem), Qnull, tem);
- tem = Fplist_get (contact, QCconnection_type);
+ tem = plist_get (contact, QCconnection_type);
if (EQ (tem, Qpty))
XPROCESS (proc)->pty_flag = true;
else if (EQ (tem, Qpipe))
@@ -1873,7 +1886,7 @@ usage: (make-process &rest ARGS) */)
Lisp_Object coding_systems = Qt;
Lisp_Object val, *args2;
- tem = Fplist_get (contact, QCcoding);
+ tem = plist_get (contact, QCcoding);
if (!NILP (tem))
{
val = tem;
@@ -2132,6 +2145,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
inchannel = p->open_fd[READ_FROM_SUBPROCESS];
forkout = p->open_fd[SUBPROCESS_STDOUT];
+#if defined(GNU_LINUX) && defined(F_SETPIPE_SZ)
+ fcntl (inchannel, F_SETPIPE_SZ, read_process_output_max);
+#endif
+
if (!NILP (p->stderrproc))
{
struct Lisp_Process *pp = XPROCESS (p->stderrproc);
@@ -2173,7 +2190,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
&& !EQ (p->filter, Qt))
add_process_read_fd (inchannel);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* This may signal an error. */
setup_process_coding_systems (process);
@@ -2340,7 +2357,6 @@ usage: (make-pipe-process &rest ARGS) */)
struct Lisp_Process *p;
Lisp_Object name, buffer;
Lisp_Object tem;
- ptrdiff_t specpdl_count;
int inchannel, outchannel;
if (nargs == 0)
@@ -2348,10 +2364,10 @@ usage: (make-pipe-process &rest ARGS) */)
contact = Flist (nargs, args);
- name = Fplist_get (contact, QCname);
+ name = plist_get (contact, QCname);
CHECK_STRING (name);
proc = make_process (name);
- specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
record_unwind_protect (remove_process, proc);
p = XPROCESS (proc);
@@ -2380,21 +2396,21 @@ usage: (make-pipe-process &rest ARGS) */)
if (inchannel > max_desc)
max_desc = inchannel;
- buffer = Fplist_get (contact, QCbuffer);
+ buffer = plist_get (contact, QCbuffer);
if (NILP (buffer))
buffer = name;
buffer = Fget_buffer_create (buffer, Qnil);
pset_buffer (p, buffer);
pset_childp (p, contact);
- pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist)));
pset_type (p, Qpipe);
- pset_sentinel (p, Fplist_get (contact, QCsentinel));
- pset_filter (p, Fplist_get (contact, QCfilter));
+ pset_sentinel (p, plist_get (contact, QCsentinel));
+ pset_filter (p, plist_get (contact, QCfilter));
eassert (NILP (p->log));
- if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
+ if (tem = plist_get (contact, QCnoquery), !NILP (tem))
p->kill_without_query = 1;
- if (tem = Fplist_get (contact, QCstop), !NILP (tem))
+ if (tem = plist_get (contact, QCstop), !NILP (tem))
pset_command (p, Qt);
eassert (! p->pty_flag);
@@ -2415,7 +2431,7 @@ usage: (make-pipe-process &rest ARGS) */)
Lisp_Object coding_systems = Qt;
Lisp_Object val;
- tem = Fplist_get (contact, QCcoding);
+ tem = plist_get (contact, QCcoding);
val = Qnil;
if (!NILP (tem))
{
@@ -2471,7 +2487,7 @@ usage: (make-pipe-process &rest ARGS) */)
eassert (p->decoding_carryover == 0);
pset_encoding_buf (p, empty_unibyte_string);
- specpdl_ptr = specpdl + specpdl_count;
+ specpdl_ptr = specpdl_ref_to_ptr (specpdl_count);
return proc;
}
@@ -2902,7 +2918,7 @@ set up yet, this function will block until socket setup has completed. */)
if (set_socket_option (s, option, value))
{
- pset_childp (p, Fplist_put (p->childp, option, value));
+ pset_childp (p, plist_put (p->childp, option, value));
return Qt;
}
@@ -2980,19 +2996,19 @@ usage: (serial-process-configure &rest ARGS) */)
contact = Flist (nargs, args);
- proc = Fplist_get (contact, QCprocess);
+ proc = plist_get (contact, QCprocess);
if (NILP (proc))
- proc = Fplist_get (contact, QCname);
+ proc = plist_get (contact, QCname);
if (NILP (proc))
- proc = Fplist_get (contact, QCbuffer);
+ proc = plist_get (contact, QCbuffer);
if (NILP (proc))
- proc = Fplist_get (contact, QCport);
+ proc = plist_get (contact, QCport);
proc = get_process (proc);
p = XPROCESS (proc);
if (!EQ (p->type, Qserial))
error ("Not a serial process");
- if (NILP (Fplist_get (p->childp, QCspeed)))
+ if (NILP (plist_get (p->childp, QCspeed)))
return Qnil;
serial_configure (p, contact);
@@ -3079,29 +3095,28 @@ usage: (make-serial-process &rest ARGS) */)
struct Lisp_Process *p;
Lisp_Object name, buffer;
Lisp_Object tem, val;
- ptrdiff_t specpdl_count;
if (nargs == 0)
return Qnil;
contact = Flist (nargs, args);
- port = Fplist_get (contact, QCport);
+ port = plist_get (contact, QCport);
if (NILP (port))
error ("No port specified");
CHECK_STRING (port);
- if (NILP (Fplist_member (contact, QCspeed)))
+ if (NILP (plist_member (contact, QCspeed)))
error (":speed not specified");
- if (!NILP (Fplist_get (contact, QCspeed)))
- CHECK_FIXNUM (Fplist_get (contact, QCspeed));
+ if (!NILP (plist_get (contact, QCspeed)))
+ CHECK_FIXNUM (plist_get (contact, QCspeed));
- name = Fplist_get (contact, QCname);
+ name = plist_get (contact, QCname);
if (NILP (name))
name = port;
CHECK_STRING (name);
proc = make_process (name);
- specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
record_unwind_protect (remove_process, proc);
p = XPROCESS (proc);
@@ -3116,21 +3131,21 @@ usage: (make-serial-process &rest ARGS) */)
eassert (0 <= fd && fd < FD_SETSIZE);
chan_process[fd] = proc;
- buffer = Fplist_get (contact, QCbuffer);
+ buffer = plist_get (contact, QCbuffer);
if (NILP (buffer))
buffer = name;
buffer = Fget_buffer_create (buffer, Qnil);
pset_buffer (p, buffer);
pset_childp (p, contact);
- pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist)));
pset_type (p, Qserial);
- pset_sentinel (p, Fplist_get (contact, QCsentinel));
- pset_filter (p, Fplist_get (contact, QCfilter));
+ pset_sentinel (p, plist_get (contact, QCsentinel));
+ pset_filter (p, plist_get (contact, QCfilter));
eassert (NILP (p->log));
- if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
+ if (tem = plist_get (contact, QCnoquery), !NILP (tem))
p->kill_without_query = 1;
- if (tem = Fplist_get (contact, QCstop), !NILP (tem))
+ if (tem = plist_get (contact, QCstop), !NILP (tem))
pset_command (p, Qt);
eassert (! p->pty_flag);
@@ -3140,7 +3155,7 @@ usage: (make-serial-process &rest ARGS) */)
update_process_mark (p);
- tem = Fplist_get (contact, QCcoding);
+ tem = plist_get (contact, QCcoding);
val = Qnil;
if (!NILP (tem))
@@ -3179,7 +3194,7 @@ usage: (make-serial-process &rest ARGS) */)
Fserial_process_configure (nargs, args);
- specpdl_ptr = specpdl + specpdl_count;
+ specpdl_ptr = specpdl_ref_to_ptr (specpdl_count);
return proc;
}
@@ -3194,7 +3209,7 @@ set_network_socket_coding_system (Lisp_Object proc, Lisp_Object host,
Lisp_Object coding_systems = Qt;
Lisp_Object val;
- tem = Fplist_get (contact, QCcoding);
+ tem = plist_get (contact, QCcoding);
/* Setup coding systems for communicating with the network stream. */
/* Qt denotes we have not yet called Ffind_operation_coding_system. */
@@ -3282,8 +3297,8 @@ finish_after_tls_connection (Lisp_Object proc)
if (!NILP (Ffboundp (Qnsm_verify_connection)))
result = call3 (Qnsm_verify_connection,
proc,
- Fplist_get (contact, QChost),
- Fplist_get (contact, QCservice));
+ plist_get (contact, QChost),
+ plist_get (contact, QCservice));
eassert (p->outfd < FD_SETSIZE);
if (NILP (result))
@@ -3341,9 +3356,9 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
s = -1;
struct sockaddr *sa = NULL;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_nothing ();
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
while (!NILP (addrinfos))
{
@@ -3464,7 +3479,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
if (getsockname (s, psa1, &len1) == 0)
{
Lisp_Object service = make_fixnum (ntohs (sa1.sin_port));
- contact = Fplist_put (contact, QCservice, service);
+ contact = plist_put (contact, QCservice, service);
/* Save the port number so that we can stash it in
the process object later. */
DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa);
@@ -3528,7 +3543,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
#endif /* !WINDOWSNT */
/* Discard the unwind protect closing S. */
- specpdl_ptr = specpdl + count1;
+ specpdl_ptr = specpdl_ref_to_ptr (count1);
emacs_close (s);
s = -1;
if (0 <= socket_to_use)
@@ -3555,7 +3570,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
{
Lisp_Object remote;
memset (datagram_address[s].sa, 0, addrlen);
- if (remote = Fplist_get (contact, QCremote), !NILP (remote))
+ if (remote = plist_get (contact, QCremote), !NILP (remote))
{
int rfamily;
ptrdiff_t rlen = get_lisp_to_sockaddr_size (remote, &rfamily);
@@ -3570,8 +3585,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
}
#endif
- contact = Fplist_put (contact, p->is_server? QClocal: QCremote,
- conv_sockaddr_to_lisp (sa, addrlen));
+ contact = plist_put (contact, p->is_server? QClocal: QCremote,
+ conv_sockaddr_to_lisp (sa, addrlen));
#ifdef HAVE_GETSOCKNAME
if (!p->is_server)
{
@@ -3579,8 +3594,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
socklen_t len1 = sizeof (sa1);
DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
if (getsockname (s, psa1, &len1) == 0)
- contact = Fplist_put (contact, QClocal,
- conv_sockaddr_to_lisp (psa1, len1));
+ contact = plist_put (contact, QClocal,
+ conv_sockaddr_to_lisp (psa1, len1));
}
#endif
}
@@ -3599,7 +3614,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
{
Lisp_Object data = get_file_errno_data (err, contact, xerrno);
- pset_status (p, list2 (Fcar (data), Fcdr (data)));
+ pset_status (p, list2 (Qfailed, data));
unbind_to (count, Qnil);
return;
}
@@ -3621,7 +3636,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
p->outfd = outch;
/* Discard the unwind protect for closing S, if any. */
- specpdl_ptr = specpdl + count1;
+ specpdl_ptr = specpdl_ref_to_ptr (count1);
if (p->is_server && p->socktype != SOCK_DGRAM)
pset_status (p, Qlisten);
@@ -3879,7 +3894,7 @@ usage: (make-network-process &rest ARGS) */)
#ifdef HAVE_GETADDRINFO_A
struct gaicb *dns_request = NULL;
#endif
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (nargs == 0)
return Qnil;
@@ -3893,7 +3908,7 @@ usage: (make-network-process &rest ARGS) */)
#endif
/* :type TYPE (nil: stream, datagram */
- tem = Fplist_get (contact, QCtype);
+ tem = plist_get (contact, QCtype);
if (NILP (tem))
socktype = SOCK_STREAM;
#ifdef DATAGRAM_SOCKETS
@@ -3907,13 +3922,13 @@ usage: (make-network-process &rest ARGS) */)
else
error ("Unsupported connection type");
- name = Fplist_get (contact, QCname);
- buffer = Fplist_get (contact, QCbuffer);
- filter = Fplist_get (contact, QCfilter);
- sentinel = Fplist_get (contact, QCsentinel);
- use_external_socket_p = Fplist_get (contact, QCuse_external_socket);
- Lisp_Object server = Fplist_get (contact, QCserver);
- bool nowait = !NILP (Fplist_get (contact, QCnowait));
+ name = plist_get (contact, QCname);
+ buffer = plist_get (contact, QCbuffer);
+ filter = plist_get (contact, QCfilter);
+ sentinel = plist_get (contact, QCsentinel);
+ use_external_socket_p = plist_get (contact, QCuse_external_socket);
+ Lisp_Object server = plist_get (contact, QCserver);
+ bool nowait = !NILP (plist_get (contact, QCnowait));
if (!NILP (server) && nowait)
error ("`:server' is incompatible with `:nowait'");
@@ -3921,9 +3936,9 @@ usage: (make-network-process &rest ARGS) */)
/* :local ADDRESS or :remote ADDRESS */
if (NILP (server))
- address = Fplist_get (contact, QCremote);
+ address = plist_get (contact, QCremote);
else
- address = Fplist_get (contact, QClocal);
+ address = plist_get (contact, QClocal);
if (!NILP (address))
{
host = service = Qnil;
@@ -3936,7 +3951,7 @@ usage: (make-network-process &rest ARGS) */)
}
/* :family FAMILY -- nil (for Inet), local, or integer. */
- tem = Fplist_get (contact, QCfamily);
+ tem = plist_get (contact, QCfamily);
if (NILP (tem))
{
#ifdef AF_INET6
@@ -3961,10 +3976,10 @@ usage: (make-network-process &rest ARGS) */)
error ("Unknown address family");
/* :service SERVICE -- string, integer (port number), or t (random port). */
- service = Fplist_get (contact, QCservice);
+ service = plist_get (contact, QCservice);
/* :host HOST -- hostname, ip address, or 'local for localhost. */
- host = Fplist_get (contact, QChost);
+ host = plist_get (contact, QChost);
if (NILP (host))
{
/* The "connection" function gets it bind info from the address we're
@@ -4003,7 +4018,7 @@ usage: (make-network-process &rest ARGS) */)
if (!NILP (host))
{
message (":family local ignores the :host property");
- contact = Fplist_put (contact, QChost, Qnil);
+ contact = plist_put (contact, QChost, Qnil);
host = Qnil;
}
CHECK_STRING (service);
@@ -4157,16 +4172,16 @@ usage: (make-network-process &rest ARGS) */)
record_unwind_protect (remove_process, proc);
p = XPROCESS (proc);
pset_childp (p, contact);
- pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
+ pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist)));
pset_type (p, Qnetwork);
pset_buffer (p, buffer);
pset_sentinel (p, sentinel);
pset_filter (p, filter);
- pset_log (p, Fplist_get (contact, QClog));
- if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
+ pset_log (p, plist_get (contact, QClog));
+ if (tem = plist_get (contact, QCnoquery), !NILP (tem))
p->kill_without_query = 1;
- if ((tem = Fplist_get (contact, QCstop), !NILP (tem)))
+ if ((tem = plist_get (contact, QCstop), !NILP (tem)))
pset_command (p, Qt);
eassert (p->pid == 0);
p->backlog = 5;
@@ -4178,7 +4193,7 @@ usage: (make-network-process &rest ARGS) */)
eassert (! p->dns_request);
#endif
#ifdef HAVE_GNUTLS
- tem = Fplist_get (contact, QCtls_parameters);
+ tem = plist_get (contact, QCtls_parameters);
CHECK_LIST (tem);
p->gnutls_boot_parameters = tem;
#endif
@@ -4208,7 +4223,7 @@ usage: (make-network-process &rest ARGS) */)
if (! postpone_connection)
connect_network_socket (proc, addrinfos, use_external_socket_p);
- specpdl_ptr = specpdl + count;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
return proc;
}
@@ -4380,7 +4395,6 @@ network_interface_info (Lisp_Object ifname)
Lisp_Object elt;
int s;
bool any = false;
- ptrdiff_t count;
#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
&& defined HAVE_GETIFADDRS && defined LLADDR)
struct ifaddrs *ifap;
@@ -4395,7 +4409,7 @@ network_interface_info (Lisp_Object ifname)
s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (s < 0)
return Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, s);
elt = Qnil;
@@ -4644,7 +4658,7 @@ error displays the error message. */)
struct addrinfo hints;
memset (&hints, 0, sizeof hints);
- if (EQ (family, Qnil))
+ if (NILP (family))
hints.ai_family = AF_UNSPEC;
else if (EQ (family, Qipv4))
hints.ai_family = AF_INET;
@@ -4761,7 +4775,7 @@ corresponding connection was closed. */)
/* Can't wait for a process that is dedicated to a different
thread. */
- if (!NILP (proc->thread) && !EQ (proc->thread, Fcurrent_thread ()))
+ if (!NILP (proc->thread) && !BASE_EQ (proc->thread, Fcurrent_thread ()))
{
Lisp_Object proc_thread_name = XTHREAD (proc->thread)->name;
@@ -4769,7 +4783,7 @@ corresponding connection was closed. */)
SDATA (proc->name),
STRINGP (proc_thread_name)
? SDATA (proc_thread_name)
- : SDATA (Fprin1_to_string (proc->thread, Qt)));
+ : SDATA (Fprin1_to_string (proc->thread, Qt, Qnil)));
}
}
else
@@ -4839,7 +4853,6 @@ server_accept_connection (Lisp_Object server, int channel)
int s;
union u_sockaddr saddr;
socklen_t len = sizeof saddr;
- ptrdiff_t count;
s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
@@ -4861,7 +4874,7 @@ server_accept_connection (Lisp_Object server, int channel)
return;
}
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, s);
connect_counter++;
@@ -4956,17 +4969,17 @@ server_accept_connection (Lisp_Object server, int channel)
/* Build new contact information for this setup. */
contact = Fcopy_sequence (ps->childp);
- contact = Fplist_put (contact, QCserver, Qnil);
- contact = Fplist_put (contact, QChost, host);
+ contact = plist_put (contact, QCserver, Qnil);
+ contact = plist_put (contact, QChost, host);
if (!NILP (service))
- contact = Fplist_put (contact, QCservice, service);
- contact = Fplist_put (contact, QCremote,
- conv_sockaddr_to_lisp (&saddr.sa, len));
+ contact = plist_put (contact, QCservice, service);
+ contact = plist_put (contact, QCremote,
+ conv_sockaddr_to_lisp (&saddr.sa, len));
#ifdef HAVE_GETSOCKNAME
len = sizeof saddr;
if (getsockname (s, &saddr.sa, &len) == 0)
- contact = Fplist_put (contact, QClocal,
- conv_sockaddr_to_lisp (&saddr.sa, len));
+ contact = plist_put (contact, QClocal,
+ conv_sockaddr_to_lisp (&saddr.sa, len));
#endif
pset_childp (p, contact);
@@ -4980,7 +4993,7 @@ server_accept_connection (Lisp_Object server, int channel)
eassert (p->pid == 0);
/* Discard the unwind protect for closing S. */
- specpdl_ptr = specpdl + count;
+ specpdl_ptr = specpdl_ref_to_ptr (count);
p->open_fd[SUBPROCESS_STDIN] = s;
p->infd = s;
@@ -5177,7 +5190,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
#if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS
bool retry_for_async;
#endif
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Close to the current time if known, an invalid timespec otherwise. */
struct timespec now = invalid_timespec ();
@@ -5479,7 +5492,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
triggered by processing X events). In the latter case, set
nfds to 1 to avoid breaking the loop. */
no_avail = 0;
- if ((read_kbd || !NILP (wait_for_cell))
+ if ((read_kbd
+ /* The following code doesn't make any sense for just the
+ wait_for_cell case, because detect_input_pending returns
+ whether or not the keyboard buffer isn't empty or there
+ is mouse movement. Any keyboard input that arrives
+ while waiting for a cell will cause the select call to
+ be skipped, and gobble_input to be called even when
+ there is no input available from the terminal itself.
+ Skipping the call to select also causes the timeout to
+ be ignored. (bug#46935) */
+ /* || !NILP (wait_for_cell) */)
&& detect_input_pending ())
{
nfds = read_kbd ? 0 : 1;
@@ -6027,7 +6050,7 @@ read_process_output (Lisp_Object proc, int channel)
struct coding_system *coding = proc_decode_coding_system[channel];
int carryover = p->decoding_carryover;
ptrdiff_t readmax = clip_to_bounds (1, read_process_output_max, PTRDIFF_MAX);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object odeactivate;
char *chars;
@@ -6243,7 +6266,6 @@ Otherwise it discards the output. */)
{
Lisp_Object old_read_only;
ptrdiff_t old_begv, old_zv;
- ptrdiff_t old_begv_byte, old_zv_byte;
ptrdiff_t before, before_byte;
ptrdiff_t opoint_byte;
struct buffer *b;
@@ -6254,8 +6276,6 @@ Otherwise it discards the output. */)
old_read_only = BVAR (current_buffer, read_only);
old_begv = BEGV;
old_zv = ZV;
- old_begv_byte = BEGV_BYTE;
- old_zv_byte = ZV_BYTE;
bset_read_only (current_buffer, Qnil);
@@ -6303,15 +6323,9 @@ Otherwise it discards the output. */)
opoint_byte += PT_BYTE - before_byte;
}
if (old_begv > before)
- {
- old_begv += PT - before;
- old_begv_byte += PT_BYTE - before_byte;
- }
+ old_begv += PT - before;
if (old_zv >= before)
- {
- old_zv += PT - before;
- old_zv_byte += PT_BYTE - before_byte;
- }
+ old_zv += PT - before;
/* If the restriction isn't what it should be, set it. */
if (old_begv != BEGV || old_zv != ZV)
@@ -6424,7 +6438,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
if (p->raw_status_new)
update_status (p);
if (! EQ (p->status, Qrun))
- error ("Process %s not running", SDATA (p->name));
+ error ("Process %s not running: %s", SDATA (p->name), SDATA (status_message (p)));
if (p->outfd < 0)
error ("Output file descriptor of %s is closed", SDATA (p->name));
@@ -6934,7 +6948,8 @@ the order of the list, until one of them returns non-nil. */)
process, current_group);
}
-DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2, 0,
+DEFUN ("kill-process", Fkill_process, Skill_process, 0, 2,
+ "(list (read-process-name \"Kill process\"))",
doc: /* Kill process PROCESS. May be process or name of one.
See function `interrupt-process' for more details on usage. */)
(Lisp_Object process, Lisp_Object current_group)
@@ -7037,14 +7052,13 @@ abbr_to_signal (char const *name)
return -1;
}
-DEFUN ("signal-process", Fsignal_process, Ssignal_process,
- 2, 2, "sProcess (name or number): \nnSignal code: ",
- doc: /* Send PROCESS the signal with code SIGCODE.
-PROCESS may also be a number specifying the process id of the
-process to signal; in this case, the process need not be a child of
-this Emacs.
-SIGCODE may be an integer, or a symbol whose name is a signal name. */)
- (Lisp_Object process, Lisp_Object sigcode)
+DEFUN ("internal-default-signal-process",
+ Finternal_default_signal_process,
+ Sinternal_default_signal_process, 2, 3, 0,
+ doc: /* Default function to send PROCESS the signal with code SIGCODE.
+It shall be the last element in list `signal-process-functions'.
+See function `signal-process' for more details on usage. */)
+ (Lisp_Object process, Lisp_Object sigcode, Lisp_Object remote)
{
pid_t pid;
int signo;
@@ -7094,6 +7108,23 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
return make_fixnum (kill (pid, signo));
}
+DEFUN ("signal-process", Fsignal_process, Ssignal_process,
+ 2, 3, "(list (read-string \"Process (name or number): \") (read-signal-name))",
+ doc: /* Send PROCESS the signal with code SIGCODE.
+PROCESS may also be a number specifying the process id of the
+process to signal; in this case, the process need not be a child of
+this Emacs.
+If PROCESS is a process object which contains the property
+`remote-pid', or PROCESS is a number and REMOTE is a remote file name,
+PROCESS is interpreted as process on the respective remote host, which
+will be the process to signal.
+SIGCODE may be an integer, or a symbol whose name is a signal name. */)
+ (Lisp_Object process, Lisp_Object sigcode, Lisp_Object remote)
+{
+ return CALLN (Frun_hook_with_args_until_success, Qsignal_process_functions,
+ process, sigcode, remote);
+}
+
DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
doc: /* Make PROCESS see end-of-file in its input.
EOF comes after any text already sent to it.
@@ -7128,7 +7159,7 @@ process has been transmitted to the serial port. */)
if (XPROCESS (proc)->raw_status_new)
update_status (XPROCESS (proc));
if (! EQ (XPROCESS (proc)->status, Qrun))
- error ("Process %s not running", SDATA (XPROCESS (proc)->name));
+ error ("Process %s not running: %s", SDATA (XPROCESS (proc)->name), SDATA (status_message (XPROCESS (proc))));
if (coding && CODING_REQUIRE_FLUSHING (coding))
{
@@ -7437,7 +7468,7 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
{
Lisp_Object sentinel, odeactivate;
struct Lisp_Process *p = XPROCESS (proc);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
@@ -8190,16 +8221,25 @@ DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
0, 0, 0,
doc: /* Return a list of numerical process IDs of all running processes.
If this functionality is unsupported, return nil.
+If `default-directory' is remote, return process IDs of the respective remote host.
See `process-attributes' for getting attributes of a process given its ID. */)
(void)
{
+ Lisp_Object handler
+ = Ffind_file_name_handler (BVAR (current_buffer, directory),
+ Qlist_system_processes);
+ if (!NILP (handler))
+ return call1 (handler, Qlist_system_processes);
+
return list_system_processes ();
}
DEFUN ("process-attributes", Fprocess_attributes,
Sprocess_attributes, 1, 1, 0,
doc: /* Return attributes of the process given by its PID, a number.
+If `default-directory' is remote, PID is regarded as process
+identifier on the respective remote host.
Value is an alist where each element is a cons cell of the form
@@ -8250,6 +8290,12 @@ integer or floating point values.
args -- command line which invoked the process (string). */)
( Lisp_Object pid)
{
+ Lisp_Object handler
+ = Ffind_file_name_handler (BVAR (current_buffer, directory),
+ Qprocess_attributes);
+ if (!NILP (handler))
+ return call2 (handler, Qprocess_attributes, pid);
+
return system_process_attributes (pid);
}
@@ -8271,6 +8317,27 @@ If QUERY is `all', also count processors not available. */)
#endif
}
+DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0,
+ doc: /* Return a list of known signal names on this system. */)
+ (void)
+{
+#ifndef MSDOS
+ int i;
+ char name[SIG2STR_MAX];
+ Lisp_Object names = Qnil;
+
+ for (i = 0; i <= SIGNUM_BOUND; ++i)
+ {
+ if (!sig2str (i, name))
+ names = Fcons (build_string (name), names);
+ }
+
+ return names;
+#else
+ return Qnil;
+#endif
+}
+
#ifdef subprocesses
/* Arrange to catch SIGCHLD if this hasn't already been arranged.
Invoke this after init_process_emacs, and after glib and/or GNUstep
@@ -8425,6 +8492,8 @@ void
syms_of_process (void)
{
DEFSYM (Qmake_process, "make-process");
+ DEFSYM (Qlist_system_processes, "list-system-processes");
+ DEFSYM (Qprocess_attributes, "process-attributes");
#ifdef subprocesses
@@ -8583,6 +8652,13 @@ These functions are called in the order of the list, until one of them
returns non-nil. */);
Vinterrupt_process_functions = list1 (Qinternal_default_interrupt_process);
+ DEFVAR_LISP ("signal-process-functions", Vsignal_process_functions,
+ doc: /* List of functions to be called for `signal-process'.
+The arguments of the functions are the same as for `signal-process'.
+These functions are called in the order of the list, until one of them
+returns non-nil. */);
+ Vsignal_process_functions = list1 (Qinternal_default_signal_process);
+
DEFVAR_LISP ("internal--daemon-sockname", Vinternal__daemon_sockname,
doc: /* Name of external socket passed to Emacs, or nil if none. */);
Vinternal__daemon_sockname = Qnil;
@@ -8590,7 +8666,10 @@ returns non-nil. */);
DEFVAR_INT ("read-process-output-max", read_process_output_max,
doc: /* Maximum number of bytes to read from subprocess in a single chunk.
Enlarge the value only if the subprocess generates very large (megabytes)
-amounts of data in one go. */);
+amounts of data in one go.
+
+On GNU/Linux systems, the value should not exceed
+/proc/sys/fs/pipe-max-size. See pipe(7) manpage for details. */);
read_process_output_max = 4096;
DEFVAR_INT ("process-error-pause-time", process_error_pause_time,
@@ -8603,8 +8682,13 @@ sentinel or a process filter function has an error. */);
"internal-default-interrupt-process");
DEFSYM (Qinterrupt_process_functions, "interrupt-process-functions");
+ DEFSYM (Qinternal_default_signal_process,
+ "internal-default-signal-process");
+ DEFSYM (Qsignal_process_functions, "signal-process-functions");
+
DEFSYM (Qnull, "null");
DEFSYM (Qpipe_process_p, "pipe-process-p");
+ DEFSYM (Qmessage, "message");
defsubr (&Sprocessp);
defsubr (&Sget_process);
@@ -8657,6 +8741,7 @@ sentinel or a process filter function has an error. */);
defsubr (&Scontinue_process);
defsubr (&Sprocess_running_child_p);
defsubr (&Sprocess_send_eof);
+ defsubr (&Sinternal_default_signal_process);
defsubr (&Ssignal_process);
defsubr (&Swaiting_for_user_input_p);
defsubr (&Sprocess_type);
@@ -8706,4 +8791,5 @@ sentinel or a process filter function has an error. */);
defsubr (&Slist_system_processes);
defsubr (&Sprocess_attributes);
defsubr (&Snum_processors);
+ defsubr (&Ssignal_names);
}
diff --git a/src/profiler.c b/src/profiler.c
index 31a46d1b5e5..5cb42d54fa6 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -132,7 +132,7 @@ static void evict_lower_half (log_t *log)
XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
Fremhash (key, tmp);
}
- eassert (EQ (Qunbound, HASH_KEY (log, i)));
+ eassert (BASE_EQ (Qunbound, HASH_KEY (log, i)));
eassert (log->next_free == i);
eassert (VECTORP (key));
@@ -158,7 +158,7 @@ record_backtrace (log_t *log, EMACS_INT count)
/* Get a "working memory" vector. */
Lisp_Object backtrace = HASH_VALUE (log, index);
- eassert (EQ (Qunbound, HASH_KEY (log, index)));
+ eassert (BASE_EQ (Qunbound, HASH_KEY (log, index)));
get_backtrace (backtrace);
{ /* We basically do a `gethash+puthash' here, except that we have to be
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 7c172fe63a2..9b2c14c413d 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -33,6 +33,7 @@
#include "buffer.h"
#include "syntax.h"
#include "category.h"
+#include "dispextern.h"
/* Maximum number of duplicates an interval can allow. Some systems
define this in other header files, but we want our value, so remove
@@ -1244,21 +1245,22 @@ static int analyze_first (re_char *p, re_char *pend,
return REG_ESIZE; \
ptrdiff_t b_off = b - old_buffer; \
ptrdiff_t begalt_off = begalt - old_buffer; \
- bool fixup_alt_jump_set = !!fixup_alt_jump; \
- bool laststart_set = !!laststart; \
- bool pending_exact_set = !!pending_exact; \
- ptrdiff_t fixup_alt_jump_off, laststart_off, pending_exact_off; \
- if (fixup_alt_jump_set) fixup_alt_jump_off = fixup_alt_jump - old_buffer; \
- if (laststart_set) laststart_off = laststart - old_buffer; \
- if (pending_exact_set) pending_exact_off = pending_exact - old_buffer; \
+ ptrdiff_t fixup_alt_jump_off = \
+ fixup_alt_jump ? fixup_alt_jump - old_buffer : -1; \
+ ptrdiff_t laststart_off = laststart ? laststart - old_buffer : -1; \
+ ptrdiff_t pending_exact_off = \
+ pending_exact ? pending_exact - old_buffer : -1; \
bufp->buffer = xpalloc (bufp->buffer, &bufp->allocated, \
requested_extension, MAX_BUF_SIZE, 1); \
unsigned char *new_buffer = bufp->buffer; \
b = new_buffer + b_off; \
begalt = new_buffer + begalt_off; \
- if (fixup_alt_jump_set) fixup_alt_jump = new_buffer + fixup_alt_jump_off; \
- if (laststart_set) laststart = new_buffer + laststart_off; \
- if (pending_exact_set) pending_exact = new_buffer + pending_exact_off; \
+ if (0 <= fixup_alt_jump_off) \
+ fixup_alt_jump = new_buffer + fixup_alt_jump_off; \
+ if (0 <= laststart_off) \
+ laststart = new_buffer + laststart_off; \
+ if (0 <= pending_exact_off) \
+ pending_exact = new_buffer + pending_exact_off; \
} while (false)
@@ -3952,6 +3954,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
and need to test it, it's not garbage. */
re_char *match_end = NULL;
+ /* This keeps track of how many buffer/string positions we examined. */
+ ptrdiff_t nchars = 0;
+
#ifdef DEBUG_COMPILES_ARGUMENTS
/* Counts the total number of registers pushed. */
ptrdiff_t num_regs_pushed = 0;
@@ -3963,7 +3968,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
INIT_FAIL_STACK ();
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Prevent shrinking and relocation of buffer text if GC happens
while we are inside this function. The calls to
@@ -4208,6 +4213,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
unbind_to (count, Qnil);
SAFE_FREE ();
+ /* The factor of 50 below is a heuristic that needs to be tuned. It
+ means we consider 50 buffer positions examined by this function
+ roughly equivalent to the display engine iterating over a single
+ buffer position. */
+ if (max_redisplay_ticks > 0 && nchars > 0)
+ update_redisplay_ticks (nchars / 50 + 1, NULL);
return dcnt;
}
@@ -4260,6 +4271,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
p += pat_charlen;
d += buf_charlen;
mcnt -= pat_charlen;
+ nchars++;
}
while (mcnt > 0);
else
@@ -4297,6 +4309,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
p += pat_charlen;
d++;
mcnt -= pat_charlen;
+ nchars++;
}
while (mcnt > 0);
@@ -4320,6 +4333,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
DEBUG_PRINT (" Matched \"%d\".\n", *d);
d += buf_charlen;
+ nchars++;
}
break;
@@ -4372,6 +4386,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
goto fail;
d += len;
+ nchars++;
}
break;
@@ -4491,6 +4506,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
goto fail;
}
d += dcnt, d2 += dcnt;
+ nchars++;
}
}
break;
@@ -4772,10 +4788,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1;
UPDATE_SYNTAX_TABLE (charpos);
GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2);
+ nchars++;
s1 = SYNTAX (c1);
UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1);
PREFETCH_NOLIMIT ();
GET_CHAR_AFTER (c2, d, dummy);
+ nchars++;
s2 = SYNTAX (c2);
if (/* Case 2: Only one of S1 and S2 is Sword. */
@@ -4811,6 +4829,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
UPDATE_SYNTAX_TABLE (charpos);
PREFETCH ();
GET_CHAR_AFTER (c2, d, dummy);
+ nchars++;
s2 = SYNTAX (c2);
/* Case 2: S2 is not Sword. */
@@ -4821,6 +4840,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
if (!AT_STRINGS_BEG (d))
{
GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2);
+ nchars++;
UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1);
s1 = SYNTAX (c1);
@@ -4851,6 +4871,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1;
UPDATE_SYNTAX_TABLE (charpos);
GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2);
+ nchars++;
s1 = SYNTAX (c1);
/* Case 2: S1 is not Sword. */
@@ -4862,6 +4883,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
{
PREFETCH_NOLIMIT ();
GET_CHAR_AFTER (c2, d, dummy);
+ nchars++;
UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1);
s2 = SYNTAX (c2);
@@ -4892,6 +4914,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
UPDATE_SYNTAX_TABLE (charpos);
PREFETCH ();
c2 = RE_STRING_CHAR (d, target_multibyte);
+ nchars++;
s2 = SYNTAX (c2);
/* Case 2: S2 is neither Sword nor Ssymbol. */
@@ -4902,6 +4925,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
if (!AT_STRINGS_BEG (d))
{
GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2);
+ nchars++;
UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1);
s1 = SYNTAX (c1);
@@ -4930,6 +4954,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1;
UPDATE_SYNTAX_TABLE (charpos);
GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2);
+ nchars++;
s1 = SYNTAX (c1);
/* Case 2: S1 is neither Ssymbol nor Sword. */
@@ -4941,6 +4966,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
{
PREFETCH_NOLIMIT ();
c2 = RE_STRING_CHAR (d, target_multibyte);
+ nchars++;
UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1);
s2 = SYNTAX (c2);
@@ -4972,6 +4998,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
if ((SYNTAX (c) != (enum syntaxcode) mcnt) ^ not)
goto fail;
d += len;
+ nchars++;
}
}
break;
@@ -4998,6 +5025,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
if ((!CHAR_HAS_CATEGORY (c, mcnt)) ^ not)
goto fail;
d += len;
+ nchars++;
}
}
break;
@@ -5059,6 +5087,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
unbind_to (count, Qnil);
SAFE_FREE ();
+ if (max_redisplay_ticks > 0 && nchars > 0)
+ update_redisplay_ticks (nchars / 50 + 1, NULL);
+
return -1; /* Failure to match. */
}
diff --git a/src/search.c b/src/search.c
index a1adfa2d8ce..9d6bd074e1b 100644
--- a/src/search.c
+++ b/src/search.c
@@ -310,7 +310,7 @@ looking_at_1 (Lisp_Object string, bool posix, bool modify_data)
s2 = 0;
}
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
freeze_buffer_relocation ();
freeze_pattern (cache_entry);
re_match_object = Qnil;
@@ -370,7 +370,6 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start,
bool posix, bool modify_data)
{
ptrdiff_t val;
- struct re_pattern_buffer *bufp;
EMACS_INT pos;
ptrdiff_t pos_byte, i;
bool modify_match_data = NILP (Vinhibit_changing_match_data) && modify_data;
@@ -401,17 +400,22 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start,
set_char_table_extras (BVAR (current_buffer, case_canon_table), 2,
BVAR (current_buffer, case_eqv_table));
- bufp = &compile_pattern (regexp,
- (modify_match_data ? &search_regs : NULL),
- (!NILP (BVAR (current_buffer, case_fold_search))
- ? BVAR (current_buffer, case_canon_table) : Qnil),
- posix,
- STRING_MULTIBYTE (string))->buf;
+ specpdl_ref count = SPECPDL_INDEX ();
+ struct regexp_cache *cache_entry
+ = compile_pattern (regexp,
+ modify_match_data ? &search_regs : NULL,
+ (!NILP (BVAR (current_buffer, case_fold_search))
+ ? BVAR (current_buffer, case_canon_table)
+ : Qnil),
+ posix,
+ STRING_MULTIBYTE (string));
+ freeze_pattern (cache_entry);
re_match_object = string;
- val = re_search (bufp, SSDATA (string),
+ val = re_search (&cache_entry->buf, SSDATA (string),
SBYTES (string), pos_byte,
SBYTES (string) - pos_byte,
(modify_match_data ? &search_regs : NULL));
+ unbind_to (count, Qnil);
/* Set last_thing_searched only when match data is changed. */
if (modify_match_data)
@@ -480,15 +484,15 @@ ptrdiff_t
fast_string_match_internal (Lisp_Object regexp, Lisp_Object string,
Lisp_Object table)
{
- ptrdiff_t val;
- struct re_pattern_buffer *bufp;
-
- bufp = &compile_pattern (regexp, 0, table,
- 0, STRING_MULTIBYTE (string))->buf;
re_match_object = string;
- val = re_search (bufp, SSDATA (string),
- SBYTES (string), 0,
- SBYTES (string), 0);
+ specpdl_ref count = SPECPDL_INDEX ();
+ struct regexp_cache *cache_entry
+ = compile_pattern (regexp, 0, table, 0, STRING_MULTIBYTE (string));
+ freeze_pattern (cache_entry);
+ ptrdiff_t val = re_search (&cache_entry->buf, SSDATA (string),
+ SBYTES (string), 0,
+ SBYTES (string), 0);
+ unbind_to (count, Qnil);
return val;
}
@@ -501,15 +505,14 @@ ptrdiff_t
fast_c_string_match_ignore_case (Lisp_Object regexp,
const char *string, ptrdiff_t len)
{
- ptrdiff_t val;
- struct re_pattern_buffer *bufp;
-
regexp = string_make_unibyte (regexp);
- bufp = &compile_pattern (regexp, 0,
- Vascii_canon_table, 0,
- 0)->buf;
+ specpdl_ref count = SPECPDL_INDEX ();
+ struct regexp_cache *cache_entry
+ = compile_pattern (regexp, 0, Vascii_canon_table, 0, 0);
+ freeze_pattern (cache_entry);
re_match_object = Qt;
- val = re_search (bufp, string, len, 0, len, 0);
+ ptrdiff_t val = re_search (&cache_entry->buf, string, len, 0, len, 0);
+ unbind_to (count, Qnil);
return val;
}
@@ -568,7 +571,7 @@ fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
struct regexp_cache *cache_entry =
compile_pattern (regexp, 0, Qnil, 0, multibyte);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
freeze_buffer_relocation ();
freeze_pattern (cache_entry);
re_match_object = STRINGP (string) ? string : Qnil;
@@ -1198,7 +1201,7 @@ search_buffer_re (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
s2 = 0;
}
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
freeze_buffer_relocation ();
freeze_pattern (cache_entry);
@@ -2827,6 +2830,14 @@ All the elements are markers or nil (nil if the Nth pair didn't match)
if the last match was on a buffer; integers or nil if a string was matched.
Use `set-match-data' to reinstate the data in this list.
+Note that non-matching optional groups at the end of the regexp are
+elided instead of being represented with two `nil's each. For instance:
+
+ (progn
+ (string-match "^\\(a\\)?\\(b\\)\\(c\\)?$" "b")
+ (match-data))
+ => (0 1 nil nil 0 1)
+
If INTEGERS (the optional first argument) is non-nil, always use
integers (rather than markers) to represent buffer positions. In
this case, and if the last match was in a buffer, the buffer will get
diff --git a/src/sheap.h b/src/sheap.h
index 297b7cf317d..9133f0b292f 100644
--- a/src/sheap.h
+++ b/src/sheap.h
@@ -23,7 +23,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* Size of the static heap. Guess a value that is probably too large,
by up to a factor of four or so. Typically the unused part is not
paged in and so does not cost much. */
-enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 22 };
+enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 23 };
extern char bss_sbrk_buffer[STATIC_HEAP_SIZE];
extern char *max_bss_sbrk_ptr;
diff --git a/src/sort.c b/src/sort.c
new file mode 100644
index 00000000000..d10ae692d33
--- /dev/null
+++ b/src/sort.c
@@ -0,0 +1,974 @@
+/* Timsort for sequences.
+
+Copyright (C) 2022 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 <https://www.gnu.org/licenses/>. */
+
+/* This is a version of the cpython code implementing the TIMSORT
+ sorting algorithm described in
+ https://github.com/python/cpython/blob/main/Objects/listsort.txt.
+ This algorithm identifies and pushes naturally ordered sublists of
+ the original list, or "runs", onto a stack, and merges them
+ periodically according to a merge strategy called "powersort".
+ State is maintained during the sort in a merge_state structure,
+ which is passed around as an argument to all the subroutines. A
+ "stretch" structure includes a pointer to the run BASE of length
+ LEN along with its POWER (a computed integer used by the powersort
+ merge strategy that depends on this run and the succeeding run.) */
+
+
+#include <config.h>
+#include "lisp.h"
+
+
+/* MAX_MERGE_PENDING is the maximum number of entries in merge_state's
+ pending-stretch stack. For a list with n elements, this needs at most
+ floor(log2(n)) + 1 entries even if we didn't force runs to a
+ minimal length. So the number of bits in a ptrdiff_t is plenty large
+ enough for all cases. */
+
+#define MAX_MERGE_PENDING (sizeof (ptrdiff_t) * 8)
+
+/* Once we get into galloping mode, we stay there as long as both runs
+ win at least GALLOP_WIN_MIN consecutive times. */
+
+#define GALLOP_WIN_MIN 7
+
+/* A small temp array of size MERGESTATE_TEMP_SIZE is used to avoid
+ malloc when merging small lists. */
+
+#define MERGESTATE_TEMP_SIZE 256
+
+struct stretch
+{
+ Lisp_Object *base;
+ ptrdiff_t len;
+ int power;
+};
+
+struct reloc
+{
+ Lisp_Object **src;
+ Lisp_Object **dst;
+ ptrdiff_t *size;
+ int order; /* -1 while in merge_lo; +1 while in merg_hi; 0 otherwise. */
+};
+
+
+typedef struct
+{
+ Lisp_Object *listbase;
+ ptrdiff_t listlen;
+
+ /* PENDING is a stack of N pending stretches yet to be merged.
+ Stretch #i starts at address base[i] and extends for len[i]
+ elements. */
+
+ int n;
+ struct stretch pending[MAX_MERGE_PENDING];
+
+ /* The variable MIN_GALLOP, initialized to GALLOP_WIN_MIN, controls
+ when we get *into* galloping mode. merge_lo and merge_hi tend to
+ nudge it higher for random data, and lower for highly structured
+ data. */
+
+ ptrdiff_t min_gallop;
+
+ /* 'A' is temporary storage, able to hold ALLOCED elements, to help
+ with merges. 'A' initially points to TEMPARRAY, and subsequently
+ to newly allocated memory if needed. */
+
+ Lisp_Object *a;
+ ptrdiff_t alloced;
+ specpdl_ref count;
+ Lisp_Object temparray[MERGESTATE_TEMP_SIZE];
+
+ /* If an exception is thrown while merging we might have to relocate
+ some list elements from temporary storage back into the list.
+ RELOC keeps track of the information needed to do this. */
+
+ struct reloc reloc;
+
+ /* PREDICATE is the lisp comparison predicate for the sort. */
+
+ Lisp_Object predicate;
+} merge_state;
+
+
+/* Return true iff (PREDICATE A B) is non-nil. */
+
+static inline bool
+inorder (const Lisp_Object predicate, const Lisp_Object a, const Lisp_Object b)
+{
+ return !NILP (call2 (predicate, a, b));
+}
+
+
+/* Sort the list starting at LO and ending at HI using a stable binary
+ insertion sort algorithm. On entry the sublist [LO, START) (with
+ START between LO and HIGH) is known to be sorted (pass START == LO
+ if you are unsure). Even in case of error, the output will be some
+ permutation of the input (nothing is lost or duplicated). */
+
+static void
+binarysort (merge_state *ms, Lisp_Object *lo, const Lisp_Object *hi,
+ Lisp_Object *start)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (lo <= start && start <= hi);
+ if (lo == start)
+ ++start;
+ for (; start < hi; ++start)
+ {
+ Lisp_Object *l = lo;
+ Lisp_Object *r = start;
+ Lisp_Object pivot = *r;
+
+ eassume (l < r);
+ do {
+ Lisp_Object *p = l + ((r - l) >> 1);
+ if (inorder (pred, pivot, *p))
+ r = p;
+ else
+ l = p + 1;
+ } while (l < r);
+ eassume (l == r);
+ for (Lisp_Object *p = start; p > l; --p)
+ p[0] = p[-1];
+ *l = pivot;
+ }
+}
+
+
+/* Find and return the length of the "run" (the longest
+ non-decreasing sequence or the longest strictly decreasing
+ sequence, with the Boolean *DESCENDING set to 0 in the former
+ case, or to 1 in the latter) beginning at LO, in the slice [LO,
+ HI) with LO < HI. The strictness of the definition of
+ "descending" ensures there are no equal elements to get out of
+ order so the caller can safely reverse a descending sequence
+ without violating stability. */
+
+static ptrdiff_t
+count_run (merge_state *ms, Lisp_Object *lo, const Lisp_Object *hi,
+ bool *descending)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (lo < hi);
+ *descending = 0;
+ ++lo;
+ ptrdiff_t n = 1;
+ if (lo == hi)
+ return n;
+
+ n = 2;
+ if (inorder (pred, lo[0], lo[-1]))
+ {
+ *descending = 1;
+ for (lo = lo + 1; lo < hi; ++lo, ++n)
+ {
+ if (!inorder (pred, lo[0], lo[-1]))
+ break;
+ }
+ }
+ else
+ {
+ for (lo = lo + 1; lo < hi; ++lo, ++n)
+ {
+ if (inorder (pred, lo[0], lo[-1]))
+ break;
+ }
+ }
+
+ return n;
+}
+
+
+/* Locate and return the proper insertion position of KEY in a sorted
+ vector: if the vector contains an element equal to KEY, return the
+ position immediately to the left of the leftmost equal element.
+ [GALLOP_RIGHT does the same except it returns the position to the
+ right of the rightmost equal element (if any).]
+
+ 'A' is a sorted vector of N elements. N must be > 0.
+
+ Elements preceding HINT, a non-negative index less than N, are
+ skipped. The closer HINT is to the final result, the faster this
+ runs.
+
+ The return value is the int k in [0, N] such that
+
+ A[k-1] < KEY <= a[k]
+
+ pretending that *(A-1) precedes all values and *(A+N) succeeds all
+ values. In other words, the first k elements of A should precede
+ KEY, and the last N-k should follow KEY. */
+
+static ptrdiff_t
+gallop_left (merge_state *ms, const Lisp_Object key, Lisp_Object *a,
+ const ptrdiff_t n, const ptrdiff_t hint)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (a && n > 0 && hint >= 0 && hint < n);
+
+ a += hint;
+ ptrdiff_t lastofs = 0;
+ ptrdiff_t ofs = 1;
+ if (inorder (pred, *a, key))
+ {
+ /* When a[hint] < key, gallop right until
+ a[hint + lastofs] < key <= a[hint + ofs]. */
+ const ptrdiff_t maxofs = n - hint; /* This is one after the end of a. */
+ while (ofs < maxofs)
+ {
+ if (inorder (pred, a[ofs], key))
+ {
+ lastofs = ofs;
+ eassume (ofs <= (PTRDIFF_MAX - 1) / 2);
+ ofs = (ofs << 1) + 1;
+ }
+ else
+ break; /* Here key <= a[hint+ofs]. */
+ }
+ if (ofs > maxofs)
+ ofs = maxofs;
+ /* Translate back to offsets relative to &a[0]. */
+ lastofs += hint;
+ ofs += hint;
+ }
+ else
+ {
+ /* When key <= a[hint], gallop left, until
+ a[hint - ofs] < key <= a[hint - lastofs]. */
+ const ptrdiff_t maxofs = hint + 1; /* Here &a[0] is lowest. */
+ while (ofs < maxofs)
+ {
+ if (inorder (pred, a[-ofs], key))
+ break;
+ /* Here key <= a[hint - ofs]. */
+ lastofs = ofs;
+ eassume (ofs <= (PTRDIFF_MAX - 1) / 2);
+ ofs = (ofs << 1) + 1;
+ }
+ if (ofs > maxofs)
+ ofs = maxofs;
+ /* Translate back to use positive offsets relative to &a[0]. */
+ ptrdiff_t k = lastofs;
+ lastofs = hint - ofs;
+ ofs = hint - k;
+ }
+ a -= hint;
+
+ eassume (-1 <= lastofs && lastofs < ofs && ofs <= n);
+ /* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the
+ right of lastofs but no farther right than ofs. Do a binary
+ search, with invariant a[lastofs-1] < key <= a[ofs]. */
+ ++lastofs;
+ while (lastofs < ofs)
+ {
+ ptrdiff_t m = lastofs + ((ofs - lastofs) >> 1);
+
+ if (inorder (pred, a[m], key))
+ lastofs = m + 1; /* Here a[m] < key. */
+ else
+ ofs = m; /* Here key <= a[m]. */
+ }
+ eassume (lastofs == ofs); /* Then a[ofs-1] < key <= a[ofs]. */
+ return ofs;
+}
+
+
+/* Locate and return the proper position of KEY in a sorted vector
+ exactly like GALLOP_LEFT, except that if KEY already exists in
+ A[0:N] find the position immediately to the right of the rightmost
+ equal value.
+
+ The return value is the int k in [0, N] such that
+
+ A[k-1] <= KEY < A[k]. */
+
+static ptrdiff_t
+gallop_right (merge_state *ms, const Lisp_Object key, Lisp_Object *a,
+ const ptrdiff_t n, const ptrdiff_t hint)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (a && n > 0 && hint >= 0 && hint < n);
+
+ a += hint;
+ ptrdiff_t lastofs = 0;
+ ptrdiff_t ofs = 1;
+ if (inorder (pred, key, *a))
+ {
+ /* When key < a[hint], gallop left until
+ a[hint - ofs] <= key < a[hint - lastofs]. */
+ const ptrdiff_t maxofs = hint + 1; /* Here &a[0] is lowest. */
+ while (ofs < maxofs)
+ {
+ if (inorder (pred, key, a[-ofs]))
+ {
+ lastofs = ofs;
+ eassume (ofs <= (PTRDIFF_MAX - 1) / 2);
+ ofs = (ofs << 1) + 1;
+ }
+ else /* Here a[hint - ofs] <= key. */
+ break;
+ }
+ if (ofs > maxofs)
+ ofs = maxofs;
+ /* Translate back to use positive offsets relative to &a[0]. */
+ ptrdiff_t k = lastofs;
+ lastofs = hint - ofs;
+ ofs = hint - k;
+ }
+ else
+ {
+ /* When a[hint] <= key, gallop right, until
+ a[hint + lastofs] <= key < a[hint + ofs]. */
+ const ptrdiff_t maxofs = n - hint; /* Here &a[n-1] is highest. */
+ while (ofs < maxofs)
+ {
+ if (inorder (pred, key, a[ofs]))
+ break;
+ /* Here a[hint + ofs] <= key. */
+ lastofs = ofs;
+ eassume (ofs <= (PTRDIFF_MAX - 1) / 2);
+ ofs = (ofs << 1) + 1;
+ }
+ if (ofs > maxofs)
+ ofs = maxofs;
+ /* Translate back to use offsets relative to &a[0]. */
+ lastofs += hint;
+ ofs += hint;
+ }
+ a -= hint;
+
+ eassume (-1 <= lastofs && lastofs < ofs && ofs <= n);
+ /* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the
+ right of lastofs but no farther right than ofs. Do a binary
+ search, with invariant a[lastofs-1] <= key < a[ofs]. */
+ ++lastofs;
+ while (lastofs < ofs)
+ {
+ ptrdiff_t m = lastofs + ((ofs - lastofs) >> 1);
+
+ if (inorder (pred, key, a[m]))
+ ofs = m; /* Here key < a[m]. */
+ else
+ lastofs = m + 1; /* Here a[m] <= key. */
+ }
+ eassume (lastofs == ofs); /* Now a[ofs-1] <= key < a[ofs]. */
+ return ofs;
+}
+
+
+static void
+merge_init (merge_state *ms, const ptrdiff_t list_size, Lisp_Object *lo,
+ const Lisp_Object predicate)
+{
+ eassume (ms != NULL);
+
+ ms->a = ms->temparray;
+ ms->alloced = MERGESTATE_TEMP_SIZE;
+
+ ms->n = 0;
+ ms->min_gallop = GALLOP_WIN_MIN;
+ ms->listlen = list_size;
+ ms->listbase = lo;
+ ms->predicate = predicate;
+ ms->reloc = (struct reloc){NULL, NULL, NULL, 0};
+}
+
+
+/* The dynamically allocated memory may hold lisp objects during
+ merging. MERGE_MARKMEM marks them so they aren't reaped during
+ GC. */
+
+static void
+merge_markmem (void *arg)
+{
+ merge_state *ms = arg;
+ eassume (ms != NULL);
+
+ if (ms->reloc.size != NULL && *ms->reloc.size > 0)
+ {
+ eassume (ms->reloc.src != NULL);
+ mark_objects (*ms->reloc.src, *ms->reloc.size);
+ }
+}
+
+
+/* Free all temp storage. If an exception occurs while merging,
+ relocate any lisp elements in temp storage back to the original
+ array. */
+
+static void
+cleanup_mem (void *arg)
+{
+ merge_state *ms = arg;
+ eassume (ms != NULL);
+
+ /* If we have an exception while merging, some of the list elements
+ might only live in temp storage; we copy everything remaining in
+ the temp storage back into the original list. This ensures that
+ the original list has all of the original elements, although
+ their order is unpredictable. */
+
+ if (ms->reloc.order != 0 && *ms->reloc.size > 0)
+ {
+ eassume (*ms->reloc.src != NULL && *ms->reloc.dst != NULL);
+ ptrdiff_t n = *ms->reloc.size;
+ ptrdiff_t shift = ms->reloc.order == -1 ? 0 : n - 1;
+ memcpy (*ms->reloc.dst - shift, *ms->reloc.src, n * word_size);
+ }
+
+ /* Free any remaining temp storage. */
+ xfree (ms->a);
+}
+
+
+/* Allocate enough temp memory for NEED array slots. Any previously
+ allocated memory is first freed, and a cleanup routine is
+ registered to free memory at the very end of the sort, or on
+ exception. */
+
+static void
+merge_getmem (merge_state *ms, const ptrdiff_t need)
+{
+ eassume (ms != NULL);
+
+ if (ms->a == ms->temparray)
+ {
+ /* We only get here if alloc is needed and this is the first
+ time, so we set up the unwind protection. */
+ specpdl_ref count = SPECPDL_INDEX ();
+ record_unwind_protect_ptr_mark (cleanup_mem, ms, merge_markmem);
+ ms->count = count;
+ }
+ else
+ {
+ /* We have previously alloced storage. Since we don't care
+ what's in the block we don't use realloc which would waste
+ cycles copying the old data. We just free and alloc
+ again. */
+ xfree (ms->a);
+ }
+ ms->a = xmalloc (need * word_size);
+ ms->alloced = need;
+}
+
+
+static inline void
+needmem (merge_state *ms, ptrdiff_t na)
+{
+ if (na > ms->alloced)
+ merge_getmem (ms, na);
+}
+
+
+/* Stably merge (in-place) the NA elements starting at SSA with the NB
+ elements starting at SSB = SSA + NA. NA and NB must be positive.
+ Require that SSA[NA-1] belongs at the end of the merge, and NA <=
+ NB. */
+
+static void
+merge_lo (merge_state *ms, Lisp_Object *ssa, ptrdiff_t na, Lisp_Object *ssb,
+ ptrdiff_t nb)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (ms && ssa && ssb && na > 0 && nb > 0);
+ eassume (ssa + na == ssb);
+ needmem (ms, na);
+ memcpy (ms->a, ssa, na * word_size);
+ Lisp_Object *dest = ssa;
+ ssa = ms->a;
+
+ ms->reloc = (struct reloc){&ssa, &dest, &na, -1};
+
+ *dest++ = *ssb++;
+ --nb;
+ if (nb == 0)
+ goto Succeed;
+ if (na == 1)
+ goto CopyB;
+
+ ptrdiff_t min_gallop = ms->min_gallop;
+ for (;;)
+ {
+ ptrdiff_t acount = 0; /* The # of consecutive times A won. */
+
+ ptrdiff_t bcount = 0; /* The # of consecutive times B won. */
+
+ for (;;)
+ {
+ eassume (na > 1 && nb > 0);
+ if (inorder (pred, *ssb, *ssa))
+ {
+ *dest++ = *ssb++ ;
+ ++bcount;
+ acount = 0;
+ --nb;
+ if (nb == 0)
+ goto Succeed;
+ if (bcount >= min_gallop)
+ break;
+ }
+ else
+ {
+ *dest++ = *ssa++;
+ ++acount;
+ bcount = 0;
+ --na;
+ if (na == 1)
+ goto CopyB;
+ if (acount >= min_gallop)
+ break;
+ }
+ }
+
+ /* One run is winning so consistently that galloping may be a
+ huge speedup. We try that, and continue galloping until (if
+ ever) neither run appears to be winning consistently
+ anymore. */
+ ++min_gallop;
+ do {
+ eassume (na > 1 && nb > 0);
+ min_gallop -= min_gallop > 1;
+ ms->min_gallop = min_gallop;
+ ptrdiff_t k = gallop_right (ms, ssb[0], ssa, na, 0);
+ acount = k;
+ if (k)
+ {
+ memcpy (dest, ssa, k * word_size);
+ dest += k;
+ ssa += k;
+ na -= k;
+ if (na == 1)
+ goto CopyB;
+ /* While na==0 is impossible for a consistent comparison
+ function, we shouldn't assume that it is. */
+ if (na == 0)
+ goto Succeed;
+ }
+ *dest++ = *ssb++ ;
+ --nb;
+ if (nb == 0)
+ goto Succeed;
+
+ k = gallop_left (ms, ssa[0], ssb, nb, 0);
+ bcount = k;
+ if (k)
+ {
+ memmove (dest, ssb, k * word_size);
+ dest += k;
+ ssb += k;
+ nb -= k;
+ if (nb == 0)
+ goto Succeed;
+ }
+ *dest++ = *ssa++;
+ --na;
+ if (na == 1)
+ goto CopyB;
+ } while (acount >= GALLOP_WIN_MIN || bcount >= GALLOP_WIN_MIN);
+ ++min_gallop; /* Apply a penalty for leaving galloping mode. */
+ ms->min_gallop = min_gallop;
+ }
+ Succeed:
+ ms->reloc = (struct reloc){NULL, NULL, NULL, 0};
+
+ if (na)
+ memcpy (dest, ssa, na * word_size);
+ return;
+ CopyB:
+ eassume (na == 1 && nb > 0);
+ ms->reloc = (struct reloc){NULL, NULL, NULL, 0};
+
+ /* The last element of ssa belongs at the end of the merge. */
+ memmove (dest, ssb, nb * word_size);
+ dest[nb] = ssa[0];
+}
+
+
+/* Stably merge (in-place) the NA elements starting at SSA with the NB
+ elements starting at SSB = SSA + NA. NA and NB must be positive.
+ Require that SSA[NA-1] belongs at the end of the merge, and NA >=
+ NB. */
+
+static void
+merge_hi (merge_state *ms, Lisp_Object *ssa, ptrdiff_t na,
+ Lisp_Object *ssb, ptrdiff_t nb)
+{
+ Lisp_Object pred = ms->predicate;
+
+ eassume (ms && ssa && ssb && na > 0 && nb > 0);
+ eassume (ssa + na == ssb);
+ needmem (ms, nb);
+ Lisp_Object *dest = ssb;
+ dest += nb - 1;
+ memcpy(ms->a, ssb, nb * word_size);
+ Lisp_Object *basea = ssa;
+ Lisp_Object *baseb = ms->a;
+ ssb = ms->a + nb - 1;
+ ssa += na - 1;
+
+ ms->reloc = (struct reloc){&baseb, &dest, &nb, 1};
+
+ *dest-- = *ssa--;
+ --na;
+ if (na == 0)
+ goto Succeed;
+ if (nb == 1)
+ goto CopyA;
+
+ ptrdiff_t min_gallop = ms->min_gallop;
+ for (;;) {
+ ptrdiff_t acount = 0; /* The # of consecutive times A won. */
+ ptrdiff_t bcount = 0; /* The # of consecutive times B won. */
+
+ for (;;) {
+ eassume (na > 0 && nb > 1);
+ if (inorder (pred, *ssb, *ssa))
+ {
+ *dest-- = *ssa--;
+ ++acount;
+ bcount = 0;
+ --na;
+ if (na == 0)
+ goto Succeed;
+ if (acount >= min_gallop)
+ break;
+ }
+ else
+ {
+ *dest-- = *ssb--;
+ ++bcount;
+ acount = 0;
+ --nb;
+ if (nb == 1)
+ goto CopyA;
+ if (bcount >= min_gallop)
+ break;
+ }
+ }
+
+ /* One run is winning so consistently that galloping may be a huge
+ speedup. Try that, and continue galloping until (if ever)
+ neither run appears to be winning consistently anymore. */
+ ++min_gallop;
+ do {
+ eassume (na > 0 && nb > 1);
+ min_gallop -= min_gallop > 1;
+ ms->min_gallop = min_gallop;
+ ptrdiff_t k = gallop_right (ms, ssb[0], basea, na, na - 1);
+ k = na - k;
+ acount = k;
+ if (k)
+ {
+ dest += -k;
+ ssa += -k;
+ memmove(dest + 1, ssa + 1, k * word_size);
+ na -= k;
+ if (na == 0)
+ goto Succeed;
+ }
+ *dest-- = *ssb--;
+ --nb;
+ if (nb == 1)
+ goto CopyA;
+
+ k = gallop_left (ms, ssa[0], baseb, nb, nb - 1);
+ k = nb - k;
+ bcount = k;
+ if (k)
+ {
+ dest += -k;
+ ssb += -k;
+ memcpy(dest + 1, ssb + 1, k * word_size);
+ nb -= k;
+ if (nb == 1)
+ goto CopyA;
+ /* While nb==0 is impossible for a consistent comparison
+ function we shouldn't assume that it is. */
+ if (nb == 0)
+ goto Succeed;
+ }
+ *dest-- = *ssa--;
+ --na;
+ if (na == 0)
+ goto Succeed;
+ } while (acount >= GALLOP_WIN_MIN || bcount >= GALLOP_WIN_MIN);
+ ++min_gallop; /* Apply a penalty for leaving galloping mode. */
+ ms->min_gallop = min_gallop;
+ }
+ Succeed:
+ ms->reloc = (struct reloc){NULL, NULL, NULL, 0};
+ if (nb)
+ memcpy (dest - nb + 1, baseb, nb * word_size);
+ return;
+ CopyA:
+ eassume (nb == 1 && na > 0);
+ ms->reloc = (struct reloc){NULL, NULL, NULL, 0};
+ /* The first element of ssb belongs at the front of the merge. */
+ memmove (dest + 1 - na, ssa + 1 - na, na * word_size);
+ dest += -na;
+ ssa += -na;
+ dest[0] = ssb[0];
+}
+
+
+/* Merge the two runs at stack indices I and I+1. */
+
+static void
+merge_at (merge_state *ms, const ptrdiff_t i)
+{
+ eassume (ms != NULL);
+ eassume (ms->n >= 2);
+ eassume (i >= 0);
+ eassume (i == ms->n - 2 || i == ms->n - 3);
+
+ Lisp_Object *ssa = ms->pending[i].base;
+ ptrdiff_t na = ms->pending[i].len;
+ Lisp_Object *ssb = ms->pending[i + 1].base;
+ ptrdiff_t nb = ms->pending[i + 1].len;
+ eassume (na > 0 && nb > 0);
+ eassume (ssa + na == ssb);
+
+ /* Record the length of the combined runs. The current run i+1 goes
+ away after the merge. If i is the 3rd-last run now, slide the
+ last run (which isn't involved in this merge) over to i+1. */
+ ms->pending[i].len = na + nb;
+ if (i == ms->n - 3)
+ ms->pending[i + 1] = ms->pending[i + 2];
+ --ms->n;
+
+ /* Where does b start in a? Elements in a before that can be
+ ignored (they are already in place). */
+ ptrdiff_t k = gallop_right (ms, *ssb, ssa, na, 0);
+ eassume (k >= 0);
+ ssa += k;
+ na -= k;
+ if (na == 0)
+ return;
+
+ /* Where does a end in b? Elements in b after that can be ignored
+ (they are already in place). */
+ nb = gallop_left (ms, ssa[na - 1], ssb, nb, nb - 1);
+ if (nb == 0)
+ return;
+ eassume (nb > 0);
+ /* Merge what remains of the runs using a temp array with size
+ min(na, nb) elements. */
+ if (na <= nb)
+ merge_lo (ms, ssa, na, ssb, nb);
+ else
+ merge_hi (ms, ssa, na, ssb, nb);
+}
+
+
+/* Compute the "power" of the first of two adjacent runs beginning at
+ index S1, with the first having length N1 and the second (starting
+ at index S1+N1) having length N2. The run has total length N. */
+
+static int
+powerloop (const ptrdiff_t s1, const ptrdiff_t n1, const ptrdiff_t n2,
+ const ptrdiff_t n)
+{
+ eassume (s1 >= 0);
+ eassume (n1 > 0 && n2 > 0);
+ eassume (s1 + n1 + n2 <= n);
+ /* The midpoints a and b are
+ a = s1 + n1/2
+ b = s1 + n1 + n2/2 = a + (n1 + n2)/2
+
+ These may not be integers because of the "/2", so we work with
+ 2*a and 2*b instead. It makes no difference to the outcome,
+ since the bits in the expansion of (2*i)/n are merely shifted one
+ position from those of i/n. */
+ ptrdiff_t a = 2 * s1 + n1;
+ ptrdiff_t b = a + n1 + n2;
+ int result = 0;
+ /* Emulate a/n and b/n one bit a time, until their bits differ. */
+ for (;;)
+ {
+ ++result;
+ if (a >= n)
+ { /* Both quotient bits are now 1. */
+ eassume (b >= a);
+ a -= n;
+ b -= n;
+ }
+ else if (b >= n)
+ { /* a/n bit is 0 and b/n bit is 1. */
+ break;
+ } /* Otherwise both quotient bits are 0. */
+ eassume (a < b && b < n);
+ a <<= 1;
+ b <<= 1;
+ }
+ return result;
+}
+
+
+/* Update the state upon identifying a run of length N2. If there's
+ already a stretch on the stack, apply the "powersort" merge
+ strategy: compute the topmost stretch's "power" (depth in a
+ conceptual binary merge tree) and merge adjacent runs on the stack
+ with greater power. */
+
+static void
+found_new_run (merge_state *ms, const ptrdiff_t n2)
+{
+ eassume (ms != NULL);
+ if (ms->n)
+ {
+ eassume (ms->n > 0);
+ struct stretch *p = ms->pending;
+ ptrdiff_t s1 = p[ms->n - 1].base - ms->listbase;
+ ptrdiff_t n1 = p[ms->n - 1].len;
+ int power = powerloop (s1, n1, n2, ms->listlen);
+ while (ms->n > 1 && p[ms->n - 2].power > power)
+ {
+ merge_at (ms, ms->n - 2);
+ }
+ eassume (ms->n < 2 || p[ms->n - 2].power < power);
+ p[ms->n - 1].power = power;
+ }
+}
+
+
+/* Unconditionally merge all stretches on the stack until only one
+ remains. */
+
+static void
+merge_force_collapse (merge_state *ms)
+{
+ struct stretch *p = ms->pending;
+
+ eassume (ms != NULL);
+ while (ms->n > 1)
+ {
+ ptrdiff_t n = ms->n - 2;
+ if (n > 0 && p[n - 1].len < p[n + 1].len)
+ --n;
+ merge_at (ms, n);
+ }
+}
+
+
+/* Compute a good value for the minimum run length; natural runs
+ shorter than this are boosted artificially via binary insertion.
+
+ If N < 64, return N (it's too small to bother with fancy stuff).
+ Otherwise if N is an exact power of 2, return 32. Finally, return
+ an int k, 32 <= k <= 64, such that N/k is close to, but strictly
+ less than, an exact power of 2. */
+
+static ptrdiff_t
+merge_compute_minrun (ptrdiff_t n)
+{
+ ptrdiff_t r = 0; /* r will become 1 if any non-zero bits are
+ shifted off. */
+
+ eassume (n >= 0);
+ while (n >= 64)
+ {
+ r |= n & 1;
+ n >>= 1;
+ }
+ return n + r;
+}
+
+
+static void
+reverse_vector (Lisp_Object *s, const ptrdiff_t n)
+{
+ for (ptrdiff_t i = 0; i < n >> 1; i++)
+ {
+ Lisp_Object tem = s[i];
+ s[i] = s[n - i - 1];
+ s[n - i - 1] = tem;
+ }
+}
+
+/* Sort the array SEQ with LENGTH elements in the order determined by
+ PREDICATE. */
+
+void
+tim_sort (Lisp_Object predicate, Lisp_Object *seq, const ptrdiff_t length)
+{
+ if (SYMBOLP (predicate))
+ {
+ /* Attempt to resolve the function as far as possible ahead of time,
+ to avoid having to do it for each call. */
+ Lisp_Object fun = XSYMBOL (predicate)->u.s.function;
+ if (SYMBOLP (fun))
+ /* Function was an alias; use slow-path resolution. */
+ fun = indirect_function (fun);
+ /* Don't resolve to an autoload spec; that would be very slow. */
+ if (!NILP (fun) && !(CONSP (fun) && EQ (XCAR (fun), Qautoload)))
+ predicate = fun;
+ }
+
+ merge_state ms;
+ Lisp_Object *lo = seq;
+
+ merge_init (&ms, length, lo, predicate);
+
+ /* March over the array once, left to right, finding natural runs,
+ and extending short natural runs to minrun elements. */
+ const ptrdiff_t minrun = merge_compute_minrun (length);
+ ptrdiff_t nremaining = length;
+ do {
+ bool descending;
+
+ /* Identify the next run. */
+ ptrdiff_t n = count_run (&ms, lo, lo + nremaining, &descending);
+ if (descending)
+ reverse_vector (lo, n);
+ /* If the run is short, extend it to min(minrun, nremaining). */
+ if (n < minrun)
+ {
+ const ptrdiff_t force = nremaining <= minrun ?
+ nremaining : minrun;
+ binarysort (&ms, lo, lo + force, lo + n);
+ n = force;
+ }
+ eassume (ms.n == 0 || ms.pending[ms.n - 1].base +
+ ms.pending[ms.n - 1].len == lo);
+ found_new_run (&ms, n);
+ /* Push the new run on to the stack. */
+ eassume (ms.n < MAX_MERGE_PENDING);
+ ms.pending[ms.n].base = lo;
+ ms.pending[ms.n].len = n;
+ ++ms.n;
+ /* Advance to find the next run. */
+ lo += n;
+ nremaining -= n;
+ } while (nremaining);
+
+ merge_force_collapse (&ms);
+ eassume (ms.n == 1);
+ eassume (ms.pending[0].len == length);
+ lo = ms.pending[0].base;
+
+ if (ms.a != ms.temparray)
+ unbind_to (ms.count, Qnil);
+}
diff --git a/src/sound.c b/src/sound.c
index 9681a136e4b..0a307828008 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -361,10 +361,10 @@ parse_sound (Lisp_Object sound, Lisp_Object *attrs)
return 0;
sound = XCDR (sound);
- attrs[SOUND_FILE] = Fplist_get (sound, QCfile);
- attrs[SOUND_DATA] = Fplist_get (sound, QCdata);
- attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
- attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
+ attrs[SOUND_FILE] = plist_get (sound, QCfile);
+ attrs[SOUND_DATA] = plist_get (sound, QCdata);
+ attrs[SOUND_DEVICE] = plist_get (sound, QCdevice);
+ attrs[SOUND_VOLUME] = plist_get (sound, QCvolume);
#ifndef WINDOWSNT
/* File name or data must be specified. */
@@ -1359,7 +1359,7 @@ Internal use only, use `play-sound' instead. */)
(Lisp_Object sound)
{
Lisp_Object attrs[SOUND_ATTR_SENTINEL];
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
#ifdef WINDOWSNT
unsigned long ui_volume_tmp = UINT_MAX;
diff --git a/src/sqlite.c b/src/sqlite.c
index 649cb382948..54bfb7b6c61 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -1,4 +1,5 @@
-/*
+/* Support for accessing SQLite databases.
+
Copyright (C) 2021-2022 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -19,8 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
This file is based on the emacs-sqlite3 package written by Syohei
YOSHIDA <syohex@gmail.com>, which can be found at:
- https://github.com/syohex/emacs-sqlite3
-*/
+ https://github.com/syohex/emacs-sqlite3 */
#include <config.h>
#include "lisp.h"
@@ -43,6 +43,8 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_open_v2,
DEF_DLL_FN (SQLITE_API int, sqlite3_reset, (sqlite3_stmt*));
DEF_DLL_FN (SQLITE_API int, sqlite3_bind_text,
(sqlite3_stmt*, int, const char*, int, void(*)(void*)));
+DEF_DLL_FN (SQLITE_API int, sqlite3_bind_blob,
+ (sqlite3_stmt*, int, const char*, int, void(*)(void*)));
DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int64,
(sqlite3_stmt*, int, sqlite3_int64));
DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double));
@@ -80,6 +82,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
# undef sqlite3_open_v2
# undef sqlite3_reset
# undef sqlite3_bind_text
+# undef sqlite3_bind_blob
# undef sqlite3_bind_int64
# undef sqlite3_bind_double
# undef sqlite3_bind_null
@@ -103,6 +106,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
# define sqlite3_open_v2 fn_sqlite3_open_v2
# define sqlite3_reset fn_sqlite3_reset
# define sqlite3_bind_text fn_sqlite3_bind_text
+# define sqlite3_bind_blob fn_sqlite3_bind_blob
# define sqlite3_bind_int64 fn_sqlite3_bind_int64
# define sqlite3_bind_double fn_sqlite3_bind_double
# define sqlite3_bind_null fn_sqlite3_bind_null
@@ -129,6 +133,7 @@ load_dll_functions (HMODULE library)
LOAD_DLL_FN (library, sqlite3_open_v2);
LOAD_DLL_FN (library, sqlite3_reset);
LOAD_DLL_FN (library, sqlite3_bind_text);
+ LOAD_DLL_FN (library, sqlite3_bind_blob);
LOAD_DLL_FN (library, sqlite3_bind_int64);
LOAD_DLL_FN (library, sqlite3_bind_double);
LOAD_DLL_FN (library, sqlite3_bind_null);
@@ -240,38 +245,38 @@ DEFUN ("sqlite-open", Fsqlite_open, Ssqlite_open, 0, 1, 0,
If FILE is nil, an in-memory database will be opened instead. */)
(Lisp_Object file)
{
- char *name;
+ Lisp_Object name;
+ int flags = (SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE);
+#ifdef SQLITE_OPEN_FULLMUTEX
+ flags |= SQLITE_OPEN_FULLMUTEX;
+#endif
+#ifdef SQLITE_OPEN_URI
+ flags |= SQLITE_OPEN_URI;
+#endif
+
if (!init_sqlite_functions ())
xsignal1 (Qerror, build_string ("sqlite support is not available"));
if (!NILP (file))
+ name = ENCODE_FILE (Fexpand_file_name (file, Qnil));
+ else
{
- CHECK_STRING (file);
- file = ENCODE_FILE (Fexpand_file_name (file, Qnil));
- name = xstrdup (SSDATA (file));
+#ifdef SQLITE_OPEN_MEMORY
+ /* In-memory database. These have to have different names to
+ refer to different databases. */
+ AUTO_STRING (memory_fmt, ":memory:%d");
+ name = CALLN (Fformat, memory_fmt, make_int (++db_count));
+ flags |= SQLITE_OPEN_MEMORY;
+#else
+ xsignal1 (Qerror, build_string ("sqlite in-memory is not available"));
+#endif
}
- else
- /* In-memory database. These have to have different names to
- refer to different databases. */
- name = xstrdup (SSDATA (CALLN (Fformat, build_string (":memory:%d"),
- make_int (++db_count))));
sqlite3 *sdb;
- int ret = sqlite3_open_v2 (name,
- &sdb,
- SQLITE_OPEN_FULLMUTEX
- | SQLITE_OPEN_READWRITE
- | SQLITE_OPEN_CREATE
- | (NILP (file) ? SQLITE_OPEN_MEMORY : 0)
-#ifdef SQLITE_OPEN_URI
- | SQLITE_OPEN_URI
-#endif
- | 0, NULL);
-
- if (ret != SQLITE_OK)
+ if (sqlite3_open_v2 (SSDATA (name), &sdb, flags, NULL) != SQLITE_OK)
return Qnil;
- return make_sqlite (false, sdb, NULL, name);
+ return make_sqlite (false, sdb, NULL, xstrdup (SSDATA (name)));
}
DEFUN ("sqlite-close", Fsqlite_close, Ssqlite_close, 1, 1, 0,
@@ -311,10 +316,37 @@ bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values)
if (EQ (type, Qstring))
{
- Lisp_Object encoded = encode_string (value);
- ret = sqlite3_bind_text (stmt, i + 1,
- SSDATA (encoded), SBYTES (encoded),
- NULL);
+ Lisp_Object encoded;
+ bool blob = false;
+
+ if (SBYTES (value) == 0)
+ encoded = value;
+ else
+ {
+ Lisp_Object coding_system =
+ Fget_text_property (make_fixnum (0), Qcoding_system, value);
+ if (NILP (coding_system))
+ /* Default to utf-8. */
+ encoded = encode_string (value);
+ else if (EQ (coding_system, Qbinary))
+ blob = true;
+ else
+ encoded = Fencode_coding_string (value, coding_system,
+ Qnil, Qnil);
+ }
+
+ if (blob)
+ {
+ if (SBYTES (value) != SCHARS (value))
+ xsignal1 (Qerror, build_string ("BLOB values must be unibyte"));
+ ret = sqlite3_bind_blob (stmt, i + 1,
+ SSDATA (value), SBYTES (value),
+ NULL);
+ }
+ else
+ ret = sqlite3_bind_text (stmt, i + 1,
+ SSDATA (encoded), SBYTES (encoded),
+ NULL);
}
else if (EQ (type, Qinteger))
{
@@ -428,11 +460,8 @@ row_to_value (sqlite3_stmt *stmt)
break;
case SQLITE_BLOB:
- v =
- code_convert_string_norecord
- (make_unibyte_string (sqlite3_column_blob (stmt, i),
- sqlite3_column_bytes (stmt, i)),
- Qutf_8, false);
+ v = make_unibyte_string (sqlite3_column_blob (stmt, i),
+ sqlite3_column_bytes (stmt, i));
break;
case SQLITE_NULL:
@@ -750,4 +779,6 @@ syms_of_sqlite (void)
DEFSYM (Qfalse, "false");
DEFSYM (Qsqlite, "sqlite");
DEFSYM (Qsqlite3, "sqlite3");
+ DEFSYM (Qbinary, "binary");
+ DEFSYM (Qcoding_system, "coding-system");
}
diff --git a/src/syntax.c b/src/syntax.c
index 9df878b8edf..15625b4d0e2 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
+#include "dispextern.h"
#include "character.h"
#include "buffer.h"
#include "regex-emacs.h"
@@ -1074,7 +1075,7 @@ unsigned char const syntax_spec_code[0400] =
/* Indexed by syntax code, give the letter that describes it. */
-char const syntax_code_spec[16] =
+static char const syntax_code_spec[16] =
{
' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@',
'!', '|'
@@ -1101,10 +1102,11 @@ this is probably the wrong function to use, because it can't take
`syntax-after' instead. */)
(Lisp_Object character)
{
- int char_int;
CHECK_CHARACTER (character);
- char_int = XFIXNUM (character);
+ int char_int = XFIXNAT (character);
SETUP_BUFFER_SYNTAX_TABLE ();
+ if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ char_int = make_char_multibyte (char_int);
return make_fixnum (syntax_code_spec[SYNTAX (char_int)]);
}
@@ -3194,6 +3196,7 @@ scan_sexps_forward (struct lisp_parse_state *state,
ptrdiff_t out_bytepos, out_charpos;
int temp;
unsigned short int quit_count = 0;
+ ptrdiff_t started_from = from;
prev_from = from;
prev_from_byte = from_byte;
@@ -3473,6 +3476,13 @@ do { prev_from = from; \
state->levelstarts);
state->prev_syntax = (SYNTAX_FLAGS_COMSTARTEND_FIRST (prev_from_syntax)
|| state->quoted) ? prev_from_syntax : Smax;
+
+ /* The factor of 10 below is a heuristic that needs to be tuned. It
+ means we consider 10 buffer positions examined by this function
+ roughly equivalent to the display engine iterating over a single
+ buffer position. */
+ if (max_redisplay_ticks > 0 && from > started_from)
+ update_redisplay_ticks ((from - started_from) / 10 + 1, NULL);
}
/* Convert a (lisp) parse state to the internal form used in
diff --git a/src/syntax.h b/src/syntax.h
index c1bb9274d00..5949a95a73b 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -147,10 +147,6 @@ extern bool syntax_prefix_flag_p (int c);
extern unsigned char const syntax_spec_code[0400];
-/* Indexed by syntax code, give the letter that describes it. */
-
-extern char const syntax_code_spec[16];
-
/* Convert the byte offset BYTEPOS into a character position,
for the object recorded in gl_state with SETUP_SYNTAX_TABLE_FOR_OBJECT.
diff --git a/src/sysdep.c b/src/sysdep.c
index d682e87cc71..c1545622dfc 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -664,7 +664,7 @@ sys_subshell (void)
#else
{
char *volatile str_volatile = str;
- pid = vfork ();
+ pid = VFORK ();
str = str_volatile;
}
#endif
@@ -2200,6 +2200,16 @@ get_random (void)
return val & INTMASK;
}
+/* Return a random unsigned long. */
+unsigned long int
+get_random_ulong (void)
+{
+ unsigned long int r = 0;
+ for (int i = 0; i < (ULONG_WIDTH + RAND_BITS - 1) / RAND_BITS; i++)
+ r = random () ^ (r << RAND_BITS) ^ (r >> (ULONG_WIDTH - RAND_BITS));
+ return r;
+}
+
#ifndef HAVE_SNPRINTF
/* Approximate snprintf as best we can on ancient hosts that lack it. */
int
@@ -2320,6 +2330,20 @@ emacs_fstatat (int dirfd, char const *filename, void *st, int flags)
return r;
}
+static int
+sys_openat (int dirfd, char const *file, int oflags, int mode)
+{
+#ifdef O_PATH
+ return openat (dirfd, file, oflags, mode);
+#else
+ /* On platforms without O_PATH, emacs_openat's callers arrange for
+ DIRFD to be AT_FDCWD, so it should be safe to just call 'open'.
+ This ports to old platforms like OS X 10.9 that lack openat. */
+ eassert (dirfd == AT_FDCWD);
+ return open (file, oflags, mode);
+#endif
+}
+
/* Assuming the directory DIRFD, open FILE for Emacs use,
using open flags OFLAGS and mode MODE.
Use binary I/O on systems that care about text vs binary I/O.
@@ -2335,7 +2359,7 @@ emacs_openat (int dirfd, char const *file, int oflags, int mode)
if (! (oflags & O_TEXT))
oflags |= O_BINARY;
oflags |= O_CLOEXEC;
- while ((fd = openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR)
+ while ((fd = sys_openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR)
maybe_quit ();
return fd;
}
@@ -2348,26 +2372,19 @@ emacs_open (char const *file, int oflags, int mode)
/* Same as above, but doesn't allow the user to quit. */
-static int
-emacs_openat_noquit (int dirfd, const char *file, int oflags,
- int mode)
+int
+emacs_open_noquit (char const *file, int oflags, int mode)
{
int fd;
if (! (oflags & O_TEXT))
oflags |= O_BINARY;
oflags |= O_CLOEXEC;
do
- fd = openat (dirfd, file, oflags, mode);
+ fd = open (file, oflags, mode);
while (fd < 0 && errno == EINTR);
return fd;
}
-int
-emacs_open_noquit (char const *file, int oflags, int mode)
-{
- return emacs_openat_noquit (AT_FDCWD, file, oflags, mode);
-}
-
/* Open FILE as a stream for Emacs use, with mode MODE.
Act like emacs_open with respect to threads, signals, and quits. */
@@ -2922,21 +2939,21 @@ serial_configure (struct Lisp_Process *p,
#endif
/* Configure speed. */
- if (!NILP (Fplist_member (contact, QCspeed)))
- tem = Fplist_get (contact, QCspeed);
+ if (!NILP (plist_member (contact, QCspeed)))
+ tem = plist_get (contact, QCspeed);
else
- tem = Fplist_get (p->childp, QCspeed);
+ tem = plist_get (p->childp, QCspeed);
CHECK_FIXNUM (tem);
err = cfsetspeed (&attr, convert_speed (XFIXNUM (tem)));
if (err != 0)
report_file_error ("Failed cfsetspeed", tem);
- childp2 = Fplist_put (childp2, QCspeed, tem);
+ childp2 = plist_put (childp2, QCspeed, tem);
/* Configure bytesize. */
- if (!NILP (Fplist_member (contact, QCbytesize)))
- tem = Fplist_get (contact, QCbytesize);
+ if (!NILP (plist_member (contact, QCbytesize)))
+ tem = plist_get (contact, QCbytesize);
else
- tem = Fplist_get (p->childp, QCbytesize);
+ tem = plist_get (p->childp, QCbytesize);
if (NILP (tem))
tem = make_fixnum (8);
CHECK_FIXNUM (tem);
@@ -2951,13 +2968,13 @@ serial_configure (struct Lisp_Process *p,
if (XFIXNUM (tem) != 8)
error ("Bytesize cannot be changed");
#endif
- childp2 = Fplist_put (childp2, QCbytesize, tem);
+ childp2 = plist_put (childp2, QCbytesize, tem);
/* Configure parity. */
- if (!NILP (Fplist_member (contact, QCparity)))
- tem = Fplist_get (contact, QCparity);
+ if (!NILP (plist_member (contact, QCparity)))
+ tem = plist_get (contact, QCparity);
else
- tem = Fplist_get (p->childp, QCparity);
+ tem = plist_get (p->childp, QCparity);
if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
error (":parity must be nil (no parity), `even', or `odd'");
#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
@@ -2984,13 +3001,13 @@ serial_configure (struct Lisp_Process *p,
if (!NILP (tem))
error ("Parity cannot be configured");
#endif
- childp2 = Fplist_put (childp2, QCparity, tem);
+ childp2 = plist_put (childp2, QCparity, tem);
/* Configure stopbits. */
- if (!NILP (Fplist_member (contact, QCstopbits)))
- tem = Fplist_get (contact, QCstopbits);
+ if (!NILP (plist_member (contact, QCstopbits)))
+ tem = plist_get (contact, QCstopbits);
else
- tem = Fplist_get (p->childp, QCstopbits);
+ tem = plist_get (p->childp, QCstopbits);
if (NILP (tem))
tem = make_fixnum (1);
CHECK_FIXNUM (tem);
@@ -3006,13 +3023,13 @@ serial_configure (struct Lisp_Process *p,
if (XFIXNUM (tem) != 1)
error ("Stopbits cannot be configured");
#endif
- childp2 = Fplist_put (childp2, QCstopbits, tem);
+ childp2 = plist_put (childp2, QCstopbits, tem);
/* Configure flowcontrol. */
- if (!NILP (Fplist_member (contact, QCflowcontrol)))
- tem = Fplist_get (contact, QCflowcontrol);
+ if (!NILP (plist_member (contact, QCflowcontrol)))
+ tem = plist_get (contact, QCflowcontrol);
else
- tem = Fplist_get (p->childp, QCflowcontrol);
+ tem = plist_get (p->childp, QCflowcontrol);
if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
#if defined (CRTSCTS)
@@ -3046,14 +3063,14 @@ serial_configure (struct Lisp_Process *p,
error ("Software flowcontrol (XON/XOFF) not supported");
#endif
}
- childp2 = Fplist_put (childp2, QCflowcontrol, tem);
+ childp2 = plist_put (childp2, QCflowcontrol, tem);
/* Activate configuration. */
err = tcsetattr (p->outfd, TCSANOW, &attr);
if (err != 0)
report_file_error ("Failed tcsetattr", Qnil);
- childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
+ childp2 = plist_put (childp2, QCsummary, build_string (summary));
pset_childp (p, childp2);
}
#endif /* not DOS_NT */
@@ -3152,95 +3169,70 @@ list_system_processes (void)
#endif /* !defined (WINDOWSNT) */
+#if defined __FreeBSD__ || defined DARWIN_OS || defined __OpenBSD__
-#if defined __FreeBSD__ || defined DARWIN_OS
-
-static struct timespec
-timeval_to_timespec (struct timeval t)
-{
- return make_timespec (t.tv_sec, t.tv_usec * 1000);
-}
static Lisp_Object
-make_lisp_timeval (struct timeval t)
+make_lisp_s_us (time_t s, long us)
{
- return make_lisp_time (timeval_to_timespec (t));
+ Lisp_Object sec = make_int (s);
+ Lisp_Object usec = make_fixnum (us);
+ Lisp_Object hz = make_fixnum (1000000);
+ Lisp_Object ticks = CALLN (Fplus, CALLN (Ftimes, sec, hz), usec);
+ return Ftime_convert (Fcons (ticks, hz), Qnil);
}
-#elif defined __OpenBSD__
+#endif
+
+#if defined __FreeBSD__ || defined DARWIN_OS
static Lisp_Object
-make_lisp_timeval (long sec, long usec)
+make_lisp_timeval (struct timeval t)
{
- return make_lisp_time(make_timespec(sec, usec * 1000));
+ return make_lisp_s_us (t.tv_sec, t.tv_usec);
}
#endif
-#ifdef GNU_LINUX
-static struct timespec
-time_from_jiffies (unsigned long long tval, long hz)
-{
- unsigned long long s = tval / hz;
- unsigned long long frac = tval % hz;
- int ns;
-
- if (TYPE_MAXIMUM (time_t) < s)
- time_overflow ();
- if (LONG_MAX - 1 <= ULLONG_MAX / TIMESPEC_HZ
- || frac <= ULLONG_MAX / TIMESPEC_HZ)
- ns = frac * TIMESPEC_HZ / hz;
- else
- {
- /* This is reachable only in the unlikely case that HZ * HZ
- exceeds ULLONG_MAX. It calculates an approximation that is
- guaranteed to be in range. */
- long hz_per_ns = hz / TIMESPEC_HZ + (hz % TIMESPEC_HZ != 0);
- ns = frac / hz_per_ns;
- }
+#if defined (GNU_LINUX) || defined (CYGWIN)
- return make_timespec (s, ns);
+static Lisp_Object
+time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form)
+{
+ return Ftime_convert (Fcons (make_uint (ticks), hz), form);
}
static Lisp_Object
-ltime_from_jiffies (unsigned long long tval, long hz)
+put_jiffies (Lisp_Object attrs, Lisp_Object propname,
+ unsigned long long ticks, Lisp_Object hz)
{
- struct timespec t = time_from_jiffies (tval, hz);
- return make_lisp_time (t);
+ return Fcons (Fcons (propname, time_from_jiffies (ticks, hz, Qnil)), attrs);
}
-static struct timespec
+static Lisp_Object
get_up_time (void)
{
FILE *fup;
- struct timespec up = make_timespec (0, 0);
+ Lisp_Object up = Qnil;
block_input ();
fup = emacs_fopen ("/proc/uptime", "r");
if (fup)
{
- unsigned long long upsec, upfrac;
+ unsigned long long upsec;
+ EMACS_UINT upfrac;
int upfrac_start, upfrac_end;
- if (fscanf (fup, "%llu.%n%llu%n",
+ if (fscanf (fup, "%llu.%n%"pI"u%n",
&upsec, &upfrac_start, &upfrac, &upfrac_end)
== 2)
{
- if (TYPE_MAXIMUM (time_t) < upsec)
- {
- upsec = TYPE_MAXIMUM (time_t);
- upfrac = TIMESPEC_HZ - 1;
- }
- else
- {
- int upfraclen = upfrac_end - upfrac_start;
- for (; upfraclen < LOG10_TIMESPEC_HZ; upfraclen++)
- upfrac *= 10;
- for (; LOG10_TIMESPEC_HZ < upfraclen; upfraclen--)
- upfrac /= 10;
- upfrac = min (upfrac, TIMESPEC_HZ - 1);
- }
- up = make_timespec (upsec, upfrac);
+ EMACS_INT hz = 1;
+ for (int i = upfrac_start; i < upfrac_end; i++)
+ hz *= 10;
+ Lisp_Object sec = make_uint (upsec);
+ Lisp_Object subsec = Fcons (make_fixnum (upfrac), make_fixnum (hz));
+ up = Ftime_add (sec, subsec);
}
fclose (fup);
}
@@ -3249,6 +3241,7 @@ get_up_time (void)
return up;
}
+# ifdef GNU_LINUX
#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
@@ -3294,6 +3287,7 @@ procfs_ttyname (int rdev)
unblock_input ();
return build_string (name);
}
+# endif /* GNU_LINUX */
static uintmax_t
procfs_get_total_memory (void)
@@ -3361,11 +3355,9 @@ system_process_attributes (Lisp_Object pid)
unsigned long long u_time, s_time, cutime, cstime, start;
long priority, niceness, rss;
unsigned long minflt, majflt, cminflt, cmajflt, vsize;
- struct timespec tnow, tstart, tboot, telapsed, us_time;
double pcpu, pmem;
Lisp_Object attrs = Qnil;
Lisp_Object decoded_cmd;
- ptrdiff_t count;
CHECK_NUMBER (pid);
CONS_TO_INTEGER (pid, pid_t, proc_id);
@@ -3390,7 +3382,7 @@ system_process_attributes (Lisp_Object pid)
if (gr)
attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
strcpy (fn, procfn);
procfn_end = fn + strlen (fn);
strcpy (procfn_end, "/stat");
@@ -3430,7 +3422,7 @@ system_process_attributes (Lisp_Object pid)
utime stime cutime cstime priority nice thcount . start vsize rss */
if (q
&& (sscanf (q + 2, ("%c %d %d %d %d %d %*u %lu %lu %lu %lu "
- "%Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld"),
+ "%llu %llu %llu %llu %ld %ld %d %*d %llu %lu %ld"),
&c, &ppid, &pgrp, &sess, &tty, &tpgid,
&minflt, &cminflt, &majflt, &cmajflt,
&u_time, &s_time, &cutime, &cstime,
@@ -3444,53 +3436,49 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (ppid)), attrs);
attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pgrp)), attrs);
attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (sess)), attrs);
+# ifdef GNU_LINUX
attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
+# endif
attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (tpgid)), attrs);
attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (minflt)), attrs);
attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs);
attrs = Fcons (Fcons (Qcminflt, INT_TO_INTEGER (cminflt)), attrs);
attrs = Fcons (Fcons (Qcmajflt, INT_TO_INTEGER (cmajflt)), attrs);
+
clocks_per_sec = sysconf (_SC_CLK_TCK);
- if (clocks_per_sec < 0)
- clocks_per_sec = 100;
- attrs = Fcons (Fcons (Qutime,
- ltime_from_jiffies (u_time, clocks_per_sec)),
- attrs);
- attrs = Fcons (Fcons (Qstime,
- ltime_from_jiffies (s_time, clocks_per_sec)),
- attrs);
- attrs = Fcons (Fcons (Qtime,
- ltime_from_jiffies (s_time + u_time,
- clocks_per_sec)),
- attrs);
- attrs = Fcons (Fcons (Qcutime,
- ltime_from_jiffies (cutime, clocks_per_sec)),
- attrs);
- attrs = Fcons (Fcons (Qcstime,
- ltime_from_jiffies (cstime, clocks_per_sec)),
- attrs);
- attrs = Fcons (Fcons (Qctime,
- ltime_from_jiffies (cstime + cutime,
- clocks_per_sec)),
- attrs);
+ if (0 < clocks_per_sec)
+ {
+ Lisp_Object hz = make_int (clocks_per_sec);
+ attrs = put_jiffies (attrs, Qutime, u_time, hz);
+ attrs = put_jiffies (attrs, Qstime, s_time, hz);
+ attrs = put_jiffies (attrs, Qtime, s_time + u_time, hz);
+ attrs = put_jiffies (attrs, Qcutime, cutime, hz);
+ attrs = put_jiffies (attrs, Qcstime, cstime, hz);
+ attrs = put_jiffies (attrs, Qctime, cstime + cutime, hz);
+
+ Lisp_Object uptime = get_up_time ();
+ if (!NILP (uptime))
+ {
+ Lisp_Object now = Ftime_convert (Qnil, hz);
+ Lisp_Object boot = Ftime_subtract (now, uptime);
+ Lisp_Object tstart = time_from_jiffies (start, hz, hz);
+ Lisp_Object lstart =
+ Ftime_convert (Ftime_add (boot, tstart), Qnil);
+ attrs = Fcons (Fcons (Qstart, lstart), attrs);
+ Lisp_Object etime =
+ Ftime_convert (Ftime_subtract (uptime, tstart), Qnil);
+ attrs = Fcons (Fcons (Qetime, etime), attrs);
+ pcpu = (100.0 * (s_time + u_time)
+ / (clocks_per_sec * float_time (etime)));
+ attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
+ }
+ }
+
attrs = Fcons (Fcons (Qpri, make_fixnum (priority)), attrs);
attrs = Fcons (Fcons (Qnice, make_fixnum (niceness)), attrs);
attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (thcount)), attrs);
- tnow = current_timespec ();
- telapsed = get_up_time ();
- tboot = timespec_sub (tnow, telapsed);
- tstart = time_from_jiffies (start, clocks_per_sec);
- tstart = timespec_add (tboot, tstart);
- attrs = Fcons (Fcons (Qstart, make_lisp_time (tstart)), attrs);
attrs = Fcons (Fcons (Qvsize, INT_TO_INTEGER (vsize / 1024)), attrs);
attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (4 * rss)), attrs);
- telapsed = timespec_sub (tnow, tstart);
- attrs = Fcons (Fcons (Qetime, make_lisp_time (telapsed)), attrs);
- us_time = time_from_jiffies (u_time + s_time, clocks_per_sec);
- pcpu = timespectod (us_time) / timespectod (telapsed);
- if (pcpu > 1.0)
- pcpu = 1.0;
- attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
if (pmem > 100)
pmem = 100;
@@ -3499,6 +3487,26 @@ system_process_attributes (Lisp_Object pid)
}
unbind_to (count, Qnil);
+# ifdef CYGWIN
+ /* ttname */
+ strcpy (procfn_end, "/ctty");
+ fd = emacs_open (fn, O_RDONLY, 0);
+ if (fd < 0)
+ nread = 0;
+ else
+ {
+ record_unwind_protect_int (close_file_unwind, fd);
+ nread = emacs_read_quit (fd, procbuf, sizeof procbuf);
+ }
+ /* /proc/<pid>/ctty should always end in newline. */
+ if (0 < nread && procbuf[nread - 1] == '\n')
+ procbuf[nread - 1] = '\0';
+ else
+ procbuf[0] = '\0';
+ attrs = Fcons (Fcons (Qttname, build_string (procbuf)), attrs);
+ unbind_to (count, Qnil);
+# endif /* CYGWIN */
+
/* args */
strcpy (procfn_end, "/cmdline");
fd = emacs_open (fn, O_RDONLY, 0);
@@ -3512,7 +3520,7 @@ system_process_attributes (Lisp_Object pid)
do
{
cmdline = xpalloc (cmdline, &cmdline_size, 2, STRING_BYTES_BOUND, 1);
- set_unwind_protect_ptr (count + 1, xfree, cmdline);
+ set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
/* Leave room even if every byte needs escaping below. */
readsize = (cmdline_size >> 1) - nread;
@@ -3546,7 +3554,7 @@ system_process_attributes (Lisp_Object pid)
nread = cmdsize + 2;
cmdline_size = nread + 1;
q = cmdline = xrealloc (cmdline, cmdline_size);
- set_unwind_protect_ptr (count + 1, xfree, cmdline);
+ set_unwind_protect_ptr (specpdl_ref_add (count, 1), xfree, cmdline);
sprintf (cmdline, "[%.*s]", cmdsize, cmd);
}
/* Command line is encoded in locale-coding-system; decode it. */
@@ -3595,7 +3603,6 @@ system_process_attributes (Lisp_Object pid)
gid_t gid;
Lisp_Object attrs = Qnil;
Lisp_Object decoded_cmd;
- ptrdiff_t count;
CHECK_NUMBER (pid);
CONS_TO_INTEGER (pid, pid_t, proc_id);
@@ -3620,7 +3627,7 @@ system_process_attributes (Lisp_Object pid)
if (gr)
attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
strcpy (fn, procfn);
procfn_end = fn + strlen (fn);
strcpy (procfn_end, "/psinfo");
@@ -3708,7 +3715,6 @@ system_process_attributes (Lisp_Object pid)
char *ttyname;
size_t len;
char args[MAXPATHLEN];
- struct timespec t, now;
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID};
struct kinfo_proc proc;
@@ -3789,35 +3795,30 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qcminflt, make_fixnum (proc.ki_rusage_ch.ru_minflt)), attrs);
attrs = Fcons (Fcons (Qcmajflt, make_fixnum (proc.ki_rusage_ch.ru_majflt)), attrs);
- attrs = Fcons (Fcons (Qutime, make_lisp_timeval (proc.ki_rusage.ru_utime)),
- attrs);
- attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.ki_rusage.ru_stime)),
- attrs);
- t = timespec_add (timeval_to_timespec (proc.ki_rusage.ru_utime),
- timeval_to_timespec (proc.ki_rusage.ru_stime));
- attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
+ Lisp_Object utime = make_lisp_timeval (proc.ki_rusage.ru_utime);
+ attrs = Fcons (Fcons (Qutime, utime), attrs);
+ Lisp_Object stime = make_lisp_timeval (proc.ki_rusage.ru_stime);
+ attrs = Fcons (Fcons (Qstime, stime), attrs);
+ attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
- attrs = Fcons (Fcons (Qcutime,
- make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
- attrs);
- attrs = Fcons (Fcons (Qcstime,
- make_lisp_timeval (proc.ki_rusage_ch.ru_utime)),
- attrs);
- t = timespec_add (timeval_to_timespec (proc.ki_rusage_ch.ru_utime),
- timeval_to_timespec (proc.ki_rusage_ch.ru_stime));
- attrs = Fcons (Fcons (Qctime, make_lisp_time (t)), attrs);
+ Lisp_Object cutime = make_lisp_timeval (proc.ki_rusage_ch.ru_utime);
+ attrs = Fcons (Fcons (Qcutime, cutime), attrs);
+ Lisp_Object cstime = make_lisp_timeval (proc.ki_rusage_ch.ru_stime);
+ attrs = Fcons (Fcons (Qcstime, cstime), attrs);
+ attrs = Fcons (Fcons (Qctime, Ftime_add (cutime, cstime)), attrs);
attrs = Fcons (Fcons (Qthcount, INT_TO_INTEGER (proc.ki_numthreads)), attrs);
attrs = Fcons (Fcons (Qpri, make_fixnum (proc.ki_pri.pri_native)), attrs);
attrs = Fcons (Fcons (Qnice, make_fixnum (proc.ki_nice)), attrs);
- attrs = Fcons (Fcons (Qstart, make_lisp_timeval (proc.ki_start)), attrs);
+ Lisp_Object start = make_lisp_timeval (proc.ki_start);
+ attrs = Fcons (Fcons (Qstart, start), attrs);
attrs = Fcons (Fcons (Qvsize, make_fixnum (proc.ki_size >> 10)), attrs);
attrs = Fcons (Fcons (Qrss, make_fixnum (proc.ki_rssize * pagesize >> 10)),
attrs);
- now = current_timespec ();
- t = timespec_sub (now, timeval_to_timespec (proc.ki_start));
- attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
+ Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
+ Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
+ attrs = Fcons (Fcons (Qetime, etime), attrs);
len = sizeof fscale;
if (sysctlbyname ("kern.fscale", &fscale, &len, NULL, 0) == 0)
@@ -3868,7 +3869,7 @@ system_process_attributes (Lisp_Object pid)
Lisp_Object
system_process_attributes (Lisp_Object pid)
{
- int proc_id, nentries, fscale, i;
+ int proc_id, fscale, i;
int pagesize = getpagesize ();
int mib[6];
size_t len;
@@ -3877,7 +3878,6 @@ system_process_attributes (Lisp_Object pid)
struct kinfo_proc proc;
struct passwd *pw;
struct group *gr;
- struct timespec t;
struct uvmexp uvmexp;
Lisp_Object attrs = Qnil;
@@ -3959,20 +3959,14 @@ system_process_attributes (Lisp_Object pid)
/* FIXME: missing cminflt, cmajflt. */
- attrs = Fcons (Fcons (Qutime, make_lisp_timeval (proc.p_uutime_sec,
- proc.p_uutime_usec)),
- attrs);
- attrs = Fcons (Fcons (Qstime, make_lisp_timeval (proc.p_ustime_sec,
- proc.p_ustime_usec)),
- attrs);
- t = timespec_add (make_timespec (proc.p_uutime_sec,
- proc.p_uutime_usec * 1000),
- make_timespec (proc.p_ustime_sec,
- proc.p_ustime_usec * 1000));
- attrs = Fcons (Fcons (Qtime, make_lisp_time (t)), attrs);
-
- attrs = Fcons (Fcons (Qcutime, make_lisp_timeval (proc.p_uctime_sec,
- proc.p_uctime_usec)),
+ Lisp_Object utime = make_lisp_s_us (proc.p_uutime_sec, proc.p_uutime_usec);
+ attrs = Fcons (Fcons (Qutime, utime), attrs);
+ Lisp_Object stime = make_lisp_s_us (proc.p_ustime_sec, proc.p_ustime_usec);
+ attrs = Fcons (Fcons (Qstime, stime), attrs);
+ attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
+
+ attrs = Fcons (Fcons (Qcutime, make_lisp_s_us (proc.p_uctime_sec,
+ proc.p_uctime_usec)),
attrs);
/* FIXME: missing cstime and thus ctime. */
@@ -3982,8 +3976,8 @@ system_process_attributes (Lisp_Object pid)
/* FIXME: missing thcount (thread count) */
- attrs = Fcons (Fcons (Qstart, make_lisp_timeval (proc.p_ustart_sec,
- proc.p_ustart_usec)),
+ attrs = Fcons (Fcons (Qstart, make_lisp_s_us (proc.p_ustart_sec,
+ proc.p_ustart_usec)),
attrs);
len = (proc.p_vm_tsize + proc.p_vm_dsize + proc.p_vm_ssize) * pagesize >> 10;
@@ -3992,10 +3986,11 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qrss, make_fixnum (proc.p_vm_rssize * pagesize >> 10)),
attrs);
- t = make_timespec (proc.p_ustart_sec,
- proc.p_ustart_usec * 1000);
- t = timespec_sub (current_timespec (), t);
- attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
+ Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
+ Lisp_Object start = make_lisp_s_us (proc.p_ustart_sec,
+ proc.p_ustart_usec);
+ Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
+ attrs = Fcons (Fcons (Qetime, etime), attrs);
len = sizeof (fscale);
mib[0] = CTL_KERN;
@@ -4048,6 +4043,9 @@ system_process_attributes (Lisp_Object pid)
#elif defined DARWIN_OS
+#define HAVE_RUSAGE_INFO_CURRENT (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
+#define HAVE_PROC_PIDINFO (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
+
Lisp_Object
system_process_attributes (Lisp_Object pid)
{
@@ -4056,7 +4054,6 @@ system_process_attributes (Lisp_Object pid)
struct group *gr;
char *ttyname;
struct timeval starttime;
- struct timespec t, now;
dev_t tdev;
uid_t uid;
gid_t gid;
@@ -4151,6 +4148,7 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (proc.kp_eproc.e_tpgid)),
attrs);
+#if HAVE_RUSAGE_INFO_CURRENT
rusage_info_current ri;
if (proc_pid_rusage(proc_id, RUSAGE_INFO_CURRENT, (rusage_info_t *) &ri) == 0)
{
@@ -4164,15 +4162,33 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (ri.ri_pageins)), attrs);
}
+#else /* !HAVE_RUSAGE_INFO_CURRENT */
+ struct rusage *rusage = proc.kp_proc.p_ru;
+ if (rusage)
+ {
+ attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (rusage->ru_minflt)),
+ attrs);
+ attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (rusage->ru_majflt)),
+ attrs);
+
+ Lisp_Object utime = make_lisp_timeval (rusage->ru_utime);
+ Lisp_Object stime = make_lisp_timeval (rusage->ru_stime);
+ attrs = Fcons (Fcons (Qutime, utime), attrs);
+ attrs = Fcons (Fcons (Qstime, stime), attrs);
+ attrs = Fcons (Fcons (Qtime, Ftime_add (utime, stime)), attrs);
+ }
+#endif /* !HAVE_RUSAGE_INFO_CURRENT */
starttime = proc.kp_proc.p_starttime;
attrs = Fcons (Fcons (Qnice, make_fixnum (proc.kp_proc.p_nice)), attrs);
- attrs = Fcons (Fcons (Qstart, make_lisp_timeval (starttime)), attrs);
+ Lisp_Object start = make_lisp_timeval (starttime);
+ attrs = Fcons (Fcons (Qstart, start), attrs);
- now = current_timespec ();
- t = timespec_sub (now, timeval_to_timespec (starttime));
- attrs = Fcons (Fcons (Qetime, make_lisp_time (t)), attrs);
+ Lisp_Object now = Ftime_convert (Qnil, make_fixnum (1000000));
+ Lisp_Object etime = Ftime_convert (Ftime_subtract (now, start), Qnil);
+ attrs = Fcons (Fcons (Qetime, etime), attrs);
+#if HAVE_PROC_PIDINFO
struct proc_taskinfo taskinfo;
if (proc_pidinfo (proc_id, PROC_PIDTASKINFO, 0, &taskinfo, sizeof (taskinfo)) > 0)
{
@@ -4180,6 +4196,7 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qrss, make_fixnum (taskinfo.pti_resident_size / 1024)), attrs);
attrs = Fcons (Fcons (Qthcount, make_fixnum (taskinfo.pti_threadnum)), attrs);
}
+#endif /* HAVE_PROC_PIDINFO */
#ifdef KERN_PROCARGS2
char args[ARG_MAX];
diff --git a/src/syssignal.h b/src/syssignal.h
index 07055c04be6..02fe44a3820 100644
--- a/src/syssignal.h
+++ b/src/syssignal.h
@@ -22,6 +22,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <signal.h>
+#include <attribute.h>
+
extern void init_signals (void);
extern void block_child_signal (sigset_t *);
extern void unblock_child_signal (sigset_t const *);
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 5bcfe7d8a58..efedc3e450b 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -24,9 +24,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
-#include "unlocked-io.h"
-extern FILE *emacs_fopen (char const *, char const *) ATTRIBUTE_MALLOC;
+#include <attribute.h>
+#include <unlocked-io.h>
+
+extern FILE *emacs_fopen (char const *, char const *)
+ ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC (fclose, 1);
extern void errputc (int);
extern void errwrite (void const *, ptrdiff_t);
extern void close_output_streams (void);
diff --git a/src/systhread.h b/src/systhread.h
index fb1a0a72d64..bf4e0306cdc 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -21,6 +21,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <stdbool.h>
+#include <attribute.h>
+
#ifdef THREADS_ENABLED
#ifdef HAVE_PTHREAD
diff --git a/src/systime.h b/src/systime.h
index f3b1b2394da..085a7ddeaba 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -26,6 +26,9 @@ INLINE_HEADER_BEGIN
#ifdef HAVE_X_WINDOWS
# include <X11/X.h>
+#elif defined HAVE_HAIKU
+# include <support/SupportDefs.h>
+typedef int64 Time;
#else
typedef unsigned long Time;
#endif
@@ -91,7 +94,7 @@ extern Lisp_Object timespec_to_lisp (struct timespec);
extern bool list4_to_timespec (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, struct timespec *);
extern struct timespec lisp_time_argument (Lisp_Object);
-extern AVOID time_overflow (void);
+extern double float_time (Lisp_Object);
extern void init_timefns (void);
extern void syms_of_timefns (void);
diff --git a/src/term.c b/src/term.c
index 4c7a90a5773..3bea621dbda 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1632,9 +1632,13 @@ produce_glyphs (struct it *it)
}
else
{
- Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
+ struct terminal *t = FRAME_TERMINAL (it->f);
+ Lisp_Object charset_list = t->charset_list, char_glyph;
- if (char_charset (it->char_to_display, charset_list, NULL))
+ if (char_charset (it->char_to_display, charset_list, NULL)
+ && (char_glyph = terminal_glyph_code (t, it->char_to_display),
+ NILP (char_glyph)
+ || (FIXNUMP (char_glyph) && XFIXNUM (char_glyph) >= 0)))
{
it->pixel_width = CHARACTER_WIDTH (it->char_to_display);
it->nglyphs = it->pixel_width;
@@ -2283,9 +2287,9 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
delete_keyboard_wait_descriptor (fileno (f));
#ifndef MSDOS
- fclose (f);
if (f != t->display_info.tty->output)
fclose (t->display_info.tty->output);
+ fclose (f);
#endif
t->display_info.tty->input = 0;
@@ -3500,7 +3504,7 @@ tty_menu_show (struct frame *f, int x, int y, int menuflags,
int dispwidth, dispheight;
int i, j, lines, maxlines;
int maxwidth;
- ptrdiff_t specpdl_count;
+ specpdl_ref specpdl_count;
eassert (FRAME_TERMCAP_P (f));
diff --git a/src/termhooks.h b/src/termhooks.h
index 518e855eae1..c5f1e286e92 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -31,7 +31,8 @@ struct glyph;
INLINE_HEADER_BEGIN
-enum scroll_bar_part {
+enum scroll_bar_part
+{
scroll_bar_nowhere,
scroll_bar_above_handle,
scroll_bar_handle,
@@ -80,10 +81,29 @@ enum event_kind
which the key was typed.
.timestamp gives a timestamp (in
milliseconds) for the keystroke. */
- MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is in .code,
- perhaps with modifiers applied.
- The others are the same as
- ASCII_KEYSTROKE_EVENT. */
+ MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is
+ in .code, perhaps with
+ modifiers applied. The
+ others are the same as
+ ASCII_KEYSTROKE_EVENT,
+ except when ARG is a
+ string, which will be
+ decoded and the decoded
+ string's characters will be
+ used as .code
+ individually.
+
+ The string can have a
+ property `coding', which
+ should be a symbol
+ describing a coding system
+ to use to decode the string.
+
+ If it is nil, then the
+ locale coding system will
+ be used. If it is t, then
+ no decoding will take
+ place. */
NON_ASCII_KEYSTROKE_EVENT, /* .code is a number identifying the
function key. A code N represents
a key whose name is
@@ -258,8 +278,9 @@ enum event_kind
#endif
#ifdef HAVE_XWIDGETS
- /* events generated by xwidgets*/
+ /* An event generated by an xwidget to tell us something. */
, XWIDGET_EVENT
+
/* Event generated when WebKit asks us to display another widget. */
, XWIDGET_DISPLAY_EVENT
#endif
@@ -306,6 +327,11 @@ enum event_kind
positive delta represents a change clockwise, and a negative
delta represents a change counter-clockwise. */
, PINCH_EVENT
+
+ /* In a MONITORS_CHANGED_EVENT, .arg gives the terminal on which the
+ monitor configuration changed. .timestamp gives the time on
+ which the monitors changed. */
+ , MONITORS_CHANGED_EVENT
};
/* Bit width of an enum event_kind tag at the start of structs and unions. */
@@ -354,9 +380,17 @@ struct input_event
when building events. Unfortunately some events have to pass much
more data than it's reasonable to pack directly into this structure. */
Lisp_Object arg;
+
+ /* The name of the device from which this event originated.
+
+ It can either be a string, or Qt, which means to use the name
+ "Virtual core pointer" for all events other than keystroke
+ events, and "Virtual core keyboard" for those. */
+ Lisp_Object device;
};
-#define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
+#define EVENT_INIT(event) (memset (&(event), 0, sizeof (struct input_event)), \
+ (event).device = Qt)
/* Bits in the modifiers member of the input_event structure.
Note that reorder_modifiers assumes that the bits are in canonical
@@ -812,6 +846,20 @@ struct terminal
frames on the terminal when it calls this hook, so infinite
recursion is prevented. */
void (*delete_terminal_hook) (struct terminal *);
+
+ /* Called to determine whether a position is on the toolkit tool bar
+ or menu bar. May be NULL. It should accept five arguments
+ FRAME, X, Y, MENU_BAR_P, TOOL_BAR_P, and store true into
+ MENU_BAR_P if X and Y are in FRAME's toolkit menu bar, and true
+ into TOOL_BAR_P if X and Y are in FRAME's toolkit tool bar. */
+ void (*toolkit_position_hook) (struct frame *, int, int, bool *, bool *);
+
+#ifdef HAVE_WINDOW_SYSTEM
+ /* Called to determine if the mouse is grabbed on the given display.
+ If either dpyinfo->grabbed or this returns true, then the display
+ will be considered as grabbed. */
+ bool (*any_grab_hook) (Display_Info *);
+#endif
} GCALIGNED_STRUCT;
INLINE bool
diff --git a/src/terminal.c b/src/terminal.c
index 3db80f4b1ff..dcde8e9f557 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -290,13 +290,13 @@ create_terminal (enum output_method type, struct redisplay_interface *rif)
keyboard_coding =
find_symbol_value (intern ("default-keyboard-coding-system"));
if (NILP (keyboard_coding)
- || EQ (keyboard_coding, Qunbound)
+ || BASE_EQ (keyboard_coding, Qunbound)
|| NILP (Fcoding_system_p (keyboard_coding)))
keyboard_coding = Qno_conversion;
terminal_coding =
find_symbol_value (intern ("default-terminal-coding-system"));
if (NILP (terminal_coding)
- || EQ (terminal_coding, Qunbound)
+ || BASE_EQ (terminal_coding, Qunbound)
|| NILP (Fcoding_system_p (terminal_coding)))
terminal_coding = Qundecided;
@@ -622,6 +622,8 @@ init_initial_terminal (void)
emacs_abort ();
initial_terminal = create_terminal (output_initial, NULL);
+ /* Note: menu-bar.el:menu-bar-update-buffers knows about this
+ special name of the initial terminal. */
initial_terminal->name = xstrdup ("initial_terminal");
initial_terminal->kboard = initial_kboard;
initial_terminal->delete_terminal_hook = &delete_initial_terminal;
diff --git a/src/textprop.c b/src/textprop.c
index 2d1e34d5867..96d07b44be8 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -341,7 +341,7 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object)
for (sym = properties;
PLIST_ELT_P (sym, value);
sym = XCDR (value))
- if (EQ (property_value (interval->plist, XCAR (sym)), Qunbound))
+ if (BASE_EQ (property_value (interval->plist, XCAR (sym)), Qunbound))
{
record_property_change (interval->position, LENGTH (interval),
XCAR (sym), Qnil,
@@ -561,8 +561,13 @@ DEFUN ("text-properties-at", Ftext_properties_at,
doc: /* Return the list of properties of the character at POSITION in OBJECT.
If the optional second argument OBJECT is a buffer (or nil, which means
the current buffer), POSITION is a buffer position (integer or marker).
+
If OBJECT is a string, POSITION is a 0-based index into it.
-If POSITION is at the end of OBJECT, the value is nil.
+
+If POSITION is at the end of OBJECT, the value is nil, but note that
+buffer narrowing does not affect the value. That is, if OBJECT is a
+buffer or nil, and the buffer is narrowed and POSITION is at the end
+of the narrowed buffer, the result may be non-nil.
If you want to display the text properties at point in a human-readable
form, use the `describe-text-properties' command. */)
@@ -590,7 +595,11 @@ DEFUN ("get-text-property", Fget_text_property, Sget_text_property, 2, 3, 0,
doc: /* Return the value of POSITION's property PROP, in OBJECT.
OBJECT should be a buffer or a string; if omitted or nil, it defaults
to the current buffer.
-If POSITION is at the end of OBJECT, the value is nil. */)
+
+If POSITION is at the end of OBJECT, the value is nil, but note that
+buffer narrowing does not affect the value. That is, if the buffer is
+narrowed and POSITION is at the end of the narrowed buffer, the result
+may be non-nil. */)
(Lisp_Object position, Lisp_Object prop, Lisp_Object object)
{
return textget (Ftext_properties_at (position, object), prop);
@@ -792,7 +801,7 @@ The property values are compared with `eq'. */)
else
{
Lisp_Object initial_value, value;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (! NILP (object))
CHECK_BUFFER (object);
@@ -879,7 +888,7 @@ first valid position in OBJECT. */)
}
else
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (! NILP (object))
CHECK_BUFFER (object);
@@ -1164,7 +1173,7 @@ add_text_properties_1 (Lisp_Object start, Lisp_Object end,
buffers is slow and often unnecessary. */
if (BUFFERP (object) && XBUFFER (object) != current_buffer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
set_buffer_internal (XBUFFER (object));
return unbind_to (count, add_text_properties_1 (start, end, properties,
@@ -1379,7 +1388,7 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties,
buffers is slow and often unnecessary. */
if (BUFFERP (object) && XBUFFER (object) != current_buffer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
set_buffer_internal (XBUFFER (object));
return unbind_to (count,
@@ -1398,8 +1407,8 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties,
/* If we want no properties for a whole string,
get rid of its intervals. */
if (NILP (properties) && STRINGP (object)
- && EQ (start, make_fixnum (0))
- && EQ (end, make_fixnum (SCHARS (object))))
+ && BASE_EQ (start, make_fixnum (0))
+ && BASE_EQ (end, make_fixnum (SCHARS (object))))
{
if (!string_intervals (object))
return Qnil;
@@ -1462,7 +1471,7 @@ set_text_properties_1 (Lisp_Object start, Lisp_Object end,
buffers is slow and often unnecessary. */
if (BUFFERP (object) && XBUFFER (object) != current_buffer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
set_buffer_internal (XBUFFER (object));
@@ -1558,7 +1567,7 @@ Use `set-text-properties' if you want to remove all text properties. */)
buffers is slow and often unnecessary. */
if (BUFFERP (object) && XBUFFER (object) != current_buffer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
set_buffer_internal (XBUFFER (object));
return unbind_to (count,
@@ -1683,7 +1692,7 @@ Return t if any property was actually removed, nil otherwise. */)
buffers is slow and often unnecessary. */
if (BUFFERP (object) && XBUFFER (object) != current_buffer)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
set_buffer_internal (XBUFFER (object));
return unbind_to (count,
@@ -2240,7 +2249,7 @@ verify_interval_modification (struct buffer *buf,
tem = textget (i->plist, Qfront_sticky);
if (TMEM (Qread_only, tem)
- || (NILP (Fplist_get (i->plist, Qread_only))
+ || (NILP (plist_get (i->plist, Qread_only))
&& TMEM (Qcategory, tem)))
text_read_only (after);
}
@@ -2260,7 +2269,7 @@ verify_interval_modification (struct buffer *buf,
tem = textget (prev->plist, Qrear_nonsticky);
if (! TMEM (Qread_only, tem)
- && (! NILP (Fplist_get (prev->plist,Qread_only))
+ && (! NILP (plist_get (prev->plist,Qread_only))
|| ! TMEM (Qcategory, tem)))
text_read_only (before);
}
@@ -2279,13 +2288,13 @@ verify_interval_modification (struct buffer *buf,
tem = textget (i->plist, Qfront_sticky);
if (TMEM (Qread_only, tem)
- || (NILP (Fplist_get (i->plist, Qread_only))
+ || (NILP (plist_get (i->plist, Qread_only))
&& TMEM (Qcategory, tem)))
text_read_only (after);
tem = textget (prev->plist, Qrear_nonsticky);
if (! TMEM (Qread_only, tem)
- && (! NILP (Fplist_get (prev->plist, Qread_only))
+ && (! NILP (plist_get (prev->plist, Qread_only))
|| ! TMEM (Qcategory, tem)))
text_read_only (after);
}
diff --git a/src/thread.c b/src/thread.c
index bfcac91982d..626d14aad0a 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -83,6 +83,22 @@ release_global_lock (void)
sys_mutex_unlock (&global_lock);
}
+static void
+rebind_for_thread_switch (void)
+{
+ ptrdiff_t distance
+ = current_thread->m_specpdl_ptr - current_thread->m_specpdl;
+ specpdl_unrewind (specpdl_ptr, -distance, true);
+}
+
+static void
+unbind_for_thread_switch (struct thread_state *thr)
+{
+ ptrdiff_t distance = thr->m_specpdl_ptr - thr->m_specpdl;
+ specpdl_unrewind (thr->m_specpdl_ptr, distance, true);
+}
+
+
/* You must call this after acquiring the global lock.
acquire_global_lock does it for you. */
static void
@@ -329,7 +345,7 @@ Note that calls to `mutex-lock' and `mutex-unlock' must be paired. */)
(Lisp_Object mutex)
{
struct Lisp_Mutex *lmutex;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
CHECK_MUTEX (mutex);
lmutex = XMUTEX (mutex);
@@ -639,7 +655,7 @@ mark_one_thread (struct thread_state *thread)
mark_specpdl (thread->m_specpdl, thread->m_specpdl_ptr);
- mark_stack (thread->m_stack_bottom, stack_top);
+ mark_c_stack (thread->m_stack_bottom, stack_top);
for (struct handler *handler = thread->m_handlerlist;
handler; handler = handler->next)
@@ -655,6 +671,8 @@ mark_one_thread (struct thread_state *thread)
mark_object (tem);
}
+ mark_bytecode (&thread->bc);
+
/* No need to mark Lisp_Object members like m_last_thing_searched,
as mark_threads_callback does that by calling mark_object. */
}
@@ -709,7 +727,7 @@ DEFUN ("thread-yield", Fthread_yield, Sthread_yield, 0, 0, 0,
static Lisp_Object
invoke_thread_function (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
current_thread->result = Ffuncall (1, &current_thread->function);
return unbind_to (count, Qnil);
@@ -774,7 +792,7 @@ run_thread (void *state)
xfree (self->m_specpdl - 1);
self->m_specpdl = NULL;
self->m_specpdl_ptr = NULL;
- self->m_specpdl_size = 0;
+ self->m_specpdl_end = NULL;
{
struct handler *c, *c_next;
@@ -823,6 +841,7 @@ finalize_one_thread (struct thread_state *state)
free_search_regs (&state->m_search_regs);
free_search_regs (&state->m_saved_search_regs);
sys_cond_destroy (&state->thread_condvar);
+ free_bc_thread (&state->bc);
}
DEFUN ("make-thread", Fmake_thread, Smake_thread, 1, 2, 0,
@@ -846,13 +865,14 @@ If NAME is given, it must be a string; it names the new thread. */)
/* Perhaps copy m_last_thing_searched from parent? */
new_thread->m_current_buffer = current_thread->m_current_buffer;
- new_thread->m_specpdl_size = 50;
- new_thread->m_specpdl = xmalloc ((1 + new_thread->m_specpdl_size)
- * sizeof (union specbinding));
- /* Skip the dummy entry. */
- ++new_thread->m_specpdl;
+ ptrdiff_t size = 50;
+ union specbinding *pdlvec = xmalloc ((1 + size) * sizeof (union specbinding));
+ new_thread->m_specpdl = pdlvec + 1; /* Skip the dummy entry. */
+ new_thread->m_specpdl_end = new_thread->m_specpdl + size;
new_thread->m_specpdl_ptr = new_thread->m_specpdl;
+ init_bc_thread (&new_thread->bc);
+
sys_cond_init (&new_thread->thread_condvar);
/* We'll need locking here eventually. */
@@ -1112,6 +1132,7 @@ init_threads (void)
sys_mutex_lock (&global_lock);
current_thread = &main_thread.s;
main_thread.s.thread_id = sys_thread_self ();
+ init_bc_thread (&main_thread.s.bc);
}
void
diff --git a/src/thread.h b/src/thread.h
index 1e7eb86f6ee..82c445ba7e7 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -33,6 +33,17 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "sysselect.h" /* FIXME */
#include "systhread.h"
+INLINE_HEADER_BEGIN
+
+/* Byte-code interpreter thread state. */
+struct bc_thread_state {
+ struct bc_frame *fp; /* current frame pointer */
+
+ /* start and end of allocated bytecode stack */
+ char *stack;
+ char *stack_end;
+};
+
struct thread_state
{
union vectorlike_header header;
@@ -92,14 +103,14 @@ struct thread_state
struct handler *m_handlerlist_sentinel;
#define handlerlist_sentinel (current_thread->m_handlerlist_sentinel)
- /* Current number of specbindings allocated in specpdl. */
- ptrdiff_t m_specpdl_size;
-#define specpdl_size (current_thread->m_specpdl_size)
-
/* Pointer to beginning of specpdl. */
union specbinding *m_specpdl;
#define specpdl (current_thread->m_specpdl)
+ /* End of specpld (just beyond the last element). */
+ union specbinding *m_specpdl_end;
+#define specpdl_end (current_thread->m_specpdl_end)
+
/* Pointer to first unused element in specpdl. */
union specbinding *m_specpdl_ptr;
#define specpdl_ptr (current_thread->m_specpdl_ptr)
@@ -181,6 +192,8 @@ struct thread_state
/* Threads are kept on a linked list. */
struct thread_state *next_thread;
+
+ struct bc_thread_state bc;
} GCALIGNED_STRUCT;
INLINE bool
@@ -304,4 +317,6 @@ int thread_select (select_func *func, int max_fds, fd_set *rfds,
bool thread_check_current_buffer (struct buffer *);
+INLINE_HEADER_END
+
#endif /* THREAD_H */
diff --git a/src/timefns.c b/src/timefns.c
index f73c69149f7..9df50eaecc3 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -69,10 +69,9 @@ enum { TM_YEAR_BASE = 1900 };
# define FASTER_TIMEFNS 1
#endif
-/* Although current-time etc. generate list-format timestamps
- (HI LO US PS), the plan is to change these functions to generate
- frequency-based timestamps (TICKS . HZ) in a future release.
- To try this now, compile with -DCURRENT_TIME_LIST=0. */
+/* current-time-list defaults to t, typically generating (HI LO US PS)
+ timestamps. To change the default to nil, generating (TICKS . HZ)
+ timestamps, compile with -DCURRENT_TIME_LIST=0. */
#ifndef CURRENT_TIME_LIST
enum { CURRENT_TIME_LIST = true };
#endif
@@ -213,7 +212,7 @@ tzlookup (Lisp_Object zone, bool settz)
if (NILP (zone))
return local_tz;
- else if (EQ (zone, Qt) || EQ (zone, make_fixnum (0)))
+ else if (BASE_EQ (zone, make_fixnum (0)) || BASE2_EQ (zone, Qt))
{
zone_string = "UTC0";
new_tz = utc_tz;
@@ -222,7 +221,7 @@ tzlookup (Lisp_Object zone, bool settz)
{
bool plain_integer = FIXNUMP (zone);
- if (EQ (zone, Qwall))
+ if (BASE2_EQ (zone, Qwall))
zone_string = 0;
else if (STRINGP (zone))
zone_string = SSDATA (ENCODE_SYSTEM (zone));
@@ -342,7 +341,7 @@ init_timefns (void)
}
/* Report that a time value is out of range for Emacs. */
-void
+static AVOID
time_overflow (void)
{
error ("Specified time is not representable");
@@ -517,7 +516,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
/* The idea is to return the floor of ((T.ticks * HZ) / T.hz). */
/* For speed, just return T.ticks if T.hz == HZ. */
- if (FASTER_TIMEFNS && EQ (t.hz, hz))
+ if (FASTER_TIMEFNS && BASE_EQ (t.hz, hz))
return t.ticks;
/* Check HZ for validity. */
@@ -569,7 +568,7 @@ lisp_time_seconds (struct lisp_time t)
Lisp_Object
make_lisp_time (struct timespec t)
{
- if (CURRENT_TIME_LIST)
+ if (current_time_list)
{
time_t s = t.tv_sec;
int ns = t.tv_nsec;
@@ -730,7 +729,7 @@ decode_time_components (enum timeform form,
case TIMEFORM_TICKS_HZ:
if (INTEGERP (high)
- && (!NILP (Fnatnump (low)) && !EQ (low, make_fixnum (0))))
+ && !NILP (Fnatnump (low)) && !BASE_EQ (low, make_fixnum (0)))
return decode_ticks_hz (high, low, result, dresult);
return EINVAL;
@@ -879,6 +878,16 @@ decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
return form;
}
+/* Convert a Lisp timestamp SPECIFIED_TIME to double.
+ Signal an error if unsuccessful. */
+double
+float_time (Lisp_Object specified_time)
+{
+ double t;
+ decode_lisp_time (specified_time, false, 0, &t);
+ return t;
+}
+
/* Convert Z to time_t, returning true if it fits. */
static bool
mpz_time (mpz_t const z, time_t *t)
@@ -914,7 +923,7 @@ lisp_to_timespec (struct lisp_time t)
yielding quotient Q (tv_sec) and remainder NS (tv_nsec).
Return an invalid timespec if Q does not fit in time_t.
For speed, prefer fixnum arithmetic if it works. */
- if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz))
+ if (FASTER_TIMEFNS && BASE_EQ (t.hz, timespec_hz))
{
if (FIXNUMP (t.ticks))
{
@@ -933,7 +942,7 @@ lisp_to_timespec (struct lisp_time t)
else
ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ);
}
- else if (FASTER_TIMEFNS && EQ (t.hz, make_fixnum (1)))
+ else if (FASTER_TIMEFNS && BASE_EQ (t.hz, make_fixnum (1)))
{
ns = 0;
if (FIXNUMP (t.ticks))
@@ -1034,7 +1043,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
if (FASTER_TIMEFNS && FIXNUMP (b))
{
- if (EQ (b, make_fixnum (0)))
+ if (BASE_EQ (b, make_fixnum (0)))
return a;
/* For speed, use EMACS_INT arithmetic if it will do. */
@@ -1068,7 +1077,7 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
if (FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
{
double da = XFLOAT_DATA (a);
- double db = XFLOAT_DATA (Ffloat_time (b));
+ double db = float_time (b);
return make_float (subtract ? da - db : da + db);
}
enum timeform aform, bform;
@@ -1081,14 +1090,14 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
quicker while we're at it. Compare here rather than earlier, to
handle NaNs and check formats. */
struct lisp_time tb;
- if (EQ (a, b))
+ if (BASE_EQ (a, b))
bform = aform, tb = ta;
else
tb = lisp_time_struct (b, &bform);
Lisp_Object ticks, hz;
- if (FASTER_TIMEFNS && EQ (ta.hz, tb.hz))
+ if (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz))
{
hz = ta.hz;
ticks = lispint_arith (ta.ticks, tb.ticks, subtract);
@@ -1162,13 +1171,13 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
}
/* Return an integer if the timestamp resolution is 1,
- otherwise the (TICKS . HZ) form if !CURRENT_TIME_LIST or if
+ otherwise the (TICKS . HZ) form if !current_time_list or if
either input used (TICKS . HZ) form or the result can't be expressed
exactly in (HI LO US PS) form, otherwise the (HI LO US PS) form
for backward compatibility. */
- return (EQ (hz, make_fixnum (1))
+ return (BASE_EQ (hz, make_fixnum (1))
? ticks
- : (!CURRENT_TIME_LIST
+ : (!current_time_list
|| aform == TIMEFORM_TICKS_HZ
|| bform == TIMEFORM_TICKS_HZ
|| !trillion_factor (hz))
@@ -1209,20 +1218,20 @@ time_cmp (Lisp_Object a, Lisp_Object b)
return da < db ? -1 : da != db;
}
- struct lisp_time ta = lisp_time_struct (a, 0);
-
/* Compare nil to nil correctly, and handle other eq values quicker
while we're at it. Compare here rather than earlier, to handle
- NaNs and check formats. */
- if (EQ (a, b))
+ NaNs. This means (time-equal-p X X) does not signal an error if
+ X is not a valid time value, but that's OK. */
+ if (BASE_EQ (a, b))
return 0;
/* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
ATICKS * BHZ to BTICKS * AHZ. */
+ struct lisp_time ta = lisp_time_struct (a, 0);
struct lisp_time tb = lisp_time_struct (b, 0);
mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
- if (! (FASTER_TIMEFNS && EQ (ta.hz, tb.hz)))
+ if (! (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz)))
{
/* This could be sped up by looking at the signs, sizes, and
number of bits of the two sides; see how GMP does mpq_cmp.
@@ -1264,9 +1273,7 @@ If precise time stamps are required, use either `encode-time',
or (if you need time as a string) `format-time-string'. */)
(Lisp_Object specified_time)
{
- double t;
- decode_lisp_time (specified_time, false, 0, &t);
- return make_float (t);
+ return make_float (float_time (specified_time));
}
/* Write information into buffer S of size MAXSIZE, according to the
@@ -1456,7 +1463,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME ZONE) */)
}
DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 3, 0,
- doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF).
+ doc: /* Decode a timestamp into (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF).
The optional TIME is the time value to convert. See
`format-time-string' for the various forms of a time value.
@@ -1528,7 +1535,7 @@ usage: (decode-time &optional TIME ZONE FORM) */)
/* Compute SEC from LOCAL_TM.tm_sec and HZ. */
Lisp_Object hz = lt.hz, sec;
- if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
+ if (BASE_EQ (hz, make_fixnum (1)) || !BASE2_EQ (form, Qt))
sec = make_fixnum (local_tm.tm_sec);
else
{
@@ -1601,27 +1608,32 @@ check_tm_member (Lisp_Object obj, int offset)
DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0,
doc: /* Convert TIME to a timestamp.
-TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE).
+TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE)
in the style of `decode-time', so that (encode-time (decode-time ...)) works.
In this list, ZONE can be nil for Emacs local time, t for Universal
Time, `wall' for system wall clock time, or a string as in the TZ
-environment variable. It can also be a list (as from
+environment variable. ZONE can also be a list (as from
`current-time-zone') or an integer (as from `decode-time') applied
without consideration for daylight saving time. If ZONE specifies a
time zone with daylight-saving transitions, DST is t for daylight
saving time, nil for standard time, and -1 to cause the daylight
saving flag to be guessed.
+TIME can also be a list (SECOND MINUTE HOUR DAY MONTH YEAR), which is
+equivalent to (SECOND MINUTE HOUR DAY MONTH YEAR nil -1 nil).
+
As an obsolescent calling convention, if this function is called with
6 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR,
DAY, MONTH, and YEAR, and specify the components of a decoded time.
If there are more than 6 arguments the *last* argument is used as ZONE
and any other extra arguments are ignored, so that (apply
#\\='encode-time (decode-time ...)) works. In this obsolescent
-convention, DST and ZONE default to -1 and nil respectively.
+convention, DST is -1 and ZONE defaults to nil.
-Years before 1970 are not guaranteed to work. On some systems,
-year values as low as 1901 do work.
+The range of supported years is at least 1970 to the near future.
+Out-of-range values for SECOND through MONTH are brought into range
+via date arithmetic. This can be tricky especially when combined with
+DST; see Info node `(elisp)Time Conversion' for details and caveats.
usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
@@ -1635,7 +1647,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
if (nargs == 1)
{
Lisp_Object tail = a;
- for (int i = 0; i < 9; i++, tail = XCDR (tail))
+ for (int i = 0; i < 6; i++, tail = XCDR (tail))
CHECK_CONS (tail);
secarg = XCAR (a); a = XCDR (a);
minarg = XCAR (a); a = XCDR (a);
@@ -1643,11 +1655,17 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
mdayarg = XCAR (a); a = XCDR (a);
monarg = XCAR (a); a = XCDR (a);
yeararg = XCAR (a); a = XCDR (a);
- a = XCDR (a);
- Lisp_Object dstflag = XCAR (a); a = XCDR (a);
- zone = XCAR (a);
- if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone))
- tm.tm_isdst = !NILP (dstflag);
+ if (! NILP (a))
+ {
+ CHECK_CONS (a);
+ a = XCDR (a);
+ CHECK_CONS (a);
+ Lisp_Object dstflag = XCAR (a); a = XCDR (a);
+ CHECK_CONS (a);
+ zone = XCAR (a);
+ if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone))
+ tm.tm_isdst = !NILP (dstflag);
+ }
}
else if (nargs < 6)
xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs));
@@ -1667,7 +1685,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
struct lisp_time lt;
decode_lisp_time (secarg, false, &lt, 0);
Lisp_Object hz = lt.hz, sec, subsecticks;
- if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1)))
+ if (FASTER_TIMEFNS && BASE_EQ (hz, make_fixnum (1)))
{
sec = lt.ticks;
subsecticks = make_fixnum (0);
@@ -1697,8 +1715,8 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
if (tm.tm_wday < 0)
time_error (mktime_errno);
- if (EQ (hz, make_fixnum (1)))
- return (CURRENT_TIME_LIST
+ if (BASE_EQ (hz, make_fixnum (1)))
+ return (current_time_list
? list2 (hi_time (value), lo_time (value))
: INT_TO_INTEGER (value));
else
@@ -1729,35 +1747,49 @@ bits, and USEC and PSEC are the microsecond and picosecond counts. */)
struct lisp_time t;
enum timeform input_form = decode_lisp_time (time, false, &t, 0);
if (NILP (form))
- form = CURRENT_TIME_LIST ? Qlist : Qt;
- if (EQ (form, Qlist))
+ form = current_time_list ? Qlist : Qt;
+ if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (form))
+ form = SYMBOL_WITH_POS_SYM (form);
+ if (BASE_EQ (form, Qlist))
return ticks_hz_list4 (t.ticks, t.hz);
- if (EQ (form, Qinteger))
+ if (BASE_EQ (form, Qinteger))
return FASTER_TIMEFNS && INTEGERP (time) ? time : lisp_time_seconds (t);
- if (EQ (form, Qt))
+ if (BASE_EQ (form, Qt))
form = t.hz;
if (FASTER_TIMEFNS
- && input_form == TIMEFORM_TICKS_HZ && EQ (form, XCDR (time)))
+ && input_form == TIMEFORM_TICKS_HZ && BASE_EQ (form, XCDR (time)))
return time;
return Fcons (lisp_time_hz_ticks (t, form), form);
}
DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
doc: /* Return the current time, as the number of seconds since 1970-01-01 00:00:00.
-The time is returned as a list of integers (HIGH LOW USEC PSEC).
-HIGH has the most significant bits of the seconds, while LOW has the
-least significant 16 bits. USEC and PSEC are the microsecond and
-picosecond counts.
-
-In a future Emacs version, the format of the returned timestamp is
-planned to change. Use `time-convert' if you need a particular
-timestamp form; for example, (time-convert nil \\='integer) returns
-the current time in seconds. */)
+If the variable `current-time-list' is nil, the time is returned as a
+pair of integers (TICKS . HZ), where TICKS counts clock ticks and HZ
+is the clock ticks per second. Otherwise, the time is returned as a
+list of integers (HIGH LOW USEC PSEC) where HIGH has the most
+significant bits of the seconds, LOW has the least significant 16
+bits, and USEC and PSEC are the microsecond and picosecond counts.
+
+You can use `time-convert' to get a particular timestamp form
+regardless of the value of `current-time-list'. */)
(void)
{
return make_lisp_time (current_timespec ());
}
+#ifdef CLOCKS_PER_SEC
+DEFUN ("current-cpu-time", Fcurrent_cpu_time, Scurrent_cpu_time, 0, 0, 0,
+ doc: /* Return the current CPU time along with its resolution.
+The return value is a pair (CPU-TICKS . TICKS-PER-SEC).
+The CPU-TICKS counter can wrap around, so values cannot be meaningfully
+compared if too much time has passed between them. */)
+ (void)
+{
+ return Fcons (make_int (clock ()), make_int (CLOCKS_PER_SEC));
+}
+#endif
+
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string,
0, 2, 0,
doc: /* Return the current local time, as a human-readable string.
@@ -1996,7 +2028,23 @@ syms_of_timefns (void)
DEFSYM (Qencode_time, "encode-time");
+ DEFVAR_BOOL ("current-time-list", current_time_list,
+ doc: /* Whether `current-time' should return list or (TICKS . HZ) form.
+
+This boolean variable is a transition aid. If t, `current-time' and
+related functions return timestamps in list form, typically
+\(HIGH LOW USEC PSEC); otherwise, they use (TICKS . HZ) form.
+Currently this variable defaults to t, for behavior compatible with
+previous Emacs versions. Developers are encouraged to test
+timestamp-related code with this variable set to nil, as it will
+default to nil in a future Emacs version, and will be removed in some
+version after that. */);
+ current_time_list = CURRENT_TIME_LIST;
+
defsubr (&Scurrent_time);
+#ifdef CLOCKS_PER_SEC
+ defsubr (&Scurrent_cpu_time);
+#endif
defsubr (&Stime_convert);
defsubr (&Stime_add);
defsubr (&Stime_subtract);
diff --git a/src/tparam.h b/src/tparam.h
index 6361f138eaa..4f4bdc8820f 100644
--- a/src/tparam.h
+++ b/src/tparam.h
@@ -20,6 +20,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef EMACS_TPARAM_H
#define EMACS_TPARAM_H
+#include <stdlib.h>
+
+#include <attribute.h>
+
/* Don't try to include termcap.h. On some systems, configure finds a
non-standard termcap.h that the main build won't find. */
@@ -30,7 +34,8 @@ int tgetnum (const char *);
char *tgetstr (const char *, char **);
char *tgoto (const char *, int, int);
-char *tparam (const char *, char *, int, int, int, int, int) ATTRIBUTE_MALLOC;
+char *tparam (const char *, char *, int, int, int, int, int)
+ ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
extern char PC;
extern char *BC;
diff --git a/src/undo.c b/src/undo.c
index 5d705945c4c..f76977dbe50 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -218,7 +218,7 @@ record_first_change (void)
base_buffer = base_buffer->base_buffer;
bset_undo_list (current_buffer,
- Fcons (Fcons (Qt, Fvisited_file_modtime ()),
+ Fcons (Fcons (Qt, buffer_visited_file_modtime (base_buffer)),
BVAR (current_buffer, undo_list)));
}
@@ -295,7 +295,7 @@ truncate_undo_list (struct buffer *b)
/* Make sure that calling undo-outer-limit-function
won't cause another GC. */
- ptrdiff_t count = inhibit_garbage_collection ();
+ specpdl_ref count = inhibit_garbage_collection ();
/* Make the buffer current to get its local values of variables such
as undo_limit. Also so that Vundo_outer_limit_function can
diff --git a/src/verbose.mk.in b/src/verbose.mk.in
index e3f56783031..4ec7788442d 100644
--- a/src/verbose.mk.in
+++ b/src/verbose.mk.in
@@ -33,24 +33,45 @@ AM_V_GLOBALS =
AM_V_NO_PD =
AM_V_RC =
else
+
+# Whether $(info ...) works. This is to work around a bug in GNU Make
+# 4.3 and earlier, which implements $(info MSG) via two system calls
+# { write (..., "MSG", 3); write (..., "\n", 1); }
+# which looks bad when make -j interleaves two of these at about the same time.
+#
+# Later versions of GNU Make have the 'notintermediate' feature,
+# so assume that $(info ...) works if this feature is present.
+#
+have_working_info = $(filter notintermediate,$(value .FEATURES))
+#
+# The workaround is to use the shell and 'echo' rather than $(info ...).
+# The workaround is done only for AM_V_ELC and AM_V_ELN,
+# since the bug is not annoying elsewhere.
+
AM_V_AR = @$(info $ AR $@)
AM_V_at = @
AM_V_CC = @$(info $ CC $@)
AM_V_CXX = @$(info $ CXX $@)
AM_V_CCLD = @$(info $ CCLD $@)
AM_V_CXXLD = @$(info $ CXXLD $@)
-ifeq ($(HAVE_NATIVE_COMP),yes)
-ifeq ($(NATIVE_DISABLED),1)
-AM_V_ELC = @$(info $ ELC $@)
-AM_V_ELN =
-else
+
+ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--)
+ifneq (,$(have_working_info))
AM_V_ELC = @$(info $ ELC+ELN $@)
AM_V_ELN = @$(info $ ELN $@)
+else
+AM_V_ELC = @echo " ELC+ELN " $@;
+AM_V_ELN = @echo " ELN " $@;
endif
else
+ifneq (,$(have_working_info))
AM_V_ELC = @$(info $ ELC $@)
+else
+AM_V_ELC = @echo " ELC " $@;
+endif
AM_V_ELN =
endif
+
AM_V_GEN = @$(info $ GEN $@)
AM_V_GLOBALS = @$(info $ GEN globals.h)
AM_V_NO_PD = --no-print-directory
diff --git a/src/w16select.c b/src/w16select.c
index f6bc3dd8d47..b878481e469 100644
--- a/src/w16select.c
+++ b/src/w16select.c
@@ -651,7 +651,7 @@ frame's display, or the first available X display. */)
by the X interface code. (On MSDOS, killed text is only put
into the clipboard if we run under Windows, so we cannot check
the clipboard alone.) */
- if ((EQ (selection, Qnil) || EQ (selection, QPRIMARY))
+ if ((NILP (selection) || EQ (selection, QPRIMARY))
&& ! NILP (Fsymbol_value (Fintern_soft (build_string ("kill-ring"),
Qnil))))
return Qt;
diff --git a/src/w32.c b/src/w32.c
index 0dc874eac40..e4c6d007661 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -71,6 +71,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#undef localtime
+#undef clock
+
char *sys_ctime (const time_t *);
int sys_chdir (const char *);
int sys_creat (const char *, int);
@@ -87,6 +89,7 @@ struct tm *sys_localtime (const time_t *);
compiler to emit a warning about sys_strerror having no
prototype. */
char *sys_strerror (int);
+clock_t sys_clock (void);
#ifdef HAVE_MODULES
extern void dynlib_reset_last_error (void);
@@ -348,6 +351,7 @@ static BOOL g_b_init_reg_open_key_ex_w;
static BOOL g_b_init_reg_query_value_ex_w;
static BOOL g_b_init_expand_environment_strings_w;
static BOOL g_b_init_get_user_default_ui_language;
+static BOOL g_b_init_get_console_font_size;
BOOL g_b_init_compare_string_w;
BOOL g_b_init_debug_break_process;
@@ -537,6 +541,22 @@ typedef LONG (WINAPI *RegQueryValueExW_Proc) (HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYT
typedef DWORD (WINAPI *ExpandEnvironmentStringsW_Proc) (LPCWSTR,LPWSTR,DWORD);
typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void);
+typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD);
+
+#if _WIN32_WINNT < 0x0501
+typedef struct
+{
+ DWORD nFont;
+ COORD dwFontSize;
+} CONSOLE_FONT_INFO;
+#endif
+
+typedef BOOL (WINAPI *GetCurrentConsoleFont_Proc) (
+ HANDLE,
+ BOOL,
+ CONSOLE_FONT_INFO *);
+
+
/* ** A utility function ** */
static BOOL
is_windows_9x (void)
@@ -4640,6 +4660,9 @@ sys_open (const char * path, int oflag, int mode)
return res;
}
+/* This is not currently used, but might be needed again at some
+ point; DO NOT DELETE! */
+#if 0
int
openat (int fd, const char * path, int oflag, int mode)
{
@@ -4660,6 +4683,7 @@ openat (int fd, const char * path, int oflag, int mode)
return sys_open (path, oflag, mode);
}
+#endif
int
fchmod (int fd, mode_t mode)
@@ -10134,6 +10158,32 @@ sys_localtime (const time_t *t)
return localtime (t);
}
+/* The Windows CRT implementation of 'clock' doesn't really return CPU
+ time of the process (it returns the elapsed time since the process
+ started), so we provide a better emulation here, if possible. */
+clock_t
+sys_clock (void)
+{
+ if (get_process_times_fn)
+ {
+ FILETIME create, exit, kernel, user;
+ HANDLE proc = GetCurrentProcess ();
+ if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
+ {
+ LARGE_INTEGER user_int, kernel_int, total;
+ user_int.LowPart = user.dwLowDateTime;
+ user_int.HighPart = user.dwHighDateTime;
+ kernel_int.LowPart = kernel.dwLowDateTime;
+ kernel_int.HighPart = kernel.dwHighDateTime;
+ total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
+ /* We could redefine CLOCKS_PER_SEC to provide a finer
+ resolution, but with the basic 15.625 msec resolution of
+ the Windows clock, it doesn't really sound worth the hassle. */
+ return total.QuadPart / (10000000 / CLOCKS_PER_SEC);
+ }
+ }
+ return clock ();
+}
/* Try loading LIBRARY_ID from the file(s) specified in
@@ -10247,7 +10297,8 @@ check_windows_init_file (void)
openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0);
if (fd < 0)
{
- Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
+ Lisp_Object load_path_print = Fprin1_to_string (Vload_path,
+ Qnil, Qnil);
char *init_file_name = SSDATA (init_file);
char *load_path = SSDATA (load_path_print);
char *buffer = alloca (1024
@@ -10614,6 +10665,120 @@ realpath (const char *file_name, char *resolved_name)
return xstrdup (tgt);
}
+static void
+get_console_font_size (HANDLE hscreen, int *font_width, int *font_height)
+{
+ static GetCurrentConsoleFont_Proc s_pfn_Get_Current_Console_Font = NULL;
+ static GetConsoleFontSize_Proc s_pfn_Get_Console_Font_Size = NULL;
+
+ /* Default guessed values, for when we cannot obtain the actual ones. */
+ *font_width = 8;
+ *font_height = 12;
+
+ if (!is_windows_9x ())
+ {
+ if (g_b_init_get_console_font_size == 0)
+ {
+ HMODULE hm_kernel32 = LoadLibrary ("Kernel32.dll");
+ if (hm_kernel32)
+ {
+ s_pfn_Get_Current_Console_Font = (GetCurrentConsoleFont_Proc)
+ get_proc_addr (hm_kernel32, "GetCurrentConsoleFont");
+ s_pfn_Get_Console_Font_Size = (GetConsoleFontSize_Proc)
+ get_proc_addr (hm_kernel32, "GetConsoleFontSize");
+ }
+ g_b_init_get_console_font_size = 1;
+ }
+ }
+ if (s_pfn_Get_Current_Console_Font && s_pfn_Get_Console_Font_Size)
+ {
+ CONSOLE_FONT_INFO font_info;
+
+ if (s_pfn_Get_Current_Console_Font (hscreen, FALSE, &font_info))
+ {
+ COORD font_size = s_pfn_Get_Console_Font_Size (hscreen,
+ font_info.nFont);
+ if (font_size.X > 0)
+ *font_width = font_size.X;
+ if (font_size.Y > 0)
+ *font_height = font_size.Y;
+ }
+ }
+}
+
+/* A replacement for Posix execvp, used to restart Emacs. This is
+ needed because the low-level Windows API to start processes accepts
+ the command-line arguments as a single string, so we cannot safely
+ use the MSVCRT execvp emulation, because elements of argv[] that
+ have embedded blanks and tabs will not be passed correctly to the
+ restarted Emacs. */
+int
+w32_reexec_emacs (char *cmd_line, const char *wdir)
+{
+ STARTUPINFO si;
+ BOOL status;
+ PROCESS_INFORMATION proc_info;
+ DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
+
+ GetStartupInfo (&si); /* Use the same startup info as the caller. */
+ if (inhibit_window_system)
+ {
+ HANDLE screen_handle;
+ CONSOLE_SCREEN_BUFFER_INFO screen_info;
+
+ screen_handle = GetStdHandle (STD_OUTPUT_HANDLE);
+ if (screen_handle != INVALID_HANDLE_VALUE
+ && GetConsoleScreenBufferInfo (screen_handle, &screen_info))
+ {
+ int font_width, font_height;
+
+ /* Make the restarted Emacs's console window the same
+ dimensions as ours. */
+ si.dwXCountChars = screen_info.dwSize.X;
+ si.dwYCountChars = screen_info.dwSize.Y;
+ get_console_font_size (screen_handle, &font_width, &font_height);
+ si.dwXSize =
+ (screen_info.srWindow.Right - screen_info.srWindow.Left + 1)
+ * font_width;
+ si.dwYSize =
+ (screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1)
+ * font_height;
+ si.dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS;
+ }
+ /* This is a kludge: it causes the restarted "emacs -nw" to have
+ a new console window created for it, and that new window
+ might have different (default) properties, not the ones of
+ the parent process's console window. But without this,
+ restarting Emacs in the -nw mode simply doesn't work,
+ probably because the parent's console is still in use.
+ FIXME! */
+ dwCreationFlags = CREATE_NEW_CONSOLE;
+ }
+
+ /* Make sure we are in the original directory, in case the command
+ line specifies the program as a relative file name. */
+ chdir (wdir);
+
+ status = CreateProcess (NULL, /* no program, take from command line */
+ cmd_line, /* command line */
+ NULL,
+ NULL, /* thread attributes */
+ FALSE, /* unherit handles? */
+ dwCreationFlags,
+ NULL, /* environment */
+ wdir, /* initial directory */
+ &si, /* startup info */
+ &proc_info);
+ if (status)
+ {
+ CloseHandle (proc_info.hThread);
+ CloseHandle (proc_info.hProcess);
+ exit (0);
+ }
+ errno = ENOEXEC;
+ return -1;
+}
+
/*
globals_of_w32 is used to initialize those global variables that
must always be initialized on startup even when the global variable
@@ -10674,6 +10839,7 @@ globals_of_w32 (void)
g_b_init_compare_string_w = 0;
g_b_init_debug_break_process = 0;
g_b_init_get_user_default_ui_language = 0;
+ g_b_init_get_console_font_size = 0;
num_of_processors = 0;
/* The following sets a handler for shutdown notifications for
console apps. This actually applies to Emacs in both console and
@@ -10787,19 +10953,19 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
dcb.EvtChar = 0;
/* Configure speed. */
- if (!NILP (Fplist_member (contact, QCspeed)))
- tem = Fplist_get (contact, QCspeed);
+ if (!NILP (plist_member (contact, QCspeed)))
+ tem = plist_get (contact, QCspeed);
else
- tem = Fplist_get (p->childp, QCspeed);
+ tem = plist_get (p->childp, QCspeed);
CHECK_FIXNUM (tem);
dcb.BaudRate = XFIXNUM (tem);
- childp2 = Fplist_put (childp2, QCspeed, tem);
+ childp2 = plist_put (childp2, QCspeed, tem);
/* Configure bytesize. */
- if (!NILP (Fplist_member (contact, QCbytesize)))
- tem = Fplist_get (contact, QCbytesize);
+ if (!NILP (plist_member (contact, QCbytesize)))
+ tem = plist_get (contact, QCbytesize);
else
- tem = Fplist_get (p->childp, QCbytesize);
+ tem = plist_get (p->childp, QCbytesize);
if (NILP (tem))
tem = make_fixnum (8);
CHECK_FIXNUM (tem);
@@ -10807,13 +10973,13 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
error (":bytesize must be nil (8), 7, or 8");
dcb.ByteSize = XFIXNUM (tem);
summary[0] = XFIXNUM (tem) + '0';
- childp2 = Fplist_put (childp2, QCbytesize, tem);
+ childp2 = plist_put (childp2, QCbytesize, tem);
/* Configure parity. */
- if (!NILP (Fplist_member (contact, QCparity)))
- tem = Fplist_get (contact, QCparity);
+ if (!NILP (plist_member (contact, QCparity)))
+ tem = plist_get (contact, QCparity);
else
- tem = Fplist_get (p->childp, QCparity);
+ tem = plist_get (p->childp, QCparity);
if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
error (":parity must be nil (no parity), `even', or `odd'");
dcb.fParity = FALSE;
@@ -10837,13 +11003,13 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
dcb.Parity = ODDPARITY;
dcb.fErrorChar = TRUE;
}
- childp2 = Fplist_put (childp2, QCparity, tem);
+ childp2 = plist_put (childp2, QCparity, tem);
/* Configure stopbits. */
- if (!NILP (Fplist_member (contact, QCstopbits)))
- tem = Fplist_get (contact, QCstopbits);
+ if (!NILP (plist_member (contact, QCstopbits)))
+ tem = plist_get (contact, QCstopbits);
else
- tem = Fplist_get (p->childp, QCstopbits);
+ tem = plist_get (p->childp, QCstopbits);
if (NILP (tem))
tem = make_fixnum (1);
CHECK_FIXNUM (tem);
@@ -10854,13 +11020,13 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
dcb.StopBits = ONESTOPBIT;
else if (XFIXNUM (tem) == 2)
dcb.StopBits = TWOSTOPBITS;
- childp2 = Fplist_put (childp2, QCstopbits, tem);
+ childp2 = plist_put (childp2, QCstopbits, tem);
/* Configure flowcontrol. */
- if (!NILP (Fplist_member (contact, QCflowcontrol)))
- tem = Fplist_get (contact, QCflowcontrol);
+ if (!NILP (plist_member (contact, QCflowcontrol)))
+ tem = plist_get (contact, QCflowcontrol);
else
- tem = Fplist_get (p->childp, QCflowcontrol);
+ tem = plist_get (p->childp, QCflowcontrol);
if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
dcb.fOutxCtsFlow = FALSE;
@@ -10887,13 +11053,13 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
}
- childp2 = Fplist_put (childp2, QCflowcontrol, tem);
+ childp2 = plist_put (childp2, QCflowcontrol, tem);
/* Activate configuration. */
if (!SetCommState (hnd, &dcb))
error ("SetCommState() failed");
- childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
+ childp2 = plist_put (childp2, QCsummary, build_string (summary));
pset_childp (p, childp2);
}
diff --git a/src/w32.h b/src/w32.h
index 4941170bdcf..dc91c595c43 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -244,6 +244,9 @@ extern int w32_init_random (void *, ptrdiff_t);
extern Lisp_Object w32_read_registry (HKEY, Lisp_Object, Lisp_Object);
+/* Used instead of execvp to restart Emacs. */
+extern int w32_reexec_emacs (char *, const char *);
+
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
diff --git a/src/w32console.c b/src/w32console.c
index 12e1f397894..09749126e03 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -716,10 +716,10 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
if (cur_screen == INVALID_HANDLE_VALUE)
{
- printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
+ printf ("CreateConsoleScreenBuffer failed in initialize_w32_display\n");
printf ("LastError = 0x%lx\n", GetLastError ());
fflush (stdout);
- exit (0);
+ exit (1);
}
#else
cur_screen = prev_screen;
@@ -760,7 +760,13 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
}
}
- GetConsoleScreenBufferInfo (cur_screen, &info);
+ if (!GetConsoleScreenBufferInfo (cur_screen, &info))
+ {
+ printf ("GetConsoleScreenBufferInfo failed in initialize_w32_display\n");
+ printf ("LastError = 0x%lx\n", GetLastError ());
+ fflush (stdout);
+ exit (1);
+ }
char_attr_normal = info.wAttributes;
diff --git a/src/w32fns.c b/src/w32fns.c
index 37f9b813c6c..51540e1880c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -247,6 +247,8 @@ static HWND w32_visible_system_caret_hwnd;
static int w32_unicode_gui;
+static bool w32_selection_dialog_open;
+
/* From w32menu.c */
int menubar_in_use = 0;
@@ -795,13 +797,6 @@ w32_default_color_map (void)
return (cmap);
}
-DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
- 0, 0, 0, doc: /* Return the default color map. */)
- (void)
-{
- return w32_default_color_map ();
-}
-
static Lisp_Object
w32_color_map_lookup (const char *colorname)
{
@@ -1217,7 +1212,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
#endif
int mask_color;
- if (!EQ (Qnil, arg))
+ if (!NILP (arg))
f->output_data.w32->mouse_pixel
= w32_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
mask_color = FRAME_BACKGROUND_PIXEL (f);
@@ -1233,7 +1228,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
/* It's not okay to crash if the user selects a screwy cursor. */
count = x_catch_errors (FRAME_W32_DISPLAY (f));
- if (!EQ (Qnil, Vx_pointer_shape))
+ if (!NILP (Vx_pointer_shape))
{
CHECK_FIXNUM (Vx_pointer_shape);
cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XFIXNUM (Vx_pointer_shape));
@@ -1242,7 +1237,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
- if (!EQ (Qnil, Vx_nontext_pointer_shape))
+ if (!NILP (Vx_nontext_pointer_shape))
{
CHECK_FIXNUM (Vx_nontext_pointer_shape);
nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
@@ -1252,7 +1247,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
- if (!EQ (Qnil, Vx_hourglass_pointer_shape))
+ if (!NILP (Vx_hourglass_pointer_shape))
{
CHECK_FIXNUM (Vx_hourglass_pointer_shape);
hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
@@ -1263,7 +1258,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
- if (!EQ (Qnil, Vx_mode_pointer_shape))
+ if (!NILP (Vx_mode_pointer_shape))
{
CHECK_FIXNUM (Vx_mode_pointer_shape);
mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
@@ -1273,7 +1268,7 @@ w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
- if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
+ if (!NILP (Vx_sensitive_text_pointer_shape))
{
CHECK_FIXNUM (Vx_sensitive_text_pointer_shape);
hand_cursor
@@ -1461,7 +1456,7 @@ w32_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
return;
if (STRINGP (arg) && STRINGP (oldval)
- && EQ (Fstring_equal (oldval, arg), Qt))
+ && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
@@ -1484,7 +1479,7 @@ w32_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!NILP (arg) || NILP (oldval))
@@ -1802,6 +1797,32 @@ w32_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
w32_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
}
+/* Enable or disable double buffering on frame F.
+
+ When double buffering is enabled, all drawing happens on a back
+ buffer (a bitmap), which is then displayed as a single operation
+ after redisplay is complete. This avoids flicker caused by the
+ results of an incomplete redisplay becoming visible. */
+static void
+w32_set_inhibit_double_buffering (struct frame *f,
+ Lisp_Object new_value,
+ /* This parameter is unused. */
+ Lisp_Object old_value)
+{
+ block_input ();
+
+ if (NILP (new_value))
+ FRAME_OUTPUT_DATA (f)->want_paint_buffer = 1;
+ else
+ {
+ FRAME_OUTPUT_DATA (f)->want_paint_buffer = 0;
+ w32_release_paint_buffer (f);
+
+ SET_FRAME_GARBAGED (f);
+ }
+
+ unblock_input ();
+}
/* Set the pixel height of the tool bar of frame F to HEIGHT. */
void
@@ -4093,7 +4114,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
case WM_ERASEBKGND:
f = w32_window_to_frame (dpyinfo, hwnd);
- if (f)
+
+ enter_crit ();
+ if (f && (w32_disable_double_buffering
+ || !FRAME_OUTPUT_DATA (f)->paint_buffer))
{
HDC hdc = get_frame_dc (f);
GetUpdateRect (hwnd, &wmsg.rect, FALSE);
@@ -4107,6 +4131,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
wmsg.rect.right, wmsg.rect.bottom));
#endif /* W32_DEBUG_DISPLAY */
}
+ leave_crit ();
return 1;
case WM_PALETTECHANGED:
/* ignore our own changes */
@@ -4154,6 +4179,16 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
update_rect.left, update_rect.top,
update_rect.right, update_rect.bottom));
#endif
+ /* Under double-buffering, update the frame from the back
+ buffer, to prevent a "ghost" of the selection dialog to
+ be left on display while the user selects in the dialog. */
+ if (w32_selection_dialog_open
+ && !w32_disable_double_buffering
+ && FRAME_OUTPUT_DATA (f)->paint_dc)
+ BitBlt (FRAME_OUTPUT_DATA (f)->paint_buffer_handle,
+ 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
+ FRAME_OUTPUT_DATA (f)->paint_dc, 0, 0, SRCCOPY);
+
EndPaint (hwnd, &paintStruct);
leave_crit ();
@@ -5506,11 +5541,11 @@ my_create_window (struct frame * f)
RES_TYPE_NUMBER);
top = gui_display_get_arg (dpyinfo, Qnil, Qtop, "top", "Top",
RES_TYPE_NUMBER);
- if (EQ (left, Qunbound))
+ if (BASE_EQ (left, Qunbound))
coords[0] = CW_USEDEFAULT;
else
coords[0] = XFIXNUM (left);
- if (EQ (top, Qunbound))
+ if (BASE_EQ (top, Qunbound))
coords[1] = CW_USEDEFAULT;
else
coords[1] = XFIXNUM (top);
@@ -5626,12 +5661,12 @@ w32_icon (struct frame *f, Lisp_Object parms)
RES_TYPE_NUMBER);
icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0,
RES_TYPE_NUMBER);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
+ if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound))
{
CHECK_FIXNUM (icon_x);
CHECK_FIXNUM (icon_y);
}
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
+ else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound))
error ("Both left and top icon corners of icon must be specified");
block_input ();
@@ -5726,7 +5761,7 @@ w32_default_font_parameter (struct frame *f, Lisp_Object parms)
parms, Qfont, NULL, NULL,
RES_TYPE_STRING);
Lisp_Object font;
- if (EQ (font_param, Qunbound))
+ if (BASE_EQ (font_param, Qunbound))
font_param = Qnil;
font = !NILP (font_param) ? font_param
: gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
@@ -5771,7 +5806,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
Lisp_Object name;
bool minibuffer_only = false;
long window_prompting = 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object display;
struct w32_display_info *dpyinfo = NULL;
Lisp_Object parent, parent_frame;
@@ -5791,10 +5826,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
display = gui_display_get_arg (dpyinfo, parameters, Qterminal, 0, 0,
RES_TYPE_NUMBER);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = gui_display_get_arg (dpyinfo, parameters, Qdisplay, 0, 0,
RES_TYPE_STRING);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_x_display_info (display);
kb = dpyinfo->terminal->kboard;
@@ -5805,7 +5840,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
name = gui_display_get_arg (dpyinfo, parameters, Qname, "name", "Name",
RES_TYPE_STRING);
if (!STRINGP (name)
- && ! EQ (name, Qunbound)
+ && ! BASE_EQ (name, Qunbound)
&& ! NILP (name))
error ("Invalid frame name--not a string or nil");
@@ -5815,7 +5850,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
/* See if parent window is specified. */
parent = gui_display_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
RES_TYPE_NUMBER);
- if (EQ (parent, Qunbound))
+ if (BASE_EQ (parent, Qunbound))
parent = Qnil;
else if (!NILP (parent))
CHECK_FIXNUM (parent);
@@ -5858,14 +5893,14 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
tem = gui_display_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
RES_TYPE_BOOLEAN);
- FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
+ FRAME_UNDECORATED (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound);
store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
tem = gui_display_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
RES_TYPE_BOOLEAN);
- FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
+ FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound);
store_frame_param (f, Qskip_taskbar,
- (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
+ (NILP (tem) || BASE_EQ (tem, Qunbound)) ? Qnil : Qt);
/* By default, make scrollbars the system standard width and height. */
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
@@ -5921,7 +5956,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->w32_id_name));
f->explicit_name = false;
@@ -5961,7 +5996,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
value = gui_display_get_arg (dpyinfo, parameters, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parameters = Fcons (Fcons (Qinternal_border_width, value),
parameters);
}
@@ -5978,7 +6013,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
value = gui_display_get_arg (dpyinfo, parameters, Qchild_frame_border_width,
"childFrameBorder", "childFrameBorder",
RES_TYPE_NUMBER);
- if (!EQ (value, Qunbound))
+ if (!BASE_EQ (value, Qunbound))
parameters = Fcons (Fcons (Qchild_frame_border_width, value),
parameters);
}
@@ -6018,6 +6053,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
NULL, NULL, RES_TYPE_BOOLEAN);
gui_default_parameter (f, parameters, Qno_special_glyphs, Qnil,
NULL, NULL, RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parameters, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
/* Process alpha here (Bug#16619). On XP this fails with child
frames. For `no-focus-on-map' frames delay processing of alpha
@@ -6078,6 +6115,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
? make_fixnum (0) : make_fixnum (1),
NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parameters, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
gui_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
gui_default_parameter (f, parameters, Qtitle, Qnil,
@@ -6155,6 +6196,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
gui_default_parameter (f, parameters, Qz_group, Qnil,
NULL, NULL, RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parameters, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+
/* Make the window appear on the frame and enable display, unless
the caller says not to. However, with explicit parent, Emacs
cannot control visibility, so don't try. */
@@ -6168,7 +6212,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
w32_iconify_frame (f);
else
{
- if (EQ (visibility, Qunbound))
+ if (BASE_EQ (visibility, Qunbound))
visibility = Qt;
if (!NILP (visibility))
@@ -6941,7 +6985,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
struct frame *f;
Lisp_Object frame;
Lisp_Object name;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct kboard *kb;
bool face_change_before = face_change;
@@ -6960,7 +7004,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
RES_TYPE_STRING);
if (!STRINGP (name)
- && !EQ (name, Qunbound)
+ && !BASE_EQ (name, Qunbound)
&& !NILP (name))
error ("Invalid frame name--not a string or nil");
Vx_resource_name = name;
@@ -6994,7 +7038,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->w32_id_name));
f->explicit_name = false;
@@ -7033,7 +7077,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
@@ -7089,6 +7133,11 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
/* Process alpha here (Bug#17344). */
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7266,10 +7315,9 @@ w32_hide_tip (bool delete)
return Qnil;
else
{
- ptrdiff_t count;
Lisp_Object was_open = Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
@@ -7310,8 +7358,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
struct text_pos pos;
int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t count_1;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object window, size, tip_buf;
AUTO_STRING (tip, " *tip*");
@@ -7324,9 +7371,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
decode_window_system_frame (frame);
if (NILP (timeout))
- timeout = make_fixnum (5);
- else
- CHECK_FIXNAT (timeout);
+ timeout = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
if (NILP (dx))
dx = make_fixnum (5);
@@ -7510,7 +7556,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
/* Insert STRING into the root window's buffer and fit the frame to
the buffer. */
- count_1 = SPECPDL_INDEX ();
+ specpdl_ref count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
@@ -7714,6 +7760,15 @@ w32_dialog_in_progress (Lisp_Object in_progress)
{
Lisp_Object frames, frame;
+ /* Indicate to w32_wnd_proc that the selection dialog is about to be
+ open (or was closed, if IN_PROGRESS is nil). */
+ if (!w32_disable_double_buffering)
+ {
+ enter_crit ();
+ w32_selection_dialog_open = !NILP (in_progress);
+ leave_crit ();
+ }
+
/* Don't let frames in `above' z-group obscure dialog windows. */
FOR_EACH_FRAME (frames, frame)
{
@@ -7945,7 +8000,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
#endif /* !NTGUI_UNICODE */
{
- int count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
w32_dialog_in_progress (Qt);
@@ -10150,21 +10205,21 @@ usage: (w32-notification-notify &rest PARAMS) */)
arg_plist = Flist (nargs, args);
/* Icon. */
- lres = Fplist_get (arg_plist, QCicon);
+ lres = plist_get (arg_plist, QCicon);
if (STRINGP (lres))
icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil)));
else
icon = (char *)"";
/* Tip. */
- lres = Fplist_get (arg_plist, QCtip);
+ lres = plist_get (arg_plist, QCtip);
if (STRINGP (lres))
tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
tip = (char *)"Emacs notification";
/* Severity. */
- lres = Fplist_get (arg_plist, QClevel);
+ lres = plist_get (arg_plist, QClevel);
if (NILP (lres))
severity = Ni_None;
else if (EQ (lres, Qinfo))
@@ -10177,14 +10232,14 @@ usage: (w32-notification-notify &rest PARAMS) */)
severity = Ni_Info;
/* Title. */
- lres = Fplist_get (arg_plist, QCtitle);
+ lres = plist_get (arg_plist, QCtitle);
if (STRINGP (lres))
title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
title = (char *)"";
/* Notification body text. */
- lres = Fplist_get (arg_plist, QCbody);
+ lres = plist_get (arg_plist, QCbody);
if (STRINGP (lres))
msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
else
@@ -10427,7 +10482,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
gui_set_alpha,
0, /* x_set_sticky */
0, /* x_set_tool_bar_position */
- 0, /* x_set_inhibit_double_buffering */
+ w32_set_inhibit_double_buffering,
w32_set_undecorated,
w32_set_parent_frame,
w32_set_skip_taskbar,
@@ -10436,6 +10491,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
w32_set_z_group,
0, /* x_set_override_redirect */
gui_set_no_special_glyphs,
+ gui_set_alpha_background,
};
void
@@ -10727,21 +10783,6 @@ bass-down, bass-boost, bass-up, treble-down, treble-up */);
doc: /* SKIP: real doc in xfns.c. */);
Vx_pixel_size_width_font_regexp = Qnil;
- DEFVAR_LISP ("w32-bdf-filename-alist",
- Vw32_bdf_filename_alist,
- doc: /* List of bdf fonts and their corresponding filenames. */);
- Vw32_bdf_filename_alist = Qnil;
-
- DEFVAR_BOOL ("w32-strict-fontnames",
- w32_strict_fontnames,
- doc: /* Non-nil means only use fonts that are exact matches for those requested.
-Default is nil, which allows old fontnames that are not XLFD compliant,
-and allows third-party CJK display to work by specifying false charset
-fields to trick Emacs into translating to Big5, SJIS etc.
-Setting this to t will prevent wrong fonts being selected when
-fontsets are automatically created. */);
- w32_strict_fontnames = 0;
-
DEFVAR_BOOL ("w32-strict-painting",
w32_strict_painting,
doc: /* Non-nil means use strict rules for repainting frames.
@@ -10831,7 +10872,6 @@ keys when IME input is received. */);
/* W32 specific functions */
defsubr (&Sw32_define_rgb_color);
- defsubr (&Sw32_default_color_map);
defsubr (&Sw32_display_monitor_attributes_list);
defsubr (&Sw32_send_sys_command);
defsubr (&Sw32_shell_execute);
@@ -11201,6 +11241,12 @@ see `w32-ansi-code-page'. */);
w32_multibyte_code_page = _getmbcp ();
#endif
+ DEFVAR_BOOL ("w32-disable-double-buffering", w32_disable_double_buffering,
+ doc: /* Completely disable double buffering.
+This variable is used for debugging, and takes precedence over any
+value of the `inhibit-double-buffering' frame parameter. */);
+ w32_disable_double_buffering = false;
+
if (os_subtype == OS_SUBTYPE_NT)
w32_unicode_gui = 1;
else
diff --git a/src/w32font.c b/src/w32font.c
index 0495099db5c..611a0c89658 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -1540,6 +1540,19 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
|| physical_font->ntmFontSig.fsUsb[1]
|| physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff;
+ /* Kludgey fix for Arial Unicode MS font that claims support for
+ scripts it doesn't actually cover. */
+ if (strncmp (logical_font->elfLogFont.lfFaceName,
+ "Arial Unicode MS", 16) == 0)
+ {
+ /* Reset bits 4 (Phonetic), 12 (Vai), 14 (Nko), 27 (Balinese). */
+ physical_font->ntmFontSig.fsUsb[0] &= 0xf7ffafef;
+ /* Reset bits 53 (Phags-pa) and 58 (Phoenician). */
+ physical_font->ntmFontSig.fsUsb[1] &= 0xfbdfffff;
+ /* Set bit 70 (Tibetan). */
+ physical_font->ntmFontSig.fsUsb[2] |= 0x00000040;
+ }
+
/* Skip non matching fonts. */
/* For uniscribe backend, consider only truetype or opentype fonts
@@ -2385,7 +2398,6 @@ font_supported_scripts (FONTSIGNATURE * sig)
SUBRANGE (108, Qkharoshthi);
SUBRANGE (109, Qtai_xuan_jing_symbol);
SUBRANGE (110, Qcuneiform);
- SUBRANGE (111, Qcuneiform_numbers_and_punctuation);
SUBRANGE (111, Qcounting_rod_numeral);
SUBRANGE (112, Qsundanese);
SUBRANGE (113, Qlepcha);
@@ -2661,7 +2673,7 @@ in the font selection dialog. */)
ReleaseDC (FRAME_W32_WINDOW (f), hdc);
{
- int count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object value = Qnil;
w32_dialog_in_progress (Qt);
@@ -2828,8 +2840,6 @@ syms_of_w32font (void)
DEFSYM (Qbuginese, "buginese");
DEFSYM (Qbuhid, "buhid");
DEFSYM (Qcuneiform, "cuneiform");
- DEFSYM (Qcuneiform_numbers_and_punctuation,
- "cuneiform-numbers-and-punctuation");
DEFSYM (Qcypriot, "cypriot");
DEFSYM (Qdeseret, "deseret");
DEFSYM (Qglagolitic, "glagolitic");
@@ -2837,18 +2847,18 @@ syms_of_w32font (void)
DEFSYM (Qhanunoo, "hanunoo");
DEFSYM (Qkharoshthi, "kharoshthi");
DEFSYM (Qlimbu, "limbu");
- DEFSYM (Qlinear_b, "linear_b");
+ DEFSYM (Qlinear_b, "linear-b");
DEFSYM (Qaegean_number, "aegean-number");
- DEFSYM (Qold_italic, "old_italic");
- DEFSYM (Qold_persian, "old_persian");
+ DEFSYM (Qold_italic, "old-italic");
+ DEFSYM (Qold_persian, "old-persian");
DEFSYM (Qosmanya, "osmanya");
DEFSYM (Qphags_pa, "phags-pa");
DEFSYM (Qphoenician, "phoenician");
DEFSYM (Qshavian, "shavian");
- DEFSYM (Qsyloti_nagri, "syloti_nagri");
+ DEFSYM (Qsyloti_nagri, "syloti-nagri");
DEFSYM (Qtagalog, "tagalog");
DEFSYM (Qtagbanwa, "tagbanwa");
- DEFSYM (Qtai_le, "tai_le");
+ DEFSYM (Qtai_le, "tai-le");
DEFSYM (Qtifinagh, "tifinagh");
DEFSYM (Qugaritic, "ugaritic");
DEFSYM (Qlycian, "lycian");
diff --git a/src/w32image.c b/src/w32image.c
index f3374dcfd30..da748b8dab4 100644
--- a/src/w32image.c
+++ b/src/w32image.c
@@ -253,6 +253,7 @@ w32_can_use_native_image_api (Lisp_Object type)
|| EQ (type, Qpng)
|| EQ (type, Qgif)
|| EQ (type, Qtiff)
+ || EQ (type, Qbmp)
|| EQ (type, Qnative_image)))
{
/* GDI+ can also display BMP, Exif, ICON, WMF, and EMF images.
@@ -381,7 +382,7 @@ w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes,
static ARGB
w32_image_bg_color (struct frame *f, struct image *img)
{
- Lisp_Object specified_bg = Fplist_get (XCDR (img->spec), QCbackground);
+ Lisp_Object specified_bg = plist_get (XCDR (img->spec), QCbackground);
Emacs_Color color;
/* If the user specified a color, try to use it; if not, use the
@@ -434,7 +435,7 @@ w32_load_image (struct frame *f, struct image *img,
if (status == Ok)
{
/* In multiframe pictures, select the first frame. */
- Lisp_Object lisp_index = Fplist_get (XCDR (img->spec), QCindex);
+ Lisp_Object lisp_index = plist_get (XCDR (img->spec), QCindex);
int index = FIXNATP (lisp_index) ? XFIXNAT (lisp_index) : 0;
int nframes;
double delay;
diff --git a/src/w32menu.c b/src/w32menu.c
index 42e27babbc9..b10239d5cc6 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -188,7 +188,7 @@ menubar_selection_callback (struct frame *f, void * client_data)
i = 0;
while (i < f->menu_bar_items_used)
{
- if (EQ (AREF (vector, i), Qnil))
+ if (NILP (AREF (vector, i)))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
@@ -285,7 +285,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= (Lisp_Object *) alloca (previous_menu_items_used
@@ -556,10 +556,8 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
HMENU menu;
POINT pos;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
- widget_value **submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- Lisp_Object *subprefix_stack
- = (Lisp_Object *) alloca (menu_items_used * word_size);
+ widget_value **submenu_stack;
+ Lisp_Object *subprefix_stack;
int submenu_depth = 0;
bool first_pane;
@@ -574,6 +572,11 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
return Qnil;
}
+ USE_SAFE_ALLOCA;
+
+ submenu_stack = SAFE_ALLOCA (menu_items_used * sizeof (widget_value *));
+ subprefix_stack = SAFE_ALLOCA (menu_items_used * word_size);
+
block_input ();
/* Create a tree of widget_value objects
@@ -587,7 +590,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
i = 0;
while (i < menu_items_used)
{
- if (EQ (AREF (menu_items, i), Qnil))
+ if (NILP (AREF (menu_items, i)))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
@@ -779,7 +782,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
i = 0;
while (i < menu_items_used)
{
- if (EQ (AREF (menu_items, i), Qnil))
+ if (NILP (AREF (menu_items, i)))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
@@ -816,6 +819,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
entry = Fcons (subprefix_stack[j], entry);
}
unblock_input ();
+ SAFE_FREE ();
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
@@ -830,6 +834,7 @@ w32_menu_show (struct frame *f, int x, int y, int menuflags,
}
unblock_input ();
+ SAFE_FREE ();
return Qnil;
}
diff --git a/src/w32notify.c b/src/w32notify.c
index e7d2f0f076b..72e634f77c7 100644
--- a/src/w32notify.c
+++ b/src/w32notify.c
@@ -40,8 +40,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
and returns. That causes the WaitForSingleObjectEx function call
inside watch_worker to return, but the thread won't terminate until
the event telling to do so will be signaled. The completion
- routine issued another call to ReadDirectoryChangesW as quickly as
- possible. (Except when it does not, see below.)
+ routine then issues another call to ReadDirectoryChangesW as quickly
+ as possible. (Except when it does not, see below.)
In a GUI session, the WM_EMACS_FILENOTIFY message posted to the
message queue gets dispatched to the main Emacs window procedure,
@@ -519,16 +519,16 @@ watched for some reason, this function signals a `file-error' error.
FILTER is a list of conditions for reporting an event. It can include
the following symbols:
- 'file-name' -- report file creation, deletion, or renaming
- 'directory-name' -- report directory creation, deletion, or renaming
- 'attributes' -- report changes in attributes
- 'size' -- report changes in file-size
- 'last-write-time' -- report changes in last-write time
- 'last-access-time' -- report changes in last-access time
- 'creation-time' -- report changes in creation time
- 'security-desc' -- report changes in security descriptor
+ `file-name' -- report file creation, deletion, or renaming
+ `directory-name' -- report directory creation, deletion, or renaming
+ `attributes' -- report changes in attributes
+ `size' -- report changes in file-size
+ `last-write-time' -- report changes in last-write time
+ `last-access-time' -- report changes in last-access time
+ `creation-time' -- report changes in creation time
+ `security-desc' -- report changes in security descriptor
-If FILE is a directory, and FILTER includes 'subtree', then all the
+If FILE is a directory, and FILTER includes `subtree', then all the
subdirectories will also be watched and changes in them reported.
When any event happens that satisfies the conditions specified by
@@ -541,11 +541,11 @@ DESCRIPTOR is the same object as the one returned by this function.
ACTION is the description of the event. It could be any one of the
following:
- 'added' -- FILE was added
- 'removed' -- FILE was deleted
- 'modified' -- FILE's contents or its attributes were modified
- 'renamed-from' -- a file was renamed whose old name was FILE
- 'renamed-to' -- a file was renamed and its new name is FILE
+ `added' -- FILE was added
+ `removed' -- FILE was deleted
+ `modified' -- FILE's contents or its attributes were modified
+ `renamed-from' -- a file was renamed whose old name was FILE
+ `renamed-to' -- a file was renamed and its new name is FILE
FILE is the name of the file whose event is being reported.
diff --git a/src/w32proc.c b/src/w32proc.c
index 781a19f480f..7acfba64d70 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -63,6 +63,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "w32term.h"
#include "coding.h"
+void w32_raise (int);
+
#define RVA_TO_PTR(var,section,filedata) \
((void *)((section)->PointerToRawData \
+ ((DWORD_PTR)(var) - (section)->VirtualAddress) \
@@ -311,6 +313,21 @@ sigismember (const sigset_t *set, int signo)
return (*set & (1U << signo)) != 0;
}
+/* A fuller emulation of 'raise', which supports signals that MS
+ runtime doesn't know about. */
+void
+w32_raise (int signo)
+{
+ if (!(signo == SIGCHLD || signo == SIGALRM || signo == SIGPROF))
+ raise (signo);
+
+ /* Call the handler directly for the signals that we handle
+ ourselves. */
+ signal_handler handler = sig_handlers[signo];
+ if (!(handler == SIG_DFL || handler == SIG_IGN || handler == SIG_ERR))
+ handler (signo);
+}
+
pid_t
getpgrp (void)
{
diff --git a/src/w32select.c b/src/w32select.c
index eae1a0bac02..37206118127 100644
--- a/src/w32select.c
+++ b/src/w32select.c
@@ -631,7 +631,7 @@ validate_coding_system (Lisp_Object coding_system)
eol_type = Fcoding_system_eol_type (coding_system);
/* Already a DOS coding system? */
- if (EQ (eol_type, make_fixnum (1)))
+ if (BASE_EQ (eol_type, make_fixnum (1)))
return coding_system;
/* Get EOL_TYPE vector of the base of CODING_SYSTEM. */
diff --git a/src/w32term.c b/src/w32term.c
index 700c492cc37..d0577efccc1 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -276,6 +276,62 @@ XGetGCValues (void *ignore, XGCValues *gc,
#endif
static void
+w32_show_back_buffer (struct frame *f)
+{
+ struct w32_output *output;
+ HDC raw_dc;
+
+ output = FRAME_OUTPUT_DATA (f);
+
+ if (!output->want_paint_buffer || w32_disable_double_buffering)
+ return;
+
+ enter_crit ();
+
+ if (output->paint_buffer)
+ {
+ raw_dc = GetDC (output->window_desc);
+
+ if (!raw_dc)
+ emacs_abort ();
+
+ BitBlt (raw_dc, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f),
+ output->paint_dc, 0, 0, SRCCOPY);
+ ReleaseDC (output->window_desc, raw_dc);
+
+ output->paint_buffer_dirty = 0;
+ }
+
+ leave_crit ();
+}
+
+void
+w32_release_paint_buffer (struct frame *f)
+{
+ /* Delete the back buffer so it gets created
+ again the next time we ask for the DC. */
+
+ enter_crit ();
+ if (FRAME_OUTPUT_DATA (f)->paint_buffer)
+ {
+ deselect_palette (f, FRAME_OUTPUT_DATA (f)->paint_buffer_handle);
+
+ SelectObject (FRAME_OUTPUT_DATA (f)->paint_dc,
+ FRAME_OUTPUT_DATA (f)->paint_dc_object);
+ ReleaseDC (FRAME_OUTPUT_DATA (f)->window_desc,
+ FRAME_OUTPUT_DATA (f)->paint_buffer_handle);
+ DeleteDC (FRAME_OUTPUT_DATA (f)->paint_dc);
+ DeleteObject (FRAME_OUTPUT_DATA (f)->paint_buffer);
+
+ FRAME_OUTPUT_DATA (f)->paint_buffer = NULL;
+ FRAME_OUTPUT_DATA (f)->paint_dc = NULL;
+ FRAME_OUTPUT_DATA (f)->paint_buffer_handle = NULL;
+ }
+ leave_crit ();
+}
+
+static void
w32_get_mouse_wheel_vertical_delta (void)
{
if (os_subtype != OS_SUBTYPE_NT)
@@ -704,10 +760,32 @@ w32_update_end (struct frame *f)
static void
w32_frame_up_to_date (struct frame *f)
{
- if (FRAME_W32_P (f))
- FRAME_MOUSE_UPDATE (f);
+ FRAME_MOUSE_UPDATE (f);
+
+ if (!buffer_flipping_blocked_p ()
+ && FRAME_OUTPUT_DATA (f)->paint_buffer_dirty)
+ w32_show_back_buffer (f);
+}
+
+static void
+w32_buffer_flipping_unblocked_hook (struct frame *f)
+{
+ if (FRAME_OUTPUT_DATA (f)->paint_buffer_dirty)
+ w32_show_back_buffer (f);
}
+/* Flip buffers on F if drawing has happened. This function is not
+ called to flush the display connection of a frame (which doesn't
+ exist on MS Windows), but also called in some situations in
+ minibuf.c to make the contents of the back buffer visible. */
+void
+w32_flip_buffers_if_dirty (struct frame *f)
+{
+ if (FRAME_OUTPUT_DATA (f)->paint_buffer
+ && FRAME_OUTPUT_DATA (f)->paint_buffer_dirty
+ && !f->garbaged && !buffer_flipping_blocked_p ())
+ w32_show_back_buffer (f);
+}
/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
arrow bitmaps, or clear the fringes if no bitmaps are required
@@ -794,12 +872,25 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
w32_fill_area (f, hdc, face->background,
p->bx, p->by, p->nx, p->ny);
- if (p->which && p->which < max_fringe_bmp)
+ if (p->which
+ && p->which < max_fringe_bmp
+ && p->which < max_used_fringe_bitmap)
{
HBITMAP pixmap = fringe_bmp[p->which];
HDC compat_hdc;
HANDLE horig_obj;
+ if (!fringe_bmp[p->which])
+ {
+ /* This fringe bitmap is known to fringe.c, but lacks the
+ HBITMAP data which shadows that bitmap. This is typical
+ to define-fringe-bitmap being called when the selected
+ frame was not a GUI frame, for example, when packages
+ that define fringe bitmaps are loaded by a daemon Emacs.
+ Create the missing HBITMAP now. */
+ gui_define_fringe_bitmap (f, p->which);
+ }
+
compat_hdc = CreateCompatibleDC (hdc);
SaveDC (hdc);
@@ -2564,7 +2655,11 @@ w32_draw_glyph_string (struct glyph_string *s)
int y;
if (s->prev
- && s->prev->face->underline == FACE_UNDER_LINE)
+ && s->prev->face->underline == FACE_UNDER_LINE
+ && (s->prev->face->underline_at_descent_line_p
+ == s->face->underline_at_descent_line_p)
+ && (s->prev->face->underline_pixels_above_descent_line
+ == s->face->underline_pixels_above_descent_line))
{
/* We use the same underline style as the previous one. */
thickness = s->prev->underline_thickness;
@@ -2587,12 +2682,13 @@ w32_draw_glyph_string (struct glyph_string *s)
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_underline_at_descent_line, s->w));
underline_at_descent_line
- = !(NILP (val) || EQ (val, Qunbound));
+ = (!(NILP (val) || BASE_EQ (val, Qunbound))
+ || s->face->underline_at_descent_line_p);
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_use_underline_position_properties, s->w));
use_underline_position_properties
- = !(NILP (val) || EQ (val, Qunbound));
+ = !(NILP (val) || BASE_EQ (val, Qunbound));
/* Get the underline thickness. Default is 1 pixel. */
if (font && font->underline_thickness > 0)
@@ -2601,7 +2697,9 @@ w32_draw_glyph_string (struct glyph_string *s)
thickness = 1;
if (underline_at_descent_line
|| !font)
- position = (s->height - thickness) - (s->ybase - s->y);
+ position = ((s->height - thickness)
+ - (s->ybase - s->y)
+ - s->face->underline_pixels_above_descent_line);
else
{
/* Get the underline position. This is the
@@ -2619,7 +2717,12 @@ w32_draw_glyph_string (struct glyph_string *s)
else
position = (font->descent + 1) / 2;
}
- position = max (position, minimum_offset);
+
+ if (!(s->face->underline_at_descent_line_p
+ /* Ignore minimum_offset if the amount of pixels
+ was explicitly specified. */
+ && s->face->underline_pixels_above_descent_line))
+ position = max (position, minimum_offset);
}
/* Check the sanity of thickness and position. We should
avoid drawing underline out of the current line area. */
@@ -2847,8 +2950,9 @@ w32_scroll_run (struct window *w, struct run *run)
{
struct frame *f = XFRAME (w->frame);
int x, y, width, height, from_y, to_y, bottom_y;
+ HDC hdc;
HWND hwnd = FRAME_W32_WINDOW (f);
- HRGN expect_dirty;
+ HRGN expect_dirty = NULL;
/* Get frame-relative bounding box of the text display area of W,
without mode lines. Include in this box the left and right
@@ -2867,7 +2971,9 @@ w32_scroll_run (struct window *w, struct run *run)
height = bottom_y - from_y;
else
height = run->height;
- expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
+
+ if (w32_disable_double_buffering)
+ expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
}
else
{
@@ -2877,44 +2983,55 @@ w32_scroll_run (struct window *w, struct run *run)
height = bottom_y - to_y;
else
height = run->height;
- expect_dirty = CreateRectRgn (x, y, x + width, to_y);
+
+ if (w32_disable_double_buffering)
+ expect_dirty = CreateRectRgn (x, y, x + width, to_y);
}
block_input ();
/* Cursor off. Will be switched on again in gui_update_window_end. */
gui_clear_cursor (w);
-
- {
- RECT from;
- RECT to;
- HRGN dirty = CreateRectRgn (0, 0, 0, 0);
- HRGN combined = CreateRectRgn (0, 0, 0, 0);
-
- from.left = to.left = x;
- from.right = to.right = x + width;
- from.top = from_y;
- from.bottom = from_y + height;
- to.top = y;
- to.bottom = bottom_y;
-
- ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
- NULL, SW_INVALIDATE);
-
- /* Combine this with what we expect to be dirty. This covers the
- case where not all of the region we expect is actually dirty. */
- CombineRgn (combined, dirty, expect_dirty, RGN_OR);
-
- /* If the dirty region is not what we expected, redraw the entire frame. */
- if (!EqualRgn (combined, expect_dirty))
- SET_FRAME_GARBAGED (f);
-
- DeleteObject (dirty);
- DeleteObject (combined);
- }
+ if (!w32_disable_double_buffering)
+ {
+ hdc = get_frame_dc (f);
+ BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
+ release_frame_dc (f, hdc);
+ }
+ else
+ {
+ RECT from;
+ RECT to;
+ HRGN dirty = CreateRectRgn (0, 0, 0, 0);
+ HRGN combined = CreateRectRgn (0, 0, 0, 0);
+
+ from.left = to.left = x;
+ from.right = to.right = x + width;
+ from.top = from_y;
+ from.bottom = from_y + height;
+ to.top = y;
+ to.bottom = bottom_y;
+
+ ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
+ NULL, SW_INVALIDATE);
+
+ /* Combine this with what we expect to be dirty. This covers the
+ case where not all of the region we expect is actually dirty. */
+ CombineRgn (combined, dirty, expect_dirty, RGN_OR);
+
+ /* If the dirty region is not what we expected, redraw the entire frame. */
+ if (!EqualRgn (combined, expect_dirty))
+ SET_FRAME_GARBAGED (f);
+
+ DeleteObject (dirty);
+ DeleteObject (combined);
+ }
unblock_input ();
- DeleteObject (expect_dirty);
+
+ if (w32_disable_double_buffering
+ && expect_dirty)
+ DeleteObject (expect_dirty);
}
@@ -4784,6 +4901,14 @@ w32_scroll_bar_clear (struct frame *f)
{
Lisp_Object bar;
+ /* Return if double buffering is enabled, since clearing a frame
+ actually clears just the back buffer, so avoid clearing all of
+ the scroll bars, since that causes the scroll bars to
+ flicker. */
+ if (!w32_disable_double_buffering
+ && FRAME_OUTPUT_DATA (f)->want_paint_buffer)
+ return;
+
/* We can have scroll bars even if this is 0,
if we just turned off scroll bar mode.
But in that case we should not clear them. */
@@ -4899,10 +5024,17 @@ w32_read_socket (struct terminal *terminal,
struct input_event inev;
int do_help = 0;
+ /* WM_WINDOWPOSCHANGED makes the buffer dirty, but there's no
+ reason to flush the back buffer after receiving such an
+ event, and that also causes flicker. */
+ bool ignore_dirty_back_buffer = false;
+
/* DebPrint (("w32_read_socket: %s time:%u\n", */
/* w32_name_of_message (msg.msg.message), */
/* msg.msg.time)); */
+ f = NULL;
+
EVENT_INIT (inev);
inev.kind = NO_EVENT;
inev.arg = Qnil;
@@ -4944,24 +5076,32 @@ w32_read_socket (struct terminal *terminal,
}
else
{
- /* Erase background again for safety. But don't do
- that if the frame's 'garbaged' flag is set, since
- in that case expose_frame will do nothing, and if
- the various redisplay flags happen to be unset,
- we are left with a blank frame. */
- if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
+ if (w32_disable_double_buffering
+ || !FRAME_OUTPUT_DATA (f)->paint_buffer)
{
- HDC hdc = get_frame_dc (f);
-
- w32_clear_rect (f, hdc, &msg.rect);
- release_frame_dc (f, hdc);
+ /* Erase background again for safety. But don't do
+ that if the frame's 'garbaged' flag is set, since
+ in that case expose_frame will do nothing, and if
+ the various redisplay flags happen to be unset,
+ we are left with a blank frame. */
+
+ if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
+ {
+ HDC hdc = get_frame_dc (f);
+
+ w32_clear_rect (f, hdc, &msg.rect);
+ release_frame_dc (f, hdc);
+ }
+
+ expose_frame (f,
+ msg.rect.left,
+ msg.rect.top,
+ msg.rect.right - msg.rect.left,
+ msg.rect.bottom - msg.rect.top);
+ w32_clear_under_internal_border (f);
}
- expose_frame (f,
- msg.rect.left,
- msg.rect.top,
- msg.rect.right - msg.rect.left,
- msg.rect.bottom - msg.rect.top);
- w32_clear_under_internal_border (f);
+ else
+ w32_show_back_buffer (f);
}
}
break;
@@ -5295,7 +5435,18 @@ w32_read_socket (struct terminal *terminal,
window = window_from_coordinates (f, x, y, 0, 1, 1);
- if (EQ (window, f->tool_bar_window))
+ if (EQ (window, f->tool_bar_window)
+ /* Make sure the tool bar was previously
+ pressed, otherwise an event that started
+ outside of the tool bar will not be handled
+ correctly when the mouse button is
+ released. For example, start dragging to
+ select some buffer text, drag the mouse to
+ the tool bar, and release the mouse button
+ -- this should not consider the release
+ event as a tool-bar click. */
+ && (inev.modifiers & down_modifier
+ || f->last_tool_bar_item != -1))
{
w32_handle_tool_bar_click (f, &inev);
tool_bar_p = 1;
@@ -5412,6 +5563,7 @@ w32_read_socket (struct terminal *terminal,
case WM_WINDOWPOSCHANGED:
f = w32_window_to_frame (dpyinfo, msg.msg.hwnd);
+ ignore_dirty_back_buffer = true;
if (f)
{
@@ -5634,6 +5786,8 @@ w32_read_socket (struct terminal *terminal,
if (width != FRAME_PIXEL_WIDTH (f)
|| height != FRAME_PIXEL_HEIGHT (f))
{
+ w32_release_paint_buffer (f);
+
change_frame_size
(f, width, height, false, true, false);
SET_FRAME_GARBAGED (f);
@@ -5758,6 +5912,29 @@ w32_read_socket (struct terminal *terminal,
(short) HIWORD (msg.msg.lParam)));
}
+ /* According to the MS documentation, this message is sent
+ to each window whenever a monitor is added, removed, or
+ has its resolution change. Detect duplicate events when
+ there are multiple frames by ensuring only one event is
+ put in the keyboard buffer at any given time. */
+ {
+ union buffered_input_event *ev;
+
+ ev = (kbd_store_ptr == kbd_buffer
+ ? kbd_buffer + KBD_BUFFER_SIZE - 1
+ : kbd_store_ptr - 1);
+
+ if (kbd_store_ptr != kbd_fetch_ptr
+ && ev->ie.kind == MONITORS_CHANGED_EVENT
+ && XTERMINAL (ev->ie.arg) == dpyinfo->terminal)
+ /* Don't store a MONITORS_CHANGED_EVENT if there is
+ already an undelivered event on the queue. */
+ break;
+
+ inev.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (inev.arg, dpyinfo->terminal);
+ }
+
check_visibility = 1;
break;
@@ -5815,6 +5992,15 @@ w32_read_socket (struct terminal *terminal,
}
count++;
}
+
+ /* Event processing might have drawn to F outside redisplay. If
+ that is the case, flush any changes that have been made to
+ the front buffer. */
+
+ if (f && !w32_disable_double_buffering
+ && FRAME_OUTPUT_DATA (f)->paint_buffer_dirty
+ && !f->garbaged && !ignore_dirty_back_buffer)
+ w32_show_back_buffer (f);
}
/* If the focus was just given to an autoraising frame,
@@ -7029,6 +7215,9 @@ w32_free_frame_resources (struct frame *f)
face. */
free_frame_faces (f);
+ /* Now release the back buffer if any exists. */
+ w32_release_paint_buffer (f);
+
if (FRAME_W32_WINDOW (f))
my_destroy_window (f, FRAME_W32_WINDOW (f));
@@ -7325,6 +7514,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
terminal->update_end_hook = w32_update_end;
terminal->read_socket_hook = w32_read_socket;
terminal->frame_up_to_date_hook = w32_frame_up_to_date;
+ terminal->buffer_flipping_unblocked_hook = w32_buffer_flipping_unblocked_hook;
terminal->defined_color_hook = w32_defined_color;
terminal->query_frame_background_color = w32_query_frame_background_color;
terminal->query_colors = w32_query_colors;
@@ -7480,6 +7670,7 @@ w32_delete_display (struct w32_display_info *dpyinfo)
if (dpyinfo->palette)
DeleteObject (dpyinfo->palette);
}
+
w32_reset_fringes ();
}
@@ -7719,9 +7910,10 @@ The native image API library used is GDI+ via GDIPLUS.DLL. This
library is available only since W2K, therefore this variable is
unconditionally set to nil on older systems. */);
- /* For now, disabled by default, since this is an experimental feature. */
-#if 0 && HAVE_NATIVE_IMAGE_API
- if (os_subtype == OS_9X)
+ /* Disabled for Cygwin/w32 builds, since they don't link against
+ -lgdiplus, see configure.ac. */
+#if defined WINDOWSNT && HAVE_NATIVE_IMAGE_API
+ if (os_subtype == OS_SUBTYPE_9X)
w32_use_native_image_api = 0;
else
w32_use_native_image_api = 1;
diff --git a/src/w32term.h b/src/w32term.h
index 6c48323651f..88b7ec22bd1 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -412,6 +412,27 @@ struct w32_output
geometry when 'fullscreen' is reset to nil. */
WINDOWPLACEMENT normal_placement;
int prev_fsmode;
+
+ /* The back buffer if there is an ongoing double-buffered drawing
+ operation. */
+ HBITMAP paint_buffer;
+
+ /* The handle of the back buffer and a DC that ought to be released
+ alongside the back buffer. */
+ HDC paint_dc, paint_buffer_handle;
+
+ /* The object previously selected into `paint_dc'. */
+ HGDIOBJ paint_dc_object;
+
+ /* The width and height of `paint_buffer'. */
+ int paint_buffer_width, paint_buffer_height;
+
+ /* Whether or not some painting was done to this window that has not
+ yet been drawn. */
+ unsigned paint_buffer_dirty : 1;
+
+ /* Whether or not this frame should be double buffered. */
+ unsigned want_paint_buffer : 1;
};
extern struct w32_output w32term_display;
@@ -876,6 +897,8 @@ typedef char guichar_t;
extern Lisp_Object w32_popup_dialog (struct frame *, Lisp_Object, Lisp_Object);
extern void w32_arrow_cursor (void);
+extern void w32_release_paint_buffer (struct frame *);
+extern void w32_flip_buffers_if_dirty (struct frame *);
extern void syms_of_w32term (void);
extern void syms_of_w32menu (void);
diff --git a/src/w32xfns.c b/src/w32xfns.c
index d5974b906e8..22d39ae0037 100644
--- a/src/w32xfns.c
+++ b/src/w32xfns.c
@@ -136,13 +136,13 @@ select_palette (struct frame *f, HDC hdc)
f->output_data.w32->old_palette = NULL;
if (RealizePalette (hdc) != GDI_ERROR)
- {
- Lisp_Object frame, framelist;
- FOR_EACH_FRAME (framelist, frame)
{
- SET_FRAME_GARBAGED (XFRAME (frame));
+ Lisp_Object frame, framelist;
+ FOR_EACH_FRAME (framelist, frame)
+ {
+ SET_FRAME_GARBAGED (XFRAME (frame));
+ }
}
- }
}
void
@@ -157,19 +157,70 @@ deselect_palette (struct frame *f, HDC hdc)
HDC
get_frame_dc (struct frame *f)
{
- HDC hdc;
+ HDC hdc, paint_dc;
+ HBITMAP back_buffer;
+ HGDIOBJ obj;
+ struct w32_output *output;
if (f->output_method != output_w32)
emacs_abort ();
enter_crit ();
+ output = FRAME_OUTPUT_DATA (f);
+
+ if (output->paint_dc)
+ {
+ if (output->paint_buffer_width != FRAME_PIXEL_WIDTH (f)
+ || output->paint_buffer_height != FRAME_PIXEL_HEIGHT (f)
+ || w32_disable_double_buffering)
+ w32_release_paint_buffer (f);
+ else
+ {
+ output->paint_buffer_dirty = 1;
+ return output->paint_dc;
+ }
+ }
- hdc = GetDC (f->output_data.w32->window_desc);
+ hdc = GetDC (output->window_desc);
/* If this gets called during startup before the frame is valid,
there is a chance of corrupting random data or crashing. */
if (hdc)
- select_palette (f, hdc);
+ {
+ select_palette (f, hdc);
+
+ if (!w32_disable_double_buffering
+ && FRAME_OUTPUT_DATA (f)->want_paint_buffer)
+ {
+ back_buffer
+ = CreateCompatibleBitmap (hdc, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+
+ if (back_buffer)
+ {
+ paint_dc = CreateCompatibleDC (hdc);
+
+ if (!paint_dc)
+ DeleteObject (back_buffer);
+ else
+ {
+ obj = SelectObject (paint_dc, back_buffer);
+
+ output->paint_dc_object = obj;
+ output->paint_dc = paint_dc;
+ output->paint_buffer_handle = hdc;
+ output->paint_buffer = back_buffer;
+ output->paint_buffer_width = FRAME_PIXEL_WIDTH (f);
+ output->paint_buffer_height = FRAME_PIXEL_HEIGHT (f);
+ output->paint_buffer_dirty = 1;
+
+ SET_FRAME_GARBAGED (f);
+
+ return paint_dc;
+ }
+ }
+ }
+ }
return hdc;
}
@@ -179,8 +230,15 @@ release_frame_dc (struct frame *f, HDC hdc)
{
int ret;
- deselect_palette (f, hdc);
- ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
+ /* Avoid releasing the double-buffered DC here, since it'll be
+ released upon the next buffer flip instead. */
+ if (hdc != FRAME_OUTPUT_DATA (f)->paint_dc)
+ {
+ deselect_palette (f, hdc);
+ ret = ReleaseDC (f->output_data.w32->window_desc, hdc);
+ }
+ else
+ ret = 0;
leave_crit ();
diff --git a/src/widget.c b/src/widget.c
index c13ec504981..b125b4caeed 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -42,11 +42,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/ShellP.h>
#include "../lwlib/lwlib.h"
-static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
-static void EmacsFrameDestroy (Widget widget);
-static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
-static void EmacsFrameResize (Widget widget);
-static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
+static void EmacsFrameInitialize (Widget, Widget, ArgList, Cardinal *);
+static void EmacsFrameDestroy (Widget);
+static void EmacsFrameRealize (Widget, XtValueMask *, XSetWindowAttributes *);
+static void EmacsFrameResize (Widget);
+static void EmacsFrameExpose (Widget, XEvent *, Region);
+static XtGeometryResult EmacsFrameQueryGeometry (Widget, XtWidgetGeometry *,
+ XtWidgetGeometry *);
#define offset(field) offsetof (EmacsFrameRec, emacs_frame.field)
@@ -118,12 +120,12 @@ static EmacsFrameClassRec emacsFrameClassRec = {
/* resource_count */ XtNumber (resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
+ /* compress_exposure */ XtExposeNoCompress,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ EmacsFrameDestroy,
/* resize */ EmacsFrameResize,
- /* expose */ XtInheritExpose,
+ /* expose */ EmacsFrameExpose,
/* Emacs never does XtSetvalues on this widget, so we have no code
for it. */
@@ -156,33 +158,41 @@ static void
get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
{
struct frame *f = ew->emacs_frame.frame;
+
*pixel_width = FRAME_COLUMN_WIDTH (f);
*pixel_height = FRAME_LINE_HEIGHT (f);
}
static void
-pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
+pixel_to_char_size (EmacsFrame ew, Dimension pixel_width,
+ Dimension pixel_height, int *char_width, int *char_height)
{
struct frame *f = ew->emacs_frame.frame;
+
*char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
*char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
}
static void
-char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
+char_to_pixel_size (EmacsFrame ew, int char_width, int char_height,
+ Dimension *pixel_width, Dimension *pixel_height)
{
struct frame *f = ew->emacs_frame.frame;
+
*pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
*pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
}
static void
-round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
+round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height,
+ Dimension *out_width, Dimension *out_height)
{
int char_width;
int char_height;
- pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
- char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
+ pixel_to_char_size (ew, in_width, in_height,
+ &char_width, &char_height);
+ char_to_pixel_size (ew, char_width, char_height,
+ out_width, out_height);
}
static Widget
@@ -260,9 +270,8 @@ set_frame_size (EmacsFrame ew)
}
static void
-update_wm_hints (EmacsFrame ew)
+update_wm_hints (Widget wmshell, EmacsFrame ew)
{
- Widget wmshell = get_wm_shell ((Widget) ew);
int cw;
int ch;
Dimension rounded_width;
@@ -272,9 +281,6 @@ update_wm_hints (EmacsFrame ew)
int base_width;
int base_height;
- /* This happens when the frame is just created. */
- if (! wmshell) return;
-
pixel_to_char_size (ew, ew->core.width, ew->core.height,
&char_width, &char_height);
char_to_pixel_size (ew, char_width, char_height,
@@ -302,10 +308,9 @@ update_wm_hints (EmacsFrame ew)
}
void
-widget_update_wm_size_hints (Widget widget)
+widget_update_wm_size_hints (Widget widget, Widget frame)
{
- EmacsFrame ew = (EmacsFrame) widget;
- update_wm_hints (ew);
+ update_wm_hints (widget, (EmacsFrame) frame);
}
static void
@@ -339,7 +344,8 @@ update_from_various_frame_slots (EmacsFrame ew)
}
static void
-EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
+EmacsFrameInitialize (Widget request, Widget new,
+ ArgList dum1, Cardinal *dum2)
{
EmacsFrame ew = (EmacsFrame) new;
@@ -364,7 +370,8 @@ resize_cb (Widget widget,
static void
-EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
+EmacsFrameRealize (Widget widget, XtValueMask *mask,
+ XSetWindowAttributes *attrs)
{
EmacsFrame ew = (EmacsFrame) widget;
struct frame *f = ew->emacs_frame.frame;
@@ -386,7 +393,8 @@ EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs
frame_size_history_plain
(f, build_string ("EmacsFrameRealize"));
- update_wm_hints (ew);
+ if (get_wm_shell (widget))
+ update_wm_hints (get_wm_shell (widget), ew);
}
static void
@@ -408,9 +416,11 @@ EmacsFrameResize (Widget widget)
ew->core.width, ew->core.height,
f->new_width, f->new_height);
- change_frame_size (f, ew->core.width, ew->core.height, false, true, false);
+ change_frame_size (f, ew->core.width, ew->core.height,
+ false, true, false);
- update_wm_hints (ew);
+ if (get_wm_shell (widget))
+ update_wm_hints (get_wm_shell (widget), ew);
update_various_frame_slots (ew);
cancel_mouse_face (f);
@@ -465,6 +475,17 @@ EmacsFrameSetCharSize (Widget widget, int columns, int rows)
rows * FRAME_LINE_HEIGHT (f));
}
+static void
+EmacsFrameExpose (Widget widget, XEvent *event, Region region)
+{
+ EmacsFrame ew = (EmacsFrame) widget;
+ struct frame *f = ew->emacs_frame.frame;
+
+ expose_frame (f, event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+ flush_frame (f);
+}
+
void
widget_store_internal_border (Widget widget)
diff --git a/src/widget.h b/src/widget.h
index dbf21a64cb9..2906d5ff9ec 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -97,6 +97,6 @@ extern struct _DisplayContext *display_context;
/* Special entry points */
void EmacsFrameSetCharSize (Widget, int, int);
void widget_store_internal_border (Widget widget);
-void widget_update_wm_size_hints (Widget widget);
+void widget_update_wm_size_hints (Widget widget, Widget frame);
#endif /* _EmacsFrame_h */
diff --git a/src/window.c b/src/window.c
index 1e7c26b82e9..10373f8a2bf 100644
--- a/src/window.c
+++ b/src/window.c
@@ -481,7 +481,9 @@ Return WINDOW. */)
DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
doc: /* Return the selected window.
The selected window is the window in which the standard cursor for
-selected windows appears and to which many commands apply. */)
+selected windows appears and to which many commands apply.
+
+Also see `old-selected-window' and `minibuffer-selected-window'. */)
(void)
{
return selected_window;
@@ -1012,11 +1014,22 @@ WINDOW must be a valid window and defaults to the selected one. */)
return make_fixnum (decode_valid_window (window)->top_line);
}
+static enum window_body_unit
+window_body_unit_from_symbol (Lisp_Object unit)
+{
+ return
+ EQ (unit, Qremap)
+ ? WINDOW_BODY_IN_REMAPPED_CHARS
+ : (NILP (unit)
+ ? WINDOW_BODY_IN_CANONICAL_CHARS
+ : WINDOW_BODY_IN_PIXELS);
+}
+
/* Return the number of lines/pixels of W's body. Don't count any mode
or header line or horizontal divider of W. Rounds down to nearest
integer when not working pixelwise. */
static int
-window_body_height (struct window *w, bool pixelwise)
+window_body_height (struct window *w, enum window_body_unit pixelwise)
{
int height = (w->pixel_height
- WINDOW_TAB_LINE_HEIGHT (w)
@@ -1027,11 +1040,27 @@ window_body_height (struct window *w, bool pixelwise)
- WINDOW_MODE_LINE_HEIGHT (w)
- WINDOW_BOTTOM_DIVIDER_WIDTH (w));
+ int denom = 1;
+ if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
+ {
+ if (!NILP (Vface_remapping_alist))
+ {
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ int face_id = lookup_named_face (NULL, f, Qdefault, true);
+ struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
+ if (face && face->font && face->font->height)
+ denom = face->font->height;
+ }
+ /* For performance, use canonical chars if no face remapping. */
+ else
+ pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
+ }
+
+ if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
+ denom = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
+
/* Don't return a negative value. */
- return max (pixelwise
- ? height
- : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
- 0);
+ return max (height / denom, 0);
}
/* Return the number of columns/pixels of W's body. Don't count columns
@@ -1040,7 +1069,7 @@ window_body_height (struct window *w, bool pixelwise)
fringes either. Round down to nearest integer when not working
pixelwise. */
int
-window_body_width (struct window *w, bool pixelwise)
+window_body_width (struct window *w, enum window_body_unit pixelwise)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -1057,48 +1086,76 @@ window_body_width (struct window *w, bool pixelwise)
? WINDOW_FRINGES_WIDTH (w)
: 0));
+ int denom = 1;
+ if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
+ {
+ if (!NILP (Vface_remapping_alist))
+ {
+ int face_id = lookup_named_face (NULL, f, Qdefault, true);
+ struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
+ if (face && face->font)
+ {
+ if (face->font->average_width)
+ denom = face->font->average_width;
+ else if (face->font->space_width)
+ denom = face->font->space_width;
+ }
+ }
+ /* For performance, use canonical chars if no face remapping. */
+ else
+ pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
+ }
+
+ if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
+ denom = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+
/* Don't return a negative value. */
- return max (pixelwise
- ? width
- : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
- 0);
+ return max (width / denom, 0);
}
DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
doc: /* Return the width of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one. Optional
-argument PIXELWISE non-nil means return the width in pixels. The return
-value does not include any vertical dividers, fringes or marginal areas,
-or scroll bars.
+WINDOW must be a live window and defaults to the selected one. The
+return value does not include any vertical dividers, fringes or
+marginal areas, or scroll bars.
-If PIXELWISE is nil, return the largest integer smaller than WINDOW's
-pixel width divided by the character width of WINDOW's frame. This
-means that if a column at the right of the text area is only partially
-visible, that column is not counted.
+The optional argument PIXELWISE defines the units to use for the
+width. If nil, return the largest integer smaller than WINDOW's pixel
+width in units of the character width of WINDOW's frame. If PIXELWISE
+is `remap' and the default face is remapped (see
+`face-remapping-alist'), use the remapped face to determine the
+character width. For any other non-nil value, return the width in
+pixels.
Note that the returned value includes the column reserved for the
-continuation glyph. */)
+continuation glyph.
+
+Also see `window-max-chars-per-line'. */)
(Lisp_Object window, Lisp_Object pixelwise)
{
- return make_fixnum (window_body_width (decode_live_window (window),
- !NILP (pixelwise)));
+ return (make_fixnum
+ (window_body_width (decode_live_window (window),
+ window_body_unit_from_symbol (pixelwise))));
}
DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
doc: /* Return the height of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one. Optional
-argument PIXELWISE non-nil means return the height of WINDOW's text area
-in pixels. The return value does not include the mode line or header
-line or any horizontal divider.
-
-If PIXELWISE is nil, return the largest integer smaller than WINDOW's
-pixel height divided by the character height of WINDOW's frame. This
-means that if a line at the bottom of the text area is only partially
-visible, that line is not counted. */)
+WINDOW must be a live window and defaults to the selected one. The
+return value does not include the mode line or header line or any
+horizontal divider.
+
+The optional argument PIXELWISE defines the units to use for the
+height. If nil, return the largest integer smaller than WINDOW's
+pixel height in units of the character height of WINDOW's frame. If
+PIXELWISE is `remap' and the default face is remapped (see
+`face-remapping-alist'), use the remapped face to determine the
+character height. For any other non-nil value, return the height in
+pixels. */)
(Lisp_Object window, Lisp_Object pixelwise)
{
- return make_fixnum (window_body_height (decode_live_window (window),
- !NILP (pixelwise)));
+ return (make_fixnum
+ (window_body_height (decode_live_window (window),
+ window_body_unit_from_symbol (pixelwise))));
}
DEFUN ("window-old-body-pixel-width",
@@ -1232,7 +1289,7 @@ WINDOW must be a live window and defaults to the selected one.
Clip the number to a reasonable value if out of range.
Return the new number. NCOL should be zero or positive.
-Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
+Note that if `auto-hscroll-mode' is non-nil, you cannot scroll the
window so that the location of point moves off-window. */)
(Lisp_Object window, Lisp_Object ncol)
{
@@ -1690,6 +1747,14 @@ column 0. */)
0, false, false);
}
+ptrdiff_t
+window_point (struct window *w)
+{
+ return (w == XWINDOW (selected_window)
+ ? BUF_PT (XBUFFER (w->contents))
+ : XMARKER (w->pointm)->charpos);
+}
+
DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
doc: /* Return current value of point in WINDOW.
WINDOW must be a live window and defaults to the selected one.
@@ -1703,12 +1768,7 @@ correct to return the top-level value of `point', outside of any
`save-excursion' forms. But that is hard to define. */)
(Lisp_Object window)
{
- register struct window *w = decode_live_window (window);
-
- if (w == XWINDOW (selected_window))
- return make_fixnum (BUF_PT (XBUFFER (w->contents)));
- else
- return Fmarker_position (w->pointm);
+ return make_fixnum (window_point (decode_live_window (window)));
}
DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
@@ -1850,13 +1910,24 @@ Return POS. */)
DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
WINDOW must be a live window and defaults to the selected one. Return
-POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
-overriding motion of point in order to display at this exact start.
+POS.
+
+Optional third arg NOFORCE non-nil prevents next redisplay from
+moving point if displaying the window at POS makes point invisible;
+redisplay will then choose the WINDOW's start position by itself in
+that case, i.e. it will disregard POS if adhering to it will make
+point not visible in the window.
For reliable setting of WINDOW start position, make sure point is
at a position that will be visible when that start is in effect,
otherwise there's a chance POS will be disregarded, e.g., if point
-winds up in a partially-visible line. */)
+winds up in a partially-visible line.
+
+The setting of the WINDOW's start position takes effect during the
+next redisplay cycle, not immediately. If NOFORCE is nil or
+omitted, forcing the display of WINDOW to start at POS cancels
+any setting of WINDOW's vertical scroll (\"vscroll\") amount
+set by `set-window-vscroll' and by scrolling functions. */)
(Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
{
register struct window *w = decode_live_window (window);
@@ -2106,7 +2177,8 @@ though when run from an idle timer with a delay of zero seconds. */)
struct glyph_row *row, *end_row;
int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
Lisp_Object rows = Qnil;
- int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
+ int window_width = NILP (body)
+ ? w->pixel_width : window_body_width (w, WINDOW_BODY_IN_PIXELS);
int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height);
@@ -2574,7 +2646,7 @@ window_list (void)
if (!CONSP (Vwindow_list))
{
Lisp_Object tail, frame;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Vwindow_list = Qnil;
/* Don't allow quitting in Fnconc. Otherwise we might end up
@@ -2714,7 +2786,7 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object
? miniwin : Qnil);
else if (EQ (*all_frames, Qvisible))
;
- else if (EQ (*all_frames, make_fixnum (0)))
+ else if (BASE_EQ (*all_frames, make_fixnum (0)))
;
else if (FRAMEP (*all_frames))
;
@@ -2732,7 +2804,7 @@ static Lisp_Object
next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
bool next_p)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
decode_next_window_args (&window, &minibuf, &all_frames);
@@ -2886,7 +2958,7 @@ static Lisp_Object
window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
{
Lisp_Object tail, list, rest;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
decode_next_window_args (&window, &minibuf, &all_frames);
list = Qnil;
@@ -3011,7 +3083,7 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini,
if (f)
frame_arg = Qlambda;
- else if (EQ (frames, make_fixnum (0)))
+ else if (BASE_EQ (frames, make_fixnum (0)))
frame_arg = frames;
else if (EQ (frames, Qvisible))
frame_arg = frames;
@@ -3179,14 +3251,6 @@ resize_root_window (Lisp_Object window, Lisp_Object delta,
horizontal, ignore, pixelwise);
}
-void
-sanitize_window_sizes (Lisp_Object horizontal)
-{
- /* Don't burp in temacs -nw before window.el is loaded. */
- if (!NILP (Fsymbol_function (Qwindow__sanitize_window_sizes)))
- call1 (Qwindow__sanitize_window_sizes, horizontal);
-}
-
static Lisp_Object
window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
@@ -3505,7 +3569,7 @@ select_frame_norecord (Lisp_Object frame)
static void
run_window_configuration_change_hook (struct frame *f)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object frame, global_wcch
= Fdefault_value (Qwindow_configuration_change_hook);
XSETFRAME (frame, f);
@@ -3538,7 +3602,7 @@ run_window_configuration_change_hook (struct frame *f)
if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
buffer)))
{
- ptrdiff_t inner_count = SPECPDL_INDEX ();
+ specpdl_ref inner_count = SPECPDL_INDEX ();
record_unwind_protect (select_window_norecord, selected_window);
select_window_norecord (window);
run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
@@ -3575,7 +3639,7 @@ has established the size of the new window. */)
(Lisp_Object window)
{
struct window *w = decode_live_window (window);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_current_buffer ();
Fset_buffer (w->contents);
@@ -3647,8 +3711,10 @@ window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
wset_old_buffer (w, w->contents);
w->old_pixel_width = w->pixel_width;
w->old_pixel_height = w->pixel_height;
- w->old_body_pixel_width = window_body_width (w, true);
- w->old_body_pixel_height = window_body_height (w, true);
+ w->old_body_pixel_width
+ = window_body_width (w, WINDOW_BODY_IN_PIXELS);
+ w->old_body_pixel_height
+ = window_body_height (w, WINDOW_BODY_IN_PIXELS);
}
w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -3815,7 +3881,7 @@ run_window_change_functions (void)
Lisp_Object tail, frame;
bool selected_frame_change = !EQ (selected_frame, old_selected_frame);
bool run_window_state_change_hook = false;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
window_change_record_frames = false;
record_unwind_protect_void (window_change_record);
@@ -3893,8 +3959,10 @@ run_window_change_functions (void)
&& (window_buffer_change
|| w->pixel_width != w->old_pixel_width
|| w->pixel_height != w->old_pixel_height
- || window_body_width (w, true) != w->old_body_pixel_width
- || window_body_height (w, true) != w->old_body_pixel_height));
+ || (window_body_width (w, WINDOW_BODY_IN_PIXELS)
+ != w->old_body_pixel_width)
+ || (window_body_height (w, WINDOW_BODY_IN_PIXELS)
+ != w->old_body_pixel_height)));
/* The following two are needed when running the default
values for this frame below. */
@@ -4012,7 +4080,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
{
struct window *w = XWINDOW (window);
struct buffer *b = XBUFFER (buffer);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool samebuf = EQ (buffer, w->contents);
wset_buffer (w, buffer);
@@ -4232,7 +4300,7 @@ temp_output_buffer_show (register Lisp_Object buf)
/* Run temp-buffer-show-hook, with the chosen window selected
and its buffer current. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object prev_window, prev_buffer;
prev_window = selected_window;
XSETBUFFER (prev_buffer, old);
@@ -4758,7 +4826,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
Lisp_Object mini = f->minibuffer_window;
struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL;
int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
- ? unit + m->pixel_height - window_body_height (m, true)
+ ? (unit + m->pixel_height
+ - window_body_height (m, WINDOW_BODY_IN_PIXELS))
: 0);
new_pixel_size = max (horflag ? size : size - mini_height, unit);
@@ -5245,7 +5314,7 @@ void
grow_mini_window (struct window *w, int delta)
{
struct frame *f = XFRAME (w->frame);
- int old_height = window_body_height (w, true);
+ int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS);
int min_height = FRAME_LINE_HEIGHT (f);
eassert (MINI_WINDOW_P (w));
@@ -5279,7 +5348,8 @@ void
shrink_mini_window (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- int delta = window_body_height (w, true) - FRAME_LINE_HEIGHT (f);
+ int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS)
+ - FRAME_LINE_HEIGHT (f));
eassert (MINI_WINDOW_P (w));
@@ -5486,7 +5556,7 @@ window_internal_height (struct window *w)
static void
window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
n = clip_to_bounds (INT_MIN, n, INT_MAX);
@@ -5498,7 +5568,11 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
/* On GUI frames, use the pixel-based version which is much slower
than the line-based one but can handle varying line heights. */
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
- window_scroll_pixel_based (window, n, whole, noerror);
+ {
+ record_unwind_protect_void (unwind_display_working_on_window);
+ display_working_on_window_p = true;
+ window_scroll_pixel_based (window, n, whole, noerror);
+ }
else
window_scroll_line_based (window, n, whole, noerror);
@@ -5626,7 +5700,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
if (w->vscroll < 0 && rtop > 0)
{
px = max (0, -w->vscroll - min (rtop, -dy));
- Fset_window_vscroll (window, make_fixnum (px), Qt);
+ Fset_window_vscroll (window, make_fixnum (px), Qt,
+ Qnil);
return;
}
}
@@ -5636,7 +5711,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
{
px = max (0, -w->vscroll + min (rbot, dy));
- Fset_window_vscroll (window, make_fixnum (px), Qt);
+ Fset_window_vscroll (window, make_fixnum (px), Qt,
+ Qnil);
return;
}
@@ -5645,7 +5721,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
{
ptrdiff_t spos;
- Fset_window_vscroll (window, make_fixnum (0), Qt);
+ Fset_window_vscroll (window, make_fixnum (0), Qt,
+ Qnil);
/* If there are other text lines above the current row,
move window start to current row. Else to next row. */
if (rbot > 0)
@@ -5664,7 +5741,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
}
}
/* Cancel previous vscroll. */
- Fset_window_vscroll (window, make_fixnum (0), Qt);
+ Fset_window_vscroll (window, make_fixnum (0), Qt, Qnil);
}
itdata = bidi_shelve_cache ();
@@ -5861,7 +5938,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
/* We moved the window start towards ZV, so PT may be now
in the scroll margin at the top. */
- move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ if (IT_CHARPOS (it) < PT)
+ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
if (IT_CHARPOS (it) == PT
&& it.current_y >= this_scroll_margin
&& it.current_y <= last_y - WINDOW_TAB_LINE_HEIGHT (w)
@@ -6211,7 +6289,7 @@ scroll_command (Lisp_Object window, Lisp_Object n, int direction)
{
struct window *w;
bool other_window;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
eassert (eabs (direction) == 1);
@@ -6307,10 +6385,12 @@ followed by all visible frames on the current terminal. */)
if (NILP (window))
window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
}
+ else if (FUNCTIONP (Vother_window_scroll_default))
+ /* Nothing specified; try to get a window from the function. */
+ window = call0 (Vother_window_scroll_default);
else
{
- /* Nothing specified; look for a neighboring window on the same
- frame. */
+ /* Otherwise, look for a neighboring window on the same frame. */
window = Fnext_window (selected_window, Qlambda, Qnil);
if (EQ (window, selected_window))
@@ -6327,34 +6407,6 @@ followed by all visible frames on the current terminal. */)
return window;
}
-DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
- doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
-A near full screen is `next-screen-context-lines' less than a full screen.
-Negative ARG means scroll downward. If ARG is the atom `-', scroll
-downward by nearly full screen. When calling from a program, supply
-as argument a number, nil, or `-'.
-
-The next window is usually the one below the current one;
-or the one at the top if the current one is at the bottom.
-It is determined by the function `other-window-for-scrolling',
-which see. */)
- (Lisp_Object arg)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
- scroll_command (Fother_window_for_scrolling (), arg, 1);
- return unbind_to (count, Qnil);
-}
-
-DEFUN ("scroll-other-window-down", Fscroll_other_window_down,
- Sscroll_other_window_down, 0, 1, "P",
- doc: /* Scroll next window downward ARG lines; or near full screen if no ARG.
-For more details, see the documentation for `scroll-other-window'. */)
- (Lisp_Object arg)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
- scroll_command (Fother_window_for_scrolling (), arg, -1);
- return unbind_to (count, Qnil);
-}
DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
doc: /* Scroll selected window display ARG columns left.
@@ -6368,9 +6420,10 @@ by this function. This happens in an interactive call. */)
(register Lisp_Object arg, Lisp_Object set_minimum)
{
struct window *w = XWINDOW (selected_window);
- EMACS_INT requested_arg = (NILP (arg)
- ? window_body_width (w, 0) - 2
- : XFIXNUM (Fprefix_numeric_value (arg)));
+ EMACS_INT requested_arg =
+ (NILP (arg)
+ ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
+ : XFIXNUM (Fprefix_numeric_value (arg)));
Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
if (!NILP (set_minimum))
@@ -6393,9 +6446,10 @@ by this function. This happens in an interactive call. */)
(register Lisp_Object arg, Lisp_Object set_minimum)
{
struct window *w = XWINDOW (selected_window);
- EMACS_INT requested_arg = (NILP (arg)
- ? window_body_width (w, 0) - 2
- : XFIXNUM (Fprefix_numeric_value (arg)));
+ EMACS_INT requested_arg =
+ (NILP (arg)
+ ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
+ : XFIXNUM (Fprefix_numeric_value (arg)));
Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
if (!NILP (set_minimum))
@@ -6446,9 +6500,14 @@ displayed_window_lines (struct window *w)
CLIP_TEXT_POS_FROM_MARKER (start, w->start);
itdata = bidi_shelve_cache ();
+
+ specpdl_ref count = SPECPDL_INDEX ();
+ record_unwind_protect_void (unwind_display_working_on_window);
+ display_working_on_window_p = true;
start_display (&it, w, start);
move_it_vertically (&it, height);
bottom_y = line_bottom_y (&it);
+ unbind_to (count, Qnil);
bidi_unshelve_cache (itdata, false);
/* Add in empty lines at the bottom of the window. */
@@ -6542,6 +6601,10 @@ and redisplay normally--don't erase and redraw the frame. */)
data structures might not be set up yet then. */
if (!FRAME_INITIAL_P (XFRAME (w->frame)))
{
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ record_unwind_protect_void (unwind_display_working_on_window);
+ display_working_on_window_p = true;
if (center_p)
{
struct it it;
@@ -6604,6 +6667,7 @@ and redisplay normally--don't erase and redraw the frame. */)
if (h <= 0)
{
bidi_unshelve_cache (itdata, false);
+ unbind_to (count, Qnil);
return Qnil;
}
@@ -6658,6 +6722,7 @@ and redisplay normally--don't erase and redraw the frame. */)
bidi_unshelve_cache (itdata, false);
}
+ unbind_to (count, Qnil);
}
else
{
@@ -6851,6 +6916,7 @@ struct saved_window
Lisp_Object left_col, top_line, total_cols, total_lines;
Lisp_Object normal_cols, normal_lines;
Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
+ Lisp_Object vscroll;
Lisp_Object parent, prev;
Lisp_Object start_at_line_beg;
Lisp_Object display_table;
@@ -7078,6 +7144,7 @@ the return value is nil. Otherwise the value is t. */)
w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
w->min_hscroll = XFIXNAT (p->min_hscroll);
w->hscroll_whole = XFIXNAT (p->hscroll_whole);
+ w->vscroll = -XFIXNAT (p->vscroll);
wset_display_table (w, p->display_table);
w->left_margin_cols = XFIXNUM (p->left_margin_cols);
w->right_margin_cols = XFIXNUM (p->right_margin_cols);
@@ -7232,7 +7299,7 @@ the return value is nil. Otherwise the value is t. */)
do_switch_frame (NILP (dont_set_frame)
? data->selected_frame
: old_frame
- , 0, 0, Qnil);
+ , 0, Qnil);
}
FRAME_WINDOW_CHANGE (f) = true;
@@ -7412,6 +7479,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
XSETFASTINT (p->min_hscroll, w->min_hscroll);
XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
+ XSETFASTINT (p->vscroll, -w->vscroll);
p->display_table = w->display_table;
p->left_margin_cols = make_fixnum (w->left_margin_cols);
p->right_margin_cols = make_fixnum (w->right_margin_cols);
@@ -7443,7 +7511,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
hare = XCDR (hare);
tortoise = XCDR (tortoise);
- if (EQ (hare, tortoise))
+ if (BASE_EQ (hare, tortoise))
/* Reset Vwindow_persistent_parameters to Qnil. */
{
Vwindow_persistent_parameters = Qnil;
@@ -7959,7 +8027,7 @@ optional second arg PIXELS-P means value is measured in pixels. */)
DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
- 2, 3, 0,
+ 2, 4, 0,
doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
This takes effect when displaying tall lines or images.
@@ -7969,8 +8037,12 @@ optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
If PIXELS-P is nil, VSCROLL may have to be rounded so that it
corresponds to an integral number of pixels. The return value is the
result of this rounding.
-If PIXELS-P is non-nil, the return value is VSCROLL. */)
- (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
+If PIXELS-P is non-nil, the return value is VSCROLL.
+
+PRESERVE-VSCROLL-P makes setting the start of WINDOW preserve the
+vscroll if its start is "frozen" due to a resized mini-window. */)
+ (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p,
+ Lisp_Object preserve_vscroll_p)
{
struct window *w = decode_live_window (window);
struct frame *f = XFRAME (w->frame);
@@ -7995,7 +8067,12 @@ If PIXELS-P is non-nil, the return value is VSCROLL. */)
/* Prevent redisplay shortcuts. */
XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
+
+ /* Mark W for redisplay. (bug#55299) */
+ wset_redisplay (w);
}
+
+ w->preserve_vscroll_p = !NILP (preserve_vscroll_p);
}
return Fwindow_vscroll (window, pixels_p);
@@ -8124,11 +8201,11 @@ compare_window_configurations (Lisp_Object configuration1,
return true;
}
-DEFUN ("compare-window-configurations", Fcompare_window_configurations,
- Scompare_window_configurations, 2, 2, 0,
- doc: /* Compare two window configurations as regards the structure of windows.
-This function ignores details such as the values of point
-and scrolling positions. */)
+DEFUN ("window-configuration-equal-p", Fwindow_configuration_equal_p,
+ Swindow_configuration_equal_p, 2, 2, 0,
+ doc: /* Say whether two window configurations have the same window layout.
+This function ignores details such as the values of point and
+scrolling positions. */)
(Lisp_Object x, Lisp_Object y)
{
if (compare_window_configurations (x, y))
@@ -8227,7 +8304,6 @@ syms_of_window (void)
DEFSYM (Qwindow__resize_root_window_vertically,
"window--resize-root-window-vertically");
DEFSYM (Qwindow__resize_mini_frame, "window--resize-mini-frame");
- DEFSYM (Qwindow__sanitize_window_sizes, "window--sanitize-window-sizes");
DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
DEFSYM (Qsafe, "safe");
DEFSYM (Qdisplay_buffer, "display-buffer");
@@ -8268,6 +8344,14 @@ is displayed in the `mode-line' face. */);
doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
Vother_window_scroll_buffer = Qnil;
+ DEFVAR_LISP ("other-window-scroll-default", Vother_window_scroll_default,
+ doc: /* Function that provides the window to scroll by \\[scroll-other-window].
+The function `other-window-for-scrolling' first tries to use
+`minibuffer-scroll-window' and `other-window-scroll-buffer'.
+But when both are nil, then by default it uses a neighboring window.
+This variable is intended to get another default instead of `next-window'. */);
+ Vother_window_scroll_default = Qnil;
+
DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
auto_window_vscroll_p = true;
@@ -8327,7 +8411,10 @@ In this case the window is passed as argument.
Functions specified by the default value are called for each frame if
at least one window on that frame has been added or changed its buffer
or its total or body size since the last redisplay. In this case the
-frame is passed as argument. */);
+frame is passed as argument.
+
+For instance, to hide the title bar when the frame is maximized, you
+can add `frame-hide-title-bar-when-maximized' to this variable. */);
Vwindow_size_change_functions = Qnil;
DEFVAR_LISP ("window-selection-change-functions", Vwindow_selection_change_functions,
@@ -8589,8 +8676,6 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
defsubr (&Sscroll_left);
defsubr (&Sscroll_right);
defsubr (&Sother_window_for_scrolling);
- defsubr (&Sscroll_other_window);
- defsubr (&Sscroll_other_window_down);
defsubr (&Sminibuffer_selected_window);
defsubr (&Srecenter);
defsubr (&Swindow_text_width);
@@ -8608,7 +8693,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
defsubr (&Swindow_scroll_bars);
defsubr (&Swindow_vscroll);
defsubr (&Sset_window_vscroll);
- defsubr (&Scompare_window_configurations);
+ defsubr (&Swindow_configuration_equal_p);
defsubr (&Swindow_bump_use_time);
defsubr (&Swindow_list);
defsubr (&Swindow_list_1);
diff --git a/src/window.h b/src/window.h
index 141c29e8100..298a80a5366 100644
--- a/src/window.h
+++ b/src/window.h
@@ -445,6 +445,10 @@ struct window
window. */
bool_bf suspend_auto_hscroll : 1;
+ /* True if vscroll should be preserved while forcing the start due
+ to a frozen window. */
+ bool_bf preserve_vscroll_p : 1;
+
/* Amount by which lines of this window are scrolled in
y-direction (smooth scrolling). */
int vscroll;
@@ -1182,16 +1186,22 @@ extern bool window_wants_mode_line (struct window *);
extern bool window_wants_header_line (struct window *);
extern bool window_wants_tab_line (struct window *);
extern int window_internal_height (struct window *);
-extern int window_body_width (struct window *w, bool);
+enum window_body_unit
+ {
+ WINDOW_BODY_IN_CANONICAL_CHARS,
+ WINDOW_BODY_IN_PIXELS,
+ WINDOW_BODY_IN_REMAPPED_CHARS
+ };
+extern int window_body_width (struct window *w, enum window_body_unit);
enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
extern int window_scroll_margin (struct window *, enum margin_unit);
extern void temp_output_buffer_show (Lisp_Object);
extern void replace_buffer_in_windows (Lisp_Object);
extern void replace_buffer_in_windows_safely (Lisp_Object);
-extern void sanitize_window_sizes (Lisp_Object horizontal);
/* This looks like a setter, but it is a bit special. */
extern void wset_buffer (struct window *, Lisp_Object);
extern bool window_outdated (struct window *);
+extern ptrdiff_t window_point (struct window *w);
extern void init_window_once (void);
extern void init_window (void);
extern void syms_of_window (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index 2326df4300d..4089525e10f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -741,10 +741,6 @@ int update_mode_lines;
static bool line_number_displayed;
-/* The name of the *Messages* buffer, a string. */
-
-static Lisp_Object Vmessages_buffer_name;
-
/* Current, index 0, and last displayed echo area message. Either
buffers from echo_buffers, or nil to indicate no message. */
@@ -774,7 +770,7 @@ static bool message_buf_print;
static bool message_cleared_p;
/* A scratch glyph row with contents used for generating truncation
- glyphs. Also used in direct_output_for_insert. */
+ glyphs and overlay-arrow glyphs. */
#define MAX_SCRATCH_GLYPHS 100
static struct glyph_row scratch_glyph_row;
@@ -836,7 +832,7 @@ void
wset_redisplay (struct window *w)
{
/* Beware: selected_window can be nil during early stages. */
- if (!EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
+ if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
redisplay_other_windows ();
w->redisplay = true;
}
@@ -1034,6 +1030,15 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
bool redisplaying_p;
+/* True while some display-engine code is working on layout of some
+ window.
+
+ WARNING: Use sparingly, preferably only in top level of commands
+ and important functions, because using it in nested calls might
+ reset the flag when the inner call returns, behind the back of
+ the callers. */
+bool display_working_on_window_p;
+
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
@@ -3002,7 +3007,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
else
{
ptrdiff_t i;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object *args;
USE_SAFE_ALLOCA;
SAFE_ALLOCA_LISP (args, nargs);
@@ -3226,6 +3231,9 @@ init_iterator (struct it *it, struct window *w,
it->cmp_it.id = -1;
+ if (max_redisplay_ticks > 0)
+ update_redisplay_ticks (0, w);
+
/* Extra space between lines (on window systems only). */
if (base_face_id == DEFAULT_FACE_ID
&& FRAME_WINDOW_P (it->f))
@@ -3988,6 +3996,12 @@ compute_stop_pos (struct it *it)
pos = next_overlay_change (charpos);
if (pos < it->stop_charpos)
it->stop_charpos = pos;
+ /* If we are breaking compositions at point, stop at point. */
+ if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
+ && !NILP (Vauto_composition_mode)
+ && composition_break_at_point
+ && charpos < PT && PT < it->stop_charpos)
+ it->stop_charpos = PT;
/* Set up variables for computing the stop position from text
property changes. */
@@ -3999,7 +4013,8 @@ compute_stop_pos (struct it *it)
chunks. We play safe here by assuming that only SPC, TAB,
FF, and NL cannot be in some composition; in particular, most
ASCII punctuation characters could be composed into ligatures. */
- if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
+ if (!composition_break_at_point
+ && !NILP (BVAR (current_buffer, enable_multibyte_characters))
&& !NILP (Vauto_composition_mode))
{
ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
@@ -4308,7 +4323,7 @@ handle_fontified_prop (struct it *it)
no amount of fontifying will be able to change it. */
NILP (prop) && IT_CHARPOS (*it) < Z))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
struct buffer *obuf = current_buffer;
ptrdiff_t begv = BEGV, zv = ZV;
@@ -4503,7 +4518,7 @@ face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
static enum prop_handled
handle_face_prop (struct it *it)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Don't allow the user to quit out of face-merging code, in case
this is called when redisplaying a non-selected window, with
point temporarily moved to window-point. */
@@ -5548,7 +5563,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
form = Qnil;
if (!NILP (form) && !EQ (form, Qt))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Bind `object' to the object having the `display' property, a
buffer or string. Bind `position' to the position in the
@@ -5625,7 +5640,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
{
/* Evaluate IT->font_height with `height' bound to the
current specified height to get the new height. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct face *face = FACE_FROM_ID (it->f, it->face_id);
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
@@ -5826,7 +5841,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
/* Don't allow quitting from lookup_derived_face, for when
we are displaying a non-selected window, and the buffer's
point was temporarily moved to the window-point. */
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
face_id2 = lookup_derived_face (it->w, it->f, face_name,
FRINGE_FACE_ID, false);
@@ -5891,7 +5906,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
location = tem;
}
- if (EQ (location, Qunbound))
+ if (BASE_EQ (location, Qunbound))
{
location = Qnil;
value = spec;
@@ -5999,7 +6014,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
#ifdef HAVE_WINDOW_SYSTEM
else
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
it->what = IT_IMAGE;
/* Don't allow quitting from lookup_image, for when we are
@@ -8172,6 +8187,9 @@ void
set_iterator_to_next (struct it *it, bool reseat_p)
{
+ if (max_redisplay_ticks > 0)
+ update_redisplay_ticks (1, it->w);
+
switch (it->method)
{
case GET_FROM_BUFFER:
@@ -9190,7 +9208,19 @@ next_element_from_buffer (struct it *it)
&& IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
run_redisplay_end_trigger_hook (it);
- stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
+ if (composition_break_at_point
+ && !NILP (BVAR (current_buffer, enable_multibyte_characters))
+ && !NILP (Vauto_composition_mode))
+ {
+ /* Limit search for composable characters to point's position. */
+ if (it->bidi_it.scan_dir < 0)
+ stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
+ else
+ stop = (IT_CHARPOS (*it) < PT
+ && PT < it->end_charpos) ? PT : it->end_charpos;
+ }
+ else
+ stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
stop)
&& next_element_from_composition (it))
@@ -9895,6 +9925,18 @@ move_it_in_display_line_to (struct it *it,
}
else
result = MOVE_NEWLINE_OR_CR;
+ /* If lines are truncated, and the line we moved across is
+ completely hscrolled out of view, reset the line metrics
+ to those of the newline we've just processed, so that
+ glyphs not on display don't affect the line's height. */
+ if (it->line_wrap == TRUNCATE
+ && it->current_x <= it->first_visible_x
+ && result == MOVE_NEWLINE_OR_CR
+ && it->char_to_display == '\n')
+ {
+ it->max_ascent = it->ascent;
+ it->max_descent = it->descent;
+ }
/* If we've processed the newline, make sure this flag is
reset, as it must only be set when the newline itself is
processed. */
@@ -10216,7 +10258,8 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
could have both positions after TO_CHARPOS or
both positions before it, due to bidi
reordering.) */
- if (IT_CHARPOS (*it) != to_charpos
+ if (to_charpos > 0
+ && IT_CHARPOS (*it) != to_charpos
&& ((IT_CHARPOS (it_backup) > to_charpos)
== (IT_CHARPOS (*it) > to_charpos)))
{
@@ -10929,6 +10972,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
max_y = XFIXNUM (y_limit);
itdata = bidi_shelve_cache ();
+
start_display (&it, w, startp);
int start_y = it.current_y;
@@ -10941,6 +10985,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
same directionality. */
it.bidi_p = false;
+ int start_x;
if (vertical_offset != 0)
{
int last_y;
@@ -10974,6 +11019,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
+ WINDOW_HEADER_LINE_HEIGHT (w));
start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
start_y = it.current_y;
+ start_x = it.current_x;
}
else
{
@@ -10983,11 +11029,52 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = 0;
if (IT_CHARPOS (it) != start)
- move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+ {
+ void *it1data = NULL;
+ struct it it1;
+
+ SAVE_IT (it1, it, it1data);
+ move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+ /* We could have a display property at START, in which case
+ asking move_it_to to stop at START will overshoot and
+ stop at position after START. So we try again, stopping
+ before START, and account for the width of the last
+ buffer position manually. */
+ if (IT_CHARPOS (it) > start && start > BEGV)
+ {
+ ptrdiff_t it1pos = IT_CHARPOS (it1);
+ int it1_x = it1.current_x;
+
+ RESTORE_IT (&it, &it1, it1data);
+ /* If START - 1 is the beginning of screen line,
+ move_it_to will not move, so we need to use a
+ lower-level move_it_in_display_line subroutine, and
+ tell it to move just 1 pixel, so it stops at the next
+ display element. */
+ if (start - 1 > it1pos)
+ move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
+ else
+ move_it_in_display_line (&it, start, it1_x + 1,
+ MOVE_TO_POS | MOVE_TO_X);
+ move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
+ start_x = it.current_x;
+ /* If we didn't change our buffer position, the pixel
+ width of what's here was not yet accounted for; do it
+ manually. */
+ if (IT_CHARPOS (it) == start - 1)
+ start_x += it.pixel_width;
+ }
+ else
+ {
+ start_x = it.current_x;
+ bidi_unshelve_cache (it1data, true);
+ }
+ }
+ else
+ start_x = it.current_x;
}
/* Now move to TO. */
- int start_x = it.current_x;
int move_op = MOVE_TO_POS | MOVE_TO_Y;
int to_x = -1;
it.current_y = start_y;
@@ -11163,7 +11250,7 @@ argument if the size of the buffer is large or unknown.
Optional argument MODE-LINES nil or omitted means do not include the
height of the mode-, tab- or header-line of WINDOW in the return value.
-If it is the symbol `mode-line', 'tab-line' or `header-line', include
+If it is the symbol `mode-line', `tab-line' or `header-line', include
only the height of that line, if present, in the return value. If t,
include the height of any of these, if present, in the return value.
@@ -11215,7 +11302,7 @@ WINDOW. */)
? current_buffer
: XBUFFER (Fget_buffer (buffer_or_name)));
Lisp_Object buffer, value;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
XSETBUFFER (buffer, b);
@@ -11377,6 +11464,10 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
old_deactivate_mark = Vdeactivate_mark;
oldbuf = current_buffer;
+ /* Sanity check, in case the variable has been set to something
+ invalid. */
+ if (! STRINGP (Vmessages_buffer_name))
+ Vmessages_buffer_name = build_string ("*Messages*");
/* Ensure the Messages buffer exists, and switch to it.
If we created it, set the major-mode. */
bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
@@ -11447,7 +11538,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
we aren't prepared to run modification hooks (we could
end up calling modification hooks from another buffer and
only with AFTER=t, Bug#21824). */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_modification_hooks, Qt);
insert_1_both ("\n", 1, 1, true, false, false);
@@ -11902,7 +11993,7 @@ with_echo_area_buffer (struct window *w, int which,
{
Lisp_Object buffer;
bool this_one, the_other, clear_buffer_p, rc;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* If buffers aren't live, make new ones. */
ensure_echo_area_buffers ();
@@ -12068,7 +12159,7 @@ setup_echo_area_for_printing (bool multibyte_p)
{
/* If we can't find an echo area any more, exit. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
ensure_echo_area_buffers ();
@@ -12087,7 +12178,7 @@ setup_echo_area_for_printing (bool multibyte_p)
if (Z > BEG)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_read_only, Qt);
/* Note that undo recording is always disabled. */
del_range (BEG, Z);
@@ -12155,7 +12246,7 @@ display_echo_area (struct window *w)
That message would modify the echo area buffer's contents while a
redisplay of the buffer is going on, and seriously confuse
redisplay. */
- ptrdiff_t count = inhibit_garbage_collection ();
+ specpdl_ref count = inhibit_garbage_collection ();
/* If there is no message, we must call display_echo_area_1
nevertheless because it resizes the window. But we will have to
@@ -12535,7 +12626,7 @@ set_message (Lisp_Object string)
if (FUNCTIONP (Vset_message_function))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
message = safe_call1 (Vset_message_function, string);
unbind_to (count, Qnil);
@@ -12606,18 +12697,23 @@ set_message_1 (void *a1, Lisp_Object string)
void
clear_message (bool current_p, bool last_displayed_p)
{
+ Lisp_Object preserve = Qnil;
+
if (current_p)
{
- echo_area_buffer[0] = Qnil;
- message_cleared_p = true;
-
if (FUNCTIONP (Vclear_message_function))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- safe_call (1, Vclear_message_function);
+ preserve = safe_call (1, Vclear_message_function);
unbind_to (count, Qnil);
}
+
+ if (!EQ (preserve, Qdont_clear_message))
+ {
+ echo_area_buffer[0] = Qnil;
+ message_cleared_p = true;
+ }
}
if (last_displayed_p)
@@ -12748,7 +12844,7 @@ echo_area_display (bool update_frame_p)
/* Must update other windows. Likewise as in other
cases, don't let this update be interrupted by
pending input. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qredisplay_dont_pause, Qt);
fset_redisplay (f);
redisplay_internal ();
@@ -13068,7 +13164,7 @@ store_mode_line_noprop (const char *string, int field_width, int precision)
Vicon_title_format if FRAME is iconified, otherwise it is
frame_title_format. */
-static void
+void
gui_consider_frame_title (Lisp_Object frame)
{
struct frame *f = XFRAME (frame);
@@ -13084,7 +13180,7 @@ gui_consider_frame_title (Lisp_Object frame)
char *title;
ptrdiff_t len;
struct it it;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
FOR_EACH_FRAME (tail, other_frame)
{
@@ -13120,8 +13216,9 @@ gui_consider_frame_title (Lisp_Object frame)
mode_line_noprop_buf; then display the title. */
record_unwind_protect (unwind_format_mode_line,
format_mode_line_unwind_data
- (NULL, current_buffer, Qnil, false));
+ (f, current_buffer, selected_window, false));
+ Fselect_window (f->selected_window, Qt);
set_buffer_internal_1
(XBUFFER (XWINDOW (f->selected_window)->contents));
fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
@@ -13170,6 +13267,20 @@ gui_consider_frame_title (Lisp_Object frame)
&& (update_mode_lines == 0 \
|| update_mode_lines == REDISPLAY_SOME))
+static bool
+needs_no_redisplay (struct window *w)
+{
+ struct buffer *buffer = XBUFFER (w->contents);
+ struct frame *f = XFRAME (w->frame);
+ return (REDISPLAY_SOME_P ()
+ && !w->redisplay
+ && !w->update_mode_line
+ && !f->face_change
+ && !f->redisplay
+ && !buffer->text->redisplay
+ && window_point (w) == w->last_point);
+}
+
/* Prepare for redisplay by updating menu-bar item lists when
appropriate. This can call eval. */
@@ -13189,12 +13300,10 @@ prepare_menu_bars (void)
{
Lisp_Object this = XCAR (ws);
struct window *w = XWINDOW (this);
- if (w->redisplay
- || XFRAME (w->frame)->redisplay
- || XBUFFER (w->contents)->text->redisplay)
- {
- windows = Fcons (this, windows);
- }
+ /* Cf. conditions for redisplaying a window at the
+ beginning of redisplay_window. */
+ if (!needs_no_redisplay (w))
+ windows = Fcons (this, windows);
}
}
safe__call1 (true, Vpre_redisplay_function, windows);
@@ -13242,7 +13351,7 @@ prepare_menu_bars (void)
if (all_windows)
{
Lisp_Object tail, frame;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* True means that update_menu_bar has run its hooks
so any further calls to update_menu_bar shouldn't do so again. */
bool menu_bar_hooks_run = false;
@@ -13339,7 +13448,7 @@ update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
|| window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_menubar_update, Qt);
@@ -13509,7 +13618,7 @@ update_tab_bar (struct frame *f, bool save_match_data)
|| window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object new_tab_bar;
int new_n_tab_bar;
@@ -13928,6 +14037,8 @@ redisplay_tab_bar (struct frame *f)
struct it it;
struct glyph_row *row;
+ f->tab_bar_redisplayed = true;
+
/* If frame hasn't a tab-bar window or if it is zero-height, don't
do anything. This means you must start with tab-bar-lines
non-zero to get the auto-sizing effect. Or in other words, you
@@ -13935,9 +14046,16 @@ redisplay_tab_bar (struct frame *f)
if (!WINDOWP (f->tab_bar_window)
|| (w = XWINDOW (f->tab_bar_window),
WINDOW_TOTAL_LINES (w) == 0))
- return false;
+ {
+ /* Even if we do not display a tab bar initially, still pretend
+ that we have resized it. This avoids that a later activation
+ of the tab bar resizes the frame, despite of the fact that the
+ setting of 'frame-inhibit-implied-resize' should inhibit it
+ (Bug#52986). */
+ f->tab_bar_resized = true;
- f->tab_bar_redisplayed = true;
+ return false;
+ }
/* Set up an iterator for the tab-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
@@ -14413,7 +14531,7 @@ update_tool_bar (struct frame *f, bool save_match_data)
|| window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object frame, new_tool_bar;
int new_n_tool_bar;
@@ -14576,7 +14694,7 @@ build_desired_tool_bar_string (struct frame *f)
selected. */
if (selected_p)
{
- plist = Fplist_put (plist, QCrelief, make_fixnum (-relief));
+ plist = plist_put (plist, QCrelief, make_fixnum (-relief));
hmargin -= relief;
vmargin -= relief;
}
@@ -14586,10 +14704,10 @@ build_desired_tool_bar_string (struct frame *f)
/* If image is selected, display it pressed, i.e. with a
negative relief. If it's not selected, display it with a
raised relief. */
- plist = Fplist_put (plist, QCrelief,
- (selected_p
- ? make_fixnum (-relief)
- : make_fixnum (relief)));
+ plist = plist_put (plist, QCrelief,
+ (selected_p
+ ? make_fixnum (-relief)
+ : make_fixnum (relief)));
hmargin -= relief;
vmargin -= relief;
}
@@ -14598,18 +14716,18 @@ build_desired_tool_bar_string (struct frame *f)
if (hmargin || vmargin)
{
if (hmargin == vmargin)
- plist = Fplist_put (plist, QCmargin, make_fixnum (hmargin));
+ plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
else
- plist = Fplist_put (plist, QCmargin,
- Fcons (make_fixnum (hmargin),
- make_fixnum (vmargin)));
+ plist = plist_put (plist, QCmargin,
+ Fcons (make_fixnum (hmargin),
+ make_fixnum (vmargin)));
}
/* If button is not enabled, and we don't have special images
for the disabled state, make the image appear disabled by
applying an appropriate algorithm to it. */
if (!enabled_p && idx < 0)
- plist = Fplist_put (plist, QCconversion, Qdisabled);
+ plist = plist_put (plist, QCconversion, Qdisabled);
/* Put a `display' text property on the string for the image to
display. Put a `menu-item' property on the string that gives
@@ -14847,6 +14965,8 @@ redisplay_tool_bar (struct frame *f)
struct it it;
struct glyph_row *row;
+ f->tool_bar_redisplayed = true;
+
/* If frame hasn't a tool-bar window or if it is zero-height, don't
do anything. This means you must start with tool-bar-lines
non-zero to get the auto-sizing effect. Or in other words, you
@@ -14854,9 +14974,16 @@ redisplay_tool_bar (struct frame *f)
if (!WINDOWP (f->tool_bar_window)
|| (w = XWINDOW (f->tool_bar_window),
WINDOW_TOTAL_LINES (w) == 0))
- return false;
+ {
+ /* Even if we do not display a tool bar initially, still pretend
+ that we have resized it already. This avoids that a later
+ activation of the tool bar resizes the frame, despite of the
+ fact that a setting of 'frame-inhibit-implied-resize' should
+ inhibit it (Bug#52986). */
+ f->tool_bar_resized = true;
- f->tool_bar_redisplayed = true;
+ return false;
+ }
/* Set up an iterator for the tool-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
@@ -15073,11 +15200,11 @@ get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
Handle mouse button event on the tool-bar of frame F, at
frame-relative coordinates X/Y. DOWN_P is true for a button press,
false for button release. MODIFIERS is event modifiers for button
- release. */
+ release. DEVICE is the device the click came from, or Qt. */
void
-handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
- int modifiers)
+handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
+ int modifiers, Lisp_Object device)
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
struct window *w = XWINDOW (f->tool_bar_window);
@@ -15134,11 +15261,18 @@ handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
event.frame_or_window = frame;
event.arg = key;
event.modifiers = modifiers;
+ event.device = device;
kbd_buffer_store_event (&event);
f->last_tool_bar_item = -1;
}
}
+void
+handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
+ int modifiers)
+{
+ handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
+}
/* Possibly highlight a tool-bar item on frame F when mouse moves to
tool-bar window-relative coordinates X/Y. Called from
@@ -15955,7 +16089,6 @@ redisplay_internal (void)
bool must_finish = false, match_p;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
- ptrdiff_t count;
struct frame *sf;
bool polling_stopped_here = false;
Lisp_Object tail, frame;
@@ -16000,11 +16133,9 @@ redisplay_internal (void)
if (!fr->glyphs_initialized_p)
return;
-#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined (HAVE_PGTK)) || defined (HAVE_NS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
if (popup_activated ())
- {
- return;
- }
+ return;
#endif
#if defined (HAVE_HAIKU)
@@ -16018,7 +16149,7 @@ redisplay_internal (void)
/* Record a function that clears redisplaying_p
when we leave this function. */
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_void (unwind_redisplay);
redisplaying_p = true;
block_buffer_flips ();
@@ -16221,6 +16352,14 @@ redisplay_internal (void)
/* Point must be on the line that we have info recorded about. */
&& PT >= CHARPOS (tlbufpos)
&& PT <= Z - CHARPOS (tlendpos)
+ /* FIXME: The following condition is only needed when
+ significant parts of the buffer are hidden (e.g., under
+ hs-minor-mode), but there doesn't seem to be a simple way of
+ detecting that, so we always disable the one-line redisplay
+ optimizations whenever display-line-numbers-mode is turned on
+ in the buffer. */
+ && (NILP (Vdisplay_line_numbers)
+ || EQ (Vdisplay_line_numbers, Qvisual))
/* All text outside that line, including its final newline,
must be unchanged. */
&& text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
@@ -16372,7 +16511,8 @@ redisplay_internal (void)
/* If highlighting the region, or if the cursor is in the echo area,
then we can't just move the cursor. */
else if (NILP (Vshow_trailing_whitespace)
- && !cursor_in_echo_area)
+ && !cursor_in_echo_area
+ && !composition_break_at_point)
{
struct it it;
struct glyph_row *row;
@@ -16600,9 +16740,14 @@ redisplay_internal (void)
list_of_error,
redisplay_window_error);
if (update_miniwindow_p)
- internal_condition_case_1 (redisplay_window_1,
- FRAME_MINIBUF_WINDOW (sf), list_of_error,
- redisplay_window_error);
+ {
+ Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
+
+ displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
+ internal_condition_case_1 (redisplay_window_1, mini_window,
+ list_of_error,
+ redisplay_window_error);
+ }
/* Compare desired and current matrices, perform output. */
@@ -16780,6 +16925,11 @@ redisplay_internal (void)
if (interrupt_input && interrupts_deferred)
request_sigio ();
+ /* We're done with this redisplay cycle, so reset the tick count in
+ preparation for the next redisplay cycle. */
+ if (max_redisplay_ticks > 0)
+ update_redisplay_ticks (0, NULL);
+
unbind_to (count, Qnil);
RESUME_POLLING;
}
@@ -16807,7 +16957,7 @@ redisplay_preserve_echo_area (int from_where)
redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
block_input ();
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
block_buffer_flips ();
unblock_input ();
@@ -16837,6 +16987,13 @@ unwind_redisplay (void)
unblock_buffer_flips ();
}
+/* Function registered with record_unwind_protect before calling
+ start_display outside of redisplay_internal. */
+void
+unwind_display_working_on_window (void)
+{
+ display_working_on_window_p = false;
+}
/* Mark the display of leaf window W as accurate or inaccurate.
If ACCURATE_P, mark display of W as accurate.
@@ -16883,6 +17040,7 @@ mark_window_display_accurate_1 (struct window *w, bool accurate_p)
w->window_end_valid = true;
w->update_mode_line = false;
+ w->preserve_vscroll_p = false;
}
w->redisplay = !accurate_p;
@@ -17010,9 +17168,19 @@ redisplay_windows (Lisp_Object window)
}
static Lisp_Object
-redisplay_window_error (Lisp_Object ignore)
+redisplay_window_error (Lisp_Object error_data)
{
displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
+
+ /* When in redisplay, the error is captured and not shown. Arrange
+ for it to be shown later. */
+ if (max_redisplay_ticks > 0
+ && CONSP (error_data)
+ && EQ (XCAR (error_data), Qerror)
+ && STRINGP (XCAR (XCDR (error_data))))
+ Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
+ XCAR (XCDR (error_data))),
+ Vdelayed_warnings_list);
return Qnil;
}
@@ -17031,6 +17199,73 @@ redisplay_window_1 (Lisp_Object window)
redisplay_window (window, true);
return Qnil;
}
+
+
+/***********************************************************************
+ Aborting runaway redisplay
+ ***********************************************************************/
+
+/* Update the redisplay-tick count for window W, and signal an error
+ if the tick count is above some threshold, indicating that
+ redisplay of the window takes "too long".
+
+ TICKS is the amount of ticks to add to the W's current count; zero
+ means to initialize the tick count to zero.
+
+ W can be NULL if TICKS is zero: that means unconditionally
+ re-initialize the current tick count to zero.
+
+ W can also be NULL if the caller doesn't know which window is being
+ processed by the display code. In that case, if TICKS is non-zero,
+ we assume it's the last window that shows the current buffer. */
+void
+update_redisplay_ticks (int ticks, struct window *w)
+{
+ /* This keeps track of the window on which redisplay is working. */
+ static struct window *cwindow;
+ static EMACS_INT window_ticks;
+
+ /* We only initialize the count if this is a different window or
+ NULL. Otherwise, this is a call from init_iterator for the same
+ window we tracked before, and we should keep the count. */
+ if (!ticks && w != cwindow)
+ {
+ cwindow = w;
+ window_ticks = 0;
+ }
+ /* Some callers can be run in contexts unrelated to display code, so
+ don't abort them and don't update the tick count in those cases. */
+ if ((!w && !redisplaying_p && !display_working_on_window_p)
+ /* We never disable redisplay of a mini-window, since that is
+ absolutely essential for communicating with Emacs. */
+ || (w && MINI_WINDOW_P (w)))
+ return;
+
+ if (ticks > 0)
+ window_ticks += ticks;
+ if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
+ {
+ /* In addition to a buffer, this could be a window (for non-leaf
+ windows, not expected here) or nil (for pseudo-windows like
+ the one used for the native tool bar). */
+ Lisp_Object contents = w ? w->contents : Qnil;
+ char *bufname =
+ NILP (contents)
+ ? SSDATA (BVAR (current_buffer, name))
+ : (BUFFERP (contents)
+ ? SSDATA (BVAR (XBUFFER (contents), name))
+ : (char *) "<unknown>");
+
+ windows_or_buffers_changed = 177;
+ /* scrolling_window depends too much on the glyph matrices being
+ correct, and we cannot guarantee that if we abort the
+ redisplay of this window. */
+ if (w && w->desired_matrix)
+ w->desired_matrix->no_scrolling_p = true;
+ error ("Window showing buffer %s takes too long to redisplay", bufname);
+ }
+}
+
/* Set cursor position of W. PT is assumed to be displayed in ROW.
@@ -17681,7 +17916,7 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
if (!NILP (Vwindow_scroll_functions))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_fixnum (CHARPOS (startp)));
@@ -17727,7 +17962,7 @@ cursor_row_fully_visible_p (struct window *w, bool force_p,
buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
/* If no local binding, use the global value. */
- if (EQ (mclfv_p, Qunbound))
+ if (BASE_EQ (mclfv_p, Qunbound))
mclfv_p = Vmake_cursor_line_fully_visible;
/* Follow mode sets the variable to a Lisp function in buffers that
are under Follow mode. */
@@ -18557,6 +18792,20 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
|| (NILP (g->object)
&& (g->charpos == PT
|| (g->charpos == 0 && endpos - 1 == PT)));
+ /* Perhaps the point position is inside
+ invisible text? In that case, we trust
+ 'set_cursor_from_row' to do its job and
+ find the best position for the cursor. */
+ if (!exact_match_p)
+ {
+ Lisp_Object val =
+ get_char_property_and_overlay (make_fixnum (PT),
+ Qinvisible,
+ Qnil, NULL);
+
+ if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
+ exact_match_p = true;
+ }
}
if (at_zv_p || exact_match_p)
{
@@ -18706,6 +18955,33 @@ set_horizontal_scroll_bar (struct window *w)
(w, portion, whole, start);
}
+/* Subroutine of redisplay_window, to determine whether a window-start
+ point STARTP of WINDOW should be rejected. */
+static bool
+window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
+{
+ if (!make_window_start_visible)
+ return true;
+
+ struct window *w = XWINDOW (window);
+ struct frame *f = XFRAME (w->frame);
+ Lisp_Object startpos = make_fixnum (startp);
+ Lisp_Object invprop, disp_spec;
+ struct text_pos ignored;
+
+ /* Is STARTP in invisible text? */
+ if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
+ TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
+ return false;
+
+ /* Is STARTP covered by a replacing 'display' property? */
+ if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
+ && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
+ FRAME_WINDOW_P (f)) > 0)
+ return false;
+
+ return true;
+}
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only
selected_window is redisplayed.
@@ -18775,7 +19051,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
It indicates that the buffer contents and narrowing are unchanged. */
bool buffer_unchanged_p = false;
bool temp_scroll_step = false;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int rc;
int centering_position = -1;
bool last_line_misfit = false;
@@ -18791,14 +19067,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
*w->desired_matrix->method = 0;
#endif
- if (!just_this_one_p
- && REDISPLAY_SOME_P ()
- && !w->redisplay
- && !w->update_mode_line
- && !f->face_change
- && !f->redisplay
- && !buffer->text->redisplay
- && BUF_PT (buffer) == w->last_point)
+ if (!just_this_one_p && needs_no_redisplay (w))
return;
/* Make sure that both W's markers are valid. */
@@ -18869,6 +19138,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
&& !window_outdated (w)
+ && !composition_break_at_point
&& !hscrolling_current_line_p (w));
beg_unchanged = BEG_UNCHANGED;
@@ -19010,7 +19280,14 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
int new_vpos = -1;
w->force_start = false;
- w->vscroll = 0;
+
+ /* The vscroll should be preserved in this case, since
+ `pixel-scroll-precision-mode' must continue working normally
+ when a mini-window is resized. (bug#55312) */
+ if (!w->preserve_vscroll_p || !window_frozen_p (w))
+ w->vscroll = 0;
+
+ w->preserve_vscroll_p = false;
w->window_end_valid = false;
/* Forget any recorded base line for line number display. */
@@ -19037,6 +19314,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
else if (CHARPOS (startp) > ZV)
SET_TEXT_POS (startp, ZV, ZV_BYTE);
+ /* Reject the specified start location if it is invisible, and
+ the buffer wants it always visible. */
+ if (!window_start_acceptable_p (window, CHARPOS (startp)))
+ goto ignore_start;
+
/* Redisplay, then check if cursor has been set during the
redisplay. Give up if new fonts were loaded. */
/* We used to issue a CHECK_MARGINS argument to try_window here,
@@ -19143,7 +19425,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),
@@ -19193,6 +19476,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
goto done;
}
+ ignore_start:
+
/* Handle case where text has not changed, only point, and it has
not moved off the frame, and we are not retrying after hscroll.
(current_matrix_up_to_date_p is true when retrying.) */
@@ -19214,10 +19499,14 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
}
}
/* If current starting point was originally the beginning of a line
- but no longer is, find a new starting point. */
+ but no longer is, or if the starting point is invisible but the
+ buffer wants it always visible, find a new starting point. */
else if (w->start_at_line_beg
- && !(CHARPOS (startp) <= BEGV
- || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
+ && ((CHARPOS (startp) > BEGV
+ && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
+ || (CHARPOS (startp) >= BEGV
+ && CHARPOS (startp) <= ZV
+ && !window_start_acceptable_p (window, CHARPOS (startp)))))
{
#ifdef GLYPH_DEBUG
debug_method_add (w, "recenter 1");
@@ -19293,6 +19582,17 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
goto force_start;
}
+ /* Don't use the same window-start if it is invisible or covered
+ by a replacing 'display' property and the buffer requested
+ the window-start to be always visible. */
+ if (!window_start_acceptable_p (window, CHARPOS (startp)))
+ {
+#ifdef GLYPH_DEBUG
+ debug_method_add (w, "recenter 2");
+#endif
+ goto recenter;
+ }
+
#ifdef GLYPH_DEBUG
debug_method_add (w, "same window start");
#endif
@@ -19698,7 +19998,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|| window_wants_header_line (w)
|| window_wants_tab_line (w)))
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
display_mode_lines (w);
@@ -20892,6 +21192,12 @@ try_window_id (struct window *w)
w->frame))))
GIVE_UP (24);
+ /* composition-break-at-point is incompatible with the optimizations
+ in this function, because we need to recompose characters when
+ point moves off their positions. */
+ if (composition_break_at_point)
+ GIVE_UP (27);
+
/* Make sure beg_unchanged and end_unchanged are up to date. Do it
only if buffer has really changed. The reason is that the gap is
initially at Z for freshly visited files. The code below would
@@ -21963,7 +22269,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
struct buffer *buffer = XBUFFER (w->contents);
struct buffer *old = current_buffer;
const unsigned char *arrow_string = SDATA (overlay_arrow_string);
- ptrdiff_t arrow_len = SCHARS (overlay_arrow_string);
+ ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
const unsigned char *arrow_end = arrow_string + arrow_len;
const unsigned char *p;
struct it it;
@@ -21994,7 +22300,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
p += it.len;
/* Get its face. */
- ilisp = make_fixnum (p - arrow_string);
+ ilisp = make_fixnum (char_num++);
face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
it.face_id = compute_char_face (f, it.char_to_display, face);
@@ -22282,6 +22588,13 @@ compute_line_metrics (struct it *it)
}
+static void
+clear_position (struct it *it)
+{
+ it->position.charpos = 0;
+ it->position.bytepos = 0;
+}
+
/* Append one space to the glyph row of iterator IT if doing a
window-based redisplay. The space has the same face as
IT->face_id. Value is true if a space was added.
@@ -22317,7 +22630,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
struct face *face;
it->what = IT_CHARACTER;
- memset (&it->position, 0, sizeof it->position);
+ clear_position (it);
it->object = Qnil;
it->len = 1;
@@ -22518,7 +22831,7 @@ extend_face_to_end_of_line (struct it *it)
|| WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
return;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Don't allow the user to quit out of face-merging code, in case
this is called when redisplaying a non-selected window, with
@@ -22646,7 +22959,7 @@ extend_face_to_end_of_line (struct it *it)
const int stretch_width =
indicator_column - it->current_x - char_width;
- memset (&it->position, 0, sizeof it->position);
+ clear_position (it);
/* Only generate a stretch glyph if there is distance
between current_x and the indicator position. */
@@ -22680,7 +22993,7 @@ extend_face_to_end_of_line (struct it *it)
if (stretch_width > 0)
{
- memset (&it->position, 0, sizeof it->position);
+ clear_position (it);
append_stretch_glyph (it, Qnil, stretch_width,
it->ascent + it->descent,
stretch_ascent);
@@ -22730,7 +23043,7 @@ extend_face_to_end_of_line (struct it *it)
(((it->ascent + it->descent)
* FONT_BASE (font)) / FONT_HEIGHT (font));
saved_pos = it->position;
- memset (&it->position, 0, sizeof it->position);
+ clear_position (it);
saved_avoid_cursor = it->avoid_cursor_p;
it->avoid_cursor_p = true;
saved_face_id = it->face_id;
@@ -22768,7 +23081,7 @@ extend_face_to_end_of_line (struct it *it)
enum display_element_type saved_what = it->what;
it->what = IT_CHARACTER;
- memset (&it->position, 0, sizeof it->position);
+ clear_position (it);
it->object = Qnil;
it->c = it->char_to_display = ' ';
it->len = 1;
@@ -23416,7 +23729,7 @@ display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
ptrdiff_t val;
- ptrdiff_t pdl_count = SPECPDL_INDEX ();
+ specpdl_ref pdl_count = SPECPDL_INDEX ();
record_unwind_protect (save_restriction_restore, save_restriction_save ());
Fwiden ();
val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
@@ -23442,7 +23755,7 @@ display_count_lines_visually (struct it *it)
return it->lnum + 1;
else
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (IT_CHARPOS (*it) <= PT)
{
@@ -23870,7 +24183,7 @@ display_line (struct it *it, int cursor_vpos)
row->displays_text_p = true;
row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
it->starts_in_middle_of_char_p = false;
- it->tab_offset = 0;
+ it->stretch_adjust = 0;
it->line_number_produced_p = false;
/* Arrange the overlays nicely for our purposes. Usually, we call
@@ -24869,15 +25182,17 @@ DEFUN ("bidi-find-overridden-directionality",
doc: /* Return position between FROM and TO where directionality was overridden.
This function returns the first character position in the specified
-region of OBJECT where there is a character whose `bidi-class' property
-is `L', but which was forced to display as `R' by a directional
-override, and likewise with characters whose `bidi-class' is `R'
-or `AL' that were forced to display as `L'.
+region of OBJECT where characters have their bidirectional
+properties affected in a way that might make its text look confusingly
+on display. For example, characters whose `bidi-class' property is `L',
+could be forced to display as `R' by a directional override, and
+likewise characters whose `bidi-class' is `R' or `AL' that are
+forced to display as `L'.
If no such character is found, the function returns nil.
OBJECT is a Lisp string or buffer to search for overridden
-directionality, and defaults to the current buffer if nil or omitted.
+directionality, and defaults to the current buffer if nil.
OBJECT can also be a window, in which case the function will search
the buffer displayed in that window. Passing the window instead of
a buffer is preferable when the buffer is displayed in some window,
@@ -24889,12 +25204,19 @@ of the text. It should be a symbol, either `left-to-right'
or `right-to-left', and defaults to `left-to-right'.
Strong directional characters `L', `R', and `AL' can have their
-intrinsic directionality overridden by directional override
-control characters RLO (u+202E) and LRO (u+202D). They can also
-have their directionality affected by other formatting control
-characters: LRE (u+202A), RLE (u+202B), LRI (u+2066), and RLI (u+2067).
-See the function `get-char-code-property' for a way to inquire about
-the `bidi-class' property of a character. */)
+intrinsic directionality overridden by directional override control
+characters RLO (u+202E) and LRO (u+202D). They can also have their
+directionality affected by other formatting control characters: LRE
+(u+202A), RLE (u+202B), LRI (u+2066), and RLI (u+2067). See the
+function `get-char-code-property' for a way to inquire about the
+`bidi-class' property of a character. Characters whose intrinsic
+directionality is weak or neutral, such as numbers or punctuation
+characters, can be forced to display in a very different place with
+respect of its surrounding characters, so as to make the surrounding
+text confuse the user regarding what the text says.
+
+Also see the `highlight-confusing-reorderings' function, which can be
+useful in similar circumstances as this function. */)
(Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
{
struct buffer *buf = current_buffer;
@@ -25872,7 +26194,7 @@ display_mode_lines (struct window *w)
{
Lisp_Object old_selected_window = selected_window;
Lisp_Object new_frame = w->frame;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int n = 0;
record_unwind_protect (restore_selected_window, selected_window);
@@ -25964,7 +26286,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
{
struct it it;
struct face *face;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
init_iterator (&it, w, -1, -1, NULL, face_id);
/* Don't extend on a previously drawn mode-line.
@@ -26188,8 +26510,8 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
tem = props;
while (CONSP (tem))
{
- oprops = Fplist_put (oprops, XCAR (tem),
- XCAR (XCDR (tem)));
+ oprops = plist_put (oprops, XCAR (tem),
+ XCAR (XCDR (tem)));
tem = XCDR (XCDR (tem));
}
props = oprops;
@@ -26640,13 +26962,13 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string,
props = mode_line_string_face_prop;
else if (!NILP (mode_line_string_face))
{
- Lisp_Object face = Fplist_get (props, Qface);
+ Lisp_Object face = plist_get (props, Qface);
props = Fcopy_sequence (props);
if (NILP (face))
face = mode_line_string_face;
else
face = list2 (face, mode_line_string_face);
- props = Fplist_put (props, Qface, face);
+ props = plist_put (props, Qface, face);
}
Fadd_text_properties (make_fixnum (0), make_fixnum (len),
props, lisp_string);
@@ -26665,7 +26987,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string,
Lisp_Object face;
if (NILP (props))
props = Ftext_properties_at (make_fixnum (0), lisp_string);
- face = Fplist_get (props, Qface);
+ face = plist_get (props, Qface);
if (NILP (face))
face = mode_line_string_face;
else
@@ -26729,7 +27051,7 @@ are the selected window and the WINDOW's buffer). */)
struct buffer *old_buffer = NULL;
int face_id;
bool no_props = FIXNUMP (face);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object str;
int string_start = 0;
@@ -27442,7 +27764,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
case '@':
{
- ptrdiff_t count = inhibit_garbage_collection ();
+ specpdl_ref count = inhibit_garbage_collection ();
Lisp_Object curdir = BVAR (current_buffer, directory);
Lisp_Object val = Qnil;
@@ -27715,7 +28037,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
face_string);
if (!NILP (display))
{
- Lisp_Object min_width = Fplist_get (display, Qmin_width);
+ Lisp_Object min_width = plist_get (display, Qmin_width);
if (!NILP (min_width))
display_min_width (it, 0, face_string, min_width);
}
@@ -28049,6 +28371,11 @@ static bool
calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
struct font *font, bool width_p, int *align_to)
{
+ /* Don't adjust for line number if we didn't yet produce it for this
+ screen line. This is for when this function is called from
+ move_it_in_display_line_to that was called by display_line to get
+ past the glyphs hscrolled off the left side of the window. */
+ int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
double pixels;
# define OK_PIXELS(val) (*res = (val), true)
@@ -28105,7 +28432,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
if (EQ (prop, Qtext))
return OK_PIXELS (width_p
? (window_box_width (it->w, TEXT_AREA)
- - it->lnum_pixel_width)
+ - lnum_pixel_width)
: WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
/* ':align_to'. First time we compute the value, window
@@ -28117,14 +28444,14 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
/* 'left': left edge of the text area. */
if (EQ (prop, Qleft))
return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
- + it->lnum_pixel_width);
+ + lnum_pixel_width);
/* 'right': right edge of the text area. */
if (EQ (prop, Qright))
return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
/* 'center': the center of the text area. */
if (EQ (prop, Qcenter))
return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
- + it->lnum_pixel_width
+ + lnum_pixel_width
+ window_box_width (it->w, TEXT_AREA) / 2);
/* 'left-fringe': left edge of the left fringe. */
if (EQ (prop, Qleft_fringe))
@@ -28167,7 +28494,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
}
prop = buffer_local_value (prop, it->w->contents);
- if (EQ (prop, Qunbound))
+ if (BASE_EQ (prop, Qunbound))
prop = Qnil;
}
@@ -28177,7 +28504,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
? FRAME_COLUMN_WIDTH (it->f)
: FRAME_LINE_HEIGHT (it->f));
if (width_p && align_to && *align_to < 0)
- return OK_PIXELS (XFLOATINT (prop) * base_unit + it->lnum_pixel_width);
+ return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
return OK_PIXELS (XFLOATINT (prop) * base_unit);
}
@@ -28230,16 +28557,16 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
}
car = buffer_local_value (car, it->w->contents);
- if (EQ (car, Qunbound))
+ if (BASE_EQ (car, Qunbound))
car = Qnil;
}
/* '(NUM)': absolute number of pixels. */
if (NUMBERP (car))
-{
+ {
double fact;
int offset =
- width_p && align_to && *align_to < 0 ? it->lnum_pixel_width : 0;
+ width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
pixels = XFLOATINT (car);
if (NILP (cdr))
return OK_PIXELS (pixels + offset);
@@ -28920,6 +29247,7 @@ normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
{
struct font_metrics *pcm = get_per_char_metric (font, &char2b);
+ eassume (pcm);
if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
{
@@ -30407,14 +30735,14 @@ produce_stretch_glyph (struct it *it)
plist = XCDR (it->object);
/* Compute the width of the stretch. */
- if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
+ if ((prop = plist_get (plist, QCwidth), !NILP (prop))
&& calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
{
/* Absolute width `:width WIDTH' specified and valid. */
zero_width_ok_p = true;
width = (int)tem;
}
- else if (prop = Fplist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
+ else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
{
/* Relative width `:relative-width FACTOR' specified and valid.
Compute the width of the characters having this `display'
@@ -30451,17 +30779,43 @@ produce_stretch_glyph (struct it *it)
PRODUCE_GLYPHS (&it2);
width = NUMVAL (prop) * it2.pixel_width;
}
- else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
+ else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
&& calc_pixel_width_or_height (&tem, it, prop, font, true,
&align_to))
{
+ int x = it->current_x + it->continuation_lines_width;
+ int x0 = x;
+ /* Adjust for line numbers, if needed. */
+ if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
+ {
+ x -= it->lnum_pixel_width;
+ /* Restore the original width, if required. */
+ if (x + it->stretch_adjust >= it->first_visible_x)
+ x += it->stretch_adjust;
+ }
+
if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
align_to = (align_to < 0
? 0
: align_to - window_box_left_offset (it->w, TEXT_AREA));
else if (align_to < 0)
align_to = window_box_left_offset (it->w, TEXT_AREA);
- width = max (0, (int)tem + align_to - it->current_x);
+ width = max (0, (int)tem + align_to - x);
+
+ int next_x = x + width;
+ if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
+ {
+ /* If the line is hscrolled, and the stretch starts before
+ the first visible pixel, simulate negative row->x. */
+ if (x < it->first_visible_x)
+ {
+ next_x -= it->first_visible_x - x;
+ it->stretch_adjust = it->first_visible_x - x;
+ }
+ else
+ next_x -= it->stretch_adjust;
+ }
+ width = next_x - x0;
zero_width_ok_p = true;
}
else
@@ -30477,13 +30831,13 @@ produce_stretch_glyph (struct it *it)
{
int default_height = normal_char_height (font, ' ');
- if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
+ if ((prop = plist_get (plist, QCheight), !NILP (prop))
&& calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
{
height = (int)tem;
zero_height_ok_p = true;
}
- else if (prop = Fplist_get (plist, QCrelative_height),
+ else if (prop = plist_get (plist, QCrelative_height),
NUMVAL (prop) > 0)
height = default_height * NUMVAL (prop);
else
@@ -30495,7 +30849,7 @@ produce_stretch_glyph (struct it *it)
/* Compute percentage of height used for ascent. If
`:ascent ASCENT' is present and valid, use that. Otherwise,
derive the ascent from the font in use. */
- if (prop = Fplist_get (plist, QCascent),
+ if (prop = plist_get (plist, QCascent),
NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
ascent = height * NUMVAL (prop) / 100.0;
else if (!NILP (prop)
@@ -31251,8 +31605,8 @@ gui_produce_glyphs (struct it *it)
{
x -= it->lnum_pixel_width;
/* Restore the original TAB width, if required. */
- if (x + it->tab_offset >= it->first_visible_x)
- x += it->tab_offset;
+ if (x + it->stretch_adjust >= it->first_visible_x)
+ x += it->stretch_adjust;
}
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
@@ -31270,10 +31624,10 @@ gui_produce_glyphs (struct it *it)
if (x < it->first_visible_x)
{
next_tab_x -= it->first_visible_x - x;
- it->tab_offset = it->first_visible_x - x;
+ it->stretch_adjust = it->first_visible_x - x;
}
else
- next_tab_x -= it->tab_offset;
+ next_tab_x -= it->stretch_adjust;
}
it->pixel_width = next_tab_x - x0;
@@ -31824,14 +32178,16 @@ gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
void
gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
- enum glyph_row_area updated_area, int to_x)
+ enum glyph_row_area updated_area, int to_x)
{
struct frame *f;
int max_x, min_y, max_y;
int from_x, from_y, to_y;
+ struct face *face;
eassert (updated_row);
f = XFRAME (w->frame);
+ face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
if (updated_row->full_width_p)
max_x = (WINDOW_PIXEL_WIDTH (w)
@@ -31883,6 +32239,9 @@ gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
block_input ();
FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
to_x - from_x, to_y - from_y);
+
+ if (face && !updated_row->stipple_p)
+ updated_row->stipple_p = face->stipple;
unblock_input ();
}
}
@@ -32447,7 +32806,7 @@ display_and_set_cursor (struct window *w, bool on,
{
struct frame *f = XFRAME (w->frame);
int new_cursor_type;
- int new_cursor_width;
+ int new_cursor_width UNINIT;
bool active_cursor;
struct glyph_row *glyph_row;
struct glyph *glyph;
@@ -33734,7 +34093,8 @@ define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
return;
/* Do not change cursor shape while dragging mouse. */
- if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping))
+ if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
+ || EQ (track_mouse, Qdrag_source))
return;
if (!NILP (pointer))
@@ -33836,7 +34196,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
if (IMAGEP (object))
{
Lisp_Object image_map, hotspot;
- if ((image_map = Fplist_get (XCDR (object), QCmap),
+ if ((image_map = plist_get (XCDR (object), QCmap),
!NILP (image_map))
&& (hotspot = find_hot_spot (image_map, dx, dy),
CONSP (hotspot))
@@ -33851,10 +34211,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
if (CONSP (hotspot)
&& (plist = XCAR (hotspot), CONSP (plist)))
{
- pointer = Fplist_get (plist, Qpointer);
+ pointer = plist_get (plist, Qpointer);
if (NILP (pointer))
pointer = Qhand;
- help = Fplist_get (plist, Qhelp_echo);
+ help = plist_get (plist, Qhelp_echo);
if (!NILP (help))
{
help_echo_string = help;
@@ -33865,7 +34225,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
}
}
if (NILP (pointer))
- pointer = Fplist_get (XCDR (object), QCpointer);
+ pointer = plist_get (XCDR (object), QCpointer);
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -34351,7 +34711,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
if (img != NULL && IMAGEP (img->spec))
{
Lisp_Object image_map, hotspot;
- if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
+ if ((image_map = plist_get (XCDR (img->spec), QCmap),
!NILP (image_map))
&& (hotspot = find_hot_spot (image_map,
glyph->slice.img.x + dx,
@@ -34369,10 +34729,10 @@ note_mouse_highlight (struct frame *f, int x, int y)
if (CONSP (hotspot)
&& (plist = XCAR (hotspot), CONSP (plist)))
{
- pointer = Fplist_get (plist, Qpointer);
+ pointer = plist_get (plist, Qpointer);
if (NILP (pointer))
pointer = Qhand;
- help_echo_string = Fplist_get (plist, Qhelp_echo);
+ help_echo_string = plist_get (plist, Qhelp_echo);
if (!NILP (help_echo_string))
{
help_echo_window = window;
@@ -34382,7 +34742,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
}
}
if (NILP (pointer))
- pointer = Fplist_get (XCDR (img->spec), QCpointer);
+ pointer = plist_get (XCDR (img->spec), QCpointer);
}
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -35556,6 +35916,7 @@ be let-bound around code that needs to disable messages temporarily. */);
DEFSYM (Qdragging, "dragging");
DEFSYM (Qdropping, "dropping");
+ DEFSYM (Qdrag_source, "drag-source");
DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
@@ -35563,7 +35924,7 @@ be let-bound around code that needs to disable messages temporarily. */);
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
- list_of_error = list1 (list2 (Qerror, Qvoid_variable));
+ list_of_error = list1 (Qerror);
staticpro (&list_of_error);
/* Values of those variables at last redisplay are stored as
@@ -35586,8 +35947,13 @@ be let-bound around code that needs to disable messages temporarily. */);
staticpro (&echo_area_buffer[0]);
staticpro (&echo_area_buffer[1]);
- Vmessages_buffer_name = build_pure_c_string ("*Messages*");
- staticpro (&Vmessages_buffer_name);
+ DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
+ doc: /* The name of the buffer where messages are logged.
+This is normally \"\*Messages*\", but can be rebound by packages that
+wish to redirect messages to a different buffer. (If the buffer
+doesn't exist, it will be created and put into
+`messages-buffer-mode'.) */);
+ Vmessages_buffer_name = build_string ("*Messages*");
mode_line_proptrans_alist = Qnil;
staticpro (&mode_line_proptrans_alist);
@@ -35928,6 +36294,12 @@ window, nil if it's okay to leave the cursor partially-visible. */);
Vmake_cursor_line_fully_visible = Qt;
DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
+ DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
+ doc: /* Whether to ensure `window-start' position is never invisible. */);
+ make_window_start_visible = false;
+ DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
+ Fmake_variable_buffer_local (Qmake_window_start_visible);
+
DEFSYM (Qclose_tab, "close-tab");
DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
doc: /* Border below tab-bar in pixels.
@@ -36025,7 +36397,7 @@ they return to their normal size when the minibuffer is closed, or the
echo area becomes empty.
This variable does not affect resizing of the minibuffer window of
-minibuffer-only frames. These are handled by 'resize-mini-frames'
+minibuffer-only frames. These are handled by `resize-mini-frames'
only. */);
/* Contrary to the doc string, we initialize this to nil, so that
loading loadup.el won't try to resize windows before loading
@@ -36249,7 +36621,7 @@ see biditest.el in the test suite. */);
doc: /* Non-nil means inhibit the Bidirectional Parentheses Algorithm.
Disabling the BPA makes redisplay faster, but might produce incorrect
display reordering of bidirectional text with embedded parentheses and
-other bracket characters whose 'paired-bracket' Unicode property is
+other bracket characters whose `paired-bracket' Unicode property is
non-nil, see `get-char-code-property'. */);
bidi_inhibit_bpa = false;
@@ -36360,12 +36732,20 @@ message displayed by this function), and `command-error-function'
(which controls how error messages are displayed). */);
Vset_message_function = Qnil;
+ DEFSYM (Qdont_clear_message, "dont-clear-message");
DEFVAR_LISP ("clear-message-function", Vclear_message_function,
doc: /* If non-nil, function to clear echo-area messages.
Usually this function is called when the next input event arrives.
-The function is called without arguments. It is expected to clear the
-message displayed by its counterpart function specified by
-`set-message-function'. */);
+It is expected to clear the message displayed by its counterpart
+function specified by `set-message-function'.
+
+The function is called without arguments.
+
+If this function returns a value that isn't `dont-clear-message', the
+message is cleared from the echo area as usual. If this function
+returns `dont-clear-message', this means that the message was already
+handled, and the original message text will not be cleared from the
+echo area. */);
Vclear_message_function = Qnil;
DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
@@ -36428,6 +36808,28 @@ Otherwise, use custom-tailored code after resizing minibuffer windows to try
and display the most important part of the minibuffer. */);
/* See bug#43519 for some discussion around this. */
redisplay_adhoc_scroll_in_resize_mini_windows = true;
+
+ DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
+ doc: /* If non-nil, prevent auto-composition of characters around point.
+This makes it easier to edit character sequences that are
+composed on display. */);
+ composition_break_at_point = false;
+
+ DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
+ doc: /* Maximum number of redisplay ticks before aborting redisplay of a window.
+
+This allows to abort the display of a window if the amount of low-level
+redisplay operations exceeds the value of this variable. When display of
+a window is aborted due to this reason, the buffer shown in that window
+will not have its windows redisplayed until the buffer is modified or until
+you type \\[recenter-top-bottom] with one of its windows selected.
+You can also decide to kill the buffer and visit it in some
+other way, like under `so-long-mode' or literally.
+
+The default value is zero, which disables this feature.
+The recommended non-zero value is between 100000 and 1000000,
+depending on your patience and the speed of your system. */);
+ max_redisplay_ticks = 0;
}
diff --git a/src/xfaces.c b/src/xfaces.c
index 3fd31b7f225..8ae922578ec 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -295,6 +295,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface)
+/* True if face attribute ATTR is `reset'. */
+
+#define RESET_P(ATTR) EQ ((ATTR), Qreset)
+
/* Size of hash table of realized faces in face caches (should be a
prime number). */
@@ -475,7 +479,7 @@ x_free_colors (struct frame *f, unsigned long *pixels, int npixels)
{
/* If display has an immutable color map, freeing colors is not
necessary and some servers don't allow it. So don't do it. */
- if (x_mutable_colormap (FRAME_X_VISUAL (f)))
+ if (x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
{
#ifdef DEBUG_X_COLORS
unregister_colors (pixels, npixels);
@@ -500,7 +504,7 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap,
/* If display has an immutable color map, freeing colors is not
necessary and some servers don't allow it. So don't do it. */
- if (x_mutable_colormap (dpyinfo->visual))
+ if (x_mutable_colormap (&dpyinfo->visual_info))
{
#ifdef DEBUG_X_COLORS
unregister_colors (pixels, npixels);
@@ -888,6 +892,11 @@ parse_hex_color_comp (const char *s, const char *e, unsigned short *dst)
static double
parse_float_color_comp (const char *s, const char *e)
{
+ /* Only allow decimal float literals without whitespace. */
+ for (const char *p = s; p < e; p++)
+ if (!((*p >= '0' && *p <= '9')
+ || *p == '.' || *p == '+' || *p == '-' || *p == 'e' || *p == 'E'))
+ return -1;
char *end;
double x = strtod (s, &end);
return (end == e && x >= 0 && x <= 1) ? x : -1;
@@ -1445,9 +1454,9 @@ enum xlfd_field
};
/* Order by which font selection chooses fonts. The default values
- mean `first, find a best match for the font width, then for the
- font height, then for weight, then for slant.' This variable can be
- set via set-face-font-sort-order. */
+ mean "first, find a best match for the font width, then for the
+ font height, then for weight, then for slant." This variable can be
+ set via 'internal-set-font-selection-order'. */
static int font_sort_order[4];
@@ -1498,16 +1507,22 @@ If FAMILY is omitted or nil, list all families.
Otherwise, FAMILY must be a string, possibly containing wildcards
`?' and `*'.
If FRAME is omitted or nil, use the selected frame.
+
Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT
SLANT FIXED-P FULL REGISTRY-AND-ENCODING].
-FAMILY is the font family name. POINT-SIZE is the size of the
-font in 1/10 pt. WIDTH, WEIGHT, and SLANT are symbols describing the
-width, weight and slant of the font. These symbols are the same as for
-face attributes. FIXED-P is non-nil if the font is fixed-pitch.
-FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string
-giving the registry and encoding of the font.
-The result list is sorted according to the current setting of
-the face font sort order. */)
+
+FAMILY is the font family name.
+POINT-SIZE is the size of the font in 1/10 pt.
+WIDTH, WEIGHT, and SLANT are symbols describing the width, weight
+ and slant of the font. These symbols are the same as for face
+ attributes, see `set-face-attribute'.
+FIXED-P is non-nil if the font is fixed-pitch.
+FULL is the full name of the font.
+REGISTRY-AND-ENCODING is a string giving the registry and encoding of
+ the font.
+
+The resulting list is sorted according to the current setting of
+the face font sort order, see `face-font-selection-order'. */)
(Lisp_Object family, Lisp_Object frame)
{
Lisp_Object font_spec, list, *drivers, vec;
@@ -1568,7 +1583,15 @@ the face font sort order. */)
make_fixnum (point),
FONT_WEIGHT_SYMBOLIC (font),
FONT_SLANT_SYMBOLIC (font),
- NILP (spacing) || EQ (spacing, Qp) ? Qnil : Qt,
+ (NILP (spacing)
+ || EQ (spacing, Qp)
+ /* If the font was specified in a way
+ different from XLFD (e.g., on MS-Windows),
+ we will have a number there, not 'p'. */
+ || BASE_EQ (spacing,
+ make_fixnum
+ (FONT_SPACING_PROPORTIONAL)))
+ ? Qnil : Qt,
Ffont_xlfd_name (font, Qnil),
AREF (font, FONT_REGISTRY_INDEX));
result = Fcons (v, result);
@@ -1738,57 +1761,72 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE])
{
eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX])
+ || RESET_P (attrs[LFACE_FAMILY_INDEX])
|| STRINGP (attrs[LFACE_FAMILY_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX])
+ || RESET_P (attrs[LFACE_FOUNDRY_INDEX])
|| STRINGP (attrs[LFACE_FOUNDRY_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX])
+ || RESET_P (attrs[LFACE_SWIDTH_INDEX])
|| SYMBOLP (attrs[LFACE_SWIDTH_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX])
+ || RESET_P (attrs[LFACE_HEIGHT_INDEX])
|| NUMBERP (attrs[LFACE_HEIGHT_INDEX])
|| FUNCTIONP (attrs[LFACE_HEIGHT_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX])
+ || RESET_P (attrs[LFACE_WEIGHT_INDEX])
|| SYMBOLP (attrs[LFACE_WEIGHT_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX])
+ || RESET_P (attrs[LFACE_SLANT_INDEX])
|| SYMBOLP (attrs[LFACE_SLANT_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
+ || RESET_P (attrs[LFACE_UNDERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
|| STRINGP (attrs[LFACE_UNDERLINE_INDEX])
|| CONSP (attrs[LFACE_UNDERLINE_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_EXTEND_INDEX])
+ || RESET_P (attrs[LFACE_EXTEND_INDEX])
|| SYMBOLP (attrs[LFACE_EXTEND_INDEX])
|| STRINGP (attrs[LFACE_EXTEND_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
+ || RESET_P (attrs[LFACE_OVERLINE_INDEX])
|| SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
|| STRINGP (attrs[LFACE_OVERLINE_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
+ || RESET_P (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX])
|| STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX])
+ || RESET_P (attrs[LFACE_BOX_INDEX])
|| SYMBOLP (attrs[LFACE_BOX_INDEX])
|| STRINGP (attrs[LFACE_BOX_INDEX])
|| FIXNUMP (attrs[LFACE_BOX_INDEX])
|| CONSP (attrs[LFACE_BOX_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX])
+ || RESET_P (attrs[LFACE_INVERSE_INDEX])
|| SYMBOLP (attrs[LFACE_INVERSE_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX])
+ || RESET_P (attrs[LFACE_FOREGROUND_INDEX])
|| STRINGP (attrs[LFACE_FOREGROUND_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
+ || RESET_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
|| STRINGP (attrs[LFACE_DISTANT_FOREGROUND_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX])
+ || RESET_P (attrs[LFACE_BACKGROUND_INDEX])
|| STRINGP (attrs[LFACE_BACKGROUND_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX])
@@ -1798,13 +1836,16 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE])
#ifdef HAVE_WINDOW_SYSTEM
eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX])
+ || RESET_P (attrs[LFACE_STIPPLE_INDEX])
|| SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
|| !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX])
|| IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX])
+ || RESET_P (attrs[LFACE_FONT_INDEX])
|| FONTP (attrs[LFACE_FONT_INDEX]));
eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX])
|| STRINGP (attrs[LFACE_FONTSET_INDEX])
+ || RESET_P (attrs[LFACE_FONTSET_INDEX])
|| NILP (attrs[LFACE_FONTSET_INDEX]));
#endif
}
@@ -1924,7 +1965,7 @@ resolve_face_name (Lisp_Object face_name, bool signal_p)
break;
tortoise = Fget (tortoise, Qface_alias);
- if (EQ (hare, tortoise))
+ if (BASE_EQ (hare, tortoise))
{
if (signal_p)
circular_list (orig_face);
@@ -2064,7 +2105,7 @@ lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE])
#ifdef HAVE_WINDOW_SYSTEM
/* Set font-related attributes of Lisp face LFACE from FONT-OBJECT.
- If FORCE_P, set only unspecified attributes of LFACE. The
+ If FORCE_P is zero, set only unspecified attributes of LFACE. The
exception is `font' attribute. It is set to FONT_OBJECT regardless
of FORCE_P. */
@@ -2320,6 +2361,14 @@ merge_named_face (struct window *w,
Lisp_Object from[LFACE_VECTOR_SIZE], val;
bool ok = get_lface_attributes (w, f, face_name, from, false,
named_merge_points);
+ if (ok && !EQ (face_name, Qdefault))
+ {
+ struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ int i;
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ if (EQ (from[i], Qreset))
+ from[i] = deflt->lface[i];
+ }
if (ok && (attr_filter == 0 /* No filter. */
|| (!NILP (from[attr_filter]) /* Filter, but specified. */
@@ -3068,7 +3117,9 @@ FRAME 0 means change the face on all frames, and change the default
if (EQ (attr, QCfamily))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_STRING (value);
if (SCHARS (value) == 0)
@@ -3080,7 +3131,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCfoundry))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_STRING (value);
if (SCHARS (value) == 0)
@@ -3092,7 +3145,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCheight))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
if (EQ (face, Qdefault))
{
@@ -3120,7 +3175,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCweight))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_SYMBOL (value);
if (FONT_WEIGHT_NAME_NUMERIC (value) < 0)
@@ -3132,7 +3189,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCslant))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_SYMBOL (value);
if (FONT_SLANT_NAME_NUMERIC (value) < 0)
@@ -3146,7 +3205,7 @@ FRAME 0 means change the face on all frames, and change the default
{
bool valid_p = false;
- if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
+ if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value))
valid_p = true;
else if (NILP (value) || EQ (value, Qt))
valid_p = true;
@@ -3165,14 +3224,15 @@ FRAME 0 means change the face on all frames, and change the default
*/
valid_p = true;
- while (!NILP (CAR_SAFE(list)))
+ while (!NILP (CAR_SAFE (list)))
{
key = CAR_SAFE (list);
list = CDR_SAFE (list);
val = CAR_SAFE (list);
list = CDR_SAFE (list);
- if (NILP (key) || NILP (val))
+ if (NILP (key) || (NILP (val)
+ && !EQ (key, QCposition)))
{
valid_p = false;
break;
@@ -3203,7 +3263,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCoverline))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
if ((SYMBOLP (value)
&& !EQ (value, Qt)
&& !NILP (value))
@@ -3217,7 +3279,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCstrike_through))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
if ((SYMBOLP (value)
&& !EQ (value, Qt)
&& !NILP (value))
@@ -3238,7 +3302,7 @@ FRAME 0 means change the face on all frames, and change the default
if (EQ (value, Qt))
value = make_fixnum (1);
- if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
+ if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value))
valid_p = true;
else if (NILP (value))
valid_p = true;
@@ -3300,7 +3364,9 @@ FRAME 0 means change the face on all frames, and change the default
else if (EQ (attr, QCinverse_video)
|| EQ (attr, QCreverse_video))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_SYMBOL (value);
if (!EQ (value, Qt) && !NILP (value))
@@ -3311,7 +3377,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCextend))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_SYMBOL (value);
if (!EQ (value, Qt) && !NILP (value))
@@ -3325,7 +3393,9 @@ FRAME 0 means change the face on all frames, and change the default
/* Compatibility with 20.x. */
if (NILP (value))
value = Qunspecified;
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
/* Don't check for valid color names here because it depends
on the frame (display) whether the color will be valid
@@ -3342,7 +3412,9 @@ FRAME 0 means change the face on all frames, and change the default
/* Compatibility with 20.x. */
if (NILP (value))
value = Qunspecified;
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
/* Don't check for valid color names here because it depends
on the frame (display) whether the color will be valid
@@ -3359,7 +3431,9 @@ FRAME 0 means change the face on all frames, and change the default
/* Compatibility with 20.x. */
if (NILP (value))
value = Qunspecified;
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
/* Don't check for valid color names here because it depends
on the frame (display) whether the color will be valid
@@ -3374,7 +3448,9 @@ FRAME 0 means change the face on all frames, and change the default
else if (EQ (attr, QCstipple))
{
#if defined (HAVE_WINDOW_SYSTEM)
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value)
&& !NILP (value)
&& NILP (Fbitmap_spec_p (value)))
signal_error ("Invalid stipple attribute", value);
@@ -3384,7 +3460,9 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (attr, QCwidth))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
CHECK_SYMBOL (value);
if (FONT_WIDTH_NAME_NUMERIC (value) < 0)
@@ -3399,7 +3477,9 @@ FRAME 0 means change the face on all frames, and change the default
#ifdef HAVE_WINDOW_SYSTEM
if (EQ (frame, Qt) || FRAME_WINDOW_P (f))
{
- if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
+ if (!UNSPECIFIEDP (value)
+ && !IGNORE_DEFFACE_P (value)
+ && !RESET_P (value))
{
struct frame *f1;
@@ -3456,12 +3536,15 @@ FRAME 0 means change the face on all frames, and change the default
#ifdef HAVE_WINDOW_SYSTEM
if (EQ (frame, Qt) || FRAME_WINDOW_P (f))
{
- Lisp_Object tmp;
+ Lisp_Object tmp = value;
old_value = LFACE_FONTSET (lface);
- tmp = Fquery_fontset (value, Qnil);
- if (NILP (tmp))
- signal_error ("Invalid fontset name", value);
+ if (!RESET_P (value))
+ {
+ tmp = Fquery_fontset (value, Qnil);
+ if (NILP (tmp))
+ signal_error ("Invalid fontset name", value);
+ }
ASET (lface, LFACE_FONTSET_INDEX, value = tmp);
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -3483,14 +3566,20 @@ FRAME 0 means change the face on all frames, and change the default
else if (EQ (attr, QCbold))
{
old_value = LFACE_WEIGHT (lface);
- ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold);
+ if (RESET_P (value))
+ ASET (lface, LFACE_WEIGHT_INDEX, value);
+ else
+ ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold);
prop_index = FONT_WEIGHT_INDEX;
}
else if (EQ (attr, QCitalic))
{
attr = QCslant;
old_value = LFACE_SLANT (lface);
- ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic);
+ if (RESET_P (value))
+ ASET (lface, LFACE_SLANT_INDEX, value);
+ else
+ ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic);
prop_index = FONT_SLANT_INDEX;
}
else
@@ -4100,6 +4189,7 @@ Default face attributes override any local face attributes. */)
/* Ensure that the face vector is fully specified by merging
the previously-cached vector. */
memcpy (attrs, oldface->lface, sizeof attrs);
+
merge_face_vectors (NULL, f, lvec, attrs, 0);
vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE);
newface = realize_face (c, lvec, DEFAULT_FACE_ID);
@@ -4150,9 +4240,9 @@ If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
The font default for a face is either nil, or a list
of the form (bold), (italic) or (bold italic).
-If FRAME is omitted or nil, use the selected frame. And, in this case,
-if the optional third argument CHARACTER is given,
-return the font name used for CHARACTER. */)
+If FRAME is omitted or nil, use the selected frame.
+If FRAME is anything but t, and the optional third argument CHARACTER
+is given, return the font name used by FACE for CHARACTER on FRAME. */)
(Lisp_Object face, Lisp_Object frame, Lisp_Object character)
{
if (EQ (frame, Qt))
@@ -4428,17 +4518,26 @@ free_realized_face (struct frame *f, struct face *face)
void
prepare_face_for_display (struct frame *f, struct face *face)
{
+ Emacs_GC egc;
+ unsigned long mask;
+
eassert (FRAME_WINDOW_P (f));
if (face->gc == 0)
{
- Emacs_GC egc;
- unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
+ mask = GCForeground | GCBackground | GCGraphicsExposures;
egc.foreground = face->foreground;
egc.background = face->background;
#ifdef HAVE_X_WINDOWS
egc.graphics_exposures = False;
+
+ /* While this was historically slower than a line_width of 0,
+ the difference no longer matters on modern X servers, so set
+ it to 1 in order for PolyLine requests to behave consistently
+ everywhere. */
+ mask |= GCLineWidth;
+ egc.line_width = 1;
#endif
block_input ();
@@ -4857,6 +4956,13 @@ lookup_named_face (struct window *w, struct frame *f,
return -1;
memcpy (attrs, default_face->lface, sizeof attrs);
+
+ /* Make explicit any attributes whose value is 'reset'. */
+ int i;
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ if (EQ (symbol_attrs[i], Qreset))
+ symbol_attrs[i] = attrs[i];
+
merge_face_vectors (w, f, symbol_attrs, attrs, 0);
return lookup_face (f, attrs);
@@ -5027,6 +5133,13 @@ lookup_derived_face (struct window *w,
default_face = FACE_FROM_ID (f, face_id);
memcpy (attrs, default_face->lface, sizeof attrs);
+
+ /* Make explicit any attributes whose value is 'reset'. */
+ int i;
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ if (EQ (symbol_attrs[i], Qreset))
+ symbol_attrs[i] = attrs[i];
+
merge_face_vectors (w, f, symbol_attrs, attrs, 0);
return lookup_face (f, attrs);
}
@@ -5074,49 +5187,60 @@ gui_supports_face_attributes_p (struct frame *f,
struct face *def_face)
{
Lisp_Object *def_attrs = def_face->lface;
+ Lisp_Object lattrs[LFACE_VECTOR_SIZE];
+
+ /* Make explicit any attributes whose value is 'reset'. */
+ int i;
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ {
+ if (EQ (attrs[i], Qreset))
+ lattrs[i] = def_attrs[i];
+ else
+ lattrs[i] = attrs[i];
+ }
/* Check that other specified attributes are different from the
default face. */
- if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
- && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
+ if ((!UNSPECIFIEDP (lattrs[LFACE_UNDERLINE_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_UNDERLINE_INDEX],
def_attrs[LFACE_UNDERLINE_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX])
- && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_INVERSE_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_INVERSE_INDEX],
def_attrs[LFACE_INVERSE_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX])
- && face_attr_equal_p (attrs[LFACE_EXTEND_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_EXTEND_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_EXTEND_INDEX],
def_attrs[LFACE_EXTEND_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX])
- && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_FOREGROUND_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_FOREGROUND_INDEX],
def_attrs[LFACE_FOREGROUND_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX])
- && face_attr_equal_p (attrs[LFACE_DISTANT_FOREGROUND_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_DISTANT_FOREGROUND_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_DISTANT_FOREGROUND_INDEX],
def_attrs[LFACE_DISTANT_FOREGROUND_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX])
- && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_BACKGROUND_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_BACKGROUND_INDEX],
def_attrs[LFACE_BACKGROUND_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
- && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_STIPPLE_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_STIPPLE_INDEX],
def_attrs[LFACE_STIPPLE_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
- && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_OVERLINE_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_OVERLINE_INDEX],
def_attrs[LFACE_OVERLINE_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX])
- && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_STRIKE_THROUGH_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_STRIKE_THROUGH_INDEX],
def_attrs[LFACE_STRIKE_THROUGH_INDEX]))
- || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX])
- && face_attr_equal_p (attrs[LFACE_BOX_INDEX],
+ || (!UNSPECIFIEDP (lattrs[LFACE_BOX_INDEX])
+ && face_attr_equal_p (lattrs[LFACE_BOX_INDEX],
def_attrs[LFACE_BOX_INDEX])))
return false;
/* Check font-related attributes, as those are the most commonly
"unsupported" on a window-system (because of missing fonts). */
- if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX])
- || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX])
- || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX])
- || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX])
- || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX])
- || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]))
+ if (!UNSPECIFIEDP (lattrs[LFACE_FAMILY_INDEX])
+ || !UNSPECIFIEDP (lattrs[LFACE_FOUNDRY_INDEX])
+ || !UNSPECIFIEDP (lattrs[LFACE_HEIGHT_INDEX])
+ || !UNSPECIFIEDP (lattrs[LFACE_WEIGHT_INDEX])
+ || !UNSPECIFIEDP (lattrs[LFACE_SLANT_INDEX])
+ || !UNSPECIFIEDP (lattrs[LFACE_SWIDTH_INDEX]))
{
int face_id;
struct face *face;
@@ -5148,8 +5272,9 @@ gui_supports_face_attributes_p (struct frame *f,
return true;
s1 = SYMBOL_NAME (face->font->props[i]);
s2 = SYMBOL_NAME (def_face->font->props[i]);
- if (! EQ (Fcompare_strings (s1, make_fixnum (0), Qnil,
- s2, make_fixnum (0), Qnil, Qt), Qt))
+ if (! BASE_EQ (Fcompare_strings (s1, make_fixnum (0), Qnil,
+ s2, make_fixnum (0), Qnil, Qt),
+ Qt))
return true;
}
return false;
@@ -5592,7 +5717,6 @@ realize_basic_faces (struct frame *f)
if (realize_default_face (f))
{
- realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
realize_named_face (f, Qmode_line_active, MODE_LINE_ACTIVE_FACE_ID);
realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
@@ -5782,8 +5906,16 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id)
lface = Finternal_make_lisp_face (symbol, frame);
}
- /* Merge SYMBOL's face with the default face. */
+
get_lface_attributes_no_remap (f, symbol, symbol_attrs, true);
+
+ /* Handle the 'reset' pseudo-value of any attribute by replacing it
+ with the corresponding value of the default face. */
+ int i;
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ if (EQ (symbol_attrs[i], Qreset))
+ symbol_attrs[i] = attrs[i];
+ /* Merge SYMBOL's face with the default face. */
merge_face_vectors (NULL, f, symbol_attrs, attrs, 0);
/* Realize the face. */
@@ -5880,7 +6012,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
#ifdef HAVE_WINDOW_SYSTEM
struct face *default_face;
struct frame *f;
- Lisp_Object stipple, underline, overline, strike_through, box;
+ Lisp_Object stipple, underline, overline, strike_through, box, temp_spec;
+ Lisp_Object temp_extra, antialias;
eassert (FRAME_WINDOW_P (cache->f));
@@ -5922,8 +6055,28 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
emacs_abort ();
}
if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
- attrs[LFACE_FONT_INDEX]
- = font_load_for_lface (f, attrs, Ffont_spec (0, NULL));
+ {
+ /* We want attrs to allow overriding most elements in the
+ spec (IOW, to start out as an empty font spec), but
+ preserve the antialiasing attribute. (bug#17973,
+ bug#37473). */
+ temp_spec = Ffont_spec (0, NULL);
+ temp_extra = AREF (attrs[LFACE_FONT_INDEX],
+ FONT_EXTRA_INDEX);
+ /* If `:antialias' wasn't specified, keep it unspecified
+ instead of changing it to nil. */
+
+ if (CONSP (temp_extra))
+ antialias = Fassq (QCantialias, temp_extra);
+ else
+ antialias = Qnil;
+
+ if (FONTP (attrs[LFACE_FONT_INDEX]) && !NILP (antialias))
+ Ffont_put (temp_spec, QCantialias, Fcdr (antialias));
+
+ attrs[LFACE_FONT_INDEX]
+ = font_load_for_lface (f, attrs, temp_spec);
+ }
if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
{
face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
@@ -5978,6 +6131,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
}
else if (CONSP (box))
{
+ bool set_color = false;
+
/* `(:width WIDTH :color COLOR :shadow SHADOW)'. SHADOW
being one of `raised' or `sunken'. */
face->box = FACE_SIMPLE_BOX;
@@ -6015,6 +6170,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->box_color = load_color (f, face, value,
LFACE_BOX_INDEX);
face->use_box_color_for_shadows_p = true;
+ set_color = true;
}
}
else if (EQ (keyword, QCstyle))
@@ -6026,7 +6182,9 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
else if (EQ (value, Qflat_button))
{
face->box = FACE_SIMPLE_BOX;
- face->box_color = face->background;
+ /* Don't override colors set in this box. */
+ if (!set_color)
+ face->box_color = face->background;
}
}
}
@@ -6041,6 +6199,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->underline = FACE_UNDER_LINE;
face->underline_defaulted_p = true;
face->underline_color = 0;
+ face->underline_at_descent_line_p = false;
+ face->underline_pixels_above_descent_line = 0;
}
else if (STRINGP (underline))
{
@@ -6050,12 +6210,16 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->underline_color
= load_color (f, face, underline,
LFACE_UNDERLINE_INDEX);
+ face->underline_at_descent_line_p = false;
+ face->underline_pixels_above_descent_line = 0;
}
else if (NILP (underline))
{
face->underline = FACE_NO_UNDERLINE;
face->underline_defaulted_p = false;
face->underline_color = 0;
+ face->underline_at_descent_line_p = false;
+ face->underline_pixels_above_descent_line = 0;
}
else if (CONSP (underline))
{
@@ -6064,6 +6228,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
face->underline = FACE_UNDER_LINE;
face->underline_color = 0;
face->underline_defaulted_p = true;
+ face->underline_at_descent_line_p = false;
+ face->underline_pixels_above_descent_line = 0;
/* FIXME? This is also not robust about checking the precise form.
See comments in Finternal_set_lisp_face_attribute. */
@@ -6100,6 +6266,13 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
else if (EQ (value, Qwave))
face->underline = FACE_UNDER_WAVE;
}
+ else if (EQ (keyword, QCposition))
+ {
+ face->underline_at_descent_line_p = !NILP (value);
+
+ if (FIXNATP (value))
+ face->underline_pixels_above_descent_line = XFIXNAT (value);
+ }
}
}
@@ -6408,8 +6581,12 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
cached faces since we've looked up these faces, we need to look
them up again. */
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. */
@@ -6676,7 +6853,21 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id,
if (!face)
return base_face_id;
- merge_face_vectors (w, f, face->lface, attrs, 0);
+ if (face_id != DEFAULT_FACE_ID)
+ {
+ struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ Lisp_Object lface_attrs[LFACE_VECTOR_SIZE];
+ int i;
+
+ memcpy (lface_attrs, face->lface, LFACE_VECTOR_SIZE);
+ /* Make explicit any attributes whose value is 'reset'. */
+ for (i = 1; i < LFACE_VECTOR_SIZE; i++)
+ if (EQ (lface_attrs[i], Qreset))
+ lface_attrs[i] = deflt->lface[i];
+ merge_face_vectors (w, f, lface_attrs, attrs, 0);
+ }
+ else
+ merge_face_vectors (w, f, face->lface, attrs, 0);
}
/* Look up a realized face with the given face attributes,
@@ -6820,7 +7011,6 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
Initialization
***********************************************************************/
-#ifdef HAVE_PDUMPER
/* All the faces defined during loadup are recorded in
face-new-frame-defaults. We need to set next_lface_id to the next
face ID number, so that any new faces defined in this session will
@@ -6830,26 +7020,35 @@ DEFUN ("show-face-resources", Fshow_face_resources, Sshow_face_resources,
void
init_xfaces (void)
{
- int nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults));
- if (nfaces > 0)
- {
- /* Allocate the lface_id_to_name[] array. */
- lface_id_to_name_size = next_lface_id = nfaces;
- lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name);
+#ifdef HAVE_PDUMPER
+ int nfaces;
- /* Store the faces. */
- struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults);
- for (ptrdiff_t idx = 0; idx < nfaces; ++idx)
+ if (dumped_with_pdumper_p ())
+ {
+ nfaces = XFIXNAT (Fhash_table_count (Vface_new_frame_defaults));
+ if (nfaces > 0)
{
- Lisp_Object lface = HASH_KEY (table, idx);
- Lisp_Object face_id = CAR (HASH_VALUE (table, idx));
- if (FIXNATP (face_id)) {
- int id = XFIXNAT (face_id);
- eassert (id >= 0);
- lface_id_to_name[id] = lface;
- }
+ /* Allocate the lface_id_to_name[] array. */
+ lface_id_to_name_size = next_lface_id = nfaces;
+ lface_id_to_name = xnmalloc (next_lface_id, sizeof *lface_id_to_name);
+
+ /* Store the faces. */
+ struct Lisp_Hash_Table* table = XHASH_TABLE (Vface_new_frame_defaults);
+ for (ptrdiff_t idx = 0; idx < nfaces; ++idx)
+ {
+ Lisp_Object lface = HASH_KEY (table, idx);
+ Lisp_Object face_id = CAR (HASH_VALUE (table, idx));
+ if (FIXNATP (face_id))
+ {
+ int id = XFIXNAT (face_id);
+ eassert (id >= 0);
+ lface_id_to_name[id] = lface;
+ }
+ }
}
}
+#endif
+
face_attr_sym[0] = Qface;
face_attr_sym[LFACE_FOUNDRY_INDEX] = QCfoundry;
face_attr_sym[LFACE_SWIDTH_INDEX] = QCwidth;
@@ -6870,7 +7069,6 @@ init_xfaces (void)
face_attr_sym[LFACE_DISTANT_FOREGROUND_INDEX] = QCdistant_foreground;
face_attr_sym[LFACE_EXTEND_INDEX] = QCextend;
}
-#endif
void
syms_of_xfaces (void)
@@ -6915,6 +7113,7 @@ syms_of_xfaces (void)
DEFSYM (QCcolor, ":color");
DEFSYM (QCline_width, ":line-width");
DEFSYM (QCstyle, ":style");
+ DEFSYM (QCposition, ":position");
DEFSYM (Qline, "line");
DEFSYM (Qwave, "wave");
DEFSYM (Qreleased_button, "released-button");
@@ -6937,6 +7136,7 @@ syms_of_xfaces (void)
DEFSYM (Qblack, "black");
DEFSYM (Qoblique, "oblique");
DEFSYM (Qitalic, "italic");
+ DEFSYM (Qreset, "reset");
/* The symbols `foreground-color' and `background-color' which can be
used as part of a `face' property. This is for compatibility with
diff --git a/src/xfns.c b/src/xfns.c
index fd3b8752449..331f22763ee 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -40,6 +40,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef USE_XCB
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_aux.h>
+#endif
+
#include "bitmaps/gray.xbm"
#include "xsettings.h"
@@ -604,7 +610,7 @@ x_relative_mouse_position (struct frame *f, int *x, int *y)
block_input ();
XQueryPointer (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ FRAME_DISPLAY_INFO (f)->root_window,
/* The root window which contains the pointer. */
&root,
@@ -681,7 +687,7 @@ x_defined_color (struct frame *f, const char *color_name,
is a monochrome frame, return MONO_COLOR regardless of what ARG says.
Signal an error if color can't be allocated. */
-static int
+static unsigned long
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
{
XColor cdef;
@@ -722,6 +728,78 @@ x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value
}
static void
+x_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ unsigned long opaque_region[] = {0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f)};
+#ifdef HAVE_GTK3
+ GObjectClass *object_class;
+ GtkWidgetClass *class;
+#endif
+
+ gui_set_alpha_background (f, arg, oldval);
+
+#ifdef HAVE_XRENDER
+ /* Setting `alpha_background' to something other than opaque on a
+ display that doesn't support the required features leads to
+ confusing results. */
+ if (f->alpha_background < 1.0
+ && !FRAME_DISPLAY_INFO (f)->alpha_bits
+ && !FRAME_CHECK_XR_VERSION (f, 0, 2))
+ f->alpha_background = 1.0;
+#else
+ f->alpha_background = 1.0;
+#endif
+
+#ifdef USE_GTK
+ /* This prevents GTK from painting the window's background, which
+ interferes with transparent background in some environments */
+
+ if (!FRAME_TOOLTIP_P (f))
+ gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f),
+ f->alpha_background != 1.0);
+#endif
+
+ if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
+ return;
+
+ if (f->alpha_background != 1.0)
+ {
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ NULL, 0);
+ }
+#ifndef HAVE_GTK3
+ else
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &opaque_region, 4);
+#else
+ else
+ {
+ if (FRAME_TOOLTIP_P (f))
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &opaque_region, 4);
+ else
+ {
+ object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
+ class = GTK_WIDGET_CLASS (object_class);
+
+ if (class->style_updated)
+ class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
+ }
+ }
+#endif
+}
+
+static void
x_set_tool_bar_position (struct frame *f,
Lisp_Object new_value,
Lisp_Object old_value)
@@ -745,22 +823,36 @@ x_set_tool_bar_position (struct frame *f,
wrong_choice (choice, new_value);
}
+#ifdef HAVE_XDBE
static void
x_set_inhibit_double_buffering (struct frame *f,
Lisp_Object new_value,
Lisp_Object old_value)
{
- block_input ();
+ bool want_double_buffering, was_double_buffered;
+
if (FRAME_X_WINDOW (f) && !EQ (new_value, old_value))
{
- bool want_double_buffering = NILP (new_value);
- bool was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
- /* font_drop_xrender_surfaces in xftfont does something only if
- we're double-buffered, so call font_drop_xrender_surfaces before
- and after any potential change. One of the calls will end up
- being a no-op. */
+ want_double_buffering = NILP (new_value);
+ was_double_buffered = FRAME_X_DOUBLE_BUFFERED_P (f);
+
+ block_input ();
if (want_double_buffering != was_double_buffered)
- font_drop_xrender_surfaces (f);
+ {
+ /* Force XftDraw etc to be recreated with the new double
+ buffered drawable. */
+ font_drop_xrender_surfaces (f);
+
+ /* Scroll bars decide whether or not to use a back buffer
+ based on the value of this frame parameter, so destroy
+ all scroll bars. */
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
+ FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
+ if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
+ FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
+#endif
+ }
if (FRAME_X_DOUBLE_BUFFERED_P (f) && !want_double_buffering)
tear_down_x_back_buffer (f);
else if (!FRAME_X_DOUBLE_BUFFERED_P (f) && want_double_buffering)
@@ -770,9 +862,10 @@ x_set_inhibit_double_buffering (struct frame *f,
SET_FRAME_GARBAGED (f);
font_drop_xrender_surfaces (f);
}
+ unblock_input ();
}
- unblock_input ();
}
+#endif
/**
* x_set_undecorated:
@@ -797,7 +890,7 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value
#else
Display *dpy = FRAME_X_DISPLAY (f);
PropMotifWmHints hints;
- Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
+ Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
memset (&hints, 0, sizeof(hints));
hints.flags = MWM_HINTS_DECORATIONS;
@@ -849,6 +942,9 @@ static void
x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
{
struct frame *p = NULL;
+#ifdef HAVE_GTK3
+ GdkWindow *window;
+#endif
if (!NILP (new_value)
&& (!FRAMEP (new_value)
@@ -864,7 +960,7 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
block_input ();
XReparentWindow
(FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
- p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ p ? FRAME_X_WINDOW (p) : FRAME_DISPLAY_INFO (f)->root_window,
f->left_pos, f->top_pos);
#ifdef USE_GTK
if (EQ (x_gtk_resize_child_frames, Qresize_mode))
@@ -872,6 +968,14 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
(GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
#endif
+
+#ifdef HAVE_GTK3
+ if (p)
+ {
+ window = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
+ gdk_x11_window_set_frame_sync_enabled (window, FALSE);
+ }
+#endif
unblock_input ();
fset_parent_frame (f, new_value);
@@ -898,7 +1002,7 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_v
xg_set_no_focus_on_map (f, new_value);
#else /* not USE_GTK */
Display *dpy = FRAME_X_DISPLAY (f);
- Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
+ Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_net_wm_user_time;
Time timestamp = NILP (new_value) ? CurrentTime : 0;
XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
@@ -1157,25 +1261,27 @@ struct mouse_cursor_types {
};
/* This array must stay in sync with enum mouse_cursor above! */
-static const struct mouse_cursor_types mouse_cursor_types[] = {
- { "text", &Vx_pointer_shape, XC_xterm },
- { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
- { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
- { "modeline", &Vx_mode_pointer_shape, XC_xterm },
- { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
- { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
- { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
- { NULL, &Vx_window_left_edge_shape, XC_left_side },
- { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner },
- { NULL, &Vx_window_top_edge_shape, XC_top_side },
- { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner },
- { NULL, &Vx_window_right_edge_shape, XC_right_side },
- { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
- { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side },
- { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner },
-};
+static const struct mouse_cursor_types mouse_cursor_types[] =
+ {
+ { "text", &Vx_pointer_shape, XC_xterm },
+ { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
+ { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
+ { "modeline", &Vx_mode_pointer_shape, XC_xterm },
+ { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
+ { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
+ { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
+ { NULL, &Vx_window_left_edge_shape, XC_left_side },
+ { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner },
+ { NULL, &Vx_window_top_edge_shape, XC_top_side },
+ { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner },
+ { NULL, &Vx_window_right_edge_shape, XC_right_side },
+ { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
+ { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side },
+ { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner },
+ };
-struct mouse_cursor_data {
+struct mouse_cursor_data
+{
/* Last index for which XCreateFontCursor has been called, and thus
the last index for which x_request_serial[] is valid. */
int last_cursor_create_request;
@@ -1256,8 +1362,10 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
cursor_data.x_request_serial[i] = XNextRequest (dpy);
cursor_data.last_cursor_create_request = i;
- cursor_data.cursor[i] = XCreateFontCursor (dpy,
- cursor_data.cursor_num[i]);
+
+ cursor_data.cursor[i]
+ = x_create_font_cursor (FRAME_DISPLAY_INFO (f),
+ cursor_data.cursor_num[i]);
}
/* Now sync up and process all received errors from cursor
@@ -1409,11 +1517,26 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
F has an x-window. */
static void
-x_set_border_pixel (struct frame *f, int pix)
+x_set_border_pixel (struct frame *f, unsigned long pix)
{
unload_color (f, f->output_data.x->border_pixel);
f->output_data.x->border_pixel = pix;
+#ifdef USE_X_TOOLKIT
+ if (f->output_data.x->widget && f->border_width > 0)
+ {
+ block_input ();
+ XtVaSetValues (f->output_data.x->widget, XtNborderColor,
+ (Pixel) pix, NULL);
+ unblock_input ();
+
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+
+ return;
+ }
+#endif
+
if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
{
block_input ();
@@ -1439,7 +1562,7 @@ x_set_border_pixel (struct frame *f, int pix)
static void
x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
- int pix;
+ unsigned long pix;
CHECK_STRING (arg);
pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
@@ -1461,7 +1584,7 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg))
@@ -1493,7 +1616,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
if (STRINGP (arg))
{
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
return;
}
else if (!NILP (arg) || NILP (oldval))
@@ -1847,6 +1970,10 @@ static void
x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
unsigned long pixel;
+#ifdef HAVE_GTK3
+ XColor color;
+ char css[64];
+#endif
if (STRINGP (value))
pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
@@ -1868,6 +1995,28 @@ x_set_scroll_bar_foreground (struct frame *f, Lisp_Object value, Lisp_Object old
update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
redraw_frame (f);
}
+
+#ifdef HAVE_GTK3
+ if (!FRAME_TOOLTIP_P (f))
+ {
+ if (pixel != -1)
+ {
+ color.pixel = pixel;
+
+ XQueryColor (FRAME_X_DISPLAY (f),
+ FRAME_X_COLORMAP (f),
+ &color);
+
+ sprintf (css, "scrollbar slider { background-color: #%02x%02x%02x; }",
+ color.red >> 8, color.green >> 8, color.blue >> 8);
+ gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider,
+ css, -1, NULL);
+ }
+ else
+ gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider,
+ "", -1, NULL);
+ }
+#endif
}
@@ -1880,6 +2029,10 @@ static void
x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object oldval)
{
unsigned long pixel;
+#ifdef HAVE_GTK3
+ XColor color;
+ char css[64];
+#endif
if (STRINGP (value))
pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
@@ -1915,11 +2068,33 @@ x_set_scroll_bar_background (struct frame *f, Lisp_Object value, Lisp_Object old
update_face_from_frame_parameter (f, Qscroll_bar_background, value);
redraw_frame (f);
}
+
+#ifdef HAVE_GTK3
+ if (!FRAME_TOOLTIP_P (f))
+ {
+ if (pixel != -1)
+ {
+ color.pixel = pixel;
+
+ XQueryColor (FRAME_X_DISPLAY (f),
+ FRAME_X_COLORMAP (f),
+ &color);
+
+ sprintf (css, "scrollbar trough { background-color: #%02x%02x%02x; }",
+ color.red >> 8, color.green >> 8, color.blue >> 8);
+ gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider,
+ css, -1, NULL);
+ }
+ else
+ gtk_css_provider_load_from_data (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider,
+ "", -1, NULL);
+ }
+#endif
}
/* Encode Lisp string STRING as a text in a format appropriate for
- XICCC (X Inter Client Communication Conventions).
+ the ICCCM (Inter Client Communication Conventions Manual).
If STRING contains only ASCII characters, do no conversion and
return the string data of STRING. Otherwise, encode the text by
@@ -2201,6 +2376,63 @@ x_set_scroll_bar_default_height (struct frame *f)
#endif
}
+static void
+x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ double alpha = 1.0;
+ double newval[2];
+ int i;
+ Lisp_Object item;
+ bool alpha_identical_p;
+
+ alpha_identical_p = true;
+
+ for (i = 0; i < 2; i++)
+ {
+ newval[i] = 1.0;
+ if (CONSP (arg))
+ {
+ item = CAR (arg);
+ arg = CDR (arg);
+
+ alpha_identical_p = false;
+ }
+ else
+ item = arg;
+
+ if (NILP (item))
+ alpha = - 1.0;
+ else if (FLOATP (item))
+ {
+ alpha = XFLOAT_DATA (item);
+ if (! (0 <= alpha && alpha <= 1.0))
+ args_out_of_range (make_float (0.0), make_float (1.0));
+ }
+ else if (FIXNUMP (item))
+ {
+ EMACS_INT ialpha = XFIXNUM (item);
+ if (! (0 <= ialpha && ialpha <= 100))
+ args_out_of_range (make_fixnum (0), make_fixnum (100));
+ alpha = ialpha / 100.0;
+ }
+ else
+ wrong_type_argument (Qnumberp, item);
+ newval[i] = alpha;
+ }
+
+ for (i = 0; i < 2; i++)
+ f->alpha[i] = newval[i];
+
+ FRAME_X_OUTPUT (f)->alpha_identical_p = alpha_identical_p;
+
+ if (FRAME_TERMINAL (f)->set_frame_alpha_hook)
+ {
+ block_input ();
+ FRAME_TERMINAL (f)->set_frame_alpha_hook (f);
+ unblock_input ();
+ }
+}
+
/* Record in frame F the specified or default value according to ALIST
of the parameter named PROP (a Lisp symbol). If no value is
@@ -2218,7 +2450,7 @@ x_default_scroll_bar_color_parameter (struct frame *f,
tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass,
RES_TYPE_STRING);
- if (EQ (tem, Qunbound))
+ if (BASE_EQ (tem, Qunbound))
{
#ifdef USE_TOOLKIT_SCROLL_BARS
@@ -2325,6 +2557,67 @@ hack_wm_protocols (struct frame *f, Widget widget)
}
#endif
+static void
+append_wm_protocols (struct x_display_info *dpyinfo,
+ struct frame *f)
+{
+ unsigned char *existing = NULL;
+ int format = 0;
+ unsigned long nitems = 0;
+ Atom type;
+ Atom *existing_protocols;
+ Atom protos[10];
+ int num_protos = 0;
+ bool found_wm_ping = false;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+ bool found_wm_sync_request = false;
+#endif
+ unsigned long bytes_after;
+
+ block_input ();
+ if ((XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_wm_protocols,
+ 0, 100, False, XA_ATOM, &type, &format, &nitems,
+ &bytes_after, &existing) == Success)
+ && format == 32 && type == XA_ATOM)
+ {
+ existing_protocols = (Atom *) existing;
+
+ while (nitems)
+ {
+ nitems--;
+
+ if (existing_protocols[nitems]
+ == dpyinfo->Xatom_net_wm_ping)
+ found_wm_ping = true;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+ else if (existing_protocols[nitems]
+ == dpyinfo->Xatom_net_wm_sync_request)
+ found_wm_sync_request = true;
+#endif
+ }
+ }
+
+ if (existing)
+ XFree (existing);
+
+ if (!found_wm_ping)
+ protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
+#if !defined HAVE_GTK3 && defined HAVE_XSYNC
+ if (!found_wm_sync_request && dpyinfo->xsync_supported_p)
+ protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
+#endif
+
+ if (num_protos)
+ XChangeProperty (dpyinfo->display,
+ FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_wm_protocols,
+ XA_ATOM, 32, PropModeAppend,
+ (unsigned char *) protos,
+ num_protos);
+ unblock_input ();
+}
+
/* Support routines for XIC (X Input Context). */
@@ -2336,14 +2629,19 @@ static void xic_preedit_caret_callback (XIC, XPointer, XIMPreeditCaretCallbackSt
static void xic_preedit_done_callback (XIC, XPointer, XPointer);
static int xic_preedit_start_callback (XIC, XPointer, XPointer);
+#ifndef HAVE_XICCALLBACK_CALLBACK
+#define XICCallback XIMCallback
+#define XICProc XIMProc
+#endif
+
static XIMCallback Xxic_preedit_draw_callback = { NULL,
(XIMProc) xic_preedit_draw_callback };
static XIMCallback Xxic_preedit_caret_callback = { NULL,
(XIMProc) xic_preedit_caret_callback };
static XIMCallback Xxic_preedit_done_callback = { NULL,
(XIMProc) xic_preedit_done_callback };
-static XIMCallback Xxic_preedit_start_callback = { NULL,
- (void *) xic_preedit_start_callback };
+static XICCallback Xxic_preedit_start_callback = { NULL,
+ (XICProc) xic_preedit_start_callback };
#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
/* Create an X fontset on frame F with base font name BASE_FONTNAME. */
@@ -2643,11 +2941,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)
@@ -2816,20 +3110,49 @@ free_frame_xic (struct frame *f)
void
xic_set_preeditarea (struct window *w, int x, int y)
{
- struct frame *f = XFRAME (w->frame);
+ struct frame *f = WINDOW_XFRAME (w);
XVaNestedList attr;
XPoint spot;
- spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + WINDOW_LEFT_MARGIN_WIDTH(w);
- spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
- attr = XVaCreateNestedList (0, XNSpotLocation, &spot,
- XNPreeditStartCallback, &Xxic_preedit_start_callback,
- XNPreeditDoneCallback, &Xxic_preedit_done_callback,
- XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
- XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
- NULL);
- XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
- XFree (attr);
+ if (FRAME_XIC (f))
+ {
+ spot.x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
+ + WINDOW_LEFT_FRINGE_WIDTH (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w));
+ spot.y = (WINDOW_TO_FRAME_PIXEL_Y (w, y)
+ + w->phys_cursor_height);
+
+ if (FRAME_XIC_STYLE (f) & XIMPreeditCallbacks)
+ attr = XVaCreateNestedList (0, XNSpotLocation, &spot,
+ XNPreeditStartCallback, &Xxic_preedit_start_callback,
+ XNPreeditDoneCallback, &Xxic_preedit_done_callback,
+ XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
+ XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
+ NULL);
+ else
+ attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
+ XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
+ XFree (attr);
+ }
+#ifdef USE_GTK
+ if (f->tooltip)
+ return;
+
+ GdkRectangle rect;
+ int scale = xg_get_scale (f);
+
+ rect.x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
+ + WINDOW_LEFT_FRINGE_WIDTH (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w)) / scale;
+ rect.y = (WINDOW_TO_FRAME_PIXEL_Y (w, y)
+ + FRAME_TOOLBAR_HEIGHT (f)
+ + FRAME_MENUBAR_HEIGHT (f)) / scale;
+ rect.width = w->phys_cursor_width / scale;
+ rect.height = w->phys_cursor_height / scale;
+
+ gtk_im_context_set_cursor_location (FRAME_X_OUTPUT (f)->im_context,
+ &rect);
+#endif
}
@@ -2905,6 +3228,7 @@ xic_preedit_start_callback (XIC xic, XPointer client_data,
output->preedit_size = 0;
output->preedit_active = true;
+ output->preedit_caret = 0;
if (output->preedit_chars)
xfree (output->preedit_chars);
@@ -2919,7 +3243,55 @@ static void
xic_preedit_caret_callback (XIC xic, XPointer client_data,
XIMPreeditCaretCallbackStruct *call_data)
{
+ struct frame *f = x_xic_to_frame (xic);
+ struct x_output *output;
+ struct input_event ie;
+ EVENT_INIT (ie);
+
+ if (f)
+ {
+ output = FRAME_X_OUTPUT (f);
+
+ if (!output->preedit_active)
+ return;
+
+ switch (call_data->direction)
+ {
+ case XIMAbsolutePosition:
+ output->preedit_caret = call_data->position;
+ break;
+ case XIMForwardChar:
+ case XIMForwardWord:
+ call_data->position = output->preedit_caret++;
+ break;
+ case XIMBackwardChar:
+ case XIMBackwardWord:
+ call_data->position = max (0, output->preedit_caret--);
+ break;
+ default:
+ call_data->position = output->preedit_caret;
+ }
+ if (output->preedit_chars)
+ {
+ ie.kind = PREEDIT_TEXT_EVENT;
+ XSETFRAME (ie.frame_or_window, f);
+ ie.arg = make_string_from_utf8 (output->preedit_chars,
+ output->preedit_size);
+
+ if (SCHARS (ie.arg))
+ Fput_text_property (make_fixnum (min (SCHARS (ie.arg) - 1,
+ max (0, output->preedit_caret))),
+ make_fixnum (max (SCHARS (ie.arg),
+ max (0, output->preedit_caret) + 1)),
+ Qcursor, Qt, ie.arg);
+
+ XSETINT (ie.x, 0);
+ XSETINT (ie.y, 0);
+
+ kbd_buffer_store_event (&ie);
+ }
+ }
}
@@ -2930,6 +3302,7 @@ xic_preedit_done_callback (XIC xic, XPointer client_data,
struct frame *f = x_xic_to_frame (xic);
struct x_output *output;
struct input_event ie;
+ EVENT_INIT (ie);
if (f)
{
@@ -2948,17 +3321,68 @@ xic_preedit_done_callback (XIC xic, XPointer client_data,
output->preedit_size = 0;
output->preedit_active = false;
output->preedit_chars = NULL;
+ output->preedit_caret = 0;
}
}
+struct x_xim_text_conversion_data
+{
+ struct coding_system *coding;
+ char *source;
+};
+
+static Lisp_Object
+x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs,
+ Lisp_Object *args)
+{
+ struct x_xim_text_conversion_data *data;
+ ptrdiff_t nbytes;
+
+ data = xmint_pointer (args[0]);
+ nbytes = strlen (data->source);
+
+ data->coding->destination = NULL;
+
+ setup_coding_system (Vlocale_coding_system,
+ data->coding);
+ data->coding->mode |= (CODING_MODE_LAST_BLOCK
+ | CODING_MODE_SAFE_ENCODING);
+ data->coding->source = (const unsigned char *) data->source;
+ data->coding->dst_bytes = 2048;
+ data->coding->destination = xmalloc (2048);
+ decode_coding_object (data->coding, Qnil, 0, 0,
+ nbytes, nbytes, Qnil);
+
+ return Qnil;
+}
+
+static Lisp_Object
+x_xim_text_to_utf8_unix_2 (Lisp_Object val,
+ ptrdiff_t nargs,
+ Lisp_Object *args)
+{
+ struct x_xim_text_conversion_data *data;
+
+ data = xmint_pointer (args[0]);
+
+ if (data->coding->destination)
+ xfree (data->coding->destination);
+
+ data->coding->destination = NULL;
+
+ return Qnil;
+}
+
/* The string returned is not null-terminated. */
static char *
x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
{
unsigned char *wchar_buf;
ptrdiff_t wchar_actual_length, i;
- ptrdiff_t nbytes;
struct coding_system coding;
+ struct x_xim_text_conversion_data data;
+ bool was_waiting_for_input_p;
+ Lisp_Object arg;
if (text->encoding_is_wchar)
{
@@ -2973,17 +3397,16 @@ x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
return (char *) wchar_buf;
}
- nbytes = strlen (text->string.multi_byte);
- setup_coding_system (Qutf_8_unix, &coding);
- coding.mode |= (CODING_MODE_LAST_BLOCK
- | CODING_MODE_SAFE_ENCODING);
- coding.source = (const unsigned char *) text->string.multi_byte;
- coding.dst_bytes = 2048;
- coding.destination = xmalloc (2048);
- decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qnil);
+ data.coding = &coding;
+ data.source = text->string.multi_byte;
- /* coding.destination has either been allocated by us, or
- reallocated by decode_coding_object. */
+ was_waiting_for_input_p = waiting_for_input;
+ /* Otherwise Fsignal will crash. */
+ waiting_for_input = false;
+ arg = make_mint_ptr (&data);
+ internal_condition_case_n (x_xim_text_to_utf8_unix_1, 1, &arg,
+ Qt, x_xim_text_to_utf8_unix_2);
+ waiting_for_input = was_waiting_for_input_p;
*length = coding.produced;
return (char *) coding.destination;
@@ -2995,12 +3418,13 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
{
struct frame *f = x_xic_to_frame (xic);
struct x_output *output;
- ptrdiff_t text_length;
+ ptrdiff_t text_length = 0;
ptrdiff_t charpos;
ptrdiff_t original_size;
char *text;
char *chg_start, *chg_end;
struct input_event ie;
+ EVENT_INIT (ie);
if (f)
{
@@ -3010,7 +3434,13 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
return;
if (call_data->text)
- text = x_xim_text_to_utf8_unix (call_data->text, &text_length);
+ {
+ text = x_xim_text_to_utf8_unix (call_data->text, &text_length);
+
+ if (!text)
+ /* Decoding the IM text failed. */
+ goto im_abort;
+ }
else
text = NULL;
@@ -3118,6 +3548,8 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
if (text)
xfree (text);
+ output->preedit_caret = call_data->caret;
+
/* This is okay because this callback is called from the big XIM
event filter, which runs inside XTread_socket. */
@@ -3125,6 +3557,14 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
XSETFRAME (ie.frame_or_window, f);
ie.arg = make_string_from_utf8 (output->preedit_chars,
output->preedit_size);
+
+ if (SCHARS (ie.arg))
+ Fput_text_property (make_fixnum (min (SCHARS (ie.arg) - 1,
+ max (0, output->preedit_caret))),
+ make_fixnum (min (SCHARS (ie.arg),
+ max (0, output->preedit_caret) + 1)),
+ Qcursor, Qt, ie.arg);
+
XSETINT (ie.x, 0);
XSETINT (ie.y, 0);
@@ -3141,6 +3581,7 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
output->preedit_chars = NULL;
output->preedit_size = 0;
output->preedit_active = false;
+ output->preedit_caret = 0;
}
void
@@ -3171,13 +3612,27 @@ xic_set_xfontset (struct frame *f, const char *base_fontname)
void
x_mark_frame_dirty (struct frame *f)
{
- if (FRAME_X_DOUBLE_BUFFERED_P (f) && !FRAME_X_NEED_BUFFER_FLIP (f))
+#ifdef HAVE_XDBE
+ if (FRAME_X_DOUBLE_BUFFERED_P (f)
+ && !FRAME_X_NEED_BUFFER_FLIP (f))
FRAME_X_NEED_BUFFER_FLIP (f) = true;
+#endif
}
static void
set_up_x_back_buffer (struct frame *f)
{
+#ifdef HAVE_XRENDER
+ block_input ();
+ if (FRAME_X_PICTURE (f) != None)
+ {
+ XRenderFreePicture (FRAME_X_DISPLAY (f),
+ FRAME_X_PICTURE (f));
+ FRAME_X_PICTURE (f) = None;
+ }
+ unblock_input ();
+#endif
+
#ifdef HAVE_XDBE
block_input ();
if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
@@ -3192,10 +3647,10 @@ set_up_x_back_buffer (struct frame *f)
server ran out of memory or we don't have the right kind
of visual, just use single-buffered rendering. */
x_catch_errors (FRAME_X_DISPLAY (f));
- FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName (
- FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- XdbeCopied);
+ FRAME_X_RAW_DRAWABLE (f)
+ = XdbeAllocateBackBufferName (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ XdbeCopied);
if (x_had_errors_p (FRAME_X_DISPLAY (f)))
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
x_uncatch_errors_after_check ();
@@ -3208,6 +3663,17 @@ set_up_x_back_buffer (struct frame *f)
void
tear_down_x_back_buffer (struct frame *f)
{
+#ifdef HAVE_XRENDER
+ block_input ();
+ if (FRAME_X_PICTURE (f) != None)
+ {
+ XRenderFreePicture (FRAME_X_DISPLAY (f),
+ FRAME_X_PICTURE (f));
+ FRAME_X_PICTURE (f) = None;
+ }
+ unblock_input ();
+#endif
+
#ifdef HAVE_XDBE
block_input ();
if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
@@ -3231,12 +3697,12 @@ tear_down_x_back_buffer (struct frame *f)
void
initial_set_up_x_back_buffer (struct frame *f)
{
- block_input ();
eassert (FRAME_X_WINDOW (f));
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
- if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist))))
+
+ if (NILP (CDR (Fassq (Qinhibit_double_buffering,
+ f->param_alist))))
set_up_x_back_buffer (f);
- unblock_input ();
}
#if defined HAVE_XINPUT2
@@ -3246,13 +3712,23 @@ setup_xi_event_mask (struct frame *f)
XIEventMask mask;
ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
unsigned char *m;
+#ifndef HAVE_XINPUT2_1
+ /* Set up fallback values, since XIGetSelectedEvents doesn't work
+ with this version of libXi. */
+ XIEventMask *selected;
+
+ selected = xzalloc (sizeof *selected + l);
+ selected->mask = ((unsigned char *) selected) + sizeof *selected;
+ selected->mask_len = l;
+ selected->deviceid = XIAllMasterDevices;
+#endif
mask.mask = m = alloca (l);
memset (m, 0, l);
mask.mask_len = l;
block_input ();
-#ifndef USE_GTK
+#ifndef HAVE_GTK3
mask.deviceid = XIAllMasterDevices;
XISetMask (m, XI_ButtonPress);
@@ -3260,18 +3736,30 @@ setup_xi_event_mask (struct frame *f)
XISetMask (m, XI_Motion);
XISetMask (m, XI_Enter);
XISetMask (m, XI_Leave);
+#ifndef USE_GTK
+ XISetMask (m, XI_FocusIn);
+ XISetMask (m, XI_FocusOut);
XISetMask (m, XI_KeyPress);
XISetMask (m, XI_KeyRelease);
+#endif
XISelectEvents (FRAME_X_DISPLAY (f),
FRAME_X_WINDOW (f),
&mask, 1);
+ /* Fortunately `xi_masks' isn't used on GTK 3, where we really have
+ to get the event mask from the X server. */
+#ifndef HAVE_XINPUT2_1
+ memcpy (selected->mask, m, l);
+#endif
+
memset (m, 0, l);
-#endif /* !USE_GTK */
+#endif /* !HAVE_GTK3 */
#ifdef USE_X_TOOLKIT
XISetMask (m, XI_KeyPress);
XISetMask (m, XI_KeyRelease);
+ XISetMask (m, XI_FocusIn);
+ XISetMask (m, XI_FocusOut);
XISelectEvents (FRAME_X_DISPLAY (f),
FRAME_OUTER_WINDOW (f),
@@ -3284,13 +3772,13 @@ setup_xi_event_mask (struct frame *f)
XISetMask (m, XI_PropertyEvent);
XISetMask (m, XI_HierarchyChanged);
XISetMask (m, XI_DeviceChanged);
-#ifdef XI_TouchBegin
+#ifdef HAVE_XINPUT2_2
if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
{
XISetMask (m, XI_TouchBegin);
XISetMask (m, XI_TouchUpdate);
XISetMask (m, XI_TouchEnd);
-#ifdef XI_GesturePinchBegin
+#ifdef HAVE_XINPUT2_4
if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
{
XISetMask (m, XI_GesturePinchBegin);
@@ -3303,6 +3791,12 @@ setup_xi_event_mask (struct frame *f)
XISelectEvents (FRAME_X_DISPLAY (f),
FRAME_X_WINDOW (f),
&mask, 1);
+
+#ifndef HAVE_XINPUT2_1
+ FRAME_X_OUTPUT (f)->xi_masks = selected;
+ FRAME_X_OUTPUT (f)->num_xi_masks = 1;
+#endif
+
unblock_input ();
}
#endif
@@ -3481,6 +3975,7 @@ x_window (struct frame *f, long window_prompting)
&f->output_data.x->wm_hints);
hack_wm_protocols (f, shell_widget);
+ append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
#ifdef X_TOOLKIT_EDITRES
XtAddEventHandler (shell_widget, 0, True, _XEditResCheckMessages, 0);
@@ -3532,7 +4027,7 @@ x_window (struct frame *f, long window_prompting)
{
Display *dpy = FRAME_X_DISPLAY (f);
PropMotifWmHints hints;
- Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
+ Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
memset (&hints, 0, sizeof(hints));
hints.flags = MWM_HINTS_DECORATIONS;
@@ -3601,6 +4096,8 @@ x_window (struct frame *f)
}
#endif
+ append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
+
#ifdef HAVE_XINPUT2
if (FRAME_DISPLAY_INFO (f)->supports_xi2)
setup_xi_event_mask (f);
@@ -3636,7 +4133,7 @@ x_window (struct frame *f)
f->top_pos,
FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
f->border_width,
- CopyFromParent, /* depth */
+ FRAME_DISPLAY_INFO (f)->n_planes, /* depth */
InputOutput, /* class */
FRAME_X_VISUAL (f),
attribute_mask, &attributes);
@@ -3689,6 +4186,8 @@ x_window (struct frame *f)
XSetWMProtocols (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), protocols, 2);
}
+ append_wm_protocols (FRAME_DISPLAY_INFO (f), f);
+
/* x_set_name normally ignores requests to set the name if the
requested name is the same as the current name. This is the one
place where that assumption isn't correct; f->name is set, but
@@ -3707,7 +4206,7 @@ x_window (struct frame *f)
{
Display *dpy = FRAME_X_DISPLAY (f);
PropMotifWmHints hints;
- Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
+ Atom prop = FRAME_DISPLAY_INFO (f)->Xatom_MOTIF_WM_HINTS;
memset (&hints, 0, sizeof(hints));
hints.flags = MWM_HINTS_DECORATIONS;
@@ -3747,12 +4246,12 @@ x_icon_verify (struct frame *f, Lisp_Object parms)
icons in an icon window. */
icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
+ if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound))
{
CHECK_FIXNUM (icon_x);
CHECK_FIXNUM (icon_y);
}
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
+ else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound))
error ("Both left and top icon corners of icon must be specified");
}
@@ -3771,8 +4270,8 @@ x_icon (struct frame *f, Lisp_Object parms)
= gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
int icon_xval, icon_yval;
- bool xgiven = !EQ (icon_x, Qunbound);
- bool ygiven = !EQ (icon_y, Qunbound);
+ bool xgiven = !BASE_EQ (icon_x, Qunbound);
+ bool ygiven = !BASE_EQ (icon_y, Qunbound);
if (xgiven != ygiven)
error ("Both left and top icon corners of icon must be specified");
if (xgiven)
@@ -3821,7 +4320,7 @@ x_make_gc (struct frame *f)
gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
gc_values.background = FRAME_BACKGROUND_PIXEL (f);
- gc_values.line_width = 0; /* Means 1 using fast algorithm. */
+ gc_values.line_width = 1;
f->output_data.x->normal_gc
= XCreateGC (FRAME_X_DISPLAY (f),
FRAME_X_DRAWABLE (f),
@@ -3840,11 +4339,9 @@ x_make_gc (struct frame *f)
/* Cursor has cursor-color background, background-color foreground. */
gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
gc_values.background = f->output_data.x->cursor_pixel;
- gc_values.fill_style = FillOpaqueStippled;
f->output_data.x->cursor_gc
= XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
- (GCForeground | GCBackground
- | GCFillStyle | GCLineWidth),
+ (GCForeground | GCBackground | GCLineWidth),
&gc_values);
/* Create the gray border tile used when the pointer is not in
@@ -3959,7 +4456,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
RES_TYPE_STRING);
Lisp_Object font = Qnil;
- if (EQ (font_param, Qunbound))
+ if (BASE_EQ (font_param, Qunbound))
font_param = Qnil;
if (NILP (font_param))
@@ -4047,9 +4544,7 @@ set_machine_and_pid_properties (struct frame *f)
unsigned long xpid = pid;
XChangeProperty (FRAME_X_DISPLAY (f),
FRAME_OUTER_WINDOW (f),
- XInternAtom (FRAME_X_DISPLAY (f),
- "_NET_WM_PID",
- False),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_pid,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) &xpid, 1);
}
@@ -4073,11 +4568,14 @@ This function is an internal primitive--use `make-frame' instead. */)
bool minibuffer_only = false;
bool undecorated = false, override_redirect = false;
long window_prompting = 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object display;
struct x_display_info *dpyinfo = NULL;
Lisp_Object parent, parent_frame;
struct kboard *kb;
+#ifdef HAVE_GTK3
+ GdkWindow *gwin;
+#endif
parms = Fcopy_alist (parms);
@@ -4087,10 +4585,10 @@ This function is an internal primitive--use `make-frame' instead. */)
display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
RES_TYPE_NUMBER);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0,
RES_TYPE_STRING);
- if (EQ (display, Qunbound))
+ if (BASE_EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_x_display_info (display);
kb = dpyinfo->terminal->kboard;
@@ -4101,7 +4599,7 @@ This function is an internal primitive--use `make-frame' instead. */)
name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
RES_TYPE_STRING);
if (!STRINGP (name)
- && ! EQ (name, Qunbound)
+ && ! BASE_EQ (name, Qunbound)
&& ! NILP (name))
error ("Invalid frame name--not a string or nil");
@@ -4111,7 +4609,7 @@ This function is an internal primitive--use `make-frame' instead. */)
/* See if parent window is specified. */
parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL,
RES_TYPE_NUMBER);
- if (EQ (parent, Qunbound))
+ if (BASE_EQ (parent, Qunbound))
parent = Qnil;
if (! NILP (parent))
CHECK_FIXNUM (parent);
@@ -4140,7 +4638,7 @@ This function is an internal primitive--use `make-frame' instead. */)
RES_TYPE_SYMBOL);
/* Accept parent-frame iff parent-id was not specified. */
if (!NILP (parent)
- || EQ (parent_frame, Qunbound)
+ || BASE_EQ (parent_frame, Qunbound)
|| NILP (parent_frame)
|| !FRAMEP (parent_frame)
|| !FRAME_LIVE_P (XFRAME (parent_frame))
@@ -4156,7 +4654,7 @@ This function is an internal primitive--use `make-frame' instead. */)
NULL,
NULL,
RES_TYPE_BOOLEAN)))
- && !(EQ (tem, Qunbound)))
+ && !(BASE_EQ (tem, Qunbound)))
undecorated = true;
FRAME_UNDECORATED (f) = undecorated;
@@ -4168,7 +4666,7 @@ This function is an internal primitive--use `make-frame' instead. */)
NULL,
NULL,
RES_TYPE_BOOLEAN)))
- && !(EQ (tem, Qunbound)))
+ && !(BASE_EQ (tem, Qunbound)))
override_redirect = true;
FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
@@ -4249,7 +4747,7 @@ This function is an internal primitive--use `make-frame' instead. */)
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
f->explicit_name = false;
@@ -4312,7 +4810,7 @@ This function is an internal primitive--use `make-frame' instead. */)
value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
@@ -4334,7 +4832,7 @@ This function is an internal primitive--use `make-frame' instead. */)
value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width,
"childFrameBorder", "childFrameBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qchild_frame_border_width, value),
parms);
}
@@ -4377,6 +4875,13 @@ This function is an internal primitive--use `make-frame' instead. */)
gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
NULL, NULL, RES_TYPE_BOOLEAN);
+#ifdef HAVE_GTK3
+ FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider
+ = gtk_css_provider_new ();
+ FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider
+ = gtk_css_provider_new ();
+#endif
+
x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
"scrollBarForeground",
"ScrollBarForeground", true);
@@ -4452,6 +4957,16 @@ This function is an internal primitive--use `make-frame' instead. */)
x_icon (f, parms);
x_make_gc (f);
+ /* While this function is present in versions of libXi that only
+ support 2.0, it does not release the display lock after
+ finishing, leading to a deadlock. */
+#if defined HAVE_XINPUT2 && defined HAVE_XINPUT2_1
+ if (dpyinfo->supports_xi2)
+ FRAME_X_OUTPUT (f)->xi_masks
+ = XIGetSelectedEvents (dpyinfo->display, FRAME_X_WINDOW (f),
+ &FRAME_X_OUTPUT (f)->num_xi_masks);
+#endif
+
/* Now consider the frame official. */
f->terminal->reference_count++;
FRAME_DISPLAY_INFO (f)->reference_count++;
@@ -4476,6 +4991,8 @@ This function is an internal primitive--use `make-frame' instead. */)
RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
if (!NILP (parent_frame))
{
@@ -4489,6 +5006,10 @@ This function is an internal primitive--use `make-frame' instead. */)
gtk_container_set_resize_mode
(GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE);
#endif
+#ifdef HAVE_GTK3
+ gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
+ gdk_x11_window_set_frame_sync_enabled (gwin, FALSE);
+#endif
unblock_input ();
}
@@ -4556,7 +5077,7 @@ This function is an internal primitive--use `make-frame' instead. */)
}
else
{
- if (EQ (visibility, Qunbound))
+ if (BASE_EQ (visibility, Qunbound))
visibility = Qt;
if (!NILP (visibility))
@@ -4570,7 +5091,7 @@ This function is an internal primitive--use `make-frame' instead. */)
from `x-create-frame-with-faces' (see above comment). */
f->was_invisible
= (f->was_invisible
- && (!EQ (height, Qunbound) || !EQ (width, Qunbound)));
+ && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound)));
store_frame_param (f, Qvisibility, visibility);
}
@@ -4591,6 +5112,46 @@ This function is an internal primitive--use `make-frame' instead. */)
(unsigned char *) &dpyinfo->client_leader_window, 1);
}
+#ifdef HAVE_XSYNC
+ if (dpyinfo->xsync_supported_p)
+ {
+#ifndef HAVE_GTK3
+ XSyncValue initial_value;
+ XSyncCounter counters[2];
+
+ AUTO_STRING (synchronizeResize, "synchronizeResize");
+ AUTO_STRING (SynchronizeResize, "SynchronizeResize");
+
+ Lisp_Object value = gui_display_get_resource (dpyinfo,
+ synchronizeResize,
+ SynchronizeResize,
+ Qnil, Qnil);
+
+ XSyncIntToValue (&initial_value, 0);
+ counters[0]
+ = FRAME_X_BASIC_COUNTER (f)
+ = XSyncCreateCounter (FRAME_X_DISPLAY (f),
+ initial_value);
+
+ if (STRINGP (value) && !strcmp (SSDATA (value), "extended"))
+ counters[1]
+ = FRAME_X_EXTENDED_COUNTER (f)
+ = XSyncCreateCounter (FRAME_X_DISPLAY (f),
+ initial_value);
+
+ FRAME_X_OUTPUT (f)->current_extended_counter_value
+ = initial_value;
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_sync_request_counter,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &counters,
+ ((STRINGP (value)
+ && !strcmp (SSDATA (value), "extended")) ? 2 : 1));
+#endif
+ }
+#endif
+
unblock_input ();
/* Works iff frame has been already mapped. */
@@ -4663,7 +5224,7 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
if (dpyinfo->n_planes <= 2)
return Qnil;
- switch (dpyinfo->visual->class)
+ switch (dpyinfo->visual_info.class)
{
case StaticColor:
case PseudoColor:
@@ -4690,7 +5251,7 @@ If omitted or nil, that stands for the selected frame's display. */)
if (dpyinfo->n_planes <= 1)
return Qnil;
- switch (dpyinfo->visual->class)
+ switch (dpyinfo->visual_info.class)
{
case StaticColor:
case PseudoColor:
@@ -4766,14 +5327,17 @@ If omitted or nil, that stands for the selected frame's display.
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
- int nr_planes = DisplayPlanes (dpyinfo->display,
- XScreenNumberOfScreen (dpyinfo->screen));
+ if (dpyinfo->visual_info.class != TrueColor
+ && dpyinfo->visual_info.class != DirectColor)
+ return make_fixnum (dpyinfo->visual_info.colormap_size);
+
+ int nr_planes = dpyinfo->n_planes;
- /* Truncate nr_planes to 24 to avoid integer overflow.
- Some displays says 32, but only 24 bits are actually significant.
+ /* Truncate nr_planes to 24 to avoid integer overflow. Some
+ displays says 32, but only 24 bits are actually significant.
There are only very few and rare video cards that have more than
- 24 significant bits. Also 24 bits is more than 16 million colors,
- it "should be enough for everyone". */
+ 24 significant bits. Also 24 bits is more than 16 million
+ colors, it "should be enough for everyone". */
if (nr_planes > 24) nr_planes = 24;
return make_fixnum (1 << nr_planes);
@@ -4848,9 +5412,9 @@ DEFUN ("x-server-input-extension-version", Fx_server_input_extension_version,
doc: /* Return the version of the X Input Extension supported by TERMINAL.
The value is nil if TERMINAL's X server doesn't support the X Input
Extension extension, or if Emacs doesn't support the version present
-on that server. Otherwise, the return value is a list of the the
-major and minor versions of the X Input Extension extension running on
-that server. */)
+on that server. Otherwise, the return value is a list of the major
+and minor versions of the X Input Extension extension running on that
+server. */)
(Lisp_Object terminal)
{
#ifdef HAVE_XINPUT2
@@ -4895,6 +5459,9 @@ for each physical monitor, use `display-monitor-attributes-list'. */)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
+ if (dpyinfo->screen_mm_height)
+ return make_fixnum (dpyinfo->screen_mm_height);
+
return make_fixnum (HeightMMOfScreen (dpyinfo->screen));
}
@@ -4912,6 +5479,9 @@ for each physical monitor, use `display-monitor-attributes-list'. */)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
+ if (dpyinfo->screen_mm_width)
+ return make_fixnum (dpyinfo->screen_mm_width);
+
return make_fixnum (WidthMMOfScreen (dpyinfo->screen));
}
@@ -4967,7 +5537,7 @@ If omitted or nil, that stands for the selected frame's display.
struct x_display_info *dpyinfo = check_x_display_info (terminal);
Lisp_Object result;
- switch (dpyinfo->visual->class)
+ switch (dpyinfo->visual_info.class)
{
case StaticGray:
result = intern ("static-gray");
@@ -5021,6 +5591,7 @@ On MS Windows, this just returns nil. */)
static bool
x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
{
+#ifndef USE_XCB
Display *dpy = dpyinfo->display;
long offset, max_len;
Atom target_type, actual_type;
@@ -5074,6 +5645,69 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
x_uncatch_errors ();
return result;
+#else
+ xcb_get_property_cookie_t current_desktop_cookie;
+ xcb_get_property_cookie_t workarea_cookie;
+ xcb_get_property_reply_t *reply;
+ xcb_generic_error_t *error;
+ bool rc;
+ uint32_t current_workspace, *values;
+
+ current_desktop_cookie
+ = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) dpyinfo->root_window,
+ (xcb_atom_t) dpyinfo->Xatom_net_current_desktop,
+ XCB_ATOM_CARDINAL, 0, 1);
+
+ workarea_cookie
+ = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) dpyinfo->root_window,
+ (xcb_atom_t) dpyinfo->Xatom_net_workarea,
+ XCB_ATOM_CARDINAL, 0, UINT32_MAX);
+
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ current_desktop_cookie, &error);
+ rc = true;
+
+ if (!reply)
+ free (error), rc = false;
+ else
+ {
+ if (xcb_get_property_value_length (reply) != 4
+ || reply->type != XCB_ATOM_CARDINAL || reply->format != 32)
+ rc = false;
+ else
+ current_workspace = *(uint32_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ workarea_cookie, &error);
+
+ if (!reply)
+ free (error), rc = false;
+ else
+ {
+ if (rc && reply->type == XCB_ATOM_CARDINAL && reply->format == 32
+ && (xcb_get_property_value_length (reply) / sizeof (uint32_t)
+ >= current_workspace + 4))
+ {
+ values = xcb_get_property_value (reply);
+
+ rect->x = values[current_workspace];
+ rect->y = values[current_workspace + 1];
+ rect->width = values[current_workspace + 2];
+ rect->height = values[current_workspace + 3];
+ }
+ else
+ rc = false;
+
+ free (reply);
+ }
+
+ return rc;
+#endif
}
#endif /* !(USE_GTK && HAVE_GTK3) */
@@ -5266,6 +5900,12 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5)
XRRMonitorInfo *rr_monitors;
+#ifdef USE_XCB
+ xcb_get_atom_name_cookie_t *atom_name_cookies;
+ xcb_get_atom_name_reply_t *reply;
+ xcb_generic_error_t *error;
+ int length;
+#endif
/* If RandR 1.5 or later is available, use that instead, as some
video drivers don't report correct dimensions via other versions
@@ -5284,6 +5924,9 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
goto fallback;
monitors = xzalloc (n_monitors * sizeof *monitors);
+#ifdef USE_XCB
+ atom_name_cookies = alloca (n_monitors * sizeof *atom_name_cookies);
+#endif
for (int i = 0; i < n_monitors; ++i)
{
@@ -5294,6 +5937,7 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
monitors[i].mm_width = rr_monitors[i].mwidth;
monitors[i].mm_height = rr_monitors[i].mheight;
+#ifndef USE_XCB
name = XGetAtomName (dpyinfo->display, rr_monitors[i].name);
if (name)
{
@@ -5302,6 +5946,11 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
}
else
monitors[i].name = xstrdup ("Unknown Monitor");
+#else
+ atom_name_cookies[i]
+ = xcb_get_atom_name (dpyinfo->xcb_connection,
+ (xcb_atom_t) rr_monitors[i].name);
+#endif
if (rr_monitors[i].primary)
primary = i;
@@ -5319,6 +5968,29 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
monitors[i].work = monitors[i].geom;
}
+#ifdef USE_XCB
+ for (int i = 0; i < n_monitors; ++i)
+ {
+ reply = xcb_get_atom_name_reply (dpyinfo->xcb_connection,
+ atom_name_cookies[i], &error);
+
+ if (!reply)
+ {
+ monitors[i].name = xstrdup ("Unknown monitor");
+ free (error);
+ }
+ else
+ {
+ length = xcb_get_atom_name_name_length (reply);
+ name = xmalloc (length + 1);
+ memcpy (name, xcb_get_atom_name_name (reply), length);
+ name[length] = '\0';
+ monitors[i].name = name;
+ free (reply);
+ }
+ }
+#endif
+
XRRFreeMonitors (rr_monitors);
randr15_p = true;
goto out;
@@ -5449,10 +6121,7 @@ x_get_monitor_attributes (struct x_display_info *dpyinfo)
#ifdef HAVE_XINERAMA
if (NILP (attributes_list))
{
- int xin_event_base, xin_error_base;
- bool xin_ok = false;
- xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
- if (xin_ok && XineramaIsActive (dpy))
+ if (dpyinfo->xinerama_supported_p && XineramaIsActive (dpy))
attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
}
#endif /* HAVE_XINERAMA */
@@ -5956,17 +6625,61 @@ menu bar or tool bar of FRAME. */)
* WINDOW to FRAMES and return FRAMES.
*/
static Lisp_Object
-x_frame_list_z_order (Display* dpy, Window window)
+x_frame_list_z_order (struct x_display_info *dpyinfo, Window window)
{
+ Display *dpy;
Window root, parent, *children;
unsigned int nchildren;
- int i;
- Lisp_Object frames = Qnil;
+ unsigned long i;
+ Lisp_Object frames, val;
+ Atom type;
+ Window *toplevels;
+ int format, rc;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ struct frame *f;
+
+ dpy = dpyinfo->display;
+ data = NULL;
+ frames = Qnil;
+
+ if (window == dpyinfo->root_window
+ && x_wm_supports_1 (dpyinfo,
+ dpyinfo->Xatom_net_client_list_stacking))
+ {
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_net_client_list_stacking,
+ 0, LONG_MAX, False, XA_WINDOW, &type,
+ &format, &nitems, &bytes_after, &data);
+
+ if (rc != Success)
+ return Qnil;
+
+ if (format != 32 || type != XA_WINDOW)
+ {
+ XFree (data);
+ return Qnil;
+ }
+
+ toplevels = (Window *) data;
+
+ for (i = 0; i < nitems; ++i)
+ {
+ f = x_top_window_to_frame (dpyinfo, toplevels[i]);
+
+ if (f)
+ {
+ XSETFRAME (val, f);
+ frames = Fcons (val, frames);
+ }
+ }
+
+ XFree (data);
+ return frames;
+ }
- block_input ();
if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
{
- unblock_input ();
for (i = 0; i < nchildren; i++)
{
Lisp_Object frame, tail;
@@ -5984,10 +6697,9 @@ x_frame_list_z_order (Display* dpy, Window window)
}
}
- if (children) XFree ((char *)children);
+ if (children)
+ XFree (children);
}
- else
- unblock_input ();
return frames;
}
@@ -6008,7 +6720,6 @@ Frames are listed from topmost (first) to bottommost (last). */)
(Lisp_Object terminal)
{
struct x_display_info *dpyinfo = check_x_display_info (terminal);
- Display *dpy = dpyinfo->display;
Window window;
if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
@@ -6016,7 +6727,7 @@ Frames are listed from topmost (first) to bottommost (last). */)
else
window = dpyinfo->root_window;
- return x_frame_list_z_order (dpy, window);
+ return x_frame_list_z_order (dpyinfo, window);
}
/**
@@ -6096,7 +6807,7 @@ selected frame's display. */)
block_input ();
XQueryPointer (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ FRAME_DISPLAY_INFO (f)->root_window,
&root, &dummy_window, &x, &y, &dummy, &dummy,
(unsigned int *) &dummy);
unblock_input ();
@@ -6110,7 +6821,7 @@ DEFUN ("x-set-mouse-absolute-pixel-position", Fx_set_mouse_absolute_pixel_positi
The coordinates X and Y are interpreted in pixels relative to a position
\(0, 0) of the selected frame's display. */)
(Lisp_Object x, Lisp_Object y)
- {
+{
struct frame *f = SELECTED_FRAME ();
if (FRAME_INITIAL_P (f) || !FRAME_X_P (f))
@@ -6130,20 +6841,195 @@ The coordinates X and Y are interpreted in pixels relative to a position
&deviceid))
{
XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ FRAME_DISPLAY_INFO (f)->root_window,
0, 0, 0, 0, xval, yval);
}
XUngrabServer (FRAME_X_DISPLAY (f));
}
else
#endif
- XWarpPointer (FRAME_X_DISPLAY (f), None, DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ XWarpPointer (FRAME_X_DISPLAY (f), None,
+ FRAME_DISPLAY_INFO (f)->root_window,
0, 0, 0, 0, xval, yval);
unblock_input ();
return Qnil;
}
+DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 6, 0,
+ doc: /* Begin dragging contents on FRAME, with targets TARGETS.
+TARGETS is a list of strings, which defines the X selection targets
+that will be available to the drop target. Block until the mouse
+buttons are released, then return the action chosen by the target, or
+`nil' if the drop was not accepted by the drop target. Dragging
+starts when the mouse is pressed on FRAME, and the contents of the
+selection `XdndSelection' will be sent to the X window underneath the
+mouse pointer (the drop target) when the mouse button is released.
+
+ACTION is a symbol which tells the target what it should do, and can
+be one of the following:
+
+ - `XdndActionCopy', which means to copy the contents from the drag
+ source (FRAME) to the drop target.
+
+ - `XdndActionMove', which means to first take the contents of
+ `XdndSelection', and to delete whatever was saved into that
+ selection afterwards.
+
+`XdndActionPrivate' is also a valid return value, and means that the
+drop target chose to perform an unspecified or unknown action.
+
+The source is also expected to cooperate with the target to perform
+the action chosen by the target. For example, callers should delete
+the buffer text that was dragged if `XdndActionMove' is returned.
+
+There are also some other valid values of ACTION that depend on
+details of both the drop target's implementation details and that of
+Emacs. For that reason, they are not mentioned here. Consult
+"Drag-and-Drop Protocol for the X Window System" for more details:
+https://freedesktop.org/wiki/Specifications/XDND/.
+
+If RETURN-FRAME is non-nil, this function will return the frame if the
+mouse pointer moves onto an Emacs frame, after first moving out of
+FRAME. (This is not guaranteed to work on some systems.) If
+RETURN-FRAME is the symbol `now', any frame underneath the mouse
+pointer will be returned immediately.
+
+If ACTION is a list and not nil, its elements are assumed to be a cons
+of (ITEM . STRING), where ITEM is the name of an action, and STRING is
+a string describing ITEM to the user. The drop target is expected to
+prompt the user to choose between any of the actions in the list.
+
+If ACTION is not specified or nil, `XdndActionCopy' is used
+instead.
+
+If ALLOW-CURRENT-FRAME is not specified or nil, then the drop target
+is allowed to be FRAME. Otherwise, no action will be taken if the
+mouse buttons are released on top of FRAME.
+
+If FOLLOW-TOOLTIP is non-nil, any tooltip currently being displayed
+will be moved to follow the mouse pointer while the drag is in
+progress. Note that this does not work with system tooltips (tooltips
+created when `use-system-tooltips' is non-nil).
+
+This function will sometimes return immediately if no mouse buttons
+are currently held down. It should only be called when it is known
+that mouse buttons are being held down, such as immediately after a
+`down-mouse-1' (or similar) event. */)
+ (Lisp_Object targets, Lisp_Object action, Lisp_Object frame,
+ Lisp_Object return_frame, Lisp_Object allow_current_frame,
+ Lisp_Object follow_tooltip)
+{
+ struct frame *f = decode_window_system_frame (frame);
+ int ntargets = 0, nnames = 0;
+ char *target_names[2048];
+ Atom *target_atoms;
+ Lisp_Object lval, original, targets_arg, tem, t1, t2;
+ Atom xaction;
+ Atom action_list[2048];
+ char *name_list[2048];
+
+ USE_SAFE_ALLOCA;
+
+ CHECK_LIST (targets);
+ original = targets;
+ targets_arg = targets;
+
+ FOR_EACH_TAIL (targets)
+ {
+ CHECK_STRING (XCAR (targets));
+
+ if (ntargets < 2048)
+ {
+ SAFE_ALLOCA_STRING (target_names[ntargets],
+ XCAR (targets));
+ ntargets++;
+ }
+ else
+ error ("Too many targets");
+ }
+
+ CHECK_LIST_END (targets, original);
+
+ if (NILP (action) || EQ (action, QXdndActionCopy))
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionCopy;
+ else if (EQ (action, QXdndActionMove))
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
+ else if (EQ (action, QXdndActionLink))
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
+ else if (EQ (action, QXdndActionPrivate))
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
+ else if (EQ (action, QXdndActionAsk))
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
+ else if (SYMBOLP (action))
+ /* This is to accommodate non-standard DND protocols such as XDS
+ that are explictly implemented by Emacs, and is not documented
+ for that reason. */
+ xaction = symbol_to_x_atom (FRAME_DISPLAY_INFO (f), action);
+ else if (CONSP (action))
+ {
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
+ original = action;
+
+ CHECK_LIST (action);
+ FOR_EACH_TAIL (action)
+ {
+ tem = XCAR (action);
+ CHECK_CONS (tem);
+ t1 = XCAR (tem);
+ t2 = XCDR (tem);
+ CHECK_SYMBOL (t1);
+ CHECK_STRING (t2);
+
+ if (nnames < 2048)
+ {
+ if (EQ (t1, QXdndActionCopy))
+ action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionCopy;
+ else if (EQ (t1, QXdndActionMove))
+ action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
+ else if (EQ (t1, QXdndActionLink))
+ action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
+ else if (EQ (t1, QXdndActionAsk))
+ action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
+ else if (EQ (t1, QXdndActionPrivate))
+ action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
+ else
+ signal_error ("Invalid drag-and-drop action", tem);
+
+ SAFE_ALLOCA_STRING (name_list[nnames],
+ ENCODE_SYSTEM (t2));
+
+ nnames++;
+ }
+ else
+ error ("Too many actions");
+ }
+ CHECK_LIST_END (action, original);
+ }
+ else
+ signal_error ("Invalid drag-and-drop action", action);
+
+ target_atoms = SAFE_ALLOCA (ntargets * sizeof *target_atoms);
+
+ /* Catch errors since interning lots of targets can potentially
+ generate a BadAlloc error. */
+ x_catch_errors (FRAME_X_DISPLAY (f));
+ XInternAtoms (FRAME_X_DISPLAY (f), target_names,
+ ntargets, False, target_atoms);
+ x_check_errors (FRAME_X_DISPLAY (f),
+ "Failed to intern target atoms: %s");
+ x_uncatch_errors_after_check ();
+
+ lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time,
+ xaction, return_frame, action_list,
+ (const char **) &name_list, nnames,
+ !NILP (allow_current_frame), target_atoms,
+ ntargets, targets_arg, !NILP (follow_tooltip));
+
+ SAFE_FREE ();
+ return lval;
+}
+
/************************************************************************
X Displays
************************************************************************/
@@ -6174,8 +7060,7 @@ visual_classes[] =
the X function with the same name when that doesn't exist. */
int
-XScreenNumberOfScreen (scr)
- register Screen *scr;
+XScreenNumberOfScreen (Screen *scr)
{
Display *dpy = scr->display;
int i;
@@ -6243,21 +7128,62 @@ select_visual (struct x_display_info *dpyinfo)
SSDATA (ENCODE_SYSTEM (value)));
dpyinfo->visual = vinfo.visual;
+ dpyinfo->visual_info = vinfo;
}
else
{
int n_visuals;
XVisualInfo *vinfo, vinfo_template;
- dpyinfo->visual = DefaultVisualOfScreen (screen);
+ vinfo_template.screen = XScreenNumberOfScreen (screen);
+
+#if !defined USE_X_TOOLKIT && !(defined USE_GTK && !defined HAVE_GTK3) \
+ && defined HAVE_XRENDER
+ int i;
+ XRenderPictFormat *format;
+
+ /* First attempt to find a visual with an alpha mask if
+ available. That information is only available when the
+ render extension is present, and we cannot do much with such
+ a visual if it isn't. */
+
+ if (dpyinfo->xrender_supported_p)
+ {
+
+ vinfo = XGetVisualInfo (dpy, VisualScreenMask,
+ &vinfo_template, &n_visuals);
+
+ for (i = 0; i < n_visuals; ++i)
+ {
+ format = XRenderFindVisualFormat (dpy, vinfo[i].visual);
+
+ if (format && format->type == PictTypeDirect
+ && format->direct.alphaMask)
+ {
+ dpyinfo->n_planes = vinfo[i].depth;
+ dpyinfo->visual = vinfo[i].visual;
+ dpyinfo->visual_info = vinfo[i];
+ dpyinfo->pict_format = format;
+
+ XFree (vinfo);
+ return;
+ }
+ }
+
+ if (vinfo)
+ XFree (vinfo);
+ }
+#endif /* !USE_X_TOOLKIT */
+ /* Visual with alpha channel (or the Render extension) not
+ available, fallback to default visual. */
+ dpyinfo->visual = DefaultVisualOfScreen (screen);
vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
- vinfo_template.screen = XScreenNumberOfScreen (screen);
vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
&vinfo_template, &n_visuals);
if (n_visuals <= 0)
fatal ("Can't get proper X visual info");
-
+ dpyinfo->visual_info = *vinfo;
dpyinfo->n_planes = vinfo->depth;
XFree (vinfo);
}
@@ -6395,7 +7321,11 @@ void
x_sync (struct frame *f)
{
block_input ();
+#ifndef USE_XCB
XSync (FRAME_X_DISPLAY (f), False);
+#else
+ xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
+#endif
unblock_input ();
}
@@ -6413,30 +7343,56 @@ converted to an atom and the value of the atom is used. If an element
is a cons, it is converted to a 32 bit number where the car is the 16
top bits and the cdr is the lower 16 bits.
-FRAME nil or omitted means use the selected frame.
-If TYPE is given and non-nil, it is the name of the type of VALUE.
- If TYPE is not given or nil, the type is STRING.
-FORMAT gives the size in bits of each element if VALUE is a list.
- It must be one of 8, 16 or 32.
- If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
-If OUTER-P is non-nil, the property is changed for the outer X window of
- FRAME. Default is to change on the edit X window.
-If WINDOW-ID is non-nil, change the property of that window instead
- of FRAME's X window; the number 0 denotes the root window. This argument
- is separate from FRAME because window IDs are not unique across X
- displays or screens on the same display, so FRAME provides context
- for the window ID. */)
+FRAME nil or omitted means use the selected frame. If TYPE is given
+and non-nil, it is the name of the type of VALUE. If TYPE is not
+given or nil, the type is STRING.
+
+FORMAT gives the size in bits of each element if VALUE is a list. It
+must be one of 8, 16 or 32.
+
+If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to
+8. If OUTER-P is non-nil, the property is changed for the outer X
+window of FRAME. Default is to change on the edit X window.
+
+If WINDOW-ID is non-nil, change the property of that window instead of
+FRAME's X window; the number 0 denotes the root window. This argument
+is separate from FRAME because window IDs are not unique across X
+displays or screens on the same display, so FRAME provides context for
+the window ID.
+
+If VALUE is a string and FORMAT is 32, then the format of VALUE is
+system-specific. VALUE must contain unsigned integer data in native
+endian-ness in multiples of the size of the C type 'long': the low 32
+bits of each such number are used as the value of each element of the
+property.
+
+Wait for the request to complete and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored. */)
(Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
Lisp_Object type, Lisp_Object format, Lisp_Object outer_p,
Lisp_Object window_id)
{
- struct frame *f = decode_window_system_frame (frame);
+ struct frame *f;
Atom prop_atom;
Atom target_type = XA_STRING;
int element_format = 8;
unsigned char *data;
int nelements;
Window target_window;
+ struct x_display_info *dpyinfo;
+#ifdef USE_XCB
+ bool intern_prop;
+ bool intern_target;
+ xcb_intern_atom_cookie_t prop_atom_cookie;
+ xcb_intern_atom_cookie_t target_type_cookie;
+ xcb_intern_atom_reply_t *reply;
+ xcb_generic_error_t *generic_error;
+ bool rc;
+#endif
+
+ f = decode_window_system_frame (frame);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
CHECK_STRING (prop);
@@ -6489,7 +7445,7 @@ If WINDOW-ID is non-nil, change the property of that window instead
{
CONS_TO_INTEGER (window_id, Window, target_window);
if (! target_window)
- target_window = FRAME_DISPLAY_INFO (f)->root_window;
+ target_window = dpyinfo->root_window;
}
else
{
@@ -6500,23 +7456,97 @@ If WINDOW-ID is non-nil, change the property of that window instead
}
block_input ();
- prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
+#ifndef USE_XCB
+ prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
+ false);
if (! NILP (type))
{
CHECK_STRING (type);
- target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
+ target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
+ false);
}
+#else
+ rc = true;
+ intern_target = true;
+ intern_prop = true;
- XChangeProperty (FRAME_X_DISPLAY (f), target_window,
- prop_atom, target_type, element_format, PropModeReplace,
- data, nelements);
+ prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
+ true);
- if (CONSP (value)) xfree (data);
+ if (prop_atom != None)
+ intern_prop = false;
+ else
+ prop_atom_cookie
+ = xcb_intern_atom (dpyinfo->xcb_connection,
+ 0, SBYTES (prop), SSDATA (prop));
- /* Make sure the property is set when we return. */
- XFlush (FRAME_X_DISPLAY (f));
- unblock_input ();
+ if (!NILP (type))
+ {
+ CHECK_STRING (type);
+
+ target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
+ true);
+
+ if (target_type)
+ intern_target = false;
+ else
+ target_type_cookie
+ = xcb_intern_atom (dpyinfo->xcb_connection,
+ 0, SBYTES (type), SSDATA (type));
+ }
+
+ if (intern_prop)
+ {
+ reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
+ prop_atom_cookie, &generic_error);
+
+ if (reply)
+ {
+ prop_atom = (Atom) reply->atom;
+ free (reply);
+ }
+ else
+ {
+ free (generic_error);
+ rc = false;
+ }
+ }
+
+ if (!NILP (type) && intern_target)
+ {
+ reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
+ target_type_cookie, &generic_error);
+
+ if (reply)
+ {
+ target_type = (Atom) reply->atom;
+ free (reply);
+ }
+ else
+ {
+ free (generic_error);
+ rc = false;
+ }
+ }
+
+ if (!rc)
+ error ("Failed to intern type or property atom");
+#endif
+
+ x_catch_errors_for_lisp (dpyinfo);
+ XChangeProperty (dpyinfo->display, target_window,
+ prop_atom, target_type, element_format,
+ PropModeReplace, data, nelements);
+
+ if (CONSP (value))
+ xfree (data);
+
+ x_check_errors_for_lisp (dpyinfo,
+ "Couldn't change window property: %s");
+ x_uncatch_errors_for_lisp (dpyinfo);
+
+ unblock_input ();
return value;
}
@@ -6531,7 +7561,11 @@ If WINDOW-ID is non-nil, remove property from that window instead
across X displays or screens on the same display, so FRAME provides
context for the window ID.
-Value is PROP. */)
+Value is PROP.
+
+Wait for the request to complete and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored. */)
(Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
{
struct frame *f = decode_window_system_frame (frame);
@@ -6548,13 +7582,16 @@ Value is PROP. */)
}
block_input ();
- prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
+ prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
+ SSDATA (prop), false);
+
+ x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom);
+ x_check_errors_for_lisp (FRAME_DISPLAY_INFO (f),
+ "Couldn't delete window property: %s");
+ x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
- /* Make sure the property is removed when we return. */
- XFlush (FRAME_X_DISPLAY (f));
unblock_input ();
-
return prop;
}
@@ -6674,15 +7711,19 @@ if PROP has no value of TYPE (always a string in the MS Windows case). */)
}
block_input ();
+ x_catch_errors (FRAME_X_DISPLAY (f));
+
if (STRINGP (type))
{
if (strcmp ("AnyPropertyType", SSDATA (type)) == 0)
target_type = AnyPropertyType;
else
- target_type = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (type), False);
+ target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
+ SSDATA (type), false);
}
- prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
+ prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
+ SSDATA (prop), false);
prop_value = x_window_property_intern (f,
target_window,
prop_atom,
@@ -6704,6 +7745,9 @@ if PROP has no value of TYPE (always a string in the MS Windows case). */)
&found);
}
+ x_check_errors (FRAME_X_DISPLAY (f),
+ "Can't retrieve window property: %s");
+ x_uncatch_errors_after_check ();
unblock_input ();
return prop_value;
@@ -6749,7 +7793,9 @@ Otherwise, the return value is a vector with the following fields:
block_input ();
- prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
+ x_catch_errors (FRAME_X_DISPLAY (f));
+ prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
+ SSDATA (prop), false);
rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
prop_atom, 0, 0, False, AnyPropertyType,
&actual_type, &actual_format, &actual_size,
@@ -6779,6 +7825,10 @@ Otherwise, the return value is a vector with the following fields:
make_fixnum (bytes_remaining / (actual_format >> 3)));
}
+ x_check_errors (FRAME_X_DISPLAY (f),
+ "Can't retrieve window property: %s");
+ x_uncatch_errors_after_check ();
+
unblock_input ();
return prop_attr;
}
@@ -6791,12 +7841,15 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
Lisp_Object, int, int, int *, int *);
/* The frame of the currently visible tooltip, or nil if none. */
-static Lisp_Object tip_frame;
+Lisp_Object tip_frame;
/* The window-system window corresponding to the frame of the
currently visible tooltip. */
Window tip_window;
+/* The X and Y deltas of the last call to `x-show-tip'. */
+Lisp_Object tip_dx, tip_dy;
+
/* A timer that hides or deletes the currently visible tooltip when it
fires. */
static Lisp_Object tip_timer;
@@ -6840,7 +7893,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
struct frame *f;
Lisp_Object frame;
Lisp_Object name;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
bool face_change_before = face_change;
if (!dpyinfo->terminal->name)
@@ -6852,7 +7905,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
RES_TYPE_STRING);
if (!STRINGP (name)
- && !EQ (name, Qunbound)
+ && !BASE_EQ (name, Qunbound)
&& !NILP (name))
error ("Invalid frame name--not a string or nil");
@@ -6919,7 +7972,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
/* Set the name; the functions to which we pass f expect the name to
be set. */
- if (EQ (name, Qunbound) || NILP (name))
+ if (BASE_EQ (name, Qunbound) || NILP (name))
{
fset_name (f, build_string (dpyinfo->x_id_name));
f->explicit_name = false;
@@ -6975,7 +8028,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
"internalBorder", "internalBorder",
RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
+ if (! BASE_EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
@@ -7002,26 +8055,15 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
NULL, NULL, RES_TYPE_BOOLEAN);
- /* Init faces before gui_default_parameter is called for the
- scroll-bar-width parameter because otherwise we end up in
- init_iterator with a null face cache, which should not happen. */
- init_frame_faces (f);
-
- f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
-
- gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
- "inhibitDoubleBuffering", "InhibitDoubleBuffering",
- RES_TYPE_BOOLEAN);
-
- gui_figure_window_size (f, parms, false, false);
-
{
+#ifndef USE_XCB
XSetWindowAttributes attrs;
unsigned long mask;
Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
block_input ();
- mask = CWBackPixel | CWOverrideRedirect | CWEventMask | CWCursor;
+ mask = (CWBackPixel | CWOverrideRedirect | CWEventMask
+ | CWCursor | CWColormap | CWBorderPixel);
if (DoesSaveUnders (dpyinfo->screen))
mask |= CWSaveUnder;
@@ -7031,9 +8073,11 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
attrs.override_redirect = True;
attrs.save_under = True;
attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+ attrs.colormap = FRAME_X_COLORMAP (f);
attrs.cursor =
f->output_data.x->current_cursor
= f->output_data.x->text_cursor;
+ attrs.border_pixel = f->output_data.x->border_pixel;
/* Arrange for getting MapNotify and UnmapNotify events. */
attrs.event_mask = StructureNotifyMask;
tip_window
@@ -7044,7 +8088,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
0, 0, 1, 1,
/* Border. */
f->border_width,
- CopyFromParent, InputOutput, CopyFromParent,
+ dpyinfo->n_planes, InputOutput,
+ FRAME_X_VISUAL (f),
mask, &attrs);
initial_set_up_x_back_buffer (f);
XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
@@ -7052,8 +8097,68 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
XA_ATOM, 32, PropModeReplace,
(unsigned char *)&type, 1);
unblock_input ();
+#else
+ uint32_t value_list[6];
+ xcb_atom_t net_wm_window_type_tooltip
+ = (xcb_atom_t) dpyinfo->Xatom_net_window_type_tooltip;
+ xcb_visualid_t visual_id
+ = (xcb_visualid_t) XVisualIDFromVisual (FRAME_X_VISUAL (f));
+
+ f->output_data.x->current_cursor = f->output_data.x->text_cursor;
+ /* Values are set in the order of their enumeration in `enum
+ xcb_cw_t'. */
+ value_list[0] = FRAME_BACKGROUND_PIXEL (f);
+ value_list[1] = f->output_data.x->border_pixel;
+ value_list[2] = true;
+ value_list[3] = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+ value_list[4] = (xcb_colormap_t) FRAME_X_COLORMAP (f);
+ value_list[5] = (xcb_cursor_t) f->output_data.x->text_cursor;
+
+ block_input ();
+ tip_window
+ = FRAME_X_WINDOW (f)
+ = (Window) xcb_generate_id (dpyinfo->xcb_connection);
+
+ xcb_create_window (dpyinfo->xcb_connection,
+ dpyinfo->n_planes,
+ (xcb_window_t) tip_window,
+ (xcb_window_t) dpyinfo->root_window,
+ 0, 0, 1, 1, f->border_width,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ visual_id,
+ (XCB_CW_BACK_PIXEL
+ | XCB_CW_BORDER_PIXEL
+ | XCB_CW_OVERRIDE_REDIRECT
+ | XCB_CW_EVENT_MASK
+ | XCB_CW_COLORMAP
+ | XCB_CW_CURSOR),
+ &value_list);
+
+ xcb_change_property (dpyinfo->xcb_connection,
+ XCB_PROP_MODE_REPLACE,
+ (xcb_window_t) tip_window,
+ (xcb_atom_t) dpyinfo->Xatom_net_window_type,
+ (xcb_atom_t) dpyinfo->Xatom_ATOM,
+ 32, 1, &net_wm_window_type_tooltip);
+
+ initial_set_up_x_back_buffer (f);
+ unblock_input ();
+#endif
}
+ /* Init faces before gui_default_parameter is called for the
+ scroll-bar-width parameter because otherwise we end up in
+ init_iterator with a null face cache, which should not happen. */
+ init_frame_faces (f);
+
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
+ gui_figure_window_size (f, parms, false, false);
+
+ f->output_data.x->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
+
x_make_gc (f);
gui_default_parameter (f, parms, Qauto_raise, Qnil,
@@ -7064,6 +8169,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
"cursorType", "CursorType", RES_TYPE_SYMBOL);
gui_default_parameter (f, parms, Qalpha, Qnil,
"alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
/* Add `tooltip' frame parameter's default value. */
if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7081,8 +8188,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
disptype = Qmono;
- else if (FRAME_DISPLAY_INFO (f)->visual->class == GrayScale
- || FRAME_DISPLAY_INFO (f)->visual->class == StaticGray)
+ else if (FRAME_X_VISUAL_INFO (f)->class == GrayScale
+ || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
disptype = intern ("grayscale");
else
disptype = intern ("color");
@@ -7148,9 +8255,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
the display in *ROOT_X, and *ROOT_Y. */
static void
-compute_tip_xy (struct frame *f,
- Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
- int width, int height, int *root_x, int *root_y)
+compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
+ Lisp_Object dy, int width, int height, int *root_x,
+ int *root_y)
{
Lisp_Object left, top, right, bottom;
int win_x, win_y;
@@ -7176,7 +8283,7 @@ compute_tip_xy (struct frame *f,
&root, &child, root_x, root_y, &win_x, &win_y, &pmask);
unblock_input ();
- XSETFRAME(frame, f);
+ XSETFRAME (frame, f);
attributes = Fx_display_monitor_attributes_list (frame);
/* Try to determine the monitor where the mouse pointer is and
@@ -7191,11 +8298,13 @@ compute_tip_xy (struct frame *f,
min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
+
if (min_x <= *root_x && *root_x < max_x
&& min_y <= *root_y && *root_y < max_y)
{
break;
}
+
max_y = -1;
}
@@ -7205,7 +8314,7 @@ compute_tip_xy (struct frame *f,
/* It was not possible to determine the monitor's geometry, so we
assign some sane defaults here: */
- if ( max_y < 0 )
+ if (max_y < 0)
{
min_x = 0;
min_y = 0;
@@ -7270,13 +8379,13 @@ x_hide_tip (bool delete)
}
#ifdef USE_GTK
- /* Any GTK+ system tooltip can be found via the x_output structure of
- tip_last_frame, provided that frame is still live. Any Emacs
- tooltip is found via the tip_frame variable. Note that the current
- value of x_gtk_use_system_tooltips might not be the same as used
- for the tooltip we have to hide, see Bug#30399. */
+ /* Any GTK+ system tooltip can be found via the x_output structure
+ of tip_last_frame, provided that frame is still live. Any Emacs
+ tooltip is found via the tip_frame variable. Note that the
+ current value of use_system_tooltips might not be the same as
+ used for the tooltip we have to hide, see Bug#30399. */
if ((NILP (tip_last_frame) && NILP (tip_frame))
- || (!x_gtk_use_system_tooltips
+ || (!use_system_tooltips
&& !delete
&& !NILP (tip_frame)
&& FRAME_LIVE_P (XFRAME (tip_frame))
@@ -7287,10 +8396,9 @@ x_hide_tip (bool delete)
return Qnil;
else
{
- ptrdiff_t count;
Lisp_Object was_open = Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
@@ -7309,7 +8417,7 @@ x_hide_tip (bool delete)
/* When using GTK+ system tooltips (compare Bug#41200) reset
tip_last_frame. It will be reassigned when showing the next
GTK+ system tooltip. */
- if (x_gtk_use_system_tooltips)
+ if (use_system_tooltips)
tip_last_frame = Qnil;
/* Now look whether there's an Emacs tip around. */
@@ -7319,7 +8427,7 @@ x_hide_tip (bool delete)
if (FRAME_LIVE_P (f))
{
- if (delete || x_gtk_use_system_tooltips)
+ if (delete || use_system_tooltips)
{
/* Delete the Emacs tooltip frame when DELETE is true
or we change the tooltip type from an Emacs one to
@@ -7349,10 +8457,9 @@ x_hide_tip (bool delete)
return Qnil;
else
{
- ptrdiff_t count;
Lisp_Object was_open = Qnil;
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_redisplay, Qt);
specbind (Qinhibit_quit, Qt);
@@ -7370,29 +8477,6 @@ x_hide_tip (bool delete)
else
x_make_frame_invisible (XFRAME (tip_frame));
-#ifdef USE_LUCID
- /* Bloodcurdling hack alert: The Lucid menu bar widget's
- redisplay procedure is not called when a tip frame over
- menu items is unmapped. Redisplay the menu manually... */
- {
- Widget w;
- struct frame *f = SELECTED_FRAME ();
-
- if (FRAME_X_P (f) && FRAME_LIVE_P (f))
- {
- w = f->output_data.x->menubar_widget;
-
- if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen)
- && w != NULL)
- {
- block_input ();
- xlwmenu_redisplay (w);
- unblock_input ();
- }
- }
- }
-#endif /* USE_LUCID */
-
was_open = Qt;
}
else
@@ -7419,7 +8503,8 @@ PARMS is an optional list of frame parameters which can be used to
change the tooltip's appearance.
Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
-means use the default timeout of 5 seconds.
+means use the default timeout from the `x-show-tooltip-timeout'
+variable.
If the list of frame parameters PARMS contains a `left' parameter,
display the tooltip at that x-position. If the list of frame parameters
@@ -7447,9 +8532,11 @@ Text larger than the specified size is clipped. */)
struct text_pos pos;
int width, height;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
- ptrdiff_t count = SPECPDL_INDEX ();
- ptrdiff_t count_1;
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object window, size, tip_buf;
+ Window child;
+ XWindowAttributes child_attrs;
+ int dest_x_return, dest_y_return;
AUTO_STRING (tip, " *tip*");
specbind (Qinhibit_redisplay, Qt);
@@ -7463,9 +8550,8 @@ Text larger than the specified size is clipped. */)
f = decode_window_system_frame (frame);
if (NILP (timeout))
- timeout = make_fixnum (5);
- else
- CHECK_FIXNAT (timeout);
+ timeout = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
if (NILP (dx))
dx = make_fixnum (5);
@@ -7477,8 +8563,11 @@ Text larger than the specified size is clipped. */)
else
CHECK_FIXNUM (dy);
+ tip_dx = dx;
+ tip_dy = dy;
+
#ifdef USE_GTK
- if (x_gtk_use_system_tooltips)
+ if (use_system_tooltips)
{
bool ok;
@@ -7502,7 +8591,7 @@ Text larger than the specified size is clipped. */)
if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
{
if (FRAME_VISIBLE_P (XFRAME (tip_frame))
- && EQ (frame, tip_last_frame)
+ && BASE_EQ (frame, tip_last_frame)
&& !NILP (Fequal_including_properties (tip_last_string, string))
&& !NILP (Fequal (tip_last_parms, parms)))
{
@@ -7523,7 +8612,7 @@ Text larger than the specified size is clipped. */)
goto start_timer;
}
- else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
+ else if (tooltip_reuse_hidden_frame && BASE_EQ (frame, tip_last_frame))
{
bool delete = false;
Lisp_Object tail, elt, parm, last;
@@ -7648,7 +8737,7 @@ Text larger than the specified size is clipped. */)
/* Insert STRING into root window's buffer and fit the frame to the
buffer. */
- count_1 = SPECPDL_INDEX ();
+ specpdl_ref count_1 = SPECPDL_INDEX ();
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (w->contents));
bset_truncate_lines (current_buffer, Qnil);
@@ -7674,9 +8763,58 @@ Text larger than the specified size is clipped. */)
/* Show tooltip frame. */
block_input ();
+ /* If the display is composited, then WM_TRANSIENT_FOR must be set
+ as well, or else the compositing manager won't display
+ decorations correctly, even though the tooltip window is override
+ redirect. See
+ https://specifications.freedesktop.org/wm-spec/1.4/ar01s08.html
+
+ Perhaps WM_TRANSIENT_FOR should be used in place of
+ override-redirect anyway. The ICCCM only recommends
+ override-redirect if the pointer will be grabbed. */
+
+ if (XTranslateCoordinates (FRAME_X_DISPLAY (f),
+ FRAME_DISPLAY_INFO (f)->root_window,
+ FRAME_DISPLAY_INFO (f)->root_window,
+ root_x, root_y, &dest_x_return,
+ &dest_y_return, &child)
+ && child != None)
+ {
+ /* But only if the child is not override-redirect, which can
+ happen if the pointer is above a menu. */
+
+ if (XGetWindowAttributes (FRAME_X_DISPLAY (f),
+ child, &child_attrs)
+ || child_attrs.override_redirect)
+ XDeleteProperty (FRAME_X_DISPLAY (tip_f),
+ FRAME_X_WINDOW (tip_f),
+ FRAME_DISPLAY_INFO (tip_f)->Xatom_wm_transient_for);
+ else
+ XSetTransientForHint (FRAME_X_DISPLAY (tip_f),
+ FRAME_X_WINDOW (tip_f), child);
+ }
+ else
+ XDeleteProperty (FRAME_X_DISPLAY (tip_f),
+ FRAME_X_WINDOW (tip_f),
+ FRAME_DISPLAY_INFO (tip_f)->Xatom_wm_transient_for);
+
+#ifndef USE_XCB
XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f),
root_x, root_y, width, height);
XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f));
+#else
+ uint32_t values[] = { root_x, root_y, width, height, XCB_STACK_MODE_ABOVE };
+
+ xcb_configure_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection,
+ (xcb_window_t) FRAME_X_WINDOW (tip_f),
+ (XCB_CONFIG_WINDOW_X
+ | XCB_CONFIG_WINDOW_Y
+ | XCB_CONFIG_WINDOW_WIDTH
+ | XCB_CONFIG_WINDOW_HEIGHT
+ | XCB_CONFIG_WINDOW_STACK_MODE), &values);
+ xcb_map_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection,
+ (xcb_window_t) FRAME_X_WINDOW (tip_f));
+#endif
unblock_input ();
#ifdef USE_CAIRO
@@ -7713,7 +8851,12 @@ DEFUN ("x-double-buffered-p", Fx_double_buffered_p, Sx_double_buffered_p,
(Lisp_Object frame)
{
struct frame *f = decode_live_frame (frame);
+
+#ifdef HAVE_XDBE
return FRAME_X_DOUBLE_BUFFERED_P (f) ? Qt : Qnil;
+#else
+ return Qnil;
+#endif
}
@@ -7789,7 +8932,7 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
Arg al[10];
int ac = 0;
XmString dir_xmstring, pattern_xmstring;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
check_window_system (f);
@@ -7802,6 +8945,9 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
+ /* Defer selection requests. */
+ DEFER_SELECTIONS;
+
block_input ();
/* Create the dialog with PROMPT as title, using DIR as initial
@@ -7885,20 +9031,70 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
result = 0;
while (result == 0)
{
- XEvent event;
+ XEvent event, copy;
x_menu_wait_for_event (0);
- XtAppNextEvent (Xt_app_con, &event);
- if (event.type == KeyPress
- && FRAME_X_DISPLAY (f) == event.xkey.display)
- {
- KeySym keysym = XLookupKeysym (&event.xkey, 0);
- /* Pop down on C-g. */
- if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
- XtUnmanageChild (dialog);
- }
+ if (XtAppPending (Xt_app_con))
+ {
+ XtAppNextEvent (Xt_app_con, &event);
+
+ copy = event;
+ if (event.type == KeyPress
+ && FRAME_X_DISPLAY (f) == event.xkey.display)
+ {
+ KeySym keysym = XLookupKeysym (&event.xkey, 0);
+
+ /* Pop down on C-g. */
+ if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
+ XtUnmanageChild (dialog);
+ }
+#ifdef HAVE_XINPUT2
+ else if (event.type == GenericEvent
+ && FRAME_X_DISPLAY (f) == event.xgeneric.display
+ && FRAME_DISPLAY_INFO (f)->supports_xi2
+ && (event.xgeneric.extension
+ == FRAME_DISPLAY_INFO (f)->xi2_opcode)
+ && event.xgeneric.evtype == XI_KeyPress)
+ {
+ KeySym keysym;
+ XIDeviceEvent *xev;
+
+ if (event.xcookie.data)
+ emacs_abort ();
- (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
+ if (XGetEventData (FRAME_X_DISPLAY (f), &event.xcookie))
+ {
+ xev = (XIDeviceEvent *) event.xcookie.data;
+
+ copy.xkey.type = KeyPress;
+ copy.xkey.serial = xev->serial;
+ copy.xkey.send_event = xev->send_event;
+ copy.xkey.display = FRAME_X_DISPLAY (f);
+ copy.xkey.window = xev->event;
+ copy.xkey.root = xev->root;
+ copy.xkey.subwindow = xev->child;
+ copy.xkey.time = xev->time;
+ copy.xkey.x = lrint (xev->event_x);
+ copy.xkey.y = lrint (xev->event_y);
+ copy.xkey.x_root = lrint (xev->root_x);
+ copy.xkey.y_root = lrint (xev->root_y);
+ copy.xkey.state = xev->mods.effective;
+ copy.xkey.keycode = xev->detail;
+ copy.xkey.same_screen = True;
+
+ keysym = XLookupKeysym (&copy.xkey, 0);
+
+ if (keysym == XK_g
+ && (copy.xkey.state & ControlMask) != 0) /* Any escape, ignore modifiers. */
+ XtUnmanageChild (dialog);
+
+ XFreeEventData (FRAME_X_DISPLAY (f), &event.xcookie);
+ }
+ }
+#endif
+
+ (void) x_dispatch_event (&copy, FRAME_X_DISPLAY (f));
+ }
}
/* Get the result. */
@@ -7956,7 +9152,7 @@ value of DIR as in previous invocations; this is standard MS Windows behavior.
char *fn;
Lisp_Object file = Qnil;
Lisp_Object decoded_file;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
char *cdef_file;
check_window_system (f);
@@ -8017,7 +9213,7 @@ nil, it defaults to the selected frame. */)
Lisp_Object font;
Lisp_Object font_param;
char *default_name = NULL;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (popup_activated ())
error ("Trying to use a menu from within a menu-entry");
@@ -8269,7 +9465,6 @@ Note: Text drawn with the `x' font backend is shown with hollow boxes. */)
(Lisp_Object frames)
{
Lisp_Object rest, tmp;
- int count;
if (!CONSP (frames))
frames = list1 (frames);
@@ -8288,7 +9483,7 @@ Note: Text drawn with the `x' font backend is shown with hollow boxes. */)
frames = Fnreverse (tmp);
/* Make sure the current matrices are up-to-date. */
- count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (32);
unbind_to (count, Qnil);
@@ -8320,6 +9515,69 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
#endif /* GTK_CHECK_VERSION (3, 14, 0) */
#endif /* HAVE_GTK3 */
#endif /* USE_GTK */
+
+DEFUN ("x-display-set-last-user-time", Fx_display_last_user_time,
+ Sx_display_set_last_user_time, 1, 2, 0,
+ doc: /* Set the last user time of TERMINAL to TIME-OBJECT.
+TIME-OBJECT is the X server time, in milliseconds, of the last user
+interaction. This is the timestamp that `x-get-selection-internal'
+will use by default to fetch selection data.
+The optional second argument TERMINAL specifies which display to act
+on. TERMINAL should be a terminal object, a frame or a display name
+(a string). If TERMINAL is omitted or nil, that stands for the
+selected frame's display. */)
+ (Lisp_Object time_object, Lisp_Object terminal)
+{
+ struct x_display_info *dpyinfo;
+ Time time;
+
+ dpyinfo = check_x_display_info (terminal);
+ CONS_TO_INTEGER (time_object, Time, time);
+
+ x_set_last_user_time_from_lisp (dpyinfo, time);
+ return Qnil;
+}
+
+DEFUN ("x-internal-focus-input-context", Fx_internal_focus_input_context,
+ Sx_internal_focus_input_context, 1, 1, 0,
+ doc: /* Focus and set the client window of all focused frames' GTK input context.
+If FOCUS is nil, focus out and remove the client window instead.
+This should be called from a variable watcher for `x-gtk-use-native-input'. */)
+ (Lisp_Object focus)
+{
+#ifdef USE_GTK
+ struct x_display_info *dpyinfo;
+ struct frame *f;
+ GtkWidget *widget;
+
+ block_input ();
+ for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+ {
+ f = dpyinfo->x_focus_frame;
+
+ if (f)
+ {
+ widget = FRAME_GTK_OUTER_WIDGET (f);
+
+ if (!NILP (focus))
+ {
+ gtk_im_context_focus_in (FRAME_X_OUTPUT (f)->im_context);
+ gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context,
+ gtk_widget_get_window (widget));
+ }
+ else
+ {
+ gtk_im_context_focus_out (FRAME_X_OUTPUT (f)->im_context);
+ gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context,
+ NULL);
+ }
+ }
+ }
+ unblock_input ();
+#endif
+
+ return Qnil;
+}
/***********************************************************************
Initialization
@@ -8366,10 +9624,14 @@ frame_parm_handler x_frame_parm_handlers[] =
x_set_wait_for_wm,
gui_set_fullscreen,
gui_set_font_backend,
- gui_set_alpha,
+ x_set_alpha,
x_set_sticky,
x_set_tool_bar_position,
+#ifdef HAVE_XDBE
x_set_inhibit_double_buffering,
+#else
+ NULL,
+#endif
x_set_undecorated,
x_set_parent_frame,
x_set_skip_taskbar,
@@ -8378,8 +9640,66 @@ frame_parm_handler x_frame_parm_handlers[] =
x_set_z_group,
x_set_override_redirect,
gui_set_no_special_glyphs,
+ x_set_alpha_background,
+ x_set_shaded,
};
+/* Some versions of libX11 don't have symbols for a few functions we
+ need, so define replacements here. */
+
+#ifdef HAVE_XKB
+#ifndef HAVE_XKBREFRESHKEYBOARDMAPPING
+Status
+XkbRefreshKeyboardMapping (XkbMapNotifyEvent *event)
+{
+ return Success;
+}
+#endif
+
+#ifndef HAVE_XKBFREENAMES
+void
+XkbFreeNames (XkbDescPtr xkb, unsigned int which, Bool free_map)
+{
+ return;
+}
+#endif
+#endif
+
+#ifndef HAVE_XDISPLAYCELLS
+int
+XDisplayCells (Display *dpy, int screen_number)
+{
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+
+ if (!dpyinfo)
+ emacs_abort ();
+
+ /* Not strictly correct, since the display could be using a
+ non-default visual, but it satisfies the callers we need to care
+ about. */
+ return dpyinfo->visual_info.colormap_size;
+}
+#endif
+
+#ifndef HAVE_XDESTROYSUBWINDOWS
+int
+XDestroySubwindows (Display *dpy, Window w)
+{
+ Window root, parent, *children;
+ unsigned int nchildren, i;
+
+ if (XQueryTree (dpy, w, &root, &parent, &children,
+ &nchildren))
+ {
+ for (i = 0; i < nchildren; ++i)
+ XDestroyWindow (dpy, children[i]);
+ XFree (children);
+ }
+
+ return 0;
+}
+#endif
+
void
syms_of_xfns (void)
{
@@ -8403,6 +9723,12 @@ syms_of_xfns (void)
DEFSYM (Qreverse_landscape, "reverse-landscape");
#endif
+ DEFSYM (QXdndActionCopy, "XdndActionCopy");
+ DEFSYM (QXdndActionMove, "XdndActionMove");
+ DEFSYM (QXdndActionLink, "XdndActionLink");
+ DEFSYM (QXdndActionAsk, "XdndActionAsk");
+ DEFSYM (QXdndActionPrivate, "XdndActionPrivate");
+
Fput (Qundefined_color, Qerror_conditions,
pure_list (Qundefined_color, Qerror));
Fput (Qundefined_color, Qerror_message,
@@ -8560,12 +9886,6 @@ If more space for files in the file chooser dialog is wanted, set this to nil
to turn the additional text off. */);
x_gtk_file_dialog_help_text = true;
- DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips,
- doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used.
-Otherwise use Emacs own tooltip implementation.
-When using Gtk+ tooltips, the tooltip face is not used. */);
- x_gtk_use_system_tooltips = true;
-
DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
doc: /* If non-nil, resize child frames specially with GTK builds.
If this is nil, resize child frames like any other frames. This is the
@@ -8574,11 +9894,11 @@ default and usually works with most desktops. Some desktop environments
however, may refuse to resize a child frame when Emacs is built with
GTK3. For those environments, the two settings below are provided.
-If this equals the symbol 'hide', Emacs temporarily hides the child
+If this equals the symbol `hide', Emacs temporarily hides the child
frame during resizing. This approach seems to work reliably, may
however induce some flicker when the frame is made visible again.
-If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
+If this equals the symbol `resize-mode', Emacs uses GTK's resize mode to
always trigger an immediate resize of the child frame. This method is
deprecated by GTK and may not work in future versions of that toolkit.
It also may freeze Emacs when used with other desktop environments. It
@@ -8682,6 +10002,8 @@ eliminated in future versions of Emacs. */);
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
defsubr (&Sx_double_buffered_p);
+ defsubr (&Sx_begin_drag);
+ defsubr (&Sx_display_set_last_user_time);
tip_timer = Qnil;
staticpro (&tip_timer);
tip_frame = Qnil;
@@ -8692,6 +10014,10 @@ eliminated in future versions of Emacs. */);
staticpro (&tip_last_string);
tip_last_parms = Qnil;
staticpro (&tip_last_parms);
+ tip_dx = Qnil;
+ staticpro (&tip_dx);
+ tip_dy = Qnil;
+ staticpro (&tip_dy);
defsubr (&Sx_uses_old_gtk_dialog);
#if defined (USE_MOTIF) || defined (USE_GTK)
@@ -8702,6 +10028,8 @@ eliminated in future versions of Emacs. */);
defsubr (&Sx_select_font);
#endif
+ defsubr (&Sx_internal_focus_input_context);
+
#ifdef USE_CAIRO
defsubr (&Sx_export_frames);
#ifdef USE_GTK
diff --git a/src/xfont.c b/src/xfont.c
index b5765cfa7b8..74237e8aa88 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -295,7 +295,7 @@ xfont_list_pattern (Display *display, const char *pattern,
{
Lisp_Object list = Qnil;
Lisp_Object chars = Qnil;
- struct charset *encoding, *repertory = NULL;
+ struct charset *encoding = NULL, *repertory = NULL;
int i, limit, num_fonts;
char **names;
/* Large enough to decode the longest XLFD (255 bytes). */
@@ -1003,6 +1003,32 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
unblock_input ();
}
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ if (with_background
+ && FRAME_DISPLAY_INFO (s->f)->alpha_bits
+ && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
+ {
+ x_xr_ensure_picture (s->f);
+
+ if (FRAME_X_PICTURE (s->f) != None)
+ {
+ XRenderColor xc;
+ int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
+
+ x_xr_apply_ext_clip (s->f, gc);
+ x_xrender_color_from_gc_background (s->f, gc, &xc,
+ s->hl != DRAW_CURSOR);
+ XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
+ PictOpSrc, FRAME_X_PICTURE (s->f),
+ &xc, x, y - ascent, s->width, height);
+ x_xr_reset_ext_clip (s->f);
+ x_mark_frame_dirty (s->f);
+
+ with_background = false;
+ }
+ }
+#endif
+
if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
{
USE_SAFE_ALLOCA;
diff --git a/src/xftfont.c b/src/xftfont.c
index f305738410e..6043ef9f94f 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "ftfont.h"
#include "pdumper.h"
+#ifdef HAVE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
+
#ifndef FC_LCD_FILTER
/* Older fontconfig versions don't have FC_LCD_FILTER. */
# define FC_LCD_FILTER "lcdfilter"
@@ -45,19 +49,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
struct xftface_info
{
+ bool bg_allocated_p;
+ bool fg_allocated_p;
XftColor xft_fg; /* color for face->foreground */
XftColor xft_bg; /* color for face->background */
};
/* Setup foreground and background colors of GC into FG and BG. If
XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG
- may be NULL. */
+ may be NULL. Return whether or not colors were allocated in
+ BG_ALLOCATED_P and FG_ALLOCATED_P. */
static void
xftfont_get_colors (struct frame *f, struct face *face, GC gc,
struct xftface_info *xftface_info,
- XftColor *fg, XftColor *bg)
+ XftColor *fg, XftColor *bg,
+ bool *bg_allocated_p, bool *fg_allocated_p)
{
+ *bg_allocated_p = false;
+ *fg_allocated_p = false;
+
if (xftface_info && face->gc == gc)
{
*fg = xftface_info->xft_fg;
@@ -90,20 +101,39 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc,
{
XColor colors[2];
- colors[0].pixel = fg->pixel = xgcv.foreground;
+ colors[0].pixel = xgcv.foreground;
if (bg)
- colors[1].pixel = bg->pixel = xgcv.background;
+ colors[1].pixel = xgcv.background;
x_query_colors (f, colors, bg ? 2 : 1);
fg->color.alpha = 0xFFFF;
fg->color.red = colors[0].red;
fg->color.green = colors[0].green;
fg->color.blue = colors[0].blue;
+
+ if (!XftColorAllocValue (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &fg->color, fg))
+ /* This color should've been allocated when creating the
+ GC. */
+ emacs_abort ();
+ else
+ *fg_allocated_p = true;
+
if (bg)
{
bg->color.alpha = 0xFFFF;
bg->color.red = colors[1].red;
bg->color.green = colors[1].green;
bg->color.blue = colors[1].blue;
+
+ if (!XftColorAllocValue (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &bg->color, bg))
+ emacs_abort ();
+ else
+ *bg_allocated_p = true;
}
}
unblock_input ();
@@ -356,9 +386,12 @@ xftfont_prepare_face (struct frame *f, struct face *face)
}
#endif
- xftface_info = xmalloc (sizeof *xftface_info);
+ xftface_info = xzalloc (sizeof *xftface_info);
xftfont_get_colors (f, face, face->gc, NULL,
- &xftface_info->xft_fg, &xftface_info->xft_bg);
+ &xftface_info->xft_fg,
+ &xftface_info->xft_bg,
+ &xftface_info->bg_allocated_p,
+ &xftface_info->fg_allocated_p);
face->extra = xftface_info;
}
@@ -377,6 +410,18 @@ xftfont_done_face (struct frame *f, struct face *face)
xftface_info = (struct xftface_info *) face->extra;
if (xftface_info)
{
+ if (xftface_info->fg_allocated_p)
+ XftColorFree (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &xftface_info->xft_fg);
+
+ if (xftface_info->bg_allocated_p)
+ XftColorFree (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &xftface_info->xft_bg);
+
xfree (xftface_info);
face->extra = NULL;
}
@@ -441,10 +486,10 @@ xftfont_get_xft_draw (struct frame *f)
if (! xft_draw)
{
block_input ();
- xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
- FRAME_X_DRAWABLE (f),
- FRAME_X_VISUAL (f),
- FRAME_X_COLORMAP (f));
+ xft_draw = XftDrawCreate (FRAME_X_DISPLAY (f),
+ FRAME_X_DRAWABLE (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f));
unblock_input ();
eassert (xft_draw != NULL);
font_put_frame_data (f, Qxft, xft_draw);
@@ -465,13 +510,16 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
XftDraw *xft_draw = xftfont_get_xft_draw (f);
FT_UInt *code;
XftColor fg, bg;
+ bool bg_allocated_p, fg_allocated_p;
int len = to - from;
int i;
if (s->font == face->font)
xftface_info = (struct xftface_info *) face->extra;
xftfont_get_colors (f, face, s->gc, xftface_info,
- &fg, with_background ? &bg : NULL);
+ &fg, with_background ? &bg : NULL,
+ &bg_allocated_p, &fg_allocated_p);
+
if (s->num_clips > 0)
XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
else
@@ -496,7 +544,40 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
height = ascent =
s->first_glyph->slice.glyphless.lower_yoff
- s->first_glyph->slice.glyphless.upper_yoff;
- XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
+
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ if (with_background
+ && FRAME_DISPLAY_INFO (s->f)->alpha_bits
+ && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
+ {
+ x_xr_ensure_picture (s->f);
+
+ if (FRAME_X_PICTURE (s->f) != None)
+ {
+ XRenderColor xc;
+ int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
+
+ if (s->num_clips > 0)
+ XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (s->f),
+ FRAME_X_PICTURE (s->f),
+ 0, 0, s->clip, s->num_clips);
+ else
+ x_xr_reset_ext_clip (f);
+ x_xrender_color_from_gc_background (s->f, s->gc, &xc, s->hl != DRAW_CURSOR);
+ XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
+ PictOpSrc, FRAME_X_PICTURE (s->f),
+ &xc, x, y - ascent, s->width, height);
+ x_xr_reset_ext_clip (f);
+ x_mark_frame_dirty (s->f);
+
+ with_background = false;
+ }
+ else
+ XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
+ }
+ else
+#endif
+ XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
}
code = alloca (sizeof (FT_UInt) * len);
for (i = 0; i < len; i++)
@@ -513,6 +594,19 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
XftDraw structure. */
x_mark_frame_dirty (f);
+
+ if (bg_allocated_p)
+ XftColorFree (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &bg);
+
+ if (fg_allocated_p)
+ XftColorFree (FRAME_X_DISPLAY (f),
+ FRAME_X_VISUAL (f),
+ FRAME_X_COLORMAP (f),
+ &fg);
+
unblock_input ();
return len;
}
@@ -549,18 +643,23 @@ xftfont_end_for_frame (struct frame *f)
return 0;
}
-/* When using X double buffering, the XftDraw structure we build
- seems to be useless once a frame is resized, so recreate it on
+/* When using X double buffering, the XRender surfaces we create seem
+ to become useless once the window acting as the front buffer is
+ resized for an unknown reason (X server bug?), so recreate it on
ConfigureNotify and in some other cases. */
+#ifdef HAVE_XDBE
static void
xftfont_drop_xrender_surfaces (struct frame *f)
{
- block_input ();
if (FRAME_X_DOUBLE_BUFFERED_P (f))
- xftfont_end_for_frame (f);
- unblock_input ();
+ {
+ block_input ();
+ xftfont_end_for_frame (f);
+ unblock_input ();
+ }
}
+#endif
static bool
xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
@@ -647,35 +746,37 @@ static void syms_of_xftfont_for_pdumper (void);
struct font_driver const xftfont_driver =
{
/* We can't draw a text without device dependent functions. */
- .type = LISPSYM_INITIALLY (Qxft),
- .get_cache = xfont_get_cache,
- .list = xftfont_list,
- .match = xftfont_match,
- .list_family = ftfont_list_family,
- .open_font = xftfont_open,
- .close_font = xftfont_close,
- .prepare_face = xftfont_prepare_face,
- .done_face = xftfont_done_face,
- .has_char = xftfont_has_char,
- .encode_char = xftfont_encode_char,
- .text_extents = xftfont_text_extents,
- .draw = xftfont_draw,
- .get_bitmap = ftfont_get_bitmap,
- .anchor_point = ftfont_anchor_point,
+ .type = LISPSYM_INITIALLY (Qxft),
+ .get_cache = xfont_get_cache,
+ .list = xftfont_list,
+ .match = xftfont_match,
+ .list_family = ftfont_list_family,
+ .open_font = xftfont_open,
+ .close_font = xftfont_close,
+ .prepare_face = xftfont_prepare_face,
+ .done_face = xftfont_done_face,
+ .has_char = xftfont_has_char,
+ .encode_char = xftfont_encode_char,
+ .text_extents = xftfont_text_extents,
+ .draw = xftfont_draw,
+ .get_bitmap = ftfont_get_bitmap,
+ .anchor_point = ftfont_anchor_point,
#ifdef HAVE_LIBOTF
- .otf_capability = ftfont_otf_capability,
+ .otf_capability = ftfont_otf_capability,
#endif
- .end_for_frame = xftfont_end_for_frame,
+ .end_for_frame = xftfont_end_for_frame,
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
- .shape = xftfont_shape,
+ .shape = xftfont_shape,
#endif
#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
- .get_variation_glyphs = ftfont_variation_glyphs,
+ .get_variation_glyphs = ftfont_variation_glyphs,
+#endif
+ .filter_properties = ftfont_filter_properties,
+ .cached_font_ok = xftfont_cached_font_ok,
+ .combining_capability = ftfont_combining_capability,
+#ifdef HAVE_XDBE
+ .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
#endif
- .filter_properties = ftfont_filter_properties,
- .cached_font_ok = xftfont_cached_font_ok,
- .combining_capability = ftfont_combining_capability,
- .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
};
#ifdef HAVE_HARFBUZZ
struct font_driver xfthbfont_driver;
@@ -696,6 +797,15 @@ syms_of_xftfont (void)
This is needed with some fonts to correct vertical overlap of glyphs. */);
xft_font_ascent_descent_override = 0;
+ DEFVAR_LISP ("xft-color-font-whitelist", Vxft_color_font_whitelist,
+ doc: /* List of "color" font families that don't actually have color glyphs.
+Some fonts (such as Source Code Pro) are reported as color fonts, but
+do not actually have glyphs with colors that can cause Xft crashes.
+
+The font families in this list will not be ignored when
+`xft-ignore-color-fonts' is non-nil. */);
+ Vxft_color_font_whitelist = list1 (build_pure_c_string ("Source Code Pro"));
+
pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper);
}
diff --git a/src/xgselect.c b/src/xgselect.c
index d22340fc9bc..6e09a15fa84 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -33,6 +33,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
static ptrdiff_t threads_holding_glib_lock;
static GMainContext *glib_main_context;
+/* The depth of xg_select suppression. */
+static int xg_select_suppress_count;
+
void
release_select_lock (void)
{
@@ -69,6 +72,23 @@ acquire_select_lock (GMainContext *context)
#endif
}
+/* Call this to not use xg_select when using it would be a bad idea,
+ i.e. during drag-and-drop. */
+void
+suppress_xg_select (void)
+{
+ ++xg_select_suppress_count;
+}
+
+void
+release_xg_select (void)
+{
+ if (!xg_select_suppress_count)
+ emacs_abort ();
+
+ --xg_select_suppress_count;
+}
+
/* `xg_select' is a `pselect' replacement. Why do we need a separate function?
1. Timeouts. Glib and Gtk rely on timer events. If we did pselect
with a greater timeout then the one scheduled by Glib, we would
@@ -96,15 +116,21 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1;
int i, nfds, tmo_in_millisec, must_free = 0;
bool need_to_dispatch;
-#ifdef HAVE_PGTK
+#ifdef USE_GTK
bool already_has_events;
#endif
+ if (xg_select_suppress_count)
+ return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask);
+
context = g_main_context_default ();
acquire_select_lock (context);
-#ifdef HAVE_PGTK
+#ifdef USE_GTK
already_has_events = g_main_context_pending (context);
+#ifndef HAVE_PGTK
+ already_has_events = already_has_events && x_gtk_use_native_input;
+#endif
#endif
if (rfds) all_rfds = *rfds;
@@ -153,21 +179,26 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
tmop = &tmo;
}
-#ifndef HAVE_PGTK
+#ifndef USE_GTK
fds_lim = max_fds + 1;
nfds = thread_select (pselect, fds_lim,
&all_rfds, have_wfds ? &all_wfds : NULL, efds,
tmop, sigmask);
#else
- /*
- On PGTK, when you type a key, the key press event are received,
- and one more key press event seems to be received internally.
- The second event is not via a socket, so there are weird status:
- - socket read buffer is empty
- - a key press event is pending
- In that case, we should not sleep, and dispatch the event immediately.
- Bug#52761
- */
+ /* On PGTK, when you type a key, the key press event are received,
+ and one more key press event seems to be received internally.
+
+ The same can happen with GTK native input, which makes input
+ slow.
+
+ The second event is not sent via the display connection, so the
+ following is the case:
+
+ - socket read buffer is empty
+ - a key press event is pending
+
+ In that case, we should not sleep in pselect, and dispatch the
+ event immediately. (Bug#52761) */
if (!already_has_events)
{
fds_lim = max_fds + 1;
diff --git a/src/xgselect.h b/src/xgselect.h
index 15482cbf922..156d4bde59f 100644
--- a/src/xgselect.h
+++ b/src/xgselect.h
@@ -25,9 +25,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
struct timespec;
-extern int xg_select (int max_fds,
- fd_set *rfds, fd_set *wfds, fd_set *efds,
- struct timespec *timeout, sigset_t *sigmask);
+extern int xg_select (int, fd_set *, fd_set *, fd_set *,
+ struct timespec *, sigset_t *);
+extern void suppress_xg_select (void);
+extern void release_xg_select (void);
extern void release_select_lock (void);
diff --git a/src/xmenu.c b/src/xmenu.c
index b755f75da02..c006d2bfe21 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -52,6 +52,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif
#ifdef HAVE_XINPUT2
+#include <math.h>
#include <X11/extensions/XInput2.h>
#endif
@@ -183,8 +184,8 @@ x_menu_wait_for_event (void *data)
instead of the small ifdefs below. */
while (
-#ifdef USE_X_TOOLKIT
- ! XtAppPending (Xt_app_con)
+#if defined USE_X_TOOLKIT
+ ! (data ? XPending (data) : XtAppPending (Xt_app_con))
#elif defined USE_GTK
! gtk_events_pending ()
#else
@@ -197,6 +198,10 @@ x_menu_wait_for_event (void *data)
struct x_display_info *dpyinfo;
int n = 0;
+ /* ISTM that if timer_check is okay, this should be too, since
+ both can run random Lisp. */
+ x_handle_pending_selection_requests ();
+
FD_ZERO (&read_fds);
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
{
@@ -221,6 +226,62 @@ x_menu_wait_for_event (void *data)
#endif
}
}
+
+#if !defined USE_GTK && !defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+static void
+x_menu_translate_generic_event (XEvent *event)
+{
+ struct x_display_info *dpyinfo;
+ XEvent copy;
+ XIDeviceEvent *xev;
+
+ dpyinfo = x_display_info_for_display (event->xgeneric.display);
+
+ if (event->xgeneric.extension == dpyinfo->xi2_opcode)
+ {
+ eassert (!event->xcookie.data);
+
+ if (XGetEventData (dpyinfo->display, &event->xcookie))
+ {
+ switch (event->xcookie.evtype)
+ {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ xev = (XIDeviceEvent *) event->xcookie.data;
+ copy.xbutton.type = (event->xcookie.evtype == XI_ButtonPress
+ ? ButtonPress : ButtonRelease);
+ copy.xbutton.serial = xev->serial;
+ copy.xbutton.send_event = xev->send_event;
+ copy.xbutton.display = dpyinfo->display;
+ copy.xbutton.window = xev->event;
+ copy.xbutton.root = xev->root;
+ copy.xbutton.subwindow = xev->child;
+ copy.xbutton.time = xev->time;
+ copy.xbutton.x = lrint (xev->event_x);
+ copy.xbutton.y = lrint (xev->event_y);
+ copy.xbutton.x_root = lrint (xev->root_x);
+ copy.xbutton.y_root = lrint (xev->root_y);
+ copy.xbutton.state = xi_convert_event_state (xev);
+ copy.xbutton.button = xev->detail;
+ copy.xbutton.same_screen = True;
+
+ XPutBackEvent (dpyinfo->display, &copy);
+
+ break;
+ }
+ XFreeEventData (dpyinfo->display, &event->xcookie);
+ }
+ }
+}
+#endif
+
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
+static void
+x_menu_expose_event (XEvent *event)
+{
+ x_dispatch_event (event, event->xexpose.display);
+}
+#endif
#endif /* ! MSDOS */
@@ -240,18 +301,25 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
LWLIB_ID id, bool do_timers)
{
XEvent event;
+ XEvent copy;
+#ifdef HAVE_XINPUT2
+ bool cookie_claimed_p = false;
+ XIDeviceEvent *xev;
+ struct xi_device_t *device;
+#endif
while (popup_activated_flag)
{
if (initial_event)
{
- event = *initial_event;
+ copy = event = *initial_event;
initial_event = 0;
}
else
{
if (do_timers) x_menu_wait_for_event (0);
XtAppNextEvent (Xt_app_con, &event);
+ copy = event;
}
/* Make sure we don't consider buttons grabbed after menu goes.
@@ -271,6 +339,7 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
so Motif thinks this is the case. */
event.xbutton.state = 0;
#endif
+ copy = event;
}
/* Pop down on C-g and Escape. */
else if (event.type == KeyPress
@@ -281,9 +350,100 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo,
if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
|| keysym == XK_Escape) /* Any escape, ignore modifiers. */
popup_activated_flag = 0;
+
+ copy = event;
}
+#ifdef HAVE_XINPUT2
+ else if (event.type == GenericEvent
+ && dpyinfo->supports_xi2
+ && event.xgeneric.display == dpyinfo->display
+ && event.xgeneric.extension == dpyinfo->xi2_opcode)
+ {
+ if (!event.xcookie.data
+ && XGetEventData (dpyinfo->display, &event.xcookie))
+ cookie_claimed_p = true;
- x_dispatch_event (&event, event.xany.display);
+ if (event.xcookie.data)
+ {
+ switch (event.xgeneric.evtype)
+ {
+ case XI_ButtonRelease:
+ {
+ xev = (XIDeviceEvent *) event.xcookie.data;
+ device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+ dpyinfo->grabbed &= ~(1 << xev->detail);
+ device->grab &= ~(1 << xev->detail);
+
+ copy.xbutton.type = ButtonRelease;
+ copy.xbutton.serial = xev->serial;
+ copy.xbutton.send_event = xev->send_event;
+ copy.xbutton.display = dpyinfo->display;
+ copy.xbutton.window = xev->event;
+ copy.xbutton.root = xev->root;
+ copy.xbutton.subwindow = xev->child;
+ copy.xbutton.time = xev->time;
+ copy.xbutton.x = lrint (xev->event_x);
+ copy.xbutton.y = lrint (xev->event_y);
+ copy.xbutton.x_root = lrint (xev->root_x);
+ copy.xbutton.y_root = lrint (xev->root_y);
+ copy.xbutton.state = xi_convert_event_state (xev);
+ copy.xbutton.button = xev->detail;
+ copy.xbutton.same_screen = True;
+
+#ifdef USE_MOTIF /* Pretending that the event came from a
+ Btn1Down seems the only way to convince Motif to
+ activate its callbacks; setting the XmNmenuPost
+ isn't working. --marcus@sysc.pdx.edu. */
+ copy.xbutton.button = 1;
+ /* Motif only pops down menus when no Ctrl, Alt or Mod
+ key is pressed and the button is released. So reset key state
+ so Motif thinks this is the case. */
+ copy.xbutton.state = 0;
+#endif
+
+ break;
+ }
+ case XI_KeyPress:
+ {
+ KeySym keysym;
+
+ xev = (XIDeviceEvent *) event.xcookie.data;
+
+ copy.xkey.type = KeyPress;
+ copy.xkey.serial = xev->serial;
+ copy.xkey.send_event = xev->send_event;
+ copy.xkey.display = dpyinfo->display;
+ copy.xkey.window = xev->event;
+ copy.xkey.root = xev->root;
+ copy.xkey.subwindow = xev->child;
+ copy.xkey.time = xev->time;
+ copy.xkey.x = lrint (xev->event_x);
+ copy.xkey.y = lrint (xev->event_y);
+ copy.xkey.x_root = lrint (xev->root_x);
+ copy.xkey.y_root = lrint (xev->root_y);
+ copy.xkey.state = xi_convert_event_state (xev);
+ copy.xkey.keycode = xev->detail;
+ copy.xkey.same_screen = True;
+
+ keysym = XLookupKeysym (&copy.xkey, 0);
+
+ if ((keysym == XK_g
+ && (copy.xkey.state & ControlMask) != 0)
+ || keysym == XK_Escape) /* Any escape, ignore modifiers. */
+ popup_activated_flag = 0;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (cookie_claimed_p)
+ XFreeEventData (dpyinfo->display, &event.xcookie);
+#endif
+
+ x_dispatch_event (&copy, copy.xany.display);
}
}
@@ -293,6 +453,9 @@ DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_i
{
XEvent ev;
struct frame *f = decode_window_system_frame (frame);
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+#endif
Widget menubar;
block_input ();
@@ -305,12 +468,44 @@ DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_i
Window child;
bool error_p = false;
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ /* Clear the XI2 grab so Motif or lwlib can set a core grab.
+ Otherwise some versions of Motif will emit a warning and hang,
+ and lwlib will fail to destroy the menu window. */
+
+ if (dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
+ {
+ for (int i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ /* The keyboard grab matters too, in this specific
+ case. */
+#ifndef USE_LUCID
+ if (dpyinfo->devices[i].grab)
+#endif
+ {
+ XIUngrabDevice (dpyinfo->display,
+ dpyinfo->devices[i].device_id,
+ CurrentTime);
+ dpyinfo->devices[i].grab = 0;
+ }
+ }
+ }
+#endif
+
x_catch_errors (FRAME_X_DISPLAY (f));
memset (&ev, 0, sizeof ev);
ev.xbutton.display = FRAME_X_DISPLAY (f);
ev.xbutton.window = XtWindow (menubar);
ev.xbutton.root = FRAME_DISPLAY_INFO (f)->root_window;
+#ifndef HAVE_XINPUT2
ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
+#else
+ ev.xbutton.time = ((dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_KeyPress))
+ ? dpyinfo->last_user_time
+ : XtLastTimestampProcessed (dpyinfo->display));
+#endif
ev.xbutton.button = Button1;
ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
ev.xbutton.same_screen = True;
@@ -454,14 +649,22 @@ x_activate_menubar (struct frame *f)
Otherwise some versions of Motif will emit a warning and hang,
and lwlib will fail to destroy the menu window. */
- if (dpyinfo->num_devices)
+ if (dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
- XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
- CurrentTime);
+ {
+ if (dpyinfo->devices[i].grab)
+ XIUngrabDevice (dpyinfo->display,
+ dpyinfo->devices[i].device_id,
+ CurrentTime);
+ }
}
#endif
- XtDispatchEvent (f->output_data.x->saved_menu_event);
+ /* The cascade button might have been deleted, so don't activate the
+ popup if it no widget was found to dispatch to. */
+ popup_activated_flag
+ = XtDispatchEvent (f->output_data.x->saved_menu_event);
#endif
unblock_input ();
@@ -742,7 +945,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
struct buffer *prev = current_buffer;
Lisp_Object buffer;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
@@ -1282,7 +1485,7 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
GtkWidget *menu;
GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
struct next_popup_x_y popup_x_y;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
bool use_pos_func = ! for_click;
#ifdef HAVE_GTK3
@@ -1342,6 +1545,26 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
if (i == 5) i = 0;
}
+#if !defined HAVE_GTK3 && defined HAVE_XINPUT2
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
+ {
+ for (int i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
+ {
+ if (FRAME_DISPLAY_INFO (f)->devices[i].grab)
+ {
+ FRAME_DISPLAY_INFO (f)->devices[i].grab = 0;
+
+ XIUngrabDevice (FRAME_X_DISPLAY (f),
+ FRAME_DISPLAY_INFO (f)->devices[i].device_id,
+ CurrentTime);
+ }
+ }
+ }
+#endif
+
+ DEFER_SELECTIONS;
+
/* Display the menu. */
gtk_widget_show_all (menu);
@@ -1384,6 +1607,84 @@ popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
menu_item_selection = client_data;
}
+
+#ifdef HAVE_XINPUT2
+static void
+prepare_for_entry_into_toolkit_menu (struct frame *f)
+{
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+ Lisp_Object tail, frame;
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (!dpyinfo->supports_xi2)
+ return;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &mask, 1);
+ }
+}
+
+static void
+leave_toolkit_menu (void *data)
+{
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+ Lisp_Object tail, frame;
+ struct x_display_info *dpyinfo;
+ struct frame *f;
+
+ dpyinfo = FRAME_DISPLAY_INFO ((struct frame *) data);
+
+ if (!dpyinfo->supports_xi2)
+ return;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+
+ if (FRAME_X_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && !FRAME_TOOLTIP_P (f))
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &mask, 1);
+ }
+}
+#endif
+
/* ID is the LWLIB ID of the dialog box. */
static void
@@ -1395,6 +1696,23 @@ pop_down_menu (int id)
popup_activated_flag = 0;
}
+#if defined HAVE_XINPUT2 && defined USE_MOTIF
+static Bool
+server_timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ XID *args = (XID *) arg;
+
+ if (xevent->type == PropertyNotify
+ && xevent->xproperty.window == args[0]
+ && xevent->xproperty.atom == args[1])
+ return True;
+
+ return False;
+}
+#endif
+
/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
menu pops down.
menu_item_selection will be set to the selection. */
@@ -1410,6 +1728,10 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
LWLIB_ID menu_id;
Widget menu;
Window dummy_window;
+#if defined HAVE_XINPUT2 && defined USE_MOTIF
+ XEvent property_dummy;
+ Atom property_atom;
+#endif
eassert (FRAME_X_P (f));
@@ -1462,26 +1784,82 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
/* Don't allow any geometry request from the user. */
XtSetArg (av[ac], (char *) XtNgeometry, 0); ac++;
XtSetValues (menu, av, ac);
-#if defined HAVE_XINPUT2 && defined USE_LUCID
+
+#ifdef HAVE_XINPUT2
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- /* Clear the XI2 grab so lwlib can set a core grab. */
- if (dpyinfo->num_devices)
+ /* Clear the XI2 grab, and if any XI2 grab was set, place a core
+ grab on the frame's edit widget. */
+ if (dpyinfo->supports_xi2)
+ XGrabServer (dpyinfo->display);
+
+ if (dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
- XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
- CurrentTime);
+ {
+ if (dpyinfo->devices[i].grab)
+ {
+ dpyinfo->devices[i].grab = 0;
+
+ XIUngrabDevice (dpyinfo->display,
+ dpyinfo->devices[i].device_id,
+ CurrentTime);
+ }
+ }
+ }
+
+#ifdef USE_MOTIF
+ if (dpyinfo->supports_xi2)
+ {
+ /* Dispatch a PropertyNotify to Xt with the current server time.
+ Motif tries to set a grab with the timestamp of the last event
+ processed by Xt, but Xt doesn't consider GenericEvents, so the
+ timestamp is always less than the last grab time. */
+
+ property_atom = dpyinfo->Xatom_EMACS_SERVER_TIME_PROP;
+
+ XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ property_atom, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *) &property_atom, 1);
+
+ XIfEvent (dpyinfo->display, &property_dummy, server_timestamp_predicate,
+ (XPointer) &(XID[]) {FRAME_OUTER_WINDOW (f), property_atom});
+
+ XtDispatchEvent (&property_dummy);
}
#endif
+#endif
+
+#ifdef HAVE_XINPUT2
+ prepare_for_entry_into_toolkit_menu (f);
+
+#ifdef USE_LUCID
+ if (dpyinfo->supports_xi2)
+ x_mouse_leave (dpyinfo);
+#endif
+#endif
/* Display the menu. */
lw_popup_menu (menu, &dummy);
+
+#ifdef HAVE_XINPUT2
+ if (dpyinfo->supports_xi2)
+ XUngrabServer (dpyinfo->display);
+#endif
+
popup_activated_flag = 1;
+
x_activate_timeout_atimer ();
{
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
+
+ DEFER_SELECTIONS;
record_unwind_protect_int (pop_down_menu, (int) menu_id);
+#ifdef HAVE_XINPUT2
+ record_unwind_protect_ptr (leave_toolkit_menu, f);
+#endif
/* Process events that apply to the menu. */
popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, true);
@@ -1504,13 +1882,19 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
{
int i;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
- widget_value **submenu_stack
- = alloca (menu_items_used * sizeof *submenu_stack);
- Lisp_Object *subprefix_stack
- = alloca (menu_items_used * sizeof *subprefix_stack);
+ widget_value **submenu_stack;
+ Lisp_Object *subprefix_stack;
int submenu_depth = 0;
+ specpdl_ref specpdl_count;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ USE_SAFE_ALLOCA;
+
+ submenu_stack = SAFE_ALLOCA (menu_items_used
+ * sizeof *submenu_stack);
+ subprefix_stack = SAFE_ALLOCA (menu_items_used
+ * sizeof *subprefix_stack);
+
+ specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_X_P (f));
@@ -1519,6 +1903,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
+ SAFE_FREE ();
return Qnil;
}
@@ -1751,6 +2136,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
entry = Fcons (subprefix_stack[j], entry);
}
unblock_input ();
+
+ SAFE_FREE ();
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
@@ -1765,6 +2152,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
}
unblock_input ();
+
+ SAFE_FREE ();
return Qnil;
}
@@ -1797,7 +2186,9 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
if (menu)
{
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
+
+ DEFER_SELECTIONS;
record_unwind_protect_ptr (pop_down_menu, menu);
/* Display the menu. */
@@ -1852,7 +2243,9 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
/* Process events that apply to the dialog box.
Also handle timers. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ DEFER_SELECTIONS;
/* xdialog_show_unwind is responsible for popping the dialog box down. */
@@ -1884,7 +2277,7 @@ x_dialog_show (struct frame *f, Lisp_Object title,
/* Whether we've seen the boundary between left-hand elts and right-hand. */
bool boundary_seen = false;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_X_P (f));
@@ -2036,7 +2429,7 @@ xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
Lisp_Object title;
const char *error_name;
Lisp_Object selection;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
check_window_system (f);
@@ -2157,7 +2550,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
int maxwidth;
int dummy_int;
unsigned int dummy_uint;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ specpdl_ref specpdl_count = SPECPDL_INDEX ();
eassert (FRAME_X_P (f) || FRAME_MSDOS_P (f));
@@ -2314,18 +2707,18 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
y = max (y, 1);
XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y,
&ulx, &uly, &width, &height);
- if (ulx+width > dispwidth)
+ if (ulx + width > dispwidth)
{
x -= (ulx + width) - dispwidth;
ulx = dispwidth - width;
}
- if (uly+height > dispheight)
+ if (uly + height > dispheight)
{
y -= (uly + height) - dispheight;
uly = dispheight - height;
}
#ifndef HAVE_X_WINDOWS
- if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
+ if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 1)
{
/* Move the menu away of the echo area, to avoid overwriting the
menu with help echo messages or vice versa. */
@@ -2349,8 +2742,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
/* If position was not given by a mouse click, adjust so upper left
corner of the menu as a whole ends up at given coordinates. This
is what x-popup-menu says in its documentation. */
- x += width/2;
- y += 1.5*height/(maxlines+2);
+ x += width / 2;
+ y += 1.5 * height/ (maxlines + 2);
}
XMenuSetAEQ (menu, true);
@@ -2358,7 +2751,13 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
pane = selidx = 0;
#ifndef MSDOS
+ DEFER_SELECTIONS;
+
XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
+#ifdef HAVE_XINPUT2
+ XMenuActivateSetTranslateFunction (x_menu_translate_generic_event);
+#endif
+ XMenuActivateSetExposeFunction (x_menu_expose_event);
#endif
record_unwind_protect_ptr (pop_down_menu,
@@ -2367,6 +2766,23 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
/* Help display under X won't work because XMenuActivate contains
a loop that doesn't give Emacs a chance to process it. */
menu_help_frame = f;
+
+#ifdef HAVE_XINPUT2
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ /* Clear the XI2 grab so a core grab can be set. */
+
+ if (dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
+ {
+ for (int i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ if (dpyinfo->devices[i].grab)
+ XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
+ CurrentTime);
+ }
+ }
+#endif
+
status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
x, y, ButtonReleaseMask, &datap,
menu_help_callback);
diff --git a/src/xrdb.c b/src/xrdb.c
index 56e07f74a26..faeea04a539 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -383,14 +383,6 @@ x_load_resources (Display *display, const char *xrm_string,
XrmDatabase db;
char line[256];
-#if defined USE_MOTIF || !(defined USE_CAIRO || defined HAVE_XFT) || !defined USE_LUCID
- const char *helv = "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1";
-#endif
-
-#ifdef USE_MOTIF
- const char *courier = "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1";
-#endif
-
x_rm_string = XrmStringToQuark (XrmStringType);
#ifndef USE_X_TOOLKIT
/* pmr@osf.org says this shouldn't be done if USE_X_TOOLKIT.
@@ -399,47 +391,7 @@ x_load_resources (Display *display, const char *xrm_string,
#endif
rdb = XrmGetStringDatabase ("");
- /* Add some font defaults. If the font `helv' doesn't exist, widgets
- will use some other default font. */
#ifdef USE_MOTIF
-
- sprintf (line, "%s.pane.background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fontList: %s", myclass, helv);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*menu*background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*menubar*background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*verticalScrollBar.background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*verticalScrollBar.troughColor: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*horizontalScrollBar.background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*horizontalScrollBar.troughColor: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s.dialog*.background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb.Text.background: white", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb.FilterText.background: white", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb*DirList.background: white", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb*ItemsList.background: white", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb*background: grey75", myclass);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb.Text.fontList: %s", myclass, courier);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb.FilterText.fontList: %s", myclass, courier);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb*ItemsList.fontList: %s", myclass, courier);
- XrmPutLineResource (&rdb, line);
- sprintf (line, "%s*fsb*DirList.fontList: %s", myclass, courier);
- XrmPutLineResource (&rdb, line);
-
/* Set double click time of list boxes in the file selection
dialog from `double-click-time'. */
if (FIXNUMP (Vdouble_click_time) && XFIXNUM (Vdouble_click_time) > 0)
@@ -451,15 +403,17 @@ x_load_resources (Display *display, const char *xrm_string,
myclass, XFIXNAT (Vdouble_click_time));
XrmPutLineResource (&rdb, line);
}
-
#else /* not USE_MOTIF */
-
+ /* Add some font defaults. If the font `helv' doesn't exist,
+ widgets will use some other default font. */
sprintf (line, "Emacs.dialog*.background: grey75");
XrmPutLineResource (&rdb, line);
#if !(defined USE_CAIRO || defined HAVE_XFT) || !defined (USE_LUCID)
- sprintf (line, "Emacs.dialog*.font: %s", helv);
+ sprintf (line, "Emacs.dialog*.font: %s",
+ "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1");
XrmPutLineResource (&rdb, line);
- sprintf (line, "*XlwMenu*font: %s", helv);
+ sprintf (line, "*XlwMenu*font: %s",
+ "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1");
XrmPutLineResource (&rdb, line);
#endif
sprintf (line, "*XlwMenu*background: grey75");
@@ -468,7 +422,6 @@ x_load_resources (Display *display, const char *xrm_string,
XrmPutLineResource (&rdb, line);
sprintf (line, "Emacs*horizontalScrollBar.background: grey75");
XrmPutLineResource (&rdb, line);
-
#endif /* not USE_MOTIF */
user_database = get_user_db (display);
@@ -533,11 +486,7 @@ x_get_resource (XrmDatabase rdb, const char *name, const char *class,
if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
&& (type == expected_type))
{
- if (type == x_rm_string)
- ret_value->addr = (char *) value.addr;
- else
- memcpy (ret_value->addr, value.addr, ret_value->size);
-
+ *ret_value = value;
return value.size;
}
diff --git a/src/xselect.c b/src/xselect.c
index cfe028a1696..80db0d1fe2a 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "termhooks.h"
#include "keyboard.h"
#include "pdumper.h"
+#include "atimer.h"
#include <X11/Xproto.h>
@@ -44,7 +45,7 @@ struct selection_data;
static void x_decline_selection_request (struct selection_input_event *);
static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool,
- struct x_display_info *);
+ struct x_display_info *, bool);
static bool waiting_for_other_props_on_window (Display *, Window);
static struct prop_location *expect_property_change (Display *, Window,
Atom, int);
@@ -52,12 +53,14 @@ static void unexpect_property_change (struct prop_location *);
static void wait_for_property_change (struct prop_location *);
static Lisp_Object x_get_window_property_as_lisp_data (struct x_display_info *,
Window, Atom,
- Lisp_Object, Atom);
+ Lisp_Object, Atom, bool);
static Lisp_Object selection_data_to_lisp_data (struct x_display_info *,
const unsigned char *,
ptrdiff_t, Atom, int);
static void lisp_data_to_selection_data (struct x_display_info *, Lisp_Object,
struct selection_data *);
+static void x_send_client_event (Lisp_Object, Lisp_Object, Lisp_Object,
+ Atom, Lisp_Object, Lisp_Object);
/* Printing traces to stderr. */
@@ -98,132 +101,81 @@ static void lisp_data_to_selection_data (struct x_display_info *, Lisp_Object,
static int
selection_quantum (Display *display)
{
- long mrs = XMaxRequestSize (display);
+ long mrs = XExtendedMaxRequestSize (display);
+
+ if (!mrs)
+ mrs = XMaxRequestSize (display);
+
return (mrs < MAX_SELECTION_QUANTUM / X_LONG_SIZE + 25
? (mrs - 25) * X_LONG_SIZE
: MAX_SELECTION_QUANTUM);
}
-#define LOCAL_SELECTION(selection_symbol,dpyinfo) \
+#define LOCAL_SELECTION(selection_symbol, dpyinfo) \
assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist)
-/* Define a queue to save up SELECTION_REQUEST_EVENT events for later
- handling. */
-
-struct selection_event_queue
- {
- struct selection_input_event event;
- struct selection_event_queue *next;
- };
-
-static struct selection_event_queue *selection_queue;
-
-/* Nonzero means queue up SELECTION_REQUEST_EVENT events. */
-
-static int x_queue_selection_requests;
-
-/* True if the input events are duplicates. */
-
-static bool
-selection_input_event_equal (struct selection_input_event *a,
- struct selection_input_event *b)
-{
- return (a->kind == b->kind && a->dpyinfo == b->dpyinfo
- && a->requestor == b->requestor && a->selection == b->selection
- && a->target == b->target && a->property == b->property
- && a->time == b->time);
-}
-
-/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */
-
-static void
-x_queue_event (struct selection_input_event *event)
-{
- struct selection_event_queue *queue_tmp;
-
- /* Don't queue repeated requests.
- This only happens for large requests which uses the incremental protocol. */
- for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
- {
- if (selection_input_event_equal (event, &queue_tmp->event))
- {
- TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp);
- x_decline_selection_request (event);
- return;
- }
- }
-
- queue_tmp = xmalloc (sizeof *queue_tmp);
- TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp);
- queue_tmp->event = *event;
- queue_tmp->next = selection_queue;
- selection_queue = queue_tmp;
-}
-
-/* Start queuing SELECTION_REQUEST_EVENT events. */
-
-static void
-x_start_queuing_selection_requests (void)
-{
- if (x_queue_selection_requests)
- emacs_abort ();
-
- x_queue_selection_requests++;
- TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests);
-}
-
-/* Stop queuing SELECTION_REQUEST_EVENT events. */
-
-static void
-x_stop_queuing_selection_requests (void)
-{
- TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests);
- --x_queue_selection_requests;
-
- /* Take all the queued events and put them back
- so that they get processed afresh. */
-
- while (selection_queue != NULL)
- {
- struct selection_event_queue *queue_tmp = selection_queue;
- TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp);
- kbd_buffer_unget_event (&queue_tmp->event);
- selection_queue = queue_tmp->next;
- xfree (queue_tmp);
- }
-}
-
/* This converts a Lisp symbol to a server Atom, avoiding a server
roundtrip whenever possible. */
-static Atom
+Atom
symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym)
{
Atom val;
- if (NILP (sym)) return 0;
- if (EQ (sym, QPRIMARY)) return XA_PRIMARY;
- if (EQ (sym, QSECONDARY)) return XA_SECONDARY;
- if (EQ (sym, QSTRING)) return XA_STRING;
- if (EQ (sym, QINTEGER)) return XA_INTEGER;
- if (EQ (sym, QATOM)) return XA_ATOM;
- if (EQ (sym, QCLIPBOARD)) return dpyinfo->Xatom_CLIPBOARD;
- if (EQ (sym, QTIMESTAMP)) return dpyinfo->Xatom_TIMESTAMP;
- if (EQ (sym, QTEXT)) return dpyinfo->Xatom_TEXT;
- if (EQ (sym, QCOMPOUND_TEXT)) return dpyinfo->Xatom_COMPOUND_TEXT;
- if (EQ (sym, QUTF8_STRING)) return dpyinfo->Xatom_UTF8_STRING;
- if (EQ (sym, QDELETE)) return dpyinfo->Xatom_DELETE;
- if (EQ (sym, QMULTIPLE)) return dpyinfo->Xatom_MULTIPLE;
- if (EQ (sym, QINCR)) return dpyinfo->Xatom_INCR;
- if (EQ (sym, Q_EMACS_TMP_)) return dpyinfo->Xatom_EMACS_TMP;
- if (EQ (sym, QTARGETS)) return dpyinfo->Xatom_TARGETS;
- if (EQ (sym, QNULL)) return dpyinfo->Xatom_NULL;
- if (!SYMBOLP (sym)) emacs_abort ();
+ if (NILP (sym))
+ return 0;
+ if (EQ (sym, QPRIMARY))
+ return XA_PRIMARY;
+ if (EQ (sym, QSECONDARY))
+ return XA_SECONDARY;
+ if (EQ (sym, QSTRING))
+ return XA_STRING;
+ if (EQ (sym, QINTEGER))
+ return XA_INTEGER;
+ if (EQ (sym, QATOM))
+ return XA_ATOM;
+ if (EQ (sym, QCLIPBOARD))
+ return dpyinfo->Xatom_CLIPBOARD;
+ if (EQ (sym, QTIMESTAMP))
+ return dpyinfo->Xatom_TIMESTAMP;
+ if (EQ (sym, QTEXT))
+ return dpyinfo->Xatom_TEXT;
+ if (EQ (sym, QCOMPOUND_TEXT))
+ return dpyinfo->Xatom_COMPOUND_TEXT;
+ if (EQ (sym, QUTF8_STRING))
+ return dpyinfo->Xatom_UTF8_STRING;
+ if (EQ (sym, QDELETE))
+ return dpyinfo->Xatom_DELETE;
+ if (EQ (sym, QMULTIPLE))
+ return dpyinfo->Xatom_MULTIPLE;
+ if (EQ (sym, QINCR))
+ return dpyinfo->Xatom_INCR;
+ if (EQ (sym, Q_EMACS_TMP_))
+ return dpyinfo->Xatom_EMACS_TMP;
+ if (EQ (sym, QTARGETS))
+ return dpyinfo->Xatom_TARGETS;
+ if (EQ (sym, QNULL))
+ return dpyinfo->Xatom_NULL;
+ if (EQ (sym, QXdndSelection))
+ return dpyinfo->Xatom_XdndSelection;
+ if (EQ (sym, QXmTRANSFER_SUCCESS))
+ return dpyinfo->Xatom_XmTRANSFER_SUCCESS;
+ if (EQ (sym, QXmTRANSFER_FAILURE))
+ return dpyinfo->Xatom_XmTRANSFER_FAILURE;
+ if (EQ (sym, QXdndDirectSave0))
+ return dpyinfo->Xatom_XdndDirectSave0;
+ if (EQ (sym, Qtext_plain))
+ return dpyinfo->Xatom_text_plain;
+ if (EQ (sym, QXdndActionDirectSave))
+ return dpyinfo->Xatom_XdndActionDirectSave;
+
+ if (!SYMBOLP (sym))
+ emacs_abort ();
TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym)));
block_input ();
- val = XInternAtom (dpyinfo->display, SSDATA (SYMBOL_NAME (sym)), False);
+ val = x_intern_cached_atom (dpyinfo, SSDATA (SYMBOL_NAME (sym)), false);
unblock_input ();
return val;
}
@@ -232,7 +184,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym)
/* This converts a server Atom to a Lisp symbol, avoiding server roundtrips
and calls to intern whenever possible. */
-static Lisp_Object
+Lisp_Object
x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom)
{
char *str;
@@ -279,36 +231,55 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom)
return QTARGETS;
if (atom == dpyinfo->Xatom_NULL)
return QNULL;
+ if (atom == dpyinfo->Xatom_XdndSelection)
+ return QXdndSelection;
+ if (atom == dpyinfo->Xatom_XmTRANSFER_SUCCESS)
+ return QXmTRANSFER_SUCCESS;
+ if (atom == dpyinfo->Xatom_XmTRANSFER_FAILURE)
+ return QXmTRANSFER_FAILURE;
+ if (atom == dpyinfo->Xatom_XdndDirectSave0)
+ return QXdndDirectSave0;
+ if (atom == dpyinfo->Xatom_text_plain)
+ return Qtext_plain;
+ if (atom == dpyinfo->Xatom_XdndActionDirectSave)
+ return QXdndActionDirectSave;
- block_input ();
- str = XGetAtomName (dpyinfo->display, atom);
- unblock_input ();
+ x_catch_errors (dpyinfo->display);
+ str = x_get_atom_name (dpyinfo, atom, NULL);
+ x_uncatch_errors ();
+
+ TRACE0 ("XGetAtomName --> NULL");
+ if (!str)
+ return Qnil;
TRACE1 ("XGetAtomName --> %s", str);
- if (! str) return Qnil;
+
val = intern (str);
- block_input ();
- /* This was allocated by Xlib, so use XFree. */
- XFree (str);
- unblock_input ();
+ xfree (str);
return val;
}
/* Do protocol to assert ourself as a selection owner.
FRAME shall be the owner; it must be a valid X frame.
+ TIMESTAMP should be the timestamp where selection ownership will be
+ assumed.
+ DND_DATA is the local value that will be used for selection requests
+ with `dpyinfo->pending_dnd_time'.
Update the Vselection_alist so that we can reply to later requests for
our selection. */
-static void
+void
x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
- Lisp_Object frame)
+ Lisp_Object frame, Lisp_Object dnd_data, Time timestamp)
{
struct frame *f = XFRAME (frame);
Window selecting_window = FRAME_X_WINDOW (f);
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Display *display = dpyinfo->display;
- Time timestamp = dpyinfo->last_user_time;
Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name);
+ if (!timestamp)
+ timestamp = dpyinfo->last_user_time;
+
block_input ();
x_catch_errors (display);
XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
@@ -321,8 +292,9 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
Lisp_Object selection_data;
Lisp_Object prev_value;
- selection_data = list4 (selection_name, selection_value,
- INT_TO_INTEGER (timestamp), frame);
+ selection_data = list5 (selection_name, selection_value,
+ INT_TO_INTEGER (timestamp), frame,
+ dnd_data);
prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
tset_selection_alist
@@ -352,18 +324,33 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
This function is used both for remote requests (LOCAL_REQUEST is zero)
and for local x-get-selection-internal (LOCAL_REQUEST is nonzero).
+ If LOCAL_VALUE is non-nil, use it as the local copy. Also allow
+ quitting in that case, and let DPYINFO be NULL.
+
+ If NEED_ALTERNATE is true, use the drag-and-drop local value
+ instead.
+
This calls random Lisp code, and may signal or gc. */
static Lisp_Object
x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
- bool local_request, struct x_display_info *dpyinfo)
+ bool local_request, struct x_display_info *dpyinfo,
+ Lisp_Object local_value, bool need_alternate)
{
- Lisp_Object local_value;
+ Lisp_Object tem;
Lisp_Object handler_fn, value, check;
+ bool may_quit;
+ specpdl_ref count;
- local_value = LOCAL_SELECTION (selection_symbol, dpyinfo);
+ may_quit = false;
- if (NILP (local_value)) return Qnil;
+ if (NILP (local_value))
+ local_value = LOCAL_SELECTION (selection_symbol, dpyinfo);
+ else
+ may_quit = true;
+
+ if (NILP (local_value))
+ return Qnil;
/* TIMESTAMP is a special case. */
if (EQ (target_type, QTIMESTAMP))
@@ -376,16 +363,38 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
/* Don't allow a quit within the converter.
When the user types C-g, he would be surprised
if by luck it came during a converter. */
- ptrdiff_t count = SPECPDL_INDEX ();
- specbind (Qinhibit_quit, Qt);
+ count = SPECPDL_INDEX ();
+
+ if (!may_quit)
+ specbind (Qinhibit_quit, Qt);
CHECK_SYMBOL (target_type);
handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
+ if (CONSP (handler_fn))
+ handler_fn = XCDR (handler_fn);
+
+ if (!need_alternate)
+ tem = XCAR (XCDR (local_value));
+ else
+ tem = XCAR (XCDR (XCDR (XCDR (XCDR (local_value)))));
+
+ if (STRINGP (tem))
+ {
+ local_value = Fget_text_property (make_fixnum (0),
+ target_type, tem);
+
+ if (!NILP (local_value))
+ tem = local_value;
+ }
+
if (!NILP (handler_fn))
- value = call3 (handler_fn,
- selection_symbol, (local_request ? Qnil : target_type),
- XCAR (XCDR (local_value)));
+ value = call3 (handler_fn, selection_symbol,
+ ((local_request
+ && NILP (Vx_treat_local_requests_remotely))
+ ? Qnil
+ : target_type),
+ tem);
else
value = Qnil;
value = unbind_to (count, value);
@@ -448,14 +457,6 @@ x_decline_selection_request (struct selection_input_event *event)
unblock_input ();
}
-/* This is the selection request currently being processed.
- It is set to zero when the request is fully processed. */
-static struct selection_input_event *x_selection_current_request;
-
-/* Display info in x_selection_request. */
-
-static struct x_display_info *selection_request_dpyinfo;
-
/* Raw selection data, for sending to a requestor window. */
struct selection_data
@@ -473,12 +474,59 @@ struct selection_data
struct selection_data *next;
};
-/* Linked list of the above (in support of MULTIPLE targets). */
+struct x_selection_request
+{
+ /* The last element in this stack. */
+ struct x_selection_request *last;
-static struct selection_data *converted_selections;
+ /* Its display info. */
+ struct x_display_info *dpyinfo;
+
+ /* Its selection input event. */
+ struct selection_input_event *request;
+
+ /* Linked list of the above (in support of MULTIPLE targets). */
+ struct selection_data *converted_selections;
+
+ /* "Data" to send a requestor for a failed MULTIPLE subtarget. */
+ Atom conversion_fail_tag;
+
+ /* Whether or not conversion was successful. */
+ bool converted;
+};
+
+/* Stack of selections currently being processed.
+ NULL if all requests have been fully processed. */
+
+struct x_selection_request *selection_request_stack;
+
+static void
+x_push_current_selection_request (struct selection_input_event *se,
+ struct x_display_info *dpyinfo)
+{
+ struct x_selection_request *frame;
+
+ frame = xmalloc (sizeof *frame);
+ frame->converted = false;
+ frame->last = selection_request_stack;
+ frame->request = se;
+ frame->dpyinfo = dpyinfo;
+ frame->converted_selections = NULL;
+ frame->conversion_fail_tag = None;
-/* "Data" to send a requestor for a failed MULTIPLE subtarget. */
-static Atom conversion_fail_tag;
+ selection_request_stack = frame;
+}
+
+static void
+x_pop_current_selection_request (void)
+{
+ struct x_selection_request *tem;
+
+ tem = selection_request_stack;
+ selection_request_stack = selection_request_stack->last;
+
+ xfree (tem);
+}
/* Used as an unwind-protect clause so that, if a selection-converter signals
an error, we tell the requestor that we were unable to do what they wanted
@@ -488,19 +536,21 @@ static void
x_selection_request_lisp_error (void)
{
struct selection_data *cs, *next;
+ struct x_selection_request *frame;
+
+ frame = selection_request_stack;
- for (cs = converted_selections; cs; cs = next)
+ for (cs = frame->converted_selections; cs; cs = next)
{
next = cs->next;
if (! cs->nofree && cs->data)
xfree (cs->data);
xfree (cs);
}
- converted_selections = NULL;
+ frame->converted_selections = NULL;
- if (x_selection_current_request != 0
- && selection_request_dpyinfo->display)
- x_decline_selection_request (x_selection_current_request);
+ if (!frame->converted && frame->dpyinfo->display)
+ x_decline_selection_request (frame->request);
}
static void
@@ -564,8 +614,11 @@ x_reply_selection_request (struct selection_input_event *event,
Window window = SELECTION_EVENT_REQUESTOR (event);
ptrdiff_t bytes_remaining;
int max_bytes = selection_quantum (display);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
struct selection_data *cs;
+ struct x_selection_request *frame;
+
+ frame = selection_request_stack;
reply->type = SelectionNotify;
reply->display = display;
@@ -589,7 +642,7 @@ x_reply_selection_request (struct selection_input_event *event,
(section 2.7.2 of ICCCM). Note that we store the data for a
MULTIPLE request in the opposite order; the ICCM says only that
the conversion itself must be done in the same order. */
- for (cs = converted_selections; cs; cs = cs->next)
+ for (cs = frame->converted_selections; cs; cs = cs->next)
{
if (cs->property == None)
continue;
@@ -644,7 +697,7 @@ x_reply_selection_request (struct selection_input_event *event,
be improved; there's a chance of deadlock if more than one
subtarget in a MULTIPLE selection requires an INCR transfer, and
the requestor and Emacs loop waiting on different transfers. */
- for (cs = converted_selections; cs; cs = cs->next)
+ for (cs = frame->converted_selections; cs; cs = cs->next)
if (cs->wait_object)
{
int format_bytes = cs->format / 8;
@@ -749,7 +802,6 @@ static void
x_handle_selection_request (struct selection_input_event *event)
{
Time local_selection_time;
-
struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event);
Atom selection = SELECTION_EVENT_SELECTION (event);
Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection);
@@ -758,9 +810,32 @@ x_handle_selection_request (struct selection_input_event *event)
Atom property = SELECTION_EVENT_PROPERTY (event);
Lisp_Object local_selection_data;
bool success = false;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
+ bool pushed, use_alternate;
+ Lisp_Object alias, tem;
+
+ alias = Vx_selection_alias_alist;
- if (!dpyinfo) goto DONE;
+ FOR_EACH_TAIL_SAFE (alias)
+ {
+ tem = Qnil;
+
+ if (CONSP (alias))
+ tem = XCAR (alias);
+
+ if (CONSP (tem)
+ && EQ (XCAR (tem), selection_symbol)
+ && SYMBOLP (XCDR (tem)))
+ {
+ selection_symbol = XCDR (tem);
+ break;
+ }
+ }
+
+ pushed = false;
+
+ if (!dpyinfo)
+ goto REALLY_DONE;
local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo);
@@ -774,14 +849,23 @@ x_handle_selection_request (struct selection_input_event *event)
&& local_selection_time > SELECTION_EVENT_TIME (event))
goto DONE;
- x_selection_current_request = event;
- selection_request_dpyinfo = dpyinfo;
- record_unwind_protect_void (x_selection_request_lisp_error);
+ use_alternate = false;
- /* We might be able to handle nested x_handle_selection_requests,
- but this is difficult to test, and seems unimportant. */
- x_start_queuing_selection_requests ();
- record_unwind_protect_void (x_stop_queuing_selection_requests);
+ /* This is how the XDND protocol recommends dropping text onto a
+ target that doesn't support XDND. */
+ if (dpyinfo->pending_dnd_time
+ && ((SELECTION_EVENT_TIME (event)
+ == dpyinfo->pending_dnd_time + 1)
+ || (SELECTION_EVENT_TIME (event)
+ == dpyinfo->pending_dnd_time + 2)))
+ use_alternate = true;
+
+ block_input ();
+ pushed = true;
+ x_push_current_selection_request (event, dpyinfo);
+ record_unwind_protect_void (x_pop_current_selection_request);
+ record_unwind_protect_void (x_selection_request_lisp_error);
+ unblock_input ();
TRACE2 ("x_handle_selection_request: selection=%s, target=%s",
SDATA (SYMBOL_NAME (selection_symbol)),
@@ -795,11 +879,12 @@ x_handle_selection_request (struct selection_input_event *event)
Window requestor = SELECTION_EVENT_REQUESTOR (event);
Lisp_Object multprop;
ptrdiff_t j, nselections;
+ struct selection_data cs;
if (property == None) goto DONE;
multprop
= x_get_window_property_as_lisp_data (dpyinfo, requestor, property,
- QMULTIPLE, selection);
+ QMULTIPLE, selection, true);
if (!VECTORP (multprop) || ASIZE (multprop) % 2)
goto DONE;
@@ -811,11 +896,20 @@ x_handle_selection_request (struct selection_input_event *event)
Lisp_Object subtarget = AREF (multprop, 2*j);
Atom subproperty = symbol_to_x_atom (dpyinfo,
AREF (multprop, 2*j+1));
+ bool subsuccess = false;
if (subproperty != None)
- x_convert_selection (selection_symbol, subtarget,
- subproperty, true, dpyinfo);
+ subsuccess = x_convert_selection (selection_symbol, subtarget,
+ subproperty, true, dpyinfo,
+ use_alternate);
+ if (!subsuccess)
+ ASET (multprop, 2*j+1, Qnil);
}
+ /* Save conversion results */
+ lisp_data_to_selection_data (dpyinfo, multprop, &cs);
+ XChangeProperty (dpyinfo->display, requestor, property,
+ cs.type, cs.format, PropModeReplace,
+ cs.data, cs.size);
success = true;
}
else
@@ -824,23 +918,29 @@ x_handle_selection_request (struct selection_input_event *event)
property = SELECTION_EVENT_TARGET (event);
success = x_convert_selection (selection_symbol,
target_symbol, property,
- false, dpyinfo);
+ false, dpyinfo,
+ use_alternate);
}
DONE:
+ if (pushed)
+ selection_request_stack->converted = true;
+
if (success)
x_reply_selection_request (event, dpyinfo);
else
x_decline_selection_request (event);
- x_selection_current_request = 0;
/* Run the `x-sent-selection-functions' abnormal hook. */
if (!NILP (Vx_sent_selection_functions)
- && !EQ (Vx_sent_selection_functions, Qunbound))
+ && !BASE_EQ (Vx_sent_selection_functions, Qunbound))
CALLN (Frun_hook_with_args, Qx_sent_selection_functions,
selection_symbol, target_symbol, success ? Qt : Qnil);
+ /* Used to punt when dpyinfo is NULL. */
+ REALLY_DONE:
+
unbind_to (count, Qnil);
}
@@ -854,14 +954,18 @@ x_handle_selection_request (struct selection_input_event *event)
static bool
x_convert_selection (Lisp_Object selection_symbol,
Lisp_Object target_symbol, Atom property,
- bool for_multiple, struct x_display_info *dpyinfo)
+ bool for_multiple, struct x_display_info *dpyinfo,
+ bool use_alternate)
{
Lisp_Object lisp_selection;
struct selection_data *cs;
+ struct x_selection_request *frame;
lisp_selection
= x_get_local_selection (selection_symbol, target_symbol,
- false, dpyinfo);
+ false, dpyinfo, Qnil, use_alternate);
+
+ frame = selection_request_stack;
/* A nil return value means we can't perform the conversion. */
if (NILP (lisp_selection)
@@ -870,15 +974,16 @@ x_convert_selection (Lisp_Object selection_symbol,
if (for_multiple)
{
cs = xmalloc (sizeof *cs);
- cs->data = (unsigned char *) &conversion_fail_tag;
+ cs->data = ((unsigned char *)
+ &selection_request_stack->conversion_fail_tag);
cs->size = 1;
cs->format = 32;
cs->type = XA_ATOM;
cs->nofree = true;
cs->property = property;
cs->wait_object = NULL;
- cs->next = converted_selections;
- converted_selections = cs;
+ cs->next = frame->converted_selections;
+ frame->converted_selections = cs;
}
return false;
@@ -890,8 +995,8 @@ x_convert_selection (Lisp_Object selection_symbol,
cs->nofree = true;
cs->property = property;
cs->wait_object = NULL;
- cs->next = converted_selections;
- converted_selections = cs;
+ cs->next = frame->converted_selections;
+ frame->converted_selections = cs;
lisp_data_to_selection_data (dpyinfo, lisp_selection, cs);
return true;
}
@@ -949,6 +1054,12 @@ x_handle_selection_clear (struct selection_input_event *event)
/* Run the `x-lost-selection-functions' abnormal hook. */
CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol);
+ /* If Emacs lost ownership of XdndSelection during drag-and-drop,
+ there is no point in continuing the drag-and-drop session. */
+ if (x_dnd_in_progress
+ && EQ (selection_symbol, QXdndSelection))
+ error ("Lost ownership of XdndSelection");
+
redisplay_preserve_echo_area (20);
}
@@ -958,8 +1069,6 @@ x_handle_selection_event (struct selection_input_event *event)
TRACE0 ("x_handle_selection_event");
if (event->kind != SELECTION_REQUEST_EVENT)
x_handle_selection_clear (event);
- else if (x_queue_selection_requests)
- x_queue_event (event);
else
x_handle_selection_request (event);
}
@@ -1073,7 +1182,7 @@ wait_for_property_change_unwind (void *loc)
static void
wait_for_property_change (struct prop_location *location)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Make sure to do unexpect_property_change if we quit or err. */
record_unwind_protect_ptr (wait_for_property_change_unwind, location);
@@ -1089,8 +1198,13 @@ wait_for_property_change (struct prop_location *location)
intmax_t secs = timeout / 1000;
int nsecs = (timeout % 1000) * 1000000;
TRACE2 (" Waiting %"PRIdMAX" secs, %d nsecs", secs, nsecs);
- wait_reading_process_output (secs, nsecs, 0, false,
- property_change_reply, NULL, 0);
+
+ if (!input_blocked_p ())
+ wait_reading_process_output (secs, nsecs, 0, false,
+ property_change_reply, NULL, 0);
+ else
+ x_wait_for_cell_change (property_change_reply,
+ make_timespec (secs, nsecs));
if (NILP (XCAR (property_change_reply)))
{
@@ -1133,6 +1247,20 @@ x_handle_property_notify (const XPropertyEvent *event)
}
}
+static void
+x_display_selection_waiting_message (struct atimer *timer)
+{
+ Lisp_Object val;
+
+ val = build_string ("Waiting for reply from selection owner...");
+ message3_nolog (val);
+}
+
+static void
+x_cancel_atimer (void *atimer)
+{
+ cancel_atimer (atimer);
+}
/* Variables for communication with x_handle_selection_notify. */
@@ -1158,9 +1286,14 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
Atom type_atom = (CONSP (target_type)
? symbol_to_x_atom (dpyinfo, XCAR (target_type))
: symbol_to_x_atom (dpyinfo, target_type));
+ struct atimer *delayed_message;
+ struct timespec message_interval;
+ specpdl_ref count;
+
+ count = SPECPDL_INDEX ();
if (!FRAME_LIVE_P (f))
- return Qnil;
+ return unbind_to (count, Qnil);
if (! NILP (time_stamp))
CONS_TO_INTEGER (time_stamp, Time, requestor_time);
@@ -1192,25 +1325,53 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
unblock_input ();
+ message_interval = make_timespec (1, 0);
+ delayed_message = start_atimer (ATIMER_RELATIVE, message_interval,
+ x_display_selection_waiting_message,
+ NULL);
+ record_unwind_protect_ptr (x_cancel_atimer, delayed_message);
+
/* This allows quits. Also, don't wait forever. */
intmax_t timeout = max (0, x_selection_timeout);
intmax_t secs = timeout / 1000;
int nsecs = (timeout % 1000) * 1000000;
- TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify", secs);
- wait_reading_process_output (secs, nsecs, 0, false,
- reading_selection_reply, NULL, 0);
- TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply)));
+ TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify.", secs);
+
+ if (input_blocked_p ())
+ TRACE0 (" Input is blocked.");
+ else
+ TRACE1 (" Waiting for %d nsecs in addition.", nsecs);
+
+ /* This function can be called with input blocked inside Xt or GTK
+ timeouts run inside popup menus, so use a function that works
+ when input is blocked. Prefer wait_reading_process_output
+ otherwise, or the toolkit might not get some events.
+ (bug#22214) */
+ if (!input_blocked_p ())
+ wait_reading_process_output (secs, nsecs, 0, false,
+ reading_selection_reply, NULL, 0);
+ else
+ x_wait_for_cell_change (reading_selection_reply,
+ make_timespec (secs, nsecs));
+ TRACE1 (" Got event = %s", (!NILP (XCAR (reading_selection_reply))
+ ? (SYMBOLP (XCAR (reading_selection_reply))
+ ? SSDATA (SYMBOL_NAME (XCAR (reading_selection_reply)))
+ : "YES")
+ : "NO"));
if (NILP (XCAR (reading_selection_reply)))
error ("Timed out waiting for reply from selection owner");
if (EQ (XCAR (reading_selection_reply), Qlambda))
- return Qnil;
+ return unbind_to (count, Qnil);
/* Otherwise, the selection is waiting for us on the requested property. */
- return
- x_get_window_property_as_lisp_data (dpyinfo, requestor_window,
- target_property, target_type,
- selection_atom);
+ return unbind_to (count,
+ x_get_window_property_as_lisp_data (dpyinfo,
+ requestor_window,
+ target_property,
+ target_type,
+ selection_atom,
+ false));
}
/* Subroutines of x_get_window_property_as_lisp_data */
@@ -1461,7 +1622,8 @@ static Lisp_Object
x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
Window window, Atom property,
Lisp_Object target_type,
- Atom selection_atom)
+ Atom selection_atom,
+ bool for_multiple)
{
Atom actual_type;
int actual_format;
@@ -1477,6 +1639,8 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
&actual_type, &actual_format, &actual_size);
if (! data)
{
+ if (for_multiple)
+ return Qnil;
block_input ();
bool there_is_a_selection_owner
= XGetSelectionOwner (display, selection_atom) != 0;
@@ -1499,7 +1663,7 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
}
}
- if (actual_type == dpyinfo->Xatom_INCR)
+ if (!for_multiple && actual_type == dpyinfo->Xatom_INCR)
{
/* That wasn't really the data, just the beginning. */
@@ -1515,11 +1679,14 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
&actual_size);
}
- block_input ();
- TRACE1 (" Delete property %s", XGetAtomName (display, property));
- XDeleteProperty (display, window, property);
- XFlush (display);
- unblock_input ();
+ if (!for_multiple)
+ {
+ block_input ();
+ TRACE1 (" Delete property %s", XGetAtomName (display, property));
+ XDeleteProperty (display, window, property);
+ XFlush (display);
+ unblock_input ();
+ }
/* It's been read. Now convert it to a lisp object in some semi-rational
manner. */
@@ -1855,9 +2022,9 @@ clean_local_selection_data (Lisp_Object obj)
&& INTEGERP (XCAR (obj))
&& FIXNUMP (XCDR (obj)))
{
- if (EQ (XCAR (obj), make_fixnum (0)))
+ if (BASE_EQ (XCAR (obj), make_fixnum (0)))
return XCDR (obj);
- if (EQ (XCAR (obj), make_fixnum (-1)))
+ if (BASE_EQ (XCAR (obj), make_fixnum (-1)))
return make_fixnum (- XFIXNUM (XCDR (obj)));
}
if (VECTORP (obj))
@@ -1888,7 +2055,7 @@ x_handle_selection_notify (const XSelectionEvent *event)
if (event->selection != reading_which_selection)
return;
- TRACE0 ("Received SelectionNotify");
+ TRACE1 ("Received SelectionNotify: %d", (int) event->property);
XSETCAR (reading_selection_reply,
(event->property != 0 ? Qt : Qlambda));
}
@@ -1962,7 +2129,7 @@ On Nextstep, FRAME is unused. */)
CHECK_SYMBOL (selection);
if (NILP (value)) error ("VALUE may not be nil");
- x_own_selection (selection, value, frame);
+ x_own_selection (selection, value, frame, Qnil, 0);
return value;
}
@@ -1990,17 +2157,29 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */)
Lisp_Object time_stamp, Lisp_Object terminal)
{
Lisp_Object val = Qnil;
+ Lisp_Object maybe_alias;
struct frame *f = frame_for_x_selection (terminal);
CHECK_SYMBOL (selection_symbol);
CHECK_SYMBOL (target_type);
+
if (EQ (target_type, QMULTIPLE))
error ("Retrieving MULTIPLE selections is currently unimplemented");
if (!f)
error ("X selection unavailable for this frame");
+ /* Quitting inside this function is okay, so we don't have to use
+ FOR_EACH_TAIL_SAFE. */
+ maybe_alias = Fassq (selection_symbol, Vx_selection_alias_alist);
+
+ if (!NILP (maybe_alias))
+ {
+ selection_symbol = XCDR (maybe_alias);
+ CHECK_SYMBOL (selection_symbol);
+ }
+
val = x_get_local_selection (selection_symbol, target_type, true,
- FRAME_DISPLAY_INFO (f));
+ FRAME_DISPLAY_INFO (f), Qnil, false);
if (NILP (val) && FRAME_LIVE_P (f))
{
@@ -2142,6 +2321,49 @@ On Nextstep, TERMINAL is unused. */)
return (owner ? Qt : Qnil);
}
+DEFUN ("x-get-local-selection", Fx_get_local_selection, Sx_get_local_selection,
+ 0, 2, 0,
+ doc: /* Run selection converters for VALUE, and return the result.
+TARGET is the selection target that is used to find a suitable
+converter. VALUE is a list of 4 values NAME, SELECTION-VALUE,
+TIMESTAMP and FRAME. NAME is the name of the selection that will be
+passed to selection converters, SELECTION-VALUE is the value of the
+selection used by the converter, TIMESTAMP is not meaningful (but must
+be a number that fits in an X timestamp), and FRAME is the frame
+describing the terminal for which the selection converter will be
+run. */)
+ (Lisp_Object value, Lisp_Object target)
+{
+ Time time;
+ Lisp_Object name, timestamp, frame, result;
+
+ CHECK_SYMBOL (target);
+
+ /* Check that VALUE has 4 elements, for x_get_local_selection. */
+ Lisp_Object v = value; CHECK_CONS (v);
+ name = XCAR (v); v = XCDR (v); CHECK_CONS (v);
+ v = XCDR (v); CHECK_CONS (v);
+ timestamp = XCAR (v); v = XCDR (v); CHECK_CONS (v);
+ frame = XCAR (v);
+
+ CHECK_SYMBOL (name);
+ CONS_TO_INTEGER (timestamp, Time, time);
+ check_window_system (decode_live_frame (frame));
+
+ result = x_get_local_selection (name, target, true,
+ NULL, value, false);
+
+ if (CONSP (result) && SYMBOLP (XCAR (result)))
+ {
+ result = XCDR (result);
+
+ if (CONSP (result) && NILP (XCDR (result)))
+ result = XCAR (result);
+ }
+
+ return clean_local_selection_data (result);
+}
+
/* Send clipboard manager a SAVE_TARGETS request with a UTF8_STRING
property (https://www.freedesktop.org/wiki/ClipboardManager/). */
@@ -2389,28 +2611,29 @@ If the value is 0 or the atom is not known, return the empty string. */)
(Lisp_Object value, Lisp_Object frame)
{
struct frame *f = decode_window_system_frame (frame);
- char *name = 0;
- char empty[] = "";
- Lisp_Object ret = Qnil;
Display *dpy = FRAME_X_DISPLAY (f);
+ struct x_display_info *dpyinfo;
Atom atom;
- bool had_errors_p;
+ bool had_errors_p, need_sync;
+ char *name;
+ Lisp_Object ret;
+ dpyinfo = FRAME_DISPLAY_INFO (f);
CONS_TO_INTEGER (value, Atom, atom);
- block_input ();
x_catch_errors (dpy);
- name = atom ? XGetAtomName (dpy, atom) : empty;
- had_errors_p = x_had_errors_p (dpy);
+ name = x_get_atom_name (dpyinfo, atom, &need_sync);
+ had_errors_p = need_sync && x_had_errors_p (dpy);
x_uncatch_errors_after_check ();
- if (!had_errors_p)
- ret = build_string (name);
-
- if (atom && name) XFree (name);
- if (NILP (ret)) ret = empty_unibyte_string;
+ ret = empty_unibyte_string;
- unblock_input ();
+ if (name)
+ {
+ if (!had_errors_p)
+ ret = build_string (name);
+ xfree (name);
+ }
return ret;
}
@@ -2427,13 +2650,13 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
ptrdiff_t i;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
if (SYMBOLP (atom))
x_atom = symbol_to_x_atom (dpyinfo, atom);
else if (STRINGP (atom))
{
block_input ();
- x_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (atom), False);
+ x_atom = x_intern_cached_atom (dpyinfo, SSDATA (atom),
+ false);
unblock_input ();
}
else
@@ -2456,7 +2679,8 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
bool
x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
- struct x_display_info *dpyinfo, struct input_event *bufp)
+ struct x_display_info *dpyinfo, struct input_event *bufp,
+ bool root_window_coords, int root_x, int root_y)
{
Lisp_Object vec;
Lisp_Object frame;
@@ -2466,6 +2690,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
unsigned char *data = (unsigned char *) event->data.b;
int idata[5];
ptrdiff_t i;
+ Window child_return;
for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
if (dpyinfo->x_dnd_atoms[i] == event->message_type) break;
@@ -2497,7 +2722,15 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
event->format,
size));
- x_relative_mouse_position (f, &x, &y);
+ if (!root_window_coords)
+ x_relative_mouse_position (f, &x, &y);
+ else
+ XTranslateCoordinates (dpyinfo->display,
+ dpyinfo->root_window,
+ FRAME_X_WINDOW (f),
+ root_x, root_y,
+ &x, &y, &child_return);
+
bufp->kind = DRAG_N_DROP_EVENT;
bufp->frame_or_window = frame;
bufp->timestamp = CurrentTime;
@@ -2533,7 +2766,11 @@ to send. If a value is a string, it is converted to an Atom and the value of
the Atom is sent. If a value is a cons, it is converted to a 32 bit number
with the high 16 bits from the car and the lower 16 bit from the cdr.
If more values than fits into the event is given, the excessive values
-are ignored. */)
+are ignored.
+
+Wait for the event to be sent and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored. */)
(Lisp_Object display, Lisp_Object dest, Lisp_Object from,
Lisp_Object message_type, Lisp_Object format, Lisp_Object values)
{
@@ -2549,7 +2786,7 @@ are ignored. */)
return Qnil;
}
-void
+static void
x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
Atom message_type, Lisp_Object format, Lisp_Object values)
{
@@ -2614,7 +2851,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
the destination window. But if we are sending to the root window,
there is no such client. Then we set the event mask to 0xffffff. The
event then goes to clients selecting for events on the root window. */
- x_catch_errors (dpyinfo->display);
+ x_catch_errors_for_lisp (dpyinfo);
{
bool propagate = !to_root;
long mask = to_root ? 0xffffff : 0;
@@ -2622,12 +2859,32 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
XFlush (dpyinfo->display);
}
- x_uncatch_errors ();
+ x_check_errors_for_lisp (dpyinfo, "Failed to send client event: %s");
+ x_uncatch_errors_for_lisp (dpyinfo);
unblock_input ();
}
+/* Return the timestamp where ownership of SELECTION was asserted, or
+ nil if no local selection is present. */
+
+Lisp_Object
+x_timestamp_for_selection (struct x_display_info *dpyinfo,
+ Lisp_Object selection)
+{
+ Lisp_Object value, local_value;
+
+ local_value = LOCAL_SELECTION (selection, dpyinfo);
+
+ if (NILP (local_value))
+ return Qnil;
+
+ value = XCAR (XCDR (XCDR (local_value)));
+
+ return value;
+}
+
static void syms_of_xselect_for_pdumper (void);
void
@@ -2642,6 +2899,7 @@ syms_of_xselect (void)
defsubr (&Sx_get_atom_name);
defsubr (&Sx_send_client_message);
defsubr (&Sx_register_dnd_atom);
+ defsubr (&Sx_get_local_selection);
reading_selection_reply = Fcons (Qnil, Qnil);
staticpro (&reading_selection_reply);
@@ -2652,11 +2910,18 @@ syms_of_xselect (void)
DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
doc: /* An alist associating X Windows selection-types with functions.
These functions are called to convert the selection, with three args:
-the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');
-a desired type to which the selection should be converted;
-and the local selection value (whatever was given to
+the name of the selection (typically `PRIMARY', `SECONDARY', or
+`CLIPBOARD'); a desired type to which the selection should be
+converted; and the local selection value (whatever was given to
`x-own-selection-internal').
+On X Windows, the function can also be a cons of (PREDICATE
+. FUNCTION), where PREDICATE determines whether or not the selection
+type will appear in the list of selection types available to other
+programs, and FUNCTION is the function which is actually called.
+PREDICATE is called with the same arguments as FUNCTION, and should
+return a non-nil value if the data type is to appear in that list.
+
The function should return the value to send to the X server
\(typically a string). A return value of nil
means that the conversion could not be done.
@@ -2702,6 +2967,23 @@ A value of 0 means wait as long as necessary. This is initialized from the
\"*selectionTimeout\" resource. */);
x_selection_timeout = 0;
+ DEFVAR_LISP ("x-treat-local-requests-remotely", Vx_treat_local_requests_remotely,
+ doc: /* Whether to treat local selection requests as remote ones.
+
+If non-nil, selection converters for string types (`STRING',
+`UTF8_STRING', `COMPOUND_TEXT', etc) will encode the strings, even
+when Emacs itself is converting the selection. */);
+ Vx_treat_local_requests_remotely = Qnil;
+
+ DEFVAR_LISP ("x-selection-alias-alist", Vx_selection_alias_alist,
+ doc: /* List of selections to alias to another.
+It should be an alist of a selection name to another. When a
+selection request arrives for the first selection, Emacs will respond
+as if the request was meant for the other.
+
+Note that this does not affect setting or owning selections. */);
+ Vx_selection_alias_alist = Qnil;
+
/* QPRIMARY is defined in keyboard.c. */
DEFSYM (QSECONDARY, "SECONDARY");
DEFSYM (QSTRING, "STRING");
@@ -2723,10 +3005,16 @@ A value of 0 means wait as long as necessary. This is initialized from the
DEFSYM (QCLIPBOARD_MANAGER, "CLIPBOARD_MANAGER");
DEFSYM (QSAVE_TARGETS, "SAVE_TARGETS");
DEFSYM (QNULL, "NULL");
+ DEFSYM (QXdndDirectSave0, "XdndDirectSave0");
+ DEFSYM (QXdndActionDirectSave, "XdndActionDirectSave");
+ DEFSYM (Qtext_plain, "text/plain");
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (Qx_lost_selection_functions, "x-lost-selection-functions");
DEFSYM (Qx_sent_selection_functions, "x-sent-selection-functions");
+ DEFSYM (QXmTRANSFER_SUCCESS, "XmTRANSFER_SUCCESS");
+ DEFSYM (QXmTRANSFER_FAILURE, "XmTRANSFER_FAILURE");
+
pdumper_do_now_and_after_load (syms_of_xselect_for_pdumper);
}
@@ -2738,6 +3026,4 @@ syms_of_xselect_for_pdumper (void)
property_change_wait_list = 0;
prop_location_identifier = 0;
property_change_reply = Fcons (Qnil, Qnil);
- converted_selections = NULL;
- conversion_fail_tag = None;
}
diff --git a/src/xsettings.c b/src/xsettings.c
index 71d02e61525..c29a844e0a8 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -206,6 +206,11 @@ struct xsettings
unsigned seen;
};
+#ifdef HAVE_PGTK
+/* The cairo font_options as obtained using gsettings. */
+static cairo_font_options_t *font_options;
+#endif
+
#ifdef HAVE_GSETTINGS
#define GSETTINGS_SCHEMA "org.gnome.desktop.interface"
#define GSETTINGS_TOOL_BAR_STYLE "toolbar-style"
@@ -215,11 +220,162 @@ struct xsettings
#define GSETTINGS_FONT_NAME "font-name"
#endif
+#ifdef HAVE_PGTK
+#define GSETTINGS_FONT_ANTIALIASING "font-antialiasing"
+#define GSETTINGS_FONT_RGBA_ORDER "font-rgba-order"
+#define GSETTINGS_FONT_HINTING "font-hinting"
+#endif
/* The single GSettings instance, or NULL if not connected to GSettings. */
static GSettings *gsettings_client;
+#if defined HAVE_PGTK && defined HAVE_GSETTINGS
+
+static bool
+xg_settings_key_valid_p (GSettings *settings, const char *key)
+{
+#ifdef GLIB_VERSION_2_32
+ GSettingsSchema *schema;
+ bool rc;
+
+ g_object_get (G_OBJECT (settings),
+ "settings-schema", &schema,
+ NULL);
+
+ if (!schema)
+ return false;
+
+ rc = g_settings_schema_has_key (schema, key);
+ g_settings_schema_unref (schema);
+
+ return rc;
+#else
+ return false;
+#endif
+}
+
+#endif
+
+#ifdef HAVE_PGTK
+/* Store an event for re-rendering of the fonts. */
+static void
+store_font_options_changed (void)
+{
+ if (dpyinfo_valid (first_dpyinfo))
+ store_config_changed_event (Qfont_render,
+ XCAR (first_dpyinfo->name_list_element));
+}
+
+/* Apply changes in the hinting system setting. */
+static void
+apply_gsettings_font_hinting (GSettings *settings)
+{
+ GVariant *val;
+ const char *hinting;
+
+ if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_HINTING))
+ return;
+
+ val = g_settings_get_value (settings, GSETTINGS_FONT_HINTING);
+
+ if (val)
+ {
+ g_variant_ref_sink (val);
+
+ if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+ {
+ hinting = g_variant_get_string (val, NULL);
+
+ if (!strcmp (hinting, "full"))
+ cairo_font_options_set_hint_style (font_options,
+ CAIRO_HINT_STYLE_FULL);
+ else if (!strcmp (hinting, "medium"))
+ cairo_font_options_set_hint_style (font_options,
+ CAIRO_HINT_STYLE_MEDIUM);
+ else if (!strcmp (hinting, "slight"))
+ cairo_font_options_set_hint_style (font_options,
+ CAIRO_HINT_STYLE_SLIGHT);
+ else if (!strcmp (hinting, "none"))
+ cairo_font_options_set_hint_style (font_options,
+ CAIRO_HINT_STYLE_NONE);
+ }
+ g_variant_unref (val);
+ }
+}
+
+/* Apply changes in the antialiasing system setting. */
+static void
+apply_gsettings_font_antialias (GSettings *settings)
+{
+ GVariant *val;
+ const char *antialias;
+
+ if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_ANTIALIASING))
+ return;
+
+ val = g_settings_get_value (settings, GSETTINGS_FONT_ANTIALIASING);
+
+ if (val)
+ {
+ g_variant_ref_sink (val);
+ if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+ {
+ antialias = g_variant_get_string (val, NULL);
+
+ if (!strcmp (antialias, "none"))
+ cairo_font_options_set_antialias (font_options,
+ CAIRO_ANTIALIAS_NONE);
+ else if (!strcmp (antialias, "grayscale"))
+ cairo_font_options_set_antialias (font_options,
+ CAIRO_ANTIALIAS_GRAY);
+ else if (!strcmp (antialias, "rgba"))
+ cairo_font_options_set_antialias (font_options,
+ CAIRO_ANTIALIAS_SUBPIXEL);
+ }
+ g_variant_unref (val);
+ }
+}
+
+/* Apply the settings for the rgb element ordering. */
+static void
+apply_gsettings_font_rgba_order (GSettings *settings)
+{
+ GVariant *val;
+ const char *rgba_order;
+
+ if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_RGBA_ORDER))
+ return;
+
+ val = g_settings_get_value (settings,
+ GSETTINGS_FONT_RGBA_ORDER);
+
+ if (val)
+ {
+ g_variant_ref_sink (val);
+
+ if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+ {
+ rgba_order = g_variant_get_string (val, NULL);
+
+ if (!strcmp (rgba_order, "rgb"))
+ cairo_font_options_set_subpixel_order (font_options,
+ CAIRO_SUBPIXEL_ORDER_RGB);
+ else if (!strcmp (rgba_order, "bgr"))
+ cairo_font_options_set_subpixel_order (font_options,
+ CAIRO_SUBPIXEL_ORDER_BGR);
+ else if (!strcmp (rgba_order, "vrgb"))
+ cairo_font_options_set_subpixel_order (font_options,
+ CAIRO_SUBPIXEL_ORDER_VRGB);
+ else if (!strcmp (rgba_order, "vbgr"))
+ cairo_font_options_set_subpixel_order (font_options,
+ CAIRO_SUBPIXEL_ORDER_VBGR);
+ }
+ g_variant_unref (val);
+ }
+}
+#endif /* HAVE_PGTK */
+
/* Callback called when something changed in GSettings. */
static void
@@ -273,6 +429,23 @@ something_changed_gsettingsCB (GSettings *settings,
}
}
#endif /* USE_CAIRO || HAVE_XFT */
+#ifdef HAVE_PGTK
+ else if (!strcmp (key, GSETTINGS_FONT_ANTIALIASING))
+ {
+ apply_gsettings_font_antialias (settings);
+ store_font_options_changed ();
+ }
+ else if (!strcmp (key, GSETTINGS_FONT_HINTING))
+ {
+ apply_gsettings_font_hinting (settings);
+ store_font_options_changed ();
+ }
+ else if (!strcmp (key, GSETTINGS_FONT_RGBA_ORDER))
+ {
+ apply_gsettings_font_rgba_order (settings);
+ store_font_options_changed ();
+ }
+#endif /* HAVE_PGTK */
}
#endif /* HAVE_GSETTINGS */
@@ -900,6 +1073,16 @@ init_gsettings (void)
dupstring (&current_font, g_variant_get_string (val, NULL));
g_variant_unref (val);
}
+
+ /* Only use the gsettings font entries for the Cairo backend
+ running on PGTK. */
+#ifdef HAVE_PGTK
+ font_options = cairo_font_options_create ();
+ apply_gsettings_font_antialias (gsettings_client);
+ apply_gsettings_font_hinting (gsettings_client);
+ apply_gsettings_font_rgba_order (gsettings_client);
+#endif /* HAVE_PGTK */
+
#endif /* USE_CAIRO || HAVE_XFT */
#endif /* HAVE_GSETTINGS */
@@ -1021,6 +1204,21 @@ xsettings_get_system_normal_font (void)
}
#endif
+#ifdef HAVE_PGTK
+/* Return the cairo font options, updated from the gsettings font
+ config entries. The caller should call cairo_font_options_destroy
+ on the result. */
+cairo_font_options_t *
+xsettings_get_font_options (void)
+{
+ if (font_options != NULL)
+ return cairo_font_options_copy (font_options);
+ else
+ /* GSettings is not configured. */
+ return cairo_font_options_create ();
+}
+#endif
+
DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font,
Sfont_get_system_normal_font,
0, 0, 0,
@@ -1073,6 +1271,10 @@ syms_of_xsettings (void)
gconf_client = NULL;
PDUMPER_IGNORE (gconf_client);
#endif
+#ifdef HAVE_PGTK
+ font_options = NULL;
+ PDUMPER_IGNORE (font_options);
+#endif
DEFSYM (Qmonospace_font_name, "monospace-font-name");
DEFSYM (Qfont_name, "font-name");
diff --git a/src/xsettings.h b/src/xsettings.h
index 266526df101..5e5df37062b 100644
--- a/src/xsettings.h
+++ b/src/xsettings.h
@@ -21,15 +21,16 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define XSETTINGS_H
#ifndef HAVE_PGTK
+#include "dispextern.h"
#include <X11/Xlib.h>
+#else
+#include <cairo.h>
#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
@@ -42,5 +43,8 @@ extern const char *xsettings_get_system_font (void);
extern const char *xsettings_get_system_normal_font (void);
#endif
+#ifdef HAVE_PGTK
+extern cairo_font_options_t *xsettings_get_font_options (void);
+#endif
#endif /* XSETTINGS_H */
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 199e3ded3dd..7015a8eb633 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -522,7 +522,7 @@ Do not call this function yourself. */)
{
/* We should not do user interaction here, but it is not easy to
prevent. Fix this in next version. */
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
#if false
/* This will not be reached, but we want kill-emacs-hook to be run. */
diff --git a/src/xterm.c b/src/xterm.c
index b284fdd3123..ac4e210786e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20,9 +20,547 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* New display code by Gerd Moellmann <gerd@gnu.org>. */
/* Xt features made by Fred Pierresteguy. */
+/* X window system support for GNU Emacs
+
+ This file is part of the X window system support for GNU Emacs. It
+ contains subroutines comprising the redisplay interface, setting up
+ scroll bars and widgets, and handling input.
+
+ Some of what is explained below also applies to the other window
+ systems that Emacs supports, to varying degrees. YMMV.
+
+ INPUT
+
+ Emacs handles input by running pselect in a loop, which returns
+ whenever there is input available on the connection to the X
+ server. On some systems, Emacs also arranges for any new input on
+ that connection to send an asynchronous signal. Whenever pselect
+ returns, or such a signal is received and input is not blocked,
+ XTread_socket is called and translates X11 events read by Xlib into
+ struct input_events, which are then stored in the keyboard buffer,
+ to be processed and acted upon at some later time. The function
+ handle_one_xevent is responsible for handling core events after
+ they are filtered, and filtering X Input Extension events. It also
+ performs actions on some special events, such as updating the
+ dimensions of a frame after a ConfigureNotify is sent by the X
+ server to inform us that it changed.
+
+ Before such events are translated, an Emacs build with
+ internationalization enabled (the default since X11R6) will filter
+ events through an X Input Method (XIM) or GTK, which might decide
+ to intercept the event and send a different one in its place, for
+ reasons such as enabling the user to insert international
+ characters that aren't on his keyboard by typing a sequence of
+ characters which are. See the function x_filter_event and its
+ callers for more details.
+
+ Events that cause Emacs to quit are treated specially by the code
+ that stores them in the keyboard buffer and generally cause an
+ immediate interrupt. Such an interrupt can lead to a longjmp from
+ the code that stored the keyboard event, which isn't safe inside
+ XTread_socket. To avoid this problem, XTread_socket is provided a
+ special event buffer named hold_quit. When a quit event is
+ encountered, it is stored inside this special buffer, which will
+ cause the keyboard code that called XTread_socket to store it at a
+ later time when it is safe to do so.
+
+ handle_one_xevent will generally have to determine which frame an
+ event should be attributed to. This is not easy, because events
+ can come from multiple X windows, and a frame can also have
+ multiple windows. handle_one_xevent usually calls the function
+ x_any_window_to_frame, which searches for a frame by toplevel
+ window and widget windows. There are also some other functions for
+ searching by specific types of window, such as
+ x_top_window_to_frame (which only searches for frames by toplevel
+ window), and x_menubar_window_to_frame (which will only search
+ through frame menu bars).
+
+ INPUT FOCUS
+
+ Under X, the window where keyboard input is sent is not always
+ explicitly defined. When there is a focus window, it receives what
+ is referred to as "explicit focus", but when there is none, it
+ receives "implicit focus" whenever the pointer enters it, and loses
+ that focus when the pointer leaves. When the toplevel window of a
+ frame receives an explicit focus event (FocusIn or FocusOut), we
+ treat that frame as having the current input focus, but when there
+ is no focus window, we treat each frame as having the input focus
+ whenever the pointer enters it, and undo that treatment when the
+ pointer leaves it. See the callers of x_detect_focus_change for
+ more details.
+
+ REDISPLAY
+
+ The redisplay engine communicates with X through the "redisplay
+ interface", which is a structure containing pointers to functions
+ which output graphics to a frame.
+
+ Some of the functions included in the redisplay interface include
+ `x_clear_frame_area', which is called by the display engine when it
+ determines that a part of the display has to be cleared,
+ x_draw_window_cursor, which is called to perform the calculations
+ necessary to display the cursor glyph with a special "highlight"
+ (more on that later) and to set the input method spot location.
+
+ Most of the actual display is performed by the function
+ `x_draw_glyph_string', also included in the redisplay interface.
+ It takes a list of glyphs of the same type and face, computes the
+ correct graphics context for the string through the function
+ `x_set_glyph_string_gc', and draws whichever glyphs it might
+ contain, along with decorations such as the box face, underline and
+ overline. That list is referred to as a "glyph string".
+
+ GRAPHICS CONTEXTS
+
+ A graphics context ("GC") is an X server-side object which contains
+ drawing attributes such as fill style, stipple, and foreground and
+ background pixel values.
+
+ Usually, one graphics context is computed for each face when it is
+ about to be displayed for the first time, and this graphics context
+ is the one which is used for future X drawing operations in a glyph
+ string with that face. (See `prepare_face_for_display' in
+ xfaces.c).
+
+ However, when drawing glyph strings for special display elements
+ such as the cursor, or mouse sensitive text, different GCs may be
+ used. When displaying the cursor, for example, the frame's cursor
+ graphics context is used for the common case where the cursor is
+ drawn with the default font, and the colors of the string's face
+ are the same as the default face. In all other cases, a temporary
+ graphics context is created with the foreground and background
+ colors of the cursor face adjusted to ensure that the cursor can be
+ distinguished from its surroundings and that the text inside the
+ cursor stays visible.
+
+ Various graphics contexts are also calculated when the frame is
+ created by the function `x_make_gcs' in xfns.c, and are adjusted
+ whenever the foreground or background colors change. The "normal"
+ graphics context is used for operations performed without a face,
+ and always corresponds to the foreground and background colors of
+ the frame's default face, the "reverse" graphics context is used to
+ draw text in inverse video, and the cursor graphics context is used
+ to display the cursor in the most common case.
+
+ N.B. that some of the other window systems supported by use an
+ emulation of graphics contexts to hold the foreground and
+ background colors used in a glyph string, while the some others
+ ports compute those colors directly based on the colors of the
+ string's face and its highlight, but only on X are graphics
+ contexts a data structure inherent to the window system.
+
+ COLOR ALLOCATION
+
+ In (and only in) X, pixel values for colors are not guaranteed to
+ correspond to their individual components. The rules for
+ converting colors into pixel values are defined by the visual class
+ of each display opened by Emacs. When a display is opened, a
+ suitable visual is obtained from the X server, and a colormap is
+ created based on that visual, which is then used for each frame
+ created.
+
+ The colormap is then used by the X server to convert pixel values
+ from a frame created by Emacs into actual colors which are output
+ onto the physical display.
+
+ When the visual class is TrueColor, the colormap will be indexed
+ based on the red, green, and blue (RGB) components of the pixel
+ values, and the colormap will be statically allocated so as to
+ contain linear ramps for each component. As such, most of the
+ color allocation described below is bypassed, and the pixel values
+ are computed directly from the color.
+
+ Otherwise, each time Emacs wants a pixel value that corresponds to
+ a color, Emacs has to ask the X server to obtain the pixel value
+ that corresponds to a "color cell" containing the color (or a close
+ approximation) from the colormap. Exactly how this is accomplished
+ further depends on the visual class, since some visuals have
+ immutable colormaps which contain color cells with pre-defined
+ values, while others have colormaps where the color cells are
+ dynamically allocated by individual X clients.
+
+ With visuals that have a visual class of StaticColor and StaticGray
+ (where the former is the case), the X server is asked to procure
+ the pixel value of a color cell that contains the closest
+ approximation of the color which Emacs wants. On the other hand,
+ when the visual class is DirectColor, PseudoColor, or GrayScale,
+ where color cells are dynamically allocated by clients, Emacs asks
+ the X server to allocate a color cell containing the desired color,
+ and uses its pixel value.
+
+ (If the color already exists, the X server returns an existing color
+ cell, but increases its reference count, so it still has to be
+ freed afterwards.)
+
+ Otherwise, if no color could be allocated (due to the colormap
+ being full), Emacs looks for a color cell inside the colormap
+ closest to the desired color, and uses its pixel value instead.
+
+ Since the capacity of a colormap is finite, X clients have to take
+ special precautions in order to not allocate too many color cells
+ that are never used. Emacs allocates its color cells when a face
+ is being realized or when a frame changes its foreground and
+ background colors, and releases them alongside the face or frame.
+ See calls to `unload_color' and `load_color' in xterm.c, xfaces.c
+ and xfns.c for more details.
+
+ The driving logic behind color allocation is in
+ `x_alloc_nearest_color_1', while the optimization for TrueColor
+ visuals is in `x_make_truecolor_pixel'. Also see `x_query_colors`,
+ which is used to determine the color values for given pixel
+ values.
+
+ In other window systems supported by Emacs, color allocation is
+ handled by the window system itself, to whom Emacs simply passes 24
+ (or 32-bit) RGB values.
+
+ OPTIONAL FEATURES
+
+ While X servers and client libraries tend to come with many
+ extensions to the core X11R6 protocol, dependencies on anything
+ other than the core X11R6 protocol and Xlib should be optional at
+ both compile-time and runtime. Emacs should also not crash
+ regardless of what combination of X server and client-side features
+ are present. For example, if you are developing a feature that
+ will need Xfixes, then add a test in configure.ac for the library
+ at compile-time which defines `HAVE_XFIXES', like this:
+
+ ### Use Xfixes (-lXfixes) if available
+ HAVE_XFIXES=no
+ if test "${HAVE_X11}" = "yes"; then
+ XFIXES_REQUIRED=4.0.0
+ XFIXES_MODULES="xfixes >= $XFIXES_REQUIRED"
+ EMACS_CHECK_MODULES([XFIXES], [$XFIXES_MODULES])
+ if test $HAVE_XFIXES = no; then
+ # Test old way in case pkg-config doesn't have it (older machines).
+ AC_CHECK_HEADER([X11/extensions/Xfixes.h],
+ [AC_CHECK_LIB([Xfixes], [XFixesHideCursor], [HAVE_XFIXES=yes])])
+ if test $HAVE_XFIXES = yes; then
+ XFIXES_LIBS=-lXfixes
+ fi
+ fi
+ if test $HAVE_XFIXES = yes; then
+ AC_DEFINE([HAVE_XFIXES], [1],
+ [Define to 1 if you have the Xfixes extension.])
+ fi
+ fi
+ AC_SUBST([XFIXES_CFLAGS])
+ AC_SUBST([XFIXES_LIBS])
+
+ Then, make sure to adjust CFLAGS and LIBES in src/Makefile.in and
+ add the new XFIXES_CFLAGS and XFIXES_LIBS variables to
+ msdos/sed1v2.inp. (The latter has to be adjusted for any new
+ variables that are included in CFLAGS and LIBES even if the
+ libraries are not used by the MS-DOS port.)
+
+ Finally, add some fields in `struct x_display_info' which specify
+ the major and minor versions of the extension, and whether or not to
+ support them. They (and their accessors) should be protected by the
+ `HAVE_XFIXES' preprocessor conditional. Then, these fields should
+ be set in `x_term_init', and all Xfixes calls must be protected by
+ not only the preprocessor conditional, but also by checks against
+ those variables.
+
+ X TOOLKIT SUPPORT
+
+ Emacs supports being built with many different toolkits (and also no
+ toolkit at all), which provide decorations such as menu bars and
+ scroll bars, along with handy features like file panels, dialog
+ boxes, font panels, and popup menus. Those configurations can
+ roughly be classified as belonging to one of three categories:
+
+ - Using no toolkit at all.
+ - Using the X Toolkit Intrinsics (Xt).
+ - Using GTK.
+
+ The no toolkit configuration is the simplest: no toolkit widgets are
+ used, Emacs uses its own implementation of scroll bars, and the
+ XMenu library that came with X11R2 and earlier versions of X is used
+ for popup menus. There is also no complicated window structure to
+ speak of.
+
+ The Xt configurations come in either the Lucid or Motif flavors.
+ The former utilizes Emacs's own Xt-based Lucid widget library for
+ menus, and Xaw (or derivatives such as neXTaw and Xaw3d) for dialog
+ boxes and, optionally, scroll bars. It does not support file
+ panels. The latter uses either Motif or LessTif for menu bars,
+ popup menus, dialogs and file panels.
+
+ The GTK configurations come in the GTK+ 2 or GTK 3 configurations,
+ where the toolkit provides all the aforementioned decorations and
+ features. They work mostly the same, though GTK 3 has various small
+ annoyances that complicate maintenance.
+
+ All of those configurations have various special technicalities
+ about event handling and the layout of windows inside a frame that
+ must be kept in mind when writing X code which is run on all of
+ them.
+
+ The no toolkit configuration has no noteworthy aspects about the
+ layout of windows inside a frame, since each frame has only one
+ associated window aside from scroll bars. However, in the Xt
+ configurations, every widget is a separate window, and there are
+ quite a few widgets. The "outer widget", a widget of class
+ ApplicationShell, is the top-level window of a frame. Its window is
+ accessed via the macro `FRAME_OUTER_WINDOW'. The "edit widget", a
+ widget class of EmacsFrame, is a child of the outer widget that
+ controls the size of a frame as known to Emacs, and is the widget
+ that Emacs draws to during display operations. The "menu bar
+ widget" is the widget holding the menu bar.
+
+ Special care must be taken when performing operations on a frame.
+ Properties that are used by the window manager, for example, must be
+ set on the outer widget. Drawing, on the other hand, must be done
+ to the edit widget, and button press events on the menu bar widget
+ must be redirected and not sent to Xt until the Lisp code is run to
+ update the menu bar.
+
+ The EmacsFrame widget is specific to Emacs and is implemented in
+ widget.c. See that file for more details.
+
+ In the GTK configurations, GTK widgets do not necessarily correspond
+ to X windows, since the toolkit might decide to keep only a
+ client-side record of the widgets for performance reasons.
+
+ Because the GtkFixed widget that holds the "edit area" might not
+ correspond to an X window, drawing operations may be directly
+ performed on the outer window, with special care taken to not
+ overwrite the surrounding GTK widgets. This also means that the
+ only important window for most purposes is the outer window, which
+ on GTK builds can usually be accessed using the macro
+ `FRAME_X_WINDOW'.
+
+ How `handle_one_xevent' is called also depends on the configuration.
+ Without a toolkit, Emacs performs all event processing by itself,
+ running XPending and XNextEvent in a loop whenever there is input,
+ passing the event to `handle_one_xevent'.
+
+ When using Xt, the same is performed, but `handle_one_xevent' may
+ also decide to call XtDispatchEvent on an event after Emacs finishes
+ processing it.
+
+ When using GTK, however, `handle_one_xevent' is called from an event
+ filter installed on the GTK event loop. Unless the event filter
+ elects to drop the event, it will be passed to GTK right after
+ leaving the event filter.
+
+ Fortunately, `handle_one_xevent' is provided a `*finish' parameter
+ that abstracts away all these details. If it is `X_EVENT_DROP',
+ then the event will not be dispatched to Xt or utilized by GTK.
+ Code inside `handle_one_xevent' should thus avoid making assumptions
+ about the event dispatch mechanism and use that parameter
+ instead.
+
+ FRAME RESIZING
+
+ In the following explanations "frame size" refers to the "native
+ size" of a frame as reported by the (frame.h) macros
+ FRAME_PIXEL_WIDTH and FRAME_PIXEL_HEIGHT. These specify the size of
+ a frame as the values passed to/received from a toolkit and the
+ window manager. The "text size" Emacs Lisp code uses in functions
+ like 'set-frame-size' or sees in the ‘width’ and 'height' frame
+ parameters is only loosely related to the native size. The
+ necessary translations are provided by the macros
+ FRAME_TEXT_TO_PIXEL_WIDTH and FRAME_TEXT_TO_PIXEL_HEIGHT as well as
+ FRAME_PIXEL_TO_TEXT_WIDTH and FRAME_PIXEL_TO_TEXT_HEIGHT (in
+ frame.h).
+
+ Lisp functions may ask for resizing a frame either explicitly, using
+ one of the interfaces provided for that purpose like, for example,
+ 'set-frame-size' or changing the 'height' or 'width' parameter of
+ that frame, or implicitly, for example, by turning off/on or
+ changing the width of fringes or scroll bars for that frame. Any
+ such request passes through the routine 'adjust_frame_size' (in
+ frame.c) which decides, among others, whether the native frame size
+ would really change and whether it is allowed to change it at that
+ moment. Only if 'adjust_frame_size' decides that the corresponding
+ terminal's 'set_window_size_hook' may be run, it will dispatch
+ execution to the appropriate function which, for X builds, is
+ 'x_set_window_size' in this file.
+
+ For GTK builds, 'x_set_window_size' calls 'xg_frame_set_char_size'
+ in gtkutil.c if the frame has an edit widget and
+ 'x_set_window_size_1' in this file otherwise. For non-GTK builds,
+ 'x_set_window_size' always calls 'x_set_window_size_1' directly.
+
+ 'xg_frame_set_char_size' calls the GTK function 'gtk_window_resize'
+ for the frame's outer widget; x_set_window_size_1 calls the Xlib
+ function 'XResizeWindow' instead. In either case, if Emacs thinks
+ that the frame is visible, it will wait for a ConfigureNotify event
+ (see below) to occur within a timeout of 'x-wait-for-event-timeout'
+ (the default is 0.1 seconds). If Emacs thinks that the frame is not
+ visible, it calls 'adjust_frame_size' to run 'resize_frame_windows'
+ (see below) and hopes for the best.
+
+ Note that if Emacs receives a ConfigureEvent in response to an
+ earlier resize request, the sizes specified by that event are not
+ necessarily the sizes Emacs requested. Window manager and toolkit
+ may override any of the requested sizes for their own reasons.
+
+ On X, size notifications are received as ConfigureNotify events.
+ The expected reaction to such an event on the Emacs side is to
+ resize all Emacs windows that are on the frame referred to by the
+ event. Since resizing Emacs windows and redisplaying their buffers
+ is a costly operation, Emacs may collapse several subsequent
+ ConfigureNotify events into one to avoid that Emacs falls behind in
+ user interactions like resizing a frame by dragging one of its
+ borders with the mouse.
+
+ Each ConfigureEvent event specifies a window, a width and a height.
+ The event loop uses 'x_top_window_to_frame' to associate the window
+ with its frame. Once the frame has been identified, on GTK the
+ event is dispatched to 'xg_frame_resized'. On Motif/Lucid
+ 'x_window' has installed 'EmacsFrameResize' as the routine that
+ handles resize events. In either case, these routines end up
+ calling the function 'change_frame_size' in dispnew.c. On
+ non-toolkit builds the effect is to call 'change_frame_size'
+ directly from the event loop. In either case, the value true is
+ passed as the DELAY argument.
+
+ 'change_frame_size' is the central function to decide whether it is
+ safe to process a resize request immediately or it has to be delayed
+ (usually because its DELAY argument is true). Since resizing a
+ frame's windows may run arbitrary Lisp code, Emacs cannot generally
+ process resize requests during redisplay and therefore has to queue
+ them. If processing the event must be delayed, the new sizes (that
+ is, the ones requested by the ConfigureEvent) are stored in the
+ new_width and new_height slots of the respective frame structure,
+ possibly replacing ones that have been stored there upon the receipt
+ of a preceding ConfigureEvent.
+
+ Delayed size changes are applied eventually upon calls of the
+ function 'do_pending_window_change' (in dispnew.c) which is called
+ by the redisplay code at suitable spots where it's safe to change
+ sizes. 'do_pending_window_change' calls 'change_frame_size' with
+ its DELAY argument false in the hope that it is now safe to call the
+ function 'resize_frame_windows' (in window.c) which is in charge of
+ adjusting the sizes of all Emacs windows on the frame accordingly.
+ Note that if 'resize_frame_windows' decides that the windows of a
+ frame do not fit into the constraints set up by the new frame sizes,
+ it will resize the windows to some minimum sizes with the effect
+ that parts of the frame at the right and bottom will appear clipped
+ off.
+
+ In addition to explicitly passing width and height values in
+ functions like 'gtk_window_resize' or 'XResizeWindow', Emacs also
+ sets window manager size hints - a more implicit form of asking for
+ the size Emacs would like its frames to assume. Some of these hints
+ only restate the size and the position explicitly requested for a
+ frame. Another hint specifies the increments in which the window
+ manager should resize a frame to - either set to the default
+ character size of a frame or to one pixel for a non-nil value of
+ 'frame-resize-pixelwise'. See the function 'x_wm_set_size_hint' -
+ in gtkutil.c for GTK and in this file for other builds - for the
+ details.
+
+ We have not discussed here a number of special issues like, for
+ example, how to handle size requests and notifications for maximized
+ and fullscreen frames or how to resize child frames. Some of these
+ require special treatment depending on the desktop or window manager
+ used.
+
+ One thing that might come handy when investigating problems wrt
+ resizing frames is the variable 'frame-size-history'. Setting this
+ to a non-nil value, will cause Emacs to start recording frame size
+ adjustments, usually specified by the function that asked for an
+ adjustment, a sizes part that records the old and new values of the
+ frame's width and height and maybe some additional information. The
+ internal function `frame--size-history' can then be used to display
+ the value of this variable in a more readable form.
+
+ FRAME RESIZE SYNCHRONIZATION
+
+ The X window system operates asynchronously. That is to say, the
+ window manager and X server might think a window has been resized
+ before Emacs has a chance to process the ConfigureNotify event that
+ was sent.
+
+ When a compositing manager is present, and the X server and Emacs
+ both support the X synchronization extension, the semi-standard
+ frame synchronization protocol can be used to notify the compositing
+ manager of when Emacs has actually finished redisplaying the
+ contents of a frame after a resize. The compositing manager will
+ customarily then postpone displaying the contents of the frame until
+ the redisplay is complete.
+
+ Emacs announces support for this protocol by creating an X
+ server-side counter object, and setting it as the
+ `_NET_WM_SYNC_REQUEST_COUNTER' property of the frame's top-level
+ window. The window manager then initiates the synchronized resize
+ process by sending Emacs a ClientMessage event before the
+ ConfigureNotify event where:
+
+ type = ClientMessage
+ window = the respective client window
+ message_type = WM_PROTOCOLS
+ format = 32
+ data.l[0] = _NET_WM_SYNC_REQUEST
+ data.l[1] = timestamp
+ data.l[2] = low 32 bits of a provided frame counter value
+ data.l[3] = high 32 bits of a provided frame counter value
+ data.l[4] = 1 if the extended frame counter should be updated,
+ otherwise 0
+
+ Upon receiving such an event, Emacs constructs and saves a counter
+ value from the provided low and high 32 bits. Then, when the
+ display engine tells us that a frame has been completely updated
+ (presumably because of a redisplay caused by a ConfigureNotify
+ event), we set the counter to the saved value, telling the
+ compositing manager that the contents of the window now accurately
+ reflect the new size. The compositing manager will then display the
+ contents of the window, and the window manager might also postpone
+ updating the window decorations until this moment.
+
+ DRAG AND DROP
+
+ Drag and drop in Emacs is implemented in two ways, depending on
+ which side initiated the drag-and-drop operation. When another X
+ client initiates a drag, and the user drops something on Emacs, a
+ `drag-n-drop-event' is sent with the contents of the ClientMessage,
+ and further processing (i.e. retrieving selection contents and
+ replying to the initiating client) is performed from Lisp inside
+ `x-dnd.el'.
+
+ However, dragging contents from Emacs is implemented almost entirely
+ in C. X Windows has several competing drag-and-drop protocols, of
+ which Emacs supports two on the C level: the XDND protocol (see
+ https://freedesktop.org/wiki/Specifications/XDND) and the Motif drag
+ and drop protocols. These protocols are based on the initiator
+ owning a special selection, specifying an action the recipient
+ should perform, grabbing the mouse, and sending various different
+ client messages to the toplevel window underneath the mouse as it
+ moves, or when buttons are released.
+
+ The Lisp interface to drag-and-drop is synchronous, and involves
+ running a nested event loop with some global state until the drag
+ finishes. When the mouse moves, Emacs looks up the toplevel window
+ underneath the pointer (the target window) either using a cache
+ provided by window managers that support the
+ _NET_WM_CLIENT_LIST_STACKING root window property, or by calling
+ XTranslateCoordinates in a loop until a toplevel window is found,
+ and sends various entry, exit, or motion events to the window
+ containing a list of targets the special selection can be converted
+ to, and the chosen action that the recipient should perform. The
+ recipient can then send messages in reply detailing the action it
+ has actually chosen to perform. Finally, when the mouse buttons are
+ released over the recipient window, Emacs sends a "drop" message to
+ the target window, waits for a reply, and returns the action
+ selected by the recipient to the Lisp code that initiated the
+ drag-and-drop operation.
+
+ When a drop happens on a window not supporting any protocol
+ implemented on the C level, the function inside
+ `x-dnd-unsupported-drop-function' is called with some parameters of
+ the drop. If it returns non-nil, then Emacs tries to simulate a
+ drop happening with the primary selection and synthetic button
+ events (see `x_dnd_do_unsupported_drop'). That function implements
+ the OffiX drag-and-drop protocol by default. See
+ `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details. */
+
#include <config.h>
#include <stdlib.h>
#include <math.h>
+#include <signal.h>
#include "lisp.h"
#include "blockinput.h"
@@ -33,6 +571,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "xterm.h"
#include <X11/cursorfont.h>
+#ifdef USE_XCB
+#include <xcb/xproto.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#endif
+
/* If we have Xfixes extension, use it for pointer blanking. */
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
@@ -50,6 +594,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/extensions/Xrandr.h>
#endif
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
+#ifdef HAVE_XCOMPOSITE
+#include <X11/extensions/Xcomposite.h>
+#endif
+
+#ifdef HAVE_XSHAPE
+#include <X11/extensions/shape.h>
+#endif
+
+#ifdef HAVE_XCB_SHAPE
+#include <xcb/shape.h>
+#endif
+
/* Load sys/types.h if not already loaded.
In some systems loading it twice is suicidal. */
#ifndef makedev
@@ -63,6 +627,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
+#include <flexmember.h>
+#include <c-ctype.h>
+#include <byteswap.h>
+
#include "character.h"
#include "coding.h"
#include "composite.h"
@@ -86,6 +654,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
+#include <X11/ShellP.h>
#endif
#include <unistd.h>
@@ -101,13 +670,20 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "../lwlib/xlwmenu.h"
#endif
+#ifdef HAVE_XWIDGETS
+#include <cairo-xlib.h>
+#endif
+
+#ifdef USE_MOTIF
+#include <Xm/Xm.h>
+#include <Xm/CascadeB.h>
+#endif
+
#ifdef USE_X_TOOLKIT
/* Include toolkit specific headers for the scroll bar widget. */
-
#ifdef USE_TOOLKIT_SCROLL_BARS
#if defined USE_MOTIF
-#include <Xm/Xm.h> /* For LESSTIF_VERSION */
#include <Xm/ScrollBar.h>
#else /* !USE_MOTIF i.e. use Xaw */
@@ -134,12 +710,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif
#endif
+#ifdef USE_GTK
+#include <xgselect.h>
+#endif
+
#include "bitmaps/gray.xbm"
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#endif
+/* Although X11/Xlib.h commonly defines the types XErrorHandler and
+ XIOErrorHandler, they are not in the Xlib spec, so for portability
+ define and use names with an Emacs_ prefix instead. */
+typedef int (*Emacs_XErrorHandler) (Display *, XErrorEvent *);
+typedef int (*Emacs_XIOErrorHandler) (Display *);
+
+#if defined USE_XCB && defined USE_CAIRO_XCB
+#define USE_CAIRO_XCB_SURFACE
+#endif
+
/* Default to using XIM if available. */
#ifdef USE_XIM
bool use_xim = true;
@@ -147,6 +737,23 @@ bool use_xim = true;
bool use_xim = false; /* configure --without-xim */
#endif
+#if XCB_SHAPE_MAJOR_VERSION > 1 \
+ || (XCB_SHAPE_MAJOR_VERSION == 1 && \
+ XCB_SHAPE_MINOR_VERSION >= 1)
+#define HAVE_XCB_SHAPE_INPUT_RECTS
+#endif
+
+#ifdef USE_GTK
+/* GTK can't tolerate a call to `handle_interrupt' inside an event
+ signal handler, but we have to store input events inside the
+ handler for native input to work.
+
+ This acts as a `hold_quit', and it is stored in the keyboard buffer
+ (thereby causing the call to `handle_interrupt') after the GTK
+ signal handler exits and control returns to XTread_socket. */
+struct input_event xg_pending_quit_event = { .kind = NO_EVENT };
+#endif
+
/* Non-zero means that a HELP_EVENT has been generated since Emacs
start. */
@@ -174,6 +781,10 @@ static bool toolkit_scroll_bar_interaction;
static Time ignore_next_mouse_click_timeout;
+/* The display that ignore_next_mouse_click_timeout applies to. */
+
+static struct x_display_info *mouse_click_timeout_display;
+
/* Used locally within XTread_socket. */
static int x_noop_count;
@@ -183,8 +794,260 @@ static int x_noop_count;
static Lisp_Object xg_default_icon_file;
#endif
+#ifdef HAVE_X_I18N
/* Some functions take this as char *, not const char *. */
static char emacs_class[] = EMACS_CLASS;
+#endif
+
+#ifdef USE_GTK
+static int current_count;
+static int current_finish;
+static struct input_event *current_hold_quit;
+#endif
+
+/* Queue selection requests in `pending_selection_requests' if more
+ than 0. */
+static int x_use_pending_selection_requests;
+
+/* Like `next_kbd_event', but for use in X code. */
+#define X_NEXT_KBD_EVENT(ptr) \
+ ((ptr) == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : (ptr) + 1)
+
+static void x_push_selection_request (struct selection_input_event *);
+
+/* Defer selection requests. Between this and
+ x_release_selection_requests, any selection requests can be
+ processed by calling `x_handle_pending_selection_requests'.
+
+ Also run through and queue all the selection events already in the
+ keyboard buffer. */
+void
+x_defer_selection_requests (void)
+{
+ union buffered_input_event *event;
+ bool between;
+
+ between = false;
+
+ block_input ();
+ if (!x_use_pending_selection_requests)
+ {
+ event = kbd_fetch_ptr;
+
+ while (event != kbd_store_ptr)
+ {
+ if (event->ie.kind == SELECTION_REQUEST_EVENT
+ || event->ie.kind == SELECTION_CLEAR_EVENT)
+ {
+ x_push_selection_request (&event->sie);
+
+ /* Mark this selection event as invalid. */
+ SELECTION_EVENT_DPYINFO (&event->sie) = NULL;
+
+ /* Move the kbd_fetch_ptr along if doing so would not
+ result in any other events being skipped. This
+ avoids exhausting the keyboard buffer with some
+ over-enthusiastic clipboard managers. */
+ if (!between)
+ {
+ kbd_fetch_ptr = X_NEXT_KBD_EVENT (event);
+
+ /* `detect_input_pending' will then recompute
+ whether or not pending input events exist. */
+ input_pending = false;
+ }
+ }
+ else
+ between = true;
+
+ event = X_NEXT_KBD_EVENT (event);
+ }
+ }
+
+ x_use_pending_selection_requests++;
+ unblock_input ();
+}
+
+static void
+x_release_selection_requests (void)
+{
+ x_use_pending_selection_requests--;
+}
+
+void
+x_release_selection_requests_and_flush (void)
+{
+ x_release_selection_requests ();
+
+ if (!x_use_pending_selection_requests)
+ x_handle_pending_selection_requests ();
+}
+
+struct x_selection_request_event
+{
+ /* The selection request event. */
+ struct selection_input_event se;
+
+ /* The next unprocessed selection request event. */
+ struct x_selection_request_event *next;
+};
+
+/* Chain of unprocessed selection request events. Used to handle
+ selection requests inside long-lasting modal event loops, such as
+ the drag-and-drop loop. */
+
+struct x_selection_request_event *pending_selection_requests;
+
+/* Compare two request serials A and B with OP, handling
+ wraparound. */
+#define X_COMPARE_SERIALS(a, op ,b) \
+ (((long) (a) - (long) (b)) op 0)
+
+struct x_atom_ref
+{
+ /* Atom name. */
+ const char *name;
+
+ /* Offset of atom in the display info structure. */
+ int offset;
+};
+
+/* List of all atoms that should be interned when connecting to a
+ display. */
+static const struct x_atom_ref x_atom_refs[] =
+ {
+#define ATOM_REFS_INIT(string, member) \
+ { string, offsetof (struct x_display_info, member) },
+ ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
+ ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
+ ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
+ ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
+ ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
+ ATOM_REFS_INIT ("WM_STATE", Xatom_wm_state)
+ ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
+ ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
+ ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
+ ATOM_REFS_INIT ("WM_TRANSIENT_FOR", Xatom_wm_transient_for)
+ ATOM_REFS_INIT ("Editres", Xatom_editres)
+ ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
+ ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
+ ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
+ ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
+ ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
+ ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
+ ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
+ ATOM_REFS_INIT ("INCR", Xatom_INCR)
+ ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
+ ATOM_REFS_INIT ("EMACS_SERVER_TIME_PROP", Xatom_EMACS_SERVER_TIME_PROP)
+ ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
+ ATOM_REFS_INIT ("NULL", Xatom_NULL)
+ ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
+ ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
+ ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
+ ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
+ ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS)
+ ATOM_REFS_INIT ("_EMACS_DRAG_ATOM", Xatom_EMACS_DRAG_ATOM)
+ /* For properties of font. */
+ ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
+ ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
+ ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
+ ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
+ ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
+ /* Ghostscript support. */
+ ATOM_REFS_INIT ("DONE", Xatom_DONE)
+ ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
+ ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
+ ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
+ ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
+ /* EWMH */
+ ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
+ ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
+ ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
+ Xatom_net_wm_state_maximized_horz)
+ ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
+ Xatom_net_wm_state_maximized_vert)
+ ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
+ ATOM_REFS_INIT ("_NET_WM_STATE_SHADED", Xatom_net_wm_state_shaded)
+ ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
+ ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
+ ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
+ Xatom_net_window_type_tooltip)
+ ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
+ ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
+ ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
+ ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
+ ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
+ ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
+ ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
+ ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
+ ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
+ ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST", Xatom_net_wm_sync_request)
+ ATOM_REFS_INIT ("_NET_WM_SYNC_REQUEST_COUNTER", Xatom_net_wm_sync_request_counter)
+ ATOM_REFS_INIT ("_NET_WM_FRAME_DRAWN", Xatom_net_wm_frame_drawn)
+ ATOM_REFS_INIT ("_NET_WM_USER_TIME", Xatom_net_wm_user_time)
+ ATOM_REFS_INIT ("_NET_WM_USER_TIME_WINDOW", Xatom_net_wm_user_time_window)
+ ATOM_REFS_INIT ("_NET_CLIENT_LIST_STACKING", Xatom_net_client_list_stacking)
+ /* Session management */
+ ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
+ ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
+ ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
+ ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
+ ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
+ ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
+ ATOM_REFS_INIT ("_NET_WM_OPAQUE_REGION", Xatom_net_wm_opaque_region)
+ ATOM_REFS_INIT ("_NET_WM_PING", Xatom_net_wm_ping)
+ ATOM_REFS_INIT ("_NET_WM_PID", Xatom_net_wm_pid)
+#ifdef HAVE_XKB
+ ATOM_REFS_INIT ("Meta", Xatom_Meta)
+ ATOM_REFS_INIT ("Super", Xatom_Super)
+ ATOM_REFS_INIT ("Hyper", Xatom_Hyper)
+ ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock)
+ ATOM_REFS_INIT ("Alt", Xatom_Alt)
+#endif
+ /* DND source. */
+ ATOM_REFS_INIT ("XdndAware", Xatom_XdndAware)
+ ATOM_REFS_INIT ("XdndSelection", Xatom_XdndSelection)
+ ATOM_REFS_INIT ("XdndTypeList", Xatom_XdndTypeList)
+ ATOM_REFS_INIT ("XdndActionCopy", Xatom_XdndActionCopy)
+ ATOM_REFS_INIT ("XdndActionMove", Xatom_XdndActionMove)
+ ATOM_REFS_INIT ("XdndActionLink", Xatom_XdndActionLink)
+ ATOM_REFS_INIT ("XdndActionAsk", Xatom_XdndActionAsk)
+ ATOM_REFS_INIT ("XdndActionPrivate", Xatom_XdndActionPrivate)
+ ATOM_REFS_INIT ("XdndActionList", Xatom_XdndActionList)
+ ATOM_REFS_INIT ("XdndActionDescription", Xatom_XdndActionDescription)
+ ATOM_REFS_INIT ("XdndProxy", Xatom_XdndProxy)
+ ATOM_REFS_INIT ("XdndEnter", Xatom_XdndEnter)
+ ATOM_REFS_INIT ("XdndPosition", Xatom_XdndPosition)
+ ATOM_REFS_INIT ("XdndStatus", Xatom_XdndStatus)
+ ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave)
+ ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop)
+ ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished)
+ /* XDS source and target. */
+ ATOM_REFS_INIT ("XdndDirectSave0", Xatom_XdndDirectSave0)
+ ATOM_REFS_INIT ("XdndActionDirectSave", Xatom_XdndActionDirectSave)
+ ATOM_REFS_INIT ("text/plain", Xatom_text_plain)
+ /* Motif drop protocol support. */
+ ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW)
+ ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS)
+ ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE",
+ Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
+ ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO",
+ Xatom_MOTIF_DRAG_INITIATOR_INFO)
+ ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO",
+ Xatom_MOTIF_DRAG_RECEIVER_INFO)
+ ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS)
+ ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE)
+ /* Old OffiX (a.k.a. old KDE) drop protocol support. */
+ ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol)
+ ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL)
+ };
+
+enum
+{
+ X_EVENT_NORMAL,
+ X_EVENT_GOTO_OUT,
+ X_EVENT_DROP
+};
enum xembed_info
{
@@ -219,6 +1082,7 @@ static void x_frame_rehighlight (struct x_display_info *);
static void x_clip_to_row (struct window *, struct glyph_row *,
enum glyph_row_area, GC);
static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
+static struct frame *x_window_to_frame (struct x_display_info *, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
@@ -247,7 +1111,3711 @@ static void x_wm_set_window_state (struct frame *, int);
static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
static void x_initialize (void);
-static bool x_get_current_wm_state (struct frame *, Window, int *, bool *);
+static bool x_get_current_wm_state (struct frame *, Window, int *, bool *, bool *);
+static void x_update_opaque_region (struct frame *, XEvent *);
+
+#if !defined USE_TOOLKIT_SCROLL_BARS && defined HAVE_XDBE
+static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar *);
+#endif
+
+#ifdef HAVE_X_I18N
+static int x_filter_event (struct x_display_info *, XEvent *);
+#endif
+static void x_ignore_errors_for_next_request (struct x_display_info *);
+static void x_stop_ignoring_errors (struct x_display_info *);
+static void x_clean_failable_requests (struct x_display_info *);
+
+static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
+ Window, bool *);
+static Window x_get_window_below (Display *, Window, int, int, int *, int *);
+
+/* Global state maintained during a drag-and-drop operation. */
+
+/* Flag that indicates if a drag-and-drop operation is in progress. */
+bool x_dnd_in_progress;
+
+/* The frame where the drag-and-drop operation originated. */
+struct frame *x_dnd_frame;
+
+/* That frame, but set when x_dnd_waiting_for_finish is true. Used to
+ prevent the frame from being deleted inside selection handlers and
+ other callbacks. */
+struct frame *x_dnd_finish_frame;
+
+/* Flag that indicates if a drag-and-drop operation is no longer in
+ progress, but the nested event loop should continue to run, because
+ handle_one_xevent is waiting for the drop target to return some
+ important information. */
+bool x_dnd_waiting_for_finish;
+
+/* Flag that means (when set in addition to
+ `x_dnd_waiting_for_finish') to run the unsupported drop function
+ with the given arguments. */
+static bool x_dnd_run_unsupported_drop_function;
+
+/* The "before"-time of the unsupported drop. */
+static Time x_dnd_unsupported_drop_time;
+
+/* The target window of the unsupported drop. */
+static Window x_dnd_unsupported_drop_window;
+
+/* The Lisp data associated with the unsupported drop function. */
+static Lisp_Object x_dnd_unsupported_drop_data;
+
+/* Whether or not to move the tooltip along with the mouse pointer
+ during drag-and-drop. */
+static bool x_dnd_update_tooltip;
+
+/* Monitor attribute list used for updating the tooltip position. */
+static Lisp_Object x_dnd_monitors;
+
+/* The display the drop target that is supposed to send information is
+ on. */
+static Display *x_dnd_finish_display;
+
+/* State of the Motif drop operation.
+
+ 0 means nothing has happened, i.e. the event loop should not wait
+ for the receiver to send any data. 1 means an XmDROP_START message
+ was sent to the target, but no response has yet been received. 2
+ means a response to our XmDROP_START message was received and the
+ target accepted the drop, so Emacs should start waiting for the
+ drop target to convert one of the special selections
+ XmTRANSFER_SUCCESS or XmTRANSFER_FAILURE. */
+static int x_dnd_waiting_for_motif_finish;
+
+/* The display the Motif drag receiver will send response data
+ from. */
+struct x_display_info *x_dnd_waiting_for_motif_finish_display;
+
+/* Whether or not F1 was pressed during the drag-and-drop operation.
+
+ Motif programs rely on this to decide whether or not help
+ information about the drop site should be displayed. */
+static bool x_dnd_xm_use_help;
+
+/* Whether or not Motif drag initiator info was set up. */
+static bool x_dnd_motif_setup_p;
+
+/* The Motif drag atom used during the drag-and-drop operation. */
+static Atom x_dnd_motif_atom;
+
+/* The target window we are waiting for an XdndFinished message
+ from. */
+static Window x_dnd_pending_finish_target;
+
+/* The protocol version of that target window. */
+static int x_dnd_waiting_for_finish_proto;
+
+/* Whether or not it is OK for something to be dropped on the frame
+ where the drag-and-drop operation originated. */
+static bool x_dnd_allow_current_frame;
+
+/* Whether or not the `XdndTypeList' property has already been set on
+ the drag frame. */
+static bool x_dnd_init_type_lists;
+
+/* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'.
+
+ 0 means to do nothing. 1 means to wait for the mouse to first exit
+ `x_dnd_frame'. 2 means to wait for the mouse to move onto a frame,
+ and 3 means to return `x_dnd_return_frame_object'. */
+static int x_dnd_return_frame;
+
+/* The frame that should be returned by
+ `x_dnd_begin_drag_and_drop'. */
+static struct frame *x_dnd_return_frame_object;
+
+/* The last drop target window the mouse pointer moved over. This can
+ be different from `x_dnd_last_seen_toplevel' if that window had an
+ XdndProxy. */
+static Window x_dnd_last_seen_window;
+
+/* The last toplevel the mouse pointer moved over. */
+static Window x_dnd_last_seen_toplevel;
+
+/* The window where the drop happened. Normally None, but it is set
+ when something is actually dropped. */
+static Window x_dnd_end_window;
+
+/* The XDND protocol version of `x_dnd_last_seen_window'. -1 means it
+ did not support XDND. */
+static int x_dnd_last_protocol_version;
+
+/* Whether or not the last seen window is actually one of our
+ frames. */
+static bool x_dnd_last_window_is_frame;
+
+/* The Motif drag and drop protocol style of `x_dnd_last_seen_window'.
+ XM_DRAG_STYLE_NONE means the window does not support the Motif drag
+ or drop protocol. XM_DRAG_STYLE_DROP_ONLY means the window does
+ not respond to any drag protocol messages, so only drops should be
+ sent. Any other value means that the window supports both the drag
+ and drop protocols. */
+static int x_dnd_last_motif_style;
+
+/* The timestamp where Emacs last acquired ownership of the
+ `XdndSelection' selection. */
+static Time x_dnd_selection_timestamp;
+
+/* The drop target window to which the rectangle below applies. */
+static Window x_dnd_mouse_rect_target;
+
+/* A rectangle where XDND position messages should not be sent to the
+ drop target if the mouse pointer lies within. */
+static XRectangle x_dnd_mouse_rect;
+
+/* If not None, Emacs is waiting for an XdndStatus event from this
+ window. */
+static Window x_dnd_waiting_for_status_window;
+
+/* If .type != 0, an event that should be sent to .xclient.window
+ upon receiving an XdndStatus event from said window. */
+static XEvent x_dnd_pending_send_position;
+
+/* If true, send a drop from `x_dnd_finish_frame' to the pending
+ status window after receiving all pending XdndStatus events. */
+static bool x_dnd_need_send_drop;
+
+/* The protocol version of any such drop. */
+static int x_dnd_send_drop_proto;
+
+/* The action the drop target actually chose to perform.
+
+ Under XDND, this is set upon receiving the XdndFinished or
+ XdndStatus messages from the drop target.
+
+ Under Motif, this is changed upon receiving a XmDROP_START message
+ in reply to our own.
+
+ When dropping on a target that doesn't support any drag-and-drop
+ protocol, this is set to the atom XdndActionPrivate. */
+static Atom x_dnd_action;
+
+/* The symbol to return from `x-begin-drag' if non-nil. Takes
+ precedence over `x_dnd_action`. */
+static Lisp_Object x_dnd_action_symbol;
+
+/* The action we want the drop target to perform. The drop target may
+ elect to perform some different action, which is guaranteed to be
+ in `x_dnd_action' upon completion of a drop. */
+static Atom x_dnd_wanted_action;
+
+/* The set of optional actions available to a Motif drop target
+ computed at the start of the drag-and-drop operation. */
+static uint8_t x_dnd_motif_operations;
+
+/* The preferred optional action out of that set. Only takes effect
+ if `x_dnd_action' is XdndAsk. */
+static uint8_t x_dnd_first_motif_operation;
+
+/* Array of selection targets available to the drop target. */
+static Atom *x_dnd_targets;
+
+/* The number of elements in that array. */
+static int x_dnd_n_targets;
+
+/* The old window attributes of the root window before the
+ drag-and-drop operation started. It is used to keep the old event
+ mask around, since that should be restored after the operation
+ finishes. */
+static XWindowAttributes x_dnd_old_window_attrs;
+
+/* Whether or not `x_dnd_cleaup_drag_and_drop' should actually clean
+ up the drag and drop operation. */
+static bool x_dnd_unwind_flag;
+
+/* The frame for which `x-dnd-movement-function' should be called. */
+static struct frame *x_dnd_movement_frame;
+
+/* The coordinates which the movement function should be called
+ with. */
+static int x_dnd_movement_x, x_dnd_movement_y;
+
+#ifdef HAVE_XKB
+/* The keyboard state during the drag-and-drop operation. */
+static unsigned int x_dnd_keyboard_state;
+#endif
+
+/* jmp_buf that gets us out of the IO error handler if an error occurs
+ terminating DND as part of the display disconnect handler. */
+static sigjmp_buf x_dnd_disconnect_handler;
+
+/* Whether or not the current invocation of handle_one_xevent
+ happened inside the drag_and_drop event loop. */
+static bool x_dnd_inside_handle_one_xevent;
+
+/* The recursive edit depth when the drag-and-drop operation was
+ started. */
+static int x_dnd_recursion_depth;
+
+/* The cons cell containing the selection alias between the Motif drag
+ selection and `XdndSelection'. The car and cdr are only set when
+ initiating Motif drag-and-drop for the first time. */
+static Lisp_Object x_dnd_selection_alias_cell;
+
+/* Structure describing a single window that can be the target of
+ drag-and-drop operations. */
+struct x_client_list_window
+{
+ /* The window itself. */
+ Window window;
+
+ /* The display that window is on. */
+ Display *dpy;
+
+ /* Its X and Y coordinates from the root window. */
+ int x, y;
+
+ /* The width and height of the window. */
+ int width, height;
+
+ /* Whether or not the window is mapped. */
+ bool mapped_p;
+
+ /* A bitmask describing events Emacs was listening for from the
+ window before some extra events were added in
+ `x_dnd_compute_toplevels'. */
+ long previous_event_mask;
+
+ /* The window manager state of the window. */
+ unsigned long wm_state;
+
+ /* The next window in this list. */
+ struct x_client_list_window *next;
+
+ /* The Motif protocol style of this window, if any. */
+ uint8_t xm_protocol_style;
+
+ /* The extents of the frame window in each direction. */
+ int frame_extents_left;
+ int frame_extents_right;
+ int frame_extents_top;
+ int frame_extents_bottom;
+
+#ifdef HAVE_XSHAPE
+ /* The border width of this window. */
+ int border_width;
+
+ /* The rectangles making up the input shape. */
+ XRectangle *input_rects;
+
+ /* The number of rectangles composing the input shape. */
+ int n_input_rects;
+
+ /* The rectangles making up the bounding shape. */
+ XRectangle *bounding_rects;
+
+ /* The number of rectangles composing the bounding shape. */
+ int n_bounding_rects;
+#endif
+};
+
+/* List of all toplevels in stacking order, from top to bottom. */
+static struct x_client_list_window *x_dnd_toplevels;
+
+/* Whether or not the window manager supports the required features
+ for `x_dnd_toplevels' to work. */
+static bool x_dnd_use_toplevels;
+
+/* Motif drag-and-drop protocol support. */
+
+/* Pointer to a variable which stores whether or not an X error
+ occured while trying to create the Motif drag window. */
+static volatile bool *xm_drag_window_error;
+
+typedef enum xm_byte_order
+ {
+ XM_BYTE_ORDER_LSB_FIRST = 'l',
+ XM_BYTE_ORDER_MSB_FIRST = 'B',
+#ifndef WORDS_BIGENDIAN
+ XM_BYTE_ORDER_CUR_FIRST = 'l',
+#else
+ XM_BYTE_ORDER_CUR_FIRST = 'B',
+#endif
+ } xm_byte_order;
+
+#ifdef ENABLE_CHECKING
+
+#define SWAPCARD32(l) \
+ { \
+ struct { unsigned t : 32; } bit32; \
+ char n, *tp = (char *) &bit32; \
+ bit32.t = l; \
+ n = tp[0]; tp[0] = tp[3]; tp[3] = n; \
+ n = tp[1]; tp[1] = tp[2]; tp[2] = n; \
+ l = bit32.t; \
+ }
+
+#define SWAPCARD16(s) \
+ { \
+ struct { unsigned t : 16; } bit16; \
+ char n, *tp = (char *) &bit16; \
+ bit16.t = s; \
+ n = tp[0]; tp[0] = tp[1]; tp[1] = n; \
+ s = bit16.t; \
+ }
+
+#else
+#define SWAPCARD32(l) ((l) = bswap_32 (l))
+#define SWAPCARD16(l) ((l) = bswap_16 (l))
+#endif
+
+typedef struct xm_targets_table_header
+{
+ /* BYTE */ uint8_t byte_order;
+ /* BYTE */ uint8_t protocol;
+
+ /* CARD16 */ uint16_t target_list_count;
+ /* CARD32 */ uint32_t total_data_size;
+} xm_targets_table_header;
+
+typedef struct xm_targets_table_rec
+{
+ /* CARD16 */ uint16_t n_targets;
+ /* CARD32 */ uint32_t targets[FLEXIBLE_ARRAY_MEMBER];
+} xm_targets_table_rec;
+
+typedef struct xm_drop_start_message
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byte_order;
+
+ /* CARD16 */ uint16_t side_effects;
+ /* CARD32 */ uint32_t timestamp;
+ /* CARD16 */ uint16_t x, y;
+ /* CARD32 */ uint32_t index_atom;
+ /* CARD32 */ uint32_t source_window;
+} xm_drop_start_message;
+
+typedef struct xm_drop_start_reply
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byte_order;
+
+ /* CARD16 */ uint16_t side_effects;
+ /* CARD16 */ uint16_t better_x;
+ /* CARD16 */ uint16_t better_y;
+} xm_drop_start_reply;
+
+typedef struct xm_drag_initiator_info
+{
+ /* BYTE */ uint8_t byteorder;
+ /* BYTE */ uint8_t protocol;
+
+ /* CARD16 */ uint16_t table_index;
+ /* CARD32 */ uint32_t selection;
+} xm_drag_initiator_info;
+
+typedef struct xm_drag_receiver_info
+{
+ /* BYTE */ uint8_t byteorder;
+ /* BYTE */ uint8_t protocol;
+
+ /* BYTE */ uint8_t protocol_style;
+ /* BYTE */ uint8_t unspecified0;
+ /* CARD32 */ uint32_t unspecified1;
+ /* CARD32 */ uint32_t unspecified2;
+ /* CARD32 */ uint32_t unspecified3;
+} xm_drag_receiver_info;
+
+typedef struct xm_top_level_enter_message
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byteorder;
+
+ /* CARD16 */ uint16_t zero;
+ /* CARD32 */ uint32_t timestamp;
+ /* CARD32 */ uint32_t source_window;
+ /* CARD32 */ uint32_t index_atom;
+} xm_top_level_enter_message;
+
+typedef struct xm_drag_motion_message
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byteorder;
+
+ /* CARD16 */ uint16_t side_effects;
+ /* CARD32 */ uint32_t timestamp;
+ /* CARD16 */ uint16_t x, y;
+} xm_drag_motion_message;
+
+typedef struct xm_drag_motion_reply
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byte_order;
+
+ /* CARD16 */ uint16_t side_effects;
+ /* CARD32 */ uint32_t timestamp;
+ /* CARD16 */ uint16_t better_x;
+ /* CARD16 */ uint16_t better_y;
+} xm_drag_motion_reply;
+
+typedef struct xm_top_level_leave_message
+{
+ /* BYTE */ uint8_t reason;
+ /* BYTE */ uint8_t byteorder;
+
+ /* CARD16 */ uint16_t zero;
+ /* CARD32 */ uint32_t timestamp;
+ /* CARD32 */ uint32_t source_window;
+} xm_top_level_leave_message;
+
+#define XM_DRAG_SIDE_EFFECT(op, site, ops, act) \
+ ((op) | ((site) << 4) | ((ops) << 8) | ((act) << 12))
+
+/* Some of the macros below are temporarily unused. */
+
+#define XM_DRAG_SIDE_EFFECT_OPERATION(effect) ((effect) & 0xf)
+#define XM_DRAG_SIDE_EFFECT_SITE_STATUS(effect) (((effect) & 0xf0) >> 4)
+/* #define XM_DRAG_SIDE_EFFECT_OPERATIONS(effect) (((effect) & 0xf00) >> 8) */
+#define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 12)
+
+enum xm_drag_operation
+ {
+ XM_DRAG_NOOP = 0,
+ XM_DRAG_MOVE = (1L << 0),
+ XM_DRAG_COPY = (1L << 1),
+ XM_DRAG_LINK = (1L << 2),
+ XM_DRAG_LINK_REC = 3,
+ };
+
+#define XM_DRAG_OPERATION_IS_LINK(op) ((op) == XM_DRAG_LINK \
+ || (op) == XM_DRAG_LINK_REC)
+
+enum xm_drag_action
+ {
+ XM_DROP_ACTION_DROP = 0,
+ XM_DROP_ACTION_DROP_HELP = 1,
+ XM_DROP_ACTION_DROP_CANCEL = 2,
+ };
+
+#define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7))
+#define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0)
+#define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f)
+
+enum xm_drag_reason
+ {
+ XM_DRAG_REASON_DROP_START = 5,
+ XM_DRAG_REASON_TOP_LEVEL_ENTER = 0,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE = 1,
+ XM_DRAG_REASON_DRAG_MOTION = 2,
+ };
+
+enum xm_drag_originator
+ {
+ XM_DRAG_ORIGINATOR_INITIATOR = 0,
+ XM_DRAG_ORIGINATOR_RECEIVER = 1,
+ };
+
+enum xm_drag_style
+ {
+ /* The values ending with _REC should be treated as equivalent to
+ the ones without in messages from the receiver. */
+ XM_DRAG_STYLE_NONE = 0,
+ XM_DRAG_STYLE_DROP_ONLY = 1,
+ XM_DRAG_STYLE_DROP_ONLY_REC = 3,
+ XM_DRAG_STYLE_DYNAMIC = 5,
+ XM_DRAG_STYLE_DYNAMIC_REC = 2,
+ XM_DRAG_STYLE_DYNAMIC_REC1 = 4,
+ };
+
+#define XM_DRAG_STYLE_IS_DROP_ONLY(n) ((n) == XM_DRAG_STYLE_DROP_ONLY \
+ || (n) == XM_DRAG_STYLE_DROP_ONLY_REC)
+#define XM_DRAG_STYLE_IS_DYNAMIC(n) ((n) == XM_DRAG_STYLE_DYNAMIC \
+ || (n) == XM_DRAG_STYLE_DYNAMIC_REC \
+ || (n) == XM_DRAG_STYLE_DYNAMIC_REC1)
+
+enum xm_drop_site_status
+ {
+ XM_DROP_SITE_VALID = 3,
+ XM_DROP_SITE_INVALID = 2,
+ XM_DROP_SITE_NONE = 1,
+ };
+
+/* The version of the Motif drag-and-drop protocols that Emacs
+ supports. */
+#define XM_DRAG_PROTOCOL_VERSION 0
+
+static uint8_t
+xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action)
+{
+ if (action == dpyinfo->Xatom_XdndActionCopy)
+ return XM_DRAG_COPY;
+ else if (action == dpyinfo->Xatom_XdndActionMove)
+ return XM_DRAG_MOVE;
+ else if (action == dpyinfo->Xatom_XdndActionLink)
+ return XM_DRAG_LINK;
+ else if (action == dpyinfo->Xatom_XdndActionAsk)
+ return x_dnd_first_motif_operation;
+
+ return XM_DRAG_NOOP;
+}
+
+static uint8_t
+xm_operations_from_actions (struct x_display_info *dpyinfo,
+ Atom *ask_actions, int n_ask_actions)
+{
+ int i;
+ uint8_t flags;
+
+ flags = 0;
+
+ for (i = 0; i < n_ask_actions; ++i)
+ {
+ if (ask_actions[i] == dpyinfo->Xatom_XdndActionCopy)
+ flags |= XM_DRAG_COPY;
+ else if (ask_actions[i] == dpyinfo->Xatom_XdndActionMove)
+ flags |= XM_DRAG_MOVE;
+ else if (ask_actions[i] == dpyinfo->Xatom_XdndActionLink)
+ flags |= XM_DRAG_LINK;
+ }
+
+ return flags;
+}
+
+static int
+xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length,
+ xm_targets_table_header *header_return,
+ xm_byte_order *byteorder_return)
+{
+ if (length < 8)
+ return -1;
+
+ header_return->byte_order = *byteorder_return = *(bytes++);
+ header_return->protocol = *(bytes++);
+
+ header_return->target_list_count = *(uint16_t *) bytes;
+ header_return->total_data_size = *(uint32_t *) (bytes + 2);
+
+ if (header_return->byte_order != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (header_return->target_list_count);
+ SWAPCARD32 (header_return->total_data_size);
+ }
+
+ header_return->byte_order = XM_BYTE_ORDER_CUR_FIRST;
+
+ return 8;
+}
+
+static xm_targets_table_rec *
+xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length,
+ xm_byte_order byteorder)
+{
+ uint16_t nitems, i;
+ xm_targets_table_rec *rec;
+
+ if (length < 2)
+ return NULL;
+
+ nitems = *(uint16_t *) bytes;
+
+ if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
+ SWAPCARD16 (nitems);
+
+ if (length < 2 + nitems * 4)
+ return NULL;
+
+ rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
+ targets, nitems * 4));
+ rec->n_targets = nitems;
+
+ for (i = 0; i < nitems; ++i)
+ {
+ rec->targets[i] = ((uint32_t *) (bytes + 2))[i];
+
+ if (byteorder != XM_BYTE_ORDER_CUR_FIRST)
+ SWAPCARD32 (rec->targets[i]);
+ }
+
+ return rec;
+}
+
+static int
+xm_find_targets_table_idx (xm_targets_table_header *header,
+ xm_targets_table_rec **recs,
+ Atom *sorted_targets, int ntargets)
+{
+ int j;
+ uint16_t i;
+ uint32_t *targets;
+
+ targets = alloca (sizeof *targets * ntargets);
+
+ for (j = 0; j < ntargets; ++j)
+ targets[j] = sorted_targets[j];
+
+ for (i = 0; i < header->target_list_count; ++i)
+ {
+ if (recs[i]->n_targets == ntargets
+ && !memcmp (&recs[i]->targets, targets,
+ sizeof *targets * ntargets))
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+x_atoms_compare (const void *a, const void *b)
+{
+ return *(Atom *) a - *(Atom *) b;
+}
+
+static void
+xm_write_targets_table (Display *dpy, Window wdesc,
+ Atom targets_table_atom,
+ xm_targets_table_header *header,
+ xm_targets_table_rec **recs)
+{
+ uint8_t *header_buffer, *ptr, *rec_buffer;
+ ptrdiff_t rec_buffer_size;
+ uint16_t i, j;
+
+ header_buffer = alloca (8);
+ ptr = header_buffer;
+
+ *(header_buffer++) = header->byte_order;
+ *(header_buffer++) = header->protocol;
+ *((uint16_t *) header_buffer) = header->target_list_count;
+ *((uint32_t *) (header_buffer + 2)) = header->total_data_size;
+
+ rec_buffer = xmalloc (600);
+ rec_buffer_size = 600;
+
+ XChangeProperty (dpy, wdesc, targets_table_atom,
+ targets_table_atom, 8, PropModeReplace,
+ (unsigned char *) ptr, 8);
+
+ for (i = 0; i < header->target_list_count; ++i)
+ {
+ if (rec_buffer_size < 2 + recs[i]->n_targets * 4)
+ {
+ rec_buffer_size = 2 + recs[i]->n_targets * 4;
+ rec_buffer = xrealloc (rec_buffer, rec_buffer_size);
+ }
+
+ *((uint16_t *) rec_buffer) = recs[i]->n_targets;
+
+ for (j = 0; j < recs[i]->n_targets; ++j)
+ ((uint32_t *) (rec_buffer + 2))[j] = recs[i]->targets[j];
+
+ XChangeProperty (dpy, wdesc, targets_table_atom,
+ targets_table_atom, 8, PropModeAppend,
+ (unsigned char *) rec_buffer,
+ 2 + recs[i]->n_targets * 4);
+ }
+
+ xfree (rec_buffer);
+}
+
+static void
+xm_write_drag_initiator_info (Display *dpy, Window wdesc,
+ Atom prop_name, Atom type_name,
+ xm_drag_initiator_info *info)
+{
+ uint8_t *buf;
+
+ buf = alloca (8);
+ buf[0] = info->byteorder;
+ buf[1] = info->protocol;
+
+ if (info->byteorder != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (info->table_index);
+ SWAPCARD16 (info->selection);
+ }
+
+ *((uint16_t *) (buf + 2)) = info->table_index;
+ *((uint32_t *) (buf + 4)) = info->selection;
+
+ XChangeProperty (dpy, wdesc, prop_name, type_name, 8,
+ PropModeReplace, (unsigned char *) buf, 8);
+}
+
+static int
+xm_drag_window_error_handler (Display *display, XErrorEvent *event)
+{
+ if (xm_drag_window_error)
+ *xm_drag_window_error = true;
+
+ return 0;
+}
+
+static _Noreturn int
+xm_drag_window_io_error_handler (Display *dpy)
+{
+ /* DPY isn't created through GDK, so it doesn't matter if we don't
+ crash here. */
+ siglongjmp (x_dnd_disconnect_handler, 1);
+}
+
+/* Determine whether or not WINDOW exists on DPYINFO by selecting for
+ input from it. */
+static bool
+x_special_window_exists_p (struct x_display_info *dpyinfo,
+ Window window)
+{
+ bool rc;
+
+ x_catch_errors (dpyinfo->display);
+ XSelectInput (dpyinfo->display, window,
+ StructureNotifyMask);
+ rc = !x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ return rc;
+}
+
+/* Drag window creation strategy (very tricky, but race-free):
+
+ First look for _MOTIF_DRAG_WINDOW. If it is already present,
+ return it immediately to avoid the overhead of new display
+ connections.
+
+ Otherwise, create a new connection to the display. In that
+ connection, create a window, which will be the new drag window. Set
+ the client disconnect mode of the new connection to
+ RetainPermanent, and close it.
+
+ Grab the current display. Look up _MOTIF_DRAG_WINDOW, the current
+ drag window. If it exists (which means _MOTIF_DRAG_WINDOW was
+ created between the first step and now), kill the client that
+ created the new drag window to free the client slot on the X
+ server. Otherwise, set _MOTIF_DRAG_WINDOW to the new drag window.
+
+ Ungrab the display and return whichever window is currently in
+ _MOTIF_DRAG_WINDOW. */
+
+static Window
+xm_get_drag_window_1 (struct x_display_info *dpyinfo)
+{
+ Atom actual_type;
+ int rc, actual_format;
+ unsigned long nitems, bytes_remaining;
+ unsigned char *tmp_data = NULL;
+ Window drag_window;
+ XSetWindowAttributes attrs;
+ Display *temp_display;
+ Emacs_XErrorHandler old_handler;
+ Emacs_XIOErrorHandler old_io_handler;
+
+ /* This is volatile because GCC mistakenly warns about them being
+ clobbered by longjmp. */
+ volatile bool error;
+
+ drag_window = None;
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
+ 0, 1, False, XA_WINDOW, &actual_type,
+ &actual_format, &nitems, &bytes_remaining,
+ &tmp_data) == Success;
+
+ if (rc && actual_type == XA_WINDOW
+ && actual_format == 32 && nitems == 1
+ && tmp_data)
+ {
+ drag_window = *(Window *) tmp_data;
+ rc = x_special_window_exists_p (dpyinfo, drag_window);
+
+ if (!rc)
+ drag_window = None;
+ }
+
+ if (tmp_data)
+ XFree (tmp_data);
+
+ if (drag_window == None)
+ {
+ block_input ();
+ old_io_handler = XSetIOErrorHandler (xm_drag_window_io_error_handler);
+
+ if (sigsetjmp (x_dnd_disconnect_handler, 1))
+ {
+ XSetIOErrorHandler (old_io_handler);
+ unblock_input ();
+
+ return None;
+ }
+
+ unrequest_sigio ();
+ temp_display = XOpenDisplay (XDisplayString (dpyinfo->display));
+ request_sigio ();
+
+ if (!temp_display)
+ {
+ XSetIOErrorHandler (old_io_handler);
+ unblock_input ();
+
+ return None;
+ }
+
+ error = false;
+ xm_drag_window_error = &error;
+
+ XSetCloseDownMode (temp_display, RetainPermanent);
+ old_handler = XSetErrorHandler (xm_drag_window_error_handler);
+
+ attrs.override_redirect = True;
+ drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
+ -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
+ CopyFromParent, CWOverrideRedirect, &attrs);
+
+ /* Handle all errors now. */
+ XSync (temp_display, False);
+
+ /* Some part of the drag window creation process failed, so
+ punt. Release all resources too. */
+ if (error)
+ {
+ XSetCloseDownMode (temp_display, DestroyAll);
+ drag_window = None;
+ }
+
+ xm_drag_window_error = NULL;
+
+ /* FIXME: why does XCloseDisplay hang if SIGIO arrives and there
+ are multiple displays? */
+ unrequest_sigio ();
+ XCloseDisplay (temp_display);
+ request_sigio ();
+
+ XSetErrorHandler (old_handler);
+ XSetIOErrorHandler (old_io_handler);
+
+ /* Make sure the drag window created is actually valid for the
+ current display, and the XOpenDisplay above didn't
+ accidentally connect to some other display. */
+ if (!x_special_window_exists_p (dpyinfo, drag_window))
+ drag_window = None;
+ unblock_input ();
+
+ if (drag_window != None)
+ {
+ XGrabServer (dpyinfo->display);
+
+ x_catch_errors (dpyinfo->display);
+ tmp_data = NULL;
+
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
+ 0, 1, False, XA_WINDOW, &actual_type,
+ &actual_format, &nitems, &bytes_remaining,
+ &tmp_data) == Success;
+
+ if (rc && actual_type == XA_WINDOW
+ && actual_format == 32 && nitems == 1
+ && tmp_data
+ && x_special_window_exists_p (dpyinfo,
+ *(Window *) tmp_data))
+ {
+ /* Kill the client now to avoid leaking a client slot,
+ which is a limited resource. */
+ XKillClient (dpyinfo->display, drag_window);
+ drag_window = *(Window *) tmp_data;
+ }
+ else
+ XChangeProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &drag_window, 1);
+
+ if (tmp_data)
+ XFree (tmp_data);
+
+ if (x_had_errors_p (dpyinfo->display))
+ drag_window = None;
+ x_uncatch_errors ();
+
+ XUngrabServer (dpyinfo->display);
+ }
+ }
+
+ return drag_window;
+}
+
+static Window
+xm_get_drag_window (struct x_display_info *dpyinfo)
+{
+ if (dpyinfo->motif_drag_window != None)
+ return dpyinfo->motif_drag_window;
+
+ dpyinfo->motif_drag_window = xm_get_drag_window_1 (dpyinfo);
+ return dpyinfo->motif_drag_window;
+}
+
+static int
+xm_setup_dnd_targets (struct x_display_info *dpyinfo,
+ Atom *targets, int ntargets)
+{
+ Window drag_window;
+ Atom *targets_sorted, actual_type;
+ unsigned char *tmp_data = NULL;
+ unsigned long nitems, bytes_remaining;
+ int rc, actual_format, idx;
+ bool had_errors;
+ xm_targets_table_header header;
+ xm_targets_table_rec **recs;
+ xm_byte_order byteorder;
+ uint8_t *data;
+ ptrdiff_t total_bytes, total_items, i;
+ uint32_t size, target_count;
+
+ retry_drag_window:
+
+ drag_window = xm_get_drag_window (dpyinfo);
+
+ if (drag_window == None || ntargets > 64)
+ return -1;
+
+ targets_sorted = xmalloc (sizeof *targets * ntargets);
+ memcpy (targets_sorted, targets,
+ sizeof *targets * ntargets);
+ qsort (targets_sorted, ntargets,
+ sizeof (Atom), x_atoms_compare);
+
+ XGrabServer (dpyinfo->display);
+
+ x_catch_errors (dpyinfo->display);
+ rc = XGetWindowProperty (dpyinfo->display, drag_window,
+ dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
+ 0L, LONG_MAX, False,
+ dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
+ &actual_type, &actual_format, &nitems,
+ &bytes_remaining, &tmp_data) == Success;
+ had_errors = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ /* The drag window is probably invalid, so remove our record of
+ it. */
+ if (had_errors)
+ {
+ dpyinfo->motif_drag_window = None;
+ XUngrabServer (dpyinfo->display);
+
+ goto retry_drag_window;
+ }
+
+ if (rc && tmp_data && !bytes_remaining
+ && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS
+ && actual_format == 8)
+ {
+ data = (uint8_t *) tmp_data;
+ if (xm_read_targets_table_header ((uint8_t *) tmp_data,
+ nitems, &header,
+ &byteorder) == 8)
+ {
+ data += 8;
+ nitems -= 8;
+ total_bytes = 0;
+ total_items = 0;
+
+ /* The extra rec is used to store a new target list if a
+ preexisting one doesn't already exist. */
+ recs = xmalloc ((header.target_list_count + 1)
+ * sizeof *recs);
+
+ while (total_items < header.target_list_count)
+ {
+ recs[total_items] = xm_read_targets_table_rec (data + total_bytes,
+ nitems, byteorder);
+
+ if (!recs[total_items])
+ break;
+
+ total_bytes += 2 + recs[total_items]->n_targets * 4;
+ nitems -= 2 + recs[total_items]->n_targets * 4;
+ total_items++;
+ }
+
+ if (header.target_list_count != total_items
+ || header.total_data_size != 8 + total_bytes)
+ {
+ for (i = 0; i < total_items; ++i)
+ {
+ if (recs[i])
+ xfree (recs[i]);
+ else
+ break;
+ }
+
+ xfree (recs);
+
+ rc = false;
+ }
+ }
+ else
+ rc = false;
+ }
+ else
+ rc = false;
+
+ if (tmp_data)
+ XFree (tmp_data);
+
+ /* Now rc means whether or not the target lists weren't updated and
+ shouldn't be written to the drag window. */
+
+ if (!rc)
+ {
+ header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ header.protocol = XM_DRAG_PROTOCOL_VERSION;
+ header.target_list_count = 1;
+ header.total_data_size = 8 + 2 + ntargets * 4;
+
+ recs = xmalloc (sizeof *recs);
+ recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
+ targets, ntargets * 4));
+
+ recs[0]->n_targets = ntargets;
+
+ for (i = 0; i < ntargets; ++i)
+ recs[0]->targets[i] = targets_sorted[i];
+
+ idx = 0;
+ }
+ else
+ {
+ idx = xm_find_targets_table_idx (&header, recs,
+ targets_sorted,
+ ntargets);
+
+ if (idx == -1)
+ {
+ target_count = header.target_list_count;
+ rc = false;
+
+ if (INT_ADD_WRAPV (header.target_list_count, 1,
+ &header.target_list_count)
+ || INT_MULTIPLY_WRAPV (ntargets, 4, &size)
+ || INT_ADD_WRAPV (header.total_data_size, size,
+ &header.total_data_size)
+ || INT_ADD_WRAPV (header.total_data_size, 2,
+ &header.total_data_size))
+ {
+ /* Overflow, remove every entry from the targets table
+ and add one for our current targets list. This
+ confuses real Motif but not GTK 2.x, and there is no
+ other choice. */
+
+ for (i = 0; i < target_count; ++i)
+ xfree (recs[i]);
+
+ xfree (recs);
+
+ header.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ header.protocol = XM_DRAG_PROTOCOL_VERSION;
+ header.target_list_count = 1;
+ header.total_data_size = 8 + 2 + ntargets * 4;
+
+ recs = xmalloc (sizeof *recs);
+ recs[0] = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
+ targets, ntargets * 4));
+
+ recs[0]->n_targets = ntargets;
+
+ for (i = 0; i < ntargets; ++i)
+ recs[0]->targets[i] = targets_sorted[i];
+
+ idx = 0;
+ }
+ else
+ {
+ recs[header.target_list_count - 1]
+ = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec,
+ targets, ntargets * 4));
+ recs[header.target_list_count - 1]->n_targets = ntargets;
+
+ for (i = 0; i < ntargets; ++i)
+ recs[header.target_list_count - 1]->targets[i] = targets_sorted[i];
+
+ idx = header.target_list_count - 1;
+ }
+ }
+ }
+
+ if (!rc)
+ {
+ /* Some implementations of Motif DND set the protocol version of
+ just the targets table to 1 without actually changing the
+ data format. To avoid confusing Motif when that happens, set
+ it back to 0. There will probably be no more updates to the
+ protocol either. */
+ header.protocol = XM_DRAG_PROTOCOL_VERSION;
+
+ x_catch_errors (dpyinfo->display);
+ xm_write_targets_table (dpyinfo->display, drag_window,
+ dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
+ &header, recs);
+ /* Presumably we got a BadAlloc upon writing the targets
+ table. */
+ if (x_had_errors_p (dpyinfo->display))
+ idx = -1;
+ x_uncatch_errors_after_check ();
+ }
+
+ XUngrabServer (dpyinfo->display);
+
+ for (i = 0; i < header.target_list_count; ++i)
+ xfree (recs[i]);
+
+ xfree (recs);
+ xfree (targets_sorted);
+
+ return idx;
+}
+
+/* Allocate an atom that will be used for the Motif selection during
+ the drag-and-drop operation.
+
+ Grab the server, and then retrieve a list of atoms named
+ _EMACS_DRAG_ATOM from the root window. Find the first atom that
+ has no selection owner, own it and return it. If there is no such
+ atom, add a unique atom to the end of the list and return that
+ instead. */
+
+static Atom
+xm_get_drag_atom_1 (struct x_display_info *dpyinfo,
+ struct frame *source_frame)
+{
+ Atom actual_type, *atoms, atom;
+ unsigned long nitems, bytes_remaining;
+ unsigned char *tmp_data;
+ int rc, actual_format;
+ unsigned long i;
+ char *buffer;
+ Window owner;
+
+ /* Make sure this operation is done atomically. */
+ XGrabServer (dpyinfo->display);
+
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_EMACS_DRAG_ATOM,
+ 0, LONG_MAX, False, XA_ATOM, &actual_type,
+ &actual_format, &nitems, &bytes_remaining,
+ &tmp_data);
+ atom = None;
+ /* GCC thinks i is used unitialized, but it's always initialized if
+ `atoms' exists at that particular spot. */
+ i = 0;
+
+ if (rc == Success
+ && actual_format == 32 && nitems
+ && actual_type == XA_ATOM)
+ {
+ atoms = (Atom *) tmp_data;
+
+ x_catch_errors (dpyinfo->display);
+
+ for (i = 0; i < nitems; ++i)
+ {
+ owner = XGetSelectionOwner (dpyinfo->display, atoms[i]);
+
+ if (!x_had_errors_p (dpyinfo->display)
+ && (owner == None
+ /* If we already own this selection (even if another
+ frame owns it), use it. There is no way of
+ knowing when ownership was asserted, so it still
+ has to be owned again. */
+ || x_window_to_frame (dpyinfo, owner)))
+ {
+ atom = atoms[i];
+
+ break;
+ }
+ }
+
+ x_uncatch_errors ();
+ }
+
+ if (tmp_data)
+ XFree (tmp_data);
+
+ buffer = dpyinfo->motif_drag_atom_name;
+
+ if (atom)
+ {
+ sprintf (buffer, "_EMACS_ATOM_%lu", i + 1);
+ XSetSelectionOwner (dpyinfo->display, atom,
+ FRAME_X_WINDOW (source_frame),
+ dpyinfo->last_user_time);
+
+ /* The selection's last-change time is newer than our
+ last_user_time, so create a new selection instead. */
+ if (XGetSelectionOwner (dpyinfo->display, atom)
+ != FRAME_X_WINDOW (source_frame))
+ atom = None;
+ }
+
+ while (!atom)
+ {
+ sprintf (buffer, "_EMACS_ATOM_%lu", nitems + 1);
+ atom = XInternAtom (dpyinfo->display, buffer, False);
+
+ XSetSelectionOwner (dpyinfo->display, atom,
+ FRAME_X_WINDOW (source_frame),
+ dpyinfo->last_user_time);
+
+ XChangeProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32,
+ (rc != Success
+ || (actual_format != 32
+ || actual_type != XA_ATOM)
+ ? PropModeReplace : PropModeAppend),
+ (unsigned char *) &atom, 1);
+
+ actual_format = 32;
+ actual_type = XA_ATOM;
+ rc = Success;
+ nitems += 1;
+
+ /* The selection's last-change time is newer than our
+ last_user_time, so create a new selection (again). */
+ if (XGetSelectionOwner (dpyinfo->display, atom)
+ != FRAME_X_WINDOW (source_frame))
+ atom = None;
+ }
+
+ dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time;
+ dpyinfo->motif_drag_atom_owner = source_frame;
+
+ XUngrabServer (dpyinfo->display);
+ return atom;
+}
+
+static Atom
+xm_get_drag_atom (struct x_display_info *dpyinfo)
+{
+ Atom atom;
+
+ if (dpyinfo->motif_drag_atom != None)
+ atom = dpyinfo->motif_drag_atom;
+ else
+ atom = xm_get_drag_atom_1 (dpyinfo, x_dnd_frame);
+
+ dpyinfo->motif_drag_atom = atom;
+ return atom;
+}
+
+static void
+xm_setup_drag_info (struct x_display_info *dpyinfo,
+ struct frame *source_frame)
+{
+ Atom atom;
+ xm_drag_initiator_info drag_initiator_info;
+ int idx;
+
+ atom = xm_get_drag_atom (dpyinfo);
+
+ if (atom == None)
+ return;
+
+ XSETCAR (x_dnd_selection_alias_cell,
+ x_atom_to_symbol (dpyinfo, atom));
+ XSETCDR (x_dnd_selection_alias_cell, QXdndSelection);
+
+ idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
+ x_dnd_n_targets);
+
+ if (idx != -1)
+ {
+ drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION;
+ drag_initiator_info.table_index = idx;
+ drag_initiator_info.selection = atom;
+
+ xm_write_drag_initiator_info (dpyinfo->display,
+ FRAME_X_WINDOW (source_frame), atom,
+ dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
+ &drag_initiator_info);
+
+ x_dnd_motif_setup_p = true;
+ x_dnd_motif_atom = atom;
+ }
+}
+
+static void
+xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
+ Window target, xm_drop_start_message *dmsg)
+{
+ XEvent msg;
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type
+ = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
+ msg.xclient.format = 8;
+ msg.xclient.window = target;
+ msg.xclient.data.b[0] = dmsg->reason;
+ msg.xclient.data.b[1] = dmsg->byte_order;
+ *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
+ *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
+ *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
+ *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
+ *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
+ *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static void
+xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
+ Window target, xm_top_level_enter_message *dmsg)
+{
+ XEvent msg;
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type
+ = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
+ msg.xclient.format = 8;
+ msg.xclient.window = target;
+ msg.xclient.data.b[0] = dmsg->reason;
+ msg.xclient.data.b[1] = dmsg->byteorder;
+ *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
+ *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
+ *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
+ *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
+ msg.xclient.data.b[16] = 0;
+ msg.xclient.data.b[17] = 0;
+ msg.xclient.data.b[18] = 0;
+ msg.xclient.data.b[19] = 0;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static void
+xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
+ Window target, xm_drag_motion_message *dmsg)
+{
+ XEvent msg;
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type
+ = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
+ msg.xclient.format = 8;
+ msg.xclient.window = target;
+ msg.xclient.data.b[0] = dmsg->reason;
+ msg.xclient.data.b[1] = dmsg->byteorder;
+ *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
+ *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
+ *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
+ *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
+ msg.xclient.data.b[12] = 0;
+ msg.xclient.data.b[13] = 0;
+ msg.xclient.data.b[14] = 0;
+ msg.xclient.data.b[15] = 0;
+ msg.xclient.data.b[16] = 0;
+ msg.xclient.data.b[17] = 0;
+ msg.xclient.data.b[18] = 0;
+ msg.xclient.data.b[19] = 0;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static void
+xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
+ Window target, xm_top_level_leave_message *dmsg)
+{
+ XEvent msg;
+ xm_drag_motion_message mmsg;
+
+ /* Motif support for TOP_LEVEL_LEAVE has bitrotted, since these days
+ it assumes every client supports the preregister protocol style,
+ but we only support drop-only and dynamic. (Interestingly enough
+ LessTif works fine.) Sending an event with impossible
+ coordinates serves to get rid of any active drop site that might
+ still be around in the target drag context. */
+
+ if (x_dnd_fix_motif_leave)
+ {
+ mmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ mmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ mmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_NONE, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ mmsg.timestamp = dmsg->timestamp;
+
+ /* Use X_SHRT_MAX instead of the max value of uint16_t since
+ that will be interpreted as a plausible position by Motif,
+ and as such breaks if the drop target is beneath that
+ position. */
+ mmsg.x = X_SHRT_MAX;
+ mmsg.y = X_SHRT_MAX;
+
+ xm_send_drag_motion_message (dpyinfo, source, target, &mmsg);
+ }
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type
+ = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
+ msg.xclient.format = 8;
+ msg.xclient.window = target;
+ msg.xclient.data.b[0] = dmsg->reason;
+ msg.xclient.data.b[1] = dmsg->byteorder;
+ *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->zero;
+ *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
+ *((uint32_t *) &msg.xclient.data.b[8]) = dmsg->source_window;
+ msg.xclient.data.b[12] = 0;
+ msg.xclient.data.b[13] = 0;
+ msg.xclient.data.b[14] = 0;
+ msg.xclient.data.b[15] = 0;
+ msg.xclient.data.b[16] = 0;
+ msg.xclient.data.b[17] = 0;
+ msg.xclient.data.b[18] = 0;
+ msg.xclient.data.b[19] = 0;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static int
+xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply)
+{
+ const uint8_t *data;
+
+ data = (const uint8_t *) &msg->xclient.data.b[0];
+
+ if ((XM_DRAG_REASON_ORIGINATOR (data[0])
+ != XM_DRAG_ORIGINATOR_RECEIVER)
+ || (XM_DRAG_REASON_CODE (data[0])
+ != XM_DRAG_REASON_DROP_START))
+ return 1;
+
+ reply->reason = *(data++);
+ reply->byte_order = *(data++);
+ reply->side_effects = *(uint16_t *) data;
+ reply->better_x = *(uint16_t *) (data + 2);
+ reply->better_y = *(uint16_t *) (data + 4);
+
+ if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (reply->side_effects);
+ SWAPCARD16 (reply->better_x);
+ SWAPCARD16 (reply->better_y);
+ }
+
+ reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
+
+ return 0;
+}
+
+static int
+xm_read_drop_start_message (const XEvent *msg,
+ xm_drop_start_message *dmsg)
+{
+ const uint8_t *data;
+
+ data = (const uint8_t *) &msg->xclient.data.b[0];
+
+ if ((XM_DRAG_REASON_ORIGINATOR (data[0])
+ != XM_DRAG_ORIGINATOR_INITIATOR)
+ || (XM_DRAG_REASON_CODE (data[0])
+ != XM_DRAG_REASON_DROP_START))
+ return 1;
+
+ dmsg->reason = *(data++);
+ dmsg->byte_order = *(data++);
+ dmsg->side_effects = *(uint16_t *) data;
+ dmsg->timestamp = *(uint32_t *) (data + 2);
+ dmsg->x = *(uint16_t *) (data + 6);
+ dmsg->y = *(uint16_t *) (data + 8);
+ dmsg->index_atom = *(uint32_t *) (data + 10);
+ dmsg->source_window = *(uint32_t *) (data + 14);
+
+ if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (dmsg->side_effects);
+ SWAPCARD32 (dmsg->timestamp);
+ SWAPCARD16 (dmsg->x);
+ SWAPCARD16 (dmsg->y);
+ SWAPCARD32 (dmsg->index_atom);
+ SWAPCARD32 (dmsg->source_window);
+ }
+
+ dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST;
+
+ return 0;
+}
+
+static int
+xm_read_drag_receiver_info (struct x_display_info *dpyinfo,
+ Window wdesc, xm_drag_receiver_info *rec)
+{
+ Atom actual_type;
+ int rc, actual_format;
+ unsigned long nitems, bytes_remaining;
+ unsigned char *tmp_data = NULL;
+ uint8_t *data;
+
+ x_catch_errors (dpyinfo->display);
+ rc = XGetWindowProperty (dpyinfo->display, wdesc,
+ dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ 0, 4, False,
+ dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ &actual_type, &actual_format, &nitems,
+ &bytes_remaining,
+ &tmp_data) == Success;
+
+ if (x_had_errors_p (dpyinfo->display)
+ || actual_format != 8 || nitems < 16 || !tmp_data
+ || actual_type != dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
+ rc = 0;
+ x_uncatch_errors_after_check ();
+
+ if (rc)
+ {
+ data = (uint8_t *) tmp_data;
+
+ if (data[1] > XM_DRAG_PROTOCOL_VERSION)
+ return 1;
+
+ rec->byteorder = data[0];
+ rec->protocol = data[1];
+ rec->protocol_style = data[2];
+ rec->unspecified0 = data[3];
+ rec->unspecified1 = *(uint32_t *) &data[4];
+ rec->unspecified2 = *(uint32_t *) &data[8];
+ rec->unspecified3 = *(uint32_t *) &data[12];
+
+ if (rec->byteorder != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD32 (rec->unspecified1);
+ SWAPCARD32 (rec->unspecified2);
+ SWAPCARD32 (rec->unspecified3);
+ }
+
+ rec->byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ }
+
+ if (tmp_data)
+ XFree (tmp_data);
+
+ return !rc;
+}
+
+static int
+xm_read_drag_motion_message (const XEvent *msg,
+ xm_drag_motion_message *dmsg)
+{
+ const uint8_t *data;
+
+ data = (const uint8_t *) &msg->xclient.data.b[0];
+
+ if ((XM_DRAG_REASON_CODE (data[0])
+ != XM_DRAG_REASON_DRAG_MOTION)
+ || (XM_DRAG_REASON_ORIGINATOR (data[0])
+ != XM_DRAG_ORIGINATOR_INITIATOR))
+ return 1;
+
+ dmsg->reason = *(data++);
+ dmsg->byteorder = *(data++);
+ dmsg->side_effects = *(uint16_t *) data;
+ dmsg->timestamp = *(uint32_t *) (data + 2);
+ dmsg->x = *(uint16_t *) (data + 6);
+ dmsg->y = *(uint16_t *) (data + 8);
+
+ if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (dmsg->side_effects);
+ SWAPCARD32 (dmsg->timestamp);
+ SWAPCARD16 (dmsg->x);
+ SWAPCARD16 (dmsg->y);
+ }
+
+ dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST;
+
+ return 0;
+}
+
+static int
+xm_read_drag_motion_reply (const XEvent *msg, xm_drag_motion_reply *reply)
+{
+ const uint8_t *data;
+
+ data = (const uint8_t *) &msg->xclient.data.b[0];
+
+ if ((XM_DRAG_REASON_CODE (data[0])
+ != XM_DRAG_REASON_DRAG_MOTION)
+ || (XM_DRAG_REASON_ORIGINATOR (data[0])
+ != XM_DRAG_ORIGINATOR_RECEIVER))
+ return 1;
+
+ reply->reason = *(data++);
+ reply->byte_order = *(data++);
+ reply->side_effects = *(uint16_t *) data;
+ reply->timestamp = *(uint32_t *) (data + 2);
+ reply->better_x = *(uint16_t *) (data + 6);
+ reply->better_y = *(uint16_t *) (data + 8);
+
+ if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST)
+ {
+ SWAPCARD16 (reply->side_effects);
+ SWAPCARD32 (reply->timestamp);
+ SWAPCARD16 (reply->better_x);
+ SWAPCARD16 (reply->better_y);
+ }
+
+ reply->byte_order = XM_BYTE_ORDER_CUR_FIRST;
+
+ return 0;
+}
+
+static void
+x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo,
+ struct frame *f, Window wdesc,
+ Time timestamp)
+{
+ xm_top_level_leave_message lmsg;
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = timestamp;
+ lmsg.source_window = FRAME_X_WINDOW (f);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (f),
+ wdesc, &lmsg);
+}
+
+static void
+x_dnd_free_toplevels (bool display_alive)
+{
+ struct x_client_list_window *last;
+ struct x_client_list_window *tem = x_dnd_toplevels;
+ ptrdiff_t n_windows, i, buffer_size;
+ Window *destroy_windows;
+ unsigned long *prev_masks;
+ specpdl_ref count;
+ Display *dpy;
+ struct x_display_info *dpyinfo;
+
+ if (!x_dnd_toplevels)
+ /* Probably called inside an IO error handler. */
+ return;
+
+ /* Pacify GCC. */
+ prev_masks = NULL;
+ destroy_windows = NULL;
+
+ if (display_alive)
+ {
+ buffer_size = 1024;
+ destroy_windows = xmalloc (sizeof *destroy_windows
+ * buffer_size);
+ prev_masks = xmalloc (sizeof *prev_masks *
+ buffer_size);
+ n_windows = 0;
+ }
+
+ block_input ();
+ while (tem)
+ {
+ last = tem;
+ tem = tem->next;
+
+ if (display_alive)
+ {
+ if (++n_windows >= buffer_size)
+ {
+ buffer_size += 1024;
+ destroy_windows
+ = xrealloc (destroy_windows, (sizeof *destroy_windows
+ * buffer_size));
+ prev_masks
+ = xrealloc (prev_masks, (sizeof *prev_masks
+ * buffer_size));
+ }
+
+ dpy = last->dpy;
+ prev_masks[n_windows - 1] = last->previous_event_mask;
+ destroy_windows[n_windows - 1] = last->window;
+ }
+
+#ifdef HAVE_XSHAPE
+ if (last->n_input_rects != -1)
+ xfree (last->input_rects);
+ if (last->n_bounding_rects != -1)
+ xfree (last->bounding_rects);
+#endif
+
+ xfree (last);
+ }
+
+ x_dnd_toplevels = NULL;
+
+ if (!display_alive)
+ {
+ unblock_input ();
+ return;
+ }
+
+ count = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (xfree, destroy_windows);
+ record_unwind_protect_ptr (xfree, prev_masks);
+
+ if (display_alive)
+ {
+ dpyinfo = x_display_info_for_display (dpy);
+
+ if (n_windows)
+ {
+ x_ignore_errors_for_next_request (dpyinfo);
+
+ for (i = 0; i < n_windows; ++i)
+ {
+ XSelectInput (dpy, destroy_windows[i], prev_masks[i]);
+#ifdef HAVE_XSHAPE
+ XShapeSelectInput (dpy, destroy_windows[i], None);
+#endif
+ }
+
+ x_stop_ignoring_errors (dpyinfo);
+ }
+ }
+
+ unbind_to (count, Qnil);
+ unblock_input ();
+}
+
+static int
+x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
+{
+ Atom type;
+ Window *toplevels;
+ int format, rc;
+ unsigned long nitems, bytes_after;
+ unsigned long i;
+ unsigned char *data = NULL;
+ int frame_extents[4];
+
+#ifndef USE_XCB
+ int dest_x, dest_y;
+ unsigned long *wmstate;
+ unsigned long wmstate_items, extent_items;
+ unsigned char *wmstate_data = NULL, *extent_data = NULL;
+ XWindowAttributes attrs;
+ Window child;
+ xm_drag_receiver_info xm_info;
+#else
+ uint32_t *wmstate, *fextents;
+ uint8_t *xmdata;
+ xcb_get_window_attributes_cookie_t *window_attribute_cookies;
+ xcb_translate_coordinates_cookie_t *translate_coordinate_cookies;
+ xcb_get_property_cookie_t *get_property_cookies;
+ xcb_get_property_cookie_t *xm_property_cookies;
+ xcb_get_property_cookie_t *extent_property_cookies;
+ xcb_get_geometry_cookie_t *get_geometry_cookies;
+ xcb_get_window_attributes_reply_t attrs, *attrs_reply;
+ xcb_translate_coordinates_reply_t *coordinates_reply;
+ xcb_get_property_reply_t *property_reply;
+ xcb_get_property_reply_t *xm_property_reply;
+ xcb_get_property_reply_t *extent_property_reply;
+ xcb_get_geometry_reply_t *geometry_reply;
+ xcb_generic_error_t *error;
+#endif
+
+#ifdef HAVE_XCB_SHAPE
+ xcb_shape_get_rectangles_cookie_t *bounding_rect_cookies;
+ xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
+ xcb_rectangle_iterator_t bounding_rect_iterator;
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+ xcb_shape_get_rectangles_cookie_t *input_rect_cookies;
+ xcb_shape_get_rectangles_reply_t *input_rect_reply;
+ xcb_rectangle_iterator_t input_rect_iterator;
+#endif
+
+ struct x_client_list_window *tem;
+#if defined HAVE_XSHAPE && !defined HAVE_XCB_SHAPE_INPUT_RECTS
+ int count, ordering;
+ XRectangle *rects;
+#endif
+
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_net_client_list_stacking,
+ 0, LONG_MAX, False, XA_WINDOW, &type,
+ &format, &nitems, &bytes_after, &data);
+
+ if (rc != Success)
+ return 1;
+
+ if (format != 32 || type != XA_WINDOW)
+ {
+ XFree (data);
+ return 1;
+ }
+
+ toplevels = (Window *) data;
+
+#ifdef USE_XCB
+ USE_SAFE_ALLOCA;
+
+ window_attribute_cookies
+ = SAFE_ALLOCA (sizeof *window_attribute_cookies * nitems);
+ translate_coordinate_cookies
+ = SAFE_ALLOCA (sizeof *translate_coordinate_cookies * nitems);
+ get_property_cookies
+ = SAFE_ALLOCA (sizeof *get_property_cookies * nitems);
+ xm_property_cookies
+ = SAFE_ALLOCA (sizeof *xm_property_cookies * nitems);
+ extent_property_cookies
+ = SAFE_ALLOCA (sizeof *extent_property_cookies * nitems);
+ get_geometry_cookies
+ = SAFE_ALLOCA (sizeof *get_geometry_cookies * nitems);
+
+#ifdef HAVE_XCB_SHAPE
+ bounding_rect_cookies
+ = SAFE_ALLOCA (sizeof *bounding_rect_cookies * nitems);
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+ input_rect_cookies
+ = SAFE_ALLOCA (sizeof *input_rect_cookies * nitems);
+#endif
+
+ for (i = 0; i < nitems; ++i)
+ {
+ window_attribute_cookies[i]
+ = xcb_get_window_attributes (dpyinfo->xcb_connection,
+ (xcb_window_t) toplevels[i]);
+ translate_coordinate_cookies[i]
+ = xcb_translate_coordinates (dpyinfo->xcb_connection,
+ (xcb_window_t) toplevels[i],
+ (xcb_window_t) dpyinfo->root_window,
+ 0, 0);
+ get_property_cookies[i]
+ = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
+ (xcb_atom_t) dpyinfo->Xatom_wm_state, XCB_ATOM_ANY,
+ 0, 2);
+ xm_property_cookies[i]
+ = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
+ (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ 0, 4);
+ extent_property_cookies[i]
+ = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) toplevels[i],
+ (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
+ XCB_ATOM_CARDINAL, 0, 4);
+ get_geometry_cookies[i]
+ = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
+
+#ifdef HAVE_XCB_SHAPE
+ bounding_rect_cookies[i]
+ = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+ (xcb_window_t) toplevels[i],
+ XCB_SHAPE_SK_BOUNDING);
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ input_rect_cookies[i]
+ = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+ (xcb_window_t) toplevels[i],
+ XCB_SHAPE_SK_INPUT);
+#endif
+ }
+#endif
+
+ /* Actually right because _NET_CLIENT_LIST_STACKING has bottom-up
+ order. */
+ for (i = 0; i < nitems; ++i)
+ {
+ frame_extents[0] = 0;
+ frame_extents[1] = 0;
+ frame_extents[2] = 0;
+ frame_extents[3] = 0;
+
+#ifndef USE_XCB
+ x_catch_errors (dpyinfo->display);
+ rc = (XGetWindowAttributes (dpyinfo->display,
+ toplevels[i], &attrs)
+ && !x_had_errors_p (dpyinfo->display));
+
+ if (rc)
+ rc = (XTranslateCoordinates (dpyinfo->display, toplevels[i],
+ attrs.root, -attrs.border_width,
+ -attrs.border_width, &dest_x,
+ &dest_y, &child)
+ && !x_had_errors_p (dpyinfo->display));
+ if (rc)
+ rc = ((XGetWindowProperty (dpyinfo->display,
+ toplevels[i],
+ dpyinfo->Xatom_wm_state,
+ 0, 2, False, AnyPropertyType,
+ &type, &format, &wmstate_items,
+ &bytes_after, &wmstate_data)
+ == Success)
+ && !x_had_errors_p (dpyinfo->display)
+ && wmstate_data && wmstate_items == 2 && format == 32);
+
+ if (XGetWindowProperty (dpyinfo->display, toplevels[i],
+ dpyinfo->Xatom_net_frame_extents,
+ 0, 4, False, XA_CARDINAL, &type,
+ &format, &extent_items, &bytes_after,
+ &extent_data) == Success
+ && !x_had_errors_p (dpyinfo->display)
+ && extent_data && extent_items >= 4 && format == 32)
+ {
+ frame_extents[0] = ((unsigned long *) extent_data)[0];
+ frame_extents[1] = ((unsigned long *) extent_data)[1];
+ frame_extents[2] = ((unsigned long *) extent_data)[2];
+ frame_extents[3] = ((unsigned long *) extent_data)[3];
+ }
+
+ if (extent_data)
+ XFree (extent_data);
+
+ x_uncatch_errors ();
+#else
+ rc = true;
+
+ attrs_reply
+ = xcb_get_window_attributes_reply (dpyinfo->xcb_connection,
+ window_attribute_cookies[i],
+ &error);
+
+ if (!attrs_reply)
+ {
+ rc = false;
+ free (error);
+ }
+
+ coordinates_reply
+ = xcb_translate_coordinates_reply (dpyinfo->xcb_connection,
+ translate_coordinate_cookies[i],
+ &error);
+
+ if (!coordinates_reply)
+ {
+ rc = false;
+ free (error);
+ }
+
+ property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ get_property_cookies[i],
+ &error);
+
+ if (!property_reply)
+ {
+ rc = false;
+ free (error);
+ }
+
+ /* These requests don't set rc on failure because they aren't
+ required. */
+
+ xm_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xm_property_cookies[i],
+ &error);
+
+ if (!xm_property_reply)
+ free (error);
+
+ extent_property_reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ extent_property_cookies[i],
+ &error);
+
+ if (!extent_property_reply)
+ free (error);
+ else
+ {
+ if (xcb_get_property_value_length (extent_property_reply) == 16
+ && extent_property_reply->format == 32
+ && extent_property_reply->type == XCB_ATOM_CARDINAL)
+ {
+ fextents = xcb_get_property_value (extent_property_reply);
+ frame_extents[0] = fextents[0];
+ frame_extents[1] = fextents[1];
+ frame_extents[2] = fextents[2];
+ frame_extents[3] = fextents[3];
+ }
+
+ free (extent_property_reply);
+ }
+
+ if (property_reply
+ && (xcb_get_property_value_length (property_reply) != 8
+ || property_reply->format != 32))
+ rc = false;
+
+ geometry_reply = xcb_get_geometry_reply (dpyinfo->xcb_connection,
+ get_geometry_cookies[i],
+ &error);
+
+ if (!geometry_reply)
+ {
+ rc = false;
+ free (error);
+ }
+#endif
+
+ if (rc)
+ {
+#ifdef USE_XCB
+ wmstate = (uint32_t *) xcb_get_property_value (property_reply);
+ attrs = *attrs_reply;
+#else
+ wmstate = (unsigned long *) wmstate_data;
+#endif
+
+ tem = xmalloc (sizeof *tem);
+ tem->window = toplevels[i];
+ tem->dpy = dpyinfo->display;
+ tem->frame_extents_left = frame_extents[0];
+ tem->frame_extents_right = frame_extents[1];
+ tem->frame_extents_top = frame_extents[2];
+ tem->frame_extents_bottom = frame_extents[3];
+
+#ifndef USE_XCB
+ tem->x = dest_x;
+ tem->y = dest_y;
+ tem->width = attrs.width + attrs.border_width;
+ tem->height = attrs.height + attrs.border_width;
+ tem->mapped_p = (attrs.map_state != IsUnmapped);
+#else
+ tem->x = (coordinates_reply->dst_x
+ - geometry_reply->border_width);
+ tem->y = (coordinates_reply->dst_y
+ - geometry_reply->border_width);
+ tem->width = (geometry_reply->width
+ + geometry_reply->border_width);
+ tem->height = (geometry_reply->height
+ + geometry_reply->border_width);
+ tem->mapped_p = (attrs.map_state != XCB_MAP_STATE_UNMAPPED);
+#endif
+ tem->next = x_dnd_toplevels;
+ tem->previous_event_mask = attrs.your_event_mask;
+ tem->wm_state = wmstate[0];
+ tem->xm_protocol_style = XM_DRAG_STYLE_NONE;
+
+#ifndef USE_XCB
+ if (!xm_read_drag_receiver_info (dpyinfo, toplevels[i], &xm_info))
+ tem->xm_protocol_style = xm_info.protocol_style;
+#else
+ if (xm_property_reply
+ && xm_property_reply->format == 8
+ && xm_property_reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
+ && xcb_get_property_value_length (xm_property_reply) >= 4)
+ {
+ xmdata = xcb_get_property_value (xm_property_reply);
+
+ if (xmdata[1] <= XM_DRAG_PROTOCOL_VERSION)
+ tem->xm_protocol_style = xmdata[2];
+ }
+#endif
+
+#ifdef HAVE_XSHAPE
+#ifndef USE_XCB
+ tem->border_width = attrs.border_width;
+#else
+ tem->border_width = geometry_reply->border_width;
+#endif
+ tem->n_bounding_rects = -1;
+ tem->n_input_rects = -1;
+
+ if (dpyinfo->xshape_supported_p)
+ {
+ x_ignore_errors_for_next_request (dpyinfo);
+ XShapeSelectInput (dpyinfo->display,
+ toplevels[i],
+ ShapeNotifyMask);
+ x_stop_ignoring_errors (dpyinfo);
+
+#ifndef HAVE_XCB_SHAPE
+ x_catch_errors (dpyinfo->display);
+ rects = XShapeGetRectangles (dpyinfo->display,
+ toplevels[i],
+ ShapeBounding,
+ &count, &ordering);
+ rc = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ /* Does XShapeGetRectangles allocate anything upon an
+ error? */
+ if (!rc)
+ {
+ tem->n_bounding_rects = count;
+ tem->bounding_rects
+ = xmalloc (sizeof *tem->bounding_rects * count);
+ memcpy (tem->bounding_rects, rects,
+ sizeof *tem->bounding_rects * count);
+
+ XFree (rects);
+ }
+#else
+ bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ bounding_rect_cookies[i],
+ &error);
+
+ if (bounding_rect_reply)
+ {
+ bounding_rect_iterator
+ = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
+ tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
+ tem->bounding_rects = xmalloc (tem->n_bounding_rects
+ * sizeof *tem->bounding_rects);
+ tem->n_bounding_rects = 0;
+
+ for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
+ {
+ tem->bounding_rects[tem->n_bounding_rects].x
+ = bounding_rect_iterator.data->x;
+ tem->bounding_rects[tem->n_bounding_rects].y
+ = bounding_rect_iterator.data->y;
+ tem->bounding_rects[tem->n_bounding_rects].width
+ = bounding_rect_iterator.data->width;
+ tem->bounding_rects[tem->n_bounding_rects].height
+ = bounding_rect_iterator.data->height;
+
+ tem->n_bounding_rects++;
+ }
+
+ free (bounding_rect_reply);
+ }
+ else
+ free (error);
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ {
+ input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ input_rect_cookies[i],
+ &error);
+
+ if (input_rect_reply)
+ {
+ input_rect_iterator
+ = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
+ tem->n_input_rects = input_rect_iterator.rem + 1;
+ tem->input_rects = xmalloc (tem->n_input_rects
+ * sizeof *tem->input_rects);
+ tem->n_input_rects = 0;
+
+ for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
+ {
+ tem->input_rects[tem->n_input_rects].x
+ = input_rect_iterator.data->x;
+ tem->input_rects[tem->n_input_rects].y
+ = input_rect_iterator.data->y;
+ tem->input_rects[tem->n_input_rects].width
+ = input_rect_iterator.data->width;
+ tem->input_rects[tem->n_input_rects].height
+ = input_rect_iterator.data->height;
+
+ tem->n_input_rects++;
+ }
+
+ free (input_rect_reply);
+ }
+ else
+ free (error);
+ }
+#else
+#ifdef ShapeInput
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ {
+ x_catch_errors (dpyinfo->display);
+ rects = XShapeGetRectangles (dpyinfo->display,
+ toplevels[i], ShapeInput,
+ &count, &ordering);
+ rc = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ /* Does XShapeGetRectangles allocate anything upon
+ an error? */
+ if (!rc)
+ {
+ tem->n_input_rects = count;
+ tem->input_rects
+ = xmalloc (sizeof *tem->input_rects * count);
+ memcpy (tem->input_rects, rects,
+ sizeof *tem->input_rects * count);
+
+ XFree (rects);
+ }
+ }
+#endif
+#endif
+ }
+
+ /* Handle the common case where the input shape equals the
+ bounding shape. */
+
+ if (tem->n_input_rects != -1
+ && tem->n_bounding_rects == tem->n_input_rects
+ && !memcmp (tem->bounding_rects, tem->input_rects,
+ tem->n_input_rects * sizeof *tem->input_rects))
+ {
+ xfree (tem->input_rects);
+ tem->n_input_rects = -1;
+ }
+
+ /* And the common case where there is no input rect and the
+ bounding rect equals the window dimensions. */
+
+ if (tem->n_input_rects == -1
+ && tem->n_bounding_rects == 1
+#ifdef USE_XCB
+ && tem->bounding_rects[0].width == (geometry_reply->width
+ + geometry_reply->border_width)
+ && tem->bounding_rects[0].height == (geometry_reply->height
+ + geometry_reply->border_width)
+ && tem->bounding_rects[0].x == -geometry_reply->border_width
+ && tem->bounding_rects[0].y == -geometry_reply->border_width
+#else
+ && tem->bounding_rects[0].width == attrs.width + attrs.border_width
+ && tem->bounding_rects[0].height == attrs.height + attrs.border_width
+ && tem->bounding_rects[0].x == -attrs.border_width
+ && tem->bounding_rects[0].y == -attrs.border_width
+#endif
+ )
+ {
+ xfree (tem->bounding_rects);
+ tem->n_bounding_rects = -1;
+ }
+#endif
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSelectInput (dpyinfo->display, toplevels[i],
+ (attrs.your_event_mask
+ | StructureNotifyMask
+ | PropertyChangeMask));
+ x_stop_ignoring_errors (dpyinfo);
+
+ x_dnd_toplevels = tem;
+ }
+ else
+ {
+#ifdef HAVE_XCB_SHAPE
+ if (dpyinfo->xshape_supported_p)
+ {
+ bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ bounding_rect_cookies[i],
+ &error);
+
+ if (bounding_rect_reply)
+ free (bounding_rect_reply);
+ else
+ free (error);
+ }
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+ if (dpyinfo->xshape_supported_p
+ && (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1)))
+ {
+ input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ input_rect_cookies[i],
+ &error);
+
+ if (input_rect_reply)
+ free (input_rect_reply);
+ else
+ free (error);
+ }
+#endif
+ }
+
+#ifdef USE_XCB
+ if (attrs_reply)
+ free (attrs_reply);
+
+ if (coordinates_reply)
+ free (coordinates_reply);
+
+ if (property_reply)
+ free (property_reply);
+
+ if (xm_property_reply)
+ free (xm_property_reply);
+
+ if (geometry_reply)
+ free (geometry_reply);
+#endif
+
+#ifndef USE_XCB
+ if (wmstate_data)
+ {
+ XFree (wmstate_data);
+ wmstate_data = NULL;
+ }
+#endif
+ }
+
+#ifdef USE_XCB
+ SAFE_FREE ();
+#endif
+
+ if (data)
+ XFree (data);
+
+ return 0;
+}
+
+static _Noreturn int
+x_dnd_io_error_handler (Display *display)
+{
+#ifdef USE_GTK
+ emacs_abort ();
+#else
+ siglongjmp (x_dnd_disconnect_handler, 1);
+#endif
+}
+
+#define X_DND_SUPPORTED_VERSION 5
+
+static int x_dnd_get_window_proto (struct x_display_info *, Window);
+static Window x_dnd_get_window_proxy (struct x_display_info *, Window);
+static void x_dnd_update_state (struct x_display_info *, Time);
+
+#ifdef USE_XCB
+static void
+x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
+ Window *proxy_out, int *proto_out)
+{
+ xcb_get_property_cookie_t xdnd_proto_cookie;
+ xcb_get_property_cookie_t xdnd_proxy_cookie;
+ xcb_get_property_reply_t *reply;
+ xcb_generic_error_t *error;
+
+ if (proxy_out)
+ *proxy_out = None;
+
+ if (proto_out)
+ *proto_out = -1;
+
+ if (proxy_out)
+ xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) wdesc,
+ (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
+ XCB_ATOM_WINDOW, 0, 1);
+
+ if (proto_out)
+ xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) wdesc,
+ (xcb_atom_t) dpyinfo->Xatom_XdndAware,
+ XCB_ATOM_ATOM, 0, 1);
+
+ if (proxy_out)
+ {
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xdnd_proxy_cookie, &error);
+
+ if (!reply)
+ free (error);
+ else
+ {
+ if (reply->format == 32
+ && reply->type == XCB_ATOM_WINDOW
+ && (xcb_get_property_value_length (reply) >= 4))
+ *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+ }
+
+ if (proto_out)
+ {
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xdnd_proto_cookie, &error);
+
+ if (!reply)
+ free (error);
+ else
+ {
+ if (reply->format == 32
+ && reply->type == XCB_ATOM_ATOM
+ && (xcb_get_property_value_length (reply) >= 4))
+ *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+ }
+}
+#endif
+
+#ifdef HAVE_XSHAPE
+static bool
+x_dnd_get_target_window_2 (XRectangle *rects, int nrects,
+ int x, int y)
+{
+ int i;
+ XRectangle *tem;
+
+ for (i = 0; i < nrects; ++i)
+ {
+ tem = &rects[i];
+
+ if (x >= tem->x && y >= tem->y
+ && x < tem->x + tem->width
+ && y < tem->y + tem->height)
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+static Window
+x_dnd_get_target_window_1 (struct x_display_info *dpyinfo,
+ int root_x, int root_y, int *motif_out,
+ bool *extents_p)
+{
+ struct x_client_list_window *tem, *chosen = NULL;
+
+ /* Loop through x_dnd_toplevels until we find the toplevel where
+ root_x and root_y are. */
+
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ for (tem = x_dnd_toplevels; tem; tem = tem->next)
+ {
+ if (!tem->mapped_p || tem->wm_state != NormalState)
+ continue;
+
+ /* Test if the coordinates are inside the window's frame
+ extents, and return None in that case. */
+
+ *extents_p = true;
+ if (root_x > tem->x - tem->frame_extents_left
+ && root_x < tem->x
+ && root_y > tem->y - tem->frame_extents_top
+ && root_y < (tem->y + tem->height - 1
+ + tem->frame_extents_bottom))
+ return None;
+
+ if (root_x > tem->x + tem->width
+ && root_x < (tem->x + tem->width - 1
+ + tem->frame_extents_right)
+ && root_y > tem->y - tem->frame_extents_top
+ && root_y < (tem->y + tem->height - 1
+ + tem->frame_extents_bottom))
+ return None;
+
+ if (root_y > tem->y - tem->frame_extents_top
+ && root_y < tem->y
+ && root_x > tem->x - tem->frame_extents_left
+ && root_x < (tem->x + tem->width - 1
+ + tem->frame_extents_right))
+ return None;
+
+ if (root_y > tem->y + tem->height
+ && root_y < (tem->y + tem->height - 1
+ + tem->frame_extents_bottom)
+ && root_x >= tem->x - tem->frame_extents_left
+ && root_x < (tem->x + tem->width - 1
+ + tem->frame_extents_right))
+ return None;
+ *extents_p = false;
+
+ if (root_x >= tem->x && root_y >= tem->y
+ && root_x < tem->x + tem->width
+ && root_y < tem->y + tem->height)
+ {
+#ifdef HAVE_XSHAPE
+ if (tem->n_bounding_rects == -1)
+#endif
+ {
+ chosen = tem;
+ break;
+ }
+
+#ifdef HAVE_XSHAPE
+ if (x_dnd_get_target_window_2 (tem->bounding_rects,
+ tem->n_bounding_rects,
+ tem->border_width + root_x - tem->x,
+ tem->border_width + root_y - tem->y))
+ {
+ if (tem->n_input_rects == -1
+ || x_dnd_get_target_window_2 (tem->input_rects,
+ tem->n_input_rects,
+ tem->border_width + root_x - tem->x,
+ tem->border_width + root_y - tem->y))
+ {
+ chosen = tem;
+ break;
+ }
+ }
+#endif
+ }
+ }
+
+ if (chosen)
+ {
+ *motif_out = (x_dnd_disable_motif_protocol
+ ? XM_DRAG_STYLE_NONE
+ : chosen->xm_protocol_style);
+ return chosen->window;
+ }
+ else
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ return None;
+}
+
+static int
+x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
+ Window window, int *wmstate_out,
+ int *proto_out, int *motif_out,
+ Window *proxy_out)
+{
+#ifndef USE_XCB
+ Atom type;
+ int format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data = NULL;
+ xm_drag_receiver_info xm_info;
+#else
+ xcb_get_property_cookie_t wmstate_cookie;
+ xcb_get_property_cookie_t xdnd_proto_cookie;
+ xcb_get_property_cookie_t xdnd_proxy_cookie;
+ xcb_get_property_cookie_t xm_style_cookie;
+ xcb_get_property_reply_t *reply;
+ xcb_generic_error_t *error;
+ uint8_t *xmdata;
+#endif
+ int rc;
+
+#ifndef USE_XCB
+ x_catch_errors (dpyinfo->display);
+ rc = ((XGetWindowProperty (dpyinfo->display, window,
+ dpyinfo->Xatom_wm_state,
+ 0, 2, False, AnyPropertyType,
+ &type, &format, &nitems,
+ &bytes_after, &data)
+ == Success)
+ && !x_had_errors_p (dpyinfo->display)
+ && data && nitems == 2 && format == 32);
+ x_uncatch_errors ();
+
+ if (rc)
+ *wmstate_out = *(unsigned long *) data;
+
+ *proto_out = x_dnd_get_window_proto (dpyinfo, window);
+
+ if (!xm_read_drag_receiver_info (dpyinfo, window, &xm_info))
+ *motif_out = xm_info.protocol_style;
+ else
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ *proxy_out = x_dnd_get_window_proxy (dpyinfo, window);
+
+ if (data)
+ XFree (data);
+#else
+ rc = true;
+
+ wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) window,
+ (xcb_atom_t) dpyinfo->Xatom_wm_state,
+ XCB_ATOM_ANY, 0, 2);
+ xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) window,
+ (xcb_atom_t) dpyinfo->Xatom_XdndAware,
+ XCB_ATOM_ATOM, 0, 1);
+ xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) window,
+ (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
+ XCB_ATOM_WINDOW, 0, 1);
+ xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) window,
+ (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
+ 0, 4);
+
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ wmstate_cookie, &error);
+
+ if (!reply)
+ free (error), rc = false;
+ else
+ {
+ if (reply->format != 32
+ || xcb_get_property_value_length (reply) != 8)
+ rc = false;
+ else
+ *wmstate_out = *(uint32_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xdnd_proto_cookie, &error);
+
+ *proto_out = -1;
+ if (!reply)
+ free (error);
+ else
+ {
+ if (reply->format == 32
+ && xcb_get_property_value_length (reply) >= 4)
+ *proto_out = *(uint32_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+
+ *proxy_out = None;
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xdnd_proxy_cookie, &error);
+
+ if (!reply)
+ free (error);
+ else
+ {
+ if (reply->format == 32
+ && reply->type == XCB_ATOM_WINDOW
+ && (xcb_get_property_value_length (reply) >= 4))
+ *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
+
+ free (reply);
+ }
+
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ reply = xcb_get_property_reply (dpyinfo->xcb_connection,
+ xm_style_cookie, &error);
+
+ if (!reply)
+ free (error);
+ else
+ {
+ if (reply->format == 8
+ && reply->type == dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO
+ && xcb_get_property_value_length (reply) >= 4)
+ {
+ xmdata = xcb_get_property_value (reply);
+ *motif_out = xmdata[2];
+ }
+
+ free (reply);
+ }
+#endif
+
+ return rc;
+}
+
+/* From the XDND protocol specification:
+
+ Dropping on windows that do not support XDND
+
+ Since middle clicking is the universal shortcut for pasting
+ in X, one can drop data into a window that does not support
+ XDND by:
+
+ 1. After the mouse has been released to trigger the drop,
+ obtain ownership of XA_PRIMARY.
+
+ 2. Send a ButtonPress event and then a ButtonRelease event to
+ the deepest subwindow containing the mouse to simulate a
+ middle click. The times for these events should be the time
+ of the actual button release +1 and +2, respectively. These
+ values will not be used by anybody else, so one can
+ unambiguously recognize the resulting `XConvertSelection'
+ request.
+
+ 3. If a request for XA_PRIMARY arrives bearing the timestamp
+ of either the ButtonPress or the ButtonRelease event, treat
+ it as a request for XdndSelection. Note that you must use
+ the X data types instead of the MIME types in this case.
+ (e.g. XA_STRING instead of text/plain). */
+void
+x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
+ Lisp_Object frame, Lisp_Object value,
+ Lisp_Object targets, Window target_window,
+ int root_x, int root_y, Time before)
+{
+ XEvent event;
+ int dest_x, dest_y;
+ Window child_return, child, owner;
+ Lisp_Object current_value;
+ struct frame *f;
+
+ f = decode_window_system_frame (frame);
+
+ if (NILP (value))
+ return;
+
+ if (!x_dnd_use_unsupported_drop)
+ return;
+
+ event.xbutton.serial = 0;
+ event.xbutton.send_event = True;
+ event.xbutton.display = dpyinfo->display;
+ event.xbutton.root = dpyinfo->root_window;
+ event.xbutton.x_root = root_x;
+ event.xbutton.y_root = root_y;
+
+ x_catch_errors (dpyinfo->display);
+
+ child = dpyinfo->root_window;
+ dest_x = root_x;
+ dest_y = root_y;
+
+ while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
+ child, root_x, root_y, &dest_x, &dest_y,
+ &child_return)
+ && child_return != None)
+ child = child_return;
+
+ x_uncatch_errors ();
+
+ if (!CONSP (value))
+ return;
+
+ current_value = assq_no_quit (QPRIMARY,
+ dpyinfo->terminal->Vselection_alist);
+
+ if (!NILP (current_value))
+ current_value = XCAR (XCDR (current_value));
+
+ x_own_selection (QPRIMARY, current_value, frame,
+ XCAR (XCDR (value)), before);
+
+ owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY);
+
+ /* If we didn't successfully obtain selection ownership, refrain
+ from generating events that will insert something else. */
+
+ if (owner != FRAME_X_WINDOW (f))
+ return;
+
+ event.xbutton.window = child;
+ event.xbutton.subwindow = None;
+ event.xbutton.x = dest_x;
+ event.xbutton.y = dest_y;
+ event.xbutton.state = 0;
+ event.xbutton.button = 2;
+ event.xbutton.same_screen = True;
+
+ dpyinfo->pending_dnd_time = before;
+
+ event.xbutton.type = ButtonPress;
+ event.xbutton.time = before + 1;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, child,
+ True, ButtonPressMask, &event);
+ x_stop_ignoring_errors (dpyinfo);
+
+ event.xbutton.type = ButtonRelease;
+ event.xbutton.time = before + 2;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, child,
+ True, ButtonReleaseMask, &event);
+ x_stop_ignoring_errors (dpyinfo);
+
+ x_dnd_action_symbol = QXdndActionPrivate;
+
+ return;
+}
+
+static void
+x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window,
+ int root_x, int root_y, Time before)
+{
+ Lisp_Object targets, arg;
+ int i;
+ char **atom_names, *name;
+
+ targets = Qnil;
+ atom_names = alloca (sizeof *atom_names * x_dnd_n_targets);
+
+ if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
+ x_dnd_n_targets, atom_names))
+ return;
+
+ for (i = x_dnd_n_targets; i > 0; --i)
+ {
+ targets = Fcons (build_string (atom_names[i - 1]),
+ targets);
+ XFree (atom_names[i - 1]);
+ }
+
+ name = x_get_atom_name (dpyinfo, x_dnd_wanted_action,
+ NULL);
+
+ if (name)
+ {
+ arg = intern (name);
+ xfree (name);
+ }
+ else
+ arg = Qnil;
+
+ x_dnd_run_unsupported_drop_function = true;
+ x_dnd_unsupported_drop_time = before;
+ x_dnd_unsupported_drop_window = target_window;
+ x_dnd_unsupported_drop_data
+ = listn (5, assq_no_quit (QXdndSelection,
+ dpyinfo->terminal->Vselection_alist),
+ targets, arg, make_fixnum (root_x),
+ make_fixnum (root_y));
+
+ x_dnd_waiting_for_finish = true;
+ x_dnd_finish_display = dpyinfo->display;
+}
+
+static Window
+x_dnd_fill_empty_target (int *proto_out, int *motif_out,
+ Window *toplevel_out, bool *was_frame)
+{
+ *proto_out = -1;
+ *motif_out = XM_DRAG_STYLE_NONE;
+ *toplevel_out = None;
+ *was_frame = false;
+
+ return None;
+}
+
+static Window
+x_dnd_get_target_window (struct x_display_info *dpyinfo,
+ int root_x, int root_y, int *proto_out,
+ int *motif_out, Window *toplevel_out,
+ bool *was_frame)
+{
+ Window child_return, child, proxy;
+ int dest_x_return, dest_y_return, rc, proto, motif;
+ int parent_x, parent_y;
+ bool extents_p;
+#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
+ Window overlay_window;
+ XWindowAttributes attrs;
+#endif
+ int wmstate;
+ struct frame *tooltip, *f;
+ bool unrelated;
+
+ child_return = dpyinfo->root_window;
+ dest_x_return = root_x;
+ dest_y_return = root_y;
+
+ proto = -1;
+ *motif_out = XM_DRAG_STYLE_NONE;
+ *toplevel_out = None;
+ *was_frame = false;
+
+ if (x_dnd_use_toplevels)
+ {
+ extents_p = false;
+ child = x_dnd_get_target_window_1 (dpyinfo, root_x,
+ root_y, motif_out,
+ &extents_p);
+
+ if (!x_dnd_allow_current_frame
+ && FRAME_X_WINDOW (x_dnd_frame) == child)
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ f = x_top_window_to_frame (dpyinfo, child);
+
+ *toplevel_out = child;
+
+ if (child != None)
+ {
+ if (f)
+ {
+ *was_frame = true;
+ *proto_out = -1;
+ *motif_out = XM_DRAG_STYLE_NONE;
+
+ return child;
+ }
+
+#ifndef USE_XCB
+ proxy = x_dnd_get_window_proxy (dpyinfo, child);
+#else
+ x_dnd_get_proxy_proto (dpyinfo, child, &proxy, proto_out);
+#endif
+
+ if (proxy != None)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *proto_out = proto;
+ return proxy;
+ }
+ }
+
+#ifndef USE_XCB
+ *proto_out = x_dnd_get_window_proto (dpyinfo, child);
+#endif
+ return child;
+ }
+
+ if (extents_p)
+ {
+ *proto_out = -1;
+ *motif_out = XM_DRAG_STYLE_NONE;
+ *toplevel_out = None;
+
+ return None;
+ }
+
+ /* Then look at the composite overlay window. */
+#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
+ if (dpyinfo->composite_supported_p
+ && (dpyinfo->composite_major > 0
+ || dpyinfo->composite_minor > 2))
+ {
+ if (XGetSelectionOwner (dpyinfo->display,
+ dpyinfo->Xatom_NET_WM_CM_Sn) != None)
+ {
+ x_catch_errors (dpyinfo->display);
+ XGrabServer (dpyinfo->display);
+ overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
+ dpyinfo->root_window);
+ XCompositeReleaseOverlayWindow (dpyinfo->display,
+ dpyinfo->root_window);
+ XUngrabServer (dpyinfo->display);
+
+ if (!x_had_errors_p (dpyinfo->display))
+ {
+ XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
+
+ if (attrs.map_state == IsViewable)
+ {
+ proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
+
+ if (proxy != None)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *proto_out = proto;
+ *toplevel_out = overlay_window;
+ x_uncatch_errors_after_check ();
+
+ return proxy;
+ }
+ }
+ }
+ }
+ x_uncatch_errors_after_check ();
+ }
+ }
+#endif
+
+ /* Now look for an XdndProxy on the root window. */
+
+ proxy = x_dnd_get_window_proxy (dpyinfo, dpyinfo->root_window);
+
+ if (proxy != None)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, dpyinfo->root_window);
+
+ if (proto != -1)
+ {
+ *toplevel_out = dpyinfo->root_window;
+ *proto_out = proto;
+ return proxy;
+ }
+ }
+
+ /* No toplevel was found and the overlay and root windows were
+ not proxies, so return None. */
+ *proto_out = -1;
+ *toplevel_out = dpyinfo->root_window;
+ return None;
+ }
+
+ /* Not strictly necessary, but satisfies GCC. */
+ child = dpyinfo->root_window;
+
+ while (child_return != None)
+ {
+ child = child_return;
+ parent_x = dest_x_return;
+ parent_y = dest_y_return;
+
+ x_catch_errors (dpyinfo->display);
+ rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
+ child_return, root_x, root_y, &dest_x_return,
+ &dest_y_return, &child_return);
+
+ if (x_had_errors_p (dpyinfo->display) || !rc)
+ {
+ x_uncatch_errors_after_check ();
+ break;
+ }
+
+ if (child_return)
+ {
+ /* If child_return is a tooltip frame, look beneath it. We
+ never want to drop anything onto a tooltip frame. */
+
+ tooltip = x_tooltip_window_to_frame (dpyinfo, child_return,
+ &unrelated);
+
+ if (tooltip || unrelated)
+ child_return = x_get_window_below (dpyinfo->display, child_return,
+ parent_x, parent_y, &dest_x_return,
+ &dest_y_return);
+
+ if (!child_return)
+ {
+ x_uncatch_errors ();
+ break;
+ }
+
+ f = x_top_window_to_frame (dpyinfo, child_return);
+
+ if (f)
+ {
+ *proto_out = -1;
+ *motif_out = XM_DRAG_STYLE_NONE;
+ *toplevel_out = child_return;
+ *was_frame = true;
+
+ return child_return;
+ }
+
+ if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return,
+ &wmstate, &proto, &motif,
+ &proxy)
+ /* `proto' and `motif' are set by x_dnd_get_wm_state
+ even if getting the wm state failed. */
+ || proto != -1 || motif != XM_DRAG_STYLE_NONE)
+ {
+ *proto_out = proto;
+ *motif_out = (x_dnd_disable_motif_protocol
+ ? XM_DRAG_STYLE_NONE : motif);
+ *toplevel_out = child_return;
+ x_uncatch_errors ();
+
+ return child_return;
+ }
+
+ if (proxy != None)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *proto_out = proto;
+ *toplevel_out = child_return;
+
+ x_uncatch_errors ();
+ return proxy;
+ }
+ }
+ }
+
+ x_uncatch_errors ();
+ }
+
+#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
+ if (child != dpyinfo->root_window)
+ {
+#endif
+ if (child != None)
+ {
+ proxy = x_dnd_get_window_proxy (dpyinfo, child);
+
+ if (proxy)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *proto_out = proto;
+ *toplevel_out = child;
+ return proxy;
+ }
+ }
+ }
+
+ *proto_out = x_dnd_get_window_proto (dpyinfo, child);
+ return child;
+#if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2)
+ }
+ else if (dpyinfo->composite_supported_p
+ && (dpyinfo->composite_major > 0
+ || dpyinfo->composite_minor > 2))
+ {
+ /* Only do this if a compositing manager is present. */
+ if (XGetSelectionOwner (dpyinfo->display,
+ dpyinfo->Xatom_NET_WM_CM_Sn) != None)
+ {
+ x_catch_errors (dpyinfo->display);
+ XGrabServer (dpyinfo->display);
+ overlay_window = XCompositeGetOverlayWindow (dpyinfo->display,
+ dpyinfo->root_window);
+ XCompositeReleaseOverlayWindow (dpyinfo->display,
+ dpyinfo->root_window);
+ XUngrabServer (dpyinfo->display);
+
+ if (!x_had_errors_p (dpyinfo->display))
+ {
+ XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs);
+
+ if (attrs.map_state == IsViewable)
+ {
+ proxy = x_dnd_get_window_proxy (dpyinfo, overlay_window);
+
+ if (proxy != None)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *proto_out = proto;
+ *toplevel_out = overlay_window;
+ x_uncatch_errors_after_check ();
+
+ return proxy;
+ }
+ }
+ }
+ }
+ x_uncatch_errors_after_check ();
+ }
+ }
+
+ if (child != None)
+ {
+ proxy = x_dnd_get_window_proxy (dpyinfo, child);
+
+ if (proxy)
+ {
+ proto = x_dnd_get_window_proto (dpyinfo, proxy);
+
+ if (proto != -1)
+ {
+ *toplevel_out = child;
+ *proto_out = proto;
+ return proxy;
+ }
+ }
+ }
+
+ *proto_out = x_dnd_get_window_proto (dpyinfo, child);
+ *toplevel_out = child;
+ return child;
+#endif
+}
+
+static Window
+x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
+{
+ int rc, actual_format;
+ unsigned long actual_size, bytes_remaining;
+ unsigned char *tmp_data = NULL;
+ XWindowAttributes attrs;
+ Atom actual_type;
+ Window proxy;
+
+ proxy = None;
+ x_catch_errors (dpyinfo->display);
+ rc = XGetWindowProperty (dpyinfo->display, wdesc,
+ dpyinfo->Xatom_XdndProxy,
+ 0, 1, False, XA_WINDOW,
+ &actual_type, &actual_format,
+ &actual_size, &bytes_remaining,
+ &tmp_data);
+
+ if (!x_had_errors_p (dpyinfo->display)
+ && rc == Success
+ && tmp_data
+ && actual_type == XA_WINDOW
+ && actual_format == 32
+ && actual_size == 1)
+ {
+ proxy = *(Window *) tmp_data;
+
+ /* Verify the proxy window exists. */
+ XGetWindowAttributes (dpyinfo->display, proxy, &attrs);
+
+ if (x_had_errors_p (dpyinfo->display))
+ proxy = None;
+ }
+
+ if (tmp_data)
+ XFree (tmp_data);
+ x_uncatch_errors_after_check ();
+
+ return proxy;
+}
+
+static int
+x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
+{
+ Atom actual, value;
+ unsigned char *tmp_data = NULL;
+ int rc, format;
+ unsigned long n, left;
+ bool had_errors;
+
+ if (wdesc == None || (!x_dnd_allow_current_frame
+ && wdesc == FRAME_OUTER_WINDOW (x_dnd_frame)))
+ return -1;
+
+ x_catch_errors (dpyinfo->display);
+ rc = XGetWindowProperty (dpyinfo->display, wdesc, dpyinfo->Xatom_XdndAware,
+ 0, 1, False, XA_ATOM, &actual, &format, &n, &left,
+ &tmp_data);
+ had_errors = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1
+ || !tmp_data)
+ {
+ if (tmp_data)
+ XFree (tmp_data);
+ return -1;
+ }
+
+ value = (int) *(Atom *) tmp_data;
+ XFree (tmp_data);
+
+ return min (X_DND_SUPPORTED_VERSION, (int) value);
+}
+
+static void
+x_dnd_send_enter (struct frame *f, Window target, int supported)
+{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ int i;
+ XEvent msg;
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type = dpyinfo->Xatom_XdndEnter;
+ msg.xclient.format = 32;
+ msg.xclient.window = target;
+ msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
+ msg.xclient.data.l[1] = (((unsigned int) min (X_DND_SUPPORTED_VERSION,
+ supported) << 24)
+ | (x_dnd_n_targets > 3 ? 1 : 0));
+ msg.xclient.data.l[2] = 0;
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
+
+ for (i = 0; i < min (3, x_dnd_n_targets); ++i)
+ msg.xclient.data.l[i + 2] = x_dnd_targets[i];
+
+ if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists)
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *) x_dnd_targets,
+ x_dnd_n_targets);
+
+ /* Now record that the type list has already been set (if required),
+ so we don't have to set it again. */
+ x_dnd_init_type_lists = true;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static void
+x_dnd_send_position (struct frame *f, Window target, int supported,
+ unsigned short root_x, unsigned short root_y,
+ Time timestamp, Atom action, int button,
+ unsigned state)
+{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ XEvent msg;
+
+ if (target == x_dnd_mouse_rect_target
+ && x_dnd_mouse_rect.width
+ && x_dnd_mouse_rect.height)
+ {
+ if (root_x >= x_dnd_mouse_rect.x
+ && root_x < (x_dnd_mouse_rect.x
+ + x_dnd_mouse_rect.width)
+ && root_y >= x_dnd_mouse_rect.y
+ && root_y < (x_dnd_mouse_rect.y
+ + x_dnd_mouse_rect.height))
+ return;
+ }
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
+ msg.xclient.format = 32;
+ msg.xclient.window = target;
+ msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
+ msg.xclient.data.l[1] = 0;
+
+ if (supported >= 5)
+ {
+ if (button >= 4 && button <= 7)
+ {
+ msg.xclient.data.l[1] |= (1 << 9);
+ msg.xclient.data.l[1] |= (button - 4) << 7;
+ }
+ else if (button)
+ return;
+
+ msg.xclient.data.l[1] |= state & 0x3f;
+ }
+ else if (button)
+ return;
+
+ msg.xclient.data.l[2] = (root_x << 16) | root_y;
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
+
+ if (supported >= 3)
+ msg.xclient.data.l[3] = timestamp;
+
+ if (supported >= 4)
+ msg.xclient.data.l[4] = action;
+
+ if (x_dnd_waiting_for_status_window == target)
+ x_dnd_pending_send_position = msg;
+ else
+ {
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+
+ x_dnd_waiting_for_status_window = target;
+ }
+}
+
+static void
+x_dnd_send_leave (struct frame *f, Window target)
+{
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ XEvent msg;
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type = dpyinfo->Xatom_XdndLeave;
+ msg.xclient.format = 32;
+ msg.xclient.window = target;
+ msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
+ msg.xclient.data.l[1] = 0;
+ msg.xclient.data.l[2] = 0;
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
+
+ x_dnd_waiting_for_status_window = None;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+static bool
+x_dnd_send_drop (struct frame *f, Window target, Time timestamp,
+ int supported)
+{
+ struct x_display_info *dpyinfo;
+ XEvent msg;
+
+ if (x_dnd_action == None)
+ {
+ x_dnd_send_leave (f, target);
+ return false;
+ }
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type = dpyinfo->Xatom_XdndDrop;
+ msg.xclient.format = 32;
+ msg.xclient.window = target;
+ msg.xclient.data.l[0] = FRAME_X_WINDOW (f);
+ msg.xclient.data.l[1] = 0;
+ msg.xclient.data.l[2] = 0;
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
+
+ if (supported >= 1)
+ msg.xclient.data.l[2] = timestamp;
+
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
+ x_stop_ignoring_errors (dpyinfo);
+ return true;
+}
+
+static bool
+x_dnd_do_drop (Window target, int supported)
+{
+ if (x_dnd_waiting_for_status_window != target)
+ return x_dnd_send_drop (x_dnd_frame, target,
+ x_dnd_selection_timestamp, supported);
+
+ x_dnd_need_send_drop = true;
+ x_dnd_send_drop_proto = supported;
+
+ return true;
+}
+
+static void
+x_set_dnd_targets (Atom *targets, int ntargets)
+{
+ if (x_dnd_targets)
+ xfree (x_dnd_targets);
+
+ block_input ();
+ x_dnd_targets = xmalloc (sizeof *targets * ntargets);
+ x_dnd_n_targets = ntargets;
+
+ memcpy (x_dnd_targets, targets,
+ sizeof *targets * ntargets);
+ unblock_input ();
+}
+
+static void
+x_free_dnd_targets (void)
+{
+ if (!x_dnd_targets)
+ return;
+
+ xfree (x_dnd_targets);
+ x_dnd_targets = NULL;
+ x_dnd_n_targets = 0;
+}
+
+/* Clear some Lisp variables after the drop finishes, so they are
+ freed by the GC. */
+
+static void
+x_clear_dnd_variables (void)
+{
+ x_dnd_monitors = Qnil;
+ x_dnd_unsupported_drop_data = Qnil;
+}
+
+static void
+x_free_dnd_toplevels (void)
+{
+ if (!x_dnd_use_toplevels || !x_dnd_toplevels)
+ return;
+
+ /* If the display is deleted, x_dnd_toplevels will already be
+ NULL, so we can always assume the display is alive here. */
+
+ x_dnd_free_toplevels (true);
+}
+
+/* Restore event masks and window properties changed during a
+ drag-and-drop operation, after it finishes. */
+static void
+x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa)
+{
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ /* Restore the old event mask. */
+ XSelectInput (dpyinfo->display, dpyinfo->root_window,
+ wa->your_event_mask);
+#ifdef HAVE_XKB
+ if (dpyinfo->supports_xkb)
+ XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
+ XkbStateNotifyMask, 0);
+#endif
+ /* Delete the Motif drag initiator info if it was set up. */
+ if (x_dnd_motif_setup_p)
+ XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
+ x_dnd_motif_atom);
+
+ /* Remove any type list set as well. */
+ if (x_dnd_init_type_lists && x_dnd_n_targets > 3)
+ XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f),
+ dpyinfo->Xatom_XdndTypeList);
+}
+
+static void
+x_dnd_cleanup_drag_and_drop (void *frame)
+{
+ struct frame *f = frame;
+ xm_drop_start_message dmsg;
+
+ if (!x_dnd_unwind_flag)
+ return;
+
+ if (x_dnd_in_progress)
+ {
+ eassert (x_dnd_frame);
+
+ block_input ();
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ x_dnd_send_leave (x_dnd_frame,
+ x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
+ && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
+ && x_dnd_motif_setup_p)
+ {
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.x = 0;
+ dmsg.y = 0;
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (f);
+
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
+ x_dnd_last_seen_window,
+ FRAME_DISPLAY_INFO (f)->last_user_time);
+ xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
+ x_dnd_last_seen_window, &dmsg);
+ }
+ unblock_input ();
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ }
+
+ x_dnd_waiting_for_finish = false;
+
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
+#ifdef USE_GTK
+ current_hold_quit = NULL;
+#endif
+ x_dnd_return_frame_object = NULL;
+ x_dnd_movement_frame = NULL;
+ x_dnd_frame = NULL;
+
+ x_restore_events_after_dnd (f, &x_dnd_old_window_attrs);
+}
+
+static void
+x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target,
+ unsigned short root_x, unsigned short root_y)
+{
+ struct frame *f;
+ int dest_x, dest_y;
+ Window child_return;
+
+ f = x_top_window_to_frame (dpyinfo, target);
+
+ if (f && XTranslateCoordinates (dpyinfo->display,
+ dpyinfo->root_window,
+ FRAME_X_WINDOW (f),
+ root_x, root_y, &dest_x,
+ &dest_y, &child_return))
+ {
+ x_dnd_movement_frame = f;
+ x_dnd_movement_x = dest_x;
+ x_dnd_movement_y = dest_y;
+
+ return;
+ }
+}
+
+static void
+x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
+ unsigned short root_x, unsigned short root_y,
+ Time timestamp)
+{
+ struct input_event ie;
+ struct frame *f;
+ Lisp_Object lval;
+ char **atom_names;
+ char *name;
+ int win_x, win_y, i;
+ Window dummy;
+
+ if (!x_dnd_allow_current_frame
+ && (FRAME_OUTER_WINDOW (x_dnd_frame)
+ == target))
+ return;
+
+ f = x_top_window_to_frame (dpyinfo, target);
+
+ if (!f)
+ return;
+
+ if (NILP (Vx_dnd_native_test_function))
+ return;
+
+ if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window,
+ FRAME_X_WINDOW (f), root_x, root_y,
+ &win_x, &win_y, &dummy))
+ return;
+
+ /* Emacs can't respond to DND events inside the nested event loop,
+ so when dragging items to itself, call the test function
+ manually. */
+
+ XSETFRAME (lval, f);
+ x_dnd_action = None;
+ x_dnd_action_symbol
+ = safe_call2 (Vx_dnd_native_test_function,
+ Fposn_at_x_y (make_fixnum (win_x),
+ make_fixnum (win_y),
+ lval, Qnil),
+ x_atom_to_symbol (dpyinfo,
+ x_dnd_wanted_action));
+
+ if (!SYMBOLP (x_dnd_action_symbol))
+ return;
+
+ EVENT_INIT (ie);
+
+ ie.kind = DRAG_N_DROP_EVENT;
+ XSETFRAME (ie.frame_or_window, f);
+
+ lval = Qnil;
+ atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
+ name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL);
+
+ if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
+ x_dnd_n_targets, atom_names))
+ {
+ xfree (name);
+ return;
+ }
+
+ for (i = x_dnd_n_targets; i != 0; --i)
+ {
+ lval = Fcons (intern (atom_names[i - 1]), lval);
+ XFree (atom_names[i - 1]);
+ }
+
+ lval = Fcons (assq_no_quit (QXdndSelection,
+ FRAME_TERMINAL (f)->Vselection_alist),
+ lval);
+ lval = Fcons (intern (name), lval);
+ lval = Fcons (QXdndSelection, lval);
+ ie.arg = lval;
+ ie.timestamp = timestamp;
+
+ XSETINT (ie.x, win_x);
+ XSETINT (ie.y, win_y);
+
+ xfree (name);
+ kbd_buffer_store_event (&ie);
+}
/* Flush display of frame F. */
@@ -265,6 +4833,40 @@ x_flush (struct frame *f)
unblock_input ();
}
+#ifdef HAVE_XDBE
+static void
+x_drop_xrender_surfaces (struct frame *f)
+{
+ font_drop_xrender_surfaces (f);
+
+#ifdef HAVE_XRENDER
+ if (f && FRAME_X_DOUBLE_BUFFERED_P (f)
+ && FRAME_X_PICTURE (f) != None)
+ {
+ XRenderFreePicture (FRAME_X_DISPLAY (f),
+ FRAME_X_PICTURE (f));
+ FRAME_X_PICTURE (f) = None;
+ }
+#endif
+}
+#endif
+
+#ifdef HAVE_XRENDER
+void
+x_xr_ensure_picture (struct frame *f)
+{
+ if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
+ {
+ XRenderPictureAttributes attrs;
+ attrs.clip_mask = None;
+ XRenderPictFormat *fmt = FRAME_X_PICTURE_FORMAT (f);
+
+ FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f),
+ FRAME_X_RAW_DRAWABLE (f),
+ fmt, CPClipMask, &attrs);
+ }
+}
+#endif
/* Remove calls to XFlush by defining XFlush to an empty replacement.
Calls to XFlush should be unnecessary because the X output buffer
@@ -308,13 +4910,131 @@ record_event (char *locus, int type)
#endif
-#ifdef USE_CAIRO
+#ifdef HAVE_XINPUT2
+bool
+xi_frame_selected_for (struct frame *f, unsigned long event)
+{
+ XIEventMask *masks;
+ int i;
-#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
-#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
- ((f)->output_data.x->cr_surface_desired_width)
-#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
- ((f)->output_data.x->cr_surface_desired_height)
+ masks = FRAME_X_OUTPUT (f)->xi_masks;
+
+ if (!masks)
+ return false;
+
+ for (i = 0; i < FRAME_X_OUTPUT (f)->num_xi_masks; ++i)
+ {
+ if (masks[i].mask_len >= XIMaskLen (event)
+ && XIMaskIsSet (masks[i].mask, event))
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+static void
+x_toolkit_position (struct frame *f, int x, int y,
+ bool *menu_bar_p, bool *tool_bar_p)
+{
+#ifdef USE_GTK
+ GdkRectangle test_rect;
+ int scale;
+
+ y += (FRAME_MENUBAR_HEIGHT (f)
+ + FRAME_TOOLBAR_TOP_HEIGHT (f));
+ x += FRAME_TOOLBAR_LEFT_WIDTH (f);
+
+ if (FRAME_EXTERNAL_MENU_BAR (f))
+ *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
+ && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
+
+ if (FRAME_X_OUTPUT (f)->toolbar_widget)
+ {
+ scale = xg_get_scale (f);
+ test_rect.x = x / scale;
+ test_rect.y = y / scale;
+ test_rect.width = 1;
+ test_rect.height = 1;
+
+ *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
+ &test_rect, NULL);
+ }
+#elif defined USE_X_TOOLKIT
+ *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f)
+ && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f)));
+#else
+ *menu_bar_p = (WINDOWP (f->menu_bar_window)
+ && (x > 0 && x < FRAME_PIXEL_WIDTH (f)
+ && (y > 0 && y < FRAME_MENU_BAR_HEIGHT (f))));
+#endif
+}
+
+static void
+x_update_opaque_region (struct frame *f, XEvent *configure)
+{
+ unsigned long opaque_region[] = {0, 0,
+ (configure
+ ? configure->xconfigure.width
+ : FRAME_PIXEL_WIDTH (f)),
+ (configure
+ ? configure->xconfigure.height
+ : FRAME_PIXEL_HEIGHT (f))};
+#ifdef HAVE_GTK3
+ GObjectClass *object_class;
+ GtkWidgetClass *class;
+#endif
+
+ if (!FRAME_DISPLAY_INFO (f)->alpha_bits)
+ return;
+
+ block_input ();
+ if (f->alpha_background < 1.0)
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ NULL, 0);
+#ifndef HAVE_GTK3
+ else
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &opaque_region, 4);
+#else
+ else if (FRAME_TOOLTIP_P (f))
+ XChangeProperty (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &opaque_region, 4);
+ else
+ {
+ /* This causes child frames to not update correctly for an
+ unknown reason. (bug#55779) */
+ if (!FRAME_PARENT_FRAME (f))
+ {
+ object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f));
+ class = GTK_WIDGET_CLASS (object_class);
+
+ if (class->style_updated)
+ class->style_updated (FRAME_GTK_OUTER_WIDGET (f));
+ }
+ }
+#endif
+ unblock_input ();
+}
+
+
+#if defined USE_CAIRO || defined HAVE_XRENDER
+static int
+x_gc_free_ext_data_private (XExtData *extension)
+{
+ xfree (extension->private_data);
+
+ return 0;
+}
static struct x_gc_ext_data *
x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
@@ -335,6 +5055,7 @@ x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
ext_data = xzalloc (sizeof (*ext_data));
ext_data->number = dpyinfo->ext_codes->extension;
ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
+ ext_data->free_private = x_gc_free_ext_data_private;
XAddToExtensionList (head, ext_data);
}
}
@@ -348,16 +5069,62 @@ x_extension_initialize (struct x_display_info *dpyinfo)
dpyinfo->ext_codes = ext_codes;
}
+#endif
+
+#ifdef USE_CAIRO
+
+#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
+#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
+ ((f)->output_data.x->cr_surface_desired_width)
+#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
+ ((f)->output_data.x->cr_surface_desired_height)
#endif /* HAVE_CAIRO */
#ifdef HAVE_XINPUT2
-/* Free all XI2 devices on dpyinfo. */
+/* Convert XI2 button state IN to a standard X button modifier
+ mask, and place it in OUT. */
+static void
+xi_convert_button_state (XIButtonState *in, unsigned int *out)
+{
+ int i;
+
+ if (in->mask_len)
+ {
+ for (i = 1; i <= 8; ++i)
+ {
+ if (XIMaskIsSet (in->mask, i))
+ *out |= (Button1Mask << (i - 1));
+ }
+ }
+}
+
+/* Return the modifier state in XEV as a standard X modifier mask. */
+
+#ifdef USE_GTK
+static
+#endif
+unsigned int
+xi_convert_event_state (XIDeviceEvent *xev)
+{
+ unsigned int mods, buttons;
+
+ mods = xev->mods.effective;
+ buttons = 0;
+
+ xi_convert_button_state (&xev->buttons, &buttons);
+
+ return mods | buttons;
+}
+
+/* Free all XI2 devices on DPYINFO. */
static void
x_free_xi_devices (struct x_display_info *dpyinfo)
{
+#ifdef HAVE_XINPUT2_2
struct xi_touch_point_t *tem, *last;
+#endif
block_input ();
@@ -365,10 +5132,11 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
{
- XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
- CurrentTime);
+#ifdef HAVE_XINPUT2_1
xfree (dpyinfo->devices[i].valuators);
+#endif
+#ifdef HAVE_XINPUT2_2
tem = dpyinfo->devices[i].touchpoints;
while (tem)
{
@@ -376,6 +5144,7 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
tem = tem->next;
xfree (last);
}
+#endif
}
xfree (dpyinfo->devices);
@@ -386,6 +5155,130 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
unblock_input ();
}
+#ifdef HAVE_XINPUT2_1
+struct xi_known_valuator
+{
+ /* The current value of this valuator. */
+ double current_value;
+
+ /* The number of the valuator. */
+ int number;
+
+ /* The next valuator whose value we already know. */
+ struct xi_known_valuator *next;
+};
+#endif
+
+static void
+xi_populate_device_from_info (struct xi_device_t *xi_device,
+ XIDeviceInfo *device)
+{
+#ifdef HAVE_XINPUT2_1
+ struct xi_scroll_valuator_t *valuator;
+ struct xi_known_valuator *values, *tem;
+ int actual_valuator_count;
+ XIScrollClassInfo *info;
+ XIValuatorClassInfo *val_info;
+#endif
+ int c;
+#ifdef HAVE_XINPUT2_2
+ XITouchClassInfo *touch_info;
+#endif
+
+#ifdef HAVE_XINPUT2_1
+ USE_SAFE_ALLOCA;
+#endif
+
+ xi_device->device_id = device->deviceid;
+ xi_device->grab = 0;
+
+#ifdef HAVE_XINPUT2_1
+ actual_valuator_count = 0;
+ xi_device->valuators = xmalloc (sizeof *xi_device->valuators
+ * device->num_classes);
+ values = NULL;
+#endif
+#ifdef HAVE_XINPUT2_2
+ xi_device->touchpoints = NULL;
+#endif
+
+ xi_device->use = device->use;
+#ifdef HAVE_XINPUT2_2
+ xi_device->direct_p = false;
+#endif
+ xi_device->name = build_string (device->name);
+
+ for (c = 0; c < device->num_classes; ++c)
+ {
+ switch (device->classes[c]->type)
+ {
+#ifdef HAVE_XINPUT2_1
+ case XIScrollClass:
+ {
+ info = (XIScrollClassInfo *) device->classes[c];
+
+ valuator = &xi_device->valuators[actual_valuator_count++];
+ valuator->horizontal
+ = (info->scroll_type == XIScrollTypeHorizontal);
+ valuator->invalid_p = true;
+ valuator->emacs_value = DBL_MIN;
+ valuator->increment = info->increment;
+ valuator->number = info->number;
+ valuator->pending_enter_reset = false;
+
+ break;
+ }
+
+ case XIValuatorClass:
+ {
+ val_info = (XIValuatorClassInfo *) device->classes[c];
+ tem = SAFE_ALLOCA (sizeof *tem);
+
+ tem->next = values;
+ tem->number = val_info->number;
+ tem->current_value = val_info->value;
+
+ values = tem;
+ break;
+ }
+#endif
+
+#ifdef HAVE_XINPUT2_2
+ case XITouchClass:
+ {
+ touch_info = (XITouchClassInfo *) device->classes[c];
+ xi_device->direct_p = touch_info->mode == XIDirectTouch;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+
+#ifdef HAVE_XINPUT2_1
+ xi_device->scroll_valuator_count = actual_valuator_count;
+
+ /* Now look through all the valuators whose values are already known
+ and populate our client-side records with their current
+ values. */
+
+ for (tem = values; values; values = values->next)
+ {
+ for (c = 0; c < xi_device->scroll_valuator_count; ++c)
+ {
+ if (xi_device->valuators[c].number == tem->number)
+ {
+ xi_device->valuators[c].invalid_p = false;
+ xi_device->valuators[c].current_value = tem->current_value;
+ xi_device->valuators[c].pending_enter_reset = true;
+ }
+ }
+ }
+
+ SAFE_FREE ();
+#endif
+}
+
/* The code below handles the tracking of scroll valuators on XInput
2, in order to support scroll wheels that report information more
granular than a screen line.
@@ -412,12 +5305,18 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
/* Setup valuator tracking for XI2 master devices on
DPYINFO->display. */
+/* This function's name is a misnomer: these days, it keeps a
+ client-side record of all devices, which includes basic information
+ about the device and also touchscreen tracking information, instead
+ of just scroll valuators. */
+
static void
x_init_master_valuators (struct x_display_info *dpyinfo)
{
- int ndevices;
+ int ndevices, actual_devices;
XIDeviceInfo *infos;
+ actual_devices = 0;
block_input ();
x_free_xi_devices (dpyinfo);
infos = XIQueryDevice (dpyinfo->display,
@@ -431,67 +5330,13 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
return;
}
- int actual_devices = 0;
dpyinfo->devices = xmalloc (sizeof *dpyinfo->devices * ndevices);
for (int i = 0; i < ndevices; ++i)
{
- XIDeviceInfo *device = &infos[i];
-
- if (device->enabled)
- {
- int actual_valuator_count = 0;
- struct xi_device_t *xi_device = &dpyinfo->devices[actual_devices++];
- xi_device->device_id = device->deviceid;
- xi_device->grab = 0;
- xi_device->valuators =
- xmalloc (sizeof *xi_device->valuators * device->num_classes);
- xi_device->touchpoints = NULL;
- xi_device->master_p = (device->use == XIMasterKeyboard
- || device->use == XIMasterPointer);
- xi_device->direct_p = false;
-
- for (int c = 0; c < device->num_classes; ++c)
- {
- switch (device->classes[c]->type)
- {
-#ifdef XIScrollClass /* XInput 2.1 */
- case XIScrollClass:
- {
- XIScrollClassInfo *info =
- (XIScrollClassInfo *) device->classes[c];
- struct xi_scroll_valuator_t *valuator;
-
- if (xi_device->master_p)
- {
- valuator = &xi_device->valuators[actual_valuator_count++];
- valuator->horizontal
- = (info->scroll_type == XIScrollTypeHorizontal);
- valuator->invalid_p = true;
- valuator->emacs_value = DBL_MIN;
- valuator->increment = info->increment;
- valuator->number = info->number;
- }
-
- break;
- }
-#endif
-#ifdef XITouchClass /* XInput 2.2 */
- case XITouchClass:
- {
- XITouchClassInfo *info;
-
- info = (XITouchClassInfo *) device->classes[c];
- xi_device->direct_p = info->mode == XIDirectTouch;
- }
-#endif
- default:
- break;
- }
- }
-
- xi_device->scroll_valuator_count = actual_valuator_count;
- }
+ if (infos[i].enabled)
+ xi_populate_device_from_info (&dpyinfo->devices[actual_devices++],
+ &infos[i]);
}
dpyinfo->num_devices = actual_devices;
@@ -499,63 +5344,58 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
unblock_input ();
}
+#ifdef HAVE_XINPUT2_1
/* Return the delta of the scroll valuator VALUATOR_NUMBER under
- DEVICE_ID in the display DPYINFO with VALUE. The valuator's
- valuator will be set to VALUE afterwards. In case no scroll
- valuator is found, or if the valuator state is invalid (see the
- comment under XI_Enter in handle_one_xevent), or if device_id is
- not known to Emacs, DBL_MAX is returned. Otherwise, the valuator
- is returned in VALUATOR_RETURN. */
+ DEVICE in the display DPYINFO with VALUE. The valuator's valuator
+ will be set to VALUE afterwards. In case no scroll valuator is
+ found, or if the valuator state is invalid (see the comment under
+ XI_Enter in handle_one_xevent). Otherwise, the valuator is
+ returned in VALUATOR_RETURN. */
static double
-x_get_scroll_valuator_delta (struct x_display_info *dpyinfo, int device_id,
+x_get_scroll_valuator_delta (struct x_display_info *dpyinfo,
+ struct xi_device_t *device,
int valuator_number, double value,
struct xi_scroll_valuator_t **valuator_return)
{
- block_input ();
+ struct xi_scroll_valuator_t *sv;
+ double delta;
+ int i;
- for (int i = 0; i < dpyinfo->num_devices; ++i)
+ for (i = 0; i < device->scroll_valuator_count; ++i)
{
- struct xi_device_t *device = &dpyinfo->devices[i];
+ sv = &device->valuators[i];
- if (device->device_id == device_id && device->master_p)
+ if (sv->number == valuator_number)
{
- for (int j = 0; j < device->scroll_valuator_count; ++j)
- {
- struct xi_scroll_valuator_t *sv = &device->valuators[j];
+ *valuator_return = sv;
- if (sv->number == valuator_number)
- {
- if (sv->invalid_p)
- {
- sv->current_value = value;
- sv->invalid_p = false;
- *valuator_return = sv;
+ if (sv->increment == 0)
+ return DBL_MAX;
- unblock_input ();
- return DBL_MAX;
- }
- else
- {
- double delta = (sv->current_value - value) / sv->increment;
- sv->current_value = value;
- *valuator_return = sv;
+ if (sv->invalid_p)
+ {
+ sv->current_value = value;
+ sv->invalid_p = false;
- unblock_input ();
- return delta;
- }
- }
+ return DBL_MAX;
}
+ else
+ {
+ delta = (sv->current_value - value) / sv->increment;
+ sv->current_value = value;
- unblock_input ();
- return DBL_MAX;
+ return delta;
+ }
}
}
- unblock_input ();
+ *valuator_return = NULL;
return DBL_MAX;
}
-static struct xi_device_t *
+#endif
+
+struct xi_device_t *
xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
@@ -567,7 +5407,7 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
return NULL;
}
-#ifdef XI_TouchBegin
+#ifdef HAVE_XINPUT2_2
static void
xi_link_touch_point (struct xi_device_t *device,
@@ -622,15 +5462,18 @@ xi_find_touch_point (struct xi_device_t *device, int detail)
return NULL;
}
-#endif /* XI_TouchBegin */
+#endif /* HAVE_XINPUT2_2 */
+
+#ifdef HAVE_XINPUT2_1
static void
-xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
+xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id,
+ bool pending_only)
{
struct xi_device_t *device = xi_device_from_id (dpyinfo, id);
struct xi_scroll_valuator_t *valuator;
- if (!device || !device->master_p)
+ if (!device)
return;
if (!device->scroll_valuator_count)
@@ -639,6 +5482,11 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
for (int i = 0; i < device->scroll_valuator_count; ++i)
{
valuator = &device->valuators[i];
+
+ if (pending_only && !valuator->pending_enter_reset)
+ continue;
+
+ valuator->pending_enter_reset = false;
valuator->invalid_p = true;
valuator->emacs_value = 0.0;
}
@@ -646,6 +5494,8 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
return;
}
+#endif /* HAVE_XINPUT2_1 */
+
#endif
#ifdef USE_CAIRO
@@ -700,11 +5550,19 @@ x_begin_cr_clip (struct frame *f, GC gc)
{
int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
- cairo_surface_t *surface
- = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
- FRAME_X_RAW_DRAWABLE (f),
- FRAME_X_VISUAL (f),
- width, height);
+ cairo_surface_t *surface;
+#ifdef USE_CAIRO_XCB_SURFACE
+ if (FRAME_DISPLAY_INFO (f)->xcb_visual)
+ surface = cairo_xcb_surface_create (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ (xcb_drawable_t) FRAME_X_RAW_DRAWABLE (f),
+ FRAME_DISPLAY_INFO (f)->xcb_visual,
+ width, height);
+ else
+#endif
+ surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
+ FRAME_X_RAW_DRAWABLE (f),
+ FRAME_X_VISUAL (f),
+ width, height);
cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
cairo_surface_destroy (surface);
@@ -724,29 +5582,65 @@ x_end_cr_clip (struct frame *f)
}
void
-x_set_cr_source_with_gc_foreground (struct frame *f, GC gc)
+x_set_cr_source_with_gc_foreground (struct frame *f, GC gc,
+ bool respect_alpha_background)
{
XGCValues xgcv;
XColor color;
+ unsigned int depth;
XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
color.pixel = xgcv.foreground;
x_query_colors (f, &color, 1);
- cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
- color.green / 65535.0, color.blue / 65535.0);
+ depth = FRAME_DISPLAY_INFO (f)->n_planes;
+
+ if (f->alpha_background < 1.0 && depth == 32
+ && respect_alpha_background)
+ {
+ cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0,
+ f->alpha_background);
+
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
+ }
+ else
+ {
+ cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0);
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
+ }
}
void
-x_set_cr_source_with_gc_background (struct frame *f, GC gc)
+x_set_cr_source_with_gc_background (struct frame *f, GC gc,
+ bool respect_alpha_background)
{
XGCValues xgcv;
XColor color;
+ unsigned int depth;
XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
color.pixel = xgcv.background;
+
x_query_colors (f, &color, 1);
- cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
- color.green / 65535.0, color.blue / 65535.0);
+
+ depth = FRAME_DISPLAY_INFO (f)->n_planes;
+
+ if (f->alpha_background < 1.0 && depth == 32
+ && respect_alpha_background)
+ {
+ cairo_set_source_rgba (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0,
+ f->alpha_background);
+
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
+ }
+ else
+ {
+ cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
+ color.green / 65535.0, color.blue / 65535.0);
+ cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
+ }
}
static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
@@ -773,6 +5667,9 @@ x_try_cr_xlib_drawable (struct frame *f, GC gc)
switch (cairo_surface_get_type (surface))
{
case CAIRO_SURFACE_TYPE_XLIB:
+#ifdef USE_CAIRO_XCB_SURFACE
+ case CAIRO_SURFACE_TYPE_XCB:
+#endif
cairo_surface_flush (surface);
return true;
@@ -928,7 +5825,7 @@ x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
cairo_rectangle (cr, dest_x, dest_y, width, height);
else
{
- x_set_cr_source_with_gc_background (f, gc);
+ x_set_cr_source_with_gc_background (f, gc, false);
cairo_rectangle (cr, dest_x, dest_y, width, height);
cairo_fill_preserve (cr);
}
@@ -945,7 +5842,7 @@ x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image,
}
else
{
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, false);
cairo_clip (cr);
cairo_mask (cr, image);
}
@@ -996,7 +5893,7 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
int width, height;
void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
Lisp_Object acc = Qnil;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qredisplay_dont_pause, Qt);
redisplay_preserve_echo_area (31);
@@ -1082,11 +5979,37 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
#endif /* USE_CAIRO */
+#if defined HAVE_XRENDER
+void
+x_xr_apply_ext_clip (struct frame *f, GC gc)
+{
+ eassert (FRAME_X_PICTURE (f) != None);
+
+ struct x_gc_ext_data *data = x_gc_get_ext_data (f, gc, 1);
+
+ if (data->n_clip_rects)
+ XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (f),
+ FRAME_X_PICTURE (f),
+ 0, 0, data->clip_rects,
+ data->n_clip_rects);
+}
+
+void
+x_xr_reset_ext_clip (struct frame *f)
+{
+ XRenderPictureAttributes attrs = { .clip_mask = None };
+
+ XRenderChangePicture (FRAME_X_DISPLAY (f),
+ FRAME_X_PICTURE (f),
+ CPClipMask, &attrs);
+}
+#endif
+
static void
x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
{
XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
-#ifdef USE_CAIRO
+#if defined USE_CAIRO || defined HAVE_XRENDER
eassert (n >= 0 && n <= MAX_CLIP_RECTS);
{
@@ -1102,7 +6025,7 @@ static void
x_reset_clip_rectangles (struct frame *f, GC gc)
{
XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
-#ifdef USE_CAIRO
+#if defined USE_CAIRO || defined HAVE_XRENDER
{
struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
@@ -1112,8 +6035,71 @@ x_reset_clip_rectangles (struct frame *f, GC gc)
#endif
}
+#ifdef HAVE_XRENDER
+# if !defined USE_CAIRO && (RENDER_MAJOR > 0 || RENDER_MINOR >= 2)
static void
-x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
+x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor *color,
+ bool apply_alpha_background)
+{
+ XGCValues xgcv;
+ XColor xc;
+
+ XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
+ xc.pixel = xgcv.foreground;
+ x_query_colors (f, &xc, 1);
+
+ color->alpha = (apply_alpha_background
+ ? 65535 * f->alpha_background
+ : 65535);
+
+ if (color->alpha == 65535)
+ {
+ color->red = xc.red;
+ color->blue = xc.blue;
+ color->green = xc.green;
+ }
+ else
+ {
+ color->red = (xc.red * color->alpha) / 65535;
+ color->blue = (xc.blue * color->alpha) / 65535;
+ color->green = (xc.green * color->alpha) / 65535;
+ }
+}
+# endif
+
+void
+x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor *color,
+ bool apply_alpha_background)
+{
+ XGCValues xgcv;
+ XColor xc;
+
+ XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
+ xc.pixel = xgcv.background;
+ x_query_colors (f, &xc, 1);
+
+ color->alpha = (apply_alpha_background
+ ? 65535 * f->alpha_background
+ : 65535);
+
+ if (color->alpha == 65535)
+ {
+ color->red = xc.red;
+ color->blue = xc.blue;
+ color->green = xc.green;
+ }
+ else
+ {
+ color->red = (xc.red * color->alpha) / 65535;
+ color->blue = (xc.blue * color->alpha) / 65535;
+ color->green = (xc.green * color->alpha) / 65535;
+ }
+}
+#endif
+
+static void
+x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
+ bool respect_alpha_background)
{
#ifdef USE_CAIRO
Display *dpy = FRAME_X_DISPLAY (f);
@@ -1129,7 +6115,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
regarded as Pixmap of unspecified size filled with ones. */
|| (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3))))
{
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
}
@@ -1137,25 +6123,139 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
{
eassert (xgcv.fill_style == FillOpaqueStippled);
eassert (xgcv.stipple != None);
- x_set_cr_source_with_gc_background (f, gc);
+ x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
cairo_rectangle (cr, x, y, width, height);
cairo_fill_preserve (cr);
cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple);
if (pattern)
{
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, respect_alpha_background);
cairo_clip (cr);
cairo_mask (cr, pattern);
}
}
x_end_cr_clip (f);
#else
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ if (respect_alpha_background
+ && f->alpha_background != 1.0
+ && FRAME_DISPLAY_INFO (f)->alpha_bits
+ && FRAME_CHECK_XR_VERSION (f, 0, 2))
+ {
+ x_xr_ensure_picture (f);
+
+ if (FRAME_X_PICTURE (f) != None)
+ {
+ XRenderColor xc;
+
+#if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
+ XGCValues xgcv;
+ XRenderPictureAttributes attrs;
+ XRenderColor alpha;
+ Picture stipple, fill;
+#endif
+
+ x_xr_apply_ext_clip (f, gc);
+
+#if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10)
+ XGetGCValues (FRAME_X_DISPLAY (f),
+ gc, GCFillStyle | GCStipple, &xgcv);
+
+ if (xgcv.fill_style == FillOpaqueStippled
+ && FRAME_CHECK_XR_VERSION (f, 0, 10))
+ {
+ x_xrender_color_from_gc_background (f, gc, &alpha, true);
+ x_xrender_color_from_gc_foreground (f, gc, &xc, true);
+ attrs.repeat = RepeatNormal;
+
+ stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f),
+ xgcv.stipple,
+ XRenderFindStandardFormat (FRAME_X_DISPLAY (f),
+ PictStandardA1),
+ CPRepeat, &attrs);
+
+ XRenderFillRectangle (FRAME_X_DISPLAY (f), PictOpSrc,
+ FRAME_X_PICTURE (f),
+ &alpha, x, y, width, height);
+
+ fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), &xc);
+
+ XRenderComposite (FRAME_X_DISPLAY (f), PictOpOver, fill, stipple,
+ FRAME_X_PICTURE (f), 0, 0, x, y, x, y, width, height);
+
+ XRenderFreePicture (FRAME_X_DISPLAY (f), stipple);
+ XRenderFreePicture (FRAME_X_DISPLAY (f), fill);
+ }
+ else
+#endif
+ {
+ x_xrender_color_from_gc_foreground (f, gc, &xc, true);
+ XRenderFillRectangle (FRAME_X_DISPLAY (f),
+ PictOpSrc, FRAME_X_PICTURE (f),
+ &xc, x, y, width, height);
+ }
+ x_xr_reset_ext_clip (f);
+ x_mark_frame_dirty (f);
+
+ return;
+ }
+ }
+#endif
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
gc, x, y, width, height);
#endif
}
+
+static void
+x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height,
+ bool respect_alpha_background)
+{
+#ifdef USE_CAIRO
+ cairo_t *cr;
+
+ cr = x_begin_cr_clip (f, gc);
+ x_set_cr_source_with_gc_background (f, gc, respect_alpha_background);
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+ x_end_cr_clip (f);
+#else
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ if (respect_alpha_background
+ && f->alpha_background != 1.0
+ && FRAME_DISPLAY_INFO (f)->alpha_bits
+ && FRAME_CHECK_XR_VERSION (f, 0, 2))
+ {
+ x_xr_ensure_picture (f);
+
+ if (FRAME_X_PICTURE (f) != None)
+ {
+ XRenderColor xc;
+
+ x_xr_apply_ext_clip (f, gc);
+ x_xrender_color_from_gc_background (f, gc, &xc, true);
+ XRenderFillRectangle (FRAME_X_DISPLAY (f),
+ PictOpSrc, FRAME_X_PICTURE (f),
+ &xc, x, y, width, height);
+ x_xr_reset_ext_clip (f);
+ x_mark_frame_dirty (f);
+
+ return;
+ }
+ }
+#endif
+
+ XGCValues xgcv;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
+ XSetForeground (dpy, gc, xgcv.background);
+ XFillRectangle (dpy, FRAME_X_DRAWABLE (f),
+ gc, x, y, width, height);
+ XSetForeground (dpy, gc, xgcv.foreground);
+#endif
+}
+
static void
x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
{
@@ -1163,7 +6263,7 @@ x_draw_rectangle (struct frame *f, GC gc, int x, int y, int width, int height)
cairo_t *cr;
cr = x_begin_cr_clip (f, gc);
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, false);
cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
cairo_set_line_width (cr, 1);
cairo_stroke (cr);
@@ -1181,15 +6281,24 @@ x_clear_window (struct frame *f)
cairo_t *cr;
cr = x_begin_cr_clip (f, NULL);
- x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
+ x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc, true);
cairo_paint (cr);
x_end_cr_clip (f);
#else
- if (FRAME_X_DOUBLE_BUFFERED_P (f))
- x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
+#ifndef USE_GTK
+ if (f->alpha_background != 1.0
+#ifdef HAVE_XDBE
+ || FRAME_X_DOUBLE_BUFFERED_P (f)
+#endif
+ )
+#endif
+ x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f));
+#ifndef USE_GTK
else
XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif
+#endif
}
#ifdef USE_CAIRO
@@ -1200,7 +6309,7 @@ x_fill_trapezoid_for_relief (struct frame *f, GC gc, int x, int y,
cairo_t *cr;
cr = x_begin_cr_clip (f, gc);
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, false);
cairo_move_to (cr, top_p ? x : x + height, y);
cairo_line_to (cr, x, y + height);
cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
@@ -1227,7 +6336,7 @@ x_erase_corners_for_relief (struct frame *f, GC gc, int x, int y,
int i;
cr = x_begin_cr_clip (f, gc);
- x_set_cr_source_with_gc_background (f, gc);
+ x_set_cr_source_with_gc_background (f, gc, false);
for (i = 0; i < CORNER_LAST; i++)
if (corners & (1 << i))
{
@@ -1260,7 +6369,7 @@ x_draw_horizontal_wave (struct frame *f, GC gc, int x, int y,
int xoffset, n;
cr = x_begin_cr_clip (f, gc);
- x_set_cr_source_with_gc_foreground (f, gc);
+ x_set_cr_source_with_gc_foreground (f, gc, false);
cairo_rectangle (cr, x, y, width, height);
cairo_clip (cr);
@@ -1364,8 +6473,6 @@ x_set_frame_alpha (struct frame *f)
opac = alpha * OPAQUE;
- x_catch_errors (dpy);
-
/* If there is a parent from the window manager, put the property there
also, to work around broken window managers that fail to do that.
Do this unconditionally as this function is called on reparent when
@@ -1374,40 +6481,23 @@ x_set_frame_alpha (struct frame *f)
if (!FRAME_PARENT_FRAME (f))
{
parent = x_find_topmost_parent (f);
+
if (parent != None)
- XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *) &opac, 1);
+ {
+ x_ignore_errors_for_next_request (dpyinfo);
+ XChangeProperty (dpy, parent,
+ dpyinfo->Xatom_net_wm_window_opacity,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &opac, 1);
+ x_stop_ignoring_errors (dpyinfo);
+ }
}
- /* return unless necessary */
- {
- unsigned char *data;
- Atom actual;
- int rc, format;
- unsigned long n, left;
-
- rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
- 0, 1, False, XA_CARDINAL,
- &actual, &format, &n, &left,
- &data);
-
- if (rc == Success && actual != None)
- {
- unsigned long value = *(unsigned long *)data;
- XFree (data);
- if (value == opac)
- {
- x_uncatch_errors ();
- return;
- }
- }
- }
-
+ x_ignore_errors_for_next_request (dpyinfo);
XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) &opac, 1);
- x_uncatch_errors ();
+ x_stop_ignoring_errors (dpyinfo);
}
/***********************************************************************
@@ -1440,7 +6530,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
face->foreground);
#ifdef USE_CAIRO
- x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
+ x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0, false);
#else
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
f->output_data.x->normal_gc, x, y0, x, y1);
@@ -1473,13 +6563,13 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
{
XSetForeground (display, f->output_data.x->normal_gc, color_first);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0, y0, 1, y1 - y0);
+ x0, y0, 1, y1 - y0, false);
XSetForeground (display, f->output_data.x->normal_gc, color);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+ x0 + 1, y0, x1 - x0 - 2, y1 - y0, false);
XSetForeground (display, f->output_data.x->normal_gc, color_last);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x1 - 1, y0, 1, y1 - y0);
+ x1 - 1, y0, 1, y1 - y0, false);
}
else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
/* A horizontal divider, at least three pixels high: Draw first and
@@ -1487,13 +6577,13 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
{
XSetForeground (display, f->output_data.x->normal_gc, color_first);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0, y0, x1 - x0, 1);
+ x0, y0, x1 - x0, 1, false);
XSetForeground (display, f->output_data.x->normal_gc, color);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+ x0, y0 + 1, x1 - x0, y1 - y0 - 2, false);
XSetForeground (display, f->output_data.x->normal_gc, color_last);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0, y1 - 1, x1 - x0, 1);
+ x0, y1 - 1, x1 - x0, 1, false);
}
else
{
@@ -1501,20 +6591,22 @@ x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
differently. */
XSetForeground (display, f->output_data.x->normal_gc, color);
x_fill_rectangle (f, f->output_data.x->normal_gc,
- x0, y0, x1 - x0, y1 - y0);
+ x0, y0, x1 - x0, y1 - y0, false);
}
}
/* Show the frame back buffer. If frame is double-buffered,
atomically publish to the user's screen graphics updates made since
the last call to show_back_buffer. */
+
+#ifdef HAVE_XDBE
static void
show_back_buffer (struct frame *f)
{
block_input ();
+
if (FRAME_X_DOUBLE_BUFFERED_P (f))
{
-#ifdef HAVE_XDBE
#ifdef USE_CAIRO
cairo_t *cr = FRAME_CR_CONTEXT (f);
if (cr)
@@ -1525,13 +6617,12 @@ show_back_buffer (struct frame *f)
swap_info.swap_window = FRAME_X_WINDOW (f);
swap_info.swap_action = XdbeCopied;
XdbeSwapBuffers (FRAME_X_DISPLAY (f), &swap_info, 1);
-#else
- eassert (!"should have back-buffer only with XDBE");
-#endif
}
FRAME_X_NEED_BUFFER_FLIP (f) = false;
+
unblock_input ();
}
+#endif
/* Updates back buffer and flushes changes to display. Called from
minibuf read code. Note that we display the back buffer even if
@@ -1539,9 +6630,20 @@ show_back_buffer (struct frame *f)
static void
x_flip_and_flush (struct frame *f)
{
+ /* Flipping buffers requires a working connection to the X server,
+ which isn't always present if `inhibit-redisplay' is t, since
+ this can be called from the IO error handler. */
+ if (!NILP (Vinhibit_redisplay)
+ /* This has to work for tooltip frames, however, and redisplay
+ cannot happen when they are being flushed anyway. (bug#55519) */
+ && !FRAME_TOOLTIP_P (f))
+ return;
+
block_input ();
+#ifdef HAVE_XDBE
if (FRAME_X_NEED_BUFFER_FLIP (f))
- show_back_buffer (f);
+ show_back_buffer (f);
+#endif
x_flush (f);
unblock_input ();
}
@@ -1577,20 +6679,85 @@ x_update_end (struct frame *f)
static void
XTframe_up_to_date (struct frame *f)
{
+#if defined HAVE_XSYNC && !defined HAVE_GTK3
+ XSyncValue add;
+ XSyncValue current;
+ Bool overflow_p;
+#elif defined HAVE_XSYNC
+ GtkWidget *widget;
+ GdkWindow *window;
+ GdkFrameClock *clock;
+#endif
+
eassert (FRAME_X_P (f));
block_input ();
FRAME_MOUSE_UPDATE (f);
- if (!buffer_flipping_blocked_p () && FRAME_X_NEED_BUFFER_FLIP (f))
+
+#ifdef HAVE_XDBE
+ if (!buffer_flipping_blocked_p ()
+ && FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
+#endif
+
+#ifdef HAVE_XSYNC
+#ifndef HAVE_GTK3
+ if (FRAME_X_OUTPUT (f)->sync_end_pending_p
+ && FRAME_X_BASIC_COUNTER (f) != None)
+ {
+ XSyncSetCounter (FRAME_X_DISPLAY (f),
+ FRAME_X_BASIC_COUNTER (f),
+ FRAME_X_OUTPUT (f)->pending_basic_counter_value);
+ FRAME_X_OUTPUT (f)->sync_end_pending_p = false;
+ }
+
+ if (FRAME_X_OUTPUT (f)->ext_sync_end_pending_p
+ && FRAME_X_EXTENDED_COUNTER (f) != None)
+ {
+ current = FRAME_X_OUTPUT (f)->current_extended_counter_value;
+
+ if (XSyncValueLow32 (current) % 2)
+ XSyncIntToValue (&add, 1);
+ else
+ XSyncIntToValue (&add, 2);
+
+ XSyncValueAdd (&FRAME_X_OUTPUT (f)->current_extended_counter_value,
+ current, add, &overflow_p);
+
+ if (overflow_p)
+ emacs_abort ();
+
+ XSyncSetCounter (FRAME_X_DISPLAY (f),
+ FRAME_X_EXTENDED_COUNTER (f),
+ FRAME_X_OUTPUT (f)->current_extended_counter_value);
+
+ FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = false;
+ }
+#else
+ if (FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
+ {
+ widget = FRAME_GTK_OUTER_WIDGET (f);
+ window = gtk_widget_get_window (widget);
+ eassert (window);
+ clock = gdk_window_get_frame_clock (window);
+ eassert (clock);
+
+ gdk_frame_clock_request_phase (clock,
+ GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
+ FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = false;
+ }
+#endif
+#endif
unblock_input ();
}
+#ifdef HAVE_XDBE
static void
XTbuffer_flipping_unblocked_hook (struct frame *f)
{
if (FRAME_X_NEED_BUFFER_FLIP (f))
show_back_buffer (f);
}
+#endif
/**
* x_clear_under_internal_border:
@@ -1626,10 +6793,10 @@ x_clear_under_internal_border (struct frame *f)
GC gc = f->output_data.x->normal_gc;
XSetForeground (display, gc, color);
- x_fill_rectangle (f, gc, 0, margin, width, border);
- x_fill_rectangle (f, gc, 0, 0, border, height);
- x_fill_rectangle (f, gc, width - border, 0, border, height);
- x_fill_rectangle (f, gc, 0, height - border, width, border);
+ x_fill_rectangle (f, gc, 0, margin, width, border, false);
+ x_fill_rectangle (f, gc, 0, 0, border, height, false);
+ x_fill_rectangle (f, gc, width - border, 0, border, height, false);
+ x_fill_rectangle (f, gc, 0, height - border, width, border, false);
XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
}
else
@@ -1696,9 +6863,9 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
GC gc = f->output_data.x->normal_gc;
XSetForeground (display, gc, color);
- x_fill_rectangle (f, gc, 0, y, width, height);
+ x_fill_rectangle (f, gc, 0, y, width, height, true);
x_fill_rectangle (f, gc, FRAME_PIXEL_WIDTH (f) - width, y,
- width, height);
+ width, height, true);
XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
}
else
@@ -1713,7 +6880,8 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
}
static void
-x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p)
+x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
+ struct draw_fringe_bitmap_params *p)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_X_DISPLAY (f);
@@ -1730,18 +6898,27 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
mono-displays, the fill style may have been changed to
FillSolid in x_draw_glyph_string_background. */
if (face->stipple)
- XSetFillStyle (display, face->gc, FillOpaqueStippled);
- else
- XSetForeground (display, face->gc, face->background);
-
- x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
+ {
+ XSetFillStyle (display, face->gc, FillOpaqueStippled);
+ x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
+ true);
+ XSetFillStyle (display, face->gc, FillSolid);
- if (!face->stipple)
- XSetForeground (display, face->gc, face->foreground);
+ row->stipple_p = true;
+ }
+ else
+ {
+ XSetBackground (display, face->gc, face->background);
+ x_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny,
+ true);
+ XSetForeground (display, face->gc, face->foreground);
+ }
}
#ifdef USE_CAIRO
- if (p->which && p->which < max_fringe_bmp)
+ if (p->which
+ && p->which < max_fringe_bmp
+ && p->which < max_used_fringe_bitmap)
{
XGCValues gcv;
@@ -1751,6 +6928,16 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
: f->output_data.x->cursor_pixel)
: face->foreground));
XSetBackground (display, gc, face->background);
+ if (!fringe_bmp[p->which])
+ {
+ /* This fringe bitmap is known to fringe.c, but lacks the
+ cairo_pattern_t pattern which shadows that bitmap. This
+ is typical to define-fringe-bitmap being called when the
+ selected frame was not a GUI frame, for example, when
+ packages that define fringe bitmaps are loaded by a
+ daemon Emacs. Create the missing pattern now. */
+ gui_define_fringe_bitmap (f, p->which);
+ }
x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
p->wd, p->h, p->x, p->y, p->overlay_p);
XSetForeground (display, gc, gcv.foreground);
@@ -1761,15 +6948,40 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
{
Drawable drawable = FRAME_X_DRAWABLE (f);
char *bits;
- Pixmap pixmap, clipmask = (Pixmap) 0;
- int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+ Pixmap pixmap, clipmask = None;
+ int depth = FRAME_DISPLAY_INFO (f)->n_planes;
XGCValues gcv;
+ unsigned long background = face->background;
+ XColor bg;
+#ifdef HAVE_XRENDER
+ Picture picture = None;
+ XRenderPictureAttributes attrs;
+
+ memset (&attrs, 0, sizeof attrs);
+#endif
if (p->wd > 8)
bits = (char *) (p->bits + p->dh);
else
bits = (char *) p->bits + p->dh;
+ if (FRAME_DISPLAY_INFO (f)->alpha_bits
+ && f->alpha_background < 1.0)
+ {
+ bg.pixel = background;
+ x_query_colors (f, &bg, 1);
+ bg.red *= f->alpha_background;
+ bg.green *= f->alpha_background;
+ bg.blue *= f->alpha_background;
+
+ background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
+ bg.red, bg.green, bg.blue);
+ background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
+ background |= (((unsigned long) (f->alpha_background * 0xffff)
+ >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
+ << FRAME_DISPLAY_INFO (f)->alpha_offset);
+ }
+
/* Draw the bitmap. I believe these small pixmaps can be cached
by the server. */
pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h,
@@ -1777,7 +6989,15 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
? (p->overlay_p ? face->background
: f->output_data.x->cursor_pixel)
: face->foreground),
- face->background, depth);
+ background, depth);
+
+#ifdef HAVE_XRENDER
+ if (FRAME_X_PICTURE_FORMAT (f)
+ && (x_xr_ensure_picture (f), FRAME_X_PICTURE (f)))
+ picture = XRenderCreatePicture (display, pixmap,
+ FRAME_X_PICTURE_FORMAT (f),
+ 0, &attrs);
+#endif
if (p->overlay_p)
{
@@ -1785,14 +7005,43 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
FRAME_DISPLAY_INFO (f)->root_window,
bits, p->wd, p->h,
1, 0, 1);
- gcv.clip_mask = clipmask;
- gcv.clip_x_origin = p->x;
- gcv.clip_y_origin = p->y;
- XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
+
+#ifdef HAVE_XRENDER
+ if (picture != None)
+ {
+ attrs.clip_mask = clipmask;
+ attrs.clip_x_origin = p->x;
+ attrs.clip_y_origin = p->y;
+
+ XRenderChangePicture (display, FRAME_X_PICTURE (f),
+ CPClipMask | CPClipXOrigin | CPClipYOrigin,
+ &attrs);
+ }
+ else
+#endif
+ {
+ gcv.clip_mask = clipmask;
+ gcv.clip_x_origin = p->x;
+ gcv.clip_y_origin = p->y;
+ XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
+ }
}
- XCopyArea (display, pixmap, drawable, gc, 0, 0,
- p->wd, p->h, p->x, p->y);
+#ifdef HAVE_XRENDER
+ if (picture != None)
+ {
+ x_xr_apply_ext_clip (f, gc);
+ XRenderComposite (display, PictOpSrc, picture,
+ None, FRAME_X_PICTURE (f),
+ 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
+ x_xr_reset_ext_clip (f);
+
+ XRenderFreePicture (display, picture);
+ }
+ else
+#endif
+ XCopyArea (display, pixmap, drawable, gc, 0, 0,
+ p->wd, p->h, p->x, p->y);
XFreePixmap (display, pixmap);
if (p->overlay_p)
@@ -1819,6 +7068,118 @@ static void x_scroll_bar_clear (struct frame *);
static void x_check_font (struct frame *, struct font *);
#endif
+/* If SEND_EVENT, make sure that TIME is larger than the current last
+ user time. We don't sanitize timestamps from events sent by the X
+ server itself because some Lisp might have set the user time to a
+ ridiculously large value, and this way a more reasonable timestamp
+ can be obtained upon the next event. */
+
+static void
+x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time,
+ bool send_event)
+{
+#ifndef USE_GTK
+ struct frame *focus_frame = dpyinfo->x_focus_frame;
+#endif
+
+#ifdef ENABLE_CHECKING
+ eassert (time <= X_ULONG_MAX);
+#endif
+
+ if (!send_event || time > dpyinfo->last_user_time)
+ dpyinfo->last_user_time = time;
+
+#ifndef USE_GTK
+ if (focus_frame)
+ {
+ while (FRAME_PARENT_FRAME (focus_frame))
+ focus_frame = FRAME_PARENT_FRAME (focus_frame);
+
+ if (FRAME_X_OUTPUT (focus_frame)->user_time_window != None)
+ XChangeProperty (dpyinfo->display,
+ FRAME_X_OUTPUT (focus_frame)->user_time_window,
+ dpyinfo->Xatom_net_wm_user_time,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &time, 1);
+ }
+#endif
+}
+
+/* Not needed on GTK because GTK handles reporting the user time
+ itself. */
+
+#ifndef USE_GTK
+static void
+x_update_frame_user_time_window (struct frame *f)
+{
+ struct x_output *output;
+ struct x_display_info *dpyinfo;
+ XSetWindowAttributes attrs;
+
+ output = FRAME_X_OUTPUT (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (!NILP (Vx_no_window_manager))
+ {
+ if (output->user_time_window != None
+ && output->user_time_window != FRAME_OUTER_WINDOW (f))
+ {
+ XDestroyWindow (dpyinfo->display, output->user_time_window);
+ XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_user_time_window);
+ }
+ else
+ XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_user_time);
+
+ output->user_time_window = None;
+ return;
+ }
+
+ if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window))
+ {
+ if (output->user_time_window == None)
+ output->user_time_window = FRAME_OUTER_WINDOW (f);
+ else if (output->user_time_window != FRAME_OUTER_WINDOW (f))
+ {
+ XDestroyWindow (dpyinfo->display,
+ output->user_time_window);
+ XDeleteProperty (dpyinfo->display,
+ FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_user_time_window);
+ output->user_time_window = FRAME_OUTER_WINDOW (f);
+ }
+ }
+ else
+ {
+ if (output->user_time_window == FRAME_OUTER_WINDOW (f)
+ || output->user_time_window == None)
+ {
+ memset (&attrs, 0, sizeof attrs);
+
+ output->user_time_window
+ = XCreateWindow (dpyinfo->display, FRAME_X_WINDOW (f),
+ -1, -1, 1, 1, 0, 0, InputOnly,
+ CopyFromParent, 0, &attrs);
+
+ XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_user_time);
+ XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_user_time_window,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &output->user_time_window, 1);
+ }
+ }
+}
+#endif
+
+void
+x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo,
+ Time time)
+{
+ x_display_set_last_user_time (dpyinfo, time, true);
+}
+
/* Set S->gc to a suitable GC for drawing glyph string S in cursor
face. */
@@ -1859,7 +7220,10 @@ x_set_cursor_gc (struct glyph_string *s)
IF_DEBUG (x_check_font (s->f, s->font));
xgcv.graphics_exposures = False;
- mask = GCForeground | GCBackground | GCGraphicsExposures;
+ xgcv.line_width = 1;
+ mask = (GCForeground | GCBackground
+ | GCGraphicsExposures
+ | GCLineWidth);
if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
@@ -1891,7 +7255,11 @@ x_set_mouse_face_gc (struct glyph_string *s)
xgcv.background = s->face->background;
xgcv.foreground = s->face->foreground;
xgcv.graphics_exposures = False;
- mask = GCForeground | GCBackground | GCGraphicsExposures;
+ xgcv.line_width = 1;
+
+ mask = (GCForeground | GCBackground
+ | GCGraphicsExposures
+ | GCLineWidth);
if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
@@ -2035,14 +7403,34 @@ x_compute_glyph_string_overhangs (struct glyph_string *s)
static void
x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
{
- Display *display = FRAME_X_DISPLAY (s->f);
+ x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR);
+}
+
+#ifndef USE_CAIRO
+
+static void
+x_clear_point (struct frame *f, GC gc, int x, int y,
+ bool respect_alpha_background)
+{
XGCValues xgcv;
- XGetGCValues (display, s->gc, GCForeground | GCBackground, &xgcv);
- XSetForeground (display, s->gc, xgcv.background);
- x_fill_rectangle (s->f, s->gc, x, y, w, h);
- XSetForeground (display, s->gc, xgcv.foreground);
+ Display *dpy;
+
+ dpy = FRAME_X_DISPLAY (f);
+
+ if (f->alpha_background != 1.0
+ && respect_alpha_background)
+ {
+ x_clear_rectangle (f, gc, x, y, 1, 1, true);
+ return;
+ }
+
+ XGetGCValues (dpy, gc, GCBackground | GCForeground, &xgcv);
+ XSetForeground (dpy, gc, xgcv.background);
+ XDrawPoint (dpy, FRAME_X_DRAWABLE (f), gc, x, y);
+ XSetForeground (dpy, gc, xgcv.foreground);
}
+#endif
/* Draw the background of glyph_string S. If S->background_filled_p
is non-zero don't draw it. FORCE_P non-zero means draw the
@@ -2066,9 +7454,10 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
/* Fill background with a stipple pattern. */
XSetFillStyle (display, s->gc, FillOpaqueStippled);
x_fill_rectangle (s->f, s->gc, s->x,
- s->y + box_line_width,
- s->background_width,
- s->height - 2 * box_line_width);
+ s->y + box_line_width,
+ s->background_width,
+ s->height - 2 * box_line_width,
+ s->hl != DRAW_CURSOR);
XSetFillStyle (display, s->gc, FillSolid);
s->background_filled_p = true;
}
@@ -2163,7 +7552,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
x_fill_rectangle (s->f, s->gc, s->x,
s->y + box_line_width,
s->background_width,
- s->height - 2 * box_line_width);
+ s->height - 2 * box_line_width,
+ false);
XSetFillStyle (display, s->gc, FillSolid);
}
else
@@ -2371,6 +7761,10 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
glyph->ascent + glyph->descent - 1);
x += glyph->pixel_width;
}
+
+ /* Defend against hypothetical bad code elsewhere that uses
+ s->char2b after this function returns. */
+ s->char2b = NULL;
}
#ifdef USE_X_TOOLKIT
@@ -2586,8 +7980,7 @@ x_color_cells (Display *dpy, int *ncells)
if (dpyinfo->color_cells == NULL)
{
- Screen *screen = dpyinfo->screen;
- int ncolor_cells = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
+ int ncolor_cells = dpyinfo->visual_info.colormap_size;
int i;
dpyinfo->color_cells = xnmalloc (ncolor_cells,
@@ -2613,12 +8006,12 @@ void
x_query_colors (struct frame *f, XColor *colors, int ncolors)
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ int i;
if (dpyinfo->red_bits > 0)
{
/* For TrueColor displays, we can decompose the RGB value
directly. */
- int i;
unsigned int rmult, gmult, bmult;
unsigned int rmask, gmask, bmask;
@@ -2674,63 +8067,180 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
}
-/* Store F's background color into *BGCOLOR. */
+/* Store F's real background color into *BGCOLOR. */
static void
x_query_frame_background_color (struct frame *f, XColor *bgcolor)
{
- bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
+ unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+#ifndef USE_CAIRO
+ XColor bg;
+#endif
+
+ if (FRAME_DISPLAY_INFO (f)->alpha_bits)
+ {
+#ifdef USE_CAIRO
+ background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask);
+ background |= (((unsigned long) (f->alpha_background * 0xffff)
+ >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
+ << FRAME_DISPLAY_INFO (f)->alpha_offset);
+#else
+ if (FRAME_DISPLAY_INFO (f)->alpha_bits
+ && f->alpha_background < 1.0)
+ {
+ bg.pixel = background;
+ x_query_colors (f, &bg, 1);
+ bg.red *= f->alpha_background;
+ bg.green *= f->alpha_background;
+ bg.blue *= f->alpha_background;
+
+ background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
+ bg.red, bg.green, bg.blue);
+ background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
+ background |= (((unsigned long) (f->alpha_background * 0xffff)
+ >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
+ << FRAME_DISPLAY_INFO (f)->alpha_offset);
+ }
+#endif
+ }
+
+ bgcolor->pixel = background;
+
x_query_colors (f, bgcolor, 1);
}
+static unsigned int
+x_hash_string_ignore_case (const char *string)
+{
+ unsigned int i;
+
+ i = 3323198485ul;
+ for (; *string; ++string)
+ {
+ i ^= c_tolower (*string);
+ i *= 0x5bd1e995;
+ i ^= i >> 15;
+ }
+ return i;
+}
+
/* On frame F, translate the color name to RGB values. Use cached
information, if possible.
- Note that there is currently no way to clean old entries out of the
- cache. However, it is limited to names in the server's database,
- and names we've actually looked up; list-colors-display is probably
- the most color-intensive case we're likely to hit. */
+ If too many entries are placed in the cache, the least recently
+ used entries are removed. */
-Status x_parse_color (struct frame *f, const char *color_name,
- XColor *color)
+Status
+x_parse_color (struct frame *f, const char *color_name,
+ XColor *color)
{
+ unsigned short r, g, b;
+ Display *dpy;
+ Colormap cmap;
+ struct x_display_info *dpyinfo;
+ struct color_name_cache_entry *cache_entry, *last;
+ struct color_name_cache_entry *next, *color_entry;
+ unsigned int hash, idx;
+ int rc, i;
+
/* Don't pass #RGB strings directly to XParseColor, because that
follows the X convention of zero-extending each channel
value: #f00 means #f00000. We want the convention of scaling
channel values, so #f00 means #ff0000, just as it does for
HTML, SVG, and CSS. */
- unsigned short r, g, b;
if (parse_color_spec (color_name, &r, &g, &b))
{
color->red = r;
color->green = g;
color->blue = b;
+
return 1;
}
- Display *dpy = FRAME_X_DISPLAY (f);
- Colormap cmap = FRAME_X_COLORMAP (f);
- struct color_name_cache_entry *cache_entry;
- for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry;
- cache_entry = cache_entry->next)
+ /* Some X servers send BadValue on empty color names. */
+ if (!strlen (color_name))
+ return 0;
+
+ cmap = FRAME_X_COLORMAP (f);
+ dpy = FRAME_X_DISPLAY (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ hash = x_hash_string_ignore_case (color_name);
+ idx = hash % dpyinfo->color_names_size;
+
+ last = NULL;
+
+ for (cache_entry = dpyinfo->color_names[idx];
+ cache_entry; cache_entry = cache_entry->next)
{
- if (!xstrcasecmp(cache_entry->name, color_name))
+ if (!xstrcasecmp (cache_entry->name, color_name))
{
- *color = cache_entry->rgb;
- return 1;
+ /* Move recently used entries to the start of the color
+ cache. */
+
+ if (last)
+ {
+ last->next = cache_entry->next;
+ cache_entry->next = dpyinfo->color_names[idx];
+
+ dpyinfo->color_names[idx] = cache_entry;
+ }
+
+ if (cache_entry->valid)
+ *color = cache_entry->rgb;
+
+ return cache_entry->valid;
}
+
+ last = cache_entry;
}
- if (XParseColor (dpy, cmap, color_name, color) == 0)
- /* No caching of negative results, currently. */
- return 0;
+ block_input ();
+ rc = XParseColor (dpy, cmap, color_name, color);
+ unblock_input ();
cache_entry = xzalloc (sizeof *cache_entry);
- cache_entry->rgb = *color;
+ dpyinfo->color_names_length[idx] += 1;
+
+ if (rc)
+ cache_entry->rgb = *color;
+
+ cache_entry->valid = rc;
cache_entry->name = xstrdup (color_name);
- cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names;
- FRAME_DISPLAY_INFO (f)->color_names = cache_entry;
- return 1;
+ cache_entry->next = dpyinfo->color_names[idx];
+
+ dpyinfo->color_names[idx] = cache_entry;
+
+ /* Don't let the color cache become too big. */
+ if (dpyinfo->color_names_length[idx] > (x_color_cache_bucket_size > 0
+ ? x_color_cache_bucket_size : 128))
+ {
+ i = 0;
+
+ for (last = dpyinfo->color_names[idx]; last; last = last->next)
+ {
+ if (++i == (x_color_cache_bucket_size > 0
+ ? x_color_cache_bucket_size : 128))
+ {
+ next = last->next;
+ last->next = NULL;
+
+ for (color_entry = next; color_entry; color_entry = last)
+ {
+ last = color_entry->next;
+
+ xfree (color_entry->name);
+ xfree (color_entry);
+
+ dpyinfo->color_names_length[idx] -= 1;
+ }
+
+ return rc;
+ }
+ }
+ }
+
+ return rc;
}
@@ -2742,40 +8252,112 @@ Status x_parse_color (struct frame *f, const char *color_name,
static bool
x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color)
{
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
bool rc;
+ eassume (dpyinfo);
rc = XAllocColor (dpy, cmap, color) != 0;
+
+ if (dpyinfo->visual_info.class == DirectColor)
+ return rc;
+
if (rc == 0)
{
/* If we got to this point, the colormap is full, so we're going
- to try to get the next closest color. The algorithm used is
+ to try and get the next closest color. The algorithm used is
a least-squares matching, which is what X uses for closest
color matching with StaticColor visuals. */
- int nearest, i;
- int max_color_delta = 255;
- int max_delta = 3 * max_color_delta;
- int nearest_delta = max_delta + 1;
- int ncells;
- const XColor *cells = x_color_cells (dpy, &ncells);
- for (nearest = i = 0; i < ncells; ++i)
+ const XColor *cells;
+ int no_cells;
+ int nearest;
+ long nearest_delta, trial_delta;
+ int x;
+ Status status;
+ bool retry = false;
+ int ncolor_cells, i;
+ bool temp_allocated;
+ XColor temp;
+
+ start:
+ cells = x_color_cells (dpy, &no_cells);
+ temp_allocated = false;
+
+ nearest = 0;
+ /* I'm assuming CSE so I'm not going to condense this. */
+ nearest_delta = ((((color->red >> 8) - (cells[0].red >> 8))
+ * ((color->red >> 8) - (cells[0].red >> 8)))
+ + (((color->green >> 8) - (cells[0].green >> 8))
+ * ((color->green >> 8) - (cells[0].green >> 8)))
+ + (((color->blue >> 8) - (cells[0].blue >> 8))
+ * ((color->blue >> 8) - (cells[0].blue >> 8))));
+ for (x = 1; x < no_cells; x++)
{
- int dred = (color->red >> 8) - (cells[i].red >> 8);
- int dgreen = (color->green >> 8) - (cells[i].green >> 8);
- int dblue = (color->blue >> 8) - (cells[i].blue >> 8);
- int delta = dred * dred + dgreen * dgreen + dblue * dblue;
-
- if (delta < nearest_delta)
+ trial_delta = ((((color->red >> 8) - (cells[x].red >> 8))
+ * ((color->red >> 8) - (cells[x].red >> 8)))
+ + (((color->green >> 8) - (cells[x].green >> 8))
+ * ((color->green >> 8) - (cells[x].green >> 8)))
+ + (((color->blue >> 8) - (cells[x].blue >> 8))
+ * ((color->blue >> 8) - (cells[x].blue >> 8))));
+ if (trial_delta < nearest_delta)
{
- nearest = i;
- nearest_delta = delta;
+ /* We didn't decide to use this color, so free it. */
+ if (temp_allocated)
+ {
+ XFreeColors (dpy, cmap, &temp.pixel, 1, 0);
+ temp_allocated = false;
+ }
+
+ temp.red = cells[x].red;
+ temp.green = cells[x].green;
+ temp.blue = cells[x].blue;
+ status = XAllocColor (dpy, cmap, &temp);
+
+ if (status)
+ {
+ temp_allocated = true;
+ nearest = x;
+ nearest_delta = trial_delta;
+ }
}
}
-
- color->red = cells[nearest].red;
+ color->red = cells[nearest].red;
color->green = cells[nearest].green;
- color->blue = cells[nearest].blue;
- rc = XAllocColor (dpy, cmap, color) != 0;
+ color->blue = cells[nearest].blue;
+
+ if (!temp_allocated)
+ status = XAllocColor (dpy, cmap, color);
+ else
+ {
+ *color = temp;
+ status = 1;
+ }
+
+ if (status == 0 && !retry)
+ {
+ /* Our private cache of color cells is probably out of date.
+ Refresh it here, and try to allocate the nearest color
+ from the new colormap. */
+
+ retry = true;
+ xfree (dpyinfo->color_cells);
+
+ ncolor_cells = dpyinfo->visual_info.colormap_size;
+
+ dpyinfo->color_cells = xnmalloc (ncolor_cells,
+ sizeof *dpyinfo->color_cells);
+ dpyinfo->ncolor_cells = ncolor_cells;
+
+ for (i = 0; i < ncolor_cells; ++i)
+ dpyinfo->color_cells[i].pixel = i;
+
+ XQueryColors (dpy, dpyinfo->cmap,
+ dpyinfo->color_cells, ncolor_cells);
+
+ goto start;
+ }
+
+ rc = status != 0;
}
else
{
@@ -2846,7 +8428,7 @@ x_copy_color (struct frame *f, unsigned long pixel)
necessary and some servers don't allow it. Since we won't free a
color once we've allocated it, we don't need to re-allocate it to
maintain the server's reference count. */
- if (!x_mutable_colormap (FRAME_X_VISUAL (f)))
+ if (!x_mutable_colormap (FRAME_X_VISUAL_INFO (f)))
return pixel;
color.pixel = pixel;
@@ -2911,7 +8493,7 @@ x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
that scaling by FACTOR alone isn't enough. */
{
/* How far below the limit this color is (0 - 1, 1 being darker). */
- double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+ double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
/* The additive adjustment. */
int min_delta = delta * dimness * factor / 2;
@@ -3037,20 +8619,62 @@ x_setup_relief_colors (struct glyph_string *s)
}
}
+#ifndef USE_CAIRO
+static void
+x_fill_triangle (struct frame *f, GC gc, XPoint point1,
+ XPoint point2, XPoint point3)
+{
+ XPoint abc[3];
+
+ abc[0] = point1;
+ abc[1] = point2;
+ abc[2] = point3;
+
+ XFillPolygon (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
+ gc, abc, 3, Convex, CoordModeOrigin);
+}
+
+static XPoint
+x_make_point (int x, int y)
+{
+ XPoint pt;
+
+ pt.x = x;
+ pt.y = y;
+
+ return pt;
+}
+
+static bool
+x_inside_rect_p (XRectangle *rects, int nrects, int x, int y)
+{
+ int i;
+
+ for (i = 0; i < nrects; ++i)
+ {
+ if (x >= rects[i].x && y >= rects[i].y
+ && x < rects[i].x + rects[i].width
+ && y < rects[i].y + rects[i].height)
+ return true;
+ }
+
+ return false;
+}
+#endif
/* Draw a relief on frame F inside the rectangle given by LEFT_X,
- TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
- to draw, it must be >= 0. RAISED_P means draw a raised
- relief. LEFT_P means draw a relief on the left side of
- the rectangle. RIGHT_P means draw a relief on the right
- side of the rectangle. CLIP_RECT is the clipping rectangle to use
- when drawing. */
-
-static void
-x_draw_relief_rect (struct frame *f,
- int left_x, int top_y, int right_x, int bottom_y,
- int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
- bool left_p, bool right_p,
+ TOP_Y, RIGHT_X, and BOTTOM_Y. VWIDTH and HWIDTH are respectively
+ the thickness of the vertical relief (left and right) and
+ horizontal relief (top and bottom) to draw, it must be >= 0.
+ RAISED_P means draw a raised relief. LEFT_P means draw a relief on
+ the left side of the rectangle. RIGHT_P means draw a relief on the
+ right side of the rectangle. CLIP_RECT is the clipping rectangle
+ to use when drawing. */
+
+static void
+x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
+ int bottom_y, int hwidth, int vwidth, bool raised_p,
+ bool top_p, bool bot_p, bool left_p, bool right_p,
XRectangle *clip_rect)
{
#ifdef USE_CAIRO
@@ -3074,7 +8698,7 @@ x_draw_relief_rect (struct frame *f,
if (left_p)
{
x_fill_rectangle (f, top_left_gc, left_x, top_y,
- vwidth, bottom_y + 1 - top_y);
+ vwidth, bottom_y + 1 - top_y, false);
if (top_p)
corners |= 1 << CORNER_TOP_LEFT;
if (bot_p)
@@ -3083,7 +8707,7 @@ x_draw_relief_rect (struct frame *f,
if (right_p)
{
x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
- vwidth, bottom_y + 1 - top_y);
+ vwidth, bottom_y + 1 - top_y, false);
if (top_p)
corners |= 1 << CORNER_TOP_RIGHT;
if (bot_p)
@@ -3093,7 +8717,7 @@ x_draw_relief_rect (struct frame *f,
{
if (!right_p)
x_fill_rectangle (f, top_left_gc, left_x, top_y,
- right_x + 1 - left_x, hwidth);
+ right_x + 1 - left_x, hwidth, false);
else
x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
right_x + 1 - left_x, hwidth, 1);
@@ -3102,7 +8726,7 @@ x_draw_relief_rect (struct frame *f,
{
if (!left_p)
x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
- right_x + 1 - left_x, hwidth);
+ right_x + 1 - left_x, hwidth, false);
else
x_fill_trapezoid_for_relief (f, bottom_right_gc,
left_x, bottom_y + 1 - hwidth,
@@ -3110,10 +8734,10 @@ x_draw_relief_rect (struct frame *f,
}
if (left_p && vwidth > 1)
x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
- 1, bottom_y + 1 - top_y);
+ 1, bottom_y + 1 - top_y, false);
if (top_p && hwidth > 1)
x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
- right_x + 1 - left_x, 1);
+ right_x + 1 - left_x, 1, false);
if (corners)
{
XSetBackground (FRAME_X_DISPLAY (f), top_left_gc,
@@ -3126,90 +8750,118 @@ x_draw_relief_rect (struct frame *f,
x_reset_clip_rectangles (f, top_left_gc);
x_reset_clip_rectangles (f, bottom_right_gc);
#else
- Display *dpy = FRAME_X_DISPLAY (f);
- Drawable drawable = FRAME_X_DRAWABLE (f);
- int i;
- GC gc;
-
- if (raised_p)
- gc = f->output_data.x->white_relief.gc;
- else
- gc = f->output_data.x->black_relief.gc;
- XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
+ GC gc, white_gc, black_gc, normal_gc;
+ Drawable drawable;
+ Display *dpy;
/* This code is more complicated than it has to be, because of two
minor hacks to make the boxes look nicer: (i) if width > 1, draw
the outermost line using the black relief. (ii) Omit the four
corner pixels. */
- /* Top. */
- if (top_p)
- {
- if (hwidth == 1)
- XDrawLine (dpy, drawable, gc,
- left_x + left_p, top_y,
- right_x + !right_p, top_y);
+ white_gc = f->output_data.x->white_relief.gc;
+ black_gc = f->output_data.x->black_relief.gc;
+ normal_gc = f->output_data.x->normal_gc;
- for (i = 1; i < hwidth; ++i)
- XDrawLine (dpy, drawable, gc,
- left_x + i * left_p, top_y + i,
- right_x + 1 - i * right_p, top_y + i);
- }
+ drawable = FRAME_X_DRAWABLE (f);
+ dpy = FRAME_X_DISPLAY (f);
- /* Left. */
- if (left_p)
- {
- if (vwidth == 1)
- XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
-
- for (i = 1; i < vwidth; ++i)
- XDrawLine (dpy, drawable, gc,
- left_x + i, top_y + (i + 1) * top_p,
- left_x + i, bottom_y + 1 - (i + 1) * bot_p);
- }
+ x_set_clip_rectangles (f, white_gc, clip_rect, 1);
+ x_set_clip_rectangles (f, black_gc, clip_rect, 1);
- XSetClipMask (dpy, gc, None);
if (raised_p)
- gc = f->output_data.x->black_relief.gc;
+ gc = white_gc;
else
- gc = f->output_data.x->white_relief.gc;
- XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
+ gc = black_gc;
- /* Outermost top line. */
- if (top_p && hwidth > 1)
- XDrawLine (dpy, drawable, gc,
- left_x + left_p, top_y,
- right_x + !right_p, top_y);
+ /* Draw lines. */
- /* Outermost left line. */
- if (left_p && vwidth > 1)
- XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
+ if (top_p)
+ x_fill_rectangle (f, gc, left_x, top_y,
+ right_x - left_x + 1, hwidth,
+ false);
+
+ if (left_p)
+ x_fill_rectangle (f, gc, left_x, top_y, vwidth,
+ bottom_y - top_y + 1, false);
+
+ if (raised_p)
+ gc = black_gc;
+ else
+ gc = white_gc;
- /* Bottom. */
if (bot_p)
+ x_fill_rectangle (f, gc, left_x, bottom_y - hwidth + 1,
+ right_x - left_x + 1, hwidth, false);
+
+ if (right_p)
+ x_fill_rectangle (f, gc, right_x - vwidth + 1, top_y,
+ vwidth, bottom_y - top_y + 1, false);
+
+ /* Draw corners. */
+
+ if (bot_p && left_p)
+ x_fill_triangle (f, raised_p ? white_gc : black_gc,
+ x_make_point (left_x, bottom_y - hwidth),
+ x_make_point (left_x + vwidth, bottom_y - hwidth),
+ x_make_point (left_x, bottom_y));
+
+ if (top_p && right_p)
+ x_fill_triangle (f, raised_p ? white_gc : black_gc,
+ x_make_point (right_x - vwidth, top_y),
+ x_make_point (right_x, top_y),
+ x_make_point (right_x - vwidth, top_y + hwidth));
+
+ /* Draw outer line. */
+
+ if (top_p && left_p && bot_p && right_p
+ && hwidth > 1 && vwidth > 1)
+ x_draw_rectangle (f, black_gc, left_x, top_y,
+ right_x - left_x, bottom_y - top_y);
+ else
{
- if (hwidth >= 1)
- XDrawLine (dpy, drawable, gc,
- left_x + left_p, bottom_y,
- right_x + !right_p, bottom_y);
+ if (top_p && hwidth > 1)
+ XDrawLine (dpy, drawable, black_gc, left_x, top_y,
+ right_x + 1, top_y);
+
+ if (bot_p && hwidth > 1)
+ XDrawLine (dpy, drawable, black_gc, left_x, bottom_y,
+ right_x + 1, bottom_y);
- for (i = 1; i < hwidth; ++i)
- XDrawLine (dpy, drawable, gc,
- left_x + i * left_p, bottom_y - i,
- right_x + 1 - i * right_p, bottom_y - i);
+ if (left_p && vwidth > 1)
+ XDrawLine (dpy, drawable, black_gc, left_x, top_y,
+ left_x, bottom_y + 1);
+
+ if (right_p && vwidth > 1)
+ XDrawLine (dpy, drawable, black_gc, right_x, top_y,
+ right_x, bottom_y + 1);
}
- /* Right. */
- if (right_p)
+ /* Erase corners. */
+
+ if (hwidth > 1 && vwidth > 1)
{
- for (i = 0; i < vwidth; ++i)
- XDrawLine (dpy, drawable, gc,
- right_x - i, top_y + (i + 1) * top_p,
- right_x - i, bottom_y + 1 - (i + 1) * bot_p);
- }
+ if (left_p && top_p && x_inside_rect_p (clip_rect, 1,
+ left_x, top_y))
+ /* This should respect `alpha-background' since it's being
+ cleared with the background color of the frame. */
+ x_clear_point (f, normal_gc, left_x, top_y, true);
- x_reset_clip_rectangles (f, gc);
+ if (left_p && bot_p && x_inside_rect_p (clip_rect, 1,
+ left_x, bottom_y))
+ x_clear_point (f, normal_gc, left_x, bottom_y, true);
+
+ if (right_p && top_p && x_inside_rect_p (clip_rect, 1,
+ right_x, top_y))
+ x_clear_point (f, normal_gc, right_x, top_y, true);
+ if (right_p && bot_p && x_inside_rect_p (clip_rect, 1,
+ right_x, bottom_y))
+ x_clear_point (f, normal_gc, right_x, bottom_y, true);
+ }
+
+ x_reset_clip_rectangles (f, white_gc);
+ x_reset_clip_rectangles (f, black_gc);
#endif
}
@@ -3235,21 +8887,25 @@ x_draw_box_rect (struct glyph_string *s,
/* Top. */
x_fill_rectangle (s->f, s->gc,
- left_x, top_y, right_x - left_x + 1, hwidth);
+ left_x, top_y, right_x - left_x + 1, hwidth,
+ false);
/* Left. */
if (left_p)
x_fill_rectangle (s->f, s->gc,
- left_x, top_y, vwidth, bottom_y - top_y + 1);
+ left_x, top_y, vwidth, bottom_y - top_y + 1,
+ false);
/* Bottom. */
x_fill_rectangle (s->f, s->gc,
- left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
+ left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth,
+ false);
/* Right. */
if (right_p)
x_fill_rectangle (s->f, s->gc,
- right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
+ right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1,
+ false);
XSetForeground (display, s->gc, xgcv.foreground);
x_reset_clip_rectangles (s->f, s->gc);
@@ -3333,14 +8989,15 @@ x_composite_image (struct glyph_string *s, Pixmap dest,
{
Display *display = FRAME_X_DISPLAY (s->f);
#ifdef HAVE_XRENDER
- if (s->img->picture)
+ if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f))
{
Picture destination;
XRenderPictFormat *default_format;
XRenderPictureAttributes attr;
+ /* Pacify GCC. */
+ memset (&attr, 0, sizeof attr);
- default_format = XRenderFindVisualFormat (display,
- DefaultVisual (display, 0));
+ default_format = FRAME_X_PICTURE_FORMAT (s->f);
destination = XRenderCreatePicture (display, dest,
default_format, 0, &attr);
@@ -3663,7 +9320,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
/* Fill background with a stipple pattern. */
XSetFillStyle (display, s->gc, FillOpaqueStippled);
- x_fill_rectangle (s->f, s->gc, x, y, w, h);
+ x_fill_rectangle (s->f, s->gc, x, y, w, h, true);
XSetFillStyle (display, s->gc, FillSolid);
}
else
@@ -3713,14 +9370,16 @@ x_draw_image_glyph_string (struct glyph_string *s)
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
+ if (s->stippled_p)
+ s->row->stipple_p = true;
+
#ifndef USE_CAIRO
if (s->img->mask)
{
/* Create a pixmap as large as the glyph string. Fill it
with the background color. Copy the image to it, using
its mask. Copy the temporary pixmap to the display. */
- Screen *screen = FRAME_X_SCREEN (s->f);
- int depth = DefaultDepthOfScreen (screen);
+ int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
/* Create a pixmap as large as the glyph string. */
pixmap = XCreatePixmap (display, FRAME_X_DRAWABLE (s->f),
@@ -3745,12 +9404,35 @@ x_draw_image_glyph_string (struct glyph_string *s)
else
{
XGCValues xgcv;
- XGetGCValues (display, s->gc, GCForeground | GCBackground,
- &xgcv);
- XSetForeground (display, s->gc, xgcv.background);
- XFillRectangle (display, pixmap, s->gc,
- 0, 0, s->background_width, s->height);
- XSetForeground (display, s->gc, xgcv.foreground);
+#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ if (FRAME_DISPLAY_INFO (s->f)->alpha_bits
+ && s->f->alpha_background != 1.0
+ && FRAME_CHECK_XR_VERSION (s->f, 0, 2)
+ && FRAME_X_PICTURE_FORMAT (s->f))
+ {
+ XRenderColor xc;
+ XRenderPictureAttributes attrs;
+ Picture pict;
+ memset (&attrs, 0, sizeof attrs);
+
+ pict = XRenderCreatePicture (display, pixmap,
+ FRAME_X_PICTURE_FORMAT (s->f),
+ 0, &attrs);
+ x_xrender_color_from_gc_background (s->f, s->gc, &xc, true);
+ XRenderFillRectangle (FRAME_X_DISPLAY (s->f), PictOpSrc, pict,
+ &xc, 0, 0, s->background_width, s->height);
+ XRenderFreePicture (display, pict);
+ }
+ else
+#endif
+ {
+ XGetGCValues (display, s->gc, GCForeground | GCBackground,
+ &xgcv);
+ XSetForeground (display, s->gc, xgcv.background);
+ XFillRectangle (display, pixmap, s->gc,
+ 0, 0, s->background_width, s->height);
+ XSetForeground (display, s->gc, xgcv.foreground);
+ }
}
}
else
@@ -3869,15 +9551,17 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
{
/* Fill background with a stipple pattern. */
XSetFillStyle (display, gc, FillOpaqueStippled);
- x_fill_rectangle (s->f, gc, x, y, w, h);
+ x_fill_rectangle (s->f, gc, x, y, w, h, true);
XSetFillStyle (display, gc, FillSolid);
+
+ s->row->stipple_p = true;
}
else
{
XGCValues xgcv;
XGetGCValues (display, gc, GCForeground | GCBackground, &xgcv);
XSetForeground (display, gc, xgcv.background);
- x_fill_rectangle (s->f, gc, x, y, w, h);
+ x_fill_rectangle (s->f, gc, x, y, w, h, true);
XSetForeground (display, gc, xgcv.foreground);
}
@@ -3897,15 +9581,20 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
background_width -= text_left_x - x;
x = text_left_x;
}
+
+ if (!s->row->stipple_p)
+ s->row->stipple_p = s->stippled_p;
+
if (background_width > 0)
- x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+ x_draw_glyph_string_bg_rect (s, x, s->y,
+ background_width, s->height);
}
s->background_filled_p = true;
}
static void
-x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
+x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
{
const int base_res = 96;
struct x_display_info * dpyinfo = x_display_info_for_display (disp);
@@ -3932,7 +9621,7 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
*/
static void
-x_draw_underwave (struct glyph_string *s)
+x_draw_underwave (struct glyph_string *s, int decoration_width)
{
Display *display = FRAME_X_DISPLAY (s->f);
@@ -3945,7 +9634,7 @@ x_draw_underwave (struct glyph_string *s)
#ifdef USE_CAIRO
x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
- s->width, wave_height, wave_length);
+ decoration_width, wave_height, wave_length);
#else /* not USE_CAIRO */
int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
bool odd;
@@ -3955,7 +9644,7 @@ x_draw_underwave (struct glyph_string *s)
dy = wave_height - 1;
x0 = s->x;
y0 = s->ybase + wave_height / 2 - scale_y;
- width = s->width;
+ width = decoration_width;
xmax = x0 + width;
/* Find and set clipping rectangle */
@@ -4105,6 +9794,21 @@ x_draw_glyph_string (struct glyph_string *s)
if (!s->for_overlaps)
{
+ int area_x, area_y, area_width, area_height;
+ int area_max_x, decoration_width;
+
+ /* Prevent the underline from overwriting surrounding areas
+ and the fringe. */
+ window_box (s->w, s->area, &area_x, &area_y,
+ &area_width, &area_height);
+ area_max_x = area_x + area_width - 1;
+
+ decoration_width = s->width;
+ if (!s->row->mode_line_p
+ && !s->row->tab_line_p
+ && area_max_x < (s->x + decoration_width - 1))
+ decoration_width -= (s->x + decoration_width - 1) - area_max_x;
+
/* Draw relief if not yet drawn. */
if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
@@ -4115,14 +9819,14 @@ x_draw_glyph_string (struct glyph_string *s)
if (s->face->underline == FACE_UNDER_WAVE)
{
if (s->face->underline_defaulted_p)
- x_draw_underwave (s);
+ x_draw_underwave (s, decoration_width);
else
{
Display *display = FRAME_X_DISPLAY (s->f);
XGCValues xgcv;
XGetGCValues (display, s->gc, GCForeground, &xgcv);
XSetForeground (display, s->gc, s->face->underline_color);
- x_draw_underwave (s);
+ x_draw_underwave (s, decoration_width);
XSetForeground (display, s->gc, xgcv.foreground);
}
}
@@ -4131,8 +9835,12 @@ x_draw_glyph_string (struct glyph_string *s)
unsigned long thickness, position;
int y;
- if (s->prev &&
- s->prev->face->underline == FACE_UNDER_LINE)
+ if (s->prev
+ && s->prev->face->underline == FACE_UNDER_LINE
+ && (s->prev->face->underline_at_descent_line_p
+ == s->face->underline_at_descent_line_p)
+ && (s->prev->face->underline_pixels_above_descent_line
+ == s->face->underline_pixels_above_descent_line))
{
/* We use the same underline style as the previous one. */
thickness = s->prev->underline_thickness;
@@ -4155,12 +9863,13 @@ x_draw_glyph_string (struct glyph_string *s)
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_underline_at_descent_line, s->w));
underline_at_descent_line
- = !(NILP (val) || EQ (val, Qunbound));
+ = (!(NILP (val) || BASE_EQ (val, Qunbound))
+ || s->face->underline_at_descent_line_p);
val = (WINDOW_BUFFER_LOCAL_VALUE
(Qx_use_underline_position_properties, s->w));
use_underline_position_properties
- = !(NILP (val) || EQ (val, Qunbound));
+ = !(NILP (val) || BASE_EQ (val, Qunbound));
/* Get the underline thickness. Default is 1 pixel. */
if (font && font->underline_thickness > 0)
@@ -4168,7 +9877,9 @@ x_draw_glyph_string (struct glyph_string *s)
else
thickness = 1;
if (underline_at_descent_line)
- position = (s->height - thickness) - (s->ybase - s->y);
+ position = ((s->height - thickness)
+ - (s->ybase - s->y)
+ - s->face->underline_pixels_above_descent_line);
else
{
/* Get the underline position. This is the
@@ -4188,12 +9899,16 @@ x_draw_glyph_string (struct glyph_string *s)
else
position = minimum_offset;
}
- position = max (position, minimum_offset);
+
+ /* Ignore minimum_offset if the amount of pixels was
+ explicitly specified. */
+ if (!s->face->underline_pixels_above_descent_line)
+ position = max (position, minimum_offset);
}
/* Check the sanity of thickness and position. We should
avoid drawing underline out of the current line area. */
- if (s->y + s->height <= s->ybase + position)
- position = (s->height - 1) - (s->ybase - s->y);
+ if (s->y + s->height <= s->ybase + position)
+ position = (s->height - 1) - (s->ybase - s->y);
if (s->y + s->height < s->ybase + position + thickness)
thickness = (s->y + s->height) - (s->ybase + position);
s->underline_thickness = thickness;
@@ -4201,7 +9916,8 @@ x_draw_glyph_string (struct glyph_string *s)
y = s->ybase + position;
if (s->face->underline_defaulted_p)
x_fill_rectangle (s->f, s->gc,
- s->x, y, s->width, thickness);
+ s->x, y, decoration_width, thickness,
+ false);
else
{
Display *display = FRAME_X_DISPLAY (s->f);
@@ -4209,7 +9925,8 @@ x_draw_glyph_string (struct glyph_string *s)
XGetGCValues (display, s->gc, GCForeground, &xgcv);
XSetForeground (display, s->gc, s->face->underline_color);
x_fill_rectangle (s->f, s->gc,
- s->x, y, s->width, thickness);
+ s->x, y, decoration_width, thickness,
+ false);
XSetForeground (display, s->gc, xgcv.foreground);
}
}
@@ -4221,7 +9938,7 @@ x_draw_glyph_string (struct glyph_string *s)
if (s->face->overline_color_defaulted_p)
x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->width, h);
+ decoration_width, h, false);
else
{
Display *display = FRAME_X_DISPLAY (s->f);
@@ -4229,7 +9946,7 @@ x_draw_glyph_string (struct glyph_string *s)
XGetGCValues (display, s->gc, GCForeground, &xgcv);
XSetForeground (display, s->gc, s->face->overline_color);
x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
- s->width, h);
+ decoration_width, h, false);
XSetForeground (display, s->gc, xgcv.foreground);
}
}
@@ -4251,7 +9968,7 @@ x_draw_glyph_string (struct glyph_string *s)
if (s->face->strike_through_color_defaulted_p)
x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
- s->width, h);
+ s->width, h, false);
else
{
Display *display = FRAME_X_DISPLAY (s->f);
@@ -4259,7 +9976,7 @@ x_draw_glyph_string (struct glyph_string *s)
XGetGCValues (display, s->gc, GCForeground, &xgcv);
XSetForeground (display, s->gc, s->face->strike_through_color);
x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
- s->width, h);
+ decoration_width, h, false);
XSetForeground (display, s->gc, xgcv.foreground);
}
}
@@ -4319,6 +10036,14 @@ x_draw_glyph_string (struct glyph_string *s)
/* Reset clipping. */
x_reset_clip_rectangles (s->f, s->gc);
s->num_clips = 0;
+
+ /* Set the stippled flag that tells redisplay whether or not a
+ stipple was actually draw. */
+
+ if (s->first_glyph->type != STRETCH_GLYPH
+ && s->first_glyph->type != IMAGE_GLYPH
+ && !s->row->stipple_p)
+ s->row->stipple_p = s->stippled_p;
}
/* Shift display to make room for inserted glyphs. */
@@ -4348,13 +10073,15 @@ x_delete_glyphs (struct frame *f, int n)
/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
If they are <= 0, this is probably an error. */
-MAYBE_UNUSED static void
+#if defined USE_GTK || !defined USE_CAIRO
+static void
x_clear_area1 (Display *dpy, Window window,
int x, int y, int width, int height, int exposures)
{
eassert (width > 0 && height > 0);
XClearArea (dpy, window, x, y, width, height, exposures);
}
+#endif
void
x_clear_area (struct frame *f, int x, int y, int width, int height)
@@ -4365,20 +10092,52 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
eassert (width > 0 && height > 0);
cr = x_begin_cr_clip (f, NULL);
- x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
+ x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc,
+ true);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
x_end_cr_clip (f);
#else
- if (FRAME_X_DOUBLE_BUFFERED_P (f))
- XFillRectangle (FRAME_X_DISPLAY (f),
- FRAME_X_DRAWABLE (f),
- f->output_data.x->reverse_gc,
- x, y, width, height);
+#ifndef USE_GTK
+ if (f->alpha_background != 1.0
+#ifdef HAVE_XDBE
+ || FRAME_X_DOUBLE_BUFFERED_P (f)
+#endif
+ )
+#endif
+ {
+#if defined HAVE_XRENDER && \
+ (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
+ x_xr_ensure_picture (f);
+ if (FRAME_DISPLAY_INFO (f)->alpha_bits
+ && FRAME_X_PICTURE (f) != None
+ && f->alpha_background != 1.0
+ && FRAME_CHECK_XR_VERSION (f, 0, 2))
+ {
+ XRenderColor xc;
+ GC gc = f->output_data.x->normal_gc;
+
+ x_xr_apply_ext_clip (f, gc);
+ x_xrender_color_from_gc_background (f, gc, &xc, true);
+ XRenderFillRectangle (FRAME_X_DISPLAY (f),
+ PictOpSrc, FRAME_X_PICTURE (f),
+ &xc, x, y, width, height);
+ x_xr_reset_ext_clip (f);
+ x_mark_frame_dirty (f);
+ }
+ else
+#endif
+ XFillRectangle (FRAME_X_DISPLAY (f),
+ FRAME_X_DRAWABLE (f),
+ f->output_data.x->reverse_gc,
+ x, y, width, height);
+ }
+#ifndef USE_GTK
else
x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
x, y, width, height, False);
#endif
+#endif
}
@@ -4425,6 +10184,7 @@ x_show_hourglass (struct frame *f)
if (!x->hourglass_window)
{
+#ifndef USE_XCB
unsigned long mask = CWCursor;
XSetWindowAttributes attrs;
#ifdef USE_GTK
@@ -4437,12 +10197,41 @@ x_show_hourglass (struct frame *f)
x->hourglass_window = XCreateWindow
(dpy, parent, 0, 0, 32000, 32000, 0, 0,
InputOnly, CopyFromParent, mask, &attrs);
+#else
+ uint32_t cursor = (uint32_t) x->hourglass_cursor;
+#ifdef USE_GTK
+ xcb_window_t parent = (xcb_window_t) FRAME_X_WINDOW (f);
+#else
+ xcb_window_t parent = (xcb_window_t) FRAME_OUTER_WINDOW (f);
+#endif
+ x->hourglass_window
+ = (Window) xcb_generate_id (FRAME_DISPLAY_INFO (f)->xcb_connection);
+
+ xcb_create_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ XCB_COPY_FROM_PARENT,
+ (xcb_window_t) x->hourglass_window,
+ parent, 0, 0, FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f), 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ XCB_COPY_FROM_PARENT, XCB_CW_CURSOR,
+ &cursor);
+#endif
}
+#ifndef USE_XCB
XMapRaised (dpy, x->hourglass_window);
- XFlush (dpy);
/* Ensure that the spinning hourglass is shown. */
flush_frame (f);
+#else
+ uint32_t value = XCB_STACK_MODE_ABOVE;
+
+ xcb_configure_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ (xcb_window_t) x->hourglass_window,
+ XCB_CONFIG_WINDOW_STACK_MODE, &value);
+ xcb_map_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ (xcb_window_t) x->hourglass_window);
+ xcb_flush (FRAME_DISPLAY_INFO (f)->xcb_connection);
+#endif
}
}
}
@@ -4457,10 +10246,16 @@ x_hide_hourglass (struct frame *f)
/* Watch out for newly created frames. */
if (x->hourglass_window)
{
+#ifndef USE_XCB
XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
/* Sync here because XTread_socket looks at the
hourglass_p flag that is reset to zero below. */
XSync (FRAME_X_DISPLAY (f), False);
+#else
+ xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ (xcb_window_t) x->hourglass_window);
+ xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
+#endif
x->hourglass_p = false;
}
}
@@ -4470,48 +10265,15 @@ x_hide_hourglass (struct frame *f)
static void
XTflash (struct frame *f)
{
- block_input ();
+ GC gc;
+ XGCValues values;
+ fd_set fds;
+ int fd, rc;
- {
-#ifdef USE_GTK
- /* Use Gdk routines to draw. This way, we won't draw over scroll bars
- when the scroll bars and the edit widget share the same X window. */
- GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
-#ifdef HAVE_GTK3
-#if GTK_CHECK_VERSION (3, 22, 0)
- cairo_region_t *region = gdk_window_get_visible_region (window);
- GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
- cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
-#else
- cairo_t *cr = gdk_cairo_create (window);
-#endif
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
-#define XFillRectangle(d, win, gc, x, y, w, h) \
- do { \
- cairo_rectangle (cr, x, y, w, h); \
- cairo_fill (cr); \
- } \
- while (false)
-#else /* ! HAVE_GTK3 */
- GdkGCValues vals;
- GdkGC *gc;
- vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
- ^ FRAME_BACKGROUND_PIXEL (f));
- vals.function = GDK_XOR;
- gc = gdk_gc_new_with_values (window,
- &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
-#define XFillRectangle(d, win, gc, x, y, w, h) \
- gdk_draw_rectangle (window, gc, true, x, y, w, h)
-#endif /* ! HAVE_GTK3 */
-#else /* ! USE_GTK */
- GC gc;
-
- /* Create a GC that will use the GXxor function to flip foreground
- pixels into background pixels. */
- {
- XGCValues values;
+ block_input ();
+ if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
+ {
values.function = GXxor;
values.foreground = (FRAME_FOREGROUND_PIXEL (f)
^ FRAME_BACKGROUND_PIXEL (f));
@@ -4519,115 +10281,100 @@ XTflash (struct frame *f)
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
GCFunction | GCForeground, &values);
}
-#endif
+ else
+ gc = FRAME_X_OUTPUT (f)->normal_gc;
+
+
+ /* Get the height not including a menu bar widget. */
+ int height = FRAME_PIXEL_HEIGHT (f);
+ /* Height of each line to flash. */
+ int flash_height = FRAME_LINE_HEIGHT (f);
+ /* These will be the left and right margins of the rectangles. */
+ int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = flash_right - flash_left;
+
+ /* If window is tall, flash top and bottom line. */
+ if (height > 3 * FRAME_LINE_HEIGHT (f))
{
- /* Get the height not including a menu bar widget. */
- int height = FRAME_PIXEL_HEIGHT (f);
- /* Height of each line to flash. */
- int flash_height = FRAME_LINE_HEIGHT (f);
- /* These will be the left and right margins of the rectangles. */
- int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
- int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
- int width = flash_right - flash_left;
-
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (FRAME_INTERNAL_BORDER_WIDTH (f)
- + FRAME_TOP_MARGIN_HEIGHT (f)),
- width, flash_height);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left,
+ (FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_TOP_MARGIN_HEIGHT (f)),
+ width, flash_height);
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left,
+ (height - flash_height
+ - FRAME_INTERNAL_BORDER_WIDTH (f)),
+ width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ }
+ else
+ /* If it is short, flash it all. */
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
- x_flush (f);
+ x_flush (f);
- {
- struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
- struct timespec wakeup = timespec_add (current_timespec (), delay);
+ struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
+ struct timespec wakeup = timespec_add (current_timespec (), delay);
+ fd = ConnectionNumber (FRAME_X_DISPLAY (f));
- /* Keep waiting until past the time wakeup or any input gets
- available. */
- while (! detect_input_pending ())
- {
- struct timespec current = current_timespec ();
- struct timespec timeout;
+ /* Keep waiting until past the time wakeup or any input gets
+ available. */
+ while (! detect_input_pending ())
+ {
+ struct timespec current = current_timespec ();
+ struct timespec timeout;
- /* Break if result would not be positive. */
- if (timespec_cmp (wakeup, current) <= 0)
- break;
+ /* Break if result would not be positive. */
+ if (timespec_cmp (wakeup, current) <= 0)
+ break;
- /* How long `select' should wait. */
- timeout = make_timespec (0, 10 * 1000 * 1000);
+ /* How long `select' should wait. */
+ timeout = make_timespec (0, 10 * 1000 * 1000);
- /* Try to wait that long--but we might wake up sooner. */
- pselect (0, NULL, NULL, NULL, &timeout, NULL);
- }
- }
+ /* Wait for some input to become available on the X
+ connection. */
+ FD_ZERO (&fds);
+ FD_SET (fd, &fds);
- /* If window is tall, flash top and bottom line. */
- if (height > 3 * FRAME_LINE_HEIGHT (f))
- {
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (FRAME_INTERNAL_BORDER_WIDTH (f)
- + FRAME_TOP_MARGIN_HEIGHT (f)),
- width, flash_height);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left,
- (height - flash_height
- - FRAME_INTERNAL_BORDER_WIDTH (f)),
- width, flash_height);
- }
- else
- /* If it is short, flash it all. */
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
- width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ /* Try to wait that long--but we might wake up sooner. */
+ rc = pselect (fd + 1, &fds, NULL, NULL, &timeout, NULL);
-#ifdef USE_GTK
-#ifdef HAVE_GTK3
-#if GTK_CHECK_VERSION (3, 22, 0)
- gdk_window_end_draw_frame (window, context);
- cairo_region_destroy (region);
-#else
- cairo_destroy (cr);
-#endif
-#else
- g_object_unref (G_OBJECT (gc));
-#endif
-#undef XFillRectangle
-#else
- XFreeGC (FRAME_X_DISPLAY (f), gc);
-#endif
- x_flush (f);
+ /* Some input is available, exit the visible bell. */
+ if (rc >= 0 && FD_ISSET (fd, &fds))
+ break;
}
- }
- unblock_input ();
-}
+ /* If window is tall, flash top and bottom line. */
+ if (height > 3 * FRAME_LINE_HEIGHT (f))
+ {
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left,
+ (FRAME_INTERNAL_BORDER_WIDTH (f)
+ + FRAME_TOP_MARGIN_HEIGHT (f)),
+ width, flash_height);
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left,
+ (height - flash_height
+ - FRAME_INTERNAL_BORDER_WIDTH (f)),
+ width, flash_height);
+ }
+ else
+ /* If it is short, flash it all. */
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+ width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+ if (FRAME_X_VISUAL_INFO (f)->class == TrueColor)
+ XFreeGC (FRAME_X_DISPLAY (f), gc);
+ x_flush (f);
-static void
-XTtoggle_invisible_pointer (struct frame *f, bool invisible)
-{
- block_input ();
- FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible);
unblock_input ();
}
-
/* Make audible bell. */
static void
@@ -4799,6 +10546,14 @@ x_scroll_run (struct window *w, struct run *run)
}
#endif
+#ifdef USE_CAIRO_XCB_SURFACE
+ /* Some of the following code depends on `normal_gc' being
+ up-to-date on the X server, but doesn't call a routine that will
+ flush it first. So do this ourselves instead. */
+ XFlushGC (FRAME_X_DISPLAY (f),
+ f->output_data.x->normal_gc);
+#endif
+
#ifdef USE_CAIRO
if (FRAME_CR_CONTEXT (f))
{
@@ -4818,6 +10573,18 @@ x_scroll_run (struct window *w, struct run *run)
x, to_y);
cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
}
+#ifdef USE_CAIRO_XCB_SURFACE
+ else if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XCB)
+ {
+ cairo_surface_flush (surface);
+ xcb_copy_area (FRAME_DISPLAY_INFO (f)->xcb_connection,
+ (xcb_drawable_t) FRAME_X_DRAWABLE (f),
+ (xcb_drawable_t) FRAME_X_DRAWABLE (f),
+ (xcb_gcontext_t) XGContextFromGC (f->output_data.x->normal_gc),
+ x, from_y, x, to_y, width, height);
+ cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height);
+ }
+#endif
else
{
cairo_surface_t *s
@@ -4861,6 +10628,10 @@ x_scroll_run (struct window *w, struct run *run)
static void
x_frame_highlight (struct frame *f)
{
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
/* We used to only do this if Vx_no_window_manager was non-nil, but
the ICCCM (section 4.1.6) says that the window's border pixmap
and border pixel are window attributes which are "private to the
@@ -4870,10 +10641,10 @@ x_frame_highlight (struct frame *f)
the window-manager in use, tho something more is at play since I've been
using that same window-manager binary for ever. Let's not crash just
because of this (bug#9310). */
- x_catch_errors (FRAME_X_DISPLAY (f));
+ x_ignore_errors_for_next_request (dpyinfo);
XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_pixel);
- x_uncatch_errors ();
+ x_stop_ignoring_errors (dpyinfo);
unblock_input ();
gui_update_cursor (f, true);
x_set_frame_alpha (f);
@@ -4882,17 +10653,23 @@ x_frame_highlight (struct frame *f)
static void
x_frame_unhighlight (struct frame *f)
{
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
/* We used to only do this if Vx_no_window_manager was non-nil, but
the ICCCM (section 4.1.6) says that the window's border pixmap
and border pixel are window attributes which are "private to the
client", so we can always change it to whatever we want. */
+
block_input ();
/* Same as above for XSetWindowBorder (bug#9310). */
- x_catch_errors (FRAME_X_DISPLAY (f));
+ x_ignore_errors_for_next_request (dpyinfo);
XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_tile);
- x_uncatch_errors ();
+ x_stop_ignoring_errors (dpyinfo);
unblock_input ();
+
gui_update_cursor (f, true);
x_set_frame_alpha (f);
}
@@ -4907,6 +10684,20 @@ static void
x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
{
struct frame *old_focus = dpyinfo->x_focus_frame;
+#if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
+ XIEventMask mask;
+ ptrdiff_t l;
+
+ if (dpyinfo->supports_xi2)
+ {
+ l = XIMaskLen (XI_LASTEVENT);
+ mask.mask = alloca (l);
+ mask.mask_len = l;
+ memset (mask.mask, 0, l);
+
+ mask.deviceid = XIAllDevices;
+ }
+#endif
if (frame != dpyinfo->x_focus_frame)
{
@@ -4914,6 +10705,17 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
the correct value of x_focus_frame. */
dpyinfo->x_focus_frame = frame;
+ /* Once none of our frames are focused anymore, stop selecting
+ for raw input events from the root window. */
+
+#if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
+ if (frame && dpyinfo->supports_xi2)
+ XISetMask (mask.mask, XI_RawKeyPress);
+
+ if (dpyinfo->supports_xi2)
+ XISelectEvents (dpyinfo->display, dpyinfo->root_window, &mask, 1);
+#endif
+
if (old_focus && old_focus->auto_lower)
x_lower_frame (old_focus);
@@ -4926,12 +10728,128 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
x_frame_rehighlight (dpyinfo);
}
+/* True if the display in DPYINFO supports a version of Xfixes
+ sufficient for pointer blanking. */
+#ifdef HAVE_XFIXES
+static bool
+x_probe_xfixes_extension (struct x_display_info *dpyinfo)
+{
+ return (dpyinfo->xfixes_supported_p
+ && dpyinfo->xfixes_major >= 4);
+}
+#endif /* HAVE_XFIXES */
+
+/* Toggle mouse pointer visibility on frame F using the XFixes
+ extension. */
+#ifdef HAVE_XFIXES
+static void
+xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
+
+{
+ if (invisible)
+ XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ else
+ XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ f->pointer_invisible = invisible;
+}
+#endif /* HAVE_XFIXES */
+
+/* Create invisible cursor on the X display referred by DPYINFO. */
+static Cursor
+make_invisible_cursor (struct x_display_info *dpyinfo)
+{
+ Display *dpy = dpyinfo->display;
+ static char const no_data[] = { 0 };
+ Pixmap pix;
+ XColor col;
+ Cursor c;
+
+ c = None;
+
+ x_catch_errors (dpy);
+ pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
+ if (!x_had_errors_p (dpy) && pix != None)
+ {
+ Cursor pixc;
+ col.pixel = 0;
+ col.red = col.green = col.blue = 0;
+ col.flags = DoRed | DoGreen | DoBlue;
+ pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
+ if (! x_had_errors_p (dpy) && pixc != None)
+ c = pixc;
+ XFreePixmap (dpy, pix);
+ }
+
+ x_uncatch_errors ();
+
+ return c;
+}
+
+/* Toggle mouse pointer visibility on frame F by using an invisible
+ cursor. */
+static void
+x_toggle_visible_pointer (struct frame *f, bool invisible)
+{
+ struct x_display_info *dpyinfo;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ /* We could have gotten a BadAlloc error while creating the
+ invisible cursor. Try to create it again, but if that fails,
+ just give up. */
+ if (dpyinfo->invisible_cursor == None)
+ dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
+
+#ifndef HAVE_XFIXES
+ if (dpyinfo->invisible_cursor == None)
+ invisible = false;
+#else
+ /* But if Xfixes is available, try using it instead. */
+ if (dpyinfo->invisible_cursor == None)
+ {
+ if (x_probe_xfixes_extension (dpyinfo))
+ {
+ dpyinfo->fixes_pointer_blanking = true;
+ xfixes_toggle_visible_pointer (f, invisible);
+
+ return;
+ }
+ else
+ invisible = false;
+ }
+#endif
+
+ if (invisible)
+ XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
+ dpyinfo->invisible_cursor);
+ else
+ XDefineCursor (dpyinfo->display, FRAME_X_WINDOW (f),
+ f->output_data.x->current_cursor);
+
+ f->pointer_invisible = invisible;
+}
+
+static void
+XTtoggle_invisible_pointer (struct frame *f, bool invisible)
+{
+ block_input ();
+#ifdef HAVE_XFIXES
+ if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
+ && x_probe_xfixes_extension (FRAME_DISPLAY_INFO (f)))
+ xfixes_toggle_visible_pointer (f, invisible);
+ else
+#endif
+ x_toggle_visible_pointer (f, invisible);
+ unblock_input ();
+}
+
/* Handle FocusIn and FocusOut state changes for FRAME.
If FRAME has focus and there exists more than one frame, puts
a FOCUS_IN_EVENT into *BUFP. */
static void
-x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, struct input_event *bufp)
+x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame,
+ struct input_event *bufp)
{
if (type == FocusIn)
{
@@ -4947,7 +10865,18 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
#ifdef HAVE_X_I18N
if (FRAME_XIC (frame))
- XSetICFocus (FRAME_XIC (frame));
+ XSetICFocus (FRAME_XIC (frame));
+#ifdef USE_GTK
+ GtkWidget *widget;
+
+ if (x_gtk_use_native_input)
+ {
+ gtk_im_context_focus_in (FRAME_X_OUTPUT (frame)->im_context);
+ widget = FRAME_GTK_OUTER_WIDGET (frame);
+ gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context,
+ gtk_widget_get_window (widget));
+ }
+#endif
#endif
}
else if (type == FocusOut)
@@ -4963,10 +10892,21 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
XSETFRAME (bufp->frame_or_window, frame);
}
+ if (!frame->output_data.x->focus_state)
+ {
#ifdef HAVE_X_I18N
- if (FRAME_XIC (frame))
- XUnsetICFocus (FRAME_XIC (frame));
+ if (FRAME_XIC (frame))
+ XUnsetICFocus (FRAME_XIC (frame));
+#ifdef USE_GTK
+ if (x_gtk_use_native_input)
+ {
+ gtk_im_context_focus_out (FRAME_X_OUTPUT (frame)->im_context);
+ gtk_im_context_set_client_window (FRAME_X_OUTPUT (frame)->im_context, NULL);
+ }
#endif
+#endif
+ }
+
if (frame->pointer_invisible)
XTtoggle_invisible_pointer (frame, false);
}
@@ -5025,6 +10965,67 @@ x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
return 0;
}
+/* Like x_any_window_to_frame but only try to find tooltip frames.
+
+ If wdesc is a toolkit tooltip without an associated frame, set
+ UNRELATED_TOOLTIP_P to true. Otherwise, set it to false. */
+static struct frame *
+x_tooltip_window_to_frame (struct x_display_info *dpyinfo,
+ Window wdesc, bool *unrelated_tooltip_p)
+{
+ Lisp_Object tail, frame;
+ struct frame *f;
+#ifdef USE_GTK
+ GtkWidget *widget;
+ GdkWindow *tooltip_window;
+#endif
+
+ *unrelated_tooltip_p = false;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+
+ if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f)
+ && FRAME_DISPLAY_INFO (f) == dpyinfo
+ && FRAME_X_WINDOW (f) == wdesc)
+ return f;
+
+#ifdef USE_GTK
+ if (!FRAME_X_P (f))
+ continue;
+
+ if (FRAME_X_OUTPUT (f)->ttip_window)
+ widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window);
+ else
+ widget = NULL;
+
+ if (widget)
+ tooltip_window = gtk_widget_get_window (widget);
+ else
+ tooltip_window = NULL;
+
+#ifdef HAVE_GTK3
+ if (tooltip_window
+ && (gdk_x11_window_get_xid (tooltip_window) == wdesc))
+ {
+ *unrelated_tooltip_p = true;
+ break;
+ }
+#else
+ if (tooltip_window
+ && (GDK_WINDOW_XID (tooltip_window) == wdesc))
+ {
+ *unrelated_tooltip_p = true;
+ break;
+ }
+#endif
+#endif
+ }
+
+ return NULL;
+}
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Like x_window_to_frame but also compares the window with the widget's
@@ -5040,6 +11041,13 @@ x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
if (wdesc == None)
return NULL;
+#ifdef HAVE_XWIDGETS
+ struct xwidget_view *xv = xwidget_view_from_window (wdesc);
+
+ if (xv)
+ return xv->frame;
+#endif
+
FOR_EACH_FRAME (tail, frame)
{
if (found)
@@ -5161,10 +11169,756 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
#else /* !USE_X_TOOLKIT && !USE_GTK */
#define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
-#define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
+
+struct frame *
+x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
+{
+ return x_window_to_frame (dpyinfo, wdesc);
+}
+
+static void
+x_next_event_from_any_display (XEvent *event)
+{
+ struct x_display_info *dpyinfo;
+ fd_set fds, rfds;
+ int fd, maxfd, rc;
+
+ rc = -1;
+ FD_ZERO (&rfds);
+
+ while (true)
+ {
+ FD_ZERO (&fds);
+ maxfd = -1;
+
+ for (dpyinfo = x_display_list; dpyinfo;
+ dpyinfo = dpyinfo->next)
+ {
+ fd = ConnectionNumber (dpyinfo->display);
+
+ if ((rc < 0 || FD_ISSET (fd, &rfds))
+ && XPending (dpyinfo->display))
+ {
+ XNextEvent (dpyinfo->display, event);
+ return;
+ }
+
+ if (fd > maxfd)
+ maxfd = fd;
+
+ eassert (fd < FD_SETSIZE);
+ FD_SET (fd, &fds);
+ }
+
+ eassert (maxfd >= 0);
+
+ /* Continue to read input even if pselect fails, because if an
+ error occurs XPending will call the IO error handler, which
+ then brings us out of this loop. */
+ rc = pselect (maxfd + 1, &fds, NULL, NULL, NULL, NULL);
+
+ if (rc >= 0)
+ rfds = fds;
+ }
+}
#endif /* USE_X_TOOLKIT || USE_GTK */
+static void
+x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem)
+{
+ specpdl_ref count;
+ struct selection_input_event se;
+
+ count = SPECPDL_INDEX ();
+ se = tem->se;
+
+ record_unwind_protect_ptr (xfree, tem);
+ x_handle_selection_event (&se);
+ unbind_to (count, Qnil);
+}
+
+/* Handle all pending selection request events from modal event
+ loops. */
+void
+x_handle_pending_selection_requests (void)
+{
+ struct x_selection_request_event *tem;
+
+ while (pending_selection_requests)
+ {
+ tem = pending_selection_requests;
+ pending_selection_requests = tem->next;
+
+ x_handle_pending_selection_requests_1 (tem);
+ }
+}
+
+static void
+x_push_selection_request (struct selection_input_event *se)
+{
+ struct x_selection_request_event *tem;
+
+ tem = xmalloc (sizeof *tem);
+ tem->next = pending_selection_requests;
+ tem->se = *se;
+ pending_selection_requests = tem;
+}
+
+bool
+x_detect_pending_selection_requests (void)
+{
+ return !!pending_selection_requests;
+}
+
+static void
+x_clear_dnd_action (void)
+{
+ x_dnd_action_symbol = Qnil;
+}
+
+/* Delete action descriptions from F after drag-and-drop. */
+static void
+x_dnd_delete_action_list (Lisp_Object frame)
+{
+ struct frame *f;
+
+ /* Delete those two properties, since some clients look at them and
+ not the action to decide whether or not the user should be
+ prompted to select an action. This can be called with FRAME no
+ longer alive (or its display dead). */
+
+ f = XFRAME (frame);
+
+ if (!FRAME_LIVE_P (f) || !FRAME_DISPLAY_INFO (f)->display)
+ return;
+
+ block_input ();
+ XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList);
+ XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
+ unblock_input ();
+}
+
+static void
+x_dnd_lose_ownership (Lisp_Object timestamp_and_frame)
+{
+ struct frame *f;
+
+ f = XFRAME (XCDR (timestamp_and_frame));
+
+ if (FRAME_LIVE_P (f))
+ Fx_disown_selection_internal (QXdndSelection,
+ XCAR (timestamp_and_frame),
+ XCDR (timestamp_and_frame));
+}
+
+/* Clean up an existing drag-and-drop operation in preparation for its
+ sudden termination. */
+
+static void
+x_dnd_process_quit (struct frame *f, Time timestamp)
+{
+ xm_drop_start_message dmsg;
+
+ if (x_dnd_in_progress)
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ x_dnd_send_leave (f, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
+ && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
+ && x_dnd_motif_setup_p)
+ {
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.timestamp = timestamp;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.x = 0;
+ dmsg.y = 0;
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (f);
+
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
+ x_dnd_last_seen_window,
+ timestamp);
+ xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
+ x_dnd_last_seen_window, &dmsg);
+ }
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_frame = NULL;
+ }
+
+ x_dnd_waiting_for_finish = false;
+ x_dnd_return_frame_object = NULL;
+ x_dnd_movement_frame = NULL;
+}
+
+/* This function is defined far away from the rest of the XDND code so
+ it can utilize `x_any_window_to_frame'. */
+
+/* Implementors beware! On most other platforms (where drag-and-drop
+ data is not provided via selections, but some kind of serialization
+ mechanism), it is usually much easier to implement a suitable
+ primitive instead of copying the C code here, and then to build
+ `x-begin-drag' on top of that, by making it a wrapper function in
+ Lisp that converts the list of targets and value of `XdndSelection'
+ to serialized data. Also be sure to update the data types used in
+ dnd.el.
+
+ For examples of how to do this, see `haiku-drag-message' and
+ `x-begin-drag' in haikuselect.c and lisp/term/haiku-win.el, and
+ `ns-begin-drag' and `x-begin-drag' in nsselect.m and
+ lisp/term/ns-win.el. */
+
+Lisp_Object
+x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
+ Lisp_Object return_frame, Atom *ask_action_list,
+ const char **ask_action_names, size_t n_ask_actions,
+ bool allow_current_frame, Atom *target_atoms,
+ int ntargets, Lisp_Object selection_target_list,
+ bool follow_tooltip)
+{
+#ifndef USE_GTK
+ XEvent next_event;
+ int finish;
+#endif
+ XWindowAttributes root_window_attrs;
+ struct input_event hold_quit;
+ char *atom_name, *ask_actions;
+ Lisp_Object action, ltimestamp, val;
+ specpdl_ref ref, count, base;
+ ptrdiff_t i, end, fill;
+ XTextProperty prop;
+ Lisp_Object frame_object, x, y, frame, local_value;
+ bool signals_were_pending, need_sync;
+#ifdef HAVE_XKB
+ XkbStateRec keyboard_state;
+#endif
+#ifndef USE_GTK
+ struct x_display_info *event_display;
+#endif
+ unsigned int additional_mask;
+
+ base = SPECPDL_INDEX ();
+
+ /* Bind this here to avoid juggling bindings and SAFE_FREE in
+ Fx_begin_drag. */
+ specbind (Qx_dnd_targets_list, selection_target_list);
+
+ if (!FRAME_VISIBLE_P (f))
+ error ("Frame must be visible");
+
+ XSETFRAME (frame, f);
+ local_value = assq_no_quit (QXdndSelection,
+ FRAME_TERMINAL (f)->Vselection_alist);
+
+ if (x_dnd_in_progress || x_dnd_waiting_for_finish)
+ error ("A drag-and-drop session is already in progress");
+
+ DEFER_SELECTIONS;
+
+ /* If local_value is nil, then we lost ownership of XdndSelection.
+ Signal a more informative error than args-out-of-range. */
+ if (NILP (local_value))
+ error ("No local value for XdndSelection");
+
+ if (popup_activated ())
+ error ("Trying to drag-and-drop from within a menu-entry");
+
+ x_set_dnd_targets (target_atoms, ntargets);
+ record_unwind_protect_void (x_free_dnd_targets);
+ record_unwind_protect_void (x_clear_dnd_action);
+
+ ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f),
+ QXdndSelection);
+
+ if (NILP (ltimestamp))
+ error ("No local value for XdndSelection");
+
+ if (BIGNUMP (ltimestamp))
+ x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp);
+ else
+ x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
+
+ /* Release ownership of XdndSelection after this function returns.
+ VirtualBox uses the owner of XdndSelection to determine whether
+ or not mouse motion is part of a drag-and-drop operation. */
+
+ if (!x_dnd_preserve_selection_data)
+ record_unwind_protect (x_dnd_lose_ownership,
+ Fcons (ltimestamp, frame));
+
+ x_dnd_motif_operations
+ = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction);
+
+ x_dnd_first_motif_operation = XM_DRAG_NOOP;
+
+ if (n_ask_actions)
+ {
+ x_dnd_motif_operations
+ = xm_operations_from_actions (FRAME_DISPLAY_INFO (f),
+ ask_action_list,
+ n_ask_actions);
+ x_dnd_first_motif_operation
+ = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
+ ask_action_list[0]);
+
+ record_unwind_protect (x_dnd_delete_action_list, frame);
+
+ ask_actions = NULL;
+ end = 0;
+ count = SPECPDL_INDEX ();
+
+ for (i = 0; i < n_ask_actions; ++i)
+ {
+ fill = end;
+ end += strlen (ask_action_names[i]) + 1;
+
+ if (ask_actions)
+ ask_actions = xrealloc (ask_actions, end);
+ else
+ ask_actions = xmalloc (end);
+
+ strncpy (ask_actions + fill,
+ ask_action_names[i],
+ end - fill);
+ }
+
+ prop.value = (unsigned char *) ask_actions;
+ prop.encoding = XA_STRING;
+ prop.format = 8;
+ prop.nitems = end;
+
+ record_unwind_protect_ptr (xfree, ask_actions);
+
+ /* This can potentially store a lot of data in window
+ properties, so check for allocation errors. */
+ block_input ();
+ x_catch_errors (FRAME_X_DISPLAY (f));
+ XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *) ask_action_list,
+ n_ask_actions);
+ x_check_errors (FRAME_X_DISPLAY (f),
+ "Can't set action descriptions: %s");
+ x_uncatch_errors_after_check ();
+ unblock_input ();
+
+ unbind_to (count, Qnil);
+ }
+
+ record_unwind_protect_void (x_clear_dnd_variables);
+
+ if (follow_tooltip)
+ {
+#if defined HAVE_XRANDR || defined USE_GTK
+ x_dnd_monitors
+ = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list;
+
+ if (NILP (x_dnd_monitors))
+#endif
+ x_dnd_monitors
+ = Fx_display_monitor_attributes_list (frame);
+ }
+
+ x_dnd_update_tooltip = follow_tooltip;
+
+ /* This shouldn't happen. */
+ if (x_dnd_toplevels)
+ x_dnd_free_toplevels (true);
+
+#ifdef USE_GTK
+ /* Prevent GTK+ timeouts from being run, since they can call
+ handle_one_xevent behind our back. */
+ suppress_xg_select ();
+ record_unwind_protect_void (release_xg_select);
+#endif
+
+ /* Set up a meaningless alias. */
+ XSETCAR (x_dnd_selection_alias_cell, QSECONDARY);
+ XSETCDR (x_dnd_selection_alias_cell, QSECONDARY);
+
+ /* Bind this here. The cell doesn't actually alias between
+ anything until `xm_setup_dnd_targets' is called. */
+ specbind (Qx_selection_alias_alist,
+ Fcons (x_dnd_selection_alias_cell,
+ Vx_selection_alias_alist));
+
+ /* Initialize most of the state for the drag-and-drop operation. */
+ x_dnd_in_progress = true;
+ x_dnd_recursion_depth = command_loop_level + minibuf_level;
+ x_dnd_frame = f;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_last_protocol_version = -1;
+ x_dnd_last_window_is_frame = false;
+ x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
+ x_dnd_mouse_rect_target = None;
+ x_dnd_action = None;
+ x_dnd_action_symbol = Qnil;
+ x_dnd_wanted_action = xaction;
+ x_dnd_return_frame = 0;
+ x_dnd_waiting_for_finish = false;
+ x_dnd_waiting_for_motif_finish = 0;
+ x_dnd_waiting_for_status_window = None;
+ x_dnd_pending_send_position.type = 0;
+ x_dnd_xm_use_help = false;
+ x_dnd_motif_setup_p = false;
+ x_dnd_end_window = None;
+ x_dnd_run_unsupported_drop_function = false;
+ x_dnd_use_toplevels
+ = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
+ x_dnd_toplevels = NULL;
+ x_dnd_allow_current_frame = allow_current_frame;
+ x_dnd_movement_frame = NULL;
+ x_dnd_init_type_lists = false;
+ x_dnd_need_send_drop = false;
+#ifdef HAVE_XKB
+ x_dnd_keyboard_state = 0;
+
+ if (FRAME_DISPLAY_INFO (f)->supports_xkb)
+ {
+ XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+ XkbStateNotifyMask, XkbStateNotifyMask);
+ XkbGetState (FRAME_X_DISPLAY (f), XkbUseCoreKbd,
+ &keyboard_state);
+
+ x_dnd_keyboard_state = (keyboard_state.mods
+ | keyboard_state.ptr_buttons);
+ }
+#endif
+
+ if (x_dnd_use_toplevels)
+ {
+ if (x_dnd_compute_toplevels (FRAME_DISPLAY_INFO (f)))
+ {
+ x_dnd_free_toplevels (true);
+ x_dnd_use_toplevels = false;
+ }
+ else
+ record_unwind_protect_void (x_free_dnd_toplevels);
+ }
+
+ if (!NILP (return_frame))
+ x_dnd_return_frame = 1;
+
+ if (EQ (return_frame, Qnow))
+ x_dnd_return_frame = 2;
+
+ /* Now select for SubstructureNotifyMask and PropertyChangeMask on
+ the root window, so we can get notified when window stacking
+ changes, a common operation during drag-and-drop. */
+
+ XGetWindowAttributes (FRAME_X_DISPLAY (f),
+ FRAME_DISPLAY_INFO (f)->root_window,
+ &root_window_attrs);
+
+ additional_mask = SubstructureNotifyMask;
+
+ if (x_dnd_use_toplevels)
+ additional_mask |= PropertyChangeMask;
+
+ XSelectInput (FRAME_X_DISPLAY (f),
+ FRAME_DISPLAY_INFO (f)->root_window,
+ root_window_attrs.your_event_mask
+ | additional_mask);
+
+ if (EQ (return_frame, Qnow))
+ x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime);
+
+ while (x_dnd_in_progress || x_dnd_waiting_for_finish)
+ {
+ EVENT_INIT (hold_quit);
+
+#ifdef USE_GTK
+ current_finish = X_EVENT_NORMAL;
+ current_hold_quit = &hold_quit;
+ current_count = 0;
+ xg_pending_quit_event.kind = NO_EVENT;
+#endif
+
+ block_input ();
+ x_dnd_inside_handle_one_xevent = true;
+#ifdef USE_GTK
+ gtk_main_iteration ();
+#elif defined USE_X_TOOLKIT
+ XtAppNextEvent (Xt_app_con, &next_event);
+#else
+ x_next_event_from_any_display (&next_event);
+#endif
+
+#ifndef USE_GTK
+ event_display
+ = x_display_info_for_display (next_event.xany.display);
+
+ if (event_display)
+ {
+#ifdef HAVE_X_I18N
+#ifdef HAVE_XINPUT2
+ if (next_event.type != GenericEvent
+ || !event_display->supports_xi2
+ || (next_event.xgeneric.extension
+ != event_display->xi2_opcode))
+ {
+#endif
+ if (!x_filter_event (event_display, &next_event))
+ handle_one_xevent (event_display,
+ &next_event, &finish, &hold_quit);
+#ifdef HAVE_XINPUT2
+ }
+ else
+ handle_one_xevent (event_display,
+ &next_event, &finish, &hold_quit);
+#endif
+#else
+ handle_one_xevent (event_display,
+ &next_event, &finish, &hold_quit);
+#endif
+ }
+#else
+ /* Clear these before the read_socket_hook can be called. */
+ current_count = -1;
+ current_hold_quit = NULL;
+#endif
+ x_dnd_inside_handle_one_xevent = false;
+
+ /* Clean up any event handlers that are now out of date. */
+ x_clean_failable_requests (FRAME_DISPLAY_INFO (f));
+
+ /* The unblock_input below might try to read input, but
+ XTread_socket does nothing inside a drag-and-drop event
+ loop, so don't let it clear the pending_signals flag. */
+ signals_were_pending = pending_signals;
+ unblock_input ();
+ pending_signals = signals_were_pending;
+
+ /* Ignore mouse movement from displays that aren't the DND
+ display. */
+#ifndef USE_GTK
+ if (event_display == FRAME_DISPLAY_INFO (f))
+ {
+#endif
+ if (x_dnd_movement_frame
+ /* FIXME: how come this can end up with movement frames
+ from other displays on GTK builds? */
+ && (FRAME_X_DISPLAY (x_dnd_movement_frame)
+ == FRAME_X_DISPLAY (f))
+ /* If both those variables are false, then F is no
+ longer protected from deletion by Lisp code. This
+ can only happen during the final iteration of the DND
+ event loop. */
+ && (x_dnd_in_progress || x_dnd_waiting_for_finish))
+ {
+ XSETFRAME (frame_object, x_dnd_movement_frame);
+ XSETINT (x, x_dnd_movement_x);
+ XSETINT (y, x_dnd_movement_y);
+ x_dnd_movement_frame = NULL;
+
+ if (!NILP (Vx_dnd_movement_function)
+ && FRAME_LIVE_P (XFRAME (frame_object))
+ && !FRAME_TOOLTIP_P (XFRAME (frame_object))
+ && x_dnd_movement_x >= 0
+ && x_dnd_movement_y >= 0
+ && x_dnd_frame
+ && (XFRAME (frame_object) != x_dnd_frame
+ || x_dnd_allow_current_frame))
+ {
+ x_dnd_old_window_attrs = root_window_attrs;
+ x_dnd_unwind_flag = true;
+
+ ref = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
+ call2 (Vx_dnd_movement_function, frame_object,
+ Fposn_at_x_y (x, y, frame_object, Qnil));
+ x_dnd_unwind_flag = false;
+ unbind_to (ref, Qnil);
+ }
+ }
+
+ if (hold_quit.kind != NO_EVENT)
+ {
+ x_dnd_process_quit (f, hold_quit.timestamp);
+#ifdef USE_GTK
+ current_hold_quit = NULL;
+#endif
+ /* Restore the old event mask. */
+ x_restore_events_after_dnd (f, &root_window_attrs);
+
+ /* Call kbd_buffer_store event, which calls
+ handle_interrupt and sets `last-event-frame' along
+ with various other things. */
+ kbd_buffer_store_event (&hold_quit);
+ /* Now quit anyway. */
+ quit ();
+ }
+
+ if (pending_selection_requests
+ && (x_dnd_in_progress || x_dnd_waiting_for_finish))
+ {
+ x_dnd_old_window_attrs = root_window_attrs;
+ x_dnd_unwind_flag = true;
+
+ ref = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
+ x_handle_pending_selection_requests ();
+ x_dnd_unwind_flag = false;
+ unbind_to (ref, Qnil);
+ }
+
+ /* Sometimes C-g can be pressed inside a selection
+ converter, where quitting is inhibited. We want
+ to quit after the converter exits. */
+ if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit))
+ {
+ x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
+#ifdef USE_GTK
+ current_hold_quit = NULL;
+#endif
+ x_restore_events_after_dnd (f, &root_window_attrs);
+ quit ();
+ }
+
+ if (x_dnd_run_unsupported_drop_function
+ && x_dnd_waiting_for_finish)
+ {
+ x_dnd_run_unsupported_drop_function = false;
+ x_dnd_waiting_for_finish = false;
+ x_dnd_unwind_flag = true;
+
+ ref = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
+
+ if (!NILP (Vx_dnd_unsupported_drop_function))
+ val = call8 (Vx_dnd_unsupported_drop_function,
+ XCAR (XCDR (x_dnd_unsupported_drop_data)),
+ Fnth (make_fixnum (3), x_dnd_unsupported_drop_data),
+ Fnth (make_fixnum (4), x_dnd_unsupported_drop_data),
+ Fnth (make_fixnum (2), x_dnd_unsupported_drop_data),
+ make_uint (x_dnd_unsupported_drop_window),
+ frame, make_uint (x_dnd_unsupported_drop_time),
+ Fcopy_sequence (XCAR (x_dnd_unsupported_drop_data)));
+ else
+ val = Qnil;
+
+ if (NILP (val))
+ x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
+ frame, XCAR (x_dnd_unsupported_drop_data),
+ XCAR (XCDR (x_dnd_unsupported_drop_data)),
+ x_dnd_unsupported_drop_window,
+ XFIXNUM (Fnth (make_fixnum (3),
+ x_dnd_unsupported_drop_data)),
+ XFIXNUM (Fnth (make_fixnum (4),
+ x_dnd_unsupported_drop_data)),
+ x_dnd_unsupported_drop_time);
+ else if (SYMBOLP (val))
+ x_dnd_action_symbol = val;
+
+ x_dnd_unwind_flag = false;
+ unbind_to (ref, Qnil);
+
+ /* Break out of the loop now, since DND has
+ completed. */
+ break;
+ }
+
+#ifdef USE_GTK
+ if (xg_pending_quit_event.kind != NO_EVENT)
+ {
+ xg_pending_quit_event.kind = NO_EVENT;
+ current_hold_quit = NULL;
+
+ x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time);
+ x_restore_events_after_dnd (f, &root_window_attrs);
+ quit ();
+ }
+#else
+ }
+ else
+ {
+ if (x_dnd_movement_frame)
+ x_dnd_movement_frame = NULL;
+
+ if (hold_quit.kind != NO_EVENT)
+ EVENT_INIT (hold_quit);
+ }
+#endif
+ }
+
+ x_dnd_waiting_for_finish = false;
+
+#ifdef USE_GTK
+ current_hold_quit = NULL;
+#endif
+ x_dnd_movement_frame = NULL;
+ x_restore_events_after_dnd (f, &root_window_attrs);
+
+ if (x_dnd_return_frame == 3
+ && FRAME_LIVE_P (x_dnd_return_frame_object))
+ {
+ /* Deliberately preserve the last device if
+ x_dnd_return_frame_object is the drag source. */
+
+ if (x_dnd_return_frame_object != x_dnd_frame)
+ x_dnd_return_frame_object->last_mouse_device = Qnil;
+
+ x_dnd_return_frame_object->mouse_moved = true;
+
+ XSETFRAME (action, x_dnd_return_frame_object);
+ x_dnd_return_frame_object = NULL;
+
+ return unbind_to (base, action);
+ }
+
+ x_dnd_return_frame_object = NULL;
+ FRAME_DISPLAY_INFO (f)->grabbed = 0;
+
+ if (!NILP (x_dnd_action_symbol))
+ return unbind_to (base, x_dnd_action_symbol);
+
+ if (x_dnd_action != None)
+ {
+ block_input ();
+ x_catch_errors (FRAME_X_DISPLAY (f));
+ atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f),
+ x_dnd_action, &need_sync);
+
+ if (need_sync)
+ x_uncatch_errors ();
+ else
+ /* No protocol request actually happened, so avoid the extra
+ sync by calling x_uncatch_errors_after_check instead. */
+ x_uncatch_errors_after_check ();
+
+ if (atom_name)
+ {
+ action = intern (atom_name);
+ xfree (atom_name);
+ }
+ else
+ action = Qnil;
+ unblock_input ();
+
+ return unbind_to (base, action);
+ }
+
+ return unbind_to (base, Qnil);
+}
+
/* The focus may have changed. Figure out if it is a real focus change,
by checking both FocusIn/Out and Enter/LeaveNotify events.
@@ -5198,27 +11952,26 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
#ifdef HAVE_XINPUT2
case GenericEvent:
{
- XIEvent *xi_event = (XIEvent *) event->xcookie.data;
+ XIEvent *xi_event = event->xcookie.data;
+ XIEnterEvent *enter_or_focus = event->xcookie.data;
struct frame *focus_frame = dpyinfo->x_focus_event_frame;
int focus_state
= focus_frame ? focus_frame->output_data.x->focus_state : 0;
-#ifdef USE_GTK
if (xi_event->evtype == XI_FocusIn
|| xi_event->evtype == XI_FocusOut)
x_focus_changed ((xi_event->evtype == XI_FocusIn
? FocusIn : FocusOut),
- FOCUS_EXPLICIT,
- dpyinfo, frame, bufp);
- else
-#endif
- if ((xi_event->evtype == XI_Enter
- || xi_event->evtype == XI_Leave)
- && (((XIEnterEvent *) xi_event)->detail
- != XINotifyInferior)
- && ((XIEnterEvent *) xi_event)->focus
- && !(focus_state & FOCUS_EXPLICIT))
+ ((enter_or_focus->detail
+ == XINotifyPointer)
+ ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+ dpyinfo, frame, bufp);
+ else if ((xi_event->evtype == XI_Enter
+ || xi_event->evtype == XI_Leave)
+ && (enter_or_focus->detail != XINotifyInferior)
+ && enter_or_focus->focus
+ && !(focus_state & FOCUS_EXPLICIT))
x_focus_changed ((xi_event->evtype == XI_Enter
? FocusIn : FocusOut),
FOCUS_IMPLICIT,
@@ -5236,8 +11989,8 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
really has focus, and these kinds of focus event don't
correspond to real user input changes. GTK+ uses the same
filtering. */
- if (event->xfocus.mode == NotifyGrab ||
- event->xfocus.mode == NotifyUngrab)
+ if (event->xfocus.mode == NotifyGrab
+ || event->xfocus.mode == NotifyUngrab)
return;
x_focus_changed (event->type,
(event->xfocus.detail == NotifyPointer ?
@@ -5257,12 +12010,21 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
}
-#if !defined USE_X_TOOLKIT && !defined USE_GTK
+#if (defined USE_LUCID && defined HAVE_XINPUT2) \
+ || (!defined USE_X_TOOLKIT && !defined USE_GTK)
/* Handle an event saying the mouse has moved out of an Emacs frame. */
void
x_mouse_leave (struct x_display_info *dpyinfo)
{
+ Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
+
+ if (hlinfo->mouse_face_mouse_frame)
+ {
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_mouse_frame = NULL;
+ }
+
x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
}
#endif
@@ -5323,13 +12085,9 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
int syms_per_code;
XModifierKeymap *mods;
#ifdef HAVE_XKB
- Atom meta;
- Atom super;
- Atom hyper;
- Atom shiftlock;
- Atom alt;
int i;
int found_meta_p = false;
+ uint vmodmask;
#endif
dpyinfo->meta_mod_mask = 0;
@@ -5338,33 +12096,28 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
dpyinfo->super_mod_mask = 0;
dpyinfo->hyper_mod_mask = 0;
- XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-
#ifdef HAVE_XKB
- if (dpyinfo->xkb_desc)
+ if (dpyinfo->xkb_desc
+ && dpyinfo->xkb_desc->server)
{
- meta = XInternAtom (dpyinfo->display, "Meta", False);
- super = XInternAtom (dpyinfo->display, "Super", False);
- hyper = XInternAtom (dpyinfo->display, "Hyper", False);
- shiftlock = XInternAtom (dpyinfo->display, "ShiftLock", False);
- alt = XInternAtom (dpyinfo->display, "Alt", False);
-
for (i = 0; i < XkbNumVirtualMods; i++)
{
- uint vmodmask = dpyinfo->xkb_desc->server->vmods[i];
+ vmodmask = dpyinfo->xkb_desc->server->vmods[i];
- if (dpyinfo->xkb_desc->names->vmods[i] == meta)
+ if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta)
{
dpyinfo->meta_mod_mask |= vmodmask;
- found_meta_p = vmodmask;
+
+ if (vmodmask)
+ found_meta_p = true;
}
- else if (dpyinfo->xkb_desc->names->vmods[i] == alt)
+ else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt)
dpyinfo->alt_mod_mask |= vmodmask;
- else if (dpyinfo->xkb_desc->names->vmods[i] == super)
+ else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Super)
dpyinfo->super_mod_mask |= vmodmask;
- else if (dpyinfo->xkb_desc->names->vmods[i] == hyper)
+ else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Hyper)
dpyinfo->hyper_mod_mask |= vmodmask;
- else if (dpyinfo->xkb_desc->names->vmods[i] == shiftlock)
+ else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_ShiftLock)
dpyinfo->shift_lock_mask |= vmodmask;
}
@@ -5384,9 +12137,19 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
}
#endif
+ XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
+
syms = XGetKeyboardMapping (dpyinfo->display,
min_code, max_code - min_code + 1,
&syms_per_code);
+
+ if (!syms)
+ {
+ dpyinfo->meta_mod_mask = Mod1Mask;
+ dpyinfo->super_mod_mask = Mod2Mask;
+ return;
+ }
+
mods = XGetModifierMapping (dpyinfo->display);
/* Scan the modifier table to see which modifier bits the Meta and
@@ -5472,8 +12235,17 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
}
+ /* If some keys are both super and hyper, make them just super.
+ Many X servers are misconfigured so that super and hyper are both
+ Mod4, but most users have no hyper key. */
+ if (dpyinfo->hyper_mod_mask & dpyinfo->super_mod_mask)
+ dpyinfo->hyper_mod_mask &= ~dpyinfo->super_mod_mask;
+
XFree (syms);
- XFreeModifiermap (mods);
+
+ if (dpyinfo->modmap)
+ XFreeModifiermap (dpyinfo->modmap);
+ dpyinfo->modmap = mods;
}
/* Convert between the modifier bits X uses and the modifier bits
@@ -5576,13 +12348,26 @@ get_keysym_name (int keysym)
/* Prepare a mouse-event in *RESULT for placement in the input queue.
If the event is a button press, then note that we have grabbed
- the mouse. */
+ the mouse.
+
+ The XButtonEvent structure passed as EVENT might not come from the
+ X server, and instead be artificially constructed from input
+ extension events. In these special events, the only fields that
+ are initialized are `time', `button', `state', `type', `window' and
+ `x' and `y'. This function should not access any other fields in
+ EVENT without also initializing the corresponding fields in `bv'
+ under the XI_ButtonPress and XI_ButtonRelease labels inside
+ `handle_one_xevent'. */
static Lisp_Object
x_construct_mouse_click (struct input_event *result,
const XButtonEvent *event,
struct frame *f)
{
+ int x = event->x;
+ int y = event->y;
+ Window dummy;
+
/* Make the event type NO_EVENT; we'll change that when we decide
otherwise. */
result->kind = MOUSE_CLICK_EVENT;
@@ -5594,8 +12379,16 @@ x_construct_mouse_click (struct input_event *result,
? up_modifier
: down_modifier));
- XSETINT (result->x, event->x);
- XSETINT (result->y, event->y);
+ /* If result->window is not the frame's edit widget (which can
+ happen with GTK+ scroll bars, for example), translate the
+ coordinates so they appear at the correct position. */
+ if (event->window != FRAME_X_WINDOW (f))
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+ event->window, FRAME_X_WINDOW (f),
+ x, y, &x, &y, &dummy);
+
+ XSETINT (result->x, x);
+ XSETINT (result->y, y);
XSETFRAME (result->frame_or_window, f);
result->arg = Qnil;
return Qnil;
@@ -5607,10 +12400,20 @@ x_construct_mouse_click (struct input_event *result,
We have received a mouse movement event, which is given in *event.
If the mouse is over a different glyph than it was last time, tell
the mainstream emacs code by setting mouse_moved. If not, ask for
- another motion event, so we can check again the next time it moves. */
+ another motion event, so we can check again the next time it moves.
+
+ The XMotionEvent structure passed as EVENT might not come from the
+ X server, and instead be artificially constructed from input
+ extension events. In these special events, the only fields that
+ are initialized are `time', `window', `send_event', `x' and `y'.
+ This function should not access any other fields in EVENT without
+ also initializing the corresponding fields in `ev' under the
+ XI_Motion, XI_Enter and XI_Leave labels inside
+ `handle_one_xevent'. */
static bool
-x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
+x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
+ Lisp_Object device)
{
XRectangle *r;
struct x_display_info *dpyinfo;
@@ -5620,6 +12423,7 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
dpyinfo = FRAME_DISPLAY_INFO (frame);
dpyinfo->last_mouse_movement_time = event->time;
+ dpyinfo->last_mouse_movement_time_send_event = event->send_event;
dpyinfo->last_mouse_motion_frame = frame;
dpyinfo->last_mouse_motion_x = event->x;
dpyinfo->last_mouse_motion_y = event->y;
@@ -5627,6 +12431,7 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
if (event->window != FRAME_X_WINDOW (frame))
{
frame->mouse_moved = true;
+ frame->last_mouse_device = device;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
dpyinfo->last_mouse_glyph_frame = NULL;
@@ -5641,6 +12446,7 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
|| event->y < r->y || event->y >= r->y + r->height)
{
frame->mouse_moved = true;
+ frame->last_mouse_device = device;
dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, event->x, event->y);
/* Remember which glyph we're now on. */
@@ -5652,6 +12458,80 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
return false;
}
+/* Get a sibling below WINDOW on DPY at PARENT_X and PARENT_Y. */
+static Window
+x_get_window_below (Display *dpy, Window window,
+ int parent_x, int parent_y,
+ int *inner_x, int *inner_y)
+{
+ int rc, i, cx, cy;
+ XWindowAttributes attrs;
+ unsigned int nchildren;
+ Window root, parent, *children, value;
+ bool window_seen;
+
+ /* TODO: rewrite to have less dependencies. */
+
+ children = NULL;
+ window_seen = false;
+ value = None;
+
+ rc = XQueryTree (dpy, window, &root, &parent,
+ &children, &nchildren);
+
+ if (rc)
+ {
+ if (children)
+ XFree (children);
+
+ rc = XQueryTree (dpy, parent, &root,
+ &parent, &children, &nchildren);
+ }
+
+ if (rc)
+ {
+ for (i = nchildren - 1; i >= 0; --i)
+ {
+ if (children[i] == window)
+ {
+ window_seen = true;
+ continue;
+ }
+
+ if (!window_seen)
+ continue;
+
+ rc = XGetWindowAttributes (dpy, children[i], &attrs);
+
+ if (rc && attrs.map_state != IsViewable)
+ continue;
+
+ if (rc && parent_x >= attrs.x
+ && parent_y >= attrs.y
+ && parent_x < attrs.x + attrs.width
+ && parent_y < attrs.y + attrs.height)
+ {
+ value = children[i];
+ cx = parent_x - attrs.x;
+ cy = parent_y - attrs.y;
+
+ break;
+ }
+ }
+ }
+
+ if (children)
+ XFree (children);
+
+ if (value)
+ {
+ *inner_x = cx;
+ *inner_y = cy;
+ }
+
+ return value;
+}
+
/* Return the current position of the mouse.
*FP should be a frame which indicates which display to ask about.
@@ -5677,8 +12557,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
Time *timestamp)
{
- struct frame *f1;
+ struct frame *f1, *maybe_tooltip;
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ bool unrelated_tooltip;
block_input ();
@@ -5733,9 +12614,11 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
Window first_win = 0;
#endif
int win_x, win_y;
- int parent_x = 0, parent_y = 0;
+ int parent_x, parent_y;
win = root;
+ parent_x = root_x;
+ parent_y = root_y;
/* XTranslateCoordinates can get errors if the window
structure is changing at the same time this function
@@ -5743,7 +12626,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
x_catch_errors (FRAME_X_DISPLAY (*fp));
- if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping))
+ if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source))
{
/* If mouse was grabbed on a frame, give coords for that frame
even if the mouse is now outside it. */
@@ -5769,6 +12653,22 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
root_x, root_y, &win_x, &win_y,
/* Child of win. */
&child);
+
+ /* If CHILD is a tooltip frame, look below it if
+ track-mouse is drag-source. */
+ if (child != None
+ && (EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping)))
+ {
+ maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child,
+ &unrelated_tooltip);
+
+ if (maybe_tooltip || unrelated_tooltip)
+ child = x_get_window_below (dpyinfo->display, child,
+ parent_x, parent_y, &win_x,
+ &win_y);
+ }
+
if (child == None || child == win)
{
#ifdef USE_GTK
@@ -5831,8 +12731,20 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
#endif /* USE_X_TOOLKIT */
}
+ /* Set last user time to avoid confusing some window managers
+ about the tooltip displayed during drag-and-drop. */
+
+ if ((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && (dpyinfo->last_user_time
+ < dpyinfo->last_mouse_movement_time))
+ x_display_set_last_user_time (dpyinfo,
+ dpyinfo->last_mouse_movement_time,
+ dpyinfo->last_mouse_movement_time_send_event);
+
if ((!f1 || FRAME_TOOLTIP_P (f1))
- && EQ (track_mouse, Qdropping)
+ && (EQ (track_mouse, Qdropping)
+ || EQ (track_mouse, Qdrag_source))
&& gui_mouse_grabbed (dpyinfo))
{
/* When dropping then if we didn't get a frame or only a
@@ -5848,12 +12760,28 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
root_x, root_y, &win_x, &win_y,
/* Child of win. */
&child);
- f1 = dpyinfo->last_mouse_frame;
+
+ if (!EQ (track_mouse, Qdrag_source)
+ /* Don't let tooltips interfere. */
+ || (f1 && FRAME_TOOLTIP_P (f1)))
+ f1 = dpyinfo->last_mouse_frame;
+ else
+ {
+ /* Don't set FP but do set WIN_X and WIN_Y in this
+ case, so make_lispy_movement knows which
+ coordinates to report. */
+ *bar_window = Qnil;
+ *part = 0;
+ *fp = NULL;
+ XSETINT (*x, win_x);
+ XSETINT (*y, win_y);
+ *timestamp = dpyinfo->last_mouse_movement_time;
+ }
}
else if (f1 && FRAME_TOOLTIP_P (f1))
f1 = NULL;
- if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
+ if (x_had_errors_p (dpyinfo->display))
f1 = NULL;
x_uncatch_errors_after_check ();
@@ -5863,7 +12791,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
{
struct scroll_bar *bar;
- bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
+ bar = x_window_to_scroll_bar (dpyinfo->display, win, 2);
if (bar)
{
@@ -5876,7 +12804,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
if (!f1 && insist > 0)
f1 = SELECTED_FRAME ();
- if (f1)
+ if (f1 && FRAME_X_P (f1))
{
/* Ok, we found a frame. Store all the values.
last_mouse_glyph is a rectangle used to reduce the
@@ -5886,7 +12814,6 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
- /* FIXME: what if F1 is not an X frame? */
dpyinfo = FRAME_DISPLAY_INFO (f1);
remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
dpyinfo->last_mouse_glyph_frame = f1;
@@ -5922,9 +12849,9 @@ x_window_to_scroll_bar (Display *display, Window window_id, int type)
{
Lisp_Object tail, frame;
-#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
+#if defined (USE_GTK) && !defined (HAVE_GTK3) && defined (USE_TOOLKIT_SCROLL_BARS)
window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
+#endif /* USE_GTK && !HAVE_GTK3 && USE_TOOLKIT_SCROLL_BARS */
FOR_EACH_FRAME (tail, frame)
{
@@ -6103,6 +13030,35 @@ xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_n
}
#endif /* not USE_GTK */
+/* Protect WINDOW from garbage collection until a matching scroll bar
+ message is received. Return whether or not protection
+ succeeded. */
+static bool
+x_protect_window_for_callback (struct x_display_info *dpyinfo,
+ Lisp_Object window)
+{
+ if (dpyinfo->n_protected_windows + 1
+ >= dpyinfo->protected_windows_max)
+ return false;
+
+ dpyinfo->protected_windows[dpyinfo->n_protected_windows++]
+ = window;
+ return true;
+}
+
+static void
+x_unprotect_window_for_callback (struct x_display_info *dpyinfo)
+{
+ if (!dpyinfo->n_protected_windows)
+ emacs_abort ();
+
+ dpyinfo->n_protected_windows--;
+
+ if (dpyinfo->n_protected_windows)
+ memmove (dpyinfo->protected_windows, &dpyinfo->protected_windows[1],
+ sizeof (Lisp_Object) * dpyinfo->n_protected_windows);
+}
+
/* Send a client message with message type Xatom_Scrollbar for a
scroll action to the frame of WINDOW. PART is a value identifying
the part of the scroll bar that was clicked on. PORTION is the
@@ -6120,8 +13076,12 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
verify (INTPTR_WIDTH <= 64);
int sign_shift = INTPTR_WIDTH - 32;
- block_input ();
+ /* Don't do anything if too many scroll bar events have been
+ sent but not received. */
+ if (!x_protect_window_for_callback (FRAME_DISPLAY_INFO (f), window))
+ return;
+ block_input ();
/* Construct a ClientMessage event to send to the frame. */
ev->type = ClientMessage;
ev->message_type = (horizontal
@@ -6151,7 +13111,8 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
/* Setting the event mask to zero means that the message will
be sent to the client that created the window, and if that
window no longer exists, no event will be sent. */
- XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
+ XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False,
+ NoEventMask, &event);
unblock_input ();
}
@@ -6646,6 +13607,30 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
XDefineCursor (XtDisplay (widget), XtWindow (widget),
f->output_data.x->nontext_cursor);
+#ifdef HAVE_XINPUT2
+ /* Ask for input extension button and motion events. This lets us
+ send the proper `wheel-up' or `wheel-down' events to Emacs. */
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ {
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ XISelectEvents (XtDisplay (widget), XtWindow (widget),
+ &mask, 1);
+ }
+#endif
#else /* !USE_MOTIF i.e. use Xaw */
/* Set resources. Create the widget. The background of the
@@ -6847,6 +13832,30 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
XDefineCursor (XtDisplay (widget), XtWindow (widget),
f->output_data.x->nontext_cursor);
+#ifdef HAVE_XINPUT2
+ /* Ask for input extension button and motion events. This lets us
+ send the proper `wheel-up' or `wheel-down' events to Emacs. */
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ {
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ XISelectEvents (XtDisplay (widget), XtWindow (widget),
+ &mask, 1);
+ }
+#endif
#else /* !USE_MOTIF i.e. use Xaw */
/* Set resources. Create the widget. The background of the
@@ -7233,6 +14242,9 @@ x_scroll_bar_create (struct window *w, int top, int left,
XSetWindowAttributes a;
unsigned long mask;
Window window;
+#ifdef HAVE_XDBE
+ Drawable drawable;
+#endif
a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
if (a.background_pixel == -1)
@@ -7261,7 +14273,51 @@ x_scroll_bar_create (struct window *w, int top, int left,
CopyFromParent,
/* Attributes. */
mask, &a);
+#ifdef HAVE_XDBE
+ if (FRAME_DISPLAY_INFO (f)->supports_xdbe
+ && FRAME_X_DOUBLE_BUFFERED_P (f))
+ {
+ x_catch_errors (FRAME_X_DISPLAY (f));
+ drawable = XdbeAllocateBackBufferName (FRAME_X_DISPLAY (f),
+ window, XdbeCopied);
+ if (x_had_errors_p (FRAME_X_DISPLAY (f)))
+ drawable = window;
+ else
+ XSetWindowBackgroundPixmap (FRAME_X_DISPLAY (f), window, None);
+ x_uncatch_errors_after_check ();
+ }
+ else
+ drawable = window;
+#endif
+
+#ifdef HAVE_XINPUT2
+ /* Ask for input extension button and motion events. This lets us
+ send the proper `wheel-up' or `wheel-down' events to Emacs. */
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ {
+ XIEventMask mask;
+ ptrdiff_t l = XIMaskLen (XI_LASTEVENT);
+ unsigned char *m;
+
+ mask.mask = m = alloca (l);
+ memset (m, 0, l);
+ mask.mask_len = l;
+
+ mask.deviceid = XIAllMasterDevices;
+ XISetMask (m, XI_ButtonPress);
+ XISetMask (m, XI_ButtonRelease);
+ XISetMask (m, XI_Motion);
+ XISetMask (m, XI_Enter);
+ XISetMask (m, XI_Leave);
+
+ XISelectEvents (FRAME_X_DISPLAY (f), window, &mask, 1);
+ }
+#endif
+
bar->x_window = window;
+#ifdef HAVE_XDBE
+ bar->x_drawable = drawable;
+#endif
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -7335,7 +14391,11 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
bool rebuild)
{
bool dragging = bar->dragging != -1;
+#ifndef HAVE_XDBE
Window w = bar->x_window;
+#else
+ Drawable w = bar->x_drawable;
+#endif
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
@@ -7385,10 +14445,22 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
/* Draw the empty space above the handle. Note that we can't clear
zero-height areas; that means "clear to end of window." */
if ((inside_width > 0) && (start > 0))
- x_clear_area1 (FRAME_X_DISPLAY (f), w,
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER,
- inside_width, start, False);
+ {
+ if (f->output_data.x->scroll_bar_background_pixel != -1)
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ f->output_data.x->scroll_bar_background_pixel);
+ else
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_BACKGROUND_PIXEL (f));
+
+ XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
+ VERTICAL_SCROLL_BAR_LEFT_BORDER,
+ VERTICAL_SCROLL_BAR_TOP_BORDER,
+ inside_width, start);
+
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_FOREGROUND_PIXEL (f));
+ }
/* Change to proper foreground color if one is specified. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -7402,20 +14474,38 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
VERTICAL_SCROLL_BAR_TOP_BORDER + start,
inside_width, end - start);
- /* Restore the foreground color of the GC if we changed it above. */
- if (f->output_data.x->scroll_bar_foreground_pixel != -1)
- XSetForeground (FRAME_X_DISPLAY (f), gc,
- FRAME_FOREGROUND_PIXEL (f));
/* Draw the empty space below the handle. Note that we can't
clear zero-height areas; that means "clear to end of window." */
if ((inside_width > 0) && (end < inside_height))
- x_clear_area1 (FRAME_X_DISPLAY (f), w,
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER + end,
- inside_width, inside_height - end, False);
+ {
+ if (f->output_data.x->scroll_bar_background_pixel != -1)
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ f->output_data.x->scroll_bar_background_pixel);
+ else
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_BACKGROUND_PIXEL (f));
+
+ XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
+ VERTICAL_SCROLL_BAR_LEFT_BORDER,
+ VERTICAL_SCROLL_BAR_TOP_BORDER + end,
+ inside_width, inside_height - end);
+
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_FOREGROUND_PIXEL (f));
+ }
+
+ /* Restore the foreground color of the GC if we changed it above. */
+ if (f->output_data.x->scroll_bar_foreground_pixel != -1)
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_FOREGROUND_PIXEL (f));
}
+#ifdef HAVE_XDBE
+ if (!rebuild)
+ x_scroll_bar_end_update (FRAME_DISPLAY_INFO (f), bar);
+#endif
+
unblock_input ();
}
@@ -7437,6 +14527,11 @@ x_scroll_bar_remove (struct scroll_bar *bar)
XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
#endif /* not USE_GTK */
#else
+#ifdef HAVE_XDBE
+ if (bar->x_window != bar->x_drawable)
+ XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
+ bar->x_drawable);
+#endif
XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
#endif
@@ -7857,29 +14952,79 @@ XTjudge_scroll_bars (struct frame *f)
static void
x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
{
+#ifndef HAVE_XDBE
Window w = bar->x_window;
+#else
+ Drawable w = bar->x_drawable;
+#endif
+ int x, y, width, height;
+
+ if (event->type == Expose)
+ {
+ x = event->xexpose.x;
+ y = event->xexpose.y;
+ width = event->xexpose.width;
+ height = event->xexpose.height;
+ }
+ else
+ {
+ x = event->xgraphicsexpose.x;
+ y = event->xgraphicsexpose.y;
+ width = event->xgraphicsexpose.width;
+ height = event->xgraphicsexpose.height;
+ }
+
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
block_input ();
+#ifdef HAVE_XDBE
+ if (w != bar->x_window)
+ {
+ if (f->output_data.x->scroll_bar_background_pixel != -1)
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ f->output_data.x->scroll_bar_background_pixel);
+ else
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_BACKGROUND_PIXEL (f));
+
+ XFillRectangle (FRAME_X_DISPLAY (f),
+ bar->x_drawable,
+ gc, x, y, width, height);
+
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_FOREGROUND_PIXEL (f));
+ }
+#endif
+
x_scroll_bar_set_handle (bar, bar->start, bar->end, true);
/* Switch to scroll bar foreground color. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
XSetForeground (FRAME_X_DISPLAY (f), gc,
- f->output_data.x->scroll_bar_foreground_pixel);
+ f->output_data.x->scroll_bar_foreground_pixel);
/* Draw a one-pixel border just inside the edges of the scroll bar. */
XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
/* x, y, width, height */
0, 0, bar->width - 1, bar->height - 1);
+ /* XDrawPoint (FRAME_X_DISPLAY (f), w, gc,
+ bar->width - 1, bar->height - 1);
+
+ This code is no longer required since the normal GC now uses the
+ regular line width. */
+
/* Restore the foreground color of the GC if we changed it above. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
XSetForeground (FRAME_X_DISPLAY (f), gc,
FRAME_FOREGROUND_PIXEL (f));
+#ifdef HAVE_XDBE
+ x_scroll_bar_end_update (FRAME_DISPLAY_INFO (f), bar);
+#endif
+
unblock_input ();
}
@@ -7895,8 +15040,14 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
static void
x_scroll_bar_handle_click (struct scroll_bar *bar,
const XEvent *event,
- struct input_event *emacs_event)
+ struct input_event *emacs_event,
+ Lisp_Object device)
{
+ int left_range, x, top_range, y;
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ int new_start, new_end;
+#endif
+
if (! WINDOWP (bar->window))
emacs_abort ();
@@ -7914,11 +15065,15 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
emacs_event->frame_or_window = bar->window;
emacs_event->arg = Qnil;
emacs_event->timestamp = event->xbutton.time;
+
+ if (!NILP (device))
+ emacs_event->device = device;
+
if (bar->horizontal)
{
- int left_range
- = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
- int x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
+
+ left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
+ x = event->xbutton.x - HORIZONTAL_SCROLL_BAR_LEFT_BORDER;
if (x < 0) x = 0;
if (x > left_range) x = left_range;
@@ -7934,8 +15089,8 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
/* If the user has released the handle, set it to its final position. */
if (event->type == ButtonRelease && bar->dragging != -1)
{
- int new_start = - bar->dragging;
- int new_end = new_start + bar->end - bar->start;
+ new_start = - bar->dragging;
+ new_end = new_start + bar->end - bar->start;
x_scroll_bar_set_handle (bar, new_start, new_end, false);
bar->dragging = -1;
@@ -7947,9 +15102,9 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
}
else
{
- int top_range
+ top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
- int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
+ y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
if (y < 0) y = 0;
if (y > top_range) y = top_range;
@@ -7965,8 +15120,8 @@ x_scroll_bar_handle_click (struct scroll_bar *bar,
/* If the user has released the handle, set it to its final position. */
if (event->type == ButtonRelease && bar->dragging != -1)
{
- int new_start = y - bar->dragging;
- int new_end = new_start + bar->end - bar->start;
+ new_start = y - bar->dragging;
+ new_end = new_start + bar->end - bar->start;
x_scroll_bar_set_handle (bar, new_start, new_end, false);
bar->dragging = -1;
@@ -7993,6 +15148,7 @@ x_scroll_bar_note_movement (struct scroll_bar *bar,
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
dpyinfo->last_mouse_movement_time = event->time;
+ dpyinfo->last_mouse_movement_time_send_event = event->send_event;
dpyinfo->last_mouse_scroll_bar = bar;
f->mouse_moved = true;
@@ -8011,6 +15167,24 @@ x_scroll_bar_note_movement (struct scroll_bar *bar,
}
}
+#ifdef HAVE_XDBE
+static void
+x_scroll_bar_end_update (struct x_display_info *dpyinfo,
+ struct scroll_bar *bar)
+{
+ XdbeSwapInfo swap_info;
+
+ /* This means the scroll bar is double-buffered. */
+ if (bar->x_drawable != bar->x_window)
+ {
+ memset (&swap_info, 0, sizeof swap_info);
+ swap_info.swap_window = bar->x_window;
+ swap_info.swap_action = XdbeCopied;
+ XdbeSwapBuffers (dpyinfo->display, &swap_info, 1);
+ }
+}
+#endif
+
#endif /* !USE_TOOLKIT_SCROLL_BARS */
/* Return information to the user about the current position of the mouse
@@ -8161,6 +15335,16 @@ x_scroll_bar_clear (struct frame *f)
{
#ifndef USE_TOOLKIT_SCROLL_BARS
Lisp_Object bar;
+#ifdef HAVE_XDBE
+ GC gc = f->output_data.x->normal_gc;
+
+ if (f->output_data.x->scroll_bar_background_pixel != -1)
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ f->output_data.x->scroll_bar_background_pixel);
+ else
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_BACKGROUND_PIXEL (f));
+#endif
/* We can have scroll bars even if this is 0,
if we just turned off scroll bar mode.
@@ -8168,9 +15352,27 @@ x_scroll_bar_clear (struct frame *f)
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
- XClearArea (FRAME_X_DISPLAY (f),
- XSCROLL_BAR (bar)->x_window,
- 0, 0, 0, 0, True);
+ {
+#ifdef HAVE_XDBE
+ if (XSCROLL_BAR (bar)->x_window
+ == XSCROLL_BAR (bar)->x_drawable)
+#endif
+ XClearArea (FRAME_X_DISPLAY (f),
+ XSCROLL_BAR (bar)->x_window,
+ 0, 0, 0, 0, True);
+#ifdef HAVE_XDBE
+ else
+ XFillRectangle (FRAME_X_DISPLAY (f),
+ XSCROLL_BAR (bar)->x_drawable,
+ gc, 0, 0, XSCROLL_BAR (bar)->width,
+ XSCROLL_BAR (bar)->height);
+#endif
+ }
+
+#ifdef HAVE_XDBE
+ XSetForeground (FRAME_X_DISPLAY (f), gc,
+ FRAME_FOREGROUND_PIXEL (f));
+#endif
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
@@ -8205,13 +15407,6 @@ static struct x_display_info *XTread_socket_fake_io_error;
static struct x_display_info *next_noop_dpyinfo;
-enum
-{
- X_EVENT_NORMAL,
- X_EVENT_GOTO_OUT,
- X_EVENT_DROP
-};
-
/* Filter events for the current X input method.
DPYINFO is the display this event is for.
EVENT is the X event to filter.
@@ -8229,18 +15424,71 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event)
XFilterEvent because that's the one for which the IC
was created. */
- struct frame *f1 = x_any_window_to_frame (dpyinfo,
- event->xclient.window);
+ struct frame *f1;
- return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
-}
+#if defined HAVE_XINPUT2 && defined USE_GTK
+ bool xinput_event = false;
+ if (dpyinfo->supports_xi2
+ && event->type == GenericEvent
+ && (event->xgeneric.extension
+ == dpyinfo->xi2_opcode)
+ && ((event->xgeneric.evtype
+ == XI_KeyPress)
+ || (event->xgeneric.evtype
+ == XI_KeyRelease)))
+ {
+ f1 = x_any_window_to_frame (dpyinfo,
+ ((XIDeviceEvent *)
+ event->xcookie.data)->event);
+ xinput_event = true;
+ }
+ else
#endif
+ f1 = x_any_window_to_frame (dpyinfo,
+ event->xclient.window);
#ifdef USE_GTK
-static int current_count;
-static int current_finish;
-static struct input_event *current_hold_quit;
+ if (!x_gtk_use_native_input
+ && !dpyinfo->prefer_native_input)
+ {
+#endif
+ return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
+#ifdef USE_GTK
+ }
+ else if (f1 && (event->type == KeyPress
+ || event->type == KeyRelease
+#ifdef HAVE_XINPUT2
+ || xinput_event
+#endif
+ ))
+ {
+ bool result;
+ block_input ();
+ result = xg_filter_key (f1, event);
+ unblock_input ();
+
+ /* Clear `xg_pending_quit_event' so we don't end up reacting to quit
+ events sent outside the main event loop (i.e. those sent from
+ inside a popup menu event loop). */
+
+ if (popup_activated ())
+ xg_pending_quit_event.kind = NO_EVENT;
+
+ 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;
+ }
+
+ return 0;
+#endif
+}
+#endif
+
+#ifdef USE_GTK
/* This is the filter function invoked by the GTK event loop.
It is invoked before the XEvent is translated to a GdkEvent,
so we have a chance to act on the event before GTK. */
@@ -8267,6 +15515,40 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
unblock_input ();
return GDK_FILTER_REMOVE;
}
+#elif USE_GTK
+ if (dpyinfo && (dpyinfo->prefer_native_input
+ || x_gtk_use_native_input)
+ && (xev->type == KeyPress
+#ifdef HAVE_XINPUT2
+ /* GTK claims cookies for us, so we don't have to claim
+ them here. */
+ || (dpyinfo->supports_xi2
+ && xev->type == GenericEvent
+ && (xev->xgeneric.extension
+ == dpyinfo->xi2_opcode)
+ && ((xev->xgeneric.evtype
+ == XI_KeyPress)
+ || (xev->xgeneric.evtype
+ == XI_KeyRelease)))
+#endif
+ ))
+ {
+ struct frame *f;
+
+#ifdef HAVE_XINPUT2
+ if (xev->type == GenericEvent)
+ f = x_any_window_to_frame (dpyinfo,
+ ((XIDeviceEvent *) xev->xcookie.data)->event);
+ else
+#endif
+ f = x_any_window_to_frame (dpyinfo, xev->xany.window);
+
+ if (f && xg_filter_key (f, xev))
+ {
+ unblock_input ();
+ return GDK_FILTER_REMOVE;
+ }
+ }
#endif
if (! dpyinfo)
@@ -8298,9 +15580,9 @@ x_net_wm_state (struct frame *f, Window window)
{
int value = FULLSCREEN_NONE;
Lisp_Object lval = Qnil;
- bool sticky = false;
+ bool sticky = false, shaded = false;
- x_get_current_wm_state (f, window, &value, &sticky);
+ x_get_current_wm_state (f, window, &value, &sticky, &shaded);
switch (value)
{
@@ -8319,28 +15601,52 @@ x_net_wm_state (struct frame *f, Window window)
}
store_frame_param (f, Qfullscreen, lval);
-/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
+ store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
+ store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
}
-/* Flip back buffers on any frames with undrawn content. */
+/* Flip back buffers on F if it has undrawn content. */
+
+#ifdef HAVE_XDBE
static void
-flush_dirty_back_buffers (void)
+flush_dirty_back_buffer_on (struct frame *f)
{
block_input ();
- Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- if (FRAME_LIVE_P (f) &&
- FRAME_X_P (f) &&
- FRAME_X_WINDOW (f) &&
- !FRAME_GARBAGED_P (f) &&
- !buffer_flipping_blocked_p () &&
- FRAME_X_NEED_BUFFER_FLIP (f))
- show_back_buffer (f);
- }
+ if (!FRAME_GARBAGED_P (f)
+ && !buffer_flipping_blocked_p ()
+ && FRAME_X_NEED_BUFFER_FLIP (f))
+ show_back_buffer (f);
unblock_input ();
}
+#endif
+
+#ifdef HAVE_GTK3
+void
+x_scroll_bar_configure (GdkEvent *event)
+{
+ XEvent configure;
+ GdkDisplay *gdpy;
+ Display *dpy;
+
+ configure.xconfigure.type = ConfigureNotify;
+ configure.xconfigure.serial = 0;
+ configure.xconfigure.send_event = event->configure.send_event;
+ configure.xconfigure.x = event->configure.x;
+ configure.xconfigure.y = event->configure.y;
+ configure.xconfigure.width = event->configure.width;
+ configure.xconfigure.height = event->configure.height;
+ configure.xconfigure.border_width = 0;
+ configure.xconfigure.event = GDK_WINDOW_XID (event->configure.window);
+ configure.xconfigure.window = GDK_WINDOW_XID (event->configure.window);
+ configure.xconfigure.above = None;
+ configure.xconfigure.override_redirect = False;
+
+ gdpy = gdk_window_get_display (event->configure.window);
+ dpy = gdk_x11_display_get_xdisplay (gdpy);
+
+ x_dispatch_event (&configure, dpy);
+}
+#endif
/**
mouse_or_wdesc_frame: When not dropping and the mouse was grabbed
@@ -8357,7 +15663,8 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
? dpyinfo->last_mouse_frame
: NULL);
- if (lm_f && !EQ (track_mouse, Qdropping))
+ if (lm_f && !EQ (track_mouse, Qdropping)
+ && !EQ (track_mouse, Qdrag_source))
return lm_f;
else
{
@@ -8373,6 +15680,598 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc)
}
}
+static void
+x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes)
+{
+ Lisp_Object monitor, geometry;
+ int min_x, min_y, max_x, max_y;
+ int width, height;
+
+ width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame));
+ height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame));
+
+ max_y = -1;
+
+ /* Try to determine the monitor where the mouse pointer is and
+ its geometry. See bug#22549. */
+ while (CONSP (attributes))
+ {
+ monitor = XCAR (attributes);
+ geometry = assq_no_quit (Qgeometry, monitor);
+
+ if (CONSP (geometry))
+ {
+ min_x = XFIXNUM (Fnth (make_fixnum (1), geometry));
+ min_y = XFIXNUM (Fnth (make_fixnum (2), geometry));
+ max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry));
+ max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry));
+
+ if (min_x <= *root_x && *root_x < max_x
+ && min_y <= *root_y && *root_y < max_y)
+ break;
+
+ max_y = -1;
+ }
+
+ attributes = XCDR (attributes);
+ }
+
+ /* It was not possible to determine the monitor's geometry, so we
+ assign some sane defaults here: */
+ if (max_y < 0)
+ {
+ min_x = 0;
+ min_y = 0;
+ max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame));
+ max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame));
+ }
+
+ if (*root_y + XFIXNUM (tip_dy) <= min_y)
+ *root_y = min_y; /* Can happen for negative dy */
+ else if (*root_y + XFIXNUM (tip_dy) + height <= max_y)
+ /* It fits below the pointer */
+ *root_y += XFIXNUM (tip_dy);
+ else if (height + XFIXNUM (tip_dy) + min_y <= *root_y)
+ /* It fits above the pointer. */
+ *root_y -= height + XFIXNUM (tip_dy);
+ else
+ /* Put it on the top. */
+ *root_y = min_y;
+
+ if (*root_x + XFIXNUM (tip_dx) <= min_x)
+ *root_x = 0; /* Can happen for negative dx */
+ else if (*root_x + XFIXNUM (tip_dx) + width <= max_x)
+ /* It fits to the right of the pointer. */
+ *root_x += XFIXNUM (tip_dx);
+ else if (width + XFIXNUM (tip_dx) + min_x <= *root_x)
+ /* It fits to the left of the pointer. */
+ *root_x -= width + XFIXNUM (tip_dx);
+ else
+ /* Put it left justified on the screen -- it ought to fit that way. */
+ *root_x = min_x;
+}
+
+static void
+x_dnd_update_tooltip_position (int root_x, int root_y)
+{
+ struct frame *tip_f;
+
+ if (!x_dnd_in_progress || !x_dnd_update_tooltip)
+ return;
+
+ if (!FRAMEP (tip_frame))
+ return;
+
+ tip_f = XFRAME (tip_frame);
+
+ if (!FRAME_LIVE_P (tip_f)
+ || !FRAME_VISIBLE_P (tip_f)
+ || (FRAME_X_DISPLAY (tip_f)
+ != FRAME_X_DISPLAY (x_dnd_frame)))
+ return;
+
+ if (tip_window != None
+ && FIXNUMP (tip_dx) && FIXNUMP (tip_dy))
+ {
+ x_dnd_compute_tip_xy (&root_x, &root_y,
+ x_dnd_monitors);
+
+ XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame),
+ tip_window, root_x, root_y);
+ }
+}
+
+static void
+x_dnd_update_tooltip_now (void)
+{
+ int root_x, root_y;
+ Window root, child;
+ int win_x, win_y;
+ unsigned int mask;
+ Bool rc;
+ struct x_display_info *dpyinfo;
+
+ if (!x_dnd_in_progress || !x_dnd_update_tooltip)
+ return;
+
+ dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame);
+
+ rc = XQueryPointer (dpyinfo->display,
+ dpyinfo->root_window,
+ &root, &child, &root_x,
+ &root_y, &win_x, &win_y,
+ &mask);
+
+ if (rc)
+ x_dnd_update_tooltip_position (root_x, root_y);
+}
+
+/* Get the window underneath the pointer, see if it moved, and update
+ the DND state accordingly. */
+static void
+x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp)
+{
+ int root_x, root_y, dummy_x, dummy_y, target_proto, motif_style;
+ unsigned int dummy_mask;
+ Window dummy, dummy_child, target, toplevel;
+ xm_top_level_leave_message lmsg;
+ xm_top_level_enter_message emsg;
+ xm_drag_motion_message dmsg;
+ xm_drop_start_message dsmsg;
+ bool was_frame;
+
+ if (XQueryPointer (dpyinfo->display,
+ dpyinfo->root_window,
+ &dummy, &dummy_child,
+ &root_x, &root_y,
+ &dummy_x, &dummy_y,
+ &dummy_mask))
+ {
+ target = x_dnd_get_target_window (dpyinfo, root_x,
+ root_y, &target_proto,
+ &motif_style, &toplevel,
+ &was_frame);
+
+ if (toplevel != x_dnd_last_seen_toplevel)
+ {
+ if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
+ && x_dnd_return_frame == 1)
+ x_dnd_return_frame = 2;
+
+ if (x_dnd_return_frame == 2
+ && x_any_window_to_frame (dpyinfo, toplevel))
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = timestamp;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_return_frame_object
+ = x_any_window_to_frame (dpyinfo, toplevel);
+ x_dnd_return_frame = 3;
+ x_dnd_waiting_for_finish = false;
+ target = None;
+ }
+
+ x_dnd_last_seen_toplevel = toplevel;
+ }
+
+ if (target != x_dnd_last_seen_window)
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = timestamp;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+
+ x_dnd_action = None;
+ x_dnd_last_seen_window = target;
+ x_dnd_last_protocol_version = target_proto;
+ x_dnd_last_motif_style = motif_style;
+ x_dnd_last_window_is_frame = was_frame;
+
+ if (target != None && x_dnd_last_protocol_version != -1)
+ x_dnd_send_enter (x_dnd_frame, target,
+ x_dnd_last_protocol_version);
+ else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_ENTER);
+ emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ emsg.zero = 0;
+ emsg.timestamp = timestamp;
+ emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+ emsg.index_atom = x_dnd_motif_atom;
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &emsg);
+ }
+ }
+
+ if (x_dnd_last_window_is_frame && target != None)
+ x_dnd_note_self_position (dpyinfo, target, root_x, root_y);
+ else if (x_dnd_last_protocol_version != -1 && target != None)
+ x_dnd_send_position (x_dnd_frame, target,
+ x_dnd_last_protocol_version,
+ root_x, root_y,
+ x_dnd_selection_timestamp,
+ x_dnd_wanted_action, 0,
+#ifdef HAVE_XKB
+ x_dnd_keyboard_state
+#else
+ 0
+#endif
+ );
+ else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ (!x_dnd_xm_use_help
+ ? XM_DROP_ACTION_DROP
+ : XM_DROP_ACTION_DROP_HELP));
+ dmsg.timestamp = timestamp;
+ dmsg.x = root_x;
+ dmsg.y = root_y;
+
+ if (x_dnd_motif_setup_p)
+ xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &dmsg);
+ }
+
+ x_dnd_update_tooltip_position (root_x, root_y);
+ }
+ /* The pointer moved out of the screen. */
+ else if (x_dnd_last_protocol_version != -1)
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ x_dnd_send_leave (x_dnd_frame,
+ x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
+ && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
+ && x_dnd_motif_setup_p)
+ {
+ dsmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dsmsg.timestamp = timestamp;
+ dsmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dsmsg.x = 0;
+ dsmsg.y = 0;
+ dsmsg.index_atom = x_dnd_motif_atom;
+ dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame,
+ x_dnd_last_seen_window, timestamp);
+ xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &dsmsg);
+ }
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_waiting_for_finish = false;
+ x_dnd_frame = NULL;
+ }
+}
+
+int
+x_display_pixel_height (struct x_display_info *dpyinfo)
+{
+ if (dpyinfo->screen_height)
+ return dpyinfo->screen_height;
+
+ return HeightOfScreen (dpyinfo->screen);
+}
+
+int
+x_display_pixel_width (struct x_display_info *dpyinfo)
+{
+ if (dpyinfo->screen_width)
+ return dpyinfo->screen_width;
+
+ return WidthOfScreen (dpyinfo->screen);
+}
+
+/* Handle events from each display until CELL's car becomes non-nil,
+ or TIMEOUT elapses. */
+void
+x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout)
+{
+ struct x_display_info *dpyinfo;
+ fd_set fds;
+ int fd, maxfd;
+#ifndef USE_GTK
+ int finish, rc;
+ XEvent event;
+ fd_set rfds;
+#endif
+ struct input_event hold_quit;
+ struct timespec current, at;
+
+ at = timespec_add (current_timespec (), timeout);
+
+#ifndef USE_GTK
+ FD_ZERO (&rfds);
+ rc = -1;
+#endif
+
+ while (true)
+ {
+ FD_ZERO (&fds);
+ maxfd = -1;
+
+ for (dpyinfo = x_display_list; dpyinfo;
+ dpyinfo = dpyinfo->next)
+ {
+ fd = ConnectionNumber (dpyinfo->display);
+
+#ifndef USE_GTK
+ if ((rc < 0 || FD_ISSET (fd, &rfds))
+ /* If pselect failed, the erroring display's IO error
+ handler will eventually be called. */
+ && XPending (dpyinfo->display))
+ {
+ while (XPending (dpyinfo->display))
+ {
+ EVENT_INIT (hold_quit);
+
+ XNextEvent (dpyinfo->display, &event);
+ handle_one_xevent (dpyinfo, &event,
+ &finish, &hold_quit);
+
+ if (!NILP (XCAR (cell)))
+ return;
+
+ if (finish == X_EVENT_GOTO_OUT)
+ break;
+
+ /* Make us quit now. */
+ if (hold_quit.kind != NO_EVENT)
+ kbd_buffer_store_event (&hold_quit);
+ }
+ }
+#endif
+
+ if (fd > maxfd)
+ maxfd = fd;
+
+ eassert (fd < FD_SETSIZE);
+ FD_SET (fd, &fds);
+ }
+
+ /* Prevent events from being lost (from GTK's point of view) by
+ using GDK to run the event loop. */
+#ifdef USE_GTK
+ while (gtk_events_pending ())
+ {
+ EVENT_INIT (hold_quit);
+ current_count = 0;
+ current_hold_quit = &hold_quit;
+ current_finish = X_EVENT_NORMAL;
+
+ gtk_main_iteration ();
+
+ current_count = -1;
+ current_hold_quit = NULL;
+
+ /* Make us quit now. */
+ if (hold_quit.kind != NO_EVENT)
+ kbd_buffer_store_event (&hold_quit);
+
+ if (!NILP (XCAR (cell)))
+ return;
+
+ if (current_finish == X_EVENT_GOTO_OUT)
+ break;
+ }
+#endif
+
+ eassert (maxfd >= 0);
+
+ current = current_timespec ();
+
+ if (timespec_cmp (at, current) < 0
+ || !NILP (XCAR (cell)))
+ return;
+
+ timeout = timespec_sub (at, current);
+
+#ifndef USE_GTK
+ rc = pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
+
+ if (rc >= 0)
+ rfds = fds;
+#else
+ pselect (maxfd + 1, &fds, NULL, NULL, &timeout, NULL);
+#endif
+ }
+}
+
+#ifdef USE_GTK
+static void
+x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
+{
+ struct x_display_info *dpyinfo;
+ struct input_event ie;
+ Lisp_Object current_monitors, terminal;
+ GdkDisplay *gdpy;
+ Display *dpy;
+
+ gdpy = gdk_screen_get_display (gscr);
+ dpy = gdk_x11_display_get_xdisplay (gdpy);
+ dpyinfo = x_display_info_for_display (dpy);
+
+ if (!dpyinfo)
+ return;
+
+ XSETTERMINAL (terminal, dpyinfo->terminal);
+
+ current_monitors
+ = Fx_display_monitor_attributes_list (terminal);
+
+ if (NILP (Fequal (current_monitors,
+ dpyinfo->last_monitor_attributes_list)))
+ {
+ EVENT_INIT (ie);
+ ie.kind = MONITORS_CHANGED_EVENT;
+ ie.arg = terminal;
+
+ kbd_buffer_store_event (&ie);
+
+ if (x_dnd_in_progress && x_dnd_update_tooltip)
+ x_dnd_monitors = current_monitors;
+
+ x_dnd_update_tooltip_now ();
+ }
+
+ dpyinfo->last_monitor_attributes_list = current_monitors;
+}
+#endif
+
+/* Extract the root window coordinates from the client message EVENT
+ if it is a message that we already understand. Return false if the
+ event was not understood. */
+static bool
+x_coords_from_dnd_message (struct x_display_info *dpyinfo,
+ XEvent *event, int *x_out, int *y_out)
+{
+ xm_drag_motion_message dmsg;
+ xm_drag_motion_reply dreply;
+ xm_drop_start_message smsg;
+ xm_drop_start_reply reply;
+ unsigned long kde_data;
+
+ if (event->type != ClientMessage)
+ return false;
+
+ if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition)
+ {
+ if (event->xclient.format != 32)
+ return false;
+
+ *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16
+ & 0xffff);
+ *y_out = (event->xclient.data.l[2] & 0xffff);
+
+ return true;
+ }
+
+ if ((event->xclient.message_type
+ == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
+ && event->xclient.format == 8)
+ {
+ if (!xm_read_drag_motion_message (event, &dmsg))
+ {
+ *x_out = dmsg.x;
+ *y_out = dmsg.y;
+
+ return true;
+ }
+ else if (!xm_read_drag_motion_reply (event, &dreply))
+ {
+ *x_out = dreply.better_x;
+ *y_out = dreply.better_y;
+
+ return true;
+ }
+ else if (!xm_read_drop_start_message (event, &smsg))
+ {
+ *x_out = smsg.x;
+ *y_out = smsg.y;
+
+ return true;
+ }
+ else if (!xm_read_drop_start_reply (event, &reply))
+ {
+ *x_out = reply.better_x;
+ *y_out = reply.better_y;
+
+ return true;
+ }
+ }
+
+ if (((event->xclient.message_type
+ == dpyinfo->Xatom_DndProtocol)
+ || (event->xclient.message_type
+ == dpyinfo->Xatom_DND_PROTOCOL))
+ && event->xclient.format == 32
+ /* Check that the version of the old KDE protocol is new
+ enough to include coordinates. */
+ && event->xclient.data.l[4])
+ {
+ kde_data = (unsigned long) event->xclient.data.l[3];
+
+ *x_out = (kde_data & 0xffff);
+ *y_out = (kde_data >> 16 & 0xffff);
+
+ return true;
+ }
+
+ return false;
+}
+
/* Handles the XEvent EVENT on display DPYINFO.
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@@ -8396,7 +16295,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int do_help = 0;
ptrdiff_t nbytes = 0;
struct frame *any, *f = NULL;
- struct coding_system coding;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
@@ -8405,7 +16303,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
static XComposeStatus compose_status;
XEvent configureEvent;
XEvent next_event;
-
+ Lisp_Object coding;
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ /* Some XInput 2 events are important for Motif and Lucid menu bars
+ to work correctly, so they must be translated into core events
+ before being passed to XtDispatchEvent. */
+ bool use_copy = false;
+ XEvent copy;
+#elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
+ GdkEvent *copy = NULL;
+ GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+#endif
+ int dx, dy;
USE_SAFE_ALLOCA;
*finish = X_EVENT_NORMAL;
@@ -8414,10 +16323,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
-#ifdef HAVE_XKB
- if (event->type != dpyinfo->xkb_event_type)
+ /* Ignore events coming from various extensions, such as XFIXES and
+ XKB. */
+ if (event->type < LASTEvent)
{
-#endif
#ifdef HAVE_XINPUT2
if (event->type != GenericEvent)
#endif
@@ -8426,11 +16335,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
else
any = NULL;
#endif
-#ifdef HAVE_XKB
}
else
any = NULL;
-#endif
if (any && any->wait_event_type == event->type)
any->wait_event_type = 0; /* Indicates we got it. */
@@ -8439,6 +16346,172 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
case ClientMessage:
{
+ int rc;
+
+ if (((x_dnd_in_progress
+ && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo)
+ || (x_dnd_waiting_for_finish
+ && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo))
+ && event->xclient.message_type == dpyinfo->Xatom_XdndStatus)
+ {
+ Window target;
+ unsigned long r1, r2;
+
+ target = event->xclient.data.l[0];
+
+ if (x_dnd_last_protocol_version != -1
+ && x_dnd_in_progress
+ && target == x_dnd_last_seen_window
+ /* The XDND documentation is not very clearly worded.
+ But this should be the correct behavior, since
+ "kDNDStatusSendHereFlag" in the reference
+ implementation is 2, and means the mouse rect
+ should be ignored. */
+ && !(event->xclient.data.l[1] & 2))
+ {
+ r1 = event->xclient.data.l[2];
+ r2 = event->xclient.data.l[3];
+
+ x_dnd_mouse_rect_target = target;
+ x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16;
+ x_dnd_mouse_rect.y = (r1 & 0xffff);
+ x_dnd_mouse_rect.width = (r2 & 0xffff0000) >> 16;
+ x_dnd_mouse_rect.height = (r2 & 0xffff);
+ }
+ else
+ x_dnd_mouse_rect_target = None;
+
+ if (x_dnd_last_protocol_version != -1
+ && (x_dnd_in_progress
+ && target == x_dnd_last_seen_window))
+ {
+ if (event->xclient.data.l[1] & 1)
+ {
+ if (x_dnd_last_protocol_version >= 2)
+ x_dnd_action = event->xclient.data.l[4];
+ else
+ x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
+ }
+ else
+ x_dnd_action = None;
+ }
+
+ /* Send any pending XdndPosition message. */
+ if (x_dnd_waiting_for_status_window == target)
+ {
+ if (x_dnd_pending_send_position.type != 0)
+ {
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSendEvent (dpyinfo->display, target,
+ False, NoEventMask,
+ &x_dnd_pending_send_position);
+ x_stop_ignoring_errors (dpyinfo);
+ x_dnd_pending_send_position.type = 0;
+
+ /* Since we sent another XdndPosition message, we
+ have to wait for another one in reply, so don't
+ reset `x_dnd_waiting_for_status_window'
+ here. */
+ }
+ else
+ x_dnd_waiting_for_status_window = None;
+
+ /* Send any pending drop if warranted. */
+ if (x_dnd_waiting_for_finish && x_dnd_need_send_drop
+ && x_dnd_waiting_for_status_window == None)
+ {
+ if (event->xclient.data.l[1] & 1)
+ {
+ if (x_dnd_send_drop_proto >= 2)
+ x_dnd_action = event->xclient.data.l[4];
+ else
+ x_dnd_action = dpyinfo->Xatom_XdndActionCopy;
+ }
+ else
+ x_dnd_action = None;
+
+ x_dnd_waiting_for_finish
+ = x_dnd_send_drop (x_dnd_finish_frame,
+ target, x_dnd_selection_timestamp,
+ x_dnd_send_drop_proto);
+ }
+ }
+
+ goto done;
+ }
+
+ if (event->xclient.message_type == dpyinfo->Xatom_XdndFinished
+ && (x_dnd_waiting_for_finish && !x_dnd_waiting_for_motif_finish)
+ /* Also check that the display is correct, since
+ `x_dnd_pending_finish_target' could still be valid on
+ another X server. */
+ && dpyinfo->display == x_dnd_finish_display
+ && event->xclient.data.l[0] == x_dnd_pending_finish_target)
+ {
+ x_dnd_waiting_for_finish = false;
+
+ if (x_dnd_waiting_for_finish_proto >= 5)
+ x_dnd_action = event->xclient.data.l[2];
+
+ if (x_dnd_waiting_for_finish_proto >= 5
+ && !(event->xclient.data.l[1] & 1))
+ x_dnd_action = None;
+
+ goto done;
+ }
+
+ if ((event->xclient.message_type
+ == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
+ && x_dnd_waiting_for_finish
+ && x_dnd_waiting_for_motif_finish == 1
+ && dpyinfo == x_dnd_waiting_for_motif_finish_display)
+ {
+ xm_drop_start_reply reply;
+ uint16_t operation, status, action;
+
+ if (!xm_read_drop_start_reply (event, &reply))
+ {
+ operation = XM_DRAG_SIDE_EFFECT_OPERATION (reply.side_effects);
+ status = XM_DRAG_SIDE_EFFECT_SITE_STATUS (reply.side_effects);
+ action = XM_DRAG_SIDE_EFFECT_DROP_ACTION (reply.side_effects);
+
+ if (operation != XM_DRAG_MOVE
+ && operation != XM_DRAG_COPY
+ && XM_DRAG_OPERATION_IS_LINK (operation))
+ {
+ x_dnd_waiting_for_finish = false;
+ goto done;
+ }
+
+ if (status != XM_DROP_SITE_VALID
+ || (action == XM_DROP_ACTION_DROP_CANCEL
+ || action == XM_DROP_ACTION_DROP_HELP))
+ {
+ x_dnd_waiting_for_finish = false;
+ goto done;
+ }
+
+ switch (operation)
+ {
+ case XM_DRAG_MOVE:
+ x_dnd_action_symbol = QXdndActionMove;
+ break;
+
+ case XM_DRAG_COPY:
+ x_dnd_action_symbol = QXdndActionCopy;
+ break;
+
+ /* This means XM_DRAG_OPERATION_IS_LINK (operation). */
+ default:
+ x_dnd_action_symbol = QXdndActionLink;
+ break;
+ }
+
+ x_dnd_waiting_for_motif_finish = 2;
+ goto done;
+ }
+ }
+
if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
&& event->xclient.format == 32)
{
@@ -8520,15 +16593,99 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
{
- f = any;
+ f = x_top_window_to_frame (dpyinfo,
+ event->xclient.window);
+
if (!f)
goto OTHER; /* May be a dialog that is to be removed */
inev.ie.kind = DELETE_WINDOW_EVENT;
+ inev.ie.timestamp = event->xclient.data.l[1];
XSETFRAME (inev.ie.frame_or_window, f);
goto done;
}
+
+ if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_ping
+ /* Handling window stacking changes during
+ drag-and-drop requires Emacs to select for
+ SubstructureNotifyMask, which in turn causes the
+ message to be sent to Emacs itself using the event
+ mask specified by the EWMH. To avoid an infinite
+ loop, make sure the client message's window is not
+ the root window if DND is in progress. */
+ && (!(x_dnd_in_progress
+ || x_dnd_waiting_for_finish)
+ || event->xclient.window != dpyinfo->root_window)
+ && event->xclient.format == 32)
+ {
+ XEvent send_event = *event;
+
+ send_event.xclient.window = dpyinfo->root_window;
+ XSendEvent (dpyinfo->display, dpyinfo->root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &send_event);
+
+ *finish = X_EVENT_DROP;
+ goto done;
+ }
+
+#if defined HAVE_XSYNC
+ if (event->xclient.data.l[0] == dpyinfo->Xatom_net_wm_sync_request
+ && event->xclient.format == 32
+ && dpyinfo->xsync_supported_p)
+ {
+ struct frame *f
+ = x_top_window_to_frame (dpyinfo,
+ event->xclient.window);
+#if defined HAVE_GTK3
+ GtkWidget *widget;
+ GdkWindow *window;
+ GdkFrameClock *frame_clock;
+#endif
+
+ if (f)
+ {
+#ifndef HAVE_GTK3
+ if (event->xclient.data.l[4] == 0)
+ {
+ XSyncIntsToValue (&FRAME_X_OUTPUT (f)->pending_basic_counter_value,
+ event->xclient.data.l[2], event->xclient.data.l[3]);
+ FRAME_X_OUTPUT (f)->sync_end_pending_p = true;
+ }
+ else if (event->xclient.data.l[4] == 1)
+ {
+ XSyncIntsToValue (&FRAME_X_OUTPUT (f)->current_extended_counter_value,
+ event->xclient.data.l[2], event->xclient.data.l[3]);
+ FRAME_X_OUTPUT (f)->ext_sync_end_pending_p = true;
+ }
+
+ *finish = X_EVENT_DROP;
+#else
+ widget = FRAME_GTK_OUTER_WIDGET (f);
+ window = gtk_widget_get_window (widget);
+ eassert (window);
+
+ /* This could be a (former) child frame for which
+ frame synchronization was disabled. Enable it
+ now. */
+ gdk_x11_window_set_frame_sync_enabled (window, TRUE);
+
+ if (widget && !FRAME_X_OUTPUT (f)->xg_sync_end_pending_p)
+ {
+ frame_clock = gdk_window_get_frame_clock (window);
+ eassert (frame_clock);
+
+ gdk_frame_clock_request_phase (frame_clock,
+ GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT);
+ FRAME_X_OUTPUT (f)->xg_sync_end_pending_p = true;
+ }
+#endif
+ goto done;
+ }
+ }
+#endif
+
goto done;
}
@@ -8556,9 +16713,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
f = any;
if (f)
- _XEditResCheckMessages (f->output_data.x->widget,
- NULL, (XEvent *) event, NULL);
- goto done;
+ {
+ _XEditResCheckMessages (f->output_data.x->widget,
+ NULL, (XEvent *) event, NULL);
+ goto done;
+ }
+
+ goto OTHER;
}
#endif /* X_TOOLKIT_EDITRES */
@@ -8574,7 +16735,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto OTHER;
#ifndef USE_CAIRO
Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
+ /* FIXME: why does this sometimes generate a BadMatch
+ error? */
+ x_catch_errors (dpyinfo->display);
x_kill_gs_process (pixmap, f);
+ x_uncatch_errors ();
expose_frame (f, 0, 0, 0, 0);
#endif /* !USE_CAIRO */
goto done;
@@ -8613,38 +16778,56 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f = any;
if (!f)
goto OTHER;
- if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
+
+ /* These values are always used initialized, but GCC doesn't
+ know that. */
+ dx = 0;
+ dy = 0;
+
+ rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
+ &dx, &dy);
+
+ if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
+ rc, dx, dy))
*finish = X_EVENT_DROP;
}
break;
case SelectionNotify:
- x_display_set_last_user_time (dpyinfo, event->xselection.time);
-#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
+#if defined USE_X_TOOLKIT || defined USE_GTK
+ if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
goto OTHER;
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT and not USE_GTK */
x_handle_selection_notify (&event->xselection);
break;
case SelectionClear: /* Someone has grabbed ownership. */
- x_display_set_last_user_time (dpyinfo, event->xselectionclear.time);
-#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
+#if defined USE_X_TOOLKIT || defined USE_GTK
+ if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
goto OTHER;
-#endif /* USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT and not USE_GTK */
{
const XSelectionClearEvent *eventp = &event->xselectionclear;
+ if (eventp->selection == dpyinfo->motif_drag_atom
+ && (eventp->time == CurrentTime
+ || dpyinfo->motif_drag_atom_time <= eventp->time))
+ dpyinfo->motif_drag_atom = None;
+
inev.sie.kind = SELECTION_CLEAR_EVENT;
SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+
+ if (x_use_pending_selection_requests)
+ {
+ x_push_selection_request (&inev.sie);
+ EVENT_INIT (inev.ie);
+ }
}
break;
case SelectionRequest: /* Someone wants our selection. */
- x_display_set_last_user_time (dpyinfo, event->xselectionrequest.time);
#ifdef USE_X_TOOLKIT
if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
goto OTHER;
@@ -8659,13 +16842,97 @@ handle_one_xevent (struct x_display_info *dpyinfo,
SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+
+ /* If drag-and-drop or another modal dialog/menu is in
+ progress, handle SelectionRequest events immediately, by
+ pushing it onto the selecction queue. */
+
+ if (x_use_pending_selection_requests)
+ {
+ x_push_selection_request (&inev.sie);
+ EVENT_INIT (inev.ie);
+ }
+
+ if (x_dnd_waiting_for_finish
+ && x_dnd_waiting_for_motif_finish == 2
+ && dpyinfo == x_dnd_waiting_for_motif_finish_display
+ && eventp->selection == x_dnd_motif_atom
+ && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS
+ || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE))
+ {
+ x_dnd_waiting_for_finish = false;
+
+ /* If the transfer failed, then return nil from
+ `x-begin-drag'. */
+ if (eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)
+ x_dnd_action = None;
+ }
}
break;
case PropertyNotify:
- x_display_set_last_user_time (dpyinfo, event->xproperty.time);
+ if (x_dnd_in_progress && x_dnd_use_toplevels
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)
+ && event->xproperty.atom == dpyinfo->Xatom_wm_state)
+ {
+ struct x_client_list_window *tem, *last;
+
+ for (last = NULL, tem = x_dnd_toplevels; tem;
+ last = tem, tem = tem->next)
+ {
+ if (tem->window == event->xproperty.window)
+ {
+ Atom actual_type;
+ int actual_format, rc;
+ unsigned long nitems, bytesafter;
+ unsigned char *data = NULL;
+
+ if (event->xproperty.state == PropertyDelete)
+ {
+ if (!last)
+ x_dnd_toplevels = tem->next;
+ else
+ last->next = tem->next;
+
+#ifdef HAVE_XSHAPE
+ if (tem->n_input_rects != -1)
+ xfree (tem->input_rects);
+ if (tem->n_bounding_rects != -1)
+ xfree (tem->bounding_rects);
+#endif
+ xfree (tem);
+ }
+ else
+ {
+ x_catch_errors (dpyinfo->display);
+ rc = XGetWindowProperty (dpyinfo->display,
+ event->xproperty.window,
+ dpyinfo->Xatom_wm_state,
+ 0, 2, False, AnyPropertyType,
+ &actual_type, &actual_format,
+ &nitems, &bytesafter, &data);
+
+ if (!x_had_errors_p (dpyinfo->display) && rc == Success && data
+ && nitems == 2 && actual_format == 32)
+ tem->wm_state = ((unsigned long *) data)[0];
+ else
+ tem->wm_state = WithdrawnState;
+
+ if (data)
+ XFree (data);
+ x_uncatch_errors_after_check ();
+ }
+
+ x_dnd_update_state (dpyinfo, event->xproperty.time);
+ break;
+ }
+ }
+ }
+
f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
- if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
+ if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state
+ /* This should never happen with embedded windows. */
+ && !FRAME_X_EMBEDDED_P (f))
{
bool not_hidden = x_handle_net_wm_state (f, &event->xproperty);
@@ -8708,6 +16975,127 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
}
+ if (f && FRAME_X_OUTPUT (f)->alpha_identical_p
+ && (event->xproperty.atom
+ == dpyinfo->Xatom_net_wm_window_opacity))
+ {
+#ifndef USE_XCB
+ int rc, actual_format;
+ Atom actual;
+ unsigned char *tmp_data;
+ unsigned long n, left, opacity;
+
+ tmp_data = NULL;
+#else
+ xcb_get_property_cookie_t opacity_cookie;
+ xcb_get_property_reply_t *opacity_reply;
+ xcb_generic_error_t *error;
+ bool rc;
+ uint32_t value;
+#endif
+
+ if (event->xproperty.state == PropertyDelete)
+ {
+ f->alpha[0] = 1.0;
+ f->alpha[1] = 1.0;
+
+ store_frame_param (f, Qalpha, Qnil);
+ }
+ else
+ {
+#ifndef USE_XCB
+ rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_window_opacity,
+ 0, 1, False, AnyPropertyType, &actual,
+ &actual_format, &n, &left, &tmp_data);
+
+ if (rc == Success && actual_format == 32
+ && (actual == XA_CARDINAL
+ /* Some broken programs set the opacity property
+ to those types, but window managers accept
+ them anyway. */
+ || actual == XA_ATOM
+ || actual == XA_WINDOW) && n)
+ {
+ opacity = *(unsigned long *) tmp_data & OPAQUE;
+ f->alpha[0] = (double) opacity / (double) OPAQUE;
+ f->alpha[1] = (double) opacity / (double) OPAQUE;
+
+ store_frame_param (f, Qalpha, make_float (f->alpha[0]));
+ }
+ else
+ {
+ f->alpha[0] = 1.0;
+ f->alpha[1] = 1.0;
+
+ store_frame_param (f, Qalpha, Qnil);
+ }
+#else
+ opacity_cookie
+ = xcb_get_property (dpyinfo->xcb_connection, 0,
+ (xcb_window_t) FRAME_OUTER_WINDOW (f),
+ (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
+ XCB_ATOM_CARDINAL, 0, 1);
+ opacity_reply
+ = xcb_get_property_reply (dpyinfo->xcb_connection,
+ opacity_cookie, &error);
+
+ if (!opacity_reply)
+ free (error), rc = false;
+ else
+ rc = (opacity_reply->format == 32
+ && (opacity_reply->type == XCB_ATOM_CARDINAL
+ || opacity_reply->type == XCB_ATOM_ATOM
+ || opacity_reply->type == XCB_ATOM_WINDOW)
+ && (xcb_get_property_value_length (opacity_reply) >= 4));
+
+ if (rc)
+ {
+ value = *(uint32_t *) xcb_get_property_value (opacity_reply);
+
+ f->alpha[0] = (double) value / (double) OPAQUE;
+ f->alpha[1] = (double) value / (double) OPAQUE;
+ store_frame_param (f, Qalpha, make_float (f->alpha[0]));
+ }
+ else
+ {
+ f->alpha[0] = 1.0;
+ f->alpha[1] = 1.0;
+
+ store_frame_param (f, Qalpha, Qnil);
+ }
+
+ if (opacity_reply)
+ free (opacity_reply);
+#endif
+ }
+
+#ifndef USE_XCB
+ if (tmp_data)
+ XFree (tmp_data);
+#endif
+ }
+
+ if (event->xproperty.window == dpyinfo->root_window
+ && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking
+ || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop)
+ && x_dnd_in_progress
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ if (x_dnd_use_toplevels)
+ {
+ x_dnd_free_toplevels (true);
+
+ if (x_dnd_compute_toplevels (dpyinfo))
+ {
+ x_dnd_free_toplevels (true);
+ x_dnd_use_toplevels = false;
+ }
+ }
+
+ x_dnd_update_state (dpyinfo, event->xproperty.time);
+ }
+
x_handle_property_notify (&event->xproperty);
xft_settings_event (dpyinfo, event);
goto OTHER;
@@ -8718,8 +17106,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
/* Maybe we shouldn't set this for child frames ?? */
f->output_data.x->parent_desc = event->xreparent.parent;
+
if (!FRAME_PARENT_FRAME (f))
- x_real_positions (f, &f->left_pos, &f->top_pos);
+ {
+ x_real_positions (f, &f->left_pos, &f->top_pos);
+
+ /* Perhaps reparented due to a WM restart. Reset this. */
+ FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
+ FRAME_DISPLAY_INFO (f)->net_supported_window = 0;
+
+#ifndef USE_GTK
+ /* The window manager could have restarted and the new
+ window manager might not support user time windows,
+ so update what is used accordingly.
+
+ Note that this doesn't handle changes between
+ non-reparenting window managers. */
+ if (FRAME_X_OUTPUT (f)->has_been_visible)
+ x_update_frame_user_time_window (f);
+#endif
+ }
else
{
Window root;
@@ -8732,10 +17138,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
unblock_input ();
}
- /* Perhaps reparented due to a WM restart. Reset this. */
- FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
- FRAME_DISPLAY_INFO (f)->net_supported_window = 0;
-
x_set_frame_alpha (f);
}
goto OTHER;
@@ -8759,15 +17161,22 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!FRAME_VISIBLE_P (f))
{
block_input ();
- /* The following two are commented out to avoid that a
- plain invisible frame gets reported as iconified. That
- problem occurred first for Emacs 26 and is described in
- https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. */
-/** SET_FRAME_VISIBLE (f, 1); **/
-/** SET_FRAME_ICONIFIED (f, false); **/
+ /* By default, do not set the frame's visibility here, see
+ https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
+ The default behavior can be overridden by setting
+ 'x-set-frame-visibility-more-laxly' (Bug#49955,
+ Bug#53298). */
+ if (EQ (x_set_frame_visibility_more_laxly, Qexpose)
+ || EQ (x_set_frame_visibility_more_laxly, Qt))
+ {
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, false);
+ }
+#ifdef HAVE_XDBE
if (FRAME_X_DOUBLE_BUFFERED_P (f))
- font_drop_xrender_surfaces (f);
+ x_drop_xrender_surfaces (f);
+#endif
f->output_data.x->has_been_visible = true;
SET_FRAME_GARBAGED (f);
unblock_input ();
@@ -8792,6 +17201,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!FRAME_GARBAGED_P (f))
{
+#ifdef USE_X_TOOLKIT
+ if (f->output_data.x->edit_widget)
+ /* The widget's expose proc will be run in this
+ case. */
+ goto OTHER;
+#endif
#ifdef USE_GTK
/* This seems to be needed for GTK 2.6 and later, see
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
@@ -8806,8 +17221,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
}
+#ifdef HAVE_XDBE
if (!FRAME_GARBAGED_P (f))
show_back_buffer (f);
+#endif
}
else
{
@@ -8855,8 +17272,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef USE_GTK
x_clear_under_internal_border (f);
#endif
+#ifdef HAVE_XDBE
show_back_buffer (f);
+#endif
}
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ struct scroll_bar *bar
+ = x_window_to_scroll_bar (dpyinfo->display,
+ /* Hopefully this is just a window,
+ not the back buffer. */
+ event->xgraphicsexpose.drawable, 2);
+
+ if (bar)
+ x_scroll_bar_expose (bar, event);
+#endif
#ifdef USE_X_TOOLKIT
else
goto OTHER;
@@ -8866,9 +17295,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case NoExpose: /* This occurs when an XCopyArea's
source area was completely
available. */
+#ifdef USE_X_TOOLKIT
+ *finish = X_EVENT_DROP;
+#endif
break;
case UnmapNotify:
+ if (x_dnd_in_progress && x_dnd_use_toplevels
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
+ tem = tem->next)
+ {
+ if (tem->window == event->xunmap.window)
+ {
+ tem->mapped_p = false;
+ break;
+ }
+ }
+ }
+
/* Redo the mouse-highlight after the tooltip has gone. */
if (event->xunmap.window == tip_window)
{
@@ -8882,6 +17328,34 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
bool visible = FRAME_VISIBLE_P (f);
+#ifdef USE_LUCID
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over
+ menu items is unmapped. Redisplay the menu manually... */
+ if (FRAME_TOOLTIP_P (f) && popup_activated ())
+ {
+ Widget w;
+ Lisp_Object tail, frame;
+ struct frame *f1;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (!FRAME_X_P (XFRAME (frame)))
+ continue;
+
+ f1 = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f1))
+ {
+ w = FRAME_X_OUTPUT (f1)->menubar_widget;
+
+ if (w && !DoesSaveUnders (FRAME_DISPLAY_INFO (f1)->screen))
+ xlwmenu_redisplay (w);
+ }
+ }
+ }
+#endif /* USE_LUCID */
+
/* While a frame is unmapped, display generation is
disabled; you don't want to spend time updating a
display that won't ever be seen. */
@@ -8913,6 +17387,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (xg_is_menu_window (dpyinfo->display, event->xmap.window))
popup_activated_flag = 1;
#endif
+
+ if (x_dnd_in_progress
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
+
+ if (x_dnd_in_progress && x_dnd_use_toplevels
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
+ tem = tem->next)
+ {
+ if (tem->window == event->xmap.window)
+ {
+ tem->mapped_p = true;
+ break;
+ }
+ }
+ }
+
/* We use x_top_window_to_frame because map events can
come for sub-windows and they don't mean that the
frame is visible. */
@@ -8921,8 +17414,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
bool iconified = FRAME_ICONIFIED_P (f);
int value;
- bool sticky;
- bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky);
+ bool sticky, shaded;
+ bool not_hidden = x_get_current_wm_state (f, event->xmap.window, &value, &sticky,
+ &shaded);
if (CONSP (frame_size_history))
frame_size_history_extra
@@ -8961,7 +17455,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_set_z_group (f, Qbelow, Qnil);
}
- if (not_hidden)
+ /* Embedded frames might have NET_WM_STATE left over, but
+ are always visible once mapped. */
+ if (not_hidden || FRAME_X_EMBEDDED_P (f))
{
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_ICONIFIED (f, false);
@@ -8978,7 +17474,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f->output_data.x->has_been_visible = true;
}
- if (not_hidden && iconified)
+ x_update_opaque_region (f, NULL);
+
+ if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified)
{
inev.ie.kind = DEICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
@@ -8987,9 +17485,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto OTHER;
case KeyPress:
-
- x_display_set_last_user_time (dpyinfo, event->xkey.time);
+ x_display_set_last_user_time (dpyinfo, event->xkey.time,
+ event->xkey.send_event);
ignore_next_mouse_click_timeout = 0;
+ coding = Qlatin_1;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Dispatch KeyPress events when in menu. */
@@ -9046,10 +17545,29 @@ handle_one_xevent (struct x_display_info *dpyinfo,
unsigned char *copy_bufptr = copy_buffer;
int copy_bufsiz = sizeof (copy_buffer);
int modifiers;
- Lisp_Object coding_system = Qlatin_1;
Lisp_Object c;
- /* Event will be modified. */
+ /* `xkey' will be modified, but it's not important to modify
+ `event' itself. */
XKeyEvent xkey = event->xkey;
+ int i;
+#ifdef HAVE_XINPUT2
+ Time pending_keystroke_time;
+ struct xi_device_t *source;
+
+ pending_keystroke_time = dpyinfo->pending_keystroke_time;
+
+ if (event->xkey.time >= pending_keystroke_time)
+ {
+#if defined USE_GTK && !defined HAVE_GTK3
+ if (!dpyinfo->pending_keystroke_time_special_p)
+#endif
+ dpyinfo->pending_keystroke_time = 0;
+#if defined USE_GTK && !defined HAVE_GTK3
+ else
+ dpyinfo->pending_keystroke_time_special_p = false;
+#endif
+ }
+#endif
#ifdef USE_GTK
/* Don't pass keys to GTK. A Tab will shift focus to the
@@ -9081,20 +17599,41 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (modifiers & dpyinfo->meta_mod_mask)
memset (&compose_status, 0, sizeof (compose_status));
+#ifdef HAVE_XKB
+ if (dpyinfo->xkb_desc)
+ {
+ XkbDescRec *rec = dpyinfo->xkb_desc;
+
+ if (rec->map->modmap && rec->map->modmap[xkey.keycode])
+ goto done_keysym;
+ }
+ else
+#endif
+ {
+ if (dpyinfo->modmap)
+ {
+ for (i = 0; i < 8 * dpyinfo->modmap->max_keypermod; i++)
+ {
+ if (xkey.keycode == dpyinfo->modmap->modifiermap[i])
+ goto done_keysym;
+ }
+ }
+ }
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
{
Status status_return;
- coding_system = Vlocale_coding_system;
nbytes = XmbLookupString (FRAME_XIC (f),
&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&status_return);
+ coding = Qnil;
if (status_return == XBufferOverflow)
{
copy_bufsiz = nbytes + 1;
- copy_bufptr = alloca (copy_bufsiz);
+ copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
nbytes = XmbLookupString (FRAME_XIC (f),
&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
@@ -9113,13 +17652,56 @@ handle_one_xevent (struct x_display_info *dpyinfo,
emacs_abort ();
}
else
- nbytes = XLookupString (&xkey, (char *) copy_bufptr,
- copy_bufsiz, &keysym,
- &compose_status);
-#else
- nbytes = XLookupString (&xkey, (char *) copy_bufptr,
- copy_bufsiz, &keysym,
- &compose_status);
+#endif
+ {
+#ifdef HAVE_XKB
+ int overflow;
+ unsigned int consumed;
+
+ if (dpyinfo->xkb_desc)
+ {
+ if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
+ xkey.keycode, xkey.state,
+ &consumed, &keysym))
+ goto done_keysym;
+
+ overflow = 0;
+
+ nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
+ xkey.state & ~consumed,
+ (char *) copy_bufptr,
+ copy_bufsiz, &overflow);
+
+ if (overflow)
+ {
+ copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
+ * sizeof *copy_bufptr);
+ overflow = 0;
+ nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
+ xkey.state & ~consumed,
+ (char *) copy_bufptr,
+ copy_bufsiz, &overflow);
+
+ if (overflow)
+ nbytes = 0;
+ }
+
+ if (nbytes)
+ coding = Qnil;
+ }
+ else
+#endif
+ nbytes = XLookupString (&xkey, (char *) copy_bufptr,
+ copy_bufsiz, &keysym,
+ &compose_status);
+ }
+
+#ifdef XK_F1
+ if (x_dnd_in_progress && keysym == XK_F1)
+ {
+ x_dnd_xm_use_help = true;
+ goto done_keysym;
+ }
#endif
/* If not using XIM/XIC, and a compose sequence is in progress,
@@ -9130,19 +17712,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
memset (&compose_status, 0, sizeof (compose_status));
orig_keysym = keysym;
- /* Common for all keysym input events. */
- XSETFRAME (inev.ie.frame_or_window, f);
- inev.ie.modifiers
- = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
- inev.ie.timestamp = xkey.time;
-
- /* First deal with keysyms which have defined
- translations to characters. */
- if (keysym >= 32 && keysym < 128)
- /* Avoid explicitly decoding each ASCII character. */
- {
- inev.ie.kind = ASCII_KEYSTROKE_EVENT;
- inev.ie.code = keysym;
+ /* Common for all keysym input events. */
+ XSETFRAME (inev.ie.frame_or_window, f);
+ inev.ie.modifiers
+ = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
+ inev.ie.timestamp = xkey.time;
+
+ /* First deal with keysyms which have defined
+ translations to characters. */
+ if (keysym >= 32 && keysym < 128)
+ /* Avoid explicitly decoding each ASCII character. */
+ {
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
+
+#ifdef HAVE_XINPUT2
+ if (event->xkey.time == pending_keystroke_time)
+ {
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
+
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+
goto done_keysym;
}
@@ -9154,6 +17748,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
else
inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
inev.ie.code = keysym & 0xFFFFFF;
+
+#ifdef HAVE_XINPUT2
+ if (event->xkey.time == pending_keystroke_time)
+ {
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
+
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+
goto done_keysym;
}
@@ -9163,158 +17769,190 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Vx_keysym_table,
Qnil),
FIXNATP (c)))
- {
+ {
inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = XFIXNAT (c);
- goto done_keysym;
- }
- /* Random non-modifier sorts of keysyms. */
- if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
- || keysym == XK_Delete
+#ifdef HAVE_XINPUT2
+ if (event->xkey.time == pending_keystroke_time)
+ {
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
+
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+
+ goto done_keysym;
+ }
+
+ /* Random non-modifier sorts of keysyms. */
+ if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+ || keysym == XK_Delete
#ifdef XK_ISO_Left_Tab
- || (keysym >= XK_ISO_Left_Tab
- && keysym <= XK_ISO_Enter)
+ || (keysym >= XK_ISO_Left_Tab
+ && keysym <= XK_ISO_Enter)
#endif
- || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
- || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
+ || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
+ || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
#ifdef HPUX
- /* This recognizes the "extended function
- keys". It seems there's no cleaner way.
- Test IsModifierKey to avoid handling
- mode_switch incorrectly. */
- || (XK_Select <= keysym && keysym < XK_KP_Space)
+ /* This recognizes the "extended function
+ keys". It seems there's no cleaner way.
+ Test IsModifierKey to avoid handling
+ mode_switch incorrectly. */
+ || (XK_Select <= keysym && keysym < XK_KP_Space)
#endif
#ifdef XK_dead_circumflex
- || orig_keysym == XK_dead_circumflex
+ || orig_keysym == XK_dead_circumflex
#endif
#ifdef XK_dead_grave
- || orig_keysym == XK_dead_grave
+ || orig_keysym == XK_dead_grave
#endif
#ifdef XK_dead_tilde
- || orig_keysym == XK_dead_tilde
+ || orig_keysym == XK_dead_tilde
#endif
#ifdef XK_dead_diaeresis
- || orig_keysym == XK_dead_diaeresis
+ || orig_keysym == XK_dead_diaeresis
#endif
#ifdef XK_dead_macron
- || orig_keysym == XK_dead_macron
+ || orig_keysym == XK_dead_macron
#endif
#ifdef XK_dead_degree
- || orig_keysym == XK_dead_degree
+ || orig_keysym == XK_dead_degree
#endif
#ifdef XK_dead_acute
- || orig_keysym == XK_dead_acute
+ || orig_keysym == XK_dead_acute
#endif
#ifdef XK_dead_cedilla
- || orig_keysym == XK_dead_cedilla
+ || orig_keysym == XK_dead_cedilla
#endif
#ifdef XK_dead_breve
- || orig_keysym == XK_dead_breve
+ || orig_keysym == XK_dead_breve
#endif
#ifdef XK_dead_ogonek
- || orig_keysym == XK_dead_ogonek
+ || orig_keysym == XK_dead_ogonek
#endif
#ifdef XK_dead_caron
- || orig_keysym == XK_dead_caron
+ || orig_keysym == XK_dead_caron
#endif
#ifdef XK_dead_doubleacute
- || orig_keysym == XK_dead_doubleacute
+ || orig_keysym == XK_dead_doubleacute
#endif
#ifdef XK_dead_abovedot
- || orig_keysym == XK_dead_abovedot
-#endif
- || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
- || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
- /* Any "vendor-specific" key is ok. */
- || (orig_keysym & (1 << 28))
- || (keysym != NoSymbol && nbytes == 0))
- && ! (IsModifierKey (orig_keysym)
- /* The symbols from XK_ISO_Lock
- to XK_ISO_Last_Group_Lock
- don't have real modifiers but
- should be treated similarly to
- Mode_switch by Emacs. */
+ || orig_keysym == XK_dead_abovedot
+#endif
+#ifdef XK_dead_abovering
+ || orig_keysym == XK_dead_abovering
+#endif
+#ifdef XK_dead_belowdot
+ || orig_keysym == XK_dead_belowdot
+#endif
+#ifdef XK_dead_voiced_sound
+ || orig_keysym == XK_dead_voiced_sound
+#endif
+#ifdef XK_dead_semivoiced_sound
+ || orig_keysym == XK_dead_semivoiced_sound
+#endif
+#ifdef XK_dead_hook
+ || orig_keysym == XK_dead_hook
+#endif
+#ifdef XK_dead_horn
+ || orig_keysym == XK_dead_horn
+#endif
+#ifdef XK_dead_stroke
+ || orig_keysym == XK_dead_stroke
+#endif
+#ifdef XK_dead_abovecomma
+ || orig_keysym == XK_dead_abovecomma
+#endif
+ || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
+ || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
+ /* Any "vendor-specific" key is ok. */
+ || (orig_keysym & (1 << 28))
+ || (keysym != NoSymbol && nbytes == 0))
+ && ! (IsModifierKey (orig_keysym)
+ /* The symbols from XK_ISO_Lock
+ to XK_ISO_Last_Group_Lock
+ don't have real modifiers but
+ should be treated similarly to
+ Mode_switch by Emacs. */
#if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
- || (XK_ISO_Lock <= orig_keysym
- && orig_keysym <= XK_ISO_Last_Group_Lock)
+ || (XK_ISO_Lock <= orig_keysym
+ && orig_keysym <= XK_ISO_Last_Group_Lock)
#endif
- ))
+ ))
{
STORE_KEYSYM_FOR_DEBUG (keysym);
/* make_lispy_event will convert this to a symbolic
key. */
inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
inev.ie.code = keysym;
+
+#ifdef HAVE_XINPUT2
+ if (event->xkey.time == pending_keystroke_time)
+ {
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
+
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+
goto done_keysym;
}
{ /* Raw bytes, not keysym. */
ptrdiff_t i;
- int nchars, len;
- for (i = 0, nchars = 0; i < nbytes; i++)
+ for (i = 0; i < nbytes; i++)
{
- if (ASCII_CHAR_P (copy_bufptr[i]))
- nchars++;
STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
}
- if (nchars < nbytes)
+ if (nbytes)
{
- /* Decode the input data. */
-
- /* The input should be decoded with `coding_system'
- which depends on which X*LookupString function
- we used just above and the locale. */
- setup_coding_system (coding_system, &coding);
- coding.src_multibyte = false;
- coding.dst_multibyte = true;
- /* The input is converted to events, thus we can't
- handle composition. Anyway, there's no XIM that
- gives us composition information. */
- coding.common_flags &= ~CODING_ANNOTATION_MASK;
-
- SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
- nbytes);
- coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = coding.destination;
- }
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
- /* Convert the input data to a sequence of
- character events. */
- for (i = 0; i < nbytes; i += len)
- {
- int ch;
- if (nchars == nbytes)
- ch = copy_bufptr[i], len = 1;
- else
- ch = string_char_and_length (copy_bufptr + i, &len);
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = ch;
- kbd_buffer_store_buffered_event (&inev, hold_quit);
- }
+ Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
+ Qcoding, coding, inev.ie.arg);
- count += nchars;
+#ifdef HAVE_XINPUT2
+ if (event->xkey.time == pending_keystroke_time
+ /* I-Bus sometimes sends events generated from
+ multiple filtered keystrokes with a time of 0,
+ so just use the recorded source device if it
+ exists. */
+ || (pending_keystroke_time && !event->xkey.time))
+ {
+ source = xi_device_from_id (dpyinfo,
+ dpyinfo->pending_keystroke_source);
- inev.ie.kind = NO_EVENT; /* Already stored above. */
+ if (source)
+ inev.ie.device = source->name;
+ }
+#endif
+ }
if (keysym == NoSymbol)
break;
}
- /* FIXME: check side effects and remove this. */
- ((XEvent *) event)->xkey = xkey;
}
done_keysym:
#ifdef HAVE_X_I18N
+ if (f)
+ {
+ struct window *w = XWINDOW (f->selected_window);
+ xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
+
+ if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+ xic_set_statusarea (f);
+ }
+
/* Don't dispatch this event since XtDispatchEvent calls
XFilterEvent, and two calls in a row may freeze the
client. */
@@ -9324,7 +17962,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
case KeyRelease:
- x_display_set_last_user_time (dpyinfo, event->xkey.time);
#ifdef HAVE_X_I18N
/* Don't dispatch this event since XtDispatchEvent calls
XFilterEvent, and two calls in a row may freeze the
@@ -9335,8 +17972,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
case EnterNotify:
- x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+ x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
+ event->xcrossing.send_event);
+
+ if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
#ifdef HAVE_XWIDGETS
{
@@ -9366,46 +18006,61 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f = any;
if (f && x_mouse_click_focus_ignore_position)
- ignore_next_mouse_click_timeout = event->xmotion.time + 200;
+ {
+ ignore_next_mouse_click_timeout = (event->xmotion.time
+ + x_mouse_click_focus_ignore_time);
+ mouse_click_timeout_display = dpyinfo;
+ }
/* EnterNotify counts as mouse movement,
so update things that depend on mouse position. */
if (f && !f->output_data.x->hourglass_p)
- x_note_mouse_movement (f, &event->xmotion);
+ x_note_mouse_movement (f, &event->xmotion, Qnil);
#ifdef USE_GTK
/* We may get an EnterNotify on the buttons in the toolbar. In that
case we moved out of any highlighted area and need to note this. */
if (!f && dpyinfo->last_mouse_glyph_frame)
- x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
+ x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion,
+ Qnil);
#endif
goto OTHER;
case FocusIn:
-#ifndef USE_GTK
+#ifdef USE_GTK
/* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
minimized/iconified windows; thus, for those WMs we won't get
- a MapNotify when unminimizing/deconifying. Check here if we
+ a MapNotify when unminimizing/deiconifying. Check here if we
are deiconizing a window (Bug42655).
- But don't do that on GTK since it may cause a plain invisible
- frame get reported as iconified, compare
+ But don't do that by default on GTK since it may cause a plain
+ invisible frame get reported as iconified, compare
https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
- That is fixed above but bites us here again. */
- f = any;
- if (f && FRAME_ICONIFIED_P (f))
- {
- SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, false);
- f->output_data.x->has_been_visible = true;
- inev.ie.kind = DEICONIFY_EVENT;
- XSETFRAME (inev.ie.frame_or_window, f);
- }
+ That is fixed above but bites us here again.
+
+ The option x_set_frame_visibility_more_laxly allows to override
+ the default behavior (Bug#49955, Bug#53298). */
+ if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
+ || EQ (x_set_frame_visibility_more_laxly, Qt))
#endif /* USE_GTK */
+ {
+ f = any;
+ if (f && FRAME_ICONIFIED_P (f))
+ {
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
+ inev.ie.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ }
+ }
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
goto OTHER;
case LeaveNotify:
+ x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
+ event->xcrossing.send_event);
+
#ifdef HAVE_XWIDGETS
{
struct xwidget_view *xvw = xwidget_view_from_window (event->xcrossing.window);
@@ -9417,14 +18072,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
}
#endif
- x_display_set_last_user_time (dpyinfo, event->xcrossing.time);
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+ if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+#if defined USE_X_TOOLKIT
+ /* If the mouse leaves the edit widget, then any mouse highlight
+ should be cleared. */
+ f = x_window_to_frame (dpyinfo, event->xcrossing.window);
+
+ if (!f)
+ f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
+#else
f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
-#if defined HAVE_X_TOOLKIT && defined HAVE_XINPUT2
+#endif
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2 && !defined USE_MOTIF
/* The XI2 event mask is set on the frame widget, so this event
likely originates from the shell widget, which we aren't
- interested in. */
+ interested in. (But don't ignore this on Motif, since we
+ want to clear the mouse face when a popup is active.) */
if (dpyinfo->supports_xi2)
f = NULL;
#endif
@@ -9442,13 +18108,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Do it only if there's something to cancel.
Otherwise, the startup message is cleared when
the mouse leaves the frame. */
- if (any_help_event_p)
+ if (any_help_event_p
+ /* But never if `mouse-drag-and-drop-region' is in
+ progress, since that results in the tooltip being
+ dismissed when the mouse moves on top. */
+ && !((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && gui_mouse_grabbed (dpyinfo)))
do_help = -1;
}
#ifdef USE_GTK
/* See comment in EnterNotify above */
else if (dpyinfo->last_mouse_glyph_frame)
- x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
+ x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame,
+ &event->xmotion, Qnil);
#endif
goto OTHER;
@@ -9458,7 +18131,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case MotionNotify:
{
- x_display_set_last_user_time (dpyinfo, event->xmotion.time);
+ XMotionEvent xmotion = event->xmotion;
+
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
@@ -9470,8 +18144,235 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
+ if (x_dnd_in_progress
+ /* Handle these events normally if the recursion
+ level is higher than when the drag-and-drop
+ operation was initiated. This is so that mouse
+ input works while we're in the debugger for, say,
+ `x-dnd-movement-function`. */
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth)
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ Window target, toplevel;
+ int target_proto, motif_style;
+ xm_top_level_leave_message lmsg;
+ xm_top_level_enter_message emsg;
+ xm_drag_motion_message dmsg;
+ XRectangle *r;
+ bool was_frame;
+
+ /* Always clear mouse face. */
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_hidden = true;
+
+ /* Sometimes the drag-and-drop operation starts with the
+ pointer of a frame invisible due to input. Since
+ motion events are ignored during that, make the pointer
+ visible manually. */
+
+ if (f)
+ {
+ XTtoggle_invisible_pointer (f, false);
+
+ r = &dpyinfo->last_mouse_glyph;
+
+ /* Also remember the mouse glyph and set
+ mouse_moved. */
+ if (f != dpyinfo->last_mouse_glyph_frame
+ || event->xmotion.x < r->x
+ || event->xmotion.x >= r->x + r->width
+ || event->xmotion.y < r->y
+ || event->xmotion.y >= r->y + r->height)
+ {
+ f->mouse_moved = true;
+ f->last_mouse_device = Qnil;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+
+ remember_mouse_glyph (f, event->xmotion.x,
+ event->xmotion.y, r);
+ dpyinfo->last_mouse_glyph_frame = f;
+ }
+ }
+
+ if (event->xmotion.same_screen)
+ target = x_dnd_get_target_window (dpyinfo,
+ event->xmotion.x_root,
+ event->xmotion.y_root,
+ &target_proto,
+ &motif_style, &toplevel,
+ &was_frame);
+ else
+ target = x_dnd_fill_empty_target (&target_proto, &motif_style,
+ &toplevel, &was_frame);
+
+ if (toplevel != x_dnd_last_seen_toplevel)
+ {
+ if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
+ && x_dnd_return_frame == 1)
+ x_dnd_return_frame = 2;
+
+ if (x_dnd_return_frame == 2
+ && x_any_window_to_frame (dpyinfo, toplevel))
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = event->xmotion.time;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_return_frame_object
+ = x_any_window_to_frame (dpyinfo, toplevel);
+ x_dnd_return_frame = 3;
+ x_dnd_waiting_for_finish = false;
+ target = None;
+ }
+
+ x_dnd_last_seen_toplevel = toplevel;
+ }
+
+ if (target != x_dnd_last_seen_window)
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ /* This is apparently required. If we don't send
+ a motion event with the current root window
+ coordinates of the pointer before the top level
+ leave, then Motif displays an ugly black border
+ around the previous drop site. */
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_NONE, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.timestamp = event->xmotion.time;
+ dmsg.x = event->xmotion.x_root;
+ dmsg.y = event->xmotion.y_root;
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = event->xbutton.time;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ {
+ xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &dmsg);
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+ }
+
+ x_dnd_action = None;
+ x_dnd_last_seen_window = target;
+ x_dnd_last_protocol_version = target_proto;
+ x_dnd_last_motif_style = motif_style;
+ x_dnd_last_window_is_frame = was_frame;
+
+ if (target != None && x_dnd_last_protocol_version != -1)
+ x_dnd_send_enter (x_dnd_frame, target,
+ x_dnd_last_protocol_version);
+ else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_ENTER);
+ emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ emsg.zero = 0;
+ emsg.timestamp = event->xbutton.time;
+ emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+ emsg.index_atom = x_dnd_motif_atom;
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &emsg);
+ }
+ }
+
+ if (x_dnd_last_window_is_frame && target != None)
+ x_dnd_note_self_position (dpyinfo, target,
+ event->xbutton.x_root,
+ event->xbutton.y_root);
+ else if (x_dnd_last_protocol_version != -1 && target != None)
+ x_dnd_send_position (x_dnd_frame, target,
+ x_dnd_last_protocol_version,
+ event->xmotion.x_root,
+ event->xmotion.y_root,
+ x_dnd_selection_timestamp,
+ x_dnd_wanted_action, 0,
+ event->xmotion.state);
+ else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ (!x_dnd_xm_use_help
+ ? XM_DROP_ACTION_DROP
+ : XM_DROP_ACTION_DROP_HELP));
+ dmsg.timestamp = event->xbutton.time;
+ dmsg.x = event->xmotion.x_root;
+ dmsg.y = event->xmotion.y_root;
+
+ if (x_dnd_motif_setup_p)
+ xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &dmsg);
+ }
+
+ x_dnd_update_tooltip_position (event->xmotion.x_root,
+ event->xmotion.y_root);
+
+ goto OTHER;
+ }
+
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, event))
+ if (f && xg_event_is_for_scrollbar (f, event, false))
f = 0;
#endif
#ifdef HAVE_XWIDGETS
@@ -9499,8 +18400,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !NILP (focus_follows_mouse)))
{
static Lisp_Object last_mouse_window;
+
+ if (xmotion.window != FRAME_X_WINDOW (f))
+ {
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+ xmotion.window, FRAME_X_WINDOW (f),
+ xmotion.x, xmotion.y, &xmotion.x,
+ &xmotion.y, &xmotion.subwindow);
+ xmotion.window = FRAME_X_WINDOW (f);
+ }
+
Lisp_Object window = window_from_coordinates
- (f, event->xmotion.x, event->xmotion.y, 0, false, false);
+ (f, xmotion.x, xmotion.y, 0, false, false);
/* A window will be autoselected only when it is not
selected now and the last mouse movement event was
@@ -9522,7 +18433,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
last_mouse_window = window;
}
- if (!x_note_mouse_movement (f, &event->xmotion))
+ if (!x_note_mouse_movement (f, &xmotion, Qnil))
help_echo_string = previous_help_echo_string;
}
else
@@ -9559,6 +18470,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
So if this ConfigureNotify is immediately followed by another
for the same window, use the info from the latest update, and
consider the events all handled. */
+
/* Opaque resize may be trickier; ConfigureNotify events are
mixed with Expose events for multiple windows. */
configureEvent = *event;
@@ -9580,15 +18492,142 @@ handle_one_xevent (struct x_display_info *dpyinfo,
configureEvent = next_event;
}
+ /* If we get a ConfigureNotify for the root window, this means
+ the dimensions of the screen it's on changed. */
+
+ if (configureEvent.xconfigure.window == dpyinfo->root_window)
+ {
+#ifdef HAVE_XRANDR
+ /* This function is OK to call even if the X server doesn't
+ support RandR. */
+ XRRUpdateConfiguration (&configureEvent);
+#elif !defined USE_GTK
+ /* Catch screen size changes even if RandR is not available
+ on the client. GTK does this internally. */
+
+ if (configureEvent.xconfigure.width != dpyinfo->screen_width
+ || configureEvent.xconfigure.height != dpyinfo->screen_height)
+ {
+ inev.ie.kind = MONITORS_CHANGED_EVENT;
+ XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
+
+ /* Store this event now since inev.ie.type could be set to
+ MOVE_FRAME_EVENT later. */
+ kbd_buffer_store_event (&inev.ie);
+ inev.ie.kind = NO_EVENT;
+ }
+#endif
+
+ dpyinfo->screen_width = configureEvent.xconfigure.width;
+ dpyinfo->screen_height = configureEvent.xconfigure.height;
+ }
+
+ if (x_dnd_in_progress && x_dnd_use_toplevels
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ int rc, dest_x, dest_y;
+ Window child;
+ struct x_client_list_window *tem, *last = NULL;
+
+ for (tem = x_dnd_toplevels; tem; last = tem, tem = tem->next)
+ {
+ /* Not completely right, since the parent could be
+ unmapped, but good enough. */
+
+ if (tem->window == configureEvent.xconfigure.window)
+ {
+ x_catch_errors (dpyinfo->display);
+ rc = (XTranslateCoordinates (dpyinfo->display,
+ configureEvent.xconfigure.window,
+ dpyinfo->root_window,
+ -configureEvent.xconfigure.border_width,
+ -configureEvent.xconfigure.border_width,
+ &dest_x, &dest_y, &child)
+ && !x_had_errors_p (dpyinfo->display));
+ x_uncatch_errors_after_check ();
+
+ if (rc)
+ {
+ tem->x = dest_x;
+ tem->y = dest_y;
+ tem->width = (configureEvent.xconfigure.width
+ + configureEvent.xconfigure.border_width);
+ tem->height = (configureEvent.xconfigure.height
+ + configureEvent.xconfigure.border_width);
+ }
+ else
+ {
+ /* The window was probably destroyed, so get rid
+ of it. */
+
+ if (!last)
+ x_dnd_toplevels = tem->next;
+ else
+ last->next = tem->next;
+
+#ifdef HAVE_XSHAPE
+ if (tem->n_input_rects != -1)
+ xfree (tem->input_rects);
+ if (tem->n_bounding_rects != -1)
+ xfree (tem->bounding_rects);
+#endif
+ xfree (tem);
+ }
+
+ break;
+ }
+ }
+ }
+
+#if defined HAVE_GTK3 && defined USE_TOOLKIT_SCROLL_BARS
+ struct scroll_bar *bar = x_window_to_scroll_bar (dpyinfo->display,
+ configureEvent.xconfigure.window, 2);
+
+ /* There is really no other way to make GTK scroll bars fit
+ in the dimensions we want them to. */
+ if (bar)
+ {
+ /* Skip all the pending configure events, not just the
+ ones where window motion occurred. */
+ while (XPending (dpyinfo->display))
+ {
+ XNextEvent (dpyinfo->display, &next_event);
+ if (next_event.type != ConfigureNotify
+ || next_event.xconfigure.window != event->xconfigure.window)
+ {
+ XPutBackEvent (dpyinfo->display, &next_event);
+ break;
+ }
+ else
+ configureEvent = next_event;
+ }
+
+ if (configureEvent.xconfigure.width != max (bar->width, 1)
+ || configureEvent.xconfigure.height != max (bar->height, 1))
+ {
+ XResizeWindow (dpyinfo->display, bar->x_window,
+ max (bar->width, 1), max (bar->height, 1));
+ x_flush (WINDOW_XFRAME (XWINDOW (bar->window)));
+ }
+
+ if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
+ x_drop_xrender_surfaces (f);
+
+ goto OTHER;
+ }
+#endif
+
f = x_top_window_to_frame (dpyinfo, configureEvent.xconfigure.window);
- /* Unfortunately, we need to call font_drop_xrender_surfaces for
+ /* Unfortunately, we need to call x_drop_xrender_surfaces for
_all_ ConfigureNotify events, otherwise we miss some and
flicker. Don't try to optimize these calls by looking only
for size changes: that's not sufficient. We miss some
surface invalidations and flicker. */
block_input ();
+#ifdef HAVE_XDBE
if (f && FRAME_X_DOUBLE_BUFFERED_P (f))
- font_drop_xrender_surfaces (f);
+ x_drop_xrender_surfaces (f);
+#endif
unblock_input ();
#if defined USE_CAIRO && !defined USE_GTK
if (f)
@@ -9598,6 +18637,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_cr_update_surface_desired_size (any,
configureEvent.xconfigure.width,
configureEvent.xconfigure.height);
+ if (f || (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any)))
+ x_update_opaque_region (f ? f : any, &configureEvent);
#endif
#ifdef USE_GTK
if (!f
@@ -9618,7 +18659,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
block_input ();
if (FRAME_X_DOUBLE_BUFFERED_P (f))
- font_drop_xrender_surfaces (f);
+ x_drop_xrender_surfaces (f);
unblock_input ();
xg_frame_resized (f, configureEvent.xconfigure.width,
configureEvent.xconfigure.height);
@@ -9626,6 +18667,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
configureEvent.xconfigure.height);
#endif
+ x_update_opaque_region (f, &configureEvent);
f = 0;
}
#endif
@@ -9641,15 +18683,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
x_net_wm_state (f, configureEvent.xconfigure.window);
-#ifdef USE_X_TOOLKIT
+#if defined USE_X_TOOLKIT || defined USE_GTK
/* Tip frames are pure X window, set size for them. */
if (FRAME_TOOLTIP_P (f))
{
if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
|| FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
- {
- SET_FRAME_GARBAGED (f);
- }
+ SET_FRAME_GARBAGED (f);
+
FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
}
@@ -9673,6 +18714,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
/* Even if the number of character rows and columns has
not changed, the font size may have changed, so we need
to check the pixel dimensions as well. */
+
if (width != FRAME_PIXEL_WIDTH (f)
|| height != FRAME_PIXEL_HEIGHT (f)
|| (f->new_size_p
@@ -9724,18 +18766,32 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef HAVE_X_I18N
- if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
- xic_set_statusarea (f);
+ if (f)
+ {
+ if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+ xic_set_statusarea (f);
+
+ struct window *w = XWINDOW (f->selected_window);
+ xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
+ }
#endif
}
+
+ if (x_dnd_in_progress
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
goto OTHER;
case ButtonRelease:
case ButtonPress:
{
+ if (event->xbutton.type == ButtonPress)
+ x_display_set_last_user_time (dpyinfo, event->xbutton.time,
+ event->xbutton.send_event);
+
#ifdef HAVE_XWIDGETS
- struct xwidget_view *xvw = xwidget_view_from_window (event->xmotion.window);
+ struct xwidget_view *xvw = xwidget_view_from_window (event->xbutton.window);
if (xvw)
{
@@ -9759,12 +18815,182 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Lisp_Object tab_bar_arg = Qnil;
bool tab_bar_p = false;
bool tool_bar_p = false;
+ bool dnd_grab = false;
+
+ if (x_dnd_in_progress
+ /* Handle these events normally if the recursion
+ level is higher than when the drag-and-drop
+ operation was initiated. This is so that mouse
+ input works while we're in the debugger for, say,
+ `x-dnd-movement-function`. */
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth)
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
+
+ if (event->type == ButtonPress)
+ {
+ x_display_set_last_user_time (dpyinfo, event->xbutton.time,
+ event->xbutton.send_event);
+
+ dpyinfo->grabbed |= (1 << event->xbutton.button);
+ dpyinfo->last_mouse_frame = f;
+ if (f && !tab_bar_p)
+ f->last_tab_bar_item = -1;
+#if ! defined (USE_GTK)
+ if (f && !tool_bar_p)
+ f->last_tool_bar_item = -1;
+#endif /* not USE_GTK */
+ }
+ else
+ dpyinfo->grabbed &= ~(1 << event->xbutton.button);
+
+ if (event->xbutton.type == ButtonPress
+ && x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ {
+ x_dnd_send_position (x_dnd_frame,
+ x_dnd_last_seen_window,
+ x_dnd_last_protocol_version,
+ event->xbutton.x_root,
+ event->xbutton.y_root,
+ x_dnd_selection_timestamp,
+ x_dnd_wanted_action,
+ event->xbutton.button,
+ event->xbutton.state);
+
+ goto OTHER;
+ }
+
+ if (event->xbutton.type == ButtonRelease)
+ {
+ for (int i = 1; i < 8; ++i)
+ {
+ if (i != event->xbutton.button
+ && event->xbutton.state & (Button1Mask << (i - 1)))
+ dnd_grab = true;
+ }
+
+ if (!dnd_grab)
+ {
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_in_progress = false;
+
+ if (x_dnd_update_tooltip
+ && FRAMEP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && (FRAME_X_DISPLAY (XFRAME (tip_frame))
+ == FRAME_X_DISPLAY (x_dnd_frame)))
+ Fx_hide_tip ();
+
+ x_dnd_finish_frame = x_dnd_frame;
+
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_window_is_frame)
+ {
+ x_dnd_waiting_for_finish = false;
+ x_dnd_note_self_drop (dpyinfo,
+ x_dnd_last_seen_window,
+ event->xbutton.x_root,
+ event->xbutton.y_root,
+ event->xbutton.time);
+ }
+ else if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ {
+ x_dnd_pending_finish_target = x_dnd_last_seen_window;
+ x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
+
+ x_dnd_waiting_for_finish
+ = x_dnd_do_drop (x_dnd_last_seen_window,
+ x_dnd_last_protocol_version);
+ x_dnd_finish_display = dpyinfo->display;
+ }
+ else if (x_dnd_last_seen_window != None)
+ {
+ xm_drop_start_message dmsg;
+ xm_drag_receiver_info drag_receiver_info;
+
+ if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
+ &drag_receiver_info)
+ && !x_dnd_disable_motif_protocol
+ && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
+ && (x_dnd_allow_current_frame
+ || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ {
+ memset (&dmsg, 0, sizeof dmsg);
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ (!x_dnd_xm_use_help
+ ? XM_DROP_ACTION_DROP
+ : XM_DROP_ACTION_DROP_HELP));
+ dmsg.timestamp = event->xbutton.time;
+ dmsg.x = event->xbutton.x_root;
+ dmsg.y = event->xbutton.y_root;
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
+ x_dnd_frame, x_dnd_last_seen_window,
+ event->xbutton.time);
+
+ xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &dmsg);
+
+ x_dnd_waiting_for_finish = true;
+ x_dnd_waiting_for_motif_finish_display = dpyinfo;
+ x_dnd_waiting_for_motif_finish = 1;
+ x_dnd_finish_display = dpyinfo->display;
+ }
+ }
+ else
+ x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
+ ? x_dnd_last_seen_toplevel
+ : x_dnd_last_seen_window),
+ event->xbutton.x_root, event->xbutton.y_root,
+ event->xbutton.time);
+ }
+ else if (x_dnd_last_seen_toplevel != None)
+ x_dnd_send_unsupported_drop (dpyinfo, x_dnd_last_seen_toplevel,
+ event->xbutton.x_root,
+ event->xbutton.y_root,
+ event->xbutton.time);
+
+
+ x_dnd_last_protocol_version = -1;
+ x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_last_window_is_frame = false;
+ x_dnd_frame = NULL;
+ }
+ }
+
+ goto OTHER;
+ }
+
+ if (x_dnd_in_progress
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth))
+ goto OTHER;
memset (&compose_status, 0, sizeof (compose_status));
dpyinfo->last_mouse_glyph_frame = NULL;
- x_display_set_last_user_time (dpyinfo, event->xbutton.time);
- f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window);
+ f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
if (f && event->xbutton.type == ButtonPress
&& !popup_activated ()
&& !x_window_to_scroll_bar (event->xbutton.display,
@@ -9789,7 +19015,37 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, event))
+ if (!f)
+ {
+ f = x_any_window_to_frame (dpyinfo, event->xbutton.window);
+
+ if (event->xbutton.button > 3
+ && event->xbutton.button < 8
+ && f)
+ {
+ if (ignore_next_mouse_click_timeout
+ && dpyinfo == mouse_click_timeout_display)
+ {
+ if (event->type == ButtonPress
+ && event->xbutton.time > ignore_next_mouse_click_timeout)
+ {
+ ignore_next_mouse_click_timeout = 0;
+ x_construct_mouse_click (&inev.ie, &event->xbutton, f);
+ }
+ if (event->type == ButtonRelease)
+ ignore_next_mouse_click_timeout = 0;
+ }
+ else
+ x_construct_mouse_click (&inev.ie, &event->xbutton, f);
+
+ *finish = X_EVENT_DROP;
+ goto OTHER;
+ }
+ else
+ f = NULL;
+ }
+
+ if (f && xg_event_is_for_scrollbar (f, event, false))
f = 0;
#endif
if (f)
@@ -9821,7 +19077,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int y = event->xbutton.y;
window = window_from_coordinates (f, x, y, 0, true, true);
- tool_bar_p = EQ (window, f->tool_bar_window);
+ tool_bar_p = (EQ (window, f->tool_bar_window)
+ && (event->xbutton.type != ButtonRelease
+ || f->last_tool_bar_item != -1));
if (tool_bar_p && event->xbutton.button < 4)
handle_tool_bar_click
@@ -9835,7 +19093,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (! popup_activated ())
#endif
{
- if (ignore_next_mouse_click_timeout)
+ if (ignore_next_mouse_click_timeout
+ && dpyinfo == mouse_click_timeout_display)
{
if (event->type == ButtonPress
&& event->xbutton.time > ignore_next_mouse_click_timeout)
@@ -9867,12 +19126,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
scroll bars. */
if (bar && event->xbutton.state & ControlMask)
{
- x_scroll_bar_handle_click (bar, event, &inev.ie);
+ x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
*finish = X_EVENT_DROP;
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
if (bar)
- x_scroll_bar_handle_click (bar, event, &inev.ie);
+ x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
@@ -9898,11 +19157,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
f = x_menubar_window_to_frame (dpyinfo, event);
- /* For a down-event in the menu bar,
- don't pass it to Xt right now.
- Instead, save it away
- and we will pass it to Xt from kbd_buffer_get_event.
- That way, we can run some Lisp code first. */
+ /* For a down-event in the menu bar, don't pass it to Xt or
+ GTK right away. Instead, save it and pass it to Xt or GTK
+ from kbd_buffer_get_event. That way, we can run some Lisp
+ code first. */
if (! popup_activated ()
#ifdef USE_GTK
/* Gtk+ menus only react to the first three buttons. */
@@ -9917,12 +19175,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
&& event->xbutton.y < FRAME_MENUBAR_HEIGHT (f)
&& event->xbutton.same_screen)
{
- if (!f->output_data.x->saved_menu_event)
- f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
- *f->output_data.x->saved_menu_event = *event;
- inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
- XSETFRAME (inev.ie.frame_or_window, f);
- *finish = X_EVENT_DROP;
+#ifdef USE_MOTIF
+ Widget widget;
+
+ widget = XtWindowToWidget (dpyinfo->display,
+ event->xbutton.window);
+
+ if (widget && XmIsCascadeButton (widget)
+ && XtIsSensitive (widget))
+ {
+#endif
+ if (!f->output_data.x->saved_menu_event)
+ f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
+ *f->output_data.x->saved_menu_event = *event;
+ inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ *finish = X_EVENT_DROP;
+#ifdef USE_MOTIF
+ }
+#endif
}
else
goto OTHER;
@@ -9931,6 +19202,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
break;
case CirculateNotify:
+ if (x_dnd_in_progress
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
goto OTHER;
case CirculateRequest:
@@ -9958,16 +19232,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto OTHER;
case DestroyNotify:
+ if (event->xdestroywindow.window
+ == dpyinfo->net_supported_window)
+ dpyinfo->net_supported_window = None;
+
xft_settings_event (dpyinfo, event);
break;
+
#ifdef HAVE_XINPUT2
case GenericEvent:
{
if (!dpyinfo->supports_xi2)
goto OTHER;
+
if (event->xgeneric.extension != dpyinfo->xi2_opcode)
/* Not an XI2 event. */
goto OTHER;
+
bool must_free_data = false;
XIEvent *xi_event = (XIEvent *) event->xcookie.data;
/* Sometimes the event is already claimed by GTK, which
@@ -9979,18 +19260,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
- XILeaveEvent *leave = (XILeaveEvent *) xi_event;
- XIEnterEvent *enter = (XIEnterEvent *) xi_event;
- XIFocusInEvent *focusin = (XIFocusInEvent *) xi_event;
- XIFocusOutEvent *focusout = (XIFocusOutEvent *) xi_event;
- XIValuatorState *states;
- double *values;
- bool found_valuator = false;
-
- /* A fake XMotionEvent for x_note_mouse_movement. */
- XMotionEvent ev;
- /* A fake XButtonEvent for x_construct_mouse_click. */
- XButtonEvent bv;
if (!xi_event)
{
@@ -10001,46 +19270,206 @@ handle_one_xevent (struct x_display_info *dpyinfo,
switch (event->xcookie.evtype)
{
case XI_FocusIn:
- any = x_any_window_to_frame (dpyinfo, focusin->event);
-#ifndef USE_GTK
- /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
- minimized/iconified windows; thus, for those WMs we won't get
- a MapNotify when unminimizing/deconifying. Check here if we
- are deiconizing a window (Bug42655).
-
- But don't do that on GTK since it may cause a plain invisible
- frame get reported as iconified, compare
- https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
- That is fixed above but bites us here again. */
- f = any;
- if (f && FRAME_ICONIFIED_P (f))
- {
- SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, false);
- f->output_data.x->has_been_visible = true;
- inev.ie.kind = DEICONIFY_EVENT;
- XSETFRAME (inev.ie.frame_or_window, f);
- }
+ {
+ XIFocusInEvent *focusin = (XIFocusInEvent *) xi_event;
+ struct xi_device_t *source;
+
+ any = x_any_window_to_frame (dpyinfo, focusin->event);
+ source = xi_device_from_id (dpyinfo, focusin->sourceid);
+#ifdef USE_GTK
+ /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
+ minimized/iconified windows; thus, for those WMs we won't get
+ a MapNotify when unminimizing/deiconifying. Check here if we
+ are deiconizing a window (Bug42655).
+
+ But don't do that by default on GTK since it may cause a plain
+ invisible frame get reported as iconified, compare
+ https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
+ That is fixed above but bites us here again.
+
+ The option x_set_frame_visibility_more_laxly allows to override
+ the default behavior (Bug#49955, Bug#53298). */
+ if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
+ || EQ (x_set_frame_visibility_more_laxly, Qt))
#endif /* USE_GTK */
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
- goto XI_OTHER;
+ {
+ f = any;
+ if (f && FRAME_ICONIFIED_P (f))
+ {
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, false);
+ f->output_data.x->has_been_visible = true;
+ inev.ie.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ }
+ }
+
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+ if (inev.ie.kind != NO_EVENT && source)
+ inev.ie.device = source->name;
+ goto XI_OTHER;
+ }
+
case XI_FocusOut:
- any = x_any_window_to_frame (dpyinfo, focusout->event);
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
- goto XI_OTHER;
- case XI_Enter:
- any = x_any_window_to_frame (dpyinfo, enter->event);
- ev.x = lrint (enter->event_x);
- ev.y = lrint (enter->event_y);
- ev.window = leave->event;
+ {
+ XIFocusOutEvent *focusout = (XIFocusOutEvent *) xi_event;
+ struct xi_device_t *source;
+
+ any = x_any_window_to_frame (dpyinfo, focusout->event);
+ source = xi_device_from_id (dpyinfo, focusout->sourceid);
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
- x_display_set_last_user_time (dpyinfo, xi_event->time);
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+ if (inev.ie.kind != NO_EVENT && source)
+ inev.ie.device = source->name;
+ goto XI_OTHER;
+ }
+
+ case XI_Enter:
{
+ XIEnterEvent *enter = (XIEnterEvent *) xi_event;
+ XMotionEvent ev;
+ struct xi_device_t *source;
+
+ any = x_top_window_to_frame (dpyinfo, enter->event);
+ source = xi_device_from_id (dpyinfo, enter->sourceid);
+
+ ev.x = lrint (enter->event_x);
+ ev.y = lrint (enter->event_y);
+ ev.window = enter->event;
+ ev.time = enter->time;
+ ev.send_event = enter->send_event;
+
+ x_display_set_last_user_time (dpyinfo, enter->time,
+ enter->send_event);
+
+#ifdef USE_MOTIF
+ use_copy = true;
+
+ copy.xcrossing.type = EnterNotify;
+ copy.xcrossing.serial = enter->serial;
+ copy.xcrossing.send_event = enter->send_event;
+ copy.xcrossing.display = dpyinfo->display;
+ copy.xcrossing.window = enter->event;
+ copy.xcrossing.root = enter->root;
+ copy.xcrossing.subwindow = enter->child;
+ copy.xcrossing.time = enter->time;
+ copy.xcrossing.x = lrint (enter->event_x);
+ copy.xcrossing.y = lrint (enter->event_y);
+ copy.xcrossing.x_root = lrint (enter->root_x);
+ copy.xcrossing.y_root = lrint (enter->root_y);
+ copy.xcrossing.mode = enter->mode;
+ copy.xcrossing.detail = enter->detail;
+ copy.xcrossing.focus = enter->focus;
+ copy.xcrossing.state = 0;
+ copy.xcrossing.same_screen = True;
+#endif
+
+ /* There is no need to handle entry/exit events for
+ passive focus from non-top windows at all, since they
+ are an inferiors of the frame's top window, which will
+ get virtual events. */
+ if (any)
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+
+ if (!any)
+ any = x_any_window_to_frame (dpyinfo, enter->event);
+
+#ifdef HAVE_XINPUT2_1
+ xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid,
+ true);
+#endif
+
+ {
#ifdef HAVE_XWIDGETS
- struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event);
-#else
- bool xwidget_view = false;
+ struct xwidget_view *xwidget_view = xwidget_view_from_window (enter->event);
+#endif
+
+#ifdef HAVE_XWIDGETS
+ if (xwidget_view)
+ {
+ xwidget_motion_or_crossing (xwidget_view, event);
+
+ goto XI_OTHER;
+ }
+#endif
+ }
+
+ f = any;
+
+ if (f && x_mouse_click_focus_ignore_position)
+ {
+ ignore_next_mouse_click_timeout = (enter->time
+ + x_mouse_click_focus_ignore_time);
+ mouse_click_timeout_display = dpyinfo;
+ }
+
+ /* EnterNotify counts as mouse movement,
+ so update things that depend on mouse position. */
+ if (f && !f->output_data.x->hourglass_p)
+ x_note_mouse_movement (f, &ev, source ? source->name : Qnil);
+#ifdef USE_GTK
+ /* We may get an EnterNotify on the buttons in the toolbar. In that
+ case we moved out of any highlighted area and need to note this. */
+ if (!f && dpyinfo->last_mouse_glyph_frame)
+ x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
+ source ? source->name : Qnil);
+#endif
+ goto XI_OTHER;
+ }
+
+ case XI_Leave:
+ {
+ XILeaveEvent *leave = (XILeaveEvent *) xi_event;
+#ifdef USE_GTK
+ struct xi_device_t *source;
+ XMotionEvent ev;
+
+ ev.x = lrint (leave->event_x);
+ ev.y = lrint (leave->event_y);
+ ev.window = leave->event;
+ ev.time = leave->time;
+ ev.send_event = leave->send_event;
+#endif
+
+ any = x_top_window_to_frame (dpyinfo, leave->event);
+
+#ifdef USE_GTK
+ source = xi_device_from_id (dpyinfo, leave->sourceid);
+#endif
+
+ /* This allows us to catch LeaveNotify events generated by
+ popup menu grabs. FIXME: this is right when there is a
+ focus menu, but implicit focus tracking can get screwed
+ up if we get this and no XI_Enter event later. */
+
+#ifdef USE_X_TOOLKIT
+ if (popup_activated ()
+ && (leave->mode == XINotifyPassiveUngrab
+ || leave->mode == XINotifyUngrab))
+ any = x_any_window_to_frame (dpyinfo, leave->event);
+#endif
+
+#ifdef USE_MOTIF
+ use_copy = true;
+
+ copy.xcrossing.type = LeaveNotify;
+ copy.xcrossing.serial = leave->serial;
+ copy.xcrossing.send_event = leave->send_event;
+ copy.xcrossing.display = dpyinfo->display;
+ copy.xcrossing.window = leave->event;
+ copy.xcrossing.root = leave->root;
+ copy.xcrossing.subwindow = leave->child;
+ copy.xcrossing.time = leave->time;
+ copy.xcrossing.x = lrint (leave->event_x);
+ copy.xcrossing.y = lrint (leave->event_y);
+ copy.xcrossing.x_root = lrint (leave->root_x);
+ copy.xcrossing.y_root = lrint (leave->root_y);
+ copy.xcrossing.mode = leave->mode;
+ copy.xcrossing.detail = leave->detail;
+ copy.xcrossing.focus = leave->focus;
+ copy.xcrossing.state = 0;
+ copy.xcrossing.same_screen = True;
#endif
/* One problem behind the design of XInput 2 scrolling is
@@ -10054,130 +19483,133 @@ handle_one_xevent (struct x_display_info *dpyinfo,
As such, to prevent wildly inaccurate results when the
valuators have changed outside Emacs, we reset our
records of each valuator's value whenever the pointer
- re-enters a frame after its valuators have potentially
- been changed elsewhere. */
- if (enter->detail != XINotifyInferior
- && enter->mode != XINotifyPassiveUngrab
- /* See the comment under FocusIn in
- `x_detect_focus_change'. The main relevant culprit
- these days seems to be XFCE. */
- && enter->mode != XINotifyUngrab
- && (xwidget_view
- || (any && enter->event == FRAME_X_WINDOW (any))))
- xi_reset_scroll_valuators_for_device_id (dpyinfo, enter->deviceid);
-
-#ifdef HAVE_XWIDGETS
- if (xwidget_view)
- {
- /* Don't send an enter event to the xwidget if the
- first button is pressed, to avoid it releasing
- the passive grab. I don't know why that happens,
- but this workaround makes dragging to select text
- work again. */
- if (!(enter->buttons.mask_len
- && XIMaskIsSet (enter->buttons.mask, 1)))
- xwidget_motion_or_crossing (xwidget_view, event);
-
- goto XI_OTHER;
- }
+ moves out of a frame (and not into one of its
+ children, which we know about). */
+#ifdef HAVE_XINPUT2_1
+ if (leave->detail != XINotifyInferior && any)
+ xi_reset_scroll_valuators_for_device_id (dpyinfo,
+ leave->deviceid, false);
#endif
- }
-
- f = any;
-
- if (f && x_mouse_click_focus_ignore_position)
- ignore_next_mouse_click_timeout = xi_event->time + 200;
- /* EnterNotify counts as mouse movement,
- so update things that depend on mouse position. */
- if (f && !f->output_data.x->hourglass_p)
- x_note_mouse_movement (f, &ev);
-#ifdef USE_GTK
- /* We may get an EnterNotify on the buttons in the toolbar. In that
- case we moved out of any highlighted area and need to note this. */
- if (!f && dpyinfo->last_mouse_glyph_frame)
- x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
-#endif
- goto XI_OTHER;
- case XI_Leave:
- ev.x = lrint (leave->event_x);
- ev.y = lrint (leave->event_y);
- ev.window = leave->event;
- any = x_any_window_to_frame (dpyinfo, leave->event);
+ x_display_set_last_user_time (dpyinfo, leave->time,
+ leave->send_event);
#ifdef HAVE_XWIDGETS
- {
- struct xwidget_view *xvw
- = xwidget_view_from_window (leave->event);
+ {
+ struct xwidget_view *xvw
+ = xwidget_view_from_window (leave->event);
- if (xvw)
- {
- *finish = X_EVENT_DROP;
- xwidget_motion_or_crossing (xvw, event);
+ if (xvw)
+ {
+ *finish = X_EVENT_DROP;
+ xwidget_motion_or_crossing (xvw, event);
- goto XI_OTHER;
- }
- }
+ goto XI_OTHER;
+ }
+ }
#endif
- x_display_set_last_user_time (dpyinfo, xi_event->time);
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+ if (any)
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
#ifndef USE_X_TOOLKIT
- f = x_top_window_to_frame (dpyinfo, leave->event);
+ f = x_top_window_to_frame (dpyinfo, leave->event);
#else
- /* On Xt builds that have XI2, the enter and leave event
- masks are set on the frame widget's window. */
- f = x_window_to_frame (dpyinfo, leave->event);
+ /* On Xt builds that have XI2, the enter and leave event
+ masks are set on the frame widget's window. */
+ f = x_window_to_frame (dpyinfo, leave->event);
+
+ /* Also do this again here, since the test for `any'
+ above may not have found a frame, as that usually
+ just looks up a top window on Xt builds. */
+
+#ifdef HAVE_XINPUT2_1
+ if (leave->detail != XINotifyInferior && f)
+ xi_reset_scroll_valuators_for_device_id (dpyinfo,
+ leave->deviceid, false);
#endif
- if (f)
- {
- if (f == hlinfo->mouse_face_mouse_frame)
- {
- /* If we move outside the frame, then we're
- certainly no longer on any text in the frame. */
- clear_mouse_face (hlinfo);
- hlinfo->mouse_face_mouse_frame = 0;
- }
- /* Generate a nil HELP_EVENT to cancel a help-echo.
- Do it only if there's something to cancel.
- Otherwise, the startup message is cleared when
- the mouse leaves the frame. */
- if (any_help_event_p)
- do_help = -1;
- }
+ if (!f)
+ f = x_top_window_to_frame (dpyinfo, leave->event);
+#endif
+ if (f)
+ {
+ if (f == hlinfo->mouse_face_mouse_frame)
+ {
+ /* If we move outside the frame, then we're
+ certainly no longer on any text in the frame. */
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_mouse_frame = 0;
+ }
+
+ /* Generate a nil HELP_EVENT to cancel a help-echo.
+ Do it only if there's something to cancel.
+ Otherwise, the startup message is cleared when
+ the mouse leaves the frame. */
+ if (any_help_event_p
+ /* But never if `mouse-drag-and-drop-region' is
+ in progress, since that results in the
+ tooltip being dismissed when the mouse moves
+ on top. */
+ && !((EQ (track_mouse, Qdrag_source)
+ || EQ (track_mouse, Qdropping))
+ && gui_mouse_grabbed (dpyinfo)))
+ do_help = -1;
+ }
#ifdef USE_GTK
- /* See comment in EnterNotify above */
- else if (dpyinfo->last_mouse_glyph_frame)
- x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
+ /* See comment in EnterNotify above */
+ else if (dpyinfo->last_mouse_glyph_frame)
+ x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
+ source ? source->name : Qnil);
#endif
- goto XI_OTHER;
+ goto XI_OTHER;
+ }
+
case XI_Motion:
{
- struct xi_device_t *device;
- bool touch_end_event_seen = false;
-
+ struct xi_device_t *device, *source;
+#ifdef HAVE_XINPUT2_1
+ XIValuatorState *states;
+ double *values;
+ bool found_valuator = false;
+ bool other_valuators_found = false;
+#endif
+ /* A fake XMotionEvent for x_note_mouse_movement. */
+ XMotionEvent ev;
+ xm_top_level_leave_message lmsg;
+ xm_top_level_enter_message emsg;
+ xm_drag_motion_message dmsg;
+ unsigned int dnd_state;
+
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
+
+#ifdef HAVE_XINPUT2_1
states = &xev->valuators;
values = states->values;
+#endif
+
device = xi_device_from_id (dpyinfo, xev->deviceid);
- if (!device || !device->master_p)
+ if (!device)
goto XI_OTHER;
-#ifdef XI_TouchBegin
- if (xev->flags & XIPointerEmulated
- && dpyinfo->xi2_version >= 2)
+#ifdef HAVE_XINPUT2_2
+ if (xev->flags & XIPointerEmulated)
goto XI_OTHER;
#endif
- x_display_set_last_user_time (dpyinfo, xi_event->time);
+ Window dummy;
+#ifdef HAVE_XINPUT2_1
#ifdef HAVE_XWIDGETS
struct xwidget_view *xv = xwidget_view_from_window (xev->event);
double xv_total_x = 0.0;
double xv_total_y = 0.0;
#endif
+ double total_x = 0.0;
+ double total_y = 0.0;
+
+ int real_x, real_y;
for (int i = 0; i < states->mask_len * 8; i++)
{
@@ -10187,26 +19619,79 @@ handle_one_xevent (struct x_display_info *dpyinfo,
double delta, scroll_unit;
int scroll_height;
Lisp_Object window;
+ struct scroll_bar *bar;
+ bar = NULL;
/* See the comment on top of
x_init_master_valuators for more details on how
scroll wheel movement is reported on XInput 2. */
- delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid,
+ delta = x_get_scroll_valuator_delta (dpyinfo, device,
i, *values, &val);
+ values++;
+
+ if (!val)
+ {
+ other_valuators_found = true;
+ continue;
+ }
if (delta != DBL_MAX)
{
+ if (!f)
+ {
+ f = x_any_window_to_frame (dpyinfo, xev->event);
+
+ if (!f)
+ {
+#if defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
+ bar = x_window_to_scroll_bar (dpyinfo->display,
+ xev->event, 2);
+
+ if (bar)
+ f = WINDOW_XFRAME (XWINDOW (bar->window));
+
+ if (!f)
+#endif
+ goto XI_OTHER;
+ }
+ }
+
+#ifdef USE_GTK
+ if (f && xg_event_is_for_scrollbar (f, event, true))
+ *finish = X_EVENT_DROP;
+#endif
+
+ if (FRAME_X_WINDOW (f) != xev->event)
+ {
+ if (!bar)
+ bar = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
+
+ /* If this is a scroll bar, compute the
+ actual position directly to avoid an
+ extra roundtrip. */
+
+ if (bar)
+ {
+ real_x = lrint (xev->event_x + bar->left);
+ real_y = lrint (xev->event_y + bar->top);
+ }
+ else
+ XTranslateCoordinates (dpyinfo->display,
+ xev->event, FRAME_X_WINDOW (f),
+ lrint (xev->event_x),
+ lrint (xev->event_y),
+ &real_x, &real_y, &dummy);
+ }
+ else
+ {
+ real_x = lrint (xev->event_x);
+ real_y = lrint (xev->event_y);
+ }
+
#ifdef HAVE_XWIDGETS
if (xv)
{
- /* FIXME: figure out what in GTK is
- causing interval values to jump by
- >100 at the end of a touch sequence
- when an xwidget gets a scroll event
- where is_stop is TRUE. */
- if (fabs (delta) > 100)
- continue;
if (val->horizontal)
xv_total_x += delta;
else
@@ -10216,15 +19701,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
continue;
}
#endif
- if (!f)
- {
- f = x_any_window_to_frame (dpyinfo, xev->event);
- if (!f)
- goto XI_OTHER;
- }
-
- found_valuator = true;
+ if (delta == 0.0)
+ found_valuator = true;
if (signbit (delta) != signbit (val->emacs_value))
val->emacs_value = 0;
@@ -10236,28 +19715,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
&& (fabs (delta) > 0))
continue;
- bool s = signbit (val->emacs_value);
- inev.ie.kind = (fabs (delta) > 0
- ? (val->horizontal
- ? HORIZ_WHEEL_EVENT
- : WHEEL_EVENT)
- : TOUCH_END_EVENT);
- inev.ie.timestamp = xev->time;
-
- XSETINT (inev.ie.x, lrint (xev->event_x));
- XSETINT (inev.ie.y, lrint (xev->event_y));
- XSETFRAME (inev.ie.frame_or_window, f);
-
- if (fabs (delta) > 0)
- {
- inev.ie.modifiers = !s ? up_modifier : down_modifier;
- inev.ie.modifiers
- |= x_x_to_emacs_modifiers (dpyinfo,
- xev->mods.effective);
- }
-
- window = window_from_coordinates (f, xev->event_x,
- xev->event_y, NULL,
+ window = window_from_coordinates (f, real_x, real_y, NULL,
false, false);
if (WINDOWP (window))
@@ -10273,57 +19731,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (NUMBERP (Vx_scroll_event_delta_factor))
scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
- if (fabs (delta) > 0)
- {
- if (val->horizontal)
- {
- inev.ie.arg
- = list3 (Qnil,
- make_float (val->emacs_value
- * scroll_unit),
- make_float (0));
- }
- else
- {
- inev.ie.arg = list3 (Qnil, make_float (0),
- make_float (val->emacs_value
- * scroll_unit));
- }
- }
+ if (val->horizontal)
+ total_x += val->emacs_value * scroll_unit;
else
- {
- inev.ie.arg = Qnil;
- }
-
- if (inev.ie.kind != TOUCH_END_EVENT
- || !touch_end_event_seen)
- {
- kbd_buffer_store_event_hold (&inev.ie, hold_quit);
- touch_end_event_seen = inev.ie.kind == TOUCH_END_EVENT;
- }
+ total_y += val->emacs_value * scroll_unit;
+ found_valuator = true;
val->emacs_value = 0;
}
- values++;
}
-
- inev.ie.kind = NO_EVENT;
}
#ifdef HAVE_XWIDGETS
if (xv)
{
- uint state = xev->mods.effective;
+ unsigned int state;
- if (xev->buttons.mask_len)
- {
- if (XIMaskIsSet (xev->buttons.mask, 1))
- state |= Button1Mask;
- if (XIMaskIsSet (xev->buttons.mask, 2))
- state |= Button2Mask;
- if (XIMaskIsSet (xev->buttons.mask, 3))
- state |= Button3Mask;
- }
+ state = xi_convert_event_state (xev);
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
if (found_valuator)
xwidget_scroll (xv, xev->event_x, xev->event_y,
@@ -10337,20 +19763,105 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto XI_OTHER;
}
-#endif
- if (found_valuator)
+ else
{
-#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, event))
- *finish = X_EVENT_DROP;
#endif
- goto XI_OTHER;
+ if (found_valuator)
+ {
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
+
+
+#if defined USE_GTK && !defined HAVE_GTK3
+ /* Unlike on Motif, we can't select for XI
+ events on the scroll bar window under GTK+ 2.
+ So instead of that, just ignore XI wheel
+ events which land on a scroll bar.
+
+ Here we assume anything which isn't the edit
+ widget window is a scroll bar. */
+
+ if (xev->child != None
+ && xev->child != FRAME_X_WINDOW (f))
+ goto XI_OTHER;
+#endif
+
+ /* If this happened during a drag-and-drop
+ operation, don't send an event. We only have
+ to set the user time. */
+ if (x_dnd_in_progress
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth)
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ goto XI_OTHER;
+
+ if (fabs (total_x) > 0 || fabs (total_y) > 0)
+ {
+ inev.ie.kind = (fabs (total_y) >= fabs (total_x)
+ ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
+ inev.ie.timestamp = xev->time;
+
+ XSETINT (inev.ie.x, lrint (real_x));
+ XSETINT (inev.ie.y, lrint (real_y));
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
+ ? total_y : total_x)
+ ? down_modifier : up_modifier);
+ inev.ie.modifiers
+ |= x_x_to_emacs_modifiers (dpyinfo,
+ xev->mods.effective);
+ inev.ie.arg = list3 (Qnil,
+ make_float (total_x),
+ make_float (total_y));
+ }
+ else
+ {
+ inev.ie.kind = TOUCH_END_EVENT;
+ inev.ie.timestamp = xev->time;
+
+ XSETINT (inev.ie.x, lrint (real_x));
+ XSETINT (inev.ie.y, lrint (real_y));
+ XSETFRAME (inev.ie.frame_or_window, f);
+ }
+
+ if (source && !NILP (source->name))
+ inev.ie.device = source->name;
+
+ if (!other_valuators_found)
+ goto XI_OTHER;
+ }
+#ifdef HAVE_XWIDGETS
}
+#endif
+#endif /* HAVE_XINPUT2_1 */
ev.x = lrint (xev->event_x);
ev.y = lrint (xev->event_y);
ev.window = xev->event;
ev.time = xev->time;
+ ev.send_event = xev->send_event;
+
+#ifdef USE_MOTIF
+ use_copy = true;
+
+ copy.xmotion.type = MotionNotify;
+ copy.xmotion.serial = xev->serial;
+ copy.xmotion.send_event = xev->send_event;
+ copy.xmotion.display = dpyinfo->display;
+ copy.xmotion.window = xev->event;
+ copy.xmotion.root = xev->root;
+ copy.xmotion.subwindow = xev->child;
+ copy.xmotion.time = xev->time;
+ copy.xmotion.x = lrint (xev->event_x);
+ copy.xmotion.y = lrint (xev->event_y);
+ copy.xmotion.x_root = lrint (xev->root_x);
+ copy.xmotion.y_root = lrint (xev->root_y);
+ copy.xmotion.state = xi_convert_event_state (xev);
+
+ copy.xmotion.is_hint = False;
+ copy.xmotion.same_screen = True;
+#endif
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
@@ -10363,12 +19874,252 @@ handle_one_xevent (struct x_display_info *dpyinfo,
f = mouse_or_wdesc_frame (dpyinfo, xev->event);
+ if (x_dnd_in_progress
+ /* Handle these events normally if the recursion
+ level is higher than when the drag-and-drop
+ operation was initiated. This is so that mouse
+ input works while we're in the debugger for, say,
+ `x-dnd-movement-function`. */
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth)
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ Window target, toplevel;
+ int target_proto, motif_style;
+ XRectangle *r;
+ bool was_frame;
+
+ /* Always clear mouse face. */
+ clear_mouse_face (hlinfo);
+ hlinfo->mouse_face_hidden = true;
+
+ /* Sometimes the drag-and-drop operation starts with the
+ pointer of a frame invisible due to input. Since
+ motion events are ignored during that, make the pointer
+ visible manually. */
+
+ if (f)
+ {
+ XTtoggle_invisible_pointer (f, false);
+
+ r = &dpyinfo->last_mouse_glyph;
+
+ /* Also remember the mouse glyph and set
+ mouse_moved. */
+ if (f != dpyinfo->last_mouse_glyph_frame
+ || xev->event_x < r->x
+ || xev->event_x >= r->x + r->width
+ || xev->event_y < r->y
+ || xev->event_y >= r->y + r->height)
+ {
+ f->mouse_moved = true;
+ f->last_mouse_device = (source ? source->name
+ : Qnil);
+ dpyinfo->last_mouse_scroll_bar = NULL;
+
+ remember_mouse_glyph (f, xev->event_x,
+ xev->event_y, r);
+ dpyinfo->last_mouse_glyph_frame = f;
+ }
+ }
+
+ if (xev->root == dpyinfo->root_window)
+ target = x_dnd_get_target_window (dpyinfo,
+ xev->root_x,
+ xev->root_y,
+ &target_proto,
+ &motif_style,
+ &toplevel,
+ &was_frame);
+ else
+ target = x_dnd_fill_empty_target (&target_proto,
+ &motif_style,
+ &toplevel,
+ &was_frame);
+
+ if (toplevel != x_dnd_last_seen_toplevel)
+ {
+ if (toplevel != FRAME_OUTER_WINDOW (x_dnd_frame)
+ && x_dnd_return_frame == 1)
+ x_dnd_return_frame = 2;
+
+ if (x_dnd_return_frame == 2
+ && x_any_window_to_frame (dpyinfo, toplevel))
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = xev->time;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_return_frame_object
+ = x_any_window_to_frame (dpyinfo, toplevel);
+ x_dnd_return_frame = 3;
+ x_dnd_waiting_for_finish = false;
+ target = None;
+ }
+
+ x_dnd_last_seen_toplevel = toplevel;
+ }
+
+ if (target != x_dnd_last_seen_window)
+ {
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag
+ && x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ /* This is apparently required. If we don't
+ send a motion event with the current root
+ window coordinates of the pointer before
+ the top level leave, then Motif displays
+ an ugly black border around the previous
+ drop site. */
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_NONE, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.timestamp = xev->time;
+ dmsg.x = lrint (xev->root_x);
+ dmsg.y = lrint (xev->root_y);
+
+ lmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_LEAVE);
+ lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ lmsg.zero = 0;
+ lmsg.timestamp = xev->time;
+ lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ {
+ xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &dmsg);
+ xm_send_top_level_leave_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &lmsg);
+ }
+ }
+
+ x_dnd_action = None;
+ x_dnd_last_seen_window = target;
+ x_dnd_last_protocol_version = target_proto;
+ x_dnd_last_motif_style = motif_style;
+ x_dnd_last_window_is_frame = was_frame;
+
+ if (target != None && x_dnd_last_protocol_version != -1)
+ x_dnd_send_enter (x_dnd_frame, target,
+ x_dnd_last_protocol_version);
+ else if (target != None && XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style)
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ emsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_TOP_LEVEL_ENTER);
+ emsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ emsg.zero = 0;
+ emsg.timestamp = xev->time;
+ emsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+ emsg.index_atom = x_dnd_motif_atom;
+
+ if (x_dnd_motif_setup_p)
+ xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &emsg);
+ }
+ }
+
+ if (x_dnd_last_window_is_frame && target != None)
+ x_dnd_note_self_position (dpyinfo, target,
+ xev->root_x, xev->root_y);
+ else if (x_dnd_last_protocol_version != -1 && target != None)
+ {
+ dnd_state = xi_convert_event_state (xev);
+
+ x_dnd_send_position (x_dnd_frame, target,
+ x_dnd_last_protocol_version,
+ xev->root_x, xev->root_y,
+ x_dnd_selection_timestamp,
+ x_dnd_wanted_action, 0,
+ dnd_state);
+ }
+ else if (XM_DRAG_STYLE_IS_DYNAMIC (x_dnd_last_motif_style) && target != None
+ && !x_dnd_disable_motif_drag)
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DRAG_MOTION);
+ dmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ (!x_dnd_xm_use_help
+ ? XM_DROP_ACTION_DROP
+ : XM_DROP_ACTION_DROP_HELP));
+ dmsg.timestamp = xev->time;
+ dmsg.x = lrint (xev->root_x);
+ dmsg.y = lrint (xev->root_y);
+
+ if (x_dnd_motif_setup_p)
+ xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ target, &dmsg);
+ }
+
+ x_dnd_update_tooltip_position (xev->root_x, xev->root_y);
+
+ goto XI_OTHER;
+ }
+
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, event))
+ if (f && xg_event_is_for_scrollbar (f, event, false))
f = 0;
#endif
if (f)
{
+ if (xev->event != FRAME_X_WINDOW (f))
+ {
+ XTranslateCoordinates (FRAME_X_DISPLAY (f),
+ xev->event, FRAME_X_WINDOW (f),
+ ev.x, ev.y, &ev.x, &ev.y, &dummy);
+ ev.window = FRAME_X_WINDOW (f);
+ }
+
/* Maybe generate a SELECT_WINDOW_EVENT for
`mouse-autoselect-window' but don't let popup menus
interfere with this (Bug#1261). */
@@ -10402,20 +20153,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
inev.ie.kind = SELECT_WINDOW_EVENT;
inev.ie.frame_or_window = window;
+
+ if (source)
+ inev.ie.device = source->name;
}
/* Remember the last window where we saw the mouse. */
last_mouse_window = window;
}
- if (!x_note_mouse_movement (f, &ev))
+ if (!x_note_mouse_movement (f, &ev, source ? source->name : Qnil))
help_echo_string = previous_help_echo_string;
}
else
{
#ifndef USE_TOOLKIT_SCROLL_BARS
struct scroll_bar *bar
- = x_window_to_scroll_bar (xi_event->display, xev->event, 2);
+ = x_window_to_scroll_bar (dpyinfo->display, xev->event, 2);
if (bar)
x_scroll_bar_note_movement (bar, &ev);
@@ -10433,6 +20187,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
do_help = 1;
goto XI_OTHER;
}
+
case XI_ButtonRelease:
case XI_ButtonPress:
{
@@ -10441,37 +20196,301 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Lisp_Object tab_bar_arg = Qnil;
bool tab_bar_p = false;
bool tool_bar_p = false;
- struct xi_device_t *device;
+ struct xi_device_t *device, *source;
#ifdef HAVE_XWIDGETS
struct xwidget_view *xvw;
#endif
+ /* A fake XButtonEvent for x_construct_mouse_click. */
+ XButtonEvent bv;
+ bool dnd_grab = false;
+ int dnd_state;
+ if (x_dnd_in_progress
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth)
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+ f = mouse_or_wdesc_frame (dpyinfo, xev->event);
+ device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+ /* Don't track grab status for emulated pointer
+ events, because they are ignored by the regular
+ mouse click processing code. */
+#ifdef XIPointerEmulated
+ if (!(xev->flags & XIPointerEmulated))
+ {
+#endif
+ if (xev->evtype == XI_ButtonPress)
+ {
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
+
+ dpyinfo->grabbed |= (1 << xev->detail);
+ dpyinfo->last_mouse_frame = f;
+
+ if (device)
+ device->grab |= (1 << xev->detail);
+
+ if (f && !tab_bar_p)
+ f->last_tab_bar_item = -1;
+#if ! defined (USE_GTK)
+ if (f && !tool_bar_p)
+ f->last_tool_bar_item = -1;
+#endif /* not USE_GTK */
+ }
+ else
+ {
+ dpyinfo->grabbed &= ~(1 << xev->detail);
+ device->grab &= ~(1 << xev->detail);
+ }
#ifdef XIPointerEmulated
+ }
+#endif
+
+ if (xev->evtype == XI_ButtonPress
+ && x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ {
+ dnd_state = xi_convert_event_state (xev);
+
+ x_dnd_send_position (x_dnd_frame, x_dnd_last_seen_window,
+ x_dnd_last_protocol_version, xev->root_x,
+ xev->root_y, x_dnd_selection_timestamp,
+ x_dnd_wanted_action, xev->detail, dnd_state);
+
+ goto XI_OTHER;
+ }
+
+ if (xev->evtype == XI_ButtonRelease)
+ {
+ for (int i = 0; i < xev->buttons.mask_len * 8; ++i)
+ {
+ if (i != xev->detail && XIMaskIsSet (xev->buttons.mask, i))
+ dnd_grab = true;
+ }
+
+ if (!dnd_grab)
+ {
+ x_dnd_end_window = x_dnd_last_seen_window;
+ x_dnd_in_progress = false;
+
+ /* If a tooltip that we're following is
+ displayed, hide it now. */
+
+ if (x_dnd_update_tooltip
+ && FRAMEP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && (FRAME_X_DISPLAY (XFRAME (tip_frame))
+ == FRAME_X_DISPLAY (x_dnd_frame)))
+ Fx_hide_tip ();
+
+ /* This doesn't have to be marked since it
+ is only accessed if
+ x_dnd_waiting_for_finish is true, which
+ is only possible inside the DND event
+ loop where that frame is on the
+ stack. */
+ x_dnd_finish_frame = x_dnd_frame;
+
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_window_is_frame)
+ {
+ x_dnd_waiting_for_finish = false;
+ x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window,
+ xev->root_x, xev->root_y, xev->time);
+ }
+ else if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ {
+ x_dnd_pending_finish_target = x_dnd_last_seen_window;
+ x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
+
+ x_dnd_waiting_for_finish
+ = x_dnd_do_drop (x_dnd_last_seen_window,
+ x_dnd_last_protocol_version);
+ x_dnd_finish_display = dpyinfo->display;
+ }
+ else if (x_dnd_last_seen_window != None)
+ {
+ xm_drop_start_message dmsg;
+ xm_drag_receiver_info drag_receiver_info;
+
+ if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
+ &drag_receiver_info)
+ && !x_dnd_disable_motif_protocol
+ && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE
+ && (x_dnd_allow_current_frame
+ || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame)))
+ {
+ if (!x_dnd_motif_setup_p)
+ xm_setup_drag_info (dpyinfo, x_dnd_frame);
+
+ if (x_dnd_motif_setup_p)
+ {
+ memset (&dmsg, 0, sizeof dmsg);
+
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ (!x_dnd_xm_use_help
+ ? XM_DROP_ACTION_DROP
+ : XM_DROP_ACTION_DROP_HELP));
+ dmsg.timestamp = xev->time;
+ dmsg.x = lrint (xev->root_x);
+ dmsg.y = lrint (xev->root_y);
+ /* This atom technically has to be
+ unique to each drag-and-drop
+ operation, but that isn't easy to
+ accomplish, since we cannot
+ randomly move data around between
+ selections. Let's hope no two
+ instances of Emacs try to drag
+ into the same window at the same
+ time. */
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
+
+ if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style))
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (x_dnd_frame),
+ x_dnd_frame, x_dnd_last_seen_window,
+ xev->time);
+
+ xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
+ x_dnd_last_seen_window, &dmsg);
+
+ x_dnd_waiting_for_finish = true;
+ x_dnd_waiting_for_motif_finish_display = dpyinfo;
+ x_dnd_waiting_for_motif_finish = 1;
+ x_dnd_finish_display = dpyinfo->display;
+ }
+ }
+ else
+ x_dnd_send_unsupported_drop (dpyinfo, (x_dnd_last_seen_toplevel != None
+ ? x_dnd_last_seen_toplevel
+ : x_dnd_last_seen_window),
+ xev->root_x, xev->root_y, xev->time);
+ }
+ else if (x_dnd_last_seen_toplevel != None)
+ x_dnd_send_unsupported_drop (dpyinfo,
+ x_dnd_last_seen_toplevel,
+ xev->root_x, xev->root_y,
+ xev->time);
+
+ x_dnd_last_protocol_version = -1;
+ x_dnd_last_motif_style = XM_DRAG_STYLE_NONE;
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_last_window_is_frame = false;
+ x_dnd_frame = NULL;
+
+ goto XI_OTHER;
+ }
+ }
+ }
+
+ if (x_dnd_in_progress
+ && (command_loop_level + minibuf_level
+ <= x_dnd_recursion_depth))
+ goto XI_OTHER;
+
+#ifdef USE_MOTIF
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ struct scroll_bar *bar
+ = x_window_to_scroll_bar (dpyinfo->display,
+ xev->event, 2);
+#endif
+
+ use_copy = true;
+ copy.xbutton.type = (xev->evtype == XI_ButtonPress
+ ? ButtonPress : ButtonRelease);
+ copy.xbutton.serial = xev->serial;
+ copy.xbutton.send_event = xev->send_event;
+ copy.xbutton.display = dpyinfo->display;
+ copy.xbutton.window = xev->event;
+ copy.xbutton.root = xev->root;
+ copy.xbutton.subwindow = xev->child;
+ copy.xbutton.time = xev->time;
+ copy.xbutton.x = lrint (xev->event_x);
+ copy.xbutton.y = lrint (xev->event_y);
+ copy.xbutton.x_root = lrint (xev->root_x);
+ copy.xbutton.y_root = lrint (xev->root_y);
+ copy.xbutton.state = xi_convert_event_state (xev);
+ copy.xbutton.button = xev->detail;
+ copy.xbutton.same_screen = True;
+
+#elif defined USE_GTK && !defined HAVE_GTK3
+ copy = gdk_event_new (xev->evtype == XI_ButtonPress
+ ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
+
+ copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event);
+ copy->button.send_event = xev->send_event;
+ copy->button.time = xev->time;
+ copy->button.x = xev->event_x;
+ copy->button.y = xev->event_y;
+ copy->button.x_root = xev->root_x;
+ copy->button.y_root = xev->root_y;
+ copy->button.state = xi_convert_event_state (xev);
+ copy->button.button = xev->detail;
+
+ if (!copy->button.window)
+ emacs_abort ();
+
+ g_object_ref (copy->button.window);
+
+ if (popup_activated ())
+ {
+ /* GTK+ popup menus don't respond to core buttons
+ after Button3, so don't dismiss popup menus upon
+ wheel movement here either. */
+ if (xev->detail > 3)
+ *finish = X_EVENT_DROP;
+
+ if (xev->evtype == XI_ButtonRelease)
+ goto XI_OTHER;
+ }
+#endif
+
+#ifdef HAVE_XINPUT2_1
/* Ignore emulated scroll events when XI2 native
scroll events are present. */
- if (((dpyinfo->xi2_version == 1
- && xev->detail >= 4
- && xev->detail <= 8)
- || (dpyinfo->xi2_version >= 2))
- && xev->flags & XIPointerEmulated)
+ if (xev->flags & XIPointerEmulated)
{
+#if !defined USE_MOTIF || !defined USE_TOOLKIT_SCROLL_BARS
*finish = X_EVENT_DROP;
+#else
+ if (bar)
+ *finish = X_EVENT_DROP;
+#endif
goto XI_OTHER;
}
#endif
+ if (xev->evtype == XI_ButtonPress)
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
+
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
+
#ifdef HAVE_XWIDGETS
xvw = xwidget_view_from_window (xev->event);
if (xvw)
{
xwidget_button (xvw, xev->evtype == XI_ButtonPress,
lrint (xev->event_x), lrint (xev->event_y),
- xev->detail, xev->mods.effective, xev->time);
+ xev->detail, xi_convert_event_state (xev),
+ xev->time);
if (!EQ (selected_window, xvw->w) && (xev->detail < 4))
{
inev.ie.kind = SELECT_WINDOW_EVENT;
inev.ie.frame_or_window = xvw->w;
+
+ if (source)
+ inev.ie.device = source->name;
}
*finish = X_EVENT_DROP;
@@ -10481,7 +20500,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
device = xi_device_from_id (dpyinfo, xev->deviceid);
- if (!device || !device->master_p)
+ if (!device)
goto XI_OTHER;
bv.button = xev->detail;
@@ -10489,18 +20508,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
bv.x = lrint (xev->event_x);
bv.y = lrint (xev->event_y);
bv.window = xev->event;
- bv.state = xev->mods.effective;
+ bv.state = xi_convert_event_state (xev);
bv.time = xev->time;
- memset (&compose_status, 0, sizeof (compose_status));
dpyinfo->last_mouse_glyph_frame = NULL;
- x_display_set_last_user_time (dpyinfo, xev->time);
f = mouse_or_wdesc_frame (dpyinfo, xev->event);
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
@@ -10521,12 +20538,85 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, event))
+ if (!f)
+ {
+ int real_x = lrint (xev->event_x);
+ int real_y = lrint (xev->event_y);
+ Window child;
+
+ f = x_any_window_to_frame (dpyinfo, xev->event);
+
+ if (xev->detail > 3 && xev->detail < 8 && f)
+ {
+ if (xev->evtype == XI_ButtonRelease)
+ {
+ if (FRAME_X_WINDOW (f) != xev->event)
+ XTranslateCoordinates (dpyinfo->display, xev->event,
+ FRAME_X_WINDOW (f), real_x,
+ real_y, &real_x, &real_y, &child);
+
+ if (xev->detail <= 5)
+ inev.ie.kind = WHEEL_EVENT;
+ else
+ inev.ie.kind = HORIZ_WHEEL_EVENT;
+
+ if (source)
+ inev.ie.device = source->name;
+
+ inev.ie.timestamp = xev->time;
+
+ XSETINT (inev.ie.x, real_x);
+ XSETINT (inev.ie.y, real_y);
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ inev.ie.modifiers
+ |= x_x_to_emacs_modifiers (dpyinfo,
+ xev->mods.effective);
+
+ inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
+ }
+
+ *finish = X_EVENT_DROP;
+ goto XI_OTHER;
+ }
+ else
+ f = NULL;
+ }
+
+ if (f && xg_event_is_for_scrollbar (f, event, false))
f = 0;
#endif
if (f)
{
+ if (xev->detail >= 4 && xev->detail < 8)
+ {
+ if (xev->evtype == XI_ButtonRelease)
+ {
+ if (xev->detail <= 5)
+ inev.ie.kind = WHEEL_EVENT;
+ else
+ inev.ie.kind = HORIZ_WHEEL_EVENT;
+
+ if (source)
+ inev.ie.device = source->name;
+
+ inev.ie.timestamp = xev->time;
+
+ XSETINT (inev.ie.x, lrint (xev->event_x));
+ XSETINT (inev.ie.y, lrint (xev->event_y));
+ XSETFRAME (inev.ie.frame_or_window, f);
+
+ inev.ie.modifiers
+ |= x_x_to_emacs_modifiers (dpyinfo,
+ xev->mods.effective);
+
+ inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
+ }
+
+ goto XI_OTHER;
+ }
+
/* Is this in the tab-bar? */
if (WINDOWP (f->tab_bar_window)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
@@ -10554,12 +20644,22 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int y = bv.y;
window = window_from_coordinates (f, x, y, 0, true, true);
- tool_bar_p = EQ (window, f->tool_bar_window);
+ /* Ignore button release events if the mouse
+ wasn't previously pressed on the tool bar.
+ We do this because otherwise selecting some
+ text with the mouse and then releasing it on
+ the tool bar doesn't stop selecting text,
+ since the tool bar eats the button up
+ event. */
+ tool_bar_p = (EQ (window, f->tool_bar_window)
+ && (xev->evtype != XI_ButtonRelease
+ || f->last_tool_bar_item != -1));
if (tool_bar_p && xev->detail < 4)
- handle_tool_bar_click
+ handle_tool_bar_click_with_device
(f, x, y, xev->evtype == XI_ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, bv.state));
+ x_x_to_emacs_modifiers (dpyinfo, bv.state),
+ source ? source->name : Qt);
}
#endif /* !USE_GTK */
@@ -10589,6 +20689,27 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xembed_send_message (f, xev->time,
XEMBED_REQUEST_FOCUS, 0, 0, 0);
}
+ else
+ {
+ struct scroll_bar *bar
+ = x_window_to_scroll_bar (dpyinfo->display,
+ xev->event, 2);
+
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ if (bar)
+ x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
+ source ? source->name : Qnil);
+#else
+ /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
+ scroll bars. */
+ if (bar && xev->mods.effective & ControlMask)
+ {
+ x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
+ source ? source->name : Qnil);
+ *finish = X_EVENT_DROP;
+ }
+#endif
+ }
if (xev->evtype == XI_ButtonPress)
{
@@ -10609,6 +20730,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
device->grab &= ~(1 << xev->detail);
}
+ if (source && inev.ie.kind != NO_EVENT)
+ inev.ie.device = source->name;
+
if (f)
f->mouse_moved = false;
@@ -10633,6 +20757,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
goto XI_OTHER;
}
+
case XI_KeyPress:
{
int state = xev->mods.effective;
@@ -10644,24 +20769,55 @@ handle_one_xevent (struct x_display_info *dpyinfo,
KeySym keysym;
char copy_buffer[81];
char *copy_bufptr = copy_buffer;
- unsigned char *copy_ubufptr;
int copy_bufsiz = sizeof (copy_buffer);
ptrdiff_t i;
- int nchars, len;
- struct xi_device_t *device;
+ uint old_state;
+ struct xi_device_t *device, *source;
+
+ coding = Qlatin_1;
device = xi_device_from_id (dpyinfo, xev->deviceid);
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
- if (!device || !device->master_p)
+ if (!device)
goto XI_OTHER;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Dispatch XI_KeyPress events when in menu. */
if (popup_activated ())
- goto XI_OTHER;
+ {
+#ifdef USE_LUCID
+ /* This makes key navigation work inside menus. */
+ use_copy = true;
+ copy.xkey.type = KeyPress;
+ copy.xkey.serial = xev->serial;
+ copy.xkey.send_event = xev->send_event;
+ copy.xkey.display = dpyinfo->display;
+ copy.xkey.window = xev->event;
+ copy.xkey.root = xev->root;
+ copy.xkey.subwindow = xev->child;
+ copy.xkey.time = xev->time;
+ copy.xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14))
+ | (xev->group.effective << 13));
+ xi_convert_button_state (&xev->buttons, &copy.xkey.state);
+
+ copy.xkey.x = lrint (xev->event_x);
+ copy.xkey.y = lrint (xev->event_y);
+ copy.xkey.x_root = lrint (xev->root_x);
+ copy.xkey.y_root = lrint (xev->root_y);
+ copy.xkey.keycode = xev->detail;
+ copy.xkey.same_screen = True;
+#endif
+ goto XI_OTHER;
+ }
#endif
-#ifdef HAVE_X_I18N
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
+ ignore_next_mouse_click_timeout = 0;
+
+ f = x_any_window_to_frame (dpyinfo, xev->event);
+
XKeyPressedEvent xkey;
memset (&xkey, 0, sizeof xkey);
@@ -10669,23 +20825,94 @@ 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;
xkey.time = xev->time;
xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14))
| (xev->group.effective << 13));
+
+ xkey.x = lrint (xev->event_x);
+ xkey.y = lrint (xev->event_y);
+ xkey.x_root = lrint (xev->root_x);
+ xkey.y_root = lrint (xev->root_y);
+
+ /* Some input methods react differently depending on the
+ buttons that are pressed. */
+ xi_convert_button_state (&xev->buttons, &xkey.state);
+
xkey.keycode = xev->detail;
xkey.same_screen = True;
+#ifdef HAVE_X_I18N
+#ifdef USE_GTK
+ if ((!x_gtk_use_native_input
+ && x_filter_event (dpyinfo, (XEvent *) &xkey))
+ || (x_gtk_use_native_input
+ && x_filter_event (dpyinfo, event)))
+ {
+ /* Try to attribute core key events from the input
+ method to the input extension event that caused
+ them. */
+ dpyinfo->pending_keystroke_time = xev->time;
+ dpyinfo->pending_keystroke_source = xev->sourceid;
+
+ *finish = X_EVENT_DROP;
+ goto XI_OTHER;
+ }
+#else
if (x_filter_event (dpyinfo, (XEvent *) &xkey))
{
+ /* Try to attribute core key events from the input
+ method to the input extension event that caused
+ them. */
+ dpyinfo->pending_keystroke_time = xev->time;
+ dpyinfo->pending_keystroke_source = xev->sourceid;
+
+ *finish = X_EVENT_DROP;
+ goto XI_OTHER;
+ }
+#endif
+#elif USE_GTK
+ if ((x_gtk_use_native_input
+ || dpyinfo->prefer_native_input)
+ && xg_filter_key (any, event))
+ {
+ /* Try to attribute core key events from the input
+ method to the input extension event that caused
+ them. */
+ dpyinfo->pending_keystroke_time = xev->time;
+ dpyinfo->pending_keystroke_source = xev->sourceid;
+
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
#endif
+ state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
+
+#ifdef HAVE_XKB
+ if (dpyinfo->xkb_desc)
+ {
+ XkbDescRec *rec = dpyinfo->xkb_desc;
+
+ if (rec->map->modmap && rec->map->modmap[xev->detail])
+ goto xi_done_keysym;
+ }
+ else
+#endif
+ {
+ if (dpyinfo->modmap)
+ {
+ for (i = 0; i < 8 * dpyinfo->modmap->max_keypermod; i++)
+ {
+ if (xev->detail == dpyinfo->modmap->modifiermap[i])
+ goto xi_done_keysym;
+ }
+ }
+ }
+
#ifdef HAVE_XKB
if (dpyinfo->xkb_desc)
{
@@ -10716,11 +20943,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (keysym == NoSymbol)
goto XI_OTHER;
- x_display_set_last_user_time (dpyinfo, xev->time);
- ignore_next_mouse_click_timeout = 0;
-
- f = x_any_window_to_frame (dpyinfo, xev->event);
-
/* If mouse-highlight is an integer, input clears out
mouse highlighting. */
if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
@@ -10744,16 +20966,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
(see above). */
*finish = X_EVENT_DROP;
#endif
- /* If not using XIM/XIC, and a compose sequence is in progress,
- we break here. Otherwise, chars_matched is always 0. */
- if (compose_status.chars_matched > 0 && nbytes == 0)
- goto XI_OTHER;
-
- memset (&compose_status, 0, sizeof (compose_status));
XSETFRAME (inev.ie.frame_or_window, f);
- inev.ie.modifiers
- = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), state);
inev.ie.timestamp = xev->time;
#ifdef HAVE_X_I18N
@@ -10764,11 +20978,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&status_return);
+ coding = Qnil;
if (status_return == XBufferOverflow)
{
copy_bufsiz = nbytes + 1;
- copy_bufptr = alloca (copy_bufsiz);
+ copy_bufptr = SAFE_ALLOCA (copy_bufsiz);
nbytes = XmbLookupString (FRAME_XIC (f),
&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
@@ -10800,8 +21015,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
copy_bufsiz, &overflow);
if (overflow)
{
- copy_bufptr = alloca ((copy_bufsiz += overflow)
- * sizeof *copy_bufptr);
+ copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
+ * sizeof *copy_bufptr);
overflow = 0;
nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
state & ~mods_rtrn, copy_bufptr,
@@ -10810,16 +21025,37 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (overflow)
nbytes = 0;
}
+
+ coding = Qnil;
}
else
#endif
{
+ old_state = xkey.state;
+ xkey.state &= ~ControlMask;
+ xkey.state &= ~(dpyinfo->meta_mod_mask
+ | dpyinfo->super_mod_mask
+ | dpyinfo->hyper_mod_mask
+ | dpyinfo->alt_mod_mask);
+
nbytes = XLookupString (&xkey, copy_bufptr,
copy_bufsiz, &keysym,
- &compose_status);
+ NULL);
+
+ xkey.state = old_state;
}
}
+ inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
+
+#ifdef XK_F1
+ if (x_dnd_in_progress && keysym == XK_F1)
+ {
+ x_dnd_xm_use_help = true;
+ goto xi_done_keysym;
+ }
+#endif
+
/* First deal with keysyms which have defined
translations to characters. */
if (keysym >= 32 && keysym < 128)
@@ -10828,6 +21064,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
inev.ie.kind = ASCII_KEYSTROKE_EVENT;
inev.ie.code = keysym;
+ if (source)
+ inev.ie.device = source->name;
+
goto xi_done_keysym;
}
@@ -10838,6 +21077,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
inev.ie.kind = ASCII_KEYSTROKE_EVENT;
else
inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+
+ if (source)
+ inev.ie.device = source->name;
+
inev.ie.code = keysym & 0xFFFFFF;
goto xi_done_keysym;
}
@@ -10853,6 +21096,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = XFIXNAT (c);
+
+ if (source)
+ inev.ie.device = source->name;
+
goto xi_done_keysym;
}
@@ -10911,6 +21158,30 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef XK_dead_abovedot
|| keysym == XK_dead_abovedot
#endif
+#ifdef XK_dead_abovering
+ || keysym == XK_dead_abovering
+#endif
+#ifdef XK_dead_belowdot
+ || keysym == XK_dead_belowdot
+#endif
+#ifdef XK_dead_voiced_sound
+ || keysym == XK_dead_voiced_sound
+#endif
+#ifdef XK_dead_semivoiced_sound
+ || keysym == XK_dead_semivoiced_sound
+#endif
+#ifdef XK_dead_hook
+ || keysym == XK_dead_hook
+#endif
+#ifdef XK_dead_horn
+ || keysym == XK_dead_horn
+#endif
+#ifdef XK_dead_stroke
+ || keysym == XK_dead_stroke
+#endif
+#ifdef XK_dead_abovecomma
+ || keysym == XK_dead_abovecomma
+#endif
|| IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
|| IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
/* Any "vendor-specific" key is ok. */
@@ -10933,100 +21204,395 @@ handle_one_xevent (struct x_display_info *dpyinfo,
key. */
inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
inev.ie.code = keysym;
+
+ if (source)
+ inev.ie.device = source->name;
+
goto xi_done_keysym;
}
- for (i = 0, nchars = 0; i < nbytes; i++)
+ for (i = 0; i < nbytes; i++)
{
- if (ASCII_CHAR_P (copy_bufptr[i]))
- nchars++;
STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
}
- if (nchars < nbytes)
+ if (nbytes)
{
- /* Decode the input data. */
-
- setup_coding_system (Vlocale_coding_system, &coding);
- coding.src_multibyte = false;
- coding.dst_multibyte = true;
- /* The input is converted to events, thus we can't
- handle composition. Anyway, there's no XIM that
- gives us composition information. */
- coding.common_flags &= ~CODING_ANNOTATION_MASK;
-
- SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
- nbytes);
- coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding_c_string (&coding, (unsigned char *) copy_bufptr,
- nbytes, Qnil);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = (char *) coding.destination;
- }
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
- copy_ubufptr = (unsigned char *) copy_bufptr;
+ Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
+ Qcoding, coding, inev.ie.arg);
- /* Convert the input data to a sequence of
- character events. */
- for (i = 0; i < nbytes; i += len)
- {
- int ch;
- if (nchars == nbytes)
- ch = copy_ubufptr[i], len = 1;
- else
- ch = string_char_and_length (copy_ubufptr + i, &len);
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = ch;
- kbd_buffer_store_buffered_event (&inev, hold_quit);
+ if (source)
+ inev.ie.device = source->name;
}
-
- inev.ie.kind = NO_EVENT;
goto xi_done_keysym;
}
+
goto XI_OTHER;
}
+
+#if defined USE_GTK && !defined HAVE_GTK3
+ case XI_RawKeyPress:
+ {
+ XIRawEvent *raw_event = (XIRawEvent *) xi_event;
+
+ /* This is the only way to attribute core keyboard
+ events generated on GTK+ 2.x to the extension device
+ that generated them. */
+ dpyinfo->pending_keystroke_time = raw_event->time;
+ dpyinfo->pending_keystroke_source = raw_event->sourceid;
+ dpyinfo->pending_keystroke_time_special_p = true;
+ goto XI_OTHER;
+ }
+#endif
+
case XI_KeyRelease:
- x_display_set_last_user_time (dpyinfo, xev->time);
-#ifdef HAVE_X_I18N
- XKeyPressedEvent xkey;
+#if defined HAVE_X_I18N || defined USE_GTK || defined USE_LUCID
+ {
+ XKeyPressedEvent xkey;
+
+ memset (&xkey, 0, sizeof xkey);
+
+ xkey.type = KeyRelease;
+ xkey.serial = xev->serial;
+ xkey.send_event = xev->send_event;
+ xkey.display = dpyinfo->display;
+ xkey.window = xev->event;
+ xkey.root = xev->root;
+ xkey.subwindow = xev->child;
+ xkey.time = xev->time;
+ xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14))
+ | (xev->group.effective << 13));
+ xkey.x = lrint (xev->event_x);
+ xkey.y = lrint (xev->event_y);
+ xkey.x_root = lrint (xev->root_x);
+ xkey.y_root = lrint (xev->root_y);
- memset (&xkey, 0, sizeof xkey);
+ /* Some input methods react differently depending on the
+ buttons that are pressed. */
+ xi_convert_button_state (&xev->buttons, &xkey.state);
- xkey.type = KeyRelease;
- xkey.serial = xev->serial;
- xkey.send_event = xev->send_event;
- xkey.display = xev->display;
- xkey.window = xev->event;
- xkey.root = xev->root;
- xkey.subwindow = xev->child;
- xkey.time = xev->time;
- xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14))
- | (xev->group.effective << 13));
- xkey.keycode = xev->detail;
- xkey.same_screen = True;
+ xkey.keycode = xev->detail;
+ xkey.same_screen = True;
- x_filter_event (dpyinfo, (XEvent *) &xkey);
+#ifdef USE_LUCID
+ if (!popup_activated ())
+ {
#endif
+#ifdef HAVE_X_I18N
+ if (x_filter_event (dpyinfo, (XEvent *) &xkey))
+ *finish = X_EVENT_DROP;
+#elif defined USE_GTK
+ f = x_any_window_to_frame (xkey->event);
+
+ if (f && xg_filter_key (f, event))
+ *finish = X_EVENT_DROP;
+#endif
+#ifdef USE_LUCID
+ }
+ else
+ {
+ /* FIXME: the Lucid menu bar pops down upon any key
+ release event, so we don't dispatch these events
+ at all, which doesn't seem to be the right
+ solution.
+
+ use_copy = true;
+ copy.xkey = xkey; */
+ }
+#endif
+ }
+#endif
+
goto XI_OTHER;
+
case XI_PropertyEvent:
+ goto XI_OTHER;
+
case XI_HierarchyChanged:
+ {
+ XIHierarchyEvent *hev = (XIHierarchyEvent *) xi_event;
+ XIDeviceInfo *info;
+ int i, j, ndevices, n_disabled, *disabled;
+ struct xi_device_t *device, *devices;
+#ifdef HAVE_XINPUT2_2
+ struct xi_touch_point_t *tem, *last;
+#endif
+
+ disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
+ n_disabled = 0;
+
+ for (i = 0; i < hev->num_info; ++i)
+ {
+ if (hev->info[i].flags & XIDeviceEnabled)
+ {
+ /* Handle all disabled devices now, to prevent
+ things happening out-of-order later. */
+ if (n_disabled)
+ {
+ ndevices = 0;
+ devices = xmalloc (sizeof *devices * dpyinfo->num_devices);
+
+ for (i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ for (j = 0; j < n_disabled; ++j)
+ {
+ if (disabled[j] == dpyinfo->devices[i].device_id)
+ {
+#ifdef HAVE_XINPUT2_1
+ xfree (dpyinfo->devices[i].valuators);
+#endif
+#ifdef HAVE_XINPUT2_2
+ tem = dpyinfo->devices[i].touchpoints;
+ while (tem)
+ {
+ last = tem;
+ tem = tem->next;
+ xfree (last);
+ }
+#endif
+ goto continue_detachment;
+ }
+ }
+
+ devices[ndevices++] = dpyinfo->devices[i];
+
+ continue_detachment:
+ continue;
+ }
+
+ xfree (dpyinfo->devices);
+ dpyinfo->devices = devices;
+ dpyinfo->num_devices = ndevices;
+
+ n_disabled = 0;
+ }
+
+ x_catch_errors (dpyinfo->display);
+ info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
+ &ndevices);
+ x_uncatch_errors ();
+
+ if (info && info->enabled)
+ {
+ dpyinfo->devices
+ = xrealloc (dpyinfo->devices, (sizeof *dpyinfo->devices
+ * ++dpyinfo->num_devices));
+ device = &dpyinfo->devices[dpyinfo->num_devices - 1];
+ xi_populate_device_from_info (device, info);
+ }
+
+ if (info)
+ XIFreeDeviceInfo (info);
+ }
+ else if (hev->info[i].flags & XIDeviceDisabled)
+ disabled[n_disabled++] = hev->info[i].deviceid;
+ else if (hev->info[i].flags & XISlaveDetached
+ || hev->info[i].flags & XISlaveAttached)
+ {
+ device = xi_device_from_id (dpyinfo, hev->info[i].deviceid);
+ x_catch_errors (dpyinfo->display);
+ info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
+ &ndevices);
+ x_uncatch_errors ();
+
+ if (info)
+ {
+ if (device && info->enabled)
+ device->use = info->use;
+ else if (device)
+ disabled[n_disabled++] = hev->info[i].deviceid;
+
+ XIFreeDeviceInfo (info);
+ }
+ }
+ }
+
+ if (n_disabled)
+ {
+ ndevices = 0;
+ devices = xmalloc (sizeof *devices * dpyinfo->num_devices);
+
+ for (i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ for (j = 0; j < n_disabled; ++j)
+ {
+ if (disabled[j] == dpyinfo->devices[i].device_id)
+ {
+#ifdef HAVE_XINPUT2_1
+ xfree (dpyinfo->devices[i].valuators);
+#endif
+#ifdef HAVE_XINPUT2_2
+ tem = dpyinfo->devices[i].touchpoints;
+ while (tem)
+ {
+ last = tem;
+ tem = tem->next;
+ xfree (last);
+ }
+#endif
+ goto break_detachment;
+ }
+ }
+
+ devices[ndevices++] = dpyinfo->devices[i];
+
+ break_detachment:
+ continue;
+ }
+
+ xfree (dpyinfo->devices);
+ dpyinfo->devices = devices;
+ dpyinfo->num_devices = ndevices;
+ }
+
+ goto XI_OTHER;
+ }
+
case XI_DeviceChanged:
- x_init_master_valuators (dpyinfo);
- goto XI_OTHER;
-#ifdef XI_TouchBegin
- case XI_TouchBegin:
{
+ XIDeviceChangedEvent *device_changed = (XIDeviceChangedEvent *) xi_event;
struct xi_device_t *device;
+#ifdef HAVE_XINPUT2_2
+ struct xi_touch_point_t *tem, *last;
+#endif
+ int c;
+#ifdef HAVE_XINPUT2_1
+ int i;
+#endif
+
+ device = xi_device_from_id (dpyinfo, device_changed->deviceid);
+
+ if (!device)
+ {
+ /* An existing device might have been enabled. */
+ x_init_master_valuators (dpyinfo);
+
+ /* Now try to find the device again, in case it was
+ just enabled. */
+ device = xi_device_from_id (dpyinfo, device_changed->deviceid);
+ }
+
+ /* If it wasn't enabled, then stop handling this event. */
+ if (!device)
+ goto XI_OTHER;
+
+ /* Free data that we will regenerate from new
+ information. */
+#ifdef HAVE_XINPUT2_1
+ device->valuators = xrealloc (device->valuators,
+ (device_changed->num_classes
+ * sizeof *device->valuators));
+ device->scroll_valuator_count = 0;
+#endif
+#ifdef HAVE_XINPUT2_2
+ device->direct_p = false;
+#endif
+
+ for (c = 0; c < device_changed->num_classes; ++c)
+ {
+ switch (device_changed->classes[c]->type)
+ {
+#ifdef HAVE_XINPUT2_1
+ case XIScrollClass:
+ {
+ XIScrollClassInfo *info;
+
+ info = (XIScrollClassInfo *) device_changed->classes[c];
+ struct xi_scroll_valuator_t *valuator;
+
+ valuator = &device->valuators[device->scroll_valuator_count++];
+ valuator->horizontal
+ = (info->scroll_type == XIScrollTypeHorizontal);
+ valuator->invalid_p = true;
+ valuator->emacs_value = DBL_MIN;
+ valuator->increment = info->increment;
+ valuator->number = info->number;
+
+ break;
+ }
+#endif
+
+#ifdef HAVE_XINPUT2_2
+ case XITouchClass:
+ {
+ XITouchClassInfo *info;
+
+ info = (XITouchClassInfo *) device_changed->classes[c];
+ device->direct_p = info->mode == XIDirectTouch;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+
+#ifdef HAVE_XINPUT2_1
+ for (c = 0; c < device_changed->num_classes; ++c)
+ {
+ if (device_changed->classes[c]->type == XIValuatorClass)
+ {
+ XIValuatorClassInfo *info;
+
+ info = (XIValuatorClassInfo *) device_changed->classes[c];
+
+ for (i = 0; i < device->scroll_valuator_count; ++i)
+ {
+ if (device->valuators[i].number == info->number)
+ {
+ device->valuators[i].invalid_p = false;
+ device->valuators[i].current_value = info->value;
+
+ /* Make sure that this is reset if the
+ pointer moves into a window of ours.
+
+ Otherwise the valuator state could be
+ left invalid if the DeviceChange
+ event happened with the pointer
+ outside any Emacs frame. */
+ device->valuators[i].pending_enter_reset = true;
+ }
+ }
+ }
+ }
+#endif
+
+#ifdef HAVE_XINPUT2_2
+ /* The device is no longer a DirectTouch device, so
+ remove any touchpoints that we might have
+ recorded. */
+ if (!device->direct_p)
+ {
+ tem = device->touchpoints;
+
+ while (tem)
+ {
+ last = tem;
+ tem = tem->next;
+ xfree (last);
+ }
+
+ device->touchpoints = NULL;
+ }
+#endif
+
+ goto XI_OTHER;
+ }
+
+#ifdef HAVE_XINPUT2_2
+ case XI_TouchBegin:
+ {
+ struct xi_device_t *device, *source;
bool menu_bar_p = false, tool_bar_p = false;
#ifdef HAVE_GTK3
GdkRectangle test_rect;
#endif
device = xi_device_from_id (dpyinfo, xev->deviceid);
- x_display_set_last_user_time (dpyinfo, xev->time);
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
if (!device)
goto XI_OTHER;
@@ -11041,8 +21607,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
&& xg_event_is_for_menubar (f, event));
if (f && FRAME_X_OUTPUT (f)->toolbar_widget)
{
- test_rect.x = xev->event_x;
- test_rect.y = xev->event_y;
+ int scale = xg_get_scale (f);
+
+ test_rect.x = xev->event_x / scale;
+ test_rect.y = xev->event_y / scale;
test_rect.width = 1;
test_rect.height = 1;
@@ -11056,9 +21624,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (f && device->direct_p)
{
*finish = X_EVENT_DROP;
+
x_catch_errors (dpyinfo->display);
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event, XIAcceptTouch);
+
+ if (x_input_grab_touch_events)
+ XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+ xev->detail, xev->event, XIAcceptTouch);
+
if (!x_had_errors_p (dpyinfo->display))
{
xi_link_touch_point (device, xev->detail, xev->event_x,
@@ -11070,16 +21642,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XSETINT (inev.ie.x, lrint (xev->event_x));
XSETINT (inev.ie.y, lrint (xev->event_y));
XSETINT (inev.ie.arg, xev->detail);
+
+ if (source)
+ inev.ie.device = source->name;
}
- x_uncatch_errors_after_check ();
+
+ x_uncatch_errors ();
}
#ifndef HAVE_GTK3
- else
+ else if (x_input_grab_touch_events)
{
- x_catch_errors (dpyinfo->display);
+ x_ignore_errors_for_next_request (dpyinfo);
XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
xev->detail, xev->event, XIRejectTouch);
- x_uncatch_errors ();
+ x_stop_ignoring_errors (dpyinfo);
}
#endif
}
@@ -11099,14 +21675,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto XI_OTHER;
}
+
case XI_TouchUpdate:
{
- struct xi_device_t *device;
+ struct xi_device_t *device, *source;
struct xi_touch_point_t *touchpoint;
Lisp_Object arg = Qnil;
device = xi_device_from_id (dpyinfo, xev->deviceid);
- x_display_set_last_user_time (dpyinfo, xev->time);
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
if (!device)
goto XI_OTHER;
@@ -11136,18 +21715,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
arg);
}
+ if (source)
+ inev.ie.device = source->name;
+
inev.ie.arg = arg;
}
goto XI_OTHER;
}
+
case XI_TouchEnd:
{
- struct xi_device_t *device;
+ struct xi_device_t *device, *source;
bool unlinked_p;
device = xi_device_from_id (dpyinfo, xev->deviceid);
- x_display_set_last_user_time (dpyinfo, xev->time);
+ source = xi_device_from_id (dpyinfo, xev->sourceid);
+ x_display_set_last_user_time (dpyinfo, xev->time,
+ xev->send_event);
if (!device)
goto XI_OTHER;
@@ -11162,27 +21747,35 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
inev.ie.kind = TOUCHSCREEN_END_EVENT;
inev.ie.timestamp = xev->time;
+
XSETFRAME (inev.ie.frame_or_window, f);
XSETINT (inev.ie.x, lrint (xev->event_x));
XSETINT (inev.ie.y, lrint (xev->event_y));
XSETINT (inev.ie.arg, xev->detail);
+
+ if (source)
+ inev.ie.device = source->name;
}
}
goto XI_OTHER;
}
+
#endif
-#ifdef XI_GesturePinchBegin
+
+#ifdef HAVE_XINPUT2_4
case XI_GesturePinchBegin:
case XI_GesturePinchUpdate:
{
- x_display_set_last_user_time (dpyinfo, xi_event->time);
-
-#ifdef HAVE_USABLE_XI_GESTURE_PINCH_EVENT
XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
- struct xi_device_t *device = xi_device_from_id (dpyinfo, pev->deviceid);
+ struct xi_device_t *device, *source;
+
+ device = xi_device_from_id (dpyinfo, pev->deviceid);
+ source = xi_device_from_id (dpyinfo, pev->sourceid);
+ x_display_set_last_user_time (dpyinfo, pev->time,
+ pev->send_event);
- if (!device || !device->master_p)
+ if (!device)
goto XI_OTHER;
#ifdef HAVE_XWIDGETS
@@ -11196,7 +21789,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
- any = x_any_window_to_frame (dpyinfo, pev->event);
+ any = x_window_to_frame (dpyinfo, pev->event);
if (any)
{
inev.ie.kind = PINCH_EVENT;
@@ -11209,18 +21802,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
make_float (pev->delta_y),
make_float (pev->scale),
make_float (pev->delta_angle));
+
+ if (source)
+ inev.ie.device = source->name;
}
-#endif
+
/* Once again GTK seems to crash when confronted by
events it doesn't understand. */
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
+
case XI_GesturePinchEnd:
{
- x_display_set_last_user_time (dpyinfo, xi_event->time);
-
-#if defined HAVE_XWIDGETS && HAVE_USABLE_XI_GESTURE_PINCH_EVENT
+#if defined HAVE_XWIDGETS
XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
struct xwidget_view *xvw = xwidget_view_from_window (pev->event);
@@ -11234,14 +21829,22 @@ handle_one_xevent (struct x_display_info *dpyinfo,
default:
goto XI_OTHER;
}
+
xi_done_keysym:
#ifdef HAVE_X_I18N
- if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
- xic_set_statusarea (f);
+ if (f)
+ {
+ struct window *w = XWINDOW (f->selected_window);
+ xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
+
+ if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+ xic_set_statusarea (f);
+ }
#endif
if (must_free_data)
XFreeEventData (dpyinfo->display, &event->xcookie);
goto done_keysym;
+
XI_OTHER:
if (must_free_data)
XFreeEventData (dpyinfo->display, &event->xcookie);
@@ -11251,7 +21854,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
default:
#ifdef HAVE_XKB
- if (event->type == dpyinfo->xkb_event_type)
+ if (dpyinfo->supports_xkb
+ && event->type == dpyinfo->xkb_event_type)
{
XkbEvent *xkbevent = (XkbEvent *) event;
@@ -11276,19 +21880,348 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
dpyinfo->xkb_desc = NULL;
}
+ }
+ else
+ {
+ dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display,
+ (XkbKeySymsMask
+ | XkbKeyTypesMask
+ | XkbModifierMapMask
+ | XkbVirtualModsMask),
+ XkbUseCoreKbd);
+
+ if (dpyinfo->xkb_desc)
+ XkbGetNames (dpyinfo->display,
+ XkbGroupNamesMask | XkbVirtualModNamesMask,
+ dpyinfo->xkb_desc);
+ }
- x_find_modifier_meanings (dpyinfo);
+ XkbRefreshKeyboardMapping (&xkbevent->map);
+ x_find_modifier_meanings (dpyinfo);
+ }
+ else if (x_dnd_in_progress
+ && xkbevent->any.xkb_type == XkbStateNotify)
+ x_dnd_keyboard_state = (xkbevent->state.mods
+ | xkbevent->state.ptr_buttons);
+ }
+#endif
+#ifdef HAVE_XSHAPE
+ if (dpyinfo->xshape_supported_p
+ && event->type == dpyinfo->xshape_event_base + ShapeNotify
+ && x_dnd_in_progress && x_dnd_use_toplevels
+ && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
+ {
+#ifndef USE_GTK
+ XEvent xevent;
+#endif
+ XShapeEvent *xse = (XShapeEvent *) event;
+#if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
+ xcb_shape_get_rectangles_cookie_t bounding_rect_cookie;
+ xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
+ xcb_rectangle_iterator_t bounding_rect_iterator;
+
+ xcb_shape_get_rectangles_cookie_t input_rect_cookie;
+ xcb_shape_get_rectangles_reply_t *input_rect_reply;
+ xcb_rectangle_iterator_t input_rect_iterator;
+
+ xcb_generic_error_t *error;
+#else
+ XRectangle *rects;
+ int rc, ordering;
+#endif
+
+ /* Somehow this really interferes with GTK's own processing
+ of ShapeNotify events. Not sure what GTK uses them for,
+ but we cannot skip any of them here. */
+#ifndef USE_GTK
+ while (XPending (dpyinfo->display))
+ {
+ XNextEvent (dpyinfo->display, &xevent);
+
+ if (xevent.type == dpyinfo->xshape_event_base + ShapeNotify
+ && ((XShapeEvent *) &xevent)->window == xse->window)
+ xse = (XShapeEvent *) &xevent;
+ else
+ {
+ XPutBackEvent (dpyinfo->display, &xevent);
+ break;
}
}
+#endif
+
+ for (struct x_client_list_window *tem = x_dnd_toplevels; tem;
+ tem = tem->next)
+ {
+ if (tem->window == xse->window)
+ {
+ if (tem->n_input_rects != -1)
+ xfree (tem->input_rects);
+ if (tem->n_bounding_rects != -1)
+ xfree (tem->bounding_rects);
+
+ tem->n_input_rects = -1;
+ tem->n_bounding_rects = -1;
+
+#if defined HAVE_XCB_SHAPE && defined HAVE_XCB_SHAPE_INPUT_RECTS
+ bounding_rect_cookie = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+ (xcb_window_t) xse->window,
+ XCB_SHAPE_SK_BOUNDING);
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ input_rect_cookie
+ = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+ (xcb_window_t) xse->window,
+ XCB_SHAPE_SK_INPUT);
+
+ bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ bounding_rect_cookie,
+ &error);
+
+ if (bounding_rect_reply)
+ {
+ bounding_rect_iterator
+ = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
+ tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
+ tem->bounding_rects = xmalloc (tem->n_bounding_rects
+ * sizeof *tem->bounding_rects);
+ tem->n_bounding_rects = 0;
+
+ for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
+ {
+ tem->bounding_rects[tem->n_bounding_rects].x
+ = bounding_rect_iterator.data->x;
+ tem->bounding_rects[tem->n_bounding_rects].y
+ = bounding_rect_iterator.data->y;
+ tem->bounding_rects[tem->n_bounding_rects].width
+ = bounding_rect_iterator.data->width;
+ tem->bounding_rects[tem->n_bounding_rects].height
+ = bounding_rect_iterator.data->height;
+
+ tem->n_bounding_rects++;
+ }
+
+ free (bounding_rect_reply);
+ }
+ else
+ free (error);
+
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ {
+ input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+ input_rect_cookie, &error);
+
+ if (input_rect_reply)
+ {
+ input_rect_iterator
+ = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
+ tem->n_input_rects = input_rect_iterator.rem + 1;
+ tem->input_rects = xmalloc (tem->n_input_rects
+ * sizeof *tem->input_rects);
+ tem->n_input_rects = 0;
+
+ for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
+ {
+ tem->input_rects[tem->n_input_rects].x
+ = input_rect_iterator.data->x;
+ tem->input_rects[tem->n_input_rects].y
+ = input_rect_iterator.data->y;
+ tem->input_rects[tem->n_input_rects].width
+ = input_rect_iterator.data->width;
+ tem->input_rects[tem->n_input_rects].height
+ = input_rect_iterator.data->height;
+
+ tem->n_input_rects++;
+ }
+
+ free (input_rect_reply);
+ }
+ else
+ free (error);
+ }
+#else
+ x_catch_errors (dpyinfo->display);
+ rects = XShapeGetRectangles (dpyinfo->display,
+ xse->window,
+ ShapeBounding,
+ &count, &ordering);
+ rc = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ /* Does XShapeGetRectangles allocate anything upon an
+ error? */
+ if (!rc)
+ {
+ tem->n_bounding_rects = count;
+ tem->bounding_rects
+ = xmalloc (sizeof *tem->bounding_rects * count);
+ memcpy (tem->bounding_rects, rects,
+ sizeof *tem->bounding_rects * count);
+
+ XFree (rects);
+ }
+
+#ifdef ShapeInput
+ if (dpyinfo->xshape_major > 1
+ || (dpyinfo->xshape_major == 1
+ && dpyinfo->xshape_minor >= 1))
+ {
+ x_catch_errors (dpyinfo->display);
+ rects = XShapeGetRectangles (dpyinfo->display,
+ xse->window, ShapeInput,
+ &count, &ordering);
+ rc = x_had_errors_p (dpyinfo->display);
+ x_uncatch_errors_after_check ();
+
+ /* Does XShapeGetRectangles allocate anything upon
+ an error? */
+ if (!rc)
+ {
+ tem->n_input_rects = count;
+ tem->input_rects
+ = xmalloc (sizeof *tem->input_rects * count);
+ memcpy (tem->input_rects, rects,
+ sizeof *tem->input_rects * count);
+
+ XFree (rects);
+ }
+ }
+#endif
+#endif
+
+ /* Handle the common case where the input shape equals the
+ bounding shape. */
+
+ if (tem->n_input_rects != -1
+ && tem->n_bounding_rects == tem->n_input_rects
+ && !memcmp (tem->bounding_rects, tem->input_rects,
+ tem->n_input_rects * sizeof *tem->input_rects))
+ {
+ xfree (tem->input_rects);
+ tem->n_input_rects = -1;
+ }
+
+ /* And the common case where there is no input rect and the
+ bounding rect equals the window dimensions. */
+
+ if (tem->n_input_rects == -1
+ && tem->n_bounding_rects == 1
+ && tem->bounding_rects[0].width == tem->width
+ && tem->bounding_rects[0].height == tem->height
+ && tem->bounding_rects[0].x == -tem->border_width
+ && tem->bounding_rects[0].y == -tem->border_width)
+ {
+ xfree (tem->bounding_rects);
+ tem->n_bounding_rects = -1;
+ }
+
+ break;
+ }
+ }
+ }
+#endif
+#if defined HAVE_XRANDR && !defined USE_GTK
+ if (dpyinfo->xrandr_supported_p
+ && (event->type == (dpyinfo->xrandr_event_base
+ + RRScreenChangeNotify)
+ || event->type == (dpyinfo->xrandr_event_base
+ + RRNotify)))
+ {
+ union buffered_input_event *ev;
+ Time timestamp;
+ Lisp_Object current_monitors;
+ XRRScreenChangeNotifyEvent *notify;
+
+ if (event->type == (dpyinfo->xrandr_event_base
+ + RRScreenChangeNotify))
+ XRRUpdateConfiguration ((XEvent *) event);
+
+ if (event->type == (dpyinfo->xrandr_event_base
+ + RRScreenChangeNotify))
+ {
+ notify = ((XRRScreenChangeNotifyEvent *) event);
+ timestamp = notify->timestamp;
+
+ /* Don't set screen dimensions if the notification is
+ for a different screen. */
+ if (notify->root == dpyinfo->root_window)
+ {
+ dpyinfo->screen_width = notify->width;
+ dpyinfo->screen_height = notify->height;
+ dpyinfo->screen_mm_width = notify->mwidth;
+ dpyinfo->screen_mm_height = notify->mheight;
+ }
+ }
+ else
+ timestamp = 0;
+
+ ev = (kbd_store_ptr == kbd_buffer
+ ? kbd_buffer + KBD_BUFFER_SIZE - 1
+ : kbd_store_ptr - 1);
+
+ if (kbd_store_ptr != kbd_fetch_ptr
+ && ev->ie.kind == MONITORS_CHANGED_EVENT
+ && XTERMINAL (ev->ie.arg) == dpyinfo->terminal)
+ /* Don't store a MONITORS_CHANGED_EVENT if there is
+ already an undelivered event on the queue. */
+ goto OTHER;
+
+ inev.ie.kind = MONITORS_CHANGED_EVENT;
+ inev.ie.timestamp = timestamp;
+ XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
+
+ /* Also don't do anything if the monitor configuration
+ didn't really change. */
+
+ current_monitors
+ = Fx_display_monitor_attributes_list (inev.ie.arg);
+
+ if (!NILP (Fequal (current_monitors,
+ dpyinfo->last_monitor_attributes_list)))
+ inev.ie.kind = NO_EVENT;
+
+ dpyinfo->last_monitor_attributes_list = current_monitors;
+
+ if (x_dnd_in_progress && x_dnd_update_tooltip)
+ x_dnd_monitors = current_monitors;
+
+ if (inev.ie.kind != NO_EVENT)
+ x_dnd_update_tooltip_now ();
}
#endif
OTHER:
#ifdef USE_X_TOOLKIT
block_input ();
- if (*finish != X_EVENT_DROP)
- XtDispatchEvent ((XEvent *) event);
- unblock_input ();
+ if (*finish != X_EVENT_DROP)
+ {
+ /* Ignore some obviously bogus ConfigureNotify events that
+ other clients have been known to send Emacs.
+ (bug#54051) */
+ if (event->type != ConfigureNotify
+ || (event->xconfigure.width != 0
+ && event->xconfigure.height != 0))
+ {
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ XtDispatchEvent (use_copy ? &copy : (XEvent *) event);
+#else
+ XtDispatchEvent ((XEvent *) event);
+#endif
+ }
+ }
+ unblock_input ();
#endif /* USE_X_TOOLKIT */
+#if defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
+ if (*finish != X_EVENT_DROP && copy)
+ {
+ gtk_main_do_event (copy);
+ *finish = X_EVENT_DROP;
+ }
+
+ if (copy)
+ gdk_event_free (copy);
+#endif
break;
}
@@ -11299,6 +22232,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
count++;
}
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ if (event->xany.type == ClientMessage
+ && inev.ie.kind == SCROLL_BAR_CLICK_EVENT)
+ x_unprotect_window_for_callback (dpyinfo);
+#endif
+
if (do_help
&& !(hold_quit && hold_quit->kind != NO_EVENT))
{
@@ -11323,21 +22262,33 @@ handle_one_xevent (struct x_display_info *dpyinfo,
count++;
}
- /* Sometimes event processing draws to the frame outside redisplay.
- To ensure that these changes become visible, draw them here. */
- flush_dirty_back_buffers ();
+ /* Sometimes event processing draws to either F or ANY outside
+ redisplay. To ensure that these changes become visible, draw
+ them here. */
+
+#ifdef HAVE_XDBE
+ if (f)
+ flush_dirty_back_buffer_on (f);
+
+ if (any && any != f)
+ flush_dirty_back_buffer_on (any);
+#endif
+
SAFE_FREE ();
return count;
}
-#if defined USE_X_TOOLKIT || defined USE_MOTIF || defined USE_GTK
-
/* Handles the XEvent EVENT on display DISPLAY.
This is used for event loops outside the normal event handling,
i.e. looping while a popup menu or a dialog is posted.
Returns the value handle_one_xevent sets in the finish argument. */
+
+#ifdef USE_GTK
+static int
+#else
int
+#endif
x_dispatch_event (XEvent *event, Display *display)
{
struct x_display_info *dpyinfo;
@@ -11350,7 +22301,6 @@ x_dispatch_event (XEvent *event, Display *display)
return finish;
}
-#endif
/* Read events coming from the X server.
Return as soon as there are no more events to be read.
@@ -11367,6 +22317,25 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
bool event_found = false;
struct x_display_info *dpyinfo = terminal->display_info.x;
+ /* Don't allow XTread_socket to do anything if drag-and-drop is in
+ progress. If unblock_input causes XTread_socket to be called and
+ read X events while the drag-and-drop event loop is in progress,
+ things can go wrong very quick.
+
+ When x_dnd_unwind_flag is true, the above doesn't apply, since
+ the surrounding code takes special precautions to keep it safe.
+
+ That doesn't matter for events from displays other than the
+ display of the drag-and-drop operation, though. */
+ if (!x_dnd_unwind_flag
+ && ((x_dnd_in_progress
+ && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame))
+ || (x_dnd_waiting_for_finish
+ && dpyinfo->display == x_dnd_finish_display)))
+ return 0;
+
+ x_clean_failable_requests (dpyinfo);
+
block_input ();
/* For debugging, this gives a way to fake an I/O error. */
@@ -11386,8 +22355,19 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
#ifdef HAVE_X_I18N
/* Filter events for the current X input method. */
- if (x_filter_event (dpyinfo, &event))
- continue;
+#ifdef HAVE_XINPUT2
+ if (event.type != GenericEvent
+ || !dpyinfo->supports_xi2
+ || event.xgeneric.extension != dpyinfo->xi2_opcode)
+ {
+ /* Input extension key events are filtered inside
+ handle_one_xevent. */
+#endif
+ if (x_filter_event (dpyinfo, &event))
+ continue;
+#ifdef HAVE_XINPUT2
+ }
+#endif
#endif
event_found = true;
@@ -11421,6 +22401,20 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
if (current_finish == X_EVENT_GOTO_OUT)
break;
}
+
+ /* Now see if `xg_pending_quit_event' was set. */
+ if (xg_pending_quit_event.kind != NO_EVENT)
+ {
+ /* Check that the frame is still valid. It could have been
+ deleted between now and the time the event was recorded. */
+ if (FRAME_LIVE_P (XFRAME (xg_pending_quit_event.frame_or_window)))
+ /* Store that event into hold_quit and clear the pending quit
+ event. */
+ *hold_quit = xg_pending_quit_event;
+
+ /* If the frame is invalid, just clear the event as well. */
+ xg_pending_quit_event.kind = NO_EVENT;
+ }
#endif /* USE_GTK */
/* On some systems, an X bug causes Emacs to get no more events
@@ -11595,6 +22589,9 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
else
xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
xgcv.graphics_exposures = False;
+ xgcv.line_width = 1;
+
+ mask |= GCLineWidth;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
@@ -11622,8 +22619,8 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
x += cursor_glyph->pixel_width - width;
x_fill_rectangle (f, gc, x,
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- width, row->height);
+ WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+ width, row->height, false);
}
else /* HBAR_CURSOR */
{
@@ -11644,7 +22641,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
x_fill_rectangle (f, gc, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
row->height - width),
- w->phys_cursor_width - 1, width);
+ w->phys_cursor_width - 1, width, false);
}
x_reset_clip_rectangles (f, gc);
@@ -11680,7 +22677,9 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
int y, enum text_cursor_kinds cursor_type,
int cursor_width, bool on_p, bool active_p)
{
+#ifdef HAVE_X_I18N
struct frame *f = XFRAME (WINDOW_FRAME (w));
+#endif
if (on_p)
{
@@ -11726,8 +22725,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
#ifdef HAVE_X_I18N
if (w == XWINDOW (f->selected_window))
- if (FRAME_XIC (f))
- xic_set_preeditarea (w, x, y);
+ xic_set_preeditarea (w, x, y);
#endif
}
@@ -11780,11 +22778,19 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
}
#elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
-
- rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
- if (rc != -1)
- FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
-
+ /* This allocates too many colors. */
+ if ((FRAME_X_VISUAL_INFO (f)->class == TrueColor
+ || FRAME_X_VISUAL_INFO (f)->class == StaticColor
+ || FRAME_X_VISUAL_INFO (f)->class == StaticGray)
+ /* That pixmap needs about 240 colors, and we should
+ also leave some more space for other colors as
+ well. */
+ || FRAME_X_VISUAL_INFO (f)->colormap_size >= (240 * 4))
+ {
+ rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+ if (rc != -1)
+ FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+ }
#endif
/* If all else fails, use the (black and white) xbm image. */
@@ -11844,70 +22850,137 @@ x_text_icon (struct frame *f, const char *icon_name)
return false;
}
-#define X_ERROR_MESSAGE_SIZE 200
-/* If non-nil, this should be a string.
- It means catch X errors and store the error message in this string.
-
- The reason we use a stack is that x_catch_error/x_uncatch_error can
- be called from a signal handler.
-*/
+struct x_error_message_stack
+{
+ /* Pointer to the error message of any error that was generated, or
+ NULL. */
+ char *string;
-struct x_error_message_stack {
- char string[X_ERROR_MESSAGE_SIZE];
+ /* The display this error handler applies to. */
Display *dpy;
+
+ /* A function to call upon an error if non-NULL. */
x_special_error_handler handler;
+
+ /* Some data to pass to that handler function. */
void *handler_data;
+
+ /* The previous handler in this stack. */
struct x_error_message_stack *prev;
+
+ /* The first request that this error handler applies to. Keeping
+ track of this allows us to avoid an XSync yet still have errors
+ for previously made requests be handled correctly. */
+ unsigned long first_request;
};
+
+/* Stack of X error message handlers. Whenever an error is generated
+ on a display, look in this stack for an appropriate error handler,
+ set its `string' to the error message and call its `handler' with
+ `handler_data'. If no handler applies to the error, don't catch
+ it, and let it crash Emacs instead.
+
+ This used to be a pointer to a string in which any error would be
+ placed before 2006. */
static struct x_error_message_stack *x_error_message;
-/* An X error handler which stores the error message in
- *x_error_message. This is called from x_error_handler if
- x_catch_errors is in effect. */
+/* The amount of items (depth) in that stack. */
+int x_error_message_count;
+
+static struct x_error_message_stack *
+x_find_error_handler (Display *dpy, XErrorEvent *event)
+{
+ struct x_error_message_stack *stack;
+
+ stack = x_error_message;
+
+ while (stack)
+ {
+ if (X_COMPARE_SERIALS (event->serial, >=,
+ stack->first_request)
+ && dpy == stack->dpy)
+ return stack;
+
+ stack = stack->prev;
+ }
+
+ return NULL;
+}
+
+void
+x_unwind_errors_to (int depth)
+{
+ while (x_error_message_count > depth)
+ /* This is safe to call because we check whether or not
+ x_error_message->dpy is still alive before calling XSync. */
+ x_uncatch_errors ();
+}
+
+#define X_ERROR_MESSAGE_SIZE 200
+
+/* An X error handler which stores the error message in the first
+ applicable handler in the x_error_message stack. This is called
+ from *x_error_handler if an x_catch_errors for DISPLAY is in
+ effect. */
static void
-x_error_catcher (Display *display, XErrorEvent *event)
+x_error_catcher (Display *display, XErrorEvent *event,
+ struct x_error_message_stack *stack)
{
+ char buf[X_ERROR_MESSAGE_SIZE];
+
XGetErrorText (display, event->error_code,
- x_error_message->string,
- X_ERROR_MESSAGE_SIZE);
- if (x_error_message->handler)
- x_error_message->handler (display, event, x_error_message->string,
- x_error_message->handler_data);
+ buf, X_ERROR_MESSAGE_SIZE);
+
+ if (stack->string)
+ xfree (stack->string);
+
+ stack->string = xstrdup (buf);
+
+ if (stack->handler)
+ stack->handler (display, event, stack->string,
+ stack->handler_data);
}
-/* Begin trapping X errors for display DPY. Actually we trap X errors
- for all displays, but DPY should be the display you are actually
- operating on.
+/* Begin trapping X errors for display DPY.
- After calling this function, X protocol errors no longer cause
- Emacs to exit; instead, they are recorded in the string
- stored in *x_error_message.
+ After calling this function, X protocol errors generated on DPY no
+ longer cause Emacs to exit; instead, they are recorded in an error
+ handler pushed onto the stack `x_error_message'.
Calling x_check_errors signals an Emacs error if an X error has
occurred since the last call to x_catch_errors or x_check_errors.
- Calling x_uncatch_errors resumes the normal error handling.
- Calling x_uncatch_errors_after_check is similar, but skips an XSync
- to the server, and should be used only immediately after
- x_had_errors_p or x_check_errors. */
+ Calling x_uncatch_errors resumes the normal error handling,
+ skipping an XSync if the last request made is known to have been
+ processed. Calling x_uncatch_errors_after_check is similar, but
+ always skips an XSync to the server, and should be used only
+ immediately after x_had_errors_p or x_check_errors, or when it is
+ known that no requests have been made since the last x_catch_errors
+ call for DPY.
+
+ There is no need to use this mechanism for ignoring errors from
+ single asynchronous requests, such as sending a ClientMessage to a
+ window that might no longer exist. Use
+ x_ignore_errors_for_next_request (paired with
+ x_stop_ignoring_errors) instead. */
void
x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
void *handler_data)
{
- struct x_error_message_stack *data = xmalloc (sizeof *data);
-
- /* Make sure any errors from previous requests have been dealt with. */
- XSync (dpy, False);
+ struct x_error_message_stack *data;
+ data = xzalloc (sizeof *data);
data->dpy = dpy;
- data->string[0] = 0;
data->handler = handler;
data->handler_data = handler_data;
data->prev = x_error_message;
+ data->first_request = XNextRequest (dpy);
x_error_message = data;
+
+ ++x_error_message_count;
}
void
@@ -11916,6 +22989,135 @@ x_catch_errors (Display *dpy)
x_catch_errors_with_handler (dpy, NULL, NULL);
}
+/* Return if errors for REQUEST should be ignored even if there is no
+ error handler applied. */
+static struct x_failable_request *
+x_request_can_fail (struct x_display_info *dpyinfo,
+ unsigned long request)
+{
+ struct x_failable_request *failable_requests;
+
+ for (failable_requests = dpyinfo->failable_requests;
+ failable_requests < dpyinfo->next_failable_request;
+ failable_requests++)
+ {
+ if (X_COMPARE_SERIALS (request, >=,
+ failable_requests->start)
+ && (!failable_requests->end
+ || X_COMPARE_SERIALS (request, <=,
+ failable_requests->end)))
+ return failable_requests;
+ }
+
+ return NULL;
+}
+
+/* Remove outdated request serials from
+ dpyinfo->failable_requests. */
+static void
+x_clean_failable_requests (struct x_display_info *dpyinfo)
+{
+ struct x_failable_request *first, *last;
+
+ last = dpyinfo->next_failable_request;
+
+ for (first = dpyinfo->failable_requests; first < last; first++)
+ {
+ if (X_COMPARE_SERIALS (first->start, >,
+ LastKnownRequestProcessed (dpyinfo->display))
+ || !first->end
+ || X_COMPARE_SERIALS (first->end, >,
+ LastKnownRequestProcessed (dpyinfo->display)))
+ break;
+ }
+
+ if (first != last)
+ memmove (&dpyinfo->failable_requests, first,
+ sizeof *first * (last - first));
+
+ dpyinfo->next_failable_request = (dpyinfo->failable_requests
+ + (last - first));
+}
+
+static void
+x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
+{
+ struct x_failable_request *request, *max;
+ unsigned long next_request;
+#ifdef HAVE_GTK3
+ GdkDisplay *gdpy;
+
+ /* GTK 3 tends to override our own error handler inside certain
+ callbacks, which this can be called from. Instead of trying to
+ restore our own, add a trap for the following requests with
+ GDK as well. */
+
+ gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+
+ if (gdpy)
+ gdk_x11_display_error_trap_push (gdpy);
+#endif
+
+ if ((dpyinfo->next_failable_request
+ != dpyinfo->failable_requests)
+ && (dpyinfo->next_failable_request - 1)->end == 0)
+ /* A new sequence should never be started before an old one
+ finishes. Use `x_catch_errors' to nest error handlers. */
+ emacs_abort ();
+
+ request = dpyinfo->next_failable_request;
+ max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS;
+ next_request = XNextRequest (dpyinfo->display);
+
+ if (request >= max)
+ {
+ /* There is no point in making this extra sync if all requests
+ are known to have been fully processed. */
+ if ((LastKnownRequestProcessed (dpyinfo->display)
+ != next_request - 1))
+ XSync (dpyinfo->display, False);
+
+ x_clean_failable_requests (dpyinfo);
+ request = dpyinfo->next_failable_request;
+ }
+
+ if (request >= max)
+ /* A request should always be made immediately after calling this
+ function. */
+ emacs_abort ();
+
+ request->start = next_request;
+ request->end = 0;
+
+ dpyinfo->next_failable_request++;
+}
+
+static void
+x_stop_ignoring_errors (struct x_display_info *dpyinfo)
+{
+ struct x_failable_request *range;
+#ifdef HAVE_GTK3
+ GdkDisplay *gdpy;
+#endif
+
+ range = dpyinfo->next_failable_request - 1;
+ range->end = XNextRequest (dpyinfo->display) - 1;
+
+ /* Abort if no request was made since
+ `x_ignore_errors_for_next_request'. */
+
+ if (X_COMPARE_SERIALS (range->end, <,
+ range->start))
+ emacs_abort ();
+
+#ifdef HAVE_GTK3
+ gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+
+ if (gdpy)
+ gdk_x11_display_error_trap_pop_ignored (gdpy);
+#endif
+}
+
/* Undo the last x_catch_errors call.
DPY should be the display that was passed to x_catch_errors.
@@ -11931,17 +23133,20 @@ x_uncatch_errors_after_check (void)
block_input ();
tmp = x_error_message;
x_error_message = x_error_message->prev;
+ --x_error_message_count;
+ if (tmp->string)
+ xfree (tmp->string);
xfree (tmp);
unblock_input ();
}
-/* Undo the last x_catch_errors call.
- DPY should be the display that was passed to x_catch_errors. */
+/* Undo the last x_catch_errors call. */
void
x_uncatch_errors (void)
{
struct x_error_message_stack *tmp;
+ struct x_display_info *dpyinfo;
/* In rare situations when running Emacs run in daemon mode,
shutting down an emacsclient via delete-frame can cause
@@ -11952,13 +23157,29 @@ x_uncatch_errors (void)
block_input ();
+ dpyinfo = x_display_info_for_display (x_error_message->dpy);
+
/* The display may have been closed before this function is called.
Check if it is still open before calling XSync. */
- if (x_display_info_for_display (x_error_message->dpy) != 0)
- XSync (x_error_message->dpy, False);
+ if (dpyinfo != 0
+ /* There is no point in making this extra sync if all requests
+ are known to have been fully processed. */
+ && (LastKnownRequestProcessed (x_error_message->dpy)
+ != XNextRequest (x_error_message->dpy) - 1)
+ /* Likewise if no request was made since the trap was
+ installed. */
+ && (NextRequest (x_error_message->dpy)
+ > x_error_message->first_request))
+ {
+ XSync (x_error_message->dpy, False);
+ x_clean_failable_requests (dpyinfo);
+ }
tmp = x_error_message;
x_error_message = x_error_message->prev;
+ --x_error_message_count;
+ if (tmp->string)
+ xfree (tmp->string);
xfree (tmp);
unblock_input ();
}
@@ -11970,36 +23191,79 @@ x_uncatch_errors (void)
void
x_check_errors (Display *dpy, const char *format)
{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
+ struct x_display_info *dpyinfo;
+ char *string;
- if (x_error_message->string[0])
+ /* This shouldn't happen, since x_check_errors should be called
+ immediately inside an x_catch_errors block. */
+ if (dpy != x_error_message->dpy)
+ emacs_abort ();
+
+ /* There is no point in making this extra sync if all requests
+ are known to have been fully processed. */
+ if ((LastKnownRequestProcessed (dpy)
+ != XNextRequest (dpy) - 1)
+ && (NextRequest (dpy)
+ > x_error_message->first_request))
+ XSync (dpy, False);
+
+ dpyinfo = x_display_info_for_display (dpy);
+
+ /* Clean the array of failable requests, since a sync happened. */
+ if (dpyinfo)
+ x_clean_failable_requests (dpyinfo);
+
+ if (x_error_message->string)
{
- char string[X_ERROR_MESSAGE_SIZE];
- memcpy (string, x_error_message->string, X_ERROR_MESSAGE_SIZE);
- x_uncatch_errors ();
+ string = alloca (strlen (x_error_message->string) + 1);
+ strcpy (string, x_error_message->string);
+
error (format, string);
}
}
-/* Nonzero if we had any X protocol errors
- since we did x_catch_errors on DPY. */
+/* Nonzero if any X protocol errors were generated since the last call
+ to x_catch_errors on DPY. */
bool
x_had_errors_p (Display *dpy)
{
+ struct x_display_info *dpyinfo;
+
+ /* This shouldn't happen, since x_check_errors should be called
+ immediately inside an x_catch_errors block. */
+ if (dpy != x_error_message->dpy)
+ emacs_abort ();
+
/* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
+ if ((LastKnownRequestProcessed (dpy)
+ != XNextRequest (dpy) - 1)
+ && (NextRequest (dpy)
+ > x_error_message->first_request))
+ XSync (dpy, False);
+
+ dpyinfo = x_display_info_for_display (dpy);
+
+ /* Clean the array of failable requests, since a sync happened. */
+ if (dpyinfo)
+ x_clean_failable_requests (dpyinfo);
- return x_error_message->string[0] != 0;
+ return !!x_error_message->string;
}
-/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
+/* Forget about any errors we have had, since we did x_catch_errors on
+ DPY. */
void
x_clear_errors (Display *dpy)
{
- x_error_message->string[0] = 0;
+ /* This shouldn't happen, since x_check_errors should be called
+ immediately inside an x_catch_errors block. */
+ if (dpy != x_error_message->dpy)
+ emacs_abort ();
+
+ xfree (x_error_message->string);
+ x_error_message->string = NULL;
}
#if false
@@ -12017,9 +23281,12 @@ x_fully_uncatch_errors (void)
#if false
static unsigned int x_wire_count;
-x_trace_wire (void)
+
+static int
+x_trace_wire (Display *dpy)
{
- fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+ fprintf (stderr, "Lib call: %u\n", ++x_wire_count);
+ return 0;
}
#endif
@@ -12038,16 +23305,94 @@ static char *error_msg;
static AVOID
x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
{
- struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+ struct x_display_info *dpyinfo;
Lisp_Object frame, tail;
- ptrdiff_t idx = SPECPDL_INDEX ();
+ specpdl_ref idx = SPECPDL_INDEX ();
+ Emacs_XIOErrorHandler io_error_handler;
+ xm_drop_start_message dmsg;
+ struct frame *f;
+ Lisp_Object minibuf_frame, tmp;
+ struct x_failable_request *failable;
+ struct x_error_message_stack *stack;
+ dpyinfo = x_display_info_for_display (dpy);
error_msg = alloca (strlen (error_message) + 1);
strcpy (error_msg, error_message);
/* Inhibit redisplay while frames are being deleted. */
specbind (Qinhibit_redisplay, Qt);
+ /* If drag-and-drop is in progress, cancel drag-and-drop. If DND
+ frame's display is DPY, don't reset event masks or try to send
+ responses to other programs because the display is going
+ away. */
+
+ if (x_dnd_in_progress || x_dnd_waiting_for_finish)
+ {
+ if (!ioerror)
+ {
+ /* Handle display disconnect errors here because this function
+ is not reentrant at this particular spot. */
+ io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler);
+
+ if (!!sigsetjmp (x_dnd_disconnect_handler, 1)
+ && x_dnd_in_progress
+ && dpy == (x_dnd_waiting_for_finish
+ ? x_dnd_finish_display
+ : FRAME_X_DISPLAY (x_dnd_frame)))
+ {
+ /* Clean up drag and drop if the drag frame's display isn't
+ the one being disconnected. */
+ f = x_dnd_frame;
+
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ x_dnd_send_leave (x_dnd_frame,
+ x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
+ && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
+ && x_dnd_motif_setup_p)
+ {
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.x = 0;
+ dmsg.y = 0;
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (f);
+
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
+ x_dnd_last_seen_window, 0);
+ xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
+ x_dnd_last_seen_window, &dmsg);
+ }
+ }
+
+ XSetIOErrorHandler (io_error_handler);
+ }
+
+ dpyinfo = x_display_info_for_display (dpy);
+
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_waiting_for_finish = false;
+
+ if (x_dnd_use_toplevels)
+ x_dnd_free_toplevels (!ioerror);
+
+ x_dnd_return_frame_object = NULL;
+ x_dnd_movement_frame = NULL;
+ x_dnd_frame = NULL;
+ }
+
if (dpyinfo)
{
/* Protect display from being closed when we delete the last
@@ -12058,13 +23403,24 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
dpyinfo->display = 0;
}
+ /* delete_frame can still try to read async input (even though we
+ tell pass `noelisp'), because looking up the `delete-before'
+ parameter calls Fassq which then calls maybe_quit. So block
+ input while deleting frames. */
+ block_input ();
+
/* First delete frames whose mini-buffers are on frames
that are on the dead display. */
FOR_EACH_FRAME (tail, frame)
{
- Lisp_Object minibuf_frame;
+ /* Tooltip frames don't have these, so avoid crashing. */
+
+ if (FRAME_TOOLTIP_P (XFRAME (frame)))
+ continue;
+
minibuf_frame
= WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
+
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_P (XFRAME (minibuf_frame))
&& ! EQ (frame, minibuf_frame)
@@ -12115,18 +23471,46 @@ For details, see etc/PROBLEMS.\n",
/* We have just closed all frames on this display. */
emacs_abort ();
- {
- Lisp_Object tmp;
- XSETTERMINAL (tmp, dpyinfo->terminal);
- Fdelete_terminal (tmp, Qnoelisp);
- }
+ /* This was the last terminal remaining, so print the error
+ message and associated error handlers and kill Emacs. */
+ if (dpyinfo->terminal == terminal_list
+ && !terminal_list->next_terminal)
+ {
+ fprintf (stderr, "%s\n", error_msg);
+
+ if (!ioerror && dpyinfo)
+ {
+ /* Dump the list of error handlers for debugging
+ purposes. */
+
+ fprintf (stderr, "X error handlers currently installed:\n");
+
+ for (failable = dpyinfo->failable_requests;
+ failable < dpyinfo->next_failable_request;
+ ++failable)
+ {
+ if (failable->end)
+ fprintf (stderr, "Ignoring errors between %lu to %lu\n",
+ failable->start, failable->end);
+ else
+ fprintf (stderr, "Ignoring errors from %lu onwards\n",
+ failable->start);
+ }
+
+ for (stack = x_error_message; stack; stack = stack->prev)
+ fprintf (stderr, "Trapping errors from %lu\n",
+ stack->first_request);
+ }
+ }
+
+ XSETTERMINAL (tmp, dpyinfo->terminal);
+ Fdelete_terminal (tmp, Qnoelisp);
}
+ unblock_input ();
+
if (terminal_list == 0)
- {
- fprintf (stderr, "%s\n", error_msg);
- Fkill_emacs (make_fixnum (70));
- }
+ Fkill_emacs (make_fixnum (70), Qnil);
totally_unblock_input ();
@@ -12147,16 +23531,61 @@ static void x_error_quitter (Display *, XErrorEvent *);
static int
x_error_handler (Display *display, XErrorEvent *event)
{
+ struct x_error_message_stack *stack;
+ struct x_display_info *dpyinfo;
+ struct x_failable_request *fail, *last;
+
#if defined USE_GTK && defined HAVE_GTK3
- if ((event->error_code == BadMatch || event->error_code == BadWindow)
+ if ((event->error_code == BadMatch
+ || event->error_code == BadWindow)
&& event->request_code == X_SetInputFocus)
+ return 0;
+#endif
+
+ dpyinfo = x_display_info_for_display (display);
+
+ if (dpyinfo)
{
- return 0;
+ fail = x_request_can_fail (dpyinfo, event->serial);
+
+ if (fail)
+ {
+ /* Now that this request sequence has been fully handled,
+ remove it from the list of requests that can fail. */
+
+ if (event->serial == fail->end)
+ {
+ last = dpyinfo->next_failable_request;
+ memmove (&dpyinfo->failable_requests, fail,
+ sizeof *fail * (last - fail));
+ dpyinfo->next_failable_request = (dpyinfo->failable_requests
+ + (last - fail));
+ }
+
+ return 0;
+ }
}
+
+ /* If we try to ungrab or grab a device that doesn't exist anymore
+ (that happens a lot in xmenu.c), just ignore the error. */
+
+#ifdef HAVE_XINPUT2
+ /* 51 is X_XIGrabDevice and 52 is X_XIUngrabDevice.
+
+ 53 is X_XIAllowEvents. We handle errors from that here to avoid
+ a sync in handle_one_xevent. */
+ if (dpyinfo && dpyinfo->supports_xi2
+ && event->request_code == dpyinfo->xi2_opcode
+ && (event->minor_code == 51
+ || event->minor_code == 52
+ || event->minor_code == 53))
+ return 0;
#endif
- if (x_error_message)
- x_error_catcher (display, event);
+ stack = x_find_error_handler (display, event);
+
+ if (stack)
+ x_error_catcher (display, event, stack);
else
x_error_quitter (display, event);
return 0;
@@ -12171,7 +23600,8 @@ x_error_handler (Display *display, XErrorEvent *event)
static void NO_INLINE
x_error_quitter (Display *display, XErrorEvent *event)
{
- char buf[256], buf1[356];
+ char buf[256], buf1[400 + INT_STRLEN_BOUND (int)
+ + INT_STRLEN_BOUND (unsigned long)];
/* Ignore BadName errors. They can happen because of fonts
or colors that are not defined. */
@@ -12183,8 +23613,9 @@ x_error_quitter (Display *display, XErrorEvent *event)
original error handler. */
XGetErrorText (display, event->error_code, buf, sizeof (buf));
- sprintf (buf1, "X protocol error: %s on protocol request %d",
- buf, event->request_code);
+ sprintf (buf1, "X protocol error: %s on protocol request %d\n"
+ "Serial no: %lu\n", buf, event->request_code,
+ event->serial);
x_connection_closed (display, buf1, false);
}
@@ -12202,6 +23633,7 @@ x_io_error_quitter (Display *display)
DisplayString (display));
x_connection_closed (display, buf, true);
}
+
/* Changing the font of the frame. */
@@ -12328,14 +23760,14 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
if (xim)
{
-#ifdef HAVE_X11R6
+#ifdef HAVE_X11R6_XIM
XIMCallback destroy;
#endif
/* Get supported styles and XIM values. */
XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
-#ifdef HAVE_X11R6
+#ifdef HAVE_X11R6_XIM
destroy.callback = xim_destroy_callback;
destroy.client_data = (XPointer)dpyinfo;
XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
@@ -12362,6 +23794,9 @@ xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_
struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
struct x_display_info *dpyinfo = xim_inst->dpyinfo;
+ if (x_dnd_in_progress)
+ return;
+
/* We don't support multiple XIM connections. */
if (dpyinfo->xim)
return;
@@ -12420,9 +23855,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);
@@ -12447,8 +23884,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);
@@ -12563,7 +23999,7 @@ x_calc_absolute_position (struct frame *f)
which means, do adjust for borders but don't change the gravity. */
static void
-x_set_offset (struct frame *f, register int xoff, register int yoff, int change_gravity)
+x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
{
int modified_top, modified_left;
#ifdef USE_GTK
@@ -12646,10 +24082,45 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
&& FRAME_X_OUTPUT (f)->move_offset_top == 0))))
x_check_expected_move (f, modified_left, modified_top);
}
+ /* Instead, just wait for the last ConfigureWindow request to
+ complete. No window manager is involved when moving child
+ frames. */
+ else
+ XSync (FRAME_X_DISPLAY (f), False);
unblock_input ();
}
+static Window
+x_get_wm_check_window (struct x_display_info *dpyinfo)
+{
+ Window result;
+ unsigned char *tmp_data = NULL;
+ int rc, actual_format;
+ unsigned long actual_size, bytes_remaining;
+ Atom actual_type;
+
+ rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
+ dpyinfo->Xatom_net_supporting_wm_check,
+ 0, 1, False, XA_WINDOW, &actual_type,
+ &actual_format, &actual_size,
+ &bytes_remaining, &tmp_data);
+
+ if (rc != Success || actual_type != XA_WINDOW
+ || actual_format != 32 || actual_size != 1)
+ {
+ if (tmp_data)
+ XFree (tmp_data);
+
+ return None;
+ }
+
+ result = *(Window *) tmp_data;
+ XFree (tmp_data);
+
+ return result;
+}
+
/* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
on the root window for frame F contains ATOMNAME.
This is how a WM check shall be done according to the Window Manager
@@ -12657,47 +24128,53 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
https://freedesktop.org/wiki/Specifications/wm-spec/. */
bool
-x_wm_supports (struct frame *f, Atom want_atom)
+x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
{
Atom actual_type;
unsigned long actual_size, bytes_remaining;
int i, rc, actual_format;
bool ret;
Window wmcheck_window;
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
Window target_window = dpyinfo->root_window;
int max_len = 65536;
- Display *dpy = FRAME_X_DISPLAY (f);
+ Display *dpy = dpyinfo->display;
unsigned char *tmp_data = NULL;
Atom target_type = XA_WINDOW;
+ /* The user says there's no window manager, so take him up on
+ it. */
+ if (!NILP (Vx_no_window_manager))
+ return false;
+
block_input ();
x_catch_errors (dpy);
- rc = XGetWindowProperty (dpy, target_window,
- dpyinfo->Xatom_net_supporting_wm_check,
- 0, max_len, False, target_type,
- &actual_type, &actual_format, &actual_size,
- &bytes_remaining, &tmp_data);
- if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
- {
- if (tmp_data) XFree (tmp_data);
- x_uncatch_errors ();
- unblock_input ();
- return false;
- }
+ wmcheck_window = dpyinfo->net_supported_window;
- wmcheck_window = *(Window *) tmp_data;
- XFree (tmp_data);
+ if (wmcheck_window == None)
+ wmcheck_window = x_get_wm_check_window (dpyinfo);
- /* Check if window exists. */
- XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
- if (x_had_errors_p (dpy))
+ if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
{
- x_uncatch_errors_after_check ();
- unblock_input ();
- return false;
+ if (dpyinfo->net_supported_window != None)
+ {
+ dpyinfo->net_supported_window = None;
+ wmcheck_window = x_get_wm_check_window (dpyinfo);
+
+ if (!x_special_window_exists_p (dpyinfo, wmcheck_window))
+ {
+ x_uncatch_errors ();
+ unblock_input ();
+ return false;
+ }
+ }
+ else
+ {
+ x_uncatch_errors ();
+ unblock_input ();
+ return false;
+ }
}
if (dpyinfo->net_supported_window != wmcheck_window)
@@ -12741,22 +24218,36 @@ x_wm_supports (struct frame *f, Atom want_atom)
return ret;
}
+bool
+x_wm_supports (struct frame *f, Atom want_atom)
+{
+ return x_wm_supports_1 (FRAME_DISPLAY_INFO (f),
+ want_atom);
+}
+
static void
set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value)
{
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
+ struct x_display_info *dpyinfo;
+ XEvent msg;
+
+ dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
+ msg.xclient.type = ClientMessage;
+ msg.xclient.window = FRAME_OUTER_WINDOW (XFRAME (frame));
+ msg.xclient.message_type = dpyinfo->Xatom_net_wm_state;
+ msg.xclient.format = 32;
+
+ msg.xclient.data.l[0] = add ? 1 : 0;
+ msg.xclient.data.l[1] = atom;
+ msg.xclient.data.l[2] = value;
+ msg.xclient.data.l[3] = 1; /* Source indication. */
+ msg.xclient.data.l[4] = 0;
- x_send_client_event (frame, make_fixnum (0), frame,
- dpyinfo->Xatom_net_wm_state,
- make_fixnum (32),
- /* 1 = add, 0 = remove */
- Fcons
- (make_fixnum (add),
- Fcons
- (INT_TO_INTEGER (atom),
- (value != 0
- ? list1 (INT_TO_INTEGER (value))
- : Qnil))));
+ block_input ();
+ XSendEvent (dpyinfo->display, dpyinfo->root_window,
+ False, (SubstructureRedirectMask
+ | SubstructureNotifyMask), &msg);
+ unblock_input ();
}
void
@@ -12771,6 +24262,18 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
dpyinfo->Xatom_net_wm_state_sticky, None);
}
+void
+x_set_shaded (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
+{
+ Lisp_Object frame;
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ XSETFRAME (frame, f);
+
+ set_wm_state (frame, !NILP (new_value),
+ dpyinfo->Xatom_net_wm_state_shaded, None);
+}
+
/**
* x_set_skip_taskbar:
*
@@ -12871,7 +24374,8 @@ static bool
x_get_current_wm_state (struct frame *f,
Window window,
int *size_state,
- bool *sticky)
+ bool *sticky,
+ bool *shaded)
{
unsigned long actual_size;
int i;
@@ -12883,18 +24387,24 @@ x_get_current_wm_state (struct frame *f,
#ifdef USE_XCB
xcb_get_property_cookie_t prop_cookie;
xcb_get_property_reply_t *prop;
- xcb_atom_t *reply_data UNINIT;
+ typedef xcb_atom_t reply_data_object;
#else
Display *dpy = FRAME_X_DISPLAY (f);
unsigned long bytes_remaining;
int rc, actual_format;
Atom actual_type;
unsigned char *tmp_data = NULL;
- Atom *reply_data UNINIT;
+ typedef Atom reply_data_object;
#endif
+ reply_data_object *reply_data;
+# if defined GCC_LINT || defined lint
+ reply_data_object reply_data_dummy;
+ reply_data = &reply_data_dummy;
+# endif
*sticky = false;
*size_state = FULLSCREEN_NONE;
+ *shaded = false;
block_input ();
@@ -12956,6 +24466,8 @@ x_get_current_wm_state (struct frame *f,
*size_state = FULLSCREEN_BOTH;
else if (a == dpyinfo->Xatom_net_wm_state_sticky)
*sticky = true;
+ else if (a == dpyinfo->Xatom_net_wm_state_shaded)
+ *shaded = true;
}
#ifdef USE_XCB
@@ -12978,7 +24490,7 @@ do_ewmh_fullscreen (struct frame *f)
int cur;
bool dummy;
- x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
+ x_get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy, &dummy);
/* Some window managers don't say they support _NET_WM_STATE, but they do say
they support _NET_WM_STATE_FULLSCREEN. Try that also. */
@@ -13118,8 +24630,10 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
{
int value = FULLSCREEN_NONE;
Lisp_Object lval;
- bool sticky = false;
- bool not_hidden = x_get_current_wm_state (f, event->window, &value, &sticky);
+ bool sticky = false, shaded = false;
+ bool not_hidden = x_get_current_wm_state (f, event->window,
+ &value, &sticky,
+ &shaded);
lval = Qnil;
switch (value)
@@ -13140,6 +24654,7 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
store_frame_param (f, Qfullscreen, lval);
store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
+ store_frame_param (f, Qshaded, shaded ? Qt : Qnil);
return not_hidden;
}
@@ -13236,7 +24751,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
int adjusted_left;
int adjusted_top;
- FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+ FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
@@ -13253,7 +24768,6 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
else
/* It's a "Type B" window manager. We don't have to adjust the
frame's position. */
-
FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
}
@@ -13267,11 +24781,17 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
static void
x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
{
- int count = 0;
+ sigset_t emptyset;
+ int count, current_left, current_top;
+ struct timespec fallback;
+
+ sigemptyset (&emptyset);
+ count = 0;
while (count++ < 50)
{
- int current_left = 0, current_top = 0;
+ current_left = 0;
+ current_top = 0;
/* In theory, this call to XSync only needs to happen once, but in
practice, it doesn't seem to work, hence the need for the surrounding
@@ -13296,9 +24816,15 @@ x_sync_with_move (struct frame *f, int left, int top, bool fuzzy)
/* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
will then return up-to-date position info. */
- wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
-}
+ fallback = dtotimespec (0.5);
+ /* This will hang if input is blocked, so use pselect to wait
+ instead. */
+ if (input_blocked_p ())
+ pselect (0, NULL, NULL, NULL, &fallback, &emptyset);
+ else
+ wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0);
+}
/* Wait for an event on frame F matching EVENTTYPE. */
void
@@ -13460,16 +24986,15 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
if (FRAME_DISPLAY_INFO (f)->supports_xi2)
{
- XGrabServer (FRAME_X_DISPLAY (f));
- if (XIGetClientPointer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ if (XIGetClientPointer (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
&deviceid))
{
- XIWarpPointer (FRAME_X_DISPLAY (f),
- deviceid, None,
- FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
+ XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
+ FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
+ x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
}
- XUngrabServer (FRAME_X_DISPLAY (f));
}
else
#endif
@@ -13537,20 +25062,32 @@ xembed_request_focus (struct frame *f)
static void
x_ewmh_activate_frame (struct frame *f)
{
- /* See Window Manager Specification/Extended Window Manager Hints at
- https://freedesktop.org/wiki/Specifications/wm-spec/ */
-
- struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+ XEvent msg;
+ struct x_display_info *dpyinfo;
- if (FRAME_VISIBLE_P (f) && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
- {
- Lisp_Object frame;
- XSETFRAME (frame, f);
- x_send_client_event (frame, make_fixnum (0), frame,
- dpyinfo->Xatom_net_active_window,
- make_fixnum (32),
- list2 (make_fixnum (1),
- INT_TO_INTEGER (dpyinfo->last_user_time)));
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (FRAME_VISIBLE_P (f)
+ && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
+ {
+ /* See the documentation at
+ https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
+ for more details on the format of this message. */
+ msg.xclient.type = ClientMessage;
+ msg.xclient.window = FRAME_OUTER_WINDOW (f);
+ msg.xclient.message_type = dpyinfo->Xatom_net_active_window;
+ msg.xclient.format = 32;
+ msg.xclient.data.l[0] = 1;
+ msg.xclient.data.l[1] = dpyinfo->last_user_time;
+ msg.xclient.data.l[2] = (!dpyinfo->x_focus_frame
+ ? None
+ : FRAME_OUTER_WINDOW (dpyinfo->x_focus_frame));
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
+
+ XSendEvent (dpyinfo->display, dpyinfo->root_window,
+ False, (SubstructureRedirectMask
+ | SubstructureNotifyMask), &msg);
}
}
@@ -13570,7 +25107,7 @@ x_get_focus_frame (struct frame *f)
/* In certain situations, when the window manager follows a
click-to-focus policy, there seems to be no way around calling
- XSetInputFocus to give another frame the input focus .
+ XSetInputFocus to give another frame the input focus.
In an ideal world, XSetInputFocus should generally be avoided so
that applications don't interfere with the window manager's focus
@@ -13580,28 +25117,26 @@ x_get_focus_frame (struct frame *f)
static void
x_focus_frame (struct frame *f, bool noactivate)
{
- Display *dpy = FRAME_X_DISPLAY (f);
+ struct x_display_info *dpyinfo;
- block_input ();
- x_catch_errors (dpy);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
if (FRAME_X_EMBEDDED_P (f))
- {
- /* For Xembedded frames, normally the embedder forwards key
- events. See XEmbed Protocol Specification at
- https://freedesktop.org/wiki/Specifications/xembed-spec/ */
- xembed_request_focus (f);
- }
+ /* For Xembedded frames, normally the embedder forwards key
+ events. See XEmbed Protocol Specification at
+ https://freedesktop.org/wiki/Specifications/xembed-spec/ */
+ xembed_request_focus (f);
else
{
- XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ /* Ignore any BadMatch error this request might result in. */
+ x_ignore_errors_for_next_request (dpyinfo);
+ XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
RevertToParent, CurrentTime);
+ x_stop_ignoring_errors (dpyinfo);
+
if (!noactivate)
x_ewmh_activate_frame (f);
}
-
- x_uncatch_errors ();
- unblock_input ();
}
@@ -13644,9 +25179,14 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
event.xclient.data.l[3] = data1;
event.xclient.data.l[4] = data2;
+ /* XXX: the XEmbed spec tells us to trap errors around this request,
+ but I don't understand why: there is no way for clients to
+ survive the death of the parent anyway. */
+
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
False, NoEventMask, &event);
- XSync (FRAME_X_DISPLAY (f), False);
+ x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
}
/* Change of visibility. */
@@ -13662,6 +25202,11 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
void
x_make_frame_visible (struct frame *f)
{
+#ifndef USE_GTK
+ struct x_display_info *dpyinfo;
+ struct x_output *output;
+#endif
+
if (FRAME_PARENT_FRAME (f))
{
if (!FRAME_VISIBLE_P (f))
@@ -13686,6 +25231,10 @@ x_make_frame_visible (struct frame *f)
gui_set_bitmap_icon (f);
+#ifndef USE_GTK
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+#endif
+
if (! FRAME_VISIBLE_P (f))
{
/* We test asked_for_visible here to make sure we don't
@@ -13697,6 +25246,25 @@ x_make_frame_visible (struct frame *f)
&& ! f->output_data.x->asked_for_visible)
x_set_offset (f, f->left_pos, f->top_pos, 0);
+#ifndef USE_GTK
+ output = FRAME_X_OUTPUT (f);
+ x_update_frame_user_time_window (f);
+
+ /* It's been a while since I wrote that code... I don't
+ remember if it can leave `user_time_window' unset or not. */
+ if (output->user_time_window != None)
+ {
+ if (dpyinfo->last_user_time)
+ XChangeProperty (dpyinfo->display, output->user_time_window,
+ dpyinfo->Xatom_net_wm_user_time,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *) &dpyinfo->last_user_time, 1);
+ else
+ XDeleteProperty (dpyinfo->display, output->user_time_window,
+ dpyinfo->Xatom_net_wm_user_time);
+ }
+#endif
+
f->output_data.x->asked_for_visible = true;
if (! EQ (Vx_no_window_manager, Qt))
@@ -13720,6 +25288,12 @@ x_make_frame_visible (struct frame *f)
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif /* not USE_GTK */
#endif /* not USE_X_TOOLKIT */
+
+ if (FRAME_X_EMBEDDED_P (f))
+ {
+ SET_FRAME_VISIBLE (f, true);
+ SET_FRAME_ICONIFIED (f, false);
+ }
}
XFlush (FRAME_X_DISPLAY (f));
@@ -13881,6 +25455,18 @@ x_make_frame_visible_invisible (struct frame *f, bool visible)
x_make_frame_invisible (f);
}
+Cursor
+x_create_font_cursor (struct x_display_info *dpyinfo, int glyph)
+{
+ if (glyph <= 65535)
+ return XCreateFontCursor (dpyinfo->display, glyph);
+
+ /* x-pointer-invisible cannot fit in CARD16, and thus cannot be any
+ existing cursor. */
+ return make_invisible_cursor (dpyinfo);
+}
+
+
/* Change window state from mapped to iconified. */
void
@@ -13968,9 +25554,13 @@ x_iconify_frame (struct frame *f)
msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
msg.xclient.format = 32;
msg.xclient.data.l[0] = IconicState;
+ msg.xclient.data.l[1] = 0;
+ msg.xclient.data.l[2] = 0;
+ msg.xclient.data.l[3] = 0;
+ msg.xclient.data.l[4] = 0;
if (! XSendEvent (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ FRAME_DISPLAY_INFO (f)->root_window,
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&msg))
@@ -14020,7 +25610,7 @@ x_free_frame_resources (struct frame *f)
/* Always exit with visible pointer to avoid weird issue
with Xfixes (Bug#17609). */
if (f->pointer_invisible)
- FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, 0);
+ XTtoggle_invisible_pointer (f, 0);
/* We must free faces before destroying windows because some
font-driver (e.g. xft) access a window while finishing a
@@ -14046,9 +25636,6 @@ x_free_frame_resources (struct frame *f)
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
-
- if (f->output_data.x->preedit_chars)
- xfree (f->output_data.x->preedit_chars);
#endif
#ifdef USE_CAIRO
@@ -14081,9 +25668,19 @@ x_free_frame_resources (struct frame *f)
tear_down_x_back_buffer (f);
if (FRAME_X_WINDOW (f))
- XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif /* !USE_X_TOOLKIT */
+#ifdef HAVE_XSYNC
+ if (FRAME_X_BASIC_COUNTER (f) != None)
+ XSyncDestroyCounter (FRAME_X_DISPLAY (f),
+ FRAME_X_BASIC_COUNTER (f));
+
+ if (FRAME_X_EXTENDED_COUNTER (f) != None)
+ XSyncDestroyCounter (FRAME_X_DISPLAY (f),
+ FRAME_X_EXTENDED_COUNTER (f));
+#endif
+
unload_color (f, FRAME_FOREGROUND_PIXEL (f));
unload_color (f, FRAME_BACKGROUND_PIXEL (f));
unload_color (f, f->output_data.x->cursor_pixel);
@@ -14156,9 +25753,19 @@ x_free_frame_resources (struct frame *f)
XFlush (FRAME_X_DISPLAY (f));
}
- xfree (f->output_data.x->saved_menu_event);
- xfree (f->output_data.x);
- f->output_data.x = NULL;
+#ifdef HAVE_GTK3
+ if (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider)
+ g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider);
+
+ if (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider)
+ g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider);
+#endif
+
+ if (f == dpyinfo->motif_drag_atom_owner)
+ {
+ dpyinfo->motif_drag_atom_owner = NULL;
+ dpyinfo->motif_drag_atom = None;
+ }
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
@@ -14185,9 +25792,216 @@ x_destroy_window (struct frame *f)
if (dpyinfo->display != 0)
x_free_frame_resources (f);
+ xfree (f->output_data.x->saved_menu_event);
+
+#ifdef HAVE_X_I18N
+ if (f->output_data.x->preedit_chars)
+ xfree (f->output_data.x->preedit_chars);
+#endif
+
+#ifdef HAVE_XINPUT2
+#ifdef HAVE_XINPUT2_1
+ if (f->output_data.x->xi_masks)
+ XFree (f->output_data.x->xi_masks);
+#else
+ /* This is allocated by us under very old versions of libXi; see
+ `setup_xi_event_mask'. */
+ if (f->output_data.x->xi_masks)
+ xfree (f->output_data.x->xi_masks);
+#endif
+#endif
+
+ xfree (f->output_data.x);
+ f->output_data.x = NULL;
+
dpyinfo->reference_count--;
}
+/* Intern NAME in DPYINFO, but check to see if the atom was already
+ interned when the X connection was opened, and use that instead.
+
+ If PREDEFINED_ONLY, return None if the atom was not interned during
+ connection setup or is predefined. */
+Atom
+x_intern_cached_atom (struct x_display_info *dpyinfo,
+ const char *name, bool predefined_only)
+{
+ int i;
+ char *ptr;
+ Atom *atom;
+
+ /* Special atoms that depend on the screen number. */
+ char xsettings_atom_name[sizeof "_XSETTINGS_S%d" - 2
+ + INT_STRLEN_BOUND (int)];
+ char cm_atom_name[sizeof "_NET_WM_CM_S%d" - 2
+ + INT_STRLEN_BOUND (int)];
+
+ sprintf (xsettings_atom_name, "_XSETTINGS_S%d",
+ XScreenNumberOfScreen (dpyinfo->screen));
+ sprintf (cm_atom_name, "_NET_WM_CM_S%d",
+ XScreenNumberOfScreen (dpyinfo->screen));
+
+ if (!strcmp (name, xsettings_atom_name))
+ return dpyinfo->Xatom_xsettings_sel;
+
+ if (!strcmp (name, cm_atom_name))
+ return dpyinfo->Xatom_NET_WM_CM_Sn;
+
+ /* Now do some common predefined atoms. */
+ if (!strcmp (name, "PRIMARY"))
+ return XA_PRIMARY;
+
+ if (!strcmp (name, "SECONDARY"))
+ return XA_SECONDARY;
+
+ if (!strcmp (name, "STRING"))
+ return XA_STRING;
+
+ if (!strcmp (name, "INTEGER"))
+ return XA_INTEGER;
+
+ if (!strcmp (name, "ATOM"))
+ return XA_ATOM;
+
+ if (!strcmp (name, "WINDOW"))
+ return XA_WINDOW;
+
+ if (!strcmp (name, "DRAWABLE"))
+ return XA_DRAWABLE;
+
+ if (!strcmp (name, "BITMAP"))
+ return XA_BITMAP;
+
+ if (!strcmp (name, "CARDINAL"))
+ return XA_CARDINAL;
+
+ if (!strcmp (name, "COLORMAP"))
+ return XA_COLORMAP;
+
+ if (!strcmp (name, "CURSOR"))
+ return XA_CURSOR;
+
+ if (!strcmp (name, "FONT"))
+ return XA_FONT;
+
+ if (dpyinfo->motif_drag_atom != None
+ && !strcmp (name, dpyinfo->motif_drag_atom_name))
+ return dpyinfo->motif_drag_atom;
+
+ for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
+ {
+ ptr = (char *) dpyinfo;
+
+ if (!strcmp (x_atom_refs[i].name, name))
+ {
+ atom = (Atom *) (ptr + x_atom_refs[i].offset);
+
+ return *atom;
+ }
+ }
+
+ if (predefined_only)
+ return None;
+
+ return XInternAtom (dpyinfo->display, name, False);
+}
+
+/* Get the name of ATOM, but try not to make a request to the X
+ server. Whether or not a request to the X server happened is
+ placed in NEED_SYNC. */
+char *
+x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
+ bool *need_sync)
+{
+ char *dpyinfo_pointer, *name, *value, *buffer;
+ int i;
+ Atom ref_atom;
+
+ dpyinfo_pointer = (char *) dpyinfo;
+ value = NULL;
+
+ if (need_sync)
+ *need_sync = false;
+
+ buffer = alloca (45 + INT_STRLEN_BOUND (int));
+
+ switch (atom)
+ {
+ case XA_PRIMARY:
+ return xstrdup ("PRIMARY");
+
+ case XA_SECONDARY:
+ return xstrdup ("SECONDARY");
+
+ case XA_INTEGER:
+ return xstrdup ("INTEGER");
+
+ case XA_ATOM:
+ return xstrdup ("ATOM");
+
+ case XA_CARDINAL:
+ return xstrdup ("CARDINAL");
+
+ case XA_WINDOW:
+ return xstrdup ("WINDOW");
+
+ case XA_DRAWABLE:
+ return xstrdup ("DRAWABLE");
+
+ case XA_BITMAP:
+ return xstrdup ("BITMAP");
+
+ case XA_COLORMAP:
+ return xstrdup ("COLORMAP");
+
+ case XA_FONT:
+ return xstrdup ("FONT");
+
+ default:
+ if (dpyinfo->motif_drag_atom
+ && atom == dpyinfo->motif_drag_atom)
+ return xstrdup (dpyinfo->motif_drag_atom_name);
+
+ if (atom == dpyinfo->Xatom_xsettings_sel)
+ {
+ sprintf (buffer, "_XSETTINGS_S%d",
+ XScreenNumberOfScreen (dpyinfo->screen));
+ return xstrdup (buffer);
+ }
+
+ if (atom == dpyinfo->Xatom_NET_WM_CM_Sn)
+ {
+ sprintf (buffer, "_NET_WM_CM_S%d",
+ XScreenNumberOfScreen (dpyinfo->screen));
+ return xstrdup (buffer);
+ }
+
+ for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
+ {
+ ref_atom = *(Atom *) (dpyinfo_pointer
+ + x_atom_refs[i].offset);
+
+ if (atom == ref_atom)
+ return xstrdup (x_atom_refs[i].name);
+ }
+
+ name = XGetAtomName (dpyinfo->display, atom);
+
+ if (need_sync)
+ *need_sync = true;
+
+ if (name)
+ {
+ value = xstrdup (name);
+ XFree (name);
+ }
+
+ break;
+ }
+
+ return value;
+}
+
/* Setting window manager hints. */
@@ -14198,12 +26012,15 @@ x_destroy_window (struct frame *f)
flag (this is useful when FLAGS is 0).
The GTK version is in gtkutils.c. */
-#ifndef USE_GTK
void
x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
{
+#ifndef USE_GTK
XSizeHints size_hints;
Window window = FRAME_OUTER_WINDOW (f);
+#ifdef USE_X_TOOLKIT
+ WMShellWidget shell;
+#endif
if (!window)
return;
@@ -14211,7 +26028,63 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{
- widget_update_wm_size_hints (f->output_data.x->widget);
+ /* Do this dance in xterm.c because some stuff is not as easily
+ available in widget.c. */
+
+ eassert (XtIsWMShell (f->output_data.x->widget));
+ shell = (WMShellWidget) f->output_data.x->widget;
+
+ shell->wm.size_hints.flags &= ~(PPosition | USPosition);
+ shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
+
+ if (user_position)
+ {
+ shell->wm.size_hints.flags &= ~PPosition;
+ shell->wm.size_hints.flags |= USPosition;
+ }
+
+ widget_update_wm_size_hints (f->output_data.x->widget,
+ f->output_data.x->edit_widget);
+
+#ifdef USE_MOTIF
+ /* Do this all over again for the benefit of Motif, which always
+ knows better than the programmer. */
+ shell->wm.size_hints.flags &= ~(PPosition | USPosition);
+ shell->wm.size_hints.flags |= flags & (PPosition | USPosition);
+
+ if (user_position)
+ {
+ shell->wm.size_hints.flags &= ~PPosition;
+ shell->wm.size_hints.flags |= USPosition;
+ }
+
+ /* Drill hints into Motif, since it keeps setting its own. */
+ size_hints.flags = shell->wm.size_hints.flags;
+ size_hints.x = shell->wm.size_hints.x;
+ size_hints.y = shell->wm.size_hints.y;
+ size_hints.width = shell->wm.size_hints.width;
+ size_hints.height = shell->wm.size_hints.height;
+ size_hints.min_width = shell->wm.size_hints.min_width;
+ size_hints.min_height = shell->wm.size_hints.min_height;
+ size_hints.max_width = shell->wm.size_hints.max_width;
+ size_hints.max_height = shell->wm.size_hints.max_height;
+ size_hints.width_inc = shell->wm.size_hints.width_inc;
+ size_hints.height_inc = shell->wm.size_hints.height_inc;
+ size_hints.min_aspect.x = shell->wm.size_hints.min_aspect.x;
+ size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y;
+ size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x;
+ size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y;
+#ifdef HAVE_X11XTR6
+ size_hints.base_width = shell->wm.base_width;
+ size_hints.base_height = shell->wm.base_height;
+ size_hints.win_gravity = shell->wm.win_gravity;
+#endif
+
+ XSetWMNormalHints (XtDisplay (f->output_data.x->widget),
+ XtWindow (f->output_data.x->widget),
+ &size_hints);
+#endif
+
return;
}
#endif
@@ -14299,8 +26172,10 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
#endif /* PWinGravity */
XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
+#else
+ xg_wm_set_size_hint (f, flags, user_position);
+#endif /* USE_GTK */
}
-#endif /* not USE_GTK */
/* Used for IconicState or NormalState */
@@ -14553,96 +26428,6 @@ my_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
}
#endif
-/* Create invisible cursor on X display referred by DPYINFO. */
-
-static Cursor
-make_invisible_cursor (struct x_display_info *dpyinfo)
-{
- Display *dpy = dpyinfo->display;
- static char const no_data[] = { 0 };
- Pixmap pix;
- XColor col;
- Cursor c = 0;
-
- x_catch_errors (dpy);
- pix = XCreateBitmapFromData (dpy, dpyinfo->root_window, no_data, 1, 1);
- if (! x_had_errors_p (dpy) && pix != None)
- {
- Cursor pixc;
- col.pixel = 0;
- col.red = col.green = col.blue = 0;
- col.flags = DoRed | DoGreen | DoBlue;
- pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
- if (! x_had_errors_p (dpy) && pixc != None)
- c = pixc;
- XFreePixmap (dpy, pix);
- }
-
- x_uncatch_errors ();
-
- return c;
-}
-
-/* True if DPY supports Xfixes extension >= 4. */
-
-static bool
-x_probe_xfixes_extension (Display *dpy)
-{
-#ifdef HAVE_XFIXES
- int major, minor;
- return XFixesQueryVersion (dpy, &major, &minor) && major >= 4;
-#else
- return false;
-#endif /* HAVE_XFIXES */
-}
-
-/* Toggle mouse pointer visibility on frame F by using Xfixes functions. */
-
-static void
-xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
-{
-#ifdef HAVE_XFIXES
- if (invisible)
- XFixesHideCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- else
- XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- f->pointer_invisible = invisible;
-#else
- emacs_abort ();
-#endif /* HAVE_XFIXES */
-}
-
-/* Toggle mouse pointer visibility on frame F by using invisible cursor. */
-
-static void
-x_toggle_visible_pointer (struct frame *f, bool invisible)
-{
- eassert (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0);
- if (invisible)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- FRAME_DISPLAY_INFO (f)->invisible_cursor);
- else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->current_cursor);
- f->pointer_invisible = invisible;
-}
-
-/* Setup pointer blanking, prefer Xfixes if available. */
-
-static void
-x_setup_pointer_blanking (struct x_display_info *dpyinfo)
-{
- /* FIXME: the brave tester should set EMACS_XFIXES because we're suspecting
- X server bug, see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17609. */
- if (egetenv ("EMACS_XFIXES") && x_probe_xfixes_extension (dpyinfo->display))
- dpyinfo->toggle_visible_pointer = xfixes_toggle_visible_pointer;
- else
- {
- dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer;
- dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
- }
-}
-
/* Current X display connection identifier. Incremented for each next
connection established. */
static unsigned x_display_id;
@@ -14661,6 +26446,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#ifdef USE_XCB
xcb_connection_t *xcb_conn;
#endif
+ static char const cm_atom_fmt[] = "_NET_WM_CM_S%d";
+ char cm_atom_sprintf[sizeof cm_atom_fmt - 2 + INT_STRLEN_BOUND (int)];
+#ifdef USE_GTK
+ GdkDisplay *gdpy;
+ GdkScreen *gscr;
+#endif
block_input ();
@@ -14822,11 +26613,18 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
}
#endif
+ /* Select for structure events on the root window, since this allows
+ us to record changes to the size of the screen. */
+
+ XSelectInput (dpy, DefaultRootWindow (dpy), StructureNotifyMask);
+
/* We have definitely succeeded. Record the new connection. */
dpyinfo = xzalloc (sizeof *dpyinfo);
terminal = x_create_terminal (dpyinfo);
+ dpyinfo->next_failable_request = dpyinfo->failable_requests;
+
{
struct x_display_info *share;
@@ -14840,7 +26638,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
{
terminal->kboard = allocate_kboard (Qx);
- if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, Qunbound))
+ if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function,
+ Qunbound))
{
char *vendor = ServerVendor (dpy);
@@ -14853,7 +26652,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
vendor ? build_string (vendor) : empty_unibyte_string));
block_input ();
terminal->next_terminal = terminal_list;
- terminal_list = terminal;
+ terminal_list = terminal;
}
/* Don't let the initial kboard remain current longer than necessary.
@@ -14880,11 +26679,17 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->smallest_font_height = 1;
dpyinfo->smallest_char_width = 1;
+ dpyinfo->color_names_size = 256;
+ dpyinfo->color_names = xzalloc (dpyinfo->color_names_size
+ * sizeof *dpyinfo->color_names);
+ dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size
+ * sizeof *dpyinfo->color_names_length);
+
/* Set the name of the terminal. */
terminal->name = xlispstrdup (display_name);
#if false
- XSetAfterFunction (x_current_display, x_trace_wire);
+ XSetAfterFunction (dpyinfo->display, x_trace_wire);
#endif
Lisp_Object system_name = Fsystem_name ();
@@ -14930,6 +26735,45 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#else
dpyinfo->display->db = xrdb;
#endif
+
+#ifdef HAVE_XRENDER
+ int event_base, error_base;
+ dpyinfo->xrender_supported_p
+ = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
+
+ if (dpyinfo->xrender_supported_p)
+ dpyinfo->xrender_supported_p
+ = XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major,
+ &dpyinfo->xrender_minor);
+#endif
+
+ /* This must come after XRenderQueryVersion! */
+#ifdef HAVE_XCOMPOSITE
+ int composite_event_base, composite_error_base;
+ dpyinfo->composite_supported_p = XCompositeQueryExtension (dpyinfo->display,
+ &composite_event_base,
+ &composite_error_base);
+
+ if (dpyinfo->composite_supported_p)
+ dpyinfo->composite_supported_p
+ = XCompositeQueryVersion (dpyinfo->display,
+ &dpyinfo->composite_major,
+ &dpyinfo->composite_minor);
+#endif
+
+#ifdef HAVE_XSHAPE
+ dpyinfo->xshape_supported_p
+ = XShapeQueryExtension (dpyinfo->display,
+ &dpyinfo->xshape_event_base,
+ &dpyinfo->xshape_error_base);
+
+ if (dpyinfo->xshape_supported_p)
+ dpyinfo->xshape_supported_p
+ = XShapeQueryVersion (dpyinfo->display,
+ &dpyinfo->xshape_major,
+ &dpyinfo->xshape_minor);
+#endif
+
/* Put the rdb where we can find it in a way that works on
all versions. */
dpyinfo->rdb = xrdb;
@@ -14944,21 +26788,53 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
reset_mouse_highlight (&dpyinfo->mouse_highlight);
- /* See if we can construct pixel values from RGB values. */
- if (dpyinfo->visual->class == TrueColor)
- {
- get_bits_and_offset (dpyinfo->visual->red_mask,
- &dpyinfo->red_bits, &dpyinfo->red_offset);
- get_bits_and_offset (dpyinfo->visual->blue_mask,
- &dpyinfo->blue_bits, &dpyinfo->blue_offset);
- get_bits_and_offset (dpyinfo->visual->green_mask,
- &dpyinfo->green_bits, &dpyinfo->green_offset);
- }
+#ifdef HAVE_XRENDER
+ if (dpyinfo->xrender_supported_p
+ /* This could already have been initialized by
+ `select_visual'. */
+ && !dpyinfo->pict_format)
+ dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display,
+ dpyinfo->visual);
+#endif
+
+#ifdef HAVE_XSYNC
+ int xsync_event_base, xsync_error_base;
+ dpyinfo->xsync_supported_p
+ = XSyncQueryExtension (dpyinfo->display,
+ &xsync_event_base,
+ &xsync_error_base);
+
+ if (dpyinfo->xsync_supported_p)
+ dpyinfo->xsync_supported_p = XSyncInitialize (dpyinfo->display,
+ &dpyinfo->xsync_major,
+ &dpyinfo->xsync_minor);
+
+ {
+ AUTO_STRING (synchronizeResize, "synchronizeResize");
+ AUTO_STRING (SynchronizeResize, "SynchronizeResize");
+
+ Lisp_Object value = gui_display_get_resource (dpyinfo,
+ synchronizeResize,
+ SynchronizeResize,
+ Qnil, Qnil);
+
+ if (STRINGP (value)
+ && (!strcmp (SSDATA (value), "false")
+ || !strcmp (SSDATA (value), "off")))
+ dpyinfo->xsync_supported_p = false;
+ }
+#endif
+
+#ifdef HAVE_XINERAMA
+ int xin_event_base, xin_error_base;
+ dpyinfo->xinerama_supported_p
+ = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
+#endif
/* See if a private colormap is requested. */
if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
{
- if (dpyinfo->visual->class == PseudoColor)
+ if (dpyinfo->visual_info.class == PseudoColor)
{
AUTO_STRING (privateColormap, "privateColormap");
AUTO_STRING (PrivateColormap, "PrivateColormap");
@@ -14975,6 +26851,52 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
dpyinfo->visual, AllocNone);
+ /* See if we can construct pixel values from RGB values. */
+ if (dpyinfo->visual_info.class == TrueColor)
+ {
+ get_bits_and_offset (dpyinfo->visual_info.red_mask,
+ &dpyinfo->red_bits, &dpyinfo->red_offset);
+ get_bits_and_offset (dpyinfo->visual_info.blue_mask,
+ &dpyinfo->blue_bits, &dpyinfo->blue_offset);
+ get_bits_and_offset (dpyinfo->visual_info.green_mask,
+ &dpyinfo->green_bits, &dpyinfo->green_offset);
+
+#ifdef HAVE_XRENDER
+ if (dpyinfo->pict_format)
+ {
+ unsigned long channel_mask
+ = ((unsigned long) dpyinfo->pict_format->direct.alphaMask
+ << dpyinfo->pict_format->direct.alpha);
+
+ if (channel_mask)
+ get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits,
+ &dpyinfo->alpha_offset);
+ dpyinfo->alpha_mask = channel_mask;
+ }
+ else
+#endif
+ {
+ XColor xc;
+ unsigned long alpha_mask;
+ xc.red = 65535;
+ xc.green = 65535;
+ xc.blue = 65535;
+
+ if (XAllocColor (dpyinfo->display,
+ dpyinfo->cmap, &xc) != 0)
+ {
+ alpha_mask = xc.pixel & ~(dpyinfo->visual_info.red_mask
+ | dpyinfo->visual_info.blue_mask
+ | dpyinfo->visual_info.green_mask);
+
+ if (alpha_mask)
+ get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits,
+ &dpyinfo->alpha_offset);
+ dpyinfo->alpha_mask = alpha_mask;
+ }
+ }
+ }
+
#ifdef HAVE_XDBE
dpyinfo->supports_xdbe = false;
int xdbe_major;
@@ -14983,47 +26905,224 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->supports_xdbe = true;
#endif
+#ifdef USE_XCB
+ xcb_screen_t *xcb_screen = NULL;
+ xcb_screen_iterator_t iter;
+ xcb_visualid_t wanted = { XVisualIDFromVisual (dpyinfo->visual) };
+ xcb_depth_iterator_t depth_iter;
+ xcb_visualtype_iterator_t visual_iter;
+
+ int screen = DefaultScreen (dpyinfo->display);
+
+ iter = xcb_setup_roots_iterator (xcb_get_setup (dpyinfo->xcb_connection));
+ for (; iter.rem; --screen, xcb_screen_next (&iter))
+ {
+ if (!screen)
+ xcb_screen = iter.data;
+ }
+
+ if (xcb_screen)
+ {
+ depth_iter = xcb_screen_allowed_depths_iterator (xcb_screen);
+ for (; depth_iter.rem; xcb_depth_next (&depth_iter))
+ {
+ visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
+ for (; visual_iter.rem; xcb_visualtype_next (&visual_iter))
+ {
+ if (wanted == visual_iter.data->visual_id)
+ {
+ dpyinfo->xcb_visual = visual_iter.data;
+ break;
+ }
+ }
+ }
+ }
+#endif
+
#ifdef HAVE_XINPUT2
dpyinfo->supports_xi2 = false;
int rc;
int major = 2;
-#ifdef XI_GesturePinchBegin /* XInput 2.4 */
+ int xi_first_event, xi_first_error;
+
+#ifndef HAVE_GTK3
+ {
+ AUTO_STRING (disableInputExtension, "disableInputExtension");
+ AUTO_STRING (DisableInputExtension, "DisableInputExtension");
+
+ Lisp_Object value = gui_display_get_resource (dpyinfo,
+ disableInputExtension,
+ DisableInputExtension,
+ Qnil, Qnil);
+
+ if (STRINGP (value)
+ && (!strcmp (SSDATA (value), "on")
+ || !strcmp (SSDATA (value), "true")))
+ goto skip_xi_setup;
+ }
+#endif
+
+#ifdef HAVE_XINPUT2_4
int minor = 4;
-#elif XI_BarrierHit /* XInput 2.3 */
+#elif defined HAVE_XINPUT2_3 /* XInput 2.3 */
int minor = 3;
-#elif defined XI_TouchBegin /* XInput 2.2 */
+#elif defined HAVE_XINPUT2_2 /* XInput 2.2 */
int minor = 2;
-#elif defined XIScrollClass /* XInput 2.1 */
+#elif defined HAVE_XINPUT2_1 /* XInput 2.1 */
int minor = 1;
#else /* Some old version of XI2 we're not interested in. */
int minor = 0;
#endif
- int fer, fee;
if (XQueryExtension (dpyinfo->display, "XInputExtension",
- &dpyinfo->xi2_opcode, &fer, &fee))
+ &dpyinfo->xi2_opcode, &xi_first_event,
+ &xi_first_error))
{
+#ifdef HAVE_GTK3
+ bool move_backwards = false;
+ int original_minor = minor;
+
+ query:
+
+ /* Catch errors caused by GTK requesting a different version of
+ XInput 2 than what Emacs was built with. Usually, the X
+ server tolerates these mistakes, but a BadValue error can
+ result if only one of GTK or Emacs wasn't built with support
+ for XInput 2.2.
+
+ To work around the first, it suffices to increase the minor
+ version until the X server is happy if the XIQueryVersion
+ request results in an error. If that doesn't work, however,
+ then it's the latter, so decrease the minor until the version
+ that GTK requested is found. */
+#endif
+
+ x_catch_errors (dpyinfo->display);
+
rc = XIQueryVersion (dpyinfo->display, &major, &minor);
+
+#ifdef HAVE_GTK3
+ /* Increase the minor version until we find one the X
+ server agrees with. If that didn't work, then
+ decrease the version until it either hits zero or
+ becomes agreeable to the X server. */
+
+ if (x_had_errors_p (dpyinfo->display))
+ {
+ x_uncatch_errors_after_check ();
+
+ /* Since BadValue errors can't be generated if both the
+ prior and current requests specify a version of 2.2 or
+ later, this means the prior request specified a version
+ of the input extension less than 2.2. */
+ if (minor >= 2)
+ {
+ move_backwards = true;
+ minor = original_minor;
+
+ if (--minor < 0)
+ rc = BadRequest;
+ else
+ goto query;
+ }
+ else
+ {
+ if (!move_backwards)
+ {
+ minor++;
+ goto query;
+ }
+
+ if (--minor < 0)
+ rc = BadRequest;
+ else
+ goto query;
+
+ }
+ }
+ else
+ x_uncatch_errors_after_check ();
+
+ /* But don't delude ourselves into thinking that we can use
+ features provided by a version of the input extension that
+ libXi itself doesn't support. */
+
+ if (minor > original_minor)
+ minor = original_minor;
+#else
+ if (x_had_errors_p (dpyinfo->display))
+ rc = BadRequest;
+
+ x_uncatch_errors_after_check ();
+#endif
+
if (rc == Success)
{
dpyinfo->supports_xi2 = true;
x_init_master_valuators (dpyinfo);
}
}
+
dpyinfo->xi2_version = minor;
+#ifndef HAVE_GTK3
+ skip_xi_setup:
+#endif
+ ;
+#endif
+
+#if defined HAVE_XRANDR || defined USE_GTK
+ Lisp_Object term;
+
+ XSETTERMINAL (term, terminal);
#endif
#ifdef HAVE_XRANDR
- int xrr_event_base, xrr_error_base;
- bool xrr_ok = false;
- xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
- if (xrr_ok)
+ dpyinfo->xrandr_supported_p
+ = XRRQueryExtension (dpy, &dpyinfo->xrandr_event_base,
+ &dpyinfo->xrandr_error_base);
+
+#ifndef USE_GTK
+ dpyinfo->last_monitor_attributes_list = Qnil;
+#endif
+
+ if (dpyinfo->xrandr_supported_p)
{
XRRQueryVersion (dpy, &dpyinfo->xrandr_major_version,
&dpyinfo->xrandr_minor_version);
+
+#ifndef USE_GTK
+ if (dpyinfo->xrandr_major_version == 1
+ && dpyinfo->xrandr_minor_version >= 2)
+ {
+ XRRSelectInput (dpyinfo->display,
+ dpyinfo->root_window,
+ (RRScreenChangeNotifyMask
+ | RRCrtcChangeNotifyMask
+ | RROutputChangeNotifyMask
+ /* Emacs doesn't actually need this, but GTK
+ selects for it when the display is
+ initialized. */
+ | RROutputPropertyNotifyMask));
+
+ dpyinfo->last_monitor_attributes_list
+ = Fx_display_monitor_attributes_list (term);
+ }
+#endif
}
#endif
+#ifdef USE_GTK
+ dpyinfo->last_monitor_attributes_list
+ = Fx_display_monitor_attributes_list (term);
+
+ gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
+ gscr = gdk_display_get_default_screen (gdpy);
+
+ g_signal_connect (G_OBJECT (gscr), "monitors-changed",
+ G_CALLBACK (x_monitors_changed_cb),
+ NULL);
+#endif
+
#ifdef HAVE_XKB
int xkb_major, xkb_minor, xkb_op, xkb_error_code;
xkb_major = XkbMajorVersion;
@@ -15046,14 +27145,24 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XkbGroupNamesMask | XkbVirtualModNamesMask,
dpyinfo->xkb_desc);
- XkbSelectEvents (dpyinfo->display,
- XkbUseCoreKbd,
+ XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd,
XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
}
+#endif
- /* Figure out which modifier bits mean what. */
- x_find_modifier_meanings (dpyinfo);
+#ifdef HAVE_XFIXES
+ int xfixes_event_base, xfixes_error_base;
+ dpyinfo->xfixes_supported_p
+ = XFixesQueryExtension (dpyinfo->display, &xfixes_event_base,
+ &xfixes_error_base);
+
+ if (dpyinfo->xfixes_supported_p)
+ {
+ if (!XFixesQueryVersion (dpyinfo->display, &dpyinfo->xfixes_major,
+ &dpyinfo->xfixes_minor))
+ dpyinfo->xfixes_supported_p = false;
+ }
#endif
#if defined USE_CAIRO || defined HAVE_XFT
@@ -15072,11 +27181,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
or larger than other for other applications, even if it is the same
font name (monospace-10 for example). */
-# ifdef HAVE_XRENDER
- int event_base, error_base;
- XRenderQueryExtension (dpyinfo->display, &event_base, &error_base);
-# endif
-
char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
double d;
if (v != NULL && sscanf (v, "%lf", &d) == 1)
@@ -15097,84 +27201,14 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
}
- {
- static const struct
- {
- const char *name;
- int offset;
- } atom_refs[] = {
-#define ATOM_REFS_INIT(string, member) \
- { string, offsetof (struct x_display_info, member) },
- ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
- ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
- ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
- ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
- ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
- ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
- ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
- ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
- ATOM_REFS_INIT ("Editres", Xatom_editres)
- ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
- ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
- ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
- ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
- ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
- ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
- ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
- ATOM_REFS_INIT ("INCR", Xatom_INCR)
- ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
- ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
- ATOM_REFS_INIT ("NULL", Xatom_NULL)
- ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
- ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
- ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
- ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
- /* For properties of font. */
- ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
- ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
- ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
- ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
- ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
- /* Ghostscript support. */
- ATOM_REFS_INIT ("DONE", Xatom_DONE)
- ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
- ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
- ATOM_REFS_INIT ("HORIZONTAL_SCROLLBAR", Xatom_Horizontal_Scrollbar)
- ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
- /* EWMH */
- ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
- ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
- ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
- Xatom_net_wm_state_maximized_horz)
- ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
- Xatom_net_wm_state_maximized_vert)
- ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
- ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
- ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
- ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
- Xatom_net_window_type_tooltip)
- ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
- ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
- ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
- ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
- ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
- ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
- ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
- ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
- ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
- /* Session management */
- ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
- ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
- ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
- ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
- ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
- ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
- };
+ sprintf (cm_atom_sprintf, cm_atom_fmt,
+ XScreenNumberOfScreen (dpyinfo->screen));
+ {
int i;
- enum { atom_count = ARRAYELTS (atom_refs) };
+ enum { atom_count = ARRAYELTS (x_atom_refs) };
/* 1 for _XSETTINGS_SN. */
- enum { total_atom_count = 1 + atom_count };
+ enum { total_atom_count = 2 + atom_count };
Atom atoms_return[total_atom_count];
char *atom_names[total_atom_count];
static char const xsettings_fmt[] = "_XSETTINGS_S%d";
@@ -15182,24 +27216,31 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
+ INT_STRLEN_BOUND (int)];
for (i = 0; i < atom_count; i++)
- atom_names[i] = (char *) atom_refs[i].name;
+ atom_names[i] = (char *) x_atom_refs[i].name;
/* Build _XSETTINGS_SN atom name. */
sprintf (xsettings_atom_name, xsettings_fmt,
XScreenNumberOfScreen (dpyinfo->screen));
atom_names[i] = xsettings_atom_name;
+ atom_names[i + 1] = cm_atom_sprintf;
XInternAtoms (dpyinfo->display, atom_names, total_atom_count,
False, atoms_return);
for (i = 0; i < atom_count; i++)
- *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
+ *(Atom *) ((char *) dpyinfo + x_atom_refs[i].offset) = atoms_return[i];
- /* Manually copy last atom. */
+ /* Manually copy last two atoms. */
dpyinfo->Xatom_xsettings_sel = atoms_return[i];
+ dpyinfo->Xatom_NET_WM_CM_Sn = atoms_return[i + 1];
}
- dpyinfo->x_dnd_atoms_size = 8;
+#ifdef HAVE_XKB
+ /* Figure out which modifier bits mean what. */
+ x_find_modifier_meanings (dpyinfo);
+#endif
+
+ dpyinfo->x_dnd_atoms_size = 16;
dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
* dpyinfo->x_dnd_atoms_size);
dpyinfo->gray
@@ -15207,7 +27248,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
gray_bits, gray_width, gray_height,
1, 0, 1);
- x_setup_pointer_blanking (dpyinfo);
+ dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
+#ifdef HAVE_XFIXES
+ dpyinfo->fixes_pointer_blanking = egetenv ("EMACS_XFIXES");
+#endif
#ifdef HAVE_X_I18N
xim_initialize (dpyinfo, resource_name);
@@ -15280,13 +27324,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
#endif
}
+#ifdef HAVE_X_I18N
{
AUTO_STRING (inputStyle, "inputStyle");
AUTO_STRING (InputStyle, "InputStyle");
Lisp_Object value = gui_display_get_resource (dpyinfo, inputStyle, InputStyle,
Qnil, Qnil);
-#ifdef HAVE_X_I18N
if (STRINGP (value))
{
if (!strcmp (SSDATA (value), "callback"))
@@ -15299,27 +27343,84 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo->preferred_xim_style = STYLE_OFFTHESPOT;
else if (!strcmp (SSDATA (value), "root"))
dpyinfo->preferred_xim_style = STYLE_ROOT;
- }
+#ifdef USE_GTK
+ else if (!strcmp (SSDATA (value), "native"))
+ dpyinfo->prefer_native_input = true;
#endif
+ }
}
+#endif
#ifdef HAVE_X_SM
/* Only do this for the very first display in the Emacs session.
Ignore X session management when Emacs was first started on a
tty or started as a daemon. */
- if (terminal->id == 1 && ! IS_DAEMON)
+ if (!dpyinfo->next && ! IS_DAEMON)
x_session_initialize (dpyinfo);
#endif
-#ifdef USE_CAIRO
+#if defined USE_CAIRO || defined HAVE_XRENDER
x_extension_initialize (dpyinfo);
#endif
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ dpyinfo->protected_windows = xmalloc (sizeof (Lisp_Object) * 256);
+ dpyinfo->n_protected_windows = 0;
+ dpyinfo->protected_windows_max = 256;
+#endif
+
unblock_input ();
return dpyinfo;
}
+
+
+/* Remove all the selection input events on the keyboard buffer
+ intended for DPYINFO. */
+
+static void
+x_delete_selection_requests (struct x_display_info *dpyinfo)
+{
+ union buffered_input_event *event;
+ int moved_events;
+
+ for (event = kbd_fetch_ptr; event != kbd_store_ptr;
+ event = X_NEXT_KBD_EVENT (event))
+ {
+ if (event->kind == SELECTION_REQUEST_EVENT
+ || event->kind == SELECTION_CLEAR_EVENT)
+ {
+ if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo)
+ continue;
+
+ /* Remove the event from the fifo buffer before processing;
+ otherwise swallow_events called recursively could see it
+ and process it again. To do this, we move the events
+ between kbd_fetch_ptr and EVENT one slot to the right,
+ cyclically. */
+
+ if (event < kbd_fetch_ptr)
+ {
+ memmove (kbd_buffer + 1, kbd_buffer,
+ (event - kbd_buffer) * sizeof *kbd_buffer);
+ kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
+ moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
+ }
+ else
+ moved_events = event - kbd_fetch_ptr;
+
+ memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
+ moved_events * sizeof *kbd_fetch_ptr);
+ kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr);
+
+ /* `detect_input_pending' will then recompute whether or not
+ pending input events exist. */
+ input_pending = false;
+ }
+ }
+}
+
/* Get rid of display DPYINFO, deleting all frames on it,
and without sending any more commands to the X server. */
@@ -15328,6 +27429,8 @@ x_delete_display (struct x_display_info *dpyinfo)
{
struct terminal *t;
struct color_name_cache_entry *color_entry, *next_color_entry;
+ int i;
+ struct x_selection_request_event *ie, *last, *temp;
/* Close all frames and delete the generic struct terminal for this
X display. */
@@ -15343,9 +27446,38 @@ x_delete_display (struct x_display_info *dpyinfo)
break;
}
+ /* Find any pending selection requests for this display and unchain
+ them. */
+
+ last = NULL;
+
+ for (ie = pending_selection_requests; ie; ie = ie->next)
+ {
+ again:
+
+ if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo)
+ {
+ if (last)
+ last->next = ie->next;
+
+ temp = ie;
+ ie = ie->next;
+ xfree (temp);
+
+ goto again;
+ }
+
+ last = ie;
+ }
+
+ x_delete_selection_requests (dpyinfo);
+
if (next_noop_dpyinfo == dpyinfo)
next_noop_dpyinfo = dpyinfo->next;
+ if (mouse_click_timeout_display == dpyinfo)
+ mouse_click_timeout_display = NULL;
+
if (x_display_list == dpyinfo)
x_display_list = dpyinfo->next;
else
@@ -15357,18 +27489,30 @@ x_delete_display (struct x_display_info *dpyinfo)
tail->next = tail->next->next;
}
- for (color_entry = dpyinfo->color_names;
- color_entry;
- color_entry = next_color_entry)
+ for (i = 0; i < dpyinfo->color_names_size; ++i)
{
- next_color_entry = color_entry->next;
- xfree (color_entry->name);
- xfree (color_entry);
+ for (color_entry = dpyinfo->color_names[i];
+ color_entry; color_entry = next_color_entry)
+ {
+ next_color_entry = color_entry->next;
+
+ xfree (color_entry->name);
+ xfree (color_entry);
+ }
}
+ xfree (dpyinfo->color_names);
+ xfree (dpyinfo->color_names_length);
xfree (dpyinfo->x_id_name);
xfree (dpyinfo->x_dnd_atoms);
xfree (dpyinfo->color_cells);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ xfree (dpyinfo->protected_windows);
+#endif
+#ifdef HAVE_XINPUT2
+ if (dpyinfo->supports_xi2)
+ x_free_xi_devices (dpyinfo);
+#endif
xfree (dpyinfo);
}
@@ -15485,6 +27629,28 @@ x_delete_terminal (struct terminal *terminal)
image_destroy_all_bitmaps (dpyinfo);
XSetCloseDownMode (dpyinfo->display, DestroyAll);
+ /* Get rid of any drag-and-drop operation that might be in
+ progress as well. */
+ if ((x_dnd_in_progress || x_dnd_waiting_for_finish)
+ && dpyinfo->display == (x_dnd_waiting_for_finish
+ ? x_dnd_finish_display
+ : FRAME_X_DISPLAY (x_dnd_frame)))
+ {
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_waiting_for_finish = false;
+
+ /* The display is going away, so there's no point in
+ de-selecting for input on the DND toplevels. */
+ if (x_dnd_use_toplevels)
+ x_dnd_free_toplevels (false);
+
+ x_dnd_return_frame_object = NULL;
+ x_dnd_movement_frame = NULL;
+ x_dnd_frame = NULL;
+ }
+
/* Whether or not XCloseDisplay destroys the associated resource
database depends on the version of libX11. To avoid both
crash and memory leak, we dissociate the database from the
@@ -15515,10 +27681,6 @@ x_delete_terminal (struct terminal *terminal)
if (dpyinfo->xkb_desc)
XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True);
#endif
-#ifdef HAVE_XINPUT2
- if (dpyinfo->supports_xi2)
- x_free_xi_devices (dpyinfo);
-#endif
#ifdef USE_GTK
xg_display_close (dpyinfo->display);
#else
@@ -15528,6 +27690,9 @@ x_delete_terminal (struct terminal *terminal)
XCloseDisplay (dpyinfo->display);
#endif
#endif /* ! USE_GTK */
+
+ if (dpyinfo->modmap)
+ XFreeModifiermap (dpyinfo->modmap);
/* Do not close the connection here because it's already closed
by X(t)CloseDisplay (Bug#18403). */
dpyinfo->display = NULL;
@@ -15549,6 +27714,25 @@ x_delete_terminal (struct terminal *terminal)
unblock_input ();
}
+#ifdef HAVE_XINPUT2
+static bool
+x_have_any_grab (struct x_display_info *dpyinfo)
+{
+ int i;
+
+ if (!dpyinfo->supports_xi2)
+ return false;
+
+ for (i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ if (dpyinfo->devices[i].grab)
+ return true;
+ }
+
+ return false;
+}
+#endif
+
/* Create a struct terminal, initialize it with the X11 specific
functions and make DISPLAY->TERMINAL point to it. */
@@ -15573,7 +27757,9 @@ x_create_terminal (struct x_display_info *dpyinfo)
terminal->update_end_hook = x_update_end;
terminal->read_socket_hook = XTread_socket;
terminal->frame_up_to_date_hook = XTframe_up_to_date;
+#ifdef HAVE_XDBE
terminal->buffer_flipping_unblocked_hook = XTbuffer_flipping_unblocked_hook;
+#endif
terminal->defined_color_hook = x_defined_color;
terminal->query_frame_background_color = x_query_frame_background_color;
terminal->query_colors = x_query_colors;
@@ -15613,6 +27799,10 @@ x_create_terminal (struct x_display_info *dpyinfo)
terminal->free_pixmap = x_free_pixmap;
terminal->delete_frame_hook = x_destroy_window;
terminal->delete_terminal_hook = x_delete_terminal;
+ terminal->toolkit_position_hook = x_toolkit_position;
+#ifdef HAVE_XINPUT2
+ terminal->any_grab_hook = x_have_any_grab;
+#endif
/* Other hooks are NULL by default. */
return terminal;
@@ -15626,6 +27816,7 @@ x_initialize (void)
x_noop_count = 0;
any_help_event_p = false;
ignore_next_mouse_click_timeout = 0;
+ mouse_click_timeout_display = NULL;
#ifdef USE_GTK
current_count = -1;
@@ -15682,19 +27873,107 @@ init_xterm (void)
/* Emacs can handle only core input events when built without XI2
support, so make sure Gtk doesn't use Xinput or Xinput2
extensions. */
+#ifndef HAVE_GTK3
xputenv ("GDK_CORE_DEVICE_EVENTS=1");
+#else
+ gdk_disable_multidevice ();
+#endif
#endif
}
#endif
void
+mark_xterm (void)
+{
+ Lisp_Object val;
+#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS
+ struct x_display_info *dpyinfo;
+ int i;
+#endif
+
+ if (x_dnd_return_frame_object)
+ {
+ XSETFRAME (val, x_dnd_return_frame_object);
+ mark_object (val);
+ }
+
+ if (x_dnd_movement_frame)
+ {
+ XSETFRAME (val, x_dnd_movement_frame);
+ mark_object (val);
+ }
+
+#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
+ || defined HAVE_XRANDR || defined USE_GTK
+ for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+ {
+#ifdef HAVE_XINPUT2
+ for (i = 0; i < dpyinfo->num_devices; ++i)
+ mark_object (dpyinfo->devices[i].name);
+#endif
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ for (i = 0; i < dpyinfo->n_protected_windows; ++i)
+ mark_object (dpyinfo->protected_windows[i]);
+#endif
+#if defined HAVE_XRANDR || defined USE_GTK
+ mark_object (dpyinfo->last_monitor_attributes_list);
+#endif
+ }
+#endif
+}
+
+/* Error handling functions for Lisp functions that expose X protocol
+ requests. They are mostly like `x_catch_errors' and friends, but
+ respect `x-fast-protocol-requests'. */
+
+void
+x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
+{
+ if (!x_fast_protocol_requests)
+ x_catch_errors (dpyinfo->display);
+ else
+ x_ignore_errors_for_next_request (dpyinfo);
+}
+
+void
+x_check_errors_for_lisp (struct x_display_info *dpyinfo,
+ const char *format)
+{
+ if (!x_fast_protocol_requests)
+ x_check_errors (dpyinfo->display, format);
+}
+
+void
+x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo)
+{
+ if (!x_fast_protocol_requests)
+ x_uncatch_errors ();
+ else
+ x_stop_ignoring_errors (dpyinfo);
+}
+
+void
syms_of_xterm (void)
{
x_error_message = NULL;
PDUMPER_IGNORE (x_error_message);
+ x_dnd_monitors = Qnil;
+ staticpro (&x_dnd_monitors);
+
+ x_dnd_action_symbol = Qnil;
+ staticpro (&x_dnd_action_symbol);
+
+ x_dnd_selection_alias_cell = Fcons (Qnil, Qnil);
+ staticpro (&x_dnd_selection_alias_cell);
+
+ x_dnd_unsupported_drop_data = Qnil;
+ staticpro (&x_dnd_unsupported_drop_data);
+
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFSYM (Qlatin_1, "latin-1");
+ DEFSYM (Qnow, "now");
+ DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
#ifdef USE_GTK
xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
@@ -15732,9 +28011,21 @@ This variable is used only when the window manager requires that you
click on a frame to select it (give it focus). In that case, a value
of nil, means that the selected window and cursor position changes to
reflect the mouse click position, while a non-nil value means that the
-selected window or cursor position is preserved. */);
+selected window or cursor position is preserved.
+
+This option works by ignoring button press events for a given amount
+of time after a frame might've been focused. If it does not work for
+you, try increasing the value of
+`x-mouse-click-focus-ignore-time'. */);
x_mouse_click_focus_ignore_position = false;
+ DEFVAR_INT ("x-mouse-click-focus-ignore-time", x_mouse_click_focus_ignore_time,
+ doc: /* Number of miliseconds for which to ignore buttons after focus change.
+This variable only takes effect if
+`x-mouse-click-focus-ignore-position' is non-nil, and should be
+adjusted if the default value does not work for whatever reason. */);
+ x_mouse_click_focus_ignore_time = 200;
+
DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
doc: /* Which toolkit scroll bars Emacs uses, if any.
A value of nil means Emacs doesn't use toolkit scroll bars.
@@ -15766,6 +28057,8 @@ With MS Windows, Haiku windowing or Nextstep, the value is t. */);
Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
DEFSYM (Qsuper, "super");
Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
+ DEFSYM (QXdndSelection, "XdndSelection");
+ DEFSYM (Qx_selection_alias_alist, "x-selection-alias-alist");
DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
doc: /* Which keys Emacs uses for the ctrl modifier.
@@ -15846,4 +28139,131 @@ always uses gtk_window_move and ignores the value of this variable. */);
This option is only effective when Emacs is built with XInput 2
support. */);
Vx_scroll_event_delta_factor = make_float (1.0);
+ DEFSYM (Qexpose, "expose");
+
+ DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
+ doc: /* Non-nil means to use GTK for input method support.
+This provides better support for some modern input methods, and is
+only effective when Emacs is built with GTK. */);
+ x_gtk_use_native_input = false;
+
+ DEFVAR_LISP ("x-set-frame-visibility-more-laxly",
+ x_set_frame_visibility_more_laxly,
+ doc: /* Non-nil means set frame visibility more laxly.
+If this is nil, Emacs is more strict when marking a frame as visible.
+Since this may cause problems on some window managers, this variable can
+be also set as follows: The value `focus-in' means to mark a frame as
+visible also when a FocusIn event is received for it on GTK builds. The
+value `expose' means to mark a frame as visible also when an Expose
+event is received for it on any X build. The value `t' means to mark a
+frame as visible in either of these two cases.
+
+Note that any non-nil setting may cause invisible frames get erroneously
+reported as iconified. */);
+ x_set_frame_visibility_more_laxly = Qnil;
+
+ DEFVAR_BOOL ("x-input-grab-touch-events", x_input_grab_touch_events,
+ doc: /* Non-nil means to actively grab touch events.
+This means touch sequences that started on an Emacs frame will
+reliably continue to receive updates even if the finger moves off the
+frame, but may cause crashes with some window managers and/or external
+programs. */);
+ x_input_grab_touch_events = true;
+
+ DEFVAR_BOOL ("x-dnd-fix-motif-leave", x_dnd_fix_motif_leave,
+ doc: /* Work around Motif bug during drag-and-drop.
+When non-nil, Emacs will send a motion event containing impossible
+coordinates to a Motif drop receiver when the mouse moves outside it
+during a drag-and-drop session, to work around broken implementations
+of Motif. */);
+ x_dnd_fix_motif_leave = true;
+
+ DEFVAR_BOOL ("x-dnd-disable-motif-drag", x_dnd_disable_motif_drag,
+ doc: /* Disable the Motif drag protocol during DND.
+This reduces network usage, but also means you can no longer scroll
+around inside the Motif window underneath the cursor during
+drag-and-drop. */);
+ x_dnd_disable_motif_drag = false;
+
+ DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function,
+ doc: /* Function called upon mouse movement on a frame during drag-and-drop.
+It should either be nil, or accept two arguments FRAME and POSITION,
+where FRAME is the frame the mouse is on top of, and POSITION is a
+mouse position list. */);
+ Vx_dnd_movement_function = Qnil;
+
+ DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function,
+ doc: /* Function called when trying to drop on an unsupported window.
+This function is called whenever the user tries to drop something on a
+window that does not support either the XDND or Motif protocols for
+drag-and-drop. It should return a non-nil value if the drop was
+handled by the function, and nil if it was not. It should accept
+several arguments TARGETS, X, Y, ACTION, WINDOW-ID, FRAME, TIME and
+LOCAL-SELECTION, where TARGETS is the list of targets that was passed
+to `x-begin-drag', WINDOW-ID is the numeric XID of the window that is
+being dropped on, X and Y are the root window-relative coordinates
+where the drop happened, ACTION is the action that was passed to
+`x-begin-drag', FRAME is the frame which initiated the drag-and-drop
+operation, TIME is the X server time when the drop happened, and
+LOCAL-SELECTION is the contents of the `XdndSelection' when
+`x-begin-drag' was run; its contents can be retrieved by calling the
+function `x-get-local-selection'.
+
+If a symbol is returned, then it will be used as the return value of
+`x-begin-drag'. */);
+ Vx_dnd_unsupported_drop_function = Qnil;
+
+ DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size,
+ doc: /* Max number of buckets allowed per display in the internal color cache.
+Values less than 1 mean 128. This option is for debugging only. */);
+ x_color_cache_bucket_size = 128;
+
+ DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list,
+ doc: /* List of drag-and-drop targets.
+This variable contains the list of drag-and-drop selection targets
+during a drag-and-drop operation, in the same format as the TARGET
+argument to `x-begin-drag'. */);
+ Vx_dnd_targets_list = Qnil;
+
+ DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function,
+ doc: /* Function that determines return value of drag-and-drop on Emacs frames.
+If the value is a function, `x-begin-drag' will call it with two
+arguments, POS and ACTION, where POS is a mouse position list
+that specifies the location of the drop, and ACTION is the
+action specified by the caller of `x-begin-drag'. The function
+should return a symbol describing what to return from
+`x-begin-drag' if the drop happens on an Emacs frame.
+
+If the value is nil, or the function returns a value that is not
+a symbol, a drop on an Emacs frame will be canceled. */);
+ Vx_dnd_native_test_function = Qnil;
+
+ DEFVAR_BOOL ("x-dnd-preserve-selection-data", x_dnd_preserve_selection_data,
+ doc: /* Preserve selection data after `x-begin-drag' returns.
+This lets you inspect the contents of `XdndSelection' after a
+drag-and-drop operation, which is useful when writing tests for
+drag-and-drop code. */);
+ x_dnd_preserve_selection_data = false;
+
+ DEFVAR_BOOL ("x-dnd-disable-motif-protocol", x_dnd_disable_motif_protocol,
+ doc: /* Disable the Motif drag-and-drop protocols.
+When non-nil, `x-begin-drag' will not drop onto any window that only
+supports the Motif drag-and-drop protocols. */);
+ x_dnd_disable_motif_protocol = false;
+
+ DEFVAR_BOOL ("x-dnd-use-unsupported-drop", x_dnd_use_unsupported_drop,
+ doc: /* Enable the emulation of drag-and-drop based on the primary selection.
+When nil, do not use the primary selection and synthetic mouse clicks
+to emulate the drag-and-drop of `STRING', `UTF8_STRING',
+`COMPOUND_TEXT' or `TEXT'. */);
+ x_dnd_use_unsupported_drop = true;
+
+ DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests,
+ doc: /* Whether or not X protocol-related functions should wait for errors.
+When this is nil, functions such as `x-delete-window-property',
+`x-change-window-property' and `x-send-client-message' will wait for a
+reply from the X server, and signal any errors that occurred while
+executing the protocol request. Otherwise, errors will be silently
+ignored without waiting, which is generally faster. */);
+ x_fast_protocol_requests = false;
}
diff --git a/src/xterm.h b/src/xterm.h
index a796f69ddc1..92e88bb50fa 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -32,6 +32,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/Xatom.h>
#include <X11/Xresource.h>
+#ifdef HAVE_XINPUT2
+#include <X11/extensions/XInput2.h>
+#endif
+
#ifdef USE_X_TOOLKIT
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h> /* CoreP.h needs this */
@@ -54,6 +58,10 @@ typedef Widget xt_or_gtk_widget;
#define GTK_CHECK_VERSION(i, j, k) false
#endif
+#ifdef HAVE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
+
#ifdef USE_GTK
/* Some definitions to reduce conditionals. */
typedef GtkWidget *xt_or_gtk_widget;
@@ -67,6 +75,9 @@ typedef GtkWidget *xt_or_gtk_widget;
#endif
#endif /* USE_GTK */
+/* Number of "failable requests" to store. */
+#define N_FAILABLE_REQUESTS 128
+
#ifdef USE_CAIRO
#include <cairo-xlib.h>
#ifdef CAIRO_HAS_PDF_SURFACE
@@ -78,6 +89,9 @@ typedef GtkWidget *xt_or_gtk_widget;
#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
#endif
+#ifdef USE_CAIRO_XCB
+#include <cairo-xcb.h>
+#endif
#endif
#ifdef HAVE_X_I18N
@@ -92,6 +106,10 @@ typedef GtkWidget *xt_or_gtk_widget;
#include <X11/XKBlib.h>
#endif
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
#include "dispextern.h"
#include "termhooks.h"
@@ -117,6 +135,7 @@ INLINE_HEADER_BEGIN
| FocusChangeMask \
| LeaveWindowMask \
| EnterWindowMask \
+ | PropertyChangeMask \
| VisibilityChangeMask)
#ifdef HAVE_X11R6_XIM
@@ -128,6 +147,21 @@ struct xim_inst_t
};
#endif /* HAVE_X11R6_XIM */
+#ifdef HAVE_XINPUT2
+#if HAVE_XISCROLLCLASSINFO_TYPE && defined XIScrollClass
+#define HAVE_XINPUT2_1
+#endif
+#if HAVE_XITOUCHCLASSINFO_TYPE && defined XITouchClass
+#define HAVE_XINPUT2_2
+#endif
+#if HAVE_XIBARRIERRELEASEPOINTERINFO_DEVICEID && defined XIBarrierPointerReleased
+#define HAVE_XINPUT2_3
+#endif
+#if HAVE_XIGESTURECLASSINFO_TYPE && defined XIGestureClass
+#define HAVE_XINPUT2_4
+#endif
+#endif
+
/* Structure recording X pixmap and reference count.
If REFCOUNT is 0 then this record is free to be reused. */
@@ -145,7 +179,7 @@ struct x_bitmap_record
int height, width, depth;
};
-#ifdef USE_CAIRO
+#if defined USE_CAIRO || defined HAVE_XRENDER
struct x_gc_ext_data
{
#define MAX_CLIP_RECTS 2
@@ -155,7 +189,9 @@ struct x_gc_ext_data
/* Clipping rectangles. */
XRectangle clip_rects[MAX_CLIP_RECTS];
};
+#endif
+#ifdef USE_CAIRO
extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap);
#endif
@@ -163,14 +199,24 @@ extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap);
struct color_name_cache_entry
{
struct color_name_cache_entry *next;
+
+ /* The color values of the cached color entry. */
XColor rgb;
+
+ /* The name of the cached color. */
char *name;
+
+ /* Whether or not RGB is valid (i.e. the color actually exists). */
+ bool_bf valid : 1;
};
#ifdef HAVE_XINPUT2
+
+#ifdef HAVE_XINPUT2_1
struct xi_scroll_valuator_t
{
bool invalid_p;
+ bool pending_enter_reset;
double current_value;
double emacs_value;
double increment;
@@ -178,7 +224,9 @@ struct xi_scroll_valuator_t
int number;
int horizontal;
};
+#endif
+#ifdef HAVE_XINPUT2_2
struct xi_touch_point_t
{
struct xi_touch_point_t *next;
@@ -186,23 +234,43 @@ struct xi_touch_point_t
int number;
double x, y;
};
+#endif
struct xi_device_t
{
int device_id;
+#ifdef HAVE_XINPUT2_1
int scroll_valuator_count;
- int grab;
- bool master_p;
+#endif
+ int grab, use;
+#ifdef HAVE_XINPUT2_2
bool direct_p;
+#endif
+#ifdef HAVE_XINPUT2_1
struct xi_scroll_valuator_t *valuators;
+#endif
+#ifdef HAVE_XINPUT2_2
struct xi_touch_point_t *touchpoints;
+#endif
+
+ Lisp_Object name;
};
#endif
Status x_parse_color (struct frame *f, const char *color_name,
XColor *color);
+struct x_failable_request
+{
+ /* The first request making up this sequence. */
+ unsigned long start;
+
+ /* If this is zero, then the request has not yet been made.
+ Otherwise, this is the request that ends this sequence. */
+ unsigned long end;
+};
+
/* For each X display, we have a structure that records
information about it. */
@@ -236,6 +304,14 @@ struct x_display_info
/* The Visual being used for this display. */
Visual *visual;
+ /* The visual information corresponding to VISUAL. */
+ XVisualInfo visual_info;
+
+#ifdef HAVE_XRENDER
+ /* The picture format for this display. */
+ XRenderPictFormat *pict_format;
+#endif
+
/* The colormap being used. */
Colormap cmap;
@@ -265,8 +341,10 @@ struct x_display_info
Unused if this display supports Xfixes extension. */
Cursor invisible_cursor;
- /* Function used to toggle pointer visibility on this display. */
- void (*toggle_visible_pointer) (struct frame *, bool);
+#ifdef HAVE_XFIXES
+ /* Whether or not to use Xfixes for pointer blanking. */
+ bool fixes_pointer_blanking;
+#endif
#ifdef USE_GTK
/* The GDK cursor for scroll bars and popup menus. */
@@ -341,26 +419,30 @@ struct x_display_info
/* Atom for indicating window state to the window manager. */
Atom Xatom_wm_change_state;
+ Atom Xatom_wm_state;
/* Other WM communication */
Atom Xatom_wm_configure_denied; /* When our config request is denied */
Atom Xatom_wm_window_moved; /* When the WM moves us. */
Atom Xatom_wm_client_leader; /* Id of client leader window. */
+ Atom Xatom_wm_transient_for; /* Id of whatever window we are
+ transient for. */
/* EditRes protocol */
Atom Xatom_editres;
/* More atoms, which are selection types. */
Atom Xatom_CLIPBOARD, Xatom_TIMESTAMP, Xatom_TEXT, Xatom_DELETE,
- Xatom_COMPOUND_TEXT, Xatom_UTF8_STRING,
- Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
- Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER;
+ Xatom_COMPOUND_TEXT, Xatom_UTF8_STRING,
+ Xatom_MULTIPLE, Xatom_INCR, Xatom_EMACS_TMP, Xatom_TARGETS, Xatom_NULL,
+ Xatom_ATOM, Xatom_ATOM_PAIR, Xatom_CLIPBOARD_MANAGER,
+ Xatom_EMACS_SERVER_TIME_PROP;
/* More atoms for font properties. The last three are private
properties, see the comments in src/fontset.h. */
Atom Xatom_PIXEL_SIZE, Xatom_AVERAGE_WIDTH,
- Xatom_MULE_BASELINE_OFFSET, Xatom_MULE_RELATIVE_COMPOSE,
- Xatom_MULE_DEFAULT_ASCENT;
+ Xatom_MULE_BASELINE_OFFSET, Xatom_MULE_RELATIVE_COMPOSE,
+ Xatom_MULE_DEFAULT_ASCENT;
/* More atoms for Ghostscript support. */
Atom Xatom_DONE, Xatom_PAGE;
@@ -371,6 +453,25 @@ struct x_display_info
/* Atom used in XEmbed client messages. */
Atom Xatom_XEMBED, Xatom_XEMBED_INFO;
+ /* Atom used to determine whether or not the screen is composited. */
+ Atom Xatom_NET_WM_CM_Sn;
+
+ /* Atoms used by the Motif drag and drop protocols. */
+ Atom Xatom_MOTIF_WM_HINTS, Xatom_MOTIF_DRAG_WINDOW,
+ Xatom_MOTIF_DRAG_TARGETS, Xatom_MOTIF_DRAG_AND_DROP_MESSAGE,
+ Xatom_MOTIF_DRAG_INITIATOR_INFO, Xatom_MOTIF_DRAG_RECEIVER_INFO;
+
+ /* Atoms used by Emacs internally. */
+ Atom Xatom_EMACS_DRAG_ATOM;
+
+ /* Special selections used by the Motif drop protocol to indicate
+ success or failure. */
+ Atom Xatom_XmTRANSFER_SUCCESS, Xatom_XmTRANSFER_FAILURE;
+
+ /* Atoms used by both versions of the OffiX DND protocol (the "old
+ KDE" protocol in x-dnd.el). */
+ Atom Xatom_DndProtocol, Xatom_DND_PROTOCOL;
+
/* The frame (if any) which has the X window that has keyboard focus.
Zero if none. This is examined by Ffocus_frame in xfns.c. Note
that a mere EnterNotify event can set this; if you need to know the
@@ -406,7 +507,8 @@ struct x_display_info
/* The scroll bar in which the last X motion event occurred. */
struct scroll_bar *last_mouse_scroll_bar;
- /* Time of last user interaction as returned in X events on this display. */
+ /* Time of last user interaction as returned in X events on this
+ display. */
Time last_user_time;
/* Position where the mouse was last time we reported a motion.
@@ -426,6 +528,9 @@ struct x_display_info
received, and return that in hopes that it's somewhat accurate. */
Time last_mouse_movement_time;
+ /* Whether or not the last mouse motion was synthetic. */
+ bool last_mouse_movement_time_send_event;
+
/* The gray pixmap. */
Pixmap gray;
@@ -438,7 +543,13 @@ struct x_display_info
#endif
/* A cache mapping color names to RGB values. */
- struct color_name_cache_entry *color_names;
+ struct color_name_cache_entry **color_names;
+
+ /* The number of buckets for each hash in that hash table. */
+ ptrdiff_t *color_names_length;
+
+ /* The size of that hash table. */
+ int color_names_size;
/* If non-null, a cache of the colors in the color map. Don't
use this directly, call x_color_cells instead. */
@@ -446,8 +557,9 @@ struct x_display_info
int ncolor_cells;
/* Bits and shifts to use to compose pixel values on TrueColor visuals. */
- int red_bits, blue_bits, green_bits;
- int red_offset, blue_offset, green_offset;
+ int red_bits, blue_bits, green_bits, alpha_bits;
+ int red_offset, blue_offset, green_offset, alpha_offset;
+ unsigned long alpha_mask;
/* The type of window manager we have. If we move FRAME_OUTER_WINDOW
to x/y 0/0, some window managers (type A) puts the window manager
@@ -468,6 +580,23 @@ struct x_display_info
ptrdiff_t x_dnd_atoms_size;
ptrdiff_t x_dnd_atoms_length;
+ /* The unique drag and drop atom used on Motif. None if it was not
+ already computed. */
+ Atom motif_drag_atom;
+
+ /* Its name. */
+ char motif_drag_atom_name[sizeof "_EMACS_ATOM_%lu" - 3
+ + INT_STRLEN_BOUND (unsigned long)];
+
+ /* When it was owned. */
+ Time motif_drag_atom_time;
+
+ /* The frame that currently owns `motif_drag_atom'. */
+ struct frame *motif_drag_atom_owner;
+
+ /* The drag window for this display. */
+ Window motif_drag_window;
+
/* Extended window manager hints, Atoms supported by the window manager and
atoms for setting the window type. */
Atom Xatom_net_supported, Xatom_net_supporting_wm_check;
@@ -482,7 +611,12 @@ struct x_display_info
Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, Xatom_net_wm_state_below,
Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
- Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea;
+ Xatom_net_wm_state_shaded, Xatom_net_frame_extents, Xatom_net_current_desktop,
+ Xatom_net_workarea, Xatom_net_wm_opaque_region, Xatom_net_wm_ping,
+ Xatom_net_wm_sync_request, Xatom_net_wm_sync_request_counter,
+ Xatom_net_wm_frame_drawn, Xatom_net_wm_user_time,
+ Xatom_net_wm_user_time_window, Xatom_net_client_list_stacking,
+ Xatom_net_wm_pid;
/* XSettings atoms and windows. */
Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -496,17 +630,46 @@ struct x_display_info
/* SM */
Atom Xatom_SM_CLIENT_ID;
+ /* DND source. */
+ Atom Xatom_XdndAware, Xatom_XdndSelection, Xatom_XdndTypeList,
+ Xatom_XdndActionCopy, Xatom_XdndActionMove, Xatom_XdndActionLink,
+ Xatom_XdndActionAsk, Xatom_XdndActionPrivate, Xatom_XdndActionList,
+ Xatom_XdndActionDescription, Xatom_XdndProxy, Xatom_XdndEnter,
+ Xatom_XdndPosition, Xatom_XdndStatus, Xatom_XdndLeave, Xatom_XdndDrop,
+ Xatom_XdndFinished;
+
+ /* XDS source and target. */
+ Atom Xatom_XdndDirectSave0, Xatom_XdndActionDirectSave, Xatom_text_plain;
+
+#ifdef HAVE_XKB
+ /* Virtual modifiers */
+ Atom Xatom_Meta, Xatom_Super, Xatom_Hyper, Xatom_ShiftLock, Xatom_Alt;
+#endif
+
+ /* Core modifier map when XKB is not present. */
+ XModifierKeymap *modmap;
+
#ifdef HAVE_XRANDR
+ bool xrandr_supported_p;
+ int xrandr_event_base;
+ int xrandr_error_base;
int xrandr_major_version;
int xrandr_minor_version;
#endif
-#ifdef USE_CAIRO
+#if defined HAVE_XRANDR || defined USE_GTK
+ /* This is used to determine if the monitor configuration really
+ changed upon receiving a monitor change event. */
+ Lisp_Object last_monitor_attributes_list;
+#endif
+
+#if defined USE_CAIRO || defined HAVE_XRENDER
XExtCodes *ext_codes;
#endif
#ifdef USE_XCB
xcb_connection_t *xcb_connection;
+ xcb_visualtype_t *xcb_visual;
#endif
#ifdef HAVE_XDBE
@@ -520,6 +683,17 @@ struct x_display_info
int num_devices;
struct xi_device_t *devices;
+
+ Time pending_keystroke_time;
+ int pending_keystroke_source;
+
+#if defined USE_GTK && !defined HAVE_GTK3
+ /* This means the two variables above shouldn't be reset the first
+ time a KeyPress event arrives, since they were set from a raw key
+ press event that was sent before the first (real, not sent by an
+ input method) core key event. */
+ bool pending_keystroke_time_special_p;
+#endif
#endif
#ifdef HAVE_XKB
@@ -527,6 +701,74 @@ struct x_display_info
int xkb_event_type;
XkbDescPtr xkb_desc;
#endif
+
+#ifdef USE_GTK
+ bool prefer_native_input;
+#endif
+
+#ifdef HAVE_XRENDER
+ bool xrender_supported_p;
+ int xrender_major;
+ int xrender_minor;
+#endif
+
+#ifdef HAVE_XFIXES
+ bool xfixes_supported_p;
+ int xfixes_major;
+ int xfixes_minor;
+#endif
+
+#ifdef HAVE_XSYNC
+ bool xsync_supported_p;
+ int xsync_major;
+ int xsync_minor;
+#endif
+
+#ifdef HAVE_XINERAMA
+ bool xinerama_supported_p;
+#endif
+
+#ifdef HAVE_XCOMPOSITE
+ bool composite_supported_p;
+ int composite_major;
+ int composite_minor;
+#endif
+
+#ifdef HAVE_XSHAPE
+ bool xshape_supported_p;
+ int xshape_major;
+ int xshape_minor;
+ int xshape_event_base;
+ int xshape_error_base;
+#endif
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ Lisp_Object *protected_windows;
+ int n_protected_windows;
+ int protected_windows_max;
+#endif
+
+ /* The current dimensions of the screen. This is updated when a
+ ConfigureNotify is received for the root window, and is zero if
+ that didn't happen. */
+ int screen_width;
+ int screen_height;
+
+ /* The mm width and height of the screen. Updated on
+ RRScreenChangeNotify. */
+ int screen_mm_width;
+ int screen_mm_height;
+
+ /* Circular buffer of request serial ranges to ignore inside an
+ error handler in increasing order. */
+ struct x_failable_request failable_requests[N_FAILABLE_REQUESTS];
+
+ /* Pointer to the next request in `failable_requests'. */
+ struct x_failable_request *next_failable_request;
+
+ /* The pending drag-and-drop time for middle-click based
+ drag-and-drop emulation. */
+ Time pending_dnd_time;
};
#ifdef HAVE_X_I18N
@@ -550,6 +792,9 @@ extern bool x_display_ok (const char *);
extern void select_visual (struct x_display_info *);
extern Window tip_window;
+extern Lisp_Object tip_dx;
+extern Lisp_Object tip_dy;
+extern Lisp_Object tip_frame;
/* Each X frame object points to its own struct x_output object
in the output_data.x field. The x_output structure contains
@@ -591,6 +836,13 @@ struct x_output
window's back buffer. */
Drawable draw_desc;
+#ifdef HAVE_XRENDER
+ /* The Xrender picture that corresponds to this drawable. None
+ means no picture format was found, or the Xrender extension is
+ not present. */
+ Picture picture;
+#endif
+
/* Flag that indicates whether we've modified the back buffer and
need to publish our modifications to the front buffer at a
convenient time. */
@@ -618,6 +870,12 @@ struct x_output
Widget menubar_widget;
#endif
+#ifndef USE_GTK
+ /* A window used to store the user time property. May be None or
+ the frame's outer window. */
+ Window user_time_window;
+#endif
+
#ifdef USE_GTK
/* The widget of this screen. This is the window of a top widget. */
GtkWidget *widget;
@@ -643,6 +901,15 @@ struct x_output
GtkTooltip *ttip_widget;
GtkWidget *ttip_lbl;
GtkWindow *ttip_window;
+
+ GtkIMContext *im_context;
+
+#ifdef HAVE_GTK3
+ /* The CSS providers used for scroll bar foreground and background
+ colors. */
+ GtkCssProvider *scrollbar_foreground_css_provider;
+ GtkCssProvider *scrollbar_background_css_provider;
+#endif
#endif /* USE_GTK */
/* If >=0, a bitmap index. The indicated bitmap is used for the
@@ -747,6 +1014,10 @@ struct x_output
false, tell Xt not to wait. */
bool_bf wait_for_wm : 1;
+ /* True if this frame's alpha value is the same for both the active
+ and inactive states. */
+ bool_bf alpha_identical_p : 1;
+
#ifdef HAVE_X_I18N
/* Input context (currently, this means Compose key handler setup). */
XIC xic;
@@ -754,6 +1025,19 @@ struct x_output
XFontSet xic_xfs;
#endif
+#ifdef HAVE_XSYNC
+ XSyncCounter basic_frame_counter;
+ XSyncCounter extended_frame_counter;
+ XSyncValue pending_basic_counter_value;
+ XSyncValue current_extended_counter_value;
+
+ bool_bf sync_end_pending_p : 1;
+ bool_bf ext_sync_end_pending_p : 1;
+#ifdef HAVE_GTK3
+ bool_bf xg_sync_end_pending_p : 1;
+#endif
+#endif
+
/* Relief GCs, colors etc. */
struct relief
{
@@ -794,6 +1078,12 @@ struct x_output
ptrdiff_t preedit_size;
char *preedit_chars;
bool preedit_active;
+ int preedit_caret;
+#endif
+
+#ifdef HAVE_XINPUT2
+ XIEventMask *xi_masks;
+ int num_xi_masks;
#endif
};
@@ -828,13 +1118,15 @@ extern void x_mark_frame_dirty (struct frame *f);
code after any drawing command, but we can run code whenever
someone asks for the handle necessary to draw. */
#define FRAME_X_DRAWABLE(f) \
- (x_mark_frame_dirty((f)), FRAME_X_RAW_DRAWABLE ((f)))
+ (x_mark_frame_dirty ((f)), FRAME_X_RAW_DRAWABLE ((f)))
+#ifdef HAVE_XDBE
#define FRAME_X_DOUBLE_BUFFERED_P(f) \
(FRAME_X_WINDOW (f) != FRAME_X_RAW_DRAWABLE (f))
/* Return the need-buffer-flip flag for frame F. */
#define FRAME_X_NEED_BUFFER_FLIP(f) ((f)->output_data.x->need_buffer_flip)
+#endif
/* Return the outermost X window associated with the frame F. */
#ifdef USE_X_TOOLKIT
@@ -905,6 +1197,24 @@ extern void x_mark_frame_dirty (struct frame *f);
/* This is the Visual which frame F is on. */
#define FRAME_X_VISUAL(f) FRAME_DISPLAY_INFO (f)->visual
+/* And its corresponding visual info. */
+#define FRAME_X_VISUAL_INFO(f) (&FRAME_DISPLAY_INFO (f)->visual_info)
+
+#ifdef HAVE_XRENDER
+#define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format
+#define FRAME_X_PICTURE(f) ((f)->output_data.x->picture)
+#define FRAME_CHECK_XR_VERSION(f, major, minor) \
+ (FRAME_DISPLAY_INFO (f)->xrender_supported_p \
+ && ((FRAME_DISPLAY_INFO (f)->xrender_major == (major) \
+ && FRAME_DISPLAY_INFO (f)->xrender_minor >= (minor)) \
+ || (FRAME_DISPLAY_INFO (f)->xrender_major > (major))))
+#endif
+
+#ifdef HAVE_XSYNC
+#define FRAME_X_BASIC_COUNTER(f) FRAME_X_OUTPUT (f)->basic_frame_counter
+#define FRAME_X_EXTENDED_COUNTER(f) FRAME_X_OUTPUT (f)->extended_frame_counter
+#endif
+
/* This is the Colormap which frame F uses. */
#define FRAME_X_COLORMAP(f) FRAME_DISPLAY_INFO (f)->cmap
@@ -940,6 +1250,11 @@ struct scroll_bar
/* The X window representing this scroll bar. */
Window x_window;
+#if defined HAVE_XDBE && !defined USE_TOOLKIT_SCROLL_BARS
+ /* The X drawable representing this scroll bar. */
+ Drawable x_drawable;
+#endif
+
/* The position and size of the scroll bar in pixels, relative to the
frame. */
int top, left, width, height;
@@ -1130,27 +1445,35 @@ extern const char *x_get_string_resource (void *, const char *, const char *);
/* Defined in xterm.c */
-typedef void (*x_special_error_handler)(Display *, XErrorEvent *, char *,
- void *);
+typedef void (*x_special_error_handler) (Display *, XErrorEvent *, char *,
+ void *);
extern bool x_text_icon (struct frame *, const char *);
extern void x_catch_errors (Display *);
extern void x_catch_errors_with_handler (Display *, x_special_error_handler,
void *);
+extern void x_catch_errors_for_lisp (struct x_display_info *);
+extern void x_uncatch_errors_for_lisp (struct x_display_info *);
+extern void x_check_errors_for_lisp (struct x_display_info *,
+ const char *)
+ ATTRIBUTE_FORMAT_PRINTF (2, 0);
extern void x_check_errors (Display *, const char *)
ATTRIBUTE_FORMAT_PRINTF (2, 0);
extern bool x_had_errors_p (Display *);
+extern void x_unwind_errors_to (int);
extern void x_uncatch_errors (void);
extern void x_uncatch_errors_after_check (void);
extern void x_clear_errors (Display *);
-extern void x_set_window_size (struct frame *f, bool, int, int);
-extern void x_make_frame_visible (struct frame *f);
-extern void x_make_frame_invisible (struct frame *f);
-extern void x_iconify_frame (struct frame *f);
+extern void x_set_window_size (struct frame *, bool, int, int);
+extern void x_set_last_user_time_from_lisp (struct x_display_info *, Time);
+extern void x_make_frame_visible (struct frame *);
+extern void x_make_frame_invisible (struct frame *);
+extern void x_iconify_frame (struct frame *);
extern void x_free_frame_resources (struct frame *);
extern void x_wm_set_size_hint (struct frame *, long, bool);
-extern void x_delete_terminal (struct terminal *terminal);
+extern void x_delete_terminal (struct terminal *);
+extern Cursor x_create_font_cursor (struct x_display_info *, int);
extern unsigned long x_copy_color (struct frame *, unsigned long);
#ifdef USE_X_TOOLKIT
extern XtAppContext Xt_app_con;
@@ -1164,11 +1487,13 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *);
extern void x_query_colors (struct frame *f, XColor *, int);
extern void x_clear_area (struct frame *f, int, int, int, int);
-#if !defined USE_X_TOOLKIT && !defined USE_GTK
+#if (defined USE_LUCID && defined HAVE_XINPUT2) \
+ || (!defined USE_X_TOOLKIT && !defined USE_GTK)
extern void x_mouse_leave (struct x_display_info *);
#endif
+extern void x_wait_for_cell_change (Lisp_Object, struct timespec);
-#if defined USE_X_TOOLKIT || defined USE_MOTIF
+#ifndef USE_GTK
extern int x_dispatch_event (XEvent *, Display *);
#endif
extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
@@ -1178,37 +1503,47 @@ extern void x_cr_destroy_frame_context (struct frame *);
extern void x_cr_update_surface_desired_size (struct frame *, int, int);
extern cairo_t *x_begin_cr_clip (struct frame *, GC);
extern void x_end_cr_clip (struct frame *);
-extern void x_set_cr_source_with_gc_foreground (struct frame *, GC);
-extern void x_set_cr_source_with_gc_background (struct frame *, GC);
+extern void x_set_cr_source_with_gc_foreground (struct frame *, GC, bool);
+extern void x_set_cr_source_with_gc_background (struct frame *, GC, bool);
extern void x_cr_draw_frame (cairo_t *, struct frame *);
extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
#endif
-INLINE int
-x_display_pixel_height (struct x_display_info *dpyinfo)
-{
- return HeightOfScreen (dpyinfo->screen);
-}
-
-INLINE int
-x_display_pixel_width (struct x_display_info *dpyinfo)
-{
- return WidthOfScreen (dpyinfo->screen);
-}
+#ifdef HAVE_XRENDER
+extern void x_xrender_color_from_gc_background (struct frame *, GC,
+ XRenderColor *, bool);
+extern void x_xr_ensure_picture (struct frame *f);
+extern void x_xr_apply_ext_clip (struct frame *f, GC gc);
+extern void x_xr_reset_ext_clip (struct frame *f);
+#endif
-INLINE void
-x_display_set_last_user_time (struct x_display_info *dpyinfo, Time t)
-{
-#ifdef ENABLE_CHECKING
- eassert (t <= X_ULONG_MAX);
+#ifdef HAVE_GTK3
+extern void x_scroll_bar_configure (GdkEvent *);
#endif
- dpyinfo->last_user_time = t;
-}
+
+#define DEFER_SELECTIONS \
+ x_defer_selection_requests (); \
+ record_unwind_protect_void (x_release_selection_requests_and_flush)
+
+extern void x_defer_selection_requests (void);
+extern void x_release_selection_requests_and_flush (void);
+extern void x_handle_pending_selection_requests (void);
+extern bool x_detect_pending_selection_requests (void);
+extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
+ Lisp_Object, Atom *, const char **,
+ size_t, bool, Atom *, int,
+ Lisp_Object, bool);
+extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object,
+ Lisp_Object, Lisp_Object, Window, int,
+ int, Time);
+
+extern int x_display_pixel_height (struct x_display_info *);
+extern int x_display_pixel_width (struct x_display_info *);
INLINE unsigned long
x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b)
{
- unsigned long pr, pg, pb;
+ unsigned long pr, pg, pb, pa = dpyinfo->alpha_mask;
/* Scale down RGB values to the visual's bits per RGB, and shift
them to the right position in the pixel color. Note that the
@@ -1218,7 +1553,7 @@ x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b)
pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
/* Assemble the pixel color. */
- return pr | pg | pb;
+ return pr | pg | pb | pa;
}
/* If display has an immutable color map, freeing colors is not
@@ -1226,16 +1561,18 @@ x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b)
also allows us to make other optimizations relating to server-side
reference counts. */
INLINE bool
-x_mutable_colormap (Visual *visual)
+x_mutable_colormap (XVisualInfo *visual)
{
int class = visual->class;
return (class != StaticColor && class != StaticGray && class != TrueColor);
}
extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
+extern void x_set_shaded (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object);
extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object);
extern bool x_wm_supports (struct frame *, Atom);
+extern bool x_wm_supports_1 (struct x_display_info *, Atom);
extern void x_wait_for_event (struct frame *, int);
extern void x_clear_under_internal_border (struct frame *f);
@@ -1260,18 +1597,14 @@ extern void x_handle_property_notify (const XPropertyEvent *);
extern void x_handle_selection_notify (const XSelectionEvent *);
extern void x_handle_selection_event (struct selection_input_event *);
extern void x_clear_frame_selections (struct frame *);
-
-extern void x_send_client_event (Lisp_Object display,
- Lisp_Object dest,
- Lisp_Object from,
- Atom message_type,
- Lisp_Object format,
- Lisp_Object values);
+extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom);
+extern Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object);
extern bool x_handle_dnd_message (struct frame *,
const XClientMessageEvent *,
struct x_display_info *,
- struct input_event *);
+ struct input_event *,
+ bool, int, int);
extern int x_check_property_data (Lisp_Object);
extern void x_fill_property_data (Display *,
Lisp_Object,
@@ -1286,6 +1619,15 @@ extern Lisp_Object x_property_data_to_lisp (struct frame *,
extern void x_clipboard_manager_save_frame (Lisp_Object);
extern void x_clipboard_manager_save_all (void);
+extern Lisp_Object x_timestamp_for_selection (struct x_display_info *,
+ Lisp_Object);
+extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object, Time);
+extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
+ bool);
+extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
+ ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
+
#ifdef USE_GTK
extern bool xg_set_icon (struct frame *, Lisp_Object);
extern bool xg_set_icon_from_xpm_data (struct frame *, const char **);
@@ -1340,6 +1682,26 @@ extern void x_session_close (void);
#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing)
#endif
+#ifdef USE_GTK
+extern struct input_event xg_pending_quit_event;
+#endif
+
+extern bool x_dnd_in_progress;
+extern bool x_dnd_waiting_for_finish;
+extern struct frame *x_dnd_frame;
+extern struct frame *x_dnd_finish_frame;
+extern int x_error_message_count;
+
+#ifdef HAVE_XINPUT2
+extern struct xi_device_t *xi_device_from_id (struct x_display_info *, int);
+extern bool xi_frame_selected_for (struct frame *, unsigned long);
+#ifndef USE_GTK
+extern unsigned int xi_convert_event_state (XIDeviceEvent *);
+#endif
+#endif
+
+extern void mark_xterm (void);
+
/* Is the frame embedded into another application? */
#define FRAME_X_EMBEDDED_P(f) (FRAME_X_OUTPUT(f)->explicit_parent != 0)
diff --git a/src/xwidget.c b/src/xwidget.c
index 7d6d256a191..8bdfab02fd4 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -40,6 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <JavaScriptCore/JavaScript.h>
#include <cairo.h>
#ifndef HAVE_PGTK
+#include <cairo-xlib.h>
#include <X11/Xlib.h>
#else
#include <gtk/gtk.h>
@@ -61,6 +62,9 @@ static uint32_t xwidget_counter = 0;
#ifdef USE_GTK
#ifdef HAVE_X_WINDOWS
static Lisp_Object x_window_to_xwv_map;
+#if WEBKIT_CHECK_VERSION (2, 34, 0)
+static Lisp_Object dummy_tooltip_string;
+#endif
#endif
static gboolean offscreen_damage_event (GtkWidget *, GdkEvent *, gpointer);
static void synthesize_focus_in_event (GtkWidget *);
@@ -106,7 +110,8 @@ webkit_decide_policy_cb (WebKitWebView *,
WebKitPolicyDecision *,
WebKitPolicyDecisionType,
gpointer);
-static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *);
+static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *, bool,
+ struct xwidget_view *);
static gboolean run_file_chooser_cb (WebKitWebView *,
WebKitFileChooserRequest *,
gpointer);
@@ -121,11 +126,12 @@ struct widget_search_data
};
static void find_widget (GtkWidget *t, struct widget_search_data *);
-static void mouse_target_changed (WebKitWebView *, WebKitHitTestResult *, guint,
- gpointer);
#endif
#ifdef HAVE_PGTK
+static void mouse_target_changed (WebKitWebView *, WebKitHitTestResult *, guint,
+ gpointer);
+
static int
xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv,
struct xwidget *xw)
@@ -142,7 +148,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv,
widget = find_widget_at_pos (xw->widgetwindow_osr,
lrint (event->button.x - xv->clip_left),
lrint (event->button.y - xv->clip_top),
- &new_x, &new_y);
+ &new_x, &new_y, false, NULL);
if (widget)
{
event->any.window = gtk_widget_get_window (widget);
@@ -155,7 +161,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv,
widget = find_widget_at_pos (xw->widgetwindow_osr,
lrint (event->scroll.x - xv->clip_left),
lrint (event->scroll.y - xv->clip_top),
- &new_x, &new_y);
+ &new_x, &new_y, false, NULL);
if (widget)
{
event->any.window = gtk_widget_get_window (widget);
@@ -168,7 +174,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv,
widget = find_widget_at_pos (xw->widgetwindow_osr,
lrint (event->motion.x - xv->clip_left),
lrint (event->motion.y - xv->clip_top),
- &new_x, &new_y);
+ &new_x, &new_y, false, NULL);
if (widget)
{
event->any.window = gtk_widget_get_window (widget);
@@ -182,7 +188,7 @@ xw_forward_event_translate (GdkEvent *event, struct xwidget_view *xv,
widget = find_widget_at_pos (xw->widgetwindow_osr,
lrint (event->crossing.x - xv->clip_left),
lrint (event->crossing.y - xv->clip_top),
- &new_x, &new_y);
+ &new_x, &new_y, false, NULL);
if (widget)
{
event->any.window = gtk_widget_get_window (widget);
@@ -223,6 +229,13 @@ xw_forward_event_from_view (GtkWidget *widget, GdkEvent *event,
#endif
#ifdef HAVE_X_WINDOWS
+enum xw_crossing_mode
+ {
+ XW_CROSSING_LEFT,
+ XW_CROSSING_ENTERED,
+ XW_CROSSING_NONE
+ };
+
static guint
xw_translate_x_modifiers (struct x_display_info *dpyinfo,
unsigned int modifiers)
@@ -252,6 +265,17 @@ xw_translate_x_modifiers (struct x_display_info *dpyinfo,
return mods;
}
+
+static bool xw_maybe_synthesize_crossing (struct xwidget_view *,
+ GdkWindow *, int, int, int,
+ Time, unsigned int,
+ GdkCrossingMode, GdkCrossingMode);
+static void xw_notify_virtual_upwards_until (struct xwidget_view *, GdkWindow *,
+ GdkWindow *, GdkWindow *, unsigned int,
+ int, int, Time, GdkEventType, bool,
+ GdkCrossingMode);
+static void window_coords_from_toplevel (GdkWindow *, GdkWindow *, int,
+ int, int *, int *);
#endif
DEFUN ("make-xwidget",
@@ -402,11 +426,12 @@ fails. */)
G_CALLBACK
(webkit_decide_policy_cb),
xw);
-
+#ifdef HAVE_PGTK
g_signal_connect (G_OBJECT (xw->widget_osr),
"mouse-target-changed",
G_CALLBACK (mouse_target_changed),
xw);
+#endif
g_signal_connect (G_OBJECT (xw->widget_osr),
"create",
G_CALLBACK (webkit_create_cb),
@@ -709,7 +734,7 @@ pick_embedded_child (GdkWindow *window, double x, double y,
return NULL;
child = find_widget_at_pos (widget, lrint (x), lrint (y),
- &xout, &yout);
+ &xout, &yout, false, NULL);
if (!child)
return NULL;
@@ -832,15 +857,34 @@ to_embedder (GdkWindow *window, double x, double y,
}
static GdkDevice *
-find_suitable_pointer (struct frame *f)
+find_suitable_pointer (struct frame *f, bool need_smooth)
{
GdkSeat *seat = gdk_display_get_default_seat
(gtk_widget_get_display (FRAME_GTK_WIDGET (f)));
+ GList *devices, *tem;
+ GdkDevice *device;
if (!seat)
return NULL;
- return gdk_seat_get_pointer (seat);
+ devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_ALL_POINTING);
+ device = NULL;
+ tem = NULL;
+
+ if (need_smooth)
+ {
+ for (tem = devices; tem; tem = tem->next)
+ {
+ device = GDK_DEVICE (tem->data);
+
+ if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHPAD)
+ break;
+ }
+ }
+
+ g_list_free (devices);
+
+ return !tem ? gdk_seat_get_pointer (seat) : device;
}
static GdkDevice *
@@ -918,9 +962,9 @@ find_widget (GtkWidget *widget,
}
}
- if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
- (data->x < new_allocation.x + new_allocation.width) &&
- (data->y < new_allocation.y + new_allocation.height))
+ if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y)
+ && (data->x < new_allocation.x + new_allocation.width)
+ && (data->y < new_allocation.y + new_allocation.height))
{
/* First, check if the drag is in a valid drop site in one of
our children. */
@@ -954,9 +998,27 @@ find_widget (GtkWidget *widget,
static GtkWidget *
find_widget_at_pos (GtkWidget *w, int x, int y,
- int *new_x, int *new_y)
+ int *new_x, int *new_y,
+ bool pointer_grabs,
+ struct xwidget_view *vw)
{
struct widget_search_data data;
+#ifdef HAVE_X_WINDOWS
+ GtkWidget *grab = NULL;
+
+ if (pointer_grabs)
+ {
+ grab = vw->passive_grab;
+
+ if (grab && gtk_widget_get_window (grab))
+ {
+ gtk_widget_translate_coordinates (w, grab, x,
+ y, new_x, new_y);
+
+ return grab;
+ }
+ }
+#endif
data.x = x;
data.y = y;
@@ -978,6 +1040,7 @@ find_widget_at_pos (GtkWidget *w, int x, int y,
return NULL;
}
+#ifdef HAVE_PGTK
static Emacs_Cursor
cursor_for_hit (guint result, struct frame *frame)
{
@@ -1001,9 +1064,7 @@ static void
define_cursors (struct xwidget *xw, WebKitHitTestResult *res)
{
struct xwidget_view *xvw;
-#ifdef HAVE_PGTK
GdkWindow *wdesc;
-#endif
xw->hit_result = webkit_hit_test_result_get_context (res);
@@ -1017,16 +1078,12 @@ define_cursors (struct xwidget *xw, WebKitHitTestResult *res)
if (XXWIDGET (xvw->model) == xw)
{
xvw->cursor = cursor_for_hit (xw->hit_result, xvw->frame);
-#ifdef HAVE_X_WINDOWS
- if (xvw->wdesc != None)
- XDefineCursor (xvw->dpy, xvw->wdesc, xvw->cursor);
-#else
+
if (gtk_widget_get_realized (xvw->widget))
{
wdesc = gtk_widget_get_window (xvw->widget);
gdk_window_set_cursor (wdesc, xvw->cursor);
}
-#endif
}
}
}
@@ -1039,6 +1096,7 @@ mouse_target_changed (WebKitWebView *webview,
{
define_cursors (xw, hitresult);
}
+#endif
static gboolean
run_file_chooser_cb (WebKitWebView *webview,
@@ -1103,23 +1161,49 @@ run_file_chooser_cb (WebKitWebView *webview,
#ifdef HAVE_X_WINDOWS
static void
+xv_drag_begin_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer user_data)
+{
+ struct xwidget_view *view = user_data;
+
+ if (view->passive_grab)
+ {
+ g_signal_handler_disconnect (view->passive_grab,
+ view->passive_grab_destruction_signal);
+ g_signal_handler_disconnect (view->passive_grab,
+ view->passive_grab_drag_signal);
+ view->passive_grab = NULL;
+ }
+}
+
+static void
xwidget_button_1 (struct xwidget_view *view,
bool down_p, int x, int y, int button,
int modifier_state, Time time)
{
- GdkEvent *xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
+ GdkEvent *xg_event;
struct xwidget *model = XXWIDGET (view->model);
GtkWidget *target;
+ GtkWidget *ungrab_target;
+ GdkWindow *toplevel, *target_window;
+ int view_x, view_y;
/* X and Y should be relative to the origin of view->wdesc. */
x += view->clip_left;
y += view->clip_top;
- target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y);
+ view_x = x;
+ view_y = y;
+
+ target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y,
+ true, view);
if (!target)
target = model->widget_osr;
+ xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
+
xg_event->any.window = gtk_widget_get_window (target);
g_object_ref (xg_event->any.window); /* The window will be unrefed
later by gdk_event_free. */
@@ -1131,10 +1215,92 @@ xwidget_button_1 (struct xwidget_view *view,
xg_event->button.button = button;
xg_event->button.state = modifier_state;
xg_event->button.time = time;
- xg_event->button.device = find_suitable_pointer (view->frame);
+ xg_event->button.device = find_suitable_pointer (view->frame, false);
gtk_main_do_event (xg_event);
gdk_event_free (xg_event);
+
+
+ if (down_p && !view->passive_grab)
+ {
+ view->passive_grab = target;
+ view->passive_grab_destruction_signal
+ = g_signal_connect (G_OBJECT (view->passive_grab),
+ "destroy", G_CALLBACK (gtk_widget_destroyed),
+ &view->passive_grab);
+ view->passive_grab_drag_signal
+ = g_signal_connect (G_OBJECT (view->passive_grab),
+ "drag-begin", G_CALLBACK (xv_drag_begin_cb),
+ view);
+ }
+ else
+ {
+ ungrab_target = find_widget_at_pos (model->widgetwindow_osr,
+ view_x, view_y, &x, &y,
+ false, NULL);
+
+ if (view->last_crossing_window && ungrab_target)
+ {
+ xw_maybe_synthesize_crossing (view, gtk_widget_get_window (ungrab_target),
+ view_x, view_y, XW_CROSSING_NONE,
+ time, modifier_state, GDK_CROSSING_UNGRAB,
+ GDK_CROSSING_UNGRAB);
+ }
+ else
+ {
+ toplevel = gtk_widget_get_window (model->widgetwindow_osr);
+ xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+ target_window = gtk_widget_get_window (target);
+ window_coords_from_toplevel (target_window, toplevel, view_x,
+ view_y, &x, &y);
+
+ xg_event->crossing.x = x;
+ xg_event->crossing.y = y;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ xg_event->crossing.mode = GDK_CROSSING_UNGRAB;
+ xg_event->crossing.window = g_object_ref (target_window);
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+
+ xw_notify_virtual_upwards_until (view, target_window, toplevel, toplevel,
+ modifier_state, view_x, view_y, time,
+ GDK_LEAVE_NOTIFY, false,
+ GDK_CROSSING_UNGRAB);
+
+ if (target_window != toplevel)
+ {
+ xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+
+ xg_event->crossing.x = view_y;
+ xg_event->crossing.y = view_y;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ xg_event->crossing.mode = GDK_CROSSING_UNGRAB;
+ xg_event->crossing.window = g_object_ref (toplevel);
+
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ }
+
+ }
+
+ if (view->passive_grab)
+ {
+ g_signal_handler_disconnect (view->passive_grab,
+ view->passive_grab_destruction_signal);
+ g_signal_handler_disconnect (view->passive_grab,
+ view->passive_grab_drag_signal);
+ view->passive_grab = NULL;
+ }
+ }
}
void
@@ -1149,51 +1315,51 @@ xwidget_button (struct xwidget_view *view,
if (button < 4 || button > 8)
xwidget_button_1 (view, down_p, x, y, button, modifier_state, time);
-#ifndef HAVE_XINPUT2
else
-#else
- else if (!FRAME_DISPLAY_INFO (view->frame)->supports_xi2
- || FRAME_DISPLAY_INFO (view->frame)->xi2_version < 1)
-#endif
{
- GdkEvent *xg_event = gdk_event_new (GDK_SCROLL);
- struct xwidget *model = XXWIDGET (view->model);
- GtkWidget *target;
-
- x += view->clip_left;
- y += view->clip_top;
-
- target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y);
-
- if (!target)
- target = model->widget_osr;
-
- xg_event->any.window = gtk_widget_get_window (target);
- g_object_ref (xg_event->any.window); /* The window will be unrefed
- later by gdk_event_free. */
- if (button == 4)
- xg_event->scroll.direction = GDK_SCROLL_UP;
- else if (button == 5)
- xg_event->scroll.direction = GDK_SCROLL_DOWN;
- else if (button == 6)
- xg_event->scroll.direction = GDK_SCROLL_LEFT;
- else
- xg_event->scroll.direction = GDK_SCROLL_RIGHT;
+ if (!down_p)
+ {
+ GdkEvent *xg_event = gdk_event_new (GDK_SCROLL);
+ struct xwidget *model = XXWIDGET (view->model);
+ GtkWidget *target;
+
+ x += view->clip_left;
+ y += view->clip_top;
+
+ target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y,
+ true, view);
+
+ if (!target)
+ target = model->widget_osr;
+
+ xg_event->any.window = gtk_widget_get_window (target);
+ g_object_ref (xg_event->any.window); /* The window will be unrefed
+ later by gdk_event_free. */
+ if (button == 4)
+ xg_event->scroll.direction = GDK_SCROLL_UP;
+ else if (button == 5)
+ xg_event->scroll.direction = GDK_SCROLL_DOWN;
+ else if (button == 6)
+ xg_event->scroll.direction = GDK_SCROLL_LEFT;
+ else
+ xg_event->scroll.direction = GDK_SCROLL_RIGHT;
- xg_event->scroll.device = find_suitable_pointer (view->frame);
+ xg_event->scroll.device = find_suitable_pointer (view->frame,
+ false);
- xg_event->scroll.x = x;
- xg_event->scroll.x_root = x;
- xg_event->scroll.y = y;
- xg_event->scroll.y_root = y;
- xg_event->scroll.state = modifier_state;
- xg_event->scroll.time = time;
+ xg_event->scroll.x = x;
+ xg_event->scroll.x_root = x;
+ xg_event->scroll.y = y;
+ xg_event->scroll.y_root = y;
+ xg_event->scroll.state = modifier_state;
+ xg_event->scroll.time = time;
- xg_event->scroll.delta_x = 0;
- xg_event->scroll.delta_y = 0;
+ xg_event->scroll.delta_x = 0;
+ xg_event->scroll.delta_y = 0;
- gtk_main_do_event (xg_event);
- gdk_event_free (xg_event);
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ }
}
}
@@ -1217,14 +1383,23 @@ xwidget_motion_notify (struct xwidget_view *view,
target = find_widget_at_pos (model->widgetwindow_osr,
lrint (x + view->clip_left),
lrint (y + view->clip_top),
- &target_x, &target_y);
+ &target_x, &target_y,
+ true, view);
if (!target)
{
- target_x = lrint (x);
- target_y = lrint (y);
+ target_x = lrint (x + view->clip_left);
+ target_y = lrint (y + view->clip_top);
target = model->widget_osr;
}
+ else if (xw_maybe_synthesize_crossing (view, gtk_widget_get_window (target),
+ x + view->clip_left, y + view->clip_top,
+ XW_CROSSING_NONE, time, state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
+ return;
xg_event = gdk_event_new (GDK_MOTION_NOTIFY);
xg_event->any.window = gtk_widget_get_window (target);
@@ -1234,7 +1409,7 @@ xwidget_motion_notify (struct xwidget_view *view,
xg_event->motion.y_root = root_y;
xg_event->motion.time = time;
xg_event->motion.state = state;
- xg_event->motion.device = find_suitable_pointer (view->frame);
+ xg_event->motion.device = find_suitable_pointer (view->frame, false);
g_object_ref (xg_event->any.window);
@@ -1260,7 +1435,8 @@ xwidget_scroll (struct xwidget_view *view, double x, double y,
target = find_widget_at_pos (model->widgetwindow_osr,
lrint (x + view->clip_left),
lrint (y + view->clip_top),
- &target_x, &target_y);
+ &target_x, &target_y,
+ true, view);
if (!target)
{
@@ -1280,7 +1456,7 @@ xwidget_scroll (struct xwidget_view *view, double x, double y,
xg_event->scroll.state = state;
xg_event->scroll.delta_x = dx;
xg_event->scroll.delta_y = dy;
- xg_event->scroll.device = find_suitable_pointer (view->frame);
+ xg_event->scroll.device = find_suitable_pointer (view->frame, true);
xg_event->scroll.is_stop = stop_p;
g_object_ref (xg_event->any.window);
@@ -1289,7 +1465,7 @@ xwidget_scroll (struct xwidget_view *view, double x, double y,
gdk_event_free (xg_event);
}
-#ifdef HAVE_USABLE_XI_GESTURE_PINCH_EVENT
+#ifdef HAVE_XINPUT2_4
void
xwidget_pinch (struct xwidget_view *view, XIGesturePinchEvent *xev)
{
@@ -1309,7 +1485,8 @@ xwidget_pinch (struct xwidget_view *view, XIGesturePinchEvent *xev)
target = find_widget_at_pos (model->widgetwindow_osr,
lrint (x + view->clip_left),
lrint (y + view->clip_top),
- &target_x, &target_y);
+ &target_x, &target_y,
+ true, view);
if (!target)
{
@@ -1344,7 +1521,7 @@ xwidget_pinch (struct xwidget_view *view, XIGesturePinchEvent *xev)
break;
}
- gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+ gdk_event_set_device (xg_event, find_suitable_pointer (view->frame, false));
g_object_ref (xg_event->any.window);
gtk_main_do_event (xg_event);
@@ -1376,13 +1553,379 @@ xi_translate_notify_detail (int detail)
}
#endif
+static void
+window_coords_from_toplevel (GdkWindow *window, GdkWindow *toplevel,
+ int x, int y, int *out_x, int *out_y)
+{
+ GdkWindow *parent;
+ GList *children, *l;
+ gdouble x_out, y_out;
+
+ if (window == toplevel)
+ {
+ *out_x = x;
+ *out_y = y;
+ return;
+ }
+
+ children = NULL;
+ while ((parent = gdk_window_get_parent (window)) != toplevel)
+ {
+ children = g_list_prepend (children, window);
+ window = parent;
+ }
+
+ for (l = children; l != NULL; l = l->next)
+ gdk_window_coords_from_parent (l->data, x, y, &x_out, &y_out);
+
+ g_list_free (children);
+
+ *out_x = x_out;
+ *out_y = y_out;
+}
+
+static GdkWindow *
+xw_find_common_ancestor (GdkWindow *window,
+ GdkWindow *other,
+ GdkWindow *toplevel)
+{
+ GdkWindow *tem;
+ GList *l1 = NULL;
+ GList *l2 = NULL;
+ GList *i1, *i2;
+
+ tem = window;
+ while (tem && tem != toplevel)
+ {
+ l1 = g_list_prepend (l1, tem);
+ tem = gdk_window_get_parent (tem);
+ }
+
+ tem = other;
+ while (tem && tem != toplevel)
+ {
+ l2 = g_list_prepend (l2, tem);
+ tem = gdk_window_get_parent (tem);
+ }
+
+ tem = NULL;
+ i1 = l1;
+ i2 = l2;
+
+ while (i1 && i2 && (i1->data == i2->data))
+ {
+ tem = i1->data;
+ i1 = i1->next;
+ i2 = i2->next;
+ }
+
+ g_list_free (l1);
+ g_list_free (l2);
+
+ return tem;
+}
+
+static void
+xw_notify_virtual_upwards_until (struct xwidget_view *xv,
+ GdkWindow *window,
+ GdkWindow *until,
+ GdkWindow *toplevel,
+ unsigned int state,
+ int x, int y, Time time,
+ GdkEventType type,
+ bool nonlinear_p,
+ GdkCrossingMode crossing)
+{
+ GdkEvent *xg_event;
+ GdkWindow *tem;
+ int cx, cy;
+
+ for (tem = gdk_window_get_parent (window);
+ tem && (tem != until);
+ tem = gdk_window_get_parent (tem))
+ {
+ xg_event = gdk_event_new (type);
+
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (xv->frame, false));
+ window_coords_from_toplevel (tem, toplevel, x, y, &cx, &cy);
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = (nonlinear_p
+ ? GDK_NOTIFY_NONLINEAR_VIRTUAL
+ : GDK_NOTIFY_VIRTUAL);
+ xg_event->crossing.mode = crossing;
+ xg_event->crossing.window = g_object_ref (tem);
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ }
+}
+
+static void
+xw_notify_virtual_downwards_until (struct xwidget_view *xv,
+ GdkWindow *window,
+ GdkWindow *until,
+ GdkWindow *toplevel,
+ unsigned int state,
+ int x, int y, Time time,
+ GdkEventType type,
+ bool nonlinear_p,
+ GdkCrossingMode crossing)
+{
+ GdkEvent *xg_event;
+ GdkWindow *tem;
+ int cx, cy;
+ GList *path = NULL, *it;
+
+ tem = gdk_window_get_parent (window);
+
+ while (tem && tem != until)
+ {
+ path = g_list_prepend (path, tem);
+ tem = gdk_window_get_parent (tem);
+ }
+
+ for (it = path; it; it = it->next)
+ {
+ tem = it->data;
+ xg_event = gdk_event_new (type);
+
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (xv->frame, false));
+ window_coords_from_toplevel (tem, toplevel, x, y, &cx, &cy);
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = (nonlinear_p
+ ? GDK_NOTIFY_NONLINEAR_VIRTUAL
+ : GDK_NOTIFY_VIRTUAL);
+ xg_event->crossing.mode = crossing;
+ xg_event->crossing.window = g_object_ref (tem);
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ }
+
+ g_list_free (path);
+}
+
+static void
+xw_update_cursor_for_view (struct xwidget_view *xv,
+ GdkWindow *crossing_window)
+{
+ GdkCursor *xg_cursor;
+ Cursor cursor;
+
+ xg_cursor = gdk_window_get_cursor (crossing_window);
+
+ if (xg_cursor)
+ {
+ cursor = gdk_x11_cursor_get_xcursor (xg_cursor);
+
+ if (gdk_x11_cursor_get_xdisplay (xg_cursor) == xv->dpy)
+ xv->cursor = cursor;
+ }
+ else
+ xv->cursor = FRAME_OUTPUT_DATA (xv->frame)->nontext_cursor;
+
+ if (xv->wdesc != None)
+ XDefineCursor (xv->dpy, xv->wdesc, xv->cursor);
+}
+
+static void
+xw_last_crossing_cursor_cb (GdkWindow *window,
+ GParamSpec *spec,
+ gpointer user_data)
+{
+ xw_update_cursor_for_view (user_data, window);
+}
+
+static bool
+xw_maybe_synthesize_crossing (struct xwidget_view *view,
+ GdkWindow *current_window,
+ int x, int y, int crossing,
+ Time time, unsigned int state,
+ GdkCrossingMode entry_crossing,
+ GdkCrossingMode exit_crossing)
+{
+ GdkWindow *last_crossing, *toplevel, *ancestor;
+ GdkEvent *xg_event;
+ int cx, cy;
+ bool nonlinear_p;
+ bool retention_flag;
+
+#if WEBKIT_CHECK_VERSION (2, 34, 0)
+ /* Work around a silly bug in WebKitGTK+ that tries to make tooltip
+ windows transient for our offscreen window. */
+ int tooltip_width, tooltip_height;
+
+ xg_prepare_tooltip (view->frame, dummy_tooltip_string,
+ &tooltip_width, &tooltip_height);
+#endif
+
+ toplevel = gtk_widget_get_window (XXWIDGET (view->model)->widgetwindow_osr);
+ retention_flag = false;
+
+ if (crossing == XW_CROSSING_LEFT
+ && (view->last_crossing_window
+ && !gdk_window_is_destroyed (view->last_crossing_window)))
+ {
+ xw_notify_virtual_upwards_until (view, view->last_crossing_window,
+ toplevel, toplevel,
+ state, x, y, time,
+ GDK_LEAVE_NOTIFY, false,
+ exit_crossing);
+ }
+
+ if (view->last_crossing_window
+ && (gdk_window_is_destroyed (view->last_crossing_window)
+ || crossing == XW_CROSSING_LEFT))
+ {
+ if (!gdk_window_is_destroyed (view->last_crossing_window)
+ && view->last_crossing_window != toplevel)
+ {
+ xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+ window_coords_from_toplevel (view->last_crossing_window,
+ toplevel, x, y, &cx, &cy);
+
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ xg_event->crossing.mode = exit_crossing;
+ xg_event->crossing.window = g_object_ref (view->last_crossing_window);
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+
+ xw_notify_virtual_upwards_until (view, view->last_crossing_window,
+ gdk_window_get_parent (toplevel),
+ toplevel, state, x, y, time,
+ GDK_LEAVE_NOTIFY, false, exit_crossing);
+ retention_flag = true;
+ }
+
+ g_signal_handler_disconnect (view->last_crossing_window,
+ view->last_crossing_cursor_signal);
+ g_clear_pointer (&view->last_crossing_window,
+ g_object_unref);
+ }
+ last_crossing = view->last_crossing_window;
+
+ if (!last_crossing)
+ {
+ if (current_window)
+ {
+ view->last_crossing_window = g_object_ref (current_window);
+ xw_update_cursor_for_view (view, current_window);
+ view->last_crossing_cursor_signal
+ = g_signal_connect (G_OBJECT (current_window), "notify::cursor",
+ G_CALLBACK (xw_last_crossing_cursor_cb), view);
+
+ xw_notify_virtual_downwards_until (view, current_window,
+ toplevel, toplevel,
+ state, x, y, time,
+ GDK_ENTER_NOTIFY,
+ false, entry_crossing);
+ }
+ return retention_flag;
+ }
+
+ if (last_crossing != current_window)
+ {
+ view->last_crossing_window = g_object_ref (current_window);
+ g_signal_handler_disconnect (last_crossing, view->last_crossing_cursor_signal);
+
+ xw_update_cursor_for_view (view, current_window);
+ view->last_crossing_cursor_signal
+ = g_signal_connect (G_OBJECT (current_window), "notify::cursor",
+ G_CALLBACK (xw_last_crossing_cursor_cb), view);
+
+ ancestor = xw_find_common_ancestor (last_crossing, current_window, toplevel);
+
+ if (!ancestor)
+ emacs_abort ();
+
+ nonlinear_p = (last_crossing != ancestor) && (current_window != ancestor);
+
+ if (nonlinear_p || (last_crossing != ancestor))
+ xw_notify_virtual_upwards_until (view, last_crossing,
+ ancestor, toplevel,
+ state, x, y, time,
+ GDK_LEAVE_NOTIFY,
+ nonlinear_p,
+ exit_crossing);
+
+ xg_event = gdk_event_new (GDK_LEAVE_NOTIFY);
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
+ window_coords_from_toplevel (last_crossing, toplevel,
+ x, y, &cx, &cy);
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.state = state;
+ xg_event->crossing.detail = (nonlinear_p
+ ? GDK_NOTIFY_NONLINEAR
+ : (last_crossing == ancestor
+ ? GDK_NOTIFY_INFERIOR
+ : GDK_NOTIFY_ANCESTOR));
+ xg_event->crossing.mode = exit_crossing;
+ xg_event->crossing.window = g_object_ref (last_crossing);
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+
+ if (nonlinear_p || (current_window != ancestor))
+ xw_notify_virtual_downwards_until (view, current_window,
+ ancestor, toplevel,
+ state, x, y, time,
+ GDK_ENTER_NOTIFY,
+ nonlinear_p,
+ entry_crossing);
+
+ xg_event = gdk_event_new (GDK_ENTER_NOTIFY);
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
+ window_coords_from_toplevel (current_window, toplevel,
+ x, y, &cx, &cy);
+ xg_event->crossing.x = cx;
+ xg_event->crossing.y = cy;
+ xg_event->crossing.time = time;
+ xg_event->crossing.focus = FALSE;
+ xg_event->crossing.state = state;
+ xg_event->crossing.detail = (nonlinear_p
+ ? GDK_NOTIFY_NONLINEAR
+ : (current_window == ancestor
+ ? GDK_NOTIFY_INFERIOR
+ : GDK_NOTIFY_ANCESTOR));
+ xg_event->crossing.mode = entry_crossing;
+ xg_event->crossing.window = g_object_ref (current_window);
+
+ gtk_main_do_event (xg_event);
+ gdk_event_free (xg_event);
+ g_object_unref (last_crossing);
+
+ return true;
+ }
+
+ return false;
+}
+
void
xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
{
GdkEvent *xg_event;
struct xwidget *model = XXWIDGET (view->model);
- int x;
- int y;
+ int x, y, toplevel_x, toplevel_y;
GtkWidget *target;
#ifdef HAVE_XINPUT2
XIEnterEvent *xev = NULL;
@@ -1400,14 +1943,15 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
: (event->type == LeaveNotify
? GDK_LEAVE_NOTIFY
: GDK_ENTER_NOTIFY));
+ toplevel_x = (event->type == MotionNotify
+ ? event->xmotion.x + view->clip_left
+ : event->xcrossing.x + view->clip_left);
+ toplevel_y = (event->type == MotionNotify
+ ? event->xmotion.y + view->clip_top
+ : event->xcrossing.y + view->clip_top);
target = find_widget_at_pos (model->widgetwindow_osr,
- (event->type == MotionNotify
- ? event->xmotion.x + view->clip_left
- : event->xcrossing.x + view->clip_left),
- (event->type == MotionNotify
- ? event->xmotion.y + view->clip_top
- : event->xcrossing.y + view->clip_top),
- &x, &y);
+ toplevel_x, toplevel_y, &x, &y,
+ true, view);
}
#ifdef HAVE_XINPUT2
else
@@ -1420,9 +1964,11 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
? GDK_ENTER_NOTIFY
: GDK_LEAVE_NOTIFY);
target = find_widget_at_pos (model->widgetwindow_osr,
- lrint (xev->event_x + view->clip_left),
- lrint (xev->event_y + view->clip_top),
- &x, &y);
+ (toplevel_x
+ = lrint (xev->event_x + view->clip_left)),
+ (toplevel_y
+ = lrint (xev->event_y + view->clip_top)),
+ &x, &y, true, view);
}
#endif
@@ -1436,19 +1982,35 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
if (event->type == MotionNotify)
{
- xg_event->motion.x = x;
- xg_event->motion.y = y;
- xg_event->motion.x_root = event->xmotion.x_root;
- xg_event->motion.y_root = event->xmotion.y_root;
- xg_event->motion.time = event->xmotion.time;
- xg_event->motion.state = event->xmotion.state;
- xg_event->motion.device = find_suitable_pointer (view->frame);
+ if (!xw_maybe_synthesize_crossing (view, xg_event->any.window,
+ toplevel_x, toplevel_y,
+ XW_CROSSING_NONE, event->xmotion.time,
+ event->xmotion.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
+ {
+ xg_event->motion.x = x;
+ xg_event->motion.y = y;
+ xg_event->motion.x_root = event->xmotion.x_root;
+ xg_event->motion.y_root = event->xmotion.y_root;
+ xg_event->motion.time = event->xmotion.time;
+ xg_event->motion.state = event->xmotion.state;
+ xg_event->motion.device
+ = find_suitable_pointer (view->frame, false);
+ }
+ else
+ {
+ gdk_event_free (xg_event);
+ return;
+ }
}
#ifdef HAVE_XINPUT2
else if (event->type == GenericEvent)
{
- xg_event->crossing.x = (gdouble) xev->event_x;
- xg_event->crossing.y = (gdouble) xev->event_y;
+ xg_event->crossing.x = x;
+ xg_event->crossing.y = y;
xg_event->crossing.x_root = (gdouble) xev->root_x;
xg_event->crossing.y_root = (gdouble) xev->root_y;
xg_event->crossing.time = xev->time;
@@ -1467,11 +2029,45 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
xg_event->crossing.state |= GDK_BUTTON3_MASK;
}
- gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+ if (view->passive_grab
+ || xw_maybe_synthesize_crossing (view, xg_event->any.window,
+ toplevel_x, toplevel_y,
+ (xev->type == XI_Enter
+ ? XW_CROSSING_ENTERED
+ : XW_CROSSING_LEFT),
+ xev->time, xg_event->crossing.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
+ {
+ gdk_event_free (xg_event);
+ return;
+ }
+
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
}
#endif
else
{
+ if (view->passive_grab
+ || xw_maybe_synthesize_crossing (view, xg_event->any.window,
+ toplevel_x, toplevel_y,
+ (event->type == EnterNotify
+ ? XW_CROSSING_ENTERED
+ : XW_CROSSING_LEFT),
+ event->xcrossing.time,
+ event->xcrossing.state,
+ (view->passive_grab
+ ? GDK_CROSSING_GRAB
+ : GDK_CROSSING_NORMAL),
+ GDK_CROSSING_NORMAL))
+ {
+ gdk_event_free (xg_event);
+ return;
+ }
+
xg_event->crossing.detail = min (5, event->xcrossing.detail);
xg_event->crossing.time = event->xcrossing.time;
xg_event->crossing.x = x;
@@ -1479,7 +2075,8 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
xg_event->crossing.x_root = event->xcrossing.x_root;
xg_event->crossing.y_root = event->xcrossing.y_root;
xg_event->crossing.focus = event->xcrossing.focus;
- gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));
+ gdk_event_set_device (xg_event,
+ find_suitable_pointer (view->frame, false));
}
gtk_main_do_event (xg_event);
@@ -1505,7 +2102,8 @@ synthesize_focus_in_event (GtkWidget *offscreen_window)
if (FRAME_WINDOW_P (SELECTED_FRAME ()))
gdk_event_set_device (focus_event,
- find_suitable_pointer (SELECTED_FRAME ()));
+ find_suitable_pointer (SELECTED_FRAME (),
+ false));
g_object_ref (wnd);
@@ -1855,7 +2453,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))
memory_full (SIZE_MAX);
ptrdiff_t n = dlen;
@@ -2132,8 +2730,10 @@ xwidget_init_view (struct xwidget *xww,
xv->wdesc = None;
xv->frame = s->f;
- xv->cursor = cursor_for_hit (xww->hit_result, s->f);
+ xv->cursor = FRAME_OUTPUT_DATA (s->f)->nontext_cursor;
xv->just_resized = false;
+ xv->last_crossing_window = NULL;
+ xv->passive_grab = NULL;
#elif defined HAVE_PGTK
xv->dpyinfo = FRAME_DISPLAY_INFO (s->f);
xv->widget = gtk_drawing_area_new ();
@@ -2284,7 +2884,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
XISetMask (m, XI_ButtonRelease);
XISetMask (m, XI_Enter);
XISetMask (m, XI_Leave);
-#ifdef XI_GesturePinchBegin
+#ifdef HAVE_XINPUT2_4
if (FRAME_DISPLAY_INFO (s->f)->xi2_version >= 4)
{
XISetMask (m, XI_GesturePinchBegin);
@@ -2406,8 +3006,11 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
#endif
#if defined HAVE_XINPUT2 || defined HAVE_PGTK
- record_osr_embedder (xv);
- synthesize_focus_in_event (xww->widget_osr);
+ if (!NILP (xww->buffer))
+ {
+ record_osr_embedder (xv);
+ synthesize_focus_in_event (xww->widget_osr);
+ }
#endif
#ifdef USE_GTK
@@ -2756,6 +3359,22 @@ DEFUN ("delete-xwidget-view",
XDestroyWindow (xv->dpy, xv->wdesc);
Fremhash (make_fixnum (xv->wdesc), x_window_to_xwv_map);
}
+
+ if (xv->last_crossing_window)
+ g_signal_handler_disconnect (xv->last_crossing_window,
+ xv->last_crossing_cursor_signal);
+ g_clear_pointer (&xv->last_crossing_window,
+ g_object_unref);
+
+ if (xv->passive_grab)
+ {
+ g_signal_handler_disconnect (xv->passive_grab,
+ xv->passive_grab_destruction_signal);
+ g_signal_handler_disconnect (xv->passive_grab,
+ xv->passive_grab_drag_signal);
+ xv->passive_grab = NULL;
+ }
+
#else
gtk_widget_destroy (xv->widget);
#endif
@@ -3355,6 +3974,11 @@ syms_of_xwidget (void)
x_window_to_xwv_map = CALLN (Fmake_hash_table, QCtest, Qeq);
staticpro (&x_window_to_xwv_map);
+
+#if WEBKIT_CHECK_VERSION (2, 34, 0)
+ dummy_tooltip_string = build_string ("");
+ staticpro (&dummy_tooltip_string);
+#endif
#endif
}
diff --git a/src/xwidget.h b/src/xwidget.h
index ee74e53c4d1..502beb67650 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -118,6 +118,12 @@ struct xwidget_view
#ifndef HAVE_PGTK
Display *dpy;
Window wdesc;
+
+ GdkWindow *last_crossing_window;
+ guint last_crossing_cursor_signal;
+ GtkWidget *passive_grab;
+ guint passive_grab_destruction_signal;
+ guint passive_grab_drag_signal;
#else
struct pgtk_display_info *dpyinfo;
GtkWidget *widget;
@@ -217,7 +223,7 @@ extern void xwidget_motion_notify (struct xwidget_view *, double,
double, double, double, uint, Time);
extern void xwidget_scroll (struct xwidget_view *, double, double,
double, double, uint, Time, bool);
-#ifdef HAVE_USABLE_XI_GESTURE_PINCH_EVENT
+#ifdef HAVE_XINPUT2_4
extern void xwidget_pinch (struct xwidget_view *, XIGesturePinchEvent *);
#endif
#endif
diff --git a/test/Makefile.in b/test/Makefile.in
index d6ab7b244d2..1fa9d5f7d9d 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -49,19 +49,8 @@ SEPCHAR = @SEPCHAR@
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
-REPLACE_FREE = @REPLACE_FREE@
-
-include ${top_builddir}/src/verbose.mk
-# Load any GNU ELPA dependencies that are present, for optional tests.
-GNU_ELPA_DIRECTORY ?= $(srcdir)/../../elpa
-# Keep elpa_dependencies dependency-ordered.
-elpa_dependencies = \
- url-http-ntlm/url-http-ntlm.el \
- web-server/web-server.el
-elpa_els = $(addprefix $(GNU_ELPA_DIRECTORY)/packages/,$(elpa_dependencies))
-elpa_opts = $(foreach el,$(elpa_els),$(and $(wildcard $(el)),-L $(dir $(el)) -l $(el)))
-
# We never change directory before running Emacs, so a relative file
# name is fine, and makes life easier. If we need to change
# directory, we can use emacs --chdir.
@@ -72,10 +61,10 @@ EMACS_EXTRAOPT =
# Command line flags for Emacs.
# Apparently MSYS bash would convert "-L :" to "-L ;" anyway,
# but we might as well be explicit.
-EMACSOPT = --no-init-file --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(elpa_opts) $(EMACS_EXTRAOPT)
+EMACSOPT = --no-init-file --no-site-file --no-site-lisp -L "$(SEPCHAR)$(srcdir)" $(EMACS_EXTRAOPT)
# Prevent any settings in the user environment causing problems.
-unexport EMACSDATA EMACSDOC EMACSPATH GREP_OPTIONS XDG_CONFIG_HOME
+unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH GREP_OPTIONS XDG_CONFIG_HOME
# To run tests under a debugger, set this to eg: "gdb --args".
GDB =
@@ -101,7 +90,7 @@ export TEST_LOAD_EL ?= \
$(if $(findstring $(MAKECMDGOALS), all check check-maybe),no,yes)
# Additional settings for ert.
-ert_opts += $(elpa_opts)
+ert_opts =
# Maximum length of lines in ert backtraces; nil for no limit.
# (if empty, use the default ert-batch-backtrace-right-margin).
@@ -118,10 +107,8 @@ MODULES_EMACSOPT :=
endif
# The actual Emacs command run in the targets below.
-# Prevent any setting of EMACSLOADPATH in user environment causing problems,
-# and prevent locals to influence the text of the errors we expect to receive.
-emacs = LANG=C EMACSLOADPATH= \
- EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
+# Prevent locales influencing the text of the errors we expect to receive.
+emacs = LANG=C EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \
$(GDB) $(TEST_TIMEOUT) "$(EMACS)" $(MODULES_EMACSOPT) $(EMACSOPT)
# Set HOME to a nonexistent directory to prevent tests from accessing
@@ -164,13 +151,13 @@ endif
%.elc: %.el
$(AM_V_ELC)$(emacs) --batch -f batch-byte-compile $<
+ifdef EMACS_HYDRA_CI
+WRITE_LOG = 2>&1 | tee $@
+else
## Save logs, and show logs for failed tests.
WRITE_LOG = > $@ 2>&1 || { STAT=$$?; cat $@; exit $$STAT; }
-## On Hydra or Emba, always show logs for certain problematic tests.
-ifdef EMACS_HYDRA_CI
-lisp/net/tramp-tests.log \
-: WRITE_LOG = 2>&1 | tee $@
endif
+## On Emba, always show logs for certain problematic tests.
ifdef EMACS_EMBA_CI
lisp/filenotify-tests.log lisp/net/tramp-tests.log src/emacs-module-tests.log \
: WRITE_LOG = 2>&1 | tee $@
@@ -245,7 +232,7 @@ define test_template
.PHONY: $(1) $(notdir $(1))
$(1):
@test ! -f $(1).log || mv $(1).log $(1).log~
- @$(MAKE) $(1).log WRITE_LOG=
+ +@$(MAKE) $(1).log WRITE_LOG=
$(notdir $(1)): $(1)
endef
@@ -253,7 +240,8 @@ $(foreach test,${TESTS},$(eval $(call test_template,${test})))
## Get the tests for only a specific directory.
SUBDIRS = $(sort $(shell cd ${srcdir} && find lib-src lisp misc src -type d \
- ! \( -path "*resources*" -o -path "*auto-save-list" \) -print))
+ \( -name '*resources*' -prune \
+ -o ! -name '*auto-save-list' -print \)))
SUBDIR_TARGETS =
define subdir_template
@@ -276,27 +264,29 @@ endif
GMP_H = @GMP_H@
LIBGMP = @LIBGMP@
+LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
+LIB_NANOSLEEP = @LIB_NANOSLEEP@
-MODULE_CFLAGS = -I../src -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib \
+MODULE_CFLAGS = $(and $(GMP_H),-I.) -I../src -I$(srcdir)/../src \
$(FPIC_CFLAGS) $(PROFILING_CFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
+gmp.h:
+ echo '#include "$(srcdir)/../lib/mini-gmp.h"' >$@
+
test_module = $(test_module_dir)/mod-test${SO}
src/emacs-module-tests.log src/emacs-module-tests.elc: $(test_module)
-FREE_SOURCE_0 =
-FREE_SOURCE_1 = $(srcdir)/../lib/free.c
-
# In the compilation command, we can't use any object or archive file
# as source because those are not compiled with -fPIC. Therefore we
# use only source files.
-$(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h
+$(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h \
+ ../src/config.h $(and $(GMP_H),gmp.h)
$(AM_V_CCLD)${MKDIR_P} $(dir $@)
$(AM_V_at)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \
-o $@ $< $(LIBGMP) \
- $(and $(GMP_H),$(srcdir)/../lib/mini-gmp-gnulib.c) \
- $(FREE_SOURCE_$(REPLACE_FREE)) \
- $(srcdir)/../lib/timespec.c $(srcdir)/../lib/gettime.c
+ $(and $(GMP_H),$(srcdir)/../lib/mini-gmp.c) \
+ $(LIB_CLOCK_GETTIME) $(LIB_NANOSLEEP)
endif
src/emacs-tests.log: ../lib-src/seccomp-filter.c
@@ -351,12 +341,20 @@ mostlyclean:
-@for f in ${LOGFILES}; do test ! -f $$f || mv $$f $$f~; done
rm -f ./*.tmp
+# If 'find' supports -delete, it also supports -path. Otherwise, use
+# -prune and $(FIND_DELETE) instead. -prune is incompatible with -delete.
+ifeq ($(FIND_DELETE),-delete)
+CLEAN_XML_FILES = '(' -name '*.xml' -a ! -path '*resources*' ')' -delete
+else
+CLEAN_XML_FILES = -name '*resources*' -prune -o -name '*.xml' $(FIND_DELETE)
+endif
+
clean:
find . '(' -name '*.log' -o -name '*.log~' ')' $(FIND_DELETE)
- find . '(' -name '*.xml' -a ! -path '*resources*' ')' $(FIND_DELETE)
+ find . $(CLEAN_XML_FILES)
rm -f ${srcdir}/lisp/gnus/mml-sec-resources/random_seed
rm -f $(test_module_dir)/*.o $(test_module_dir)/*.so \
- $(test_module_dir)/*.dll
+ $(test_module_dir)/*.dll gmp.h
bootstrap-clean: clean
find $(srcdir) -name '*.elc' $(FIND_DELETE)
diff --git a/test/README b/test/README
index e44c4a43eeb..17783a4bacf 100644
--- a/test/README
+++ b/test/README
@@ -111,27 +111,22 @@ debugging. To do that, use
By default, ERT test failure summaries are quite brief in batch
mode--only the names of the failed tests are listed. If the
-$EMACS_TEST_VERBOSE environment variable is set, the failure summaries
-will also include the data from the failing test.
+$EMACS_TEST_VERBOSE environment variable is set and non-empty, the
+failure summaries will also include the data from the failing test.
If the $EMACS_TEST_JUNIT_REPORT environment variable is set to a file
name, a JUnit test report is generated under this name.
Some of the tests require a remote temporary directory
-(autorevert-tests.el, filenotify-tests.el, shadowfile-tests.el and
-tramp-tests.el). Per default, a mock-up connection method is used
-(this might not be possible when running on MS Windows). If you want
-to test a real remote connection, set $REMOTE_TEMPORARY_FILE_DIRECTORY
-to a suitable value in order to overwrite the default value:
+(autorevert-tests.el, dnd-tests.el, filenotify-tests.el,
+shadowfile-tests.el and tramp-tests.el). Per default, a mock-up
+connection method is used (this might not be possible when running on
+MS Windows). If you want to test a real remote connection, set
+$REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
+overwrite the default value:
env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make ...
-Some optional tests require packages from GNU ELPA. By default
-../../elpa will be checked for these packages. If GNU ELPA is checked
-out somewhere else, use
-
- make GNU_ELPA_DIRECTORY=/path/to/elpa ...
-
There are also continuous integration tests on
<https://hydra.nixos.org/jobset/gnu/emacs-trunk> (see
diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el
index 394eae48ee3..947178473e4 100644
--- a/test/lisp/abbrev-tests.el
+++ b/test/lisp/abbrev-tests.el
@@ -301,6 +301,10 @@
(inverse-add-abbrev table "Global" -1)))
(should (string= (abbrev-expansion "text" table) "bar"))))
+(ert-deftest test-abbrev-table-p ()
+ (should-not (abbrev-table-p translation-table-vector))
+ (should (abbrev-table-p (make-abbrev-table))))
+
(provide 'abbrev-tests)
;;; abbrev-tests.el ends here
diff --git a/test/lisp/ansi-color-tests.el b/test/lisp/ansi-color-tests.el
index 71b706c763f..1b04e8e9def 100644
--- a/test/lisp/ansi-color-tests.el
+++ b/test/lisp/ansi-color-tests.el
@@ -171,7 +171,25 @@ strings with `eq', this function compares them with `equal'."
(insert str)
(ansi-color-apply-on-region opoint (point))))
(should (ansi-color-tests-equal-props
- propertized-str (buffer-string))))))
+ propertized-str (buffer-string))))
+
+ ;; \e not followed by '[' and invalid ANSI escape sequences
+ (dolist (fun (list ansi-filt ansi-app))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e") ""))
+ (should (equal (funcall fun "\e[33m test \e[0m")
+ (with-temp-buffer
+ (concat "\e" (funcall fun "\e[33m test \e[0m"))))))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e[") ""))
+ (should (equal (funcall fun "\e[33m Z \e[0m")
+ (with-temp-buffer
+ (concat "\e[" (funcall fun "\e[33m Z \e[0m"))))))
+ (with-temp-buffer
+ (should (equal (funcall fun "\e a \e\e[\e[") "\e a \e\e["))
+ (should (equal (funcall fun "\e[33m Z \e[0m")
+ (with-temp-buffer
+ (concat "\e[" (funcall fun "\e[33m Z \e[0m")))))))))
(provide 'ansi-color-tests)
diff --git a/test/lisp/auth-source-tests.el b/test/lisp/auth-source-tests.el
index 7060d9570eb..41f8b6d8c9d 100644
--- a/test/lisp/auth-source-tests.el
+++ b/test/lisp/auth-source-tests.el
@@ -295,11 +295,7 @@
(setq found (apply #'auth-source-search parameters))
(when (listp found)
(dolist (f found)
- (setf f (plist-put f :secret
- (let ((secret (plist-get f :secret)))
- (if (functionp secret)
- (funcall secret)
- secret))))))
+ (setf f (plist-put f :secret (auth-info-password f)))))
(setq found-as-string (format "%s: %S" testname found))
;; (message "With parameters %S found: [%s] needed: [%s]"
@@ -326,10 +322,7 @@
auth-info
(car (auth-source-search
:max 1 :host host :require '(:user :secret) :create t))
- auth-passwd (plist-get auth-info :secret)
- auth-passwd (if (functionp auth-passwd)
- (funcall auth-passwd)
- auth-passwd))
+ auth-passwd (auth-info-password auth-info))
(should (string-equal (plist-get auth-info :user) (user-login-name)))
(should (string-equal (plist-get auth-info :host) host))
(should (equal auth-passwd passwd))
@@ -339,10 +332,7 @@
;; Check, that the item has been created indeed.
(auth-source-forget+ :host t)
(setq auth-info (car (auth-source-search :host host))
- auth-passwd (plist-get auth-info :secret)
- auth-passwd (if (functionp auth-passwd)
- (funcall auth-passwd)
- auth-passwd))
+ auth-passwd (auth-info-password auth-info))
(if (zerop (length passwd))
(progn
(should-not (plist-get auth-info :user))
@@ -377,10 +367,7 @@
auth-info
(car (auth-source-search
:max 1 :host host :require '(:user :secret) :create t))
- auth-passwd (plist-get auth-info :secret)
- auth-passwd (if (functionp auth-passwd)
- (funcall auth-passwd)
- auth-passwd))
+ auth-passwd (auth-info-password auth-info))
(should (string-equal (plist-get auth-info :user) (user-login-name)))
(should (string-equal (plist-get auth-info :host) host))
(should (equal auth-passwd passwd))
@@ -391,10 +378,7 @@
(auth-source-forget+ :host t)
(setq auth-source-netrc-cache nil)
(setq auth-info (car (auth-source-search :host host))
- auth-passwd (plist-get auth-info :secret)
- auth-passwd (if (functionp auth-passwd)
- (funcall auth-passwd)
- auth-passwd))
+ auth-passwd (auth-info-password auth-info))
(with-temp-buffer
(insert-file-contents netrc-file)
(if (zerop (length passwd))
@@ -421,9 +405,7 @@ machine c1 port c2 user c3 password c4\n"
(parameters '(:max 1 :host t))
(found (apply #'auth-source-delete parameters)))
(dolist (f found)
- (let ((s (plist-get f :secret)))
- (setf f (plist-put f :secret
- (if (functionp s) (funcall s) s)))))
+ (setf f (plist-put f :secret (auth-info-password f))))
;; Note: The netrc backend doesn't delete anything, so
;; this is actually the same as `auth-source-search'.
(should (equal found expected)))))
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index d26e0f5a159..54b1a16b5db 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -52,10 +52,9 @@
;;; Code:
-(require 'ert)
+(require 'tramp)
(require 'ert-x)
(require 'autorevert)
-(require 'tramp)
(setq auto-revert-debug nil
auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
@@ -70,30 +69,6 @@
(defvar auto-revert--messages nil
"Used to collect messages issued during a section of a test.")
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst auto-revert-test-remote-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
- ;; batch mode only, therefore. `temporary-file-directory' might
- ;; be quoted, so we unquote it just in case.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" (file-name-unquote temporary-file-directory)))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
-
;; Filter suppressed remote file-notify libraries.
(when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY"))
(dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir"))
@@ -114,10 +89,9 @@ being the result.")
t (ignore-errors
(and
(not (getenv "EMACS_HYDRA_CI"))
- (file-remote-p auto-revert-test-remote-temporary-file-directory)
- (file-directory-p auto-revert-test-remote-temporary-file-directory)
- (file-writable-p
- auto-revert-test-remote-temporary-file-directory))))))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))))
;; Return result.
(cdr auto-revert--test-enabled-remote-checked))
@@ -146,7 +120,7 @@ This expects `auto-revert--messages' to be bound by
,docstring
:tags '(:expensive-test :unstable)
(let ((temporary-file-directory
- auto-revert-test-remote-temporary-file-directory)
+ ert-remote-temporary-file-directory)
(auto-revert-remote-files t)
(ert-test (ert-get-test ',test))
vc-handled-backends)
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index ae7331fcc2b..3bea08bc37a 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -197,6 +197,9 @@ the lexically-bound variable `buffer'."
(bookmark-maybe-historicize-string "foo")
(should (equal (car bookmark-history) "foo"))))
+(defun bookmark-remove-last-modified (bmk)
+ (assoc-delete-all 'last-modified bmk))
+
(ert-deftest bookmark-tests-make-record ()
(with-bookmark-test-file
(let* ((record `("example.txt" (filename . ,bookmark-tests-example-file)
@@ -206,9 +209,11 @@ the lexically-bound variable `buffer'."
(defaults "example.txt"))))
(with-current-buffer buffer
(goto-char 3)
- (should (equal (bookmark-make-record) record))
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))
;; calling twice gives same record
- (should (equal (bookmark-make-record) record))))))
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))))))
(ert-deftest bookmark-tests-make-record-list ()
(with-bookmark-test-file-list
@@ -219,9 +224,11 @@ the lexically-bound variable `buffer'."
(defaults "example.txt"))))
(with-current-buffer buffer
(goto-char 3)
- (should (equal (bookmark-make-record) record))
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))
;; calling twice gives same record
- (should (equal (bookmark-make-record) record))))))
+ (should (equal (bookmark-remove-last-modified (bookmark-make-record))
+ record))))))
(ert-deftest bookmark-tests-make-record-function ()
(with-bookmark-test
@@ -255,15 +262,18 @@ the lexically-bound variable `buffer'."
;; Set first bookmark
(goto-char (point-min))
(bookmark-set "foo")
- (should (equal bookmark-alist (list bmk1)))
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1)))
;; Replace that bookmark
(goto-char (point-max))
(bookmark-set "foo")
- (should (equal bookmark-alist (list bmk2)))
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk2)))
;; Push another bookmark with the same name
(goto-char (point-min))
(bookmark-set "foo" t) ; NO-OVERWRITE is t
- (should (equal bookmark-alist (list bmk1 bmk2)))
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1 bmk2)))
;; 2. bookmark-set-no-overwrite
;; Don't overwrite
@@ -271,11 +281,13 @@ the lexically-bound variable `buffer'."
;; Set new bookmark
(setq bookmark-alist nil)
(bookmark-set-no-overwrite "foo")
- (should (equal bookmark-alist (list bmk1)))
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk1)))
;; Push another bookmark with the same name
(goto-char (point-max))
(bookmark-set-no-overwrite "foo" t) ; PUSH-BOOKMARK is t
- (should (equal bookmark-alist (list bmk2 bmk1)))
+ (should (equal (mapcar #'bookmark-remove-last-modified bookmark-alist)
+ (list bmk2 bmk1)))
;; 3. bookmark-set-internal
(should-error (bookmark-set-internal "foo" "bar" t))))))
@@ -289,7 +301,7 @@ the lexically-bound variable `buffer'."
(bookmark-set "foo")
(should (equal major-mode 'bookmark-edit-annotation-mode))
;; Should return to the original buffer
- (bookmark-send-edited-annotation)
+ (bookmark-edit-annotation-confirm)
(should (equal (current-buffer) buffer))))))
(ert-deftest bookmark-tests-kill-line ()
@@ -322,7 +334,7 @@ the lexically-bound variable `buffer'."
(with-bookmark-test
(bookmark-edit-annotation "name")
(insert "new text")
- (bookmark-send-edited-annotation)
+ (bookmark-edit-annotation-confirm)
(should (equal (bookmark-get-annotation "name") "new text"))))
(ert-deftest bookmark-tests-jump ()
@@ -459,7 +471,7 @@ testing `bookmark-bmenu-list'."
(with-bookmark-bmenu-test
(bookmark-bmenu-edit-annotation)
(insert "foo")
- (bookmark-send-edited-annotation)
+ (bookmark-edit-annotation-confirm)
(should (equal (bookmark-get-annotation "name") "foo"))))
(ert-deftest bookmark-test-bmenu-send-edited-annotation/restore-focus ()
@@ -467,7 +479,7 @@ testing `bookmark-bmenu-list'."
(with-bookmark-bmenu-test
(bookmark-bmenu-edit-annotation)
(insert "foo")
- (bookmark-send-edited-annotation)
+ (bookmark-edit-annotation-confirm)
(should (equal (buffer-name (current-buffer)) bookmark-bmenu-buffer))
(beginning-of-line)
(forward-char 4)
diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el
index 892fd278df8..56cb9057ed9 100644
--- a/test/lisp/calc/calc-tests.el
+++ b/test/lisp/calc/calc-tests.el
@@ -38,7 +38,7 @@
;; be used to compare such calc expressions.
(defun calc-tests-equal (a b)
"Like `equal' but allow for different representations of numbers.
-For example: (calc-tests-equal 10 '(float 1 1)) => t.
+For example: (calc-tests-equal 10 \\='(float 1 1)) => t.
A and B should be calc expressions."
(cond ((math-numberp a)
(and (math-numberp b)
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el
index c918b0f63fa..ac7a84aa571 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -1639,19 +1639,17 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30
"2004-09-17T03:09:10+0000"))
(let ((orig (icalendar-test--format "20040917T050910")))
(unwind-protect
- (progn
- (set-time-zone-rule "UTC-02:00")
- (should (equal (icalendar-test--format "20040917T050910")
+ (let ((zone "XXX-02"))
+ (should (equal (icalendar-test--format "20040917T050910" nil zone)
"2004-09-17T03:09:10+0000"))
- (should (equal (icalendar-test--format "20040917T0509")
+ (should (equal (icalendar-test--format "20040917T0509" nil zone)
"2004-09-17T03:09:00+0000"))
- (should (equal (icalendar-test--format "20040917")
+ (should (equal (icalendar-test--format "20040917" nil zone)
"2004-09-16T22:00:00+0000"))
- (should (equal (icalendar-test--format "20040917T050910" 1)
+ (should (equal (icalendar-test--format "20040917T050910" 1 zone)
"2004-09-18T03:09:10+0000"))
- (should (equal (icalendar-test--format "20040917T050910" 30)
+ (should (equal (icalendar-test--format "20040917T050910" 30 zone)
"2004-10-17T03:09:10+0000")))
- (set-time-zone-rule 'wall) ;; (set-time-zone-rule nil) is broken
(should (equal orig (icalendar-test--format "20040917T050910")))))
(should (equal (icalendar-test--format "20040917T050910Z")
"2004-09-17T05:09:10+0000"))
diff --git a/test/lisp/calendar/iso8601-tests.el b/test/lisp/calendar/iso8601-tests.el
index 6c9e85ec920..f64c498c027 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -82,9 +82,9 @@
(should (equal (iso8601-parse "2008-03-02T13:47:30Z")
'(30 47 13 2 3 2008 nil nil 0)))
(should (equal (iso8601-parse "2008-03-02T13:47:30+01:00")
- '(30 47 13 2 3 2008 nil nil 3600)))
+ '(30 47 13 2 3 2008 nil -1 3600)))
(should (equal (iso8601-parse "2008-03-02T13:47:30-01")
- '(30 47 13 2 3 2008 nil nil -3600))))
+ '(30 47 13 2 3 2008 nil -1 -3600))))
(ert-deftest test-iso8601-duration ()
(should (equal (iso8601-parse-duration "P3Y6M4DT12H30M5S")
@@ -221,24 +221,24 @@
(ert-deftest standard-test-time-of-day-zone ()
(should (equal (iso8601-parse-time "152746+0100")
- '(46 27 15 nil nil nil nil nil 3600)))
+ '(46 27 15 nil nil nil nil -1 3600)))
(should (equal (iso8601-parse-time "15:27:46+0100")
- '(46 27 15 nil nil nil nil nil 3600)))
+ '(46 27 15 nil nil nil nil -1 3600)))
(should (equal (iso8601-parse-time "152746+01")
- '(46 27 15 nil nil nil nil nil 3600)))
+ '(46 27 15 nil nil nil nil -1 3600)))
(should (equal (iso8601-parse-time "15:27:46+01")
- '(46 27 15 nil nil nil nil nil 3600)))
+ '(46 27 15 nil nil nil nil -1 3600)))
(should (equal (iso8601-parse-time "152746-0500")
- '(46 27 15 nil nil nil nil nil -18000)))
+ '(46 27 15 nil nil nil nil -1 -18000)))
(should (equal (iso8601-parse-time "15:27:46-0500")
- '(46 27 15 nil nil nil nil nil -18000)))
+ '(46 27 15 nil nil nil nil -1 -18000)))
(should (equal (iso8601-parse-time "152746-05")
- '(46 27 15 nil nil nil nil nil -18000)))
+ '(46 27 15 nil nil nil nil -1 -18000)))
(should (equal (iso8601-parse-time "15:27:46-05")
- '(46 27 15 nil nil nil nil nil -18000))))
+ '(46 27 15 nil nil nil nil -1 -18000))))
(defun test-iso8601-format-time-string-zone-round-trip (offset-minutes z-format)
diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el
index 5a37c914931..fd4d5ac8a1b 100644
--- a/test/lisp/calendar/time-date-tests.el
+++ b/test/lisp/calendar/time-date-tests.el
@@ -88,14 +88,19 @@
(ert-deftest test-format-seconds ()
(should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %"))
(should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %"))
- (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) " 1 %"))
+ (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %"))
(should (equal (format-seconds "%mm %ss" 66) "1m 6s"))
(should (equal (format-seconds "%mm %5ss" 66) "1m 6s"))
(should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s"))
(should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s"))
(should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s"))
- (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s")))
+ (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s"))
+
+ (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m"))
+ (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s"))
+ (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m"))
+ (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s")))
(ert-deftest test-ordinal ()
(should (equal (date-ordinal-to-time 2008 271)
diff --git a/test/lisp/cedet/cedet-files-tests.el b/test/lisp/cedet/cedet-files-tests.el
index d264410e3cb..daaf3edfc4e 100644
--- a/test/lisp/cedet/cedet-files-tests.el
+++ b/test/lisp/cedet/cedet-files-tests.el
@@ -29,20 +29,17 @@
(require 'cedet-files)
(defvar cedet-files-utest-list
- '(
- ( "/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c" )
- ( "c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el" )
- ( "//windows/proj/foo.java" . "!!windows!proj!foo.java" )
- ( "/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c" )
- )
- "List of different file names to test.
-Each entry is a cons cell of ( FNAME . CONVERTED )
+ '(("/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c")
+ ("c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el")
+ ("//windows/proj/foo.java" . "!!windows!proj!foo.java")
+ ("/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c"))
+ "List of file names to test.
+Each entry is a cons cell of (FNAME . CONVERTED)
where FNAME is some file name, and CONVERTED is what it should be
converted into.")
(ert-deftest cedet-files-utest ()
- "Test out some file name conversions."
- (interactive)
+ "Test some file name conversions."
(dolist (FT cedet-files-utest-list)
(let ((dir->file (cedet-directory-name-to-file-name (car FT) t))
(file->dir (cedet-file-name-to-directory-name (cdr FT) t)))
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
index e7d85101a1a..f5b6d641842 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
@@ -20,7 +20,7 @@
// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-// Note: initially provided by by Alex Ott.
+// Note: initially provided by Alex Ott.
template <typename DerivedT>
struct grammar {
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el b/test/lisp/cedet/semantic/bovine/gcc-tests.el
index 2e61f91e58c..041773a0c80 100644
--- a/test/lisp/cedet/semantic/bovine/gcc-tests.el
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -26,6 +26,7 @@
;;; Code:
(require 'ert)
+(require 'ert-x)
(require 'semantic/bovine/gcc)
;;; From bovine-gcc:
@@ -122,14 +123,9 @@ gcc version 2.95.2 19991024 (release)"
(ert-deftest semantic-gcc-test-output-parser-this-machine ()
"Test the output parser against the machine currently running Emacs."
- (skip-unless (executable-find "gcc"))
+ (skip-unless (and (executable-find "gcc")
+ (not (ert-gcc-is-clang-p))))
(let ((semantic-gcc-test-strings (list (semantic-gcc-query "gcc" "-v"))))
- ;; Some macOS machines run llvm when you type gcc. (!)
- ;; We can't even check if it's a symlink; it's a binary placed in
- ;; "/usr/bin/gcc". So check the output and just skip this test if
- ;; it looks like that's the case.
- (unless (string-match "Apple \\(LLVM\\|clang\\)\\|Xcode\\.app"
- (car semantic-gcc-test-strings))
- (semantic-gcc-test-output-parser))))
+ (semantic-gcc-test-output-parser)))
;;; gcc-tests.el ends here
diff --git a/test/lisp/cedet/srecode-utest-template.el b/test/lisp/cedet/srecode-utest-template.el
index 1eb91e6053b..87c28c6af12 100644
--- a/test/lisp/cedet/srecode-utest-template.el
+++ b/test/lisp/cedet/srecode-utest-template.el
@@ -33,7 +33,7 @@
;;; MAP DUMP TESTING
(defun srecode-utest-map-reset ()
"Reset, then dump the map of SRecoder templates.
-Probably should be called 'describe-srecode-maps'."
+Probably should be called `describe-srecode-maps'."
(interactive)
(message "SRecode Template Path: %S" srecode-map-load-path)
;; Interactive call allows us to dump.
diff --git a/test/lisp/cedet/srecode/document-tests.el b/test/lisp/cedet/srecode/document-tests.el
index 71c4cd7410b..5341bb09366 100644
--- a/test/lisp/cedet/srecode/document-tests.el
+++ b/test/lisp/cedet/srecode/document-tests.el
@@ -35,8 +35,6 @@
"Test old comment extraction.
Dump out the extracted dictionary."
:tags '(:unstable)
- (interactive)
-
(srecode-load-tables-for-mode major-mode)
(srecode-load-tables-for-mode major-mode 'document)
diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el
index 49b632c8410..e4e1eda26d3 100644
--- a/test/lisp/color-tests.el
+++ b/test/lisp/color-tests.el
@@ -220,32 +220,32 @@
(ert-deftest color-tests-lighten-hsl ()
(should (equal (color-lighten-hsl 360 0.5 0.5 0) '(360 0.5 0.5)))
- (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.4)))
+ (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.45)))
(should (equal (color-lighten-hsl 360 0.5 0.5 -500) '(360 0.5 0.0)))
(should
(color-tests--approx-equal
- (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.85)))
+ (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.84)))
(should
(equal (color-lighten-hsl 120 0.5 0.8 500) '(120 0.5 1.0))))
(ert-deftest color-tests-lighten-name ()
- (should (equal (color-lighten-name "black" 100) "#ffffffffffff"))
+ (should (equal (color-lighten-name "black" 100) "#000000000000"))
(should (equal (color-lighten-name "white" 100) "#ffffffffffff"))
(should (equal (color-lighten-name "red" 0) "#ffff00000000"))
- (should (equal (color-lighten-name "red" 10) "#ffff33323332")))
+ (should (equal (color-lighten-name "red" 10) "#ffff19991999")))
(ert-deftest color-tests-darken-hsl ()
(should (equal (color-darken-hsl 360 0.5 0.5 0) '(360 0.5 0.5)))
- (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.6)))
+ (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.55)))
(should (equal (color-darken-hsl 360 0.5 0.5 -500) '(360 0.5 1.0)))
- (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.75)))
+ (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.76)))
(should (equal (color-darken-hsl 120 0.5 0.8 500) '(120 0.5 0.0))))
(ert-deftest color-tests-darken-name ()
(should (equal (color-darken-name "black" 100) "#000000000000"))
(should (equal (color-darken-name "white" 100) "#000000000000"))
(should (equal (color-darken-name "red" 0) "#ffff00000000"))
- (should (equal (color-darken-name "red" 10) "#cccc00000000")))
+ (should (equal (color-darken-name "red" 10) "#e66500000000")))
(provide 'color-tests)
;;; color-tests.el ends here
diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el
index 01a1407dcaa..0ef5168109b 100644
--- a/test/lisp/cus-edit-tests.el
+++ b/test/lisp/cus-edit-tests.el
@@ -76,5 +76,14 @@
(customize-saved)
(should (search-forward cus-edit-tests--obsolete-option-tag nil t)))))
+(defcustom cus-edit-test-foo1 0
+ ""
+ :type 'number)
+
+(ert-deftest test-setopt ()
+ (should (= (setopt cus-edit-test-foo1 1) 1))
+ (should (= cus-edit-test-foo1 1))
+ (should-error (setopt cus-edit-test-foo1 :foo)))
+
(provide 'cus-edit-tests)
;;; cus-edit-tests.el ends here
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index 77bb337d6aa..d1effaa72a8 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -24,6 +24,7 @@
(require 'wid-edit)
(require 'cus-edit)
+(require 'bytecomp)
(ert-deftest custom-theme--load-path ()
"Test `custom-theme--load-path' behavior."
diff --git a/test/lisp/desktop-tests.el b/test/lisp/desktop-tests.el
new file mode 100644
index 00000000000..d52fe39ed96
--- /dev/null
+++ b/test/lisp/desktop-tests.el
@@ -0,0 +1,50 @@
+;;; desktop-tests.el --- Tests for desktop.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'desktop)
+
+(ert-deftest desktop-tests--emacs-pid-running-p ()
+ (should (desktop--emacs-pid-running-p (emacs-pid)))
+ (should-not (desktop--emacs-pid-running-p 1)))
+
+(ert-deftest desktop-tests--load-locked-desktop-p ()
+ (let ((desktop-load-locked-desktop t))
+ (should (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-nil ()
+ (let ((desktop-load-locked-desktop nil))
+ (should-not (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-ask ()
+ (let ((desktop-load-locked-desktop 'ask))
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) t)))
+ (should (desktop--load-locked-desktop-p (emacs-pid))))
+ (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) nil)))
+ (should-not (desktop--load-locked-desktop-p (emacs-pid))))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-check ()
+ (let ((desktop-load-locked-desktop 'check-pid))
+ (desktop--load-locked-desktop-p (emacs-pid))))
+
+(provide 'desktop-tests)
diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el
new file mode 100644
index 00000000000..88f6e694577
--- /dev/null
+++ b/test/lisp/dnd-tests.el
@@ -0,0 +1,441 @@
+;;; dnd-tests.el --- Tests for window system independent DND support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for stuff in dnd.el that doesn't require a window system.
+
+;; The drag API tests only check the behavior of the simplified drag
+;; APIs in dnd.el. Actual drags are not performed during the
+;; automated testing process (make check), but some of the tests can
+;; also be run under X.
+
+;;; Code:
+
+(require 'dnd)
+(require 'cl-lib)
+(require 'tramp)
+(require 'select)
+(require 'ert-x)
+
+(defvar dnd-tests-selection-table nil
+ "Alist of selection names to their values.")
+
+(defvar x-treat-local-requests-remotely)
+(defvar x-dnd-preserve-selection-data)
+
+;; Define some replacements for functions used by the drag-and-drop
+;; code on X when running under something else.
+(unless (eq window-system 'x)
+ ;; Substitute for x-begin-drag, which isn't present on all systems.
+ (defalias 'x-begin-drag
+ (lambda (_targets &optional action frame &rest _)
+ ;; Verify that frame is either nil or a valid frame.
+ (when (and frame (not (frame-live-p frame)))
+ (signal 'wrong-type-argument frame))
+ ;; Verify that the action is valid and pretend the drag succeeded
+ ;; (by returning the action).
+ (cl-ecase action
+ ('XdndActionCopy action)
+ ('XdndActionMove action)
+ ('XdndActionLink action)
+ ;; These two are not technically valid, but x-begin-drag accepts
+ ;; them anyway.
+ ('XdndActionPrivate action)
+ ('XdndActionAsk 'XdndActionPrivate))))
+
+ ;; This doesn't work during tests.
+ (defalias 'gui-set-selection
+ (lambda (type data)
+ (or (gui--valid-simple-selection-p data)
+ (and (vectorp data)
+ (let ((valid t))
+ (dotimes (i (length data))
+ (or (gui--valid-simple-selection-p (aref data i))
+ (setq valid nil)))
+ valid))
+ (signal 'error (list "invalid selection" data)))
+ (setf (alist-get type dnd-tests-selection-table) data))))
+
+(declare-function x-get-selection-internal "xselect.c")
+
+(defun dnd-tests-verify-selection-data (type)
+ "Return the data of the drag-and-drop selection converted to TYPE."
+ (if (eq window-system 'x)
+ (let ((x-treat-local-requests-remotely t))
+ (x-get-selection-internal 'XdndSelection type))
+ (let* ((basic-value (cdr (assq 'XdndSelection
+ dnd-tests-selection-table)))
+ (local-value (if (stringp basic-value)
+ (or (get-text-property 0 type basic-value)
+ basic-value)
+ basic-value))
+ (converter-list (cdr (assq type selection-converter-alist)))
+ (converter (if (consp converter-list)
+ (cdr converter-list)
+ converter-list)))
+ (if (and local-value converter)
+ (funcall converter 'XdndSelection type local-value)
+ (error "No selection converter or local value: %s" type)))))
+
+(defun dnd-tests-remote-accessible-p ()
+ "Return if a test involving remote files can proceed."
+ (ignore-errors
+ (and
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))
+
+(defun dnd-tests-make-temp-name ()
+ "Return a temporary remote file name for test.
+The temporary file is not created."
+ (expand-file-name (make-temp-name "dnd-test-remote")
+ ert-remote-temporary-file-directory))
+
+(defun dnd-tests-parse-tt-netfile (netfile)
+ "Parse NETFILE and return its components.
+NETFILE should be a canonicalized ToolTalk file name.
+Return a list of its hostname, real path, and local path."
+ (save-match-data
+ (when (string-match (concat "HOST=0-\\([[:digit:]]+\\),RPATH=\\([[:digit:]]+\\)-"
+ "\\([[:digit:]]+\\),LPATH=\\([[:digit:]]+\\)-"
+ "\\([[:digit:]]+\\)\\(:\\)")
+ netfile)
+ (let ((beg (match-end 6)))
+ (list (substring netfile beg
+ (+ beg 1
+ (string-to-number (match-string 1 netfile))))
+ (substring netfile
+ (+ beg
+ (string-to-number (match-string 2 netfile)))
+ (+ beg 1
+ (string-to-number (match-string 3 netfile))))
+ (substring netfile
+ (+ beg
+ (string-to-number (match-string 4 netfile)))
+ (+ beg 1
+ (string-to-number (match-string 5 netfile)))))))))
+
+(defun dnd-tests-extract-selection-data (selection expect-cons)
+ "Return the selection data in SELECTION.
+SELECTION can either be the value of `gui-get-selection', or the
+return value of a selection converter.
+
+If EXPECT-CONS, then expect SELECTION to be a cons (when not
+running under X).
+
+This function only tries to handle strings."
+ (when (and expect-cons (not (eq window-system 'x)))
+ (should (and (consp selection)
+ (stringp (cdr selection)))))
+ (if (stringp selection)
+ selection
+ (cdr selection)))
+
+(ert-deftest dnd-tests-begin-text-drag ()
+ ;; When running this test under X, please make sure to drop onto a
+ ;; program with reasonably correct behavior, such as dtpad, gedit,
+ ;; or Mozilla.
+ ;; ASCII Latin-1 UTF-8
+ (let ((test-text "hello, everyone! sæl öllsömul! всем привет")
+ (x-dnd-preserve-selection-data t))
+ ;; Verify that dragging works.
+ (should (eq (dnd-begin-text-drag test-text) 'copy))
+ (should (eq (dnd-begin-text-drag test-text nil 'move) 'move))
+ ;; Verify that the important data types are converted correctly.
+ (let ((string-data (dnd-tests-verify-selection-data 'STRING)))
+ ;; Check that the Latin-1 target is converted correctly.
+ (should (equal (dnd-tests-extract-selection-data string-data t)
+ (encode-coding-string test-text
+ 'iso-8859-1))))
+ ;; And that UTF8_STRING and the Xdnd UTF8 string are as well.
+ (let* ((string-data (dnd-tests-verify-selection-data
+ 'UTF8_STRING))
+ (string-data-1 (dnd-tests-verify-selection-data
+ 'text/plain\;charset=utf-8))
+ (extracted-1 (dnd-tests-extract-selection-data string-data-1 t))
+ (extracted (dnd-tests-extract-selection-data string-data t)))
+ (should (and (stringp extracted) (stringp extracted-1)))
+ (should (equal extracted extracted)))
+ ;; Now check text/plain.
+ (let ((string-data (dnd-tests-verify-selection-data
+ 'text/plain)))
+ (should (equal (dnd-tests-extract-selection-data string-data t)
+ (encode-coding-string test-text 'ascii))))))
+
+(ert-deftest dnd-tests-begin-file-drag ()
+ ;; These tests also involve handling remote file names.
+ (skip-unless (and (dnd-tests-remote-accessible-p)
+ ;; TODO: make these tests work under X.
+ (not (eq window-system 'x))))
+ (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (normal-multibyte-file (expand-file-name
+ (make-temp-name "тест-на-перетаскивание")
+ temporary-file-directory))
+ (remote-temp-file (dnd-tests-make-temp-name))
+ (x-dnd-preserve-selection-data t))
+ ;; Touch those files if they don't exist.
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p normal-multibyte-file)
+ (write-region "" 0 normal-multibyte-file))
+ (unless (file-exists-p remote-temp-file)
+ (write-region "" 0 remote-temp-file))
+ (unwind-protect
+ (progn
+ ;; Now test dragging a normal file.
+ (should (eq (dnd-begin-file-drag normal-temp-file) 'copy))
+ ;; Test that the selection data is correct.
+ (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list)))
+ (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username))
+ (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME)))
+ (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME)))
+ (netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE))))
+ ;; Check if the URI list is formatted correctly.
+ (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t))
+ (decoded (dnd-get-local-file-name (car split-uri-list))))
+ (should (equal decoded normal-temp-file)))
+ ;; Test that the username reported is correct.
+ (should (equal username-data (user-real-login-name)))
+ ;; Test that the file name data is correct.
+ (let* ((split-file-names (split-string file-name-data "\0"))
+ (file-name (car split-file-names)))
+ ;; Make sure there are no extra leading or trailing NULL bytes.
+ (should (and split-file-names (null (cdr split-file-names))))
+ ;; Make sure the file name is encoded correctly;
+ (should-not (multibyte-string-p file-name))
+ ;; Make sure decoding the file name results in the
+ ;; originals.
+ (should (equal (decode-coding-string file-name
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file))
+ ;; Also make sure the hostname is correct.
+ (should (equal host-name-data (system-name))))
+ ;; Check that the netfile hostname, rpath and lpath are correct.
+ (let ((parsed (dnd-tests-parse-tt-netfile netfile-data))
+ (filename (encode-coding-string normal-temp-file
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal (nth 0 parsed) (system-name)))
+ (should (equal (nth 1 parsed) filename))
+ (should (equal (nth 2 parsed) filename))))
+ ;; And the remote file.
+ (should (eq (dnd-begin-file-drag remote-temp-file) 'copy))
+ ;; Test that the remote file was added to the list of files
+ ;; to remove later.
+ (should dnd-last-dragged-remote-file)
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test that the remote file was removed.
+ (should (progn
+ (dnd-begin-file-drag normal-temp-file)
+ (not dnd-last-dragged-remote-file)))
+ ;; Make sure the remote file removal hook was deleted.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test that links to remote files can't be created.
+ (should-error (dnd-begin-file-drag remote-temp-file nil 'link))
+ ;; Test dragging a file with a multibyte filename.
+ (should (eq (dnd-begin-file-drag normal-multibyte-file) 'copy))
+ ;; Test that the ToolTalk filename is encodes and decodes correctly.
+ (let* ((netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE)))
+ (parsed (dnd-tests-parse-tt-netfile netfile-data))
+ (filename (encode-coding-string normal-multibyte-file
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal (nth 0 parsed) (system-name)))
+ (should (equal (nth 1 parsed) filename))
+ (should (equal (nth 2 parsed) filename))))
+ (delete-file normal-temp-file)
+ (delete-file normal-multibyte-file)
+ (delete-file remote-temp-file))))
+
+(ert-deftest dnd-tests-begin-drag-files ()
+ (skip-unless (and (dnd-tests-remote-accessible-p)
+ ;; TODO: make these tests work under X.
+ (not (eq window-system 'x))))
+ (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (normal-temp-file-1 (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (remote-temp-file (dnd-tests-make-temp-name))
+ (nonexistent-local-file
+ (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory))
+ (nonexistent-remote-file (dnd-tests-make-temp-name))
+ (nonexistent-remote-file-1 (dnd-tests-make-temp-name))
+ (x-dnd-preserve-selection-data t))
+ ;; Touch those files if they don't exist.
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p normal-temp-file-1)
+ (write-region "" 0 normal-temp-file))
+ (unless (file-exists-p remote-temp-file)
+ (write-region "" 0 remote-temp-file))
+ (ignore-errors
+ (delete-file nonexistent-local-file)
+ (delete-file nonexistent-remote-file)
+ (delete-file nonexistent-remote-file-1))
+ (unwind-protect
+ (progn
+ ;; Now test dragging a normal file and a remote file.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file))
+ 'copy))
+ ;; Test that the remote file produced was added to the list
+ ;; of files to remove upon the next call.
+ (should dnd-last-dragged-remote-file)
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Two local files at the same time.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ normal-temp-file-1))
+ 'copy))
+ ;; Test that the remote files were removed.
+ (should-not dnd-last-dragged-remote-file)
+ ;; And so was the hook.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Test the selection data is correct.
+ (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list)))
+ (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username))
+ (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME)))
+ (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME))))
+ ;; Check if the URI list is formatted correctly.
+ (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t))
+ (decoded (mapcar #'dnd-get-local-file-name split-uri-list)))
+ (should (equal (car decoded) normal-temp-file))
+ (should (equal (cadr decoded) normal-temp-file-1)))
+ ;; Test that the username reported is correct.
+ (should (equal username-data (user-real-login-name)))
+ ;; Test that the file name data is correct.
+ (let ((split-file-names (split-string file-name-data "\0")))
+ ;; Make sure there are no extra leading or trailing NULL bytes.
+ (should (equal (length split-file-names) 2))
+ ;; Make sure all file names are encoded correctly;
+ (dolist (name split-file-names)
+ (should-not (multibyte-string-p name)))
+ ;; Make sure decoding the file names result in the
+ ;; originals.
+ (should (equal (decode-coding-string (car split-file-names)
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file))
+ (should (equal (decode-coding-string (cadr split-file-names)
+ (or file-name-coding-system
+ default-file-name-coding-system))
+ normal-temp-file-1))
+ ;; Also make sure the hostname is correct.
+ (should (equal host-name-data (system-name)))))
+ ;; Multiple local files with some remote files that will
+ ;; fail, and some that won't.
+ (should (and (eq (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file
+ remote-temp-file
+ nonexistent-remote-file
+ normal-temp-file-1
+ nonexistent-remote-file-1))
+ 'copy)
+ ;; Make sure exactly two valid remote files
+ ;; were downloaded.
+ (eq (length dnd-last-dragged-remote-file) 2)))
+ ;; Make sure the appropriate hook is added so the remote
+ ;; files are removed when Emacs exits.
+ (should (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Make sure links can't be created to remote files.
+ (should-error (dnd-begin-drag-files (list normal-temp-file
+ remote-temp-file
+ normal-temp-file-1)
+ nil 'link))
+ ;; And that they can to normal files.
+ (should (eq (dnd-begin-drag-files (list normal-temp-file
+ normal-temp-file-1)
+ nil 'link)
+ 'link))
+ ;; Make sure the remote file removal hook was deleted.
+ (should-not (memq #'dnd-remove-last-dragged-remote-file
+ kill-emacs-hook))
+ ;; Make sure you can't drag an empty list of files.
+ (should-error (dnd-begin-drag-files nil))
+ ;; And when all remote files are inaccessible.
+ (should-error (dnd-begin-drag-files (list nonexistent-remote-file
+ nonexistent-remote-file-1))))
+ (delete-file normal-temp-file)
+ (delete-file normal-temp-file-1)
+ (delete-file remote-temp-file))))
+
+(ert-deftest dnd-tests-get-local-file-uri ()
+ (should (equal (dnd-get-local-file-uri "file://localhost/path/to/foo")
+ "file:///path/to/foo"))
+ (should (equal (dnd-get-local-file-uri
+ (format "file://%s/path/to/" (system-name)))
+ "file:///path/to/"))
+ (should-not (dnd-get-local-file-uri "file://some-remote-host/path/to/foo"))
+ (should-not (dnd-get-local-file-uri "file:///path/to/foo")))
+
+(ert-deftest dnd-tests-open-remote-url ()
+ ;; Expensive test to make sure opening an FTP URL during
+ ;; drag-and-drop works.
+ :tags '(:expensive-test)
+ ;; Don't run if there is no ftp client.
+ (skip-unless (executable-find "ftp"))
+ ;; Don't run this test if the FTP server isn't reachable.
+ (skip-unless (and (fboundp 'network-lookup-address-info)
+ (network-lookup-address-info "ftp.gnu.org")))
+ ;; Make sure bug#56078 doesn't happen again.
+ (let ((url "ftp://anonymous@ftp.gnu.org/")
+ ;; This prints a bunch of annoying spaces to stdout.
+ (inhibit-message t))
+ (should (prog1 t (dnd-open-remote-url url 'private)))))
+
+(ert-deftest dnd-tests-direct-save ()
+ ;; This test just verifies that a direct save works; the window
+ ;; system specific test is in x-dnd-tests.el. When running this
+ ;; interactively, keep in mind that there are only two file managers
+ ;; which are known to implement XDS correctly: System G (see
+ ;; http://nps-systemg.sourceforge.net), and Emacs itself. GTK file
+ ;; managers such as Nautilus will not work, since they prefer the
+ ;; `text/uri-list' selection target to `XdndDirectSave0', contrary
+ ;; to the XDS specification.
+ (let ((window-system window-system)
+ (normal-temp-file (expand-file-name (make-temp-name "dnd-test")
+ temporary-file-directory)))
+ (unwind-protect
+ (progn
+ (unless (file-exists-p normal-temp-file)
+ (write-region "" 0 normal-temp-file))
+ (unless (eq window-system 'x)
+ ;; Use a window system that isn't X, since we only want to test
+ ;; the fallback code when run non-interactively.
+ (setq window-system 'haiku))
+ (should (eq (dnd-direct-save normal-temp-file
+ (make-temp-name "target-file-name"))
+ 'copy)))
+ (ignore-errors
+ (delete-file normal-temp-file)))))
+
+(provide 'dnd-tests)
+;;; dnd-tests.el ends here
diff --git a/test/lisp/edmacro-tests.el b/test/lisp/edmacro-tests.el
index b5809ad0b77..e386342f6ee 100644
--- a/test/lisp/edmacro-tests.el
+++ b/test/lisp/edmacro-tests.el
@@ -25,23 +25,24 @@
(require 'edmacro)
(ert-deftest edmacro-test-edmacro-parse-keys ()
- (should (equal (edmacro-parse-keys "") ""))
- (should (equal (edmacro-parse-keys "x") "x"))
- (should (equal (edmacro-parse-keys "C-a") "\C-a"))
+ (should (equal (edmacro-parse-keys "") []))
+ (should (equal (edmacro-parse-keys "x") [?x]))
+ (should (equal (edmacro-parse-keys "C-a") [?\C-a]))
;; comments
- (should (equal (edmacro-parse-keys ";; foobar") ""))
- (should (equal (edmacro-parse-keys ";;;") ""))
- (should (equal (edmacro-parse-keys "; ; ;") ";;;"))
- (should (equal (edmacro-parse-keys "REM foobar") ""))
- (should (equal (edmacro-parse-keys "x ;; foobar") "x"))
- (should (equal (edmacro-parse-keys "x REM foobar") "x"))
+ (should (equal (edmacro-parse-keys ";; foobar") []))
+ (should (equal (edmacro-parse-keys ";;;") []))
+ (should (equal (edmacro-parse-keys "; ; ;") [?\; ?\; ?\;]))
+ (should (equal (edmacro-parse-keys "REM foobar") []))
+ (should (equal (edmacro-parse-keys "x ;; foobar") [?x]))
+ (should (equal (edmacro-parse-keys "x REM foobar") [?x]))
(should (equal (edmacro-parse-keys "<<goto-line>>")
- [134217848 103 111 116 111 45 108 105 110 101 13]))
+ [?\M-x ?g ?o ?t ?o ?- ?l ?i ?n ?e ?\r]))
;; repetitions
- (should (equal (edmacro-parse-keys "3*x") "xxx"))
- (should (equal (edmacro-parse-keys "3*C-m") "\C-m\C-m\C-m"))
- (should (equal (edmacro-parse-keys "10*foo") "foofoofoofoofoofoofoofoofoofoo")))
+ (should (equal (edmacro-parse-keys "3*x") [?x ?x ?x]))
+ (should (equal (edmacro-parse-keys "3*C-m") [?\C-m ?\C-m ?\C-m]))
+ (should (equal (edmacro-parse-keys "10*foo")
+ (apply #'vconcat (make-list 10 [?f ?o ?o])))))
;;; edmacro-tests.el ends here
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index e10ed04f9d3..5d7e905cfa3 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -79,7 +79,7 @@
(should (equal (point)
expected-point))))
-(eval-when-compile
+(eval-and-compile
(defun electric-pair-define-test-form (name fixture
char
pos
diff --git a/test/lisp/elide-head-tests.el b/test/lisp/elide-head-tests.el
index 804617f48ff..6f351170f1d 100644
--- a/test/lisp/elide-head-tests.el
+++ b/test/lisp/elide-head-tests.el
@@ -28,41 +28,67 @@
(require 'elide-head)
(require 'ert)
+(require 'ert-x)
-(ert-deftest elide-head-tests-elide-head ()
+(ert-deftest elide-head-tests-elide-head-mode ()
(let ((elide-head-headers-to-hide '(("START" . "END"))))
(with-temp-buffer
(insert "foo\nSTART\nHIDDEN\nEND\nbar")
- (elide-head)
+ (elide-head-mode 1)
(let ((o (car (overlays-at 14))))
(should (= (overlay-start o) 10))
(should (= (overlay-end o) 21))
(should (overlay-get o 'invisible))
(should (overlay-get o 'evaporate))))))
-(ert-deftest elide-head-tests-elide-head-with-prefix-arg ()
+(ert-deftest elide-head-tests-elide-head-mode/enable-disable ()
(let ((elide-head-headers-to-hide '(("START" . "END"))))
(with-temp-buffer
(insert "foo\nSTART\nHIDDEN\nEND\nbar")
- (elide-head)
+ (elide-head-mode 1)
(should (overlays-at 14))
- (elide-head t)
+ (elide-head-mode -1)
(should-not (overlays-at 14)))))
-(ert-deftest elide-head-tests-show ()
- (let ((elide-head-headers-to-hide '(("START" . "END"))))
- (with-temp-buffer
- (insert "foo\nSTART\nHIDDEN\nEND\nbar")
- (elide-head)
- (should (overlays-at 14))
- (elide-head-show)
- (should-not (overlays-at 14)))))
+(ert-deftest elide-head-tests-elide-head-mode/normal-mode ()
+ (ert-with-temp-file fil
+ (with-temp-file fil
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar"))
+ (let ((elide-head-headers-to-hide '(("START" . "END")))
+ (buf (find-file-noselect fil)))
+ (save-excursion
+ (unwind-protect
+ (progn
+ (set-buffer buf)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max)))))
+ (normal-mode)
+ (should (= 0 (length (overlays-in (point-min) (point-max))))))
+ (when buf (kill-buffer buf)))))))
+
+(ert-deftest elide-head-tests-elide-head-mode/revert-buffer ()
+ (ert-with-temp-file fil
+ (with-temp-file fil
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar"))
+ (let ((elide-head-headers-to-hide '(("START" . "END")))
+ (buf (find-file-noselect fil)))
+ (save-excursion
+ (unwind-protect
+ (progn
+ (set-buffer buf)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max)))))
+ (revert-buffer nil t)
+ (elide-head-mode 1)
+ (should (= 1 (length (overlays-in (point-min) (point-max))))))
+ (when buf (kill-buffer buf)))))))
+
(defmacro elide-head--add-test (name text search-str)
`(ert-deftest ,(intern (format "elide-head--test-headers-to-hide/%s" name)) ()
(with-temp-buffer
(insert ,text)
- (elide-head)
+ (elide-head-mode 1)
(goto-char (point-min))
(re-search-forward ,search-str)
(let ((o (car (overlays-at (match-beginning 0)))))
@@ -163,5 +189,39 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
" "This program is distributed in the hope that")
+
+;;; Obsolete
+
+(with-suppressed-warnings ((obsolete elide-head)
+ (obsolete elide-head-show))
+ (ert-deftest elide-head-tests-elide-head ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (let ((o (car (overlays-at 14))))
+ (should (= (overlay-start o) 10))
+ (should (= (overlay-end o) 21))
+ (should (overlay-get o 'invisible))
+ (should (overlay-get o 'evaporate))))))
+
+ (ert-deftest elide-head-tests-elide-head-with-prefix-arg ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (should (overlays-at 14))
+ (elide-head t)
+ (should-not (overlays-at 14)))))
+
+ (ert-deftest elide-head-tests-show ()
+ (let ((elide-head-headers-to-hide '(("START" . "END"))))
+ (with-temp-buffer
+ (insert "foo\nSTART\nHIDDEN\nEND\nbar")
+ (elide-head)
+ (should (overlays-at 14))
+ (elide-head-show)
+ (should-not (overlays-at 14))))))
+
(provide 'elide-head-tests)
;;; elide-head-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 7722cf6c020..0c03c51e2ef 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -36,7 +36,7 @@
(bindat-type
(type u8)
(opcode u8)
- (length uintr 16) ;; little endian order
+ (length uint 16 'le) ;; little endian order
(id strz 8)
(data vec length)
(_ align 4)))
@@ -128,18 +128,17 @@
(r (zerop (% kind 2))))
(dotimes (_ 100)
(let* ((n (random (ash 1 bitlen)))
- (i (- n (ash 1 (1- bitlen)))))
+ (i (- n (ash 1 (1- bitlen))))
+ (stype (bindat-type sint bitlen r))
+ (utype (bindat-type if r (uintr bitlen) (uint bitlen))))
(should (equal (bindat-unpack
- (bindat-type sint bitlen r)
- (bindat-pack (bindat-type sint bitlen r) i))
+ stype
+ (bindat-pack stype i))
i))
(when (>= i 0)
- (should (equal (bindat-pack
- (bindat-type if r (uintr bitlen) (uint bitlen)) i)
- (bindat-pack (bindat-type sint bitlen r) i)))
- (should (equal (bindat-unpack
- (bindat-type if r (uintr bitlen) (uint bitlen))
- (bindat-pack (bindat-type sint bitlen r) i))
+ (should (equal (bindat-pack utype i)
+ (bindat-pack stype i)))
+ (should (equal (bindat-unpack utype (bindat-pack stype i))
i))))))))
(defconst bindat-test--LEB128
@@ -162,4 +161,125 @@
(bindat-pack bindat-test--LEB128 n))
n)))))))
+(ert-deftest bindat-test--str-strz-prealloc ()
+ (dolist (tc `(((,(bindat-type str 1) "") . "xx")
+ ((,(bindat-type str 2) "") . "xx")
+ ((,(bindat-type str 2) "a") . "ax")
+ ((,(bindat-type str 2) "ab") . "ab")
+ ((,(bindat-type str 2) "abc") . "ab")
+ ((((x str 1)) ((x . ""))) . "xx")
+ ((((x str 2)) ((x . ""))) . "xx")
+ ((((x str 2)) ((x . "a"))) . "ax")
+ ((((x str 2)) ((x . "ab"))) . "ab")
+ ((((x str 2)) ((x . "abc"))) . "ab")
+ ((,(bindat-type strz 1) "") . "\0x")
+ ((,(bindat-type strz 2) "") . "\0x")
+ ((,(bindat-type strz 2) "a") . "a\0")
+ ((,(bindat-type strz 2) "ab") . "ab")
+ ((,(bindat-type strz 2) "abc") . "ab")
+ ((((x strz 1)) ((x . ""))) . "\0x")
+ ((((x strz 2)) ((x . ""))) . "\0x")
+ ((((x strz 2)) ((x . "a"))) . "a\0")
+ ((((x strz 2)) ((x . "ab"))) . "ab")
+ ((((x strz 2)) ((x . "abc"))) . "ab")
+ ((,(bindat-type strz) "") . "\0x")
+ ((,(bindat-type strz) "a") . "a\0")))
+ (let ((prealloc (make-string 2 ?x)))
+ (apply #'bindat-pack (append (car tc) (list prealloc)))
+ (should (equal prealloc (cdr tc))))))
+
+(ert-deftest bindat-test--str-strz-multibyte ()
+ (dolist (spec (list (bindat-type str 2)
+ (bindat-type strz 2)
+ (bindat-type strz)))
+ (should (equal (bindat-pack spec (string-to-multibyte "x")) "x\0"))
+ (should (equal (bindat-pack spec (string-to-multibyte "\xff")) "\xff\0"))
+ (should-error (bindat-pack spec "💩"))
+ (should-error (bindat-pack spec "\N{U+ff}")))
+ (dolist (spec (list '((x str 2)) '((x strz 2))))
+ (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "x"))))
+ "x\0"))
+ (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "\xff"))))
+ "\xff\0"))
+ (should-error (bindat-pack spec '((x . "💩"))))
+ (should-error (bindat-pack spec '((x . "\N{U+ff}"))))))
+
+(let ((spec (bindat-type strz 2)))
+ (ert-deftest bindat-test--strz-fixedlen-len ()
+ (should (equal (bindat-length spec "") 2))
+ (should (equal (bindat-length spec "a") 2)))
+
+ (ert-deftest bindat-test--strz-fixedlen-len-overflow ()
+ (should (equal (bindat-length spec "ab") 2))
+ (should (equal (bindat-length spec "abc") 2)))
+
+ (ert-deftest bindat-test--strz-fixedlen-pack ()
+ (should (equal (bindat-pack spec "") "\0\0"))
+ (should (equal (bindat-pack spec "a") "a\0")))
+
+ (ert-deftest bindat-test--strz-fixedlen-pack-overflow ()
+ ;; This is not the only valid semantic, but it's the one we've
+ ;; offered historically.
+ (should (equal (bindat-pack spec "ab") "ab"))
+ (should (equal (bindat-pack spec "abc") "ab")))
+
+ (ert-deftest bindat-test--strz-fixedlen-unpack ()
+ (should (equal (bindat-unpack spec "\0\0") ""))
+ (should (equal (bindat-unpack spec "\0X") ""))
+ (should (equal (bindat-unpack spec "a\0") "a"))
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-unpack spec "ab") "ab"))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
+(let ((spec (bindat-type strz)))
+ (ert-deftest bindat-test--strz-varlen-len ()
+ (should (equal (bindat-length spec "") 1))
+ (should (equal (bindat-length spec "abc") 4)))
+
+ (ert-deftest bindat-test--strz-varlen-pack ()
+ (should (equal (bindat-pack spec "") "\0"))
+ (should (equal (bindat-pack spec "abc") "abc\0"))
+ ;; Null bytes in the input string break unpacking.
+ (should-error (bindat-pack spec "\0"))
+ (should-error (bindat-pack spec "\0x"))
+ (should-error (bindat-pack spec "x\0"))
+ (should-error (bindat-pack spec "x\0y")))
+
+ (ert-deftest bindat-test--strz-varlen-unpack ()
+ (should (equal (bindat-unpack spec "\0") ""))
+ (should (equal (bindat-unpack spec "abc\0") "abc"))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
+(let ((spec '((x strz 2))))
+ (ert-deftest bindat-test--strz-legacy-fixedlen-len ()
+ (should (equal (bindat-length spec '((x . ""))) 2))
+ (should (equal (bindat-length spec '((x . "a"))) 2)))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-len-overflow ()
+ (should (equal (bindat-length spec '((x . "ab"))) 2))
+ (should (equal (bindat-length spec '((x . "abc"))) 2)))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-pack ()
+ (should (equal (bindat-pack spec '((x . ""))) "\0\0"))
+ (should (equal (bindat-pack spec '((x . "a"))) "a\0")))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-pack-overflow ()
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-pack spec '((x . "ab"))) "ab"))
+ (should (equal (bindat-pack spec '((x . "abc"))) "ab")))
+
+ (ert-deftest bindat-test--strz-legacy-fixedlen-unpack ()
+ (should (equal (bindat-unpack spec "\0\0") '((x . ""))))
+ (should (equal (bindat-unpack spec "\0X") '((x . ""))))
+ (should (equal (bindat-unpack spec "a\0") '((x . "a"))))
+ ;; Same comment as for b-t-s-f-pack-overflow.
+ (should (equal (bindat-unpack spec "ab") '((x . "ab"))))
+ ;; Missing null terminator.
+ (should-error (bindat-unpack spec ""))
+ (should-error (bindat-unpack spec "a"))))
+
;;; bindat-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
new file mode 100644
index 00000000000..be907b32f47
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el
@@ -0,0 +1,266 @@
+;;; -*- lexical-binding: t -*-
+
+;; Correct
+
+(defun faw-str-decl-code (x)
+ "something"
+ (declare (pure t))
+ (print x))
+
+(defun faw-doc-decl-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (print x))
+
+(defun faw-str-int-code (x)
+ "something"
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-int-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (print x))
+
+(defun faw-decl-int-code (x)
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-int-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+
+;; Correct (last string is return value)
+
+(defun faw-str ()
+ "something")
+
+(defun faw-decl-str ()
+ (declare (pure t))
+ "something")
+
+(defun faw-decl-int-str ()
+ (declare (pure t))
+ (interactive)
+ "something")
+
+(defun faw-str-str ()
+ "something"
+ "something else")
+
+(defun faw-doc-str ()
+ (:documentation "something")
+ "something else")
+
+
+;; Incorrect (bad order)
+
+(defun faw-int-decl-code (x)
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-str-code (x)
+ (interactive "P")
+ "something"
+ (print x))
+
+(defun faw-int-doc-code (x)
+ (interactive "P")
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-str-code (x)
+ (declare (pure t))
+ "something"
+ (print x))
+
+(defun faw-decl-doc-code (x)
+ (declare (pure t))
+ (:documentation "something")
+ (print x))
+
+(defun faw-str-int-decl-code (x)
+ "something"
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-doc-int-decl-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-str-decl-code (x)
+ (interactive "P")
+ "something"
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-doc-decl-code (x)
+ (interactive "P")
+ (:documentation "something")
+ (declare (pure t))
+ (print x))
+
+(defun faw-int-decl-str-code (x)
+ (interactive "P")
+ (declare (pure t))
+ "something"
+ (print x))
+
+(defun faw-int-decl-doc-code (x)
+ (interactive "P")
+ (declare (pure t))
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-int-str-code (x)
+ (declare (pure t))
+ (interactive "P")
+ "something"
+ (print x))
+
+(defun faw-decl-int-doc-code (x)
+ (declare (pure t))
+ (interactive "P")
+ (:documentation "something")
+ (print x))
+
+(defun faw-decl-str-int-code (x)
+ (declare (pure t))
+ "something"
+ (interactive "P")
+ (print x))
+
+(defun faw-decl-doc-int-code (x)
+ (declare (pure t))
+ (:documentation "something")
+ (interactive "P")
+ (print x))
+
+
+;; Incorrect (duplication)
+
+(defun faw-str-str-decl-int-code (x)
+ "something"
+ "something else"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-doc-decl-int-code (x)
+ "something"
+ (:documentation "something else")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-str-decl-int-code (x)
+ (:documentation "something")
+ "something else"
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-doc-decl-int-code (x)
+ (:documentation "something")
+ (:documentation "something else")
+ (declare (pure t))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-str-int-code (x)
+ "something"
+ (declare (pure t))
+ "something else"
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-str-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ "something else"
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-doc-int-code (x)
+ "something"
+ (declare (pure t))
+ (:documentation "something else")
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-doc-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (:documentation "something else")
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-decl-int-code (x)
+ "something"
+ (declare (pure t))
+ (declare (indent 1))
+ (interactive "P")
+ (print x))
+
+(defun faw-doc-decl-decl-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (declare (indent 1))
+ (interactive "P")
+ (print x))
+
+(defun faw-str-decl-int-decl-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (declare (indent 1))
+ (print x))
+
+(defun faw-doc-decl-int-decl-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (declare (indent 1))
+ (print x))
+
+(defun faw-str-decl-int-int-code (x)
+ "something"
+ (declare (pure t))
+ (interactive "P")
+ (interactive "p")
+ (print x))
+
+(defun faw-doc-decl-int-int-code (x)
+ (:documentation "something")
+ (declare (pure t))
+ (interactive "P")
+ (interactive "p")
+ (print x))
+
+(defun faw-str-int-decl-int-code (x)
+ "something"
+ (interactive "P")
+ (declare (pure t))
+ (interactive "p")
+ (print x))
+
+(defun faw-doc-int-decl-int-code (x)
+ (:documentation "something")
+ (interactive "P")
+ (declare (pure t))
+ (interactive "p")
+ (print x))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
new file mode 100644
index 00000000000..00ad1947507
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
@@ -0,0 +1 @@
+;; -*- no-byte-compile: t; -*-
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el
new file mode 100644
index 00000000000..5a56913cd9b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo ()
+ (setq (a) nil))
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el
new file mode 100644
index 00000000000..9ce80de08cd
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el
@@ -0,0 +1,3 @@
+;;; -*- lexical-binding: t -*-
+(defun foo (a b)
+ (setq a 1 b))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index abd33ab8e5a..9c5bef09a34 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -747,6 +747,7 @@ byte-compiled. Run with dynamic binding."
(ert-with-temp-file elcfile
:suffix ".elc"
(with-temp-buffer
+ (insert ";;; -*- lexical-binding: t -*-\n")
(dolist (form forms)
(print form (current-buffer)))
(write-region (point-min) (point-max) elfile nil 'silent))
@@ -950,11 +951,17 @@ byte-compiled. Run with dynamic binding."
"let-bind nonvariable")
(bytecomp--define-warning-file-test "warn-variable-set-constant.el"
- "variable reference to constant")
+ "attempt to set constant")
(bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el"
"variable reference to nonvariable")
+(bytecomp--define-warning-file-test "warn-variable-setq-nonvariable.el"
+ "attempt to set non-variable")
+
+(bytecomp--define-warning-file-test "warn-variable-setq-odd.el"
+ "odd number of arguments")
+
(bytecomp--define-warning-file-test
"warn-wide-docstring-autoload.el"
"autoload .foox. docstring wider than .* characters")
@@ -1227,12 +1234,19 @@ literals (Bug#20852)."
'((lexical prefixless))
"global/dynamic var .prefixless. lacks")
- (test-suppression
- '(defun foo()
- (let ((nil t))
- (message-mail)))
- '((constants nil))
- "Warning: attempt to let-bind constant .nil.")
+ ;; FIXME: These messages cannot be suppressed reliably right now,
+ ;; but attempting mutate `nil' or `5' is a rather daft thing to do
+ ;; in the first place. Preventing mutation of constants such as
+ ;; `most-positive-fixnum' makes more sense but the compiler doesn't
+ ;; warn about that at all right now (it's caught at runtime, and we
+ ;; allow writing the same value).
+ ;;
+ ;; (test-suppression
+ ;; '(defun foo()
+ ;; (let ((nil t))
+ ;; (message-mail)))
+ ;; '((constants nil))
+ ;; "Warning: attempt to let-bind constant .nil.")
(test-suppression
'(progn
@@ -1251,7 +1265,7 @@ literals (Bug#20852)."
(defun zot ()
(wrong-params 1 2 3)))
'((callargs wrong-params))
- "Warning: wrong-params called with")
+ "Warning: .wrong-params. called with")
(test-byte-comp-compile-and-load nil
(defvar obsolete-variable nil)
@@ -1538,6 +1552,103 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
(TEST-IN-COMMENTS t) (TEST-IN-STRINGS t) (TEST-IN-CODE t) \
(FIXTURE-FN \\='#\\='electric-pair-mode))" fill-column)))
+(defun test-bytecomp-defgroup-choice ()
+ (should-not (byte-compile--suspicious-defcustom-choice 'integer))
+ (should-not (byte-compile--suspicious-defcustom-choice
+ '(choice (const :tag "foo" bar))))
+ (should (byte-compile--suspicious-defcustom-choice
+ '(choice (const :tag "foo" 'bar)))))
+
+(ert-deftest bytecomp-function-attributes ()
+ ;; Check that `byte-compile' keeps the declarations, interactive spec and
+ ;; doc string of the function (bug#55830).
+ (let ((fname 'bytecomp-test-fun))
+ (fset fname nil)
+ (put fname 'pure nil)
+ (put fname 'lisp-indent-function nil)
+ (eval `(defun ,fname (x)
+ "tata"
+ (declare (pure t) (indent 1))
+ (interactive "P")
+ (list 'toto x))
+ t)
+ (let ((bc (byte-compile fname)))
+ (should (byte-code-function-p bc))
+ (should (equal (funcall bc 'titi) '(toto titi)))
+ (should (equal (aref bc 5) "P"))
+ (should (equal (get fname 'pure) t))
+ (should (equal (get fname 'lisp-indent-function) 1))
+ (should (equal (aref bc 4) "tata\n\n(fn X)")))))
+
+(ert-deftest bytecomp-fun-attr-warn ()
+ ;; Check that warnings are emitted when doc strings, `declare' and
+ ;; `interactive' forms don't come in the proper order, or more than once.
+ (let* ((filename "fun-attr-warn.el")
+ (el (ert-resource-file filename))
+ (elc (concat el "c"))
+ (text-quoting-style 'grave))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (byte-compile-file el)
+ (let ((expected
+ '("70:4: Warning: `declare' after `interactive'"
+ "74:4: Warning: Doc string after `interactive'"
+ "79:4: Warning: Doc string after `interactive'"
+ "84:4: Warning: Doc string after `declare'"
+ "89:4: Warning: Doc string after `declare'"
+ "96:4: Warning: `declare' after `interactive'"
+ "102:4: Warning: `declare' after `interactive'"
+ "108:4: Warning: `declare' after `interactive'"
+ "106:4: Warning: Doc string after `interactive'"
+ "114:4: Warning: `declare' after `interactive'"
+ "112:4: Warning: Doc string after `interactive'"
+ "118:4: Warning: Doc string after `interactive'"
+ "119:4: Warning: `declare' after `interactive'"
+ "124:4: Warning: Doc string after `interactive'"
+ "125:4: Warning: `declare' after `interactive'"
+ "130:4: Warning: Doc string after `declare'"
+ "136:4: Warning: Doc string after `declare'"
+ "142:4: Warning: Doc string after `declare'"
+ "148:4: Warning: Doc string after `declare'"
+ "159:4: Warning: More than one doc string"
+ "165:4: Warning: More than one doc string"
+ "171:4: Warning: More than one doc string"
+ "178:4: Warning: More than one doc string"
+ "186:4: Warning: More than one doc string"
+ "192:4: Warning: More than one doc string"
+ "200:4: Warning: More than one doc string"
+ "206:4: Warning: More than one doc string"
+ "215:4: Warning: More than one `declare' form"
+ "222:4: Warning: More than one `declare' form"
+ "230:4: Warning: More than one `declare' form"
+ "237:4: Warning: More than one `declare' form"
+ "244:4: Warning: More than one `interactive' form"
+ "251:4: Warning: More than one `interactive' form"
+ "258:4: Warning: More than one `interactive' form"
+ "257:4: Warning: `declare' after `interactive'"
+ "265:4: Warning: More than one `interactive' form"
+ "264:4: Warning: `declare' after `interactive'")))
+ (goto-char (point-min))
+ (let ((actual nil))
+ (while (re-search-forward
+ (rx bol (* (not ":")) ":"
+ (group (+ digit) ":" (+ digit) ": Warning: "
+ (or "More than one " (+ nonl) " form"
+ (: (+ nonl) " after " (+ nonl))))
+ eol)
+ nil t)
+ (push (match-string 1) actual))
+ (setq actual (nreverse actual))
+ (should (equal actual expected)))))))
+
+(ert-deftest byte-compile-file/no-byte-compile ()
+ (let* ((src-file (ert-resource-file "no-byte-compile.el"))
+ (dest-file (make-temp-file "bytecomp-tests-" nil ".elc"))
+ (byte-compile-dest-file-function (lambda (_) dest-file)))
+ (should (eq (byte-compile-file src-file) 'no-byte-compile))
+ (should-not (file-exists-p dest-file))))
+
;; Local Variables:
;; no-byte-compile: t
diff --git a/test/lisp/emacs-lisp/cconv-tests.el b/test/lisp/emacs-lisp/cconv-tests.el
index 0668e44ba51..9904c6a969c 100644
--- a/test/lisp/emacs-lisp/cconv-tests.el
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -24,6 +24,7 @@
(require 'ert)
(require 'cl-lib)
(require 'generator)
+(require 'bytecomp)
(ert-deftest cconv-tests-lambda-:documentation ()
"Docstring for lambda can be specified with :documentation."
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el
index 2ec01b2b5d7..56b766769ea 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -27,7 +27,7 @@
(require 'edebug)
;; Don't indirectly require `cl-lib' at run-time.
-(eval-when-compile (require 'ert))
+(require 'ert)
(declare-function ert--should-signal-hook "ert")
(declare-function ert--signal-should-execution "ert")
(declare-function ert-fail "ert")
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
index 008ec0de4a6..19ede627a13 100644
--- a/test/lisp/emacs-lisp/cl-macs-tests.el
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -23,6 +23,7 @@
(require 'cl-lib)
(require 'cl-macs)
+(require 'edebug)
(require 'ert)
@@ -694,4 +695,36 @@ collection clause."
(list cl-macs--test1 cl-macs--test2))
'(1 2))))
+(ert-deftest cl-define-compiler-macro/edebug ()
+ "Check that we can instrument compiler macros."
+ (with-temp-buffer
+ (dolist (form '((defun cl-define-compiler-macro/edebug (a b) nil)
+ (cl-define-compiler-macro
+ cl-define-compiler-macro/edebug
+ (&whole w a b)
+ w)))
+ (print form (current-buffer)))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ ;; Just make sure the forms can be instrumented.
+ (eval-buffer))))
+
+(ert-deftest cl-defstruct/edebug ()
+ "Check that we can instrument `cl-defstruct' forms."
+ (with-temp-buffer
+ (dolist (form '((cl-defstruct cl-defstruct/edebug/1)
+ (cl-defstruct (cl-defstruct/edebug/2
+ :noinline))
+ (cl-defstruct (cl-defstruct/edebug/3
+ (:noinline t)))
+ (cl-defstruct (cl-defstruct/edebug/4
+ :named))
+ (cl-defstruct (cl-defstruct/edebug/5
+ (:named t)))))
+ (print form (current-buffer)))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ ;; Just make sure the forms can be instrumented.
+ (eval-buffer))))
+
;;; cl-macs-tests.el ends here
diff --git a/test/lisp/emacs-lisp/copyright-tests.el b/test/lisp/emacs-lisp/copyright-tests.el
index dc82974a99e..b00d697aa64 100644
--- a/test/lisp/emacs-lisp/copyright-tests.el
+++ b/test/lisp/emacs-lisp/copyright-tests.el
@@ -50,5 +50,47 @@
(dolist (test copyright-tests--data)
(with-copyright-test (car test) (cdr test))))
+(ert-deftest test-end-chop ()
+ (should
+ (equal
+ (with-temp-buffer
+ (let ((copyright-query nil))
+ (insert (make-string (- copyright-limit 14) ?x) "\n"
+ "\nCopyright 2006, 2007, 2008 Foo Bar\n\n")
+ (copyright-update)
+ (buffer-substring (- (point-max) 42) (point-max))))
+ "Copyright 2006, 2007, 2008, 2022 Foo Bar\n\n")))
+
+(ert-deftest test-correct-notice ()
+ (should (equal
+ (with-temp-buffer
+ (dotimes (_ 2)
+ (insert "Copyright 2021 FSF\n"))
+ (let ((copyright-at-end-flag t)
+ (copyright-query nil))
+ (copyright-update))
+ (buffer-string))
+ "Copyright 2021 FSF\nCopyright 2021, 2022 FSF\n")))
+
+(defmacro with-copyright-fix-years-test (orig result)
+ `(let ((copyright-year-ranges t))
+ (with-temp-buffer
+ (insert ,orig)
+ (copyright-fix-years)
+ (should (equal (buffer-string) ,result)))))
+
+(defvar copyright-fix-years-tests--data
+ '((";; Copyright (C) 2008, 2010, 2012"
+ . ";; Copyright (C) 2008, 2010, 2012")
+ (";; Copyright (C) 2008, 2009, 2010, 2013, 2014, 2015, 2016, 2018"
+ . ";; Copyright (C) 2008-2010, 2013-2016, 2018")
+ (";; Copyright (C) 2008-2010, 2011, 2015, 2016, 2017"
+ . ";; Copyright (C) 2008-2010, 2011, 2015-2017")))
+
+(ert-deftest text-copyright-fix-years ()
+ "Test basics of \\[copyright-fix-years]."
+ (dolist (test copyright-fix-years-tests--data)
+ (with-copyright-fix-years-test (car test) (cdr test))))
+
(provide 'copyright-tests)
;;; copyright-tests.el ends here
diff --git a/test/lisp/emacs-lisp/derived-tests.el b/test/lisp/emacs-lisp/derived-tests.el
index d867a181832..547b16843d4 100644
--- a/test/lisp/emacs-lisp/derived-tests.el
+++ b/test/lisp/emacs-lisp/derived-tests.el
@@ -40,4 +40,25 @@
(derived-tests--child-mode)
(should (equal (buffer-string) "PB CB MH AFP=S AFC=S ")))))
+(declare-function mode-a "derived-tests")
+(declare-function mode-b "derived-tests")
+(declare-function mode-c "derived-tests")
+(ert-deftest test-add-font-lock ()
+ (define-derived-mode mode-a fundamental-mode "mode-a"
+ (font-lock-add-keywords nil `(("a" 0 'font-lock-keyword-face))))
+ (define-derived-mode mode-b mode-a "mode-b"
+ (font-lock-add-keywords nil `(("b" 0 'font-lock-builtin-face))))
+ (define-derived-mode mode-c mode-b "mode-c"
+ (font-lock-add-keywords nil `(("c" 0 'font-lock-constant-face))))
+
+ (with-temp-buffer
+ (mode-c)
+ (should (equal font-lock-keywords
+ '(t (("c" 0 'font-lock-constant-face)
+ ("b" 0 'font-lock-builtin-face)
+ ("a" 0 'font-lock-keyword-face))
+ ("c" (0 'font-lock-constant-face))
+ ("b" (0 'font-lock-builtin-face))
+ ("a" (0 'font-lock-keyword-face)))))))
+
;;; derived-tests.el ends here
diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el b/test/lisp/emacs-lisp/easy-mmode-tests.el
index 0a3bbb189ba..f6d07196727 100644
--- a/test/lisp/emacs-lisp/easy-mmode-tests.el
+++ b/test/lisp/emacs-lisp/easy-mmode-tests.el
@@ -60,6 +60,4 @@
(easy-mmode-test-mode 'toggle)
(should (eq easy-mmode-test-mode t))))
-(provide 'easy-mmode-tests)
-
;;; easy-mmode-tests.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
index d238bffdaa1..008e1e467ba 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -1094,5 +1094,24 @@ This avoids potential duplicate definitions (Bug#41988)."
(edebug-new-definition name))))
(should-error (eval-buffer) :type 'invalid-read-syntax))))
+(ert-deftest edebug-tests-inline ()
+ "Check that Edebug can instrument inline functions (Bug#53068)."
+ (with-temp-buffer
+ (print '(define-inline edebug-tests-inline (arg)
+ (inline-quote ,arg))
+ (current-buffer))
+ (let ((edebug-all-defs t)
+ (edebug-initial-mode 'Go-nonstop))
+ (eval-buffer))))
+
+(ert-deftest edebug-test-dot-reader ()
+ (with-temp-buffer
+ (insert "(defun x () `(t .,t))")
+ (goto-char (point-min))
+ (should (equal (save-excursion
+ (edebug-read-storing-offsets (current-buffer)))
+ (save-excursion
+ (read (current-buffer)))))))
+
(provide 'edebug-tests)
;;; edebug-tests.el ends here
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index ac130644743..84c28e11315 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -377,8 +377,11 @@ This macro is used to test if macroexpansion in `should' works."
(test (make-ert-test :body test-body))
(result (ert-run-test test)))
(should (ert-test-failed-p result))
- (should (eq (backtrace-frame-fun (car (ert-test-failed-backtrace result)))
- 'signal))))
+ (should (memq (backtrace-frame-fun (car (ert-test-failed-backtrace result)))
+ ;;; This is `ert-fail' on nativecomp and `signal'
+ ;;; otherwise. It's not clear whether that's a bug
+ ;;; or not (bug#51308).
+ '(ert-fail signal)))))
(ert-deftest ert-test-messages ()
:tags '(:causes-redisplay)
@@ -595,6 +598,7 @@ This macro is used to test if macroexpansion in `should' works."
(should found-complex)))))
(ert-deftest ert-test-run-tests-batch-expensive ()
+ :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
(let* ((complex-list '((:1 (:2 (:3 (:4 (:5 (:6 "abc"))))))))
(failing-test-1
(make-ert-test :name 'failing-test-1
@@ -865,7 +869,7 @@ This macro is used to test if macroexpansion in `should' works."
(ert-deftest ert-test-with-demoted-errors ()
"Check that ERT correctly handles `with-demoted-errors'."
:expected-result :failed ;; FIXME! Bug#11218
- (should-not (with-demoted-errors (error "Foo"))))
+ (should-not (with-demoted-errors "FOO: %S" (error "Foo"))))
(ert-deftest ert-test-fail-inside-should ()
"Check that `ert-fail' inside `should' works correctly."
@@ -881,6 +885,9 @@ This macro is used to test if macroexpansion in `should' works."
"Check that `lexical-binding' in `ert-deftest' has the file value."
(should (equal lexical-binding t)))
+(ert-deftest ert-test-get-explainer ()
+ (should (eq (ert--get-explainer 'string-equal) 'ert--explain-string-equal))
+ (should (eq (ert--get-explainer 'string=) 'ert--explain-string-equal)))
(provide 'ert-tests)
diff --git a/test/lisp/emacs-lisp/find-func-tests.el b/test/lisp/emacs-lisp/find-func-tests.el
index d29d9ff6563..420c61acb55 100644
--- a/test/lisp/emacs-lisp/find-func-tests.el
+++ b/test/lisp/emacs-lisp/find-func-tests.el
@@ -95,6 +95,13 @@ expected function symbol and function library, respectively."
(advice-remove #'mark-sexp 'my-message))
(ert-deftest find-func-tests--find-library-verbose ()
+ (unwind-protect
+ (progn
+ (advice-add 'dired :before #'ignore)
+ ;; bug#41104
+ (should (equal (find-function-library #'dired) '(dired . "dired"))))
+ (advice-remove 'dired #'ignore))
+
(find-function-library #'join-line nil t)
(with-current-buffer "*Messages*"
(save-excursion
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el b/test/lisp/emacs-lisp/nadvice-tests.el
index f21624cfd87..a675986b90b 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -153,13 +153,13 @@ function being an around advice."
(ert-deftest advice-test-call-interactively ()
"Check interaction between advice on call-interactively and called-interactively-p."
- (defun sm-test7.4 () (interactive) (cons 1 (called-interactively-p)))
- (let ((old (symbol-function 'call-interactively)))
+ (let ((sm-test7.4 (lambda () (interactive) (cons 1 (called-interactively-p))))
+ (old (symbol-function 'call-interactively)))
(unwind-protect
(progn
(advice-add 'call-interactively :before #'ignore)
- (should (equal (sm-test7.4) '(1 . nil)))
- (should (equal (call-interactively 'sm-test7.4) '(1 . t))))
+ (should (equal (funcall sm-test7.4) '(1 . nil)))
+ (should (equal (call-interactively sm-test7.4) '(1 . t))))
(advice-remove 'call-interactively #'ignore)
(should (eq (symbol-function 'call-interactively) old)))))
@@ -204,6 +204,15 @@ function being an around advice."
(remove-function (var sm-test10) sm-advice)
(should (equal (funcall sm-test10 5) 15))))
+(ert-deftest advice-test-print ()
+ (let ((x (list 'cdr)))
+ (add-function :after (car x) 'car)
+ (should (equal (cl-prin1-to-string (car x))
+ "#f(advice car :after cdr)"))
+ (add-function :before (car x) 'first)
+ (should (equal (cl-prin1-to-string (car x))
+ "#f(advice first :before #f(advice car :after cdr))"))))
+
;; Local Variables:
;; no-byte-compile: t
;; End:
diff --git a/test/lisp/emacs-lisp/oclosure-tests.el b/test/lisp/emacs-lisp/oclosure-tests.el
new file mode 100644
index 00000000000..00b008845c0
--- /dev/null
+++ b/test/lisp/emacs-lisp/oclosure-tests.el
@@ -0,0 +1,166 @@
+;;; oclosure-tests.e; --- Tests for Open Closures -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'oclosure)
+(require 'cl-lib)
+(require 'eieio)
+
+(oclosure-define (oclosure-test
+ (:copier oclosure-test-copy)
+ (:copier oclosure-test-copy1 (fst)))
+ "Simple OClosure."
+ fst snd (name :mutable t))
+
+(cl-defmethod oclosure-test-gen ((_x compiled-function)) "#<bytecode>")
+
+(cl-defmethod oclosure-test-gen ((_x cons)) "#<cons>")
+
+(cl-defmethod oclosure-test-gen ((_x oclosure))
+ (format "#<oclosure:%s>" (cl-call-next-method)))
+
+(cl-defmethod oclosure-test-gen ((_x oclosure-test))
+ (format "#<oclosure-test:%s>" (cl-call-next-method)))
+
+(ert-deftest oclosure-test ()
+ (let* ((i 42)
+ (ocl1 (oclosure-lambda (oclosure-test (fst 1) (snd 2) (name "hi"))
+ ()
+ (list fst snd i)))
+ (ocl2 (oclosure-lambda (oclosure-test (name (cl-incf i)) (fst (cl-incf i)))
+ ()
+ (list fst snd 152 i))))
+ (should (equal (list (oclosure-test--fst ocl1)
+ (oclosure-test--snd ocl1)
+ (oclosure-test--name ocl1))
+ '(1 2 "hi")))
+ (should (equal (list (oclosure-test--fst ocl2)
+ (oclosure-test--snd ocl2)
+ (oclosure-test--name ocl2))
+ '(44 nil 43)))
+ (should (equal (funcall ocl1) '(1 2 44)))
+ (should (equal (funcall ocl2) '(44 nil 152 44)))
+ (should (equal (funcall (oclosure-test-copy ocl1 :fst 7)) '(7 2 44)))
+ (should (equal (funcall (oclosure-test-copy1 ocl1 9)) '(9 2 44)))
+ (should (cl-typep ocl1 'oclosure-test))
+ (should (cl-typep ocl1 'oclosure))
+ (should (member (oclosure-test-gen ocl1)
+ '("#<oclosure-test:#<oclosure:#<cons>>>"
+ "#<oclosure-test:#<oclosure:#<bytecode>>>")))
+ (should (stringp (documentation #'oclosure-test--fst)))
+ ))
+
+(ert-deftest oclosure-test-limits ()
+ (defvar byte-compile-debug)
+ (should
+ (condition-case err
+ (let ((lexical-binding t)
+ (byte-compile-debug t))
+ (byte-compile '(lambda ()
+ (let ((inc-fst nil))
+ (oclosure-lambda (oclosure-test (fst 'foo)) ()
+ (setq inc-fst (lambda () (setq fst (1+ fst))))
+ fst))))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "fst.*mutated" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand-all '(oclosure-define oclosure--foo a a))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot name: a$" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand-all
+ '(oclosure-define (oclosure--foo (:parent oclosure-test)) fst))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot name: fst$" (cadr err))))))
+ (should
+ (condition-case err
+ (progn (macroexpand '(oclosure-lambda (oclosure-test (fst 1) (fst 2))
+ () fst))
+ nil)
+ (error
+ (and (eq 'error (car err))
+ (string-match "Duplicate slot: fst$" (cadr err)))))))
+
+(cl-defmethod oclosure-interactive-form ((ot oclosure-test))
+ (let ((snd (oclosure-test--snd ot)))
+ (if (stringp snd) (list 'interactive snd))))
+
+(ert-deftest oclosure-test-interactive-form ()
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) () fst))
+ nil))
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) ()
+ (interactive "r")
+ fst))
+ '(interactive "r")))
+ (should (equal (interactive-form
+ (oclosure-lambda (oclosure-test (fst 1) (snd "P")) () fst))
+ '(interactive "P")))
+ (should (not (commandp
+ (oclosure-lambda (oclosure-test (fst 1) (snd 2)) () fst))))
+ (should (commandp
+ (oclosure-lambda (oclosure-test (fst 1) (snd "P")) () fst))))
+
+(oclosure-define (oclosure-test-mut
+ (:parent oclosure-test)
+ (:copier oclosure-test-mut-copy))
+ "Simple OClosure with a mutable field."
+ (mut :mutable t))
+
+(ert-deftest oclosure-test-mutate ()
+ (let* ((f (oclosure-lambda (oclosure-test-mut (fst 0) (mut 3))
+ (x)
+ (+ x fst mut)))
+ (f2 (oclosure-test-mut-copy f :fst 50)))
+ (should (equal (oclosure-test-mut--mut f) 3))
+ (should (equal (funcall f 5) 8))
+ (should (equal (funcall f2 5) 58))
+ (cl-incf (oclosure-test-mut--mut f) 7)
+ (should (equal (oclosure-test-mut--mut f) 10))
+ (should (equal (funcall f 5) 15))
+ (should (equal (funcall f2 15) 68))))
+
+(ert-deftest oclosure-test-slot-value ()
+ (require 'eieio)
+ (let ((ocl (oclosure-lambda
+ (oclosure-test (fst 'fst1) (snd 'snd1) (name 'name1))
+ (x)
+ (list name fst snd x))))
+ (should (equal 'fst1 (slot-value ocl 'fst)))
+ (should (equal 'snd1 (slot-value ocl 'snd)))
+ (should (equal 'name1 (slot-value ocl 'name)))
+ (setf (slot-value ocl 'name) 'new-name)
+ (should (equal 'new-name (slot-value ocl 'name)))
+ (should (equal '(new-name fst1 snd1 arg) (funcall ocl 'arg)))
+ (should-error (setf (slot-value ocl 'fst) 'new-fst) :type 'setting-constant)
+ (should (equal 'fst1 (slot-value ocl 'fst)))
+ ))
+
+;;; oclosure-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts
index 002a5cf1650..c3e3023cb19 100644
--- a/test/lisp/emacs-lisp/pp-resources/code-formats.erts
+++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts
@@ -128,3 +128,15 @@ Name: code-formats12
=-=
(global-set-key (kbd "s-x") #'kill-region)
=-=-=
+
+Name: code-formats13
+
+=-=
+'("a")
+=-=-=
+
+Name: code-formats14
+
+=-=
+'("a" . "b")
+=-=-=
diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el
new file mode 100644
index 00000000000..660110aa1fb
--- /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-2022 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 <https://www.gnu.org/licenses/>.
+
+;;; 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
diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el
index c1c46d6400e..385b0fe44a5 100644
--- a/test/lisp/emacs-lisp/rmc-tests.el
+++ b/test/lisp/emacs-lisp/rmc-tests.el
@@ -66,5 +66,26 @@
(should (equal (list char str)
(read-multiple-choice "Do it? " '((?y "yes") (?n "no"))))))))
-(provide 'rmc-tests)
+(ert-deftest test-read-multiple-choice-help ()
+ (let ((chars '(?o ?a))
+ help)
+ (cl-letf* (((symbol-function #'read-event)
+ (lambda ()
+ (message "chars %S" chars)
+ (when (= 1 (length chars))
+ (with-current-buffer "*Multiple Choice Help*"
+ (setq help (buffer-string))))
+ (pop chars))))
+ (read-multiple-choice
+ "Choose:"
+ '((?a "aaa")
+ (?b "bbb")
+ (?c "ccc" "a really long description of ccc")))
+ (should (equal help "Choose:
+
+a: [A]aa b: [B]bb c: [C]cc
+ a really long
+ description of ccc
+ \n")))))
+
;;; rmc-tests.el ends here
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index 9e5d59163f9..d979604910e 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -511,5 +511,26 @@ Evaluate BODY for each created sequence.
(should (equal (seq-difference '(1 nil) '(2 nil))
'(1)))))
+(ert-deftest test-seq-split ()
+ (let ((seq [0 1 2 3 4 5 6 7 8 9 10]))
+ (should (equal seq (car (seq-split seq 20))))
+ (should (equal seq (car (seq-split seq 11))))
+ (should (equal (seq-split seq 10)
+ '([0 1 2 3 4 5 6 7 8 9] [10])))
+ (should (equal (seq-split seq 5)
+ '([0 1 2 3 4] [5 6 7 8 9] [10])))
+ (should (equal (seq-split seq 1)
+ '([0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10])))
+ (should-error (seq-split seq 0))
+ (should-error (seq-split seq -10)))
+ (let ((seq '(0 1 2 3 4 5 6 7 8 9)))
+ (should (equal (seq-split seq 5)
+ '((0 1 2 3 4) (5 6 7 8 9)))))
+ (let ((seq "0123456789"))
+ (should (equal (seq-split seq 2)
+ '("01" "23" "45" "67" "89")))
+ (should (equal (seq-split seq 3)
+ '("012" "345" "678" "9")))))
+
(provide 'seq-tests)
;;; seq-tests.el ends here
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index d38a8e2352b..99c0e822155 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -607,21 +607,36 @@
(should (equal (string-limit "foó" 4 nil 'utf-8) "fo\303\263"))
(should (equal (string-limit "foóa" 4 nil 'utf-8) "fo\303\263"))
(should (equal (string-limit "foóá" 4 nil 'utf-8) "fo\303\263"))
+ (should (equal (string-limit "foóá" 2 nil 'utf-8-with-signature)
+ ""))
(should (equal (string-limit "foóá" 4 nil 'utf-8-with-signature)
- "fo\303\263"))
+ "\357\273\277f"))
(should (equal (string-limit "foóa" 4 nil 'iso-8859-1) "fo\363a"))
(should (equal (string-limit "foóá" 4 nil 'iso-8859-1) "fo\363\341"))
- (should (equal (string-limit "foóá" 4 nil 'utf-16) "\000f\000o"))
+ (should (equal (string-limit "foóá" 3 nil 'utf-16) ""))
+ (should (equal (string-limit "foóá" 6 nil 'utf-16) "\376\377\000f\000o"))
(should (equal (string-limit "foó" 10 t 'utf-8) "fo\303\263"))
(should (equal (string-limit "foó" 3 t 'utf-8) "o\303\263"))
(should (equal (string-limit "foó" 4 t 'utf-8) "fo\303\263"))
(should (equal (string-limit "foóa" 4 t 'utf-8) "o\303\263a"))
(should (equal (string-limit "foóá" 4 t 'utf-8) "\303\263\303\241"))
- (should (equal (string-limit "foóá" 2 t 'utf-8-with-signature) "\303\241"))
+ (should (equal (string-limit "foóá" 2 t 'utf-8-with-signature)
+ ""))
(should (equal (string-limit "foóa" 4 t 'iso-8859-1) "fo\363a"))
(should (equal (string-limit "foóá" 4 t 'iso-8859-1) "fo\363\341"))
- (should (equal (string-limit "foóá" 4 t 'utf-16) "\000\363\000\341")))
+ (should (equal (string-limit "foóá" 6 t 'utf-16) "\376\377\000\363\000\341")))
+
+(ert-deftest subr-string-limit-glyphs ()
+ (should (equal (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273"))
+ (should (= (length (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8)) 41))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 100 nil 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273"))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 15 nil 'utf-8)
+ "Hello, \360\237\221\274\360\237\217\273"))
+ (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 10 nil 'utf-8)
+ "Hello, ")))
(ert-deftest subr-string-lines ()
(should (equal (string-lines "foo") '("foo")))
@@ -712,5 +727,44 @@
(loop (cdr rest) (+ sum (car rest))))))
(should (equal (mapcar #'funcall funs) '(43 1 0)))))
+(ert-deftest test-with-buffer-unmodified-if-unchanged ()
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t"))
+ (should (buffer-modified-p)))
+
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1))
+ (should-not (buffer-modified-p)))
+
+ ;; Shouldn't error.
+ (should
+ (with-temp-buffer
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1)
+ (kill-buffer))))
+
+ (with-temp-buffer
+ (let ((outer (current-buffer)))
+ (with-temp-buffer
+ (let ((inner (current-buffer)))
+ (with-buffer-unmodified-if-unchanged
+ (insert "t")
+ (delete-char -1)
+ (set-buffer outer))
+ (with-current-buffer inner
+ (should-not (buffer-modified-p))))))))
+
+(ert-deftest subr-x--hash-table-keys-and-values ()
+ (let ((h (make-hash-table)))
+ (puthash 'a 1 h)
+ (puthash 'c 3 h)
+ (puthash 'b 2 h)
+ (should (equal (sort (hash-table-keys h) #'string<) '(a b c)))
+ (should (equal (sort (hash-table-values h) #'<) '(1 2 3)))))
+
(provide 'subr-x-tests)
;;; subr-x-tests.el ends here
diff --git a/test/lisp/emacs-lisp/tabulated-list-tests.el b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 0074b10170f..3ce4a63f4f0 100644
--- a/test/lisp/emacs-lisp/tabulated-list-tests.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -55,28 +55,37 @@
(ert-deftest tabulated-list-print ()
(tabulated-list--test-with-buffer
;; Basic printing.
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " zzzz-game zzzz-game 2113 installed play zzzz in Emacs
- 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
- abc-mode abc-mode 944 available Major mode for editing abc music files
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
;; Preserve position.
(forward-line 3)
(let ((pos (thing-at-point 'line)))
(pop tabulated-list-entries)
(tabulated-list-print t)
(should (equal (thing-at-point 'line) pos))
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
- abc-mode abc-mode 944 available Major mode for editing abc music files
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
;; Check the UPDATE argument
(pop tabulated-list-entries)
(setf (cdr (car tabulated-list-entries)) (list ["x" "x" "944" "available" " XX"]))
(tabulated-list-print t t)
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " x x 944 available XX
- mode mode 1128 installed A simple mode for editing Actionscript 3 files\n"))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ x x 944 available XX
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+"))
(should (equal (thing-at-point 'line) pos)))))
(ert-deftest tabulated-list-sort ()
@@ -86,11 +95,14 @@
(skip-chars-forward "[:blank:]")
(tabulated-list-sort)
(let ((text (buffer-substring-no-properties (point-min) (point-max))))
- (should (string= text
- " 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
- abc-mode abc-mode 944 available Major mode for editing abc music files
- mode mode 1128 installed A simple mode for editing Actionscript 3 files
- zzzz-game zzzz-game 2113 installed play zzzz in Emacs\n"))
+ (should (string-equal
+ text
+ "\
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+"))
(skip-chars-forward "^[:blank:]")
(skip-chars-forward "[:blank:]")
@@ -101,11 +113,14 @@
(should (string= text (buffer-substring-no-properties (point-min) (point-max))))
;; Invert.
(tabulated-list-sort 1)
- (should (string= (buffer-substring-no-properties (point-min) (point-max))
- " zzzz-game zzzz-game 2113 installed play zzzz in Emacs
- mode mode 1128 installed A simple mode for editing Actionscript 3 files
- abc-mode abc-mode 944 available Major mode for editing abc music files
- 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions\n"))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+"))
;; Again
(tabulated-list-sort 1)
(should (string= text (buffer-substring-no-properties (point-min) (point-max)))))
diff --git a/test/lisp/emacs-lisp/text-property-search-tests.el b/test/lisp/emacs-lisp/text-property-search-tests.el
index d137572f304..98fdd55e85f 100644
--- a/test/lisp/emacs-lisp/text-property-search-tests.el
+++ b/test/lisp/emacs-lisp/text-property-search-tests.el
@@ -156,20 +156,19 @@
;;;; Position after search.
-(defun text-property-search--pos-test (fun pos &optional reverse)
+(ert-deftest text-property-search-forward/point-at-beginning ()
(with-temp-buffer
- (insert (concat "foo "
- (propertize "bar" 'x t)
- " baz"))
- (goto-char (if reverse (point-max) (point-min)))
- (funcall fun 'x t)
- (should (= (point) pos))))
-
-(ert-deftest text-property-search-forward-point-at-beginning ()
- (text-property-search--pos-test #'text-property-search-forward 5))
-
-(ert-deftest text-property-search-backward-point-at-end ()
- (text-property-search--pos-test #'text-property-search-backward 8 t))
+ (insert (concat "1234" (propertize "567" 'x t) "890"))
+ (goto-char (point-min))
+ (text-property-search-forward 'x t)
+ (should (= (point) 5))))
+
+(ert-deftest text-property-search-backward/point-at-end ()
+ (with-temp-buffer
+ (insert (concat "1234" (propertize "567" 'x t) "890"))
+ (goto-char (point-max))
+ (text-property-search-backward 'x t)
+ (should (= (point) 8))))
(provide 'text-property-search-tests)
diff --git a/test/lisp/emacs-lisp/vtable-tests.el b/test/lisp/emacs-lisp/vtable-tests.el
new file mode 100644
index 00000000000..627d9f9c5df
--- /dev/null
+++ b/test/lisp/emacs-lisp/vtable-tests.el
@@ -0,0 +1,42 @@
+;;; vtable-tests.el --- Tests for vtable.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'vtable)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-vstable-compute-columns ()
+ (should
+ (equal (mapcar
+ (lambda (column)
+ (vtable-column-align column))
+ (vtable--compute-columns
+ (make-vtable :columns '("a" "b" "c")
+ :objects '(("foo" 1 2)
+ ("bar" 3 :zot))
+ :insert nil)))
+ '(left right left))))
+
+;;; vtable-tests.el ends here
diff --git a/test/lisp/erc/erc-dcc-tests.el b/test/lisp/erc/erc-dcc-tests.el
new file mode 100644
index 00000000000..a1dfbab9dc5
--- /dev/null
+++ b/test/lisp/erc/erc-dcc-tests.el
@@ -0,0 +1,167 @@
+;;; erc-dcc-tests.el --- Tests for erc-dcc -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'ert)
+(require 'erc-dcc)
+
+(ert-deftest erc-dcc-ctcp-query-send-regexp ()
+ (let ((s "DCC SEND \"file name\" 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should-not (match-string 2 s))
+ (should (string= "file name" (match-string 1 s)))
+ (should (string= "SEND" (match-string 6 s))))
+ (let ((s "DCC SEND \"file \\\" name\" 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should-not (match-string 2 s))
+ (should (string= "SEND" (match-string 6 s)))
+ (should (string= "file \" name"
+ (erc-dcc-unquote-filename (match-string 1 s)))))
+ (let ((s "DCC SEND filename 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should (string= "filename" (match-string 2 s)))
+ (should (string= "2130706433" (match-string 3 s)))
+ (should (string= "9899" (match-string 4 s)))
+ (should (string= "1405135128" (match-string 5 s))))
+ (let ((s "DCC TSEND filename 2130706433 9899 1405135128"))
+ (should (string-match erc-dcc-ctcp-query-send-regexp s))
+ (should (string= "TSEND" (match-string 6 s)))))
+
+;; This also indirectly tests base functionality for
+;; `erc-dcc-do-LIST-command'
+
+(defun erc-dcc-tests--dcc-handle-ctcp-send (turbo)
+ (let (erc-send-completed-hook
+ erc-insert-modify-hook
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+ (with-current-buffer (get-buffer-create "fake-server")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "fake" (current-buffer) "sleep" "10")
+ erc-input-marker (make-marker)
+ erc-insert-marker (make-marker)
+ erc-server-current-nick "dummy")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not erc-dcc-list)
+ (erc-ctcp-query-DCC erc-server-process
+ "tester"
+ "~tester"
+ "fake.irc"
+ "dummy"
+ (concat "DCC " (if turbo "TSEND" "SEND")
+ " foo 2130706433 9899 1405135128"))
+ (should-not (cdr erc-dcc-list))
+ (should (equal (plist-put (car erc-dcc-list) :parent 'fake)
+ `(:nick "tester!~tester@fake.irc"
+ :type GET
+ :peer nil
+ :parent fake
+ :ip "127.0.0.1"
+ :port "9899"
+ :file "foo"
+ :size 1405135128
+ :turbo ,(and turbo t)
+ :secure nil)))
+ (goto-char (point-min))
+ (should (search-forward "file foo offered by tester" nil t))
+ (erc-dcc-do-LIST-command erc-server-process)
+ (should (search-forward-regexp (concat
+ "GET +no +1405135128 +foo"
+ (and turbo " +(T)") "$")
+ nil t))
+ (when noninteractive
+ (kill-buffer))))
+ ;; `erc-dcc-list' is global; must leave it empty
+ (should erc-dcc-list)
+ (setq erc-dcc-list nil))
+
+(ert-deftest erc-dcc-handle-ctcp-send--base ()
+ (erc-dcc-tests--dcc-handle-ctcp-send nil))
+
+(ert-deftest erc-dcc-handle-ctcp-send--turbo ()
+ (erc-dcc-tests--dcc-handle-ctcp-send t))
+
+(ert-deftest erc-dcc-do-GET-command ()
+ (with-temp-buffer
+ (let* ((proc (start-process "fake" (current-buffer) "sleep" "10"))
+ (elt (list :nick "tester!~tester@fake.irc"
+ :type 'GET
+ :peer nil
+ :parent proc
+ :ip "127.0.0.1"
+ :port "9899"
+ :file "foo.bin"
+ :size 1405135128))
+ (erc-dcc-list (list elt))
+ ;;
+ erc-accidental-paste-threshold-seconds
+ erc-insert-modify-hook erc-send-completed-hook
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ calls)
+ (erc-mode)
+ (setq erc-server-process proc
+ erc-input-marker (make-marker)
+ erc-insert-marker (make-marker)
+ erc-server-current-nick "dummy")
+ (set-process-query-on-exit-flag proc nil)
+ (cl-letf (((symbol-function 'read-file-name)
+ (lambda (&rest _) "foo.bin"))
+ ((symbol-function 'erc-dcc-get-file)
+ (lambda (&rest r) (push r calls))))
+ (goto-char (point-max))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt)
+
+ (ert-info ("No turbo")
+ (should-not (plist-member elt :turbo))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester foo.bin")
+ (erc-send-current-line)
+ (should-not (plist-member (car erc-dcc-list) :turbo))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 2")
+ (should-not (plist-member elt :turbo))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET -t tester foo.bin")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 4")
+ (setq elt (plist-put elt :turbo nil)
+ erc-dcc-list (list elt))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester -t foo.bin")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))
+
+ (ert-info ("Arg turbo in pos 6")
+ (setq elt (plist-put elt :turbo nil)
+ erc-dcc-list (list elt))
+ (goto-char erc-input-marker)
+ (insert "/dcc GET tester foo.bin -t")
+ (erc-send-current-line)
+ (should (eq t (plist-get (car erc-dcc-list) :turbo)))
+ (should (equal (pop calls) (list elt "foo.bin" proc))))))))
+
+;;; erc-dcc-tests.el ends here
diff --git a/test/lisp/erc/erc-join-tests.el b/test/lisp/erc/erc-join-tests.el
new file mode 100644
index 00000000000..8210defbfbd
--- /dev/null
+++ b/test/lisp/erc/erc-join-tests.el
@@ -0,0 +1,361 @@
+;;; erc-join-tests.el --- Tests for erc-join. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(require 'erc-join)
+(require 'erc-networks)
+
+(ert-deftest erc-autojoin-channels--connect ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-session-server "irc.gnu.chat"
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-autojoin-channels erc-server-announced-name
+ "tester")
+ (should-not erc--autojoin-timer))))
+
+ (ert-info ("Join immediately on connect; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Join immediately on connect; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Do nothing; server")
+ (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan"))))
+ (funcall common))
+ (should-not calls))
+
+ (ert-info ("Do nothing; network")
+ (let ((erc-autojoin-channels-alist '((BarNet "#chan"))))
+ (funcall common))
+ (should-not calls)))))
+
+(ert-deftest erc-autojoin-channels--delay ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ (erc-autojoin-timing 'ident)
+ (erc-autojoin-delay 0.05))
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls)))
+ ((symbol-function 'erc-autojoin-after-ident)
+ (lambda (&rest _r) (error "I ran but shouldn't have"))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-session-server "irc.gnu.chat"
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not erc--autojoin-timer)
+ (erc-autojoin-channels erc-server-announced-name "tester")
+ (should erc--autojoin-timer)
+ (should-not calls)
+ (sleep-for 0.1))))
+
+ (ert-info ("Deferred on connect; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Deferred on connect; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Do nothing; server")
+ (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan"))))
+ (funcall common))
+ (should-not calls)))))
+
+(ert-deftest erc-autojoin-channels--ident ()
+ (should (eq erc-autojoin-timing 'connect))
+ (should (= erc-autojoin-delay 30))
+ (should-not erc--autojoin-timer)
+
+ (let (calls
+ common
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook
+ (erc-autojoin-timing 'ident))
+
+ (cl-letf (((symbol-function 'erc-server-send)
+ (lambda (line) (push line calls))))
+
+ (setq common
+ (lambda ()
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-announced-name "foo.gnu.chat")
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-autojoin-after-ident 'FooNet "tester")
+ (should-not erc--autojoin-timer))))
+
+ (ert-info ("Join on NickServ hook; server")
+ (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan")))
+
+ (ert-info ("Join on NickServ hook; network")
+ (let ((erc-autojoin-channels-alist '((FooNet "#chan"))))
+ (funcall common))
+ (should (equal (pop calls) "JOIN #chan"))))))
+
+(defun erc-join-tests--autojoin-add--common (setup &optional fwd)
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc--isupport-params (make-hash-table)
+ erc-server-announced-name "foo.gnu.chat")
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (funcall setup)
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Add #chan")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN #chan"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist '((FooNet "#chan")))))
+
+ (ert-info ("More recently joined chans are prepended")
+ (erc-parse-server-response
+ erc-server-process ; with account username
+ (concat ":tester!~i@c.u JOIN #spam" (and fwd " tester :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam" "#chan")))))
+
+ (ert-info ("Duplicates skipped")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN #chan"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam" "#chan")))))
+
+ (ert-info ("Server used for local channel")
+ (erc-parse-server-response erc-server-process
+ (concat ":tester!~i@c.u JOIN &local"
+ (and fwd " * :Tes Ter")))
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("foo\\.gnu\\.chat" "&local")
+ (FooNet "#spam" "#chan")))))))))
+
+(ert-deftest erc-autojoin-add--network ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))))
+
+(ert-deftest erc-autojoin-add--network-extended-syntax ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))
+ 'forward-compatible))
+
+(ert-deftest erc-autojoin-add--network-id ()
+ (erc-join-tests--autojoin-add--common
+ (lambda () (setq erc-network 'invalid
+ erc-networks--id (erc-networks--id-create 'FooNet)))))
+
+(ert-deftest erc-autojoin-add--server ()
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (ert-info ("Network unavailable, announced name used")
+ (setq erc-autojoin-channels-alist nil)
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc-server-announced-name "foo.gnu.chat"
+ erc-networks--id (make-erc-networks--id)) ; assume too early
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+ (erc-parse-server-response erc-server-process
+ ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (should calls)
+ (erc-autojoin-add erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#chan")))))))))
+
+(defun erc-join-tests--autojoin-remove--common (setup)
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (setq erc-autojoin-channels-alist ; mutated, so can't quote whole thing
+ (list '(FooNet "#spam" "##chan")
+ '(BarNet "#bar" "##bar")
+ '("foo\\.gnu\\.chat" "&local")))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc--isupport-params (make-hash-table)
+ erc-server-announced-name "foo.gnu.chat")
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (funcall setup)
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Remove #chan")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART ##chan")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam")
+ (BarNet "#bar" "##bar")
+ ("foo\\.gnu\\.chat" "&local")))))
+
+ (ert-info ("Wrong network, nothing done")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART #bar")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam")
+ (BarNet "#bar" "##bar")
+ ("foo\\.gnu\\.chat" "&local")))))
+
+ (ert-info ("Local channel keyed by server found")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART &local")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '((FooNet "#spam") (BarNet "#bar" "##bar")))))))))
+
+(ert-deftest erc-autojoin-remove--network ()
+ (erc-join-tests--autojoin-remove--common
+ (lambda () (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create nil)))))
+
+(ert-deftest erc-autojoin-remove--network-id ()
+ (erc-join-tests--autojoin-remove--common
+ (lambda () (setq erc-network 'fake-a-roo
+ erc-networks--id (erc-networks--id-create 'FooNet)))))
+
+(ert-deftest erc-autojoin-remove--server ()
+ (let (calls
+ erc-autojoin-channels-alist
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (cl-letf (((symbol-function 'erc-handle-parsed-server-response)
+ (lambda (_p m) (push m calls))))
+
+ (setq erc-autojoin-channels-alist (list '("gnu.chat" "#spam" "##chan")
+ '("fsf.chat" "#bar" "##bar")))
+
+ (ert-with-test-buffer (:name "foonet")
+ (erc-mode)
+ (setq erc-server-process
+ (start-process "true" (current-buffer) "true")
+ erc-server-current-nick "tester"
+ erc-server-announced-name "foo.gnu.chat"
+ ;; Assume special case w/o known network
+ erc-networks--id (make-erc-networks--id))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should-not calls)
+
+ (ert-info ("Announced name matched, #chan removed")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART ##chan")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#spam")
+ ("fsf.chat" "#bar" "##bar")))))
+
+ (ert-info ("Wrong announced name, nothing done")
+ (erc-parse-server-response erc-server-process
+ ":tester!~i@c.u PART #bar")
+ (should calls)
+ (erc-autojoin-remove erc-server-process (pop calls))
+ (should (equal erc-autojoin-channels-alist
+ '(("gnu.chat" "#spam")
+ ("fsf.chat" "#bar" "##bar")))))))))
+
+;;; erc-join-tests.el ends here
diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el
new file mode 100644
index 00000000000..66a334b7091
--- /dev/null
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -0,0 +1,1707 @@
+;;; erc-networks-tests.el --- Tests for erc-networks. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x) ; cl-lib
+(require 'erc-networks)
+
+(defun erc-networks-tests--create-dead-proc (&optional buf)
+ (let ((p (start-process "true" (or buf (current-buffer)) "true")))
+ (while (process-live-p p) (sit-for 0.1))
+ p))
+
+(defun erc-networks-tests--create-live-proc (&optional buf)
+ (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1")))
+ (set-process-query-on-exit-flag proc nil)
+ proc))
+
+;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS.
+(defun erc-networks-tests--clean-bufs ()
+ (let (erc-kill-channel-hook
+ erc-kill-server-hook
+ erc-kill-buffer-hook)
+ (dolist (buf (erc-buffer-list))
+ (kill-buffer buf))))
+
+(defun erc-networks-tests--bufnames (prefix)
+ (let* ((case-fold-search)
+ (pred (lambda (b) (string-prefix-p prefix (buffer-name b))))
+ (prefixed (seq-filter pred (buffer-list))))
+ (sort (mapcar #'buffer-name prefixed) #'string<)))
+
+(ert-deftest erc-networks--id ()
+ (cl-letf (((symbol-function 'float-time)
+ (lambda (&optional _) 0.0)))
+
+ ;; Fixed
+ (should (equal (erc-networks--id-fixed-create 'foo)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+
+ ;; Eliding
+ (let* ((erc-network 'FooNet)
+ (erc-server-current-nick "Joe")
+ (identity (erc-networks--id-create nil)))
+
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet [FooNet "joe"] 1)))
+ (should (equal (erc-networks--id-qualifying-grow-id identity)
+ 'FooNet/joe))
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet/joe [FooNet "joe"] 2)))
+ (should-not (erc-networks--id-qualifying-grow-id identity))
+ (should (equal identity #s(erc-networks--id-qualifying
+ 0.0 FooNet/joe [FooNet "joe"] 2))))
+
+ ;; Compat
+ (with-current-buffer (get-buffer-create "fake.chat")
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (should (equal (erc-networks--id-create nil)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'fake.chat)))))
+ (kill-buffer))))
+
+(ert-deftest erc-networks--id-create ()
+ (cl-letf (((symbol-function 'float-time)
+ (lambda (&optional _) 0.0)))
+
+ (should (equal (erc-networks--id-create 'foo)
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (should (equal (erc-networks--id-create "foo")
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (should (equal (erc-networks--id-create [h i])
+ (make-erc-networks--id-fixed :ts (float-time)
+ :symbol (quote \[h\ \i\]))))
+
+ (with-current-buffer (get-buffer-create "foo")
+ (let ((expected (make-erc-networks--id-fixed :ts (float-time)
+ :symbol 'foo)))
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (should (equal (erc-networks--id-create nil) expected))))
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (let (erc-reuse-buffers)
+ (should (equal (erc-networks--id-create nil) expected))
+ (should (equal (erc-networks--id-create 'bar) expected)))))
+ (kill-buffer))))
+
+(ert-deftest erc-networks--id-qualifying-prefix-length ()
+ (should-not (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying)
+ (make-erc-networks--id-qualifying)))
+
+ (should-not (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [2 3])))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1])
+ (make-erc-networks--id-qualifying :parts [1 2]))))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [1 3]))))
+
+ (should (= 2 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts [1 2])
+ (make-erc-networks--id-qualifying :parts [1 2]))))
+
+ (should (= 1 (erc-networks--id-qualifying-prefix-length
+ (make-erc-networks--id-qualifying :parts ["1"])
+ (make-erc-networks--id-qualifying :parts ["1"])))))
+
+(ert-deftest erc-networks--id-sort-buffers ()
+ (let (oldest middle newest)
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'oldest)
+ oldest (current-buffer))
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'middle)
+ middle (current-buffer))
+
+ (with-temp-buffer
+ (setq erc-networks--id (erc-networks--id-fixed-create 'newest)
+ newest (current-buffer))
+
+ (should (equal (erc-networks--id-sort-buffers
+ (list oldest newest middle))
+ (list newest middle oldest))))))))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--channel ()
+ (should (memq #'erc-networks-rename-surviving-target-buffer
+ erc-kill-channel-hook))
+
+ (let ((chan-foonet-buffer (get-buffer-create "#chan@foonet")))
+
+ (with-current-buffer chan-foonet-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1)
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [barnet "bob"] :len 1)
+ erc--target (erc--target-from-string "#chan")))
+
+ (kill-buffer "#chan@barnet")
+ (should (equal (erc-networks-tests--bufnames "#chan") '("#chan")))
+ (should (eq chan-foonet-buffer (get-buffer "#chan"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--query ()
+ (should (memq #'erc-networks-rename-surviving-target-buffer
+ erc-kill-buffer-hook))
+
+ (let ((bob-foonet (get-buffer-create "bob@foonet")))
+
+ (with-current-buffer bob-foonet
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1)
+ erc--target (erc--target-from-string "bob")))
+
+ (with-current-buffer (get-buffer-create "bob@barnet")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [barnet "bob"] :len 1)
+ erc--target (erc--target-from-string "bob")))
+
+ (kill-buffer "bob@barnet")
+ (should (equal (erc-networks-tests--bufnames "bob") '("bob")))
+ (should (eq bob-foonet (get-buffer "bob"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--multi ()
+
+ (ert-info ("Multiple leftover channels untouched")
+ (with-current-buffer (get-buffer-create "#chan@foonet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (with-current-buffer (get-buffer-create "#chan@baznet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")))
+ (kill-buffer "#chan@baznet")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet")))
+ (erc-networks-tests--clean-bufs))
+
+ (ert-info ("Multiple leftover queries untouched")
+ (with-current-buffer (get-buffer-create "bob@foonet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (with-current-buffer (get-buffer-create "bob@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (with-current-buffer (get-buffer-create "bob@baznet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "bob")))
+ (kill-buffer "bob@baznet")
+ (should (equal (erc-networks-tests--bufnames "bob")
+ '("bob@barnet" "bob@foonet")))
+ (erc-networks-tests--clean-bufs)))
+
+;; As of May 2022, this "shrink" stuff runs whenever an ERC buffer is
+;; killed because `erc-networks-shrink-ids-and-buffer-names' is a
+;; default member of all three erc-kill-* functions.
+
+;; Note: this overlaps a fair bit with the "hook" variants, i.e.,
+;; `erc-networks--shrink-ids-and-buffer-names--hook-outstanding-*' If
+;; this ever fails, just delete this and fix those. But please copy
+;; over and adapt the comments first.
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-outstanding ()
+ ;; While some buffer #a@barnet/dummy is being killed, its display ID
+ ;; is not collapsed because collisions still exist.
+ ;;
+ ;; Note that we don't have to set `erc-server-connected' because
+ ;; this function is intentionally connectivity agnostic.
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-server-current-nick "tester" ; Always set (`erc-open')
+ ;; Set when transport connected
+ erc-server-process (erc-networks-tests--create-live-proc)
+ ;; Both set just before IRC (logically) connected (post MOTD)
+ erc-network 'foonet
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2))) ; is/was a plain foonet collision
+
+ ;; Presumably, some server buffer named foonet/dummy was just
+ ;; killed, hence the length 2 display ID.
+
+ ;; A target buffer for chan #a exists for foonet/tester. The
+ ;; precise form of its name should not affect shrinking.
+ (with-current-buffer (get-buffer-create
+ (elt ["#a" "#a@foonet" "#a@foonet/tester"] (random 3)))
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ ;; Another network context exists (so we have buffers to iterate
+ ;; over), and it's also part of a collision group.
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "barnet/dummy")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/dummy
+ :parts [barnet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ ;; The buffer being killed is not part of the foonet collision
+ ;; group, which contains one display ID eligible for shrinkage.
+ (with-current-buffer (get-buffer-create
+ (elt ["#a@barnet" "#a@barnet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-temp-buffer ; doesn't matter what the current buffer is
+ (setq erc-networks--id (make-erc-networks--id-qualifying)) ; mock
+ (erc-networks--shrink-ids-and-buffer-names))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" ; shrunk
+ "#a@foonet" ; shrunk
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+
+ (erc-networks-tests--clean-bufs))
+
+;; This likewise overlaps with the "hook" variants below. If this
+;; should ever fail, just delete it and optionally fix those.
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-collapse ()
+ ;; This is similar to the "outstanding" variant above, but both
+ ;; groups are eligible for renaming, which is abnormal but possible
+ ;; when recovering from some mishap.
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#a" "#a@foonet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#b" "#b@foonet/tester"] (random 2)))
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#b")))
+
+ (with-temp-buffer
+ (setq erc-networks--id (make-erc-networks--id-qualifying))
+ (erc-networks--shrink-ids-and-buffer-names))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" "#a" "barnet" "#b")))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common ()
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@foonet/tester")
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "barnet/dummy")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/dummy
+ :parts [barnet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#a"))))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-srv ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc))
+ (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "#a@foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-tgt ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+ (with-current-buffer (get-buffer-create "#a@foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc--target (erc--target-from-string "#a")
+ erc-server-process (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+
+ (with-current-buffer "#a@foonet/dummy" (kill-buffer))
+
+ ;; Identical to *-server variant above
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "#a@foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a@barnet/tester")))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks-rename-surviving-target-buffer--shrink ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common)
+
+ ;; This buffer isn't "#a@foonet" (yet) because the shrink-ids hook
+ ;; hasn't run. However, when it's the rename hook runs, its network
+ ;; id *is* "foonet", not "foonet/tester".
+ (with-current-buffer "#a@foonet/tester" (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet"
+ "barnet/tester"
+ "barnet/dummy"
+ "#a")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--server ()
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-dead-proc))
+ (kill-buffer))
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list)) '("foonet")))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-networks--shrink-ids-and-buffer-names--hook-collapse (check)
+
+ (with-current-buffer (get-buffer-create "foonet/tester")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/tester
+ :parts [foonet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#a@foonet/tester")
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/tester"))
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/tester"))
+ erc--target (erc--target-from-string "#a")))
+
+ (with-current-buffer (get-buffer-create "barnet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'barnet/tester
+ :parts [barnet "tester"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#b@foonet/tester")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet/tester"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet/tester"))
+ erc--target (erc--target-from-string "#b")))
+
+ (funcall check)
+
+ (should (equal (mapcar #'buffer-name (erc-buffer-list))
+ '("foonet" "#a" "barnet" "#b")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-server ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-collapse
+ (lambda ()
+ (with-current-buffer (get-buffer-create "foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc))
+ (kill-buffer)))))
+
+(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-target ()
+ (erc-networks--shrink-ids-and-buffer-names--hook-collapse
+ (lambda ()
+ (with-current-buffer (get-buffer-create "#a@foonet/dummy")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "dummy"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/dummy
+ :parts [foonet "dummy"]
+ :len 2)
+ ;; `erc-kill-buffer-function' uses legacy target detection
+ ;; but falls back on buffer name, so no need for:
+ ;;
+ ;; erc-default-recipients '("#a")
+ ;;
+ erc--target (erc--target-from-string "#a")
+ erc-server-process (with-temp-buffer
+ (erc-networks-tests--create-dead-proc)))
+ (kill-buffer)))))
+
+;; FIXME this test is old and may describe impossible states:
+;; leftover identities being qual-equal but not eq (implies
+;; `erc-networks--reclaim-orphaned-target-buffers' is somehow broken).
+;;
+;; Otherwise, the point of this test is to show that server process
+;; identity does not impact the hunt for duplicates.
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates (start)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (funcall start)))
+
+ (with-current-buffer (get-buffer-create "#chan") ; prior session
+ (erc-mode)
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet"))
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("Conflicts not recognized as ERC buffers and not renamed")
+ (get-buffer-create "#chan@foonet")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan@foonet"))))
+
+ ;; These are dupes (not "collisions")
+
+ (with-current-buffer "#chan@foonet" ; same proc
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet"))
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet<dead>")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet<live>")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (let ((created (list (get-buffer "#chan@foonet<live>")
+ (get-buffer "#chan@foonet<dead>")
+ (get-buffer "#chan@foonet"))))
+
+ (with-current-buffer "foonet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+
+ (ert-info ("All buffers considered dupes renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan<2>" "#chan<3>" "#chan<4>"))))
+
+ (ert-info ("All buffers renamed from newest to oldest")
+ (should (equal created (list (get-buffer "#chan<2>")
+ (get-buffer "#chan<3>")
+ (get-buffer "#chan<4>"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given (go)
+
+ ;; The connection's network is discovered before target buffers are
+ ;; created. This shows that the network doesn't matter when only
+ ;; "given" IDs are present.
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (funcall go)))
+
+ (with-current-buffer (get-buffer-create "#chan") ; prior session
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "oofnet"))
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer (get-buffer-create "#chan@oofnet") ;dupe/not collision
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "oofnet"))
+ erc--target (erc--target-from-string "#chan")))
+
+ (with-current-buffer "oofnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+
+ (ert-info ("All buffers matching target and network renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan" "#chan<2>"))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--duplicates ()
+ (ert-info ("Process live, no error")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates
+ #'erc-networks-tests--create-live-proc))
+
+ (ert-info ("Process live, no error, given ID")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given
+ #'erc-networks-tests--create-live-proc))
+
+ (ert-info ("Process dead")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates
+ #'erc-networks-tests--create-dead-proc))
+
+ (ert-info ("Process dead, given ID")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given
+ #'erc-networks-tests--create-dead-proc)))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf (check)
+ (let ((foonet-proc (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ ;; Different proc and not "qual-equal" (different elts)
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc--target (erc--target-from-string "#chan")
+ erc-server-process foonet-proc))
+ (funcall check)
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf ()
+ (ert-info ("Existing #chan buffer respected")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer "barnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@barnet")))
+ (ert-info ("Existing #chan buffer found and renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet")))))))
+
+ (ert-info ("Existing #chan buffer")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-process (erc-networks-tests--create-dead-proc))
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan")))
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan") '("#chan")))))))
+
+ (ert-info ("Existing #chan@foonet and #chan@barnet buffers")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf
+ (lambda ()
+ (with-current-buffer "#chan"
+ (rename-buffer "#chan@foonet"))
+ (should-not (get-buffer "#chan@barnet"))
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet"))
+ erc-networks--id (erc-networks--id-create nil)))
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@foonet")))
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet"))))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (check)
+ (let ((oofnet-proc (with-temp-buffer
+ (erc-networks-tests--create-dead-proc))))
+
+ (with-current-buffer (get-buffer-create "rabnet")
+ (erc-mode)
+ ;; Again, given name preempts network lookup (unrealistic but
+ ;; highlights priorities)
+ (setq erc-networks--id (erc-networks--id-create 'rabnet)
+ erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ ;; Identity is not "qual-equal" to above
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-networks--id (erc-networks--id-create 'oofnet)
+ erc-network 'foonet
+ erc--target (erc--target-from-string "#chan")
+ erc-server-process oofnet-proc))
+ (funcall check)
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf-given ()
+
+ (ert-info ("Existing #chan buffer respected")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ (with-current-buffer "rabnet"
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@rabnet")))
+
+ (ert-info ("Existing #chan buffer found and renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet")))))))
+
+ (ert-info ("Existing #chan@oofnet and #chan@rabnet buffers")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ ;; #chan has already been uniquified (but not grown)
+ (with-current-buffer "#chan" (rename-buffer "#chan@oofnet"))
+ (should-not (get-buffer "#chan@rabnet"))
+
+ (with-current-buffer (get-buffer-create "#chan@rabnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "rabnet"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "rabnet"))))
+
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'oofnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create 'oofnet)) ; given
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@oofnet")))
+
+ (ert-info ("Nothing renamed")
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet"))))))))
+
+;; This shows a corner case where a user explicitly assigns a "given"
+;; ID via `erc-tls' but later connects again without one. It would
+;; actually probably be better if the given identity were to win and
+;; the derived one got an <n>-suffix.
+;;
+;; If we just compared net identities, the two would match, but they
+;; don't here because one has a given name and the other a
+;; discovered/assembled one; so they are *not* qual-equal.
+(ert-deftest erc-networks--reconcile-buffer-names--no-srv-buf-given-mismatch ()
+ ;; Existing #chan buffer *not* respected
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given
+ (lambda ()
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'oofnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil)) ; derived
+ (should (string= (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)
+ "#chan@oofnet")))
+
+ (ert-info ("Collision renamed but not grown (because it's a given)")
+ ;; Original chan uniquified and moved out of the way
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet<2>")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net (check)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))) ; derived
+
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))) ; derived
+
+ (with-current-buffer
+ (get-buffer-create (elt ["#chan" "#chan@foonet"] (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "foonet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "barnet"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net ()
+ (ert-info ("Same network rename")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net
+ (lambda ()
+ (with-current-buffer "foonet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet"))))))
+
+ (ert-info ("Same network keep name")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net
+ (lambda ()
+ (with-current-buffer "barnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@barnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (check)
+
+ (with-current-buffer (get-buffer-create "oofnet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'oofnet) ; one given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create "rabnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'rabnet) ; another given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create (elt ["chan" "#chan@oofnet"]
+ (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "oofnet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "rabnet"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-given ()
+ (ert-info ("Same network rename")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (lambda ()
+ (with-current-buffer "oofnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@oofnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet"))))))
+
+ (ert-info ("Same network keep name")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given
+ (lambda ()
+ (with-current-buffer "rabnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@rabnet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@oofnet" "#chan@rabnet")))))))
+
+(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (check)
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create nil) ; one derived
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create "my-conn")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick "tester"
+ erc-networks--id (erc-networks--id-create 'my-conn) ; one given
+ erc-server-process (erc-networks-tests--create-dead-proc)))
+
+ (with-current-buffer (get-buffer-create (elt ["#chan" "#chan@foonet"]
+ (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "foonet"
+ (list erc-server-process erc-networks--id))))
+
+ (with-current-buffer (get-buffer-create "#chan@my-conn")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan"))
+ (cl-multiple-value-setq (erc-server-process erc-networks--id)
+ (with-current-buffer "my-conn"
+ (list erc-server-process erc-networks--id))))
+
+ (funcall check)
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-existing ()
+
+ (ert-info ("Buf name derived from network")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (lambda ()
+ (with-current-buffer "foonet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet" "#chan@my-conn"))))))
+
+ (ert-info ("Buf name given")
+ (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed
+ (lambda ()
+ (with-current-buffer "my-conn"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@my-conn"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@foonet" "#chan@my-conn")))))))
+
+(ert-deftest erc-networks--reconcile-buffer-names--multi-net-suffixed ()
+ ;; Two networks, same channel. One network has two connections.
+ ;; When the same channel is joined on the latter under a different
+ ;; nick, all buffer names involving that network are suffixed with
+ ;; the network identity.
+
+ (with-current-buffer (get-buffer-create "foonet/bob")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "bob"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/bob
+ :parts [foonet "bob"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create
+ (elt ["#chan@foonet" "#chan@foonet/bob"] (random 2)))
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "foonet/bob"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/bob"))))
+
+ (with-current-buffer (get-buffer-create "barnet")
+ (erc-mode)
+ (setq erc-network 'barnet
+ erc-server-current-nick (elt ["alice" "bob"] (random 2))
+ erc-networks--id (erc-networks--id-create 'barnet)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer (get-buffer-create "#chan@barnet")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "barnet"))
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "barnet"))))
+
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-network 'foonet
+ erc-server-current-nick "alice"
+ erc-networks--id (make-erc-networks--id-qualifying
+ :symbol 'foonet/alice
+ :parts [foonet "alice"]
+ :len 2)
+ erc-server-process (erc-networks-tests--create-live-proc)))
+
+ (with-current-buffer "foonet/alice"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "#chan") erc-networks--id)))
+ (should (string= result "#chan@foonet/alice"))))
+
+ (should (equal (erc-networks-tests--bufnames "#chan")
+ '("#chan@barnet" "#chan@foonet/bob")))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--reconcile-buffer-names--local ()
+ (with-current-buffer (get-buffer-create "DALnet")
+ (erc-mode)
+ (setq erc-network 'DALnet
+ erc-server-announced-name "elysium.ga.us.dal.net"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (ert-info ("Local chan buffer from older, disconnected identity")
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ ;; Cheat here because localp is determined on identity init
+ (setq erc--target (with-current-buffer "DALnet"
+ (erc--target-from-string "&chan"))
+ erc-network 'DALnet
+ erc-server-announced-name "twisted.ma.us.dal.net"
+ erc-server-process (erc-networks-tests--create-dead-proc)
+ erc-networks--id (erc-networks--id-create nil))))
+
+ (ert-info ("Local channels renamed using network server names")
+ (with-current-buffer "DALnet"
+ (let ((result (erc-networks--reconcile-buffer-names
+ (erc--target-from-string "&chan") erc-networks--id)))
+ (should (string= result "&chan@elysium.ga.us.dal.net")))))
+
+ (should (get-buffer "&chan@twisted.ma.us.dal.net"))
+ (should-not (get-buffer "&chan"))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--set-name ()
+ (with-current-buffer (get-buffer-create "localhost:6667")
+ (let (erc-server-announced-name
+ (erc--isupport-params (make-hash-table))
+ erc-network
+ calls)
+ (erc-mode)
+
+ (cl-letf (((symbol-function 'erc-display-line)
+ (lambda (&rest r) (push r calls))))
+
+ (ert-info ("Signals when `erc-server-announced-name' unset")
+ (should-error (erc-networks--set-name nil (make-erc-response)))
+ (should-not calls))
+
+ (ert-info ("Signals when table empty and NETWORK param unset")
+ (setq erc-server-announced-name "irc.fake.gnu.org")
+ (let ((err (should-error (erc-networks--set-name
+ nil (make-erc-response)))))
+ (should (string-match-p "failed" (cadr err)))
+ (should (eq (car err) 'error)))
+ (should (string-match-p (rx "*** Failed") (car (pop calls)))))))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--ensure-announced ()
+ (with-current-buffer (get-buffer-create "localhost:6667")
+ (should (local-variable-if-set-p 'erc-server-announced-name))
+ (let (erc-insert-modify-hook
+ (erc-server-process (erc-networks-tests--create-live-proc))
+ (parsed (make-erc-response
+ :unparsed ":irc.barnet.org 422 tester :MOTD File is missing"
+ :sender "irc.barnet.org"
+ :command "422"
+ :command-args '("tester" "MOTD File is missing")
+ :contents "MOTD File is missing")))
+
+ (erc-mode) ; boilerplate displayable start (needs `erc-server-process')
+ (insert "\n\n")
+ (setq erc-input-marker (make-marker) erc-insert-marker (make-marker))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt) ; boilerplate displayable end
+
+ (erc-networks--ensure-announced erc-server-process parsed)
+ (goto-char (point-min))
+ (search-forward "Failed")
+ (should (string= erc-server-announced-name "irc.barnet.org")))
+ (when noninteractive (kill-buffer))))
+
+(ert-deftest erc-networks--rename-server-buffer--no-existing--orphan ()
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet")))
+
+ (ert-info ("Channel buffer reassociated")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--existing--reuse ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("New buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer reassociated")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf))))
+
+ (erc-networks-tests--clean-bufs))
+
+;; This is for compatibility with pre-28.1 behavior. Basically, we're
+;; trying to match the behavior bug for bug. All buffers were always
+;; suffixed and never reassociated. 28.1 introduced a regression that
+;; reversed the latter, but we've reverted that.
+
+(ert-deftest erc-networks--rename-server-buffer--existing--noreuse ()
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers) ; default
+ (let* ((old-buf (get-buffer-create "irc.foonet.org:6697/irc.foonet.org"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf))
+ erc-reuse-buffers)
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (buffer-local-value 'erc-networks--id old-buf)
+ erc--target (erc--target-from-string "#chan"))
+ (rename-buffer (erc-networks--construct-target-buffer-name erc--target)))
+
+ (ert-info ("Server buffer uniquely renamed")
+ (with-current-buffer
+ (get-buffer-create "irc.foonet.org:6697/irc.foonet.org<2>")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name)
+ "irc.foonet.org:6697/irc.foonet.org<2>"))
+ (goto-char (point-min))
+ (should-not (search-forward "Old buf" nil t))))
+
+ (ert-info ("Channel buffer not reassociated")
+ (should-not
+ (erc-server-process-alive
+ (should (get-buffer "#chan/irc.foonet.org"))))
+ (with-current-buffer (get-buffer "#chan/irc.foonet.org")
+ (should-not erc-server-connected)
+ (should (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name)
+ "irc.foonet.org:6697/irc.foonet.org")))))
+
+ (ert-info ("Old buffer still around")
+ (should (buffer-live-p old-buf)))))
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--reconnecting ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc--target (erc--target-from-string "#chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("No new buffer")
+ (with-current-buffer old-buf
+ (setq erc-server-process (erc-networks-tests--create-live-proc))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--id ()
+ (let* ((old-buf (get-buffer-create "MySession"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create 'MySession)
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-networks--id (erc-networks--id-create 'MySession)
+ erc-server-process old-proc
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("No new buffer")
+ (with-current-buffer old-buf
+ (setq erc-server-process (erc-networks-tests--create-live-proc))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "MySession"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (erc-server-process-alive "#chan")
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "MySession"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--existing--live ()
+ (let* (erc-kill-server-hook
+ erc-insert-modify-hook
+ (old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil))
+ (should (erc-server-process-alive)))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-networks--id (erc-networks--id-create nil)
+ erc-server-connected t
+ erc--target (erc--target-from-string "#chan")))
+
+ (ert-info ("New buffer rejected, abandoned, not killed")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc-networks--id (erc-networks--id-create nil))
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (eq erc-active-buffer old-buf))
+ (should-not (erc-server-process-alive))
+ (should (string= (buffer-name) "irc.foonet.org"))
+ (goto-char (point-min))
+ (search-forward "still connected")))
+
+ (ert-info ("Channel buffer updated with live proc")
+ (should (erc-server-process-alive "#chan"))
+ (with-current-buffer "#chan"
+ (should erc-server-connected)
+ (should (erc-server-buffer-live-p))
+ (should (eq erc-server-process old-proc))
+ (should (buffer-live-p (process-buffer erc-server-process)))
+ (with-current-buffer (process-buffer erc-server-process)
+ (should (eq (current-buffer) (get-buffer "FooNet")))
+ (should (eq (current-buffer) old-buf))))))
+
+ (should (get-buffer "FooNet"))
+ (should (get-buffer "irc.foonet.org"))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--rename-server-buffer--local-match ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-server-announced-name "us-east.foonet.org"
+ erc--target (erc--target-from-string "&chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("New server buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org"
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer reassociated when &local server matches")
+ (should (erc-server-process-alive "&chan"))
+ (with-current-buffer "&chan"
+ (should erc-server-connected)
+ (should-not (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf)))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--rename-server-buffer--local-nomatch ()
+ (let* ((old-buf (get-buffer-create "FooNet"))
+ (old-proc (erc-networks-tests--create-dead-proc old-buf)))
+
+ (with-current-buffer old-buf
+ (erc-mode)
+ (insert "*** Old buf")
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-west.foonet.org"
+ erc-insert-marker (set-marker (make-marker) (point-max))
+ erc-server-process old-proc
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params))
+
+ (with-current-buffer (get-buffer-create "&chan")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-process old-proc
+ erc-server-announced-name "us-west.foonet.org" ; west
+ erc--target (erc--target-from-string "&chan")
+ erc-networks--id (erc-networks--id-create nil)))
+
+ (ert-info ("New server buffer steals name, content")
+ (with-current-buffer (get-buffer-create "irc.foonet.org")
+ (erc-mode)
+ (setq erc-network 'FooNet
+ erc-server-current-nick "tester"
+ erc-server-announced-name "us-east.foonet.org" ; east
+ erc-server-process (erc-networks-tests--create-live-proc)
+ erc--isupport-params (make-hash-table)
+ erc-networks--id (erc-networks--id-create nil))
+
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc-networks--rename-server-buffer erc-server-process))
+ (should (string= (buffer-name) "FooNet"))
+ (goto-char (point-min))
+ (should (search-forward "Old buf"))))
+
+ (ert-info ("Channel buffer now orphaned even though network matches")
+ (should-not (erc-server-process-alive "&chan"))
+ (with-current-buffer "&chan"
+ (should-not erc-server-connected)
+ (should (eq erc-server-process old-proc))
+ (erc-with-server-buffer
+ (should (string= (buffer-name) "FooNet")))))
+
+ (ert-info ("Original buffer killed off")
+ (should-not (buffer-live-p old-buf)))
+
+ (erc-networks-tests--clean-bufs)))
+
+(ert-deftest erc-networks--update-server-identity--double-existing ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "#chan@foonet/bob")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 2)))
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2)))
+
+ (ert-info ("Adopt equivalent identity")
+ (should (eq (erc-networks--update-server-identity)
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "#chan@foonet/bob")))))
+
+ (ert-info ("Ignore non-matches")
+ (should-not (erc-networks--update-server-identity))
+ (should (eq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "#chan@foonet/bob"))))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-new ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/alice")
+ (erc-mode)
+ (setq erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/alice"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-bounded ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/alice/home")
+ (erc-mode)
+ (setq erc-networks--id (make-erc-networks--id-qualifying
+ :parts [foonet "alice" home] :len 3)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/alice/home")
+ (erc-mode)
+ (setq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/alice/home"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--double-even ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob"] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 1)))
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "#chan")
+ erc-networks--id (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet"))))
+
+ (ert-info ("Evolve identity to prevent ambiguity")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 2))
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))
+
+ (ert-info ("Collision renamed")
+ (with-current-buffer "foonet/alice"
+ (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/alice)))
+
+ (with-current-buffer "#chan@foonet/alice"
+ (should (eq (erc-networks--id-symbol erc-networks--id)
+ 'foonet/alice)))))
+
+ (erc-networks-tests--clean-bufs))
+
+(ert-deftest erc-networks--update-server-identity--triple-new ()
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob" home] :len 1))
+
+ (with-current-buffer (get-buffer-create "foonet/bob/office")
+ (erc-mode)
+ (setq erc-networks--id
+ (make-erc-networks--id-qualifying :parts [foonet "bob" office]
+ :len 3)))
+ (with-current-buffer (get-buffer-create "#chan@foonet/bob/office")
+ (erc-mode)
+ (setq erc-networks--id
+ (buffer-local-value 'erc-networks--id
+ (get-buffer "foonet/bob/office"))))
+
+ (ert-info ("Extend our identity's canonical ID so that it's unique")
+ (should-not (erc-networks--update-server-identity))
+ (should (= (erc-networks--id-qualifying-len erc-networks--id) 3))))
+
+ (erc-networks-tests--clean-bufs))
+
+;;; erc-networks-tests.el ends here
diff --git a/test/lisp/erc/erc-scenarios-auth-source.el b/test/lisp/erc/erc-scenarios-auth-source.el
new file mode 100644
index 00000000000..3d399a18154
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-auth-source.el
@@ -0,0 +1,178 @@
+;;; erc-scenarios-auth-source.el --- auth-source scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; For practical reasons (mainly lack of imagination), this file
+;; contains tests for both server-password and NickServ contexts.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(defun erc-scenarios-common--auth-source (id dialog &rest rest)
+ (push "machine GNU.chat port %d user \"#chan\" password spam" rest)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/auth-source")
+ (dumb-server (erc-d-run "localhost" t dialog))
+ (port (process-contact dumb-server :service))
+ (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest)
+ "machine MyHost port irc password 123"))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester"
+ :id id)
+ (should (string= (buffer-name) (if id
+ (symbol-name id)
+ (format "127.0.0.1:%d" port))))
+ (erc-d-t-wait-for 5 (eq erc-network 'FooNet))))))
+
+(ert-deftest erc-scenarios-base-auth-source-server--dialed ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--auth-source
+ nil 'foonet
+ "machine GNU.chat port %d user tester password fake"
+ "machine FooNet port %d user tester password fake"
+ "machine 127.0.0.1 port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user imposter password fake"))
+
+(ert-deftest erc-scenarios-base-auth-source-server--netid ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--auth-source
+ 'MySession 'foonet
+ "machine MySession port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user tester password fake"
+ "machine FooNet port %d user tester password fake"))
+
+(ert-deftest erc-scenarios-base-auth-source-server--netid-custom ()
+ :tags '(:expensive-test)
+ (let ((erc-auth-source-server-function
+ (lambda (&rest _) (erc-auth-source-search :host "MyHost"))))
+ (erc-scenarios-common--auth-source
+ 'MySession 'foonet
+ "machine 127.0.0.1 port %d user tester password fake"
+ "machine MyHost port %d user tester password changeme"
+ "machine MySession port %d user tester password fake")))
+
+(ert-deftest erc-scenarios-base-auth-source-server--nopass ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--auth-source nil 'nopass)))
+
+(ert-deftest erc-scenarios-base-auth-source-server--nopass-netid ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--auth-source 'MySession 'nopass)))
+
+;; Identify via auth source with no initial password
+
+(defun erc-scenarios-common--services-auth-source (&rest rest)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/auth-source")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service))
+ (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest)
+ "machine MyHost port irc password 123"))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-modules (cons 'services erc-modules))
+ (erc-use-auth-source-for-nickserv-password t) ; do consult for NickServ
+ (expect (erc-d-t-make-expecter))
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (cl-letf (((symbol-function 'read-passwd)
+ (lambda (&rest _) (error "Unexpected read-passwd call"))))
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 8 (eq erc-network 'Libera.Chat))
+ (funcall expect 3 "This nickname is registered.")
+ (funcall expect 3 "You are now identified")
+ (funcall expect 3 "Last login from")
+ (erc-cmd-QUIT ""))))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+;; These tests are about authenticating to nick services
+
+(ert-deftest erc-scenarios-services-auth-source--network ()
+ :tags '(:expensive-test)
+ ;; Skip consulting auth-source for the server password (PASS).
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password spam"
+ "machine zirconium.libera.chat port %d user tester password fake"
+ "machine Libera.Chat port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--network-connect-lookup ()
+ :tags '(:expensive-test)
+ ;; Do consult auth-source for the server password (and find nothing)
+ (erc-scenarios-common--services-auth-source
+ "machine zirconium.libera.chat port %d user tester password fake"
+ "machine Libera.Chat port %d user tester password changeme"))
+
+(ert-deftest erc-scenarios-services-auth-source--announced ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password spam"
+ "machine zirconium.libera.chat port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--dialed ()
+ :tags '(:expensive-test)
+ ;; Support legacy host -> domain name
+ ;; (likely most common in real configs)
+ (let (erc-auth-source-server-function)
+ (erc-scenarios-common--services-auth-source
+ "machine 127.0.0.1 port %d user tester password changeme")))
+
+(ert-deftest erc-scenarios-services-auth-source--custom ()
+ :tags '(:expensive-test)
+ (let (erc-auth-source-server-function
+ (erc-auth-source-services-function
+ (lambda (&rest _) (erc-auth-source-search :host "MyAccount"))))
+ (erc-scenarios-common--services-auth-source
+ "machine zirconium.libera.chat port %d user tester password spam"
+ "machine MyAccount port %d user tester password changeme"
+ "machine 127.0.0.1 port %d user tester password fake")))
+
+;;; erc-scenarios-auth-source.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association-nick.el b/test/lisp/erc/erc-scenarios-base-association-nick.el
new file mode 100644
index 00000000000..3e848be4df2
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association-nick.el
@@ -0,0 +1,163 @@
+;;; erc-scenarios-base-association-nick.el --- base assoc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; You register a new nick, disconnect, and log back in, but your nick
+;; is not granted, so ERC obtains a backtick'd version. You open a
+;; query buffer for NickServ, and ERC names it using the net-ID (which
+;; includes the backtick'd nick) as a suffix. The original
+;; (disconnected) NickServ buffer gets renamed with *its* net-ID as
+;; well. You then identify to NickServ, and the dead session is no
+;; longer considered distinct.
+
+(ert-deftest erc-scenarios-base-association-nick-bumped ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bumped")
+ (dumb-server (erc-d-run "localhost" t 'renicked 'again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Create an account for tester and quit")
+ (with-current-buffer "foonet"
+ (funcall expect 3 "debug mode")
+
+ (erc-cmd-QUERY "NickServ")
+ (with-current-buffer "NickServ"
+ (erc-scenarios-common-say "REGISTER changeme")
+ (funcall expect 5 "Account created")
+ (funcall expect 1 "You're now logged in as tester"))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (funcall expect 5 "ERC finished"))))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT))
+
+ (erc-d-t-wait-for 10 "Nick request rejection prevents reassociation (good)"
+ (get-buffer "foonet/tester`"))
+
+ (ert-info ("Ask NickServ to change nick")
+ (with-current-buffer "foonet/tester`"
+ (funcall expect 3 "already in use")
+ (funcall expect 3 "debug mode")
+ (erc-cmd-QUERY "NickServ"))
+
+ (erc-d-t-wait-for 1 "Dead NickServ query buffer renamed, now qualified"
+ (get-buffer "NickServ@foonet/tester"))
+
+ (with-current-buffer "NickServ@foonet/tester`" ; new one
+ (erc-scenarios-common-say "IDENTIFY tester changeme")
+ (funcall expect 5 "You're now logged in as tester")
+ (ert-info ("Original buffer found, reused")
+ (erc-d-t-wait-for 2 (equal (buffer-name) "NickServ")))))
+
+ (ert-info ("Ours is the only NickServ buffer that remains")
+ (should-not (cdr (erc-scenarios-common-buflist "NickServ"))))
+
+ (ert-info ("Visible network ID truncated to one component")
+ (should (not (get-buffer "foonet/tester`")))
+ (should (not (get-buffer "foonet/tester")))
+ (should (get-buffer "foonet")))))
+
+;; A less common variant is when your bouncer switches to an alternate
+;; nick while you're disconnected, and upon reconnecting, you get
+;; a new nick.
+
+(ert-deftest erc-scenarios-base-association-nick-bumped-mandated-renick ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bumped")
+ (dumb-server (erc-d-run "localhost" t 'foisted 'refoisted))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Greet bob and quit")
+ (with-current-buffer "foonet"
+ (funcall expect 3 "debug mode")
+
+ (erc-cmd-QUERY "bob")
+ (with-current-buffer "bob"
+ (erc-scenarios-common-say "hi")
+ (funcall expect 5 "hola")
+ (funcall expect 1 "how r u?"))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (funcall expect 5 "ERC finished"))))
+
+ ;; Since we use reconnect, a new buffer won't be created
+ ;; TODO add variant with clean `erc' invocation
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT))
+
+ (ert-info ("Server-initiated renick")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet/dummy"))
+ (should-not (get-buffer "foonet/tester"))
+ (funcall expect 15 "debug mode"))
+
+ (erc-d-t-wait-for 1 "Old query renamed, now qualified"
+ (get-buffer "bob@foonet/tester"))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "bob@foonet/dummy"))
+ (erc-cmd-NICK "tester")
+ (ert-info ("Buffers combined")
+ (erc-d-t-wait-for 2 (equal (buffer-name) "bob")))))
+
+ (with-current-buffer "foonet"
+ (funcall expect 5 "You're now logged in as tester"))
+
+ (ert-info ("Ours is the only bob buffer that remains")
+ (should-not (cdr (erc-scenarios-common-buflist "bob"))))
+
+ (ert-info ("Visible network ID truncated to one component")
+ (should (not (get-buffer "foonet/dummy")))
+ (should (get-buffer "foonet")))))
+
+;;; erc-scenarios-base-association-nick.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association-samenet.el b/test/lisp/erc/erc-scenarios-base-association-samenet.el
new file mode 100644
index 00000000000..b7c7079df34
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association-samenet.el
@@ -0,0 +1,144 @@
+;;; erc-scenarios-base-association-samenet.el --- assoc samenet scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(declare-function erc-network-name "erc-networks")
+(declare-function erc-network "erc-networks")
+(defvar erc-autojoin-channels-alist)
+(defvar erc-network)
+
+;; One network, two simultaneous connections, no IDs.
+;; Reassociates on reconnect with and without server buffer.
+
+(defun erc-scenarios-common--base-association-samenet (after)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/samenet")
+ (dumb-server (erc-d-run "localhost" t 'tester 'chester 'tester2))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.5)
+ (erc-server-flood-margin 30))
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "chester"
+ :password "changeme"
+ :full-name "chester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)))
+
+ (erc-d-t-wait-for 3 "Dialed Buflist is Empty"
+ (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer "foonet/tester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester"))
+ (with-current-buffer "foonet/chester" (funcall expect 3 "debug mode"))
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester"))
+
+ (ert-info ("Nick tester sees other nick chester in channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "find the forester")
+ (erc-cmd-QUIT "")))
+
+ (ert-info ("Nick chester sees other nick tester in same channel")
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "find the forester")))
+
+ (funcall after expect)))
+
+(ert-deftest erc-scenarios-base-association-samenet--reconnect-one ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-samenet
+ (lambda (expect)
+
+ (ert-info ("Connection tester reconnects")
+ (with-current-buffer "foonet/tester"
+ (erc-d-t-wait-for 10 (not (erc-server-process-alive)))
+ (funcall expect 10 "*** ERC finished")
+ (erc-cmd-RECONNECT)
+ (funcall expect 5 "debug mode")))
+
+ (ert-info ("Reassociated to same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))
+
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "welcome again")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))))
+
+(ert-deftest erc-scenarios-base-association-samenet--new-buffer ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-samenet
+ (lambda (expect)
+
+ (ert-info ("Tester kills buffer and connects from scratch")
+
+ (let (port)
+ (with-current-buffer "foonet/tester"
+ (erc-d-t-wait-for 10 (not (erc-server-process-alive)))
+ (funcall expect 10 "*** ERC finished")
+ (setq port erc-session-port)
+ (kill-buffer))
+
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet)))))
+
+ (with-current-buffer "foonet/tester" (funcall expect 3 "debug mode"))
+
+ (ert-info ("Reassociated to same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "chester")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))
+
+ (with-current-buffer "#chan@foonet/chester"
+ (funcall expect 5 "tester")
+ (funcall expect 5 "welcome again")
+ (funcall expect 5 "welcome again")
+ (erc-cmd-QUIT "")))))
+
+;;; erc-scenarios-base-association-samenet.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-association.el b/test/lisp/erc/erc-scenarios-base-association.el
new file mode 100644
index 00000000000..83e5101e3ad
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-association.el
@@ -0,0 +1,192 @@
+;;; erc-scenarios-base-association.el --- base assoc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(declare-function erc-network-name "erc-networks")
+(declare-function erc-network "erc-networks")
+(defvar erc-autojoin-channels-alist)
+(defvar erc-network)
+
+;; Two networks, same channel name, no confusion (no bouncer). Some
+;; of this draws from bug#47522 "foil-in-server-buf". It shows that
+;; disambiguation-related changes added for bug#48598 are not specific
+;; to bouncers.
+
+(defun erc-scenarios-common--base-association-multi-net (second-join)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/multi-net")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server-foonet-buffer (get-buffer-create "*server-foonet*"))
+ (dumb-server-barnet-buffer (get-buffer-create "*server-barnet*"))
+ (dumb-server-foonet (erc-d-run "localhost" t "server-foonet" 'foonet))
+ (dumb-server-barnet (erc-d-run "localhost" t "server-barnet" 'barnet))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet, join #chan")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port (process-contact dumb-server-foonet :service)
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 2 (get-buffer "#chan"))
+
+ (ert-info ("Connect to barnet, join #chan")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port (process-contact dumb-server-barnet :service)
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (funcall expect 5 "debug mode")))
+
+ (funcall second-join)
+
+ (erc-d-t-wait-for 3 (get-buffer "#chan@barnet"))
+
+ (erc-d-t-wait-for 2 "Buf #chan now #chan@foonet"
+ (and (get-buffer "#chan@foonet") (not (get-buffer "#chan"))))
+
+ (ert-info ("All #chan@foonet output consumed")
+ (with-current-buffer "#chan@foonet"
+ (funcall expect 3 "bob")
+ (funcall expect 3 "was created on")
+ (funcall expect 3 "prosperous")))
+
+ (ert-info ("All #chan@barnet output consumed")
+ (with-current-buffer "#chan@barnet"
+ (funcall expect 3 "mike")
+ (funcall expect 3 "was created on")
+ (funcall expect 20 "ingenuous")))))
+
+(ert-deftest erc-scenarios-base-association-multi-net--baseline ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-multi-net
+ (lambda () (with-current-buffer "barnet" (erc-cmd-JOIN "#chan")))))
+
+;; The /join command only targets the current buffer's process. This
+;; recasts scenario bug#48598 "ambiguous-join" (which was based on
+;; bug#47522) to show that issuing superfluous /join commands
+;; (apparently fairly common) is benign.
+
+(ert-deftest erc-scenarios-base-association-multi-net--ambiguous-join ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-association-multi-net
+ (lambda ()
+ (ert-info ("Nonsensical JOIN attempts silently dropped.")
+ (with-current-buffer "foonet" (erc-cmd-JOIN "#chan"))
+ (sit-for 0.1)
+ (with-current-buffer "#chan" (erc-cmd-JOIN "#chan"))
+ (sit-for 0.1)
+ (erc-d-t-wait-for 2 (get-buffer "#chan"))
+ (erc-d-t-wait-for 1 "Only one #chan buffer exists"
+ (should (equal (erc-scenarios-common-buflist "#chan")
+ (list (get-buffer "#chan")))))
+ (with-current-buffer "*server-barnet*"
+ (erc-d-t-absent-for 0.1 "JOIN"))
+ (with-current-buffer "barnet" (erc-cmd-JOIN "#chan"))))))
+
+;; Playback for same channel on two networks routed correctly.
+;; Originally from Bug#48598: 28.0.50; buffer-naming collisions
+;; involving bouncers in ERC.
+
+(ert-deftest erc-scenarios-base-association-bouncer-history ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bouncer-history")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.5)
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (setq erc-server-process-foo erc-server-process)
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "foonet")))
+
+ (erc-d-t-wait-for 5 (get-buffer "#chan"))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 5 "Temporary name assigned"
+ (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)))
+
+ (ert-info ("Networks correctly determined and adopted as buffer names")
+ (with-current-buffer erc-server-buffer-foo
+ (erc-d-t-wait-for 3 "network name foonet becomes buffer name"
+ (and (eq (erc-network) 'foonet) (string= (buffer-name) "foonet"))))
+ (with-current-buffer erc-server-buffer-bar
+ (erc-d-t-wait-for 3 "network name barnet becomes buffer name"
+ (and (eq (erc-network) 'barnet) (string= (buffer-name) "barnet")))))
+
+ (erc-d-t-wait-for 5 (get-buffer "#chan@barnet"))
+
+ (ert-info ("Two channel buffers created, original #chan renamed")
+ (should (= 4 (length (erc-buffer-list))))
+ (should (equal (list (get-buffer "#chan@barnet")
+ (get-buffer "#chan@foonet"))
+ (erc-scenarios-common-buflist "#chan"))))
+
+ (ert-info ("#chan@foonet is exclusive, no cross-contamination")
+ (with-current-buffer "#chan@foonet"
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))))
+
+ (ert-info ("#chan@barnet is exclusive, no cross-contamination")
+ (with-current-buffer "#chan@barnet"
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (should (eq erc-server-process erc-server-process-bar))))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan@foonet"
+ (erc-d-t-search-for 10 "please your lordship"))
+ (with-current-buffer "#chan@barnet"
+ (erc-d-t-search-for 10 "I'll bid adieu")))))
+
+;;; erc-scenarios-base-association.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
new file mode 100644
index 00000000000..474739d01be
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
@@ -0,0 +1,171 @@
+;;; erc-scenarios-compat-rename-bouncer.el --- compat-rename scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; Ensure deprecated option still respected when old default value
+;; explicitly set ("respected" in the sense of having names reflect
+;; dialed TCP endpoints with possible uniquifiers but without any of
+;; the old issues, pre-bug#48598).
+
+(defun erc-scenarios-common--base-compat-no-rename-bouncer (dialogs auto more)
+ (erc-scenarios-common-with-cleanup
+ ;; These actually *are* (assigned-)network-id related because
+ ;; our kludge assigns one after the fact.
+ ((erc-scenarios-common-dialog "base/netid/bouncer")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (chan-buf-foo (format "#chan@127.0.0.1:%d" port))
+ (chan-buf-bar (format "#chan@127.0.0.1:%d<2>" port))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect auto)
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id nil))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 "Final buffer name determined"
+ (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id nil))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 "Final buffer name determined"
+ (string= (buffer-name) (format "127.0.0.1:%d<2>" port)))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should (equal (erc-scenarios-common-buflist "127.0.0.1")
+ (list (get-buffer (format "127.0.0.1:%d<2>" port))
+ (get-buffer (format "127.0.0.1:%d" port))))))
+
+ (ert-info ("Join #chan@barnet")
+ (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist"
+ (equal (list (get-buffer chan-buf-bar)
+ (get-buffer chan-buf-foo))
+ (erc-scenarios-common-buflist "#chan")))
+
+ (ert-info ("#chan@127.0.0.1:$port is exclusive to foonet")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))
+ (erc-d-t-search-for 10 "ape is dead")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (ert-info ("#chan@127.0.0.1:$port<2> is exclusive to barnet")
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (should (eq erc-server-process erc-server-process-bar))
+ (erc-d-t-search-for 10 "keeps you from dishonour")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (when more (funcall more))))
+
+(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--basic ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (erc-scenarios-common--base-compat-no-rename-bouncer
+ '(foonet barnet) nil nil))))
+
+(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--reconnect ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass #'erc-scenarios-common--clash-rename-pass-handler))
+ (dialogs '(foonet-drop barnet-drop stub-again stub-again
+ foonet-again barnet-again))
+ (after
+ (lambda ()
+ (pcase-let* ((`(,barnet ,foonet)
+ (erc-scenarios-common-buflist "127.0.0.1"))
+ (port (process-contact (with-current-buffer foonet
+ erc-server-process)
+ :service)))
+
+ (ert-info ("Sanity check: barnet retains uniquifying suffix")
+ (should (string-suffix-p "<2>" (buffer-name barnet))))
+
+ ;; Simulate disconnection and `erc-server-auto-reconnect'
+ (ert-info ("Reconnect to foonet and barnet back-to-back")
+ (with-current-buffer foonet
+ (erc-d-t-wait-for 5 (erc-server-process-alive)))
+ (with-current-buffer barnet
+ (erc-d-t-wait-for 5 (erc-server-process-alive))))
+
+ (ert-info ("#chan@127.0.0.1:<port> is exclusive to foonet")
+ (with-current-buffer (format "#chan@127.0.0.1:%d" port)
+ (erc-d-t-search-for 1 "<alice>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (erc-d-t-search-for 10 "please your lordship")))
+
+ (ert-info ("#chan@barnet is exclusive to barnet")
+ (with-current-buffer (format "#chan@127.0.0.1:%d<2>" port)
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-search-for 1 "much in private")))
+
+ ;; Ordering deterministic here even though not so for reconnect
+ (should (equal (list barnet foonet)
+ (erc-scenarios-common-buflist "127.0.0.1")))
+ (should (equal (list
+ (get-buffer (format "#chan@127.0.0.1:%d<2>" port))
+ (get-buffer (format "#chan@127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "#chan")))))))
+
+ (with-suppressed-warnings ((obsolete erc-rename-buffers))
+ (let (erc-rename-buffers)
+ (erc-scenarios-common--base-compat-no-rename-bouncer dialogs
+ 'auto after)))))
+
+;;; erc-scenarios-compat-rename-bouncer.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-misc-regressions.el b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
new file mode 100644
index 00000000000..8f5700df14b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
@@ -0,0 +1,126 @@
+;;; erc-scenarios-base-misc-regressions.el --- misc regressions scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(defun erc-scenarios--rebuffed-gapless-pass-handler (dialog exchange)
+ (when (eq (erc-d-dialog-name dialog) 'pass-stub)
+ (let* ((match (erc-d-exchange-match exchange 1))
+ (sym (if (string= match "foonet") 'foonet 'barnet)))
+ (should (member match (list "foonet" "barnet")))
+ (erc-d-load-replacement-dialog dialog sym 1))))
+
+(ert-deftest erc-scenarios-base-gapless-connect ()
+ "Back-to-back entry-point invocations happen successfully.
+Originally from scenario rebuffed/gapless as explained in Bug#48598:
+28.0.50; buffer-naming collisions involving bouncers in ERC."
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/gapless-connect")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-penalty erc-server-flood-penalty)
+ (erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass #'erc-scenarios--rebuffed-gapless-pass-handler))
+ (dumb-server (erc-d-run "localhost" t
+ 'pass-stub 'pass-stub 'barnet 'foonet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo
+ erc-server-buffer-bar)
+
+ (ert-info ("Connect twice to same endpoint without pausing")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")))
+
+ (ert-info ("Returned server buffers are unique")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)))
+
+ (ert-info ("Both connections still alive")
+ (should (get-process (format "erc-127.0.0.1-%d" port)))
+ (should (get-process (format "erc-127.0.0.1-%d<1>" port))))
+
+ (with-current-buffer erc-server-buffer-bar
+ (funcall expect 2 "marked as being away"))
+
+ (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
+ (funcall expect 10 "was created on")
+ (funcall expect 2 "his second fit"))
+
+ (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
+ (funcall expect 10 "was created on")
+ (funcall expect 2 "no use of him"))))
+
+;; This defends against a regression in `erc-server-PRIVMSG' caused by
+;; the removal of `erc-auto-query'. When an active channel buffer is
+;; killed off and PRIVMSGs arrive targeting it, the buffer should be
+;; recreated. See elsewhere for NOTICE logic, which is more complex.
+
+(ert-deftest erc-scenarios-base-channel-buffer-revival ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/channel-buffer-revival")
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 1 (get-buffer "FooNet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Channel buffer #chan alive and well")
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "Our queen and all her elves")
+ (kill-buffer)))
+
+ (should-not (get-buffer "#chan"))
+
+ (ert-info ("Channel buffer #chan revived")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "and be prosperous")))))
+
+;;; erc-scenarios-base-misc-regressions.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
new file mode 100644
index 00000000000..6c6568cad68
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
@@ -0,0 +1,34 @@
+;;; erc-scenarios-base-netid-bouncer-id.el --- net-id bouncer ID scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--id-foo ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:foo-id t) 'foonet 'barnet))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--id-bar ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:bar-id t) 'foonet 'barnet))
+
+;;; erc-scenarios-base-netid-bouncer-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
new file mode 100644
index 00000000000..f48e1ef3940
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
@@ -0,0 +1,30 @@
+;;; erc-scenarios-base-netid-bouncer-recon-base.el --- net-id base scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--recon-base ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect nil nil))
+
+;;; erc-scenarios-base-netid-bouncer-recon-base.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
new file mode 100644
index 00000000000..2f58c3269e3
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
@@ -0,0 +1,32 @@
+;;; erc-scenarios-base-netid-bouncer-recon-both.el --- net-id both scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-scenarios-common)
+
+(ert-deftest erc-scenarios-base-netid-bouncer--recon-both ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id 'bar-id))
+
+;;; erc-scenarios-base-netid-bouncer-recon-both.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
new file mode 100644
index 00000000000..72510809ab4
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
@@ -0,0 +1,35 @@
+;;; erc-scenarios-base-netid-bouncer-recon-id.el --- recon ID scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-foo ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id nil))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-bar ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer--reconnect nil 'bar-id))
+
+
+;;; erc-scenarios-base-netid-bouncer-recon-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
new file mode 100644
index 00000000000..d171e1f9f91
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
@@ -0,0 +1,35 @@
+;;; erc-scenarios-base-netid-bouncer.el --- net-id bouncer scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--base ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer () 'foonet 'barnet))
+
+(ert-deftest erc-scenarios-base-netid-bouncer--both ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-bouncer '(:foo-id t :bar-id t)
+ 'foonet 'barnet))
+
+;;; erc-scenarios-base-netid-bouncer.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
new file mode 100644
index 00000000000..248144d6f9b
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
@@ -0,0 +1,147 @@
+;;; erc-scenarios-base-network-id-samenet.el --- netid-id samenet scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(cl-defun erc-scenarios-common--base-network-id-same-network
+ ((&key nick id server chan
+ &aux (nick-a nick) (id-a id) (serv-buf-a server) (chan-buf-a chan))
+ (&key nick id server chan
+ &aux (nick-b nick) (id-b id) (serv-buf-b server) (chan-buf-b chan)))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/netid/samenet")
+ (dumb-server (erc-d-run "localhost" t 'tester 'chester))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ erc-serv-buf-a erc-serv-buf-b)
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer
+ (setq erc-serv-buf-a (erc :server "127.0.0.1"
+ :port port
+ :nick nick-a
+ :password "changeme"
+ :full-name nick-a
+ :id id-a))
+ (erc-scenarios-common-assert-initial-buf-name id-a port)
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer
+ (setq erc-serv-buf-b (erc :server "127.0.0.1"
+ :port port
+ :nick nick-b
+ :password "changeme"
+ :full-name nick-b
+ :id id-b))
+ (erc-scenarios-common-assert-initial-buf-name id-b port)))
+
+ (erc-d-t-wait-for 3 (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer erc-serv-buf-a
+ (should (string= (buffer-name) serv-buf-a))
+ (funcall expect 8 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (with-current-buffer erc-serv-buf-b
+ (should (string= (buffer-name) serv-buf-b))
+ (funcall expect 8 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer chan-buf-a))
+ (erc-d-t-wait-for 10 (get-buffer chan-buf-b))
+
+ (ert-info ("Greets other nick in same channel")
+ (with-current-buffer chan-buf-a
+ (funcall expect 5 "chester")
+ (funcall expect 5 "find the forester")
+ (erc-cmd-MSG "#chan chester: hi")))
+
+ (ert-info ("Sees other nick in same channel")
+ (with-current-buffer chan-buf-b
+ (funcall expect 5 "tester")
+ (funcall expect 10 "<tester> chester: hi")
+ (funcall expect 5 "This was lofty")
+ (erc-cmd-MSG "#chan hi tester")))
+
+ (with-current-buffer chan-buf-a
+ (funcall expect 5 "To employ you towards")
+ (erc-cmd-QUIT ""))
+
+ (with-current-buffer chan-buf-b
+ (funcall expect 5 "To employ you towards")
+ (erc-cmd-QUIT ""))))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--two-ids ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id 'tester/foonet
+ :server "tester/foonet"
+ :chan "#chan@tester/foonet")
+ (list :nick "chester"
+ :id 'chester/foonet
+ :server "chester/foonet"
+ :chan "#chan@chester/foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--one-id-tester ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id 'tester/foonet
+ :server "tester/foonet"
+ :chan "#chan@tester/foonet")
+ (list :nick "chester"
+ :id nil
+ :server "foonet"
+ :chan "#chan@foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--one-id-chester ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id nil
+ :server "foonet"
+ :chan "#chan@foonet")
+ (list :nick "chester"
+ :id 'chester/foonet
+ :server "chester/foonet"
+ :chan "#chan@chester/foonet")))
+
+(ert-deftest erc-scenarios-base-network-id-same-network--no-ids ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--base-network-id-same-network
+ (list :nick "tester"
+ :id nil
+ :server "foonet/tester"
+ :chan "#chan@foonet/tester") ; <- note net before nick
+ (list :nick "chester"
+ :id nil
+ :server "foonet/chester"
+ :chan "#chan@foonet/chester")))
+
+;;; erc-scenarios-base-network-id-samenet.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el b/test/lisp/erc/erc-scenarios-base-reconnect.el
new file mode 100644
index 00000000000..30d692058d6
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-reconnect.el
@@ -0,0 +1,226 @@
+;;; erc-scenarios-base-reconnect.el --- Base-reconnect scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; This ensures we only reconnect `erc-server-reconnect-attempts'
+;; (rather than infinitely many) times, which can easily happen when
+;; tweaking code related to process sentinels in erc-backend.el.
+
+(ert-deftest erc-scenarios-base-reconnect-timer ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'timer 'timer 'timer-last))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect t)
+ erc-autojoin-channels-alist
+ erc-server-buffer)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server tries to connect thrice (including initial attempt)")
+ (with-current-buffer erc-server-buffer
+ (dotimes (n 3)
+ (ert-info ((format "Attempt %d" n))
+ (funcall expect 3 "Opening connection")
+ (funcall expect 2 "Password incorrect")
+ (funcall expect 2 "Connection failed!")
+ (funcall expect 2 "Re-establishing connection")))
+ (ert-info ("Prev attempt was final")
+ (erc-d-t-absent-for 1 "Opening connection" (point)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (should (equal (list (get-buffer (format "127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "127.0.0.1"))))))
+
+(defun erc-scenarios-common--base-reconnect-options (test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'options 'options-again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-auto-reconnect t)
+ erc-autojoin-channels-alist
+ erc-server-buffer)
+
+ (should (memq 'autojoin erc-modules))
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 10 "debug mode")))
+
+ (ert-info ("Wait for some output in channels")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "welcome")))
+
+ (ert-info ("Server buffer shows connection failed")
+ (with-current-buffer erc-server-buffer
+ (funcall expect 10 "Connection failed! Re-establishing")))
+
+ (should (equal erc-autojoin-channels-alist '((FooNet "#chan"))))
+
+ (funcall test)
+
+ (with-current-buffer "FooNet" (erc-cmd-JOIN "#spam"))
+
+ (erc-d-t-wait-for 5 "Channel #spam shown when autojoined"
+ (eq (window-buffer) (get-buffer "#spam")))
+
+ (ert-info ("Wait for auto reconnect")
+ (with-current-buffer erc-server-buffer
+ (funcall expect 10 "still in debug mode")))
+
+ (ert-info ("Wait for activity to recommence in channels")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (funcall expect 10 "forest of Arden"))
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
+ (funcall expect 10 "her elves come here anon")))))
+
+(ert-deftest erc-scenarios-base-reconnect-options--default ()
+ :tags '(:expensive-test)
+ (should (eq erc-join-buffer 'buffer))
+ (should-not erc-reconnect-display)
+
+ ;; FooNet (the server buffer) is not switched to because it's
+ ;; already current (but not shown) when `erc-open' is called. See
+ ;; related conditional guard towards the end of that function.
+
+ (erc-scenarios-common--base-reconnect-options
+ (lambda ()
+ (pop-to-buffer-same-window "*Messages*")
+
+ (erc-d-t-ensure-for 1 "Server buffer not shown"
+ (not (eq (window-buffer) (get-buffer "FooNet"))))
+
+ (erc-d-t-wait-for 5 "Channel #chan shown when autojoined"
+ (eq (window-buffer) (get-buffer "#chan"))))))
+
+(ert-deftest erc-scenarios-base-reconnect-options--bury ()
+ :tags '(:expensive-test)
+ (should (eq erc-join-buffer 'buffer))
+ (should-not erc-reconnect-display)
+
+ (let ((erc-reconnect-display 'bury))
+ (erc-scenarios-common--base-reconnect-options
+
+ (lambda ()
+ (pop-to-buffer-same-window "*Messages*")
+
+ (erc-d-t-ensure-for 1 "Server buffer not shown"
+ (not (eq (window-buffer) (get-buffer "FooNet"))))
+
+ (erc-d-t-ensure-for 3 "Channel #chan not shown"
+ (not (eq (window-buffer) (get-buffer "#chan"))))
+
+ (eq (window-buffer) (messages-buffer))))))
+
+;; Upon reconnecting, playback for channel and target buffers is
+;; routed correctly. Autojoin is irrelevant here, but for the
+;; skeptical, see `erc-scenarios-common--join-network-id', which
+;; overlaps with this and includes spurious JOINs ignored by the
+;; server.
+
+(ert-deftest erc-scenarios-base-association-reconnect-playback ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/reconplay")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Setup")
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Channel buffer #chan playback received")
+ (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan"))
+ (funcall expect 10 "But purgatory")))
+
+ (ert-info ("Ask for help from services or bouncer bot")
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-MSG "*status help")))
+
+ (ert-info ("Help received")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "*status"))
+ (funcall expect 10 "Rehash")))
+
+ (ert-info ("#chan convo done")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "most egregious indignity"))))
+
+ ;; KLUDGE (see note above test)
+ (should erc-autojoin-channels-alist)
+ (setq erc-autojoin-channels-alist nil)
+
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-QUIT "")
+ (erc-d-t-wait-for 4 (not (erc-server-process-alive)))
+ (erc-cmd-RECONNECT))
+
+ (ert-info ("Channel buffer found and associated")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "Wilt thou rest damned")))
+
+ (ert-info ("Help buffer found and associated")
+ (with-current-buffer "*status"
+ (erc-scenarios-common-say "help")
+ (funcall expect 10 "Restart ZNC")))
+
+ (ert-info ("#chan convo done")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "here comes the lady")))))
+
+;;; erc-scenarios-base-reconnect.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-renick.el b/test/lisp/erc/erc-scenarios-base-renick.el
new file mode 100644
index 00000000000..bf27f61b3fc
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-renick.el
@@ -0,0 +1,305 @@
+;;; erc-scenarios-base-renick.el --- Re-nicking scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; The server changes your nick just after registration.
+
+(ert-deftest erc-scenarios-base-renick-self-auto ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'auto))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (erc-d-t-search-for 10 "Your new nickname is dummy"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (erc-d-t-search-for 10 "dummy")
+ (erc-d-t-search-for 10 "On Thursday")))))
+
+;; You change your nickname manually in a server buffer; a message is
+;; printed in channel buffers.
+
+(ert-deftest erc-scenarios-base-renick-self-manual ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'manual))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 3 (get-buffer "foonet"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (funcall expect 5 "tester")
+ (funcall expect 5 "On Thursday")
+ (erc-with-server-buffer (erc-cmd-NICK "dummy"))
+ (funcall expect 5 "Your new nickname is dummy")
+ (funcall expect 5 "<bob> dummy: Hi")
+ ;; Regression in which changing a nick would trigger #foo@foonet
+ (erc-d-t-ensure-for 0.4 (equal (buffer-name) "#foo"))))))
+
+;; You connect to the same network with two different nicks. You
+;; manually change the first nick at some point, and buffer names are
+;; updated correctly.
+
+(ert-deftest erc-scenarios-base-renick-self-qualified ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (dumb-server (erc-d-run "localhost" t 'qual-tester 'qual-chester))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ erc-serv-buf-a erc-serv-buf-b)
+
+ (ert-info ("Connect to foonet with nick tester")
+ (with-current-buffer
+ (setq erc-serv-buf-a (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (erc-d-t-wait-for 5 (eq erc-network 'foonet))))
+
+ (ert-info ("Connect to foonet with nick chester")
+ (with-current-buffer
+ (setq erc-serv-buf-b (erc :server "127.0.0.1"
+ :port port
+ :nick "chester"
+ :password "changeme"
+ :full-name "chester"))))
+
+ (erc-d-t-wait-for 3 "Dialed Buflist is Empty"
+ (not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer "foonet/tester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (with-current-buffer "foonet/chester"
+ (funcall expect 3 "debug mode")
+ (erc-cmd-JOIN "#chan"))
+
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester"))
+ (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester"))
+
+ (ert-info ("Greets other nick in same channel")
+ (with-current-buffer "#chan@foonet/tester"
+ (funcall expect 5 "<bob> chester, welcome!")
+ (erc-cmd-NICK "dummy")
+ (funcall expect 5 "Your new nickname is dummy")
+ (funcall expect 5 "find the forester")
+ (erc-d-t-wait-for 5 (string= (buffer-name) "#chan@foonet/dummy"))))
+
+ (ert-info ("Renick propagated throughout all buffers of process")
+ (should-not (get-buffer "#chan@foonet/tester"))
+ (should-not (get-buffer "foonet/tester"))
+ (should (get-buffer "foonet/dummy")))))
+
+;; When a channel user changes their nick, any query buffers for them
+;; are updated.
+
+(ert-deftest erc-scenarios-base-renick-queries-solo ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/queries")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 20)
+ (dumb-server (erc-d-run "localhost" t 'solo))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 1 (get-buffer "foonet"))
+
+ (ert-info ("Joined by bouncer to #foo, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (erc-d-t-search-for 1 "On Thursday")
+ (erc-scenarios-common-say "hi")))
+
+ (erc-d-t-wait-for 10 "Query buffer appears with message from pal"
+ (get-buffer "Lal"))
+
+ (ert-info ("Chat with pal, who changes name")
+ (with-current-buffer "Lal"
+ (erc-d-t-search-for 3 "hello")
+ (erc-scenarios-common-say "hi")
+ (erc-d-t-search-for 10 "is now known as Linguo")
+ (should-not (search-forward "is now known as Linguo" nil t))))
+
+ (erc-d-t-wait-for 1 (get-buffer "Linguo"))
+ (should-not (get-buffer "Lal"))
+
+ (with-current-buffer "Linguo" (erc-scenarios-common-say "howdy Linguo"))
+
+ (with-current-buffer "#foo"
+ (erc-d-t-search-for 10 "is now known as Linguo")
+ (should-not (search-forward "is now known as Linguo" nil t))
+ (erc-cmd-PART ""))
+
+ (with-current-buffer "Linguo"
+ (erc-d-t-search-for 10 "get along"))))
+
+;; You share a channel and a query buffer with a user on two different
+;; networks (through a proxy). The user changes their nick on both
+;; networks at the same time. Query buffers are updated accordingly.
+
+(ert-deftest erc-scenarios-base-renick-queries-bouncer ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/queries")
+ (erc-server-flood-penalty 0.1)
+ (erc-server-flood-margin 30)
+ (dumb-server (erc-d-run "localhost" t 'bouncer-foonet 'bouncer-barnet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-accidental-paste-threshold-seconds
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo
+ erc-server-buffer-bar)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 5 (get-buffer "foonet"))
+
+ (ert-info ("Connect to barnet")
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-bar
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 5 (get-buffer "barnet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+
+ (ert-info ("Joined by bouncer to #chan@foonet, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@foonet"))
+ (funcall expect 1 "rando")
+ (funcall expect 1 "simply misused")))
+
+ (ert-info ("Joined by bouncer to #chan@barnet, pal persent")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@barnet"))
+ (funcall expect 1 "rando")
+ (funcall expect 2 "come, sir, I am")))
+
+ (ert-info ("Query buffer exists for rando@foonet")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@foonet"))
+ (funcall expect 1 "guess not")
+ (erc-scenarios-common-say "I here")))
+
+ (ert-info ("Query buffer exists for rando@barnet")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@barnet"))
+ (funcall expect 2 "rentacop")
+ (erc-scenarios-common-say "Linda said you were gonna kill me.")))
+
+ (ert-info ("Sync convo for rando@foonet")
+ (with-current-buffer "rando@foonet"
+ (funcall expect 1 "u are dumb")
+ (erc-scenarios-common-say "not so")))
+
+ (ert-info ("Sync convo for rando@barnet")
+ (with-current-buffer "rando@barnet"
+ (funcall expect 3 "I never saw her before")
+ (erc-scenarios-common-say "You aren't with Wage?")))
+
+ (erc-d-t-wait-for 3 (get-buffer "frenemy@foonet"))
+ (erc-d-t-wait-for 3 (get-buffer "frenemy@barnet"))
+ (should-not (get-buffer "rando@foonet"))
+ (should-not (get-buffer "rando@barnet"))
+
+ (with-current-buffer "frenemy@foonet"
+ (funcall expect 1 "now known as")
+ (funcall expect 1 "doubly so"))
+
+ (with-current-buffer "frenemy@barnet"
+ (funcall expect 1 "now known as")
+ (funcall expect 1 "reality picture"))
+
+ (when noninteractive
+ (with-current-buffer "frenemy@barnet" (kill-buffer))
+ (erc-d-t-wait-for 2 (get-buffer "frenemy"))
+ (should-not (get-buffer "frenemy@foonet")))
+
+ (with-current-buffer "#chan@foonet"
+ (funcall expect 10 "is now known as frenemy")
+ (should-not (search-forward "now known as frenemy" nil t)) ; regression
+ (funcall expect 10 "words are razors"))
+
+ (with-current-buffer "#chan@barnet"
+ (funcall expect 10 "is now known as frenemy")
+ (should-not (search-forward "now known as frenemy" nil t))
+ (erc-d-t-search-for 25 "I have lost"))))
+
+;;; erc-scenarios-base-renick.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
new file mode 100644
index 00000000000..f134f3ffb69
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
@@ -0,0 +1,238 @@
+;;; erc-scenarios-base-reuse-buffers.el --- base-reuse-buffers scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(defun erc-scenarios-common--base-reuse-buffers-server-buffers (&optional more)
+ "Show that `erc-reuse-buffers' doesn't affect server buffers.
+Overlaps some with `clash-of-chans/uniquify'. Adapted from
+rebuffed/reuseless, described in Bug#48598: 28.0.50; buffer-naming
+collisions involving bouncers in ERC. Run EXTRA."
+ (erc-scenarios-common-with-cleanup
+ ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name)
+ (format "127.0.0.1:%d/127.0.0.1" port)))
+ (erc-d-t-search-for 12 "marked as being away")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name)
+ (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+ (erc-d-t-search-for 45 "marked as being away")))
+
+ (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1" port)))
+ (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+
+ (ert-info ("Server buffers are unique, no IP-based names")
+ (should (cdr (erc-scenarios-common-buflist "127.0.0.1"))))
+ (when more (funcall more port))))
+
+;; XXX maybe remove: already covered many times over by other scenarios
+(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--enabled ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers))
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/server"))
+ (erc-scenarios-common-with-cleanup
+ ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-search-for 12 "marked as being away")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-search-for 45 "marked as being away")))
+
+ (erc-d-t-wait-for 2 (get-buffer "foonet"))
+ (erc-d-t-wait-for 2 (get-buffer "barnet"))
+
+ (ert-info ("Server buffers are unique, no IP-based names")
+ (should-not (eq (get-buffer "foonet") (get-buffer "barnet")))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))))))
+
+;; FIXME no sense in running this twice (JOIN variant includes this)
+(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--disabled ()
+ :tags '(:expensive-test)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers)
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/server")
+ erc-reuse-buffers)
+ (erc-scenarios-common--base-reuse-buffers-server-buffers nil))))
+
+;; This also asserts that `erc-cmd-JOIN' is no longer susceptible to a
+;; regression introduced in 28.1 (ERC 5.4) that caused phantom target
+;; buffers of the form target/server to be created via
+;; `switch-to-buffer' ("phantom" because they would go unused"). This
+;; would happen (in place of a JOIN being sent out) when a previously
+;; used (parted) target buffer existed and `erc-reuse-buffers' was
+;; nil.
+;;
+;; Note: All the `erc-get-channel-user' calls have to do with the fact
+;; that `erc-default-target' relies on the ambiguously defined
+;; `erc-default-recipients' (meaning it's overloaded in the sense of
+;; being used both for retrieving a target name and checking if a
+;; channel has been PARTed). While not ideal, `erc-get-channel-user'
+;; can (also) be used to detect the latter.
+
+(defun erc-scenarios-common--base-reuse-buffers-channel-buffers (port)
+ "The option `erc-reuse-buffers' is still respected when nil.
+Adapted from scenario clash-of-chans/uniquify described in Bug#48598:
+28.0.50; buffer-naming collisions involving bouncers in ERC."
+ (let* ((expect (erc-d-t-make-expecter))
+ (server-buffer-foo
+ (get-buffer (format "127.0.0.1:%d/127.0.0.1" port)))
+ (server-buffer-bar
+ (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port)))
+ (chan-buffer-foo (get-buffer "#chan/127.0.0.1"))
+ (chan-buffer-bar (get-buffer "#chan/127.0.0.1<2>"))
+ (server-process-foo (with-current-buffer server-buffer-foo
+ erc-server-process))
+ (server-process-bar (with-current-buffer server-buffer-bar
+ erc-server-process)))
+
+ (ert-info ("Unique #chan buffers exist")
+ (let ((chan-bufs (erc-scenarios-common-buflist "#chan"))
+ (known (list chan-buffer-bar chan-buffer-foo)))
+ (should (memq (pop chan-bufs) known))
+ (should (memq (pop chan-bufs) known))
+ (should-not chan-bufs)))
+
+ (ert-info ("#chan@foonet is exclusive and not contaminated")
+ (with-current-buffer chan-buffer-foo
+ (funcall expect 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (funcall expect 1 "strength to climb")
+ (should (eq erc-server-process server-process-foo))))
+
+ (ert-info ("#chan@barnet is exclusive and not contaminated")
+ (with-current-buffer chan-buffer-bar
+ (funcall expect 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (funcall expect 1 "the loudest noise")
+ (should (eq erc-server-process server-process-bar))))
+
+ (ert-info ("Part #chan@foonet")
+ (with-current-buffer chan-buffer-foo
+ (erc-d-t-search-for 1 "shake my sword")
+ (erc-cmd-PART "#chan")
+ (funcall expect 3 "You have left channel #chan")
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Part #chan@barnet")
+ (with-current-buffer chan-buffer-bar
+ (funcall expect 10 "Arm it in rags")
+ (should (erc-get-channel-user (erc-current-nick)))
+ (erc-cmd-PART "#chan")
+ (funcall expect 3 "You have left channel #chan")
+ (should-not (erc-get-channel-user (erc-current-nick)))
+ (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 3 "New unique target buffer for #chan@foonet created"
+ (get-buffer "#chan/127.0.0.1<3>"))
+
+ (ert-info ("Activity continues in new, <n>-suffixed #chan@foonet buffer")
+ (with-current-buffer chan-buffer-foo
+ (should-not (erc-get-channel-user (erc-current-nick))))
+ (with-current-buffer "#chan/127.0.0.1<3>"
+ (should (erc-get-channel-user (erc-current-nick)))
+ (funcall expect 2 "You have joined channel #chan")
+ (funcall expect 2 "#chan was created on")
+ (funcall expect 2 "<alice>")
+ (should (eq erc-server-process server-process-foo))
+ (erc-d-t-absent-for 0.2 "<joe>")))
+
+ (sit-for 3)
+ (erc-d-t-wait-for 5 "New unique target buffer for #chan@barnet created"
+ (get-buffer "#chan/127.0.0.1<4>"))
+
+ (ert-info ("Activity continues in new, <n>-suffixed #chan@barnet buffer")
+ (with-current-buffer chan-buffer-bar
+ (should-not (erc-get-channel-user (erc-current-nick))))
+ (with-current-buffer "#chan/127.0.0.1<4>"
+ (funcall expect 2 "You have joined channel #chan")
+ (funcall expect 1 "Users on #chan: @mike joe tester")
+ (funcall expect 2 "<mike>")
+ (should (eq erc-server-process server-process-bar))
+ (erc-d-t-absent-for 0.2 "<bob>")))
+
+ (ert-info ("Two new chans created for a total of four")
+ (let* ((bufs (erc-scenarios-common-buflist "#chan"))
+ (names (sort (mapcar #'buffer-name bufs) #'string<)))
+ (should
+ (equal names (mapcar (lambda (f) (concat "#chan/127.0.0.1" f))
+ '("" "<2>" "<3>" "<4>"))))))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan/127.0.0.1<3>"
+ (funcall expect 10 "most lively"))
+ (with-current-buffer "#chan/127.0.0.1<4>"
+ (funcall expect 10 "soul black")))
+
+ ;; TODO ensure the exact <N>'s aren't reassigned during killing as
+ ;; they are when the option is on.
+ (ert-info ("Buffers are exempt from shortening")
+ (kill-buffer "#chan/127.0.0.1<4>")
+ (kill-buffer "#chan/127.0.0.1<3>")
+ (kill-buffer chan-buffer-bar)
+ (should-not (get-buffer "#chan"))
+ (should chan-buffer-foo))))
+
+(ert-deftest erc-scenarios-base-reuse-buffers-channel-buffers--disabled ()
+ :tags '(:expensive-test :unstable)
+ (with-suppressed-warnings ((obsolete erc-reuse-buffers))
+ (should erc-reuse-buffers)
+ (let ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+ (erc-server-flood-penalty 0.1)
+ erc-reuse-buffers)
+ (erc-scenarios-common--base-reuse-buffers-server-buffers
+ #'erc-scenarios-common--base-reuse-buffers-channel-buffers))))
+
+;;; erc-scenarios-base-reuse-buffers.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-unstable.el b/test/lisp/erc/erc-scenarios-base-unstable.el
new file mode 100644
index 00000000000..2313a15842c
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-unstable.el
@@ -0,0 +1,134 @@
+;;; erc-scenarios-base-unstable.el --- base unstable scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+;; Not unstable, but stashed here for now
+
+(ert-deftest erc-scenarios-aux-unix-socket ()
+ :tags '(:expensive-test)
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/renick/self")
+ (erc-server-flood-penalty 0.1)
+ (sock (expand-file-name "erc-d.sock" temporary-file-directory))
+ (erc-scenarios-common-extra-teardown (lambda () (delete-file sock)))
+ (erc-server-connect-function
+ (lambda (n b _ p &rest r)
+ (apply #'make-network-process
+ `(:name ,n :buffer ,b :service ,p :family local ,@r))))
+ (dumb-server (erc-d-run nil sock 'auto))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "fake"
+ :port sock
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "fake:%s" sock)))))
+
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet"))
+ (erc-d-t-search-for 10 "Your new nickname is dummy"))
+
+ (ert-info ("Joined by bouncer to #foo, own nick present")
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo"))
+ (erc-d-t-search-for 10 "dummy")
+ (erc-d-t-search-for 10 "On Thursday")))))
+
+;; See `erc-networks--rename-server-buffer'. A perceived loss in
+;; network connectivity turns out to be a false alarm, but the bouncer
+;; has already accepted the second connection
+
+(defun erc-scenarios--base-aborted-reconnect ()
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (dumb-server (erc-d-run "localhost" t 'aborted 'aborted-dupe))
+ (port (process-contact dumb-server :service))
+ erc-autojoin-channels-alist
+ erc-server-buffer-foo)
+
+ (ert-info ("Connect to foonet")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (erc-d-t-wait-for 10 (get-buffer "FooNet"))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ (with-current-buffer erc-server-buffer-foo
+ (erc-cmd-JOIN "#chan")))
+
+ (ert-info ("Channel buffer #chan alive and well")
+ (with-current-buffer (erc-d-t-wait-for 4 (get-buffer "#chan"))
+ (erc-d-t-search-for 10 "welcome")))
+
+ (ert-info ("Connect to foonet again")
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester"))
+ (let ((inhibit-message noninteractive))
+ (with-current-buffer erc-server-buffer-foo
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))
+ (erc-d-t-search-for 10 "FooNet still connected"))))
+
+ (ert-info ("Server buffer is unique and temp name is absent")
+ (should (equal (list (get-buffer "FooNet"))
+ (erc-scenarios-common-buflist "FooNet")))
+ (should (equal (list (get-buffer (format "127.0.0.1:%d" port)))
+ (erc-scenarios-common-buflist "127.0.0.1"))))
+
+ (ert-info ("Channel buffer #chan still going")
+ (with-current-buffer "#chan"
+ (erc-d-t-search-for 10 "and be prosperous")))))
+
+(ert-deftest erc-scenarios-base-aborted-reconnect ()
+ :tags '(:unstable)
+ (let ((tries 3)
+ (timeout 1)
+ failed)
+ (while (condition-case _err
+ (progn
+ (erc-scenarios--base-aborted-reconnect)
+ nil)
+ (ert-test-failed
+ (message "Test %S failed; %s attempt(s) remaining."
+ (ert-test-name (ert-running-test))
+ tries)
+ (sleep-for (cl-incf timeout))
+ (not (setq failed (zerop (cl-decf tries)))))))
+ (should-not failed)))
+
+;;; erc-scenarios-base-unstable.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
new file mode 100644
index 00000000000..5a5b363f31d
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
@@ -0,0 +1,43 @@
+;;; erc-scenarios-upstream-recon-soju.el --- Upstream soju -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; These concern the loss and recovery of a proxy's IRC-side connection.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-upstream-recon--soju ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--upstream-reconnect
+ (lambda ()
+ (with-current-buffer "foonet"
+ (erc-d-t-search-for 1 "disconnected from foonet")
+ (erc-d-t-search-for 1 "connected from foonet"))
+ (with-current-buffer "barnet"
+ (erc-d-t-search-for 1 "disconnected from barnet")
+ (erc-d-t-search-for 1 "connected from barnet")))
+ 'soju-foonet
+ 'soju-barnet))
+
+;;; erc-scenarios-upstream-recon-soju.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
new file mode 100644
index 00000000000..6e9a2172459
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
@@ -0,0 +1,43 @@
+;;; erc-scenarios-upstream-recon-znc.el --- Upstream znc -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;; Commentary:
+;;
+;; These concern the loss and recovery of a proxy's IRC-side connection.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-upstream-recon--znc ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common--upstream-reconnect
+ (lambda ()
+ (with-current-buffer "*status@foonet"
+ (erc-d-t-search-for 1 "Disconnected from IRC")
+ (erc-d-t-search-for 1 "Connected!"))
+ (with-current-buffer "*status@barnet"
+ (erc-d-t-search-for 1 "Disconnected from IRC")
+ (erc-d-t-search-for 1 "Connected!")))
+ 'znc-foonet
+ 'znc-barnet))
+
+;;; erc-scenarios-upstream-recon-znc.el ends here
diff --git a/test/lisp/erc/erc-scenarios-internal.el b/test/lisp/erc/erc-scenarios-internal.el
new file mode 100644
index 00000000000..e4e1edb97e3
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-internal.el
@@ -0,0 +1,27 @@
+;;; erc-scenarios-internal.el --- Proxy file for erc-d tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (expand-file-name "erc-d" (ert-resource-directory))
+ load-path)))
+ (load "erc-d-tests" nil 'silent)))
+
+;;; erc-scenarios-internal.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-auth-source.el b/test/lisp/erc/erc-scenarios-join-auth-source.el
new file mode 100644
index 00000000000..94336db07c5
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-auth-source.el
@@ -0,0 +1,67 @@
+;;; erc-scenarios-join-auth-source.el --- join-auth-source scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; TODO add another test with autojoin and channel keys
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-auth-source--network ()
+ :tags '(:expensive-test)
+ (should erc-auth-source-join-function)
+ (erc-scenarios-common-with-cleanup
+ ((entries
+ '("machine 127.0.0.1 port %d login \"#foo\" password spam"
+ "machine irc.foonet.org port %d login tester password fake"
+ "machine irc.foonet.org login \"#spam\" password secret"
+ "machine foonet port %d login dummy password fake"
+ "machine 127.0.0.1 port %d login dummy password changeme"))
+ (erc-scenarios-common-dialog "join/auth-source")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ (ents (mapcar (lambda (fmt) (format fmt port)) entries))
+ (netrc-file (make-temp-file "auth-source-test" nil nil
+ (string-join ents "\n")))
+ (auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (expect (erc-d-t-make-expecter))
+ (erc-scenarios-common-extra-teardown (lambda ()
+ (delete-file netrc-file))))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "dummy"
+ :full-name "dummy")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 8 (eq erc-network 'foonet))
+ (funcall expect 10 "user modes")
+ (erc-scenarios-common-say "/JOIN #spam")))
+
+ (ert-info ("Join #spam")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
+ (funcall expect 10 "#spam was created on")))))
+
+;;; erc-scenarios-join-auth-source.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
new file mode 100644
index 00000000000..e2e437321d9
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
@@ -0,0 +1,50 @@
+;;; erc-scenarios-join-netid-newcmd-id.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd-id ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "oofnet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id 'oofnet))))
+ (erc-scenarios-common--join-network-id connect 'oofnet nil)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd-ids ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "oofnet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id 'oofnet))))
+ (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet)))
+
+;;; erc-scenarios-join-netid-newcmd-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
new file mode 100644
index 00000000000..1a541a46b3f
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
@@ -0,0 +1,37 @@
+;;; erc-scenarios-join-netid-newcmd.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--newcmd ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (erc :server "127.0.0.1"
+ :port (with-current-buffer "foonet"
+ (process-contact erc-server-process :service))
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"))))
+ (erc-scenarios-common--join-network-id connect nil nil)))
+
+;;; erc-scenarios-join-netid-newcmd.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
new file mode 100644
index 00000000000..92bdd643de8
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
@@ -0,0 +1,46 @@
+;;; erc-scenarios-join-netid-recon-id.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--recon-id ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "oofnet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect 'oofnet nil)))
+
+(ert-deftest erc-scenarios-join-netid--recon-ids ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "oofnet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet)))
+
+;;; erc-scenarios-join-netid-recon-id.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon.el b/test/lisp/erc/erc-scenarios-join-netid-recon.el
new file mode 100644
index 00000000000..cbdba07e256
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon.el
@@ -0,0 +1,36 @@
+;;; erc-scenarios-join-netid-recon.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-join-netid--recon ()
+ :tags '(:expensive-test)
+ (let ((connect (lambda ()
+ (with-current-buffer "foonet"
+ (erc-cmd-RECONNECT)
+ (should (eq (current-buffer)
+ (process-buffer erc-server-process)))
+ (current-buffer)))))
+ (erc-scenarios-common--join-network-id connect nil nil)))
+
+;;; erc-scenarios-join-netid-recon.el ends here
diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el
new file mode 100644
index 00000000000..9d6d5bc1d6a
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-misc.el
@@ -0,0 +1,141 @@
+;;; erc-scenarios-misc.el --- Misc scenarios for ERC -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join))
+
+(ert-deftest erc-scenarios-base-flood ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/flood")
+ (dumb-server (erc-d-run "localhost" t 'soju))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.5) ; this ratio MUST match
+ (erc-server-flood-margin 1.5) ; the default of 3:10
+ (expect (erc-d-t-make-expecter))
+ erc-autojoin-channels-alist)
+
+ (ert-info ("Connect to bouncer")
+ (with-current-buffer
+ (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (funcall expect 5 "Soju")))
+
+ (ert-info ("#chan@foonet exists")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan/foonet"))
+ (erc-d-t-search-for 2 "<bob/foonet>")
+ (erc-d-t-absent-for 0.1 "<joe")
+ (funcall expect 3 "was created on")))
+
+ (ert-info ("#chan@barnet exists")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan/barnet"))
+ (erc-d-t-search-for 2 "<joe/barnet>")
+ (erc-d-t-absent-for 0.1 "<bob")
+ (funcall expect 3 "was created on")
+ (funcall expect 5 "To get good guard")))
+
+ (ert-info ("Message not held in queue limbo")
+ (with-current-buffer "#chan/foonet"
+ ;; Without 'no-penalty param in `erc-server-send', should fail
+ ;; after ~10 secs with:
+ ;;
+ ;; (erc-d-timeout "Timed out awaiting request: (:name ~privmsg
+ ;; :pattern \\`PRIVMSG #chan/foonet :alice: hi :timeout 2
+ ;; :dialog soju)")
+ ;;
+ ;; Try reversing commit and spying on queue interactively
+ (erc-cmd-MSG "#chan/foonet alice: hi")
+ (funcall expect 5 "tester: Good, very good")))
+
+ (ert-info ("All output sent")
+ (with-current-buffer "#chan/foonet"
+ (funcall expect 8 "Some man or other"))
+ (with-current-buffer "#chan/barnet"
+ (funcall expect 10 "That's he that was Othello")))))
+
+;; Corner case demoing fallback behavior for an absent 004 RPL but a
+;; present 422 or 375. If this is unlikely enough, remove or guard
+;; with `ert-skip' plus some condition so it only runs when explicitly
+;; named via ERT specifier
+
+(ert-deftest erc-scenarios-networks-announced-missing ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "networks/announced-missing")
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (let ((err (should-error (sleep-for 1))))
+ (should (string-match-p "Failed to determine" (cadr err))))
+ (funcall expect 1 "Failed to determine")
+ (funcall expect 1 "Failed to determine")
+ (should-not erc-network)
+ (should (string= erc-server-announced-name "irc.foonet.org"))))))
+
+;; Targets that are host/server masks like $*, $$*, and #* are routed
+;; to the server buffer: https://github.com/ircdocs/wooooms/issues/5
+
+(ert-deftest erc-scenarios-base-mask-target-routing ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/mask-target-routing")
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (erc-d-t-wait-for 10 (get-buffer "foonet"))
+
+ (ert-info ("Channel buffer #foo playback received")
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo"))
+ (funcall expect 10 "Excellent workman")))
+
+ (ert-info ("Global notices routed to server buffer")
+ (with-current-buffer "foonet"
+ (funcall expect 10 "going down soon")
+ (funcall expect 10 "this is a warning")
+ (funcall expect 10 "second warning")
+ (funcall expect 10 "final warning")))
+
+ (should-not (get-buffer "$*"))))
+
+;;; erc-scenarios-misc.el ends here
diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el
new file mode 100644
index 00000000000..cb1aa6ff324
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-services-misc.el
@@ -0,0 +1,86 @@
+;;; erc-scenarios-services-misc.el --- Services-misc scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(ert-deftest erc-scenarios-services-password ()
+ :tags '(:expensive-test)
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/password")
+ (erc-server-flood-penalty 0.1)
+ (erc-modules (cons 'services erc-modules))
+ (erc-nickserv-passwords '((Libera.Chat (("joe" . "bar")
+ ("tester" . "changeme")))))
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (erc-d-t-wait-for 5 (eq erc-network 'Libera.Chat))
+ (funcall expect 5 "This nickname is registered.")
+ (funcall expect 2 "You are now identified")
+ (funcall expect 1 "Last login from")
+ (erc-cmd-QUIT "")))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+(ert-deftest erc-scenarios-services-prompt ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "services/password")
+ (erc-server-flood-penalty 0.1)
+ (inhibit-interaction nil)
+ (erc-modules (cons 'services erc-modules))
+ (expect (erc-d-t-make-expecter))
+ (dumb-server (erc-d-run "localhost" t 'libera))
+ (port (process-contact dumb-server :service)))
+
+ (ert-info ("Connect without password")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+ (ert-simulate-keys "changeme\r"
+ (erc-d-t-wait-for 10 (eq erc-network 'Libera.Chat))
+ (funcall expect 3 "This nickname is registered.")
+ (funcall expect 3 "You are now identified")
+ (funcall expect 3 "Last login from"))
+ (erc-cmd-QUIT "")))
+
+ (erc-services-mode -1)
+
+ (should-not (memq 'services erc-modules))))
+
+;;; erc-scenarios-services-misc.el ends here
diff --git a/test/lisp/erc/erc-services-tests.el b/test/lisp/erc/erc-services-tests.el
new file mode 100644
index 00000000000..8e2b8d29273
--- /dev/null
+++ b/test/lisp/erc/erc-services-tests.el
@@ -0,0 +1,574 @@
+;;; erc-services-tests.el --- Tests for erc-services. -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; TODO: move the auth-source tests somewhere else. They've been
+;; stashed here for pragmatic reasons.
+
+;;; Code:
+
+(require 'ert-x)
+(require 'erc-services)
+(require 'erc-compat)
+(require 'secrets)
+
+;;;; Core auth-source
+
+(ert-deftest erc--auth-source-determine-params-merge ()
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'fake)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create 'GNU.chat)))
+
+ (should (equal (erc--auth-source-determine-params-merge)
+ '(:host ("GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("6697" "irc")
+ :require (:secret))))
+
+ (should (equal (erc--auth-source-determine-params-merge :host "fake")
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("6697" "irc")
+ :require (:secret))))
+
+ (should (equal (erc--auth-source-determine-params-merge
+ :host '("fake") :require :host)
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :require (:host :secret)
+ :port ("6697" "irc"))))
+
+ (should (equal (erc--auth-source-determine-params-merge
+ :host '("fake" "GNU.chat") :port "1234" :x "x")
+ '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org")
+ :port ("1234" "6697" "irc")
+ :x ("x")
+ :require (:secret))))))
+
+;; Some of the following may be related to bug#23438.
+
+(defun erc-services-tests--auth-source-standard (search)
+
+ (ert-info ("Session wins")
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'fake)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create 'GNU.chat)))
+ (should (string= (funcall search :user "#chan") "foo"))))
+
+ (ert-info ("Network wins")
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "foo"))))
+
+ (ert-info ("Announced wins")
+ (let ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ erc-network
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "baz")))))
+
+(defun erc-services-tests--auth-source-announced (search)
+ (let* ((erc--isupport-params (make-hash-table))
+ (erc-server-parameters '(("CHANTYPES" . "&#")))
+ (erc--target (erc--target-from-string "&chan")))
+
+ (ert-info ("Announced prioritized")
+
+ (ert-info ("Announced wins")
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "baz"))))
+
+ (ert-info ("Peer next")
+ (let* ((erc-server-announced-name "irc.gnu.org")
+ (erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "bar"))))
+
+ (ert-info ("Network used as fallback")
+ (let* ((erc-session-port 6697)
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil)))
+ (should (string= (funcall search :user "#chan") "foo")))))))
+
+(defun erc-services-tests--auth-source-overrides (search)
+ (let* ((erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-network 'GNU.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil))
+ (erc-session-port 6667))
+
+ (ert-info ("Specificity and overrides")
+
+ (ert-info ("More specific port")
+ (let ((erc-session-port 6697))
+ (should (string= (funcall search :user "#chan") "spam"))))
+
+ (ert-info ("More specific user (network loses)")
+ (should (string= (funcall search :user '("#fsf")) "42")))
+
+ (ert-info ("Actual override")
+ (should (string= (funcall search :port "6667") "sesame")))
+
+ (ert-info ("Overrides don't interfere with post-processing")
+ (should (string= (funcall search :host "MyHost") "123"))))))
+
+;; auth-source netrc backend
+
+(defvar erc-services-tests--auth-source-entries
+ '("machine irc.gnu.org port irc user \"#chan\" password bar"
+ "machine my.gnu.org port irc user \"#chan\" password baz"
+ "machine GNU.chat port irc user \"#chan\" password foo"))
+
+;; FIXME explain what this is for
+(defun erc-services-tests--auth-source-shuffle (&rest extra)
+ (string-join `(,@(sort (append erc-services-tests--auth-source-entries extra)
+ (lambda (&rest _) (zerop (random 2))))
+ "")
+ "\n"))
+
+(ert-deftest erc--auth-source-search--netrc-standard ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--standard"
+ :text (erc-services-tests--auth-source-shuffle)
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--netrc-announced ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--announced"
+ :text (erc-services-tests--auth-source-shuffle)
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--netrc-overrides ()
+ (ert-with-temp-file netrc-file
+ :prefix "erc--auth-source-search--overrides"
+ :text (erc-services-tests--auth-source-shuffle
+ "machine GNU.chat port 6697 user \"#chan\" password spam"
+ "machine my.gnu.org port irc user \"#fsf\" password 42"
+ "machine irc.gnu.org port 6667 password sesame"
+ "machine MyHost port irc password 456"
+ "machine MyHost port 6667 password 123")
+
+ (let ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source plstore backend
+
+(defun erc-services-test--call-with-plstore (&rest args)
+ (advice-add 'epg-decrypt-string :override
+ (lambda (&rest r) (prin1-to-string (cadr r)))
+ '((name . erc--auth-source-plstore)))
+ (advice-add 'epg-find-configuration :override
+ (lambda (&rest _) "" '((program . "/bin/true")))
+ '((name . erc--auth-source-plstore)))
+ (unwind-protect
+ (apply #'erc-auth-source-search args)
+ (advice-remove 'epg-decrypt-string 'erc--auth-source-plstore)
+ (advice-remove 'epg-find-configuration 'erc--auth-source-plstore)))
+
+(defvar erc-services-tests--auth-source-plstore-standard-entries
+ '(("ba950d38118a76d71f9f0591bb373d6cb366a512"
+ :secret-secret t
+ :host "irc.gnu.org"
+ :user "#chan"
+ :port "irc")
+ ("7f17ca445d11158065e911a6d0f4cbf52ca250e3"
+ :secret-secret t
+ :host "my.gnu.org"
+ :user "#chan"
+ :port "irc")
+ ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377"
+ :secret-secret t
+ :host "GNU.chat"
+ :user "#chan"
+ :port "irc")))
+
+(defvar erc-services-tests--auth-source-plstore-standard-secrets
+ '(("ba950d38118a76d71f9f0591bb373d6cb366a512" :secret "bar")
+ ("7f17ca445d11158065e911a6d0f4cbf52ca250e3" :secret "baz")
+ ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377" :secret "foo")))
+
+(ert-deftest erc--auth-source-search--plstore-standard ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-entries)
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-secrets)
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard
+ #'erc-services-test--call-with-plstore))))
+
+(ert-deftest erc--auth-source-search--plstore-announced ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-entries)
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ erc-services-tests--auth-source-plstore-standard-secrets)
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced
+ #'erc-services-test--call-with-plstore))))
+
+(ert-deftest erc--auth-source-search--plstore-overrides ()
+ (ert-with-temp-file plstore-file
+ :suffix ".plist"
+ :text (concat
+ ";;; public entries -*- mode: plstore -*- \n"
+ (prin1-to-string
+ `(,@erc-services-tests--auth-source-plstore-standard-entries
+ ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a"
+ :secret-secret t :host "GNU.chat" :user "#chan" :port "6697")
+ ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc"
+ :secret-secret t :host "my.gnu.org" :user "#fsf" :port "irc")
+ ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d"
+ :secret-secret t :host "irc.gnu.org" :port "6667")
+ ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537"
+ :secret-secret t :host "MyHost" :port "irc")
+ ("61a6bd552059494f479ff720e8de33e22574650a"
+ :secret-secret t :host "MyHost" :port "6667")))
+ "\n;;; secret entries\n"
+ (prin1-to-string
+ `(,@erc-services-tests--auth-source-plstore-standard-secrets
+ ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a" :secret "spam")
+ ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc" :secret "42")
+ ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d" :secret "sesame")
+ ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537" :secret "456")
+ ("61a6bd552059494f479ff720e8de33e22574650a" :secret "123")))
+ "\n")
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides
+ #'erc-services-test--call-with-plstore))))
+
+;; auth-source JSON backend
+
+(defvar erc-services-tests--auth-source-json-standard-entries
+ [(:host "irc.gnu.org" :port "irc" :user "#chan" :secret "bar")
+ (:host "my.gnu.org" :port "irc" :user "#chan" :secret "baz")
+ (:host "GNU.chat" :port "irc" :user "#chan" :secret "foo")])
+
+(ert-deftest erc--auth-source-search--json-standard ()
+ (ert-with-temp-file json-store
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ erc-services-tests--auth-source-json-standard-entries))
+ (let ((auth-sources (list json-store))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--json-announced ()
+ (ert-with-temp-file plstore-file
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ erc-services-tests--auth-source-json-standard-entries))
+
+ (let ((auth-sources (list plstore-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--json-overrides ()
+ (ert-with-temp-file json-file
+ :suffix ".json"
+ :text (let ((json-object-type 'plist))
+ (json-encode
+ (vconcat
+ erc-services-tests--auth-source-json-standard-entries
+ [(:secret "spam" :host "GNU.chat" :user "#chan" :port "6697")
+ (:secret "42" :host "my.gnu.org" :user "#fsf" :port "irc")
+ (:secret "sesame" :host "irc.gnu.org" :port "6667")
+ (:secret "456" :host "MyHost" :port "irc")
+ (:secret "123" :host "MyHost" :port "6667")])))
+
+ (let ((auth-sources (list json-file))
+ (auth-source-do-cache nil))
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source-secrets backend
+
+(defvar erc-services-tests--auth-source-secrets-standard-entries
+ '(("#chan@irc.gnu.org:irc" ; label
+ (:host . "irc.gnu.org")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#chan@my.gnu.org:irc"
+ (:host . "my.gnu.org")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#chan@GNU.chat:irc"
+ (:host . "GNU.chat")
+ (:user . "#chan")
+ (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))))
+
+(defvar erc-services-tests--auth-source-secrets-standard-secrets
+ '(("#chan@irc.gnu.org:irc" . "bar")
+ ("#chan@my.gnu.org:irc" . "baz")
+ ("#chan@GNU.chat:irc" . "foo")))
+
+(ert-deftest erc--auth-source-search--secrets-standard ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries erc-services-tests--auth-source-secrets-standard-entries)
+ (secrets erc-services-tests--auth-source-secrets-standard-secrets))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest r)
+ (should (equal col "Test"))
+ (should (plist-get r :user))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--secrets-announced ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries erc-services-tests--auth-source-secrets-standard-entries)
+ (secrets erc-services-tests--auth-source-secrets-standard-secrets))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest r)
+ (should (equal col "Test"))
+ (should (plist-get r :user))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--secrets-overrides ()
+ (skip-unless (bound-and-true-p secrets-enabled))
+ (let ((auth-sources '("secrets:Test"))
+ (auth-source-do-cache nil)
+ (entries `(,@erc-services-tests--auth-source-secrets-standard-entries
+ ("#chan@GNU.chat:6697"
+ (:host . "GNU.chat") (:user . "#chan") (:port . "6697")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("#fsf@my.gnu.org:irc"
+ (:host . "my.gnu.org") (:user . "#fsf") (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("irc.gnu.org:6667"
+ (:host . "irc.gnu.org") (:port . "6667")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("MyHost:irc"
+ (:host . "MyHost") (:port . "irc")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))
+ ("MyHost:6667"
+ (:host . "MyHost") (:port . "6667")
+ (:xdg:schema . "org.freedesktop.Secret.Generic"))))
+ (secrets `(,@erc-services-tests--auth-source-secrets-standard-secrets
+ ("#chan@GNU.chat:6697" . "spam")
+ ("#fsf@my.gnu.org:irc" . "42" )
+ ("irc.gnu.org:6667" . "sesame")
+ ("MyHost:irc" . "456")
+ ("MyHost:6667" . "123"))))
+
+ (cl-letf (((symbol-function 'secrets-search-items)
+ (lambda (col &rest _)
+ (should (equal col "Test"))
+ (map-keys entries)))
+ ((symbol-function 'secrets-get-secret)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label secrets)))
+ ((symbol-function 'secrets-get-attributes)
+ (lambda (col label)
+ (should (equal col "Test"))
+ (assoc-default label entries))))
+
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;; auth-source-pass backend
+
+(require 'auth-source-pass)
+
+;; `auth-source-pass--find-match-unambiguous' returns something like:
+;;
+;; (list :host "irc.gnu.org"
+;; :port "6697"
+;; :user "rms"
+;; :secret
+;; #[0 "\301\302\300\"\207"
+;; [((secret . "freedom")) auth-source-pass--get-attr secret] 3])
+;;
+;; This function gives ^ (faked here to avoid gpg and file IO). See
+;; `auth-source-pass--with-store' in ../auth-source-pass-tests.el
+(defun erc-services-tests--asp-parse-entry (store entry)
+ (when-let ((found (cl-find entry store :key #'car :test #'string=)))
+ (list (assoc 'secret (cdr found)))))
+
+(defvar erc-join-tests--auth-source-pass-entries
+ '(("irc.gnu.org:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "bar"))
+ ("my.gnu.org:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "baz"))
+ ("GNU.chat:irc/#chan"
+ ("port" . "irc") ("user" . "#chan") (secret . "foo"))))
+
+(ert-deftest erc--auth-source-search--pass-standard ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store erc-join-tests--auth-source-pass-entries)
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-standard #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--pass-announced ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store erc-join-tests--auth-source-pass-entries)
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-announced #'erc-auth-source-search))))
+
+(ert-deftest erc--auth-source-search--pass-overrides ()
+ (ert-skip "Pass backend not yet supported")
+ (let ((store
+ `(,@erc-join-tests--auth-source-pass-entries
+ ("GNU.chat:6697/#chan"
+ ("port" . "6697") ("user" . "#chan") (secret . "spam"))
+ ("my.gnu.org:irc/#fsf"
+ ("port" . "irc") ("user" . "#fsf") (secret . "42"))
+ ("irc.gnu.org:6667"
+ ("port" . "6667") (secret . "sesame"))
+ ("MyHost:irc"
+ ("port" . "irc") (secret . "456"))
+ ("MyHost:6667"
+ ("port" . "6667") (secret . "123"))))
+ (auth-sources '(password-store))
+ (auth-source-do-cache nil))
+
+ (cl-letf (((symbol-function 'auth-source-pass-parse-entry)
+ (apply-partially #'erc-services-tests--asp-parse-entry store))
+ ((symbol-function 'auth-source-pass-entries)
+ (lambda () (mapcar #'car store))))
+
+ (erc-services-tests--auth-source-overrides #'erc-auth-source-search))))
+
+;;;; The services module
+
+(ert-deftest erc-nickserv-get-password ()
+ (should erc-prompt-for-nickserv-password)
+ (ert-with-temp-file netrc-file
+ :prefix "erc-nickserv-get-password"
+ :text (mapconcat 'identity
+ '("machine GNU/chat port 6697 user bob password spam"
+ "machine FSF.chat port 6697 user bob password sesame"
+ "machine MyHost port irc password 123")
+ "\n")
+
+ (let* ((auth-sources (list netrc-file))
+ (auth-source-do-cache nil)
+ (erc-nickserv-passwords '((FSF.chat (("alice" . "foo")
+ ("joe" . "bar")))))
+ (erc-use-auth-source-for-nickserv-password t)
+ (erc-session-server "irc.gnu.org")
+ (erc-server-announced-name "my.gnu.org")
+ (erc-network 'FSF.chat)
+ (erc-server-current-nick "tester")
+ (erc-networks--id (erc-networks--id-create nil))
+ (erc-session-port 6697))
+
+ (ert-info ("Lookup custom option")
+ (should (string= (erc-nickserv-get-password "alice") "foo")))
+
+ (ert-info ("Auth source")
+ (ert-info ("Network")
+ (should (string= (erc-nickserv-get-password "bob") "sesame")))
+
+ (ert-info ("Network ID")
+ (let ((erc-networks--id (erc-networks--id-create 'GNU/chat)))
+ (should (string= (erc-nickserv-get-password "bob") "spam")))))
+
+ (ert-info ("Read input")
+ (should (string=
+ (ert-simulate-keys "baz\r" (erc-nickserv-get-password "mike"))
+ "baz")))
+
+ (ert-info ("Failed")
+ (should-not (ert-simulate-keys "\r"
+ (erc-nickserv-get-password "fake")))))))
+
+
+;;; erc-services-tests.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 5603e764547..4971d0e194f 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -21,7 +21,7 @@
;;; Code:
-(require 'ert)
+(require 'ert-x)
(require 'erc)
(require 'erc-ring)
(require 'erc-networks)
@@ -48,6 +48,27 @@
(cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1d")))
(should (equal (erc--read-time-period "foo: ") 86400))))
+(ert-deftest erc--meta--backend-dependencies ()
+ (with-temp-buffer
+ (insert-file-contents-literally
+ (concat (file-name-sans-extension (symbol-file 'erc)) ".el"))
+ (let ((beg (search-forward ";; Defined in erc-backend"))
+ (end (search-forward "\n\n"))
+ vars)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (with-syntax-table lisp-data-mode-syntax-table
+ (condition-case _
+ (while (push (cadr (read (current-buffer))) vars))
+ (end-of-file)))))
+ (should (= (point) end))
+ (dolist (var vars)
+ (setq var (concat "\\_<" (symbol-name var) "\\_>"))
+ (ert-info (var)
+ (should (save-excursion (search-forward-regexp var nil t))))))))
+
(ert-deftest erc-with-all-buffers-of-server ()
(let (proc-exnet
proc-onet
@@ -114,6 +135,207 @@
(should (get-buffer "#spam"))
(kill-buffer "#spam")))
+(defun erc-tests--send-prep ()
+ ;; Caller should probably shadow `erc-insert-modify-hook' or
+ ;; populate user tables for erc-button.
+ (erc-mode)
+ (insert "\n\n")
+ (setq erc-input-marker (make-marker)
+ erc-insert-marker (make-marker))
+ (set-marker erc-insert-marker (point-max))
+ (erc-display-prompt)
+ (should (= (point) erc-input-marker)))
+
+(defun erc-tests--set-fake-server-process (&rest args)
+ (setq erc-server-process
+ (apply #'start-process (car args) (current-buffer) args))
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+(ert-deftest erc-hide-prompt ()
+ (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (with-current-buffer (get-buffer-create "ServNet")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (set-process-sentinel erc-server-process #'ignore)
+ (setq erc-network 'ServNet)
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "ServNet"))
+ erc-default-recipients '("#chan")))
+
+ (with-current-buffer (get-buffer-create "bob")
+ (erc-tests--send-prep)
+ (goto-char erc-insert-marker)
+ (should (looking-at-p (regexp-quote erc-prompt)))
+ (setq erc-server-process (buffer-local-value 'erc-server-process
+ (get-buffer "ServNet"))
+ erc-default-recipients '("bob")))
+
+ (ert-info ("Value: t (default)")
+ (should (eq erc-hide-prompt t))
+ (with-current-buffer "ServNet"
+ (should (= (point) erc-insert-marker))
+ (erc--hide-prompt erc-server-process)
+ (should (string= ">" (get-text-property (point) 'display))))
+
+ (with-current-buffer "#chan"
+ (goto-char erc-insert-marker)
+ (should (string= ">" (get-text-property (point) 'display)))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (goto-char erc-input-marker)
+ (ert-simulate-command '(self-insert-command 1 ?/))
+ (goto-char erc-insert-marker)
+ (should-not (get-text-property (point) 'display))
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook)))
+
+ (with-current-buffer "bob"
+ (goto-char erc-insert-marker)
+ (should (string= ">" (get-text-property (point) 'display)))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (goto-char erc-input-marker)
+ (ert-simulate-command '(self-insert-command 1 ?/))
+ (goto-char erc-insert-marker)
+ (should-not (get-text-property (point) 'display))
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook)))
+
+ (with-current-buffer "ServNet"
+ (should (get-text-property erc-insert-marker 'display))
+ (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
+ (erc--unhide-prompt)
+ (should-not (memq #'erc--unhide-prompt-on-self-insert
+ pre-command-hook))
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: server")
+ (setq erc-hide-prompt '(server))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should (string= ">" (get-text-property erc-insert-marker 'display))))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "ServNet"
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: channel")
+ (setq erc-hide-prompt '(channel))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: query")
+ (setq erc-hide-prompt '(query))
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (erc--unhide-prompt)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (ert-info ("Value: nil")
+ (setq erc-hide-prompt nil)
+ (with-current-buffer "ServNet"
+ (erc--hide-prompt erc-server-process)
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "bob"
+ (should-not (get-text-property erc-insert-marker 'display)))
+
+ (with-current-buffer "#chan"
+ (should-not (get-text-property erc-insert-marker 'display))
+ (erc--unhide-prompt) ; won't blow up when prompt already showing
+ (should-not (get-text-property erc-insert-marker 'display))))
+
+ (when noninteractive
+ (kill-buffer "#chan")
+ (kill-buffer "bob")
+ (kill-buffer "ServNet"))))
+
+(ert-deftest erc--switch-to-buffer ()
+ (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el
+
+ (let ((proc (start-process "aNet" (current-buffer) "true"))
+ (erc-modified-channels-alist `(("fake") (,(messages-buffer))))
+ (inhibit-message noninteractive)
+ (completion-fail-discreetly t) ; otherwise ^G^G printed to .log file
+ ;;
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+
+ (with-current-buffer (get-buffer-create "server")
+ (erc-mode)
+ (set-process-buffer (setq erc-server-process proc) (current-buffer))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ (with-current-buffer (get-buffer-create "#chan")
+ (erc-mode)
+ (setq erc-server-process proc))
+ (with-current-buffer (get-buffer-create "#foo")
+ (erc-mode)
+ (setq erc-server-process proc))
+
+ (ert-info ("Channel #chan selectable from server buffer")
+ (ert-simulate-keys (list ?# ?c ?h ?a ?n ?\C-m)
+ (should (string= "#chan" (erc--switch-to-buffer))))))
+
+ (ert-info ("Channel #foo selectable from non-ERC buffer")
+ (ert-simulate-keys (list ?# ?f ?o ?o ?\C-m)
+ (should (string= "#foo" (erc--switch-to-buffer)))))
+
+ (ert-info ("Default selectable")
+ (ert-simulate-keys (list ?\C-m)
+ (should (string= "*Messages*" (erc--switch-to-buffer)))))
+
+ (ert-info ("Extant but non-ERC buffer not selectable")
+ (get-buffer-create "#fake") ; not ours
+ (ert-simulate-keys (kbd "#fake C-m C-a C-k C-m")
+ ;; Initial query fails ~~~~~~^; clearing input accepts default
+ (should (string= "*Messages*" (erc--switch-to-buffer)))))
+
+ (with-current-buffer (get-buffer-create "other")
+ (erc-mode)
+ (setq erc-server-process (start-process "bNet" (current-buffer) "true"))
+ (set-process-query-on-exit-flag erc-server-process nil))
+
+ (ert-info ("Foreign ERC buffer not selectable")
+ (ert-simulate-keys (kbd "other C-m C-a C-k C-m")
+ (with-current-buffer "server"
+ (should (string= "*Messages*" (erc--switch-to-buffer))))))
+
+ (ert-info ("Any ERC-buffer selectable from non-ERC buffer")
+ (should-not (eq major-mode 'erc-mode))
+ (ert-simulate-keys (list ?o ?t ?h ?e ?r ?\C-m)
+ (should (string= "other" (erc--switch-to-buffer)))))
+
+ (dolist (b '("server" "other" "#chan" "#foo" "#fake"))
+ (kill-buffer b))))
+
(ert-deftest erc-lurker-maybe-trim ()
(let (erc-lurker-trim-nicks
(erc-lurker-ignore-chars "_`"))
@@ -127,6 +349,147 @@
(setq erc-lurker-ignore-chars "_-`") ; set of chars, not character alts
(should (string= "nick" (erc-lurker-maybe-trim "nick-_`")))))
+(ert-deftest erc--parse-isupport-value ()
+ (should (equal (erc--parse-isupport-value "a,b") '("a" "b")))
+ (should (equal (erc--parse-isupport-value "a,b,c") '("a" "b" "c")))
+
+ (should (equal (erc--parse-isupport-value "abc") '("abc")))
+ (should (equal (erc--parse-isupport-value "\\x20foo") '(" foo")))
+ (should (equal (erc--parse-isupport-value "foo\\x20") '("foo ")))
+ (should (equal (erc--parse-isupport-value "a\\x20b\\x20c") '("a b c")))
+ (should (equal (erc--parse-isupport-value "a\\x20b\\x20c\\x20") '("a b c ")))
+ (should (equal (erc--parse-isupport-value "\\x20a\\x20b\\x20c") '(" a b c")))
+ (should (equal (erc--parse-isupport-value "a\\x20\\x20c") '("a c")))
+ (should (equal (erc--parse-isupport-value "\\x20\\x20\\x20") '(" ")))
+ (should (equal (erc--parse-isupport-value "\\x5Co/") '("\\o/")))
+ (should (equal (erc--parse-isupport-value "\\x7F,\\x19") '("\\x7F" "\\x19")))
+ (should (equal (erc--parse-isupport-value "a\\x2Cb,c") '("a,b" "c"))))
+
+(ert-deftest erc--get-isupport-entry ()
+ (let ((erc--isupport-params (make-hash-table))
+ (erc-server-parameters '(("FOO" . "1") ("BAR") ("BAZ" . "A,B,C")))
+ (items (lambda ()
+ (cl-loop for k being the hash-keys of erc--isupport-params
+ using (hash-values v) collect (cons k v)))))
+
+ (should-not (erc--get-isupport-entry 'FAKE))
+ (should-not (erc--get-isupport-entry 'FAKE 'single))
+ (should (zerop (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'BAR) '(BAR)))
+ (should-not (erc--get-isupport-entry 'BAR 'single))
+ (should (= 1 (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'BAZ) '(BAZ "A" "B" "C")))
+ (should (equal (erc--get-isupport-entry 'BAZ 'single) "A"))
+ (should (= 2 (hash-table-count erc--isupport-params)))
+
+ (should (equal (erc--get-isupport-entry 'FOO 'single) "1"))
+ (should (equal (erc--get-isupport-entry 'FOO) '(FOO "1")))
+
+ (should (equal (funcall items)
+ '((BAR . --empty--) (BAZ "A" "B" "C") (FOO "1"))))))
+
+(ert-deftest erc-server-005 ()
+ (let* ((hooked 0)
+ (verify #'ignore)
+ (hook (lambda (_ _) (funcall verify) (cl-incf hooked)))
+ (erc-server-005-functions (list #'erc-server-005 hook #'ignore))
+ erc-server-parameters
+ erc--isupport-params
+ erc-timer-hook
+ calls
+ args
+ parsed)
+
+ (cl-letf (((symbol-function 'erc-display-message)
+ (lambda (_ _ _ line) (push line calls))))
+
+ (ert-info ("Baseline")
+ (setq args '("tester" "BOT=B" "EXCEPTS" "PREFIX=(ov)@+" "are supp...")
+ parsed (make-erc-response :command-args args :command "005"))
+
+ (setq verify
+ (lambda ()
+ (should (equal erc-server-parameters
+ '(("PREFIX" . "(ov)@+") ("EXCEPTS")
+ ("BOT" . "B"))))
+ (should (zerop (hash-table-count erc--isupport-params)))
+ (should (equal "(ov)@+" (erc--get-isupport-entry 'PREFIX t)))
+ (should (equal '(EXCEPTS) (erc--get-isupport-entry 'EXCEPTS)))
+ (should (equal "B" (erc--get-isupport-entry 'BOT t)))
+ (should (string= (pop calls)
+ "BOT=B EXCEPTS PREFIX=(ov)@+ are supp..."))
+ (should (equal args (erc-response.command-args parsed)))))
+
+ (erc-call-hooks nil parsed))
+
+ (ert-info ("Negated, updated")
+ (setq args '("tester" "-EXCEPTS" "-FAKE" "PREFIX=(ohv)@%+" "are su...")
+ parsed (make-erc-response :command-args args :command "005"))
+
+ (setq verify
+ (lambda ()
+ (should (equal erc-server-parameters
+ '(("PREFIX" . "(ohv)@%+") ("BOT" . "B"))))
+ (should (string= (pop calls)
+ "-EXCEPTS -FAKE PREFIX=(ohv)@%+ are su..."))
+ (should (equal "(ohv)@%+" (erc--get-isupport-entry 'PREFIX t)))
+ (should (equal "B" (erc--get-isupport-entry 'BOT t)))
+ (should-not (erc--get-isupport-entry 'EXCEPTS))
+ (should (equal args (erc-response.command-args parsed)))))
+
+ (erc-call-hooks nil parsed))
+ (should (= hooked 2)))))
+
+(ert-deftest erc-downcase ()
+ (let ((erc--isupport-params (make-hash-table)))
+
+ (puthash 'PREFIX '("(ov)@+") erc--isupport-params)
+ (puthash 'BOT '("B") erc--isupport-params)
+
+ (ert-info ("ascii")
+ (puthash 'CASEMAPPING '("ascii") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob[m]`"))
+ (should (equal (erc-downcase "Tilde~") "tilde~" ))
+ (should (equal (erc-downcase "\\O/") "\\o/" )))
+
+ (ert-info ("rfc1459")
+ (puthash 'CASEMAPPING '("rfc1459") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob{m}`" ))
+ (should (equal (erc-downcase "Tilde~") "tilde^" ))
+ (should (equal (erc-downcase "\\O/") "|o/" )))
+
+ (ert-info ("rfc1459-strict")
+ (puthash 'CASEMAPPING '("rfc1459-strict") erc--isupport-params)
+ (should (equal (erc-downcase "Bob[m]`") "bob{m}`"))
+ (should (equal (erc-downcase "Tilde~") "tilde~" ))
+ (should (equal (erc-downcase "\\O/") "|o/" )))))
+
+(ert-deftest erc--valid-local-channel-p ()
+ (ert-info ("Local channels not supported")
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("#") erc--isupport-params)
+ (should-not (erc--valid-local-channel-p "#chan"))
+ (should-not (erc--valid-local-channel-p "&local"))))
+ (ert-info ("Local channels supported")
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should-not (erc--valid-local-channel-p "#chan"))
+ (should (erc--valid-local-channel-p "&local")))))
+
+(ert-deftest erc--target-from-string ()
+ (should (equal (erc--target-from-string "#chan")
+ #s(erc--target-channel "#chan" \#chan)))
+
+ (should (equal (erc--target-from-string "Bob")
+ #s(erc--target "Bob" bob)))
+
+ (let ((erc--isupport-params (make-hash-table)))
+ (puthash 'CHANTYPES '("&#") erc--isupport-params)
+ (should (equal (erc--target-from-string "&Bitlbee")
+ #s(erc--target-channel-local "&Bitlbee" &bitlbee)))))
+
(ert-deftest erc-ring-previous-command-base-case ()
(ert-info ("Create ring when nonexistent and do nothing")
(let (erc-input-ring
@@ -140,14 +503,10 @@
(ert-deftest erc-ring-previous-command ()
(with-current-buffer (get-buffer-create "*#fake*")
(erc-mode)
- (insert "\n\n")
+ (erc-tests--send-prep)
+ (setq-local erc-last-input-time 0)
(should-not (local-variable-if-set-p 'erc-send-completed-hook))
(set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals)
- (setq erc-input-marker (make-marker)
- erc-insert-marker (make-marker))
- (set-marker erc-insert-marker (point-max))
- (erc-display-prompt)
- (should (= (point) erc-input-marker))
;; Just in case erc-ring-mode is already on
(setq-local erc-pre-send-functions nil)
(add-hook 'erc-pre-send-functions #'erc-add-to-input-ring)
@@ -207,8 +566,9 @@
(erc-log-irc-protocol ":irc.gnu.org 001 tester :Welcome")
(erc-log-irc-protocol ":irc.gnu.org 002 tester :Your host is irc.gnu.org")
(setq erc-network 'FooNet)
+ (setq erc-networks--id (erc-networks--id-create nil))
(erc-log-irc-protocol ":irc.gnu.org 422 tester :MOTD missing")
- (setq erc-network 'BarNet)
+ (setq erc-networks--id (erc-networks--id-create 'BarNet))
(erc-log-irc-protocol ":irc.gnu.org 221 tester +i")
(set-process-query-on-exit-flag erc-server-process nil)))
(with-current-buffer "*erc-protocol*"
@@ -228,6 +588,240 @@
(kill-buffer "*erc-protocol*")
(should-not erc-debug-irc-protocol)))
+(ert-deftest erc--input-line-delim-regexp ()
+ (let ((p erc--input-line-delim-regexp))
+ ;; none
+ (should (equal '("a" "b") (split-string "a\r\nb" p)))
+ (should (equal '("a" "b") (split-string "a\nb" p)))
+ (should (equal '("a" "b") (split-string "a\rb" p)))
+
+ ;; one
+ (should (equal '("") (split-string "" p)))
+ (should (equal '("a" "" "b") (split-string "a\r\rb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\rb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\nb" p)))
+ (should (equal '("a" "" "b") (split-string "a\r\r\nb" p)))
+ (should (equal '("a" "" "b") (split-string "a\n\r\nb" p)))
+ (should (equal '("a" "") (split-string "a\n" p)))
+ (should (equal '("a" "") (split-string "a\r" p)))
+ (should (equal '("a" "") (split-string "a\r\n" p)))
+ (should (equal '("" "b") (split-string "\nb" p)))
+ (should (equal '("" "b") (split-string "\rb" p)))
+ (should (equal '("" "b") (split-string "\r\nb" p)))
+
+ ;; two
+ (should (equal '("" "") (split-string "\r" p)))
+ (should (equal '("" "") (split-string "\n" p)))
+ (should (equal '("" "") (split-string "\r\n" p)))
+
+ ;; three
+ (should (equal '("" "" "") (split-string "\r\r" p)))
+ (should (equal '("" "" "") (split-string "\n\n" p)))
+ (should (equal '("" "" "") (split-string "\n\r" p)))))
+
+(ert-deftest erc--blank-in-multiline-input-p ()
+ (let ((check (lambda (s)
+ (erc--blank-in-multiline-input-p
+ (split-string s erc--input-line-delim-regexp)))))
+
+ (ert-info ("With `erc-send-whitespace-lines'")
+ (let ((erc-send-whitespace-lines t))
+ (should (funcall check ""))
+ (should-not (funcall check "\na"))
+ (should-not (funcall check "/msg a\n")) ; real /cmd
+ (should-not (funcall check "a\n\nb")) ; "" allowed
+ (should-not (funcall check "/msg a\n\nb")) ; non-/cmd
+ (should-not (funcall check " "))
+ (should-not (funcall check "\t"))
+ (should-not (funcall check "a\nb"))
+ (should-not (funcall check "a\n "))
+ (should-not (funcall check "a\n \t"))
+ (should-not (funcall check "a\n \f"))
+ (should-not (funcall check "a\n \nb"))
+ (should-not (funcall check "a\n \t\nb"))
+ (should-not (funcall check "a\n \f\nb"))))
+
+ (should (funcall check ""))
+ (should (funcall check " "))
+ (should (funcall check "\t"))
+ (should (funcall check "a\n\nb"))
+ (should (funcall check "a\n\nb"))
+ (should (funcall check "a\n "))
+ (should (funcall check "a\n \t"))
+ (should (funcall check "a\n \f"))
+ (should (funcall check "a\n \nb"))
+ (should (funcall check "a\n \t\nb"))
+
+ (should-not (funcall check "a\rb"))
+ (should-not (funcall check "a\nb"))
+ (should-not (funcall check "a\r\nb"))))
+
+(defun erc-tests--with-process-input-spy (test)
+ (with-current-buffer (get-buffer-create "FakeNet")
+ (let* ((erc-pre-send-functions
+ (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now
+ (inhibit-message noninteractive)
+ (erc-server-current-nick "tester")
+ (erc-last-input-time 0)
+ erc-accidental-paste-threshold-seconds
+ erc-send-modify-hook
+ ;;
+ calls)
+ (cl-letf (((symbol-function 'erc-process-input-line)
+ (lambda (&rest r) (push r calls)))
+ ((symbol-function 'erc-server-buffer)
+ (lambda () (current-buffer))))
+ (erc-tests--send-prep)
+ (funcall test (lambda () (pop calls)))))
+ (when noninteractive (kill-buffer))))
+
+(ert-deftest erc--check-prompt-input-functions ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+
+ (ert-info ("Errors when point not in prompt area") ; actually just dings
+ (insert "/msg #chan hi")
+ (forward-line -1)
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "Point is not in the input area" (cadr e))))
+ (goto-char (point-max))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
+
+ (ert-info ("Errors when no process running")
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "ERC: No process running" (cadr e))))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
+
+ (ert-info ("Errors when line contains empty newline")
+ (erc-bol)
+ (delete-region (point) (point-max))
+ (insert "one\n")
+ (let ((e (should-error (erc-send-current-line))))
+ (should (equal "Blank line - ignoring..." (cadr e))))
+ (goto-char (point-max))
+ (ert-info ("Input remains untouched")
+ (should (save-excursion (goto-char erc-input-marker)
+ (looking-at "one\n")))))
+
+ (should (= 0 erc-last-input-time))
+ (should-not (funcall next)))))
+
+;; These also indirectly tests `erc-send-input'
+
+(ert-deftest erc-send-current-line ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (should (= 0 erc-last-input-time))
+
+ (ert-info ("Simple command")
+ (insert "/msg #chan hi")
+ (erc-send-current-line)
+ (ert-info ("Prompt restored")
+ (forward-line 0)
+ (should (looking-at-p erc-prompt)))
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ ;; Commands are forced (no flood protection)
+ (should (equal (funcall next) '("/msg #chan hi\n" t nil))))
+
+ (ert-info ("Simple non-command")
+ (insert "hi")
+ (erc-send-current-line)
+ (should (eq (point) (point-max)))
+ (should (save-excursion (forward-line -1)
+ (search-forward "<tester> hi")))
+ ;; Non-ommands are forced only when `erc-flood-protect' is nil
+ (should (equal (funcall next) '("hi\n" nil t))))
+
+ (should (consp erc-last-input-time)))))
+
+(ert-deftest erc-send-whitespace-lines ()
+ (erc-tests--with-process-input-spy
+ (lambda (next)
+ (erc-tests--set-fake-server-process "sleep" "1")
+ (setq-local erc-send-whitespace-lines t)
+
+ (ert-info ("Multiline hunk with blank line correctly split")
+ (insert "one\n\ntwo")
+ (erc-send-current-line)
+ (ert-info ("Prompt restored")
+ (forward-line 0)
+ (should (looking-at-p erc-prompt)))
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("two\n" nil t)))
+ (should (equal (funcall next) '("\n" nil t)))
+ (should (equal (funcall next) '("one\n" nil t))))
+
+ (ert-info ("Multiline hunk with trailing newline filtered")
+ (insert "hi\n")
+ (erc-send-current-line)
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("hi\n" nil t)))
+ (should-not (funcall next)))
+
+ (ert-info ("Multiline hunk with trailing carriage filtered")
+ (insert "hi\r")
+ (erc-send-current-line)
+ (ert-info ("Input cleared")
+ (erc-bol)
+ (should (eq (point) (point-max))))
+ (should (equal (funcall next) '("hi\n" nil t)))
+ (should-not (funcall next)))
+
+ (ert-info ("Multiline command with trailing blank filtered")
+ (pcase-dolist (`(,p . ,q)
+ '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n")
+ ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n")
+ ("a b\nc\n\n" "c\n" "a b\n")
+ ("/a b\nc\n\n" "c\n" "/a b\n")
+ ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n")))
+ (insert p)
+ (erc-send-current-line)
+ (erc-bol)
+ (should (eq (point) (point-max)))
+ (while q
+ (should (equal (funcall next) (list (pop q) nil t))))
+ (should-not (funcall next))))
+
+ (ert-info ("Multiline hunk with trailing whitespace not filtered")
+ (insert "there\n ")
+ (erc-send-current-line)
+ (should (equal (funcall next) '(" \n" nil t)))
+ (should (equal (funcall next) '("there\n" nil t)))
+ (should-not (funcall next))))))
+
+(ert-deftest erc--check-prompt-input-for-excess-lines ()
+ (ert-info ("Without `erc-inhibit-multiline-input'")
+ (should-not erc-inhibit-multiline-input)
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))
+
+ (ert-info ("With `erc-inhibit-multiline-input' as t (2)")
+ (let ((erc-inhibit-multiline-input t))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "")))
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
+
+ (ert-info ("With `erc-inhibit-multiline-input' as 3")
+ (let ((erc-inhibit-multiline-input 3))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" "")))
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c")))))
+
+ (ert-info ("With `erc-ask-about-multiline-input'")
+ (let ((erc-inhibit-multiline-input t)
+ (erc-ask-about-multiline-input t))
+ (ert-simulate-keys '(?n ?\r ?y ?\r)
+ (should (erc--check-prompt-input-for-excess-lines "" '("a" "b")))
+ (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
+ (should-not erc-ask-about-multiline-input)))
;; The point of this test is to ensure output is handled identically
;; regardless of whether a command handler is summoned.
@@ -283,19 +877,19 @@
(ert-info ("Implicit cmd via `erc-send-input-line-function'")
(ert-info ("Baseline")
- (erc-process-input-line "hi")
+ (erc-process-input-line "hi\n")
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi\r\n" . utf-8))))
(ert-info ("Spaces preserved")
- (erc-process-input-line "hi you")
+ (erc-process-input-line "hi you\n")
(should (equal (pop erc-server-flood-queue)
'("PRIVMSG #chan :hi you\r\n" . utf-8))))
- (ert-info ("Empty line transmitted without injected-space kludge")
- (erc-process-input-line "")
+ (ert-info ("Empty line transmitted with injected-space kludge")
+ (erc-process-input-line "\n")
(should (equal (pop erc-server-flood-queue)
- '("PRIVMSG #chan :\r\n" . utf-8))))
+ '("PRIVMSG #chan : \r\n" . utf-8))))
(should-not calls))))))
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
new file mode 100644
index 00000000000..4b6ccfff38a
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
@@ -0,0 +1,44 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 28 Apr 2021 06:59:59 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 6 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1619593200")
+ (0.25 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defence, by mercy, 'tis most just.")
+ (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.")
+ (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.")
+ (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu."))
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
new file mode 100644
index 00000000000..58df79e19fa
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
@@ -0,0 +1,48 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 28 Apr 2021 07:00:00 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:37] alice: Here, at your lordship's service.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:42] bob: By my troth, and in good earnest, and so God mend me, and by all pretty oaths that are not dangerous, if you break one jot of your promise or come one minute behind your hour, I will think you the most pathetical break-promise, and the most hollow lover, and the most unworthy of her you call Rosalind, that may be chosen out of the gross band of the unfaithful. Therefore, beware my censure, and keep your promise.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 6 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1619593200")
+ (0.9 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")
+ (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.")
+ (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.")
+ (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you."))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/again.eld b/test/lisp/erc/resources/base/assoc/bumped/again.eld
new file mode 100644
index 00000000000..ab3c7b06214
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/again.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 433 * tester :Nickname is reserved by a different account")
+ (0.0 ":irc.foonet.org FAIL NICK NICKNAME_RESERVED tester :Nickname is reserved by a different account"))
+
+((nick 3 "NICK tester`")
+ (0.1 ":irc.foonet.org 001 tester` :Welcome to the foonet IRC Network tester`")
+ (0.0 ":irc.foonet.org 002 tester` :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester` :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester` irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester` AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.1 ":irc.foonet.org 005 tester` MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.1 ":irc.foonet.org 005 tester` draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester` :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester` 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester` 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester` 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester` :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester` 3 3 :Current local users 3, max 3")
+ (0.2 ":irc.foonet.org 266 tester` 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester` :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester` +i")
+ (0.0 ":irc.foonet.org 221 tester` +i")
+ (0.0 ":irc.foonet.org NOTICE tester` :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 42.6 "PRIVMSG NickServ :IDENTIFY tester changeme")
+ (0.01 ":tester`!~u@rpaau95je67ci.irc NICK tester")
+ (0.0 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/foisted.eld b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
new file mode 100644
index 00000000000..5c36e58d9d3
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.foonet.org 221 tester +i")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 17.21 "PRIVMSG bob :hi")
+ (0.02 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :hola")
+ (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :how r u?"))
+
+((quit 18.19 "QUIT :" quit)
+ (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit))
+((drop 1 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
new file mode 100644
index 00000000000..33e4168ac46
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
@@ -0,0 +1,31 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.1 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
+ (0.0 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 dummy :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 dummy irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.1 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.1 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 dummy :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 dummy 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 dummy 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 dummy 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 dummy :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 dummy 3 3 :Current local users 3, max 3")
+ (0.2 ":irc.foonet.org 266 dummy 3 3 :Current global users 3, max 3")
+ ;; Could arrive anytime around this point
+ (0.0 ":tester!~u@rpaau95je67ci.irc NICK :dummy")
+ (0.0 ":irc.foonet.org 422 dummy :MOTD File is missing")
+ ;; Playback
+ (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG dummy :back?")
+ )
+
+((mode-user 1.2 "MODE dummy +i")
+ (0.0 ":irc.foonet.org 221 dummy +i")
+ (0.0 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((renick 42.6 "NICK tester")
+ (0.01 ":dummy!~u@rpaau95je67ci.irc NICK tester")
+ (0.0 ":NickServ!NickServ@localhost NOTICE dummy :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/renicked.eld b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld
new file mode 100644
index 00000000000..4e96fd73045
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld
@@ -0,0 +1,30 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0.0 ":irc.foonet.org 221 tester +i")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((privmsg 17.21 "PRIVMSG NickServ :REGISTER changeme")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :Account created")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester"))
+
+((quit 18.19 "QUIT :" quit)
+ (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit))
+((drop 1 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
new file mode 100644
index 00000000000..c62a22a11c7
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Tue, 04 May 2021 05:06:19 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ (0 ":irc.barnet.org 221 tester +i")
+ (0 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@jnu48g2wrycbw.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620104779")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Whipp'd first, sir, and hang'd after.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: We have yet many among us can gripe as hard as Cassibelan; I do not say I am one, but I have a hand. Why tribute ? why should we pay tribute ? If C sar can hide the sun from us with a blanket, or put the moon in his pocket, we will pay him tribute for light; else, sir, no more tribute, pray you now.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Double and treble admonition, and still forfeit in the same kind ? This would make mercy swear, and play the tyrant.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: And secretly to greet the empress' friends.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: You have not been inquired after: I have sat here all day.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: That same Berowne I'll torture ere I go.")
+ (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: For mine own part,no offence to the general, nor any man of quality,I hope to be saved.")
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: Mehercle! if their sons be ingenuous, they shall want no instruction; if their daughters be capable, I will put it to them. But, vir sapit qui pauca loquitur. A soul feminine saluteth us."))
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
new file mode 100644
index 00000000000..f30b7deca11
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/assoc/reconplay/again.eld b/test/lisp/erc/resources/base/assoc/reconplay/again.eld
new file mode 100644
index 00000000000..4210c07e41a
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/reconplay/again.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 4.0 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ ;; No mode answer
+ (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:52] bob: Thou pout'st upon thy fortune and thy love.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:56] alice: With these mortals on the ground.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete."))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623816901")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My name, my good lord, is Parolles.")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Wilt thou rest damned ? God help thee, shallow man! God make incision in thee! thou art raw."))
+
+((privmsg 3.0 "PRIVMSG *status :help")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Version\17: Print which version of ZNC this is")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Shutdown [message]\17: Shut down ZNC completely")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Restart [message]\17: Restart ZNC")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: In that word's death; no words can that woe sound.")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Look, sir, here comes the lady towards my cell."))
diff --git a/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
new file mode 100644
index 00000000000..6f50ecca4ef
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 5 "MODE tester +i")
+ ;; No mode answer
+ (0.0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:50] bob: To Laced mon did my land extend.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:55] alice: This is but a custom in your tongue; you bear a graver purpose, I hope.")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:16] bob: To imitate them; faults that are rich are fair.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:18] alice: Our Romeo hath not been in bed to-night.")
+ (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:21] bob: But, in defence, by mercy, 'tis most just.")
+ (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:25] alice: Younger than she are happy mothers made.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 3 "MODE #chan")
+ (1.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623816901")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: At thy good heart's oppression.")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: But purgatory, torture, hell itself."))
+
+((privmsg 3 "PRIVMSG *status :help")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2AddPort <[+]port> <ipv4|ipv6|all> <web|irc|all> [bindhost [uriprefix]]\17: Add another port for ZNC to listen on")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2DelPort <port> <ipv4|ipv6|all> [bindhost]\17: Remove a port from ZNC")
+ (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Rehash\17: Reload global settings, modules, and listeners from znc.conf")
+ (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: And at my suit, sweet, pardon what is past.")
+ (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My lord, you give me most egregious indignity."))
+
+((quit 2 "QUIT :\2ERC\2"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/chester.eld b/test/lisp/erc/resources/base/assoc/samenet/chester.eld
new file mode 100644
index 00000000000..f1aed2836c7
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/chester.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 12 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")
+ (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)
+ (0.5 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!"))
+
+((quit 20 "QUIT :" quit)
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester.eld b/test/lisp/erc/resources/base/assoc/samenet/tester.eld
new file mode 100644
index 00000000000..cd9cacbe5dc
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/tester.eld
@@ -0,0 +1,42 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((quit 4 "QUIT "))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester2.eld b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld
new file mode 100644
index 00000000000..67c3a94a262
--- /dev/null
+++ b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld
@@ -0,0 +1,39 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 4.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob chester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~useless-join 10 "JOIN #chan"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!"))
+
+((quit 4 "QUIT :" quit)
+ (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
+
+((linger 5 LINGER))
diff --git a/test/lisp/erc/resources/base/auth-source/foonet.eld b/test/lisp/erc/resources/base/auth-source/foonet.eld
new file mode 100644
index 00000000000..1fe772c7e23
--- /dev/null
+++ b/test/lisp/erc/resources/base/auth-source/foonet.eld
@@ -0,0 +1,23 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/auth-source/nopass.eld b/test/lisp/erc/resources/base/auth-source/nopass.eld
new file mode 100644
index 00000000000..3fdb4ecf7bc
--- /dev/null
+++ b/test/lisp/erc/resources/base/auth-source/nopass.eld
@@ -0,0 +1,22 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld
new file mode 100644
index 00000000000..b09692327c7
--- /dev/null
+++ b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 6 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 8 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/flood/soju.eld b/test/lisp/erc/resources/base/flood/soju.eld
new file mode 100644
index 00000000000..05266ca9411
--- /dev/null
+++ b/test/lisp/erc/resources/base/flood/soju.eld
@@ -0,0 +1,87 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.13 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.0 ":soju.im 002 tester :Your host is soju.im")
+ (0.0 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.0 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii NETWORK=Soju :are supported")
+ (0.0 ":soju.im 422 tester :No MOTD"))
+
+((mode 1 "MODE tester +i")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan/foonet")
+ (0.25 ":soju.im 331 tester #chan/foonet :No topic is set")
+ (0.0 ":soju.im 353 tester = #chan/foonet :@bob/foonet alice/foonet tester")
+ (0.01 ":soju.im 366 tester #chan/foonet :End of /NAMES list")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan/barnet")
+ (0.04 ":soju.im 331 tester #chan/barnet :No topic is set")
+ (0.0 ":soju.im 353 tester = #chan/barnet :tester @mike/barnet joe/barnet")
+ (0.01 ":soju.im 366 tester #chan/barnet :End of /NAMES list")
+ (0.01 ":bob/foonet PRIVMSG #chan/foonet :alice: Then this breaking of his has been but a try for his friends.")
+ (0.16 ":alice/foonet PRIVMSG #chan/foonet :bob: By my troth, I take my young lord to be a very melancholy man.")
+ (0.91 ":bob/foonet PRIVMSG #chan/foonet :alice: No, truly, for the truest poetry is the most feigning; and lovers are given to poetry, and what they swear in poetry may be said as lovers they do feign.")
+ (0.01 ":alice/foonet PRIVMSG #chan/foonet :bob: Sir, his wife some two months since fled from his house: her pretence is a pilgrimage to Saint Jaques le Grand; which holy undertaking with most austere sanctimony she accomplished; and, there residing, the tenderness of her nature became as a prey to her grief; in fine, made a groan of her last breath, and now she sings in heaven.")
+ (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: Who ? not the duke ? yes, your beggar of fifty, and his use was to put a ducat in her clack-dish; the duke had crotchets in him. He would be drunk too; that let me inform you.")
+ (0.01 ":joe/barnet PRIVMSG #chan/barnet :mike: Prove it before these varlets here, thou honourable man, prove it.")
+ (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: That my report is just and full of truth.")
+ (0.0 ":joe/barnet PRIVMSG #chan/barnet :mike: It is impossible they bear it out.")
+ ;; Expected, since we blindly send +i
+ (0.0 ":soju.im 501 tester :Cannot change user mode in multi-upstream mode"))
+
+((~mode-foonet 5 "MODE #chan/foonet")
+ (0.0 ":soju.im 324 tester #chan/foonet +nt")
+ (0.16 ":soju.im 329 tester #chan/foonet 1647158643")
+ ;; Start frantic pinging
+ (0.0 "PING :soju-msgid-1"))
+
+((~mode-barnet 5 "MODE #chan/barnet")
+ (0.0 ":soju.im 324 tester #chan/barnet +nt")
+ (0.0 ":soju.im 329 tester #chan/barnet 1647158643"))
+
+((pong-1 5 "PONG :soju-msgid-1")
+ (0.0 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: The king's coming; I know by his trumpets. Sirrah, inquire further after me; I had talk of you last night: though you are a fool and a knave, you shall eat: go to, follow.")
+ (0.0 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Up: so. How is 't ? Feel you your legs ? You stand.")
+ (0.0 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Consider then we come but in despite.")
+ (0.1 "PING :soju-msgid-2"))
+
+((pong-2 2 "PONG :soju-msgid-2")
+ (0.1 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: All hail, Macbeth! that shalt be king hereafter.")
+ (0.1 "PING :soju-msgid-3"))
+
+((pong-3 2 "PONG :soju-msgid-3")
+ (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: And that at my bidding you could so stand up.")
+ (0.1 "PING :soju-msgid-4"))
+
+((pong-4 2 "PONG :soju-msgid-4")
+ (0.03 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Now he tells how she plucked him to my chamber. O! I see that nose of yours, but not the dog I shall throw it to.")
+ (0.1 "PING :soju-msgid-5"))
+
+((pong-5 2 "PONG :soju-msgid-5")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: For policy sits above conscience.")
+ (0.1 "PING :soju-msgid-6"))
+
+((pong-6 2 "PONG :soju-msgid-6")
+ (0.0 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: Take heed o' the foul fiend. Obey thy parents; keep thy word justly; swear not; commit not with man's sworn spouse; set not thy sweet heart on proud array. Tom's a-cold.")
+ (0.1 "PING :soju-msgid-7"))
+
+((pong-7 2 "PONG :soju-msgid-7")
+ (0.08 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: To suffer with him. Good love, call him back.")
+ (0.1 "PING :soju-msgid-8"))
+
+((pong-9 2 "PONG :soju-msgid-8")
+ (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: Be not obdurate, open thy deaf ears.")
+ (0.0 "PING :soju-msgid-9"))
+
+((pong-10 2 "PONG :soju-msgid-9")
+ (0.04 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: To get good guard and go along with me.")
+ (0.1 "PING :soju-msgid-10"))
+
+((~privmsg 2 "PRIVMSG #chan/foonet :alice: hi")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :tester: Good, very good; it is so then: good, very good. Let it be concealed awhile."))
+
+((pong-11 2 "PONG :soju-msgid-10")
+ (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Some man or other must present Wall; and let him have some plaster, or some loam, or some rough-cast about him, to signify wall; and let him hold his fingers thus, and through that cranny shall Pyramus and Thisby whisper.")
+ (0.0 "PING :soju-msgid-11"))
+
+((pong-12 5 "PONG :soju-msgid-11")
+ (0.1 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: That's he that was Othello; here I am."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/barnet.eld b/test/lisp/erc/resources/base/gapless-connect/barnet.eld
new file mode 100644
index 00000000000..4e658802ef6
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/barnet.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 10 "NICK tester"))
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.5.1-4860c5cad0179db1")
+ (0 ":irc.barnet.org 003 tester :This server was created Fri, 19 Mar 2021 10:23:19 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.5.1-4860c5cad0179db1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 1 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 0 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 1 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 1 1 :Current local users 1, max 1")
+ (0 ":irc.barnet.org 266 tester 1 1 :Current global users 1, max 1")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@8cgjyczyrjgby.irc JOIN #bar")
+ (0 ":irc.barnet.org 353 tester = #bar :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #bar :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #bar :Buffer Playback...")
+ (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!")
+ (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!")
+ (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:49] mike: Bid me farewell, and let me hear thee going.")
+ (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:54] joe: By heaven, thy love is black as ebony.")
+ (0 ":***!znc@znc.in PRIVMSG #bar :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[10:23:22] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 20 "MODE #bar")
+ (0 ":irc.barnet.org 324 tester #bar +nt")
+ (0 ":irc.barnet.org 329 tester #bar 1616149403")
+ (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: To ask of whence you are: report it.")
+ (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: Friar, thou knowest not the duke so well as I do: he's a better woodman than thou takest him for.")
+ (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: Like the sequel, I. Signior Costard, adieu.")
+ (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: This is his second fit; he had one yesterday."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
new file mode 100644
index 00000000000..4ac4a3e5968
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:44] alice: Why dost thou call them knaves ? thou know'st them not.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:05] bob: Now, by the faith of my love, I will: tell me where it is.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:09] alice: Give me the letter; I will look on it.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 8 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1619593200")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him."))
diff --git a/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld
new file mode 100644
index 00000000000..0c8dfd19d00
--- /dev/null
+++ b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :" token ":changeme"))
+
+((fake 1 "FAKE no op"))
diff --git a/test/lisp/erc/resources/base/mask-target-routing/foonet.eld b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld
new file mode 100644
index 00000000000..796d5566b65
--- /dev/null
+++ b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob rando tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 5 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ ;; Invalid msg
+ (0.1 ":rando!~u@em2i467d4ejul.irc PRIVMSG :")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $* :[Global notice] going down soon.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $$* :[Global notice] this is a warning.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG $* :[Global msg] second warning.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: And will you, being a man of your breeding.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE #* :[Global notice] final warning."))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld
new file mode 100644
index 00000000000..766035a524c
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+
+ (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.")
+ (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.")
+ (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((~join 3 "JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defence, by mercy, 'tis most just.")
+ (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.")
+ (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.")
+ (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
new file mode 100644
index 00000000000..2c3d297b9cf
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
new file mode 100644
index 00000000000..abfcc6ed481
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.")
+ (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld
new file mode 100644
index 00000000000..bf8712305a4
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :foonet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.")
+ (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.")
+ (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+
+ (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((~join 3 "JOIN #chan"))
+
+((mode 8 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
new file mode 100644
index 00000000000..e3c41e2133a
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honour again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him."))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
new file mode 100644
index 00000000000..c241c59bb88
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :foonet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 4.2 "MODE tester +i")
+ ;; No mode answer ^
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((join 1 "JOIN #chan")
+ (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805271")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honour again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.")
+ (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.")
+ (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him."))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld
new file mode 100644
index 00000000000..c666ee4fa0f
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :" token ":changeme"))
+
+((fake 1 "FAKE no op"))
diff --git a/test/lisp/erc/resources/base/netid/samenet/chester.eld b/test/lisp/erc/resources/base/netid/samenet/chester.eld
new file mode 100644
index 00000000000..8c2448733ce
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/samenet/chester.eld
@@ -0,0 +1,48 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 14 "JOIN #chan")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")
+ (0.1 ":tester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :chester: hi")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling."))
+
+((privmsg 4 "PRIVMSG #chan :hi tester")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen."))
+
+((quit 5 "QUIT :" quit)
+ (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)
+ (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/netid/samenet/tester.eld b/test/lisp/erc/resources/base/netid/samenet/tester.eld
new file mode 100644
index 00000000000..76312a7a14a
--- /dev/null
+++ b/test/lisp/erc/resources/base/netid/samenet/tester.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.")
+ (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.")
+ (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((privmsg 3 "PRIVMSG #chan :chester: hi")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling.")
+ (0.1 ":chester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :hi tester")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen."))
+
+((quit 4 "QUIT :" quit)
+ (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
new file mode 100644
index 00000000000..8e299ec44c0
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
@@ -0,0 +1,28 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :changeme"))
+((nick 1 "NICK tester"))
+
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (-0.02 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (-0.02 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (-0.02 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (-0.02 ":irc.foonet.org 254 tester 1 :channels formed")
+ (-0.02 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (-0.02 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (-0.02 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (-0.02 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((~mode-user 3.2 "MODE tester +i")
+ (-0.02 ":irc.foonet.org 221 tester +i")
+ (-0.02 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((~join 10 "JOIN #chan"))
+((eof 5 EOF))
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted.eld b/test/lisp/erc/resources/base/reconnect/aborted.eld
new file mode 100644
index 00000000000..5c32070d85f
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/aborted.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/base/reconnect/options-again.eld b/test/lisp/erc/resources/base/reconnect/options-again.eld
new file mode 100644
index 00000000000..f1fcc439cc3
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/options-again.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode."))
+
+((~join-chan 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~join-spam 12 "JOIN #spam")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((~mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon."))
diff --git a/test/lisp/erc/resources/base/reconnect/options.eld b/test/lisp/erc/resources/base/reconnect/options.eld
new file mode 100644
index 00000000000..3b305d85594
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/options.eld
@@ -0,0 +1,35 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/reconnect/timer-last.eld b/test/lisp/erc/resources/base/reconnect/timer-last.eld
new file mode 100644
index 00000000000..23849bc1bad
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/timer-last.eld
@@ -0,0 +1,6 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.znc.in 464 tester :Invalid Password"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/base/reconnect/timer.eld b/test/lisp/erc/resources/base/reconnect/timer.eld
new file mode 100644
index 00000000000..95c6af8d880
--- /dev/null
+++ b/test/lisp/erc/resources/base/reconnect/timer.eld
@@ -0,0 +1,6 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.znc.in 464 tester :Invalid Password"))
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld
new file mode 100644
index 00000000000..fc6cdaafe91
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld
@@ -0,0 +1,54 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:23 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@286u8jcpis84e.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike rando tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:19] mike: Chi non te vede, non te pretia.")
+ (0 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:28] joe: The valiant heart's not whipt out of his trade.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:20] Why'd you pull that scene at the arcade?")
+ (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:32] I had to mess up this rentacop came after me with nunchucks.")
+ (0 ":irc.barnet.org NOTICE tester :[09:13:24] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1622538742")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: By favours several which they did bestow.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: You, Roderigo! come, sir, I am for you."))
+
+((privmsg-a 5 "PRIVMSG rando :Linda said you were gonna kill me.")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Play, music, then! Nay, you must do it soon.")
+ (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :Linda said? I never saw her before I came up here.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Of arts inhibited and out of warrant."))
+
+((privmsg-b 3 "PRIVMSG rando :You aren't with Wage?")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: But most of all, agreeing with the proclamation.")
+ (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :I think you screwed up, Case.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Good gentleman, go your gait, and let poor volk pass. An chud ha' bin zwaggered out of my life, 'twould not ha' bin zo long as 'tis by a vortnight. Nay, come not near th' old man; keep out, che vor ye, or ise try whether your costard or my ballow be the harder. Chill be plain with you.")
+ ;; Nick change
+ (0.1 ":rando!~u@95i756tt32ym8.irc NICK frenemy")
+ (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Till time beget some careful remedy.")
+ (0.1 ":frenemy!~u@95i756tt32ym8.irc PRIVMSG tester :I showed up and you just fit me right into your reality picture.")
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: For I have lost him on a dangerous sea."))
diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld
new file mode 100644
index 00000000000..162e8bf9655
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 5.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@u4mvbswyw8gbg.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob rando tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:28] alice: Great men should drink with harness on their throats.")
+ (0 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:31] bob: Your lips will feel them the sooner: shallow again. A more sounder instance; come.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:51] u thur?")
+ (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:58] guess not")
+ (0 ":irc.foonet.org NOTICE tester :[09:12:53] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1622538742")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: When there is nothing living but thee, thou shalt be welcome. I had rather be a beggar's dog than Apemantus.")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: You have simply misused our sex in your love-prate: we must have your doublot and hose plucked over your head, and show the world what the bird hath done to her own nest."))
+
+((privmsg-a 6 "PRIVMSG rando :I here")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: And I will make thee think thy swan a crow.")
+ (0.1 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :u are dumb")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Lie not, to say mine eyes are murderers."))
+
+((privmsg-b 3 "PRIVMSG rando :not so")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: Commit myself, my person, and the cause.")
+ ;; Nick change
+ (0.1 ":rando!~u@bivkhq8yav938.irc NICK frenemy")
+ (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Of raging waste! It cannot hold; it will not.")
+ (0.1 ":frenemy!~u@bivkhq8yav938.irc PRIVMSG tester :doubly so")
+ (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: These words are razors to my wounded heart."))
diff --git a/test/lisp/erc/resources/base/renick/queries/solo.eld b/test/lisp/erc/resources/base/renick/queries/solo.eld
new file mode 100644
index 00000000000..12fa7d264e9
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/queries/solo.eld
@@ -0,0 +1,55 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 8 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 1 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
+
+((privmsg-a 10 "PRIVMSG #foo :hi")
+ (0.2 ":Lal!~u@b82mytupn2t5k.irc PRIVMSG tester :hello")
+ (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.")
+ (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Thou art thy father's daughter; there's enough."))
+
+((privmsg-b 10 "PRIVMSG Lal :hi")
+ (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: Here are the beetle brows shall blush for me.")
+ (0.2 ":Lal!~u@b82mytupn2t5k.irc NICK Linguo")
+ (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: He hath abandoned his physicians, madam; under whose practices he hath persecuted time with hope, and finds no other advantage in the process but only the losing of hope by time."))
+
+((privmsg-c 10 "PRIVMSG Linguo :howdy Linguo")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.")
+ (0.2 ":Linguo!~u@b82mytupn2t5k.irc PART #foo"))
+
+((part 10 "PART #foo :\2ERC\2")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc PART #foo :\2ERC\2")
+ (0.1 ":Linguo!~u@b82mytupn2t5k.irc PRIVMSG tester :get along little doggie"))
diff --git a/test/lisp/erc/resources/base/renick/self/auto.eld b/test/lisp/erc/resources/base/renick/self/auto.eld
new file mode 100644
index 00000000000..851db7f1cf7
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/auto.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev")
+ (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers")
+ (0 ":irc.foonet.org 252 tester 34 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 12815 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers")
+ (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739")
+ (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541")
+ (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0 ":irc.foonet.org 375 dummy :- irc.foonet.org Message of the Day - ")
+ (0 ":irc.foonet.org 372 dummy :- This server provided by NORDUnet/SUNET")
+ (0 ":irc.foonet.org 372 dummy :- Welcome to foonet, the IRC network for free & open-source software")
+ (0 ":irc.foonet.org 372 dummy :- and peer directed projects.")
+ (0 ":irc.foonet.org 372 dummy :- ")
+ (0 ":irc.foonet.org 372 dummy :- Please visit us in #libera for questions and support.")
+ (0 ":irc.foonet.org 376 dummy :End of /MOTD command."))
+
+((mode-user 10.2 "MODE dummy +i")
+ (0 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0 ":irc.znc.in 306 dummy :You have been marked as being away")
+ (0 ":dummy!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+
+ (0 ":irc.foonet.org 353 dummy = #foo :alice @bob Lal dummy")
+ (0 ":irc.foonet.org 366 dummy #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE dummy :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 dummy :You are no longer marked as being away"))
+
+((mode 10 "MODE #foo")
+ (0 ":irc.foonet.org 324 dummy #foo +nt")
+ (0 ":irc.foonet.org 329 dummy #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
diff --git a/test/lisp/erc/resources/base/renick/self/manual.eld b/test/lisp/erc/resources/base/renick/self/manual.eld
new file mode 100644
index 00000000000..dd107b806d5
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/manual.eld
@@ -0,0 +1,50 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev")
+ (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers")
+ (0 ":irc.foonet.org 252 tester 34 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 12815 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers")
+ (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739")
+ (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541")
+ (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)")
+ (0 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the Day - ")
+ (0 ":irc.foonet.org 372 tester :- This server provided by NORDUnet/SUNET")
+ (0 ":irc.foonet.org 372 tester :- Welcome to foonet, the IRC network for free & open-source software")
+ (0 ":irc.foonet.org 372 tester :- and peer directed projects.")
+ (0 ":irc.foonet.org 372 tester :- ")
+ (0 ":irc.foonet.org 372 tester :- Please visit us in #libera for questions and support.")
+ (0 ":irc.foonet.org 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc MODE tester :+RZi")
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo")
+
+ (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester")
+ (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...")
+ (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.")
+ (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 1 "MODE #foo")
+ (0 ":irc.foonet.org 324 tester #foo +nt")
+ (0 ":irc.foonet.org 329 tester #foo 1622454985")
+ (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short."))
+
+((nick 2 "NICK dummy")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :dummy: Hi."))
diff --git a/test/lisp/erc/resources/base/renick/self/qual-chester.eld b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
new file mode 100644
index 00000000000..75b50fe68bd
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK chester"))
+((user 1 "USER user 0 * :chester")
+ (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester")
+ (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 chester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 chester 1 :unregistered connections")
+ (0 ":irc.foonet.org 254 chester 1 :channels formed")
+ (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4")
+ (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
+ (0 ":irc.foonet.org 422 chester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE chester +i")
+ (0 ":irc.foonet.org 221 chester +i")
+ (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 14 "JOIN #chan")
+ (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob")
+ (0 ":irc.foonet.org 366 chester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 chester #chan +nt")
+ (0.0 ":irc.foonet.org 329 chester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
+
+((linger 10 LINGER))
diff --git a/test/lisp/erc/resources/base/renick/self/qual-tester.eld b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
new file mode 100644
index 00000000000..25199226658
--- /dev/null
+++ b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 15 "JOIN #chan")
+ (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 10 "MODE #chan")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1623563121")
+ (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.")
+ (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.")
+ (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!"))
+
+((nick 5 "NICK dummy")
+ (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy")
+ (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.")
+ (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.")
+ (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester."))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
new file mode 100644
index 00000000000..82700c5912c
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
@@ -0,0 +1,68 @@
+;; -*- mode: lisp-data; -*-
+((pass 3 "PASS :barnet:changeme"))
+((nick 3 "NICK tester"))
+((user 3 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Wed, 05 May 2021 09:05:33 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:16] joe: Tush! none but minstrels like of sonneting.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:19] mike: Prithee, nuncle, be contented; 'tis a naughty night to swim in. Now a little fire in a wide field were like an old lecher's heart; a small spark, all the rest on's body cold. Look! here comes a walking fire.")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:22] joe: My name is Edgar, and thy father's son.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:26] mike: Good my lord, be good to me; your honour is accounted a merciful man; good my lord.")
+ (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:31] joe: Thy child shall live, and I will see it nourish'd.")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:33] mike: Quick, quick; fear nothing; I'll be at thy elbow.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.barnet.org NOTICE tester :[09:05:35] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620205534")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: That will be given to the loudest noise we make.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If it please your honour, I am the poor duke's constable, and my name is Elbow: I do lean upon justice, sir; and do bring in here before your good honour two notorious benefactors.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Following the signs, woo'd but the sign of she.")
+ (0.5 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: That, sir, which I will not report after her.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Boyet, prepare: I will away to-night.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If the man be a bachelor, sir, I can; but if he be a married man, he is his wife's head, and I can never cut off a woman's head.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Thyself upon thy virtues, they on thee.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Arm it in rags, a pigmy's straw doth pierce it."))
+
+((part 5.1 "PART #chan :" quit)
+ (0 ":tester!~u@wvys46tx8tpmk.irc PART #chan :" quit))
+
+((join 10.1 "JOIN #chan")
+ (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620205534")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Chi non te vede, non te pretia.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Well, if ever thou dost fall from this faith, thou wilt prove a notable argument.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Of heavenly oaths, vow'd with integrity.")
+ (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: These herblets shall, which we upon you strew.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Aaron will have his soul black like his face."))
+
+((linger 0.5 LINGER))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
new file mode 100644
index 00000000000..a11cfac2e73
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
@@ -0,0 +1,66 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Wed, 05 May 2021 09:05:34 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:19] bob: Is this; she hath bought the name of whore thus dearly.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:24] alice: He sent to me, sir,Here he comes.")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:26] bob: Till I torment thee for this injury.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:29] alice: There's an Italian come; and 'tis thought, one of Leonatus' friends.")
+ (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:33] bob: Ay, and the particular confirmations, point from point, to the full arming of the verity.")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:35] alice: Kneel in the streets and beg for grace in vain.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0 ":irc.foonet.org NOTICE tester :[09:06:05] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
+
+((mode 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620205534")
+ (0.5 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Nor I no strength to climb without thy help.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Nothing, but let him have thanks. Demand of him my condition, and what credit I have with the duke.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Show me this piece. I am joyful of your sights.")
+ (0.2 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Whilst I can shake my sword or hear the drum."))
+
+((part 5 "PART #chan :" quit)
+ (0 ":tester!~u@247eaxkrufj44.irc PART #chan :" quit))
+
+((join 10 "JOIN #chan")
+ (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@bob alice tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620205534")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: And dar'st not stand, nor look me in the face.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: It should not be, by the persuasion of his new feasting.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: He that would vouch it in any place but here.")
+ (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: In everything I wait upon his will.")
+ (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou counterfeit'st most lively."))
+
+((linger 8 LINGER))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
new file mode 100644
index 00000000000..cc7aff10076
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
@@ -0,0 +1,24 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :barnet:changeme"))
+((nick 1 "NICK tester"))
+((user 2 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.barnet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
new file mode 100644
index 00000000000..3a846108466
--- /dev/null
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
@@ -0,0 +1,24 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer
+ (0 ":irc.znc.in 306 tester :You have been marked as being away")
+ (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld
new file mode 100644
index 00000000000..b8fc45e57b5
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld
@@ -0,0 +1,64 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/barnet 0 * :tester")
+ (0.01 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.01 ":soju.im 002 tester :Your host is soju.im")
+ (0.00 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.53 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=2 AWAYLEN=390 CHANLIMIT=#:100 INVEX NETWORK=barnet NICKLEN=32 WHOX MODES BOT=B ELIST=U MAXLIST=beI:60 :are supported")
+ (0.01 ":soju.im 005 tester TOPICLEN=390 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 EXCEPTS EXTBAN=,m KICKLEN=390 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 MAXTARGETS=4 MONITOR=100 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY :are supported")
+ (0.22 ":soju.im 221 tester +Zi")
+ (0.00 ":soju.im 422 tester :Use /motd to read the message of the day"))
+
+((mode 5 "MODE tester +i")
+ (0.00 ":tester!tester@10.0.2.100 JOIN #chan")
+ (0.06 ":soju.im 353 tester = #chan :tester @mike joe")
+ (0.01 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.23 ":irc.barnet.org 221 tester +Zi"))
+
+((mode 5 "MODE #chan")
+ (0.00 ":soju.im 324 tester #chan +tn")
+ (0.01 ":soju.im 329 tester #chan 1652878846")
+ (0.01 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: There is five in the first show.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Sir, I was an inward of his. A shy fellow was the duke; and, I believe I know the cause of his withdrawing.")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Proud of employment, willingly I go.")
+ (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Dull not device by coldness and delay.")
+ (0.09 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Our states are forfeit: seek not to undo us.")
+ (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come, you are too severe a moraler. As the time, the place, and the condition of this country stands, I could heartily wish this had not befallen, but since it is as it is, mend it for your own good.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Who hath upon him still that natural stamp.")
+ (0.07 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Arraign her first; 'tis Goneril. I here take my oath before this honourable assembly, she kicked the poor king her father.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Lady, I will commend you to mine own heart.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Look, what I will not, that I cannot do.")
+ (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: That he would wed me, or else die my lover.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come your way, sir. Bless you, good father friar.")
+ (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Under correction, sir, we know whereuntil it doth amount.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: For I am nothing if not critical.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Once more I'll read the ode that I have writ.")
+ (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: This is the foul fiend Flibbertigibbet: he begins at curfew, and walks till the first cock; he gives the web and the pin, squints the eye, and makes the harelip; mildews the white wheat, and hurts the poor creature of earth.")
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Sir, I praise the Lord for you, and so may my parishioners; for their sons are well tutored by you, and their daughters profit very greatly under you: you are a good member of the commonwealth.")
+ (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: If it please your honour, I know not well what they are; but precise villains they are, that I am sure of, and void of all profanation in the world that good Christians ought to have.")
+ ;; Unexpected disconnect
+ (0.03 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from barnet: failed to handle messages: failed to read IRC command: read tcp [::1]:54990->[::1]:6668: read: software caused connection abort")
+ ;; Eventual reconnect
+ (0.79 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to barnet")
+ ;; No MOTD or other numerics
+ (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported")
+ (0.01 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported")
+ (0.22 ":irc.barnet.org 221 tester +Zi")
+ (0.01 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ ;; Server-initialed join
+ (0.01 ":tester!tester@10.0.2.100 JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.22 ":soju.im 353 tester = #chan :@mike joe tester")
+ (0.00 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878846")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!")
+ (0.06 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878846")
+ (0.62 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Thou art my brother; so we'll hold thee ever.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Very well! go to! I cannot go to, man; nor 'tis not very well: by this hand, I say, it is very scurvy, and begin to find myself fobbed in it.")
+ (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: The heir of Alen on, Katharine her name.")
+ (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse."))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld
new file mode 100644
index 00000000000..63dfcb184c8
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld
@@ -0,0 +1,72 @@
+;; -*- mode: lisp-data; -*-
+((pass 5 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/foonet 0 * :tester")
+ (0.01 ":soju.im 001 tester :Welcome to soju, tester")
+ (0.02 ":soju.im 002 tester :Your host is soju.im")
+ (0.01 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI")
+ (0.00 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=1 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY AWAYLEN=390 NICKLEN=32 WHOX CHANLIMIT=#:100 INVEX NETWORK=foonet MODES :are supported")
+ (0.00 ":soju.im 005 tester TOPICLEN=390 BOT=B ELIST=U MAXLIST=beI:60 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 EXCEPTS EXTBAN=,m KICKLEN=390 MAXTARGETS=4 MONITOR=100 :are supported")
+ (0.00 ":soju.im 221 tester +Zi")
+ (0.00 ":soju.im 422 tester :Use /motd to read the message of the day"))
+
+((mode 5 "MODE tester +i")
+ (0.2 ":irc.foonet.org 221 tester +Zi")
+ (0.0 ":tester!tester@10.0.2.100 JOIN #chan")
+ (0.0 ":soju.im 353 tester = #chan :tester @alice bob")
+ (0.1 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Princely shall be thy usage every way.")
+ (0.1 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Tell me thy reason why thou wilt marry."))
+
+((mode 5 "MODE #chan")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.01 ":soju.im 329 tester #chan 1652878847")
+ (0.02 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: There is no leprosy but what thou speak'st.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I upon this bank will rest my head.")
+ (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: To ruffle in the commonwealth of Rome.")
+ (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I can nowhere find him like a man.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ay, sir; but she will none, she gives you thanks.")
+ (0.05 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That man should be at woman's command, and yet no hurt done! Though honesty be no puritan, yet it will do no hurt; it will wear the surplice of humility over the black gown of a big heart. I am going, forsooth: the business is for Helen to come hither.")
+ (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Indeed, I should have asked you that before.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Faith, we met, and found the quarrel was upon the seventh cause.")
+ (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: And then, I hope, thou wilt be satisfied.")
+ (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.")
+ (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ah! sirrah, this unlook'd-for sport comes well.")
+ (0.01 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Mayst thou inherit too! Welcome to Paris.")
+ (0.04 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That I would choose, were I to choose anew.")
+ (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Good Tom Drum, lend me a handkercher: so, I thank thee. Wait on me home, I'll make sport with thee: let thy curtsies alone, they are scurvy ones.")
+ (0.06 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.")
+ (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That every braggart shall be found an ass.")
+ (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: This is but a custom in your tongue; you bear a graver purpose, I hope.")
+ (0.02 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, we will have such a prologue, and it shall be written in eight and six.")
+ (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Tell me thy reason why thou wilt marry.")
+ (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: According to the measure of their states.")
+
+ ;; Unexpected disconnect
+ (0.07 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from foonet: failed to handle messages: failed to read IRC command: read tcp [::1]:57224->[::1]:6667: read: software caused connection abort")
+ ;; Eventual reconnect
+ (1.02 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to foonet")
+ ;; No MOTD or other numerics
+ (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported")
+ (0.02 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported")
+ (0.02 ":irc.foonet.org 221 tester +Zi")
+ (0.23 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ ;; Server-initialed join
+ (0.02 ":tester!tester@10.0.2.100 JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.03 ":soju.im 353 tester = #chan :@alice bob tester")
+ (0.03 ":soju.im 366 tester #chan :End of /NAMES list")
+ (0.00 ":soju.im 324 tester #chan +nt")
+ (0.00 ":soju.im 329 tester #chan 1652878847")
+ (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!")
+ (0.46 ":soju.im 324 tester #chan +nt")
+ (0.01 ":soju.im 329 tester #chan 1652878847")
+ (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.")
+ (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: But my intents are fix'd and will not leave me.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That last is true; the sweeter rest was mine.")
+ (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: No matter whither, so you come not here.")
+ (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round."))
+
+((linger 12 LINGER))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld
new file mode 100644
index 00000000000..bf5c2b5a749
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld
@@ -0,0 +1,93 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/barnet 0 * :tester")
+ (0.00 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0")
+ (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.00 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.00 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0.11 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode 5 "MODE tester +i")
+ (0.0 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan")
+ (0.05 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0.01 ":irc.barnet.org 366 tester #chan :End of /NAMES list.")
+ (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.0 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:13] mike: But send the midwife presently to me.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:18] joe: Alas! poor rogue, I think, i' faith, she loves me.")
+ (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:20] mike: They did not bless us with one happy word.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:24] joe: And hear the sentence of your moved prince.")
+ (0.21 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:29] mike: Swear me to this, and I will ne'er say no.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:32] joe: As they had seen me with these hangman's hands.")
+ (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:34] mike: Boyet, prepare: I will away to-night.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:36] joe: For being a little bad: so may my husband.")
+ (0.04 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.0 ":irc.barnet.org 221 tester +Zi")
+ (2.55 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And whirl along with thee about the globe."))
+
+((mode 5 "MODE #chan")
+ (0.00 ":irc.barnet.org 324 tester #chan +nt")
+ (0.00 ":irc.barnet.org 329 tester #chan 1652938384")
+ (0.06 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Unless good-counsel may the cause remove.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Thyself domestic officers thine enemy.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Go after her: she's desperate; govern her.")
+ (0.30 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Or else to heaven she heaves them for revenge.")
+ (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Keep up your bright swords, for the dew will rust them.")
+ (0.04 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...")
+ (0.41 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...")
+ (0.59 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.02 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0")
+ (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.01 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.01 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.22 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.01 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.17 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.barnet.org 422 tester :MOTD File is missing")
+ (0.01 ":irc.barnet.org 221 tester +Zi")
+ (0.00 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.05 ":irc.barnet.org 352 tester * ~u fsr9fwzfeeybc.irc irc.barnet.org tester H :0 ZNC - https://znc.in")
+ (0.02 ":irc.barnet.org 315 tester tester!*@* :End of WHO list")
+ (0.08 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan"))
+
+((mode 5 "MODE #chan")
+ (0.05 ":irc.barnet.org 353 tester = #chan :mike tester @joe")
+ (0.01 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!")
+ (0.02 ":irc.barnet.org 324 tester #chan +nt")
+ (0.01 ":irc.barnet.org 329 tester #chan 1652938384")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: See, here he comes, and I must ply my theme.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Confine yourself but in a patient list.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Bid me farewell, and let me hear thee going.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Nor shall not, if I do as I intend.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Our corn's to reap, for yet our tithe's to sow.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And almost broke my heart with extreme laughter.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Of modern seeming do prefer against him.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Like humble-visag'd suitors, his high will.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: But yet, poor Claudio! There's no remedy.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Let him make treble satisfaction.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: He's that he is; I may not breathe my censure.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: To check their folly, passion's solemn tears.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Villain, I have done thy mother.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Please you, therefore, draw nigh, and take your places.")
+ (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: You shall not be admitted to his sight.")
+ (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Sir, you shall present before her the Nine Worthies. Sir Nathaniel, as concerning some entertainment of time, some show in the posterior of this day, to be rendered by our assistance, at the king's command, and this most gallant, illustrate, and learned gentleman, before the princess; I say, none so fit as to present the Nine Worthies.")
+ (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse."))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld
new file mode 100644
index 00000000000..39c2950aa09
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld
@@ -0,0 +1,86 @@
+;; -*- mode: lisp-data; -*-
+((pass 6 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER tester@vanilla/foonet 0 * :tester")
+ (0.16 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.00 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode 6 "MODE tester +i")
+ (0.00 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan")
+ (0.09 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0.00 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0.00 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:11] alice: And be aveng'd on cursed Tamora.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:13] bob: The stronger part of it by her own letters, which make her story true, even to the point of her death: her death itself, which could not be her office to say is come, was faithfully confirmed by the rector of the place.")
+ (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:15] alice: The ape is dead, and I must conjure him.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:17] bob: Not so; but I answer you right painted cloth, from whence you have studied your questions.")
+ (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:21] alice: The valiant Paris seeks you for his love.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:26] bob: To prison with her; and away with him.")
+ (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:30] alice: Tell them there I have gold; look, so I have.")
+ (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:35] bob: Will even weigh, and both as light as tales.")
+ (0.00 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")
+ (0.00 ":irc.foonet.org 221 tester +Zi")
+ (0.08 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By some vile forfeit of untimely death."))
+
+((mode 3.51 "MODE #chan")
+ (0.1 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1652938384")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: What does this knave here ? Get you gone, sirrah: the complaints I have heard of you I do not all believe: 'tis my slowness that I do not; for I know you lack not folly to commit them, and have ability enough to make such knaveries yours.")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: When sects and factions were newly born.")
+ (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Fall, when Love please! marry, to each, but one.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: For I ne'er saw true beauty till this night.")
+ (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Or say, sweet love, what thou desir'st to eat.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: Yes, and will nobly him remunerate.")
+ (0.1 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...")
+ (0.4 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...")
+ (0.9 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.0 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC")
+ (0.0 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.1 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.1 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.0 ":irc.foonet.org 221 tester +Zi")
+ (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.6 ":irc.foonet.org 352 tester * ~u rmtvrz9zcwbdq.irc irc.foonet.org tester H :0 ZNC - https://znc.in")
+ (0.0 ":irc.foonet.org 315 tester tester!*@* :End of WHO list")
+ (0.0 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan"))
+
+((mode 6 "MODE #chan")
+ (0.0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0.0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Being of no power to make his wishes good.")
+ (0.0 ":irc.foonet.org 324 tester #chan +nt")
+ (0.0 ":irc.foonet.org 329 tester #chan 1652938384")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: In everything I wait upon his will.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Make choice of which your highness will see first.")
+ (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: We waste our lights in vain, like lamps by day.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: No, I know that; but it is fit I should commit offence to my inferiors.")
+ (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By my head, here come the Capulets.")
+ (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.")
+ (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round."))
+
+((linger 12 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el b/test/lisp/erc/resources/erc-d/erc-d-i.el
new file mode 100644
index 00000000000..db113335a82
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-i.el
@@ -0,0 +1,124 @@
+;;; erc-d-i.el --- IRC helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+
+(cl-defstruct (erc-d-i-message (:conc-name erc-d-i-message.))
+ "Identical to `erc-response'.
+When member `compat' is nil, it means the raw message was decoded as
+UTF-8 text before parsing, which is nonstandard."
+ (unparsed "" :type string)
+ (sender "" :type string)
+ (command "" :type string)
+ (command-args nil :type (list-of string))
+ (contents "" :type string)
+ (tags nil :type (list-of (cons symbol string)))
+ (compat t :type boolean))
+
+(defconst erc-d-i--tag-escapes
+ '((";" . "\\:") (" " . "\\s") ("\\" . "\\\\") ("\r" . "\\r") ("\n" . "\\n")))
+
+;; These are not mirror inverses; unescaping may drop stranded or
+;; misplaced backslashes.
+
+(defconst erc-d-i--tag-escaped-regexp (rx (or ?\; ?\ ?\\ ?\r ?\n)))
+
+(defconst erc-d-i--tag-unescaped-regexp
+ (rx (or "\\:" "\\s" "\\\\" "\\r" "\\n"
+ (seq "\\" (or string-end (not (or ":" "s" "n" "r" "\\")))))))
+
+(defun erc-d-i--unescape-tag-value (str)
+ "Undo substitution of char placeholders in raw tag value STR."
+ (replace-regexp-in-string erc-d-i--tag-unescaped-regexp
+ (lambda (s)
+ (or (car (rassoc s erc-d-i--tag-escapes))
+ (substring s 1)))
+ str t t))
+
+(defun erc-d-i--escape-tag-value (str)
+ "Swap out banned chars in tag value STR with message representation."
+ (replace-regexp-in-string erc-d-i--tag-escaped-regexp
+ (lambda (s)
+ (cdr (assoc s erc-d-i--tag-escapes)))
+ str t t))
+
+(defconst erc-d-i--invalid-tag-regexp (rx (any "\0\7\r\n; ")))
+
+(defun erc-d-i--validate-tags (raw)
+ "Validate tags portion of some RAW incoming message.
+RAW must not have a leading \"@\" or a trailing space. The spec says
+validation shouldn't be performed on keys and that undecodeable values
+or ones with illegal (unescaped) chars may be dropped. This does not
+respect any of that. Its purpose is to catch bad input created by us."
+ (unless (> 4094 (string-bytes raw))
+ ;; 417 ERR_INPUTTOOLONG Input line was too long
+ (error "Message tags exceed 4094 bytes: %S" raw))
+ (let (tags
+ (tag-strings (split-string raw ";")))
+ (dolist (s tag-strings (nreverse tags))
+ (let* ((m (if (>= emacs-major-version 28)
+ (string-search "=" s)
+ (string-match-p "=" s)))
+ (key (if m (substring s 0 m) s))
+ (val (when-let* (m ; check first, like (m), but shadow
+ (v (substring s (1+ m)))
+ ((not (string-equal v ""))))
+ (when (string-match-p erc-d-i--invalid-tag-regexp v)
+ (error "Bad tag: %s" s))
+ (thread-first v
+ (decode-coding-string 'utf-8 t)
+ (erc-d-i--unescape-tag-value)))))
+ (when (string-empty-p key)
+ (error "Tag missing key: %S" s))
+ (setf (alist-get (intern key) tags) val)))))
+
+(defun erc-d-i--parse-message (s &optional decode)
+ "Parse string S into `erc-d-i-message' object.
+With DECODE, decode as UTF-8 text."
+ (when (string-suffix-p "\r\n" s)
+ (error "Unstripped message encountered"))
+ (when decode
+ (setq s (decode-coding-string s 'utf-8 t)))
+ (let ((mes (make-erc-d-i-message :unparsed s :compat (not decode)))
+ tokens)
+ (when-let* (((not (string-empty-p s)))
+ ((eq ?@ (aref s 0)))
+ (m (string-match " " s))
+ (u (substring s 1 m)))
+ (setf (erc-d-i-message.tags mes) (erc-d-i--validate-tags u)
+ s (substring s (1+ m))))
+ (if-let* ((m (string-match " :" s))
+ (other-toks (split-string (substring s 0 m) " " t))
+ (rest (substring s (+ 2 m))))
+ (setf (erc-d-i-message.contents mes) rest
+ tokens (nconc other-toks (list rest)))
+ (setq tokens (split-string s " " t " ")))
+ (when (and tokens (eq ?: (aref (car tokens) 0)))
+ (setf (erc-d-i-message.sender mes) (substring (pop tokens) 1)))
+ (setf (erc-d-i-message.command mes) (or (pop tokens) "")
+ (erc-d-i-message.command-args mes) tokens)
+ mes))
+
+(provide 'erc-d-i)
+;;; erc-d-i.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el b/test/lisp/erc/resources/erc-d/erc-d-t.el
new file mode 100644
index 00000000000..a1a7e7e88d5
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-t.el
@@ -0,0 +1,170 @@
+;;; erc-d-t.el --- ERT helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(eval-and-compile
+ (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name)))
+ (load-path (cons (directory-file-name d) load-path)))
+ (require 'erc-d-u)))
+
+(require 'ert)
+
+(defun erc-d-t-kill-related-buffers ()
+ "Kill all erc- or erc-d- related buffers."
+ (let (buflist)
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when (or erc-d-u--process-buffer
+ (derived-mode-p 'erc-mode))
+ (push buf buflist))))
+ (dolist (buf buflist)
+ (when (and (boundp 'erc-server-flood-timer)
+ (timerp erc-server-flood-timer))
+ (cancel-timer erc-server-flood-timer))
+ (when-let ((proc (get-buffer-process buf)))
+ (delete-process proc))
+ (when (buffer-live-p buf)
+ (kill-buffer buf))))
+ (while (when-let ((buf (pop erc-d-u--canned-buffers)))
+ (kill-buffer buf))))
+
+(defun erc-d-t-silence-around (orig &rest args)
+ "Run ORIG function with ARGS silently.
+Use this on `erc-handle-login' and `erc-server-connect'."
+ (let ((inhibit-message t))
+ (apply orig args)))
+
+(defvar erc-d-t-cleanup-sleep-secs 0.1)
+
+(defmacro erc-d-t-with-cleanup (bindings cleanup &rest body)
+ "Execute BODY and run CLEANUP form regardless of outcome.
+`let*'-bind BINDINGS and make them available in BODY and CLEANUP.
+After CLEANUP, destroy any values in BINDINGS that remain bound to
+buffers or processes. Sleep `erc-d-t-cleanup-sleep-secs' before
+returning."
+ (declare (indent 2))
+ `(let* ,bindings
+ (unwind-protect
+ (progn ,@body)
+ ,cleanup
+ (when noninteractive
+ (let (bufs procs)
+ (dolist (o (list ,@(mapcar (lambda (b) (or (car-safe b) b))
+ bindings)))
+ (when (bufferp o)
+ (push o bufs))
+ (when (processp o)
+ (push o procs)))
+ (dolist (proc procs)
+ (delete-process proc)
+ (when-let ((buf (process-buffer proc)))
+ (push buf bufs)))
+ (dolist (buf bufs)
+ (when-let ((proc (get-buffer-process buf)))
+ (delete-process proc))
+ (when (bufferp buf)
+ (ignore-errors (kill-buffer buf)))))
+ (sleep-for erc-d-t-cleanup-sleep-secs)))))
+
+(defmacro erc-d-t-wait-for (max-secs msg &rest body)
+ "Wait for BODY to become non-nil.
+Or signal error with MSG after MAX-SECS. When MAX-SECS is negative,
+signal if BODY is ever non-nil before MAX-SECS elapses. On success,
+return BODY's value.
+
+Note: this assumes BODY is waiting on a peer's output. It tends to
+artificially accelerate consumption of all process output, which may not
+be desirable."
+ (declare (indent 2))
+ (unless (or (stringp msg) (memq (car-safe msg) '(format concat)))
+ (push msg body)
+ (setq msg (prin1-to-string body)))
+ (let ((inverted (make-symbol "inverted"))
+ (time-out (make-symbol "time-out"))
+ (result (make-symbol "result")))
+ `(ert-info ((concat "Awaiting: " ,msg))
+ (let ((,time-out (abs ,max-secs))
+ (,inverted (< ,max-secs 0))
+ (,result ',result))
+ (with-timeout (,time-out (if ,inverted
+ (setq ,inverted nil)
+ (error "Failed awaiting: %s" ,msg)))
+ (while (not (setq ,result (progn ,@body)))
+ (when (and (accept-process-output nil 0.1) (not noninteractive))
+ (redisplay))))
+ (when ,inverted
+ (error "Failed awaiting: %s" ,msg))
+ ,result))))
+
+(defmacro erc-d-t-ensure-for (max-secs msg &rest body)
+ "Ensure BODY remains non-nil for MAX-SECS.
+On failure, emit MSG."
+ (declare (indent 2))
+ (unless (or (stringp msg) (memq (car-safe msg) '(format concat)))
+ (push msg body)
+ (setq msg (prin1-to-string body)))
+ `(erc-d-t-wait-for (- (abs ,max-secs)) ,msg (not (progn ,@body))))
+
+(defun erc-d-t-search-for (timeout text &optional from on-success)
+ "Wait for TEXT to appear in current buffer before TIMEOUT secs.
+With marker or number FROM, only consider the portion of the buffer from
+that point forward. If TEXT is a cons, interpret it as an RX regular
+expression. If ON-SUCCESS is a function, call it when TEXT is found."
+ (save-restriction
+ (widen)
+ (let* ((rxp (consp text))
+ (fun (if rxp #'search-forward-regexp #'search-forward))
+ (pat (if rxp (rx-to-string text) text))
+ res)
+ (erc-d-t-wait-for timeout (format "string: %s" text)
+ (goto-char (or from (point-min)))
+ (setq res (funcall fun pat nil t))
+ (if (and on-success res)
+ (funcall on-success)
+ res)))))
+
+(defun erc-d-t-absent-for (timeout text &optional from on-success)
+ "Assert TEXT doesn't appear in current buffer for TIMEOUT secs."
+ (erc-d-t-search-for (- (abs timeout)) text from on-success))
+
+(defun erc-d-t-make-expecter ()
+ "Return function to search for new output in buffer.
+Assume new text is only inserted at or after `erc-insert-marker'.
+
+The returned function works like `erc-d-t-search-for', but it never
+revisits previously covered territory, and the optional fourth argument,
+ON-SUCCESS, is nonexistent. To reset, specify a FROM argument."
+ (let (positions)
+ (lambda (timeout text &optional reset-from)
+ (let* ((pos (cdr (assq (current-buffer) positions)))
+ (cb (lambda ()
+ (unless pos
+ (push (cons (current-buffer) (setq pos (make-marker)))
+ positions))
+ (marker-position
+ (set-marker pos (min (point) (1- (point-max))))))))
+ (when reset-from
+ (set-marker pos reset-from))
+ (erc-d-t-search-for timeout text pos cb)))))
+
+(provide 'erc-d-t)
+;;; erc-d-t.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-tests.el b/test/lisp/erc/resources/erc-d/erc-d-tests.el
new file mode 100644
index 00000000000..f64b5e8a74c
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-tests.el
@@ -0,0 +1,1346 @@
+;;; erc-d-tests.el --- tests for erc-d -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (expand-file-name ".." (ert-resource-directory))
+ load-path)))
+ (require 'erc-d)
+ (require 'erc-d-t)))
+
+(require 'erc)
+
+;; Temporary kludge to silence warning
+(put 'erc-parse-tags 'erc-v3-warned-p t)
+
+(ert-deftest erc-d-u--canned-load-dialog--basic ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers)
+ (let* ((exes (erc-d-u--canned-load-dialog 'basic))
+ (reap (lambda ()
+ (cl-loop with e = (erc-d-u--read-dialog exes)
+ for s = (erc-d-u--read-exchange e)
+ while s collect s))))
+ (should (get-buffer "basic.eld"))
+ (should (memq (get-buffer "basic.eld") erc-d-u--canned-buffers))
+ (should (equal (funcall reap) '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap) '((nick 0.2 "NICK tester"))))
+ (let ((r (funcall reap)))
+ (should (equal (car r) '(user 0.2 "USER user 0 * :tester")))
+ (should (equal
+ (car (last r))
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+ (should (equal (car (funcall reap)) '(mode-user 5 "MODE tester +i")))
+ (should (equal (funcall reap)
+ '((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))))
+ ;; See `define-error' site for `iter-end-of-sequence'
+ (ert-info ("EOB detected") (should-not (erc-d-u--read-dialog exes))))
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers))
+
+(defun erc-d-tests--make-hunk-reader (hunks)
+ (let ((p (erc-d-u--read-dialog hunks)))
+ (lambda () (erc-d-u--read-exchange p))))
+
+;; Fuzzies need to be able to access any non-exhausted genny.
+(ert-deftest erc-d-u--canned-load-dialog--intermingled ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers)
+ (let* ((exes (erc-d-u--canned-load-dialog 'basic))
+ (pass (erc-d-tests--make-hunk-reader exes))
+ (nick (erc-d-tests--make-hunk-reader exes))
+ (user (erc-d-tests--make-hunk-reader exes))
+ (modu (erc-d-tests--make-hunk-reader exes))
+ (modc (erc-d-tests--make-hunk-reader exes)))
+
+ (should (equal (funcall user) '(user 0.2 "USER user 0 * :tester")))
+ (should (equal (funcall modu) '(mode-user 5 "MODE tester +i")))
+ (should (equal (funcall modc) '(mode-chan 1.2 "MODE #chan")))
+
+ (cl-loop repeat 8 do (funcall user)) ; skip a few
+ (should (equal (funcall user)
+ '(0 ":irc.example.org 254 tester 1 :channels formed")))
+ (should (equal (funcall modu)
+ '(0 ":irc.example.org 221 tester +Zi")))
+ (should (equal (cl-loop for s = (funcall modc) while s collect s) ; done
+ '((0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))))
+
+ (cl-loop repeat 3 do (funcall user))
+ (cl-loop repeat 3 do (funcall modu))
+
+ (ert-info ("Change up the order")
+ (should
+ (equal (funcall modu)
+ '(0 ":irc.example.org 366 alice #chan :End of NAMES list")))
+ (should
+ (equal (funcall user)
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+
+ ;; Exhaust these
+ (should (equal (cl-loop for s = (funcall pass) while s collect s) ; done
+ '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (cl-loop for s = (funcall nick) while s collect s) ; done
+ '((nick 0.2 "NICK tester"))))
+
+ (ert-info ("End of file but no teardown because hunks outstanding")
+ (should-not (erc-d-u--read-dialog exes))
+ (should (get-buffer "basic.eld")))
+
+ ;; Finish
+ (should-not (funcall user))
+ (should-not (funcall modu)))
+
+ (should-not (get-buffer "basic.eld"))
+ (should-not erc-d-u--canned-buffers))
+
+;; This indirectly tests `erc-d-u--canned-read' cleanup/teardown
+
+(ert-deftest erc-d-u--rewrite-for-slow-mo ()
+ (should-not (get-buffer "basic.eld"))
+ (should-not (get-buffer "basic.eld<2>"))
+ (should-not (get-buffer "basic.eld<3>"))
+ (should-not erc-d-u--canned-buffers)
+ (let ((exes (erc-d-u--canned-load-dialog 'basic))
+ (exes-lower (erc-d-u--canned-load-dialog 'basic))
+ (exes-custom (erc-d-u--canned-load-dialog 'basic))
+ (reap (lambda (e) (cl-loop with p = (erc-d-u--read-dialog e)
+ for s = (erc-d-u--read-exchange p)
+ while s collect s))))
+ (should (get-buffer "basic.eld"))
+ (should (get-buffer "basic.eld<2>"))
+ (should (get-buffer "basic.eld<3>"))
+ (should (equal (list (get-buffer "basic.eld<3>")
+ (get-buffer "basic.eld<2>")
+ (get-buffer "basic.eld"))
+ erc-d-u--canned-buffers))
+
+ (ert-info ("Rewrite for slowmo basic")
+ (setq exes (erc-d-u--rewrite-for-slow-mo 10 exes))
+ (should (equal (funcall reap exes)
+ '((pass 20.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes)
+ '((nick 10.2 "NICK tester"))))
+ (let ((r (funcall reap exes)))
+ (should (equal (car r) '(user 10.2 "USER user 0 * :tester")))
+ (should (equal
+ (car (last r))
+ '(0 ":irc.example.org 422 tester :MOTD File is missing"))))
+ (should (equal (car (funcall reap exes))
+ '(mode-user 15 "MODE tester +i")))
+ (should (equal (car (funcall reap exes))
+ '(mode-chan 11.2 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes)))
+
+ (ert-info ("Rewrite for slowmo bounded")
+ (setq exes-lower (erc-d-u--rewrite-for-slow-mo -5 exes-lower))
+ (should (equal (funcall reap exes-lower)
+ '((pass 10.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes-lower)
+ '((nick 5 "NICK tester"))))
+ (should (equal (car (funcall reap exes-lower))
+ '(user 5 "USER user 0 * :tester")))
+ (should (equal (car (funcall reap exes-lower))
+ '(mode-user 5 "MODE tester +i")))
+ (should (equal (car (funcall reap exes-lower))
+ '(mode-chan 5 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes-lower)))
+
+ (ert-info ("Rewrite for slowmo custom")
+ (setq exes-custom (erc-d-u--rewrite-for-slow-mo
+ (lambda (n) (* 2 n)) exes-custom))
+ (should (equal (funcall reap exes-custom)
+ '((pass 20.0 "PASS " (? ?:) "changeme"))))
+ (should (equal (funcall reap exes-custom)
+ '((nick 0.4 "NICK tester"))))
+ (should (equal (car (funcall reap exes-custom))
+ '(user 0.4 "USER user 0 * :tester")))
+ (should (equal (car (funcall reap exes-custom))
+ '(mode-user 10 "MODE tester +i")))
+ (should (equal (car (funcall reap exes-custom))
+ '(mode-chan 2.4 "MODE #chan")))
+ (should-not (erc-d-u--read-dialog exes-custom))))
+
+ (should-not (get-buffer "basic.eld"))
+ (should-not (get-buffer "basic.eld<2>"))
+ (should-not (get-buffer "basic.eld<3>"))
+ (should-not erc-d-u--canned-buffers))
+
+(ert-deftest erc-d--active-ex-p ()
+ (let ((ring (make-ring 5)))
+ (ert-info ("Empty ring returns nil for not active")
+ (should-not (erc-d--active-ex-p ring)))
+ (ert-info ("One fuzzy member returns nil for not active")
+ (ring-insert ring (make-erc-d-exchange :tag '~foo))
+ (should-not (erc-d--active-ex-p ring)))
+ (ert-info ("One active member returns t for active")
+ (ring-insert-at-beginning ring (make-erc-d-exchange :tag 'bar))
+ (should (erc-d--active-ex-p ring)))))
+
+(defun erc-d-tests--parse-message-upstream (raw)
+ "Hack shim for parsing RAW line recvd from peer."
+ (cl-letf (((symbol-function #'erc-handle-parsed-server-response)
+ (lambda (_ p) p)))
+ (let ((erc-active-buffer nil))
+ (erc-parse-server-response nil raw))))
+
+(ert-deftest erc-d-i--validate-tags ()
+ (should (erc-d-i--validate-tags
+ (concat "batch=4cc99692bf24a4bec4aa03da437364f5;"
+ "time=2021-01-04T00:32:13.839Z")))
+ (should (erc-d-i--validate-tags "+foo=bar;baz=spam"))
+ (should (erc-d-i--validate-tags "foo=\\:ok;baz=\\s"))
+ (should (erc-d-i--validate-tags "foo=\303\247edilla"))
+ (should (erc-d-i--validate-tags "foo=\\"))
+ (should (erc-d-i--validate-tags "foo=bar\\baz"))
+ (should-error (erc-d-i--validate-tags "foo=\\\\;baz=\\\r\\\n"))
+ (should-error (erc-d-i--validate-tags "foo=\n"))
+ (should-error (erc-d-i--validate-tags "foo=\0ok"))
+ (should-error (erc-d-i--validate-tags "foo=bar baz"))
+ (should-error (erc-d-i--validate-tags "foo=bar\r"))
+ (should-error (erc-d-i--validate-tags "foo=bar;")))
+
+(ert-deftest erc-d-i--parse-message ()
+ (let* ((raw (concat "@time=2020-11-23T09:10:33.088Z "
+ ":tilde.chat BATCH +1 chathistory :#meta"))
+ (upstream (erc-d-tests--parse-message-upstream raw))
+ (ours (erc-d-i--parse-message raw)))
+
+ (ert-info ("Baseline upstream")
+ (should (equal (erc-response.unparsed upstream) raw))
+ (should (equal (erc-response.sender upstream) "tilde.chat"))
+ (should (equal (erc-response.command upstream) "BATCH"))
+ (should (equal (erc-response.command-args upstream)
+ '("+1" "chathistory" "#meta")))
+ (should (equal (erc-response.contents upstream) "#meta")))
+
+ (ert-info ("Ours my not compare cl-equalp but is otherwise the same")
+ (should (equal (erc-d-i-message.unparsed ours) raw))
+ (should (equal (erc-d-i-message.sender ours) "tilde.chat"))
+ (should (equal (erc-d-i-message.command ours) "BATCH"))
+ (should (equal (erc-d-i-message.command-args ours)
+ '("+1" "chathistory" "#meta")))
+ (should (equal (erc-d-i-message.contents ours) "#meta"))
+ (should (equal (erc-d-i-message.tags ours)
+ '((time . "2020-11-23T09:10:33.088Z")))))
+
+ (ert-info ("No compat decodes the whole message as utf-8")
+ (setq ours (erc-d-i--parse-message
+ "@foo=\303\247edilla TAGMSG #ch\303\240n"
+ 'decode))
+ (should-not (erc-d-i-message.compat ours))
+ (should (equal (erc-d-i-message.command-args ours) '("#chàn")))
+ (should (equal (erc-d-i-message.contents ours) ""))
+ (should (equal (erc-d-i-message.tags ours) '((foo . "çedilla")))))))
+
+(ert-deftest erc-d-i--unescape-tag-value ()
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\sabc\\sdef\\s\\sxyz\\s")
+ " abc def xyz "))
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\\\abc\\\\def\\\\\\\\xyz\\\\")
+ "\\abc\\def\\\\xyz\\"))
+ (should (equal (erc-d-i--unescape-tag-value "a\\bc") "abc"))
+ (should (equal (erc-d-i--unescape-tag-value
+ "\\\\abc\\\\def\\\\\\\\xyz\\")
+ "\\abc\\def\\\\xyz"))
+ (should (equal (erc-d-i--unescape-tag-value "a\\:b\\r\\nc\\sd")
+ "a;b\r\nc d")))
+
+(ert-deftest erc-d-i--escape-tag-value ()
+ (should (equal (erc-d-i--escape-tag-value " abc def xyz ")
+ "\\sabc\\sdef\\s\\sxyz\\s"))
+ (should (equal (erc-d-i--escape-tag-value "\\abc\\def\\\\xyz\\")
+ "\\\\abc\\\\def\\\\\\\\xyz\\\\"))
+ (should (equal (erc-d-i--escape-tag-value "a;b\r\nc d")
+ "a\\:b\\r\\nc\\sd")))
+
+;; TODO add tests for msg-join, mask-match, userhost-split,
+;; validate-hostname
+
+(ert-deftest erc-d-i--parse-message--irc-parser-tests ()
+ (let* ((data (with-temp-buffer
+ (insert-file-contents
+ (expand-file-name "irc-parser-tests.eld"
+ (ert-resource-directory)))
+ (read (current-buffer))))
+ (tests (assoc-default 'tests (assoc-default 'msg-split data)))
+ input atoms m ours)
+ (dolist (test tests)
+ (setq input (assoc-default 'input test)
+ atoms (assoc-default 'atoms test)
+ m (erc-d-i--parse-message input))
+ (ert-info ("Parses tags correctly")
+ (setq ours (erc-d-i-message.tags m))
+ (if-let ((tags (assoc-default 'tags atoms)))
+ (pcase-dolist (`(,key . ,value) ours)
+ (should (string= (cdr (assq key tags)) (or value ""))))
+ (should-not ours)))
+ (ert-info ("Parses verbs correctly")
+ (setq ours (erc-d-i-message.command m))
+ (if-let ((verbs (assoc-default 'verb atoms)))
+ (should (string= (downcase verbs) (downcase ours)))
+ (should (string-empty-p ours))))
+ (ert-info ("Parses sources correctly")
+ (setq ours (erc-d-i-message.sender m))
+ (if-let ((source (assoc-default 'source atoms)))
+ (should (string= source ours))
+ (should (string-empty-p ours))))
+ (ert-info ("Parses params correctly")
+ (setq ours (erc-d-i-message.command-args m))
+ (if-let ((params (assoc-default 'params atoms)))
+ (should (equal ours params))
+ (should-not ours))))))
+
+(defun erc-d-tests--new-ex (existing raw-hunk)
+ (let* ((f (lambda (_) (pop raw-hunk)))
+ (sd (make-erc-d-u-scan-d :f f)))
+ (setf (erc-d-exchange-hunk existing) (make-erc-d-u-scan-e :sd sd)
+ (erc-d-exchange-spec existing) (make-erc-d-spec)))
+ (erc-d--iter existing))
+
+(ert-deftest erc-d--render-entries ()
+ (let* ((erc-nick "foo")
+ (dialog (make-erc-d-dialog :vars `((:a . 1)
+ (c . ((a b) (: a space b)))
+ (d . (c alpha digit))
+ (bee . 2)
+ (f . ,(lambda () "3"))
+ (i . erc-nick))))
+ (exchange (make-erc-d-exchange :dialog dialog))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("Baseline Outgoing")
+ (setq it (funcall mex '((0 "abc"))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Incoming are regexp escaped")
+ (setq it (funcall mex '((i 0.0 "fsf" ".org"))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`fsf\\.org")))
+
+ (ert-info ("Incoming can access vars via rx-let")
+ (setq it (funcall mex '((i 0.0 bee))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`\002")))
+
+ (ert-info ("Incoming rx-let params")
+ (setq it (funcall mex '((i 0.0 d))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`[[:alpha:]][[:space:]][[:digit:]]")))
+
+ (ert-info ("Incoming literal rx forms")
+ (setq it (funcall mex '((i 0.0 (= 3 alpha) ".org"))))
+ (should (equal (cons (funcall it) (funcall it)) '(i . 0.0)))
+ (should (equal (funcall it) "\\`[[:alpha:]]\\{3\\}\\.org")))
+
+ (ert-info ("Self-quoting disallowed")
+ (setq it (funcall mex '((0 :a "abc"))))
+ (should (equal (funcall it) 0))
+ (should-error (funcall it)))
+
+ (ert-info ("Global vars and short vars")
+ (setq it (funcall mex '((0 i f erc-nick))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo3foo")))
+
+ (ert-info ("Exits clean")
+ (when (listp (alist-get 'f (erc-d-dialog-vars dialog))) ; may be compiled
+ (should (eq 'closure (car (alist-get 'f (erc-d-dialog-vars dialog))))))
+ (should-not (funcall it))
+ (should (equal (erc-d-dialog-vars dialog)
+ `((:a . 1)
+ (c . ((a b) (: a space b)))
+ (d . (c alpha digit))
+ (bee . 2)
+ (f . ,(alist-get 'f (erc-d-dialog-vars dialog)))
+ (i . erc-nick)))))))
+
+(ert-deftest erc-d--render-entries--matches ()
+ (let* ((alist (list
+ (cons 'f (lambda (a) (funcall a :match 1)))
+ (cons 'g (lambda () (match-string 2 "foo bar baz")))
+ (cons 'h (lambda (a) (concat (funcall a :match 0)
+ (funcall a :request))))
+ (cons 'i (lambda (_ e) (erc-d-exchange-request e)))
+ (cons 'j (lambda ()
+ (set-match-data '(0 1))
+ (match-string 0 "j")))))
+ (dialog (make-erc-d-dialog :vars alist))
+ (exchange (make-erc-d-exchange :dialog dialog
+ :request "foo bar baz"
+ ;; 11 222
+ :match-data '(4 11 4 6 8 11)))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("One arg, match")
+ (setq it (funcall mex '((0 f))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "ba")))
+
+ (ert-info ("No args")
+ (setq it (funcall mex '((0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "baz")))
+
+ (ert-info ("Second arg is exchange object")
+ (setq it (funcall mex '((0 i))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo bar baz")))
+
+ (ert-info ("One arg, multiple calls")
+ (setq it (funcall mex '((0 h))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "bar bazfoo bar baz")))
+
+ (ert-info ("Match data restored")
+ (setq it (funcall mex '((0 j))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "j"))
+
+ (setq it (funcall mex '((0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "baz")))
+
+ (ert-info ("Bad signature")
+ (let ((qlist (list 'f '(lambda (p q x) (ignore)))))
+ (setf (erc-d-dialog-vars dialog) qlist)
+ (should-error (erc-d-exchange-reload dialog exchange))))))
+
+(ert-deftest erc-d--render-entries--dynamic ()
+ (let* ((alist (list
+ (cons 'foo "foo")
+ (cons 'f (lambda (a) (funcall a :get-binding 'foo)))
+ (cons 'h (lambda (a) (upcase (funcall a :get-var 'foo))))
+ (cons 'g (lambda (a)
+ (funcall a :rebind 'g (funcall a :get-var 'f))
+ "bar"))
+ (cons 'j (lambda (a) (funcall a :set "123") "abc"))
+ (cons 'k (lambda () "abc"))))
+ (dialog (make-erc-d-dialog :vars alist))
+ (exchange (make-erc-d-exchange :dialog dialog))
+ (mex (apply-partially #'erc-d-tests--new-ex exchange))
+ it)
+
+ (erc-d-exchange-reload dialog exchange)
+
+ (ert-info ("Initial reference calls function")
+ (setq it (funcall mex '((0 j) (0 j))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Subsequent reference expands to string")
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "123")))
+
+ (ert-info ("Outside manipulation: initial reference calls function")
+ (setq it (funcall mex '((0 k) (0 k))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "abc")))
+
+ (ert-info ("Outside manipulation: subsequent reference expands to string")
+ (erc-d-exchange-rebind dialog exchange 'k "123")
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "123")))
+
+ (ert-info ("Swap one function for another")
+ (setq it (funcall mex '((0 g) (0 g))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "bar"))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo")))
+
+ (ert-info ("Bindings accessible inside functions")
+ (setq it (funcall mex '((0 f h))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "fooFOO")))
+
+ (ert-info ("Rebuild alist by sending flag")
+ (setq it (funcall mex '((0 f) (1 f) (2 f) (i 3 f))))
+ (should (equal (funcall it) 0))
+ (should (equal (funcall it) "foo"))
+ (erc-d-exchange-rebind dialog exchange 'f "bar")
+ (should (equal (funcall it) 1))
+ (should (equal (funcall it) "bar"))
+ (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog))
+ (lambda nil "baz")))
+ (should (eq (funcall it) 2))
+ (should (equal (funcall it 'reload) "baz"))
+ (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog)) "spam"))
+ (should (eq (funcall it) 'i))
+ (should (eq (funcall it 'reload) 3))
+ (should (equal (funcall it) "\\`spam")))))
+
+(ert-deftest erc-d-t-with-cleanup ()
+ (should-not (get-buffer "*echo*"))
+ (should-not (get-buffer "*foo*"))
+ (should-not (get-buffer "*bar*"))
+ (should-not (get-buffer "*baz*"))
+ (erc-d-t-with-cleanup
+ ((echo (start-process "echo" (get-buffer-create "*echo*") "sleep" "1"))
+ (buffer-foo (get-buffer-create "*foo*"))
+ (buffer-bar (get-buffer-create "*bar*"))
+ (clean-up (list (intern (process-name echo)))) ; let*
+ buffer-baz)
+ (ert-info ("Clean Up")
+ (should (equal clean-up '(ran echo)))
+ (should (bufferp buffer-baz))
+ (should (bufferp buffer-foo))
+ (setq buffer-foo nil))
+ (setq buffer-baz (get-buffer-create "*baz*"))
+ (push 'ran clean-up))
+ (ert-info ("Buffers and procs destroyed")
+ (should-not (get-buffer "*echo*"))
+ (should-not (get-buffer "*bar*"))
+ (should-not (get-buffer "*baz*")))
+ (ert-info ("Buffer foo spared")
+ (should (get-buffer "*foo*"))
+ (kill-buffer "*foo*")))
+
+(ert-deftest erc-d-t-wait-for ()
+ :tags '(:unstable)
+ (let (v)
+ (run-at-time 0.2 nil (lambda () (setq v t)))
+ (should (erc-d-t-wait-for 0.4 "result becomes non-nil" v))
+ (should-error (erc-d-t-wait-for 0.4 "result stays nil" (not v)))
+ (setq v nil)
+ (should-not (erc-d-t-wait-for -0.4 "inverted stays nil" v))
+ (run-at-time 0.2 nil (lambda () (setq v t)))
+ (setq v nil)
+ (should-error (erc-d-t-wait-for -0.4 "inverted becomes non-nil" v))))
+
+(defvar erc-d-tests-with-server-password "changeme")
+
+;; Compromise between removing `autojoin' from `erc-modules' entirely
+;; and allowing side effects to meddle excessively
+(defvar erc-autojoin-channels-alist)
+
+;; This is only meant to be used by tests in this file.
+(cl-defmacro erc-d-tests-with-server ((dumb-server-var erc-server-buffer-var)
+ dialog &rest body)
+ "Create server for DIALOG and run BODY.
+DIALOG may also be a list of dialogs. ERC-SERVER-BUFFER-VAR and
+DUMB-SERVER-VAR are bound accordingly in BODY."
+ (declare (indent 2))
+ (when (eq '_ dumb-server-var)
+ (setq dumb-server-var (make-symbol "dumb-server-var")))
+ (when (eq '_ erc-server-buffer-var)
+ (setq erc-server-buffer-var (make-symbol "erc-server-buffer-var")))
+ (if (listp dialog)
+ (setq dialog (mapcar (lambda (f) (list 'quote f)) dialog))
+ (setq dialog `((quote ,dialog))))
+ `(let* (auth-source-do-cache
+ (,dumb-server-var (erc-d-run "localhost" t ,@dialog))
+ ,erc-server-buffer-var
+ ;;
+ (erc-server-flood-penalty 0.05)
+ erc-autojoin-channels-alist
+ erc-server-auto-reconnect)
+ (should-not erc-d--slow-mo)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ ;; Allow important messages through, even in -batch mode.
+ (advice-add #'erc-handle-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-server-connect :around #'erc-d-t-silence-around)
+ (unless (or noninteractive erc-debug-irc-protocol)
+ (erc-toggle-debug-irc-protocol))
+ (setq ,erc-server-buffer-var
+ (erc :server "localhost"
+ :password erc-d-tests-with-server-password
+ :port (process-contact ,dumb-server-var :service)
+ :nick "tester"
+ :full-name "tester"))
+ (unwind-protect
+ (progn
+ ,@body
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p ,dumb-server-var))))
+ (when (process-live-p erc-server-process)
+ (delete-process erc-server-process))
+ (advice-remove #'erc-handle-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-server-connect #'erc-d-t-silence-around)
+ (when noninteractive
+ (kill-buffer ,erc-server-buffer-var)
+ (erc-d-t-kill-related-buffers)))))
+
+(defmacro erc-d-tests-with-failure-spy (found func-syms &rest body)
+ "Wrap functions with advice for inspecting errors caused by BODY.
+Do this for functions whose names appear in FUNC-SYMS. When running
+advice code, add errors to list FOUND. Note: the teardown finalizer is
+not added by default. Also, `erc-d-linger-secs' likely has to be
+nonzero for this to work."
+ (declare (indent 2))
+ ;; Catch errors thrown by timers that `should-error'ignores
+ `(progn
+ (let ((ad (lambda (f o &rest r)
+ (condition-case err
+ (apply o r)
+ (error (push err ,found)
+ (advice-remove f 'spy))))))
+ (dolist (sym ,func-syms)
+ (advice-add sym :around (apply-partially ad sym) '((name . spy)))))
+ (progn ,@body)
+ (dolist (sym ,func-syms)
+ (advice-remove sym 'spy))
+ (setq ,found (nreverse ,found))))
+
+(ert-deftest erc-d-run-nonstandard-messages ()
+ :tags '(:expensive-test)
+ (let* ((erc-d-linger-secs 0.2)
+ (dumb-server (erc-d-run "localhost" t 'nonstandard))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (expect (erc-d-t-make-expecter))
+ client)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client (open-network-stream "erc-d-client" nil
+ "localhost"
+ (process-contact dumb-server :service)
+ :coding 'binary))
+ (ert-info ("Server splits CRLF delimited lines")
+ (process-send-string client "ONE one\r\nTWO two\r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(: "<- nonstandard:" (+ digit) " ONE one" eol))
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ TWO two$"))))
+ (ert-info ("Server doesn't discard empty lines")
+ (process-send-string client "\r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ $"))))
+ (ert-info ("Server preserves spaces")
+ (process-send-string client " \r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{2\\}$")))
+ (process-send-string client " \r\n")
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{3\\}$"))))
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client)
+ (when noninteractive
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-basic ()
+ :tags '(:expensive-test)
+ (erc-d-tests-with-server (_ _) basic
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (when noninteractive
+ (kill-buffer "#chan"))))
+
+(ert-deftest erc-d-run-eof ()
+ :tags '(:expensive-test)
+ (skip-unless noninteractive)
+ (erc-d-tests-with-server (_ erc-s-buf) eof
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (with-current-buffer erc-s-buf
+ (process-send-eof erc-server-process))))
+
+(ert-deftest erc-d-run-eof-fail ()
+ :tags '(:expensive-test)
+ (let (errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown)
+ (erc-d-tests-with-server (_ _) eof
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (erc-d-t-wait-for 10 errors)))
+ (should (string-match-p "Timed out awaiting request.*__EOF__"
+ (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-linger ()
+ :tags '(:expensive-test)
+ (erc-d-tests-with-server (dumb-s _) linger
+ (with-current-buffer (erc-d-t-wait-for 6 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey"))
+ (with-current-buffer (process-buffer dumb-s)
+ (erc-d-t-search-for 2 "Lingering for 1.00 seconds"))
+ (with-current-buffer (process-buffer dumb-s)
+ (erc-d-t-search-for 3 "Lingered for 1.00 seconds"))))
+
+(ert-deftest erc-d-run-linger-fail ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 0.1)
+ errors)
+ (erc-d-tests-with-failure-spy
+ errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ _) linger
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "hey")
+ (erc-cmd-MSG "#chan hi"))
+ (erc-d-t-wait-for 10 "Bad match" errors)))
+ (should (string-match-p "Match failed.*hi" (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-linger-direct ()
+ :tags '(:expensive-test)
+ (let* ((dumb-server (erc-d-run "localhost" t
+ 'linger-multi-a 'linger-multi-b))
+ (port (process-contact dumb-server :service))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer-a (get-buffer-create "*erc-d-client-a*"))
+ (client-buffer-b (get-buffer-create "*erc-d-client-b*"))
+ (start (current-time))
+ client-a client-b)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a
+ "localhost" port
+ :coding 'binary)
+ client-b (open-network-stream "erc-d-client-b" client-buffer-b
+ "localhost" port
+ :coding 'binary))
+ (process-send-string client-a "PASS :a\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-b "PASS :b\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (ert-info ("Ensure linger of one second")
+ (should (time-less-p 1 (time-subtract (current-time) start)))
+ (should (time-less-p (time-subtract (current-time) start) 1.5)))
+ (delete-process client-a)
+ (delete-process client-b)
+ (when noninteractive
+ (kill-buffer client-buffer-a)
+ (kill-buffer client-buffer-b)
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-drop-direct ()
+ :tags '(:unstable)
+ (let* ((dumb-server (erc-d-run "localhost" t 'drop-a 'drop-b))
+ (port (process-contact dumb-server :service))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer-a (get-buffer-create "*erc-d-client-a*"))
+ (client-buffer-b (get-buffer-create "*erc-d-client-b*"))
+ (start (current-time))
+ client-a client-b)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a
+ "localhost" port
+ :coding 'binary)
+ client-b (open-network-stream "erc-d-client-b" client-buffer-b
+ "localhost" port
+ :coding 'binary))
+ (process-send-string client-a "PASS :a\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-b "PASS :b\r\n")
+ (erc-d-t-wait-for 3 "client-a dies" (not (process-live-p client-a)))
+ (should (time-less-p (time-subtract (current-time) start) 0.32))
+ (erc-d-t-wait-for 3 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (ert-info ("Ensure linger of one second")
+ (should (time-less-p 1 (time-subtract (current-time) start))))
+ (delete-process client-a)
+ (delete-process client-b)
+ (when noninteractive
+ (kill-buffer client-buffer-a)
+ (kill-buffer client-buffer-b)
+ (kill-buffer dumb-server-buffer))))
+
+(ert-deftest erc-d-run-no-match ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 1)
+ erc-server-auto-reconnect
+ errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ erc-server-buffer) no-match
+ (with-current-buffer erc-server-buffer
+ (erc-d-t-search-for 2 "away")
+ (erc-cmd-JOIN "#foo")
+ (erc-d-t-wait-for 10 "Bad match" errors))))
+ (should (string-match-p "Match failed.*foo.*chan" (cadr (pop errors))))
+ (should-not (get-buffer "#foo"))))
+
+(ert-deftest erc-d-run-timeout ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 1)
+ err errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown)
+ (erc-d-tests-with-server (_ _) timeout
+ (erc-d-t-wait-for 10 "error caught" errors)))
+ (setq err (pop errors))
+ (should (eq (car err) 'erc-d-timeout))
+ (should (string-match-p "Timed out" (cadr err)))))
+
+(ert-deftest erc-d-run-unexpected ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 2)
+ errors)
+ (erc-d-tests-with-failure-spy
+ errors '(erc-d--teardown erc-d-command)
+ (erc-d-tests-with-server (_ _) unexpected
+ (ert-info ("All specs consumed when more input arrives")
+ (erc-d-t-wait-for 10 "error caught" (cdr errors)))))
+ (should (string-match-p "unexpected.*MODE" (cadr (pop errors))))
+ ;; Nonsensical normally because func would have already exited when
+ ;; first error was thrown
+ (should (string-match-p "Match failed" (cadr (pop errors))))))
+
+(ert-deftest erc-d-run-unexpected-depleted ()
+ :tags '(:expensive-test)
+ (let ((erc-d-linger-secs 3)
+ errors)
+ (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command)
+ (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (dumb-server (erc-d-run "localhost" t 'depleted))
+ (expect (erc-d-t-make-expecter))
+ (client-buf (get-buffer-create "*erc-d-client*"))
+ client-proc)
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (setq client-proc (make-network-process
+ :buffer client-buf
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-proc "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (when (process-live-p client-proc)
+ (process-send-string client-proc "BLAH :too much\r\n")
+ (sleep-for 0.01))
+ (with-current-buffer client-buf
+ (funcall expect 3 "Welcome to the Internet"))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-proc)
+ (when noninteractive
+ (kill-buffer client-buf)
+ (kill-buffer dumb-server-buffer))))
+ (should (string-match-p "unexpected.*BLAH" (cadr (pop errors))))
+ ;; Wouldn't happen IRL
+ (should (string-match-p "unexpected.*BLAH" (cadr (pop errors))))
+ (should-not errors)))
+
+(defun erc-d-tests--dynamic-match-user (_dialog exchange)
+ "Shared pattern/response handler for canned dynamic DIALOG test."
+ (should (string= (match-string 1 (erc-d-exchange-request exchange))
+ "tester")))
+
+(defun erc-d-tests--run-dynamic ()
+ "Perform common assertions for \"dynamic\" dialog."
+ (erc-d-tests-with-server (dumb-server erc-server-buffer) dynamic
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "tester: hey"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.fsf.org")
+ (funcall expect 2 "modes for tester")))
+ (with-current-buffer (process-buffer dumb-server)
+ (erc-d-t-search-for 2 "irc.fsf.org"))
+ (when noninteractive
+ (kill-buffer "#chan"))))
+
+(ert-deftest erc-d-run-dynamic-default-match ()
+ :tags '(:expensive-test)
+ (let* (dynamic-tally
+ (erc-d-tmpl-vars '((user . "user")
+ (ignored . ((a b) (: a space b)))
+ (realname . (group (+ graph)))))
+ (nick (lambda (a)
+ (push '(nick . match-user) dynamic-tally)
+ (funcall a :set (funcall a :match 1) 'export)))
+ (dom (lambda (a)
+ (push '(dom . match-user) dynamic-tally)
+ (funcall a :set erc-d-server-fqdn)))
+ (erc-d-match-handlers
+ (list :user (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick nick)
+ (erc-d-exchange-rebind d e 'dom dom)
+ (erc-d-tests--dynamic-match-user d e))
+ :mode-user (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick "tester")
+ (erc-d-exchange-rebind d e 'dom dom))))
+ (erc-d-server-fqdn "irc.fsf.org"))
+ (erc-d-tests--run-dynamic)
+ (should (equal '((dom . match-user) (nick . match-user) (dom . match-user))
+ dynamic-tally))))
+
+(ert-deftest erc-d-run-dynamic-default-match-rebind ()
+ :tags '(:expensive-test)
+ (let* (tally
+ ;;
+ (erc-d-tmpl-vars '((user . "user")
+ (ignored . ((a b) (: a space b)))
+ (realname . (group (+ graph)))))
+ (erc-d-match-handlers
+ (list :user
+ (lambda (d e)
+ (erc-d-exchange-rebind
+ d e 'nick
+ (lambda (a)
+ (push 'bind-nick tally)
+ (funcall a :rebind 'nick (funcall a :match 1) 'export)))
+ (erc-d-exchange-rebind
+ d e 'dom
+ (lambda ()
+ (push 'bind-dom tally)
+ (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn)))
+ (erc-d-tests--dynamic-match-user d e))
+ :mode-user
+ (lambda (d e)
+ (erc-d-exchange-rebind d e 'nick "tester")
+ (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn))))
+ (erc-d-server-fqdn "irc.fsf.org"))
+ (erc-d-tests--run-dynamic)
+ (should (equal '(bind-nick bind-dom) tally))))
+
+(ert-deftest erc-d-run-dynamic-runtime-stub ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . (group (or "barnet" "foonet")))))
+ (erc-d-match-handlers
+ (list :pass (lambda (d _e)
+ (erc-d-load-replacement-dialog d 'dynamic-foonet))))
+ (erc-d-tests-with-server-password "foonet:changeme"))
+ (erc-d-tests-with-server (_ erc-server-buffer)
+ (dynamic-stub dynamic-foonet)
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "alice:")
+ (erc-d-t-absent-for 0.1 "joe"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.foonet.org")
+ (funcall expect 2 "NETWORK=FooNet")))
+ (when noninteractive
+ (kill-buffer "#chan")))))
+
+(ert-deftest erc-d-run-dynamic-runtime-stub-skip ()
+ :tags '(:expensive-test)
+ (let ((erc-d-tmpl-vars '((token . "barnet")))
+ (erc-d-match-handlers
+ (list :pass (lambda (d _e)
+ (erc-d-load-replacement-dialog
+ d 'dynamic-barnet 1))))
+ (erc-d-tests-with-server-password "barnet:changeme"))
+ (erc-d-tests-with-server (_ erc-server-buffer)
+ (dynamic-stub dynamic-barnet)
+ (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan"))
+ (erc-d-t-search-for 2 "joe:")
+ (erc-d-t-absent-for 0.1 "alice"))
+ (with-current-buffer erc-server-buffer
+ (let ((expect (erc-d-t-make-expecter)))
+ (funcall expect 2 "host is irc.barnet.org")
+ (funcall expect 2 "NETWORK=BarNet")))
+ (when noninteractive
+ (kill-buffer "#chan")))))
+
+;; Two servers, in-process, one client per
+(ert-deftest erc-d-run-dual-direct ()
+ :tags '(:expensive-test)
+ (let* ((erc-d--slow-mo -1)
+ (server-a (erc-d-run "localhost" t "erc-d-server-a" 'dynamic-foonet))
+ (server-b (erc-d-run "localhost" t "erc-d-server-b" 'dynamic-barnet))
+ (server-a-buffer (get-buffer "*erc-d-server-a*"))
+ (server-b-buffer (get-buffer "*erc-d-server-b*"))
+ (client-a-buffer (get-buffer-create "*erc-d-client-a*"))
+ (client-b-buffer (get-buffer-create "*erc-d-client-b*"))
+ client-a client-b)
+ (with-current-buffer server-a-buffer (erc-d-t-search-for 4 "Starting"))
+ (with-current-buffer server-b-buffer (erc-d-t-search-for 4 "Starting"))
+ (setq client-a (make-network-process
+ :buffer client-a-buffer
+ :name "erc-d-client-a"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact server-a :service)
+ :host "localhost")
+ client-b (make-network-process
+ :buffer client-b-buffer
+ :name "erc-d-client-b"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact server-b :service)
+ :host "localhost"))
+ ;; Also tests slo-mo indirectly because FAKE would fail without it
+ (process-send-string client-a "NICK tester\r\n")
+ (process-send-string client-b "FAKE noop\r\nNICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "USER user 0 * :tester\r\n")
+ (process-send-string client-b "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "MODE tester +i\r\n")
+ (process-send-string client-b "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-a "MODE #chan\r\n")
+ (process-send-string client-b "MODE #chan\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 2 "server-a death" (not (process-live-p server-a)))
+ (erc-d-t-wait-for 2 "server-b death" (not (process-live-p server-b)))
+ (when noninteractive
+ (kill-buffer client-a-buffer)
+ (kill-buffer client-b-buffer)
+ (kill-buffer server-a-buffer)
+ (kill-buffer server-b-buffer))))
+
+;; This can be removed; only exists to get a baseline for next test
+(ert-deftest erc-d-run-fuzzy-direct ()
+ :tags '(:expensive-test)
+ (let* ((erc-d-tmpl-vars
+ `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t)))))
+ (dumb-server (erc-d-run "localhost" t 'fuzzy))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer (get-buffer-create "*erc-d-client*"))
+ client)
+ (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting"))
+ (setq client (make-network-process
+ :buffer client-buffer
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ ;; We could also just send this as a single fatty
+ (process-send-string client "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "JOIN #bar\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "JOIN #foo\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #bar\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #foo\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (when noninteractive
+ (kill-buffer client-buffer)
+ (kill-buffer dumb-server-buffer))))
+
+;; Without adjusting penalty, takes ~15 secs. With is comprable to direct ^.
+(ert-deftest erc-d-run-fuzzy ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 1.2) ; penalty < margin/sends is basically 0
+ (erc-d-linger-secs 0.1)
+ (erc-d-tmpl-vars
+ `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t)))))
+ erc-server-auto-reconnect)
+ (erc-d-tests-with-server (_ erc-server-buffer) fuzzy
+ (with-current-buffer erc-server-buffer
+ (erc-d-t-search-for 2 "away")
+ (goto-char erc-input-marker)
+ (erc-cmd-JOIN "#bar"))
+ (erc-d-t-wait-for 2 (get-buffer "#bar"))
+ (with-current-buffer erc-server-buffer
+ (erc-cmd-JOIN "#foo"))
+ (erc-d-t-wait-for 20 (get-buffer "#foo"))
+ (with-current-buffer "#bar"
+ (erc-d-t-search-for 1 "was created on"))
+ (with-current-buffer "#foo"
+ (erc-d-t-search-for 5 "was created on")))))
+
+(ert-deftest erc-d-run-no-block ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 1)
+ (erc-d-linger-secs 1.2)
+ (expect (erc-d-t-make-expecter))
+ erc-server-auto-reconnect)
+ (erc-d-tests-with-server (_ erc-server-buffer) no-block
+ (with-current-buffer erc-server-buffer
+ (funcall expect 2 "away")
+ (funcall expect 1 erc-prompt)
+ (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#foo")))
+ (with-current-buffer (erc-d-t-wait-for 2 (get-buffer "#foo"))
+ (funcall expect 2 "was created on"))
+
+ (ert-info ("Join #bar")
+ (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#bar"))
+ (erc-d-t-wait-for 2 (get-buffer "#bar")))
+
+ (with-current-buffer "#bar" (funcall expect 1 "was created on"))
+
+ (ert-info ("Server expects next pattern but keeps sending")
+ (with-current-buffer "#foo" (funcall expect 2 "Rosalind, I will "))
+ (with-current-buffer "#bar" (funcall expect 1 "hi 123"))
+ (with-current-buffer "#foo"
+ (should-not (search-forward "<bob> I am heard" nil t))
+ (funcall expect 1.5 "<bob> I am heard"))))))
+
+(defun erc-d-tests--run-proxy-direct (dumb-server dumb-server-buffer port)
+ "Start DUMB-SERVER with DUMB-SERVER-BUFFER and PORT.
+These are steps shared by in-proc and subproc variants testing a
+bouncer-like setup."
+ (when (version< emacs-version "28") (ert-skip "TODO connection refused"))
+ (let ((client-buffer-foo (get-buffer-create "*erc-d-client-foo*"))
+ (client-buffer-bar (get-buffer-create "*erc-d-client-bar*"))
+ (expect (erc-d-t-make-expecter))
+ client-foo
+ client-bar)
+ (setq client-foo (make-network-process
+ :buffer client-buffer-foo
+ :name "erc-d-client-foo"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service port
+ :host "localhost")
+ client-bar (make-network-process
+ :buffer client-buffer-bar
+ :name "erc-d-client-bar"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service port
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-foo "PASS :foo:changeme\r\n")
+ (process-send-string client-bar "PASS :bar:changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "NICK tester\r\n")
+ (process-send-string client-bar "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "USER user 0 * :tester\r\n")
+ (process-send-string client-bar "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-foo "MODE tester +i\r\n")
+ (process-send-string client-bar "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (with-current-buffer client-buffer-foo
+ (funcall expect 3 "FooNet")
+ (funcall expect 3 "irc.foo.net")
+ (funcall expect 3 "marked as being away")
+ (goto-char (point-min))
+ (should-not (search-forward "bar" nil t)))
+ (with-current-buffer client-buffer-bar
+ (funcall expect 3 "BarNet")
+ (funcall expect 3 "irc.bar.net")
+ (funcall expect 3 "marked as being away")
+ (goto-char (point-min))
+ (should-not (search-forward "foo" nil t)))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-foo)
+ (delete-process client-bar)
+ (when noninteractive
+ (kill-buffer client-buffer-foo)
+ (kill-buffer client-buffer-bar)
+ (kill-buffer dumb-server-buffer))))
+
+;; This test shows the simplest way to set up template variables: put
+;; everything needed for the whole session in `erc-d-tmpl-vars' before
+;; starting the server.
+
+(ert-deftest erc-d-run-proxy-direct-spec-vars ()
+ :tags '(:expensive-test)
+ (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (erc-d-linger-secs 0.5)
+ (erc-d-tmpl-vars
+ `((network . (group (+ alpha)))
+ (fqdn . ,(lambda (a)
+ (let ((network (funcall a :match 1 'pass)))
+ (should (member network '("foo" "bar")))
+ (funcall a :set (concat "irc." network ".net")))))
+ (net . ,(lambda (a)
+ (let ((network (funcall a :match 1 'pass)))
+ (should (member network '("foo" "bar")))
+ (concat (capitalize network) "Net"))))))
+ (dumb-server (erc-d-run "localhost" t 'proxy-foonet 'proxy-barnet))
+ (port (process-contact dumb-server :service)))
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (erc-d-tests--run-proxy-direct dumb-server dumb-server-buffer port)))
+
+(cl-defun erc-d-tests--start-server (&key dialogs buffer linger program libs)
+ "Start and return a server in a subprocess using BUFFER and PORT.
+DIALOGS are symbols representing the base names of dialog files in
+`erc-d-u-canned-dialog-dir'. LIBS are extra files to load."
+ (push (locate-library "erc-d" nil (list erc-d-u--library-directory)) libs)
+ (cl-assert (car libs))
+ (let* ((args `("erc-d-server" ,buffer
+ ,(concat invocation-directory invocation-name)
+ "-Q" "-batch" "-L" ,erc-d-u--library-directory
+ ,@(let (o) (while libs (push (pop libs) o) (push "-l" o)) o)
+ "-eval" ,(format "%S" program) "-f" "erc-d-serve"
+ ,@(when linger (list "--linger" (number-to-string linger)))
+ ,@(mapcar #'erc-d-u--expand-dialog-symbol dialogs)))
+ (proc (apply #'start-process args)))
+ (set-process-query-on-exit-flag proc nil)
+ (with-current-buffer buffer
+ (erc-d-t-search-for 5 "Starting")
+ (search-forward " (")
+ (backward-char))
+ (let ((pair (read buffer)))
+ (cons proc (cdr pair)))))
+
+(ert-deftest erc-d-run-proxy-direct-subprocess ()
+ :tags '(:expensive-test)
+ (let* ((buffer (get-buffer-create "*erc-d-server*"))
+ ;; These are quoted because they're passed as printed forms to subproc
+ (fqdn '(lambda (a e)
+ (let* ((d (erc-d-exchange-dialog e))
+ (name (erc-d-dialog-name d)))
+ (funcall a :set (if (eq name 'proxy-foonet)
+ "irc.foo.net"
+ "irc.bar.net")))))
+ (net '(lambda (a)
+ (funcall a :rebind 'net
+ (if (eq (funcall a :dialog-name) 'proxy-foonet)
+ "FooNet"
+ "BarNet"))))
+ (program `(setq erc-d-tmpl-vars '((fqdn . ,fqdn)
+ (net . ,net)
+ (network . (group (+ alpha))))))
+ (port (erc-d-tests--start-server
+ :linger 0.3
+ :program program
+ :buffer buffer
+ :dialogs '(proxy-foonet proxy-barnet)))
+ (server (pop port)))
+ (erc-d-tests--run-proxy-direct server buffer port)))
+
+(ert-deftest erc-d-run-proxy-direct-subprocess-lib ()
+ :tags '(:expensive-test)
+ (let* ((buffer (get-buffer-create "*erc-d-server*"))
+ (lib (expand-file-name "proxy-subprocess.el"
+ (ert-resource-directory)))
+ (port (erc-d-tests--start-server :linger 0.3
+ :buffer buffer
+ :dialogs '(proxy-foonet proxy-barnet)
+ :libs (list lib)))
+ (server (pop port)))
+ (erc-d-tests--run-proxy-direct server buffer port)))
+
+(ert-deftest erc-d-run-no-pong ()
+ :tags '(:expensive-test)
+ (let* (erc-d-auto-pong
+ ;;
+ (erc-d-tmpl-vars
+ `((nonce . (group (: digit digit)))
+ (echo . ,(lambda (a)
+ (should (string= (funcall a :match 1) "42")) "42"))))
+ (dumb-server-buffer (get-buffer-create "*erc-d-server*"))
+ (dumb-server (erc-d-run "localhost" t 'no-pong))
+ (expect (erc-d-t-make-expecter))
+ (client-buf (get-buffer-create "*erc-d-client*"))
+ client-proc)
+ (with-current-buffer dumb-server-buffer
+ (erc-d-t-search-for 3 "Starting"))
+ (setq client-proc (make-network-process
+ :buffer client-buf
+ :name "erc-d-client"
+ :family 'ipv4
+ :noquery t
+ :coding 'binary
+ :service (process-contact dumb-server :service)
+ :host "localhost"))
+ (with-current-buffer dumb-server-buffer
+ (funcall expect 3 "open from"))
+ (process-send-string client-proc "PASS :changeme\r\nNICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "USER user 0 * :tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client-proc "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (with-current-buffer client-buf
+ (funcall expect 3 "ExampleOrg")
+ (funcall expect 3 "irc.example.org")
+ (funcall expect 3 "marked as being away"))
+ (ert-info ("PING is not intercepted by specialized method")
+ (process-send-string client-proc "PING 42\r\n")
+ (with-current-buffer client-buf
+ (funcall expect 3 "PONG")))
+ (erc-d-t-wait-for 2 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (delete-process client-proc)
+ (when noninteractive
+ (kill-buffer client-buf)
+ (kill-buffer dumb-server-buffer))))
+
+;; Inspect replies as they arrive within a single exchange, i.e., ensure we
+;; don't regress to prior buggy version in which inspection wasn't possible
+;; until all replies had been sent by the server.
+(ert-deftest erc-d-run-incremental ()
+ :tags '(:expensive-test)
+ (let ((erc-server-flood-penalty 0)
+ (expect (erc-d-t-make-expecter))
+ erc-d-linger-secs)
+ (erc-d-tests-with-server (_ erc-server-buffer) incremental
+ (with-current-buffer erc-server-buffer
+ (funcall expect 3 "marked as being away"))
+ (with-current-buffer erc-server-buffer
+ (erc-cmd-JOIN "#foo"))
+ (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
+ (funcall expect 1 "Users on #foo")
+ (funcall expect 1 "Look for me")
+ (not (search-forward "Done" nil t))
+ (funcall expect 10 "Done")
+ (erc-send-message "Hi")))))
+
+(ert-deftest erc-d-unix-socket-direct ()
+ :tags '(:expensive-test)
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ (let* ((erc-d-linger-secs 0.1)
+ (sock (expand-file-name "erc-d.sock" temporary-file-directory))
+ (dumb-server (erc-d-run nil sock 'basic))
+ (dumb-server-buffer (get-buffer "*erc-d-server*"))
+ (client-buffer (get-buffer-create "*erc-d-client*"))
+ client)
+ (with-current-buffer "*erc-d-server*"
+ (erc-d-t-search-for 4 "Starting"))
+ (unwind-protect
+ (progn
+ (setq client (make-network-process
+ :buffer client-buffer
+ :name "erc-d-client"
+ :family 'local
+ :noquery t
+ :coding 'binary
+ :service sock))
+ (process-send-string client "PASS :changeme\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "NICK tester\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "USER user 0 * :tester\r\n")
+ (sleep-for 0.1)
+ (process-send-string client "MODE tester +i\r\n")
+ (sleep-for 0.01)
+ (process-send-string client "MODE #chan\r\n")
+ (sleep-for 0.01)
+ (erc-d-t-wait-for 1 "dumb-server death"
+ (not (process-live-p dumb-server)))
+ (when noninteractive
+ (kill-buffer client-buffer)
+ (kill-buffer dumb-server-buffer)))
+ (delete-file sock))))
+
+;;; erc-d-tests.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d-u.el b/test/lisp/erc/resources/erc-d/erc-d-u.el
new file mode 100644
index 00000000000..ce13efef624
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d-u.el
@@ -0,0 +1,213 @@
+;;; erc-d-u.el --- Helpers for ERC test server -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The utilities here are kept separate from those in `erc-d' so that
+;; tests running the server in a subprocess can use them without
+;; having to require the main lib. If migrating outside of test/lisp,
+;; there may be no reason to continue this.
+;;
+;; Another (perhaps misguided) goal here is to avoid having ERC itself
+;; as a dependency.
+;;
+;; FIXME this ^ is no longer the case (ERC is not a dependency)
+
+;;; Code:
+(require 'rx)
+(require 'subr-x)
+(eval-when-compile (require 'ert))
+
+(defvar erc-d-u--canned-buffers nil
+ "List of canned dialog buffers currently open for reading.")
+
+(cl-defstruct (erc-d-u-scan-d) ; dialog scanner
+ (buf nil :type buffer)
+ (done nil :type boolean)
+ (last nil :type integer)
+ (hunks nil :type (list-of marker))
+ (f #'erc-d-u--read-exchange-default :type function))
+
+(cl-defstruct (erc-d-u-scan-e) ; exchange scanner
+ (sd nil :type erc-d-u-scan-d)
+ (pos nil :type marker))
+
+(defun erc-d-u--read-dialog (info)
+ "Read dialog file and stash relevant state in `erc-d-u-scan-d' INFO."
+ (if (and (buffer-live-p (erc-d-u-scan-d-buf info))
+ (with-current-buffer (erc-d-u-scan-d-buf info)
+ (condition-case _err
+ (progn
+ (when (erc-d-u-scan-d-last info)
+ (goto-char (erc-d-u-scan-d-last info))
+ (forward-list))
+ (setf (erc-d-u-scan-d-last info) (point))
+ (down-list)
+ (push (set-marker (make-marker) (point))
+ (erc-d-u-scan-d-hunks info)))
+ ((end-of-buffer scan-error)
+ (setf (erc-d-u-scan-d-done info) t)
+ nil))))
+ (make-erc-d-u-scan-e :sd info :pos (car (erc-d-u-scan-d-hunks info)))
+ (unless (erc-d-u-scan-d-hunks info)
+ (kill-buffer (erc-d-u-scan-d-buf info))
+ nil)))
+
+(defun erc-d-u--read-exchange-default (info)
+ "Read from marker in exchange `erc-d-u-scan-e' object INFO."
+ (let ((hunks (erc-d-u-scan-e-sd info))
+ (pos (erc-d-u-scan-e-pos info)))
+ (or (and (erc-d-u-scan-d-hunks hunks)
+ (with-current-buffer (erc-d-u-scan-d-buf hunks)
+ (goto-char pos)
+ (condition-case _err
+ (read pos)
+ ;; Raised unless malformed
+ (invalid-read-syntax
+ nil))))
+ (unless (or (cl-callf (lambda (s) (delq pos s)) ; flip
+ (erc-d-u-scan-d-hunks hunks))
+ (not (erc-d-u-scan-d-done hunks)))
+ (kill-buffer (erc-d-u-scan-d-buf hunks))
+ nil))))
+
+(defun erc-d-u--read-exchange (info)
+ "Call exchange reader assigned in `erc-d-u-scan-e' object INFO."
+ (funcall (erc-d-u-scan-d-f (erc-d-u-scan-e-sd info)) info))
+
+(defun erc-d-u--canned-read (file)
+ "Dispense a reader for each exchange in dialog FILE."
+ (let ((buf (generate-new-buffer (file-name-nondirectory file))))
+ (push buf erc-d-u--canned-buffers)
+ (with-current-buffer buf
+ (setq-local parse-sexp-ignore-comments t
+ coding-system-for-read 'utf-8)
+ (add-hook 'kill-buffer-hook
+ (lambda () (setq erc-d-u--canned-buffers
+ (delq buf erc-d-u--canned-buffers)))
+ nil 'local)
+ (insert-file-contents-literally file)
+ (lisp-data-mode))
+ (make-erc-d-u-scan-d :buf buf)))
+
+(defvar erc-d-u--library-directory (file-name-directory load-file-name))
+(defvar erc-d-u-canned-dialog-dir
+ (file-name-as-directory (expand-file-name "resources"
+ erc-d-u--library-directory)))
+
+(defun erc-d-u--normalize-canned-name (dialog)
+ "Return DIALOG name as a symbol without validating it."
+ (if (symbolp dialog)
+ dialog
+ (intern (file-name-base dialog))))
+
+(defvar erc-d-u-canned-file-name-extension ".eld")
+
+(defun erc-d-u--expand-dialog-symbol (dialog)
+ "Return filename based on symbol DIALOG."
+ (let ((name (symbol-name dialog)))
+ (unless (equal (file-name-extension name)
+ erc-d-u-canned-file-name-extension)
+ (setq name (concat name erc-d-u-canned-file-name-extension)))
+ (expand-file-name name erc-d-u-canned-dialog-dir)))
+
+(defun erc-d-u--massage-canned-name (dialog)
+ "Return DIALOG in a form acceptable to `erc-d-run'."
+ (if (or (symbolp dialog) (file-exists-p dialog))
+ dialog
+ (erc-d-u--expand-dialog-symbol (intern dialog))))
+
+(defun erc-d-u--canned-load-dialog (dialog)
+ "Load dispensing exchanges from DIALOG.
+If DIALOG is a string, consider it a filename. Otherwise find a file
+in `erc-d-u-canned-dialog-dir' with a base name matching the symbol's
+name.
+
+Return an iterator that yields exchanges, each one an iterator of spec
+forms. The first is a so-called request spec and the rest are composed
+of zero or more response specs."
+ (when (symbolp dialog)
+ (setq dialog (erc-d-u--expand-dialog-symbol dialog)))
+ (unless (file-exists-p dialog)
+ (error "File not found: %s" dialog))
+ (erc-d-u--canned-read dialog))
+
+(defun erc-d-u--read-exchange-slowly (num orig info)
+ (when-let ((spec (funcall orig info)))
+ (when (symbolp (car spec))
+ (setf spec (copy-sequence spec)
+ (nth 1 spec) (cond ((functionp num) (funcall num (nth 1 spec)))
+ ((< num 0) (max (nth 1 spec) (- num)))
+ (t (+ (nth 1 spec) num)))))
+ spec))
+
+(defun erc-d-u--rewrite-for-slow-mo (num read-info)
+ "Return READ-INFO with a modified reader.
+When NUM is a positive number, delay incoming requests by NUM more
+seconds. If NUM is negative, raise insufficient incoming delays to at
+least -NUM seconds. If NUM is a function, set each delay to whatever it
+returns when called with the existing value."
+ (let ((orig (erc-d-u-scan-d-f read-info)))
+ (setf (erc-d-u-scan-d-f read-info)
+ (apply-partially #'erc-d-u--read-exchange-slowly num orig))
+ read-info))
+
+(defun erc-d-u--get-remote-port (process)
+ "Return peer TCP port for client PROCESS.
+When absent, just generate an id."
+ (let ((remote (plist-get (process-contact process t) :remote)))
+ (if (vectorp remote)
+ (aref remote (1- (length remote)))
+ (format "%s:%d" (process-contact process :local)
+ (logand 1023 (time-convert nil 'integer))))))
+
+(defun erc-d-u--format-bind-address (process)
+ "Return string or (STRING . INT) for bind address of network PROCESS."
+ (let ((local (process-contact process :local)))
+ (if (vectorp local) ; inet
+ (cons (mapconcat #'number-to-string (seq-subseq local 0 -1) ".")
+ (aref local (1- (length local))))
+ local)))
+
+(defun erc-d-u--unkeyword (plist)
+ "Return a copy of PLIST with keywords keys converted to non-keywords."
+ (cl-loop for (key value) on plist by #'cddr
+ when (keywordp key)
+ do (setq key (intern (substring (symbol-name key) 1)))
+ append (list key value)))
+
+(defun erc-d-u--massage-rx-args (key val)
+ " Massage val so it's suitable for an `rx-let' binding.
+Handle cases in which VAL is ([ARGLIST] RX-FORM) rather than just
+RX-FORM. KEY becomes the binding name."
+ (if (and (listp val)
+ (cdr val)
+ (not (cddr val))
+ (consp (car val)))
+ (cons key val)
+ (list key val)))
+
+(defvar-local erc-d-u--process-buffer nil
+ "Beacon for erc-d process buffers.
+The server process is usually deleted first, but we may want to examine
+the buffer afterward.")
+
+(provide 'erc-d-u)
+;;; erc-d-u.el ends here
diff --git a/test/lisp/erc/resources/erc-d/erc-d.el b/test/lisp/erc/resources/erc-d/erc-d.el
new file mode 100644
index 00000000000..ee9b6a7fec9
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/erc-d.el
@@ -0,0 +1,997 @@
+;;; erc-d.el --- A dumb test server for ERC -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is a netcat style server for testing ERC. The "d" in the name
+;; stands for "daemon" as well as for "dialog" (as well as for "dumb"
+;; because this server isn't very smart). It either spits out a
+;; canned reply when an incoming request matches the expected regexp
+;; or signals an error and dies. The entry point function is
+;; `erc-d-run'.
+;;
+;; Canned scripts, or "dialogs," should be Lisp-Data files containing
+;; one or more request/reply forms like this:
+;;
+;; | ((mode-chan 1.5 "MODE #chan") ; request: tag, expr, regex
+;; | (0.1 ":irc.org 324 bob #chan +Cint") ; reply: delay, content
+;; | (0.0 ":irc.org 329 bob #chan 12345")) ; reply: ...
+;;
+;; These are referred to as "exchanges." The first element is a list
+;; whose CAR is a descriptive "tag" and whose CDR is an incoming
+;; "spec" representing an inbound message from the client. The rest
+;; of the exchange is composed of outgoing specs representing
+;; server-to-client messages. A tag can be any symbol (ideally unique
+;; in the dialog), but a leading tilde means the request should be
+;; allowed to arrive out of order (within the allotted time).
+;;
+;; The first element in an incoming spec is a number indicating the
+;; maximum number of seconds to wait for a match before raising an
+;; error. The CDR is interpreted as the collective arguments of an
+;; `rx' form to be matched against the raw request (stripped of its
+;; CRLF line ending). A "string-start" backslash assertion, "\\`", is
+;; prepended to all patterns.
+;;
+;; Similarly, the leading number in an *outgoing* spec indicates how
+;; many seconds to wait before sending the line, which is rendered by
+;; concatenating the other members after evaluating each in place.
+;; CRLF line endings are appended on the way out and should be absent.
+;;
+;; Recall that IRC is "asynchronous," meaning some flow intervals
+;; don't jibe with lockstep request-reply semantics. However, for our
+;; purposes, grouping things as [input, output1, ..., outputN] makes
+;; sense, even though input and output may be completely unrelated.
+;;
+;; Template interpolation:
+;;
+;; A rudimentary templating facility is provided for additional
+;; flexibility. However, it's best to keep things simple (even if
+;; overly verbose), so others can easily tell what's going on at a
+;; glance. If necessary, consult existing tests for examples (grep
+;; for the variables `erc-d-tmpl-vars' and `erc-d-match-handlers').
+;;
+;; Subprocess or in-process?:
+;;
+;; Running in-process confers better visibility and easier setup at
+;; the cost of additional cleanup and resource wrangling. With a
+;; subprocess, cleanup happens by pulling the plug, but configuration
+;; means loading a separate file or passing -eval "(forms...)" during
+;; invocation. In some cases, a subprocess may be the only option,
+;; like when trying to avoid `require'ing this file.
+;;
+;; Dialog objects:
+;;
+;; For a given exchange, the first argument passed to a request
+;; handler is the `erc-d-dialog' object representing the overall
+;; conversation with the connecting peer. It can be used to pass
+;; information between handlers during a session. Some important
+;; items are:
+;;
+;; * name (symbol); name of the current dialog
+;;
+;; * queue (ring); a backlog of unhandled raw requests, minus CRLF
+;; endings.
+;;
+;; * timers (list of timers); when run, these send messages originally
+;; deferred as per the most recently matched exchange's delay info.
+;; Normally, all outgoing messages must be sent before another request
+;; is considered. (See `erc-d--send-outgoing' for an escape hatch.)
+;;
+;; * hunks (iterator of iterators); unconsumed exchanges as read from
+;; a Lisp-Data dialog file. The exchange iterators being dispensed
+;; themselves yield portions of member forms as a 2- or 3-part
+;; sequence: [tag] spec. (Here, "hunk" just means "list of raw,
+;; unrendered exchange elements")
+;;
+;; * vars (alist of cons pairs); for sharing state among template
+;; functions during the lifetime of an exchange. Initially populated
+;; by `erc-d-tmpl-vars', these KEY/VALUE pairs are expanded in the
+;; templates and optionally updated by "exchange handlers" (see
+;; `erc-d-match-handlers'). When VALUE is a function, occurrences of
+;; KEY in an outgoing spec are replaced with the result of calling
+;; VALUE with match data set appropriately. See
+;; `erc-d--render-entries' for details.
+;;
+;; * exchanges (ring of erc-d-exchange objects); activated hunks
+;; allowed to match out of order, plus the current active exchange
+;; being yielded from, if any. See `erc-d-exchange'.
+;;
+;; TODO
+;;
+;; - Remove un(der)used functionality and simplify API
+;; - Maybe migrate d-u and d-i dependencies here
+
+;;; Code:
+(eval-and-compile
+ (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name)))
+ (load-path (cons (directory-file-name d) load-path)))
+ (require 'erc-d-i)
+ (require 'erc-d-u)))
+
+(require 'ring)
+
+(defvar erc-d-server-name "erc-d-server"
+ "Default name of a server process and basis for its buffer name.
+Only relevant when starting a server with `erc-d-run'.")
+
+(defvar erc-d-server-fqdn "irc.example.org"
+ "Usually the same as the server's RPL_MYINFO \"announced name\".
+Possibly used by overriding handlers, like the one for PING, and/or
+dialog templates for the sender portion of a reply message.")
+
+(defvar erc-d-linger-secs nil
+ "Seconds to wait before quitting for all dialogs.
+For more granular control, use the provided LINGER `rx' variable (alone)
+as the incoming template spec of a dialog's last exchange.")
+
+(defvar erc-d-tmpl-vars nil
+ "An alist of template bindings available to client dialogs.
+Populate it when calling `erc-d-run', and the contents will be made
+available to all client dialogs through the `erc-d-dialog' \"vars\"
+field and (therefore) to all templates as variables when rendering. For
+example, a key/value pair like (network . \"oftc\") will cause instances
+of the (unquoted) symbol `network' to be replaced with \"oftc\" in the
+rendered template string.
+
+This list provides default template bindings common to all dialogs.
+Each new client-connection process makes a shallow copy on init, but the
+usual precautions apply when mutating member items. Within the span of
+a dialog, updates not applicable to all exchanges should die with their
+exchange. See `erc-d--render-entries' for details. In the unlikely
+event that an exchange-specific handler is needed, see
+`erc-d-match-handlers'.")
+
+(defvar erc-d-match-handlers nil
+ "A plist of exchange-tag symbols mapped to request-handler functions.
+This is meant to address edge cases for which `erc-d-tmpl-vars' comes up
+short. These may include (1) needing access to the client process
+itself and/or (2) adding or altering outgoing response templates before
+rendering. Note that (2) requires using `erc-d-exchange-rebind' instead
+of manipulating exchange bindings directly.
+
+The hook-like function `erc-d-on-match' calls any handler whose key is
+`eq' to the tag of the currently matched exchange (passing the client
+`erc-d-dialog' as the first argument and the current `erc-d-exchange'
+object as the second). The handler runs just prior to sending the first
+response.")
+
+(defvar erc-d-auto-pong t
+ "Handle PING requests automatically.")
+
+(defvar erc-d--in-process t
+ "Whether the server is running in the same Emacs as ERT.")
+
+(defvar erc-d--slow-mo nil
+ "Adjustment for all incoming timeouts.
+This is to allow for human interaction or a slow Emacs or CI runner.
+The value is the number of seconds to extend all incoming spec timeouts
+by on init. If the value is a negative number, it's negated and
+interpreted as a lower bound to raise all incoming timeouts to. If the
+value is a function, it should take an existing timeout in seconds and
+return a replacement.")
+
+(defconst erc-d--eof-sentinel "__EOF__")
+(defconst erc-d--linger-sentinel "__LINGER__")
+(defconst erc-d--drop-sentinel "__DROP__")
+
+(defvar erc-d--clients nil
+ "List containing all clients for this server session.")
+
+;; Some :type names may just be made up (not actual CL types)
+
+(cl-defstruct (erc-d-spec) ; see `erc-d--render-entries'
+ (head nil :type symbol) ; or number?
+ (entry nil :type list)
+ (state 0 :type integer))
+
+(cl-defstruct (erc-d-exchange)
+ "Object representing a request/response unit from a canned dialog."
+ (dialog nil :type erc-d-dialog) ; owning dialog
+ (tag nil :type symbol) ; a.k.a. tag, the caar
+ (pattern nil :type string) ; regexp to match requests against
+ (inspec nil :type list) ; original unrendered incoming spec
+ (hunk nil :type erc-d-u-scan-e) ; active raw exchange hunk being yielded
+ (spec nil :type erc-d-spec) ; active spec, see `erc-d--render-entries'
+ (timeout nil :type number) ; time allotted for current request
+ (timer nil :type timer) ; match timer fires when timeout expires
+ (bindings nil :type list) ; `eval'-style env pairs (KEY . VAL) ...
+ (rx-bindings nil :type list) ; rx-let bindings
+ (deferred nil :type boolean) ; whether sender is paused
+ ;; Post-match
+ (match-data nil :type match-data) ; from the latest matched request
+ (request nil :type string)) ; the original request sans CRLF
+
+(cl-defstruct (erc-d-dialog)
+ "Session state for managing a client conversation."
+ (process nil :type process) ; client-connection process
+ (name nil :type symbol) ; likely the interned stem of the file
+ (queue nil :type ring) ; backlog of incoming lines to process
+ (hunks nil :type erc-d-u-scan-d) ; nil when done; info on raw exchange hunks
+ (timers nil :type list) ; unsent replies
+ (vars nil :type list) ; template bindings for rendering
+ (exchanges nil :type ring) ; ring of erc-d-exchange objects
+ (state nil :type symbol) ; handler's last recorded control state
+ (matched nil :type erc-d-exchange) ; currently matched exchange
+ (message nil :type erc-d-i-message) ; `erc-d-i-message'
+ (match-handlers nil :type list) ; copy of `erc-d-match-handlers'
+ (server-fqdn nil :type string) ; copy of `erc-d-server-fqdn'
+ (finalizer nil :type function) ; custom teardown, passed dialog and exchange
+ ;; Post-match history is a plist whose keys are exchange tags
+ ;; (symbols) and whose values are a cons of match-data and request
+ ;; values from prior matches.
+ (history nil :type list))
+
+(defun erc-d--initialize-client (process)
+ "Initialize state variables used by a client PROCESS."
+ ;; Discard server-only/owned props
+ (process-put process :dialog-dialogs nil)
+ (let* ((server (process-get process :server))
+ (reader (pop (process-get server :dialog-dialogs)))
+ (name (pop reader))
+ ;; Copy handlers so they can self-mutate per process
+ (mat-h (copy-sequence (process-get process :dialog-match-handlers)))
+ (fqdn (copy-sequence (process-get process :dialog-server-fqdn)))
+ (vars (copy-sequence (process-get process :dialog-vars)))
+ (dialog (make-erc-d-dialog :name name
+ :process process
+ :queue (make-ring 5)
+ :exchanges (make-ring 10)
+ :match-handlers mat-h
+ :server-fqdn fqdn)))
+ ;; Add items expected by convenience commands like `erc-d-exchange-reload'.
+ (setf (alist-get 'EOF vars) `(: ,erc-d--eof-sentinel eot)
+ (alist-get 'LINGER vars) `(: ,erc-d--linger-sentinel eot)
+ (alist-get 'DROP vars) `(: ,erc-d--drop-sentinel eot)
+ (erc-d-dialog-vars dialog) vars
+ (erc-d-dialog-hunks dialog) reader)
+ ;; Add reverse link, register client, launch
+ (process-put process :dialog dialog)
+ (push process erc-d--clients)
+ (erc-d--command-refresh dialog nil)
+ (erc-d--on-request process)))
+
+(defun erc-d-load-replacement-dialog (dialog replacement &optional skip)
+ "Find REPLACEMENT among backlog and swap out current DIALOG's iterator.
+With int SKIP, advance past that many exchanges."
+ (let* ((process (erc-d-dialog-process dialog))
+ (server (process-get process :server))
+ (reader (assoc-default replacement
+ (process-get server :dialog-dialogs)
+ #'eq)))
+ (when skip (while (not (zerop skip))
+ (erc-d-u--read-dialog reader)
+ (cl-decf skip)))
+ (dolist (timer (erc-d-dialog-timers dialog))
+ (cancel-timer timer))
+ (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog)))
+ (cancel-timer (erc-d-exchange-timer exchange)))
+ (setf (erc-d-dialog-hunks dialog) reader)
+ (erc-d--command-refresh dialog nil)))
+
+(defvar erc-d--m-debug (getenv "ERC_D_DEBUG"))
+
+(defmacro erc-d--m (process format-string &rest args)
+ "Output ARGS using FORMAT-STRING somewhere depending on context.
+PROCESS should be a client connection or a server network process."
+ `(let ((format-string (if erc-d--m-debug
+ (concat (format-time-string "%s.%N: ")
+ ,format-string)
+ ,format-string))
+ (want-insert (and ,process erc-d--in-process)))
+ (when want-insert
+ (with-current-buffer (process-buffer (process-get ,process :server))
+ (goto-char (point-max))
+ (insert (concat (format ,format-string ,@args) "\n"))))
+ (when (or erc-d--m-debug (not want-insert))
+ (message format-string ,@args))))
+
+(defmacro erc-d--log (process string &optional outbound)
+ "Log STRING sent to (OUTBOUND) or received from PROCESS peer."
+ `(let ((id (or (process-get ,process :log-id)
+ (let ((port (erc-d-u--get-remote-port ,process)))
+ (process-put ,process :log-id port)
+ port)))
+ (name (erc-d-dialog-name (process-get ,process :dialog))))
+ (if ,outbound
+ (erc-d--m process "-> %s:%s %s" name id ,string)
+ (dolist (line (split-string ,string "\r\n"))
+ (erc-d--m process "<- %s:%s %s" name id line)))))
+
+(defun erc-d--log-process-event (server process msg)
+ (erc-d--m server "%s: %s" process (string-trim-right msg)))
+
+(defun erc-d--send (process string)
+ "Send STRING to PROCESS peer."
+ (erc-d--log process string 'outbound)
+ (process-send-string process (concat string "\r\n")))
+
+(define-inline erc-d--fuzzy-p (exchange)
+ (inline-letevals (exchange)
+ (inline-quote
+ (let ((tag (symbol-name (erc-d-exchange-tag ,exchange))))
+ (eq ?~ (aref tag 0))))))
+
+(define-error 'erc-d-timeout "Timed out awaiting expected request")
+
+(defun erc-d--finalize-dialog (dialog)
+ "Delete client-connection and finalize DIALOG.
+Return associated server."
+ (let ((process (erc-d-dialog-process dialog)))
+ (setq erc-d--clients (delq process erc-d--clients))
+ (dolist (timer (erc-d-dialog-timers dialog))
+ (cancel-timer timer))
+ (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog)))
+ (cancel-timer (erc-d-exchange-timer exchange)))
+ (prog1 (process-get process :server)
+ (delete-process process))))
+
+(defun erc-d--teardown (&optional sig &rest msg)
+ "Clean up processes and maybe send signal SIG using MSG."
+ (unless erc-d--in-process
+ (when sig
+ (erc-d--m nil "%s %s" sig (apply #'format-message msg)))
+ (kill-emacs (if msg 1 0)))
+ (let (process servers)
+ (while (setq process (pop erc-d--clients))
+ (push (erc-d--finalize-dialog (process-get process :dialog)) servers))
+ (dolist (server servers)
+ (delete-process server)))
+ (dolist (timer timer-list)
+ (when (memq (timer--function timer)
+ '(erc-d--send erc-d--command-handle-all))
+ (erc-d--m nil "Stray timer found: %S" (timer--function timer))
+ (cancel-timer timer)))
+ (when sig
+ (dolist (buf erc-d-u--canned-buffers)
+ (kill-buffer buf))
+ (setq erc-d-u--canned-buffers nil)
+ (signal sig (list (apply #'format-message msg)))))
+
+(defun erc-d--teardown-this-dialog-at-least (dialog)
+ "Run `erc-d--teardown' after destroying DIALOG if it's the last one."
+ (let ((server (process-get (erc-d-dialog-process dialog) :server))
+ (us (erc-d-dialog-process dialog)))
+ (erc-d--finalize-dialog dialog)
+ (cl-assert (not (memq us erc-d--clients)))
+ (unless (or (process-get server :dialog-dialogs)
+ (catch 'other
+ (dolist (process erc-d--clients)
+ (when (eq (process-get process :server) server)
+ (throw 'other process)))))
+ (push us erc-d--clients)
+ (erc-d--teardown))))
+
+(defun erc-d--expire (dialog exchange)
+ "Raise timeout error for EXCHANGE.
+This will start the teardown for DIALOG."
+ (setf (erc-d-exchange-spec exchange) nil)
+ (if-let ((finalizer (erc-d-dialog-finalizer dialog)))
+ (funcall finalizer dialog exchange)
+ (erc-d--teardown 'erc-d-timeout "Timed out awaiting request: %s"
+ (list :name (erc-d-exchange-tag exchange)
+ :pattern (erc-d-exchange-pattern exchange)
+ :timeout (erc-d-exchange-timeout exchange)
+ :dialog (erc-d-dialog-name dialog)))))
+
+;; Using `run-at-time' here allows test cases to examine replies as
+;; they arrive instead of forcing tests to wait until an exchange
+;; completes. The `run-at-time' in `erc-d--command-meter-replies'
+;; does the same. When running as a subprocess, a normal while loop
+;; with a `sleep-for' works fine (including with multiple dialogs).
+;; FYI, this issue was still present in older versions that called
+;; this directly from `erc-d--filter'.
+
+(defun erc-d--on-request (process)
+ "Handle one request for client-connection PROCESS."
+ (when (process-live-p process)
+ (let* ((dialog (process-get process :dialog))
+ (queue (erc-d-dialog-queue dialog)))
+ (unless (ring-empty-p queue)
+ (let* ((parsed (ring-remove queue))
+ (cmd (intern (erc-d-i-message.command parsed))))
+ (setf (erc-d-dialog-message dialog) parsed)
+ (erc-d-command dialog cmd)))
+ (run-at-time nil nil #'erc-d--on-request process))))
+
+(defun erc-d--drop-p (exchange)
+ (memq 'DROP (erc-d-exchange-inspec exchange)))
+
+(defun erc-d--linger-p (exchange)
+ (memq 'LINGER (erc-d-exchange-inspec exchange)))
+
+(defun erc-d--fake-eof (dialog)
+ "Simulate receiving a fictitious \"EOF\" message from peer."
+ (setf (erc-d-dialog-message dialog) ; use downcase for internal cmds
+ (make-erc-d-i-message :command "eof" :unparsed erc-d--eof-sentinel))
+ (run-at-time nil nil #'erc-d-command dialog 'eof))
+
+(defun erc-d--process-sentinel (process event)
+ "Set up or tear down client-connection PROCESS depending on EVENT."
+ (erc-d--log-process-event process process event)
+ (if (eq 'open (process-status process))
+ (erc-d--initialize-client process)
+ (let* ((dialog (process-get process :dialog))
+ (exes (and dialog (erc-d-dialog-exchanges dialog))))
+ (if (and exes (not (ring-empty-p exes)))
+ (cond ((string-prefix-p "connection broken" event)
+ (erc-d--fake-eof dialog))
+ ;; Ignore disconnecting peer when pattern is DROP
+ ((and (string-prefix-p "deleted" event)
+ (erc-d--drop-p (ring-ref exes -1))))
+ (t (erc-d--teardown)))
+ (erc-d--teardown)))))
+
+(defun erc-d--filter (process string)
+ "Handle input received from peer.
+PROCESS represents a client peer connection and STRING is a raw request
+including line delimiters."
+ (let ((queue (erc-d-dialog-queue (process-get process :dialog))))
+ (setq string (concat (process-get process :stashed-input) string))
+ (while (and string (string-match (rx (+ "\r\n")) string))
+ (let ((line (substring string 0 (match-beginning 0))))
+ (setq string (unless (= (match-end 0) (length string))
+ (substring string (match-end 0))))
+ (erc-d--log process line nil)
+ (ring-insert queue (erc-d-i--parse-message line 'decode))))
+ (when string
+ (setf (process-get process :stashed-input) string))))
+
+;; Misc process properties:
+;;
+;; The server property `:dialog-dialogs' is an alist of (symbol
+;; . erc-d-u-scan-d) conses, each of which pairs a dialogs name with
+;; info on its read progress (described above in the Commentary).
+;; This list is populated by `erc-d-run' at the start of each session.
+;;
+;; Client-connection processes keep a reference to their server via a
+;; `:server' property, which can be used to share info with other
+;; clients. There is currently no built-in way to do the same with
+;; clients of other servers. Clients also keep references to their
+;; dialogs and raw messages via `:dialog' and `:stashed-input'.
+;;
+;; The logger stores a unique, human-friendly process name in the
+;; client-process property `:log-id'.
+
+(defun erc-d--start (host service name &rest plist)
+ "Serve canned replies on HOST at SERVICE.
+Return the new server process immediately when `erc-d--in-process' is
+non-nil. Otherwise, serve forever. PLIST becomes the plist of the
+server process and is used to initialize the plists of connection
+processes. NAME is used for the process and the buffer."
+ (let* ((buf (get-buffer-create (concat "*" name "*")))
+ (proc (make-network-process :server t
+ :buffer buf
+ :noquery t
+ :filter #'erc-d--filter
+ :log #'erc-d--log-process-event
+ :sentinel #'erc-d--process-sentinel
+ :name name
+ :family (if host 'ipv4 'local)
+ :coding 'binary
+ :service (or service t)
+ :host host
+ :plist plist)))
+ (process-put proc :server proc)
+ ;; We don't have a minor mode, so use an arbitrary variable to mark
+ ;; buffers owned by us instead
+ (with-current-buffer buf (setq erc-d-u--process-buffer t))
+ (erc-d--m proc "Starting network process: %S %S"
+ proc (erc-d-u--format-bind-address proc))
+ (if erc-d--in-process
+ proc
+ (while (process-live-p proc)
+ (accept-process-output nil 0.01)))))
+
+(defun erc-d--wrap-func-val (dialog exchange key func)
+ "Return a form invoking FUNC when evaluated.
+Arrange for FUNC to be called with the args it expects based on
+the description in `erc-d--render-entries'."
+ (let (args)
+ ;; Ignore &rest or &optional
+ (pcase-let ((`(,n . ,_) (func-arity func)))
+ (pcase n
+ (0)
+ (1 (push (apply-partially #'erc-d-exchange-multi dialog exchange key)
+ args))
+ (2 (push exchange args)
+ (push (apply-partially #'erc-d-exchange-multi dialog exchange key)
+ args))
+ (_ (error "Incompatible function: %s" func))))
+ (lambda () (apply func args))))
+
+(defun erc-d-exchange-reload (dialog exchange)
+ "Rebuild all bindings for EXCHANGE from those in DIALOG."
+ (cl-loop for (key . val) in (erc-d-dialog-vars dialog)
+ unless (keywordp key)
+ do (push (erc-d-u--massage-rx-args key val)
+ (erc-d-exchange-rx-bindings exchange))
+ when (functionp val) do
+ (setq val (erc-d--wrap-func-val dialog exchange key val))
+ do (push (cons key val) (erc-d-exchange-bindings exchange))))
+
+(defun erc-d-exchange-rebind (dialog exchange key val &optional export)
+ "Modify a binding between renders.
+
+Bind symbol KEY to VAL, replacing whatever existed before, which may
+have been a function. A third, optional argument, if present and
+non-nil, results in the DIALOG's bindings for all EXCHANGEs adopting
+this binding. VAL can either be a function of the type described in
+`erc-d--render-entries' or any value acceptable as an argument to the
+function `concat'.
+
+DIALOG and EXCHANGE are the current `erc-d-dialog' and `erc-d-exchange'
+objects for the request context."
+ (when export
+ (setf (alist-get key (erc-d-dialog-vars dialog)) val))
+ (if (functionp val)
+ (setf (alist-get key (erc-d-exchange-bindings exchange))
+ (erc-d--wrap-func-val dialog exchange key val))
+ (setf (alist-get key (erc-d-exchange-rx-bindings exchange)) (list val)
+ (alist-get key (erc-d-exchange-bindings exchange)) val))
+ val)
+
+(defun erc-d-exchange-match (exchange match-number &optional tag)
+ "Return match portion of current or previous request.
+MATCH-NUMBER is the match group number. TAG, if provided, means the
+exchange tag (name) from some previously matched request."
+ (if tag
+ (pcase-let* ((dialog (erc-d-exchange-dialog exchange))
+ (`(,m-d . ,req) (plist-get (erc-d-dialog-history dialog)
+ tag)))
+ (set-match-data m-d)
+ (match-string match-number req))
+ (match-string match-number (erc-d-exchange-request exchange))))
+
+(defun erc-d-exchange-multi (dialog exchange key cmd &rest args)
+ "Call CMD with ARGS.
+This is a utility passed as the first argument to all template
+functions. DIALOG and EXCHANGE are pre-applied. A few pseudo
+commands, like `:request', are provided for convenience so that
+the caller's definition doesn't have to include this file. The
+rest are access and mutation utilities, such as `:set', which
+assigns KEY a new value, `:get-binding', which looks up KEY in
+`erc-d-exchange-bindings', and `:get-var', which looks up KEY in
+`erc-d-dialog-vars'."
+ (pcase cmd
+ (:set (apply #'erc-d-exchange-rebind dialog exchange key args))
+ (:reload (apply #'erc-d-exchange-reload dialog exchange args))
+ (:rebind (apply #'erc-d-exchange-rebind dialog exchange args))
+ (:match (apply #'erc-d-exchange-match exchange args))
+ (:request (erc-d-exchange-request exchange))
+ (:match-data (erc-d-exchange-match-data exchange))
+ (:dialog-name (erc-d-dialog-name dialog))
+ (:get-binding (cdr (assq (car args) (erc-d-exchange-bindings exchange))))
+ (:get-var (alist-get (car args) (erc-d-dialog-vars dialog)))))
+
+(defun erc-d--render-incoming-entry (exchange spec)
+ (let ((rx--local-definitions (rx--extend-local-defs
+ (erc-d-exchange-rx-bindings exchange))))
+ (rx-to-string `(: bos ,@(erc-d-spec-entry spec)) 'no-group)))
+
+(defun erc-d--render-outgoing-entry (exchange entry)
+ (let (out this)
+ (while (setq this (pop entry))
+ (set-match-data (erc-d-exchange-match-data exchange))
+ (unless (stringp this)
+ (cl-assert (symbolp this))
+ (setq this (or (alist-get this (erc-d-exchange-bindings exchange))
+ (symbol-value this)))
+ ;; Allow reference to overlong var name unbecoming of a template
+ (when this
+ (when (symbolp this) (setq this (symbol-value this)))
+ (when (functionp this) (setq this (save-match-data (funcall this))))
+ (unless (stringp this) (error "Unexpected token %S" this))))
+ (push this out))
+ (apply #'concat (nreverse out))))
+
+(defun erc-d--render-entries (exchange &optional yield-result)
+ "Act as an iterator producing rendered strings from EXCHANGE hunks.
+When an entry's CAR is an arbitrary symbol, yield that back first, and
+consider the entry an \"incoming\" entry. Then, regardless of the
+entry's type (incoming or outgoing), yield back the next element, which
+should be a number representing either a timeout (incoming) or a
+delay (outgoing). After that, yield a rendered template (outgoing) or a
+regular expression (incoming); both should be treated as immutable.
+
+When evaluating a template, bind the keys in the alist stored in the
+dialog's `vars' field to its values, but skip any self-quoters, like
+:foo. When an entry is incoming, replace occurrences of a key with its
+value, which can be any valid `rx' form (see Info node `(elisp)
+Extending Rx'). Do the same when an entry is outgoing, but expect a
+value's form to be (anything that evaluates to) something acceptable by
+`concat' or, alternatively, a function that returns a string or nil.
+
+Repeat the last two steps for the remaining entries, all of which are
+assumed to be outgoing. That is, continue yielding a timeout/delay and
+a rendered string for each entry, and yield nil when exhausted.
+
+Once again, for an incoming entry, the yielded string is a regexp to be
+matched against the raw request. For outgoing, it's the final response,
+ready to be sent out (after adding the appropriate line ending).
+
+To help with testing, bindings are not automatically created from
+DIALOG's \"vars\" alist when this function is invoked. But this can be
+forced by sending a non-nil YIELD-RESULT into the generator on the
+second \"next\" invocation of a given iteration. This clobbers any
+temporary bindings that don't exist in the DIALOG's `vars' alist, such
+as those added via `erc-d-exchange-rebind' (unless \"exported\").
+
+As noted earlier, template symbols can be bound to functions. When
+called during rendering, the match data from the current (matched)
+request is accessible by calling the function `match-data'.
+
+A function may ask for up to two required args, which are provided as
+needed. When applicable, the first required arg is a `funcall'-able
+helper that accepts various keyword-based commands, like :rebind, and a
+variable number of args. See `erc-d-exchange-multi' for details. When
+specified, the second required arg is the current `erc-d-exchange'
+object, which has among its members its owning `erc-d-dialog' object.
+This should suffice as a safety valve for any corner-case needs.
+Non-required args are ignored."
+ (let ((spec (erc-d-exchange-spec exchange))
+ (dialog (erc-d-exchange-dialog exchange))
+ (entries (erc-d-exchange-hunk exchange)))
+ (unless (erc-d-spec-entry spec)
+ (setf (erc-d-spec-entry spec) (erc-d-u--read-exchange entries)))
+ (catch 'yield
+ (while (erc-d-spec-entry spec)
+ (pcase (erc-d-spec-state spec)
+ (0 (cl-incf (erc-d-spec-state spec))
+ (throw 'yield (setf (erc-d-spec-head spec)
+ (pop (erc-d-spec-entry spec)))))
+ (1 (cl-incf (erc-d-spec-state spec))
+ (when yield-result
+ (erc-d-exchange-reload dialog exchange))
+ (unless (numberp (erc-d-spec-head spec))
+ (setf (erc-d-exchange-inspec exchange) (erc-d-spec-entry spec))
+ (throw 'yield
+ (prog1 (pop (erc-d-spec-entry spec))
+ (setf (erc-d-spec-entry spec)
+ (erc-d--render-incoming-entry exchange spec))))))
+ (2 (setf (erc-d-spec-state spec) 0)
+ (throw 'yield
+ (let ((entry (erc-d-spec-entry spec)))
+ (setf (erc-d-spec-entry spec) nil)
+ (if (stringp entry)
+ entry
+ (erc-d--render-outgoing-entry exchange entry))))))))))
+
+(defun erc-d--iter (exchange)
+ (apply-partially #'erc-d--render-entries exchange))
+
+(defun erc-d-on-match (dialog exchange)
+ "Handle matched exchange request.
+Allow the first handler in `erc-d-match-handlers' whose key matches TAG
+to manipulate replies before they're sent to the DIALOG peer."
+ (when-let* ((tag (erc-d-exchange-tag exchange))
+ (handler (plist-get (erc-d-dialog-match-handlers dialog) tag)))
+ (let ((md (erc-d-exchange-match-data exchange)))
+ (set-match-data md)
+ (funcall handler dialog exchange))))
+
+(defun erc-d--send-outgoing (dialog exchange)
+ "Send outgoing lines for EXCHANGE to DIALOG peer.
+Assume the next spec is outgoing. If its delay value is zero, render
+the template and send the resulting message straight away. Do the same
+when DELAY is negative, only arrange for its message to be sent (abs
+DELAY) seconds later, and then keep on processing. If DELAY is
+positive, pause processing and yield DELAY."
+ (let ((specs (erc-d--iter exchange))
+ (process (erc-d-dialog-process dialog))
+ (deferred (erc-d-exchange-deferred exchange))
+ delay)
+ ;; Could stash/pass thunk instead to ensure specs can't be mutated
+ ;; between calls (by temporarily replacing dialog member with a fugazi)
+ (when deferred
+ (erc-d--send process (funcall specs))
+ (setf deferred nil (erc-d-exchange-deferred exchange) deferred))
+ (while (and (not deferred) (setq delay (funcall specs)))
+ (cond ((zerop delay) (erc-d--send process (funcall specs)))
+ ((< delay 0) (push (run-at-time (- delay) nil #'erc-d--send
+ process (funcall specs))
+ (erc-d-dialog-timers dialog)))
+ ((setf deferred t (erc-d-exchange-deferred exchange) deferred))))
+ delay))
+
+(defun erc-d--add-dialog-linger (dialog exchange)
+ "Add finalizer for EXCHANGE in DIALOG."
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Lingering for %.2f seconds" (erc-d-exchange-timeout exchange))
+ (let ((start (current-time)))
+ (setf (erc-d-dialog-finalizer dialog)
+ (lambda (&rest _)
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Lingered for %.2f seconds"
+ (float-time (time-subtract (current-time) start)))
+ (erc-d--teardown-this-dialog-at-least dialog)))))
+
+(defun erc-d--add-dialog-drop (dialog exchange)
+ "Add finalizer for EXCHANGE in DIALOG."
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Dropping in %.2f seconds" (erc-d-exchange-timeout exchange))
+ (setf (erc-d-dialog-finalizer dialog)
+ (lambda (&rest _)
+ (erc-d--m (erc-d-dialog-process dialog)
+ "Dropping %S" (erc-d-dialog-name dialog))
+ (erc-d--finalize-dialog dialog))))
+
+(defun erc-d--create-exchange (dialog hunk)
+ "Initialize next exchange HUNK for DIALOG."
+ (let* ((spec (make-erc-d-spec))
+ (exchange (make-erc-d-exchange :dialog dialog :hunk hunk :spec spec))
+ (specs (erc-d--iter exchange)))
+ (setf (erc-d-exchange-tag exchange) (funcall specs)
+ (erc-d-exchange-timeout exchange) (funcall specs t)
+ (erc-d-exchange-pattern exchange) (funcall specs))
+ (cond ((erc-d--linger-p exchange)
+ (erc-d--add-dialog-linger dialog exchange))
+ ((erc-d--drop-p exchange)
+ (erc-d--add-dialog-drop dialog exchange)))
+ (setf (erc-d-exchange-timer exchange)
+ (run-at-time (erc-d-exchange-timeout exchange)
+ nil #'erc-d--expire dialog exchange))
+ exchange))
+
+(defun erc-d--command-consider-prep-fail (dialog line exes)
+ (list 'error "Match failed: %S %S" line
+ (list :exes (mapcar #'erc-d-exchange-pattern
+ (ring-elements exes))
+ :dialog (erc-d-dialog-name dialog))))
+
+(defun erc-d--command-consider-prep-success (dialog line exes matched)
+ (setf (erc-d-exchange-request matched) line
+ (erc-d-exchange-match-data matched) (match-data)
+ ;; Also add current to match history, indexed by exchange tag
+ (plist-get (erc-d-dialog-history dialog)
+ (erc-d-exchange-tag matched))
+ (cons (match-data) line)) ; do we need to make a copy of this?
+ (cancel-timer (erc-d-exchange-timer matched))
+ (ring-remove exes (ring-member exes matched)))
+
+(cl-defun erc-d--command-consider (dialog)
+ "Maybe return next matched exchange for DIALOG.
+Upon encountering a mismatch, return an error of the form (ERROR-SYMBOL
+DATA). But when only fuzzies remain in the exchange pool, return nil."
+ (let* ((parsed (erc-d-dialog-message dialog))
+ (line (erc-d-i-message.unparsed parsed))
+ (exes (erc-d-dialog-exchanges dialog))
+ ;;
+ matched)
+ (let ((elts (ring-elements exes)))
+ (while (and (setq matched (pop elts))
+ (not (string-match (erc-d-exchange-pattern matched) line)))
+ (if (and (not elts) (erc-d--fuzzy-p matched))
+ ;; Nothing to do, so advance
+ (cl-return-from erc-d--command-consider nil)
+ (cl-assert (or (not elts) (erc-d--fuzzy-p matched))))))
+ (if matched
+ (erc-d--command-consider-prep-success dialog line exes matched)
+ (erc-d--command-consider-prep-fail dialog line exes))))
+
+(defun erc-d--active-ex-p (ring)
+ "Return non-nil when RING has a non-fuzzy exchange.
+That is, return nil when RING is empty or when it only has exchanges
+with leading-tilde tags."
+ (let ((i 0)
+ (len (ring-length ring))
+ ex found)
+ (while (and (not found) (< i len))
+ (unless (erc-d--fuzzy-p (setq ex (ring-ref ring i)))
+ (setq found ex))
+ (cl-incf i))
+ found))
+
+(defun erc-d--finalize-done (dialog)
+ ;; Linger logic for individual dialogs is handled elsewhere
+ (if-let ((finalizer (erc-d-dialog-finalizer dialog)))
+ (funcall finalizer dialog)
+ (let ((d (process-get (erc-d-dialog-process dialog) :dialog-linger-secs)))
+ (push (run-at-time d nil #'erc-d--teardown)
+ (erc-d-dialog-timers dialog)))))
+
+(defun erc-d--advance-or-die (dialog)
+ "Govern the lifetime of DIALOG.
+Replenish exchanges from reader and insert them into the pool of
+expected matches, as produced. Return a symbol indicating session
+status: deferring, matching, depleted, or done."
+ (let ((exes (erc-d-dialog-exchanges dialog))
+ hunk)
+ (cond ((erc-d--active-ex-p exes) 'deferring)
+ ((setq hunk (erc-d-u--read-dialog (erc-d-dialog-hunks dialog)))
+ (let ((exchange (erc-d--create-exchange dialog hunk)))
+ (if (erc-d--fuzzy-p exchange)
+ (ring-insert exes exchange)
+ (ring-insert-at-beginning exes exchange)))
+ 'matching)
+ ((not (ring-empty-p exes)) 'depleted)
+ (t 'done))))
+
+(defun erc-d--command-meter-replies (dialog exchange &optional cmd)
+ "Ignore requests until all replies have been sent.
+Do this for some previously matched EXCHANGE in DIALOG based on CMD, a
+symbol. As a side effect, maybe schedule the resumption of the main
+loop after some delay."
+ (let (delay)
+ (if (or (not cmd) (eq 'resume cmd))
+ (when (setq delay (erc-d--send-outgoing dialog exchange))
+ (push (run-at-time delay nil #'erc-d--command-handle-all
+ dialog 'resume)
+ (erc-d-dialog-timers dialog))
+ (erc-d-dialog-state dialog))
+ (setf (erc-d-dialog-state dialog) 'sending))))
+
+(defun erc-d--die-unexpected (dialog)
+ (erc-d--teardown 'error "Received unexpected input: %S"
+ (erc-d-i-message.unparsed (erc-d-dialog-message dialog))))
+
+(defun erc-d--command-refresh (dialog matched)
+ (let ((state (erc-d--advance-or-die dialog)))
+ (when (eq state 'done)
+ (erc-d--finalize-done dialog))
+ (unless matched
+ (when (eq state 'depleted)
+ (erc-d--die-unexpected dialog))
+ (cl-assert (memq state '(matching depleted)) t))
+ (setf (erc-d-dialog-state dialog) state)))
+
+(defun erc-d--command-handle-all (dialog cmd)
+ "Create handler to act as control agent and process DIALOG requests.
+Have it ingest internal control commands (lowercase symbols) and yield
+back others indicating the lifecycle stage of the current dialog."
+ (let ((matched (erc-d-dialog-matched dialog)))
+ (cond
+ (matched
+ (or (erc-d--command-meter-replies dialog matched cmd)
+ (setf (erc-d-dialog-matched dialog) nil)
+ (erc-d--command-refresh dialog t)))
+ ((pcase cmd ; FIXME remove command facility or make extensible
+ ('resume nil)
+ ('eof (erc-d--m (erc-d-dialog-process dialog) "Received an EOF") nil)))
+ (t ; matching
+ (setq matched nil)
+ (catch 'yield
+ (while (not matched)
+ (when (ring-empty-p (erc-d-dialog-exchanges dialog))
+ (erc-d--die-unexpected dialog))
+ (when (setq matched (erc-d--command-consider dialog))
+ (if (eq (car-safe matched) 'error)
+ (apply #'erc-d--teardown matched)
+ (erc-d-on-match dialog matched)
+ (setf (erc-d-dialog-matched dialog) matched)
+ (if-let ((s (erc-d--command-meter-replies dialog matched nil)))
+ (throw 'yield s)
+ (setf (erc-d-dialog-matched dialog) nil))))
+ (erc-d--command-refresh dialog matched)))))))
+
+;;;; Handlers for IRC commands
+
+(cl-defgeneric erc-d-command (dialog cmd)
+ "Handle new CMD from client for DIALOG.
+By default, defer to this dialog's `erc-d--command-handle-all' instance,
+which is stored in its `handler' field.")
+
+(cl-defmethod erc-d-command ((dialog erc-d-dialog) cmd)
+ (when (eq 'sending (erc-d--command-handle-all dialog cmd))
+ (ring-insert-at-beginning (erc-d-dialog-queue dialog)
+ (erc-d-dialog-message dialog))))
+
+;; A similar PONG handler would be useless because we know when to
+;; expect them
+
+(cl-defmethod erc-d-command ((dialog erc-d-dialog) (_cmd (eql PING))
+ &context (erc-d-auto-pong (eql t)))
+ "Respond to PING request from DIALOG peer when ERC-D-AUTO-PONG is t."
+ (let* ((parsed (erc-d-dialog-message dialog))
+ (process (erc-d-dialog-process dialog))
+ (nonce (car (erc-d-i-message.command-args parsed)))
+ (fqdn (erc-d-dialog-server-fqdn dialog)))
+ (erc-d--send process (format ":%s PONG %s :%s" fqdn fqdn nonce))))
+
+
+;;;; Entry points
+
+(defun erc-d-run (host service &optional server-name &rest dialogs)
+ "Start serving DIALOGS on HOST at SERVICE.
+Pass HOST and SERVICE directly to `make-network-process'. When present,
+use string SERVER-NAME for the server-process name as well as that of
+its buffer (w. surrounding asterisks). When absent, do the same with
+`erc-d-server-name'. When running \"in process,\" return the server
+process, otherwise sleep for the duration of the server process.
+
+A dialog must be a symbol matching the base name of a dialog file in
+`erc-d-u-canned-dialog-dir'.
+
+The variable `erc-d-tmpl-vars' determines the common members of the
+`erc-d--render-entries' ENTRIES param. Variables `erc-d-server-fqdn'
+and `erc-d-linger-secs' determine the `erc-d-dialog' items
+`:server-fqdn' and `:linger-secs' for all client processes.
+
+The variable `erc-d-tmpl-vars' can be used to initialize the
+process's `erc-d-dialog' vars item."
+ (when (and server-name (symbolp server-name))
+ (push server-name dialogs)
+ (setq server-name nil))
+ (let (loaded)
+ (dolist (dialog (nreverse dialogs))
+ (let ((reader (erc-d-u--canned-load-dialog dialog)))
+ (when erc-d--slow-mo
+ (setq reader (erc-d-u--rewrite-for-slow-mo erc-d--slow-mo reader)))
+ (push (cons (erc-d-u--normalize-canned-name dialog) reader) loaded)))
+ (setq dialogs loaded))
+ (erc-d--start host service (or server-name erc-d-server-name)
+ :dialog-dialogs dialogs
+ :dialog-vars erc-d-tmpl-vars
+ :dialog-linger-secs erc-d-linger-secs
+ :dialog-server-fqdn erc-d-server-fqdn
+ :dialog-match-handlers (erc-d-u--unkeyword
+ erc-d-match-handlers)))
+
+(defun erc-d-serve ()
+ "Start serving canned dialogs from the command line.
+Although not autoloaded, this function is meant to be summoned via the
+Emacs -f flag while starting a batch session. It prints incoming and
+outgoing messages to standard out.
+
+The main options are --host HOST and --port PORT, which default to
+localhost and auto, respectively. The args are the dialogs to run.
+Unlike with `erc-d-run', dialogs here *must* be files, meaning Lisp-Data
+files adhering to the required format. (These consist of \"specs\"
+detailing timing and template info; see commentary for specifics.)
+
+An optional --add-time N option can also be passed to hike up timeouts
+by some number of seconds N. For example, you might run:
+
+ $ emacs -Q -batch -L . \\
+ > -l erc-d.el \\
+ > -f erc-d-serve \\
+ > --host 192.168.124.1 \\
+ > --port 16667 \\
+ > --add-time 10 \\
+ > ./my-dialog.eld
+
+from a Makefile or manually with \\<global-map>\\[compile]. And then in
+another terminal, do:
+
+ $ nc -C 192.168.124.1 16667 ; or telnet if your nc doesn't have -C
+ > PASS changeme
+ ...
+
+Use `erc-d-run' instead to start the server from within Emacs."
+ (unless noninteractive
+ (error "Command-line func erc-d-serve not run in -batch session"))
+ (setq erc-d--in-process nil)
+ (let (port host dialogs erc-d--slow-mo)
+ (while command-line-args-left
+ (pcase (pop command-line-args-left)
+ ("--add-time" (setq erc-d--slow-mo
+ (string-to-number (pop command-line-args-left))))
+ ("--linger" (setq erc-d-linger-secs
+ (string-to-number (pop command-line-args-left))))
+ ("--host" (setq host (pop command-line-args-left)))
+ ("--port" (setq port (string-to-number (pop command-line-args-left))))
+ (dialog (push dialog dialogs))))
+ (setq dialogs (mapcar #'erc-d-u--massage-canned-name dialogs))
+ (when erc-d--slow-mo
+ (message "Slow mo is ON"))
+ (apply #'erc-d-run (or host "localhost") port nil (nreverse dialogs))))
+
+(provide 'erc-d)
+
+;;; erc-d.el ends here
diff --git a/test/lisp/erc/resources/erc-d/resources/basic.eld b/test/lisp/erc/resources/erc-d/resources/basic.eld
new file mode 100644
index 00000000000..a020eec3fff
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/basic.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0.1 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 5 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+;; Some comment (to prevent regression)
+((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/depleted.eld b/test/lisp/erc/resources/erc-d/resources/depleted.eld
new file mode 100644
index 00000000000..e5a7f03efb7
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/depleted.eld
@@ -0,0 +1,12 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS :changeme"))
+
+((~fake 3.2 "FAKE ")
+ (0.1 ":irc.example.org FAKE irc.example.com :ok"))
+
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet tester")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
diff --git a/test/lisp/erc/resources/erc-d/resources/drop-a.eld b/test/lisp/erc/resources/erc-d/resources/drop-a.eld
new file mode 100644
index 00000000000..2e23eeb20ff
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/drop-a.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "a")
+ (0 "hi"))
+((drop 0.01 DROP))
diff --git a/test/lisp/erc/resources/erc-d/resources/drop-b.eld b/test/lisp/erc/resources/erc-d/resources/drop-b.eld
new file mode 100644
index 00000000000..facecd5e812
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/drop-b.eld
@@ -0,0 +1,4 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "b")
+ (0 "hi"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
new file mode 100644
index 00000000000..36b1cc23081
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+((fake 0 "FAKE noop"))
+
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0. ":irc.barnet.org 001 tester :Welcome to the BAR Network tester")
+ (0. ":irc.barnet.org 002 tester :Your host is irc.barnet.org")
+ (0. ":irc.barnet.org 003 tester :This server was created just now")
+ (0. ":irc.barnet.org 004 tester irc.barnet.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0. ":irc.barnet.org 005 tester MODES NETWORK=BarNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0. ":irc.barnet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0. ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0. ":irc.barnet.org 253 tester 0 :unregistered connections")
+ (0. ":irc.barnet.org 254 tester 1 :channels formed")
+ (0. ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0. ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0. ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0. ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0. ":irc.barnet.org 221 tester +Zi")
+ (0. ":irc.barnet.org 306 tester :You have been marked as being away")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com @%+mike!~mike@example.org")
+ (0 ":irc.barnet.org 366 joe #chan :End of NAMES list"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620805269")
+ (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: As he regards his aged father's life.")
+ (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
new file mode 100644
index 00000000000..5dbea50f865
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0. ":irc.foonet.org 001 tester :Welcome to the FOO Network tester")
+ (0. ":irc.foonet.org 002 tester :Your host is irc.foonet.org")
+ (0. ":irc.foonet.org 003 tester :This server was created just now")
+ (0. ":irc.foonet.org 004 tester irc.foonet.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0. ":irc.foonet.org 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0. ":irc.foonet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0. ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0. ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0. ":irc.foonet.org 254 tester 1 :channels formed")
+ (0. ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0. ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0. ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0. ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0. ":irc.foonet.org 221 tester +Zi")
+ (0. ":irc.foonet.org 306 tester :You have been marked as being away")
+ (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foonet.org 366 alice #chan :End of NAMES list"))
+
+((mode 2 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620805269")
+ (0.1 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
+ (0.05 ":bob!~u@awyxgybtkx7uq.irc PRIVMSG #chan :alice: As he regards his aged father's life.")
+ (0.05 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it."))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld
new file mode 100644
index 00000000000..d93313023d0
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld
@@ -0,0 +1,4 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) token ":changeme"))
+
+((fake 0 "FAKE"))
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic.eld b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
new file mode 100644
index 00000000000..459b6e52bfe
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
@@ -0,0 +1,30 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 2.2 "NICK tester"))
+
+((user 2.2 "USER " user " " (ignored digit "*") " :" realname)
+ (0.0 ":" dom " 001 " nick " :Welcome to the Internet Relay Network tester")
+ (0.0 ":" dom " 002 " nick " :Your host is " dom)
+ (0.0 ":" dom " 003 " nick " :This server was created just now")
+ (0.0 ":" dom " 004 " nick " " dom " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":" dom " 251 " nick " :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":" dom " 252 " nick " 0 :IRC Operators online")
+ (0.0 ":" dom " 253 " nick " 0 :unregistered connections")
+ (0.0 ":" dom " 254 " nick " 1 :channels formed")
+ (0.0 ":" dom " 255 " nick " :I have 3 clients and 0 servers")
+ (0.0 ":" dom " 265 " nick " 3 3 :Current local users 3, max 3")
+ (0.0 ":" dom " 266 " nick " 3 3 :Current global users 3, max 3")
+ (0.0 ":" dom " 422 " nick " :MOTD File is missing"))
+
+((mode-user 2.2 "MODE tester +i")
+ (0.0 ":" dom " 221 " nick " +Zi")
+
+ (0.0 ":" dom " 306 " nick " :You have been marked as being away")
+ (0.0 ":" nick "!~" nick "@localhost JOIN #chan")
+ (0.0 ":" dom " 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":" dom " 366 alice #chan :End of NAMES list"))
+
+((mode 2.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :" nick ": hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/eof.eld b/test/lisp/erc/resources/erc-d/resources/eof.eld
new file mode 100644
index 00000000000..5da84b2e74f
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/eof.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 1.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
+
+((eof 1.0 EOF))
diff --git a/test/lisp/erc/resources/erc-d/resources/fuzzy.eld b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
new file mode 100644
index 00000000000..0504b6a6682
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
@@ -0,0 +1,42 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.5 "USER user 0 * :tester")
+ (0.0 "@time=" now " :irc.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 "@time=" now " :irc.org 002 tester :Your host is irc.org")
+ (0.0 "@time=" now " :irc.org 003 tester :This server was created just now")
+ (0.0 "@time=" now " :irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 "@time=" now " :irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
+ (0.0 "@time=" now " :irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 "@time=" now " :irc.org 252 tester 0 :IRC Operators online")
+ (0.0 "@time=" now " :irc.org 253 tester 0 :unregistered connections")
+ (0.0 "@time=" now " :irc.org 254 tester 1 :channels formed")
+ (0.0 "@time=" now " :irc.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 "@time=" now " :irc.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 "@time=" now " :irc.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 "@time=" now " :irc.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 "@time=" now " :irc.org 221 tester +Zi")
+ (0.0 "@time=" now " :irc.org 306 tester :You have been marked as being away"))
+
+((~join-foo 3.2 "JOIN #foo")
+ (0 "@time=" now " :tester!~tester@localhost JOIN #foo")
+ (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 366 alice #foo :End of NAMES list"))
+
+((~join-bar 1.2 "JOIN #bar")
+ (0 "@time=" now " :tester!~tester@localhost JOIN #bar")
+ (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 366 alice #bar :End of NAMES list"))
+
+((~mode-foo 3.2 "MODE #foo")
+ (0.0 "@time=" now " :irc.example.org 324 tester #foo +Cint")
+ (0.0 "@time=" now " :irc.example.org 329 tester #foo 1519850102")
+ (0.1 "@time=" now " :bob!~bob@example.org PRIVMSG #foo :hey"))
+
+((mode-bar 10.2 "MODE #bar")
+ (0.0 "@time=" now " :irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5")
+ (0.0 "@time=" now " :irc.example.org 329 tester #bar :1602642829")
+ (0.1 "@time=" now " :alice!~alice@example.com PRIVMSG #bar :hi"))
diff --git a/test/lisp/erc/resources/erc-d/resources/incremental.eld b/test/lisp/erc/resources/erc-d/resources/incremental.eld
new file mode 100644
index 00000000000..ab940fe6129
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/incremental.eld
@@ -0,0 +1,43 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.foo.net 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.foo.net 002 tester :Your host is irc.foo.net")
+ (0.0 ":irc.foo.net 003 tester :This server was created just now")
+ (0.0 ":irc.foo.net 004 tester irc.foo.net BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.foo.net 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.foo.net 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.foo.net 253 tester 0 :unregistered connections")
+ (0.0 ":irc.foo.net 254 tester 1 :channels formed")
+ (0.0 ":irc.foo.net 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.foo.net 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.foo.net 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.foo.net 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.foo.net 221 tester +Zi")
+ (0.0 ":irc.foo.net 306 tester :You have been marked as being away"))
+
+((join 3 "JOIN #foo")
+ (0 ":tester!~tester@localhost JOIN #foo")
+ (0 ":irc.foo.net 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foo.net 366 alice #foo :End of NAMES list"))
+
+((mode 3 "MODE #foo")
+ (0.0 ":irc.foo.net 324 tester #foo +Cint")
+ (0.0 ":irc.foo.net 329 tester #foo 1519850102")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defence, by mercy, 'tis most just.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Look for me.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.")
+ (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Done"))
+
+((hi 10 "PRIVMSG #foo :Hi"))
diff --git a/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld
new file mode 100644
index 00000000000..168569f5481
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld
@@ -0,0 +1,380 @@
+;;; -*- mode: lisp-data; -*-
+
+;; https://github.com/DanielOaks/irc-parser-tests
+((mask-match
+ (tests
+ ((mask . "*@127.0.0.1")
+ (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1")
+ (fails "coolguy!ab@127.0.0.5" "cooldud3!~d@124.0.0.1"))
+ ((mask . "cool*@*")
+ (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "cool132!ab@example.com")
+ (fails "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1"))
+ ((mask . "cool!*@*")
+ (matches "cool!guyab@127.0.0.1" "cool!~dudebc@127.0.0.1" "cool!312ab@example.com")
+ (fails "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1"))
+ ((mask . "cool!?username@*")
+ (matches "cool!ausername@127.0.0.1" "cool!~username@127.0.0.1")
+ (fails "cool!username@127.0.0.1"))
+ ((mask . "cool!a?*@*")
+ (matches "cool!ab@127.0.0.1" "cool!abc@127.0.0.1")
+ (fails "cool!a@127.0.0.1"))
+ ((mask . "cool[guy]!*@*")
+ (matches "cool[guy]!guy@127.0.0.1" "cool[guy]!a@example.com")
+ (fails "coolg!ab@127.0.0.1" "cool[!ac@127.0.1.1"))))
+ (msg-join
+ (tests
+ ((desc . "Simple test with verb and params.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf"))
+ (matches "foo bar baz asdf" "foo bar baz :asdf"))
+ ((desc . "Simple test with source and no params.")
+ (atoms
+ (source . "src")
+ (verb . "AWAY"))
+ (matches ":src AWAY"))
+ ((desc . "Simple test with source and empty trailing param.")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")
+ (params ""))
+ (matches ":src AWAY :"))
+ ((desc . "Simple test with source.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf"))
+ (matches ":coolguy foo bar baz asdf" ":coolguy foo bar baz :asdf"))
+ ((desc . "Simple test with trailing param.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux"))
+ (matches "foo bar baz :asdf quux"))
+ ((desc . "Simple test with empty trailing param.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ""))
+ (matches "foo bar baz :"))
+ ((desc . "Simple test with trailing param containing colon.")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ":asdf"))
+ (matches "foo bar baz ::asdf"))
+ ((desc . "Test with source and trailing param.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux"))
+ (matches ":coolguy foo bar baz :asdf quux"))
+ ((desc . "Test with trailing containing beginning+end whitespace.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " asdf quux "))
+ (matches ":coolguy foo bar baz : asdf quux "))
+ ((desc . "Test with trailing containing what looks like another trailing param.")
+ (atoms
+ (source . "coolguy")
+ (verb . "PRIVMSG")
+ (params "bar" "lol :) "))
+ (matches ":coolguy PRIVMSG bar :lol :) "))
+ ((desc . "Simple test with source and empty trailing.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" ""))
+ (matches ":coolguy foo bar baz :"))
+ ((desc . "Trailing contains only spaces.")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " "))
+ (matches ":coolguy foo bar baz : "))
+ ((desc . "Param containing tab (tab is not considered SPACE for message splitting).")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "b ar" "baz"))
+ (matches ":coolguy foo b ar baz" ":coolguy foo b ar :baz"))
+ ((desc . "Tag with no value and space-filled trailing.")
+ (atoms
+ (tags
+ (asd . ""))
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " "))
+ (matches "@asd :coolguy foo bar baz : "))
+ ((desc . "Tags with escaped values.")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (d . "gh;764")))
+ (matches "@a=b\\\\and\\nk;d=gh\\:764 foo" "@d=gh\\:764;a=b\\\\and\\nk foo"))
+ ((desc . "Tags with escaped values and params.")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (d . "gh;764"))
+ (params "par1" "par2"))
+ (matches "@a=b\\\\and\\nk;d=gh\\:764 foo par1 par2" "@a=b\\\\and\\nk;d=gh\\:764 foo par1 :par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 :par2"))
+ ((desc . "Tag with long, strange values (including LF and newline).")
+ (atoms
+ (tags
+ (foo . "\\\\;\\s \n"))
+ (verb . "COMMAND"))
+ (matches "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND"))))
+ (msg-split
+ (tests
+ ((input . "foo bar baz asdf")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf")))
+ ((input . ":coolguy foo bar baz asdf")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf")))
+ ((input . "foo bar baz :asdf quux")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux")))
+ ((input . "foo bar baz :")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" "")))
+ ((input . "foo bar baz ::asdf")
+ (atoms
+ (verb . "foo")
+ (params "bar" "baz" ":asdf")))
+ ((input . ":coolguy foo bar baz :asdf quux")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "asdf quux")))
+ ((input . ":coolguy foo bar baz : asdf quux ")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " asdf quux ")))
+ ((input . ":coolguy PRIVMSG bar :lol :) ")
+ (atoms
+ (source . "coolguy")
+ (verb . "PRIVMSG")
+ (params "bar" "lol :) ")))
+ ((input . ":coolguy foo bar baz :")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" "")))
+ ((input . ":coolguy foo bar baz : ")
+ (atoms
+ (source . "coolguy")
+ (verb . "foo")
+ (params "bar" "baz" " ")))
+ ((input . "@a=b;c=32;k;rt=ql7 foo")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b")
+ (c . "32")
+ (k . "")
+ (rt . "ql7"))))
+ ((input . "@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo")
+ (atoms
+ (verb . "foo")
+ (tags
+ (a . "b\\and\nk")
+ (c . "72 45")
+ (d . "gh;764"))))
+ ((input . "@c;h=;a=b :quux ab cd")
+ (atoms
+ (tags
+ (c . "")
+ (h . "")
+ (a . "b"))
+ (source . "quux")
+ (verb . "ab")
+ (params "cd")))
+ ((input . ":src JOIN #chan")
+ (atoms
+ (source . "src")
+ (verb . "JOIN")
+ (params "#chan")))
+ ((input . ":src JOIN :#chan")
+ (atoms
+ (source . "src")
+ (verb . "JOIN")
+ (params "#chan")))
+ ((input . ":src AWAY")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")))
+ ((input . ":src AWAY ")
+ (atoms
+ (source . "src")
+ (verb . "AWAY")))
+ ((input . ":cool guy foo bar baz")
+ (atoms
+ (source . "cool guy")
+ (verb . "foo")
+ (params "bar" "baz")))
+ ((input . ":coolguy!ag@net5work.admin PRIVMSG foo :bar baz")
+ (atoms
+ (source . "coolguy!ag@net5work.admin")
+ (verb . "PRIVMSG")
+ (params "foo" "bar baz")))
+ ((input . ":coolguy!~ag@net05work.admin PRIVMSG foo :bar baz")
+ (atoms
+ (source . "coolguy!~ag@net05work.admin")
+ (verb . "PRIVMSG")
+ (params "foo" "bar baz")))
+ ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= :irc.example.com COMMAND param1 param2 :param3 param3")
+ (atoms
+ (tags
+ (tag1 . "value1")
+ (tag2 . "")
+ (vendor1/tag3 . "value2")
+ (vendor2/tag4 . ""))
+ (source . "irc.example.com")
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . ":irc.example.com COMMAND param1 param2 :param3 param3")
+ (atoms
+ (source . "irc.example.com")
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4 COMMAND param1 param2 :param3 param3")
+ (atoms
+ (tags
+ (tag1 . "value1")
+ (tag2 . "")
+ (vendor1/tag3 . "value2")
+ (vendor2/tag4 . ""))
+ (verb . "COMMAND")
+ (params "param1" "param2" "param3 param3")))
+ ((input . "COMMAND")
+ (atoms
+ (verb . "COMMAND")))
+ ((input . "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND")
+ (atoms
+ (tags
+ (foo . "\\\\;\\s \n"))
+ (verb . "COMMAND")))
+ ((input . ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal characters")
+ (atoms
+ (source . "gravel.mozilla.org")
+ (verb . "432")
+ (params "#momo" "Erroneous Nickname: Illegal characters")))
+ ((input . ":gravel.mozilla.org MODE #tckk +n ")
+ (atoms
+ (source . "gravel.mozilla.org")
+ (verb . "MODE")
+ (params "#tckk" "+n")))
+ ((input . ":services.esper.net MODE #foo-bar +o foobar ")
+ (atoms
+ (source . "services.esper.net")
+ (verb . "MODE")
+ (params "#foo-bar" "+o" "foobar")))
+ ((input . "@tag1=value\\\\ntest COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value\\ntest"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=value\\1 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value1"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=value1\\ COMMAND")
+ (atoms
+ (tags
+ (tag1 . "value1"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "5")
+ (tag2 . "3")
+ (tag3 . "4"))
+ (verb . "COMMAND")))
+ ((input . "@tag1=1;tag2=3;tag3=4;tag1=5;vendor/tag2=8 COMMAND")
+ (atoms
+ (tags
+ (tag1 . "5")
+ (tag2 . "3")
+ (tag3 . "4")
+ (vendor/tag2 . "8"))
+ (verb . "COMMAND")))
+ ((input . ":SomeOp MODE #channel :+i")
+ (atoms
+ (source . "SomeOp")
+ (verb . "MODE")
+ (params "#channel" "+i")))
+ ((input . ":SomeOp MODE #channel +oo SomeUser :AnotherUser")
+ (atoms
+ (source . "SomeOp")
+ (verb . "MODE")
+ (params "#channel" "+oo" "SomeUser" "AnotherUser")))))
+ (userhost-split
+ (tests
+ ((source . "coolguy")
+ (atoms
+ (nick . "coolguy")))
+ ((source . "coolguy!ag@127.0.0.1")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")
+ (host . "127.0.0.1")))
+ ((source . "coolguy!~ag@localhost")
+ (atoms
+ (nick . "coolguy")
+ (user . "~ag")
+ (host . "localhost")))
+ ((source . "coolguy@127.0.0.1")
+ (atoms
+ (nick . "coolguy")
+ (host . "127.0.0.1")))
+ ((source . "coolguy!ag")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")))
+ ((source . "coolguy!ag@net5work.admin")
+ (atoms
+ (nick . "coolguy")
+ (user . "ag")
+ (host . "net5work.admin")))
+ ((source . "coolguy!~ag@net05work.admin")
+ (atoms
+ (nick . "coolguy")
+ (user . "~ag")
+ (host . "net05work.admin")))))
+ (validate-hostname
+ (tests
+ ((host . "irc.example.com")
+ (valid . t))
+ ((host . "i.coolguy.net")
+ (valid . t))
+ ((host . "irc-srv.net.uk")
+ (valid . t))
+ ((host . "iRC.CooLguY.NeT")
+ (valid . t))
+ ((host . "gsf.ds342.co.uk")
+ (valid . t))
+ ((host . "324.net.uk")
+ (valid . t))
+ ((host . "xn--bcher-kva.ch")
+ (valid . t))
+ ((host . "-lol-.net.uk")
+ (valid . :false))
+ ((host . "-lol.net.uk")
+ (valid . :false))
+ ((host . "_irc._sctp.lol.net.uk")
+ (valid . :false))
+ ((host . "irc")
+ (valid . :false))
+ ((host . "com")
+ (valid . :false))
+ ((host . "")
+ (valid . :false)))))
diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld
new file mode 100644
index 00000000000..751500537d9
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld
@@ -0,0 +1,3 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "a"))
+((linger 100 LINGER)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld
new file mode 100644
index 00000000000..c906c9e649b
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld
@@ -0,0 +1,3 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS " (? ?:) "b"))
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/linger.eld b/test/lisp/erc/resources/erc-d/resources/linger.eld
new file mode 100644
index 00000000000..36c81a3af4b
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/linger.eld
@@ -0,0 +1,33 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ ;; Just to mix thing's up (force handler to schedule timer)
+ (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 1.2 "MODE #chan")
+ (0 ":bob!~bob@example.org PRIVMSG #chan :hey"))
+
+((linger 1.0 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-block.eld b/test/lisp/erc/resources/erc-d/resources/no-block.eld
new file mode 100644
index 00000000000..1b1f3965637
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-block.eld
@@ -0,0 +1,55 @@
+;;; -*- mode: lisp-data -*-
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.org 002 tester :Your host is irc.org")
+ (0.0 ":irc.org 003 tester :This server was created just now")
+ (0.0 ":irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.org 254 tester 1 :channels formed")
+ (0.0 ":irc.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.org 221 tester +Zi")
+ (0.0 ":irc.org 306 tester :You have been marked as being away"))
+
+((join-foo 1.2 "JOIN #foo")
+ (0 ":tester!~tester@localhost JOIN #foo")
+ (0 ":irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #foo :End of NAMES list"))
+
+;; This would time out if the mode-foo's outgoing blocked (remove minus signs to see)
+((~join-bar 1.5 "JOIN #bar")
+ (0 ":tester!~tester@localhost JOIN #bar")
+ (0 ":irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #bar :End of NAMES list"))
+
+((mode-foo 1.2 "MODE #foo")
+ (0.0 ":irc.example.org 324 tester #foo +Cint")
+ (0.0 ":irc.example.org 329 tester #foo 1519850102")
+ (-0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defence, by mercy, 'tis most just.")
+ (-0.2 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.")
+ (-0.3 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: For these two hours, Rosalind, I will leave thee.")
+ (-0.4 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.")
+ (-0.5 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.")
+ (-0.6 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.")
+ (-0.7 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.")
+ (-0.8 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.")
+ (-0.9 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him.")
+ (-1.0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: If there be truth in sight, you are my Rosalind.")
+ (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That is another's lawful promis'd love.")
+ (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :I am heard."))
+
+((mode-bar 1.5 "MODE #bar")
+ (0.0 ":irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5")
+ (0.0 ":irc.example.org 329 tester #bar :1602642829")
+ (0.1 ":alice!~alice@example.com PRIVMSG #bar :hi 123"))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-match.eld b/test/lisp/erc/resources/erc-d/resources/no-match.eld
new file mode 100644
index 00000000000..d147be1e084
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-match.eld
@@ -0,0 +1,32 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
+
+((join 1.2 "JOIN #chan")
+ (0 ":tester!~tester@localhost JOIN #chan")
+ (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
+
+((mode-chan 0.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/no-pong.eld b/test/lisp/erc/resources/erc-d/resources/no-pong.eld
new file mode 100644
index 00000000000..30cd805d76c
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/no-pong.eld
@@ -0,0 +1,27 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((~ping 1.2 "PING " nonce)
+ (0.1 ":irc.example.org PONG irc.example.com " echo))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/nonstandard.eld b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld
new file mode 100644
index 00000000000..c9cd608e6be
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld
@@ -0,0 +1,6 @@
+;;; -*- mode: lisp-data -*-
+((one 1 "ONE one"))
+((two 1 "TWO two"))
+((blank 1 ""))
+((one-space 1 " "))
+((two-spaces 1 " "))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld
new file mode 100644
index 00000000000..e74d20d5b37
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld
@@ -0,0 +1,24 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) network ":changeme"))
+((nick 1.2 "NICK tester"))
+
+((user 1.2 "USER user 0 * :tester")
+ (0.001 ":" fqdn " 001 tester :Welcome to the BAR Network tester")
+ (0.002 ":" fqdn " 002 tester :Your host is " fqdn)
+ (0.003 ":" fqdn " 003 tester :This server was created just now")
+ (0.004 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.005 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.006 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.007 ":" fqdn " 252 tester 0 :IRC Operators online")
+ (0.008 ":" fqdn " 253 tester 0 :unregistered connections")
+ (0.009 ":" fqdn " 254 tester 1 :channels formed")
+ (0.010 ":" fqdn " 255 tester :I have 3 clients and 0 servers")
+ (0.011 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3")
+ (0.012 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3")
+ (0.013 ":" fqdn " 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.014 ":" fqdn " 221 tester +Zi")
+ (0.015 ":" fqdn " 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld
new file mode 100644
index 00000000000..cc2e9d253c1
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld
@@ -0,0 +1,24 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) network ":changeme"))
+((nick 1.2 "NICK tester"))
+
+((user 2.2 "USER user 0 * :tester")
+ (0.015 ":" fqdn " 001 tester :Welcome to the FOO Network tester")
+ (0.014 ":" fqdn " 002 tester :Your host is " fqdn)
+ (0.013 ":" fqdn " 003 tester :This server was created just now")
+ (0.012 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.011 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.010 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.009 ":" fqdn " 252 tester 0 :IRC Operators online")
+ (0.008 ":" fqdn " 253 tester 0 :unregistered connections")
+ (0.007 ":" fqdn " 254 tester 1 :channels formed")
+ (0.006 ":" fqdn " 255 tester :I have 3 clients and 0 servers")
+ (0.005 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3")
+ (0.004 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3")
+ (0.003 ":" fqdn " 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.002 ":" fqdn " 221 tester +Zi")
+ (0.001 ":" fqdn " 306 tester :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
new file mode 100644
index 00000000000..af216c80edc
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld
@@ -0,0 +1,9 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :" (group (+ alpha)) eos)
+ (0 ":*status!znc@znc.in NOTICE " nick " :You have no networks configured."
+ " Use /znc AddNetwork <network> to add one.")
+ (0 ":irc.znc.in 001 " nick " :Welcome " nick "!"))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
new file mode 100644
index 00000000000..bb8869dff69
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
@@ -0,0 +1,45 @@
+;;; proxy-subprocess.el --- Example setup file for erc-d -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;; Code:
+
+(defvar erc-d-tmpl-vars)
+
+(setq erc-d-tmpl-vars
+
+ (list
+ (cons 'fqdn (lambda (helper)
+ (let ((name (funcall helper :dialog-name)))
+ (funcall helper :set
+ (if (eq name 'proxy-foonet)
+ "irc.foo.net"
+ "irc.bar.net")))))
+
+ (cons 'net (lambda (helper)
+ (let ((name (funcall helper :dialog-name)))
+ (funcall helper :set
+ (if (eq name 'proxy-foonet)
+ "FooNet"
+ "BarNet")))))
+
+ (cons 'network '(group (+ alpha)))))
+
+;;; proxy-subprocess.el ends here
diff --git a/test/lisp/erc/resources/erc-d/resources/timeout.eld b/test/lisp/erc/resources/erc-d/resources/timeout.eld
new file mode 100644
index 00000000000..9cfad4fa8cd
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/timeout.eld
@@ -0,0 +1,27 @@
+;;; -*- mode: lisp-data -*-
+
+((pass 10.0 "PASS " (? ?:) "changeme"))
+((nick 0.2 "NICK tester"))
+
+((user 0.2 "USER user 0 * :tester")
+ (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0 ":irc.example.org 003 tester :This server was created just now")
+ (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0 ":irc.example.org 254 tester 1 :channels formed")
+ (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":irc.example.org 221 tester +Zi")
+ (0 ":irc.example.org 306 tester :You have been marked as being away"))
+
+((mode 0.2 "MODE #chan")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-d/resources/unexpected.eld b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
new file mode 100644
index 00000000000..ac0a8fecfa6
--- /dev/null
+++ b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
@@ -0,0 +1,28 @@
+;;; -*- mode: lisp-data -*-
+((t 10.0 "PASS " (? ?:) "changeme"))
+((t 0.2 "NICK tester"))
+
+((t 0.2 "USER user 0 * :tester")
+ (0.0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester")
+ (0.0 ":irc.example.org 002 tester :Your host is irc.example.org")
+ (0.0 ":irc.example.org 003 tester :This server was created just now")
+ (0.0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
+ (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
+ " :are supported by this server")
+ (0.0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
+ (0.0 ":irc.example.org 252 tester 0 :IRC Operators online")
+ (0.0 ":irc.example.org 253 tester 0 :unregistered connections")
+ (0.0 ":irc.example.org 254 tester 1 :channels formed")
+ (0.0 ":irc.example.org 255 tester :I have 3 clients and 0 servers")
+ (0.0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.0 ":irc.example.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.0 ":irc.example.org 221 tester +Zi")
+
+ (0.0 ":irc.example.org 306 tester :You have been marked as being away")
+ (0.0 ":tester!~tester@localhost JOIN #chan")
+ (0.0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":irc.example.org 366 alice #chan :End of NAMES list")
+ (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el
new file mode 100644
index 00000000000..cbabfcd26be
--- /dev/null
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -0,0 +1,516 @@
+;;; erc-scenarios-common.el --- Common helpers for ERC scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see
+;; <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; These are e2e-ish test cases primarily intended to assert core,
+;; fundamental behavior expected of any modern IRC client. Tests may
+;; also simulate specific scenarios drawn from bug reports. Incoming
+;; messages are provided by playback scripts resembling I/O logs. In
+;; place of time stamps, they have time deltas, which are used to
+;; govern the test server in a fashion reminiscent of music rolls (or
+;; the script(1) UNIX program). These scripts can be found in the
+;; other directories under test/lisp/erc/resources.
+;;
+;; Isolation:
+;;
+;; The set of enabled modules is shared among all tests. The function
+;; `erc-update-modules' activates them (as minor modes), but it never
+;; deactivates them. So there's no going back, and let-binding
+;; `erc-modules' is useless. The safest route is therefore to (1)
+;; assume the set of default modules is already activated or will be
+;; over the course of the test session and (2) let-bind relevant user
+;; options as needed. For example, to limit the damage of
+;; `erc-autojoin-channels-alist' to a given test, assume the
+;; `erc-join' library has already been loaded or will be on the next
+;; call to `erc-open'. And then just let-bind
+;; `erc-autojoin-channels-alist' for the duration of the test.
+;;
+;; Playing nice:
+;;
+;; Right now, these tests all rely on an ugly fixture macro named
+;; `erc-scenarios-common-with-cleanup', which is defined just below.
+;; It helps restore (but not really prepare) the environment by
+;; destroying any stray processes or buffers named in the first
+;; argument, a `let*'-style VAR-LIST. Relying on such a macro is
+;; unfortunate because in many ways it actually hampers readability by
+;; favoring magic over verbosity. But without it (or something
+;; similar), any failing test would cause all subsequent tests in this
+;; file to fail like dominoes (making all but the first backtrace
+;; useless).
+;;
+;; Misc:
+;;
+;; Note that in the following examples, nicknames Alice and Bob are
+;; always associated with the fake network FooNet, while nicks Joe and
+;; Mike are always on BarNet. (Networks are sometimes downcased.)
+;;
+;; XXX This file should *not* contain any test cases.
+
+;;; Code:
+
+(require 'ert-x) ; cl-lib
+(eval-and-compile
+ (let* ((d (expand-file-name ".." (ert-resource-directory)))
+ (load-path (cons (concat d "/erc-d") load-path)))
+ (require 'erc-d-t)
+ (require 'erc-d)))
+
+(require 'erc-backend)
+
+(eval-when-compile (require 'erc-join)
+ (require 'erc-services))
+
+(declare-function erc-network "erc-networks")
+(defvar erc-network)
+
+(defvar erc-scenarios-common--resources-dir
+ (expand-file-name "../" (ert-resource-directory)))
+
+;; Teardown is already inhibited when running interactively, which
+;; prevents subsequent tests from succeeding, so we might as well
+;; treat inspection as the goal.
+(unless noninteractive
+ (setq erc-server-auto-reconnect nil))
+
+(defvar erc-scenarios-common-dialog nil)
+(defvar erc-scenarios-common-extra-teardown nil)
+
+(defun erc-scenarios-common--add-silence ()
+ (advice-add #'erc-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-handle-login :around #'erc-d-t-silence-around)
+ (advice-add #'erc-server-connect :around #'erc-d-t-silence-around))
+
+(defun erc-scenarios-common--remove-silence ()
+ (advice-remove #'erc-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-handle-login #'erc-d-t-silence-around)
+ (advice-remove #'erc-server-connect #'erc-d-t-silence-around))
+
+(defun erc-scenarios-common--print-trace ()
+ (when (and (boundp 'trace-buffer) (get-buffer trace-buffer))
+ (with-current-buffer trace-buffer
+ (message "%S" (buffer-string))
+ (kill-buffer))))
+
+(eval-and-compile
+ (defun erc-scenarios-common--make-bindings (bindings)
+ `((erc-d-u-canned-dialog-dir (expand-file-name
+ (or erc-scenarios-common-dialog
+ (cadr (assq 'erc-scenarios-common-dialog
+ ',bindings)))
+ erc-scenarios-common--resources-dir))
+ (erc-d-tmpl-vars `(,@erc-d-tmpl-vars
+ (quit . ,(erc-quit/part-reason-default))
+ (erc-version . ,erc-version)))
+ (erc-modules (copy-sequence erc-modules))
+ (inhibit-interaction t)
+ (auth-source-do-cache nil)
+ (erc-auth-source-parameters-join-function nil)
+ (erc-autojoin-channels-alist nil)
+ (erc-server-auto-reconnect nil)
+ (erc-d-linger-secs 10)
+ ,@bindings)))
+
+(defmacro erc-scenarios-common-with-cleanup (bindings &rest body)
+ "Provide boilerplate cleanup tasks after calling BODY with BINDINGS.
+
+If an `erc-d' process exists, wait for it to start before running BODY.
+If `erc-autojoin-mode' mode is bound, restore it during cleanup if
+disabled by BODY. Other defaults common to these test cases are added
+below and can be overridden, except when wanting the \"real\" default
+value, which must be looked up or captured outside of the calling form.
+
+Dialog resource directories are located by expanding the variable
+`erc-scenarios-common-dialog' or its value in BINDINGS."
+ (declare (indent 1))
+
+ (let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode"))
+ (combind `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode))
+ ,@(erc-scenarios-common--make-bindings bindings))))
+
+ `(erc-d-t-with-cleanup (,@combind)
+
+ (ert-info ("Restore autojoin, etc., kill ERC buffers")
+ (dolist (buf (buffer-list))
+ (when-let ((erc-d-u--process-buffer)
+ (proc (get-buffer-process buf)))
+ (delete-process proc)))
+
+ (erc-scenarios-common--remove-silence)
+
+ (when erc-scenarios-common-extra-teardown
+ (ert-info ("Running extra teardown")
+ (funcall erc-scenarios-common-extra-teardown)))
+
+ (when (and (boundp 'erc-autojoin-mode)
+ (not (eq erc-autojoin-mode ,orig-autojoin-mode)))
+ (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1)))
+
+ (when noninteractive
+ (erc-scenarios-common--print-trace)
+ (erc-d-t-kill-related-buffers)
+ (delete-other-windows)))
+
+ (erc-scenarios-common--add-silence)
+
+ (ert-info ("Wait for dumb server")
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when erc-d-u--process-buffer
+ (erc-d-t-search-for 3 "Starting")))))
+
+ (ert-info ("Activate erc-debug-irc-protocol")
+ (unless (and noninteractive (not erc-debug-irc-protocol))
+ (erc-toggle-debug-irc-protocol)))
+
+ ,@body)))
+
+(defun erc-scenarios-common-assert-initial-buf-name (id port)
+ ;; Assert no limbo period when explicit ID given
+ (should (string= (if id
+ (symbol-name id)
+ (format "127.0.0.1:%d" port))
+ (buffer-name))))
+
+(defun erc-scenarios-common-buflist (prefix)
+ "Return list of buffers with names sharing PREFIX."
+ (let (case-fold-search)
+ (erc-networks--id-sort-buffers
+ (delq nil
+ (mapcar (lambda (b)
+ (when (string-prefix-p prefix (buffer-name b)) b))
+ (buffer-list))))))
+
+;; This is more realistic than `erc-send-message' because it runs
+;; `erc-pre-send-functions', etc. Keyboard macros may be preferable,
+;; but they sometimes experience complications when an earlier test
+;; has failed.
+(defun erc-scenarios-common-say (str)
+ (let (erc-accidental-paste-threshold-seconds)
+ (goto-char erc-input-marker)
+ (insert str)
+ (erc-send-current-line)))
+
+
+;;;; Fixtures
+
+(cl-defun erc-scenarios-common--base-network-id-bouncer
+ ((&key autop foo-id bar-id after
+ &aux
+ (foo-id (and foo-id 'oofnet))
+ (bar-id (and bar-id 'rabnet))
+ (serv-buf-foo (if foo-id "oofnet" "foonet"))
+ (serv-buf-bar (if bar-id "rabnet" "barnet"))
+ (chan-buf-foo (if foo-id "#chan@oofnet" "#chan@foonet"))
+ (chan-buf-bar (if bar-id "#chan@rabnet" "#chan@barnet")))
+ &rest dialogs)
+ "Ensure retired option `erc-rename-buffers' is now the default behavior.
+The option `erc-rename-buffers' is now deprecated and on by default, so
+this now just asserts baseline behavior. Originally from scenario
+clash-of-chans/rename-buffers as explained in Bug#48598: 28.0.50;
+buffer-naming collisions involving bouncers in ERC."
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/netid/bouncer")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ (erc-server-auto-reconnect autop)
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id foo-id))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name foo-id port)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-foo))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id bar-id))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name bar-id port)
+ (erc-d-t-wait-for 6 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-bar))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Join #chan@barnet")
+ (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan")))
+
+ (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist"
+ (equal (list (get-buffer chan-buf-bar)
+ (get-buffer chan-buf-foo))
+ (erc-scenarios-common-buflist "#chan")))
+
+ (ert-info ("#chan@<esid> is exclusive to foonet")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-search-for 1 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should (eq erc-server-process erc-server-process-foo))
+ (erc-d-t-search-for 10 "ape is dead")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (ert-info ("#chan@<esid> is exclusive to barnet")
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-wait-for 5 (eq erc-server-process erc-server-process-bar))
+ (erc-d-t-search-for 15 "keeps you from dishonour")
+ (erc-d-t-wait-for 5 (not (erc-server-process-alive)))))
+
+ (when after (funcall after))))
+
+(defun erc-scenarios-common--clash-rename-pass-handler (dialog exchange)
+ (when (eq (erc-d-dialog-name dialog) 'stub-again)
+ (let* ((match (erc-d-exchange-match exchange 1))
+ (sym (if (string= match "foonet") 'foonet-again 'barnet-again)))
+ (should (member match (list "foonet" "barnet")))
+ (erc-d-load-replacement-dialog dialog sym 1))))
+
+(defun erc-scenarios-common--base-network-id-bouncer--reconnect (foo-id bar-id)
+ (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet")))))
+ (erc-d-match-handlers
+ ;; Auto reconnect is nondeterministic, so let computer decide
+ (list :pass #'erc-scenarios-common--clash-rename-pass-handler))
+ (after
+ (lambda ()
+ ;; Simulate disconnection and `erc-server-auto-reconnect'
+ (ert-info ("Reconnect to foonet and barnet back-to-back")
+ (with-current-buffer (if foo-id "oofnet" "foonet")
+ (erc-d-t-wait-for 10 (erc-server-process-alive)))
+ (with-current-buffer (if bar-id "rabnet" "barnet")
+ (erc-d-t-wait-for 10 (erc-server-process-alive))))
+
+ (ert-info ("#chan@foonet is exclusive to foonet")
+ (with-current-buffer (if foo-id "#chan@oofnet" "#chan@foonet")
+ (erc-d-t-search-for 1 "<alice>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (erc-d-t-search-for 20 "please your lordship")))
+
+ (ert-info ("#chan@barnet is exclusive to barnet")
+ (with-current-buffer (if bar-id "#chan@rabnet" "#chan@barnet")
+ (erc-d-t-search-for 1 "<joe>")
+ (erc-d-t-absent-for 0.1 "<bob>")
+ (erc-d-t-search-for 20 "much in private")))
+
+ ;; XXX this is important (reconnects overlapped, so we'd get
+ ;; chan@127.0.0.1:6667)
+ (should-not (erc-scenarios-common-buflist "127.0.0.1"))
+ ;; Reconnection order doesn't matter here because session objects
+ ;; are persisted, meaning original timestamps preserved.
+ (should (equal (list (get-buffer (if bar-id "#chan@rabnet"
+ "#chan@barnet"))
+ (get-buffer (if foo-id "#chan@oofnet"
+ "#chan@foonet")))
+ (erc-scenarios-common-buflist "#chan"))))))
+ (erc-scenarios-common--base-network-id-bouncer
+ (list :autop t :foo-id foo-id :bar-id bar-id :after after)
+ 'foonet-drop 'barnet-drop
+ 'stub-again 'stub-again
+ 'foonet-again 'barnet-again)))
+
+(defun erc-scenarios-common--upstream-reconnect (test &rest dialogs)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/upstream-reconnect")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (apply #'erc-d-run "localhost" t dialogs))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester@vanilla/foonet"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) "foonet"))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan@foonet")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "<alice>")))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester@vanilla/barnet"
+ :password "changeme"
+ :full-name "tester")
+ (erc-scenarios-common-assert-initial-buf-name nil port)
+ (erc-d-t-wait-for 10 (eq (erc-network) 'barnet))
+ (erc-d-t-wait-for 3 (string= (buffer-name) "barnet"))
+ (funcall expect 5 "barnet")))
+
+ (ert-info ("Server buffers are unique, no names based on IPs")
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@foonet"))
+ (funcall expect 5 "#chan was created on ")
+ (ert-info ("Joined again #chan@foonet")
+ (funcall expect 10 "#chan was created on "))
+ (funcall expect 10 "My lord, in heart"))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@barnet"))
+ (funcall expect 5 "#chan was created on ")
+ (ert-info ("Joined again #chan@barnet")
+ (funcall expect 10 "#chan was created on "))
+ (funcall expect 10 "Go to; farewell"))
+
+ (funcall test)))
+
+;; XXX this is okay, but we also need to check that target buffers are
+;; already associated with a new process *before* a JOIN is sent by a
+;; server's playback burst. This doesn't do that.
+;;
+;; This *does* check that superfluous JOINs sent by the autojoin
+;; module are harmless when they're not acked (superfluous because the
+;; bouncer/server intitates the JOIN).
+
+(defun erc-scenarios-common--join-network-id (foo-reconnector foo-id bar-id)
+ "Ensure channels rejoined by erc-join.el DTRT.
+Originally from scenario clash-of-chans/autojoin as described in
+Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC."
+ (erc-scenarios-common-with-cleanup
+ ((chan-buf-foo (format "#chan@%s" (or foo-id "foonet")))
+ (chan-buf-bar (format "#chan@%s" (or bar-id "barnet")))
+ (erc-scenarios-common-dialog "join/network-id")
+ (erc-d-t-cleanup-sleep-secs 1)
+ (erc-server-flood-penalty 0.5)
+ (dumb-server (erc-d-run "localhost" t 'foonet 'barnet 'foonet-again))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter))
+ erc-server-buffer-foo erc-server-process-foo
+ erc-server-buffer-bar erc-server-process-bar)
+
+ (should (memq 'autojoin erc-modules))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer
+ (setq erc-server-buffer-foo (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester"
+ :id foo-id))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-scenarios-common-assert-initial-buf-name foo-id port)
+ (erc-d-t-wait-for 5 (eq (erc-network) 'foonet))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("Join #chan, find sentinel, quit")
+ (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 5 "vile thing")
+ (erc-cmd-QUIT "")))
+
+ (erc-d-t-wait-for 2 "Foonet connection deceased"
+ (not (erc-server-process-alive erc-server-buffer-foo)))
+
+ (should (equal erc-autojoin-channels-alist
+ (if foo-id '((oofnet "#chan")) '((foonet "#chan")))))
+
+ (ert-info ("Connect to barnet")
+ (with-current-buffer
+ (setq erc-server-buffer-bar (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "barnet:changeme"
+ :full-name "tester"
+ :id bar-id))
+ (setq erc-server-process-bar erc-server-process)
+ (erc-d-t-wait-for 5 (eq erc-network 'barnet))
+ (should (string= (buffer-name) (if bar-id "rabnet" "barnet")))))
+
+ (ert-info ("Server buffers are unique, no stray IP-based names")
+ (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))
+ (should-not (erc-scenarios-common-buflist "127.0.0.1")))
+
+ (ert-info ("Only one #chan buffer exists")
+ (should (equal (list (get-buffer "#chan"))
+ (erc-scenarios-common-buflist "#chan"))))
+
+ (ert-info ("#chan is not auto-joined")
+ (with-current-buffer "#chan"
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (should-not (process-live-p erc-server-process))
+ (erc-d-t-ensure-for 0.1 "server buffer remains foonet"
+ (eq erc-server-process erc-server-process-foo))))
+
+ (with-current-buffer erc-server-buffer-bar
+ (erc-cmd-JOIN "#chan")
+ (erc-d-t-wait-for 3 (get-buffer chan-buf-foo))
+ (erc-d-t-wait-for 3 (get-buffer chan-buf-bar))
+ (with-current-buffer chan-buf-bar
+ (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-bar))
+ (funcall expect 5 "marry her instantly")))
+
+ (ert-info ("Reconnect to foonet")
+ (with-current-buffer (setq erc-server-buffer-foo
+ (funcall foo-reconnector))
+ (should (member (if foo-id '(oofnet "#chan") '(foonet "#chan"))
+ erc-autojoin-channels-alist))
+ (erc-d-t-wait-for 3 (erc-server-process-alive))
+ (setq erc-server-process-foo erc-server-process)
+ (erc-d-t-wait-for 2 (eq erc-network 'foonet))
+ (should (string= (buffer-name) (if foo-id "oofnet" "foonet")))
+ (funcall expect 5 "foonet")))
+
+ (ert-info ("#chan@foonet is clean, no cross-contamination")
+ (with-current-buffer chan-buf-foo
+ (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-foo))
+ (funcall expect 3 "<bob>")
+ (erc-d-t-absent-for 0.1 "<joe>")
+ (funcall expect 10 "not given me")))
+
+ (ert-info ("All #chan@barnet output received")
+ (with-current-buffer chan-buf-bar
+ (funcall expect 10 "hath an uncle here")))))
+
+(provide 'erc-scenarios-common)
+
+;;; erc-scenarios-common.el ends here
diff --git a/test/lisp/erc/resources/join/auth-source/foonet.eld b/test/lisp/erc/resources/join/auth-source/foonet.eld
new file mode 100644
index 00000000000..32b9e3fa0b6
--- /dev/null
+++ b/test/lisp/erc/resources/join/auth-source/foonet.eld
@@ -0,0 +1,33 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK dummy"))
+((user 1 "USER user 0 * :dummy")
+ (0.00 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
+ (0.01 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version ergo-v2.8.0")
+ (0.00 ":irc.foonet.org 003 dummy :This server was created Tue, 24 May 2022 05:28:42 UTC")
+ (0.00 ":irc.foonet.org 004 dummy irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0.01 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 dummy :There are 0 users and 4 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 dummy 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 dummy 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 dummy 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 dummy :I have 4 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 dummy 4 4 :Current local users 4, max 4")
+ (0.00 ":irc.foonet.org 266 dummy 4 4 :Current global users 4, max 4")
+ (0.00 ":irc.foonet.org 422 dummy :MOTD File is missing"))
+
+((mode 6 "MODE dummy +i")
+ (0.00 ":irc.foonet.org 221 dummy +i")
+ (0.00 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.02 ":irc.foonet.org 221 dummy +i"))
+
+((join 6.47 "JOIN #spam secret")
+ (0.03 ":dummy!~u@w9rfqveugz722.irc JOIN #spam"))
+
+((mode 1 "MODE #spam")
+ (0.01 ":irc.foonet.org 353 dummy = #spam :~tester dummy")
+ (0.00 ":irc.foonet.org 366 dummy #spam :End of NAMES list")
+ (0.01 ":irc.foonet.org 324 dummy #spam +knt secret")
+ (0.03 ":irc.foonet.org 329 dummy #spam 1653370308"))
diff --git a/test/lisp/erc/resources/join/legacy/foonet.eld b/test/lisp/erc/resources/join/legacy/foonet.eld
new file mode 100644
index 00000000000..344ba7c1daf
--- /dev/null
+++ b/test/lisp/erc/resources/join/legacy/foonet.eld
@@ -0,0 +1,38 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 6 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow."))
diff --git a/test/lisp/erc/resources/join/network-id/barnet.eld b/test/lisp/erc/resources/join/network-id/barnet.eld
new file mode 100644
index 00000000000..e33dd6be29e
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/barnet.eld
@@ -0,0 +1,43 @@
+;; -*- mode: lisp-data; -*-
+((pass 2 "PASS :barnet:changeme"))
+((nick 2 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
+ (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.barnet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.barnet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.barnet.org 254 tester 1 :channels formed")
+ (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.barnet.org 422 tester :MOTD File is missing"))
+
+((mode-user 12 "MODE tester +i"))
+;; No mode answer
+
+((join 2 "JOIN #chan")
+ (0 ":tester!~u@6yximxrnkg65a.irc JOIN #chan")
+ (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
+ (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 1 "MODE #chan")
+ (0 ":irc.barnet.org 324 tester #chan +nt")
+ (0 ":irc.barnet.org 329 tester #chan 1620608304")
+ ;; Wait for foonet's buffer playback
+ (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: Go take her hence, and marry her instantly.")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Of all the four, or the three, or the two, or one of the four.")
+ (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And gives the crutch the cradle's infancy.")
+ (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Such is the simplicity of man to hearken after the flesh.")
+ (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: The leaf to read them. Let us toward the king.")
+ (0.05 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Many can brook the weather that love not the wind.")
+ (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And now, dear maid, be you as free to us.")
+ (0.00 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: He hath an uncle here in Messina will be very much glad of it."))
+
+((linger 3.5 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet-again.eld b/test/lisp/erc/resources/join/network-id/foonet-again.eld
new file mode 100644
index 00000000000..b230eff27c7
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/foonet-again.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((pass-redux 10 "PASS :foonet:changeme"))
+((nick-redux 1 "NICK tester"))
+
+((user-redux 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i")
+ ;; No mode answer ^
+
+ ;; History
+ (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...")
+ (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:23] alice: And soar with them above a common bound.")
+ (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:27] bob: And be aveng'd on cursed Tamora.")
+ (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:29] alice: He did love her, sir, as a gentleman loves a woman.")
+ (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete."))
+
+;; As a server, we ignore useless join sent by autojoin module
+((~join 10 "JOIN #chan"))
+
+((mode-redux 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620608304")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Ay, madam, with the swiftest wing of speed.")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Five times in that ere once in our five wits.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: And bid him come to take his last farewell.")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: But we are spirits of another sort.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it."))
+
+((linger 6 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet.eld b/test/lisp/erc/resources/join/network-id/foonet.eld
new file mode 100644
index 00000000000..7d63f5f0c6c
--- /dev/null
+++ b/test/lisp/erc/resources/join/network-id/foonet.eld
@@ -0,0 +1,39 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :foonet:changeme"))
+((nick 1 "NICK tester"))
+
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10.2 "MODE tester +i"))
+;; No mode answer ^
+
+((join 3 "JOIN #chan")
+ (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 3 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620608304")
+ (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Pray you, sir, deliver me this paper.")
+ (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Wake when some vile thing is near."))
+
+((quit 3 "QUIT :\2ERC\2"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/join/reconnect/foonet-again.eld b/test/lisp/erc/resources/join/reconnect/foonet-again.eld
new file mode 100644
index 00000000000..f1fcc439cc3
--- /dev/null
+++ b/test/lisp/erc/resources/join/reconnect/foonet-again.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode."))
+
+((~join-chan 12 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((~join-spam 12 "JOIN #spam")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((~mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon."))
diff --git a/test/lisp/erc/resources/join/reconnect/foonet.eld b/test/lisp/erc/resources/join/reconnect/foonet.eld
new file mode 100644
index 00000000000..efb269f5ae5
--- /dev/null
+++ b/test/lisp/erc/resources/join/reconnect/foonet.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((pass 1 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 3.2 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam")
+ (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
+
+((mode-chan 4 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode-spam 4 "MODE #spam")
+ (0 ":irc.foonet.org 324 tester #spam +nt")
+ (0 ":irc.foonet.org 329 tester #spam 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!")
+ (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/networks/announced-missing/foonet.eld b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
new file mode 100644
index 00000000000..79b0fb462a8
--- /dev/null
+++ b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
@@ -0,0 +1,8 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 1.2 "MODE tester +i")
+ (0 ":tester MODE tester :+Zi"))
diff --git a/test/lisp/erc/resources/services/auth-source/libera.eld b/test/lisp/erc/resources/services/auth-source/libera.eld
new file mode 100644
index 00000000000..c8dbc9d425a
--- /dev/null
+++ b/test/lisp/erc/resources/services/auth-source/libera.eld
@@ -0,0 +1,49 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response")
+ (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com")
+ (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester")
+ (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev")
+ (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC")
+ (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers")
+ (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online")
+ (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)")
+ (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed")
+ (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers")
+ (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289")
+ (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929")
+ (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)")
+ (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ")
+ (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb <https://www.seeweb.it/>")
+ (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for")
+ (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.")
+ (0.01 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies")
+ (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat")
+ (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.02 ":tester MODE tester :+Zi")
+ (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester <password>\2"))
+
+((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme")
+ (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.")
+ (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000."))
+
+((quit 5 "QUIT :\2ERC\2")
+ (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit"))
+
+((linger 1 LINGER))
diff --git a/test/lisp/erc/resources/services/password/libera.eld b/test/lisp/erc/resources/services/password/libera.eld
new file mode 100644
index 00000000000..c8dbc9d425a
--- /dev/null
+++ b/test/lisp/erc/resources/services/password/libera.eld
@@ -0,0 +1,49 @@
+;; -*- mode: lisp-data; -*-
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...")
+ (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response")
+ (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com")
+ (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester")
+ (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev")
+ (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC")
+ (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI")
+ (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server")
+ (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server")
+ (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers")
+ (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online")
+ (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)")
+ (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed")
+ (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers")
+ (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289")
+ (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929")
+ (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)")
+ (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ")
+ (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb <https://www.seeweb.it/>")
+ (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for")
+ (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.")
+ (0.00 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.")
+ (0.01 ":zirconium.libera.chat 372 tester :- ")
+ (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat")
+ (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies")
+ (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat")
+ (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command."))
+
+((mode-user 1.2 "MODE tester +i")
+ (0.02 ":tester MODE tester :+Zi")
+ (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester <password>\2"))
+
+((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme")
+ (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.")
+ (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000."))
+
+((quit 5 "QUIT :\2ERC\2")
+ (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit"))
+
+((linger 1 LINGER))
diff --git a/test/lisp/eshell/em-basic-tests.el b/test/lisp/eshell/em-basic-tests.el
new file mode 100644
index 00000000000..7a24f8b46c3
--- /dev/null
+++ b/test/lisp/eshell/em-basic-tests.el
@@ -0,0 +1,71 @@
+;;; em-basic-tests.el --- em-basic test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for basic Eshell commands.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-basic)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+;;; Tests:
+
+(ert-deftest em-basic-test/umask-print-numeric ()
+ "Test printing umask numerically."
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
+ (should (equal (eshell-test-command-result "umask") "002\n")))
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654)))
+ (should (equal (eshell-test-command-result "umask") "123\n")))
+ ;; Make sure larger numbers don't cause problems.
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775)))
+ (should (equal (eshell-test-command-result "umask") "002\n"))))
+
+(ert-deftest em-basic-test/umask-read-symbolic ()
+ "Test printing umask symbolically."
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
+ (should (equal (eshell-test-command-result "umask -S")
+ "u=rwx,g=rwx,o=rx\n")))
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o654)))
+ (should (equal (eshell-test-command-result "umask -S")
+ "u=wx,g=rx,o=x\n")))
+ ;; Make sure larger numbers don't cause problems.
+ (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775)))
+ (should (equal (eshell-test-command-result "umask -S")
+ "u=rwx,g=rwx,o=rx\n"))))
+
+(ert-deftest em-basic-test/umask-set ()
+ "Test setting umask."
+ (let ((file-modes 0))
+ (cl-letf (((symbol-function 'set-default-file-modes)
+ (lambda (mode) (setq file-modes mode))))
+ (eshell-test-command-result "umask 002")
+ (should (= file-modes #o775))
+ (eshell-test-command-result "umask 123")
+ (should (= file-modes #o654))
+ (eshell-test-command-result "umask $(identity #o222)")
+ (should (= file-modes #o555)))))
+
+;; em-basic-tests.el ends here
diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el
new file mode 100644
index 00000000000..29f5dc05512
--- /dev/null
+++ b/test/lisp/eshell/em-extpipe-tests.el
@@ -0,0 +1,205 @@
+;;; em-extpipe-tests.el --- em-extpipe test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Sean Whitton <spwhitton@spwhitton.name>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+(require 'ert-x)
+(require 'em-extpipe)
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defmacro em-extpipe-tests--deftest (name input &rest body)
+ (declare (indent 2))
+ `(ert-deftest ,name ()
+ (cl-macrolet
+ ((should-parse (expected)
+ `(let ((shell-file-name "sh")
+ (shell-command-switch "-c"))
+ ;; Strip `eshell-trap-errors'.
+ (should (equal ,expected
+ (cadr (eshell-parse-command input))))))
+ (with-substitute-for-temp (&rest body)
+ ;; Substitute name of an actual temporary file and/or
+ ;; buffer into `input'. The substitution logic is
+ ;; appropriate for only the use we put it to in this file.
+ `(ert-with-temp-file temp
+ (let ((temp-buffer (generate-new-buffer " *temp*" t)))
+ (unwind-protect
+ (let ((input
+ (replace-regexp-in-string
+ "temp\\([^>]\\|\\'\\)" temp
+ (string-replace "#<buffer temp>"
+ (buffer-name temp-buffer)
+ input))))
+ ,@body)
+ (when (buffer-name temp-buffer)
+ (kill-buffer temp-buffer))))))
+ (temp-should-string= (expected)
+ `(string= ,expected (string-trim-right
+ (with-temp-buffer
+ (insert-file-contents temp)
+ (buffer-string)))))
+ (temp-buffer-should-string= (expected)
+ `(string= ,expected (string-trim-right
+ (with-current-buffer temp-buffer
+ (buffer-string))))))
+ (skip-unless shell-file-name)
+ (skip-unless shell-command-switch)
+ (skip-unless (executable-find shell-file-name))
+ (let ((input ,input))
+ (with-temp-eshell ,@body)))))
+
+(em-extpipe-tests--deftest em-extpipe-test-1
+ "echo \"bar\" *| rev >temp"
+ (skip-unless (executable-find "rev"))
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "echo \"bar\" | rev >temp")))
+ (with-substitute-for-temp
+ (eshell-command-result-p input "^$")
+ (temp-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-2
+ "echo \"bar\" | rev *>temp"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "echo" (list (eshell-escape-arg "bar")))
+ (eshell-named-command "sh" (list "-c" "rev >temp")))))
+ (with-substitute-for-temp
+ (eshell-command-result-p input "^$")
+ (temp-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-3 "foo *| bar | baz -d"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "sh" (list "-c" "foo | bar"))
+ (eshell-named-command "baz" (list "-d"))))))
+
+(em-extpipe-tests--deftest em-extpipe-test-4
+ "echo \"bar\" *| rev >#<buffer temp>"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite
+ (get-buffer-create "temp")))
+ (eshell-named-command "sh"
+ (list "-c" "echo \"bar\" | rev"))))
+ (with-substitute-for-temp
+ (eshell-command-result-p input "^$")
+ (temp-buffer-should-string= "rab")))
+
+(em-extpipe-tests--deftest em-extpipe-test-5
+ "foo *| bar >#<buffer quux> baz"
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "foo | bar >#<buffer quux> baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-6
+ "foo >#<buffer quux> *| bar baz"
+ (should-parse '(eshell-named-command
+ "sh" (list "-c" "foo >#<buffer quux> | bar baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-7
+ "foo *| bar >#<buffer quux> >>#<process other>"
+ (should-parse
+ '(progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite
+ (get-buffer-create "quux")))
+ (ignore
+ (eshell-set-output-handle 1 'append
+ (get-process "other")))
+ (eshell-named-command "sh"
+ (list "-c" "foo | bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-8
+ "foo *| bar >/dev/kill | baz"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((progn
+ (ignore
+ (eshell-set-output-handle 1 'overwrite "/dev/kill"))
+ (eshell-named-command "sh"
+ (list "-c" "foo | bar")))
+ (eshell-named-command "baz")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-9 "foo \\*| bar"
+ (should-parse
+ '(eshell-execute-pipeline
+ '((eshell-named-command "foo"
+ (list (eshell-escape-arg "*")))
+ (eshell-named-command "bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-10 "foo \"*|\" *>bar"
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "foo \"*|\" >bar"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-11 "foo '*|' bar"
+ (should-parse '(eshell-named-command
+ "foo" (list (eshell-escape-arg "*|") "bar"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-12 ">foo bar *| baz"
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" ">foo bar | baz"))))
+
+(em-extpipe-tests--deftest em-extpipe-test-13 "foo*|bar"
+ (should-parse '(eshell-execute-pipeline
+ '((eshell-named-command (eshell-concat nil "foo" "*"))
+ (eshell-named-command "bar")))))
+
+(em-extpipe-tests--deftest em-extpipe-test-14 "tac *<temp"
+ (skip-unless (executable-find "tac"))
+ (should-parse '(eshell-named-command "sh" (list "-c" "tac <temp")))
+ (with-substitute-for-temp
+ (with-temp-buffer (insert "bar\nbaz\n") (write-file temp))
+ (eshell-command-result-p input "baz\nbar")))
+
+(em-extpipe-tests--deftest em-extpipe-test-15 "echo \"bar\" *| cat"
+ (skip-unless (executable-find "cat"))
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "echo \"bar\" | cat")))
+ (cl-letf (((symbol-function 'eshell/cat)
+ (lambda (&rest _args) (eshell-print "nonsense"))))
+ (eshell-command-result-p input "bar")
+ (eshell-command-result-p "echo \"bar\" | cat" "nonsense")))
+
+(em-extpipe-tests--deftest em-extpipe-test-16 "echo \"bar\" *| rev"
+ (skip-unless (executable-find "rev"))
+ (should-parse
+ '(eshell-named-command "sh" (list "-c" "echo \"bar\" | rev")))
+ (let ((eshell-prefer-lisp-functions t))
+ (cl-letf (((symbol-function 'rev)
+ (lambda (&rest _args) (eshell-print "nonsense"))))
+ (eshell-command-result-p input "rab")
+ (eshell-command-result-p "echo \"bar\" | rev" "nonsense"))))
+
+;; Confirm we don't break input of sharp-quoted symbols (Bug#53518).
+(em-extpipe-tests--deftest em-extpipe-test-17 "funcall #'upcase foo"
+ (eshell-command-result-p input "FOO"))
+
+;;; em-extpipe-tests.el ends here
diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el
new file mode 100644
index 00000000000..b733be35d9a
--- /dev/null
+++ b/test/lisp/eshell/em-glob-tests.el
@@ -0,0 +1,197 @@
+;;; em-glob-tests.el --- em-glob test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's glob expansion.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-glob)
+
+(defmacro with-fake-files (files &rest body)
+ "Evaluate BODY forms, pretending that FILES exist on the filesystem.
+FILES is a list of file names that should be reported as
+appropriate by `file-name-all-completions'. Any file name
+component ending in \"symlink\" is treated as a symbolic link."
+ (declare (indent 1))
+ `(cl-letf (((symbol-function 'file-name-all-completions)
+ (lambda (file directory)
+ (cl-assert (string= file ""))
+ (setq directory (expand-file-name directory))
+ `("./" "../"
+ ,@(delete-dups
+ (remq nil
+ (mapcar
+ (lambda (file)
+ (setq file (expand-file-name file))
+ (when (string-prefix-p directory file)
+ (replace-regexp-in-string
+ "/.*" "/"
+ (substring file (length directory)))))
+ ,files))))))
+ ((symbol-function 'file-symlink-p)
+ (lambda (file)
+ (string-suffix-p "symlink" file))))
+ ,@body))
+
+;;; Tests:
+
+(ert-deftest em-glob-test/match-any-string ()
+ "Test that \"*\" pattern matches any string."
+ (with-fake-files '("a.el" "b.el" "c.txt" "dir/a.el")
+ (should (equal (eshell-extended-glob "*.el")
+ '("a.el" "b.el")))))
+
+(ert-deftest em-glob-test/match-any-directory ()
+ "Test that \"*/\" pattern matches any directory."
+ (with-fake-files '("a.el" "b.el" "dir/a.el" "dir/sub/a.el" "symlink/")
+ (should (equal (eshell-extended-glob "*/")
+ '("dir/" "symlink/")))))
+
+(ert-deftest em-glob-test/match-any-character ()
+ "Test that \"?\" pattern matches any character."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el")
+ (should (equal (eshell-extended-glob "?.el")
+ '("a.el" "b.el")))))
+
+(ert-deftest em-glob-test/match-recursive ()
+ "Test that \"**/\" recursively matches directories."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el" "dir/sub/a.el"
+ "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el")
+ (should (equal (eshell-extended-glob "**/a.el")
+ '("a.el" "dir/a.el" "dir/sub/a.el")))
+ (should (equal (eshell-extended-glob "**/")
+ '("dir/" "dir/sub/")))))
+
+(ert-deftest em-glob-test/match-recursive-follow-symlinks ()
+ "Test that \"***/\" recursively matches directories, following symlinks."
+ (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el" "dir/sub/a.el"
+ "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el")
+ (should (equal (eshell-extended-glob "***/a.el")
+ '("a.el" "dir/a.el" "dir/sub/a.el" "dir/symlink/a.el"
+ "symlink/a.el" "symlink/sub/a.el")))
+ (should (equal (eshell-extended-glob "***/")
+ '("dir/" "dir/sub/" "dir/symlink/" "symlink/"
+ "symlink/sub/")))))
+
+(ert-deftest em-glob-test/match-recursive-mixed ()
+ "Test combination of \"**/\" and \"***/\"."
+ (with-fake-files '("dir/a.el" "dir/sub/a.el" "dir/sub2/a.el"
+ "dir/symlink/a.el" "dir/sub/symlink/a.el" "symlink/a.el"
+ "symlink/sub/a.el" "symlink/sub/symlink/a.el")
+ (should (equal (eshell-extended-glob "**/sub/***/a.el")
+ '("dir/sub/a.el" "dir/sub/symlink/a.el")))
+ (should (equal (eshell-extended-glob "***/sub/**/a.el")
+ '("dir/sub/a.el" "symlink/sub/a.el")))))
+
+(ert-deftest em-glob-test/match-character-set-individual ()
+ "Test \"[...]\" for individual characters."
+ (with-fake-files '("a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[ab].el")
+ '("a.el" "b.el")))
+ (should (equal (eshell-extended-glob "[^ab].el")
+ '("c.el" "d.el")))))
+
+(ert-deftest em-glob-test/match-character-set-range ()
+ "Test \"[...]\" for character ranges."
+ (with-fake-files '("a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[a-c].el")
+ '("a.el" "b.el" "c.el")))
+ (should (equal (eshell-extended-glob "[^a-c].el")
+ '("d.el")))))
+
+(ert-deftest em-glob-test/match-character-set-class ()
+ "Test \"[...]\" for character classes."
+ (with-fake-files '("1.el" "a.el" "b.el" "c.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[[:alpha:]].el")
+ '("a.el" "b.el" "c.el")))
+ (should (equal (eshell-extended-glob "[^[:alpha:]].el")
+ '("1.el")))))
+
+(ert-deftest em-glob-test/match-character-set-mixed ()
+ "Test \"[...]\" with multiple kinds of members at once."
+ (with-fake-files '("1.el" "a.el" "b.el" "c.el" "d.el" "dir/a.el")
+ (should (equal (eshell-extended-glob "[ac-d[:digit:]].el")
+ '("1.el" "a.el" "c.el" "d.el")))
+ (should (equal (eshell-extended-glob "[^ac-d[:digit:]].el")
+ '("b.el")))))
+
+(ert-deftest em-glob-test/match-group-alternative ()
+ "Test \"(x|y)\" matches either \"x\" or \"y\"."
+ (with-fake-files '("em-alias.el" "em-banner.el" "esh-arg.el" "misc.el"
+ "test/em-xtra.el")
+ (should (equal (eshell-extended-glob "e(m|sh)-*.el")
+ '("em-alias.el" "em-banner.el" "esh-arg.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-characters ()
+ "Test that \"x#\" and \"x#\" match zero or more instances of \"x\"."
+ (with-fake-files '("h.el" "ha.el" "hi.el" "hii.el" "dir/hi.el")
+ (should (equal (eshell-extended-glob "hi#.el")
+ '("h.el" "hi.el" "hii.el")))
+ (should (equal (eshell-extended-glob "hi##.el")
+ '("hi.el" "hii.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-groups ()
+ "Test that \"(x)#\" and \"(x)#\" match zero or more instances of \"(x)\"."
+ (with-fake-files '("h.el" "ha.el" "hi.el" "hii.el" "dir/hi.el")
+ (should (equal (eshell-extended-glob "hi#.el")
+ '("h.el" "hi.el" "hii.el")))
+ (should (equal (eshell-extended-glob "hi##.el")
+ '("hi.el" "hii.el")))))
+
+(ert-deftest em-glob-test/match-n-or-more-character-sets ()
+ "Test that \"[x]#\" and \"[x]#\" match zero or more instances of \"[x]\"."
+ (with-fake-files '("w.el" "wh.el" "wha.el" "whi.el" "whaha.el" "dir/wha.el")
+ (should (equal (eshell-extended-glob "w[ah]#.el")
+ '("w.el" "wh.el" "wha.el" "whaha.el")))
+ (should (equal (eshell-extended-glob "w[ah]##.el")
+ '("wh.el" "wha.el" "whaha.el")))))
+
+(ert-deftest em-glob-test/match-x-but-not-y ()
+ "Test that \"x~y\" matches \"x\" but not \"y\"."
+ (with-fake-files '("1" "12" "123" "42" "dir/1")
+ (should (equal (eshell-extended-glob "[[:digit:]]##~4?")
+ '("1" "12" "123")))))
+
+(ert-deftest em-glob-test/match-dot-files ()
+ "Test that dot files are matched correctly."
+ (with-fake-files '("foo.el" ".emacs")
+ (should (equal (eshell-extended-glob ".*")
+ '("../" "./" ".emacs")))
+ (let (eshell-glob-include-dot-dot)
+ (should (equal (eshell-extended-glob ".*")
+ '(".emacs"))))
+ (let ((eshell-glob-include-dot-files t))
+ (should (equal (eshell-extended-glob "*")
+ '("../" "./" ".emacs" "foo.el")))
+ (let (eshell-glob-include-dot-dot)
+ (should (equal (eshell-extended-glob "*")
+ '(".emacs" "foo.el")))))))
+
+(ert-deftest em-glob-test/no-matches ()
+ "Test behavior when a glob fails to match any files."
+ (with-fake-files '("foo.el" "bar.el")
+ (should (equal (eshell-extended-glob "*.txt")
+ "*.txt"))
+ (let ((eshell-error-if-no-glob t))
+ (should-error (eshell-extended-glob "*.txt")))))
+
+;; em-glob-tests.el ends here
diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el
new file mode 100644
index 00000000000..c8c1a6a9317
--- /dev/null
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -0,0 +1,566 @@
+;;; em-pred-tests.el --- em-pred test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's argument predicates/modifiers.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+(require 'em-glob)
+(require 'em-pred)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+(defun eshell-eval-predicate (initial-value predicate)
+ "Evaluate PREDICATE on INITIAL-VALUE, returning the result.
+PREDICATE is an Eshell argument predicate/modifier."
+ (let ((eshell-test-value initial-value))
+ (ignore-errors
+ (eshell-test-command-result
+ (format "echo $eshell-test-value(%s)" predicate)))))
+
+(defun eshell-parse-file-name-attributes (file)
+ "Parse a fake FILE name to determine its attributes.
+Fake file names are file names beginning with \"/fake/\". This
+allows defining file names for fake files with various properties
+to query via predicates. Attributes are written as a
+comma-separate list of ATTR=VALUE pairs as the file's base name,
+like:
+
+ /fake/type=-,modes=0755.el
+
+The following attributes are recognized:
+
+ * \"type\": A single character describing the file type;
+ accepts the same values as the first character of the file
+ modes in `ls -l'.
+ * \"modes\": The file's permission modes, in octal.
+ * \"links\": The number of links to this file.
+ * \"uid\": The UID of the file's owner.
+ * \"gid\": The UID of the file's group.
+ * \"atime\": The time the file was last accessed, in seconds
+ since the UNIX epoch.
+ * \"mtime\": As \"atime\", but for modification time.
+ * \"ctime\": As \"atime\", but for inode change time.
+ * \"size\": The file's size in bytes."
+ (mapcar (lambda (i)
+ (pcase (split-string i "=")
+ (`("modes" ,modes)
+ (cons 'modes (string-to-number modes 8)))
+ (`(,(and (or "links" "uid" "gid" "size") key) ,value)
+ (cons (intern key) (string-to-number value)))
+ (`(,(and (or "atime" "mtime" "ctime") key) ,value)
+ (cons (intern key) (time-convert (string-to-number value))))
+ (`(,key ,value)
+ (cons (intern key) value))
+ (_ (error "invalid format %S" i))))
+ (split-string (file-name-base file) ",")))
+
+(defmacro eshell-partial-let-func (overrides &rest body)
+ "Temporarily bind to FUNCTION-NAMEs and evaluate BODY.
+This is roughly analogous to advising functions, but only does so
+while BODY is executing, and only calls NEW-FUNCTION if its first
+argument is a string beginning with \"/fake/\".
+
+This allows selectively overriding functions to test file
+properties with fake files without altering the functions'
+behavior for real files.
+
+\(fn ((FUNCTION-NAME NEW-FUNCTION) ...) BODY...)"
+ (declare (indent 1))
+ `(cl-letf
+ ,(mapcar
+ (lambda (override)
+ `((symbol-function #',(car override))
+ (let ((orig-function (symbol-function #',(car override))))
+ (lambda (file &rest rest)
+ (apply
+ (if (and (stringp file) (string-prefix-p "/fake/" file))
+ ,(cadr override)
+ orig-function)
+ file rest)))))
+ overrides)
+ ,@body))
+
+(defmacro eshell-with-file-attributes-from-name (&rest body)
+ "Temporarily override file attribute functions and evaluate BODY."
+ (declare (indent 0))
+ `(eshell-partial-let-func
+ ((file-attributes
+ (lambda (file &optional _id-format)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (list (equal (alist-get 'type attrs) "d")
+ (or (alist-get 'links attrs) 1)
+ (or (alist-get 'uid attrs) 0)
+ (or (alist-get 'gid attrs) 0)
+ (or (alist-get 'atime attrs) nil)
+ (or (alist-get 'mtime attrs) nil)
+ (or (alist-get 'ctime attrs) nil)
+ (or (alist-get 'size attrs) 0)
+ (format "%s---------" (or (alist-get 'type attrs) "-"))
+ nil 0 0))))
+ (file-modes
+ (lambda (file _nofollow)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (or (alist-get 'modes attrs) 0))))
+ (file-exists-p #'always)
+ (file-regular-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (member (or (alist-get 'type attrs) "-") '("-" "l")))))
+ (file-symlink-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ (equal (alist-get 'type attrs) "l"))))
+ (file-executable-p
+ (lambda (file)
+ (let ((attrs (eshell-parse-file-name-attributes file)))
+ ;; For simplicity, just return whether the file is
+ ;; world-executable.
+ (= (logand (or (alist-get 'modes attrs) 0) 1) 1)))))
+ ,@body))
+
+;;; Tests:
+
+
+;; Argument predicates
+
+(ert-deftest em-pred-test/predicate-file-types ()
+ "Test file type predicates."
+ (eshell-with-file-attributes-from-name
+ (let ((files (mapcar (lambda (i) (format "/fake/type=%s" i))
+ '("b" "c" "d/" "p" "s" "l" "-"))))
+ (should (equal (eshell-eval-predicate files "%")
+ '("/fake/type=b" "/fake/type=c")))
+ (should (equal (eshell-eval-predicate files "%b") '("/fake/type=b")))
+ (should (equal (eshell-eval-predicate files "%c") '("/fake/type=c")))
+ (should (equal (eshell-eval-predicate files "/") '("/fake/type=d/")))
+ (should (equal (eshell-eval-predicate files ".") '("/fake/type=-")))
+ (should (equal (eshell-eval-predicate files "p") '("/fake/type=p")))
+ (should (equal (eshell-eval-predicate files "=") '("/fake/type=s")))
+ (should (equal (eshell-eval-predicate files "@") '("/fake/type=l"))))))
+
+(ert-deftest em-pred-test/predicate-executable ()
+ "Test that \"*\" matches only regular, non-symlink executable files."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/modes=0777" "/fake/modes=0666"
+ "/fake/type=d,modes=0777" "/fake/type=l,modes=0777")))
+ (should (equal (eshell-eval-predicate files "*")
+ '("/fake/modes=0777"))))))
+
+(defmacro em-pred-test--file-modes-deftest (name mode-template predicates
+ &optional docstring)
+ "Define NAME as a file-mode test.
+MODE-TEMPLATE is a format string to convert an integer from 0 to
+7 to an octal file mode. PREDICATES is a list of strings for the
+read, write, and execute predicates to query the file's modes."
+ (declare (indent 4) (doc-string 4))
+ `(ert-deftest ,name ()
+ ,docstring
+ (eshell-with-file-attributes-from-name
+ (let ((file-template (concat "/fake/modes=" ,mode-template)))
+ (cl-flet ((make-files (perms)
+ (mapcar (lambda (i) (format file-template i))
+ perms)))
+ (pcase-let ((files (make-files (number-sequence 0 7)))
+ (`(,read ,write ,exec) ,predicates))
+ (should (equal (eshell-eval-predicate files read)
+ (make-files '(4 5 6 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" read))
+ (make-files '(0 1 2 3))))
+ (should (equal (eshell-eval-predicate files write)
+ (make-files '(2 3 6 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" write))
+ (make-files '(0 1 4 5))))
+ (should (equal (eshell-eval-predicate files exec)
+ (make-files '(1 3 5 7))))
+ (should (equal (eshell-eval-predicate files (concat "^" exec))
+ (make-files '(0 2 4 6))))))))))
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-owner
+ "0%o00" '("r" "w" "x")
+ "Test predicates for file permissions for the owner.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-group
+ "00%o0" '("A" "I" "E")
+ "Test predicates for file permissions for the group.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-world
+ "000%o" '("R" "W" "X")
+ "Test predicates for file permissions for the world.")
+
+(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-flags
+ "%o000" '("s" "S" "t")
+ "Test predicates for \"s\" (setuid), \"S\" (setgid), and \"t\" (sticky).")
+
+(ert-deftest em-pred-test/predicate-effective-uid ()
+ "Test that \"U\" matches files owned by the effective UID."
+ (eshell-with-file-attributes-from-name
+ (cl-letf (((symbol-function 'user-uid) (lambda () 1)))
+ (let ((files '("/fake/uid=1" "/fake/uid=2")))
+ (should (equal (eshell-eval-predicate files "U")
+ '("/fake/uid=1")))))))
+
+(ert-deftest em-pred-test/predicate-effective-gid ()
+ "Test that \"G\" matches files owned by the effective GID."
+ (eshell-with-file-attributes-from-name
+ (cl-letf (((symbol-function 'group-gid) (lambda () 1)))
+ (let ((files '("/fake/gid=1" "/fake/gid=2")))
+ (should (equal (eshell-eval-predicate files "G")
+ '("/fake/gid=1")))))))
+
+(ert-deftest em-pred-test/predicate-links ()
+ "Test that \"l\" filters by number of links."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/links=1" "/fake/links=2" "/fake/links=3")))
+ (should (equal (eshell-eval-predicate files "l1")
+ '("/fake/links=1")))
+ (should (equal (eshell-eval-predicate files "l+1")
+ '("/fake/links=2" "/fake/links=3")))
+ (should (equal (eshell-eval-predicate files "l-3")
+ '("/fake/links=1" "/fake/links=2"))))))
+
+(ert-deftest em-pred-test/predicate-uid ()
+ "Test that \"u\" filters by UID/user name."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/uid=1" "/fake/uid=2"))
+ (user-names '("root" "one" "two")))
+ (should (equal (eshell-eval-predicate files "u1")
+ '("/fake/uid=1")))
+ (cl-letf (((symbol-function 'eshell-user-id)
+ (lambda (name) (seq-position user-names name))))
+ (should (equal (eshell-eval-predicate files "u'one'")
+ '("/fake/uid=1")))))))
+
+(ert-deftest em-pred-test/predicate-gid ()
+ "Test that \"g\" filters by GID/group name."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/gid=1" "/fake/gid=2"))
+ (group-names '("root" "one" "two")))
+ (should (equal (eshell-eval-predicate files "g1")
+ '("/fake/gid=1")))
+ (cl-letf (((symbol-function 'eshell-group-id)
+ (lambda (name) (seq-position group-names name))))
+ (should (equal (eshell-eval-predicate files "g'one'")
+ '("/fake/gid=1")))))))
+
+(defmacro em-pred-test--time-deftest (name file-attribute predicate
+ &optional docstring)
+ "Define NAME as a file-time test.
+FILE-ATTRIBUTE is the file's attribute to set (e.g. \"atime\").
+PREDICATE is the predicate used to query that attribute."
+ (declare (indent 4) (doc-string 4))
+ `(ert-deftest ,name ()
+ ,docstring
+ (eshell-with-file-attributes-from-name
+ (cl-flet ((make-file (time)
+ (format "/fake/%s=%d" ,file-attribute time)))
+ (let* ((now (time-convert nil 'integer))
+ (yesterday (- now 86400))
+ (files (mapcar #'make-file (list now yesterday))))
+ ;; Test comparison against a number of days.
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "-1"))
+ (mapcar #'make-file (list now))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+1"))
+ (mapcar #'make-file (list yesterday))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+2"))
+ nil))
+ ;; Test comparison against a number of hours.
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "h-1"))
+ (mapcar #'make-file (list now))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "h+1"))
+ (mapcar #'make-file (list yesterday))))
+ (should (equal (eshell-eval-predicate
+ files (concat ,predicate "+48"))
+ nil))
+ ;; Test comparison against another file.
+ (should (equal (eshell-eval-predicate
+ files (format "%s-'%s'" ,predicate (make-file now)))
+ nil))
+ (should (equal (eshell-eval-predicate
+ files (format "%s+'%s'" ,predicate (make-file now)))
+ (mapcar #'make-file (list yesterday)))))))))
+
+(em-pred-test--time-deftest em-pred-test/predicate-access-time
+ "atime" "a"
+ "Test that \"a\" filters by access time.")
+
+(em-pred-test--time-deftest em-pred-test/predicate-modification-time
+ "mtime" "m"
+ "Test that \"m\" filters by change time.")
+
+(em-pred-test--time-deftest em-pred-test/predicate-change-time
+ "ctime" "c"
+ "Test that \"c\" filters by change time.")
+
+(ert-deftest em-pred-test/predicate-size ()
+ "Test that \"L\" filters by file size."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/size=0"
+ ;; 1 and 2 KiB.
+ "/fake/size=1024" "/fake/size=2048"
+ ;; 1 and 2 MiB.
+ "/fake/size=1048576" "/fake/size=2097152")))
+ ;; Size in bytes.
+ (should (equal (eshell-eval-predicate files "L2048")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "L+2048")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "L-2048")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in blocks.
+ (should (equal (eshell-eval-predicate files "Lp4")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "Lp+4")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "Lp-4")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in KiB.
+ (should (equal (eshell-eval-predicate files "Lk2")
+ '("/fake/size=2048")))
+ (should (equal (eshell-eval-predicate files "Lk+2")
+ '("/fake/size=1048576" "/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "Lk-2")
+ '("/fake/size=0" "/fake/size=1024")))
+ ;; Size in MiB.
+ (should (equal (eshell-eval-predicate files "LM1")
+ '("/fake/size=1048576")))
+ (should (equal (eshell-eval-predicate files "LM+1")
+ '("/fake/size=2097152")))
+ (should (equal (eshell-eval-predicate files "LM-1")
+ '("/fake/size=0" "/fake/size=1024" "/fake/size=2048"))))))
+
+
+;; Argument modifiers
+
+(ert-deftest em-pred-test/modifier-eval ()
+ "Test that \":E\" re-evaluates the value."
+ (should (equal (eshell-eval-predicate "${echo hi}" ":E") "hi"))
+ (should (equal (eshell-eval-predicate
+ '("${echo hi}" "$(upcase \"bye\")") ":E")
+ '("hi" "BYE"))))
+
+(ert-deftest em-pred-test/modifier-downcase ()
+ "Test that \":L\" downcases values."
+ (should (equal (eshell-eval-predicate "FOO" ":L") "foo"))
+ (should (equal (eshell-eval-predicate '("FOO" "BAR") ":L")
+ '("foo" "bar"))))
+
+(ert-deftest em-pred-test/modifier-upcase ()
+ "Test that \":U\" upcases values."
+ (should (equal (eshell-eval-predicate "foo" ":U") "FOO"))
+ (should (equal (eshell-eval-predicate '("foo" "bar") ":U")
+ '("FOO" "BAR"))))
+
+(ert-deftest em-pred-test/modifier-capitalize ()
+ "Test that \":C\" capitalizes values."
+ (should (equal (eshell-eval-predicate "foo bar" ":C") "Foo Bar"))
+ (should (equal (eshell-eval-predicate '("foo bar" "baz") ":C")
+ '("Foo Bar" "Baz"))))
+
+(ert-deftest em-pred-test/modifier-dirname ()
+ "Test that \":h\" returns the dirname."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":h") "/path/to/"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":h")
+ '("/path/to/" "/other/path/"))))
+
+(ert-deftest em-pred-test/modifier-basename ()
+ "Test that \":t\" returns the basename."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":t") "file.el"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":t")
+ '("file.el" ""))))
+
+(ert-deftest em-pred-test/modifier-extension ()
+ "Test that \":e\" returns the extension."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":e") "el"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":e")
+ '("el" nil))))
+
+(ert-deftest em-pred-test/modifier-sans-extension ()
+ "Test that \":r\" returns the file name san extension."
+ (should (equal (eshell-eval-predicate "/path/to/file.el" ":r")
+ "/path/to/file"))
+ (should (equal (eshell-eval-predicate
+ '("/path/to/file.el" "/other/path/") ":r")
+ '("/path/to/file" "/other/path/"))))
+
+(ert-deftest em-pred-test/modifier-quote ()
+ "Test that \":q\" quotes arguments."
+ (should (equal-including-properties
+ (eshell-eval-predicate '("foo" "bar") ":q")
+ (list (eshell-escape-arg "foo") (eshell-escape-arg "bar")))))
+
+(ert-deftest em-pred-test/modifier-substitute ()
+ "Test that \":s/PAT/REP/\" replaces PAT with REP once."
+ (should (equal (eshell-eval-predicate "bar" ":s/a/*/") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s|a|*|") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s{a}{*}") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":s{a}'*'") "b*r"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s/[ao]/*/")
+ '("f*o" "b*r" "b*z")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s|[ao]|*|")
+ '("f*o" "b*r" "b*z"))))
+
+(ert-deftest em-pred-test/modifier-global-substitute ()
+ "Test that \":s/PAT/REP/\" replaces PAT with REP for all occurrences."
+ (should (equal (eshell-eval-predicate "foo" ":gs/a/*/") "foo"))
+ (should (equal (eshell-eval-predicate "foo" ":gs|a|*|") "foo"))
+ (should (equal (eshell-eval-predicate "bar" ":gs/a/*/") "b*r"))
+ (should (equal (eshell-eval-predicate "bar" ":gs|a|*|") "b*r"))
+ (should (equal (eshell-eval-predicate "foo" ":gs/o/O/") "fOO"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs/[aeiou]/*/")
+ '("f**" "b*r" "b*z")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs|[aeiou]|*|")
+ '("f**" "b*r" "b*z"))))
+
+(ert-deftest em-pred-test/modifier-include ()
+ "Test that \":i/PAT/\" filters elements to include only ones matching PAT."
+ (should (equal (eshell-eval-predicate "foo" ":i/a/") nil))
+ (should (equal (eshell-eval-predicate "bar" ":i/a/") "bar"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":i/a/")
+ '("bar" "baz"))))
+
+(ert-deftest em-pred-test/modifier-exclude ()
+ "Test that \":x/PAT/\" filters elements to exclude any matching PAT."
+ (should (equal (eshell-eval-predicate "foo" ":x/a/") "foo"))
+ (should (equal (eshell-eval-predicate "bar" ":x/a/") nil))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":x/a/")
+ '("foo"))))
+
+(ert-deftest em-pred-test/modifier-split ()
+ "Test that \":S\" and \":S/PAT/\" split elements by spaces (or PAT)."
+ (should (equal (eshell-eval-predicate "foo bar baz" ":S")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo bar" "baz") ":S")
+ '(("foo" "bar") ("baz"))))
+ (should (equal (eshell-eval-predicate "foo-bar-baz" ":S/-/")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo-bar" "baz") ":S/-/")
+ '(("foo" "bar") ("baz")))))
+
+(ert-deftest em-pred-test/modifier-join ()
+ "Test that \":j\" and \":j/DELIM/\" join elements by spaces (or DELIM)."
+ (should (equal (eshell-eval-predicate "foo" ":j") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j")
+ "foo bar baz"))
+ (should (equal (eshell-eval-predicate "foo" ":j/-/") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j/-/")
+ "foo-bar-baz")))
+
+(ert-deftest em-pred-test/modifier-sort ()
+ "Test that \":o\" sorts elements in lexicographic order."
+ (should (equal (eshell-eval-predicate "foo" ":o") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":o")
+ '("bar" "baz" "foo"))))
+
+(ert-deftest em-pred-test/modifier-sort-reverse ()
+ "Test that \":o\" sorts elements in reverse lexicographic order."
+ (should (equal (eshell-eval-predicate "foo" ":O") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":O")
+ '("foo" "baz" "bar"))))
+
+(ert-deftest em-pred-test/modifier-unique ()
+ "Test that \":u\" filters out duplicate elements."
+ (should (equal (eshell-eval-predicate "foo" ":u") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":u")
+ '("foo" "bar" "baz")))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz" "foo") ":u")
+ '("foo" "bar" "baz"))))
+
+(ert-deftest em-pred-test/modifier-reverse ()
+ "Test that \":r\" reverses the order of elements."
+ (should (equal (eshell-eval-predicate "foo" ":R") "foo"))
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":R")
+ '("baz" "bar" "foo"))))
+
+
+;; Miscellaneous
+
+(ert-deftest em-pred-test/combine-predicate-and-modifier ()
+ "Test combination of predicates and modifiers."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/type=-.el" "/fake/type=-.txt" "/fake/type=s.el"
+ "/fake/subdir/type=-.el")))
+ (should (equal (eshell-eval-predicate files ".:e:u")
+ '("el" "txt"))))))
+
+(ert-deftest em-pred-test/predicate-delimiters ()
+ "Test various delimiter pairs with predicates and modifiers."
+ (dolist (delims eshell-pred-delimiter-pairs)
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/uid=1" "/fake/uid=2"))
+ (user-names '("root" "one" "two")))
+ (cl-letf (((symbol-function 'eshell-user-id)
+ (lambda (name) (seq-position user-names name))))
+ (should (equal (eshell-eval-predicate
+ files (format "u%cone%c" (car delims) (cdr delims)))
+ '("/fake/uid=1"))))))
+ (should (equal (eshell-eval-predicate
+ '("foo" "bar" "baz")
+ (format ":j%c-%c" (car delims) (cdr delims)))
+ "foo-bar-baz"))))
+
+(ert-deftest em-pred-test/predicate-escaping ()
+ "Test string escaping in predicate and modifier parameters."
+ ;; Escaping the delimiter should remove the backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\''")
+ "foo'bar'baz"))
+ ;; Escaping a backlash should remove the first backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\\'")
+ "foo\\bar\\baz"))
+ ;; Escaping a different character should keep the backslash.
+ (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\"'")
+ "foo\\\"bar\\\"baz")))
+
+(ert-deftest em-pred-test/no-matches ()
+ "Test behavior when a predicate fails to match any files."
+ (eshell-with-file-attributes-from-name
+ (let ((files '("/fake/modes=0666" "/fake/type=d,modes=0777"
+ "/fake/type=l,modes=0777")))
+ (should (equal (eshell-eval-predicate files "*") nil))
+ (let ((eshell-error-if-no-glob t))
+ ;; Don't signal an error if the original list is empty.
+ (should (equal (eshell-eval-predicate nil "*") nil))
+ ;; Ensure this signals an error. This test case is a bit
+ ;; clumsy, since `eshell-do-eval' makes it hard to catch
+ ;; errors otherwise.
+ (let ((modifiers (with-temp-eshell
+ (eshell-with-temp-command "*"
+ (eshell-parse-modifiers)))))
+ (should-error (eshell-apply-modifiers files (car modifiers)
+ (cdr modifiers) "*")))))))
+
+;; em-pred-tests.el ends here
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
new file mode 100644
index 00000000000..8969c1e2294
--- /dev/null
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -0,0 +1,88 @@
+;;; em-tramp-tests.el --- em-tramp test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'em-tramp)
+(require 'tramp)
+
+(ert-deftest em-tramp-test/su-default ()
+ "Test Eshell `su' command with no arguments."
+ (should (equal
+ (catch 'eshell-replace-command (eshell/su))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:%s"
+ tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/su-user ()
+ "Test Eshell `su' command with USER argument."
+ (should (equal
+ (catch 'eshell-replace-command (eshell/su "USER"))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:USER@%s:%s"
+ tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/su-login ()
+ "Test Eshell `su' command with -/-l/--login option."
+ (dolist (args '(("--login")
+ ("-l")
+ ("-")))
+ (should (equal
+ (catch 'eshell-replace-command (apply #'eshell/su args))
+ `(eshell-trap-errors
+ (eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:~/" tramp-default-host))))))))
+
+(defun mock-eshell-named-command (&rest args)
+ "Dummy function to test Eshell `sudo' command rewriting."
+ (list default-directory args))
+
+(ert-deftest em-tramp-test/sudo-basic ()
+ "Test Eshell `sudo' command with default user."
+ (cl-letf (((symbol-function 'eshell-named-command)
+ #'mock-eshell-named-command))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "echo" "hi"))
+ `(,(format "/sudo:root@%s:%s" tramp-default-host default-directory)
+ ("echo" ("hi")))))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "echo" "-u" "hi"))
+ `(,(format "/sudo:root@%s:%s" tramp-default-host default-directory)
+ ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/sudo-user ()
+ "Test Eshell `sudo' command with specified user."
+ (cl-letf (((symbol-function 'eshell-named-command)
+ #'mock-eshell-named-command))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "hi"))
+ `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
+ ("echo" ("hi")))))
+ (should (equal
+ (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "-u" "hi"))
+ `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
+ ("echo" ("-u" "hi")))))))
+
+;;; em-tramp-tests.el ends here
diff --git a/test/lisp/eshell/esh-opt-tests.el b/test/lisp/eshell/esh-opt-tests.el
index 532adfb733a..5b30de414a3 100644
--- a/test/lisp/eshell/esh-opt-tests.el
+++ b/test/lisp/eshell/esh-opt-tests.el
@@ -22,102 +22,267 @@
(require 'ert)
(require 'esh-opt)
-(ert-deftest esh-opt-process-args-test ()
- "Unit tests which verify correct behavior of `eshell--process-args'."
+(ert-deftest esh-opt-test/process-args ()
+ "Test behavior of `eshell--process-args'."
(should
(equal '(t)
(eshell--process-args
- "sudo"
- '("-a")
- '((?a "all" nil show-all "")))))
- (should
- (equal '(nil)
- (eshell--process-args
- "sudo"
- '("-g")
- '((?a "all" nil show-all "")))))
+ "sudo" '("-a")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")))))
(should
(equal '("root" "world")
(eshell--process-args
- "sudo"
- '("-u" "root" "world")
- '((?u "user" t user "execute a command as another USER")))))
+ "sudo" '("-u" "root" "world")
+ '((?u "user" t user
+ "execute a command as another USER"))))))
+
+(ert-deftest esh-opt-test/process-args-parse-leading-options-only ()
+ "Test behavior of :parse-leading-options-only in `eshell--process-args'."
(should
(equal '(nil "emerge" "-uDN" "world")
(eshell--process-args
- "sudo"
- '("emerge" "-uDN" "world")
- '((?u "user" t user "execute a command as another USER")
+ "sudo" '("emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER")
:parse-leading-options-only))))
(should
(equal '("root" "emerge" "-uDN" "world")
(eshell--process-args
- "sudo"
- '("-u" "root" "emerge" "-uDN" "world")
- '((?u "user" t user "execute a command as another USER")
+ "sudo" '("-u" "root" "emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER")
:parse-leading-options-only))))
(should
- (equal '("world" "emerge")
+ (equal '("DN" "emerge" "world")
(eshell--process-args
- "sudo"
- '("-u" "root" "emerge" "-uDN" "world")
- '((?u "user" t user "execute a command as another USER"))))))
+ "sudo" '("-u" "root" "emerge" "-uDN" "world")
+ '((?u "user" t user
+ "execute a command as another USER"))))))
+
+(ert-deftest esh-opt-test/process-args-external ()
+ "Test behavior of :external in `eshell--process-args'."
+ (cl-letf (((symbol-function 'eshell-search-path) #'ignore))
+ (should
+ (equal '(nil "/some/path")
+ (eshell--process-args
+ "ls" '("/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls")))))
+ (cl-letf (((symbol-function 'eshell-search-path) #'identity))
+ (should
+ (equal '(no-catch eshell-ext-command "ls")
+ (should-error
+ (eshell--process-args
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls"))
+ :type 'no-catch))))
+ (cl-letf (((symbol-function 'eshell-search-path) #'ignore))
+ (should-error
+ (eshell--process-args
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ :external "ls"))
+ :type 'error)))
+
+(ert-deftest esh-opt-test/eval-using-options-short ()
+ "Test `eshell-eval-using-options' with short options."
+ (eshell-eval-using-options
+ "ls" '("-a" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all t))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-long ()
+ "Test `eshell-eval-using-options' with long options."
+ (eshell-eval-using-options
+ "ls" '("--all" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all t))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-constant ()
+ "Test `eshell-eval-using-options' with options with constant values."
+ (eshell-eval-using-options
+ "ls" '("/some/path" "-h")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eql human-readable 1024))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path" "--human-readable")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eql human-readable 1024))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("/some/path")
+ '((?h "human-readable" 1024 human-readable
+ "print sizes in human readable format"))
+ (should (eq human-readable nil))
+ (should (equal args '("/some/path")))))
-(ert-deftest test-eshell-eval-using-options ()
- "Tests for `eshell-eval-using-options'."
+(ert-deftest esh-opt-test/eval-using-options-user-specified ()
+ "Test `eshell-eval-using-options' with options with user-specified values."
+ (eshell-eval-using-options
+ "ls" '("-I" "*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("-I*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("--ignore" "*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("--ignore=*.txt" "/some/path")
+ '((?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-short-single-token ()
+ "Test `eshell-eval-using-options' with multiple short options in one token."
+ (eshell-eval-using-options
+ "ls" '("-al" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ (?l nil long-listing listing-style
+ "use a long listing format"))
+ (should (eq t show-all))
+ (should (eql listing-style 'long-listing))
+ (should (equal args '("/some/path"))))
+ (eshell-eval-using-options
+ "ls" '("-aI*.txt" "/some/path")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with .")
+ (?I "ignore" t ignore-pattern
+ "do not list implied entries matching pattern"))
+ (should (eq t show-all))
+ (should (equal ignore-pattern "*.txt"))
+ (should (equal args '("/some/path")))))
+
+(ert-deftest esh-opt-test/eval-using-options-stdin ()
+ "Test that \"-\" is a positional arg in `eshell-eval-using-options'."
+ (eshell-eval-using-options
+ "cat" '("-")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all nil))
+ (should (equal args '("-"))))
+ (eshell-eval-using-options
+ "cat" '("-A" "-")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all t))
+ (should (equal args '("-"))))
+ (eshell-eval-using-options
+ "cat" '("-" "-A")
+ '((?A "show-all" nil show-all
+ "show all characters"))
+ (should (eq show-all t))
+ (should (equal args '("-")))))
+
+(ert-deftest esh-opt-test/eval-using-options-terminate-options ()
+ "Test that \"--\" terminates options in `eshell-eval-using-options'."
+ (eshell-eval-using-options
+ "ls" '("--" "-a")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("-a"))))
+ (eshell-eval-using-options
+ "ls" '("--" "--all")
+ '((?a "all" nil show-all
+ "do not ignore entries starting with ."))
+ (should (eq show-all nil))
+ (should (equal args '("--all")))))
+
+(ert-deftest esh-opt-test/eval-using-options-parse-leading-options-only ()
+ "Test :parse-leading-options-only in `eshell-eval-using-options'."
(eshell-eval-using-options
"sudo" '("-u" "root" "whoami")
'((?u "user" t user "execute a command as another USER")
:parse-leading-options-only)
- (should (equal user "root")))
+ (should (equal user "root"))
+ (should (equal args '("whoami"))))
(eshell-eval-using-options
"sudo" '("--user" "root" "whoami")
'((?u "user" t user "execute a command as another USER")
:parse-leading-options-only)
- (should (equal user "root")))
-
+ (should (equal user "root"))
+ (should (equal args '("whoami"))))
(eshell-eval-using-options
"sudo" '("emerge" "-uDN" "world")
'((?u "user" t user "execute a command as another USER"))
- (should (equal user "world")))
+ (should (equal user "DN"))
+ (should (equal args '("emerge" "world"))))
(eshell-eval-using-options
"sudo" '("emerge" "-uDN" "world")
'((?u "user" t user "execute a command as another USER")
:parse-leading-options-only)
- (should (eq user nil)))
+ (should (eq user nil))
+ (should (equal args '("emerge" "-uDN" "world")))))
- (eshell-eval-using-options
- "ls" '("-I" "*.txt" "/dev/null")
- '((?I "ignore" t ignore-pattern
- "do not list implied entries matching pattern"))
- (should (equal ignore-pattern "*.txt")))
-
- (eshell-eval-using-options
- "ls" '("-l" "/dev/null")
- '((?l nil long-listing listing-style
- "use a long listing format"))
- (should (eql listing-style 'long-listing)))
- (eshell-eval-using-options
- "ls" '("/dev/null")
- '((?l nil long-listing listing-style
- "use a long listing format"))
- (should (eq listing-style nil)))
+(ert-deftest esh-opt-test/eval-using-options-unrecognized ()
+ "Test `eshell-eval-using-options' with unrecognized options."
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("-u" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with ."))))
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("-au" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with ."))))
+ (should-error
+ (eshell-eval-using-options
+ "ls" '("--unrecognized" "/some/path")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")))))
- (eshell-eval-using-options
- "ls" '("/dev/null" "-h")
- '((?h "human-readable" 1024 human-readable
- "print sizes in human readable format"))
- (should (eql human-readable 1024)))
- (eshell-eval-using-options
- "ls" '("/dev/null" "--human-readable")
- '((?h "human-readable" 1024 human-readable
- "print sizes in human readable format"))
- (should (eql human-readable 1024)))
- (eshell-eval-using-options
- "ls" '("/dev/null")
- '((?h "human-readable" 1024 human-readable
- "print sizes in human readable format"))
- (should (eq human-readable nil))))
+(ert-deftest esh-opt-test/eval-using-options-external ()
+ "Test :external in `eshell-eval-using-options'."
+ (cl-letf (((symbol-function 'eshell-search-path) #'identity)
+ ((symbol-function 'eshell-external-command) #'list))
+ (should
+ (equal (catch 'eshell-external
+ (eshell-eval-using-options
+ "ls" '("/some/path" "-u")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")
+ :external "ls")))
+ '("ls" ("/some/path" "-u"))))
+ (should
+ (equal (catch 'eshell-external
+ (eshell-eval-using-options
+ "ls" '("/some/path2" "-u")
+ '((?a "all" nil _show-all
+ "do not ignore entries starting with .")
+ :preserve-args
+ :external "ls")))
+ '("ls" ("/some/path2" "-u"))))))
(provide 'esh-opt-tests)
diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el
new file mode 100644
index 00000000000..7f461d1813c
--- /dev/null
+++ b/test/lisp/eshell/esh-proc-tests.el
@@ -0,0 +1,96 @@
+;;; esh-proc-tests.el --- esh-proc test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(ert-deftest esh-proc-test/sigpipe-exits-process ()
+ "Test that a SIGPIPE is properly sent to a process if a pipe closes"
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-command-result-p
+ ;; The first command is like `yes' but slower. This is to prevent
+ ;; it from taxing Emacs's process filter too much and causing a
+ ;; hang.
+ (concat "sh -c 'while true; do echo y; sleep 1; done' | "
+ "sh -c 'read NAME; echo ${NAME}'")
+ "y\n")
+ (eshell-wait-for-subprocess t)
+ (should (eq (process-list) nil))))
+
+(ert-deftest esh-proc-test/kill-pipeline ()
+ "Test that killing a pipeline of processes only emits a single
+prompt. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ ;; This test doesn't work on EMBA with AOT nativecomp, but works
+ ;; fine elsewhere.
+ (skip-unless (not (getenv "EMACS_EMBA_CI")))
+ (with-temp-eshell
+ (eshell-insert-command
+ (concat "sh -c 'while true; do echo y; sleep 1; done' | "
+ "sh -c 'while true; do read NAME; done'"))
+ (let ((output-start (eshell-beginning-of-output)))
+ (eshell-kill-process)
+ (eshell-wait-for-subprocess t)
+ (should (string-match-p
+ ;; "interrupt\n" is for MS-Windows.
+ (rx (or "interrupt\n" "killed\n" "killed: 9\n"))
+ (buffer-substring-no-properties
+ output-start (eshell-end-of-output)))))))
+
+(ert-deftest esh-proc-test/kill-pipeline-head ()
+ "Test that killing the first process in a pipeline doesn't
+write the exit status to the pipe. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "echo")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-insert-command
+ (concat "sh -c 'while true; do sleep 1; done' | "
+ "sh -c 'while read NAME; do echo =${NAME}=; done'"))
+ (let ((output-start (eshell-beginning-of-output)))
+ (kill-process (eshell-head-process))
+ (eshell-wait-for-subprocess t)
+ (should (equal (buffer-substring-no-properties
+ output-start (eshell-end-of-output))
+ "")))))
+
+(ert-deftest esh-proc-test/kill-background-process ()
+ "Test that killing a background process doesn't emit a new
+prompt. See bug#54136."
+ (skip-unless (and (executable-find "sh")
+ (executable-find "sleep")))
+ (with-temp-eshell
+ (eshell-insert-command "sh -c 'while true; do sleep 1; done' &")
+ (kill-process (caar eshell-process-list))
+ ;; Give `eshell-sentinel' a chance to run.
+ (sit-for 0.1)
+ (eshell-match-result "\\[sh\\(\\.exe\\)?\\] [[:digit:]]+\n")))
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
new file mode 100644
index 00000000000..3180fe7a5fc
--- /dev/null
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -0,0 +1,508 @@
+;;; esh-var-tests.el --- esh-var test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's variable handling.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+;;; Tests:
+
+
+;; Variable interpolation
+
+(ert-deftest esh-var-test/interp-var ()
+ "Interpolate variable"
+ (should (equal (eshell-test-command-result "echo $user-login-name")
+ user-login-name)))
+
+(ert-deftest esh-var-test/interp-quoted-var ()
+ "Interpolate quoted variable"
+ (should (equal (eshell-test-command-result "echo $'user-login-name'")
+ user-login-name))
+ (should (equal (eshell-test-command-result "echo $\"user-login-name\"")
+ user-login-name)))
+
+(ert-deftest esh-var-test/interp-quoted-var-concat ()
+ "Interpolate and concat quoted variable"
+ (should (equal (eshell-test-command-result "echo $'user-login-name'-foo")
+ (concat user-login-name "-foo")))
+ (should (equal (eshell-test-command-result "echo $\"user-login-name\"-foo")
+ (concat user-login-name "-foo"))))
+
+(ert-deftest esh-var-test/interp-var-indices ()
+ "Interpolate list variable with indices"
+ (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0]")
+ "zero"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]")
+ '("zero" "two")))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2 4]")
+ '("zero" "two" "four")))))
+
+(ert-deftest esh-var-test/interp-var-split-indices ()
+ "Interpolate string variable with indices"
+ (let ((eshell-test-value "zero one two three four"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0]")
+ "zero"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]")
+ '("zero" "two")))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2 4]")
+ '("zero" "two" "four")))))
+
+(ert-deftest esh-var-test/interp-var-string-split-indices ()
+ "Interpolate string variable with string splitter and indices"
+ (let ((eshell-test-value "zero:one:two:three:four"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0]")
+ "zero"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0 2]")
+ '("zero" "two"))))
+ (let ((eshell-test-value "zeroXoneXtwoXthreeXfour"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[X 0]")
+ "zero"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[X 0 2]")
+ '("zero" "two")))))
+
+(ert-deftest esh-var-test/interp-var-regexp-split-indices ()
+ "Interpolate string variable with regexp splitter and indices"
+ (let ((eshell-test-value "zero:one!two:three!four"))
+ (should (equal (eshell-test-command-result
+ "echo $eshell-test-value['[:!]' 0]")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo $eshell-test-value['[:!]' 0 2]")
+ '("zero" "two")))
+ (should (equal (eshell-test-command-result
+ "echo $eshell-test-value[\"[:!]\" 0]")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo $eshell-test-value[\"[:!]\" 0 2]")
+ '("zero" "two")))))
+
+(ert-deftest esh-var-test/interp-var-assoc ()
+ "Interpolate alist variable with index"
+ (let ((eshell-test-value '(("foo" . 1))))
+ (should (eq (eshell-test-command-result "echo $eshell-test-value[foo]")
+ 1))))
+
+(ert-deftest esh-var-test/interp-var-length-list ()
+ "Interpolate length of list variable"
+ (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9)))))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value") 3))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value[1]") 1))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value[2][1]")
+ 4))))
+
+(ert-deftest esh-var-test/interp-var-length-string ()
+ "Interpolate length of string variable"
+ (let ((eshell-test-value "foobar"))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value") 6))))
+
+(ert-deftest esh-var-test/interp-var-length-alist ()
+ "Interpolate length of alist variable"
+ (let ((eshell-test-value '(("foo" . (1 2 3)))))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value") 1))
+ (should (eq (eshell-test-command-result "echo $#eshell-test-value[foo]")
+ 3))))
+
+(ert-deftest esh-var-test/interp-lisp ()
+ "Interpolate Lisp form evaluation"
+ (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6)))
+
+(ert-deftest esh-var-test/interp-lisp-indices ()
+ "Interpolate Lisp form evaluation with index"
+ (should (equal (eshell-test-command-result "+ $(list 1 2)[1] 3") 5)))
+
+(ert-deftest esh-var-test/interp-cmd ()
+ "Interpolate command result"
+ (should (equal (eshell-test-command-result "+ ${+ 1 2} 3") 6)))
+
+(ert-deftest esh-var-test/interp-cmd-indices ()
+ "Interpolate command result with index"
+ (should (equal (eshell-test-command-result "+ ${listify 1 2}[1] 3") 5)))
+
+(ert-deftest esh-var-test/interp-cmd-external ()
+ "Interpolate command result from external command"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-command-result-p "echo ${*echo hi}"
+ "hi\n")))
+
+(ert-deftest esh-var-test/interp-cmd-external-indices ()
+ "Interpolate command result from external command with index"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-command-result-p "echo ${*echo \"hi\nbye\"}[1]"
+ "bye\n")))
+
+(ert-deftest esh-var-test/interp-temp-cmd ()
+ "Interpolate command result redirected to temp file"
+ (should (equal (eshell-test-command-result "cat $<echo hi>") "hi")))
+
+(ert-deftest esh-var-test/interp-concat-lisp ()
+ "Interpolate and concat Lisp form"
+ (should (equal (eshell-test-command-result "+ $(+ 1 2)3 3") 36)))
+
+(ert-deftest esh-var-test/interp-concat-lisp2 ()
+ "Interpolate and concat two Lisp forms"
+ (should (equal (eshell-test-command-result "+ $(+ 1 2)$(+ 1 2) 3") 36)))
+
+(ert-deftest esh-var-test/interp-concat-cmd ()
+ "Interpolate and concat command with literal"
+ (should (equal (eshell-test-command-result "+ ${+ 1 2}3 3") 36))
+ (should (equal (eshell-test-command-result "echo ${*echo \"foo\nbar\"}-baz")
+ '("foo" "bar-baz")))
+ ;; Concatenating to a number in a list should produce a number...
+ (should (equal (eshell-test-command-result "echo ${*echo \"1\n2\"}3")
+ '(1 23)))
+ ;; ... but concatenating to a string that looks like a number in a list
+ ;; should produce a string.
+ (should (equal (eshell-test-command-result "echo ${*echo \"hi\n2\"}3")
+ '("hi" "23"))))
+
+(ert-deftest esh-var-test/interp-concat-cmd2 ()
+ "Interpolate and concat two commands"
+ (should (equal (eshell-test-command-result "+ ${+ 1 2}${+ 1 2} 3") 36)))
+
+(ert-deftest esh-var-test/interp-concat-cmd-external ()
+ "Interpolate command result from external command with concatenation"
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-command-result-p "echo ${echo hi}-${*echo there}"
+ "hi-there\n")))
+
+(ert-deftest esh-var-test/quoted-interp-var ()
+ "Interpolate variable inside double-quotes"
+ (should (equal (eshell-test-command-result "echo \"$user-login-name\"")
+ user-login-name)))
+
+(ert-deftest esh-var-test/quoted-interp-quoted-var ()
+ "Interpolate quoted variable inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "echo \"hi, $'user-login-name'\"")
+ (concat "hi, " user-login-name)))
+ (should (equal (eshell-test-command-result
+ "echo \"hi, $\\\"user-login-name\\\"\"")
+ (concat "hi, " user-login-name))))
+
+(ert-deftest esh-var-test/quoted-interp-var-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0]\"")
+ "zero"))
+ ;; FIXME: These tests would use the 0th index like the other tests
+ ;; here, but evaluating the command just above adds an `escaped'
+ ;; property to the string "zero". This results in the output
+ ;; printing the string properties, which is probably the wrong
+ ;; behavior. See bug#54486.
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[1 2]\"")
+ "(\"one\" \"two\")"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[1 2 4]\"")
+ "(\"one\" \"two\" \"four\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-split-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value "zero one two three four"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0]\"")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0 2]\"")
+ "(\"zero\" \"two\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-string-split-indices ()
+ "Interpolate string variable with string splitter and indices
+inside double-quotes"
+ (let ((eshell-test-value "zero:one:two:three:four"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[: 0]\"")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[: 0 2]\"")
+ "(\"zero\" \"two\")")))
+ (let ((eshell-test-value "zeroXoneXtwoXthreeXfour"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[X 0]\"")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[X 0 2]\"")
+ "(\"zero\" \"two\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-regexp-split-indices ()
+ "Interpolate string variable with regexp splitter and indices"
+ (let ((eshell-test-value "zero:one!two:three!four"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value['[:!]' 0]\"")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value['[:!]' 0 2]\"")
+ "(\"zero\" \"two\")"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[\\\"[:!]\\\" 0]\"")
+ "zero"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[\\\"[:!]\\\" 0 2]\"")
+ "(\"zero\" \"two\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-assoc ()
+ "Interpolate alist variable with index inside double-quotes"
+ (let ((eshell-test-value '(("foo" . 1))))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[foo]\"")
+ "1"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-list ()
+ "Interpolate length of list variable inside double-quotes"
+ (let ((eshell-test-value '((1 2) (3) (5 (6 7 8 9)))))
+ (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"")
+ "3"))
+ (should (equal (eshell-test-command-result
+ "echo \"$#eshell-test-value[1]\"")
+ "1"))
+ (should (equal (eshell-test-command-result
+ "echo \"$#eshell-test-value[2][1]\"")
+ "4"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-string ()
+ "Interpolate length of string variable inside double-quotes"
+ (let ((eshell-test-value "foobar"))
+ (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"")
+ "6"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-length-alist ()
+ "Interpolate length of alist variable inside double-quotes"
+ (let ((eshell-test-value '(("foo" . (1 2 3)))))
+ (should (equal (eshell-test-command-result "echo \"$#eshell-test-value\"")
+ "1"))
+ (should (equal (eshell-test-command-result
+ "echo \"$#eshell-test-value[foo]\"")
+ "3"))))
+
+(ert-deftest esh-var-test/quoted-interp-lisp ()
+ "Interpolate Lisp form evaluation inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\"")
+ "hi there")))
+
+(ert-deftest esh-var-test/quoted-interp-lisp-indices ()
+ "Interpolate Lisp form evaluation with index"
+ (should (equal (eshell-test-command-result "concat \"$(list 1 2)[1]\" cool")
+ "2cool")))
+
+(ert-deftest esh-var-test/quoted-interp-cmd ()
+ "Interpolate command result inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "echo \"hi ${echo \\\"there\\\"}\"")
+ "hi there")))
+
+(ert-deftest esh-var-test/quoted-interp-cmd-indices ()
+ "Interpolate command result with index inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "concat \"${listify 1 2}[1]\" cool")
+ "2cool")))
+
+(ert-deftest esh-var-test/quoted-interp-temp-cmd ()
+ "Interpolate command result redirected to temp file inside double-quotes"
+ (let ((temporary-file-directory
+ (file-name-as-directory (make-temp-file "esh-vars-tests" t))))
+ (unwind-protect
+ (should (equal (eshell-test-command-result "cat \"$<echo hi>\"")
+ "hi"))
+ (delete-directory temporary-file-directory t))))
+
+(ert-deftest esh-var-test/quoted-interp-concat-cmd ()
+ "Interpolate and concat command with literal"
+ (should (equal (eshell-test-command-result
+ "echo \"${echo \\\"foo\nbar\\\"} baz\"")
+ "foo\nbar baz")))
+
+
+;; Interpolated variable conversion
+
+(ert-deftest esh-var-test/interp-convert-var-number ()
+ "Interpolate numeric variable"
+ (let ((eshell-test-value 123))
+ (should (equal (eshell-test-command-result "type-of $eshell-test-value")
+ 'integer))))
+
+(ert-deftest esh-var-test/interp-convert-var-split-indices ()
+ "Interpolate and convert string variable with indices"
+ ;; Check that numeric forms are converted to numbers.
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0]")
+ 0))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]")
+ '(0 20))))
+ ;; Check that multiline forms are preserved as-is.
+ (let ((eshell-test-value "foo\nbar:baz\n"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0]")
+ "foo\nbar"))
+ (should (equal (eshell-test-command-result "echo $eshell-test-value[: 1]")
+ "baz\n"))))
+
+(ert-deftest esh-var-test/interp-convert-quoted-var-number ()
+ "Interpolate numeric quoted numeric variable"
+ (let ((eshell-test-value 123))
+ (should (equal (eshell-test-command-result "type-of $'eshell-test-value'")
+ 'integer))
+ (should (equal (eshell-test-command-result "type-of $\"eshell-test-value\"")
+ 'integer))))
+
+(ert-deftest esh-var-test/interp-convert-quoted-var-split-indices ()
+ "Interpolate and convert quoted string variable with indices"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (should (equal (eshell-test-command-result "echo $'eshell-test-value'[0]")
+ 0))
+ (should (equal (eshell-test-command-result "echo $'eshell-test-value'[0 2]")
+ '(0 20)))))
+
+(ert-deftest esh-var-test/interp-convert-cmd-string-newline ()
+ "Interpolate trailing-newline command result"
+ (should (equal (eshell-test-command-result "echo ${echo \"foo\n\"}") "foo")))
+
+(ert-deftest esh-var-test/interp-convert-cmd-multiline ()
+ "Interpolate multi-line command result"
+ (should (equal (eshell-test-command-result "echo ${echo \"foo\nbar\"}")
+ '("foo" "bar")))
+ ;; Numeric output should be converted to numbers...
+ (should (equal (eshell-test-command-result "echo ${echo \"01\n02\n03\"}")
+ '(1 2 3)))
+ ;; ... but only if every line is numeric.
+ (should (equal (eshell-test-command-result "echo ${echo \"01\n02\nhi\"}")
+ '("01" "02" "hi"))))
+
+(ert-deftest esh-var-test/interp-convert-cmd-number ()
+ "Interpolate numeric command result"
+ (should (equal (eshell-test-command-result "echo ${echo \"1\"}") 1)))
+
+(ert-deftest esh-var-test/interp-convert-cmd-split-indices ()
+ "Interpolate command result with indices"
+ (should (equal (eshell-test-command-result "echo ${echo \"000 010 020\"}[0]")
+ 0))
+ (should (equal (eshell-test-command-result
+ "echo ${echo \"000 010 020\"}[0 2]")
+ '(0 20))))
+
+(ert-deftest esh-var-test/quoted-interp-convert-var-number ()
+ "Interpolate numeric variable inside double-quotes"
+ (let ((eshell-test-value 123))
+ (should (equal (eshell-test-command-result "type-of \"$eshell-test-value\"")
+ 'string))))
+
+(ert-deftest esh-var-test/quoted-interp-convert-var-split-indices ()
+ "Interpolate string variable with indices inside double-quotes"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0]\"")
+ "000"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0 2]\"")
+ "(\"000\" \"020\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-convert-quoted-var-number ()
+ "Interpolate numeric quoted variable inside double-quotes"
+ (let ((eshell-test-value 123))
+ (should (equal (eshell-test-command-result
+ "type-of \"$'eshell-test-value'\"")
+ 'string))
+ (should (equal (eshell-test-command-result
+ "type-of \"$\\\"eshell-test-value\\\"\"")
+ 'string))))
+
+(ert-deftest esh-var-test/quoted-interp-convert-quoted-var-split-indices ()
+ "Interpolate quoted string variable with indices inside double-quotes"
+ (let ((eshell-test-value "000 010 020 030 040"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0]\"")
+ "000"))
+ (should (equal (eshell-test-command-result
+ "echo \"$eshell-test-value[0 2]\"")
+ "(\"000\" \"020\")"))))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-string-newline ()
+ "Interpolate trailing-newline command result inside double-quotes"
+ (should (equal (eshell-test-command-result "echo \"${echo \\\"foo\n\\\"}\"")
+ "foo"))
+ (should (equal (eshell-test-command-result "echo \"${echo \\\"foo\n\n\\\"}\"")
+ "foo")))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-multiline ()
+ "Interpolate multi-line command result inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "echo \"${echo \\\"foo\nbar\\\"}\"")
+ "foo\nbar")))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-number ()
+ "Interpolate numeric command result inside double-quotes"
+ (should (equal (eshell-test-command-result "echo \"${echo \\\"1\\\"}\"")
+ "1")))
+
+(ert-deftest esh-var-test/quoted-interp-convert-cmd-split-indices ()
+ "Interpolate command result with indices inside double-quotes"
+ (should (equal (eshell-test-command-result
+ "echo \"${echo \\\"000 010 020\\\"}[0]\"")
+ "000")))
+
+
+;; Built-in variables
+
+(ert-deftest esh-var-test/lines-var ()
+ "$LINES should equal (window-body-height nil 'remap)"
+ (should (equal (eshell-test-command-result "echo $LINES")
+ (window-body-height nil 'remap))))
+
+(ert-deftest esh-var-test/columns-var ()
+ "$COLUMNS should equal (window-body-width nil 'remap)"
+ (should (equal (eshell-test-command-result "echo $COLUMNS")
+ (window-body-width nil 'remap))))
+
+(ert-deftest esh-var-test/last-result-var ()
+ "Test using the \"last result\" ($$) variable"
+ (with-temp-eshell
+ (eshell-command-result-p "+ 1 2; + $$ 2"
+ "3\n5\n")))
+
+(ert-deftest esh-var-test/last-result-var2 ()
+ "Test using the \"last result\" ($$) variable twice"
+ (with-temp-eshell
+ (eshell-command-result-p "+ 1 2; + $$ $$"
+ "3\n6\n")))
+
+(ert-deftest esh-var-test/last-arg-var ()
+ "Test using the \"last arg\" ($_) variable"
+ (with-temp-eshell
+ (eshell-command-result-p "+ 1 2; + $_ 4"
+ "3\n6\n")))
+
+;; esh-var-tests.el ends here
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
new file mode 100644
index 00000000000..4ad76ca6978
--- /dev/null
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -0,0 +1,97 @@
+;;; eshell-tests-helpers.el --- Eshell test suite helpers -*- lexical-binding:t -*-
+
+;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Eshell test suite helpers.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
+(require 'eshell)
+
+(defvar eshell-history-file-name nil)
+
+(defvar eshell-test--max-subprocess-time 5
+ "The maximum amount of time to wait for a subprocess to finish, in seconds.
+See `eshell-wait-for-subprocess'.")
+
+(defmacro with-temp-eshell (&rest body)
+ "Evaluate BODY in a temporary Eshell buffer."
+ `(save-current-buffer
+ (ert-with-temp-directory eshell-directory-name
+ (let* (;; We want no history file, so prevent Eshell from falling
+ ;; back on $HISTFILE.
+ (process-environment (cons "HISTFILE" process-environment))
+ (eshell-history-file-name nil)
+ (eshell-buffer (eshell t)))
+ (unwind-protect
+ (with-current-buffer eshell-buffer
+ ,@body)
+ (let (kill-buffer-query-functions)
+ (kill-buffer eshell-buffer)))))))
+
+(defun eshell-wait-for-subprocess (&optional all)
+ "Wait until there is no interactive subprocess running in Eshell.
+If ALL is non-nil, wait until there are no Eshell subprocesses at
+all running.
+
+If this takes longer than `eshell-test--max-subprocess-time',
+raise an error."
+ (let ((start (current-time)))
+ (while (if all eshell-process-list (eshell-interactive-process-p))
+ (when (> (float-time (time-since start))
+ eshell-test--max-subprocess-time)
+ (error "timed out waiting for subprocess(es)"))
+ (sit-for 0.1))))
+
+(defun eshell-insert-command (text &optional func)
+ "Insert a command at the end of the buffer."
+ (goto-char eshell-last-output-end)
+ (insert-and-inherit text)
+ (funcall (or func 'eshell-send-input)))
+
+(defun eshell-match-result (regexp)
+ "Check that output of last command matches REGEXP."
+ (should
+ (string-match-p
+ regexp (buffer-substring-no-properties
+ (eshell-beginning-of-output) (eshell-end-of-output)))))
+
+(defun eshell-command-result-p (text regexp &optional func)
+ "Insert a command at the end of the buffer."
+ (eshell-insert-command text func)
+ (eshell-wait-for-subprocess)
+ (eshell-match-result regexp))
+
+(defvar eshell-history-file-name)
+
+(defun eshell-test-command-result (command)
+ "Like `eshell-command-result', but not using HOME."
+ (ert-with-temp-directory eshell-directory-name
+ (let ((eshell-history-file-name nil))
+ (eshell-command-result command))))
+
+(provide 'eshell-tests-helpers)
+
+;;; eshell-tests-helpers.el ends here
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index aef14479078..ab5d73d4792 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -29,45 +29,10 @@
(require 'ert-x)
(require 'esh-mode)
(require 'eshell)
-
-(defmacro with-temp-eshell (&rest body)
- "Evaluate BODY in a temporary Eshell buffer."
- `(ert-with-temp-directory eshell-directory-name
- (let* (;; We want no history file, so prevent Eshell from falling
- ;; back on $HISTFILE.
- (process-environment (cons "HISTFILE" process-environment))
- (eshell-history-file-name nil)
- (eshell-buffer (eshell t)))
- (unwind-protect
- (with-current-buffer eshell-buffer
- ,@body)
- (let (kill-buffer-query-functions)
- (kill-buffer eshell-buffer))))))
-
-(defun eshell-insert-command (text &optional func)
- "Insert a command at the end of the buffer."
- (goto-char eshell-last-output-end)
- (insert-and-inherit text)
- (funcall (or func 'eshell-send-input)))
-
-(defun eshell-match-result (regexp)
- "Check that text after `eshell-last-input-end' matches REGEXP."
- (goto-char eshell-last-input-end)
- (should (string-match-p regexp (buffer-substring-no-properties
- (point) (point-max)))))
-
-(defun eshell-command-result-p (text regexp &optional func)
- "Insert a command at the end of the buffer."
- (eshell-insert-command text func)
- (eshell-match-result regexp))
-
-(defvar eshell-history-file-name)
-
-(defun eshell-test-command-result (command)
- "Like `eshell-command-result', but not using HOME."
- (ert-with-temp-directory eshell-directory-name
- (let ((eshell-history-file-name nil))
- (eshell-command-result command))))
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
;;; Tests:
@@ -79,6 +44,10 @@
"Test `eshell-command-result' with an elisp command."
(should (equal (eshell-test-command-result "(+ 1 2)") 3)))
+(ert-deftest eshell-test/lisp-command-with-quote ()
+ "Test `eshell-command-result' with an elisp command containing a quote."
+ (should (equal (eshell-test-command-result "(eq 'foo nil)") nil)))
+
(ert-deftest eshell-test/for-loop ()
"Test `eshell-command-result' with a for loop.."
(let ((process-environment (cons "foo" process-environment)))
@@ -120,55 +89,94 @@ Test that trailing arguments outside the subcommand are ignored.
e.g. \"{(+ 1 2)} 3\" => 3"
(should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3)))
-(ert-deftest eshell-test/interp-cmd ()
- "Interpolate command result"
- (should (equal (eshell-test-command-result "+ ${+ 1 2} 3") 6)))
-
-(ert-deftest eshell-test/interp-lisp ()
- "Interpolate Lisp form evaluation"
- (should (equal (eshell-test-command-result "+ $(+ 1 2) 3") 6)))
-
-(ert-deftest eshell-test/interp-concat ()
- "Interpolate and concat command"
- (should (equal (eshell-test-command-result "+ ${+ 1 2}3 3") 36)))
-
-(ert-deftest eshell-test/interp-concat-lisp ()
- "Interpolate and concat Lisp form"
- (should (equal (eshell-test-command-result "+ $(+ 1 2)3 3") 36)))
-
-(ert-deftest eshell-test/interp-concat2 ()
- "Interpolate and concat two commands"
- (should (equal (eshell-test-command-result "+ ${+ 1 2}${+ 1 2} 3") 36)))
-
-(ert-deftest eshell-test/interp-concat-lisp2 ()
- "Interpolate and concat two Lisp forms"
- (should (equal (eshell-test-command-result "+ $(+ 1 2)$(+ 1 2) 3") 36)))
-
-(ert-deftest eshell-test/window-height ()
- "$LINES should equal (window-height)"
- (should (eshell-test-command-result "= $LINES (window-height)")))
-
-(ert-deftest eshell-test/window-width ()
- "$COLUMNS should equal (window-width)"
- (should (eshell-test-command-result "= $COLUMNS (window-width)")))
+(ert-deftest eshell-test/pipe-headproc ()
+ "Check that piping a non-process to a process command waits for the process"
+ (skip-unless (executable-find "cat"))
+ (with-temp-eshell
+ (eshell-command-result-p "echo hi | *cat"
+ "hi")))
-(ert-deftest eshell-test/last-result-var ()
- "Test using the \"last result\" ($$) variable"
+(ert-deftest eshell-test/pipe-tailproc ()
+ "Check that piping a process to a non-process command waits for the process"
+ (skip-unless (executable-find "echo"))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $$ 2"
- "3\n5\n")))
+ (eshell-command-result-p "*echo hi | echo bye"
+ "bye\nhi\n")))
-(ert-deftest eshell-test/last-result-var2 ()
- "Test using the \"last result\" ($$) variable twice"
+(ert-deftest eshell-test/pipe-headproc-stdin ()
+ "Check that standard input is sent to the head process in a pipeline"
+ (skip-unless (and (executable-find "tr")
+ (executable-find "rev")))
+ (with-temp-eshell
+ (eshell-insert-command "tr a-z A-Z | rev")
+ (eshell-insert-command "hello")
+ (eshell-send-eof-to-process)
+ (eshell-wait-for-subprocess)
+ (eshell-match-result "OLLEH\n")))
+
+(ert-deftest eshell-test/pipe-subcommand ()
+ "Check that piping with an asynchronous subcommand works"
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $$ $$"
- "3\n6\n")))
+ (eshell-command-result-p "echo ${*echo hi} | *cat"
+ "hi")))
-(ert-deftest eshell-test/last-arg-var ()
- "Test using the \"last arg\" ($_) variable"
+(ert-deftest eshell-test/pipe-subcommand-with-pipe ()
+ "Check that piping with an asynchronous subcommand with its own pipe works"
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
(with-temp-eshell
- (eshell-command-result-p "+ 1 2; + $_ 4"
- "3\n6\n")))
+ (eshell-command-result-p "echo ${*echo hi | *cat} | *cat"
+ "hi")))
+
+(ert-deftest eshell-test/subcommand-reset-in-pipeline ()
+ "Check that subcommands reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo {%s} | *cat"
+ "echo ${%s} | *cat"
+ "*cat $<%s> | *cat"))
+ (should (equal (eshell-test-command-result
+ (format template "echo $eshell-in-pipeline-p"))
+ nil))
+ (should (equal (eshell-test-command-result
+ (format template "echo | echo $eshell-in-pipeline-p"))
+ "last"))
+ (should (equal (eshell-test-command-result
+ (format template "echo $eshell-in-pipeline-p | echo"))
+ "first"))
+ (should (equal (eshell-test-command-result
+ (format template
+ "echo | echo $eshell-in-pipeline-p | echo"))
+ "t"))))
+
+(ert-deftest eshell-test/lisp-reset-in-pipeline ()
+ "Check that interpolated Lisp forms reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo (%s) | *cat"
+ "echo $(%s) | *cat"))
+ (should (equal (eshell-test-command-result
+ (format template "format \"%s\" eshell-in-pipeline-p"))
+ "nil"))))
+
+(ert-deftest eshell-test/redirect-buffer ()
+ "Check that piping to a buffer works"
+ (with-temp-buffer
+ (rename-buffer "eshell-temp-buffer" t)
+ (let ((bufname (buffer-name)))
+ (with-temp-eshell
+ (eshell-insert-command (format "echo hi > #<%s>" bufname)))
+ (should (equal (buffer-string) "hi")))))
+
+(ert-deftest eshell-test/redirect-buffer-escaped ()
+ "Check that piping to a buffer with escaped characters works"
+ (with-temp-buffer
+ (rename-buffer "eshell\\temp\\buffer" t)
+ (let ((bufname (buffer-name)))
+ (with-temp-eshell
+ (eshell-insert-command (format "echo hi > #<%s>"
+ (string-replace "\\" "\\\\" bufname))))
+ (should (equal (buffer-string) "hi")))))
(ert-deftest eshell-test/inside-emacs-var ()
"Test presence of \"INSIDE_EMACS\" in subprocesses"
@@ -204,9 +212,9 @@ chars"
"Test that the backslash is not preserved for escaped special
chars"
(with-temp-eshell
- (eshell-command-result-p "echo \"h\\\\i\""
+ (eshell-command-result-p "echo \"\\\"hi\\\\\""
;; Backslashes are doubled for regexp.
- "h\\\\i\n")))
+ "\\\"hi\\\\\n")))
(ert-deftest eshell-test/command-running-p ()
"Modeline should show no command running"
@@ -247,9 +255,8 @@ chars"
(with-temp-eshell
(eshell-insert-command "echo alpha")
(eshell-kill-output)
- (eshell-match-result (regexp-quote "*** output flushed ***\n"))
- (should (forward-line))
- (should (= (point) eshell-last-output-start))))
+ (eshell-match-result
+ (concat "^" (regexp-quote "*** output flushed ***\n") "$"))))
(ert-deftest eshell-test/run-old-command ()
"Re-run an old command"
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index aebc9b6dbb9..4b580b5af52 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -73,7 +73,7 @@ left alone when opening a URL in an external browser."
(urls nil)
(ffap-url-fetcher (lambda (url) (push url urls) nil)))
(should-not (ffap-other-window "https://www.gnu.org"))
- (should (compare-window-configurations (current-window-configuration) old))
+ (should (window-configuration-equal-p (current-window-configuration) old))
(should (equal urls '("https://www.gnu.org")))))
(defun ffap-test-string (space string)
@@ -141,6 +141,23 @@ left alone when opening a URL in an external browser."
(let (kill-buffer-query-functions)
(kill-buffer (call-interactively #'find-file-at-point)))))))
+(ert-deftest ffap-test-path ()
+ (skip-unless (file-exists-p "/bin"))
+ (skip-unless (file-exists-p "/usr/bin"))
+ (with-temp-buffer
+ (insert "/usr/bin:/bin")
+ (goto-char (point-min))
+ (should (equal (ffap-file-at-point) "/usr/bin")))
+ (with-temp-buffer
+ (insert "/usr/bin:/bin")
+ (goto-char (point-min))
+ (search-forward ":")
+ (should (equal (ffap-file-at-point) "/bin")))
+ (with-temp-buffer
+ (insert ":/bin")
+ (goto-char (point-min))
+ (should (equal (ffap-file-at-point) nil))))
+
(provide 'ffap-tests)
;;; ffap-tests.el ends here
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index 13bb2cd3452..4ed1786a8ef 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -52,34 +52,9 @@
;;; Code:
-(require 'ert)
+(require 'tramp)
(require 'ert-x)
(require 'filenotify)
-(require 'tramp)
-
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst file-notify-test-remote-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
- ;; batch mode only, therefore. `temporary-file-directory' might
- ;; be quoted, so we unquote it just in case.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" (file-name-unquote temporary-file-directory)))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
;; Filter suppressed remote file-notify libraries.
(when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY"))
@@ -203,10 +178,6 @@ Return nil when any other file notification watch is still active."
tramp-allow-unsafe-temporary-files
(or tramp-allow-unsafe-temporary-files noninteractive))
-;; This should happen on hydra only.
-(when (getenv "EMACS_HYDRA_CI")
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
-
(defun file-notify--test-add-watch (file flags callback)
"Like `file-notify-add-watch', but also passing FILE to CALLBACK."
(file-notify-add-watch file flags
@@ -232,12 +203,12 @@ being the result.")
(let (desc)
(ignore-errors
(and
- (file-remote-p file-notify-test-remote-temporary-file-directory)
- (file-directory-p file-notify-test-remote-temporary-file-directory)
- (file-writable-p file-notify-test-remote-temporary-file-directory)
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory)
(setq desc
(file-notify-add-watch
- file-notify-test-remote-temporary-file-directory
+ ert-remote-temporary-file-directory
'(change) #'ignore))))
(setq file-notify--test-remote-enabled-checked (cons t desc))
(when desc (file-notify-rm-watch desc))))
@@ -297,8 +268,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
`(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
,docstring
:tags (if ,unstable '(:expensive-test :unstable) '(:expensive-test))
- (let* ((temporary-file-directory
- file-notify-test-remote-temporary-file-directory)
+ (let* ((temporary-file-directory ert-remote-temporary-file-directory)
(ert-test (ert-get-test ',test))
vc-handled-backends)
(skip-unless (file-notify--test-remote-enabled))
diff --git a/test/lisp/files-resources/compile-utf8.el b/test/lisp/files-resources/compile-utf8.el
new file mode 100644
index 00000000000..1f804dcf8dc
--- /dev/null
+++ b/test/lisp/files-resources/compile-utf8.el
@@ -0,0 +1,12 @@
+;; -*- lexical-binding: t; -*-
+(defun zot ()
+ "Yes."
+ nil)
+
+(defun foo ()
+ "Yés."
+ nil)
+
+(defun bar ()
+ "Nó."
+ nil)
diff --git a/test/lisp/files-resources/file-mode b/test/lisp/files-resources/file-mode
new file mode 100644
index 00000000000..92ac4c30ef5
--- /dev/null
+++ b/test/lisp/files-resources/file-mode
@@ -0,0 +1,3 @@
+Local variables:
+mode: text
+end:
diff --git a/test/lisp/files-resources/file-mode-multiple b/test/lisp/files-resources/file-mode-multiple
new file mode 100644
index 00000000000..ac051ccbcbd
--- /dev/null
+++ b/test/lisp/files-resources/file-mode-multiple
@@ -0,0 +1,5 @@
+Local variables:
+mode: text
+mode: test-mode-undef
+mode: outline
+end:
diff --git a/test/lisp/files-resources/file-mode-prop-line b/test/lisp/files-resources/file-mode-prop-line
new file mode 100644
index 00000000000..e0e7ad24d71
--- /dev/null
+++ b/test/lisp/files-resources/file-mode-prop-line
@@ -0,0 +1 @@
+-*- mode: notexist; mode: text -*-
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index a3c67bc3d64..54ada088003 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -263,7 +263,7 @@ form.")
nil))
(kill-emacs-args nil)
((symbol-function #'kill-emacs)
- (lambda (&optional arg) (push arg kill-emacs-args)))
+ (lambda (&rest args) (push args kill-emacs-args)))
(process
(make-process
:name "sleep"
@@ -274,7 +274,7 @@ form.")
(save-buffers-kill-emacs)
(kill-process process)
(should-not yes-or-no-p-prompts)
- (should (equal kill-emacs-args '(nil)))))
+ (should (equal kill-emacs-args '((nil nil))))))
(ert-deftest files-tests-read-file-in-~ ()
"Test file prompting in directory named `~'.
@@ -393,6 +393,8 @@ After evaluating BODY, the temporary file or directory is deleted."
(cl-check-type name symbol)
(cl-check-type non-special-name symbol)
`(let* ((temporary-file-directory (file-truename temporary-file-directory))
+ (temporary-file-directory
+ (file-name-as-directory (make-temp-file "files-tests" t)))
(,name (make-temp-file "files-tests" ,dir-flag))
(,non-special-name (file-name-quote ,name)))
(unwind-protect
@@ -402,7 +404,9 @@ After evaluating BODY, the temporary file or directory is deleted."
(delete-file ,name)))
(when (file-exists-p ,non-special-name)
(if ,dir-flag (delete-directory ,non-special-name t)
- (delete-file ,non-special-name))))))
+ (delete-file ,non-special-name)))
+ (when (file-exists-p temporary-file-directory)
+ (delete-directory temporary-file-directory t)))))
(defconst files-tests--special-file-name-extension ".special"
"Trailing string for test file name handler.")
@@ -444,14 +448,16 @@ unquoted file names."
(cl-check-type name symbol)
(cl-check-type non-special-name symbol)
`(let* ((temporary-file-directory (file-truename temporary-file-directory))
+ (temporary-file-directory
+ (file-name-as-directory (make-temp-file "files-tests" t)))
(file-name-handler-alist
`((,files-tests--special-file-name-regexp
. files-tests--special-file-name-handler)
. ,file-name-handler-alist))
- (,name (concat
+ (,name (concat
(make-temp-file "files-tests" ,dir-flag)
files-tests--special-file-name-extension))
- (,non-special-name (file-name-quote ,name)))
+ (,non-special-name (file-name-quote ,name)))
(unwind-protect
(progn ,@body)
(when (file-exists-p ,name)
@@ -459,7 +465,9 @@ unquoted file names."
(delete-file ,name)))
(when (file-exists-p ,non-special-name)
(if ,dir-flag (delete-directory ,non-special-name t)
- (delete-file ,non-special-name))))))
+ (delete-file ,non-special-name)))
+ (when (file-exists-p temporary-file-directory)
+ (delete-directory temporary-file-directory t)))))
(defun files-tests--new-name (name part)
(let (file-name-handler-alist)
@@ -931,7 +939,7 @@ unquoted file names."
(files-tests--with-temp-non-special (tmpfile nospecial)
(should (load nospecial nil t)))
(files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
- (should (load nospecial nil t))))
+ (should-error (load nospecial nil t))))
(ert-deftest files-tests-file-name-non-special-make-auto-save-file-name ()
(files-tests--with-temp-non-special (tmpfile nospecial)
@@ -1411,7 +1419,10 @@ See <https://debbugs.gnu.org/35241>."
(equal tmpfile
(executable-find (file-name-nondirectory tmpfile)))))))
-(ert-deftest files-tests-dont-rewrite-precious-files ()
+;; Note: we call this test "...-zzdont..." so that it runs near the
+;; end, because otherwise the advice it adds to write-region doesn't
+;; get removed(??) and breaks the revert-file tests on MS-Windows.
+(ert-deftest files-tests-zzdont-rewrite-precious-files ()
"Test that `file-precious-flag' forces files to be saved by
renaming only, rather than modified in-place."
(ert-with-temp-file temp-file-name
@@ -1457,7 +1468,7 @@ renaming only, rather than modified in-place."
(should (equal (file-size-human-readable-iec 0) "0 B"))
(should (equal (file-size-human-readable-iec 1) "1 B"))
(should (equal (file-size-human-readable-iec 9621) "9.4 KiB"))
- (should (equal (file-size-human-readable-iec 72528034765) "67.5 GiB")))
+ (should (equal (file-size-human-readable-iec 72528034765) "68 GiB")))
(ert-deftest files-test-magic-mode-alist-re-baseline ()
"Test magic-mode-alist with RE, expected behavior for match."
@@ -1540,13 +1551,10 @@ The door of all subtleties!
(ert-with-temp-file temp-file-name
(with-temp-buffer
(insert files-tests-lao)
- ;; Disable lock files, since that barfs in
- ;; userlock--check-content-unchanged on MS-Windows.
- (let (create-lockfiles)
- (write-file temp-file-name)
- (erase-buffer)
- (insert files-tests-tzu)
- (revert-buffer t t t))
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (revert-buffer t t t)
(should (compare-strings files-tests-lao nil nil
(buffer-substring (point-min) (point-max))
nil nil)))))
@@ -1556,13 +1564,10 @@ The door of all subtleties!
(ert-with-temp-file temp-file-name
(with-temp-buffer
(insert files-tests-lao)
- ;; Disable lock files, since that barfs in
- ;; userlock--check-content-unchanged on MS-Windows.
- (let (create-lockfiles)
- (write-file temp-file-name)
- (erase-buffer)
- (insert files-tests-tzu)
- (should (revert-buffer-with-fine-grain t t)))
+ (write-file temp-file-name)
+ (erase-buffer)
+ (insert files-tests-tzu)
+ (should (revert-buffer-with-fine-grain t t))
(should (compare-strings files-tests-lao nil nil
(buffer-substring (point-min) (point-max))
nil nil)))))
@@ -1679,7 +1684,7 @@ PRED is nil."
(pcase-dolist (`(,pred ,def-pred-bind ,exp-1 ,exp-2) args-results)
(files-tests--save-some-buffers pred def-pred-bind exp-1 exp-2))))
-(defmacro files-tests--with-buffer-offer-save (buffers-offer fn-test fn-binders args-results)
+(defun files-tests--with-buffer-offer-save (buffers-offer fn-test args-results)
"Helper macro to test `save-some-buffers' and `save-buffers-kill-emacs'.
This macro creates several non-file-visiting buffers in different
@@ -1693,52 +1698,52 @@ FN-TEST is the function to test: either `save-some-buffers' or
`save-some-buffers-default-predicate' let-bound to a value
specified inside ARGS-RESULTS.
-FN-BINDERS is a list of elements (FUNCTION . BINDING), where FUNCTION
-is a function symbol that this macro temporary binds to BINDING during
-the FN-TEST call.
+During the call to FN-TEST,`read-event' is overridden with a function that
+just returns `n' and `kill-emacs' is overridden to do nothing.
ARGS-RESULTS is a list of elements (FN-ARGS CALLERS-DIR EXPECTED), where
FN-ARGS are the arguments for FN-TEST;
CALLERS-DIR specifies the value to let-bind
\`save-some-buffers-default-predicate';
EXPECTED is the expected result of the test."
- (declare (debug (form symbol form form)))
- (let ((dir (gensym "dir"))
- (buffers (gensym "buffers")))
- `(let* ((,dir (make-temp-file "testdir" 'dir))
- (inhibit-message t)
- (use-dialog-box nil)
- ,buffers)
- (pcase-dolist (`(,bufsym ,offer-save) ,buffers-offer)
- (let* ((buf (generate-new-buffer (symbol-name bufsym)))
- (subdir (expand-file-name
- (format "subdir-%s" (buffer-name buf))
- ,dir)))
- (make-directory subdir 'parens)
- (push buf ,buffers)
- (with-current-buffer buf
- (cd subdir)
- (setq buffer-offer-save offer-save)
- (insert "foobar\n"))))
- (setq ,buffers (nreverse ,buffers))
- (let ((nb-saved-buffers 0))
- (unwind-protect
- (pcase-dolist (`(,fn-test-args ,callers-dir ,expected)
- ,args-results)
- (setq nb-saved-buffers 0)
- (with-current-buffer (car ,buffers)
- (cl-letf
- (,@(mapcar (lambda (pair) `((symbol-function ,(car pair)) ,(cdr pair)))
- fn-binders)
- (save-some-buffers-default-predicate callers-dir))
- (apply #',fn-test fn-test-args)
- (should (equal nb-saved-buffers expected)))))
- ;; Clean up.
- (dolist (buf ,buffers)
- (with-current-buffer buf
- (set-buffer-modified-p nil)
- (kill-buffer buf)))
- (delete-directory ,dir 'recursive))))))
+ (let* ((dir (make-temp-file "testdir" 'dir))
+ (inhibit-message t)
+ (use-dialog-box nil)
+ buffers)
+ (pcase-dolist (`(,bufsym ,offer-save) buffers-offer)
+ (let* ((buf (generate-new-buffer (symbol-name bufsym)))
+ (subdir (expand-file-name
+ (format "subdir-%s" (buffer-name buf))
+ dir)))
+ (make-directory subdir 'parens)
+ (push buf buffers)
+ (with-current-buffer buf
+ (cd subdir)
+ (setq buffer-offer-save offer-save)
+ (insert "foobar\n"))))
+ (setq buffers (nreverse buffers))
+ (let ((nb-saved-buffers 0))
+ (unwind-protect
+ (pcase-dolist (`(,fn-test-args ,callers-dir ,expected)
+ args-results)
+ (setq nb-saved-buffers 0)
+ (with-current-buffer (car buffers)
+ (cl-letf
+ (((symbol-function 'read-event)
+ ;; Increase counter and answer 'n' when prompted
+ ;; to save a buffer.
+ (lambda (&rest _) (cl-incf nb-saved-buffers) ?n))
+ ;; Do not kill Emacs.
+ ((symbol-function 'kill-emacs) #'ignore)
+ (save-some-buffers-default-predicate callers-dir))
+ (apply fn-test fn-test-args)
+ (should (equal nb-saved-buffers expected)))))
+ ;; Clean up.
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (set-buffer-modified-p nil)
+ (kill-buffer buf)))
+ (delete-directory dir 'recursive)))))
(defmacro files-tests-with-all-permutations (permutation list &rest body)
"Execute BODY forms for all permutations of LIST.
@@ -1777,7 +1782,7 @@ PRED is nil."
(files-tests-with-all-permutations
buffers-offer
buffers-offer-init
- (dolist (pred `(nil t save-some-buffers-root))
+ (dolist (pred `(nil t))
(dolist (callers-dir `(nil save-some-buffers-root))
(let* ((head-offer (cadar buffers-offer))
(res (cond ((null pred)
@@ -1790,9 +1795,7 @@ PRED is nil."
(args-res `(((nil ,pred) ,callers-dir ,res))))
(files-tests--with-buffer-offer-save
buffers-offer
- save-some-buffers
- ;; Increase counter and answer 'n' when prompted to save a buffer.
- (('read-event . (lambda (&rest _) (cl-incf nb-saved-buffers) ?n)))
+ #'save-some-buffers
args-res)))))))
(ert-deftest files-tests-save-buffers-kill-emacs--asks-to-save-buffers ()
@@ -1807,10 +1810,7 @@ Prompt users for any modified buffer with `buffer-offer-save' non-nil."
buffers-offer-init
(files-tests--with-buffer-offer-save
buffers-offer
- save-buffers-kill-emacs
- ;; Increase counter and answer 'n' when prompted to save a buffer.
- (('read-event . (lambda (&rest _) (cl-incf nb-saved-buffers) ?n))
- ('kill-emacs . #'ignore)) ; Do not kill Emacs.
+ #'save-buffers-kill-emacs
`((nil nil ,nb-might-save)
;; `save-some-buffers-default-predicate' (i.e. the 2nd element) is ignored.
(nil save-some-buffers-root ,nb-might-save))))))
@@ -1822,5 +1822,50 @@ Prompt users for any modified buffer with `buffer-offer-save' non-nil."
(should (equal (file-name-split "/foo/bar/") '("" "foo" "bar" "")))
(should (equal (file-name-split "foo/bar/") '("foo" "bar" ""))))
+(ert-deftest files-test-set-mode ()
+ (find-file (ert-resource-file "file-mode"))
+ (should (eq major-mode 'text-mode))
+ (emacs-lisp-mode)
+ ;; Check that the mode cookie doesn't override the explicit setting.
+ (should (eq major-mode 'emacs-lisp-mode)))
+
+(ert-deftest files-test-set-mode-multiple ()
+ (find-file (ert-resource-file "file-mode-multiple"))
+ (should (eq major-mode 'outline-mode)))
+
+(ert-deftest files-test-set-mode-prop-line ()
+ (find-file (ert-resource-file "file-mode-prop-line"))
+ (should (eq major-mode 'text-mode)))
+
+(ert-deftest files-load-elc-gz-file ()
+ (skip-unless (executable-find "gzip"))
+ (ert-with-temp-directory dir
+ (let* ((pref (expand-file-name "compile-utf8" dir))
+ (el (concat pref ".el")))
+ (copy-file (ert-resource-file "compile-utf8.el") el)
+ (push dir load-path)
+ (should (load pref t))
+ (should (fboundp 'foo))
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot))
+
+ (byte-compile-file el)
+ (fmakunbound 'foo)
+ (should (load (concat pref ".elc") t))
+ (should (fboundp 'foo))
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot))
+
+ (dired-compress-file (concat pref ".elc"))
+ (fmakunbound 'foo)
+ (should (load (concat pref ".elc.gz") t))
+ (should (fboundp 'foo))
+ ;; This fails due to bug#12598.
+ (should (documentation 'foo))
+ (should (documentation 'bar))
+ (should (documentation 'zot)))))
+
(provide 'files-tests)
;;; files-tests.el ends here
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
index 60787e1cd3d..7ee2f0c1a65 100644
--- a/test/lisp/files-x-tests.el
+++ b/test/lisp/files-x-tests.el
@@ -325,6 +325,9 @@
(should-not (boundp 'remote-shell-file-name))
(should (string-equal (symbol-value 'remote-null-device) "null"))
+ (connection-local-set-profiles
+ files-x-test--application 'remote-bash)
+
(with-connection-local-variables
;; All connection-local variables are set. They apply in
;; reverse order in `connection-local-variables-alist'.
@@ -347,6 +350,21 @@
(should
(string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
(should
+ (string-equal (symbol-value 'remote-null-device) "/dev/null"))
+
+ ;; Run another instance of `with-connection-local-variables'
+ ;; with a different application.
+ (let ((connection-local-default-application (cadr files-x-test--application)))
+ (with-connection-local-variables
+ ;; The proper variable values are set.
+ (should
+ (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
+ (should
+ (string-equal (symbol-value 'remote-null-device) "/dev/null"))))
+ ;; The variable values are reset.
+ (should
+ (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
+ (should
(string-equal (symbol-value 'remote-null-device) "/dev/null")))
;; Everything is rewound. The old variable values are reset.
diff --git a/test/lisp/gnus/mml-sec-tests.el b/test/lisp/gnus/mml-sec-tests.el
index 182d82b9618..f308a617645 100644
--- a/test/lisp/gnus/mml-sec-tests.el
+++ b/test/lisp/gnus/mml-sec-tests.el
@@ -605,6 +605,9 @@ In this test, the encryption key needs to fixed among multiple ones."
(ert-deftest mml-secure-en-decrypt-3 ()
"Encrypt message; then decrypt and test for expected result.
In this test, encrypt-to-self variables are set to t."
+ ;; Random failures with "wrong-type-argument stringp nil".
+ ;; Seems unlikely to be specific to hydra.nixos.org...
+ :tags (if (getenv "EMACS_HYDRA_CI") '(:unstable))
(skip-unless (test-conf))
(skip-unless (ignore-errors (epg-find-configuration 'CMS)))
;; sub@example.org with multiple candidate keys,
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 6ee7b4f3eb1..e3fed60b4cb 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -25,6 +25,7 @@
(require 'ert)
(require 'help-fns)
+(require 'subr-x)
(autoload 'help-fns-test--macro "foo" nil nil t)
@@ -177,4 +178,13 @@ Return first line of the output of (describe-function-1 FUNC)."
(should-not (find-lisp-object-file-name help-fns--test-var 'defface))
(should-not (find-lisp-object-file-name help-fns--test-var 1))))
+(ert-deftest help-fns--analyze-function-recursive ()
+ (defalias 'help-fns--a 'help-fns--b)
+ (should (equal (help-fns--analyze-function 'help-fns--a)
+ '(help-fns--a help-fns--b t help-fns--b)))
+ ;; Make a loop and see that it doesn't infloop.
+ (defalias 'help-fns--b 'help-fns--a)
+ (should (equal (help-fns--analyze-function 'help-fns--a)
+ '(help-fns--a help-fns--b t help-fns--b))))
+
;;; help-fns-tests.el ends here
diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el
index c0c1cf8b530..04241f31383 100644
--- a/test/lisp/help-mode-tests.el
+++ b/test/lisp/help-mode-tests.el
@@ -41,11 +41,6 @@
(should (equal (buffer-name (current-buffer))
(help-buffer))))))
-(ert-deftest help-mode-tests-help-buffer-current-buffer-error ()
- (with-temp-buffer
- (let ((help-xref-following t))
- (should-error (help-buffer)))))
-
(ert-deftest help-mode-tests-make-xrefs ()
(with-temp-buffer
(insert "car is a built-in function in ‘C source code’.
@@ -81,7 +76,7 @@ Lisp concepts such as car, cdr, cons cell and list.")
(insert (format fmt fn))
(goto-char (point-min))
(re-search-forward help-xref-symbol-regexp)
- (help-xref-button 8 'help-function)
+ (help-xref-button 9 'help-function)
(should-not (button-at (1- beg)))
(should-not (button-at (+ beg (length (symbol-name fn)))))
(should (eq (button-type (button-at beg)) 'help-function))))))
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index d27e3d7cd4d..5c935965f78 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -95,16 +95,26 @@
(test "\\`C-m'\\`C-j'" "C-mC-j")
(test "foo\\`C-m'bar\\`C-j'baz" "fooC-mbarC-jbaz")))
-(ert-deftest help-tests-substitute-command-keys/literal-key-sequence-errors ()
- (should-error (substitute-command-keys "\\`'"))
- (should-error (substitute-command-keys "\\`c-c'"))
- (should-error (substitute-command-keys "\\`<foo bar baz>'")))
-
-(ert-deftest help-tests-substitute-key-bindings/face-help-key-binding ()
- (should (eq (get-text-property 0 'face (substitute-command-keys "\\[next-line]"))
- 'help-key-binding))
- (should (eq (get-text-property 0 'face (substitute-command-keys "\\`f'"))
- 'help-key-binding)))
+(ert-deftest help-tests-substitute-command-keys/literal-key-sequence-ignore-invalid ()
+ "Ignore any invalid literal key sequence."
+ (with-substitute-command-keys-test
+ (test-re "ab\\`'cd" "ab\\\\[`'‘]['’]cd")
+ (test-re "\\`c-c'" "\\\\[`'‘]c-c['’]")
+ (test-re "\\`<foo bar baz>'" "\\\\[`'‘]<foo bar baz>['’]")))
+
+(ert-deftest help-tests-substitute-key-bindings/help-key-binding-face ()
+ (let ((A (substitute-command-keys "\\[next-line]"))
+ (B (substitute-command-keys "\\`f'")))
+ (should (eq (get-text-property 0 'face A) 'help-key-binding))
+ (should (eq (get-text-property 0 'face B) 'help-key-binding))))
+
+(ert-deftest help-tests-substitute-key-bindings/help-key-binding-no-face ()
+ (let ((A (substitute-command-keys "\\[next-line]" t))
+ (B (substitute-command-keys "\\`f'" t)))
+ (should (eq (get-text-property 0 'face A) nil))
+ (should (eq (get-text-property 0 'face B) nil))
+ (should (equal A "C-n"))
+ (should (equal B "f"))))
(defvar-keymap help-tests--test-keymap
:doc "Just some keymap for testing."
@@ -286,11 +296,11 @@ M-g M-c switch-to-completions
"
Key Binding
-+
-( .. ) short-range
1 .. 4 foo-range
a .. c foo-other-range
C-e foo-something
+( .. ) short-range
x foo-original
<F1> foo-function-key1
"))))
@@ -304,12 +314,12 @@ x foo-original
"
Key Binding
-+
-( .. ) short-range
1 .. 4 foo-range
a .. c foo-other-range
C-e foo-something
(this binding is currently shadowed)
+( .. ) short-range
x foo-original
(this binding is currently shadowed)
<F1> foo-function-key1
diff --git a/test/lisp/hi-lock-tests.el b/test/lisp/hi-lock-tests.el
index 71983c713d2..760b319a926 100644
--- a/test/lisp/hi-lock-tests.el
+++ b/test/lisp/hi-lock-tests.el
@@ -30,10 +30,9 @@
(let ((faces hi-lock-face-defaults))
(with-temp-buffer
(insert "a A b B\n")
- (cl-letf (((symbol-function 'completing-read)
- (lambda (_prompt _coll
- &optional _x _y _z _hist defaults _inherit)
- (car defaults))))
+ (cl-letf (((symbol-function 'read-face-name)
+ (lambda (_prompt &optional defaults)
+ (intern (car defaults)))))
(dotimes (_ 2)
(let ((face (hi-lock-read-face-name)))
(hi-lock-set-pattern "a" face))))
@@ -43,10 +42,9 @@
(let ((faces hi-lock-face-defaults))
(with-temp-buffer
(insert "foo bar")
- (cl-letf (((symbol-function 'completing-read)
- (lambda (_prompt _coll
- &optional _x _y _z _hist defaults _inherit)
- (car defaults))))
+ (cl-letf (((symbol-function 'read-face-name)
+ (lambda (_prompt &optional defaults)
+ (intern (car defaults)))))
(hi-lock-set-pattern "9999" (hi-lock-read-face-name)) ; No match
(hi-lock-set-pattern "foo" (hi-lock-read-face-name)))
;; Only one match, then we have used just 1 face
diff --git a/test/lisp/hl-line-tests.el b/test/lisp/hl-line-tests.el
new file mode 100644
index 00000000000..888351addac
--- /dev/null
+++ b/test/lisp/hl-line-tests.el
@@ -0,0 +1,114 @@
+;;; hl-line-tests.el --- Test suite for hl-line. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+(require 'hl-line)
+
+(defsubst hl-line-tests-verify (_label on-p)
+ (if on-p
+ (cl-some (apply-partially #'eq hl-line-overlay)
+ (overlays-at (point)))
+ (not (cl-some (apply-partially #'eq hl-line-overlay)
+ (overlays-at (point))))))
+
+(ert-deftest hl-line-tests-sticky-across-frames ()
+ (skip-unless (display-graphic-p))
+ (customize-set-variable 'global-hl-line-sticky-flag t)
+ (call-interactively #'global-hl-line-mode)
+ (let ((first-frame (selected-frame))
+ (first-buffer "foo")
+ (second-buffer "bar")
+ second-frame)
+ (unwind-protect
+ (progn
+ (switch-to-buffer first-buffer)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 111 t))
+ (select-frame (setq second-frame (make-frame)))
+ (switch-to-buffer second-buffer)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 762 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 534 t)))
+ (call-interactively #'global-hl-line-mode)
+ (should (hl-line-tests-verify 125 nil))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 892 nil)))
+
+ ;; now do unsticky
+ (customize-set-variable 'hl-line-sticky-flag nil)
+ (call-interactively #'global-hl-line-mode)
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 467 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 765 nil)))
+ (select-frame first-frame)
+ (should (equal (buffer-name) first-buffer))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 423 t))
+ (with-current-buffer second-buffer
+ (should (hl-line-tests-verify 897 nil))))
+ (let (kill-buffer-query-functions)
+ (ignore-errors (kill-buffer first-buffer))
+ (ignore-errors (kill-buffer second-buffer))
+ (ignore-errors (delete-frame second-frame))))))
+
+(ert-deftest hl-line-tests-sticky ()
+ (customize-set-variable 'hl-line-sticky-flag t)
+ (let ((first-buffer "foo")
+ (second-buffer "bar"))
+ (unwind-protect
+ (progn
+ (switch-to-buffer first-buffer)
+ (hl-line-mode 1)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 123 t))
+ (switch-to-buffer second-buffer)
+ (hl-line-mode 1)
+ (save-excursion
+ (insert (buffer-name)))
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 56 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 67 t)))
+
+ ;; now do unsticky
+ (customize-set-variable 'hl-line-sticky-flag nil)
+ (should (hl-line-tests-verify 234 t))
+ (with-current-buffer first-buffer
+ (should (hl-line-tests-verify 231 nil)))
+ (switch-to-buffer first-buffer)
+ (run-hooks 'post-command-hook)
+ (should (hl-line-tests-verify 257 t))
+ (with-current-buffer second-buffer
+ (should (hl-line-tests-verify 999 nil)))))
+ (let (kill-buffer-query-functions)
+ (ignore-errors (kill-buffer first-buffer))
+ (ignore-errors (kill-buffer second-buffer)))))
+
+(provide 'hl-line-tests)
+
+;;; hl-line-tests.el ends here
diff --git a/test/lisp/htmlfontify-tests.el b/test/lisp/htmlfontify-tests.el
index fdfe996b033..5c1f053066b 100644
--- a/test/lisp/htmlfontify-tests.el
+++ b/test/lisp/htmlfontify-tests.el
@@ -21,15 +21,6 @@
(require 'ert)
(require 'htmlfontify)
-(ert-deftest htmlfontify-autoload ()
- "Tests to see whether reftex-auc has been autoloaded"
- (should
- (fboundp 'htmlfontify-load-rgb-file))
- (should
- (autoloadp
- (symbol-function
- 'htmlfontify-load-rgb-file))))
-
(ert-deftest htmlfontify-bug25468 ()
"Tests that htmlfontify can be loaded even if no shell is
available (Bug#25468)."
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index 252d2c5d7f7..343e2ae50b1 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -785,7 +785,7 @@
(funcall tag
(funcall description
'starred-name)
- ": " "nil"))
+ "" ""))
(funcall tag
(funcall description 'directory)
": " "\\<org\\>")))))
@@ -806,7 +806,7 @@
(funcall tag "AND"
(funcall tag
(funcall description 'starred-name)
- ": " "nil")
+ "" "")
(funcall tag
(funcall description 'name)
": " "elisp"))
diff --git a/test/lisp/image-tests.el b/test/lisp/image-tests.el
index 6abfcfedcf4..bc8c3636c3c 100644
--- a/test/lisp/image-tests.el
+++ b/test/lisp/image-tests.el
@@ -74,10 +74,24 @@
(should (listp (find-image '((:type png :file "newsticker/rss-feed.png" :ascent center)))))
(should-not (find-image '((:type png :file "does-not-exist-foo-bar.png")))))
+(ert-deftest image-supported-file-p/built-in ()
+ ;; (skip-unless (image-type-available-p 'pbm)) ; Always built-in
+ (skip-unless (display-images-p)) ; (except in nox builds).
+ (should (eq (image-supported-file-p "foo.pbm") 'pbm)))
+
+(ert-deftest image-supported-file-p/optional ()
+ (if (image-type-available-p 'jpeg)
+ (should (eq (image-supported-file-p "foo.jpg") 'jpeg))
+ (should-not (image-supported-file-p "foo.jpg"))))
+
+(ert-deftest image-supported-file-p/unsupported-returns-nil ()
+ (should-not (image-supported-file-p "foo.some-unsupported-format")))
+
(ert-deftest image-type-from-file-name ()
- (should (eq (image-type-from-file-name "foo.jpg") 'jpeg))
- (should (eq (image-type-from-file-name "foo.png") 'png))
- (should (eq (image-type-from-file-name "foo.webp") 'webp)))
+ (with-suppressed-warnings ((obsolete image-type-from-file-name))
+ (should (eq (image-type-from-file-name "foo.jpg") 'jpeg))
+ (should (eq (image-type-from-file-name "foo.png") 'png))
+ (should (eq (image-type-from-file-name "foo.webp") 'webp))))
(ert-deftest image-type/from-filename ()
;; On emba, `image-types' and `image-load-path' do not exist.
diff --git a/test/lisp/international/textsec-tests.el b/test/lisp/international/textsec-tests.el
new file mode 100644
index 00000000000..6b0773dc407
--- /dev/null
+++ b/test/lisp/international/textsec-tests.el
@@ -0,0 +1,214 @@
+;;; textsec-tests.el --- Tests for textsec.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'textsec)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-scripts ()
+ (should (equal (textsec-scripts "Circle")
+ '((latin) (latin) (latin) (latin) (latin) (latin))))
+ (should (textsec-single-script-p "Circle"))
+
+ (should (equal (textsec-scripts "СігсӀе")
+ '((cyrillic) (cyrillic) (cyrillic)
+ (cyrillic) (cyrillic) (cyrillic))))
+ (should (textsec-single-script-p "СігсӀе"))
+
+ (should (equal (textsec-scripts "Сirсlе")
+ '((cyrillic) (latin) (latin) (cyrillic) (latin) (cyrillic))))
+ (should-not (textsec-single-script-p "Сirсlе"))
+
+ (should (equal (textsec-scripts "Circ1e")
+ '((latin) (latin) (latin) (latin) (common) (latin))))
+ (should (textsec-single-script-p "Circ1e"))
+
+ (should (equal (textsec-scripts "C𝗂𝗋𝖼𝗅𝖾")
+ '((latin) (common) (common) (common) (common) (common))))
+ (should (textsec-single-script-p "C𝗂𝗋𝖼𝗅𝖾"))
+
+ (should (equal (textsec-scripts "𝖢𝗂𝗋𝖼𝗅𝖾")
+ '((common) (common) (common) (common) (common) (common))))
+ (should (textsec-single-script-p "𝖢𝗂𝗋𝖼𝗅𝖾"))
+
+ (should (equal (textsec-scripts "〆切")
+ '((common han) (han))))
+ (should (textsec-single-script-p "〆切"))
+
+ (should (equal (textsec-scripts "ねガ")
+ '((hiragana) (katakana))))
+ (should (textsec-single-script-p "ねガ")))
+
+(ert-deftest test-minimal-scripts ()
+ (should (equal (textsec-covering-scripts "Circle")
+ '(latin)))
+ (should (equal (textsec-covering-scripts "Сirсlе")
+ '(cyrillic latin)))
+ (should (equal (textsec-covering-scripts "〆切")
+ '(han))))
+
+(ert-deftest test-restriction-level ()
+ (should (eq (textsec-restriction-level "foo")
+ 'ascii-only))
+ (should (eq (textsec-restriction-level "C𝗂𝗋𝖼𝗅𝖾")
+ 'single-script))
+ (should (eq (textsec-restriction-level "切foo")
+ 'highly-restrictive))
+ (should (eq (textsec-restriction-level "հfoo")
+ 'moderately-retrictive))
+ (should (eq (textsec-restriction-level "Сirсlе")
+ 'unrestricted)))
+
+(ert-deftest test-mixed-numbers ()
+ (should-not (textsec-mixed-numbers-p "foo"))
+ (should-not (textsec-mixed-numbers-p "8foo8"))
+ (should-not (textsec-mixed-numbers-p "foo20@foo.org"))
+ (should (textsec-mixed-numbers-p "8foo৪")))
+
+(ert-deftest test-resolved ()
+ (should (equal (textsec-resolved-script-set "ljeto")
+ '(latin)))
+ (should-not (textsec-resolved-script-set "Сirсlе")))
+
+(ert-deftest test-confusable ()
+ (should (equal (textsec-unconfuse-string "ljeto") "ljeto"))
+ (should (textsec-ascii-confusable-p "ljeto"))
+ (should-not (textsec-ascii-confusable-p "ljeto"))
+ (should (equal (textsec-unconfuse-string "~") "〜"))
+ (should-not (textsec-ascii-confusable-p "~"))
+
+ (should (textsec-single-script-confusable-p "ljeto" "ljeto"))
+ (should-not (textsec-single-script-confusable-p "paypal" "pаypаl"))
+ (should-not (textsec-single-script-confusable-p "scope""ѕсоре"))
+
+ (should-not (textsec-mixed-script-confusable-p "ljeto" "ljeto"))
+ (should (textsec-mixed-script-confusable-p "paypal" "pаypаl"))
+ (should (textsec-mixed-script-confusable-p "scope""ѕсоре"))
+
+ (should-not (textsec-whole-script-confusable-p "ljeto" "ljeto"))
+ (should-not (textsec-whole-script-confusable-p "paypal" "pаypаl"))
+ (should (textsec-whole-script-confusable-p "scope""ѕсоре")))
+
+(ert-deftest test-suspiction-domain ()
+ (should (textsec-domain-suspicious-p "foo/bar.org"))
+ (should-not (textsec-domain-suspicious-p "foo.org"))
+ (should (textsec-domain-suspicious-p "f\N{LEFT-TO-RIGHT ISOLATE}oo.org"))
+
+ (should (textsec-domain-suspicious-p "Сгсе.ru"))
+ (should-not (textsec-domain-suspicious-p "фСгсе.ru"))
+
+ (should-not (textsec-domain-suspicious-p
+ "21a:34aa:c782:3ad2:1bf8:73f8:141:66e8"))
+ (should (textsec-domain-suspicious-p
+ "21a:34aa:c782:3ad2:1bf8:73f8:141:66e8:66e8"))
+ (should-not (textsec-domain-suspicious-p
+ "[21a:34aa:c782:3ad2:1bf8:73f8:141:66e8]"))
+ (should (textsec-domain-suspicious-p
+ "[21a:34aa:c782:3ad2:1bf8:73f8:141:66e8"))
+ (should-not (textsec-domain-suspicious-p "138.25.106.12"))
+ (should-not (textsec-domain-suspicious-p "2001:db8::ff00:42:8329"))
+ (should-not (textsec-domain-suspicious-p "::ffff:129.55.2.201")))
+
+(ert-deftest test-suspicious-local ()
+ (should-not (textsec-local-address-suspicious-p "larsi"))
+ (should (textsec-local-address-suspicious-p ".larsi"))
+ (should (textsec-local-address-suspicious-p "larsi."))
+ (should-not (textsec-local-address-suspicious-p "la.rsi"))
+ (should (textsec-local-address-suspicious-p "lar..si"))
+
+ (should-not (textsec-local-address-suspicious-p "LÅRSI"))
+ (should (textsec-local-address-suspicious-p "LÅRSI"))
+
+ (should (textsec-local-address-suspicious-p "larsi8৪")))
+
+(ert-deftest test-suspicious-name ()
+ (should-not (textsec-name-suspicious-p "Lars Ingebrigtsen"))
+ (should (textsec-name-suspicious-p "LÅRS INGEBRIGTSEN"))
+ (should-not (textsec-name-suspicious-p "LÅRS INGEBRIGTSEN"))
+
+ (should (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT OVERRIDE}"))
+ (should (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT OVERRIDE}f"))
+ (should-not (textsec-name-suspicious-p
+ "Lars Ingebrigtsen\N{LEFT-TO-RIGHT MARK}"))
+ (should-not (textsec-name-suspicious-p "אבגד ⁧שונה⁩ מרגיל"))
+
+ (should (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING GRAVE ACCENT}Lars Ingebrigtsen"))
+ (should-not (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}Lars Ingebrigtsen"))
+ (should (textsec-name-suspicious-p
+ "\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}\N{COMBINING GRAVE ACCENT}\N{COMBINING ENCLOSING CIRCLE}\N{COMBINING GRAVE ACCENT}Lars Ingebrigtsen")))
+
+(ert-deftest test-suspicious-email ()
+ (should-not
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "LÅrs Ingebrigtsen <larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <.larsi@gnus.org>"))
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@gn\N{LEFT-TO-RIGHT ISOLATE}us.org>"))
+
+ (should
+ (textsec-email-address-header-suspicious-p
+ "Lars Ingebrigtsen <larsi@\N{RIGHT-TO-LEFT OVERRIDE}gnus.org>"))
+
+ (should-not (textsec-email-address-header-suspicious-p
+ "דגבא <foo@bar.com>"))
+
+ (should (textsec-email-address-suspicious-p
+ "Bob_Norbolwits@GCSsafetyACE.com​")))
+
+(ert-deftest test-suspicious-url ()
+ (should-not (textsec-url-suspicious-p "http://example.ru/bar"))
+ (should (textsec-url-suspicious-p "http://Сгсе.ru/bar")))
+
+(ert-deftest test-suspicious-link ()
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "Hello")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "https://gnu.org/")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://gnu.org/" "https://www.gnu.org/")))
+ (should-not (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://gnu.org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "https://fsf.org/")))
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gnu.org/" "http://fsf.org/")))
+
+ (should (textsec-link-suspicious-p
+ (cons "https://www.gn\N{LEFT-TO-RIGHT ISOLATE}u.org/"
+ "https://gn\N{LEFT-TO-RIGHT ISOLATE}u.org"))))
+
+;;; textsec-tests.el ends here
diff --git a/test/lisp/isearch-tests.el b/test/lisp/isearch-tests.el
index 4600757d940..8cb5e5e4542 100644
--- a/test/lisp/isearch-tests.el
+++ b/test/lisp/isearch-tests.el
@@ -38,5 +38,85 @@
;; Bug #21091: let `isearch-done' work without `isearch-update'.
(isearch-done))
+
+;; Search functions.
+
+(defun isearch--test-search-within-boundaries (pairs)
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp nil))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string "foo" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp nil))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "foo" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string ".*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string "^.*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-min))
+ (let ((isearch-forward t)
+ (isearch-regexp t))
+ (dolist (pos (append pairs nil))
+ (should (eq (cdr pos) (isearch-search-string ".*$" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (car pos) (should (eq (car pos) (match-beginning 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp t))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "^.*" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0))))))
+
+ (goto-char (point-max))
+ (let ((isearch-forward nil)
+ (isearch-regexp t))
+ (dolist (pos (append (reverse pairs) nil))
+ (should (eq (car pos) (isearch-search-string "foo$" nil t)))
+ (should (equal (match-string 0) "foo"))
+ (when (cdr pos) (should (eq (cdr pos) (match-end 0)))))))
+
+(ert-deftest isearch--test-search-fun-in-text-property ()
+ (let* ((pairs '((4 . 7) (11 . 14) (21 . 24)))
+ (isearch-search-fun-function
+ (lambda () (isearch-search-fun-in-text-property nil 'dired-filename))))
+ (with-temp-buffer
+ (insert "foo" (propertize "foo" 'dired-filename t) "foo\n")
+ (insert (propertize "foo" 'dired-filename t) "foo\n")
+ (insert "foo" (propertize "foo" 'dired-filename t) "\n")
+ (isearch--test-search-within-boundaries pairs))))
+
+(ert-deftest isearch--test-search-fun-in-noncontiguous-region ()
+ (let* ((pairs '((4 . 7) (11 . 14) (21 . 24)))
+ (isearch-search-fun-function
+ (lambda () (isearch-search-fun-in-noncontiguous-region nil pairs))))
+ (with-temp-buffer
+ (insert "foofoofoo\n")
+ (insert "foofoo\n")
+ (insert "foofoo\n")
+ (isearch--test-search-within-boundaries pairs))))
+
(provide 'isearch-tests)
;;; isearch-tests.el ends here
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index ef7805a3416..ab1f19fb6e7 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -510,8 +510,8 @@ Point is moved to beginning of the buffer."
(let ((json-key-type 'string))
(setq obj (json-add-to-object obj "g" 7))
(setq obj (json-add-to-object obj "h" 8))
- (should (= (lax-plist-get obj "g") 7))
- (should (= (lax-plist-get obj "h") 8)))))
+ (should (= (plist-get obj "g" #'equal) 7))
+ (should (= (plist-get obj "h" #'equal) 8)))))
(ert-deftest test-json-add-to-hash-table ()
(let* ((json-object-type 'hash-table)
diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el
index c62a2a501ba..75d700070aa 100644
--- a/test/lisp/kmacro-tests.el
+++ b/test/lisp/kmacro-tests.el
@@ -580,8 +580,10 @@ This is a regression test for: Bug#3412, Bug#11817."
;; Check the bound key and run it and verify correct counter
;; and format.
(should (equal (string-to-vector "\C-cxi")
- (car (kmacro-extract-lambda
- (key-binding "\C-x\C-kA")))))
+ (car (with-suppressed-warnings
+ ((obsolete kmacro-extract-lambda))
+ (kmacro-extract-lambda
+ (key-binding "\C-x\C-kA"))))))
(kmacro-tests-should-insert "<5>"
(funcall (key-binding "\C-x\C-kA")))))
@@ -605,7 +607,7 @@ This is a regression test for: Bug#3412, Bug#11817."
(dotimes (i 2)
(kmacro-tests-define-macro (make-vector (1+ i) (+ ?a i)))
(kmacro-name-last-macro 'kmacro-tests-symbol-for-test)
- (should (fboundp 'kmacro-tests-symbol-for-test)))
+ (should (commandp 'kmacro-tests-symbol-for-test)))
;; Now run the function bound to the symbol. Result should be the
;; second macro.
@@ -822,6 +824,15 @@ This is a regression for item 7 in Bug#24991."
:macro-result "x")
(kmacro-tests-simulate-command '(beginning-of-line))))
+(ert-deftest kmacro-tests--cl-print ()
+ (should (equal (cl-prin1-to-string
+ (kmacro [?a ?b backspace backspace]))
+ "#f(kmacro \"a b <backspace> <backspace>\")"))
+ (should (equal (cl-prin1-to-string
+ (with-suppressed-warnings ((obsolete kmacro-lambda-form))
+ (kmacro-lambda-form [?a ?b backspace backspace] 1 "%d")))
+ "#f(kmacro \"a b <backspace> <backspace>\" 1 \"%d\")")))
+
(cl-defun kmacro-tests-run-step-edit
(macro &key events sequences result macro-result)
"Set up and run a test of `kmacro-step-edit-macro'.
diff --git a/test/lisp/loadhist-resources/loadhist--bar.el b/test/lisp/loadhist-resources/loadhist--bar.el
new file mode 100644
index 00000000000..5c8914ed573
--- /dev/null
+++ b/test/lisp/loadhist-resources/loadhist--bar.el
@@ -0,0 +1,27 @@
+;;; loadhist--bar.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(autoload 'loadhist--foo-inc "loadhist--foo")
+
+(defun loadhist--bar-dec (x) (1- x))
+
+(provide 'loadhist--bar)
+;;; loadhist--bar.el ends here
diff --git a/test/lisp/loadhist-resources/loadhist--foo.el b/test/lisp/loadhist-resources/loadhist--foo.el
new file mode 100644
index 00000000000..3574c220135
--- /dev/null
+++ b/test/lisp/loadhist-resources/loadhist--foo.el
@@ -0,0 +1,29 @@
+;;; loadhist--foo.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(autoload 'loadhist--bar-dec "loadhist--bar")
+
+(defun loadhist--foo-inc (x) (1+ x))
+
+(provide 'loadhist--foo)
+;;; loadhist--foo.el ends here
diff --git a/test/lisp/loadhist-tests.el b/test/lisp/loadhist-tests.el
index a941ac06320..ef5fc164d34 100644
--- a/test/lisp/loadhist-tests.el
+++ b/test/lisp/loadhist-tests.el
@@ -54,4 +54,51 @@
(should-error (unload-feature 'dired))
(unload-feature 'dired-x))
+(defvar loadhist--tests-dir (file-name-directory (macroexp-file-name)))
+
+(ert-deftest loadhist-tests-unload-feature-nested ()
+ (add-to-list 'load-path (expand-file-name
+ "loadhist-resources/"
+ loadhist--tests-dir))
+ (declare-function loadhist--foo-inc "loadhist--foo")
+ (declare-function loadhist--bar-dec "loadhist--dec")
+ (load "loadhist--foo" nil t)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (autoloadp (symbol-function 'loadhist--bar-dec)))
+ (load "loadhist--bar" nil t)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (not (autoloadp (symbol-function 'loadhist--bar-dec))))
+ (should (not (autoloadp (symbol-function 'loadhist--foo-inc))))
+ (should (equal (list 40 42)
+ (list (loadhist--bar-dec 41) (loadhist--foo-inc 41))))
+ (unload-feature 'loadhist--bar)
+ (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc)))
+ (should (autoloadp (symbol-function 'loadhist--bar-dec)))
+ (should (not (autoloadp (symbol-function 'loadhist--foo-inc))))
+ (unload-feature 'loadhist--foo)
+ (should (null (symbol-function 'loadhist--bar-dec)))
+ (should (null (symbol-function 'loadhist--foo-inc)))
+ (should (null (get 'loadhist--bar-dec 'function-history)))
+ (should (null (get 'loadhist--foo-inc 'function-history))))
+
+(ert-deftest loadhist-tests-unload-feature-notnested ()
+ (add-to-list 'load-path (expand-file-name
+ "loadhist-resources/"
+ loadhist--tests-dir))
+ (load "loadhist--foo" nil t)
+ (load "loadhist--bar" nil t)
+ (should (equal (list 40 42)
+ (list (loadhist--bar-dec 41) (loadhist--foo-inc 41))))
+ (unload-feature 'loadhist--foo)
+ (should (functionp 'loadhist--bar-dec))
+ (should (not (autoloadp (symbol-function 'loadhist--bar-dec))))
+ (should (let ((f (symbol-function 'loadhist--foo-inc)))
+ ;; Both choices seem acceptable.
+ (or (null f) (autoloadp f))))
+ (unload-feature 'loadhist--bar)
+ (should (null (symbol-function 'loadhist--bar-dec)))
+ (should (null (symbol-function 'loadhist--foo-inc)))
+ (should (null (get 'loadhist--bar-dec 'function-history)))
+ (should (null (get 'loadhist--foo-inc 'function-history))))
+
;;; loadhist-tests.el ends here
diff --git a/test/lisp/ls-lisp-tests.el b/test/lisp/ls-lisp-tests.el
index 3e23fc74540..39843defc2e 100644
--- a/test/lisp/ls-lisp-tests.el
+++ b/test/lisp/ls-lisp-tests.el
@@ -93,5 +93,44 @@
(should (looking-back "[[:space:]]" (1- (point)))))
(when (buffer-live-p buf) (kill-buffer buf)))))
+(ert-deftest ls-lisp-test-bug55787 ()
+ "Test proper sorting by version."
+ (let ((files1 (vector "34 klmn-300dpi.jpg"
+ "34 klmn-300dpi.png"
+ "054_xyz.jpg"
+ "054_xyz.png"
+ "91 opqrs.jpg"
+ "91 opqrs.png"
+ "0717-abcd.jpg"
+ "0717-abcd.png"
+ "1935 uv.jpg"
+ "1935 uv.png"
+ "FFFF_fghk.jpg"
+ "FFFF_fghk.png"
+ "hhhh.jpg"
+ "hhhh.png"))
+ (files2 (vector "01.0" "10" "010" "01.2")))
+ (should (equal (sort files1
+ (lambda (x y)
+ (ls-lisp-version-lessp x y)))
+ '["0717-abcd.jpg"
+ "0717-abcd.png"
+ "054_xyz.jpg"
+ "054_xyz.png"
+ "34 klmn-300dpi.jpg"
+ "34 klmn-300dpi.png"
+ "91 opqrs.jpg"
+ "91 opqrs.png"
+ "1935 uv.jpg"
+ "1935 uv.png"
+ "FFFF_fghk.jpg"
+ "FFFF_fghk.png"
+ "hhhh.jpg"
+ "hhhh.png"]))
+ (should (equal (sort files2
+ (lambda (x y)
+ (ls-lisp-version-lessp x y)))
+ '["01.0" "01.2" "010" "10"]))))
+
(provide 'ls-lisp-tests)
;;; ls-lisp-tests.el ends here
diff --git a/test/lisp/mail/ietf-drums-date-tests.el b/test/lisp/mail/ietf-drums-date-tests.el
new file mode 100644
index 00000000000..781d72d3529
--- /dev/null
+++ b/test/lisp/mail/ietf-drums-date-tests.el
@@ -0,0 +1,172 @@
+;;; ietf-drums-date-tests.el --- Test suite for ietf-drums-date.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Bob Rogers <rogers@rgrjr.com>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ietf-drums)
+(require 'ietf-drums-date)
+
+(ert-deftest ietf-drums-date-tests ()
+ "Test basic ietf-drums-parse-date-string functionality."
+
+ ;; Test tokenization.
+ (should (equal (ietf-drums-date--tokenize-string " ") '()))
+ (should (equal (ietf-drums-date--tokenize-string " a b") '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "a bbc dde")
+ '("a" "bbc" "dde")))
+ (should (equal (ietf-drums-date--tokenize-string " , a 27 b,, c 14:32 ")
+ '("a" 27 "b" "c" "14:32")))
+ ;; Some folding whitespace tests.
+ (should (equal (ietf-drums-date--tokenize-string " a b (end) c" t)
+ '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "(quux)a (foo (bar)) b(baz)")
+ '("a" "b")))
+ (should (equal (ietf-drums-date--tokenize-string "a b\\cde")
+ ;; Strictly incorrect, but strictly unnecessary syntax.
+ '("a" "b\\cde")))
+ (should (equal (ietf-drums-date--tokenize-string "a b\\ de")
+ '("a" "b\\ de")))
+ (should (equal (ietf-drums-date--tokenize-string "a \\de \\(f")
+ '("a" "\\de" "\\(f")))
+
+ ;; Start with some compatible RFC822 dates.
+ (dolist (case '(("Mon, 22 Feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("22 Feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 nil -1 3600))
+ ("Mon, 22 February 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Mon, 22 feb 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Monday, 22 february 2016 19:35:42 +0100"
+ (42 35 19 22 2 2016 1 -1 3600))
+ ("Monday, 22 february 2016 19:35:42 PST"
+ (42 35 19 22 2 2016 1 nil -28800))
+ ("Friday, 21 Sep 2018 13:47:58 PDT"
+ (58 47 13 21 9 2018 5 t -25200))
+ ("Friday, 21 Sep 2018 13:47:58 EDT"
+ (58 47 13 21 9 2018 5 t -14400))
+ ("Mon, 22 Feb 2016 19:35:42"
+ (42 35 19 22 2 2016 1 -1 nil))
+ ("Friday, 21 Sep 2018 13:47:58"
+ (58 47 13 21 9 2018 5 -1 nil))))
+ (let* ((input (car case))
+ (parsed (cadr case)))
+ ;; The input should parse the same without RFC822.
+ (should (equal (ietf-drums-parse-date-string input) parsed))
+ (should (equal (ietf-drums-parse-date-string input nil t) parsed))
+ ;; Check the encoded date (the official output, though the
+ ;; decoded-time is easier to debug).
+ (should (time-equal-p (ietf-drums-parse-date input)
+ (encode-time parsed)))))
+
+ ;; Two-digit years are not allowed by the "modern" format.
+ (should (equal (ietf-drums-parse-date-string "22 Feb 16 19:35:42 +0100")
+ '(42 35 19 22 2 2016 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 16 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb 16 19:35:42 +0100" t t))
+ '(date-parse-error "Four-digit years are required" 16)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 96 19:35:42 +0100")
+ '(42 35 19 22 2 1996 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string "22 Feb 96 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb 96 19:35:42 +0100" t t))
+ '(date-parse-error "Four-digit years are required" 96)))
+
+ ;; Try some dates with comments.
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100")
+ '(42 35 19 22 2 2016 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100" nil t)
+ '(nil nil nil 22 2 nil nil -1 nil)))
+ (should (equal (should-error (ietf-drums-parse-date-string
+ "22 Feb (today) 16 19:35:42 +0100" t t))
+ '(date-parse-error "Expected a year" nil)))
+ (should (equal (ietf-drums-parse-date-string
+ "22 Feb 96 (long ago) 19:35:42 +0100")
+ '(42 35 19 22 2 1996 nil -1 3600)))
+ (should (equal (ietf-drums-parse-date-string
+ "Friday, 21 Sep(comment \\) with \\( parens)18 19:35:42")
+ '(42 35 19 21 9 2018 5 -1 nil)))
+ (should (equal (ietf-drums-parse-date-string
+ "Friday, 21 Sep 18 19:35:42 (unterminated comment")
+ '(42 35 19 21 9 2018 5 -1 nil)))
+
+ ;; Test some RFC822 error cases
+ (dolist (test '(("33 1 2022" ("Slot out of range" day 33 1 31))
+ ("0 1 2022" ("Slot out of range" day 0 1 31))
+ ("1 1 2020 2021" ("Expected an alphabetic month" 1))
+ ("1 Jan 2020 2021" ("Expected a time" 2021))
+ ("1 Jan 2020 20:21 2000" ("Expected a timezone" 2000))
+ ("1 Jan 2020 20:21 +0200 33" ("Extra token(s)" 33))))
+ (should (equal (should-error (ietf-drums-parse-date-string (car test) t))
+ (cons 'date-parse-error (cadr test)))))
+
+ (dolist (test '(("22 Feb 196" nil ;; bad year
+ ("Four-digit years are required" 196))
+ ("22 Feb 16 19:35:24" t ;; two-digit year
+ ("Four-digit years are required" 16))
+ ("22 Feb 96 19:35:42" t ;; two-digit year
+ ("Four-digit years are required" 96))
+ ("2 Feb 2021 1996" nil
+ ("Expected a time" 1996))
+ ("22 Fub 1996" nil
+ ("Expected an alphabetic month" "fub"))
+ ("1 Jan 2020 30" nil
+ ("Expected a time" 30))
+ ("1 Jan 2020 16:47 15:15" nil
+ ("Expected a timezone" "15:15"))
+ ("1 Jan 2020 16:47 +0800 -0800" t
+ ("Extra token(s)" "-0800"))
+ ;; Range tests
+ ("32 Dec 2021" nil
+ ("Slot out of range" day 32 1 31))
+ ("0 Dec 2021" nil
+ ("Slot out of range" day 0 1 31))
+ ("3 13 2021" nil
+ ("Expected an alphabetic month" 13))
+ ("3 Dec 0000" t
+ ("Four-digit years are required" 0))
+ ("3 Dec 20021" nil
+ ("Slot out of range" year 20021 1 9999))
+ ("1 Jan 2020 24:21:14" nil
+ ("Slot out of range" hour "24:21:14" 0 23))
+ ("1 Jan 2020 14:60:21" nil
+ ("Slot out of range" minute "14:60:21" 0 59))
+ ("1 Jan 2020 14:21:61" nil
+ ("Slot out of range" second "14:21:61" 0 60))))
+ (should (equal (should-error
+ (ietf-drums-parse-date-string (car test) t (cadr test)))
+ (cons 'date-parse-error (caddr test)))))
+ (should (equal (ietf-drums-parse-date-string
+ "1 Jan 2020 14:21:60") ;; a leap second!
+ '(60 21 14 1 1 2020 nil -1 nil))))
+
+(provide 'ietf-drums-date-tests)
+
+;;; ietf-drums-date-tests.el ends here
diff --git a/test/lisp/mail/ietf-drums-tests.el b/test/lisp/mail/ietf-drums-tests.el
new file mode 100644
index 00000000000..b13937bf736
--- /dev/null
+++ b/test/lisp/mail/ietf-drums-tests.el
@@ -0,0 +1,178 @@
+;;; ietf-drums-tests.el --- Test suite for ietf-drums.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Bob Rogers <rogers@rgrjr.com>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'ietf-drums)
+
+(ert-deftest ietf-drums-tests ()
+ "Test ietf-drums functionality."
+
+ ;; ietf-drums-remove-comments
+ (should (equal (ietf-drums-remove-comments "random string") "random string"))
+ (should (equal (ietf-drums-remove-comments "random \"non comment\" string")
+ "random \"non comment\" string"))
+ (should (equal (ietf-drums-remove-comments "random (comment) string")
+ "random string"))
+ (should (equal (ietf-drums-remove-comments "random (comment) (string)")
+ "random "))
+ (should (equal (ietf-drums-remove-comments
+ "random (first) (second (and)) (third) not fourth")
+ "random not fourth"))
+ ;; Test some unterminated comments.
+ (should (equal (ietf-drums-remove-comments "test an (unterminated comment")
+ "test an "))
+ (should (equal (ietf-drums-remove-comments "test an \"unterminated quote")
+ ;; returns the string unchanged (and doesn't barf).
+ "test an \"unterminated quote"))
+ (should (equal (ietf-drums-remove-comments
+ ;; note that double-quote is not special.
+ "test (unterminated comments with \"quoted (\" )stuff")
+ "test "))
+
+ ;; ietf-drums-remove-whitespace
+ (should (equal (ietf-drums-remove-whitespace "random string")
+ "randomstring"))
+ (should (equal (ietf-drums-remove-whitespace "random (comment) string")
+ "random(comment)string"))
+ (should (equal (ietf-drums-remove-whitespace "random \"non comment\" string")
+ "random\"non comment\"string"))
+ (should (equal (ietf-drums-remove-whitespace "random (comment)\r\n(string)")
+ "random(comment)(string)"))
+ (should (equal (ietf-drums-remove-whitespace
+ "random (first) (second (and)) (third) not fourth")
+ "random(first)(second (and))(third)notfourth"))
+ ;; Test some unterminated comments and quotes.
+ (should (equal (ietf-drums-remove-whitespace
+ "random (first) (second (and)) (third unterminated")
+ "random(first)(second (and))(third unterminated"))
+ (should (equal (ietf-drums-remove-whitespace "random \"non terminated string")
+ "random\"non terminated string"))
+
+ ;; ietf-drums-strip
+ (should (equal (ietf-drums-strip "random string") "randomstring"))
+ (should (equal (ietf-drums-strip "random \"non comment\" string")
+ "random\"non comment\"string"))
+ (should (equal (ietf-drums-strip "random (comment) string")
+ "randomstring"))
+ (should (equal (ietf-drums-strip "random (comment) (string)")
+ "random"))
+ (should (equal (ietf-drums-strip
+ "random (first) (second (and)) (third) not fourth")
+ "randomnotfourth"))
+
+ ;; ietf-drums-strip-cte
+ (should (equal (ietf-drums-strip-cte "random \"non comment\" string")
+ ;; [the " " is still in there because it was quoted
+ ;; through the "strip". -- rgr, 5-Feb-22.]
+ "randomnon commentstring"))
+ (should (equal (ietf-drums-strip-cte "ran(d)do<m@>[s;t:r],,in=g")
+ "randomstring"))
+
+ ;; ietf-drums-quote-string
+ (should (equal (ietf-drums-quote-string "Bob") "Bob"))
+ (should (equal (ietf-drums-quote-string "Foo Bar") "\"Foo Bar\""))
+
+ ;; ietf-drums-get-comment
+ (should (equal (ietf-drums-get-comment "random string") nil))
+ (should (equal (ietf-drums-get-comment "random (comment) string") "comment"))
+ (should (equal (ietf-drums-get-comment "random \"non comment\" string") nil))
+ (should (equal (ietf-drums-get-comment "\"still (non) comment\" string")
+ nil))
+ (should (equal (ietf-drums-get-comment "random (comment)\r\nstring")
+ "comment"))
+ (should (equal (ietf-drums-get-comment "random (comment) (string)") "string"))
+ (should (equal (ietf-drums-get-comment
+ "random (first) (second (and)) (third) not fourth")
+ "third"))
+
+ ;; ietf-drums-make-address
+ (should (equal (ietf-drums-make-address "Bob Rogers" "rogers@rgrjr.com")
+ "\"Bob Rogers\" <rogers@rgrjr.com>"))
+ (should (equal (ietf-drums-make-address nil "rogers@rgrjr.com")
+ "rogers@rgrjr.com"))
+
+ ;; ietf-drums-parse-address
+ (should (equal (ietf-drums-parse-address "foo@example.com")
+ '("foo@example.com")))
+ (should (equal (ietf-drums-parse-address "<foo@example.com>")
+ '("foo@example.com")))
+ (should (equal (ietf-drums-parse-address "'foo' <foo@example.com>")
+ '("foo@example.com" . "'foo'")))
+ (should (equal (ietf-drums-parse-address "foo <foo@example.com>")
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "foo <foo@example.com> bar")
+ ;; [contrary to RFC2822, which wants the display-name
+ ;; before the address. -- rgr, 5-Feb-22.]
+ '("foo@example.com" . "foo bar")))
+ (should (equal (ietf-drums-parse-address " <foo@example.com> foo ")
+ ;; [ditto. -- rgr, 5-Feb-22.]
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "foo@example.com (foo)")
+ '("foo@example.com" . "foo")))
+ (should (equal (ietf-drums-parse-address "Bar Baz <barbaz@example.com>")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address "barbaz@example.com (Bar Baz)")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address
+ "Bar Baz (ignored) <barbaz@example.com>")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address "<barbaz@example.com> Bar Baz")
+ '("barbaz@example.com" . "Bar Baz")))
+ (should (equal (ietf-drums-parse-address
+ "(Bar Baz not ignored) barbaz@example.com")
+ ;; [not strictly RFC2822, which expects the name
+ ;; comment after the address. -- rgr, 5-Feb-22.]
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ (should (equal (ietf-drums-parse-address
+ "(ignored) <barbaz@example.com> (Bar Baz not ignored)")
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ (should (equal (ietf-drums-parse-address
+ "(ignored) barbaz@example.com (Bar Baz not ignored)")
+ '("barbaz@example.com" . "Bar Baz not ignored")))
+ ;; Test for RFC2047 token decoding.
+ (should (equal (ietf-drums-parse-address
+ "=?utf-8?B?0JfQtNGA0LDMgdCy0YHRgtCy0YPQudGC0LUh?= <foo@goo.ru>"
+ t)
+ '("foo@goo.ru" . "Здра́вствуйте!")))
+
+ ;; ietf-drums-parse-addresses
+ ;; Note that it's not worth getting too elaborate here, as the heavy
+ ;; lifting is all done by ietf-drums-parse-address.
+ (should (equal (ietf-drums-parse-addresses "foo@example.com")
+ '(("foo@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, bar@example.com")
+ '(("foo@example.com") ("bar@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, quux, bar@example.com")
+ '(("foo@example.com") ("bar@example.com"))))
+ (should (equal (ietf-drums-parse-addresses
+ "foo@example.com, Quux Dude <quux@noop.org>, bar@example.com")
+ '(("foo@example.com") ("quux@noop.org" . "Quux Dude")
+ ("bar@example.com")))))
+
+(provide 'ietf-drums-tests)
+
+;;; ietf-drums-tests.el ends here
diff --git a/test/lisp/mail/mail-extr-tests.el b/test/lisp/mail/mail-extr-tests.el
new file mode 100644
index 00000000000..a8f0c605cb0
--- /dev/null
+++ b/test/lisp/mail/mail-extr-tests.el
@@ -0,0 +1,41 @@
+;;; mail-extr-tests.el --- Tests for mail-extr.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'mail-extr)
+
+(defconst mail-extract-test-cases
+ '(("foo@example.org" . (nil "foo@example.org"))
+ ("J. Random Hacker <foo@example.org>" . ("J. Random Hacker" "foo@example.org"))
+ ("\"J. Random Hacker\" <foo@example.org>" . ("J. Random Hacker" "foo@example.org"))
+ ("Ååå Äää <foo@example.org>" . ("Ååå Äää" "foo@example.org"))))
+
+(ert-deftest mail-extract-address-components ()
+ (dolist (test mail-extract-test-cases)
+ (should (equal (mail-extract-address-components (car test)) (cdr test)))))
+
+(ert-deftest what-domain ()
+ (should (equal (what-domain "cu") "CU: Cuba")))
+
+(provide 'mail-extr-tests)
+;;; mail-extr-tests.el ends here
diff --git a/test/lisp/mail/undigest-tests.el b/test/lisp/mail/undigest-tests.el
new file mode 100644
index 00000000000..d52c9f9c5ab
--- /dev/null
+++ b/test/lisp/mail/undigest-tests.el
@@ -0,0 +1,359 @@
+;;; undigest-tests.el --- Tests for undigest.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'rmail)
+(require 'undigest)
+
+;;; Variables:
+;; Some digests for testing.
+(defvar rmail-rfc934-digest "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Testing the undigester.
+
+------- Message sep
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+This is message one.
+
+------- Message sep
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+This is message two.
+"
+
+ "RFC 934 digest.")
+
+(defvar rmail-rfc1153-digest-strict "From tester Fri Jan 24 00:00:00 2022
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+End of Digest.
+************************************
+"
+ "RFC 1153 strict style digest.")
+
+(defvar rmail-rfc1153-digest-less-strict "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+Subject: Digest Footer
+
+End of Sbcl-help Digest, Vol 158, Issue 4
+*****************************************
+"
+ "RFC 1153 style digest, with a Subject header.")
+
+(defvar rmail-rfc1153-digest-sloppy "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Testing you
+
+Some mailing list information.
+
+Today's Topics:
+
+ 1. Message One Subject (Sender)
+ 2. Message Two Subject (Sender)
+
+----------------------------------------------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN1 <nn1@nn1.com>
+Subject: Message One Subject
+
+This is message one.
+
+------------------------------
+
+Date: ddd, dd mmm yy hh:mm:ss zzz
+From: NN2 <nn2@nn2.com>
+Subject: Message Two Subject
+
+This is message two.
+
+------------------------------
+
+Subject: Digest Footer
+
+______________________________________________
+Some blurb.
+
+End of Digest.
+************************************
+"
+ "RFC 1153 sloppy style digest.")
+
+(defvar rmail-rfc1521-mime-digest "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Test digest
+MIME-Version: 1.0
+Content-Type: multipart/digest; boundary=\"----- =_aaaaaaaaaa0\"
+
+------- =_aaaaaaaaaa0
+Content-Type: message/rfc822
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+Message one.
+
+------- =_aaaaaaaaaa0
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+Message two.
+
+------- =_aaaaaaaaaa0
+"
+ "RFC 1521 style MIME digest.")
+
+(defvar rmail-multipart-mixed-digest
+ "From tester Fri Jan 24 00:00:00 2022
+From: Digester <digester@digester.com>
+To: Undigester <undigester@undigester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Test digest
+Content-Type: multipart/mixed; boundary=\"===============2529375068597856000==\"
+MIME-Version: 1.0
+
+--===============2529375068597856000==
+Content-Type: text/plain;
+MIME-Version: 1.0
+Content-Description: Today's Topics
+
+Some message.
+
+--===============2529375068597856000==
+Content-Type: multipart/digest; boundary=\"===============6060050777038710134==\"
+MIME-Version: 1.0
+
+--===============6060050777038710134==
+Content-Type: message/rfc822
+MIME-Version: 1.0
+
+From: NN1 <nn1@nn1.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message one
+
+Message one.
+
+--===============6060050777038710134==
+Content-Type: message/rfc822
+MIME-Version: 1.0
+
+From: NN2 <nn2@nn2.com>
+To: Digester <digester@digester.com>
+Date: ddd, dd mmm yy hh:mm:ss zzz
+Subject: Message two
+
+Message two.
+
+--===============6060050777038710134==--
+
+--===============2529375068597856000==
+Content-Type: text/plain;
+MIME-Version: 1.0
+Content-Description: Digest Footer
+
+The footer.
+
+--===============2529375068597856000==--"
+ "RFC 1521 digest inside a multipart/mixed message.")
+
+;;; Utils:
+(defun rmail-message-content (message)
+ "Return the content of the message numbered MESSAGE."
+ (rmail-show-message message)
+ (let ((beg (rmail-msgbeg rmail-current-message))
+ (end (rmail-msgend rmail-current-message)))
+ (with-current-buffer rmail-view-buffer
+ (save-excursion
+ (goto-char beg)
+ (search-forward "\n\n" end nil)
+ (buffer-substring-no-properties (match-end 0) end)))))
+
+;;; Tests:
+(ert-deftest rmail-undigest-test-rfc934-digest ()
+ "Test that we can undigest a RFC 934 digest."
+ (ert-with-temp-file file
+ :text rmail-rfc934-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 4))
+ (should (string= (rmail-message-content 2) "Testing the undigester.\n\n"))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n"))))
+
+(ert-deftest rmail-undigest-test-rfc1153-digest-strict ()
+ "Test that we can undigest a strict RFC 1153 digest."
+ :expected-result :failed
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-strict
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (should
+ (ignore-errors
+ ;; This throws an error, because the Trailer is not recognized
+ ;; as a valid RFC 822 (or later) message.
+ (undigestify-rmail-message)
+ (should (string= (rmail-message-content 2) "Testing the undigester.\n\n"))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n"))
+ t))))
+
+(ert-deftest rmail-undigest-test-rfc1153-less-strict-digest ()
+ "Test that we can undigest a RFC 1153 with a Subject header in its footer."
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-less-strict
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 5))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n\n"))))
+
+(ert-deftest rmail-undigest-test-rfc1153-sloppy-digest ()
+ "Test that we can undigest a sloppy RFC 1153 digest."
+ (ert-with-temp-file file
+ :text rmail-rfc1153-digest-sloppy
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 5))
+ (should (string= (rmail-message-content 3) "This is message one.\n\n"))
+ (should (string= (rmail-message-content 4) "This is message two.\n\n"))))
+
+;; This fails because `rmail-digest-parse-mime' combines the preamble with the
+;; first message of the digest. And then, it doesn't get rid of the last
+;; separator.
+(ert-deftest rmail-undigest-test-rfc1521-mime-digest ()
+ "Test that we can undigest a RFC 1521 MIME digest."
+ :expected-result :failed
+ (ert-with-temp-file file
+ :text rmail-rfc1521-mime-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 3))
+ (should (string= (rmail-message-content 2) "Message one.\n\n"))
+ (should (string= (rmail-message-content 3) "Message two.\n\n"))))
+
+(ert-deftest rmail-undigest-test-multipart-mixed-digest ()
+ "Test that we can undigest a digest inside a multipart/mixed digest."
+ (ert-with-temp-file file
+ :text rmail-multipart-mixed-digest
+ ;; Rmail reads mbox files literally, so we must make sure the
+ ;; temporary mbox file has Unix-style EOLs.
+ :coding 'undecided-unix
+ (rmail file)
+ (undigestify-rmail-message)
+ (should (= rmail-total-messages 4))
+ (should (string= (rmail-message-content 2) "Message one.\n\n"))
+ (should (string= (rmail-message-content 3) "Message two.\n\n"))))
diff --git a/test/lisp/mh-e/mh-thread-tests.el b/test/lisp/mh-e/mh-thread-tests.el
index 84f59e5d300..ea8d441e2d1 100644
--- a/test/lisp/mh-e/mh-thread-tests.el
+++ b/test/lisp/mh-e/mh-thread-tests.el
@@ -24,7 +24,7 @@
(eval-when-compile (require 'cl-lib))
(defun mh-thread-tests-before-from ()
- "Generate the fields of a scan line up to where the 'From' field would start.
+ "Generate the fields of a scan line up to where the \"From\" field would start.
The exact contents are not important, but the number of characters is."
(concat (make-string mh-cmd-note ?9)
(make-string mh-scan-cmd-note-width ?A)
diff --git a/test/lisp/mh-e/mh-utils-tests.el b/test/lisp/mh-e/mh-utils-tests.el
index 07086172595..72ee2fc4745 100644
--- a/test/lisp/mh-e/mh-utils-tests.el
+++ b/test/lisp/mh-e/mh-utils-tests.el
@@ -48,8 +48,10 @@
;;; Code:
(require 'ert)
-(eval-when-compile (require 'cl-lib))
(require 'mh-utils)
+(eval-when-compile
+ (require 'cl-lib)
+ (require 'subr-x))
(ert-deftest mh-quote-pick-expr ()
"Test `mh-quote-pick-expr'."
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 2a29d5f167b..ec93c8f42a5 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -331,5 +331,141 @@
"custgroup" '("customize-group-other-window") nil 9)))
15)))
+
+(defmacro completing-read-with-minibuffer-setup (collection &rest body)
+ (declare (indent 1) (debug (collection body)))
+ `(catch 'result
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (let ((redisplay-skip-initial-frame nil)
+ (executing-kbd-macro nil)) ; Don't skip redisplay
+ (throw 'result (progn . ,body))))
+ (let ((executing-kbd-macro t)) ; Force the real minibuffer
+ (completing-read "Prompt: " ,collection)))))
+
+(ert-deftest completion-auto-help-test ()
+ (let (messages)
+ (cl-letf* (((symbol-function 'minibuffer-message)
+ (lambda (message &rest args)
+ (push (apply #'format-message message args) messages))))
+ (let ((completion-auto-help nil))
+ (completing-read-with-minibuffer-setup
+ '("a" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB TAB"))
+ (should (equal (car messages) "Complete, but not unique"))
+ (should-not (get-buffer-window "*Completions*" 0))))
+ (let ((completion-auto-help t))
+ (completing-read-with-minibuffer-setup
+ '("a" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB TAB"))
+ (should (get-buffer-window "*Completions*" 0)))))))
+
+(ert-deftest completion-auto-select-test ()
+ (let ((completion-auto-select t))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer "*Completions*"))))
+ (execute-kbd-macro (kbd "TAB TAB TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer " *Minibuf-1*"))))
+ (execute-kbd-macro (kbd "S-TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (eq (current-buffer) (get-buffer "*Completions*"))))))
+ (let ((completion-auto-select 'second-tab))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (execute-kbd-macro (kbd "a TAB"))
+ (should (and (get-buffer-window "*Completions*" 0)
+ (not (eq (current-buffer) (get-buffer "*Completions*")))))
+ (execute-kbd-macro (kbd "TAB TAB"))
+ (should (eq (current-buffer) (get-buffer "*Completions*"))))))
+
+(ert-deftest completion-auto-wrap-test ()
+ (let ((completion-auto-wrap nil))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (next-completion 5)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-completion 5)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))))
+ (let ((completion-auto-wrap t))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (previous-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string))))))
+
+(ert-deftest completions-header-format-test ()
+ (let ((completion-show-help nil)
+ (completions-header-format nil))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ ;; Fixed in bug#55430
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-completion 2)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (previous-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#55430
+ (execute-kbd-macro (kbd "C-u RET"))
+ (should (equal (minibuffer-contents) "aa")))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ ;; Fixed in bug#55289
+ (execute-kbd-macro (kbd "a M-<up> M-<down>"))
+ (should (equal (minibuffer-contents) "aa")))))
+
+(ert-deftest completions-affixation-navigation-test ()
+ (let ((completion-extra-properties
+ '(:affixation-function
+ (lambda (completions)
+ (mapcar (lambda (c)
+ (list c "prefix " " suffix"))
+ completions)))))
+ (completing-read-with-minibuffer-setup
+ '("aa" "ab" "ac")
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap t))
+ (next-completion 3))
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap nil))
+ (next-completion 3))
+ (should (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ ;; Fixed in bug#54374
+ (goto-char (1- (point-max)))
+ (should-not (equal 'highlight (get-text-property (point) 'mouse-face)))
+ (execute-kbd-macro (kbd "C-u RET"))
+ (should (equal (minibuffer-contents) "ac")))))
+
(provide 'minibuffer-tests)
;;; minibuffer-tests.el ends here
diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el
index 36a8726b885..a56feaa0495 100644
--- a/test/lisp/misc-tests.el
+++ b/test/lisp/misc-tests.el
@@ -44,7 +44,14 @@
(zap-up-to-char 1 ?c))
(with-misc-test "abcde abc123" "c123"
(goto-char (point-min))
- (zap-up-to-char 2 ?c)))
+ (zap-up-to-char 2 ?c))
+ (let ((case-fold-search t))
+ (with-misc-test "abcdeCXYZ" "cdeCXYZ"
+ (goto-char (point-min))
+ (zap-up-to-char 1 ?C))
+ (with-misc-test "abcdeCXYZ" "CXYZ"
+ (goto-char (point-min))
+ (zap-up-to-char 1 ?C 'interactive))))
(ert-deftest misc-test-upcase-char ()
(with-misc-test "abcde" "aBCDe"
@@ -73,5 +80,21 @@
(backward-to-word 3)
(should (equal (point) 1))))
+(ert-deftest misc--duplicate-line ()
+ ;; Duplicate a line (twice).
+ (with-temp-buffer
+ (insert "abc\ndefg\nh\n")
+ (goto-char 7)
+ (duplicate-line 2)
+ (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n"))
+ (should (equal (point) 7)))
+ ;; Duplicate a non-terminated line.
+ (with-temp-buffer
+ (insert "abc")
+ (goto-char 2)
+ (duplicate-line)
+ (should (equal (buffer-string) "abc\nabc\n"))
+ (should (equal (point) 2))))
+
(provide 'misc-tests)
;;; misc-tests.el ends here
diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el
index 1be32006a10..03ecbc19858 100644
--- a/test/lisp/mouse-tests.el
+++ b/test/lisp/mouse-tests.el
@@ -25,6 +25,20 @@
;;; Code:
+(ert-deftest mouse-test-mouse-double-click-time ()
+ (let ((double-click-time 500))
+ (should (= (mouse-double-click-time) 500)))
+ (let ((double-click-time 0))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time -500))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time nil))
+ (should (= (mouse-double-click-time) 0)))
+ (let ((double-click-time t))
+ (should (numberp (mouse-double-click-time))))
+ (let ((double-click-time '(invalid)))
+ (should (= (mouse-double-click-time) 0))))
+
(ert-deftest bug23288-use-return-value ()
"If `mouse-on-link-p' returns a string, its first character is used."
(cl-letf ((unread-command-events '((down-mouse-1 nil 1) (mouse-1 nil 1)))
diff --git a/test/lisp/net/browse-url-tests.el b/test/lisp/net/browse-url-tests.el
index 8f180f3d6bb..1c993958b81 100644
--- a/test/lisp/net/browse-url-tests.el
+++ b/test/lisp/net/browse-url-tests.el
@@ -31,7 +31,7 @@
(require 'ert-x)
(ert-deftest browse-url-tests-browser-kind ()
- (should (eq (browse-url--browser-kind #'browse-url-w3 "gnu.org")
+ (should (eq (browse-url--browser-kind #'browse-url-emacs "gnu.org")
'internal))
(should
(eq (browse-url--browser-kind #'browse-url-firefox "gnu.org")
@@ -73,7 +73,7 @@
(should (equal (browse-url-encode-url "\"a\" \"b\"")
"%22a%22%20%22b%22"))
(should (equal (browse-url-encode-url "(a) (b)") "%28a%29%20%28b%29"))
- (should (equal (browse-url-encode-url "a$ b$") "a%24%20b%24")))
+ (should (equal (browse-url-encode-url "a$ b$") "a$%20b$")))
(ert-deftest browse-url-tests-url-at-point ()
(with-temp-buffer
@@ -82,10 +82,13 @@
(ert-deftest browse-url-tests-file-url ()
(should (equal (browse-url-file-url "/foo") "file:///foo"))
- (should (equal (browse-url-file-url "/foo:") "ftp://foo/"))
- (should (equal (browse-url-file-url "/ftp@foo:") "ftp://foo/"))
- (should (equal (browse-url-file-url "/anonymous@foo:")
- "ftp://foo/")))
+ (when (file-remote-p "/foo:")
+ (should (equal (browse-url-file-url "/foo:") "ftp://foo/")))
+ (when (file-remote-p "/ftp@foo:")
+ (should (equal (browse-url-file-url "/ftp@foo:") "ftp://foo/")))
+ (when (file-remote-p "/anonymous@foo:")
+ (should (equal (browse-url-file-url "/anonymous@foo:")
+ "ftp://foo/"))))
(ert-deftest browse-url-tests-delete-temp-file ()
(ert-with-temp-file browse-url-temp-file-name
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..188706fc86a 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
+ (with-environment-variables (("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
diff --git a/test/lisp/net/ntlm-tests.el b/test/lisp/net/ntlm-tests.el
index f7407032323..a02d97f19a8 100644
--- a/test/lisp/net/ntlm-tests.el
+++ b/test/lisp/net/ntlm-tests.el
@@ -234,8 +234,13 @@ This string will be returned from the NTLM server to the NTLM client."
(declare-function ws-start nil)
(declare-function ws-stop-all nil)
-(require 'web-server nil t)
-(require 'url-http-ntlm nil t)
+(eval-and-compile
+ (push (expand-file-name "../elpa/packages/web-server/" source-directory)
+ load-path)
+ (require 'web-server nil t)
+ (push (expand-file-name "../elpa/packages/url-http-ntlm/" source-directory)
+ load-path)
+ (require 'url-http-ntlm nil t))
(defun ntlm-server-do-token (request _process)
"Process an NTLM client's REQUEST.
diff --git a/test/lisp/net/puny-resources/IdnaTestV2.txt b/test/lisp/net/puny-resources/IdnaTestV2.txt
new file mode 100644
index 00000000000..ed2f32e129f
--- /dev/null
+++ b/test/lisp/net/puny-resources/IdnaTestV2.txt
@@ -0,0 +1,6344 @@
+# IdnaTestV2.txt
+# Date: 2021-08-17, 19:34:01 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 IDNA Compatible Preprocessing for UTS #46
+# Version: 14.0.0
+#
+# For documentation and usage, see http://www.unicode.org/reports/tr46
+#
+# Test cases for verifying UTS #46 conformance.
+#
+# FORMAT:
+#
+# This file is in UTF-8, where characters may be escaped using the \uXXXX or \x{XXXX}
+# convention where they could otherwise have a confusing display.
+# These characters include control codes and combining marks.
+#
+# Columns (c1, c2,...) are separated by semicolons.
+# Leading and trailing spaces and tabs in each column are ignored.
+# Comments are indicated with hash marks.
+#
+# Column 1: source - The source string to be tested
+# Column 2: toUnicode - The result of applying toUnicode to the source,
+# with Transitional_Processing=false.
+# A blank value means the same as the source value.
+# Column 3: toUnicodeStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means [] (no errors).
+# Column 4: toAsciiN - The result of applying toASCII to the source,
+# with Transitional_Processing=false.
+# A blank value means the same as the toUnicode value.
+# Column 5: toAsciiNStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means the same as the toUnicodeStatus value.
+# An explicit [] means no errors.
+# Column 6: toAsciiT - The result of applying toASCII to the source,
+# with Transitional_Processing=true.
+# A blank value means the same as the toAsciiN value.
+# Column 7: toAsciiTStatus - A set of status codes, each corresponding to a particular test.
+# A blank value means the same as the toAsciiNStatus value.
+# An explicit [] means no errors.
+#
+# The line comments currently show visible characters that have been escaped.
+#
+# CONFORMANCE:
+#
+# To test for conformance to UTS #46, an implementation will perform the toUnicode, toAsciiN, and
+# toAsciiT operations on the source string, then verify the resulting strings and relevant status
+# values.
+#
+# If the implementation converts illegal code points into U+FFFD (as per
+# https://www.unicode.org/reports/tr46/#Processing) then the string comparisons need to
+# account for that by treating U+FFFD in the actual value as a wildcard when comparing to the
+# expected value in the test file.
+#
+# A status in toUnicode, toAsciiN or toAsciiT is indicated by a value in square brackets,
+# such as "[B5 B6]". In such a case, the contents is a list of status codes based on the step
+# numbers in UTS #46 and IDNA2008, with the following formats.
+#
+# Pn for Section 4 Processing step n
+# Vn for 4.1 Validity Criteria step n
+# U1 for UseSTD3ASCIIRules
+# An for 4.2 ToASCII step n
+# Bn for Bidi (in IDNA2008)
+# Cn for ContextJ (in IDNA2008)
+# Xn for toUnicode issues (see below)
+#
+# Thus C1 = Appendix A.1. ZERO WIDTH NON-JOINER, and C2 = Appendix A.2. ZERO WIDTH JOINER.
+# (The CONTEXTO tests are optional for client software, and not tested here.)
+#
+# Implementations that allow values of particular input flags to be false would ignore
+# the corresponding status codes listed in the table below when testing for errors.
+#
+# VerifyDnsLength: P4
+# CheckHyphens: V2, V3
+# CheckBidi: V8
+# CheckJoiners: V7
+# UseSTD3ASCIIRules: U1
+#
+# Implementations may be more strict than the default settings for UTS #46.
+# In particular, an implementation conformant to IDNA2008 would disallow the input for lines
+# marked with NV8.
+#
+# Implementations need only record that there is an error: they need not reproduce the
+# precise status codes (after removing the ignored status values).
+#
+# Compatibility errors
+#
+# The special error codes X3 and X4_2 are now returned where a toASCII error code
+# was formerly being generated in toUnicode due to an empty label.
+#
+# A3 was being generated in the following cases (in addition to its normal usage).
+# • an empty label in toUnicode. In this case, it is replaced by X3.
+#
+# A4_2 was being generated in the following case (in addition to its normal usage).
+# • an empty label in V8 (CheckBidi). In this case, it is being replaced by X4_2.
+# ============================================================================================
+fass.de; ; ; ; ; ; # fass.de
+faß.de; ; ; xn--fa-hia.de; ; fass.de; # faß.de
+Faß.de; faß.de; ; xn--fa-hia.de; ; fass.de; # faß.de
+xn--fa-hia.de; faß.de; ; xn--fa-hia.de; ; ; # faß.de
+
+# BIDI TESTS
+
+àא; ; [B5, B6]; xn--0ca24w; ; ; # àא
+àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+Àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+Àא; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+xn--0ca24w; àא; [B5, B6]; xn--0ca24w; ; ; # àא
+0à.א; ; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0à.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0À.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+0À.א; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+xn--0-sfa.xn--4db; 0à.א; [B1]; xn--0-sfa.xn--4db; ; ; # 0à.א
+à.א̈; ; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+à.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+À.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+À.א̈; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+xn--0ca.xn--ssa73l; à.א̈; ; xn--0ca.xn--ssa73l; ; ; # à.א̈
+à.א0٠א; ; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+à.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+À.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+À.א0٠א; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+xn--0ca.xn--0-zhcb98c; à.א0٠א; [B4]; xn--0ca.xn--0-zhcb98c; ; ; # à.א0٠א
+̈.א; ; [B1, B3, B6, V5]; xn--ssa.xn--4db; ; ; # ̈.א
+xn--ssa.xn--4db; ̈.א; [B1, B3, B6, V5]; xn--ssa.xn--4db; ; ; # ̈.א
+à.א0٠; ; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+à.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+À.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+À.א0٠; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+xn--0ca.xn--0-zhc74b; à.א0٠; [B4]; xn--0ca.xn--0-zhc74b; ; ; # à.א0٠
+àˇ.א; ; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+Àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+Àˇ.א; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+xn--0ca88g.xn--4db; àˇ.א; [B6]; xn--0ca88g.xn--4db; ; ; # àˇ.א
+à̈.א; ; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+à̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+À̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+À̈.א; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+xn--0ca81i.xn--4db; à̈.א; ; xn--0ca81i.xn--4db; ; ; # à̈.א
+
+# CONTEXT TESTS
+
+a‌b; ; [C1]; xn--ab-j1t; ; ab; [] # ab
+A‌B; a‌b; [C1]; xn--ab-j1t; ; ab; [] # ab
+A‌b; a‌b; [C1]; xn--ab-j1t; ; ab; [] # ab
+ab; ; ; ; ; ; # ab
+xn--ab-j1t; a‌b; [C1]; xn--ab-j1t; ; ; # ab
+a्‌b; ; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+A्‌B; a्‌b; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+A्‌b; a्‌b; ; xn--ab-fsf604u; ; xn--ab-fsf; # a्b
+xn--ab-fsf; a्b; ; xn--ab-fsf; ; ; # a्b
+a्b; ; ; xn--ab-fsf; ; ; # a्b
+A्B; a्b; ; xn--ab-fsf; ; ; # a्b
+A्b; a्b; ; xn--ab-fsf; ; ; # a्b
+xn--ab-fsf604u; a्‌b; ; xn--ab-fsf604u; ; ; # a्b
+̈‌̈بb; ; [B1, C1, V5]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+̈‌̈بB; ̈‌̈بb; [B1, C1, V5]; xn--b-bcba413a2w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+xn--b-bcba413a; ̈̈بb; [B1, V5]; xn--b-bcba413a; ; ; # ̈̈بb
+xn--b-bcba413a2w8b; ̈‌̈بb; [B1, C1, V5]; xn--b-bcba413a2w8b; ; ; # ̈̈بb
+aب̈‌̈; ; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+Aب̈‌̈; aب̈‌̈; [B5, B6, C1]; xn--a-ccba213a5w8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+xn--a-ccba213a; aب̈̈; [B5, B6]; xn--a-ccba213a; ; ; # aب̈̈
+xn--a-ccba213a5w8b; aب̈‌̈; [B5, B6, C1]; xn--a-ccba213a5w8b; ; ; # aب̈̈
+aب̈‌̈بb; ; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+Aب̈‌̈بB; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+Aب̈‌̈بb; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; xn--ab-uuba211bca; # aب̈̈بb
+xn--ab-uuba211bca; aب̈̈بb; [B5]; xn--ab-uuba211bca; ; ; # aب̈̈بb
+xn--ab-uuba211bca8057b; aب̈‌̈بb; [B5]; xn--ab-uuba211bca8057b; ; ; # aب̈̈بb
+a‍b; ; [C2]; xn--ab-m1t; ; ab; [] # ab
+A‍B; a‍b; [C2]; xn--ab-m1t; ; ab; [] # ab
+A‍b; a‍b; [C2]; xn--ab-m1t; ; ab; [] # ab
+xn--ab-m1t; a‍b; [C2]; xn--ab-m1t; ; ; # ab
+a्‍b; ; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+A्‍B; a्‍b; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+A्‍b; a्‍b; ; xn--ab-fsf014u; ; xn--ab-fsf; # a्b
+xn--ab-fsf014u; a्‍b; ; xn--ab-fsf014u; ; ; # a्b
+̈‍̈بb; ; [B1, C2, V5]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+̈‍̈بB; ̈‍̈بb; [B1, C2, V5]; xn--b-bcba413a7w8b; ; xn--b-bcba413a; [B1, V5] # ̈̈بb
+xn--b-bcba413a7w8b; ̈‍̈بb; [B1, C2, V5]; xn--b-bcba413a7w8b; ; ; # ̈̈بb
+aب̈‍̈; ; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+Aب̈‍̈; aب̈‍̈; [B5, B6, C2]; xn--a-ccba213abx8b; ; xn--a-ccba213a; [B5, B6] # aب̈̈
+xn--a-ccba213abx8b; aب̈‍̈; [B5, B6, C2]; xn--a-ccba213abx8b; ; ; # aب̈̈
+aب̈‍̈بb; ; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+Aب̈‍̈بB; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+Aب̈‍̈بb; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; xn--ab-uuba211bca; [B5] # aب̈̈بb
+xn--ab-uuba211bca5157b; aب̈‍̈بb; [B5, C2]; xn--ab-uuba211bca5157b; ; ; # aب̈̈بb
+
+# SELECTED TESTS
+
+¡; ; ; xn--7a; ; ; # ¡
+xn--7a; ¡; ; xn--7a; ; ; # ¡
+᧚; ; ; xn--pkf; ; ; # ᧚
+xn--pkf; ᧚; ; xn--pkf; ; ; # ᧚
+。; .; [X4_2]; ; [A4_2]; ; # .
+.; ; [X4_2]; ; [A4_2]; ; # .
+ꭠ; ; ; xn--3y9a; ; ; # ꭠ
+xn--3y9a; ꭠ; ; xn--3y9a; ; ; # ꭠ
+1234567890ä1234567890123456789012345678901234567890123456; ; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890Ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+1234567890Ä1234567890123456789012345678901234567890123456; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+xn--12345678901234567890123456789012345678901234567890123456-fxe; 1234567890ä1234567890123456789012345678901234567890123456; ; xn--12345678901234567890123456789012345678901234567890123456-fxe; [A4_2]; ; # 1234567890ä1234567890123456789012345678901234567890123456
+www.eXample.cOm; www.example.com; ; ; ; ; # www.example.com
+Bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+Bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+bücher.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+bücher.de; ; ; xn--bcher-kva.de; ; ; # bücher.de
+BÜCHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+BÜCHER.DE; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+xn--bcher-kva.de; bücher.de; ; xn--bcher-kva.de; ; ; # bücher.de
+ÖBB; öbb; ; xn--bb-eka; ; ; # öbb
+ÖBB; öbb; ; xn--bb-eka; ; ; # öbb
+öbb; öbb; ; xn--bb-eka; ; ; # öbb
+öbb; ; ; xn--bb-eka; ; ; # öbb
+Öbb; öbb; ; xn--bb-eka; ; ; # öbb
+Öbb; öbb; ; xn--bb-eka; ; ; # öbb
+xn--bb-eka; öbb; ; xn--bb-eka; ; ; # öbb
+βόλος.com; ; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+ΒΌΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+ΒΌΛΟΣ.COM; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+βόλοσ.com; ; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλοσ.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+xn--nxasmq6b.com; βόλοσ.com; ; xn--nxasmq6b.com; ; ; # βόλοσ.com
+Βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+Βόλος.com; βόλος.com; ; xn--nxasmm1c.com; ; xn--nxasmq6b.com; # βόλος.com
+xn--nxasmm1c.com; βόλος.com; ; xn--nxasmm1c.com; ; ; # βόλος.com
+xn--nxasmm1c; βόλος; ; xn--nxasmm1c; ; ; # βόλος
+βόλος; ; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+ΒΌΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+ΒΌΛΟΣ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+βόλοσ; ; ; xn--nxasmq6b; ; ; # βόλοσ
+βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλοσ; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+xn--nxasmq6b; βόλοσ; ; xn--nxasmq6b; ; ; # βόλοσ
+Βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+Βόλος; βόλος; ; xn--nxasmm1c; ; xn--nxasmq6b; # βόλος
+www.ශ්‍රී.com; ; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+WWW.ශ්‍රී.COM; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+Www.ශ්‍රී.com; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; www.xn--10cl1a0b.com; # www.ශ්රී.com
+www.xn--10cl1a0b.com; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+www.ශ්රී.com; ; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+WWW.ශ්රී.COM; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+Www.ශ්රී.com; www.ශ්රී.com; ; www.xn--10cl1a0b.com; ; ; # www.ශ්රී.com
+www.xn--10cl1a0b660p.com; www.ශ්‍රී.com; ; www.xn--10cl1a0b660p.com; ; ; # www.ශ්රී.com
+نامه‌ای; ; ; xn--mgba3gch31f060k; ; xn--mgba3gch31f; # نامهای
+xn--mgba3gch31f; نامهای; ; xn--mgba3gch31f; ; ; # نامهای
+نامهای; ; ; xn--mgba3gch31f; ; ; # نامهای
+xn--mgba3gch31f060k; نامه‌ای; ; xn--mgba3gch31f060k; ; ; # نامهای
+xn--mgba3gch31f060k.com; نامه‌ای.com; ; xn--mgba3gch31f060k.com; ; ; # نامهای.com
+نامه‌ای.com; ; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com
+نامه‌ای.COM; نامه‌ای.com; ; xn--mgba3gch31f060k.com; ; xn--mgba3gch31f.com; # نامهای.com
+xn--mgba3gch31f.com; نامهای.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+نامهای.com; ; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+نامهای.COM; نامهای.com; ; xn--mgba3gch31f.com; ; ; # نامهای.com
+a.b.c。d。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+a.b.c。d。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.B.C。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.b.c。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+a.b.c.d.; ; ; ; ; ; # a.b.c.d.
+A.B.C。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+A.b.c。D。; a.b.c.d.; ; ; ; ; # a.b.c.d.
+Ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.XN--TDA; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.xn--Tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+xn--tda.xn--tda; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.ü; ; ; xn--tda.xn--tda; ; ; # ü.ü
+ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.Ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.Ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+Ü.ü; ü.ü; ; xn--tda.xn--tda; ; ; # ü.ü
+xn--u-ccb; ü; [V1]; xn--u-ccb; ; ; # ü
+a⒈com; ; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+a1.com; ; ; ; ; ; # a1.com
+A⒈COM; a⒈com; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+A⒈Com; a⒈com; [P1, V6]; xn--acom-0w1b; ; ; # a⒈com
+xn--acom-0w1b; a⒈com; [V6]; xn--acom-0w1b; ; ; # a⒈com
+xn--a-ecp.ru; a⒈.ru; [V6]; xn--a-ecp.ru; ; ; # a⒈.ru
+xn--0.pt; ; [P4]; ; ; ; # xn--0.pt
+xn--a.pt; €.pt; [V6]; xn--a.pt; ; ; # .pt
+xn--a-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--a-ä.pt; ; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+XN--A-Ä.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+XN--A-Ä.PT; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+Xn--A-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+Xn--A-Ä.pt; xn--a-ä.pt; [P4]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+xn--xn--a--gua.pt; xn--a-ä.pt; [V2]; xn--xn--a--gua.pt; ; ; # xn--a-ä.pt
+日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+xn--wgv71a119e.jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.jp; ; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.JP; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語.Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+日本語。Jp; 日本語.jp; ; xn--wgv71a119e.jp; ; ; # 日本語.jp
+☕; ; ; xn--53h; ; ; # ☕
+xn--53h; ☕; ; xn--53h; ; ; # ☕
+1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; ; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+1.ASS‌‍B‌‍CSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASS‌‍B‌‍CSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.ASSBCSSSSSSSSDΣΣSSSSSSSSSSSSSSSSESSSSSSSSSSSSSSSSSSSSXSSSSSSSSSSSSSSSSSSSSYSSSSSSSSSSSSSSSŜSSZ; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; ; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; 1.ass‌‍b‌‍cssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz; [C1, C2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa69989dba9gc; [C1, C2, A4_2]; ; # 1.assbcssssssssdσσssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssŝssz
+1.Aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; 1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; 1.xn--assbcssssssssdssssssssssssssssessssssssssssssssssssxssssssssssssssssssssysssssssssssssssssz-pxq1419aa; [A4_2] # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; 1.aß‌‍b‌‍cßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz; [C1, C2]; 1.xn--abcdexyz-qyacaaabaaaaaaabaaaaaaaaabaaaaaaaaabaaaaaaaa010ze2isb1140zba8cc; [C1, C2, A4_2]; ; # 1.aßbcßßßßdςσßßßßßßßßeßßßßßßßßßßxßßßßßßßßßßyßßßßßßßß̂ßz
+‌x‍n‌-‍-bß; ; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß
+‌X‍N‌-‍-BSS; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+‌x‍n‌-‍-bss; ; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+‌X‍n‌-‍-Bss; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; xn--bss; [] # xn--bss
+xn--bss; 夙; ; xn--bss; ; ; # 夙
+夙; ; ; xn--bss; ; ; # 夙
+xn--xn--bss-7z6ccid; ‌x‍n‌-‍-bss; [C1, C2]; xn--xn--bss-7z6ccid; ; ; # xn--bss
+‌X‍n‌-‍-Bß; ‌x‍n‌-‍-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; xn--bss; [] # xn--bß
+xn--xn--b-pqa5796ccahd; ‌x‍n‌-‍-bß; [C1, C2]; xn--xn--b-pqa5796ccahd; ; ; # xn--bß
+ˣ͏ℕ​﹣­-᠌ℬ︀ſ⁤𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏N​-­-᠌B︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏n​-­-᠌b︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+X͏N​-­-᠌B︀S⁤S󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+X͏n​-­-᠌B︀s⁤s󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+xn--bssffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+夡夞夜夙; ; ; xn--bssffl; ; ; # 夡夞夜夙
+ˣ͏ℕ​﹣­-᠌ℬ︀S⁤𝔰󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+x͏N​-­-᠌B︀S⁤s󠇯FFL; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+ˣ͏ℕ​﹣­-᠌ℬ︀s⁤𝔰󠇯ffl; 夡夞夜夙; ; xn--bssffl; ; ; # 夡夞夜夙
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; ; ; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; ; ; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; ; ; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; ; ; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; ; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901234.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+ä1234567890123456789012345678901234567890123456789012345; ; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+Ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+Ä1234567890123456789012345678901234567890123456789012345; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+xn--1234567890123456789012345678901234567890123456789012345-9te; ä1234567890123456789012345678901234567890123456789012345; ; xn--1234567890123456789012345678901234567890123456789012345-9te; ; ; # ä1234567890123456789012345678901234567890123456789012345
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.; ; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; ; 123456789012345678901234567890123456789012345678901234567890123.xn--1234567890123456789012345678901234567890123456789012345-kue.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012; [A4_1]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.; [A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.1234567890Ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; ; 123456789012345678901234567890123456789012345678901234567890123.xn--12345678901234567890123456789012345678901234567890123456-fxe.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901; [A4_1, A4_2]; ; # 123456789012345678901234567890123456789012345678901234567890123.1234567890ä1234567890123456789012345678901234567890123456.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901
+a.b..-q--a-.e; ; [V2, V3, X4_2]; ; [V2, V3, A4_2]; ; # a.b..-q--a-.e
+a.b..-q--ä-.e; ; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a.b..-q--ä-.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.B..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.B..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.b..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+A.b..-Q--Ä-.E; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a.b..xn---q----jra.e; a.b..-q--ä-.e; [V2, V3, X4_2]; a.b..xn---q----jra.e; [V2, V3, A4_2]; ; # a.b..-q--ä-.e
+a..c; ; [X4_2]; ; [A4_2]; ; # a..c
+a.-b.; ; [V3]; ; ; ; # a.-b.
+a.b-.c; ; [V3]; ; ; ; # a.b-.c
+a.-.c; ; [V3]; ; ; ; # a.-.c
+a.bc--de.f; ; [V2]; ; ; ; # a.bc--de.f
+ä.­.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+ä.­.c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+Ä.­.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+Ä.­.C; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+xn--4ca..c; ä..c; [X4_2]; xn--4ca..c; [A4_2]; ; # ä..c
+ä.-b.; ; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+ä.-b.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+Ä.-B.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+Ä.-B.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+xn--4ca.-b.; ä.-b.; [V3]; xn--4ca.-b.; ; ; # ä.-b.
+ä.b-.c; ; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+ä.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.B-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+Ä.b-.C; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+xn--4ca.b-.c; ä.b-.c; [V3]; xn--4ca.b-.c; ; ; # ä.b-.c
+ä.-.c; ; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+ä.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+Ä.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+Ä.-.C; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+xn--4ca.-.c; ä.-.c; [V3]; xn--4ca.-.c; ; ; # ä.-.c
+ä.bc--de.f; ; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+ä.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.BC--DE.F; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+Ä.bc--De.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+xn--4ca.bc--de.f; ä.bc--de.f; [V2]; xn--4ca.bc--de.f; ; ; # ä.bc--de.f
+a.b.̈c.d; ; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A.B.̈C.D; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A.b.̈c.d; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+a.b.xn--c-bcb.d; a.b.̈c.d; [V5]; a.b.xn--c-bcb.d; ; ; # a.b.̈c.d
+A0; a0; ; ; ; ; # a0
+0A; 0a; ; ; ; ; # 0a
+0A.א; 0a.א; [B1]; 0a.xn--4db; ; ; # 0a.א
+0a.א; ; [B1]; 0a.xn--4db; ; ; # 0a.א
+0a.xn--4db; 0a.א; [B1]; 0a.xn--4db; ; ; # 0a.א
+c.xn--0-eha.xn--4db; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+b-.א; ; [B6, V3]; b-.xn--4db; ; ; # b-.א
+B-.א; b-.א; [B6, V3]; b-.xn--4db; ; ; # b-.א
+b-.xn--4db; b-.א; [B6, V3]; b-.xn--4db; ; ; # b-.א
+d.xn----dha.xn--4db; d.ü-.א; [B6, V3]; d.xn----dha.xn--4db; ; ; # d.ü-.א
+aא; ; [B5, B6]; xn--a-0hc; ; ; # aא
+Aא; aא; [B5, B6]; xn--a-0hc; ; ; # aא
+xn--a-0hc; aא; [B5, B6]; xn--a-0hc; ; ; # aא
+אׇ; ; ; xn--vdbr; ; ; # אׇ
+xn--vdbr; אׇ; ; xn--vdbr; ; ; # אׇ
+א9ׇ; ; ; xn--9-ihcz; ; ; # א9ׇ
+xn--9-ihcz; א9ׇ; ; xn--9-ihcz; ; ; # א9ׇ
+אaׇ; ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+אAׇ; אaׇ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+xn--a-ihcz; אaׇ; [B2, B3]; xn--a-ihcz; ; ; # אaׇ
+את; ; ; xn--4db6c; ; ; # את
+xn--4db6c; את; ; xn--4db6c; ; ; # את
+א׳ת; ; ; xn--4db6c0a; ; ; # א׳ת
+xn--4db6c0a; א׳ת; ; xn--4db6c0a; ; ; # א׳ת
+aאTz; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+aאtz; ; [B5]; xn--atz-qpe; ; ; # aאtz
+AאTZ; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+Aאtz; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+xn--atz-qpe; aאtz; [B5]; xn--atz-qpe; ; ; # aאtz
+אTת; אtת; [B2]; xn--t-zhc3f; ; ; # אtת
+אtת; ; [B2]; xn--t-zhc3f; ; ; # אtת
+xn--t-zhc3f; אtת; [B2]; xn--t-zhc3f; ; ; # אtת
+א7ת; ; ; xn--7-zhc3f; ; ; # א7ת
+xn--7-zhc3f; א7ת; ; xn--7-zhc3f; ; ; # א7ת
+א٧ת; ; ; xn--4db6c6t; ; ; # א٧ת
+xn--4db6c6t; א٧ת; ; xn--4db6c6t; ; ; # א٧ת
+a7٧z; ; [B5]; xn--a7z-06e; ; ; # a7٧z
+A7٧Z; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+A7٧z; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+xn--a7z-06e; a7٧z; [B5]; xn--a7z-06e; ; ; # a7٧z
+א7٧ת; ; [B4]; xn--7-zhc3fty; ; ; # א7٧ת
+xn--7-zhc3fty; א7٧ת; [B4]; xn--7-zhc3fty; ; ; # א7٧ת
+ஹ்‍; ; ; xn--dmc4b194h; ; xn--dmc4b; # ஹ்
+xn--dmc4b; ஹ்; ; xn--dmc4b; ; ; # ஹ்
+ஹ்; ; ; xn--dmc4b; ; ; # ஹ்
+xn--dmc4b194h; ஹ்‍; ; xn--dmc4b194h; ; ; # ஹ்
+ஹ‍; ; [C2]; xn--dmc225h; ; xn--dmc; [] # ஹ
+xn--dmc; ஹ; ; xn--dmc; ; ; # ஹ
+ஹ; ; ; xn--dmc; ; ; # ஹ
+xn--dmc225h; ஹ‍; [C2]; xn--dmc225h; ; ; # ஹ
+‍; ; [C2]; xn--1ug; ; ; [A4_2] #
+; ; [X4_2]; ; [A4_2]; ; #
+xn--1ug; ‍; [C2]; xn--1ug; ; ; #
+ஹ்‌; ; ; xn--dmc4by94h; ; xn--dmc4b; # ஹ்
+xn--dmc4by94h; ஹ்‌; ; xn--dmc4by94h; ; ; # ஹ்
+ஹ‌; ; [C1]; xn--dmc025h; ; xn--dmc; [] # ஹ
+xn--dmc025h; ஹ‌; [C1]; xn--dmc025h; ; ; # ஹ
+‌; ; [C1]; xn--0ug; ; ; [A4_2] #
+xn--0ug; ‌; [C1]; xn--0ug; ; ; #
+لٰ‌ۭۯ; ; ; xn--ghb2gxqia7523a; ; xn--ghb2gxqia; # لٰۭۯ
+xn--ghb2gxqia; لٰۭۯ; ; xn--ghb2gxqia; ; ; # لٰۭۯ
+لٰۭۯ; ; ; xn--ghb2gxqia; ; ; # لٰۭۯ
+xn--ghb2gxqia7523a; لٰ‌ۭۯ; ; xn--ghb2gxqia7523a; ; ; # لٰۭۯ
+لٰ‌ۯ; ; ; xn--ghb2g3qq34f; ; xn--ghb2g3q; # لٰۯ
+xn--ghb2g3q; لٰۯ; ; xn--ghb2g3q; ; ; # لٰۯ
+لٰۯ; ; ; xn--ghb2g3q; ; ; # لٰۯ
+xn--ghb2g3qq34f; لٰ‌ۯ; ; xn--ghb2g3qq34f; ; ; # لٰۯ
+ل‌ۭۯ; ; ; xn--ghb25aga828w; ; xn--ghb25aga; # لۭۯ
+xn--ghb25aga; لۭۯ; ; xn--ghb25aga; ; ; # لۭۯ
+لۭۯ; ; ; xn--ghb25aga; ; ; # لۭۯ
+xn--ghb25aga828w; ل‌ۭۯ; ; xn--ghb25aga828w; ; ; # لۭۯ
+ل‌ۯ; ; ; xn--ghb65a953d; ; xn--ghb65a; # لۯ
+xn--ghb65a; لۯ; ; xn--ghb65a; ; ; # لۯ
+لۯ; ; ; xn--ghb65a; ; ; # لۯ
+xn--ghb65a953d; ل‌ۯ; ; xn--ghb65a953d; ; ; # لۯ
+لٰ‌ۭ; ; [B3, C1]; xn--ghb2gxqy34f; ; xn--ghb2gxq; [] # لٰۭ
+xn--ghb2gxq; لٰۭ; ; xn--ghb2gxq; ; ; # لٰۭ
+لٰۭ; ; ; xn--ghb2gxq; ; ; # لٰۭ
+xn--ghb2gxqy34f; لٰ‌ۭ; [B3, C1]; xn--ghb2gxqy34f; ; ; # لٰۭ
+ۯ‌ۯ; ; [C1]; xn--cmba004q; ; xn--cmba; [] # ۯۯ
+xn--cmba; ۯۯ; ; xn--cmba; ; ; # ۯۯ
+ۯۯ; ; ; xn--cmba; ; ; # ۯۯ
+xn--cmba004q; ۯ‌ۯ; [C1]; xn--cmba004q; ; ; # ۯۯ
+ل‌; ; [B3, C1]; xn--ghb413k; ; xn--ghb; [] # ل
+xn--ghb; ل; ; xn--ghb; ; ; # ل
+ل; ; ; xn--ghb; ; ; # ل
+xn--ghb413k; ل‌; [B3, C1]; xn--ghb413k; ; ; # ل
+a。。b; a..b; [X4_2]; ; [A4_2]; ; # a..b
+A。。B; a..b; [X4_2]; ; [A4_2]; ; # a..b
+a..b; ; [X4_2]; ; [A4_2]; ; # a..b
+‍。。ڹ‌; ‍..ڹ‌; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ..xn--skb; [A4_2] # ..ڹ
+..xn--skb; ..ڹ; [X4_2]; ..xn--skb; [A4_2]; ; # ..ڹ
+xn--1ug..xn--skb080k; ‍..ڹ‌; [B1, B3, C1, C2, X4_2]; xn--1ug..xn--skb080k; [B1, B3, C1, C2, A4_2]; ; # ..ڹ
+א0٠; ; [B4]; xn--0-zhc74b; ; ; # א0٠
+xn--0-zhc74b; א0٠; [B4]; xn--0-zhc74b; ; ; # א0٠
+$; ; [P1, V6]; ; ; ; # $
+
+# RANDOMIZED TESTS
+
+c.0ü.א; ; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+c.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0Ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0Ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+C.0ü.א; c.0ü.א; [B1]; c.xn--0-eha.xn--4db; ; ; # c.0ü.א
+⒕∝ٟ򓤦.-󠄯; ⒕∝ٟ򓤦.-; [P1, V3, V6]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.-
+14.∝ٟ򓤦.-󠄯; 14.∝ٟ򓤦.-; [P1, V3, V6]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.-
+14.xn--7hb713l3v90n.-; 14.∝ٟ򓤦.-; [V3, V6]; 14.xn--7hb713l3v90n.-; ; ; # 14.∝ٟ.-
+xn--7hb713lfwbi1311b.-; ⒕∝ٟ򓤦.-; [V3, V6]; xn--7hb713lfwbi1311b.-; ; ; # ⒕∝ٟ.-
+ꡣ.ߏ; ; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ
+xn--8c9a.xn--qsb; ꡣ.ߏ; ; xn--8c9a.xn--qsb; ; ; # ꡣ.ߏ
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+≯؃。-; ≯؃.-; [B1, P1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+xn--lfb566l.-; ≯؃.-; [B1, V3, V6]; xn--lfb566l.-; ; ; # ≯.-
+⾛𐹧⾕.ᅟ󠗰ςႭ; 走𐹧谷.ᅟ󠗰ςႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; xn--6g3a1x434z.xn--4xa627dhpae6345i; # 走𐹧谷.ςႭ
+走𐹧谷.ᅟ󠗰ςႭ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; xn--6g3a1x434z.xn--4xa627dhpae6345i; # 走𐹧谷.ςႭ
+走𐹧谷.ᅟ󠗰ςⴍ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; xn--6g3a1x434z.xn--4xa180eotvh7453a; # 走𐹧谷.ςⴍ
+走𐹧谷.ᅟ󠗰ΣႭ; 走𐹧谷.ᅟ󠗰σႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+走𐹧谷.ᅟ󠗰σⴍ; ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+走𐹧谷.ᅟ󠗰Σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+xn--6g3a1x434z.xn--4xa180eotvh7453a; 走𐹧谷.ᅟ󠗰σⴍ; [B5, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+xn--6g3a1x434z.xn--4xa627dhpae6345i; 走𐹧谷.ᅟ󠗰σႭ; [B5, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+xn--6g3a1x434z.xn--3xa380eotvh7453a; 走𐹧谷.ᅟ󠗰ςⴍ; [B5, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; ; # 走𐹧谷.ςⴍ
+xn--6g3a1x434z.xn--3xa827dhpae6345i; 走𐹧谷.ᅟ󠗰ςႭ; [B5, V6]; xn--6g3a1x434z.xn--3xa827dhpae6345i; ; ; # 走𐹧谷.ςႭ
+⾛𐹧⾕.ᅟ󠗰ςⴍ; 走𐹧谷.ᅟ󠗰ςⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--3xa380eotvh7453a; ; xn--6g3a1x434z.xn--4xa180eotvh7453a; # 走𐹧谷.ςⴍ
+⾛𐹧⾕.ᅟ󠗰ΣႭ; 走𐹧谷.ᅟ󠗰σႭ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa627dhpae6345i; ; ; # 走𐹧谷.σႭ
+⾛𐹧⾕.ᅟ󠗰σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+⾛𐹧⾕.ᅟ󠗰Σⴍ; 走𐹧谷.ᅟ󠗰σⴍ; [B5, P1, V6]; xn--6g3a1x434z.xn--4xa180eotvh7453a; ; ; # 走𐹧谷.σⴍ
+‍≠ᢙ≯.솣-ᡴႠ; ; [C2, P1, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; xn--jbf911clb.xn----6zg521d196p; [P1, V6] # ≠ᢙ≯.솣-ᡴႠ
+‍≠ᢙ≯.솣-ᡴႠ; ‍≠ᢙ≯.솣-ᡴႠ; [C2, P1, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; xn--jbf911clb.xn----6zg521d196p; [P1, V6] # ≠ᢙ≯.솣-ᡴႠ
+‍≠ᢙ≯.솣-ᡴⴀ; ‍≠ᢙ≯.솣-ᡴⴀ; [C2, P1, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [P1, V6] # ≠ᢙ≯.솣-ᡴⴀ
+‍≠ᢙ≯.솣-ᡴⴀ; ; [C2, P1, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; xn--jbf911clb.xn----p9j493ivi4l; [P1, V6] # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf911clb.xn----p9j493ivi4l; ≠ᢙ≯.솣-ᡴⴀ; [V6]; xn--jbf911clb.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf929a90b0b.xn----p9j493ivi4l; ‍≠ᢙ≯.솣-ᡴⴀ; [C2, V6]; xn--jbf929a90b0b.xn----p9j493ivi4l; ; ; # ≠ᢙ≯.솣-ᡴⴀ
+xn--jbf911clb.xn----6zg521d196p; ≠ᢙ≯.솣-ᡴႠ; [V6]; xn--jbf911clb.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ
+xn--jbf929a90b0b.xn----6zg521d196p; ‍≠ᢙ≯.솣-ᡴႠ; [C2, V6]; xn--jbf929a90b0b.xn----6zg521d196p; ; ; # ≠ᢙ≯.솣-ᡴႠ
+񯞜.𐿇ྡྷݽ؀; 񯞜.𐿇ྡྷݽ؀; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+񯞜.𐿇ྡྷݽ؀; 񯞜.𐿇ྡྷݽ؀; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+񯞜.𐿇ྡྷݽ؀; ; [P1, V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+xn--gw68a.xn--ifb57ev2psc6027m; 񯞜.𐿇ྡྷݽ؀; [V6]; xn--gw68a.xn--ifb57ev2psc6027m; ; ; # .𐿇ྡྷݽ
+𣳔̃.𑓂; ; [V5]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂
+xn--nsa95820a.xn--wz1d; 𣳔̃.𑓂; [V5]; xn--nsa95820a.xn--wz1d; ; ; # 𣳔̃.𑓂
+𞤀𞥅񘐱。󠄌Ⴣꡥ; 𞤢𞥅񘐱.Ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--7nd0578e; ; ; # 𞤢𞥅.Ⴣꡥ
+𞤢𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+xn--9d6hgcy3556a.xn--rlju750b; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+xn--9d6hgcy3556a.xn--7nd0578e; 𞤢𞥅񘐱.Ⴣꡥ; [B2, B3, V6]; xn--9d6hgcy3556a.xn--7nd0578e; ; ; # 𞤢𞥅.Ⴣꡥ
+𞤀𞥅񘐱。󠄌ⴣꡥ; 𞤢𞥅񘐱.ⴣꡥ; [B2, B3, P1, V6]; xn--9d6hgcy3556a.xn--rlju750b; ; ; # 𞤢𞥅.ⴣꡥ
+࣢𑁿ς𖬱。󠅡렧; ࣢𑁿ς𖬱.렧; [B1, P1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧
+࣢𑁿ς𖬱。󠅡렧; ࣢𑁿ς𖬱.렧; [B1, P1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; xn--4xa53xp48ys2xc.xn--kn2b; # 𑁿ς𖬱.렧
+࣢𑁿Σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿Σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+࣢𑁿σ𖬱。󠅡렧; ࣢𑁿σ𖬱.렧; [B1, P1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+xn--4xa53xp48ys2xc.xn--kn2b; ࣢𑁿σ𖬱.렧; [B1, V6]; xn--4xa53xp48ys2xc.xn--kn2b; ; ; # 𑁿σ𖬱.렧
+xn--3xa73xp48ys2xc.xn--kn2b; ࣢𑁿ς𖬱.렧; [B1, V6]; xn--3xa73xp48ys2xc.xn--kn2b; ; ; # 𑁿ς𖬱.렧
+-‍。𞤍‌‍⒈; -‍.𞤯‌‍⒈; [B1, C1, C2, P1, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, P1, V3, V6] # -.𞤯⒈
+-‍。𞤍‌‍1.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; -.xn--1-0i8r.; [B1, V3] # -.𞤯1.
+-‍。𞤯‌‍1.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; -.xn--1-0i8r.; [B1, V3] # -.𞤯1.
+-.xn--1-0i8r.; -.𞤯1.; [B1, V3]; -.xn--1-0i8r.; ; ; # -.𞤯1.
+xn----ugn.xn--1-rgnd61297b.; -‍.𞤯‌‍1.; [B1, C1, C2, V3]; xn----ugn.xn--1-rgnd61297b.; ; ; # -.𞤯1.
+-‍。𞤯‌‍⒈; -‍.𞤯‌‍⒈; [B1, C1, C2, P1, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; -.xn--tsh3666n; [B1, P1, V3, V6] # -.𞤯⒈
+-.xn--tsh3666n; -.𞤯⒈; [B1, V3, V6]; -.xn--tsh3666n; ; ; # -.𞤯⒈
+xn----ugn.xn--0ugc555aiv51d; -‍.𞤯‌‍⒈; [B1, C1, C2, V3, V6]; xn----ugn.xn--0ugc555aiv51d; ; ; # -.𞤯⒈
+‌򅎭.Ⴒ𑇀; ; [C1, P1, V6]; xn--0ug15083f.xn--qnd6272k; ; xn--bn95b.xn--qnd6272k; [P1, V6] # .Ⴒ𑇀
+‌򅎭.ⴒ𑇀; ; [C1, P1, V6]; xn--0ug15083f.xn--9kj2034e; ; xn--bn95b.xn--9kj2034e; [P1, V6] # .ⴒ𑇀
+xn--bn95b.xn--9kj2034e; 򅎭.ⴒ𑇀; [V6]; xn--bn95b.xn--9kj2034e; ; ; # .ⴒ𑇀
+xn--0ug15083f.xn--9kj2034e; ‌򅎭.ⴒ𑇀; [C1, V6]; xn--0ug15083f.xn--9kj2034e; ; ; # .ⴒ𑇀
+xn--bn95b.xn--qnd6272k; 򅎭.Ⴒ𑇀; [V6]; xn--bn95b.xn--qnd6272k; ; ; # .Ⴒ𑇀
+xn--0ug15083f.xn--qnd6272k; ‌򅎭.Ⴒ𑇀; [C1, V6]; xn--0ug15083f.xn--qnd6272k; ; ; # .Ⴒ𑇀
+繱𑖿‍.8︒; 繱𑖿‍.8︒; [P1, V6]; xn--1ug6928ac48e.xn--8-o89h; ; xn--gl0as212a.xn--8-o89h; # 繱𑖿.8︒
+繱𑖿‍.8。; 繱𑖿‍.8.; ; xn--1ug6928ac48e.8.; ; xn--gl0as212a.8.; # 繱𑖿.8.
+xn--gl0as212a.8.; 繱𑖿.8.; ; xn--gl0as212a.8.; ; ; # 繱𑖿.8.
+繱𑖿.8.; ; ; xn--gl0as212a.8.; ; ; # 繱𑖿.8.
+xn--1ug6928ac48e.8.; 繱𑖿‍.8.; ; xn--1ug6928ac48e.8.; ; ; # 繱𑖿.8.
+繱𑖿‍.8.; ; ; xn--1ug6928ac48e.8.; ; xn--gl0as212a.8.; # 繱𑖿.8.
+xn--gl0as212a.xn--8-o89h; 繱𑖿.8︒; [V6]; xn--gl0as212a.xn--8-o89h; ; ; # 繱𑖿.8︒
+xn--1ug6928ac48e.xn--8-o89h; 繱𑖿‍.8︒; [V6]; xn--1ug6928ac48e.xn--8-o89h; ; ; # 繱𑖿.8︒
+󠆾.𞀈; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+󠆾.𞀈; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+.xn--ph4h; .𞀈; [V5, X4_2]; .xn--ph4h; [V5, A4_2]; ; # .𞀈
+ß۫。‍; ß۫.‍; [C2]; xn--zca012a.xn--1ug; ; xn--ss-59d.; [] # ß۫.
+SS۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+ss۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+Ss۫。‍; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; xn--ss-59d.; [] # ss۫.
+xn--ss-59d.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+ss۫.; ; ; xn--ss-59d.; ; ; # ss۫.
+SS۫.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+Ss۫.; ss۫.; ; xn--ss-59d.; ; ; # ss۫.
+xn--ss-59d.xn--1ug; ss۫.‍; [C2]; xn--ss-59d.xn--1ug; ; ; # ss۫.
+xn--zca012a.xn--1ug; ß۫.‍; [C2]; xn--zca012a.xn--1ug; ; ; # ß۫.
+󠐵‌⒈.󠎇; 󠐵‌⒈.󠎇; [C1, P1, V6]; xn--0ug88o47900b.xn--tv36e; ; xn--tshz2001k.xn--tv36e; [P1, V6] # ⒈.
+󠐵‌1..󠎇; ; [C1, P1, V6, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, P1, V6, A4_2]; xn--1-bs31m..xn--tv36e; [P1, V6, A4_2] # 1..
+xn--1-bs31m..xn--tv36e; 󠐵1..󠎇; [V6, X4_2]; xn--1-bs31m..xn--tv36e; [V6, A4_2]; ; # 1..
+xn--1-rgn37671n..xn--tv36e; 󠐵‌1..󠎇; [C1, V6, X4_2]; xn--1-rgn37671n..xn--tv36e; [C1, V6, A4_2]; ; # 1..
+xn--tshz2001k.xn--tv36e; 󠐵⒈.󠎇; [V6]; xn--tshz2001k.xn--tv36e; ; ; # ⒈.
+xn--0ug88o47900b.xn--tv36e; 󠐵‌⒈.󠎇; [C1, V6]; xn--0ug88o47900b.xn--tv36e; ; ; # ⒈.
+󟈣ٟꪲß。󌓧; 󟈣ٟꪲß.󌓧; [P1, V6]; xn--zca92z0t7n5w96j.xn--bb79d; ; xn--ss-3xd2839nncy1m.xn--bb79d; # ٟꪲß.
+󟈣ٟꪲSS。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+󟈣ٟꪲss。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+󟈣ٟꪲSs。󌓧; 󟈣ٟꪲss.󌓧; [P1, V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+xn--ss-3xd2839nncy1m.xn--bb79d; 󟈣ٟꪲss.󌓧; [V6]; xn--ss-3xd2839nncy1m.xn--bb79d; ; ; # ٟꪲss.
+xn--zca92z0t7n5w96j.xn--bb79d; 󟈣ٟꪲß.󌓧; [V6]; xn--zca92z0t7n5w96j.xn--bb79d; ; ; # ٟꪲß.
+ݴ‌𞤿。𽘐䉜‍񿤼; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, P1, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [P1, V6] # ݴ𞤿.䉜
+ݴ‌𞤝。𽘐䉜‍񿤼; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, P1, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; xn--4pb2977v.xn--z0nt555ukbnv; [P1, V6] # ݴ𞤿.䉜
+xn--4pb2977v.xn--z0nt555ukbnv; ݴ𞤿.𽘐䉜񿤼; [V6]; xn--4pb2977v.xn--z0nt555ukbnv; ; ; # ݴ𞤿.䉜
+xn--4pb607jjt73a.xn--1ug236ke314donv1a; ݴ‌𞤿.𽘐䉜‍񿤼; [C1, C2, V6]; xn--4pb607jjt73a.xn--1ug236ke314donv1a; ; ; # ݴ𞤿.䉜
+򔭜ςᡱ⒈.≮𑄳‍𐮍; ; [B1, P1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍
+򔭜ςᡱ⒈.≮𑄳‍𐮍; 򔭜ςᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # ςᡱ⒈.≮𑄳𐮍
+򔭜ςᡱ1..≮𑄳‍𐮍; ; [B1, P1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍
+򔭜ςᡱ1..≮𑄳‍𐮍; 򔭜ςᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # ςᡱ1..≮𑄳𐮍
+򔭜Σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜Σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜σᡱ1..≮𑄳‍𐮍; ; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+򔭜σᡱ1..≮𑄳‍𐮍; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, P1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, P1, V6, A4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; # σᡱ1..≮𑄳𐮍
+xn--1-zmb699meq63t..xn--gdh5392g6sd; 򔭜σᡱ1..≮𑄳𐮍; [B1, V6, X4_2]; xn--1-zmb699meq63t..xn--gdh5392g6sd; [B1, V6, A4_2]; ; # σᡱ1..≮𑄳𐮍
+xn--1-zmb699meq63t..xn--1ug85gn777ahze; 򔭜σᡱ1..≮𑄳‍𐮍; [B1, V6, X4_2]; xn--1-zmb699meq63t..xn--1ug85gn777ahze; [B1, V6, A4_2]; ; # σᡱ1..≮𑄳𐮍
+xn--1-xmb999meq63t..xn--1ug85gn777ahze; 򔭜ςᡱ1..≮𑄳‍𐮍; [B1, V6, X4_2]; xn--1-xmb999meq63t..xn--1ug85gn777ahze; [B1, V6, A4_2]; ; # ςᡱ1..≮𑄳𐮍
+򔭜Σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜Σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜σᡱ⒈.≮𑄳‍𐮍; ; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+򔭜σᡱ⒈.≮𑄳‍𐮍; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, P1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; xn--4xa207hkzinr77u.xn--gdh5392g6sd; # σᡱ⒈.≮𑄳𐮍
+xn--4xa207hkzinr77u.xn--gdh5392g6sd; 򔭜σᡱ⒈.≮𑄳𐮍; [B1, V6]; xn--4xa207hkzinr77u.xn--gdh5392g6sd; ; ; # σᡱ⒈.≮𑄳𐮍
+xn--4xa207hkzinr77u.xn--1ug85gn777ahze; 򔭜σᡱ⒈.≮𑄳‍𐮍; [B1, V6]; xn--4xa207hkzinr77u.xn--1ug85gn777ahze; ; ; # σᡱ⒈.≮𑄳𐮍
+xn--3xa407hkzinr77u.xn--1ug85gn777ahze; 򔭜ςᡱ⒈.≮𑄳‍𐮍; [B1, V6]; xn--3xa407hkzinr77u.xn--1ug85gn777ahze; ; ; # ςᡱ⒈.≮𑄳𐮍
+ㅤ्Ⴀ័.᠋; ㅤ्Ⴀ័.; [P1, V6]; xn--n3b468azngju2a.; ; ; # ्Ⴀ័.
+ᅠ्Ⴀ័.᠋; ᅠ्Ⴀ័.; [P1, V6]; xn--n3b468aoqa89r.; ; ; # ्Ⴀ័.
+ᅠ्ⴀ័.᠋; ᅠ्ⴀ័.; [P1, V6]; xn--n3b742bkqf4ty.; ; ; # ्ⴀ័.
+xn--n3b742bkqf4ty.; ᅠ्ⴀ័.; [V6]; xn--n3b742bkqf4ty.; ; ; # ्ⴀ័.
+xn--n3b468aoqa89r.; ᅠ्Ⴀ័.; [V6]; xn--n3b468aoqa89r.; ; ; # ्Ⴀ័.
+ㅤ्ⴀ័.᠋; ㅤ्ⴀ័.; [P1, V6]; xn--n3b445e53po6d.; ; ; # ्ⴀ័.
+xn--n3b445e53po6d.; ㅤ्ⴀ័.; [V6]; xn--n3b445e53po6d.; ; ; # ्ⴀ័.
+xn--n3b468azngju2a.; ㅤ्Ⴀ័.; [V6]; xn--n3b468azngju2a.; ; ; # ्Ⴀ័.
+❣‍.্𑰽ؒꤩ; ❣‍.্𑰽ؒꤩ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V5] # ❣.্𑰽ؒꤩ
+❣‍.্𑰽ؒꤩ; ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; xn--pei.xn--0fb32q3w7q2g4d; [V5] # ❣.্𑰽ؒꤩ
+xn--pei.xn--0fb32q3w7q2g4d; ❣.্𑰽ؒꤩ; [V5]; xn--pei.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ
+xn--1ugy10a.xn--0fb32q3w7q2g4d; ❣‍.্𑰽ؒꤩ; [C2, V5]; xn--1ugy10a.xn--0fb32q3w7q2g4d; ; ; # ❣.্𑰽ؒꤩ
+≮𐳺𐹄.≯񪮸ꡅ; ; [B1, P1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+≮𐳺𐹄.≯񪮸ꡅ; ≮𐳺𐹄.≯񪮸ꡅ; [B1, P1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+xn--gdh7943gk2a.xn--hdh1383c5e36c; ≮𐳺𐹄.≯񪮸ꡅ; [B1, V6]; xn--gdh7943gk2a.xn--hdh1383c5e36c; ; ; # ≮𐳺.≯ꡅ
+ೌ𐧅𐳏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐳏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐲏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+xn--7tc6360ky5bn2732c.xn--8tc429c; ೌ𐧅𐳏󠲺.್ᠦ; [B1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+ೌ𐧅𐲏󠲺。್ᠦ; ೌ𐧅𐳏󠲺.್ᠦ; [B1, P1, V5, V6]; xn--7tc6360ky5bn2732c.xn--8tc429c; ; ; # ೌ𐧅𐳏.್ᠦ
+͉。𧡫; ͉.𧡫; [V5]; xn--nua.xn--bc6k; ; ; # ͉.𧡫
+xn--nua.xn--bc6k; ͉.𧡫; [V5]; xn--nua.xn--bc6k; ; ; # ͉.𧡫
+𑰿󠅦.ᅠ; 𑰿.ᅠ; [P1, V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+𑰿󠅦.ᅠ; 𑰿.ᅠ; [P1, V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+xn--ok3d.xn--psd; 𑰿.ᅠ; [V5, V6]; xn--ok3d.xn--psd; ; ; # 𑰿.
+-𞤆‍。󸼄𞳒; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, P1, V3, V6]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, P1, V3, V6] # -𞤨.
+-𞤨‍。󸼄𞳒; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, P1, V3, V6]; xn----ugnx367r.xn--846h96596c; ; xn----ni8r.xn--846h96596c; [B1, B5, B6, P1, V3, V6] # -𞤨.
+xn----ni8r.xn--846h96596c; -𞤨.󸼄𞳒; [B1, B5, B6, V3, V6]; xn----ni8r.xn--846h96596c; ; ; # -𞤨.
+xn----ugnx367r.xn--846h96596c; -𞤨‍.󸼄𞳒; [B1, B5, B6, C2, V3, V6]; xn----ugnx367r.xn--846h96596c; ; ; # -𞤨.
+ꡏ󠇶≯𳾽。᷽⾇滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽⾇滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽舛滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+ꡏ󠇶≯𳾽。᷽舛滸𐹰; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, P1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ꡏ󠇶≯𳾽.᷽舛滸𐹰; [B1, V5, V6]; xn--hdh7483cu6twwki8e.xn--yfg0765a58l0n6k; ; ; # ꡏ≯.᷽舛滸𐹰
+蔏。𑰺; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+蔏。𑰺; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+xn--uy1a.xn--jk3d; 蔏.𑰺; [V5]; xn--uy1a.xn--jk3d; ; ; # 蔏.𑰺
+𝟿𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+9𐮋。󠄊; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+xn--9-rv5i.; 9𐮋.; [B1]; xn--9-rv5i.; ; ; # 9𐮋.
+󟇇-䟖F。ߋ⒈٢; 󟇇-䟖f.ߋ⒈٢; [B4, P1, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+󟇇-䟖F。ߋ1.٢; 󟇇-䟖f.ߋ1.٢; [B1, P1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+󟇇-䟖f。ߋ1.٢; 󟇇-䟖f.ߋ1.٢; [B1, P1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+xn---f-mz8b08788k.xn--1-ybd.xn--bib; 󟇇-䟖f.ߋ1.٢; [B1, V6]; xn---f-mz8b08788k.xn--1-ybd.xn--bib; ; ; # -䟖f.ߋ1.٢
+󟇇-䟖f。ߋ⒈٢; 󟇇-䟖f.ߋ⒈٢; [B4, P1, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+xn---f-mz8b08788k.xn--bib53ev44d; 󟇇-䟖f.ߋ⒈٢; [B4, V6]; xn---f-mz8b08788k.xn--bib53ev44d; ; ; # -䟖f.ߋ⒈٢
+‌。𐹺; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺
+‌。𐹺; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; .xn--yo0d; [B1, A4_2] # .𐹺
+.xn--yo0d; .𐹺; [B1, X4_2]; .xn--yo0d; [B1, A4_2]; ; # .𐹺
+xn--0ug.xn--yo0d; ‌.𐹺; [B1, C1]; xn--0ug.xn--yo0d; ; ; # .𐹺
+𐡆.≯‌-𞥀; ; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞥀; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞤞; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+𐡆.≯‌-𞤞; 𐡆.≯‌-𞥀; [B1, C1, P1, V6]; xn--le9c.xn----rgn40iy359e; ; xn--le9c.xn----ogo9956r; [B1, P1, V6] # 𐡆.≯-𞥀
+xn--le9c.xn----ogo9956r; 𐡆.≯-𞥀; [B1, V6]; xn--le9c.xn----ogo9956r; ; ; # 𐡆.≯-𞥀
+xn--le9c.xn----rgn40iy359e; 𐡆.≯‌-𞥀; [B1, C1, V6]; xn--le9c.xn----rgn40iy359e; ; ; # 𐡆.≯-𞥀
+󠁀-。≠ﳗ; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠ﳗ; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠هج; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+󠁀-。≠هج; 󠁀-.≠هج; [B1, P1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+xn----f411m.xn--rgb7c611j; 󠁀-.≠هج; [B1, V3, V6]; xn----f411m.xn--rgb7c611j; ; ; # -.≠هج
+񻬹𑈵。‍𞨶; 񻬹𑈵.‍𞨶; [B1, C2, P1, V6]; xn--8g1d12120a.xn--1ug6651p; ; xn--8g1d12120a.xn--5l6h; [P1, V6] # 𑈵.
+xn--8g1d12120a.xn--5l6h; 񻬹𑈵.𞨶; [V6]; xn--8g1d12120a.xn--5l6h; ; ; # 𑈵.
+xn--8g1d12120a.xn--1ug6651p; 񻬹𑈵.‍𞨶; [B1, C2, V6]; xn--8g1d12120a.xn--1ug6651p; ; ; # 𑈵.
+𑋧꧀2。㧉򒖄; 𑋧꧀2.㧉򒖄; [P1, V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+𑋧꧀2。㧉򒖄; 𑋧꧀2.㧉򒖄; [P1, V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+xn--2-5z4eu89y.xn--97l02706d; 𑋧꧀2.㧉򒖄; [V5, V6]; xn--2-5z4eu89y.xn--97l02706d; ; ; # 𑋧꧀2.㧉
+‌𽬄𐹴𞩥。≯6; ‌𽬄𐹴𞩥.≯6; [B1, C1, P1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, P1, V6] # 𐹴.≯6
+‌𽬄𐹴𞩥。≯6; ‌𽬄𐹴𞩥.≯6; [B1, C1, P1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; xn--so0du768aim9m.xn--6-ogo; [B1, B5, B6, P1, V6] # 𐹴.≯6
+xn--so0du768aim9m.xn--6-ogo; 𽬄𐹴𞩥.≯6; [B1, B5, B6, V6]; xn--so0du768aim9m.xn--6-ogo; ; ; # 𐹴.≯6
+xn--0ug7105gf5wfxepq.xn--6-ogo; ‌𽬄𐹴𞩥.≯6; [B1, C1, V6]; xn--0ug7105gf5wfxepq.xn--6-ogo; ; ; # 𐹴.≯6
+𑁿.𐹦𻞵-‍; 𑁿.𐹦𻞵-‍; [B1, B3, B6, C2, P1, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, B3, B6, P1, V3, V5, V6] # 𑁿.𐹦-
+𑁿.𐹦𻞵-‍; ; [B1, B3, B6, C2, P1, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; xn--q30d.xn----i26i1299n; [B1, B3, B6, P1, V3, V5, V6] # 𑁿.𐹦-
+xn--q30d.xn----i26i1299n; 𑁿.𐹦𻞵-; [B1, B3, B6, V3, V5, V6]; xn--q30d.xn----i26i1299n; ; ; # 𑁿.𐹦-
+xn--q30d.xn----ugn1088hfsxv; 𑁿.𐹦𻞵-‍; [B1, B3, B6, C2, V5, V6]; xn--q30d.xn----ugn1088hfsxv; ; ; # 𑁿.𐹦-
+⤸ς𺱀。ᅠ; ⤸ς𺱀.ᅠ; [P1, V6]; xn--3xa392qmp03d.xn--cl7c; ; xn--4xa192qmp03d.xn--cl7c; # ⤸ς.
+⤸ς𺱀。ᅠ; ⤸ς𺱀.ᅠ; [P1, V6]; xn--3xa392qmp03d.xn--psd; ; xn--4xa192qmp03d.xn--psd; # ⤸ς.
+⤸Σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+⤸σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+xn--4xa192qmp03d.xn--psd; ⤸σ𺱀.ᅠ; [V6]; xn--4xa192qmp03d.xn--psd; ; ; # ⤸σ.
+xn--3xa392qmp03d.xn--psd; ⤸ς𺱀.ᅠ; [V6]; xn--3xa392qmp03d.xn--psd; ; ; # ⤸ς.
+⤸Σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+⤸σ𺱀。ᅠ; ⤸σ𺱀.ᅠ; [P1, V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+xn--4xa192qmp03d.xn--cl7c; ⤸σ𺱀.ᅠ; [V6]; xn--4xa192qmp03d.xn--cl7c; ; ; # ⤸σ.
+xn--3xa392qmp03d.xn--cl7c; ⤸ς𺱀.ᅠ; [V6]; xn--3xa392qmp03d.xn--cl7c; ; ; # ⤸ς.
+ݥဵ𐫔ە.𐦬𑋪Ⴃ; ; [B2, B3, P1, V6]; xn--llb10as9tqp5y.xn--bnd9168j21f; ; ; # ݥဵ𐫔ە.𐦬𑋪Ⴃ
+ݥဵ𐫔ە.𐦬𑋪ⴃ; ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ
+xn--llb10as9tqp5y.xn--ukj7371e21f; ݥဵ𐫔ە.𐦬𑋪ⴃ; [B2, B3]; xn--llb10as9tqp5y.xn--ukj7371e21f; ; ; # ݥဵ𐫔ە.𐦬𑋪ⴃ
+xn--llb10as9tqp5y.xn--bnd9168j21f; ݥဵ𐫔ە.𐦬𑋪Ⴃ; [B2, B3, V6]; xn--llb10as9tqp5y.xn--bnd9168j21f; ; ; # ݥဵ𐫔ە.𐦬𑋪Ⴃ
+١᭄-킼.᮪ؖ٬≯; ; [B1, B5, B6, P1, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+١᭄-킼.᮪ؖ٬≯; ١᭄-킼.᮪ؖ٬≯; [B1, B5, B6, P1, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+xn----9pc551nk39n.xn--4fb6o571degg; ١᭄-킼.᮪ؖ٬≯; [B1, B5, B6, V5, V6]; xn----9pc551nk39n.xn--4fb6o571degg; ; ; # ١᭄-킼.᮪ؖ٬≯
+-。ۂ؄򅖡𑓂; -.ۂ؄򅖡𑓂; [B1, B2, B3, P1, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+-。ۂ؄򅖡𑓂; -.ۂ؄򅖡𑓂; [B1, B2, B3, P1, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+-.xn--mfb39a7208dzgs3d; -.ۂ؄򅖡𑓂; [B1, B2, B3, V3, V6]; -.xn--mfb39a7208dzgs3d; ; ; # -.ۂ𑓂
+‍󯑖󠁐.ֽ𙮰ꡝ𐋡; ‍󯑖󠁐.ֽ𙮰ꡝ𐋡; [C2, P1, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [P1, V5, V6] # .ֽꡝ𐋡
+‍󯑖󠁐.ֽ𙮰ꡝ𐋡; ; [C2, P1, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; xn--b726ey18m.xn--ldb8734fg0qcyzzg; [P1, V5, V6] # .ֽꡝ𐋡
+xn--b726ey18m.xn--ldb8734fg0qcyzzg; 󯑖󠁐.ֽ𙮰ꡝ𐋡; [V5, V6]; xn--b726ey18m.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡
+xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ‍󯑖󠁐.ֽ𙮰ꡝ𐋡; [C2, V5, V6]; xn--1ug66101lt8me.xn--ldb8734fg0qcyzzg; ; ; # .ֽꡝ𐋡
+︒􃈵ς񀠇。𐮈; ︒􃈵ς񀠇.𐮈; [B1, P1, V6]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; xn--4xa1729jwz5t7gl5f.xn--f29c; # ︒ς.𐮈
+。􃈵ς񀠇。𐮈; .􃈵ς񀠇.𐮈; [P1, V6, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [P1, V6, A4_2]; .xn--4xa68573c7n64d.xn--f29c; # .ς.𐮈
+。􃈵Σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [P1, V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [P1, V6, A4_2]; ; # .σ.𐮈
+。􃈵σ񀠇。𐮈; .􃈵σ񀠇.𐮈; [P1, V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [P1, V6, A4_2]; ; # .σ.𐮈
+.xn--4xa68573c7n64d.xn--f29c; .􃈵σ񀠇.𐮈; [V6, X4_2]; .xn--4xa68573c7n64d.xn--f29c; [V6, A4_2]; ; # .σ.𐮈
+.xn--3xa88573c7n64d.xn--f29c; .􃈵ς񀠇.𐮈; [V6, X4_2]; .xn--3xa88573c7n64d.xn--f29c; [V6, A4_2]; ; # .ς.𐮈
+︒􃈵Σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, P1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+︒􃈵σ񀠇。𐮈; ︒􃈵σ񀠇.𐮈; [B1, P1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+xn--4xa1729jwz5t7gl5f.xn--f29c; ︒􃈵σ񀠇.𐮈; [B1, V6]; xn--4xa1729jwz5t7gl5f.xn--f29c; ; ; # ︒σ.𐮈
+xn--3xa3729jwz5t7gl5f.xn--f29c; ︒􃈵ς񀠇.𐮈; [B1, V6]; xn--3xa3729jwz5t7gl5f.xn--f29c; ; ; # ︒ς.𐮈
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ߙ.ۮ󆾃≯󠅲; ߙ.ۮ󆾃≯; [B2, B3, P1, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+xn--0sb.xn--bmb691l0524t; ߙ.ۮ󆾃≯; [B2, B3, V6]; xn--0sb.xn--bmb691l0524t; ; ; # ߙ.ۮ≯
+ᩳ󚙸.𐭍; ; [B1, P1, V5, V6]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍
+xn--2of22352n.xn--q09c; ᩳ󚙸.𐭍; [B1, V5, V6]; xn--2of22352n.xn--q09c; ; ; # ᩳ.𐭍
+⒉󠊓≠。Ⴟ⬣Ⴈ; ⒉󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+⒉󠊓≠。Ⴟ⬣Ⴈ; ⒉󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+2.󠊓≠。Ⴟ⬣Ⴈ; 2.󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+2.󠊓≠。Ⴟ⬣Ⴈ; 2.󠊓≠.Ⴟ⬣Ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+2.󠊓≠。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.󠊓≠。ⴟ⬣ⴈ; 2.󠊓≠.ⴟ⬣ⴈ; [P1, V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.xn--1chz4101l.xn--45iz7d6b; 2.󠊓≠.ⴟ⬣ⴈ; [V6]; 2.xn--1chz4101l.xn--45iz7d6b; ; ; # 2.≠.ⴟ⬣ⴈ
+2.xn--1chz4101l.xn--gnd9b297j; 2.󠊓≠.Ⴟ⬣Ⴈ; [V6]; 2.xn--1chz4101l.xn--gnd9b297j; ; ; # 2.≠.Ⴟ⬣Ⴈ
+⒉󠊓≠。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [P1, V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+⒉󠊓≠。ⴟ⬣ⴈ; ⒉󠊓≠.ⴟ⬣ⴈ; [P1, V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+xn--1ch07f91401d.xn--45iz7d6b; ⒉󠊓≠.ⴟ⬣ⴈ; [V6]; xn--1ch07f91401d.xn--45iz7d6b; ; ; # ⒉≠.ⴟ⬣ⴈ
+xn--1ch07f91401d.xn--gnd9b297j; ⒉󠊓≠.Ⴟ⬣Ⴈ; [V6]; xn--1ch07f91401d.xn--gnd9b297j; ; ; # ⒉≠.Ⴟ⬣Ⴈ
+-󠉱ྸჅ。-𐹽ݴ𞣑; -󠉱ྸჅ.-𐹽ݴ𞣑; [B1, P1, V3, V6]; xn----xmg12fm2555h.xn----05c4213ryr0g; ; ; # -ྸჅ.-𐹽ݴ𞣑
+-󠉱ྸⴥ。-𐹽ݴ𞣑; -󠉱ྸⴥ.-𐹽ݴ𞣑; [B1, P1, V3, V6]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑
+xn----xmg317tgv352a.xn----05c4213ryr0g; -󠉱ྸⴥ.-𐹽ݴ𞣑; [B1, V3, V6]; xn----xmg317tgv352a.xn----05c4213ryr0g; ; ; # -ྸⴥ.-𐹽ݴ𞣑
+xn----xmg12fm2555h.xn----05c4213ryr0g; -󠉱ྸჅ.-𐹽ݴ𞣑; [B1, V3, V6]; xn----xmg12fm2555h.xn----05c4213ryr0g; ; ; # -ྸჅ.-𐹽ݴ𞣑
+ٙ。𑄴︒اߝ; ٙ.𑄴︒اߝ; [B1, B3, B6, P1, V5, V6]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ
+ٙ。𑄴。اߝ; ٙ.𑄴.اߝ; [B1, B3, B6, V5]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ
+xn--1hb.xn--w80d.xn--mgb09f; ٙ.𑄴.اߝ; [B1, B3, B6, V5]; xn--1hb.xn--w80d.xn--mgb09f; ; ; # ٙ.𑄴.اߝ
+xn--1hb.xn--mgb09fp820c08pa; ٙ.𑄴︒اߝ; [B1, B3, B6, V5, V6]; xn--1hb.xn--mgb09fp820c08pa; ; ; # ٙ.𑄴︒اߝ
+Ⴙظ.󠆓‍; Ⴙظ.‍; [B1, B5, B6, C2, P1, V6]; xn--3gb194c.xn--1ug; ; xn--3gb194c.; [B5, B6, P1, V6] # Ⴙظ.
+ⴙظ.󠆓‍; ⴙظ.‍; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; xn--3gb910r.; [B5, B6] # ⴙظ.
+xn--3gb910r.; ⴙظ.; [B5, B6]; xn--3gb910r.; ; ; # ⴙظ.
+xn--3gb910r.xn--1ug; ⴙظ.‍; [B1, B5, B6, C2]; xn--3gb910r.xn--1ug; ; ; # ⴙظ.
+xn--3gb194c.; Ⴙظ.; [B5, B6, V6]; xn--3gb194c.; ; ; # Ⴙظ.
+xn--3gb194c.xn--1ug; Ⴙظ.‍; [B1, B5, B6, C2, V6]; xn--3gb194c.xn--1ug; ; ; # Ⴙظ.
+󠆸。₆0𐺧ݖ; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+󠆸。60𐺧ݖ; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+.xn--60-cke9470y; .60𐺧ݖ; [B1, X4_2]; .xn--60-cke9470y; [B1, A4_2]; ; # .60𐺧ݖ
+6ࡏ。-𑈴; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+6ࡏ。-𑈴; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+xn--6-jjd.xn----6n8i; 6ࡏ.-𑈴; [B1, V3]; xn--6-jjd.xn----6n8i; ; ; # 6ࡏ.-𑈴
+‍񋌿𐹰。્ς𞰎ࣖ; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્ςࣖ
+‍񋌿𐹰。્ς𞰎ࣖ; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્ςࣖ
+‍񋌿𐹰。્Σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+‍񋌿𐹰。્σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+xn--oo0d1330n.xn--4xa21xcwbfz15g; 񋌿𐹰.્σ𞰎ࣖ; [B1, B5, B6, V5, V6]; xn--oo0d1330n.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ
+xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; ; # 𐹰.્σࣖ
+xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ‍񋌿𐹰.્ς𞰎ࣖ; [B1, C2, V5, V6]; xn--1ugx105gq26y.xn--3xa41xcwbfz15g; ; ; # 𐹰.્ςࣖ
+‍񋌿𐹰。્Σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+‍񋌿𐹰。્σ𞰎ࣖ; ‍񋌿𐹰.્σ𞰎ࣖ; [B1, C2, P1, V5, V6]; xn--1ugx105gq26y.xn--4xa21xcwbfz15g; ; xn--oo0d1330n.xn--4xa21xcwbfz15g; [B1, B5, B6, P1, V5, V6] # 𐹰.્σࣖ
+⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; ⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; [B1, P1, V5, V6]; xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ; ; # ⒈Ⴓ⒪.්ࢋ𐹢
+1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; ; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.񟄜ⴓ(o).්򘘶ࢋ𐹢; ; [B1, B6, P1, V5, V6]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢
+1.񟄜Ⴓ(O).්򘘶ࢋ𐹢; 1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; 1.񟄜Ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-7sn88849j.xn--3xb99xpx1yoes3e; ; ; # 1.Ⴓ(o).්ࢋ𐹢
+1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; 1.񟄜ⴓ(o).්򘘶ࢋ𐹢; [B1, B6, P1, V5, V6]; 1.xn--(o)-ej1bu5389e.xn--3xb99xpx1yoes3e; ; ; # 1.ⴓ(o).්ࢋ𐹢
+⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; ⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; [B1, P1, V5, V6]; xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ⒪.්ࢋ𐹢
+xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ⒈񟄜ⴓ⒪.්򘘶ࢋ𐹢; [B1, V5, V6]; xn--tsh0ds63atl31n.xn--3xb99xpx1yoes3e; ; ; # ⒈ⴓ⒪.්ࢋ𐹢
+xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ⒈񟄜Ⴓ⒪.්򘘶ࢋ𐹢; [B1, V5, V6]; xn--rnd762h7cx3027d.xn--3xb99xpx1yoes3e; ; ; # ⒈Ⴓ⒪.්ࢋ𐹢
+𞤷.𐮐𞢁𐹠ؤ; ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤷.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤕.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𞤕.𐮐𞢁𐹠ؤ; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+xn--ve6h.xn--jgb1694kz0b2176a; 𞤷.𐮐𞢁𐹠ؤ; ; xn--ve6h.xn--jgb1694kz0b2176a; ; ; # 𞤷.𐮐𞢁𐹠ؤ
+𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐲈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+xn----ue6i.xn--v80d6662t; 𐳈-.𑄳񢌻; [B1, B3, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+𐳈-。𑄳񢌻; 𐳈-.𑄳񢌻; [B1, B3, P1, V3, V5, V6]; xn----ue6i.xn--v80d6662t; ; ; # 𐳈-.𑄳
+-󠉖ꡧ.󠊂񇆃🄉; -󠉖ꡧ.󠊂񇆃🄉; [P1, V3, V6]; xn----hg4ei0361g.xn--207ht163h7m94c; ; ; # -ꡧ.🄉
+-󠉖ꡧ.󠊂񇆃8,; ; [P1, V3, V6]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8,
+xn----hg4ei0361g.xn--8,-k362evu488a; -󠉖ꡧ.󠊂񇆃8,; [P1, V3, V6]; xn----hg4ei0361g.xn--8,-k362evu488a; ; ; # -ꡧ.8,
+xn----hg4ei0361g.xn--207ht163h7m94c; -󠉖ꡧ.󠊂񇆃🄉; [V3, V6]; xn----hg4ei0361g.xn--207ht163h7m94c; ; ; # -ꡧ.🄉
+󠾛󠈴臯𧔤.ݨ𝟝; 󠾛󠈴臯𧔤.ݨ5; [B1, P1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+󠾛󠈴臯𧔤.ݨ5; ; [B1, P1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+xn--zb1at733hm579ddhla.xn--5-b5c; 󠾛󠈴臯𧔤.ݨ5; [B1, V6]; xn--zb1at733hm579ddhla.xn--5-b5c; ; ; # 臯𧔤.ݨ5
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+≮𐹣.𝨿; ≮𐹣.𝨿; [B1, B3, B6, P1, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+xn--gdh1504g.xn--e92h; ≮𐹣.𝨿; [B1, B3, B6, V5, V6]; xn--gdh1504g.xn--e92h; ; ; # ≮𐹣.𝨿
+𐹯ᯛ੍。脥; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+𐹯ᯛ੍。脥; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+xn--ybc101g3m1p.xn--740a; 𐹯ᯛ੍.脥; [B1]; xn--ybc101g3m1p.xn--740a; ; ; # 𐹯ᯛ੍.脥
+᭄ᅟ𞷿򃀍.-; ; [B1, B5, P1, V3, V5, V6]; xn--osd971cpx70btgt8b.-; ; ; # ᭄.-
+xn--osd971cpx70btgt8b.-; ᭄ᅟ𞷿򃀍.-; [B1, B5, V3, V5, V6]; xn--osd971cpx70btgt8b.-; ; ; # ᭄.-
+‌。͔; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; .xn--yua; [V5, A4_2] # .͔
+‌。͔; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; .xn--yua; [V5, A4_2] # .͔
+.xn--yua; .͔; [V5, X4_2]; .xn--yua; [V5, A4_2]; ; # .͔
+xn--0ug.xn--yua; ‌.͔; [C1, V5]; xn--0ug.xn--yua; ; ; # .͔
+𞤥󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+xn--de6h.xn--37e857h; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤥.ᡄⴎ; ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+xn--de6h.xn--mnd799a; 𞤥.ᡄႮ; [V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤥󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤃󠅮.ᡄႮ; 𞤥.ᡄႮ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤃󠅮.ᡄⴎ; 𞤥.ᡄⴎ; ; xn--de6h.xn--37e857h; ; ; # 𞤥.ᡄⴎ
+𞤥.ᡄႮ; ; [P1, V6]; xn--de6h.xn--mnd799a; ; ; # 𞤥.ᡄႮ
+𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨ξ.𪺏㛨❸; ; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+xn--zxa5691vboja.xn--bfi293ci119b; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤧𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨Ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+𞤅𝨨ξ.𪺏㛨❸; 𞤧𝨨ξ.𪺏㛨❸; [B2, B3, B6]; xn--zxa5691vboja.xn--bfi293ci119b; ; ; # 𞤧𝨨ξ.𪺏㛨❸
+᠆몆‌-。Ⴛ𐦅︒; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; xn----e3j6620g.xn--znd2362jhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅︒
+᠆몆‌-。Ⴛ𐦅︒; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; xn----e3j6620g.xn--znd2362jhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅︒
+᠆몆‌-。Ⴛ𐦅。; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; xn----e3j6620g.xn--znd4948j.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。Ⴛ𐦅。; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; xn----e3j6620g.xn--znd4948j.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅。; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅。; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; xn----e3j6620g.xn--jlju661e.; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅.
+xn----e3j6620g.xn--jlju661e.; ᠆몆-.ⴛ𐦅.; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--jlju661e.; ; ; # ᠆몆-.ⴛ𐦅.
+xn----e3j425bsk1o.xn--jlju661e.; ᠆몆‌-.ⴛ𐦅.; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--jlju661e.; ; ; # ᠆몆-.ⴛ𐦅.
+xn----e3j6620g.xn--znd4948j.; ᠆몆-.Ⴛ𐦅.; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--znd4948j.; ; ; # ᠆몆-.Ⴛ𐦅.
+xn----e3j425bsk1o.xn--znd4948j.; ᠆몆‌-.Ⴛ𐦅.; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--znd4948j.; ; ; # ᠆몆-.Ⴛ𐦅.
+᠆몆‌-。ⴛ𐦅︒; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅︒
+᠆몆‌-。ⴛ𐦅︒; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, P1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; xn----e3j6620g.xn--jlj4997dhgh; [B1, B5, B6, P1, V3, V6] # ᠆몆-.ⴛ𐦅︒
+xn----e3j6620g.xn--jlj4997dhgh; ᠆몆-.ⴛ𐦅︒; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒
+xn----e3j425bsk1o.xn--jlj4997dhgh; ᠆몆‌-.ⴛ𐦅︒; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--jlj4997dhgh; ; ; # ᠆몆-.ⴛ𐦅︒
+xn----e3j6620g.xn--znd2362jhgh; ᠆몆-.Ⴛ𐦅︒; [B1, B5, B6, V3, V6]; xn----e3j6620g.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒
+xn----e3j425bsk1o.xn--znd2362jhgh; ᠆몆‌-.Ⴛ𐦅︒; [B1, B5, B6, C1, V3, V6]; xn----e3j425bsk1o.xn--znd2362jhgh; ; ; # ᠆몆-.Ⴛ𐦅︒
+󠾳.︒⥱‌𐹬; ; [B1, C1, P1, V6]; xn--uf66e.xn--0ugz28axl3pqxna; ; xn--uf66e.xn--qtiz073e3ik; [B1, P1, V6] # .︒⥱𐹬
+󠾳.。⥱‌𐹬; 󠾳..⥱‌𐹬; [B1, C1, P1, V6, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, P1, V6, A4_2]; xn--uf66e..xn--qti2829e; [B1, P1, V6, A4_2] # ..⥱𐹬
+xn--uf66e..xn--qti2829e; 󠾳..⥱𐹬; [B1, V6, X4_2]; xn--uf66e..xn--qti2829e; [B1, V6, A4_2]; ; # ..⥱𐹬
+xn--uf66e..xn--0ugz28as66q; 󠾳..⥱‌𐹬; [B1, C1, V6, X4_2]; xn--uf66e..xn--0ugz28as66q; [B1, C1, V6, A4_2]; ; # ..⥱𐹬
+xn--uf66e.xn--qtiz073e3ik; 󠾳.︒⥱𐹬; [B1, V6]; xn--uf66e.xn--qtiz073e3ik; ; ; # .︒⥱𐹬
+xn--uf66e.xn--0ugz28axl3pqxna; 󠾳.︒⥱‌𐹬; [B1, C1, V6]; xn--uf66e.xn--0ugz28axl3pqxna; ; ; # .︒⥱𐹬
+𐯖.𐹠Ⴑ񚇜𐫊; ; [B1, P1, V6]; xn--n49c.xn--pnd4619jwicl862o; ; ; # .𐹠Ⴑ𐫊
+𐯖.𐹠ⴑ񚇜𐫊; ; [B1, P1, V6]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊
+xn--n49c.xn--8kj8702ewicl862o; 𐯖.𐹠ⴑ񚇜𐫊; [B1, V6]; xn--n49c.xn--8kj8702ewicl862o; ; ; # .𐹠ⴑ𐫊
+xn--n49c.xn--pnd4619jwicl862o; 𐯖.𐹠Ⴑ񚇜𐫊; [B1, V6]; xn--n49c.xn--pnd4619jwicl862o; ; ; # .𐹠Ⴑ𐫊
+ྤ񱤯.𝟭Ⴛ; ྤ񱤯.1Ⴛ; [P1, V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.1Ⴛ; ; [P1, V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.1ⴛ; ; [P1, V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+xn--0fd40533g.xn--1-tws; ྤ񱤯.1ⴛ; [V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+xn--0fd40533g.xn--1-q1g; ྤ񱤯.1Ⴛ; [V5, V6]; xn--0fd40533g.xn--1-q1g; ; ; # ྤ.1Ⴛ
+ྤ񱤯.𝟭ⴛ; ྤ񱤯.1ⴛ; [P1, V5, V6]; xn--0fd40533g.xn--1-tws; ; ; # ྤ.1ⴛ
+-ࠦ齀。릿𐸋; -ࠦ齀.릿𐸋; [B1, B5, B6, P1, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+-ࠦ齀。릿𐸋; -ࠦ齀.릿𐸋; [B1, B5, B6, P1, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+xn----6gd0617i.xn--7y2bm55m; -ࠦ齀.릿𐸋; [B1, B5, B6, V3, V6]; xn----6gd0617i.xn--7y2bm55m; ; ; # -ࠦ齀.릿
+󠔊ܜ鹝꾗。񾵐‍‍⏃; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, P1, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, P1, V6] # ܜ鹝꾗.⏃
+󠔊ܜ鹝꾗。񾵐‍‍⏃; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, P1, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; xn--mnb6558e91kyq533a.xn--6mh27269e; [B1, B6, P1, V6] # ܜ鹝꾗.⏃
+xn--mnb6558e91kyq533a.xn--6mh27269e; 󠔊ܜ鹝꾗.񾵐⏃; [B1, B6, V6]; xn--mnb6558e91kyq533a.xn--6mh27269e; ; ; # ܜ鹝꾗.⏃
+xn--mnb6558e91kyq533a.xn--1uga46zs309y; 󠔊ܜ鹝꾗.񾵐‍‍⏃; [B1, B6, C2, V6]; xn--mnb6558e91kyq533a.xn--1uga46zs309y; ; ; # ܜ鹝꾗.⏃
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+≮.-܈--; ≮.-܈--; [B1, P1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+xn--gdh.xn------eqf; ≮.-܈--; [B1, V2, V3, V6]; xn--gdh.xn------eqf; ; ; # ≮.-܈--
+𐹸󠋳。‍ς𝟩; 𐹸󠋳.‍ς7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.ς7
+𐹸󠋳。‍ς7; 𐹸󠋳.‍ς7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-xmb248s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.ς7
+𐹸󠋳。‍Σ7; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+𐹸󠋳。‍σ7; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+xn--wo0di5177c.xn--7-zmb; 𐹸󠋳.σ7; [B1, V6]; xn--wo0di5177c.xn--7-zmb; ; ; # 𐹸.σ7
+xn--wo0di5177c.xn--7-zmb938s; 𐹸󠋳.‍σ7; [B1, C2, V6]; xn--wo0di5177c.xn--7-zmb938s; ; ; # 𐹸.σ7
+xn--wo0di5177c.xn--7-xmb248s; 𐹸󠋳.‍ς7; [B1, C2, V6]; xn--wo0di5177c.xn--7-xmb248s; ; ; # 𐹸.ς7
+𐹸󠋳。‍Σ𝟩; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+𐹸󠋳。‍σ𝟩; 𐹸󠋳.‍σ7; [B1, C2, P1, V6]; xn--wo0di5177c.xn--7-zmb938s; ; xn--wo0di5177c.xn--7-zmb; [B1, P1, V6] # 𐹸.σ7
+ς򅜌8.𞭤; ς򅜌8.𞭤; [P1, V6]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8.
+ς򅜌8.𞭤; ; [P1, V6]; xn--8-xmb44974n.xn--su6h; ; xn--8-zmb14974n.xn--su6h; # ς8.
+Σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+σ򅜌8.𞭤; ; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+xn--8-zmb14974n.xn--su6h; σ򅜌8.𞭤; [V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+xn--8-xmb44974n.xn--su6h; ς򅜌8.𞭤; [V6]; xn--8-xmb44974n.xn--su6h; ; ; # ς8.
+Σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+σ򅜌8.𞭤; σ򅜌8.𞭤; [P1, V6]; xn--8-zmb14974n.xn--su6h; ; ; # σ8.
+‌ᡑ🄀ڄ.-𐫄𑲤; ‌ᡑ🄀ڄ.-𐫄𑲤; [B1, C1, P1, V3, V6]; xn--9ib722gvtfi563c.xn----ek5i065b; ; xn--9ib722gbw95a.xn----ek5i065b; [B1, B5, B6, P1, V3, V6] # ᡑ🄀ڄ.-𐫄𑲤
+‌ᡑ0.ڄ.-𐫄𑲤; ; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; xn--0-o7j.xn--9ib.xn----ek5i065b; [B1, V3] # ᡑ0.ڄ.-𐫄𑲤
+xn--0-o7j.xn--9ib.xn----ek5i065b; ᡑ0.ڄ.-𐫄𑲤; [B1, V3]; xn--0-o7j.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤
+xn--0-o7j263b.xn--9ib.xn----ek5i065b; ‌ᡑ0.ڄ.-𐫄𑲤; [B1, C1, V3]; xn--0-o7j263b.xn--9ib.xn----ek5i065b; ; ; # ᡑ0.ڄ.-𐫄𑲤
+xn--9ib722gbw95a.xn----ek5i065b; ᡑ🄀ڄ.-𐫄𑲤; [B1, B5, B6, V3, V6]; xn--9ib722gbw95a.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤
+xn--9ib722gvtfi563c.xn----ek5i065b; ‌ᡑ🄀ڄ.-𐫄𑲤; [B1, C1, V3, V6]; xn--9ib722gvtfi563c.xn----ek5i065b; ; ; # ᡑ🄀ڄ.-𐫄𑲤
+𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, P1, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+𖠍。𐪿넯򞵲; 𖠍.𐪿넯򞵲; [B2, B3, P1, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+xn--4e9e.xn--l60bj21opd57g; 𖠍.𐪿넯򞵲; [B2, B3, V6]; xn--4e9e.xn--l60bj21opd57g; ; ; # 𖠍.넯
+᠇Ⴘ。؃Ⴈ𝆊; ᠇Ⴘ.؃Ⴈ𝆊; [B1, P1, V6]; xn--wnd558a.xn--lfb465c1v87a; ; ; # ᠇Ⴘ.Ⴈ𝆊
+᠇ⴘ。؃ⴈ𝆊; ᠇ⴘ.؃ⴈ𝆊; [B1, P1, V6]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊
+xn--d6e009h.xn--lfb290rfu3z; ᠇ⴘ.؃ⴈ𝆊; [B1, V6]; xn--d6e009h.xn--lfb290rfu3z; ; ; # ᠇ⴘ.ⴈ𝆊
+xn--wnd558a.xn--lfb465c1v87a; ᠇Ⴘ.؃Ⴈ𝆊; [B1, V6]; xn--wnd558a.xn--lfb465c1v87a; ; ; # ᠇Ⴘ.Ⴈ𝆊
+⒚󠋑𞤰。牣٧Ⴜᣥ; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+19.󠋑𞤰。牣٧Ⴜᣥ; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+19.󠋑𞤰。牣٧ⴜᣥ; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.󠋑𞤎。牣٧Ⴜᣥ; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+19.󠋑𞤎。牣٧ⴜᣥ; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.xn--oe6h75760c.xn--gib285gtxo2l9d; 19.󠋑𞤰.牣٧ⴜᣥ; [B1, B5, V6]; 19.xn--oe6h75760c.xn--gib285gtxo2l9d; ; ; # 19.𞤰.牣٧ⴜᣥ
+19.xn--oe6h75760c.xn--gib404ccxgh00h; 19.󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, V6]; 19.xn--oe6h75760c.xn--gib404ccxgh00h; ; ; # 19.𞤰.牣٧Ⴜᣥ
+⒚󠋑𞤰。牣٧ⴜᣥ; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+⒚󠋑𞤎。牣٧Ⴜᣥ; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+⒚󠋑𞤎。牣٧ⴜᣥ; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, P1, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+xn--cthy466n29j3e.xn--gib285gtxo2l9d; ⒚󠋑𞤰.牣٧ⴜᣥ; [B1, B5, V6]; xn--cthy466n29j3e.xn--gib285gtxo2l9d; ; ; # ⒚𞤰.牣٧ⴜᣥ
+xn--cthy466n29j3e.xn--gib404ccxgh00h; ⒚󠋑𞤰.牣٧Ⴜᣥ; [B1, B5, V6]; xn--cthy466n29j3e.xn--gib404ccxgh00h; ; ; # ⒚𞤰.牣٧Ⴜᣥ
+-𐋱𐰽⒈.Ⴓ; ; [B1, P1, V3, V6]; xn----ecp0206g90h.xn--rnd; ; ; # -𐋱𐰽⒈.Ⴓ
+-𐋱𐰽1..Ⴓ; ; [B1, P1, V3, V6, X4_2]; xn---1-895nq11a..xn--rnd; [B1, P1, V3, V6, A4_2]; ; # -𐋱𐰽1..Ⴓ
+-𐋱𐰽1..ⴓ; ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ
+xn---1-895nq11a..xn--blj; -𐋱𐰽1..ⴓ; [B1, V3, X4_2]; xn---1-895nq11a..xn--blj; [B1, V3, A4_2]; ; # -𐋱𐰽1..ⴓ
+xn---1-895nq11a..xn--rnd; -𐋱𐰽1..Ⴓ; [B1, V3, V6, X4_2]; xn---1-895nq11a..xn--rnd; [B1, V3, V6, A4_2]; ; # -𐋱𐰽1..Ⴓ
+-𐋱𐰽⒈.ⴓ; ; [B1, P1, V3, V6]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ
+xn----ecp0206g90h.xn--blj; -𐋱𐰽⒈.ⴓ; [B1, V3, V6]; xn----ecp0206g90h.xn--blj; ; ; # -𐋱𐰽⒈.ⴓ
+xn----ecp0206g90h.xn--rnd; -𐋱𐰽⒈.Ⴓ; [B1, V3, V6]; xn----ecp0206g90h.xn--rnd; ; ; # -𐋱𐰽⒈.Ⴓ
+‌긃.榶-; ; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶-
+‌긃.榶-; ‌긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; xn--ej0b.xn----d87b; [V3] # 긃.榶-
+xn--ej0b.xn----d87b; 긃.榶-; [V3]; xn--ej0b.xn----d87b; ; ; # 긃.榶-
+xn--0ug3307c.xn----d87b; ‌긃.榶-; [C1, V3]; xn--0ug3307c.xn----d87b; ; ; # 긃.榶-
+뉓泓𜵽.্‍; ; [P1, V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓.্
+뉓泓𜵽.্‍; 뉓泓𜵽.্‍; [P1, V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; xn--lwwp69lqs7m.xn--b7b; # 뉓泓.্
+xn--lwwp69lqs7m.xn--b7b; 뉓泓𜵽.্; [V5, V6]; xn--lwwp69lqs7m.xn--b7b; ; ; # 뉓泓.্
+xn--lwwp69lqs7m.xn--b7b605i; 뉓泓𜵽.্‍; [V5, V6]; xn--lwwp69lqs7m.xn--b7b605i; ; ; # 뉓泓.্
+‍𐹴ß。ິ⭵񪅌; ‍𐹴ß.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ß.ິ
+‍𐹴ß。ິ⭵񪅌; ‍𐹴ß.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ß.ິ
+‍𐹴SS。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴Ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+xn--ss-ti3o.xn--57c638l8774i; 𐹴ss.ິ⭵񪅌; [B1, V5, V6]; xn--ss-ti3o.xn--57c638l8774i; ; ; # 𐹴ss.ິ
+xn--ss-l1t5169j.xn--57c638l8774i; ‍𐹴ss.ິ⭵񪅌; [B1, C2, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; ; # 𐹴ss.ິ
+xn--zca770nip7n.xn--57c638l8774i; ‍𐹴ß.ິ⭵񪅌; [B1, C2, V5, V6]; xn--zca770nip7n.xn--57c638l8774i; ; ; # 𐹴ß.ິ
+‍𐹴SS。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+‍𐹴Ss。ິ⭵񪅌; ‍𐹴ss.ິ⭵񪅌; [B1, C2, P1, V5, V6]; xn--ss-l1t5169j.xn--57c638l8774i; ; xn--ss-ti3o.xn--57c638l8774i; [B1, P1, V5, V6] # 𐹴ss.ິ
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᭄.᮪-≮≠; ᭄.᮪-≮≠; [P1, V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+xn--1uf.xn----nmlz65aub; ᭄.᮪-≮≠; [V5, V6]; xn--1uf.xn----nmlz65aub; ; ; # ᭄.᮪-≮≠
+᯳Ⴑᅟ.𑄴Ⅎ; ᯳Ⴑᅟ.𑄴Ⅎ; [P1, V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳Ⴑᅟ.𑄴Ⅎ; ; [P1, V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳ⴑᅟ.𑄴ⅎ; ; [P1, V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+᯳Ⴑᅟ.𑄴ⅎ; ; [P1, V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+xn--pnd26a55x.xn--73g3065g; ᯳Ⴑᅟ.𑄴ⅎ; [V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+xn--osd925cvyn.xn--73g3065g; ᯳ⴑᅟ.𑄴ⅎ; [V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+xn--pnd26a55x.xn--f3g7465g; ᯳Ⴑᅟ.𑄴Ⅎ; [V5, V6]; xn--pnd26a55x.xn--f3g7465g; ; ; # ᯳Ⴑ.𑄴Ⅎ
+᯳ⴑᅟ.𑄴ⅎ; ᯳ⴑᅟ.𑄴ⅎ; [P1, V5, V6]; xn--osd925cvyn.xn--73g3065g; ; ; # ᯳ⴑ.𑄴ⅎ
+᯳Ⴑᅟ.𑄴ⅎ; ᯳Ⴑᅟ.𑄴ⅎ; [P1, V5, V6]; xn--pnd26a55x.xn--73g3065g; ; ; # ᯳Ⴑ.𑄴ⅎ
+𜉆。Ⴃ𐴣𐹹똯; 𜉆.Ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𜉆。Ⴃ𐴣𐹹똯; 𜉆.Ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+𜉆。ⴃ𐴣𐹹똯; 𜉆.ⴃ𐴣𐹹똯; [B5, P1, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+xn--187g.xn--ukjy205b8rscdeb; 𜉆.ⴃ𐴣𐹹똯; [B5, V6]; xn--187g.xn--ukjy205b8rscdeb; ; ; # .ⴃ𐴣𐹹똯
+xn--187g.xn--bnd4785f8r8bdeb; 𜉆.Ⴃ𐴣𐹹똯; [B5, V6]; xn--187g.xn--bnd4785f8r8bdeb; ; ; # .Ⴃ𐴣𐹹똯
+𐫀。⳻󠙾󠄷ㅤ; 𐫀.⳻󠙾ㅤ; [B1, P1, V6]; xn--pw9c.xn--mkj83l4v899a; ; ; # 𐫀.⳻
+𐫀。⳻󠙾󠄷ᅠ; 𐫀.⳻󠙾ᅠ; [B1, P1, V6]; xn--pw9c.xn--psd742lxt32w; ; ; # 𐫀.⳻
+xn--pw9c.xn--psd742lxt32w; 𐫀.⳻󠙾ᅠ; [B1, V6]; xn--pw9c.xn--psd742lxt32w; ; ; # 𐫀.⳻
+xn--pw9c.xn--mkj83l4v899a; 𐫀.⳻󠙾ㅤ; [B1, V6]; xn--pw9c.xn--mkj83l4v899a; ; ; # 𐫀.⳻
+ޚ⾇.ܞ-𐋰; ޚ舛.ܞ-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+ޚ舛.ܞ-𐋰; ; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+xn--7qb6383d.xn----20c3154q; ޚ舛.ܞ-𐋰; [B2, B3]; xn--7qb6383d.xn----20c3154q; ; ; # ޚ舛.ܞ-𐋰
+Ⴉ猕󹛫≮.︒; Ⴉ猕󹛫≮.︒; [P1, V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+Ⴉ猕󹛫≮.︒; Ⴉ猕󹛫≮.︒; [P1, V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+Ⴉ猕󹛫≮.。; Ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--hnd212gz32d54x5r..; [P1, V6, A4_2]; ; # Ⴉ猕≮..
+Ⴉ猕󹛫≮.。; Ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--hnd212gz32d54x5r..; [P1, V6, A4_2]; ; # Ⴉ猕≮..
+ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--gdh892bbz0d5438s..; [P1, V6, A4_2]; ; # ⴉ猕≮..
+ⴉ猕󹛫≮.。; ⴉ猕󹛫≮..; [P1, V6, X4_2]; xn--gdh892bbz0d5438s..; [P1, V6, A4_2]; ; # ⴉ猕≮..
+xn--gdh892bbz0d5438s..; ⴉ猕󹛫≮..; [V6, X4_2]; xn--gdh892bbz0d5438s..; [V6, A4_2]; ; # ⴉ猕≮..
+xn--hnd212gz32d54x5r..; Ⴉ猕󹛫≮..; [V6, X4_2]; xn--hnd212gz32d54x5r..; [V6, A4_2]; ; # Ⴉ猕≮..
+ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [P1, V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+ⴉ猕󹛫≮.︒; ⴉ猕󹛫≮.︒; [P1, V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+xn--gdh892bbz0d5438s.xn--y86c; ⴉ猕󹛫≮.︒; [V6]; xn--gdh892bbz0d5438s.xn--y86c; ; ; # ⴉ猕≮.︒
+xn--hnd212gz32d54x5r.xn--y86c; Ⴉ猕󹛫≮.︒; [V6]; xn--hnd212gz32d54x5r.xn--y86c; ; ; # Ⴉ猕≮.︒
+🏮。ث鳳ߢ󠅉; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+🏮。ث鳳ߢ󠅉; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+xn--8m8h.xn--qgb29f6z90a; 🏮.ث鳳ߢ; [B1, B2]; xn--8m8h.xn--qgb29f6z90a; ; ; # 🏮.ث鳳ߢ
+‍𐹶。ß; ‍𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; xn--uo0d.ss; [B1] # 𐹶.ß
+‍𐹶。SS; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+‍𐹶。ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+‍𐹶。Ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; xn--uo0d.ss; [B1] # 𐹶.ss
+xn--uo0d.ss; 𐹶.ss; [B1]; xn--uo0d.ss; ; ; # 𐹶.ss
+xn--1ug9105g.ss; ‍𐹶.ss; [B1, C2]; xn--1ug9105g.ss; ; ; # 𐹶.ss
+xn--1ug9105g.xn--zca; ‍𐹶.ß; [B1, C2]; xn--1ug9105g.xn--zca; ; ; # 𐹶.ß
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+Å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; ; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+xn----1fa1788k.; å둄-.; [V3]; xn----1fa1788k.; ; ; # å둄-.
+xn----1fa1788k.xn--0ug; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; ; # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+å둄-.‌; å둄-.‌; [C1, V3]; xn----1fa1788k.xn--0ug; ; xn----1fa1788k.; [V3] # å둄-.
+゙򬎑ᷗ𞤀.򱲢-॓; ゙򬎑ᷗ𞤢.򱲢-॓; [B1, B6, P1, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+゙򬎑ᷗ𞤢.򱲢-॓; ; [B1, B6, P1, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+xn--veg121fwg63altj9d.xn----eyd92688s; ゙򬎑ᷗ𞤢.򱲢-॓; [B1, B6, V5, V6]; xn--veg121fwg63altj9d.xn----eyd92688s; ; ; # ゙ᷗ𞤢.-॓
+ς.ß񴱄۝⵿; ; [B5, B6, P1, V6]; xn--3xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # ς.ß⵿
+Σ.SS񴱄۝⵿; σ.ss񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+σ.ss񴱄۝⵿; ; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+Σ.ss񴱄۝⵿; σ.ss񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+xn--4xa.xn--ss-y8d4760biv60n; σ.ss񴱄۝⵿; [B5, B6, V6]; xn--4xa.xn--ss-y8d4760biv60n; ; ; # σ.ss⵿
+Σ.ß񴱄۝⵿; σ.ß񴱄۝⵿; [B5, B6, P1, V6]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿
+σ.ß񴱄۝⵿; ; [B5, B6, P1, V6]; xn--4xa.xn--zca281az71b8x73m; ; xn--4xa.xn--ss-y8d4760biv60n; # σ.ß⵿
+xn--4xa.xn--zca281az71b8x73m; σ.ß񴱄۝⵿; [B5, B6, V6]; xn--4xa.xn--zca281az71b8x73m; ; ; # σ.ß⵿
+xn--3xa.xn--zca281az71b8x73m; ς.ß񴱄۝⵿; [B5, B6, V6]; xn--3xa.xn--zca281az71b8x73m; ; ; # ς.ß⵿
+ꡀ𞀟。٫֙; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+ꡀ𞀟。٫֙; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+xn--8b9a1720d.xn--kcb33b; ꡀ𞀟.٫֙; [B1]; xn--8b9a1720d.xn--kcb33b; ; ; # ꡀ𞀟.٫֙
+򈛉‌ࢩ。⧅񘘡-𐭡; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, P1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, P1, V6] # ࢩ.⧅-𐭡
+򈛉‌ࢩ。⧅񘘡-𐭡; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, P1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; xn--yyb56242i.xn----zir1232guu71b; [B1, B5, B6, P1, V6] # ࢩ.⧅-𐭡
+xn--yyb56242i.xn----zir1232guu71b; 򈛉ࢩ.⧅񘘡-𐭡; [B1, B5, B6, V6]; xn--yyb56242i.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡
+xn--yyb780jll63m.xn----zir1232guu71b; 򈛉‌ࢩ.⧅񘘡-𐭡; [B1, B5, B6, C1, V6]; xn--yyb780jll63m.xn----zir1232guu71b; ; ; # ࢩ.⧅-𐭡
+룱‍𰍨‌。𝨖︒; 룱‍𰍨‌.𝨖︒; [C1, C2, P1, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [P1, V5, V6] # 룱𰍨.𝨖︒
+룱‍𰍨‌。𝨖︒; 룱‍𰍨‌.𝨖︒; [C1, C2, P1, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; xn--ct2b0738h.xn--y86cl899a; [P1, V5, V6] # 룱𰍨.𝨖︒
+룱‍𰍨‌。𝨖。; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; xn--ct2b0738h.xn--772h.; [V5] # 룱𰍨.𝨖.
+룱‍𰍨‌。𝨖。; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; xn--ct2b0738h.xn--772h.; [V5] # 룱𰍨.𝨖.
+xn--ct2b0738h.xn--772h.; 룱𰍨.𝨖.; [V5]; xn--ct2b0738h.xn--772h.; ; ; # 룱𰍨.𝨖.
+xn--0ugb3358ili2v.xn--772h.; 룱‍𰍨‌.𝨖.; [C1, C2, V5]; xn--0ugb3358ili2v.xn--772h.; ; ; # 룱𰍨.𝨖.
+xn--ct2b0738h.xn--y86cl899a; 룱𰍨.𝨖︒; [V5, V6]; xn--ct2b0738h.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒
+xn--0ugb3358ili2v.xn--y86cl899a; 룱‍𰍨‌.𝨖︒; [C1, C2, V5, V6]; xn--0ugb3358ili2v.xn--y86cl899a; ; ; # 룱𰍨.𝨖︒
+🄄.᳜⒈ß; 🄄.᳜⒈ß; [P1, V5, V6]; xn--x07h.xn--zca344lmif; ; xn--x07h.xn--ss-k1r094b; # 🄄.᳜⒈ß
+3,.᳜1.ß; ; [P1, V5, V6]; 3,.xn--1-43l.xn--zca; ; 3,.xn--1-43l.ss; # 3,.᳜1.ß
+3,.᳜1.SS; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.᳜1.ss; ; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.᳜1.Ss; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.xn--1-43l.ss; 3,.᳜1.ss; [P1, V5, V6]; 3,.xn--1-43l.ss; ; ; # 3,.᳜1.ss
+3,.xn--1-43l.xn--zca; 3,.᳜1.ß; [P1, V5, V6]; 3,.xn--1-43l.xn--zca; ; ; # 3,.᳜1.ß
+🄄.᳜⒈SS; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+🄄.᳜⒈ss; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+🄄.᳜⒈Ss; 🄄.᳜⒈ss; [P1, V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+xn--x07h.xn--ss-k1r094b; 🄄.᳜⒈ss; [V5, V6]; xn--x07h.xn--ss-k1r094b; ; ; # 🄄.᳜⒈ss
+xn--x07h.xn--zca344lmif; 🄄.᳜⒈ß; [V5, V6]; xn--x07h.xn--zca344lmif; ; ; # 🄄.᳜⒈ß
+񇌍⵿。𞼓򡄨𑐺; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, P1, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+񇌍⵿。𞼓򡄨𑐺; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, P1, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+xn--eoj16016a.xn--0v1d3848a3lr0d; 񇌍⵿.𞼓򡄨𑐺; [B2, B3, V6]; xn--eoj16016a.xn--0v1d3848a3lr0d; ; ; # ⵿.𑐺
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+်्᷽.≠‍㇛; ်्᷽.≠‍㇛; [C2, P1, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; xn--n3b956a9zm.xn--1ch912d; [P1, V5, V6] # ်्᷽.≠㇛
+xn--n3b956a9zm.xn--1ch912d; ်्᷽.≠㇛; [V5, V6]; xn--n3b956a9zm.xn--1ch912d; ; ; # ်्᷽.≠㇛
+xn--n3b956a9zm.xn--1ug63gz5w; ်्᷽.≠‍㇛; [C2, V5, V6]; xn--n3b956a9zm.xn--1ug63gz5w; ; ; # ်्᷽.≠㇛
+Ⴁ𐋨娤.‍̼٢𑖿; ; [B1, C2, P1, V6]; xn--8md2578ag21g.xn--9ta62ngt6aou8t; ; xn--8md2578ag21g.xn--9ta62nrv36a; [B1, P1, V5, V6] # Ⴁ𐋨娤.̼٢𑖿
+ⴁ𐋨娤.‍̼٢𑖿; ; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; xn--skjw75lg29h.xn--9ta62nrv36a; [B1, V5] # ⴁ𐋨娤.̼٢𑖿
+xn--skjw75lg29h.xn--9ta62nrv36a; ⴁ𐋨娤.̼٢𑖿; [B1, V5]; xn--skjw75lg29h.xn--9ta62nrv36a; ; ; # ⴁ𐋨娤.̼٢𑖿
+xn--skjw75lg29h.xn--9ta62ngt6aou8t; ⴁ𐋨娤.‍̼٢𑖿; [B1, C2]; xn--skjw75lg29h.xn--9ta62ngt6aou8t; ; ; # ⴁ𐋨娤.̼٢𑖿
+xn--8md2578ag21g.xn--9ta62nrv36a; Ⴁ𐋨娤.̼٢𑖿; [B1, V5, V6]; xn--8md2578ag21g.xn--9ta62nrv36a; ; ; # Ⴁ𐋨娤.̼٢𑖿
+xn--8md2578ag21g.xn--9ta62ngt6aou8t; Ⴁ𐋨娤.‍̼٢𑖿; [B1, C2, V6]; xn--8md2578ag21g.xn--9ta62ngt6aou8t; ; ; # Ⴁ𐋨娤.̼٢𑖿
+🄀Ⴄ٩ࠠ。⒈ྶß; 🄀Ⴄ٩ࠠ.⒈ྶß; [B1, P1, V6]; xn--iib29f26o6n43c.xn--zca117e3vp; ; xn--iib29f26o6n43c.xn--ss-1sj588o; # 🄀Ⴄ٩ࠠ.⒈ྶß
+0.Ⴄ٩ࠠ。1.ྶß; 0.Ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--zca117e; ; 0.xn--iib29f26o.1.xn--ss-1sj; # 0.Ⴄ٩ࠠ.1.ྶß
+0.ⴄ٩ࠠ。1.ྶß; 0.ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--zca117e; ; 0.xn--iib29fp25e.1.xn--ss-1sj; # 0.ⴄ٩ࠠ.1.ྶß
+0.Ⴄ٩ࠠ。1.ྶSS; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.ⴄ٩ࠠ。1.ྶss; 0.ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss
+0.Ⴄ٩ࠠ。1.ྶSs; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, P1, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.xn--iib29f26o.1.xn--ss-1sj; 0.Ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5, V6]; 0.xn--iib29f26o.1.xn--ss-1sj; ; ; # 0.Ⴄ٩ࠠ.1.ྶss
+0.xn--iib29fp25e.1.xn--ss-1sj; 0.ⴄ٩ࠠ.1.ྶss; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--ss-1sj; ; ; # 0.ⴄ٩ࠠ.1.ྶss
+0.xn--iib29fp25e.1.xn--zca117e; 0.ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5]; 0.xn--iib29fp25e.1.xn--zca117e; ; ; # 0.ⴄ٩ࠠ.1.ྶß
+0.xn--iib29f26o.1.xn--zca117e; 0.Ⴄ٩ࠠ.1.ྶß; [B1, B5, B6, V5, V6]; 0.xn--iib29f26o.1.xn--zca117e; ; ; # 0.Ⴄ٩ࠠ.1.ྶß
+🄀ⴄ٩ࠠ。⒈ྶß; 🄀ⴄ٩ࠠ.⒈ྶß; [B1, P1, V6]; xn--iib29fp25e0219a.xn--zca117e3vp; ; xn--iib29fp25e0219a.xn--ss-1sj588o; # 🄀ⴄ٩ࠠ.⒈ྶß
+🄀Ⴄ٩ࠠ。⒈ྶSS; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+🄀ⴄ٩ࠠ。⒈ྶss; 🄀ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss
+🄀Ⴄ٩ࠠ。⒈ྶSs; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, P1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+xn--iib29f26o6n43c.xn--ss-1sj588o; 🄀Ⴄ٩ࠠ.⒈ྶss; [B1, V6]; xn--iib29f26o6n43c.xn--ss-1sj588o; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶss
+xn--iib29fp25e0219a.xn--ss-1sj588o; 🄀ⴄ٩ࠠ.⒈ྶss; [B1, V6]; xn--iib29fp25e0219a.xn--ss-1sj588o; ; ; # 🄀ⴄ٩ࠠ.⒈ྶss
+xn--iib29fp25e0219a.xn--zca117e3vp; 🄀ⴄ٩ࠠ.⒈ྶß; [B1, V6]; xn--iib29fp25e0219a.xn--zca117e3vp; ; ; # 🄀ⴄ٩ࠠ.⒈ྶß
+xn--iib29f26o6n43c.xn--zca117e3vp; 🄀Ⴄ٩ࠠ.⒈ྶß; [B1, V6]; xn--iib29f26o6n43c.xn--zca117e3vp; ; ; # 🄀Ⴄ٩ࠠ.⒈ྶß
+≠.‌-٫; ; [B1, C1, P1, V6]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, P1, V3, V6] # ≠.-٫
+≠.‌-٫; ≠.‌-٫; [B1, C1, P1, V6]; xn--1ch.xn----vqc597q; ; xn--1ch.xn----vqc; [B1, P1, V3, V6] # ≠.-٫
+xn--1ch.xn----vqc; ≠.-٫; [B1, V3, V6]; xn--1ch.xn----vqc; ; ; # ≠.-٫
+xn--1ch.xn----vqc597q; ≠.‌-٫; [B1, C1, V6]; xn--1ch.xn----vqc597q; ; ; # ≠.-٫
+٠۱。󠳶𞠁٥; ٠۱.󠳶𞠁٥; [B1, P1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+٠۱。󠳶𞠁٥; ٠۱.󠳶𞠁٥; [B1, P1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+xn--8hb40a.xn--eib7967vner3e; ٠۱.󠳶𞠁٥; [B1, V6]; xn--8hb40a.xn--eib7967vner3e; ; ; # ٠۱.𞠁٥
+‌٣⒖。󱅉𽷛᯳; ‌٣⒖.󱅉𽷛᯳; [B1, C1, P1, V6]; xn--cib152kwgd.xn--1zf13512buy41d; ; xn--cib675m.xn--1zf13512buy41d; [B1, P1, V6] # ٣⒖.᯳
+‌٣15.。󱅉𽷛᯳; ‌٣15..󱅉𽷛᯳; [B1, C1, P1, V6, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, P1, V6, A4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, P1, V6, A4_2] # ٣15..᯳
+xn--15-gyd..xn--1zf13512buy41d; ٣15..󱅉𽷛᯳; [B1, V6, X4_2]; xn--15-gyd..xn--1zf13512buy41d; [B1, V6, A4_2]; ; # ٣15..᯳
+xn--15-gyd983x..xn--1zf13512buy41d; ‌٣15..󱅉𽷛᯳; [B1, C1, V6, X4_2]; xn--15-gyd983x..xn--1zf13512buy41d; [B1, C1, V6, A4_2]; ; # ٣15..᯳
+xn--cib675m.xn--1zf13512buy41d; ٣⒖.󱅉𽷛᯳; [B1, V6]; xn--cib675m.xn--1zf13512buy41d; ; ; # ٣⒖.᯳
+xn--cib152kwgd.xn--1zf13512buy41d; ‌٣⒖.󱅉𽷛᯳; [B1, C1, V6]; xn--cib152kwgd.xn--1zf13512buy41d; ; ; # ٣⒖.᯳
+᯳.-逋񳦭󙙮; ; [P1, V3, V5, V6]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋
+xn--1zf.xn----483d46987byr50b; ᯳.-逋񳦭󙙮; [V3, V5, V6]; xn--1zf.xn----483d46987byr50b; ; ; # ᯳.-逋
+ݖ。ㅤ‍ς; ݖ.ㅤ‍ς; [C2, P1, V6]; xn--9ob.xn--3xa995lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.ς
+ݖ。ᅠ‍ς; ݖ.ᅠ‍ς; [C2, P1, V6]; xn--9ob.xn--3xa580ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.ς
+ݖ。ᅠ‍Σ; ݖ.ᅠ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa380ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.σ
+ݖ。ᅠ‍σ; ݖ.ᅠ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa380ebol; ; xn--9ob.xn--4xa380e; [P1, V6] # ݖ.σ
+xn--9ob.xn--4xa380e; ݖ.ᅠσ; [V6]; xn--9ob.xn--4xa380e; ; ; # ݖ.σ
+xn--9ob.xn--4xa380ebol; ݖ.ᅠ‍σ; [C2, V6]; xn--9ob.xn--4xa380ebol; ; ; # ݖ.σ
+xn--9ob.xn--3xa580ebol; ݖ.ᅠ‍ς; [C2, V6]; xn--9ob.xn--3xa580ebol; ; ; # ݖ.ς
+ݖ。ㅤ‍Σ; ݖ.ㅤ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa795lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.σ
+ݖ。ㅤ‍σ; ݖ.ㅤ‍σ; [C2, P1, V6]; xn--9ob.xn--4xa795lq2l; ; xn--9ob.xn--4xa574u; [P1, V6] # ݖ.σ
+xn--9ob.xn--4xa574u; ݖ.ㅤσ; [V6]; xn--9ob.xn--4xa574u; ; ; # ݖ.σ
+xn--9ob.xn--4xa795lq2l; ݖ.ㅤ‍σ; [C2, V6]; xn--9ob.xn--4xa795lq2l; ; ; # ݖ.σ
+xn--9ob.xn--3xa995lq2l; ݖ.ㅤ‍ς; [C2, V6]; xn--9ob.xn--3xa995lq2l; ; ; # ݖ.ς
+ᡆႣ。󞢧̕‍‍; ᡆႣ.󞢧̕‍‍; [C2, P1, V6]; xn--bnd320b.xn--5sa649la993427a; ; xn--bnd320b.xn--5sa98523p; [P1, V6] # ᡆႣ.̕
+ᡆႣ。󞢧̕‍‍; ᡆႣ.󞢧̕‍‍; [C2, P1, V6]; xn--bnd320b.xn--5sa649la993427a; ; xn--bnd320b.xn--5sa98523p; [P1, V6] # ᡆႣ.̕
+ᡆⴃ。󞢧̕‍‍; ᡆⴃ.󞢧̕‍‍; [C2, P1, V6]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [P1, V6] # ᡆⴃ.̕
+xn--57e237h.xn--5sa98523p; ᡆⴃ.󞢧̕; [V6]; xn--57e237h.xn--5sa98523p; ; ; # ᡆⴃ.̕
+xn--57e237h.xn--5sa649la993427a; ᡆⴃ.󞢧̕‍‍; [C2, V6]; xn--57e237h.xn--5sa649la993427a; ; ; # ᡆⴃ.̕
+xn--bnd320b.xn--5sa98523p; ᡆႣ.󞢧̕; [V6]; xn--bnd320b.xn--5sa98523p; ; ; # ᡆႣ.̕
+xn--bnd320b.xn--5sa649la993427a; ᡆႣ.󞢧̕‍‍; [C2, V6]; xn--bnd320b.xn--5sa649la993427a; ; ; # ᡆႣ.̕
+ᡆⴃ。󞢧̕‍‍; ᡆⴃ.󞢧̕‍‍; [C2, P1, V6]; xn--57e237h.xn--5sa649la993427a; ; xn--57e237h.xn--5sa98523p; [P1, V6] # ᡆⴃ.̕
+㭄‍ࡏ𑚵.ς𐮮‌‍; 㭄‍ࡏ𑚵.ς𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.ς𐮮‌‍; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.Σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+㭄‍ࡏ𑚵.σ𐮮‌‍; ; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+xn--ewb302xhu1l.xn--4xa0426k; 㭄ࡏ𑚵.σ𐮮; [B5, B6]; xn--ewb302xhu1l.xn--4xa0426k; ; ; # 㭄ࡏ𑚵.σ𐮮
+xn--ewb962jfitku4r.xn--4xa695lda6932v; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; ; # 㭄ࡏ𑚵.σ𐮮
+xn--ewb962jfitku4r.xn--3xa895lda6932v; 㭄‍ࡏ𑚵.ς𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--3xa895lda6932v; ; ; # 㭄ࡏ𑚵.ς𐮮
+㭄‍ࡏ𑚵.Σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+㭄‍ࡏ𑚵.σ𐮮‌‍; 㭄‍ࡏ𑚵.σ𐮮‌‍; [B5, B6, C1, C2]; xn--ewb962jfitku4r.xn--4xa695lda6932v; ; xn--ewb302xhu1l.xn--4xa0426k; [B5, B6] # 㭄ࡏ𑚵.σ𐮮
+឵。𞯸ꡀ🄋; ឵.𞯸ꡀ🄋; [B1, B2, B3, B6, P1, V5, V6]; xn--03e.xn--8b9ar252dngd; ; ; # .ꡀ🄋
+xn--03e.xn--8b9ar252dngd; ឵.𞯸ꡀ🄋; [B1, B2, B3, B6, V5, V6]; xn--03e.xn--8b9ar252dngd; ; ; # .ꡀ🄋
+󐪺暑.⾑٨; 󐪺暑.襾٨; [B5, B6, P1, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+󐪺暑.襾٨; ; [B5, B6, P1, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+xn--tlvq3513e.xn--hib9228d; 󐪺暑.襾٨; [B5, B6, V6]; xn--tlvq3513e.xn--hib9228d; ; ; # 暑.襾٨
+󠄚≯ꡢ。࢑᷿; ≯ꡢ.࢑᷿; [B1, P1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+󠄚≯ꡢ。࢑᷿; ≯ꡢ.࢑᷿; [B1, P1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+xn--hdh7783c.xn--9xb680i; ≯ꡢ.࢑᷿; [B1, V6]; xn--hdh7783c.xn--9xb680i; ; ; # ≯ꡢ.᷿
+ﷃ𮁱୍𐨿.󐧤Ⴗ; كمم𮁱୍𐨿.󐧤Ⴗ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+كمم𮁱୍𐨿.󐧤Ⴗ; ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+كمم𮁱୍𐨿.󐧤ⴗ; ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+xn--fhbea662czx68a2tju.xn--fljz2846h; كمم𮁱୍𐨿.󐧤ⴗ; [B2, B3, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+xn--fhbea662czx68a2tju.xn--vnd55511o; كمم𮁱୍𐨿.󐧤Ⴗ; [B2, B3, V6]; xn--fhbea662czx68a2tju.xn--vnd55511o; ; ; # كمم𮁱୍𐨿.Ⴗ
+ﷃ𮁱୍𐨿.󐧤ⴗ; كمم𮁱୍𐨿.󐧤ⴗ; [B2, B3, P1, V6]; xn--fhbea662czx68a2tju.xn--fljz2846h; ; ; # كمم𮁱୍𐨿.ⴗ
+𞀨。᭄򡛨𞎇; 𞀨.᭄򡛨𞎇; [P1, V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+𞀨。᭄򡛨𞎇; 𞀨.᭄򡛨𞎇; [P1, V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+xn--mi4h.xn--1uf6843smg20c; 𞀨.᭄򡛨𞎇; [V5, V6]; xn--mi4h.xn--1uf6843smg20c; ; ; # 𞀨.᭄
+󠣼‌.𐺰‌ᡟ; 󠣼‌.𐺰‌ᡟ; [B1, B2, B3, C1, P1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, P1, V6] # .𐺰ᡟ
+󠣼‌.𐺰‌ᡟ; ; [B1, B2, B3, C1, P1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; xn--q046e.xn--v8e7227j; [B1, B2, B3, P1, V6] # .𐺰ᡟ
+xn--q046e.xn--v8e7227j; 󠣼.𐺰ᡟ; [B1, B2, B3, V6]; xn--q046e.xn--v8e7227j; ; ; # .𐺰ᡟ
+xn--0ug18531l.xn--v8e340bp21t; 󠣼‌.𐺰‌ᡟ; [B1, B2, B3, C1, V6]; xn--0ug18531l.xn--v8e340bp21t; ; ; # .𐺰ᡟ
+ᢛ󨅟ß.ጧ; ; [P1, V6]; xn--zca562jc642x.xn--p5d; ; xn--ss-7dp66033t.xn--p5d; # ᢛß.ጧ
+ᢛ󨅟SS.ጧ; ᢛ󨅟ss.ጧ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+ᢛ󨅟ss.ጧ; ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+ᢛ󨅟Ss.ጧ; ᢛ󨅟ss.ጧ; [P1, V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+xn--ss-7dp66033t.xn--p5d; ᢛ󨅟ss.ጧ; [V6]; xn--ss-7dp66033t.xn--p5d; ; ; # ᢛss.ጧ
+xn--zca562jc642x.xn--p5d; ᢛ󨅟ß.ጧ; [V6]; xn--zca562jc642x.xn--p5d; ; ; # ᢛß.ጧ
+⮒‌.񒚗‌; ; [C1, P1, V6]; xn--0ugx66b.xn--0ugz2871c; ; xn--b9i.xn--5p9y; [P1, V6] # ⮒.
+xn--b9i.xn--5p9y; ⮒.񒚗; [V6]; xn--b9i.xn--5p9y; ; ; # ⮒.
+xn--0ugx66b.xn--0ugz2871c; ⮒‌.񒚗‌; [C1, V6]; xn--0ugx66b.xn--0ugz2871c; ; ; # ⮒.
+𞤂񹞁𐹯。Ⴜ; 𞤤񹞁𐹯.Ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--0nd; ; ; # 𞤤𐹯.Ⴜ
+𞤤񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+xn--no0dr648a51o3b.xn--klj; 𞤤񹞁𐹯.ⴜ; [B2, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+xn--no0dr648a51o3b.xn--0nd; 𞤤񹞁𐹯.Ⴜ; [B2, V6]; xn--no0dr648a51o3b.xn--0nd; ; ; # 𞤤𐹯.Ⴜ
+𞤂񹞁𐹯。ⴜ; 𞤤񹞁𐹯.ⴜ; [B2, P1, V6]; xn--no0dr648a51o3b.xn--klj; ; ; # 𞤤𐹯.ⴜ
+𐹵⮣‌𑄰。񷴿ﲷ; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, P1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, P1, V6] # 𐹵⮣𑄰.ضم
+𐹵⮣‌𑄰。񷴿ضم; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, P1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; xn--s9i5458e7yb.xn--1gb4a66004i; [B1, B5, B6, P1, V6] # 𐹵⮣𑄰.ضم
+xn--s9i5458e7yb.xn--1gb4a66004i; 𐹵⮣𑄰.񷴿ضم; [B1, B5, B6, V6]; xn--s9i5458e7yb.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم
+xn--0ug586bcj8p7jc.xn--1gb4a66004i; 𐹵⮣‌𑄰.񷴿ضم; [B1, B5, B6, C1, V6]; xn--0ug586bcj8p7jc.xn--1gb4a66004i; ; ; # 𐹵⮣𑄰.ضم
+Ⴒ。デß𞤵్; Ⴒ.デß𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; xn--qnd.xn--ss-9nh3648ahh20b; # Ⴒ.デß𞤵్
+Ⴒ。デß𞤵్; Ⴒ.デß𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; xn--qnd.xn--ss-9nh3648ahh20b; # Ⴒ.デß𞤵్
+ⴒ。デß𞤵్; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్
+ⴒ。デß𞤵్; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; xn--9kj.xn--ss-9nh3648ahh20b; # ⴒ.デß𞤵్
+Ⴒ。デSS𞤓్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSS𞤓్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+ⴒ。デss𞤵్; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+ⴒ。デss𞤵్; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+Ⴒ。デSs𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSs𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+xn--qnd.xn--ss-9nh3648ahh20b; Ⴒ.デss𞤵్; [B5, B6, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+xn--9kj.xn--ss-9nh3648ahh20b; ⴒ.デss𞤵్; [B5, B6]; xn--9kj.xn--ss-9nh3648ahh20b; ; ; # ⴒ.デss𞤵్
+xn--9kj.xn--zca669cmr3a0f28a; ⴒ.デß𞤵్; [B5, B6]; xn--9kj.xn--zca669cmr3a0f28a; ; ; # ⴒ.デß𞤵్
+xn--qnd.xn--zca669cmr3a0f28a; Ⴒ.デß𞤵్; [B5, B6, V6]; xn--qnd.xn--zca669cmr3a0f28a; ; ; # Ⴒ.デß𞤵్
+Ⴒ。デSS𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+Ⴒ。デSS𞤵్; Ⴒ.デss𞤵్; [B5, B6, P1, V6]; xn--qnd.xn--ss-9nh3648ahh20b; ; ; # Ⴒ.デss𞤵్
+𑁿്.7-ߒ; 𑁿്.7-ߒ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+𑁿്.7-ߒ; ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+xn--wxc1283k.xn--7--yue; 𑁿്.7-ߒ; [B1, B3, B6, V5]; xn--wxc1283k.xn--7--yue; ; ; # 𑁿്.7-ߒ
+≯𑜫󠭇.᜴񒞤𑍬ᢧ; ; [P1, V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+≯𑜫󠭇.᜴񒞤𑍬ᢧ; ≯𑜫󠭇.᜴񒞤𑍬ᢧ; [P1, V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ≯𑜫󠭇.᜴񒞤𑍬ᢧ; [V5, V6]; xn--hdhx157g68o0g.xn--c0e65eu616c34o7a; ; ; # ≯𑜫.᜴𑍬ᢧ
+ᷛ򎐙Ⴗ쏔。ށ; ᷛ򎐙Ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ᷛ򎐙Ⴗ쏔。ށ; ᷛ򎐙Ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ᷛ򎐙ⴗ쏔。ށ; ᷛ򎐙ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+ᷛ򎐙ⴗ쏔。ށ; ᷛ򎐙ⴗ쏔.ށ; [B1, P1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+xn--zegy26dw47iy6w2f.xn--iqb; ᷛ򎐙ⴗ쏔.ށ; [B1, V5, V6]; xn--zegy26dw47iy6w2f.xn--iqb; ; ; # ᷛⴗ쏔.ށ
+xn--vnd148d733ky6n9e.xn--iqb; ᷛ򎐙Ⴗ쏔.ށ; [B1, V5, V6]; xn--vnd148d733ky6n9e.xn--iqb; ; ; # ᷛႷ쏔.ށ
+ß。𐋳Ⴌྸ; ß.𐋳Ⴌྸ; [P1, V6]; xn--zca.xn--lgd10cu829c; ; ss.xn--lgd10cu829c; # ß.𐋳Ⴌྸ
+ß。𐋳Ⴌྸ; ß.𐋳Ⴌྸ; [P1, V6]; xn--zca.xn--lgd10cu829c; ; ss.xn--lgd10cu829c; # ß.𐋳Ⴌྸ
+ß。𐋳ⴌྸ; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+SS。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss。𐋳ⴌྸ; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+Ss。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss.xn--lgd10cu829c; ss.𐋳Ⴌྸ; [V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss.xn--lgd921mvv0m; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+ss.𐋳ⴌྸ; ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+SS.𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+Ss.𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+xn--zca.xn--lgd921mvv0m; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ; # ß.𐋳ⴌྸ
+ß.𐋳ⴌྸ; ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+xn--zca.xn--lgd10cu829c; ß.𐋳Ⴌྸ; [V6]; xn--zca.xn--lgd10cu829c; ; ; # ß.𐋳Ⴌྸ
+ß。𐋳ⴌྸ; ß.𐋳ⴌྸ; ; xn--zca.xn--lgd921mvv0m; ; ss.xn--lgd921mvv0m; # ß.𐋳ⴌྸ
+SS。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+ss。𐋳ⴌྸ; ss.𐋳ⴌྸ; ; ss.xn--lgd921mvv0m; ; ; # ss.𐋳ⴌྸ
+Ss。𐋳Ⴌྸ; ss.𐋳Ⴌྸ; [P1, V6]; ss.xn--lgd10cu829c; ; ; # ss.𐋳Ⴌྸ
+-ڞ𐶡.‌⾝্; -ڞ𐶡.‌身্; [B1, C1, P1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, P1, V3, V6] # -ڞ.身্
+-ڞ𐶡.‌身্; ; [B1, C1, P1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; xn----stc7013r.xn--b7b1419d; [B1, P1, V3, V6] # -ڞ.身্
+xn----stc7013r.xn--b7b1419d; -ڞ𐶡.身্; [B1, V3, V6]; xn----stc7013r.xn--b7b1419d; ; ; # -ڞ.身্
+xn----stc7013r.xn--b7b305imj2f; -ڞ𐶡.‌身্; [B1, C1, V3, V6]; xn----stc7013r.xn--b7b305imj2f; ; ; # -ڞ.身্
+😮ݤ𑈵𞀖.💅‍; 😮ݤ𑈵𞀖.💅‍; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅
+😮ݤ𑈵𞀖.💅‍; ; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; xn--opb4277kuc7elqsa.xn--kr8h; [B1] # 😮ݤ𑈵𞀖.💅
+xn--opb4277kuc7elqsa.xn--kr8h; 😮ݤ𑈵𞀖.💅; [B1]; xn--opb4277kuc7elqsa.xn--kr8h; ; ; # 😮ݤ𑈵𞀖.💅
+xn--opb4277kuc7elqsa.xn--1ug5265p; 😮ݤ𑈵𞀖.💅‍; [B1, C2]; xn--opb4277kuc7elqsa.xn--1ug5265p; ; ; # 😮ݤ𑈵𞀖.💅
+ࣲ‍꙳ܒ.ᢏ‌󠍄; ; [B1, B6, C1, C2, P1, V5, V6]; xn--cnb37g904be26j.xn--89e849ax9363a; ; xn--cnb37gdy00a.xn--89e02253p; [B1, B6, P1, V5, V6] # ࣲ꙳ܒ.ᢏ
+xn--cnb37gdy00a.xn--89e02253p; ࣲ꙳ܒ.ᢏ󠍄; [B1, B6, V5, V6]; xn--cnb37gdy00a.xn--89e02253p; ; ; # ࣲ꙳ܒ.ᢏ
+xn--cnb37g904be26j.xn--89e849ax9363a; ࣲ‍꙳ܒ.ᢏ‌󠍄; [B1, B6, C1, C2, V5, V6]; xn--cnb37g904be26j.xn--89e849ax9363a; ; ; # ࣲ꙳ܒ.ᢏ
+Ⴑ.ڿ𞯓ᠲ; Ⴑ.ڿ𞯓ᠲ; [B2, B3, P1, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+Ⴑ.ڿ𞯓ᠲ; ; [B2, B3, P1, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+ⴑ.ڿ𞯓ᠲ; ; [B2, B3, P1, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+xn--8kj.xn--ykb840gd555a; ⴑ.ڿ𞯓ᠲ; [B2, B3, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+xn--pnd.xn--ykb840gd555a; Ⴑ.ڿ𞯓ᠲ; [B2, B3, V6]; xn--pnd.xn--ykb840gd555a; ; ; # Ⴑ.ڿᠲ
+ⴑ.ڿ𞯓ᠲ; ⴑ.ڿ𞯓ᠲ; [B2, B3, P1, V6]; xn--8kj.xn--ykb840gd555a; ; ; # ⴑ.ڿᠲ
+ᩚ𛦝్。𚝬𝟵; ᩚ𛦝్.𚝬9; [P1, V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+ᩚ𛦝్。𚝬9; ᩚ𛦝్.𚝬9; [P1, V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+xn--lqc703ebm93a.xn--9-000p; ᩚ𛦝్.𚝬9; [V5, V6]; xn--lqc703ebm93a.xn--9-000p; ; ; # ᩚ్.9
+‌ڠ𿺆𝟗。Ⴣ꒘ﳐ񐘖; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; [B2, B5, P1, V6] # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆9。Ⴣ꒘مخ񐘖; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; [B2, B5, P1, V6] # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆9。ⴣ꒘مخ񐘖; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, P1, V6] # ڠ9.ⴣ꒘مخ
+xn--9-vtc42319e.xn--tgb9bz87p833hw316c; ڠ𿺆9.ⴣ꒘مخ񐘖; [B2, B5, V6]; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ
+xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; ; # ڠ9.ⴣ꒘مخ
+xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; ڠ𿺆9.Ⴣ꒘مخ񐘖; [B2, B5, V6]; xn--9-vtc42319e.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ
+xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ‌ڠ𿺆9.Ⴣ꒘مخ񐘖; [B1, B5, C1, V6]; xn--9-vtc736qts91g.xn--tgb9bz61cfn8mw3t2c; ; ; # ڠ9.Ⴣ꒘مخ
+‌ڠ𿺆𝟗。ⴣ꒘ﳐ񐘖; ‌ڠ𿺆9.ⴣ꒘مخ񐘖; [B1, B5, C1, P1, V6]; xn--9-vtc736qts91g.xn--tgb9bz87p833hw316c; ; xn--9-vtc42319e.xn--tgb9bz87p833hw316c; [B2, B5, P1, V6] # ڠ9.ⴣ꒘مخ
+ᡖ。̟񗛨ஂ-; ᡖ.̟񗛨ஂ-; [P1, V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+ᡖ。̟񗛨ஂ-; ᡖ.̟񗛨ஂ-; [P1, V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+xn--m8e.xn----mdb555dkk71m; ᡖ.̟񗛨ஂ-; [V3, V5, V6]; xn--m8e.xn----mdb555dkk71m; ; ; # ᡖ.̟ஂ-
+𞠠浘。絧𞀀; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀
+xn--e0wp491f.xn--ud0a3573e; 𞠠浘.絧𞀀; [B2, B3]; xn--e0wp491f.xn--ud0a3573e; ; ; # 𞠠浘.絧𞀀
+֖Ⴋ.𝟳≯︒︊; ֖Ⴋ.7≯︒; [P1, V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+֖Ⴋ.𝟳≯︒︊; ֖Ⴋ.7≯︒; [P1, V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+֖Ⴋ.7≯。︊; ֖Ⴋ.7≯.; [P1, V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖Ⴋ.7≯。︊; ֖Ⴋ.7≯.; [P1, V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖ⴋ.7≯。︊; ֖ⴋ.7≯.; [P1, V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+֖ⴋ.7≯。︊; ֖ⴋ.7≯.; [P1, V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+xn--hcb613r.xn--7-pgo.; ֖ⴋ.7≯.; [V5, V6]; xn--hcb613r.xn--7-pgo.; ; ; # ֖ⴋ.7≯.
+xn--hcb887c.xn--7-pgo.; ֖Ⴋ.7≯.; [V5, V6]; xn--hcb887c.xn--7-pgo.; ; ; # ֖Ⴋ.7≯.
+֖ⴋ.𝟳≯︒︊; ֖ⴋ.7≯︒; [P1, V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+֖ⴋ.𝟳≯︒︊; ֖ⴋ.7≯︒; [P1, V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+xn--hcb613r.xn--7-pgoy530h; ֖ⴋ.7≯︒; [V5, V6]; xn--hcb613r.xn--7-pgoy530h; ; ; # ֖ⴋ.7≯︒
+xn--hcb887c.xn--7-pgoy530h; ֖Ⴋ.7≯︒; [V5, V6]; xn--hcb887c.xn--7-pgoy530h; ; ; # ֖Ⴋ.7≯︒
+‍F𑓂。󠺨︒ݾ𐹢; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, P1, V6] # f𑓂.︒ݾ𐹢
+‍F𑓂。󠺨。ݾ𐹢; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, P1, V6] # f𑓂..ݾ𐹢
+‍f𑓂。󠺨。ݾ𐹢; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; xn--f-kq9i.xn--7656e.xn--fqb4175k; [B1, P1, V6] # f𑓂..ݾ𐹢
+xn--f-kq9i.xn--7656e.xn--fqb4175k; f𑓂.󠺨.ݾ𐹢; [B1, V6]; xn--f-kq9i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢
+xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ‍f𑓂.󠺨.ݾ𐹢; [B1, C2, V6]; xn--f-tgn9761i.xn--7656e.xn--fqb4175k; ; ; # f𑓂..ݾ𐹢
+‍f𑓂。󠺨︒ݾ𐹢; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, P1, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; xn--f-kq9i.xn--fqb1637j8hky9452a; [B1, P1, V6] # f𑓂.︒ݾ𐹢
+xn--f-kq9i.xn--fqb1637j8hky9452a; f𑓂.󠺨︒ݾ𐹢; [B1, V6]; xn--f-kq9i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢
+xn--f-tgn9761i.xn--fqb1637j8hky9452a; ‍f𑓂.󠺨︒ݾ𐹢; [B1, C2, V6]; xn--f-tgn9761i.xn--fqb1637j8hky9452a; ; ; # f𑓂.︒ݾ𐹢
+ࡅ🄇𐼗︒。𐹻𑜫; ࡅ🄇𐼗︒.𐹻𑜫; [B1, B3, P1, V6]; xn--3vb4696jpxkjh7s.xn--zo0di2m; ; ; # ࡅ🄇𐼗︒.𐹻𑜫
+ࡅ6,𐼗。。𐹻𑜫; ࡅ6,𐼗..𐹻𑜫; [B1, P1, V6, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, P1, V6, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫
+xn--6,-r4e4420y..xn--zo0di2m; ࡅ6,𐼗..𐹻𑜫; [B1, P1, V6, X4_2]; xn--6,-r4e4420y..xn--zo0di2m; [B1, P1, V6, A4_2]; ; # ࡅ6,𐼗..𐹻𑜫
+xn--3vb4696jpxkjh7s.xn--zo0di2m; ࡅ🄇𐼗︒.𐹻𑜫; [B1, B3, V6]; xn--3vb4696jpxkjh7s.xn--zo0di2m; ; ; # ࡅ🄇𐼗︒.𐹻𑜫
+𐹈.᷀𑈱𐦭; ; [B1, P1, V5, V6]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭
+xn--jn0d.xn--7dg0871h3lf; 𐹈.᷀𑈱𐦭; [B1, V5, V6]; xn--jn0d.xn--7dg0871h3lf; ; ; # .᷀𑈱𐦭
+Ⴂ䠺。𞤃񅏎󙮦ړ; Ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--9md875z.xn--pjb9818vg4xno967d; ; ; # Ⴂ䠺.𞤥ړ
+ⴂ䠺。𞤥񅏎󙮦ړ; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+xn--tkj638f.xn--pjb9818vg4xno967d; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+xn--9md875z.xn--pjb9818vg4xno967d; Ⴂ䠺.𞤥񅏎󙮦ړ; [B2, V6]; xn--9md875z.xn--pjb9818vg4xno967d; ; ; # Ⴂ䠺.𞤥ړ
+ⴂ䠺。𞤃񅏎󙮦ړ; ⴂ䠺.𞤥񅏎󙮦ړ; [B2, P1, V6]; xn--tkj638f.xn--pjb9818vg4xno967d; ; ; # ⴂ䠺.𞤥ړ
+🄇伐︒.𜙚꣄; ; [P1, V6]; xn--woqs083bel0g.xn--0f9ao925c; ; ; # 🄇伐︒.꣄
+6,伐。.𜙚꣄; 6,伐..𜙚꣄; [P1, V6, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [P1, V6, A4_2]; ; # 6,伐..꣄
+xn--6,-7i3c..xn--0f9ao925c; 6,伐..𜙚꣄; [P1, V6, X4_2]; xn--6,-7i3c..xn--0f9ao925c; [P1, V6, A4_2]; ; # 6,伐..꣄
+xn--woqs083bel0g.xn--0f9ao925c; 🄇伐︒.𜙚꣄; [V6]; xn--woqs083bel0g.xn--0f9ao925c; ; ; # 🄇伐︒.꣄
+‍𐹠꯭。‍𐫓Ⴚ𑂹; ‍𐹠꯭.‍𐫓Ⴚ𑂹; [B1, C2, P1, V6]; xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ; xn--429az70n29i.xn--ynd3619jqyd; [B1, B2, B3, P1, V6] # 𐹠꯭.𐫓Ⴚ𑂹
+‍𐹠꯭。‍𐫓ⴚ𑂹; ‍𐹠꯭.‍𐫓ⴚ𑂹; [B1, C2, P1, V6]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; xn--429az70n29i.xn--ilj7702eqyd; [B1, B2, B3, P1, V6] # 𐹠꯭.𐫓ⴚ𑂹
+xn--429az70n29i.xn--ilj7702eqyd; 𐹠꯭.𐫓ⴚ𑂹; [B1, B2, B3, V6]; xn--429az70n29i.xn--ilj7702eqyd; ; ; # 𐹠꯭.𐫓ⴚ𑂹
+xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ‍𐹠꯭.‍𐫓ⴚ𑂹; [B1, C2, V6]; xn--1ugz126coy7bdbm.xn--1ug062chv7ov6e; ; ; # 𐹠꯭.𐫓ⴚ𑂹
+xn--429az70n29i.xn--ynd3619jqyd; 𐹠꯭.𐫓Ⴚ𑂹; [B1, B2, B3, V6]; xn--429az70n29i.xn--ynd3619jqyd; ; ; # 𐹠꯭.𐫓Ⴚ𑂹
+xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ‍𐹠꯭.‍𐫓Ⴚ𑂹; [B1, C2, V6]; xn--1ugz126coy7bdbm.xn--ynd959evs1pv6e; ; ; # 𐹠꯭.𐫓Ⴚ𑂹
+󠆠.񷐴󌟈; .񷐴󌟈; [P1, V6, X4_2]; .xn--rx21bhv12i; [P1, V6, A4_2]; ; # .
+󠆠.񷐴󌟈; .񷐴󌟈; [P1, V6, X4_2]; .xn--rx21bhv12i; [P1, V6, A4_2]; ; # .
+.xn--rx21bhv12i; .񷐴󌟈; [V6, X4_2]; .xn--rx21bhv12i; [V6, A4_2]; ; # .
+𐫃‌Ⴆ.≠𞷙; ; [B1, B2, B3, C1, P1, V6]; xn--end799ekr1p.xn--1ch2802p; ; xn--end1719j.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃Ⴆ.≠
+𐫃‌Ⴆ.≠𞷙; 𐫃‌Ⴆ.≠𞷙; [B1, B2, B3, C1, P1, V6]; xn--end799ekr1p.xn--1ch2802p; ; xn--end1719j.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃Ⴆ.≠
+𐫃‌ⴆ.≠𞷙; 𐫃‌ⴆ.≠𞷙; [B1, B2, B3, C1, P1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃ⴆ.≠
+𐫃‌ⴆ.≠𞷙; ; [B1, B2, B3, C1, P1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; xn--xkjz802e.xn--1ch2802p; [B1, B2, B3, P1, V6] # 𐫃ⴆ.≠
+xn--xkjz802e.xn--1ch2802p; 𐫃ⴆ.≠𞷙; [B1, B2, B3, V6]; xn--xkjz802e.xn--1ch2802p; ; ; # 𐫃ⴆ.≠
+xn--0ug132csv7o.xn--1ch2802p; 𐫃‌ⴆ.≠𞷙; [B1, B2, B3, C1, V6]; xn--0ug132csv7o.xn--1ch2802p; ; ; # 𐫃ⴆ.≠
+xn--end1719j.xn--1ch2802p; 𐫃Ⴆ.≠𞷙; [B1, B2, B3, V6]; xn--end1719j.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠
+xn--end799ekr1p.xn--1ch2802p; 𐫃‌Ⴆ.≠𞷙; [B1, B2, B3, C1, V6]; xn--end799ekr1p.xn--1ch2802p; ; ; # 𐫃Ⴆ.≠
+󠁲𙩢𝟥ꘌ.ࡁ; 󠁲𙩢3ꘌ.ࡁ; [B1, P1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+󠁲𙩢3ꘌ.ࡁ; ; [B1, P1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+xn--3-0g3es485d8i15h.xn--zvb; 󠁲𙩢3ꘌ.ࡁ; [B1, V6]; xn--3-0g3es485d8i15h.xn--zvb; ; ; # 3ꘌ.ࡁ
+-.ᢆ󡲣-; ; [P1, V3, V5, V6]; -.xn----pbkx6497q; ; ; # -.ᢆ-
+-.xn----pbkx6497q; -.ᢆ󡲣-; [V3, V5, V6]; -.xn----pbkx6497q; ; ; # -.ᢆ-
+󲚗‌。‌𞰆ς; 󲚗‌.‌𞰆ς; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .ς
+󲚗‌。‌𞰆ς; 󲚗‌.‌𞰆ς; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .ς
+󲚗‌。‌𞰆Σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+󲚗‌。‌𞰆σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+xn--qp42f.xn--4xa3011w; 󲚗.𞰆σ; [B2, B3, V6]; xn--qp42f.xn--4xa3011w; ; ; # .σ
+xn--0ug76062m.xn--4xa595lhn92a; 󲚗‌.‌𞰆σ; [B1, B6, C1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; ; # .σ
+xn--0ug76062m.xn--3xa795lhn92a; 󲚗‌.‌𞰆ς; [B1, B6, C1, V6]; xn--0ug76062m.xn--3xa795lhn92a; ; ; # .ς
+󲚗‌。‌𞰆Σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+󲚗‌。‌𞰆σ; 󲚗‌.‌𞰆σ; [B1, B6, C1, P1, V6]; xn--0ug76062m.xn--4xa595lhn92a; ; xn--qp42f.xn--4xa3011w; [B2, B3, P1, V6] # .σ
+堕𑓂ᬂ。𐮇𞤽‌-; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽-
+堕𑓂ᬂ。𐮇𞤛‌-; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; xn--5sf345zdk8h.xn----iv5iw606c; [B3, V3] # 堕𑓂ᬂ.𐮇𞤽-
+xn--5sf345zdk8h.xn----iv5iw606c; 堕𑓂ᬂ.𐮇𞤽-; [B3, V3]; xn--5sf345zdk8h.xn----iv5iw606c; ; ; # 堕𑓂ᬂ.𐮇𞤽-
+xn--5sf345zdk8h.xn----rgnt157hwl9g; 堕𑓂ᬂ.𐮇𞤽‌-; [B3, C1, V3]; xn--5sf345zdk8h.xn----rgnt157hwl9g; ; ; # 堕𑓂ᬂ.𐮇𞤽-
+𐹶𑁆ᡕ𞤢。ᡥςتς; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤢。ᡥςتς; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤀。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥσتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+xn--l8e1317j1ebz456b.xn--4xaa85plx4a; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+xn--l8e1317j1ebz456b.xn--3xaa16plx4a; 𐹶𑁆ᡕ𞤢.ᡥςتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xaa16plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥςتς
+𐹶𑁆ᡕ𞤀。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥσتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥσتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+xn--l8e1317j1ebz456b.xn--3xab95plx4a; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥΣتΣ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتσ; 𐹶𑁆ᡕ𞤢.ᡥσتσ; [B1, B5]; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; ; ; # 𐹶𑁆ᡕ𞤢.ᡥσتσ
+𐹶𑁆ᡕ𞤢。ᡥΣتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+𐹶𑁆ᡕ𞤢。ᡥσتς; 𐹶𑁆ᡕ𞤢.ᡥσتς; [B1, B5]; xn--l8e1317j1ebz456b.xn--3xab95plx4a; ; xn--l8e1317j1ebz456b.xn--4xaa85plx4a; # 𐹶𑁆ᡕ𞤢.ᡥσتς
+󏒰.-𝟻ß; 󏒰.-5ß; [P1, V3, V6]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß
+󏒰.-5ß; ; [P1, V3, V6]; xn--t960e.xn---5-hia; ; xn--t960e.-5ss; # .-5ß
+󏒰.-5SS; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-5ss; ; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+xn--t960e.-5ss; 󏒰.-5ss; [V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+xn--t960e.xn---5-hia; 󏒰.-5ß; [V3, V6]; xn--t960e.xn---5-hia; ; ; # .-5ß
+󏒰.-𝟻SS; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-𝟻ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-𝟻Ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+󏒰.-5Ss; 󏒰.-5ss; [P1, V3, V6]; xn--t960e.-5ss; ; ; # .-5ss
+‍𐨿.🤒Ⴥ򑮶; ; [C2, P1, V6]; xn--1ug9533g.xn--9nd3211w0gz4b; ; xn--0s9c.xn--9nd3211w0gz4b; [P1, V5, V6] # 𐨿.🤒Ⴥ
+‍𐨿.🤒ⴥ򑮶; ; [C2, P1, V6]; xn--1ug9533g.xn--tljz038l0gz4b; ; xn--0s9c.xn--tljz038l0gz4b; [P1, V5, V6] # 𐨿.🤒ⴥ
+xn--0s9c.xn--tljz038l0gz4b; 𐨿.🤒ⴥ򑮶; [V5, V6]; xn--0s9c.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ
+xn--1ug9533g.xn--tljz038l0gz4b; ‍𐨿.🤒ⴥ򑮶; [C2, V6]; xn--1ug9533g.xn--tljz038l0gz4b; ; ; # 𐨿.🤒ⴥ
+xn--0s9c.xn--9nd3211w0gz4b; 𐨿.🤒Ⴥ򑮶; [V5, V6]; xn--0s9c.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ
+xn--1ug9533g.xn--9nd3211w0gz4b; ‍𐨿.🤒Ⴥ򑮶; [C2, V6]; xn--1ug9533g.xn--9nd3211w0gz4b; ; ; # 𐨿.🤒Ⴥ
+𵋅。ß𬵩‍; 𵋅.ß𬵩‍; [C2, P1, V6]; xn--ey1p.xn--zca870nz438b; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ß𬵩
+𵋅。SS𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+𵋅。ss𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+𵋅。Ss𬵩‍; 𵋅.ss𬵩‍; [C2, P1, V6]; xn--ey1p.xn--ss-n1tx0508a; ; xn--ey1p.xn--ss-eq36b; [P1, V6] # .ss𬵩
+xn--ey1p.xn--ss-eq36b; 𵋅.ss𬵩; [V6]; xn--ey1p.xn--ss-eq36b; ; ; # .ss𬵩
+xn--ey1p.xn--ss-n1tx0508a; 𵋅.ss𬵩‍; [C2, V6]; xn--ey1p.xn--ss-n1tx0508a; ; ; # .ss𬵩
+xn--ey1p.xn--zca870nz438b; 𵋅.ß𬵩‍; [C2, V6]; xn--ey1p.xn--zca870nz438b; ; ; # .ß𬵩
+‌𭉝。߱́𞹻; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V5] # 𭉝.߱́غ
+‌𭉝。߱́غ; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; xn--634m.xn--lsa46nuub; [B1, V5] # 𭉝.߱́غ
+xn--634m.xn--lsa46nuub; 𭉝.߱́غ; [B1, V5]; xn--634m.xn--lsa46nuub; ; ; # 𭉝.߱́غ
+xn--0ugy003y.xn--lsa46nuub; ‌𭉝.߱́غ; [B1, C1, V5]; xn--0ugy003y.xn--lsa46nuub; ; ; # 𭉝.߱́غ
+𞼌‌𑈶。𐹡; 𞼌‌𑈶.𐹡; [B1, B3, C1, P1, V6]; xn--0ug7946gzpxf.xn--8n0d; ; xn--9g1d1288a.xn--8n0d; [B1, P1, V6] # 𑈶.𐹡
+xn--9g1d1288a.xn--8n0d; 𞼌𑈶.𐹡; [B1, V6]; xn--9g1d1288a.xn--8n0d; ; ; # 𑈶.𐹡
+xn--0ug7946gzpxf.xn--8n0d; 𞼌‌𑈶.𐹡; [B1, B3, C1, V6]; xn--0ug7946gzpxf.xn--8n0d; ; ; # 𑈶.𐹡
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻ς≠; 򇽭‌🜭.𑖿᪻ς≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+xn--zb9h5968x.xn--4xa378i1mfjw7y; 򇽭🜭.𑖿᪻σ≠; [V5, V6]; xn--zb9h5968x.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠
+xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; 򇽭‌🜭.𑖿᪻σ≠; [C1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; ; # 🜭.𑖿᪻σ≠
+xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; 򇽭‌🜭.𑖿᪻ς≠; [C1, V5, V6]; xn--0ug3766p5nm1b.xn--3xa578i1mfjw7y; ; ; # 🜭.𑖿᪻ς≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻Σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+󠅯򇽭‌🜭。𑖿᪻σ≠; 򇽭‌🜭.𑖿᪻σ≠; [C1, P1, V5, V6]; xn--0ug3766p5nm1b.xn--4xa378i1mfjw7y; ; xn--zb9h5968x.xn--4xa378i1mfjw7y; [P1, V5, V6] # 🜭.𑖿᪻σ≠
+⒋。⒈‍򳴢; ⒋.⒈‍򳴢; [C2, P1, V6]; xn--wsh.xn--1ug58o74922a; ; xn--wsh.xn--tsh07994h; [P1, V6] # ⒋.⒈
+4.。1.‍򳴢; 4..1.‍򳴢; [C2, P1, V6, X4_2]; 4..1.xn--1ug64613i; [C2, P1, V6, A4_2]; 4..1.xn--sf51d; [P1, V6, A4_2] # 4..1.
+4..1.xn--sf51d; 4..1.򳴢; [V6, X4_2]; 4..1.xn--sf51d; [V6, A4_2]; ; # 4..1.
+4..1.xn--1ug64613i; 4..1.‍򳴢; [C2, V6, X4_2]; 4..1.xn--1ug64613i; [C2, V6, A4_2]; ; # 4..1.
+xn--wsh.xn--tsh07994h; ⒋.⒈򳴢; [V6]; xn--wsh.xn--tsh07994h; ; ; # ⒋.⒈
+xn--wsh.xn--1ug58o74922a; ⒋.⒈‍򳴢; [C2, V6]; xn--wsh.xn--1ug58o74922a; ; ; # ⒋.⒈
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤾; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+xn--ss-svd.xn--jof2298hn83fln78f; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+xn--zca57y.xn--jof2298hn83fln78f; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; ; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لss。᩠𐇽򾅢𞤜; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لß。᩠𐇽򾅢𞤜; لß.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--zca57y.xn--jof2298hn83fln78f; ; xn--ss-svd.xn--jof2298hn83fln78f; # لß.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSS。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+لSs。᩠𐇽򾅢𞤾; لss.᩠𐇽򾅢𞤾; [B1, B2, B3, P1, V5, V6]; xn--ss-svd.xn--jof2298hn83fln78f; ; ; # لss.᩠𐇽𞤾
+𐹽𑄳񼜲.ᷟី꠆𑜫; ; [B1, B3, B6, P1, V5, V6]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫
+xn--1o0di0c0652w.xn--33e362arr1l153d; 𐹽𑄳񼜲.ᷟី꠆𑜫; [B1, B3, B6, V5, V6]; xn--1o0di0c0652w.xn--33e362arr1l153d; ; ; # 𐹽𑄳.ᷟី꠆𑜫
+Ⴓ𑜫‍򗭓.ڧ𑰶; Ⴓ𑜫‍򗭓.ڧ𑰶; [P1, V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; xn--rnd8945ky009c.xn--9jb4223l; # Ⴓ𑜫.ڧ𑰶
+Ⴓ𑜫‍򗭓.ڧ𑰶; ; [P1, V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; xn--rnd8945ky009c.xn--9jb4223l; # Ⴓ𑜫.ڧ𑰶
+ⴓ𑜫‍򗭓.ڧ𑰶; ; [P1, V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶
+xn--blj6306ey091d.xn--9jb4223l; ⴓ𑜫򗭓.ڧ𑰶; [V6]; xn--blj6306ey091d.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶
+xn--1ugy52cym7p7xu5e.xn--9jb4223l; ⴓ𑜫‍򗭓.ڧ𑰶; [V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; ; # ⴓ𑜫.ڧ𑰶
+xn--rnd8945ky009c.xn--9jb4223l; Ⴓ𑜫򗭓.ڧ𑰶; [V6]; xn--rnd8945ky009c.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶
+xn--rnd479ep20q7x12e.xn--9jb4223l; Ⴓ𑜫‍򗭓.ڧ𑰶; [V6]; xn--rnd479ep20q7x12e.xn--9jb4223l; ; ; # Ⴓ𑜫.ڧ𑰶
+ⴓ𑜫‍򗭓.ڧ𑰶; ⴓ𑜫‍򗭓.ڧ𑰶; [P1, V6]; xn--1ugy52cym7p7xu5e.xn--9jb4223l; ; xn--blj6306ey091d.xn--9jb4223l; # ⴓ𑜫.ڧ𑰶
+𐨿.🄆—; ; [P1, V5, V6]; xn--0s9c.xn--8ug8324p; ; ; # 𐨿.🄆—
+𐨿.5,—; ; [P1, V5, V6]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,—
+xn--0s9c.xn--5,-81t; 𐨿.5,—; [P1, V5, V6]; xn--0s9c.xn--5,-81t; ; ; # 𐨿.5,—
+xn--0s9c.xn--8ug8324p; 𐨿.🄆—; [V5, V6]; xn--0s9c.xn--8ug8324p; ; ; # 𐨿.🄆—
+򔊱񁦮۸。󠾭-; 򔊱񁦮۸.󠾭-; [P1, V3, V6]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.-
+xn--lmb18944c0g2z.xn----2k81m; 򔊱񁦮۸.󠾭-; [V3, V6]; xn--lmb18944c0g2z.xn----2k81m; ; ; # ۸.-
+𼗸ߍ𐹮。۝ᡎᠴ; 𼗸ߍ𐹮.۝ᡎᠴ; [B1, B5, B6, P1, V6]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ
+xn--osb0855kcc2r.xn--tlb299fhc; 𼗸ߍ𐹮.۝ᡎᠴ; [B1, B5, B6, V6]; xn--osb0855kcc2r.xn--tlb299fhc; ; ; # ߍ𐹮.ᡎᠴ
+‍ᠮႾ🄂.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ; xn--2nd129ai554b.xn--zvb3124wpkpf; [B1, P1, V6] # ᠮႾ🄂.🚗ࡁ
+‍ᠮႾ1,.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ; xn--1,-ogkx89c.xn--zvb3124wpkpf; [B1, B6, P1, V6] # ᠮႾ1,.🚗ࡁ
+‍ᠮⴞ1,.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; xn--1,-v3o625k.xn--zvb3124wpkpf; [B1, B6, P1, V6] # ᠮⴞ1,.🚗ࡁ
+xn--1,-v3o625k.xn--zvb3124wpkpf; ᠮⴞ1,.🚗ࡁ𮹌; [B1, B6, P1, V6]; xn--1,-v3o625k.xn--zvb3124wpkpf; ; ; # ᠮⴞ1,.🚗ࡁ
+xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ‍ᠮⴞ1,.🚗ࡁ𮹌‌; [B1, C1, C2, P1, V6]; xn--1,-v3o161c53q.xn--zvb692j9664aic1g; ; ; # ᠮⴞ1,.🚗ࡁ
+xn--1,-ogkx89c.xn--zvb3124wpkpf; ᠮႾ1,.🚗ࡁ𮹌; [B1, B6, P1, V6]; xn--1,-ogkx89c.xn--zvb3124wpkpf; ; ; # ᠮႾ1,.🚗ࡁ
+xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ‍ᠮႾ1,.🚗ࡁ𮹌‌; [B1, C1, C2, P1, V6]; xn--1,-ogkx89c39j.xn--zvb692j9664aic1g; ; ; # ᠮႾ1,.🚗ࡁ
+‍ᠮⴞ🄂.🚗ࡁ𮹌‌; ; [B1, C1, C2, P1, V6]; xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ; xn--h7e438h1p44a.xn--zvb3124wpkpf; [B1, P1, V6] # ᠮⴞ🄂.🚗ࡁ
+xn--h7e438h1p44a.xn--zvb3124wpkpf; ᠮⴞ🄂.🚗ࡁ𮹌; [B1, V6]; xn--h7e438h1p44a.xn--zvb3124wpkpf; ; ; # ᠮⴞ🄂.🚗ࡁ
+xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ‍ᠮⴞ🄂.🚗ࡁ𮹌‌; [B1, C1, C2, V6]; xn--h7e341b0wlbv45b.xn--zvb692j9664aic1g; ; ; # ᠮⴞ🄂.🚗ࡁ
+xn--2nd129ai554b.xn--zvb3124wpkpf; ᠮႾ🄂.🚗ࡁ𮹌; [B1, V6]; xn--2nd129ai554b.xn--zvb3124wpkpf; ; ; # ᠮႾ🄂.🚗ࡁ
+xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ‍ᠮႾ🄂.🚗ࡁ𮹌‌; [B1, C1, C2, V6]; xn--2nd129ay2gnw71c.xn--zvb692j9664aic1g; ; ; # ᠮႾ🄂.🚗ࡁ
+؁ڗ.𑚶񼡷⾆; ؁ڗ.𑚶񼡷舌; [B1, P1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+؁ڗ.𑚶񼡷舌; ; [B1, P1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+xn--jfb41a.xn--tc1ap851axo39c; ؁ڗ.𑚶񼡷舌; [B1, V5, V6]; xn--jfb41a.xn--tc1ap851axo39c; ; ; # ڗ.𑚶舌
+🞅󠳡󜍙.񲖷; ; [P1, V6]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅.
+xn--ie9hi1349bqdlb.xn--oj69a; 🞅󠳡󜍙.񲖷; [V6]; xn--ie9hi1349bqdlb.xn--oj69a; ; ; # 🞅.
+⃧񯡎-򫣝.4Ⴄ‌; ; [C1, P1, V5, V6]; xn----9snu5320fi76w.xn--4-f0g649i; ; xn----9snu5320fi76w.xn--4-f0g; [P1, V5, V6] # ⃧-.4Ⴄ
+⃧񯡎-򫣝.4ⴄ‌; ; [C1, P1, V5, V6]; xn----9snu5320fi76w.xn--4-sgn589c; ; xn----9snu5320fi76w.xn--4-ivs; [P1, V5, V6] # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-ivs; ⃧񯡎-򫣝.4ⴄ; [V5, V6]; xn----9snu5320fi76w.xn--4-ivs; ; ; # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-sgn589c; ⃧񯡎-򫣝.4ⴄ‌; [C1, V5, V6]; xn----9snu5320fi76w.xn--4-sgn589c; ; ; # ⃧-.4ⴄ
+xn----9snu5320fi76w.xn--4-f0g; ⃧񯡎-򫣝.4Ⴄ; [V5, V6]; xn----9snu5320fi76w.xn--4-f0g; ; ; # ⃧-.4Ⴄ
+xn----9snu5320fi76w.xn--4-f0g649i; ⃧񯡎-򫣝.4Ⴄ‌; [C1, V5, V6]; xn----9snu5320fi76w.xn--4-f0g649i; ; ; # ⃧-.4Ⴄ
+ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠ß𖫱; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+xn--hwe.xn--ss-ci1ub261a; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠ss𖫱; ; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ.𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+xn--hwe.xn--zca4946pblnc; ᚭ.𝌠ß𖫱; ; xn--hwe.xn--zca4946pblnc; ; ; # ᚭ.𝌠ß𖫱
+ᚭ.𝌠ß𖫱; ; ; xn--hwe.xn--zca4946pblnc; ; xn--hwe.xn--ss-ci1ub261a; # ᚭ.𝌠ß𖫱
+ᚭ。𝌠SS𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+ᚭ。𝌠Ss𖫱; ᚭ.𝌠ss𖫱; ; xn--hwe.xn--ss-ci1ub261a; ; ; # ᚭ.𝌠ss𖫱
+₁。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1。𞤫ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+1.xn--gd9al691d; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+₁。𞤉ꡪ; 1.𞤫ꡪ; [B1, B2, B3]; 1.xn--gd9al691d; ; ; # 1.𞤫ꡪ
+𯻼‌.𞶞򻙤񥘇; ; [B2, B3, B6, C1, P1, V6]; xn--0ug27500a.xn--2b7hs861pl540a; ; xn--kg4n.xn--2b7hs861pl540a; [B2, B3, P1, V6] # .
+xn--kg4n.xn--2b7hs861pl540a; 𯻼.𞶞򻙤񥘇; [B2, B3, V6]; xn--kg4n.xn--2b7hs861pl540a; ; ; # .
+xn--0ug27500a.xn--2b7hs861pl540a; 𯻼‌.𞶞򻙤񥘇; [B2, B3, B6, C1, V6]; xn--0ug27500a.xn--2b7hs861pl540a; ; ; # .
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+𑑄≯。𑜤; 𑑄≯.𑜤; [P1, V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+xn--hdh5636g.xn--ci2d; 𑑄≯.𑜤; [V5, V6]; xn--hdh5636g.xn--ci2d; ; ; # 𑑄≯.𑜤
+Ⴋ≮𱲆。‍ާ𐋣; Ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; xn--jnd802gsm17c.xn--lrb6479j; [P1, V5, V6] # Ⴋ≮.ާ𐋣
+Ⴋ≮𱲆。‍ާ𐋣; Ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; xn--jnd802gsm17c.xn--lrb6479j; [P1, V5, V6] # Ⴋ≮.ާ𐋣
+ⴋ≮𱲆。‍ާ𐋣; ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [P1, V5, V6] # ⴋ≮.ާ𐋣
+ⴋ≮𱲆。‍ާ𐋣; ⴋ≮𱲆.‍ާ𐋣; [C2, P1, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; xn--gdhz03bxt42d.xn--lrb6479j; [P1, V5, V6] # ⴋ≮.ާ𐋣
+xn--gdhz03bxt42d.xn--lrb6479j; ⴋ≮𱲆.ާ𐋣; [V5, V6]; xn--gdhz03bxt42d.xn--lrb6479j; ; ; # ⴋ≮.ާ𐋣
+xn--gdhz03bxt42d.xn--lrb506jqr4n; ⴋ≮𱲆.‍ާ𐋣; [C2, V6]; xn--gdhz03bxt42d.xn--lrb506jqr4n; ; ; # ⴋ≮.ާ𐋣
+xn--jnd802gsm17c.xn--lrb6479j; Ⴋ≮𱲆.ާ𐋣; [V5, V6]; xn--jnd802gsm17c.xn--lrb6479j; ; ; # Ⴋ≮.ާ𐋣
+xn--jnd802gsm17c.xn--lrb506jqr4n; Ⴋ≮𱲆.‍ާ𐋣; [C2, V6]; xn--jnd802gsm17c.xn--lrb506jqr4n; ; ; # Ⴋ≮.ާ𐋣
+្.򆽒≯; ; [P1, V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+្.򆽒≯; ្.򆽒≯; [P1, V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+xn--u4e.xn--hdhx0084f; ្.򆽒≯; [V5, V6]; xn--u4e.xn--hdhx0084f; ; ; # ្.≯
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺É⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; ; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+xn--c0e34564d.xn--9ca207st53lg3f; 񏁇᜴.𐨺é⬓𑄴; [V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+񏁇᜴.𐨺é⬓𑄴; 񏁇᜴.𐨺é⬓𑄴; [P1, V5, V6]; xn--c0e34564d.xn--9ca207st53lg3f; ; ; # ᜴.𐨺é⬓𑄴
+ᢇ‍꣄。︒𞤺; ᢇ‍꣄.︒𞤺; [B1, B6, C2, P1, V6]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, P1, V6] # ᢇ꣄.︒𞤺
+ᢇ‍꣄。。𞤺; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺
+ᢇ‍꣄。。𞤘; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; xn--09e4694e..xn--ye6h; [A4_2] # ᢇ꣄..𞤺
+xn--09e4694e..xn--ye6h; ᢇ꣄..𞤺; [X4_2]; xn--09e4694e..xn--ye6h; [A4_2]; ; # ᢇ꣄..𞤺
+xn--09e669a6x8j..xn--ye6h; ᢇ‍꣄..𞤺; [B6, C2, X4_2]; xn--09e669a6x8j..xn--ye6h; [B6, C2, A4_2]; ; # ᢇ꣄..𞤺
+ᢇ‍꣄。︒𞤘; ᢇ‍꣄.︒𞤺; [B1, B6, C2, P1, V6]; xn--09e669a6x8j.xn--y86cv562b; ; xn--09e4694e.xn--y86cv562b; [B1, P1, V6] # ᢇ꣄.︒𞤺
+xn--09e4694e.xn--y86cv562b; ᢇ꣄.︒𞤺; [B1, V6]; xn--09e4694e.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺
+xn--09e669a6x8j.xn--y86cv562b; ᢇ‍꣄.︒𞤺; [B1, B6, C2, V6]; xn--09e669a6x8j.xn--y86cv562b; ; ; # ᢇ꣄.︒𞤺
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+𞩬򖙱᜔‌。رު≮; 𞩬򖙱᜔‌.رު≮; [B2, B3, P1, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; xn--fze3930v7hz6b.xn--wgb86el10d; # ᜔.رު≮
+xn--fze3930v7hz6b.xn--wgb86el10d; 𞩬򖙱᜔.رު≮; [B2, B3, V6]; xn--fze3930v7hz6b.xn--wgb86el10d; ; ; # ᜔.رު≮
+xn--fze607b9651bjwl7c.xn--wgb86el10d; 𞩬򖙱᜔‌.رު≮; [B2, B3, V6]; xn--fze607b9651bjwl7c.xn--wgb86el10d; ; ; # ᜔.رު≮
+Ⴣ.ٓᢤ; Ⴣ.ٓᢤ; [P1, V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+Ⴣ.ٓᢤ; ; [P1, V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+ⴣ.ٓᢤ; ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+xn--rlj.xn--vhb294g; ⴣ.ٓᢤ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+xn--7nd.xn--vhb294g; Ⴣ.ٓᢤ; [V5, V6]; xn--7nd.xn--vhb294g; ; ; # Ⴣ.ٓᢤ
+ⴣ.ٓᢤ; ⴣ.ٓᢤ; [V5]; xn--rlj.xn--vhb294g; ; ; # ⴣ.ٓᢤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻Ⴤ򂡐; ࠓ.싉򄆻Ⴤ򂡐; [P1, V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+xn--oub.xn--sljz109bpe25dviva; ࠓ.싉򄆻ⴤ򂡐; [V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+xn--oub.xn--8nd9522gpe69cviva; ࠓ.싉򄆻Ⴤ򂡐; [V6]; xn--oub.xn--8nd9522gpe69cviva; ; ; # ࠓ.싉Ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+󠄈ࠓ.싉򄆻ⴤ򂡐; ࠓ.싉򄆻ⴤ򂡐; [P1, V6]; xn--oub.xn--sljz109bpe25dviva; ; ; # ࠓ.싉ⴤ
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+ꨬ𑲫≮.⤂; ꨬ𑲫≮.⤂; [P1, V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+xn--gdh1854cn19c.xn--kqi; ꨬ𑲫≮.⤂; [V5, V6]; xn--gdh1854cn19c.xn--kqi; ; ; # ꨬ𑲫≮.⤂
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮Ⴢ.Ⴃ; ؄𐩔≮Ⴢ.Ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮ⴢ.ⴃ; ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+xn--mfb416c0jox02t.xn--ukj; ؄𐩔≮Ⴢ.ⴃ; [B1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+xn--mfb266l4khr54u.xn--ukj; ؄𐩔≮ⴢ.ⴃ; [B1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+xn--mfb416c0jox02t.xn--bnd; ؄𐩔≮Ⴢ.Ⴃ; [B1, V6]; xn--mfb416c0jox02t.xn--bnd; ; ; # 𐩔≮Ⴢ.Ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮ⴢ.ⴃ; ؄𐩔≮ⴢ.ⴃ; [B1, P1, V6]; xn--mfb266l4khr54u.xn--ukj; ; ; # 𐩔≮ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+؄𐩔≮Ⴢ.ⴃ; ؄𐩔≮Ⴢ.ⴃ; [B1, P1, V6]; xn--mfb416c0jox02t.xn--ukj; ; ; # 𐩔≮Ⴢ.ⴃ
+𑁅。-; 𑁅.-; [V3, V5]; xn--210d.-; ; ; # 𑁅.-
+xn--210d.-; 𑁅.-; [V3, V5]; xn--210d.-; ; ; # 𑁅.-
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+්򕸽󠧱。饈≠٤; ්򕸽󠧱.饈≠٤; [B1, B5, B6, P1, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+xn--h1c25913jfwov.xn--dib144ler5f; ්򕸽󠧱.饈≠٤; [B1, B5, B6, V5, V6]; xn--h1c25913jfwov.xn--dib144ler5f; ; ; # ්.饈≠٤
+𞥃ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞥃ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ7。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+xn--7-v4j2826w.xn--4-ogoy01bou3i; 𞥃ᠠ7.≯邅⬻4; [B1, B2, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+𞤡ᠠ⁷。≯邅⬻4; 𞥃ᠠ7.≯邅⬻4; [B1, B2, P1, V6]; xn--7-v4j2826w.xn--4-ogoy01bou3i; ; ; # 𞥃ᠠ7.≯邅⬻4
+򠿯ᡳ-𑐻.𐹴𐋫؅󑎳; ; [B1, B6, P1, V6]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫
+xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; 򠿯ᡳ-𑐻.𐹴𐋫؅󑎳; [B1, B6, V6]; xn----m9j3429kxmy7e.xn--nfb7950kdihrp812a; ; ; # ᡳ-𑐻.𐹴𐋫
+򠶆ࡅੑ.넨-󶧈; ; [B5, B6, P1, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+򠶆ࡅੑ.넨-󶧈; 򠶆ࡅੑ.넨-󶧈; [B5, B6, P1, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+xn--3vb26hb6834b.xn----i37ez0957g; 򠶆ࡅੑ.넨-󶧈; [B5, B6, V6]; xn--3vb26hb6834b.xn----i37ez0957g; ; ; # ࡅੑ.넨-
+ꡦᡑ‍⒈。𐋣-; ꡦᡑ‍⒈.𐋣-; [C2, P1, V3, V6]; xn--h8e470bl0d838o.xn----381i; ; xn--h8e863drj7h.xn----381i; [P1, V3, V6] # ꡦᡑ⒈.𐋣-
+ꡦᡑ‍1.。𐋣-; ꡦᡑ‍1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2] # ꡦᡑ1..𐋣-
+xn--1-o7j0610f..xn----381i; ꡦᡑ1..𐋣-; [V3, X4_2]; xn--1-o7j0610f..xn----381i; [V3, A4_2]; ; # ꡦᡑ1..𐋣-
+xn--1-o7j663bdl7m..xn----381i; ꡦᡑ‍1..𐋣-; [C2, V3, X4_2]; xn--1-o7j663bdl7m..xn----381i; [C2, V3, A4_2]; ; # ꡦᡑ1..𐋣-
+xn--h8e863drj7h.xn----381i; ꡦᡑ⒈.𐋣-; [V3, V6]; xn--h8e863drj7h.xn----381i; ; ; # ꡦᡑ⒈.𐋣-
+xn--h8e470bl0d838o.xn----381i; ꡦᡑ‍⒈.𐋣-; [C2, V3, V6]; xn--h8e470bl0d838o.xn----381i; ; ; # ꡦᡑ⒈.𐋣-
+Ⴌ。􍼠ﭩ; Ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+Ⴌ。􍼠ٹ; Ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+ⴌ。􍼠ٹ; ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+xn--3kj.xn--yib19191t; ⴌ.􍼠ٹ; [B5, B6, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+xn--knd.xn--yib19191t; Ⴌ.􍼠ٹ; [B5, B6, V6]; xn--knd.xn--yib19191t; ; ; # Ⴌ.ٹ
+ⴌ。􍼠ﭩ; ⴌ.􍼠ٹ; [B5, B6, P1, V6]; xn--3kj.xn--yib19191t; ; ; # ⴌ.ٹ
+𐮁𐭱.྄፞-ᳺ; ; [B1, V5]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ
+xn--r19c5a.xn----xjg270ag3m; 𐮁𐭱.྄፞-ᳺ; [B1, V5]; xn--r19c5a.xn----xjg270ag3m; ; ; # 𐮁𐭱.྄፞-ᳺ
+⒈䰹‍-。웈; ⒈䰹‍-.웈; [C2, P1, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [P1, V3, V6] # ⒈䰹-.웈
+⒈䰹‍-。웈; ⒈䰹‍-.웈; [C2, P1, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; xn----dcp160o.xn--kp5b; [P1, V3, V6] # ⒈䰹-.웈
+1.䰹‍-。웈; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈
+1.䰹‍-。웈; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; 1.xn----zw5a.xn--kp5b; [V3] # 1.䰹-.웈
+1.xn----zw5a.xn--kp5b; 1.䰹-.웈; [V3]; 1.xn----zw5a.xn--kp5b; ; ; # 1.䰹-.웈
+1.xn----tgnz80r.xn--kp5b; 1.䰹‍-.웈; [C2, V3]; 1.xn----tgnz80r.xn--kp5b; ; ; # 1.䰹-.웈
+xn----dcp160o.xn--kp5b; ⒈䰹-.웈; [V3, V6]; xn----dcp160o.xn--kp5b; ; ; # ⒈䰹-.웈
+xn----tgnx5rjr6c.xn--kp5b; ⒈䰹‍-.웈; [C2, V3, V6]; xn----tgnx5rjr6c.xn--kp5b; ; ; # ⒈䰹-.웈
+て。‌󠳽߳; て.‌󠳽߳; [C1, P1, V6]; xn--m9j.xn--rtb154j9l73w; ; xn--m9j.xn--rtb10784p; [P1, V6] # て.߳
+xn--m9j.xn--rtb10784p; て.󠳽߳; [V6]; xn--m9j.xn--rtb10784p; ; ; # て.߳
+xn--m9j.xn--rtb154j9l73w; て.‌󠳽߳; [C1, V6]; xn--m9j.xn--rtb154j9l73w; ; ; # て.߳
+ς。꧀ۧ; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ
+ς。꧀ۧ; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; xn--4xa.xn--3lb1944f; # ς.꧀ۧ
+Σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+xn--4xa.xn--3lb1944f; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+xn--3xa.xn--3lb1944f; ς.꧀ۧ; [V5]; xn--3xa.xn--3lb1944f; ; ; # ς.꧀ۧ
+Σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+σ。꧀ۧ; σ.꧀ۧ; [V5]; xn--4xa.xn--3lb1944f; ; ; # σ.꧀ۧ
+்󥫅򌉑.ႢႵ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--9md2b; ; ; # ்.ႢႵ
+்󥫅򌉑.ⴂⴕ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ
+்󥫅򌉑.Ⴂⴕ; ; [P1, V5, V6]; xn--xmc83135idcxza.xn--9md086l; ; ; # ்.Ⴂⴕ
+xn--xmc83135idcxza.xn--9md086l; ்󥫅򌉑.Ⴂⴕ; [V5, V6]; xn--xmc83135idcxza.xn--9md086l; ; ; # ்.Ⴂⴕ
+xn--xmc83135idcxza.xn--tkjwb; ்󥫅򌉑.ⴂⴕ; [V5, V6]; xn--xmc83135idcxza.xn--tkjwb; ; ; # ்.ⴂⴕ
+xn--xmc83135idcxza.xn--9md2b; ்󥫅򌉑.ႢႵ; [V5, V6]; xn--xmc83135idcxza.xn--9md2b; ; ; # ்.ႢႵ
+ᰲ🄈⾛֦.‍򯥤߽; ᰲ🄈走֦.‍򯥤߽; [C2, P1, V5, V6]; xn--xcb756i493fwi5o.xn--1tb334j1197q; ; xn--xcb756i493fwi5o.xn--1tb13454l; [P1, V5, V6] # ᰲ🄈走֦.߽
+ᰲ7,走֦.‍򯥤߽; ; [C2, P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; xn--7,-bid991urn3k.xn--1tb13454l; [P1, V5, V6] # ᰲ7,走֦.߽
+xn--7,-bid991urn3k.xn--1tb13454l; ᰲ7,走֦.򯥤߽; [P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb13454l; ; ; # ᰲ7,走֦.߽
+xn--7,-bid991urn3k.xn--1tb334j1197q; ᰲ7,走֦.‍򯥤߽; [C2, P1, V5, V6]; xn--7,-bid991urn3k.xn--1tb334j1197q; ; ; # ᰲ7,走֦.߽
+xn--xcb756i493fwi5o.xn--1tb13454l; ᰲ🄈走֦.򯥤߽; [V5, V6]; xn--xcb756i493fwi5o.xn--1tb13454l; ; ; # ᰲ🄈走֦.߽
+xn--xcb756i493fwi5o.xn--1tb334j1197q; ᰲ🄈走֦.‍򯥤߽; [C2, V5, V6]; xn--xcb756i493fwi5o.xn--1tb334j1197q; ; ; # ᰲ🄈走֦.߽
+ᢗ。Ӏ񝄻; ᢗ.Ӏ񝄻; [P1, V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。Ӏ񝄻; ᢗ.Ӏ񝄻; [P1, V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [P1, V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+xn--hbf.xn--s5a83117e; ᢗ.ӏ񝄻; [V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+xn--hbf.xn--d5a86117e; ᢗ.Ӏ񝄻; [V6]; xn--hbf.xn--d5a86117e; ; ; # ᢗ.Ӏ
+ᢗ。ӏ񝄻; ᢗ.ӏ񝄻; [P1, V6]; xn--hbf.xn--s5a83117e; ; ; # ᢗ.ӏ
+٨-。񠏇🝆ᄾ; ٨-.񠏇🝆ᄾ; [B1, P1, V3, V6]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ
+xn----oqc.xn--qrd1699v327w; ٨-.񠏇🝆ᄾ; [B1, V3, V6]; xn----oqc.xn--qrd1699v327w; ; ; # ٨-.🝆ᄾ
+-𐋷𖾑。󠆬; -𐋷𖾑.; [V3]; xn----991iq40y.; ; ; # -𐋷𖾑.
+xn----991iq40y.; -𐋷𖾑.; [V3]; xn----991iq40y.; ; ; # -𐋷𖾑.
+‌𐹳🐴멈.꯭񐡼; ; [B1, C1, P1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, P1, V5, V6] # 𐹳🐴멈.꯭
+‌𐹳🐴멈.꯭񐡼; ‌𐹳🐴멈.꯭񐡼; [B1, C1, P1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; xn--422b325mqb6i.xn--429a8682s; [B1, P1, V5, V6] # 𐹳🐴멈.꯭
+xn--422b325mqb6i.xn--429a8682s; 𐹳🐴멈.꯭񐡼; [B1, V5, V6]; xn--422b325mqb6i.xn--429a8682s; ; ; # 𐹳🐴멈.꯭
+xn--0ug6681d406b7bwk.xn--429a8682s; ‌𐹳🐴멈.꯭񐡼; [B1, C1, V5, V6]; xn--0ug6681d406b7bwk.xn--429a8682s; ; ; # 𐹳🐴멈.꯭
+≮.ݩ؃; ; [B1, P1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+≮.ݩ؃; ≮.ݩ؃; [B1, P1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+xn--gdh.xn--lfb92e; ≮.ݩ؃; [B1, V6]; xn--gdh.xn--lfb92e; ; ; # ≮.ݩ
+𐶭⾆。‌𑚶򟱃𞰘; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, P1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, P1, V5, V6] # 舌.𑚶
+𐶭舌。‌𑚶򟱃𞰘; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, P1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; xn--tc1ao37z.xn--6e2dw557azds2d; [B2, B3, B5, B6, P1, V5, V6] # 舌.𑚶
+xn--tc1ao37z.xn--6e2dw557azds2d; 𐶭舌.𑚶򟱃𞰘; [B2, B3, B5, B6, V5, V6]; xn--tc1ao37z.xn--6e2dw557azds2d; ; ; # 舌.𑚶
+xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; 𐶭舌.‌𑚶򟱃𞰘; [B1, B2, B3, C1, V6]; xn--tc1ao37z.xn--0ugx728gi1nfwqz2e; ; ; # 舌.𑚶
+‌Ⴠ-.𝟷ς𞴺ς; ‌Ⴠ-.1ς𞴺ς; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺ς
+‌Ⴠ-.1ς𞴺ς; ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺ς
+‌ⴠ-.1ς𞴺ς; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς
+‌Ⴠ-.1Σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌ⴠ-.1σ𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ
+‌Ⴠ-.1σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+xn----z1g.xn--1-0mba52321c; Ⴠ-.1σ𞴺σ; [B1, B6, V3, V6]; xn----z1g.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ
+xn----z1g168i.xn--1-0mba52321c; ‌Ⴠ-.1σ𞴺σ; [B1, C1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; ; # Ⴠ-.1σ𞴺σ
+xn----2ws.xn--1-0mba52321c; ⴠ-.1σ𞴺σ; [B1, B6, V3]; xn----2ws.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ
+xn----rgn530d.xn--1-0mba52321c; ‌ⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; ; # ⴠ-.1σ𞴺σ
+‌Ⴠ-.1ς𞴺Σ; ‌Ⴠ-.1ς𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺σ
+‌ⴠ-.1ς𞴺σ; ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ
+xn----rgn530d.xn--1-ymbd52321c; ‌ⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; ; # ⴠ-.1ς𞴺σ
+xn----z1g168i.xn--1-ymbd52321c; ‌Ⴠ-.1ς𞴺σ; [B1, C1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; ; # Ⴠ-.1ς𞴺σ
+xn----rgn530d.xn--1-ymba92321c; ‌ⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; ; # ⴠ-.1ς𞴺ς
+xn----z1g168i.xn--1-ymba92321c; ‌Ⴠ-.1ς𞴺ς; [B1, C1, V3, V6]; xn----z1g168i.xn--1-ymba92321c; ; ; # Ⴠ-.1ς𞴺ς
+‌ⴠ-.𝟷ς𞴺ς; ‌ⴠ-.1ς𞴺ς; [B1, C1, V3]; xn----rgn530d.xn--1-ymba92321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺ς
+‌Ⴠ-.𝟷Σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌ⴠ-.𝟷σ𞴺σ; ‌ⴠ-.1σ𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-0mba52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1σ𞴺σ
+‌Ⴠ-.𝟷σ𞴺Σ; ‌Ⴠ-.1σ𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-0mba52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1σ𞴺σ
+‌Ⴠ-.𝟷ς𞴺Σ; ‌Ⴠ-.1ς𞴺σ; [B1, C1, P1, V3, V6]; xn----z1g168i.xn--1-ymbd52321c; ; xn----z1g.xn--1-0mba52321c; [B1, B6, P1, V3, V6] # Ⴠ-.1ς𞴺σ
+‌ⴠ-.𝟷ς𞴺σ; ‌ⴠ-.1ς𞴺σ; [B1, C1, V3]; xn----rgn530d.xn--1-ymbd52321c; ; xn----2ws.xn--1-0mba52321c; [B1, B6, V3] # ⴠ-.1ς𞴺σ
+𑲘󠄒𓑡。𝟪Ⴜ; 𑲘𓑡.8Ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。8Ⴜ; 𑲘𓑡.8Ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。8ⴜ; 𑲘𓑡.8ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+xn--7m3d291b.xn--8-vws; 𑲘𓑡.8ⴜ; [V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+xn--7m3d291b.xn--8-s1g; 𑲘𓑡.8Ⴜ; [V5, V6]; xn--7m3d291b.xn--8-s1g; ; ; # 𑲘.8Ⴜ
+𑲘󠄒𓑡。𝟪ⴜ; 𑲘𓑡.8ⴜ; [P1, V5, V6]; xn--7m3d291b.xn--8-vws; ; ; # 𑲘.8ⴜ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+䪏ګߠु。뭕ᢝឹ; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+xn--ekb23dj4at01n.xn--43e96bh910b; 䪏ګߠु.뭕ᢝឹ; [B5, B6]; xn--ekb23dj4at01n.xn--43e96bh910b; ; ; # 䪏ګߠु.뭕ᢝឹ
+᮫。🂉󠁰; ᮫.🂉󠁰; [P1, V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+᮫。🂉󠁰; ᮫.🂉󠁰; [P1, V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+xn--zxf.xn--fx7ho0250c; ᮫.🂉󠁰; [V5, V6]; xn--zxf.xn--fx7ho0250c; ; ; # ᮫.🂉
+󩎃ૄ。ς‍𐹮𑈵; 󩎃ૄ.ς‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.ς𐹮𑈵
+󩎃ૄ。Σ‍𐹮𑈵; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.σ𐹮𑈵
+󩎃ૄ。σ‍𐹮𑈵; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, P1, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; xn--dfc53161q.xn--4xa8467k5mc; [B5, P1, V6] # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--4xa8467k5mc; 󩎃ૄ.σ𐹮𑈵; [B5, V6]; xn--dfc53161q.xn--4xa8467k5mc; ; ; # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--4xa895lzo7nsfd; 󩎃ૄ.σ‍𐹮𑈵; [B5, C2, V6]; xn--dfc53161q.xn--4xa895lzo7nsfd; ; ; # ૄ.σ𐹮𑈵
+xn--dfc53161q.xn--3xa006lzo7nsfd; 󩎃ૄ.ς‍𐹮𑈵; [B5, C2, V6]; xn--dfc53161q.xn--3xa006lzo7nsfd; ; ; # ૄ.ς𐹮𑈵
+𐫀ᡂ𑜫.𑘿; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+𐫀ᡂ𑜫.𑘿; ; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+xn--17e9625js1h.xn--sb2d; 𐫀ᡂ𑜫.𑘿; [B1, B2, B3, B6, V5]; xn--17e9625js1h.xn--sb2d; ; ; # 𐫀ᡂ𑜫.𑘿
+󬚶󸋖򖩰-。‌; 󬚶󸋖򖩰-.‌; [C1, P1, V3, V6]; xn----7i12hu122k9ire.xn--0ug; ; xn----7i12hu122k9ire.; [P1, V3, V6] # -.
+xn----7i12hu122k9ire.; 󬚶󸋖򖩰-.; [V3, V6]; xn----7i12hu122k9ire.; ; ; # -.
+xn----7i12hu122k9ire.xn--0ug; 󬚶󸋖򖩰-.‌; [C1, V3, V6]; xn----7i12hu122k9ire.xn--0ug; ; ; # -.
+𐹣.߂; 𐹣.߂; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+𐹣.߂; ; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+xn--bo0d.xn--dsb; 𐹣.߂; [B1]; xn--bo0d.xn--dsb; ; ; # 𐹣.߂
+-ߡ。Ↄ; -ߡ.Ↄ; [B1, P1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。Ↄ; -ߡ.Ↄ; [B1, P1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。ↄ; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+xn----8cd.xn--r5g; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+xn----8cd.xn--q5g; -ߡ.Ↄ; [B1, V3, V6]; xn----8cd.xn--q5g; ; ; # -ߡ.Ↄ
+-ߡ。ↄ; -ߡ.ↄ; [B1, V3]; xn----8cd.xn--r5g; ; ; # -ߡ.ↄ
+‍-︒󠄄。ß哑‌𐵿; ‍-︒.ß哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--zca670n5f0binyk; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ß哑
+‍-。󠄄。ß哑‌𐵿; ‍-..ß哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ß哑
+‍-。󠄄。SS哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+‍-。󠄄。ss哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+‍-。󠄄。Ss哑‌𐵿; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, P1, V3, V6, A4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6, A4_2] # -..ss哑
+-..xn--ss-h46c5711e; -..ss哑𐵿; [B1, B5, B6, V3, V6, X4_2]; -..xn--ss-h46c5711e; [B1, B5, B6, V3, V6, A4_2]; ; # -..ss哑
+xn----tgn..xn--ss-k1ts75zb8ym; ‍-..ss哑‌𐵿; [B1, B5, B6, C1, C2, V3, V6, X4_2]; xn----tgn..xn--ss-k1ts75zb8ym; [B1, B5, B6, C1, C2, V3, V6, A4_2]; ; # -..ss哑
+xn----tgn..xn--zca670n5f0binyk; ‍-..ß哑‌𐵿; [B1, B5, B6, C1, C2, V3, V6, X4_2]; xn----tgn..xn--zca670n5f0binyk; [B1, B5, B6, C1, C2, V3, V6, A4_2]; ; # -..ß哑
+‍-︒󠄄。SS哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+‍-︒󠄄。ss哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+‍-︒󠄄。Ss哑‌𐵿; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, P1, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; xn----o89h.xn--ss-h46c5711e; [B1, B5, B6, P1, V3, V6] # -︒.ss哑
+xn----o89h.xn--ss-h46c5711e; -︒.ss哑𐵿; [B1, B5, B6, V3, V6]; xn----o89h.xn--ss-h46c5711e; ; ; # -︒.ss哑
+xn----tgnt341h.xn--ss-k1ts75zb8ym; ‍-︒.ss哑‌𐵿; [B1, B5, B6, C1, C2, V6]; xn----tgnt341h.xn--ss-k1ts75zb8ym; ; ; # -︒.ss哑
+xn----tgnt341h.xn--zca670n5f0binyk; ‍-︒.ß哑‌𐵿; [B1, B5, B6, C1, C2, V6]; xn----tgnt341h.xn--zca670n5f0binyk; ; ; # -︒.ß哑
+︒.𑑂︯; ︒.𑑂︯; [P1, V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+︒.𑑂︯; ︒.𑑂︯; [P1, V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+。.𑑂︯; ..𑑂︯; [V5, X4_2]; ..xn--s96cu30b; [V5, A4_2]; ; # ..𑑂︯
+..xn--s96cu30b; ..𑑂︯; [V5, X4_2]; ..xn--s96cu30b; [V5, A4_2]; ; # ..𑑂︯
+xn--y86c.xn--s96cu30b; ︒.𑑂︯; [V5, V6]; xn--y86c.xn--s96cu30b; ; ; # ︒.𑑂︯
+꤬。‍; ꤬.‍; [C2, V5]; xn--zi9a.xn--1ug; ; xn--zi9a.; [V5] # ꤬.
+xn--zi9a.; ꤬.; [V5]; xn--zi9a.; ; ; # ꤬.
+xn--zi9a.xn--1ug; ꤬.‍; [C2, V5]; xn--zi9a.xn--1ug; ; ; # ꤬.
+‍󠸡。ﳗ; ‍󠸡.هج; [B1, C2, P1, V6]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, P1, V6] # .هج
+‍󠸡。هج; ‍󠸡.هج; [B1, C2, P1, V6]; xn--1ug80651l.xn--rgb7c; ; xn--d356e.xn--rgb7c; [B1, P1, V6] # .هج
+xn--d356e.xn--rgb7c; 󠸡.هج; [B1, V6]; xn--d356e.xn--rgb7c; ; ; # .هج
+xn--1ug80651l.xn--rgb7c; ‍󠸡.هج; [B1, C2, V6]; xn--1ug80651l.xn--rgb7c; ; ; # .هج
+-Ⴄ𝟢٣.𑍴ς; -Ⴄ0٣.𑍴ς; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; xn---0-iyd216h.xn--4xa9120l; # -Ⴄ0٣.𑍴ς
+-Ⴄ0٣.𑍴ς; ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; xn---0-iyd216h.xn--4xa9120l; # -Ⴄ0٣.𑍴ς
+-ⴄ0٣.𑍴ς; ; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς
+-Ⴄ0٣.𑍴Σ; -Ⴄ0٣.𑍴σ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+-ⴄ0٣.𑍴σ; ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+xn---0-iyd8660b.xn--4xa9120l; -ⴄ0٣.𑍴σ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+xn---0-iyd216h.xn--4xa9120l; -Ⴄ0٣.𑍴σ; [B1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+xn---0-iyd8660b.xn--3xa1220l; -ⴄ0٣.𑍴ς; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; ; # -ⴄ0٣.𑍴ς
+xn---0-iyd216h.xn--3xa1220l; -Ⴄ0٣.𑍴ς; [B1, V3, V5, V6]; xn---0-iyd216h.xn--3xa1220l; ; ; # -Ⴄ0٣.𑍴ς
+-ⴄ𝟢٣.𑍴ς; -ⴄ0٣.𑍴ς; [B1, V3, V5]; xn---0-iyd8660b.xn--3xa1220l; ; xn---0-iyd8660b.xn--4xa9120l; # -ⴄ0٣.𑍴ς
+-Ⴄ𝟢٣.𑍴Σ; -Ⴄ0٣.𑍴σ; [B1, P1, V3, V5, V6]; xn---0-iyd216h.xn--4xa9120l; ; ; # -Ⴄ0٣.𑍴σ
+-ⴄ𝟢٣.𑍴σ; -ⴄ0٣.𑍴σ; [B1, V3, V5]; xn---0-iyd8660b.xn--4xa9120l; ; ; # -ⴄ0٣.𑍴σ
+󦈄。-; 󦈄.-; [P1, V3, V6]; xn--xm38e.-; ; ; # .-
+xn--xm38e.-; 󦈄.-; [V3, V6]; xn--xm38e.-; ; ; # .-
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘ß≯; ⋠𐋮.򶈮༘ß≯; [P1, V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; xn--pgh4639f.xn--ss-ifj426nle504a; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+xn--pgh4639f.xn--ss-ifj426nle504a; ⋠𐋮.򶈮༘ss≯; [V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+xn--pgh4639f.xn--zca593eo6oc013y; ⋠𐋮.򶈮༘ß≯; [V6]; xn--pgh4639f.xn--zca593eo6oc013y; ; ; # ⋠𐋮.༘ß≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘SS≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+⋠𐋮.򶈮༘Ss≯; ⋠𐋮.򶈮༘ss≯; [P1, V6]; xn--pgh4639f.xn--ss-ifj426nle504a; ; ; # ⋠𐋮.༘ss≯
+1𐋸٤。󠢮ﮤ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+1𐋸٤。󠢮ۀ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+1𐋸٤。󠢮ۀ񷝊; 1𐋸٤.󠢮ۀ񷝊; [B1, P1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+xn--1-hqc3905q.xn--zkb83268gqee4a; 1𐋸٤.󠢮ۀ񷝊; [B1, V6]; xn--1-hqc3905q.xn--zkb83268gqee4a; ; ; # 1𐋸٤.ۀ
+儭-。𐹴Ⴢ񥳠‌; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; xn----gz7a.xn--6nd5001kyw98a; [B1, B6, P1, V3, V6] # 儭-.𐹴Ⴢ
+儭-。𐹴Ⴢ񥳠‌; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; xn----gz7a.xn--6nd5001kyw98a; [B1, B6, P1, V3, V6] # 儭-.𐹴Ⴢ
+儭-。𐹴ⴢ񥳠‌; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, P1, V3, V6] # 儭-.𐹴ⴢ
+xn----gz7a.xn--qlj9223eywx0b; 儭-.𐹴ⴢ񥳠; [B1, B6, V3, V6]; xn----gz7a.xn--qlj9223eywx0b; ; ; # 儭-.𐹴ⴢ
+xn----gz7a.xn--0ug472cfq0pus98b; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; ; # 儭-.𐹴ⴢ
+xn----gz7a.xn--6nd5001kyw98a; 儭-.𐹴Ⴢ񥳠; [B1, B6, V3, V6]; xn----gz7a.xn--6nd5001kyw98a; ; ; # 儭-.𐹴Ⴢ
+xn----gz7a.xn--6nd249ejl4pusr7b; 儭-.𐹴Ⴢ񥳠‌; [B1, B6, C1, V3, V6]; xn----gz7a.xn--6nd249ejl4pusr7b; ; ; # 儭-.𐹴Ⴢ
+儭-。𐹴ⴢ񥳠‌; 儭-.𐹴ⴢ񥳠‌; [B1, B6, C1, P1, V3, V6]; xn----gz7a.xn--0ug472cfq0pus98b; ; xn----gz7a.xn--qlj9223eywx0b; [B1, B6, P1, V3, V6] # 儭-.𐹴ⴢ
+𝟺𐋷ڹ.𞤭򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+4𐋷ڹ.𞤭򿍡; ; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+4𐋷ڹ.𞤋򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+xn--4-cvc5384q.xn--le6hi7322b; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+𝟺𐋷ڹ.𞤋򿍡; 4𐋷ڹ.𞤭򿍡; [B1, B2, B3, P1, V6]; xn--4-cvc5384q.xn--le6hi7322b; ; ; # 4𐋷ڹ.𞤭
+≯-ꡋ𑲣.⒈𐹭; ; [B1, P1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+≯-ꡋ𑲣.⒈𐹭; ≯-ꡋ𑲣.⒈𐹭; [B1, P1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+≯-ꡋ𑲣.1.𐹭; ; [B1, P1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+≯-ꡋ𑲣.1.𐹭; ≯-ꡋ𑲣.1.𐹭; [B1, P1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+xn----ogox061d5i8d.1.xn--lo0d; ≯-ꡋ𑲣.1.𐹭; [B1, V6]; xn----ogox061d5i8d.1.xn--lo0d; ; ; # ≯-ꡋ𑲣.1.𐹭
+xn----ogox061d5i8d.xn--tsh0666f; ≯-ꡋ𑲣.⒈𐹭; [B1, V6]; xn----ogox061d5i8d.xn--tsh0666f; ; ; # ≯-ꡋ𑲣.⒈𐹭
+̰.󰜱蚀; ̰.󰜱蚀; [P1, V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+̰.󰜱蚀; ; [P1, V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+xn--xta.xn--e91aw9417e; ̰.󰜱蚀; [V5, V6]; xn--xta.xn--e91aw9417e; ; ; # ̰.蚀
+יּႸ.𞡼𑇀ß⃗; יּႸ.𞡼𑇀ß⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; xn--kdb1d867b.xn--ss-yju5690ken9h; # יּႸ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀ß⃗; ; [B2, B3, P1, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; xn--kdb1d867b.xn--ss-yju5690ken9h; # יּႸ.𞡼𑇀ß⃗
+יּⴘ.𞡼𑇀ß⃗; ; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀SS⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּⴘ.𞡼𑇀ss⃗; ; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+xn--kdb1d278n.xn--ss-yju5690ken9h; יּⴘ.𞡼𑇀ss⃗; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+xn--kdb1d867b.xn--ss-yju5690ken9h; יּႸ.𞡼𑇀ss⃗; [B2, B3, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+xn--kdb1d278n.xn--zca284nhg9nrrxg; יּⴘ.𞡼𑇀ß⃗; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; ; # יּⴘ.𞡼𑇀ß⃗
+xn--kdb1d867b.xn--zca284nhg9nrrxg; יּႸ.𞡼𑇀ß⃗; [B2, B3, V6]; xn--kdb1d867b.xn--zca284nhg9nrrxg; ; ; # יּႸ.𞡼𑇀ß⃗
+יּⴘ.𞡼𑇀ß⃗; יּⴘ.𞡼𑇀ß⃗; [B2, B3]; xn--kdb1d278n.xn--zca284nhg9nrrxg; ; xn--kdb1d278n.xn--ss-yju5690ken9h; # יּⴘ.𞡼𑇀ß⃗
+יּႸ.𞡼𑇀SS⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּⴘ.𞡼𑇀ss⃗; יּⴘ.𞡼𑇀ss⃗; [B2, B3]; xn--kdb1d278n.xn--ss-yju5690ken9h; ; ; # יּⴘ.𞡼𑇀ss⃗
+יּႸ.𞡼𑇀ss⃗; ; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+יּႸ.𞡼𑇀ss⃗; יּႸ.𞡼𑇀ss⃗; [B2, B3, P1, V6]; xn--kdb1d867b.xn--ss-yju5690ken9h; ; ; # יּႸ.𞡼𑇀ss⃗
+ᮣ𐹰򁱓。凬; ᮣ𐹰򁱓.凬; [B1, P1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+ᮣ𐹰򁱓。凬; ᮣ𐹰򁱓.凬; [B1, P1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+xn--rxfz314ilg20c.xn--t9q; ᮣ𐹰򁱓.凬; [B1, V5, V6]; xn--rxfz314ilg20c.xn--t9q; ; ; # ᮣ𐹰.凬
+🢟🄈‍ꡎ。྄; 🢟🄈‍ꡎ.྄; [C2, P1, V5, V6]; xn--1ug4874cfd0kbmg.xn--3ed; ; xn--nc9aq743ds0e.xn--3ed; [P1, V5, V6] # 🢟🄈ꡎ.྄
+🢟7,‍ꡎ。྄; 🢟7,‍ꡎ.྄; [C2, P1, V5, V6]; xn--7,-n1t0654eqo3o.xn--3ed; ; xn--7,-gh9hg322i.xn--3ed; [P1, V5, V6] # 🢟7,ꡎ.྄
+xn--7,-gh9hg322i.xn--3ed; 🢟7,ꡎ.྄; [P1, V5, V6]; xn--7,-gh9hg322i.xn--3ed; ; ; # 🢟7,ꡎ.྄
+xn--7,-n1t0654eqo3o.xn--3ed; 🢟7,‍ꡎ.྄; [C2, P1, V5, V6]; xn--7,-n1t0654eqo3o.xn--3ed; ; ; # 🢟7,ꡎ.྄
+xn--nc9aq743ds0e.xn--3ed; 🢟🄈ꡎ.྄; [V5, V6]; xn--nc9aq743ds0e.xn--3ed; ; ; # 🢟🄈ꡎ.྄
+xn--1ug4874cfd0kbmg.xn--3ed; 🢟🄈‍ꡎ.྄; [C2, V5, V6]; xn--1ug4874cfd0kbmg.xn--3ed; ; ; # 🢟🄈ꡎ.྄
+ꡔ。္ᢇ; ꡔ.္ᢇ; [V5]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ
+xn--tc9a.xn--9jd663b; ꡔ.္ᢇ; [V5]; xn--tc9a.xn--9jd663b; ; ; # ꡔ.္ᢇ
+⃫≮.𝨖; ; [P1, V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+⃫≮.𝨖; ⃫≮.𝨖; [P1, V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+xn--e1g71d.xn--772h; ⃫≮.𝨖; [V5, V6]; xn--e1g71d.xn--772h; ; ; # ⃫≮.𝨖
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+Ⴢ≯褦.ᠪߪႾݧ; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+ⴢ≯褦.ᠪߪⴞݧ; ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+xn--6nd461g478e.xn--rpb5x392bcyt; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+xn--hdh433bev8e.xn--rpb5x392bcyt; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+xn--6nd461g478e.xn--rpb5x49td2h; Ⴢ≯褦.ᠪߪႾݧ; [B5, B6, V6]; xn--6nd461g478e.xn--rpb5x49td2h; ; ; # Ⴢ≯褦.ᠪߪႾݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+ⴢ≯褦.ᠪߪⴞݧ; ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--hdh433bev8e.xn--rpb5x392bcyt; ; ; # ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+Ⴢ≯褦.ᠪߪⴞݧ; Ⴢ≯褦.ᠪߪⴞݧ; [B5, B6, P1, V6]; xn--6nd461g478e.xn--rpb5x392bcyt; ; ; # Ⴢ≯褦.ᠪߪⴞݧ
+򊉆󠆒‌꥓。𞤙ٻꡘ; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, P1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, P1, V6] # ꥓.𞤻ٻꡘ
+򊉆󠆒‌꥓。𞤻ٻꡘ; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, P1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; xn--3j9al6189a.xn--0ib8893fegvj; [B2, B3, P1, V6] # ꥓.𞤻ٻꡘ
+xn--3j9al6189a.xn--0ib8893fegvj; 򊉆꥓.𞤻ٻꡘ; [B2, B3, V6]; xn--3j9al6189a.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ
+xn--0ug8815chtz0e.xn--0ib8893fegvj; 򊉆‌꥓.𞤻ٻꡘ; [B2, B3, C1, V6]; xn--0ug8815chtz0e.xn--0ib8893fegvj; ; ; # ꥓.𞤻ٻꡘ
+‌.≯; ; [C1, P1, V6]; xn--0ug.xn--hdh; ; .xn--hdh; [P1, V6, A4_2] # .≯
+‌.≯; ‌.≯; [C1, P1, V6]; xn--0ug.xn--hdh; ; .xn--hdh; [P1, V6, A4_2] # .≯
+.xn--hdh; .≯; [V6, X4_2]; .xn--hdh; [V6, A4_2]; ; # .≯
+xn--0ug.xn--hdh; ‌.≯; [C1, V6]; xn--0ug.xn--hdh; ; ; # .≯
+𰅧񣩠-.꯭-悜; 𰅧񣩠-.꯭-悜; [P1, V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+𰅧񣩠-.꯭-悜; ; [P1, V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+xn----7m53aj640l.xn----8f4br83t; 𰅧񣩠-.꯭-悜; [V3, V5, V6]; xn----7m53aj640l.xn----8f4br83t; ; ; # 𰅧-.꯭-悜
+ᡉ𶓧⬞ᢜ.-‍𞣑‮; ; [C2, P1, V3, V6]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; xn--87e0ol04cdl39e.xn----qinu247r; [P1, V3, V6] # ᡉ⬞ᢜ.-𞣑
+xn--87e0ol04cdl39e.xn----qinu247r; ᡉ𶓧⬞ᢜ.-𞣑‮; [V3, V6]; xn--87e0ol04cdl39e.xn----qinu247r; ; ; # ᡉ⬞ᢜ.-𞣑
+xn--87e0ol04cdl39e.xn----ugn5e3763s; ᡉ𶓧⬞ᢜ.-‍𞣑‮; [C2, V3, V6]; xn--87e0ol04cdl39e.xn----ugn5e3763s; ; ; # ᡉ⬞ᢜ.-𞣑
+⒐‌衃Ⴝ.ڂႴ; ; [B1, B2, B3, C1, P1, V6]; xn--1nd159ecmd785k.xn--7ib433c; ; xn--1nd362hy16e.xn--7ib433c; [B1, B2, B3, P1, V6] # ⒐衃Ⴝ.ڂႴ
+9.‌衃Ⴝ.ڂႴ; ; [B1, B2, B3, C1, P1, V6]; 9.xn--1nd159e1y2f.xn--7ib433c; ; 9.xn--1nd9032d.xn--7ib433c; [B1, B2, B3, P1, V6] # 9.衃Ⴝ.ڂႴ
+9.‌衃ⴝ.ڂⴔ; ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; 9.xn--llj1920a.xn--7ib268q; [B1, B2, B3] # 9.衃ⴝ.ڂⴔ
+9.‌衃Ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; 9.xn--1nd159e1y2f.xn--7ib268q; ; 9.xn--1nd9032d.xn--7ib268q; [B1, B2, B3, P1, V6] # 9.衃Ⴝ.ڂⴔ
+9.xn--1nd9032d.xn--7ib268q; 9.衃Ⴝ.ڂⴔ; [B1, B2, B3, V6]; 9.xn--1nd9032d.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ
+9.xn--1nd159e1y2f.xn--7ib268q; 9.‌衃Ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; 9.xn--1nd159e1y2f.xn--7ib268q; ; ; # 9.衃Ⴝ.ڂⴔ
+9.xn--llj1920a.xn--7ib268q; 9.衃ⴝ.ڂⴔ; [B1, B2, B3]; 9.xn--llj1920a.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ
+9.xn--0ug862cbm5e.xn--7ib268q; 9.‌衃ⴝ.ڂⴔ; [B1, B2, B3, C1]; 9.xn--0ug862cbm5e.xn--7ib268q; ; ; # 9.衃ⴝ.ڂⴔ
+9.xn--1nd9032d.xn--7ib433c; 9.衃Ⴝ.ڂႴ; [B1, B2, B3, V6]; 9.xn--1nd9032d.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ
+9.xn--1nd159e1y2f.xn--7ib433c; 9.‌衃Ⴝ.ڂႴ; [B1, B2, B3, C1, V6]; 9.xn--1nd159e1y2f.xn--7ib433c; ; ; # 9.衃Ⴝ.ڂႴ
+⒐‌衃ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; xn--0ugx0px1izu2h.xn--7ib268q; ; xn--1shy52abz3f.xn--7ib268q; [B1, B2, B3, P1, V6] # ⒐衃ⴝ.ڂⴔ
+⒐‌衃Ⴝ.ڂⴔ; ; [B1, B2, B3, C1, P1, V6]; xn--1nd159ecmd785k.xn--7ib268q; ; xn--1nd362hy16e.xn--7ib268q; [B1, B2, B3, P1, V6] # ⒐衃Ⴝ.ڂⴔ
+xn--1nd362hy16e.xn--7ib268q; ⒐衃Ⴝ.ڂⴔ; [B1, B2, B3, V6]; xn--1nd362hy16e.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ
+xn--1nd159ecmd785k.xn--7ib268q; ⒐‌衃Ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; xn--1nd159ecmd785k.xn--7ib268q; ; ; # ⒐衃Ⴝ.ڂⴔ
+xn--1shy52abz3f.xn--7ib268q; ⒐衃ⴝ.ڂⴔ; [B1, B2, B3, V6]; xn--1shy52abz3f.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ
+xn--0ugx0px1izu2h.xn--7ib268q; ⒐‌衃ⴝ.ڂⴔ; [B1, B2, B3, C1, V6]; xn--0ugx0px1izu2h.xn--7ib268q; ; ; # ⒐衃ⴝ.ڂⴔ
+xn--1nd362hy16e.xn--7ib433c; ⒐衃Ⴝ.ڂႴ; [B1, B2, B3, V6]; xn--1nd362hy16e.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ
+xn--1nd159ecmd785k.xn--7ib433c; ⒐‌衃Ⴝ.ڂႴ; [B1, B2, B3, C1, V6]; xn--1nd159ecmd785k.xn--7ib433c; ; ; # ⒐衃Ⴝ.ڂႴ
+ߡ‌。--⸬; ߡ‌.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; xn--8sb.xn-----iw2a; [B1, V3] # ߡ.--⸬
+xn--8sb.xn-----iw2a; ߡ.--⸬; [B1, V3]; xn--8sb.xn-----iw2a; ; ; # ߡ.--⸬
+xn--8sb884j.xn-----iw2a; ߡ‌.--⸬; [B1, B3, C1, V3]; xn--8sb884j.xn-----iw2a; ; ; # ߡ.--⸬
+𞥓.ܘ; 𞥓.ܘ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+𞥓.ܘ; ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+xn--of6h.xn--inb; 𞥓.ܘ; ; xn--of6h.xn--inb; ; ; # 𞥓.ܘ
+󠄽-.-්; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+󠄽-.-්; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+-.xn----ptf; -.-්; [V3]; -.xn----ptf; ; ; # -.-්
+󠇝ݛ-.ᤧ; ݛ-.ᤧ; [B1, B3, B6, V3, V5]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ
+xn----k4c.xn--lff; ݛ-.ᤧ; [B1, B3, B6, V3, V5]; xn----k4c.xn--lff; ; ; # ݛ-.ᤧ
+𞤴󠆹⦉𐹺.꠆⒌󘤸; 𞤴⦉𐹺.꠆⒌󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+𞤴󠆹⦉𐹺.꠆5.󘤸; 𞤴⦉𐹺.꠆5.󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+𞤒󠆹⦉𐹺.꠆5.󘤸; 𞤴⦉𐹺.꠆5.󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+xn--fuix729epewf.xn--5-w93e.xn--7b83e; 𞤴⦉𐹺.꠆5.󘤸; [B1, V5, V6]; xn--fuix729epewf.xn--5-w93e.xn--7b83e; ; ; # 𞤴⦉𐹺.꠆5.
+𞤒󠆹⦉𐹺.꠆⒌󘤸; 𞤴⦉𐹺.꠆⒌󘤸; [B1, P1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+xn--fuix729epewf.xn--xsh5029b6e77i; 𞤴⦉𐹺.꠆⒌󘤸; [B1, V5, V6]; xn--fuix729epewf.xn--xsh5029b6e77i; ; ; # 𞤴⦉𐹺.꠆⒌
+󠄸₀。𑖿‌𐦂‍; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V5] # 0.𑖿𐦂
+󠄸0。𑖿‌𐦂‍; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; 0.xn--mn9cz2s; [B1, V5] # 0.𑖿𐦂
+0.xn--mn9cz2s; 0.𑖿𐦂; [B1, V5]; 0.xn--mn9cz2s; ; ; # 0.𑖿𐦂
+0.xn--0ugc8040p9hk; 0.𑖿‌𐦂‍; [B1, C2, V5]; 0.xn--0ugc8040p9hk; ; ; # 0.𑖿𐦂
+Ⴚ𐋸󠄄。𝟝ퟶ်; Ⴚ𐋸.5ퟶ်; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+Ⴚ𐋸󠄄。5ퟶ်; Ⴚ𐋸.5ퟶ်; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+ⴚ𐋸󠄄。5ퟶ်; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+xn--ilj2659d.xn--5-dug9054m; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+ⴚ𐋸.5ퟶ်; ; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+Ⴚ𐋸.5ퟶ်; ; [P1, V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+xn--ynd2415j.xn--5-dug9054m; Ⴚ𐋸.5ퟶ်; [V6]; xn--ynd2415j.xn--5-dug9054m; ; ; # Ⴚ𐋸.5ퟶ်
+ⴚ𐋸󠄄。𝟝ퟶ်; ⴚ𐋸.5ퟶ်; ; xn--ilj2659d.xn--5-dug9054m; ; ; # ⴚ𐋸.5ퟶ်
+‍-ᠹ﹪.ᷡᤢ; ; [C2, P1, V5, V6]; xn----c6j614b1z4v.xn--gff52t; ; xn----c6jx047j.xn--gff52t; [P1, V3, V5, V6] # -ᠹ﹪.ᷡᤢ
+‍-ᠹ%.ᷡᤢ; ; [C2, P1, V5, V6]; xn---%-u4oy48b.xn--gff52t; ; xn---%-u4o.xn--gff52t; [P1, V3, V5, V6] # -ᠹ%.ᷡᤢ
+xn---%-u4o.xn--gff52t; -ᠹ%.ᷡᤢ; [P1, V3, V5, V6]; xn---%-u4o.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ
+xn---%-u4oy48b.xn--gff52t; ‍-ᠹ%.ᷡᤢ; [C2, P1, V5, V6]; xn---%-u4oy48b.xn--gff52t; ; ; # -ᠹ%.ᷡᤢ
+xn----c6jx047j.xn--gff52t; -ᠹ﹪.ᷡᤢ; [V3, V5, V6]; xn----c6jx047j.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ
+xn----c6j614b1z4v.xn--gff52t; ‍-ᠹ﹪.ᷡᤢ; [C2, V5, V6]; xn----c6j614b1z4v.xn--gff52t; ; ; # -ᠹ﹪.ᷡᤢ
+≠.ᠿ; ; [P1, V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+≠.ᠿ; ≠.ᠿ; [P1, V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+xn--1ch.xn--y7e; ≠.ᠿ; [V6]; xn--1ch.xn--y7e; ; ; # ≠.ᠿ
+ܣ֣。㌪; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+ܣ֣。ハイツ; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+xn--ucb18e.xn--eck4c5a; ܣ֣.ハイツ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+ܣ֣.ハイツ; ; ; xn--ucb18e.xn--eck4c5a; ; ; # ܣ֣.ハイツ
+𞷥󠆀≮.⵿-; 𞷥≮.⵿-; [B1, B3, P1, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+𞷥󠆀≮.⵿-; 𞷥≮.⵿-; [B1, B3, P1, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+xn--gdhx802p.xn----i2s; 𞷥≮.⵿-; [B1, B3, V3, V5, V6]; xn--gdhx802p.xn----i2s; ; ; # ≮.⵿-
+₆榎򦖎്。𞤅ۭﱚ󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+6榎򦖎്。𞤅ۭيي󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+6榎򦖎്。𞤧ۭيي󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+₆榎򦖎്。𞤧ۭﱚ󠮨; 6榎򦖎്.𞤧ۭيي󠮨; [B1, B3, P1, V6]; xn--6-kmf4691ejv41j.xn--mhba10ch545mn8v8h; ; ; # 6榎്.𞤧ۭيي
+𣩫.򌑲; 𣩫.򌑲; [P1, V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+𣩫.򌑲; ; [P1, V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+xn--td3j.xn--4628b; 𣩫.򌑲; [V6]; xn--td3j.xn--4628b; ; ; # 𣩫.
+‍︒。ڹ‌; ‍︒.ڹ‌; [B1, B3, C1, C2, P1, V6]; xn--1ug2658f.xn--skb080k; ; xn--y86c.xn--skb; [B1, P1, V6] # ︒.ڹ
+xn--y86c.xn--skb; ︒.ڹ; [B1, V6]; xn--y86c.xn--skb; ; ; # ︒.ڹ
+xn--1ug2658f.xn--skb080k; ‍︒.ڹ‌; [B1, B3, C1, C2, V6]; xn--1ug2658f.xn--skb080k; ; ; # ︒.ڹ
+xn--skb; ڹ; ; xn--skb; ; ; # ڹ
+ڹ; ; ; xn--skb; ; ; # ڹ
+𐹦‌𐹶。; 𐹦‌𐹶.; [B1, C1, P1, V6]; xn--0ug4994goba.xn--sxg; ; xn--eo0d6a.xn--sxg; [B1, P1, V6] # 𐹦𐹶.
+xn--eo0d6a.xn--sxg; 𐹦𐹶.; [B1, V6]; xn--eo0d6a.xn--sxg; ; ; # 𐹦𐹶.
+xn--0ug4994goba.xn--sxg; 𐹦‌𐹶.; [B1, C1, V6]; xn--0ug4994goba.xn--sxg; ; ; # 𐹦𐹶.
+్𝨾֩𝟭。-𑜨; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+్𝨾֩1。-𑜨; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+xn--1-rfc312cdp45c.xn----nq0j; ్𝨾֩1.-𑜨; [V3, V5]; xn--1-rfc312cdp45c.xn----nq0j; ; ; # ్𝨾֩1.-𑜨
+򣿈。뙏; 򣿈.뙏; [P1, V6]; xn--ph26c.xn--281b; ; ; # .뙏
+򣿈。뙏; 򣿈.뙏; [P1, V6]; xn--ph26c.xn--281b; ; ; # .뙏
+xn--ph26c.xn--281b; 򣿈.뙏; [V6]; xn--ph26c.xn--281b; ; ; # .뙏
+񕨚󠄌󑽀ᡀ.ࢶ; 񕨚󑽀ᡀ.ࢶ; [P1, V6]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ
+xn--z7e98100evc01b.xn--czb; 񕨚󑽀ᡀ.ࢶ; [V6]; xn--z7e98100evc01b.xn--czb; ; ; # ᡀ.ࢶ
+‍。񅁛; ‍.񅁛; [C2, P1, V6]; xn--1ug.xn--6x4u; ; .xn--6x4u; [P1, V6, A4_2] # .
+‍。񅁛; ‍.񅁛; [C2, P1, V6]; xn--1ug.xn--6x4u; ; .xn--6x4u; [P1, V6, A4_2] # .
+.xn--6x4u; .񅁛; [V6, X4_2]; .xn--6x4u; [V6, A4_2]; ; # .
+xn--1ug.xn--6x4u; ‍.񅁛; [C2, V6]; xn--1ug.xn--6x4u; ; ; # .
+ࡋ皥.-; ࡋ皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+ࡋ皥.-; ; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+xn--9vb4167c.-; ࡋ皥.-; [B1, B2, B3, V3]; xn--9vb4167c.-; ; ; # ࡋ皥.-
+𐣸̕𐮇.⒈ꡦ; 𐣸̕𐮇.⒈ꡦ; [B1, P1, V6]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ
+𐣸̕𐮇.1.ꡦ; ; [B1, P1, V6]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ
+xn--5sa9915kgvb.1.xn--cd9a; 𐣸̕𐮇.1.ꡦ; [B1, V6]; xn--5sa9915kgvb.1.xn--cd9a; ; ; # ̕𐮇.1.ꡦ
+xn--5sa9915kgvb.xn--tshw539b; 𐣸̕𐮇.⒈ꡦ; [B1, V6]; xn--5sa9915kgvb.xn--tshw539b; ; ; # ̕𐮇.⒈ꡦ
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠā𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; xn--tcb323r.xn--yda594fdn5q; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; xn--tcb323r.xn--yda594fdn5q; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; xn--tcb597c.xn--yda594fdn5q; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+xn--tcb597c.xn--yda594fdn5q; Ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb597c.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦
+xn--tcb597cdmmfa.xn--yda594fdn5q; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb597cdmmfa.xn--yda594fdn5q; ; ; # Ⴛ֢.ā𐹦
+xn--tcb323r.xn--yda594fdn5q; ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb323r.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦
+xn--tcb736kea974k.xn--yda594fdn5q; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb736kea974k.xn--yda594fdn5q; ; ; # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; xn--tcb323r.xn--yda9741khjj; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+ⴛ‌֢‍。ᅠā𐹦; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; xn--tcb323r.xn--yda9741khjj; [B5, B6, P1, V6] # ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+Ⴛ‌֢‍。ᅠĀ𐹦; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, P1, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; xn--tcb597c.xn--yda9741khjj; [B5, B6, P1, V6] # Ⴛ֢.ā𐹦
+xn--tcb597c.xn--yda9741khjj; Ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb597c.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦
+xn--tcb597cdmmfa.xn--yda9741khjj; Ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb597cdmmfa.xn--yda9741khjj; ; ; # Ⴛ֢.ā𐹦
+xn--tcb323r.xn--yda9741khjj; ⴛ֢.ᅠā𐹦; [B5, B6, V6]; xn--tcb323r.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦
+xn--tcb736kea974k.xn--yda9741khjj; ⴛ‌֢‍.ᅠā𐹦; [B5, B6, C1, C2, V6]; xn--tcb736kea974k.xn--yda9741khjj; ; ; # ⴛ֢.ā𐹦
+‌。曳⾑𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳⾑𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳襾𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+‌。曳襾𐋰≯; ‌.曳襾𐋰≯; [C1, P1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; xn--vn7c.xn--hdh501y8wvfs5h; [P1, V6] # .曳襾𐋰≯
+xn--vn7c.xn--hdh501y8wvfs5h; .曳襾𐋰≯; [V6]; xn--vn7c.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯
+xn--0ug2139f.xn--hdh501y8wvfs5h; ‌.曳襾𐋰≯; [C1, V6]; xn--0ug2139f.xn--hdh501y8wvfs5h; ; ; # .曳襾𐋰≯
+≯⒈。ß; ≯⒈.ß; [P1, V6]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß
+≯⒈。ß; ≯⒈.ß; [P1, V6]; xn--hdh84f.xn--zca; ; xn--hdh84f.ss; # ≯⒈.ß
+≯1.。ß; ≯1..ß; [P1, V6, X4_2]; xn--1-ogo..xn--zca; [P1, V6, A4_2]; xn--1-ogo..ss; # ≯1..ß
+≯1.。ß; ≯1..ß; [P1, V6, X4_2]; xn--1-ogo..xn--zca; [P1, V6, A4_2]; xn--1-ogo..ss; # ≯1..ß
+≯1.。SS; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。SS; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。Ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+≯1.。Ss; ≯1..ss; [P1, V6, X4_2]; xn--1-ogo..ss; [P1, V6, A4_2]; ; # ≯1..ss
+xn--1-ogo..ss; ≯1..ss; [V6, X4_2]; xn--1-ogo..ss; [V6, A4_2]; ; # ≯1..ss
+xn--1-ogo..xn--zca; ≯1..ß; [V6, X4_2]; xn--1-ogo..xn--zca; [V6, A4_2]; ; # ≯1..ß
+≯⒈。SS; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。SS; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。Ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+≯⒈。Ss; ≯⒈.ss; [P1, V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+xn--hdh84f.ss; ≯⒈.ss; [V6]; xn--hdh84f.ss; ; ; # ≯⒈.ss
+xn--hdh84f.xn--zca; ≯⒈.ß; [V6]; xn--hdh84f.xn--zca; ; ; # ≯⒈.ß
+٧‍ﮖ。ߚ-₆Ⴙ; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, P1, V6]; xn--gib6m343e.xn---6-lve002g; ; xn--gib6m.xn---6-lve002g; [B1, B2, B3, P1, V6] # ٧ڳ.ߚ-6Ⴙ
+٧‍ڳ。ߚ-6Ⴙ; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, P1, V6]; xn--gib6m343e.xn---6-lve002g; ; xn--gib6m.xn---6-lve002g; [B1, B2, B3, P1, V6] # ٧ڳ.ߚ-6Ⴙ
+٧‍ڳ。ߚ-6ⴙ; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ
+xn--gib6m.xn---6-lve6529a; ٧ڳ.ߚ-6ⴙ; [B1, B2, B3]; xn--gib6m.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ
+xn--gib6m343e.xn---6-lve6529a; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; ; # ٧ڳ.ߚ-6ⴙ
+xn--gib6m.xn---6-lve002g; ٧ڳ.ߚ-6Ⴙ; [B1, B2, B3, V6]; xn--gib6m.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ
+xn--gib6m343e.xn---6-lve002g; ٧‍ڳ.ߚ-6Ⴙ; [B1, B2, B3, C2, V6]; xn--gib6m343e.xn---6-lve002g; ; ; # ٧ڳ.ߚ-6Ⴙ
+٧‍ﮖ。ߚ-₆ⴙ; ٧‍ڳ.ߚ-6ⴙ; [B1, B2, B3, C2]; xn--gib6m343e.xn---6-lve6529a; ; xn--gib6m.xn---6-lve6529a; [B1, B2, B3] # ٧ڳ.ߚ-6ⴙ
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+‌。≠; ‌.≠; [C1, P1, V6]; xn--0ug.xn--1ch; ; .xn--1ch; [P1, V6, A4_2] # .≠
+.xn--1ch; .≠; [V6, X4_2]; .xn--1ch; [V6, A4_2]; ; # .≠
+xn--0ug.xn--1ch; ‌.≠; [C1, V6]; xn--0ug.xn--1ch; ; ; # .≠
+𑖿𝨔.ᡟ𑖿ᭂ‌; ; [C1, V5]; xn--461dw464a.xn--v8e29ldzfo952a; ; xn--461dw464a.xn--v8e29loy65a; [V5] # 𑖿𝨔.ᡟ𑖿ᭂ
+xn--461dw464a.xn--v8e29loy65a; 𑖿𝨔.ᡟ𑖿ᭂ; [V5]; xn--461dw464a.xn--v8e29loy65a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ
+xn--461dw464a.xn--v8e29ldzfo952a; 𑖿𝨔.ᡟ𑖿ᭂ‌; [C1, V5]; xn--461dw464a.xn--v8e29ldzfo952a; ; ; # 𑖿𝨔.ᡟ𑖿ᭂ
+򔣳‍򑝱.𖬴Ↄ≠-; ; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; xn--6j00chy9a.xn----61n81bt713h; [P1, V3, V5, V6] # .𖬴Ↄ≠-
+򔣳‍򑝱.𖬴Ↄ≠-; 򔣳‍򑝱.𖬴Ↄ≠-; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; xn--6j00chy9a.xn----61n81bt713h; [P1, V3, V5, V6] # .𖬴Ↄ≠-
+򔣳‍򑝱.𖬴ↄ≠-; 򔣳‍򑝱.𖬴ↄ≠-; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [P1, V3, V5, V6] # .𖬴ↄ≠-
+򔣳‍򑝱.𖬴ↄ≠-; ; [C2, P1, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; xn--6j00chy9a.xn----81n51bt713h; [P1, V3, V5, V6] # .𖬴ↄ≠-
+xn--6j00chy9a.xn----81n51bt713h; 򔣳򑝱.𖬴ↄ≠-; [V3, V5, V6]; xn--6j00chy9a.xn----81n51bt713h; ; ; # .𖬴ↄ≠-
+xn--1ug15151gkb5a.xn----81n51bt713h; 򔣳‍򑝱.𖬴ↄ≠-; [C2, V3, V5, V6]; xn--1ug15151gkb5a.xn----81n51bt713h; ; ; # .𖬴ↄ≠-
+xn--6j00chy9a.xn----61n81bt713h; 򔣳򑝱.𖬴Ↄ≠-; [V3, V5, V6]; xn--6j00chy9a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠-
+xn--1ug15151gkb5a.xn----61n81bt713h; 򔣳‍򑝱.𖬴Ↄ≠-; [C2, V3, V5, V6]; xn--1ug15151gkb5a.xn----61n81bt713h; ; ; # .𖬴Ↄ≠-
+ߢς‍𝟳。蔑򛖢; ߢς‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢς7.蔑
+ߢς‍7。蔑򛖢; ߢς‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢς7.蔑
+ߢΣ‍7。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+ߢσ‍7。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+xn--7-zmb872a.xn--wy1ao4929b; ߢσ7.蔑򛖢; [B2, V6]; xn--7-zmb872a.xn--wy1ao4929b; ; ; # ߢσ7.蔑
+xn--7-zmb872aez5a.xn--wy1ao4929b; ߢσ‍7.蔑򛖢; [B2, C2, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; ; # ߢσ7.蔑
+xn--7-xmb182aez5a.xn--wy1ao4929b; ߢς‍7.蔑򛖢; [B2, C2, V6]; xn--7-xmb182aez5a.xn--wy1ao4929b; ; ; # ߢς7.蔑
+ߢΣ‍𝟳。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+ߢσ‍𝟳。蔑򛖢; ߢσ‍7.蔑򛖢; [B2, C2, P1, V6]; xn--7-zmb872aez5a.xn--wy1ao4929b; ; xn--7-zmb872a.xn--wy1ao4929b; [B2, P1, V6] # ߢσ7.蔑
+𐹰.؀; ; [B1, P1, V6]; xn--oo0d.xn--ifb; ; ; # 𐹰.
+xn--oo0d.xn--ifb; 𐹰.؀; [B1, V6]; xn--oo0d.xn--ifb; ; ; # 𐹰.
+-ࢨ.𱠖; ; [B1, P1, V3, V6]; xn----mod.xn--5o9n; ; ; # -ࢨ.
+xn----mod.xn--5o9n; -ࢨ.𱠖; [B1, V3, V6]; xn----mod.xn--5o9n; ; ; # -ࢨ.
+≯𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, P1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+≯𞱸󠇀。誆⒈; ≯𞱸.誆⒈; [B1, P1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+≯𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1, P1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+≯𞱸󠇀。誆1.; ≯𞱸.誆1.; [B1, P1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+xn--hdh7151p.xn--1-dy1d.; ≯𞱸.誆1.; [B1, V6]; xn--hdh7151p.xn--1-dy1d.; ; ; # ≯𞱸.誆1.
+xn--hdh7151p.xn--tsh1248a; ≯𞱸.誆⒈; [B1, V6]; xn--hdh7151p.xn--tsh1248a; ; ; # ≯𞱸.誆⒈
+ؖ𞥙䐊ِ.︒م↺ڜ; ؖ𞥙䐊ِ.︒م↺ڜ; [B1, P1, V5, V6]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ
+ؖ𞥙䐊ِ.。م↺ڜ; ؖ𞥙䐊ِ..م↺ڜ; [B1, V5, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V5, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ
+xn--4fb0j490qjg4x..xn--hhb8o948e; ؖ𞥙䐊ِ..م↺ڜ; [B1, V5, X4_2]; xn--4fb0j490qjg4x..xn--hhb8o948e; [B1, V5, A4_2]; ; # ؖ𞥙䐊ِ..م↺ڜ
+xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ؖ𞥙䐊ِ.︒م↺ڜ; [B1, V5, V6]; xn--4fb0j490qjg4x.xn--hhb8o948euo5r; ; ; # ؖ𞥙䐊ِ.︒م↺ڜ
+퀬-?񶳒.‌ૅ󩸤۴; ; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [P1, V5, V6] # 퀬-?.ૅ۴
+퀬-?񶳒.‌ૅ󩸤۴; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; xn---?-6g4k75207c.xn--hmb76q74166b; [P1, V5, V6] # 퀬-?.ૅ۴
+xn---?-6g4k75207c.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+xn---?-6g4k75207c.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q74166B; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q74166b; 퀬-?񶳒.ૅ󩸤۴; [P1, V5, V6]; xn---?-6g4k75207c.xn--hmb76q74166b; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.xn--hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.XN--HMB76Q48Y18505A; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+퀬-?񶳒.Xn--Hmb76q48y18505a; 퀬-?񶳒.‌ૅ󩸤۴; [C1, P1, V6]; xn---?-6g4k75207c.xn--hmb76q48y18505a; ; ; # 퀬-?.ૅ۴
+Ⴌ.𐹾︒𑁿𞾄; ; [B1, P1, V6]; xn--knd.xn--y86c030a9ob6374b; ; ; # Ⴌ.𐹾︒𑁿
+Ⴌ.𐹾。𑁿𞾄; Ⴌ.𐹾.𑁿𞾄; [B1, P1, V5, V6]; xn--knd.xn--2o0d.xn--q30dg029a; ; ; # Ⴌ.𐹾.𑁿
+ⴌ.𐹾。𑁿𞾄; ⴌ.𐹾.𑁿𞾄; [B1, P1, V5, V6]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿
+xn--3kj.xn--2o0d.xn--q30dg029a; ⴌ.𐹾.𑁿𞾄; [B1, V5, V6]; xn--3kj.xn--2o0d.xn--q30dg029a; ; ; # ⴌ.𐹾.𑁿
+xn--knd.xn--2o0d.xn--q30dg029a; Ⴌ.𐹾.𑁿𞾄; [B1, V5, V6]; xn--knd.xn--2o0d.xn--q30dg029a; ; ; # Ⴌ.𐹾.𑁿
+ⴌ.𐹾︒𑁿𞾄; ; [B1, P1, V6]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿
+xn--3kj.xn--y86c030a9ob6374b; ⴌ.𐹾︒𑁿𞾄; [B1, V6]; xn--3kj.xn--y86c030a9ob6374b; ; ; # ⴌ.𐹾︒𑁿
+xn--knd.xn--y86c030a9ob6374b; Ⴌ.𐹾︒𑁿𞾄; [B1, V6]; xn--knd.xn--y86c030a9ob6374b; ; ; # Ⴌ.𐹾︒𑁿
+񧞿╏。𞩕󠁾; 񧞿╏.𞩕󠁾; [B3, B6, P1, V6]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏.
+xn--iyh90030d.xn--1m6hs0260c; 񧞿╏.𞩕󠁾; [B3, B6, V6]; xn--iyh90030d.xn--1m6hs0260c; ; ; # ╏.
+‍┮󠇐.ఀ్᜴‍; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V5] # ┮.ఀ్᜴
+‍┮󠇐.ఀ్᜴‍; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; xn--kxh.xn--eoc8m432a; [V5] # ┮.ఀ్᜴
+xn--kxh.xn--eoc8m432a; ┮.ఀ్᜴; [V5]; xn--kxh.xn--eoc8m432a; ; ; # ┮.ఀ్᜴
+xn--1ug04r.xn--eoc8m432a40i; ‍┮.ఀ్᜴‍; [C2, V5]; xn--1ug04r.xn--eoc8m432a40i; ; ; # ┮.ఀ్᜴
+򹚪。🄂; 򹚪.🄂; [P1, V6]; xn--n433d.xn--v07h; ; ; # .🄂
+򹚪。1,; 򹚪.1,; [P1, V6]; xn--n433d.1,; ; ; # .1,
+xn--n433d.1,; 򹚪.1,; [P1, V6]; xn--n433d.1,; ; ; # .1,
+xn--n433d.xn--v07h; 򹚪.🄂; [V6]; xn--n433d.xn--v07h; ; ; # .🄂
+𑍨刍.🛦; ; [V5]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦
+xn--rbry728b.xn--y88h; 𑍨刍.🛦; [V5]; xn--rbry728b.xn--y88h; ; ; # 𑍨刍.🛦
+󠌏3。ᯱ𝟒; 󠌏3.ᯱ4; [P1, V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+󠌏3。ᯱ4; 󠌏3.ᯱ4; [P1, V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+xn--3-ib31m.xn--4-pql; 󠌏3.ᯱ4; [V5, V6]; xn--3-ib31m.xn--4-pql; ; ; # 3.ᯱ4
+ڇ6Ⴔ辘.ﴢڇ‌; ڇ6Ⴔ辘.صيڇ‌; [B2, B3, C1, P1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; xn--6-gsc039eqq6k.xn--0gb6bxk; [B2, B3, P1, V6] # ڇ6Ⴔ辘.صيڇ
+ڇ6Ⴔ辘.صيڇ‌; ; [B2, B3, C1, P1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; xn--6-gsc039eqq6k.xn--0gb6bxk; [B2, B3, P1, V6] # ڇ6Ⴔ辘.صيڇ
+ڇ6ⴔ辘.صيڇ‌; ; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ
+xn--6-gsc2270akm6f.xn--0gb6bxk; ڇ6ⴔ辘.صيڇ; [B2, B3]; xn--6-gsc2270akm6f.xn--0gb6bxk; ; ; # ڇ6ⴔ辘.صيڇ
+xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ڇ6ⴔ辘.صيڇ‌; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; ; # ڇ6ⴔ辘.صيڇ
+xn--6-gsc039eqq6k.xn--0gb6bxk; ڇ6Ⴔ辘.صيڇ; [B2, B3, V6]; xn--6-gsc039eqq6k.xn--0gb6bxk; ; ; # ڇ6Ⴔ辘.صيڇ
+xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ڇ6Ⴔ辘.صيڇ‌; [B2, B3, C1, V6]; xn--6-gsc039eqq6k.xn--0gb6bxkx18g; ; ; # ڇ6Ⴔ辘.صيڇ
+ڇ6ⴔ辘.ﴢڇ‌; ڇ6ⴔ辘.صيڇ‌; [B2, B3, C1]; xn--6-gsc2270akm6f.xn--0gb6bxkx18g; ; xn--6-gsc2270akm6f.xn--0gb6bxk; [B2, B3] # ڇ6ⴔ辘.صيڇ
+󠄍.𐮭𞰬򻫞۹; .𐮭𞰬򻫞۹; [B2, P1, V6, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, P1, V6, A4_2]; ; # .𐮭۹
+.xn--mmb3954kd0uf1zx7f; .𐮭𞰬򻫞۹; [B2, V6, X4_2]; .xn--mmb3954kd0uf1zx7f; [B2, V6, A4_2]; ; # .𐮭۹
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+꡽≯.򻲀򒳄; ꡽≯.򻲀򒳄; [P1, V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+xn--hdh8193c.xn--5z40cp629b; ꡽≯.򻲀򒳄; [V6]; xn--hdh8193c.xn--5z40cp629b; ; ; # ≯.
+ςოٻ.ςܔ; ; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # ςოٻ.ςܔ
+ΣᲝٻ.Σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+σოٻ.σܔ; ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+Σოٻ.σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+xn--4xa60l26n.xn--4xa21o; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+Σოٻ.ςܔ; σოٻ.ςܔ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ
+σოٻ.ςܔ; ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; xn--4xa60l26n.xn--4xa21o; # σოٻ.ςܔ
+xn--4xa60l26n.xn--3xa41o; σოٻ.ςܔ; [B5, B6]; xn--4xa60l26n.xn--3xa41o; ; ; # σოٻ.ςܔ
+xn--3xa80l26n.xn--3xa41o; ςოٻ.ςܔ; [B5, B6]; xn--3xa80l26n.xn--3xa41o; ; ; # ςოٻ.ςܔ
+Σოٻ.Σܔ; σოٻ.σܔ; [B5, B6]; xn--4xa60l26n.xn--4xa21o; ; ; # σოٻ.σܔ
+򄖚݈𠄯ݟ。󠛩; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, P1, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+򄖚݈𠄯ݟ。󠛩; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, P1, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+xn--vob0c4369twfv8b.xn--kl46e; 򄖚݈𠄯ݟ.󠛩; [B1, B5, B6, V6]; xn--vob0c4369twfv8b.xn--kl46e; ; ; # ݈𠄯ݟ.
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠Ⴞ; 󠳛.‍䤫≠Ⴞ; [C2, P1, V6]; xn--1t56e.xn--2nd159e9vb743e; ; xn--1t56e.xn--2nd141ghl2a; [P1, V6] # .䤫≠Ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+󠳛.‍䤫≠ⴞ; ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+xn--1t56e.xn--1ch153bqvw; 󠳛.䤫≠ⴞ; [V6]; xn--1t56e.xn--1ch153bqvw; ; ; # .䤫≠ⴞ
+xn--1t56e.xn--1ug73gzzpwi3a; 󠳛.‍䤫≠ⴞ; [C2, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; ; # .䤫≠ⴞ
+xn--1t56e.xn--2nd141ghl2a; 󠳛.䤫≠Ⴞ; [V6]; xn--1t56e.xn--2nd141ghl2a; ; ; # .䤫≠Ⴞ
+xn--1t56e.xn--2nd159e9vb743e; 󠳛.‍䤫≠Ⴞ; [C2, V6]; xn--1t56e.xn--2nd159e9vb743e; ; ; # .䤫≠Ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+󠳛.‍䤫≠ⴞ; 󠳛.‍䤫≠ⴞ; [C2, P1, V6]; xn--1t56e.xn--1ug73gzzpwi3a; ; xn--1t56e.xn--1ch153bqvw; [P1, V6] # .䤫≠ⴞ
+𐽘𑈵.𐹣🕥; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+𐽘𑈵.𐹣🕥; ; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+xn--bv0d02c.xn--bo0dq650b; 𐽘𑈵.𐹣🕥; [B1, B2, B3]; xn--bv0d02c.xn--bo0dq650b; ; ; # 𐽘𑈵.𐹣🕥
+⒊⒈𑁄。9; ⒊⒈𑁄.9; [P1, V6]; xn--tshd3512p.9; ; ; # ⒊⒈𑁄.9
+3.1.𑁄。9; 3.1.𑁄.9; [V5]; 3.1.xn--110d.9; ; ; # 3.1.𑁄.9
+3.1.xn--110d.9; 3.1.𑁄.9; [V5]; 3.1.xn--110d.9; ; ; # 3.1.𑁄.9
+xn--tshd3512p.9; ⒊⒈𑁄.9; [V6]; xn--tshd3512p.9; ; ; # ⒊⒈𑁄.9
+-‌ⷱ≮.𐹱򭏴4₉; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴4₉; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴49; ; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+-‌ⷱ≮.𐹱򭏴49; -‌ⷱ≮.𐹱򭏴49; [B1, C1, P1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; xn----ngo823c.xn--49-ki3om2611f; [B1, P1, V3, V6] # -ⷱ≮.𐹱49
+xn----ngo823c.xn--49-ki3om2611f; -ⷱ≮.𐹱򭏴49; [B1, V3, V6]; xn----ngo823c.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49
+xn----sgn20i14s.xn--49-ki3om2611f; -‌ⷱ≮.𐹱򭏴49; [B1, C1, V3, V6]; xn----sgn20i14s.xn--49-ki3om2611f; ; ; # -ⷱ≮.𐹱49
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+-≯딾。ࡇ; -≯딾.ࡇ; [B1, P1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+xn----pgow547d.xn--5vb; -≯딾.ࡇ; [B1, V3, V6]; xn----pgow547d.xn--5vb; ; ; # -≯딾.ࡇ
+𑙢⒈𐹠-。󠗐‌; 𑙢⒈𐹠-.󠗐‌; [B1, C1, P1, V3, V6]; xn----dcpy090hiyg.xn--0ug23321l; ; xn----dcpy090hiyg.xn--jd46e; [B1, P1, V3, V6] # 𑙢⒈𐹠-.
+𑙢1.𐹠-。󠗐‌; 𑙢1.𐹠-.󠗐‌; [B1, C1, P1, V3, V6]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; xn--1-bf0j.xn----516i.xn--jd46e; [B1, P1, V3, V6] # 𑙢1.𐹠-.
+xn--1-bf0j.xn----516i.xn--jd46e; 𑙢1.𐹠-.󠗐; [B1, V3, V6]; xn--1-bf0j.xn----516i.xn--jd46e; ; ; # 𑙢1.𐹠-.
+xn--1-bf0j.xn----516i.xn--0ug23321l; 𑙢1.𐹠-.󠗐‌; [B1, C1, V3, V6]; xn--1-bf0j.xn----516i.xn--0ug23321l; ; ; # 𑙢1.𐹠-.
+xn----dcpy090hiyg.xn--jd46e; 𑙢⒈𐹠-.󠗐; [B1, V3, V6]; xn----dcpy090hiyg.xn--jd46e; ; ; # 𑙢⒈𐹠-.
+xn----dcpy090hiyg.xn--0ug23321l; 𑙢⒈𐹠-.󠗐‌; [B1, C1, V3, V6]; xn----dcpy090hiyg.xn--0ug23321l; ; ; # 𑙢⒈𐹠-.
+͊.𐨎; ͊.𐨎; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+͊.𐨎; ; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+xn--oua.xn--mr9c; ͊.𐨎; [V5]; xn--oua.xn--mr9c; ; ; # ͊.𐨎
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+훉≮。ิ; 훉≮.ิ; [P1, V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+xn--gdh2512e.xn--i4c; 훉≮.ิ; [V5, V6]; xn--gdh2512e.xn--i4c; ; ; # 훉≮.ิ
+ⷷ򞣉🃘.𴈇𝟸ٙ𞤯; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇2ٙ𞤯; ; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇2ٙ𞤍; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+xn--trj8045le6s9b.xn--2-upc23918acjsj; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+ⷷ򞣉🃘.𴈇𝟸ٙ𞤍; ⷷ򞣉🃘.𴈇2ٙ𞤯; [B1, B5, B6, P1, V5, V6]; xn--trj8045le6s9b.xn--2-upc23918acjsj; ; ; # ⷷ🃘.2ٙ𞤯
+󗇩ßᢞ‌。٠𞷻ﳔ-; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ßᢞ.٠نخ-
+󗇩ßᢞ‌。٠𞷻نخ-; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ßᢞ.٠نخ-
+󗇩SSᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩ssᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩Ssᢞ‌。٠𞷻نخ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+xn--ss-jepz4596r.xn----dnc5e1er384z; 󗇩ssᢞ.٠𞷻نخ-; [B1, V3, V6]; xn--ss-jepz4596r.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ-
+xn--ss-jep006bqt765b.xn----dnc5e1er384z; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; ; # ssᢞ.٠نخ-
+xn--zca272jbif10059a.xn----dnc5e1er384z; 󗇩ßᢞ‌.٠𞷻نخ-; [B1, B6, C1, V3, V6]; xn--zca272jbif10059a.xn----dnc5e1er384z; ; ; # ßᢞ.٠نخ-
+󗇩SSᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩ssᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+󗇩Ssᢞ‌。٠𞷻ﳔ-; 󗇩ssᢞ‌.٠𞷻نخ-; [B1, B6, C1, P1, V3, V6]; xn--ss-jep006bqt765b.xn----dnc5e1er384z; ; xn--ss-jepz4596r.xn----dnc5e1er384z; [B1, P1, V3, V6] # ssᢞ.٠نخ-
+ꡆ。Ↄྵ놮-; ꡆ.Ↄྵ놮-; [P1, V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ꡆ。Ↄྵ놮-; ꡆ.Ↄྵ놮-; [P1, V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ꡆ。ↄྵ놮-; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+ꡆ。ↄྵ놮-; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+xn--fc9a.xn----qmg097k469k; ꡆ.ↄྵ놮-; [V3]; xn--fc9a.xn----qmg097k469k; ; ; # ꡆ.ↄྵ놮-
+xn--fc9a.xn----qmg787k869k; ꡆ.Ↄྵ놮-; [V3, V6]; xn--fc9a.xn----qmg787k869k; ; ; # ꡆ.Ↄྵ놮-
+ﶭ‍.񥰌ک; لمي‍.񥰌ک; [B3, B5, B6, C2, P1, V6]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, P1, V6] # لمي.ک
+لمي‍.񥰌ک; ; [B3, B5, B6, C2, P1, V6]; xn--ghbcp494x.xn--ckb36214f; ; xn--ghbcp.xn--ckb36214f; [B5, B6, P1, V6] # لمي.ک
+xn--ghbcp.xn--ckb36214f; لمي.񥰌ک; [B5, B6, V6]; xn--ghbcp.xn--ckb36214f; ; ; # لمي.ک
+xn--ghbcp494x.xn--ckb36214f; لمي‍.񥰌ک; [B3, B5, B6, C2, V6]; xn--ghbcp494x.xn--ckb36214f; ; ; # لمي.ک
+Ⴜᰯ𐳒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐳒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+ⴜᰯ𐳒≯。۠ᜲྺ; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+ⴜᰯ𐳒≯。۠ᜲྺ; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐲒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+Ⴜᰯ𐲒≯。۠ᜲྺ; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, P1, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+xn--0nd679cf3eq67y.xn--wlb646b4ng; Ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, V5, V6]; xn--0nd679cf3eq67y.xn--wlb646b4ng; ; ; # Ⴜᰯ𐳒≯.۠ᜲྺ
+xn--r1f68xh1jgv7u.xn--wlb646b4ng; ⴜᰯ𐳒≯.۠ᜲྺ; [B1, B3, B5, B6, V5, V6]; xn--r1f68xh1jgv7u.xn--wlb646b4ng; ; ; # ⴜᰯ𐳒≯.۠ᜲྺ
+𐋵。ﳬ; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+𐋵。كم; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+xn--p97c.xn--fhbe; 𐋵.كم; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+𐋵.كم; ; [B1]; xn--p97c.xn--fhbe; ; ; # 𐋵.كم
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+≮𝅶.񱲁ꫬ⹈󰥭; ≮𝅶.񱲁ꫬ⹈󰥭; [P1, V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ≮𝅶.񱲁ꫬ⹈󰥭; [V6]; xn--gdh0880o.xn--4tjx101bsg00ds9pyc; ; ; # ≮.ꫬ⹈
+ⷰ͘ᢕ.͡𐹷󠴍; ⷰ͘ᢕ.͡𐹷󠴍; [B1, P1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+ⷰ͘ᢕ.͡𐹷󠴍; ; [B1, P1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+xn--2ua889htsp.xn--cva2687k2tv0g; ⷰ͘ᢕ.͡𐹷󠴍; [B1, V5, V6]; xn--2ua889htsp.xn--cva2687k2tv0g; ; ; # ⷰ͘ᢕ.͡𐹷
+ﵹᡐ‌ڭ.𑋪ׇ; غممᡐ‌ڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ
+غممᡐ‌ڭ.𑋪ׇ; ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; xn--5gbwa03bg24e.xn--vdb1198k; # غممᡐڭ.𑋪ׇ
+xn--5gbwa03bg24e.xn--vdb1198k; غممᡐڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24e.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ
+xn--5gbwa03bg24eptk.xn--vdb1198k; غممᡐ‌ڭ.𑋪ׇ; [B1, B2, B3, B6, V5]; xn--5gbwa03bg24eptk.xn--vdb1198k; ; ; # غممᡐڭ.𑋪ׇ
+𑑂。‍󥞀🞕򥁔; 𑑂.‍󥞀🞕򥁔; [C2, P1, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [P1, V5, V6] # 𑑂.🞕
+𑑂。‍󥞀🞕򥁔; 𑑂.‍󥞀🞕򥁔; [C2, P1, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; xn--8v1d.xn--ye9h41035a2qqs; [P1, V5, V6] # 𑑂.🞕
+xn--8v1d.xn--ye9h41035a2qqs; 𑑂.󥞀🞕򥁔; [V5, V6]; xn--8v1d.xn--ye9h41035a2qqs; ; ; # 𑑂.🞕
+xn--8v1d.xn--1ug1386plvx1cd8vya; 𑑂.‍󥞀🞕򥁔; [C2, V5, V6]; xn--8v1d.xn--1ug1386plvx1cd8vya; ; ; # 𑑂.🞕
+-ש。⒚; -ש.⒚; [B1, P1, V3, V6]; xn----gjc.xn--cth; ; ; # -ש.⒚
+-ש。19.; -ש.19.; [B1, V3]; xn----gjc.19.; ; ; # -ש.19.
+xn----gjc.19.; -ש.19.; [B1, V3]; xn----gjc.19.; ; ; # -ש.19.
+xn----gjc.xn--cth; -ש.⒚; [B1, V3, V6]; xn----gjc.xn--cth; ; ; # -ש.⒚
+􊾻ࡅ‌。ᢎ‍; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, P1, V6]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, P1, V6] # ࡅ.ᢎ
+􊾻ࡅ‌。ᢎ‍; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, P1, V6]; xn--3vb882jz4411a.xn--79e259a; ; xn--3vb50049s.xn--79e; [B5, B6, P1, V6] # ࡅ.ᢎ
+xn--3vb50049s.xn--79e; 􊾻ࡅ.ᢎ; [B5, B6, V6]; xn--3vb50049s.xn--79e; ; ; # ࡅ.ᢎ
+xn--3vb882jz4411a.xn--79e259a; 􊾻ࡅ‌.ᢎ‍; [B5, B6, C1, C2, V6]; xn--3vb882jz4411a.xn--79e259a; ; ; # ࡅ.ᢎ
+ßুᷭ。ؠ8₅; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+ßুᷭ。ؠ85; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+SSুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ。ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+xn--ss-e2f077r.xn--85-psd; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ.ؠ85; ; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+SSুᷭ.ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ.ؠ85; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+xn--zca266bwrr.xn--85-psd; ßুᷭ.ؠ85; ; xn--zca266bwrr.xn--85-psd; ; ; # ßুᷭ.ؠ85
+ßুᷭ.ؠ85; ; ; xn--zca266bwrr.xn--85-psd; ; xn--ss-e2f077r.xn--85-psd; # ßুᷭ.ؠ85
+SSুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+ssুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+Ssুᷭ。ؠ8₅; ssুᷭ.ؠ85; ; xn--ss-e2f077r.xn--85-psd; ; ; # ssুᷭ.ؠ85
+્҄魅𝟣.₃𐹥ß; ્҄魅1.3𐹥ß; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß
+્҄魅1.3𐹥ß; ; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; xn--1-0xb049b102o.xn--3ss-nv9t; # ્҄魅1.3𐹥ß
+્҄魅1.3𐹥SS; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅1.3𐹥ss; ; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅1.3𐹥Ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+xn--1-0xb049b102o.xn--3ss-nv9t; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+xn--1-0xb049b102o.xn--3-qfa7018r; ્҄魅1.3𐹥ß; [B1, V5]; xn--1-0xb049b102o.xn--3-qfa7018r; ; ; # ્҄魅1.3𐹥ß
+્҄魅𝟣.₃𐹥SS; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅𝟣.₃𐹥ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+્҄魅𝟣.₃𐹥Ss; ્҄魅1.3𐹥ss; [B1, V5]; xn--1-0xb049b102o.xn--3ss-nv9t; ; ; # ્҄魅1.3𐹥ss
+ܫ。𑓂⒈𑜫󠿻; ܫ.𑓂⒈𑜫󠿻; [B1, P1, V5, V6]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫
+ܫ。𑓂1.𑜫󠿻; ܫ.𑓂1.𑜫󠿻; [B1, P1, V5, V6]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫
+xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ܫ.𑓂1.𑜫󠿻; [B1, V5, V6]; xn--1nb.xn--1-jq9i.xn--ji2dg9877c; ; ; # ܫ.𑓂1.𑜫
+xn--1nb.xn--tsh7798f6rbrt828c; ܫ.𑓂⒈𑜫󠿻; [B1, V5, V6]; xn--1nb.xn--tsh7798f6rbrt828c; ; ; # ܫ.𑓂⒈𑜫
+︍છ。嵨; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨
+xn--6dc.xn--tot; છ.嵨; ; xn--6dc.xn--tot; ; ; # છ.嵨
+છ.嵨; ; ; xn--6dc.xn--tot; ; ; # છ.嵨
+Ⴔ≠Ⴀ.𐹥𐹰; ; [B1, P1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+Ⴔ≠Ⴀ.𐹥𐹰; Ⴔ≠Ⴀ.𐹥𐹰; [B1, P1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+ⴔ≠ⴀ.𐹥𐹰; ⴔ≠ⴀ.𐹥𐹰; [B1, P1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+ⴔ≠ⴀ.𐹥𐹰; ; [B1, P1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+xn--1ch603bxb.xn--do0dwa; ⴔ≠ⴀ.𐹥𐹰; [B1, V6]; xn--1ch603bxb.xn--do0dwa; ; ; # ⴔ≠ⴀ.𐹥𐹰
+xn--7md3b171g.xn--do0dwa; Ⴔ≠Ⴀ.𐹥𐹰; [B1, V6]; xn--7md3b171g.xn--do0dwa; ; ; # Ⴔ≠Ⴀ.𐹥𐹰
+-‌⒙𐫥。𝨵; -‌⒙𐫥.𝨵; [C1, P1, V3, V5, V6]; xn----sgn18r3191a.xn--382h; ; xn----ddps939g.xn--382h; [P1, V3, V5, V6] # -⒙𐫥.𝨵
+-‌18.𐫥。𝨵; -‌18.𐫥.𝨵; [C1, V3, V5]; xn---18-9m0a.xn--rx9c.xn--382h; ; -18.xn--rx9c.xn--382h; [V3, V5] # -18.𐫥.𝨵
+-18.xn--rx9c.xn--382h; -18.𐫥.𝨵; [V3, V5]; -18.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵
+xn---18-9m0a.xn--rx9c.xn--382h; -‌18.𐫥.𝨵; [C1, V3, V5]; xn---18-9m0a.xn--rx9c.xn--382h; ; ; # -18.𐫥.𝨵
+xn----ddps939g.xn--382h; -⒙𐫥.𝨵; [V3, V5, V6]; xn----ddps939g.xn--382h; ; ; # -⒙𐫥.𝨵
+xn----sgn18r3191a.xn--382h; -‌⒙𐫥.𝨵; [C1, V3, V5, V6]; xn----sgn18r3191a.xn--382h; ; ; # -⒙𐫥.𝨵
+︒.ʌᠣ-𐹽; ; [B1, B5, B6, P1, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+。.ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+。.Ʌᠣ-𐹽; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+..xn----73a596nuh9t; ..ʌᠣ-𐹽; [B5, B6, X4_2]; ..xn----73a596nuh9t; [B5, B6, A4_2]; ; # ..ʌᠣ-𐹽
+︒.Ʌᠣ-𐹽; ︒.ʌᠣ-𐹽; [B1, B5, B6, P1, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+xn--y86c.xn----73a596nuh9t; ︒.ʌᠣ-𐹽; [B1, B5, B6, V6]; xn--y86c.xn----73a596nuh9t; ; ; # ︒.ʌᠣ-𐹽
+︅︒。𦀾᳠; ︒.𦀾᳠; [P1, V6]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠
+︅。。𦀾᳠; ..𦀾᳠; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠
+..xn--t6f5138v; ..𦀾᳠; [X4_2]; ..xn--t6f5138v; [A4_2]; ; # ..𦀾᳠
+xn--y86c.xn--t6f5138v; ︒.𦀾᳠; [V6]; xn--y86c.xn--t6f5138v; ; ; # ︒.𦀾᳠
+xn--t6f5138v; 𦀾᳠; ; xn--t6f5138v; ; ; # 𦀾᳠
+𦀾᳠; ; ; xn--t6f5138v; ; ; # 𦀾᳠
+𞮑ß􏞞。ᡁ; 𞮑ß􏞞.ᡁ; [B2, B3, P1, V6]; xn--zca9432wb989f.xn--07e; ; xn--ss-o412ac6305g.xn--07e; # ß.ᡁ
+𞮑SS􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+𞮑ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+𞮑Ss􏞞。ᡁ; 𞮑ss􏞞.ᡁ; [B2, B3, P1, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+xn--ss-o412ac6305g.xn--07e; 𞮑ss􏞞.ᡁ; [B2, B3, V6]; xn--ss-o412ac6305g.xn--07e; ; ; # ss.ᡁ
+xn--zca9432wb989f.xn--07e; 𞮑ß􏞞.ᡁ; [B2, B3, V6]; xn--zca9432wb989f.xn--07e; ; ; # ß.ᡁ
+꥓‍ج٬。𱆎󻡟‌󠅆; ꥓‍ج٬.𱆎󻡟‌; [B5, B6, C1, P1, V5, V6]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; xn--rgb2k6711c.xn--ec8nj3948b; [B5, B6, P1, V5, V6] # ꥓ج٬.𱆎
+xn--rgb2k6711c.xn--ec8nj3948b; ꥓ج٬.𱆎󻡟; [B5, B6, V5, V6]; xn--rgb2k6711c.xn--ec8nj3948b; ; ; # ꥓ج٬.𱆎
+xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ꥓‍ج٬.𱆎󻡟‌; [B5, B6, C1, V5, V6]; xn--rgb2k500fhq9j.xn--0ug78870a5sp9d; ; ; # ꥓ج٬.𱆎
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; ; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-ß‌≠; 󠕏.-ß‌≠; [C1, P1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ß≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; ; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+xn--u836e.xn---ss-gl2a; 󠕏.-ss≠; [V3, V6]; xn--u836e.xn---ss-gl2a; ; ; # .-ss≠
+xn--u836e.xn---ss-cn0at5l; 󠕏.-ss‌≠; [C1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; ; # .-ss≠
+xn--u836e.xn----qfa750ve7b; 󠕏.-ß‌≠; [C1, V3, V6]; xn--u836e.xn----qfa750ve7b; ; ; # .-ß≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-SS‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+󠕏.-Ss‌≠; 󠕏.-ss‌≠; [C1, P1, V3, V6]; xn--u836e.xn---ss-cn0at5l; ; xn--u836e.xn---ss-gl2a; [P1, V3, V6] # .-ss≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+ᡙ‌。≯𐋲≠; ᡙ‌.≯𐋲≠; [C1, P1, V6]; xn--p8e650b.xn--1ch3a7084l; ; xn--p8e.xn--1ch3a7084l; [P1, V6] # ᡙ.≯𐋲≠
+xn--p8e.xn--1ch3a7084l; ᡙ.≯𐋲≠; [V6]; xn--p8e.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠
+xn--p8e650b.xn--1ch3a7084l; ᡙ‌.≯𐋲≠; [C1, V6]; xn--p8e650b.xn--1ch3a7084l; ; ; # ᡙ.≯𐋲≠
+𐹧𞲄󠁭񆼩。͎🄀; 𐹧𞲄󠁭񆼩.͎🄀; [B1, P1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀
+𐹧𞲄󠁭񆼩。͎0.; 𐹧𞲄󠁭񆼩.͎0.; [B1, P1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; ; ; # 𐹧𞲄.͎0.
+xn--fo0dw409aq58qrn69d.xn--0-bgb.; 𐹧𞲄󠁭񆼩.͎0.; [B1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--0-bgb.; ; ; # 𐹧𞲄.͎0.
+xn--fo0dw409aq58qrn69d.xn--sua6883w; 𐹧𞲄󠁭񆼩.͎🄀; [B1, V5, V6]; xn--fo0dw409aq58qrn69d.xn--sua6883w; ; ; # 𐹧𞲄.͎🄀
+Ⴄ.‍ܡ󻣋ς; Ⴄ.‍ܡ󻣋ς; [B1, C2, P1, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡς
+Ⴄ.‍ܡ󻣋ς; ; [B1, C2, P1, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡς
+ⴄ.‍ܡ󻣋ς; ; [B1, C2, P1, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡς
+Ⴄ.‍ܡ󻣋Σ; Ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡσ
+ⴄ.‍ܡ󻣋σ; ; [B1, C2, P1, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡσ
+xn--vkj.xn--4xa73ob5892c; ⴄ.ܡ󻣋σ; [B2, B3, V6]; xn--vkj.xn--4xa73ob5892c; ; ; # ⴄ.ܡσ
+xn--vkj.xn--4xa73o3t5ajq467a; ⴄ.‍ܡ󻣋σ; [B1, C2, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; ; # ⴄ.ܡσ
+xn--cnd.xn--4xa73ob5892c; Ⴄ.ܡ󻣋σ; [B2, B3, V6]; xn--cnd.xn--4xa73ob5892c; ; ; # Ⴄ.ܡσ
+xn--cnd.xn--4xa73o3t5ajq467a; Ⴄ.‍ܡ󻣋σ; [B1, C2, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; ; # Ⴄ.ܡσ
+xn--vkj.xn--3xa93o3t5ajq467a; ⴄ.‍ܡ󻣋ς; [B1, C2, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; ; # ⴄ.ܡς
+xn--cnd.xn--3xa93o3t5ajq467a; Ⴄ.‍ܡ󻣋ς; [B1, C2, V6]; xn--cnd.xn--3xa93o3t5ajq467a; ; ; # Ⴄ.ܡς
+ⴄ.‍ܡ󻣋ς; ⴄ.‍ܡ󻣋ς; [B1, C2, P1, V6]; xn--vkj.xn--3xa93o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡς
+Ⴄ.‍ܡ󻣋Σ; Ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--cnd.xn--4xa73o3t5ajq467a; ; xn--cnd.xn--4xa73ob5892c; [B2, B3, P1, V6] # Ⴄ.ܡσ
+ⴄ.‍ܡ󻣋σ; ⴄ.‍ܡ󻣋σ; [B1, C2, P1, V6]; xn--vkj.xn--4xa73o3t5ajq467a; ; xn--vkj.xn--4xa73ob5892c; [B2, B3, P1, V6] # ⴄ.ܡσ
+򮵛ؓ.Ⴕ; ; [P1, V6]; xn--1fb94204l.xn--tnd; ; ; # ؓ.Ⴕ
+򮵛ؓ.ⴕ; ; [P1, V6]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ
+xn--1fb94204l.xn--dlj; 򮵛ؓ.ⴕ; [V6]; xn--1fb94204l.xn--dlj; ; ; # ؓ.ⴕ
+xn--1fb94204l.xn--tnd; 򮵛ؓ.Ⴕ; [V6]; xn--1fb94204l.xn--tnd; ; ; # ؓ.Ⴕ
+≯ᷳ𞤥。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤥。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤃。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+≯ᷳ𞤃。‌꣄󠪉‍; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, P1, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; xn--ofg13qyr21c.xn--0f9au6706d; [B1, P1, V5, V6] # ≯ᷳ𞤥.꣄
+xn--ofg13qyr21c.xn--0f9au6706d; ≯ᷳ𞤥.꣄󠪉; [B1, V5, V6]; xn--ofg13qyr21c.xn--0f9au6706d; ; ; # ≯ᷳ𞤥.꣄
+xn--ofg13qyr21c.xn--0ugc0116hix29k; ≯ᷳ𞤥.‌꣄󠪉‍; [B1, C1, C2, V6]; xn--ofg13qyr21c.xn--0ugc0116hix29k; ; ; # ≯ᷳ𞤥.꣄
+‌󠄷。򒑁; ‌.򒑁; [C1, P1, V6]; xn--0ug.xn--w720c; ; .xn--w720c; [P1, V6, A4_2] # .
+‌󠄷。򒑁; ‌.򒑁; [C1, P1, V6]; xn--0ug.xn--w720c; ; .xn--w720c; [P1, V6, A4_2] # .
+.xn--w720c; .򒑁; [V6, X4_2]; .xn--w720c; [V6, A4_2]; ; # .
+xn--0ug.xn--w720c; ‌.򒑁; [C1, V6]; xn--0ug.xn--w720c; ; ; # .
+⒈ූ焅.󗡙‍ꡟ; ; [C2, P1, V6]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; xn--t1c337io97c.xn--4c9a21133d; [P1, V6] # ⒈ූ焅.ꡟ
+1.ූ焅.󗡙‍ꡟ; ; [C2, P1, V5, V6]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; 1.xn--t1c6981c.xn--4c9a21133d; [P1, V5, V6] # 1.ූ焅.ꡟ
+1.xn--t1c6981c.xn--4c9a21133d; 1.ූ焅.󗡙ꡟ; [V5, V6]; 1.xn--t1c6981c.xn--4c9a21133d; ; ; # 1.ූ焅.ꡟ
+1.xn--t1c6981c.xn--1ugz184c9lw7i; 1.ූ焅.󗡙‍ꡟ; [C2, V5, V6]; 1.xn--t1c6981c.xn--1ugz184c9lw7i; ; ; # 1.ූ焅.ꡟ
+xn--t1c337io97c.xn--4c9a21133d; ⒈ූ焅.󗡙ꡟ; [V6]; xn--t1c337io97c.xn--4c9a21133d; ; ; # ⒈ූ焅.ꡟ
+xn--t1c337io97c.xn--1ugz184c9lw7i; ⒈ූ焅.󗡙‍ꡟ; [C2, V6]; xn--t1c337io97c.xn--1ugz184c9lw7i; ; ; # ⒈ූ焅.ꡟ
+᷍ς≮.ς𝪦𞤕0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤕0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤷0; ᷍ς≮.ς𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍ς≮.ς𝪦𞤷0; ; [B1, B5, P1, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; xn--4xa544kvid.xn--0-zmb55727aggma; # ᷍ς≮.ς𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤷0; ; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍Σ≮.Σ𝪦𞤷0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+xn--4xa544kvid.xn--0-zmb55727aggma; ᷍σ≮.σ𝪦𞤷0; [B1, B5, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+xn--3xa744kvid.xn--0-xmb85727aggma; ᷍ς≮.ς𝪦𞤷0; [B1, B5, V5, V6]; xn--3xa744kvid.xn--0-xmb85727aggma; ; ; # ᷍ς≮.ς𝪦𞤷0
+᷍σ≮.σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+᷍σ≮.σ𝪦𞤕0; ᷍σ≮.σ𝪦𞤷0; [B1, B5, P1, V5, V6]; xn--4xa544kvid.xn--0-zmb55727aggma; ; ; # ᷍σ≮.σ𝪦𞤷0
+򢦾ßֹ𐫙.֭ࢡ; ; [B1, B5, B6, P1, V5, V6]; xn--zca89v339zj118e.xn--4cb62m; ; xn--ss-xjd6058xlz50g.xn--4cb62m; # ßֹ𐫙.֭ࢡ
+򢦾SSֹ𐫙.֭ࢡ; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+򢦾ssֹ𐫙.֭ࢡ; ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+򢦾Ssֹ𐫙.֭ࢡ; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, P1, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+xn--ss-xjd6058xlz50g.xn--4cb62m; 򢦾ssֹ𐫙.֭ࢡ; [B1, B5, B6, V5, V6]; xn--ss-xjd6058xlz50g.xn--4cb62m; ; ; # ssֹ𐫙.֭ࢡ
+xn--zca89v339zj118e.xn--4cb62m; 򢦾ßֹ𐫙.֭ࢡ; [B1, B5, B6, V5, V6]; xn--zca89v339zj118e.xn--4cb62m; ; ; # ßֹ𐫙.֭ࢡ
+-𞣄。⒈; -𞣄.⒈; [B1, P1, V3, V6]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈
+-𞣄。1.; -𞣄.1.; [B1, V3]; xn----xc8r.1.; ; ; # -𞣄.1.
+xn----xc8r.1.; -𞣄.1.; [B1, V3]; xn----xc8r.1.; ; ; # -𞣄.1.
+xn----xc8r.xn--tsh; -𞣄.⒈; [B1, V3, V6]; xn----xc8r.xn--tsh; ; ; # -𞣄.⒈
+񈠢𐫖𝟡。ؾ𑘿; 񈠢𐫖9.ؾ𑘿; [B5, P1, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+񈠢𐫖9。ؾ𑘿; 񈠢𐫖9.ؾ𑘿; [B5, P1, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+xn--9-el5iv442t.xn--9gb0830l; 񈠢𐫖9.ؾ𑘿; [B5, V6]; xn--9-el5iv442t.xn--9gb0830l; ; ; # 𐫖9.ؾ𑘿
+٨ﲌ٨ᩝ.‍; ٨نم٨ᩝ.‍; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1] # ٨نم٨ᩝ.
+٨نم٨ᩝ.‍; ; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; xn--hhbb5hc956w.; [B1] # ٨نم٨ᩝ.
+xn--hhbb5hc956w.; ٨نم٨ᩝ.; [B1]; xn--hhbb5hc956w.; ; ; # ٨نم٨ᩝ.
+xn--hhbb5hc956w.xn--1ug; ٨نم٨ᩝ.‍; [B1, C2]; xn--hhbb5hc956w.xn--1ug; ; ; # ٨نم٨ᩝ.
+𝟘.Ⴇ󀳑ﵐ񫃱; 0.Ⴇ󀳑تجم񫃱; [B1, B5, P1, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+0.Ⴇ󀳑تجم񫃱; ; [B1, B5, P1, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+0.ⴇ󀳑تجم񫃱; ; [B1, B5, P1, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+0.xn--pgbe9ez79qd207lvff8b; 0.ⴇ󀳑تجم񫃱; [B1, B5, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+0.xn--pgbe9e344c2725svff8b; 0.Ⴇ󀳑تجم񫃱; [B1, B5, V6]; 0.xn--pgbe9e344c2725svff8b; ; ; # 0.Ⴇتجم
+𝟘.ⴇ󀳑ﵐ񫃱; 0.ⴇ󀳑تجم񫃱; [B1, B5, P1, V6]; 0.xn--pgbe9ez79qd207lvff8b; ; ; # 0.ⴇتجم
+𑇀▍.⁞ᠰ; ; [V5]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ
+xn--9zh3057f.xn--j7e103b; 𑇀▍.⁞ᠰ; [V5]; xn--9zh3057f.xn--j7e103b; ; ; # 𑇀▍.⁞ᠰ
+‍-ٺ.򏯩; ; [B1, C2, P1, V6]; xn----qrc357q.xn--ts49b; ; xn----qrc.xn--ts49b; [B1, P1, V3, V6] # -ٺ.
+xn----qrc.xn--ts49b; -ٺ.򏯩; [B1, V3, V6]; xn----qrc.xn--ts49b; ; ; # -ٺ.
+xn----qrc357q.xn--ts49b; ‍-ٺ.򏯩; [B1, C2, V6]; xn----qrc357q.xn--ts49b; ; ; # -ٺ.
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+ᠢ𐮂𐫘寐。‌≯✳; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, P1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; xn--46e6675axzzhota.xn--hdh99p; [B1, B5, P1, V6] # ᠢ𐮂𐫘寐.≯✳
+xn--46e6675axzzhota.xn--hdh99p; ᠢ𐮂𐫘寐.≯✳; [B1, B5, V6]; xn--46e6675axzzhota.xn--hdh99p; ; ; # ᠢ𐮂𐫘寐.≯✳
+xn--46e6675axzzhota.xn--0ug06gu8f; ᠢ𐮂𐫘寐.‌≯✳; [B1, B5, C1, V6]; xn--46e6675axzzhota.xn--0ug06gu8f; ; ; # ᠢ𐮂𐫘寐.≯✳
+‍。󸲜ႺႴ𞨇; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--sndl01647an3h1h; ; .xn--sndl01647an3h1h; [B5, B6, P1, V6, A4_2] # .ႺႴ
+‍。󸲜ႺႴ𞨇; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--sndl01647an3h1h; ; .xn--sndl01647an3h1h; [B5, B6, P1, V6, A4_2] # .ႺႴ
+‍。󸲜ⴚⴔ𞨇; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, P1, V6, A4_2] # .ⴚⴔ
+‍。󸲜Ⴚⴔ𞨇; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; .xn--ynd036lq981an3r4h; [B5, B6, P1, V6, A4_2] # .Ⴚⴔ
+.xn--ynd036lq981an3r4h; .󸲜Ⴚⴔ𞨇; [B5, B6, V6, X4_2]; .xn--ynd036lq981an3r4h; [B5, B6, V6, A4_2]; ; # .Ⴚⴔ
+xn--1ug.xn--ynd036lq981an3r4h; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; ; # .Ⴚⴔ
+.xn--cljl81825an3r4h; .󸲜ⴚⴔ𞨇; [B5, B6, V6, X4_2]; .xn--cljl81825an3r4h; [B5, B6, V6, A4_2]; ; # .ⴚⴔ
+xn--1ug.xn--cljl81825an3r4h; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--cljl81825an3r4h; ; ; # .ⴚⴔ
+.xn--sndl01647an3h1h; .󸲜ႺႴ𞨇; [B5, B6, V6, X4_2]; .xn--sndl01647an3h1h; [B5, B6, V6, A4_2]; ; # .ႺႴ
+xn--1ug.xn--sndl01647an3h1h; ‍.󸲜ႺႴ𞨇; [B1, B5, B6, C2, V6]; xn--1ug.xn--sndl01647an3h1h; ; ; # .ႺႴ
+‍。󸲜ⴚⴔ𞨇; ‍.󸲜ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--cljl81825an3r4h; ; .xn--cljl81825an3r4h; [B5, B6, P1, V6, A4_2] # .ⴚⴔ
+‍。󸲜Ⴚⴔ𞨇; ‍.󸲜Ⴚⴔ𞨇; [B1, B5, B6, C2, P1, V6]; xn--1ug.xn--ynd036lq981an3r4h; ; .xn--ynd036lq981an3r4h; [B5, B6, P1, V6, A4_2] # .Ⴚⴔ
+-3.‍ヌᢕ; ; [C2, V3]; -3.xn--fbf739aq5o; ; -3.xn--fbf115j; [V3] # -3.ヌᢕ
+-3.xn--fbf115j; -3.ヌᢕ; [V3]; -3.xn--fbf115j; ; ; # -3.ヌᢕ
+-3.xn--fbf739aq5o; -3.‍ヌᢕ; [C2, V3]; -3.xn--fbf739aq5o; ; ; # -3.ヌᢕ
+🂃٦ß‍。󠠂򭰍𞩒-; 🂃٦ß‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ß.-
+🂃٦SS‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+🂃٦ss‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+xn--ss-pyd98921c.xn----nz8rh7531csznt; 🂃٦ss.󠠂򭰍𞩒-; [B1, V3, V6]; xn--ss-pyd98921c.xn----nz8rh7531csznt; ; ; # 🂃٦ss.-
+xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; ; # 🂃٦ss.-
+xn--zca34z68yzu83b.xn----nz8rh7531csznt; 🂃٦ß‍.󠠂򭰍𞩒-; [B1, C2, V3, V6]; xn--zca34z68yzu83b.xn----nz8rh7531csznt; ; ; # 🂃٦ß.-
+🂃٦Ss‍。󠠂򭰍𞩒-; 🂃٦ss‍.󠠂򭰍𞩒-; [B1, C2, P1, V3, V6]; xn--ss-pyd483x5k99b.xn----nz8rh7531csznt; ; xn--ss-pyd98921c.xn----nz8rh7531csznt; [B1, P1, V3, V6] # 🂃٦ss.-
+ꇟ-𐾺ڟ。򰀺‌; ꇟ-𐾺ڟ.򰀺‌; [B5, B6, C1, P1, V6]; xn----utc4430jd3zd.xn--0ugx6670i; ; xn----utc4430jd3zd.xn--bp20d; [B5, B6, P1, V6] # ꇟ-𐾺ڟ.
+xn----utc4430jd3zd.xn--bp20d; ꇟ-𐾺ڟ.򰀺; [B5, B6, V6]; xn----utc4430jd3zd.xn--bp20d; ; ; # ꇟ-𐾺ڟ.
+xn----utc4430jd3zd.xn--0ugx6670i; ꇟ-𐾺ڟ.򰀺‌; [B5, B6, C1, V6]; xn----utc4430jd3zd.xn--0ugx6670i; ; ; # ꇟ-𐾺ڟ.
+٥.҄𐨗𝩋𴤃; ; [B1, P1, V5, V6]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋
+xn--eib.xn--n3a0405kus8eft5l; ٥.҄𐨗𝩋𴤃; [B1, V5, V6]; xn--eib.xn--n3a0405kus8eft5l; ; ; # ٥.҄𐨗𝩋
+-.񱼓ى𐨿; ; [B1, B5, B6, P1, V3, V6]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿
+-.xn--lhb4124khbq4b; -.񱼓ى𐨿; [B1, B5, B6, V3, V6]; -.xn--lhb4124khbq4b; ; ; # -.ى𐨿
+󾬨ς.𞶙녫ß; ; [B2, B3, P1, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß
+󾬨ς.𞶙녫ß; 󾬨ς.𞶙녫ß; [B2, B3, P1, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # ς.녫ß
+󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫SS; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨σ.𞶙녫ss; ; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫Ss; 󾬨σ.𞶙녫ss; [B2, B3, P1, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+xn--4xa76659r.xn--ss-d64i8755h; 󾬨σ.𞶙녫ss; [B2, B3, V6]; xn--4xa76659r.xn--ss-d64i8755h; ; ; # σ.녫ss
+󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨Σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨σ.𞶙녫ß; ; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+󾬨σ.𞶙녫ß; 󾬨σ.𞶙녫ß; [B2, B3, P1, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; xn--4xa76659r.xn--ss-d64i8755h; # σ.녫ß
+xn--4xa76659r.xn--zca5051g4h4i; 󾬨σ.𞶙녫ß; [B2, B3, V6]; xn--4xa76659r.xn--zca5051g4h4i; ; ; # σ.녫ß
+xn--3xa96659r.xn--zca5051g4h4i; 󾬨ς.𞶙녫ß; [B2, B3, V6]; xn--3xa96659r.xn--zca5051g4h4i; ; ; # ς.녫ß
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+Ⅎ្‍。≠‍‌; Ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bcza.xn--0ugb89o; ; xn--u4e319b.xn--1ch; [P1, V6] # Ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+xn--u4e969b.xn--1ch; ⅎ្.≠; [V6]; xn--u4e969b.xn--1ch; ; ; # ⅎ្.≠
+xn--u4e823bq1a.xn--0ugb89o; ⅎ្‍.≠‍‌; [C1, C2, V6]; xn--u4e823bq1a.xn--0ugb89o; ; ; # ⅎ្.≠
+xn--u4e319b.xn--1ch; Ⅎ្.≠; [V6]; xn--u4e319b.xn--1ch; ; ; # Ⅎ្.≠
+xn--u4e823bcza.xn--0ugb89o; Ⅎ្‍.≠‍‌; [C1, C2, V6]; xn--u4e823bcza.xn--0ugb89o; ; ; # Ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+ⅎ្‍。≠‍‌; ⅎ្‍.≠‍‌; [C1, C2, P1, V6]; xn--u4e823bq1a.xn--0ugb89o; ; xn--u4e969b.xn--1ch; [P1, V6] # ⅎ្.≠
+𐋺꫶꥓󧦉.‌᜔ڏ; 𐋺꫶꥓󧦉.‌᜔ڏ; [B1, C1, P1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, P1, V5, V6] # 𐋺꫶꥓.᜔ڏ
+𐋺꫶꥓󧦉.‌᜔ڏ; ; [B1, C1, P1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; xn--3j9a14ak27osbz2o.xn--ljb175f; [B1, P1, V5, V6] # 𐋺꫶꥓.᜔ڏ
+xn--3j9a14ak27osbz2o.xn--ljb175f; 𐋺꫶꥓󧦉.᜔ڏ; [B1, V5, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f; ; ; # 𐋺꫶꥓.᜔ڏ
+xn--3j9a14ak27osbz2o.xn--ljb175f1wg; 𐋺꫶꥓󧦉.‌᜔ڏ; [B1, C1, V6]; xn--3j9a14ak27osbz2o.xn--ljb175f1wg; ; ; # 𐋺꫶꥓.᜔ڏ
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; ; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+񺔯ྨ.≯; 񺔯ྨ.≯; [P1, V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+xn--4fd57150h.xn--hdh; 񺔯ྨ.≯; [V6]; xn--4fd57150h.xn--hdh; ; ; # ྨ.≯
+‍𞡄Ⴓ.𐇽; ‍𞡄Ⴓ.𐇽; [B1, B3, B6, C2, P1, V5, V6]; xn--rnd379ex885a.xn--m27c; ; xn--rnd5552v.xn--m27c; [B1, B2, B3, B6, P1, V5, V6] # 𞡄Ⴓ.𐇽
+‍𞡄Ⴓ.𐇽; ; [B1, B3, B6, C2, P1, V5, V6]; xn--rnd379ex885a.xn--m27c; ; xn--rnd5552v.xn--m27c; [B1, B2, B3, B6, P1, V5, V6] # 𞡄Ⴓ.𐇽
+‍𞡄ⴓ.𐇽; ; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, B6, V5] # 𞡄ⴓ.𐇽
+xn--blj7492l.xn--m27c; 𞡄ⴓ.𐇽; [B1, B2, B3, B6, V5]; xn--blj7492l.xn--m27c; ; ; # 𞡄ⴓ.𐇽
+xn--1ugz52c4i16a.xn--m27c; ‍𞡄ⴓ.𐇽; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; ; # 𞡄ⴓ.𐇽
+xn--rnd5552v.xn--m27c; 𞡄Ⴓ.𐇽; [B1, B2, B3, B6, V5, V6]; xn--rnd5552v.xn--m27c; ; ; # 𞡄Ⴓ.𐇽
+xn--rnd379ex885a.xn--m27c; ‍𞡄Ⴓ.𐇽; [B1, B3, B6, C2, V5, V6]; xn--rnd379ex885a.xn--m27c; ; ; # 𞡄Ⴓ.𐇽
+‍𞡄ⴓ.𐇽; ‍𞡄ⴓ.𐇽; [B1, B3, B6, C2, V5]; xn--1ugz52c4i16a.xn--m27c; ; xn--blj7492l.xn--m27c; [B1, B2, B3, B6, V5] # 𞡄ⴓ.𐇽
+𐪒ß꣪.ᡤ; 𐪒ß꣪.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ
+𐪒ß꣪.ᡤ; ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; xn--ss-tu9hw933a.xn--08e; # 𐪒ß꣪.ᡤ
+𐪒SS꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒ss꣪.ᡤ; ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+xn--ss-tu9hw933a.xn--08e; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+xn--zca2517f2hvc.xn--08e; 𐪒ß꣪.ᡤ; [B2, B3]; xn--zca2517f2hvc.xn--08e; ; ; # 𐪒ß꣪.ᡤ
+𐪒SS꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒Ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐪒Ss꣪.ᡤ; 𐪒ss꣪.ᡤ; [B2, B3]; xn--ss-tu9hw933a.xn--08e; ; ; # 𐪒ss꣪.ᡤ
+𐨿󠆌鸮𑚶.ς; 𐨿鸮𑚶.ς; [V5]; xn--l76a726rt2h.xn--3xa; ; xn--l76a726rt2h.xn--4xa; # 𐨿鸮𑚶.ς
+𐨿󠆌鸮𑚶.Σ; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+𐨿󠆌鸮𑚶.σ; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+xn--l76a726rt2h.xn--4xa; 𐨿鸮𑚶.σ; [V5]; xn--l76a726rt2h.xn--4xa; ; ; # 𐨿鸮𑚶.σ
+xn--l76a726rt2h.xn--3xa; 𐨿鸮𑚶.ς; [V5]; xn--l76a726rt2h.xn--3xa; ; ; # 𐨿鸮𑚶.ς
+⒗𞤬。-𑚶; ⒗𞤬.-𑚶; [B1, P1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+16.𞤬。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+16.𞤊。-𑚶; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+16.xn--ke6h.xn----4j0j; 16.𞤬.-𑚶; [B1, V3]; 16.xn--ke6h.xn----4j0j; ; ; # 16.𞤬.-𑚶
+⒗𞤊。-𑚶; ⒗𞤬.-𑚶; [B1, P1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+xn--8shw466n.xn----4j0j; ⒗𞤬.-𑚶; [B1, V3, V6]; xn--8shw466n.xn----4j0j; ; ; # ⒗𞤬.-𑚶
+ࢳ𞤿⾫。𐹣ڏ⒈; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, P1, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+ࢳ𞤿隹。𐹣ڏ1.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+ࢳ𞤝隹。𐹣ڏ1.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+xn--8yb0383efiwk.xn--1-wsc3373r.; ࢳ𞤿隹.𐹣ڏ1.; [B1, B2, B3]; xn--8yb0383efiwk.xn--1-wsc3373r.; ; ; # ࢳ𞤿隹.𐹣ڏ1.
+ࢳ𞤝⾫。𐹣ڏ⒈; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, P1, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+xn--8yb0383efiwk.xn--ljb064mol4n; ࢳ𞤿隹.𐹣ڏ⒈; [B1, B2, B3, V6]; xn--8yb0383efiwk.xn--ljb064mol4n; ; ; # ࢳ𞤿隹.𐹣ڏ⒈
+␳𚎛𝟧١.ᡢ8ི؀; ␳𚎛5١.ᡢ8ི؀; [B5, B6, P1, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+␳𚎛5١.ᡢ8ི؀; ; [B5, B6, P1, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+xn--5-bqc410un435a.xn--8-rkc763epjj; ␳𚎛5١.ᡢ8ི؀; [B5, B6, V6]; xn--5-bqc410un435a.xn--8-rkc763epjj; ; ; # 5١.ᡢ8ི
+𐹠.🄀⒒-󨰈; ; [B1, P1, V6]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒-
+𐹠.0.11.-󨰈; ; [B1, P1, V3, V6]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.-
+xn--7n0d.0.11.xn----8j07m; 𐹠.0.11.-󨰈; [B1, V3, V6]; xn--7n0d.0.11.xn----8j07m; ; ; # 𐹠.0.11.-
+xn--7n0d.xn----xcp9757q1s13g; 𐹠.🄀⒒-󨰈; [B1, V6]; xn--7n0d.xn----xcp9757q1s13g; ; ; # 𐹠.🄀⒒-
+ς-。‌𝟭-; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1-
+ς-。‌1-; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; xn----zmb.1-; [V3] # ς-.1-
+Σ-。‌1-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+σ-。‌1-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+xn----zmb.1-; σ-.1-; [V3]; xn----zmb.1-; ; ; # σ-.1-
+xn----zmb.xn--1--i1t; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; ; # σ-.1-
+xn----xmb.xn--1--i1t; ς-.‌1-; [C1, V3]; xn----xmb.xn--1--i1t; ; ; # ς-.1-
+Σ-。‌𝟭-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+σ-。‌𝟭-; σ-.‌1-; [C1, V3]; xn----zmb.xn--1--i1t; ; xn----zmb.1-; [V3] # σ-.1-
+᜴-ೢ.󠄩Ⴄ; ᜴-ೢ.Ⴄ; [P1, V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩Ⴄ; ᜴-ೢ.Ⴄ; [P1, V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩ⴄ; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+xn----ggf830f.xn--vkj; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+xn----ggf830f.xn--cnd; ᜴-ೢ.Ⴄ; [V5, V6]; xn----ggf830f.xn--cnd; ; ; # ᜴-ೢ.Ⴄ
+᜴-ೢ.󠄩ⴄ; ᜴-ೢ.ⴄ; [V5]; xn----ggf830f.xn--vkj; ; ; # ᜴-ೢ.ⴄ
+򭈗♋ڻ𐦥。॔⒈; 򭈗♋ڻ𐦥.॔⒈; [B1, B5, B6, P1, V5, V6]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈
+򭈗♋ڻ𐦥。॔1.; 򭈗♋ڻ𐦥.॔1.; [B1, B5, B6, P1, V5, V6]; xn--ukb372n129m3rs7f.xn--1-fyd.; ; ; # ♋ڻ𐦥.॔1.
+xn--ukb372n129m3rs7f.xn--1-fyd.; 򭈗♋ڻ𐦥.॔1.; [B1, B5, B6, V5, V6]; xn--ukb372n129m3rs7f.xn--1-fyd.; ; ; # ♋ڻ𐦥.॔1.
+xn--ukb372n129m3rs7f.xn--u3b240l; 򭈗♋ڻ𐦥.॔⒈; [B1, B5, B6, V5, V6]; xn--ukb372n129m3rs7f.xn--u3b240l; ; ; # ♋ڻ𐦥.॔⒈
+֤.ہ᪳‌; ֤.ہ᪳‌; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, B3, B6, V5] # ֤.ہ᪳
+֤.ہ᪳‌; ; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; xn--vcb.xn--0kb623h; [B1, B3, B6, V5] # ֤.ہ᪳
+xn--vcb.xn--0kb623h; ֤.ہ᪳; [B1, B3, B6, V5]; xn--vcb.xn--0kb623h; ; ; # ֤.ہ᪳
+xn--vcb.xn--0kb623hm1d; ֤.ہ᪳‌; [B1, B3, B6, C1, V5]; xn--vcb.xn--0kb623hm1d; ; ; # ֤.ہ᪳
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; ; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+񢭏ࡆ≮્.𞦊; 񢭏ࡆ≮્.𞦊; [B5, B6, P1, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+xn--4vb80kq29ayo62l.xn--8g6h; 񢭏ࡆ≮્.𞦊; [B5, B6, V6]; xn--4vb80kq29ayo62l.xn--8g6h; ; ; # ࡆ≮્.
+‍。𞀘⒈ꡍ擉; ‍.𞀘⒈ꡍ擉; [C2, P1, V5, V6]; xn--1ug.xn--tsh026uql4bew9p; ; .xn--tsh026uql4bew9p; [P1, V5, V6, A4_2] # .𞀘⒈ꡍ擉
+‍。𞀘1.ꡍ擉; ‍.𞀘1.ꡍ擉; [C2, V5]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; .xn--1-1p4r.xn--s7uv61m; [V5, A4_2] # .𞀘1.ꡍ擉
+.xn--1-1p4r.xn--s7uv61m; .𞀘1.ꡍ擉; [V5, X4_2]; .xn--1-1p4r.xn--s7uv61m; [V5, A4_2]; ; # .𞀘1.ꡍ擉
+xn--1ug.xn--1-1p4r.xn--s7uv61m; ‍.𞀘1.ꡍ擉; [C2, V5]; xn--1ug.xn--1-1p4r.xn--s7uv61m; ; ; # .𞀘1.ꡍ擉
+.xn--tsh026uql4bew9p; .𞀘⒈ꡍ擉; [V5, V6, X4_2]; .xn--tsh026uql4bew9p; [V5, V6, A4_2]; ; # .𞀘⒈ꡍ擉
+xn--1ug.xn--tsh026uql4bew9p; ‍.𞀘⒈ꡍ擉; [C2, V5, V6]; xn--1ug.xn--tsh026uql4bew9p; ; ; # .𞀘⒈ꡍ擉
+₈ߋ.ﭤ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+₈ߋ.ﭤ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+8ߋ.ٿ≠; ; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+8ߋ.ٿ≠; 8ߋ.ٿ≠; [B1, B3, P1, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+xn--8-zbd.xn--4ib883l; 8ߋ.ٿ≠; [B1, B3, V6]; xn--8-zbd.xn--4ib883l; ; ; # 8ߋ.ٿ≠
+ᢡߞ򹐣.⒒ق𑍦; ; [B1, B5, P1, V6]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦
+ᢡߞ򹐣.11.ق𑍦; ; [B1, B5, P1, V6]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦
+xn--5sb596fi873t.11.xn--ehb4198k; ᢡߞ򹐣.11.ق𑍦; [B1, B5, V6]; xn--5sb596fi873t.11.xn--ehb4198k; ; ; # ᢡߞ.11.ق𑍦
+xn--5sb596fi873t.xn--ehb336mvy7n; ᢡߞ򹐣.⒒ق𑍦; [B1, B5, V6]; xn--5sb596fi873t.xn--ehb336mvy7n; ; ; # ᢡߞ.⒒ق𑍦
+่-𐹺𝟜.ͣۡ⒏; ่-𐹺4.ͣۡ⒏; [B1, P1, V5, V6]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏
+่-𐹺4.ͣۡ8.; ; [B1, V5]; xn---4-owiz479s.xn--8-ihb69x.; ; ; # ่-𐹺4.ͣۡ8.
+xn---4-owiz479s.xn--8-ihb69x.; ่-𐹺4.ͣۡ8.; [B1, V5]; xn---4-owiz479s.xn--8-ihb69x.; ; ; # ่-𐹺4.ͣۡ8.
+xn---4-owiz479s.xn--eva20pjv9a; ่-𐹺4.ͣۡ⒏; [B1, V5, V6]; xn---4-owiz479s.xn--eva20pjv9a; ; ; # ่-𐹺4.ͣۡ⒏
+⫐。Ⴠ-󃐢; ⫐.Ⴠ-󃐢; [P1, V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。Ⴠ-󃐢; ⫐.Ⴠ-󃐢; [P1, V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [P1, V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+xn--r3i.xn----2wst7439i; ⫐.ⴠ-󃐢; [V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+xn--r3i.xn----z1g58579u; ⫐.Ⴠ-󃐢; [V6]; xn--r3i.xn----z1g58579u; ; ; # ⫐.Ⴠ-
+⫐。ⴠ-󃐢; ⫐.ⴠ-󃐢; [P1, V6]; xn--r3i.xn----2wst7439i; ; ; # ⫐.ⴠ-
+𑑂◊.⦟∠; 𑑂◊.⦟∠; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+𑑂◊.⦟∠; ; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+xn--01h3338f.xn--79g270a; 𑑂◊.⦟∠; [V5]; xn--01h3338f.xn--79g270a; ; ; # 𑑂◊.⦟∠
+𿌰-٢。󋸛ꡂ; 𿌰-٢.󋸛ꡂ; [B5, B6, P1, V6]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ
+xn----dqc20828e.xn--bc9an2879c; 𿌰-٢.󋸛ꡂ; [B5, B6, V6]; xn----dqc20828e.xn--bc9an2879c; ; ; # -٢.ꡂ
+ٸ。󠏬݁𞪭𐹪; يٴ.󠏬݁𞪭𐹪; [B1, P1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+يٴ。󠏬݁𞪭𐹪; يٴ.󠏬݁𞪭𐹪; [B1, P1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+xn--mhb8f.xn--oob2585kfdsfsbo7h; يٴ.󠏬݁𞪭𐹪; [B1, V6]; xn--mhb8f.xn--oob2585kfdsfsbo7h; ; ; # يٴ.݁𐹪
+𐫆ꌄ。‍ᣬ; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ
+𐫆ꌄ。‍ᣬ; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; xn--y77ao18q.xn--wdf; [B2, B3] # 𐫆ꌄ.ᣬ
+xn--y77ao18q.xn--wdf; 𐫆ꌄ.ᣬ; [B2, B3]; xn--y77ao18q.xn--wdf; ; ; # 𐫆ꌄ.ᣬ
+xn--y77ao18q.xn--wdf367a; 𐫆ꌄ.‍ᣬ; [B1, B2, B3, C2]; xn--y77ao18q.xn--wdf367a; ; ; # 𐫆ꌄ.ᣬ
+₀٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+₀٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+0٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+0٢。󅪞≯-; 0٢.󅪞≯-; [B1, B6, P1, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+xn--0-dqc.xn----ogov3342l; 0٢.󅪞≯-; [B1, B6, V3, V6]; xn--0-dqc.xn----ogov3342l; ; ; # 0٢.≯-
+̜𐹫-𞯃.𐋤ࡅ; ; [B1, P1, V5, V6]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ
+xn----gdb7046r692g.xn--3vb1349j; ̜𐹫-𞯃.𐋤ࡅ; [B1, V5, V6]; xn----gdb7046r692g.xn--3vb1349j; ; ; # ̜𐹫-.𐋤ࡅ
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩Ⴡ֔; ≠.𝩑𐹩Ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+xn--1ch.xn--fcb363rk03mypug; ≠.𝩑𐹩ⴡ֔; [B1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+xn--1ch.xn--fcb538c649rypog; ≠.𝩑𐹩Ⴡ֔; [B1, V5, V6]; xn--1ch.xn--fcb538c649rypog; ; ; # ≠.𝩑𐹩Ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+≠。𝩑𐹩ⴡ֔; ≠.𝩑𐹩ⴡ֔; [B1, P1, V5, V6]; xn--1ch.xn--fcb363rk03mypug; ; ; # ≠.𝩑𐹩ⴡ֔
+𖫳≠.Ⴀ𐮀; ; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+𖫳≠.Ⴀ𐮀; 𖫳≠.Ⴀ𐮀; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+𖫳≠.ⴀ𐮀; 𖫳≠.ⴀ𐮀; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+𖫳≠.ⴀ𐮀; ; [B1, B5, B6, P1, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+xn--1ch9250k.xn--rkj6232e; 𖫳≠.ⴀ𐮀; [B1, B5, B6, V5, V6]; xn--1ch9250k.xn--rkj6232e; ; ; # 𖫳≠.ⴀ𐮀
+xn--1ch9250k.xn--7md2659j; 𖫳≠.Ⴀ𐮀; [B1, B5, B6, V5, V6]; xn--1ch9250k.xn--7md2659j; ; ; # 𖫳≠.Ⴀ𐮀
+󠅾ܶܦ.ᢚ閪࣢𝩟; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, P1, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+󠅾ܶܦ.ᢚ閪࣢𝩟; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, P1, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+xn--wnb5a.xn--l0b161fis8gbp5m; ܶܦ.ᢚ閪࣢𝩟; [B1, B5, B6, V5, V6]; xn--wnb5a.xn--l0b161fis8gbp5m; ; ; # ܶܦ.ᢚ閪𝩟
+‍󠇜ۋ꣩。⃝ྰ-ᛟ; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V5] # ۋ꣩.⃝ྰ-ᛟ
+‍󠇜ۋ꣩。⃝ྰ-ᛟ; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; xn--blb8114f.xn----gmg236cj6k; [B1, V5] # ۋ꣩.⃝ྰ-ᛟ
+xn--blb8114f.xn----gmg236cj6k; ۋ꣩.⃝ྰ-ᛟ; [B1, V5]; xn--blb8114f.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ
+xn--blb540ke10h.xn----gmg236cj6k; ‍ۋ꣩.⃝ྰ-ᛟ; [B1, C2, V5]; xn--blb540ke10h.xn----gmg236cj6k; ; ; # ۋ꣩.⃝ྰ-ᛟ
+헁󘖙ฺ󚍚。ں𝟜; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں𝟜; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں4; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+헁󘖙ฺ󚍚。ں4; 헁󘖙ฺ󚍚.ں4; [P1, V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+xn--o4c1723h8g85gt4ya.xn--4-dvc; 헁󘖙ฺ󚍚.ں4; [V6]; xn--o4c1723h8g85gt4ya.xn--4-dvc; ; ; # 헁ฺ.ں4
+𐹭。󃱂‌Ⴞ; 𐹭.󃱂‌Ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--2nd949eqw95u; ; xn--lo0d.xn--2nd75260n; [B1, P1, V6] # 𐹭.Ⴞ
+𐹭。󃱂‌Ⴞ; 𐹭.󃱂‌Ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--2nd949eqw95u; ; xn--lo0d.xn--2nd75260n; [B1, P1, V6] # 𐹭.Ⴞ
+𐹭。󃱂‌ⴞ; 𐹭.󃱂‌ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, P1, V6] # 𐹭.ⴞ
+xn--lo0d.xn--mljx1099g; 𐹭.󃱂ⴞ; [B1, V6]; xn--lo0d.xn--mljx1099g; ; ; # 𐹭.ⴞ
+xn--lo0d.xn--0ugx72cwi33v; 𐹭.󃱂‌ⴞ; [B1, C1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; ; # 𐹭.ⴞ
+xn--lo0d.xn--2nd75260n; 𐹭.󃱂Ⴞ; [B1, V6]; xn--lo0d.xn--2nd75260n; ; ; # 𐹭.Ⴞ
+xn--lo0d.xn--2nd949eqw95u; 𐹭.󃱂‌Ⴞ; [B1, C1, V6]; xn--lo0d.xn--2nd949eqw95u; ; ; # 𐹭.Ⴞ
+𐹭。󃱂‌ⴞ; 𐹭.󃱂‌ⴞ; [B1, C1, P1, V6]; xn--lo0d.xn--0ugx72cwi33v; ; xn--lo0d.xn--mljx1099g; [B1, P1, V6] # 𐹭.ⴞ
+꥓.̽𑂽馋; ; [P1, V5, V6]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋
+xn--3j9a.xn--bua0708eqzrd; ꥓.̽𑂽馋; [V5, V6]; xn--3j9a.xn--bua0708eqzrd; ; ; # ꥓.̽馋
+󈫝򪛸‍。䜖; 󈫝򪛸‍.䜖; [C2, P1, V6]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [P1, V6] # .䜖
+󈫝򪛸‍。䜖; 󈫝򪛸‍.䜖; [C2, P1, V6]; xn--1ug30527h9mxi.xn--k0o; ; xn--g138cxw05a.xn--k0o; [P1, V6] # .䜖
+xn--g138cxw05a.xn--k0o; 󈫝򪛸.䜖; [V6]; xn--g138cxw05a.xn--k0o; ; ; # .䜖
+xn--1ug30527h9mxi.xn--k0o; 󈫝򪛸‍.䜖; [C2, V6]; xn--1ug30527h9mxi.xn--k0o; ; ; # .䜖
+ᡯ⚉姶🄉.۷‍🎪‍; ᡯ⚉姶🄉.۷‍🎪‍; [C2, P1, V6]; xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ; xn--c9e433epi4b3j20a.xn--kmb6733w; [P1, V6] # ᡯ⚉姶🄉.۷🎪
+ᡯ⚉姶8,.۷‍🎪‍; ; [C2, P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; xn--8,-g9oy26fzu4d.xn--kmb6733w; [P1, V6] # ᡯ⚉姶8,.۷🎪
+xn--8,-g9oy26fzu4d.xn--kmb6733w; ᡯ⚉姶8,.۷🎪; [P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb6733w; ; ; # ᡯ⚉姶8,.۷🎪
+xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ᡯ⚉姶8,.۷‍🎪‍; [C2, P1, V6]; xn--8,-g9oy26fzu4d.xn--kmb859ja94998b; ; ; # ᡯ⚉姶8,.۷🎪
+xn--c9e433epi4b3j20a.xn--kmb6733w; ᡯ⚉姶🄉.۷🎪; [V6]; xn--c9e433epi4b3j20a.xn--kmb6733w; ; ; # ᡯ⚉姶🄉.۷🎪
+xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ᡯ⚉姶🄉.۷‍🎪‍; [C2, V6]; xn--c9e433epi4b3j20a.xn--kmb859ja94998b; ; ; # ᡯ⚉姶🄉.۷🎪
+𞽀.𐹸🚖ฺ; ; [B1, P1, V6]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ
+xn--0n7h.xn--o4c9032klszf; 𞽀.𐹸🚖ฺ; [B1, V6]; xn--0n7h.xn--o4c9032klszf; ; ; # .𐹸🚖ฺ
+Ⴔᠵ。𐹧݇۹; Ⴔᠵ.𐹧݇۹; [B1, P1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+Ⴔᠵ。𐹧݇۹; Ⴔᠵ.𐹧݇۹; [B1, P1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+ⴔᠵ。𐹧݇۹; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+xn--o7e997h.xn--mmb9ml895e; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+xn--snd659a.xn--mmb9ml895e; Ⴔᠵ.𐹧݇۹; [B1, V6]; xn--snd659a.xn--mmb9ml895e; ; ; # Ⴔᠵ.𐹧݇۹
+ⴔᠵ。𐹧݇۹; ⴔᠵ.𐹧݇۹; [B1]; xn--o7e997h.xn--mmb9ml895e; ; ; # ⴔᠵ.𐹧݇۹
+፟ᡈ‌.︒-𖾐-; ፟ᡈ‌.︒-𖾐-; [C1, P1, V3, V5, V6]; xn--b7d82wo4h.xn-----c82nz547a; ; xn--b7d82w.xn-----c82nz547a; [P1, V3, V5, V6] # ፟ᡈ.︒-𖾐-
+፟ᡈ‌.。-𖾐-; ፟ᡈ‌..-𖾐-; [C1, V3, V5, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V5, A4_2]; xn--b7d82w..xn-----pe4u; [V3, V5, A4_2] # ፟ᡈ..-𖾐-
+xn--b7d82w..xn-----pe4u; ፟ᡈ..-𖾐-; [V3, V5, X4_2]; xn--b7d82w..xn-----pe4u; [V3, V5, A4_2]; ; # ፟ᡈ..-𖾐-
+xn--b7d82wo4h..xn-----pe4u; ፟ᡈ‌..-𖾐-; [C1, V3, V5, X4_2]; xn--b7d82wo4h..xn-----pe4u; [C1, V3, V5, A4_2]; ; # ፟ᡈ..-𖾐-
+xn--b7d82w.xn-----c82nz547a; ፟ᡈ.︒-𖾐-; [V3, V5, V6]; xn--b7d82w.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐-
+xn--b7d82wo4h.xn-----c82nz547a; ፟ᡈ‌.︒-𖾐-; [C1, V3, V5, V6]; xn--b7d82wo4h.xn-----c82nz547a; ; ; # ፟ᡈ.︒-𖾐-
+⒈؁⒖‌.ᷰߛ; ; [B1, C1, P1, V5, V6]; xn--jfb844kmfdwb.xn--2sb914i; ; xn--jfb347mib.xn--2sb914i; [B1, P1, V5, V6] # ⒈⒖.ᷰߛ
+1.؁15.‌.ᷰߛ; ; [B1, C1, P1, V5, V6]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; 1.xn--15-1pd..xn--2sb914i; [B1, P1, V5, V6, A4_2] # 1.15..ᷰߛ
+1.xn--15-1pd..xn--2sb914i; 1.؁15..ᷰߛ; [B1, V5, V6, X4_2]; 1.xn--15-1pd..xn--2sb914i; [B1, V5, V6, A4_2]; ; # 1.15..ᷰߛ
+1.xn--15-1pd.xn--0ug.xn--2sb914i; 1.؁15.‌.ᷰߛ; [B1, C1, V5, V6]; 1.xn--15-1pd.xn--0ug.xn--2sb914i; ; ; # 1.15..ᷰߛ
+xn--jfb347mib.xn--2sb914i; ⒈؁⒖.ᷰߛ; [B1, V5, V6]; xn--jfb347mib.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ
+xn--jfb844kmfdwb.xn--2sb914i; ⒈؁⒖‌.ᷰߛ; [B1, C1, V5, V6]; xn--jfb844kmfdwb.xn--2sb914i; ; ; # ⒈⒖.ᷰߛ
+𝩜。-୍Ⴋ; 𝩜.-୍Ⴋ; [P1, V3, V5, V6]; xn--792h.xn----bse632b; ; ; # 𝩜.-୍Ⴋ
+𝩜。-୍ⴋ; 𝩜.-୍ⴋ; [V3, V5]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ
+xn--792h.xn----bse820x; 𝩜.-୍ⴋ; [V3, V5]; xn--792h.xn----bse820x; ; ; # 𝩜.-୍ⴋ
+xn--792h.xn----bse632b; 𝩜.-୍Ⴋ; [V3, V5, V6]; xn--792h.xn----bse632b; ; ; # 𝩜.-୍Ⴋ
+ßჀ.ؠ刯Ⴝ; ; [B2, B3, P1, V6]; xn--zca442f.xn--fgb845cb66c; ; xn--ss-wgk.xn--fgb845cb66c; # ßჀ.ؠ刯Ⴝ
+ßⴠ.ؠ刯ⴝ; ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; xn--ss-j81a.xn--fgb670rovy; # ßⴠ.ؠ刯ⴝ
+SSჀ.ؠ刯Ⴝ; ssჀ.ؠ刯Ⴝ; [B2, B3, P1, V6]; xn--ss-wgk.xn--fgb845cb66c; ; ; # ssჀ.ؠ刯Ⴝ
+ssⴠ.ؠ刯ⴝ; ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ
+Ssⴠ.ؠ刯Ⴝ; ssⴠ.ؠ刯Ⴝ; [B2, B3, P1, V6]; xn--ss-j81a.xn--fgb845cb66c; ; ; # ssⴠ.ؠ刯Ⴝ
+xn--ss-j81a.xn--fgb845cb66c; ssⴠ.ؠ刯Ⴝ; [B2, B3, V6]; xn--ss-j81a.xn--fgb845cb66c; ; ; # ssⴠ.ؠ刯Ⴝ
+xn--ss-j81a.xn--fgb670rovy; ssⴠ.ؠ刯ⴝ; [B2, B3]; xn--ss-j81a.xn--fgb670rovy; ; ; # ssⴠ.ؠ刯ⴝ
+xn--ss-wgk.xn--fgb845cb66c; ssჀ.ؠ刯Ⴝ; [B2, B3, V6]; xn--ss-wgk.xn--fgb845cb66c; ; ; # ssჀ.ؠ刯Ⴝ
+xn--zca277t.xn--fgb670rovy; ßⴠ.ؠ刯ⴝ; [B2, B3]; xn--zca277t.xn--fgb670rovy; ; ; # ßⴠ.ؠ刯ⴝ
+xn--zca442f.xn--fgb845cb66c; ßჀ.ؠ刯Ⴝ; [B2, B3, V6]; xn--zca442f.xn--fgb845cb66c; ; ; # ßჀ.ؠ刯Ⴝ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ႣℲ。ᠳ툻ٳ; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+xn--bnd957c2pe.xn--sib102gc69k; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+xn--yxf24x4ol.xn--sib102gc69k; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+xn--bnd957cone.xn--sib102gc69k; ᮪ႣℲ.ᠳ툻ٳ; [B5, B6, V5, V6]; xn--bnd957cone.xn--sib102gc69k; ; ; # ᮪ႣℲ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪ⴃⅎ。ᠳ툻ٳ; ᮪ⴃⅎ.ᠳ툻ٳ; [B5, B6, V5]; xn--yxf24x4ol.xn--sib102gc69k; ; ; # ᮪ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+᮪Ⴃⅎ。ᠳ툻ٳ; ᮪Ⴃⅎ.ᠳ툻ٳ; [B5, B6, P1, V5, V6]; xn--bnd957c2pe.xn--sib102gc69k; ; ; # ᮪Ⴃⅎ.ᠳ툻ٳ
+۬.ࢢ𐹫ټ; ; [B1, B3, B6, V5]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ
+xn--8lb.xn--1ib31ily45b; ۬.ࢢ𐹫ټ; [B1, B3, B6, V5]; xn--8lb.xn--1ib31ily45b; ; ; # ۬.ࢢ𐹫ټ
+ڶ۟。₇꠆; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+ڶ۟。7꠆; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+xn--pkb6f.xn--7-x93e; ڶ۟.7꠆; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+ڶ۟.7꠆; ; [B1]; xn--pkb6f.xn--7-x93e; ; ; # ڶ۟.7꠆
+Ⴣ𐹻.‌𝪣≮󠩉; ; [B1, B5, B6, C1, P1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; xn--7nd8101k.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # Ⴣ𐹻.𝪣≮
+Ⴣ𐹻.‌𝪣≮󠩉; Ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, P1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; xn--7nd8101k.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # Ⴣ𐹻.𝪣≮
+ⴣ𐹻.‌𝪣≮󠩉; ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, P1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # ⴣ𐹻.𝪣≮
+ⴣ𐹻.‌𝪣≮󠩉; ; [B1, B5, B6, C1, P1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; xn--rlj6323e.xn--gdh4944ob3x3e; [B1, B5, B6, P1, V5, V6] # ⴣ𐹻.𝪣≮
+xn--rlj6323e.xn--gdh4944ob3x3e; ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V5, V6]; xn--rlj6323e.xn--gdh4944ob3x3e; ; ; # ⴣ𐹻.𝪣≮
+xn--rlj6323e.xn--0ugy6gn120eb103g; ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, V6]; xn--rlj6323e.xn--0ugy6gn120eb103g; ; ; # ⴣ𐹻.𝪣≮
+xn--7nd8101k.xn--gdh4944ob3x3e; Ⴣ𐹻.𝪣≮󠩉; [B1, B5, B6, V5, V6]; xn--7nd8101k.xn--gdh4944ob3x3e; ; ; # Ⴣ𐹻.𝪣≮
+xn--7nd8101k.xn--0ugy6gn120eb103g; Ⴣ𐹻.‌𝪣≮󠩉; [B1, B5, B6, C1, V6]; xn--7nd8101k.xn--0ugy6gn120eb103g; ; ; # Ⴣ𐹻.𝪣≮
+𝟵隁⯮.᠍‌; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [] # 9隁⯮.
+9隁⯮.᠍‌; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; xn--9-mfs8024b.; [] # 9隁⯮.
+xn--9-mfs8024b.; 9隁⯮.; ; xn--9-mfs8024b.; ; ; # 9隁⯮.
+9隁⯮.; ; ; xn--9-mfs8024b.; ; ; # 9隁⯮.
+xn--9-mfs8024b.xn--0ug; 9隁⯮.‌; [C1]; xn--9-mfs8024b.xn--0ug; ; ; # 9隁⯮.
+⒏𐹧。Ⴣ྄彦; ⒏𐹧.Ⴣ྄彦; [B1, P1, V6]; xn--0sh2466f.xn--3ed15dt93o; ; ; # ⒏𐹧.Ⴣ྄彦
+8.𐹧。Ⴣ྄彦; 8.𐹧.Ⴣ྄彦; [B1, P1, V6]; 8.xn--fo0d.xn--3ed15dt93o; ; ; # 8.𐹧.Ⴣ྄彦
+8.𐹧。ⴣ྄彦; 8.𐹧.ⴣ྄彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦
+8.xn--fo0d.xn--3ed972m6o8a; 8.𐹧.ⴣ྄彦; [B1]; 8.xn--fo0d.xn--3ed972m6o8a; ; ; # 8.𐹧.ⴣ྄彦
+8.xn--fo0d.xn--3ed15dt93o; 8.𐹧.Ⴣ྄彦; [B1, V6]; 8.xn--fo0d.xn--3ed15dt93o; ; ; # 8.𐹧.Ⴣ྄彦
+⒏𐹧。ⴣ྄彦; ⒏𐹧.ⴣ྄彦; [B1, P1, V6]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦
+xn--0sh2466f.xn--3ed972m6o8a; ⒏𐹧.ⴣ྄彦; [B1, V6]; xn--0sh2466f.xn--3ed972m6o8a; ; ; # ⒏𐹧.ⴣ྄彦
+xn--0sh2466f.xn--3ed15dt93o; ⒏𐹧.Ⴣ྄彦; [B1, V6]; xn--0sh2466f.xn--3ed15dt93o; ; ; # ⒏𐹧.Ⴣ྄彦
+-问񬰔⒛。؄-񜗉橬; -问񬰔⒛.؄-񜗉橬; [B1, P1, V3, V6]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬
+-问񬰔20.。؄-񜗉橬; -问񬰔20..؄-񜗉橬; [B1, P1, V3, V6, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, P1, V3, V6, A4_2]; ; # -问20..-橬
+xn---20-658jx1776d..xn----ykc7228efm46d; -问񬰔20..؄-񜗉橬; [B1, V3, V6, X4_2]; xn---20-658jx1776d..xn----ykc7228efm46d; [B1, V3, V6, A4_2]; ; # -问20..-橬
+xn----hdpu849bhis3e.xn----ykc7228efm46d; -问񬰔⒛.؄-񜗉橬; [B1, V3, V6]; xn----hdpu849bhis3e.xn----ykc7228efm46d; ; ; # -问⒛.-橬
+ᮬႬ‌̥。𝟸; ᮬႬ‌̥.2; [C1, P1, V5, V6]; xn--mta930emribme.2; ; xn--mta930emri.2; [P1, V5, V6] # ᮬႬ̥.2
+ᮬႬ‌̥。2; ᮬႬ‌̥.2; [C1, P1, V5, V6]; xn--mta930emribme.2; ; xn--mta930emri.2; [P1, V5, V6] # ᮬႬ̥.2
+ᮬⴌ‌̥。2; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V5] # ᮬⴌ̥.2
+xn--mta176jjjm.2; ᮬⴌ̥.2; [V5]; xn--mta176jjjm.2; ; ; # ᮬⴌ̥.2
+xn--mta176j97cl2q.2; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; ; # ᮬⴌ̥.2
+xn--mta930emri.2; ᮬႬ̥.2; [V5, V6]; xn--mta930emri.2; ; ; # ᮬႬ̥.2
+xn--mta930emribme.2; ᮬႬ‌̥.2; [C1, V5, V6]; xn--mta930emribme.2; ; ; # ᮬႬ̥.2
+ᮬⴌ‌̥。𝟸; ᮬⴌ‌̥.2; [C1, V5]; xn--mta176j97cl2q.2; ; xn--mta176jjjm.2; [V5] # ᮬⴌ̥.2
+?。꠆٩󠒩; ?.꠆٩󠒩; [B1, P1, V5, V6]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩
+?.xn--iib9583fusy0i; ?.꠆٩󠒩; [B1, P1, V5, V6]; ?.xn--iib9583fusy0i; ; ; # ?.꠆٩
+󠄁͟⾶。₇︒눇≮; ͟飛.7︒눇≮; [P1, V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+󠄁͟⾶。₇︒눇≮; ͟飛.7︒눇≮; [P1, V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+󠄁͟飛。7。눇≮; ͟飛.7.눇≮; [P1, V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+󠄁͟飛。7。눇≮; ͟飛.7.눇≮; [P1, V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+xn--9ua0567e.7.xn--gdh6767c; ͟飛.7.눇≮; [V5, V6]; xn--9ua0567e.7.xn--gdh6767c; ; ; # ͟飛.7.눇≮
+xn--9ua0567e.xn--7-ngou006d1ttc; ͟飛.7︒눇≮; [V5, V6]; xn--9ua0567e.xn--7-ngou006d1ttc; ; ; # ͟飛.7︒눇≮
+‌︉𐹴‍.‌⿃; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥
+‌︉𐹴‍.‌鳥; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; xn--so0d.xn--6x6a; [B1] # 𐹴.鳥
+xn--so0d.xn--6x6a; 𐹴.鳥; [B1]; xn--so0d.xn--6x6a; ; ; # 𐹴.鳥
+xn--0ugc6024p.xn--0ug1920c; ‌𐹴‍.‌鳥; [B1, C1, C2]; xn--0ugc6024p.xn--0ug1920c; ; ; # 𐹴.鳥
+🍮.‍󠗒𐦁𝨝; 🍮.‍󠗒𐦁𝨝; [B1, C2, P1, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, P1, V6] # 🍮.𐦁𝨝
+🍮.‍󠗒𐦁𝨝; ; [B1, C2, P1, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; xn--lj8h.xn--ln9ci476aqmr2g; [B1, P1, V6] # 🍮.𐦁𝨝
+xn--lj8h.xn--ln9ci476aqmr2g; 🍮.󠗒𐦁𝨝; [B1, V6]; xn--lj8h.xn--ln9ci476aqmr2g; ; ; # 🍮.𐦁𝨝
+xn--lj8h.xn--1ug6603gr1pfwq37h; 🍮.‍󠗒𐦁𝨝; [B1, C2, V6]; xn--lj8h.xn--1ug6603gr1pfwq37h; ; ; # 🍮.𐦁𝨝
+ٽृ.𞤓‍; ٽृ.𞤵‍; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵
+ٽृ.𞤵‍; ; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; xn--2ib43l.xn--te6h; [] # ٽृ.𞤵
+xn--2ib43l.xn--te6h; ٽृ.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+ٽृ.𞤵; ; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+ٽृ.𞤓; ٽृ.𞤵; ; xn--2ib43l.xn--te6h; ; ; # ٽृ.𞤵
+xn--2ib43l.xn--1ugy711p; ٽृ.𞤵‍; [B3, C2]; xn--2ib43l.xn--1ugy711p; ; ; # ٽृ.𞤵
+٤੍-.󥜽္񦦐; ٤੍-.󥜽္񦦐; [B1, P1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+٤੍-.󥜽္񦦐; ; [B1, P1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+xn----gqc711a.xn--9jd88234f3qm0b; ٤੍-.󥜽္񦦐; [B1, V3, V6]; xn----gqc711a.xn--9jd88234f3qm0b; ; ; # ٤੍-.္
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+4်-𐹸。ꨩ‌𐹴≮; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, P1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; xn--4--e4j7831r.xn--gdh8754cz40c; [B1, P1, V5, V6] # 4်-𐹸.ꨩ𐹴≮
+xn--4--e4j7831r.xn--gdh8754cz40c; 4်-𐹸.ꨩ𐹴≮; [B1, V5, V6]; xn--4--e4j7831r.xn--gdh8754cz40c; ; ; # 4်-𐹸.ꨩ𐹴≮
+xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; 4်-𐹸.ꨩ‌𐹴≮; [B1, C1, V5, V6]; xn--4--e4j7831r.xn--0ugy6gjy5sl3ud; ; ; # 4်-𐹸.ꨩ𐹴≮
+‌。ᅠ྄ྖ; ‌.ᅠ྄ྖ; [C1, P1, V6]; xn--0ug.xn--3ed0by082k; ; .xn--3ed0by082k; [P1, V6, A4_2] # .྄ྖ
+‌。ᅠ྄ྖ; ‌.ᅠ྄ྖ; [C1, P1, V6]; xn--0ug.xn--3ed0b20h; ; .xn--3ed0b20h; [P1, V6, A4_2] # .྄ྖ
+.xn--3ed0b20h; .ᅠ྄ྖ; [V6, X4_2]; .xn--3ed0b20h; [V6, A4_2]; ; # .྄ྖ
+xn--0ug.xn--3ed0b20h; ‌.ᅠ྄ྖ; [C1, V6]; xn--0ug.xn--3ed0b20h; ; ; # .྄ྖ
+.xn--3ed0by082k; .ᅠ྄ྖ; [V6, X4_2]; .xn--3ed0by082k; [V6, A4_2]; ; # .྄ྖ
+xn--0ug.xn--3ed0by082k; ‌.ᅠ྄ྖ; [C1, V6]; xn--0ug.xn--3ed0by082k; ; ; # .྄ྖ
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+≯򍘅.‍𐅼򲇛; ≯򍘅.‍𐅼򲇛; [C2, P1, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; xn--hdh84488f.xn--xy7cw2886b; [P1, V6] # ≯.𐅼
+xn--hdh84488f.xn--xy7cw2886b; ≯򍘅.𐅼򲇛; [V6]; xn--hdh84488f.xn--xy7cw2886b; ; ; # ≯.𐅼
+xn--hdh84488f.xn--1ug8099fbjp4e; ≯򍘅.‍𐅼򲇛; [C2, V6]; xn--hdh84488f.xn--1ug8099fbjp4e; ; ; # ≯.𐅼
+فß𐰯。𝟕𐫫; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫
+فß𐰯。7𐫫; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; xn--ss-jvd2339x.xn--7-mm5i; # فß𐰯.7𐫫
+فSS𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فss𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+xn--ss-jvd2339x.xn--7-mm5i; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+xn--zca96ys96y.xn--7-mm5i; فß𐰯.7𐫫; [B1, B2]; xn--zca96ys96y.xn--7-mm5i; ; ; # فß𐰯.7𐫫
+فSS𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فss𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فSs𐰯。7𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+فSs𐰯。𝟕𐫫; فss𐰯.7𐫫; [B1, B2]; xn--ss-jvd2339x.xn--7-mm5i; ; ; # فss𐰯.7𐫫
+ßެާࢱ。𐭁􅮙𐹲; ßެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--zca685aoa95h.xn--e09co8cr9861c; ; xn--ss-9qet02k.xn--e09co8cr9861c; # ßެާࢱ.𐭁𐹲
+SSެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+ssެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+Ssެާࢱ。𐭁􅮙𐹲; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, P1, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+xn--ss-9qet02k.xn--e09co8cr9861c; ssެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, V6]; xn--ss-9qet02k.xn--e09co8cr9861c; ; ; # ssެާࢱ.𐭁𐹲
+xn--zca685aoa95h.xn--e09co8cr9861c; ßެާࢱ.𐭁􅮙𐹲; [B2, B5, B6, V6]; xn--zca685aoa95h.xn--e09co8cr9861c; ; ; # ßެާࢱ.𐭁𐹲
+-。󠉗⒌𞯛; -.󠉗⒌𞯛; [B1, P1, V3, V6]; -.xn--xsh6367n1bi3e; ; ; # -.⒌
+-。󠉗5.𞯛; -.󠉗5.𞯛; [B1, P1, V3, V6]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5.
+-.xn--5-zz21m.xn--6x6h; -.󠉗5.𞯛; [B1, V3, V6]; -.xn--5-zz21m.xn--6x6h; ; ; # -.5.
+-.xn--xsh6367n1bi3e; -.󠉗⒌𞯛; [B1, V3, V6]; -.xn--xsh6367n1bi3e; ; ; # -.⒌
+𼎏ς.-≮ﲫ; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮ﲫ; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮خج; ; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏ς.-≮خج; 𼎏ς.-≮خج; [B1, P1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; xn--4xa92520c.xn----9mcf1400a; # ς.-≮خج
+𼎏Σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏Σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮خج; ; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮خج; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+xn--4xa92520c.xn----9mcf1400a; 𼎏σ.-≮خج; [B1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+xn--3xa13520c.xn----9mcf1400a; 𼎏ς.-≮خج; [B1, V3, V6]; xn--3xa13520c.xn----9mcf1400a; ; ; # ς.-≮خج
+𼎏Σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏Σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+𼎏σ.-≮ﲫ; 𼎏σ.-≮خج; [B1, P1, V3, V6]; xn--4xa92520c.xn----9mcf1400a; ; ; # σ.-≮خج
+ꡗࢸܙ.񔤔󠛙్ﰾ; ꡗࢸܙ.񔤔󠛙్كي; [B5, B6, P1, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+ꡗࢸܙ.񔤔󠛙్كي; ; [B5, B6, P1, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ꡗࢸܙ.񔤔󠛙్كي; [B5, B6, V6]; xn--jnb34fs003a.xn--fhbo927bk128mpi24d; ; ; # ꡗࢸܙ.్كي
+𐠰ࢷ𞤌𐫭。𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤮𐫭。𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤮𐫭.𐋦៍𝩃; ; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+𐠰ࢷ𞤌𐫭.𐋦៍𝩃; 𐠰ࢷ𞤮𐫭.𐋦៍𝩃; [B1]; xn--dzb5191kezbrw47a.xn--p4e3841jz9tf; ; ; # 𐠰ࢷ𞤮𐫭.𐋦៍𝩃
+₂㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+₂㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+2㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+2㘷--。ۓ‌𐫆𑖿; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; xn--2---u58b.xn--jlb8024k14g; [B1, V2, V3] # 2㘷--.ۓ𐫆𑖿
+xn--2---u58b.xn--jlb8024k14g; 2㘷--.ۓ𐫆𑖿; [B1, V2, V3]; xn--2---u58b.xn--jlb8024k14g; ; ; # 2㘷--.ۓ𐫆𑖿
+xn--2---u58b.xn--jlb820ku99nbgj; 2㘷--.ۓ‌𐫆𑖿; [B1, C1, V2, V3]; xn--2---u58b.xn--jlb820ku99nbgj; ; ; # 2㘷--.ۓ𐫆𑖿
+-𘊻.ᡮح-; -𘊻.ᡮح-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+-𘊻.ᡮح-; ; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+xn----bp5n.xn----bnc231l; -𘊻.ᡮح-; [B1, B5, B6, V3]; xn----bp5n.xn----bnc231l; ; ; # -𘊻.ᡮح-
+‌-ß。ᢣ𐹭ؿ; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ
+‌-ß。ᢣ𐹭ؿ; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ß.ᢣ𐹭ؿ
+‌-SS。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-Ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+-ss.xn--bhb925glx3p; -ss.ᢣ𐹭ؿ; [B1, B5, B6, V3]; -ss.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ
+xn---ss-8m0a.xn--bhb925glx3p; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; ; # -ss.ᢣ𐹭ؿ
+xn----qfa550v.xn--bhb925glx3p; ‌-ß.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn----qfa550v.xn--bhb925glx3p; ; ; # -ß.ᢣ𐹭ؿ
+‌-SS。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+‌-Ss。ᢣ𐹭ؿ; ‌-ss.ᢣ𐹭ؿ; [B1, B5, B6, C1]; xn---ss-8m0a.xn--bhb925glx3p; ; -ss.xn--bhb925glx3p; [B1, B5, B6, V3] # -ss.ᢣ𐹭ؿ
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐Ӏ᮪ࣶ.눵; ꧐Ӏ᮪ࣶ.눵; [P1, V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+xn--s5a04sn4u297k.xn--2e1b; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+xn--d5a07sn4u297k.xn--2e1b; ꧐Ӏ᮪ࣶ.눵; [V6]; xn--d5a07sn4u297k.xn--2e1b; ; ; # ꧐Ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꧐ӏ᮪ࣶ.눵; ꧐ӏ᮪ࣶ.눵; ; xn--s5a04sn4u297k.xn--2e1b; ; ; # ꧐ӏ᮪ࣶ.눵
+꣪。𖄿𑆾󠇗; ꣪.𖄿𑆾; [P1, V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+꣪。𖄿𑆾󠇗; ꣪.𖄿𑆾; [P1, V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+xn--3g9a.xn--ud1dz07k; ꣪.𖄿𑆾; [V5, V6]; xn--3g9a.xn--ud1dz07k; ; ; # ꣪.𑆾
+󇓓𑚳。񐷿≯⾇; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯⾇; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯舛; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+󇓓𑚳。񐷿≯舛; 󇓓𑚳.񐷿≯舛; [P1, V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+xn--3e2d79770c.xn--hdh0088abyy1c; 󇓓𑚳.񐷿≯舛; [V6]; xn--3e2d79770c.xn--hdh0088abyy1c; ; ; # 𑚳.≯舛
+𐫇١‌.‍‌; 𐫇١‌.‍‌; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [] # 𐫇١.
+𐫇١‌.‍‌; ; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; xn--9hb7344k.; [] # 𐫇١.
+xn--9hb7344k.; 𐫇١.; ; xn--9hb7344k.; ; ; # 𐫇١.
+𐫇١.; ; ; xn--9hb7344k.; ; ; # 𐫇١.
+xn--9hb652kv99n.xn--0ugb; 𐫇١‌.‍‌; [B1, B3, C1, C2]; xn--9hb652kv99n.xn--0ugb; ; ; # 𐫇١.
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+񡅈砪≯ᢑ。≯𝩚򓴔‌; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, P1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; [P1, V6] # 砪≯ᢑ.≯𝩚
+xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; 񡅈砪≯ᢑ.≯𝩚򓴔; [V6]; xn--bbf561cf95e57y3e.xn--hdh0834o7mj6b; ; ; # 砪≯ᢑ.≯𝩚
+xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; 񡅈砪≯ᢑ.≯𝩚򓴔‌; [C1, V6]; xn--bbf561cf95e57y3e.xn--0ugz6gc910ejro8c; ; ; # 砪≯ᢑ.≯𝩚
+Ⴥ.𑄳㊸; Ⴥ.𑄳43; [P1, V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+Ⴥ.𑄳43; ; [P1, V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+ⴥ.𑄳43; ; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+xn--tlj.xn--43-274o; ⴥ.𑄳43; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+xn--9nd.xn--43-274o; Ⴥ.𑄳43; [V5, V6]; xn--9nd.xn--43-274o; ; ; # Ⴥ.𑄳43
+ⴥ.𑄳㊸; ⴥ.𑄳43; [V5]; xn--tlj.xn--43-274o; ; ; # ⴥ.𑄳43
+𝟎٣。Ⴒᡇࣲ𐹠; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, P1, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+0٣。Ⴒᡇࣲ𐹠; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, P1, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+0٣。ⴒᡇࣲ𐹠; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+xn--0-fqc.xn--10b369eivp359r; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+xn--0-fqc.xn--10b180bnwgfy0z; 0٣.Ⴒᡇࣲ𐹠; [B1, B5, B6, V6]; xn--0-fqc.xn--10b180bnwgfy0z; ; ; # 0٣.Ⴒᡇࣲ𐹠
+𝟎٣。ⴒᡇࣲ𐹠; 0٣.ⴒᡇࣲ𐹠; [B1, B5, B6]; xn--0-fqc.xn--10b369eivp359r; ; ; # 0٣.ⴒᡇࣲ𐹠
+񗪨󠄉ᅠྷ.񸞰꥓; 񗪨ᅠྷ.񸞰꥓; [P1, V6]; xn--kgd7493jee34a.xn--3j9au7544a; ; ; # ྷ.꥓
+񗪨󠄉ᅠྷ.񸞰꥓; 񗪨ᅠྷ.񸞰꥓; [P1, V6]; xn--kgd36f9z57y.xn--3j9au7544a; ; ; # ྷ.꥓
+xn--kgd36f9z57y.xn--3j9au7544a; 񗪨ᅠྷ.񸞰꥓; [V6]; xn--kgd36f9z57y.xn--3j9au7544a; ; ; # ྷ.꥓
+xn--kgd7493jee34a.xn--3j9au7544a; 񗪨ᅠྷ.񸞰꥓; [V6]; xn--kgd7493jee34a.xn--3j9au7544a; ; ; # ྷ.꥓
+ؘ.۳‌꥓; ; [C1, V5]; xn--6fb.xn--gmb469jjf1h; ; xn--6fb.xn--gmb0524f; [V5] # ؘ.۳꥓
+xn--6fb.xn--gmb0524f; ؘ.۳꥓; [V5]; xn--6fb.xn--gmb0524f; ; ; # ؘ.۳꥓
+xn--6fb.xn--gmb469jjf1h; ؘ.۳‌꥓; [C1, V5]; xn--6fb.xn--gmb469jjf1h; ; ; # ؘ.۳꥓
+ᡌ.︒ᢑ; ᡌ.︒ᢑ; [P1, V6]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ
+ᡌ.。ᢑ; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ
+xn--c8e..xn--bbf; ᡌ..ᢑ; [X4_2]; xn--c8e..xn--bbf; [A4_2]; ; # ᡌ..ᢑ
+xn--c8e.xn--bbf9168i; ᡌ.︒ᢑ; [V6]; xn--c8e.xn--bbf9168i; ; ; # ᡌ.︒ᢑ
+𑋪ၳ。𞽧; 𑋪ၳ.𞽧; [B1, B3, B6, P1, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+𑋪ၳ。𞽧; 𑋪ၳ.𞽧; [B1, B3, B6, P1, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+xn--xld7443k.xn--4o7h; 𑋪ၳ.𞽧; [B1, B3, B6, V5, V6]; xn--xld7443k.xn--4o7h; ; ; # 𑋪ၳ.
+𞷏。ᠢ򓘆; 𞷏.ᠢ򓘆; [P1, V6]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ
+xn--hd7h.xn--46e66060j; 𞷏.ᠢ򓘆; [V6]; xn--hd7h.xn--46e66060j; ; ; # .ᠢ
+𑄳㴼.‌𐹡⃫񫺦; 𑄳㴼.‌𐹡⃫񫺦; [B1, C1, P1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, P1, V5, V6] # 𑄳㴼.𐹡⃫
+𑄳㴼.‌𐹡⃫񫺦; ; [B1, C1, P1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; xn--iym9428c.xn--e1g3464g08p3b; [B1, P1, V5, V6] # 𑄳㴼.𐹡⃫
+xn--iym9428c.xn--e1g3464g08p3b; 𑄳㴼.𐹡⃫񫺦; [B1, V5, V6]; xn--iym9428c.xn--e1g3464g08p3b; ; ; # 𑄳㴼.𐹡⃫
+xn--iym9428c.xn--0ug46a7218cllv0c; 𑄳㴼.‌𐹡⃫񫺦; [B1, C1, V5, V6]; xn--iym9428c.xn--0ug46a7218cllv0c; ; ; # 𑄳㴼.𐹡⃫
+񠻟𐹳𑈯。̝; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, P1, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+񠻟𐹳𑈯。̝; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, P1, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+xn--ro0dw7dey96m.xn--eta; 񠻟𐹳𑈯.̝; [B1, B3, B5, B6, V5, V6]; xn--ro0dw7dey96m.xn--eta; ; ; # 𐹳𑈯.̝
+ᢊ뾜󠱴𑚶。࢝𐹥; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, P1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+ᢊ뾜󠱴𑚶。࢝𐹥; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, P1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+xn--39e4566fjv8bwmt6n.xn--myb6415k; ᢊ뾜󠱴𑚶.࢝𐹥; [B1, V5, V6]; xn--39e4566fjv8bwmt6n.xn--myb6415k; ; ; # ᢊ뾜𑚶.࢝𐹥
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+𐹥≠。𐋲󠧠‌; 𐹥≠.𐋲󠧠‌; [B1, C1, P1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; xn--1ch6704g.xn--m97cw2999c; [B1, P1, V6] # 𐹥≠.𐋲
+xn--1ch6704g.xn--m97cw2999c; 𐹥≠.𐋲󠧠; [B1, V6]; xn--1ch6704g.xn--m97cw2999c; ; ; # 𐹥≠.𐋲
+xn--1ch6704g.xn--0ug3840g51u4g; 𐹥≠.𐋲󠧠‌; [B1, C1, V6]; xn--1ch6704g.xn--0ug3840g51u4g; ; ; # 𐹥≠.𐋲
+ᅟ񙯠्.‍꥓𐪤; ᅟ񙯠्.‍꥓𐪤; [B1, C2, P1, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; xn--n3b542bb085j.xn--3j9al95p; [B5, B6, P1, V5, V6] # ्.꥓
+ᅟ񙯠्.‍꥓𐪤; ; [B1, C2, P1, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; xn--n3b542bb085j.xn--3j9al95p; [B5, B6, P1, V5, V6] # ्.꥓
+xn--n3b542bb085j.xn--3j9al95p; ᅟ񙯠्.꥓𐪤; [B5, B6, V5, V6]; xn--n3b542bb085j.xn--3j9al95p; ; ; # ्.꥓
+xn--n3b542bb085j.xn--1ug6815co9wc; ᅟ񙯠्.‍꥓𐪤; [B1, C2, V6]; xn--n3b542bb085j.xn--1ug6815co9wc; ; ; # ्.꥓
+򌋔󠆎󠆗𑲕。≮; 򌋔𑲕.≮; [P1, V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+򌋔󠆎󠆗𑲕。≮; 򌋔𑲕.≮; [P1, V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+xn--4m3dv4354a.xn--gdh; 򌋔𑲕.≮; [V6]; xn--4m3dv4354a.xn--gdh; ; ; # 𑲕.≮
+󠆦.ࣣ暀≠; .ࣣ暀≠; [P1, V5, V6, X4_2]; .xn--m0b461k3g2c; [P1, V5, V6, A4_2]; ; # .ࣣ暀≠
+󠆦.ࣣ暀≠; .ࣣ暀≠; [P1, V5, V6, X4_2]; .xn--m0b461k3g2c; [P1, V5, V6, A4_2]; ; # .ࣣ暀≠
+.xn--m0b461k3g2c; .ࣣ暀≠; [V5, V6, X4_2]; .xn--m0b461k3g2c; [V5, V6, A4_2]; ; # .ࣣ暀≠
+𐡤꯭。ﴰ򜖅ᷰ; 𐡤꯭.شم򜖅ᷰ; [B2, B3, P1, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+𐡤꯭。شم򜖅ᷰ; 𐡤꯭.شم򜖅ᷰ; [B2, B3, P1, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+xn--429ak76o.xn--zgb8a701kox37t; 𐡤꯭.شم򜖅ᷰ; [B2, B3, V6]; xn--429ak76o.xn--zgb8a701kox37t; ; ; # 𐡤꯭.شمᷰ
+𝉃‍⒈。Ⴌ𞱓; 𝉃‍⒈.Ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6]; xn--1ug68oq348b.xn--knd8464v; ; xn--tshz828m.xn--knd8464v; [B1, B5, B6, P1, V5, V6] # 𝉃⒈.Ⴌ
+𝉃‍1.。Ⴌ𞱓; 𝉃‍1..Ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6, X4_2]; xn--1-tgn9827q..xn--knd8464v; [B1, B5, B6, C2, P1, V5, V6, A4_2]; xn--1-px8q..xn--knd8464v; [B1, B5, B6, P1, V5, V6, A4_2] # 𝉃1..Ⴌ
+𝉃‍1.。ⴌ𞱓; 𝉃‍1..ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, P1, V5, V6, A4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, P1, V5, V6, A4_2] # 𝉃1..ⴌ
+xn--1-px8q..xn--3kj4524l; 𝉃1..ⴌ𞱓; [B1, B5, B6, V5, V6, X4_2]; xn--1-px8q..xn--3kj4524l; [B1, B5, B6, V5, V6, A4_2]; ; # 𝉃1..ⴌ
+xn--1-tgn9827q..xn--3kj4524l; 𝉃‍1..ⴌ𞱓; [B1, B5, B6, C2, V5, V6, X4_2]; xn--1-tgn9827q..xn--3kj4524l; [B1, B5, B6, C2, V5, V6, A4_2]; ; # 𝉃1..ⴌ
+xn--1-px8q..xn--knd8464v; 𝉃1..Ⴌ𞱓; [B1, B5, B6, V5, V6, X4_2]; xn--1-px8q..xn--knd8464v; [B1, B5, B6, V5, V6, A4_2]; ; # 𝉃1..Ⴌ
+xn--1-tgn9827q..xn--knd8464v; 𝉃‍1..Ⴌ𞱓; [B1, B5, B6, C2, V5, V6, X4_2]; xn--1-tgn9827q..xn--knd8464v; [B1, B5, B6, C2, V5, V6, A4_2]; ; # 𝉃1..Ⴌ
+𝉃‍⒈。ⴌ𞱓; 𝉃‍⒈.ⴌ𞱓; [B1, B5, B6, C2, P1, V5, V6]; xn--1ug68oq348b.xn--3kj4524l; ; xn--tshz828m.xn--3kj4524l; [B1, B5, B6, P1, V5, V6] # 𝉃⒈.ⴌ
+xn--tshz828m.xn--3kj4524l; 𝉃⒈.ⴌ𞱓; [B1, B5, B6, V5, V6]; xn--tshz828m.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ
+xn--1ug68oq348b.xn--3kj4524l; 𝉃‍⒈.ⴌ𞱓; [B1, B5, B6, C2, V5, V6]; xn--1ug68oq348b.xn--3kj4524l; ; ; # 𝉃⒈.ⴌ
+xn--tshz828m.xn--knd8464v; 𝉃⒈.Ⴌ𞱓; [B1, B5, B6, V5, V6]; xn--tshz828m.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ
+xn--1ug68oq348b.xn--knd8464v; 𝉃‍⒈.Ⴌ𞱓; [B1, B5, B6, C2, V5, V6]; xn--1ug68oq348b.xn--knd8464v; ; ; # 𝉃⒈.Ⴌ
+󠣙੍𱫘𞤸.ς񵯞􈰔; ; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𞤸.ς
+󠣙੍𱫘𞤖.Σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤸.σ񵯞􈰔; ; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤖.σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+󠣙੍𱫘𞤖.ς񵯞􈰔; 󠣙੍𱫘𞤸.ς񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; # ੍𞤸.ς
+xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; 󠣙੍𱫘𞤸.ς񵯞􈰔; [B1, V6]; xn--ybc0236vjvxgt5q0g.xn--3xa03737giye6b; ; ; # ੍𞤸.ς
+󠣙੍𱫘𞤸.Σ񵯞􈰔; 󠣙੍𱫘𞤸.σ񵯞􈰔; [B1, P1, V6]; xn--ybc0236vjvxgt5q0g.xn--4xa82737giye6b; ; ; # ੍𞤸.σ
+ߓ。‌𐫀򞭱; ߓ.‌𐫀򞭱; [B1, C1, P1, V6]; xn--usb.xn--0ug9553gm3v5d; ; xn--usb.xn--pw9ci1099a; [B2, B3, P1, V6] # ߓ.𐫀
+xn--usb.xn--pw9ci1099a; ߓ.𐫀򞭱; [B2, B3, V6]; xn--usb.xn--pw9ci1099a; ; ; # ߓ.𐫀
+xn--usb.xn--0ug9553gm3v5d; ߓ.‌𐫀򞭱; [B1, C1, V6]; xn--usb.xn--0ug9553gm3v5d; ; ; # ߓ.𐫀
+ᰮ𞀝.֦ꡟ𞤕󠆖; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+ᰮ𞀝.֦ꡟ𞤷󠆖; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+xn--q1f4493q.xn--xcb8244fifvj; ᰮ𞀝.֦ꡟ𞤷; [B1, B3, B6, V5]; xn--q1f4493q.xn--xcb8244fifvj; ; ; # ᰮ𞀝.֦ꡟ𞤷
+䂹󾖅𐋦.‍; 䂹󾖅𐋦.‍; [C2, P1, V6]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [P1, V6] # 䂹𐋦.
+䂹󾖅𐋦.‍; ; [C2, P1, V6]; xn--0on3543c5981i.xn--1ug; ; xn--0on3543c5981i.; [P1, V6] # 䂹𐋦.
+xn--0on3543c5981i.; 䂹󾖅𐋦.; [V6]; xn--0on3543c5981i.; ; ; # 䂹𐋦.
+xn--0on3543c5981i.xn--1ug; 䂹󾖅𐋦.‍; [C2, V6]; xn--0on3543c5981i.xn--1ug; ; ; # 䂹𐋦.
+꧀‌𐹲‌。ݧ🄉; ꧀‌𐹲‌.ݧ🄉; [B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--rpb6081w; ; xn--7m9an32q.xn--rpb6081w; [B5, B6, P1, V5, V6] # ꧀𐹲.ݧ🄉
+꧀‌𐹲‌。ݧ8,; ꧀‌𐹲‌.ݧ8,; [B3, B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--8,-qle; ; xn--7m9an32q.xn--8,-qle; [B3, B5, B6, P1, V5, V6] # ꧀𐹲.ݧ8,
+xn--7m9an32q.xn--8,-qle; ꧀𐹲.ݧ8,; [B3, B5, B6, P1, V5, V6]; xn--7m9an32q.xn--8,-qle; ; ; # ꧀𐹲.ݧ8,
+xn--0uga8686hdgvd.xn--8,-qle; ꧀‌𐹲‌.ݧ8,; [B3, B5, B6, C1, P1, V5, V6]; xn--0uga8686hdgvd.xn--8,-qle; ; ; # ꧀𐹲.ݧ8,
+xn--7m9an32q.xn--rpb6081w; ꧀𐹲.ݧ🄉; [B5, B6, V5, V6]; xn--7m9an32q.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉
+xn--0uga8686hdgvd.xn--rpb6081w; ꧀‌𐹲‌.ݧ🄉; [B5, B6, C1, V5, V6]; xn--0uga8686hdgvd.xn--rpb6081w; ; ; # ꧀𐹲.ݧ🄉
+︒。Ⴃ≯; ︒.Ⴃ≯; [P1, V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+︒。Ⴃ≯; ︒.Ⴃ≯; [P1, V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+。。Ⴃ≯; ..Ⴃ≯; [P1, V6, X4_2]; ..xn--bnd622g; [P1, V6, A4_2]; ; # ..Ⴃ≯
+。。Ⴃ≯; ..Ⴃ≯; [P1, V6, X4_2]; ..xn--bnd622g; [P1, V6, A4_2]; ; # ..Ⴃ≯
+。。ⴃ≯; ..ⴃ≯; [P1, V6, X4_2]; ..xn--hdh782b; [P1, V6, A4_2]; ; # ..ⴃ≯
+。。ⴃ≯; ..ⴃ≯; [P1, V6, X4_2]; ..xn--hdh782b; [P1, V6, A4_2]; ; # ..ⴃ≯
+..xn--hdh782b; ..ⴃ≯; [V6, X4_2]; ..xn--hdh782b; [V6, A4_2]; ; # ..ⴃ≯
+..xn--bnd622g; ..Ⴃ≯; [V6, X4_2]; ..xn--bnd622g; [V6, A4_2]; ; # ..Ⴃ≯
+︒。ⴃ≯; ︒.ⴃ≯; [P1, V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+︒。ⴃ≯; ︒.ⴃ≯; [P1, V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+xn--y86c.xn--hdh782b; ︒.ⴃ≯; [V6]; xn--y86c.xn--hdh782b; ; ; # ︒.ⴃ≯
+xn--y86c.xn--bnd622g; ︒.Ⴃ≯; [V6]; xn--y86c.xn--bnd622g; ; ; # ︒.Ⴃ≯
+𐹮。󠢼‍; 𐹮.󠢼‍; [B1, C2, P1, V6]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, P1, V6] # 𐹮.
+𐹮。󠢼‍; 𐹮.󠢼‍; [B1, C2, P1, V6]; xn--mo0d.xn--1ug18431l; ; xn--mo0d.xn--wy46e; [B1, P1, V6] # 𐹮.
+xn--mo0d.xn--wy46e; 𐹮.󠢼; [B1, V6]; xn--mo0d.xn--wy46e; ; ; # 𐹮.
+xn--mo0d.xn--1ug18431l; 𐹮.󠢼‍; [B1, C2, V6]; xn--mo0d.xn--1ug18431l; ; ; # 𐹮.
+Ⴞ𐹨。︒ݽ‍Ⴏ; Ⴞ𐹨.︒ݽ‍Ⴏ; [B1, B5, B6, C2, P1, V6]; xn--2nd0990k.xn--eqb228bgzmvp0t; ; xn--2nd0990k.xn--eqb228b583r; [B1, B5, B6, P1, V6] # Ⴞ𐹨.︒ݽႯ
+Ⴞ𐹨。。ݽ‍Ⴏ; Ⴞ𐹨..ݽ‍Ⴏ; [B2, B3, B5, B6, C2, P1, V6, X4_2]; xn--2nd0990k..xn--eqb228bgzm; [B2, B3, B5, B6, C2, P1, V6, A4_2]; xn--2nd0990k..xn--eqb228b; [B2, B3, B5, B6, P1, V6, A4_2] # Ⴞ𐹨..ݽႯ
+ⴞ𐹨。。ݽ‍ⴏ; ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2] # ⴞ𐹨..ݽⴏ
+Ⴞ𐹨。。ݽ‍ⴏ; Ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, P1, V6, X4_2]; xn--2nd0990k..xn--eqb096jpgj; [B2, B3, B5, B6, C2, P1, V6, A4_2]; xn--2nd0990k..xn--eqb053q; [B2, B3, B5, B6, P1, V6, A4_2] # Ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb053q; Ⴞ𐹨..ݽⴏ; [B2, B3, B5, B6, V6, X4_2]; xn--2nd0990k..xn--eqb053q; [B2, B3, B5, B6, V6, A4_2]; ; # Ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb096jpgj; Ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, V6, X4_2]; xn--2nd0990k..xn--eqb096jpgj; [B2, B3, B5, B6, C2, V6, A4_2]; ; # Ⴞ𐹨..ݽⴏ
+xn--mlju223e..xn--eqb053q; ⴞ𐹨..ݽⴏ; [B2, B3, B5, B6, X4_2]; xn--mlju223e..xn--eqb053q; [B2, B3, B5, B6, A4_2]; ; # ⴞ𐹨..ݽⴏ
+xn--mlju223e..xn--eqb096jpgj; ⴞ𐹨..ݽ‍ⴏ; [B2, B3, B5, B6, C2, X4_2]; xn--mlju223e..xn--eqb096jpgj; [B2, B3, B5, B6, C2, A4_2]; ; # ⴞ𐹨..ݽⴏ
+xn--2nd0990k..xn--eqb228b; Ⴞ𐹨..ݽႯ; [B2, B3, B5, B6, V6, X4_2]; xn--2nd0990k..xn--eqb228b; [B2, B3, B5, B6, V6, A4_2]; ; # Ⴞ𐹨..ݽႯ
+xn--2nd0990k..xn--eqb228bgzm; Ⴞ𐹨..ݽ‍Ⴏ; [B2, B3, B5, B6, C2, V6, X4_2]; xn--2nd0990k..xn--eqb228bgzm; [B2, B3, B5, B6, C2, V6, A4_2]; ; # Ⴞ𐹨..ݽႯ
+ⴞ𐹨。︒ݽ‍ⴏ; ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, P1, V6]; xn--mlju223e.xn--eqb096jpgj9y7r; ; xn--mlju223e.xn--eqb053qjk7l; [B1, B5, B6, P1, V6] # ⴞ𐹨.︒ݽⴏ
+Ⴞ𐹨。︒ݽ‍ⴏ; Ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, P1, V6]; xn--2nd0990k.xn--eqb096jpgj9y7r; ; xn--2nd0990k.xn--eqb053qjk7l; [B1, B5, B6, P1, V6] # Ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb053qjk7l; Ⴞ𐹨.︒ݽⴏ; [B1, B5, B6, V6]; xn--2nd0990k.xn--eqb053qjk7l; ; ; # Ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb096jpgj9y7r; Ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, V6]; xn--2nd0990k.xn--eqb096jpgj9y7r; ; ; # Ⴞ𐹨.︒ݽⴏ
+xn--mlju223e.xn--eqb053qjk7l; ⴞ𐹨.︒ݽⴏ; [B1, B5, B6, V6]; xn--mlju223e.xn--eqb053qjk7l; ; ; # ⴞ𐹨.︒ݽⴏ
+xn--mlju223e.xn--eqb096jpgj9y7r; ⴞ𐹨.︒ݽ‍ⴏ; [B1, B5, B6, C2, V6]; xn--mlju223e.xn--eqb096jpgj9y7r; ; ; # ⴞ𐹨.︒ݽⴏ
+xn--2nd0990k.xn--eqb228b583r; Ⴞ𐹨.︒ݽႯ; [B1, B5, B6, V6]; xn--2nd0990k.xn--eqb228b583r; ; ; # Ⴞ𐹨.︒ݽႯ
+xn--2nd0990k.xn--eqb228bgzmvp0t; Ⴞ𐹨.︒ݽ‍Ⴏ; [B1, B5, B6, C2, V6]; xn--2nd0990k.xn--eqb228bgzmvp0t; ; ; # Ⴞ𐹨.︒ݽႯ
+‌Ⴆ𝟹。-⃒-ߑ; ‌Ⴆ3.-⃒-ߑ; [B1, C1, P1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; xn--3-i0g.xn-----vue617w; [B1, P1, V3, V6] # Ⴆ3.-⃒-ߑ
+‌Ⴆ3。-⃒-ߑ; ‌Ⴆ3.-⃒-ߑ; [B1, C1, P1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; xn--3-i0g.xn-----vue617w; [B1, P1, V3, V6] # Ⴆ3.-⃒-ߑ
+‌ⴆ3。-⃒-ߑ; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ
+xn--3-lvs.xn-----vue617w; ⴆ3.-⃒-ߑ; [B1, V3]; xn--3-lvs.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ
+xn--3-rgnv99c.xn-----vue617w; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; ; # ⴆ3.-⃒-ߑ
+xn--3-i0g.xn-----vue617w; Ⴆ3.-⃒-ߑ; [B1, V3, V6]; xn--3-i0g.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ
+xn--3-i0g939i.xn-----vue617w; ‌Ⴆ3.-⃒-ߑ; [B1, C1, V3, V6]; xn--3-i0g939i.xn-----vue617w; ; ; # Ⴆ3.-⃒-ߑ
+‌ⴆ𝟹。-⃒-ߑ; ‌ⴆ3.-⃒-ߑ; [B1, C1, V3]; xn--3-rgnv99c.xn-----vue617w; ; xn--3-lvs.xn-----vue617w; [B1, V3] # ⴆ3.-⃒-ߑ
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃Ⴡ-󠁝。≠-🤖; 箃Ⴡ-󠁝.≠-🤖; [P1, V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+xn----4wsr321ay823p.xn----tfot873s; 箃ⴡ-󠁝.≠-🤖; [V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+xn----11g3013fy8x5m.xn----tfot873s; 箃Ⴡ-󠁝.≠-🤖; [V6]; xn----11g3013fy8x5m.xn----tfot873s; ; ; # 箃Ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+箃ⴡ-󠁝。≠-🤖; 箃ⴡ-󠁝.≠-🤖; [P1, V6]; xn----4wsr321ay823p.xn----tfot873s; ; ; # 箃ⴡ-.≠-🤖
+ߥ.ڵ; ; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ
+xn--dtb.xn--okb; ߥ.ڵ; ; xn--dtb.xn--okb; ; ; # ߥ.ڵ
+‌‍.𞤿; ; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿
+‌‍.𞤝; ‌‍.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; .xn--3e6h; [A4_2] # .𞤿
+.xn--3e6h; .𞤿; [X4_2]; .xn--3e6h; [A4_2]; ; # .𞤿
+xn--0ugc.xn--3e6h; ‌‍.𞤿; [B1, C1, C2]; xn--0ugc.xn--3e6h; ; ; # .𞤿
+xn--3e6h; 𞤿; ; xn--3e6h; ; ; # 𞤿
+𞤿; ; ; xn--3e6h; ; ; # 𞤿
+𞤝; 𞤿; ; xn--3e6h; ; ; # 𞤿
+🜑𐹧ع.ς𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; xn--4gb3736kk4zf.xn--4xa2248dy27d; # 🜑𐹧ع.ς𑍍蜹
+🜑𐹧ع.Σ𑍍蜹; 🜑𐹧ع.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+🜑𐹧ع.σ𑍍蜹; ; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+xn--4gb3736kk4zf.xn--4xa2248dy27d; 🜑𐹧ع.σ𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--4xa2248dy27d; ; ; # 🜑𐹧ع.σ𑍍蜹
+xn--4gb3736kk4zf.xn--3xa4248dy27d; 🜑𐹧ع.ς𑍍蜹; [B1]; xn--4gb3736kk4zf.xn--3xa4248dy27d; ; ; # 🜑𐹧ع.ς𑍍蜹
+򫠐ス􆟤٩.󚃟; 򫠐ス􆟤٩.󚃟; [B5, B6, P1, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+򫠐ス􆟤٩.󚃟; ; [B5, B6, P1, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+xn--iib777sp230oo708a.xn--7824e; 򫠐ス􆟤٩.󚃟; [B5, B6, V6]; xn--iib777sp230oo708a.xn--7824e; ; ; # ス٩.
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+𝪣򕡝.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.xn--?-wec30g; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+XN--8C3HU7971A.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+XN--8C3HU7971A.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+Xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+Xn--8c3hu7971a.֚?ۂ; 𝪣򕡝.֚?ۂ; [B1, P1, V5, V6]; xn--8c3hu7971a.xn--?-wec30g; ; ; # 𝪣.֚?ۂ
+٠򪓵‌。ݗ; ٠򪓵‌.ݗ; [B1, C1, P1, V6]; xn--8hb852ke991q.xn--bpb; ; xn--8hb82030l.xn--bpb; [B1, P1, V6] # ٠.ݗ
+xn--8hb82030l.xn--bpb; ٠򪓵.ݗ; [B1, V6]; xn--8hb82030l.xn--bpb; ; ; # ٠.ݗ
+xn--8hb852ke991q.xn--bpb; ٠򪓵‌.ݗ; [B1, C1, V6]; xn--8hb852ke991q.xn--bpb; ; ; # ٠.ݗ
+်‍‌。-‌; ်‍‌.-‌; [C1, V3, V5]; xn--bkd412fca.xn----sgn; ; xn--bkd.-; [V3, V5] # ်.-
+xn--bkd.-; ်.-; [V3, V5]; xn--bkd.-; ; ; # ်.-
+xn--bkd412fca.xn----sgn; ်‍‌.-‌; [C1, V3, V5]; xn--bkd412fca.xn----sgn; ; ; # ်.-
+︒。᭄ᡉ; ︒.᭄ᡉ; [P1, V5, V6]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ
+。。᭄ᡉ; ..᭄ᡉ; [V5, X4_2]; ..xn--87e93m; [V5, A4_2]; ; # ..᭄ᡉ
+..xn--87e93m; ..᭄ᡉ; [V5, X4_2]; ..xn--87e93m; [V5, A4_2]; ; # ..᭄ᡉ
+xn--y86c.xn--87e93m; ︒.᭄ᡉ; [V5, V6]; xn--y86c.xn--87e93m; ; ; # ︒.᭄ᡉ
+ݘß。ጫᢊݨ𝟐; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2
+ݘß。ጫᢊݨ2; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; xn--ss-gke.xn--2-b5c641gfmf; # ݘß.ጫᢊݨ2
+ݘSS。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘss。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+xn--ss-gke.xn--2-b5c641gfmf; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+xn--zca724a.xn--2-b5c641gfmf; ݘß.ጫᢊݨ2; [B2, B3, B5]; xn--zca724a.xn--2-b5c641gfmf; ; ; # ݘß.ጫᢊݨ2
+ݘSS。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘss。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘSs。ጫᢊݨ2; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+ݘSs。ጫᢊݨ𝟐; ݘss.ጫᢊݨ2; [B2, B3, B5]; xn--ss-gke.xn--2-b5c641gfmf; ; ; # ݘss.ጫᢊݨ2
+߃𞶇ᚲ.ं͓𝟚্; ߃𞶇ᚲ.ं͓2্; [B1, B2, B3, P1, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+߃𞶇ᚲ.ं͓2্; ; [B1, B2, B3, P1, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+xn--esb067enh07a.xn--2-lgb874bjxa; ߃𞶇ᚲ.ं͓2্; [B1, B2, B3, V5, V6]; xn--esb067enh07a.xn--2-lgb874bjxa; ; ; # ߃ᚲ.ं͓2্
+-᮫︒‍.񒶈񥹓; ; [C2, P1, V3, V6]; xn----qmlv7tw180a.xn--x50zy803a; ; xn----qml1407i.xn--x50zy803a; [P1, V3, V6] # -᮫︒.
+-᮫。‍.񒶈񥹓; -᮫.‍.񒶈񥹓; [C2, P1, V3, V6]; xn----qml.xn--1ug.xn--x50zy803a; ; xn----qml..xn--x50zy803a; [P1, V3, V6, A4_2] # -᮫..
+xn----qml..xn--x50zy803a; -᮫..񒶈񥹓; [V3, V6, X4_2]; xn----qml..xn--x50zy803a; [V3, V6, A4_2]; ; # -᮫..
+xn----qml.xn--1ug.xn--x50zy803a; -᮫.‍.񒶈񥹓; [C2, V3, V6]; xn----qml.xn--1ug.xn--x50zy803a; ; ; # -᮫..
+xn----qml1407i.xn--x50zy803a; -᮫︒.񒶈񥹓; [V3, V6]; xn----qml1407i.xn--x50zy803a; ; ; # -᮫︒.
+xn----qmlv7tw180a.xn--x50zy803a; -᮫︒‍.񒶈񥹓; [C2, V3, V6]; xn----qmlv7tw180a.xn--x50zy803a; ; ; # -᮫︒.
+󠦮.≯𞀆; ; [P1, V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+󠦮.≯𞀆; 󠦮.≯𞀆; [P1, V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+xn--t546e.xn--hdh5166o; 󠦮.≯𞀆; [V6]; xn--t546e.xn--hdh5166o; ; ; # .≯𞀆
+-𑄳󠊗𐹩。𞮱; -𑄳󠊗𐹩.𞮱; [B1, P1, V3, V6]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩.
+xn----p26i72em2894c.xn--zw6h; -𑄳󠊗𐹩.𞮱; [B1, V3, V6]; xn----p26i72em2894c.xn--zw6h; ; ; # -𑄳𐹩.
+ڹ.ᡳᅟ; ڹ.ᡳᅟ; [P1, V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+ڹ.ᡳᅟ; ; [P1, V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+xn--skb.xn--osd737a; ڹ.ᡳᅟ; [V6]; xn--skb.xn--osd737a; ; ; # ڹ.ᡳ
+㨛𘱎.︒𝟕ഁ; 㨛𘱎.︒7ഁ; [P1, V6]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ
+㨛𘱎.。7ഁ; 㨛𘱎..7ഁ; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ
+xn--mbm8237g..xn--7-7hf; 㨛𘱎..7ഁ; [X4_2]; xn--mbm8237g..xn--7-7hf; [A4_2]; ; # 㨛𘱎..7ഁ
+xn--mbm8237g.xn--7-7hf1526p; 㨛𘱎.︒7ഁ; [V6]; xn--mbm8237g.xn--7-7hf1526p; ; ; # 㨛𘱎.︒7ഁ
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤣≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+xn----dxc06304e.xn--gdh5020pk5c; ۝𻱧-.𞷁𞤣≮; [B1, B3, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+۝𻱧-。𞷁⁤𞤁≮; ۝𻱧-.𞷁𞤣≮; [B1, B3, P1, V3, V6]; xn----dxc06304e.xn--gdh5020pk5c; ; ; # -.𞤣≮
+ß‌꫶ᢥ.⊶ჁႶ; ß‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--zca682johfi89m.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ჁႶ; ; [C1, P1, V6]; xn--zca682johfi89m.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ⴡⴖ; ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ
+SS‌꫶ᢥ.⊶ჁႶ; ss‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ss꫶ᢥ.⊶ჁႶ
+ss‌꫶ᢥ.⊶ⴡⴖ; ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ
+Ss‌꫶ᢥ.⊶Ⴡⴖ; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; xn--ss-4epx629f.xn--5nd703gyrh; [P1, V6] # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--5nd703gyrh; ss꫶ᢥ.⊶Ⴡⴖ; [V6]; xn--ss-4epx629f.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4ep585bkm5p.xn--5nd703gyrh; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--ifh802b6a; ss꫶ᢥ.⊶ⴡⴖ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+ss꫶ᢥ.⊶ⴡⴖ; ; ; xn--ss-4epx629f.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+SS꫶ᢥ.⊶ჁႶ; ss꫶ᢥ.⊶ჁႶ; [P1, V6]; xn--ss-4epx629f.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+Ss꫶ᢥ.⊶Ⴡⴖ; ss꫶ᢥ.⊶Ⴡⴖ; [P1, V6]; xn--ss-4epx629f.xn--5nd703gyrh; ; ; # ss꫶ᢥ.⊶Ⴡⴖ
+xn--ss-4epx629f.xn--undv409k; ss꫶ᢥ.⊶ჁႶ; [V6]; xn--ss-4epx629f.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+xn--ss-4ep585bkm5p.xn--ifh802b6a; ss‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; ; # ss꫶ᢥ.⊶ⴡⴖ
+xn--ss-4ep585bkm5p.xn--undv409k; ss‌꫶ᢥ.⊶ჁႶ; [C1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; ; # ss꫶ᢥ.⊶ჁႶ
+xn--zca682johfi89m.xn--ifh802b6a; ß‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; ; # ß꫶ᢥ.⊶ⴡⴖ
+xn--zca682johfi89m.xn--undv409k; ß‌꫶ᢥ.⊶ჁႶ; [C1, V6]; xn--zca682johfi89m.xn--undv409k; ; ; # ß꫶ᢥ.⊶ჁႶ
+ß‌꫶ᢥ.⊶ⴡⴖ; ß‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--zca682johfi89m.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ß꫶ᢥ.⊶ⴡⴖ
+SS‌꫶ᢥ.⊶ჁႶ; ss‌꫶ᢥ.⊶ჁႶ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--undv409k; ; xn--ss-4epx629f.xn--undv409k; [P1, V6] # ss꫶ᢥ.⊶ჁႶ
+ss‌꫶ᢥ.⊶ⴡⴖ; ss‌꫶ᢥ.⊶ⴡⴖ; [C1]; xn--ss-4ep585bkm5p.xn--ifh802b6a; ; xn--ss-4epx629f.xn--ifh802b6a; [] # ss꫶ᢥ.⊶ⴡⴖ
+Ss‌꫶ᢥ.⊶Ⴡⴖ; ss‌꫶ᢥ.⊶Ⴡⴖ; [C1, P1, V6]; xn--ss-4ep585bkm5p.xn--5nd703gyrh; ; xn--ss-4epx629f.xn--5nd703gyrh; [P1, V6] # ss꫶ᢥ.⊶Ⴡⴖ
+‍。ς󠁉; ‍.ς󠁉; [C2, P1, V6]; xn--1ug.xn--3xa44344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .ς
+‍。Σ󠁉; ‍.σ󠁉; [C2, P1, V6]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .σ
+‍。σ󠁉; ‍.σ󠁉; [C2, P1, V6]; xn--1ug.xn--4xa24344p; ; .xn--4xa24344p; [P1, V6, A4_2] # .σ
+.xn--4xa24344p; .σ󠁉; [V6, X4_2]; .xn--4xa24344p; [V6, A4_2]; ; # .σ
+xn--1ug.xn--4xa24344p; ‍.σ󠁉; [C2, V6]; xn--1ug.xn--4xa24344p; ; ; # .σ
+xn--1ug.xn--3xa44344p; ‍.ς󠁉; [C2, V6]; xn--1ug.xn--3xa44344p; ; ; # .ς
+𞵑ß.ݑ‍𞤛-; 𞵑ß.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ß.ݑ𞤽-
+𞵑ß.ݑ‍𞤽-; ; [B2, B3, C2, P1, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ß.ݑ𞤽-
+𞵑SS.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑ss.ݑ‍𞤽-; ; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑Ss.ݑ‍𞤽-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+xn--ss-2722a.xn----z3c03218a; 𞵑ss.ݑ𞤽-; [B2, B3, V3, V6]; xn--ss-2722a.xn----z3c03218a; ; ; # ss.ݑ𞤽-
+xn--ss-2722a.xn----z3c011q9513b; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; ; # ss.ݑ𞤽-
+xn--zca5423w.xn----z3c011q9513b; 𞵑ß.ݑ‍𞤽-; [B2, B3, C2, V3, V6]; xn--zca5423w.xn----z3c011q9513b; ; ; # ß.ݑ𞤽-
+𞵑ss.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𞵑Ss.ݑ‍𞤛-; 𞵑ss.ݑ‍𞤽-; [B2, B3, C2, P1, V3, V6]; xn--ss-2722a.xn----z3c011q9513b; ; xn--ss-2722a.xn----z3c03218a; [B2, B3, P1, V3, V6] # ss.ݑ𞤽-
+𑘽‍𞤧.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+𑘽‍𞤧.𐹧󡦪-; ; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+𑘽‍𞤅.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+xn--qb2ds317a.xn----k26iq1483f; 𑘽𞤧.𐹧󡦪-; [B1, V3, V5, V6]; xn--qb2ds317a.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧-
+xn--1ugz808gdimf.xn----k26iq1483f; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; ; # 𑘽𞤧.𐹧-
+𑘽‍𞤅.𐹧󡦪-; 𑘽‍𞤧.𐹧󡦪-; [B1, C2, P1, V3, V5, V6]; xn--1ugz808gdimf.xn----k26iq1483f; ; xn--qb2ds317a.xn----k26iq1483f; [B1, P1, V3, V5, V6] # 𑘽𞤧.𐹧-
+⒒򨘙򳳠𑓀.-󞡊; ; [P1, V3, V6]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.-
+11.򨘙򳳠𑓀.-󞡊; ; [P1, V3, V6]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.-
+11.xn--uz1d59632bxujd.xn----x310m; 11.򨘙򳳠𑓀.-󞡊; [V3, V6]; 11.xn--uz1d59632bxujd.xn----x310m; ; ; # 11.𑓀.-
+xn--3shy698frsu9dt1me.xn----x310m; ⒒򨘙򳳠𑓀.-󞡊; [V3, V6]; xn--3shy698frsu9dt1me.xn----x310m; ; ; # ⒒𑓀.-
+-。‍; -.‍; [C2, V3]; -.xn--1ug; ; -.; [V3] # -.
+-。‍; -.‍; [C2, V3]; -.xn--1ug; ; -.; [V3] # -.
+-.; ; [V3]; ; ; ; # -.
+-.xn--1ug; -.‍; [C2, V3]; -.xn--1ug; ; ; # -.
+≮ᡬ.ς¹-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς¹-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς1-?; ; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+≮ᡬ.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ1-?; ; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.xn--1-?-pzc; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.xn--1-?-lzc; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; ; # ≮ᡬ.ς1-?
+≮ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.Σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+≮ᡬ.σ¹-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+XN--88E732C.Σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+Xn--88e732c.ς1-?; ≮ᡬ.ς1-?; [P1, V6]; xn--88e732c.xn--1-?-lzc; ; xn--88e732c.xn--1-?-pzc; # ≮ᡬ.ς1-?
+Xn--88e732c.σ1-?; ≮ᡬ.σ1-?; [P1, V6]; xn--88e732c.xn--1-?-pzc; ; ; # ≮ᡬ.σ1-?
+ቬ򔠼񁗶。𐨬𝟠; ቬ򔠼񁗶.𐨬8; [P1, V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+ቬ򔠼񁗶。𐨬8; ቬ򔠼񁗶.𐨬8; [P1, V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+xn--d0d41273c887z.xn--8-ob5i; ቬ򔠼񁗶.𐨬8; [V6]; xn--d0d41273c887z.xn--8-ob5i; ; ; # ቬ.𐨬8
+𐱲。蔫ݦ; 𐱲.蔫ݦ; [B5, B6, P1, V6]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ
+xn--389c.xn--qpb7055d; 𐱲.蔫ݦ; [B5, B6, V6]; xn--389c.xn--qpb7055d; ; ; # .蔫ݦ
+򒲧₃。ꡚ𛇑󠄳ه; 򒲧3.ꡚ𛇑ه; [B5, B6, P1, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+򒲧3。ꡚ𛇑󠄳ه; 򒲧3.ꡚ𛇑ه; [B5, B6, P1, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+xn--3-ep59g.xn--jhb5904fcp0h; 򒲧3.ꡚ𛇑ه; [B5, B6, V6]; xn--3-ep59g.xn--jhb5904fcp0h; ; ; # 3.ꡚ𛇑ه
+蓸ق≠.ß; ; [B5, B6, P1, V6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß
+蓸ق≠.ß; 蓸ق≠.ß; [B5, B6, P1, V6]; xn--ehb015lnt1e.xn--zca; ; xn--ehb015lnt1e.ss; # 蓸ق≠.ß
+蓸ق≠.SS; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.SS; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.ss; ; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.Ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+蓸ق≠.Ss; 蓸ق≠.ss; [B5, B6, P1, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+xn--ehb015lnt1e.ss; 蓸ق≠.ss; [B5, B6, V6]; xn--ehb015lnt1e.ss; ; ; # 蓸ق≠.ss
+xn--ehb015lnt1e.xn--zca; 蓸ق≠.ß; [B5, B6, V6]; xn--ehb015lnt1e.xn--zca; ; ; # 蓸ق≠.ß
+ࡎٺී⒊.𐹹𞱩󠃪‌; ; [B1, C1, P1, V6]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; xn--zib94gfziuq1a.xn--xo0dw109an237f; [B1, P1, V6] # ࡎٺී⒊.𐹹
+ࡎٺී3..𐹹𞱩󠃪‌; ; [B1, C1, P1, V6, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, P1, V6, A4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, P1, V6, A4_2] # ࡎٺී3..𐹹
+xn--3-prc71ls9j..xn--xo0dw109an237f; ࡎٺී3..𐹹𞱩󠃪; [B1, V6, X4_2]; xn--3-prc71ls9j..xn--xo0dw109an237f; [B1, V6, A4_2]; ; # ࡎٺී3..𐹹
+xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; ࡎٺී3..𐹹𞱩󠃪‌; [B1, C1, V6, X4_2]; xn--3-prc71ls9j..xn--0ug3205g7eyf3c96h; [B1, C1, V6, A4_2]; ; # ࡎٺී3..𐹹
+xn--zib94gfziuq1a.xn--xo0dw109an237f; ࡎٺී⒊.𐹹𞱩󠃪; [B1, V6]; xn--zib94gfziuq1a.xn--xo0dw109an237f; ; ; # ࡎٺී⒊.𐹹
+xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ࡎٺී⒊.𐹹𞱩󠃪‌; [B1, C1, V6]; xn--zib94gfziuq1a.xn--0ug3205g7eyf3c96h; ; ; # ࡎٺී⒊.𐹹
+ς‍-.Ⴣ𦟙; ; [C2, P1, V3, V6]; xn----xmb348s.xn--7nd64871a; ; xn----zmb.xn--7nd64871a; [P1, V3, V6] # ς-.Ⴣ𦟙
+ς‍-.ⴣ𦟙; ; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # ς-.ⴣ𦟙
+Σ‍-.Ⴣ𦟙; σ‍-.Ⴣ𦟙; [C2, P1, V3, V6]; xn----zmb048s.xn--7nd64871a; ; xn----zmb.xn--7nd64871a; [P1, V3, V6] # σ-.Ⴣ𦟙
+σ‍-.ⴣ𦟙; ; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; xn----zmb.xn--rlj2573p; [V3] # σ-.ⴣ𦟙
+xn----zmb.xn--rlj2573p; σ-.ⴣ𦟙; [V3]; xn----zmb.xn--rlj2573p; ; ; # σ-.ⴣ𦟙
+xn----zmb048s.xn--rlj2573p; σ‍-.ⴣ𦟙; [C2, V3]; xn----zmb048s.xn--rlj2573p; ; ; # σ-.ⴣ𦟙
+xn----zmb.xn--7nd64871a; σ-.Ⴣ𦟙; [V3, V6]; xn----zmb.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙
+xn----zmb048s.xn--7nd64871a; σ‍-.Ⴣ𦟙; [C2, V3, V6]; xn----zmb048s.xn--7nd64871a; ; ; # σ-.Ⴣ𦟙
+xn----xmb348s.xn--rlj2573p; ς‍-.ⴣ𦟙; [C2, V3]; xn----xmb348s.xn--rlj2573p; ; ; # ς-.ⴣ𦟙
+xn----xmb348s.xn--7nd64871a; ς‍-.Ⴣ𦟙; [C2, V3, V6]; xn----xmb348s.xn--7nd64871a; ; ; # ς-.Ⴣ𦟙
+≠。🞳𝟲; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳𝟲; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳6; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+≠。🞳6; ≠.🞳6; [P1, V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+xn--1ch.xn--6-dl4s; ≠.🞳6; [V6]; xn--1ch.xn--6-dl4s; ; ; # ≠.🞳6
+󅬽.蠔; ; [P1, V6]; xn--g747d.xn--xl2a; ; ; # .蠔
+xn--g747d.xn--xl2a; 󅬽.蠔; [V6]; xn--g747d.xn--xl2a; ; ; # .蠔
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+ࣦ‍.뼽; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; xn--p0b.xn--e43b; [V5] # ࣦ.뼽
+xn--p0b.xn--e43b; ࣦ.뼽; [V5]; xn--p0b.xn--e43b; ; ; # ࣦ.뼽
+xn--p0b869i.xn--e43b; ࣦ‍.뼽; [C2, V5]; xn--p0b869i.xn--e43b; ; ; # ࣦ.뼽
+₇்􃂷ے。👖ٵ-𞪑; 7்􃂷ے.👖اٴ-𞪑; [B1, P1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+7்􃂷ے。👖اٴ-𞪑; 7்􃂷ے.👖اٴ-𞪑; [B1, P1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+xn--7-rwc839aj3073c.xn----ymc5uv818oghka; 7்􃂷ے.👖اٴ-𞪑; [B1, V6]; xn--7-rwc839aj3073c.xn----ymc5uv818oghka; ; ; # 7்ے.👖اٴ-
+-。ݻ; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+-。ݻ; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+-.xn--cqb; -.ݻ; [B1, V3]; -.xn--cqb; ; ; # -.ݻ
+𑇌𵛓。-⒈ꡏܫ; 𑇌𵛓.-⒈ꡏܫ; [B1, P1, V3, V5, V6]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ
+𑇌𵛓。-1.ꡏܫ; 𑇌𵛓.-1.ꡏܫ; [B1, B5, B6, P1, V3, V5, V6]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ
+xn--8d1dg030h.-1.xn--1nb7163f; 𑇌𵛓.-1.ꡏܫ; [B1, B5, B6, V3, V5, V6]; xn--8d1dg030h.-1.xn--1nb7163f; ; ; # 𑇌.-1.ꡏܫ
+xn--8d1dg030h.xn----u1c466tp10j; 𑇌𵛓.-⒈ꡏܫ; [B1, V3, V5, V6]; xn--8d1dg030h.xn----u1c466tp10j; ; ; # 𑇌.-⒈ꡏܫ
+璛᜴گ.-; ; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.-
+xn--ikb175frt4e.-; 璛᜴گ.-; [B1, B5, B6, V3]; xn--ikb175frt4e.-; ; ; # 璛᜴گ.-
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+󠆰ࢡ੍샕.𐹲휁; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+xn--qyb07fj857a.xn--728bv72h; ࢡ੍샕.𐹲휁; [B1, B2, B3]; xn--qyb07fj857a.xn--728bv72h; ; ; # ࢡ੍샕.𐹲휁
+񍨽.񋸕; 񍨽.񋸕; [P1, V6]; xn--pr3x.xn--rv7w; ; ; # .
+񍨽.񋸕; ; [P1, V6]; xn--pr3x.xn--rv7w; ; ; # .
+xn--pr3x.xn--rv7w; 񍨽.񋸕; [V6]; xn--pr3x.xn--rv7w; ; ; # .
+ٽ𞥕。𑑂𞤶Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+ٽ𞥕。𑑂𞤔Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤔ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+xn--2ib0338v.xn----zvs0199fo91g; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+xn--2ib0338v.xn----w0g2740ro9vg; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤶ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+ٽ𞥕。𑑂𞤔Ⴍ-; ٽ𞥕.𑑂𞤶Ⴍ-; [B1, P1, V3, V5, V6]; xn--2ib0338v.xn----w0g2740ro9vg; ; ; # ٽ𞥕.𑑂𞤶Ⴍ-
+ٽ𞥕。𑑂𞤔ⴍ-; ٽ𞥕.𑑂𞤶ⴍ-; [B1, V3, V5]; xn--2ib0338v.xn----zvs0199fo91g; ; ; # ٽ𞥕.𑑂𞤶ⴍ-
+𐯀𐸉𞧏。񢚧₄Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧4Ⴋ񂹫; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧4ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+xn--039c42bq865a.xn--4-wvs27840bnrzm; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+xn--039c42bq865a.xn--4-t0g49302fnrzm; 𐯀𐸉𞧏.񢚧4Ⴋ񂹫; [V6]; xn--039c42bq865a.xn--4-t0g49302fnrzm; ; ; # .4Ⴋ
+𐯀𐸉𞧏。񢚧₄ⴋ񂹫; 𐯀𐸉𞧏.񢚧4ⴋ񂹫; [P1, V6]; xn--039c42bq865a.xn--4-wvs27840bnrzm; ; ; # .4ⴋ
+4ڽ︒󠑥.≠; ; [B1, P1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+4ڽ︒󠑥.≠; 4ڽ︒󠑥.≠; [B1, P1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+4ڽ。󠑥.≠; 4ڽ.󠑥.≠; [B1, P1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+4ڽ。󠑥.≠; 4ڽ.󠑥.≠; [B1, P1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+xn--4-kvc.xn--5136e.xn--1ch; 4ڽ.󠑥.≠; [B1, V6]; xn--4-kvc.xn--5136e.xn--1ch; ; ; # 4ڽ..≠
+xn--4-kvc5601q2h50i.xn--1ch; 4ڽ︒󠑥.≠; [B1, V6]; xn--4-kvc5601q2h50i.xn--1ch; ; ; # 4ڽ︒.≠
+𝟓。ۗ; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+5。ۗ; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+5.xn--nlb; 5.ۗ; [V5]; 5.xn--nlb; ; ; # 5.ۗ
+‌򺸩.⾕; ‌򺸩.谷; [C1, P1, V6]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [P1, V6] # .谷
+‌򺸩.谷; ; [C1, P1, V6]; xn--0ug26167i.xn--6g3a; ; xn--i183d.xn--6g3a; [P1, V6] # .谷
+xn--i183d.xn--6g3a; 򺸩.谷; [V6]; xn--i183d.xn--6g3a; ; ; # .谷
+xn--0ug26167i.xn--6g3a; ‌򺸩.谷; [C1, V6]; xn--0ug26167i.xn--6g3a; ; ; # .谷
+︒󎰇‍.-ܼ‌; ; [C1, C2, P1, V3, V6]; xn--1ug1658ftw26f.xn----t2c071q; ; xn--y86c71305c.xn----t2c; [P1, V3, V6] # ︒.-ܼ
+。󎰇‍.-ܼ‌; .󎰇‍.-ܼ‌; [C1, C2, P1, V3, V6, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, P1, V3, V6, A4_2]; .xn--hh50e.xn----t2c; [P1, V3, V6, A4_2] # ..-ܼ
+.xn--hh50e.xn----t2c; .󎰇.-ܼ; [V3, V6, X4_2]; .xn--hh50e.xn----t2c; [V3, V6, A4_2]; ; # ..-ܼ
+.xn--1ug05310k.xn----t2c071q; .󎰇‍.-ܼ‌; [C1, C2, V3, V6, X4_2]; .xn--1ug05310k.xn----t2c071q; [C1, C2, V3, V6, A4_2]; ; # ..-ܼ
+xn--y86c71305c.xn----t2c; ︒󎰇.-ܼ; [V3, V6]; xn--y86c71305c.xn----t2c; ; ; # ︒.-ܼ
+xn--1ug1658ftw26f.xn----t2c071q; ︒󎰇‍.-ܼ‌; [C1, C2, V3, V6]; xn--1ug1658ftw26f.xn----t2c071q; ; ; # ︒.-ܼ
+≯𞤟。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞤟。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞥁。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+≯𞥁。ᡨ; ≯𞥁.ᡨ; [B1, P1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+xn--hdhz520p.xn--48e; ≯𞥁.ᡨ; [B1, V6]; xn--hdhz520p.xn--48e; ; ; # ≯𞥁.ᡨ
+ུ𫫰𝨄。ܓ𐹦; ུ𫫰𝨄.ܓ𐹦; [B1, V5]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦
+xn--ned8985uo92e.xn--dnb6395k; ུ𫫰𝨄.ܓ𐹦; [B1, V5]; xn--ned8985uo92e.xn--dnb6395k; ; ; # ུ𫫰𝨄.ܓ𐹦
+̼ߛ⁷𝟹。𝟬; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+̼ߛ73。0; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+xn--73-9yb648b.0; ̼ߛ73.0; [B1, V5]; xn--73-9yb648b.0; ; ; # ̼ߛ73.0
+‍.𝟗; ‍.9; [C2]; xn--1ug.9; ; .9; [A4_2] # .9
+‍.9; ; [C2]; xn--1ug.9; ; .9; [A4_2] # .9
+.9; ; [X4_2]; ; [A4_2]; ; # .9
+xn--1ug.9; ‍.9; [C2]; xn--1ug.9; ; ; # .9
+9; ; ; ; ; ; # 9
+ݹᡭ𪕈。ڶࣙ; ݹᡭ𪕈.ڶࣙ; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ
+xn--9pb497fs270c.xn--pkb80i; ݹᡭ𪕈.ڶࣙ; [B2, B3]; xn--9pb497fs270c.xn--pkb80i; ; ; # ݹᡭ𪕈.ڶࣙ
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+ܦ5ߢ겙。᳴𐷚; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, P1, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+xn--5-j1c97c2483c.xn--e7f2093h; ܦ5ߢ겙.᳴𐷚; [B1, B2, B3, V5, V6]; xn--5-j1c97c2483c.xn--e7f2093h; ; ; # ܦ5ߢ겙.᳴
+Ⴍ𿣍ꡨ֮。Ⴞ‌‌; Ⴍ𿣍ꡨ֮.Ⴞ‌‌; [C1, P1, V6]; xn--5cb347co96jug15a.xn--2nd059ea; ; xn--5cb347co96jug15a.xn--2nd; [P1, V6] # Ⴍꡨ֮.Ⴞ
+ⴍ𿣍ꡨ֮。ⴞ‌‌; ⴍ𿣍ꡨ֮.ⴞ‌‌; [C1, P1, V6]; xn--5cb172r175fug38a.xn--0uga051h; ; xn--5cb172r175fug38a.xn--mlj; [P1, V6] # ⴍꡨ֮.ⴞ
+xn--5cb172r175fug38a.xn--mlj; ⴍ𿣍ꡨ֮.ⴞ; [V6]; xn--5cb172r175fug38a.xn--mlj; ; ; # ⴍꡨ֮.ⴞ
+xn--5cb172r175fug38a.xn--0uga051h; ⴍ𿣍ꡨ֮.ⴞ‌‌; [C1, V6]; xn--5cb172r175fug38a.xn--0uga051h; ; ; # ⴍꡨ֮.ⴞ
+xn--5cb347co96jug15a.xn--2nd; Ⴍ𿣍ꡨ֮.Ⴞ; [V6]; xn--5cb347co96jug15a.xn--2nd; ; ; # Ⴍꡨ֮.Ⴞ
+xn--5cb347co96jug15a.xn--2nd059ea; Ⴍ𿣍ꡨ֮.Ⴞ‌‌; [C1, V6]; xn--5cb347co96jug15a.xn--2nd059ea; ; ; # Ⴍꡨ֮.Ⴞ
+𐋰。󑓱; 𐋰.󑓱; [P1, V6]; xn--k97c.xn--q031e; ; ; # 𐋰.
+xn--k97c.xn--q031e; 𐋰.󑓱; [V6]; xn--k97c.xn--q031e; ; ; # 𐋰.
+󡎦឴୍.𐹾; ; [B1, P1, V6]; xn--9ic364dho91z.xn--2o0d; ; ; # ୍.𐹾
+xn--9ic364dho91z.xn--2o0d; 󡎦឴୍.𐹾; [B1, V6]; xn--9ic364dho91z.xn--2o0d; ; ; # ୍.𐹾
+ࣟႫ𶿸귤.򠅼𝟢휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼𝟢휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼0휪ૣ; ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟႫ𶿸귤.򠅼0휪ૣ; ࣟႫ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼0휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼0휪ૣ; ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ࣟⴋ𶿸귤.򠅼0휪ૣ; [V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ࣟႫ𶿸귤.򠅼0휪ૣ; [V5, V6]; xn--i0b601b6r7l2hs0a.xn--0-8le8997mulr5f; ; ; # ࣟႫ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼𝟢휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ࣟⴋ𶿸귤.򠅼𝟢휪ૣ; ࣟⴋ𶿸귤.򠅼0휪ૣ; [P1, V5, V6]; xn--i0b436pkl2g2h42a.xn--0-8le8997mulr5f; ; ; # ࣟⴋ귤.0휪ૣ
+ބ.𞡝؁; ބ.𞡝؁; [P1, V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+ބ.𞡝؁; ; [P1, V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+xn--lqb.xn--jfb1808v; ބ.𞡝؁; [V6]; xn--lqb.xn--jfb1808v; ; ; # ބ.𞡝
+્₃.8꣄‍🃤; ્3.8꣄‍🃤; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤
+્3.8꣄‍🃤; ; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; xn--3-yke.xn--8-sl4et308f; # ્3.8꣄🃤
+xn--3-yke.xn--8-sl4et308f; ્3.8꣄🃤; [V5]; xn--3-yke.xn--8-sl4et308f; ; ; # ્3.8꣄🃤
+xn--3-yke.xn--8-ugnv982dbkwm; ્3.8꣄‍🃤; [V5]; xn--3-yke.xn--8-ugnv982dbkwm; ; ; # ્3.8꣄🃤
+℻⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+xn--fax-4c9a1676t.xn--6e6h; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+℻⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆。𞥂󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆。𞤠󠆁᠌; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+fax⩷𝆆.𞥂; ; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆.𞤠; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+FAX⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+Fax⩷𝆆.𞥂; fax⩷𝆆.𞥂; [B6]; xn--fax-4c9a1676t.xn--6e6h; ; ; # fax⩷𝆆.𞥂
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+ꡕ≠ၞ󮿱。𐵧󠄫ᅠ; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, P1, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+xn--cld333gn31h0158l.xn--psd1510k; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, V6]; xn--cld333gn31h0158l.xn--psd1510k; ; ; # ꡕ≠ၞ.
+xn--cld333gn31h0158l.xn--cl7c96v; ꡕ≠ၞ󮿱.𐵧ᅠ; [B2, B3, V6]; xn--cld333gn31h0158l.xn--cl7c96v; ; ; # ꡕ≠ၞ.
+鱊。‌; 鱊.‌; [C1]; xn--rt6a.xn--0ug; ; xn--rt6a.; [] # 鱊.
+xn--rt6a.; 鱊.; ; xn--rt6a.; ; ; # 鱊.
+鱊.; ; ; xn--rt6a.; ; ; # 鱊.
+xn--rt6a.xn--0ug; 鱊.‌; [C1]; xn--rt6a.xn--0ug; ; ; # 鱊.
+8𐹣.𑍨; 8𐹣.𑍨; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+8𐹣.𑍨; ; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+xn--8-d26i.xn--0p1d; 8𐹣.𑍨; [B1, B3, B6, V5]; xn--8-d26i.xn--0p1d; ; ; # 8𐹣.𑍨
+⏹𐧀.𐫯; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+⏹𐧀.𐫯; ; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+xn--qoh9161g.xn--1x9c; ⏹𐧀.𐫯; [B1]; xn--qoh9161g.xn--1x9c; ; ; # ⏹𐧀.𐫯
+𞤺ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+𞤺ߌ4.‍; ; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+𞤘ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+xn--4-0bd15808a.; 𞤺ߌ4.; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+𞤺ߌ4.; ; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+𞤘ߌ4.; 𞤺ߌ4.; ; xn--4-0bd15808a.; ; ; # 𞤺ߌ4.
+xn--4-0bd15808a.xn--1ug; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; ; # 𞤺ߌ4.
+𞤘ߌ4.‍; 𞤺ߌ4.‍; [B1, C2]; xn--4-0bd15808a.xn--1ug; ; xn--4-0bd15808a.; [] # 𞤺ߌ4.
+⒗ঁ⃯-.࣢•; ; [B1, P1, V3, V6]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.•
+16.ঁ⃯-.࣢•; ; [B1, P1, V3, V5, V6]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.•
+16.xn----z0d801p.xn--l0b810j; 16.ঁ⃯-.࣢•; [B1, V3, V5, V6]; 16.xn----z0d801p.xn--l0b810j; ; ; # 16.ঁ⃯-.•
+xn----z0d801p6kd.xn--l0b810j; ⒗ঁ⃯-.࣢•; [B1, V3, V6]; xn----z0d801p6kd.xn--l0b810j; ; ; # ⒗ঁ⃯-.•
+-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+-。䏛; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+-.xn--xco; -.䏛; [V3]; -.xn--xco; ; ; # -.䏛
+‌񒃠.‍; ‌񒃠.‍; [C1, C2, P1, V6]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [P1, V6] # .
+‌񒃠.‍; ; [C1, C2, P1, V6]; xn--0ugz7551c.xn--1ug; ; xn--dj8y.; [P1, V6] # .
+xn--dj8y.; 񒃠.; [V6]; xn--dj8y.; ; ; # .
+xn--0ugz7551c.xn--1ug; ‌񒃠.‍; [C1, C2, V6]; xn--0ugz7551c.xn--1ug; ; ; # .
+⒈⓰󥣇。𐹠‍򗷦Ⴕ; ⒈⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, P1, V6]; xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ; xn--tsh0nz9380h.xn--tnd1990ke579c; [B1, P1, V6] # ⒈⓰.𐹠Ⴕ
+1.⓰󥣇。𐹠‍򗷦Ⴕ; 1.⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, P1, V6]; 1.xn--svh00804k.xn--tnd969erj4psgl3e; ; 1.xn--svh00804k.xn--tnd1990ke579c; [B1, P1, V6] # 1.⓰.𐹠Ⴕ
+1.⓰󥣇。𐹠‍򗷦ⴕ; 1.⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, P1, V6]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; 1.xn--svh00804k.xn--dljv223ee5t2d; [B1, P1, V6] # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--dljv223ee5t2d; 1.⓰󥣇.𐹠򗷦ⴕ; [B1, V6]; 1.xn--svh00804k.xn--dljv223ee5t2d; ; ; # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--1ug352csp0psg45e; 1.⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, V6]; 1.xn--svh00804k.xn--1ug352csp0psg45e; ; ; # 1.⓰.𐹠ⴕ
+1.xn--svh00804k.xn--tnd1990ke579c; 1.⓰󥣇.𐹠򗷦Ⴕ; [B1, V6]; 1.xn--svh00804k.xn--tnd1990ke579c; ; ; # 1.⓰.𐹠Ⴕ
+1.xn--svh00804k.xn--tnd969erj4psgl3e; 1.⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, V6]; 1.xn--svh00804k.xn--tnd969erj4psgl3e; ; ; # 1.⓰.𐹠Ⴕ
+⒈⓰󥣇。𐹠‍򗷦ⴕ; ⒈⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, P1, V6]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; xn--tsh0nz9380h.xn--dljv223ee5t2d; [B1, P1, V6] # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--dljv223ee5t2d; ⒈⓰󥣇.𐹠򗷦ⴕ; [B1, V6]; xn--tsh0nz9380h.xn--dljv223ee5t2d; ; ; # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--1ug352csp0psg45e; ⒈⓰󥣇.𐹠‍򗷦ⴕ; [B1, C2, V6]; xn--tsh0nz9380h.xn--1ug352csp0psg45e; ; ; # ⒈⓰.𐹠ⴕ
+xn--tsh0nz9380h.xn--tnd1990ke579c; ⒈⓰󥣇.𐹠򗷦Ⴕ; [B1, V6]; xn--tsh0nz9380h.xn--tnd1990ke579c; ; ; # ⒈⓰.𐹠Ⴕ
+xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ⒈⓰󥣇.𐹠‍򗷦Ⴕ; [B1, C2, V6]; xn--tsh0nz9380h.xn--tnd969erj4psgl3e; ; ; # ⒈⓰.𐹠Ⴕ
+𞠊ᠮ-ß。᳐効؁𷣭; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-ß。᳐効؁𷣭; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; xn---ss-21t18904a.xn--jfb197i791bi6x4c; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-SS。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-Ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+xn---ss-21t18904a.xn--jfb197i791bi6x4c; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+xn----qfa310pg973b.xn--jfb197i791bi6x4c; 𞠊ᠮ-ß.᳐効؁𷣭; [B1, B2, B3, V5, V6]; xn----qfa310pg973b.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ß.᳐効
+𞠊ᠮ-SS。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𞠊ᠮ-Ss。᳐効؁𷣭; 𞠊ᠮ-ss.᳐効؁𷣭; [B1, B2, B3, P1, V5, V6]; xn---ss-21t18904a.xn--jfb197i791bi6x4c; ; ; # 𞠊ᠮ-ss.᳐効
+𑇀.󠨱; ; [P1, V5, V6]; xn--wd1d.xn--k946e; ; ; # 𑇀.
+xn--wd1d.xn--k946e; 𑇀.󠨱; [V5, V6]; xn--wd1d.xn--k946e; ; ; # 𑇀.
+␒3ﮈ。𝟘𐨿𐹆; ␒3ڈ.0𐨿𐹆; [B1, P1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+␒3ڈ。0𐨿𐹆; ␒3ڈ.0𐨿𐹆; [B1, P1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+xn--3-jsc897t.xn--0-sc5iy3h; ␒3ڈ.0𐨿𐹆; [B1, V6]; xn--3-jsc897t.xn--0-sc5iy3h; ; ; # ␒3ڈ.0𐨿
+ݫ6ઁࢦ。ᷣ; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+ݫ6ઁࢦ。ᷣ; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+xn--6-h5c06gj6c.xn--7eg; ݫ6ઁࢦ.ᷣ; [B1, B3, B6, V5]; xn--6-h5c06gj6c.xn--7eg; ; ; # ݫ6ઁࢦ.ᷣ
+؅-𽤞Ⴂ。򅤶‍; ؅-𽤞Ⴂ.򅤶‍; [B1, B6, C2, P1, V6]; xn----0kc662fc152h.xn--1ugy3204f; ; xn----0kc662fc152h.xn--ss06b; [B1, P1, V6] # -Ⴂ.
+؅-𽤞ⴂ。򅤶‍; ؅-𽤞ⴂ.򅤶‍; [B1, B6, C2, P1, V6]; xn----0kc8501a5399e.xn--1ugy3204f; ; xn----0kc8501a5399e.xn--ss06b; [B1, P1, V6] # -ⴂ.
+xn----0kc8501a5399e.xn--ss06b; ؅-𽤞ⴂ.򅤶; [B1, V6]; xn----0kc8501a5399e.xn--ss06b; ; ; # -ⴂ.
+xn----0kc8501a5399e.xn--1ugy3204f; ؅-𽤞ⴂ.򅤶‍; [B1, B6, C2, V6]; xn----0kc8501a5399e.xn--1ugy3204f; ; ; # -ⴂ.
+xn----0kc662fc152h.xn--ss06b; ؅-𽤞Ⴂ.򅤶; [B1, V6]; xn----0kc662fc152h.xn--ss06b; ; ; # -Ⴂ.
+xn----0kc662fc152h.xn--1ugy3204f; ؅-𽤞Ⴂ.򅤶‍; [B1, B6, C2, V6]; xn----0kc662fc152h.xn--1ugy3204f; ; ; # -Ⴂ.
+⾆.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+⾆.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯ß; ; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯ß; 舌.ꡈ5≯ß; [P1, V6]; xn--tc1a.xn--5-qfa988w745i; ; xn--tc1a.xn--5ss-3m2a5009e; # 舌.ꡈ5≯ß
+舌.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯ss; ; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+舌.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+xn--tc1a.xn--5ss-3m2a5009e; 舌.ꡈ5≯ss; [V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+xn--tc1a.xn--5-qfa988w745i; 舌.ꡈ5≯ß; [V6]; xn--tc1a.xn--5-qfa988w745i; ; ; # 舌.ꡈ5≯ß
+⾆.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯SS; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+⾆.ꡈ5≯Ss; 舌.ꡈ5≯ss; [P1, V6]; xn--tc1a.xn--5ss-3m2a5009e; ; ; # 舌.ꡈ5≯ss
+્8‍.򾂈ݜ; ્8‍.򾂈ݜ; [B1, B5, B6, C2, P1, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, P1, V5, V6] # ્8.ݜ
+્8‍.򾂈ݜ; ; [B1, B5, B6, C2, P1, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; xn--8-yke.xn--gpb79046m; [B1, B5, B6, P1, V5, V6] # ્8.ݜ
+xn--8-yke.xn--gpb79046m; ્8.򾂈ݜ; [B1, B5, B6, V5, V6]; xn--8-yke.xn--gpb79046m; ; ; # ્8.ݜ
+xn--8-yke534n.xn--gpb79046m; ્8‍.򾂈ݜ; [B1, B5, B6, C2, V5, V6]; xn--8-yke534n.xn--gpb79046m; ; ; # ્8.ݜ
+򸷆ੰ≮򹓙.񞎧⁷󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧⁷󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧7󠯙ڶ; ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+򸷆ੰ≮򹓙.񞎧7󠯙ڶ; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, P1, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; 򸷆ੰ≮򹓙.񞎧7󠯙ڶ; [B5, B6, V6]; xn--ycc893jqh38rb6fa.xn--7-5uc53836ixt41c; ; ; # ੰ≮.7ڶ
+𞤪.ς; ; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς
+𞤈.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤪.σ; ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤈.σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+xn--ie6h.xn--4xa; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+𞤈.ς; 𞤪.ς; ; xn--ie6h.xn--3xa; ; xn--ie6h.xn--4xa; # 𞤪.ς
+xn--ie6h.xn--3xa; 𞤪.ς; ; xn--ie6h.xn--3xa; ; ; # 𞤪.ς
+𞤪.Σ; 𞤪.σ; ; xn--ie6h.xn--4xa; ; ; # 𞤪.σ
+‌Ⴚ。ς; ‌Ⴚ.ς; [C1, P1, V6]; xn--ynd759e.xn--3xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.ς
+‌Ⴚ。ς; ‌Ⴚ.ς; [C1, P1, V6]; xn--ynd759e.xn--3xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.ς
+‌ⴚ。ς; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς
+‌Ⴚ。Σ; ‌Ⴚ.σ; [C1, P1, V6]; xn--ynd759e.xn--4xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.σ
+‌ⴚ。σ; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ
+xn--ilj.xn--4xa; ⴚ.σ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ
+ⴚ.σ; ; ; xn--ilj.xn--4xa; ; ; # ⴚ.σ
+Ⴚ.Σ; Ⴚ.σ; [P1, V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+ⴚ.ς; ; ; xn--ilj.xn--3xa; ; xn--ilj.xn--4xa; # ⴚ.ς
+Ⴚ.ς; ; [P1, V6]; xn--ynd.xn--3xa; ; xn--ynd.xn--4xa; # Ⴚ.ς
+xn--ynd.xn--4xa; Ⴚ.σ; [V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+xn--ynd.xn--3xa; Ⴚ.ς; [V6]; xn--ynd.xn--3xa; ; ; # Ⴚ.ς
+xn--ilj.xn--3xa; ⴚ.ς; ; xn--ilj.xn--3xa; ; ; # ⴚ.ς
+Ⴚ.σ; ; [P1, V6]; xn--ynd.xn--4xa; ; ; # Ⴚ.σ
+xn--0ug262c.xn--4xa; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; ; # ⴚ.σ
+xn--ynd759e.xn--4xa; ‌Ⴚ.σ; [C1, V6]; xn--ynd759e.xn--4xa; ; ; # Ⴚ.σ
+xn--0ug262c.xn--3xa; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; ; # ⴚ.ς
+xn--ynd759e.xn--3xa; ‌Ⴚ.ς; [C1, V6]; xn--ynd759e.xn--3xa; ; ; # Ⴚ.ς
+‌ⴚ。ς; ‌ⴚ.ς; [C1]; xn--0ug262c.xn--3xa; ; xn--ilj.xn--4xa; [] # ⴚ.ς
+‌Ⴚ。Σ; ‌Ⴚ.σ; [C1, P1, V6]; xn--ynd759e.xn--4xa; ; xn--ynd.xn--4xa; [P1, V6] # Ⴚ.σ
+‌ⴚ。σ; ‌ⴚ.σ; [C1]; xn--0ug262c.xn--4xa; ; xn--ilj.xn--4xa; [] # ⴚ.σ
+𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤃.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤥.𐹦; ; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+xn--de6h.xn--eo0d; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+𞤥.𐹦; 𞤥.𐹦; [B1]; xn--de6h.xn--eo0d; ; ; # 𞤥.𐹦
+‍⾕。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+‍⾕。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+‍谷。‌꥓̐ꡎ; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; xn--6g3a.xn--0sa8175flwa; [V5] # 谷.꥓̐ꡎ
+xn--6g3a.xn--0sa8175flwa; 谷.꥓̐ꡎ; [V5]; xn--6g3a.xn--0sa8175flwa; ; ; # 谷.꥓̐ꡎ
+xn--1ug0273b.xn--0sa359l6n7g13a; ‍谷.‌꥓̐ꡎ; [C1, C2]; xn--1ug0273b.xn--0sa359l6n7g13a; ; ; # 谷.꥓̐ꡎ
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤐‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+xn----guc3592k.xn--qe6h; ڪ-뉔.𞤲; [B2, B3]; xn----guc3592k.xn--qe6h; ; ; # ڪ-뉔.𞤲
+xn----guc3592k.xn--0ug7611p; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; ; # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+ڪ-뉔.𞤲‌; ڪ-뉔.𞤲‌; [B2, B3, C1]; xn----guc3592k.xn--0ug7611p; ; xn----guc3592k.xn--qe6h; [B2, B3] # ڪ-뉔.𞤲
+񔲵5ᦛς.꣄ݻܸ᳒; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛς.꣄ݻܸ᳒; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛς.꣄ݻܸ᳒; ; [B1, P1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; xn--5-0mb988ng603j.xn--fob7kk44dl41k; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; ; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+xn--5-0mb988ng603j.xn--fob7kk44dl41k; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+xn--5-ymb298ng603j.xn--fob7kk44dl41k; 񔲵5ᦛς.꣄ݻܸ᳒; [B1, V5, V6]; xn--5-ymb298ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛς.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛΣ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+񔲵5ᦛσ.꣄ݻܸ᳒; 񔲵5ᦛσ.꣄ݻܸ᳒; [B1, P1, V5, V6]; xn--5-0mb988ng603j.xn--fob7kk44dl41k; ; ; # 5ᦛσ.꣄ݻܸ᳒
+淽。ᠾ; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+xn--34w.xn--x7e; 淽.ᠾ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+淽.ᠾ; ; ; xn--34w.xn--x7e; ; ; # 淽.ᠾ
+𐹴𑘷。-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.-
+xn--so0do6k.-; 𐹴𑘷.-; [B1, V3]; xn--so0do6k.-; ; ; # 𐹴𑘷.-
+򬨩Ⴓ❓。𑄨; 򬨩Ⴓ❓.𑄨; [P1, V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩Ⴓ❓。𑄨; 򬨩Ⴓ❓.𑄨; [P1, V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [P1, V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+xn--8di78qvw32y.xn--k80d; 򬨩ⴓ❓.𑄨; [V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+xn--rnd896i0j14q.xn--k80d; 򬨩Ⴓ❓.𑄨; [V5, V6]; xn--rnd896i0j14q.xn--k80d; ; ; # Ⴓ❓.𑄨
+򬨩ⴓ❓。𑄨; 򬨩ⴓ❓.𑄨; [P1, V5, V6]; xn--8di78qvw32y.xn--k80d; ; ; # ⴓ❓.𑄨
+‌𐹡𞤌Ⴇ。ßႣ; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤌Ⴇ。ßႣ; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤮ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌Ⴇ。SSႣ; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssႣ
+‌𐹡𞤮ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。Ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+xn--ykj9323eegwf.xn--ss-151a; 𐹡𞤮ⴇ.ssⴃ; [B1]; xn--ykj9323eegwf.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ
+xn--0ug332c3q0pr56g.xn--ss-151a; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; ; # 𐹡𞤮ⴇ.ssⴃ
+xn--fnd1201kegrf.xn--ss-fek; 𐹡𞤮Ⴇ.ssႣ; [B1, V6]; xn--fnd1201kegrf.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ
+xn--fnd599eyj4pr50g.xn--ss-fek; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; ; # 𐹡𞤮Ⴇ.ssႣ
+xn--0ug332c3q0pr56g.xn--zca417t; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; ; # 𐹡𞤮ⴇ.ßⴃ
+xn--fnd599eyj4pr50g.xn--zca681f; ‌𐹡𞤮Ⴇ.ßႣ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--zca681f; ; ; # 𐹡𞤮Ⴇ.ßႣ
+‌𐹡𞤮ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌Ⴇ。SSႣ; ‌𐹡𞤮Ⴇ.ssႣ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-fek; ; xn--fnd1201kegrf.xn--ss-fek; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssႣ
+‌𐹡𞤮ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。Ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌Ⴇ。Ssⴃ; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; xn--fnd1201kegrf.xn--ss-151a; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssⴃ
+xn--fnd1201kegrf.xn--ss-151a; 𐹡𞤮Ⴇ.ssⴃ; [B1, V6]; xn--fnd1201kegrf.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ
+xn--fnd599eyj4pr50g.xn--ss-151a; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; ; # 𐹡𞤮Ⴇ.ssⴃ
+‌𐹡𞤌ⴇ。ßⴃ; ‌𐹡𞤮ⴇ.ßⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--zca417t; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ßⴃ
+‌𐹡𞤌ⴇ。ssⴃ; ‌𐹡𞤮ⴇ.ssⴃ; [B1, C1]; xn--0ug332c3q0pr56g.xn--ss-151a; ; xn--ykj9323eegwf.xn--ss-151a; [B1] # 𐹡𞤮ⴇ.ssⴃ
+‌𐹡𞤌Ⴇ。Ssⴃ; ‌𐹡𞤮Ⴇ.ssⴃ; [B1, C1, P1, V6]; xn--fnd599eyj4pr50g.xn--ss-151a; ; xn--fnd1201kegrf.xn--ss-151a; [B1, P1, V6] # 𐹡𞤮Ⴇ.ssⴃ
+៿。𞬳; ៿.𞬳; [P1, V6]; xn--45e.xn--et6h; ; ; # .
+៿。𞬳; ៿.𞬳; [P1, V6]; xn--45e.xn--et6h; ; ; # .
+xn--45e.xn--et6h; ៿.𞬳; [V6]; xn--45e.xn--et6h; ; ; # .
+ْ‍。್𑚳; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V5] # ْ.್𑚳
+ْ‍。್𑚳; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; xn--uhb.xn--8tc4527k; [V5] # ْ.್𑚳
+xn--uhb.xn--8tc4527k; ْ.್𑚳; [V5]; xn--uhb.xn--8tc4527k; ; ; # ْ.್𑚳
+xn--uhb882k.xn--8tc4527k; ْ‍.್𑚳; [C2, V5]; xn--uhb882k.xn--8tc4527k; ; ; # ْ.್𑚳
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; ; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞥃≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+xn----g6j886c.xn--xpb049kk353abj99f; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+-≠ᠻ.ݭ𞤡≮󟷺; -≠ᠻ.ݭ𞥃≮󟷺; [B1, B2, B3, P1, V3, V6]; xn----g6j886c.xn--xpb049kk353abj99f; ; ; # -≠ᠻ.ݭ𞥃≮
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+󠰆≯޵𐻪.򊥕≮𑁆ࡌ; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, P1, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; 󠰆≯޵𐻪.򊥕≮𑁆ࡌ; [B1, B5, B6, V6]; xn--zrb797kdm1oes34i.xn--bwb394k8k2o25n6d; ; ; # ≯.≮𑁆ࡌ
+≠󦋂.؀்-ڹ; ; [B1, P1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+≠󦋂.؀்-ڹ; ≠󦋂.؀்-ڹ; [B1, P1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+xn--1ch22084l.xn----qkc07co6n; ≠󦋂.؀்-ڹ; [B1, V6]; xn--1ch22084l.xn----qkc07co6n; ; ; # ≠.்-ڹ
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+៝󠁣≠。𐹼𐋤; ៝󠁣≠.𐹼𐋤; [B1, P1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+xn--54e694cn389z.xn--787ct8r; ៝󠁣≠.𐹼𐋤; [B1, V5, V6]; xn--54e694cn389z.xn--787ct8r; ; ; # ៝≠.𐹼𐋤
+ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [P1, V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß
+ß𰀻񆬗。𝩨🕮ß; ß𰀻񆬗.𝩨🕮ß; [P1, V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; xn--ss-jl59biy67d.xn--ss-4d11aw87d; # ß𰀻.𝩨🕮ß
+SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+xn--ss-jl59biy67d.xn--ss-4d11aw87d; ss𰀻񆬗.𝩨🕮ss; [V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+xn--zca20040bgrkh.xn--zca3653v86qa; ß𰀻񆬗.𝩨🕮ß; [V5, V6]; xn--zca20040bgrkh.xn--zca3653v86qa; ; ; # ß𰀻.𝩨🕮ß
+SS𰀻񆬗。𝩨🕮SS; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+ss𰀻񆬗。𝩨🕮ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+Ss𰀻񆬗。𝩨🕮Ss; ss𰀻񆬗.𝩨🕮ss; [P1, V5, V6]; xn--ss-jl59biy67d.xn--ss-4d11aw87d; ; ; # ss𰀻.𝩨🕮ss
+‍。‌; ‍.‌; [C1, C2]; xn--1ug.xn--0ug; ; .; [A4_2] # .
+xn--1ug.xn--0ug; ‍.‌; [C1, C2]; xn--1ug.xn--0ug; ; ; # .
+҃𐭞‍.ឹ𞯌򟩚; ; [B1, C2, P1, V5, V6]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; xn--m3a6965k.xn--43e8670vmd79b; [B1, P1, V5, V6] # ҃𐭞.ឹ
+xn--m3a6965k.xn--43e8670vmd79b; ҃𐭞.ឹ𞯌򟩚; [B1, V5, V6]; xn--m3a6965k.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ
+xn--m3a412lrr0o.xn--43e8670vmd79b; ҃𐭞‍.ឹ𞯌򟩚; [B1, C2, V5, V6]; xn--m3a412lrr0o.xn--43e8670vmd79b; ; ; # ҃𐭞.ឹ
+‌𐠨‌临。ꡢ򄷞ⶏ𐹣; ‌𐠨‌临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, P1, V6]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; xn--miq9646b.xn--uojv340bk71c99u9f; [B2, B3, B5, B6, P1, V6] # 𐠨临.ꡢⶏ𐹣
+xn--miq9646b.xn--uojv340bk71c99u9f; 𐠨临.ꡢ򄷞ⶏ𐹣; [B2, B3, B5, B6, V6]; xn--miq9646b.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣
+xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ‌𐠨‌临.ꡢ򄷞ⶏ𐹣; [B1, B5, B6, C1, V6]; xn--0uga2656aop9k.xn--uojv340bk71c99u9f; ; ; # 𐠨临.ꡢⶏ𐹣
+󠑘.󠄮; 󠑘.; [P1, V6]; xn--s136e.; ; ; # .
+󠑘.󠄮; 󠑘.; [P1, V6]; xn--s136e.; ; ; # .
+xn--s136e.; 󠑘.; [V6]; xn--s136e.; ; ; # .
+𐫄്.꫶; 𐫄്.꫶; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+𐫄്.꫶; ; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+xn--wxc7880k.xn--2v9a; 𐫄്.꫶; [B1, B3, B6, V5]; xn--wxc7880k.xn--2v9a; ; ; # 𐫄്.꫶
+ꦷ󝵙멹。⒛󠨇; ꦷ󝵙멹.⒛󠨇; [P1, V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+ꦷ󝵙멹。⒛󠨇; ꦷ󝵙멹.⒛󠨇; [P1, V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+ꦷ󝵙멹。20.󠨇; ꦷ󝵙멹.20.󠨇; [P1, V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+ꦷ󝵙멹。20.󠨇; ꦷ󝵙멹.20.󠨇; [P1, V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+xn--ym9av13acp85w.20.xn--d846e; ꦷ󝵙멹.20.󠨇; [V5, V6]; xn--ym9av13acp85w.20.xn--d846e; ; ; # ꦷ멹.20.
+xn--ym9av13acp85w.xn--dth22121k; ꦷ󝵙멹.⒛󠨇; [V5, V6]; xn--ym9av13acp85w.xn--dth22121k; ; ; # ꦷ멹.⒛
+Ⴅ󲬹릖󠶚.ݷ𐹳⒊; ; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+Ⴅ󲬹릖󠶚.ݷ𐹳⒊; Ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+Ⴅ󲬹릖󠶚.ݷ𐹳3.; ; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+Ⴅ󲬹릖󠶚.ݷ𐹳3.; Ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, P1, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳3.; ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳3.; ; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+xn--wkj8016bne45io02g.xn--3-55c6803r.; ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, V6]; xn--wkj8016bne45io02g.xn--3-55c6803r.; ; ; # ⴅ릖.ݷ𐹳3.
+xn--dnd2167fnet0io02g.xn--3-55c6803r.; Ⴅ󲬹릖󠶚.ݷ𐹳3.; [B4, B6, V6]; xn--dnd2167fnet0io02g.xn--3-55c6803r.; ; ; # Ⴅ릖.ݷ𐹳3.
+ⴅ󲬹릖󠶚.ݷ𐹳⒊; ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+ⴅ󲬹릖󠶚.ݷ𐹳⒊; ; [B4, B6, P1, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+xn--wkj8016bne45io02g.xn--7pb000mwm4n; ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, V6]; xn--wkj8016bne45io02g.xn--7pb000mwm4n; ; ; # ⴅ릖.ݷ𐹳⒊
+xn--dnd2167fnet0io02g.xn--7pb000mwm4n; Ⴅ󲬹릖󠶚.ݷ𐹳⒊; [B4, B6, V6]; xn--dnd2167fnet0io02g.xn--7pb000mwm4n; ; ; # Ⴅ릖.ݷ𐹳⒊
+‌。︒; ‌.︒; [C1, P1, V6]; xn--0ug.xn--y86c; ; .xn--y86c; [P1, V6, A4_2] # .︒
+‌。。; ‌..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ..; [A4_2] # ..
+..; ; [X4_2]; ; [A4_2]; ; # ..
+xn--0ug..; ‌..; [C1, X4_2]; xn--0ug..; [C1, A4_2]; ; # ..
+.xn--y86c; .︒; [V6, X4_2]; .xn--y86c; [V6, A4_2]; ; # .︒
+xn--0ug.xn--y86c; ‌.︒; [C1, V6]; xn--0ug.xn--y86c; ; ; # .︒
+≯ݭ.₄; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.₄; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.4; ; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+≯ݭ.4; ≯ݭ.4; [B1, P1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+xn--xpb149k.4; ≯ݭ.4; [B1, V6]; xn--xpb149k.4; ; ; # ≯ݭ.4
+ᡲ-𝟹.ß-‌-; ᡲ-3.ß-‌-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß--
+ᡲ-3.ß-‌-; ; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ß--
+ᡲ-3.SS-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-3.ss-‌-; ; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-3.Ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+xn---3-p9o.ss--; ᡲ-3.ss--; [V2, V3]; xn---3-p9o.ss--; ; ; # ᡲ-3.ss--
+xn---3-p9o.xn--ss---276a; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; ; # ᡲ-3.ss--
+xn---3-p9o.xn-----fia9303a; ᡲ-3.ß-‌-; [C1, V3]; xn---3-p9o.xn-----fia9303a; ; ; # ᡲ-3.ß--
+ᡲ-𝟹.SS-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-𝟹.ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ᡲ-𝟹.Ss-‌-; ᡲ-3.ss-‌-; [C1, V3]; xn---3-p9o.xn--ss---276a; ; xn---3-p9o.ss--; [V2, V3] # ᡲ-3.ss--
+ﴈ𝟦ه󎊯。Ӏ; ضي4ه󎊯.Ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ضي4ه󎊯。Ӏ; ضي4ه󎊯.Ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ضي4ه󎊯。ӏ; ضي4ه󎊯.ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+xn--4-tnc6ck183523b.xn--s5a; ضي4ه󎊯.ӏ; [B2, B3, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+xn--4-tnc6ck183523b.xn--d5a; ضي4ه󎊯.Ӏ; [B2, B3, V6]; xn--4-tnc6ck183523b.xn--d5a; ; ; # ضي4ه.Ӏ
+ﴈ𝟦ه󎊯。ӏ; ضي4ه󎊯.ӏ; [B2, B3, P1, V6]; xn--4-tnc6ck183523b.xn--s5a; ; ; # ضي4ه.ӏ
+-.؂آ𑆾🐹; ; [B1, P1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+-.؂آ𑆾🐹; -.؂آ𑆾🐹; [B1, P1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+-.xn--kfb8dy983hgl7g; -.؂آ𑆾🐹; [B1, V3, V6]; -.xn--kfb8dy983hgl7g; ; ; # -.آ𑆾🐹
+󙶜ᢘ。᩿⺢; 󙶜ᢘ.᩿⺢; [P1, V5, V6]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢
+xn--ibf35138o.xn--fpfz94g; 󙶜ᢘ.᩿⺢; [V5, V6]; xn--ibf35138o.xn--fpfz94g; ; ; # ᢘ.᩿⺢
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ႷᠤႫ。?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--66e353ce0ilb.xn--?-7fb34t0u7s; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+xn--jndx718cnnl.xn--?-7fb34t0u7s; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠ⴗᠤⴋ。?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+≠Ⴗᠤⴋ。?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--vnd619as6ig6k.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+XN--VND619AS6IG6K.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+Xn--Vnd619as6ig6k.?͌س觴; ≠Ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--vnd619as6ig6k.xn--?-7fb34t0u7s; ; ; # ≠Ⴗᠤⴋ.?͌س觴
+xn--66e353ce0ilb.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+XN--66E353CE0ILB.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+Xn--66e353ce0ilb.?͌س觴; ≠ⴗᠤⴋ.?͌س觴; [B1, P1, V6]; xn--66e353ce0ilb.xn--?-7fb34t0u7s; ; ; # ≠ⴗᠤⴋ.?͌س觴
+xn--jndx718cnnl.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+XN--JNDX718CNNL.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+Xn--Jndx718cnnl.?͌س觴; ≠ႷᠤႫ.?͌س觴; [B1, P1, V6]; xn--jndx718cnnl.xn--?-7fb34t0u7s; ; ; # ≠ႷᠤႫ.?͌س觴
+٧.𐥨; ; [B1, P1, V6]; xn--gib.xn--vm9c; ; ; # ٧.
+xn--gib.xn--vm9c; ٧.𐥨; [B1, V6]; xn--gib.xn--vm9c; ; ; # ٧.
+꧀𝟯。‍񼑥𐹪᯳; ꧀3.‍񼑥𐹪᯳; [B1, C2, P1, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, P1, V5, V6] # ꧀3.𐹪᯳
+꧀3。‍񼑥𐹪᯳; ꧀3.‍񼑥𐹪᯳; [B1, C2, P1, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; xn--3-5z4e.xn--1zfz754hncv8b; [B5, P1, V5, V6] # ꧀3.𐹪᯳
+xn--3-5z4e.xn--1zfz754hncv8b; ꧀3.񼑥𐹪᯳; [B5, V5, V6]; xn--3-5z4e.xn--1zfz754hncv8b; ; ; # ꧀3.𐹪᯳
+xn--3-5z4e.xn--1zf96ony8ygd68c; ꧀3.‍񼑥𐹪᯳; [B1, C2, V5, V6]; xn--3-5z4e.xn--1zf96ony8ygd68c; ; ; # ꧀3.𐹪᯳
+򣕄4񠖽.≯٤𑀾󠸌; ; [B1, P1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+򣕄4񠖽.≯٤𑀾󠸌; 򣕄4񠖽.≯٤𑀾󠸌; [B1, P1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+xn--4-fg85dl688i.xn--dib174li86ntdy0i; 򣕄4񠖽.≯٤𑀾󠸌; [B1, V6]; xn--4-fg85dl688i.xn--dib174li86ntdy0i; ; ; # 4.≯٤𑀾
+򗆧𝟯。⒈᩶𝟚򠘌; 򗆧3.⒈᩶2򠘌; [P1, V6]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2
+򗆧3。1.᩶2򠘌; 򗆧3.1.᩶2򠘌; [P1, V5, V6]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2
+xn--3-rj42h.1.xn--2-13k96240l; 򗆧3.1.᩶2򠘌; [V5, V6]; xn--3-rj42h.1.xn--2-13k96240l; ; ; # 3.1.᩶2
+xn--3-rj42h.xn--2-13k746cq465x; 򗆧3.⒈᩶2򠘌; [V6]; xn--3-rj42h.xn--2-13k746cq465x; ; ; # 3.⒈᩶2
+‍₅⒈。≯𝟴‍; ‍5⒈.≯8‍; [C2, P1, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [P1, V6] # 5⒈.≯8
+‍₅⒈。≯𝟴‍; ‍5⒈.≯8‍; [C2, P1, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; xn--5-ecp.xn--8-ogo; [P1, V6] # 5⒈.≯8
+‍51.。≯8‍; ‍51..≯8‍; [C2, P1, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, P1, V6, A4_2]; 51..xn--8-ogo; [P1, V6, A4_2] # 51..≯8
+‍51.。≯8‍; ‍51..≯8‍; [C2, P1, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, P1, V6, A4_2]; 51..xn--8-ogo; [P1, V6, A4_2] # 51..≯8
+51..xn--8-ogo; 51..≯8; [V6, X4_2]; 51..xn--8-ogo; [V6, A4_2]; ; # 51..≯8
+xn--51-l1t..xn--8-ugn00i; ‍51..≯8‍; [C2, V6, X4_2]; xn--51-l1t..xn--8-ugn00i; [C2, V6, A4_2]; ; # 51..≯8
+xn--5-ecp.xn--8-ogo; 5⒈.≯8; [V6]; xn--5-ecp.xn--8-ogo; ; ; # 5⒈.≯8
+xn--5-tgnz5r.xn--8-ugn00i; ‍5⒈.≯8‍; [C2, V6]; xn--5-tgnz5r.xn--8-ugn00i; ; ; # 5⒈.≯8
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+ꡰڗႆ.򪘙ܯ≠‌; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, P1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; xn--tjb002cn51k.xn--5nb630lbj91q; [B5, B6, P1, V6] # ꡰڗႆ.ܯ≠
+xn--tjb002cn51k.xn--5nb630lbj91q; ꡰڗႆ.򪘙ܯ≠; [B5, B6, V6]; xn--tjb002cn51k.xn--5nb630lbj91q; ; ; # ꡰڗႆ.ܯ≠
+xn--tjb002cn51k.xn--5nb448jcubcz547b; ꡰڗႆ.򪘙ܯ≠‌; [B5, B6, C1, V6]; xn--tjb002cn51k.xn--5nb448jcubcz547b; ; ; # ꡰڗႆ.ܯ≠
+𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B3, B5, B6, P1, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+𑄱。򪌿𐹵; 𑄱.򪌿𐹵; [B1, B3, B5, B6, P1, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+xn--t80d.xn--to0d14792b; 𑄱.򪌿𐹵; [B1, B3, B5, B6, V5, V6]; xn--t80d.xn--to0d14792b; ; ; # 𑄱.𐹵
+𝟥؀。ܽ; 3؀.ܽ; [B1, B3, B6, P1, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+3؀。ܽ; 3؀.ܽ; [B1, B3, B6, P1, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+xn--3-rkc.xn--kob; 3؀.ܽ; [B1, B3, B6, V5, V6]; xn--3-rkc.xn--kob; ; ; # 3.ܽ
+ط𐹣٦.ݭ긷; ; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+ط𐹣٦.ݭ긷; ط𐹣٦.ݭ긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+xn--2gb8gu829f.xn--xpb0156f; ط𐹣٦.ݭ긷; [B2, B3]; xn--2gb8gu829f.xn--xpb0156f; ; ; # ط𐹣٦.ݭ긷
+︒Ↄⷧ򾀃.Ⴗ𐣞; ︒Ↄⷧ򾀃.Ⴗ𐣞; [B1, B5, B6, P1, V6]; xn--q5g000c056n0226g.xn--vnd8618j; ; ; # ︒Ↄⷧ.Ⴗ
+。Ↄⷧ򾀃.Ⴗ𐣞; .Ↄⷧ򾀃.Ⴗ𐣞; [B5, B6, P1, V6, X4_2]; .xn--q5g000cll06u.xn--vnd8618j; [B5, B6, P1, V6, A4_2]; ; # .Ↄⷧ.Ⴗ
+。ↄⷧ򾀃.ⴗ𐣞; .ↄⷧ򾀃.ⴗ𐣞; [B5, B6, P1, V6, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, P1, V6, A4_2]; ; # .ↄⷧ.ⴗ
+.xn--r5gy00cll06u.xn--flj4541e; .ↄⷧ򾀃.ⴗ𐣞; [B5, B6, V6, X4_2]; .xn--r5gy00cll06u.xn--flj4541e; [B5, B6, V6, A4_2]; ; # .ↄⷧ.ⴗ
+.xn--q5g000cll06u.xn--vnd8618j; .Ↄⷧ򾀃.Ⴗ𐣞; [B5, B6, V6, X4_2]; .xn--q5g000cll06u.xn--vnd8618j; [B5, B6, V6, A4_2]; ; # .Ↄⷧ.Ⴗ
+︒ↄⷧ򾀃.ⴗ𐣞; ︒ↄⷧ򾀃.ⴗ𐣞; [B1, B5, B6, P1, V6]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ
+xn--r5gy00c056n0226g.xn--flj4541e; ︒ↄⷧ򾀃.ⴗ𐣞; [B1, B5, B6, V6]; xn--r5gy00c056n0226g.xn--flj4541e; ; ; # ︒ↄⷧ.ⴗ
+xn--q5g000c056n0226g.xn--vnd8618j; ︒Ↄⷧ򾀃.Ⴗ𐣞; [B1, B5, B6, V6]; xn--q5g000c056n0226g.xn--vnd8618j; ; ; # ︒Ↄⷧ.Ⴗ
+؀.ֱ; ; [B1, B3, B6, P1, V5, V6]; xn--ifb.xn--8cb; ; ; # .ֱ
+xn--ifb.xn--8cb; ؀.ֱ; [B1, B3, B6, V5, V6]; xn--ifb.xn--8cb; ; ; # .ֱ
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+ς≯。𐹽; ς≯.𐹽; [B1, B6, P1, V6]; xn--3xa028m.xn--1o0d; ; xn--4xa818m.xn--1o0d; # ς≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+xn--4xa818m.xn--1o0d; σ≯.𐹽; [B1, B6, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+xn--3xa028m.xn--1o0d; ς≯.𐹽; [B1, B6, V6]; xn--3xa028m.xn--1o0d; ; ; # ς≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+Σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+σ≯。𐹽; σ≯.𐹽; [B1, B6, P1, V6]; xn--4xa818m.xn--1o0d; ; ; # σ≯.𐹽
+្‍ݟ。𐹶; ្‍ݟ.𐹶; [B1, V5]; xn--jpb535fv9f.xn--uo0d; ; xn--jpb535f.xn--uo0d; # ្ݟ.𐹶
+xn--jpb535f.xn--uo0d; ្ݟ.𐹶; [B1, V5]; xn--jpb535f.xn--uo0d; ; ; # ្ݟ.𐹶
+xn--jpb535fv9f.xn--uo0d; ្‍ݟ.𐹶; [B1, V5]; xn--jpb535fv9f.xn--uo0d; ; ; # ្ݟ.𐹶
+𾷂ੂႪ񂂟.≮; ; [P1, V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+𾷂ੂႪ񂂟.≮; 𾷂ੂႪ񂂟.≮; [P1, V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+𾷂ੂⴊ񂂟.≮; 𾷂ੂⴊ񂂟.≮; [P1, V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+𾷂ੂⴊ񂂟.≮; ; [P1, V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+xn--nbc229o4y27dgskb.xn--gdh; 𾷂ੂⴊ񂂟.≮; [V6]; xn--nbc229o4y27dgskb.xn--gdh; ; ; # ੂⴊ.≮
+xn--nbc493aro75ggskb.xn--gdh; 𾷂ੂႪ񂂟.≮; [V6]; xn--nbc493aro75ggskb.xn--gdh; ; ; # ੂႪ.≮
+ꡠ.۲; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+ꡠ.۲; ; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+xn--5c9a.xn--fmb; ꡠ.۲; ; xn--5c9a.xn--fmb; ; ; # ꡠ.۲
+𐹣񄷄。ꡬ🄄; 𐹣񄷄.ꡬ🄄; [B1, P1, V6]; xn--bo0d0203l.xn--id9a4443d; ; ; # 𐹣.ꡬ🄄
+𐹣񄷄。ꡬ3,; 𐹣񄷄.ꡬ3,; [B1, B6, P1, V6]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3,
+xn--bo0d0203l.xn--3,-yj9h; 𐹣񄷄.ꡬ3,; [B1, B6, P1, V6]; xn--bo0d0203l.xn--3,-yj9h; ; ; # 𐹣.ꡬ3,
+xn--bo0d0203l.xn--id9a4443d; 𐹣񄷄.ꡬ🄄; [B1, V6]; xn--bo0d0203l.xn--id9a4443d; ; ; # 𐹣.ꡬ🄄
+-్𞾀𑲓。‍്; -్𞾀𑲓.‍്; [B1, C2, P1, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, B3, B6, P1, V3, V5, V6] # -్𑲓.്
+-్𞾀𑲓。‍്; -్𞾀𑲓.‍്; [B1, C2, P1, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; xn----x6e0220sclug.xn--wxc; [B1, B3, B6, P1, V3, V5, V6] # -్𑲓.്
+xn----x6e0220sclug.xn--wxc; -్𞾀𑲓.്; [B1, B3, B6, V3, V5, V6]; xn----x6e0220sclug.xn--wxc; ; ; # -్𑲓.്
+xn----x6e0220sclug.xn--wxc317g; -్𞾀𑲓.‍്; [B1, C2, V3, V6]; xn----x6e0220sclug.xn--wxc317g; ; ; # -్𑲓.്
+꙽‌霣🄆。‌𑁂ᬁ; ꙽‌霣🄆.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; xn--2q5a751a653w.xn--4sf0725i; [P1, V5, V6] # ꙽霣🄆.𑁂ᬁ
+꙽‌霣🄆。‌𑁂ᬁ; ꙽‌霣🄆.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; xn--2q5a751a653w.xn--4sf0725i; [P1, V5, V6] # ꙽霣🄆.𑁂ᬁ
+꙽‌霣5,。‌𑁂ᬁ; ꙽‌霣5,.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; xn--5,-op8g373c.xn--4sf0725i; [P1, V5, V6] # ꙽霣5,.𑁂ᬁ
+xn--5,-op8g373c.xn--4sf0725i; ꙽霣5,.𑁂ᬁ; [P1, V5, V6]; xn--5,-op8g373c.xn--4sf0725i; ; ; # ꙽霣5,.𑁂ᬁ
+xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ꙽‌霣5,.‌𑁂ᬁ; [C1, P1, V5, V6]; xn--5,-i1tz135dnbqa.xn--4sf36u6u4w; ; ; # ꙽霣5,.𑁂ᬁ
+xn--2q5a751a653w.xn--4sf0725i; ꙽霣🄆.𑁂ᬁ; [V5, V6]; xn--2q5a751a653w.xn--4sf0725i; ; ; # ꙽霣🄆.𑁂ᬁ
+xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ꙽‌霣🄆.‌𑁂ᬁ; [C1, V5, V6]; xn--0ug4208b2vjuk63a.xn--4sf36u6u4w; ; ; # ꙽霣🄆.𑁂ᬁ
+兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [P1, V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+兎。ᠼ󠴜𑚶𑰿; 兎.ᠼ󠴜𑚶𑰿; [P1, V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+xn--b5q.xn--v7e6041kqqd4m251b; 兎.ᠼ󠴜𑚶𑰿; [V6]; xn--b5q.xn--v7e6041kqqd4m251b; ; ; # 兎.ᠼ𑚶𑰿
+𝟙。‍𝟸‍⁷; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27
+1。‍2‍7; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; 1.27; [] # 1.27
+1.27; ; ; ; ; ; # 1.27
+1.xn--27-l1tb; 1.‍2‍7; [C2]; 1.xn--27-l1tb; ; ; # 1.27
+ᡨ-。󠻋𝟷; ᡨ-.󠻋1; [P1, V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+ᡨ-。󠻋1; ᡨ-.󠻋1; [P1, V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+xn----z8j.xn--1-5671m; ᡨ-.󠻋1; [V3, V6]; xn----z8j.xn--1-5671m; ; ; # ᡨ-.1
+𑰻񵀐𐫚.٨⁹; 𑰻񵀐𐫚.٨9; [B1, P1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+𑰻񵀐𐫚.٨9; ; [B1, P1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+xn--gx9cr01aul57i.xn--9-oqc; 𑰻񵀐𐫚.٨9; [B1, V5, V6]; xn--gx9cr01aul57i.xn--9-oqc; ; ; # 𑰻𐫚.٨9
+Ⴜ򈷭ྀ⾇。Ⴏ♀‌‌; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, P1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; xn--zed54dz10wo343g.xn--nnd651i; [P1, V6] # Ⴜྀ舛.Ⴏ♀
+Ⴜ򈷭ྀ舛。Ⴏ♀‌‌; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, P1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; xn--zed54dz10wo343g.xn--nnd651i; [P1, V6] # Ⴜྀ舛.Ⴏ♀
+ⴜ򈷭ྀ舛。ⴏ♀‌‌; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, P1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [P1, V6] # ⴜྀ舛.ⴏ♀
+xn--zed372mdj2do3v4h.xn--e5h11w; ⴜ򈷭ྀ舛.ⴏ♀; [V6]; xn--zed372mdj2do3v4h.xn--e5h11w; ; ; # ⴜྀ舛.ⴏ♀
+xn--zed372mdj2do3v4h.xn--0uga678bgyh; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; ; # ⴜྀ舛.ⴏ♀
+xn--zed54dz10wo343g.xn--nnd651i; Ⴜ򈷭ྀ舛.Ⴏ♀; [V6]; xn--zed54dz10wo343g.xn--nnd651i; ; ; # Ⴜྀ舛.Ⴏ♀
+xn--zed54dz10wo343g.xn--nnd089ea464d; Ⴜ򈷭ྀ舛.Ⴏ♀‌‌; [C1, V6]; xn--zed54dz10wo343g.xn--nnd089ea464d; ; ; # Ⴜྀ舛.Ⴏ♀
+ⴜ򈷭ྀ⾇。ⴏ♀‌‌; ⴜ򈷭ྀ舛.ⴏ♀‌‌; [C1, P1, V6]; xn--zed372mdj2do3v4h.xn--0uga678bgyh; ; xn--zed372mdj2do3v4h.xn--e5h11w; [P1, V6] # ⴜྀ舛.ⴏ♀
+𑁆𝟰.‍; 𑁆4.‍; [C2, V5]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V5] # 𑁆4.
+𑁆4.‍; ; [C2, V5]; xn--4-xu7i.xn--1ug; ; xn--4-xu7i.; [V5] # 𑁆4.
+xn--4-xu7i.; 𑁆4.; [V5]; xn--4-xu7i.; ; ; # 𑁆4.
+xn--4-xu7i.xn--1ug; 𑁆4.‍; [C2, V5]; xn--4-xu7i.xn--1ug; ; ; # 𑁆4.
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘Ⴞ癀。𑘿‍‌붼; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; xn--2nd6803c7q37d.xn--et3bn23n; [P1, V5, V6] # Ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+xn--mlju35u7qx2f.xn--et3bn23n; 񮴘ⴞ癀.𑘿붼; [V5, V6]; xn--mlju35u7qx2f.xn--et3bn23n; ; ; # ⴞ癀.𑘿붼
+xn--mlju35u7qx2f.xn--0ugb6122js83c; 񮴘ⴞ癀.𑘿‍‌붼; [C1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; ; # ⴞ癀.𑘿붼
+xn--2nd6803c7q37d.xn--et3bn23n; 񮴘Ⴞ癀.𑘿붼; [V5, V6]; xn--2nd6803c7q37d.xn--et3bn23n; ; ; # Ⴞ癀.𑘿붼
+xn--2nd6803c7q37d.xn--0ugb6122js83c; 񮴘Ⴞ癀.𑘿‍‌붼; [C1, V5, V6]; xn--2nd6803c7q37d.xn--0ugb6122js83c; ; ; # Ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+񮴘ⴞ癀。𑘿‍‌붼; 񮴘ⴞ癀.𑘿‍‌붼; [C1, P1, V5, V6]; xn--mlju35u7qx2f.xn--0ugb6122js83c; ; xn--mlju35u7qx2f.xn--et3bn23n; [P1, V5, V6] # ⴞ癀.𑘿붼
+󚀅-்。ڹ; 󚀅-்.ڹ; [B6, P1, V6]; xn----mze84808x.xn--skb; ; ; # -்.ڹ
+xn----mze84808x.xn--skb; 󚀅-்.ڹ; [B6, V6]; xn----mze84808x.xn--skb; ; ; # -்.ڹ
+ᡃ𝟧≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ𝟧≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ5≯ᠣ.氁񨏱ꁫ; ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+ᡃ5≯ᠣ.氁񨏱ꁫ; ᡃ5≯ᠣ.氁񨏱ꁫ; [P1, V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+xn--5-24jyf768b.xn--lqw213ime95g; ᡃ5≯ᠣ.氁񨏱ꁫ; [V6]; xn--5-24jyf768b.xn--lqw213ime95g; ; ; # ᡃ5≯ᠣ.氁ꁫ
+𐹬𝩇.ྲྀ; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+𐹬𝩇.ྲྀ; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+𐹬𝩇.ྲྀ; ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+xn--ko0d8295a.xn--zed3h; 𐹬𝩇.ྲྀ; [B1, B3, B6, V5]; xn--ko0d8295a.xn--zed3h; ; ; # 𐹬𝩇.ྲྀ
+-𑈶⒏.⒎𰛢󠎭; -𑈶⒏.⒎𰛢󠎭; [P1, V3, V6]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢
+-𑈶8..7.𰛢󠎭; ; [P1, V3, V6, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [P1, V3, V6, A4_2]; ; # -𑈶8..7.𰛢
+xn---8-bv5o..7.xn--c35nf1622b; -𑈶8..7.𰛢󠎭; [V3, V6, X4_2]; xn---8-bv5o..7.xn--c35nf1622b; [V3, V6, A4_2]; ; # -𑈶8..7.𰛢
+xn----scp6252h.xn--zshy411yzpx2d; -𑈶⒏.⒎𰛢󠎭; [V3, V6]; xn----scp6252h.xn--zshy411yzpx2d; ; ; # -𑈶⒏.⒎𰛢
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌Ⴁ畝‍.≮; ‌Ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--8md700fea3748f.xn--gdh; ; xn--8md0962c.xn--gdh; [P1, V6] # Ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+‌ⴁ畝‍.≮; ; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+xn--skjy82u.xn--gdh; ⴁ畝.≮; [V6]; xn--skjy82u.xn--gdh; ; ; # ⴁ畝.≮
+xn--0ugc160hb36e.xn--gdh; ‌ⴁ畝‍.≮; [C1, C2, V6]; xn--0ugc160hb36e.xn--gdh; ; ; # ⴁ畝.≮
+xn--8md0962c.xn--gdh; Ⴁ畝.≮; [V6]; xn--8md0962c.xn--gdh; ; ; # Ⴁ畝.≮
+xn--8md700fea3748f.xn--gdh; ‌Ⴁ畝‍.≮; [C1, C2, V6]; xn--8md700fea3748f.xn--gdh; ; ; # Ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+‌ⴁ畝‍.≮; ‌ⴁ畝‍.≮; [C1, C2, P1, V6]; xn--0ugc160hb36e.xn--gdh; ; xn--skjy82u.xn--gdh; [P1, V6] # ⴁ畝.≮
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+歷。𐹻≯󳛽‍; 歷.𐹻≯󳛽‍; [B1, C2, P1, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; xn--nmw.xn--hdh7804gdms2h; [B1, P1, V6] # 歷.𐹻≯
+xn--nmw.xn--hdh7804gdms2h; 歷.𐹻≯󳛽; [B1, V6]; xn--nmw.xn--hdh7804gdms2h; ; ; # 歷.𐹻≯
+xn--nmw.xn--1ugx6gs128a1134j; 歷.𐹻≯󳛽‍; [B1, C2, V6]; xn--nmw.xn--1ugx6gs128a1134j; ; ; # 歷.𐹻≯
+໋‍.鎁󠰑; ໋‍.鎁󠰑; [C2, P1, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [P1, V5, V6] # ໋.鎁
+໋‍.鎁󠰑; ; [C2, P1, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; xn--t8c.xn--iz4a43209d; [P1, V5, V6] # ໋.鎁
+xn--t8c.xn--iz4a43209d; ໋.鎁󠰑; [V5, V6]; xn--t8c.xn--iz4a43209d; ; ; # ໋.鎁
+xn--t8c059f.xn--iz4a43209d; ໋‍.鎁󠰑; [C2, V5, V6]; xn--t8c059f.xn--iz4a43209d; ; ; # ໋.鎁
+‍‌𞤀。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+‍‌𞤀。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+‍‌𞤢。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+xn--9d6h.xn--wh0dj799f; 𞤢.𱘅𐶃; [B5, B6, V6]; xn--9d6h.xn--wh0dj799f; ; ; # 𞤢.
+xn--0ugb45126a.xn--wh0dj799f; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, V6]; xn--0ugb45126a.xn--wh0dj799f; ; ; # 𞤢.
+‍‌𞤢。𱘅𐶃; ‍‌𞤢.𱘅𐶃; [B1, B5, B6, C1, C2, P1, V6]; xn--0ugb45126a.xn--wh0dj799f; ; xn--9d6h.xn--wh0dj799f; [B5, B6, P1, V6] # 𞤢.
+ب≠𝟫-.ς⒍𐹦≠; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠
+ب≠𝟫-.ς⒍𐹦≠; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; xn--9--etd0100a.xn--4xa887mzpbzz04b; # ب≠9-.ς⒍𐹦≠
+ب≠9-.ς6.𐹦≠; ; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠
+ب≠9-.ς6.𐹦≠; ب≠9-.ς6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; # ب≠9-.ς6.𐹦≠
+ب≠9-.Σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.Σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.σ6.𐹦≠; ; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+ب≠9-.σ6.𐹦≠; ب≠9-.σ6.𐹦≠; [B1, B3, P1, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ب≠9-.σ6.𐹦≠; [B1, B3, V3, V6]; xn--9--etd0100a.xn--6-zmb.xn--1ch8704g; ; ; # ب≠9-.σ6.𐹦≠
+xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ب≠9-.ς6.𐹦≠; [B1, B3, V3, V6]; xn--9--etd0100a.xn--6-xmb.xn--1ch8704g; ; ; # ب≠9-.ς6.𐹦≠
+ب≠𝟫-.Σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.Σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+ب≠𝟫-.σ⒍𐹦≠; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, P1, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+xn--9--etd0100a.xn--4xa887mzpbzz04b; ب≠9-.σ⒍𐹦≠; [B3, B5, B6, V3, V6]; xn--9--etd0100a.xn--4xa887mzpbzz04b; ; ; # ب≠9-.σ⒍𐹦≠
+xn--9--etd0100a.xn--3xa097mzpbzz04b; ب≠9-.ς⒍𐹦≠; [B3, B5, B6, V3, V6]; xn--9--etd0100a.xn--3xa097mzpbzz04b; ; ; # ب≠9-.ς⒍𐹦≠
+򉛴.-ᡢ֒𝨠; ; [P1, V3, V6]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠
+xn--ep37b.xn----hec165lho83b; 򉛴.-ᡢ֒𝨠; [V3, V6]; xn--ep37b.xn----hec165lho83b; ; ; # .-ᡢ֒𝨠
+ۋ⒈ß󠄽。񷋍-; ۋ⒈ß.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--zca541ato3a.xn----q001f; ; xn--ss-d7d6651a.xn----q001f; # ۋ⒈ß.-
+ۋ1.ß󠄽。񷋍-; ۋ1.ß.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.xn--zca.xn----q001f; ; xn--1-cwc.ss.xn----q001f; # ۋ1.ß.-
+ۋ1.SS󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+ۋ1.ss󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+ۋ1.Ss󠄽。񷋍-; ۋ1.ss.񷋍-; [B6, P1, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+xn--1-cwc.ss.xn----q001f; ۋ1.ss.񷋍-; [B6, V3, V6]; xn--1-cwc.ss.xn----q001f; ; ; # ۋ1.ss.-
+xn--1-cwc.xn--zca.xn----q001f; ۋ1.ß.񷋍-; [B6, V3, V6]; xn--1-cwc.xn--zca.xn----q001f; ; ; # ۋ1.ß.-
+ۋ⒈SS󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+ۋ⒈ss󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+ۋ⒈Ss󠄽。񷋍-; ۋ⒈ss.񷋍-; [B2, B3, B6, P1, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+xn--ss-d7d6651a.xn----q001f; ۋ⒈ss.񷋍-; [B2, B3, B6, V3, V6]; xn--ss-d7d6651a.xn----q001f; ; ; # ۋ⒈ss.-
+xn--zca541ato3a.xn----q001f; ۋ⒈ß.񷋍-; [B2, B3, B6, V3, V6]; xn--zca541ato3a.xn----q001f; ; ; # ۋ⒈ß.-
+𿀫.᮪ςႦ‍; 𿀫.᮪ςႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪ςႦ
+𿀫.᮪ςႦ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪ςႦ
+𿀫.᮪ςⴆ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪ςⴆ
+𿀫.᮪ΣႦ‍; 𿀫.᮪σႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪σႦ
+𿀫.᮪σⴆ‍; ; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+𿀫.᮪Σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+xn--nu4s.xn--4xa153j7im; 𿀫.᮪σⴆ; [V5, V6]; xn--nu4s.xn--4xa153j7im; ; ; # .᮪σⴆ
+xn--nu4s.xn--4xa153jk8cs1q; 𿀫.᮪σⴆ‍; [C2, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; ; # .᮪σⴆ
+xn--nu4s.xn--4xa217dxri; 𿀫.᮪σႦ; [V5, V6]; xn--nu4s.xn--4xa217dxri; ; ; # .᮪σႦ
+xn--nu4s.xn--4xa217dxriome; 𿀫.᮪σႦ‍; [C2, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; ; # .᮪σႦ
+xn--nu4s.xn--3xa353jk8cs1q; 𿀫.᮪ςⴆ‍; [C2, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; ; # .᮪ςⴆ
+xn--nu4s.xn--3xa417dxriome; 𿀫.᮪ςႦ‍; [C2, V5, V6]; xn--nu4s.xn--3xa417dxriome; ; ; # .᮪ςႦ
+𿀫.᮪ςⴆ‍; 𿀫.᮪ςⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--3xa353jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪ςⴆ
+𿀫.᮪ΣႦ‍; 𿀫.᮪σႦ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa217dxriome; ; xn--nu4s.xn--4xa217dxri; [P1, V5, V6] # .᮪σႦ
+𿀫.᮪σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+𿀫.᮪Σⴆ‍; 𿀫.᮪σⴆ‍; [C2, P1, V5, V6]; xn--nu4s.xn--4xa153jk8cs1q; ; xn--nu4s.xn--4xa153j7im; [P1, V5, V6] # .᮪σⴆ
+⾆࣢.𝈴; 舌࣢.𝈴; [B1, B5, B6, P1, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+舌࣢.𝈴; ; [B1, B5, B6, P1, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+xn--l0b9413d.xn--kl1h; 舌࣢.𝈴; [B1, B5, B6, V6]; xn--l0b9413d.xn--kl1h; ; ; # 舌.𝈴
+⫞𐹶𖫴。⭠⒈; ⫞𐹶𖫴.⭠⒈; [B1, P1, V6]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈
+⫞𐹶𖫴。⭠1.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; ; ; # ⫞𐹶𖫴.⭠1.
+xn--53ix188et88b.xn--1-h6r.; ⫞𐹶𖫴.⭠1.; [B1]; xn--53ix188et88b.xn--1-h6r.; ; ; # ⫞𐹶𖫴.⭠1.
+xn--53ix188et88b.xn--tsh52w; ⫞𐹶𖫴.⭠⒈; [B1, V6]; xn--53ix188et88b.xn--tsh52w; ; ; # ⫞𐹶𖫴.⭠⒈
+⒈‌ꫬ︒.્; ⒈‌ꫬ︒.્; [C1, P1, V5, V6]; xn--0ug78o720myr1c.xn--mfc; ; xn--tsh0720cse8b.xn--mfc; [P1, V5, V6] # ⒈ꫬ︒.્
+1.‌ꫬ。.્; 1.‌ꫬ..્; [C1, V5, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V5, A4_2]; 1.xn--sv9a..xn--mfc; [V5, A4_2] # 1.ꫬ..્
+1.xn--sv9a..xn--mfc; 1.ꫬ..્; [V5, X4_2]; 1.xn--sv9a..xn--mfc; [V5, A4_2]; ; # 1.ꫬ..્
+1.xn--0ug7185c..xn--mfc; 1.‌ꫬ..્; [C1, V5, X4_2]; 1.xn--0ug7185c..xn--mfc; [C1, V5, A4_2]; ; # 1.ꫬ..્
+xn--tsh0720cse8b.xn--mfc; ⒈ꫬ︒.્; [V5, V6]; xn--tsh0720cse8b.xn--mfc; ; ; # ⒈ꫬ︒.્
+xn--0ug78o720myr1c.xn--mfc; ⒈‌ꫬ︒.્; [C1, V5, V6]; xn--0ug78o720myr1c.xn--mfc; ; ; # ⒈ꫬ︒.્
+ె。䰀٨𞭅󠅼; ె.䰀٨𞭅; [B1, B3, B5, B6, P1, V5, V6]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨
+xn--eqc.xn--hib5476aim6t; ె.䰀٨𞭅; [B1, B3, B5, B6, V5, V6]; xn--eqc.xn--hib5476aim6t; ; ; # ె.䰀٨
+ß‍.᯲񄾼; ; [C2, P1, V5, V6]; xn--zca870n.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ß.᯲
+SS‍.᯲񄾼; ss‍.᯲񄾼; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+ss‍.᯲񄾼; ; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+Ss‍.᯲񄾼; ss‍.᯲񄾼; [C2, P1, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ss.xn--0zf22107b; [P1, V5, V6] # ss.᯲
+ss.xn--0zf22107b; ss.᯲񄾼; [V5, V6]; ss.xn--0zf22107b; ; ; # ss.᯲
+xn--ss-n1t.xn--0zf22107b; ss‍.᯲񄾼; [C2, V5, V6]; xn--ss-n1t.xn--0zf22107b; ; ; # ss.᯲
+xn--zca870n.xn--0zf22107b; ß‍.᯲񄾼; [C2, V5, V6]; xn--zca870n.xn--0zf22107b; ; ; # ß.᯲
+𑓂‌≮.≮; ; [P1, V5, V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮
+𑓂‌≮.≮; 𑓂‌≮.≮; [P1, V5, V6]; xn--0ugy6glz29a.xn--gdh; ; xn--gdhz656g.xn--gdh; # 𑓂≮.≮
+xn--gdhz656g.xn--gdh; 𑓂≮.≮; [V5, V6]; xn--gdhz656g.xn--gdh; ; ; # 𑓂≮.≮
+xn--0ugy6glz29a.xn--gdh; 𑓂‌≮.≮; [V5, V6]; xn--0ugy6glz29a.xn--gdh; ; ; # 𑓂≮.≮
+🕼.ᅠ; 🕼.ᅠ; [P1, V6]; xn--my8h.xn--cl7c; ; ; # 🕼.
+🕼.ᅠ; ; [P1, V6]; xn--my8h.xn--psd; ; ; # 🕼.
+xn--my8h.xn--psd; 🕼.ᅠ; [V6]; xn--my8h.xn--psd; ; ; # 🕼.
+xn--my8h.xn--cl7c; 🕼.ᅠ; [V6]; xn--my8h.xn--cl7c; ; ; # 🕼.
+ᡔﶂ。񷘎; ᡔلحى.񷘎; [B5, B6, P1, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+ᡔلحى。񷘎; ᡔلحى.񷘎; [B5, B6, P1, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+xn--sgb9bq785p.xn--bc31b; ᡔلحى.񷘎; [B5, B6, V6]; xn--sgb9bq785p.xn--bc31b; ; ; # ᡔلحى.
+爕򳙑.𝟰気; 爕򳙑.4気; [P1, V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+爕򳙑.4気; ; [P1, V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+xn--1zxq3199c.xn--4-678b; 爕򳙑.4気; [V6]; xn--1zxq3199c.xn--4-678b; ; ; # 爕.4気
+⒋𑍍Ⴝ-.𞬪්ֵ; ⒋𑍍Ⴝ-.𞬪්ֵ; [B1, P1, V3, V6]; xn----t1g323mnk9t.xn--ddb152b7y23b; ; ; # ⒋𑍍Ⴝ-.්ֵ
+4.𑍍Ⴝ-.𞬪්ֵ; ; [B1, B6, P1, V3, V5, V6]; 4.xn----t1g9869q.xn--ddb152b7y23b; ; ; # 4.𑍍Ⴝ-.්ֵ
+4.𑍍ⴝ-.𞬪්ֵ; ; [B1, B6, P1, V3, V5, V6]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ
+4.xn----wwsx259f.xn--ddb152b7y23b; 4.𑍍ⴝ-.𞬪්ֵ; [B1, B6, V3, V5, V6]; 4.xn----wwsx259f.xn--ddb152b7y23b; ; ; # 4.𑍍ⴝ-.්ֵ
+4.xn----t1g9869q.xn--ddb152b7y23b; 4.𑍍Ⴝ-.𞬪්ֵ; [B1, B6, V3, V5, V6]; 4.xn----t1g9869q.xn--ddb152b7y23b; ; ; # 4.𑍍Ⴝ-.්ֵ
+⒋𑍍ⴝ-.𞬪්ֵ; ⒋𑍍ⴝ-.𞬪්ֵ; [B1, P1, V3, V6]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ
+xn----jcp487avl3w.xn--ddb152b7y23b; ⒋𑍍ⴝ-.𞬪්ֵ; [B1, V3, V6]; xn----jcp487avl3w.xn--ddb152b7y23b; ; ; # ⒋𑍍ⴝ-.්ֵ
+xn----t1g323mnk9t.xn--ddb152b7y23b; ⒋𑍍Ⴝ-.𞬪්ֵ; [B1, V3, V6]; xn----t1g323mnk9t.xn--ddb152b7y23b; ; ; # ⒋𑍍Ⴝ-.්ֵ
+󞝃。򑆃񉢗--; 󞝃.򑆃񉢗--; [P1, V2, V3, V6]; xn--2y75e.xn-----1l15eer88n; ; ; # .--
+xn--2y75e.xn-----1l15eer88n; 󞝃.򑆃񉢗--; [V2, V3, V6]; xn--2y75e.xn-----1l15eer88n; ; ; # .--
+‍ߟ。‌꯭; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, B3, B6, V5] # ߟ.꯭
+‍ߟ。‌꯭; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; xn--6sb.xn--429a; [B1, B3, B6, V5] # ߟ.꯭
+xn--6sb.xn--429a; ߟ.꯭; [B1, B3, B6, V5]; xn--6sb.xn--429a; ; ; # ߟ.꯭
+xn--6sb394j.xn--0ug1126c; ‍ߟ.‌꯭; [B1, C1, C2]; xn--6sb394j.xn--0ug1126c; ; ; # ߟ.꯭
+𞮽߿ࡎ。ᢍ򝹁𐫘; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, P1, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+𞮽߿ࡎ。ᢍ򝹁𐫘; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, P1, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+xn--3tb2nz468k.xn--69e8615j5rn5d; 𞮽߿ࡎ.ᢍ򝹁𐫘; [B5, B6, V6]; xn--3tb2nz468k.xn--69e8615j5rn5d; ; ; # ߿ࡎ.ᢍ𐫘
+ۭ𞺌𑄚᜔.ꡞࢷ; ۭم𑄚᜔.ꡞࢷ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+ۭم𑄚᜔.ꡞࢷ; ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+xn--hhb94ag41b739u.xn--dzb5582f; ۭم𑄚᜔.ꡞࢷ; [B1, B5, B6, V5]; xn--hhb94ag41b739u.xn--dzb5582f; ; ; # ۭم𑄚᜔.ꡞࢷ
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ςؼς; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+xn--3sb7483hoyvbbe76g.xn--4xaa21q; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+xn--3sb7483hoyvbbe76g.xn--3xab31q; 񻂵킃𑘶ߜ.σؼς; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; ; # 킃𑘶ߜ.σؼς
+xn--3sb7483hoyvbbe76g.xn--3xaa51q; 񻂵킃𑘶ߜ.ςؼς; [B5, B6, V6]; xn--3sb7483hoyvbbe76g.xn--3xaa51q; ; ; # 킃𑘶ߜ.ςؼς
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。ΣؼΣ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼσ; 񻂵킃𑘶ߜ.σؼσ; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--4xaa21q; ; ; # 킃𑘶ߜ.σؼσ
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。Σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+񻂵킃𑘶ߜ。σؼς; 񻂵킃𑘶ߜ.σؼς; [B5, B6, P1, V6]; xn--3sb7483hoyvbbe76g.xn--3xab31q; ; xn--3sb7483hoyvbbe76g.xn--4xaa21q; # 킃𑘶ߜ.σؼς
+蔰。󠁹ࣝ-𑈵; 蔰.󠁹ࣝ-𑈵; [P1, V6]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵
+xn--sz1a.xn----mrd9984r3dl0i; 蔰.󠁹ࣝ-𑈵; [V6]; xn--sz1a.xn----mrd9984r3dl0i; ; ; # 蔰.ࣝ-𑈵
+ςჅ。ݚ; ςჅ.ݚ; [P1, V6]; xn--3xa677d.xn--epb; ; xn--4xa477d.xn--epb; # ςჅ.ݚ
+ςⴥ。ݚ; ςⴥ.ݚ; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ
+ΣჅ。ݚ; σჅ.ݚ; [P1, V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+σⴥ。ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+Σⴥ。ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+xn--4xa203s.xn--epb; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+σⴥ.ݚ; ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+ΣჅ.ݚ; σჅ.ݚ; [P1, V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+Σⴥ.ݚ; σⴥ.ݚ; ; xn--4xa203s.xn--epb; ; ; # σⴥ.ݚ
+xn--4xa477d.xn--epb; σჅ.ݚ; [V6]; xn--4xa477d.xn--epb; ; ; # σჅ.ݚ
+xn--3xa403s.xn--epb; ςⴥ.ݚ; ; xn--3xa403s.xn--epb; ; ; # ςⴥ.ݚ
+ςⴥ.ݚ; ; ; xn--3xa403s.xn--epb; ; xn--4xa203s.xn--epb; # ςⴥ.ݚ
+xn--3xa677d.xn--epb; ςჅ.ݚ; [V6]; xn--3xa677d.xn--epb; ; ; # ςჅ.ݚ
+్Ⴉ𞰓.᭲; ్Ⴉ𞰓.᭲; [B1, B3, B6, P1, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్Ⴉ𞰓.᭲; ; [B1, B3, B6, P1, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్ⴉ𞰓.᭲; ; [B1, B3, B6, P1, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+xn--lqc478nlr02a.xn--dwf; ్ⴉ𞰓.᭲; [B1, B3, B6, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+xn--lqc64t7t26c.xn--dwf; ్Ⴉ𞰓.᭲; [B1, B3, B6, V5, V6]; xn--lqc64t7t26c.xn--dwf; ; ; # ్Ⴉ.᭲
+్ⴉ𞰓.᭲; ్ⴉ𞰓.᭲; [B1, B3, B6, P1, V5, V6]; xn--lqc478nlr02a.xn--dwf; ; ; # ్ⴉ.᭲
+⮷≮񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, P1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+⮷≮񎈴󠄟。𐠄; ⮷≮񎈴.𐠄; [B1, P1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+xn--gdh877a3513h.xn--pc9c; ⮷≮񎈴.𐠄; [B1, V6]; xn--gdh877a3513h.xn--pc9c; ; ; # ⮷≮.𐠄
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+xn--vkb.xn--08e172a; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.ẏᡤ; ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.Ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+ڼ.Ẏᡤ; ڼ.ẏᡤ; ; xn--vkb.xn--08e172a; ; ; # ڼ.ẏᡤ
+xn--vkb.xn--08e172ax6aca; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; ; # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+ڼ。‍Ẏ‌ᡤ; ڼ.‍ẏ‌ᡤ; [B1, C1, C2]; xn--vkb.xn--08e172ax6aca; ; xn--vkb.xn--08e172a; [] # ڼ.ẏᡤ
+𐹹𑲛。񑂐්; 𐹹𑲛.񑂐්; [B1, P1, V6]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.්
+xn--xo0dg5v.xn--h1c39876d; 𐹹𑲛.񑂐්; [B1, V6]; xn--xo0dg5v.xn--h1c39876d; ; ; # 𐹹𑲛.්
+-≠𑈵。嵕ﻱ۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ﻱ۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ي۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+-≠𑈵。嵕ي۴꥓; -≠𑈵.嵕ي۴꥓; [B1, B5, P1, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+xn----ufo4749h.xn--mhb45a235sns3c; -≠𑈵.嵕ي۴꥓; [B1, B5, V3, V6]; xn----ufo4749h.xn--mhb45a235sns3c; ; ; # -≠𑈵.嵕ي۴꥓
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+‌񍸰𐹶ݮ.ہ‍≯‍; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, P1, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; xn--ypb5875khz9y.xn--0kb682l; [B3, B5, B6, P1, V6] # 𐹶ݮ.ہ≯
+xn--ypb5875khz9y.xn--0kb682l; 񍸰𐹶ݮ.ہ≯; [B3, B5, B6, V6]; xn--ypb5875khz9y.xn--0kb682l; ; ; # 𐹶ݮ.ہ≯
+xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ‌񍸰𐹶ݮ.ہ‍≯‍; [B1, B3, C1, C2, V6]; xn--ypb717jrx2o7v94a.xn--0kb660ka35v; ; ; # 𐹶ݮ.ہ≯
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+≮.឵ࡕ𐫔; ≮.឵ࡕ𐫔; [B1, P1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+xn--gdh.xn--kwb589e217p; ≮.឵ࡕ𐫔; [B1, V5, V6]; xn--gdh.xn--kwb589e217p; ; ; # ≮.ࡕ𐫔
+𐩗‍。ႩႵ; 𐩗‍.ႩႵ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hndy; ; xn--pt9c.xn--hndy; [P1, V6] # 𐩗.ႩႵ
+𐩗‍。ႩႵ; 𐩗‍.ႩႵ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hndy; ; xn--pt9c.xn--hndy; [P1, V6] # 𐩗.ႩႵ
+𐩗‍。ⴉⴕ; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ
+𐩗‍。Ⴉⴕ; 𐩗‍.Ⴉⴕ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hnd666l; ; xn--pt9c.xn--hnd666l; [P1, V6] # 𐩗.Ⴉⴕ
+xn--pt9c.xn--hnd666l; 𐩗.Ⴉⴕ; [V6]; xn--pt9c.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--1ug4933g.xn--hnd666l; 𐩗‍.Ⴉⴕ; [B3, C2, V6]; xn--1ug4933g.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--pt9c.xn--0kjya; 𐩗.ⴉⴕ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+𐩗.ⴉⴕ; ; ; xn--pt9c.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+𐩗.ႩႵ; ; [P1, V6]; xn--pt9c.xn--hndy; ; ; # 𐩗.ႩႵ
+𐩗.Ⴉⴕ; ; [P1, V6]; xn--pt9c.xn--hnd666l; ; ; # 𐩗.Ⴉⴕ
+xn--pt9c.xn--hndy; 𐩗.ႩႵ; [V6]; xn--pt9c.xn--hndy; ; ; # 𐩗.ႩႵ
+xn--1ug4933g.xn--0kjya; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; ; # 𐩗.ⴉⴕ
+xn--1ug4933g.xn--hndy; 𐩗‍.ႩႵ; [B3, C2, V6]; xn--1ug4933g.xn--hndy; ; ; # 𐩗.ႩႵ
+𐩗‍。ⴉⴕ; 𐩗‍.ⴉⴕ; [B3, C2]; xn--1ug4933g.xn--0kjya; ; xn--pt9c.xn--0kjya; [] # 𐩗.ⴉⴕ
+𐩗‍。Ⴉⴕ; 𐩗‍.Ⴉⴕ; [B3, C2, P1, V6]; xn--1ug4933g.xn--hnd666l; ; xn--pt9c.xn--hnd666l; [P1, V6] # 𐩗.Ⴉⴕ
+‌‌ㄤ.̮󕨑ূ; ‌‌ㄤ.̮󕨑ূ; [C1, P1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [P1, V5, V6] # ㄤ.̮ূ
+‌‌ㄤ.̮󕨑ূ; ; [C1, P1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; xn--1fk.xn--vta284a9o563a; [P1, V5, V6] # ㄤ.̮ূ
+xn--1fk.xn--vta284a9o563a; ㄤ.̮󕨑ূ; [V5, V6]; xn--1fk.xn--vta284a9o563a; ; ; # ㄤ.̮ূ
+xn--0uga242k.xn--vta284a9o563a; ‌‌ㄤ.̮󕨑ূ; [C1, V5, V6]; xn--0uga242k.xn--vta284a9o563a; ; ; # ㄤ.̮ূ
+𐋻。-‌𐫄Ⴗ; 𐋻.-‌𐫄Ⴗ; [B1, C1, P1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; xn--v97c.xn----i1g2513q; [B1, P1, V3, V6] # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄Ⴗ; 𐋻.-‌𐫄Ⴗ; [B1, C1, P1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; xn--v97c.xn----i1g2513q; [B1, P1, V3, V6] # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄ⴗ; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ
+xn--v97c.xn----lws0526f; 𐋻.-𐫄ⴗ; [B1, V3]; xn--v97c.xn----lws0526f; ; ; # 𐋻.-𐫄ⴗ
+xn--v97c.xn----sgnv20du99s; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; ; # 𐋻.-𐫄ⴗ
+xn--v97c.xn----i1g2513q; 𐋻.-𐫄Ⴗ; [B1, V3, V6]; xn--v97c.xn----i1g2513q; ; ; # 𐋻.-𐫄Ⴗ
+xn--v97c.xn----i1g888ih12u; 𐋻.-‌𐫄Ⴗ; [B1, C1, V3, V6]; xn--v97c.xn----i1g888ih12u; ; ; # 𐋻.-𐫄Ⴗ
+𐋻。-‌𐫄ⴗ; 𐋻.-‌𐫄ⴗ; [B1, C1, V3]; xn--v97c.xn----sgnv20du99s; ; xn--v97c.xn----lws0526f; [B1, V3] # 𐋻.-𐫄ⴗ
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; ; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+🙑𐷺.≠‌; 🙑𐷺.≠‌; [B1, C1, P1, V6]; xn--bl0dh970b.xn--0ug83g; ; xn--bl0dh970b.xn--1ch; [B1, P1, V6] # 🙑.≠
+xn--bl0dh970b.xn--1ch; 🙑𐷺.≠; [B1, V6]; xn--bl0dh970b.xn--1ch; ; ; # 🙑.≠
+xn--bl0dh970b.xn--0ug83g; 🙑𐷺.≠‌; [B1, C1, V6]; xn--bl0dh970b.xn--0ug83g; ; ; # 🙑.≠
+ٌ᳒。𞮞⵿⧎; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, P1, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+ٌ᳒。𞮞⵿⧎; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, P1, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+xn--ohb646i.xn--ewi38jf765c; ٌ᳒.𞮞⵿⧎; [B1, B3, B6, V5, V6]; xn--ohb646i.xn--ewi38jf765c; ; ; # ٌ᳒.⵿⧎
+Ⴔ𝨨₃󠁦.𝟳𑂹ஂ; Ⴔ𝨨3󠁦.7𑂹ஂ; [P1, V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+Ⴔ𝨨3󠁦.7𑂹ஂ; ; [P1, V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+ⴔ𝨨3󠁦.7𑂹ஂ; ; [P1, V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+xn--3-ews6985n35s3g.xn--7-cve6271r; ⴔ𝨨3󠁦.7𑂹ஂ; [V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+xn--3-b1g83426a35t0g.xn--7-cve6271r; Ⴔ𝨨3󠁦.7𑂹ஂ; [V6]; xn--3-b1g83426a35t0g.xn--7-cve6271r; ; ; # Ⴔ𝨨3.7𑂹ஂ
+ⴔ𝨨₃󠁦.𝟳𑂹ஂ; ⴔ𝨨3󠁦.7𑂹ஂ; [P1, V6]; xn--3-ews6985n35s3g.xn--7-cve6271r; ; ; # ⴔ𝨨3.7𑂹ஂ
+䏈‌。‌⒈񱢕; 䏈‌.‌⒈񱢕; [C1, P1, V6]; xn--0ug491l.xn--0ug88oot66q; ; xn--eco.xn--tsh21126d; [P1, V6] # 䏈.⒈
+䏈‌。‌1.񱢕; 䏈‌.‌1.񱢕; [C1, P1, V6]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; xn--eco.1.xn--ms39a; [P1, V6] # 䏈.1.
+xn--eco.1.xn--ms39a; 䏈.1.񱢕; [V6]; xn--eco.1.xn--ms39a; ; ; # 䏈.1.
+xn--0ug491l.xn--1-rgn.xn--ms39a; 䏈‌.‌1.񱢕; [C1, V6]; xn--0ug491l.xn--1-rgn.xn--ms39a; ; ; # 䏈.1.
+xn--eco.xn--tsh21126d; 䏈.⒈񱢕; [V6]; xn--eco.xn--tsh21126d; ; ; # 䏈.⒈
+xn--0ug491l.xn--0ug88oot66q; 䏈‌.‌⒈񱢕; [C1, V6]; xn--0ug491l.xn--0ug88oot66q; ; ; # 䏈.⒈
+1꫶ß𑲥。ᷘ; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ
+1꫶ß𑲥。ᷘ; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; xn--1ss-ir6ln166b.xn--weg; # 1꫶ß𑲥.ᷘ
+1꫶SS𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+xn--1ss-ir6ln166b.xn--weg; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+xn--1-qfa2471kdb0d.xn--weg; 1꫶ß𑲥.ᷘ; [V5]; xn--1-qfa2471kdb0d.xn--weg; ; ; # 1꫶ß𑲥.ᷘ
+1꫶SS𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶Ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+1꫶Ss𑲥。ᷘ; 1꫶ss𑲥.ᷘ; [V5]; xn--1ss-ir6ln166b.xn--weg; ; ; # 1꫶ss𑲥.ᷘ
+‍񫶩𞪯್。ݼ⒈; ‍񫶩𞪯್.ݼ⒈; [B1, C2, P1, V6]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; xn--8tc9875v5is1a.xn--dqb689l; [B5, B6, P1, V6] # ್.ݼ⒈
+‍񫶩𞪯್。ݼ1.; ‍񫶩𞪯್.ݼ1.; [B1, C2, P1, V6]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; ; xn--8tc9875v5is1a.xn--1-g6c.; [B5, B6, P1, V6] # ್.ݼ1.
+xn--8tc9875v5is1a.xn--1-g6c.; 񫶩𞪯್.ݼ1.; [B5, B6, V6]; xn--8tc9875v5is1a.xn--1-g6c.; ; ; # ್.ݼ1.
+xn--8tc969gzn94a4lm8a.xn--1-g6c.; ‍񫶩𞪯್.ݼ1.; [B1, C2, V6]; xn--8tc969gzn94a4lm8a.xn--1-g6c.; ; ; # ್.ݼ1.
+xn--8tc9875v5is1a.xn--dqb689l; 񫶩𞪯್.ݼ⒈; [B5, B6, V6]; xn--8tc9875v5is1a.xn--dqb689l; ; ; # ್.ݼ⒈
+xn--8tc969gzn94a4lm8a.xn--dqb689l; ‍񫶩𞪯್.ݼ⒈; [B1, C2, V6]; xn--8tc969gzn94a4lm8a.xn--dqb689l; ; ; # ್.ݼ⒈
+᪶.𞤳򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤳򓢖򻉒ߗ; ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤑򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+xn--zqf.xn--ysb9657vuiz5bj0ep; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+᪶.𞤑򓢖򻉒ߗ; ᪶.𞤳򓢖򻉒ߗ; [B1, B2, B3, B6, P1, V5, V6]; xn--zqf.xn--ysb9657vuiz5bj0ep; ; ; # ᪶.𞤳ߗ
+ࡂ𞩚⒈.󠬌8򏳏ݰ; ࡂ𞩚⒈.󠬌8򏳏ݰ; [B1, P1, V6]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ
+ࡂ𞩚1..󠬌8򏳏ݰ; ; [B1, P1, V6, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, P1, V6, A4_2]; ; # ࡂ1..8ݰ
+xn--1-rid26318a..xn--8-s5c22427ox454a; ࡂ𞩚1..󠬌8򏳏ݰ; [B1, V6, X4_2]; xn--1-rid26318a..xn--8-s5c22427ox454a; [B1, V6, A4_2]; ; # ࡂ1..8ݰ
+xn--0vb095ldg52a.xn--8-s5c22427ox454a; ࡂ𞩚⒈.󠬌8򏳏ݰ; [B1, V6]; xn--0vb095ldg52a.xn--8-s5c22427ox454a; ; ; # ࡂ⒈.8ݰ
+͡𐫫ͩᡷ。-󠰛鞰; ͡𐫫ͩᡷ.-󠰛鞰; [B1, P1, V3, V5, V6]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰
+xn--cvaq482npv5t.xn----yg7dt1332g; ͡𐫫ͩᡷ.-󠰛鞰; [B1, V3, V5, V6]; xn--cvaq482npv5t.xn----yg7dt1332g; ; ; # ͡𐫫ͩᡷ.-鞰
+-.્剘ß𐫃; ; [B1, V3, V5]; -.xn--zca791c493duf8i; ; -.xn--ss-bqg4734erywk; # -.્剘ß𐫃
+-.્剘SS𐫃; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.્剘ss𐫃; ; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.્剘Ss𐫃; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.xn--ss-bqg4734erywk; -.્剘ss𐫃; [B1, V3, V5]; -.xn--ss-bqg4734erywk; ; ; # -.્剘ss𐫃
+-.xn--zca791c493duf8i; -.્剘ß𐫃; [B1, V3, V5]; -.xn--zca791c493duf8i; ; ; # -.્剘ß𐫃
+ࣻ𞵸。-; ࣻ𞵸.-; [B1, P1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+ࣻ𞵸。-; ࣻ𞵸.-; [B1, P1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+xn--b1b2719v.-; ࣻ𞵸.-; [B1, V3, V5, V6]; xn--b1b2719v.-; ; ; # ࣻ.-
+⒈󠈻𐹲。≠؃𐹽; ⒈󠈻𐹲.≠؃𐹽; [B1, P1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+⒈󠈻𐹲。≠؃𐹽; ⒈󠈻𐹲.≠؃𐹽; [B1, P1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+1.󠈻𐹲。≠؃𐹽; 1.󠈻𐹲.≠؃𐹽; [B1, P1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+1.󠈻𐹲。≠؃𐹽; 1.󠈻𐹲.≠؃𐹽; [B1, P1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+1.xn--qo0dl3077c.xn--lfb536lb35n; 1.󠈻𐹲.≠؃𐹽; [B1, V6]; 1.xn--qo0dl3077c.xn--lfb536lb35n; ; ; # 1.𐹲.≠𐹽
+xn--tshw766f1153g.xn--lfb536lb35n; ⒈󠈻𐹲.≠؃𐹽; [B1, V6]; xn--tshw766f1153g.xn--lfb536lb35n; ; ; # ⒈𐹲.≠𐹽
+𐹢󠈚Ⴎ‌.㖾𐹡; ; [B1, B5, B6, C1, P1, V6]; xn--mnd289ezj4pqxp0i.xn--pelu572d; ; xn--mnd9001km0o0g.xn--pelu572d; [B1, B5, B6, P1, V6] # 𐹢Ⴎ.㖾𐹡
+𐹢󠈚ⴎ‌.㖾𐹡; ; [B1, B5, B6, C1, P1, V6]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; xn--5kjx323em053g.xn--pelu572d; [B1, B5, B6, P1, V6] # 𐹢ⴎ.㖾𐹡
+xn--5kjx323em053g.xn--pelu572d; 𐹢󠈚ⴎ.㖾𐹡; [B1, B5, B6, V6]; xn--5kjx323em053g.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡
+xn--0ug342clq0pqxv4i.xn--pelu572d; 𐹢󠈚ⴎ‌.㖾𐹡; [B1, B5, B6, C1, V6]; xn--0ug342clq0pqxv4i.xn--pelu572d; ; ; # 𐹢ⴎ.㖾𐹡
+xn--mnd9001km0o0g.xn--pelu572d; 𐹢󠈚Ⴎ.㖾𐹡; [B1, B5, B6, V6]; xn--mnd9001km0o0g.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡
+xn--mnd289ezj4pqxp0i.xn--pelu572d; 𐹢󠈚Ⴎ‌.㖾𐹡; [B1, B5, B6, C1, V6]; xn--mnd289ezj4pqxp0i.xn--pelu572d; ; ; # 𐹢Ⴎ.㖾𐹡
+򩼗.߇ᡖႳႧ; 򩼗.߇ᡖႳႧ; [B2, B3, P1, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖႳႧ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖⴓⴇ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+xn--te28c.xn--isb295fbtpmb; 򩼗.߇ᡖⴓⴇ; [B2, B3, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+xn--te28c.xn--isb856b9a631d; 򩼗.߇ᡖႳႧ; [B2, B3, V6]; xn--te28c.xn--isb856b9a631d; ; ; # .߇ᡖႳႧ
+򩼗.߇ᡖⴓⴇ; 򩼗.߇ᡖⴓⴇ; [B2, B3, P1, V6]; xn--te28c.xn--isb295fbtpmb; ; ; # .߇ᡖⴓⴇ
+򩼗.߇ᡖႳⴇ; ; [B2, B3, P1, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+xn--te28c.xn--isb286btrgo7w; 򩼗.߇ᡖႳⴇ; [B2, B3, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+򩼗.߇ᡖႳⴇ; 򩼗.߇ᡖႳⴇ; [B2, B3, P1, V6]; xn--te28c.xn--isb286btrgo7w; ; ; # .߇ᡖႳⴇ
+‍􅍉.ڳݵ; ; [B1, C2, P1, V6]; xn--1ug39444n.xn--mkb20b; ; xn--3j78f.xn--mkb20b; [P1, V6] # .ڳݵ
+xn--3j78f.xn--mkb20b; 􅍉.ڳݵ; [V6]; xn--3j78f.xn--mkb20b; ; ; # .ڳݵ
+xn--1ug39444n.xn--mkb20b; ‍􅍉.ڳݵ; [B1, C2, V6]; xn--1ug39444n.xn--mkb20b; ; ; # .ڳݵ
+𲤱⒛⾳.ꡦ⒈; 𲤱⒛音.ꡦ⒈; [P1, V6]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈
+𲤱20.音.ꡦ1.; ; [P1, V6]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; ; ; # 20.音.ꡦ1.
+xn--20-9802c.xn--0w5a.xn--1-eg4e.; 𲤱20.音.ꡦ1.; [V6]; xn--20-9802c.xn--0w5a.xn--1-eg4e.; ; ; # 20.音.ꡦ1.
+xn--dth6033bzbvx.xn--tsh9439b; 𲤱⒛音.ꡦ⒈; [V6]; xn--dth6033bzbvx.xn--tsh9439b; ; ; # ⒛音.ꡦ⒈
+ߜ8񳦓-。򞲙𑁿𐩥্; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, P1, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+ߜ8񳦓-。򞲙𑁿𐩥্; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, P1, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+xn--8--rve13079p.xn--b7b9842k42df776x; ߜ8񳦓-.򞲙𑁿𐩥্; [B2, B3, B5, B6, V3, V6]; xn--8--rve13079p.xn--b7b9842k42df776x; ; ; # ߜ8-.𑁿𐩥্
+Ⴕ。۰≮ß݅; Ⴕ.۰≮ß݅; [P1, V6]; xn--tnd.xn--zca912alh227g; ; xn--tnd.xn--ss-jbe65aw27i; # Ⴕ.۰≮ß݅
+Ⴕ。۰≮ß݅; Ⴕ.۰≮ß݅; [P1, V6]; xn--tnd.xn--zca912alh227g; ; xn--tnd.xn--ss-jbe65aw27i; # Ⴕ.۰≮ß݅
+ⴕ。۰≮ß݅; ⴕ.۰≮ß݅; [P1, V6]; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅
+ⴕ。۰≮ß݅; ⴕ.۰≮ß݅; [P1, V6]; xn--dlj.xn--zca912alh227g; ; xn--dlj.xn--ss-jbe65aw27i; # ⴕ.۰≮ß݅
+Ⴕ。۰≮SS݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+Ⴕ。۰≮SS݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+ⴕ。۰≮ss݅; ⴕ.۰≮ss݅; [P1, V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+ⴕ。۰≮ss݅; ⴕ.۰≮ss݅; [P1, V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+Ⴕ。۰≮Ss݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+Ⴕ。۰≮Ss݅; Ⴕ.۰≮ss݅; [P1, V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+xn--tnd.xn--ss-jbe65aw27i; Ⴕ.۰≮ss݅; [V6]; xn--tnd.xn--ss-jbe65aw27i; ; ; # Ⴕ.۰≮ss݅
+xn--dlj.xn--ss-jbe65aw27i; ⴕ.۰≮ss݅; [V6]; xn--dlj.xn--ss-jbe65aw27i; ; ; # ⴕ.۰≮ss݅
+xn--dlj.xn--zca912alh227g; ⴕ.۰≮ß݅; [V6]; xn--dlj.xn--zca912alh227g; ; ; # ⴕ.۰≮ß݅
+xn--tnd.xn--zca912alh227g; Ⴕ.۰≮ß݅; [V6]; xn--tnd.xn--zca912alh227g; ; ; # Ⴕ.۰≮ß݅
+ߩ-.𝨗꒱᭲; ; [B1, B3, V3, V5]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲
+xn----odd.xn--dwf8994dc8wj; ߩ-.𝨗꒱᭲; [B1, B3, V3, V5]; xn----odd.xn--dwf8994dc8wj; ; ; # ߩ-.𝨗꒱᭲
+𞼸‌.≯䕵⫧; ; [B1, B3, C1, P1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, P1, V6] # .≯䕵⫧
+𞼸‌.≯䕵⫧; 𞼸‌.≯䕵⫧; [B1, B3, C1, P1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; xn--sn7h.xn--hdh754ax6w; [B1, P1, V6] # .≯䕵⫧
+xn--sn7h.xn--hdh754ax6w; 𞼸.≯䕵⫧; [B1, V6]; xn--sn7h.xn--hdh754ax6w; ; ; # .≯䕵⫧
+xn--0ugx453p.xn--hdh754ax6w; 𞼸‌.≯䕵⫧; [B1, B3, C1, V6]; xn--0ugx453p.xn--hdh754ax6w; ; ; # .≯䕵⫧
+𐨅ßﱗ.ڬ۳︒; 𐨅ßيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--zca23yncs877j.xn--fkb6lp314e; ; xn--ss-ytd5i7765l.xn--fkb6lp314e; # 𐨅ßيخ.ڬ۳︒
+𐨅ßيخ.ڬ۳。; 𐨅ßيخ.ڬ۳.; [B1, V5]; xn--zca23yncs877j.xn--fkb6l.; ; xn--ss-ytd5i7765l.xn--fkb6l.; # 𐨅ßيخ.ڬ۳.
+𐨅SSيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+𐨅ssيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+𐨅Ssيخ.ڬ۳。; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+xn--ss-ytd5i7765l.xn--fkb6l.; 𐨅ssيخ.ڬ۳.; [B1, V5]; xn--ss-ytd5i7765l.xn--fkb6l.; ; ; # 𐨅ssيخ.ڬ۳.
+xn--zca23yncs877j.xn--fkb6l.; 𐨅ßيخ.ڬ۳.; [B1, V5]; xn--zca23yncs877j.xn--fkb6l.; ; ; # 𐨅ßيخ.ڬ۳.
+𐨅SSﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+𐨅ssﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+𐨅Ssﱗ.ڬ۳︒; 𐨅ssيخ.ڬ۳︒; [B1, B3, P1, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+xn--ss-ytd5i7765l.xn--fkb6lp314e; 𐨅ssيخ.ڬ۳︒; [B1, B3, V5, V6]; xn--ss-ytd5i7765l.xn--fkb6lp314e; ; ; # 𐨅ssيخ.ڬ۳︒
+xn--zca23yncs877j.xn--fkb6lp314e; 𐨅ßيخ.ڬ۳︒; [B1, B3, V5, V6]; xn--zca23yncs877j.xn--fkb6lp314e; ; ; # 𐨅ßيخ.ڬ۳︒
+-≮🡒᳭.񏿾Ⴁܔ; ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+-≮🡒᳭.񏿾Ⴁܔ; -≮🡒᳭.񏿾Ⴁܔ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+-≮🡒᳭.񏿾ⴁܔ; -≮🡒᳭.񏿾ⴁܔ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+-≮🡒᳭.񏿾ⴁܔ; ; [B1, P1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+xn----44l04zxt68c.xn--enb135qf106f; -≮🡒᳭.񏿾ⴁܔ; [B1, V3, V6]; xn----44l04zxt68c.xn--enb135qf106f; ; ; # -≮🡒᳭.ⴁܔ
+xn----44l04zxt68c.xn--enb300c1597h; -≮🡒᳭.񏿾Ⴁܔ; [B1, V3, V6]; xn----44l04zxt68c.xn--enb300c1597h; ; ; # -≮🡒᳭.Ⴁܔ
+𞤨。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+𞤨。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+𞤆。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+xn--ge6h.xn--oc9a; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+𞤨.ꡏ; ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+𞤆.ꡏ; 𞤨.ꡏ; ; xn--ge6h.xn--oc9a; ; ; # 𞤨.ꡏ
+xn--ge6h.xn--0ugb9575h; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; ; # 𞤨.ꡏ
+𞤆。ꡏ‍‌; 𞤨.ꡏ‍‌; [B6, C1, C2]; xn--ge6h.xn--0ugb9575h; ; xn--ge6h.xn--oc9a; [] # 𞤨.ꡏ
+󠅹𑂶.ᢌ𑂹٩; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+󠅹𑂶.ᢌ𑂹٩; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+xn--b50d.xn--iib993gyp5p; 𑂶.ᢌ𑂹٩; [B1, B3, B5, B6, V5]; xn--b50d.xn--iib993gyp5p; ; ; # 𑂶.ᢌ𑂹٩
+Ⅎ󠅺񝵒。≯⾑; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯⾑; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯襾; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+Ⅎ󠅺񝵒。≯襾; Ⅎ񝵒.≯襾; [P1, V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ⅎ󠅺񝵒。≯襾; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+xn--73g39298c.xn--hdhz171b; ⅎ񝵒.≯襾; [V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+xn--f3g73398c.xn--hdhz171b; Ⅎ񝵒.≯襾; [V6]; xn--f3g73398c.xn--hdhz171b; ; ; # Ⅎ.≯襾
+ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ⅎ󠅺񝵒。≯⾑; ⅎ񝵒.≯襾; [P1, V6]; xn--73g39298c.xn--hdhz171b; ; ; # ⅎ.≯襾
+ς‍ු٠。-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.-
+ς‍ු٠。-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # ςු٠.-
+Σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+xn--4xa25ks2j.-; σු٠.-; [B1, B5, B6, V3]; xn--4xa25ks2j.-; ; ; # σු٠.-
+xn--4xa25ks2jenu.-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; ; # σු٠.-
+xn--3xa45ks2jenu.-; ς‍ු٠.-; [B1, B5, B6, C2, V3]; xn--3xa45ks2jenu.-; ; ; # ςු٠.-
+Σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+σ‍ු٠。-; σ‍ු٠.-; [B1, B5, B6, C2, V3]; xn--4xa25ks2jenu.-; ; xn--4xa25ks2j.-; [B1, B5, B6, V3] # σු٠.-
+‌.ßႩ-; ; [C1, P1, V3, V6]; xn--0ug.xn----pfa042j; ; .xn--ss--4rn; [P1, V3, V6, A4_2] # .ßႩ-
+‌.ßⴉ-; ; [C1, V3]; xn--0ug.xn----pfa2305a; ; .xn--ss--bi1b; [V3, A4_2] # .ßⴉ-
+‌.SSႩ-; ‌.ssႩ-; [C1, P1, V3, V6]; xn--0ug.xn--ss--4rn; ; .xn--ss--4rn; [P1, V3, V6, A4_2] # .ssႩ-
+‌.ssⴉ-; ; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ-
+‌.Ssⴉ-; ‌.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; .xn--ss--bi1b; [V3, A4_2] # .ssⴉ-
+.xn--ss--bi1b; .ssⴉ-; [V3, X4_2]; .xn--ss--bi1b; [V3, A4_2]; ; # .ssⴉ-
+xn--0ug.xn--ss--bi1b; ‌.ssⴉ-; [C1, V3]; xn--0ug.xn--ss--bi1b; ; ; # .ssⴉ-
+.xn--ss--4rn; .ssႩ-; [V3, V6, X4_2]; .xn--ss--4rn; [V3, V6, A4_2]; ; # .ssႩ-
+xn--0ug.xn--ss--4rn; ‌.ssႩ-; [C1, V3, V6]; xn--0ug.xn--ss--4rn; ; ; # .ssႩ-
+xn--0ug.xn----pfa2305a; ‌.ßⴉ-; [C1, V3]; xn--0ug.xn----pfa2305a; ; ; # .ßⴉ-
+xn--0ug.xn----pfa042j; ‌.ßႩ-; [C1, V3, V6]; xn--0ug.xn----pfa042j; ; ; # .ßႩ-
+󍭲𐫍㓱。⾑; 󍭲𐫍㓱.襾; [B5, P1, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+󍭲𐫍㓱。襾; 󍭲𐫍㓱.襾; [B5, P1, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+xn--u7kt691dlj09f.xn--9v2a; 󍭲𐫍㓱.襾; [B5, V6]; xn--u7kt691dlj09f.xn--9v2a; ; ; # 𐫍㓱.襾
+ڠ𐮋𐹰≮。≯󠦗‍; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, P1, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, P1, V6] # ڠ𐮋𐹰≮.≯
+ڠ𐮋𐹰≮。≯󠦗‍; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, P1, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; xn--2jb053lf13nyoc.xn--hdh08821l; [B1, B3, P1, V6] # ڠ𐮋𐹰≮.≯
+xn--2jb053lf13nyoc.xn--hdh08821l; ڠ𐮋𐹰≮.≯󠦗; [B1, B3, V6]; xn--2jb053lf13nyoc.xn--hdh08821l; ; ; # ڠ𐮋𐹰≮.≯
+xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ڠ𐮋𐹰≮.≯󠦗‍; [B1, B3, C2, V6]; xn--2jb053lf13nyoc.xn--1ugx6gc8096c; ; ; # ڠ𐮋𐹰≮.≯
+𝟞。񃰶ݷࢰ⩋; 6.񃰶ݷࢰ⩋; [B1, B5, B6, P1, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+6。񃰶ݷࢰ⩋; 6.񃰶ݷࢰ⩋; [B1, B5, B6, P1, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+6.xn--7pb04do15eq748f; 6.񃰶ݷࢰ⩋; [B1, B5, B6, V6]; 6.xn--7pb04do15eq748f; ; ; # 6.ݷࢰ⩋
+-ﳽ。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+-ﳽ。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+-شى。𑇀𑍴; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+xn----qnc7d.xn--wd1d62a; -شى.𑇀𑍴; [B1, V3, V5]; xn----qnc7d.xn--wd1d62a; ; ; # -شى.𑇀𑍴
+‌󠊶𝟏.ൃ򪥐𐹬󊓶; ‌󠊶1.ൃ򪥐𐹬󊓶; [B1, C1, P1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, P1, V5, V6] # 1.ൃ𐹬
+‌󠊶1.ൃ򪥐𐹬󊓶; ; [B1, C1, P1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; xn--1-f521m.xn--mxc0872kcu37dnmem; [B1, P1, V5, V6] # 1.ൃ𐹬
+xn--1-f521m.xn--mxc0872kcu37dnmem; 󠊶1.ൃ򪥐𐹬󊓶; [B1, V5, V6]; xn--1-f521m.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬
+xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ‌󠊶1.ൃ򪥐𐹬󊓶; [B1, C1, V5, V6]; xn--1-rgnu0071n.xn--mxc0872kcu37dnmem; ; ; # 1.ൃ𐹬
+齙--𝟰.ß; 齙--4.ß; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß
+齙--4.ß; ; ; xn----4-p16k.xn--zca; ; xn----4-p16k.ss; # 齙--4.ß
+齙--4.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--4.ss; ; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--4.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+xn----4-p16k.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+xn----4-p16k.xn--zca; 齙--4.ß; ; xn----4-p16k.xn--zca; ; ; # 齙--4.ß
+齙--𝟰.SS; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--𝟰.ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+齙--𝟰.Ss; 齙--4.ss; ; xn----4-p16k.ss; ; ; # 齙--4.ss
+᯲.𐹢𞀖‌; ; [B1, C1, V5]; xn--0zf.xn--0ug9894grqqf; ; xn--0zf.xn--9n0d2296a; [B1, V5] # ᯲.𐹢𞀖
+xn--0zf.xn--9n0d2296a; ᯲.𐹢𞀖; [B1, V5]; xn--0zf.xn--9n0d2296a; ; ; # ᯲.𐹢𞀖
+xn--0zf.xn--0ug9894grqqf; ᯲.𐹢𞀖‌; [B1, C1, V5]; xn--0zf.xn--0ug9894grqqf; ; ; # ᯲.𐹢𞀖
+󃲙󠋘。?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+󃲙󠋘。?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+xn--ct86d8w51a.?-; 󃲙󠋘.?-; [P1, V3, V6]; xn--ct86d8w51a.?-; ; ; # .?-
+xn--ct86d8w51a.xn--?--n1t; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; ; # .?-
+xn--ct86d8w51a.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+XN--CT86D8W51A.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+Xn--Ct86d8w51a.?-‍; 󃲙󠋘.?-‍; [C2, P1, V6]; xn--ct86d8w51a.xn--?--n1t; ; xn--ct86d8w51a.?-; [P1, V3, V6] # .?-
+᩠.𞵷-𝪩悎; ᩠.𞵷-𝪩悎; [B1, B2, B3, B6, P1, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+᩠.𞵷-𝪩悎; ; [B1, B2, B3, B6, P1, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+xn--jof.xn----gf4bq282iezpa; ᩠.𞵷-𝪩悎; [B1, B2, B3, B6, V5, V6]; xn--jof.xn----gf4bq282iezpa; ; ; # ᩠.-𝪩悎
+𛜯󠊛.𞤳񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤳񏥾; ; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+xn--xx5gy2741c.xn--re6hw266j; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+𛜯󠊛.𞤑񏥾; 𛜯󠊛.𞤳񏥾; [B2, B3, B6, P1, V6]; xn--xx5gy2741c.xn--re6hw266j; ; ; # .𞤳
+ܜ𐫒خ.𐋲; ; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲
+xn--tgb98b8643d.xn--m97c; ܜ𐫒خ.𐋲; [B1]; xn--tgb98b8643d.xn--m97c; ; ; # ܜ𐫒خ.𐋲
+𐼑𞤓ط࣢.?; 𐼑𞤵ط࣢.?; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+𐼑𞤵ط࣢.?; ; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+xn--2gb08k9w69agm0g.?; 𐼑𞤵ط࣢.?; [B1, P1, V6]; xn--2gb08k9w69agm0g.?; ; ; # 𐼑𞤵ط.?
+Ↄ。᳔੍𞷣; Ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+Ↄ。᳔੍𞷣; Ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+ↄ。᳔੍𞷣; ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+xn--r5g.xn--ybc995g0835a; ↄ.᳔੍𞷣; [B1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+xn--q5g.xn--ybc995g0835a; Ↄ.᳔੍𞷣; [B1, V5, V6]; xn--q5g.xn--ybc995g0835a; ; ; # Ↄ.᳔੍
+ↄ。᳔੍𞷣; ↄ.᳔੍𞷣; [B1, P1, V5, V6]; xn--r5g.xn--ybc995g0835a; ; ; # ↄ.᳔੍
+󠪢-。򛂏≮𑜫; 󠪢-.򛂏≮𑜫; [P1, V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+󠪢-。򛂏≮𑜫; 󠪢-.򛂏≮𑜫; [P1, V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+xn----bh61m.xn--gdhz157g0em1d; 󠪢-.򛂏≮𑜫; [V3, V6]; xn----bh61m.xn--gdhz157g0em1d; ; ; # -.≮𑜫
+‌󠉹‍。򌿧≮Ⴉ; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; xn--3n36e.xn--hnd112gpz83n; [P1, V6] # .≮Ⴉ
+‌󠉹‍。򌿧≮Ⴉ; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; xn--3n36e.xn--hnd112gpz83n; [P1, V6] # .≮Ⴉ
+‌󠉹‍。򌿧≮ⴉ; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [P1, V6] # .≮ⴉ
+‌󠉹‍。򌿧≮ⴉ; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, P1, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; xn--3n36e.xn--gdh992byu01p; [P1, V6] # .≮ⴉ
+xn--3n36e.xn--gdh992byu01p; 󠉹.򌿧≮ⴉ; [V6]; xn--3n36e.xn--gdh992byu01p; ; ; # .≮ⴉ
+xn--0ugc90904y.xn--gdh992byu01p; ‌󠉹‍.򌿧≮ⴉ; [C1, C2, V6]; xn--0ugc90904y.xn--gdh992byu01p; ; ; # .≮ⴉ
+xn--3n36e.xn--hnd112gpz83n; 󠉹.򌿧≮Ⴉ; [V6]; xn--3n36e.xn--hnd112gpz83n; ; ; # .≮Ⴉ
+xn--0ugc90904y.xn--hnd112gpz83n; ‌󠉹‍.򌿧≮Ⴉ; [C1, C2, V6]; xn--0ugc90904y.xn--hnd112gpz83n; ; ; # .≮Ⴉ
+𐹯-𑄴ࢼ。︒䖐⾆; 𐹯-𑄴ࢼ.︒䖐舌; [B1, P1, V6]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌
+𐹯-𑄴ࢼ。。䖐舌; 𐹯-𑄴ࢼ..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌
+xn----rpd7902rclc..xn--fpo216m; 𐹯-𑄴ࢼ..䖐舌; [B1, X4_2]; xn----rpd7902rclc..xn--fpo216m; [B1, A4_2]; ; # 𐹯-𑄴ࢼ..䖐舌
+xn----rpd7902rclc.xn--fpo216mn07e; 𐹯-𑄴ࢼ.︒䖐舌; [B1, V6]; xn----rpd7902rclc.xn--fpo216mn07e; ; ; # 𐹯-𑄴ࢼ.︒䖐舌
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞Ⴐ。쪡; 𝪞Ⴐ.쪡; [P1, V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+xn--7kj1858k.xn--pi6b; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+xn--ond3755u.xn--pi6b; 𝪞Ⴐ.쪡; [V5, V6]; xn--ond3755u.xn--pi6b; ; ; # 𝪞Ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+𝪞ⴐ。쪡; 𝪞ⴐ.쪡; [V5]; xn--7kj1858k.xn--pi6b; ; ; # 𝪞ⴐ.쪡
+ฺ쩁𐹬.􋉳; ; [B1, P1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+ฺ쩁𐹬.􋉳; ฺ쩁𐹬.􋉳; [B1, P1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+xn--o4c4837g2zvb.xn--5f70g; ฺ쩁𐹬.􋉳; [B1, V5, V6]; xn--o4c4837g2zvb.xn--5f70g; ; ; # ฺ쩁𐹬.
+ᡅ0‌。⎢󤨄; ᡅ0‌.⎢󤨄; [C1, P1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [P1, V6] # ᡅ0.⎢
+ᡅ0‌。⎢󤨄; ᡅ0‌.⎢󤨄; [C1, P1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; xn--0-z6j.xn--8lh28773l; [P1, V6] # ᡅ0.⎢
+xn--0-z6j.xn--8lh28773l; ᡅ0.⎢󤨄; [V6]; xn--0-z6j.xn--8lh28773l; ; ; # ᡅ0.⎢
+xn--0-z6jy93b.xn--8lh28773l; ᡅ0‌.⎢󤨄; [C1, V6]; xn--0-z6jy93b.xn--8lh28773l; ; ; # ᡅ0.⎢
+𲮚9ꍩ៓.‍ß; 𲮚9ꍩ៓.‍ß; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍ß; ; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍SS; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍ss; ; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.ss; 𲮚9ꍩ៓.ss; [V6]; xn--9-i0j5967eg3qz.ss; ; ; # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.xn--ss-l1t; 𲮚9ꍩ៓.‍ss; [C2, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; ; # 9ꍩ៓.ss
+xn--9-i0j5967eg3qz.xn--zca770n; 𲮚9ꍩ៓.‍ß; [C2, V6]; xn--9-i0j5967eg3qz.xn--zca770n; ; ; # 9ꍩ៓.ß
+𲮚9ꍩ៓.‍SS; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍Ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+𲮚9ꍩ៓.‍Ss; 𲮚9ꍩ៓.‍ss; [C2, P1, V6]; xn--9-i0j5967eg3qz.xn--ss-l1t; ; xn--9-i0j5967eg3qz.ss; [P1, V6] # 9ꍩ៓.ss
+ꗷ𑆀.ݝ𐩒; ; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒
+xn--ju8a625r.xn--hpb0073k; ꗷ𑆀.ݝ𐩒; ; xn--ju8a625r.xn--hpb0073k; ; ; # ꗷ𑆀.ݝ𐩒
+⒐≯-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [P1, V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+⒐≯-。︒򩑣-񞛠; ⒐≯-.︒򩑣-񞛠; [P1, V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+9.≯-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [P1, V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [P1, V3, V6, A4_2]; ; # 9.≯-..-
+9.≯-。。򩑣-񞛠; 9.≯-..򩑣-񞛠; [P1, V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [P1, V3, V6, A4_2]; ; # 9.≯-..-
+9.xn----ogo..xn----xj54d1s69k; 9.≯-..򩑣-񞛠; [V3, V6, X4_2]; 9.xn----ogo..xn----xj54d1s69k; [V3, V6, A4_2]; ; # 9.≯-..-
+xn----ogot9g.xn----n89hl0522az9u2a; ⒐≯-.︒򩑣-񞛠; [V3, V6]; xn----ogot9g.xn----n89hl0522az9u2a; ; ; # ⒐≯-.︒-
+򈪚ೣჁ󠢏.؝; 򈪚ೣჁ󠢏.؝; [B6, P1, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣჁ󠢏.؝; ; [B6, P1, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣⴡ󠢏.؝; ; [B6, P1, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+xn--vuc226n8n28lmju7a.xn--cgb; 򈪚ೣⴡ󠢏.؝; [B6, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+xn--vuc49qvu85xmju7a.xn--cgb; 򈪚ೣჁ󠢏.؝; [B6, V6]; xn--vuc49qvu85xmju7a.xn--cgb; ; ; # ೣჁ.؝
+򈪚ೣⴡ󠢏.؝; 򈪚ೣⴡ󠢏.؝; [B6, P1, V6]; xn--vuc226n8n28lmju7a.xn--cgb; ; ; # ೣⴡ.؝
+ᷫ。𐋩ظ-𐫮; ᷫ.𐋩ظ-𐫮; [B1, B3, B6, V5]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮
+xn--gfg.xn----xnc0815qyyg; ᷫ.𐋩ظ-𐫮; [B1, B3, B6, V5]; xn--gfg.xn----xnc0815qyyg; ; ; # ᷫ.𐋩ظ-𐫮
+싇。⾇𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。舛𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+xn--9u4b.xn--llj123yh74e; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+xn--9u4b.xn--1nd7519ch79d; 싇.舛𐳋Ⴝ; [B5, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐳋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐲋Ⴝ; 싇.舛𐳋Ⴝ; [B5, P1, V6]; xn--9u4b.xn--1nd7519ch79d; ; ; # 싇.舛𐳋Ⴝ
+싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+싇。⾇𐲋ⴝ; 싇.舛𐳋ⴝ; [B5]; xn--9u4b.xn--llj123yh74e; ; ; # 싇.舛𐳋ⴝ
+𐹠ς。‌ڿჀ; 𐹠ς.‌ڿჀ; [B1, C1, P1, V6]; xn--3xa1267k.xn--ykb632cvxm; ; xn--4xa9167k.xn--ykb632c; [B1, B2, B3, P1, V6] # 𐹠ς.ڿჀ
+𐹠ς。‌ڿⴠ; 𐹠ς.‌ڿⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠ς.ڿⴠ
+𐹠Σ。‌ڿჀ; 𐹠σ.‌ڿჀ; [B1, C1, P1, V6]; xn--4xa9167k.xn--ykb632cvxm; ; xn--4xa9167k.xn--ykb632c; [B1, B2, B3, P1, V6] # 𐹠σ.ڿჀ
+𐹠σ。‌ڿⴠ; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ
+𐹠Σ。‌ڿⴠ; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; xn--4xa9167k.xn--ykb467q; [B1, B2, B3] # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb467q; 𐹠σ.ڿⴠ; [B1, B2, B3]; xn--4xa9167k.xn--ykb467q; ; ; # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb760k9hj; 𐹠σ.‌ڿⴠ; [B1, C1]; xn--4xa9167k.xn--ykb760k9hj; ; ; # 𐹠σ.ڿⴠ
+xn--4xa9167k.xn--ykb632c; 𐹠σ.ڿჀ; [B1, B2, B3, V6]; xn--4xa9167k.xn--ykb632c; ; ; # 𐹠σ.ڿჀ
+xn--4xa9167k.xn--ykb632cvxm; 𐹠σ.‌ڿჀ; [B1, C1, V6]; xn--4xa9167k.xn--ykb632cvxm; ; ; # 𐹠σ.ڿჀ
+xn--3xa1267k.xn--ykb760k9hj; 𐹠ς.‌ڿⴠ; [B1, C1]; xn--3xa1267k.xn--ykb760k9hj; ; ; # 𐹠ς.ڿⴠ
+xn--3xa1267k.xn--ykb632cvxm; 𐹠ς.‌ڿჀ; [B1, C1, V6]; xn--3xa1267k.xn--ykb632cvxm; ; ; # 𐹠ς.ڿჀ
+򇒐‌؄.ښ-ß; ; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn----qfa315b; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ß
+򇒐‌؄.ښ-SS; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+򇒐‌؄.ښ-ss; ; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+򇒐‌؄.ښ-Ss; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, P1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; xn--mfb98261i.xn---ss-sdf; [B2, B3, B5, B6, P1, V6] # .ښ-ss
+xn--mfb98261i.xn---ss-sdf; 򇒐؄.ښ-ss; [B2, B3, B5, B6, V6]; xn--mfb98261i.xn---ss-sdf; ; ; # .ښ-ss
+xn--mfb144kqo32m.xn---ss-sdf; 򇒐‌؄.ښ-ss; [B2, B3, B5, B6, C1, V6]; xn--mfb144kqo32m.xn---ss-sdf; ; ; # .ښ-ss
+xn--mfb144kqo32m.xn----qfa315b; 򇒐‌؄.ښ-ß; [B2, B3, B5, B6, C1, V6]; xn--mfb144kqo32m.xn----qfa315b; ; ; # .ښ-ß
+‌‍឵ٺ.-ﮰ󅄞𐸚; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+‌‍឵ٺ.-ۓ󅄞𐸚; ; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+‌‍឵ٺ.-ۓ󅄞𐸚; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, P1, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; xn--zib539f.xn----twc1133r17r6g; [B1, P1, V3, V5, V6] # ٺ.-ۓ
+xn--zib539f.xn----twc1133r17r6g; ឵ٺ.-ۓ󅄞𐸚; [B1, V3, V5, V6]; xn--zib539f.xn----twc1133r17r6g; ; ; # ٺ.-ۓ
+xn--zib539f8igea.xn----twc1133r17r6g; ‌‍឵ٺ.-ۓ󅄞𐸚; [B1, C1, C2, V3, V6]; xn--zib539f8igea.xn----twc1133r17r6g; ; ; # ٺ.-ۓ
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+򡶱。𐮬≠; 򡶱.𐮬≠; [B3, P1, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+xn--dd55c.xn--1ch3003g; 򡶱.𐮬≠; [B3, V6]; xn--dd55c.xn--1ch3003g; ; ; # .𐮬≠
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+ྲ𞶅。𐹮𐹷덝۵; ྲ𞶅.𐹮𐹷덝۵; [B1, P1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+xn--fgd0675v.xn--imb5839fidpcbba; ྲ𞶅.𐹮𐹷덝۵; [B1, V5, V6]; xn--fgd0675v.xn--imb5839fidpcbba; ; ; # ྲ.𐹮𐹷덝۵
+Ⴏ󠅋-.‍Ⴉ; Ⴏ-.‍Ⴉ; [C2, P1, V3, V6]; xn----00g.xn--hnd399e; ; xn----00g.xn--hnd; [P1, V3, V6] # Ⴏ-.Ⴉ
+Ⴏ󠅋-.‍Ⴉ; Ⴏ-.‍Ⴉ; [C2, P1, V3, V6]; xn----00g.xn--hnd399e; ; xn----00g.xn--hnd; [P1, V3, V6] # Ⴏ-.Ⴉ
+ⴏ󠅋-.‍ⴉ; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ
+xn----3vs.xn--0kj; ⴏ-.ⴉ; [V3]; xn----3vs.xn--0kj; ; ; # ⴏ-.ⴉ
+xn----3vs.xn--1ug532c; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; ; # ⴏ-.ⴉ
+xn----00g.xn--hnd; Ⴏ-.Ⴉ; [V3, V6]; xn----00g.xn--hnd; ; ; # Ⴏ-.Ⴉ
+xn----00g.xn--hnd399e; Ⴏ-.‍Ⴉ; [C2, V3, V6]; xn----00g.xn--hnd399e; ; ; # Ⴏ-.Ⴉ
+ⴏ󠅋-.‍ⴉ; ⴏ-.‍ⴉ; [C2, V3]; xn----3vs.xn--1ug532c; ; xn----3vs.xn--0kj; [V3] # ⴏ-.ⴉ
+⇧𐨏󠾈󯶅。؀󠈵󠆉; ⇧𐨏󠾈󯶅.؀󠈵; [B1, P1, V6]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏.
+xn--l8g5552g64t4g46xf.xn--ifb08144p; ⇧𐨏󠾈󯶅.؀󠈵; [B1, V6]; xn--l8g5552g64t4g46xf.xn--ifb08144p; ; ; # ⇧𐨏.
+≠𐮂.↑🄇⒈; ; [B1, P1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+≠𐮂.↑🄇⒈; ≠𐮂.↑🄇⒈; [B1, P1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+≠𐮂.↑6,1.; ; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+≠𐮂.↑6,1.; ≠𐮂.↑6,1.; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+xn--1chy492g.xn--6,1-pw1a.; ≠𐮂.↑6,1.; [B1, P1, V6]; xn--1chy492g.xn--6,1-pw1a.; ; ; # ≠𐮂.↑6,1.
+xn--1chy492g.xn--45gx9iuy44d; ≠𐮂.↑🄇⒈; [B1, V6]; xn--1chy492g.xn--45gx9iuy44d; ; ; # ≠𐮂.↑🄇⒈
+𝩏󠲉ß.ᢤ򄦌‌𐹫; ; [B1, B5, B6, C1, P1, V5, V6]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ß.ᢤ𐹫
+𝩏󠲉SS.ᢤ򄦌‌𐹫; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+𝩏󠲉ss.ᢤ򄦌‌𐹫; ; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+𝩏󠲉Ss.ᢤ򄦌‌𐹫; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, P1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; [B1, B5, B6, P1, V5, V6] # 𝩏ss.ᢤ𐹫
+xn--ss-zb11ap1427e.xn--ubf2596jbt61c; 𝩏󠲉ss.ᢤ򄦌𐹫; [B1, B5, B6, V5, V6]; xn--ss-zb11ap1427e.xn--ubf2596jbt61c; ; ; # 𝩏ss.ᢤ𐹫
+xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; 𝩏󠲉ss.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, V5, V6]; xn--ss-zb11ap1427e.xn--ubf609atw1tynn3d; ; ; # 𝩏ss.ᢤ𐹫
+xn--zca3153vupz3e.xn--ubf609atw1tynn3d; 𝩏󠲉ß.ᢤ򄦌‌𐹫; [B1, B5, B6, C1, V5, V6]; xn--zca3153vupz3e.xn--ubf609atw1tynn3d; ; ; # 𝩏ß.ᢤ𐹫
+ß𐵳񗘁Ⴇ。ꙺ; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; xn--ss-rek7420r4hs7b.xn--9x8a; # ßႧ.ꙺ
+ß𐵳񗘁Ⴇ。ꙺ; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; xn--ss-rek7420r4hs7b.xn--9x8a; # ßႧ.ꙺ
+ß𐵳񗘁ⴇ。ꙺ; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ßⴇ.ꙺ
+SS𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+ss𐵳񗘁ⴇ。ꙺ; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+Ss𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+xn--ss-rek7420r4hs7b.xn--9x8a; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+xn--ss-e61ar955h4hs7b.xn--9x8a; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+xn--zca227tpy4lkns1b.xn--9x8a; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; ; # ßⴇ.ꙺ
+xn--zca491fci5qkn79a.xn--9x8a; ß𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, V5, V6]; xn--zca491fci5qkn79a.xn--9x8a; ; ; # ßႧ.ꙺ
+ß𐵳񗘁ⴇ。ꙺ; ß𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--zca227tpy4lkns1b.xn--9x8a; ; xn--ss-e61ar955h4hs7b.xn--9x8a; # ßⴇ.ꙺ
+SS𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+ss𐵳񗘁ⴇ。ꙺ; ss𐵳񗘁ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-e61ar955h4hs7b.xn--9x8a; ; ; # ssⴇ.ꙺ
+Ss𐵳񗘁Ⴇ。ꙺ; ss𐵳񗘁Ⴇ.ꙺ; [B1, B3, B5, B6, P1, V5, V6]; xn--ss-rek7420r4hs7b.xn--9x8a; ; ; # ssႧ.ꙺ
+᜔。󠆣-𑋪; ᜔.-𑋪; [V3, V5]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪
+xn--fze.xn----ly8i; ᜔.-𑋪; [V3, V5]; xn--fze.xn----ly8i; ; ; # ᜔.-𑋪
+ꯨ-.򨏜ֽß; ꯨ-.򨏜ֽß; [P1, V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß
+ꯨ-.򨏜ֽß; ; [P1, V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; xn----pw5e.xn--ss-7jd10716y; # ꯨ-.ֽß
+ꯨ-.򨏜ֽSS; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽss; ; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽSs; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+xn----pw5e.xn--ss-7jd10716y; ꯨ-.򨏜ֽss; [V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+xn----pw5e.xn--zca50wfv060a; ꯨ-.򨏜ֽß; [V3, V5, V6]; xn----pw5e.xn--zca50wfv060a; ; ; # ꯨ-.ֽß
+ꯨ-.򨏜ֽSS; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽss; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ꯨ-.򨏜ֽSs; ꯨ-.򨏜ֽss; [P1, V3, V5, V6]; xn----pw5e.xn--ss-7jd10716y; ; ; # ꯨ-.ֽss
+ᡓ-≮。٫󠅱ᡄ; ᡓ-≮.٫ᡄ; [B1, B6, P1, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+ᡓ-≮。٫󠅱ᡄ; ᡓ-≮.٫ᡄ; [B1, B6, P1, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+xn----s7j866c.xn--kib252g; ᡓ-≮.٫ᡄ; [B1, B6, V6]; xn----s7j866c.xn--kib252g; ; ; # ᡓ-≮.٫ᡄ
+𝟥♮𑜫࣭.្𑜫8󠆏; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+3♮𑜫࣭.្𑜫8󠆏; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+xn--3-ksd277tlo7s.xn--8-f0jx021l; 3♮𑜫࣭.្𑜫8; [V5]; xn--3-ksd277tlo7s.xn--8-f0jx021l; ; ; # 3♮𑜫࣭.្𑜫8
+-。򕌀‍❡; -.򕌀‍❡; [C2, P1, V3, V6]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [P1, V3, V6] # -.❡
+-。򕌀‍❡; -.򕌀‍❡; [C2, P1, V3, V6]; -.xn--1ug800aq795s; ; -.xn--nei54421f; [P1, V3, V6] # -.❡
+-.xn--nei54421f; -.򕌀❡; [V3, V6]; -.xn--nei54421f; ; ; # -.❡
+-.xn--1ug800aq795s; -.򕌀‍❡; [C2, V3, V6]; -.xn--1ug800aq795s; ; ; # -.❡
+𝟓☱𝟐򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [P1, V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+5☱2򥰵。𝪮񐡳; 5☱2򥰵.𝪮񐡳; [P1, V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+xn--52-dwx47758j.xn--kd3hk431k; 5☱2򥰵.𝪮񐡳; [V5, V6]; xn--52-dwx47758j.xn--kd3hk431k; ; ; # 5☱2.𝪮
+-.-├򖦣; ; [P1, V3, V6]; -.xn----ukp70432h; ; ; # -.-├
+-.xn----ukp70432h; -.-├򖦣; [V3, V6]; -.xn----ukp70432h; ; ; # -.-├
+֥ݭ。‍󠀘; ֥ݭ.‍󠀘; [B1, C2, P1, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, P1, V5, V6] # ֥ݭ.
+֥ݭ。‍󠀘; ֥ݭ.‍󠀘; [B1, C2, P1, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; xn--wcb62g.xn--p526e; [B1, P1, V5, V6] # ֥ݭ.
+xn--wcb62g.xn--p526e; ֥ݭ.󠀘; [B1, V5, V6]; xn--wcb62g.xn--p526e; ; ; # ֥ݭ.
+xn--wcb62g.xn--1ugy8001l; ֥ݭ.‍󠀘; [B1, C2, V5, V6]; xn--wcb62g.xn--1ugy8001l; ; ; # ֥ݭ.
+쥥󔏉Ⴎ.‌⒈⒈𐫒; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; xn--mnd7865gcy28g.xn--tsha6797o; [B1, P1, V6] # 쥥Ⴎ.⒈⒈𐫒
+쥥󔏉Ⴎ.‌⒈⒈𐫒; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; xn--mnd7865gcy28g.xn--tsha6797o; [B1, P1, V6] # 쥥Ⴎ.⒈⒈𐫒
+쥥󔏉Ⴎ.‌1.1.𐫒; ; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; xn--mnd7865gcy28g.1.1.xn--7w9c; [B1, P1, V6] # 쥥Ⴎ.1.1.𐫒
+쥥󔏉Ⴎ.‌1.1.𐫒; 쥥󔏉Ⴎ.‌1.1.𐫒; [B1, C1, P1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; xn--mnd7865gcy28g.1.1.xn--7w9c; [B1, P1, V6] # 쥥Ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌1.1.𐫒; 쥥󔏉ⴎ.‌1.1.𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, P1, V6] # 쥥ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌1.1.𐫒; ; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; xn--5kj3511ccyw3h.1.1.xn--7w9c; [B1, P1, V6] # 쥥ⴎ.1.1.𐫒
+xn--5kj3511ccyw3h.1.1.xn--7w9c; 쥥󔏉ⴎ.1.1.𐫒; [B1, V6]; xn--5kj3511ccyw3h.1.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒
+xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; 쥥󔏉ⴎ.‌1.1.𐫒; [B1, C1, V6]; xn--5kj3511ccyw3h.xn--1-rgn.1.xn--7w9c; ; ; # 쥥ⴎ.1.1.𐫒
+xn--mnd7865gcy28g.1.1.xn--7w9c; 쥥󔏉Ⴎ.1.1.𐫒; [B1, V6]; xn--mnd7865gcy28g.1.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒
+xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; 쥥󔏉Ⴎ.‌1.1.𐫒; [B1, C1, V6]; xn--mnd7865gcy28g.xn--1-rgn.1.xn--7w9c; ; ; # 쥥Ⴎ.1.1.𐫒
+쥥󔏉ⴎ.‌⒈⒈𐫒; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, P1, V6] # 쥥ⴎ.⒈⒈𐫒
+쥥󔏉ⴎ.‌⒈⒈𐫒; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, P1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; xn--5kj3511ccyw3h.xn--tsha6797o; [B1, P1, V6] # 쥥ⴎ.⒈⒈𐫒
+xn--5kj3511ccyw3h.xn--tsha6797o; 쥥󔏉ⴎ.⒈⒈𐫒; [B1, V6]; xn--5kj3511ccyw3h.xn--tsha6797o; ; ; # 쥥ⴎ.⒈⒈𐫒
+xn--5kj3511ccyw3h.xn--0ug88oa0396u; 쥥󔏉ⴎ.‌⒈⒈𐫒; [B1, C1, V6]; xn--5kj3511ccyw3h.xn--0ug88oa0396u; ; ; # 쥥ⴎ.⒈⒈𐫒
+xn--mnd7865gcy28g.xn--tsha6797o; 쥥󔏉Ⴎ.⒈⒈𐫒; [B1, V6]; xn--mnd7865gcy28g.xn--tsha6797o; ; ; # 쥥Ⴎ.⒈⒈𐫒
+xn--mnd7865gcy28g.xn--0ug88oa0396u; 쥥󔏉Ⴎ.‌⒈⒈𐫒; [B1, C1, V6]; xn--mnd7865gcy28g.xn--0ug88oa0396u; ; ; # 쥥Ⴎ.⒈⒈𐫒
+ࠧ𝟶ڠ-。𑄳; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+ࠧ0ڠ-。𑄳; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+xn--0--p3d67m.xn--v80d; ࠧ0ڠ-.𑄳; [B1, B3, B6, V3, V5]; xn--0--p3d67m.xn--v80d; ; ; # ࠧ0ڠ-.𑄳
+ς.ﷁ🞛⒈; ς.فمي🞛⒈; [P1, V6]; xn--3xa.xn--dhbip2802atb20c; ; xn--4xa.xn--dhbip2802atb20c; # ς.فمي🞛⒈
+ς.فمي🞛1.; ; ; xn--3xa.xn--1-gocmu97674d.; ; xn--4xa.xn--1-gocmu97674d.; # ς.فمي🞛1.
+Σ.فمي🞛1.; σ.فمي🞛1.; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+σ.فمي🞛1.; ; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+xn--4xa.xn--1-gocmu97674d.; σ.فمي🞛1.; ; xn--4xa.xn--1-gocmu97674d.; ; ; # σ.فمي🞛1.
+xn--3xa.xn--1-gocmu97674d.; ς.فمي🞛1.; ; xn--3xa.xn--1-gocmu97674d.; ; ; # ς.فمي🞛1.
+Σ.ﷁ🞛⒈; σ.فمي🞛⒈; [P1, V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+σ.ﷁ🞛⒈; σ.فمي🞛⒈; [P1, V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+xn--4xa.xn--dhbip2802atb20c; σ.فمي🞛⒈; [V6]; xn--4xa.xn--dhbip2802atb20c; ; ; # σ.فمي🞛⒈
+xn--3xa.xn--dhbip2802atb20c; ς.فمي🞛⒈; [V6]; xn--3xa.xn--dhbip2802atb20c; ; ; # ς.فمي🞛⒈
+🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, P1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+🗩-。𐹻󐞆񥉮; 🗩-.𐹻󐞆񥉮; [B1, P1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+xn----6t3s.xn--zo0d4811u6ru6a; 🗩-.𐹻󐞆񥉮; [B1, V3, V6]; xn----6t3s.xn--zo0d4811u6ru6a; ; ; # 🗩-.𐹻
+𐡜-🔪。𝟻‌𐿀; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀
+𐡜-🔪。5‌𐿀; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; xn----5j4iv089c.xn--5-bn7i; [B1, B3] # 𐡜-🔪.5𐿀
+xn----5j4iv089c.xn--5-bn7i; 𐡜-🔪.5𐿀; [B1, B3]; xn----5j4iv089c.xn--5-bn7i; ; ; # 𐡜-🔪.5𐿀
+xn----5j4iv089c.xn--5-sgn7149h; 𐡜-🔪.5‌𐿀; [B1, B3, C1]; xn----5j4iv089c.xn--5-sgn7149h; ; ; # 𐡜-🔪.5𐿀
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍ß.ߏ0ּ; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ß.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+xn--ss-i05i7041a.xn--0-vgc50n; 𐹣늿ss.ߏ0ּ; [B1]; xn--ss-i05i7041a.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ
+xn--ss-l1tu910fo0xd.xn--0-vgc50n; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; ; # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+xn--zca770n5s4hev6c.xn--0-vgc50n; 𐹣늿‍ß.ߏ0ּ; [B1, C2]; xn--zca770n5s4hev6c.xn--0-vgc50n; ; ; # 𐹣늿ß.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍SS.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+𐹣늿‍Ss.ߏ0ּ; 𐹣늿‍ss.ߏ0ּ; [B1, C2]; xn--ss-l1tu910fo0xd.xn--0-vgc50n; ; xn--ss-i05i7041a.xn--0-vgc50n; [B1] # 𐹣늿ss.ߏ0ּ
+9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [P1, V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+9󠇥.󪴴ᢓ; 9.󪴴ᢓ; [P1, V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+9.xn--dbf91222q; 9.󪴴ᢓ; [V6]; 9.xn--dbf91222q; ; ; # 9.ᢓ
+‌ᅠ.𐫭🠗ß⽟; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--zca2289c550e0iwi; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗ß玉; ; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--zca2289c550e0iwi; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗SS玉; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗ss玉; ; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗Ss玉; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; xn--psd.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+xn--psd.xn--ss-je6eq954cp25j; ᅠ.𐫭🠗ss玉; [B2, B3, V6]; xn--psd.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--psd526e.xn--ss-je6eq954cp25j; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, V6]; xn--psd526e.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--psd526e.xn--zca2289c550e0iwi; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, V6]; xn--psd526e.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉
+‌ᅠ.𐫭🠗SS⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗ss⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+‌ᅠ.𐫭🠗Ss⽟; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, P1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; xn--cl7c.xn--ss-je6eq954cp25j; [B2, B3, P1, V6] # .𐫭🠗ss玉
+xn--cl7c.xn--ss-je6eq954cp25j; ᅠ.𐫭🠗ss玉; [B2, B3, V6]; xn--cl7c.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--0ug7719f.xn--ss-je6eq954cp25j; ‌ᅠ.𐫭🠗ss玉; [B1, B2, B3, C1, V6]; xn--0ug7719f.xn--ss-je6eq954cp25j; ; ; # .𐫭🠗ss玉
+xn--0ug7719f.xn--zca2289c550e0iwi; ‌ᅠ.𐫭🠗ß玉; [B1, B2, B3, C1, V6]; xn--0ug7719f.xn--zca2289c550e0iwi; ; ; # .𐫭🠗ß玉
+︒Ⴖͦ.‌; ︒Ⴖͦ.‌; [C1, P1, V6]; xn--hva929dl29p.xn--0ug; ; xn--hva929dl29p.; [P1, V6] # ︒Ⴖͦ.
+。Ⴖͦ.‌; .Ⴖͦ.‌; [C1, P1, V6, X4_2]; .xn--hva929d.xn--0ug; [C1, P1, V6, A4_2]; .xn--hva929d.; [P1, V6, A4_2] # .Ⴖͦ.
+。ⴖͦ.‌; .ⴖͦ.‌; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; .xn--hva754s.; [A4_2] # .ⴖͦ.
+.xn--hva754s.; .ⴖͦ.; [X4_2]; .xn--hva754s.; [A4_2]; ; # .ⴖͦ.
+.xn--hva754s.xn--0ug; .ⴖͦ.‌; [C1, X4_2]; .xn--hva754s.xn--0ug; [C1, A4_2]; ; # .ⴖͦ.
+.xn--hva929d.; .Ⴖͦ.; [V6, X4_2]; .xn--hva929d.; [V6, A4_2]; ; # .Ⴖͦ.
+.xn--hva929d.xn--0ug; .Ⴖͦ.‌; [C1, V6, X4_2]; .xn--hva929d.xn--0ug; [C1, V6, A4_2]; ; # .Ⴖͦ.
+︒ⴖͦ.‌; ︒ⴖͦ.‌; [C1, P1, V6]; xn--hva754sy94k.xn--0ug; ; xn--hva754sy94k.; [P1, V6] # ︒ⴖͦ.
+xn--hva754sy94k.; ︒ⴖͦ.; [V6]; xn--hva754sy94k.; ; ; # ︒ⴖͦ.
+xn--hva754sy94k.xn--0ug; ︒ⴖͦ.‌; [C1, V6]; xn--hva754sy94k.xn--0ug; ; ; # ︒ⴖͦ.
+xn--hva929dl29p.; ︒Ⴖͦ.; [V6]; xn--hva929dl29p.; ; ; # ︒Ⴖͦ.
+xn--hva929dl29p.xn--0ug; ︒Ⴖͦ.‌; [C1, V6]; xn--hva929dl29p.xn--0ug; ; ; # ︒Ⴖͦ.
+xn--hva754s.; ⴖͦ.; ; xn--hva754s.; ; ; # ⴖͦ.
+ⴖͦ.; ; ; xn--hva754s.; ; ; # ⴖͦ.
+Ⴖͦ.; ; [P1, V6]; xn--hva929d.; ; ; # Ⴖͦ.
+xn--hva929d.; Ⴖͦ.; [V6]; xn--hva929d.; ; ; # Ⴖͦ.
+ࢻ.‌Ⴃ𞀒; ࢻ.‌Ⴃ𞀒; [B1, C1, P1, V6]; xn--hzb.xn--bnd300f7225a; ; xn--hzb.xn--bnd2938u; [P1, V6] # ࢻ.Ⴃ𞀒
+ࢻ.‌Ⴃ𞀒; ; [B1, C1, P1, V6]; xn--hzb.xn--bnd300f7225a; ; xn--hzb.xn--bnd2938u; [P1, V6] # ࢻ.Ⴃ𞀒
+ࢻ.‌ⴃ𞀒; ; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒
+xn--hzb.xn--ukj4430l; ࢻ.ⴃ𞀒; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒
+ࢻ.ⴃ𞀒; ; ; xn--hzb.xn--ukj4430l; ; ; # ࢻ.ⴃ𞀒
+ࢻ.Ⴃ𞀒; ; [P1, V6]; xn--hzb.xn--bnd2938u; ; ; # ࢻ.Ⴃ𞀒
+xn--hzb.xn--bnd2938u; ࢻ.Ⴃ𞀒; [V6]; xn--hzb.xn--bnd2938u; ; ; # ࢻ.Ⴃ𞀒
+xn--hzb.xn--0ug822cp045a; ࢻ.‌ⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; ; # ࢻ.ⴃ𞀒
+xn--hzb.xn--bnd300f7225a; ࢻ.‌Ⴃ𞀒; [B1, C1, V6]; xn--hzb.xn--bnd300f7225a; ; ; # ࢻ.Ⴃ𞀒
+ࢻ.‌ⴃ𞀒; ࢻ.‌ⴃ𞀒; [B1, C1]; xn--hzb.xn--0ug822cp045a; ; xn--hzb.xn--ukj4430l; [] # ࢻ.ⴃ𞀒
+‍‌。2䫷󠧷; ‍‌.2䫷󠧷; [C1, C2, P1, V6]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [P1, V6, A4_2] # .2䫷
+‍‌。2䫷󠧷; ‍‌.2䫷󠧷; [C1, C2, P1, V6]; xn--0ugb.xn--2-me5ay1273i; ; .xn--2-me5ay1273i; [P1, V6, A4_2] # .2䫷
+.xn--2-me5ay1273i; .2䫷󠧷; [V6, X4_2]; .xn--2-me5ay1273i; [V6, A4_2]; ; # .2䫷
+xn--0ugb.xn--2-me5ay1273i; ‍‌.2䫷󠧷; [C1, C2, V6]; xn--0ugb.xn--2-me5ay1273i; ; ; # .2䫷
+-𞀤󜠐。򈬖; -𞀤󜠐.򈬖; [P1, V3, V6]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤.
+xn----rq4re4997d.xn--l707b; -𞀤󜠐.򈬖; [V3, V6]; xn----rq4re4997d.xn--l707b; ; ; # -𞀤.
+󳛂︒‌㟀.ؤ⒈; 󳛂︒‌㟀.ؤ⒈; [C1, P1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [P1, V6] # ︒㟀.ؤ⒈
+󳛂︒‌㟀.ؤ⒈; 󳛂︒‌㟀.ؤ⒈; [C1, P1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; xn--etlt457ccrq7h.xn--jgb476m; [P1, V6] # ︒㟀.ؤ⒈
+󳛂。‌㟀.ؤ1.; 󳛂.‌㟀.ؤ1.; [B1, C1, P1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; xn--z272f.xn--etl.xn--1-smc.; [P1, V6] # .㟀.ؤ1.
+󳛂。‌㟀.ؤ1.; 󳛂.‌㟀.ؤ1.; [B1, C1, P1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; xn--z272f.xn--etl.xn--1-smc.; [P1, V6] # .㟀.ؤ1.
+xn--z272f.xn--etl.xn--1-smc.; 󳛂.㟀.ؤ1.; [V6]; xn--z272f.xn--etl.xn--1-smc.; ; ; # .㟀.ؤ1.
+xn--z272f.xn--0ug754g.xn--1-smc.; 󳛂.‌㟀.ؤ1.; [B1, C1, V6]; xn--z272f.xn--0ug754g.xn--1-smc.; ; ; # .㟀.ؤ1.
+xn--etlt457ccrq7h.xn--jgb476m; 󳛂︒㟀.ؤ⒈; [V6]; xn--etlt457ccrq7h.xn--jgb476m; ; ; # ︒㟀.ؤ⒈
+xn--0ug754gxl4ldlt0k.xn--jgb476m; 󳛂︒‌㟀.ؤ⒈; [C1, V6]; xn--0ug754gxl4ldlt0k.xn--jgb476m; ; ; # ︒㟀.ؤ⒈
+𑲜ߊ𝅼。-‍; 𑲜ߊ𝅼.-‍; [B1, C2, V3, V5]; xn--lsb5482l7nre.xn----ugn; ; xn--lsb5482l7nre.-; [B1, V3, V5] # 𑲜ߊ𝅼.-
+xn--lsb5482l7nre.-; 𑲜ߊ𝅼.-; [B1, V3, V5]; xn--lsb5482l7nre.-; ; ; # 𑲜ߊ𝅼.-
+xn--lsb5482l7nre.xn----ugn; 𑲜ߊ𝅼.-‍; [B1, C2, V3, V5]; xn--lsb5482l7nre.xn----ugn; ; ; # 𑲜ߊ𝅼.-
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.Ⴉ≠𐫶; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--hnd481gv73o; ; .xn--hnd481gv73o; [B5, B6, P1, V6, A4_2] # .Ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+‌.ⴉ≠𐫶; ; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+.xn--1chx23bzj4p; .ⴉ≠𐫶; [B5, B6, V6, X4_2]; .xn--1chx23bzj4p; [B5, B6, V6, A4_2]; ; # .ⴉ≠𐫶
+xn--0ug.xn--1chx23bzj4p; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, V6]; xn--0ug.xn--1chx23bzj4p; ; ; # .ⴉ≠𐫶
+.xn--hnd481gv73o; .Ⴉ≠𐫶; [B5, B6, V6, X4_2]; .xn--hnd481gv73o; [B5, B6, V6, A4_2]; ; # .Ⴉ≠𐫶
+xn--0ug.xn--hnd481gv73o; ‌.Ⴉ≠𐫶; [B1, B5, B6, C1, V6]; xn--0ug.xn--hnd481gv73o; ; ; # .Ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+‌.ⴉ≠𐫶; ‌.ⴉ≠𐫶; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--1chx23bzj4p; ; .xn--1chx23bzj4p; [B5, B6, P1, V6, A4_2] # .ⴉ≠𐫶
+ݐ。≯ς; ݐ.≯ς; [B1, P1, V6]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς
+ݐ。≯ς; ݐ.≯ς; [B1, P1, V6]; xn--3ob.xn--3xa918m; ; xn--3ob.xn--4xa718m; # ݐ.≯ς
+ݐ。≯Σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯Σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+ݐ。≯σ; ݐ.≯σ; [B1, P1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+xn--3ob.xn--4xa718m; ݐ.≯σ; [B1, V6]; xn--3ob.xn--4xa718m; ; ; # ݐ.≯σ
+xn--3ob.xn--3xa918m; ݐ.≯ς; [B1, V6]; xn--3ob.xn--3xa918m; ; ; # ݐ.≯ς
+߼𐸆.𓖏︒񊨩Ⴐ; ; [P1, V6]; xn--0tb8725k.xn--ond3562jt18a7py9c; ; ; # .︒Ⴐ
+߼𐸆.𓖏。񊨩Ⴐ; ߼𐸆.𓖏.񊨩Ⴐ; [P1, V6]; xn--0tb8725k.xn--tu8d.xn--ond97931d; ; ; # ..Ⴐ
+߼𐸆.𓖏。񊨩ⴐ; ߼𐸆.𓖏.񊨩ⴐ; [P1, V6]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # ..ⴐ
+xn--0tb8725k.xn--tu8d.xn--7kj73887a; ߼𐸆.𓖏.񊨩ⴐ; [V6]; xn--0tb8725k.xn--tu8d.xn--7kj73887a; ; ; # ..ⴐ
+xn--0tb8725k.xn--tu8d.xn--ond97931d; ߼𐸆.𓖏.񊨩Ⴐ; [V6]; xn--0tb8725k.xn--tu8d.xn--ond97931d; ; ; # ..Ⴐ
+߼𐸆.𓖏︒񊨩ⴐ; ; [P1, V6]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .︒ⴐ
+xn--0tb8725k.xn--7kj9008dt18a7py9c; ߼𐸆.𓖏︒񊨩ⴐ; [V6]; xn--0tb8725k.xn--7kj9008dt18a7py9c; ; ; # .︒ⴐ
+xn--0tb8725k.xn--ond3562jt18a7py9c; ߼𐸆.𓖏︒񊨩Ⴐ; [V6]; xn--0tb8725k.xn--ond3562jt18a7py9c; ; ; # .︒Ⴐ
+Ⴥ⚭󠖫⋃。𑌼; Ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+Ⴥ⚭󠖫⋃。𑌼; Ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+xn--vfh16m67gx1162b.xn--ro1d; ⴥ⚭󠖫⋃.𑌼; [V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+xn--9nd623g4zc5z060c.xn--ro1d; Ⴥ⚭󠖫⋃.𑌼; [V5, V6]; xn--9nd623g4zc5z060c.xn--ro1d; ; ; # Ⴥ⚭⋃.𑌼
+ⴥ⚭󠖫⋃。𑌼; ⴥ⚭󠖫⋃.𑌼; [P1, V5, V6]; xn--vfh16m67gx1162b.xn--ro1d; ; ; # ⴥ⚭⋃.𑌼
+🄈。󠷳ࡄ; 🄈.󠷳ࡄ; [B1, P1, V6]; xn--107h.xn--2vb13094p; ; ; # 🄈.ࡄ
+7,。󠷳ࡄ; 7,.󠷳ࡄ; [B1, P1, V6]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ
+7,.xn--2vb13094p; 7,.󠷳ࡄ; [B1, P1, V6]; 7,.xn--2vb13094p; ; ; # 7,.ࡄ
+xn--107h.xn--2vb13094p; 🄈.󠷳ࡄ; [B1, V6]; xn--107h.xn--2vb13094p; ; ; # 🄈.ࡄ
+≮ࡆ。섖쮖ß; ≮ࡆ.섖쮖ß; [B1, P1, V6]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß
+≮ࡆ。섖쮖ß; ≮ࡆ.섖쮖ß; [B1, P1, V6]; xn--4vb505k.xn--zca7259goug; ; xn--4vb505k.xn--ss-5z4j006a; # ≮ࡆ.섖쮖ß
+≮ࡆ。섖쮖SS; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖SS; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+xn--4vb505k.xn--ss-5z4j006a; ≮ࡆ.섖쮖ss; [B1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖Ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+≮ࡆ。섖쮖Ss; ≮ࡆ.섖쮖ss; [B1, P1, V6]; xn--4vb505k.xn--ss-5z4j006a; ; ; # ≮ࡆ.섖쮖ss
+xn--4vb505k.xn--zca7259goug; ≮ࡆ.섖쮖ß; [B1, V6]; xn--4vb505k.xn--zca7259goug; ; ; # ≮ࡆ.섖쮖ß
+󠆓⛏-。ꡒ; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ
+xn----o9p.xn--rc9a; ⛏-.ꡒ; [V3]; xn----o9p.xn--rc9a; ; ; # ⛏-.ꡒ
+޻𐹳ئ𑁆。ࢧڰ‌ᢒ; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, P1, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ
+޻𐹳ئ𑁆。ࢧڰ‌ᢒ; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, P1, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; xn--lgb32f2753cosb.xn--jkb91hlz1a; # 𐹳ئ𑁆.ࢧڰᢒ
+xn--lgb32f2753cosb.xn--jkb91hlz1a; ޻𐹳ئ𑁆.ࢧڰᢒ; [B2, B3, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1a; ; ; # 𐹳ئ𑁆.ࢧڰᢒ
+xn--lgb32f2753cosb.xn--jkb91hlz1azih; ޻𐹳ئ𑁆.ࢧڰ‌ᢒ; [B2, B3, V6]; xn--lgb32f2753cosb.xn--jkb91hlz1azih; ; ; # 𐹳ئ𑁆.ࢧڰᢒ
+ࠖ.𐨕𚚕; ; [B1, B2, B3, B6, P1, V5, V6]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕
+xn--rub.xn--tr9c248x; ࠖ.𐨕𚚕; [B1, B2, B3, B6, V5, V6]; xn--rub.xn--tr9c248x; ; ; # ࠖ.𐨕
+--。𽊆ݧ𐽋𞠬; --.𽊆ݧ𐽋𞠬; [B1, B5, B6, P1, V3, V6]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬
+--.xn--rpb6226k77pfh58p; --.𽊆ݧ𐽋𞠬; [B1, B5, B6, V3, V6]; --.xn--rpb6226k77pfh58p; ; ; # --.ݧ𐽋𞠬
+򛭦𐋥𹸐.≯ࢰࢦ󔛣; ; [B1, P1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+򛭦𐋥𹸐.≯ࢰࢦ󔛣; 򛭦𐋥𹸐.≯ࢰࢦ󔛣; [B1, P1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+xn--887c2298i5mv6a.xn--vybt688qm8981a; 򛭦𐋥𹸐.≯ࢰࢦ󔛣; [B1, V6]; xn--887c2298i5mv6a.xn--vybt688qm8981a; ; ; # 𐋥.≯ࢰࢦ
+䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, P1, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+䔛󠇒򤸞𐹧.-䤷; 䔛򤸞𐹧.-䤷; [B1, B5, B6, P1, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+xn--2loy662coo60e.xn----0n4a; 䔛򤸞𐹧.-䤷; [B1, B5, B6, V3, V6]; xn--2loy662coo60e.xn----0n4a; ; ; # 䔛𐹧.-䤷
+𐹩.‍-; 𐹩.‍-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.-
+𐹩.‍-; ; [B1, C2, V3]; xn--ho0d.xn----tgn; ; xn--ho0d.-; [B1, V3] # 𐹩.-
+xn--ho0d.-; 𐹩.-; [B1, V3]; xn--ho0d.-; ; ; # 𐹩.-
+xn--ho0d.xn----tgn; 𐹩.‍-; [B1, C2, V3]; xn--ho0d.xn----tgn; ; ; # 𐹩.-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+񂈦帷。≯萺᷈-; 񂈦帷.≯萺᷈-; [P1, V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+xn--qutw175s.xn----mimu6tf67j; 񂈦帷.≯萺᷈-; [V3, V6]; xn--qutw175s.xn----mimu6tf67j; ; ; # 帷.≯萺᷈-
+‍攌꯭。ᢖ-Ⴘ; ‍攌꯭.ᢖ-Ⴘ; [C2, P1, V6]; xn--1ug592ykp6b.xn----k1g451d; ; xn--p9ut19m.xn----k1g451d; [P1, V6] # 攌꯭.ᢖ-Ⴘ
+‍攌꯭。ᢖ-ⴘ; ‍攌꯭.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; xn--p9ut19m.xn----mck373i; [] # 攌꯭.ᢖ-ⴘ
+xn--p9ut19m.xn----mck373i; 攌꯭.ᢖ-ⴘ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+攌꯭.ᢖ-ⴘ; ; ; xn--p9ut19m.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+攌꯭.ᢖ-Ⴘ; ; [P1, V6]; xn--p9ut19m.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+xn--p9ut19m.xn----k1g451d; 攌꯭.ᢖ-Ⴘ; [V6]; xn--p9ut19m.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+xn--1ug592ykp6b.xn----mck373i; ‍攌꯭.ᢖ-ⴘ; [C2]; xn--1ug592ykp6b.xn----mck373i; ; ; # 攌꯭.ᢖ-ⴘ
+xn--1ug592ykp6b.xn----k1g451d; ‍攌꯭.ᢖ-Ⴘ; [C2, V6]; xn--1ug592ykp6b.xn----k1g451d; ; ; # 攌꯭.ᢖ-Ⴘ
+‌ꖨ.⒗3툒۳; ‌ꖨ.⒗3툒۳; [C1, P1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [P1, V6] # ꖨ.⒗3툒۳
+‌ꖨ.⒗3툒۳; ‌ꖨ.⒗3툒۳; [C1, P1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; xn--9r8a.xn--3-nyc678tu07m; [P1, V6] # ꖨ.⒗3툒۳
+‌ꖨ.16.3툒۳; ; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳
+‌ꖨ.16.3툒۳; ‌ꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; xn--9r8a.16.xn--3-nyc0117m; [] # ꖨ.16.3툒۳
+xn--9r8a.16.xn--3-nyc0117m; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+ꖨ.16.3툒۳; ; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+ꖨ.16.3툒۳; ꖨ.16.3툒۳; ; xn--9r8a.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+xn--0ug2473c.16.xn--3-nyc0117m; ‌ꖨ.16.3툒۳; [C1]; xn--0ug2473c.16.xn--3-nyc0117m; ; ; # ꖨ.16.3툒۳
+xn--9r8a.xn--3-nyc678tu07m; ꖨ.⒗3툒۳; [V6]; xn--9r8a.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳
+xn--0ug2473c.xn--3-nyc678tu07m; ‌ꖨ.⒗3툒۳; [C1, V6]; xn--0ug2473c.xn--3-nyc678tu07m; ; ; # ꖨ.⒗3툒۳
+⒈걾6.𐱁ې; ; [B1, P1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+⒈걾6.𐱁ې; ⒈걾6.𐱁ې; [B1, P1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+1.걾6.𐱁ې; ; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+1.걾6.𐱁ې; 1.걾6.𐱁ې; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+1.xn--6-945e.xn--glb1794k; 1.걾6.𐱁ې; [B1]; 1.xn--6-945e.xn--glb1794k; ; ; # 1.걾6.𐱁ې
+xn--6-dcps419c.xn--glb1794k; ⒈걾6.𐱁ې; [B1, V6]; xn--6-dcps419c.xn--glb1794k; ; ; # ⒈걾6.𐱁ې
+𐲞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐲞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞0≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞0≮≮.󠀧ع; ; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+xn--0-ngoa5711v.xn--4gb31034p; 𐳞0≮≮.󠀧ع; [B1, B3, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+𐳞𝟶≮≮.󠀧ع; 𐳞0≮≮.󠀧ع; [B1, B3, P1, V6]; xn--0-ngoa5711v.xn--4gb31034p; ; ; # 𐳞0≮≮.ع
+ૣ.𐹺ᅟ; ; [B1, B3, B6, P1, V5, V6]; xn--8fc.xn--osd3070k; ; ; # ૣ.𐹺
+xn--8fc.xn--osd3070k; ૣ.𐹺ᅟ; [B1, B3, B6, V5, V6]; xn--8fc.xn--osd3070k; ; ; # ૣ.𐹺
+𝟏𝨙⸖.‍; 1𝨙⸖.‍; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [] # 1𝨙⸖.
+1𝨙⸖.‍; ; [C2]; xn--1-5bt6845n.xn--1ug; ; xn--1-5bt6845n.; [] # 1𝨙⸖.
+xn--1-5bt6845n.; 1𝨙⸖.; ; xn--1-5bt6845n.; ; ; # 1𝨙⸖.
+1𝨙⸖.; ; ; xn--1-5bt6845n.; ; ; # 1𝨙⸖.
+xn--1-5bt6845n.xn--1ug; 1𝨙⸖.‍; [C2]; xn--1-5bt6845n.xn--1ug; ; ; # 1𝨙⸖.
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤐≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+xn--wnb859grzfzw60c.xn----kcd; 𞤲≠ܦ᩠.-ߕ; [B1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd; ; ; # 𞤲≠ܦ᩠.-ߕ
+xn--wnb859grzfzw60c.xn----kcd017p; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; ; # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𞤲≠ܦ᩠。-‌ߕ; 𞤲≠ܦ᩠.-‌ߕ; [B1, C1, P1, V3, V6]; xn--wnb859grzfzw60c.xn----kcd017p; ; xn--wnb859grzfzw60c.xn----kcd; [B1, P1, V3, V6] # 𞤲≠ܦ᩠.-ߕ
+𐹰ͨ-ꡧ。ٵ; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+𐹰ͨ-ꡧ。اٴ; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+xn----shb2387jgkqd.xn--mgb8m; 𐹰ͨ-ꡧ.اٴ; [B1]; xn----shb2387jgkqd.xn--mgb8m; ; ; # 𐹰ͨ-ꡧ.اٴ
+F󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+F󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+f󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+f.xn--45hz6953f; f.򏗅♚; [V6]; f.xn--45hz6953f; ; ; # f.♚
+f󠅟。򏗅♚; f.򏗅♚; [P1, V6]; f.xn--45hz6953f; ; ; # f.♚
+୍𑄴ᷩ。𝟮Ⴘ𞀨񃥇; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。2Ⴘ𞀨񃥇; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。2ⴘ𞀨񃥇; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+xn--9ic246gs21p.xn--2-nws2918ndrjr; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+xn--9ic246gs21p.xn--2-k1g43076adrwq; ୍𑄴ᷩ.2Ⴘ𞀨񃥇; [V5, V6]; xn--9ic246gs21p.xn--2-k1g43076adrwq; ; ; # ୍𑄴ᷩ.2Ⴘ𞀨
+୍𑄴ᷩ。𝟮ⴘ𞀨񃥇; ୍𑄴ᷩ.2ⴘ𞀨񃥇; [P1, V5, V6]; xn--9ic246gs21p.xn--2-nws2918ndrjr; ; ; # ୍𑄴ᷩ.2ⴘ𞀨
+򓠭‌‌⒈。勉𑁅; 򓠭‌‌⒈.勉𑁅; [C1, P1, V6]; xn--0uga855aez302a.xn--4grs325b; ; xn--tsh11906f.xn--4grs325b; [P1, V6] # ⒈.勉𑁅
+򓠭‌‌1.。勉𑁅; 򓠭‌‌1..勉𑁅; [C1, P1, V6, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, P1, V6, A4_2]; xn--1-yi00h..xn--4grs325b; [P1, V6, A4_2] # 1..勉𑁅
+xn--1-yi00h..xn--4grs325b; 򓠭1..勉𑁅; [V6, X4_2]; xn--1-yi00h..xn--4grs325b; [V6, A4_2]; ; # 1..勉𑁅
+xn--1-rgna61159u..xn--4grs325b; 򓠭‌‌1..勉𑁅; [C1, V6, X4_2]; xn--1-rgna61159u..xn--4grs325b; [C1, V6, A4_2]; ; # 1..勉𑁅
+xn--tsh11906f.xn--4grs325b; 򓠭⒈.勉𑁅; [V6]; xn--tsh11906f.xn--4grs325b; ; ; # ⒈.勉𑁅
+xn--0uga855aez302a.xn--4grs325b; 򓠭‌‌⒈.勉𑁅; [C1, V6]; xn--0uga855aez302a.xn--4grs325b; ; ; # ⒈.勉𑁅
+ᡃ.玿񫈜󕞐; ; [P1, V6]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿
+xn--27e.xn--7cy81125a0yq4a; ᡃ.玿񫈜󕞐; [V6]; xn--27e.xn--7cy81125a0yq4a; ; ; # ᡃ.玿
+‌‌。⒈≯𝟵; ‌‌.⒈≯9; [C1, P1, V6]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [P1, V6, A4_2] # .⒈≯9
+‌‌。⒈≯𝟵; ‌‌.⒈≯9; [C1, P1, V6]; xn--0uga.xn--9-ogo37g; ; .xn--9-ogo37g; [P1, V6, A4_2] # .⒈≯9
+‌‌。1.≯9; ‌‌.1.≯9; [C1, P1, V6]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [P1, V6, A4_2] # .1.≯9
+‌‌。1.≯9; ‌‌.1.≯9; [C1, P1, V6]; xn--0uga.1.xn--9-ogo; ; .1.xn--9-ogo; [P1, V6, A4_2] # .1.≯9
+.1.xn--9-ogo; .1.≯9; [V6, X4_2]; .1.xn--9-ogo; [V6, A4_2]; ; # .1.≯9
+xn--0uga.1.xn--9-ogo; ‌‌.1.≯9; [C1, V6]; xn--0uga.1.xn--9-ogo; ; ; # .1.≯9
+.xn--9-ogo37g; .⒈≯9; [V6, X4_2]; .xn--9-ogo37g; [V6, A4_2]; ; # .⒈≯9
+xn--0uga.xn--9-ogo37g; ‌‌.⒈≯9; [C1, V6]; xn--0uga.xn--9-ogo37g; ; ; # .⒈≯9
+ᅟᷠ򐀁.𺻆≯𐮁; ; [B5, B6, P1, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+ᅟᷠ򐀁.𺻆≯𐮁; ᅟᷠ򐀁.𺻆≯𐮁; [B5, B6, P1, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+xn--osd615d5659o.xn--hdh5192gkm6r; ᅟᷠ򐀁.𺻆≯𐮁; [B5, B6, V6]; xn--osd615d5659o.xn--hdh5192gkm6r; ; ; # ᷠ.≯𐮁
+󠄫𝩤‍ؾ.𝩩-ࠞ󑼩; 𝩤‍ؾ.𝩩-ࠞ󑼩; [B1, C2, P1, V5, V6]; xn--9gb723kg862a.xn----qgd52296avol4f; ; xn--9gb5080v.xn----qgd52296avol4f; [B1, P1, V5, V6] # 𝩤ؾ.𝩩-ࠞ
+xn--9gb5080v.xn----qgd52296avol4f; 𝩤ؾ.𝩩-ࠞ󑼩; [B1, V5, V6]; xn--9gb5080v.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ
+xn--9gb723kg862a.xn----qgd52296avol4f; 𝩤‍ؾ.𝩩-ࠞ󑼩; [B1, C2, V5, V6]; xn--9gb723kg862a.xn----qgd52296avol4f; ; ; # 𝩤ؾ.𝩩-ࠞ
+⃚.𑘿-; ⃚.𑘿-; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+⃚.𑘿-; ; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+xn--w0g.xn----bd0j; ⃚.𑘿-; [V3, V5]; xn--w0g.xn----bd0j; ; ; # ⃚.𑘿-
+䮸ß.󠵟󠭎紙ࢨ; ; [B1, P1, V6]; xn--zca5349a.xn--xyb1370div70kpzba; ; xn--ss-sf1c.xn--xyb1370div70kpzba; # 䮸ß.紙ࢨ
+䮸SS.󠵟󠭎紙ࢨ; 䮸ss.󠵟󠭎紙ࢨ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+䮸ss.󠵟󠭎紙ࢨ; ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+䮸Ss.󠵟󠭎紙ࢨ; 䮸ss.󠵟󠭎紙ࢨ; [B1, P1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+xn--ss-sf1c.xn--xyb1370div70kpzba; 䮸ss.󠵟󠭎紙ࢨ; [B1, V6]; xn--ss-sf1c.xn--xyb1370div70kpzba; ; ; # 䮸ss.紙ࢨ
+xn--zca5349a.xn--xyb1370div70kpzba; 䮸ß.󠵟󠭎紙ࢨ; [B1, V6]; xn--zca5349a.xn--xyb1370div70kpzba; ; ; # 䮸ß.紙ࢨ
+-Ⴞ.-𝩨⅔𐦕; -Ⴞ.-𝩨2⁄3𐦕; [B1, P1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-Ⴞ.-𝩨2⁄3𐦕; ; [B1, P1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-ⴞ.-𝩨2⁄3𐦕; ; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+xn----zws.xn---23-pt0a0433lk3jj; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+xn----w1g.xn---23-pt0a0433lk3jj; -Ⴞ.-𝩨2⁄3𐦕; [B1, V3, V6]; xn----w1g.xn---23-pt0a0433lk3jj; ; ; # -Ⴞ.-𝩨2⁄3𐦕
+-ⴞ.-𝩨⅔𐦕; -ⴞ.-𝩨2⁄3𐦕; [B1, V3]; xn----zws.xn---23-pt0a0433lk3jj; ; ; # -ⴞ.-𝩨2⁄3𐦕
+󧈯𐹯ૂ。򖢨𐮁񇼖ᡂ; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, P1, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+󧈯𐹯ૂ。򖢨𐮁񇼖ᡂ; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, P1, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; 󧈯𐹯ૂ.򖢨𐮁񇼖ᡂ; [B5, B6, V6]; xn--bfc7604kv8m3g.xn--17e5565jl7zw4h16a; ; ; # 𐹯ૂ.𐮁ᡂ
+ႂ-‍꣪.ꡊ‍񼸳; ႂ-‍꣪.ꡊ‍񼸳; [C2, P1, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [P1, V5, V6] # ႂ-꣪.ꡊ
+ႂ-‍꣪.ꡊ‍񼸳; ; [C2, P1, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; xn----gyg3618i.xn--jc9ao4185a; [P1, V5, V6] # ႂ-꣪.ꡊ
+xn----gyg3618i.xn--jc9ao4185a; ႂ-꣪.ꡊ񼸳; [V5, V6]; xn----gyg3618i.xn--jc9ao4185a; ; ; # ႂ-꣪.ꡊ
+xn----gyg250jio7k.xn--1ug8774cri56d; ႂ-‍꣪.ꡊ‍񼸳; [C2, V5, V6]; xn----gyg250jio7k.xn--1ug8774cri56d; ; ; # ႂ-꣪.ꡊ
+۱。≠٨; ۱.≠٨; [B1, P1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+۱。≠٨; ۱.≠٨; [B1, P1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+xn--emb.xn--hib334l; ۱.≠٨; [B1, V6]; xn--emb.xn--hib334l; ; ; # ۱.≠٨
+𑈵廊.𐠍; ; [V5]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍
+xn--xytw701b.xn--yc9c; 𑈵廊.𐠍; [V5]; xn--xytw701b.xn--yc9c; ; ; # 𑈵廊.𐠍
+‍͖-.-Ⴐ١; ‍͖-.-Ⴐ١; [B1, C2, P1, V3, V6]; xn----rgb661t.xn----bqc030f; ; xn----rgb.xn----bqc030f; [B1, P1, V3, V5, V6] # ͖-.-Ⴐ١
+‍͖-.-Ⴐ١; ; [B1, C2, P1, V3, V6]; xn----rgb661t.xn----bqc030f; ; xn----rgb.xn----bqc030f; [B1, P1, V3, V5, V6] # ͖-.-Ⴐ١
+‍͖-.-ⴐ١; ; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V5] # ͖-.-ⴐ١
+xn----rgb.xn----bqc2280a; ͖-.-ⴐ١; [B1, V3, V5]; xn----rgb.xn----bqc2280a; ; ; # ͖-.-ⴐ١
+xn----rgb661t.xn----bqc2280a; ‍͖-.-ⴐ١; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; ; # ͖-.-ⴐ١
+xn----rgb.xn----bqc030f; ͖-.-Ⴐ١; [B1, V3, V5, V6]; xn----rgb.xn----bqc030f; ; ; # ͖-.-Ⴐ١
+xn----rgb661t.xn----bqc030f; ‍͖-.-Ⴐ١; [B1, C2, V3, V6]; xn----rgb661t.xn----bqc030f; ; ; # ͖-.-Ⴐ١
+‍͖-.-ⴐ١; ‍͖-.-ⴐ١; [B1, C2, V3]; xn----rgb661t.xn----bqc2280a; ; xn----rgb.xn----bqc2280a; [B1, V3, V5] # ͖-.-ⴐ١
+غ١挏󾯐.-; ; [B1, B2, B3, P1, V3, V6]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.-
+xn--5gb2f4205aqi47p.-; غ١挏󾯐.-; [B1, B2, B3, V3, V6]; xn--5gb2f4205aqi47p.-; ; ; # غ١挏.-
+ۯ。𐹧𞤽; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤽; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤛; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+xn--cmb.xn--fo0dy848a; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+ۯ。𐹧𞤛; ۯ.𐹧𞤽; [B1]; xn--cmb.xn--fo0dy848a; ; ; # ۯ.𐹧𞤽
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; ; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+Ⴞ𶛀𛗻.ᢗ릫; Ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+xn--mlj0486jgl2j.xn--hbf6853f; ⴞ𶛀𛗻.ᢗ릫; [V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+xn--2nd8876sgl2j.xn--hbf6853f; Ⴞ𶛀𛗻.ᢗ릫; [V6]; xn--2nd8876sgl2j.xn--hbf6853f; ; ; # Ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+ⴞ𶛀𛗻.ᢗ릫; ⴞ𶛀𛗻.ᢗ릫; [P1, V6]; xn--mlj0486jgl2j.xn--hbf6853f; ; ; # ⴞ.ᢗ릫
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+󠎃󗭞ڷ𐹷。≯‌᷾; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, P1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; xn--qkb4516kbi06fg2id.xn--zfg31q; [B1, P1, V6] # ڷ𐹷.≯᷾
+xn--qkb4516kbi06fg2id.xn--zfg31q; 󠎃󗭞ڷ𐹷.≯᷾; [B1, V6]; xn--qkb4516kbi06fg2id.xn--zfg31q; ; ; # ڷ𐹷.≯᷾
+xn--qkb4516kbi06fg2id.xn--zfg59fm0c; 󠎃󗭞ڷ𐹷.≯‌᷾; [B1, C1, V6]; xn--qkb4516kbi06fg2id.xn--zfg59fm0c; ; ; # ڷ𐹷.≯᷾
+ᛎ󠅍󠐕‍。𐹾𐹪𐻝-; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, P1, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, P1, V3, V6] # ᛎ.𐹾𐹪-
+ᛎ󠅍󠐕‍。𐹾𐹪𐻝-; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, P1, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; xn--fxe63563p.xn----q26i2bvu; [B1, B6, P1, V3, V6] # ᛎ.𐹾𐹪-
+xn--fxe63563p.xn----q26i2bvu; ᛎ󠐕.𐹾𐹪𐻝-; [B1, B6, V3, V6]; xn--fxe63563p.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪-
+xn--fxe848bq3411a.xn----q26i2bvu; ᛎ󠐕‍.𐹾𐹪𐻝-; [B1, B6, C2, V3, V6]; xn--fxe848bq3411a.xn----q26i2bvu; ; ; # ᛎ.𐹾𐹪-
+𐹶.𐫂; ; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂
+xn--uo0d.xn--rw9c; 𐹶.𐫂; [B1]; xn--uo0d.xn--rw9c; ; ; # 𐹶.𐫂
+ß‍်。⒈; ß‍်.⒈; [C2, P1, V6]; xn--zca679eh2l.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ß်.⒈
+ß‍်。1.; ß‍်.1.; [C2]; xn--zca679eh2l.1.; ; xn--ss-f4j.1.; [] # ß်.1.
+SS‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+ss‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+Ss‍်。1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; xn--ss-f4j.1.; [] # ss်.1.
+xn--ss-f4j.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+ss်.1.; ; ; xn--ss-f4j.1.; ; ; # ss်.1.
+SS်.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+Ss်.1.; ss်.1.; ; xn--ss-f4j.1.; ; ; # ss်.1.
+xn--ss-f4j585j.1.; ss‍်.1.; [C2]; xn--ss-f4j585j.1.; ; ; # ss်.1.
+xn--zca679eh2l.1.; ß‍်.1.; [C2]; xn--zca679eh2l.1.; ; ; # ß်.1.
+SS‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+ss‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+Ss‍်。⒈; ss‍်.⒈; [C2, P1, V6]; xn--ss-f4j585j.xn--tsh; ; xn--ss-f4j.xn--tsh; [P1, V6] # ss်.⒈
+xn--ss-f4j.xn--tsh; ss်.⒈; [V6]; xn--ss-f4j.xn--tsh; ; ; # ss်.⒈
+xn--ss-f4j585j.xn--tsh; ss‍်.⒈; [C2, V6]; xn--ss-f4j585j.xn--tsh; ; ; # ss်.⒈
+xn--zca679eh2l.xn--tsh; ß‍်.⒈; [C2, V6]; xn--zca679eh2l.xn--tsh; ; ; # ß်.⒈
+୍‌𙶵𞻘。‍; ୍‌𙶵𞻘.‍; [B1, C2, P1, V5, V6]; xn--9ic637hz82z32jc.xn--1ug; ; xn--9ic6417rn4xb.; [B1, P1, V5, V6] # ୍.
+xn--9ic6417rn4xb.; ୍𙶵𞻘.; [B1, V5, V6]; xn--9ic6417rn4xb.; ; ; # ୍.
+xn--9ic637hz82z32jc.xn--1ug; ୍‌𙶵𞻘.‍; [B1, C2, V5, V6]; xn--9ic637hz82z32jc.xn--1ug; ; ; # ୍.
+𐮅。ڼ🁕; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+𐮅。ڼ🁕; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+xn--c29c.xn--vkb8871w; 𐮅.ڼ🁕; [B3]; xn--c29c.xn--vkb8871w; ; ; # 𐮅.ڼ🁕
+ؠ្。𐫔󠀧‌𑈵; ؠ្.𐫔󠀧‌𑈵; [B2, B3, C1, P1, V6]; xn--fgb471g.xn--0ug9853g7verp838a; ; xn--fgb471g.xn--9w9c29jw3931a; [B2, B3, P1, V6] # ؠ្.𐫔𑈵
+xn--fgb471g.xn--9w9c29jw3931a; ؠ្.𐫔󠀧𑈵; [B2, B3, V6]; xn--fgb471g.xn--9w9c29jw3931a; ; ; # ؠ្.𐫔𑈵
+xn--fgb471g.xn--0ug9853g7verp838a; ؠ្.𐫔󠀧‌𑈵; [B2, B3, C1, V6]; xn--fgb471g.xn--0ug9853g7verp838a; ; ; # ؠ្.𐫔𑈵
+񋉕.𞣕𞤊; 񋉕.𞣕𞤬; [B1, P1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+񋉕.𞣕𞤬; ; [B1, P1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+xn--tf5w.xn--2b6hof; 񋉕.𞣕𞤬; [B1, V5, V6]; xn--tf5w.xn--2b6hof; ; ; # .𞣕𞤬
+ی𐨿.ß྄𑍬; ی𐨿.ß྄𑍬; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬
+ی𐨿.ß྄𑍬; ; ; xn--clb2593k.xn--zca216edt0r; ; xn--clb2593k.xn--ss-toj6092t; # ی𐨿.ß྄𑍬
+ی𐨿.SS྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.ss྄𑍬; ; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+xn--clb2593k.xn--ss-toj6092t; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+xn--clb2593k.xn--zca216edt0r; ی𐨿.ß྄𑍬; ; xn--clb2593k.xn--zca216edt0r; ; ; # ی𐨿.ß྄𑍬
+ی𐨿.SS྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.Ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+ی𐨿.Ss྄𑍬; ی𐨿.ss྄𑍬; ; xn--clb2593k.xn--ss-toj6092t; ; ; # ی𐨿.ss྄𑍬
+𝟠≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+𝟠≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+8≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+8≮‌。󠅱឴; 8≮‌.឴; [C1, P1, V5, V6]; xn--8-sgn10i.xn--z3e; ; xn--8-ngo.xn--z3e; [P1, V5, V6] # 8≮.
+xn--8-ngo.xn--z3e; 8≮.឴; [V5, V6]; xn--8-ngo.xn--z3e; ; ; # 8≮.
+xn--8-sgn10i.xn--z3e; 8≮‌.឴; [C1, V5, V6]; xn--8-sgn10i.xn--z3e; ; ; # 8≮.
+ᢕ≯︒񄂯.Ⴀ; ᢕ≯︒񄂯.Ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ᢕ≯︒񄂯.Ⴀ; ᢕ≯︒񄂯.Ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ᢕ≯。񄂯.Ⴀ; ᢕ≯.񄂯.Ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯。񄂯.Ⴀ; ᢕ≯.񄂯.Ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+ᢕ≯。񄂯.ⴀ; ᢕ≯.񄂯.ⴀ; [P1, V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+xn--fbf851c.xn--ko1u.xn--rkj; ᢕ≯.񄂯.ⴀ; [V6]; xn--fbf851c.xn--ko1u.xn--rkj; ; ; # ᢕ≯..ⴀ
+xn--fbf851c.xn--ko1u.xn--7md; ᢕ≯.񄂯.Ⴀ; [V6]; xn--fbf851c.xn--ko1u.xn--7md; ; ; # ᢕ≯..Ⴀ
+ᢕ≯︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+ᢕ≯︒񄂯.ⴀ; ᢕ≯︒񄂯.ⴀ; [P1, V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+xn--fbf851cq98poxw1a.xn--rkj; ᢕ≯︒񄂯.ⴀ; [V6]; xn--fbf851cq98poxw1a.xn--rkj; ; ; # ᢕ≯︒.ⴀ
+xn--fbf851cq98poxw1a.xn--7md; ᢕ≯︒񄂯.Ⴀ; [V6]; xn--fbf851cq98poxw1a.xn--7md; ; ; # ᢕ≯︒.Ⴀ
+ྟ.-ࠪ; ྟ.-ࠪ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+ྟ.-ࠪ; ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+xn--vfd.xn----fhd; ྟ.-ࠪ; [V3, V5]; xn--vfd.xn----fhd; ; ; # ྟ.-ࠪ
+ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [P1, V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ᵬ󠆠.핒⒒⒈􈄦; ᵬ.핒⒒⒈􈄦; [P1, V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [P1, V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+ᵬ󠆠.핒11.1.􈄦; ᵬ.핒11.1.􈄦; [P1, V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+xn--tbg.xn--11-5o7k.1.xn--k469f; ᵬ.핒11.1.􈄦; [V6]; xn--tbg.xn--11-5o7k.1.xn--k469f; ; ; # ᵬ.핒11.1.
+xn--tbg.xn--tsht7586kyts9l; ᵬ.핒⒒⒈􈄦; [V6]; xn--tbg.xn--tsht7586kyts9l; ; ; # ᵬ.핒⒒⒈
+ς𑓂𐋢.٨; ς𑓂𐋢.٨; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨
+ς𑓂𐋢.٨; ; [B1]; xn--3xa8371khhl.xn--hib; ; xn--4xa6371khhl.xn--hib; # ς𑓂𐋢.٨
+Σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+σ𑓂𐋢.٨; ; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+xn--4xa6371khhl.xn--hib; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+xn--3xa8371khhl.xn--hib; ς𑓂𐋢.٨; [B1]; xn--3xa8371khhl.xn--hib; ; ; # ς𑓂𐋢.٨
+Σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+σ𑓂𐋢.٨; σ𑓂𐋢.٨; [B1]; xn--4xa6371khhl.xn--hib; ; ; # σ𑓂𐋢.٨
+꥓‌𐋻‍.ⷸ𞿄𐹲; ; [B1, B6, C2, P1, V5, V6]; xn--0ugc8356he76c.xn--urju692efj0f; ; xn--3j9a531o.xn--urju692efj0f; [B1, P1, V5, V6] # ꥓𐋻.ⷸ𐹲
+xn--3j9a531o.xn--urju692efj0f; ꥓𐋻.ⷸ𞿄𐹲; [B1, V5, V6]; xn--3j9a531o.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲
+xn--0ugc8356he76c.xn--urju692efj0f; ꥓‌𐋻‍.ⷸ𞿄𐹲; [B1, B6, C2, V5, V6]; xn--0ugc8356he76c.xn--urju692efj0f; ; ; # ꥓𐋻.ⷸ𐹲
+⊼。񪧖ڕ; ⊼.񪧖ڕ; [B1, B5, B6, P1, V6]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ
+xn--ofh.xn--rjb13118f; ⊼.񪧖ڕ; [B1, B5, B6, V6]; xn--ofh.xn--rjb13118f; ; ; # ⊼.ڕ
+𐯬񖋔。󜳥; 𐯬񖋔.󜳥; [B2, B3, P1, V6]; xn--949co370q.xn--7g25e; ; ; # .
+xn--949co370q.xn--7g25e; 𐯬񖋔.󜳥; [B2, B3, V6]; xn--949co370q.xn--7g25e; ; ; # .
+؁𑍧ߝ。ς򬍘🀞឵; ؁𑍧ߝ.ς򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--3xa823h9p95ars26d; ; xn--jfb66gt010c.xn--4xa623h9p95ars26d; # 𑍧ߝ.ς🀞
+؁𑍧ߝ。Σ򬍘🀞឵; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+؁𑍧ߝ。σ򬍘🀞឵; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, P1, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+xn--jfb66gt010c.xn--4xa623h9p95ars26d; ؁𑍧ߝ.σ򬍘🀞឵; [B1, B6, V6]; xn--jfb66gt010c.xn--4xa623h9p95ars26d; ; ; # 𑍧ߝ.σ🀞
+xn--jfb66gt010c.xn--3xa823h9p95ars26d; ؁𑍧ߝ.ς򬍘🀞឵; [B1, B6, V6]; xn--jfb66gt010c.xn--3xa823h9p95ars26d; ; ; # 𑍧ߝ.ς🀞
+-𐳲ن󠺐。꯭𝟥; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐳲ن󠺐。꯭3; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐲲ن󠺐。꯭3; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+xn----roc5482rek10i.xn--3-zw5e; -𐳲ن󠺐.꯭3; [B1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+-𐲲ن󠺐。꯭𝟥; -𐳲ن󠺐.꯭3; [B1, P1, V3, V5, V6]; xn----roc5482rek10i.xn--3-zw5e; ; ; # -𐳲ن.꯭3
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+‌󠴦。񲨕≮𐦜; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, P1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; xn--6v56e.xn--gdhz712gzlr6b; [B1, B5, B6, P1, V6] # .≮𐦜
+xn--6v56e.xn--gdhz712gzlr6b; 󠴦.񲨕≮𐦜; [B1, B5, B6, V6]; xn--6v56e.xn--gdhz712gzlr6b; ; ; # .≮𐦜
+xn--0ug22251l.xn--gdhz712gzlr6b; ‌󠴦.񲨕≮𐦜; [B1, B5, B6, C1, V6]; xn--0ug22251l.xn--gdhz712gzlr6b; ; ; # .≮𐦜
+⒈✌򟬟.𝟡񠱣; ⒈✌򟬟.9񠱣; [P1, V6]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9
+1.✌򟬟.9񠱣; ; [P1, V6]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9
+1.xn--7bi44996f.xn--9-o706d; 1.✌򟬟.9񠱣; [V6]; 1.xn--7bi44996f.xn--9-o706d; ; ; # 1.✌.9
+xn--tsh24g49550b.xn--9-o706d; ⒈✌򟬟.9񠱣; [V6]; xn--tsh24g49550b.xn--9-o706d; ; ; # ⒈✌.9
+𑆾𞤬𐮆.٦ᷔ; ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+𑆾𞤊𐮆.٦ᷔ; 𑆾𞤬𐮆.٦ᷔ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+xn--d29c79hf98r.xn--fib011j; 𑆾𞤬𐮆.٦ᷔ; [B1, V5]; xn--d29c79hf98r.xn--fib011j; ; ; # 𑆾𞤬𐮆.٦ᷔ
+ς.꧀꣄; ς.꧀꣄; [V5]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄
+ς.꧀꣄; ; [V5]; xn--3xa.xn--0f9ars; ; xn--4xa.xn--0f9ars; # ς.꧀꣄
+Σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+σ.꧀꣄; ; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+xn--4xa.xn--0f9ars; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+xn--3xa.xn--0f9ars; ς.꧀꣄; [V5]; xn--3xa.xn--0f9ars; ; ; # ς.꧀꣄
+Σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+σ.꧀꣄; σ.꧀꣄; [V5]; xn--4xa.xn--0f9ars; ; ; # σ.꧀꣄
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; ; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐳐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+xn--hdhz343g3wj.xn--qwb; 𑰶≯𐳐.࡛; [B1, B3, B6, V5, V6]; xn--hdhz343g3wj.xn--qwb; ; ; # 𑰶≯𐳐.࡛
+xn--0ug06g7697ap4ma.xn--qwb; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; ; # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+𑰶‌≯𐲐.࡛; 𑰶‌≯𐳐.࡛; [B1, B3, B6, C1, P1, V5, V6]; xn--0ug06g7697ap4ma.xn--qwb; ; xn--hdhz343g3wj.xn--qwb; [B1, B3, B6, P1, V5, V6] # 𑰶≯𐳐.࡛
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+羚。≯; 羚.≯; [P1, V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+xn--xt0a.xn--hdh; 羚.≯; [V6]; xn--xt0a.xn--hdh; ; ; # 羚.≯
+𑓂᝙.ࢨ; 𑓂᝙.ࢨ; [B1, P1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+𑓂᝙.ࢨ; ; [B1, P1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+xn--e1e9580k.xn--xyb; 𑓂᝙.ࢨ; [B1, V5, V6]; xn--e1e9580k.xn--xyb; ; ; # 𑓂.ࢨ
+󨣿󠇀‍。٣ҠჀ𝟑; 󨣿‍.٣ҡჀ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; xn--1r19e.xn--3-ozb36kixu; [B1, P1, V6] # .٣ҡჀ3
+󨣿󠇀‍。٣ҠჀ3; 󨣿‍.٣ҡჀ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; xn--1r19e.xn--3-ozb36kixu; [B1, P1, V6] # .٣ҡჀ3
+󨣿󠇀‍。٣ҡⴠ3; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+xn--1r19e.xn--3-ozb36ko13f; 󨣿.٣ҡⴠ3; [B1, V6]; xn--1r19e.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3
+xn--1ug89936l.xn--3-ozb36ko13f; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; ; # .٣ҡⴠ3
+xn--1r19e.xn--3-ozb36kixu; 󨣿.٣ҡჀ3; [B1, V6]; xn--1r19e.xn--3-ozb36kixu; ; ; # .٣ҡჀ3
+xn--1ug89936l.xn--3-ozb36kixu; 󨣿‍.٣ҡჀ3; [B1, B6, C2, V6]; xn--1ug89936l.xn--3-ozb36kixu; ; ; # .٣ҡჀ3
+󨣿󠇀‍。٣ҡⴠ𝟑; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+󨣿󠇀‍。٣Ҡⴠ3; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+󨣿󠇀‍。٣Ҡⴠ𝟑; 󨣿‍.٣ҡⴠ3; [B1, B6, C2, P1, V6]; xn--1ug89936l.xn--3-ozb36ko13f; ; xn--1r19e.xn--3-ozb36ko13f; [B1, P1, V6] # .٣ҡⴠ3
+ᡷ。𐹢࣠; ᡷ.𐹢࣠; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠
+xn--k9e.xn--j0b5005k; ᡷ.𐹢࣠; [B1]; xn--k9e.xn--j0b5005k; ; ; # ᡷ.𐹢࣠
+򕮇᯳。٦񗜼្ß; 򕮇᯳.٦񗜼្ß; [B1, P1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß
+򕮇᯳。٦񗜼្ß; 򕮇᯳.٦񗜼្ß; [B1, P1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; xn--1zf58212h.xn--ss-pyd459o3258m; # ᯳.٦្ß
+򕮇᯳。٦񗜼្SS; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្Ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+xn--1zf58212h.xn--ss-pyd459o3258m; 򕮇᯳.٦񗜼្ss; [B1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+xn--1zf58212h.xn--zca34zk4qx711k; 򕮇᯳.٦񗜼្ß; [B1, V6]; xn--1zf58212h.xn--zca34zk4qx711k; ; ; # ᯳.٦្ß
+򕮇᯳。٦񗜼្SS; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+򕮇᯳。٦񗜼្Ss; 򕮇᯳.٦񗜼្ss; [B1, P1, V6]; xn--1zf58212h.xn--ss-pyd459o3258m; ; ; # ᯳.٦្ss
+٤򤽎𑲛.󠔢︒≠; ; [B1, P1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+٤򤽎𑲛.󠔢︒≠; ٤򤽎𑲛.󠔢︒≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+٤򤽎𑲛.󠔢。≠; ٤򤽎𑲛.󠔢.≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+٤򤽎𑲛.󠔢。≠; ٤򤽎𑲛.󠔢.≠; [B1, P1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+xn--dib0653l2i02d.xn--k736e.xn--1ch; ٤򤽎𑲛.󠔢.≠; [B1, V6]; xn--dib0653l2i02d.xn--k736e.xn--1ch; ; ; # ٤𑲛..≠
+xn--dib0653l2i02d.xn--1ch7467f14u4g; ٤򤽎𑲛.󠔢︒≠; [B1, V6]; xn--dib0653l2i02d.xn--1ch7467f14u4g; ; ; # ٤𑲛.︒≠
+➆񷧕ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕ỗ1..򑬒񡘮࡛9; ; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ1..򑬒񡘮࡛9; ➆񷧕ỗ1..򑬒񡘮࡛9; [P1, V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [P1, V6, A4_2]; ; # ➆ỗ1..࡛9
+xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; ➆񷧕ỗ1..򑬒񡘮࡛9; [V6, X4_2]; xn--1-3xm292b6044r..xn--9-6jd87310jtcqs; [V6, A4_2]; ; # ➆ỗ1..࡛9
+➆񷧕Ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+➆񷧕Ỗ⒈.򑬒񡘮࡛𝟫; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [P1, V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ➆񷧕ỗ⒈.򑬒񡘮࡛9; [V6]; xn--6lg26tvvc6v99z.xn--9-6jd87310jtcqs; ; ; # ➆ỗ⒈.࡛9
+‍。𞤘; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+‍。𞤘; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+‍。𞤺; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+.xn--ye6h; .𞤺; [X4_2]; .xn--ye6h; [A4_2]; ; # .𞤺
+xn--1ug.xn--ye6h; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; ; # .𞤺
+‍。𞤺; ‍.𞤺; [B1, C2]; xn--1ug.xn--ye6h; ; .xn--ye6h; [A4_2] # .𞤺
+xn--ye6h; 𞤺; ; xn--ye6h; ; ; # 𞤺
+𞤺; ; ; xn--ye6h; ; ; # 𞤺
+𞤘; 𞤺; ; xn--ye6h; ; ; # 𞤺
+ࠩܤ.ᢣ; ; [B1, V5]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ
+xn--unb53c.xn--tbf; ࠩܤ.ᢣ; [B1, V5]; xn--unb53c.xn--tbf; ; ; # ࠩܤ.ᢣ
+ܼ‌-。𓐾ß; ܼ‌-.𓐾ß; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--zca7848m; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ß
+ܼ‌-。𓐾SS; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+ܼ‌-。𓐾ss; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+ܼ‌-。𓐾Ss; ܼ‌-.𓐾ss; [C1, P1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; xn----s2c.xn--ss-066q; [P1, V3, V5, V6] # ܼ-.ss
+xn----s2c.xn--ss-066q; ܼ-.𓐾ss; [V3, V5, V6]; xn----s2c.xn--ss-066q; ; ; # ܼ-.ss
+xn----s2c071q.xn--ss-066q; ܼ‌-.𓐾ss; [C1, V3, V5, V6]; xn----s2c071q.xn--ss-066q; ; ; # ܼ-.ss
+xn----s2c071q.xn--zca7848m; ܼ‌-.𓐾ß; [C1, V3, V5, V6]; xn----s2c071q.xn--zca7848m; ; ; # ܼ-.ß
+‌ς🃡⒗.ೆ仧ݖ; ; [B1, B5, B6, C1, P1, V5, V6]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # ς🃡⒗.ೆ仧ݖ
+‌ς🃡16..ೆ仧ݖ; ; [B1, B5, B6, C1, V5, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # ς🃡16..ೆ仧ݖ
+‌Σ🃡16..ೆ仧ݖ; ‌σ🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # σ🃡16..ೆ仧ݖ
+‌σ🃡16..ೆ仧ݖ; ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2] # σ🃡16..ೆ仧ݖ
+xn--16-ubc66061c..xn--9ob79ycx2e; σ🃡16..ೆ仧ݖ; [B5, B6, V5, X4_2]; xn--16-ubc66061c..xn--9ob79ycx2e; [B5, B6, V5, A4_2]; ; # σ🃡16..ೆ仧ݖ
+xn--16-ubc7700avy99b..xn--9ob79ycx2e; ‌σ🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-ubc7700avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; ; # σ🃡16..ೆ仧ݖ
+xn--16-rbc1800avy99b..xn--9ob79ycx2e; ‌ς🃡16..ೆ仧ݖ; [B1, B5, B6, C1, V5, X4_2]; xn--16-rbc1800avy99b..xn--9ob79ycx2e; [B1, B5, B6, C1, V5, A4_2]; ; # ς🃡16..ೆ仧ݖ
+‌Σ🃡⒗.ೆ仧ݖ; ‌σ🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, P1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # σ🃡⒗.ೆ仧ݖ
+‌σ🃡⒗.ೆ仧ݖ; ; [B1, B5, B6, C1, P1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; xn--4xa229nbu92a.xn--9ob79ycx2e; [B5, B6, P1, V5, V6] # σ🃡⒗.ೆ仧ݖ
+xn--4xa229nbu92a.xn--9ob79ycx2e; σ🃡⒗.ೆ仧ݖ; [B5, B6, V5, V6]; xn--4xa229nbu92a.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ
+xn--4xa595lz9czy52d.xn--9ob79ycx2e; ‌σ🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, V5, V6]; xn--4xa595lz9czy52d.xn--9ob79ycx2e; ; ; # σ🃡⒗.ೆ仧ݖ
+xn--3xa795lz9czy52d.xn--9ob79ycx2e; ‌ς🃡⒗.ೆ仧ݖ; [B1, B5, B6, C1, V5, V6]; xn--3xa795lz9czy52d.xn--9ob79ycx2e; ; ; # ς🃡⒗.ೆ仧ݖ
+-.𞸚; -.ظ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+-.ظ; ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+-.xn--3gb; -.ظ; [B1, V3]; -.xn--3gb; ; ; # -.ظ
+򏛓ڃ.ཾش; ; [B1, B5, B6, P1, V5, V6]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش
+xn--8ib92728i.xn--zgb968b; 򏛓ڃ.ཾش; [B1, B5, B6, V5, V6]; xn--8ib92728i.xn--zgb968b; ; ; # ڃ.ཾش
+࿦ࡃ񽶬.𐮏; ; [B5, P1, V6]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏
+xn--1vb320b5m04p.xn--m29c; ࿦ࡃ񽶬.𐮏; [B5, V6]; xn--1vb320b5m04p.xn--m29c; ; ; # ࡃ.𐮏
+2񎨠ߋß。ᠽ; 2񎨠ߋß.ᠽ; [B1, P1, V6]; xn--2-qfa924cez02l.xn--w7e; ; xn--2ss-odg83511n.xn--w7e; # 2ߋß.ᠽ
+2񎨠ߋSS。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+2񎨠ߋss。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+xn--2ss-odg83511n.xn--w7e; 2񎨠ߋss.ᠽ; [B1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+xn--2-qfa924cez02l.xn--w7e; 2񎨠ߋß.ᠽ; [B1, V6]; xn--2-qfa924cez02l.xn--w7e; ; ; # 2ߋß.ᠽ
+2񎨠ߋSs。ᠽ; 2񎨠ߋss.ᠽ; [B1, P1, V6]; xn--2ss-odg83511n.xn--w7e; ; ; # 2ߋss.ᠽ
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; ; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێß-‍; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; ; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn--ss--qjf; 㸳ߊ≮.ێss-; [B2, B3, B5, B6, V3, V6]; xn--lsb457kkut.xn--ss--qjf; ; ; # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn--ss--qjf2343a; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; ; # 㸳ߊ≮.ێss-
+xn--lsb457kkut.xn----pfa076bys4a; 㸳ߊ≮.ێß-‍; [B2, B3, B5, B6, C2, V6]; xn--lsb457kkut.xn----pfa076bys4a; ; ; # 㸳ߊ≮.ێß-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSS-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێss-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+㸳ߊ≮.ێSs-‍; 㸳ߊ≮.ێss-‍; [B2, B3, B5, B6, C2, P1, V6]; xn--lsb457kkut.xn--ss--qjf2343a; ; xn--lsb457kkut.xn--ss--qjf; [B2, B3, B5, B6, P1, V3, V6] # 㸳ߊ≮.ێss-
+-򷝬፞𑜧.ᷫ-︒; ; [P1, V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒
+-򷝬፞𑜧.ᷫ-。; -򷝬፞𑜧.ᷫ-.; [P1, V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkm.; ; ; # -፞𑜧.ᷫ-.
+xn----b5h1837n2ok9f.xn----mkm.; -򷝬፞𑜧.ᷫ-.; [V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkm.; ; ; # -፞𑜧.ᷫ-.
+xn----b5h1837n2ok9f.xn----mkmw278h; -򷝬፞𑜧.ᷫ-︒; [V3, V5, V6]; xn----b5h1837n2ok9f.xn----mkmw278h; ; ; # -፞𑜧.ᷫ-︒
+︒.򚠡ᩙ; ; [P1, V6]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ
+。.򚠡ᩙ; ..򚠡ᩙ; [P1, V6, X4_2]; ..xn--cof61594i; [P1, V6, A4_2]; ; # ..ᩙ
+..xn--cof61594i; ..򚠡ᩙ; [V6, X4_2]; ..xn--cof61594i; [V6, A4_2]; ; # ..ᩙ
+xn--y86c.xn--cof61594i; ︒.򚠡ᩙ; [V6]; xn--y86c.xn--cof61594i; ; ; # ︒.ᩙ
+̣ⷡ。‌⓾‌ڹ; ̣ⷡ.‌⓾‌ڹ; [B1, B3, B6, C1, V5]; xn--kta899s.xn--skb970ka771c; ; xn--kta899s.xn--skb116m; [B1, B3, B6, V5] # ̣ⷡ.⓾ڹ
+xn--kta899s.xn--skb116m; ̣ⷡ.⓾ڹ; [B1, B3, B6, V5]; xn--kta899s.xn--skb116m; ; ; # ̣ⷡ.⓾ڹ
+xn--kta899s.xn--skb970ka771c; ̣ⷡ.‌⓾‌ڹ; [B1, B3, B6, C1, V5]; xn--kta899s.xn--skb970ka771c; ; ; # ̣ⷡ.⓾ڹ
+𞠶ᠴ۝。ၴ𞤵󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤵󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤓󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+xn--tlb199fwl35a.xn--yld4613v; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𞠶ᠴ۝。ၴ𞤓󠅦; 𞠶ᠴ۝.ၴ𞤵; [B1, B2, P1, V5, V6]; xn--tlb199fwl35a.xn--yld4613v; ; ; # 𞠶ᠴ.ၴ𞤵
+𑰺.-򑟏; ; [P1, V3, V5, V6]; xn--jk3d.xn----iz68g; ; ; # 𑰺.-
+xn--jk3d.xn----iz68g; 𑰺.-򑟏; [V3, V5, V6]; xn--jk3d.xn----iz68g; ; ; # 𑰺.-
+󠻩.赏; 󠻩.赏; [P1, V6]; xn--2856e.xn--6o3a; ; ; # .赏
+󠻩.赏; ; [P1, V6]; xn--2856e.xn--6o3a; ; ; # .赏
+xn--2856e.xn--6o3a; 󠻩.赏; [V6]; xn--2856e.xn--6o3a; ; ; # .赏
+ڰᠡ。Ⴁ; ڰᠡ.Ⴁ; [B2, B3, P1, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。Ⴁ; ڰᠡ.Ⴁ; [B2, B3, P1, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。ⴁ; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+xn--jkb440g.xn--skj; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+xn--jkb440g.xn--8md; ڰᠡ.Ⴁ; [B2, B3, V6]; xn--jkb440g.xn--8md; ; ; # ڰᠡ.Ⴁ
+ڰᠡ。ⴁ; ڰᠡ.ⴁ; [B2, B3]; xn--jkb440g.xn--skj; ; ; # ڰᠡ.ⴁ
+⃞Ⴊڻς。-; ⃞Ⴊڻς.-; [B1, P1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; xn--4xa33m7zmb0q.-; # ⃞Ⴊڻς.-
+⃞Ⴊڻς。-; ⃞Ⴊڻς.-; [B1, P1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; xn--4xa33m7zmb0q.-; # ⃞Ⴊڻς.-
+⃞ⴊڻς。-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.-
+⃞ႪڻΣ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+⃞ⴊڻσ。-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+⃞Ⴊڻσ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+xn--4xa33m7zmb0q.-; ⃞Ⴊڻσ.-; [B1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+xn--4xa33mr38aeel.-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+xn--3xa53mr38aeel.-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; ; # ⃞ⴊڻς.-
+xn--3xa53m7zmb0q.-; ⃞Ⴊڻς.-; [B1, V3, V5, V6]; xn--3xa53m7zmb0q.-; ; ; # ⃞Ⴊڻς.-
+⃞ⴊڻς。-; ⃞ⴊڻς.-; [B1, V3, V5]; xn--3xa53mr38aeel.-; ; xn--4xa33mr38aeel.-; # ⃞ⴊڻς.-
+⃞ႪڻΣ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+⃞ⴊڻσ。-; ⃞ⴊڻσ.-; [B1, V3, V5]; xn--4xa33mr38aeel.-; ; ; # ⃞ⴊڻσ.-
+⃞Ⴊڻσ。-; ⃞Ⴊڻσ.-; [B1, P1, V3, V5, V6]; xn--4xa33m7zmb0q.-; ; ; # ⃞Ⴊڻσ.-
+Ⴍ.񍇦‌; Ⴍ.񍇦‌; [C1, P1, V6]; xn--lnd.xn--0ug56448b; ; xn--lnd.xn--p01x; [P1, V6] # Ⴍ.
+Ⴍ.񍇦‌; ; [C1, P1, V6]; xn--lnd.xn--0ug56448b; ; xn--lnd.xn--p01x; [P1, V6] # Ⴍ.
+ⴍ.񍇦‌; ; [C1, P1, V6]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [P1, V6] # ⴍ.
+xn--4kj.xn--p01x; ⴍ.񍇦; [V6]; xn--4kj.xn--p01x; ; ; # ⴍ.
+xn--4kj.xn--0ug56448b; ⴍ.񍇦‌; [C1, V6]; xn--4kj.xn--0ug56448b; ; ; # ⴍ.
+xn--lnd.xn--p01x; Ⴍ.񍇦; [V6]; xn--lnd.xn--p01x; ; ; # Ⴍ.
+xn--lnd.xn--0ug56448b; Ⴍ.񍇦‌; [C1, V6]; xn--lnd.xn--0ug56448b; ; ; # Ⴍ.
+ⴍ.񍇦‌; ⴍ.񍇦‌; [C1, P1, V6]; xn--4kj.xn--0ug56448b; ; xn--4kj.xn--p01x; [P1, V6] # ⴍ.
+򉟂󠵣.𐫫᩠󴺖᭄; ; [B2, B3, B6, P1, V6]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄
+xn--9u37blu98h.xn--jof13bt568cork1j; 򉟂󠵣.𐫫᩠󴺖᭄; [B2, B3, B6, V6]; xn--9u37blu98h.xn--jof13bt568cork1j; ; ; # .𐫫᩠᭄
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+≯❊ᠯ。𐹱⺨; ≯❊ᠯ.𐹱⺨; [B1, P1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+xn--i7e163ct2d.xn--vwj7372e; ≯❊ᠯ.𐹱⺨; [B1, V6]; xn--i7e163ct2d.xn--vwj7372e; ; ; # ≯❊ᠯ.𐹱⺨
+􁕜𐹧𞭁𐹩。Ⴈ𐫮Ⴏ; 􁕜𐹧𞭁𐹩.Ⴈ𐫮Ⴏ; [B5, B6, P1, V6]; xn--fo0de1270ope54j.xn--gndo2033q; ; ; # 𐹧𐹩.Ⴈ𐫮Ⴏ
+􁕜𐹧𞭁𐹩。ⴈ𐫮ⴏ; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, P1, V6]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ
+xn--fo0de1270ope54j.xn--zkjo0151o; 􁕜𐹧𞭁𐹩.ⴈ𐫮ⴏ; [B5, B6, V6]; xn--fo0de1270ope54j.xn--zkjo0151o; ; ; # 𐹧𐹩.ⴈ𐫮ⴏ
+xn--fo0de1270ope54j.xn--gndo2033q; 􁕜𐹧𞭁𐹩.Ⴈ𐫮Ⴏ; [B5, B6, V6]; xn--fo0de1270ope54j.xn--gndo2033q; ; ; # 𐹧𐹩.Ⴈ𐫮Ⴏ
+𞠂。ꤦ; 𞠂.ꤦ; [B1, B3, B6, V5]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ
+xn--145h.xn--ti9a; 𞠂.ꤦ; [B1, B3, B6, V5]; xn--145h.xn--ti9a; ; ; # 𞠂.ꤦ
+𝟔𐹫.့ܳ9ꡇ; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+𝟔𐹫.့ܳ9ꡇ; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+6𐹫.့ܳ9ꡇ; ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+xn--6-t26i.xn--9-91c730e8u8n; 6𐹫.့ܳ9ꡇ; [B1, V5]; xn--6-t26i.xn--9-91c730e8u8n; ; ; # 6𐹫.့ܳ9ꡇ
+ܤ؃𞲶.ۘ; ܤ؃𞲶.ۘ; [B1, B3, B6, P1, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+ܤ؃𞲶.ۘ; ; [B1, B3, B6, P1, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+xn--lfb19ct414i.xn--olb; ܤ؃𞲶.ۘ; [B1, B3, B6, V5, V6]; xn--lfb19ct414i.xn--olb; ; ; # ܤ.ۘ
+✆񱔩ꡋ.ز‍𞣴; ✆񱔩ꡋ.ز‍𞣴; [B1, C2, P1, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, P1, V6] # ✆ꡋ.ز
+✆񱔩ꡋ.ز‍𞣴; ; [B1, C2, P1, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; xn--1biv525bcix0d.xn--xgb6828v; [B1, P1, V6] # ✆ꡋ.ز
+xn--1biv525bcix0d.xn--xgb6828v; ✆񱔩ꡋ.ز𞣴; [B1, V6]; xn--1biv525bcix0d.xn--xgb6828v; ; ; # ✆ꡋ.ز
+xn--1biv525bcix0d.xn--xgb253k0m73a; ✆񱔩ꡋ.ز‍𞣴; [B1, C2, V6]; xn--1biv525bcix0d.xn--xgb253k0m73a; ; ; # ✆ꡋ.ز
+ࡅ񃾰𞸍-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰𞸍-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰ن-.≠򃁟𑋪; ; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+ࡅ񃾰ن-.≠򃁟𑋪; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, P1, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+xn----qoc64my971s.xn--1ch7585g76o3c; ࡅ񃾰ن-.≠򃁟𑋪; [B1, B2, B3, V3, V6]; xn----qoc64my971s.xn--1ch7585g76o3c; ; ; # ࡅن-.≠𑋪
+𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+𝟛.笠; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+3.笠; ; ; 3.xn--6vz; ; ; # 3.笠
+3.xn--6vz; 3.笠; ; 3.xn--6vz; ; ; # 3.笠
+-‍.Ⴞ𐋷; ; [C2, P1, V3, V6]; xn----ugn.xn--2nd2315j; ; -.xn--2nd2315j; [P1, V3, V6] # -.Ⴞ𐋷
+-‍.ⴞ𐋷; ; [C2, V3]; xn----ugn.xn--mlj8559d; ; -.xn--mlj8559d; [V3] # -.ⴞ𐋷
+-.xn--mlj8559d; -.ⴞ𐋷; [V3]; -.xn--mlj8559d; ; ; # -.ⴞ𐋷
+xn----ugn.xn--mlj8559d; -‍.ⴞ𐋷; [C2, V3]; xn----ugn.xn--mlj8559d; ; ; # -.ⴞ𐋷
+-.xn--2nd2315j; -.Ⴞ𐋷; [V3, V6]; -.xn--2nd2315j; ; ; # -.Ⴞ𐋷
+xn----ugn.xn--2nd2315j; -‍.Ⴞ𐋷; [C2, V3, V6]; xn----ugn.xn--2nd2315j; ; ; # -.Ⴞ𐋷
+‍ςßܱ.்; ‍ςßܱ.்; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # ςßܱ.்
+‍ςßܱ.்; ; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # ςßܱ.்
+‍ΣSSܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍σssܱ.்; ; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+xn--ss-ubc826a.xn--xmc; σssܱ.்; [V5]; xn--ss-ubc826a.xn--xmc; ; ; # σssܱ.்
+xn--ss-ubc826ab34b.xn--xmc; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; ; # σssܱ.்
+‍Σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+‍σßܱ.்; ; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+xn--zca39lk1di19a.xn--xmc; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; ; # σßܱ.்
+xn--zca19ln1di19a.xn--xmc; ‍ςßܱ.்; [C2, V5]; xn--zca19ln1di19a.xn--xmc; ; ; # ςßܱ.்
+‍ΣSSܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σssܱ.்; ‍σssܱ.்; [C2, V5]; xn--ss-ubc826ab34b.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σssܱ.்
+‍Σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+‍σßܱ.்; ‍σßܱ.்; [C2, V5]; xn--zca39lk1di19a.xn--xmc; ; xn--ss-ubc826a.xn--xmc; [V5] # σßܱ.்
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+≠.‍; ≠.‍; [C2, P1, V6]; xn--1ch.xn--1ug; ; xn--1ch.; [P1, V6] # ≠.
+xn--1ch.; ≠.; [V6]; xn--1ch.; ; ; # ≠.
+xn--1ch.xn--1ug; ≠.‍; [C2, V6]; xn--1ch.xn--1ug; ; ; # ≠.
+ﰁ。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+ئح。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+ئح。ಁᠼ▗򒁋; ئح.ಁᠼ▗򒁋; [B1, P1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+xn--lgbo.xn--2rc021dcxkrx55t; ئح.ಁᠼ▗򒁋; [B1, V5, V6]; xn--lgbo.xn--2rc021dcxkrx55t; ; ; # ئح.ಁᠼ▗
+󧋵্ς.ς𐨿; 󧋵্ς.ς𐨿; [P1, V6]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿
+󧋵্ς.ς𐨿; ; [P1, V6]; xn--3xa702av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্ς.ς𐨿
+󧋵্Σ.Σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্σ.ς𐨿; ; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+󧋵্σ.σ𐨿; ; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+xn--4xa502av8297a.xn--4xa6055k; 󧋵্σ.σ𐨿; [V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+xn--4xa502av8297a.xn--3xa8055k; 󧋵্σ.ς𐨿; [V6]; xn--4xa502av8297a.xn--3xa8055k; ; ; # ্σ.ς𐨿
+xn--3xa702av8297a.xn--3xa8055k; 󧋵্ς.ς𐨿; [V6]; xn--3xa702av8297a.xn--3xa8055k; ; ; # ্ς.ς𐨿
+󧋵্Σ.Σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+󧋵্σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.σ𐨿; 󧋵্σ.σ𐨿; [P1, V6]; xn--4xa502av8297a.xn--4xa6055k; ; ; # ্σ.σ𐨿
+󧋵্Σ.ς𐨿; 󧋵্σ.ς𐨿; [P1, V6]; xn--4xa502av8297a.xn--3xa8055k; ; xn--4xa502av8297a.xn--4xa6055k; # ্σ.ς𐨿
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰Ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰Ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰Ⴙ; [B2, B3, V6]; xn--zsb09cu46vjs6f.xn--xnd909bv540bm5k9d; ; ; # 𐫓ߘ牅ࣸ.ᨗႹ
+𐫓ߘ牅ࣸ。𞦤ᨗ򱍰ⴙ; 𐫓ߘ牅ࣸ.𞦤ᨗ򱍰ⴙ; [B2, B3, P1, V6]; xn--zsb09cu46vjs6f.xn--gmf469fr883am5r1e; ; ; # 𐫓ߘ牅ࣸ.ᨗⴙ
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+񣤒。륧; 񣤒.륧; [P1, V6]; xn--s264a.xn--pw2b; ; ; # .륧
+xn--s264a.xn--pw2b; 񣤒.륧; [V6]; xn--s264a.xn--pw2b; ; ; # .륧
+𐹷‍。󉵢; 𐹷‍.󉵢; [B1, C2, P1, V6]; xn--1ugx205g.xn--8088d; ; xn--vo0d.xn--8088d; [B1, P1, V6] # 𐹷.
+xn--vo0d.xn--8088d; 𐹷.󉵢; [B1, V6]; xn--vo0d.xn--8088d; ; ; # 𐹷.
+xn--1ugx205g.xn--8088d; 𐹷‍.󉵢; [B1, C2, V6]; xn--1ugx205g.xn--8088d; ; ; # 𐹷.
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+Ⴘۂ𑲭。-; Ⴘۂ𑲭.-; [B1, B5, B6, P1, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+xn--1kb147qfk3n.-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+xn--1kb312c139t.-; Ⴘۂ𑲭.-; [B1, B5, B6, V3, V6]; xn--1kb312c139t.-; ; ; # Ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+ⴘۂ𑲭。-; ⴘۂ𑲭.-; [B1, B5, B6, V3]; xn--1kb147qfk3n.-; ; ; # ⴘۂ𑲭.-
+꠆ٻ₆ᡐ。🛇ﳝ; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+꠆ٻ6ᡐ。🛇يم; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+xn--6-rrc018krt9k.xn--hhbj61429a; ꠆ٻ6ᡐ.🛇يم; [B1, V5]; xn--6-rrc018krt9k.xn--hhbj61429a; ; ; # ꠆ٻ6ᡐ.🛇يم
+򸍂.㇄ᡟ𐫂آ; ; [B1, P1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+򸍂.㇄ᡟ𐫂آ; 򸍂.㇄ᡟ𐫂آ; [B1, P1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+xn--p292d.xn--hgb154ghrsvm2r; 򸍂.㇄ᡟ𐫂آ; [B1, V6]; xn--p292d.xn--hgb154ghrsvm2r; ; ; # .㇄ᡟ𐫂آ
+ߟ򵚌。-ߩ; ߟ򵚌.-ߩ; [B1, B2, B3, P1, V3, V6]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ
+xn--6sb88139l.xn----pdd; ߟ򵚌.-ߩ; [B1, B2, B3, V3, V6]; xn--6sb88139l.xn----pdd; ; ; # ߟ.-ߩ
+ςك⾑.‌ᢟ‌⒈; ςك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--3xa69jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # ςك襾.ᢟ⒈
+ςك襾.‌ᢟ‌1.; ; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # ςك襾.ᢟ1.
+Σك襾.‌ᢟ‌1.; σك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # σك襾.ᢟ1.
+σك襾.‌ᢟ‌1.; ; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; xn--4xa49jux8r.xn--1-4ck.; [B5] # σك襾.ᢟ1.
+xn--4xa49jux8r.xn--1-4ck.; σك襾.ᢟ1.; [B5]; xn--4xa49jux8r.xn--1-4ck.; ; ; # σك襾.ᢟ1.
+xn--4xa49jux8r.xn--1-4ck691bba.; σك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--4xa49jux8r.xn--1-4ck691bba.; ; ; # σك襾.ᢟ1.
+xn--3xa69jux8r.xn--1-4ck691bba.; ςك襾.‌ᢟ‌1.; [B1, B5, C1]; xn--3xa69jux8r.xn--1-4ck691bba.; ; ; # ςك襾.ᢟ1.
+Σك⾑.‌ᢟ‌⒈; σك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # σك襾.ᢟ⒈
+σك⾑.‌ᢟ‌⒈; σك襾.‌ᢟ‌⒈; [B1, B5, C1, P1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; xn--4xa49jux8r.xn--pbf212d; [B5, P1, V6] # σك襾.ᢟ⒈
+xn--4xa49jux8r.xn--pbf212d; σك襾.ᢟ⒈; [B5, V6]; xn--4xa49jux8r.xn--pbf212d; ; ; # σك襾.ᢟ⒈
+xn--4xa49jux8r.xn--pbf519aba607b; σك襾.‌ᢟ‌⒈; [B1, B5, C1, V6]; xn--4xa49jux8r.xn--pbf519aba607b; ; ; # σك襾.ᢟ⒈
+xn--3xa69jux8r.xn--pbf519aba607b; ςك襾.‌ᢟ‌⒈; [B1, B5, C1, V6]; xn--3xa69jux8r.xn--pbf519aba607b; ; ; # ςك襾.ᢟ⒈
+ᡆ𑓝.𞵆; ᡆ𑓝.𞵆; [P1, V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+ᡆ𑓝.𞵆; ; [P1, V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+xn--57e0440k.xn--k86h; ᡆ𑓝.𞵆; [V6]; xn--57e0440k.xn--k86h; ; ; # ᡆ.
+੍𦍓ᷮ。‌ࢽ񝹲; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, P1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, P1, V5, V6] # ੍𦍓ᷮ.ࢽ
+੍𦍓ᷮ。‌ࢽ񝹲; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, P1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; xn--ybc461hph93b.xn--jzb29857e; [B1, B2, B3, P1, V5, V6] # ੍𦍓ᷮ.ࢽ
+xn--ybc461hph93b.xn--jzb29857e; ੍𦍓ᷮ.ࢽ񝹲; [B1, B2, B3, V5, V6]; xn--ybc461hph93b.xn--jzb29857e; ; ; # ੍𦍓ᷮ.ࢽ
+xn--ybc461hph93b.xn--jzb740j1y45h; ੍𦍓ᷮ.‌ࢽ񝹲; [B1, C1, V5, V6]; xn--ybc461hph93b.xn--jzb740j1y45h; ; ; # ੍𦍓ᷮ.ࢽ
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; ; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+خ݈񅪪-.‌먿; خ݈񅪪-.‌먿; [B1, B2, B3, C1, P1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; xn----dnc06f42153a.xn--v22b; [B2, B3, P1, V3, V6] # خ݈-.먿
+xn----dnc06f42153a.xn--v22b; خ݈񅪪-.먿; [B2, B3, V3, V6]; xn----dnc06f42153a.xn--v22b; ; ; # خ݈-.먿
+xn----dnc06f42153a.xn--0ug1581d; خ݈񅪪-.‌먿; [B1, B2, B3, C1, V3, V6]; xn----dnc06f42153a.xn--0ug1581d; ; ; # خ݈-.먿
+􋿦。ᠽ; 􋿦.ᠽ; [P1, V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+􋿦。ᠽ; 􋿦.ᠽ; [P1, V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+xn--j890g.xn--w7e; 􋿦.ᠽ; [V6]; xn--j890g.xn--w7e; ; ; # .ᠽ
+嬃𝍌.‍ୄ; 嬃𝍌.‍ୄ; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V5] # 嬃𝍌.ୄ
+嬃𝍌.‍ୄ; ; [C2]; xn--b6s0078f.xn--0ic557h; ; xn--b6s0078f.xn--0ic; [V5] # 嬃𝍌.ୄ
+xn--b6s0078f.xn--0ic; 嬃𝍌.ୄ; [V5]; xn--b6s0078f.xn--0ic; ; ; # 嬃𝍌.ୄ
+xn--b6s0078f.xn--0ic557h; 嬃𝍌.‍ୄ; [C2]; xn--b6s0078f.xn--0ic557h; ; ; # 嬃𝍌.ୄ
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+؂𝌪≯.𚋲򵁨; ؂𝌪≯.𚋲򵁨; [B1, P1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+xn--kfb866llx01a.xn--wp1gm3570b; ؂𝌪≯.𚋲򵁨; [B1, V6]; xn--kfb866llx01a.xn--wp1gm3570b; ; ; # 𝌪≯.
+򫾥ࢷ៌꧀.𞼠; ; [B5, P1, V6]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀.
+xn--dzb638ewm4i1iy1h.xn--3m7h; 򫾥ࢷ៌꧀.𞼠; [B5, V6]; xn--dzb638ewm4i1iy1h.xn--3m7h; ; ; # ࢷ៌꧀.
+‌.񟛤; ; [C1, P1, V6]; xn--0ug.xn--q823a; ; .xn--q823a; [P1, V6, A4_2] # .
+.xn--q823a; .񟛤; [V6, X4_2]; .xn--q823a; [V6, A4_2]; ; # .
+xn--0ug.xn--q823a; ‌.񟛤; [C1, V6]; xn--0ug.xn--q823a; ; ; # .
+򺛕Ⴃ䠅.𐸑; 򺛕Ⴃ䠅.𐸑; [P1, V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕Ⴃ䠅.𐸑; ; [P1, V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕ⴃ䠅.𐸑; ; [P1, V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+xn--ukju77frl47r.xn--yl0d; 򺛕ⴃ䠅.𐸑; [V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+xn--bnd074zr557n.xn--yl0d; 򺛕Ⴃ䠅.𐸑; [V6]; xn--bnd074zr557n.xn--yl0d; ; ; # Ⴃ䠅.
+򺛕ⴃ䠅.𐸑; 򺛕ⴃ䠅.𐸑; [P1, V6]; xn--ukju77frl47r.xn--yl0d; ; ; # ⴃ䠅.
+ᯱ𐹳𐹵𞤚。𝟨Ⴅ; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, P1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤚。6Ⴅ; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, P1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤼。6ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+ᯱ𐹳𐹵𞤚。6ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+xn--zzfy954hga2415t.xn--6-kvs; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+xn--zzfy954hga2415t.xn--6-h0g; ᯱ𐹳𐹵𞤼.6Ⴅ; [B1, V5, V6]; xn--zzfy954hga2415t.xn--6-h0g; ; ; # ᯱ𐹳𐹵𞤼.6Ⴅ
+ᯱ𐹳𐹵𞤼。𝟨ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+ᯱ𐹳𐹵𞤚。𝟨ⴅ; ᯱ𐹳𐹵𞤼.6ⴅ; [B1, V5]; xn--zzfy954hga2415t.xn--6-kvs; ; ; # ᯱ𐹳𐹵𞤼.6ⴅ
+-。︒; -.︒; [P1, V3, V6]; -.xn--y86c; ; ; # -.︒
+-。。; -..; [V3, X4_2]; ; [V3, A4_2]; ; # -..
+-..; ; [V3, X4_2]; ; [V3, A4_2]; ; # -..
+-.xn--y86c; -.︒; [V3, V6]; -.xn--y86c; ; ; # -.︒
+ߛჀ。-⁵--; ߛჀ.-5--; [B1, B2, B3, P1, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛჀ。-5--; ߛჀ.-5--; [B1, B2, B3, P1, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛⴠ。-5--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+xn--2sb691q.-5--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+xn--2sb866b.-5--; ߛჀ.-5--; [B1, B2, B3, V2, V3, V6]; xn--2sb866b.-5--; ; ; # ߛჀ.-5--
+ߛⴠ。-⁵--; ߛⴠ.-5--; [B1, B2, B3, V2, V3]; xn--2sb691q.-5--; ; ; # ߛⴠ.-5--
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕。𐹷𐹻≯𐷒; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+xn--?-ogo25661n.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.xn--hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.XN--HDH8283GDOAQA; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+≯?󠑕.Xn--Hdh8283gdoaqa; ≯?󠑕.𐹷𐹻≯𐷒; [B1, P1, V6]; xn--?-ogo25661n.xn--hdh8283gdoaqa; ; ; # ≯?.𐹷𐹻≯
+㍔ࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+ルーブルࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+ルーブルࣦݼ‍。͆򁳊𝅶؄; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, P1, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; [B1, B5, B6, P1, V5, V6] # ルーブルࣦݼ.͆
+xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ルーブルࣦݼ.͆򁳊𝅶؄; [B1, B5, B6, V5, V6]; xn--dqb73el09fncab4h.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆
+xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ルーブルࣦݼ‍.͆򁳊𝅶؄; [B1, B5, B6, C2, V5, V6]; xn--dqb73ec22c9kp8cb1j.xn--kua81ls548d3608b; ; ; # ルーブルࣦݼ.͆
+‍.F; ‍.f; [C2]; xn--1ug.f; ; .f; [A4_2] # .f
+‍.f; ; [C2]; xn--1ug.f; ; .f; [A4_2] # .f
+.f; ; [X4_2]; ; [A4_2]; ; # .f
+xn--1ug.f; ‍.f; [C2]; xn--1ug.f; ; ; # .f
+f; ; ; ; ; ; # f
+‍㨲。ß; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß
+‍㨲。ß; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; xn--9bm.ss; [] # 㨲.ß
+‍㨲。SS; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。Ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+xn--9bm.ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.ss; ; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.SS; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+㨲.Ss; 㨲.ss; ; xn--9bm.ss; ; ; # 㨲.ss
+xn--1ug914h.ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; ; # 㨲.ss
+xn--1ug914h.xn--zca; ‍㨲.ß; [C2]; xn--1ug914h.xn--zca; ; ; # 㨲.ß
+‍㨲。SS; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+‍㨲。Ss; ‍㨲.ss; [C2]; xn--1ug914h.ss; ; xn--9bm.ss; [] # 㨲.ss
+؅پ。ࢨ; ؅پ.ࢨ; [B1, P1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+؅پ。ࢨ; ؅پ.ࢨ; [B1, P1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+xn--nfb6v.xn--xyb; ؅پ.ࢨ; [B1, V6]; xn--nfb6v.xn--xyb; ; ; # پ.ࢨ
+⾑ݓ𞤁。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+襾ݓ𞤁。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+襾ݓ𞤣。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+xn--6ob9577deqwl.xn--7ib5526k; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+⾑ݓ𞤣。𐹵ڂ; 襾ݓ𞤣.𐹵ڂ; [B1, B5, B6]; xn--6ob9577deqwl.xn--7ib5526k; ; ; # 襾ݓ𞤣.𐹵ڂ
+񦴻ς-⃫。ݔ-ꡛ; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ
+񦴻ς-⃫。ݔ-ꡛ; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----xmb015tuo34l.xn----53c4874j; ; xn----zmb705tuo34l.xn----53c4874j; # ς-⃫.ݔ-ꡛ
+񦴻Σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+񦴻σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+xn----zmb705tuo34l.xn----53c4874j; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+xn----xmb015tuo34l.xn----53c4874j; 񦴻ς-⃫.ݔ-ꡛ; [B2, B3, B6, V6]; xn----xmb015tuo34l.xn----53c4874j; ; ; # ς-⃫.ݔ-ꡛ
+񦴻Σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+񦴻σ-⃫。ݔ-ꡛ; 񦴻σ-⃫.ݔ-ꡛ; [B2, B3, B6, P1, V6]; xn----zmb705tuo34l.xn----53c4874j; ; ; # σ-⃫.ݔ-ꡛ
+‍.􀸨; ‍.􀸨; [C2, P1, V6]; xn--1ug.xn--h327f; ; .xn--h327f; [P1, V6, A4_2] # .
+‍.􀸨; ; [C2, P1, V6]; xn--1ug.xn--h327f; ; .xn--h327f; [P1, V6, A4_2] # .
+.xn--h327f; .􀸨; [V6, X4_2]; .xn--h327f; [V6, A4_2]; ; # .
+xn--1ug.xn--h327f; ‍.􀸨; [C2, V6]; xn--1ug.xn--h327f; ; ; # .
+񣭻񌥁。≠𝟲; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠𝟲; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠6; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+񣭻񌥁。≠6; 񣭻񌥁.≠6; [P1, V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+xn--h79w4z99a.xn--6-tfo; 񣭻񌥁.≠6; [V6]; xn--h79w4z99a.xn--6-tfo; ; ; # .≠6
+󠅊ᡭ‍.𐥡; ᡭ‍.𐥡; [B6, C2, P1, V6]; xn--98e810b.xn--om9c; ; xn--98e.xn--om9c; [P1, V6] # ᡭ.
+xn--98e.xn--om9c; ᡭ.𐥡; [V6]; xn--98e.xn--om9c; ; ; # ᡭ.
+xn--98e810b.xn--om9c; ᡭ‍.𐥡; [B6, C2, V6]; xn--98e810b.xn--om9c; ; ; # ᡭ.
+ీࡕ𐥛𑄴.󭰵; ీࡕ𐥛𑄴.󭰵; [B1, P1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+ీࡕ𐥛𑄴.󭰵; ; [B1, P1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+xn--kwb91r5112avtg.xn--o580f; ీࡕ𐥛𑄴.󭰵; [B1, V5, V6]; xn--kwb91r5112avtg.xn--o580f; ; ; # ీࡕ𑄴.
+𞤮。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤮。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤌。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+𞤌。𑇊‌≯᳦; 𞤮.𑇊‌≯᳦; [B1, C1, P1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; xn--me6h.xn--z6fz8ueq2v; [B1, P1, V5, V6] # 𞤮.𑇊≯᳦
+xn--me6h.xn--z6fz8ueq2v; 𞤮.𑇊≯᳦; [B1, V5, V6]; xn--me6h.xn--z6fz8ueq2v; ; ; # 𞤮.𑇊≯᳦
+xn--me6h.xn--z6f16kn9b2642b; 𞤮.𑇊‌≯᳦; [B1, C1, V5, V6]; xn--me6h.xn--z6f16kn9b2642b; ; ; # 𞤮.𑇊≯᳦
+󠄀𝟕.𞤌񛗓Ⴉ; 7.𞤮񛗓Ⴉ; [B1, B2, B3, P1, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀7.𞤌񛗓Ⴉ; 7.𞤮񛗓Ⴉ; [B1, B2, B3, P1, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀7.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+7.xn--0kjz523lv1vv; 7.𞤮񛗓ⴉ; [B1, B2, B3, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+7.xn--hnd3403vv1vv; 7.𞤮񛗓Ⴉ; [B1, B2, B3, V6]; 7.xn--hnd3403vv1vv; ; ; # 7.𞤮Ⴉ
+󠄀𝟕.𞤮񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+󠄀7.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+󠄀𝟕.𞤌񛗓ⴉ; 7.𞤮񛗓ⴉ; [B1, B2, B3, P1, V6]; 7.xn--0kjz523lv1vv; ; ; # 7.𞤮ⴉ
+閃9𝩍。Ↄ٩ࢱ୍; 閃9𝩍.Ↄ٩ࢱ୍; [B5, B6, P1, V6]; xn--9-3j6dk517f.xn--iib28ij3c0t9a; ; ; # 閃9𝩍.Ↄ٩ࢱ୍
+閃9𝩍。ↄ٩ࢱ୍; 閃9𝩍.ↄ٩ࢱ୍; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍
+xn--9-3j6dk517f.xn--iib28ij3c4t9a; 閃9𝩍.ↄ٩ࢱ୍; [B5, B6]; xn--9-3j6dk517f.xn--iib28ij3c4t9a; ; ; # 閃9𝩍.ↄ٩ࢱ୍
+xn--9-3j6dk517f.xn--iib28ij3c0t9a; 閃9𝩍.Ↄ٩ࢱ୍; [B5, B6, V6]; xn--9-3j6dk517f.xn--iib28ij3c0t9a; ; ; # 閃9𝩍.Ↄ٩ࢱ୍
+꫶ᢏฺ2.𐋢݅ྟ︒; ꫶ᢏฺ2.𐋢݅ྟ︒; [P1, V5, V6]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒
+꫶ᢏฺ2.𐋢݅ྟ。; ꫶ᢏฺ2.𐋢݅ྟ.; [V5]; xn--2-2zf840fk16m.xn--sob093b2m7s.; ; ; # ꫶ᢏฺ2.𐋢݅ྟ.
+xn--2-2zf840fk16m.xn--sob093b2m7s.; ꫶ᢏฺ2.𐋢݅ྟ.; [V5]; xn--2-2zf840fk16m.xn--sob093b2m7s.; ; ; # ꫶ᢏฺ2.𐋢݅ྟ.
+xn--2-2zf840fk16m.xn--sob093bj62sz9d; ꫶ᢏฺ2.𐋢݅ྟ︒; [V5, V6]; xn--2-2zf840fk16m.xn--sob093bj62sz9d; ; ; # ꫶ᢏฺ2.𐋢݅ྟ︒
+󅴧。≠-󠙄⾛; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄⾛; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄走; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+󅴧。≠-󠙄走; 󅴧.≠-󠙄走; [P1, V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+xn--gm57d.xn----tfo4949b3664m; 󅴧.≠-󠙄走; [V6]; xn--gm57d.xn----tfo4949b3664m; ; ; # .≠-走
+ݮ؄Ⴊ。-≠ᅠ; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ݮ؄Ⴊ。-≠ᅠ; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ݮ؄ⴊ。-≠ᅠ; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+ݮ؄ⴊ。-≠ᅠ; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, P1, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+xn--mfb73ek93f.xn----5bh589i; ݮ؄ⴊ.-≠ᅠ; [B1, B2, B3, V3, V6]; xn--mfb73ek93f.xn----5bh589i; ; ; # ݮⴊ.-≠
+xn--mfb73ex6r.xn----5bh589i; ݮ؄Ⴊ.-≠ᅠ; [B1, B2, B3, V3, V6]; xn--mfb73ex6r.xn----5bh589i; ; ; # ݮႪ.-≠
+ﭏ𐹧𝟒≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+ﭏ𐹧𝟒≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+אל𐹧4≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+אל𐹧4≯。‌; אל𐹧4≯.‌; [B1, B3, B4, C1, P1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; xn--4-zhc0by36txt0w.; [B3, B4, P1, V6] # אל𐹧4≯.
+xn--4-zhc0by36txt0w.; אל𐹧4≯.; [B3, B4, V6]; xn--4-zhc0by36txt0w.; ; ; # אל𐹧4≯.
+xn--4-zhc0by36txt0w.xn--0ug; אל𐹧4≯.‌; [B1, B3, B4, C1, V6]; xn--4-zhc0by36txt0w.xn--0ug; ; ; # אל𐹧4≯.
+𝟎。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0。甯; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0.xn--qny; 0.甯; ; 0.xn--qny; ; ; # 0.甯
+0.甯; ; ; 0.xn--qny; ; ; # 0.甯
+-⾆.꫶; -舌.꫶; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+-舌.꫶; ; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+xn----ef8c.xn--2v9a; -舌.꫶; [V3, V5]; xn----ef8c.xn--2v9a; ; ; # -舌.꫶
+-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+-。ᢘ; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+-.xn--ibf; -.ᢘ; [V3]; -.xn--ibf; ; ; # -.ᢘ
+🂴Ⴋ.≮; ; [P1, V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+🂴Ⴋ.≮; 🂴Ⴋ.≮; [P1, V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+🂴ⴋ.≮; 🂴ⴋ.≮; [P1, V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+🂴ⴋ.≮; ; [P1, V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+xn--2kj7565l.xn--gdh; 🂴ⴋ.≮; [V6]; xn--2kj7565l.xn--gdh; ; ; # 🂴ⴋ.≮
+xn--jnd1986v.xn--gdh; 🂴Ⴋ.≮; [V6]; xn--jnd1986v.xn--gdh; ; ; # 🂴Ⴋ.≮
+璼𝨭。‌󠇟; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [] # 璼𝨭.
+璼𝨭。‌󠇟; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; xn--gky8837e.; [] # 璼𝨭.
+xn--gky8837e.; 璼𝨭.; ; xn--gky8837e.; ; ; # 璼𝨭.
+璼𝨭.; ; ; xn--gky8837e.; ; ; # 璼𝨭.
+xn--gky8837e.xn--0ug; 璼𝨭.‌; [C1]; xn--gky8837e.xn--0ug; ; ; # 璼𝨭.
+٩8񂍽。-5🞥; ٩8񂍽.-5🞥; [B1, P1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+٩8񂍽。-5🞥; ٩8񂍽.-5🞥; [B1, P1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+xn--8-qqc97891f.xn---5-rp92a; ٩8񂍽.-5🞥; [B1, V3, V6]; xn--8-qqc97891f.xn---5-rp92a; ; ; # ٩8.-5🞥
+‌.‌; ; [C1]; xn--0ug.xn--0ug; ; .; [A4_2] # .
+xn--0ug.xn--0ug; ‌.‌; [C1]; xn--0ug.xn--0ug; ; ; # .
+‍튛.ܖ; ; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ
+‍튛.ܖ; ‍튛.ܖ; [B1, C2]; xn--1ug4441e.xn--gnb; ; xn--157b.xn--gnb; [] # 튛.ܖ
+xn--157b.xn--gnb; 튛.ܖ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+튛.ܖ; ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+튛.ܖ; 튛.ܖ; ; xn--157b.xn--gnb; ; ; # 튛.ܖ
+xn--1ug4441e.xn--gnb; ‍튛.ܖ; [B1, C2]; xn--1ug4441e.xn--gnb; ; ; # 튛.ܖ
+ᡋ𐹰𞽳.ݹⴞ; ; [B2, B3, B5, B6, P1, V6]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ
+ᡋ𐹰𞽳.ݹႾ; ; [B2, B3, B5, B6, P1, V6]; xn--b8e0417jocvf.xn--9pb068b; ; ; # ᡋ𐹰.ݹႾ
+xn--b8e0417jocvf.xn--9pb068b; ᡋ𐹰𞽳.ݹႾ; [B2, B3, B5, B6, V6]; xn--b8e0417jocvf.xn--9pb068b; ; ; # ᡋ𐹰.ݹႾ
+xn--b8e0417jocvf.xn--9pb883q; ᡋ𐹰𞽳.ݹⴞ; [B2, B3, B5, B6, V6]; xn--b8e0417jocvf.xn--9pb883q; ; ; # ᡋ𐹰.ݹⴞ
+𐷃٢𝅻𝟧.𐹮𐹬Ⴇ; 𐷃٢𝅻5.𐹮𐹬Ⴇ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻5.𐹮𐹬Ⴇ; ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻5.𐹮𐹬ⴇ; ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+xn--5-cqc8833rhv7f.xn--ykjz523efa; 𐷃٢𝅻5.𐹮𐹬ⴇ; [B1, B4, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+xn--5-cqc8833rhv7f.xn--fnd3401kfa; 𐷃٢𝅻5.𐹮𐹬Ⴇ; [B1, B4, V6]; xn--5-cqc8833rhv7f.xn--fnd3401kfa; ; ; # ٢𝅻5.𐹮𐹬Ⴇ
+𐷃٢𝅻𝟧.𐹮𐹬ⴇ; 𐷃٢𝅻5.𐹮𐹬ⴇ; [B1, B4, P1, V6]; xn--5-cqc8833rhv7f.xn--ykjz523efa; ; ; # ٢𝅻5.𐹮𐹬ⴇ
+Ⴗ.𑄴ׂꦷ񘃨; Ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+Ⴗ.𑄴ׂꦷ񘃨; Ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+Ⴗ.𑄴ׂꦷ񘃨; ; [P1, V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+xn--flj.xn--qdb0605f14ycrms3c; ⴗ.𑄴ׂꦷ񘃨; [V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+xn--vnd.xn--qdb0605f14ycrms3c; Ⴗ.𑄴ׂꦷ񘃨; [V5, V6]; xn--vnd.xn--qdb0605f14ycrms3c; ; ; # Ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+ⴗ.𑄴ׂꦷ񘃨; ⴗ.𑄴ׂꦷ񘃨; [P1, V5, V6]; xn--flj.xn--qdb0605f14ycrms3c; ; ; # ⴗ.𑄴ׂꦷ
+𝟾𾤘.򇕛٬; 8𾤘.򇕛٬; [B1, B5, B6, P1, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+8𾤘.򇕛٬; ; [B1, B5, B6, P1, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+xn--8-kh23b.xn--lib78461i; 8𾤘.򇕛٬; [B1, B5, B6, V6]; xn--8-kh23b.xn--lib78461i; ; ; # 8.٬
+⒈酫︒。ࣖ; ⒈酫︒.ࣖ; [P1, V5, V6]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ
+1.酫。。ࣖ; 1.酫..ࣖ; [V5, X4_2]; 1.xn--8j4a..xn--8zb; [V5, A4_2]; ; # 1.酫..ࣖ
+1.xn--8j4a..xn--8zb; 1.酫..ࣖ; [V5, X4_2]; 1.xn--8j4a..xn--8zb; [V5, A4_2]; ; # 1.酫..ࣖ
+xn--tsh4490bfe8c.xn--8zb; ⒈酫︒.ࣖ; [V5, V6]; xn--tsh4490bfe8c.xn--8zb; ; ; # ⒈酫︒.ࣖ
+ⷣ‌≮ᩫ.‌ฺ; ; [C1, P1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [P1, V5, V6] # ⷣ≮ᩫ.ฺ
+ⷣ‌≮ᩫ.‌ฺ; ⷣ‌≮ᩫ.‌ฺ; [C1, P1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; xn--uof548an0j.xn--o4c; [P1, V5, V6] # ⷣ≮ᩫ.ฺ
+xn--uof548an0j.xn--o4c; ⷣ≮ᩫ.ฺ; [V5, V6]; xn--uof548an0j.xn--o4c; ; ; # ⷣ≮ᩫ.ฺ
+xn--uof63xk4bf3s.xn--o4c732g; ⷣ‌≮ᩫ.‌ฺ; [C1, V5, V6]; xn--uof63xk4bf3s.xn--o4c732g; ; ; # ⷣ≮ᩫ.ฺ
+𞪂。ႷႽ¹‍; 𞪂.ႷႽ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1gs597m; ; xn--co6h.xn--1-h1gs; [P1, V6] # .ႷႽ1
+𞪂。ႷႽ1‍; 𞪂.ႷႽ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1gs597m; ; xn--co6h.xn--1-h1gs; [P1, V6] # .ႷႽ1
+𞪂。ⴗⴝ1‍; 𞪂.ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [P1, V6] # .ⴗⴝ1
+𞪂。Ⴗⴝ1‍; 𞪂.Ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1g398iewm; ; xn--co6h.xn--1-h1g429s; [P1, V6] # .Ⴗⴝ1
+xn--co6h.xn--1-h1g429s; 𞪂.Ⴗⴝ1; [V6]; xn--co6h.xn--1-h1g429s; ; ; # .Ⴗⴝ1
+xn--co6h.xn--1-h1g398iewm; 𞪂.Ⴗⴝ1‍; [B6, C2, V6]; xn--co6h.xn--1-h1g398iewm; ; ; # .Ⴗⴝ1
+xn--co6h.xn--1-kwssa; 𞪂.ⴗⴝ1; [V6]; xn--co6h.xn--1-kwssa; ; ; # .ⴗⴝ1
+xn--co6h.xn--1-ugn710dya; 𞪂.ⴗⴝ1‍; [B6, C2, V6]; xn--co6h.xn--1-ugn710dya; ; ; # .ⴗⴝ1
+xn--co6h.xn--1-h1gs; 𞪂.ႷႽ1; [V6]; xn--co6h.xn--1-h1gs; ; ; # .ႷႽ1
+xn--co6h.xn--1-h1gs597m; 𞪂.ႷႽ1‍; [B6, C2, V6]; xn--co6h.xn--1-h1gs597m; ; ; # .ႷႽ1
+𞪂。ⴗⴝ¹‍; 𞪂.ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-ugn710dya; ; xn--co6h.xn--1-kwssa; [P1, V6] # .ⴗⴝ1
+𞪂。Ⴗⴝ¹‍; 𞪂.Ⴗⴝ1‍; [B6, C2, P1, V6]; xn--co6h.xn--1-h1g398iewm; ; xn--co6h.xn--1-h1g429s; [P1, V6] # .Ⴗⴝ1
+𑄴𑄳2.𞳿󠀳-; ; [B1, B3, P1, V3, V5, V6]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.-
+xn--2-h87ic.xn----s39r33498d; 𑄴𑄳2.𞳿󠀳-; [B1, B3, V3, V5, V6]; xn--2-h87ic.xn----s39r33498d; ; ; # 𑄴𑄳2.-
+󠕲󟶶٥。񀁁𑄳𞤃ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤃ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤥ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+󠕲󟶶٥。񀁁𑄳𞤥ܐ; 󠕲󟶶٥.񀁁𑄳𞤥ܐ; [B1, B5, B6, P1, V6]; xn--eib57614py3ea.xn--9mb5737kqnpfzkwr; ; ; # ٥.𑄳𞤥ܐ
+ܠ򲠽𐹢ុ。ςᢈ🝭‌; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。ςᢈ🝭‌; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。Σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+ܠ򲠽𐹢ុ。σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--4xa847hli46a; ܠ򲠽𐹢ុ.σᢈ🝭; [B2, B6, V6]; xn--qnb616fis0qzt36f.xn--4xa847hli46a; ; ; # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; ; # ܠ𐹢ុ.σᢈ🝭
+xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ܠ򲠽𐹢ុ.ςᢈ🝭‌; [B2, B6, C1, V6]; xn--qnb616fis0qzt36f.xn--3xa057h6ofgl44c; ; ; # ܠ𐹢ុ.ςᢈ🝭
+ܠ򲠽𐹢ុ。Σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+ܠ򲠽𐹢ុ。σᢈ🝭‌; ܠ򲠽𐹢ុ.σᢈ🝭‌; [B2, B6, C1, P1, V6]; xn--qnb616fis0qzt36f.xn--4xa847h6ofgl44c; ; xn--qnb616fis0qzt36f.xn--4xa847hli46a; [B2, B6, P1, V6] # ܠ𐹢ុ.σᢈ🝭
+‍--≮。𐹧; ‍--≮.𐹧; [B1, C2, P1, V6]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, P1, V3, V6] # --≮.𐹧
+‍--≮。𐹧; ‍--≮.𐹧; [B1, C2, P1, V6]; xn-----l1tz1k.xn--fo0d; ; xn-----ujv.xn--fo0d; [B1, P1, V3, V6] # --≮.𐹧
+xn-----ujv.xn--fo0d; --≮.𐹧; [B1, V3, V6]; xn-----ujv.xn--fo0d; ; ; # --≮.𐹧
+xn-----l1tz1k.xn--fo0d; ‍--≮.𐹧; [B1, C2, V6]; xn-----l1tz1k.xn--fo0d; ; ; # --≮.𐹧
+꠆。𻚏ྰ⒕; ꠆.𻚏ྰ⒕; [P1, V5, V6]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕
+꠆。𻚏ྰ14.; ꠆.𻚏ྰ14.; [P1, V5, V6]; xn--l98a.xn--14-jsj57880f.; ; ; # ꠆.ྰ14.
+xn--l98a.xn--14-jsj57880f.; ꠆.𻚏ྰ14.; [V5, V6]; xn--l98a.xn--14-jsj57880f.; ; ; # ꠆.ྰ14.
+xn--l98a.xn--dgd218hhp28d; ꠆.𻚏ྰ⒕; [V5, V6]; xn--l98a.xn--dgd218hhp28d; ; ; # ꠆.ྰ⒕
+򮉂ڼ.𑆺٩; 򮉂ڼ.𑆺٩; [B1, B5, B6, P1, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+򮉂ڼ.𑆺٩; ; [B1, B5, B6, P1, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+xn--vkb92243l.xn--iib9797k; 򮉂ڼ.𑆺٩; [B1, B5, B6, V5, V6]; xn--vkb92243l.xn--iib9797k; ; ; # ڼ.𑆺٩
+󠁎ې-。𞤴; 󠁎ې-.𞤴; [B1, P1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+󠁎ې-。𞤒; 󠁎ې-.𞤴; [B1, P1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+xn----mwc72685y.xn--se6h; 󠁎ې-.𞤴; [B1, V3, V6]; xn----mwc72685y.xn--se6h; ; ; # ې-.𞤴
+𝟠4󠇗𝈻.‍𐋵⛧‍; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧
+84󠇗𝈻.‍𐋵⛧‍; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; xn--84-s850a.xn--59h6326e; [] # 84𝈻.𐋵⛧
+xn--84-s850a.xn--59h6326e; 84𝈻.𐋵⛧; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧
+84𝈻.𐋵⛧; ; ; xn--84-s850a.xn--59h6326e; ; ; # 84𝈻.𐋵⛧
+xn--84-s850a.xn--1uga573cfq1w; 84𝈻.‍𐋵⛧‍; [C2]; xn--84-s850a.xn--1uga573cfq1w; ; ; # 84𝈻.𐋵⛧
+-؁。ᡪ; -؁.ᡪ; [B1, P1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+-؁。ᡪ; -؁.ᡪ; [B1, P1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+xn----tkc.xn--68e; -؁.ᡪ; [B1, V3, V6]; xn----tkc.xn--68e; ; ; # -.ᡪ
+≮𝟕.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮𝟕.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖ß≯; ; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖ß≯; ≮7.謖ß≯; [P1, V6]; xn--7-mgo.xn--zca892oly5e; ; xn--7-mgo.xn--ss-xjvv174c; # ≮7.謖ß≯
+≮7.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖ss≯; ; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮7.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+xn--7-mgo.xn--ss-xjvv174c; ≮7.謖ss≯; [V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+xn--7-mgo.xn--zca892oly5e; ≮7.謖ß≯; [V6]; xn--7-mgo.xn--zca892oly5e; ; ; # ≮7.謖ß≯
+≮𝟕.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖SS≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+≮𝟕.謖Ss≯; ≮7.謖ss≯; [P1, V6]; xn--7-mgo.xn--ss-xjvv174c; ; ; # ≮7.謖ss≯
+朶Ⴉ𞪡.𝨽ࠥ📻-; ; [B1, B5, B6, P1, V3, V5, V6]; xn--hnd7245bd56p.xn----3gd37096apmwa; ; ; # 朶Ⴉ.𝨽ࠥ📻-
+朶ⴉ𞪡.𝨽ࠥ📻-; ; [B1, B5, B6, P1, V3, V5, V6]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻-
+xn--0kjz47pd57t.xn----3gd37096apmwa; 朶ⴉ𞪡.𝨽ࠥ📻-; [B1, B5, B6, V3, V5, V6]; xn--0kjz47pd57t.xn----3gd37096apmwa; ; ; # 朶ⴉ.𝨽ࠥ📻-
+xn--hnd7245bd56p.xn----3gd37096apmwa; 朶Ⴉ𞪡.𝨽ࠥ📻-; [B1, B5, B6, V3, V5, V6]; xn--hnd7245bd56p.xn----3gd37096apmwa; ; ; # 朶Ⴉ.𝨽ࠥ📻-
+𐤎。󑿰‌≮‍; 𐤎.󑿰‌≮‍; [B6, C1, C2, P1, V6]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, P1, V6] # 𐤎.≮
+𐤎。󑿰‌≮‍; 𐤎.󑿰‌≮‍; [B6, C1, C2, P1, V6]; xn--bk9c.xn--0ugc04p2u638c; ; xn--bk9c.xn--gdhx6802k; [B6, P1, V6] # 𐤎.≮
+xn--bk9c.xn--gdhx6802k; 𐤎.󑿰≮; [B6, V6]; xn--bk9c.xn--gdhx6802k; ; ; # 𐤎.≮
+xn--bk9c.xn--0ugc04p2u638c; 𐤎.󑿰‌≮‍; [B6, C1, C2, V6]; xn--bk9c.xn--0ugc04p2u638c; ; ; # 𐤎.≮
+񭜎⒈。‌𝟤; 񭜎⒈.‌2; [C1, P1, V6]; xn--tsh94183d.xn--2-rgn; ; xn--tsh94183d.2; [P1, V6] # ⒈.2
+񭜎1.。‌2; 񭜎1..‌2; [C1, P1, V6, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, P1, V6, A4_2]; xn--1-ex54e..2; [P1, V6, A4_2] # 1..2
+xn--1-ex54e..2; 񭜎1..2; [V6, X4_2]; xn--1-ex54e..2; [V6, A4_2]; ; # 1..2
+xn--1-ex54e..xn--2-rgn; 񭜎1..‌2; [C1, V6, X4_2]; xn--1-ex54e..xn--2-rgn; [C1, V6, A4_2]; ; # 1..2
+xn--tsh94183d.2; 񭜎⒈.2; [V6]; xn--tsh94183d.2; ; ; # ⒈.2
+xn--tsh94183d.xn--2-rgn; 񭜎⒈.‌2; [C1, V6]; xn--tsh94183d.xn--2-rgn; ; ; # ⒈.2
+󠟊𐹤‍.𐹳󙄵𐹶; 󠟊𐹤‍.𐹳󙄵𐹶; [B1, C2, P1, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, P1, V6] # 𐹤.𐹳𐹶
+󠟊𐹤‍.𐹳󙄵𐹶; ; [B1, C2, P1, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; xn--co0d98977c.xn--ro0dga22807v; [B1, P1, V6] # 𐹤.𐹳𐹶
+xn--co0d98977c.xn--ro0dga22807v; 󠟊𐹤.𐹳󙄵𐹶; [B1, V6]; xn--co0d98977c.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶
+xn--1ugy994g7k93g.xn--ro0dga22807v; 󠟊𐹤‍.𐹳󙄵𐹶; [B1, C2, V6]; xn--1ugy994g7k93g.xn--ro0dga22807v; ; ; # 𐹤.𐹳𐹶
+𞤴𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤴𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤒𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+xn--609c96c09grp2w.xn--n3b28708s; 𞤴𐹻𑓂𐭝.्􉛯; [B1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+𞤒𐹻𑓂𐭝.्︇􉛯; 𞤴𐹻𑓂𐭝.्􉛯; [B1, P1, V5, V6]; xn--609c96c09grp2w.xn--n3b28708s; ; ; # 𞤴𐹻𑓂𐭝.्
+٨。𐹠𐹽񗮶; ٨.𐹠𐹽񗮶; [B1, P1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+٨。𐹠𐹽񗮶; ٨.𐹠𐹽񗮶; [B1, P1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+xn--hib.xn--7n0d2bu9196b; ٨.𐹠𐹽񗮶; [B1, V6]; xn--hib.xn--7n0d2bu9196b; ; ; # ٨.𐹠𐹽
+ᅠ񍀜.8򶾵ڜ; ; [B1, P1, V6]; xn--psd85033d.xn--8-otc61545t; ; ; # .8ڜ
+xn--psd85033d.xn--8-otc61545t; ᅠ񍀜.8򶾵ڜ; [B1, V6]; xn--psd85033d.xn--8-otc61545t; ; ; # .8ڜ
+‍‌󠆪。ß𑓃; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃
+‍‌󠆪。ß𑓃; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; .xn--ss-bh7o; [A4_2] # .ß𑓃
+‍‌󠆪。SS𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。Ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+.xn--ss-bh7o; .ss𑓃; [X4_2]; .xn--ss-bh7o; [A4_2]; ; # .ss𑓃
+xn--0ugb.xn--ss-bh7o; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; ; # .ss𑓃
+xn--0ugb.xn--zca0732l; ‍‌.ß𑓃; [C1, C2]; xn--0ugb.xn--zca0732l; ; ; # .ß𑓃
+‍‌󠆪。SS𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+‍‌󠆪。Ss𑓃; ‍‌.ss𑓃; [C1, C2]; xn--0ugb.xn--ss-bh7o; ; .xn--ss-bh7o; [A4_2] # .ss𑓃
+xn--ss-bh7o; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+ss𑓃; ; ; xn--ss-bh7o; ; ; # ss𑓃
+SS𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+Ss𑓃; ss𑓃; ; xn--ss-bh7o; ; ; # ss𑓃
+︒‌ヶ䒩.ꡪ; ; [C1, P1, V6]; xn--0ug287dj0or48o.xn--gd9a; ; xn--qekw60dns9k.xn--gd9a; [P1, V6] # ︒ヶ䒩.ꡪ
+。‌ヶ䒩.ꡪ; .‌ヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; .xn--qekw60d.xn--gd9a; [A4_2] # .ヶ䒩.ꡪ
+.xn--qekw60d.xn--gd9a; .ヶ䒩.ꡪ; [X4_2]; .xn--qekw60d.xn--gd9a; [A4_2]; ; # .ヶ䒩.ꡪ
+.xn--0ug287dj0o.xn--gd9a; .‌ヶ䒩.ꡪ; [C1, X4_2]; .xn--0ug287dj0o.xn--gd9a; [C1, A4_2]; ; # .ヶ䒩.ꡪ
+xn--qekw60dns9k.xn--gd9a; ︒ヶ䒩.ꡪ; [V6]; xn--qekw60dns9k.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ
+xn--0ug287dj0or48o.xn--gd9a; ︒‌ヶ䒩.ꡪ; [C1, V6]; xn--0ug287dj0or48o.xn--gd9a; ; ; # ︒ヶ䒩.ꡪ
+xn--qekw60d.xn--gd9a; ヶ䒩.ꡪ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ
+ヶ䒩.ꡪ; ; ; xn--qekw60d.xn--gd9a; ; ; # ヶ䒩.ꡪ
+‌⒈𤮍.󢓋᩠; ; [C1, P1, V6]; xn--0ug88o7471d.xn--jof45148n; ; xn--tshw462r.xn--jof45148n; [P1, V6] # ⒈𤮍.᩠
+‌1.𤮍.󢓋᩠; ; [C1, P1, V6]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; 1.xn--4x6j.xn--jof45148n; [P1, V6] # 1.𤮍.᩠
+1.xn--4x6j.xn--jof45148n; 1.𤮍.󢓋᩠; [V6]; 1.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠
+xn--1-rgn.xn--4x6j.xn--jof45148n; ‌1.𤮍.󢓋᩠; [C1, V6]; xn--1-rgn.xn--4x6j.xn--jof45148n; ; ; # 1.𤮍.᩠
+xn--tshw462r.xn--jof45148n; ⒈𤮍.󢓋᩠; [V6]; xn--tshw462r.xn--jof45148n; ; ; # ⒈𤮍.᩠
+xn--0ug88o7471d.xn--jof45148n; ‌⒈𤮍.󢓋᩠; [C1, V6]; xn--0ug88o7471d.xn--jof45148n; ; ; # ⒈𤮍.᩠
+⒈‌𐫓󠀺。᩠񤰵‍; ⒈‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, P1, V5, V6]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; xn--tsh4435fk263g.xn--jofz5294e; [B1, P1, V5, V6] # ⒈𐫓.᩠
+1.‌𐫓󠀺。᩠񤰵‍; 1.‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, P1, V5, V6]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; 1.xn--8w9c40377c.xn--jofz5294e; [B1, B3, P1, V5, V6] # 1.𐫓.᩠
+1.xn--8w9c40377c.xn--jofz5294e; 1.𐫓󠀺.᩠񤰵; [B1, B3, V5, V6]; 1.xn--8w9c40377c.xn--jofz5294e; ; ; # 1.𐫓.᩠
+1.xn--0ug8853gk263g.xn--jof95xex98m; 1.‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, V5, V6]; 1.xn--0ug8853gk263g.xn--jof95xex98m; ; ; # 1.𐫓.᩠
+xn--tsh4435fk263g.xn--jofz5294e; ⒈𐫓󠀺.᩠񤰵; [B1, V5, V6]; xn--tsh4435fk263g.xn--jofz5294e; ; ; # ⒈𐫓.᩠
+xn--0ug78ol75wzcx4i.xn--jof95xex98m; ⒈‌𐫓󠀺.᩠񤰵‍; [B1, C1, C2, V5, V6]; xn--0ug78ol75wzcx4i.xn--jof95xex98m; ; ; # ⒈𐫓.᩠
+𝅵。𝟫𞀈䬺⒈; 𝅵.9𞀈䬺⒈; [P1, V6]; xn--3f1h.xn--9-ecp936non25a; ; ; # .9𞀈䬺⒈
+𝅵。9𞀈䬺1.; 𝅵.9𞀈䬺1.; [P1, V6]; xn--3f1h.xn--91-030c1650n.; ; ; # .9𞀈䬺1.
+xn--3f1h.xn--91-030c1650n.; 𝅵.9𞀈䬺1.; [V6]; xn--3f1h.xn--91-030c1650n.; ; ; # .9𞀈䬺1.
+xn--3f1h.xn--9-ecp936non25a; 𝅵.9𞀈䬺⒈; [V6]; xn--3f1h.xn--9-ecp936non25a; ; ; # .9𞀈䬺⒈
+򡼺≯。盚ص; 򡼺≯.盚ص; [B5, B6, P1, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+򡼺≯。盚ص; 򡼺≯.盚ص; [B5, B6, P1, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+xn--hdh30181h.xn--0gb7878c; 򡼺≯.盚ص; [B5, B6, V6]; xn--hdh30181h.xn--0gb7878c; ; ; # ≯.盚ص
+-񿰭ִ。-󠁊𐢸≯; -񿰭ִ.-󠁊𐢸≯; [B1, P1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+-񿰭ִ。-󠁊𐢸≯; -񿰭ִ.-󠁊𐢸≯; [B1, P1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+xn----fgc06667m.xn----pgoy615he5y4i; -񿰭ִ.-󠁊𐢸≯; [B1, V3, V6]; xn----fgc06667m.xn----pgoy615he5y4i; ; ; # -ִ.-≯
+󿭓᭄‌੍.𐭛񳋔; 󿭓᭄‌੍.𐭛񳋔; [B2, B3, B6, P1, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, P1, V6] # ᭄੍.𐭛
+󿭓᭄‌੍.𐭛񳋔; ; [B2, B3, B6, P1, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; xn--ybc997fb5881a.xn--409c6100y; [B2, B3, P1, V6] # ᭄੍.𐭛
+xn--ybc997fb5881a.xn--409c6100y; 󿭓᭄੍.𐭛񳋔; [B2, B3, V6]; xn--ybc997fb5881a.xn--409c6100y; ; ; # ᭄੍.𐭛
+xn--ybc997f6rd2n772c.xn--409c6100y; 󿭓᭄‌੍.𐭛񳋔; [B2, B3, B6, V6]; xn--ybc997f6rd2n772c.xn--409c6100y; ; ; # ᭄੍.𐭛
+⾇.ٽ𞤴ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+舛.ٽ𞤴ڻ‍; ; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+舛.ٽ𞤒ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+xn--8c1a.xn--2ib8jn539l; 舛.ٽ𞤴ڻ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+舛.ٽ𞤴ڻ; ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+舛.ٽ𞤒ڻ; 舛.ٽ𞤴ڻ; ; xn--8c1a.xn--2ib8jn539l; ; ; # 舛.ٽ𞤴ڻ
+xn--8c1a.xn--2ib8jv19e6413b; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; ; # 舛.ٽ𞤴ڻ
+⾇.ٽ𞤒ڻ‍; 舛.ٽ𞤴ڻ‍; [B3, C2]; xn--8c1a.xn--2ib8jv19e6413b; ; xn--8c1a.xn--2ib8jn539l; [] # 舛.ٽ𞤴ڻ
+4򭆥。ݧ≯; 4򭆥.ݧ≯; [B1, B3, P1, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+4򭆥。ݧ≯; 4򭆥.ݧ≯; [B1, B3, P1, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+xn--4-xn17i.xn--rpb459k; 4򭆥.ݧ≯; [B1, B3, V6]; xn--4-xn17i.xn--rpb459k; ; ; # 4.ݧ≯
+𲔏𞫨񺿂硲.ڭ; 𲔏𞫨񺿂硲.ڭ; [B5, P1, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+𲔏𞫨񺿂硲.ڭ; ; [B5, P1, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+xn--lcz1610fn78gk609a.xn--gkb; 𲔏𞫨񺿂硲.ڭ; [B5, V6]; xn--lcz1610fn78gk609a.xn--gkb; ; ; # 硲.ڭ
+‌.︈٦Ⴆ℮; ‌.٦Ⴆ℮; [B1, C1, P1, V6]; xn--0ug.xn--fib263c0yn; ; .xn--fib263c0yn; [B1, P1, V6, A4_2] # .٦Ⴆ℮
+‌.︈٦ⴆ℮; ‌.٦ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; .xn--fib628k4li; [B1, A4_2] # .٦ⴆ℮
+.xn--fib628k4li; .٦ⴆ℮; [B1, X4_2]; .xn--fib628k4li; [B1, A4_2]; ; # .٦ⴆ℮
+xn--0ug.xn--fib628k4li; ‌.٦ⴆ℮; [B1, C1]; xn--0ug.xn--fib628k4li; ; ; # .٦ⴆ℮
+.xn--fib263c0yn; .٦Ⴆ℮; [B1, V6, X4_2]; .xn--fib263c0yn; [B1, V6, A4_2]; ; # .٦Ⴆ℮
+xn--0ug.xn--fib263c0yn; ‌.٦Ⴆ℮; [B1, C1, V6]; xn--0ug.xn--fib263c0yn; ; ; # .٦Ⴆ℮
+ڣ.്‍Ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+ڣ.്‍Ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+ڣ.്‍ϟ; ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+xn--5jb.xn--xya149b; ڣ.്ϟ; [B1, V5]; xn--5jb.xn--xya149b; ; ; # ڣ.്ϟ
+xn--5jb.xn--xya149bpvp; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; ; # ڣ.്ϟ
+ڣ.്‍ϟ; ڣ.്‍ϟ; [B1, V5]; xn--5jb.xn--xya149bpvp; ; xn--5jb.xn--xya149b; # ڣ.്ϟ
+‌𞸇𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌𞸇𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌ح𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+‌ح𑘿。أ𐮂-腍; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; xn--sgb4140l.xn----qmc5075grs9e; [B2, B3] # ح𑘿.أ𐮂-腍
+xn--sgb4140l.xn----qmc5075grs9e; ح𑘿.أ𐮂-腍; [B2, B3]; xn--sgb4140l.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍
+xn--sgb953kmi8o.xn----qmc5075grs9e; ‌ح𑘿.أ𐮂-腍; [B1, B2, B3, C1]; xn--sgb953kmi8o.xn----qmc5075grs9e; ; ; # ح𑘿.أ𐮂-腍
+-򭷙٫纛。𝟛񭤇🄅; -򭷙٫纛.3񭤇🄅; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--3-os1sn476y; ; ; # -٫纛.3🄅
+-򭷙٫纛。3񭤇4,; -򭷙٫纛.3񭤇4,; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34,
+xn----vqc8143g0tt4i.xn--34,-8787l; -򭷙٫纛.3񭤇4,; [B1, P1, V3, V6]; xn----vqc8143g0tt4i.xn--34,-8787l; ; ; # -٫纛.34,
+xn----vqc8143g0tt4i.xn--3-os1sn476y; -򭷙٫纛.3񭤇🄅; [B1, V3, V6]; xn----vqc8143g0tt4i.xn--3-os1sn476y; ; ; # -٫纛.3🄅
+🔔.Ⴂߌ்𐋮; 🔔.Ⴂߌ்𐋮; [B1, B5, P1, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.Ⴂߌ்𐋮; ; [B1, B5, P1, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.ⴂߌ்𐋮; ; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+xn--nv8h.xn--nsb46rvz1b222p; 🔔.ⴂߌ்𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+xn--nv8h.xn--nsb46r83e8112a; 🔔.Ⴂߌ்𐋮; [B1, B5, V6]; xn--nv8h.xn--nsb46r83e8112a; ; ; # 🔔.Ⴂߌ்𐋮
+🔔.ⴂߌ்𐋮; 🔔.ⴂߌ்𐋮; [B1, B5]; xn--nv8h.xn--nsb46rvz1b222p; ; ; # 🔔.ⴂߌ்𐋮
+軥ڳ.-𖬵; ; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵
+xn--mkb5480e.xn----6u5m; 軥ڳ.-𖬵; [B1, B5, B6, V3]; xn--mkb5480e.xn----6u5m; ; ; # 軥ڳ.-𖬵
+𐹤ߊڶ.𐨂-; ; [B1, V3, V5]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂-
+xn--pkb56cn614d.xn----974i; 𐹤ߊڶ.𐨂-; [B1, V3, V5]; xn--pkb56cn614d.xn----974i; ; ; # 𐹤ߊڶ.𐨂-
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-󠅱0。៏᷽톇십; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+-0.xn--r4e872ah77nghm; -0.៏᷽톇십; [V3, V5]; -0.xn--r4e872ah77nghm; ; ; # -0.៏᷽톇십
+ꡰ︒--。៌靈𐹢񘳮; ꡰ︒--.៌靈𐹢񘳮; [B1, B6, P1, V2, V3, V5, V6]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢
+ꡰ。--。៌靈𐹢񘳮; ꡰ.--.៌靈𐹢񘳮; [B1, P1, V3, V5, V6]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢
+xn--md9a.--.xn--o4e6836dpxudz0v1c; ꡰ.--.៌靈𐹢񘳮; [B1, V3, V5, V6]; xn--md9a.--.xn--o4e6836dpxudz0v1c; ; ; # ꡰ.--.៌靈𐹢
+xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ꡰ︒--.៌靈𐹢񘳮; [B1, B6, V2, V3, V5, V6]; xn-----bk9hu24z.xn--o4e6836dpxudz0v1c; ; ; # ꡰ︒--.៌靈𐹢
+ᅟႿႵრ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟႿႵრ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟⴟⴕრ。୍; ᅟⴟⴕრ.୍; [P1, V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟႿႵᲠ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+xn--tndt4hvw.xn--9ic; ᅟႿႵრ.୍; [V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+xn--1od7wz74eeb.xn--9ic; ᅟⴟⴕრ.୍; [V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟⴟⴕრ。୍; ᅟⴟⴕრ.୍; [P1, V5, V6]; xn--1od7wz74eeb.xn--9ic; ; ; # ⴟⴕრ.୍
+ᅟႿႵᲠ。୍; ᅟႿႵრ.୍; [P1, V5, V6]; xn--tndt4hvw.xn--9ic; ; ; # ႿႵრ.୍
+ᅟႿⴕრ。୍; ᅟႿⴕრ.୍; [P1, V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+xn--3nd0etsm92g.xn--9ic; ᅟႿⴕრ.୍; [V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+ᅟႿⴕრ。୍; ᅟႿⴕრ.୍; [P1, V5, V6]; xn--3nd0etsm92g.xn--9ic; ; ; # Ⴟⴕრ.୍
+🄃𐹠.٤󠅇; 🄃𐹠.٤; [B1, P1, V6]; xn--7n0d1189a.xn--dib; ; ; # 🄃𐹠.٤
+2,𐹠.٤󠅇; 2,𐹠.٤; [B1, P1, V6]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤
+xn--2,-5g3o.xn--dib; 2,𐹠.٤; [B1, P1, V6]; xn--2,-5g3o.xn--dib; ; ; # 2,𐹠.٤
+xn--7n0d1189a.xn--dib; 🄃𐹠.٤; [B1, V6]; xn--7n0d1189a.xn--dib; ; ; # 🄃𐹠.٤
+򻲼‌ﱛ.ߒࡈ᯳; 򻲼‌ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, C1, P1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, P1, V6] # ذٰ.ߒࡈ᯳
+򻲼‌ذٰ.ߒࡈ᯳; ; [B2, B3, B5, B6, C1, P1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; xn--vgb2kp1223g.xn--tsb0vz43c; [B2, B3, B5, B6, P1, V6] # ذٰ.ߒࡈ᯳
+xn--vgb2kp1223g.xn--tsb0vz43c; 򻲼ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, V6]; xn--vgb2kp1223g.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳
+xn--vgb2kq00fl213y.xn--tsb0vz43c; 򻲼‌ذٰ.ߒࡈ᯳; [B2, B3, B5, B6, C1, V6]; xn--vgb2kq00fl213y.xn--tsb0vz43c; ; ; # ذٰ.ߒࡈ᯳
+‍‍𞵪‌。ᡘ𑲭឵; ‍‍𞵪‌.ᡘ𑲭឵; [B1, C1, C2, P1, V6]; xn--0ugba05538b.xn--03e93aq365d; ; xn--l96h.xn--03e93aq365d; [P1, V6] # .ᡘ𑲭
+xn--l96h.xn--03e93aq365d; 𞵪.ᡘ𑲭឵; [V6]; xn--l96h.xn--03e93aq365d; ; ; # .ᡘ𑲭
+xn--0ugba05538b.xn--03e93aq365d; ‍‍𞵪‌.ᡘ𑲭឵; [B1, C1, C2, V6]; xn--0ugba05538b.xn--03e93aq365d; ; ; # .ᡘ𑲭
+𞷻。⚄񗑇𑁿; 𞷻.⚄񗑇𑁿; [B1, P1, V6]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿
+xn--qe7h.xn--c7h2966f7so4a; 𞷻.⚄񗑇𑁿; [B1, V6]; xn--qe7h.xn--c7h2966f7so4a; ; ; # .⚄𑁿
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+꣄≠.𞠨٧; ꣄≠.𞠨٧; [B1, P1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+xn--1chy504c.xn--gib1777v; ꣄≠.𞠨٧; [B1, V5, V6]; xn--1chy504c.xn--gib1777v; ; ; # ꣄≠.𞠨٧
+𝟛꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+𝟛꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+3꣄𝆪。꣪-; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+xn--3-sl4eu679e.xn----xn4e; 3꣄𝆪.꣪-; [V3, V5]; xn--3-sl4eu679e.xn----xn4e; ; ; # 3꣄𝆪.꣪-
+ݟᮢ်Ⴇ.4; ; [B1, B2, B3, P1, V6]; xn--jpb846bmjw88a.4; ; ; # ݟᮢ်Ⴇ.4
+ݟᮢ်ⴇ.4; ; [B1, B2, B3]; xn--jpb846bjzj7pr.4; ; ; # ݟᮢ်ⴇ.4
+xn--jpb846bjzj7pr.4; ݟᮢ်ⴇ.4; [B1, B2, B3]; xn--jpb846bjzj7pr.4; ; ; # ݟᮢ်ⴇ.4
+xn--jpb846bmjw88a.4; ݟᮢ်Ⴇ.4; [B1, B2, B3, V6]; xn--jpb846bmjw88a.4; ; ; # ݟᮢ်Ⴇ.4
+ᄹ。໊򠯤󠄞; ᄹ.໊򠯤; [P1, V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+ᄹ。໊򠯤󠄞; ᄹ.໊򠯤; [P1, V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+xn--lrd.xn--s8c05302k; ᄹ.໊򠯤; [V5, V6]; xn--lrd.xn--s8c05302k; ; ; # ᄹ.໊
+Ⴆ򻢩.󠆡︉𞤍; Ⴆ򻢩.𞤯; [P1, V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+Ⴆ򻢩.󠆡︉𞤍; Ⴆ򻢩.𞤯; [P1, V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤯; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+xn--xkjw3965g.xn--ne6h; ⴆ򻢩.𞤯; [V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+xn--end82983m.xn--ne6h; Ⴆ򻢩.𞤯; [V6]; xn--end82983m.xn--ne6h; ; ; # Ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤯; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤍; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ⴆ򻢩.󠆡︉𞤍; ⴆ򻢩.𞤯; [P1, V6]; xn--xkjw3965g.xn--ne6h; ; ; # ⴆ.𞤯
+ßࠋ︒ٻ.帼F∬‌; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ßࠋ︒ٻ.帼f∫∫
+ßࠋ。ٻ.帼F∫∫‌; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫
+ßࠋ。ٻ.帼f∫∫‌; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ßࠋ.ٻ.帼f∫∫
+SSࠋ。ٻ.帼F∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+ssࠋ。ٻ.帼f∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+Ssࠋ。ٻ.帼F∫∫‌; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; [B5, B6] # ssࠋ.ٻ.帼f∫∫
+xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ssࠋ.ٻ.帼f∫∫; [B5, B6]; xn--ss-uze.xn--0ib.xn--f-tcoa9162d; ; ; # ssࠋ.ٻ.帼f∫∫
+xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ssࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--ss-uze.xn--0ib.xn--f-sgn48ga6997e; ; ; # ssࠋ.ٻ.帼f∫∫
+xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ßࠋ.ٻ.帼f∫∫‌; [B5, B6, C1]; xn--zca687a.xn--0ib.xn--f-sgn48ga6997e; ; ; # ßࠋ.ٻ.帼f∫∫
+ßࠋ︒ٻ.帼f∬‌; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ßࠋ︒ٻ.帼f∫∫
+SSࠋ︒ٻ.帼F∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+ssࠋ︒ٻ.帼f∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+Ssࠋ︒ٻ.帼F∬‌; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, P1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; xn--ss-k0d31nu121d.xn--f-tcoa9162d; [B5, B6, P1, V6] # ssࠋ︒ٻ.帼f∫∫
+xn--ss-k0d31nu121d.xn--f-tcoa9162d; ssࠋ︒ٻ.帼f∫∫; [B5, B6, V6]; xn--ss-k0d31nu121d.xn--f-tcoa9162d; ; ; # ssࠋ︒ٻ.帼f∫∫
+xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ssࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, V6]; xn--ss-k0d31nu121d.xn--f-sgn48ga6997e; ; ; # ssࠋ︒ٻ.帼f∫∫
+xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ßࠋ︒ٻ.帼f∫∫‌; [B5, B6, C1, V6]; xn--zca68zj8ac956c.xn--f-sgn48ga6997e; ; ; # ßࠋ︒ٻ.帼f∫∫
+󘪗。𐹴𞨌‍; 󘪗.𐹴𞨌‍; [B1, C2, P1, V6]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, P1, V6] # .𐹴
+󘪗。𐹴𞨌‍; 󘪗.𐹴𞨌‍; [B1, C2, P1, V6]; xn--8l83e.xn--1ug4105gsxwf; ; xn--8l83e.xn--so0dw168a; [B1, P1, V6] # .𐹴
+xn--8l83e.xn--so0dw168a; 󘪗.𐹴𞨌; [B1, V6]; xn--8l83e.xn--so0dw168a; ; ; # .𐹴
+xn--8l83e.xn--1ug4105gsxwf; 󘪗.𐹴𞨌‍; [B1, C2, V6]; xn--8l83e.xn--1ug4105gsxwf; ; ; # .𐹴
+񗛨.򅟢𝟨꣄; 񗛨.򅟢6꣄; [P1, V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+񗛨.򅟢6꣄; ; [P1, V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+xn--mi60a.xn--6-sl4es8023c; 񗛨.򅟢6꣄; [V6]; xn--mi60a.xn--6-sl4es8023c; ; ; # .6꣄
+᪲ﶎ。-۹ႱႨ; ᪲مخج.-۹ႱႨ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲مخج。-۹ႱႨ; ᪲مخج.-۹ႱႨ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲مخج。-۹ⴑⴈ; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+xn--rgbd2e831i.xn----zyc3430a9a; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+xn--rgbd2e831i.xn----zyc155e9a; ᪲مخج.-۹ႱႨ; [B1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc155e9a; ; ; # ᪲مخج.-۹ႱႨ
+᪲ﶎ。-۹ⴑⴈ; ᪲مخج.-۹ⴑⴈ; [B1, V3, V5]; xn--rgbd2e831i.xn----zyc3430a9a; ; ; # ᪲مخج.-۹ⴑⴈ
+᪲مخج。-۹Ⴑⴈ; ᪲مخج.-۹Ⴑⴈ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+xn--rgbd2e831i.xn----zyc875efr3a; ᪲مخج.-۹Ⴑⴈ; [B1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+᪲ﶎ。-۹Ⴑⴈ; ᪲مخج.-۹Ⴑⴈ; [B1, P1, V3, V5, V6]; xn--rgbd2e831i.xn----zyc875efr3a; ; ; # ᪲مخج.-۹Ⴑⴈ
+𞤤.-ࢣ︒; 𞤤.-ࢣ︒; [B1, P1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+𞤤.-ࢣ。; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+𞤂.-ࢣ。; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+xn--ce6h.xn----cod.; 𞤤.-ࢣ.; [B1, V3]; xn--ce6h.xn----cod.; ; ; # 𞤤.-ࢣ.
+𞤂.-ࢣ︒; 𞤤.-ࢣ︒; [B1, P1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+xn--ce6h.xn----cod7069p; 𞤤.-ࢣ︒; [B1, V3, V6]; xn--ce6h.xn----cod7069p; ; ; # 𞤤.-ࢣ︒
+‌𐺨.࡙--; ; [B1, C1, V3, V5]; xn--0ug7905g.xn-----h6e; ; xn--9p0d.xn-----h6e; [B1, V3, V5] # 𐺨.࡙--
+xn--9p0d.xn-----h6e; 𐺨.࡙--; [B1, V3, V5]; xn--9p0d.xn-----h6e; ; ; # 𐺨.࡙--
+xn--0ug7905g.xn-----h6e; ‌𐺨.࡙--; [B1, C1, V3, V5]; xn--0ug7905g.xn-----h6e; ; ; # 𐺨.࡙--
+𐋸󮘋Ⴢ.Ⴁ; ; [P1, V6]; xn--6nd5215jr2u0h.xn--8md; ; ; # 𐋸Ⴢ.Ⴁ
+𐋸󮘋ⴢ.ⴁ; ; [P1, V6]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ
+𐋸󮘋Ⴢ.ⴁ; ; [P1, V6]; xn--6nd5215jr2u0h.xn--skj; ; ; # 𐋸Ⴢ.ⴁ
+xn--6nd5215jr2u0h.xn--skj; 𐋸󮘋Ⴢ.ⴁ; [V6]; xn--6nd5215jr2u0h.xn--skj; ; ; # 𐋸Ⴢ.ⴁ
+xn--qlj1559dr224h.xn--skj; 𐋸󮘋ⴢ.ⴁ; [V6]; xn--qlj1559dr224h.xn--skj; ; ; # 𐋸ⴢ.ⴁ
+xn--6nd5215jr2u0h.xn--8md; 𐋸󮘋Ⴢ.Ⴁ; [V6]; xn--6nd5215jr2u0h.xn--8md; ; ; # 𐋸Ⴢ.Ⴁ
+񗑿꠆₄򩞆。𲩧󠒹ς; 񗑿꠆4򩞆.𲩧󠒹ς; [P1, V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς
+񗑿꠆4򩞆。𲩧󠒹ς; 񗑿꠆4򩞆.𲩧󠒹ς; [P1, V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; # ꠆4.ς
+񗑿꠆4򩞆。𲩧󠒹Σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+񗑿꠆4򩞆。𲩧󠒹σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; 񗑿꠆4򩞆.𲩧󠒹σ; [V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; 񗑿꠆4򩞆.𲩧󠒹ς; [V6]; xn--4-w93ej7463a9io5a.xn--3xa51142bk3f0d; ; ; # ꠆4.ς
+񗑿꠆₄򩞆。𲩧󠒹Σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+񗑿꠆₄򩞆。𲩧󠒹σ; 񗑿꠆4򩞆.𲩧󠒹σ; [P1, V6]; xn--4-w93ej7463a9io5a.xn--4xa31142bk3f0d; ; ; # ꠆4.σ
+󠆀ܣ。ᷴݵ; ܣ.ᷴݵ; [B1, V5]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ
+xn--tnb.xn--5pb136i; ܣ.ᷴݵ; [B1, V5]; xn--tnb.xn--5pb136i; ; ; # ܣ.ᷴݵ
+𐹱ࡂ𝪨。𬼖Ⴑ‍; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, P1, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; xn--0vb1535kdb6e.xn--pnd93707a; [B1, P1, V6] # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖Ⴑ‍; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, P1, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; xn--0vb1535kdb6e.xn--pnd93707a; [B1, P1, V6] # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖ⴑ‍; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--8kjz186s; 𐹱ࡂ𝪨.𬼖ⴑ; [B1]; xn--0vb1535kdb6e.xn--8kjz186s; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--1ug742c5714c; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; ; # 𐹱ࡂ𝪨.𬼖ⴑ
+xn--0vb1535kdb6e.xn--pnd93707a; 𐹱ࡂ𝪨.𬼖Ⴑ; [B1, V6]; xn--0vb1535kdb6e.xn--pnd93707a; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ
+xn--0vb1535kdb6e.xn--pnd879eqy33c; 𐹱ࡂ𝪨.𬼖Ⴑ‍; [B1, B6, C2, V6]; xn--0vb1535kdb6e.xn--pnd879eqy33c; ; ; # 𐹱ࡂ𝪨.𬼖Ⴑ
+𐹱ࡂ𝪨。𬼖ⴑ‍; 𐹱ࡂ𝪨.𬼖ⴑ‍; [B1, B6, C2]; xn--0vb1535kdb6e.xn--1ug742c5714c; ; xn--0vb1535kdb6e.xn--8kjz186s; [B1] # 𐹱ࡂ𝪨.𬼖ⴑ
+᜔𐭪󠙘‍。-𐹴; ᜔𐭪󠙘‍.-𐹴; [B1, C2, P1, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, P1, V3, V5, V6] # ᜔𐭪.-𐹴
+᜔𐭪󠙘‍。-𐹴; ᜔𐭪󠙘‍.-𐹴; [B1, C2, P1, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; xn--fze4126jujt0g.xn----c36i; [B1, P1, V3, V5, V6] # ᜔𐭪.-𐹴
+xn--fze4126jujt0g.xn----c36i; ᜔𐭪󠙘.-𐹴; [B1, V3, V5, V6]; xn--fze4126jujt0g.xn----c36i; ; ; # ᜔𐭪.-𐹴
+xn--fze807bso0spy14i.xn----c36i; ᜔𐭪󠙘‍.-𐹴; [B1, C2, V3, V5, V6]; xn--fze807bso0spy14i.xn----c36i; ; ; # ᜔𐭪.-𐹴
+𾢬。ܩ︒쯙𝟧; 𾢬.ܩ︒쯙5; [B2, P1, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𾢬。ܩ︒쯙𝟧; 𾢬.ܩ︒쯙5; [B2, P1, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𾢬。ܩ。쯙5; 𾢬.ܩ.쯙5; [P1, V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+𾢬。ܩ。쯙5; 𾢬.ܩ.쯙5; [P1, V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+xn--t92s.xn--znb.xn--5-y88f; 𾢬.ܩ.쯙5; [V6]; xn--t92s.xn--znb.xn--5-y88f; ; ; # .ܩ.쯙5
+xn--t92s.xn--5-p1c0712mm8rb; 𾢬.ܩ︒쯙5; [B2, V6]; xn--t92s.xn--5-p1c0712mm8rb; ; ; # .ܩ︒쯙5
+𞤟-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞤟-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥁-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥁-。ݢ≮뻐; 𞥁-.ݢ≮뻐; [B2, B3, P1, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+xn----1j8r.xn--mpb269krv4i; 𞥁-.ݢ≮뻐; [B2, B3, V3, V6]; xn----1j8r.xn--mpb269krv4i; ; ; # 𞥁-.ݢ≮뻐
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; ; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+𞥩-򊫠.ࢴ≠; 𞥩-򊫠.ࢴ≠; [B2, B3, P1, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+xn----cm8rp3609a.xn--9yb852k; 𞥩-򊫠.ࢴ≠; [B2, B3, V6]; xn----cm8rp3609a.xn--9yb852k; ; ; # -.ࢴ≠
+-񅂏ςႼ.١; -񅂏ςႼ.١; [B1, P1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; xn----0mb770hun11i.xn--9hb; # -ςႼ.١
+-񅂏ςႼ.١; ; [B1, P1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; xn----0mb770hun11i.xn--9hb; # -ςႼ.١
+-񅂏ςⴜ.١; ; [B1, P1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١
+-񅂏ΣႼ.١; -񅂏σႼ.١; [B1, P1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+-񅂏σⴜ.١; ; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+-񅂏Σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+xn----0mb9682aov12f.xn--9hb; -񅂏σⴜ.١; [B1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+xn----0mb770hun11i.xn--9hb; -񅂏σႼ.١; [B1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+xn----ymb2782aov12f.xn--9hb; -񅂏ςⴜ.١; [B1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; ; # -ςⴜ.١
+xn----ymb080hun11i.xn--9hb; -񅂏ςႼ.١; [B1, V3, V6]; xn----ymb080hun11i.xn--9hb; ; ; # -ςႼ.١
+-񅂏ςⴜ.١; -񅂏ςⴜ.١; [B1, P1, V3, V6]; xn----ymb2782aov12f.xn--9hb; ; xn----0mb9682aov12f.xn--9hb; # -ςⴜ.١
+-񅂏ΣႼ.١; -񅂏σႼ.١; [B1, P1, V3, V6]; xn----0mb770hun11i.xn--9hb; ; ; # -σႼ.١
+-񅂏σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+-񅂏Σⴜ.١; -񅂏σⴜ.١; [B1, P1, V3, V6]; xn----0mb9682aov12f.xn--9hb; ; ; # -σⴜ.١
+៊.‍𝟮𑀿; ៊.‍2𑀿; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V5] # ៊.2𑀿
+៊.‍2𑀿; ; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; xn--m4e.xn--2-ku7i; [V5] # ៊.2𑀿
+xn--m4e.xn--2-ku7i; ៊.2𑀿; [V5]; xn--m4e.xn--2-ku7i; ; ; # ៊.2𑀿
+xn--m4e.xn--2-tgnv469h; ៊.‍2𑀿; [C2, V5]; xn--m4e.xn--2-tgnv469h; ; ; # ៊.2𑀿
+≯𝟖。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯𝟖。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯8。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+≯8。᩠𐫓򟇑; ≯8.᩠𐫓򟇑; [B1, P1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+xn--8-ogo.xn--jof5303iv1z5d; ≯8.᩠𐫓򟇑; [B1, V5, V6]; xn--8-ogo.xn--jof5303iv1z5d; ; ; # ≯8.᩠𐫓
+𑲫Ↄ٤。‌; 𑲫Ↄ٤.‌; [B1, C1, P1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; xn--dib999kcy1p.; [B1, P1, V5, V6] # 𑲫Ↄ٤.
+𑲫Ↄ٤。‌; 𑲫Ↄ٤.‌; [B1, C1, P1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; xn--dib999kcy1p.; [B1, P1, V5, V6] # 𑲫Ↄ٤.
+𑲫ↄ٤。‌; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V5] # 𑲫ↄ٤.
+xn--dib100l8x1p.; 𑲫ↄ٤.; [B1, V5]; xn--dib100l8x1p.; ; ; # 𑲫ↄ٤.
+xn--dib100l8x1p.xn--0ug; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; ; # 𑲫ↄ٤.
+xn--dib999kcy1p.; 𑲫Ↄ٤.; [B1, V5, V6]; xn--dib999kcy1p.; ; ; # 𑲫Ↄ٤.
+xn--dib999kcy1p.xn--0ug; 𑲫Ↄ٤.‌; [B1, C1, V5, V6]; xn--dib999kcy1p.xn--0ug; ; ; # 𑲫Ↄ٤.
+𑲫ↄ٤。‌; 𑲫ↄ٤.‌; [B1, C1, V5]; xn--dib100l8x1p.xn--0ug; ; xn--dib100l8x1p.; [B1, V5] # 𑲫ↄ٤.
+ఀ𝟵‍ﲝ.‍ݐ⒈; ఀ9‍بح.‍ݐ⒈; [B1, C2, P1, V5, V6]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; xn--9-1mcp570d.xn--3ob470m; [B1, P1, V5, V6] # ఀ9بح.ݐ⒈
+ఀ9‍بح.‍ݐ1.; ; [B1, C2, V5]; xn--9-1mcp570dl51a.xn--1-x3c211q.; ; xn--9-1mcp570d.xn--1-x3c.; [B1, V5] # ఀ9بح.ݐ1.
+xn--9-1mcp570d.xn--1-x3c.; ఀ9بح.ݐ1.; [B1, V5]; xn--9-1mcp570d.xn--1-x3c.; ; ; # ఀ9بح.ݐ1.
+xn--9-1mcp570dl51a.xn--1-x3c211q.; ఀ9‍بح.‍ݐ1.; [B1, C2, V5]; xn--9-1mcp570dl51a.xn--1-x3c211q.; ; ; # ఀ9بح.ݐ1.
+xn--9-1mcp570d.xn--3ob470m; ఀ9بح.ݐ⒈; [B1, V5, V6]; xn--9-1mcp570d.xn--3ob470m; ; ; # ఀ9بح.ݐ⒈
+xn--9-1mcp570dl51a.xn--3ob977jmfd; ఀ9‍بح.‍ݐ⒈; [B1, C2, V5, V6]; xn--9-1mcp570dl51a.xn--3ob977jmfd; ; ; # ఀ9بح.ݐ⒈
+꫶。嬶ß葽; ꫶.嬶ß葽; [V5]; xn--2v9a.xn--zca7637b14za; ; xn--2v9a.xn--ss-q40dp97m; # ꫶.嬶ß葽
+꫶。嬶SS葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+꫶。嬶ss葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+꫶。嬶Ss葽; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+xn--2v9a.xn--ss-q40dp97m; ꫶.嬶ss葽; [V5]; xn--2v9a.xn--ss-q40dp97m; ; ; # ꫶.嬶ss葽
+xn--2v9a.xn--zca7637b14za; ꫶.嬶ß葽; [V5]; xn--2v9a.xn--zca7637b14za; ; ; # ꫶.嬶ß葽
+𑚶⒈。񞻡𐹺; 𑚶⒈.񞻡𐹺; [B5, B6, P1, V5, V6]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺
+𑚶1.。񞻡𐹺; 𑚶1..񞻡𐹺; [B5, B6, P1, V5, V6, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, P1, V5, V6, A4_2]; ; # 𑚶1..𐹺
+xn--1-3j0j..xn--yo0d5914s; 𑚶1..񞻡𐹺; [B5, B6, V5, V6, X4_2]; xn--1-3j0j..xn--yo0d5914s; [B5, B6, V5, V6, A4_2]; ; # 𑚶1..𐹺
+xn--tshz969f.xn--yo0d5914s; 𑚶⒈.񞻡𐹺; [B5, B6, V5, V6]; xn--tshz969f.xn--yo0d5914s; ; ; # 𑚶⒈.𐹺
+𑜤︒≮.񚕽ט𞾩; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, P1, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+𑜤︒≮.񚕽ט𞾩; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, P1, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+𑜤。≮.񚕽ט𞾩; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, P1, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+𑜤。≮.񚕽ט𞾩; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, P1, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+xn--ci2d.xn--gdh.xn--deb0091w5q9u; 𑜤.≮.񚕽ט𞾩; [B1, B3, B5, B6, V5, V6]; xn--ci2d.xn--gdh.xn--deb0091w5q9u; ; ; # 𑜤.≮.ט
+xn--gdh5267fdzpa.xn--deb0091w5q9u; 𑜤︒≮.񚕽ט𞾩; [B1, B5, B6, V5, V6]; xn--gdh5267fdzpa.xn--deb0091w5q9u; ; ; # 𑜤︒≮.ט
+󠆋؃񏦤.⇁ς򏋈򺇥; ؃񏦤.⇁ς򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; xn--lfb04106d.xn--4xa964mxv16m8moq; # .⇁ς
+󠆋؃񏦤.⇁Σ򏋈򺇥; ؃񏦤.⇁σ򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+󠆋؃񏦤.⇁σ򏋈򺇥; ؃񏦤.⇁σ򏋈򺇥; [B1, P1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+xn--lfb04106d.xn--4xa964mxv16m8moq; ؃񏦤.⇁σ򏋈򺇥; [B1, V6]; xn--lfb04106d.xn--4xa964mxv16m8moq; ; ; # .⇁σ
+xn--lfb04106d.xn--3xa174mxv16m8moq; ؃񏦤.⇁ς򏋈򺇥; [B1, V6]; xn--lfb04106d.xn--3xa174mxv16m8moq; ; ; # .⇁ς
+ς𑐽𵢈𑜫。𞬩‌𐫄; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # ς𑐽𑜫.𐫄
+ς𑐽𵢈𑜫。𞬩‌𐫄; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # ς𑐽𑜫.𐫄
+Σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+xn--4xa2260lk3b8z15g.xn--tw9ct349a; σ𑐽𵢈𑜫.𞬩𐫄; [V6]; xn--4xa2260lk3b8z15g.xn--tw9ct349a; ; ; # σ𑐽𑜫.𐫄
+xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; ; # σ𑐽𑜫.𐫄
+xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ς𑐽𵢈𑜫.𞬩‌𐫄; [C1, V6]; xn--3xa4260lk3b8z15g.xn--0ug4653g2xzf; ; ; # ς𑐽𑜫.𐫄
+Σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+σ𑐽𵢈𑜫。𞬩‌𐫄; σ𑐽𵢈𑜫.𞬩‌𐫄; [C1, P1, V6]; xn--4xa2260lk3b8z15g.xn--0ug4653g2xzf; ; xn--4xa2260lk3b8z15g.xn--tw9ct349a; [P1, V6] # σ𑐽𑜫.𐫄
+-򵏽。-ﱌݛ; -򵏽.-نحݛ; [B1, P1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+-򵏽。-نحݛ; -򵏽.-نحݛ; [B1, P1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+xn----o452j.xn----cnc8e38c; -򵏽.-نحݛ; [B1, V3, V6]; xn----o452j.xn----cnc8e38c; ; ; # -.-نحݛ
+⺢򇺅𝟤。‍🚷; ⺢򇺅2.‍🚷; [C2, P1, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [P1, V6] # ⺢2.🚷
+⺢򇺅2。‍🚷; ⺢򇺅2.‍🚷; [C2, P1, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; xn--2-4jtr4282f.xn--m78h; [P1, V6] # ⺢2.🚷
+xn--2-4jtr4282f.xn--m78h; ⺢򇺅2.🚷; [V6]; xn--2-4jtr4282f.xn--m78h; ; ; # ⺢2.🚷
+xn--2-4jtr4282f.xn--1ugz946p; ⺢򇺅2.‍🚷; [C2, V6]; xn--2-4jtr4282f.xn--1ugz946p; ; ; # ⺢2.🚷
+೸‍ⷾ𐹲。򤐶; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, P1, V6]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, P1, V6] # ⷾ𐹲.
+೸‍ⷾ𐹲。򤐶; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, P1, V6]; xn--hvc488g69j402t.xn--3e36c; ; xn--hvc220of37m.xn--3e36c; [B5, B6, P1, V6] # ⷾ𐹲.
+xn--hvc220of37m.xn--3e36c; ೸ⷾ𐹲.򤐶; [B5, B6, V6]; xn--hvc220of37m.xn--3e36c; ; ; # ⷾ𐹲.
+xn--hvc488g69j402t.xn--3e36c; ೸‍ⷾ𐹲.򤐶; [B5, B6, C2, V6]; xn--hvc488g69j402t.xn--3e36c; ; ; # ⷾ𐹲.
+𐹢.Ⴍ₉⁸; 𐹢.Ⴍ98; [B1, P1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.Ⴍ98; ; [B1, P1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.ⴍ98; ; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+xn--9n0d.xn--98-u61a; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+xn--9n0d.xn--98-7ek; 𐹢.Ⴍ98; [B1, V6]; xn--9n0d.xn--98-7ek; ; ; # 𐹢.Ⴍ98
+𐹢.ⴍ₉⁸; 𐹢.ⴍ98; [B1]; xn--9n0d.xn--98-u61a; ; ; # 𐹢.ⴍ98
+‌͏。ß࣢⒚≯; ‌.ß࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ß⒚≯
+‌͏。ß࣢⒚≯; ‌.ß࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--zca612bx9vo5b; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ß⒚≯
+‌͏。ß࣢19.≯; ‌.ß࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ß19.≯
+‌͏。ß࣢19.≯; ‌.ß࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ß19.≯
+‌͏。SS࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。SS࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。Ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+‌͏。Ss࣢19.≯; ‌.ss࣢19.≯; [B1, B5, C1, P1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; .xn--ss19-w0i.xn--hdh; [B1, B5, P1, V6, A4_2] # .ss19.≯
+.xn--ss19-w0i.xn--hdh; .ss࣢19.≯; [B1, B5, V6, X4_2]; .xn--ss19-w0i.xn--hdh; [B1, B5, V6, A4_2]; ; # .ss19.≯
+xn--0ug.xn--ss19-w0i.xn--hdh; ‌.ss࣢19.≯; [B1, B5, C1, V6]; xn--0ug.xn--ss19-w0i.xn--hdh; ; ; # .ss19.≯
+xn--0ug.xn--19-fia813f.xn--hdh; ‌.ß࣢19.≯; [B1, B5, C1, V6]; xn--0ug.xn--19-fia813f.xn--hdh; ; ; # .ß19.≯
+‌͏。SS࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。SS࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。Ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+‌͏。Ss࣢⒚≯; ‌.ss࣢⒚≯; [B1, B5, B6, C1, P1, V6]; xn--0ug.xn--ss-9if872xjjc; ; .xn--ss-9if872xjjc; [B5, B6, P1, V6, A4_2] # .ss⒚≯
+.xn--ss-9if872xjjc; .ss࣢⒚≯; [B5, B6, V6, X4_2]; .xn--ss-9if872xjjc; [B5, B6, V6, A4_2]; ; # .ss⒚≯
+xn--0ug.xn--ss-9if872xjjc; ‌.ss࣢⒚≯; [B1, B5, B6, C1, V6]; xn--0ug.xn--ss-9if872xjjc; ; ; # .ss⒚≯
+xn--0ug.xn--zca612bx9vo5b; ‌.ß࣢⒚≯; [B1, B5, B6, C1, V6]; xn--0ug.xn--zca612bx9vo5b; ; ; # .ß⒚≯
+‌𞥍ᡌ.𣃔; ‌𞥍ᡌ.𣃔; [B1, C1, P1, V6]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, P1, V6] # ᡌ.𣃔
+‌𞥍ᡌ.𣃔; ; [B1, C1, P1, V6]; xn--c8e180bqz13b.xn--od1j; ; xn--c8e5919u.xn--od1j; [B2, B3, P1, V6] # ᡌ.𣃔
+xn--c8e5919u.xn--od1j; 𞥍ᡌ.𣃔; [B2, B3, V6]; xn--c8e5919u.xn--od1j; ; ; # ᡌ.𣃔
+xn--c8e180bqz13b.xn--od1j; ‌𞥍ᡌ.𣃔; [B1, C1, V6]; xn--c8e180bqz13b.xn--od1j; ; ; # ᡌ.𣃔
+ߐ򜬝-񡢬。ྠႻ𞷏𝆬; ߐ򜬝-񡢬.ྠႻ𞷏𝆬; [B1, B2, B3, P1, V5, V6]; xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ; ; # ߐ-.ྠႻ𝆬
+ߐ򜬝-񡢬。ྠⴛ𞷏𝆬; ߐ򜬝-񡢬.ྠⴛ𞷏𝆬; [B1, B2, B3, P1, V5, V6]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬
+xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ߐ򜬝-񡢬.ྠⴛ𞷏𝆬; [B1, B2, B3, V5, V6]; xn----8bd11730jefvw.xn--wfd802mpm20agsxa; ; ; # ߐ-.ྠⴛ𝆬
+xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ߐ򜬝-񡢬.ྠႻ𞷏𝆬; [B1, B2, B3, V5, V6]; xn----8bd11730jefvw.xn--wfd08cd265hgsxa; ; ; # ߐ-.ྠႻ𝆬
+𝨥。⫟𑈾; 𝨥.⫟𑈾; [V5]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾
+xn--n82h.xn--63iw010f; 𝨥.⫟𑈾; [V5]; xn--n82h.xn--63iw010f; ; ; # 𝨥.⫟𑈾
+⾛ݓ.Ⴕ𞠬؄‍; 走ݓ.Ⴕ𞠬؄‍; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; xn--6ob9779d.xn--mfb785ck569a; [B5, B6, P1, V6] # 走ݓ.Ⴕ𞠬
+走ݓ.Ⴕ𞠬؄‍; ; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; xn--6ob9779d.xn--mfb785ck569a; [B5, B6, P1, V6] # 走ݓ.Ⴕ𞠬
+走ݓ.ⴕ𞠬؄‍; ; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, P1, V6] # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb511rxu80a; 走ݓ.ⴕ𞠬؄; [B5, B6, V6]; xn--6ob9779d.xn--mfb511rxu80a; ; ; # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb444k5gjt754b; 走ݓ.ⴕ𞠬؄‍; [B5, B6, C2, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; ; # 走ݓ.ⴕ𞠬
+xn--6ob9779d.xn--mfb785ck569a; 走ݓ.Ⴕ𞠬؄; [B5, B6, V6]; xn--6ob9779d.xn--mfb785ck569a; ; ; # 走ݓ.Ⴕ𞠬
+xn--6ob9779d.xn--mfb785czmm0y85b; 走ݓ.Ⴕ𞠬؄‍; [B5, B6, C2, V6]; xn--6ob9779d.xn--mfb785czmm0y85b; ; ; # 走ݓ.Ⴕ𞠬
+⾛ݓ.ⴕ𞠬؄‍; 走ݓ.ⴕ𞠬؄‍; [B5, B6, C2, P1, V6]; xn--6ob9779d.xn--mfb444k5gjt754b; ; xn--6ob9779d.xn--mfb511rxu80a; [B5, B6, P1, V6] # 走ݓ.ⴕ𞠬
+-ᢗ‌🄄.𑜢; ; [C1, P1, V3, V5, V6]; xn----pck312bx563c.xn--9h2d; ; xn----pck1820x.xn--9h2d; [P1, V3, V5, V6] # -ᢗ🄄.𑜢
+-ᢗ‌3,.𑜢; ; [C1, P1, V3, V5, V6]; xn---3,-3eu051c.xn--9h2d; ; xn---3,-3eu.xn--9h2d; [P1, V3, V5, V6] # -ᢗ3,.𑜢
+xn---3,-3eu.xn--9h2d; -ᢗ3,.𑜢; [P1, V3, V5, V6]; xn---3,-3eu.xn--9h2d; ; ; # -ᢗ3,.𑜢
+xn---3,-3eu051c.xn--9h2d; -ᢗ‌3,.𑜢; [C1, P1, V3, V5, V6]; xn---3,-3eu051c.xn--9h2d; ; ; # -ᢗ3,.𑜢
+xn----pck1820x.xn--9h2d; -ᢗ🄄.𑜢; [V3, V5, V6]; xn----pck1820x.xn--9h2d; ; ; # -ᢗ🄄.𑜢
+xn----pck312bx563c.xn--9h2d; -ᢗ‌🄄.𑜢; [C1, V3, V5, V6]; xn----pck312bx563c.xn--9h2d; ; ; # -ᢗ🄄.𑜢
+≠𐸁𹏁‌.Ⴚ򳄠; ; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; xn--1ch2293gv3nr.xn--ynd49496l; [B1, P1, V6] # ≠.Ⴚ
+≠𐸁𹏁‌.Ⴚ򳄠; ≠𐸁𹏁‌.Ⴚ򳄠; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; xn--1ch2293gv3nr.xn--ynd49496l; [B1, P1, V6] # ≠.Ⴚ
+≠𐸁𹏁‌.ⴚ򳄠; ≠𐸁𹏁‌.ⴚ򳄠; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, P1, V6] # ≠.ⴚ
+≠𐸁𹏁‌.ⴚ򳄠; ; [B1, C1, P1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; xn--1ch2293gv3nr.xn--ilj23531g; [B1, P1, V6] # ≠.ⴚ
+xn--1ch2293gv3nr.xn--ilj23531g; ≠𐸁𹏁.ⴚ򳄠; [B1, V6]; xn--1ch2293gv3nr.xn--ilj23531g; ; ; # ≠.ⴚ
+xn--0ug83gn618a21ov.xn--ilj23531g; ≠𐸁𹏁‌.ⴚ򳄠; [B1, C1, V6]; xn--0ug83gn618a21ov.xn--ilj23531g; ; ; # ≠.ⴚ
+xn--1ch2293gv3nr.xn--ynd49496l; ≠𐸁𹏁.Ⴚ򳄠; [B1, V6]; xn--1ch2293gv3nr.xn--ynd49496l; ; ; # ≠.Ⴚ
+xn--0ug83gn618a21ov.xn--ynd49496l; ≠𐸁𹏁‌.Ⴚ򳄠; [B1, C1, V6]; xn--0ug83gn618a21ov.xn--ynd49496l; ; ; # ≠.Ⴚ
+٩。󠇀𑇊; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+٩。󠇀𑇊; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+xn--iib.xn--6d1d; ٩.𑇊; [B1, B3, B6, V5]; xn--iib.xn--6d1d; ; ; # ٩.𑇊
+ႆ𞶀≯⒍。-; ႆ𞶀≯⒍.-; [B1, P1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+ႆ𞶀≯⒍。-; ႆ𞶀≯⒍.-; [B1, P1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+ႆ𞶀≯6.。-; ႆ𞶀≯6..-; [B1, P1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, P1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+ႆ𞶀≯6.。-; ႆ𞶀≯6..-; [B1, P1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, P1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+xn--6-oyg968k7h74b..-; ႆ𞶀≯6..-; [B1, V3, V5, V6, X4_2]; xn--6-oyg968k7h74b..-; [B1, V3, V5, V6, A4_2]; ; # ႆ≯6..-
+xn--hmd482gqqb8730g.-; ႆ𞶀≯⒍.-; [B1, V3, V5, V6]; xn--hmd482gqqb8730g.-; ; ; # ႆ≯⒍.-
+឴.쮇-; ; [P1, V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+឴.쮇-; ឴.쮇-; [P1, V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+xn--z3e.xn----938f; ឴.쮇-; [V3, V5, V6]; xn--z3e.xn----938f; ; ; # .쮇-
+‌𑓂。⒈-􀪛; ‌𑓂.⒈-􀪛; [C1, P1, V6]; xn--0ugy057g.xn----dcp29674o; ; xn--wz1d.xn----dcp29674o; [P1, V5, V6] # 𑓂.⒈-
+‌𑓂。1.-􀪛; ‌𑓂.1.-􀪛; [C1, P1, V3, V6]; xn--0ugy057g.1.xn----rg03o; ; xn--wz1d.1.xn----rg03o; [P1, V3, V5, V6] # 𑓂.1.-
+xn--wz1d.1.xn----rg03o; 𑓂.1.-􀪛; [V3, V5, V6]; xn--wz1d.1.xn----rg03o; ; ; # 𑓂.1.-
+xn--0ugy057g.1.xn----rg03o; ‌𑓂.1.-􀪛; [C1, V3, V6]; xn--0ugy057g.1.xn----rg03o; ; ; # 𑓂.1.-
+xn--wz1d.xn----dcp29674o; 𑓂.⒈-􀪛; [V5, V6]; xn--wz1d.xn----dcp29674o; ; ; # 𑓂.⒈-
+xn--0ugy057g.xn----dcp29674o; ‌𑓂.⒈-􀪛; [C1, V6]; xn--0ugy057g.xn----dcp29674o; ; ; # 𑓂.⒈-
+⒈ﺮ‌。⃩🖞‌𖬴; ⒈ر‌.⃩🖞‌𖬴; [B1, C1, P1, V5, V6]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; xn--wgb746m.xn--c1g6021kg18c; [B1, P1, V5, V6] # ⒈ر.⃩🖞𖬴
+1.ر‌。⃩🖞‌𖬴; 1.ر‌.⃩🖞‌𖬴; [B1, B3, C1, V5]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; 1.xn--wgb.xn--c1g6021kg18c; [B1, V5] # 1.ر.⃩🖞𖬴
+1.xn--wgb.xn--c1g6021kg18c; 1.ر.⃩🖞𖬴; [B1, V5]; 1.xn--wgb.xn--c1g6021kg18c; ; ; # 1.ر.⃩🖞𖬴
+1.xn--wgb253k.xn--0ugz6a8040fty5d; 1.ر‌.⃩🖞‌𖬴; [B1, B3, C1, V5]; 1.xn--wgb253k.xn--0ugz6a8040fty5d; ; ; # 1.ر.⃩🖞𖬴
+xn--wgb746m.xn--c1g6021kg18c; ⒈ر.⃩🖞𖬴; [B1, V5, V6]; xn--wgb746m.xn--c1g6021kg18c; ; ; # ⒈ر.⃩🖞𖬴
+xn--wgb253kmfd.xn--0ugz6a8040fty5d; ⒈ر‌.⃩🖞‌𖬴; [B1, C1, V5, V6]; xn--wgb253kmfd.xn--0ugz6a8040fty5d; ; ; # ⒈ر.⃩🖞𖬴
+󌭇。𝟐ᮨߔ; 󌭇.2ᮨߔ; [B1, P1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+󌭇。2ᮨߔ; 󌭇.2ᮨߔ; [B1, P1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+xn--xm89d.xn--2-icd143m; 󌭇.2ᮨߔ; [B1, V6]; xn--xm89d.xn--2-icd143m; ; ; # .2ᮨߔ
+ﶏ򫳺.ς‍𐹷; مخم򫳺.ς‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.ς𐹷
+مخم򫳺.ς‍𐹷; ; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.ς𐹷
+مخم򫳺.Σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+مخم򫳺.σ‍𐹷; ; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+xn--tgb9bb64691z.xn--4xa6667k; مخم򫳺.σ𐹷; [B2, B3, B5, B6, V6]; xn--tgb9bb64691z.xn--4xa6667k; ; ; # مخم.σ𐹷
+xn--tgb9bb64691z.xn--4xa895lrp7n; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; ; # مخم.σ𐹷
+xn--tgb9bb64691z.xn--3xa006lrp7n; مخم򫳺.ς‍𐹷; [B2, B3, B5, B6, C2, V6]; xn--tgb9bb64691z.xn--3xa006lrp7n; ; ; # مخم.ς𐹷
+ﶏ򫳺.Σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+ﶏ򫳺.σ‍𐹷; مخم򫳺.σ‍𐹷; [B2, B3, B5, B6, C2, P1, V6]; xn--tgb9bb64691z.xn--4xa895lrp7n; ; xn--tgb9bb64691z.xn--4xa6667k; [B2, B3, B5, B6, P1, V6] # مخم.σ𐹷
+⒎ہ؅。꫶۵𐇽; ⒎ہ؅.꫶۵𐇽; [B1, P1, V5, V6]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽
+7.ہ؅。꫶۵𐇽; 7.ہ؅.꫶۵𐇽; [B1, P1, V5, V6]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽
+7.xn--nfb98a.xn--imb3805fxt8b; 7.ہ؅.꫶۵𐇽; [B1, V5, V6]; 7.xn--nfb98a.xn--imb3805fxt8b; ; ; # 7.ہ.꫶۵𐇽
+xn--nfb98ai25e.xn--imb3805fxt8b; ⒎ہ؅.꫶۵𐇽; [B1, V5, V6]; xn--nfb98ai25e.xn--imb3805fxt8b; ; ; # ⒎ہ.꫶۵𐇽
+-ᡥ᠆󍲭。؅ᩝ𐹡; -ᡥ᠆󍲭.؅ᩝ𐹡; [B1, P1, V3, V6]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡
+xn----f3j6s87156i.xn--nfb035hoo2p; -ᡥ᠆󍲭.؅ᩝ𐹡; [B1, V3, V6]; xn----f3j6s87156i.xn--nfb035hoo2p; ; ; # -ᡥ᠆.ᩝ𐹡
+‍.ڽ٣֖; ; [B1, C2]; xn--1ug.xn--hcb32bni; ; .xn--hcb32bni; [A4_2] # .ڽ٣֖
+.xn--hcb32bni; .ڽ٣֖; [X4_2]; .xn--hcb32bni; [A4_2]; ; # .ڽ٣֖
+xn--1ug.xn--hcb32bni; ‍.ڽ٣֖; [B1, C2]; xn--1ug.xn--hcb32bni; ; ; # .ڽ٣֖
+xn--hcb32bni; ڽ٣֖; ; xn--hcb32bni; ; ; # ڽ٣֖
+ڽ٣֖; ; ; xn--hcb32bni; ; ; # ڽ٣֖
+㒧۱.Ⴚٸ‍; 㒧۱.Ⴚيٴ‍; [B5, B6, C2, P1, V6]; xn--emb715u.xn--mhb8f817ao2p; ; xn--emb715u.xn--mhb8f817a; [B5, B6, P1, V6] # 㒧۱.Ⴚيٴ
+㒧۱.Ⴚيٴ‍; ; [B5, B6, C2, P1, V6]; xn--emb715u.xn--mhb8f817ao2p; ; xn--emb715u.xn--mhb8f817a; [B5, B6, P1, V6] # 㒧۱.Ⴚيٴ
+㒧۱.ⴚيٴ‍; ; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8fy26k; 㒧۱.ⴚيٴ; [B5, B6]; xn--emb715u.xn--mhb8fy26k; ; ; # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8f960g03l; 㒧۱.ⴚيٴ‍; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; ; # 㒧۱.ⴚيٴ
+xn--emb715u.xn--mhb8f817a; 㒧۱.Ⴚيٴ; [B5, B6, V6]; xn--emb715u.xn--mhb8f817a; ; ; # 㒧۱.Ⴚيٴ
+xn--emb715u.xn--mhb8f817ao2p; 㒧۱.Ⴚيٴ‍; [B5, B6, C2, V6]; xn--emb715u.xn--mhb8f817ao2p; ; ; # 㒧۱.Ⴚيٴ
+㒧۱.ⴚٸ‍; 㒧۱.ⴚيٴ‍; [B5, B6, C2]; xn--emb715u.xn--mhb8f960g03l; ; xn--emb715u.xn--mhb8fy26k; [B5, B6] # 㒧۱.ⴚيٴ
+ྔꡋ-.-𖬴; ྔꡋ-.-𖬴; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+ྔꡋ-.-𖬴; ; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+xn----ukg9938i.xn----4u5m; ྔꡋ-.-𖬴; [V3, V5]; xn----ukg9938i.xn----4u5m; ; ; # ྔꡋ-.-𖬴
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; ; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+񿒳-⋢‌.标-; 񿒳-⋢‌.标-; [C1, P1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; xn----9mo67451g.xn----qj7b; [P1, V3, V6] # -⋢.标-
+xn----9mo67451g.xn----qj7b; 񿒳-⋢.标-; [V3, V6]; xn----9mo67451g.xn----qj7b; ; ; # -⋢.标-
+xn----sgn90kn5663a.xn----qj7b; 񿒳-⋢‌.标-; [C1, V3, V6]; xn----sgn90kn5663a.xn----qj7b; ; ; # -⋢.标-
+ٱ.ςߜ; ٱ.ςߜ; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ
+ٱ.ςߜ; ; [B5, B6]; xn--qib.xn--3xa41s; ; xn--qib.xn--4xa21s; # ٱ.ςߜ
+ٱ.Σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+ٱ.σߜ; ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+xn--qib.xn--4xa21s; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+xn--qib.xn--3xa41s; ٱ.ςߜ; [B5, B6]; xn--qib.xn--3xa41s; ; ; # ٱ.ςߜ
+ٱ.Σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+ٱ.σߜ; ٱ.σߜ; [B5, B6]; xn--qib.xn--4xa21s; ; ; # ٱ.σߜ
+񼈶؅.ࣁ‍𑑂𱼱; 񼈶؅.ࣁ‍𑑂𱼱; [B2, B3, B5, B6, C2, P1, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, P1, V6] # .ࣁ𑑂
+񼈶؅.ࣁ‍𑑂𱼱; ; [B2, B3, B5, B6, C2, P1, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; xn--nfb17942h.xn--nzb6708kx3pn; [B2, B3, B5, B6, P1, V6] # .ࣁ𑑂
+xn--nfb17942h.xn--nzb6708kx3pn; 񼈶؅.ࣁ𑑂𱼱; [B2, B3, B5, B6, V6]; xn--nfb17942h.xn--nzb6708kx3pn; ; ; # .ࣁ𑑂
+xn--nfb17942h.xn--nzb240jv06otevq; 񼈶؅.ࣁ‍𑑂𱼱; [B2, B3, B5, B6, C2, V6]; xn--nfb17942h.xn--nzb240jv06otevq; ; ; # .ࣁ𑑂
+𐹾𐋩𞵜。᯲; 𐹾𐋩𞵜.᯲; [B1, P1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+𐹾𐋩𞵜。᯲; 𐹾𐋩𞵜.᯲; [B1, P1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+xn--d97cn8rn44p.xn--0zf; 𐹾𐋩𞵜.᯲; [B1, V5, V6]; xn--d97cn8rn44p.xn--0zf; ; ; # 𐹾𐋩.᯲
+6ᅠᰳ󠸧.򟜊锰ܬς; ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; ; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; # 6ᰳ.锰ܬς
+6ᅠᰳ󠸧.򟜊锰ܬΣ; 6ᅠᰳ󠸧.򟜊锰ܬσ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+6ᅠᰳ󠸧.򟜊锰ܬσ; ; [B1, B5, P1, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; 6ᅠᰳ󠸧.򟜊锰ܬσ; [B1, B5, V6]; xn--6-5bh476ewr517a.xn--4xa95ohw6pk078g; ; ; # 6ᰳ.锰ܬσ
+xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; 6ᅠᰳ󠸧.򟜊锰ܬς; [B1, B5, V6]; xn--6-5bh476ewr517a.xn--3xa16ohw6pk078g; ; ; # 6ᰳ.锰ܬς
+ڳ︄񅎦𝟽。𐹽; ڳ񅎦7.𐹽; [B1, B2, P1, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+ڳ︄񅎦7。𐹽; ڳ񅎦7.𐹽; [B1, B2, P1, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+xn--7-yuc34665f.xn--1o0d; ڳ񅎦7.𐹽; [B1, B2, V6]; xn--7-yuc34665f.xn--1o0d; ; ; # ڳ7.𐹽
+𞮧.‌⫞; 𞮧.‌⫞; [B1, C1, P1, V6]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, P1, V6] # .⫞
+𞮧.‌⫞; ; [B1, C1, P1, V6]; xn--pw6h.xn--0ug283b; ; xn--pw6h.xn--53i; [B1, P1, V6] # .⫞
+xn--pw6h.xn--53i; 𞮧.⫞; [B1, V6]; xn--pw6h.xn--53i; ; ; # .⫞
+xn--pw6h.xn--0ug283b; 𞮧.‌⫞; [B1, C1, V6]; xn--pw6h.xn--0ug283b; ; ; # .⫞
+-񕉴.۠ᢚ-; ; [P1, V3, V5, V6]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ-
+xn----qi38c.xn----jxc827k; -񕉴.۠ᢚ-; [V3, V5, V6]; xn----qi38c.xn----jxc827k; ; ; # -.۠ᢚ-
+⌁‍𑄴.‌𝟩٬; ⌁‍𑄴.‌7٬; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬
+⌁‍𑄴.‌7٬; ; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; xn--nhh5394g.xn--7-xqc; [B1] # ⌁𑄴.7٬
+xn--nhh5394g.xn--7-xqc; ⌁𑄴.7٬; [B1]; xn--nhh5394g.xn--7-xqc; ; ; # ⌁𑄴.7٬
+xn--1ug38i2093a.xn--7-xqc297q; ⌁‍𑄴.‌7٬; [B1, C1, C2]; xn--1ug38i2093a.xn--7-xqc297q; ; ; # ⌁𑄴.7٬
+︒ﴅืﻼ。岓᯲󠾃ᡂ; ︒صىืلا.岓᯲󠾃ᡂ; [B1, P1, V6]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ
+。صىืلا。岓᯲󠾃ᡂ; .صىืلا.岓᯲󠾃ᡂ; [P1, V6, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [P1, V6, A4_2]; ; # .صىืلا.岓᯲ᡂ
+.xn--mgb1a7bt462h.xn--17e10qe61f9r71s; .صىืلا.岓᯲󠾃ᡂ; [V6, X4_2]; .xn--mgb1a7bt462h.xn--17e10qe61f9r71s; [V6, A4_2]; ; # .صىืلا.岓᯲ᡂ
+xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ︒صىืلا.岓᯲󠾃ᡂ; [B1, V6]; xn--mgb1a7bt462hf267a.xn--17e10qe61f9r71s; ; ; # ︒صىืلا.岓᯲ᡂ
+𐹨。8𑁆; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆
+xn--go0d.xn--8-yu7i; 𐹨.8𑁆; [B1]; xn--go0d.xn--8-yu7i; ; ; # 𐹨.8𑁆
+𞀕ൃ.ꡚࣺ𐹰ൄ; 𞀕ൃ.ꡚࣺ𐹰ൄ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+𞀕ൃ.ꡚࣺ𐹰ൄ; ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+xn--mxc5210v.xn--90b01t8u2p1ltd; 𞀕ൃ.ꡚࣺ𐹰ൄ; [B1, B3, B5, B6, V5]; xn--mxc5210v.xn--90b01t8u2p1ltd; ; ; # 𞀕ൃ.ꡚࣺ𐹰ൄ
+󆩏𐦹̃。󠍅; 󆩏𐦹̃.󠍅; [B1, B5, B6, P1, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+󆩏𐦹̃。󠍅; 󆩏𐦹̃.󠍅; [B1, B5, B6, P1, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+xn--nsa1265kp9z9e.xn--xt36e; 󆩏𐦹̃.󠍅; [B1, B5, B6, V6]; xn--nsa1265kp9z9e.xn--xt36e; ; ; # ̃.
+ᢌ.-࡚; ᢌ.-࡚; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+ᢌ.-࡚; ; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+xn--59e.xn----5jd; ᢌ.-࡚; [V3]; xn--59e.xn----5jd; ; ; # ᢌ.-࡚
+𥛛𑘶。𐹬𐲸்; 𥛛𑘶.𐹬𐲸்; [B1, P1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+𥛛𑘶。𐹬𐲸்; 𥛛𑘶.𐹬𐲸்; [B1, P1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+xn--jb2dj685c.xn--xmc5562kmcb; 𥛛𑘶.𐹬𐲸்; [B1, V6]; xn--jb2dj685c.xn--xmc5562kmcb; ; ; # 𥛛𑘶.𐹬்
+Ⴐݿ.‌; Ⴐݿ.‌; [B1, B5, B6, C1, P1, V6]; xn--gqb918b.xn--0ug; ; xn--gqb918b.; [B5, B6, P1, V6] # Ⴐݿ.
+Ⴐݿ.‌; ; [B1, B5, B6, C1, P1, V6]; xn--gqb918b.xn--0ug; ; xn--gqb918b.; [B5, B6, P1, V6] # Ⴐݿ.
+ⴐݿ.‌; ; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6] # ⴐݿ.
+xn--gqb743q.; ⴐݿ.; [B5, B6]; xn--gqb743q.; ; ; # ⴐݿ.
+xn--gqb743q.xn--0ug; ⴐݿ.‌; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; ; # ⴐݿ.
+xn--gqb918b.; Ⴐݿ.; [B5, B6, V6]; xn--gqb918b.; ; ; # Ⴐݿ.
+xn--gqb918b.xn--0ug; Ⴐݿ.‌; [B1, B5, B6, C1, V6]; xn--gqb918b.xn--0ug; ; ; # Ⴐݿ.
+ⴐݿ.‌; ⴐݿ.‌; [B1, B5, B6, C1]; xn--gqb743q.xn--0ug; ; xn--gqb743q.; [B5, B6] # ⴐݿ.
+🄅𑲞-⒈。‍ᠩڥ; 🄅𑲞-⒈.‍ᠩڥ; [B1, C2, P1, V6]; xn----ecp8796hjtvg.xn--7jb180gexf; ; xn----ecp8796hjtvg.xn--7jb180g; [B1, B5, B6, P1, V6] # 🄅𑲞-⒈.ᠩڥ
+4,𑲞-1.。‍ᠩڥ; 4,𑲞-1..‍ᠩڥ; [B1, C2, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, P1, V6, A4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, P1, V6, A4_2] # 4,𑲞-1..ᠩڥ
+xn--4,-1-w401a..xn--7jb180g; 4,𑲞-1..ᠩڥ; [B1, B5, B6, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180g; [B1, B5, B6, P1, V6, A4_2]; ; # 4,𑲞-1..ᠩڥ
+xn--4,-1-w401a..xn--7jb180gexf; 4,𑲞-1..‍ᠩڥ; [B1, C2, P1, V6, X4_2]; xn--4,-1-w401a..xn--7jb180gexf; [B1, C2, P1, V6, A4_2]; ; # 4,𑲞-1..ᠩڥ
+xn----ecp8796hjtvg.xn--7jb180g; 🄅𑲞-⒈.ᠩڥ; [B1, B5, B6, V6]; xn----ecp8796hjtvg.xn--7jb180g; ; ; # 🄅𑲞-⒈.ᠩڥ
+xn----ecp8796hjtvg.xn--7jb180gexf; 🄅𑲞-⒈.‍ᠩڥ; [B1, C2, V6]; xn----ecp8796hjtvg.xn--7jb180gexf; ; ; # 🄅𑲞-⒈.ᠩڥ
+񗀤。𞤪򮿋; 񗀤.𞤪򮿋; [B2, B3, P1, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+񗀤。𞤈򮿋; 񗀤.𞤪򮿋; [B2, B3, P1, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+xn--4240a.xn--ie6h83808a; 񗀤.𞤪򮿋; [B2, B3, V6]; xn--4240a.xn--ie6h83808a; ; ; # .𞤪
+ׁ۲。𐮊٬𝨊鄨; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+ׁ۲。𐮊٬𝨊鄨; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+xn--pdb42d.xn--lib6412enztdwv6h; ׁ۲.𐮊٬𝨊鄨; [B1, B2, B3, V5]; xn--pdb42d.xn--lib6412enztdwv6h; ; ; # ׁ۲.𐮊٬𝨊鄨
+𞭳-ꡁ。ᩩ்-; 𞭳-ꡁ.ᩩ்-; [B1, B2, B3, P1, V3, V5, V6]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்-
+xn----be4e4276f.xn----lze333i; 𞭳-ꡁ.ᩩ்-; [B1, B2, B3, V3, V5, V6]; xn----be4e4276f.xn----lze333i; ; ; # -ꡁ.ᩩ்-
+္-𚮭🞢.ß; ္-𚮭🞢.ß; [P1, V5, V6]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß
+္-𚮭🞢.ß; ; [P1, V5, V6]; xn----9tg11172akr8b.xn--zca; ; xn----9tg11172akr8b.ss; # ္-🞢.ß
+္-𚮭🞢.SS; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.ss; ; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.Ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+xn----9tg11172akr8b.ss; ္-𚮭🞢.ss; [V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+xn----9tg11172akr8b.xn--zca; ္-𚮭🞢.ß; [V5, V6]; xn----9tg11172akr8b.xn--zca; ; ; # ္-🞢.ß
+္-𚮭🞢.SS; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+္-𚮭🞢.Ss; ္-𚮭🞢.ss; [P1, V5, V6]; xn----9tg11172akr8b.ss; ; ; # ္-🞢.ss
+ﳲ-‌。Ⴟ‌␣; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, P1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; xn----eoc6bm.xn--3nd240h; [B3, B6, P1, V3, V6] # ـَّ-.Ⴟ␣
+ـَّ-‌。Ⴟ‌␣; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, P1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; xn----eoc6bm.xn--3nd240h; [B3, B6, P1, V3, V6] # ـَّ-.Ⴟ␣
+ـَّ-‌。ⴟ‌␣; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣
+xn----eoc6bm.xn--xph904a; ـَّ-.ⴟ␣; [B3, B6, V3]; xn----eoc6bm.xn--xph904a; ; ; # ـَّ-.ⴟ␣
+xn----eoc6bm0504a.xn--0ug13nd0j; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; ; # ـَّ-.ⴟ␣
+xn----eoc6bm.xn--3nd240h; ـَّ-.Ⴟ␣; [B3, B6, V3, V6]; xn----eoc6bm.xn--3nd240h; ; ; # ـَّ-.Ⴟ␣
+xn----eoc6bm0504a.xn--3nd849e05c; ـَّ-‌.Ⴟ‌␣; [B3, B6, C1, V6]; xn----eoc6bm0504a.xn--3nd849e05c; ; ; # ـَّ-.Ⴟ␣
+ﳲ-‌。ⴟ‌␣; ـَّ-‌.ⴟ‌␣; [B3, B6, C1]; xn----eoc6bm0504a.xn--0ug13nd0j; ; xn----eoc6bm.xn--xph904a; [B3, B6, V3] # ـَّ-.ⴟ␣
+്-‍‌。񥞧₅≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧₅≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧5≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+്-‍‌。񥞧5≠; ്-‍‌.񥞧5≠; [C1, C2, P1, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; xn----jmf.xn--5-ufo50192e; [P1, V3, V5, V6] # ്-.5≠
+xn----jmf.xn--5-ufo50192e; ്-.񥞧5≠; [V3, V5, V6]; xn----jmf.xn--5-ufo50192e; ; ; # ്-.5≠
+xn----jmf215lda.xn--5-ufo50192e; ്-‍‌.񥞧5≠; [C1, C2, V5, V6]; xn----jmf215lda.xn--5-ufo50192e; ; ; # ്-.5≠
+锣。੍󠘻󠚆; 锣.੍󠘻󠚆; [P1, V5, V6]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍
+xn--gc5a.xn--ybc83044ppga; 锣.੍󠘻󠚆; [V5, V6]; xn--gc5a.xn--ybc83044ppga; ; ; # 锣.੍
+ؽ𑈾.ى‍꤫; ؽ𑈾.ى‍꤫; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫
+ؽ𑈾.ى‍꤫; ; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; xn--8gb2338k.xn--lhb0154f; [] # ؽ𑈾.ى꤫
+xn--8gb2338k.xn--lhb0154f; ؽ𑈾.ى꤫; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫
+ؽ𑈾.ى꤫; ; ; xn--8gb2338k.xn--lhb0154f; ; ; # ؽ𑈾.ى꤫
+xn--8gb2338k.xn--lhb603k060h; ؽ𑈾.ى‍꤫; [B3, C2]; xn--8gb2338k.xn--lhb603k060h; ; ; # ؽ𑈾.ى꤫
+٦⁴Ⴅ.ࢽ‌; ٦4Ⴅ.ࢽ‌; [B1, B3, C1, P1, V6]; xn--4-kqc489e.xn--jzb840j; ; xn--4-kqc489e.xn--jzb; [B1, P1, V6] # ٦4Ⴅ.ࢽ
+٦4Ⴅ.ࢽ‌; ; [B1, B3, C1, P1, V6]; xn--4-kqc489e.xn--jzb840j; ; xn--4-kqc489e.xn--jzb; [B1, P1, V6] # ٦4Ⴅ.ࢽ
+٦4ⴅ.ࢽ‌; ; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ
+xn--4-kqc6770a.xn--jzb; ٦4ⴅ.ࢽ; [B1]; xn--4-kqc6770a.xn--jzb; ; ; # ٦4ⴅ.ࢽ
+xn--4-kqc6770a.xn--jzb840j; ٦4ⴅ.ࢽ‌; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; ; # ٦4ⴅ.ࢽ
+xn--4-kqc489e.xn--jzb; ٦4Ⴅ.ࢽ; [B1, V6]; xn--4-kqc489e.xn--jzb; ; ; # ٦4Ⴅ.ࢽ
+xn--4-kqc489e.xn--jzb840j; ٦4Ⴅ.ࢽ‌; [B1, B3, C1, V6]; xn--4-kqc489e.xn--jzb840j; ; ; # ٦4Ⴅ.ࢽ
+٦⁴ⴅ.ࢽ‌; ٦4ⴅ.ࢽ‌; [B1, B3, C1]; xn--4-kqc6770a.xn--jzb840j; ; xn--4-kqc6770a.xn--jzb; [B1] # ٦4ⴅ.ࢽ
+ჁႱ6̘。ßᬃ; ჁႱ6̘.ßᬃ; [P1, V6]; xn--6-8cb555h2b.xn--zca894k; ; xn--6-8cb555h2b.xn--ss-2vq; # ჁႱ6̘.ßᬃ
+ⴡⴑ6̘。ßᬃ; ⴡⴑ6̘.ßᬃ; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ
+ჁႱ6̘。SSᬃ; ჁႱ6̘.ssᬃ; [P1, V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+ⴡⴑ6̘。ssᬃ; ⴡⴑ6̘.ssᬃ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+Ⴡⴑ6̘。Ssᬃ; Ⴡⴑ6̘.ssᬃ; [P1, V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb306hms1a.xn--ss-2vq; Ⴡⴑ6̘.ssᬃ; [V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb7433a2ba.xn--ss-2vq; ⴡⴑ6̘.ssᬃ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+ⴡⴑ6̘.ssᬃ; ; ; xn--6-8cb7433a2ba.xn--ss-2vq; ; ; # ⴡⴑ6̘.ssᬃ
+ჁႱ6̘.SSᬃ; ჁႱ6̘.ssᬃ; [P1, V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+Ⴡⴑ6̘.Ssᬃ; Ⴡⴑ6̘.ssᬃ; [P1, V6]; xn--6-8cb306hms1a.xn--ss-2vq; ; ; # Ⴡⴑ6̘.ssᬃ
+xn--6-8cb555h2b.xn--ss-2vq; ჁႱ6̘.ssᬃ; [V6]; xn--6-8cb555h2b.xn--ss-2vq; ; ; # ჁႱ6̘.ssᬃ
+xn--6-8cb7433a2ba.xn--zca894k; ⴡⴑ6̘.ßᬃ; ; xn--6-8cb7433a2ba.xn--zca894k; ; ; # ⴡⴑ6̘.ßᬃ
+ⴡⴑ6̘.ßᬃ; ; ; xn--6-8cb7433a2ba.xn--zca894k; ; xn--6-8cb7433a2ba.xn--ss-2vq; # ⴡⴑ6̘.ßᬃ
+xn--6-8cb555h2b.xn--zca894k; ჁႱ6̘.ßᬃ; [V6]; xn--6-8cb555h2b.xn--zca894k; ; ; # ჁႱ6̘.ßᬃ
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+򋡐。≯𑋪; 򋡐.≯𑋪; [P1, V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+xn--eo08b.xn--hdh3385g; 򋡐.≯𑋪; [V6]; xn--eo08b.xn--hdh3385g; ; ; # .≯𑋪
+ٚ۲。‌-᯳࣢; ٚ۲.‌-᯳࣢; [B1, C1, P1, V5, V6]; xn--2hb81a.xn----xrd657l30d; ; xn--2hb81a.xn----xrd657l; [B1, P1, V3, V5, V6] # ٚ۲.-᯳
+xn--2hb81a.xn----xrd657l; ٚ۲.-᯳࣢; [B1, V3, V5, V6]; xn--2hb81a.xn----xrd657l; ; ; # ٚ۲.-᯳
+xn--2hb81a.xn----xrd657l30d; ٚ۲.‌-᯳࣢; [B1, C1, V5, V6]; xn--2hb81a.xn----xrd657l30d; ; ; # ٚ۲.-᯳
+󠄏𖬴󠲽。ᅠ; 𖬴󠲽.ᅠ; [P1, V5, V6]; xn--619ep9154c.xn--cl7c; ; ; # 𖬴.
+󠄏𖬴󠲽。ᅠ; 𖬴󠲽.ᅠ; [P1, V5, V6]; xn--619ep9154c.xn--psd; ; ; # 𖬴.
+xn--619ep9154c.xn--psd; 𖬴󠲽.ᅠ; [V5, V6]; xn--619ep9154c.xn--psd; ; ; # 𖬴.
+xn--619ep9154c.xn--cl7c; 𖬴󠲽.ᅠ; [V5, V6]; xn--619ep9154c.xn--cl7c; ; ; # 𖬴.
+ß⒈ݠ힮.􉖲󠅄؅򉔯; ß⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; # ß⒈ݠ.
+ß1.ݠ힮.􉖲󠅄؅򉔯; ß1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; # ß1.ݠ.
+SS1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+ss1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+Ss1.ݠ힮.􉖲󠅄؅򉔯; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, P1, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ss1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, V6]; ss1.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ss1.ݠ.
+xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ß1.ݠ힮.􉖲؅򉔯; [B2, B3, B5, V6]; xn--1-pfa.xn--kpb6677h.xn--nfb09923ifkyyb; ; ; # ß1.ݠ.
+SS⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+ss⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+Ss⒈ݠ힮.􉖲󠅄؅򉔯; ss⒈ݠ힮.􉖲؅򉔯; [B5, P1, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ss⒈ݠ힮.􉖲؅򉔯; [B5, V6]; xn--ss-6ke9690a0g1q.xn--nfb09923ifkyyb; ; ; # ss⒈ݠ.
+xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ß⒈ݠ힮.􉖲؅򉔯; [B5, V6]; xn--zca444a0s1ao12n.xn--nfb09923ifkyyb; ; ; # ß⒈ݠ.
+󠭔.𐋱₂; 󠭔.𐋱2; [P1, V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+󠭔.𐋱2; ; [P1, V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+xn--vi56e.xn--2-w91i; 󠭔.𐋱2; [V6]; xn--vi56e.xn--2-w91i; ; ; # .𐋱2
+ܖे。-ßڥ‌; ܖे.-ßڥ‌; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ßڥ
+ܖे。-SSڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+ܖे。-ssڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+ܖे。-Ssڥ‌; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; xn--gnb63i.xn---ss-4ef; [B1, V3] # ܖे.-ssڥ
+xn--gnb63i.xn---ss-4ef; ܖे.-ssڥ; [B1, V3]; xn--gnb63i.xn---ss-4ef; ; ; # ܖे.-ssڥ
+xn--gnb63i.xn---ss-4ef9263a; ܖे.-ssڥ‌; [B1, C1, V3]; xn--gnb63i.xn---ss-4ef9263a; ; ; # ܖे.-ssڥ
+xn--gnb63i.xn----qfa845bhx4a; ܖे.-ßڥ‌; [B1, C1, V3]; xn--gnb63i.xn----qfa845bhx4a; ; ; # ܖे.-ßڥ
+ᮩ‍ت񡚈.᳕䷉Ⴡ; ᮩ‍ت񡚈.᳕䷉Ⴡ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; xn--pgb911izv33i.xn--5nd792dgv3b; [B1, P1, V5, V6] # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉Ⴡ; ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; xn--pgb911izv33i.xn--5nd792dgv3b; [B1, P1, V5, V6] # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉ⴡ; ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, P1, V5, V6] # ᮩت.᳕䷉ⴡ
+xn--pgb911izv33i.xn--i6f270etuy; ᮩت񡚈.᳕䷉ⴡ; [B1, V5, V6]; xn--pgb911izv33i.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ
+xn--pgb911imgdrw34r.xn--i6f270etuy; ᮩ‍ت񡚈.᳕䷉ⴡ; [B1, C2, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; ; # ᮩت.᳕䷉ⴡ
+xn--pgb911izv33i.xn--5nd792dgv3b; ᮩت񡚈.᳕䷉Ⴡ; [B1, V5, V6]; xn--pgb911izv33i.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ
+xn--pgb911imgdrw34r.xn--5nd792dgv3b; ᮩ‍ت񡚈.᳕䷉Ⴡ; [B1, C2, V5, V6]; xn--pgb911imgdrw34r.xn--5nd792dgv3b; ; ; # ᮩت.᳕䷉Ⴡ
+ᮩ‍ت񡚈.᳕䷉ⴡ; ᮩ‍ت񡚈.᳕䷉ⴡ; [B1, C2, P1, V5, V6]; xn--pgb911imgdrw34r.xn--i6f270etuy; ; xn--pgb911izv33i.xn--i6f270etuy; [B1, P1, V5, V6] # ᮩت.᳕䷉ⴡ
+⶿.ß‍; ; [C2, P1, V6]; xn--7pj.xn--zca870n; ; xn--7pj.ss; [P1, V6] # .ß
+⶿.SS‍; ⶿.ss‍; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+⶿.ss‍; ; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+⶿.Ss‍; ⶿.ss‍; [C2, P1, V6]; xn--7pj.xn--ss-n1t; ; xn--7pj.ss; [P1, V6] # .ss
+xn--7pj.ss; ⶿.ss; [V6]; xn--7pj.ss; ; ; # .ss
+xn--7pj.xn--ss-n1t; ⶿.ss‍; [C2, V6]; xn--7pj.xn--ss-n1t; ; ; # .ss
+xn--7pj.xn--zca870n; ⶿.ß‍; [C2, V6]; xn--7pj.xn--zca870n; ; ; # .ß
+᯳︒.ت≯ꡂ; ; [B2, B3, B6, P1, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+᯳︒.ت≯ꡂ; ᯳︒.ت≯ꡂ; [B2, B3, B6, P1, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+᯳。.ت≯ꡂ; ᯳..ت≯ꡂ; [B2, B3, P1, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, P1, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+᯳。.ت≯ꡂ; ᯳..ت≯ꡂ; [B2, B3, P1, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, P1, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+xn--1zf..xn--pgb885lry5g; ᯳..ت≯ꡂ; [B2, B3, V5, V6, X4_2]; xn--1zf..xn--pgb885lry5g; [B2, B3, V5, V6, A4_2]; ; # ᯳..ت≯ꡂ
+xn--1zf8957g.xn--pgb885lry5g; ᯳︒.ت≯ꡂ; [B2, B3, B6, V5, V6]; xn--1zf8957g.xn--pgb885lry5g; ; ; # ᯳︒.ت≯ꡂ
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+≮≠񏻃。-𫠆ڷ𐹪; ≮≠񏻃.-𫠆ڷ𐹪; [B1, P1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+xn--1ch1a29470f.xn----7uc5363rc1rn; ≮≠񏻃.-𫠆ڷ𐹪; [B1, V3, V6]; xn--1ch1a29470f.xn----7uc5363rc1rn; ; ; # ≮≠.-𫠆ڷ𐹪
+𐹡ݷ。ꡂ; 𐹡ݷ.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ
+xn--7pb5275k.xn--bc9a; 𐹡ݷ.ꡂ; [B1]; xn--7pb5275k.xn--bc9a; ; ; # 𐹡ݷ.ꡂ
+Ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; ; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; # Ⴉؙ𝆅.ß𐧦𐹳ݵ
+ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; # ⴉؙ𝆅.ß𐧦𐹳ݵ
+Ⴉ𝆅񔻅ؙ.SS𐧦𐹳ݵ; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; ; [B5, B6, P1, V6]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ
+Ⴉ𝆅񔻅ؙ.Ss𐧦𐹳ݵ; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, P1, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; Ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb125cjv87a7xvz.xn--ss-zme7575xp0e; ; ; # Ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ⴉ𝆅񔻅ؙ.ss𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb940rwt3z7xvz.xn--ss-zme7575xp0e; ; ; # ⴉؙ𝆅.ss𐧦𐹳ݵ
+xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb940rwt3z7xvz.xn--zca684a699vf2d; ; ; # ⴉؙ𝆅.ß𐧦𐹳ݵ
+xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; Ⴉ𝆅񔻅ؙ.ß𐧦𐹳ݵ; [B5, B6, V6]; xn--7fb125cjv87a7xvz.xn--zca684a699vf2d; ; ; # Ⴉؙ𝆅.ß𐧦𐹳ݵ
+‍ك𐧾↙.񊽡; ; [B1, C2, P1, V6]; xn--fhb713k87ag053c.xn--7s4w; ; xn--fhb011lnp8n.xn--7s4w; [B3, P1, V6] # ك𐧾↙.
+xn--fhb011lnp8n.xn--7s4w; ك𐧾↙.񊽡; [B3, V6]; xn--fhb011lnp8n.xn--7s4w; ; ; # ك𐧾↙.
+xn--fhb713k87ag053c.xn--7s4w; ‍ك𐧾↙.񊽡; [B1, C2, V6]; xn--fhb713k87ag053c.xn--7s4w; ; ; # ك𐧾↙.
+梉。‌; 梉.‌; [C1]; xn--7zv.xn--0ug; ; xn--7zv.; [] # 梉.
+xn--7zv.; 梉.; ; xn--7zv.; ; ; # 梉.
+梉.; ; ; xn--7zv.; ; ; # 梉.
+xn--7zv.xn--0ug; 梉.‌; [C1]; xn--7zv.xn--0ug; ; ; # 梉.
+ꡣ-≠.‍𞤗𐅢Ↄ; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; xn----ufo9661d.xn--q5g0929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢Ↄ
+ꡣ-≠.‍𞤗𐅢Ↄ; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; xn----ufo9661d.xn--q5g0929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢Ↄ
+ꡣ-≠.‍𞤹𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤹𐅢ↄ; ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤗𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+ꡣ-≠.‍𞤗𐅢ↄ; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, P1, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; xn----ufo9661d.xn--r5gy929fhm4f; [B2, B3, B6, P1, V6] # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--r5gy929fhm4f; ꡣ-≠.𞤹𐅢ↄ; [B2, B3, B6, V6]; xn----ufo9661d.xn--r5gy929fhm4f; ; ; # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--1ug99cj620c71sh; ꡣ-≠.‍𞤹𐅢ↄ; [B1, B6, C2, V6]; xn----ufo9661d.xn--1ug99cj620c71sh; ; ; # ꡣ-≠.𞤹𐅢ↄ
+xn----ufo9661d.xn--q5g0929fhm4f; ꡣ-≠.𞤹𐅢Ↄ; [B2, B3, B6, V6]; xn----ufo9661d.xn--q5g0929fhm4f; ; ; # ꡣ-≠.𞤹𐅢Ↄ
+xn----ufo9661d.xn--1ug79cm620c71sh; ꡣ-≠.‍𞤹𐅢Ↄ; [B1, B6, C2, V6]; xn----ufo9661d.xn--1ug79cm620c71sh; ; ; # ꡣ-≠.𞤹𐅢Ↄ
+ς⒐𝆫⸵。𐱢🄊𝟳; ς⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--3xa019nwtghi25b.xn--7-075iy877c; ; xn--4xa809nwtghi25b.xn--7-075iy877c; # ς⒐𝆫⸵.🄊7
+ς9.𝆫⸵。𐱢9,7; ς9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; # ς9.𝆫⸵.9,7
+Σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+σ9.𝆫⸵。𐱢9,7; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; σ9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-zmb.xn--ltj1535k.xn--9,7-r67t; ; ; # σ9.𝆫⸵.9,7
+xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ς9.𝆫⸵.𐱢9,7; [B1, P1, V5, V6]; xn--9-xmb.xn--ltj1535k.xn--9,7-r67t; ; ; # ς9.𝆫⸵.9,7
+Σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+σ⒐𝆫⸵。𐱢🄊𝟳; σ⒐𝆫⸵.𐱢🄊7; [B6, P1, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+xn--4xa809nwtghi25b.xn--7-075iy877c; σ⒐𝆫⸵.𐱢🄊7; [B6, V6]; xn--4xa809nwtghi25b.xn--7-075iy877c; ; ; # σ⒐𝆫⸵.🄊7
+xn--3xa019nwtghi25b.xn--7-075iy877c; ς⒐𝆫⸵.𐱢🄊7; [B6, V6]; xn--3xa019nwtghi25b.xn--7-075iy877c; ; ; # ς⒐𝆫⸵.🄊7
+ࡓ.‌ß; ࡓ.‌ß; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß
+ࡓ.‌ß; ; [B1, C1]; xn--iwb.xn--zca570n; ; xn--iwb.ss; [] # ࡓ.ß
+ࡓ.‌SS; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌ss; ; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+xn--iwb.ss; ࡓ.ss; ; xn--iwb.ss; ; ; # ࡓ.ss
+ࡓ.ss; ; ; xn--iwb.ss; ; ; # ࡓ.ss
+ࡓ.SS; ࡓ.ss; ; xn--iwb.ss; ; ; # ࡓ.ss
+xn--iwb.xn--ss-i1t; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; ; # ࡓ.ss
+xn--iwb.xn--zca570n; ࡓ.‌ß; [B1, C1]; xn--iwb.xn--zca570n; ; ; # ࡓ.ß
+ࡓ.‌SS; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌Ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+ࡓ.‌Ss; ࡓ.‌ss; [B1, C1]; xn--iwb.xn--ss-i1t; ; xn--iwb.ss; [] # ࡓ.ss
+񯶣-.‍ݎꥍ󠻨; ; [B1, B6, C2, P1, V3, V6]; xn----s116e.xn--1ob387jy90hq459k; ; xn----s116e.xn--1ob6504fmf40i; [B3, B6, P1, V3, V6] # -.ݎꥍ
+xn----s116e.xn--1ob6504fmf40i; 񯶣-.ݎꥍ󠻨; [B3, B6, V3, V6]; xn----s116e.xn--1ob6504fmf40i; ; ; # -.ݎꥍ
+xn----s116e.xn--1ob387jy90hq459k; 񯶣-.‍ݎꥍ󠻨; [B1, B6, C2, V3, V6]; xn----s116e.xn--1ob387jy90hq459k; ; ; # -.ݎꥍ
+䃚蟥-。-񽒘⒈; 䃚蟥-.-񽒘⒈; [P1, V3, V6]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈
+䃚蟥-。-񽒘1.; 䃚蟥-.-񽒘1.; [P1, V3, V6]; xn----n50a258u.xn---1-up07j.; ; ; # 䃚蟥-.-1.
+xn----n50a258u.xn---1-up07j.; 䃚蟥-.-񽒘1.; [V3, V6]; xn----n50a258u.xn---1-up07j.; ; ; # 䃚蟥-.-1.
+xn----n50a258u.xn----ecp33805f; 䃚蟥-.-񽒘⒈; [V3, V6]; xn----n50a258u.xn----ecp33805f; ; ; # 䃚蟥-.-⒈
+𐹸䚵-ꡡ。⺇; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇
+xn----bm3an932a1l5d.xn--xvj; 𐹸䚵-ꡡ.⺇; [B1]; xn----bm3an932a1l5d.xn--xvj; ; ; # 𐹸䚵-ꡡ.⺇
+𑄳。᫜𐹻; 𑄳.᫜𐹻; [B1, B3, B5, B6, P1, V5, V6]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻
+xn--v80d.xn--2rf1154i; 𑄳.᫜𐹻; [B1, B3, B5, B6, V5, V6]; xn--v80d.xn--2rf1154i; ; ; # 𑄳.𐹻
+≮𐹻.⒎𑂵ں؂; ; [B1, P1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+≮𐹻.⒎𑂵ں؂; ≮𐹻.⒎𑂵ں؂; [B1, P1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+≮𐹻.7.𑂵ں؂; ; [B1, P1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+≮𐹻.7.𑂵ں؂; ≮𐹻.7.𑂵ں؂; [B1, P1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+xn--gdhx904g.7.xn--kfb18an307d; ≮𐹻.7.𑂵ں؂; [B1, V5, V6]; xn--gdhx904g.7.xn--kfb18an307d; ; ; # ≮𐹻.7.𑂵ں
+xn--gdhx904g.xn--kfb18a325efm3s; ≮𐹻.⒎𑂵ں؂; [B1, V6]; xn--gdhx904g.xn--kfb18a325efm3s; ; ; # ≮𐹻.⒎𑂵ں
+ᢔ≠􋉂.‍𐋢; ; [C2, P1, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [P1, V6] # ᢔ≠.𐋢
+ᢔ≠􋉂.‍𐋢; ᢔ≠􋉂.‍𐋢; [C2, P1, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; xn--ebf031cf7196a.xn--587c; [P1, V6] # ᢔ≠.𐋢
+xn--ebf031cf7196a.xn--587c; ᢔ≠􋉂.𐋢; [V6]; xn--ebf031cf7196a.xn--587c; ; ; # ᢔ≠.𐋢
+xn--ebf031cf7196a.xn--1ug9540g; ᢔ≠􋉂.‍𐋢; [C2, V6]; xn--ebf031cf7196a.xn--1ug9540g; ; ; # ᢔ≠.𐋢
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; ; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+𐩁≮񣊛≯.٬𞵕⳿; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, P1, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+xn--gdhc0519o0y27b.xn--lib468q0d21a; 𐩁≮񣊛≯.٬𞵕⳿; [B1, B2, B3, V6]; xn--gdhc0519o0y27b.xn--lib468q0d21a; ; ; # 𐩁≮≯.٬⳿
+-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+-。⺐; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+-.xn--6vj; -.⺐; [V3]; -.xn--6vj; ; ; # -.⺐
+󠰩𑲬.ٜ; 󠰩𑲬.ٜ; [P1, V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+󠰩𑲬.ٜ; ; [P1, V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+xn--sn3d59267c.xn--4hb; 󠰩𑲬.ٜ; [V5, V6]; xn--sn3d59267c.xn--4hb; ; ; # 𑲬.ٜ
+𐍺.񚇃‌; ; [C1, P1, V5, V6]; xn--ie8c.xn--0ug03366c; ; xn--ie8c.xn--2g51a; [P1, V5, V6] # 𐍺.
+xn--ie8c.xn--2g51a; 𐍺.񚇃; [V5, V6]; xn--ie8c.xn--2g51a; ; ; # 𐍺.
+xn--ie8c.xn--0ug03366c; 𐍺.񚇃‌; [C1, V5, V6]; xn--ie8c.xn--0ug03366c; ; ; # 𐍺.
+ؽۣ.𐨎; ; [B1, B3, B6, V5]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎
+xn--8gb64a.xn--mr9c; ؽۣ.𐨎; [B1, B3, B6, V5]; xn--8gb64a.xn--mr9c; ; ; # ؽۣ.𐨎
+漦Ⴙς.񡻀𐴄; ; [B5, B6, P1, V6]; xn--3xa157d717e.xn--9d0d3162t; ; xn--4xa947d717e.xn--9d0d3162t; # 漦Ⴙς.𐴄
+漦ⴙς.񡻀𐴄; ; [B5, B6, P1, V6]; xn--3xa972sl47b.xn--9d0d3162t; ; xn--4xa772sl47b.xn--9d0d3162t; # 漦ⴙς.𐴄
+漦ႹΣ.񡻀𐴄; 漦Ⴙσ.񡻀𐴄; [B5, B6, P1, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+漦ⴙσ.񡻀𐴄; ; [B5, B6, P1, V6]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄
+漦Ⴙσ.񡻀𐴄; ; [B5, B6, P1, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+xn--4xa947d717e.xn--9d0d3162t; 漦Ⴙσ.񡻀𐴄; [B5, B6, V6]; xn--4xa947d717e.xn--9d0d3162t; ; ; # 漦Ⴙσ.𐴄
+xn--4xa772sl47b.xn--9d0d3162t; 漦ⴙσ.񡻀𐴄; [B5, B6, V6]; xn--4xa772sl47b.xn--9d0d3162t; ; ; # 漦ⴙσ.𐴄
+xn--3xa972sl47b.xn--9d0d3162t; 漦ⴙς.񡻀𐴄; [B5, B6, V6]; xn--3xa972sl47b.xn--9d0d3162t; ; ; # 漦ⴙς.𐴄
+xn--3xa157d717e.xn--9d0d3162t; 漦Ⴙς.񡻀𐴄; [B5, B6, V6]; xn--3xa157d717e.xn--9d0d3162t; ; ; # 漦Ⴙς.𐴄
+𐹫踧್򫚇.󜀃⒈𝨤; ; [B1, P1, V6]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤
+𐹫踧್򫚇.󜀃1.𝨤; ; [B1, B3, B6, P1, V5, V6]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤
+xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; 𐹫踧್򫚇.󜀃1.𝨤; [B1, B3, B6, V5, V6]; xn--8tc1437dro0d6q06h.xn--1-p948l.xn--m82h; ; ; # 𐹫踧್.1.𝨤
+xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; 𐹫踧್򫚇.󜀃⒈𝨤; [B1, V6]; xn--8tc1437dro0d6q06h.xn--tsh2611ncu71e; ; ; # 𐹫踧್.⒈𝨤
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+‍≮.󠟪𹫏-; ‍≮.󠟪𹫏-; [C2, P1, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; xn--gdh.xn----cr99a1w710b; [P1, V3, V6] # ≮.-
+xn--gdh.xn----cr99a1w710b; ≮.󠟪𹫏-; [V3, V6]; xn--gdh.xn----cr99a1w710b; ; ; # ≮.-
+xn--1ug95g.xn----cr99a1w710b; ‍≮.󠟪𹫏-; [C2, V3, V6]; xn--1ug95g.xn----cr99a1w710b; ; ; # ≮.-
+‍‍襔。Ⴜ5ꡮ񵝏; ‍‍襔.Ⴜ5ꡮ񵝏; [C2, P1, V6]; xn--1uga7691f.xn--5-r1g7167ipfw8d; ; xn--2u2a.xn--5-r1g7167ipfw8d; [P1, V6] # 襔.Ⴜ5ꡮ
+‍‍襔。ⴜ5ꡮ񵝏; ‍‍襔.ⴜ5ꡮ񵝏; [C2, P1, V6]; xn--1uga7691f.xn--5-uws5848bpf44e; ; xn--2u2a.xn--5-uws5848bpf44e; [P1, V6] # 襔.ⴜ5ꡮ
+xn--2u2a.xn--5-uws5848bpf44e; 襔.ⴜ5ꡮ񵝏; [V6]; xn--2u2a.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ
+xn--1uga7691f.xn--5-uws5848bpf44e; ‍‍襔.ⴜ5ꡮ񵝏; [C2, V6]; xn--1uga7691f.xn--5-uws5848bpf44e; ; ; # 襔.ⴜ5ꡮ
+xn--2u2a.xn--5-r1g7167ipfw8d; 襔.Ⴜ5ꡮ񵝏; [V6]; xn--2u2a.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ
+xn--1uga7691f.xn--5-r1g7167ipfw8d; ‍‍襔.Ⴜ5ꡮ񵝏; [C2, V6]; xn--1uga7691f.xn--5-r1g7167ipfw8d; ; ; # 襔.Ⴜ5ꡮ
+𐫜𑌼‍.婀; 𐫜𑌼‍.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀
+𐫜𑌼‍.婀; ; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; xn--ix9c26l.xn--q0s; [] # 𐫜𑌼.婀
+xn--ix9c26l.xn--q0s; 𐫜𑌼.婀; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀
+𐫜𑌼.婀; ; ; xn--ix9c26l.xn--q0s; ; ; # 𐫜𑌼.婀
+xn--1ugx063g1if.xn--q0s; 𐫜𑌼‍.婀; [B3, C2]; xn--1ugx063g1if.xn--q0s; ; ; # 𐫜𑌼.婀
+󠅽︒︒𐹯。⬳᩸; ︒︒𐹯.⬳᩸; [B1, P1, V6]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸
+󠅽。。𐹯。⬳᩸; ..𐹯.⬳᩸; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸
+..xn--no0d.xn--7of309e; ..𐹯.⬳᩸; [B1, X4_2]; ..xn--no0d.xn--7of309e; [B1, A4_2]; ; # ..𐹯.⬳᩸
+xn--y86ca186j.xn--7of309e; ︒︒𐹯.⬳᩸; [B1, V6]; xn--y86ca186j.xn--7of309e; ; ; # ︒︒𐹯.⬳᩸
+𝟖ß.󠄐-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; 8ss.xn---?-gfk; # 8ß.-?Ⴏ
+8ß.󠄐-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; 8ss.xn---?-gfk; # 8ß.-?Ⴏ
+8ß.󠄐-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ
+8SS.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.󠄐-?ⴏ; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+8ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.xn---?-gfk; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.xn---?-261a; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+xn--8-qfa.xn---?-261a; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ
+xn--8-qfa.xn---?-gfk; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+𝟖ß.󠄐-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; 8ss.xn---?-261a; # 8ß.-?ⴏ
+𝟖SS.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+𝟖ss.󠄐-?ⴏ; 8ss.-?ⴏ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+𝟖ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.-?Ⴏ; ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8ss.-?ⴏ; ; [P1, V3, V6]; 8ss.xn---?-261a; ; ; # 8ss.-?ⴏ
+8SS.-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+xn--8-qfa.-?ⴏ; 8ß.-?ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-261a; ; ; # 8ß.-?ⴏ
+XN--8-QFA.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+Xn--8-Qfa.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+xn--8-qfa.-?Ⴏ; 8ß.-?Ⴏ; [P1, V3, V6]; xn--8-qfa.xn---?-gfk; ; ; # 8ß.-?Ⴏ
+𝟖Ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+8Ss.󠄐-?Ⴏ; 8ss.-?Ⴏ; [P1, V3, V6]; 8ss.xn---?-gfk; ; ; # 8ss.-?Ⴏ
+-‍󠋟.‌𐹣Ⴅ; ; [B1, C1, C2, P1, V3, V6]; xn----ugnv7071n.xn--dnd999e4j4p; ; xn----s721m.xn--dnd9201k; [B1, P1, V3, V6] # -.𐹣Ⴅ
+-‍󠋟.‌𐹣ⴅ; ; [B1, C1, C2, P1, V3, V6]; xn----ugnv7071n.xn--0ugz32cgr0p; ; xn----s721m.xn--wkj1423e; [B1, P1, V3, V6] # -.𐹣ⴅ
+xn----s721m.xn--wkj1423e; -󠋟.𐹣ⴅ; [B1, V3, V6]; xn----s721m.xn--wkj1423e; ; ; # -.𐹣ⴅ
+xn----ugnv7071n.xn--0ugz32cgr0p; -‍󠋟.‌𐹣ⴅ; [B1, C1, C2, V3, V6]; xn----ugnv7071n.xn--0ugz32cgr0p; ; ; # -.𐹣ⴅ
+xn----s721m.xn--dnd9201k; -󠋟.𐹣Ⴅ; [B1, V3, V6]; xn----s721m.xn--dnd9201k; ; ; # -.𐹣Ⴅ
+xn----ugnv7071n.xn--dnd999e4j4p; -‍󠋟.‌𐹣Ⴅ; [B1, C1, C2, V3, V6]; xn----ugnv7071n.xn--dnd999e4j4p; ; ; # -.𐹣Ⴅ
+ꦹ‍큷𻶡。₂; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。₂; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。2; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+ꦹ‍큷𻶡。2; ꦹ‍큷𻶡.2; [C2, P1, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; xn--0m9as84e2e21c.2; [P1, V5, V6] # ꦹ큷.2
+xn--0m9as84e2e21c.2; ꦹ큷𻶡.2; [V5, V6]; xn--0m9as84e2e21c.2; ; ; # ꦹ큷.2
+xn--1ug1435cfkyaoi04d.2; ꦹ‍큷𻶡.2; [C2, V5, V6]; xn--1ug1435cfkyaoi04d.2; ; ; # ꦹ큷.2
+?.🄄𞯘; ; [B1, P1, V6]; ?.xn--3x6hx6f; ; ; # ?.🄄
+?.3,𞯘; ; [B1, P1, V6]; ?.xn--3,-tb22a; ; ; # ?.3,
+?.xn--3,-tb22a; ?.3,𞯘; [B1, P1, V6]; ?.xn--3,-tb22a; ; ; # ?.3,
+?.xn--3x6hx6f; ?.🄄𞯘; [B1, P1, V6]; ?.xn--3x6hx6f; ; ; # ?.🄄
+𝨖𐩙。۝󀡶ꣅ⒈; 𝨖𐩙.۝󀡶ꣅ⒈; [B1, P1, V5, V6]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈
+𝨖𐩙。۝󀡶ꣅ1.; 𝨖𐩙.۝󀡶ꣅ1.; [B1, P1, V5, V6]; xn--rt9cl956a.xn--1-dxc8545j0693i.; ; ; # 𝨖.ꣅ1.
+xn--rt9cl956a.xn--1-dxc8545j0693i.; 𝨖𐩙.۝󀡶ꣅ1.; [B1, V5, V6]; xn--rt9cl956a.xn--1-dxc8545j0693i.; ; ; # 𝨖.ꣅ1.
+xn--rt9cl956a.xn--tlb403mxv4g06s9i; 𝨖𐩙.۝󀡶ꣅ⒈; [B1, V5, V6]; xn--rt9cl956a.xn--tlb403mxv4g06s9i; ; ; # 𝨖.ꣅ⒈
+򒈣סڸ。Ⴈ‍; 򒈣סڸ.Ⴈ‍; [B5, B6, C2, P1, V6]; xn--meb44b57607c.xn--gnd699e; ; xn--meb44b57607c.xn--gnd; [B5, B6, P1, V6] # סڸ.Ⴈ
+򒈣סڸ。ⴈ‍; 򒈣סڸ.ⴈ‍; [B5, B6, C2, P1, V6]; xn--meb44b57607c.xn--1ug232c; ; xn--meb44b57607c.xn--zkj; [B5, B6, P1, V6] # סڸ.ⴈ
+xn--meb44b57607c.xn--zkj; 򒈣סڸ.ⴈ; [B5, B6, V6]; xn--meb44b57607c.xn--zkj; ; ; # סڸ.ⴈ
+xn--meb44b57607c.xn--1ug232c; 򒈣סڸ.ⴈ‍; [B5, B6, C2, V6]; xn--meb44b57607c.xn--1ug232c; ; ; # סڸ.ⴈ
+xn--meb44b57607c.xn--gnd; 򒈣סڸ.Ⴈ; [B5, B6, V6]; xn--meb44b57607c.xn--gnd; ; ; # סڸ.Ⴈ
+xn--meb44b57607c.xn--gnd699e; 򒈣סڸ.Ⴈ‍; [B5, B6, C2, V6]; xn--meb44b57607c.xn--gnd699e; ; ; # סڸ.Ⴈ
+󀚶𝨱ߦ⒈.𑗝髯‌; 󀚶𝨱ߦ⒈.𑗝髯‌; [B1, B5, C1, P1, V5, V6]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; xn--etb477lq931a1f58e.xn--uj6at43v; [B1, B5, P1, V5, V6] # 𝨱ߦ⒈.𑗝髯
+󀚶𝨱ߦ1..𑗝髯‌; ; [B1, B5, C1, P1, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, P1, V5, V6, A4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, P1, V5, V6, A4_2] # 𝨱ߦ1..𑗝髯
+xn--1-idd62296a1fr6e..xn--uj6at43v; 󀚶𝨱ߦ1..𑗝髯; [B1, B5, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--uj6at43v; [B1, B5, V5, V6, A4_2]; ; # 𝨱ߦ1..𑗝髯
+xn--1-idd62296a1fr6e..xn--0ugx259bocxd; 󀚶𝨱ߦ1..𑗝髯‌; [B1, B5, C1, V5, V6, X4_2]; xn--1-idd62296a1fr6e..xn--0ugx259bocxd; [B1, B5, C1, V5, V6, A4_2]; ; # 𝨱ߦ1..𑗝髯
+xn--etb477lq931a1f58e.xn--uj6at43v; 󀚶𝨱ߦ⒈.𑗝髯; [B1, B5, V5, V6]; xn--etb477lq931a1f58e.xn--uj6at43v; ; ; # 𝨱ߦ⒈.𑗝髯
+xn--etb477lq931a1f58e.xn--0ugx259bocxd; 󀚶𝨱ߦ⒈.𑗝髯‌; [B1, B5, C1, V5, V6]; xn--etb477lq931a1f58e.xn--0ugx259bocxd; ; ; # 𝨱ߦ⒈.𑗝髯
+𐫀.ډ𑌀; 𐫀.ډ𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+𐫀.ډ𑌀; ; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+xn--pw9c.xn--fjb8658k; 𐫀.ډ𑌀; ; xn--pw9c.xn--fjb8658k; ; ; # 𐫀.ډ𑌀
+𑋪.𐳝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐳝; ; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐲝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+xn--fm1d.xn--5c0d; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+𑋪.𐲝; 𑋪.𐳝; [B1, B3, B6, V5]; xn--fm1d.xn--5c0d; ; ; # 𑋪.𐳝
+≠膣。ྃ; ≠膣.ྃ; [P1, V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+≠膣。ྃ; ≠膣.ྃ; [P1, V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+xn--1chy468a.xn--2ed; ≠膣.ྃ; [V5, V6]; xn--1chy468a.xn--2ed; ; ; # ≠膣.ྃ
+񰀎-ݽ。ß; 񰀎-ݽ.ß; [B5, B6, P1, V6]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß
+񰀎-ݽ。ß; 񰀎-ݽ.ß; [B5, B6, P1, V6]; xn----j6c95618k.xn--zca; ; xn----j6c95618k.ss; # -ݽ.ß
+񰀎-ݽ。SS; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。Ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+xn----j6c95618k.ss; 񰀎-ݽ.ss; [B5, B6, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+xn----j6c95618k.xn--zca; 񰀎-ݽ.ß; [B5, B6, V6]; xn----j6c95618k.xn--zca; ; ; # -ݽ.ß
+񰀎-ݽ。SS; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+񰀎-ݽ。Ss; 񰀎-ݽ.ss; [B5, B6, P1, V6]; xn----j6c95618k.ss; ; ; # -ݽ.ss
+ς𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, P1, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+Σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; ; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ς𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, V6]; xn--3xa856hp23pxmc.xn--es5a888tvjc2u15h; ; ; # ς𐹠ᡚ𑄳.靑𐹽𐫜
+Σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+σ𐹠ᡚ𑄳.⾭𐹽𽐖𐫜; σ𐹠ᡚ𑄳.靑𐹽𽐖𐫜; [B5, B6, P1, V6]; xn--4xa656hp23pxmc.xn--es5a888tvjc2u15h; ; ; # σ𐹠ᡚ𑄳.靑𐹽𐫜
+𐋷。‍; 𐋷.‍; [C2]; xn--r97c.xn--1ug; ; xn--r97c.; [] # 𐋷.
+xn--r97c.; 𐋷.; ; xn--r97c.; ; ; # 𐋷.
+𐋷.; ; ; xn--r97c.; ; ; # 𐋷.
+xn--r97c.xn--1ug; 𐋷.‍; [C2]; xn--r97c.xn--1ug; ; ; # 𐋷.
+𑰳𑈯。⥪; 𑰳𑈯.⥪; [V5]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪
+xn--2g1d14o.xn--jti; 𑰳𑈯.⥪; [V5]; xn--2g1d14o.xn--jti; ; ; # 𑰳𑈯.⥪
+𑆀䁴񤧣.Ⴕ𝟜‌͈; 𑆀䁴񤧣.Ⴕ4‌͈; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; xn--1mnx647cg3x1b.xn--4-zfb324h; [P1, V5, V6] # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.Ⴕ4‌͈; ; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; xn--1mnx647cg3x1b.xn--4-zfb324h; [P1, V5, V6] # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.ⴕ4‌͈; ; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [P1, V5, V6] # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb5123a; 𑆀䁴񤧣.ⴕ4͈; [V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb5123a; ; ; # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb502tlsl; 𑆀䁴񤧣.ⴕ4‌͈; [C1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; ; # 𑆀䁴.ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb324h; 𑆀䁴񤧣.Ⴕ4͈; [V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h; ; ; # 𑆀䁴.Ⴕ4͈
+xn--1mnx647cg3x1b.xn--4-zfb324h32o; 𑆀䁴񤧣.Ⴕ4‌͈; [C1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb324h32o; ; ; # 𑆀䁴.Ⴕ4͈
+𑆀䁴񤧣.ⴕ𝟜‌͈; 𑆀䁴񤧣.ⴕ4‌͈; [C1, P1, V5, V6]; xn--1mnx647cg3x1b.xn--4-zfb502tlsl; ; xn--1mnx647cg3x1b.xn--4-zfb5123a; [P1, V5, V6] # 𑆀䁴.ⴕ4͈
+憡?‌Ⴔ.𐋮‍≠; ; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1chz659f; [P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌Ⴔ.𐋮‍≠; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1chz659f; [P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌ⴔ.𐋮‍≠; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [P1, V6] # 憡?ⴔ.𐋮≠
+憡?‌ⴔ.𐋮‍≠; ; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1chz659f; [P1, V6] # 憡?ⴔ.𐋮≠
+xn--?-fwsr13r.xn--1chz659f; 憡?ⴔ.𐋮≠; [P1, V6]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠
+xn--?-sgn310doh5c.xn--1ug73gl146a; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+xn--?-c1g3623d.xn--1chz659f; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+xn--?-c1g798iy27d.xn--1ug73gl146a; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+憡?ⴔ.xn--1chz659f; 憡?ⴔ.𐋮≠; [P1, V6]; xn--?-fwsr13r.xn--1chz659f; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.XN--1CHZ659F; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+憡?Ⴔ.xn--1chz659f; 憡?Ⴔ.𐋮≠; [P1, V6]; xn--?-c1g3623d.xn--1chz659f; ; ; # 憡?Ⴔ.𐋮≠
+憡?‌ⴔ.xn--1ug73gl146a; 憡?‌ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-sgn310doh5c.xn--1ug73gl146a; ; xn--?-fwsr13r.xn--1ug73gl146a; [C2, P1, V6] # 憡?ⴔ.𐋮≠
+憡?‌Ⴔ.XN--1UG73GL146A; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1ug73gl146a; [C2, P1, V6] # 憡?Ⴔ.𐋮≠
+憡?‌Ⴔ.xn--1ug73gl146a; 憡?‌Ⴔ.𐋮‍≠; [C1, C2, P1, V6]; xn--?-c1g798iy27d.xn--1ug73gl146a; ; xn--?-c1g3623d.xn--1ug73gl146a; [C2, P1, V6] # 憡?Ⴔ.𐋮≠
+xn--?-c1g3623d.xn--1ug73gl146a; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+xn--?-fwsr13r.xn--1ug73gl146a; 憡?ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.xn--1ug73gl146a; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
+憡?ⴔ.xn--1ug73gl146a; 憡?ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-fwsr13r.xn--1ug73gl146a; ; ; # 憡?ⴔ.𐋮≠
+憡?Ⴔ.XN--1UG73GL146A; 憡?Ⴔ.𐋮‍≠; [C2, P1, V6]; xn--?-c1g3623d.xn--1ug73gl146a; ; ; # 憡?Ⴔ.𐋮≠
diff --git a/test/lisp/net/puny-tests.el b/test/lisp/net/puny-tests.el
index c6f9474f65a..1b0cf56895e 100644
--- a/test/lisp/net/puny-tests.el
+++ b/test/lisp/net/puny-tests.el
@@ -68,4 +68,10 @@
"xn--b.com-gra"))
(should (equal (puny-encode-string "Bä.com") "xn--b.com-gra")))
+;;; TODO!
+;; puny-resources/IdnaTestV2.txt has a bunch of tests, and they should
+;; be implemented. However, the puny encoding does not fully
+;; implement https://www.unicode.org/reports/tr46/#Conformance yet, so
+;; it'll fail.
+
;;; puny-tests.el ends here
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
index 254595d1b4f..54d1ecf3652 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -888,7 +888,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(zerop (nth 1 fsi))
(zerop (nth 2 fsi))))))
-(ert-deftest tramp-archive-test46-auto-load ()
+(ert-deftest tramp-archive-test47-auto-load ()
"Check that `tramp-archive' autoloads properly."
:tags '(:expensive-test)
(skip-unless tramp-archive-enabled)
@@ -905,30 +905,33 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(file-attributes %S \"/\")) \
(message \"tramp-archive loaded: %%s\" \
(featurep 'tramp-archive))))"))
- (dolist (default-directory
- `(,temporary-file-directory
- ;; Starting Emacs in a directory which has
- ;; `tramp-archive-file-name-regexp' syntax is
- ;; supported only with Emacs > 27.2 (sigh!).
- ;; (Bug#48476)
- ,(file-name-as-directory tramp-archive-test-directory)))
- (dolist (file `("/mock::foo" ,(concat tramp-archive-test-archive "foo")))
- (should
- (string-match
- (format
- "tramp-archive loaded: %s[[:ascii:]]+tramp-archive loaded: %s"
- (tramp-archive-file-name-p default-directory)
- (or (tramp-archive-file-name-p default-directory)
- (tramp-archive-file-name-p file)))
- (shell-command-to-string
- (format
- "%s -batch -Q -L %s --eval %s"
- (shell-quote-argument
- (expand-file-name invocation-name invocation-directory))
- (mapconcat #'shell-quote-argument load-path " -L ")
- (shell-quote-argument (format code file))))))))))
-
-(ert-deftest tramp-archive-test46-delay-load ()
+ (dolist (enabled '(t nil))
+ (dolist (default-directory
+ `(,temporary-file-directory
+ ;; Starting Emacs in a directory which has
+ ;; `tramp-archive-file-name-regexp' syntax is
+ ;; supported only with Emacs > 27.2 (sigh!).
+ ;; (Bug#48476)
+ ,(file-name-as-directory tramp-archive-test-directory)))
+ (dolist (file `("/mock::foo" ,(concat tramp-archive-test-archive "foo")))
+ (should
+ (string-match
+ (format
+ "tramp-archive loaded: %s[[:ascii:]]+tramp-archive loaded: %s"
+ (tramp-archive-file-name-p default-directory)
+ (or (tramp-archive-file-name-p default-directory)
+ (and enabled (tramp-archive-file-name-p file))))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat #'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (format "(setq tramp-archive-enabled %s)" enabled))
+ (shell-quote-argument (format code file)))))))))))
+
+(ert-deftest tramp-archive-test47-delay-load ()
"Check that `tramp-archive' is loaded lazily, only when needed."
:tags '(:expensive-test)
(skip-unless tramp-archive-enabled)
diff --git a/test/lisp/net/tramp-resources/foo.tar.gz b/test/lisp/net/tramp-resources/foo.tar.gz
new file mode 100644
index 00000000000..0d2e9878dd7
--- /dev/null
+++ b/test/lisp/net/tramp-resources/foo.tar.gz
Binary files differ
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index ea0ff3c760e..8b6d10033f1 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -44,11 +44,11 @@
(require 'cl-lib)
(require 'dired)
(require 'dired-aux)
-(require 'ert)
+(require 'tramp)
(require 'ert-x)
(require 'seq) ; For `seq-random-elt', autoloaded since Emacs 28.1
+(require 'tar-mode)
(require 'trace)
-(require 'tramp)
(require 'vc)
(require 'vc-bzr)
(require 'vc-git)
@@ -64,24 +64,101 @@
(declare-function tramp-method-out-of-band-p "tramp-sh")
(declare-function tramp-smb-get-localname "tramp-smb")
(defvar ange-ftp-make-backup-files)
-(defvar auto-save-file-name-transforms)
-(defvar lock-file-name-transforms)
-(defvar remote-file-name-inhibit-locks)
(defvar tramp-connection-properties)
(defvar tramp-copy-size-limit)
(defvar tramp-display-escape-sequence-regexp)
+(defvar tramp-fuse-remove-hidden-files)
(defvar tramp-fuse-unmount-on-cleanup)
(defvar tramp-inline-compress-start-size)
(defvar tramp-persistency-file-name)
(defvar tramp-remote-path)
(defvar tramp-remote-process-environment)
+;; Needed for Emacs 26.
+(declare-function with-connection-local-variables "files-x")
;; Needed for Emacs 27.
+(defvar lock-file-name-transforms)
(defvar process-file-return-signal-string)
+(defvar remote-file-name-inhibit-locks)
(defvar shell-command-dont-erase-buffer)
;; Needed for Emacs 28.
(defvar dired-copy-dereference)
+;; `ert-resource-file' was introduced in Emacs 28.1.
+(unless (macrop 'ert-resource-file)
+ (eval-and-compile
+ (defvar ert-resource-directory-format "%s-resources/"
+ "Format for `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-left-regexp ""
+ "Regexp for `string-trim' (left) used by `ert-resource-directory'.")
+ (defvar ert-resource-directory-trim-right-regexp "\\(-tests?\\)?\\.el"
+ "Regexp for `string-trim' (right) used by `ert-resource-directory'.")
+
+ (defmacro ert-resource-directory ()
+ "Return absolute file name of the resource directory for this file.
+
+The path to the resource directory is the \"resources\" directory
+in the same directory as the test file.
+
+If that directory doesn't exist, use the directory named like the
+test file but formatted by `ert-resource-directory-format' and trimmed
+using `string-trim' with arguments
+`ert-resource-directory-trim-left-regexp' and
+`ert-resource-directory-trim-right-regexp'. The default values mean
+that if called from a test file named \"foo-tests.el\", return
+the absolute file name for \"foo-resources\"."
+ `(let* ((testfile ,(or (bound-and-true-p byte-compile-current-file)
+ (and load-in-progress load-file-name)
+ buffer-file-name))
+ (default-directory (file-name-directory testfile)))
+ (file-truename
+ (if (file-accessible-directory-p "resources/")
+ (expand-file-name "resources/")
+ (expand-file-name
+ (format
+ ert-resource-directory-format
+ (string-trim testfile
+ ert-resource-directory-trim-left-regexp
+ ert-resource-directory-trim-right-regexp)))))))
+
+ (defmacro ert-resource-file (file)
+ "Return file name of resource file named FILE.
+A resource file is in the resource directory as per
+`ert-resource-directory'."
+ `(expand-file-name ,file (ert-resource-directory)))))
+
+;; `ert-remote-temporary-file-directory' was introduced in Emacs 29.1.
+;; Adapting `tramp-remote-path' happens also there.
+(unless (boundp 'ert-remote-temporary-file-directory)
+ (eval-and-compile
+ ;; There is no default value on w32 systems, which could work out
+ ;; of the box.
+ (defconst ert-remote-temporary-file-directory
+ (cond
+ ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
+ ((eq system-type 'windows-nt) null-device)
+ (t (add-to-list
+ 'tramp-methods
+ '("mock"
+ (tramp-login-program "sh")
+ (tramp-login-args (("-i")))
+ (tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-args ("-c"))
+ (tramp-connection-timeout 10)))
+ (add-to-list
+ 'tramp-default-host-alist
+ `("\\`mock\\'" nil ,(system-name)))
+ ;; Emacs's Makefile sets $HOME to a nonexistent value.
+ ;; Needed in batch mode only, therefore.
+ (unless (and (null noninteractive) (file-directory-p "~/"))
+ (setenv "HOME" temporary-file-directory))
+ (format "/mock::%s" temporary-file-directory)))
+ "Temporary directory for remote file tests.")
+
+ ;; This should happen on hydra only.
+ (when (getenv "EMACS_HYDRA_CI")
+ (add-to-list 'tramp-remote-path 'tramp-own-remote-path))))
+
;; Beautify batch mode.
(when noninteractive
;; Suppress nasty messages.
@@ -91,32 +168,9 @@
'(fset 'tramp-gvfs-handler-askquestion
(lambda (_message _choices) '(t nil 0)))))
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst tramp-test-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed
- ;; in batch mode only, therefore.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" temporary-file-directory))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
-
(defconst tramp-test-vec
- (and (file-remote-p tramp-test-temporary-file-directory)
- (tramp-dissect-file-name tramp-test-temporary-file-directory))
+ (and (file-remote-p ert-remote-temporary-file-directory)
+ (tramp-dissect-file-name ert-remote-temporary-file-directory))
"The used `tramp-file-name' structure.")
(setq auth-source-save-behavior nil
@@ -125,13 +179,10 @@
tramp-allow-unsafe-temporary-files t
tramp-cache-read-persistent-data t ;; For auth-sources.
tramp-copy-size-limit nil
+ tramp-error-show-message-timeout nil
tramp-persistency-file-name nil
tramp-verbose 0)
-;; This should happen on hydra only.
-(when (getenv "EMACS_HYDRA_CI")
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
-
(defvar tramp--test-enabled-checked nil
"Cached result of `tramp--test-enabled'.
If the function did run, the value is a cons cell, the `cdr'
@@ -145,9 +196,9 @@ being the result.")
(cons
t (ignore-errors
(and
- (file-remote-p tramp-test-temporary-file-directory)
- (file-directory-p tramp-test-temporary-file-directory)
- (file-writable-p tramp-test-temporary-file-directory))))))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory))))))
(when (cdr tramp--test-enabled-checked)
;; Cleanup connection.
@@ -166,7 +217,7 @@ The temporary file is not created."
(if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(make-temp-name "tramp-test")
- (if local temporary-file-directory tramp-test-temporary-file-directory))))
+ (if local temporary-file-directory ert-remote-temporary-file-directory))))
;; Method "smb" supports `make-symbolic-link' only if the remote host
;; has CIFS capabilities. tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
@@ -248,12 +299,12 @@ Also see `ignore'."
"Test availability of Tramp functions."
:expected-result (if (tramp--test-enabled) :passed :failed)
(tramp--test-message
- "Remote directory: `%s'" tramp-test-temporary-file-directory)
+ "Remote directory: `%s'" ert-remote-temporary-file-directory)
(should (ignore-errors
(and
- (file-remote-p tramp-test-temporary-file-directory)
- (file-directory-p tramp-test-temporary-file-directory)
- (file-writable-p tramp-test-temporary-file-directory)))))
+ (file-remote-p ert-remote-temporary-file-directory)
+ (file-directory-p ert-remote-temporary-file-directory)
+ (file-writable-p ert-remote-temporary-file-directory)))))
(ert-deftest tramp-test01-file-name-syntax ()
"Check remote file name syntax."
@@ -796,8 +847,7 @@ Also see `ignore'."
(string-equal
(file-remote-p
"/method1:user1@host1|method2:user2@host2:/path/to/file")
- (format "/%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1" "method2" "user2" "host2")))
+ "/method2:user2@host2:"))
(should
(string-equal
(file-remote-p
@@ -833,10 +883,7 @@ Also see `ignore'."
"/method1:user1@host1"
"|method2:user2@host2"
"|method3:user3@host3:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/method3:user3@host3:"))
(should
(string-equal
(file-remote-p
@@ -895,10 +942,7 @@ Also see `ignore'."
"/-:user1@host1"
"|-:user2@host2"
"|-:user3@host3:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/method3:user3@host3:"))
;; Expand `tramp-default-user-alist'.
(add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
@@ -911,10 +955,7 @@ Also see `ignore'."
"/method1:host1"
"|method2:host2"
"|method3:host3:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/method3:user3@host3:"))
;; Expand `tramp-default-host-alist'.
(add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
@@ -927,10 +968,7 @@ Also see `ignore'."
"/method1:user1@"
"|method2:user2@"
"|method3:user3@:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/method3:user3@host3:"))
;; Ad-hoc user name and host name expansion.
(setq tramp-default-method-alist nil
@@ -943,10 +981,7 @@ Also see `ignore'."
"/method1:user1@host1"
"|method2:user2@"
"|method3:user3@:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user1" "host1"
- "method2" "user2" "host1"
- "method3" "user3" "host1")))
+ "/method3:user3@host1:"))
(should
(string-equal
(file-remote-p
@@ -955,11 +990,7 @@ Also see `ignore'."
"|method2:user2@host2"
"|method3:%u@%h"
"|method4:user4%domain4@host4#1234:/path/to/file"))
- (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s|%s:%s@%s:"
- "method1" "user2" "host2"
- "method2" "user2" "host2"
- "method3" "user4" "host4"
- "method4" "user4%domain4" "host4#1234"))))
+ "/method4:user4%domain4@host4#1234:")))
;; Exit.
(tramp-change-syntax syntax))))
@@ -1147,7 +1178,7 @@ Also see `ignore'."
(should
(string-equal
(file-remote-p "/user1@host1|user2@host2:/path/to/file")
- (format "/%s@%s|%s@%s:" "user1" "host1" "user2" "host2")))
+ "/user2@host2:"))
(should
(string-equal
(file-remote-p
@@ -1181,10 +1212,7 @@ Also see `ignore'."
"/user1@host1"
"|user2@host2"
"|user3@host3:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s:"
- "user1" "host1"
- "user2" "host2"
- "user3" "host3")))
+ "/user3@host3:"))
(should
(string-equal
(file-remote-p
@@ -1243,10 +1271,7 @@ Also see `ignore'."
"/host1"
"|host2"
"|host3:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s:"
- "user1" "host1"
- "user2" "host2"
- "user3" "host3")))
+ "/user3@host3:"))
;; Expand `tramp-default-host-alist'.
(add-to-list 'tramp-default-host-alist '(nil "user1" "host1"))
@@ -1259,10 +1284,7 @@ Also see `ignore'."
"/user1@"
"|user2@"
"|user3@:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s:"
- "user1" "host1"
- "user2" "host2"
- "user3" "host3")))
+ "/user3@host3:"))
;; Ad-hoc user name and host name expansion.
(setq tramp-default-user-alist nil
@@ -1274,10 +1296,7 @@ Also see `ignore'."
"/user1@host1"
"|user2@"
"|user3@:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s:"
- "user1" "host1"
- "user2" "host1"
- "user3" "host1")))
+ "/user3@host1:"))
(should
(string-equal
(file-remote-p
@@ -1286,11 +1305,7 @@ Also see `ignore'."
"|user2@host2"
"|%u@%h"
"|user4%domain4@host4#1234:/path/to/file"))
- (format "/%s@%s|%s@%s|%s@%s|%s@%s:"
- "user2" "host2"
- "user2" "host2"
- "user4" "host4"
- "user4%domain4" "host4#1234"))))
+ "/user4%domain4@host4#1234:")))
;; Exit.
(tramp-change-syntax syntax))))
@@ -1786,8 +1801,7 @@ Also see `ignore'."
(string-equal
(file-remote-p
"/[method1/user1@host1|method2/user2@host2]/path/to/file")
- (format "/[%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1" "method2" "user2" "host2")))
+ "/[method2/user2@host2]"))
(should
(string-equal
(file-remote-p
@@ -1823,10 +1837,7 @@ Also see `ignore'."
"/[method1/user1@host1"
"|method2/user2@host2"
"|method3/user3@host3]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/[method3/user3@host3]"))
(should
(string-equal
(file-remote-p
@@ -1885,10 +1896,7 @@ Also see `ignore'."
"/[/user1@host1"
"|/user2@host2"
"|/user3@host3]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/[method3/user3@host3]"))
;; Expand `tramp-default-user-alist'.
(add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
@@ -1901,10 +1909,7 @@ Also see `ignore'."
"/[method1/host1"
"|method2/host2"
"|method3/host3]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/[method3/user3@host3]"))
;; Expand `tramp-default-host-alist'.
(add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
@@ -1917,10 +1922,7 @@ Also see `ignore'."
"/[method1/user1@"
"|method2/user2@"
"|method3/user3@]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host2"
- "method3" "user3" "host3")))
+ "/[method3/user3@host3]"))
;; Ad-hoc user name and host name expansion.
(setq tramp-default-method-alist nil
@@ -1933,10 +1935,7 @@ Also see `ignore'."
"/[method1/user1@host1"
"|method2/user2@"
"|method3/user3@]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user1" "host1"
- "method2" "user2" "host1"
- "method3" "user3" "host1")))
+ "/[method3/user3@host1]"))
(should
(string-equal
(file-remote-p
@@ -1945,11 +1944,7 @@ Also see `ignore'."
"|method2/user2@host2"
"|method3/%u@%h"
"|method4/user4%domain4@host4#1234]/path/to/file"))
- (format "/[%s/%s@%s|%s/%s@%s|%s/%s@%s|%s/%s@%s]"
- "method1" "user2" "host2"
- "method2" "user2" "host2"
- "method3" "user4" "host4"
- "method4" "user4%domain4" "host4#1234"))))
+ "/[method4/user4%domain4@host4#1234]")))
;; Exit.
(tramp-change-syntax syntax))))
@@ -2006,7 +2001,7 @@ Also see `ignore'."
(find-file
(format
"%s|%s:foo:"
- (substring (file-remote-p tramp-test-temporary-file-directory) 0 -1)
+ (substring (file-remote-p ert-remote-temporary-file-directory) 0 -1)
m))
:type 'user-error))))
@@ -2022,17 +2017,7 @@ Also see `ignore'."
:type 'user-error)
(should-error
(expand-file-name "/method:user1@host1|ssh:user2@host2:/path/to/file")
- :type 'user-error))
-
- ;; Samba does not support file names with periods followed by
- ;; spaces, and trailing periods or spaces.
- (when (tramp--test-smb-p)
- (dolist (file '("foo." "foo. bar" "foo "))
- (should-error
- (tramp-smb-get-localname
- (tramp-dissect-file-name
- (expand-file-name file tramp-test-temporary-file-directory)))
- :type 'file-error))))
+ :type 'user-error)))
(ert-deftest tramp-test04-substitute-in-file-name ()
"Check `substitute-in-file-name'."
@@ -2178,25 +2163,25 @@ Also see `ignore'."
(ert-deftest tramp-test05-expand-file-name-relative ()
"Check `expand-file-name'."
(skip-unless (tramp--test-enabled))
- ;; The bugs are fixed in Emacs 28.1.
- (skip-unless (tramp--test-emacs28-p))
;; Methods with a share do not expand "/path/..".
(skip-unless (not (tramp--test-share-p)))
+ ;; The bugs are fixed in Emacs 28.1.
+ (skip-unless (tramp--test-emacs28-p))
(should
(string-equal
(let ((default-directory
(concat
- (file-remote-p tramp-test-temporary-file-directory) "/path")))
+ (file-remote-p ert-remote-temporary-file-directory) "/path")))
(expand-file-name ".." "./"))
- (concat (file-remote-p tramp-test-temporary-file-directory) "/"))))
+ (concat (file-remote-p ert-remote-temporary-file-directory) "/"))))
(ert-deftest tramp-test05-expand-file-name-top ()
"Check `expand-file-name'."
(skip-unless (tramp--test-enabled))
(skip-unless (not (tramp--test-ange-ftp-p)))
- (let ((dir (concat (file-remote-p tramp-test-temporary-file-directory) "/")))
+ (let ((dir (concat (file-remote-p ert-remote-temporary-file-directory) "/")))
(dolist (local '("." ".."))
(should (string-equal (expand-file-name local dir) dir))
(should (string-equal (expand-file-name (concat dir local)) dir)))))
@@ -2259,8 +2244,8 @@ This checks also `file-name-as-directory', `file-name-directory',
;; We must clear `tramp-default-method'. On hydra, it is "ftp",
;; which ruins the tests.
(let ((tramp-default-method
- (file-remote-p tramp-test-temporary-file-directory 'method))
- (host (file-remote-p tramp-test-temporary-file-directory 'host)))
+ (file-remote-p ert-remote-temporary-file-directory 'method))
+ (host (file-remote-p ert-remote-temporary-file-directory 'host)))
(dolist
(file
`(,(format "/%s::" tramp-default-method)
@@ -2282,21 +2267,27 @@ This checks also `file-name-as-directory', `file-name-directory',
(ert-deftest tramp-test07-abbreviate-file-name ()
"Check that Tramp abbreviates file names correctly."
(skip-unless (tramp--test-enabled))
- (skip-unless (tramp--test-emacs29-p))
(skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; `abbreviate-file-name' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
- (let* ((remote-host (file-remote-p tramp-test-temporary-file-directory))
+ ;; We must refill the cache. `file-truename' does it.
+ (file-truename ert-remote-temporary-file-directory)
+ (let* ((remote-host (file-remote-p ert-remote-temporary-file-directory))
+ (remote-host-nohop
+ (tramp-make-tramp-file-name (tramp-dissect-file-name remote-host)))
;; Not all methods can expand "~".
- (home-dir (ignore-errors (expand-file-name (concat remote-host "~")))))
+ (home-dir (ignore-errors (expand-file-name (concat remote-host "~"))))
+ home-dir-nohop)
(skip-unless home-dir)
;; Check home-dir abbreviation.
(unless (string-suffix-p "~" home-dir)
(should (equal (abbreviate-file-name (concat home-dir "/foo/bar"))
- (concat remote-host "~/foo/bar")))
+ (concat remote-host-nohop "~/foo/bar")))
(should (equal (abbreviate-file-name
(concat remote-host "/nowhere/special"))
- (concat remote-host "/nowhere/special"))))
+ (concat remote-host-nohop "/nowhere/special"))))
;; Check `directory-abbrev-alist' abbreviation.
(let ((directory-abbrev-alist
@@ -2305,19 +2296,21 @@ This checks also `file-name-as-directory', `file-name-directory',
(,(concat "\\`" (regexp-quote remote-host) "/nowhere")
. ,(concat remote-host "/nw")))))
(should (equal (abbreviate-file-name (concat home-dir "/foo/bar"))
- (concat remote-host "~/f/bar")))
+ (concat remote-host-nohop "~/f/bar")))
(should (equal (abbreviate-file-name
(concat remote-host "/nowhere/special"))
- (concat remote-host "/nw/special"))))
+ (concat remote-host-nohop "/nw/special"))))
;; Check that home-dir abbreviation doesn't occur when home-dir is just "/".
- (setq home-dir (concat remote-host "/"))
- ;; The remote home directory is kept in the connection property
- ;; "home-directory". We fake this setting.
- (tramp-set-connection-property tramp-test-vec "home-directory" home-dir)
- (should (equal (concat home-dir "foo/bar")
- (abbreviate-file-name (concat home-dir "foo/bar"))))
- (tramp-flush-connection-property tramp-test-vec "home-directory")))
+ (setq home-dir (concat remote-host "/")
+ home-dir-nohop
+ (tramp-make-tramp-file-name (tramp-dissect-file-name home-dir)))
+ ;; The remote home directory is kept in the connection property "~".
+ ;; We fake this setting.
+ (tramp-set-connection-property tramp-test-vec "~" (file-local-name home-dir))
+ (should (equal (abbreviate-file-name (concat home-dir "foo/bar"))
+ (concat home-dir-nohop "foo/bar")))
+ (tramp-flush-connection-property tramp-test-vec "~")))
(ert-deftest tramp-test07-file-exists-p ()
"Check `file-exist-p', `write-region' and `delete-file'."
@@ -2369,7 +2362,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(insert-file-contents tmp-name2)
(should (string-equal (buffer-string) "foo")))
;; Check also that a file transfer with compression works.
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tramp-copy-size-limit 4)
(tramp-inline-compress-start-size 2))
(delete-file tmp-name2)
@@ -2551,13 +2544,65 @@ This checks also `file-name-as-directory', `file-name-directory',
(setq-local file-precious-flag t)
(setq-local backup-inhibited t)
(insert "bar")
+ (should (buffer-modified-p))
(should (null (save-buffer)))
+ (should (not (buffer-modified-p)))
(should-not (cl-member tmp-name written-files :test #'string=)))
;; Cleanup.
(ignore-errors (advice-remove 'write-region advice))
(ignore-errors (delete-file tmp-name)))))
+;; The following test is inspired by Bug#55166.
+(ert-deftest tramp-test10-write-region-other-file-name-handler ()
+ "Check that another file name handler in VISIT is acknowledged."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ (skip-unless (executable-find "gzip"))
+ ;; The function was introduced in Emacs 28.1.
+ (skip-unless (boundp 'tar-goto-file))
+
+ (let* ((default-directory ert-remote-temporary-file-directory)
+ (archive (ert-resource-file "foo.tar.gz"))
+ (tmp-file (expand-file-name (file-name-nondirectory archive)))
+ (require-final-newline t)
+ (inhibit-message t)
+ (backup-inhibited t)
+ create-lockfiles buffer1 buffer2)
+ (unwind-protect
+ (progn
+ (copy-file archive tmp-file 'ok)
+ ;; Read archive. Check contents of foo.txt, and modify it. Save.
+ (with-current-buffer (setq buffer1 (find-file-noselect tmp-file))
+ ;; The function was introduced in Emacs 28.1.
+ (with-no-warnings (should (tar-goto-file "foo.txt")))
+ (save-current-buffer
+ (setq buffer2 (tar-extract))
+ (should (string-equal (buffer-string) "foo\n"))
+ (goto-char (point-max))
+ (insert "bar")
+ (should (buffer-modified-p))
+ (should (null (save-buffer)))
+ (should-not (buffer-modified-p)))
+ (should (buffer-modified-p))
+ (should (null (save-buffer)))
+ (should-not (buffer-modified-p)))
+
+ (kill-buffer buffer1)
+ (kill-buffer buffer2)
+ ;; Read archive. Check contents of modified foo.txt.
+ (with-current-buffer (setq buffer1 (find-file-noselect tmp-file))
+ ;; The function was introduced in Emacs 28.1.
+ (with-no-warnings (should (tar-goto-file "foo.txt")))
+ (save-current-buffer
+ (setq buffer2 (tar-extract))
+ (should (string-equal (buffer-string) "foo\nbar\n")))))
+
+ ;; Cleanup.
+ (ignore-errors (kill-buffer buffer1))
+ (ignore-errors (kill-buffer buffer2))
+ (ignore-errors (delete-file tmp-file)))))
+
(ert-deftest tramp-test11-copy-file ()
"Check `copy-file'."
(skip-unless (tramp--test-enabled))
@@ -3018,7 +3063,8 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
- (let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (let* ((tramp-fuse-remove-hidden-files t)
+ (tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "bla" tmp-name1))
(tmp-name3 (expand-file-name "foo" tmp-name1)))
(unwind-protect
@@ -3062,7 +3108,8 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
- (let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+ (let* ((tramp-fuse-remove-hidden-files t)
+ (tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(tmp-name3 (expand-file-name "bar" tmp-name1))
(tmp-name4 (expand-file-name "baz" tmp-name1))
@@ -3205,7 +3252,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(ert-deftest tramp-test17-dired-with-wildcards ()
"Check `dired' with wildcards."
;; `separate' syntax and IPv6 host name syntax do not work.
- (skip-unless (not (string-match-p "\\[" tramp-test-temporary-file-directory)))
+ (skip-unless (not (string-match-p "\\[" ert-remote-temporary-file-directory)))
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
(skip-unless (not (tramp--test-rsync-p)))
@@ -3219,10 +3266,10 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name3 (expand-file-name "foo" tmp-name1))
(tmp-name4 (expand-file-name "bar" tmp-name2))
- (tramp-test-temporary-file-directory
+ (ert-remote-temporary-file-directory
(funcall
(if quoted #'tramp-compat-file-name-quote #'identity)
- tramp-test-temporary-file-directory))
+ ert-remote-temporary-file-directory))
buffer)
(unwind-protect
(progn
@@ -3240,19 +3287,19 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*" tramp-test-temporary-file-directory)))
+ "tramp-test*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
- tmp-name1 tramp-test-temporary-file-directory))))
+ tmp-name1 ert-remote-temporary-file-directory))))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
- tmp-name2 tramp-test-temporary-file-directory)))))
+ tmp-name2 ert-remote-temporary-file-directory)))))
(kill-buffer buffer)
;; Check for expanded directory and file names.
@@ -3260,20 +3307,20 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*/*" tramp-test-temporary-file-directory)))
+ "tramp-test*/*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
- tmp-name3 tramp-test-temporary-file-directory))))
+ tmp-name3 ert-remote-temporary-file-directory))))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
tmp-name4
- tramp-test-temporary-file-directory)))))
+ ert-remote-temporary-file-directory)))))
(kill-buffer buffer)
;; Check for special characters.
@@ -3288,20 +3335,20 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(setq buffer
(dired-noselect
(expand-file-name
- "tramp-test*/*" tramp-test-temporary-file-directory)))
+ "tramp-test*/*" ert-remote-temporary-file-directory)))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
- tmp-name3 tramp-test-temporary-file-directory))))
+ tmp-name3 ert-remote-temporary-file-directory))))
(goto-char (point-min))
(should
(re-search-forward
(regexp-quote
(file-relative-name
tmp-name4
- tramp-test-temporary-file-directory)))))
+ ert-remote-temporary-file-directory)))))
(kill-buffer buffer))
;; Cleanup.
@@ -3374,8 +3421,8 @@ This tests also `access-file', `file-readable-p',
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
;; File name with "//".
@@ -3395,7 +3442,7 @@ This tests also `access-file', `file-readable-p',
(and test-file-ownership-preserved-p
(zerop (logand
#o1000
- (file-modes tramp-test-temporary-file-directory))))
+ (file-modes ert-remote-temporary-file-directory))))
(write-region "foo" nil tmp-name1)
(setq test-file-ownership-preserved-p
(= (file-attribute-group-id (file-attributes tmp-name1))
@@ -3474,7 +3521,7 @@ This tests also `access-file', `file-readable-p',
;; Check, that "//" in symlinks are handled properly.
(with-temp-buffer
- (let ((default-directory tramp-test-temporary-file-directory))
+ (let ((default-directory ert-remote-temporary-file-directory))
(shell-command
(format
"ln -s %s %s"
@@ -3488,8 +3535,10 @@ This tests also `access-file', `file-readable-p',
(should
(string-equal
(file-attribute-type attr)
- (tramp-file-name-localname
- (tramp-dissect-file-name tmp-name3))))
+ (funcall
+ (if (tramp--test-sshfs-p) #'file-name-nondirectory #'identity)
+ (tramp-file-name-localname
+ (tramp-dissect-file-name tmp-name3)))))
(delete-file tmp-name2))
(when test-file-ownership-preserved-p
@@ -3649,7 +3698,9 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(should (= (file-modes tmp-name1) #o444))
(should-not (file-executable-p tmp-name1))
;; A file is always writable for user "root".
- (unless (zerop (file-attribute-user-id (file-attributes tmp-name1)))
+ (unless
+ (or (zerop (file-attribute-user-id (file-attributes tmp-name1)))
+ (tramp--test-sshfs-p))
(should-not (file-writable-p tmp-name1)))
;; Check the NOFOLLOW arg. It exists since Emacs 28. For
;; regular files, there shouldn't be a difference.
@@ -3728,8 +3779,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name 'local quoted))
@@ -3876,7 +3927,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should (file-equal-p tmp-name1 tmp-name2))
;; Check relative symlink file name.
(delete-file tmp-name2)
- (let ((default-directory tramp-test-temporary-file-directory))
+ (let ((default-directory ert-remote-temporary-file-directory))
(make-symbolic-link (file-name-nondirectory tmp-name1) tmp-name2))
(should (file-symlink-p tmp-name2))
(should-not (string-equal tmp-name2 (file-truename tmp-name2)))
@@ -3923,7 +3974,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(tramp--test-ignore-make-symbolic-link-error
(make-directory tmp-name1)
(should (file-directory-p tmp-name1))
- (let* ((tramp-test-temporary-file-directory
+ (let* ((ert-remote-temporary-file-directory
(file-truename tmp-name1))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 tmp-name2)
@@ -3984,7 +4035,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(directory-file-name
(funcall
(if quoted #'tramp-compat-file-name-quote #'identity)
- tramp-test-temporary-file-directory)))
+ ert-remote-temporary-file-directory)))
(dir2 (file-name-as-directory dir1)))
(should (string-equal (file-truename dir1) (expand-file-name dir1)))
(should (string-equal (file-truename dir2) (expand-file-name dir2)))))))
@@ -4074,7 +4125,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
"Check that `file-acl' and `set-file-acl' work proper."
(skip-unless (tramp--test-enabled))
;; The following test checks also whether `set-file-modes' will work.
- (skip-unless (file-acl tramp-test-temporary-file-directory))
+ (skip-unless (file-acl ert-remote-temporary-file-directory))
(skip-unless (not (tramp--test-crypt-p)))
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
@@ -4153,7 +4204,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
"Check `file-selinux-context' and `set-file-selinux-context'."
(skip-unless (tramp--test-enabled))
(skip-unless
- (not (equal (file-selinux-context tramp-test-temporary-file-directory)
+ (not (equal (file-selinux-context ert-remote-temporary-file-directory)
'(nil nil nil nil))))
(skip-unless (not (tramp--test-crypt-p)))
@@ -4214,7 +4265,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(let ((default-directory temporary-file-directory))
(shell-command-to-string "id -Z"))
(let ((default-directory
- tramp-test-temporary-file-directory))
+ ert-remote-temporary-file-directory))
(shell-command-to-string "id -Z"))))
;; Two files with same SELinux context.
@@ -4298,8 +4349,9 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Method and host name in completion mode. This kind of completion
;; does not work on MS Windows.
(unless (memq system-type '(cygwin windows-nt))
- (let ((method (file-remote-p tramp-test-temporary-file-directory 'method))
- (host (file-remote-p tramp-test-temporary-file-directory 'host))
+ (let ((tramp-fuse-remove-hidden-files t)
+ (method (file-remote-p ert-remote-temporary-file-directory 'method))
+ (host (file-remote-p ert-remote-temporary-file-directory 'host))
(orig-syntax tramp-syntax))
(when (and (stringp host) (string-match tramp-host-with-port-regexp host))
(setq host (match-string 1 host)))
@@ -4350,7 +4402,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(dolist (non-essential '(nil t))
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
- (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
+ (let ((tramp-fuse-remove-hidden-files t)
+ (tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -4420,7 +4473,9 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
- (load tmp-name 'noerror 'nomessage)
+ ;; Ange-FTP does not tolerate a missing file, even with `noerror'.
+ (unless (tramp--test-ange-ftp-p)
+ (load tmp-name 'noerror 'nomessage))
(should-not (featurep 'tramp-test-load))
(write-region "(provide 'tramp-test-load)" nil tmp-name)
;; `load' in lread.c does not pass `must-suffix'. Why?
@@ -4448,7 +4503,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name (tramp--test-make-temp-name nil quoted))
(fnnd (file-name-nondirectory tmp-name))
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
+ (buffer (get-buffer-create "*tramp-tests*"))
kill-buffer-query-functions)
(unwind-protect
(progn
@@ -4481,32 +4537,87 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(tramp--test-shell-file-name)
nil nil nil "-c" "kill -2 $$")))))
- (with-temp-buffer
- (write-region "foo" nil tmp-name)
- (should (file-exists-p tmp-name))
- (should (zerop (process-file "ls" nil t nil fnnd)))
- ;; "ls" could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- (should (string-equal (format "%s\n" fnnd) (buffer-string)))
- (should-not (get-buffer-window (current-buffer) t))
+ ;; Check DESTINATION.
+ (dolist (destination `(nil t ,buffer))
+ (when (bufferp destination)
+ (with-current-buffer destination
+ (delete-region (point-min) (point-max))))
+ (with-temp-buffer
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (should (zerop (process-file "ls" nil destination nil fnnd)))
+ (with-current-buffer
+ (if (bufferp destination) destination (current-buffer))
+ ;; "ls" could produce colorized output.
+ (goto-char (point-min))
+ (while (re-search-forward
+ tramp-display-escape-sequence-regexp nil t)
+ (replace-match "" nil nil))
+ (should
+ (string-equal (if destination (format "%s\n" fnnd) "")
+ (buffer-string)))
+ (should-not (get-buffer-window (current-buffer) t))
+ (goto-char (point-max)))
+
+ ;; Second run. The output must be appended.
+ (should (zerop (process-file "ls" nil destination t fnnd)))
+ (with-current-buffer
+ (if (bufferp destination) destination (current-buffer))
+ ;; "ls" could produce colorized output.
+ (goto-char (point-min))
+ (while (re-search-forward
+ tramp-display-escape-sequence-regexp nil t)
+ (replace-match "" nil nil))
+ (should
+ (string-equal
+ (if destination (format "%s\n%s\n" fnnd fnnd) "")
+ (buffer-string))))
- ;; Second run. The output must be appended.
- (goto-char (point-max))
- (should (zerop (process-file "ls" nil t t fnnd)))
- ;; "ls" could produce colorized output.
- (goto-char (point-min))
- (while
- (re-search-forward tramp-display-escape-sequence-regexp nil t)
- (replace-match "" nil nil))
- (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))))
+ (unless (eq destination t)
+ (should (string-empty-p (buffer-string))))
+ ;; A non-nil DISPLAY must not raise the buffer.
+ (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)))
+
+ ;; Check remote and local DESTNATION file. This isn't
+ ;; implemented yet ina all file name handler backends.
+ ;; (dolist (local '(nil t))
+ ;; (setq tmp-name (tramp--test-make-temp-name local quoted))
+ ;; (should
+ ;; (zerop (process-file "echo" nil `(:file ,tmp-name) nil "foo")))
+ ;; (with-temp-buffer
+ ;; (insert-file-contents tmp-name)
+ ;; (should (string-equal "foo" (buffer-string)))
+ ;; (should-not (get-buffer-window (current-buffer) t))
+ ;; (delete-file tmp-name)))
+
+ ;; Check remote and local STDERR.
+ (dolist (local '(nil t))
+ (setq tmp-name (tramp--test-make-temp-name local quoted))
+ (should-not
+ (zerop
+ (process-file "cat" nil `(t ,tmp-name) nil "/does-not-exist")))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should
+ (string-match-p
+ "cat:.* No such file or directory" (buffer-string)))
+ (should-not (get-buffer-window (current-buffer) t))
+ (delete-file tmp-name))))
;; Cleanup.
+ (ignore-errors (kill-buffer buffer))
(ignore-errors (delete-file tmp-name))))))
;; Must be a command, because used as `sigusr1' handler.
@@ -4526,16 +4637,19 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-supports-processes-p))
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name nil quoted))
- kill-buffer-query-functions proc)
+ kill-buffer-query-functions command proc)
;; Simple process.
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test1" (current-buffer) "cat"))
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test1" (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output.
@@ -4552,11 +4666,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(with-temp-buffer
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
- (setq proc
- (start-file-process
- "test2" (current-buffer)
- "cat" (file-name-nondirectory tmp-name)))
+ (setq command `("cat" ,(file-name-nondirectory tmp-name))
+ proc
+ (apply #'start-file-process "test2" (current-buffer) command))
(should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
(while (< (- (point-max) (point-min)) (length "foo"))
@@ -4571,9 +4685,12 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Process filter.
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test3" (current-buffer) "cat"))
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test3" (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(set-process-filter
proc
(lambda (p s) (with-current-buffer (process-buffer p) (insert s))))
@@ -4592,9 +4709,12 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(unless (tramp--test-sshfs-p)
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process "test3" (current-buffer) "cat"))
+ (setq command '("cat")
+ proc
+ (apply #'start-file-process "test4" (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(set-process-filter proc t)
(process-send-string proc "foo\n")
(process-send-eof proc)
@@ -4620,12 +4740,14 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(dolist (process-connection-type '(nil pipe t pty))
(unwind-protect
(with-temp-buffer
- (setq proc
- (start-file-process
- (format "test4-%s" process-connection-type)
- (current-buffer) "hexdump" "-v" "-e" "/1 \"%02X\n\""))
+ (setq command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+ proc
+ (apply #'start-file-process
+ (format "test5-%s" process-connection-type)
+ (current-buffer) command))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\r\n")
(process-send-eof proc)
;; Read output.
@@ -4653,12 +4775,13 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; It works only for tramp-sh.el, and not direct async processes.
(if (or (not (tramp--test-sh-p)) (tramp-direct-async-process-p))
(should-error
- (start-file-process "test5" (current-buffer) nil)
+ (start-file-process "test6" (current-buffer) nil)
:type 'wrong-type-argument)
- (setq proc (start-file-process "test5" (current-buffer) nil))
+ (setq proc (start-file-process "test6" (current-buffer) nil))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should-not (process-get proc 'remote-command))
;; On MS Windows, `process-tty-name' returns nil.
(unless (tramp--test-windows-nt-p)
(should (stringp (process-tty-name proc))))))
@@ -4680,7 +4803,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
:tags (append '(:expensive-test :tramp-asynchronous-processes)
(and ,unstable '(:unstable)))
(skip-unless (tramp--test-enabled))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(ert-test (ert-get-test ',test))
(tramp-connection-properties
(cons '(nil "direct-async-process" t)
@@ -4693,7 +4816,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(cl-letf (((symbol-function #'tramp--test-enabled) #'tramp--test-always)
((symbol-function #'internal-default-process-sentinel)
#'ignore))
- (file-truename tramp-test-temporary-file-directory)
+ (file-truename ert-remote-temporary-file-directory)
(funcall (ert-test-body ert-test)))))))
(tramp--test--deftest-direct-async-process tramp-test29-start-file-process
@@ -4701,28 +4824,32 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(ert-deftest tramp-test30-make-process ()
"Check `make-process'."
- :tags '(:expensive-test :tramp-asynchronous-processes)
+ :tags (append '(:expensive-test :tramp-asynchronous-processes)
+ (and (getenv "EMACS_EMBA_CI")
+ '(:unstable)))
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-supports-processes-p))
;; `make-process' supports file name handlers since Emacs 27.
(skip-unless (tramp--test-emacs27-p))
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name nil quoted))
- kill-buffer-query-functions proc)
+ kill-buffer-query-functions command proc)
(with-no-warnings (should-not (make-process)))
;; Simple process.
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat")
+ proc
(with-no-warnings
(make-process
- :name "test1" :buffer (current-buffer) :command '("cat")
+ :name "test1" :buffer (current-buffer) :command command
:file-handler t)))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output.
@@ -4739,13 +4866,14 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(with-temp-buffer
(write-region "foo" nil tmp-name)
(should (file-exists-p tmp-name))
- (setq proc
+ (setq command `("cat" ,(file-name-nondirectory tmp-name))
+ proc
(with-no-warnings
(make-process
- :name "test2" :buffer (current-buffer)
- :command `("cat" ,(file-name-nondirectory tmp-name))
+ :name "test2" :buffer (current-buffer) :command command
:file-handler t)))
(should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
(while (< (- (point-max) (point-min)) (length "foo"))
@@ -4760,16 +4888,18 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
;; Process filter.
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat")
+ proc
(with-no-warnings
(make-process
- :name "test3" :buffer (current-buffer) :command '("cat")
+ :name "test3" :buffer (current-buffer) :command command
:filter
(lambda (p s)
(with-current-buffer (process-buffer p) (insert s)))
:file-handler t)))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output.
@@ -4785,14 +4915,16 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(unless (tramp--test-sshfs-p)
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat")
+ proc
(with-no-warnings
(make-process
- :name "test3" :buffer (current-buffer) :command '("cat")
+ :name "test4" :buffer (current-buffer) :command command
:filter t
:file-handler t)))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\n")
(process-send-eof proc)
;; Read output. There shouldn't be any.
@@ -4808,16 +4940,18 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
;; Process sentinel.
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat")
+ proc
(with-no-warnings
(make-process
- :name "test4" :buffer (current-buffer) :command '("cat")
+ :name "test5" :buffer (current-buffer) :command command
:sentinel
(lambda (p s)
(with-current-buffer (process-buffer p) (insert s)))
:file-handler t)))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\n")
(process-send-eof proc)
(delete-process proc)
@@ -4836,14 +4970,15 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(let ((stderr (generate-new-buffer "*stderr*")))
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat" "/does-not-exist")
+ proc
(with-no-warnings
(make-process
- :name "test5" :buffer (current-buffer)
- :command '("cat" "/does-not-exist")
+ :name "test6" :buffer (current-buffer) :command command
:stderr stderr
:file-handler t)))
(should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
;; Read output.
(with-timeout (10 (tramp--test-timeout-handler))
(while (accept-process-output proc 0 nil t)))
@@ -4867,14 +5002,15 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(unless (tramp-direct-async-process-p)
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("cat" "/does-not-exist")
+ proc
(with-no-warnings
(make-process
- :name "test6" :buffer (current-buffer)
- :command '("cat" "/does-not-exist")
+ :name "test7" :buffer (current-buffer) :command command
:stderr tmp-name
:file-handler t)))
(should (processp proc))
+ (should (equal (process-get proc 'remote-command) command))
;; Read stderr.
(with-timeout (10 (tramp--test-timeout-handler))
(while (accept-process-output proc nil nil t)))
@@ -4905,18 +5041,20 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(unless connection-type '(nil pipe t pty)))
(unwind-protect
(with-temp-buffer
- (setq proc
+ (setq command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+ proc
(with-no-warnings
(make-process
:name
- (format "test7-%s-%s"
+ (format "test8-%s-%s"
connection-type process-connection-type)
:buffer (current-buffer)
:connection-type connection-type
- :command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+ :command command
:file-handler t)))
(should (processp proc))
(should (equal (process-status proc) 'run))
+ (should (equal (process-get proc 'remote-command) command))
(process-send-string proc "foo\r\n")
(process-send-eof proc)
;; Read output.
@@ -4944,28 +5082,33 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(ert-deftest tramp-test31-interrupt-process ()
"Check `interrupt-process'."
- :tags (append '(:expensive-test :tramp-asynchronous-processes)
- (and (or (getenv "EMACS_HYDRA_CI") (getenv "EMACS_EMBA_CI"))
- '(:unstable)))
+ ;; The final `process-live-p' check does not run sufficiently.
+ :tags '(:expensive-test :tramp-asynchronous-processes :unstable)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-windows-nt-p)))
(skip-unless (not (tramp--test-crypt-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (macrop 'with-connection-local-variables))
;; We must use `file-truename' for the temporary directory, in
;; order to establish the connection prior running an asynchronous
;; process.
- (let ((default-directory (file-truename tramp-test-temporary-file-directory))
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
(delete-exited-processes t)
- kill-buffer-query-functions proc)
+ kill-buffer-query-functions command proc)
(unwind-protect
(with-temp-buffer
- (setq proc (start-file-process-shell-command
- "test" (current-buffer)
- "trap 'echo boom; exit 1' 2; sleep 100"))
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ "test" (current-buffer) command))
(should (processp proc))
(should (process-live-p proc))
(should (equal (process-status proc) 'run))
(should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
(should (interrupt-process proc))
;; Let the process accept the interrupt.
(with-timeout (10 (tramp--test-timeout-handler))
@@ -4980,12 +5123,132 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
;; Cleanup.
(ignore-errors (delete-process proc)))))
+(ert-deftest tramp-test31-signal-process ()
+ "Check `signal-process'."
+ ;; The final `process-live-p' check does not run sufficiently.
+ :tags '(:expensive-test :tramp-asynchronous-processes :unstable)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ (skip-unless (not (tramp--test-windows-nt-p)))
+ (skip-unless (not (tramp--test-crypt-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (macrop 'with-connection-local-variables))
+ ;; Since Emacs 29.1.
+ (skip-unless (boundp 'signal-process-functions))
+
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
+ (delete-exited-processes t)
+ kill-buffer-query-functions command proc)
+
+ (dolist (sigcode '(2 INT))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test1%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ (should (zerop (signal-process proc sigcode)))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
+
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))
+
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test2%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ ;; `signal-process' has argument REMOTE since Emacs 29.
+ (with-no-warnings
+ (should
+ (zerop
+ (signal-process
+ (process-get proc 'remote-pid) sigcode default-directory))))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
+
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc))))))
+
+(ert-deftest tramp-test31-list-system-processes ()
+ "Check `list-system-processes'."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; `list-system-processes' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
+
+ (let ((default-directory ert-remote-temporary-file-directory))
+ (skip-unless (consp (list-system-processes)))
+ (should (not (equal (list-system-processes)
+ (let ((default-directory temporary-file-directory))
+ (list-system-processes)))))))
+
+(ert-deftest tramp-test31-process-attributes ()
+ "Check `process-attributes'."
+ :tags '(:expensive-test :tramp-asynchronous-processes)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-supports-processes-p))
+ ;; `process-attributes' is supported since Emacs 29.1.
+ (skip-unless (tramp--test-emacs29-p))
+
+ ;; We must use `file-truename' for the temporary directory, in
+ ;; order to establish the connection prior running an asynchronous
+ ;; process.
+ (let ((default-directory (file-truename ert-remote-temporary-file-directory))
+ (delete-exited-processes t)
+ kill-buffer-query-functions command proc)
+ (skip-unless (consp (list-system-processes)))
+
+ (unwind-protect
+ (progn
+ (setq command '("sleep" "100")
+ proc (apply #'start-file-process "test" nil command))
+ (while (accept-process-output proc 0))
+ (when-let ((pid (process-get proc 'remote-pid))
+ (attributes (process-attributes pid)))
+ ;; (tramp--test-message "%s" attributes)
+ (should (equal (cdr (assq 'comm attributes)) (car command)))
+ (should (equal (cdr (assq 'args attributes))
+ (mapconcat #'identity command " ")))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-process proc)))))
+
(defun tramp--test-async-shell-command
(command output-buffer &optional error-buffer input)
"Like `async-shell-command', reading the output.
INPUT, if non-nil, is a string sent to the process."
(let ((proc (async-shell-command command output-buffer error-buffer))
(delete-exited-processes t))
+ ;; Since Emacs 27.1.
+ (when (macrop 'with-connection-local-variables)
+ (should (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command)))))
(cl-letf (((symbol-function #'shell-command-sentinel) #'ignore))
(when (stringp input)
(process-send-string proc input))
@@ -5013,7 +5276,7 @@ INPUT, if non-nil, is a string sent to the process."
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted))
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
;; Suppress nasty messages.
(inhibit-message t)
kill-buffer-query-functions)
@@ -5094,7 +5357,7 @@ INPUT, if non-nil, is a string sent to the process."
(when (and (tramp--test-asynchronous-processes-p)
(tramp--test-sh-p) (tramp--test-emacs27-p))
(let* ((async-shell-command-width 1024)
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
(cols (ignore-errors
(read (tramp--test-shell-command-to-string-asynchronously
"tput cols")))))
@@ -5146,7 +5409,7 @@ INPUT, if non-nil, is a string sent to the process."
;; We check both the local and remote case, in order to guarantee
;; that they behave similar.
(dolist (default-directory
- `(,temporary-file-directory ,tramp-test-temporary-file-directory))
+ `(,temporary-file-directory ,ert-remote-temporary-file-directory))
;; These are the possible values of `shell-command-dont-erase-buffer'.
;; `random' is taken as non-nil value without special meaning.
(dolist (shell-command-dont-erase-buffer
@@ -5246,7 +5509,7 @@ INPUT, if non-nil, is a string sent to the process."
(and (tramp--test-asynchronous-processes-p)
'(tramp--test-shell-command-to-string-asynchronously))))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(shell-file-name "/bin/sh")
(envvar (concat "VAR_" (upcase (md5 (current-time-string)))))
kill-buffer-query-functions)
@@ -5337,7 +5600,7 @@ Use direct async.")
(skip-unless (not (tramp--test-crypt-p)))
;; We force a reconnect, in order to have a clean environment.
- (dolist (dir `(,tramp-test-temporary-file-directory
+ (dolist (dir `(,ert-remote-temporary-file-directory
"/mock:localhost#11111:" "/mock:localhost#22222:"))
(tramp-cleanup-connection
(tramp-dissect-file-name dir) 'keep-debug 'keep-password))
@@ -5369,9 +5632,9 @@ Use direct async.")
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
;; Since Emacs 27.1.
- (skip-unless (fboundp 'with-connection-local-variables))
+ (skip-unless (macrop 'with-connection-local-variables))
- (let* ((default-directory tramp-test-temporary-file-directory)
+ (let* ((default-directory ert-remote-temporary-file-directory)
(tmp-name1 (tramp--test-make-temp-name))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(enable-local-variables :all)
@@ -5385,6 +5648,8 @@ Use direct async.")
(should (file-directory-p tmp-name1))
;; `local-variable' is buffer-local due to explicit setting.
+ ;; We need `with-no-warnings', because `defvar-local' is not
+ ;; called at toplevel.
(with-no-warnings
(defvar-local local-variable 'buffer))
(with-temp-buffer
@@ -5436,7 +5701,7 @@ Use direct async.")
(when (tramp--test-adb-p)
(skip-unless (tramp--test-emacs27-p)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
explicit-shell-file-name kill-buffer-query-functions
connection-local-profile-alist connection-local-criteria-alist)
(unwind-protect
@@ -5486,7 +5751,7 @@ Use direct async.")
(skip-unless (fboundp 'exec-path))
(let ((tmp-name (tramp--test-make-temp-name))
- (default-directory tramp-test-temporary-file-directory))
+ (default-directory ert-remote-temporary-file-directory))
(unwind-protect
(progn
(should (consp (with-no-warnings (exec-path))))
@@ -5531,7 +5796,7 @@ Use direct async.")
(skip-unless (fboundp 'exec-path))
(let* ((tmp-name (tramp--test-make-temp-name))
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
(orig-exec-path (with-no-warnings (exec-path)))
(tramp-remote-path tramp-remote-path)
(orig-tramp-remote-path tramp-remote-path)
@@ -5598,7 +5863,7 @@ Use direct async.")
;; order to establish the connection prior running an asynchronous
;; process.
(let* ((default-directory
- (file-truename tramp-test-temporary-file-directory))
+ (file-truename ert-remote-temporary-file-directory))
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(tramp-remote-process-environment tramp-remote-process-environment)
@@ -5702,7 +5967,7 @@ Use direct async.")
(if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(format "#%s#" (file-name-nondirectory tmp-name1))
- tramp-test-temporary-file-directory))))))
+ ert-remote-temporary-file-directory))))))
;; Use default `tramp-auto-save-directory' mechanism.
;; Ange-FTP doesn't care.
@@ -5807,7 +6072,7 @@ Use direct async.")
(if quoted #'tramp-compat-file-name-quote #'identity)
(expand-file-name
(format "%s~" (file-name-nondirectory tmp-name1))
- tramp-test-temporary-file-directory)))))))
+ ert-remote-temporary-file-directory)))))))
(unwind-protect
;; Map `backup-directory-alist'.
@@ -5965,7 +6230,9 @@ Use direct async.")
(with-temp-buffer
(set-visited-file-name tmp-name1)
(insert "foo")
- (save-buffer))
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
(should-not (with-no-warnings (file-locked-p tmp-name1)))
(with-no-warnings (lock-file tmp-name1))
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
@@ -6057,12 +6324,88 @@ Use direct async.")
(ignore-errors (delete-file tmp-name1))
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)))))
+;; The functions were introduced in Emacs 28.1.
+(ert-deftest tramp-test39-detect-external-change ()
+ "Check that an external file modification is reported."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+ ;; Since Emacs 28.1.
+ (skip-unless (and (fboundp 'lock-file) (fboundp 'file-locked-p)))
+
+ (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
+ (dolist (create-lockfiles '(nil t))
+ (let ((tmp-name (tramp--test-make-temp-name nil quoted))
+ (remote-file-name-inhibit-cache t)
+ (remote-file-name-inhibit-locks nil)
+ tramp-allow-unsafe-temporary-files
+ (inhibit-message t)
+ ;; tramp-rclone.el and tramp-sshfs.el cache the mounted files.
+ (tramp-fuse-unmount-on-cleanup t)
+ auto-save-default
+ (backup-inhibited t)
+ noninteractive)
+ (with-temp-buffer
+ (unwind-protect
+ (progn
+ (setq buffer-file-name tmp-name
+ buffer-file-truename tmp-name)
+ (insert "foo")
+ ;; Bug#53207: with `create-lockfiles' nil, saving the
+ ;; buffer results in a prompt.
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (_) (ert-fail "Test failed unexpectedly"))))
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
+ (should-not (file-locked-p tmp-name))
+
+ ;; For local files, just changing the file
+ ;; modification on disk doesn't hurt, because file
+ ;; contents in buffer and on disk are equal. For
+ ;; remote files, file contents is not compared. We
+ ;; mock an older modification time in buffer, because
+ ;; Tramp regards modification times equal if they
+ ;; differ for less than 2 seconds.
+ (set-visited-file-modtime (time-add (current-time) -60))
+ ;; Some Tramp methods cannot check the file
+ ;; modification time properly, for them it doesn't
+ ;; make sense to test.
+ (when (not (verify-visited-file-modtime))
+ (cl-letf (((symbol-function 'read-char-choice)
+ (lambda (prompt &rest _) (message "%s" prompt) ?y)))
+ (ert-with-message-capture captured-messages
+ (insert "bar")
+ (when create-lockfiles
+ (should (string-match-p
+ (format
+ "^%s changed on disk; really edit the buffer\\?"
+ (if (tramp--test-crypt-p)
+ ".+" (file-name-nondirectory tmp-name)))
+ captured-messages))
+ (should (file-locked-p tmp-name)))))
+
+ ;; `save-buffer' removes the file lock.
+ (cl-letf (((symbol-function 'yes-or-no-p) #'tramp--test-always)
+ ((symbol-function 'read-char-choice)
+ (lambda (&rest _) ?y)))
+ (should (buffer-modified-p))
+ (save-buffer)
+ (should-not (buffer-modified-p)))
+ (should-not (file-locked-p tmp-name))))
+
+ ;; Cleanup.
+ (set-buffer-modified-p nil)
+ (ignore-errors (delete-file tmp-name))
+ (tramp-cleanup-connection
+ tramp-test-vec 'keep-debug 'keep-password)))))))
+
+;; The functions were introduced in Emacs 26.1.
(ert-deftest tramp-test40-make-nearby-temp-file ()
"Check `make-nearby-temp-file' and `temporary-file-directory'."
(skip-unless (tramp--test-enabled))
(skip-unless (not (tramp--test-ange-ftp-p)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
tmp-file)
;; The remote host shall know a temporary file directory.
(should (stringp (temporary-file-directory)))
@@ -6109,36 +6452,40 @@ variables, so we check the Emacs version directly."
(defun tramp--test-adb-p ()
"Check, whether the remote host runs Android.
This requires restrictions of file name syntax."
- (tramp-adb-file-name-p tramp-test-temporary-file-directory))
+ (tramp-adb-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-ange-ftp-p ()
"Check, whether Ange-FTP is used."
(eq
- (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
+ (tramp-find-foreign-file-name-handler tramp-test-vec)
'tramp-ftp-file-name-handler))
(defun tramp--test-asynchronous-processes-p ()
"Whether asynchronous processes tests are run.
-This is used in tests which we dont't want to tag
+This is used in tests which we don't want to tag
`:tramp-asynchronous-processes' completely."
- (ert-select-tests
- (ert--stats-selector ert--current-run-stats)
- (list (make-ert-test :name (ert-test-name (ert-running-test))
- :body nil :tags '(:tramp-asynchronous-processes)))))
+ (and
+ (ert-select-tests
+ (ert--stats-selector ert--current-run-stats)
+ (list (make-ert-test :name (ert-test-name (ert-running-test))
+ :body nil :tags '(:tramp-asynchronous-processes))))
+ ;; tramp-adb.el cannot apply multi-byte commands.
+ (not (and (tramp--test-adb-p)
+ (string-match-p "[[:multibyte:]]" default-directory)))))
(defun tramp--test-crypt-p ()
"Check, whether the remote directory is crypted."
- (tramp-crypt-file-name-p tramp-test-temporary-file-directory))
+ (tramp-crypt-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-docker-p ()
"Check, whether the docker method is used.
This does not support some special file names."
(string-equal
- "docker" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "docker" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-expensive-test-p ()
"Whether expensive tests are run.
-This is used in tests which we dont't want to tag `:expensive'
+This is used in tests which we don't want to tag `:expensive'
completely."
(ert-select-tests
(ert--stats-selector ert--current-run-stats)
@@ -6150,7 +6497,7 @@ completely."
This does not support globbing characters in file names (yet)."
;; Globbing characters are ??, ?* and ?\[.
(string-match-p
- "ftp$" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "ftp$" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-fuse-p ()
"Check, whether an FUSE file system isused."
@@ -6159,42 +6506,42 @@ This does not support globbing characters in file names (yet)."
(defun tramp--test-gdrive-p ()
"Check, whether the gdrive method is used."
(string-equal
- "gdrive" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "gdrive" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-gvfs-p (&optional method)
"Check, whether the remote host runs a GVFS based method.
This requires restrictions of file name syntax.
If optional METHOD is given, it is checked first."
(or (member method tramp-gvfs-methods)
- (tramp-gvfs-file-name-p tramp-test-temporary-file-directory)))
+ (tramp-gvfs-file-name-p ert-remote-temporary-file-directory)))
(defun tramp--test-hpux-p ()
"Check, whether the remote host runs HP-UX.
Several special characters do not work properly there."
;; We must refill the cache. `file-truename' does it.
- (file-truename tramp-test-temporary-file-directory)
- (tramp-check-remote-uname tramp-test-vec "^HP-UX"))
+ (file-truename ert-remote-temporary-file-directory)
+ (ignore-errors (tramp-check-remote-uname tramp-test-vec "^HP-UX")))
(defun tramp--test-ksh-p ()
"Check, whether the remote shell is ksh.
ksh93 makes some strange conversions of non-latin characters into
a $'' syntax."
;; We must refill the cache. `file-truename' does it.
- (file-truename tramp-test-temporary-file-directory)
+ (file-truename ert-remote-temporary-file-directory)
(string-match-p
"ksh$" (tramp-get-connection-property tramp-test-vec "remote-shell" "")))
(defun tramp--test-macos-p ()
"Check, whether the remote host runs macOS."
;; We must refill the cache. `file-truename' does it.
- (file-truename tramp-test-temporary-file-directory)
- (tramp-check-remote-uname tramp-test-vec "Darwin"))
+ (file-truename ert-remote-temporary-file-directory)
+ (ignore-errors (tramp-check-remote-uname tramp-test-vec "Darwin")))
(defun tramp--test-mock-p ()
"Check, whether the mock method is used.
This does not support external Emacs calls."
(string-equal
- "mock" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "mock" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-out-of-band-p ()
"Check, whether an out-of-band method is used."
@@ -6203,13 +6550,13 @@ This does not support external Emacs calls."
(defun tramp--test-rclone-p ()
"Check, whether the remote host is offered by rclone.
This requires restrictions of file name syntax."
- (tramp-rclone-file-name-p tramp-test-temporary-file-directory))
+ (tramp-rclone-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-rsync-p ()
"Check, whether the rsync method is used.
This does not support special file names."
(string-equal
- "rsync" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "rsync" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-sh-p ()
"Check, whether the remote host runs a based method from tramp-sh.el."
@@ -6223,30 +6570,30 @@ Additionally, ls does not support \"--dired\"."
;; We must refill the cache. `insert-directory' does it.
;; This fails for tramp-crypt.el, so we ignore that.
(ignore-errors
- (insert-directory tramp-test-temporary-file-directory "-al"))
- (not (tramp-get-connection-property tramp-test-vec "ls--dired" nil)))))
+ (insert-directory ert-remote-temporary-file-directory "-al"))
+ (not (tramp-get-connection-property tramp-test-vec "ls--dired")))))
(defun tramp--test-share-p ()
"Check, whether the method needs a share."
(and (tramp--test-gvfs-p)
(string-match-p
"^\\(afp\\|davs?\\|smb\\)$"
- (file-remote-p tramp-test-temporary-file-directory 'method))))
+ (file-remote-p ert-remote-temporary-file-directory 'method))))
(defun tramp--test-sshfs-p ()
"Check, whether the remote host is offered by sshfs.
This requires restrictions of file name syntax."
- (tramp-sshfs-file-name-p tramp-test-temporary-file-directory))
+ (tramp-sshfs-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-sudoedit-p ()
"Check, whether the sudoedit method is used."
- (tramp-sudoedit-file-name-p tramp-test-temporary-file-directory))
+ (tramp-sudoedit-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-telnet-p ()
"Check, whether the telnet method is used.
This does not support special file names."
(string-equal
- "telnet" (file-remote-p tramp-test-temporary-file-directory 'method)))
+ "telnet" (file-remote-p ert-remote-temporary-file-directory 'method)))
(defun tramp--test-windows-nt-p ()
"Check, whether the locale host runs MS Windows."
@@ -6267,7 +6614,7 @@ This requires restrictions of file name syntax."
(defun tramp--test-smb-p ()
"Check, whether the locale or remote host runs MS Windows.
This requires restrictions of file name syntax."
- (tramp-smb-file-name-p tramp-test-temporary-file-directory))
+ (tramp-smb-file-name-p ert-remote-temporary-file-directory))
(defun tramp--test-supports-processes-p ()
"Return whether the method under test supports external processes."
@@ -6283,7 +6630,7 @@ This requires restrictions of file name syntax."
(and
(tramp--test-gvfs-p)
(string-match-p
- "ftp" (file-remote-p tramp-test-temporary-file-directory 'method)))))
+ "ftp" (file-remote-p ert-remote-temporary-file-directory 'method)))))
(defun tramp--test-check-files (&rest files)
"Run a simple but comprehensive test over every file in FILES."
@@ -6294,8 +6641,9 @@ This requires restrictions of file name syntax."
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
- (let* ((tramp-test-temporary-file-directory
- (file-truename tramp-test-temporary-file-directory))
+ (let* ((ert-remote-temporary-file-directory
+ (file-truename ert-remote-temporary-file-directory))
+ (tramp-fuse-remove-hidden-files t)
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name 'local quoted))
(files
@@ -6442,9 +6790,34 @@ This requires restrictions of file name syntax."
(delete-file file3)
(should-not (file-exists-p file3))))
+ ;; Check, that a process runs on a remote
+ ;; `default-directory' with special characters. See
+ ;; Bug#53846.
+ (when (and (tramp--test-expensive-test-p)
+ (tramp--test-supports-processes-p)
+ ;; Prior Emacs 27, `shell-file-name' was
+ ;; hard coded as "/bin/sh" for remote
+ ;; processes in Emacs. That doesn't work
+ ;; for tramp-adb.el. tramp-sshfs.el times
+ ;; out for older Emacsen, reason unknown.
+ (or (and (not (tramp--test-adb-p))
+ (not (tramp--test-sshfs-p)))
+ (tramp--test-emacs27-p)))
+ (let ((default-directory file1))
+ (dolist (this-shell-command
+ (append
+ ;; Synchronously.
+ '(shell-command)
+ ;; Asynchronously.
+ (and (tramp--test-asynchronous-processes-p)
+ '(tramp--test-async-shell-command))))
+ (with-temp-buffer
+ (funcall this-shell-command "cat -- *" (current-buffer))
+ (should (string-equal elt (buffer-string)))))))
+
(delete-file file2)
(should-not (file-exists-p file2))
- (delete-directory file1)
+ (delete-directory file1 'recursive)
(should-not (file-exists-p file1))))
;; Check, that environment variables are set correctly.
@@ -6456,7 +6829,7 @@ This requires restrictions of file name syntax."
(dolist (elt files)
(let ((envvar (concat "VAR_" (upcase (md5 elt))))
(elt (encode-coding-string elt coding-system-for-read))
- (default-directory tramp-test-temporary-file-directory)
+ (default-directory ert-remote-temporary-file-directory)
(process-environment process-environment))
(setenv envvar elt)
;; The value of PS1 could confuse Tramp's detection
@@ -6511,7 +6884,7 @@ This requires restrictions of file name syntax."
(unless (or (tramp--test-ftp-p)
(tramp--test-gvfs-p)
(tramp--test-windows-nt-or-smb-p))
- "*foo*bar*baz*")
+ "*foo+bar*baz+")
(if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
"'foo'bar'baz'"
"'foo\"bar'baz\"")
@@ -6554,12 +6927,12 @@ Use the \"stat\" command."
(skip-unless (tramp--test-sh-p))
(skip-unless (not (tramp--test-rsync-p)))
;; We cannot use `tramp-test-vec', because this fails during compilation.
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
+ (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil
(skip-unless (tramp-get-remote-stat v)))
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"perl" nil))
tramp-connection-properties)))
(tramp--test-special-characters)))
@@ -6573,15 +6946,15 @@ Use the \"perl\" command."
(skip-unless (tramp--test-sh-p))
(skip-unless (not (tramp--test-rsync-p)))
;; We cannot use `tramp-test-vec', because this fails during compilation.
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
+ (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil
(skip-unless (tramp-get-remote-perl v)))
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"stat" nil)
;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"readlink" nil))
tramp-connection-properties)))
(tramp--test-special-characters)))
@@ -6597,12 +6970,12 @@ Use the \"ls\" command."
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"perl" nil)
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"stat" nil)
;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"readlink" nil))
tramp-connection-properties)))
(tramp--test-special-characters)))
@@ -6681,12 +7054,12 @@ Use the \"stat\" command."
(skip-unless (not (tramp--test-ksh-p)))
(skip-unless (not (tramp--test-crypt-p)))
;; We cannot use `tramp-test-vec', because this fails during compilation.
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
+ (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil
(skip-unless (tramp-get-remote-stat v)))
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"perl" nil))
tramp-connection-properties)))
(tramp--test-utf8)))
@@ -6704,15 +7077,15 @@ Use the \"perl\" command."
(skip-unless (not (tramp--test-ksh-p)))
(skip-unless (not (tramp--test-crypt-p)))
;; We cannot use `tramp-test-vec', because this fails during compilation.
- (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
+ (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil
(skip-unless (tramp-get-remote-perl v)))
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"stat" nil)
;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"readlink" nil))
tramp-connection-properties)))
(tramp--test-utf8)))
@@ -6732,12 +7105,12 @@ Use the \"ls\" command."
(let ((tramp-connection-properties
(append
- `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"perl" nil)
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"stat" nil)
;; See `tramp-sh-handle-file-truename'.
- (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
+ (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory))
"readlink" nil))
tramp-connection-properties)))
(tramp--test-utf8)))
@@ -6750,14 +7123,12 @@ Use the \"ls\" command."
;; `file-system-info' exists since Emacs 27.1. We don't want to see
;; compiler warnings for older Emacsen.
- (let ((fsi (with-no-warnings
- (file-system-info tramp-test-temporary-file-directory))))
- (skip-unless fsi)
- (should (and (consp fsi)
- (= (length fsi) 3)
- (numberp (nth 0 fsi))
- (numberp (nth 1 fsi))
- (numberp (nth 2 fsi))))))
+ (when-let ((fsi (with-no-warnings
+ (file-system-info ert-remote-temporary-file-directory))))
+ (should (consp fsi))
+ (should (= (length fsi) 3))
+ (dotimes (i (length fsi))
+ (should (natnump (or (nth i fsi) 0))))))
;; `tramp-test44-asynchronous-requests' could be blocked. So we set a
;; timeout of 300 seconds, and we send a SIGUSR1 signal after 300
@@ -6771,13 +7142,13 @@ The values are derived from PROC. Run BODY.
This is needed in timer functions as well as process filters and sentinels."
;; FIXME: For tramp-sshfs.el, `processp' does not work.
(declare (indent 1) (debug (processp body)))
- `(let* ((v (tramp-get-connection-property ,proc "vector" nil))
- (pname (tramp-get-connection-property v "process-name" nil))
- (pbuffer (tramp-get-connection-property v "process-buffer" nil)))
+ `(let* ((v (tramp-get-connection-property ,proc "vector"))
+ (pname (tramp-get-connection-property v "process-name"))
+ (pbuffer (tramp-get-connection-property v "process-buffer")))
(tramp--test-message
"tramp--test-with-proper-process-name-and-buffer before %s %s"
- (tramp-get-connection-property v "process-name" nil)
- (tramp-get-connection-property v "process-buffer" nil))
+ (tramp-get-connection-property v "process-name")
+ (tramp-get-connection-property v "process-buffer"))
(if (process-name ,proc)
(tramp-set-connection-property v "process-name" (process-name ,proc))
(tramp-flush-connection-property v "process-name"))
@@ -6787,8 +7158,8 @@ This is needed in timer functions as well as process filters and sentinels."
(tramp-flush-connection-property v "process-buffer"))
(tramp--test-message
"tramp--test-with-proper-process-name-and-buffer changed %s %s"
- (tramp-get-connection-property v "process-name" nil)
- (tramp-get-connection-property v "process-buffer" nil))
+ (tramp-get-connection-property v "process-name")
+ (tramp-get-connection-property v "process-buffer"))
(unwind-protect
(progn ,@body)
(if pname
@@ -6804,7 +7175,9 @@ This is needed in timer functions as well as process filters and sentinels."
Such requests could arrive from timers, process filters and
process sentinels. They shall not disturb each other."
:tags (append '(:expensive-test :tramp-asynchronous-processes)
- (and (getenv "EMACS_HYDRA_CI") '(:unstable)))
+ (and (or (getenv "EMACS_HYDRA_CI")
+ (getenv "EMACS_EMBA_CI"))
+ '(:unstable)))
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-supports-processes-p))
;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for
@@ -7006,7 +7379,7 @@ process sentinels. They shall not disturb each other."
;; default handler.
(skip-unless (not (tramp--test-emacs29-p)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name)))
(write-region "foo" nil tmp-name)
(dired default-directory)
@@ -7027,7 +7400,7 @@ process sentinels. They shall not disturb each other."
;; default handler.
(skip-unless (not (tramp--test-emacs29-p)))
- (let ((default-directory tramp-test-temporary-file-directory)
+ (let ((default-directory ert-remote-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name)))
(make-directory tmp-name)
(dired default-directory)
@@ -7040,8 +7413,67 @@ process sentinels. They shall not disturb each other."
(delete-directory tmp-name)
(delete-file (concat tmp-name ".tar.gz"))))
+(ert-deftest tramp-test46-read-password ()
+ "Check Tramp password handling."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-mock-p))
+ ;; Not all read commands understand argument "-s" or "-p".
+ (skip-unless
+ (string-empty-p
+ (let ((shell-file-name "sh"))
+ (shell-command-to-string "read -s -p Password: pass"))))
+
+ (let ((pass "secret")
+ (mock-entry (copy-sequence (assoc "mock" tramp-methods)))
+ mocked-input tramp-methods)
+ ;; We must mock `read-string', in order to avoid interactive
+ ;; arguments.
+ (cl-letf* (((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+ (setcdr
+ (assq 'tramp-login-args mock-entry)
+ `((("-c")
+ (,(tramp-shell-quote-argument
+ (concat
+ "read -s -p 'Password: ' pass; echo; "
+ "(test \"pass$pass\" != \"pass" pass "\" && "
+ "echo \"Login incorrect\" || sh -i)"))))))
+ (setq tramp-methods `(,mock-entry))
+
+ ;; Reading password from stdin works.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ ;; We don't want to invalidate the password.
+ (setq mocked-input `(,(copy-sequence pass)))
+ (should (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; Don't entering a password returns in error.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; A wrong password doesn't work either.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input `(,(concat pass pass)))
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; Reading password from auth-source works. We use the netrc
+ ;; backend; the other backends shall behave similar.
+ ;; Macro `ert-with-temp-file' was introduced in Emacs 29.1.
+ (with-no-warnings (when (symbol-plist 'ert-with-temp-file)
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (auth-source-forget-all-cached)
+ (ert-with-temp-file netrc-file
+ :prefix "tramp-test" :suffix ""
+ :text (format
+ "machine %s port mock password %s"
+ (file-remote-p ert-remote-temporary-file-directory 'host) pass)
+ (let ((auth-sources `(,netrc-file)))
+ (should (file-exists-p ert-remote-temporary-file-directory)))))))))
+
;; This test is inspired by Bug#29163.
-(ert-deftest tramp-test46-auto-load ()
+(ert-deftest tramp-test47-auto-load ()
"Check that Tramp autoloads properly."
;; If we use another syntax but `default', Tramp is already loaded
;; due to the `tramp-change-syntax' call.
@@ -7054,7 +7486,7 @@ process sentinels. They shall not disturb each other."
;; Suppress method name check.
"(let ((non-essential t)) \
(message \"Tramp loaded: %%s\" (and (file-remote-p %S) t)))"
- tramp-test-temporary-file-directory)))
+ ert-remote-temporary-file-directory)))
(should
(string-match-p
"Tramp loaded: t[\n\r]+"
@@ -7066,7 +7498,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
-(ert-deftest tramp-test46-delay-load ()
+(ert-deftest tramp-test47-delay-load ()
"Check that Tramp is loaded lazily, only when needed."
;; Tramp is neither loaded at Emacs startup, nor when completing a
;; non-Tramp file name like "/foo". Completing a Tramp-alike file
@@ -7095,7 +7527,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument (format code tm)))))))))
-(ert-deftest tramp-test46-recursive-load ()
+(ert-deftest tramp-test47-recursive-load ()
"Check that Tramp does not fail due to recursive load."
(skip-unless (tramp--test-enabled))
@@ -7103,10 +7535,10 @@ process sentinels. They shall not disturb each other."
(dolist (code
(list
(format
- "(expand-file-name %S)" tramp-test-temporary-file-directory)
+ "(expand-file-name %S)" ert-remote-temporary-file-directory)
(format
"(let ((default-directory %S)) (expand-file-name %S))"
- tramp-test-temporary-file-directory
+ ert-remote-temporary-file-directory
temporary-file-directory)))
(should-not
(string-match-p
@@ -7119,7 +7551,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code))))))))
-(ert-deftest tramp-test46-remote-load-path ()
+(ert-deftest tramp-test47-remote-load-path ()
"Check that Tramp autoloads its packages with remote `load-path'."
;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el.
;; It shall still work, when a remote file name is in the
@@ -7144,11 +7576,10 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
-(ert-deftest tramp-test47-unload ()
+(ert-deftest tramp-test48-unload ()
"Check that Tramp and its subpackages unload completely.
Since it unloads Tramp, it shall be the last test to run."
:tags '(:expensive-test)
- (skip-unless noninteractive)
;; We have autoloaded objects from tramp.el and tramp-archive.el.
;; In order to remove them, we first need to load both packages.
(require 'tramp)
@@ -7157,28 +7588,34 @@ Since it unloads Tramp, it shall be the last test to run."
(should (featurep 'tramp-archive))
;; This unloads also tramp-archive.el and tramp-theme.el if needed.
(unload-feature 'tramp 'force)
- ;; No Tramp feature must be left.
+
+ ;; No Tramp feature must be left except the test packages.
(should-not (featurep 'tramp))
(should-not (featurep 'tramp-archive))
(should-not (featurep 'tramp-theme))
(should-not
(all-completions
"tramp" (delq 'tramp-tests (delq 'tramp-archive-tests features))))
+
;; `file-name-handler-alist' must be clean.
(should-not (all-completions "tramp" (mapcar #'cdr file-name-handler-alist)))
+
;; There shouldn't be left a bound symbol, except buffer-local
- ;; variables, and autoload functions. We do not regard our test
+ ;; variables, and autoloaded functions. We do not regard our test
;; symbols, and the Tramp unload hooks.
(mapatoms
(lambda (x)
(and (or (and (boundp x) (null (local-variable-if-set-p x)))
- (and (functionp x) (null (autoloadp (symbol-function x)))))
+ (and (functionp x) (null (autoloadp (symbol-function x))))
+ (macrop x))
(string-match-p "^tramp" (symbol-name x))
;; `tramp-completion-mode' is autoloaded in Emacs < 28.1.
(not (eq 'tramp-completion-mode x))
(not (string-match-p "^tramp\\(-archive\\)?--?test" (symbol-name x)))
(not (string-match-p "unload-hook$" (symbol-name x)))
+ (not (get x 'tramp-autoload))
(ert-fail (format "`%s' still bound" x)))))
+
;; The defstruct `tramp-file-name' and all its internal functions
;; shall be purged.
(should-not (cl--find-class 'tramp-file-name))
@@ -7187,6 +7624,7 @@ Since it unloads Tramp, it shall be the last test to run."
(and (functionp x)
(string-match-p "tramp-file-name" (symbol-name x))
(ert-fail (format "Structure function `%s' still exists" x)))))
+
;; There shouldn't be left a hook function containing a Tramp
;; function. We do not regard the Tramp unload hooks.
(mapatoms
@@ -7196,7 +7634,24 @@ Since it unloads Tramp, it shall be the last test to run."
(not (string-match-p "unload-hook$" (symbol-name x)))
(consp (symbol-value x))
(ignore-errors (all-completions "tramp" (symbol-value x)))
- (ert-fail (format "Hook `%s' still contains Tramp function" x))))))
+ (ert-fail (format "Hook `%s' still contains Tramp function" x)))))
+
+ ;; There shouldn't be left an advice function from Tramp.
+ (mapatoms
+ (lambda (x)
+ (and (functionp x)
+ (advice-mapc
+ (lambda (fun _symbol)
+ (and (string-match-p "^tramp" (symbol-name fun))
+ (ert-fail
+ (format "Function `%s' still contains Tramp advice" x))))
+ x))))
+
+ ;; Reload.
+ (require 'tramp)
+ (require 'tramp-archive)
+ (should (featurep 'tramp))
+ (should (featurep 'tramp-archive)))
(defun tramp-test-all (&optional interactive)
"Run all tests for \\[tramp].
@@ -7219,8 +7674,9 @@ If INTERACTIVE is non-nil, the tests are run interactively."
;; * Work on skipped tests. Make a comment, when it is impossible.
;; * Revisit expensive tests, once problems in `tramp-error' are solved.
;; * Fix `tramp-test06-directory-file-name' for "ftp".
-;; * Implement `tramp-test31-interrupt-process' for "adb", "sshfs" and
-;; for direct async processes.
+;; * Implement `tramp-test31-interrupt-process' and
+;; `tramp-test31-signal-process' for "adb", "sshfs" and for direct
+;; async processes. Check, why they don't run stable.
;; * Check, why direct async processes do not work for
;; `tramp-test44-asynchronous-requests'.
diff --git a/test/lisp/obsolete/inversion-tests.el b/test/lisp/obsolete/inversion-tests.el
index 7c8815c2822..8af91d7d147 100644
--- a/test/lisp/obsolete/inversion-tests.el
+++ b/test/lisp/obsolete/inversion-tests.el
@@ -30,7 +30,6 @@
(ert-deftest inversion-unit-test ()
"Test inversion to make sure it can identify different version strings."
- (interactive)
(let ((c1 (inversion-package-version 'inversion))
(c1i (inversion-package-incompatibility-version 'inversion))
(c2 (inversion-decode-version "1.3alpha2"))
diff --git a/test/lisp/progmodes/autoconf-tests.el b/test/lisp/progmodes/autoconf-tests.el
index e383b4bb6c4..7c609f3c2a7 100644
--- a/test/lisp/progmodes/autoconf-tests.el
+++ b/test/lisp/progmodes/autoconf-tests.el
@@ -31,18 +31,18 @@
(ert-deftest autoconf-tests-current-defun-function-define ()
(with-temp-buffer
- (insert "AC_DEFINE(HAVE_RSVG, 1, [Define to 1 if using librsvg.])")
+ (insert "AC_DEFINE([HAVE_RSVG], [1], [Define to 1 if using librsvg.])")
(goto-char (point-min))
(should-not (autoconf-current-defun-function))
- (forward-char 10)
+ (forward-char 11)
(should (equal (autoconf-current-defun-function) "HAVE_RSVG"))))
(ert-deftest autoconf-tests-current-defun-function-subst ()
(with-temp-buffer
- (insert "AC_SUBST(srcdir)")
+ (insert "AC_SUBST([srcdir])")
(goto-char (point-min))
(should-not (autoconf-current-defun-function))
- (forward-char 9)
+ (forward-char 10)
(should (equal (autoconf-current-defun-function) "srcdir"))))
(ert-deftest autoconf-tests-autoconf-mode-comment-syntax ()
diff --git a/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
new file mode 100644
index 00000000000..7138bf631df
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/proto-and-attrs.pl
@@ -0,0 +1,50 @@
+# The next two lines are required as of 2022, but obsolescent
+# as soon as signatures leave their "experimental" state
+use feature 'signatures';
+no warnings 'experimental::signatures';
+
+# Tests for subroutine prototypes, signatures and the like
+
+# Prototypes have syntactical properties different from "normal" Perl:
+# Perl has a variable $), so ($)) is not an unbalanced parenthesis.
+# On the other hand, in a prototype ($) is _not_ an open paren
+# followed by the variable $), so the parens are balanced. Prototypes
+# are somewhat frowned upon most of the times, but they are required
+# for some Perl magic
+
+# FIXME: 2022-02-02 CPerl mode does not handle subroutine signatures.
+# In simple cases it mistakes them as prototypes, when attributes are
+# present, it doesn't handle them at all. Variables in signatures
+# SHOULD be fontified like variable declarations.
+
+# Part 1: Named subroutines
+# A prototype and a trivial subroutine attribute
+{
+ no feature 'signatures'; # that's a prototype, not a signature
+ sub sub_1 ($) :lvalue { local $); }
+}
+
+# A prototype as an attribute (how it should be written these days)
+sub sub_2 :prototype($) { ...; }
+
+# A signature (these will soon-ish leave the experimental state)
+sub sub_3 ($foo,$bar) { ...; }
+
+# Attribute plus signature FIXME: Not yet supported
+sub bad_sub_4 :prototype($$$) ($foo,$bar,$baz) { ...; }
+
+# Part 2: Same constructs for anonymous subs
+# A prototype and a trivial subroutine attribute
+{
+ no feature 'signatures'; # that's a prototype, not a signature
+ my $subref_1 = sub ($) :lvalue { local $); };
+}
+
+# A prototype as an attribute (how it should be written these days)
+my $subref_2 = sub :prototype($) { ...; };
+
+# A signature (these will soon-ish leave the experimental state)
+my $subref_3 = sub ($foo,$bar) { ...; };
+
+# Attribute plus signature
+my $subref_4 = sub :prototype($$$) ($foo,$bar,$baz) { ...; };
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index 0124dad6f17..7eb2d9be756 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -5,7 +5,7 @@
;; Author: Harald Jörg <haj@posteo.de>
;; Maintainer: Harald Jörg
;; Keywords: internal
-;; Homepage: https://github.com/HaraldJoerg/cperl-mode
+;; URL: https://github.com/HaraldJoerg/cperl-mode
;; This file is part of GNU Emacs.
@@ -64,7 +64,7 @@ The expected output from running BODY on the input goes here.
# -------- NAME: end --------
You can have many of these blocks in one test file. You can
-chose a NAME for each block, which is passed to the 'should'
+chose a NAME for each block, which is passed to the `should'
clause for easy identification of the first test case that
failed (if any). Text outside these the blocks is ignored by the
tests, so you can use it to document the test cases if you wish."
@@ -154,6 +154,55 @@ point in the distant past, and is still broken in perl-mode. "
(should (equal (get-text-property (match-beginning 0) 'face)
'font-lock-keyword-face))))
+(ert-deftest cperl-test-fontify-attrs-and-signatures ()
+ "Test fontification of the various combinations of subroutine
+attributes, prototypes and signatures."
+ (skip-unless (eq cperl-test-mode #'cperl-mode))
+ (let ((file (ert-resource-file "proto-and-attrs.pl")))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+
+ ;; Named subroutines
+ (while (search-forward-regexp "\\_<sub_[[:digit:]]+" nil t)
+ (should (equal (get-text-property (match-beginning 0) 'face)
+ 'font-lock-function-name-face))
+ (let ((start-of-sub (match-beginning 0))
+ (end-of-sub (save-excursion (search-forward "}") (point))))
+
+ ;; Prototypes are shown as strings
+ (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+ (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+ 'font-lock-string-face)))
+ (goto-char start-of-sub)
+ (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
+ (should (equal (get-text-property (match-beginning 1) 'face)
+ 'font-lock-constant-face))
+ (when (match-beginning 2)
+ (should (equal (get-text-property (match-beginning 2) 'face)
+ 'font-lock-string-face))))
+ (goto-char end-of-sub)))
+
+ ;; Anonymous subroutines
+ (while (search-forward-regexp "= sub" nil t)
+ (let ((start-of-sub (match-beginning 0))
+ (end-of-sub (save-excursion (search-forward "}") (point))))
+
+ ;; Prototypes are shown as strings
+ (when (search-forward-regexp " ([$%@*]*) " end-of-sub t)
+ (should (equal (get-text-property (1+ (match-beginning 0)) 'face)
+ 'font-lock-string-face)))
+ (goto-char start-of-sub)
+ (when (search-forward-regexp "\\(:[a-z]+\\)\\((.*?)\\)?" end-of-sub t)
+ (should (equal (get-text-property (match-beginning 1) 'face)
+ 'font-lock-constant-face))
+ (when (match-beginning 2)
+ (should (equal (get-text-property (match-beginning 2) 'face)
+ 'font-lock-string-face))))
+ (goto-char end-of-sub))))))
+
(ert-deftest cperl-test-fontify-special-variables ()
"Test fontification of variables like $^T or ${^ENCODING}.
These can occur as \"local\" aliases."
@@ -698,7 +747,6 @@ without a statement terminator on the same line does not loop
forever. The test starts an asynchronous Emacs batch process
under timeout control."
:tags '(:expensive-test)
- (interactive)
(skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; FIXME times out
(skip-unless (not (< emacs-major-version 28))) ; times out in older Emacsen
(skip-unless (eq cperl-test-mode #'cperl-mode))
diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el
index ced7b5aaced..71b03b21e5c 100644
--- a/test/lisp/progmodes/flymake-tests.el
+++ b/test/lisp/progmodes/flymake-tests.el
@@ -140,15 +140,10 @@ SEVERITY-PREDICATE is used to setup
(flymake-goto-next-error)
(should (eq 'flymake-error (face-at-point)))))))
-(defun flymake-tests--gcc-is-clang ()
- "Whether the `gcc' command actually runs the Clang compiler."
- (string-match "[Cc]lang version "
- (shell-command-to-string "gcc --version")))
-
(ert-deftest different-diagnostic-types ()
"Test GCC warning via function predicate."
(skip-unless (and (executable-find "gcc")
- (not (flymake-tests--gcc-is-clang))
+ (not (ert-gcc-is-clang-p))
(version<=
"5" (string-trim
(shell-command-to-string "gcc -dumpversion")))
@@ -173,7 +168,7 @@ SEVERITY-PREDICATE is used to setup
(ert-deftest included-c-header-files ()
"Test inclusion of .h header files."
(skip-unless (and (executable-find "gcc")
- (not (flymake-tests--gcc-is-clang))
+ (not (ert-gcc-is-clang-p))
(executable-find "make")))
(let ((flymake-wrap-around nil))
(flymake-tests--with-flymake
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index 0eb1c087f4c..d7b3c102f2d 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -95,6 +95,19 @@ STRING, it is skipped so the next STRING occurrence is selected."
found-point
(and restore-point (goto-char starting-point)))))
+(defun python-tests-assert-faces (content faces)
+ "Assert that font faces for CONTENT are equal to FACES."
+ (python-tests-with-temp-buffer content
+ (font-lock-ensure nil nil)
+ (should (equal faces (python-tests-get-buffer-faces)))))
+
+(defun python-tests-get-buffer-faces ()
+ "Return a list of (position . face) for each face change positions."
+ (cl-loop for pos = (point-min)
+ then (next-single-property-change pos 'face)
+ while pos
+ collect (cons pos (get-text-property pos 'face))))
+
(defun python-tests-self-insert (char-or-str)
"Call `self-insert-command' for chars in CHAR-OR-STR."
(let ((chars
@@ -201,6 +214,172 @@ aliqua."
(should (string= (buffer-string) "\"\""))
(should (null (nth 3 (syntax-ppss))))))
+(ert-deftest python-font-lock-keywords-level-1-1 ()
+ (python-tests-assert-faces
+ "def func():"
+ '((1 . font-lock-keyword-face) (4)
+ (5 . font-lock-function-name-face) (9))))
+
+(ert-deftest python-font-lock-keywords-level-1-2 ()
+ "Invalid function name should not be font-locked."
+ (python-tests-assert-faces
+ "def 1func():"
+ '((1 . font-lock-keyword-face) (4))))
+
+(ert-deftest python-font-lock-assignment-statement-1 ()
+ (python-tests-assert-faces
+ "a, b, c = 1, 2, 3"
+ '((1 . font-lock-variable-name-face) (2)
+ (4 . font-lock-variable-name-face) (5)
+ (7 . font-lock-variable-name-face) (8))))
+
+(ert-deftest python-font-lock-assignment-statement-2 ()
+ (python-tests-assert-faces
+ "a, *b, c = 1, 2, 3, 4, 5"
+ '((1 . font-lock-variable-name-face) (2)
+ (5 . font-lock-variable-name-face) (6)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-3 ()
+ (python-tests-assert-faces
+ "[a, b] = (1, 2)"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (5 . font-lock-variable-name-face) (6))))
+
+(ert-deftest python-font-lock-assignment-statement-4 ()
+ (python-tests-assert-faces
+ "(l[1], l[2]) = (10, 11)"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-5 ()
+ (python-tests-assert-faces
+ "(a, b, c, *d) = *x, y = 5, 6, 7, 8, 9"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (5 . font-lock-variable-name-face) (6)
+ (8 . font-lock-variable-name-face) (9)
+ (12 . font-lock-variable-name-face) (13)
+ (18 . font-lock-variable-name-face) (19)
+ (21 . font-lock-variable-name-face) (22))))
+
+(ert-deftest python-font-lock-assignment-statement-6 ()
+ (python-tests-assert-faces
+ "(a,) = 'foo',"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-string-face) (13))))
+
+(ert-deftest python-font-lock-assignment-statement-7 ()
+ (python-tests-assert-faces
+ "(*a,) = ['foo', 'bar', 'baz']"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (10 . font-lock-string-face) (15)
+ (17 . font-lock-string-face) (22)
+ (24 . font-lock-string-face) (29))))
+
+(ert-deftest python-font-lock-assignment-statement-8 ()
+ (python-tests-assert-faces
+ "d = D('a', ['b'], 'c')"
+ '((1 . font-lock-variable-name-face) (2)
+ (7 . font-lock-string-face) (10)
+ (13 . font-lock-string-face) (16)
+ (19 . font-lock-string-face) (22))))
+
+(ert-deftest python-font-lock-assignment-statement-9 ()
+ (python-tests-assert-faces
+ "d.x, d.y[0], *d.z = 'a', 'b', 'c', 'd', 'e'"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (8 . font-lock-variable-name-face) (9)
+ (17 . font-lock-variable-name-face) (18)
+ (21 . font-lock-string-face) (24)
+ (26 . font-lock-string-face) (29)
+ (31 . font-lock-string-face) (34)
+ (36 . font-lock-string-face) (39)
+ (41 . font-lock-string-face))))
+
+(ert-deftest python-font-lock-assignment-statement-10 ()
+ (python-tests-assert-faces
+ "a: int = 5"
+ '((1 . font-lock-variable-name-face) (2)
+ (4 . font-lock-builtin-face) (7))))
+
+(ert-deftest python-font-lock-assignment-statement-11 ()
+ (python-tests-assert-faces
+ "b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo')"
+ '((1 . font-lock-variable-name-face) (2)
+ (19 . font-lock-builtin-face) (22)
+ (40 . font-lock-builtin-face) (43)
+ (46 . font-lock-builtin-face) (49)
+ (55 . font-lock-constant-face) (59)
+ (61 . font-lock-string-face) (66))))
+
+(ert-deftest python-font-lock-assignment-statement-12 ()
+ (python-tests-assert-faces
+ "c: Collection = {1, 2, 3}"
+ '((1 . font-lock-variable-name-face) (2))))
+
+(ert-deftest python-font-lock-assignment-statement-13 ()
+ (python-tests-assert-faces
+ "d: Mapping[int, str] = {1: 'bar', 2: 'baz'}"
+ '((1 . font-lock-variable-name-face) (2)
+ (12 . font-lock-builtin-face) (15)
+ (17 . font-lock-builtin-face) (20)
+ (28 . font-lock-string-face) (33)
+ (38 . font-lock-string-face) (43))))
+
+(ert-deftest python-font-lock-assignment-statement-14 ()
+ (python-tests-assert-faces
+ "(a) = 5; (b) = 6"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (11 . font-lock-variable-name-face) (12))))
+
+(ert-deftest python-font-lock-assignment-statement-15 ()
+ (python-tests-assert-faces
+ "[a] = 5,; [b] = 6,"
+ '((1)
+ (2 . font-lock-variable-name-face) (3)
+ (12 . font-lock-variable-name-face) (13))))
+
+(ert-deftest python-font-lock-assignment-statement-16 ()
+ (python-tests-assert-faces
+ "[*a] = 5, 6; [*b] = 7, 8"
+ '((1)
+ (3 . font-lock-variable-name-face) (4)
+ (16 . font-lock-variable-name-face) (17))))
+
+(ert-deftest python-font-lock-assignment-statement-17 ()
+ (python-tests-assert-faces
+ "(a) = (b) = 1"
+ `((1)
+ (2 . font-lock-variable-name-face) (3)
+ (8 . font-lock-variable-name-face) (9))))
+
+(ert-deftest python-font-lock-assignment-statement-18 ()
+ (python-tests-assert-faces
+ "CustomInt = int
+
+def f(x: CustomInt) -> CustomInt:
+ y = x + 1
+ ys: Sequence[CustomInt] = [y, y + 1]
+ res: CustomInt = sum(ys) + 1
+ return res
+"
+ '((1 . font-lock-variable-name-face) (10)
+ (13 . font-lock-builtin-face) (16)
+ (18 . font-lock-keyword-face) (21)
+ (22 . font-lock-function-name-face) (23)
+ (56 . font-lock-variable-name-face) (57)
+ (70 . font-lock-variable-name-face) (72)
+ (111 . font-lock-variable-name-face) (114)
+ (128 . font-lock-builtin-face) (131)
+ (144 . font-lock-keyword-face) (150))))
+
;;; Indentation
@@ -1349,6 +1528,31 @@ this is an arbitrarily
(should (string= (buffer-substring-no-properties (point-min) (point-max))
expected)))))
+(ert-deftest python-indent-after-match-block ()
+ "Test PEP634 match."
+ (python-tests-with-temp-buffer
+ "
+match foo:
+"
+ (should (eq (car (python-indent-context)) :no-indent))
+ (should (= (python-indent-calculate-indentation) 0))
+ (goto-char (point-max))
+ (should (eq (car (python-indent-context)) :after-block-start))
+ (should (= (python-indent-calculate-indentation) 4))))
+
+(ert-deftest python-indent-after-case-block ()
+ "Test PEP634 case."
+ (python-tests-with-temp-buffer
+ "
+match foo:
+ case 1:
+"
+ (should (eq (car (python-indent-context)) :no-indent))
+ (should (= (python-indent-calculate-indentation) 0))
+ (goto-char (point-max))
+ (should (eq (car (python-indent-context)) :after-block-start))
+ (should (= (python-indent-calculate-indentation) 8))))
+
;;; Filling
@@ -1532,6 +1736,57 @@ class C:
(should (= (marker-position (mark-marker))
expected-mark-end-position)))))
+(ert-deftest python-mark-defun-4 ()
+ "Test `python-mark-defun' with nested functions."
+ (python-tests-with-temp-buffer
+ "
+def foo(x):
+ def bar():
+ return x
+ if True:
+ return bar
+"
+ (let ((expected-mark-beginning-position
+ (progn
+ (python-tests-look-at "def foo(x):")
+ (1- (line-beginning-position))))
+ (expected-mark-end-position (point-max)))
+ (python-tests-look-at "return bar")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position)))))
+
+(ert-deftest python-mark-defun-5 ()
+ "Test `python-mark-defun' with point inside backslash escaped defun."
+ (python-tests-with-temp-buffer
+ "
+def \\
+ foo(x):
+ return x
+"
+ (let ((transient-mark-mode t)
+ (expected-mark-beginning-position
+ (progn
+ (python-tests-look-at "def ")
+ (1- (line-beginning-position))))
+ (expected-mark-end-position
+ (save-excursion
+ (python-tests-look-at "return x")
+ (forward-line)
+ (point))))
+ (python-tests-look-at "def ")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position))
+ (deactivate-mark)
+ (python-tests-look-at "foo(x)")
+ (python-mark-defun 1)
+ (should (= (point) expected-mark-beginning-position))
+ (should (= (marker-position (mark-marker))
+ expected-mark-end-position)))))
+
;;; Navigation
@@ -1558,12 +1813,20 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
return wrapped_f
return wwrap
"
- (python-tests-look-at "return wrap")
+ (python-tests-look-at "return wwrap")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def decoratorFunctionWithArguments" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "return wrap" -1)
(should (= (save-excursion
(python-nav-beginning-of-defun)
(point))
(save-excursion
- (python-tests-look-at "def wrapped_f(*args):" -1)
+ (python-tests-look-at "def wwrap(f):" -1)
(beginning-of-line)
(point))))
(python-tests-look-at "def wrapped_f(*args):" -1)
@@ -1597,6 +1860,9 @@ class C(object):
def a():
pass
+ if True:
+ return a
+
def c(self):
pass
"
@@ -1609,6 +1875,15 @@ class C(object):
(python-tests-look-at "def m(self):" -1)
(beginning-of-line)
(point))))
+ ;; Nested defuns shuld be skipped.
+ (python-tests-look-at "return a" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def m(self):" -1)
+ (beginning-of-line)
+ (point))))
;; Defuns on same levels should be respected.
(python-tests-look-at "def a():" -1)
(should (= (save-excursion
@@ -1657,6 +1932,52 @@ class C(object):
(beginning-of-line)
(point))))))
+(ert-deftest python-nav-beginning-of-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def a():
+ pass
+
+def \\
+ b():
+ return 0
+
+def c():
+ pass
+"
+ (python-tests-look-at "def c():")
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "return 0" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "b():" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\" -1)
+ (beginning-of-line)
+ (point))))
+ (python-tests-look-at "def a():" -1)
+ (should (= (save-excursion
+ (python-nav-beginning-of-defun -1)
+ (point))
+ (save-excursion
+ (python-tests-look-at "def \\")
+ (beginning-of-line)
+ (point))))))
+
(ert-deftest python-nav-end-of-defun-1 ()
(python-tests-with-temp-buffer
"
@@ -1760,6 +2081,20 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(python-tests-look-at "return wrapped_f")
(line-beginning-position))))))
+(ert-deftest python-nav-end-of-defun-3 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (should (= (save-excursion
+ (python-tests-look-at "def \\")
+ (python-nav-end-of-defun)
+ (point))
+ (save-excursion
+ (point-max))))))
+
(ert-deftest python-nav-backward-defun-1 ()
(python-tests-with-temp-buffer
"
@@ -1858,6 +2193,18 @@ class A(object):
(should (not (python-nav-backward-defun)))
(should (= point (point))))))
+(ert-deftest python-nav-backward-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (goto-char (point-max))
+ (should (= (save-excursion (python-nav-backward-defun))
+ (python-tests-look-at "def \\" -1)))
+ (should (not (python-nav-backward-defun)))))
+
(ert-deftest python-nav-forward-defun-1 ()
(python-tests-with-temp-buffer
"
@@ -1956,6 +2303,18 @@ class A(object):
(should (not (python-nav-forward-defun)))
(should (= point (point))))))
+(ert-deftest python-nav-forward-defun-4 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ a():
+ return 0
+"
+ (goto-char (point-min))
+ (should (= (save-excursion (python-nav-forward-defun))
+ (python-tests-look-at "():")))
+ (should (not (python-nav-forward-defun)))))
+
(ert-deftest python-nav-beginning-of-statement-1 ()
(python-tests-with-temp-buffer
"
@@ -2266,6 +2625,18 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(python-tests-look-at "print 'After f(*args)'")
(line-end-position))))))
+(ert-deftest python-nav-end-of-block-2 ()
+ "Ensure that `python-nav-end-of-block' does not enter an infinite loop."
+ (python-tests-with-temp-buffer
+ "def
+ =''
+ '
+\"\"\"\"\"\"
+ #
+''
+"
+ (python-nav-end-of-block)))
+
(ert-deftest python-nav-forward-block-1 ()
"This also accounts as a test for `python-nav-backward-block'."
(python-tests-with-temp-buffer
@@ -2634,58 +3005,59 @@ if x:
"Test `python-shell-process-environment' modification."
(let* ((python-shell-process-environment
'("TESTVAR1=value1" "TESTVAR2=value2"))
- (process-environment (python-shell-calculate-process-environment)))
- (should (equal (getenv "TESTVAR1") "value1"))
- (should (equal (getenv "TESTVAR2") "value2"))))
+ (env (python-shell--calculate-process-environment)))
+ (should (equal (getenv-internal "TESTVAR1" env) "value1"))
+ (should (equal (getenv-internal "TESTVAR2" env) "value2"))))
(ert-deftest python-shell-calculate-process-environment-2 ()
"Test `python-shell-extra-pythonpaths' modification."
(let* ((process-environment process-environment)
(_original-pythonpath (setenv "PYTHONPATH" "/path0"))
(python-shell-extra-pythonpaths '("/path1" "/path2"))
- (process-environment (python-shell-calculate-process-environment)))
- (should (equal (getenv "PYTHONPATH")
+ (env (python-shell--calculate-process-environment)))
+ (should (equal (getenv-internal "PYTHONPATH" env)
(concat "/path1" path-separator
"/path2" path-separator "/path0")))))
(ert-deftest python-shell-calculate-process-environment-3 ()
"Test `python-shell-virtualenv-root' modification."
(let* ((python-shell-virtualenv-root "/env")
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONHOME" "/home")
(setenv "VIRTUAL_ENV")
- (python-shell-calculate-process-environment))))
- (should (not (getenv "PYTHONHOME")))
- (should (string= (getenv "VIRTUAL_ENV") "/env"))))
+ (python-shell--calculate-process-environment))))
+ (should (member "PYTHONHOME" env))
+ (should (string= (getenv-internal "VIRTUAL_ENV" env) "/env"))))
(ert-deftest python-shell-calculate-process-environment-4 ()
"Test PYTHONUNBUFFERED when `python-shell-unbuffered' is non-nil."
(let* ((python-shell-unbuffered t)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED")
- (python-shell-calculate-process-environment))))
- (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+ (python-shell--calculate-process-environment))))
+ (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
(ert-deftest python-shell-calculate-process-environment-5 ()
"Test PYTHONUNBUFFERED when `python-shell-unbuffered' is nil."
(let* ((python-shell-unbuffered nil)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED")
- (python-shell-calculate-process-environment))))
- (should (not (getenv "PYTHONUNBUFFERED")))))
+ (python-shell--calculate-process-environment))))
+ (should (not (getenv-internal "PYTHONUNBUFFERED" env)))))
(ert-deftest python-shell-calculate-process-environment-6 ()
"Test PYTHONUNBUFFERED=1 when `python-shell-unbuffered' is nil."
(let* ((python-shell-unbuffered nil)
- (process-environment
+ (env
(let ((process-environment process-environment))
(setenv "PYTHONUNBUFFERED" "1")
- (python-shell-calculate-process-environment))))
+ (append (python-shell--calculate-process-environment)
+ process-environment))))
;; User default settings must remain untouched:
- (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+ (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
(ert-deftest python-shell-calculate-process-environment-7 ()
"Test no side-effects on `process-environment'."
@@ -2695,7 +3067,7 @@ if x:
(python-shell-unbuffered t)
(python-shell-extra-pythonpaths'("/path1" "/path2"))
(original-process-environment (copy-sequence process-environment)))
- (python-shell-calculate-process-environment)
+ (python-shell--calculate-process-environment)
(should (equal process-environment original-process-environment))))
(ert-deftest python-shell-calculate-process-environment-8 ()
@@ -2708,7 +3080,7 @@ if x:
(python-shell-extra-pythonpaths'("/path1" "/path2"))
(original-process-environment
(copy-sequence tramp-remote-process-environment)))
- (python-shell-calculate-process-environment)
+ (python-shell--calculate-process-environment)
(should (equal tramp-remote-process-environment original-process-environment))))
(ert-deftest python-shell-calculate-exec-path-1 ()
@@ -2780,23 +3152,43 @@ if x:
(should (string= (getenv "VIRTUAL_ENV") "/env")))
(should (equal exec-path original-exec-path))))
+(defun python--tests-process-env-canonical (pe)
+ ;; `process-environment' can contain various entries for the same
+ ;; var, and the first in the list hides the others.
+ (let ((process-environment '()))
+ (dolist (x (reverse pe))
+ (if (string-match "=" x)
+ (setenv (substring x 0 (match-beginning 0))
+ (substring x (match-end 0)))
+ (setenv x nil)))
+ process-environment))
+
+(defun python--tests-process-env-eql (pe1 pe2)
+ (equal (python--tests-process-env-canonical pe1)
+ (python--tests-process-env-canonical pe2)))
+
(ert-deftest python-shell-with-environment-2 ()
"Test environment with remote `default-directory'."
(let* ((default-directory "/ssh::/example/dir/")
(python-shell-remote-exec-path '("/remote1" "/remote2"))
(python-shell-exec-path '("/path1" "/path2"))
(tramp-remote-process-environment '("EMACS=t"))
- (original-process-environment (copy-sequence tramp-remote-process-environment))
+ (original-process-environment
+ (copy-sequence tramp-remote-process-environment))
(python-shell-virtualenv-root "/env"))
(python-shell-with-environment
(should (equal (python-shell-calculate-exec-path)
(list (python-virt-bin)
"/path1" "/path2" "/remote1" "/remote2")))
- (let ((process-environment (python-shell-calculate-process-environment)))
+ (let ((process-environment
+ (append (python-shell--calculate-process-environment)
+ tramp-remote-process-environment)))
(should (not (getenv "PYTHONHOME")))
(should (string= (getenv "VIRTUAL_ENV") "/env"))
- (should (equal tramp-remote-process-environment process-environment))))
- (should (equal tramp-remote-process-environment original-process-environment))))
+ (should (python--tests-process-env-eql
+ tramp-remote-process-environment process-environment))))
+ (should (equal tramp-remote-process-environment
+ original-process-environment))))
(ert-deftest python-shell-with-environment-3 ()
"Test `python-shell-with-environment' is idempotent."
@@ -2805,11 +3197,14 @@ if x:
(python-shell-virtualenv-root "/home/user/env")
(single-call
(python-shell-with-environment
- (list exec-path process-environment)))
+ (list exec-path
+ (python--tests-process-env-canonical process-environment))))
(nested-call
(python-shell-with-environment
(python-shell-with-environment
- (list exec-path process-environment)))))
+ (list exec-path
+ (python--tests-process-env-canonical
+ process-environment))))))
(should (equal single-call nested-call))))
(ert-deftest python-shell-make-comint-1 ()
@@ -3479,10 +3874,7 @@ def foo():
(should (string= (python-shell-buffer-substring
(python-tests-look-at "print ('a')")
(point-max))
- "if True:
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\nif True:\n print ('a')\n\n"))))
(ert-deftest python-shell-buffer-substring-11 ()
"Check substring from partial block and point within indentation."
@@ -3497,10 +3889,7 @@ def foo():
(backward-char 1)
(point))
(point-max))
- "if True:
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\nif True:\n print ('a')\n\n"))))
(ert-deftest python-shell-buffer-substring-12 ()
"Check substring from partial block and point in whitespace."
@@ -3515,13 +3904,7 @@ def foo():
(should (string= (python-shell-buffer-substring
(python-tests-look-at "# Whitespace")
(point-max))
- "if True:
-
-
- # Whitespace
-
- print ('a')
-"))))
+ "# -*- coding: utf-8 -*-\n\nif True:\n # Whitespace\n\n print ('a')\n\n"))))
@@ -4919,6 +5302,23 @@ def decorat0r(deff):
(python-tests-look-at "deff()")
(should (not (python-info-looking-at-beginning-of-defun)))))
+(ert-deftest python-info-looking-at-beginning-of-defun-2 ()
+ (python-tests-with-temp-buffer
+ "
+def \\
+ foo(arg):
+ pass
+"
+ (python-tests-look-at "def \\")
+ (should (python-info-looking-at-beginning-of-defun))
+ (should (python-info-looking-at-beginning-of-defun nil t))
+ (python-tests-look-at "foo(arg):")
+ (should (not (python-info-looking-at-beginning-of-defun)))
+ (should (python-info-looking-at-beginning-of-defun nil t))
+ (python-tests-look-at "pass")
+ (should (not (python-info-looking-at-beginning-of-defun)))
+ (should (not (python-info-looking-at-beginning-of-defun nil t)))))
+
(ert-deftest python-info-current-line-comment-p-1 ()
(python-tests-with-temp-buffer
"
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index 8c698e4fac8..0c206b1e0c2 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -483,3 +483,20 @@ foo bar, {
2 = 3
:foo= if true
{:abc=>4} # not indented, and '=' is not highlighted
+
+# Pattern matching
+case translation
+in ['th', orig_text, 'en', trans_text]
+ puts "English translation: #{orig_text} => #{trans_text}"
+in {'th' => orig_text, 'ja' => trans_text}
+ puts "Japanese translation: #{orig_text} => #{trans_text}"
+end
+
+# Tokenizing "**" and "|" separately.
+def resolve(**args)
+ members = proc do |**args|
+ p(**args)
+ end
+
+ member.call(**args)
+end
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index 23e13b94e6b..33fded5a59b 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -407,6 +407,13 @@ VALUES-PLIST is a list with alternating index and value elements."
(ruby-toggle-block)
(should (string= "foo { \"#{bar}\" }" (buffer-string)))))
+(ert-deftest ruby-toggle-block-to-brace-no-space ()
+ (ruby-with-temp-buffer "foo do |b|\n b + 2\nend"
+ (beginning-of-line)
+ (let (ruby-toggle-block-space-before-parameters)
+ (ruby-toggle-block))
+ (should (string= "foo {|b| b + 2 }" (buffer-string)))))
+
(ert-deftest ruby-recognize-symbols-starting-with-at-character ()
(ruby-assert-face ":@abc" 3 font-lock-constant-face))
diff --git a/test/lisp/progmodes/sh-script-resources/sh-indents.erts b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
new file mode 100644
index 00000000000..1f92610b3aa
--- /dev/null
+++ b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
@@ -0,0 +1,40 @@
+Code:
+ (lambda ()
+ (shell-script-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: sh-indents1
+
+=-=
+if test;then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents2
+
+=-=
+if test; then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents3
+
+=-=
+if test ; then
+ something
+fi
+other
+=-=-=
+
+Name: sh-indents4
+
+=-=
+if test ;then
+ something
+fi
+other
+=-=-=
diff --git a/test/lisp/progmodes/sh-script-tests.el b/test/lisp/progmodes/sh-script-tests.el
index ebd26ab4295..5d01cc1c226 100644
--- a/test/lisp/progmodes/sh-script-tests.el
+++ b/test/lisp/progmodes/sh-script-tests.el
@@ -23,6 +23,7 @@
(require 'sh-script)
(require 'ert)
+(require 'ert-x)
(ert-deftest test-sh-script-indentation ()
(with-temp-buffer
@@ -48,4 +49,24 @@
}
"))))
+(ert-deftest test-indentation ()
+ (ert-test-erts-file (ert-resource-file "sh-indents.erts")))
+
+(defun test-sh-back (string &optional pos)
+ (with-temp-buffer
+ (shell-script-mode)
+ (insert string)
+ (sh-smie--default-backward-token)
+ (= (point) (or pos 1))))
+
+(ert-deftest test-backward-token ()
+ (should (test-sh-back "foo"))
+ (should (test-sh-back "foo.bar"))
+ (should (test-sh-back "foo\\1bar"))
+ (should (test-sh-back "foo\\\nbar"))
+ (should (test-sh-back "foo\\\n\\\n\\\nbar"))
+ (should (test-sh-back "foo"))
+ (should-not (test-sh-back "foo;bar"))
+ (should (test-sh-back "foo#zot")))
+
;;; sh-script-tests.el ends here
diff --git a/test/lisp/progmodes/sql-tests.el b/test/lisp/progmodes/sql-tests.el
index 7e36d845e2c..c644d115df6 100644
--- a/test/lisp/progmodes/sql-tests.el
+++ b/test/lisp/progmodes/sql-tests.el
@@ -425,5 +425,85 @@ The ACTION will be tested after set-up of PRODUCT."
(let ((sql-password "password"))
(should (equal "password" (sql-comint-automatic-password "")))))
+
+
+;; Tests for sql-interactive-remove-continuation-prompt
+
+(defmacro sql-tests-remove-cont-prompts-harness (&rest body)
+ "Set-up and tear-down for tests of
+`sql-interactive-remove-continuation-prompt'."
+ (declare (indent 0))
+ `(let ((comint-prompt-regexp "^ +\\.\\{3\\} ")
+ (sql-output-newline-count nil)
+ (sql-preoutput-hold nil))
+ ,@body
+ (should (null sql-output-newline-count))
+ (should (null sql-preoutput-hold))))
+
+(ert-deftest sql-tests-remove-cont-prompts-pass-through ()
+ "Test that `sql-interactive-remove-continuation-prompt' just
+passes the output line through when it doesn't expect prompts."
+ (sql-tests-remove-cont-prompts-harness
+ (should
+ (equal " ... "
+ (sql-interactive-remove-continuation-prompt
+ " ... ")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-anchored-successive ()
+ "Test that `sql-interactive-remove-continuation-prompt' is able
+to delete multiple prompts (anchored to bol) even if they appear
+in a single line, but not more than `sql-output-newline-count'."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-output-newline-count 2)
+ (should
+ (equal
+ ;; 2 of 3 prompts are deleted
+ "some output ... more output...\n\
+ ... \n\
+output after prompt"
+ (sql-interactive-remove-continuation-prompt
+ "some output ... more output...\n\
+ ... ... ... \n\
+output after prompt")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-collect-chunked-output ()
+ "Test that `sql-interactive-remove-continuation-prompt' properly
+collects output when output arrives in chunks, with prompts
+intermixed."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-output-newline-count 2)
+
+ ;; Part of first prompt gets held. Complete line is passed
+ ;; through.
+ (should (equal "line1\n"
+ (sql-interactive-remove-continuation-prompt
+ "line1\n ..")))
+ (should (equal " .." sql-preoutput-hold))
+ (should (equal 2 sql-output-newline-count))
+
+ ;; First prompt is complete - remove it. Hold part of line2.
+ (should (equal ""
+ (sql-interactive-remove-continuation-prompt ". li")))
+ (should (equal "li" sql-preoutput-hold))
+ (should (equal 1 sql-output-newline-count))
+
+ ;; Remove second prompt. Flush output & don't hold / process any
+ ;; output further on.
+ (should (equal "line2\nli"
+ (sql-interactive-remove-continuation-prompt "ne2\n ... li")))
+ (should (null sql-preoutput-hold))
+ (should (null sql-output-newline-count))
+ (should (equal "line3\n ... "
+ (sql-interactive-remove-continuation-prompt "line3\n ... ")))))
+
+(ert-deftest sql-tests-remove-cont-prompts-flush-held ()
+ "Test that when we don't wait for prompts,
+ `sql-interactive-remove-continuation-prompt' just 'flushes' held
+ output, with no prompt processing."
+ (sql-tests-remove-cont-prompts-harness
+ (setq sql-preoutput-hold "line1\n ..")
+ (should (equal "line1\n ... line2 .."
+ (sql-interactive-remove-continuation-prompt ". line2 ..")))))
+
(provide 'sql-tests)
;;; sql-tests.el ends here
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 5ba11ed0d57..ef1e5c3eafc 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -406,6 +406,102 @@ Each element has the format:
(kill-buffer temp-buffer)))))
+;;; General tests for `query-replace' and `query-replace-regexp'.
+
+(defconst query-replace-tests
+ '(
+ ;; query-replace
+ ("aaa" "M-% a RET 1 RET !" "111")
+ ("aaa" "M-% a RET 1 RET y n y" "1a1")
+ ;; Empty inputs
+ ("aaa" "M-% a RET RET !" "")
+ ("aaa" "M-% RET 1 RET !" "1a1a1a")
+ ("aaa" "M-% RET RET !" "aaa")
+ ;; Reuse the previous default
+ ("aaa" "M-% a RET 1 RET . M-% RET !" "111")
+
+ ;; query-replace-regexp
+ ("aaa" "C-M-% a* RET 1 RET !" "1")
+ ;; Empty inputs
+ ("aaa" "C-M-% a* RET RET !" "")
+ ("aaa" "C-M-% RET 1 RET !" "1a1a1a")
+ ("aaa" "C-M-% RET RET !" "aaa")
+ ;; Empty matches
+ ("aaa" "C-M-% b* RET 1 RET !" "1a1a1a")
+ ;; Complete matches
+ ("aaa" "C-M-% .* RET 1 RET !" "1")
+ ;; Adjacent non-empty matches
+ ("abaab" "C-M-% ab* RET 12 RET !" "121212")
+ ;; Adjacent non-empty and empty matches
+ ("abab" "C-M-% a* RET 1 RET !" "1b1b")
+ ("abab" "C-M-% b* RET 1 RET !" "1a1a1")
+ ;; Test case from commit 5632eb272c7
+ ("a a a " "C-M-% \\ba SPC RET c RET !" "ccc") ; not "ca c"
+ ))
+
+(defun query-replace--run-tests (tests)
+ (with-temp-buffer
+ (save-window-excursion
+ ;; `execute-kbd-macro' is applied to window only
+ (set-window-buffer nil (current-buffer))
+ (dolist (case tests)
+ ;; Ensure empty input means empty string to replace:
+ (setq query-replace-defaults nil)
+ (delete-region (point-min) (point-max))
+ (insert (nth 0 case))
+ (goto-char (point-min))
+ (execute-kbd-macro (kbd (nth 1 case)))
+ (should (equal (buffer-string) (nth 2 case)))))))
+
+(ert-deftest query-replace-tests ()
+ (query-replace--run-tests query-replace-tests))
+
+(ert-deftest query-replace-search-function-tests ()
+ (let* ((replace-re-search-function #'re-search-forward))
+ (query-replace--run-tests query-replace-tests))
+
+ (let* ((pairs '((1 . 2) (3 . 4)))
+ (replace-re-search-function
+ (lambda (string &optional _bound noerror count)
+ (let (found)
+ (while (and (not found) pairs)
+ (goto-char (caar pairs))
+ (when (re-search-forward string (cdar pairs) noerror count)
+ (setq found t))
+ (pop pairs))
+ found)))
+ (tests
+ '(
+ ;; FIXME: this test should pass after fixing bug#54733:
+ ;; ("aaaa" "C-M-% .* RET 1 RET !" "1a1a")
+ )))
+ (query-replace--run-tests tests)))
+
+
+;;; General tests for `perform-replace'.
+
+(defconst perform-replace-tests
+ '(
+ ;; Test case from commit 5632eb272c7
+ ("a a a " "\\ba " "c" nil t nil nil nil nil nil nil nil "ccc") ; not "ca c"
+ ;; The same with region inside the second match
+ ;; FIXME: this test should pass after fixing bug#54733:
+ ;; ("a a a " "\\ba " "c" nil t nil nil nil 1 4 nil nil "ca a ")
+ ))
+
+(defun perform-replace--run-tests (tests)
+ (with-temp-buffer
+ (dolist (case tests)
+ (delete-region (point-min) (point-max))
+ (insert (pop case))
+ (goto-char (point-min))
+ (apply 'perform-replace (butlast case))
+ (should (equal (buffer-string) (car (last case)))))))
+
+(ert-deftest perform-replace-tests ()
+ (perform-replace--run-tests perform-replace-tests))
+
+
;;; Tests for `query-replace' undo feature.
(defvar replace-tests-bind-read-string nil
diff --git a/test/lisp/ses-tests.el b/test/lisp/ses-tests.el
index cd524cbf6e0..ea3f9d05d70 100644
--- a/test/lisp/ses-tests.el
+++ b/test/lisp/ses-tests.el
@@ -22,12 +22,24 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'ert-x))
(require 'ses)
;; Silence byte-compiler.
-(with-suppressed-warnings ((lexical A2) (lexical A3))
+(with-suppressed-warnings ((lexical ses--cells)
+ (lexical A2)
+ (lexical A3)
+ (lexical ses--foo)
+ (lexical ses--bar)
+ (lexical B2)
+ (lexical ses--toto))
+ (defvar ses--cells)
(defvar A2)
- (defvar A3))
+ (defvar A3)
+ (defvar ses--foo)
+ (defvar ses--bar)
+ (defvar B2)
+ (defvar ses--toto))
;; PLAIN FORMULA TESTS
;; ======================================================================
@@ -58,9 +70,6 @@ equal to 2. This is done using interactive calls."
;; PLAIN CELL RENAMING TESTS
;; ======================================================================
-(defvar ses--foo)
-(defvar ses--cells)
-
(ert-deftest ses-tests-lowlevel-renamed-cell ()
"Check that renaming A1 to `ses--foo' and setting `ses--foo' to 1 and A2 to (1+ ses--foo), makes A2 value equal to 2.
This is done using low level functions, `ses-rename-cell' is not
@@ -154,7 +163,6 @@ to A2 and inserting a row, makes A2 value empty, and A3 equal to
(should-not (bound-and-true-p A2))
(should (eq (bound-and-true-p A3) 2)))))
-(defvar ses--bar)
(ert-deftest ses-tests-renamed-cells-row-insertion ()
"Check that setting A1 to 1 and A2 to (1+ A1), and then renaming A1 to `ses--foo' and A2 to `ses--bar' jumping
@@ -178,6 +186,61 @@ to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to
(should (eq ses--bar 2)))))
+;; JUMP tests
+;; ======================================================================
+(ert-deftest ses-jump-B2-prefix-arg ()
+ "Test jumping to cell B2 by use of prefix argument"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ ;; C-u 4 M-x ses-jump
+ (let ((current-prefix-arg 4))
+ (call-interactively 'ses-jump))
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+
+(ert-deftest ses-jump-B2-lowcase ()
+ "Test jumping to cell B2 by use of lowcase cell name string"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump "b2")
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-lowcase-keys ()
+ "Test jumping to cell B2 by use of lowcase cell name string with simulating keys"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ert-simulate-keys [ ?b ?2 return] (ses-jump))
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-symbol ()
+ "Test jumping to cell B2 by use of cell name symbol"
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (funcall-interactively 'ses-jump 'B2)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'B2)))))
+
+(ert-deftest ses-jump-B2-renamed ()
+ "Test jumping to cell B2 after renaming it `ses--toto'."
+ (let ((ses-initial-size '(3 . 3))
+ ses-after-entry-functions)
+ (with-temp-buffer
+ (ses-mode)
+ (ses-rename-cell 'ses--toto (ses-get-cell 1 1))
+ (ses-jump 'ses--toto)
+ (ses-command-hook)
+ (should (eq (ses--cell-at-pos (point)) 'ses--toto)))))
+
(provide 'ses-tests)
;;; ses-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index 46ab34535d4..0916f7ce688 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -37,37 +37,9 @@
;;; Code:
-(require 'ert)
-(require 'shadowfile)
(require 'tramp)
-
-;; There is no default value on w32 systems, which could work out of the box.
-(defconst shadow-test-remote-temporary-file-directory
- (cond
- ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
- ((eq system-type 'windows-nt) null-device)
- (t (add-to-list
- 'tramp-methods
- '("mock"
- (tramp-login-program "sh")
- (tramp-login-args (("-i")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-connection-timeout 10)))
- (add-to-list
- 'tramp-default-host-alist
- `("\\`mock\\'" nil ,(system-name)))
- ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
- ;; batch mode only, therefore. `shadow-homedir' cannot be
- ;; `temporary-directory', because the tests with "~" would fail.
- (unless (and (null noninteractive) (file-directory-p "~/"))
- (setenv "HOME" (file-name-unquote temporary-file-directory))
- (setq shadow-homedir invocation-directory)
- (add-to-list
- 'tramp-connection-properties
- `(,(file-remote-p "/mock::") "~" ,invocation-directory)))
- (format "/mock::%s" temporary-file-directory)))
- "Temporary directory for Tramp tests.")
+(require 'ert-x)
+(require 'shadowfile)
(setq auth-source-save-behavior nil
password-cache-expiry nil
@@ -80,13 +52,8 @@
tramp-verbose 0
;; On macOS, `temporary-file-directory' is a symlinked directory.
temporary-file-directory (file-truename temporary-file-directory)
- shadow-test-remote-temporary-file-directory
- (ignore-errors
- (file-truename shadow-test-remote-temporary-file-directory)))
-
-;; This should happen on hydra only.
-(when (getenv "EMACS_HYDRA_CI")
- (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
+ ert-remote-temporary-file-directory
+ (ignore-errors (file-truename ert-remote-temporary-file-directory)))
(defconst shadow-test-info-file
(expand-file-name "shadows_test" temporary-file-directory)
@@ -100,7 +67,7 @@
"Reset all `shadowfile' internals."
;; Cleanup Tramp.
(tramp-cleanup-connection
- (tramp-dissect-file-name shadow-test-remote-temporary-file-directory) t t)
+ (tramp-dissect-file-name ert-remote-temporary-file-directory) t t)
;; Delete auto-saved files.
(with-current-buffer (find-file-noselect shadow-info-file 'nowarn)
(ignore-errors (delete-file (make-auto-save-file-name)))
@@ -135,7 +102,7 @@ a cluster (or site). This is not tested here; it must be
guaranteed by the originator of a cluster definition."
:tags '(:expensive-test)
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((text-quoting-style 'grave) ;; We inspect the *Messages* buffer!
(inhibit-message t)
@@ -222,8 +189,7 @@ guaranteed by the originator of a cluster definition."
(shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
;; Redefine the cluster.
- (setq primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary)
mocked-input `(,cluster ,primary ,regexp))
(call-interactively #'shadow-define-cluster)
@@ -254,7 +220,7 @@ Per definition, all files are identical on the different hosts of
a cluster (or site). This is not tested here; it must be
guaranteed by the originator of a cluster definition."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -286,14 +252,14 @@ guaranteed by the originator of a cluster definition."
(should (string-equal (system-name) (shadow-site-name primary1)))
(should
(string-equal
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (file-remote-p ert-remote-temporary-file-directory)
(shadow-name-site
- (file-remote-p shadow-test-remote-temporary-file-directory))))
+ (file-remote-p ert-remote-temporary-file-directory))))
(should
(string-equal
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (file-remote-p ert-remote-temporary-file-directory)
(shadow-site-name
- (file-remote-p shadow-test-remote-temporary-file-directory))))
+ (file-remote-p ert-remote-temporary-file-directory))))
(should (equal (shadow-site-cluster cluster1)
(shadow-get-cluster cluster1)))
@@ -324,8 +290,7 @@ guaranteed by the originator of a cluster definition."
;; Define a second cluster.
(setq cluster2 "cluster2"
- primary2
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ primary2 (file-remote-p ert-remote-temporary-file-directory)
regexp2 (format "^\\(%s\\|%s\\)$" shadow-system-name primary2))
(shadow-set-cluster cluster2 primary2 regexp2)
@@ -356,7 +321,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test02-files ()
"Check file manipulation functions."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -398,8 +363,7 @@ guaranteed by the originator of a cluster definition."
(string-equal (shadow-local-file (concat primary file)) file))
;; Redefine the cluster.
- (setq primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster primary regexp)
@@ -428,7 +392,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test03-expand-cluster-in-file-name ()
"Check canonical file name of a cluster or site."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -453,8 +417,7 @@ guaranteed by the originator of a cluster definition."
file2
(make-temp-name
(expand-file-name
- "shadowfile-tests"
- shadow-test-remote-temporary-file-directory)))
+ "shadowfile-tests" ert-remote-temporary-file-directory)))
;; A local file name is kept.
(should
@@ -473,8 +436,7 @@ guaranteed by the originator of a cluster definition."
(shadow-expand-cluster-in-file-name (concat primary file1)) file1))
;; Redefine the cluster.
- (setq primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster primary regexp)
@@ -495,7 +457,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test04-contract-file-name ()
"Check canonical file name of a cluster or site."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -533,8 +495,7 @@ guaranteed by the originator of a cluster definition."
(concat "/cluster:" file)))
;; Redefine the cluster.
- (setq primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster primary regexp)
@@ -542,8 +503,7 @@ guaranteed by the originator of a cluster definition."
(should
(string-equal
(shadow-contract-file-name
- (concat
- (file-remote-p shadow-test-remote-temporary-file-directory) file))
+ (concat (file-remote-p ert-remote-temporary-file-directory) file))
(concat "/cluster:" file))))
;; Cleanup.
@@ -552,7 +512,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test05-file-match ()
"Check `shadow-same-site' and `shadow-file-match'."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -588,17 +548,14 @@ guaranteed by the originator of a cluster definition."
(should (shadow-file-match (shadow-parse-name file) file))
;; Redefine the cluster.
- (setq primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ (setq primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster primary regexp)
(should
(shadow-file-match
(shadow-parse-name
- (concat
- (file-remote-p shadow-test-remote-temporary-file-directory)
- file))
+ (concat (file-remote-p ert-remote-temporary-file-directory) file))
file)))
;; Cleanup.
@@ -607,7 +564,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test06-literal-groups ()
"Check literal group definitions."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -632,8 +589,7 @@ guaranteed by the originator of a cluster definition."
(shadow-set-cluster cluster1 primary regexp)
(setq cluster2 "cluster2"
- primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ primary (file-remote-p ert-remote-temporary-file-directory)
regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
(shadow-set-cluster cluster2 primary regexp)
@@ -644,8 +600,7 @@ guaranteed by the originator of a cluster definition."
file2
(make-temp-name
(expand-file-name
- "shadowfile-tests"
- shadow-test-remote-temporary-file-directory))
+ "shadowfile-tests" ert-remote-temporary-file-directory))
mocked-input
`(,cluster1 ,file1 ,cluster2 ,file2
,primary ,file1 ,(kbd "RET")))
@@ -694,7 +649,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test07-regexp-groups ()
"Check regexp group definitions."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
(shadow-todo-file shadow-test-todo-file)
@@ -719,8 +674,7 @@ guaranteed by the originator of a cluster definition."
(shadow-set-cluster cluster1 primary regexp)
(setq cluster2 "cluster2"
- primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ primary (file-remote-p ert-remote-temporary-file-directory)
regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
(shadow-set-cluster cluster2 primary regexp)
@@ -757,8 +711,8 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test08-shadow-todo ()
"Check that needed shadows are added to todo."
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
- (skip-unless (file-writable-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+ (skip-unless (file-writable-p ert-remote-temporary-file-directory))
(let ((backup-inhibited t)
create-lockfiles
@@ -778,7 +732,7 @@ guaranteed by the originator of a cluster definition."
(message
"%s %s %s %s %s"
temporary-file-directory
- shadow-test-remote-temporary-file-directory
+ ert-remote-temporary-file-directory
shadow-homedir shadow-info-file shadow-todo-file))
;; Define clusters.
@@ -792,8 +746,7 @@ guaranteed by the originator of a cluster definition."
cluster1 primary regexp shadow-clusters))
(setq cluster2 "cluster2"
- primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster2 primary regexp)
(when shadow-debug
@@ -903,8 +856,8 @@ guaranteed by the originator of a cluster definition."
"Check that needed shadow files are copied."
:tags '(:expensive-test)
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
- (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
- (skip-unless (file-writable-p shadow-test-remote-temporary-file-directory))
+ (skip-unless (file-remote-p ert-remote-temporary-file-directory))
+ (skip-unless (file-writable-p ert-remote-temporary-file-directory))
(let ((backup-inhibited t)
create-lockfiles
@@ -928,8 +881,7 @@ guaranteed by the originator of a cluster definition."
(shadow-set-cluster cluster1 primary regexp)
(setq cluster2 "cluster2"
- primary
- (file-remote-p shadow-test-remote-temporary-file-directory)
+ primary (file-remote-p ert-remote-temporary-file-directory)
regexp (shadow-regexp-superquote primary))
(shadow-set-cluster cluster2 primary regexp)
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index 6350bebeeea..b4576889dcd 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -966,10 +966,65 @@ See Bug#21722."
(setq buffer-undo-list nil)
(downcase-word 1)
(should (= (length (delq nil (undo-make-selective-list 1 9))) 2))
- (should (= (length (delq nil (undo-make-selective-list 4 9))) 1))
- ;; FIXME this is the off-by-one error case.
+ ;; FIXME: These should give 0, but currently give 1.
+ ;;(should (= (length (delq nil (undo-make-selective-list 4 9))) 0))
;;(should (= (length (delq nil (undo-make-selective-list 5 9))) 0))
(should (= (length (delq nil (undo-make-selective-list 6 9))) 0))))
+(ert-deftest test-yank-in-context ()
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo \"foo\"")
+ (kill-new "\"bar\"")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo \"f\\\"bar\\\"oo\""))
+
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo \"foo\"")
+ (kill-new "'bar'")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo \"f'bar'oo\""))
+
+ (should
+ (equal
+ (with-temp-buffer
+ (sh-mode)
+ (insert "echo 'foo'")
+ (kill-new "'bar'")
+ (goto-char 8)
+ (yank-in-context)
+ (buffer-string))
+ "echo 'f'\\''bar'\\''oo'")))
+
+;;; Tests for `zap-to-char'
+
+(defmacro with-zap-to-char-test (original result &rest body)
+ (declare (indent 2) (debug (stringp stringp body)))
+ `(with-temp-buffer
+ (insert ,original)
+ (goto-char (point-min))
+ ,@body
+ (should (equal (buffer-string) ,result))))
+
+(ert-deftest simple-tests-zap-to-char ()
+ (with-zap-to-char-test "abcde" "de"
+ (zap-to-char 1 ?c))
+ (with-zap-to-char-test "abcde abc123" "123"
+ (zap-to-char 2 ?c))
+ (let ((case-fold-search t))
+ (with-zap-to-char-test "abcdeCXYZ" "deCXYZ"
+ (zap-to-char 1 ?C))
+ (with-zap-to-char-test "abcdeCXYZ" "XYZ"
+ (zap-to-char 1 ?C 'interactive))))
+
(provide 'simple-test)
;;; simple-tests.el ends here
diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el
index d83ed34e274..bf619f453d2 100644
--- a/test/lisp/so-long-tests/so-long-tests.el
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -59,7 +59,7 @@
(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
(declare-function so-long-tests-predicates "so-long-tests-helpers")
-;; Enable the automated behaviour for all tests.
+;; Enable the automated behavior for all tests.
(global-so-long-mode 1)
(ert-deftest so-long-tests-threshold-under ()
@@ -210,7 +210,7 @@
;; From Emacs 27 the `display-buffer' call is insufficient.
;; The various 'window change functions' are now invoked by the
;; redisplay, and redisplay does nothing at all in batch mode,
- ;; so we cannot test under this revised behaviour. Refer to:
+ ;; so we cannot test under this revised behavior. Refer to:
;; https://lists.gnu.org/r/emacs-devel/2019-10/msg00971.html
;; For interactive (non-batch) test runs, calling `redisplay'
;; does do the trick; so do that first.
diff --git a/test/lisp/so-long-tests/spelling-tests.el b/test/lisp/so-long-tests/spelling-tests.el
index 317513e9a91..ce4b0844c99 100644
--- a/test/lisp/so-long-tests/spelling-tests.el
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -36,12 +36,11 @@
;; make lisp/so-long-tests/spelling-tests SELECTOR=t
;; Only define the test if spell-checking is possible.
-(when (and ispell-program-name
- (executable-find ispell-program-name)
- (condition-case ()
- (progn (ispell-check-version) t)
- (error nil))
- (member "british" (ispell-valid-dictionary-list)))
+(when (ignore-errors
+ (and ispell-program-name
+ (executable-find ispell-program-name)
+ (progn (ispell-check-version) t)
+ (member "british" (ispell-valid-dictionary-list))))
(ert-deftest so-long-spelling ()
"Check the spelling in the source code."
:tags '(:unstable) ;; It works for me, but I'm not sure about others.
@@ -51,8 +50,9 @@
;; The Emacs test Makefile's use of HOME=/nonexistent triggers an error
;; when starting the inferior ispell process, so we set HOME to a valid
;; (but empty) temporary directory for this test.
- (ert-with-temp-file tmpdir
- :suffix "so-long.ispell"
+ (ert-with-temp-directory tmpdir
+ :prefix "so-long."
+ :suffix ".ispell"
(let* ((process-environment (cons (format "HOME=%s" tmpdir)
process-environment))
(find-spelling-mistake
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 9be7511bdc9..ced2bc5c4e5 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -112,7 +112,7 @@
(should (equal (kbd "C-x C-f") "\C-x\C-f"))
(should (equal (kbd "C-M-<down>") [C-M-down]))
(should (equal (kbd "<C-M-down>") [C-M-down]))
- (should (equal (kbd "C-RET") [?\C-\C-m]))
+ (should (equal (kbd "C-RET") [?\C-\r]))
(should (equal (kbd "C-SPC") [?\C- ]))
(should (equal (kbd "C-TAB") [?\C-\t]))
(should (equal (kbd "C-<down>") [C-down]))
@@ -1007,5 +1007,88 @@ final or penultimate step during initialization."))
(should (equal (ensure-list :foo) '(:foo)))
(should (equal (ensure-list '(1 2 3)) '(1 2 3))))
+(ert-deftest test-alias-p ()
+ (should-not (function-alias-p 1))
+
+ (defun subr-tests--fun ())
+ (should-not (function-alias-p 'subr-tests--fun))
+
+ (defalias 'subr-tests--a 'subr-tests--b)
+ (defalias 'subr-tests--b 'subr-tests--c)
+ (should (equal (function-alias-p 'subr-tests--a)
+ '(subr-tests--b subr-tests--c)))
+
+ (defalias 'subr-tests--d 'subr-tests--e)
+ (defalias 'subr-tests--e 'subr-tests--d)
+ (should-error (function-alias-p 'subr-tests--d))
+ (should (equal (function-alias-p 'subr-tests--d t)
+ '(subr-tests--e))))
+
+(ert-deftest test-readablep ()
+ (should (readablep "foo"))
+ (should-not (readablep (list (make-marker)))))
+
+(ert-deftest test-string-lines ()
+ (should (equal (string-lines "") '("")))
+ (should (equal (string-lines "" t) '()))
+
+ (should (equal (string-lines "foo") '("foo")))
+ (should (equal (string-lines "foo\n") '("foo")))
+ (should (equal (string-lines "foo\nbar") '("foo" "bar")))
+
+ (should (equal (string-lines "foo" t) '("foo")))
+ (should (equal (string-lines "foo\n" t) '("foo")))
+ (should (equal (string-lines "foo\nbar" t) '("foo" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" t) '("foo" "bar")))
+
+ (should (equal (string-lines "foo" nil t) '("foo")))
+ (should (equal (string-lines "foo\n" nil t) '("foo\n")))
+ (should (equal (string-lines "foo\nbar" nil t) '("foo\n" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" nil t)
+ '("foo\n" "\n" "\n" "bar")))
+
+ (should (equal (string-lines "foo" t t) '("foo")))
+ (should (equal (string-lines "foo\n" t t) '("foo\n")))
+ (should (equal (string-lines "foo\nbar" t t) '("foo\n" "bar")))
+ (should (equal (string-lines "foo\n\n\nbar" t t)
+ '("foo\n" "bar"))))
+
+(ert-deftest test-keymap-parse-macros ()
+ (should (equal (key-parse "C-x ( C-d C-x )") [24 40 4 24 41]))
+ (should (equal (kbd "C-x ( C-d C-x )") ""))
+ (should (equal (kbd "C-x ( C-x )") "")))
+
+(defvar subr-test--global)
+(ert-deftest test-local-set-state ()
+ (setq subr-test--global 1)
+ (with-temp-buffer
+ (setq-local subr-test--local 2)
+ (let ((state (buffer-local-set-state subr-test--global 10
+ subr-test--local 20
+ subr-test--unexist 30)))
+ (should (= subr-test--global 10))
+ (should (= subr-test--local 20))
+ (should (= subr-test--unexist 30))
+ (buffer-local-restore-state state)
+ (should (= subr-test--global 1))
+ (should (= subr-test--local 2))
+ (should-not (boundp 'subr-test--unexist)))))
+
+(ert-deftest test-char-uppercase-p ()
+ "Tests for `char-uppercase-p'."
+ (dolist (c (list ?R ?S ?Ω ?Ψ))
+ (should (char-uppercase-p c)))
+ (dolist (c (list ?a ?b ?α ?β))
+ (should-not (char-uppercase-p c))))
+
+(ert-deftest test-plistp ()
+ (should (plistp nil))
+ (should-not (plistp 1))
+ (should (plistp '(1 2)))
+ (should-not (plistp '(1 . 2)))
+ (should (plistp '(1 2 3 4)))
+ (should-not (plistp '(1 2 3)))
+ (should-not (plistp '(1 2 3 . 4))))
+
(provide 'subr-tests)
;;; subr-tests.el ends here
diff --git a/test/lisp/textmodes/css-mode-resources/css-selectors.txt b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
new file mode 100644
index 00000000000..5b3d990f279
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/css-selectors.txt
@@ -0,0 +1,56 @@
+#firstname
+*
+p
+p.intro
+div, p
+div p
+div > p
+div + p
+p ~ ul
+[target]
+[target=_blank]
+[title~=flower]
+[lang|=en]
+a[href^="https"]
+a[href$=".pdf"]
+a[href*="w3schools"]
+a:active
+p::after
+p::before
+input:checked
+input:default
+input:disabled
+p:empty
+input:enabled
+p:first-child
+p::first-letter
+p::first-line
+p:first-of-type
+input:focus
+:fullscreen
+a:hover
+input:in-range
+input:indeterminate
+input:invalid
+p:lang(it)
+p:last-child
+p:last-of-type
+a:link
+::marker
+:not(p)
+p:nth-child(2)
+p:nth-last-child(2)
+p:nth-last-of-type(2)
+p:nth-of-type(2)
+p:only-of-type
+p:only-child
+input:optional
+input:out-of-range
+input:read-only
+input:read-write
+input:required
+:root
+::selection
+#news:target
+input:valid
+a:visited
diff --git a/test/lisp/textmodes/css-mode-resources/scss-selectors.txt b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
new file mode 100644
index 00000000000..3e05191a910
--- /dev/null
+++ b/test/lisp/textmodes/css-mode-resources/scss-selectors.txt
@@ -0,0 +1,10 @@
+p.#{$name} var
+p.#{$name}:active var
+p.#{$name}::after var
+f.#{$bar}::after p::after
+p.#{$name} f.#{$bar} k.var #{$bar} #{$bar}
+p.#{$name}
+&:hover
+> li
++ li
+~ li
diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el
index 0ae1593508d..a746edf8944 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -419,5 +419,74 @@
(indent-region (point-min) (point-max))
(should (equal (buffer-string) orig)))))
+(ert-deftest css-mode-test-selectors ()
+ (let ((selectors
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "css-selectors.txt"))
+ (string-lines (buffer-string)))))
+ (with-suppressed-warnings ((interactive-only font-lock-debug-fontify))
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " {\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (line-end-position)))))))
+ ;; Test many selectors.
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " ")
+ (dotimes (_ (random 5))
+ (insert (seq-random-elt '(" , " " > " " + "))
+ (seq-random-elt selectors)))
+ (insert "{\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (line-end-position)))))))
+ ;; Test wrong separators.
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (css-mode)
+ (insert selector " ")
+ (dotimes (_ (1+ (random 5)))
+ (insert (seq-random-elt '("=" " @ "))
+ (seq-random-elt selectors)))
+ (insert "{\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (when (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Recognized %s as a selector"
+ (buffer-substring-no-properties
+ (point) (line-end-position))))))))))
+
+(ert-deftest scss-mode-test-selectors ()
+ (let ((selectors
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "scss-selectors.txt"))
+ (string-lines (buffer-string)))))
+ (with-suppressed-warnings ((interactive-only font-lock-debug-fontify))
+ (dolist (selector selectors)
+ (with-temp-buffer
+ (scss-mode)
+ (insert selector " {\n}\n")
+ (font-lock-debug-fontify)
+ (goto-char (point-min))
+ (unless (eq (get-text-property (point) 'face)
+ 'css-selector)
+ (should-not (format "Didn't recognize %s as a selector"
+ (buffer-substring-no-properties
+ (point) (line-end-position))))))))))
+
+
(provide 'css-mode-tests)
;;; css-mode-tests.el ends here
diff --git a/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts b/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts
new file mode 100644
index 00000000000..63c3b1b7d8a
--- /dev/null
+++ b/test/lisp/textmodes/emacs-news-mode-resources/toggle-tag.erts
@@ -0,0 +1,131 @@
+Name: tag1
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available with 'dired-x'.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available with 'dired-x'.
+=-=-=
+
+Name: tag2
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
++++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag3
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
++++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+|Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag4-point-at-headline
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+---
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag5-point-at-tag
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|+++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
+
+Name: tag6-point-at-tag
+Point-Char: |
+
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|+++
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key "% Y" is now bound by default in Dired.
+
+|*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the 'dired-x' package was
+loaded.
+=-=-=
diff --git a/test/lisp/textmodes/emacs-news-mode-tests.el b/test/lisp/textmodes/emacs-news-mode-tests.el
new file mode 100644
index 00000000000..d2da5eda906
--- /dev/null
+++ b/test/lisp/textmodes/emacs-news-mode-tests.el
@@ -0,0 +1,32 @@
+;;; emacs-news-mode-tests.el --- Tests for emacs-news-mode.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'emacs-news-mode)
+
+(ert-deftest emacs-news-toggle-tag ()
+ (ert-test-erts-file (ert-resource-file "toggle-tag.erts")
+ (lambda ()
+ (emacs-news-mode)
+ (emacs-news-toggle-tag))))
+
+;;; emacs-news-mode-tests.el ends here
diff --git a/test/lisp/textmodes/fill-tests.el b/test/lisp/textmodes/fill-tests.el
index a3265e24451..b730de5a690 100644
--- a/test/lisp/textmodes/fill-tests.el
+++ b/test/lisp/textmodes/fill-tests.el
@@ -45,6 +45,8 @@
(should (string= (buffer-string) "Abc\nd efg\n(h ijk)."))))
(ert-deftest fill-test-unbreakable-paragraph ()
+ ;; See bug#45720 and bug#53537.
+ :expected-result :failed
(with-temp-buffer
(let ((string "aaa = baaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"))
(insert string)
@@ -98,6 +100,27 @@
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eius. Foo")))
+(ert-deftest test-fill-haskell ()
+ (should
+ (equal
+ (with-temp-buffer
+ (asm-mode)
+ (dolist (line '(" ;; a b c"
+ " ;; d e f"
+ " ;; x y z"
+ " ;; w"))
+ (insert line "\n"))
+ (goto-char (point-min))
+ (end-of-line)
+ (setf fill-column 10)
+ (fill-paragraph nil)
+ (buffer-string))
+ " ;; a b c
+ ;; d e f
+ ;; x y z
+ ;; w
+")))
+
(provide 'fill-tests)
;;; fill-tests.el ends here
diff --git a/test/lisp/textmodes/page-tests.el b/test/lisp/textmodes/page-tests.el
index 596f3a6ceb7..b7217e69f0c 100644
--- a/test/lisp/textmodes/page-tests.el
+++ b/test/lisp/textmodes/page-tests.el
@@ -80,6 +80,17 @@
(narrow-to-page 2)
(should (equal (buffer-string) "baz"))
(narrow-to-page -1)
+ (should (equal (buffer-string) "bar\n"))
+
+ (widen)
+ (goto-char (point-min))
+ (narrow-to-page)
+ (should (equal (buffer-string) "foo\n"))
+ (goto-char (point-max))
+ (narrow-to-page 2)
+ (should (equal (buffer-string) "baz"))
+ (goto-char (point-max))
+ (narrow-to-page -1)
(should (equal (buffer-string) "bar\n"))))
(ert-deftest page-tests-count-lines-page ()
@@ -100,4 +111,5 @@
(forward-page)
(should (equal (page--what-page) '(3 4)))))
+
;;; page-tests.el ends here
diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el
index d52a19ef5d1..8361d58b558 100644
--- a/test/lisp/time-stamp-tests.el
+++ b/test/lisp/time-stamp-tests.el
@@ -271,7 +271,8 @@
(should (equal (time-stamp-string "%3a" ref-time1) Mon))
(should (equal (time-stamp-string "%#A" ref-time1) MONDAY))
;; documented 1997-2019
- (should (equal (time-stamp-string "%3A" ref-time1) MON))
+ (should (equal (time-stamp-string "%3A" ref-time1)
+ (substring MONDAY 0 3)))
(should (equal (time-stamp-string "%:a" ref-time1) Monday))
;; implemented since 2001, documented since 2019
(should (equal (time-stamp-string "%#a" ref-time1) MON))
@@ -291,10 +292,12 @@
(January (format-time-string "%B" ref-time1 t))
(JANUARY (format-time-string "%^B" ref-time1 t)))
;; implemented and documented since 1997
- (should (equal (time-stamp-string "%3b" ref-time1) Jan))
+ (should (equal (time-stamp-string "%3b" ref-time1)
+ (substring January 0 3)))
(should (equal (time-stamp-string "%#B" ref-time1) JANUARY))
;; documented 1997-2019
- (should (equal (time-stamp-string "%3B" ref-time1) JAN))
+ (should (equal (time-stamp-string "%3B" ref-time1)
+ (substring JANUARY 0 3)))
(should (equal (time-stamp-string "%:b" ref-time1) January))
;; implemented since 2001, documented since 2019
(should (equal (time-stamp-string "%#b" ref-time1) JAN))
@@ -652,15 +655,17 @@
(should (equal (time-stamp-string "%0b" ref-time3) ""))
(should (equal (time-stamp-string "%1b" ref-time3) (substring May 0 1)))
(should (equal (time-stamp-string "%2b" ref-time3) (substring May 0 2)))
- (should (equal (time-stamp-string "%3b" ref-time3) May))
+ (should (equal (time-stamp-string "%3b" ref-time3) (substring May 0 3)))
(should (equal (time-stamp-string "%4b" ref-time3) (concat " " May)))
(should (equal (time-stamp-string "%0%" ref-time3) ""))
(should (equal (time-stamp-string "%1%" ref-time3) "%"))
(should (equal (time-stamp-string "%2%" ref-time3) " %"))
(should (equal (time-stamp-string "%9%" ref-time3) " %"))
(should (equal (time-stamp-string "%10%" ref-time3) " %"))
- (should (equal (time-stamp-string "%#3a" ref-time3) SUN))
- (should (equal (time-stamp-string "%#3b" ref-time2) NOV)))))
+ (should (equal (time-stamp-string "%#3a" ref-time3)
+ (substring SUN 0 3)))
+ (should (equal (time-stamp-string "%#3b" ref-time2)
+ (substring NOV 0 3))))))
;;; Tests of helper functions
diff --git a/test/lisp/url/url-tramp-tests.el b/test/lisp/url/url-tramp-tests.el
index 033c17444db..369de0e2457 100644
--- a/test/lisp/url/url-tramp-tests.el
+++ b/test/lisp/url/url-tramp-tests.el
@@ -55,8 +55,12 @@
(password-cache-remove key)
(should-not (password-in-cache-p key)))
- ;; "http" does not belong to `url-tramp-protocols'.
- (should-not (url-tramp-convert-url-to-tramp "http://www.gnu.org")))
+ ;; "http" does not belong to `url-tramp-protocols'. The string
+ ;; isn't changed, therefore.
+ (should
+ (string-equal
+ (url-tramp-convert-url-to-tramp "http://www.gnu.org")
+ "http://www.gnu.org")))
(ert-deftest url-tramp-test-convert-tramp-to-url ()
"Test that Tramp file names are converted into proper URLs."
@@ -75,8 +79,12 @@
(url-tramp-convert-tramp-to-url "/telnet:user@remotehost#42:")
"telnet://user@remotehost:42"))
- ;; "sftp" does not belong to `url-tramp-protocols'.
- (should-not (url-tramp-convert-tramp-to-url "/sftp:user@localhost:")))
+ ;; "sftp" does not belong to `url-tramp-protocols'. The string
+ ;; isn't changed, therefore.
+ (should
+ (string-equal
+ (url-tramp-convert-tramp-to-url "/sftp:user@localhost:")
+ "/sftp:user@localhost:")))
(provide 'url-tramp-tests)
diff --git a/test/lisp/vc/vc-bzr-tests.el b/test/lisp/vc/vc-bzr-tests.el
index 12f1e9034c3..52f06df5bcd 100644
--- a/test/lisp/vc/vc-bzr-tests.el
+++ b/test/lisp/vc/vc-bzr-tests.el
@@ -140,7 +140,7 @@
;; causes bzr status to fail. This simulates a broken bzr
;; installation.
(delete-file ".bzr/checkout/dirstate")
- (should (progn (make-directory-autoloads
+ (should (progn (loaddefs-generate
default-directory
(expand-file-name "loaddefs.el" bzrdir))
t)))))
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index 7bf5ae6bc1d..dc4d3af6999 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -153,7 +153,7 @@ For backends which dont support it, it is emulated."
(delete-directory "module" 'recursive)
;; We must cleanup the "remote" CVS repo as well.
(add-hook 'vc-test--cleanup-hook
- `(lambda () (delete-directory ,tmp-dir 'recursive)))))
+ (lambda () (delete-directory tmp-dir 'recursive)))))
((eq backend 'Arch)
(let ((archive-name (format "%s--%s" user-mail-address (random))))
@@ -196,7 +196,8 @@ For backends which dont support it, it is emulated."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Check the revision granularity.
(should (memq (vc-test--revision-granularity-function backend)
@@ -249,7 +250,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository.
(make-directory default-directory)
@@ -329,7 +331,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository.
(make-directory default-directory)
@@ -394,7 +397,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository. Check working revision of
;; repository, should be nil.
@@ -471,7 +475,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository. Check repository checkout model.
(make-directory default-directory)
@@ -553,7 +558,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository.
(make-directory default-directory)
@@ -613,7 +619,8 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; Cleanup.
(add-hook
'vc-test--cleanup-hook
- `(lambda () (delete-directory ,default-directory 'recursive)))
+ (let ((dir default-directory))
+ (lambda () (delete-directory dir 'recursive))))
;; Create empty repository. Check repository checkout model.
(make-directory default-directory)
@@ -771,8 +778,9 @@ This checks also `vc-backend' and `vc-responsible-backend'."
',(intern
(format "vc-test-%s01-register" backend-string))))))
;; CVS calls vc-delete-file, which insists on prompting
- ;; "Really want to delete ...?"
- (skip-unless (not (eq 'CVS ',backend)))
+ ;; "Really want to delete ...?", and `vc-mtn.el' does not implement
+ ;; `delete-file' at all.
+ (skip-unless (not (memq ',backend '(CVS Mtn))))
(vc-test--rename-file ',backend))
(ert-deftest
@@ -785,6 +793,9 @@ This checks also `vc-backend' and `vc-responsible-backend'."
(ert-get-test
',(intern
(format "vc-test-%s01-register" backend-string))))))
+ ;; `vc-mtn.el' gives me:
+ ;; "Failed (status 1): mtn commit -m Testing vc-version-diff\n\n foo"
+ (skip-unless (not (memq ',backend '(Mtn))))
(vc-test--version-diff ',backend))
))))
diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el
new file mode 100644
index 00000000000..8856be79ebc
--- /dev/null
+++ b/test/lisp/x-dnd-tests.el
@@ -0,0 +1,203 @@
+;;; dnd-tests.el --- Tests for X DND support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for stuff in x-dnd.el that doesn't require a window system.
+
+;;; Code:
+
+(require 'x-dnd)
+(require 'cl-lib)
+
+(when (display-graphic-p)
+ (error "This test cannot be run under X"))
+
+;; Dummy replacements.
+
+(defconst x-dnd-tests-drag-window-xid 3948573
+ "XID of the drag window returned during the test.")
+
+(defvar x-dnd-tests-xds-property-value nil
+ "The value of the `XdndDirectSave0' window property.")
+
+(defconst x-dnd-tests-targets-table
+ (base64-decode-string
+ "bAArAKIBAAAGAB8AAABqAQAANgIAAJMCAAAFAwAABgMAAAEAkMJbAAEAINNbAAUAHwAAAGoBAAA2
+AgAAkwIAANkfAAALAB8AAABqAQAANgIAAJMCAADyAgAA2R8AANwfAADgHwAA4R8AAOIfAADjHwAA
+AQDQMAgCAQBQTggCAQCwe5IAAQDQmZIABgDyAgAA9wIAABcRAADgHwAAvSEAAI3AAAABAHC52AAB
+AGDY2AABAABq3QABAGBw3QAIAB8AAAA2AgAA8gIAANwfAADgHwAA4R8AAOIfAADjHwAAAQBwBOEA
+AQCACuEAAQAwLwUCAQDwPgUCAQBQxoQBAQCQ3YQBAQCQBYoBAQDACYoBAQCgMooBAQCgOIoBAQAf
+AAAAAQDATrcDAQAQ1LcDAQCw/sADAQAgBcEDAQBQt7oDAQAAUsIDAQCAc7wDAQAwerwDAQBAIKUE
+AQAALKUEAQDwfKUEAQDgg6UEAQCgjesEAQAAmusEAQCA7+sEAQCw9usECAAfAAAAagEAADYCAACT
+AgAABQMAAAYDAAATGwAAGhsAAA==")
+ "Predefined Motif targets table used to test the targets table parser.")
+
+(defconst x-dnd-tests-lispy-targets-table [[31 362 566 659 773 774] [6013584] [6017824]
+ [31 362 566 659 8153]
+ [31 362 566 659 754 8153 8156 8160 8161 8162 8163]
+ [34091216] [34098768] [9599920]
+ [9607632] [754 759 4375 8160 8637 49293]
+ [14203248] [14211168] [14510592]
+ [14512224] [31 566 754 8156 8160 8161 8162 8163]
+ [14746736] [14748288] [33894192] [33898224]
+ [25478736] [25484688] [25822608] [25823680]
+ [25834144] [25835680] [31] [62344896] [62379024]
+ [62979760] [62981408] [62568272] [63066624]
+ [62681984] [62683696] [77930560] [77933568]
+ [77954288] [77956064] [82546080] [82549248]
+ [82571136] [82572976] [31 362 566 659 773 774 6931 6938]]
+ "The expected result of parsing that targets table.")
+
+(defalias 'x-window-property
+ (lambda (prop &optional _frame type window-id delete-p _vector-ret-p)
+ (cond
+ ((and (equal prop "_MOTIF_DRAG_WINDOW")
+ (zerop window-id) (equal type "WINDOW"))
+ x-dnd-tests-drag-window-xid)
+ ((and (equal prop "_MOTIF_DRAG_TARGETS")
+ (equal type "_MOTIF_DRAG_TARGETS")
+ (equal window-id x-dnd-tests-drag-window-xid))
+ x-dnd-tests-targets-table)
+ ((and (equal prop "XdndDirectSave0")
+ (or (equal type "text/plain")
+ (equal type "AnyPropertyType")))
+ (prog1 x-dnd-tests-xds-property-value
+ (when delete-p
+ (setq x-dnd-tests-xds-property-value nil)))))))
+
+;; This test also serves to exercise most of the Motif value
+;; extraction code.
+(ert-deftest x-dnd-tests-read-xm-targets-table ()
+ (should (equal (x-dnd-xm-read-targets-table nil)
+ x-dnd-tests-lispy-targets-table)))
+
+;;; XDS tests.
+
+(defvar x-dnd-tests-xds-target-dir nil
+ "The name of the target directory where the file will be saved.")
+
+(defvar x-dnd-tests-xds-name nil
+ "The name that the dragged file should be saved under.")
+
+(defvar x-dnd-tests-xds-include-hostname nil
+ "Whether or not to include the hostname inside the XDS URI.")
+
+(defun x-dnd-tests-call-xds-converter ()
+ "Look up the XDS selection converter and call it.
+Return the result of the selection."
+ (let ((conv (cdr (assq 'XdndDirectSave0
+ selection-converter-alist))))
+ (should (functionp conv))
+ (funcall conv 'XdndDirectSave0 'XdndDirectSave0 nil)))
+
+(defalias 'x-begin-drag
+ (lambda (_targets &optional action frame &rest _)
+ ;; Verify that frame is either nil or a valid frame.
+ (when (and frame (not (frame-live-p frame)))
+ (signal 'wrong-type-argument frame))
+ (prog1 'XdndActionDirectSave
+ ;; Verify that the action is `XdndActionDirectSave'.
+ (should (eq action 'XdndActionDirectSave))
+ ;; Set the property value to the URI of the new file.
+ (should (and (stringp x-dnd-tests-xds-property-value)
+ (not (multibyte-string-p x-dnd-tests-xds-property-value))))
+ (let ((uri (if x-dnd-tests-xds-include-hostname
+ (format "file://%s%s" (system-name)
+ (expand-file-name x-dnd-tests-xds-property-value
+ x-dnd-tests-xds-target-dir))
+ (concat "file:///" (expand-file-name x-dnd-tests-xds-property-value
+ x-dnd-tests-xds-target-dir)))))
+ (setq x-dnd-tests-xds-property-value
+ (encode-coding-string (url-encode-url uri)
+ 'raw-text)))
+ ;; Convert the selection and verify its success.
+ (should (equal (x-dnd-tests-call-xds-converter)
+ '(STRING . "S"))))))
+
+(defalias 'x-change-window-property
+ (lambda (prop value &optional _frame type format outer-p _window-id)
+ ;; Check that the properties are the right type.
+ (should (equal prop "XdndDirectSave0"))
+ (should (equal value (encode-coding-string
+ x-dnd-tests-xds-name
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (should (equal type "text/plain"))
+ (should (equal format 8))
+ (should (not outer-p))
+ (setq x-dnd-tests-xds-property-value value)))
+
+(defalias 'x-delete-window-property
+ (lambda (&rest _args)
+ ;; This function shouldn't ever be reached during XDS.
+ (setq x-dnd-tests-xds-property-value nil)))
+
+(defun x-dnd-tests-do-direct-save-internal (include-hostname)
+ "Test the behavior of `x-dnd-do-direct-save'.
+Make it perform a direct save to a randomly generated directory,
+and check that the file exists. If INCLUDE-HOSTNAME, include the
+hostname in the target URI."
+ (let ((x-dnd-tests-xds-include-hostname include-hostname)
+ (x-dnd-tests-xds-target-dir
+ (file-name-as-directory (expand-file-name
+ (make-temp-name "x-dnd-test")
+ temporary-file-directory)))
+ (original-file (expand-file-name
+ (make-temp-name "x-dnd-test")
+ temporary-file-directory))
+ (x-dnd-tests-xds-name (make-temp-name "x-dnd-test-target")))
+ ;; The call to `gui-set-selection' is only used for providing the
+ ;; conventional `text/uri-list' target and can be ignored.
+ (cl-flet ((gui-set-selection #'ignore))
+ (unwind-protect
+ (progn
+ ;; Touch `original-file' if it doesn't exist.
+ (unless (file-exists-p original-file)
+ (write-region "" 0 original-file))
+ ;; Create `x-dnd-tests-xds-target-dir'.
+ (make-directory x-dnd-tests-xds-target-dir)
+ ;; Start the direct save and verify it returns the correct action.
+ (should (eq (x-dnd-do-direct-save original-file
+ x-dnd-tests-xds-name
+ nil nil)
+ 'XdndActionDirectSave))
+ ;; Now verify that the new file exists.
+ (should (file-exists-p
+ (expand-file-name x-dnd-tests-xds-name
+ x-dnd-tests-xds-target-dir)))
+ ;; The XDS protocol makes very clear that the window
+ ;; property must be deleted after the drag-and-drop
+ ;; operation completes.
+ (should (not x-dnd-tests-xds-property-value)))
+ ;; Clean up after ourselves.
+ (ignore-errors
+ (delete-file original-file))
+ (ignore-errors
+ (delete-directory x-dnd-tests-xds-target-dir t))))))
+
+(ert-deftest x-dnd-tests-do-direct-save ()
+ ;; TODO: add tests for application/octet-stream transfer.
+ (x-dnd-tests-do-direct-save-internal nil)
+ ;; Test with both kinds of file: URIs, since different programs
+ ;; generate different kinds.
+ (x-dnd-tests-do-direct-save-internal t))
+
+(provide 'x-dnd-tests)
+;;; x-dnd-tests.el ends here
diff --git a/test/lisp/xml-tests.el b/test/lisp/xml-tests.el
index eecf6406fb8..748f1e39446 100644
--- a/test/lisp/xml-tests.el
+++ b/test/lisp/xml-tests.el
@@ -97,7 +97,7 @@
((("FOOBAR:" . "something") nil "hi there"))
((FOOBAR:something nil "hi there"))))
"List of strings which are parsed using namespace expansion.
-Parser is called with and without 'symbol-qnames argument.")
+Parser is called with and without `symbol-qnames' argument.")
(ert-deftest xml-parse-tests ()
"Test XML parsing."
diff --git a/test/lisp/yank-media-tests.el b/test/lisp/yank-media-tests.el
new file mode 100644
index 00000000000..4487ae150da
--- /dev/null
+++ b/test/lisp/yank-media-tests.el
@@ -0,0 +1,38 @@
+;;; yank-media-tests.el --- Tests for yank-media.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'yank-media)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-utf-16 ()
+ (should-not (yank-media--utf-16-p "f"))
+ (should-not (yank-media--utf-16-p "fo"))
+ (should-not (yank-media--utf-16-p "\000ofo"))
+ (should (eq (yank-media--utf-16-p "\000o\000o") 'utf-16-be))
+ (should (eq (yank-media--utf-16-p "o\000o\000") 'utf-16-le))
+ (should-not (yank-media--utf-16-p "o\000\000o")))
+
+;;; yank-media-tests.el ends here
diff --git a/test/manual/etags/ETAGS.good_1 b/test/manual/etags/ETAGS.good_1
index 1b4f80ceaac..c3d1477d44c 100644
--- a/test/manual/etags/ETAGS.good_1
+++ b/test/manual/etags/ETAGS.good_1
@@ -915,277 +915,277 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,20276
#define EMACS_LISP_H22,801
@@ -2166,109 +2166,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/ETAGS.good_2 b/test/manual/etags/ETAGS.good_2
index 124aa7fc1cf..3c611dc8ef5 100644
--- a/test/manual/etags/ETAGS.good_2
+++ b/test/manual/etags/ETAGS.good_2
@@ -1098,288 +1098,288 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-static Lisp_Object command_loop_2 1086,33638
-static Lisp_Object top_level_1 1087,33687
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-static int read_key_sequence 1282,38800
-static void adjust_point_for_property 1284,38918
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object kbd_buffer_get_event 2152,65485
-static void record_char 2154,65597
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,33840
#define EMACS_LISP_H22,801
@@ -2735,112 +2735,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defvar etags-case-fold-search)855,33908
-(defvar etags-syntax-table)856,33940
-(defvar local-find-tag-hook)857,33968
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/ETAGS.good_3 b/test/manual/etags/ETAGS.good_3
index 9dca0084de3..45507706b32 100644
--- a/test/manual/etags/ETAGS.good_3
+++ b/test/manual/etags/ETAGS.good_3
@@ -1029,289 +1029,289 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
- KBOARD *kboard;kboard860,27088
- struct kboard_stack *next;next861,27106
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
c-src/emacs/src/lisp.h,27827
#define EMACS_LISP_H22,801
@@ -2543,109 +2543,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/ETAGS.good_4 b/test/manual/etags/ETAGS.good_4
index 8527ed726ea..dee534ae753 100644
--- a/test/manual/etags/ETAGS.good_4
+++ b/test/manual/etags/ETAGS.good_4
@@ -937,417 +937,417 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,20276
#define EMACS_LISP_H22,801
@@ -2328,109 +2328,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/ETAGS.good_5 b/test/manual/etags/ETAGS.good_5
index 6d2e44fbfe6..6410685cb30 100644
--- a/test/manual/etags/ETAGS.good_5
+++ b/test/manual/etags/ETAGS.good_5
@@ -1234,440 +1234,440 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
- KBOARD *kboard;kboard860,27088
- struct kboard_stack *next;next861,27106
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-static Lisp_Object command_loop_2 1086,33638
-static Lisp_Object top_level_1 1087,33687
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-static int read_key_sequence 1282,38800
-static void adjust_point_for_property 1284,38918
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object kbd_buffer_get_event 2152,65485
-static void record_char 2154,65597
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,41391
#define EMACS_LISP_H22,801
@@ -3274,112 +3274,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defvar etags-case-fold-search)855,33908
-(defvar etags-syntax-table)856,33940
-(defvar local-find-tag-hook)857,33968
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/ETAGS.good_6 b/test/manual/etags/ETAGS.good_6
index 9a38e20dcea..6f440a7fc95 100644
--- a/test/manual/etags/ETAGS.good_6
+++ b/test/manual/etags/ETAGS.good_6
@@ -1234,440 +1234,440 @@ record_auto_save 742,23849
force_auto_save_soon 751,24017
DEFUN ("recursive-edit", Frecursive_edit,759,24138
DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138
-recursive_edit_unwind 804,25748
-any_kboard_state 817,26014
-single_kboard_state 838,26666
-not_single_kboard_state 848,26804
-struct kboard_stack858,27066
- KBOARD *kboard;kboard860,27088
- struct kboard_stack *next;next861,27106
-static struct kboard_stack *kboard_stack;kboard_stack864,27139
-push_kboard 867,27187
-pop_kboard 879,27376
-temporarily_switch_to_single_kboard 914,28264
-record_single_kboard_state 943,29438
-restore_kboard_configuration 952,29622
-cmd_error 970,30078
-cmd_error_internal 1024,31511
-DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031
-DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031
-static Lisp_Object command_loop_2 1086,33638
-static Lisp_Object top_level_1 1087,33687
-command_loop 1094,33917
-command_loop_2 1134,35136
-top_level_2 1146,35340
-top_level_1 1152,35418
-DEFUN ("top-level", Ftop_level,1164,35788
-DEFUN ("top-level", Ftop_level,top-level1164,35788
-user_error 1183,36289
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430
-DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820
-DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820
-tracking_off 1216,37282
-DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817
-DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817
-bool ignore_mouse_drag_p;1256,38393
-some_mouse_moved 1259,38442
-static int read_key_sequence 1282,38800
-static void adjust_point_for_property 1284,38918
-Lisp_Object last_undo_boundary;1287,39033
-command_loop_1 1294,39274
-read_menu_command 1649,50890
-adjust_point_for_property 1678,51618
-safe_run_hooks_1 1831,57340
-safe_run_hooks_error 1841,57570
-safe_run_hook_funcall 1878,58577
-safe_run_hooks 1893,59059
-int poll_suppress_count;1908,59398
-static struct atimer *poll_timer;poll_timer1915,59488
-poll_for_input_1 1919,59590
-poll_for_input 1930,59790
-start_polling 1942,60054
-input_polling_used 1979,61092
-stop_polling 1994,61391
-set_poll_suppress_count 2009,61760
-bind_polling_period 2029,62142
-make_ctrl_char 2048,62493
-show_help_echo 2113,64456
-static Lisp_Object kbd_buffer_get_event 2152,65485
-static void record_char 2154,65597
-static Lisp_Object help_form_saved_window_configs;2156,65639
-read_char_help_form_unwind 2158,65702
-#define STOP_POLLING 2166,65960
-#define RESUME_POLLING 2170,66085
-read_event_from_main_queue 2175,66230
-read_decoded_event_from_main_queue 2249,68418
-#define MAX_ENCODED_BYTES 2254,68665
-echo_keystrokes_p 2342,71557
-read_char 2376,72849
-record_menu_key 3225,98950
-help_char_p 3258,99675
-record_char 3273,99954
-save_getcjmp 3412,104236
-restore_getcjmp 3418,104327
-readable_events 3430,104698
-int stop_character EXTERNALLY_VISIBLE;3497,106438
-event_to_kboard 3500,106494
-kbd_buffer_nr_stored 3522,107143
-kbd_buffer_store_event 3534,107484
-kbd_buffer_store_event_hold 3550,108026
-kbd_buffer_unget_event 3684,111618
-#define INPUT_EVENT_POS_MAX 3698,112019
-#define INPUT_EVENT_POS_MIN 3701,112148
-position_to_Time 3706,112288
-Time_to_position 3716,112515
-gen_help_event 3738,113172
-kbd_buffer_store_help_event 3756,113612
-discard_mouse_events 3773,113977
-kbd_buffer_events_waiting 3803,114712
-clear_event 3823,115069
-kbd_buffer_get_event 3836,115409
-process_special_events 4258,127882
-swallow_events 4322,129706
-timer_start_idle 4339,130099
-timer_stop_idle 4355,130577
-timer_resume_idle 4363,130721
-struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913
-Lisp_Object pending_funcalls;4377,131173
-decode_timer 4381,131294
-timer_check_2 4414,132247
-timer_check 4572,136818
-DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663
-DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663
-static Lisp_Object accent_key_syms;4625,138240
-static Lisp_Object func_key_syms;4626,138276
-static Lisp_Object mouse_syms;4627,138310
-static Lisp_Object wheel_syms;4628,138341
-static Lisp_Object drag_n_drop_syms;4629,138372
-static const int lispy_accent_codes[lispy_accent_codes4634,138517
-static const char *const lispy_accent_keys[lispy_accent_keys4741,139879
-#define FUNCTION_KEY_OFFSET 4766,140315
-const char *const lispy_function_keys[lispy_function_keys4768,140348
-static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902
-static const char *const lispy_kana_keys[lispy_kana_keys5026,150136
-#define FUNCTION_KEY_OFFSET 5061,151752
-static const char *const lispy_function_keys[lispy_function_keys5065,151895
-#define ISO_FUNCTION_KEY_OFFSET 5149,154430
-static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470
-static Lisp_Object Vlispy_mouse_stem;5172,155329
-static const char *const lispy_wheel_names[lispy_wheel_names5174,155368
-static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620
-static short const scroll_bar_parts[scroll_bar_parts5189,155886
-static Lisp_Object button_down_location;5210,156911
-static int last_mouse_button;5215,157066
-static int last_mouse_x;5216,157096
-static int last_mouse_y;5217,157121
-static Time button_down_time;5218,157146
-static int double_click_count;5222,157230
-make_lispy_position 5228,157391
-toolkit_menubar_in_use 5456,163954
-make_scroll_bar_position 5469,164322
-make_lispy_event 5485,164968
-make_lispy_movement 6104,183531
-make_lispy_switch_frame 6131,184262
-make_lispy_focus_in 6137,184369
-make_lispy_focus_out 6145,184495
-parse_modifiers_uncached 6163,184945
-#define SINGLE_LETTER_MOD(6185,185465
-#undef SINGLE_LETTER_MOD6212,185906
-#define MULTI_LETTER_MOD(6214,185932
-#undef MULTI_LETTER_MOD6231,186400
-apply_modifiers_uncached 6273,187574
-static const char *const modifier_names[modifier_names6319,189193
-#define NUM_MOD_NAMES 6325,189399
-static Lisp_Object modifier_symbols;6327,189449
-lispy_modifier_list 6331,189586
-#define KEY_TO_CHAR(6353,190252
-parse_modifiers 6356,190328
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517
-DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517
-apply_modifiers 6422,192391
-reorder_modifiers 6491,194720
-modify_event_symbol 6536,196528
-DEFUN ("event-convert-list", Fevent_convert_list,6628,199244
-DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244
-parse_solitary_modifier 6695,201135
-#define SINGLE_LETTER_MOD(6701,201258
-#define MULTI_LETTER_MOD(6705,201343
-#undef SINGLE_LETTER_MOD6763,202641
-#undef MULTI_LETTER_MOD6764,202666
-lucid_event_type_list_p 6775,202889
-get_input_pending 6814,203960
-record_asynch_buffer_change 6834,204579
-gobble_input 6872,205702
-tty_read_avail_input 6967,208310
-handle_async_input 7149,214039
-process_pending_signals 7165,214359
-unblock_input_to 7177,214645
-unblock_input 7200,215277
-totally_unblock_input 7209,215445
-handle_input_available_signal 7217,215529
-deliver_input_available_signal 7226,215700
-struct user_signal_info7235,215865
- int sig;7238,215915
- char *name;name7241,215956
- int npending;7244,216007
- struct user_signal_info *next;next7246,216024
-static struct user_signal_info *user_signals user_signals7250,216090
-add_user_signal 7253,216149
-handle_user_signal 7275,216598
-deliver_user_signal 7316,217558
-find_user_signal_name 7322,217659
-store_user_signal_events 7334,217841
-static void menu_bar_item 7362,218341
-static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416
-static Lisp_Object menu_bar_items_vector;7368,218630
-static int menu_bar_items_index;7369,218672
-static const char *separator_names[separator_names7372,218707
-menu_separator_name_p 7393,219148
-menu_bar_items 7426,219852
-Lisp_Object item_properties;7568,224603
-menu_bar_item 7571,224645
-menu_item_eval_property_1 7647,227175
-eval_dyn 7658,227465
-menu_item_eval_property 7666,227675
-parse_menu_item 7686,228341
-static Lisp_Object tool_bar_items_vector;7965,236336
-static Lisp_Object tool_bar_item_properties;7970,236510
-static int ntool_bar_items;7974,236606
-static void init_tool_bar_items 7978,236664
-static void process_tool_bar_item 7979,236711
-static bool parse_tool_bar_item 7981,236801
-static void append_tool_bar_item 7982,236861
-tool_bar_items 7990,237083
-process_tool_bar_item 8075,239892
-#define PROP(8112,240969
-set_prop 8114,241038
-parse_tool_bar_item 8167,242453
-#undef PROP8379,248844
-init_tool_bar_items 8387,248969
-append_tool_bar_item 8401,249261
-read_char_x_menu_prompt 8443,250771
-read_char_minibuf_menu_prompt 8503,252445
-#define PUSH_C_STR(8527,253014
-follow_key 8726,258553
-active_maps 8733,258695
-typedef struct keyremap8742,259021
- Lisp_Object parent;8745,259107
- Lisp_Object map;8748,259224
- int start,8753,259446
- int start, end;8753,259446
-} keyremap;8754,259464
-access_keymap_keyremap 8764,259808
-keyremap_step 8811,261450
-test_undefined 8867,262934
-read_key_sequence 8916,264861
-read_key_sequence_vs 9826,295821
-DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294
-DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982
-detect_input_pending 9950,300488
-detect_input_pending_ignore_squeezables 9959,300654
-detect_input_pending_run_timers 9967,300870
-clear_input_pending 9985,301362
-requeued_events_pending_p 9997,301732
-DEFUN ("input-pending-p", Finput_pending_p,10002,301813
-DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813
-DEFUN ("recent-keys", Frecent_keys,10024,302596
-DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596
-DEFUN ("this-command-keys", Fthis_command_keys,10055,303517
-DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958
-DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380
-DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955
-DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495
-DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510
-DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510
-DEFUN ("recursion-depth", Frecursion_depth,10158,307069
-DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069
-DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406
-DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406
-DEFUN ("discard-input", Fdiscard_input,10203,308447
-DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447
-DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949
-DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949
-stuff_buffered_input 10285,311045
-set_waiting_for_input 10323,312016
-clear_waiting_for_input 10337,312390
-handle_interrupt_signal 10351,312754
-deliver_interrupt_signal 10378,313642
-static int volatile force_quit_count;10387,313932
-handle_interrupt 10401,314414
-quit_throw_to_read_char 10541,318711
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288
-DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288
-DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516
-DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432
-DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432
-DEFUN ("set-quit-char", Fset_quit_char,10694,322706
-DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706
-DEFUN ("set-input-mode", Fset_input_mode,10729,323570
-DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570
-DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459
-DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459
-DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837
-DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837
-DEFUN ("posn-at-point", Fposn_at_point,10824,327060
-DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060
-init_kboard 10861,328214
-allocate_kboard 10893,329284
-wipe_kboard 10909,329637
-delete_kboard 10917,329751
-init_keyboard 10942,330281
-struct event_head11021,332696
- short var;11023,332716
- short kind;11024,332729
-static const struct event_head head_table[head_table11027,332747
-syms_of_keyboard 11045,333577
- DEFVAR_LISP ("internal--top-level-message"11058,333972
- DEFVAR_LISP ("last-command-event"11312,342173
- DEFVAR_LISP ("last-nonmenu-event"11315,342297
- DEFVAR_LISP ("last-input-event"11321,342636
- DEFVAR_LISP ("unread-command-events"11324,342730
- DEFVAR_LISP ("unread-post-input-method-events"11332,343190
- DEFVAR_LISP ("unread-input-method-events"11338,343529
- DEFVAR_LISP ("meta-prefix-char"11346,343898
- DEFVAR_KBOARD ("last-command"11351,344106
- DEFVAR_KBOARD ("real-last-command"11368,344787
- DEFVAR_KBOARD ("last-repeatable-command"11372,344973
- DEFVAR_LISP ("this-command"11378,345261
- DEFVAR_LISP ("real-this-command"11384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680
- DEFVAR_LISP ("this-original-command"11396,346123
- DEFVAR_INT ("auto-save-interval"11403,346520
- DEFVAR_LISP ("auto-save-timeout"11408,346734
- DEFVAR_LISP ("echo-keystrokes"11415,347079
- DEFVAR_INT ("polling-period"11421,347350
- DEFVAR_LISP ("double-click-time"11428,347693
- DEFVAR_INT ("double-click-fuzz"11435,348029
- DEFVAR_INT ("num-input-keys"11446,348519
- DEFVAR_INT ("num-nonmacro-input-events"11452,348794
- DEFVAR_LISP ("last-event-frame"11457,349032
- DEFVAR_LISP ("tty-erase-char"11463,349311
- DEFVAR_LISP ("help-char"11466,349434
- DEFVAR_LISP ("help-event-list"11472,349717
- DEFVAR_LISP ("help-form"11477,349928
- DEFVAR_LISP ("prefix-help-command"11483,350176
- DEFVAR_LISP ("top-level"11489,350454
- DEFVAR_KBOARD ("keyboard-translate-table"11495,350675
- DEFVAR_BOOL ("cannot-suspend"11511,351488
- DEFVAR_BOOL ("menu-prompting"11516,351715
- DEFVAR_LISP ("menu-prompt-more-char"11526,352145
- DEFVAR_INT ("extra-keyboard-modifiers"11531,352391
- DEFVAR_LISP ("deactivate-mark"11545,353117
- DEFVAR_LISP ("pre-command-hook"11553,353486
- DEFVAR_LISP ("post-command-hook"11560,353841
- DEFVAR_LISP ("echo-area-clear-hook"11568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419
- DEFVAR_LISP ("menu-bar-final-items"11578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230
- DEFVAR_LISP ("overriding-local-map"11598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103
- DEFVAR_LISP ("special-event-map"11613,356442
- DEFVAR_LISP ("track-mouse"11617,356630
- DEFVAR_KBOARD ("system-key-alist"11620,356757
- DEFVAR_KBOARD ("local-function-key-map"11629,357138
- DEFVAR_KBOARD ("input-decode-map"11658,358597
- DEFVAR_LISP ("function-key-map"11675,359385
- DEFVAR_LISP ("key-translation-map"11683,359801
- DEFVAR_LISP ("deferred-action-list"11689,360145
- DEFVAR_LISP ("deferred-action-function"11694,360393
- DEFVAR_LISP ("delayed-warnings-list"11700,360692
- DEFVAR_LISP ("timer-list"11708,361100
- DEFVAR_LISP ("timer-idle-list"11712,361252
- DEFVAR_LISP ("input-method-function"11716,361415
- DEFVAR_LISP ("input-method-previous-message"11737,362384
- DEFVAR_LISP ("show-help-function"11744,362745
- DEFVAR_LISP ("disable-point-adjustment"11749,362977
- DEFVAR_LISP ("global-disable-point-adjustment"11761,363527
- DEFVAR_LISP ("minibuffer-message-timeout"11770,363893
- DEFVAR_LISP ("throw-on-input"11775,364171
- DEFVAR_LISP ("command-error-function"11781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909
- DEFVAR_LISP ("select-active-regions"11798,365236
- DEFVAR_LISP ("saved-region-selection"11807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013
- DEFVAR_LISP ("debug-on-event"11825,366554
-keys_of_keyboard 11841,367115
-mark_kboards 11916,370434
- DEFVAR_LISP ("internal--top-level-message",\111058,333972
- DEFVAR_LISP ("last-command-event",\111312,342173
- DEFVAR_LISP ("last-nonmenu-event",\111315,342297
- DEFVAR_LISP ("last-input-event",\111321,342636
- DEFVAR_LISP ("unread-command-events",\111324,342730
- DEFVAR_LISP ("unread-post-input-method-events",\111332,343190
- DEFVAR_LISP ("unread-input-method-events",\111338,343529
- DEFVAR_LISP ("meta-prefix-char",\111346,343898
- DEFVAR_KBOARD ("last-command",\111351,344106
- DEFVAR_KBOARD ("real-last-command",\111368,344787
- DEFVAR_KBOARD ("last-repeatable-command",\111372,344973
- DEFVAR_LISP ("this-command",\111378,345261
- DEFVAR_LISP ("real-this-command",\111384,345498
- DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680
- DEFVAR_LISP ("this-original-command",\111396,346123
- DEFVAR_INT ("auto-save-interval",\111403,346520
- DEFVAR_LISP ("auto-save-timeout",\111408,346734
- DEFVAR_LISP ("echo-keystrokes",\111415,347079
- DEFVAR_INT ("polling-period",\111421,347350
- DEFVAR_LISP ("double-click-time",\111428,347693
- DEFVAR_INT ("double-click-fuzz",\111435,348029
- DEFVAR_INT ("num-input-keys",\111446,348519
- DEFVAR_INT ("num-nonmacro-input-events",\111452,348794
- DEFVAR_LISP ("last-event-frame",\111457,349032
- DEFVAR_LISP ("tty-erase-char",\111463,349311
- DEFVAR_LISP ("help-char",\111466,349434
- DEFVAR_LISP ("help-event-list",\111472,349717
- DEFVAR_LISP ("help-form",\111477,349928
- DEFVAR_LISP ("prefix-help-command",\111483,350176
- DEFVAR_LISP ("top-level",\111489,350454
- DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675
- DEFVAR_BOOL ("cannot-suspend",\111511,351488
- DEFVAR_BOOL ("menu-prompting",\111516,351715
- DEFVAR_LISP ("menu-prompt-more-char",\111526,352145
- DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391
- DEFVAR_LISP ("deactivate-mark",\111545,353117
- DEFVAR_LISP ("pre-command-hook",\111553,353486
- DEFVAR_LISP ("post-command-hook",\111560,353841
- DEFVAR_LISP ("echo-area-clear-hook",\111568,354204
- DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419
- DEFVAR_LISP ("menu-bar-final-items",\111578,354622
- DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872
- DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230
- DEFVAR_LISP ("overriding-local-map",\111598,355652
- DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103
- DEFVAR_LISP ("special-event-map",\111613,356442
- DEFVAR_LISP ("track-mouse",\111617,356630
- DEFVAR_KBOARD ("system-key-alist",\111620,356757
- DEFVAR_KBOARD ("local-function-key-map",\111629,357138
- DEFVAR_KBOARD ("input-decode-map",\111658,358597
- DEFVAR_LISP ("function-key-map",\111675,359385
- DEFVAR_LISP ("key-translation-map",\111683,359801
- DEFVAR_LISP ("deferred-action-list",\111689,360145
- DEFVAR_LISP ("deferred-action-function",\111694,360393
- DEFVAR_LISP ("delayed-warnings-list",\111700,360692
- DEFVAR_LISP ("timer-list",\111708,361100
- DEFVAR_LISP ("timer-idle-list",\111712,361252
- DEFVAR_LISP ("input-method-function",\111716,361415
- DEFVAR_LISP ("input-method-previous-message",\111737,362384
- DEFVAR_LISP ("show-help-function",\111744,362745
- DEFVAR_LISP ("disable-point-adjustment",\111749,362977
- DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527
- DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893
- DEFVAR_LISP ("throw-on-input",\111775,364171
- DEFVAR_LISP ("command-error-function",\111781,364422
- DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909
- DEFVAR_LISP ("select-active-regions",\111798,365236
- DEFVAR_LISP ("saved-region-selection",\111807,365628
- DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013
- DEFVAR_LISP ("debug-on-event",\111825,366554
+recursive_edit_unwind 804,25751
+any_kboard_state 817,26017
+single_kboard_state 838,26669
+not_single_kboard_state 848,26807
+struct kboard_stack858,27069
+ KBOARD *kboard;kboard860,27091
+ struct kboard_stack *next;next861,27109
+static struct kboard_stack *kboard_stack;kboard_stack864,27142
+push_kboard 867,27190
+pop_kboard 879,27379
+temporarily_switch_to_single_kboard 914,28267
+record_single_kboard_state 943,29441
+restore_kboard_configuration 952,29625
+cmd_error 970,30081
+cmd_error_internal 1024,31514
+DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034
+DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034
+static Lisp_Object command_loop_2 1086,33641
+static Lisp_Object top_level_1 1087,33690
+command_loop 1094,33920
+command_loop_2 1134,35139
+top_level_2 1146,35343
+top_level_1 1152,35421
+DEFUN ("top-level", Ftop_level,1164,35791
+DEFUN ("top-level", Ftop_level,top-level1164,35791
+user_error 1183,36292
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433
+DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823
+DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823
+tracking_off 1216,37285
+DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820
+DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820
+bool ignore_mouse_drag_p;1256,38396
+some_mouse_moved 1259,38445
+static int read_key_sequence 1282,38803
+static void adjust_point_for_property 1284,38921
+Lisp_Object last_undo_boundary;1287,39036
+command_loop_1 1294,39277
+read_menu_command 1649,50893
+adjust_point_for_property 1678,51621
+safe_run_hooks_1 1831,57343
+safe_run_hooks_error 1841,57573
+safe_run_hook_funcall 1878,58580
+safe_run_hooks 1893,59062
+int poll_suppress_count;1908,59401
+static struct atimer *poll_timer;poll_timer1915,59491
+poll_for_input_1 1919,59593
+poll_for_input 1930,59793
+start_polling 1942,60057
+input_polling_used 1979,61095
+stop_polling 1994,61394
+set_poll_suppress_count 2009,61763
+bind_polling_period 2029,62145
+make_ctrl_char 2048,62496
+show_help_echo 2113,64459
+static Lisp_Object kbd_buffer_get_event 2152,65488
+static void record_char 2154,65600
+static Lisp_Object help_form_saved_window_configs;2156,65642
+read_char_help_form_unwind 2158,65705
+#define STOP_POLLING 2166,65963
+#define RESUME_POLLING 2170,66088
+read_event_from_main_queue 2175,66233
+read_decoded_event_from_main_queue 2249,68421
+#define MAX_ENCODED_BYTES 2254,68668
+echo_keystrokes_p 2342,71560
+read_char 2376,72852
+record_menu_key 3225,98953
+help_char_p 3258,99678
+record_char 3273,99957
+save_getcjmp 3412,104239
+restore_getcjmp 3418,104330
+readable_events 3430,104701
+int stop_character EXTERNALLY_VISIBLE;3497,106441
+event_to_kboard 3500,106497
+kbd_buffer_nr_stored 3522,107146
+kbd_buffer_store_event 3534,107487
+kbd_buffer_store_event_hold 3550,108029
+kbd_buffer_unget_event 3684,111621
+#define INPUT_EVENT_POS_MAX 3698,112022
+#define INPUT_EVENT_POS_MIN 3701,112151
+position_to_Time 3706,112291
+Time_to_position 3716,112518
+gen_help_event 3738,113175
+kbd_buffer_store_help_event 3756,113615
+discard_mouse_events 3773,113980
+kbd_buffer_events_waiting 3803,114715
+clear_event 3823,115072
+kbd_buffer_get_event 3836,115412
+process_special_events 4258,127885
+swallow_events 4322,129709
+timer_start_idle 4339,130102
+timer_stop_idle 4355,130580
+timer_resume_idle 4363,130724
+struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916
+Lisp_Object pending_funcalls;4377,131176
+decode_timer 4381,131297
+timer_check_2 4414,132250
+timer_check 4572,136821
+DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666
+DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666
+static Lisp_Object accent_key_syms;4625,138243
+static Lisp_Object func_key_syms;4626,138279
+static Lisp_Object mouse_syms;4627,138313
+static Lisp_Object wheel_syms;4628,138344
+static Lisp_Object drag_n_drop_syms;4629,138375
+static const int lispy_accent_codes[lispy_accent_codes4634,138520
+static const char *const lispy_accent_keys[lispy_accent_keys4741,139882
+#define FUNCTION_KEY_OFFSET 4766,140318
+const char *const lispy_function_keys[lispy_function_keys4768,140351
+static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905
+static const char *const lispy_kana_keys[lispy_kana_keys5026,150139
+#define FUNCTION_KEY_OFFSET 5061,151755
+static const char *const lispy_function_keys[lispy_function_keys5065,151898
+#define ISO_FUNCTION_KEY_OFFSET 5149,154433
+static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473
+static Lisp_Object Vlispy_mouse_stem;5172,155332
+static const char *const lispy_wheel_names[lispy_wheel_names5174,155371
+static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623
+static short const scroll_bar_parts[scroll_bar_parts5189,155889
+static Lisp_Object button_down_location;5210,156914
+static int last_mouse_button;5215,157069
+static int last_mouse_x;5216,157099
+static int last_mouse_y;5217,157124
+static Time button_down_time;5218,157149
+static int double_click_count;5222,157233
+make_lispy_position 5228,157394
+toolkit_menubar_in_use 5456,163957
+make_scroll_bar_position 5469,164325
+make_lispy_event 5485,164971
+make_lispy_movement 6104,183534
+make_lispy_switch_frame 6131,184265
+make_lispy_focus_in 6137,184372
+make_lispy_focus_out 6145,184498
+parse_modifiers_uncached 6163,184948
+#define SINGLE_LETTER_MOD(6185,185468
+#undef SINGLE_LETTER_MOD6212,185909
+#define MULTI_LETTER_MOD(6214,185935
+#undef MULTI_LETTER_MOD6231,186403
+apply_modifiers_uncached 6273,187577
+static const char *const modifier_names[modifier_names6319,189196
+#define NUM_MOD_NAMES 6325,189402
+static Lisp_Object modifier_symbols;6327,189452
+lispy_modifier_list 6331,189589
+#define KEY_TO_CHAR(6353,190255
+parse_modifiers 6356,190331
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520
+apply_modifiers 6422,192394
+reorder_modifiers 6491,194723
+modify_event_symbol 6536,196531
+DEFUN ("event-convert-list", Fevent_convert_list,6628,199247
+DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247
+parse_solitary_modifier 6695,201138
+#define SINGLE_LETTER_MOD(6701,201261
+#define MULTI_LETTER_MOD(6705,201346
+#undef SINGLE_LETTER_MOD6763,202644
+#undef MULTI_LETTER_MOD6764,202669
+lucid_event_type_list_p 6775,202892
+get_input_pending 6814,203963
+record_asynch_buffer_change 6834,204582
+gobble_input 6872,205705
+tty_read_avail_input 6967,208313
+handle_async_input 7149,214042
+process_pending_signals 7165,214362
+unblock_input_to 7177,214648
+unblock_input 7200,215280
+totally_unblock_input 7209,215448
+handle_input_available_signal 7217,215532
+deliver_input_available_signal 7226,215703
+struct user_signal_info7235,215868
+ int sig;7238,215918
+ char *name;name7241,215959
+ int npending;7244,216010
+ struct user_signal_info *next;next7246,216027
+static struct user_signal_info *user_signals user_signals7250,216093
+add_user_signal 7253,216152
+handle_user_signal 7275,216601
+deliver_user_signal 7316,217561
+find_user_signal_name 7322,217662
+store_user_signal_events 7334,217844
+static void menu_bar_item 7362,218344
+static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419
+static Lisp_Object menu_bar_items_vector;7368,218633
+static int menu_bar_items_index;7369,218675
+static const char *separator_names[separator_names7372,218710
+menu_separator_name_p 7393,219151
+menu_bar_items 7426,219855
+Lisp_Object item_properties;7568,224606
+menu_bar_item 7571,224648
+menu_item_eval_property_1 7647,227178
+eval_dyn 7658,227468
+menu_item_eval_property 7666,227678
+parse_menu_item 7686,228344
+static Lisp_Object tool_bar_items_vector;7965,236339
+static Lisp_Object tool_bar_item_properties;7970,236513
+static int ntool_bar_items;7974,236609
+static void init_tool_bar_items 7978,236667
+static void process_tool_bar_item 7979,236714
+static bool parse_tool_bar_item 7981,236804
+static void append_tool_bar_item 7982,236864
+tool_bar_items 7990,237086
+process_tool_bar_item 8075,239895
+#define PROP(8112,240972
+set_prop 8114,241041
+parse_tool_bar_item 8167,242456
+#undef PROP8379,248847
+init_tool_bar_items 8387,248972
+append_tool_bar_item 8401,249264
+read_char_x_menu_prompt 8443,250774
+read_char_minibuf_menu_prompt 8503,252448
+#define PUSH_C_STR(8527,253017
+follow_key 8726,258556
+active_maps 8733,258698
+typedef struct keyremap8742,259024
+ Lisp_Object parent;8745,259110
+ Lisp_Object map;8748,259227
+ int start,8753,259449
+ int start, end;8753,259449
+} keyremap;8754,259467
+access_keymap_keyremap 8764,259811
+keyremap_step 8811,261453
+test_undefined 8867,262937
+read_key_sequence 8916,264864
+read_key_sequence_vs 9826,295824
+DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297
+DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985
+detect_input_pending 9950,300491
+detect_input_pending_ignore_squeezables 9959,300657
+detect_input_pending_run_timers 9967,300873
+clear_input_pending 9985,301365
+requeued_events_pending_p 9997,301735
+DEFUN ("input-pending-p", Finput_pending_p,10002,301816
+DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816
+DEFUN ("recent-keys", Frecent_keys,10024,302599
+DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599
+DEFUN ("this-command-keys", Fthis_command_keys,10055,303520
+DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961
+DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383
+DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498
+DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513
+DEFUN ("recursion-depth", Frecursion_depth,10158,307072
+DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072
+DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409
+DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409
+DEFUN ("discard-input", Fdiscard_input,10203,308450
+DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450
+DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952
+DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952
+stuff_buffered_input 10285,311048
+set_waiting_for_input 10323,312019
+clear_waiting_for_input 10337,312393
+handle_interrupt_signal 10351,312757
+deliver_interrupt_signal 10378,313645
+static int volatile force_quit_count;10387,313935
+handle_interrupt 10401,314417
+quit_throw_to_read_char 10541,318714
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291
+DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291
+DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519
+DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435
+DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435
+DEFUN ("set-quit-char", Fset_quit_char,10694,322709
+DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709
+DEFUN ("set-input-mode", Fset_input_mode,10729,323573
+DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573
+DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462
+DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462
+DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840
+DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840
+DEFUN ("posn-at-point", Fposn_at_point,10824,327063
+DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063
+init_kboard 10861,328217
+allocate_kboard 10893,329287
+wipe_kboard 10909,329640
+delete_kboard 10917,329754
+init_keyboard 10942,330284
+struct event_head11021,332699
+ short var;11023,332719
+ short kind;11024,332732
+static const struct event_head head_table[head_table11027,332750
+syms_of_keyboard 11045,333580
+ DEFVAR_LISP ("internal--top-level-message"11058,333975
+ DEFVAR_LISP ("last-command-event"11312,342176
+ DEFVAR_LISP ("last-nonmenu-event"11315,342300
+ DEFVAR_LISP ("last-input-event"11321,342639
+ DEFVAR_LISP ("unread-command-events"11324,342733
+ DEFVAR_LISP ("unread-post-input-method-events"11332,343193
+ DEFVAR_LISP ("unread-input-method-events"11338,343532
+ DEFVAR_LISP ("meta-prefix-char"11346,343901
+ DEFVAR_KBOARD ("last-command"11351,344109
+ DEFVAR_KBOARD ("real-last-command"11368,344790
+ DEFVAR_KBOARD ("last-repeatable-command"11372,344976
+ DEFVAR_LISP ("this-command"11378,345264
+ DEFVAR_LISP ("real-this-command"11384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683
+ DEFVAR_LISP ("this-original-command"11396,346126
+ DEFVAR_INT ("auto-save-interval"11403,346523
+ DEFVAR_LISP ("auto-save-timeout"11408,346737
+ DEFVAR_LISP ("echo-keystrokes"11415,347082
+ DEFVAR_INT ("polling-period"11421,347353
+ DEFVAR_LISP ("double-click-time"11428,347696
+ DEFVAR_INT ("double-click-fuzz"11435,348032
+ DEFVAR_INT ("num-input-keys"11446,348522
+ DEFVAR_INT ("num-nonmacro-input-events"11452,348797
+ DEFVAR_LISP ("last-event-frame"11457,349035
+ DEFVAR_LISP ("tty-erase-char"11463,349314
+ DEFVAR_LISP ("help-char"11466,349437
+ DEFVAR_LISP ("help-event-list"11472,349720
+ DEFVAR_LISP ("help-form"11477,349931
+ DEFVAR_LISP ("prefix-help-command"11483,350179
+ DEFVAR_LISP ("top-level"11489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table"11495,350678
+ DEFVAR_BOOL ("cannot-suspend"11511,351491
+ DEFVAR_BOOL ("menu-prompting"11516,351718
+ DEFVAR_LISP ("menu-prompt-more-char"11526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers"11531,352394
+ DEFVAR_LISP ("deactivate-mark"11545,353120
+ DEFVAR_LISP ("pre-command-hook"11553,353489
+ DEFVAR_LISP ("post-command-hook"11560,353844
+ DEFVAR_LISP ("echo-area-clear-hook"11568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422
+ DEFVAR_LISP ("menu-bar-final-items"11578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233
+ DEFVAR_LISP ("overriding-local-map"11598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106
+ DEFVAR_LISP ("special-event-map"11613,356445
+ DEFVAR_LISP ("track-mouse"11617,356633
+ DEFVAR_KBOARD ("system-key-alist"11620,356760
+ DEFVAR_KBOARD ("local-function-key-map"11629,357141
+ DEFVAR_KBOARD ("input-decode-map"11658,358600
+ DEFVAR_LISP ("function-key-map"11675,359388
+ DEFVAR_LISP ("key-translation-map"11683,359804
+ DEFVAR_LISP ("deferred-action-list"11689,360148
+ DEFVAR_LISP ("deferred-action-function"11694,360396
+ DEFVAR_LISP ("delayed-warnings-list"11700,360695
+ DEFVAR_LISP ("timer-list"11708,361103
+ DEFVAR_LISP ("timer-idle-list"11712,361255
+ DEFVAR_LISP ("input-method-function"11716,361418
+ DEFVAR_LISP ("input-method-previous-message"11737,362387
+ DEFVAR_LISP ("show-help-function"11744,362748
+ DEFVAR_LISP ("disable-point-adjustment"11749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment"11761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout"11770,363896
+ DEFVAR_LISP ("throw-on-input"11775,364174
+ DEFVAR_LISP ("command-error-function"11781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912
+ DEFVAR_LISP ("select-active-regions"11798,365239
+ DEFVAR_LISP ("saved-region-selection"11807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016
+ DEFVAR_LISP ("debug-on-event"11825,366557
+keys_of_keyboard 11841,367118
+mark_kboards 11916,370437
+ DEFVAR_LISP ("internal--top-level-message",\111058,333975
+ DEFVAR_LISP ("last-command-event",\111312,342176
+ DEFVAR_LISP ("last-nonmenu-event",\111315,342300
+ DEFVAR_LISP ("last-input-event",\111321,342639
+ DEFVAR_LISP ("unread-command-events",\111324,342733
+ DEFVAR_LISP ("unread-post-input-method-events",\111332,343193
+ DEFVAR_LISP ("unread-input-method-events",\111338,343532
+ DEFVAR_LISP ("meta-prefix-char",\111346,343901
+ DEFVAR_KBOARD ("last-command",\111351,344109
+ DEFVAR_KBOARD ("real-last-command",\111368,344790
+ DEFVAR_KBOARD ("last-repeatable-command",\111372,344976
+ DEFVAR_LISP ("this-command",\111378,345264
+ DEFVAR_LISP ("real-this-command",\111384,345501
+ DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683
+ DEFVAR_LISP ("this-original-command",\111396,346126
+ DEFVAR_INT ("auto-save-interval",\111403,346523
+ DEFVAR_LISP ("auto-save-timeout",\111408,346737
+ DEFVAR_LISP ("echo-keystrokes",\111415,347082
+ DEFVAR_INT ("polling-period",\111421,347353
+ DEFVAR_LISP ("double-click-time",\111428,347696
+ DEFVAR_INT ("double-click-fuzz",\111435,348032
+ DEFVAR_INT ("num-input-keys",\111446,348522
+ DEFVAR_INT ("num-nonmacro-input-events",\111452,348797
+ DEFVAR_LISP ("last-event-frame",\111457,349035
+ DEFVAR_LISP ("tty-erase-char",\111463,349314
+ DEFVAR_LISP ("help-char",\111466,349437
+ DEFVAR_LISP ("help-event-list",\111472,349720
+ DEFVAR_LISP ("help-form",\111477,349931
+ DEFVAR_LISP ("prefix-help-command",\111483,350179
+ DEFVAR_LISP ("top-level",\111489,350457
+ DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678
+ DEFVAR_BOOL ("cannot-suspend",\111511,351491
+ DEFVAR_BOOL ("menu-prompting",\111516,351718
+ DEFVAR_LISP ("menu-prompt-more-char",\111526,352148
+ DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394
+ DEFVAR_LISP ("deactivate-mark",\111545,353120
+ DEFVAR_LISP ("pre-command-hook",\111553,353489
+ DEFVAR_LISP ("post-command-hook",\111560,353844
+ DEFVAR_LISP ("echo-area-clear-hook",\111568,354207
+ DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422
+ DEFVAR_LISP ("menu-bar-final-items",\111578,354625
+ DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875
+ DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233
+ DEFVAR_LISP ("overriding-local-map",\111598,355655
+ DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106
+ DEFVAR_LISP ("special-event-map",\111613,356445
+ DEFVAR_LISP ("track-mouse",\111617,356633
+ DEFVAR_KBOARD ("system-key-alist",\111620,356760
+ DEFVAR_KBOARD ("local-function-key-map",\111629,357141
+ DEFVAR_KBOARD ("input-decode-map",\111658,358600
+ DEFVAR_LISP ("function-key-map",\111675,359388
+ DEFVAR_LISP ("key-translation-map",\111683,359804
+ DEFVAR_LISP ("deferred-action-list",\111689,360148
+ DEFVAR_LISP ("deferred-action-function",\111694,360396
+ DEFVAR_LISP ("delayed-warnings-list",\111700,360695
+ DEFVAR_LISP ("timer-list",\111708,361103
+ DEFVAR_LISP ("timer-idle-list",\111712,361255
+ DEFVAR_LISP ("input-method-function",\111716,361418
+ DEFVAR_LISP ("input-method-previous-message",\111737,362387
+ DEFVAR_LISP ("show-help-function",\111744,362748
+ DEFVAR_LISP ("disable-point-adjustment",\111749,362980
+ DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530
+ DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896
+ DEFVAR_LISP ("throw-on-input",\111775,364174
+ DEFVAR_LISP ("command-error-function",\111781,364425
+ DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912
+ DEFVAR_LISP ("select-active-regions",\111798,365239
+ DEFVAR_LISP ("saved-region-selection",\111807,365631
+ DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016
+ DEFVAR_LISP ("debug-on-event",\111825,366557
c-src/emacs/src/lisp.h,41391
#define EMACS_LISP_H22,801
@@ -3274,112 +3274,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188
(defcustom tags-tag-face 148,5700
(defcustom tags-apropos-verbose 154,5835
(defcustom tags-apropos-additional-actions 160,5999
-(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918
-(defvar default-tags-table-function 189,7098
-(defvar tags-location-ring 194,7324
-(defvar tags-table-files 201,7600
-(defvar tags-completion-table 206,7767
-(defvar tags-included-tables 209,7859
-(defvar next-file-list 212,7954
-(defvar tags-table-format-functions 217,8060
-(defvar file-of-tag-function 224,8441
-(defvar tags-table-files-function 228,8635
-(defvar tags-completion-table-function 230,8746
-(defvar snarf-tag-function 232,8841
-(defvar goto-tag-location-function 236,9050
-(defvar find-tag-regexp-search-function 239,9223
-(defvar find-tag-regexp-tag-order 241,9344
-(defvar find-tag-regexp-next-line-after-failure-p 243,9453
-(defvar find-tag-search-function 245,9573
-(defvar find-tag-tag-order 247,9680
-(defvar find-tag-next-line-after-failure-p 249,9775
-(defvar list-tags-function 251,9881
-(defvar tags-apropos-function 253,9969
-(defvar tags-included-tables-function 255,10063
-(defvar verify-tags-table-function 257,10182
-(defun initialize-new-tags-table 260,10293
-(defun tags-table-mode 276,10981
-(defun visit-tags-table 285,11246
-(defun tags-table-check-computed-list 321,12784
-(defun tags-table-extend-computed-list 360,14655
-(defun tags-expand-table-name 400,16368
-(defun tags-table-list-member 409,16711
-(defun tags-verify-table 421,17183
-(defun tags-table-including 470,19303
-(defun tags-next-table 522,21347
-(defun visit-tags-table-buffer 543,22204
-(defun tags-reset-tags-tables 712,28514
-(defun file-of-tag 731,29171
-(defun tags-table-files 740,29521
-(defun tags-included-tables 749,29871
-(defun tags-completion-table 755,30117
-(defun tags-lazy-completion-table 783,31311
-(defun tags-completion-at-point-function 799,31946
-(defun find-tag-tag 818,32696
-(defvar last-tag 837,33369
-(defun find-tag-interactive 840,33428
-(defvar find-tag-history 852,33843
-(defvar etags-case-fold-search)855,33908
-(defvar etags-syntax-table)856,33940
-(defvar local-find-tag-hook)857,33968
-(defun find-tag-noselect 860,34013
-(defun find-tag 932,37127
-(defun find-tag-other-window 959,38343
-(defun find-tag-other-frame 1000,40271
-(defun find-tag-regexp 1025,41445
-(defalias 'pop-tag-mark pop-tag-mark1049,42607
-(defvar tag-lines-already-matched 1052,42658
-(defun find-tag-in-order 1055,42765
-(defun tag-find-file-of-tag-noselect 1167,47111
-(defun tag-find-file-of-tag 1200,48957
-(defun etags-recognize-tags-table 1208,49183
-(defun etags-verify-tags-table 1241,50814
-(defun etags-file-of-tag 1246,51012
-(defun etags-tags-completion-table 1256,51347
-(defun etags-snarf-tag 1286,52553
-(defun etags-goto-tag-location 1324,54122
-(defun etags-list-tags 1388,56565
-(defmacro tags-with-face 1423,57840
-(defun etags-tags-apropos-additional 1431,58173
-(defun etags-tags-apropos 1465,59410
-(defun etags-tags-table-files 1527,61619
-(defun etags-tags-included-tables 1542,62055
-(defun tags-recognize-empty-tags-table 1559,62595
-(defun tag-exact-file-name-match-p 1587,63741
-(defun tag-file-name-match-p 1596,64134
-(defun tag-exact-match-p 1609,64690
-(defun tag-implicit-name-match-p 1620,65258
-(defun tag-symbol-match-p 1633,65858
-(defun tag-word-match-p 1643,66294
-(defun tag-partial-file-name-match-p 1652,66692
-(defun tag-any-match-p 1662,67136
-(defun tag-re-match-p 1667,67320
-(defcustom tags-loop-revert-buffers 1675,67569
-(defun next-file 1685,67978
-(defvar tags-loop-operate 1760,70892
-(defvar tags-loop-scan1763,70986
-(defun tags-loop-eval 1771,71315
-(defun tags-loop-continue 1782,71644
-(defun tags-search 1850,73950
-(defun tags-query-replace 1871,74776
-(defun tags-complete-tags-table-file 1896,76000
-(defun list-tags 1906,76379
-(defun tags-apropos 1934,77332
-(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158
-(defun select-tags-table 1964,78397
-(defvar select-tags-table-mode-map 2019,80524
-(define-derived-mode select-tags-table-mode 2030,80907
-(defun select-tags-table-select 2034,81091
-(defun select-tags-table-quit 2043,81457
-(defun complete-tag 2049,81612
-(defconst etags--xref-limit 2074,82553
-(defvar etags-xref-find-definitions-tag-order 2076,82588
-(defun etags-xref-find 2082,82878
-(defun etags--xref-find-definitions 2096,83407
-(defclass xref-etags-location 2129,85121
-(defun xref-make-etags-location 2135,85344
-(cl-defmethod xref-location-marker 2139,85499
-(cl-defmethod xref-location-line 2146,85743
+(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921
+(defvar default-tags-table-function 189,7101
+(defvar tags-location-ring 194,7327
+(defvar tags-table-files 201,7603
+(defvar tags-completion-table 206,7770
+(defvar tags-included-tables 209,7862
+(defvar next-file-list 212,7957
+(defvar tags-table-format-functions 217,8063
+(defvar file-of-tag-function 224,8444
+(defvar tags-table-files-function 228,8638
+(defvar tags-completion-table-function 230,8749
+(defvar snarf-tag-function 232,8844
+(defvar goto-tag-location-function 236,9053
+(defvar find-tag-regexp-search-function 239,9226
+(defvar find-tag-regexp-tag-order 241,9347
+(defvar find-tag-regexp-next-line-after-failure-p 243,9456
+(defvar find-tag-search-function 245,9576
+(defvar find-tag-tag-order 247,9683
+(defvar find-tag-next-line-after-failure-p 249,9778
+(defvar list-tags-function 251,9884
+(defvar tags-apropos-function 253,9972
+(defvar tags-included-tables-function 255,10066
+(defvar verify-tags-table-function 257,10185
+(defun initialize-new-tags-table 260,10296
+(defun tags-table-mode 276,10984
+(defun visit-tags-table 285,11249
+(defun tags-table-check-computed-list 321,12787
+(defun tags-table-extend-computed-list 360,14658
+(defun tags-expand-table-name 400,16371
+(defun tags-table-list-member 409,16714
+(defun tags-verify-table 421,17186
+(defun tags-table-including 470,19306
+(defun tags-next-table 522,21350
+(defun visit-tags-table-buffer 543,22207
+(defun tags-reset-tags-tables 712,28517
+(defun file-of-tag 731,29174
+(defun tags-table-files 740,29524
+(defun tags-included-tables 749,29874
+(defun tags-completion-table 755,30120
+(defun tags-lazy-completion-table 783,31314
+(defun tags-completion-at-point-function 799,31949
+(defun find-tag-tag 818,32699
+(defvar last-tag 837,33372
+(defun find-tag-interactive 840,33431
+(defvar find-tag-history 852,33846
+(defvar etags-case-fold-search)855,33911
+(defvar etags-syntax-table)856,33943
+(defvar local-find-tag-hook)857,33971
+(defun find-tag-noselect 860,34016
+(defun find-tag 932,37130
+(defun find-tag-other-window 959,38346
+(defun find-tag-other-frame 1000,40274
+(defun find-tag-regexp 1025,41448
+(defalias 'pop-tag-mark pop-tag-mark1049,42610
+(defvar tag-lines-already-matched 1052,42661
+(defun find-tag-in-order 1055,42768
+(defun tag-find-file-of-tag-noselect 1167,47114
+(defun tag-find-file-of-tag 1200,48960
+(defun etags-recognize-tags-table 1208,49186
+(defun etags-verify-tags-table 1241,50817
+(defun etags-file-of-tag 1246,51015
+(defun etags-tags-completion-table 1256,51350
+(defun etags-snarf-tag 1286,52556
+(defun etags-goto-tag-location 1324,54125
+(defun etags-list-tags 1388,56568
+(defmacro tags-with-face 1423,57843
+(defun etags-tags-apropos-additional 1431,58176
+(defun etags-tags-apropos 1465,59413
+(defun etags-tags-table-files 1527,61622
+(defun etags-tags-included-tables 1542,62058
+(defun tags-recognize-empty-tags-table 1559,62598
+(defun tag-exact-file-name-match-p 1587,63744
+(defun tag-file-name-match-p 1596,64137
+(defun tag-exact-match-p 1609,64693
+(defun tag-implicit-name-match-p 1620,65261
+(defun tag-symbol-match-p 1633,65861
+(defun tag-word-match-p 1643,66297
+(defun tag-partial-file-name-match-p 1652,66695
+(defun tag-any-match-p 1662,67139
+(defun tag-re-match-p 1667,67323
+(defcustom tags-loop-revert-buffers 1675,67572
+(defun next-file 1685,67981
+(defvar tags-loop-operate 1760,70895
+(defvar tags-loop-scan1763,70989
+(defun tags-loop-eval 1771,71318
+(defun tags-loop-continue 1782,71647
+(defun tags-search 1850,73953
+(defun tags-query-replace 1871,74779
+(defun tags-complete-tags-table-file 1896,76003
+(defun list-tags 1906,76382
+(defun tags-apropos 1934,77335
+(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161
+(defun select-tags-table 1964,78400
+(defvar select-tags-table-mode-map 2019,80527
+(define-derived-mode select-tags-table-mode 2030,80910
+(defun select-tags-table-select 2034,81094
+(defun select-tags-table-quit 2043,81460
+(defun complete-tag 2049,81615
+(defconst etags--xref-limit 2074,82556
+(defvar etags-xref-find-definitions-tag-order 2076,82591
+(defun etags-xref-find 2082,82881
+(defun etags--xref-find-definitions 2096,83410
+(defclass xref-etags-location 2129,85124
+(defun xref-make-etags-location 2135,85347
+(cl-defmethod xref-location-marker 2139,85502
+(cl-defmethod xref-location-line 2146,85746
erl-src/gs_dialog.erl,98
-define(VERSION2,32
diff --git a/test/manual/etags/c-src/emacs/src/keyboard.c b/test/manual/etags/c-src/emacs/src/keyboard.c
index 7228f8cb5dc..506bf0d01c4 100644
--- a/test/manual/etags/c-src/emacs/src/keyboard.c
+++ b/test/manual/etags/c-src/emacs/src/keyboard.c
@@ -759,7 +759,7 @@ force_auto_save_soon (void)
DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
doc: /* Invoke the editor command loop recursively.
To get out of the recursive edit, a command can throw to `exit' -- for
-instance `(throw 'exit nil)'.
+instance `(throw \\='exit nil)'.
If you throw a value other than t, `recursive-edit' returns normally
to the function that called it. Throwing a t value causes
`recursive-edit' to quit, so that control returns to the command loop
diff --git a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
index e589263dc3f..9ae80149559 100644
--- a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
+++ b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
@@ -171,7 +171,7 @@ is the symbol being selected.
Example value:
- '((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
+ \\='((\"Emacs Lisp\" Info-goto-emacs-command-node obarray)
(\"Common Lisp\" common-lisp-hyperspec common-lisp-hyperspec-obarray)
(\"SCWM\" scwm-documentation scwm-obarray))"
:group 'etags
diff --git a/test/manual/image-circular-tests.el b/test/manual/image-circular-tests.el
index edc65eee9b8..1299970f827 100644
--- a/test/manual/image-circular-tests.el
+++ b/test/manual/image-circular-tests.el
@@ -29,22 +29,25 @@
(ert-deftest image-test-duplicate-keywords ()
"Test that duplicate keywords in an image spec lead to rejection."
- (should-error (image-size `(image :type xbm :type xbm :width 1 :height 1
+ (should-error (image-size `(image :type xbm :type xbm
+ :data-width 1 :data-height 1
:data ,(bool-vector t))
t)))
(ert-deftest image-test-circular-plist ()
"Test that a circular image spec is rejected."
(should-error
- (let ((l `(image :type xbm :width 1 :height 1 :data ,(bool-vector t))))
+ (let ((l `(image :type xbm :data-width 1 :data-height 1
+ :data ,(bool-vector t))))
(setcdr (last l) '#1=(:invalid . #1#))
(image-size l t))))
(ert-deftest image-test-:type-property-value ()
"Test that :type is allowed as a property value in an image spec."
- (should (equal (image-size `(image :dummy :type :type xbm :width 1 :height 1
- :data ,(bool-vector t))
- t)
+ (should (equal (image-size `(image :dummy :type :type xbm
+ :data-width 1 :data-height 1
+ :data ,(bool-vector t))
+ t)
(cons 1 1))))
(ert-deftest image-test-circular-specs ()
@@ -52,9 +55,9 @@
(should
(let* ((circ1 (cons :dummy nil))
(circ2 (cons :dummy nil))
- (spec1 `(image :type xbm :width 1 :height 1
+ (spec1 `(image :type xbm :data-width 1 :data-height 1
:data ,(bool-vector 1) :ignored ,circ1))
- (spec2 `(image :type xbm :width 1 :height 1
+ (spec2 `(image :type xbm :data-width 1 :data-height 1
:data ,(bool-vector 1) :ignored ,circ2)))
(setcdr circ1 circ1)
(setcdr circ2 circ2)
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 31a4b1ac71b..cba10a05025 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -101,7 +101,7 @@ with parameters from the *Messages* buffer modification."
;; | Overlay test setup
;; +==========================================================================+
-(eval-when-compile
+(eval-and-compile
(defun buffer-tests--make-test-name (fn x y)
(intern (format "buffer-tests--%s-%s-%s" fn x y))))
@@ -1482,4 +1482,57 @@ with parameters from the *Messages* buffer modification."
(when auto-save
(ignore-errors (delete-file auto-save))))))))
+(ert-deftest test-buffer-modifications ()
+ (ert-with-temp-file file
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (buffer-modified-p))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (should-not (eq (buffer-modified-p) 'autosaved))
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'bold))
+ (should (eq (buffer-modified-p) 'autosaved))
+ (save-buffer)
+ (should-not (buffer-modified-p))
+ (with-silent-modifications
+ (put-text-property 1 3 'face 'italic))
+ (should-not (buffer-modified-p)))))
+
+(ert-deftest test-restore-buffer-modified-p ()
+ (ert-with-temp-file file
+ ;; This avoids the annoying "foo and bar are the same file" on
+ ;; MS-Windows.
+ (setq file (file-truename file))
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (eq (buffer-modified-p) t))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (restore-buffer-modified-p nil)
+ (should-not (buffer-modified-p))
+ (insert "bar")
+ (do-auto-save nil t)
+ (should (eq (buffer-modified-p) 'autosaved))
+ (insert "zot")
+ (restore-buffer-modified-p 'autosaved)
+ (should (eq (buffer-modified-p) 'autosaved))
+
+ ;; Clean up.
+ (when (file-exists-p buffer-auto-save-file-name)
+ (delete-file buffer-auto-save-file-name))))
+
+ (ert-with-temp-file file
+ (setq file (file-truename file))
+ (with-current-buffer (find-file file)
+ (auto-save-mode 1)
+ (should-not (eq (buffer-modified-p) t))
+ (insert "foo")
+ (should (buffer-modified-p))
+ (should-not (eq (buffer-modified-p) 'autosaved))
+ (restore-buffer-modified-p 'autosaved)
+ (should (eq (buffer-modified-p) 'autosaved)))))
+
;;; buffer-tests.el ends here
diff --git a/test/src/comp-resources/comp-test-45603.el b/test/src/comp-resources/comp-test-45603.el
index f1c0dafb68d..65147ee0156 100644
--- a/test/src/comp-resources/comp-test-45603.el
+++ b/test/src/comp-resources/comp-test-45603.el
@@ -7,7 +7,7 @@
(defvar comp-test-45603-directory)
(defvar comp-test-45603-marked-candidates)
-(defun comp-test-45603--call-marked (action)
+(defun comp-test-45603--call-marked (_action)
(let* ((prefix-len (length comp-test-45603-mark-prefix))
(marked-candidates
(mapcar
@@ -17,7 +17,8 @@
(expand-file-name cand comp-test-45603-directory)
cand)))
comp-test-45603-marked-candidates))
- (multi-action (comp-test-45603--get-multi-action comp-test-45603-last)))))
+ (_multi-action (comp-test-45603--get-multi-action comp-test-45603-last)))
+ marked-candidates))
(defalias 'comp-test-45603--file-local-name
(if (fboundp 'file-local-name)
diff --git a/test/src/comp-resources/comp-test-funcs.el b/test/src/comp-resources/comp-test-funcs.el
index d740a5f8107..0a60f4d6cc4 100644
--- a/test/src/comp-resources/comp-test-funcs.el
+++ b/test/src/comp-resources/comp-test-funcs.el
@@ -189,7 +189,7 @@
;; Bnumberp
(numberp x))
-(defun comp-tests-discardn-f (x)
+(defun comp-tests-discardn-f (_x)
;; BdiscardN
(1+ (let ((a 1)
(_b)
@@ -297,8 +297,8 @@
;; potentially use all registers and that is modifying local
;; variables inside condition-case.
(let ((str-len (length str))
- (str-width 14)
- (ellipsis-width 3)
+ (_str-width 14)
+ (_ellipsis-width 3)
(idx 0)
(column 0)
(head-padding "") (tail-padding "")
@@ -489,7 +489,7 @@
(cl-defun comp-test-46824-1-f ()
(let ((next-repos '(1)))
(while t
- (let ((recipe (car next-repos)))
+ (let ((_recipe (car next-repos)))
(cl-block loop
(while t
(let ((err
@@ -640,7 +640,7 @@
(2 2))
3))))
-(defun comp-test-silly-frame2 (token)
+(defun comp-test-silly-frame2 (_token)
;; Check robustness against dead code.
(while c
(cl-case c
@@ -677,7 +677,7 @@
(progn
(if (and noninteractive (not byte-compile-verbose))
(message "Compiling %s..." filename))
- (byte-compile-file filename load))
+ (byte-compile-file filename))
(when load
(load (if (file-exists-p dest) dest filename)))
'no-byte-compile)))
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
index 89cb3d153d8..e7b534d00ec 100644
--- a/test/src/comp-tests.el
+++ b/test/src/comp-tests.el
@@ -51,7 +51,14 @@
(doc-string 3))
`(ert-deftest ,(intern (concat "comp-tests-" (symbol-name name))) ,args
:tags '(:nativecomp)
- ,@docstring-and-body))
+ ,@(and (stringp (car docstring-and-body))
+ (list (pop docstring-and-body)))
+ ;; Some of the tests leave spill files behind -- so create a
+ ;; sub-dir where native-comp can do its work, and then delete it
+ ;; at the end.
+ (ert-with-temp-directory dir
+ (let ((temporary-file-directory dir))
+ ,@docstring-and-body))))
@@ -1369,7 +1376,14 @@ Return a list of results."
(when (eql x 1.0)
(error ""))
x)
- t)))
+ t)
+
+ ;; 74
+ ((defun comp-tests-ret-type-spec-f (x)
+ (if (eq x 0)
+ (error "")
+ (1+ x)))
+ number)))
(defun comp-tests-define-type-spec-test (number x)
`(comp-deftest ,(intern (format "ret-type-spec-%d" number)) ()
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
index 8dabba90352..ee4f02347ec 100644
--- a/test/src/doc-tests.el
+++ b/test/src/doc-tests.el
@@ -29,8 +29,8 @@
(ert-deftest doc-tests-documentation/autoloaded-macro ()
(skip-unless noninteractive)
- (should (autoloadp (symbol-function 'rx)))
- (should (stringp (documentation 'rx)))) ; See Bug#52969.
+ (should (autoloadp (symbol-function 'benchmark-run)))
+ (should (stringp (documentation 'benchmark-run)))) ; See Bug#52969.
(ert-deftest doc-tests-documentation/autoloaded-defun ()
(skip-unless noninteractive)
diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c
index 015c1efd978..187af821c22 100644
--- a/test/src/emacs-module-resources/mod-test.c
+++ b/test/src/emacs-module-resources/mod-test.c
@@ -47,8 +47,6 @@ uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
#include <gmp.h>
#include <emacs-module.h>
-#include "timespec.h"
-
int plugin_is_GPL_compatible;
#if INTPTR_MAX <= 0
@@ -74,9 +72,6 @@ int plugin_is_GPL_compatible;
# error "INTPTR_MAX too large"
#endif
-/* Smoke test to verify that EMACS_LIMB_MAX is defined. */
-_Static_assert (0 < EMACS_LIMB_MAX, "EMACS_LIMB_MAX missing or incorrect");
-
/* Always return symbol 't'. */
static emacs_value
Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
@@ -422,6 +417,16 @@ signal_errno (emacs_env *env, const char *function)
signal_system_error (env, errno, function);
}
+#ifdef CLOCK_REALTIME
+
+/* Whether A <= B. */
+static bool
+timespec_le (struct timespec a, struct timespec b)
+{
+ return (a.tv_sec < b.tv_sec
+ || (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec));
+}
+
/* A long-running operation that occasionally calls `should_quit' or
`process_input'. */
@@ -434,11 +439,13 @@ Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
if (env->non_local_exit_check (env))
return NULL;
const bool process_input = env->is_not_nil (env, args[1]);
- const struct timespec amount = make_timespec(0, 10000000);
+ const struct timespec amount = { .tv_nsec = 10000000 };
while (true)
{
- const struct timespec now = current_timespec ();
- if (timespec_cmp (now, until) >= 0)
+ struct timespec now;
+ if (clock_gettime (CLOCK_REALTIME, &now) != 0)
+ return NULL;
+ if (timespec_le (until, now))
break;
if (nanosleep (&amount, NULL) && errno != EINTR)
{
@@ -452,6 +459,7 @@ Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
}
return env->intern (env, "finished");
}
+#endif
static emacs_value
Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
@@ -553,6 +561,7 @@ make_big_integer (emacs_env *env, const mpz_t value)
return result;
}
+#ifdef CLOCK_REALTIME
static emacs_value
Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
assert (nargs == 1);
@@ -560,11 +569,6 @@ Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void
mpz_t nanoseconds;
assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
mpz_init_set_si (nanoseconds, time.tv_sec);
-#ifdef __MINGW32__
- _Static_assert (1000000000 <= ULONG_MAX, "unsupported architecture");
-#else
- static_assert (1000000000 <= ULONG_MAX, "unsupported architecture");
-#endif
mpz_mul_ui (nanoseconds, nanoseconds, 1000000000);
assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec);
@@ -572,6 +576,7 @@ Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void
mpz_clear (nanoseconds);
return result;
}
+#endif
static emacs_value
Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
@@ -631,7 +636,7 @@ sleep_for_half_second (void)
#ifdef WINDOWSNT
Sleep (500);
#else
- const struct timespec sleep = {0, 500000000};
+ const struct timespec sleep = { .tv_nsec = 500000000 };
if (nanosleep (&sleep, NULL) != 0)
perror ("nanosleep");
#endif
@@ -763,6 +768,11 @@ bind_function (emacs_env *env, const char *name, emacs_value Sfun)
int
emacs_module_init (struct emacs_runtime *ert)
{
+ /* These smoke tests don't use _Static_assert because too many
+ compilers lack support for _Static_assert. */
+ assert (0 < EMACS_LIMB_MAX);
+ assert (1000000000 <= ULONG_MAX);
+
/* Check that EMACS_MAJOR_VERSION is defined and an integral
constant. */
char dummy[EMACS_MAJOR_VERSION];
@@ -815,9 +825,13 @@ emacs_module_init (struct emacs_runtime *ert)
DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
NULL, NULL);
+#ifdef CLOCK_REALTIME
DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
+#endif
DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL);
+#ifdef CLOCK_REALTIME
DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
+#endif
DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
DEFUN ("mod-test-make-function-with-finalizer",
Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL);
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 2ff33644a8e..1099fd04678 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -308,7 +308,8 @@ local reference."
"Check that Bug#30163 is fixed."
(with-temp-buffer
(let ((standard-output (current-buffer))
- (text-quoting-style 'grave))
+ (text-quoting-style 'grave)
+ (fill-column 200)) ; prevent line breaks when filling
(describe-function-1 #'mod-test-sum)
(goto-char (point-min))
(while (re-search-forward "`[^']*/src/emacs-module-resources/" nil t)
@@ -335,6 +336,7 @@ Return A + B
(ert-deftest mod-test-sleep-until ()
"Check that `mod-test-sleep-until' either returns normally or quits.
Interactively, you can try hitting \\[keyboard-quit] to quit."
+ (skip-unless (fboundp 'mod-test-sleep-until))
(dolist (arg '(nil t))
;; Guard against some caller setting `inhibit-quit'.
(with-local-quit
@@ -389,6 +391,7 @@ Interactively, you can try hitting \\[keyboard-quit] to quit."
(ert-deftest mod-test-nanoseconds ()
"Test truncation when converting to `struct timespec'."
+ (skip-unless (fboundp 'mod-test-nanoseconds))
(dolist (test-case '((0 . 0)
(-1 . -1000000000)
((1 . 1000000000) . 1)
@@ -407,6 +410,7 @@ Interactively, you can try hitting \\[keyboard-quit] to quit."
(should (= (mod-test-nanoseconds input) expected))))))
(ert-deftest mod-test-double ()
+ (skip-unless (fboundp 'mod-test-double))
(dolist (input (list 0 1 2 -1 42 12345678901234567890
most-positive-fixnum (1+ most-positive-fixnum)
most-negative-fixnum (1- most-negative-fixnum)))
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index e4230c10efd..1b2ad99360b 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -240,4 +240,31 @@ expressions works for identifiers starting with period."
(should (equal (string-trim (buffer-string))
"Error: (error \"Boo\")")))))
+(ert-deftest eval-tests/funcall-with-delayed-message ()
+ ;; Check that `funcall-with-delayed-message' displays its message before
+ ;; its function terminates iff the timeout is short enough.
+
+ ;; This also serves as regression test for bug#55628 where a short
+ ;; timeout was rounded up to the next whole second.
+ (dolist (params '((0.8 0.4)
+ (0.1 0.8)))
+ (let ((timeout (nth 0 params))
+ (work-time (nth 1 params)))
+ (ert-info ((prin1-to-string params) :prefix "params: ")
+ (with-current-buffer "*Messages*"
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (let ((stop (+ (float-time) work-time)))
+ (funcall-with-delayed-message
+ timeout "timed out"
+ (lambda ()
+ (while (< (float-time) stop))
+ (message "finished"))))
+ (let ((expected-messages
+ (if (< timeout work-time)
+ "timed out\nfinished"
+ "finished")))
+ (should (equal (string-trim (buffer-string))
+ expected-messages))))))))
+
;;; eval-tests.el ends here
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 511490c5745..08582c8a862 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -138,7 +138,7 @@ Also check that an encoding error can appear in a symlink."
(should (and (file-name-absolute-p name)
(not (eq (aref name 0) ?~))))))
-(ert-deftest fileio-test--expand-file-name-null-bytes ()
+(ert-deftest fileio-tests--expand-file-name-null-bytes ()
"Test that `expand-file-name' checks for null bytes in filenames."
(should-error (expand-file-name (concat "file" (char-to-string ?\0) ".txt"))
:type 'wrong-type-argument)
@@ -193,4 +193,28 @@ Also check that an encoding error can appear in a symlink."
(should (equal (file-name-concat "" "bar") "bar"))
(should (equal (file-name-concat "" "") "")))
+(ert-deftest fileio-tests--non-regular-insert ()
+ (skip-unless (file-exists-p "/dev/urandom"))
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (should-error (insert-file-contents "/dev/urandom" nil 5 10))
+ (insert-file-contents "/dev/urandom" nil nil 10)
+ (should (= (buffer-size) 10))))
+
+(defun fileio-tests--identity-expand-handler (_ file &rest _)
+ file)
+(put 'fileio-tests--identity-expand-handler 'operations '(expand-file-name))
+
+(ert-deftest fileio--file-name-case-insensitive-p ()
+ ;; Check that we at least don't crash if given nonexisting files
+ ;; without a directory (bug#56443).
+
+ ;; Use an identity file-name handler, as if called by `ffap'.
+ (let* ((file-name-handler-alist
+ '(("^mailto:" . fileio-tests--identity-expand-handler)))
+ (file "mailto:snowball@hell.com"))
+ ;; Check that `expand-file-name' is identity for this name.
+ (should (equal (expand-file-name file nil) file))
+ (file-name-case-insensitive-p file)))
+
;;; fileio-tests.el ends here
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
index 21478a1a0f2..97642669a0d 100644
--- a/test/src/filelock-tests.el
+++ b/test/src/filelock-tests.el
@@ -31,26 +31,26 @@
(require 'ert-x)
(require 'seq)
-(defun filelock-tests--fixture (test-function)
- "Call TEST-FUNCTION under a test fixture.
+(defmacro filelock-tests--fixture (&rest body)
+ "Call BODY under a test fixture.
Create a test directory and a buffer whose `buffer-file-name' and
-`buffer-file-truename' are a file within it, then call
-TEST-FUNCTION. Finally, delete the buffer and the test
-directory."
- (ert-with-temp-directory temp-dir
- (let ((name (concat (file-name-as-directory temp-dir)
- "userfile"))
- (create-lockfiles t))
- (with-temp-buffer
- (setq buffer-file-name name
- buffer-file-truename name)
- (unwind-protect
- (save-current-buffer
- (funcall test-function))
- ;; Set `buffer-file-truename' nil to prevent unlocking,
- ;; which might prompt the user and/or signal errors.
- (setq buffer-file-name nil
- buffer-file-truename nil))))))
+`buffer-file-truename' are a file within it, then call BODY.
+Finally, delete the buffer and the test directory."
+ (declare (debug (body)))
+ `(ert-with-temp-directory temp-dir
+ (let ((name (concat (file-name-as-directory temp-dir)
+ "userfile"))
+ (create-lockfiles t))
+ (with-temp-buffer
+ (setq buffer-file-name name
+ buffer-file-truename name)
+ (unwind-protect
+ (save-current-buffer
+ ,@body)
+ ;; Set `buffer-file-truename' nil to prevent unlocking,
+ ;; which might prompt the user and/or signal errors.
+ (setq buffer-file-name nil
+ buffer-file-truename nil))))))
(defun filelock-tests--make-lock-name (file-name)
"Return the lock file name for FILE-NAME.
@@ -86,105 +86,132 @@ the case)."
(ert-deftest filelock-tests-lock-unlock-no-errors ()
"Check that locking and unlocking works without error."
(filelock-tests--fixture
- (lambda ()
- (should-not (file-locked-p (buffer-file-name)))
+ (should-not (file-locked-p (buffer-file-name)))
- ;; inserting text should lock the buffer's file.
- (insert "this locks the buffer's file")
- (filelock-tests--should-be-locked)
- (unlock-buffer)
- (set-buffer-modified-p nil)
- (should-not (file-locked-p (buffer-file-name)))
+ ;; Inserting text should lock the buffer's file.
+ (insert "this locks the buffer's file")
+ (filelock-tests--should-be-locked)
+ (unlock-buffer)
+ (set-buffer-modified-p nil)
+ (should-not (file-locked-p (buffer-file-name)))
- ;; `set-buffer-modified-p' should lock the buffer's file.
- (set-buffer-modified-p t)
- (filelock-tests--should-be-locked)
- (unlock-buffer)
- (should-not (file-locked-p (buffer-file-name)))
+ ;; `set-buffer-modified-p' should lock the buffer's file.
+ (set-buffer-modified-p t)
+ (filelock-tests--should-be-locked)
+ (unlock-buffer)
+ (should-not (file-locked-p (buffer-file-name)))
- (should-not (file-locked-p (buffer-file-name))))))
+ (should-not (file-locked-p (buffer-file-name)))))
(ert-deftest filelock-tests-lock-spoiled ()
- "Check `lock-buffer' ."
+ "Check `lock-buffer'."
(skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
(filelock-tests--fixture
- (lambda ()
- (filelock-tests--spoil-lock-file buffer-file-truename)
- ;; FIXME: errors when locking a file are ignored; should they be?
- (set-buffer-modified-p t)
- (filelock-tests--unspoil-lock-file buffer-file-truename)
- (should-not (file-locked-p buffer-file-truename)))))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+ ;; FIXME: errors when locking a file are ignored; should they be?
+ (set-buffer-modified-p t)
+ (filelock-tests--unspoil-lock-file buffer-file-truename)
+ (should-not (file-locked-p buffer-file-truename))))
(ert-deftest filelock-tests-file-locked-p-spoiled ()
"Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
(skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
(filelock-tests--fixture
- (lambda ()
- (filelock-tests--spoil-lock-file buffer-file-truename)
- (let ((err (should-error (file-locked-p (buffer-file-name)))))
- (should (equal (seq-subseq err 0 2)
- (if (eq system-type 'windows-nt)
- '(permission-denied "Testing file lock")
- '(file-error "Testing file lock"))))))))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+ (let ((err (should-error (file-locked-p (buffer-file-name)))))
+ (should (equal (seq-subseq err 0 2)
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Testing file lock")
+ '(file-error "Testing file lock")))))))
(ert-deftest filelock-tests-unlock-spoiled ()
"Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
(skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
(filelock-tests--fixture
- (lambda ()
- ;; Set the buffer modified with file locking temporarily
- ;; disabled.
- (let ((create-lockfiles nil))
- (set-buffer-modified-p t))
- (should-not (file-locked-p buffer-file-truename))
- (filelock-tests--spoil-lock-file buffer-file-truename)
-
- ;; Errors from `unlock-buffer' should call
- ;; `userlock--handle-unlock-error' (bug#46397).
- (let (errors)
- (cl-letf (((symbol-function 'userlock--handle-unlock-error)
- (lambda (err) (push err errors))))
- (unlock-buffer))
- (should (consp errors))
- (should (equal
- (if (eq system-type 'windows-nt)
- '(permission-denied "Unlocking file")
- '(file-error "Unlocking file"))
- (seq-subseq (car errors) 0 2)))
- (should (equal (length errors) 1))))))
+ ;; Set the buffer modified with file locking temporarily disabled.
+ (let ((create-lockfiles nil))
+ (set-buffer-modified-p t))
+ (should-not (file-locked-p buffer-file-truename))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+
+ ;; Errors from `unlock-buffer' should call
+ ;; `userlock--handle-unlock-error' (bug#46397).
+ (cl-letf (((symbol-function 'userlock--handle-unlock-error)
+ (lambda (err) (signal (car err) (cdr err)))))
+ (should (equal
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Unlocking file")
+ '(file-error "Unlocking file"))
+ (seq-subseq (should-error (unlock-buffer)) 0 2))))))
(ert-deftest filelock-tests-kill-buffer-spoiled ()
"Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
(skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
(filelock-tests--fixture
- (lambda ()
- ;; Set the buffer modified with file locking temporarily
- ;; disabled.
- (let ((create-lockfiles nil))
- (set-buffer-modified-p t))
- (should-not (file-locked-p buffer-file-truename))
- (filelock-tests--spoil-lock-file buffer-file-truename)
-
- ;; Kill the current buffer. Because the buffer is modified Emacs
- ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to
- ;; a function that fakes a "yes" answer for the "Buffer modified;
- ;; kill anyway?" prompt.
- ;;
- ;; File errors from unlocking files should call
- ;; `userlock--handle-unlock-error' (bug#46397).
- (let (errors)
+ ;; Set the buffer modified with file locking temporarily disabled.
+ (let ((create-lockfiles nil))
+ (set-buffer-modified-p t))
+ (should-not (file-locked-p buffer-file-truename))
+ (filelock-tests--spoil-lock-file buffer-file-truename)
+
+ ;; Kill the current buffer. Because the buffer is modified Emacs
+ ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to a
+ ;; function that fakes a "yes" answer for the "Buffer modified;
+ ;; kill anyway?" prompt.
+ ;;
+ ;; File errors from unlocking files should call
+ ;; `userlock--handle-unlock-error' (bug#46397).
+ (cl-letf (((symbol-function 'yes-or-no-p) #'always)
+ ((symbol-function 'userlock--handle-unlock-error)
+ (lambda (err) (signal (car err) (cdr err)))))
+ (should (equal
+ (if (eq system-type 'windows-nt)
+ '(permission-denied "Unlocking file")
+ '(file-error "Unlocking file"))
+ (seq-subseq (should-error (kill-buffer)) 0 2))))))
+
+(ert-deftest filelock-tests-detect-external-change ()
+ "Check that an external file modification is reported."
+ (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-unless (executable-find "touch"))
+ (skip-unless (executable-find "echo"))
+ (dolist (cl '(t nil))
+ (filelock-tests--fixture
+ (let ((create-lockfiles cl))
+ (write-region "foo" nil (buffer-file-name))
+ (revert-buffer nil 'noconfirm)
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; Just changing the file modification on disk doesn't hurt,
+ ;; because file contents in buffer and on disk look equal.
+ (shell-command (format "touch %s" (buffer-file-name)))
+ (insert "bar")
+ (when cl (filelock-tests--should-be-locked))
+
+ ;; Bug#53207: with `create-lockfiles' nil, saving the buffer
+ ;; results in a prompt.
(cl-letf (((symbol-function 'yes-or-no-p)
- (lambda (&rest _) t))
- ((symbol-function 'userlock--handle-unlock-error)
- (lambda (err) (push err errors))))
- (kill-buffer))
- (should (consp errors))
- (should (equal
- (if (eq system-type 'windows-nt)
- '(permission-denied "Unlocking file")
- '(file-error "Unlocking file"))
- (seq-subseq (car errors) 0 2)))
- (should (equal (length errors) 1))))))
+ (lambda (_) (ert-fail "Test failed unexpectedly"))))
+ (save-buffer))
+ (should-not (file-locked-p (buffer-file-name)))
+
+ ;; Changing the file contents on disk hurts when buffer is
+ ;; modified. There shall be a query, which we answer.
+ ;; *Messages* buffer is checked for prompt.
+ (shell-command (format "echo bar >>%s" (buffer-file-name)))
+ (cl-letf (((symbol-function 'read-char-choice)
+ (lambda (prompt &rest _) (message "%s" prompt) ?y)))
+ (ert-with-message-capture captured-messages
+ ;; `ask-user-about-supersession-threat' does not work in
+ ;; batch mode, let's simulate interactiveness.
+ (let (noninteractive)
+ (insert "baz"))
+ (should (string-match-p
+ (format
+ "^%s changed on disk; really edit the buffer\\?"
+ (file-name-nondirectory (buffer-file-name)))
+ captured-messages))))
+ (when cl (filelock-tests--should-be-locked))))))
(provide 'filelock-tests)
;;; filelock-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index f74e925d3b6..0119e31df11 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -130,6 +130,49 @@
(should (equal [nil nil nil nil nil t t t t t] (vconcat A)))
(should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A))))))
+(defconst fns-tests--string-lessp-cases
+ '((a 97 error)
+ (97 "a" error)
+ ("abc" "abd" t)
+ ("abd" "abc" nil)
+ (abc "abd" t)
+ ("abd" abc nil)
+ (abc abd t)
+ (abd abc nil)
+ ("" "" nil)
+ ("" " " t)
+ (" " "" nil)
+ ("abc" "abcd" t)
+ ("abcd" "abc" nil)
+ ("abc" "abc" nil)
+ (abc abc nil)
+ ("\0" "" nil)
+ ("" "\0" t)
+ ("~" "\x80" t)
+ ("\x80" "\x80" nil)
+ ("\xfe" "\xff" t)
+ ("Munchen" "München" t)
+ ("München" "Munchen" nil)
+ ("München" "München" nil)
+ ("Ré" "Réunion" t)))
+
+
+(ert-deftest fns-tests-string-lessp ()
+ ;; Exercise both `string-lessp' and its alias `string<', both directly
+ ;; and in a function (exercising its bytecode).
+ (dolist (lessp (list #'string-lessp #'string<
+ (lambda (a b) (string-lessp a b))
+ (lambda (a b) (string< a b))))
+ (ert-info ((prin1-to-string lessp) :prefix "function: ")
+ (dolist (case fns-tests--string-lessp-cases)
+ (ert-info ((prin1-to-string case) :prefix "case: ")
+ (pcase case
+ (`(,x ,y error)
+ (should-error (funcall lessp x y)))
+ (`(,x ,y ,expected)
+ (should (equal (funcall lessp x y) expected)))))))))
+
+
(ert-deftest fns-tests-compare-strings ()
(should-error (compare-strings))
(should-error (compare-strings "xyzzy" "xyzzy"))
@@ -204,6 +247,76 @@
[-1 2 3 4 5 5 7 8 9]))
(should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
[9 8 7 5 5 4 3 2 -1]))
+ ;; Sort a reversed list and vector.
+ (should (equal
+ (sort (reverse (number-sequence 1 1000)) (lambda (x y) (< x y)))
+ (number-sequence 1 1000)))
+ (should (equal
+ (sort (reverse (vconcat (number-sequence 1 1000)))
+ (lambda (x y) (< x y)))
+ (vconcat (number-sequence 1 1000))))
+ ;; Sort a constant list and vector.
+ (should (equal
+ (sort (make-vector 100 1) (lambda (x y) (> x y)))
+ (make-vector 100 1)))
+ (should (equal
+ (sort (append (make-vector 100 1) nil) (lambda (x y) (> x y)))
+ (append (make-vector 100 1) nil)))
+ ;; Sort a long list and vector with every pair reversed.
+ (let ((vec (make-vector 100000 nil))
+ (logxor-vec (make-vector 100000 nil)))
+ (dotimes (i 100000)
+ (aset logxor-vec i (logxor i 1))
+ (aset vec i i))
+ (should (equal
+ (sort logxor-vec (lambda (x y) (< x y)))
+ vec))
+ (should (equal
+ (sort (append logxor-vec nil) (lambda (x y) (< x y)))
+ (append vec nil))))
+ ;; Sort a list and vector with seven swaps.
+ (let ((vec (make-vector 100 nil))
+ (swap-vec (make-vector 100 nil)))
+ (dotimes (i 100)
+ (aset vec i (- i 50))
+ (aset swap-vec i (- i 50)))
+ (mapc (lambda (p)
+ (let ((tmp (elt swap-vec (car p))))
+ (aset swap-vec (car p) (elt swap-vec (cdr p)))
+ (aset swap-vec (cdr p) tmp)))
+ '((48 . 94) (75 . 77) (33 . 41) (92 . 52)
+ (10 . 96) (1 . 14) (43 . 81)))
+ (should (equal
+ (sort (copy-sequence swap-vec) (lambda (x y) (< x y)))
+ vec))
+ (should (equal
+ (sort (append swap-vec nil) (lambda (x y) (< x y)))
+ (append vec nil))))
+ ;; Check for possible corruption after GC.
+ (let* ((size 3000)
+ (complex-vec (make-vector size nil))
+ (vec (make-vector size nil))
+ (counter 0)
+ (my-counter (lambda ()
+ (if (< counter 500)
+ (cl-incf counter)
+ (setq counter 0)
+ (garbage-collect))))
+ (rand 1)
+ (generate-random
+ (lambda () (setq rand
+ (logand (+ (* rand 1103515245) 12345) 2147483647)))))
+ ;; Make a complex vector and its sorted version.
+ (dotimes (i size)
+ (let ((r (funcall generate-random)))
+ (aset complex-vec i (cons r "a"))
+ (aset vec i (cons r "a"))))
+ ;; Sort it.
+ (should (equal
+ (sort complex-vec
+ (lambda (x y) (funcall my-counter) (< (car x) (car y))))
+ (sort vec 'car-less-than-car))))
+ ;; Check for sorting stability.
(should (equal
(sort
(vector
@@ -739,24 +852,6 @@
(should-not (plist-get d1 3))
(should-not (plist-get d2 3))))
-(ert-deftest test-cycle-lax-plist-get ()
- (let ((c1 (cyc1 1))
- (c2 (cyc2 1 2))
- (d1 (dot1 1))
- (d2 (dot2 1 2)))
- (should (lax-plist-get c1 1))
- (should (lax-plist-get c2 1))
- (should (lax-plist-get d1 1))
- (should (lax-plist-get d2 1))
- (should-error (lax-plist-get c1 2) :type 'circular-list)
- (should (lax-plist-get c2 2))
- (should-error (lax-plist-get d1 2) :type 'wrong-type-argument)
- (should (lax-plist-get d2 2))
- (should-error (lax-plist-get c1 3) :type 'circular-list)
- (should-error (lax-plist-get c2 3) :type 'circular-list)
- (should-error (lax-plist-get d1 3) :type 'wrong-type-argument)
- (should-error (lax-plist-get d2 3) :type 'wrong-type-argument)))
-
(ert-deftest test-cycle-plist-member ()
(let ((c1 (cyc1 1))
(c2 (cyc2 1 2))
@@ -793,24 +888,6 @@
(should-error (plist-put d1 3 3) :type 'wrong-type-argument)
(should-error (plist-put d2 3 3) :type 'wrong-type-argument)))
-(ert-deftest test-cycle-lax-plist-put ()
- (let ((c1 (cyc1 1))
- (c2 (cyc2 1 2))
- (d1 (dot1 1))
- (d2 (dot2 1 2)))
- (should (lax-plist-put c1 1 1))
- (should (lax-plist-put c2 1 1))
- (should (lax-plist-put d1 1 1))
- (should (lax-plist-put d2 1 1))
- (should-error (lax-plist-put c1 2 2) :type 'circular-list)
- (should (lax-plist-put c2 2 2))
- (should-error (lax-plist-put d1 2 2) :type 'wrong-type-argument)
- (should (lax-plist-put d2 2 2))
- (should-error (lax-plist-put c1 3 3) :type 'circular-list)
- (should-error (lax-plist-put c2 3 3) :type 'circular-list)
- (should-error (lax-plist-put d1 3 3) :type 'wrong-type-argument)
- (should-error (lax-plist-put d2 3 3) :type 'wrong-type-argument)))
-
(ert-deftest test-cycle-equal ()
(should-error (equal (cyc1 1) (cyc1 1)))
(should-error (equal (cyc2 1 2) (cyc2 1 2))))
@@ -823,24 +900,12 @@
"Test that `plist-get' doesn't signal an error on degenerate plists."
(should-not (plist-get '(:foo 1 :bar) :bar)))
-(ert-deftest lax-plist-get/odd-number-of-elements ()
- "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
- (should (equal (should-error (lax-plist-get '(:foo 1 :bar) :bar)
- :type 'wrong-type-argument)
- '(wrong-type-argument plistp (:foo 1 :bar)))))
-
(ert-deftest plist-put/odd-number-of-elements ()
"Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
(should (equal (should-error (plist-put '(:foo 1 :bar) :zot 2)
:type 'wrong-type-argument)
'(wrong-type-argument plistp (:foo 1 :bar)))))
-(ert-deftest lax-plist-put/odd-number-of-elements ()
- "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
- (should (equal (should-error (lax-plist-put '(:foo 1 :bar) :zot 2)
- :type 'wrong-type-argument)
- '(wrong-type-argument plistp (:foo 1 :bar)))))
-
(ert-deftest plist-member/improper-list ()
"Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
(should (equal (should-error (plist-member '(:foo 1 . :bar) :qux)
@@ -865,7 +930,7 @@
(should (equal 1 (string-distance "ab" "a我b")))
(should (equal 1 (string-distance "我" "她")))
- ;; correct behaviour with empty strings
+ ;; correct behavior with empty strings
(should (equal 0 (string-distance "" "")))
(should (equal 0 (string-distance "" "" t)))
(should (equal 1 (string-distance "x" "")))
@@ -1192,4 +1257,106 @@
(should-error (line-number-at-pos -1))
(should-error (line-number-at-pos 100))))
+(defun fns-tests-concat (&rest args)
+ ;; Dodge the byte-compiler's partial evaluation of `concat' with
+ ;; constant arguments.
+ (apply #'concat args))
+
+(ert-deftest fns-concat ()
+ (should (equal (fns-tests-concat) ""))
+ (should (equal (fns-tests-concat "") ""))
+ (should (equal (fns-tests-concat nil) ""))
+ (should (equal (fns-tests-concat []) ""))
+ (should (equal (fns-tests-concat [97 98]) "ab"))
+ (should (equal (fns-tests-concat '(97 98)) "ab"))
+ (should (equal (fns-tests-concat "ab" '(99 100) nil [101 102] "gh")
+ "abcdefgh"))
+ (should (equal (fns-tests-concat "Ab" "\200" "cd") "Ab\200cd"))
+ (should (equal (fns-tests-concat "aB" "\200" "çd") "aB\200çd"))
+ (should (equal (fns-tests-concat "AB" (string-to-multibyte "\200") "cd")
+ (string-to-multibyte "AB\200cd")))
+ (should (equal (fns-tests-concat "ab" '(#xe5) [255] "cd") "abåÿcd"))
+ (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy") "\377\200xy"))
+ (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy§") "\377\200xy§"))
+ (should (equal-including-properties
+ (fns-tests-concat #("abc" 0 3 (a 1)) #("de" 0 2 (a 1)))
+ #("abcde" 0 5 (a 1))))
+ (should (equal-including-properties
+ (fns-tests-concat #("abc" 0 3 (a 1)) "§ü" #("çå" 0 2 (b 2)))
+ #("abc§üçå" 0 3 (a 1) 5 7 (b 2))))
+ (should-error (fns-tests-concat "a" '(98 . 99))
+ :type 'wrong-type-argument)
+ (let ((loop (list 66 67)))
+ (setcdr (cdr loop) loop)
+ (should-error (fns-tests-concat "A" loop)
+ :type 'circular-list)))
+
+(ert-deftest fns-vconcat ()
+ (should (equal (vconcat) []))
+ (should (equal (vconcat nil) []))
+ (should (equal (vconcat "") []))
+ (should (equal (vconcat [1 2 3]) [1 2 3]))
+ (should (equal (vconcat '(1 2 3)) [1 2 3]))
+ (should (equal (vconcat "ABC") [65 66 67]))
+ (should (equal (vconcat "ü§") [252 167]))
+ (should (equal (vconcat [1 2 3] nil '(4 5) "AB" "å"
+ "\377" (string-to-multibyte "\377")
+ (bool-vector t nil nil t nil))
+ [1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil]))
+ (should-error (vconcat [1] '(2 . 3))
+ :type 'wrong-type-argument)
+ (let ((loop (list 1 2)))
+ (setcdr (cdr loop) loop)
+ (should-error (vconcat [1] loop)
+ :type 'circular-list)))
+
+(ert-deftest fns-append ()
+ (should (equal (append) nil))
+ (should (equal (append 'tail) 'tail))
+ (should (equal (append [1 2 3] nil '(4 5) "AB" "å"
+ "\377" (string-to-multibyte "\377")
+ (bool-vector t nil nil t nil)
+ '(9 10))
+ '(1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil 9 10)))
+ (should (equal (append '(1 2) '(3 4) 'tail)
+ '(1 2 3 4 . tail)))
+ (should-error (append '(1 . 2) '(3))
+ :type 'wrong-type-argument)
+ (let ((loop (list 1 2)))
+ (setcdr (cdr loop) loop)
+ (should-error (append loop '(end))
+ :type 'circular-list)))
+
+(ert-deftest test-plist ()
+ (let ((plist '(:a "b")))
+ (setq plist (plist-put plist :b "c"))
+ (should (equal (plist-get plist :b) "c"))
+ (should (equal (plist-member plist :b) '(:b "c"))))
+
+ (let ((plist '("1" "2" "a" "b")))
+ (setq plist (plist-put plist (copy-sequence "a") "c"))
+ (should-not (equal (plist-get plist (copy-sequence "a")) "c"))
+ (should-not (equal (plist-member plist (copy-sequence "a")) '("a" "c"))))
+
+ (let ((plist '("1" "2" "a" "b")))
+ (setq plist (plist-put plist (copy-sequence "a") "c" #'equal))
+ (should (equal (plist-get plist (copy-sequence "a") #'equal) "c"))
+ (should (equal (plist-member plist (copy-sequence "a") #'equal)
+ '("a" "c")))))
+
+(ert-deftest fns--string-to-unibyte ()
+ (dolist (str '("" "a" "abc" "a\x00\x7fz" "a\xaa\xbbz ""\x80\xdd\xff"))
+ (ert-info ((prin1-to-string str) :prefix "str: ")
+ (should-not (multibyte-string-p str))
+ (let* ((u (string-to-unibyte str)) ; should be identity
+ (m (string-to-multibyte u)) ; lossless conversion
+ (uu (string-to-unibyte m))) ; also lossless
+ (should-not (multibyte-string-p u))
+ (should (multibyte-string-p m))
+ (should-not (multibyte-string-p uu))
+ (should (equal str u))
+ (should (equal str uu)))))
+ (should-error (string-to-unibyte "å"))
+ (should-error (string-to-unibyte "ABC∀BC")))
+
;;; fns-tests.el ends here
diff --git a/test/src/image-tests.el b/test/src/image-tests.el
index 3885981e0b2..f710aadea74 100644
--- a/test/src/image-tests.el
+++ b/test/src/image-tests.el
@@ -53,6 +53,8 @@
;;;; image-test-size
+(declare-function image-size "image.c" (spec &optional pixels frame))
+
(ert-deftest image-tests-image-size/gif ()
(image-skip-unless 'gif)
(pcase (image-size (create-image (cdr (assq 'gif image-tests--images))))
@@ -126,6 +128,8 @@
;;;; image-mask-p
+(declare-function image-mask-p "image.c" (spec &optional frame))
+
(ert-deftest image-tests-image-mask-p/gif ()
(image-skip-unless 'gif)
(should-not (image-mask-p (create-image
@@ -176,6 +180,8 @@
;;;; image-metadata
+(declare-function image-metadata "image.c" (spec &optional frame))
+
;; TODO: These tests could be expanded with files that actually
;; contain metadata.
@@ -238,6 +244,7 @@
(ert-deftest image-tests-init-image-library ()
(skip-unless (fboundp 'init-image-library))
+ (declare-function init-image-library "image.c" (type))
(should (init-image-library 'pbm)) ; built-in
(should-not (init-image-library 'invalid-image-type)))
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index f3dfeea30b4..3560e1abc96 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -187,8 +187,11 @@
(ert-deftest json-parse-string/null ()
(skip-unless (fboundp 'json-parse-string))
(should-error (json-parse-string "\x00") :type 'wrong-type-argument)
- ;; FIXME: Reconsider whether this is the right behavior.
- (should-error (json-parse-string "[\"a\\u0000b\"]") :type 'json-parse-error))
+ (should (json-parse-string "[\"a\\u0000b\"]"))
+ (let* ((string "{\"foo\":\"this is a string including a literal \\u0000\"}")
+ (data (json-parse-string string)))
+ (should (hash-table-p data))
+ (should (equal string (json-serialize data)))))
(ert-deftest json-parse-string/invalid-unicode ()
"Some examples from
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index 69aa7238493..de3012b5764 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -125,7 +125,7 @@
;; ...)
(ert-deftest keymap-lookup-key/mixed-case ()
- "Backwards compatibility behaviour (Bug#50752)."
+ "Backwards compatibility behavior (Bug#50752)."
(let ((map (make-keymap)))
(define-key map [menu-bar foo bar] 'foo)
(should (eq (lookup-key map [menu-bar foo bar]) 'foo))
@@ -418,6 +418,18 @@ g .. h foo
(should-error (text-char-description ?\M-c))
(should-error (text-char-description ?\s-c)))
+(ert-deftest test-non-key-events ()
+ ;; Dummy command.
+ (declare-function keymap-tests-command nil)
+ (should (null (where-is-internal 'keymap-tests-command)))
+ (keymap-set global-map "C-c g" #'keymap-tests-command)
+ (should (equal (where-is-internal 'keymap-tests-command) '([3 103])))
+ (keymap-set global-map "<keymap-tests-event>" #'keymap-tests-command)
+ (should (equal (where-is-internal 'keymap-tests-command)
+ '([keymap-tests-event] [3 103])))
+ (make-non-key-event 'keymap-tests-event)
+ (should (equal (where-is-internal 'keymap-tests-command) '([3 103]))))
+
(provide 'keymap-tests)
;;; keymap-tests.el ends here
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 862f6a6595f..f190f14781e 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -258,5 +258,68 @@ literals (Bug#20852)."
(should (equal (read "-0.e-5") -0.0))
)
+(defun lread-test-read-and-print (str)
+ (let* ((read-circle t)
+ (print-circle t)
+ (val (read-from-string str)))
+ (if (consp val)
+ (prin1-to-string (car val))
+ (error "reading %S failed: %S" str val))))
+
+(defconst lread-test-circle-cases
+ '("#1=(#1# . #1#)"
+ "#1=[#1# a #1#]"
+ "#1=(#2=[#1# #2#] . #1#)"
+ "#1=(#2=[#1# #2#] . #2#)"
+ "#1=[#2=(#1# . #2#)]"
+ "#1=(#2=[#3=(#1# . #2#) #4=(#3# . #4#)])"
+ ))
+
+(ert-deftest lread-circle ()
+ (dolist (str lread-test-circle-cases)
+ (ert-info (str :prefix "input: ")
+ (should (equal (lread-test-read-and-print str) str))))
+ (should-error (read-from-string "#1=#1#") :type 'invalid-read-syntax))
+
+(ert-deftest lread-deeply-nested ()
+ ;; Check that we can read a deeply nested data structure correctly.
+ (let ((levels 10000)
+ (prefix nil)
+ (suffix nil))
+ (dotimes (_ levels)
+ (push "([#s(r " prefix)
+ (push ")])" suffix))
+ (let ((str (concat (apply #'concat prefix)
+ "a"
+ (apply #'concat suffix))))
+ (let* ((read-circle t)
+ (result (read-from-string str)))
+ (should (equal (cdr result) (length str)))
+ ;; Check the result. (We can't build a reference value and compare
+ ;; using `equal' because that function is currently depth-limited.)
+ (named-let check ((x (car result)) (level 0))
+ (if (equal level levels)
+ (should (equal x 'a))
+ (should (and (consp x) (null (cdr x))))
+ (let ((x2 (car x)))
+ (should (and (vectorp x2) (equal (length x2) 1)))
+ (let ((x3 (aref x2 0)))
+ (should (and (recordp x3) (equal (length x3) 2)
+ (equal (aref x3 0) 'r)))
+ (check (aref x3 1) (1+ level))))))))))
+
+(ert-deftest lread-misc ()
+ ;; Regression tests for issues found and fixed in bug#55676:
+ ;; Non-breaking space after a dot makes it a dot token.
+ (should (equal (read-from-string "(a .\u00A0b)")
+ '((a . b) . 7)))
+ ;; #_ without symbol following is the interned empty symbol.
+ (should (equal (read-from-string "#_")
+ '(## . 2))))
+
+(ert-deftest lread-escaped-lf ()
+ ;; ?\LF should signal an error; \LF is ignored inside string literals.
+ (should-error (read-from-string "?\\\n x"))
+ (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6))))
;;; lread-tests.el ends here
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index 4c7b339e0c6..6ff7e997837 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -406,5 +406,129 @@ otherwise, use a different charset."
(should (equal printed-nonprints
"(55296 57343 778 65535 8194 8204)"))))
+(ert-deftest test-unreadable ()
+ (should (equal (prin1-to-string (make-marker)) "#<marker in no buffer>"))
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ "hello")))
+ (should (equal (prin1-to-string (make-marker)) "hello")))
+ (let ((print-unreadable-function
+ (lambda (_object _escape)
+ t)))
+ (should (equal (prin1-to-string (make-marker)) ""))))
+
+(ert-deftest test-dots ()
+ (should (equal (prin1-to-string 'foo.bar) "foo.bar"))
+ (should (equal (prin1-to-string '.foo) "\\.foo"))
+ (should (equal (prin1-to-string '.foo.) "\\.foo."))
+ (should (equal (prin1-to-string 'bar?bar) "bar?bar"))
+ (should (equal (prin1-to-string '\?bar) "\\?bar"))
+ (should (equal (prin1-to-string '\?bar?) "\\?bar?")))
+
+(ert-deftest test-prin1-overrides ()
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) t)
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 20)))
+
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) '((length . 5)))
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 6)))
+
+ (with-temp-buffer
+ (let ((print-length 10))
+ (prin1 (make-list 20 t) (current-buffer) '(t (length . 5)))
+ (should (= print-length 10)))
+ (goto-char (point-min))
+ (should (= (length (read (current-buffer))) 6))))
+
+(ert-deftest test-prin1-to-string-overrides ()
+ (let ((print-length 10))
+ (should
+ (= (length (car (read-from-string
+ (prin1-to-string (make-list 20 t) nil t))))
+ 20)))
+
+ (let ((print-length 10))
+ (should
+ (= (length (car (read-from-string
+ (prin1-to-string (make-list 20 t) nil
+ '((length . 5))))))
+ 6)))
+
+ (should-error (prin1-to-string 'foo nil 'a))
+ (should-error (prin1-to-string 'foo nil '(a)))
+ (should-error (prin1-to-string 'foo nil '(t . b)))
+ (should-error (prin1-to-string 'foo nil '(t b)))
+ (should-error (prin1-to-string 'foo nil '((a . b) b)))
+ (should-error (prin1-to-string 'foo nil '((length . 10) . b))))
+
+(ert-deftest print-deeply-nested ()
+ ;; Check that we can print a deeply nested data structure correctly.
+ (let ((print-circle t))
+ (let ((levels 10000)
+ (x 'a)
+ (prefix nil)
+ (suffix nil))
+ (dotimes (_ levels)
+ (setq x (list (vector (record 'r x))))
+ (push "([#s(r " prefix)
+ (push ")])" suffix))
+ (let ((expected (concat (apply #'concat prefix)
+ "a"
+ (apply #'concat suffix))))
+ (should (equal (prin1-to-string x) expected))))))
+
+(defun print-test-rho (lead loop)
+ "A circular iota list with LEAD elements followed by LOOP in circle."
+ (let ((l (number-sequence 1 (+ lead loop))))
+ (setcdr (nthcdr (+ lead loop -1) l) (nthcdr lead l))
+ l))
+
+(ert-deftest print-circular ()
+ ;; Check printing of rho-shaped circular lists such as (1 2 3 4 5 4 5 4 . #6)
+ ;; when `print-circle' is nil. The exact output may differ since the number
+ ;; of elements printed of the looping part can vary depending on when the
+ ;; circularity was detected.
+ (dotimes (lead 7)
+ (ert-info ((prin1-to-string lead) :prefix "lead: ")
+ (dolist (loop (number-sequence 1 7))
+ (ert-info ((prin1-to-string loop) :prefix "loop: ")
+ (let* ((rho (print-test-rho lead loop))
+ (print-circle nil)
+ (str (prin1-to-string rho)))
+ (should (string-match (rx "("
+ (group (+ (+ digit) " "))
+ ". #" (group (+ digit)) ")")
+ str))
+ (let* ((g1 (match-string 1 str))
+ (g2 (match-string 2 str))
+ (numbers (mapcar #'string-to-number (split-string g1)))
+ (loopback-index (string-to-number g2)))
+ ;; Split the numbers in the lead and loop part.
+ (should (< lead (length numbers)))
+ (should (<= lead loopback-index))
+ (should (< loopback-index (length numbers)))
+ (let ((lead-part (butlast numbers (- (length numbers) lead)))
+ (loop-part (nthcdr lead numbers)))
+ ;; The lead part must match exactly.
+ (should (equal lead-part (number-sequence 1 lead)))
+ ;; The loop part is at least LOOP long: make sure it matches.
+ (should (>= (length loop-part) loop))
+ (let ((expected-loop-part
+ (mapcar (lambda (x) (+ lead 1 (% x loop)))
+ (number-sequence 0 (1- (length loop-part))))))
+ (should (equal loop-part expected-loop-part))
+ ;; The loopback index must match the length of the
+ ;; loop part.
+ (should (equal (% (- (length numbers) loopback-index) loop)
+ 0)))))))))))
+
+
(provide 'print-tests)
;;; print-tests.el ends here
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index f5908d3cda5..824c6da1191 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -931,7 +931,7 @@ Return nil if FILENAME doesn't exist."
(< (float-time) (+ t0 limit)))
(sit-for 0.1)))
(should status)
- (should-not (assq :error status))
+ (should-not (plist-get status ':error))
(should buf)
(should (> (buffer-size buf) 0))
)
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index e6288d1fc9b..ff0d6be3f5d 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -157,8 +157,8 @@ are known failures, and are skipped."
(defun regex-tests-compare (string what-failed bounds-ref &optional substring-ref)
"I just ran a search, looking at STRING. WHAT-FAILED describes
-what failed, if anything; valid values are 'search-failed,
-'compilation-failed and nil. I compare the beginning/end of each
+what failed, if anything; valid values are `search-failed',
+`compilation-failed' and nil. I compare the beginning/end of each
group with their expected values. This is done with either
BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil.
BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1
@@ -166,9 +166,9 @@ end-ref1 ....] while SUBSTRING-REF is the expected substring
obtained by indexing the input string by start/end-ref.
If the search was supposed to fail then start-ref0/substring-ref0
-is 'search-failed. If the search wasn't even supposed to compile
+is `search-failed'. If the search wasn't even supposed to compile
successfully, then start-ref0/substring-ref0 is
-'compilation-failed. If I only care about a match succeeding,
+`compilation-failed'. If I only care about a match succeeding,
this can be set to t.
This function returns a string that describes the failure, or nil
@@ -259,8 +259,8 @@ BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1 end-ref1
....].
If the search was supposed to fail then start-ref0 is
-'search-failed. If the search wasn't even supposed to compile
-successfully, then start-ref0 is 'compilation-failed.
+`search-failed'. If the search wasn't even supposed to compile
+successfully, then start-ref0 is `compilation-failed'.
This function returns a string that describes the failure, or nil
on success"
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
index 6e44300f3ad..5af43923012 100644
--- a/test/src/sqlite-tests.el
+++ b/test/src/sqlite-tests.el
@@ -216,4 +216,29 @@
db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
'(nil t)))))
+(ert-deftest sqlite-blob ()
+ (skip-unless (sqlite-available-p))
+ (let (db)
+ (progn
+ (setq db (sqlite-open))
+ (sqlite-execute
+ db "create table if not exists test10 (col1 text, col2 blob, col3 numbre)")
+ (let ((string (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert 0 1 2)
+ (buffer-string))))
+ (should-not (multibyte-string-p string))
+ (sqlite-execute
+ db "insert into test10 values (?, ?, 1)"
+ (list string
+ (propertize string
+ 'coding-system 'binary)))
+ (cl-destructuring-bind
+ (c1 c2 _)
+ (car (sqlite-select db "select * from test10 where col3 = 1"))
+ (should (equal c1 string))
+ (should (equal c2 string))
+ (should (multibyte-string-p c1))
+ (should-not (multibyte-string-p c2)))))))
+
;;; sqlite-tests.el ends here
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 3b9f21cde37..751a900a23e 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -506,4 +506,19 @@ the `parse-partial-sexp's are expected to stop. See
(should (parse-partial-sexp 1 1))
(should-error (parse-partial-sexp 2 1))))
+(ert-deftest syntax-char-syntax ()
+ ;; Verify that char-syntax behaves identically in interpreted and
+ ;; byte-compiled code (bug#53260).
+ (let ((cs (byte-compile (lambda (x) (char-syntax x)))))
+ ;; Use a unibyte buffer with a syntax table using symbol syntax
+ ;; for raw byte 128.
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (let ((st (make-syntax-table)))
+ (modify-syntax-entry (unibyte-char-to-multibyte 128) "_" st)
+ (set-syntax-table st)
+ (should (equal (eval '(char-syntax 128) t) ?_))
+ (should (equal (funcall cs 128) ?_))))
+ (list (char-syntax 128) (funcall cs 128))))
+
;;; syntax-tests.el ends here
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index b7ab31120aa..75d67140a90 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -393,4 +393,29 @@
(let ((th (make-thread 'ignore)))
(should-not (equal th main-thread))))
+(defvar threads-test--var 'global)
+
+(ert-deftest threads-test-bug48990 ()
+ (skip-unless (fboundp 'make-thread))
+ (let ((buf1 (generate-new-buffer " thread-test"))
+ (buf2 (generate-new-buffer " thread-test")))
+ (with-current-buffer buf1
+ (setq-local threads-test--var 'local1))
+ (with-current-buffer buf2
+ (setq-local threads-test--var 'local2))
+ (let ((seen nil))
+ (with-current-buffer buf1
+ (should (eq threads-test--var 'local1))
+ (make-thread (lambda () (setq seen threads-test--var))))
+ (with-current-buffer buf2
+ (should (eq threads-test--var 'local2))
+ (let ((threads-test--var 'let2))
+ (should (eq threads-test--var 'let2))
+ (while (not seen)
+ (thread-yield))
+ (should (eq threads-test--var 'let2))
+ (should (eq seen 'local1)))
+ (should (eq threads-test--var 'local2)))
+ (should (eq threads-test--var 'global)))))
+
;;; thread-tests.el ends here
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
index 1b49e0622f5..24f9000ffbd 100644
--- a/test/src/timefns-tests.el
+++ b/test/src/timefns-tests.el
@@ -93,7 +93,6 @@
most-negative-fixnum most-positive-fixnum
(1- most-negative-fixnum)
(1+ most-positive-fixnum)
- 1e+INF -1e+INF 1e+NaN -1e+NaN
'(0 1 0 0) '(1 0 0 0) '(-1 0 0 0)
'(123456789000000 . 1000000)
(cons (1+ most-positive-fixnum) 1000000000000)
@@ -180,7 +179,6 @@ a fixed place on the right and are padded on the left."
1e10 -1e10 1e-10 -1e-10
1e16 -1e16 1e-16 -1e-16
1e37 -1e37 1e-37 -1e-37
- 1e+INF -1e+INF 1e+NaN -1e+NaN
'(0 0 0 1) '(0 0 1 0) '(0 1 0 0) '(1 0 0 0)
'(-1 0 0 0) '(1 2 3 4) '(-1 2 3 4)
'(-123456789 . 100000) '(123456789 . 1000000)
@@ -221,6 +219,15 @@ a fixed place on the right and are padded on the left."
(encode-time '(29 31 17 30 4 2019 2 t 7200))
'(23752 27217))))
+(ert-deftest encode-time-alternate-apis ()
+ (let* ((time '(30 30 12 15 6 1970))
+ (time-1 (append time '(nil -1 nil)))
+ (etime (encode-time time)))
+ (should (time-equal-p etime (encode-time time-1)))
+ (should (time-equal-p etime (apply #'encode-time time)))
+ (should (time-equal-p etime (apply #'encode-time time-1)))
+ (should (time-equal-p etime (apply #'encode-time (append time '(nil)))))))
+
(ert-deftest float-time-precision ()
(should (= (float-time '(0 1 0 4025)) 1.000000004025))
(should (= (float-time '(1000000004025 . 1000000000000)) 1.000000004025))
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el
index 0870dc9de4d..6ff64d0431a 100644
--- a/test/src/xdisp-tests.el
+++ b/test/src/xdisp-tests.el
@@ -170,4 +170,13 @@ int main () {
(should (equal (get-display-property 2 'height) 2.0))
(should (equal (get-display-property 2 'space-width) 20))))
+(ert-deftest test-messages-buffer-name ()
+ (should
+ (equal
+ (let ((messages-buffer-name "test-message"))
+ (message "foo")
+ (with-current-buffer messages-buffer-name
+ (buffer-string)))
+ "foo\n")))
+
;;; xdisp-tests.el ends here
diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el
index 31c0f021b28..16f16537918 100644
--- a/test/src/xfaces-tests.el
+++ b/test/src/xfaces-tests.el
@@ -47,7 +47,10 @@
'(0 32768 6554)))
(should (equal (color-values-from-color-spec "rgbi:1e-3/1.0e-2/1e0")
'(66 655 65535)))
- (should (equal (color-values-from-color-spec "rgbi:0/0.5/10") nil)))
+ (should (equal (color-values-from-color-spec "rgbi:0/0.5/10") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/0/ 0") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/0x0/0") nil))
+ (should (equal (color-values-from-color-spec "rgbi:0/+0x1/0") nil)))
(provide 'xfaces-tests)